gsd-pi 2.54.0-dev.e1efc1a → 2.55.0-dev.9ec7cdf
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/dist/cli.js +19 -19
- package/dist/headless-ui.d.ts +27 -1
- package/dist/headless-ui.js +203 -13
- package/dist/headless.js +60 -3
- package/dist/resources/extensions/bg-shell/bg-shell-lifecycle.js +2 -2
- package/dist/resources/extensions/bg-shell/utilities.js +34 -5
- package/dist/resources/extensions/gsd/auto/phases.js +19 -3
- package/dist/resources/extensions/gsd/auto-dispatch.js +1 -1
- package/dist/resources/extensions/gsd/auto-model-selection.js +17 -1
- package/dist/resources/extensions/gsd/auto-prompts.js +9 -0
- package/dist/resources/extensions/gsd/auto-start.js +12 -5
- package/dist/resources/extensions/gsd/auto-worktree.js +39 -14
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +18 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -5
- package/dist/resources/extensions/gsd/bootstrap/register-shortcuts.js +20 -0
- package/dist/resources/extensions/gsd/commands/catalog.js +2 -1
- package/dist/resources/extensions/gsd/commands/handlers/parallel.js +15 -1
- package/dist/resources/extensions/gsd/crash-recovery.js +2 -2
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +413 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +5 -1
- package/dist/resources/extensions/gsd/session-lock.js +46 -12
- package/dist/resources/extensions/gsd/skill-health.js +2 -2
- package/dist/resources/extensions/gsd/visualizer-overlay.js +3 -3
- package/dist/resources/extensions/shared/format-utils.js +1 -1
- package/dist/resources/extensions/subagent/worker-registry.js +2 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +18 -18
- package/dist/web/standalone/.next/server/chunks/2229.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.2305d0afd2385711.js +9 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-b950e4e384cc62b3.js → page-0c485498795110d6.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-bca0e732db0dcec3.js → webpack-4332cbd5dd1be584.js} +1 -1
- package/package.json +6 -4
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +14 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/model-registry.ts +1 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -2
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -41
- package/src/resources/extensions/bg-shell/bg-shell-lifecycle.ts +2 -2
- package/src/resources/extensions/bg-shell/utilities.ts +39 -4
- package/src/resources/extensions/gsd/auto/phases.ts +25 -4
- package/src/resources/extensions/gsd/auto-dispatch.ts +1 -1
- package/src/resources/extensions/gsd/auto-model-selection.ts +21 -1
- package/src/resources/extensions/gsd/auto-prompts.ts +15 -0
- package/src/resources/extensions/gsd/auto-start.ts +13 -5
- package/src/resources/extensions/gsd/auto-worktree.ts +46 -13
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +5 -4
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +53 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -6
- package/src/resources/extensions/gsd/bootstrap/register-shortcuts.ts +24 -0
- package/src/resources/extensions/gsd/commands/catalog.ts +2 -1
- package/src/resources/extensions/gsd/commands/handlers/parallel.ts +19 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +2 -3
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +497 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +6 -1
- package/src/resources/extensions/gsd/session-lock.ts +46 -12
- package/src/resources/extensions/gsd/skill-health.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +139 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/{all-milestones-complete-merge.test.ts → integration/all-milestones-complete-merge.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{atomic-task-closeout.test.ts → integration/atomic-task-closeout.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{auto-preflight.test.ts → integration/auto-preflight.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{auto-recovery.test.ts → integration/auto-recovery.test.ts} +7 -7
- package/src/resources/extensions/gsd/tests/{auto-secrets-gate.test.ts → integration/auto-secrets-gate.test.ts} +2 -2
- package/src/resources/extensions/gsd/tests/{auto-stash-merge.test.ts → integration/auto-stash-merge.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{auto-worktree-milestone-merge.test.ts → integration/auto-worktree-milestone-merge.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{auto-worktree.test.ts → integration/auto-worktree.test.ts} +5 -5
- package/src/resources/extensions/gsd/tests/{continue-here.test.ts → integration/continue-here.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{doctor-completion-deferral.test.ts → integration/doctor-completion-deferral.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-delimiter-fix.test.ts → integration/doctor-delimiter-fix.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-enhancements.test.ts → integration/doctor-enhancements.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{doctor-environment-worktree.test.ts → integration/doctor-environment-worktree.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-environment.test.ts → integration/doctor-environment.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-fixlevel.test.ts → integration/doctor-fixlevel.test.ts} +2 -2
- package/src/resources/extensions/gsd/tests/{doctor-git.test.ts → integration/doctor-git.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-proactive.test.ts → integration/doctor-proactive.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-roadmap-summary-atomicity.test.ts → integration/doctor-roadmap-summary-atomicity.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor-runtime.test.ts → integration/doctor-runtime.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{doctor.test.ts → integration/doctor.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{e2e-workflow-pipeline-integration.test.ts → integration/e2e-workflow-pipeline-integration.test.ts} +5 -5
- package/src/resources/extensions/gsd/tests/{feature-branch-lifecycle-integration.test.ts → integration/feature-branch-lifecycle-integration.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{git-locale.test.ts → integration/git-locale.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{git-self-heal.test.ts → integration/git-self-heal.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{git-service.test.ts → integration/git-service.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{gitignore-tracked-gsd.test.ts → integration/gitignore-tracked-gsd.test.ts} +2 -2
- package/src/resources/extensions/gsd/tests/{idle-recovery.test.ts → integration/idle-recovery.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{inherited-repo-home-dir.test.ts → integration/inherited-repo-home-dir.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{integration-lifecycle.test.ts → integration/integration-lifecycle.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{integration-mixed-milestones.test.ts → integration/integration-mixed-milestones.test.ts} +6 -6
- package/src/resources/extensions/gsd/tests/{integration-proof.test.ts → integration/integration-proof.test.ts} +12 -12
- package/src/resources/extensions/gsd/tests/{migrate-command.test.ts → integration/migrate-command.test.ts} +2 -2
- package/src/resources/extensions/gsd/tests/{milestone-transition-worktree.test.ts → integration/milestone-transition-worktree.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{parallel-merge.test.ts → integration/parallel-merge.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{parallel-workers-multi-milestone-e2e.test.ts → integration/parallel-workers-multi-milestone-e2e.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{paths.test.ts → integration/paths.test.ts} +1 -1
- package/src/resources/extensions/gsd/tests/{plugin-importer-live.test.ts → integration/plugin-importer-live.test.ts} +2 -2
- package/src/resources/extensions/gsd/tests/{queue-completed-milestone-perf.test.ts → integration/queue-completed-milestone-perf.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{queue-reorder-e2e.test.ts → integration/queue-reorder-e2e.test.ts} +5 -5
- package/src/resources/extensions/gsd/tests/{quick-branch-lifecycle.test.ts → integration/quick-branch-lifecycle.test.ts} +5 -5
- package/src/resources/extensions/gsd/tests/{run-uat.test.ts → integration/run-uat.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/{token-savings.test.ts → integration/token-savings.test.ts} +3 -3
- package/src/resources/extensions/gsd/tests/{worktree-e2e.test.ts → integration/worktree-e2e.test.ts} +4 -4
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +60 -0
- package/src/resources/extensions/gsd/tests/parallel-worker-lock-contention.test.ts +226 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-queue-context.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +61 -19
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/worktree-preferences-sync.test.ts +49 -24
- package/src/resources/extensions/gsd/visualizer-overlay.ts +3 -3
- package/src/resources/extensions/shared/format-utils.ts +1 -1
- package/src/resources/extensions/subagent/worker-registry.ts +2 -1
- package/dist/web/standalone/.next/static/chunks/4024.87fd909ae0110f50.js +0 -9
- /package/dist/web/standalone/.next/static/{nISuDzAIpGYC-DVTvs4Po → k92jvAf8IfV4dZE3nnrAr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{nISuDzAIpGYC-DVTvs4Po → k92jvAf8IfV4dZE3nnrAr}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/provider-manager.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACN,SAAS,EAET,oBAAoB,EACpB,MAAM,EACN,IAAI,GAEJ,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,wBAAwB,EAAE,MAAM,kCAAkC,CAAC;AAE5E,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AASnD,MAAM,OAAO,wBAAyB,SAAQ,SAAS;IAEtD,IAAI,OAAO;QACV,OAAO,IAAI,CAAC,QAAQ,CAAC;IACtB,CAAC;IACD,IAAI,OAAO,CAAC,KAAc;QACzB,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACvB,CAAC;IAWD,YACC,GAAQ,EACR,WAAwB,EACxB,aAA4B,EAC5B,MAAkB,EAClB,UAAsC;QAEtC,KAAK,EAAE,CAAC;QAxBD,aAAQ,GAAG,KAAK,CAAC;QAQjB,cAAS,GAAmB,EAAE,CAAC;QAC/B,kBAAa,GAAG,CAAC,CAAC;QAiBzB,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,aAAa,GAAG,aAAa,CAAC;QACnC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAE7B,SAAS;QACT,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,QAAQ;QACR,MAAM,KAAK,GAAG;YACb,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC;YAC3B,UAAU,CAAC,GAAG,EAAE,aAAa,CAAC;YAC9B,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC;SAC1B,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACb,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAE7B,OAAO;QACP,IAAI,CAAC,aAAa,GAAG,IAAI,SAAS,EAAE,CAAC;QACrC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAElC,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,UAAU,EAAE,CAAC;IACnB,CAAC;IAEO,aAAa;QACpB,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,wBAAwB,EAAE,CAAC,CAAC;QAC5D,MAAM,SAAS,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;QAE9C,2BAA2B;QAC3B,MAAM,mBAAmB,GAAG,IAAI,GAAG,EAAkB,CAAC;QACtD,KAAK,MAAM,KAAK,IAAI,SAAS,EAAE,CAAC;YAC/B,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,mBAAmB,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7F,CAAC;QAED,+CAA+C;QAC/C,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;YAC7B,GAAG,mBAAmB,CAAC,IAAI,EAAE;YAC7B,GAAG,eAAe;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC;aACxC,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACf,IAAI;YACJ,OAAO,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;YACvC,iBAAiB,EAAE,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;YAC5C,UAAU,EAAE,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;SAC9C,CAAC,CAAC,CAAC;IACN,CAAC;IAEO,UAAU;QACjB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAE3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAChD,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;YAC5B,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC;YAE5C,MAAM,SAAS,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YAC7F,MAAM,cAAc,GAAG,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpF,MAAM,UAAU,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,UAAU,UAAU,CAAC,CAAC;YAEjE,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC5D,MAAM,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAElE,MAAM,KAAK,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,CAAC,CAAC;YACjD,IAAI,cAAc;gBAAE,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;YACpD,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;YAE5B,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7D,CAAC;QAED,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,2BAA2B,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7F,CAAC;IACF,CAAC;IAED,WAAW,CAAC,OAAe;QAC1B,MAAM,EAAE,GAAG,oBAAoB,EAAE,CAAC;QAElC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC;YACrC,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACnG,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;aAAM,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,CAAC;YAC9C,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC;gBAAE,OAAO;YACxC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;YACnG,IAAI,CAAC,UAAU,EAAE,CAAC;YAClB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC1B,CAAC;aAAM,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACf,CAAC;aAAM,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACpD,IAAI,QAAQ,EAAE,iBAAiB,EAAE,CAAC;gBACjC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC;QACF,CAAC;aAAM,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,GAAG,EAAE,CAAC;YAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;YACpD,IAAI,QAAQ,EAAE,OAAO,EAAE,CAAC;gBACvB,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;gBACvC,IAAI,CAAC,aAAa,EAAE,CAAC;gBACrB,IAAI,CAAC,UAAU,EAAE,CAAC;gBAClB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YAC1B,CAAC;QACF,CAAC;IACF,CAAC;CACD","sourcesContent":["/**\n * TUI component for managing provider configurations.\n * Shows providers with auth status, discovery support, and model counts.\n */\n\nimport {\n\tContainer,\n\ttype Focusable,\n\tgetEditorKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getDiscoverableProviders } from \"../../../core/model-discovery.js\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { rawKeyHint } from \"./keybinding-hints.js\";\n\ninterface ProviderInfo {\n\tname: string;\n\thasAuth: boolean;\n\tsupportsDiscovery: boolean;\n\tmodelCount: number;\n}\n\nexport class ProviderManagerComponent extends Container implements Focusable {\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tprivate providers: ProviderInfo[] = [];\n\tprivate selectedIndex = 0;\n\tprivate listContainer: Container;\n\tprivate tui: TUI;\n\tprivate authStorage: AuthStorage;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate onDone: () => void;\n\tprivate onDiscover: (provider: string) => void;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tauthStorage: AuthStorage,\n\t\tmodelRegistry: ModelRegistry,\n\t\tonDone: () => void,\n\t\tonDiscover: (provider: string) => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.onDone = onDone;\n\t\tthis.onDiscover = onDiscover;\n\n\t\t// Header\n\t\tthis.addChild(new Text(theme.fg(\"accent\", \"Provider Manager\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Hints\n\t\tconst hints = [\n\t\t\trawKeyHint(\"d\", \"discover\"),\n\t\t\trawKeyHint(\"r\", \"remove auth\"),\n\t\t\trawKeyHint(\"esc\", \"close\"),\n\t\t].join(\" \");\n\t\tthis.addChild(new Text(hints, 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.loadProviders();\n\t\tthis.updateList();\n\t}\n\n\tprivate loadProviders(): void {\n\t\tconst discoverableSet = new Set(getDiscoverableProviders());\n\t\tconst allModels = this.modelRegistry.getAll();\n\n\t\t// Group models by provider\n\t\tconst providerModelCounts = new Map<string, number>();\n\t\tfor (const model of allModels) {\n\t\t\tproviderModelCounts.set(model.provider, (providerModelCounts.get(model.provider) ?? 0) + 1);\n\t\t}\n\n\t\t// Build provider list from all known providers\n\t\tconst providerNames = new Set([\n\t\t\t...providerModelCounts.keys(),\n\t\t\t...discoverableSet,\n\t\t]);\n\n\t\tthis.providers = Array.from(providerNames)\n\t\t\t.sort()\n\t\t\t.map((name) => ({\n\t\t\t\tname,\n\t\t\t\thasAuth: this.authStorage.hasAuth(name),\n\t\t\t\tsupportsDiscovery: discoverableSet.has(name),\n\t\t\t\tmodelCount: providerModelCounts.get(name) ?? 0,\n\t\t\t}));\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tfor (let i = 0; i < this.providers.length; i++) {\n\t\t\tconst p = this.providers[i];\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst authBadge = p.hasAuth ? theme.fg(\"success\", \"[auth]\") : theme.fg(\"muted\", \"[no auth]\");\n\t\t\tconst discoveryBadge = p.supportsDiscovery ? theme.fg(\"accent\", \"[discovery]\") : \"\";\n\t\t\tconst countBadge = theme.fg(\"muted\", `(${p.modelCount} models)`);\n\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"> \") : \" \";\n\t\t\tconst nameText = isSelected ? theme.fg(\"accent\", p.name) : p.name;\n\n\t\t\tconst parts = [prefix, nameText, \" \", authBadge];\n\t\t\tif (discoveryBadge) parts.push(\" \", discoveryBadge);\n\t\t\tparts.push(\" \", countBadge);\n\n\t\t\tthis.listContainer.addChild(new Text(parts.join(\"\"), 0, 0));\n\t\t}\n\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No providers configured\"), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.providers.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.providers.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tthis.onDone();\n\t\t} else if (keyData === \"d\" || keyData === \"D\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.supportsDiscovery) {\n\t\t\t\tthis.onDiscover(provider.name);\n\t\t\t}\n\t\t} else if (keyData === \"r\" || keyData === \"R\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.hasAuth) {\n\t\t\t\tthis.authStorage.remove(provider.name);\n\t\t\t\tthis.loadProviders();\n\t\t\t\tthis.updateList();\n\t\t\t\tthis.tui.requestRender();\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/provider-manager.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * TUI component for managing provider configurations.\n * Shows providers with auth status, discovery support, and model counts.\n */\n\nimport {\n\tContainer,\n\ttype Focusable,\n\tgetEditorKeybindings,\n\tSpacer,\n\tText,\n\ttype TUI,\n} from \"@gsd/pi-tui\";\nimport type { AuthStorage } from \"../../../core/auth-storage.js\";\nimport { getDiscoverableProviders } from \"../../../core/model-discovery.js\";\nimport type { ModelRegistry } from \"../../../core/model-registry.js\";\nimport { ModelsJsonWriter } from \"../../../core/models-json-writer.js\";\nimport { theme } from \"../theme/theme.js\";\nimport { rawKeyHint } from \"./keybinding-hints.js\";\n\ninterface ProviderInfo {\n\tname: string;\n\thasAuth: boolean;\n\tsupportsDiscovery: boolean;\n\tmodelCount: number;\n}\n\nexport class ProviderManagerComponent extends Container implements Focusable {\n\tprivate _focused = false;\n\tget focused(): boolean {\n\t\treturn this._focused;\n\t}\n\tset focused(value: boolean) {\n\t\tthis._focused = value;\n\t}\n\n\tprivate providers: ProviderInfo[] = [];\n\tprivate selectedIndex = 0;\n\tprivate listContainer: Container;\n\tprivate tui: TUI;\n\tprivate authStorage: AuthStorage;\n\tprivate modelRegistry: ModelRegistry;\n\tprivate modelsJsonWriter: ModelsJsonWriter;\n\tprivate onDone: () => void;\n\tprivate onDiscover: (provider: string) => void;\n\n\tconstructor(\n\t\ttui: TUI,\n\t\tauthStorage: AuthStorage,\n\t\tmodelRegistry: ModelRegistry,\n\t\tonDone: () => void,\n\t\tonDiscover: (provider: string) => void,\n\t) {\n\t\tsuper();\n\n\t\tthis.tui = tui;\n\t\tthis.authStorage = authStorage;\n\t\tthis.modelRegistry = modelRegistry;\n\t\tthis.modelsJsonWriter = new ModelsJsonWriter(this.modelRegistry.modelsJsonPath);\n\t\tthis.onDone = onDone;\n\t\tthis.onDiscover = onDiscover;\n\n\t\t// Header\n\t\tthis.addChild(new Text(theme.fg(\"accent\", \"Provider Manager\"), 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// Hints\n\t\tconst hints = [\n\t\t\trawKeyHint(\"d\", \"discover\"),\n\t\t\trawKeyHint(\"r\", \"remove\"),\n\t\t\trawKeyHint(\"esc\", \"close\"),\n\t\t].join(\" \");\n\t\tthis.addChild(new Text(hints, 0, 0));\n\t\tthis.addChild(new Spacer(1));\n\n\t\t// List\n\t\tthis.listContainer = new Container();\n\t\tthis.addChild(this.listContainer);\n\n\t\tthis.loadProviders();\n\t\tthis.updateList();\n\t}\n\n\tprivate loadProviders(): void {\n\t\tconst discoverableSet = new Set(getDiscoverableProviders());\n\t\tconst allModels = this.modelRegistry.getAll();\n\n\t\t// Group models by provider\n\t\tconst providerModelCounts = new Map<string, number>();\n\t\tfor (const model of allModels) {\n\t\t\tproviderModelCounts.set(model.provider, (providerModelCounts.get(model.provider) ?? 0) + 1);\n\t\t}\n\n\t\t// Build provider list from all known providers\n\t\tconst providerNames = new Set([\n\t\t\t...providerModelCounts.keys(),\n\t\t\t...discoverableSet,\n\t\t]);\n\n\t\tthis.providers = Array.from(providerNames)\n\t\t\t.sort()\n\t\t\t.map((name) => ({\n\t\t\t\tname,\n\t\t\t\thasAuth: this.authStorage.hasAuth(name),\n\t\t\t\tsupportsDiscovery: discoverableSet.has(name),\n\t\t\t\tmodelCount: providerModelCounts.get(name) ?? 0,\n\t\t\t}));\n\t\tthis.clampSelectedIndex();\n\t}\n\n\tprivate clampSelectedIndex(): void {\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.selectedIndex = 0;\n\t\t\treturn;\n\t\t}\n\t\tthis.selectedIndex = Math.min(this.selectedIndex, this.providers.length - 1);\n\t}\n\n\tprivate updateList(): void {\n\t\tthis.listContainer.clear();\n\n\t\tfor (let i = 0; i < this.providers.length; i++) {\n\t\t\tconst p = this.providers[i];\n\t\t\tconst isSelected = i === this.selectedIndex;\n\n\t\t\tconst authBadge = p.hasAuth ? theme.fg(\"success\", \"[auth]\") : theme.fg(\"muted\", \"[no auth]\");\n\t\t\tconst discoveryBadge = p.supportsDiscovery ? theme.fg(\"accent\", \"[discovery]\") : \"\";\n\t\t\tconst countBadge = theme.fg(\"muted\", `(${p.modelCount} models)`);\n\n\t\t\tconst prefix = isSelected ? theme.fg(\"accent\", \"> \") : \" \";\n\t\t\tconst nameText = isSelected ? theme.fg(\"accent\", p.name) : p.name;\n\n\t\t\tconst parts = [prefix, nameText, \" \", authBadge];\n\t\t\tif (discoveryBadge) parts.push(\" \", discoveryBadge);\n\t\t\tparts.push(\" \", countBadge);\n\n\t\t\tthis.listContainer.addChild(new Text(parts.join(\"\"), 0, 0));\n\t\t}\n\n\t\tif (this.providers.length === 0) {\n\t\t\tthis.listContainer.addChild(new Text(theme.fg(\"muted\", \" No providers configured\"), 0, 0));\n\t\t}\n\t}\n\n\thandleInput(keyData: string): void {\n\t\tconst kb = getEditorKeybindings();\n\n\t\tif (kb.matches(keyData, \"selectUp\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === 0 ? this.providers.length - 1 : this.selectedIndex - 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectDown\")) {\n\t\t\tif (this.providers.length === 0) return;\n\t\t\tthis.selectedIndex = this.selectedIndex === this.providers.length - 1 ? 0 : this.selectedIndex + 1;\n\t\t\tthis.updateList();\n\t\t\tthis.tui.requestRender();\n\t\t} else if (kb.matches(keyData, \"selectCancel\")) {\n\t\t\tthis.onDone();\n\t\t} else if (keyData === \"d\" || keyData === \"D\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider?.supportsDiscovery) {\n\t\t\t\tthis.onDiscover(provider.name);\n\t\t\t}\n\t\t} else if (keyData === \"r\" || keyData === \"R\") {\n\t\t\tconst provider = this.providers[this.selectedIndex];\n\t\t\tif (provider) {\n\t\t\t\tthis.authStorage.remove(provider.name);\n\t\t\t\tthis.modelsJsonWriter.removeProvider(provider.name);\n\t\t\t\tthis.modelRegistry.refresh();\n\t\t\t\tthis.loadProviders();\n\t\t\t\tthis.updateList();\n\t\t\t\tthis.tui.requestRender();\n\t\t\t}\n\t\t}\n\t}\n}\n"]}
|
|
@@ -235,7 +235,7 @@ export class ModelRegistry {
|
|
|
235
235
|
|
|
236
236
|
constructor(
|
|
237
237
|
readonly authStorage: AuthStorage,
|
|
238
|
-
|
|
238
|
+
readonly modelsJsonPath: string | undefined = join(getAgentDir(), "models.json"),
|
|
239
239
|
) {
|
|
240
240
|
this.discoveryCache = new ModelDiscoveryCache();
|
|
241
241
|
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
import type { AuthStorage } from "../../../core/auth-storage.js";
|
|
15
15
|
import { getDiscoverableProviders } from "../../../core/model-discovery.js";
|
|
16
16
|
import type { ModelRegistry } from "../../../core/model-registry.js";
|
|
17
|
+
import { ModelsJsonWriter } from "../../../core/models-json-writer.js";
|
|
17
18
|
import { theme } from "../theme/theme.js";
|
|
18
19
|
import { rawKeyHint } from "./keybinding-hints.js";
|
|
19
20
|
|
|
@@ -39,6 +40,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
|
|
|
39
40
|
private tui: TUI;
|
|
40
41
|
private authStorage: AuthStorage;
|
|
41
42
|
private modelRegistry: ModelRegistry;
|
|
43
|
+
private modelsJsonWriter: ModelsJsonWriter;
|
|
42
44
|
private onDone: () => void;
|
|
43
45
|
private onDiscover: (provider: string) => void;
|
|
44
46
|
|
|
@@ -54,6 +56,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
|
|
|
54
56
|
this.tui = tui;
|
|
55
57
|
this.authStorage = authStorage;
|
|
56
58
|
this.modelRegistry = modelRegistry;
|
|
59
|
+
this.modelsJsonWriter = new ModelsJsonWriter(this.modelRegistry.modelsJsonPath);
|
|
57
60
|
this.onDone = onDone;
|
|
58
61
|
this.onDiscover = onDiscover;
|
|
59
62
|
|
|
@@ -64,7 +67,7 @@ export class ProviderManagerComponent extends Container implements Focusable {
|
|
|
64
67
|
// Hints
|
|
65
68
|
const hints = [
|
|
66
69
|
rawKeyHint("d", "discover"),
|
|
67
|
-
rawKeyHint("r", "remove
|
|
70
|
+
rawKeyHint("r", "remove"),
|
|
68
71
|
rawKeyHint("esc", "close"),
|
|
69
72
|
].join(" ");
|
|
70
73
|
this.addChild(new Text(hints, 0, 0));
|
|
@@ -102,6 +105,15 @@ export class ProviderManagerComponent extends Container implements Focusable {
|
|
|
102
105
|
supportsDiscovery: discoverableSet.has(name),
|
|
103
106
|
modelCount: providerModelCounts.get(name) ?? 0,
|
|
104
107
|
}));
|
|
108
|
+
this.clampSelectedIndex();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
private clampSelectedIndex(): void {
|
|
112
|
+
if (this.providers.length === 0) {
|
|
113
|
+
this.selectedIndex = 0;
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.selectedIndex = Math.min(this.selectedIndex, this.providers.length - 1);
|
|
105
117
|
}
|
|
106
118
|
|
|
107
119
|
private updateList(): void {
|
|
@@ -152,8 +164,10 @@ export class ProviderManagerComponent extends Container implements Focusable {
|
|
|
152
164
|
}
|
|
153
165
|
} else if (keyData === "r" || keyData === "R") {
|
|
154
166
|
const provider = this.providers[this.selectedIndex];
|
|
155
|
-
if (provider
|
|
167
|
+
if (provider) {
|
|
156
168
|
this.authStorage.remove(provider.name);
|
|
169
|
+
this.modelsJsonWriter.removeProvider(provider.name);
|
|
170
|
+
this.modelRegistry.refresh();
|
|
157
171
|
this.loadProviders();
|
|
158
172
|
this.updateList();
|
|
159
173
|
this.tui.requestRender();
|
package/pkg/package.json
CHANGED
|
@@ -18,25 +18,6 @@ const { existsSync, statSync, readdirSync } = require('fs')
|
|
|
18
18
|
const { resolve, join } = require('path')
|
|
19
19
|
const { execSync } = require('child_process')
|
|
20
20
|
|
|
21
|
-
const root = resolve(__dirname, '..')
|
|
22
|
-
const packagesDir = join(root, 'packages')
|
|
23
|
-
|
|
24
|
-
// Skip if packages/ doesn't exist (published tarball / end-user install)
|
|
25
|
-
if (!existsSync(packagesDir)) process.exit(0)
|
|
26
|
-
|
|
27
|
-
// Skip in CI — the pipeline runs `npm run build` explicitly
|
|
28
|
-
if (process.env.CI === 'true' || process.env.CI === '1') process.exit(0)
|
|
29
|
-
|
|
30
|
-
// Workspace packages that need dist/index.js at runtime.
|
|
31
|
-
// Order matters: dependencies must build before dependents.
|
|
32
|
-
const WORKSPACE_PACKAGES = [
|
|
33
|
-
'native',
|
|
34
|
-
'pi-tui',
|
|
35
|
-
'pi-ai',
|
|
36
|
-
'pi-agent-core',
|
|
37
|
-
'pi-coding-agent',
|
|
38
|
-
]
|
|
39
|
-
|
|
40
21
|
/**
|
|
41
22
|
* Returns the most recent mtime (ms) of any .ts file under dir, recursively.
|
|
42
23
|
* Returns 0 if no .ts files found.
|
|
@@ -56,31 +37,54 @@ function newestSrcMtime(dir) {
|
|
|
56
37
|
return newest
|
|
57
38
|
}
|
|
58
39
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
40
|
+
if (require.main === module) {
|
|
41
|
+
const root = resolve(__dirname, '..')
|
|
42
|
+
const packagesDir = join(root, 'packages')
|
|
43
|
+
|
|
44
|
+
// Skip if packages/ doesn't exist (published tarball / end-user install)
|
|
45
|
+
if (!existsSync(packagesDir)) process.exit(0)
|
|
46
|
+
|
|
47
|
+
// Skip in CI — the pipeline runs `npm run build` explicitly
|
|
48
|
+
if (process.env.CI === 'true' || process.env.CI === '1') process.exit(0)
|
|
49
|
+
|
|
50
|
+
// Workspace packages that need dist/index.js at runtime.
|
|
51
|
+
// Order matters: dependencies must build before dependents.
|
|
52
|
+
const WORKSPACE_PACKAGES = [
|
|
53
|
+
'native',
|
|
54
|
+
'pi-tui',
|
|
55
|
+
'pi-ai',
|
|
56
|
+
'pi-agent-core',
|
|
57
|
+
'pi-coding-agent',
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
const stale = []
|
|
61
|
+
for (const pkg of WORKSPACE_PACKAGES) {
|
|
62
|
+
const distIndex = join(packagesDir, pkg, 'dist', 'index.js')
|
|
63
|
+
if (!existsSync(distIndex)) {
|
|
64
|
+
stale.push(pkg)
|
|
65
|
+
continue
|
|
66
|
+
}
|
|
67
|
+
const distMtime = statSync(distIndex).mtimeMs
|
|
68
|
+
const srcMtime = newestSrcMtime(join(packagesDir, pkg, 'src'))
|
|
69
|
+
if (srcMtime > distMtime) {
|
|
70
|
+
stale.push(pkg)
|
|
71
|
+
}
|
|
70
72
|
}
|
|
71
|
-
}
|
|
72
73
|
|
|
73
|
-
if (stale.length === 0) process.exit(0)
|
|
74
|
+
if (stale.length === 0) process.exit(0)
|
|
74
75
|
|
|
75
|
-
process.stderr.write(` Building ${stale.length} workspace package(s) with stale or missing dist/: ${stale.join(', ')}\n`)
|
|
76
|
+
process.stderr.write(` Building ${stale.length} workspace package(s) with stale or missing dist/: ${stale.join(', ')}\n`)
|
|
76
77
|
|
|
77
|
-
for (const pkg of stale) {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
78
|
+
for (const pkg of stale) {
|
|
79
|
+
const pkgDir = join(packagesDir, pkg)
|
|
80
|
+
try {
|
|
81
|
+
execSync('npm run build', { cwd: pkgDir, stdio: 'pipe' })
|
|
82
|
+
process.stderr.write(` ✓ ${pkg}\n`)
|
|
83
|
+
} catch (err) {
|
|
84
|
+
process.stderr.write(` ✗ ${pkg} build failed: ${err.message}\n`)
|
|
85
|
+
// Non-fatal — the user can run `npm run build` manually
|
|
86
|
+
}
|
|
85
87
|
}
|
|
86
88
|
}
|
|
89
|
+
|
|
90
|
+
module.exports = { newestSrcMtime }
|
|
@@ -22,7 +22,7 @@ import {
|
|
|
22
22
|
loadManifest,
|
|
23
23
|
pruneDeadProcesses,
|
|
24
24
|
} from "./process-manager.js";
|
|
25
|
-
import { formatUptime, resolveBgShellPersistenceCwd } from "./utilities.js";
|
|
25
|
+
import { formatUptime, getBgShellLiveCwd, resolveBgShellPersistenceCwd } from "./utilities.js";
|
|
26
26
|
import { formatTokenCount } from "../shared/format-utils.js";
|
|
27
27
|
|
|
28
28
|
import type { BgShellSharedState } from "./index.js";
|
|
@@ -213,7 +213,7 @@ export function registerBgShellLifecycle(pi: ExtensionAPI, state: BgShellSharedS
|
|
|
213
213
|
return {
|
|
214
214
|
render(width: number): string[] {
|
|
215
215
|
// ── Line 1: pwd (branch) [session] ... bg status ──
|
|
216
|
-
let pwd =
|
|
216
|
+
let pwd = getBgShellLiveCwd(state.latestCtx?.cwd);
|
|
217
217
|
const home = process.env.HOME || process.env.USERPROFILE;
|
|
218
218
|
if (home && pwd.startsWith(home)) {
|
|
219
219
|
pwd = `~${pwd.slice(home.length)}`;
|
|
@@ -42,16 +42,51 @@ export function formatTimeAgo(timestamp: number): string {
|
|
|
42
42
|
return formatDuration(Date.now() - timestamp) + " ago";
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
function deriveProjectRootFromAutoWorktree(cachedCwd?: string): string | undefined {
|
|
46
|
+
if (!cachedCwd) return undefined;
|
|
47
|
+
const match = cachedCwd.match(/^(.*?)[\\/]\.gsd[\\/]worktrees[\\/][^\\/]+(?:[\\/].*)?$/);
|
|
48
|
+
return match?.[1];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function getBgShellLiveCwd(
|
|
52
|
+
cachedCwd?: string,
|
|
53
|
+
pathExists: (path: string) => boolean = existsSync,
|
|
54
|
+
getCwd: () => string = () => process.cwd(),
|
|
55
|
+
chdir: (path: string) => void = (path) => process.chdir(path),
|
|
56
|
+
): string {
|
|
57
|
+
try {
|
|
58
|
+
return getCwd();
|
|
59
|
+
} catch {
|
|
60
|
+
const projectRoot = deriveProjectRootFromAutoWorktree(cachedCwd);
|
|
61
|
+
const home = process.env.HOME || process.env.USERPROFILE;
|
|
62
|
+
const fallbacks = [projectRoot, cachedCwd, home, "/"].filter(
|
|
63
|
+
(candidate): candidate is string => Boolean(candidate),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
for (const candidate of fallbacks) {
|
|
67
|
+
if (candidate !== "/" && !pathExists(candidate)) continue;
|
|
68
|
+
try {
|
|
69
|
+
chdir(candidate);
|
|
70
|
+
} catch {
|
|
71
|
+
// Best-effort only. Returning a known-good fallback is enough to avoid crashes.
|
|
72
|
+
}
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return "/";
|
|
77
|
+
}
|
|
78
|
+
}
|
|
45
79
|
|
|
46
80
|
export function resolveBgShellPersistenceCwd(
|
|
47
81
|
cachedCwd: string,
|
|
48
|
-
liveCwd =
|
|
82
|
+
liveCwd: string | undefined = undefined,
|
|
49
83
|
pathExists: (path: string) => boolean = existsSync,
|
|
50
84
|
): string {
|
|
85
|
+
const resolvedLiveCwd = liveCwd ?? getBgShellLiveCwd(cachedCwd, pathExists);
|
|
51
86
|
const cachedIsAutoWorktree = /(?:^|[\\/])\.gsd[\\/]worktrees[\\/]/.test(cachedCwd);
|
|
52
87
|
if (!cachedIsAutoWorktree) return cachedCwd;
|
|
53
|
-
if (cachedCwd ===
|
|
54
|
-
if (!pathExists(cachedCwd)) return
|
|
55
|
-
if (
|
|
88
|
+
if (cachedCwd === resolvedLiveCwd && pathExists(cachedCwd)) return cachedCwd;
|
|
89
|
+
if (!pathExists(cachedCwd)) return resolvedLiveCwd;
|
|
90
|
+
if (resolvedLiveCwd !== cachedCwd) return resolvedLiveCwd;
|
|
56
91
|
return cachedCwd;
|
|
57
92
|
}
|
|
@@ -45,6 +45,17 @@ export function _resolveReportBasePath(s: Pick<AutoSession, "originalBasePath" |
|
|
|
45
45
|
return s.originalBasePath || s.basePath;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the authoritative project base for dispatch guards.
|
|
50
|
+
* Prior-milestone completion lives at the project root, even when the active
|
|
51
|
+
* unit is running inside an auto worktree.
|
|
52
|
+
*/
|
|
53
|
+
export function _resolveDispatchGuardBasePath(
|
|
54
|
+
s: Pick<AutoSession, "originalBasePath" | "basePath">,
|
|
55
|
+
): string {
|
|
56
|
+
return s.originalBasePath || s.basePath;
|
|
57
|
+
}
|
|
58
|
+
|
|
48
59
|
/**
|
|
49
60
|
* Generate and write an HTML milestone report snapshot.
|
|
50
61
|
* Extracted from the milestone-transition block in autoLoop.
|
|
@@ -667,9 +678,10 @@ export async function runDispatch(
|
|
|
667
678
|
prompt = preDispatchResult.prompt;
|
|
668
679
|
}
|
|
669
680
|
|
|
681
|
+
const guardBasePath = _resolveDispatchGuardBasePath(s);
|
|
670
682
|
const priorSliceBlocker = deps.getPriorSliceCompletionBlocker(
|
|
671
|
-
|
|
672
|
-
deps.getMainBranch(
|
|
683
|
+
guardBasePath,
|
|
684
|
+
deps.getMainBranch(guardBasePath),
|
|
673
685
|
unitType,
|
|
674
686
|
unitId,
|
|
675
687
|
);
|
|
@@ -707,8 +719,17 @@ export async function runGuards(
|
|
|
707
719
|
const budgetCeiling = prefs?.budget_ceiling;
|
|
708
720
|
if (budgetCeiling !== undefined && budgetCeiling > 0) {
|
|
709
721
|
const currentLedger = deps.getLedger() as { units: unknown } | null;
|
|
710
|
-
|
|
711
|
-
|
|
722
|
+
// In parallel worker mode, only count cost from the current auto-mode session
|
|
723
|
+
// to avoid hitting the ceiling due to historical project-wide spend (#2184).
|
|
724
|
+
let costUnits = currentLedger?.units;
|
|
725
|
+
if (process.env.GSD_PARALLEL_WORKER && s.autoStartTime && Array.isArray(costUnits)) {
|
|
726
|
+
const sessionStartISO = new Date(s.autoStartTime).toISOString();
|
|
727
|
+
costUnits = costUnits.filter(
|
|
728
|
+
(u: { startedAt?: string }) => u.startedAt != null && u.startedAt >= sessionStartISO,
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
const totalCost = costUnits
|
|
732
|
+
? deps.getProjectTotals(costUnits).cost
|
|
712
733
|
: 0;
|
|
713
734
|
const budgetPct = totalCost / budgetCeiling;
|
|
714
735
|
const budgetAlertLevel = deps.getBudgetAlertLevel(budgetPct);
|
|
@@ -200,7 +200,7 @@ export const DISPATCH_RULES: DispatchRule[] = [
|
|
|
200
200
|
uatContent ?? "",
|
|
201
201
|
basePath,
|
|
202
202
|
),
|
|
203
|
-
pauseAfterDispatch: uatType !== "artifact-driven" && uatType !== "browser-executable" && uatType !== "runtime-executable",
|
|
203
|
+
pauseAfterDispatch: !process.env.GSD_HEADLESS && uatType !== "artifact-driven" && uatType !== "browser-executable" && uatType !== "runtime-executable",
|
|
204
204
|
};
|
|
205
205
|
},
|
|
206
206
|
},
|
|
@@ -18,6 +18,26 @@ export interface ModelSelectionResult {
|
|
|
18
18
|
routing: { tier: string; modelDowngraded: boolean } | null;
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
export function resolvePreferredModelConfig(
|
|
22
|
+
unitType: string,
|
|
23
|
+
autoModeStartModel: { provider: string; id: string } | null,
|
|
24
|
+
) {
|
|
25
|
+
const explicitConfig = resolveModelWithFallbacksForUnit(unitType);
|
|
26
|
+
if (explicitConfig) return explicitConfig;
|
|
27
|
+
|
|
28
|
+
const routingConfig = resolveDynamicRoutingConfig();
|
|
29
|
+
if (!routingConfig.enabled || !routingConfig.tier_models) return undefined;
|
|
30
|
+
|
|
31
|
+
const ceilingModel = routingConfig.tier_models.heavy
|
|
32
|
+
?? (autoModeStartModel ? `${autoModeStartModel.provider}/${autoModeStartModel.id}` : undefined);
|
|
33
|
+
if (!ceilingModel) return undefined;
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
primary: ceilingModel,
|
|
37
|
+
fallbacks: [],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
21
41
|
/**
|
|
22
42
|
* Select and apply the appropriate model for a unit dispatch.
|
|
23
43
|
* Handles: per-unit-type model preferences, dynamic complexity routing,
|
|
@@ -36,7 +56,7 @@ export async function selectAndApplyModel(
|
|
|
36
56
|
autoModeStartModel: { provider: string; id: string } | null,
|
|
37
57
|
retryContext?: { isRetry: boolean; previousTier?: string },
|
|
38
58
|
): Promise<ModelSelectionResult> {
|
|
39
|
-
const modelConfig =
|
|
59
|
+
const modelConfig = resolvePreferredModelConfig(unitType, autoModeStartModel);
|
|
40
60
|
let routing: { tier: string; modelDowngraded: boolean } | null = null;
|
|
41
61
|
|
|
42
62
|
if (modelConfig) {
|
|
@@ -87,6 +87,11 @@ function buildSourceFilePaths(
|
|
|
87
87
|
paths.push(`- **Decisions**: \`${relGsdRootFile("DECISIONS")}\``);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
|
+
const queuePath = resolveGsdRootFile(base, "QUEUE");
|
|
91
|
+
if (existsSync(queuePath)) {
|
|
92
|
+
paths.push(`- **Queue**: \`${relGsdRootFile("QUEUE")}\``);
|
|
93
|
+
}
|
|
94
|
+
|
|
90
95
|
const contextPath = resolveMilestoneFile(base, mid, "CONTEXT");
|
|
91
96
|
if (contextPath) {
|
|
92
97
|
paths.push(`- **Milestone Context**: \`${relMilestoneFile(base, mid, "CONTEXT")}\``);
|
|
@@ -915,6 +920,16 @@ export async function buildPlanMilestonePrompt(mid: string, midTitle: string, ba
|
|
|
915
920
|
const decisionsInline = await inlineDecisionsFromDb(base, mid, undefined, inlineLevel);
|
|
916
921
|
if (decisionsInline) inlined.push(decisionsInline);
|
|
917
922
|
}
|
|
923
|
+
const queuePath = resolveGsdRootFile(base, "QUEUE");
|
|
924
|
+
if (existsSync(queuePath)) {
|
|
925
|
+
const queueInline = await inlineFileSmart(
|
|
926
|
+
queuePath,
|
|
927
|
+
relGsdRootFile("QUEUE"),
|
|
928
|
+
"Project Queue",
|
|
929
|
+
`${mid} ${midTitle}`,
|
|
930
|
+
);
|
|
931
|
+
inlined.push(queueInline);
|
|
932
|
+
}
|
|
918
933
|
const knowledgeInlinePM = await inlineGsdRootFile(base, "knowledge.md", "Project Knowledge");
|
|
919
934
|
if (knowledgeInlinePM) inlined.push(knowledgeInlinePM);
|
|
920
935
|
inlined.push(inlineTemplate("roadmap", "Roadmap"));
|
|
@@ -131,6 +131,15 @@ export async function bootstrapAutoSession(
|
|
|
131
131
|
return false;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
// Capture the user's session model before guided-flow dispatch can apply a
|
|
135
|
+
// phase-specific planning model for a discuss turn (#2829).
|
|
136
|
+
const startModelSnapshot = ctx.model
|
|
137
|
+
? {
|
|
138
|
+
provider: ctx.model.provider,
|
|
139
|
+
id: ctx.model.id,
|
|
140
|
+
}
|
|
141
|
+
: null;
|
|
142
|
+
|
|
134
143
|
try {
|
|
135
144
|
// Validate GSD_PROJECT_ID early so the user gets immediate feedback
|
|
136
145
|
const customProjectId = process.env.GSD_PROJECT_ID;
|
|
@@ -576,12 +585,11 @@ export async function bootstrapAutoSession(
|
|
|
576
585
|
// Initialize routing history
|
|
577
586
|
initRoutingHistory(s.basePath);
|
|
578
587
|
|
|
579
|
-
//
|
|
580
|
-
|
|
581
|
-
if (currentModel) {
|
|
588
|
+
// Restore the model that was active when auto bootstrap began (#650, #2829).
|
|
589
|
+
if (startModelSnapshot) {
|
|
582
590
|
s.autoModeStartModel = {
|
|
583
|
-
provider:
|
|
584
|
-
id:
|
|
591
|
+
provider: startModelSnapshot.provider,
|
|
592
|
+
id: startModelSnapshot.id,
|
|
585
593
|
};
|
|
586
594
|
}
|
|
587
595
|
|
|
@@ -65,6 +65,8 @@ import {
|
|
|
65
65
|
} from "./native-git-bridge.js";
|
|
66
66
|
|
|
67
67
|
const gsdHome = process.env.GSD_HOME || join(homedir(), ".gsd");
|
|
68
|
+
const PROJECT_PREFERENCES_FILE = "PREFERENCES.md";
|
|
69
|
+
const LEGACY_PROJECT_PREFERENCES_FILE = "preferences.md";
|
|
68
70
|
|
|
69
71
|
// ─── Shared Constants & Helpers ─────────────────────────────────────────────
|
|
70
72
|
|
|
@@ -82,7 +84,7 @@ const ROOT_STATE_FILES = [
|
|
|
82
84
|
"QUEUE.md",
|
|
83
85
|
"completed-units.json",
|
|
84
86
|
"metrics.json",
|
|
85
|
-
// NOTE: preferences
|
|
87
|
+
// NOTE: project preferences are intentionally NOT in ROOT_STATE_FILES.
|
|
86
88
|
// Forward-sync (main → worktree) is handled explicitly in syncGsdStateToWorktree().
|
|
87
89
|
// Back-sync (worktree → main) must NEVER overwrite the project root's copy
|
|
88
90
|
// because the project root is authoritative for preferences (#2684).
|
|
@@ -196,6 +198,11 @@ export function syncProjectRootToWorktree(
|
|
|
196
198
|
const prGsd = join(projectRoot, ".gsd");
|
|
197
199
|
const wtGsd = join(worktreePath_, ".gsd");
|
|
198
200
|
|
|
201
|
+
// When .gsd is a symlink to the same external directory in both locations,
|
|
202
|
+
// cpSync rejects the copy because source === destination (ERR_FS_CP_EINVAL).
|
|
203
|
+
// Compare realpaths and skip when they resolve to the same physical path (#2184).
|
|
204
|
+
if (isSamePath(prGsd, wtGsd)) return;
|
|
205
|
+
|
|
199
206
|
// Copy milestone directory from project root to worktree — additive only.
|
|
200
207
|
// force:false prevents cpSync from overwriting existing worktree files.
|
|
201
208
|
// Without this, worktree-authoritative files (e.g. VALIDATION.md written
|
|
@@ -245,6 +252,11 @@ export function syncStateToProjectRoot(
|
|
|
245
252
|
const wtGsd = join(worktreePath_, ".gsd");
|
|
246
253
|
const prGsd = join(projectRoot, ".gsd");
|
|
247
254
|
|
|
255
|
+
// When .gsd is a symlink to the same external directory in both locations,
|
|
256
|
+
// cpSync rejects the copy because source === destination (ERR_FS_CP_EINVAL).
|
|
257
|
+
// Compare realpaths and skip when they resolve to the same physical path (#2184).
|
|
258
|
+
if (isSamePath(wtGsd, prGsd)) return;
|
|
259
|
+
|
|
248
260
|
// 1. STATE.md — the quick-glance status used by initial deriveState()
|
|
249
261
|
safeCopy(join(wtGsd, "STATE.md"), join(prGsd, "STATE.md"), { force: true });
|
|
250
262
|
|
|
@@ -439,18 +451,25 @@ export function syncGsdStateToWorktree(
|
|
|
439
451
|
}
|
|
440
452
|
}
|
|
441
453
|
|
|
442
|
-
// Forward-sync preferences
|
|
443
|
-
//
|
|
444
|
-
//
|
|
454
|
+
// Forward-sync project preferences from project root to worktree (additive only).
|
|
455
|
+
// Prefer the canonical uppercase file name, but keep the legacy lowercase
|
|
456
|
+
// fallback so older repos still work on case-sensitive filesystems.
|
|
445
457
|
{
|
|
446
|
-
const
|
|
447
|
-
|
|
448
|
-
if (
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
458
|
+
const worktreeHasPreferences = existsSync(join(wtGsd, PROJECT_PREFERENCES_FILE))
|
|
459
|
+
|| existsSync(join(wtGsd, LEGACY_PROJECT_PREFERENCES_FILE));
|
|
460
|
+
if (!worktreeHasPreferences) {
|
|
461
|
+
for (const file of [PROJECT_PREFERENCES_FILE, LEGACY_PROJECT_PREFERENCES_FILE] as const) {
|
|
462
|
+
const src = join(mainGsd, file);
|
|
463
|
+
const dst = join(wtGsd, file);
|
|
464
|
+
if (existsSync(src)) {
|
|
465
|
+
try {
|
|
466
|
+
cpSync(src, dst);
|
|
467
|
+
synced.push(file);
|
|
468
|
+
} catch {
|
|
469
|
+
/* non-fatal */
|
|
470
|
+
}
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
454
473
|
}
|
|
455
474
|
}
|
|
456
475
|
}
|
|
@@ -985,11 +1004,25 @@ function copyPlanningArtifacts(srcBase: string, wtPath: string): void {
|
|
|
985
1004
|
"STATE.md",
|
|
986
1005
|
"KNOWLEDGE.md",
|
|
987
1006
|
"OVERRIDES.md",
|
|
988
|
-
"preferences.md",
|
|
989
1007
|
]) {
|
|
990
1008
|
safeCopy(join(srcGsd, file), join(dstGsd, file), { force: true });
|
|
991
1009
|
}
|
|
992
1010
|
|
|
1011
|
+
// Seed canonical PREFERENCES.md when available; fall back to legacy lowercase.
|
|
1012
|
+
if (existsSync(join(srcGsd, PROJECT_PREFERENCES_FILE))) {
|
|
1013
|
+
safeCopy(
|
|
1014
|
+
join(srcGsd, PROJECT_PREFERENCES_FILE),
|
|
1015
|
+
join(dstGsd, PROJECT_PREFERENCES_FILE),
|
|
1016
|
+
{ force: true },
|
|
1017
|
+
);
|
|
1018
|
+
} else if (existsSync(join(srcGsd, LEGACY_PROJECT_PREFERENCES_FILE))) {
|
|
1019
|
+
safeCopy(
|
|
1020
|
+
join(srcGsd, LEGACY_PROJECT_PREFERENCES_FILE),
|
|
1021
|
+
join(dstGsd, LEGACY_PROJECT_PREFERENCES_FILE),
|
|
1022
|
+
{ force: true },
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
|
|
993
1026
|
// Shared WAL (R012): worktrees use the project root's DB directly.
|
|
994
1027
|
// No longer copy gsd.db into the worktree — the DB path resolver in
|
|
995
1028
|
// ensureDbOpen() detects the worktree location and opens the root DB.
|
|
@@ -7,6 +7,7 @@ import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
|
7
7
|
import { isSessionSwitchInFlight, resolveAgentEnd } from "../auto-loop.js";
|
|
8
8
|
import { resolveModelId } from "../auto-model-selection.js";
|
|
9
9
|
import { clearDiscussionFlowState } from "./write-gate.js";
|
|
10
|
+
import { resumeAutoAfterProviderDelay } from "./provider-error-resume.js";
|
|
10
11
|
import {
|
|
11
12
|
classifyError,
|
|
12
13
|
createRetryState,
|
|
@@ -44,10 +45,10 @@ async function pauseTransientWithBackoff(
|
|
|
44
45
|
retryAfterMs,
|
|
45
46
|
resume: allowAutoResume
|
|
46
47
|
? () => {
|
|
47
|
-
pi.
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
48
|
+
void resumeAutoAfterProviderDelay(pi, ctx).catch((err) => {
|
|
49
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
50
|
+
ctx.ui.notify(`Provider error recovery delay elapsed, but auto-mode failed to resume: ${message}`, "error");
|
|
51
|
+
});
|
|
51
52
|
}
|
|
52
53
|
: undefined,
|
|
53
54
|
});
|