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
|
@@ -37,8 +37,9 @@ import { getRtkSessionSavings } from "../shared/rtk-session-stats.js";
|
|
|
37
37
|
import { deactivateGSD } from "../shared/gsd-phase-state.js";
|
|
38
38
|
import { initMetrics, resetMetrics, getLedger, getProjectTotals, formatCost, formatTokenCount, } from "./metrics.js";
|
|
39
39
|
import { setLogBasePath, logWarning } from "./workflow-logger.js";
|
|
40
|
+
import { preflightCleanRoot, postflightPopStash } from "./clean-root-preflight.js";
|
|
40
41
|
import { homedir } from "node:os";
|
|
41
|
-
import { join } from "node:path";
|
|
42
|
+
import { isAbsolute, join } from "node:path";
|
|
42
43
|
import { pathToFileURL } from "node:url";
|
|
43
44
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs";
|
|
44
45
|
import { atomicWriteSync } from "./atomic-write.js";
|
|
@@ -55,7 +56,7 @@ import { getErrorMessage } from "./error-utils.js";
|
|
|
55
56
|
import { recoverFailedMigration } from "./migrate-external.js";
|
|
56
57
|
import { initRegistry, convertDispatchRules } from "./rule-registry.js";
|
|
57
58
|
import { emitJournalEvent as _emitJournalEvent } from "./journal.js";
|
|
58
|
-
import { updateProgressWidget as _updateProgressWidget, updateSliceProgressCache, clearSliceProgressCache,
|
|
59
|
+
import { updateProgressWidget as _updateProgressWidget, updateSliceProgressCache, clearSliceProgressCache, } from "./auto-dashboard.js";
|
|
59
60
|
import { registerSigtermHandler as _registerSigtermHandler, deregisterSigtermHandler as _deregisterSigtermHandler, } from "./auto-supervisor.js";
|
|
60
61
|
import { isDbAvailable, getMilestone } from "./gsd-db.js";
|
|
61
62
|
import { countPendingCaptures } from "./captures.js";
|
|
@@ -136,6 +137,24 @@ function restoreMilestoneLockEnv() {
|
|
|
136
137
|
s.hadMilestoneLockEnv = false;
|
|
137
138
|
s.milestoneLockEnvCaptured = false;
|
|
138
139
|
}
|
|
140
|
+
function normalizeSessionFilePath(raw) {
|
|
141
|
+
if (typeof raw !== "string")
|
|
142
|
+
return null;
|
|
143
|
+
const trimmed = raw.trim();
|
|
144
|
+
if (!trimmed)
|
|
145
|
+
return null;
|
|
146
|
+
const firstLine = trimmed.split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
147
|
+
if (!firstLine)
|
|
148
|
+
return null;
|
|
149
|
+
// Guard against accidental message concatenation by trimming to .jsonl.
|
|
150
|
+
const jsonlIndex = firstLine.toLowerCase().indexOf(".jsonl");
|
|
151
|
+
const candidate = jsonlIndex >= 0 ? firstLine.slice(0, jsonlIndex + ".jsonl".length) : firstLine;
|
|
152
|
+
if (!isAbsolute(candidate))
|
|
153
|
+
return null;
|
|
154
|
+
if (!candidate.toLowerCase().endsWith(".jsonl"))
|
|
155
|
+
return null;
|
|
156
|
+
return candidate;
|
|
157
|
+
}
|
|
139
158
|
export function startAutoDetached(ctx, pi, base, verboseMode, options) {
|
|
140
159
|
void startAuto(ctx, pi, base, verboseMode, options).catch((err) => {
|
|
141
160
|
const message = getErrorMessage(err);
|
|
@@ -145,8 +164,8 @@ export function startAutoDetached(ctx, pi, base, verboseMode, options) {
|
|
|
145
164
|
});
|
|
146
165
|
}
|
|
147
166
|
/** Returns true if the project is configured for `isolation:worktree` mode. */
|
|
148
|
-
export function shouldUseWorktreeIsolation() {
|
|
149
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences?.git;
|
|
167
|
+
export function shouldUseWorktreeIsolation(basePath) {
|
|
168
|
+
const prefs = loadEffectiveGSDPreferences(basePath)?.preferences?.git;
|
|
150
169
|
if (prefs?.isolation === "worktree")
|
|
151
170
|
return true;
|
|
152
171
|
// Default is false — worktree isolation requires explicit opt-in
|
|
@@ -215,7 +234,7 @@ export function getAutoDashboardData() {
|
|
|
215
234
|
const rtkSavings = sessionId && s.basePath
|
|
216
235
|
? getRtkSessionSavings(s.basePath, sessionId)
|
|
217
236
|
: null;
|
|
218
|
-
const rtkEnabled = loadEffectiveGSDPreferences()?.preferences.experimental?.rtk === true;
|
|
237
|
+
const rtkEnabled = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences.experimental?.rtk === true;
|
|
219
238
|
// Pending capture count — lazy check, non-fatal
|
|
220
239
|
let pendingCaptureCount = 0;
|
|
221
240
|
try {
|
|
@@ -393,7 +412,7 @@ function clearUnitTimeout() {
|
|
|
393
412
|
}
|
|
394
413
|
/** Build snapshot metric opts. */
|
|
395
414
|
function buildSnapshotOpts(_unitType, _unitId) {
|
|
396
|
-
const prefs = loadEffectiveGSDPreferences()?.preferences;
|
|
415
|
+
const prefs = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
397
416
|
const uokFlags = resolveUokFlags(prefs);
|
|
398
417
|
return {
|
|
399
418
|
...(s.autoStartTime > 0 ? { autoSessionKey: String(s.autoStartTime) } : {}),
|
|
@@ -427,7 +446,7 @@ function handleLostSessionLock(ctx, lockStatus) {
|
|
|
427
446
|
restoreProjectRootEnv();
|
|
428
447
|
restoreMilestoneLockEnv();
|
|
429
448
|
deregisterSigtermHandler();
|
|
430
|
-
clearCmuxSidebar(loadEffectiveGSDPreferences()?.preferences);
|
|
449
|
+
clearCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences);
|
|
431
450
|
const base = lockBase();
|
|
432
451
|
const lockFilePath = base ? join(gsdRoot(base), "auto.lock") : "unknown";
|
|
433
452
|
const recoverySuggestion = "\nTo recover, run: gsd doctor --fix";
|
|
@@ -443,7 +462,6 @@ function handleLostSessionLock(ctx, lockStatus) {
|
|
|
443
462
|
ctx?.ui.notify(message, "error");
|
|
444
463
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
445
464
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
446
|
-
ctx?.ui.setFooter(undefined);
|
|
447
465
|
if (ctx)
|
|
448
466
|
initHealthWidget(ctx);
|
|
449
467
|
}
|
|
@@ -480,7 +498,6 @@ function cleanupAfterLoopExit(ctx) {
|
|
|
480
498
|
if (!s.paused) {
|
|
481
499
|
ctx.ui.setStatus("gsd-auto", undefined);
|
|
482
500
|
ctx.ui.setWidget("gsd-progress", undefined);
|
|
483
|
-
ctx.ui.setFooter(undefined);
|
|
484
501
|
initHealthWidget(ctx);
|
|
485
502
|
}
|
|
486
503
|
// Restore CWD out of worktree back to original project root
|
|
@@ -498,7 +515,7 @@ function cleanupAfterLoopExit(ctx) {
|
|
|
498
515
|
export async function stopAuto(ctx, pi, reason) {
|
|
499
516
|
if (!s.active && !s.paused)
|
|
500
517
|
return;
|
|
501
|
-
const loadedPreferences = loadEffectiveGSDPreferences()?.preferences;
|
|
518
|
+
const loadedPreferences = loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences;
|
|
502
519
|
const reasonSuffix = reason ? ` — ${reason}` : "";
|
|
503
520
|
try {
|
|
504
521
|
// ── Step 1: Timers and locks ──
|
|
@@ -695,13 +712,16 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
695
712
|
catch (err) { /* non-fatal */
|
|
696
713
|
logWarning("engine", `file unlink failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
697
714
|
}
|
|
698
|
-
// ── Step 13: Restore original model (before reset clears IDs) ──
|
|
715
|
+
// ── Step 13: Restore original model + thinking (before reset clears IDs) ──
|
|
699
716
|
try {
|
|
700
717
|
if (pi && ctx && s.originalModelId && s.originalModelProvider) {
|
|
701
718
|
const original = ctx.modelRegistry.find(s.originalModelProvider, s.originalModelId);
|
|
702
719
|
if (original)
|
|
703
720
|
await pi.setModel(original);
|
|
704
721
|
}
|
|
722
|
+
if (pi && s.originalThinkingLevel) {
|
|
723
|
+
pi.setThinkingLevel(s.originalThinkingLevel);
|
|
724
|
+
}
|
|
705
725
|
}
|
|
706
726
|
catch (e) {
|
|
707
727
|
debugLog("stop-cleanup-model", { error: e instanceof Error ? e.message : String(e) });
|
|
@@ -740,7 +760,6 @@ export async function stopAuto(ctx, pi, reason) {
|
|
|
740
760
|
// UI cleanup
|
|
741
761
|
ctx?.ui.setStatus("gsd-auto", undefined);
|
|
742
762
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
743
|
-
ctx?.ui.setFooter(undefined);
|
|
744
763
|
if (ctx)
|
|
745
764
|
initHealthWidget(ctx);
|
|
746
765
|
restoreProjectRootEnv();
|
|
@@ -775,7 +794,7 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
|
|
|
775
794
|
// Pass errorContext so runUnitPhase can distinguish user-initiated pause
|
|
776
795
|
// from provider-error pause and avoid hard-stopping (#2762).
|
|
777
796
|
resolveAgentEndCancelled(_errorContext);
|
|
778
|
-
s.pausedSessionFile = ctx?.sessionManager?.getSessionFile() ?? null;
|
|
797
|
+
s.pausedSessionFile = normalizeSessionFilePath(ctx?.sessionManager?.getSessionFile() ?? null);
|
|
779
798
|
// Persist paused-session metadata so resume survives /exit (#1383).
|
|
780
799
|
// The fresh-start bootstrap checks for this file and restores worktree context.
|
|
781
800
|
try {
|
|
@@ -829,7 +848,6 @@ export async function pauseAuto(ctx, _pi, _errorContext) {
|
|
|
829
848
|
s.verificationRetryCount.clear();
|
|
830
849
|
ctx?.ui.setStatus("gsd-auto", "paused");
|
|
831
850
|
ctx?.ui.setWidget("gsd-progress", undefined);
|
|
832
|
-
ctx?.ui.setFooter(undefined);
|
|
833
851
|
if (ctx)
|
|
834
852
|
initHealthWidget(ctx);
|
|
835
853
|
const resumeCmd = s.stepMode ? "/gsd next" : "/gsd auto";
|
|
@@ -975,6 +993,9 @@ function buildLoopDeps() {
|
|
|
975
993
|
},
|
|
976
994
|
// Journal
|
|
977
995
|
emitJournalEvent: (entry) => _emitJournalEvent(s.basePath, entry),
|
|
996
|
+
// Clean-root preflight gate (#2909)
|
|
997
|
+
preflightCleanRoot,
|
|
998
|
+
postflightPopStash,
|
|
978
999
|
};
|
|
979
1000
|
}
|
|
980
1001
|
/**
|
|
@@ -1031,7 +1052,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1031
1052
|
unlinkSync(pausedPath);
|
|
1032
1053
|
}
|
|
1033
1054
|
catch (e) {
|
|
1034
|
-
|
|
1055
|
+
if (e.code !== "ENOENT") {
|
|
1056
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1057
|
+
}
|
|
1035
1058
|
}
|
|
1036
1059
|
ctx.ui.notify(`Resuming paused custom workflow${meta.activeRunDir ? ` (${meta.activeRunDir})` : ""}.`, "info");
|
|
1037
1060
|
}
|
|
@@ -1049,7 +1072,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1049
1072
|
unlinkSync(pausedPath);
|
|
1050
1073
|
}
|
|
1051
1074
|
catch (err) {
|
|
1052
|
-
|
|
1075
|
+
if (err.code !== "ENOENT") {
|
|
1076
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1077
|
+
}
|
|
1053
1078
|
}
|
|
1054
1079
|
ctx.ui.notify(`Paused milestone ${meta.milestoneId} is ${!mDir ? "missing" : "already complete"}. Starting fresh.`, "info");
|
|
1055
1080
|
}
|
|
@@ -1057,7 +1082,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1057
1082
|
s.currentMilestoneId = meta.milestoneId;
|
|
1058
1083
|
s.originalBasePath = meta.originalBasePath || base;
|
|
1059
1084
|
s.stepMode = meta.stepMode ?? requestedStepMode;
|
|
1060
|
-
s.pausedSessionFile = meta.sessionFile ?? null;
|
|
1085
|
+
s.pausedSessionFile = normalizeSessionFilePath(meta.sessionFile ?? null);
|
|
1061
1086
|
s.pausedUnitType = meta.unitType ?? null;
|
|
1062
1087
|
s.pausedUnitId = meta.unitId ?? null;
|
|
1063
1088
|
s.autoStartTime = meta.autoStartTime || Date.now();
|
|
@@ -1067,7 +1092,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1067
1092
|
unlinkSync(pausedPath);
|
|
1068
1093
|
}
|
|
1069
1094
|
catch (e) {
|
|
1070
|
-
|
|
1095
|
+
if (e.code !== "ENOENT") {
|
|
1096
|
+
logWarning("session", `pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1097
|
+
}
|
|
1071
1098
|
}
|
|
1072
1099
|
ctx.ui.notify(`Resuming paused session for ${meta.milestoneId}${meta.worktreePath && existsSync(meta.worktreePath) ? ` (worktree)` : ""}.`, "info");
|
|
1073
1100
|
}
|
|
@@ -1077,7 +1104,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1077
1104
|
unlinkSync(pausedPath);
|
|
1078
1105
|
}
|
|
1079
1106
|
catch (e) {
|
|
1080
|
-
|
|
1107
|
+
if (e.code !== "ENOENT") {
|
|
1108
|
+
logWarning("session", `stale pause file cleanup failed: ${e instanceof Error ? e.message : String(e)}`, { file: "auto.ts" });
|
|
1109
|
+
}
|
|
1081
1110
|
}
|
|
1082
1111
|
}
|
|
1083
1112
|
}
|
|
@@ -1133,7 +1162,9 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1133
1162
|
unlinkSync(s.pausedSessionFile);
|
|
1134
1163
|
}
|
|
1135
1164
|
catch (err) {
|
|
1136
|
-
|
|
1165
|
+
if (err.code !== "ENOENT") {
|
|
1166
|
+
logWarning("session", `pause file cleanup failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1167
|
+
}
|
|
1137
1168
|
}
|
|
1138
1169
|
s.pausedSessionFile = null;
|
|
1139
1170
|
}
|
|
@@ -1143,6 +1174,17 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1143
1174
|
s.stepMode = requestedStepMode;
|
|
1144
1175
|
s.cmdCtx = ctx;
|
|
1145
1176
|
s.basePath = base;
|
|
1177
|
+
// ── Resume worktree: if the paused session was inside a milestone worktree,
|
|
1178
|
+
// apply that path as the dispatch basePath immediately (#3723).
|
|
1179
|
+
// This ensures the dispatch loop runs from the worktree directory even when
|
|
1180
|
+
// enterMilestone guard conditions differ between the original and resumed
|
|
1181
|
+
// session (e.g. isolation mode changed, detectWorktreeName differs across
|
|
1182
|
+
// process restarts). We guard with existsSync so a stale or deleted
|
|
1183
|
+
// worktree directory safely falls back to the project root.
|
|
1184
|
+
const resumeWorktreePath = freshStartAssessment.pausedSession?.worktreePath;
|
|
1185
|
+
if (resumeWorktreePath && existsSync(resumeWorktreePath)) {
|
|
1186
|
+
s.basePath = resumeWorktreePath;
|
|
1187
|
+
}
|
|
1146
1188
|
// Ensure the workflow-logger audit log is pinned to the project root
|
|
1147
1189
|
// even when auto-mode is entered via a path that bypasses the
|
|
1148
1190
|
// bootstrap/dynamic-tools ensureDbOpen() → setLogBasePath() chain
|
|
@@ -1161,7 +1203,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1161
1203
|
});
|
|
1162
1204
|
// ── Auto-worktree / branch-mode: re-enter on resume ──
|
|
1163
1205
|
if (s.currentMilestoneId &&
|
|
1164
|
-
getIsolationMode() !== "none" &&
|
|
1206
|
+
getIsolationMode(s.originalBasePath || s.basePath) !== "none" &&
|
|
1165
1207
|
s.originalBasePath &&
|
|
1166
1208
|
!isInAutoWorktree(s.basePath) &&
|
|
1167
1209
|
!detectWorktreeName(s.basePath) &&
|
|
@@ -1172,7 +1214,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1172
1214
|
}
|
|
1173
1215
|
registerSigtermHandler(lockBase());
|
|
1174
1216
|
ctx.ui.setStatus("gsd-auto", s.stepMode ? "next" : "auto");
|
|
1175
|
-
ctx.ui.
|
|
1217
|
+
ctx.ui.setWidget("gsd-health", undefined);
|
|
1176
1218
|
ctx.ui.notify(s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "info");
|
|
1177
1219
|
restoreHookState(s.basePath);
|
|
1178
1220
|
// Re-sync managed resources on resume so long-lived auto sessions pick up
|
|
@@ -1194,7 +1236,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1194
1236
|
await openProjectDbIfPresent(s.basePath);
|
|
1195
1237
|
try {
|
|
1196
1238
|
await rebuildState(s.basePath);
|
|
1197
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1239
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1198
1240
|
}
|
|
1199
1241
|
catch (e) {
|
|
1200
1242
|
debugLog("resume-rebuild-state-failed", {
|
|
@@ -1224,7 +1266,7 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1224
1266
|
}
|
|
1225
1267
|
updateSessionLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
|
|
1226
1268
|
writeLock(lockBase(), "resuming", s.currentMilestoneId ?? "unknown");
|
|
1227
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1269
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, s.stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "progress");
|
|
1228
1270
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1229
1271
|
startAutoCommandPolling(s.basePath);
|
|
1230
1272
|
await runAutoLoopWithUok({
|
|
@@ -1250,13 +1292,13 @@ export async function startAuto(ctx, pi, base, verboseMode, options) {
|
|
|
1250
1292
|
return;
|
|
1251
1293
|
captureProjectRootEnv(s.originalBasePath || s.basePath);
|
|
1252
1294
|
try {
|
|
1253
|
-
syncCmuxSidebar(loadEffectiveGSDPreferences()?.preferences, await deriveState(s.basePath));
|
|
1295
|
+
syncCmuxSidebar(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, await deriveState(s.basePath));
|
|
1254
1296
|
}
|
|
1255
1297
|
catch (err) {
|
|
1256
1298
|
// Best-effort only — sidebar sync must never block auto-mode startup
|
|
1257
1299
|
logWarning("engine", `cmux sync failed: ${err instanceof Error ? err.message : String(err)}`, { file: "auto.ts" });
|
|
1258
1300
|
}
|
|
1259
|
-
logCmuxEvent(loadEffectiveGSDPreferences()?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1301
|
+
logCmuxEvent(loadEffectiveGSDPreferences(s.basePath || undefined)?.preferences, requestedStepMode ? "Step-mode started." : "Auto-mode started.", "progress");
|
|
1260
1302
|
startAutoCommandPolling(s.basePath);
|
|
1261
1303
|
// Dispatch the first unit
|
|
1262
1304
|
await runAutoLoopWithUok({
|
|
@@ -1361,8 +1403,8 @@ export async function dispatchHookUnit(ctx, pi, hookName, triggerUnitType, trigg
|
|
|
1361
1403
|
`Ensure the model is defined in models.json and has auth configured.`, "warning");
|
|
1362
1404
|
}
|
|
1363
1405
|
}
|
|
1364
|
-
const sessionFile = ctx.sessionManager.getSessionFile();
|
|
1365
|
-
writeLock(lockBase(), hookUnitType, triggerUnitId, sessionFile);
|
|
1406
|
+
const sessionFile = normalizeSessionFilePath(ctx.sessionManager.getSessionFile());
|
|
1407
|
+
writeLock(lockBase(), hookUnitType, triggerUnitId, sessionFile ?? undefined);
|
|
1366
1408
|
clearUnitTimeout();
|
|
1367
1409
|
const supervisor = resolveAutoSupervisorConfig();
|
|
1368
1410
|
const hookHardTimeoutMs = (supervisor.hard_timeout_minutes ?? 30) * 60 * 1000;
|
|
@@ -0,0 +1,68 @@
|
|
|
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
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
9
|
+
import { dirname, join } from "node:path";
|
|
10
|
+
import { gsdRoot } from "./paths.js";
|
|
11
|
+
import { withFileLockSync } from "./file-lock.js";
|
|
12
|
+
function blockedModelsPath(basePath) {
|
|
13
|
+
return join(gsdRoot(basePath), "runtime", "blocked-models.json");
|
|
14
|
+
}
|
|
15
|
+
function modelKey(provider, id) {
|
|
16
|
+
return `${provider.toLowerCase()}/${id.toLowerCase()}`;
|
|
17
|
+
}
|
|
18
|
+
function readFileSafe(path) {
|
|
19
|
+
if (!existsSync(path))
|
|
20
|
+
return { version: 1, blocked: [] };
|
|
21
|
+
try {
|
|
22
|
+
const raw = readFileSync(path, "utf-8");
|
|
23
|
+
const parsed = JSON.parse(raw);
|
|
24
|
+
if (!parsed || !Array.isArray(parsed.blocked)) {
|
|
25
|
+
return { version: 1, blocked: [] };
|
|
26
|
+
}
|
|
27
|
+
const blocked = parsed.blocked.filter((e) => !!e && typeof e.provider === "string" && typeof e.id === "string");
|
|
28
|
+
return { version: 1, blocked };
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
// Corrupted JSON: treat as empty so a bad file never blocks dispatch.
|
|
32
|
+
return { version: 1, blocked: [] };
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function loadBlockedModels(basePath) {
|
|
36
|
+
return readFileSafe(blockedModelsPath(basePath)).blocked;
|
|
37
|
+
}
|
|
38
|
+
export function isModelBlocked(basePath, provider, id) {
|
|
39
|
+
if (!provider || !id)
|
|
40
|
+
return false;
|
|
41
|
+
const target = modelKey(provider, id);
|
|
42
|
+
return loadBlockedModels(basePath).some((e) => modelKey(e.provider, e.id) === target);
|
|
43
|
+
}
|
|
44
|
+
export function blockModel(basePath, provider, id, reason) {
|
|
45
|
+
const path = blockedModelsPath(basePath);
|
|
46
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
47
|
+
// Ensure the file exists before we try to lock it — proper-lockfile requires
|
|
48
|
+
// the target path to exist (file-lock.ts falls through to an unlocked call
|
|
49
|
+
// otherwise).
|
|
50
|
+
if (!existsSync(path)) {
|
|
51
|
+
writeFileSync(path, JSON.stringify({ version: 1, blocked: [] }, null, 2) + "\n", "utf-8");
|
|
52
|
+
}
|
|
53
|
+
withFileLockSync(path, () => {
|
|
54
|
+
const current = readFileSafe(path);
|
|
55
|
+
const target = modelKey(provider, id);
|
|
56
|
+
if (current.blocked.some((e) => modelKey(e.provider, e.id) === target)) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const next = {
|
|
60
|
+
version: 1,
|
|
61
|
+
blocked: [
|
|
62
|
+
...current.blocked,
|
|
63
|
+
{ provider, id, reason, blockedAt: Date.now() },
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
writeFileSync(path, JSON.stringify(next, null, 2) + "\n", "utf-8");
|
|
67
|
+
});
|
|
68
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { logWarning } from "../workflow-logger.js";
|
|
2
|
-
import { checkAutoStartAfterDiscuss } from "../guided-flow.js";
|
|
2
|
+
import { checkAutoStartAfterDiscuss, maybeHandleReadyPhraseWithoutFiles, maybeHandleEmptyIntentTurn, resetEmptyTurnCounter, } from "../guided-flow.js";
|
|
3
3
|
import { getAutoDashboardData, getAutoModeStartModel, isAutoActive, pauseAuto, setCurrentDispatchedModelId } from "../auto.js";
|
|
4
4
|
import { getNextFallbackModel, resolveModelWithFallbacksForUnit } from "../preferences.js";
|
|
5
5
|
import { pauseAutoForProviderError } from "../provider-error-pause.js";
|
|
@@ -8,6 +8,7 @@ import { resolveModelId } from "../auto-model-selection.js";
|
|
|
8
8
|
import { clearDiscussionFlowState } from "./write-gate.js";
|
|
9
9
|
import { resumeAutoAfterProviderDelay } from "./provider-error-resume.js";
|
|
10
10
|
import { classifyError, createRetryState, resetRetryState, isTransient, } from "../error-classifier.js";
|
|
11
|
+
import { blockModel, isModelBlocked } from "../blocked-models.js";
|
|
11
12
|
const retryState = createRetryState();
|
|
12
13
|
const MAX_NETWORK_RETRIES = 2;
|
|
13
14
|
const MAX_TRANSIENT_AUTO_RESUMES = 8;
|
|
@@ -52,6 +53,19 @@ export async function handleAgentEnd(pi, event, ctx) {
|
|
|
52
53
|
clearDiscussionFlowState();
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
56
|
+
// #4573 — When the LLM emits "Milestone X ready." but the required files
|
|
57
|
+
// are missing, `checkAutoStartAfterDiscuss` returns false silently. Surface
|
|
58
|
+
// that and nudge the LLM to complete the writes before the user hits the
|
|
59
|
+
// downstream "All milestones complete" warning loop.
|
|
60
|
+
if (maybeHandleReadyPhraseWithoutFiles(event))
|
|
61
|
+
return;
|
|
62
|
+
// #4573 — Empty-turn recovery: if the LLM announced intent in prose but
|
|
63
|
+
// emitted no tool calls, nudge it to execute. Fires only when auto-mode is
|
|
64
|
+
// active or a discussion autostart is pending (non-auto interactive discuss
|
|
65
|
+
// is user-driven). Runs before `isAutoActive` early return so pending
|
|
66
|
+
// discussions (where isAutoActive may be false) still get recovered.
|
|
67
|
+
if (maybeHandleEmptyIntentTurn(event, isAutoActive()))
|
|
68
|
+
return;
|
|
55
69
|
if (!isAutoActive())
|
|
56
70
|
return;
|
|
57
71
|
if (isSessionSwitchInFlight())
|
|
@@ -106,6 +120,81 @@ export async function handleAgentEnd(pi, event, ctx) {
|
|
|
106
120
|
const explicitRetryAfterMs = ("retryAfterMs" in lastMsg && typeof lastMsg.retryAfterMs === "number") ? lastMsg.retryAfterMs : undefined;
|
|
107
121
|
// ── 1. Classify using rawErrorMsg to avoid prose false-positives ────
|
|
108
122
|
const cls = classifyError(rawErrorMsg, explicitRetryAfterMs);
|
|
123
|
+
// ── 1a. Unsupported-model: provider rejected this model for the current
|
|
124
|
+
// account/plan at request time (#4513). Persist a block so the
|
|
125
|
+
// same dead model isn't reselected on the next /gsd auto restart,
|
|
126
|
+
// then try a fallback before pausing.
|
|
127
|
+
if (cls.kind === "unsupported-model") {
|
|
128
|
+
const dash = getAutoDashboardData();
|
|
129
|
+
const rejectedProvider = ctx.model?.provider;
|
|
130
|
+
const rejectedId = ctx.model?.id;
|
|
131
|
+
if (dash.basePath && rejectedProvider && rejectedId) {
|
|
132
|
+
try {
|
|
133
|
+
blockModel(dash.basePath, rejectedProvider, rejectedId, rawErrorMsg || "unsupported for account");
|
|
134
|
+
ctx.ui.notify(`Blocked ${rejectedProvider}/${rejectedId} for this project — provider rejected it for the current account.`, "warning");
|
|
135
|
+
}
|
|
136
|
+
catch (err) {
|
|
137
|
+
const m = err instanceof Error ? err.message : String(err);
|
|
138
|
+
logWarning("bootstrap", `Failed to persist blocked model: ${m}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Try configured fallback chain, skipping anything already blocked.
|
|
142
|
+
if (dash.currentUnit && dash.basePath) {
|
|
143
|
+
const modelConfig = resolveModelWithFallbacksForUnit(dash.currentUnit.type);
|
|
144
|
+
if (modelConfig && modelConfig.fallbacks.length > 0) {
|
|
145
|
+
const availableModels = ctx.modelRegistry.getAvailable();
|
|
146
|
+
let cursorModelId = ctx.model?.id;
|
|
147
|
+
while (true) {
|
|
148
|
+
const nextModelId = getNextFallbackModel(cursorModelId, modelConfig);
|
|
149
|
+
if (!nextModelId)
|
|
150
|
+
break;
|
|
151
|
+
const candidate = resolveModelId(nextModelId, availableModels, ctx.model?.provider);
|
|
152
|
+
if (candidate && !isModelBlocked(dash.basePath, candidate.provider, candidate.id)) {
|
|
153
|
+
const ok = await pi.setModel(candidate, { persist: false });
|
|
154
|
+
if (ok) {
|
|
155
|
+
setCurrentDispatchedModelId({ provider: candidate.provider, id: candidate.id });
|
|
156
|
+
ctx.ui.notify(`Switched to fallback ${candidate.provider}/${candidate.id} after account entitlement rejection.`, "warning");
|
|
157
|
+
pi.sendMessage({ customType: "gsd-auto-timeout-recovery", content: "Continue execution.", display: false }, { triggerTurn: true });
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
cursorModelId = nextModelId;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Fallback chain exhausted — try the auto-mode start model if it isn't
|
|
165
|
+
// the same one we just blocked and isn't itself blocked.
|
|
166
|
+
const sessionModel = getAutoModeStartModel();
|
|
167
|
+
if (sessionModel &&
|
|
168
|
+
!(sessionModel.provider === rejectedProvider && sessionModel.id === rejectedId) &&
|
|
169
|
+
!isModelBlocked(dash.basePath, sessionModel.provider, sessionModel.id)) {
|
|
170
|
+
const startModel = ctx.modelRegistry
|
|
171
|
+
.getAvailable()
|
|
172
|
+
.find((m) => m.provider === sessionModel.provider && m.id === sessionModel.id);
|
|
173
|
+
if (startModel) {
|
|
174
|
+
const ok = await pi.setModel(startModel, { persist: false });
|
|
175
|
+
if (ok) {
|
|
176
|
+
setCurrentDispatchedModelId({ provider: startModel.provider, id: startModel.id });
|
|
177
|
+
ctx.ui.notify(`Restored auto-mode start model ${startModel.provider}/${startModel.id} after entitlement rejection.`, "warning");
|
|
178
|
+
pi.sendMessage({ customType: "gsd-auto-timeout-recovery", content: "Continue execution.", display: false }, { triggerTurn: true });
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
// No usable fallback — pause with a clearly named message.
|
|
185
|
+
const blockedLabel = rejectedProvider && rejectedId ? `${rejectedProvider}/${rejectedId}` : "current model";
|
|
186
|
+
const pauseDetail = `Model ${blockedLabel} blocked for this account${errorDetail}. Configure a different model and restart /gsd auto.`;
|
|
187
|
+
await pauseAutoForProviderError(ctx.ui, pauseDetail, () => pauseAuto(ctx, pi, {
|
|
188
|
+
message: pauseDetail,
|
|
189
|
+
category: "provider",
|
|
190
|
+
isTransient: false,
|
|
191
|
+
}), {
|
|
192
|
+
isRateLimit: false,
|
|
193
|
+
isTransient: false,
|
|
194
|
+
retryAfterMs: 0,
|
|
195
|
+
});
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
109
198
|
// ── 1b. Defer to Core RetryHandler for most transient errors ────────
|
|
110
199
|
// Core retries transient failures in-session after this handler.
|
|
111
200
|
// Keep that behavior for non-rate-limit classes to avoid pause/retry races,
|
|
@@ -210,6 +299,9 @@ export async function handleAgentEnd(pi, event, ctx) {
|
|
|
210
299
|
// ── Success path ─────────────────────────────────────────────────────────
|
|
211
300
|
try {
|
|
212
301
|
resetRetryState(retryState);
|
|
302
|
+
// #4573 — Reset the empty-turn counter on any successful agent turn so
|
|
303
|
+
// transient stalls don't accumulate across independent units.
|
|
304
|
+
resetEmptyTurnCounter();
|
|
213
305
|
resolveAgentEnd(event);
|
|
214
306
|
}
|
|
215
307
|
catch (err) {
|
|
@@ -19,6 +19,18 @@ function registerAlias(pi, toolDef, aliasName, canonicalName) {
|
|
|
19
19
|
promptGuidelines: [`Alias for ${canonicalName} — prefer the canonical name.`],
|
|
20
20
|
});
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* Read a tool result's structured payload, accommodating MCP's `details` →
|
|
24
|
+
* `structuredContent` rename (#4472, #4477). In-process executions still
|
|
25
|
+
* deliver the payload on `result.details`; MCP-routed executions deliver it
|
|
26
|
+
* on `result.structuredContent` (post `adaptExecutorResult` transform). All
|
|
27
|
+
* `renderResult` callbacks in this file route through this helper so a future
|
|
28
|
+
* field rename only needs to be applied in one place.
|
|
29
|
+
*/
|
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- result shape varies by tool
|
|
31
|
+
function readDetails(result) {
|
|
32
|
+
return result?.details ?? result?.structuredContent;
|
|
33
|
+
}
|
|
22
34
|
export function registerDbTools(pi) {
|
|
23
35
|
// ─── gsd_decision_save (formerly gsd_save_decision) ─────────────────────
|
|
24
36
|
const decisionSaveExecute = async (_toolCallId, params, _signal, _onUpdate, _ctx) => {
|
|
@@ -92,7 +104,7 @@ export function registerDbTools(pi) {
|
|
|
92
104
|
return new Text(text, 0, 0);
|
|
93
105
|
},
|
|
94
106
|
renderResult(result, _options, theme) {
|
|
95
|
-
const d = result
|
|
107
|
+
const d = readDetails(result);
|
|
96
108
|
if (result.isError || d?.error) {
|
|
97
109
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
98
110
|
}
|
|
@@ -175,7 +187,7 @@ export function registerDbTools(pi) {
|
|
|
175
187
|
return new Text(text, 0, 0);
|
|
176
188
|
},
|
|
177
189
|
renderResult(result, _options, theme) {
|
|
178
|
-
const d = result
|
|
190
|
+
const d = readDetails(result);
|
|
179
191
|
if (result.isError || d?.error) {
|
|
180
192
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
181
193
|
}
|
|
@@ -255,7 +267,7 @@ export function registerDbTools(pi) {
|
|
|
255
267
|
return new Text(text, 0, 0);
|
|
256
268
|
},
|
|
257
269
|
renderResult(result, _options, theme) {
|
|
258
|
-
const d = result
|
|
270
|
+
const d = readDetails(result);
|
|
259
271
|
if (result.isError || d?.error) {
|
|
260
272
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
261
273
|
}
|
|
@@ -301,7 +313,7 @@ export function registerDbTools(pi) {
|
|
|
301
313
|
return new Text(text, 0, 0);
|
|
302
314
|
},
|
|
303
315
|
renderResult(result, _options, theme) {
|
|
304
|
-
const d = result
|
|
316
|
+
const d = readDetails(result);
|
|
305
317
|
if (result.isError || d?.error) {
|
|
306
318
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
307
319
|
}
|
|
@@ -382,7 +394,7 @@ export function registerDbTools(pi) {
|
|
|
382
394
|
return new Text(theme.fg("toolTitle", theme.bold("milestone_generate_id")), 0, 0);
|
|
383
395
|
},
|
|
384
396
|
renderResult(result, _options, theme) {
|
|
385
|
-
const d = result
|
|
397
|
+
const d = readDetails(result);
|
|
386
398
|
if (result.isError || d?.error) {
|
|
387
399
|
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
388
400
|
}
|
|
@@ -967,13 +979,31 @@ export function registerDbTools(pi) {
|
|
|
967
979
|
text += theme.fg("dim", ` → ${args.verdict ?? ""}`);
|
|
968
980
|
return new Text(text, 0, 0);
|
|
969
981
|
},
|
|
982
|
+
/**
|
|
983
|
+
* Render the save_gate_result tool output for the TUI.
|
|
984
|
+
*
|
|
985
|
+
* Prefers structured fields, but falls back to `content[0].text` when the
|
|
986
|
+
* structured payload is empty. Defensive: the structural fix on this
|
|
987
|
+
* branch plumbs `details` through MCP via `structuredContent`, but older
|
|
988
|
+
* hosts, a future handler that forgets `structuredContent`, or any drop
|
|
989
|
+
* of non-standard return fields would otherwise render as
|
|
990
|
+
* "undefined: undefined". Same fallback applies to error rendering, and
|
|
991
|
+
* we strip a leading `Error:` from the fallback text to avoid producing
|
|
992
|
+
* `Error: Error: ...`.
|
|
993
|
+
*/
|
|
970
994
|
renderResult(result, _options, theme) {
|
|
971
|
-
const d = result
|
|
995
|
+
const d = readDetails(result);
|
|
972
996
|
if (result.isError || d?.error) {
|
|
973
|
-
|
|
997
|
+
const rawMsg = d?.error ?? result.content?.[0]?.text ?? "unknown";
|
|
998
|
+
const msg = rawMsg.replace(/^\s*Error:\s*/i, "");
|
|
999
|
+
return new Text(theme.fg("error", `Error: ${msg}`), 0, 0);
|
|
1000
|
+
}
|
|
1001
|
+
if (!d?.gateId || !d?.verdict) {
|
|
1002
|
+
const text = result.content?.[0]?.text ?? "Gate result saved";
|
|
1003
|
+
return new Text(theme.fg("success", text), 0, 0);
|
|
974
1004
|
}
|
|
975
|
-
const color = d
|
|
976
|
-
return new Text(theme.fg(color, `${d
|
|
1005
|
+
const color = d.verdict === "flag" ? "warning" : "success";
|
|
1006
|
+
return new Text(theme.fg(color, `${d.gateId}: ${d.verdict}`), 0, 0);
|
|
977
1007
|
},
|
|
978
1008
|
};
|
|
979
1009
|
pi.registerTool(saveGateResultTool);
|