@chorus-aidlc/chorus 0.16.3 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-build-manifest.json +445 -445
- package/.next/standalone/.next/app-path-routes-manifest.json +54 -54
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +42 -42
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/project-groups/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/activity/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/[ideaUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/dashboard/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/documents/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/graph/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/proposals/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/[uuid]/tasks/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/settings/page.js +2 -2
- package/.next/standalone/.next/server/app/(dashboard)/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/(dashboard)/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +2 -2
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/companies/[uuid]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies/new.html +2 -2
- package/.next/standalone/.next/server/app/admin/companies/new.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/companies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin/companies.html +2 -2
- package/.next/standalone/.next/server/app/admin/companies.rsc +1 -1
- package/.next/standalone/.next/server/app/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/admin.html +2 -2
- package/.next/standalone/.next/server/app/admin.rsc +1 -1
- package/.next/standalone/.next/server/app/api/admin/companies/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/companies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/admin/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agent-connections/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/agents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/api-keys/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/callback/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/check-default/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/company-oidc/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/default-login/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/identify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/me/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/sync-token/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/comments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/connection-heartbeat/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/control/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/directory-request/report/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/execution-state/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/executions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/pending-turns/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/report-interrupt/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/resume/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/transcript/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/turn-advance/route.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon/turn-advance/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-directory-requests/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/instruction/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/repoint/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/[sessionUuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/ad-hoc/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/daemon-sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/documents/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/entities/[type]/[uuid]/root-idea/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/events/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/health/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/preview/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/move/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/parent/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/[uuid]/wake-preview/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/ideas/conversational/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mcp/route.js +3 -3
- package/.next/standalone/.next/server/app/api/mcp/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route.js +1 -1
- package/.next/standalone/.next/server/app/api/me/assignments/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/mentionables/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/archive/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/[uuid]/read/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/preferences/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/read-all/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/notifications/unread-count/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/dashboard/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-groups/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/pin/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/project-visits/visit/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/activity/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/agent-cwds/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/available/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/documents/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/group/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/ideas/tracker/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/[proposalUuid]/validate/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/proposals/summary/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/resource-graph/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/stats/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/[uuid]/tasks/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/agent-cwd-options/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/approve/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/close/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/reject/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/revoke/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/proposals/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/references/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/references/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/search/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/session/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/sessions/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/claim/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/[dependsOnUuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/dependencies/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/release/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/tasks/[uuid]/sessions/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +2 -2
- package/.next/standalone/.next/server/app/index.rsc +1 -1
- package/.next/standalone/.next/server/app/login/admin/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/admin.html +2 -2
- package/.next/standalone/.next/server/app/login/admin.rsc +1 -1
- package/.next/standalone/.next/server/app/login/callback/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/callback.html +2 -2
- package/.next/standalone/.next/server/app/login/callback.rsc +1 -1
- package/.next/standalone/.next/server/app/login/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/login/pick-workspace.html +2 -2
- package/.next/standalone/.next/server/app/login/pick-workspace.rsc +1 -1
- package/.next/standalone/.next/server/app/login.html +2 -2
- package/.next/standalone/.next/server/app/login.rsc +1 -1
- package/.next/standalone/.next/server/app/onboarding/page.js +2 -2
- package/.next/standalone/.next/server/app/onboarding/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/onboarding/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/onboarding.html +2 -2
- package/.next/standalone/.next/server/app/onboarding.rsc +2 -2
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects.html +2 -2
- package/.next/standalone/.next/server/app/projects.rsc +2 -2
- package/.next/standalone/.next/server/app/settings.html +2 -2
- package/.next/standalone/.next/server/app/settings.rsc +3 -3
- package/.next/standalone/.next/server/app-paths-manifest.json +54 -54
- package/.next/standalone/.next/server/chunks/1114.js +1 -1
- package/.next/standalone/.next/server/chunks/1318.js +1 -1
- package/.next/standalone/.next/server/chunks/1437.js +1 -0
- package/.next/standalone/.next/server/chunks/1559.js +2 -2
- package/.next/standalone/.next/server/chunks/2572.js +1 -1
- package/.next/standalone/.next/server/chunks/2618.js +1 -1
- package/.next/standalone/.next/server/chunks/2961.js +1 -1
- package/.next/standalone/.next/server/chunks/{9793.js → 3045.js} +1 -1
- package/.next/standalone/.next/server/chunks/3831.js +37 -0
- package/.next/standalone/.next/server/chunks/4827.js +1 -1
- package/.next/standalone/.next/server/chunks/5245.js +1 -1
- package/.next/standalone/.next/server/chunks/{4394.js → 5706.js} +1 -1
- package/.next/standalone/.next/server/chunks/6113.js +1 -1
- package/.next/standalone/.next/server/chunks/6207.js +1 -1
- package/.next/standalone/.next/server/chunks/6506.js +2 -2
- package/.next/standalone/.next/server/chunks/6515.js +2 -2
- package/.next/standalone/.next/server/chunks/679.js +1 -1
- package/.next/standalone/.next/server/chunks/7368.js +1 -1
- package/.next/standalone/.next/server/chunks/7530.js +1 -1
- package/.next/standalone/.next/server/chunks/8454.js +1 -1
- package/.next/standalone/.next/server/chunks/920.js +1 -1
- package/.next/standalone/.next/server/chunks/9213.js +1 -1
- package/.next/standalone/.next/server/chunks/9378.js +1 -1
- package/.next/standalone/.next/server/chunks/9449.js +1 -0
- package/.next/standalone/.next/server/chunks/9458.js +1 -0
- package/.next/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/.next/standalone/.next/server/middleware-manifest.json +5 -5
- package/.next/standalone/.next/server/pages/404.html +2 -2
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{11595.97e534422c57aee1.js → 11595.bbe40924d18958bf.js} +1 -1
- package/.next/standalone/.next/static/chunks/18139-e6ef4b5869593f8e.js +1 -0
- package/.next/standalone/.next/static/chunks/28856-ef2cb58fbd404ef9.js +1 -0
- package/.next/standalone/.next/static/chunks/{31308-fda6febfb2882a28.js → 31308-bb4a97b3f39c22dd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{33456.6dc44a6aca1a01fd.js → 33456.5499eb8e892b110a.js} +1 -1
- package/.next/standalone/.next/static/chunks/{4860.7873ebc9ba435c8c.js → 4860.be77046fb2b3a2bd.js} +1 -1
- package/.next/standalone/.next/static/chunks/66873-e3be53f41b3f2255.js +1 -0
- package/.next/standalone/.next/static/chunks/70303-aec3d52ad87602a3.js +1 -0
- package/.next/standalone/.next/static/chunks/76201-83b26515f85ce37c.js +1 -0
- package/.next/standalone/.next/static/chunks/78917-a8a8dff98857c045.js +1 -0
- package/.next/standalone/.next/static/chunks/{94643-01be319472d751b3.js → 94643-ffa140f765c73daf.js} +1 -1
- package/.next/standalone/.next/static/chunks/97663-9c3ae4fd60b353db.js +1 -0
- package/.next/standalone/.next/static/chunks/{99373.d0e808c18408b8da.js → 99373.111493dc260a2a04.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/{layout-b742c51c0a764daf.js → layout-40fe7d026c5a7c6d.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-87d4d0fe90fca28c.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-1206abaee85dc915.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/{page-425acbe9ade5fa83.js → page-474e494097c8945f.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-e902b19328092ccf.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-f273288c3530aa0f.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-6568a7b08bf9a54b.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-fbd3c27b68666234.js +1 -0
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/[taskUuid]/{page-58b48aa0a11603c3.js → page-15bb6e1696668512.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/tasks/{page-286faced32c6133f.js → page-2bea97214b1595cc.js} +1 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-2bf7ceee62b574c7.js +1 -0
- package/.next/standalone/.next/static/chunks/app/onboarding/{page-5c82cf3abd856301.js → page-540da64d7ba16dc7.js} +1 -1
- package/.next/standalone/.next/static/chunks/{webpack-fa066d7ff9ab2b29.js → webpack-7cbb3ba6792f1fb3.js} +1 -1
- package/.next/standalone/package.json +1 -1
- package/.next/standalone/public/chorus-plugin/.claude-plugin/plugin.json +1 -1
- package/.next/standalone/public/chorus-plugin/bin/chorus-api.sh +44 -1
- package/.next/standalone/public/chorus-plugin/bin/on-session-start.sh +4 -3
- package/.next/standalone/public/chorus-plugin/bin/tests/test-mcp-cli-delegation.sh +244 -0
- package/.next/standalone/public/chorus-plugin/skills/brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/chorus/SKILL.md +19 -1
- package/.next/standalone/public/chorus-plugin/skills/chorus-cli/SKILL.md +57 -0
- package/.next/standalone/public/chorus-plugin/skills/develop/SKILL.md +2 -2
- package/.next/standalone/public/chorus-plugin/skills/docs/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/idea/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/openspec-aware/SKILL.md +85 -42
- package/.next/standalone/public/chorus-plugin/skills/orchestrate/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/proposal/SKILL.md +2 -2
- package/.next/standalone/public/chorus-plugin/skills/quick-dev/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/review/SKILL.md +1 -1
- package/.next/standalone/public/chorus-plugin/skills/yolo/SKILL.md +3 -3
- package/.next/standalone/public/dsh-credentials.sh +30 -0
- package/.next/standalone/public/install-codex.sh +21 -406
- package/.next/standalone/public/install-kiro.sh +20 -344
- package/.next/standalone/public/install-opencode.sh +20 -275
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-brainstorm/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-cli/SKILL.md +57 -0
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-develop/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-docs/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-idea/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-openspec-aware/SKILL.md +85 -42
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-orchestrate/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-proposal/SKILL.md +2 -2
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-quick-dev/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-review/SKILL.md +1 -1
- package/.next/standalone/public/kiro-plugin/.kiro/skills/chorus-yolo/SKILL.md +3 -3
- package/.next/standalone/public/kiro-plugin/bin/chorus-api.sh +44 -1
- package/.next/standalone/public/kiro-plugin/bin/on-agent-spawn.sh +6 -4
- package/.next/standalone/public/kiro-plugin/manifest.txt +41 -0
- package/.next/standalone/public/skill/brainstorm-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/chorus/SKILL.md +19 -1
- package/.next/standalone/public/skill/code-reviewer-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/develop-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/docs-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/idea-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/orchestrate-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/proposal-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/proposal-reviewer-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/quick-dev-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/review-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/task-reviewer-chorus/SKILL.md +1 -1
- package/.next/standalone/public/skill/yolo-chorus/SKILL.md +1 -1
- package/.next/standalone/public/test-dsh-credentials.sh +39 -0
- package/.next/standalone/public/test-install-codex.sh +31 -79
- package/README.ja.md +5 -3
- package/README.ko.md +5 -3
- package/README.md +5 -3
- package/README.zh.md +5 -3
- package/chorus.mjs +35 -1
- package/cli/agent-backend-prompt.mjs +94 -0
- package/cli/agents.mjs +329 -0
- package/cli/chorus-client.mjs +69 -0
- package/cli/claude-spawner.mjs +4 -0
- package/cli/client-args.mjs +11 -5
- package/cli/codex-spawner.mjs +11 -6
- package/cli/credentials.mjs +185 -3
- package/cli/daemon-agent.mjs +30 -5
- package/cli/daemon-banner.mjs +3 -3
- package/cli/daemon-config.mjs +27 -2
- package/cli/daemon-install-config.mjs +21 -14
- package/cli/daemon-rest-client.mjs +31 -8
- package/cli/daemon-service.mjs +120 -33
- package/cli/daemon.mjs +175 -28
- package/cli/dsh-managed-config.mjs +407 -0
- package/cli/dsh-spawner.mjs +445 -0
- package/cli/init/adapters.mjs +137 -0
- package/cli/init/agent-type-map.mjs +60 -0
- package/cli/init/chorus-plugin-consts.mjs +16 -0
- package/cli/init/codex-mcp-config.mjs +183 -0
- package/cli/init/contracts.mjs +120 -0
- package/cli/init/detect.mjs +97 -0
- package/cli/init/file-template.mjs +248 -0
- package/cli/init/install-methods.mjs +508 -0
- package/cli/init/registry.mjs +74 -0
- package/cli/init/run-command.mjs +30 -0
- package/cli/init/select.mjs +111 -0
- package/cli/init/steps/credential-seed.mjs +751 -0
- package/cli/init/steps/daemon-setup.mjs +246 -0
- package/cli/init/steps/plugin-install.mjs +37 -0
- package/cli/init-args.mjs +137 -0
- package/cli/init.mjs +198 -0
- package/cli/kiro-spawner.mjs +4 -0
- package/cli/login.mjs +26 -4
- package/cli/mcp-args.mjs +280 -0
- package/cli/mcp.mjs +164 -0
- package/cli/spawner-select.mjs +54 -2
- package/cli/turn-reporter.mjs +5 -2
- package/cli/upload-hooks.mjs +31 -1
- package/cli/waker.mjs +49 -6
- package/package.json +1 -1
- package/prisma/migrations/20260818024700_add_turn_backend_session_id/migration.sql +1 -0
- package/prisma/schema.prisma +3 -0
- package/.next/standalone/.next/server/chunks/3594.js +0 -1
- package/.next/standalone/.next/server/chunks/5351.js +0 -32
- package/.next/standalone/.next/server/chunks/6667.js +0 -1
- package/.next/standalone/.next/server/chunks/6995.js +0 -1
- package/.next/standalone/.next/static/chunks/19887-c0bb297a78a1c7cd.js +0 -1
- package/.next/standalone/.next/static/chunks/29108-5a11eea003f4cc11.js +0 -1
- package/.next/standalone/.next/static/chunks/53073-a7ed20af6538a178.js +0 -1
- package/.next/standalone/.next/static/chunks/6603-e70ddeab6ad09c50.js +0 -1
- package/.next/standalone/.next/static/chunks/78917-1b59cbb806b3ecfc.js +0 -1
- package/.next/standalone/.next/static/chunks/82751-3e161e1d8dbda3ac.js +0 -1
- package/.next/standalone/.next/static/chunks/99366-425e9ef22e60e3e2.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/dashboard/page-f636e00c28f425ea.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/documents/[documentUuid]/page-c004f1a194af7fa5.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/graph/page-fdd617457730a116.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/[proposalUuid]/page-6b3fb08d53826d02.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/new/page-d5b222f379b2e8ca.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/projects/[uuid]/proposals/page-0a6c2d0e1b68e0e4.js +0 -1
- package/.next/standalone/.next/static/chunks/app/(dashboard)/settings/page-1507a761e67c2aa9.js +0 -1
- /package/.next/standalone/.next/static/{K8qIdwvKoIWbwQ_f01mnM → 0spgxl3lP26Fl1otd1D7R}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{K8qIdwvKoIWbwQ_f01mnM → 0spgxl3lP26Fl1otd1D7R}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
// cli/init/codex-mcp-config.mjs
|
|
2
|
+
// Writes the Chorus native-MCP server block into ~/.codex/config.toml using a KEYLESS
|
|
3
|
+
// env-var reference — `bearer_token_env_var = "CHORUS_API_KEY"` — instead of a literal
|
|
4
|
+
// `Authorization: Bearer <key>`. Codex loads ~/.codex/.env into its process env at arg0
|
|
5
|
+
// startup and resolves that env var into `Authorization: Bearer <key>` at connect time
|
|
6
|
+
// (config/src/mcp_types.rs StreamableHttp.bearer_token_env_var; codex-mcp resolve_bearer_token),
|
|
7
|
+
// so the API key lives in exactly ONE place (~/.codex/.env). A daemon-woken Codex — whose
|
|
8
|
+
// spawner exports CHORUS_API_KEY into the child env — then also authenticates to native MCP,
|
|
9
|
+
// closing the gap a literal Bearer left (cli/codex-spawner.mjs:16-22).
|
|
10
|
+
//
|
|
11
|
+
// `codex plugin add` does NOT write [mcp_servers.chorus] (its marketplace `authentication:
|
|
12
|
+
// ON_INSTALL` is metadata only — verified codex-cli 0.150.1), so `chorus agents add` writes it
|
|
13
|
+
// here, AFTER the plugin install (authoritative, no race).
|
|
14
|
+
//
|
|
15
|
+
// TARGETED TEXTUAL upsert — no TOML-parser dependency (the repo stays pure-JS / cross-platform),
|
|
16
|
+
// preserving every other section, key, and comment verbatim. The secret is NEVER written here
|
|
17
|
+
// (bearer_token_env_var is a variable NAME, not the key).
|
|
18
|
+
|
|
19
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
20
|
+
import { homedir } from "node:os";
|
|
21
|
+
import { dirname, join } from "node:path";
|
|
22
|
+
|
|
23
|
+
const BEARER_ENV_VAR = "CHORUS_API_KEY";
|
|
24
|
+
|
|
25
|
+
/** A non-empty trimmed string, or undefined. */
|
|
26
|
+
function nonEmpty(value) {
|
|
27
|
+
return typeof value === "string" && value.trim() ? value.trim() : undefined;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the Codex `~/.codex/config.toml` path. Honors `CODEX_HOME`, then `HOME` (so tests
|
|
32
|
+
* can inject a temp home), else the OS home dir — matching cli/codex-spawner.mjs +
|
|
33
|
+
* install-methods.mjs.
|
|
34
|
+
* @param {Record<string, string | undefined>} env
|
|
35
|
+
*/
|
|
36
|
+
export function resolveCodexConfigPath(env) {
|
|
37
|
+
const base = nonEmpty(env.CODEX_HOME) ?? join(nonEmpty(env.HOME) ?? homedir(), ".codex");
|
|
38
|
+
return join(base, "config.toml");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Normalize a Chorus base URL to the MCP endpoint the same way the hook wrapper
|
|
43
|
+
* (chorus-mcp-call.sh) does: a URL that already has a path segment beyond the host is used
|
|
44
|
+
* as-is; a bare host gains `/api/mcp`. Returns undefined for an empty URL.
|
|
45
|
+
* @param {string | undefined} rawUrl
|
|
46
|
+
*/
|
|
47
|
+
export function codexMcpUrl(rawUrl) {
|
|
48
|
+
const u = nonEmpty(rawUrl);
|
|
49
|
+
if (!u) return undefined;
|
|
50
|
+
const trimmed = u.replace(/\/+$/, "");
|
|
51
|
+
const m = trimmed.match(/^https?:\/\/[^/]+(\/.*)?$/);
|
|
52
|
+
if (m && m[1] && m[1].length > 0) return trimmed; // already a full endpoint
|
|
53
|
+
return `${trimmed}/api/mcp`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// TOML basic-string value: escape backslash then double-quote. URLs don't contain these, but
|
|
57
|
+
// escape defensively so we never emit invalid TOML.
|
|
58
|
+
const toToml = (v) => `"${String(v).replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Upsert `[mcp_servers.chorus]` in `~/.codex/config.toml` to
|
|
62
|
+
* url = "<mcp-endpoint>"
|
|
63
|
+
* bearer_token_env_var = "CHORUS_API_KEY"
|
|
64
|
+
* and MIGRATE away any legacy literal auth: a `bearer_token = "..."` line is dropped, and a
|
|
65
|
+
* `[mcp_servers.chorus.http_headers]` `Authorization = "..."` line is removed (dropping the
|
|
66
|
+
* whole http_headers subtable when it becomes empty, preserving any OTHER header). Every other
|
|
67
|
+
* section/key/comment in the file is preserved verbatim.
|
|
68
|
+
*
|
|
69
|
+
* Atomic 0600 temp+rename; idempotent (a re-run with the same url reproduces the file). The API
|
|
70
|
+
* key is NEVER written — only the env-var NAME.
|
|
71
|
+
* @param {{ configPath: string, url: string }} args
|
|
72
|
+
* @param {{
|
|
73
|
+
* read?: (p: string) => string,
|
|
74
|
+
* write?: (p: string, c: string, o: object) => void,
|
|
75
|
+
* mkdir?: (p: string, o: object) => void,
|
|
76
|
+
* rename?: (from: string, to: string) => void,
|
|
77
|
+
* }} [deps]
|
|
78
|
+
* @returns {string} the config.toml path written
|
|
79
|
+
*/
|
|
80
|
+
export function writeCodexMcpServer({ configPath, url }, deps = {}) {
|
|
81
|
+
const read = deps.read ?? ((p) => readFileSync(p, "utf8"));
|
|
82
|
+
const write = deps.write ?? writeFileSync;
|
|
83
|
+
const mkdir = deps.mkdir ?? mkdirSync;
|
|
84
|
+
const rename = deps.rename ?? renameSync;
|
|
85
|
+
|
|
86
|
+
const mcpUrl = codexMcpUrl(url);
|
|
87
|
+
if (!mcpUrl) throw new Error("writeCodexMcpServer requires a url");
|
|
88
|
+
|
|
89
|
+
let existing = "";
|
|
90
|
+
try {
|
|
91
|
+
existing = read(configPath);
|
|
92
|
+
} catch {
|
|
93
|
+
existing = ""; // no file yet — start fresh
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const lines = existing.length ? existing.split(/\r?\n/) : [];
|
|
97
|
+
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
98
|
+
|
|
99
|
+
const isHeader = (s) => /^\s*\[/.test(s);
|
|
100
|
+
const chorusHeaderRe = /^\s*\[mcp_servers\.chorus\]\s*$/;
|
|
101
|
+
const headersHeaderRe = /^\s*\[mcp_servers\.chorus\.http_headers\]\s*$/;
|
|
102
|
+
// A `key = value` line (not a comment or blank) — used to tell whether a subtable still has
|
|
103
|
+
// content after removing Authorization.
|
|
104
|
+
const isKvLine = (s) => /^\s*[^#\s][^=]*=/.test(s);
|
|
105
|
+
|
|
106
|
+
// Split into groups: a preamble (before the first table header) + one group per table header.
|
|
107
|
+
const groups = [];
|
|
108
|
+
let cur = { header: null, body: [] };
|
|
109
|
+
for (const line of lines) {
|
|
110
|
+
if (isHeader(line)) {
|
|
111
|
+
groups.push(cur);
|
|
112
|
+
cur = { header: line, body: [] };
|
|
113
|
+
} else {
|
|
114
|
+
cur.body.push(line);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
groups.push(cur);
|
|
118
|
+
|
|
119
|
+
const outGroups = [];
|
|
120
|
+
let wroteChorus = false;
|
|
121
|
+
for (const g of groups) {
|
|
122
|
+
if (g.header === null) {
|
|
123
|
+
outGroups.push(...g.body); // preamble verbatim
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
if (chorusHeaderRe.test(g.header)) {
|
|
127
|
+
// Normalize the [mcp_servers.chorus] body: set url + bearer_token_env_var in place,
|
|
128
|
+
// drop any literal bearer_token, preserve every other key.
|
|
129
|
+
let seenUrl = false;
|
|
130
|
+
let seenBearerEnv = false;
|
|
131
|
+
const body = [];
|
|
132
|
+
for (const l of g.body) {
|
|
133
|
+
if (/^\s*url\s*=/.test(l)) {
|
|
134
|
+
body.push(`url = ${toToml(mcpUrl)}`);
|
|
135
|
+
seenUrl = true;
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
if (/^\s*bearer_token_env_var\s*=/.test(l)) {
|
|
139
|
+
body.push(`bearer_token_env_var = ${toToml(BEARER_ENV_VAR)}`);
|
|
140
|
+
seenBearerEnv = true;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
if (/^\s*bearer_token\s*=/.test(l)) continue; // drop legacy literal bearer_token
|
|
144
|
+
body.push(l);
|
|
145
|
+
}
|
|
146
|
+
const head = [];
|
|
147
|
+
if (!seenUrl) head.push(`url = ${toToml(mcpUrl)}`);
|
|
148
|
+
if (!seenBearerEnv) head.push(`bearer_token_env_var = ${toToml(BEARER_ENV_VAR)}`);
|
|
149
|
+
outGroups.push(g.header, ...head, ...body);
|
|
150
|
+
wroteChorus = true;
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (headersHeaderRe.test(g.header)) {
|
|
154
|
+
// Strip the literal Authorization; drop the whole subtable if nothing else remains.
|
|
155
|
+
const body = g.body.filter((l) => !/^\s*Authorization\s*=/i.test(l));
|
|
156
|
+
if (body.some(isKvLine)) {
|
|
157
|
+
outGroups.push(g.header, ...body);
|
|
158
|
+
}
|
|
159
|
+
// else: drop the emptied subtable entirely
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
outGroups.push(g.header, ...g.body);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (!wroteChorus) {
|
|
166
|
+
if (outGroups.length && outGroups[outGroups.length - 1] !== "") outGroups.push("");
|
|
167
|
+
outGroups.push(
|
|
168
|
+
"[mcp_servers.chorus]",
|
|
169
|
+
`url = ${toToml(mcpUrl)}`,
|
|
170
|
+
`bearer_token_env_var = ${toToml(BEARER_ENV_VAR)}`,
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Trim trailing blank lines so idempotent re-runs never accumulate them.
|
|
175
|
+
while (outGroups.length && outGroups[outGroups.length - 1] === "") outGroups.pop();
|
|
176
|
+
const content = outGroups.join("\n") + "\n";
|
|
177
|
+
|
|
178
|
+
mkdir(dirname(configPath), { recursive: true });
|
|
179
|
+
const tmp = `${configPath}.tmp`;
|
|
180
|
+
write(tmp, content, { mode: 0o600 });
|
|
181
|
+
rename(tmp, configPath);
|
|
182
|
+
return configPath;
|
|
183
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// cli/init/contracts.mjs
|
|
2
|
+
// Shared contracts for `chorus init` (idea c055e285, A1 foundation). Two
|
|
3
|
+
// extension points let sibling ideas grow the command without editing its core:
|
|
4
|
+
//
|
|
5
|
+
// 1. AgentAdapter — one per coding-agent harness (Claude Code, Codex, Kiro,
|
|
6
|
+
// opencode, OpenClaw, Pi, dsh). Adding an agent = adding an adapter to the
|
|
7
|
+
// registry (cli/init/registry.mjs). Detection, install-state read, and the
|
|
8
|
+
// plugin install all live behind this interface.
|
|
9
|
+
//
|
|
10
|
+
// 2. InitStep — one per configuration concern. THIS change ships the
|
|
11
|
+
// credential-seed step (scope "once") and the plugin-install step (scope
|
|
12
|
+
// "per-agent"). Sibling ideas register more steps (MCP proxy cc115e6b,
|
|
13
|
+
// daemon setup a7c2a3e8) into the same ordered registry.
|
|
14
|
+
//
|
|
15
|
+
// Iteration ownership (resolves proposal-review note #3): the ORCHESTRATOR
|
|
16
|
+
// (runInit) owns per-agent iteration. A `per-agent` step's run(ctx) is invoked
|
|
17
|
+
// once per selected agent with ctx.agentId set; a `once` step's run(ctx) is
|
|
18
|
+
// invoked a single time with ctx.agentId undefined. Steps never loop the
|
|
19
|
+
// selection themselves.
|
|
20
|
+
//
|
|
21
|
+
// Plain ESM, zero dependencies — ships verbatim in the npm package. This module
|
|
22
|
+
// is intentionally (mostly) JSDoc typedefs plus a few frozen enums so the shape
|
|
23
|
+
// is one source of truth for the whole cli/init tree and its tests.
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Step scopes. `once` runs a single time per `chorus init` invocation;
|
|
27
|
+
* `per-agent` runs once for each selected agent.
|
|
28
|
+
* @readonly
|
|
29
|
+
*/
|
|
30
|
+
export const STEP_SCOPES = Object.freeze({ ONCE: "once", PER_AGENT: "per-agent" });
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Terminal per-unit outcomes a step reports for the summary table.
|
|
34
|
+
* - installed: a fresh configuration was applied
|
|
35
|
+
* - repaired: an existing but incomplete/broken configuration was fixed
|
|
36
|
+
* - skipped: already configured / nothing to do
|
|
37
|
+
* - seeded: a `once` step persisted shared state (e.g. credentials)
|
|
38
|
+
* - failed: the unit could not be configured (detail carries the reason)
|
|
39
|
+
* - unsupported: the agent has no verified automated mechanism (guided message)
|
|
40
|
+
* @readonly
|
|
41
|
+
*/
|
|
42
|
+
export const OUTCOME_ACTIONS = Object.freeze({
|
|
43
|
+
INSTALLED: "installed",
|
|
44
|
+
REPAIRED: "repaired",
|
|
45
|
+
SKIPPED: "skipped",
|
|
46
|
+
SEEDED: "seeded",
|
|
47
|
+
FAILED: "failed",
|
|
48
|
+
UNSUPPORTED: "unsupported",
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
/** Outcome actions that mean "this unit did not succeed" — drive the exit code. */
|
|
52
|
+
export const FAILURE_ACTIONS = Object.freeze([OUTCOME_ACTIONS.FAILED]);
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @typedef {Object} AgentDetection
|
|
56
|
+
* @property {string} id Stable adapter id (e.g. "claude").
|
|
57
|
+
* @property {string} displayName Human label (e.g. "Claude Code").
|
|
58
|
+
* @property {boolean} binaryOnPath Whether the agent's CLI resolves on PATH.
|
|
59
|
+
* @property {boolean} configDirPresent Whether the agent's config dir exists.
|
|
60
|
+
* @property {boolean} detected `binaryOnPath || configDirPresent` — drives
|
|
61
|
+
* default pre-selection only, never gates choice.
|
|
62
|
+
*/
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* @typedef {Object} AgentInstallState
|
|
66
|
+
* @property {boolean} supported Whether an automated install is available on
|
|
67
|
+
* this machine (false ⇒ guided message only).
|
|
68
|
+
* @property {boolean} marketplaceRegistered Whether the Chorus marketplace/source
|
|
69
|
+
* is already registered for this agent.
|
|
70
|
+
* @property {boolean} pluginInstalled Whether the Chorus plugin is already installed.
|
|
71
|
+
* @property {string} [version] Installed plugin version, when known.
|
|
72
|
+
* @property {string} [detail] Optional human note (e.g. why unsupported).
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @typedef {Object} AgentAdapter
|
|
77
|
+
* @property {string} id
|
|
78
|
+
* @property {string} displayName
|
|
79
|
+
* @property {(env: NodeJS.ProcessEnv) => {binaryOnPath: boolean, configDirPresent: boolean}} detect
|
|
80
|
+
* Pure-ish: may stat the filesystem and look up PATH; MUST NOT mutate anything.
|
|
81
|
+
* @property {(deps: object) => AgentInstallState} readInstallState
|
|
82
|
+
* Read-only idempotency probe (e.g. parse the agent's own state files).
|
|
83
|
+
* @property {(ctx: StepContext) => StepOutcome} installPlugin
|
|
84
|
+
* Register the agent's native remote marketplace and install/enable the Chorus
|
|
85
|
+
* plugin surface. MUST be idempotent, MUST back up before overwrite via
|
|
86
|
+
* ctx.backup(), and MUST NOT write any per-agent MCP/credential config.
|
|
87
|
+
*/
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @typedef {Object} InitStep
|
|
91
|
+
* @property {string} id Stable step id (e.g. "credential-seed").
|
|
92
|
+
* @property {number} order Ascending run order.
|
|
93
|
+
* @property {("once"|"per-agent")} scope
|
|
94
|
+
* @property {(ctx: StepContext) => (StepOutcome | Promise<StepOutcome>)} run
|
|
95
|
+
*/
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @typedef {Object} StepOutcome
|
|
99
|
+
* @property {string} stepId
|
|
100
|
+
* @property {string} [agentId] Present for per-agent outcomes.
|
|
101
|
+
* @property {("installed"|"repaired"|"skipped"|"seeded"|"failed"|"unsupported")} action
|
|
102
|
+
* @property {string} detail One-line human explanation for the summary.
|
|
103
|
+
*/
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @typedef {Object} StepContext
|
|
107
|
+
* @property {string[]} selection Selected agent ids (for `once` steps that need the set).
|
|
108
|
+
* @property {string} [agentId] The current agent id (per-agent steps only).
|
|
109
|
+
* @property {AgentAdapter} [adapter] The current agent's adapter (per-agent steps only).
|
|
110
|
+
* @property {object} flags Parsed init flags (see cli/init-args.mjs).
|
|
111
|
+
* @property {{ log: (m: string) => void, ask: Function, isTTY: boolean }} io
|
|
112
|
+
* @property {(path: string) => (string|null)} backup Copy a file to <path>.chorus-bak
|
|
113
|
+
* once before overwrite; returns the backup path or null if the source is absent.
|
|
114
|
+
* @property {NodeJS.ProcessEnv} env
|
|
115
|
+
*/
|
|
116
|
+
|
|
117
|
+
/** True when an outcome represents a failure (drives the process exit code). */
|
|
118
|
+
export function isFailureOutcome(outcome) {
|
|
119
|
+
return !!outcome && FAILURE_ACTIONS.includes(outcome.action);
|
|
120
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// cli/init/detect.mjs
|
|
2
|
+
// Cross-platform detection primitives for `chorus init` adapters. Dual signal:
|
|
3
|
+
// a CLI binary resolvable on PATH, and/or an agent config directory present.
|
|
4
|
+
// All IO (env, filesystem, platform, home) is injectable so adapters unit-test
|
|
5
|
+
// without a real machine. Zero runtime dependencies beyond node core.
|
|
6
|
+
|
|
7
|
+
import { existsSync as fsExistsSync } from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join, delimiter as pathDelimiter } from "node:path";
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Expand a config-dir spec into an absolute path:
|
|
13
|
+
* - a leading `~` → the home directory,
|
|
14
|
+
* - a leading `$VAR` segment → env[VAR] (whole spec dropped if unset),
|
|
15
|
+
* Returns null when the spec cannot be resolved (e.g. `$DSH_HOME` unset).
|
|
16
|
+
* @param {string} spec
|
|
17
|
+
* @param {{ env?: Record<string,string|undefined>, home?: string }} [deps]
|
|
18
|
+
* @returns {string | null}
|
|
19
|
+
*/
|
|
20
|
+
export function expandPath(spec, { env = process.env, home = homedir() } = {}) {
|
|
21
|
+
if (typeof spec !== "string" || !spec) return null;
|
|
22
|
+
if (spec.startsWith("~")) {
|
|
23
|
+
return join(home, spec.slice(1).replace(/^[/\\]/, ""));
|
|
24
|
+
}
|
|
25
|
+
if (spec.startsWith("$")) {
|
|
26
|
+
const slash = spec.search(/[/\\]/);
|
|
27
|
+
const varName = (slash === -1 ? spec.slice(1) : spec.slice(1, slash));
|
|
28
|
+
const value = env[varName];
|
|
29
|
+
if (!value) return null; // unset env var → this candidate does not apply
|
|
30
|
+
const rest = slash === -1 ? "" : spec.slice(slash + 1);
|
|
31
|
+
return rest ? join(value, rest) : value;
|
|
32
|
+
}
|
|
33
|
+
return spec;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* True if any of `names` resolves to an executable on PATH. Scans PATH entries
|
|
38
|
+
* and (on Windows) the PATHEXT extension list. Pure lookup — never executes.
|
|
39
|
+
* @param {string[]} names candidate binary base names (e.g. ["claude"])
|
|
40
|
+
* @param {{
|
|
41
|
+
* env?: Record<string,string|undefined>,
|
|
42
|
+
* existsSync?: (p: string) => boolean,
|
|
43
|
+
* platform?: NodeJS.Platform,
|
|
44
|
+
* }} [deps]
|
|
45
|
+
* @returns {boolean}
|
|
46
|
+
*/
|
|
47
|
+
export function binaryOnPath(names, { env = process.env, existsSync = fsExistsSync, platform = process.platform } = {}) {
|
|
48
|
+
const rawPath = env.PATH ?? env.Path ?? "";
|
|
49
|
+
if (!rawPath) return false;
|
|
50
|
+
const sep = platform === "win32" ? ";" : pathDelimiter;
|
|
51
|
+
const dirs = rawPath.split(sep).filter(Boolean);
|
|
52
|
+
const exts =
|
|
53
|
+
platform === "win32"
|
|
54
|
+
? ["", ...String(env.PATHEXT ?? ".EXE;.CMD;.BAT;.COM").split(";").filter(Boolean)]
|
|
55
|
+
: [""];
|
|
56
|
+
for (const name of names) {
|
|
57
|
+
if (!name) continue;
|
|
58
|
+
for (const dir of dirs) {
|
|
59
|
+
for (const ext of exts) {
|
|
60
|
+
// Windows filesystems are case-insensitive; try the ext as-given.
|
|
61
|
+
if (existsSync(join(dir, name + ext))) return true;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* True if any of the config-dir specs (after expandPath) exists on disk.
|
|
70
|
+
* @param {string[]} specs
|
|
71
|
+
* @param {{
|
|
72
|
+
* env?: Record<string,string|undefined>,
|
|
73
|
+
* existsSync?: (p: string) => boolean,
|
|
74
|
+
* home?: string,
|
|
75
|
+
* }} [deps]
|
|
76
|
+
* @returns {boolean}
|
|
77
|
+
*/
|
|
78
|
+
export function configDirPresent(specs, { env = process.env, existsSync = fsExistsSync, home = homedir() } = {}) {
|
|
79
|
+
for (const spec of specs || []) {
|
|
80
|
+
const resolved = expandPath(spec, { env, home });
|
|
81
|
+
if (resolved && existsSync(resolved)) return true;
|
|
82
|
+
}
|
|
83
|
+
return false;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Compute the dual-signal detection for one agent descriptor.
|
|
88
|
+
* @param {{ binaries: string[], configDirs: string[] }} descriptor
|
|
89
|
+
* @param {object} [deps] forwarded to binaryOnPath / configDirPresent
|
|
90
|
+
* @returns {{ binaryOnPath: boolean, configDirPresent: boolean }}
|
|
91
|
+
*/
|
|
92
|
+
export function detectSignals(descriptor, deps = {}) {
|
|
93
|
+
return {
|
|
94
|
+
binaryOnPath: binaryOnPath(descriptor.binaries || [], deps),
|
|
95
|
+
configDirPresent: configDirPresent(descriptor.configDirs || [], deps),
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
// cli/init/file-template.mjs
|
|
2
|
+
// Kiro's Chorus "plugin" is not a CLI-installable package — it is a set of loose
|
|
3
|
+
// files dropped under .kiro/ (skills, the `chorus` main agent + reviewer
|
|
4
|
+
// subagents, the steering doc, and the session-automation hook scripts), plus a
|
|
5
|
+
// `chorus` MCP server merged into settings/mcp.json. This module drops those
|
|
6
|
+
// files natively in pure JS so `chorus init` can install them CROSS-PLATFORM
|
|
7
|
+
// (Windows-safe) with no bash / curl dependency — Node's built-in `fetch`
|
|
8
|
+
// downloads the template, node:fs writes it. (The legacy public/install-kiro.sh
|
|
9
|
+
// is now a deprecation stub that redirects to `chorus init`; this module is the
|
|
10
|
+
// sole Kiro plugin installer.)
|
|
11
|
+
//
|
|
12
|
+
// ASSET SOURCE (owner-decided): the .kiro/ assets are DOWNLOADED from the
|
|
13
|
+
// connected Chorus instance at `${CHORUS_URL}/kiro-plugin/…`, NOT bundled into
|
|
14
|
+
// the npm package. `chorus init` already holds the connection URL, so this keeps
|
|
15
|
+
// the assets in lockstep with the server the user is connecting to and avoids
|
|
16
|
+
// shipping a second copy.
|
|
17
|
+
//
|
|
18
|
+
// The variable asset lists (skills / reviewer agents / hook scripts) live in a
|
|
19
|
+
// data file — public/kiro-plugin/manifest.txt — read by this module
|
|
20
|
+
// (parseManifest), so the shipped asset set is declared in one place.
|
|
21
|
+
|
|
22
|
+
import { readFileSync, writeFileSync, mkdirSync, chmodSync, existsSync } from "node:fs";
|
|
23
|
+
import { join, dirname } from "node:path";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
|
|
26
|
+
/** The shared artifact manifest (repo path — used by the parity test; the runtime
|
|
27
|
+
* installer downloads its own copy from the instance so it works in the stripped
|
|
28
|
+
* npm package where public/ is not shipped). */
|
|
29
|
+
export const KIRO_MANIFEST_URL = new URL("../../public/kiro-plugin/manifest.txt", import.meta.url);
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Parse the manifest text into the three artifact lists: one "<kind> <name>"
|
|
33
|
+
* pair per line; blank lines and `#` comments ignored; kind ∈ {skill, reviewer,
|
|
34
|
+
* hook}. Unknown kinds are ignored (forward-compatible).
|
|
35
|
+
* @param {string} text
|
|
36
|
+
* @returns {{ skills: string[], reviewerAgents: string[], hookScripts: string[] }}
|
|
37
|
+
*/
|
|
38
|
+
export function parseManifest(text) {
|
|
39
|
+
const skills = [];
|
|
40
|
+
const reviewerAgents = [];
|
|
41
|
+
const hookScripts = [];
|
|
42
|
+
for (const rawLine of String(text ?? "").split(/\r?\n/)) {
|
|
43
|
+
const line = rawLine.trim();
|
|
44
|
+
if (!line || line.startsWith("#")) continue;
|
|
45
|
+
const parts = line.split(/\s+/);
|
|
46
|
+
const kind = parts[0];
|
|
47
|
+
const name = parts[1];
|
|
48
|
+
if (!name) continue;
|
|
49
|
+
if (kind === "skill") skills.push(name);
|
|
50
|
+
else if (kind === "reviewer") reviewerAgents.push(name);
|
|
51
|
+
else if (kind === "hook") hookScripts.push(name);
|
|
52
|
+
}
|
|
53
|
+
return { skills, reviewerAgents, hookScripts };
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** Read + parse the shared manifest from a local file (default: the repo copy).
|
|
57
|
+
* Used by the parity test; the installer downloads its copy instead. */
|
|
58
|
+
export function readKiroManifestFile({ manifestUrl = KIRO_MANIFEST_URL } = {}) {
|
|
59
|
+
return parseManifest(readFileSync(fileURLToPath(manifestUrl), "utf8"));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Normalize a Chorus connection URL to the ASSET BASE — the origin under which
|
|
64
|
+
* public/ is served (public/kiro-plugin/… ⇒ `${base}/kiro-plugin/…`). Mirrors
|
|
65
|
+
* install-kiro.sh: strip a trailing `/api/mcp` (the MCP endpoint) and any
|
|
66
|
+
* trailing slash. Throws on an empty / non-http(s) URL (named in the message).
|
|
67
|
+
* @param {string} chorusUrl
|
|
68
|
+
* @returns {string}
|
|
69
|
+
*/
|
|
70
|
+
export function normalizeAssetBase(chorusUrl) {
|
|
71
|
+
const raw = typeof chorusUrl === "string" ? chorusUrl.trim() : "";
|
|
72
|
+
if (!raw) throw new Error("CHORUS_URL is not set — cannot download the kiro .kiro/ template");
|
|
73
|
+
if (!/^https?:\/\//i.test(raw)) {
|
|
74
|
+
throw new Error(`CHORUS_URL must start with http:// or https:// — got: ${raw}`);
|
|
75
|
+
}
|
|
76
|
+
return raw
|
|
77
|
+
.replace(/\/+$/, "") // trailing slash(es)
|
|
78
|
+
.replace(/\/api\/mcp$/i, "") // the MCP endpoint suffix
|
|
79
|
+
.replace(/\/+$/, ""); // any slash the strip left behind
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Substitute the `__CHORUS_BIN__` placeholder in the main agent's hook `command`
|
|
84
|
+
* strings with the resolved ABSOLUTE chorus-bin path. Fails loudly (throws) if
|
|
85
|
+
* any placeholder survives — mirrors install-kiro.sh's post-write grep guard.
|
|
86
|
+
* @param {string} text raw agents/chorus.json content
|
|
87
|
+
* @param {string} chorusBinAbs absolute path to <KIRO_DIR>/chorus-bin
|
|
88
|
+
* @returns {string}
|
|
89
|
+
*/
|
|
90
|
+
export function substituteChorusBin(text, chorusBinAbs) {
|
|
91
|
+
const out = String(text).split("__CHORUS_BIN__").join(chorusBinAbs);
|
|
92
|
+
if (out.includes("__CHORUS_BIN__")) {
|
|
93
|
+
throw new Error("__CHORUS_BIN__ placeholder was not fully substituted in agents/chorus.json");
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Merge the `chorus` MCP server into an existing settings/mcp.json body,
|
|
100
|
+
* PRESERVING every pre-existing server. Empty/absent body ⇒ a fresh document.
|
|
101
|
+
* Invalid JSON throws (never silently clobbers a file we can't parse).
|
|
102
|
+
* @param {string} existingText current file contents ("" if absent)
|
|
103
|
+
* @param {object} serverObj the chorus server object to set at .mcpServers.chorus
|
|
104
|
+
* @returns {string} pretty-printed JSON (trailing newline)
|
|
105
|
+
*/
|
|
106
|
+
export function mergeChorusServer(existingText, serverObj) {
|
|
107
|
+
let data = {};
|
|
108
|
+
const trimmed = (existingText ?? "").trim();
|
|
109
|
+
if (trimmed) {
|
|
110
|
+
try {
|
|
111
|
+
data = JSON.parse(trimmed);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
throw new Error(`existing settings/mcp.json is not valid JSON: ${err?.message ?? String(err)}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (typeof data !== "object" || data === null || Array.isArray(data)) data = {};
|
|
117
|
+
if (typeof data.mcpServers !== "object" || data.mcpServers === null || Array.isArray(data.mcpServers)) {
|
|
118
|
+
data.mcpServers = {};
|
|
119
|
+
}
|
|
120
|
+
data.mcpServers.chorus = serverObj;
|
|
121
|
+
return `${JSON.stringify(data, null, 2)}\n`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Install the Chorus `.kiro/` file template natively.
|
|
126
|
+
*
|
|
127
|
+
* Two phases guarantee NO PARTIAL DROP: (1) download every asset into memory,
|
|
128
|
+
* verifying each fetch and aborting (naming the unreachable URL) before touching
|
|
129
|
+
* disk; (2) only once all fetches succeed, write the tree, chmod hooks (POSIX
|
|
130
|
+
* only), and merge the `chorus` MCP server into settings/mcp.json.
|
|
131
|
+
*
|
|
132
|
+
* @param {{
|
|
133
|
+
* chorusUrl: string,
|
|
134
|
+
* kiroDir: string,
|
|
135
|
+
* fetchImpl?: typeof fetch,
|
|
136
|
+
* backup?: (path: string) => (string|null),
|
|
137
|
+
* platform?: NodeJS.Platform,
|
|
138
|
+
* log?: (m: string) => void,
|
|
139
|
+
* }} opts
|
|
140
|
+
* @returns {Promise<{ skills: number, reviewerAgents: number, hookScripts: number, kiroDir: string, chorusBinAbs: string }>}
|
|
141
|
+
*/
|
|
142
|
+
export async function installFileTemplate({
|
|
143
|
+
chorusUrl,
|
|
144
|
+
kiroDir,
|
|
145
|
+
fetchImpl,
|
|
146
|
+
backup,
|
|
147
|
+
platform = process.platform,
|
|
148
|
+
log,
|
|
149
|
+
} = {}) {
|
|
150
|
+
const assetBase = normalizeAssetBase(chorusUrl); // throws on bad/empty URL
|
|
151
|
+
const doFetch = fetchImpl ?? globalThis.fetch;
|
|
152
|
+
if (typeof doFetch !== "function") {
|
|
153
|
+
throw new Error("no fetch implementation available (need Node 18+ global fetch or an injected fetchImpl)");
|
|
154
|
+
}
|
|
155
|
+
const kiroBase = `${assetBase}/kiro-plugin`;
|
|
156
|
+
const chorusBinAbs = join(kiroDir, "chorus-bin");
|
|
157
|
+
|
|
158
|
+
// fetch <relpath-under-kiro-plugin> as text; verify + name the URL on failure.
|
|
159
|
+
async function fetchText(rel) {
|
|
160
|
+
const url = `${kiroBase}/${rel}`;
|
|
161
|
+
let res;
|
|
162
|
+
try {
|
|
163
|
+
res = await doFetch(url);
|
|
164
|
+
} catch (err) {
|
|
165
|
+
throw new Error(`failed to download ${url}: ${err?.message ?? String(err)}`);
|
|
166
|
+
}
|
|
167
|
+
if (!res || !res.ok) {
|
|
168
|
+
throw new Error(`failed to download ${url} (HTTP ${res?.status ?? "?"}) — is CHORUS_URL correct and reachable?`);
|
|
169
|
+
}
|
|
170
|
+
return await res.text();
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ---- phase 1: fetch EVERYTHING into memory (no disk writes) ----
|
|
174
|
+
const manifest = parseManifest(await fetchText("manifest.txt"));
|
|
175
|
+
if (manifest.skills.length === 0 && manifest.reviewerAgents.length === 0 && manifest.hookScripts.length === 0) {
|
|
176
|
+
throw new Error(`manifest at ${kiroBase}/manifest.txt resolved no assets — is the instance serving the kiro plugin?`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** @type {Map<string, { text: string, exec?: boolean }>} dest-abs-path -> content */
|
|
180
|
+
const files = new Map();
|
|
181
|
+
|
|
182
|
+
// fixed assets (single, always-present files — not in the variable manifest)
|
|
183
|
+
const mcpTemplateText = await fetchText(".kiro/settings/mcp.json");
|
|
184
|
+
files.set(join(kiroDir, "steering", "chorus.md"), { text: await fetchText(".kiro/steering/chorus.md") });
|
|
185
|
+
files.set(join(kiroDir, "agents", "chorus.md"), { text: await fetchText(".kiro/agents/chorus.md") });
|
|
186
|
+
// main agent: substitute the hook-command placeholder in memory (throws if it survives)
|
|
187
|
+
files.set(join(kiroDir, "agents", "chorus.json"), {
|
|
188
|
+
text: substituteChorusBin(await fetchText(".kiro/agents/chorus.json"), chorusBinAbs),
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
for (const a of manifest.reviewerAgents) {
|
|
192
|
+
files.set(join(kiroDir, "agents", `${a}.json`), { text: await fetchText(`.kiro/agents/${a}.json`) });
|
|
193
|
+
}
|
|
194
|
+
for (const s of manifest.skills) {
|
|
195
|
+
files.set(join(kiroDir, "skills", s, "SKILL.md"), { text: await fetchText(`.kiro/skills/${s}/SKILL.md`) });
|
|
196
|
+
}
|
|
197
|
+
for (const h of manifest.hookScripts) {
|
|
198
|
+
files.set(join(chorusBinAbs, h), { text: await fetchText(`bin/${h}`), exec: true });
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// The chorus server object is single-sourced from the downloaded template, but
|
|
202
|
+
// its `url` MUST be the CONCRETE endpoint, not the template's
|
|
203
|
+
// `${CHORUS_URL}/api/mcp` token: kiro does NOT interpolate a bare `${...}` in the
|
|
204
|
+
// url field (only `${env:...}`, as the Authorization header uses), so leaving a
|
|
205
|
+
// token here makes kiro fail the server with "relative URL without a base". Bake
|
|
206
|
+
// the resolved `<assetBase>/api/mcp`; the API key stays the `${env:CHORUS_API_KEY}`
|
|
207
|
+
// ref — kiro DOES resolve that, and it keeps the secret off disk + per-agent.
|
|
208
|
+
let serverObj;
|
|
209
|
+
try {
|
|
210
|
+
serverObj = JSON.parse(mcpTemplateText)?.mcpServers?.chorus;
|
|
211
|
+
} catch (err) {
|
|
212
|
+
throw new Error(`downloaded settings/mcp.json template is not valid JSON: ${err?.message ?? String(err)}`);
|
|
213
|
+
}
|
|
214
|
+
if (!serverObj || typeof serverObj !== "object") {
|
|
215
|
+
throw new Error("downloaded settings/mcp.json template has no mcpServers.chorus entry to merge");
|
|
216
|
+
}
|
|
217
|
+
serverObj.url = `${assetBase}/api/mcp`;
|
|
218
|
+
|
|
219
|
+
// ---- phase 2: write to disk (every fetch already verified) ----
|
|
220
|
+
for (const [dest, { text, exec }] of files) {
|
|
221
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
222
|
+
writeFileSync(dest, text);
|
|
223
|
+
if (exec && platform !== "win32") {
|
|
224
|
+
try {
|
|
225
|
+
chmodSync(dest, 0o755);
|
|
226
|
+
} catch {
|
|
227
|
+
// chmod is best-effort; a read-only FS shouldn't fail the whole install.
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// ---- merge the `chorus` MCP server into settings/mcp.json (back up first) ----
|
|
233
|
+
const mcpJsonPath = join(kiroDir, "settings", "mcp.json");
|
|
234
|
+
mkdirSync(dirname(mcpJsonPath), { recursive: true });
|
|
235
|
+
const existed = existsSync(mcpJsonPath);
|
|
236
|
+
if (existed && typeof backup === "function") backup(mcpJsonPath);
|
|
237
|
+
const existingText = existed ? readFileSync(mcpJsonPath, "utf8") : "";
|
|
238
|
+
writeFileSync(mcpJsonPath, mergeChorusServer(existingText, serverObj));
|
|
239
|
+
|
|
240
|
+
log?.(`[chorus agents add] kiro: wrote .kiro/ template into ${kiroDir}`);
|
|
241
|
+
return {
|
|
242
|
+
skills: manifest.skills.length,
|
|
243
|
+
reviewerAgents: manifest.reviewerAgents.length,
|
|
244
|
+
hookScripts: manifest.hookScripts.length,
|
|
245
|
+
kiroDir,
|
|
246
|
+
chorusBinAbs,
|
|
247
|
+
};
|
|
248
|
+
}
|