@opengsd/gsd-pi 1.0.2-dev.867e002 → 1.0.2-dev.aed3486
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/dist/onboarding.js +22 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/context7/index.js +12 -2
- package/dist/resources/extensions/get-secrets-from-user.js +16 -16
- package/dist/resources/extensions/google-cli/index.js +30 -0
- package/dist/resources/extensions/google-cli/models.js +55 -0
- package/dist/resources/extensions/google-cli/package.json +11 -0
- package/dist/resources/extensions/google-cli/readiness.js +12 -0
- package/dist/resources/extensions/google-cli/stream-adapter.js +191 -0
- package/dist/resources/extensions/gsd/auto/loop.js +62 -1
- package/dist/resources/extensions/gsd/auto/orchestrator.js +4 -2
- package/dist/resources/extensions/gsd/auto/phases.js +37 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +8 -0
- package/dist/resources/extensions/gsd/auto/session.js +3 -0
- package/dist/resources/extensions/gsd/auto-dispatch.js +17 -7
- package/dist/resources/extensions/gsd/auto-post-unit.js +21 -11
- package/dist/resources/extensions/gsd/auto-prompts.js +5 -236
- package/dist/resources/extensions/gsd/auto-recovery.js +10 -5
- package/dist/resources/extensions/gsd/auto-start.js +232 -49
- package/dist/resources/extensions/gsd/auto.js +6 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +4 -3
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +7 -2
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +39 -5
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +17 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +3 -27
- package/dist/resources/extensions/gsd/closeout-recovery.js +7 -1
- package/dist/resources/extensions/gsd/commands/handlers/auto.js +9 -1
- package/dist/resources/extensions/gsd/commands-usage.js +105 -1
- package/dist/resources/extensions/gsd/config-overlay.js +20 -14
- package/dist/resources/extensions/gsd/context-overlay.js +22 -16
- package/dist/resources/extensions/gsd/dashboard-overlay.js +10 -23
- package/dist/resources/extensions/gsd/doctor-engine-checks.js +87 -0
- package/dist/resources/extensions/gsd/doctor-providers.js +54 -24
- package/dist/resources/extensions/gsd/doctor.js +6 -1
- package/dist/resources/extensions/gsd/git-conflict-state.js +26 -1
- package/dist/resources/extensions/gsd/guided-flow.js +5 -6
- package/dist/resources/extensions/gsd/key-manager.js +45 -13
- package/dist/resources/extensions/gsd/milestone-reopen-events.js +28 -0
- package/dist/resources/extensions/gsd/notification-overlay.js +8 -9
- package/dist/resources/extensions/gsd/parallel-monitor-overlay.js +15 -13
- package/dist/resources/extensions/gsd/preferences-skills.js +11 -4
- package/dist/resources/extensions/gsd/preferences.js +14 -2
- package/dist/resources/extensions/gsd/prompt-loader.js +2 -0
- package/dist/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/dist/resources/extensions/gsd/prompts/system.md +1 -3
- package/dist/resources/extensions/gsd/queue-reorder-ui.js +28 -18
- package/dist/resources/extensions/gsd/repository-registry.js +3 -1
- package/dist/resources/extensions/gsd/safety/evidence-collector.js +11 -4
- package/dist/resources/extensions/gsd/skill-activation.js +233 -0
- package/dist/resources/extensions/gsd/skill-catalog.data.js +820 -0
- package/dist/resources/extensions/gsd/skill-catalog.install.js +179 -0
- package/dist/resources/extensions/gsd/skill-catalog.js +5 -1028
- package/dist/resources/extensions/gsd/skill-discovery.js +121 -79
- package/dist/resources/extensions/gsd/skill-scope.js +52 -0
- package/dist/resources/extensions/gsd/skill-telemetry.js +6 -39
- package/dist/resources/extensions/gsd/skills.js +60 -0
- package/dist/resources/extensions/gsd/state-reconciliation/drift/artifact-db.js +351 -0
- package/dist/resources/extensions/gsd/state-reconciliation/index.js +41 -0
- package/dist/resources/extensions/gsd/state-reconciliation/registry.js +4 -0
- package/dist/resources/extensions/gsd/tools/complete-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +42 -8
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +63 -2
- package/dist/resources/extensions/gsd/tui/render-kit.js +51 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +35 -26
- package/dist/resources/extensions/gsd/user-input-boundary.js +1 -1
- package/dist/resources/extensions/gsd/vision-ask.js +22 -0
- package/dist/resources/extensions/gsd/visualizer-overlay.js +8 -36
- package/dist/resources/extensions/gsd/worktree-lifecycle.js +24 -3
- package/dist/resources/extensions/search-the-web/native-search.js +57 -8
- package/dist/resources/extensions/shared/confirm-ui.js +9 -6
- package/dist/resources/extensions/shared/dialog-frame.js +42 -0
- package/dist/resources/extensions/shared/interview-ui.js +42 -30
- package/dist/resources/extensions/shared/next-action-ui.js +6 -6
- package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +4 -4
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- 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 +4 -4
- package/dist/web/standalone/.next/server/chunks/1834.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/cloud-mcp-gateway/package.json +2 -2
- package/packages/contracts/package.json +1 -1
- package/packages/daemon/package.json +4 -4
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts +1 -0
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.d.ts.map +1 -1
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js +22 -8
- package/packages/gsd-agent-core/dist/session/agent-session-extensions.js.map +1 -1
- package/packages/gsd-agent-core/package.json +5 -5
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts +12 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.d.ts.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js +45 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/dialog-container.js.map +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts +3 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js +11 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js +13 -11
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts +3 -3
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js +12 -10
- package/packages/gsd-agent-modes/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js +1 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/components/index.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js +2 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts +6 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js +9 -6
- package/packages/gsd-agent-modes/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js +0 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/components/transcript-design.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts +3 -0
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js +144 -2
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-auth.js.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.d.ts.map +1 -1
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js +2 -14
- package/packages/gsd-agent-modes/dist/modes/interactive/interactive-selectors-session.js.map +1 -1
- package/packages/gsd-agent-modes/package.json +7 -7
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +10 -5
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +3 -3
- package/packages/native/package.json +1 -1
- package/packages/pi-agent-core/dist/harness/skills.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/skills.js +6 -0
- package/packages/pi-agent-core/dist/harness/skills.js.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/harness/system-prompt.js +7 -0
- package/packages/pi-agent-core/dist/harness/system-prompt.js.map +1 -1
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-ai/dist/models.generated.d.ts +8 -59
- package/packages/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/packages/pi-ai/dist/models.generated.js +21 -72
- package/packages/pi-ai/dist/models.generated.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +50 -0
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/openai-responses-shared.js +28 -4
- package/packages/pi-ai/dist/providers/openai-responses-shared.js.map +1 -1
- package/packages/pi-ai/dist/types.d.ts +2 -0
- package/packages/pi-ai/dist/types.d.ts.map +1 -1
- package/packages/pi-ai/dist/types.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-coding-agent/README.md +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts +2 -2
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/extension-upstream-types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +8 -2
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/skills.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/skills.js +3 -0
- package/packages/pi-coding-agent/dist/core/skills.js.map +1 -1
- package/packages/pi-coding-agent/package.json +7 -7
- package/packages/pi-tui/package.json +1 -1
- package/packages/rpc-client/package.json +2 -2
- package/pkg/package.json +1 -1
- package/src/resources/extensions/context7/index.ts +15 -2
- package/src/resources/extensions/get-secrets-from-user.ts +17 -16
- package/src/resources/extensions/google-cli/index.ts +34 -0
- package/src/resources/extensions/google-cli/models.ts +57 -0
- package/src/resources/extensions/google-cli/package.json +11 -0
- package/src/resources/extensions/google-cli/readiness.ts +15 -0
- package/src/resources/extensions/google-cli/stream-adapter.ts +245 -0
- package/src/resources/extensions/gsd/auto/loop.ts +74 -1
- package/src/resources/extensions/gsd/auto/orchestrator.ts +4 -2
- package/src/resources/extensions/gsd/auto/phases.ts +46 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -0
- package/src/resources/extensions/gsd/auto/session.ts +3 -0
- package/src/resources/extensions/gsd/auto-dispatch.ts +31 -11
- package/src/resources/extensions/gsd/auto-post-unit.ts +43 -14
- package/src/resources/extensions/gsd/auto-prompts.ts +4 -284
- package/src/resources/extensions/gsd/auto-recovery.ts +10 -7
- package/src/resources/extensions/gsd/auto-start.ts +307 -56
- package/src/resources/extensions/gsd/auto.ts +6 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +4 -3
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +9 -4
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +42 -5
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +18 -6
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +3 -28
- package/src/resources/extensions/gsd/closeout-recovery.ts +6 -1
- package/src/resources/extensions/gsd/commands/handlers/auto.ts +9 -1
- package/src/resources/extensions/gsd/commands-usage.ts +110 -5
- package/src/resources/extensions/gsd/config-overlay.ts +19 -16
- package/src/resources/extensions/gsd/context-overlay.ts +24 -19
- package/src/resources/extensions/gsd/dashboard-overlay.ts +14 -27
- package/src/resources/extensions/gsd/doctor-engine-checks.ts +99 -0
- package/src/resources/extensions/gsd/doctor-providers.ts +55 -27
- package/src/resources/extensions/gsd/doctor-types.ts +2 -0
- package/src/resources/extensions/gsd/doctor.ts +6 -1
- package/src/resources/extensions/gsd/git-conflict-state.ts +25 -1
- package/src/resources/extensions/gsd/guided-flow.ts +5 -6
- package/src/resources/extensions/gsd/key-manager.ts +57 -14
- package/src/resources/extensions/gsd/milestone-reopen-events.ts +28 -0
- package/src/resources/extensions/gsd/notification-overlay.ts +12 -11
- package/src/resources/extensions/gsd/parallel-monitor-overlay.ts +16 -12
- package/src/resources/extensions/gsd/preferences-skills.ts +11 -4
- package/src/resources/extensions/gsd/preferences.ts +17 -2
- package/src/resources/extensions/gsd/prompt-loader.ts +2 -0
- package/src/resources/extensions/gsd/prompts/discuss.md +4 -2
- package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +2 -0
- package/src/resources/extensions/gsd/prompts/system.md +1 -3
- package/src/resources/extensions/gsd/queue-reorder-ui.ts +29 -20
- package/src/resources/extensions/gsd/repository-registry.ts +3 -1
- package/src/resources/extensions/gsd/safety/evidence-collector.ts +11 -4
- package/src/resources/extensions/gsd/skill-activation.ts +292 -0
- package/src/resources/extensions/gsd/skill-catalog.data.ts +858 -0
- package/src/resources/extensions/gsd/skill-catalog.install.ts +205 -0
- package/src/resources/extensions/gsd/skill-catalog.ts +16 -1087
- package/src/resources/extensions/gsd/skill-discovery.ts +134 -78
- package/src/resources/extensions/gsd/skill-scope.ts +63 -0
- package/src/resources/extensions/gsd/skill-telemetry.ts +6 -40
- package/src/resources/extensions/gsd/skills.ts +75 -0
- package/src/resources/extensions/gsd/state-reconciliation/drift/artifact-db.ts +499 -0
- package/src/resources/extensions/gsd/state-reconciliation/index.ts +40 -0
- package/src/resources/extensions/gsd/state-reconciliation/registry.ts +8 -0
- package/src/resources/extensions/gsd/state-reconciliation/types.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +328 -2
- package/src/resources/extensions/gsd/tests/auto-orchestrator.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/auto-post-unit-artifact-diagnostic.test.ts +28 -2
- package/src/resources/extensions/gsd/tests/auto-post-unit-evidence-crossref-4909.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +41 -0
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +436 -0
- package/src/resources/extensions/gsd/tests/closeout-recovery.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/commands-context.test.ts +5 -3
- package/src/resources/extensions/gsd/tests/commands-dispatcher-workspace-git.test.ts +15 -2
- package/src/resources/extensions/gsd/tests/commands-usage.test.ts +97 -0
- package/src/resources/extensions/gsd/tests/context-chart.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/dashboard-overlay.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/discord-invite-links.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/discuss-prompt.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/doctor-providers.test.ts +105 -0
- package/src/resources/extensions/gsd/tests/doctor-scope-db-unavailable.test.ts +101 -1
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/guided-discuss-milestone-prompt-rendering.test.ts +6 -0
- package/src/resources/extensions/gsd/tests/key-manager.test.ts +23 -4
- package/src/resources/extensions/gsd/tests/notification-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +70 -10
- package/src/resources/extensions/gsd/tests/parallel-monitor-overlay.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/post-unit-retry-on-orchestrator-bridge.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/queue-reorder-ui.test.ts +46 -0
- package/src/resources/extensions/gsd/tests/register-extension-guard.test.ts +116 -11
- package/src/resources/extensions/gsd/tests/repository-registry.test.ts +30 -1
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/skill-discovery.test.ts +111 -0
- package/src/resources/extensions/gsd/tests/skill-scope-auto.test.ts +67 -0
- package/src/resources/extensions/gsd/tests/skills.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +13 -2
- package/src/resources/extensions/gsd/tests/state-reconciliation-drift.test.ts +303 -0
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/tool-param-optionality.test.ts +24 -1
- package/src/resources/extensions/gsd/tests/tui-border-assertions.ts +28 -0
- package/src/resources/extensions/gsd/tests/tui-render-kit.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +18 -0
- package/src/resources/extensions/gsd/tests/user-input-boundary.test.ts +26 -0
- package/src/resources/extensions/gsd/tests/vision-ask.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +6 -1
- package/src/resources/extensions/gsd/tests/workflow-mcp-auto-prep.test.ts +74 -1
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +82 -0
- package/src/resources/extensions/gsd/tests/workspace-git-preflight.test.ts +16 -1
- package/src/resources/extensions/gsd/tests/worktree-lifecycle.test.ts +28 -0
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +45 -1
- package/src/resources/extensions/gsd/tools/complete-task.ts +9 -0
- package/src/resources/extensions/gsd/tools/exec-tool.ts +42 -10
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +82 -5
- package/src/resources/extensions/gsd/tui/render-kit.ts +82 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +37 -26
- package/src/resources/extensions/gsd/user-input-boundary.ts +1 -1
- package/src/resources/extensions/gsd/vision-ask.ts +28 -0
- package/src/resources/extensions/gsd/visualizer-overlay.ts +12 -40
- package/src/resources/extensions/gsd/worktree-lifecycle.ts +37 -2
- package/src/resources/extensions/search-the-web/native-search.ts +60 -8
- package/src/resources/extensions/shared/confirm-ui.ts +8 -12
- package/src/resources/extensions/shared/dialog-frame.ts +71 -0
- package/src/resources/extensions/shared/interview-ui.ts +43 -42
- package/src/resources/extensions/shared/next-action-ui.ts +6 -6
- package/src/resources/extensions/shared/tests/confirm-ui.test.ts +57 -0
- package/src/resources/extensions/shared/tests/interview-ui-border.test.ts +163 -0
- package/src/resources/extensions/shared/tests/next-action-ui-hasui.test.ts +55 -0
- package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +1 -1
- /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → _LIEWYP8ISVAPKAEEXxFr}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{praHP_OATcjBkvAVejjGK → _LIEWYP8ISVAPKAEEXxFr}/_ssgManifest.js +0 -0
package/dist/onboarding.js
CHANGED
|
@@ -15,6 +15,7 @@ import { dirname, join } from 'node:path';
|
|
|
15
15
|
import { renderGsdPiLogo, GSD_PI_BRAND, GSD_WEBSITE } from './logo.js';
|
|
16
16
|
import { agentDir } from './app-paths.js';
|
|
17
17
|
import { isClaudeCliReady } from './claude-cli-check.js';
|
|
18
|
+
import { isAntigravityCliReady, isGeminiCliReady } from './resources/extensions/google-cli/readiness.js';
|
|
18
19
|
import { markOnboardingComplete, markStepCompleted, markStepSkipped, isOnboardingComplete, } from './resources/extensions/gsd/onboarding-state.js';
|
|
19
20
|
import { getLlmProviderIds } from './resources/extensions/gsd/setup-catalog.js';
|
|
20
21
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
@@ -358,7 +359,13 @@ export async function runLlmStep(p, pc, authStorage) {
|
|
|
358
359
|
if (isClaudeCliReady()) {
|
|
359
360
|
authOptions.push({ value: 'claude-cli', label: 'Use Claude Code CLI', hint: 'recommended — uses your existing Claude subscription' });
|
|
360
361
|
}
|
|
361
|
-
|
|
362
|
+
if (isGeminiCliReady()) {
|
|
363
|
+
authOptions.push({ value: 'gemini-cli', label: 'Use Google Gemini CLI', hint: 'uses your existing Gemini CLI session' });
|
|
364
|
+
}
|
|
365
|
+
if (isAntigravityCliReady()) {
|
|
366
|
+
authOptions.push({ value: 'antigravity-cli', label: 'Use Antigravity CLI', hint: 'uses your existing Antigravity session' });
|
|
367
|
+
}
|
|
368
|
+
authOptions.push({ value: 'browser', label: 'Sign in with your browser', hint: 'GitHub Copilot or ChatGPT/Codex' }, { value: 'api-key', label: 'Paste an API key', hint: 'from your provider dashboard' }, { value: 'skip', label: 'Skip for now', hint: 'use /login inside GSD later' });
|
|
362
369
|
const method = await p.select({
|
|
363
370
|
message: existingAuth ? `LLM provider: ${existingAuth} — change it?` : 'How do you want to sign in?',
|
|
364
371
|
options: authOptions,
|
|
@@ -377,6 +384,20 @@ export async function runLlmStep(p, pc, authStorage) {
|
|
|
377
384
|
persistDefaultProvider('claude-code');
|
|
378
385
|
return true;
|
|
379
386
|
}
|
|
387
|
+
if (method === 'gemini-cli') {
|
|
388
|
+
p.log.success('Google Gemini CLI detected — routing through local CLI');
|
|
389
|
+
p.log.info('Your Gemini CLI session will be used for inference. No API key needed.');
|
|
390
|
+
authStorage.set('google-gemini-cli', { type: 'api_key', key: 'cli' });
|
|
391
|
+
persistDefaultProvider('google-gemini-cli');
|
|
392
|
+
return true;
|
|
393
|
+
}
|
|
394
|
+
if (method === 'antigravity-cli') {
|
|
395
|
+
p.log.success('Antigravity CLI detected — routing through local CLI');
|
|
396
|
+
p.log.info('Your Antigravity session will be used for inference. No API key needed.');
|
|
397
|
+
authStorage.set('google-antigravity', { type: 'api_key', key: 'cli' });
|
|
398
|
+
persistDefaultProvider('google-antigravity');
|
|
399
|
+
return true;
|
|
400
|
+
}
|
|
380
401
|
// ── Step 2: Which provider? ──────────────────────────────────────────────
|
|
381
402
|
if (method === 'browser') {
|
|
382
403
|
// Anthropic OAuth is removed from browser auth — it violates Anthropic TOS for
|
|
@@ -387,8 +408,6 @@ export async function runLlmStep(p, pc, authStorage) {
|
|
|
387
408
|
options: [
|
|
388
409
|
{ value: 'github-copilot', label: 'GitHub Copilot' },
|
|
389
410
|
{ value: 'openai-codex', label: 'ChatGPT Plus/Pro (Codex)' },
|
|
390
|
-
{ value: 'google-gemini-cli', label: 'Google Gemini CLI' },
|
|
391
|
-
{ value: 'google-antigravity', label: 'Antigravity (Gemini 3, Claude, GPT-OSS)' },
|
|
392
411
|
],
|
|
393
412
|
});
|
|
394
413
|
if (p.isCancel(provider))
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
679e72aa2db909a2
|
|
@@ -92,6 +92,16 @@ function formatLibraryList(libs, query) {
|
|
|
92
92
|
lines.push("\nUse the ID (e.g. /websites/react_dev) with get_library_docs to fetch documentation.");
|
|
93
93
|
return lines.join("\n");
|
|
94
94
|
}
|
|
95
|
+
function getFirstTextContent(result) {
|
|
96
|
+
const content = result.content;
|
|
97
|
+
if (!Array.isArray(content))
|
|
98
|
+
return undefined;
|
|
99
|
+
const textBlock = content.find((block) => typeof block === "object" &&
|
|
100
|
+
block !== null &&
|
|
101
|
+
block.type === "text" &&
|
|
102
|
+
typeof block.text === "string");
|
|
103
|
+
return textBlock?.text.trim() || undefined;
|
|
104
|
+
}
|
|
95
105
|
// ─── Extension ───────────────────────────────────────────────────────────────
|
|
96
106
|
export default function (pi) {
|
|
97
107
|
// ── resolve_library ──────────────────────────────────────────────────────
|
|
@@ -164,7 +174,7 @@ export default function (pi) {
|
|
|
164
174
|
if (isPartial)
|
|
165
175
|
return new Text(theme.fg("warning", "Searching Context7..."), 0, 0);
|
|
166
176
|
if (result.isError || d?.error) {
|
|
167
|
-
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
177
|
+
return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
|
|
168
178
|
}
|
|
169
179
|
let text = theme.fg("success", `${d?.resultCount ?? 0} ${d?.resultCount === 1 ? "library" : "libraries"} found`);
|
|
170
180
|
if (d?.cached)
|
|
@@ -303,7 +313,7 @@ export default function (pi) {
|
|
|
303
313
|
if (isPartial)
|
|
304
314
|
return new Text(theme.fg("warning", "Fetching documentation..."), 0, 0);
|
|
305
315
|
if (result.isError || d?.error) {
|
|
306
|
-
return new Text(theme.fg("error", `Error: ${d?.error ?? "unknown"}`), 0, 0);
|
|
316
|
+
return new Text(theme.fg("error", `Error: ${d?.error ?? getFirstTextContent(result) ?? "unknown"}`), 0, 0);
|
|
307
317
|
}
|
|
308
318
|
let text = theme.fg("success", `${(d?.charCount ?? 0).toLocaleString()} chars`);
|
|
309
319
|
text += theme.fg("dim", ` · ${d?.tokens ?? 5000} token budget`);
|
|
@@ -10,6 +10,7 @@ import { existsSync, statSync } from "node:fs";
|
|
|
10
10
|
import { resolve } from "node:path";
|
|
11
11
|
import { Editor, Key, matchesKey, Text, truncateToWidth, wrapTextWithAnsi } from "@gsd/pi-tui";
|
|
12
12
|
import { Type } from "@sinclair/typebox";
|
|
13
|
+
import { renderSharedDialogFrame } from "./shared/dialog-frame.js";
|
|
13
14
|
import { makeUI } from "./shared/tui.js";
|
|
14
15
|
import { maskEditorLine } from "./shared/mod.js";
|
|
15
16
|
import { parseSecretsManifest, formatSecretsManifest } from "./gsd/files.js";
|
|
@@ -22,6 +23,9 @@ function maskPreview(value) {
|
|
|
22
23
|
return "*".repeat(value.length);
|
|
23
24
|
return `${value.slice(0, 4)}${"*".repeat(Math.max(4, value.length - 8))}${value.slice(-4)}`;
|
|
24
25
|
}
|
|
26
|
+
function dialogContentWidth(width) {
|
|
27
|
+
return width < 4 ? Math.max(1, width) : Math.max(1, width - 4);
|
|
28
|
+
}
|
|
25
29
|
function shellEscapeSingle(value) {
|
|
26
30
|
return `'${value.replace(/'/g, `'\\''`)}'`;
|
|
27
31
|
}
|
|
@@ -132,9 +136,9 @@ async function collectOneSecret(ctx, pageIndex, totalPages, keyName, hint, guida
|
|
|
132
136
|
function render(width) {
|
|
133
137
|
if (cachedLines)
|
|
134
138
|
return cachedLines;
|
|
139
|
+
const contentWidth = dialogContentWidth(width);
|
|
135
140
|
const lines = [];
|
|
136
|
-
const add = (s) => lines.push(truncateToWidth(s,
|
|
137
|
-
add(theme.fg("accent", "─".repeat(width)));
|
|
141
|
+
const add = (s) => lines.push(truncateToWidth(s, contentWidth));
|
|
138
142
|
add(theme.fg("dim", ` Page ${pageIndex + 1}/${totalPages} · Secure Env Setup`));
|
|
139
143
|
lines.push("");
|
|
140
144
|
// Key name as big header
|
|
@@ -148,7 +152,7 @@ async function collectOneSecret(ctx, pageIndex, totalPages, keyName, hint, guida
|
|
|
148
152
|
for (let g = 0; g < guidance.length; g++) {
|
|
149
153
|
const prefix = ` ${g + 1}. `;
|
|
150
154
|
const step = guidance[g];
|
|
151
|
-
const wrappedLines = wrapTextWithAnsi(step,
|
|
155
|
+
const wrappedLines = wrapTextWithAnsi(step, Math.max(1, contentWidth - 4));
|
|
152
156
|
for (let w = 0; w < wrappedLines.length; w++) {
|
|
153
157
|
const indent = w === 0 ? prefix : " ".repeat(prefix.length);
|
|
154
158
|
lines.push(theme.fg("dim", `${indent}${wrappedLines[w]}`));
|
|
@@ -163,14 +167,13 @@ async function collectOneSecret(ctx, pageIndex, totalPages, keyName, hint, guida
|
|
|
163
167
|
lines.push("");
|
|
164
168
|
// Editor
|
|
165
169
|
add(theme.fg("muted", " Enter value:"));
|
|
166
|
-
for (const line of editor.render(
|
|
170
|
+
for (const line of editor.render(Math.max(1, contentWidth - 2))) {
|
|
167
171
|
add(theme.fg("text", maskEditorLine(line)));
|
|
168
172
|
}
|
|
169
173
|
lines.push("");
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
cachedLines
|
|
173
|
-
return lines;
|
|
174
|
+
const footer = theme.fg("dim", " enter to confirm | ctrl+s or esc to skip | esc cancels");
|
|
175
|
+
cachedLines = renderSharedDialogFrame(theme, "Secure Env Setup", lines, width, { footer });
|
|
176
|
+
return cachedLines;
|
|
174
177
|
}
|
|
175
178
|
return {
|
|
176
179
|
render,
|
|
@@ -224,13 +227,11 @@ export async function showSecretsSummary(ctx, entries, existingKeys) {
|
|
|
224
227
|
function render(width) {
|
|
225
228
|
if (cachedLines)
|
|
226
229
|
return cachedLines;
|
|
227
|
-
const
|
|
230
|
+
const contentWidth = dialogContentWidth(width);
|
|
231
|
+
const ui = makeUI(theme, contentWidth);
|
|
228
232
|
const lines = [];
|
|
229
233
|
const push = (...rows) => { for (const r of rows)
|
|
230
234
|
lines.push(...r); };
|
|
231
|
-
push(ui.bar());
|
|
232
|
-
push(ui.blank());
|
|
233
|
-
push(ui.header(" Secrets Summary"));
|
|
234
235
|
push(ui.blank());
|
|
235
236
|
for (const entry of entries) {
|
|
236
237
|
let status;
|
|
@@ -251,10 +252,9 @@ export async function showSecretsSummary(ctx, entries, existingKeys) {
|
|
|
251
252
|
push(ui.progressItem(entry.key, status, { detail }));
|
|
252
253
|
}
|
|
253
254
|
push(ui.blank());
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
cachedLines
|
|
257
|
-
return lines;
|
|
255
|
+
const footer = ui.hints(["any key to continue"])[0] ?? "";
|
|
256
|
+
cachedLines = renderSharedDialogFrame(theme, "Secrets Summary", lines, width, { footer });
|
|
257
|
+
return cachedLines;
|
|
258
258
|
}
|
|
259
259
|
return {
|
|
260
260
|
render,
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Google local CLI providers.
|
|
3
|
+
*
|
|
4
|
+
* These deliberately use authMode "externalCli": GSD never owns the browser
|
|
5
|
+
* OAuth flow or cached tokens. Users authenticate with the official CLI, then
|
|
6
|
+
* /login activates the provider once the local binary is available.
|
|
7
|
+
*/
|
|
8
|
+
import { GOOGLE_ANTIGRAVITY_MODELS, GOOGLE_GEMINI_CLI_MODELS } from "./models.js";
|
|
9
|
+
import { isAntigravityCliReady, isGeminiCliReady } from "./readiness.js";
|
|
10
|
+
import { streamViaGoogleCli } from "./stream-adapter.js";
|
|
11
|
+
export default function googleCli(pi) {
|
|
12
|
+
pi.registerProvider("google-gemini-cli", {
|
|
13
|
+
name: "Google Gemini CLI",
|
|
14
|
+
authMode: "externalCli",
|
|
15
|
+
api: "google-gemini-cli",
|
|
16
|
+
baseUrl: "local://google-gemini-cli",
|
|
17
|
+
isReady: isGeminiCliReady,
|
|
18
|
+
streamSimple: streamViaGoogleCli,
|
|
19
|
+
models: GOOGLE_GEMINI_CLI_MODELS,
|
|
20
|
+
});
|
|
21
|
+
pi.registerProvider("google-antigravity", {
|
|
22
|
+
name: "Google Antigravity",
|
|
23
|
+
authMode: "externalCli",
|
|
24
|
+
api: "google-antigravity",
|
|
25
|
+
baseUrl: "local://google-antigravity",
|
|
26
|
+
isReady: isAntigravityCliReady,
|
|
27
|
+
streamSimple: streamViaGoogleCli,
|
|
28
|
+
models: GOOGLE_ANTIGRAVITY_MODELS,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
const ZERO_COST = {
|
|
2
|
+
input: 0,
|
|
3
|
+
output: 0,
|
|
4
|
+
cacheRead: 0,
|
|
5
|
+
cacheWrite: 0,
|
|
6
|
+
};
|
|
7
|
+
export const GOOGLE_GEMINI_CLI_MODELS = [
|
|
8
|
+
{
|
|
9
|
+
id: "gemini-2.5-flash",
|
|
10
|
+
name: "Gemini 2.5 Flash",
|
|
11
|
+
reasoning: true,
|
|
12
|
+
input: ["text"],
|
|
13
|
+
cost: ZERO_COST,
|
|
14
|
+
contextWindow: 1_000_000,
|
|
15
|
+
maxTokens: 65_536,
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "gemini-2.5-pro",
|
|
19
|
+
name: "Gemini 2.5 Pro",
|
|
20
|
+
reasoning: true,
|
|
21
|
+
input: ["text"],
|
|
22
|
+
cost: ZERO_COST,
|
|
23
|
+
contextWindow: 1_000_000,
|
|
24
|
+
maxTokens: 65_536,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
id: "gemini-3-flash-preview",
|
|
28
|
+
name: "Gemini 3 Flash Preview",
|
|
29
|
+
reasoning: true,
|
|
30
|
+
input: ["text"],
|
|
31
|
+
cost: ZERO_COST,
|
|
32
|
+
contextWindow: 1_000_000,
|
|
33
|
+
maxTokens: 65_536,
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
id: "gemini-3.1-pro-preview",
|
|
37
|
+
name: "Gemini 3.1 Pro Preview",
|
|
38
|
+
reasoning: true,
|
|
39
|
+
input: ["text"],
|
|
40
|
+
cost: ZERO_COST,
|
|
41
|
+
contextWindow: 1_000_000,
|
|
42
|
+
maxTokens: 65_536,
|
|
43
|
+
},
|
|
44
|
+
];
|
|
45
|
+
export const GOOGLE_ANTIGRAVITY_MODELS = [
|
|
46
|
+
{
|
|
47
|
+
id: "default",
|
|
48
|
+
name: "Antigravity Default",
|
|
49
|
+
reasoning: true,
|
|
50
|
+
input: ["text"],
|
|
51
|
+
cost: ZERO_COST,
|
|
52
|
+
contextWindow: 1_000_000,
|
|
53
|
+
maxTokens: 65_536,
|
|
54
|
+
},
|
|
55
|
+
];
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
function isCommandInPath(command) {
|
|
3
|
+
const resolver = process.platform === "win32" ? "where" : "which";
|
|
4
|
+
const result = spawnSync(resolver, [command], { stdio: "ignore" });
|
|
5
|
+
return result.status === 0;
|
|
6
|
+
}
|
|
7
|
+
export function isGeminiCliReady() {
|
|
8
|
+
return isCommandInPath("gemini");
|
|
9
|
+
}
|
|
10
|
+
export function isAntigravityCliReady() {
|
|
11
|
+
return isCommandInPath("agy");
|
|
12
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { createAssistantMessageEventStream } from "@gsd/pi-ai";
|
|
3
|
+
const ZERO_USAGE = {
|
|
4
|
+
input: 0,
|
|
5
|
+
output: 0,
|
|
6
|
+
cacheRead: 0,
|
|
7
|
+
cacheWrite: 0,
|
|
8
|
+
totalTokens: 0,
|
|
9
|
+
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },
|
|
10
|
+
};
|
|
11
|
+
function textBlocks(content) {
|
|
12
|
+
return content
|
|
13
|
+
.map((block) => block.type === "text" ? block.text : `[${block.type} omitted]`)
|
|
14
|
+
.join("\n");
|
|
15
|
+
}
|
|
16
|
+
function messageToText(message) {
|
|
17
|
+
if (message.role === "user") {
|
|
18
|
+
const content = typeof message.content === "string" ? message.content : textBlocks(message.content);
|
|
19
|
+
return `User:\n${content}`;
|
|
20
|
+
}
|
|
21
|
+
if (message.role === "assistant") {
|
|
22
|
+
const text = message.content
|
|
23
|
+
.map((block) => {
|
|
24
|
+
if (block.type === "text")
|
|
25
|
+
return block.text;
|
|
26
|
+
if (block.type === "thinking")
|
|
27
|
+
return `[thinking omitted]`;
|
|
28
|
+
if (block.type === "toolCall")
|
|
29
|
+
return `[tool call: ${block.name}]`;
|
|
30
|
+
if (block.type === "serverToolUse")
|
|
31
|
+
return `[server tool: ${block.name}]`;
|
|
32
|
+
if (block.type === "webSearchResult")
|
|
33
|
+
return `[web search result omitted]`;
|
|
34
|
+
return `[${block.type} omitted]`;
|
|
35
|
+
})
|
|
36
|
+
.join("\n");
|
|
37
|
+
return `Assistant:\n${text}`;
|
|
38
|
+
}
|
|
39
|
+
return `Tool result (${message.toolName}):\n${textBlocks(message.content)}`;
|
|
40
|
+
}
|
|
41
|
+
export function buildGoogleCliPrompt(context) {
|
|
42
|
+
const parts = [];
|
|
43
|
+
if (context.systemPrompt?.trim()) {
|
|
44
|
+
parts.push(`System instructions:\n${context.systemPrompt.trim()}`);
|
|
45
|
+
}
|
|
46
|
+
if (context.messages.length > 0) {
|
|
47
|
+
parts.push(context.messages.map(messageToText).join("\n\n"));
|
|
48
|
+
}
|
|
49
|
+
if (context.tools?.length) {
|
|
50
|
+
const names = context.tools.map((tool) => tool.name).join(", ");
|
|
51
|
+
parts.push(`Available local GSD tools were not forwarded to this external CLI bridge. ` +
|
|
52
|
+
`If you need to act, use the CLI's own tools or ask the user to switch to a provider with native tool-call support. ` +
|
|
53
|
+
`Requested GSD tools: ${names}`);
|
|
54
|
+
}
|
|
55
|
+
return parts.join("\n\n").trim();
|
|
56
|
+
}
|
|
57
|
+
function buildAssistantMessage(model, text, stopReason = "stop", errorMessage) {
|
|
58
|
+
return {
|
|
59
|
+
role: "assistant",
|
|
60
|
+
content: text ? [{ type: "text", text }] : [],
|
|
61
|
+
api: model.api,
|
|
62
|
+
provider: model.provider,
|
|
63
|
+
model: model.id,
|
|
64
|
+
usage: { ...ZERO_USAGE, cost: { ...ZERO_USAGE.cost } },
|
|
65
|
+
stopReason,
|
|
66
|
+
...(errorMessage ? { errorMessage } : {}),
|
|
67
|
+
timestamp: Date.now(),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function extractGeminiJsonResponse(raw) {
|
|
71
|
+
const trimmed = raw.trim();
|
|
72
|
+
if (!trimmed)
|
|
73
|
+
return "";
|
|
74
|
+
try {
|
|
75
|
+
const parsed = JSON.parse(trimmed);
|
|
76
|
+
for (const key of ["response", "text", "content", "message"]) {
|
|
77
|
+
const value = parsed[key];
|
|
78
|
+
if (typeof value === "string")
|
|
79
|
+
return value;
|
|
80
|
+
}
|
|
81
|
+
return JSON.stringify(parsed, null, 2);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return trimmed;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function commandForProvider(provider) {
|
|
88
|
+
return provider === "google-gemini-cli" ? "gemini" : "agy";
|
|
89
|
+
}
|
|
90
|
+
function argsForProvider(provider, model, prompt) {
|
|
91
|
+
if (provider === "google-gemini-cli") {
|
|
92
|
+
const args = ["-p", prompt, "--output-format", "json"];
|
|
93
|
+
if (model.id !== "default")
|
|
94
|
+
args.unshift("-m", model.id);
|
|
95
|
+
return args;
|
|
96
|
+
}
|
|
97
|
+
const args = ["-p", prompt];
|
|
98
|
+
if (model.id !== "default")
|
|
99
|
+
args.unshift("-m", model.id);
|
|
100
|
+
return args;
|
|
101
|
+
}
|
|
102
|
+
export function buildGoogleCliSpawnInvocation(command, args, platform = process.platform) {
|
|
103
|
+
if (platform === "win32") {
|
|
104
|
+
return { command: "cmd", args: ["/c", command, ...args] };
|
|
105
|
+
}
|
|
106
|
+
return { command, args };
|
|
107
|
+
}
|
|
108
|
+
function runCli(command, args, options) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const invocation = buildGoogleCliSpawnInvocation(command, args);
|
|
111
|
+
const child = spawn(invocation.command, invocation.args, {
|
|
112
|
+
cwd: options?.cwd || process.cwd(),
|
|
113
|
+
env: process.env,
|
|
114
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
115
|
+
});
|
|
116
|
+
let stdout = "";
|
|
117
|
+
let stderr = "";
|
|
118
|
+
let settled = false;
|
|
119
|
+
const settle = (fn) => {
|
|
120
|
+
if (settled)
|
|
121
|
+
return;
|
|
122
|
+
settled = true;
|
|
123
|
+
options?.signal?.removeEventListener("abort", onAbort);
|
|
124
|
+
fn();
|
|
125
|
+
};
|
|
126
|
+
const onAbort = () => {
|
|
127
|
+
child.kill("SIGTERM");
|
|
128
|
+
settle(() => reject(new Error("Request was aborted")));
|
|
129
|
+
};
|
|
130
|
+
if (options?.signal?.aborted) {
|
|
131
|
+
onAbort();
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
options?.signal?.addEventListener("abort", onAbort);
|
|
135
|
+
child.stdout.setEncoding("utf8");
|
|
136
|
+
child.stderr.setEncoding("utf8");
|
|
137
|
+
child.stdout.on("data", (chunk) => {
|
|
138
|
+
stdout += chunk;
|
|
139
|
+
});
|
|
140
|
+
child.stderr.on("data", (chunk) => {
|
|
141
|
+
stderr += chunk;
|
|
142
|
+
});
|
|
143
|
+
child.on("error", (error) => {
|
|
144
|
+
settle(() => reject(error));
|
|
145
|
+
});
|
|
146
|
+
child.on("close", (code, signal) => {
|
|
147
|
+
settle(() => resolve({ stdout, stderr, code, signal }));
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function emitText(stream, message, text) {
|
|
152
|
+
stream.push({ type: "start", partial: { ...message, content: [] } });
|
|
153
|
+
if (text) {
|
|
154
|
+
stream.push({ type: "text_start", contentIndex: 0, partial: message });
|
|
155
|
+
stream.push({ type: "text_delta", contentIndex: 0, delta: text, partial: message });
|
|
156
|
+
stream.push({ type: "text_end", contentIndex: 0, content: text, partial: message });
|
|
157
|
+
}
|
|
158
|
+
stream.push({ type: "done", reason: "stop", message });
|
|
159
|
+
stream.end(message);
|
|
160
|
+
}
|
|
161
|
+
function emitError(stream, model, error) {
|
|
162
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
163
|
+
const output = buildAssistantMessage(model, "", "error", message);
|
|
164
|
+
stream.push({ type: "error", reason: "error", error: output });
|
|
165
|
+
stream.end(output);
|
|
166
|
+
}
|
|
167
|
+
export function streamViaGoogleCli(model, context, options) {
|
|
168
|
+
const stream = createAssistantMessageEventStream();
|
|
169
|
+
const provider = model.provider;
|
|
170
|
+
queueMicrotask(async () => {
|
|
171
|
+
try {
|
|
172
|
+
const prompt = buildGoogleCliPrompt(context);
|
|
173
|
+
const command = commandForProvider(provider);
|
|
174
|
+
const args = argsForProvider(provider, model, prompt);
|
|
175
|
+
const result = await runCli(command, args, options);
|
|
176
|
+
if (result.code !== 0) {
|
|
177
|
+
const detail = (result.stderr || result.stdout || `CLI exited with code ${result.code}`).trim();
|
|
178
|
+
throw new Error(detail);
|
|
179
|
+
}
|
|
180
|
+
const text = provider === "google-gemini-cli"
|
|
181
|
+
? extractGeminiJsonResponse(result.stdout)
|
|
182
|
+
: result.stdout.trim();
|
|
183
|
+
const message = buildAssistantMessage(model, text);
|
|
184
|
+
emitText(stream, message, text);
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
emitError(stream, model, error);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
return stream;
|
|
191
|
+
}
|
|
@@ -732,11 +732,36 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
732
732
|
message: orchestrationResult.reason,
|
|
733
733
|
category: "unknown",
|
|
734
734
|
});
|
|
735
|
+
finishTurn("paused", "manual-attention", "orchestration-blocked");
|
|
735
736
|
}
|
|
736
737
|
else {
|
|
737
738
|
await deps.stopAuto(ctx, pi, orchestrationResult.reason);
|
|
739
|
+
finishTurn("stopped", "manual-attention", "orchestration-blocked");
|
|
738
740
|
}
|
|
739
|
-
|
|
741
|
+
finishIncompleteIteration({
|
|
742
|
+
status: orchestrationResult.action === "pause" ? "paused" : "stopped",
|
|
743
|
+
reason: orchestrationResult.reason,
|
|
744
|
+
failureClass: "manual-attention",
|
|
745
|
+
});
|
|
746
|
+
break;
|
|
747
|
+
}
|
|
748
|
+
if (orchestrationResult.kind === "paused") {
|
|
749
|
+
s.pendingOrchestrationDispatch = null;
|
|
750
|
+
finishTurn("skipped");
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
if (orchestrationResult.kind === "error") {
|
|
754
|
+
s.pendingOrchestrationDispatch = null;
|
|
755
|
+
await deps.pauseAuto(ctx, pi, {
|
|
756
|
+
message: orchestrationResult.reason,
|
|
757
|
+
category: "unknown",
|
|
758
|
+
});
|
|
759
|
+
finishTurn("paused", "manual-attention", `orchestration-${orchestrationResult.kind}`);
|
|
760
|
+
finishIncompleteIteration({
|
|
761
|
+
status: "paused",
|
|
762
|
+
reason: orchestrationResult.reason,
|
|
763
|
+
failureClass: "manual-attention",
|
|
764
|
+
});
|
|
740
765
|
break;
|
|
741
766
|
}
|
|
742
767
|
if (orchestrationResult.kind === "stopped") {
|
|
@@ -769,6 +794,42 @@ export async function autoLoop(ctx, pi, s, deps, options) {
|
|
|
769
794
|
isRetry: false,
|
|
770
795
|
previousTier: undefined,
|
|
771
796
|
};
|
|
797
|
+
const preDispatchResult = deps.runPreDispatchHooks(iterData.unitType, iterData.unitId, iterData.prompt, s.basePath);
|
|
798
|
+
if (preDispatchResult.firedHooks.length > 0) {
|
|
799
|
+
ctx.ui.notify(`Pre-dispatch hook${preDispatchResult.firedHooks.length > 1 ? "s" : ""}: ${preDispatchResult.firedHooks.join(", ")}`, "info");
|
|
800
|
+
deps.emitJournalEvent({
|
|
801
|
+
ts: new Date().toISOString(),
|
|
802
|
+
flowId: ic.flowId,
|
|
803
|
+
seq: ic.nextSeq(),
|
|
804
|
+
eventType: "pre-dispatch-hook",
|
|
805
|
+
data: {
|
|
806
|
+
firedHooks: preDispatchResult.firedHooks,
|
|
807
|
+
action: preDispatchResult.action,
|
|
808
|
+
},
|
|
809
|
+
});
|
|
810
|
+
}
|
|
811
|
+
if (preDispatchResult.action === "skip") {
|
|
812
|
+
ctx.ui.notify(`Skipping ${iterData.unitType} ${iterData.unitId} (pre-dispatch hook).`, "info");
|
|
813
|
+
s.pendingOrchestrationDispatch = null;
|
|
814
|
+
emitIterationEnd({ skipped: true });
|
|
815
|
+
completeIteration();
|
|
816
|
+
finishTurn("skipped");
|
|
817
|
+
continue;
|
|
818
|
+
}
|
|
819
|
+
if (preDispatchResult.action === "replace") {
|
|
820
|
+
iterData.prompt = preDispatchResult.prompt ?? iterData.prompt;
|
|
821
|
+
iterData.finalPrompt = iterData.prompt;
|
|
822
|
+
if (preDispatchResult.unitType) {
|
|
823
|
+
iterData.unitType = preDispatchResult.unitType;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
else if (preDispatchResult.prompt) {
|
|
827
|
+
iterData.prompt = preDispatchResult.prompt;
|
|
828
|
+
iterData.finalPrompt = preDispatchResult.prompt;
|
|
829
|
+
}
|
|
830
|
+
if (preDispatchResult.model) {
|
|
831
|
+
iterData.hookModelOverride = preDispatchResult.model;
|
|
832
|
+
}
|
|
772
833
|
s.pendingOrchestrationDispatch = null;
|
|
773
834
|
phaseReporter.report("dispatch", "next", {
|
|
774
835
|
unitType: iterData.unitType,
|
|
@@ -369,9 +369,11 @@ export class AutoOrchestrator {
|
|
|
369
369
|
const activeUnitKey = this.status.activeUnit
|
|
370
370
|
? `${this.status.activeUnit.unitType}:${this.status.activeUnit.unitId}`
|
|
371
371
|
: null;
|
|
372
|
-
if (activeUnitKey !== unitKey)
|
|
372
|
+
if (activeUnitKey !== unitKey && this.lastFinalizedUnitKey !== unitKey)
|
|
373
373
|
return;
|
|
374
|
-
|
|
374
|
+
if (activeUnitKey === unitKey) {
|
|
375
|
+
this.status.activeUnit = undefined;
|
|
376
|
+
}
|
|
375
377
|
this.lastAdvanceKey = null;
|
|
376
378
|
this.lastFinalizedUnitKey = null;
|
|
377
379
|
this.bumpTransition();
|
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { importExtensionModule } from "@gsd/pi-coding-agent";
|
|
12
12
|
import { USER_DRIVEN_DEEP_UNITS, isAwaitingUserInput, } from "../auto-post-unit.js";
|
|
13
|
+
import { lastAssistantText } from "../user-input-boundary.js";
|
|
13
14
|
import { MAX_RECOVERY_CHARS, BUDGET_THRESHOLDS, MAX_FINALIZE_TIMEOUTS, } from "./types.js";
|
|
14
15
|
import { detectStuck } from "./detect-stuck.js";
|
|
15
16
|
import { runUnit } from "./run-unit.js";
|
|
@@ -52,8 +53,19 @@ import { decideVerificationRetry, verificationRetryKey } from "./verification-re
|
|
|
52
53
|
import { buildPhaseHandoffOutcome, setAutoOutcomeWidget } from "../auto-dashboard.js";
|
|
53
54
|
import { getConsecutiveDispatchBlocker } from "../dispatch-guard.js";
|
|
54
55
|
import { captureRootDirtySnapshot, detectRootWriteLeak, formatRootWriteLeakMessage, } from "../root-write-leak-guard.js";
|
|
56
|
+
import { classifyError, isTransient } from "../error-classifier.js";
|
|
55
57
|
export const STUCK_WINDOW_SIZE = 6;
|
|
56
58
|
const STUCK_RECOVERY_ATTEMPTS_KEY = "stuck_recovery_attempts";
|
|
59
|
+
const ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE = /^(?:api error(?::|$|\s*\()|provider error(?::|$|\s*\()|request failed\b|(?:http\s*)?(?:429|500|502|503)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|socket hang up\b|fetch failed\b|(?:network|connection|server) error(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|dns\b.*(?:fail|error|timeout)|unexpected eof\b|stream idle timeout\b|partial response received\b|stream_exhausted\b|terminated(?::|$)|(?:connection|stream|request)\b.{0,40}\bterminated\b|other side closed\b|rate.?limit(?:ed| exceeded| reached| error)|too many requests\b|you(?:'ve| have) hit your limit\b|usage limit\b|out of extra usage\b|service.?unavailable\b|internal(?: server)? error(?::|$)|internal(?:[_-]server)?[_-]error\b|server[_-]error\b|(?:provider|server|api|model|codex|claude|openai|anthropic|gemini)\b.{0,80}\boverloaded\b|overloaded\b.{0,80}\b(?:provider|server|api|model)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
60
|
+
const ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE = /(?:\b(?:http|status(?: code)?|code|error:)\s*(?:429|500|502|503)\b|\b(?:api|provider) error\s*[:(]?\s*(?:429|500|502|503)\b|\b(?:typeerror|error):\s*(?:fetch failed\b|socket hang up\b|terminated(?::|$)|connection (?:reset|refused)(?::|$|\s+by\b)|(?:network|connection|server) error(?::|$)|stream idle timeout\b|partial response received\b|unexpected eof\b)|\b(?:server_error|api_error|stream_exhausted(?:_without_result)?)\b|\b(?:econnreset|etimedout|econnrefused|epipe)\b|context (?:window|length) exceed|context window exceed)/i;
|
|
61
|
+
function classifyZeroToolProviderMessage(message) {
|
|
62
|
+
const firstLine = message.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
63
|
+
if (!firstLine ||
|
|
64
|
+
(!ZERO_TOOL_PROVIDER_ERROR_PREFIX_RE.test(firstLine) &&
|
|
65
|
+
!ZERO_TOOL_PROVIDER_ERROR_SIGNAL_RE.test(firstLine)))
|
|
66
|
+
return null;
|
|
67
|
+
return classifyError(firstLine);
|
|
68
|
+
}
|
|
57
69
|
export function resolveDispatchRecoveryAttempts(unitRecoveryCount, unitType, unitId) {
|
|
58
70
|
return (unitRecoveryCount.get(`${unitType}/${unitId}`) ?? 0) > 0
|
|
59
71
|
? 0
|
|
@@ -1999,6 +2011,31 @@ export async function runUnitPhase(ic, iterData, loopState, sidecarItem) {
|
|
|
1999
2011
|
if (currentLedger?.units) {
|
|
2000
2012
|
const lastUnit = [...currentLedger.units].reverse().find((u) => u.type === unitType && u.id === unitId && u.startedAt === _resolveCurrentUnitStartedAtForTest(s.currentUnit));
|
|
2001
2013
|
if (lastUnit && lastUnit.toolCalls === 0) {
|
|
2014
|
+
const lastAssistantMessage = lastAssistantText(s.lastUnitAgentEndMessages);
|
|
2015
|
+
const providerMessageClass = classifyZeroToolProviderMessage(lastAssistantMessage);
|
|
2016
|
+
if (providerMessageClass && isTransient(providerMessageClass)) {
|
|
2017
|
+
const retryAfterMs = "retryAfterMs" in providerMessageClass ? providerMessageClass.retryAfterMs : 15_000;
|
|
2018
|
+
await pauseAutoForProviderError(ctx.ui, ` for ${unitType} ${unitId}`, () => deps.pauseAuto(ctx, pi), {
|
|
2019
|
+
isRateLimit: providerMessageClass.kind === "rate-limit",
|
|
2020
|
+
isTransient: true,
|
|
2021
|
+
retryAfterMs,
|
|
2022
|
+
resume: () => {
|
|
2023
|
+
void resumeAutoAfterProviderDelay(pi, ctx).catch((err) => {
|
|
2024
|
+
logWarning("engine", `Provider error auto-resume failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2025
|
+
});
|
|
2026
|
+
},
|
|
2027
|
+
});
|
|
2028
|
+
await emitCancelledUnitEnd(ic, unitType, unitId, unitStartSeq, {
|
|
2029
|
+
message: lastAssistantMessage.slice(0, 200),
|
|
2030
|
+
category: "provider",
|
|
2031
|
+
isTransient: true,
|
|
2032
|
+
retryAfterMs,
|
|
2033
|
+
});
|
|
2034
|
+
return {
|
|
2035
|
+
action: "break",
|
|
2036
|
+
reason: providerMessageClass.kind === "rate-limit" ? "rate-limit" : "api-timeout",
|
|
2037
|
+
};
|
|
2038
|
+
}
|
|
2002
2039
|
if (USER_DRIVEN_DEEP_UNITS.has(unitType) && isAwaitingUserInput(s.lastUnitAgentEndMessages ?? undefined)) {
|
|
2003
2040
|
debugLog("runUnitPhase", {
|
|
2004
2041
|
phase: "zero-tool-calls-awaiting-user-input",
|