feat(packaging): ship wrapper-first Next.js npm integration#20
feat(packaging): ship wrapper-first Next.js npm integration#20
Conversation
Extract route handlers, layout, instrumentation, and Next.js config into importable modules under src/ so consumers can install junior as a package and deploy without touching Next.js internals. The CLI now supports init/dev/build/start subcommands with automatic shim generation. - Extract webhook and health handlers to src/handlers/ - Add catch-all router for consumer shim (single route file) - Add withJunior() config helper for Next.js setup - Default JUNIOR_HOME to process.cwd() instead of throwing - Add tsup build tooling to produce dist/ with resolved @/ aliases - Add package exports, files, and peerDependencies - Update CLI with init, dev, build, start subcommands Refs GH-9 Co-Authored-By: Claude <noreply@anthropic.com>
Move SOUL.md and skills from src/ to the jr-sentry/ home directory so the project structure matches the npm package model where bot content lives in a separate home directory. - Move src/chat/SOUL.md → jr-sentry/SOUL.md - Move src/junior/skills/ → jr-sentry/skills/ - Add jr-sentry/config.toml - Update config.ts to read from loadHomeConfig() via home module - Rename routerModelId → fastModelId across bot, tools, and tests - Update prompt.ts and skills.ts to use soulPath()/skillsDir() - Update check-skills.mjs to resolve from JUNIOR_HOME - Add Slack thread id normalization to chat-background-patch.ts Co-Authored-By: Claude <noreply@anthropic.com>
Rebase preserved main's Slack thread normalization behavior where\nmissing raw fields return the original thread id instead of throwing.\nUpdate the legacy test to assert that behavior so test expectations\nmatch current runtime behavior. Regenerate pnpm-lock.yaml to reflect the current dependency layout\nafter the npm-deployable packaging and home-directory cutover. Co-Authored-By: GPT-5 <noreply@openai.com>
Ensure the npm deployable path behaves correctly after the rebase. withJunior now wraps async/sync Next config factories, the catch-all router accepts generated and legacy API route forms, and runtime references use fastModelId consistently after config field renames. Also allow JUNIOR_HOME overrides in local dev and add regression tests for router and config composition behavior. Co-Authored-By: GPT-5 <noreply@openai.com>
Stop mutating consumer apps during dev/build and treat integration as explicit Next.js wrappers. junior init now scaffolds wrapper files once (route, config, instrumentation, layout) and uses standard next scripts with JUNIOR_HOME set. Also defer loading chat bot runtime in webhook handlers so builds do not fail when Slack secrets are unavailable at compile time. Co-Authored-By: GPT-5 <noreply@openai.com>
Next.js 16 route segment config no longer accepts re-exported runtime. Declare runtime in app route files and only re-export handlers so root builds remain valid under Turbopack. Co-Authored-By: GPT-5 <noreply@openai.com>
66c53a3 to
b25a808
Compare
Remove config.toml and JUNIOR_HOME-driven home resolution in favor of\nroot-level data/, skills/, and plugins/ directories so installs work as\nstandard Next.js apps without custom startup wrappers.\n\nAlign CLI init output, runtime discovery, tracing includes, skill/plugin\nchecks, tests, and docs with the new single-model package flow.\n\nCo-Authored-By: GPT-5 Codex <noreply@openai.com>
Document .js/.mjs wrapper filenames for manual integration so the setup\nworks with default Next.js TypeScript configuration without module\nresolution changes.\n\nCo-Authored-By: GPT-5 Codex <noreply@openai.com>
Merge existing /api/** output tracing entries in withJunior so consumer config values are preserved instead of replaced. Restrict webhook catch-all routing to a single platform segment so multi-segment paths correctly return 404, matching the original route behavior. Add regression tests for both behaviors. Refs GH-9 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Reinstate the @chat-adapter/slack patch so file_share subtype events are not discarded by the adapter. Also remove the unused JUNIOR_HOME entry from .env.test now that home resolution is convention-based and no longer env-driven. Refs GH-9 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Use AI_MODEL as the intermediate fallback for fastModelId when AI_FAST_MODEL is unset, restoring prior behavior and keeping config selection consistent with web-search model resolution. Add regression tests for fallback precedence. Refs GH-9 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Avoid duplicate entries in serverExternalPackages when consumers already include Junior's default packages. Add regression coverage for dedup behavior. Refs GH-9 Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Keep external in the package build while declaring it in\n so npm consumers install it. This avoids runtime\nmodule resolution failures when bundled output references the module. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Keep workflow libraries external in tsup to match package runtime dependencies and avoid duplicate bundled/runtime copies. Remove unused runtime exports from handler modules because runtime is defined by route files in consumers. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Handler modules no longer export runtime; runtime is defined on Next.js route files. Update the lazy-load test to assert only the exported webhook handler function. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Set up a pnpm workspace with an in-repo jr-sentry consumer project so we can validate package behavior in a production-like integration path. Use workspace linking for junior and document the local smoke workflow. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Drop from runtime dependencies and tsup externals since the package no longer imports it. This keeps consumer installs minimal while preserving current bundle behavior. Co-Authored-By: GPT-5 Codex <noreply@openai.com>
Move the publishable junior package to packages/junior and move the smoke-test consumer app to packages/jr-sentry. Keep root developer ergonomics by proxying dev/build/test scripts from the workspace root, and preserve patched dependency wiring at root. Update test env loading to include workspace-root env files so root test behavior stays stable after the package cwd move. Fix Sentry config loading in ESM by using createRequire instead of a global require call. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Drop SENTRY_ORG, SENTRY_PROJECT, and SENTRY_AUTH_TOKEN from consumer and scaffold env templates because withJunior() defaults to sentry disabled in those generated configs. This keeps setup docs aligned with actual behavior and avoids dead configuration for new consumers. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Set the package Next build to webpack and pin turbopack root to the workspace root for the in-repo app config. This avoids workspace root inference failures seen after relocating the package to packages/junior and keeps root build commands working for PR validation and deployment checks. Co-Authored-By: GPT-5 Codex <codex@openai.com>
Add oauth callback routing for GET /api/oauth/callback/:provider in junior/handler so package consumers can complete OAuth flows when using the catch-all API route. Introduce a dedicated oauth-callback handler wrapper and extend router tests for both normal and legacy api-prefixed path forms. Co-Authored-By: GPT-5 Codex <codex@openai.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| start: "next start" | ||
| }, | ||
| dependencies: { | ||
| junior: "latest", |
There was a problem hiding this comment.
Scaffolded dependency uses unpinned "latest" version specifier
Medium Severity
The junior init scaffold sets "junior": "latest" in the generated package.json, while all other dependencies use caret ranges (e.g. "next": "^16.0.0"). The "latest" tag always resolves to the newest published version at install time and isn't bounded by semver range, so a future major release with breaking changes would silently break newly scaffolded (or re-installed) projects. Using a caret range based on the current version (or reading it from the package's own package.json) would be more consistent and safer.


Make Junior deployable as an npm dependency using standard Next.js wrappers.
The previous package approach depended on CLI-generated shim files and custom build commands. This change moves to a wrapper-first integration so consumers keep normal Next.js dev/build/start scripts while importing Junior runtime surfaces directly.
Key changes:
withJunior()to merge requiredserverExternalPackagesandoutputFileTracingIncludesfor/api/**, with optional Sentry wrappingsrc/handlers/*and reuse them from app routes and package exportstsup, exports map,files, peer dependency layout) so published artifacts are consumable from external Next.js appsdata/,skills/, andplugins/conventions for scaffolded and consuming reposapp/api/[...path]/route.js,next.config.mjs,instrumentation.js, optionalapp/layout.js)outputFileTracingIncludes["/api/**"]entries when applying Junior config instead of overwriting consumer-defined values/api/webhooks/slack) and returning 404 for multi-segment pathsThis keeps deployment ergonomics aligned with normal Next.js behavior while preserving the runtime/data loading guarantees Junior needs in production.
Refs GH-9