gsd-pi 2.57.0-dev.f22a903 → 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/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 +17 -2
- 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 +196 -12
- 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 +80 -8
- 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/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 +36 -9
- 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/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 +13 -16
- 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/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 +14 -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 +16 -16
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/react-loadable-manifest.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +2 -2
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +2 -2
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- 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 +2 -2
- 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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.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_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_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_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_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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_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_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.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 +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +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 +16 -16
- package/dist/web/standalone/.next/server/chunks/2229.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/6502.7593d7797a4b3999.js +9 -0
- package/dist/web/standalone/.next/static/chunks/{webpack-61d3afac6d0f0ce7.js → webpack-a1c1e452c6b32d04.js} +1 -1
- package/dist/web/standalone/.next/static/css/f6e8833d46e738d8.css +1 -0
- 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/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 +18 -2
- 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 +190 -9
- 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 +85 -8
- 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/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 +43 -7
- 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/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 +13 -15
- 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/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/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/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/project-relocation-recovery.test.ts +297 -0
- package/src/resources/extensions/gsd/tests/prompt-contracts.test.ts +29 -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 +4 -1
- 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-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 +20 -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.8b732f67a11b11b4.js +0 -9
- 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/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{OS7_z6QaL6uqp8q5pjHSJ → R0D4xaIPl5kg93edN7Oo0}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RetryHandler tests — long-context entitlement 429 error handling (#2803)
|
|
3
|
+
*
|
|
4
|
+
* Verifies that "Extra usage is required for long context requests" errors
|
|
5
|
+
* are classified as quota_exhausted (not rate_limit) and trigger a model
|
|
6
|
+
* downgrade from [1m] to base when no cross-provider fallback exists.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { describe, it, beforeEach, mock, type Mock } from "node:test";
|
|
10
|
+
import assert from "node:assert/strict";
|
|
11
|
+
import { RetryHandler, type RetryHandlerDeps } from "./retry-handler.js";
|
|
12
|
+
import type { Api, AssistantMessage, Model } from "@gsd/pi-ai";
|
|
13
|
+
import type { FallbackResolver } from "./fallback-resolver.js";
|
|
14
|
+
import type { ModelRegistry } from "./model-registry.js";
|
|
15
|
+
import type { SettingsManager } from "./settings-manager.js";
|
|
16
|
+
|
|
17
|
+
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
18
|
+
|
|
19
|
+
function createMockModel(provider: string, id: string): Model<Api> {
|
|
20
|
+
return {
|
|
21
|
+
id,
|
|
22
|
+
name: id,
|
|
23
|
+
api: "anthropic" as Api,
|
|
24
|
+
provider,
|
|
25
|
+
baseUrl: "https://api.anthropic.com",
|
|
26
|
+
reasoning: false,
|
|
27
|
+
input: ["text"],
|
|
28
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
29
|
+
contextWindow: 1_000_000,
|
|
30
|
+
maxTokens: 16384,
|
|
31
|
+
} as Model<Api>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function errorMessage(msg: string): AssistantMessage {
|
|
35
|
+
return {
|
|
36
|
+
role: "assistant",
|
|
37
|
+
content: [],
|
|
38
|
+
api: "anthropic-messages",
|
|
39
|
+
provider: "anthropic",
|
|
40
|
+
model: "claude-opus-4-6[1m]",
|
|
41
|
+
usage: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, totalTokens: 0, cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 } },
|
|
42
|
+
stopReason: "error",
|
|
43
|
+
errorMessage: msg,
|
|
44
|
+
timestamp: Date.now(),
|
|
45
|
+
} as AssistantMessage;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
interface MockDeps {
|
|
49
|
+
deps: RetryHandlerDeps;
|
|
50
|
+
emittedEvents: Array<Record<string, any>>;
|
|
51
|
+
continueFn: Mock<() => Promise<void>>;
|
|
52
|
+
onModelChangeFn: Mock<(model: Model<any>) => void>;
|
|
53
|
+
markUsageLimitReached: Mock<(...args: any[]) => boolean>;
|
|
54
|
+
findFallback: Mock<(...args: any[]) => Promise<any>>;
|
|
55
|
+
findModel: Mock<(provider: string, modelId: string) => Model<Api> | undefined>;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function createMockDeps(overrides?: {
|
|
59
|
+
model?: Model<Api>;
|
|
60
|
+
retryEnabled?: boolean;
|
|
61
|
+
markUsageLimitReachedResult?: boolean;
|
|
62
|
+
fallbackResult?: any;
|
|
63
|
+
findModelResult?: (provider: string, modelId: string) => Model<Api> | undefined;
|
|
64
|
+
}): MockDeps {
|
|
65
|
+
const model = overrides?.model ?? createMockModel("anthropic", "claude-opus-4-6[1m]");
|
|
66
|
+
const emittedEvents: Array<Record<string, any>> = [];
|
|
67
|
+
const continueFn = mock.fn(async () => {});
|
|
68
|
+
const onModelChangeFn = mock.fn((_model: Model<any>) => {});
|
|
69
|
+
const markUsageLimitReached = mock.fn(
|
|
70
|
+
() => overrides?.markUsageLimitReachedResult ?? false,
|
|
71
|
+
);
|
|
72
|
+
const findFallback = mock.fn(async () => overrides?.fallbackResult ?? null);
|
|
73
|
+
const findModel = mock.fn(
|
|
74
|
+
overrides?.findModelResult ?? ((_provider: string, _modelId: string) => undefined),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const messages: Array<{ role: string } & Record<string, any>> = [];
|
|
78
|
+
|
|
79
|
+
const deps: RetryHandlerDeps = {
|
|
80
|
+
agent: {
|
|
81
|
+
continue: continueFn,
|
|
82
|
+
state: { messages },
|
|
83
|
+
setModel: mock.fn(),
|
|
84
|
+
replaceMessages: mock.fn((newMessages: any[]) => {
|
|
85
|
+
messages.length = 0;
|
|
86
|
+
messages.push(...newMessages);
|
|
87
|
+
}),
|
|
88
|
+
} as any,
|
|
89
|
+
settingsManager: {
|
|
90
|
+
getRetryEnabled: () => overrides?.retryEnabled ?? true,
|
|
91
|
+
getRetrySettings: () => ({
|
|
92
|
+
enabled: overrides?.retryEnabled ?? true,
|
|
93
|
+
maxRetries: 5,
|
|
94
|
+
baseDelayMs: 1000,
|
|
95
|
+
maxDelayMs: 30000,
|
|
96
|
+
}),
|
|
97
|
+
} as unknown as SettingsManager,
|
|
98
|
+
modelRegistry: {
|
|
99
|
+
authStorage: {
|
|
100
|
+
markUsageLimitReached,
|
|
101
|
+
},
|
|
102
|
+
find: findModel,
|
|
103
|
+
} as unknown as ModelRegistry,
|
|
104
|
+
fallbackResolver: {
|
|
105
|
+
findFallback,
|
|
106
|
+
} as unknown as FallbackResolver,
|
|
107
|
+
getModel: () => model,
|
|
108
|
+
getSessionId: () => "test-session",
|
|
109
|
+
emit: (event: any) => emittedEvents.push(event),
|
|
110
|
+
onModelChange: onModelChangeFn,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return { deps, emittedEvents, continueFn, onModelChangeFn, markUsageLimitReached, findFallback, findModel };
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// ─── _classifyErrorType (tested via handleRetryableError behavior) ──────────
|
|
117
|
+
|
|
118
|
+
describe("RetryHandler — long-context entitlement 429 (#2803)", () => {
|
|
119
|
+
|
|
120
|
+
describe("error classification", () => {
|
|
121
|
+
it("classifies 'Extra usage is required for long context requests' as quota_exhausted, not rate_limit", async () => {
|
|
122
|
+
// When the error is classified as quota_exhausted AND no alternate credentials
|
|
123
|
+
// AND no fallback, the handler should emit fallback_chain_exhausted and stop.
|
|
124
|
+
// If misclassified as rate_limit, it would enter the backoff loop instead.
|
|
125
|
+
const { deps, emittedEvents, findModel } = createMockDeps({
|
|
126
|
+
model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
|
|
127
|
+
markUsageLimitReachedResult: false, // no alternate credentials
|
|
128
|
+
fallbackResult: null, // no cross-provider fallback
|
|
129
|
+
findModelResult: () => undefined, // no base model either
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
const handler = new RetryHandler(deps);
|
|
133
|
+
const msg = errorMessage(
|
|
134
|
+
'429 {"type":"error","error":{"type":"rate_limit_error","message":"Extra usage is required for long context requests."}}'
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const result = await handler.handleRetryableError(msg);
|
|
138
|
+
|
|
139
|
+
// Should NOT retry (would be true if misclassified as rate_limit entering backoff)
|
|
140
|
+
assert.equal(result, false);
|
|
141
|
+
|
|
142
|
+
// Should emit fallback_chain_exhausted (quota_exhausted path), NOT auto_retry_start (backoff path)
|
|
143
|
+
const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
|
|
144
|
+
assert.ok(chainExhausted, "Expected fallback_chain_exhausted event for entitlement error");
|
|
145
|
+
|
|
146
|
+
const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
|
|
147
|
+
assert.equal(retryStart, undefined, "Should NOT emit auto_retry_start for entitlement error");
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("still classifies regular 429 rate limits as rate_limit", async () => {
|
|
151
|
+
// A normal "rate limit" 429 should still be classified as rate_limit
|
|
152
|
+
const { deps, emittedEvents } = createMockDeps({
|
|
153
|
+
model: createMockModel("anthropic", "claude-opus-4-6"),
|
|
154
|
+
markUsageLimitReachedResult: false,
|
|
155
|
+
fallbackResult: null,
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
const handler = new RetryHandler(deps);
|
|
159
|
+
const msg = errorMessage("429 Too Many Requests");
|
|
160
|
+
|
|
161
|
+
const result = await handler.handleRetryableError(msg);
|
|
162
|
+
|
|
163
|
+
// Should enter the backoff loop (rate_limit path, not quota_exhausted)
|
|
164
|
+
assert.equal(result, true);
|
|
165
|
+
|
|
166
|
+
const retryStart = emittedEvents.find((e) => e.type === "auto_retry_start");
|
|
167
|
+
assert.ok(retryStart, "Regular 429 should enter backoff retry");
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe("long-context model downgrade", () => {
|
|
172
|
+
it("downgrades from [1m] to base model when entitlement error and no fallback", async () => {
|
|
173
|
+
const baseModel = createMockModel("anthropic", "claude-opus-4-6");
|
|
174
|
+
const { deps, emittedEvents, onModelChangeFn, continueFn } = createMockDeps({
|
|
175
|
+
model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
|
|
176
|
+
markUsageLimitReachedResult: false,
|
|
177
|
+
fallbackResult: null,
|
|
178
|
+
findModelResult: (provider: string, modelId: string) => {
|
|
179
|
+
if (provider === "anthropic" && modelId === "claude-opus-4-6") return baseModel;
|
|
180
|
+
return undefined;
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const handler = new RetryHandler(deps);
|
|
185
|
+
const msg = errorMessage("Extra usage is required for long context requests.");
|
|
186
|
+
|
|
187
|
+
const result = await handler.handleRetryableError(msg);
|
|
188
|
+
|
|
189
|
+
assert.equal(result, true, "Should retry after downgrade");
|
|
190
|
+
|
|
191
|
+
// Should have called setModel with the base model
|
|
192
|
+
const setModelCalls = (deps.agent.setModel as any).mock.calls;
|
|
193
|
+
assert.equal(setModelCalls.length, 1);
|
|
194
|
+
assert.equal(setModelCalls[0].arguments[0].id, "claude-opus-4-6");
|
|
195
|
+
|
|
196
|
+
// Should have notified about model change
|
|
197
|
+
assert.equal(onModelChangeFn.mock.calls.length, 1);
|
|
198
|
+
|
|
199
|
+
// Should emit a fallback_provider_switch event indicating downgrade
|
|
200
|
+
const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
|
|
201
|
+
assert.ok(switchEvent, "Expected fallback_provider_switch event for downgrade");
|
|
202
|
+
assert.ok(switchEvent!.reason.includes("long context downgrade"), `reason should mention downgrade: ${switchEvent!.reason}`);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it("emits fallback_chain_exhausted when base model is also unavailable", async () => {
|
|
206
|
+
const { deps, emittedEvents } = createMockDeps({
|
|
207
|
+
model: createMockModel("anthropic", "claude-opus-4-6[1m]"),
|
|
208
|
+
markUsageLimitReachedResult: false,
|
|
209
|
+
fallbackResult: null,
|
|
210
|
+
findModelResult: () => undefined, // base model not found
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
const handler = new RetryHandler(deps);
|
|
214
|
+
const msg = errorMessage("Extra usage is required for long context requests.");
|
|
215
|
+
|
|
216
|
+
const result = await handler.handleRetryableError(msg);
|
|
217
|
+
|
|
218
|
+
assert.equal(result, false);
|
|
219
|
+
const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
|
|
220
|
+
assert.ok(chainExhausted, "Expected fallback_chain_exhausted when base model unavailable");
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
it("does not attempt downgrade for non-[1m] models", async () => {
|
|
224
|
+
// When a regular model (no [1m] suffix) gets a quota_exhausted error
|
|
225
|
+
// with no fallback, it should just stop — no downgrade attempt.
|
|
226
|
+
const { deps, emittedEvents } = createMockDeps({
|
|
227
|
+
model: createMockModel("anthropic", "claude-opus-4-6"),
|
|
228
|
+
markUsageLimitReachedResult: false,
|
|
229
|
+
fallbackResult: null,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
const handler = new RetryHandler(deps);
|
|
233
|
+
const msg = errorMessage("Extra usage is required for long context requests.");
|
|
234
|
+
|
|
235
|
+
const result = await handler.handleRetryableError(msg);
|
|
236
|
+
|
|
237
|
+
assert.equal(result, false);
|
|
238
|
+
const chainExhausted = emittedEvents.find((e) => e.type === "fallback_chain_exhausted");
|
|
239
|
+
assert.ok(chainExhausted);
|
|
240
|
+
|
|
241
|
+
// No downgrade switch should occur
|
|
242
|
+
const switchEvent = emittedEvents.find((e) => e.type === "fallback_provider_switch");
|
|
243
|
+
assert.equal(switchEvent, undefined, "Should not switch for non-[1m] models");
|
|
244
|
+
});
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
describe("isRetryableError", () => {
|
|
248
|
+
it("considers long-context entitlement error as retryable", () => {
|
|
249
|
+
const { deps } = createMockDeps();
|
|
250
|
+
const handler = new RetryHandler(deps);
|
|
251
|
+
const msg = errorMessage("Extra usage is required for long context requests.");
|
|
252
|
+
assert.equal(handler.isRetryableError(msg), true);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -107,7 +107,7 @@ export class RetryHandler {
|
|
|
107
107
|
if (isContextOverflow(message, contextWindow)) return false;
|
|
108
108
|
|
|
109
109
|
const err = message.errorMessage;
|
|
110
|
-
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|temporarily backed off/i.test(
|
|
110
|
+
return /overloaded|rate.?limit|too many requests|429|500|502|503|504|service.?unavailable|server.?error|internal.?error|connection.?error|connection.?refused|other side closed|fetch failed|upstream.?connect|reset before headers|terminated|retry delay|network.?(?:is\s+)?unavailable|credentials.*expired|temporarily backed off|extra usage is required/i.test(
|
|
111
111
|
err,
|
|
112
112
|
);
|
|
113
113
|
}
|
|
@@ -202,6 +202,10 @@ export class RetryHandler {
|
|
|
202
202
|
|
|
203
203
|
// No fallback available either
|
|
204
204
|
if (errorType === "quota_exhausted") {
|
|
205
|
+
// Try long-context model downgrade ([1m] → base) before giving up
|
|
206
|
+
const downgraded = this._tryLongContextDowngrade(message);
|
|
207
|
+
if (downgraded) return true;
|
|
208
|
+
|
|
205
209
|
this._deps.emit({
|
|
206
210
|
type: "fallback_chain_exhausted",
|
|
207
211
|
reason: `All providers exhausted for ${this._deps.getModel()!.provider}/${this._deps.getModel()!.id}`,
|
|
@@ -343,12 +347,59 @@ export class RetryHandler {
|
|
|
343
347
|
*/
|
|
344
348
|
private _classifyErrorType(errorMessage: string): UsageLimitErrorType {
|
|
345
349
|
const err = errorMessage.toLowerCase();
|
|
350
|
+
// Long-context entitlement errors are billing gates, not transient rate limits.
|
|
351
|
+
// Must be checked before the generic 429/rate_limit regex.
|
|
352
|
+
if (/extra usage is required|long context required/i.test(err)) return "quota_exhausted";
|
|
346
353
|
if (/quota|billing|exceeded.*limit|usage.*limit/i.test(err)) return "quota_exhausted";
|
|
347
354
|
if (/rate.?limit|too many requests|429/i.test(err)) return "rate_limit";
|
|
348
355
|
if (/500|502|503|504|server.?error|internal.?error|service.?unavailable/i.test(err)) return "server_error";
|
|
349
356
|
return "unknown";
|
|
350
357
|
}
|
|
351
358
|
|
|
359
|
+
/**
|
|
360
|
+
* Attempt to downgrade a long-context model (e.g. claude-opus-4-6[1m]) to its
|
|
361
|
+
* base model (claude-opus-4-6) when the account lacks the long-context billing
|
|
362
|
+
* entitlement. Returns true if the downgrade was initiated.
|
|
363
|
+
*/
|
|
364
|
+
private _tryLongContextDowngrade(message: AssistantMessage): boolean {
|
|
365
|
+
const currentModel = this._deps.getModel();
|
|
366
|
+
if (!currentModel) return false;
|
|
367
|
+
|
|
368
|
+
// Only attempt downgrade for [1m] (or similar long-context) model IDs
|
|
369
|
+
const match = currentModel.id.match(/^(.+)\[\d+m\]$/);
|
|
370
|
+
if (!match) return false;
|
|
371
|
+
|
|
372
|
+
const baseModelId = match[1];
|
|
373
|
+
const baseModel = this._deps.modelRegistry.find(currentModel.provider, baseModelId);
|
|
374
|
+
if (!baseModel) return false;
|
|
375
|
+
|
|
376
|
+
const previousId = currentModel.id;
|
|
377
|
+
this._deps.agent.setModel(baseModel);
|
|
378
|
+
this._deps.onModelChange(baseModel);
|
|
379
|
+
this._removeLastAssistantError();
|
|
380
|
+
|
|
381
|
+
this._deps.emit({
|
|
382
|
+
type: "fallback_provider_switch",
|
|
383
|
+
from: `${currentModel.provider}/${previousId}`,
|
|
384
|
+
to: `${baseModel.provider}/${baseModel.id}`,
|
|
385
|
+
reason: `long context downgrade: ${previousId} → ${baseModel.id}`,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
this._deps.emit({
|
|
389
|
+
type: "auto_retry_start",
|
|
390
|
+
attempt: this._retryAttempt + 1,
|
|
391
|
+
maxAttempts: this._deps.settingsManager.getRetrySettings().maxRetries,
|
|
392
|
+
delayMs: 0,
|
|
393
|
+
errorMessage: `${message.errorMessage} (long context downgrade)`,
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
setTimeout(() => {
|
|
397
|
+
this._deps.agent.continue().catch(() => {});
|
|
398
|
+
}, 0);
|
|
399
|
+
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
|
|
352
403
|
/** Remove the last assistant error message from agent state */
|
|
353
404
|
private _removeLastAssistantError(): void {
|
|
354
405
|
const messages = this._deps.agent.state.messages;
|
|
@@ -123,12 +123,15 @@ export function createHashlineReadTool(cwd: string, options?: HashlineReadToolOp
|
|
|
123
123
|
const allLines = textContent.split("\n");
|
|
124
124
|
const totalFileLines = allLines.length;
|
|
125
125
|
|
|
126
|
-
|
|
127
|
-
const startLineDisplay = startLine + 1;
|
|
126
|
+
let startLine = offset ? Math.max(0, offset - 1) : 0;
|
|
128
127
|
|
|
128
|
+
// Clamp offset to file bounds instead of throwing (#3007)
|
|
129
|
+
let offsetClamped = false;
|
|
129
130
|
if (startLine >= allLines.length) {
|
|
130
|
-
|
|
131
|
+
startLine = Math.max(0, allLines.length - 1);
|
|
132
|
+
offsetClamped = true;
|
|
131
133
|
}
|
|
134
|
+
const startLineDisplay = startLine + 1;
|
|
132
135
|
|
|
133
136
|
let selectedContent: string;
|
|
134
137
|
let userLimitedLines: number | undefined;
|
|
@@ -172,6 +175,11 @@ export function createHashlineReadTool(cwd: string, options?: HashlineReadToolOp
|
|
|
172
175
|
outputText = formatHashLines(truncation.content, startLineDisplay);
|
|
173
176
|
}
|
|
174
177
|
|
|
178
|
+
// Prepend clamp notice so the agent knows offset was adjusted
|
|
179
|
+
if (offsetClamped) {
|
|
180
|
+
outputText = `[Offset ${offset} beyond end of file (${totalFileLines} lines). Clamped to line ${startLineDisplay}.]\n\n${outputText}`;
|
|
181
|
+
}
|
|
182
|
+
|
|
175
183
|
content = [{ type: "text", text: outputText }];
|
|
176
184
|
}
|
|
177
185
|
|
|
@@ -133,13 +133,18 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo
|
|
|
133
133
|
const totalFileLines = allLines.length;
|
|
134
134
|
|
|
135
135
|
// Apply offset if specified (1-indexed to 0-indexed)
|
|
136
|
-
|
|
137
|
-
const startLineDisplay = startLine + 1; // For display (1-indexed)
|
|
136
|
+
let startLine = offset ? Math.max(0, offset - 1) : 0;
|
|
138
137
|
|
|
139
|
-
//
|
|
138
|
+
// Clamp offset to file bounds instead of throwing (#3007).
|
|
139
|
+
// When an agent requests offset:30 on a 13-line file, return
|
|
140
|
+
// the last line with a notice rather than an error that
|
|
141
|
+
// propagates as invalid JSON downstream.
|
|
142
|
+
let offsetClamped = false;
|
|
140
143
|
if (startLine >= allLines.length) {
|
|
141
|
-
|
|
144
|
+
startLine = Math.max(0, allLines.length - 1);
|
|
145
|
+
offsetClamped = true;
|
|
142
146
|
}
|
|
147
|
+
const startLineDisplay = startLine + 1; // For display (1-indexed)
|
|
143
148
|
|
|
144
149
|
// If limit is specified by user, use it; otherwise we'll let truncateHead decide
|
|
145
150
|
let selectedContent: string;
|
|
@@ -187,6 +192,11 @@ export function createReadTool(cwd: string, options?: ReadToolOptions): AgentToo
|
|
|
187
192
|
outputText = truncation.content;
|
|
188
193
|
}
|
|
189
194
|
|
|
195
|
+
// Prepend clamp notice so the agent knows offset was adjusted
|
|
196
|
+
if (offsetClamped) {
|
|
197
|
+
outputText = `[Offset ${offset} beyond end of file (${totalFileLines} lines). Clamped to line ${startLineDisplay}.]\n\n${outputText}`;
|
|
198
|
+
}
|
|
199
|
+
|
|
190
200
|
content = [{ type: "text", text: outputText }];
|
|
191
201
|
}
|
|
192
202
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* spawn-shell-windows.test.ts — Regression test for Windows spawn ENOENT/EINVAL.
|
|
3
|
+
*
|
|
4
|
+
* On Windows, npm/npx/tsc and other tools are installed as .cmd batch scripts.
|
|
5
|
+
* Node's `spawn()` without `shell: true` cannot execute .cmd files, resulting
|
|
6
|
+
* in ENOENT or EINVAL errors. Every spawn site that may invoke a user-installed
|
|
7
|
+
* binary (not `node` or a shell like `sh`/`bash`/`cmd`) must include
|
|
8
|
+
* `shell: process.platform === "win32"` so the call is resolved through cmd.exe
|
|
9
|
+
* on Windows while remaining a direct exec on POSIX.
|
|
10
|
+
*
|
|
11
|
+
* This test structurally scans all spawn sites and verifies the guard is present.
|
|
12
|
+
*
|
|
13
|
+
* Fixes: gsd-build/gsd-2#2854
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import test from "node:test";
|
|
17
|
+
import assert from "node:assert/strict";
|
|
18
|
+
import { readFileSync } from "node:fs";
|
|
19
|
+
import { join, dirname, relative } from "node:path";
|
|
20
|
+
import { fileURLToPath } from "node:url";
|
|
21
|
+
|
|
22
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const coreDir = join(__dirname, "..");
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Files that call `spawn()` with a user-facing binary (not `node`, `sh`, `bash`,
|
|
27
|
+
* or `cmd`) and therefore need the Windows shell guard.
|
|
28
|
+
*
|
|
29
|
+
* If a file spawns only hardcoded system binaries (like `node` in rpc-client.ts),
|
|
30
|
+
* it does not need the guard and should NOT appear here.
|
|
31
|
+
*/
|
|
32
|
+
const SPAWN_FILES_NEEDING_SHELL_GUARD = [
|
|
33
|
+
// Extension's GSD client — spawns the `gsd` binary which is a .cmd on Windows
|
|
34
|
+
join(coreDir, "..", "..", "..", "vscode-extension", "src", "gsd-client.ts"),
|
|
35
|
+
// exec.ts — used by extensions to run arbitrary commands
|
|
36
|
+
join(coreDir, "exec.ts"),
|
|
37
|
+
// LSP index — spawns project-type commands (tsc, cargo, etc.)
|
|
38
|
+
join(coreDir, "lsp", "index.ts"),
|
|
39
|
+
// LSP client — spawns LSP server binaries (npx, etc.)
|
|
40
|
+
join(coreDir, "lsp", "client.ts"),
|
|
41
|
+
// LSP mux — spawns lspmux binary
|
|
42
|
+
join(coreDir, "lsp", "lspmux.ts"),
|
|
43
|
+
// Package manager — spawns npm/yarn/pnpm
|
|
44
|
+
join(coreDir, "package-manager.ts"),
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
test("all spawn sites that invoke user-facing binaries include shell: process.platform === 'win32'", () => {
|
|
48
|
+
const failures: string[] = [];
|
|
49
|
+
|
|
50
|
+
for (const file of SPAWN_FILES_NEEDING_SHELL_GUARD) {
|
|
51
|
+
let content: string;
|
|
52
|
+
try {
|
|
53
|
+
content = readFileSync(file, "utf-8");
|
|
54
|
+
} catch {
|
|
55
|
+
// File may not exist in this checkout — skip
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const lines = content.split("\n");
|
|
60
|
+
|
|
61
|
+
// Find all spawn(..., { ... }) call sites and check each one
|
|
62
|
+
// for the presence of `shell: process.platform === "win32"` within
|
|
63
|
+
// 5 lines after the spawn call.
|
|
64
|
+
for (let i = 0; i < lines.length; i++) {
|
|
65
|
+
const line = lines[i]!;
|
|
66
|
+
// Skip comments
|
|
67
|
+
if (line.trim().startsWith("//") || line.trim().startsWith("*")) continue;
|
|
68
|
+
|
|
69
|
+
// Detect a spawn() call
|
|
70
|
+
if (/\bspawn\(/.test(line)) {
|
|
71
|
+
// Look ahead up to 8 lines for the shell guard
|
|
72
|
+
const lookahead = lines.slice(i, i + 8).join("\n");
|
|
73
|
+
const hasShellGuard =
|
|
74
|
+
/shell:\s*process\.platform\s*===\s*["']win32["']/.test(lookahead);
|
|
75
|
+
|
|
76
|
+
if (!hasShellGuard) {
|
|
77
|
+
const relPath = relative(join(coreDir, "..", ".."), file);
|
|
78
|
+
failures.push(`${relPath}:${i + 1}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
assert.deepEqual(
|
|
85
|
+
failures,
|
|
86
|
+
[],
|
|
87
|
+
`The following spawn sites are missing 'shell: process.platform === "win32"':\n` +
|
|
88
|
+
failures.map(f => ` - ${f}`).join("\n") +
|
|
89
|
+
`\nOn Windows, .cmd wrapper scripts (npm, npx, tsc, gsd) require shell ` +
|
|
90
|
+
`resolution. Without this guard, spawn fails with ENOENT or EINVAL.`,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
@@ -68,6 +68,7 @@ export type {
|
|
|
68
68
|
Extension,
|
|
69
69
|
ExtensionActions,
|
|
70
70
|
ExtensionAPI,
|
|
71
|
+
ExtensionManifest,
|
|
71
72
|
ExtensionCommandContext,
|
|
72
73
|
ExtensionCommandContextActions,
|
|
73
74
|
ExtensionContext,
|
|
@@ -119,6 +120,8 @@ export type {
|
|
|
119
120
|
ToolCallEvent,
|
|
120
121
|
ToolDefinition,
|
|
121
122
|
ToolInfo,
|
|
123
|
+
SortResult,
|
|
124
|
+
SortWarning,
|
|
122
125
|
ToolRenderResultOptions,
|
|
123
126
|
ToolResultEvent,
|
|
124
127
|
TurnEndEvent,
|
|
@@ -137,6 +140,9 @@ export {
|
|
|
137
140
|
importExtensionModule,
|
|
138
141
|
isToolCallEventType,
|
|
139
142
|
isToolResultEventType,
|
|
143
|
+
readManifest,
|
|
144
|
+
readManifestFromEntryPath,
|
|
145
|
+
sortExtensionPaths,
|
|
140
146
|
wrapRegisteredTool,
|
|
141
147
|
wrapRegisteredTools,
|
|
142
148
|
wrapToolsWithExtensions,
|
|
@@ -337,5 +337,12 @@ export async function handleAgentEvent(host: InteractiveModeStateHost & {
|
|
|
337
337
|
host.showError(event.reason);
|
|
338
338
|
host.ui.requestRender();
|
|
339
339
|
break;
|
|
340
|
+
|
|
341
|
+
case "image_overflow_recovery":
|
|
342
|
+
host.showStatus(
|
|
343
|
+
`Removed ${event.strippedCount} older image(s) to comply with API limits. Retrying...`,
|
|
344
|
+
);
|
|
345
|
+
host.ui.requestRender();
|
|
346
|
+
break;
|
|
340
347
|
}
|
|
341
348
|
}
|
|
@@ -49,6 +49,12 @@ export class RemoteTerminal implements Terminal {
|
|
|
49
49
|
return this._rows;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
get isTTY(): boolean {
|
|
53
|
+
// RemoteTerminal renders to a browser-based terminal emulator via
|
|
54
|
+
// the RPC bridge — it behaves like a real TTY for rendering purposes.
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
|
|
52
58
|
get kittyProtocolActive(): boolean {
|
|
53
59
|
return false;
|
|
54
60
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Minimal terminal interface for TUI
|
|
3
3
|
*/
|
|
4
4
|
export interface Terminal {
|
|
5
|
+
readonly isTTY: boolean;
|
|
5
6
|
start(onInput: (data: string) => void, onResize: () => void): void;
|
|
6
7
|
stop(): void;
|
|
7
8
|
/**
|
|
@@ -36,6 +37,7 @@ export declare class ProcessTerminal implements Terminal {
|
|
|
36
37
|
private stdinBuffer?;
|
|
37
38
|
private stdinDataHandler?;
|
|
38
39
|
private writeLogPath;
|
|
40
|
+
get isTTY(): boolean;
|
|
39
41
|
get kittyProtocolActive(): boolean;
|
|
40
42
|
start(onInput: (data: string) => void, onResize: () => void): void;
|
|
41
43
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,QAAQ;IAExB,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAGnE,IAAI,IAAI,IAAI,CAAC;IAEb;;;;;OAKG;IACH,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IAGnB,IAAI,mBAAmB,IAAI,OAAO,CAAC;IAGnC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;IAGnB,SAAS,IAAI,IAAI,CAAC;IAClB,eAAe,IAAI,IAAI,CAAC;IACxB,WAAW,IAAI,IAAI,CAAC;IAGpB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC/C,OAAO,CAAC,MAAM,CAAC,UAAU,CAA0E;IACnG,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,gBAAgB,CAAC,CAAyB;IAClD,OAAO,CAAC,YAAY,CAAsC;IAE1D,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","sourceRoot":"","sources":["../src/terminal.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,QAAQ;IAExB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAGxB,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAGnE,IAAI,IAAI,IAAI,CAAC;IAEb;;;;;OAKG;IACH,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAG3D,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAG1B,IAAI,OAAO,IAAI,MAAM,CAAC;IACtB,IAAI,IAAI,IAAI,MAAM,CAAC;IAGnB,IAAI,mBAAmB,IAAI,OAAO,CAAC;IAGnC,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,UAAU,IAAI,IAAI,CAAC;IACnB,UAAU,IAAI,IAAI,CAAC;IAGnB,SAAS,IAAI,IAAI,CAAC;IAClB,eAAe,IAAI,IAAI,CAAC;IACxB,WAAW,IAAI,IAAI,CAAC;IAGpB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,QAAQ;IAC/C,OAAO,CAAC,MAAM,CAAC,UAAU,CAA0E;IACnG,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,YAAY,CAAC,CAAyB;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAa;IACnC,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,sBAAsB,CAAS;IACvC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,gBAAgB,CAAC,CAAyB;IAClD,OAAO,CAAC,YAAY,CAAsC;IAE1D,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED,IAAI,mBAAmB,IAAI,OAAO,CAEjC;IAED,KAAK,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI;IA2ClE;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;IA8CxB;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,2BAA2B;IAYnC;;;;;OAKG;IACH,OAAO,CAAC,oBAAoB;IAyBtB,UAAU,CAAC,KAAK,SAAO,EAAE,MAAM,SAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAsC1D,IAAI,IAAI,IAAI;IA2CZ,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAWzB,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAW3B,UAAU,IAAI,IAAI;IAIlB,UAAU,IAAI,IAAI;IAIlB,SAAS,IAAI,IAAI;IAIjB,eAAe,IAAI,IAAI;IAIvB,WAAW,IAAI,IAAI;IAInB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;CAI7B"}
|
|
@@ -14,10 +14,19 @@ export class ProcessTerminal {
|
|
|
14
14
|
this.writeLogPath = process.env.PI_TUI_WRITE_LOG || "";
|
|
15
15
|
}
|
|
16
16
|
static { this._vtHandles = null; }
|
|
17
|
+
get isTTY() {
|
|
18
|
+
return !!process.stdout.isTTY;
|
|
19
|
+
}
|
|
17
20
|
get kittyProtocolActive() {
|
|
18
21
|
return this._kittyProtocolActive;
|
|
19
22
|
}
|
|
20
23
|
start(onInput, onResize) {
|
|
24
|
+
// Non-TTY stdout (pipe) — skip TUI initialization entirely.
|
|
25
|
+
// RPC bridge processes communicate via JSON, not terminal escape codes.
|
|
26
|
+
// Without this guard, the render loop burns 500%+ CPU. (issue #3095)
|
|
27
|
+
if (!this.isTTY) {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
21
30
|
this.inputHandler = onInput;
|
|
22
31
|
this.resizeHandler = onResize;
|
|
23
32
|
// Save previous state and enable raw mode
|