gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0-dev.aeeb2ca00
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 +53 -17
- package/dist/claude-cli-check.js +46 -10
- package/dist/headless.js +49 -4
- package/dist/resource-loader.d.ts +40 -0
- package/dist/resource-loader.js +32 -13
- package/dist/resources/extensions/browser-tools/capture.js +9 -0
- package/dist/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/dist/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/dist/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/dist/resources/extensions/browser-tools/tools/forms.js +5 -1
- package/dist/resources/extensions/browser-tools/tools/intent.js +5 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +72 -16
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +481 -17
- package/dist/resources/extensions/github-sync/templates.js +103 -0
- package/dist/resources/extensions/google-search/index.js +3 -2
- package/dist/resources/extensions/gsd/auto/loop.js +124 -2
- package/dist/resources/extensions/gsd/auto/phases.js +57 -39
- package/dist/resources/extensions/gsd/auto/session.js +6 -2
- package/dist/resources/extensions/gsd/auto-dispatch.js +142 -29
- package/dist/resources/extensions/gsd/auto-model-selection.js +124 -4
- package/dist/resources/extensions/gsd/auto-post-unit.js +150 -64
- package/dist/resources/extensions/gsd/auto-prompts.js +372 -104
- package/dist/resources/extensions/gsd/auto-recovery.js +197 -48
- package/dist/resources/extensions/gsd/auto-start.js +107 -29
- package/dist/resources/extensions/gsd/auto-tool-tracking.js +47 -7
- package/dist/resources/extensions/gsd/auto-worktree.js +122 -26
- package/dist/resources/extensions/gsd/auto.js +76 -21
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +19 -1
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +209 -0
- package/dist/resources/extensions/gsd/bootstrap/provider-error-resume.js +3 -6
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +7 -3
- package/dist/resources/extensions/gsd/bootstrap/write-gate.js +127 -9
- package/dist/resources/extensions/gsd/component-loader.js +447 -0
- package/dist/resources/extensions/gsd/component-types.js +69 -0
- package/dist/resources/extensions/gsd/context-store.js +23 -7
- package/dist/resources/extensions/gsd/detection.js +49 -1
- package/dist/resources/extensions/gsd/dispatch-guard.js +2 -17
- package/dist/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/dist/resources/extensions/gsd/forensics.js +106 -0
- package/dist/resources/extensions/gsd/gate-registry.js +2 -2
- package/dist/resources/extensions/gsd/git-constants.js +28 -1
- package/dist/resources/extensions/gsd/git-self-heal.js +27 -0
- package/dist/resources/extensions/gsd/git-service.js +126 -2
- package/dist/resources/extensions/gsd/gsd-db.js +6 -3
- package/dist/resources/extensions/gsd/guided-flow.js +39 -13
- package/dist/resources/extensions/gsd/memory-extractor.js +7 -1
- package/dist/resources/extensions/gsd/milestone-scope-classifier.js +299 -0
- package/dist/resources/extensions/gsd/milestone-summary-classifier.js +37 -0
- package/dist/resources/extensions/gsd/model-cost-table.js +3 -0
- package/dist/resources/extensions/gsd/model-router.js +6 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +34 -4
- package/dist/resources/extensions/gsd/preferences-validation.js +23 -0
- package/dist/resources/extensions/gsd/prompt-cache-optimizer.js +4 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/dist/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/dist/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/dist/resources/extensions/gsd/safety/git-checkpoint.js +11 -0
- package/dist/resources/extensions/gsd/service-tier.js +5 -2
- package/dist/resources/extensions/gsd/session-lock.js +19 -10
- package/dist/resources/extensions/gsd/skill-manifest.js +168 -0
- package/dist/resources/extensions/gsd/slice-cadence.js +238 -0
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +278 -8
- package/dist/resources/extensions/gsd/state-transition-matrix.js +118 -0
- package/dist/resources/extensions/gsd/state.js +69 -58
- package/dist/resources/extensions/gsd/sync-lock.js +98 -42
- package/dist/resources/extensions/gsd/tools/validate-milestone.js +7 -2
- package/dist/resources/extensions/gsd/unit-context-composer.js +147 -0
- package/dist/resources/extensions/gsd/unit-context-manifest.js +370 -0
- package/dist/resources/extensions/gsd/uok/dispatch-envelope.js +33 -0
- package/dist/resources/extensions/gsd/uok/execution-graph.js +10 -0
- package/dist/resources/extensions/gsd/uok/gate-runner.js +53 -5
- package/dist/resources/extensions/gsd/uok/gitops.js +2 -1
- package/dist/resources/extensions/gsd/uok/loop-adapter.js +37 -10
- package/dist/resources/extensions/gsd/uok/parity-report.js +58 -0
- package/dist/resources/extensions/gsd/uok/plan-v2.js +10 -4
- package/dist/resources/extensions/gsd/uok/writer.js +82 -0
- package/dist/resources/extensions/gsd/workflow-mcp.js +6 -0
- package/dist/resources/extensions/gsd/worktree-manager.js +85 -8
- package/dist/resources/extensions/gsd/worktree-resolver.js +86 -7
- package/dist/resources/extensions/gsd/worktree-telemetry.js +198 -0
- package/dist/resources/extensions/mcp-client/index.js +3 -1
- package/dist/resources/extensions/ollama/index.js +5 -1
- package/dist/resources/extensions/remote-questions/manager.js +11 -5
- 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 +11 -11
- 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/api/git/route.js +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 +11 -11
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
- package/dist/web/standalone/.next/server/chunks/6897.js +1 -1
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- 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 +2 -3
- package/packages/daemon/package.json +2 -2
- package/packages/daemon/src/logger.ts +4 -3
- package/packages/mcp-server/dist/server.d.ts +24 -0
- package/packages/mcp-server/dist/server.d.ts.map +1 -1
- package/packages/mcp-server/dist/server.js +88 -87
- package/packages/mcp-server/dist/server.js.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +15 -6
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/package.json +2 -2
- package/packages/mcp-server/src/mcp-server.test.ts +25 -3
- package/packages/mcp-server/src/readers/graph.test.ts +87 -15
- package/packages/mcp-server/src/secure-env-collect.test.ts +232 -237
- package/packages/mcp-server/src/server.ts +131 -105
- package/packages/mcp-server/src/workflow-tools.test.ts +85 -0
- package/packages/mcp-server/src/workflow-tools.ts +19 -6
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/package.json +2 -2
- package/packages/native/src/__tests__/_test-coverage-guard.test.mjs +98 -0
- package/packages/native/src/__tests__/module-compat.test.mjs +59 -27
- package/packages/native/src/__tests__/ps.test.mjs +14 -8
- package/packages/native/src/__tests__/stream-process.test.mjs +23 -2
- package/packages/native/src/__tests__/truncate.test.mjs +17 -2
- package/packages/pi-agent-core/package.json +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +5 -15
- package/packages/pi-agent-core/src/agent.test.ts +96 -102
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-ai/dist/models/capability-patches.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/capability-patches.js +9 -2
- package/packages/pi-ai/dist/models/capability-patches.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/index.d.ts +34 -0
- package/packages/pi-ai/dist/models/generated/index.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai-codex.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai-codex.js.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.d.ts +17 -0
- package/packages/pi-ai/dist/models/generated/openai.d.ts.map +1 -1
- package/packages/pi-ai/dist/models/generated/openai.js +17 -0
- package/packages/pi-ai/dist/models/generated/openai.js.map +1 -1
- package/packages/pi-ai/dist/models.generated.test.js +43 -70
- package/packages/pi-ai/dist/models.generated.test.js.map +1 -1
- package/packages/pi-ai/dist/models.test.js +36 -11
- package/packages/pi-ai/dist/models.test.js.map +1 -1
- package/packages/pi-ai/package.json +1 -1
- package/packages/pi-ai/scripts/generate-models.ts +44 -0
- package/packages/pi-ai/src/models/capability-patches.ts +10 -2
- package/packages/pi-ai/src/models/generated/openai-codex.ts +17 -0
- package/packages/pi-ai/src/models/generated/openai.ts +17 -0
- package/packages/pi-ai/src/models.generated.test.ts +46 -73
- package/packages/pi-ai/src/models.test.ts +48 -11
- package/packages/pi-ai/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +96 -32
- 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-model-switch.test.js +75 -12
- package/packages/pi-coding-agent/dist/core/agent-session-model-switch.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js +99 -31
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts +5 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/loader.js +61 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js +30 -4
- package/packages/pi-coding-agent/dist/core/lsp/lsp-integration.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js +17 -0
- package/packages/pi-coding-agent/dist/core/model-registry-auth-mode.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js +76 -18
- package/packages/pi-coding-agent/dist/core/resource-loader-cache-reset.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.js +2 -6
- package/packages/pi-coding-agent/dist/core/retry-handler.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js +5 -1
- package/packages/pi-coding-agent/dist/core/retry-handler.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js +18 -0
- package/packages/pi-coding-agent/dist/core/retryable-error-regex.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +16 -2
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/index.d.ts +1 -0
- package/packages/pi-coding-agent/dist/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/index.js +1 -0
- package/packages/pi-coding-agent/dist/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +36 -5
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js +20 -13
- package/packages/pi-coding-agent/dist/modes/interactive/components/dynamic-border.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js +30 -12
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js +18 -3
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js +125 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/input-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts +2 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode-state.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts +4 -0
- 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 +105 -13
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js +130 -0
- package/packages/pi-coding-agent/dist/tests/system-prompt-skill-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/package.json +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +113 -37
- package/packages/pi-coding-agent/src/core/agent-session-model-switch.test.ts +89 -17
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +112 -43
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +58 -0
- package/packages/pi-coding-agent/src/core/lsp/lsp-integration.test.ts +35 -4
- package/packages/pi-coding-agent/src/core/model-registry-auth-mode.test.ts +20 -0
- package/packages/pi-coding-agent/src/core/resource-loader-cache-reset.test.ts +93 -28
- package/packages/pi-coding-agent/src/core/retry-handler.test.ts +5 -1
- package/packages/pi-coding-agent/src/core/retry-handler.ts +2 -8
- package/packages/pi-coding-agent/src/core/retryable-error-regex.ts +18 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +35 -1
- package/packages/pi-coding-agent/src/index.ts +1 -0
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +49 -3
- package/packages/pi-coding-agent/src/modes/interactive/components/dynamic-border.test.ts +26 -20
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +48 -9
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.test.ts +146 -1
- package/packages/pi-coding-agent/src/modes/interactive/controllers/input-controller.ts +20 -3
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode-state.ts +2 -0
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +119 -13
- package/packages/pi-coding-agent/src/tests/system-prompt-skill-filter.test.ts +157 -0
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js +18 -8
- package/packages/pi-tui/dist/__tests__/autocomplete.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js +128 -17
- package/packages/pi-tui/dist/__tests__/overlay-layout.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js +37 -11
- package/packages/pi-tui/dist/__tests__/stdin-buffer.test.js.map +1 -1
- package/packages/pi-tui/dist/__tests__/tui.test.js +18 -30
- package/packages/pi-tui/dist/__tests__/tui.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/input.test.js +10 -3
- package/packages/pi-tui/dist/components/__tests__/input.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/loader.test.js +53 -9
- package/packages/pi-tui/dist/components/__tests__/loader.test.js.map +1 -1
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js +6 -2
- package/packages/pi-tui/dist/components/__tests__/markdown-maxlines.test.js.map +1 -1
- package/packages/pi-tui/dist/components/editor.d.ts +14 -0
- package/packages/pi-tui/dist/components/editor.d.ts.map +1 -1
- package/packages/pi-tui/dist/components/editor.js +19 -0
- package/packages/pi-tui/dist/components/editor.js.map +1 -1
- package/packages/pi-tui/dist/components/image.test.js +6 -5
- package/packages/pi-tui/dist/components/image.test.js.map +1 -1
- package/packages/pi-tui/dist/editor-component.d.ts +2 -0
- package/packages/pi-tui/dist/editor-component.d.ts.map +1 -1
- package/packages/pi-tui/dist/editor-component.js.map +1 -1
- package/packages/pi-tui/package.json +1 -1
- package/packages/pi-tui/src/__tests__/autocomplete.test.ts +24 -8
- package/packages/pi-tui/src/__tests__/overlay-layout.test.ts +140 -17
- package/packages/pi-tui/src/__tests__/stdin-buffer.test.ts +42 -11
- package/packages/pi-tui/src/__tests__/tui.test.ts +18 -37
- package/packages/pi-tui/src/components/__tests__/input.test.ts +19 -3
- package/packages/pi-tui/src/components/__tests__/loader.test.ts +112 -35
- package/packages/pi-tui/src/components/__tests__/markdown-maxlines.test.ts +9 -2
- package/packages/pi-tui/src/components/editor.ts +22 -0
- package/packages/pi-tui/src/components/image.test.ts +10 -5
- package/packages/pi-tui/src/editor-component.ts +3 -0
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/packages/rpc-client/dist/rpc-client.test.js +101 -51
- package/packages/rpc-client/dist/rpc-client.test.js.map +1 -1
- package/packages/rpc-client/package.json +1 -1
- package/packages/rpc-client/src/rpc-client.test.ts +109 -52
- package/packages/rpc-client/tsconfig.tsbuildinfo +1 -1
- package/pkg/package.json +1 -1
- package/scripts/install.js +15 -1
- package/src/resources/extensions/browser-tools/capture.ts +12 -0
- package/src/resources/extensions/browser-tools/tests/browser-tools-integration.test.mjs +8 -59
- package/src/resources/extensions/browser-tools/tests/browser-tools-unit.test.cjs +36 -24
- package/src/resources/extensions/browser-tools/tests/capture-sharp-optional.test.cjs +69 -71
- package/src/resources/extensions/browser-tools/tools/forms.ts +5 -1
- package/src/resources/extensions/browser-tools/tools/intent.ts +5 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +75 -16
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +518 -19
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +919 -75
- package/src/resources/extensions/github-sync/templates.ts +151 -0
- package/src/resources/extensions/github-sync/tests/cli.test.ts +76 -7
- package/src/resources/extensions/github-sync/tests/templates.test.ts +92 -1
- package/src/resources/extensions/google-search/index.ts +3 -2
- package/src/resources/extensions/gsd/auto/loop.ts +142 -2
- package/src/resources/extensions/gsd/auto/phases.ts +62 -38
- package/src/resources/extensions/gsd/auto/session.ts +7 -2
- package/src/resources/extensions/gsd/auto-dispatch.ts +156 -29
- package/src/resources/extensions/gsd/auto-model-selection.ts +131 -4
- package/src/resources/extensions/gsd/auto-post-unit.ts +163 -73
- package/src/resources/extensions/gsd/auto-prompts.ts +385 -93
- package/src/resources/extensions/gsd/auto-recovery.ts +230 -51
- package/src/resources/extensions/gsd/auto-start.ts +127 -9
- package/src/resources/extensions/gsd/auto-tool-tracking.ts +51 -7
- package/src/resources/extensions/gsd/auto-worktree.ts +130 -26
- package/src/resources/extensions/gsd/auto.ts +90 -23
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +20 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +221 -0
- package/src/resources/extensions/gsd/bootstrap/provider-error-resume.ts +3 -7
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +7 -3
- package/src/resources/extensions/gsd/bootstrap/write-gate.ts +158 -9
- package/src/resources/extensions/gsd/component-loader.ts +598 -0
- package/src/resources/extensions/gsd/component-types.ts +362 -0
- package/src/resources/extensions/gsd/context-store.ts +25 -8
- package/src/resources/extensions/gsd/detection.ts +58 -1
- package/src/resources/extensions/gsd/dispatch-guard.ts +2 -20
- package/src/resources/extensions/gsd/docs/preferences-reference.md +1 -1
- package/src/resources/extensions/gsd/forensics.ts +118 -1
- package/src/resources/extensions/gsd/gate-registry.ts +2 -2
- package/src/resources/extensions/gsd/git-constants.ts +30 -1
- package/src/resources/extensions/gsd/git-self-heal.ts +31 -0
- package/src/resources/extensions/gsd/git-service.ts +149 -2
- package/src/resources/extensions/gsd/gsd-db.ts +6 -3
- package/src/resources/extensions/gsd/guided-flow.ts +57 -14
- package/src/resources/extensions/gsd/journal.ts +11 -1
- package/src/resources/extensions/gsd/memory-extractor.ts +11 -3
- package/src/resources/extensions/gsd/milestone-scope-classifier.ts +366 -0
- package/src/resources/extensions/gsd/milestone-summary-classifier.ts +42 -0
- package/src/resources/extensions/gsd/model-cost-table.ts +3 -0
- package/src/resources/extensions/gsd/model-router.ts +6 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +34 -4
- package/src/resources/extensions/gsd/preferences-validation.ts +21 -0
- package/src/resources/extensions/gsd/prompt-cache-optimizer.ts +4 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +6 -2
- package/src/resources/extensions/gsd/prompts/discuss-headless.md +23 -4
- package/src/resources/extensions/gsd/prompts/doctor-heal.md +5 -4
- package/src/resources/extensions/gsd/prompts/plan-slice.md +15 -2
- package/src/resources/extensions/gsd/safety/git-checkpoint.ts +15 -0
- package/src/resources/extensions/gsd/service-tier.ts +5 -2
- package/src/resources/extensions/gsd/session-lock.ts +20 -10
- package/src/resources/extensions/gsd/skill-manifest.ts +175 -0
- package/src/resources/extensions/gsd/slice-cadence.ts +299 -0
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +309 -8
- package/src/resources/extensions/gsd/state-transition-matrix.ts +152 -0
- package/src/resources/extensions/gsd/state.ts +76 -66
- package/src/resources/extensions/gsd/sync-lock.ts +97 -39
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +270 -0
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/auto-deterministic-error-classification-4973.test.ts +341 -0
- package/src/resources/extensions/gsd/tests/auto-discuss-milestone-deadlock-4973.test.ts +264 -0
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +133 -292
- package/src/resources/extensions/gsd/tests/auto-model-selection-tool-poisoning.test.ts +742 -0
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +78 -0
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +61 -0
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +93 -0
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +4 -1
- package/src/resources/extensions/gsd/tests/auto-retry-mcp-churn-fixes.test.ts +8 -194
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +15 -58
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/canonical-milestone-root.test.ts +108 -0
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +263 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +192 -0
- package/src/resources/extensions/gsd/tests/complete-slice-verification-gate.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +16 -8
- package/src/resources/extensions/gsd/tests/component-loader.test.ts +589 -0
- package/src/resources/extensions/gsd/tests/component-types.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/context-store.test.ts +79 -0
- package/src/resources/extensions/gsd/tests/copy-planning-artifacts-samepath.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +159 -0
- package/src/resources/extensions/gsd/tests/db-access-guardrails.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/derive-state-db-disk-reconcile.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +91 -3
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +4 -4
- package/src/resources/extensions/gsd/tests/discuss-slice-structured-questions.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/discuss-tool-scope-leak.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +5 -0
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +25 -0
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +14 -0
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/double-merge-guard.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/empty-content-abort-loop.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/execution-entry-missing-context-4671.test.ts +173 -0
- package/src/resources/extensions/gsd/tests/extension-bootstrap-isolation.test.ts +139 -129
- package/src/resources/extensions/gsd/tests/finalize-timeout-guard.test.ts +8 -104
- package/src/resources/extensions/gsd/tests/gate-state-canonicalization.test.ts +102 -0
- package/src/resources/extensions/gsd/tests/gate-storage.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/google-search-stub.test.ts +14 -4
- package/src/resources/extensions/gsd/tests/headless-milestone-parity.test.ts +117 -0
- package/src/resources/extensions/gsd/tests/hook-key-parsing.test.ts +4 -55
- package/src/resources/extensions/gsd/tests/integration/all-milestones-complete-merge.test.ts +7 -56
- package/src/resources/extensions/gsd/tests/integration/auto-recovery.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/integration/doctor-proactive.test.ts +18 -2
- package/src/resources/extensions/gsd/tests/integration/queue-completed-milestone-perf.test.ts +10 -4
- package/src/resources/extensions/gsd/tests/integration/state-machine-edge-cases.test.ts +144 -7
- package/src/resources/extensions/gsd/tests/integration/state-machine-live-validation.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/integration/state-machine-runtime-failures.test.ts +2 -16
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +9 -3
- package/src/resources/extensions/gsd/tests/interrupted-session-ui.test.ts +6 -9
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +93 -1
- package/src/resources/extensions/gsd/tests/mcp-client-security.test.ts +8 -37
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +5 -15
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +227 -55
- package/src/resources/extensions/gsd/tests/milestone-scope-classifier.test.ts +187 -0
- package/src/resources/extensions/gsd/tests/milestone-summary-classifier.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/model-cost-table.test.ts +9 -1
- package/src/resources/extensions/gsd/tests/model-router.test.ts +1 -1
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +6 -48
- package/src/resources/extensions/gsd/tests/notification-widget.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/orphaned-worktree-audit.test.ts +59 -2
- package/src/resources/extensions/gsd/tests/parallel-research-dispatch.test.ts +273 -130
- package/src/resources/extensions/gsd/tests/pipeline-variant-dispatch.test.ts +301 -0
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/prompt-cache-optimizer.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +15 -4
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +23 -24
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/queued-discuss-fast-path.test.ts +4 -5
- package/src/resources/extensions/gsd/tests/ready-phrase-no-files-4573.test.ts +75 -2
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/recovery-attempts-reset.test.ts +8 -40
- package/src/resources/extensions/gsd/tests/regex-hardening.test.ts +136 -256
- package/src/resources/extensions/gsd/tests/research-milestone-composer.test.ts +114 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/run-uat-composer.test.ts +148 -0
- package/src/resources/extensions/gsd/tests/service-tier.test.ts +4 -0
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +29 -0
- package/src/resources/extensions/gsd/tests/sidecar-queue.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/silent-catch-diagnostics.test.ts +55 -95
- package/src/resources/extensions/gsd/tests/single-writer-v3-tool-surface.test.ts +158 -0
- package/src/resources/extensions/gsd/tests/skill-activation.test.ts +120 -1
- package/src/resources/extensions/gsd/tests/skill-manifest.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +164 -1
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +2 -1
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/state-machine-full-walkthrough.test.ts +29 -5
- package/src/resources/extensions/gsd/tests/state-transition-matrix.test.ts +44 -0
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/structured-data-formatter.test.ts +11 -92
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +7 -6
- package/src/resources/extensions/gsd/tests/survivor-branch-complete.test.ts +102 -101
- package/src/resources/extensions/gsd/tests/sync-lock.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +4 -3
- package/src/resources/extensions/gsd/tests/test-helpers.test.ts +98 -0
- package/src/resources/extensions/gsd/tests/test-helpers.ts +153 -0
- package/src/resources/extensions/gsd/tests/token-profile.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/tool-invocation-error-loop-break.test.ts +61 -1
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +8 -1
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +355 -0
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +258 -0
- package/src/resources/extensions/gsd/tests/uok-contracts.test.ts +51 -0
- package/src/resources/extensions/gsd/tests/uok-execution-graph.test.ts +16 -0
- package/src/resources/extensions/gsd/tests/uok-gate-runner.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/uok-gitops-wiring.test.ts +49 -26
- package/src/resources/extensions/gsd/tests/uok-loop-adapter-writer.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/uok-parity-report.test.ts +42 -0
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +19 -2
- package/src/resources/extensions/gsd/tests/uok-writer.test.ts +75 -0
- package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/verify-artifact-tightened.test.ts +144 -80
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +342 -277
- package/src/resources/extensions/gsd/tests/worker-model-override.test.ts +37 -29
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +226 -266
- package/src/resources/extensions/gsd/tests/worktree-health-monorepo.test.ts +103 -67
- package/src/resources/extensions/gsd/tests/worktree-nested-git-safety.test.ts +92 -90
- package/src/resources/extensions/gsd/tests/worktree-submodule-safety.test.ts +238 -59
- package/src/resources/extensions/gsd/tests/worktree-sync-overwrite-loop.test.ts +113 -161
- package/src/resources/extensions/gsd/tests/worktree-telemetry.test.ts +210 -0
- package/src/resources/extensions/gsd/tests/write-gate-planning-unit.test.ts +262 -0
- package/src/resources/extensions/gsd/tests/write-gate-predicates.test.ts +186 -0
- package/src/resources/extensions/gsd/tests/write-gate.test.ts +7 -5
- package/src/resources/extensions/gsd/tests/zombie-gsd-state.test.ts +80 -96
- package/src/resources/extensions/gsd/tools/validate-milestone.ts +8 -2
- package/src/resources/extensions/gsd/types.ts +3 -3
- package/src/resources/extensions/gsd/unit-context-composer.ts +218 -0
- package/src/resources/extensions/gsd/unit-context-manifest.ts +574 -0
- package/src/resources/extensions/gsd/uok/contracts.ts +65 -0
- package/src/resources/extensions/gsd/uok/dispatch-envelope.ts +56 -0
- package/src/resources/extensions/gsd/uok/execution-graph.ts +22 -0
- package/src/resources/extensions/gsd/uok/gate-runner.ts +65 -5
- package/src/resources/extensions/gsd/uok/gitops.ts +6 -1
- package/src/resources/extensions/gsd/uok/loop-adapter.ts +45 -10
- package/src/resources/extensions/gsd/uok/parity-report.ts +84 -0
- package/src/resources/extensions/gsd/uok/plan-v2.ts +13 -5
- package/src/resources/extensions/gsd/uok/writer.ts +113 -0
- package/src/resources/extensions/gsd/workflow-mcp.ts +6 -0
- package/src/resources/extensions/gsd/worktree-manager.ts +108 -7
- package/src/resources/extensions/gsd/worktree-resolver.ts +96 -9
- package/src/resources/extensions/gsd/worktree-telemetry.ts +322 -0
- package/src/resources/extensions/mcp-client/index.ts +3 -1
- package/src/resources/extensions/mcp-client/tests/server-name-spaces.test.ts +70 -36
- package/src/resources/extensions/ollama/index.ts +5 -1
- package/src/resources/extensions/ollama/ollama-auth-mode.test.ts +123 -15
- package/src/resources/extensions/ollama/ollama-status-indicator.test.ts +206 -19
- package/src/resources/extensions/remote-questions/manager.ts +36 -4
- package/src/resources/extensions/remote-questions/tests/command-polling.test.ts +200 -190
- package/src/resources/extensions/shared/tests/interview-preview.test.ts +11 -3
- package/src/resources/extensions/voice/tests/linux-ready.test.ts +129 -113
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts +0 -2
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.d.ts.map +0 -1
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js +0 -289
- package/packages/pi-ai/dist/utils/oauth/oauth-providers.test.js.map +0 -1
- package/packages/pi-ai/src/utils/oauth/oauth-providers.test.ts +0 -363
- package/src/resources/extensions/gsd/tests/auto-start-model-capture.test.ts +0 -143
- package/src/resources/extensions/gsd/tests/complete-milestone-false-merge.test.ts +0 -157
- package/src/resources/extensions/gsd/tests/dashboard-model-label-ordering.test.ts +0 -107
- package/src/resources/extensions/gsd/tests/find-missing-summaries-closed.test.ts +0 -48
- package/src/resources/extensions/gsd/tests/forensics-context-persist.test.ts +0 -159
- package/src/resources/extensions/gsd/tests/forensics-db-completion.test.ts +0 -96
- package/src/resources/extensions/gsd/tests/forensics-dedup.test.ts +0 -79
- package/src/resources/extensions/gsd/tests/forensics-hook-key-parse.test.ts +0 -74
- package/src/resources/extensions/gsd/tests/forensics-journal.test.ts +0 -162
- package/src/resources/extensions/gsd/tests/gitignore-bg-shell.test.ts +0 -38
- package/src/resources/extensions/gsd/tests/gsd-no-project-error.test.ts +0 -73
- package/src/resources/extensions/gsd/tests/idle-watchdog-stall-override.test.ts +0 -125
- package/src/resources/extensions/gsd/tests/import-done-milestones.test.ts +0 -42
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → cAJH99yNS1UPbeSEiNRrV}/_ssgManifest.js +0 -0
|
@@ -1,363 +0,0 @@
|
|
|
1
|
-
import { describe, test } from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
import type { Model, Api } from "../../types.js";
|
|
7
|
-
import type { OAuthCredentials } from "./types.js";
|
|
8
|
-
|
|
9
|
-
// Test files that need to import from the OAuth modules
|
|
10
|
-
import {
|
|
11
|
-
githubCopilotOAuthProvider,
|
|
12
|
-
normalizeDomain,
|
|
13
|
-
getGitHubCopilotBaseUrl,
|
|
14
|
-
} from "./github-copilot.js";
|
|
15
|
-
import { antigravityOAuthProvider } from "./google-antigravity.js";
|
|
16
|
-
import { geminiCliOAuthProvider } from "./google-gemini-cli.js";
|
|
17
|
-
|
|
18
|
-
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
19
|
-
|
|
20
|
-
// Local type for Copilot credentials (includes optional fields)
|
|
21
|
-
type CopilotCredentials = OAuthCredentials & {
|
|
22
|
-
enterpriseUrl?: string;
|
|
23
|
-
modelLimits?: Record<string, { contextWindow: number; maxTokens: number }>;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
// Helper to create a minimal model for testing
|
|
27
|
-
function createModel(overrides: Partial<Model<Api>> = {}): Model<Api> {
|
|
28
|
-
return {
|
|
29
|
-
id: "test-model",
|
|
30
|
-
name: "Test Model",
|
|
31
|
-
api: "openai-completions",
|
|
32
|
-
provider: "test-provider",
|
|
33
|
-
baseUrl: "https://example.com",
|
|
34
|
-
reasoning: false,
|
|
35
|
-
input: ["text"],
|
|
36
|
-
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
|
|
37
|
-
contextWindow: 128000,
|
|
38
|
-
maxTokens: 8192,
|
|
39
|
-
...overrides,
|
|
40
|
-
} as Model<Api>;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
-
// GitHub Copilot OAuth Provider Tests
|
|
45
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
46
|
-
|
|
47
|
-
describe("GitHub Copilot OAuth — normalizeDomain", () => {
|
|
48
|
-
test("returns null for empty input", () => {
|
|
49
|
-
assert.equal(normalizeDomain(""), null);
|
|
50
|
-
assert.equal(normalizeDomain(" "), null);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("returns null for invalid domain", () => {
|
|
54
|
-
assert.equal(normalizeDomain("not a domain!@#"), null);
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("extracts hostname from full URL", () => {
|
|
58
|
-
assert.equal(normalizeDomain("https://github.com"), "github.com");
|
|
59
|
-
assert.equal(normalizeDomain("https://company.ghe.com"), "company.ghe.com");
|
|
60
|
-
assert.equal(normalizeDomain("http://example.com/path"), "example.com");
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("returns domain as-is when no protocol", () => {
|
|
64
|
-
assert.equal(normalizeDomain("github.com"), "github.com");
|
|
65
|
-
assert.equal(normalizeDomain("company.ghe.com"), "company.ghe.com");
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
test("trims whitespace", () => {
|
|
69
|
-
assert.equal(normalizeDomain(" github.com "), "github.com");
|
|
70
|
-
});
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
describe("GitHub Copilot OAuth — getBaseUrlFromToken", () => {
|
|
74
|
-
test("extracts API URL from token with proxy-ep", () => {
|
|
75
|
-
// Token format: tid=...;exp=...;proxy-ep=proxy.individual.githubcopilot.com;...
|
|
76
|
-
const token = "tid=123;exp=1234567890;proxy-ep=proxy.individual.githubcopilot.com;other=value";
|
|
77
|
-
const baseUrl = getGitHubCopilotBaseUrl(token);
|
|
78
|
-
assert.equal(baseUrl, "https://api.individual.githubcopilot.com");
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("extracts API URL from enterprise proxy-ep", () => {
|
|
82
|
-
const token = "tid=123;exp=1234567890;proxy-ep=proxy.company.ghe.com;other=value";
|
|
83
|
-
const baseUrl = getGitHubCopilotBaseUrl(token);
|
|
84
|
-
assert.equal(baseUrl, "https://api.company.ghe.com");
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
test("falls back to default when no token provided", () => {
|
|
88
|
-
const baseUrl = getGitHubCopilotBaseUrl();
|
|
89
|
-
assert.equal(baseUrl, "https://api.individual.githubcopilot.com");
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
test("falls back to default when token has no proxy-ep", () => {
|
|
93
|
-
const token = "tid=123;exp=1234567890;other=value";
|
|
94
|
-
const baseUrl = getGitHubCopilotBaseUrl(token);
|
|
95
|
-
assert.equal(baseUrl, "https://api.individual.githubcopilot.com");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("uses enterprise domain when provided", () => {
|
|
99
|
-
const baseUrl = getGitHubCopilotBaseUrl(undefined, "company.ghe.com");
|
|
100
|
-
assert.equal(baseUrl, "https://copilot-api.company.ghe.com");
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
test("prioritizes token proxy-ep over enterprise domain", () => {
|
|
104
|
-
const token = "tid=123;exp=1234567890;proxy-ep=proxy.individual.githubcopilot.com;other=value";
|
|
105
|
-
const baseUrl = getGitHubCopilotBaseUrl(token, "company.ghe.com");
|
|
106
|
-
assert.equal(baseUrl, "https://api.individual.githubcopilot.com");
|
|
107
|
-
});
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
describe("GitHub Copilot OAuth — provider structure", () => {
|
|
111
|
-
test("has correct id and name", () => {
|
|
112
|
-
assert.equal(githubCopilotOAuthProvider.id, "github-copilot");
|
|
113
|
-
assert.equal(githubCopilotOAuthProvider.name, "GitHub Copilot");
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
test("has required methods", () => {
|
|
117
|
-
assert.equal(typeof githubCopilotOAuthProvider.login, "function");
|
|
118
|
-
assert.equal(typeof githubCopilotOAuthProvider.refreshToken, "function");
|
|
119
|
-
assert.equal(typeof githubCopilotOAuthProvider.getApiKey, "function");
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("getApiKey returns access token", () => {
|
|
123
|
-
const credentials: OAuthCredentials = {
|
|
124
|
-
access: "test-access-token",
|
|
125
|
-
refresh: "test-refresh-token",
|
|
126
|
-
expires: Date.now() + 3600000,
|
|
127
|
-
};
|
|
128
|
-
const apiKey = githubCopilotOAuthProvider.getApiKey(credentials);
|
|
129
|
-
assert.equal(apiKey, "test-access-token");
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
test("modifyModels preserves non-Copilot models", () => {
|
|
133
|
-
if (!githubCopilotOAuthProvider.modifyModels) return;
|
|
134
|
-
const models = [createModel({ id: "gpt-4", provider: "openai" })];
|
|
135
|
-
const credentials: OAuthCredentials = {
|
|
136
|
-
access: "test-token",
|
|
137
|
-
refresh: "test-refresh",
|
|
138
|
-
expires: Date.now() + 3600000,
|
|
139
|
-
};
|
|
140
|
-
const result = githubCopilotOAuthProvider.modifyModels(models, credentials);
|
|
141
|
-
assert.deepEqual(result, models);
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
test("modifyModels updates Copilot model baseUrl when token has proxy-ep", () => {
|
|
145
|
-
if (!githubCopilotOAuthProvider.modifyModels) return;
|
|
146
|
-
const models = [
|
|
147
|
-
createModel({
|
|
148
|
-
id: "claude-3.5-sonnet",
|
|
149
|
-
provider: "github-copilot",
|
|
150
|
-
baseUrl: "https://api.default.com",
|
|
151
|
-
}),
|
|
152
|
-
];
|
|
153
|
-
const credentials: CopilotCredentials = {
|
|
154
|
-
access: "tid=123;exp=1234567890;proxy-ep=proxy.individual.githubcopilot.com;",
|
|
155
|
-
refresh: "test-refresh",
|
|
156
|
-
expires: Date.now() + 3600000,
|
|
157
|
-
};
|
|
158
|
-
const result = githubCopilotOAuthProvider.modifyModels(models, credentials);
|
|
159
|
-
assert.equal(result[0].baseUrl, "https://api.individual.githubcopilot.com");
|
|
160
|
-
});
|
|
161
|
-
|
|
162
|
-
test("modifyModels applies model limits when available", () => {
|
|
163
|
-
if (!githubCopilotOAuthProvider.modifyModels) return;
|
|
164
|
-
const models = [
|
|
165
|
-
createModel({
|
|
166
|
-
id: "claude-3.5-sonnet",
|
|
167
|
-
provider: "github-copilot",
|
|
168
|
-
baseUrl: "https://api.default.com",
|
|
169
|
-
}),
|
|
170
|
-
];
|
|
171
|
-
const credentials: CopilotCredentials = {
|
|
172
|
-
access: "test-token",
|
|
173
|
-
refresh: "test-refresh",
|
|
174
|
-
expires: Date.now() + 3600000,
|
|
175
|
-
modelLimits: {
|
|
176
|
-
"claude-3.5-sonnet": { contextWindow: 123456, maxTokens: 4096 },
|
|
177
|
-
},
|
|
178
|
-
};
|
|
179
|
-
const result = githubCopilotOAuthProvider.modifyModels(models, credentials);
|
|
180
|
-
assert.equal(result[0].contextWindow, 123456);
|
|
181
|
-
assert.equal(result[0].maxTokens, 4096);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
186
|
-
// Antigravity OAuth Provider Tests
|
|
187
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
188
|
-
|
|
189
|
-
describe("Antigravity OAuth — provider structure", () => {
|
|
190
|
-
test("has correct id and name", () => {
|
|
191
|
-
assert.equal(antigravityOAuthProvider.id, "google-antigravity");
|
|
192
|
-
assert.equal(antigravityOAuthProvider.name, "Antigravity (Gemini 3, Claude, GPT-OSS)");
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
test("uses callback server", () => {
|
|
196
|
-
assert.equal(antigravityOAuthProvider.usesCallbackServer, true);
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
test("has required methods", () => {
|
|
200
|
-
assert.equal(typeof antigravityOAuthProvider.login, "function");
|
|
201
|
-
assert.equal(typeof antigravityOAuthProvider.refreshToken, "function");
|
|
202
|
-
assert.equal(typeof antigravityOAuthProvider.getApiKey, "function");
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
test("getApiKey returns JSON with token and projectId", () => {
|
|
206
|
-
const credentials: OAuthCredentials = {
|
|
207
|
-
access: "test-access-token",
|
|
208
|
-
refresh: "test-refresh-token",
|
|
209
|
-
expires: Date.now() + 3600000,
|
|
210
|
-
projectId: "test-project-123",
|
|
211
|
-
email: "test@example.com",
|
|
212
|
-
};
|
|
213
|
-
const apiKey = antigravityOAuthProvider.getApiKey(credentials);
|
|
214
|
-
assert.equal(typeof apiKey, "string");
|
|
215
|
-
const parsed = JSON.parse(apiKey);
|
|
216
|
-
assert.equal(parsed.token, "test-access-token");
|
|
217
|
-
assert.equal(parsed.projectId, "test-project-123");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("refreshToken throws when projectId is missing", async () => {
|
|
221
|
-
const credentials: OAuthCredentials = {
|
|
222
|
-
access: "test-access-token",
|
|
223
|
-
refresh: "test-refresh-token",
|
|
224
|
-
expires: Date.now() + 3600000,
|
|
225
|
-
};
|
|
226
|
-
await assert.rejects(
|
|
227
|
-
antigravityOAuthProvider.refreshToken(credentials),
|
|
228
|
-
/Antigravity credentials missing projectId/,
|
|
229
|
-
);
|
|
230
|
-
});
|
|
231
|
-
});
|
|
232
|
-
|
|
233
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
234
|
-
// Gemini CLI OAuth Provider Tests
|
|
235
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
236
|
-
|
|
237
|
-
describe("Gemini CLI OAuth — provider structure", () => {
|
|
238
|
-
test("has correct id and name", () => {
|
|
239
|
-
assert.equal(geminiCliOAuthProvider.id, "google-gemini-cli");
|
|
240
|
-
assert.equal(geminiCliOAuthProvider.name, "Google Cloud Code Assist (Gemini CLI)");
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
test("uses callback server", () => {
|
|
244
|
-
assert.equal(geminiCliOAuthProvider.usesCallbackServer, true);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
test("has required methods", () => {
|
|
248
|
-
assert.equal(typeof geminiCliOAuthProvider.login, "function");
|
|
249
|
-
assert.equal(typeof geminiCliOAuthProvider.refreshToken, "function");
|
|
250
|
-
assert.equal(typeof geminiCliOAuthProvider.getApiKey, "function");
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
test("getApiKey returns JSON with token and projectId", () => {
|
|
254
|
-
const credentials: OAuthCredentials = {
|
|
255
|
-
access: "test-access-token",
|
|
256
|
-
refresh: "test-refresh-token",
|
|
257
|
-
expires: Date.now() + 3600000,
|
|
258
|
-
projectId: "test-project-456",
|
|
259
|
-
email: "test@example.com",
|
|
260
|
-
};
|
|
261
|
-
const apiKey = geminiCliOAuthProvider.getApiKey(credentials);
|
|
262
|
-
assert.equal(typeof apiKey, "string");
|
|
263
|
-
const parsed = JSON.parse(apiKey);
|
|
264
|
-
assert.equal(parsed.token, "test-access-token");
|
|
265
|
-
assert.equal(parsed.projectId, "test-project-456");
|
|
266
|
-
});
|
|
267
|
-
|
|
268
|
-
test("refreshToken throws when projectId is missing", async () => {
|
|
269
|
-
const credentials: OAuthCredentials = {
|
|
270
|
-
access: "test-access-token",
|
|
271
|
-
refresh: "test-refresh-token",
|
|
272
|
-
expires: Date.now() + 3600000,
|
|
273
|
-
};
|
|
274
|
-
await assert.rejects(
|
|
275
|
-
geminiCliOAuthProvider.refreshToken(credentials),
|
|
276
|
-
/Google Cloud credentials missing projectId/,
|
|
277
|
-
);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
282
|
-
// Regression tests for credential de-obfuscation
|
|
283
|
-
//
|
|
284
|
-
// These tests verify that OAuth credentials are stored in plaintext
|
|
285
|
-
// (not base64-encoded) after the refactor in commit 289bb325c.
|
|
286
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
287
|
-
|
|
288
|
-
describe("OAuth credentials — de-obfuscated regression", () => {
|
|
289
|
-
// Verify we can import the modules without decoding errors
|
|
290
|
-
test("GitHub Copilot module imports successfully", () => {
|
|
291
|
-
// If the module imports, the CLIENT_ID is valid plaintext
|
|
292
|
-
assert.ok(githubCopilotOAuthProvider);
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
test("Antigravity module imports successfully", () => {
|
|
296
|
-
assert.ok(antigravityOAuthProvider);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
test("Gemini CLI module imports successfully", () => {
|
|
300
|
-
assert.ok(geminiCliOAuthProvider);
|
|
301
|
-
});
|
|
302
|
-
|
|
303
|
-
test("GitHub Copilot CLIENT_ID is plaintext (not base64)", () => {
|
|
304
|
-
const content = readFileSync(join(__dirname, "github-copilot.ts"), "utf-8");
|
|
305
|
-
// Should contain plaintext CLIENT_ID
|
|
306
|
-
assert.ok(content.includes('CLIENT_ID = "Iv1.b507a08c87ecfe98"'));
|
|
307
|
-
// Should NOT contain atob calls for de-obfuscation
|
|
308
|
-
assert.ok(!content.includes("atob("));
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
test("Antigravity CLIENT_ID and CLIENT_SECRET are plaintext", () => {
|
|
312
|
-
const content = readFileSync(join(__dirname, "google-antigravity.ts"), "utf-8");
|
|
313
|
-
// Should contain plaintext credentials
|
|
314
|
-
assert.ok(
|
|
315
|
-
content.includes(
|
|
316
|
-
'CLIENT_ID = "1071006060591-tmhssin2h21lcre235vtolojh4g403ep.apps.googleusercontent.com"',
|
|
317
|
-
),
|
|
318
|
-
);
|
|
319
|
-
assert.ok(
|
|
320
|
-
content.includes('CLIENT_SECRET = "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"'),
|
|
321
|
-
);
|
|
322
|
-
// Should NOT contain atob calls for de-obfuscation
|
|
323
|
-
assert.ok(!content.includes("atob("));
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
test("Gemini CLI CLIENT_ID and CLIENT_SECRET are plaintext", () => {
|
|
327
|
-
const content = readFileSync(join(__dirname, "google-gemini-cli.ts"), "utf-8");
|
|
328
|
-
// Should contain plaintext credentials
|
|
329
|
-
assert.ok(
|
|
330
|
-
content.includes(
|
|
331
|
-
'CLIENT_ID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"',
|
|
332
|
-
),
|
|
333
|
-
);
|
|
334
|
-
assert.ok(
|
|
335
|
-
content.includes('CLIENT_SECRET = "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"'),
|
|
336
|
-
);
|
|
337
|
-
// Should NOT contain atob calls for de-obfuscation
|
|
338
|
-
assert.ok(!content.includes("atob("));
|
|
339
|
-
});
|
|
340
|
-
|
|
341
|
-
test("all OAuth files include security explanation comments", () => {
|
|
342
|
-
const files = [
|
|
343
|
-
"github-copilot.ts",
|
|
344
|
-
"google-antigravity.ts",
|
|
345
|
-
"google-gemini-cli.ts",
|
|
346
|
-
];
|
|
347
|
-
|
|
348
|
-
for (const file of files) {
|
|
349
|
-
const content = readFileSync(join(__dirname, file), "utf-8");
|
|
350
|
-
// Should include explanation of why credentials are public
|
|
351
|
-
assert.ok(
|
|
352
|
-
content.includes("NOTE: This credential is public") ||
|
|
353
|
-
content.includes("NOTE: These credentials are public"),
|
|
354
|
-
`${file} should explain why credentials are public`,
|
|
355
|
-
);
|
|
356
|
-
assert.ok(
|
|
357
|
-
content.includes("obfuscated") ||
|
|
358
|
-
content.includes("security scanners"),
|
|
359
|
-
`${file} should reference the security scanner issue`,
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
});
|
|
363
|
-
});
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import test from "node:test";
|
|
2
|
-
import assert from "node:assert/strict";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
|
|
6
|
-
const sourcePath = join(import.meta.dirname, "..", "auto-start.ts");
|
|
7
|
-
const source = readFileSync(sourcePath, "utf-8");
|
|
8
|
-
|
|
9
|
-
test("bootstrapAutoSession snapshots ctx.model before guided-flow entry (#2829)", () => {
|
|
10
|
-
// The snapshot ordering guarantee still holds: build snapshot before guided-flow.
|
|
11
|
-
const snapshotIdx = source.indexOf("const startModelSnapshot = manualSessionOverride");
|
|
12
|
-
assert.ok(snapshotIdx > -1, "auto-start.ts should snapshot model at bootstrap start");
|
|
13
|
-
|
|
14
|
-
const firstDiscussIdx = source.indexOf('await showSmartEntry(ctx, pi, base, { step: requestedStepMode });');
|
|
15
|
-
assert.ok(firstDiscussIdx > -1, "auto-start.ts should route through showSmartEntry during guided flow");
|
|
16
|
-
|
|
17
|
-
assert.ok(
|
|
18
|
-
snapshotIdx < firstDiscussIdx,
|
|
19
|
-
"auto-start.ts must capture the start model before guided-flow can mutate ctx.model",
|
|
20
|
-
);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
test("bootstrapAutoSession restores autoModeStartModel from the early snapshot (#2829)", () => {
|
|
24
|
-
const assignmentIdx = source.indexOf("s.autoModeStartModel = {");
|
|
25
|
-
assert.ok(assignmentIdx > -1, "auto-start.ts should assign autoModeStartModel");
|
|
26
|
-
|
|
27
|
-
const snapshotRefIdx = source.indexOf("provider: startModelSnapshot.provider", assignmentIdx);
|
|
28
|
-
assert.ok(snapshotRefIdx > -1, "autoModeStartModel should be restored from startModelSnapshot");
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
test("bootstrapAutoSession checks manual session override before preferences", () => {
|
|
32
|
-
const manualIdx = source.indexOf("const manualSessionOverride = getSessionModelOverride(");
|
|
33
|
-
assert.ok(manualIdx > -1, "auto-start.ts should read session model override first");
|
|
34
|
-
|
|
35
|
-
// resolveDefaultSessionModel() should still be called for fallback behavior
|
|
36
|
-
const preferredIdx = source.indexOf("const preferredModel = ");
|
|
37
|
-
assert.ok(preferredIdx > -1, "auto-start.ts should build preferredModel");
|
|
38
|
-
assert.ok(
|
|
39
|
-
source.indexOf("resolveDefaultSessionModel(") > -1,
|
|
40
|
-
"auto-start.ts should call resolveDefaultSessionModel()",
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
// Session provider should be passed for bare model ID resolution
|
|
44
|
-
const withProviderIdx = source.indexOf("resolveDefaultSessionModel(ctx.model?.provider)");
|
|
45
|
-
assert.ok(withProviderIdx > -1, "auto-start.ts should pass ctx.model?.provider for bare ID resolution");
|
|
46
|
-
|
|
47
|
-
const snapshotIdx = source.indexOf("const startModelSnapshot = manualSessionOverride");
|
|
48
|
-
assert.ok(snapshotIdx > -1, "startModelSnapshot should prefer manual session override");
|
|
49
|
-
|
|
50
|
-
assert.ok(
|
|
51
|
-
manualIdx < snapshotIdx && preferredIdx < snapshotIdx,
|
|
52
|
-
"manual override and preference fallback must be resolved before building startModelSnapshot",
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
// Preferred model should still be part of fallback resolution.
|
|
56
|
-
const snapshotBlock = source.slice(snapshotIdx, snapshotIdx + 400);
|
|
57
|
-
assert.ok(
|
|
58
|
-
snapshotBlock.includes("validatedPreferredModel") || snapshotBlock.includes("preferredModel"),
|
|
59
|
-
"startModelSnapshot must still consider preferredModel for built-in providers",
|
|
60
|
-
);
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("bootstrapAutoSession prioritizes current session model over PREFERENCES.md default", () => {
|
|
64
|
-
const snapshotIdx = source.indexOf("const startModelSnapshot = manualSessionOverride");
|
|
65
|
-
assert.ok(snapshotIdx > -1, "auto-start.ts should build startModelSnapshot");
|
|
66
|
-
|
|
67
|
-
const snapshotBlock = source.slice(snapshotIdx, snapshotIdx + 500);
|
|
68
|
-
const currentIdx = snapshotBlock.indexOf("currentSessionModel");
|
|
69
|
-
const preferredIdx = snapshotBlock.indexOf("validatedPreferredModel");
|
|
70
|
-
|
|
71
|
-
assert.ok(currentIdx > -1, "startModelSnapshot should include currentSessionModel");
|
|
72
|
-
assert.ok(preferredIdx > -1, "startModelSnapshot should include validatedPreferredModel");
|
|
73
|
-
assert.ok(
|
|
74
|
-
currentIdx < preferredIdx,
|
|
75
|
-
"startModelSnapshot should prefer currentSessionModel before validatedPreferredModel",
|
|
76
|
-
);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test("bootstrapAutoSession prefers session model over PREFERENCES.md when provider is custom (#4122)", () => {
|
|
80
|
-
// Custom providers (Ollama, vLLM, OpenAI-compatible proxies) live in
|
|
81
|
-
// ~/.gsd/agent/models.json, not PREFERENCES.md. When the user picks one
|
|
82
|
-
// via /gsd model, that selection must win over any preferredModel from
|
|
83
|
-
// PREFERENCES.md, otherwise auto-mode tries to start a built-in provider
|
|
84
|
-
// the user is not logged into and pauses with "Not logged in".
|
|
85
|
-
const customCheckIdx = source.indexOf("isCustomProvider(ctx.model?.provider)");
|
|
86
|
-
assert.ok(
|
|
87
|
-
customCheckIdx > -1,
|
|
88
|
-
"auto-start.ts should call isCustomProvider() to detect custom-model sessions",
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// sessionProviderIsCustom must gate preferredModel resolution so that when the
|
|
92
|
-
// session provider is custom, preferredModel is null and PREFERENCES.md is
|
|
93
|
-
// skipped entirely — the snapshot then falls through to ctx.model.
|
|
94
|
-
const gateIdx = source.indexOf("sessionProviderIsCustom");
|
|
95
|
-
assert.ok(gateIdx > -1, "auto-start.ts should bind sessionProviderIsCustom");
|
|
96
|
-
|
|
97
|
-
const preferredIdx = source.indexOf("const preferredModel = ");
|
|
98
|
-
assert.ok(preferredIdx > -1, "auto-start.ts should build preferredModel");
|
|
99
|
-
|
|
100
|
-
const preferredBlock = source.slice(preferredIdx, preferredIdx + 200);
|
|
101
|
-
assert.ok(
|
|
102
|
-
preferredBlock.includes("sessionProviderIsCustom"),
|
|
103
|
-
"preferredModel must be gated on sessionProviderIsCustom so PREFERENCES.md is skipped for custom providers",
|
|
104
|
-
);
|
|
105
|
-
|
|
106
|
-
const snapshotIdx = source.indexOf("const startModelSnapshot = ");
|
|
107
|
-
assert.ok(snapshotIdx > -1, "auto-start.ts should build startModelSnapshot");
|
|
108
|
-
|
|
109
|
-
assert.ok(
|
|
110
|
-
customCheckIdx < preferredIdx && preferredIdx < snapshotIdx,
|
|
111
|
-
"isCustomProvider() must be evaluated before preferredModel, which must be resolved before startModelSnapshot",
|
|
112
|
-
);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("bootstrapAutoSession validates preferred model against live registry auth (#unconfigured-models)", () => {
|
|
116
|
-
// The raw PREFERENCES.md value must be validated against getAvailable()
|
|
117
|
-
// before being captured as the snapshot, so an unconfigured provider
|
|
118
|
-
// (no API key / OAuth) can't become autoModeStartModel.
|
|
119
|
-
const validationIdx = source.indexOf("ctx.modelRegistry.getAvailable()");
|
|
120
|
-
assert.ok(validationIdx > -1, "auto-start.ts should validate preferred model against getAvailable()");
|
|
121
|
-
|
|
122
|
-
const resolveModelIdIdx = source.indexOf("resolveModelId");
|
|
123
|
-
assert.ok(resolveModelIdIdx > -1, "auto-start.ts should resolve preferred model against the registry");
|
|
124
|
-
|
|
125
|
-
const warningIdx = source.indexOf("is not configured; falling back to session default");
|
|
126
|
-
assert.ok(warningIdx > -1, "auto-start.ts should warn when preferred model is unconfigured");
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
test("bootstrapAutoSession snapshots and persists thinking level for auto-mode lifecycle", () => {
|
|
130
|
-
const captureIdx = source.indexOf("const startThinkingSnapshot = pi.getThinkingLevel()");
|
|
131
|
-
assert.ok(captureIdx > -1, "auto-start.ts should snapshot thinking level at bootstrap start");
|
|
132
|
-
|
|
133
|
-
const originalThinkingIdx = source.indexOf("s.originalThinkingLevel = startThinkingSnapshot ?? null");
|
|
134
|
-
assert.ok(originalThinkingIdx > -1, "auto-start.ts should store originalThinkingLevel from snapshot");
|
|
135
|
-
|
|
136
|
-
const autoThinkingIdx = source.indexOf("s.autoModeStartThinkingLevel = startThinkingSnapshot ?? null");
|
|
137
|
-
assert.ok(autoThinkingIdx > -1, "auto-start.ts should store autoModeStartThinkingLevel from snapshot");
|
|
138
|
-
|
|
139
|
-
assert.ok(
|
|
140
|
-
captureIdx < originalThinkingIdx && captureIdx < autoThinkingIdx,
|
|
141
|
-
"thinking snapshot must be captured before session state assignment",
|
|
142
|
-
);
|
|
143
|
-
});
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* complete-milestone-false-merge.test.ts — Regression test for #4175.
|
|
3
|
-
*
|
|
4
|
-
* Before the fix, a failed complete-milestone unit could leave a stub
|
|
5
|
-
* SUMMARY blocker placeholder on disk. stopAuto's SUMMARY-presence check
|
|
6
|
-
* then treated the milestone as complete and merged the worktree branch
|
|
7
|
-
* into main — emitting a misleading metadata-only merge warning for a
|
|
8
|
-
* milestone that was never legitimately finished.
|
|
9
|
-
*
|
|
10
|
-
* The fix has three cooperating parts:
|
|
11
|
-
* 1. stopAuto uses DB status (authoritative) instead of SUMMARY presence
|
|
12
|
-
* when the project DB is available.
|
|
13
|
-
* 2. postUnitPreVerification pauses auto-mode for complete-milestone
|
|
14
|
-
* after retries are exhausted instead of writing a blocker placeholder.
|
|
15
|
-
* 3. recoverTimedOutUnit pauses for complete-milestone instead of
|
|
16
|
-
* writing a blocker placeholder.
|
|
17
|
-
*
|
|
18
|
-
* This test guards all three via source inspection so a future refactor
|
|
19
|
-
* cannot silently reintroduce the false-merge path.
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
import test from "node:test";
|
|
23
|
-
import assert from "node:assert/strict";
|
|
24
|
-
import { readFileSync } from "node:fs";
|
|
25
|
-
import { join } from "node:path";
|
|
26
|
-
|
|
27
|
-
const gsdDir = join(import.meta.dirname, "..");
|
|
28
|
-
const autoSrc = readFileSync(join(gsdDir, "auto.ts"), "utf-8");
|
|
29
|
-
const postUnitSrc = readFileSync(join(gsdDir, "auto-post-unit.ts"), "utf-8");
|
|
30
|
-
const timeoutSrc = readFileSync(join(gsdDir, "auto-timeout-recovery.ts"), "utf-8");
|
|
31
|
-
|
|
32
|
-
test("#4175: stopAuto uses DB status as the authoritative milestone-complete signal", () => {
|
|
33
|
-
const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
|
|
34
|
-
assert.ok(step4Idx !== -1, "Step 4 comment exists in stopAuto");
|
|
35
|
-
const step5Idx = autoSrc.indexOf("Step 5:", step4Idx);
|
|
36
|
-
const step4Block = autoSrc.slice(step4Idx, step5Idx);
|
|
37
|
-
|
|
38
|
-
assert.ok(
|
|
39
|
-
step4Block.includes("isDbAvailable()"),
|
|
40
|
-
"Step 4 should branch on isDbAvailable() so DB is consulted when present",
|
|
41
|
-
);
|
|
42
|
-
assert.ok(
|
|
43
|
-
step4Block.includes("getMilestone(s.currentMilestoneId)"),
|
|
44
|
-
"Step 4 should read authoritative milestone status via getMilestone()",
|
|
45
|
-
);
|
|
46
|
-
assert.ok(
|
|
47
|
-
/status\s*===\s*"complete"/.test(step4Block),
|
|
48
|
-
'Step 4 should compare the DB row status to "complete"',
|
|
49
|
-
);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test("#4175: stopAuto imports getMilestone from gsd-db", () => {
|
|
53
|
-
assert.ok(
|
|
54
|
-
/import\s*\{[^}]*\bgetMilestone\b[^}]*\}\s*from\s*"\.\/gsd-db\.js"/.test(autoSrc),
|
|
55
|
-
"auto.ts should import getMilestone from ./gsd-db.js",
|
|
56
|
-
);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
test("#4175: stopAuto still falls back to SUMMARY presence when DB is unavailable", () => {
|
|
60
|
-
const step4Idx = autoSrc.indexOf("Step 4: Auto-worktree exit");
|
|
61
|
-
const step5Idx = autoSrc.indexOf("Step 5:", step4Idx);
|
|
62
|
-
const step4Block = autoSrc.slice(step4Idx, step5Idx);
|
|
63
|
-
|
|
64
|
-
assert.ok(
|
|
65
|
-
step4Block.includes("resolveMilestoneFile"),
|
|
66
|
-
"Step 4 should keep SUMMARY-file resolution for DB-unavailable projects",
|
|
67
|
-
);
|
|
68
|
-
assert.ok(
|
|
69
|
-
step4Block.includes("preserveBranch"),
|
|
70
|
-
"Step 4 should still preserve branch for incomplete milestones (fallback path)",
|
|
71
|
-
);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
test("#4175: postUnitPreVerification pauses complete-milestone after retries exhausted", () => {
|
|
75
|
-
// The pause branch must live inside the retries-exhausted block, above the
|
|
76
|
-
// writeBlockerPlaceholder call — otherwise the stub SUMMARY is still written.
|
|
77
|
-
const retriesExhaustedIdx = postUnitSrc.indexOf(
|
|
78
|
-
"if (attempt > MAX_VERIFICATION_RETRIES)",
|
|
79
|
-
);
|
|
80
|
-
assert.ok(
|
|
81
|
-
retriesExhaustedIdx !== -1,
|
|
82
|
-
"retries-exhausted guard exists in postUnitPreVerification",
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
const blockerCallIdx = postUnitSrc.indexOf("writeBlockerPlaceholder", retriesExhaustedIdx);
|
|
86
|
-
assert.ok(
|
|
87
|
-
blockerCallIdx !== -1,
|
|
88
|
-
"blocker placeholder call still exists for non-milestone units",
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
const exhaustedBlock = postUnitSrc.slice(retriesExhaustedIdx, blockerCallIdx);
|
|
92
|
-
|
|
93
|
-
assert.ok(
|
|
94
|
-
/s\.currentUnit\.type\s*===\s*"complete-milestone"/.test(exhaustedBlock),
|
|
95
|
-
"retries-exhausted block should specifically handle complete-milestone",
|
|
96
|
-
);
|
|
97
|
-
assert.ok(
|
|
98
|
-
/pauseAuto\s*\(\s*ctx\s*,\s*pi\s*\)/.test(exhaustedBlock),
|
|
99
|
-
"complete-milestone path should call pauseAuto instead of falling through",
|
|
100
|
-
);
|
|
101
|
-
// The pause branch must return so execution never reaches writeBlockerPlaceholder.
|
|
102
|
-
assert.ok(
|
|
103
|
-
/return\s+"dispatched"\s*;/.test(exhaustedBlock),
|
|
104
|
-
"complete-milestone pause branch should return before the placeholder call",
|
|
105
|
-
);
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
test("#4658: postUnitPreVerification waits briefly for DB-close on complete-milestone before retrying", () => {
|
|
109
|
-
assert.ok(
|
|
110
|
-
/async function waitForMilestoneDbClose/.test(postUnitSrc),
|
|
111
|
-
"auto-post-unit should define a DB settle helper for complete-milestone",
|
|
112
|
-
);
|
|
113
|
-
assert.ok(
|
|
114
|
-
/setTimeout\(resolve,\s*COMPLETE_MILESTONE_DB_SETTLE_POLL_MS\)/.test(postUnitSrc),
|
|
115
|
-
"DB settle helper should poll with a bounded timeout window",
|
|
116
|
-
);
|
|
117
|
-
assert.ok(
|
|
118
|
-
/s\.currentUnit\.type\s*===\s*"complete-milestone"[\s\S]*waitForMilestoneDbClose/.test(postUnitSrc),
|
|
119
|
-
"complete-milestone path should invoke DB settle check before retry flow",
|
|
120
|
-
);
|
|
121
|
-
});
|
|
122
|
-
|
|
123
|
-
test("#4175: recoverTimedOutUnit pauses complete-milestone instead of writing a blocker placeholder", () => {
|
|
124
|
-
// The complete-milestone pause branch must sit immediately above the
|
|
125
|
-
// "retries exhausted" writeBlockerPlaceholder call so a failed
|
|
126
|
-
// complete-milestone never produces a stub SUMMARY. Anchor on the
|
|
127
|
-
// comment that precedes that specific placeholder call rather than the
|
|
128
|
-
// function's earlier writeBlockerPlaceholder use sites or its import.
|
|
129
|
-
// Use lastIndexOf so we find the final retries-exhausted block in
|
|
130
|
-
// recoverTimedOutUnit, not an earlier helper with the same comment.
|
|
131
|
-
const exhaustedAnchor = "Retries exhausted — write a blocker placeholder";
|
|
132
|
-
const exhaustedIdx = timeoutSrc.lastIndexOf(exhaustedAnchor);
|
|
133
|
-
assert.ok(
|
|
134
|
-
exhaustedIdx !== -1,
|
|
135
|
-
"retries-exhausted blocker-placeholder path still exists for non-milestone units",
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
const guardIdx = timeoutSrc.lastIndexOf(
|
|
139
|
-
'unitType === "complete-milestone"',
|
|
140
|
-
exhaustedIdx,
|
|
141
|
-
);
|
|
142
|
-
assert.ok(
|
|
143
|
-
guardIdx !== -1,
|
|
144
|
-
"complete-milestone guard should appear above the retries-exhausted placeholder call",
|
|
145
|
-
);
|
|
146
|
-
|
|
147
|
-
const guardBlock = timeoutSrc.slice(guardIdx, exhaustedIdx);
|
|
148
|
-
assert.ok(
|
|
149
|
-
/return\s+"paused"\s*;/.test(guardBlock),
|
|
150
|
-
"complete-milestone guard should return 'paused' before the placeholder call",
|
|
151
|
-
);
|
|
152
|
-
// The guard itself must not call writeBlockerPlaceholder.
|
|
153
|
-
assert.ok(
|
|
154
|
-
!guardBlock.includes("writeBlockerPlaceholder"),
|
|
155
|
-
"complete-milestone guard must not write a blocker placeholder",
|
|
156
|
-
);
|
|
157
|
-
});
|