gsd-pi 2.73.0 → 2.73.1-dev.088d28f
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 +0 -47
- package/dist/help-text.js +1 -1
- package/dist/resource-loader.js +2 -2
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +9 -3
- package/dist/resources/extensions/gsd/auto/phases.js +15 -9
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -6
- package/dist/resources/extensions/gsd/auto-model-selection.js +54 -11
- package/dist/resources/extensions/gsd/auto-prompts.js +9 -6
- package/dist/resources/extensions/gsd/auto-start.js +23 -6
- package/dist/resources/extensions/gsd/auto.js +13 -1
- package/dist/resources/extensions/gsd/bootstrap/crash-log.js +31 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +8 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +51 -0
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/gsd-db.js +36 -2
- package/dist/resources/extensions/gsd/milestone-actions.js +19 -1
- package/dist/resources/extensions/gsd/notification-widget.js +2 -2
- package/dist/resources/extensions/gsd/preferences-models.js +43 -0
- package/dist/resources/extensions/gsd/preferences-types.js +1 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +22 -0
- package/dist/resources/extensions/gsd/state.js +36 -0
- package/dist/startup-model-validation.js +8 -5
- package/dist/update-check.d.ts +1 -0
- package/dist/update-check.js +13 -5
- package/dist/update-cmd.js +4 -3
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +12 -12
- 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/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- 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 +1 -1
- 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.js +2 -2
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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.js +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.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.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.js +2 -2
- 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.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.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.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.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.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.js +2 -2
- 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.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.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.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.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.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.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.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.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.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/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.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.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.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.js +2 -2
- 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.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.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.js +2 -2
- 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.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.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.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.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.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.js +2 -2
- 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.js +2 -2
- 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.js +2 -2
- 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.js +4 -4
- 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.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.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.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.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 +4 -4
- 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 +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-2f24283c162b6ab3.js → page-f2a7482d42a5614b.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-9ecfd95f343793f0.js → layout-a16c7a7ecdf0c2cf.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-f1e30ab6bb269149.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +1 -1
- package/package.json +1 -1
- package/packages/pi-ai/dist/index.d.ts +1 -0
- package/packages/pi-ai/dist/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/index.js +1 -0
- package/packages/pi-ai/dist/index.js.map +1 -1
- package/packages/pi-ai/dist/utils/overflow.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/overflow.js +12 -0
- package/packages/pi-ai/dist/utils/overflow.js.map +1 -1
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js +50 -0
- package/packages/pi-ai/dist/utils/tests/overflow.test.js.map +1 -0
- package/packages/pi-ai/src/index.ts +4 -0
- package/packages/pi-ai/src/utils/overflow.ts +14 -1
- package/packages/pi-ai/src/utils/tests/overflow.test.ts +58 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.js +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +27 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +313 -8
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/utils.js +5 -5
- package/packages/pi-coding-agent/dist/core/compaction/utils.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js +45 -0
- package/packages/pi-coding-agent/dist/core/compaction-utils.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +25 -68
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts +12 -2
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js +51 -26
- package/packages/pi-coding-agent/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts +2 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js +9 -3
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +52 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +116 -25
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +63 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +11 -3
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +38 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +1 -1
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +355 -8
- package/packages/pi-coding-agent/src/core/compaction/utils.ts +5 -5
- package/packages/pi-coding-agent/src/core/compaction-utils.test.ts +50 -0
- package/packages/pi-coding-agent/src/core/model-resolver.ts +26 -70
- package/packages/pi-coding-agent/src/modes/interactive/components/assistant-message.ts +62 -26
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +73 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.ts +9 -3
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +71 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +136 -30
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +11 -3
- package/packages/pi-tui/dist/__tests__/tui.test.js +60 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts +8 -0
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +32 -3
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/__tests__/tui.test.ts +76 -1
- package/packages/pi-tui/src/tui.ts +31 -3
- package/pkg/package.json +1 -1
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +12 -4
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +23 -2
- package/src/resources/extensions/gsd/auto/phases.ts +22 -9
- package/src/resources/extensions/gsd/auto-dispatch.ts +15 -4
- package/src/resources/extensions/gsd/auto-model-selection.ts +85 -11
- package/src/resources/extensions/gsd/auto-prompts.ts +9 -3
- package/src/resources/extensions/gsd/auto-start.ts +30 -6
- package/src/resources/extensions/gsd/auto.ts +10 -0
- package/src/resources/extensions/gsd/bootstrap/crash-log.ts +32 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +8 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +59 -0
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/gsd-db.ts +52 -2
- package/src/resources/extensions/gsd/milestone-actions.ts +19 -1
- package/src/resources/extensions/gsd/notification-widget.ts +2 -2
- package/src/resources/extensions/gsd/preferences-models.ts +41 -0
- package/src/resources/extensions/gsd/preferences-types.ts +12 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +23 -0
- package/src/resources/extensions/gsd/state.ts +46 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +51 -2
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +235 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +137 -1
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/model-isolation.test.ts +91 -2
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +267 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-7115e62689b5fd84.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +0 -1
- /package/dist/web/standalone/.next/static/{KSZ2dcC3p4z6lOmUpPpzr → nwYTvJZ1-hZIfw98d9Wfg}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{KSZ2dcC3p4z6lOmUpPpzr → nwYTvJZ1-hZIfw98d9Wfg}/_ssgManifest.js +0 -0
|
@@ -6,6 +6,7 @@ import { debugTime } from "../debug-logger.js";
|
|
|
6
6
|
import { loadPrompt, getTemplatesDir } from "../prompt-loader.js";
|
|
7
7
|
import { readForensicsMarker } from "../forensics.js";
|
|
8
8
|
import { resolveAllSkillReferences, renderPreferencesForSystemPrompt, loadEffectiveGSDPreferences } from "../preferences.js";
|
|
9
|
+
import { resolveModelWithFallbacksForUnit } from "../preferences-models.js";
|
|
9
10
|
import { resolveSkillReference } from "../preferences-skills.js";
|
|
10
11
|
import { resolveGsdRootFile, resolveSliceFile, resolveSlicePath, resolveTaskFile, resolveTaskFiles, resolveTasksDir, relSliceFile, relSlicePath, relTaskFile } from "../paths.js";
|
|
11
12
|
import { ensureCodebaseMapFresh, readCodebaseMap } from "../codebase-generator.js";
|
|
@@ -147,7 +148,11 @@ export async function buildBeforeAgentStartResult(event, ctx) {
|
|
|
147
148
|
// Re-inject forensics context on follow-up turns (#2941)
|
|
148
149
|
const forensicsInjection = !injection ? buildForensicsContextInjection(process.cwd(), event.prompt) : null;
|
|
149
150
|
const worktreeBlock = buildWorktreeContextBlock();
|
|
150
|
-
const
|
|
151
|
+
const subagentModelConfig = resolveModelWithFallbacksForUnit("subagent");
|
|
152
|
+
const subagentModelBlock = subagentModelConfig
|
|
153
|
+
? `\n\n## Subagent Model\n\nWhen spawning subagents via the \`subagent\` tool, always pass \`model: "${subagentModelConfig.primary}"\` in the tool call parameters. Never omit this — always specify it explicitly.`
|
|
154
|
+
: "";
|
|
155
|
+
const fullSystem = `${event.systemPrompt}\n\n[SYSTEM CONTEXT — GSD]\n\n${systemContent}${preferenceBlock}${knowledgeBlock}${codebaseBlock}${memoryBlock}${newSkillsBlock}${worktreeBlock}${subagentModelBlock}`;
|
|
151
156
|
stopContextTimer({
|
|
152
157
|
systemPromptSize: fullSystem.length,
|
|
153
158
|
injectionSize: injection?.length ?? forensicsInjection?.length ?? 0,
|
|
@@ -17,6 +17,11 @@ import { projectRoot } from "./commands/context.js";
|
|
|
17
17
|
import { loadPrompt } from "./prompt-loader.js";
|
|
18
18
|
const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/gsd-pi/latest";
|
|
19
19
|
const UPDATE_FETCH_TIMEOUT_MS = 5000;
|
|
20
|
+
function resolveInstallCommand(pkg) {
|
|
21
|
+
if ('bun' in process.versions)
|
|
22
|
+
return `bun add -g ${pkg}`;
|
|
23
|
+
return `npm install -g ${pkg}`;
|
|
24
|
+
}
|
|
20
25
|
async function fetchLatestVersionForCommand() {
|
|
21
26
|
const controller = new AbortController();
|
|
22
27
|
const timeout = setTimeout(() => controller.abort(), UPDATE_FETCH_TIMEOUT_MS);
|
|
@@ -344,13 +349,14 @@ export async function handleUpdate(ctx) {
|
|
|
344
349
|
return;
|
|
345
350
|
}
|
|
346
351
|
ctx.ui.notify(`Updating: v${current} → v${latest}...`, "info");
|
|
352
|
+
const installCmd = resolveInstallCommand(`${NPM_PACKAGE}@latest`);
|
|
347
353
|
try {
|
|
348
|
-
execSync(
|
|
354
|
+
execSync(installCmd, {
|
|
349
355
|
stdio: ["ignore", "pipe", "ignore"],
|
|
350
356
|
});
|
|
351
357
|
ctx.ui.notify(`Updated to v${latest}. Restart your GSD session to use the new version.`, "info");
|
|
352
358
|
}
|
|
353
359
|
catch {
|
|
354
|
-
ctx.ui.notify(`Update failed. Try manually:
|
|
360
|
+
ctx.ui.notify(`Update failed. Try manually: ${installCmd}`, "error");
|
|
355
361
|
}
|
|
356
362
|
}
|
|
@@ -14,6 +14,7 @@ import { join } from "node:path";
|
|
|
14
14
|
import { gsdRoot } from "./paths.js";
|
|
15
15
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
16
16
|
import { effectiveLockFile } from "./session-lock.js";
|
|
17
|
+
import { emitJournalEvent, queryJournal } from "./journal.js";
|
|
17
18
|
function lockPath(basePath) {
|
|
18
19
|
return join(gsdRoot(basePath), effectiveLockFile());
|
|
19
20
|
}
|
|
@@ -110,3 +111,53 @@ export function formatCrashInfo(lock) {
|
|
|
110
111
|
}
|
|
111
112
|
return lines.join("\n");
|
|
112
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Emit a synthetic unit-end event for a unit that crashed without emitting its own.
|
|
116
|
+
*
|
|
117
|
+
* Queries the journal to find the most recent unit-start for the crashed unit.
|
|
118
|
+
* If a matching unit-end already exists (e.g. the hard timeout fired), this is a
|
|
119
|
+
* no-op. Called during crash recovery, before clearing the stale lock.
|
|
120
|
+
*
|
|
121
|
+
* Addresses the gap reported in #3348 where `unit-start` was emitted but no
|
|
122
|
+
* `unit-end` followed — side effects landed but the worker died before closeout.
|
|
123
|
+
*/
|
|
124
|
+
export function emitCrashRecoveredUnitEnd(basePath, lock) {
|
|
125
|
+
// Skip bootstrap / starting pseudo-units — they have no meaningful unit-start event.
|
|
126
|
+
if (!lock.unitType || !lock.unitId || lock.unitType === "starting")
|
|
127
|
+
return;
|
|
128
|
+
try {
|
|
129
|
+
const all = queryJournal(basePath);
|
|
130
|
+
// Find the most recent unit-start for this unitId
|
|
131
|
+
const starts = all.filter((e) => e.eventType === "unit-start" && e.data?.unitId === lock.unitId);
|
|
132
|
+
if (starts.length === 0)
|
|
133
|
+
return;
|
|
134
|
+
const lastStart = starts[starts.length - 1];
|
|
135
|
+
// Check if a unit-end was already emitted (e.g. hard timeout fired after the crash)
|
|
136
|
+
const alreadyClosed = all.some((e) => e.eventType === "unit-end" &&
|
|
137
|
+
e.data?.unitId === lock.unitId &&
|
|
138
|
+
e.causedBy?.flowId === lastStart.flowId &&
|
|
139
|
+
e.causedBy?.seq === lastStart.seq);
|
|
140
|
+
if (alreadyClosed)
|
|
141
|
+
return;
|
|
142
|
+
// Find the highest seq in this flow for monotonic ordering
|
|
143
|
+
const maxSeq = all
|
|
144
|
+
.filter((e) => e.flowId === lastStart.flowId)
|
|
145
|
+
.reduce((max, e) => Math.max(max, e.seq), lastStart.seq);
|
|
146
|
+
emitJournalEvent(basePath, {
|
|
147
|
+
ts: new Date().toISOString(),
|
|
148
|
+
flowId: lastStart.flowId,
|
|
149
|
+
seq: maxSeq + 1,
|
|
150
|
+
eventType: "unit-end",
|
|
151
|
+
data: {
|
|
152
|
+
unitType: lock.unitType,
|
|
153
|
+
unitId: lock.unitId,
|
|
154
|
+
status: "crash-recovered",
|
|
155
|
+
artifactVerified: false,
|
|
156
|
+
},
|
|
157
|
+
causedBy: { flowId: lastStart.flowId, seq: lastStart.seq },
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Never throw from crash recovery path — journal failure must not block recovery
|
|
162
|
+
}
|
|
163
|
+
}
|
|
@@ -157,7 +157,7 @@ Setting `prefer_skills: []` does **not** disable skill discovery — it just mea
|
|
|
157
157
|
|
|
158
158
|
- `phases`: fine-grained control over which phases run. Usually set by `token_profile`, but can be overridden. Keys:
|
|
159
159
|
- `skip_research`: boolean — skip milestone-level research. Default: `false`.
|
|
160
|
-
- `reassess_after_slice`: boolean — run roadmap reassessment after each completed slice. Default: `
|
|
160
|
+
- `reassess_after_slice`: boolean — run roadmap reassessment after each completed slice. Default: `true`.
|
|
161
161
|
- `skip_reassess`: boolean — force-disable roadmap reassessment even if `reassess_after_slice` is enabled. Default: `false`.
|
|
162
162
|
- `skip_slice_research`: boolean — skip per-slice research. Default: `false`.
|
|
163
163
|
|
|
@@ -1352,6 +1352,25 @@ export function setSliceSummaryMd(milestoneId, sliceId, summaryMd, uatMd) {
|
|
|
1352
1352
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1353
1353
|
currentDb.prepare(`UPDATE slices SET full_summary_md = :summary_md, full_uat_md = :uat_md WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId, ":summary_md": summaryMd, ":uat_md": uatMd });
|
|
1354
1354
|
}
|
|
1355
|
+
function parseTaskArrayColumn(raw) {
|
|
1356
|
+
if (typeof raw !== "string" || raw.trim() === "")
|
|
1357
|
+
return [];
|
|
1358
|
+
try {
|
|
1359
|
+
const parsed = JSON.parse(raw);
|
|
1360
|
+
if (Array.isArray(parsed))
|
|
1361
|
+
return parsed.map((value) => String(value));
|
|
1362
|
+
if (parsed === null || parsed === undefined || parsed === "")
|
|
1363
|
+
return [];
|
|
1364
|
+
return [String(parsed)];
|
|
1365
|
+
}
|
|
1366
|
+
catch {
|
|
1367
|
+
// Older/corrupt rows may contain comma-separated strings instead of JSON.
|
|
1368
|
+
return raw
|
|
1369
|
+
.split(",")
|
|
1370
|
+
.map((value) => value.trim())
|
|
1371
|
+
.filter(Boolean);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1355
1374
|
function rowToTask(row) {
|
|
1356
1375
|
const parseTaskArray = (value) => {
|
|
1357
1376
|
if (Array.isArray(value)) {
|
|
@@ -1390,8 +1409,8 @@ function rowToTask(row) {
|
|
|
1390
1409
|
blocker_discovered: row["blocker_discovered"] === 1,
|
|
1391
1410
|
deviations: row["deviations"],
|
|
1392
1411
|
known_issues: row["known_issues"],
|
|
1393
|
-
key_files:
|
|
1394
|
-
key_decisions:
|
|
1412
|
+
key_files: parseTaskArrayColumn(row["key_files"]),
|
|
1413
|
+
key_decisions: parseTaskArrayColumn(row["key_decisions"]),
|
|
1395
1414
|
full_summary_md: row["full_summary_md"],
|
|
1396
1415
|
description: row["description"] ?? "",
|
|
1397
1416
|
estimate: row["estimate"] ?? "",
|
|
@@ -1855,6 +1874,21 @@ export function deleteSlice(milestoneId, sliceId) {
|
|
|
1855
1874
|
currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid AND id = :sid`).run({ ":mid": milestoneId, ":sid": sliceId });
|
|
1856
1875
|
});
|
|
1857
1876
|
}
|
|
1877
|
+
export function deleteMilestone(milestoneId) {
|
|
1878
|
+
if (!currentDb)
|
|
1879
|
+
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
1880
|
+
transaction(() => {
|
|
1881
|
+
currentDb.prepare(`DELETE FROM verification_evidence WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1882
|
+
currentDb.prepare(`DELETE FROM quality_gates WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1883
|
+
currentDb.prepare(`DELETE FROM tasks WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1884
|
+
currentDb.prepare(`DELETE FROM slice_dependencies WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1885
|
+
currentDb.prepare(`DELETE FROM slices WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1886
|
+
currentDb.prepare(`DELETE FROM replan_history WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1887
|
+
currentDb.prepare(`DELETE FROM assessments WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1888
|
+
currentDb.prepare(`DELETE FROM artifacts WHERE milestone_id = :mid`).run({ ":mid": milestoneId });
|
|
1889
|
+
currentDb.prepare(`DELETE FROM milestones WHERE id = :mid`).run({ ":mid": milestoneId });
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1858
1892
|
export function updateSliceFields(milestoneId, sliceId, fields) {
|
|
1859
1893
|
if (!currentDb)
|
|
1860
1894
|
throw new GSDError(GSD_STALE_STATE, "gsd-db: No database open");
|
|
@@ -15,7 +15,8 @@ import { join } from "node:path";
|
|
|
15
15
|
import { resolveMilestonePath, resolveMilestoneFile, buildMilestoneFileName, } from "./paths.js";
|
|
16
16
|
import { invalidateAllCaches } from "./cache.js";
|
|
17
17
|
import { loadQueueOrder, saveQueueOrder } from "./queue-order.js";
|
|
18
|
-
import { getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
18
|
+
import { deleteMilestone, getMilestone, isDbAvailable, updateMilestoneStatus } from "./gsd-db.js";
|
|
19
|
+
import { removeWorktree } from "./worktree-manager.js";
|
|
19
20
|
import { logWarning } from "./workflow-logger.js";
|
|
20
21
|
// ─── Park ──────────────────────────────────────────────────────────────────
|
|
21
22
|
/**
|
|
@@ -99,12 +100,29 @@ export function discardMilestone(basePath, milestoneId) {
|
|
|
99
100
|
const mDir = resolveMilestonePath(basePath, milestoneId);
|
|
100
101
|
if (!mDir || !existsSync(mDir))
|
|
101
102
|
return false;
|
|
103
|
+
try {
|
|
104
|
+
removeWorktree(basePath, milestoneId, {
|
|
105
|
+
branch: `milestone/${milestoneId}`,
|
|
106
|
+
deleteBranch: true,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
logWarning("engine", `discardMilestone worktree cleanup failed for ${milestoneId}: ${err.message}`);
|
|
111
|
+
}
|
|
102
112
|
rmSync(mDir, { recursive: true, force: true });
|
|
103
113
|
// Prune from queue order if present
|
|
104
114
|
const order = loadQueueOrder(basePath);
|
|
105
115
|
if (order && order.includes(milestoneId)) {
|
|
106
116
|
saveQueueOrder(basePath, order.filter(id => id !== milestoneId));
|
|
107
117
|
}
|
|
118
|
+
if (isDbAvailable()) {
|
|
119
|
+
try {
|
|
120
|
+
deleteMilestone(milestoneId);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
logWarning("engine", `discardMilestone DB cleanup failed for ${milestoneId}: ${err.message}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
108
126
|
invalidateAllCaches();
|
|
109
127
|
return true;
|
|
110
128
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// GSD Extension — Notification Widget
|
|
2
2
|
// Always-on ambient widget rendered belowEditor showing unread count and
|
|
3
|
-
// the most recent notification message. Refreshes every
|
|
3
|
+
// the most recent notification message. Refreshes every 30 seconds.
|
|
4
4
|
// Widget key: "gsd-notifications", placement: "belowEditor"
|
|
5
5
|
import { getUnreadCount, onNotificationStoreChange } from "./notification-store.js";
|
|
6
6
|
import { formattedShortcutPair } from "./shortcut-defs.js";
|
|
@@ -12,7 +12,7 @@ export function buildNotificationWidgetLines() {
|
|
|
12
12
|
return [` 🔔 Notifications: ${unread} unread (${formattedShortcutPair("notifications")})`];
|
|
13
13
|
}
|
|
14
14
|
// ─── Widget init ────────────────────────────────────────────────────────
|
|
15
|
-
const REFRESH_INTERVAL_MS =
|
|
15
|
+
const REFRESH_INTERVAL_MS = 30_000;
|
|
16
16
|
/**
|
|
17
17
|
* Initialize the always-on notification widget (belowEditor).
|
|
18
18
|
* Call once from session_start after the notification store is initialized.
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* and dynamic routing configuration.
|
|
7
7
|
*/
|
|
8
8
|
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
9
11
|
import { defaultRoutingConfig } from "./model-router.js";
|
|
10
12
|
import { loadEffectiveGSDPreferences, getGlobalGSDPreferencesPath } from "./preferences.js";
|
|
11
13
|
/**
|
|
@@ -161,6 +163,47 @@ export function resolveDefaultSessionModel(sessionProvider) {
|
|
|
161
163
|
}
|
|
162
164
|
return undefined;
|
|
163
165
|
}
|
|
166
|
+
/**
|
|
167
|
+
* Returns true if `provider` is defined as a custom provider in the user's
|
|
168
|
+
* `~/.gsd/agent/models.json` (Ollama, vLLM, LM Studio, OpenAI-compatible
|
|
169
|
+
* proxies, etc.).
|
|
170
|
+
*
|
|
171
|
+
* Used by auto-mode bootstrap to decide whether the session model
|
|
172
|
+
* (set via `/gsd model`) should override `PREFERENCES.md`. Custom providers
|
|
173
|
+
* are never reachable from `PREFERENCES.md` (which only knows built-in
|
|
174
|
+
* providers), so when the user has explicitly selected one, it must take
|
|
175
|
+
* priority — otherwise auto-mode tries to start the built-in provider from
|
|
176
|
+
* PREFERENCES.md and fails with "Not logged in · Please run /login" (#4122).
|
|
177
|
+
*
|
|
178
|
+
* Reads models.json directly with a lightweight JSON parse to avoid
|
|
179
|
+
* pulling in the full model-registry at this call site. Falls back to
|
|
180
|
+
* `~/.pi/agent/models.json` for parity with `resolveModelsJsonPath()`.
|
|
181
|
+
* Any read or parse error yields `false` (treat as not-custom) so a
|
|
182
|
+
* malformed models.json never breaks the session bootstrap.
|
|
183
|
+
*/
|
|
184
|
+
export function isCustomProvider(provider) {
|
|
185
|
+
if (!provider)
|
|
186
|
+
return false;
|
|
187
|
+
const candidates = [
|
|
188
|
+
join(homedir(), ".gsd", "agent", "models.json"),
|
|
189
|
+
join(homedir(), ".pi", "agent", "models.json"),
|
|
190
|
+
];
|
|
191
|
+
for (const path of candidates) {
|
|
192
|
+
if (!existsSync(path))
|
|
193
|
+
continue;
|
|
194
|
+
try {
|
|
195
|
+
const raw = readFileSync(path, "utf-8");
|
|
196
|
+
const parsed = JSON.parse(raw);
|
|
197
|
+
if (parsed?.providers && Object.prototype.hasOwnProperty.call(parsed.providers, provider)) {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
// Ignore — malformed models.json must not break bootstrap.
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
return false;
|
|
206
|
+
}
|
|
164
207
|
/**
|
|
165
208
|
* Determines the next fallback model to try when the current model fails.
|
|
166
209
|
* If the current model is not in the configured list, returns the primary model.
|
|
@@ -155,6 +155,28 @@ export function validatePreferences(preferences) {
|
|
|
155
155
|
errors.push(`search_provider must be one of: brave, tavily, ollama, native, auto`);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
|
+
// ─── Flat-rate Providers ────────────────────────────────────────────
|
|
159
|
+
// User-declared flat-rate providers for dynamic routing suppression.
|
|
160
|
+
// Built-in providers (github-copilot, copilot, claude-code) and any
|
|
161
|
+
// externalCli provider are already auto-detected; this list layers on
|
|
162
|
+
// top for private subscription proxies and custom CLI wrappers.
|
|
163
|
+
if (preferences.flat_rate_providers !== undefined) {
|
|
164
|
+
if (Array.isArray(preferences.flat_rate_providers)) {
|
|
165
|
+
const allStrings = preferences.flat_rate_providers.every((item) => typeof item === "string");
|
|
166
|
+
if (allStrings) {
|
|
167
|
+
// Strip empty/whitespace-only entries to avoid false matches.
|
|
168
|
+
validated.flat_rate_providers = preferences.flat_rate_providers
|
|
169
|
+
.map((s) => s.trim())
|
|
170
|
+
.filter((s) => s.length > 0);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
errors.push("flat_rate_providers must be an array of strings");
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
errors.push("flat_rate_providers must be an array of strings");
|
|
178
|
+
}
|
|
179
|
+
}
|
|
158
180
|
// ─── Phase Skip Preferences ─────────────────────────────────────────
|
|
159
181
|
if (preferences.phases !== undefined) {
|
|
160
182
|
if (typeof preferences.phases === "object" && preferences.phases !== null) {
|
|
@@ -516,6 +516,9 @@ function resolveSliceDependencies(activeMilestoneSlices) {
|
|
|
516
516
|
return { activeSlice: null, activeSliceRow: null };
|
|
517
517
|
}
|
|
518
518
|
}
|
|
519
|
+
// First pass: find a slice with ALL dependencies satisfied (strict)
|
|
520
|
+
let bestFallback = null;
|
|
521
|
+
let bestFallbackSatisfied = -1;
|
|
519
522
|
for (const s of activeMilestoneSlices) {
|
|
520
523
|
if (isStatusDone(s.status))
|
|
521
524
|
continue;
|
|
@@ -524,6 +527,23 @@ function resolveSliceDependencies(activeMilestoneSlices) {
|
|
|
524
527
|
if (s.depends.every(dep => doneSliceIds.has(dep))) {
|
|
525
528
|
return { activeSlice: { id: s.id, title: s.title }, activeSliceRow: s };
|
|
526
529
|
}
|
|
530
|
+
// Track the slice with the most satisfied dependencies as fallback
|
|
531
|
+
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
532
|
+
if (satisfied > bestFallbackSatisfied || (satisfied === bestFallbackSatisfied && !bestFallback)) {
|
|
533
|
+
bestFallback = s;
|
|
534
|
+
bestFallbackSatisfied = satisfied;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
// Fallback: if no slice has all deps met but there ARE incomplete non-deferred
|
|
538
|
+
// slices, pick the one with the most deps satisfied. This prevents hard-blocking
|
|
539
|
+
// when dependency metadata is stale (e.g. after reassessment added/removed slices)
|
|
540
|
+
// or when deps reference slices from previous milestones.
|
|
541
|
+
if (bestFallback) {
|
|
542
|
+
const unmet = bestFallback.depends.filter(dep => !doneSliceIds.has(dep));
|
|
543
|
+
logWarning("state", `No slice has all deps satisfied — falling back to ${bestFallback.id} ` +
|
|
544
|
+
`(${bestFallbackSatisfied}/${bestFallback.depends.length} deps met, ` +
|
|
545
|
+
`unmet: ${unmet.join(", ")})`, { mid: activeMilestoneSlices[0]?.milestone_id, sid: bestFallback.id });
|
|
546
|
+
return { activeSlice: { id: bestFallback.id, title: bestFallback.title }, activeSliceRow: bestFallback };
|
|
527
547
|
}
|
|
528
548
|
return { activeSlice: null, activeSliceRow: null };
|
|
529
549
|
}
|
|
@@ -1269,6 +1289,8 @@ export async function _deriveStateImpl(basePath) {
|
|
|
1269
1289
|
}
|
|
1270
1290
|
}
|
|
1271
1291
|
else {
|
|
1292
|
+
let bestFallbackLegacy = null;
|
|
1293
|
+
let bestFallbackLegacySatisfied = -1;
|
|
1272
1294
|
for (const s of activeRoadmap.slices) {
|
|
1273
1295
|
if (s.done)
|
|
1274
1296
|
continue;
|
|
@@ -1276,6 +1298,20 @@ export async function _deriveStateImpl(basePath) {
|
|
|
1276
1298
|
activeSlice = { id: s.id, title: s.title };
|
|
1277
1299
|
break;
|
|
1278
1300
|
}
|
|
1301
|
+
// Track best fallback
|
|
1302
|
+
const satisfied = s.depends.filter(dep => doneSliceIds.has(dep)).length;
|
|
1303
|
+
if (satisfied > bestFallbackLegacySatisfied) {
|
|
1304
|
+
bestFallbackLegacy = s;
|
|
1305
|
+
bestFallbackLegacySatisfied = satisfied;
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
// Fallback: if no slice has all deps met, pick the one with the most deps satisfied
|
|
1309
|
+
if (!activeSlice && bestFallbackLegacy) {
|
|
1310
|
+
const unmet = bestFallbackLegacy.depends.filter(dep => !doneSliceIds.has(dep));
|
|
1311
|
+
logWarning("state", `No slice has all deps satisfied — falling back to ${bestFallbackLegacy.id} ` +
|
|
1312
|
+
`(${bestFallbackLegacySatisfied}/${bestFallbackLegacy.depends.length} deps met, ` +
|
|
1313
|
+
`unmet: ${unmet.join(", ")})`);
|
|
1314
|
+
activeSlice = { id: bestFallbackLegacy.id, title: bestFallbackLegacy.title };
|
|
1279
1315
|
}
|
|
1280
1316
|
}
|
|
1281
1317
|
if (!activeSlice) {
|
|
@@ -34,15 +34,18 @@ export function validateConfiguredModel(modelRegistry, settingsManager) {
|
|
|
34
34
|
if (!configuredModel || !configuredExists) {
|
|
35
35
|
// Model not configured at all, or removed from registry — pick a fallback.
|
|
36
36
|
// Only fires when the model is genuinely unknown (not just temporarily unavailable).
|
|
37
|
+
//
|
|
38
|
+
// Model-agnostic selection order:
|
|
39
|
+
// 1. Pi migration default (preserves migration from ~/.pi install)
|
|
40
|
+
// 2. Any model from the user's previously-chosen provider (provider stickiness)
|
|
41
|
+
// 3. First available model in registry order (user-controlled via models.json)
|
|
37
42
|
const piDefault = getPiDefaultModelAndProvider();
|
|
38
43
|
const preferred = (piDefault
|
|
39
44
|
? availableModels.find((m) => m.provider === piDefault.provider && m.id === piDefault.model)
|
|
40
45
|
: undefined) ||
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
availableModels.find((m) => m.provider === 'anthropic' && m.id.includes('opus')) ||
|
|
45
|
-
availableModels.find((m) => m.provider === 'anthropic') ||
|
|
46
|
+
(configuredProvider
|
|
47
|
+
? availableModels.find((m) => m.provider === configuredProvider)
|
|
48
|
+
: undefined) ||
|
|
46
49
|
availableModels[0];
|
|
47
50
|
if (preferred) {
|
|
48
51
|
settingsManager.setDefaultModelAndProvider(preferred.provider, preferred.id);
|
package/dist/update-check.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export declare function compareSemver(a: string, b: string): number;
|
|
|
9
9
|
export declare function readUpdateCache(cachePath?: string): UpdateCheckCache | null;
|
|
10
10
|
export declare function writeUpdateCache(cache: UpdateCheckCache, cachePath?: string): void;
|
|
11
11
|
export declare function fetchLatestVersionFromRegistry(registryUrl?: string, fetchTimeoutMs?: number): Promise<string | null>;
|
|
12
|
+
export declare function resolveInstallCommand(pkg: string): string;
|
|
12
13
|
export interface UpdateCheckOptions {
|
|
13
14
|
currentVersion?: string;
|
|
14
15
|
cachePath?: string;
|
package/dist/update-check.js
CHANGED
|
@@ -66,9 +66,16 @@ export async function fetchLatestVersionFromRegistry(registryUrl = DEFAULT_REGIS
|
|
|
66
66
|
clearTimeout(timeout);
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
|
+
export function resolveInstallCommand(pkg) {
|
|
70
|
+
if ('bun' in process.versions) {
|
|
71
|
+
return `bun add -g ${pkg}`;
|
|
72
|
+
}
|
|
73
|
+
return `npm install -g ${pkg}`;
|
|
74
|
+
}
|
|
69
75
|
function printUpdateBanner(current, latest) {
|
|
76
|
+
const installCmd = resolveInstallCommand('gsd-pi');
|
|
70
77
|
process.stderr.write(` ${chalk.yellow('Update available:')} ${chalk.dim(`v${current}`)} → ${chalk.bold(`v${latest}`)}\n` +
|
|
71
|
-
` ${chalk.dim('Run')}
|
|
78
|
+
` ${chalk.dim('Run')} ${installCmd} ${chalk.dim('or')} /gsd update ${chalk.dim('to upgrade')}\n\n`);
|
|
72
79
|
}
|
|
73
80
|
/**
|
|
74
81
|
* Non-blocking update check. Queries npm registry at most once per 24h,
|
|
@@ -152,7 +159,7 @@ export async function checkAndPromptForUpdates(options = {}) {
|
|
|
152
159
|
const readline = await import('node:readline');
|
|
153
160
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
154
161
|
const choice = await new Promise((resolve) => {
|
|
155
|
-
process.stderr.write(` ${chalk.bold('[1]')} Update now ${chalk.dim(
|
|
162
|
+
process.stderr.write(` ${chalk.bold('[1]')} Update now ${chalk.dim(resolveInstallCommand(`${NPM_PACKAGE_NAME}@latest`))}\n` +
|
|
156
163
|
` ${chalk.bold('[2]')} Skip\n\n`);
|
|
157
164
|
// Default to skip if the user doesn't respond within PROMPT_TIMEOUT_MS
|
|
158
165
|
const timer = setTimeout(() => {
|
|
@@ -173,14 +180,15 @@ export async function checkAndPromptForUpdates(options = {}) {
|
|
|
173
180
|
process.stdin.setRawMode(false);
|
|
174
181
|
process.stdin.pause();
|
|
175
182
|
if (choice === '1') {
|
|
176
|
-
|
|
183
|
+
const installCmd = resolveInstallCommand(`${NPM_PACKAGE_NAME}@latest`);
|
|
184
|
+
process.stderr.write(`\n ${chalk.dim('Running:')} ${installCmd}\n\n`);
|
|
177
185
|
try {
|
|
178
|
-
execSync(
|
|
186
|
+
execSync(installCmd, { stdio: 'inherit' });
|
|
179
187
|
process.stderr.write(`\n ${chalk.green.bold(`✓ Updated to v${latestVersion}`)}\n\n`);
|
|
180
188
|
return true;
|
|
181
189
|
}
|
|
182
190
|
catch {
|
|
183
|
-
process.stderr.write(`\n ${chalk.yellow(`Update failed. You can run:
|
|
191
|
+
process.stderr.write(`\n ${chalk.yellow(`Update failed. You can run: ${installCmd}`)}\n\n`);
|
|
184
192
|
}
|
|
185
193
|
}
|
|
186
194
|
else {
|
package/dist/update-cmd.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
|
-
import { compareSemver, fetchLatestVersionFromRegistry } from './update-check.js';
|
|
2
|
+
import { compareSemver, fetchLatestVersionFromRegistry, resolveInstallCommand } from './update-check.js';
|
|
3
3
|
const NPM_PACKAGE = 'gsd-pi';
|
|
4
4
|
export async function runUpdate() {
|
|
5
5
|
const current = process.env.GSD_VERSION || '0.0.0';
|
|
@@ -21,14 +21,15 @@ export async function runUpdate() {
|
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
process.stdout.write(`${dim}Updating:${reset} v${current} → ${bold}v${latest}${reset}\n`);
|
|
24
|
+
const installCmd = resolveInstallCommand(`${NPM_PACKAGE}@latest`);
|
|
24
25
|
try {
|
|
25
|
-
execSync(
|
|
26
|
+
execSync(installCmd, {
|
|
26
27
|
stdio: 'inherit',
|
|
27
28
|
});
|
|
28
29
|
process.stdout.write(`\n${green}${bold}Updated to v${latest}${reset}\n`);
|
|
29
30
|
}
|
|
30
31
|
catch {
|
|
31
|
-
process.stderr.write(`\n${yellow}Update failed. Try manually:
|
|
32
|
+
process.stderr.write(`\n${yellow}Update failed. Try manually: ${installCmd}${reset}\n`);
|
|
32
33
|
process.exit(1);
|
|
33
34
|
}
|
|
34
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
nwYTvJZ1-hZIfw98d9Wfg
|
|
@@ -1,46 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"/_not-found/page": "/_not-found",
|
|
3
3
|
"/_global-error/page": "/_global-error",
|
|
4
|
-
"/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
|
|
5
|
-
"/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
|
|
6
4
|
"/api/boot/route": "/api/boot",
|
|
5
|
+
"/api/bridge-terminal/input/route": "/api/bridge-terminal/input",
|
|
6
|
+
"/api/bridge-terminal/resize/route": "/api/bridge-terminal/resize",
|
|
7
7
|
"/api/bridge-terminal/stream/route": "/api/bridge-terminal/stream",
|
|
8
8
|
"/api/dev-mode/route": "/api/dev-mode",
|
|
9
|
-
"/api/cleanup/route": "/api/cleanup",
|
|
10
9
|
"/api/doctor/route": "/api/doctor",
|
|
11
10
|
"/api/captures/route": "/api/captures",
|
|
11
|
+
"/api/cleanup/route": "/api/cleanup",
|
|
12
12
|
"/api/export-data/route": "/api/export-data",
|
|
13
13
|
"/api/forensics/route": "/api/forensics",
|
|
14
14
|
"/api/browse-directories/route": "/api/browse-directories",
|
|
15
15
|
"/api/git/route": "/api/git",
|
|
16
|
-
"/api/hooks/route": "/api/hooks",
|
|
17
16
|
"/api/history/route": "/api/history",
|
|
17
|
+
"/api/hooks/route": "/api/hooks",
|
|
18
18
|
"/api/inspect/route": "/api/inspect",
|
|
19
19
|
"/api/knowledge/route": "/api/knowledge",
|
|
20
|
-
"/api/notifications/route": "/api/notifications",
|
|
21
20
|
"/api/live-state/route": "/api/live-state",
|
|
22
|
-
"/api/
|
|
21
|
+
"/api/notifications/route": "/api/notifications",
|
|
23
22
|
"/api/experimental/route": "/api/experimental",
|
|
24
|
-
"/api/
|
|
23
|
+
"/api/preferences/route": "/api/preferences",
|
|
25
24
|
"/api/recovery/route": "/api/recovery",
|
|
26
25
|
"/api/projects/route": "/api/projects",
|
|
26
|
+
"/api/onboarding/route": "/api/onboarding",
|
|
27
27
|
"/api/session/browser/route": "/api/session/browser",
|
|
28
28
|
"/api/session/command/route": "/api/session/command",
|
|
29
|
-
"/api/session/manage/route": "/api/session/manage",
|
|
30
|
-
"/api/settings-data/route": "/api/settings-data",
|
|
31
29
|
"/api/session/events/route": "/api/session/events",
|
|
30
|
+
"/api/settings-data/route": "/api/settings-data",
|
|
31
|
+
"/api/session/manage/route": "/api/session/manage",
|
|
32
32
|
"/api/shutdown/route": "/api/shutdown",
|
|
33
33
|
"/api/skill-health/route": "/api/skill-health",
|
|
34
34
|
"/api/steer/route": "/api/steer",
|
|
35
|
-
"/api/files/route": "/api/files",
|
|
36
35
|
"/api/terminal/input/route": "/api/terminal/input",
|
|
37
36
|
"/api/terminal/resize/route": "/api/terminal/resize",
|
|
38
|
-
"/api/terminal/sessions/route": "/api/terminal/sessions",
|
|
39
37
|
"/api/switch-root/route": "/api/switch-root",
|
|
38
|
+
"/api/terminal/sessions/route": "/api/terminal/sessions",
|
|
39
|
+
"/api/files/route": "/api/files",
|
|
40
40
|
"/api/terminal/stream/route": "/api/terminal/stream",
|
|
41
|
+
"/api/undo/route": "/api/undo",
|
|
41
42
|
"/api/terminal/upload/route": "/api/terminal/upload",
|
|
42
43
|
"/api/visualizer/route": "/api/visualizer",
|
|
43
|
-
"/api/undo/route": "/api/undo",
|
|
44
44
|
"/api/update/route": "/api/update",
|
|
45
45
|
"/api/remote-questions/route": "/api/remote-questions",
|
|
46
46
|
"/page": "/"
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
],
|
|
5
5
|
"devFiles": [],
|
|
6
6
|
"lowPriorityFiles": [
|
|
7
|
-
"static/
|
|
8
|
-
"static/
|
|
7
|
+
"static/nwYTvJZ1-hZIfw98d9Wfg/_buildManifest.js",
|
|
8
|
+
"static/nwYTvJZ1-hZIfw98d9Wfg/_ssgManifest.js"
|
|
9
9
|
],
|
|
10
10
|
"rootMainFiles": [
|
|
11
11
|
"static/chunks/webpack-b868033a5834586d.js",
|
|
12
12
|
"static/chunks/4bd1b696-e356ca5ba0218e27.js",
|
|
13
13
|
"static/chunks/3794-42fdce068d44fa4f.js",
|
|
14
|
-
"static/chunks/main-app-
|
|
14
|
+
"static/chunks/main-app-fdab67f7802d7832.js"
|
|
15
15
|
],
|
|
16
16
|
"rootMainFilesTree": {},
|
|
17
17
|
"pages": {
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"dynamicRoutes": {},
|
|
79
79
|
"notFoundRoutes": [],
|
|
80
80
|
"preview": {
|
|
81
|
-
"previewModeId": "
|
|
82
|
-
"previewModeSigningKey": "
|
|
83
|
-
"previewModeEncryptionKey": "
|
|
81
|
+
"previewModeId": "0d74a2aa6b006dd14811b9bbf32d42fa",
|
|
82
|
+
"previewModeSigningKey": "fa0cfda94f65f8fe26fd9b9bf19d6ae1cdbda72e6b17afe5827bf8861b070f06",
|
|
83
|
+
"previewModeEncryptionKey": "4458972e6433066063f0a25222104d24b8524438fd03f72cc9ea192774799ae5"
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -104,7 +104,7 @@
|
|
|
104
104
|
"transform": "lodash/{{member}}"
|
|
105
105
|
}
|
|
106
106
|
},
|
|
107
|
-
"outputFileTracingRoot": "/
|
|
107
|
+
"outputFileTracingRoot": "/__w/gsd-2/gsd-2",
|
|
108
108
|
"cacheComponents": false,
|
|
109
109
|
"cacheLife": {
|
|
110
110
|
"default": {
|
|
@@ -308,11 +308,11 @@
|
|
|
308
308
|
"node-pty"
|
|
309
309
|
],
|
|
310
310
|
"turbopack": {
|
|
311
|
-
"root": "/
|
|
311
|
+
"root": "/__w/gsd-2/gsd-2"
|
|
312
312
|
},
|
|
313
313
|
"distDirRoot": ".next"
|
|
314
314
|
},
|
|
315
|
-
"appDir": "/
|
|
315
|
+
"appDir": "/__w/gsd-2/gsd-2/web",
|
|
316
316
|
"relativeAppDir": "web",
|
|
317
317
|
"files": [
|
|
318
318
|
".next/routes-manifest.json",
|