gsd-pi 2.76.0 → 2.77.0
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 +45 -25
- package/dist/claude-cli-check.js +32 -3
- package/dist/mcp-server.d.ts +7 -0
- package/dist/mcp-server.js +35 -1
- package/dist/onboarding.js +45 -0
- package/dist/resource-loader.d.ts +1 -1
- package/dist/resource-loader.js +2 -8
- package/dist/resources/agents/researcher.md +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +31 -8
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +77 -17
- package/dist/resources/extensions/gsd/auto/loop.js +9 -0
- package/dist/resources/extensions/gsd/auto/phases.js +104 -11
- package/dist/resources/extensions/gsd/auto/run-unit.js +38 -2
- package/dist/resources/extensions/gsd/auto/session.js +22 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -3
- package/dist/resources/extensions/gsd/auto-model-selection.js +53 -16
- package/dist/resources/extensions/gsd/auto-post-unit.js +25 -2
- package/dist/resources/extensions/gsd/auto-prompts.js +14 -0
- package/dist/resources/extensions/gsd/auto-recovery.js +32 -1
- package/dist/resources/extensions/gsd/auto-start.js +58 -57
- package/dist/resources/extensions/gsd/auto-verification.js +33 -0
- package/dist/resources/extensions/gsd/auto-worktree.js +51 -53
- package/dist/resources/extensions/gsd/auto.js +70 -28
- package/dist/resources/extensions/gsd/blocked-models.js +68 -0
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +93 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +39 -9
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +93 -0
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +3 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +12 -0
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +52 -6
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +84 -23
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +34 -2
- package/dist/resources/extensions/gsd/clean-root-preflight.js +93 -0
- package/dist/resources/extensions/gsd/commands-extract-learnings.js +54 -89
- package/dist/resources/extensions/gsd/commands-prefs-wizard.js +968 -23
- package/dist/resources/extensions/gsd/compaction-snapshot.js +121 -0
- package/dist/resources/extensions/gsd/complexity-classifier.js +5 -3
- package/dist/resources/extensions/gsd/db-writer.js +88 -16
- package/dist/resources/extensions/gsd/doctor-git-checks.js +23 -29
- package/dist/resources/extensions/gsd/doctor-providers.js +51 -5
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +1 -0
- package/dist/resources/extensions/gsd/error-classifier.js +31 -3
- package/dist/resources/extensions/gsd/exec-history.js +120 -0
- package/dist/resources/extensions/gsd/exec-sandbox.js +258 -0
- package/dist/resources/extensions/gsd/gitignore.js +1 -0
- package/dist/resources/extensions/gsd/gsd-db.js +168 -23
- package/dist/resources/extensions/gsd/guided-flow.js +190 -1
- package/dist/resources/extensions/gsd/health-widget.js +4 -1
- package/dist/resources/extensions/gsd/hook-emitter.js +108 -0
- package/dist/resources/extensions/gsd/init-wizard.js +15 -1
- package/dist/resources/extensions/gsd/key-manager.js +28 -0
- package/dist/resources/extensions/gsd/memory-backfill.js +126 -0
- package/dist/resources/extensions/gsd/memory-store.js +19 -0
- package/dist/resources/extensions/gsd/model-router.js +36 -3
- package/dist/resources/extensions/gsd/pre-execution-checks.js +44 -9
- package/dist/resources/extensions/gsd/preferences-types.js +9 -0
- package/dist/resources/extensions/gsd/preferences-validation.js +83 -0
- package/dist/resources/extensions/gsd/preferences.js +17 -17
- package/dist/resources/extensions/gsd/prompt-loader.js +22 -7
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/dist/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/dist/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +96 -0
- package/dist/resources/extensions/gsd/safety/file-change-validator.js +13 -5
- package/dist/resources/extensions/gsd/safety/safety-harness.js +5 -1
- package/dist/resources/extensions/gsd/state.js +43 -4
- package/dist/resources/extensions/gsd/token-counter.js +22 -5
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +16 -10
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +59 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +126 -0
- package/dist/resources/extensions/gsd/tools/memory-tools.js +26 -1
- package/dist/resources/extensions/gsd/tools/resume-tool.js +23 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +20 -3
- package/dist/resources/extensions/gsd/workflow-mcp.js +3 -0
- package/dist/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +50 -10
- package/dist/resources/extensions/search-the-web/command-search-provider.js +5 -4
- package/dist/resources/extensions/search-the-web/native-search.js +45 -13
- package/dist/resources/skills/api-design/SKILL.md +190 -0
- package/dist/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/dist/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/dist/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/dist/resources/skills/design-an-interface/SKILL.md +102 -0
- package/dist/resources/skills/forensics/SKILL.md +153 -0
- package/dist/resources/skills/grill-me/SKILL.md +93 -0
- package/dist/resources/skills/handoff/SKILL.md +121 -0
- package/dist/resources/skills/observability/SKILL.md +174 -0
- package/dist/resources/skills/security-review/SKILL.md +181 -0
- package/dist/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/dist/resources/skills/tdd/SKILL.md +112 -0
- package/dist/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/dist/resources/skills/write-docs/SKILL.md +82 -0
- package/dist/resources/skills/write-milestone-brief/SKILL.md +135 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +10 -10
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- 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 +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +10 -10
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.js +6 -1
- package/dist/wizard.js +2 -0
- package/package.json +1 -1
- package/packages/daemon/package.json +2 -2
- package/packages/mcp-server/dist/remote-questions.d.ts +45 -0
- package/packages/mcp-server/dist/remote-questions.d.ts.map +1 -0
- package/packages/mcp-server/dist/remote-questions.js +732 -0
- package/packages/mcp-server/dist/remote-questions.js.map +1 -0
- package/packages/mcp-server/dist/server.d.ts +7 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +70 -8
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/session-manager.d.ts +14 -0
- package/packages/mcp-server/dist/session-manager.d.ts.map +1 -1
- package/packages/mcp-server/dist/session-manager.js +49 -1
- package/packages/mcp-server/dist/session-manager.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +163 -25
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +4 -3
- package/packages/mcp-server/src/mcp-server.test.ts +67 -0
- package/packages/mcp-server/src/remote-questions.test.ts +294 -0
- package/packages/mcp-server/src/remote-questions.ts +916 -0
- package/packages/mcp-server/src/server.ts +89 -14
- package/packages/mcp-server/src/session-manager.ts +43 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +146 -1
- package/packages/mcp-server/src/workflow-tools.ts +215 -43
- package/packages/mcp-server/tsconfig.test.json +19 -0
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +12 -0
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/types.d.ts +30 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.ts +14 -0
- package/packages/pi-agent-core/src/types.ts +34 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/custom.d.ts +38 -0
- package/packages/pi-ai/dist/models/custom.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/custom.js +41 -0
- package/packages/pi-ai/dist/models/custom.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js +1 -1
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +13 -0
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/anthropic-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-shared.js +27 -4
- package/packages/pi-ai/dist/providers/anthropic-shared.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +13 -4
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +80 -0
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -0
- package/packages/pi-ai/dist/providers/openai-completions.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-completions.js +60 -15
- package/packages/pi-ai/dist/providers/openai-completions.js.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.d.ts +10 -0
- package/packages/pi-ai/dist/providers/simple-options.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/simple-options.js +16 -1
- package/packages/pi-ai/dist/providers/simple-options.js.map +1 -1
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts +17 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js +75 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.js.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts +2 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js +41 -0
- package/packages/pi-ai/dist/providers/think-tag-parser.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/github-copilot.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js +12 -2
- package/packages/pi-ai/dist/utils/oauth/github-copilot.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +164 -14
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js +15 -3
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.d.ts.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js +16 -3
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +67 -0
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +2 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +1 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +289 -0
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +1 -0
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/src/models/custom.ts +42 -0
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +1 -1
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -0
- package/packages/pi-ai/src/providers/anthropic-shared.ts +26 -5
- package/packages/pi-ai/src/providers/anthropic.ts +15 -4
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +98 -0
- package/packages/pi-ai/src/providers/openai-completions.ts +57 -16
- package/packages/pi-ai/src/providers/simple-options.ts +17 -1
- package/packages/pi-ai/src/providers/think-tag-parser.test.ts +44 -0
- package/packages/pi-ai/src/providers/think-tag-parser.ts +94 -0
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +200 -23
- package/packages/pi-ai/src/utils/oauth/github-copilot.ts +12 -2
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-antigravity.ts +15 -5
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +84 -0
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.ts +16 -5
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +363 -0
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +3 -2
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +2 -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 +32 -2
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +4 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +35 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +233 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +205 -2
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts +53 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js +337 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +234 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts +3 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.js +92 -12
- package/packages/pi-coding-agent/dist/core/model-discovery.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js +16 -1
- package/packages/pi-coding-agent/dist/core/model-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js +40 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-header.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js +203 -0
- package/packages/pi-coding-agent/dist/core/model-registry-custom-caps.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js +61 -1
- package/packages/pi-coding-agent/dist/core/model-registry-discovery.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/model-registry.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry.js +90 -10
- package/packages/pi-coding-agent/dist/core/model-registry.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js +49 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js +67 -0
- package/packages/pi-coding-agent/dist/core/redact-secrets.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/session-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.js +10 -6
- package/packages/pi-coding-agent/dist/core/session-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +45 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +55 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js +5 -4
- package/packages/pi-coding-agent/dist/modes/interactive/components/chat-frame.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js +13 -7
- package/packages/pi-coding-agent/dist/modes/interactive/components/provider-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts +7 -6
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js +29 -21
- package/packages/pi-coding-agent/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +13 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +3 -2
- package/packages/pi-coding-agent/src/core/agent-session.ts +38 -2
- package/packages/pi-coding-agent/src/core/extensions/index.ts +16 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +5 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +351 -0
- package/packages/pi-coding-agent/src/core/extensions/types.ts +258 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +269 -0
- package/packages/pi-coding-agent/src/core/hooks-runner.ts +460 -0
- package/packages/pi-coding-agent/src/core/index.ts +10 -0
- package/packages/pi-coding-agent/src/core/model-discovery.test.ts +19 -0
- package/packages/pi-coding-agent/src/core/model-discovery.ts +99 -12
- package/packages/pi-coding-agent/src/core/model-registry-auth-header.test.ts +44 -0
- package/packages/pi-coding-agent/src/core/model-registry-custom-caps.test.ts +245 -0
- package/packages/pi-coding-agent/src/core/model-registry-discovery.test.ts +75 -0
- package/packages/pi-coding-agent/src/core/model-registry.ts +102 -10
- package/packages/pi-coding-agent/src/core/redact-secrets.test.ts +86 -0
- package/packages/pi-coding-agent/src/core/redact-secrets.ts +58 -0
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +65 -1
- package/packages/pi-coding-agent/src/core/session-manager.ts +10 -6
- package/packages/pi-coding-agent/src/core/settings-manager.ts +57 -0
- package/packages/pi-coding-agent/src/index.ts +16 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/chat-frame.ts +6 -6
- package/packages/pi-coding-agent/src/modes/interactive/components/provider-manager.ts +16 -7
- package/packages/pi-coding-agent/src/modes/interactive/components/skill-invocation-message.ts +36 -22
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +13 -1
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/pkg/package.json +1 -1
- package/scripts/link-workspace-packages.cjs +1 -0
- package/src/resources/agents/researcher.md +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +32 -8
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +78 -17
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +149 -5
- package/src/resources/extensions/gsd/auto/loop-deps.ts +14 -0
- package/src/resources/extensions/gsd/auto/loop.ts +9 -0
- package/src/resources/extensions/gsd/auto/phases.ts +131 -10
- package/src/resources/extensions/gsd/auto/run-unit.ts +40 -2
- package/src/resources/extensions/gsd/auto/session.ts +35 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -3
- package/src/resources/extensions/gsd/auto-model-selection.ts +71 -15
- package/src/resources/extensions/gsd/auto-post-unit.ts +29 -3
- package/src/resources/extensions/gsd/auto-prompts.ts +28 -1
- package/src/resources/extensions/gsd/auto-recovery.ts +26 -1
- package/src/resources/extensions/gsd/auto-start.ts +60 -68
- package/src/resources/extensions/gsd/auto-verification.ts +33 -0
- package/src/resources/extensions/gsd/auto-worktree.ts +62 -63
- package/src/resources/extensions/gsd/auto.ts +73 -28
- package/src/resources/extensions/gsd/blocked-models.ts +98 -0
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +120 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +40 -9
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +109 -0
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +15 -0
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +54 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +89 -26
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +35 -2
- package/src/resources/extensions/gsd/clean-root-preflight.ts +111 -0
- package/src/resources/extensions/gsd/commands-extract-learnings.ts +55 -90
- package/src/resources/extensions/gsd/commands-prefs-wizard.ts +898 -32
- package/src/resources/extensions/gsd/compaction-snapshot.ts +165 -0
- package/src/resources/extensions/gsd/complexity-classifier.ts +5 -3
- package/src/resources/extensions/gsd/db-writer.ts +88 -17
- package/src/resources/extensions/gsd/doctor-git-checks.ts +23 -27
- package/src/resources/extensions/gsd/doctor-providers.ts +59 -6
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +2 -0
- package/src/resources/extensions/gsd/error-classifier.ts +36 -3
- package/src/resources/extensions/gsd/exec-history.ts +153 -0
- package/src/resources/extensions/gsd/exec-sandbox.ts +326 -0
- package/src/resources/extensions/gsd/gitignore.ts +1 -1
- package/src/resources/extensions/gsd/gsd-db.ts +186 -23
- package/src/resources/extensions/gsd/guided-flow.ts +222 -1
- package/src/resources/extensions/gsd/health-widget.ts +3 -1
- package/src/resources/extensions/gsd/hook-emitter.ts +188 -0
- package/src/resources/extensions/gsd/init-wizard.ts +15 -1
- package/src/resources/extensions/gsd/journal.ts +2 -1
- package/src/resources/extensions/gsd/key-manager.ts +28 -0
- package/src/resources/extensions/gsd/memory-backfill.ts +140 -0
- package/src/resources/extensions/gsd/memory-store.ts +26 -0
- package/src/resources/extensions/gsd/model-router.ts +42 -1
- package/src/resources/extensions/gsd/pre-execution-checks.ts +46 -10
- package/src/resources/extensions/gsd/preferences-types.ts +46 -0
- package/src/resources/extensions/gsd/preferences-validation.ts +79 -0
- package/src/resources/extensions/gsd/preferences.ts +17 -17
- package/src/resources/extensions/gsd/prompt-loader.ts +30 -7
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +1 -1
- package/src/resources/extensions/gsd/prompts/complete-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/debug-diagnose.md +2 -0
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +8 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +29 -2
- package/src/resources/extensions/gsd/prompts/execute-task.md +3 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +5 -2
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -0
- package/src/resources/extensions/gsd/prompts/research-slice.md +1 -0
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +119 -0
- package/src/resources/extensions/gsd/safety/file-change-validator.ts +17 -4
- package/src/resources/extensions/gsd/safety/safety-harness.ts +9 -0
- package/src/resources/extensions/gsd/state.ts +45 -4
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +188 -2
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +95 -1
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +141 -0
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +33 -3
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +38 -0
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/blocked-models.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/bundled-skill-triggers.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/commands-extract-learnings.test.ts +68 -66
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +123 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/complexity-classifier.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +2 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/derive-state-helpers.test.ts +8 -4
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +148 -3
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +306 -1
- package/src/resources/extensions/gsd/tests/escalation.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +237 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/file-change-validator.test.ts +58 -0
- package/src/resources/extensions/gsd/tests/flat-rate-routing-guard.test.ts +40 -9
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +62 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +447 -1
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git-symlink-cwd.test.ts +11 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-git.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/gitignore-tracked-gsd.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/integration/idle-recovery.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/issue-4540-regressions.test.ts +288 -0
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/load-memory-block.test.ts +36 -0
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/plan-gate-failed-doctor-heal-hint.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/pre-exec-gate-loop.test.ts +272 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +356 -0
- package/src/resources/extensions/gsd/tests/preferences.test.ts +110 -0
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/prompt-loader-extension-dir.test.ts +49 -0
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +103 -4
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +388 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/safety-harness-false-positives.test.ts +205 -0
- package/src/resources/extensions/gsd/tests/save-gate-result-render.test.ts +95 -0
- package/src/resources/extensions/gsd/tests/schema-v21-sequence.test.ts +413 -0
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +32 -40
- package/src/resources/extensions/gsd/tests/stash-queued-context-files.test.ts +56 -0
- package/src/resources/extensions/gsd/tests/token-counter.test.ts +105 -1
- package/src/resources/extensions/gsd/tests/tool-compatibility.test.ts +107 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +65 -2
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +35 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +78 -5
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +3 -1
- package/src/resources/extensions/gsd/token-counter.ts +22 -5
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +15 -9
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +81 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +183 -0
- package/src/resources/extensions/gsd/tools/memory-tools.ts +31 -1
- package/src/resources/extensions/gsd/tools/resume-tool.ts +40 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +26 -3
- package/src/resources/extensions/gsd/workflow-logger.ts +4 -1
- package/src/resources/extensions/gsd/workflow-mcp.ts +3 -0
- package/src/resources/extensions/gsd/workflow-templates/spike.md +6 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +54 -9
- package/src/resources/extensions/search-the-web/command-search-provider.ts +5 -4
- package/src/resources/extensions/search-the-web/native-search.ts +48 -12
- package/src/resources/skills/api-design/SKILL.md +190 -0
- package/src/resources/skills/create-mcp-server/SKILL.md +121 -0
- package/src/resources/skills/decompose-into-slices/SKILL.md +139 -0
- package/src/resources/skills/dependency-upgrade/SKILL.md +158 -0
- package/src/resources/skills/design-an-interface/SKILL.md +102 -0
- package/src/resources/skills/forensics/SKILL.md +153 -0
- package/src/resources/skills/grill-me/SKILL.md +93 -0
- package/src/resources/skills/handoff/SKILL.md +121 -0
- package/src/resources/skills/observability/SKILL.md +174 -0
- package/src/resources/skills/security-review/SKILL.md +181 -0
- package/src/resources/skills/spike-wrap-up/SKILL.md +138 -0
- package/src/resources/skills/tdd/SKILL.md +112 -0
- package/src/resources/skills/verify-before-complete/SKILL.md +98 -0
- package/src/resources/skills/write-docs/SKILL.md +82 -0
- package/src/resources/skills/write-milestone-brief/SKILL.md +135 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{ssX7BLv3Dw9Fb4CtrCGeR → pV-mPo7rYGb5JBC09C8GG}/_ssgManifest.js +0 -0
|
@@ -126,8 +126,9 @@ import {
|
|
|
126
126
|
formatTokenCount,
|
|
127
127
|
} from "./metrics.js";
|
|
128
128
|
import { setLogBasePath, logWarning, logError } from "./workflow-logger.js";
|
|
129
|
+
import { preflightCleanRoot, postflightPopStash } from "./clean-root-preflight.js";
|
|
129
130
|
import { homedir } from "node:os";
|
|
130
|
-
import { join } from "node:path";
|
|
131
|
+
import { isAbsolute, join } from "node:path";
|
|
131
132
|
import { pathToFileURL } from "node:url";
|
|
132
133
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
|
|
133
134
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
@@ -182,7 +183,6 @@ import {
|
|
|
182
183
|
unitVerb,
|
|
183
184
|
formatAutoElapsed as _formatAutoElapsed,
|
|
184
185
|
formatWidgetTokens,
|
|
185
|
-
hideFooter,
|
|
186
186
|
type WidgetStateAccessors,
|
|
187
187
|
} from "./auto-dashboard.js";
|
|
188
188
|
import {
|
|
@@ -310,6 +310,21 @@ function restoreMilestoneLockEnv(): void {
|
|
|
310
310
|
s.milestoneLockEnvCaptured = false;
|
|
311
311
|
}
|
|
312
312
|
|
|
313
|
+
function normalizeSessionFilePath(raw: unknown): string | null {
|
|
314
|
+
if (typeof raw !== "string") return null;
|
|
315
|
+
const trimmed = raw.trim();
|
|
316
|
+
if (!trimmed) return null;
|
|
317
|
+
const firstLine = trimmed.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
318
|
+
if (!firstLine) return null;
|
|
319
|
+
|
|
320
|
+
// Guard against accidental message concatenation by trimming to .jsonl.
|
|
321
|
+
const jsonlIndex = firstLine.toLowerCase().indexOf(".jsonl");
|
|
322
|
+
const candidate = jsonlIndex >= 0 ? firstLine.slice(0, jsonlIndex + ".jsonl".length) : firstLine;
|
|
323
|
+
if (!isAbsolute(candidate)) return null;
|
|
324
|
+
if (!candidate.toLowerCase().endsWith(".jsonl")) return null;
|
|
325
|
+
return candidate;
|
|
326
|
+
}
|
|
327
|
+
|
|
313
328
|
export function startAutoDetached(
|
|
314
329
|
ctx: ExtensionCommandContext,
|
|
315
330
|
pi: ExtensionAPI,
|
|
@@ -330,8 +345,8 @@ export function startAutoDetached(
|
|
|
330
345
|
}
|
|
331
346
|
|
|
332
347
|
/** Returns true if the project is configured for `isolation:worktree` mode. */
|
|
333
|
-
export function shouldUseWorktreeIsolation(): boolean {
|
|
334
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
348
|
+
export function shouldUseWorktreeIsolation(basePath?: string): boolean {
|
|
349
|
+
const prefs = loadEffectiveGSDPreferences(basePath)?.preferences?.git;
|
|
335
350
|
if (prefs?.isolation === "worktree") return true;
|
|
336
351
|
// Default is false — worktree isolation requires explicit opt-in
|
|
337
352
|
return false;
|
|
@@ -424,7 +439,7 @@ export function getAutoDashboardData(): AutoDashboardData {
|
|
|
424
439
|
const rtkSavings = sessionId && s.basePath
|
|
425
440
|
? getRtkSessionSavings(s.basePath, sessionId)
|
|
426
441
|
: null;
|
|
427
|
-
const rtkEnabled = loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
|
|
442
|
+
const rtkEnabled = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences.experimental?.rtk === true;
|
|
428
443
|
// Pending capture count — lazy check, non-fatal
|
|
429
444
|
let pendingCaptureCount = 0;
|
|
430
445
|
try {
|
|
@@ -648,7 +663,7 @@ function buildSnapshotOpts(
|
|
|
648
663
|
gitStatus?: "ok" | "failed";
|
|
649
664
|
gitError?: string;
|
|
650
665
|
} & Record<string, unknown> {
|
|
651
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
666
|
+
const prefs = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
652
667
|
const uokFlags = resolveUokFlags(prefs);
|
|
653
668
|
return {
|
|
654
669
|
...(s.autoStartTime > 0 ? { autoSessionKey: String(s.autoStartTime) } : {}),
|
|
@@ -686,7 +701,7 @@ function handleLostSessionLock(
|
|
|
686
701
|
restoreProjectRootEnv();
|
|
687
702
|
restoreMilestoneLockEnv();
|
|
688
703
|
deregisterSigtermHandler();
|
|
689
|
-
clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
|
|
704
|
+
clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
|
|
690
705
|
const base = lockBase();
|
|
691
706
|
const lockFilePath = base ? join(gsdRoot(base), "auto.lock") : "unknown";
|
|
692
707
|
const recoverySuggestion = "\nTo recover, run: gsd doctor --fix";
|
|
@@ -706,7 +721,6 @@ function handleLostSessionLock(
|
|
|
706
721
|
);
|
|
707
722
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
708
723
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
709
|
-
ctx?.ui.setFooter(undefined);
|
|
710
724
|
if (ctx) initHealthWidget(ctx);
|
|
711
725
|
}
|
|
712
726
|
|
|
@@ -742,7 +756,6 @@ function cleanupAfterLoopExit(ctx: ExtensionContext): void {
|
|
|
742
756
|
if (!s.paused) {
|
|
743
757
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
744
758
|
ctx.ui.setWidget("gsd-progress", undefined);
|
|
745
|
-
ctx.ui.setFooter(undefined);
|
|
746
759
|
initHealthWidget(ctx);
|
|
747
760
|
}
|
|
748
761
|
|
|
@@ -764,7 +777,7 @@ export async function stopAuto(
|
|
|
764
777
|
reason?: string,
|
|
765
778
|
): Promise<void> {
|
|
766
779
|
if (!s.active && !s.paused) return;
|
|
767
|
-
const loadedPreferences = loadEffectiveGSDPreferences()?.preferences;
|
|
780
|
+
const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
768
781
|
const reasonSuffix = reason ? ` — ${reason}` : "";
|
|
769
782
|
|
|
770
783
|
try {
|
|
@@ -969,7 +982,7 @@ export async function stopAuto(
|
|
|
969
982
|
logWarning("engine", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
970
983
|
}
|
|
971
984
|
|
|
972
|
-
// ── Step 13: Restore original model (before reset clears IDs) ──
|
|
985
|
+
// ── Step 13: Restore original model + thinking (before reset clears IDs) ──
|
|
973
986
|
try {
|
|
974
987
|
if (pi && ctx && s.originalModelId && s.originalModelProvider) {
|
|
975
988
|
const original = ctx.modelRegistry.find(
|
|
@@ -978,6 +991,9 @@ export async function stopAuto(
|
|
|
978
991
|
);
|
|
979
992
|
if (original) await pi.setModel(original);
|
|
980
993
|
}
|
|
994
|
+
if (pi && s.originalThinkingLevel) {
|
|
995
|
+
pi.setThinkingLevel(s.originalThinkingLevel);
|
|
996
|
+
}
|
|
981
997
|
} catch (e) {
|
|
982
998
|
debugLog("stop-cleanup-model", { error: e instanceof Error ? e.message : String(e) });
|
|
983
999
|
}
|
|
@@ -1015,7 +1031,6 @@ export async function stopAuto(
|
|
|
1015
1031
|
// UI cleanup
|
|
1016
1032
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
1017
1033
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
1018
|
-
ctx?.ui.setFooter(undefined);
|
|
1019
1034
|
if (ctx) initHealthWidget(ctx);
|
|
1020
1035
|
restoreProjectRootEnv();
|
|
1021
1036
|
restoreMilestoneLockEnv();
|
|
@@ -1056,7 +1071,7 @@ export async function pauseAuto(
|
|
|
1056
1071
|
// from provider-error pause and avoid hard-stopping (#2762).
|
|
1057
1072
|
resolveAgentEndCancelled(_errorContext);
|
|
1058
1073
|
|
|
1059
|
-
s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
|
|
1074
|
+
s.pausedSessionFile = normalizeSessionFilePath(ctx?.sessionManager?.getSessionFile() ?? null);
|
|
1060
1075
|
|
|
1061
1076
|
// Persist paused-session metadata so resume survives /exit (#1383).
|
|
1062
1077
|
// The fresh-start bootstrap checks for this file and restores worktree context.
|
|
@@ -1118,7 +1133,6 @@ export async function pauseAuto(
|
|
|
1118
1133
|
s.verificationRetryCount.clear();
|
|
1119
1134
|
ctx?.ui.setStatus("gsd-auto", "paused");
|
|
1120
1135
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
1121
|
-
ctx?.ui.setFooter(undefined);
|
|
1122
1136
|
if (ctx) initHealthWidget(ctx);
|
|
1123
1137
|
const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
|
|
1124
1138
|
ctx?.ui.notify(
|
|
@@ -1289,6 +1303,10 @@ function buildLoopDeps(): LoopDeps {
|
|
|
1289
1303
|
|
|
1290
1304
|
// Journal
|
|
1291
1305
|
emitJournalEvent: (entry: JournalEntry) => _emitJournalEvent(s.basePath, entry),
|
|
1306
|
+
|
|
1307
|
+
// Clean-root preflight gate (#2909)
|
|
1308
|
+
preflightCleanRoot,
|
|
1309
|
+
postflightPopStash,
|
|
1292
1310
|
} as unknown as LoopDeps;
|
|
1293
1311
|
}
|
|
1294
1312
|
|
|
@@ -1361,7 +1379,11 @@ export async function startAuto(
|
|
|
1361
1379
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1362
1380
|
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1363
1381
|
s.paused = true;
|
|
1364
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1382
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1383
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1384
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1385
|
+
}
|
|
1386
|
+
}
|
|
1365
1387
|
ctx.ui.notify(
|
|
1366
1388
|
`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`,
|
|
1367
1389
|
"info",
|
|
@@ -1380,7 +1402,9 @@ export async function startAuto(
|
|
|
1380
1402
|
const summaryFile = resolveMilestoneFile(base, meta.milestoneId, "SUMMARY");
|
|
1381
1403
|
if (!mDir || summaryFile) {
|
|
1382
1404
|
try { unlinkSync(pausedPath); } catch (err) {
|
|
1383
|
-
|
|
1405
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1406
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1407
|
+
}
|
|
1384
1408
|
}
|
|
1385
1409
|
ctx.ui.notify(
|
|
1386
1410
|
`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`,
|
|
@@ -1390,20 +1414,28 @@ export async function startAuto(
|
|
|
1390
1414
|
s.currentMilestoneId = meta.milestoneId;
|
|
1391
1415
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1392
1416
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1393
|
-
s.pausedSessionFile = meta.sessionFile ?? null;
|
|
1417
|
+
s.pausedSessionFile = normalizeSessionFilePath(meta.sessionFile ?? null);
|
|
1394
1418
|
s.pausedUnitType = meta.unitType ?? null;
|
|
1395
1419
|
s.pausedUnitId = meta.unitId ?? null;
|
|
1396
1420
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
1397
1421
|
s.sessionMilestoneLock = meta.milestoneLock ?? null;
|
|
1398
1422
|
s.paused = true;
|
|
1399
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1423
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1424
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1425
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1400
1428
|
ctx.ui.notify(
|
|
1401
1429
|
`Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`,
|
|
1402
1430
|
"info",
|
|
1403
1431
|
);
|
|
1404
1432
|
}
|
|
1405
1433
|
} else if (existsSync(pausedPath)) {
|
|
1406
|
-
try { unlinkSync(pausedPath); } catch (e) {
|
|
1434
|
+
try { unlinkSync(pausedPath); } catch (e) {
|
|
1435
|
+
if ((e as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1436
|
+
logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1407
1439
|
}
|
|
1408
1440
|
}
|
|
1409
1441
|
} catch (err) {
|
|
@@ -1462,7 +1494,9 @@ export async function startAuto(
|
|
|
1462
1494
|
// Lock acquired — now safe to delete the pause file
|
|
1463
1495
|
if (s.pausedSessionFile) {
|
|
1464
1496
|
try { unlinkSync(s.pausedSessionFile); } catch (err) {
|
|
1465
|
-
|
|
1497
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") {
|
|
1498
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1499
|
+
}
|
|
1466
1500
|
}
|
|
1467
1501
|
s.pausedSessionFile = null;
|
|
1468
1502
|
}
|
|
@@ -1473,6 +1507,17 @@ export async function startAuto(
|
|
|
1473
1507
|
s.stepMode = requestedStepMode;
|
|
1474
1508
|
s.cmdCtx = ctx;
|
|
1475
1509
|
s.basePath = base;
|
|
1510
|
+
// ── Resume worktree: if the paused session was inside a milestone worktree,
|
|
1511
|
+
// apply that path as the dispatch basePath immediately (#3723).
|
|
1512
|
+
// This ensures the dispatch loop runs from the worktree directory even when
|
|
1513
|
+
// enterMilestone guard conditions differ between the original and resumed
|
|
1514
|
+
// session (e.g. isolation mode changed, detectWorktreeName differs across
|
|
1515
|
+
// process restarts). We guard with existsSync so a stale or deleted
|
|
1516
|
+
// worktree directory safely falls back to the project root.
|
|
1517
|
+
const resumeWorktreePath = freshStartAssessment.pausedSession?.worktreePath;
|
|
1518
|
+
if (resumeWorktreePath && existsSync(resumeWorktreePath)) {
|
|
1519
|
+
s.basePath = resumeWorktreePath;
|
|
1520
|
+
}
|
|
1476
1521
|
// Ensure the workflow-logger audit log is pinned to the project root
|
|
1477
1522
|
// even when auto-mode is entered via a path that bypasses the
|
|
1478
1523
|
// bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
|
|
@@ -1492,7 +1537,7 @@ export async function startAuto(
|
|
|
1492
1537
|
// ── Auto-worktree / branch-mode: re-enter on resume ──
|
|
1493
1538
|
if (
|
|
1494
1539
|
s.currentMilestoneId &&
|
|
1495
|
-
getIsolationMode() !== "none" &&
|
|
1540
|
+
getIsolationMode(s.originalBasePath || s.basePath) !== "none" &&
|
|
1496
1541
|
s.originalBasePath &&
|
|
1497
1542
|
!isInAutoWorktree(s.basePath) &&
|
|
1498
1543
|
!detectWorktreeName(s.basePath) &&
|
|
@@ -1506,7 +1551,7 @@ export async function startAuto(
|
|
|
1506
1551
|
registerSigtermHandler(lockBase());
|
|
1507
1552
|
|
|
1508
1553
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
1509
|
-
ctx.ui.
|
|
1554
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
1510
1555
|
ctx.ui.notify(
|
|
1511
1556
|
s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.",
|
|
1512
1557
|
"info",
|
|
@@ -1531,7 +1576,7 @@ export async function startAuto(
|
|
|
1531
1576
|
await openProjectDbIfPresent(s.basePath);
|
|
1532
1577
|
try {
|
|
1533
1578
|
await rebuildState(s.basePath);
|
|
1534
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1579
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1535
1580
|
} catch (e) {
|
|
1536
1581
|
debugLog("resume-rebuild-state-failed", {
|
|
1537
1582
|
error: e instanceof Error ? e.message : String(e),
|
|
@@ -1581,7 +1626,7 @@ export async function startAuto(
|
|
|
1581
1626
|
"resuming",
|
|
1582
1627
|
s.currentMilestoneId ?? "unknown",
|
|
1583
1628
|
);
|
|
1584
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1629
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1585
1630
|
|
|
1586
1631
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1587
1632
|
startAutoCommandPolling(s.basePath);
|
|
@@ -1619,12 +1664,12 @@ export async function startAuto(
|
|
|
1619
1664
|
|
|
1620
1665
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1621
1666
|
try {
|
|
1622
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1667
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1623
1668
|
} catch (err) {
|
|
1624
1669
|
// Best-effort only — sidebar sync must never block auto-mode startup
|
|
1625
1670
|
logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1626
1671
|
}
|
|
1627
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1672
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1628
1673
|
|
|
1629
1674
|
startAutoCommandPolling(s.basePath);
|
|
1630
1675
|
|
|
@@ -1773,12 +1818,12 @@ export async function dispatchHookUnit(
|
|
|
1773
1818
|
}
|
|
1774
1819
|
}
|
|
1775
1820
|
|
|
1776
|
-
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
1821
|
+
const sessionFile = normalizeSessionFilePath(ctx.sessionManager.getSessionFile());
|
|
1777
1822
|
writeLock(
|
|
1778
1823
|
lockBase(),
|
|
1779
1824
|
hookUnitType,
|
|
1780
1825
|
triggerUnitId,
|
|
1781
|
-
sessionFile,
|
|
1826
|
+
sessionFile ?? undefined,
|
|
1782
1827
|
);
|
|
1783
1828
|
|
|
1784
1829
|
clearUnitTimeout();
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// GSD — Persistent per-project blocklist of provider/model pairs that the
|
|
2
|
+
// provider has rejected at request time for account entitlement reasons.
|
|
3
|
+
//
|
|
4
|
+
// Lives at `.gsd/runtime/blocked-models.json` so the block survives /gsd auto
|
|
5
|
+
// restarts. Auto-mode model selection skips blocked entries; agent-end
|
|
6
|
+
// recovery adds entries when a runtime rejection is classified as
|
|
7
|
+
// `unsupported-model`. See issue #4513.
|
|
8
|
+
|
|
9
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
10
|
+
import { dirname, join } from "node:path";
|
|
11
|
+
import { gsdRoot } from "./paths.js";
|
|
12
|
+
import { withFileLockSync } from "./file-lock.js";
|
|
13
|
+
|
|
14
|
+
export interface BlockedModelEntry {
|
|
15
|
+
provider: string;
|
|
16
|
+
id: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
blockedAt: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface BlockedModelsFile {
|
|
22
|
+
version: 1;
|
|
23
|
+
blocked: BlockedModelEntry[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function blockedModelsPath(basePath: string): string {
|
|
27
|
+
return join(gsdRoot(basePath), "runtime", "blocked-models.json");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function modelKey(provider: string, id: string): string {
|
|
31
|
+
return `${provider.toLowerCase()}/${id.toLowerCase()}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function readFileSafe(path: string): BlockedModelsFile {
|
|
35
|
+
if (!existsSync(path)) return { version: 1, blocked: [] };
|
|
36
|
+
try {
|
|
37
|
+
const raw = readFileSync(path, "utf-8");
|
|
38
|
+
const parsed = JSON.parse(raw) as Partial<BlockedModelsFile>;
|
|
39
|
+
if (!parsed || !Array.isArray(parsed.blocked)) {
|
|
40
|
+
return { version: 1, blocked: [] };
|
|
41
|
+
}
|
|
42
|
+
const blocked = parsed.blocked.filter(
|
|
43
|
+
(e): e is BlockedModelEntry =>
|
|
44
|
+
!!e && typeof e.provider === "string" && typeof e.id === "string",
|
|
45
|
+
);
|
|
46
|
+
return { version: 1, blocked };
|
|
47
|
+
} catch {
|
|
48
|
+
// Corrupted JSON: treat as empty so a bad file never blocks dispatch.
|
|
49
|
+
return { version: 1, blocked: [] };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function loadBlockedModels(basePath: string): BlockedModelEntry[] {
|
|
54
|
+
return readFileSafe(blockedModelsPath(basePath)).blocked;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isModelBlocked(
|
|
58
|
+
basePath: string,
|
|
59
|
+
provider: string | undefined,
|
|
60
|
+
id: string | undefined,
|
|
61
|
+
): boolean {
|
|
62
|
+
if (!provider || !id) return false;
|
|
63
|
+
const target = modelKey(provider, id);
|
|
64
|
+
return loadBlockedModels(basePath).some(
|
|
65
|
+
(e) => modelKey(e.provider, e.id) === target,
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function blockModel(
|
|
70
|
+
basePath: string,
|
|
71
|
+
provider: string,
|
|
72
|
+
id: string,
|
|
73
|
+
reason: string,
|
|
74
|
+
): void {
|
|
75
|
+
const path = blockedModelsPath(basePath);
|
|
76
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
77
|
+
// Ensure the file exists before we try to lock it — proper-lockfile requires
|
|
78
|
+
// the target path to exist (file-lock.ts falls through to an unlocked call
|
|
79
|
+
// otherwise).
|
|
80
|
+
if (!existsSync(path)) {
|
|
81
|
+
writeFileSync(path, JSON.stringify({ version: 1, blocked: [] }, null, 2) + "\n", "utf-8");
|
|
82
|
+
}
|
|
83
|
+
withFileLockSync(path, () => {
|
|
84
|
+
const current = readFileSafe(path);
|
|
85
|
+
const target = modelKey(provider, id);
|
|
86
|
+
if (current.blocked.some((e) => modelKey(e.provider, e.id) === target)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const next: BlockedModelsFile = {
|
|
90
|
+
version: 1,
|
|
91
|
+
blocked: [
|
|
92
|
+
...current.blocked,
|
|
93
|
+
{ provider, id, reason, blockedAt: Date.now() },
|
|
94
|
+
],
|
|
95
|
+
};
|
|
96
|
+
writeFileSync(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
97
|
+
});
|
|
98
|
+
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import type { ExtensionAPI, ExtensionContext } from "@gsd/pi-coding-agent";
|
|
2
2
|
|
|
3
3
|
import { logWarning } from "../workflow-logger.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
checkAutoStartAfterDiscuss,
|
|
6
|
+
maybeHandleReadyPhraseWithoutFiles,
|
|
7
|
+
maybeHandleEmptyIntentTurn,
|
|
8
|
+
resetEmptyTurnCounter,
|
|
9
|
+
} from "../guided-flow.js";
|
|
5
10
|
import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
|
|
6
11
|
import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
|
|
7
12
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
@@ -16,6 +21,7 @@ import {
|
|
|
16
21
|
isTransient,
|
|
17
22
|
type ErrorClass,
|
|
18
23
|
} from "../error-classifier.js";
|
|
24
|
+
import { blockModel, isModelBlocked } from "../blocked-models.js";
|
|
19
25
|
|
|
20
26
|
const retryState = createRetryState();
|
|
21
27
|
const MAX_NETWORK_RETRIES = 2;
|
|
@@ -74,6 +80,20 @@ export async function handleAgentEnd(
|
|
|
74
80
|
clearDiscussionFlowState();
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
83
|
+
|
|
84
|
+
// #4573 — When the LLM emits "Milestone X ready." but the required files
|
|
85
|
+
// are missing, `checkAutoStartAfterDiscuss` returns false silently. Surface
|
|
86
|
+
// that and nudge the LLM to complete the writes before the user hits the
|
|
87
|
+
// downstream "All milestones complete" warning loop.
|
|
88
|
+
if (maybeHandleReadyPhraseWithoutFiles(event)) return;
|
|
89
|
+
|
|
90
|
+
// #4573 — Empty-turn recovery: if the LLM announced intent in prose but
|
|
91
|
+
// emitted no tool calls, nudge it to execute. Fires only when auto-mode is
|
|
92
|
+
// active or a discussion autostart is pending (non-auto interactive discuss
|
|
93
|
+
// is user-driven). Runs before `isAutoActive` early return so pending
|
|
94
|
+
// discussions (where isAutoActive may be false) still get recovered.
|
|
95
|
+
if (maybeHandleEmptyIntentTurn(event, isAutoActive())) return;
|
|
96
|
+
|
|
77
97
|
if (!isAutoActive()) return;
|
|
78
98
|
if (isSessionSwitchInFlight()) return;
|
|
79
99
|
|
|
@@ -124,6 +144,102 @@ export async function handleAgentEnd(
|
|
|
124
144
|
// ── 1. Classify using rawErrorMsg to avoid prose false-positives ────
|
|
125
145
|
const cls = classifyError(rawErrorMsg, explicitRetryAfterMs);
|
|
126
146
|
|
|
147
|
+
// ── 1a. Unsupported-model: provider rejected this model for the current
|
|
148
|
+
// account/plan at request time (#4513). Persist a block so the
|
|
149
|
+
// same dead model isn't reselected on the next /gsd auto restart,
|
|
150
|
+
// then try a fallback before pausing.
|
|
151
|
+
if (cls.kind === "unsupported-model") {
|
|
152
|
+
const dash = getAutoDashboardData();
|
|
153
|
+
const rejectedProvider = ctx.model?.provider;
|
|
154
|
+
const rejectedId = ctx.model?.id;
|
|
155
|
+
if (dash.basePath && rejectedProvider && rejectedId) {
|
|
156
|
+
try {
|
|
157
|
+
blockModel(dash.basePath, rejectedProvider, rejectedId, rawErrorMsg || "unsupported for account");
|
|
158
|
+
ctx.ui.notify(
|
|
159
|
+
`Blocked ${rejectedProvider}/${rejectedId} for this project — provider rejected it for the current account.`,
|
|
160
|
+
"warning",
|
|
161
|
+
);
|
|
162
|
+
} catch (err) {
|
|
163
|
+
const m = err instanceof Error ? err.message : String(err);
|
|
164
|
+
logWarning("bootstrap", `Failed to persist blocked model: ${m}`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Try configured fallback chain, skipping anything already blocked.
|
|
169
|
+
if (dash.currentUnit && dash.basePath) {
|
|
170
|
+
const modelConfig = resolveModelWithFallbacksForUnit(dash.currentUnit.type);
|
|
171
|
+
if (modelConfig && modelConfig.fallbacks.length > 0) {
|
|
172
|
+
const availableModels = ctx.modelRegistry.getAvailable();
|
|
173
|
+
let cursorModelId: string | undefined = ctx.model?.id;
|
|
174
|
+
while (true) {
|
|
175
|
+
const nextModelId = getNextFallbackModel(cursorModelId, modelConfig);
|
|
176
|
+
if (!nextModelId) break;
|
|
177
|
+
const candidate = resolveModelId(nextModelId, availableModels, ctx.model?.provider);
|
|
178
|
+
if (candidate && !isModelBlocked(dash.basePath, candidate.provider, candidate.id)) {
|
|
179
|
+
const ok = await pi.setModel(candidate, { persist: false });
|
|
180
|
+
if (ok) {
|
|
181
|
+
setCurrentDispatchedModelId({ provider: candidate.provider, id: candidate.id });
|
|
182
|
+
ctx.ui.notify(
|
|
183
|
+
`Switched to fallback ${candidate.provider}/${candidate.id} after account entitlement rejection.`,
|
|
184
|
+
"warning",
|
|
185
|
+
);
|
|
186
|
+
pi.sendMessage(
|
|
187
|
+
{ customType: "gsd-auto-timeout-recovery", content: "Continue execution.", display: false },
|
|
188
|
+
{ triggerTurn: true },
|
|
189
|
+
);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
cursorModelId = nextModelId;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Fallback chain exhausted — try the auto-mode start model if it isn't
|
|
198
|
+
// the same one we just blocked and isn't itself blocked.
|
|
199
|
+
const sessionModel = getAutoModeStartModel();
|
|
200
|
+
if (
|
|
201
|
+
sessionModel &&
|
|
202
|
+
!(sessionModel.provider === rejectedProvider && sessionModel.id === rejectedId) &&
|
|
203
|
+
!isModelBlocked(dash.basePath, sessionModel.provider, sessionModel.id)
|
|
204
|
+
) {
|
|
205
|
+
const startModel = ctx.modelRegistry
|
|
206
|
+
.getAvailable()
|
|
207
|
+
.find((m) => m.provider === sessionModel.provider && m.id === sessionModel.id);
|
|
208
|
+
if (startModel) {
|
|
209
|
+
const ok = await pi.setModel(startModel, { persist: false });
|
|
210
|
+
if (ok) {
|
|
211
|
+
setCurrentDispatchedModelId({ provider: startModel.provider, id: startModel.id });
|
|
212
|
+
ctx.ui.notify(
|
|
213
|
+
`Restored auto-mode start model ${startModel.provider}/${startModel.id} after entitlement rejection.`,
|
|
214
|
+
"warning",
|
|
215
|
+
);
|
|
216
|
+
pi.sendMessage(
|
|
217
|
+
{ customType: "gsd-auto-timeout-recovery", content: "Continue execution.", display: false },
|
|
218
|
+
{ triggerTurn: true },
|
|
219
|
+
);
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// No usable fallback — pause with a clearly named message.
|
|
227
|
+
const blockedLabel = rejectedProvider && rejectedId ? `${rejectedProvider}/${rejectedId}` : "current model";
|
|
228
|
+
const pauseDetail = `Model ${blockedLabel} blocked for this account${errorDetail}. Configure a different model and restart /gsd auto.`;
|
|
229
|
+
await pauseAutoForProviderError(ctx.ui, pauseDetail, () =>
|
|
230
|
+
pauseAuto(ctx, pi, {
|
|
231
|
+
message: pauseDetail,
|
|
232
|
+
category: "provider",
|
|
233
|
+
isTransient: false,
|
|
234
|
+
}),
|
|
235
|
+
{
|
|
236
|
+
isRateLimit: false,
|
|
237
|
+
isTransient: false,
|
|
238
|
+
retryAfterMs: 0,
|
|
239
|
+
});
|
|
240
|
+
return;
|
|
241
|
+
}
|
|
242
|
+
|
|
127
243
|
// ── 1b. Defer to Core RetryHandler for most transient errors ────────
|
|
128
244
|
// Core retries transient failures in-session after this handler.
|
|
129
245
|
// Keep that behavior for non-rate-limit classes to avoid pause/retry races,
|
|
@@ -239,6 +355,9 @@ export async function handleAgentEnd(
|
|
|
239
355
|
// ── Success path ─────────────────────────────────────────────────────────
|
|
240
356
|
try {
|
|
241
357
|
resetRetryState(retryState);
|
|
358
|
+
// #4573 — Reset the empty-turn counter on any successful agent turn so
|
|
359
|
+
// transient stalls don't accumulate across independent units.
|
|
360
|
+
resetEmptyTurnCounter();
|
|
242
361
|
resolveAgentEnd(event);
|
|
243
362
|
} catch (err) {
|
|
244
363
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -35,6 +35,19 @@ function registerAlias(pi: ExtensionAPI, toolDef: any, aliasName: string, canoni
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Read a tool result's structured payload, accommodating MCP's `details` →
|
|
40
|
+
* `structuredContent` rename (#4472, #4477). In-process executions still
|
|
41
|
+
* deliver the payload on `result.details`; MCP-routed executions deliver it
|
|
42
|
+
* on `result.structuredContent` (post `adaptExecutorResult` transform). All
|
|
43
|
+
* `renderResult` callbacks in this file route through this helper so a future
|
|
44
|
+
* field rename only needs to be applied in one place.
|
|
45
|
+
*/
|
|
46
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- result shape varies by tool
|
|
47
|
+
function readDetails(result: any): any {
|
|
48
|
+
return result?.details ?? result?.structuredContent;
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
export function registerDbTools(pi: ExtensionAPI): void {
|
|
39
52
|
// ─── gsd_decision_save (formerly gsd_save_decision) ─────────────────────
|
|
40
53
|
|
|
@@ -110,7 +123,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
110
123
|
return new Text(text, 0, 0);
|
|
111
124
|
},
|
|
112
125
|
renderResult(result: any, _options: any, theme: any) {
|
|
113
|
-
const d = result
|
|
126
|
+
const d = readDetails(result);
|
|
114
127
|
if (result.isError || d?.error) {
|
|
115
128
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
116
129
|
}
|
|
@@ -188,7 +201,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
188
201
|
return new Text(text, 0, 0);
|
|
189
202
|
},
|
|
190
203
|
renderResult(result: any, _options: any, theme: any) {
|
|
191
|
-
const d = result
|
|
204
|
+
const d = readDetails(result);
|
|
192
205
|
if (result.isError || d?.error) {
|
|
193
206
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
194
207
|
}
|
|
@@ -273,7 +286,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
273
286
|
return new Text(text, 0, 0);
|
|
274
287
|
},
|
|
275
288
|
renderResult(result: any, _options: any, theme: any) {
|
|
276
|
-
const d = result
|
|
289
|
+
const d = readDetails(result);
|
|
277
290
|
if (result.isError || d?.error) {
|
|
278
291
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
279
292
|
}
|
|
@@ -322,7 +335,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
322
335
|
return new Text(text, 0, 0);
|
|
323
336
|
},
|
|
324
337
|
renderResult(result: any, _options: any, theme: any) {
|
|
325
|
-
const d = result
|
|
338
|
+
const d = readDetails(result);
|
|
326
339
|
if (result.isError || d?.error) {
|
|
327
340
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
328
341
|
}
|
|
@@ -406,7 +419,7 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
406
419
|
return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
|
|
407
420
|
},
|
|
408
421
|
renderResult(result: any, _options: any, theme: any) {
|
|
409
|
-
const d = result
|
|
422
|
+
const d = readDetails(result);
|
|
410
423
|
if (result.isError || d?.error) {
|
|
411
424
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
412
425
|
}
|
|
@@ -1074,13 +1087,31 @@ export function registerDbTools(pi: ExtensionAPI): void {
|
|
|
1074
1087
|
text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
|
|
1075
1088
|
return new Text(text, 0, 0);
|
|
1076
1089
|
},
|
|
1090
|
+
/**
|
|
1091
|
+
* Render the save_gate_result tool output for the TUI.
|
|
1092
|
+
*
|
|
1093
|
+
* Prefers structured fields, but falls back to `content[0].text` when the
|
|
1094
|
+
* structured payload is empty. Defensive: the structural fix on this
|
|
1095
|
+
* branch plumbs `details` through MCP via `structuredContent`, but older
|
|
1096
|
+
* hosts, a future handler that forgets `structuredContent`, or any drop
|
|
1097
|
+
* of non-standard return fields would otherwise render as
|
|
1098
|
+
* "undefined: undefined". Same fallback applies to error rendering, and
|
|
1099
|
+
* we strip a leading `Error:` from the fallback text to avoid producing
|
|
1100
|
+
* `Error: Error: ...`.
|
|
1101
|
+
*/
|
|
1077
1102
|
renderResult(result: any, _options: any, theme: any) {
|
|
1078
|
-
const d = result
|
|
1103
|
+
const d = readDetails(result);
|
|
1079
1104
|
if (result.isError || d?.error) {
|
|
1080
|
-
|
|
1105
|
+
const rawMsg = d?.error ?? result.content?.[0]?.text ?? "unknown";
|
|
1106
|
+
const msg = rawMsg.replace(/^\s*Error:\s*/i, "");
|
|
1107
|
+
return new Text(theme.fg("error", `Error: ${msg}`), 0, 0);
|
|
1108
|
+
}
|
|
1109
|
+
if (!d?.gateId || !d?.verdict) {
|
|
1110
|
+
const text = result.content?.[0]?.text ?? "Gate result saved";
|
|
1111
|
+
return new Text(theme.fg("success", text), 0, 0);
|
|
1081
1112
|
}
|
|
1082
|
-
const color = d
|
|
1083
|
-
return new Text(theme.fg(color, `${d
|
|
1113
|
+
const color = d.verdict === "flag" ? "warning" : "success";
|
|
1114
|
+
return new Text(theme.fg(color, `${d.gateId}: ${d.verdict}`), 0, 0);
|
|
1084
1115
|
},
|
|
1085
1116
|
};
|
|
1086
1117
|
|