gsd-pi 2.57.0 → 2.58.0-dev.778d6ac
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 +1 -1
- package/dist/cli.js +49 -35
- package/dist/headless-ui.d.ts +17 -0
- package/dist/headless-ui.js +97 -3
- package/dist/headless.js +67 -6
- package/dist/help-text.js +1 -0
- package/dist/onboarding.js +44 -0
- package/dist/resource-loader.js +16 -1
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/ask-user-questions.js +16 -3
- package/dist/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/dist/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/dist/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/dist/resources/extensions/claude-code-cli/partial-builder.js +14 -6
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +59 -36
- package/dist/resources/extensions/context7/extension-manifest.json +1 -1
- package/dist/resources/extensions/get-secrets-from-user.js +8 -5
- package/dist/resources/extensions/google-search/extension-manifest.json +1 -1
- package/dist/resources/extensions/google-search/index.js +2 -1
- package/dist/resources/extensions/gsd/auto/infra-errors.js +4 -0
- package/dist/resources/extensions/gsd/auto/phases.js +25 -21
- package/dist/resources/extensions/gsd/auto-artifact-paths.js +2 -2
- package/dist/resources/extensions/gsd/auto-dashboard.js +37 -20
- package/dist/resources/extensions/gsd/auto-dispatch.js +20 -5
- package/dist/resources/extensions/gsd/auto-model-selection.js +26 -3
- package/dist/resources/extensions/gsd/auto-post-unit.js +16 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +1 -1
- package/dist/resources/extensions/gsd/auto-recovery.js +13 -5
- package/dist/resources/extensions/gsd/auto-start.js +35 -22
- package/dist/resources/extensions/gsd/auto-worktree.js +203 -14
- package/dist/resources/extensions/gsd/auto.js +4 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +32 -0
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +82 -9
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +32 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +33 -18
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +44 -11
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +67 -0
- package/dist/resources/extensions/gsd/captures.js +56 -4
- package/dist/resources/extensions/gsd/db-writer.js +116 -8
- package/dist/resources/extensions/gsd/dispatch-guard.js +11 -1
- package/dist/resources/extensions/gsd/doctor-git-checks.js +28 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +2 -1
- package/dist/resources/extensions/gsd/doctor-runtime-checks.js +5 -4
- package/dist/resources/extensions/gsd/doctor.js +3 -1
- package/dist/resources/extensions/gsd/error-classifier.js +13 -10
- package/dist/resources/extensions/gsd/extension-manifest.json +16 -1
- package/dist/resources/extensions/gsd/forensics.js +123 -20
- package/dist/resources/extensions/gsd/git-service.js +23 -1
- package/dist/resources/extensions/gsd/gitignore.js +33 -0
- package/dist/resources/extensions/gsd/gsd-db.js +44 -10
- package/dist/resources/extensions/gsd/guided-flow.js +106 -44
- package/dist/resources/extensions/gsd/health-widget-core.js +31 -0
- package/dist/resources/extensions/gsd/health-widget.js +17 -0
- package/dist/resources/extensions/gsd/index.js +1 -1
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -0
- package/dist/resources/extensions/gsd/migrate-external.js +8 -1
- package/dist/resources/extensions/gsd/milestone-validation-gates.js +45 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +18 -0
- package/dist/resources/extensions/gsd/model-router.js +35 -1
- package/dist/resources/extensions/gsd/native-git-bridge.js +17 -0
- package/dist/resources/extensions/gsd/notifications.js +16 -1
- package/dist/resources/extensions/gsd/parallel-eligibility.js +13 -2
- package/dist/resources/extensions/gsd/parallel-merge.js +78 -5
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +23 -6
- package/dist/resources/extensions/gsd/parsers-legacy.js +20 -3
- package/dist/resources/extensions/gsd/paths.js +43 -0
- package/dist/resources/extensions/gsd/preferences-models.js +14 -1
- package/dist/resources/extensions/gsd/preferences-types.js +2 -1
- package/dist/resources/extensions/gsd/preferences.js +42 -31
- package/dist/resources/extensions/gsd/prompt-loader.js +4 -1
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/dist/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/dist/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/dist/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/dist/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/repo-identity.js +205 -11
- package/dist/resources/extensions/gsd/rethink.js +5 -0
- package/dist/resources/extensions/gsd/roadmap-slices.js +5 -4
- package/dist/resources/extensions/gsd/state.js +85 -27
- package/dist/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/dist/resources/extensions/gsd/tools/complete-task.js +34 -71
- package/dist/resources/extensions/gsd/tools/plan-milestone.js +12 -2
- package/dist/resources/extensions/gsd/tools/reassess-roadmap.js +29 -1
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +18 -3
- package/dist/resources/extensions/gsd/triage-resolution.js +22 -7
- package/dist/resources/extensions/gsd/undo.js +2 -2
- package/dist/resources/extensions/gsd/unit-ownership.js +164 -33
- package/dist/resources/extensions/gsd/verdict-parser.js +20 -8
- package/dist/resources/extensions/gsd/workflow-manifest.js +24 -5
- package/dist/resources/extensions/gsd/workflow-projections.js +95 -63
- package/dist/resources/extensions/gsd/workflow-reconcile.js +35 -5
- package/dist/resources/extensions/gsd/workspace-index.js +24 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +105 -1
- package/dist/resources/extensions/gsd/worktree-resolver.js +20 -3
- package/dist/resources/extensions/mcp-client/index.js +11 -7
- package/dist/resources/extensions/ollama/index.js +112 -0
- package/dist/resources/extensions/ollama/model-capabilities.js +115 -0
- package/dist/resources/extensions/ollama/ollama-client.js +168 -0
- package/dist/resources/extensions/ollama/ollama-commands.js +194 -0
- package/dist/resources/extensions/ollama/ollama-discovery.js +69 -0
- package/dist/resources/extensions/ollama/ollama-tool.js +184 -0
- package/dist/resources/extensions/ollama/types.js +2 -0
- package/dist/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/dist/resources/extensions/shared/interview-ui.js +11 -1
- package/dist/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/startup-model-validation.d.ts +39 -0
- package/dist/startup-model-validation.js +50 -0
- 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 +4 -4
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- 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 +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page.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 +4 -4
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +4 -4
- 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 +4 -4
- 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 +2 -2
- 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/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 +5 -5
- 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 +5 -5
- 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 +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- 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/2229.js +2 -2
- package/dist/web/standalone/.next/server/chunks/7471.js +3 -3
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/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 +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- 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-0c485498795110d6.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/.next/static/chunks/{webpack-4332cbd5dd1be584.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +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/dist/web-mode.js +2 -1
- package/package.json +2 -2
- package/packages/daemon/src/cli.ts +49 -0
- package/packages/daemon/src/daemon.test.ts +104 -1
- package/packages/daemon/src/daemon.ts +24 -1
- package/packages/daemon/src/discord-bot.ts +73 -3
- package/packages/daemon/src/event-bridge.ts +15 -9
- package/packages/daemon/src/event-formatter.ts +30 -2
- package/packages/daemon/src/index.ts +9 -0
- package/packages/daemon/src/launchd.test.ts +356 -0
- package/packages/daemon/src/launchd.ts +242 -0
- package/packages/daemon/src/message-batcher.test.ts +2 -2
- package/packages/daemon/src/message-batcher.ts +9 -3
- package/packages/daemon/src/orchestrator.test.ts +1 -0
- package/packages/daemon/src/orchestrator.ts +106 -2
- package/packages/native/dist/ast/index.js +9 -5
- package/packages/native/dist/ast/types.js +2 -1
- package/packages/native/dist/clipboard/index.js +12 -7
- package/packages/native/dist/clipboard/types.js +2 -1
- package/packages/native/dist/diff/index.js +12 -7
- package/packages/native/dist/diff/types.js +2 -1
- package/packages/native/dist/fd/index.js +6 -3
- package/packages/native/dist/fd/types.js +2 -1
- package/packages/native/dist/glob/index.js +9 -5
- package/packages/native/dist/glob/types.js +2 -1
- package/packages/native/dist/grep/index.js +9 -5
- package/packages/native/dist/grep/types.js +2 -1
- package/packages/native/dist/gsd-parser/index.js +18 -11
- package/packages/native/dist/gsd-parser/types.js +2 -1
- package/packages/native/dist/highlight/index.js +12 -7
- package/packages/native/dist/highlight/types.js +2 -1
- package/packages/native/dist/html/index.js +6 -3
- package/packages/native/dist/html/types.js +2 -1
- package/packages/native/dist/image/index.js +10 -5
- package/packages/native/dist/image/types.js +7 -4
- package/packages/native/dist/index.js +70 -17
- package/packages/native/dist/json-parse/index.js +13 -8
- package/packages/native/dist/native.js +47 -10
- package/packages/native/dist/ps/index.js +15 -9
- package/packages/native/dist/ps/types.js +2 -1
- package/packages/native/dist/stream-process/index.js +12 -7
- package/packages/native/dist/text/index.js +24 -14
- package/packages/native/dist/text/types.js +5 -2
- package/packages/native/dist/truncate/index.js +12 -7
- package/packages/native/dist/ttsr/index.js +12 -7
- package/packages/native/dist/ttsr/types.js +2 -1
- package/packages/native/dist/xxhash/index.js +9 -5
- package/packages/native/package.json +19 -19
- package/packages/native/src/__tests__/module-compat.test.mjs +91 -0
- package/packages/native/src/native.ts +9 -8
- package/packages/pi-agent-core/dist/agent-loop.js +3 -2
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts +1 -1
- package/packages/pi-agent-core/dist/proxy.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/proxy.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +45 -0
- package/packages/pi-agent-core/src/agent-loop.ts +3 -2
- package/packages/pi-agent-core/src/proxy.ts +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/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/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +19 -2
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js +25 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.test.js.map +1 -0
- package/packages/pi-ai/dist/types.d.ts +3 -3
- 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/json-parse.d.ts +3 -0
- package/packages/pi-ai/dist/utils/json-parse.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/json-parse.js +24 -1
- package/packages/pi-ai/dist/utils/json-parse.js.map +1 -1
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts +37 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js +75 -0
- package/packages/pi-ai/dist/utils/repair-tool-json.js.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js +73 -0
- package/packages/pi-ai/dist/utils/tests/repair-tool-json.test.js.map +1 -0
- package/packages/pi-ai/src/env-api-keys.ts +1 -0
- package/packages/pi-ai/src/index.ts +1 -0
- package/packages/pi-ai/src/providers/anthropic-shared.test.ts +29 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +17 -2
- package/packages/pi-ai/src/types.ts +3 -2
- package/packages/pi-ai/src/utils/json-parse.ts +28 -1
- package/packages/pi-ai/src/utils/repair-tool-json.ts +88 -0
- package/packages/pi-ai/src/utils/tests/repair-tool-json.test.ts +102 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +31 -0
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +17 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +62 -2
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js +176 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/exec.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/exec.js +3 -1
- package/packages/pi-coding-agent/dist/core/exec.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts +28 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js +37 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js +63 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-manifest.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js +115 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js +109 -0
- package/packages/pi-coding-agent/dist/core/extensions/extension-sort.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js +2 -0
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts +44 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js +97 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js +181 -0
- package/packages/pi-coding-agent/dist/core/image-overflow-recovery.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -1
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/index.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js +3 -0
- package/packages/pi-coding-agent/dist/core/lsp/lspmux.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.js +31 -2
- package/packages/pi-coding-agent/dist/core/messages.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/messages.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/messages.test.js +86 -0
- package/packages/pi-coding-agent/dist/core/messages.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 +1 -0
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts +10 -0
- package/packages/pi-coding-agent/dist/core/resource-loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js +12 -1
- package/packages/pi-coding-agent/dist/core/resource-loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts +6 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +48 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts +9 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +193 -0
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +13 -4
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts +16 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +80 -0
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts +2 -2
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- 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 +4 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts +1 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js +5 -0
- package/packages/pi-coding-agent/dist/modes/rpc/remote-terminal.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.test.ts +236 -0
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +94 -1
- package/packages/pi-coding-agent/src/core/exec.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.test.ts +77 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-manifest.ts +62 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.test.ts +134 -0
- package/packages/pi-coding-agent/src/core/extensions/extension-sort.ts +137 -0
- package/packages/pi-coding-agent/src/core/extensions/index.ts +4 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.test.ts +228 -0
- package/packages/pi-coding-agent/src/core/image-overflow-recovery.ts +118 -0
- package/packages/pi-coding-agent/src/core/index.ts +6 -0
- package/packages/pi-coding-agent/src/core/lsp/index.ts +3 -0
- package/packages/pi-coding-agent/src/core/lsp/lspmux.ts +3 -0
- package/packages/pi-coding-agent/src/core/messages.test.ts +114 -0
- package/packages/pi-coding-agent/src/core/messages.ts +29 -2
- package/packages/pi-coding-agent/src/core/model-resolver.ts +1 -0
- package/packages/pi-coding-agent/src/core/resource-loader.ts +20 -1
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +255 -0
- package/packages/pi-coding-agent/src/core/retry-handler.ts +52 -1
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +14 -4
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +92 -0
- package/packages/pi-coding-agent/src/index.ts +6 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +7 -0
- package/packages/pi-coding-agent/src/modes/rpc/remote-terminal.ts +6 -0
- package/packages/pi-tui/dist/terminal.d.ts +2 -0
- package/packages/pi-tui/dist/terminal.d.ts.map +1 -1
- package/packages/pi-tui/dist/terminal.js +9 -0
- package/packages/pi-tui/dist/terminal.js.map +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +9 -0
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/terminal.ts +14 -0
- package/packages/pi-tui/src/tui.ts +8 -0
- package/pkg/package.json +1 -1
- package/scripts/ensure-workspace-builds.cjs +45 -14
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/ask-user-questions.ts +21 -3
- package/src/resources/extensions/async-jobs/extension-manifest.json +1 -1
- package/src/resources/extensions/bg-shell/extension-manifest.json +1 -1
- package/src/resources/extensions/browser-tools/extension-manifest.json +1 -1
- package/src/resources/extensions/claude-code-cli/partial-builder.ts +13 -6
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +63 -35
- package/src/resources/extensions/claude-code-cli/tests/partial-builder.test.ts +28 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +108 -1
- package/src/resources/extensions/context7/extension-manifest.json +1 -1
- package/src/resources/extensions/get-secrets-from-user.ts +8 -5
- package/src/resources/extensions/google-search/extension-manifest.json +1 -1
- package/src/resources/extensions/google-search/index.ts +2 -1
- package/src/resources/extensions/gsd/auto/infra-errors.ts +3 -0
- package/src/resources/extensions/gsd/auto/loop-deps.ts +1 -0
- package/src/resources/extensions/gsd/auto/phases.ts +43 -34
- package/src/resources/extensions/gsd/auto-artifact-paths.ts +2 -2
- package/src/resources/extensions/gsd/auto-dashboard.ts +37 -19
- package/src/resources/extensions/gsd/auto-dispatch.ts +21 -5
- package/src/resources/extensions/gsd/auto-model-selection.ts +26 -5
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +1 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +12 -5
- package/src/resources/extensions/gsd/auto-start.ts +35 -26
- package/src/resources/extensions/gsd/auto-worktree.ts +197 -11
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +31 -0
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +87 -9
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +38 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +31 -19
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +50 -11
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +75 -0
- package/src/resources/extensions/gsd/captures.ts +63 -3
- package/src/resources/extensions/gsd/db-writer.ts +140 -7
- package/src/resources/extensions/gsd/dispatch-guard.ts +12 -1
- package/src/resources/extensions/gsd/doctor-git-checks.ts +26 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +2 -1
- package/src/resources/extensions/gsd/doctor-runtime-checks.ts +5 -4
- package/src/resources/extensions/gsd/doctor.ts +3 -1
- package/src/resources/extensions/gsd/error-classifier.ts +14 -11
- package/src/resources/extensions/gsd/extension-manifest.json +16 -1
- package/src/resources/extensions/gsd/forensics.ts +144 -20
- package/src/resources/extensions/gsd/git-service.ts +26 -3
- package/src/resources/extensions/gsd/gitignore.ts +33 -0
- package/src/resources/extensions/gsd/gsd-db.ts +49 -8
- package/src/resources/extensions/gsd/guided-flow.ts +114 -45
- package/src/resources/extensions/gsd/health-widget-core.ts +34 -0
- package/src/resources/extensions/gsd/health-widget.ts +17 -0
- package/src/resources/extensions/gsd/index.ts +1 -0
- package/src/resources/extensions/gsd/memory-extractor.ts +8 -0
- package/src/resources/extensions/gsd/migrate-external.ts +9 -1
- package/src/resources/extensions/gsd/milestone-validation-gates.ts +56 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +19 -0
- package/src/resources/extensions/gsd/model-router.ts +35 -1
- package/src/resources/extensions/gsd/native-git-bridge.ts +17 -0
- package/src/resources/extensions/gsd/notifications.ts +16 -0
- package/src/resources/extensions/gsd/parallel-eligibility.ts +15 -2
- package/src/resources/extensions/gsd/parallel-merge.ts +87 -4
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +23 -6
- package/src/resources/extensions/gsd/parsers-legacy.ts +22 -3
- package/src/resources/extensions/gsd/paths.ts +42 -0
- package/src/resources/extensions/gsd/preferences-models.ts +14 -1
- package/src/resources/extensions/gsd/preferences-types.ts +2 -1
- package/src/resources/extensions/gsd/preferences.ts +45 -29
- package/src/resources/extensions/gsd/prompt-loader.ts +4 -1
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +4 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +1 -1
- package/src/resources/extensions/gsd/prompts/discuss.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -1
- package/src/resources/extensions/gsd/prompts/forensics.md +2 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/guided-discuss-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +2 -0
- package/src/resources/extensions/gsd/prompts/rethink.md +1 -1
- package/src/resources/extensions/gsd/prompts/triage-captures.md +1 -0
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/repo-identity.ts +186 -11
- package/src/resources/extensions/gsd/rethink.ts +6 -0
- package/src/resources/extensions/gsd/roadmap-slices.ts +5 -4
- package/src/resources/extensions/gsd/state.ts +84 -32
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/auto-mode-interactive-guard.test.ts +71 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +71 -1
- package/src/resources/extensions/gsd/tests/captures.test.ts +103 -0
- package/src/resources/extensions/gsd/tests/cli-provider-rate-limit.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/completion-hierarchy-guards.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/db-path-worktree-symlink.test.ts +131 -0
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +7 -12
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/discuss-empty-db-fallback.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/discuss-queued-milestones.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/dist-redirect.mjs +20 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/dynamic-routing-default.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +74 -0
- package/src/resources/extensions/gsd/tests/event-replay-idempotency.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +129 -0
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +125 -12
- package/src/resources/extensions/gsd/tests/gsdroot-worktree-detection.test.ts +164 -0
- package/src/resources/extensions/gsd/tests/guided-flow-dynamic-routing.test.ts +135 -0
- package/src/resources/extensions/gsd/tests/guided-flow-session-isolation.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +111 -1
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/integration/auto-worktree.test.ts +59 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-false-positives.test.ts +243 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-staging-2570.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/integration/parallel-merge.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/integration/run-uat.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +959 -0
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +85 -2
- package/src/resources/extensions/gsd/tests/migrate-external-worktree.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/milestone-status-authoritative.test.ts +116 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/model-router.test.ts +68 -3
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/notifications.test.ts +45 -0
- package/src/resources/extensions/gsd/tests/parallel-commit-scope.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/parallel-eligibility-ghost.test.ts +150 -0
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +9 -8
- package/src/resources/extensions/gsd/tests/plan-milestone-title.test.ts +70 -0
- package/src/resources/extensions/gsd/tests/plan-milestone.test.ts +33 -1
- package/src/resources/extensions/gsd/tests/preferences.test.ts +34 -0
- package/src/resources/extensions/gsd/tests/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-replacement.test.ts +178 -0
- package/src/resources/extensions/gsd/tests/prompt-tool-names.test.ts +69 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/queue-execution-guard.test.ts +157 -0
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/reassess-handler.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/reconciliation-edge-cases.test.ts +162 -0
- package/src/resources/extensions/gsd/tests/roadmap-slices.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/secure-env-collect.test.ts +134 -0
- package/src/resources/extensions/gsd/tests/slice-disk-reconcile.test.ts +233 -0
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +305 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +405 -0
- package/src/resources/extensions/gsd/tests/state-derivation-parity.test.ts +257 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +1628 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/stuck-detection-coverage.test.ts +174 -0
- package/src/resources/extensions/gsd/tests/summary-render-parity.test.ts +221 -0
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/triage-resolution.test.ts +8 -0
- package/src/resources/extensions/gsd/tests/uat-stuck-loop-orphaned-worktree.test.ts +289 -0
- package/src/resources/extensions/gsd/tests/unit-ownership.test.ts +100 -17
- package/src/resources/extensions/gsd/tests/vacuum-recovery.test.ts +154 -0
- package/src/resources/extensions/gsd/tests/validate-milestone-write-order.test.ts +27 -2
- package/src/resources/extensions/gsd/tests/validation-gate-patterns.test.ts +44 -2
- package/src/resources/extensions/gsd/tests/verdict-parser.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/verification-operational-gate.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workflow-logger.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/workflow-manifest.test.ts +92 -0
- package/src/resources/extensions/gsd/tests/workflow-projections.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/worktree-db-respawn-truncation.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +175 -0
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +101 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +48 -1
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +95 -0
- package/src/resources/extensions/gsd/tools/complete-task.ts +36 -74
- package/src/resources/extensions/gsd/tools/plan-milestone.ts +13 -1
- package/src/resources/extensions/gsd/tools/reassess-roadmap.ts +36 -0
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +25 -2
- package/src/resources/extensions/gsd/triage-resolution.ts +23 -6
- package/src/resources/extensions/gsd/types.ts +4 -2
- package/src/resources/extensions/gsd/undo.ts +2 -2
- package/src/resources/extensions/gsd/unit-ownership.ts +206 -35
- package/src/resources/extensions/gsd/verdict-parser.ts +21 -6
- package/src/resources/extensions/gsd/workflow-logger.ts +3 -1
- package/src/resources/extensions/gsd/workflow-manifest.ts +22 -5
- package/src/resources/extensions/gsd/workflow-projections.ts +97 -64
- package/src/resources/extensions/gsd/workflow-reconcile.ts +39 -10
- package/src/resources/extensions/gsd/workspace-index.ts +30 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +120 -1
- package/src/resources/extensions/gsd/worktree-resolver.ts +22 -3
- package/src/resources/extensions/mcp-client/index.ts +13 -7
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +55 -0
- package/src/resources/extensions/ollama/index.ts +130 -0
- package/src/resources/extensions/ollama/model-capabilities.ts +145 -0
- package/src/resources/extensions/ollama/ollama-client.ts +196 -0
- package/src/resources/extensions/ollama/ollama-commands.ts +248 -0
- package/src/resources/extensions/ollama/ollama-discovery.ts +106 -0
- package/src/resources/extensions/ollama/ollama-tool.ts +218 -0
- package/src/resources/extensions/ollama/tests/model-capabilities.test.ts +162 -0
- package/src/resources/extensions/ollama/tests/ollama-client.test.ts +38 -0
- package/src/resources/extensions/ollama/tests/ollama-discovery.test.ts +28 -0
- package/src/resources/extensions/ollama/types.ts +130 -0
- package/src/resources/extensions/search-the-web/extension-manifest.json +1 -1
- package/src/resources/extensions/shared/interview-ui.ts +12 -1
- package/src/resources/extensions/shared/tests/ask-user-freetext.test.ts +156 -0
- package/src/resources/skills/create-gsd-extension/SKILL.md +5 -3
- package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +5 -4
- package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +2 -2
- package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +4 -4
- package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +5 -3
- package/dist/web/standalone/.next/static/chunks/6502.2305d0afd2385711.js +0 -9
- package/dist/web/standalone/.next/static/chunks/app/page-62be3b5fa91e4c8f.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/css/a58ef8a151aa0493.css +0 -1
- package/src/resources/extensions/gsd/tests/empty-db-reconciliation.test.ts +0 -79
- /package/dist/web/standalone/.next/static/{yowc5qPtuKxjOr22KmOAy → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{yowc5qPtuKxjOr22KmOAy → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
|
@@ -3,6 +3,7 @@ import { isDbAvailable, getMilestoneSlices, getSliceTasks } from "./gsd-db.js";
|
|
|
3
3
|
import { parseRoadmap, parsePlan } from "./parsers-legacy.js";
|
|
4
4
|
import { resolveMilestoneFile, resolveSliceFile, resolveTaskFile, resolveTasksDir, } from "./paths.js";
|
|
5
5
|
import { deriveState } from "./state.js";
|
|
6
|
+
import { extractVerdict } from "./verdict-parser.js";
|
|
6
7
|
import { findMilestoneIds } from "./guided-flow.js";
|
|
7
8
|
import { getSliceBranchName, detectWorktreeName } from "./worktree.js";
|
|
8
9
|
// Extract milestone title from roadmap header without using parsers.
|
|
@@ -116,6 +117,29 @@ export async function indexWorkspace(basePath, opts = {}) {
|
|
|
116
117
|
taskId: state.activeTask?.id,
|
|
117
118
|
phase: state.phase,
|
|
118
119
|
};
|
|
120
|
+
// Enrich milestones with authoritative status from state registry (#2807)
|
|
121
|
+
if (state.registry) {
|
|
122
|
+
const registryMap = new Map(state.registry.map(e => [e.id, e]));
|
|
123
|
+
for (const milestone of milestones) {
|
|
124
|
+
const entry = registryMap.get(milestone.id);
|
|
125
|
+
if (entry) {
|
|
126
|
+
milestone.status = entry.status;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Populate validationVerdict from VALIDATION files (#2807)
|
|
131
|
+
for (const milestone of milestones) {
|
|
132
|
+
const validationPath = resolveMilestoneFile(basePath, milestone.id, "VALIDATION");
|
|
133
|
+
if (validationPath) {
|
|
134
|
+
const validationContent = await loadFile(validationPath);
|
|
135
|
+
if (validationContent) {
|
|
136
|
+
const verdict = extractVerdict(validationContent);
|
|
137
|
+
if (verdict === "pass" || verdict === "needs-attention" || verdict === "needs-remediation") {
|
|
138
|
+
milestone.validationVerdict = verdict;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
119
143
|
const scopes = [{ scope: "project", label: "project", kind: "project" }];
|
|
120
144
|
for (const milestone of milestones) {
|
|
121
145
|
scopes.push({ scope: milestone.id, label: `${milestone.id}: ${milestone.title}`, kind: "milestone" });
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* 3. merge() — LLM-guided reconciliation of .gsd/ artifacts back to main
|
|
15
15
|
* 4. remove() — git worktree remove + branch cleanup
|
|
16
16
|
*/
|
|
17
|
-
import { existsSync, mkdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
17
|
+
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync } from "node:fs";
|
|
18
18
|
import { execFileSync } from "node:child_process";
|
|
19
19
|
import { join, resolve, sep } from "node:path";
|
|
20
20
|
import { GSDError, GSD_PARSE_ERROR, GSD_STALE_STATE, GSD_LOCK_HELD, GSD_GIT_ERROR, GSD_MERGE_CONFLICT } from "./errors.js";
|
|
@@ -203,6 +203,73 @@ export function listWorktrees(basePath) {
|
|
|
203
203
|
}
|
|
204
204
|
return worktrees;
|
|
205
205
|
}
|
|
206
|
+
// ─── Nested .git Detection (#2616) ──────────────────────────────────────
|
|
207
|
+
//
|
|
208
|
+
// Scaffolding tools (create-next-app, cargo init, etc.) create nested .git
|
|
209
|
+
// directories inside worktrees. Git records these as gitlinks (mode 160000)
|
|
210
|
+
// without a .gitmodules entry — so worktree cleanup destroys the only copy
|
|
211
|
+
// of their object database, causing permanent silent data loss.
|
|
212
|
+
/** Directories to skip when scanning for nested .git dirs. */
|
|
213
|
+
const NESTED_GIT_SKIP_DIRS = new Set([
|
|
214
|
+
".git", ".gsd", "node_modules", ".next", ".nuxt", "dist", "build",
|
|
215
|
+
"__pycache__", ".tox", ".venv", "venv", "target", "vendor",
|
|
216
|
+
]);
|
|
217
|
+
/**
|
|
218
|
+
* Recursively find nested .git directories inside a worktree root.
|
|
219
|
+
* Returns paths to directories that contain their own .git (directory, not file).
|
|
220
|
+
* Skips node_modules, .gsd, and other non-project directories for performance.
|
|
221
|
+
*
|
|
222
|
+
* A nested .git *directory* (not a .git file — which is a legitimate worktree
|
|
223
|
+
* pointer) indicates a scaffolded repo that will become an orphaned gitlink.
|
|
224
|
+
*/
|
|
225
|
+
export function findNestedGitDirs(rootPath) {
|
|
226
|
+
const results = [];
|
|
227
|
+
function walk(dir, depth) {
|
|
228
|
+
// Cap recursion depth to avoid runaway scanning
|
|
229
|
+
if (depth > 10)
|
|
230
|
+
return;
|
|
231
|
+
let entries;
|
|
232
|
+
try {
|
|
233
|
+
entries = readdirSync(dir);
|
|
234
|
+
}
|
|
235
|
+
catch {
|
|
236
|
+
return; // Permission denied, broken symlink, etc.
|
|
237
|
+
}
|
|
238
|
+
for (const entry of entries) {
|
|
239
|
+
if (NESTED_GIT_SKIP_DIRS.has(entry))
|
|
240
|
+
continue;
|
|
241
|
+
const fullPath = join(dir, entry);
|
|
242
|
+
// Only follow real directories, not symlinks
|
|
243
|
+
let stat;
|
|
244
|
+
try {
|
|
245
|
+
stat = lstatSync(fullPath);
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
if (!stat.isDirectory())
|
|
251
|
+
continue;
|
|
252
|
+
// Check if this directory contains a .git *directory* (not a .git file).
|
|
253
|
+
// A .git file is a worktree pointer and is legitimate.
|
|
254
|
+
// A .git directory is a standalone repo created by scaffolding.
|
|
255
|
+
const innerGit = join(fullPath, ".git");
|
|
256
|
+
try {
|
|
257
|
+
const innerStat = lstatSync(innerGit);
|
|
258
|
+
if (innerStat.isDirectory()) {
|
|
259
|
+
results.push(fullPath);
|
|
260
|
+
// Don't recurse into the nested repo — we found what we need
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// No .git here — continue scanning
|
|
266
|
+
}
|
|
267
|
+
walk(fullPath, depth + 1);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
walk(rootPath, 0);
|
|
271
|
+
return results;
|
|
272
|
+
}
|
|
206
273
|
/**
|
|
207
274
|
* Remove a worktree and optionally delete its branch.
|
|
208
275
|
* If the process is currently inside the worktree, chdir out first.
|
|
@@ -269,6 +336,24 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
269
336
|
// submodule status failed — proceed with normal removal
|
|
270
337
|
}
|
|
271
338
|
}
|
|
339
|
+
// Nested .git safety (#2616): detect nested .git directories created by
|
|
340
|
+
// scaffolding tools (create-next-app, cargo init, etc.). These produce
|
|
341
|
+
// gitlink entries (mode 160000) without .gitmodules — cleanup would destroy
|
|
342
|
+
// the only copy of the nested object database, causing permanent data loss.
|
|
343
|
+
// Fix: remove the nested .git dirs so git tracks the files as regular content.
|
|
344
|
+
const nestedGitDirs = findNestedGitDirs(resolvedWtPath);
|
|
345
|
+
if (nestedGitDirs.length > 0) {
|
|
346
|
+
for (const nestedDir of nestedGitDirs) {
|
|
347
|
+
const nestedGitPath = join(nestedDir, ".git");
|
|
348
|
+
try {
|
|
349
|
+
rmSync(nestedGitPath, { recursive: true, force: true });
|
|
350
|
+
logWarning("reconcile", `Removed nested .git directory from scaffolded project to prevent data loss (#2616)`, { worktree: name, nestedRepo: nestedDir });
|
|
351
|
+
}
|
|
352
|
+
catch {
|
|
353
|
+
logWarning("reconcile", `Failed to remove nested .git directory — files may be lost as orphaned gitlink`, { worktree: name, nestedRepo: nestedDir });
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
272
357
|
// Remove worktree: try non-force first when submodules have changes,
|
|
273
358
|
// falling back to force only after submodule state has been preserved.
|
|
274
359
|
const useForce = hasSubmoduleChanges ? false : force;
|
|
@@ -283,6 +368,25 @@ export function removeWorktree(basePath, name, opts = {}) {
|
|
|
283
368
|
}
|
|
284
369
|
catch { /* may fail */ }
|
|
285
370
|
}
|
|
371
|
+
// (#2821) If the worktree directory STILL exists after both native removal
|
|
372
|
+
// attempts (e.g. untracked files like ASSESSMENT/UAT-RESULT prevent git
|
|
373
|
+
// worktree remove), force-remove the git internal worktree metadata first,
|
|
374
|
+
// then remove the filesystem directory. Without this, the .git/worktrees/<name>
|
|
375
|
+
// lock prevents rmSync from cleaning up, and the orphaned worktree directory
|
|
376
|
+
// causes every subsequent `/gsd auto` to re-enter the stale worktree.
|
|
377
|
+
if (existsSync(resolvedWtPath)) {
|
|
378
|
+
try {
|
|
379
|
+
const wtInternalDir = join(basePath, ".git", "worktrees", name);
|
|
380
|
+
if (existsSync(wtInternalDir)) {
|
|
381
|
+
rmSync(wtInternalDir, { recursive: true, force: true });
|
|
382
|
+
}
|
|
383
|
+
rmSync(resolvedWtPath, { recursive: true, force: true });
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
logWarning("reconcile", `Worktree directory could not be removed after git internal cleanup: ${resolvedWtPath}. ` +
|
|
387
|
+
`Manual cleanup: rm -rf "${resolvedWtPath.replaceAll("\\", "/")}"`, { worktree: name });
|
|
388
|
+
}
|
|
389
|
+
}
|
|
286
390
|
// Prune stale entries so git knows the worktree is gone
|
|
287
391
|
nativeWorktreePrune(basePath);
|
|
288
392
|
if (deleteBranch) {
|
|
@@ -248,7 +248,12 @@ export class WorktreeResolver {
|
|
|
248
248
|
eventType: "worktree-merge-start",
|
|
249
249
|
data: { milestoneId, mode },
|
|
250
250
|
});
|
|
251
|
-
|
|
251
|
+
// #2625: If we are physically inside an auto-worktree, we MUST merge
|
|
252
|
+
// regardless of the current isolation config. This prevents data loss when
|
|
253
|
+
// the default isolation mode changes between versions (e.g., "worktree" ->
|
|
254
|
+
// "none"): the worktree branch still holds real commits that need merging.
|
|
255
|
+
const inWorktree = this.deps.isInAutoWorktree(this.s.basePath) && this.s.originalBasePath;
|
|
256
|
+
if (mode === "none" && !inWorktree) {
|
|
252
257
|
debugLog("WorktreeResolver", {
|
|
253
258
|
action: "mergeAndExit",
|
|
254
259
|
milestoneId,
|
|
@@ -257,8 +262,7 @@ export class WorktreeResolver {
|
|
|
257
262
|
});
|
|
258
263
|
return;
|
|
259
264
|
}
|
|
260
|
-
if (mode === "worktree" ||
|
|
261
|
-
(this.deps.isInAutoWorktree(this.s.basePath) && this.s.originalBasePath)) {
|
|
265
|
+
if (mode === "worktree" || inWorktree) {
|
|
262
266
|
this._mergeWorktreeMode(milestoneId, ctx);
|
|
263
267
|
}
|
|
264
268
|
else if (mode === "branch") {
|
|
@@ -308,6 +312,19 @@ export class WorktreeResolver {
|
|
|
308
312
|
if (roadmapPath) {
|
|
309
313
|
const roadmapContent = this.deps.readFileSync(roadmapPath, "utf-8");
|
|
310
314
|
const mergeResult = this.deps.mergeMilestoneToMain(originalBase, milestoneId, roadmapContent);
|
|
315
|
+
// #2945 Bug 3: mergeMilestoneToMain performs best-effort worktree
|
|
316
|
+
// cleanup internally (step 12), but it can silently fail on Windows
|
|
317
|
+
// or when the worktree directory is locked. Perform a secondary
|
|
318
|
+
// teardown here to ensure the worktree is properly cleaned up.
|
|
319
|
+
// This is idempotent — if the worktree was already removed,
|
|
320
|
+
// teardownAutoWorktree handles the no-op case gracefully.
|
|
321
|
+
try {
|
|
322
|
+
this.deps.teardownAutoWorktree(originalBase, milestoneId);
|
|
323
|
+
}
|
|
324
|
+
catch {
|
|
325
|
+
// Best-effort — the primary cleanup in mergeMilestoneToMain may
|
|
326
|
+
// have already removed the worktree.
|
|
327
|
+
}
|
|
311
328
|
if (mergeResult.codeFilesChanged) {
|
|
312
329
|
ctx.notify(`Milestone ${milestoneId} merged to main.${mergeResult.pushed ? " Pushed to remote." : ""}`, "info");
|
|
313
330
|
}
|
|
@@ -74,7 +74,9 @@ function readConfigs() {
|
|
|
74
74
|
return servers;
|
|
75
75
|
}
|
|
76
76
|
function getServerConfig(name) {
|
|
77
|
-
|
|
77
|
+
const trimmed = name.trim();
|
|
78
|
+
return readConfigs().find((s) => s.name === trimmed ||
|
|
79
|
+
s.name.toLowerCase() === trimmed.toLowerCase());
|
|
78
80
|
}
|
|
79
81
|
/** Resolve ${VAR} references in env values against process.env. */
|
|
80
82
|
function resolveEnv(env) {
|
|
@@ -90,12 +92,14 @@ function resolveEnv(env) {
|
|
|
90
92
|
return resolved;
|
|
91
93
|
}
|
|
92
94
|
async function getOrConnect(name, signal) {
|
|
93
|
-
const existing = connections.get(name);
|
|
94
|
-
if (existing)
|
|
95
|
-
return existing.client;
|
|
96
95
|
const config = getServerConfig(name);
|
|
97
96
|
if (!config)
|
|
98
97
|
throw new Error(`Unknown MCP server: "${name}". Use mcp_servers to list available servers.`);
|
|
98
|
+
// Always use config.name as the canonical cache key so that variant
|
|
99
|
+
// casing / whitespace still hits the same connection.
|
|
100
|
+
const existing = connections.get(config.name);
|
|
101
|
+
if (existing)
|
|
102
|
+
return existing.client;
|
|
99
103
|
const client = new Client({ name: "gsd", version: "1.0.0" });
|
|
100
104
|
let transport;
|
|
101
105
|
if (config.transport === "stdio" && config.command) {
|
|
@@ -108,14 +112,14 @@ async function getOrConnect(name, signal) {
|
|
|
108
112
|
});
|
|
109
113
|
}
|
|
110
114
|
else if (config.transport === "http" && config.url) {
|
|
111
|
-
const resolvedUrl = config.url.replace(/\$\{([^}]+)\}/g, (_,
|
|
115
|
+
const resolvedUrl = config.url.replace(/\$\{([^}]+)\}/g, (_, varName) => process.env[varName] ?? "");
|
|
112
116
|
transport = new StreamableHTTPClientTransport(new URL(resolvedUrl));
|
|
113
117
|
}
|
|
114
118
|
else {
|
|
115
|
-
throw new Error(`Server "${name}" has unsupported transport: ${config.transport}`);
|
|
119
|
+
throw new Error(`Server "${config.name}" has unsupported transport: ${config.transport}`);
|
|
116
120
|
}
|
|
117
121
|
await client.connect(transport, { signal, timeout: 30000 });
|
|
118
|
-
connections.set(name, { client, transport });
|
|
122
|
+
connections.set(config.name, { client, transport });
|
|
119
123
|
return client;
|
|
120
124
|
}
|
|
121
125
|
async function closeAll() {
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// GSD2 — Ollama Extension: First-class local LLM support
|
|
2
|
+
/**
|
|
3
|
+
* Ollama Extension
|
|
4
|
+
*
|
|
5
|
+
* Auto-detects a running Ollama instance, discovers locally pulled models,
|
|
6
|
+
* and registers them as a first-class provider. No configuration required —
|
|
7
|
+
* if Ollama is running, models appear automatically.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - Auto-discovery of local models via /api/tags
|
|
11
|
+
* - Capability detection (vision, reasoning, context window)
|
|
12
|
+
* - /ollama slash commands for model management
|
|
13
|
+
* - ollama_manage tool for LLM-driven model operations
|
|
14
|
+
* - Zero-cost model registration (local inference)
|
|
15
|
+
*
|
|
16
|
+
* Respects OLLAMA_HOST env var for non-default endpoints.
|
|
17
|
+
*/
|
|
18
|
+
import { importExtensionModule } from "@gsd/pi-coding-agent";
|
|
19
|
+
import * as client from "./ollama-client.js";
|
|
20
|
+
import { discoverModels, getOllamaOpenAIBaseUrl } from "./ollama-discovery.js";
|
|
21
|
+
import { registerOllamaCommands } from "./ollama-commands.js";
|
|
22
|
+
/** Default compat settings for Ollama models via OpenAI-compat endpoint */
|
|
23
|
+
const OLLAMA_COMPAT = {
|
|
24
|
+
supportsDeveloperRole: false,
|
|
25
|
+
supportsReasoningEffort: false,
|
|
26
|
+
supportsUsageInStreaming: false,
|
|
27
|
+
maxTokensField: "max_tokens",
|
|
28
|
+
supportsStore: false,
|
|
29
|
+
};
|
|
30
|
+
let toolsPromise = null;
|
|
31
|
+
async function registerOllamaTools(pi) {
|
|
32
|
+
if (!toolsPromise) {
|
|
33
|
+
toolsPromise = (async () => {
|
|
34
|
+
const { registerOllamaTool } = await importExtensionModule(import.meta.url, "./ollama-tool.js");
|
|
35
|
+
registerOllamaTool(pi);
|
|
36
|
+
})().catch((error) => {
|
|
37
|
+
toolsPromise = null;
|
|
38
|
+
throw error;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return toolsPromise;
|
|
42
|
+
}
|
|
43
|
+
/** Track whether we've registered models so we can clean up on shutdown */
|
|
44
|
+
let providerRegistered = false;
|
|
45
|
+
/**
|
|
46
|
+
* Probe Ollama and register discovered models.
|
|
47
|
+
* Safe to call multiple times — re-discovers and re-registers.
|
|
48
|
+
*/
|
|
49
|
+
async function probeAndRegister(pi) {
|
|
50
|
+
const running = await client.isRunning();
|
|
51
|
+
if (!running) {
|
|
52
|
+
if (providerRegistered) {
|
|
53
|
+
pi.unregisterProvider("ollama");
|
|
54
|
+
providerRegistered = false;
|
|
55
|
+
}
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
const models = await discoverModels();
|
|
59
|
+
if (models.length === 0)
|
|
60
|
+
return true; // Running but no models pulled
|
|
61
|
+
const baseUrl = getOllamaOpenAIBaseUrl();
|
|
62
|
+
pi.registerProvider("ollama", {
|
|
63
|
+
authMode: "none",
|
|
64
|
+
baseUrl,
|
|
65
|
+
api: "openai-completions",
|
|
66
|
+
isReady: () => true,
|
|
67
|
+
models: models.map((m) => ({
|
|
68
|
+
id: m.id,
|
|
69
|
+
name: m.name,
|
|
70
|
+
reasoning: m.reasoning,
|
|
71
|
+
input: m.input,
|
|
72
|
+
cost: m.cost,
|
|
73
|
+
contextWindow: m.contextWindow,
|
|
74
|
+
maxTokens: m.maxTokens,
|
|
75
|
+
compat: OLLAMA_COMPAT,
|
|
76
|
+
})),
|
|
77
|
+
});
|
|
78
|
+
providerRegistered = true;
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
export default function ollama(pi) {
|
|
82
|
+
// Register slash commands immediately (they check Ollama availability themselves)
|
|
83
|
+
registerOllamaCommands(pi);
|
|
84
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
85
|
+
// Register tool (deferred to avoid blocking startup)
|
|
86
|
+
if (ctx.hasUI) {
|
|
87
|
+
void registerOllamaTools(pi).catch((error) => {
|
|
88
|
+
ctx.ui.notify(`Ollama tool failed to load: ${error instanceof Error ? error.message : String(error)}`, "warning");
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
await registerOllamaTools(pi);
|
|
93
|
+
}
|
|
94
|
+
// Async probe — don't block startup
|
|
95
|
+
probeAndRegister(pi)
|
|
96
|
+
.then((found) => {
|
|
97
|
+
if (found && ctx.hasUI) {
|
|
98
|
+
ctx.ui.setStatus("ollama", "Ollama");
|
|
99
|
+
}
|
|
100
|
+
})
|
|
101
|
+
.catch(() => {
|
|
102
|
+
// Silently ignore probe failures
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
pi.on("session_shutdown", async () => {
|
|
106
|
+
if (providerRegistered) {
|
|
107
|
+
pi.unregisterProvider("ollama");
|
|
108
|
+
providerRegistered = false;
|
|
109
|
+
}
|
|
110
|
+
toolsPromise = null;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
// GSD2 — Known model capability table for Ollama models
|
|
2
|
+
/**
|
|
3
|
+
* Known model family capabilities.
|
|
4
|
+
* Keys are matched as prefixes against the model name (before the colon/tag).
|
|
5
|
+
* More specific entries should appear first.
|
|
6
|
+
*/
|
|
7
|
+
const KNOWN_MODELS = [
|
|
8
|
+
// ─── Reasoning models ───────────────────────────────────────────────
|
|
9
|
+
["deepseek-r1", { contextWindow: 131072, reasoning: true }],
|
|
10
|
+
["qwq", { contextWindow: 131072, reasoning: true }],
|
|
11
|
+
// ─── Vision models ──────────────────────────────────────────────────
|
|
12
|
+
["llava", { contextWindow: 4096, input: ["text", "image"] }],
|
|
13
|
+
["bakllava", { contextWindow: 4096, input: ["text", "image"] }],
|
|
14
|
+
["moondream", { contextWindow: 8192, input: ["text", "image"] }],
|
|
15
|
+
["llama3.2-vision", { contextWindow: 131072, input: ["text", "image"] }],
|
|
16
|
+
["minicpm-v", { contextWindow: 4096, input: ["text", "image"] }],
|
|
17
|
+
// ─── Code models ────────────────────────────────────────────────────
|
|
18
|
+
["codestral", { contextWindow: 262144, maxTokens: 32768 }],
|
|
19
|
+
["qwen2.5-coder", { contextWindow: 131072, maxTokens: 32768 }],
|
|
20
|
+
["deepseek-coder-v2", { contextWindow: 131072, maxTokens: 16384 }],
|
|
21
|
+
["starcoder2", { contextWindow: 16384, maxTokens: 8192 }],
|
|
22
|
+
["codegemma", { contextWindow: 8192, maxTokens: 8192 }],
|
|
23
|
+
["codellama", { contextWindow: 16384, maxTokens: 8192 }],
|
|
24
|
+
["devstral", { contextWindow: 131072, maxTokens: 32768 }],
|
|
25
|
+
// ─── Llama family ───────────────────────────────────────────────────
|
|
26
|
+
["llama3.3", { contextWindow: 131072, maxTokens: 16384 }],
|
|
27
|
+
["llama3.2", { contextWindow: 131072, maxTokens: 16384 }],
|
|
28
|
+
["llama3.1", { contextWindow: 131072, maxTokens: 16384 }],
|
|
29
|
+
["llama3", { contextWindow: 8192, maxTokens: 8192 }],
|
|
30
|
+
["llama2", { contextWindow: 4096, maxTokens: 4096 }],
|
|
31
|
+
// ─── Qwen family ────────────────────────────────────────────────────
|
|
32
|
+
["qwen3", { contextWindow: 131072, maxTokens: 32768 }],
|
|
33
|
+
["qwen2.5", { contextWindow: 131072, maxTokens: 32768 }],
|
|
34
|
+
["qwen2", { contextWindow: 131072, maxTokens: 32768 }],
|
|
35
|
+
// ─── Gemma family ───────────────────────────────────────────────────
|
|
36
|
+
["gemma3", { contextWindow: 131072, maxTokens: 16384 }],
|
|
37
|
+
["gemma2", { contextWindow: 8192, maxTokens: 8192 }],
|
|
38
|
+
// ─── Mistral family ─────────────────────────────────────────────────
|
|
39
|
+
["mistral-large", { contextWindow: 131072, maxTokens: 16384 }],
|
|
40
|
+
["mistral-small", { contextWindow: 131072, maxTokens: 16384 }],
|
|
41
|
+
["mistral-nemo", { contextWindow: 131072, maxTokens: 16384 }],
|
|
42
|
+
["mistral", { contextWindow: 32768, maxTokens: 8192 }],
|
|
43
|
+
["mixtral", { contextWindow: 32768, maxTokens: 8192 }],
|
|
44
|
+
// ─── Phi family ─────────────────────────────────────────────────────
|
|
45
|
+
["phi4", { contextWindow: 16384, maxTokens: 16384 }],
|
|
46
|
+
["phi3.5", { contextWindow: 131072, maxTokens: 16384 }],
|
|
47
|
+
["phi3", { contextWindow: 131072, maxTokens: 4096 }],
|
|
48
|
+
// ─── Command R ──────────────────────────────────────────────────────
|
|
49
|
+
["command-r-plus", { contextWindow: 131072, maxTokens: 16384 }],
|
|
50
|
+
["command-r", { contextWindow: 131072, maxTokens: 16384 }],
|
|
51
|
+
];
|
|
52
|
+
/**
|
|
53
|
+
* Look up capabilities for a model by name.
|
|
54
|
+
* Matches the longest prefix from the known models table.
|
|
55
|
+
*/
|
|
56
|
+
export function getModelCapabilities(modelName) {
|
|
57
|
+
// Strip tag (everything after the colon) for matching
|
|
58
|
+
const baseName = modelName.split(":")[0].toLowerCase();
|
|
59
|
+
for (const [pattern, caps] of KNOWN_MODELS) {
|
|
60
|
+
if (baseName === pattern || baseName.startsWith(pattern)) {
|
|
61
|
+
return caps;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return {};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Estimate context window from parameter size string (e.g. "7B", "70B", "1.5B").
|
|
68
|
+
* Used as fallback when model isn't in the known table.
|
|
69
|
+
*/
|
|
70
|
+
export function estimateContextFromParams(parameterSize) {
|
|
71
|
+
const match = parameterSize.match(/([\d.]+)\s*([BbMm])/);
|
|
72
|
+
if (!match)
|
|
73
|
+
return 8192;
|
|
74
|
+
const size = parseFloat(match[1]);
|
|
75
|
+
const unit = match[2].toUpperCase();
|
|
76
|
+
// Convert to billions
|
|
77
|
+
const billions = unit === "M" ? size / 1000 : size;
|
|
78
|
+
// Rough heuristics: larger models tend to support larger contexts
|
|
79
|
+
if (billions >= 70)
|
|
80
|
+
return 131072;
|
|
81
|
+
if (billions >= 30)
|
|
82
|
+
return 65536;
|
|
83
|
+
if (billions >= 13)
|
|
84
|
+
return 32768;
|
|
85
|
+
if (billions >= 7)
|
|
86
|
+
return 16384;
|
|
87
|
+
return 8192;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Humanize a model name for display (e.g. "llama3.1:8b" → "Llama 3.1 8B").
|
|
91
|
+
*/
|
|
92
|
+
export function humanizeModelName(modelName) {
|
|
93
|
+
const [base, tag] = modelName.split(":");
|
|
94
|
+
// Capitalize first letter, add spaces around version numbers
|
|
95
|
+
let name = base
|
|
96
|
+
.replace(/([a-z])(\d)/g, "$1 $2")
|
|
97
|
+
.replace(/(\d)([a-z])/g, "$1 $2")
|
|
98
|
+
.replace(/^./, (c) => c.toUpperCase());
|
|
99
|
+
// Clean up common patterns
|
|
100
|
+
name = name.replace(/\s*-\s*/g, " ");
|
|
101
|
+
if (tag && tag !== "latest") {
|
|
102
|
+
name += ` ${tag.toUpperCase()}`;
|
|
103
|
+
}
|
|
104
|
+
return name;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Format byte size for display (e.g. 4700000000 → "4.7 GB").
|
|
108
|
+
*/
|
|
109
|
+
export function formatModelSize(bytes) {
|
|
110
|
+
if (bytes >= 1e9)
|
|
111
|
+
return `${(bytes / 1e9).toFixed(1)} GB`;
|
|
112
|
+
if (bytes >= 1e6)
|
|
113
|
+
return `${(bytes / 1e6).toFixed(1)} MB`;
|
|
114
|
+
return `${(bytes / 1e3).toFixed(0)} KB`;
|
|
115
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
// GSD2 — HTTP client for Ollama REST API
|
|
2
|
+
const DEFAULT_HOST = "http://localhost:11434";
|
|
3
|
+
const PROBE_TIMEOUT_MS = 1500;
|
|
4
|
+
const REQUEST_TIMEOUT_MS = 10000;
|
|
5
|
+
/**
|
|
6
|
+
* Get the Ollama host URL from OLLAMA_HOST or default.
|
|
7
|
+
*/
|
|
8
|
+
export function getOllamaHost() {
|
|
9
|
+
const host = process.env.OLLAMA_HOST;
|
|
10
|
+
if (!host)
|
|
11
|
+
return DEFAULT_HOST;
|
|
12
|
+
// OLLAMA_HOST can be just a host:port without scheme
|
|
13
|
+
if (host.startsWith("http://") || host.startsWith("https://"))
|
|
14
|
+
return host;
|
|
15
|
+
return `http://${host}`;
|
|
16
|
+
}
|
|
17
|
+
async function fetchWithTimeout(url, options = {}, timeoutMs = REQUEST_TIMEOUT_MS) {
|
|
18
|
+
const controller = new AbortController();
|
|
19
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
20
|
+
try {
|
|
21
|
+
return await fetch(url, { ...options, signal: controller.signal });
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
clearTimeout(timeout);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Check if Ollama is running and reachable.
|
|
29
|
+
*/
|
|
30
|
+
export async function isRunning() {
|
|
31
|
+
try {
|
|
32
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/`, {}, PROBE_TIMEOUT_MS);
|
|
33
|
+
return response.ok;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get Ollama version.
|
|
41
|
+
*/
|
|
42
|
+
export async function getVersion() {
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/version`);
|
|
45
|
+
if (!response.ok)
|
|
46
|
+
return null;
|
|
47
|
+
const data = (await response.json());
|
|
48
|
+
return data.version;
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* List all locally available models.
|
|
56
|
+
*/
|
|
57
|
+
export async function listModels() {
|
|
58
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/tags`);
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
throw new Error(`Ollama /api/tags returned ${response.status}: ${response.statusText}`);
|
|
61
|
+
}
|
|
62
|
+
return (await response.json());
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get detailed information about a specific model.
|
|
66
|
+
*/
|
|
67
|
+
export async function showModel(name) {
|
|
68
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/show`, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "Content-Type": "application/json" },
|
|
71
|
+
body: JSON.stringify({ name }),
|
|
72
|
+
});
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
throw new Error(`Ollama /api/show returned ${response.status}: ${response.statusText}`);
|
|
75
|
+
}
|
|
76
|
+
return (await response.json());
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* List currently loaded/running models.
|
|
80
|
+
*/
|
|
81
|
+
export async function getRunningModels() {
|
|
82
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/ps`);
|
|
83
|
+
if (!response.ok) {
|
|
84
|
+
throw new Error(`Ollama /api/ps returned ${response.status}: ${response.statusText}`);
|
|
85
|
+
}
|
|
86
|
+
return (await response.json());
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Pull a model with streaming progress.
|
|
90
|
+
* Calls onProgress for each progress update.
|
|
91
|
+
* Returns when the pull is complete.
|
|
92
|
+
*/
|
|
93
|
+
export async function pullModel(name, onProgress, signal) {
|
|
94
|
+
const response = await fetch(`${getOllamaHost()}/api/pull`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: { "Content-Type": "application/json" },
|
|
97
|
+
body: JSON.stringify({ name, stream: true }),
|
|
98
|
+
signal,
|
|
99
|
+
});
|
|
100
|
+
if (!response.ok) {
|
|
101
|
+
const text = await response.text();
|
|
102
|
+
throw new Error(`Ollama /api/pull returned ${response.status}: ${text}`);
|
|
103
|
+
}
|
|
104
|
+
if (!response.body) {
|
|
105
|
+
throw new Error("Ollama /api/pull returned no body");
|
|
106
|
+
}
|
|
107
|
+
const reader = response.body.getReader();
|
|
108
|
+
const decoder = new TextDecoder();
|
|
109
|
+
let buffer = "";
|
|
110
|
+
while (true) {
|
|
111
|
+
const { done, value } = await reader.read();
|
|
112
|
+
if (done)
|
|
113
|
+
break;
|
|
114
|
+
buffer += decoder.decode(value, { stream: true });
|
|
115
|
+
const lines = buffer.split("\n");
|
|
116
|
+
buffer = lines.pop() ?? "";
|
|
117
|
+
for (const line of lines) {
|
|
118
|
+
const trimmed = line.trim();
|
|
119
|
+
if (!trimmed)
|
|
120
|
+
continue;
|
|
121
|
+
try {
|
|
122
|
+
const progress = JSON.parse(trimmed);
|
|
123
|
+
onProgress?.(progress);
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Skip malformed lines
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Process remaining buffer
|
|
131
|
+
if (buffer.trim()) {
|
|
132
|
+
try {
|
|
133
|
+
const progress = JSON.parse(buffer.trim());
|
|
134
|
+
onProgress?.(progress);
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
// Ignore
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Delete a local model.
|
|
143
|
+
*/
|
|
144
|
+
export async function deleteModel(name) {
|
|
145
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/delete`, {
|
|
146
|
+
method: "DELETE",
|
|
147
|
+
headers: { "Content-Type": "application/json" },
|
|
148
|
+
body: JSON.stringify({ name }),
|
|
149
|
+
});
|
|
150
|
+
if (!response.ok) {
|
|
151
|
+
const text = await response.text();
|
|
152
|
+
throw new Error(`Ollama /api/delete returned ${response.status}: ${text}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Copy a model to a new name.
|
|
157
|
+
*/
|
|
158
|
+
export async function copyModel(source, destination) {
|
|
159
|
+
const response = await fetchWithTimeout(`${getOllamaHost()}/api/copy`, {
|
|
160
|
+
method: "POST",
|
|
161
|
+
headers: { "Content-Type": "application/json" },
|
|
162
|
+
body: JSON.stringify({ source, destination }),
|
|
163
|
+
});
|
|
164
|
+
if (!response.ok) {
|
|
165
|
+
const text = await response.text();
|
|
166
|
+
throw new Error(`Ollama /api/copy returned ${response.status}: ${text}`);
|
|
167
|
+
}
|
|
168
|
+
}
|