gsd-pi 2.72.0 → 2.73.0-dev.27730dc
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/README.md +12 -2
- package/dist/cli.js +59 -50
- package/dist/help-text.js +1 -1
- package/dist/onboarding.js +10 -0
- package/dist/resources/extensions/async-jobs/await-tool.js +7 -4
- package/dist/resources/extensions/async-jobs/job-manager.js +28 -3
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +40 -12
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +48 -23
- package/dist/resources/extensions/gsd/auto/loop.js +84 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +5 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +6 -0
- package/dist/resources/extensions/gsd/auto-prompts.js +9 -6
- package/dist/resources/extensions/gsd/auto-recovery.js +11 -0
- package/dist/resources/extensions/gsd/auto.js +30 -20
- 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/register-hooks.js +9 -11
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -1
- package/dist/resources/extensions/gsd/commands-handlers.js +4 -1
- package/dist/resources/extensions/gsd/context-injector.js +1 -1
- package/dist/resources/extensions/gsd/crash-recovery.js +51 -0
- package/dist/resources/extensions/gsd/custom-workflow-engine.js +3 -7
- package/dist/resources/extensions/gsd/definition-io.js +15 -0
- package/dist/resources/extensions/gsd/dispatch-guard.js +4 -0
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +6 -3
- package/dist/resources/extensions/gsd/git-service.js +11 -8
- package/dist/resources/extensions/gsd/gitignore.js +12 -6
- package/dist/resources/extensions/gsd/gsd-db.js +85 -8
- package/dist/resources/extensions/gsd/key-manager.js +2 -0
- package/dist/resources/extensions/gsd/milestone-actions.js +19 -1
- package/dist/resources/extensions/gsd/preferences-skills.js +2 -34
- package/dist/resources/extensions/gsd/preferences-types.js +15 -0
- package/dist/resources/extensions/gsd/preferences.js +16 -3
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +122 -13
- package/dist/resources/extensions/gsd/prompts/system.md +1 -1
- package/dist/resources/extensions/gsd/state.js +21 -1
- package/dist/resources/extensions/gsd/workflow-projections.js +7 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +30 -3
- package/dist/resources/extensions/gsd/write-intercept.js +10 -1
- package/dist/resources/extensions/ollama/index.js +4 -5
- package/dist/resources/extensions/ollama/ollama-client.js +35 -6
- package/dist/resources/extensions/ollama/ollama-discovery.js +32 -6
- package/dist/startup-model-validation.js +8 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- 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 +3 -3
- 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 +10 -10
- package/dist/web/standalone/.next/server/chunks/2331.js +16 -16
- package/dist/web/standalone/.next/server/chunks/4741.js +12 -12
- package/dist/web/standalone/.next/server/chunks/5822.js +2 -2
- package/dist/web/standalone/.next/server/chunks/63.js +8 -8
- package/dist/web/standalone/.next/server/chunks/6897.js +3 -3
- package/dist/web/standalone/.next/server/edge-runtime-webpack.js +2 -0
- package/dist/web/standalone/.next/server/functions-config-manifest.json +0 -9
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +29 -2
- package/dist/web/standalone/.next/server/middleware.js +4 -12
- 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/server/webpack-runtime.js +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/env-api-keys.js +1 -0
- package/packages/pi-ai/dist/env-api-keys.js.map +1 -1
- package/packages/pi-ai/dist/models.custom.d.ts +105 -0
- package/packages/pi-ai/dist/models.custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.custom.js +97 -0
- package/packages/pi-ai/dist/models.custom.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +648 -140
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +867 -370
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.d.ts +2 -0
- package/packages/pi-ai/dist/models.generated.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/models.generated.test.js +334 -0
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -0
- package/packages/pi-ai/dist/models.test.js +105 -0
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +1 -1
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +5 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +57 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/models.custom.ts +98 -0
- package/packages/pi-ai/src/models.generated.test.ts +373 -0
- package/packages/pi-ai/src/models.generated.ts +867 -370
- package/packages/pi-ai/src/models.test.ts +135 -0
- package/packages/pi-ai/src/types.ts +1 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +71 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +4 -1
- 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/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +25 -67
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +9 -0
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +87 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- 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 +22 -9
- 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/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/model-resolver.ts +26 -69
- package/packages/pi-coding-agent/src/core/sdk.ts +10 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +72 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +84 -12
- 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 +23 -9
- package/packages/pi-tui/dist/components/__tests__/editor.test.js +12 -0
- package/packages/pi-tui/dist/components/__tests__/editor.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +12 -0
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/keys.d.ts.map +1 -1
- package/packages/pi-tui/dist/keys.js +27 -0
- package/packages/pi-tui/dist/keys.js.map +1 -1
- package/packages/pi-tui/src/components/__tests__/editor.test.ts +18 -0
- package/packages/pi-tui/src/components/__tests__/input.test.ts +18 -0
- package/packages/pi-tui/src/keys.ts +32 -0
- package/pkg/package.json +1 -1
- package/src/resources/extensions/async-jobs/await-tool.test.ts +40 -7
- package/src/resources/extensions/async-jobs/await-tool.ts +7 -4
- package/src/resources/extensions/async-jobs/job-manager.ts +33 -3
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +45 -12
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +49 -24
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +91 -2
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +112 -0
- package/src/resources/extensions/gsd/auto/loop.ts +89 -1
- package/src/resources/extensions/gsd/auto-dispatch.ts +5 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +7 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +9 -3
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -0
- package/src/resources/extensions/gsd/auto.ts +30 -20
- 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/register-hooks.ts +8 -10
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -1
- package/src/resources/extensions/gsd/commands-handlers.ts +5 -1
- package/src/resources/extensions/gsd/context-injector.ts +1 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +59 -0
- package/src/resources/extensions/gsd/custom-workflow-engine.ts +4 -8
- package/src/resources/extensions/gsd/definition-io.ts +18 -0
- package/src/resources/extensions/gsd/dispatch-guard.ts +5 -0
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +6 -3
- package/src/resources/extensions/gsd/git-service.ts +11 -8
- package/src/resources/extensions/gsd/gitignore.ts +12 -6
- package/src/resources/extensions/gsd/gsd-db.ts +106 -8
- package/src/resources/extensions/gsd/key-manager.ts +2 -0
- package/src/resources/extensions/gsd/milestone-actions.ts +19 -1
- package/src/resources/extensions/gsd/preferences-skills.ts +2 -36
- package/src/resources/extensions/gsd/preferences-types.ts +16 -0
- package/src/resources/extensions/gsd/preferences.ts +19 -6
- package/src/resources/extensions/gsd/prompt-loader.ts +6 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +122 -13
- package/src/resources/extensions/gsd/prompts/system.md +1 -1
- package/src/resources/extensions/gsd/state.ts +20 -0
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/block-db-writes.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +235 -0
- package/src/resources/extensions/gsd/tests/definition-io.test.ts +57 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/doctor-heal-fixable-warnings.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/false-degraded-mode-warning.test.ts +104 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +165 -5
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +8 -6
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/plan-milestone-artifact-verification.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/preferences-formatting.test.ts +87 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +53 -0
- package/src/resources/extensions/gsd/tests/projection-regression.test.ts +96 -1
- package/src/resources/extensions/gsd/tests/prompt-loader-working-directory.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/register-hooks-depth-verification.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +267 -0
- package/src/resources/extensions/gsd/workflow-projections.ts +8 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +29 -3
- package/src/resources/extensions/gsd/write-intercept.ts +10 -1
- package/src/resources/extensions/ollama/index.ts +4 -5
- package/src/resources/extensions/ollama/ollama-client.ts +35 -6
- package/src/resources/extensions/ollama/ollama-discovery.ts +37 -6
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +54 -0
- package/dist/resources/extensions/gsd/auto-observability.js +0 -54
- package/dist/resources/extensions/gsd/file-watcher.js +0 -80
- package/dist/resources/extensions/gsd/rtk-status.js +0 -43
- 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/src/resources/extensions/gsd/auto-observability.ts +0 -72
- package/src/resources/extensions/gsd/file-watcher.ts +0 -100
- package/src/resources/extensions/gsd/rtk-status.ts +0 -53
- /package/dist/web/standalone/.next/static/{Y0I7CjXJl-tWoV__KidV4 → jNiH700EcljeLnbQ2_RCv}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{Y0I7CjXJl-tWoV__KidV4 → jNiH700EcljeLnbQ2_RCv}/_ssgManifest.js +0 -0
|
@@ -24,6 +24,9 @@ const BLOCKED_PATTERNS: RegExp[] = [
|
|
|
24
24
|
/(^|[/\\])\.gsd[/\\]STATE\.md$/i,
|
|
25
25
|
// Also match resolved symlink paths under ~/.gsd/projects/ (Pitfall #6)
|
|
26
26
|
/(^|[/\\])\.gsd[/\\]projects[/\\][^/\\]+[/\\]STATE\.md$/i,
|
|
27
|
+
// gsd.db and WAL/SHM files — single-writer WAL connection managed by engine (#3625)
|
|
28
|
+
/(^|[/\\])\.gsd[/\\]gsd\.db(-wal|-shm)?$/i,
|
|
29
|
+
/(^|[/\\])\.gsd[/\\]projects[/\\][^/\\]+[/\\]gsd\.db(-wal|-shm)?$/i,
|
|
27
30
|
];
|
|
28
31
|
|
|
29
32
|
/**
|
|
@@ -41,6 +44,12 @@ const BASH_STATE_PATTERNS: RegExp[] = [
|
|
|
41
44
|
/\bsed\b.*-i.*STATE\.md/i,
|
|
42
45
|
// dd output to STATE.md
|
|
43
46
|
/\bdd\b.*of=\S*STATE\.md/i,
|
|
47
|
+
// Direct DB access via sqlite3/sql.js/better-sqlite3 targeting gsd.db (#3625)
|
|
48
|
+
/\b(sqlite3|sql\.js|better-sqlite3|node:sqlite)\b.*gsd\.db/i,
|
|
49
|
+
/\bgsd\.db\b.*\b(sqlite3|sql\.js|better-sqlite3)\b/i,
|
|
50
|
+
// Shell writes targeting gsd.db files
|
|
51
|
+
/[>|]+\s*\S*gsd\.db/i,
|
|
52
|
+
/\b(cp|mv|dd)\b.*gsd\.db/i,
|
|
44
53
|
];
|
|
45
54
|
|
|
46
55
|
/**
|
|
@@ -81,7 +90,7 @@ function matchesBlockedPattern(path: string): boolean {
|
|
|
81
90
|
* Error message returned when an agent attempts to directly write an authoritative .gsd/ state file.
|
|
82
91
|
* Directs the agent to use engine tool calls instead.
|
|
83
92
|
*/
|
|
84
|
-
export const BLOCKED_WRITE_ERROR = `Direct writes to .gsd/STATE.md are blocked. Use engine tool calls instead:
|
|
93
|
+
export const BLOCKED_WRITE_ERROR = `Direct writes to .gsd/STATE.md and .gsd/gsd.db are blocked. Use engine tool calls instead:
|
|
85
94
|
- To complete a task: call gsd_complete_task(milestone_id, slice_id, task_id, summary)
|
|
86
95
|
- To complete a slice: call gsd_complete_slice(milestone_id, slice_id, summary, uat_result)
|
|
87
96
|
- To save a decision: call gsd_save_decision(scope, decision, choice, rationale)
|
|
@@ -69,13 +69,12 @@ async function probeAndRegister(pi: ExtensionAPI): Promise<boolean> {
|
|
|
69
69
|
|
|
70
70
|
const baseUrl = client.getOllamaHost();
|
|
71
71
|
|
|
72
|
-
// Use authMode "apiKey"
|
|
73
|
-
//
|
|
74
|
-
//
|
|
75
|
-
// Authorization header so the dummy key is harmless.
|
|
72
|
+
// Use authMode "apiKey" (#3440). Local Ollama ignores the Authorization header,
|
|
73
|
+
// so the "ollama" fallback is harmless. For cloud endpoints (OLLAMA_HOST pointing
|
|
74
|
+
// to ollama.com or a remote instance), OLLAMA_API_KEY is picked up here.
|
|
76
75
|
pi.registerProvider("ollama", {
|
|
77
76
|
authMode: "apiKey",
|
|
78
|
-
apiKey: "ollama",
|
|
77
|
+
apiKey: process.env.OLLAMA_API_KEY ?? "ollama",
|
|
79
78
|
baseUrl,
|
|
80
79
|
api: "ollama-chat",
|
|
81
80
|
streamSimple: streamOllamaChat,
|
|
@@ -34,11 +34,34 @@ export function getOllamaHost(): string {
|
|
|
34
34
|
return `http://${host}`;
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
/**
|
|
38
|
+
* Get auth headers for Ollama API requests.
|
|
39
|
+
* For cloud endpoints (OLLAMA_HOST pointing to ollama.com or remote instances),
|
|
40
|
+
* OLLAMA_API_KEY is used as a Bearer token. Local Ollama ignores the header.
|
|
41
|
+
*/
|
|
42
|
+
function getAuthHeaders(): Record<string, string> {
|
|
43
|
+
const apiKey = process.env.OLLAMA_API_KEY;
|
|
44
|
+
if (!apiKey) return {};
|
|
45
|
+
return { Authorization: `Bearer ${apiKey}` };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Merge auth headers into request options.
|
|
50
|
+
*/
|
|
51
|
+
function withAuth(options: RequestInit = {}): RequestInit {
|
|
52
|
+
const authHeaders = getAuthHeaders();
|
|
53
|
+
if (Object.keys(authHeaders).length === 0) return options;
|
|
54
|
+
return {
|
|
55
|
+
...options,
|
|
56
|
+
headers: { ...authHeaders, ...(options.headers as Record<string, string> || {}) },
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
37
60
|
async function fetchWithTimeout(url: string, options: RequestInit = {}, timeoutMs = REQUEST_TIMEOUT_MS): Promise<Response> {
|
|
38
61
|
const controller = new AbortController();
|
|
39
62
|
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
40
63
|
try {
|
|
41
|
-
return await fetch(url, { ...options, signal: controller.signal });
|
|
64
|
+
return await fetch(url, withAuth({ ...options, signal: controller.signal }));
|
|
42
65
|
} finally {
|
|
43
66
|
clearTimeout(timeout);
|
|
44
67
|
}
|
|
@@ -46,10 +69,16 @@ async function fetchWithTimeout(url: string, options: RequestInit = {}, timeoutM
|
|
|
46
69
|
|
|
47
70
|
/**
|
|
48
71
|
* Check if Ollama is running and reachable.
|
|
72
|
+
* For cloud endpoints (OLLAMA_HOST pointing to ollama.com), uses /api/tags
|
|
73
|
+
* as the probe since the root endpoint may not be available.
|
|
49
74
|
*/
|
|
50
75
|
export async function isRunning(): Promise<boolean> {
|
|
51
76
|
try {
|
|
52
|
-
const
|
|
77
|
+
const host = getOllamaHost();
|
|
78
|
+
const isCloud = host.includes("ollama.com") || host.includes("cloud");
|
|
79
|
+
const probeUrl = isCloud ? `${host}/api/tags` : `${host}/`;
|
|
80
|
+
const timeout = isCloud ? REQUEST_TIMEOUT_MS : PROBE_TIMEOUT_MS;
|
|
81
|
+
const response = await fetchWithTimeout(probeUrl, isCloud ? { method: "GET" } : {}, timeout);
|
|
53
82
|
return response.ok;
|
|
54
83
|
} catch {
|
|
55
84
|
return false;
|
|
@@ -117,12 +146,12 @@ export async function pullModel(
|
|
|
117
146
|
onProgress?: (progress: OllamaPullProgress) => void,
|
|
118
147
|
signal?: AbortSignal,
|
|
119
148
|
): Promise<void> {
|
|
120
|
-
const response = await fetch(`${getOllamaHost()}/api/pull`, {
|
|
149
|
+
const response = await fetch(`${getOllamaHost()}/api/pull`, withAuth({
|
|
121
150
|
method: "POST",
|
|
122
151
|
headers: { "Content-Type": "application/json" },
|
|
123
152
|
body: JSON.stringify({ name, stream: true }),
|
|
124
153
|
signal,
|
|
125
|
-
});
|
|
154
|
+
}));
|
|
126
155
|
|
|
127
156
|
if (!response.ok) {
|
|
128
157
|
const text = await response.text();
|
|
@@ -146,12 +175,12 @@ export async function* chat(
|
|
|
146
175
|
request: OllamaChatRequest,
|
|
147
176
|
signal?: AbortSignal,
|
|
148
177
|
): AsyncGenerator<OllamaChatResponse> {
|
|
149
|
-
const response = await fetch(`${getOllamaHost()}/api/chat`, {
|
|
178
|
+
const response = await fetch(`${getOllamaHost()}/api/chat`, withAuth({
|
|
150
179
|
method: "POST",
|
|
151
180
|
headers: { "Content-Type": "application/json" },
|
|
152
181
|
body: JSON.stringify(request),
|
|
153
182
|
signal,
|
|
154
|
-
});
|
|
183
|
+
}));
|
|
155
184
|
|
|
156
185
|
if (!response.ok) {
|
|
157
186
|
const text = await response.text();
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* Returns models in the format expected by pi.registerProvider().
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import { listModels } from "./ollama-client.js";
|
|
11
|
+
import { listModels, showModel } from "./ollama-client.js";
|
|
12
12
|
import {
|
|
13
13
|
estimateContextFromParams,
|
|
14
14
|
formatModelSize,
|
|
@@ -17,6 +17,24 @@ import {
|
|
|
17
17
|
} from "./model-capabilities.js";
|
|
18
18
|
import type { OllamaChatOptions, OllamaModelInfo } from "./types.js";
|
|
19
19
|
|
|
20
|
+
/**
|
|
21
|
+
* Extract context window from /api/show model_info.
|
|
22
|
+
* Keys follow the pattern "{architecture}.context_length" (e.g. "llama.context_length").
|
|
23
|
+
*/
|
|
24
|
+
function extractContextFromModelInfo(modelInfo: Record<string, unknown>): number | undefined {
|
|
25
|
+
for (const [key, value] of Object.entries(modelInfo)) {
|
|
26
|
+
if (key.endsWith(".context_length") && typeof value === "number" && value > 0) {
|
|
27
|
+
return value;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
type ClientDeps = {
|
|
34
|
+
listModels: typeof listModels;
|
|
35
|
+
showModel: typeof showModel;
|
|
36
|
+
};
|
|
37
|
+
|
|
20
38
|
export interface DiscoveredOllamaModel {
|
|
21
39
|
id: string;
|
|
22
40
|
name: string;
|
|
@@ -35,13 +53,26 @@ export interface DiscoveredOllamaModel {
|
|
|
35
53
|
|
|
36
54
|
const ZERO_COST = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 };
|
|
37
55
|
|
|
38
|
-
function enrichModel(info: OllamaModelInfo): DiscoveredOllamaModel {
|
|
56
|
+
async function enrichModel(info: OllamaModelInfo, deps: ClientDeps): Promise<DiscoveredOllamaModel> {
|
|
39
57
|
const caps = getModelCapabilities(info.name);
|
|
40
58
|
const parameterSize = info.details?.parameter_size ?? "";
|
|
41
59
|
|
|
42
|
-
//
|
|
60
|
+
// /api/tags doesn't include context length; /api/show does via "{arch}.context_length" in model_info.
|
|
61
|
+
let showContextWindow: number | undefined;
|
|
62
|
+
if (caps.contextWindow === undefined) {
|
|
63
|
+
try {
|
|
64
|
+
const showData = await deps.showModel(info.name);
|
|
65
|
+
showContextWindow = extractContextFromModelInfo(showData.model_info);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
// non-fatal: fall through to estimate
|
|
68
|
+
if (process.env.GSD_DEBUG) console.warn(`[ollama] /api/show failed for ${info.name}:`, err instanceof Error ? err.message : String(err));
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Determine context window: known table > /api/show > estimate from param size > default
|
|
43
73
|
const contextWindow =
|
|
44
74
|
caps.contextWindow ??
|
|
75
|
+
showContextWindow ??
|
|
45
76
|
(parameterSize ? estimateContextFromParams(parameterSize) : 8192);
|
|
46
77
|
|
|
47
78
|
// Determine max tokens: known table > fraction of context > default
|
|
@@ -73,11 +104,11 @@ function enrichModel(info: OllamaModelInfo): DiscoveredOllamaModel {
|
|
|
73
104
|
/**
|
|
74
105
|
* Discover all locally available Ollama models with enriched capabilities.
|
|
75
106
|
*/
|
|
76
|
-
export async function discoverModels(): Promise<DiscoveredOllamaModel[]> {
|
|
77
|
-
const tags = await listModels();
|
|
107
|
+
export async function discoverModels(deps: ClientDeps = { listModels, showModel }): Promise<DiscoveredOllamaModel[]> {
|
|
108
|
+
const tags = await deps.listModels();
|
|
78
109
|
if (!tags.models || tags.models.length === 0) return [];
|
|
79
110
|
|
|
80
|
-
return tags.models.map(enrichModel);
|
|
111
|
+
return Promise.all(tags.models.map((m) => enrichModel(m, deps)));
|
|
81
112
|
}
|
|
82
113
|
|
|
83
114
|
/**
|
|
@@ -1 +1,55 @@
|
|
|
1
1
|
// GSD2 — Tests for Ollama model discovery and enrichment
|
|
2
|
+
import { describe, it } from "node:test";
|
|
3
|
+
import assert from "node:assert/strict";
|
|
4
|
+
import { discoverModels } from "../ollama-discovery.js";
|
|
5
|
+
import type { OllamaTagsResponse, OllamaShowResponse } from "../types.js";
|
|
6
|
+
|
|
7
|
+
const EMPTY_DETAILS = { parent_model: "", format: "", family: "", families: null, parameter_size: "", quantization_level: "" };
|
|
8
|
+
|
|
9
|
+
function modelStub(name: string, parameterSize = "") {
|
|
10
|
+
return { name, model: name, modified_at: "", size: 0, digest: "", details: { ...EMPTY_DETAILS, parameter_size: parameterSize } };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function tagsStub(name: string, parameterSize = ""): OllamaTagsResponse {
|
|
14
|
+
return { models: [modelStub(name, parameterSize)] };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function showStub(modelInfo: Record<string, unknown>): OllamaShowResponse {
|
|
18
|
+
return { modelfile: "", parameters: "", template: "", details: EMPTY_DETAILS, model_info: modelInfo };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
describe("discoverModels — context window resolution", () => {
|
|
22
|
+
it("uses known table context window without calling /api/show", async () => {
|
|
23
|
+
let showCalled = false;
|
|
24
|
+
const models = await discoverModels({
|
|
25
|
+
listModels: async () => tagsStub("llama3.2:latest", "3B"),
|
|
26
|
+
showModel: async () => { showCalled = true; throw new Error("should not be called"); },
|
|
27
|
+
});
|
|
28
|
+
assert.equal(models[0].contextWindow, 131072);
|
|
29
|
+
assert.equal(showCalled, false);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
it("uses context_length from /api/show model_info for unknown model", async () => {
|
|
33
|
+
const models = await discoverModels({
|
|
34
|
+
listModels: async () => tagsStub("gemini-3-flash-preview:latest"),
|
|
35
|
+
showModel: async () => showStub({ "gemini.context_length": 1048576 }),
|
|
36
|
+
});
|
|
37
|
+
assert.equal(models[0].contextWindow, 1048576);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it("falls back to 8192 when /api/show model_info has no context_length key", async () => {
|
|
41
|
+
const models = await discoverModels({
|
|
42
|
+
listModels: async () => tagsStub("unknown-model:latest"),
|
|
43
|
+
showModel: async () => showStub({}),
|
|
44
|
+
});
|
|
45
|
+
assert.equal(models[0].contextWindow, 8192);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("falls back to 8192 when /api/show throws", async () => {
|
|
49
|
+
const models = await discoverModels({
|
|
50
|
+
listModels: async () => tagsStub("unknown-model:latest"),
|
|
51
|
+
showModel: async () => { throw new Error("network error"); },
|
|
52
|
+
});
|
|
53
|
+
assert.equal(models[0].contextWindow, 8192);
|
|
54
|
+
});
|
|
55
|
+
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-dispatch observability checks for auto-mode units.
|
|
3
|
-
* Validates plan/summary file quality and builds repair instructions
|
|
4
|
-
* for the agent to fix gaps before proceeding with the unit.
|
|
5
|
-
*/
|
|
6
|
-
import { validatePlanBoundary, validateExecuteBoundary, validateCompleteBoundary, formatValidationIssues, } from "./observability-validator.js";
|
|
7
|
-
import { parseUnitId } from "./unit-id.js";
|
|
8
|
-
export async function collectObservabilityWarnings(ctx, basePath, unitType, unitId) {
|
|
9
|
-
// Hook units have custom artifacts — skip standard observability checks
|
|
10
|
-
if (unitType.startsWith("hook/"))
|
|
11
|
-
return [];
|
|
12
|
-
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
13
|
-
if (!mid || !sid)
|
|
14
|
-
return [];
|
|
15
|
-
let issues = [];
|
|
16
|
-
if (unitType === "plan-slice") {
|
|
17
|
-
issues = await validatePlanBoundary(basePath, mid, sid);
|
|
18
|
-
}
|
|
19
|
-
else if (unitType === "execute-task" && tid) {
|
|
20
|
-
issues = await validateExecuteBoundary(basePath, mid, sid, tid);
|
|
21
|
-
}
|
|
22
|
-
else if (unitType === "complete-slice") {
|
|
23
|
-
issues = await validateCompleteBoundary(basePath, mid, sid);
|
|
24
|
-
}
|
|
25
|
-
if (issues.length > 0) {
|
|
26
|
-
ctx.ui.notify(`Observability check (${unitType}) found ${issues.length} warning${issues.length === 1 ? "" : "s"}:\n${formatValidationIssues(issues)}`, "warning");
|
|
27
|
-
}
|
|
28
|
-
return issues;
|
|
29
|
-
}
|
|
30
|
-
export function buildObservabilityRepairBlock(issues) {
|
|
31
|
-
if (issues.length === 0)
|
|
32
|
-
return "";
|
|
33
|
-
const items = issues.map(issue => {
|
|
34
|
-
const fileName = issue.file.split("/").pop() || issue.file;
|
|
35
|
-
let line = `- **${fileName}**: ${issue.message}`;
|
|
36
|
-
if (issue.suggestion)
|
|
37
|
-
line += ` → ${issue.suggestion}`;
|
|
38
|
-
return line;
|
|
39
|
-
});
|
|
40
|
-
return [
|
|
41
|
-
"",
|
|
42
|
-
"---",
|
|
43
|
-
"",
|
|
44
|
-
"## Pre-flight: Observability gaps to fix FIRST",
|
|
45
|
-
"",
|
|
46
|
-
"The following issues were detected in plan/summary files for this unit.",
|
|
47
|
-
"**Read each flagged file, apply the fix described, then proceed with the unit.**",
|
|
48
|
-
"",
|
|
49
|
-
...items,
|
|
50
|
-
"",
|
|
51
|
-
"---",
|
|
52
|
-
"",
|
|
53
|
-
].join("\n");
|
|
54
|
-
}
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { relative } from "node:path";
|
|
2
|
-
let watcher = null;
|
|
3
|
-
let pending = new Map();
|
|
4
|
-
const EVENT_MAP = {
|
|
5
|
-
"settings.json": "settings-changed",
|
|
6
|
-
"auth.json": "auth-changed",
|
|
7
|
-
"models.json": "models-changed",
|
|
8
|
-
};
|
|
9
|
-
const EXTENSIONS_DIR = "extensions";
|
|
10
|
-
const IGNORED_PATTERNS = [
|
|
11
|
-
"**/sessions/**",
|
|
12
|
-
"**/*.tmp",
|
|
13
|
-
"**/*.swp",
|
|
14
|
-
"**/*~",
|
|
15
|
-
"**/.DS_Store",
|
|
16
|
-
];
|
|
17
|
-
const DEBOUNCE_MS = 300;
|
|
18
|
-
/**
|
|
19
|
-
* Start watching `agentDir` (e.g. `~/.gsd/agent/`) for config changes.
|
|
20
|
-
* Emits events on the supplied EventBus when watched files are modified.
|
|
21
|
-
*/
|
|
22
|
-
export async function startFileWatcher(agentDir, eventBus) {
|
|
23
|
-
if (watcher) {
|
|
24
|
-
await watcher.close();
|
|
25
|
-
}
|
|
26
|
-
const { watch } = await import("chokidar");
|
|
27
|
-
pending = new Map();
|
|
28
|
-
function debounceEmit(event) {
|
|
29
|
-
const existing = pending.get(event);
|
|
30
|
-
if (existing)
|
|
31
|
-
clearTimeout(existing);
|
|
32
|
-
pending.set(event, setTimeout(() => {
|
|
33
|
-
pending.delete(event);
|
|
34
|
-
eventBus.emit(event, { timestamp: Date.now() });
|
|
35
|
-
}, DEBOUNCE_MS));
|
|
36
|
-
}
|
|
37
|
-
function resolveEvent(filePath) {
|
|
38
|
-
const rel = relative(agentDir, filePath);
|
|
39
|
-
if (rel.startsWith(".."))
|
|
40
|
-
return null;
|
|
41
|
-
// Check direct file matches
|
|
42
|
-
for (const [file, event] of Object.entries(EVENT_MAP)) {
|
|
43
|
-
if (rel === file)
|
|
44
|
-
return event;
|
|
45
|
-
}
|
|
46
|
-
// Check extensions directory
|
|
47
|
-
if (rel.startsWith(EXTENSIONS_DIR + "/") || rel === EXTENSIONS_DIR) {
|
|
48
|
-
return "extensions-changed";
|
|
49
|
-
}
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
watcher = watch(agentDir, {
|
|
53
|
-
ignoreInitial: true,
|
|
54
|
-
depth: 2,
|
|
55
|
-
ignored: IGNORED_PATTERNS,
|
|
56
|
-
});
|
|
57
|
-
for (const eventType of ["add", "change", "unlink"]) {
|
|
58
|
-
watcher.on(eventType, (filePath) => {
|
|
59
|
-
const event = resolveEvent(filePath);
|
|
60
|
-
if (event)
|
|
61
|
-
debounceEmit(event);
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
// Wait for watcher to be ready
|
|
65
|
-
await new Promise((resolve) => {
|
|
66
|
-
watcher.on("ready", resolve);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
/**
|
|
70
|
-
* Stop the file watcher and clean up resources.
|
|
71
|
-
*/
|
|
72
|
-
export async function stopFileWatcher() {
|
|
73
|
-
for (const timer of pending.values())
|
|
74
|
-
clearTimeout(timer);
|
|
75
|
-
pending.clear();
|
|
76
|
-
if (watcher) {
|
|
77
|
-
await watcher.close();
|
|
78
|
-
watcher = null;
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
import { ensureRtkSessionBaseline, formatRtkSavingsLabel, getRtkSessionSavings, } from "../shared/rtk-session-stats.js";
|
|
2
|
-
import { loadEffectiveGSDPreferences } from "./preferences.js";
|
|
3
|
-
const STATUS_KEY = "gsd-rtk";
|
|
4
|
-
const REFRESH_INTERVAL_MS = 30_000;
|
|
5
|
-
let refreshTimer = null;
|
|
6
|
-
function clearTimer() {
|
|
7
|
-
if (refreshTimer) {
|
|
8
|
-
clearInterval(refreshTimer);
|
|
9
|
-
refreshTimer = null;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
function isRtkEnabledInPrefs() {
|
|
13
|
-
return loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
|
|
14
|
-
}
|
|
15
|
-
function updateStatus(ctx) {
|
|
16
|
-
if (!ctx.hasUI)
|
|
17
|
-
return;
|
|
18
|
-
if (!isRtkEnabledInPrefs())
|
|
19
|
-
return;
|
|
20
|
-
const basePath = ctx.cwd;
|
|
21
|
-
const sessionId = ctx.sessionManager.getSessionId();
|
|
22
|
-
ensureRtkSessionBaseline(basePath, sessionId);
|
|
23
|
-
const savings = getRtkSessionSavings(basePath, sessionId);
|
|
24
|
-
ctx.ui.setStatus(STATUS_KEY, formatRtkSavingsLabel(savings) ?? undefined);
|
|
25
|
-
}
|
|
26
|
-
export function startRtkStatusUpdates(ctx) {
|
|
27
|
-
clearTimer();
|
|
28
|
-
if (!isRtkEnabledInPrefs()) {
|
|
29
|
-
// Ensure any previously set status is cleared (e.g. preference was toggled off)
|
|
30
|
-
ctx.ui.setStatus(STATUS_KEY, undefined);
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
updateStatus(ctx);
|
|
34
|
-
if (!ctx.hasUI)
|
|
35
|
-
return;
|
|
36
|
-
refreshTimer = setInterval(() => {
|
|
37
|
-
updateStatus(ctx);
|
|
38
|
-
}, REFRESH_INTERVAL_MS);
|
|
39
|
-
}
|
|
40
|
-
export function stopRtkStatusUpdates(ctx) {
|
|
41
|
-
clearTimer();
|
|
42
|
-
ctx?.ui.setStatus(STATUS_KEY, undefined);
|
|
43
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[8974],{5214:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorage",{enumerable:!0,get:function(){return r.workAsyncStorageInstance}});let r=n(17828)},15726:(e,t,n)=>{Promise.resolve().then(n.bind(n,66919))},17828:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"workAsyncStorageInstance",{enumerable:!0,get:function(){return r}});let r=(0,n(64054).createAsyncLocalStorage)()},21957:(e,t,n)=>{"use strict";function r({moduleIds:e}){return null}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"PreloadChunks",{enumerable:!0,get:function(){return r}}),n(95155),n(47650),n(5214),n(2451),n(53887)},37206:(e,t,n)=>{"use strict";n.d(t,{default:()=>u.a});var r=n(75707),u=n.n(r)},41112:(e,t,n)=>{"use strict";function r({reason:e,children:t}){return t}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"BailoutToCSR",{enumerable:!0,get:function(){return r}}),n(1980)},64054:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={bindSnapshot:function(){return s},createAsyncLocalStorage:function(){return a},createSnapshot:function(){return i}};for(var r in n)Object.defineProperty(t,r,{enumerable:!0,get:n[r]});let u=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class l{disable(){throw u}getStore(){}run(){throw u}exit(){throw u}enterWith(){throw u}static bind(e){return e}}let o="u">typeof globalThis&&globalThis.AsyncLocalStorage;function a(){return o?new o:new l}function s(e){return o?o.bind(e):l.bind(e)}function i(){return o?o.snapshot():function(e,...t){return e(...t)}}},66919:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>l});var r=n(95155);let u=(0,n(37206).default)(()=>Promise.all([n.e(1838),n.e(6079),n.e(4986),n.e(2008),n.e(2826)]).then(n.bind(n,62826)).then(e=>e.GSDAppShell),{loadableGenerated:{webpack:()=>[62826]},ssr:!1,loading:()=>(0,r.jsx)("div",{className:"flex h-screen items-center justify-center bg-background text-sm text-muted-foreground",children:"Loading workspace…"})});function l(){return(0,r.jsx)(u,{})}},68635:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return s}});let r=n(95155),u=n(12115),l=n(41112);function o(e){return{default:e&&"default"in e?e.default:e}}n(21957);let a={loader:()=>Promise.resolve(o(()=>null)),loading:null,ssr:!0},s=function(e){let t={...a,...e},n=(0,u.lazy)(()=>t.loader().then(o)),s=t.loading;function i(e){let o=s?(0,r.jsx)(s,{isLoading:!0,pastDelay:!0,error:null}):null,a=!t.ssr||!!t.loading,i=a?u.Suspense:u.Fragment,c=t.ssr?(0,r.jsxs)(r.Fragment,{children:[null,(0,r.jsx)(n,{...e})]}):(0,r.jsx)(l.BailoutToCSR,{reason:"next/dynamic",children:(0,r.jsx)(n,{...e})});return(0,r.jsx)(i,{...a?{fallback:o}:{},children:c})}return i.displayName="LoadableComponent",i}},75707:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let r=n(73623)._(n(68635));function u(e,t){let n={};"function"==typeof e&&(n.loader=e);let u={...n,...t};return(0,r.default)({...u,modules:u.loadableGenerated?.modules})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=15726)),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[7358],{2852:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,27123,23)),Promise.resolve().then(n.t.bind(n,61304,23)),Promise.resolve().then(n.t.bind(n,78616,23)),Promise.resolve().then(n.t.bind(n,64777,23)),Promise.resolve().then(n.t.bind(n,57121,23)),Promise.resolve().then(n.t.bind(n,74581,23)),Promise.resolve().then(n.t.bind(n,90484,23)),Promise.resolve().then(n.bind(n,86869))},19393:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[8441,3794],()=>(s(83861),s(2852))),_N_E=e.O()}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[9337],{52560:(e,s,_)=>{Promise.resolve().then(_.t.bind(_,27123,23))}},e=>{e.O(0,[8441,3794,7358],()=>e(e.s=52560)),_N_E=e.O()}]);
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pre-dispatch observability checks for auto-mode units.
|
|
3
|
-
* Validates plan/summary file quality and builds repair instructions
|
|
4
|
-
* for the agent to fix gaps before proceeding with the unit.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import type { ExtensionContext } from "@gsd/pi-coding-agent";
|
|
8
|
-
import {
|
|
9
|
-
validatePlanBoundary,
|
|
10
|
-
validateExecuteBoundary,
|
|
11
|
-
validateCompleteBoundary,
|
|
12
|
-
formatValidationIssues,
|
|
13
|
-
} from "./observability-validator.js";
|
|
14
|
-
import type { ValidationIssue } from "./observability-validator.js";
|
|
15
|
-
import { parseUnitId } from "./unit-id.js";
|
|
16
|
-
|
|
17
|
-
export async function collectObservabilityWarnings(
|
|
18
|
-
ctx: ExtensionContext,
|
|
19
|
-
basePath: string,
|
|
20
|
-
unitType: string,
|
|
21
|
-
unitId: string,
|
|
22
|
-
): Promise<ValidationIssue[]> {
|
|
23
|
-
// Hook units have custom artifacts — skip standard observability checks
|
|
24
|
-
if (unitType.startsWith("hook/")) return [];
|
|
25
|
-
|
|
26
|
-
const { milestone: mid, slice: sid, task: tid } = parseUnitId(unitId);
|
|
27
|
-
|
|
28
|
-
if (!mid || !sid) return [];
|
|
29
|
-
|
|
30
|
-
let issues = [] as Awaited<ReturnType<typeof validatePlanBoundary>>;
|
|
31
|
-
|
|
32
|
-
if (unitType === "plan-slice") {
|
|
33
|
-
issues = await validatePlanBoundary(basePath, mid, sid);
|
|
34
|
-
} else if (unitType === "execute-task" && tid) {
|
|
35
|
-
issues = await validateExecuteBoundary(basePath, mid, sid, tid);
|
|
36
|
-
} else if (unitType === "complete-slice") {
|
|
37
|
-
issues = await validateCompleteBoundary(basePath, mid, sid);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (issues.length > 0) {
|
|
41
|
-
ctx.ui.notify(
|
|
42
|
-
`Observability check (${unitType}) found ${issues.length} warning${issues.length === 1 ? "" : "s"}:\n${formatValidationIssues(issues)}`,
|
|
43
|
-
"warning",
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return issues;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function buildObservabilityRepairBlock(issues: ValidationIssue[]): string {
|
|
51
|
-
if (issues.length === 0) return "";
|
|
52
|
-
const items = issues.map(issue => {
|
|
53
|
-
const fileName = issue.file.split("/").pop() || issue.file;
|
|
54
|
-
let line = `- **${fileName}**: ${issue.message}`;
|
|
55
|
-
if (issue.suggestion) line += ` → ${issue.suggestion}`;
|
|
56
|
-
return line;
|
|
57
|
-
});
|
|
58
|
-
return [
|
|
59
|
-
"",
|
|
60
|
-
"---",
|
|
61
|
-
"",
|
|
62
|
-
"## Pre-flight: Observability gaps to fix FIRST",
|
|
63
|
-
"",
|
|
64
|
-
"The following issues were detected in plan/summary files for this unit.",
|
|
65
|
-
"**Read each flagged file, apply the fix described, then proceed with the unit.**",
|
|
66
|
-
"",
|
|
67
|
-
...items,
|
|
68
|
-
"",
|
|
69
|
-
"---",
|
|
70
|
-
"",
|
|
71
|
-
].join("\n");
|
|
72
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import type { FSWatcher } from "chokidar";
|
|
2
|
-
import type { EventBus } from "@gsd/pi-coding-agent";
|
|
3
|
-
import { relative } from "node:path";
|
|
4
|
-
|
|
5
|
-
let watcher: FSWatcher | null = null;
|
|
6
|
-
let pending = new Map<string, ReturnType<typeof setTimeout>>();
|
|
7
|
-
|
|
8
|
-
const EVENT_MAP: Record<string, string> = {
|
|
9
|
-
"settings.json": "settings-changed",
|
|
10
|
-
"auth.json": "auth-changed",
|
|
11
|
-
"models.json": "models-changed",
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const EXTENSIONS_DIR = "extensions";
|
|
15
|
-
|
|
16
|
-
const IGNORED_PATTERNS = [
|
|
17
|
-
"**/sessions/**",
|
|
18
|
-
"**/*.tmp",
|
|
19
|
-
"**/*.swp",
|
|
20
|
-
"**/*~",
|
|
21
|
-
"**/.DS_Store",
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const DEBOUNCE_MS = 300;
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Start watching `agentDir` (e.g. `~/.gsd/agent/`) for config changes.
|
|
28
|
-
* Emits events on the supplied EventBus when watched files are modified.
|
|
29
|
-
*/
|
|
30
|
-
export async function startFileWatcher(
|
|
31
|
-
agentDir: string,
|
|
32
|
-
eventBus: EventBus,
|
|
33
|
-
): Promise<void> {
|
|
34
|
-
if (watcher) {
|
|
35
|
-
await watcher.close();
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
const { watch } = await import("chokidar");
|
|
39
|
-
|
|
40
|
-
pending = new Map<string, ReturnType<typeof setTimeout>>();
|
|
41
|
-
|
|
42
|
-
function debounceEmit(event: string): void {
|
|
43
|
-
const existing = pending.get(event);
|
|
44
|
-
if (existing) clearTimeout(existing);
|
|
45
|
-
pending.set(
|
|
46
|
-
event,
|
|
47
|
-
setTimeout(() => {
|
|
48
|
-
pending.delete(event);
|
|
49
|
-
eventBus.emit(event, { timestamp: Date.now() });
|
|
50
|
-
}, DEBOUNCE_MS),
|
|
51
|
-
);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function resolveEvent(filePath: string): string | null {
|
|
55
|
-
const rel = relative(agentDir, filePath);
|
|
56
|
-
if (rel.startsWith("..")) return null;
|
|
57
|
-
|
|
58
|
-
// Check direct file matches
|
|
59
|
-
for (const [file, event] of Object.entries(EVENT_MAP)) {
|
|
60
|
-
if (rel === file) return event;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Check extensions directory
|
|
64
|
-
if (rel.startsWith(EXTENSIONS_DIR + "/") || rel === EXTENSIONS_DIR) {
|
|
65
|
-
return "extensions-changed";
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
return null;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
watcher = watch(agentDir, {
|
|
72
|
-
ignoreInitial: true,
|
|
73
|
-
depth: 2,
|
|
74
|
-
ignored: IGNORED_PATTERNS,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
for (const eventType of ["add", "change", "unlink"] as const) {
|
|
78
|
-
watcher.on(eventType, (filePath: string) => {
|
|
79
|
-
const event = resolveEvent(filePath);
|
|
80
|
-
if (event) debounceEmit(event);
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// Wait for watcher to be ready
|
|
85
|
-
await new Promise<void>((resolve) => {
|
|
86
|
-
watcher!.on("ready", resolve);
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Stop the file watcher and clean up resources.
|
|
92
|
-
*/
|
|
93
|
-
export async function stopFileWatcher(): Promise<void> {
|
|
94
|
-
for (const timer of pending.values()) clearTimeout(timer);
|
|
95
|
-
pending.clear();
|
|
96
|
-
if (watcher) {
|
|
97
|
-
await watcher.close();
|
|
98
|
-
watcher = null;
|
|
99
|
-
}
|
|
100
|
-
}
|