gsd-pi 2.77.0-dev.eaa4973bc → 2.78.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/claude-cli-check.js +5 -1
- package/dist/headless.js +49 -4
- package/dist/loader.js +0 -0
- 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 +5 -1
- 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 +12 -12
- package/dist/web/standalone/.next/build-manifest.json +3 -3
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/required-server-files.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page.js +3 -3
- package/dist/web/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.html +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/page.js +2 -2
- package/dist/web/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +3 -3
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +3 -3
- 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 +3 -3
- 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/boot/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/boot/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/bridge-terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/browse-directories/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/captures/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/cleanup/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/dev-mode/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/doctor/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/experimental/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/experimental/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/export-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/files/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/forensics/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/git/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/history/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/hooks/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/inspect/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/knowledge/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/live-state/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/notifications/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/notifications/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/onboarding/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/preferences/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/projects/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/recovery/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/remote-questions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/remote-questions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/browser/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/command/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/events/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/session/events/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/session/manage/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/settings-data/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/shutdown/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/skill-health/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/steer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/switch-root/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/input/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/input/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/resize/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route.js +2 -2
- package/dist/web/standalone/.next/server/app/api/terminal/sessions/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route.js +4 -4
- package/dist/web/standalone/.next/server/app/api/terminal/stream/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/terminal/upload/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/undo/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/update/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route.js +1 -1
- package/dist/web/standalone/.next/server/app/api/visualizer/route_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +4 -4
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +4 -4
- 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 +3 -3
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/page.js +2 -2
- package/dist/web/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +12 -12
- package/dist/web/standalone/.next/server/chunks/1926.js +1 -1
- package/dist/web/standalone/.next/server/chunks/63.js +3 -3
- package/dist/web/standalone/.next/server/chunks/6897.js +2 -2
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/middleware.js +2 -2
- package/dist/web/standalone/.next/server/next-font-manifest.js +1 -1
- package/dist/web/standalone/.next/server/next-font-manifest.json +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/dist/web/standalone/.next/static/chunks/app/_not-found/{page-f2a7482d42a5614b.js → page-2f24283c162b6ab3.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/{layout-a16c7a7ecdf0c2cf.js → layout-9ecfd95f343793f0.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/app/page-151349214571e2b6.js +1 -0
- package/dist/web/standalone/.next/static/chunks/main-app-d3d4c336195465f9.js +1 -0
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-ab5a8926e07ec673.js +1 -0
- package/dist/web/standalone/node_modules/node-pty/build/Makefile +2 -2
- package/dist/web/standalone/node_modules/node-pty/build/Release/pty.node +0 -0
- package/dist/web/standalone/node_modules/node-pty/build/pty.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_except.target.mk +14 -14
- package/dist/web/standalone/node_modules/node-pty/node-addon-api/node_addon_api_maybe.target.mk +14 -14
- package/dist/web/standalone/server.js +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 +5 -1
- 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/dist/web/standalone/.next/static/chunks/app/page-5b113fd32bc2a1c3.js +0 -1
- package/dist/web/standalone/.next/static/chunks/main-app-fdab67f7802d7832.js +0 -1
- package/dist/web/standalone/.next/static/chunks/next/dist/client/components/builtin/global-error-459824ffb8c323dd.js +0 -1
- 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 → C1zT2kEfoLhDdbWPWKrXd}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{5wbu35_C2_MQ3Jj1lEVDx → C1zT2kEfoLhDdbWPWKrXd}/_ssgManifest.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-prompt-skill-filter.test.d.ts","sourceRoot":"","sources":["../../src/tests/system-prompt-skill-filter.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @gsd/pi-coding-agent + system-prompt-skill-filter.test — coverage for the
|
|
2
|
+
// optional `skillFilter` option added to buildSystemPrompt (RFC #4779). The
|
|
3
|
+
// filter lets consumers narrow the <available_skills> catalog rendered into
|
|
4
|
+
// the cached system prompt without touching skill loading or invocation.
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import assert from "node:assert/strict";
|
|
7
|
+
import { buildSystemPrompt } from "../core/system-prompt.js";
|
|
8
|
+
function makeSkill(name, description = `description for ${name}`) {
|
|
9
|
+
return {
|
|
10
|
+
name,
|
|
11
|
+
description,
|
|
12
|
+
filePath: `/tmp/${name}/SKILL.md`,
|
|
13
|
+
baseDir: `/tmp/${name}`,
|
|
14
|
+
source: "project",
|
|
15
|
+
disableModelInvocation: false,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function extractAvailableSkills(prompt) {
|
|
19
|
+
const start = prompt.indexOf("<available_skills>");
|
|
20
|
+
const end = prompt.indexOf("</available_skills>");
|
|
21
|
+
if (start === -1 || end === -1)
|
|
22
|
+
return "";
|
|
23
|
+
return prompt.slice(start, end + "</available_skills>".length);
|
|
24
|
+
}
|
|
25
|
+
// ─── Default branch (no customPrompt) ──────────────────────────────────────
|
|
26
|
+
test("buildSystemPrompt: skillFilter omits filtered-out skills from <available_skills>", () => {
|
|
27
|
+
const skills = [makeSkill("alpha"), makeSkill("beta"), makeSkill("gamma")];
|
|
28
|
+
const prompt = buildSystemPrompt({
|
|
29
|
+
skills,
|
|
30
|
+
selectedTools: ["read", "Skill"],
|
|
31
|
+
skillFilter: skill => skill.name !== "beta",
|
|
32
|
+
});
|
|
33
|
+
const section = extractAvailableSkills(prompt);
|
|
34
|
+
assert.ok(section.length > 0, "catalog section should render");
|
|
35
|
+
assert.match(section, /<name>alpha<\/name>/);
|
|
36
|
+
assert.match(section, /<name>gamma<\/name>/);
|
|
37
|
+
assert.doesNotMatch(section, /<name>beta<\/name>/);
|
|
38
|
+
});
|
|
39
|
+
test("buildSystemPrompt: skillFilter omitted preserves pre-filter behavior (all skills render)", () => {
|
|
40
|
+
const skills = [makeSkill("alpha"), makeSkill("beta")];
|
|
41
|
+
const prompt = buildSystemPrompt({
|
|
42
|
+
skills,
|
|
43
|
+
selectedTools: ["read", "Skill"],
|
|
44
|
+
});
|
|
45
|
+
const section = extractAvailableSkills(prompt);
|
|
46
|
+
assert.match(section, /<name>alpha<\/name>/);
|
|
47
|
+
assert.match(section, /<name>beta<\/name>/);
|
|
48
|
+
});
|
|
49
|
+
test("buildSystemPrompt: skillFilter that rejects every skill suppresses the <available_skills> block", () => {
|
|
50
|
+
const skills = [makeSkill("alpha"), makeSkill("beta")];
|
|
51
|
+
const prompt = buildSystemPrompt({
|
|
52
|
+
skills,
|
|
53
|
+
selectedTools: ["read", "Skill"],
|
|
54
|
+
skillFilter: () => false,
|
|
55
|
+
});
|
|
56
|
+
// With zero visible skills, formatSkillsForPrompt returns an empty string,
|
|
57
|
+
// so the opening tag should not appear anywhere.
|
|
58
|
+
assert.ok(!prompt.includes("<available_skills>"));
|
|
59
|
+
});
|
|
60
|
+
// ─── Custom-prompt branch ──────────────────────────────────────────────────
|
|
61
|
+
test("buildSystemPrompt (customPrompt): skillFilter applies to the catalog appended onto a custom prompt", () => {
|
|
62
|
+
const skills = [makeSkill("alpha"), makeSkill("beta"), makeSkill("gamma")];
|
|
63
|
+
const prompt = buildSystemPrompt({
|
|
64
|
+
customPrompt: "CUSTOM BASE",
|
|
65
|
+
skills,
|
|
66
|
+
selectedTools: ["read", "Skill"],
|
|
67
|
+
skillFilter: skill => skill.name === "alpha",
|
|
68
|
+
});
|
|
69
|
+
const section = extractAvailableSkills(prompt);
|
|
70
|
+
assert.match(section, /<name>alpha<\/name>/);
|
|
71
|
+
assert.doesNotMatch(section, /<name>beta<\/name>/);
|
|
72
|
+
assert.doesNotMatch(section, /<name>gamma<\/name>/);
|
|
73
|
+
});
|
|
74
|
+
// ─── Interaction with disableModelInvocation ──────────────────────────────
|
|
75
|
+
test("buildSystemPrompt: skillFilter composes with disableModelInvocation (both must pass)", () => {
|
|
76
|
+
// A skill already hidden from the catalog by disableModelInvocation must
|
|
77
|
+
// remain hidden even if skillFilter would otherwise admit it. The filter
|
|
78
|
+
// narrows, it does not override the existing invisibility contract.
|
|
79
|
+
const skills = [
|
|
80
|
+
{ ...makeSkill("visible"), disableModelInvocation: false },
|
|
81
|
+
{ ...makeSkill("hidden"), disableModelInvocation: true },
|
|
82
|
+
];
|
|
83
|
+
const prompt = buildSystemPrompt({
|
|
84
|
+
skills,
|
|
85
|
+
selectedTools: ["read", "Skill"],
|
|
86
|
+
skillFilter: () => true,
|
|
87
|
+
});
|
|
88
|
+
const section = extractAvailableSkills(prompt);
|
|
89
|
+
assert.match(section, /<name>visible<\/name>/);
|
|
90
|
+
assert.doesNotMatch(section, /<name>hidden<\/name>/);
|
|
91
|
+
});
|
|
92
|
+
// ─── Pass-through of non-filtered fields ──────────────────────────────────
|
|
93
|
+
test("buildSystemPrompt: skillFilter does not affect context files or cwd rendering", () => {
|
|
94
|
+
const skills = [makeSkill("alpha")];
|
|
95
|
+
const prompt = buildSystemPrompt({
|
|
96
|
+
skills,
|
|
97
|
+
cwd: "/tmp/example",
|
|
98
|
+
contextFiles: [{ path: "CLAUDE.md", content: "project instructions" }],
|
|
99
|
+
selectedTools: ["read", "Skill"],
|
|
100
|
+
skillFilter: () => false,
|
|
101
|
+
});
|
|
102
|
+
assert.ok(prompt.includes("/tmp/example"), "cwd should still render");
|
|
103
|
+
assert.ok(prompt.includes("project instructions"), "context files should still render");
|
|
104
|
+
assert.ok(!prompt.includes("<available_skills>"), "no skill catalog when filter rejects all");
|
|
105
|
+
});
|
|
106
|
+
// ─── Exception safety ─────────────────────────────────────────────────────
|
|
107
|
+
test("buildSystemPrompt: skillFilter that throws falls back to unfiltered list and does not propagate", (t) => {
|
|
108
|
+
// A buggy consumer predicate must not bubble out of buildSystemPrompt.
|
|
109
|
+
// If it did, _rebuildSystemPrompt could unwind mid-setTools() and leave
|
|
110
|
+
// the session with updated tools but a stale system prompt.
|
|
111
|
+
const skills = [makeSkill("alpha"), makeSkill("beta")];
|
|
112
|
+
// Suppress the console.warn the fallback emits so test output stays clean.
|
|
113
|
+
const originalWarn = console.warn;
|
|
114
|
+
const warnings = [];
|
|
115
|
+
console.warn = (...args) => { warnings.push(args.join(" ")); };
|
|
116
|
+
t.after(() => { console.warn = originalWarn; });
|
|
117
|
+
let prompt = "";
|
|
118
|
+
assert.doesNotThrow(() => {
|
|
119
|
+
prompt = buildSystemPrompt({
|
|
120
|
+
skills,
|
|
121
|
+
selectedTools: ["read", "Skill"],
|
|
122
|
+
skillFilter: () => { throw new Error("consumer bug"); },
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
const section = extractAvailableSkills(prompt);
|
|
126
|
+
assert.match(section, /<name>alpha<\/name>/, "alpha should render (fallback to unfiltered)");
|
|
127
|
+
assert.match(section, /<name>beta<\/name>/, "beta should render (fallback to unfiltered)");
|
|
128
|
+
assert.ok(warnings.some(w => w.includes("skillFilter threw") && w.includes("consumer bug")), "fallback should emit an identifying warning");
|
|
129
|
+
});
|
|
130
|
+
//# sourceMappingURL=system-prompt-skill-filter.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"system-prompt-skill-filter.test.js","sourceRoot":"","sources":["../../src/tests/system-prompt-skill-filter.test.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,4EAA4E;AAC5E,4EAA4E;AAC5E,yEAAyE;AAEzE,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AAExC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAG7D,SAAS,SAAS,CAAC,IAAY,EAAE,WAAW,GAAG,mBAAmB,IAAI,EAAE;IACvE,OAAO;QACN,IAAI;QACJ,WAAW;QACX,QAAQ,EAAE,QAAQ,IAAI,WAAW;QACjC,OAAO,EAAE,QAAQ,IAAI,EAAE;QACvB,MAAM,EAAE,SAAS;QACjB,sBAAsB,EAAE,KAAK;KAC7B,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAAC,MAAc;IAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACnD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAClD,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1C,OAAO,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;AAChE,CAAC;AAED,8EAA8E;AAE9E,IAAI,CAAC,kFAAkF,EAAE,GAAG,EAAE;IAC7F,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,MAAM;QACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAChC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM;KAC3C,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,+BAA+B,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7C,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0FAA0F,EAAE,GAAG,EAAE;IACrG,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,MAAM;QACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;KAChC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;AAC7C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,iGAAiG,EAAE,GAAG,EAAE;IAC5G,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,MAAM;QACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK;KACxB,CAAC,CAAC;IAEH,2EAA2E;IAC3E,iDAAiD;IACjD,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAE9E,IAAI,CAAC,oGAAoG,EAAE,GAAG,EAAE;IAC/G,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,YAAY,EAAE,aAAa;QAC3B,MAAM;QACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAChC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO;KAC5C,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;IAC7C,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;IACnD,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAE7E,IAAI,CAAC,sFAAsF,EAAE,GAAG,EAAE;IACjG,yEAAyE;IACzE,yEAAyE;IACzE,oEAAoE;IACpE,MAAM,MAAM,GAAY;QACvB,EAAE,GAAG,SAAS,CAAC,SAAS,CAAC,EAAE,sBAAsB,EAAE,KAAK,EAAE;QAC1D,EAAE,GAAG,SAAS,CAAC,QAAQ,CAAC,EAAE,sBAAsB,EAAE,IAAI,EAAE;KACxD,CAAC;IACF,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,MAAM;QACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,IAAI;KACvB,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,uBAAuB,CAAC,CAAC;IAC/C,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAE7E,IAAI,CAAC,+EAA+E,EAAE,GAAG,EAAE;IAC1F,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACpC,MAAM,MAAM,GAAG,iBAAiB,CAAC;QAChC,MAAM;QACN,GAAG,EAAE,cAAc;QACnB,YAAY,EAAE,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;QACtE,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;QAChC,WAAW,EAAE,GAAG,EAAE,CAAC,KAAK;KACxB,CAAC,CAAC;IAEH,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,yBAAyB,CAAC,CAAC;IACtE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,mCAAmC,CAAC,CAAC;IACxF,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,0CAA0C,CAAC,CAAC;AAC/F,CAAC,CAAC,CAAC;AAEH,6EAA6E;AAE7E,IAAI,CAAC,iGAAiG,EAAE,CAAC,CAAC,EAAE,EAAE;IAC7G,uEAAuE;IACvE,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAEvD,2EAA2E;IAC3E,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1E,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;IAEhD,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE;QACxB,MAAM,GAAG,iBAAiB,CAAC;YAC1B,MAAM;YACN,aAAa,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC;YAChC,WAAW,EAAE,GAAG,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;SACvD,CAAC,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,sBAAsB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,qBAAqB,EAAE,8CAA8C,CAAC,CAAC;IAC7F,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,oBAAoB,EAAE,6CAA6C,CAAC,CAAC;IAC3F,MAAM,CAAC,EAAE,CACR,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,EACjF,6CAA6C,CAC7C,CAAC;AACH,CAAC,CAAC,CAAC","sourcesContent":["// @gsd/pi-coding-agent + system-prompt-skill-filter.test — coverage for the\n// optional `skillFilter` option added to buildSystemPrompt (RFC #4779). The\n// filter lets consumers narrow the <available_skills> catalog rendered into\n// the cached system prompt without touching skill loading or invocation.\n\nimport test from \"node:test\";\nimport assert from \"node:assert/strict\";\n\nimport { buildSystemPrompt } from \"../core/system-prompt.js\";\nimport type { Skill } from \"../core/skills.js\";\n\nfunction makeSkill(name: string, description = `description for ${name}`): Skill {\n\treturn {\n\t\tname,\n\t\tdescription,\n\t\tfilePath: `/tmp/${name}/SKILL.md`,\n\t\tbaseDir: `/tmp/${name}`,\n\t\tsource: \"project\",\n\t\tdisableModelInvocation: false,\n\t};\n}\n\nfunction extractAvailableSkills(prompt: string): string {\n\tconst start = prompt.indexOf(\"<available_skills>\");\n\tconst end = prompt.indexOf(\"</available_skills>\");\n\tif (start === -1 || end === -1) return \"\";\n\treturn prompt.slice(start, end + \"</available_skills>\".length);\n}\n\n// ─── Default branch (no customPrompt) ──────────────────────────────────────\n\ntest(\"buildSystemPrompt: skillFilter omits filtered-out skills from <available_skills>\", () => {\n\tconst skills = [makeSkill(\"alpha\"), makeSkill(\"beta\"), makeSkill(\"gamma\")];\n\tconst prompt = buildSystemPrompt({\n\t\tskills,\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t\tskillFilter: skill => skill.name !== \"beta\",\n\t});\n\n\tconst section = extractAvailableSkills(prompt);\n\tassert.ok(section.length > 0, \"catalog section should render\");\n\tassert.match(section, /<name>alpha<\\/name>/);\n\tassert.match(section, /<name>gamma<\\/name>/);\n\tassert.doesNotMatch(section, /<name>beta<\\/name>/);\n});\n\ntest(\"buildSystemPrompt: skillFilter omitted preserves pre-filter behavior (all skills render)\", () => {\n\tconst skills = [makeSkill(\"alpha\"), makeSkill(\"beta\")];\n\tconst prompt = buildSystemPrompt({\n\t\tskills,\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t});\n\n\tconst section = extractAvailableSkills(prompt);\n\tassert.match(section, /<name>alpha<\\/name>/);\n\tassert.match(section, /<name>beta<\\/name>/);\n});\n\ntest(\"buildSystemPrompt: skillFilter that rejects every skill suppresses the <available_skills> block\", () => {\n\tconst skills = [makeSkill(\"alpha\"), makeSkill(\"beta\")];\n\tconst prompt = buildSystemPrompt({\n\t\tskills,\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t\tskillFilter: () => false,\n\t});\n\n\t// With zero visible skills, formatSkillsForPrompt returns an empty string,\n\t// so the opening tag should not appear anywhere.\n\tassert.ok(!prompt.includes(\"<available_skills>\"));\n});\n\n// ─── Custom-prompt branch ──────────────────────────────────────────────────\n\ntest(\"buildSystemPrompt (customPrompt): skillFilter applies to the catalog appended onto a custom prompt\", () => {\n\tconst skills = [makeSkill(\"alpha\"), makeSkill(\"beta\"), makeSkill(\"gamma\")];\n\tconst prompt = buildSystemPrompt({\n\t\tcustomPrompt: \"CUSTOM BASE\",\n\t\tskills,\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t\tskillFilter: skill => skill.name === \"alpha\",\n\t});\n\n\tconst section = extractAvailableSkills(prompt);\n\tassert.match(section, /<name>alpha<\\/name>/);\n\tassert.doesNotMatch(section, /<name>beta<\\/name>/);\n\tassert.doesNotMatch(section, /<name>gamma<\\/name>/);\n});\n\n// ─── Interaction with disableModelInvocation ──────────────────────────────\n\ntest(\"buildSystemPrompt: skillFilter composes with disableModelInvocation (both must pass)\", () => {\n\t// A skill already hidden from the catalog by disableModelInvocation must\n\t// remain hidden even if skillFilter would otherwise admit it. The filter\n\t// narrows, it does not override the existing invisibility contract.\n\tconst skills: Skill[] = [\n\t\t{ ...makeSkill(\"visible\"), disableModelInvocation: false },\n\t\t{ ...makeSkill(\"hidden\"), disableModelInvocation: true },\n\t];\n\tconst prompt = buildSystemPrompt({\n\t\tskills,\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t\tskillFilter: () => true,\n\t});\n\n\tconst section = extractAvailableSkills(prompt);\n\tassert.match(section, /<name>visible<\\/name>/);\n\tassert.doesNotMatch(section, /<name>hidden<\\/name>/);\n});\n\n// ─── Pass-through of non-filtered fields ──────────────────────────────────\n\ntest(\"buildSystemPrompt: skillFilter does not affect context files or cwd rendering\", () => {\n\tconst skills = [makeSkill(\"alpha\")];\n\tconst prompt = buildSystemPrompt({\n\t\tskills,\n\t\tcwd: \"/tmp/example\",\n\t\tcontextFiles: [{ path: \"CLAUDE.md\", content: \"project instructions\" }],\n\t\tselectedTools: [\"read\", \"Skill\"],\n\t\tskillFilter: () => false,\n\t});\n\n\tassert.ok(prompt.includes(\"/tmp/example\"), \"cwd should still render\");\n\tassert.ok(prompt.includes(\"project instructions\"), \"context files should still render\");\n\tassert.ok(!prompt.includes(\"<available_skills>\"), \"no skill catalog when filter rejects all\");\n});\n\n// ─── Exception safety ─────────────────────────────────────────────────────\n\ntest(\"buildSystemPrompt: skillFilter that throws falls back to unfiltered list and does not propagate\", (t) => {\n\t// A buggy consumer predicate must not bubble out of buildSystemPrompt.\n\t// If it did, _rebuildSystemPrompt could unwind mid-setTools() and leave\n\t// the session with updated tools but a stale system prompt.\n\tconst skills = [makeSkill(\"alpha\"), makeSkill(\"beta\")];\n\n\t// Suppress the console.warn the fallback emits so test output stays clean.\n\tconst originalWarn = console.warn;\n\tconst warnings: string[] = [];\n\tconsole.warn = (...args: unknown[]) => { warnings.push(args.join(\" \")); };\n\tt.after(() => { console.warn = originalWarn; });\n\n\tlet prompt = \"\";\n\tassert.doesNotThrow(() => {\n\t\tprompt = buildSystemPrompt({\n\t\t\tskills,\n\t\t\tselectedTools: [\"read\", \"Skill\"],\n\t\t\tskillFilter: () => { throw new Error(\"consumer bug\"); },\n\t\t});\n\t});\n\n\tconst section = extractAvailableSkills(prompt);\n\tassert.match(section, /<name>alpha<\\/name>/, \"alpha should render (fallback to unfiltered)\");\n\tassert.match(section, /<name>beta<\\/name>/, \"beta should render (fallback to unfiltered)\");\n\tassert.ok(\n\t\twarnings.some(w => w.includes(\"skillFilter threw\") && w.includes(\"consumer bug\")),\n\t\t\"fallback should emit an identifying warning\",\n\t);\n});\n"]}
|
|
@@ -1,57 +1,133 @@
|
|
|
1
|
-
|
|
1
|
+
// Regression test for #4243 — abort() must be called BEFORE
|
|
2
|
+
// _disconnectFromAgent() inside newSession() and switchSession() so that
|
|
3
|
+
// message_end/agent_end events (and the #4216 finalization code) fire
|
|
4
|
+
// before we unsubscribe from the event bus.
|
|
5
|
+
//
|
|
6
|
+
// Verified behaviourally: we construct a real AgentSession, wrap `abort`
|
|
7
|
+
// and `_disconnectFromAgent` with call-order recording, trigger each
|
|
8
|
+
// session-transition method, and assert the observed call order.
|
|
9
|
+
|
|
2
10
|
import assert from "node:assert/strict";
|
|
3
|
-
import {
|
|
11
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
12
|
+
import { tmpdir } from "node:os";
|
|
4
13
|
import { join } from "node:path";
|
|
14
|
+
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
15
|
+
|
|
16
|
+
import { Agent } from "@gsd/pi-agent-core";
|
|
17
|
+
import { AgentSession } from "./agent-session.js";
|
|
18
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
19
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
20
|
+
import { DefaultResourceLoader } from "./resource-loader.js";
|
|
21
|
+
import { SessionManager } from "./session-manager.js";
|
|
22
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
5
23
|
|
|
6
|
-
|
|
7
|
-
join(process.cwd(), "packages/pi-coding-agent/src/core/agent-session.ts"),
|
|
8
|
-
"utf-8",
|
|
9
|
-
);
|
|
24
|
+
let testDir: string;
|
|
10
25
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
26
|
+
async function createSession(opts: { persistSessions?: boolean } = {}): Promise<AgentSession> {
|
|
27
|
+
const agentDir = join(testDir, "agent-home");
|
|
28
|
+
const authStorage = AuthStorage.inMemory({});
|
|
29
|
+
const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
|
|
30
|
+
const settingsManager = SettingsManager.inMemory();
|
|
31
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
32
|
+
cwd: testDir,
|
|
33
|
+
agentDir,
|
|
34
|
+
settingsManager,
|
|
35
|
+
noExtensions: true,
|
|
36
|
+
noPromptTemplates: true,
|
|
37
|
+
noThemes: true,
|
|
38
|
+
});
|
|
39
|
+
await resourceLoader.reload();
|
|
16
40
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
41
|
+
// switchSession() needs a sessionFile; in-memory manager returns undefined.
|
|
42
|
+
// Use file-backed manager when the test needs to resume.
|
|
43
|
+
const sessionManager = opts.persistSessions
|
|
44
|
+
? SessionManager.create(testDir, join(testDir, "sessions"))
|
|
45
|
+
: SessionManager.inMemory(testDir);
|
|
46
|
+
|
|
47
|
+
return new AgentSession({
|
|
48
|
+
agent: new Agent(),
|
|
49
|
+
sessionManager,
|
|
50
|
+
settingsManager,
|
|
51
|
+
cwd: testDir,
|
|
52
|
+
resourceLoader,
|
|
53
|
+
modelRegistry,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
20
56
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
57
|
+
/**
|
|
58
|
+
* Wrap two methods on the same object so their call order is recorded.
|
|
59
|
+
* Returns the recording array — assertions use index lookups.
|
|
60
|
+
*/
|
|
61
|
+
function recordCallOrder<O extends object>(
|
|
62
|
+
target: O,
|
|
63
|
+
methods: Array<keyof O>,
|
|
64
|
+
): string[] {
|
|
65
|
+
const order: string[] = [];
|
|
66
|
+
for (const method of methods) {
|
|
67
|
+
const name = String(method);
|
|
68
|
+
const original = (target as any)[name] as (...args: unknown[]) => unknown;
|
|
69
|
+
if (typeof original !== "function") {
|
|
70
|
+
throw new Error(`recordCallOrder: ${name} is not a function on target`);
|
|
71
|
+
}
|
|
72
|
+
(target as any)[name] = function (this: O, ...args: unknown[]) {
|
|
73
|
+
order.push(name);
|
|
74
|
+
return original.apply(this, args);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return order;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
describe("#4243 — abort() must run before _disconnectFromAgent()", () => {
|
|
81
|
+
beforeEach(() => {
|
|
82
|
+
testDir = mkdtempSync(join(tmpdir(), "agent-session-abort-"));
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
afterEach(() => {
|
|
86
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
87
|
+
});
|
|
24
88
|
|
|
25
|
-
|
|
26
|
-
|
|
89
|
+
it("newSession() invokes abort() before _disconnectFromAgent()", async () => {
|
|
90
|
+
const session = await createSession();
|
|
91
|
+
const order = recordCallOrder(session as any, ["abort", "_disconnectFromAgent"]);
|
|
92
|
+
|
|
93
|
+
const ok = await session.newSession();
|
|
94
|
+
assert.equal(ok, true);
|
|
95
|
+
|
|
96
|
+
const abortIdx = order.indexOf("abort");
|
|
97
|
+
const disconnectIdx = order.indexOf("_disconnectFromAgent");
|
|
98
|
+
assert.ok(abortIdx >= 0, `newSession should call abort(); order=${order.join(",")}`);
|
|
99
|
+
assert.ok(
|
|
100
|
+
disconnectIdx >= 0,
|
|
101
|
+
`newSession should call _disconnectFromAgent(); order=${order.join(",")}`,
|
|
102
|
+
);
|
|
27
103
|
assert.ok(
|
|
28
104
|
abortIdx < disconnectIdx,
|
|
29
|
-
|
|
105
|
+
`abort() must run before _disconnectFromAgent(); order=${order.join(",")}`,
|
|
30
106
|
);
|
|
31
107
|
});
|
|
32
108
|
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Find the switchSession method body
|
|
40
|
-
const switchStart = source.indexOf("async switchSession(sessionPath:");
|
|
41
|
-
assert.ok(switchStart >= 0, "should find switchSession method");
|
|
109
|
+
it("switchSession() invokes abort() before _disconnectFromAgent()", async () => {
|
|
110
|
+
const session = await createSession({ persistSessions: true });
|
|
111
|
+
// Seed a session file to switch to (switchSession reads from the session manager).
|
|
112
|
+
await session.newSession();
|
|
113
|
+
const sessionFile = session.sessionFile;
|
|
114
|
+
assert.ok(typeof sessionFile === "string" && sessionFile.length > 0, "need a session file to switch to");
|
|
42
115
|
|
|
43
|
-
|
|
44
|
-
const window = source.slice(switchStart, switchStart + 800);
|
|
116
|
+
const order = recordCallOrder(session as any, ["abort", "_disconnectFromAgent"]);
|
|
45
117
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const disconnectIdx = window.indexOf("this._disconnectFromAgent();");
|
|
118
|
+
const ok = await session.switchSession(sessionFile);
|
|
119
|
+
assert.equal(ok, true);
|
|
49
120
|
|
|
50
|
-
|
|
51
|
-
|
|
121
|
+
const abortIdx = order.indexOf("abort");
|
|
122
|
+
const disconnectIdx = order.indexOf("_disconnectFromAgent");
|
|
123
|
+
assert.ok(abortIdx >= 0, `switchSession should call abort(); order=${order.join(",")}`);
|
|
124
|
+
assert.ok(
|
|
125
|
+
disconnectIdx >= 0,
|
|
126
|
+
`switchSession should call _disconnectFromAgent(); order=${order.join(",")}`,
|
|
127
|
+
);
|
|
52
128
|
assert.ok(
|
|
53
129
|
abortIdx < disconnectIdx,
|
|
54
|
-
|
|
130
|
+
`abort() must run before _disconnectFromAgent() in switchSession; order=${order.join(",")}`,
|
|
55
131
|
);
|
|
56
132
|
});
|
|
57
133
|
});
|
|
@@ -1,21 +1,93 @@
|
|
|
1
|
-
|
|
1
|
+
// Regression test: explicit model switches must cancel any in-flight retry
|
|
2
|
+
// BEFORE applying the new model. Otherwise stale provider backoff errors
|
|
3
|
+
// from the previous model can continue to land after the switch.
|
|
4
|
+
//
|
|
5
|
+
// Verified behaviourally: construct a real AgentSession, wrap
|
|
6
|
+
// `_retryHandler.abortRetry` and `agent.setModel` to record call order,
|
|
7
|
+
// invoke setModel(), and assert the observed order.
|
|
8
|
+
|
|
2
9
|
import assert from "node:assert/strict";
|
|
3
|
-
import {
|
|
10
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
11
|
+
import { tmpdir } from "node:os";
|
|
4
12
|
import { join } from "node:path";
|
|
13
|
+
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
14
|
+
|
|
15
|
+
import { Agent } from "@gsd/pi-agent-core";
|
|
16
|
+
import { getModel } from "@gsd/pi-ai";
|
|
17
|
+
import { AgentSession } from "./agent-session.js";
|
|
18
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
19
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
20
|
+
import { DefaultResourceLoader } from "./resource-loader.js";
|
|
21
|
+
import { SessionManager } from "./session-manager.js";
|
|
22
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
23
|
+
|
|
24
|
+
let testDir: string;
|
|
25
|
+
|
|
26
|
+
async function createSession(): Promise<AgentSession> {
|
|
27
|
+
const agentDir = join(testDir, "agent-home");
|
|
28
|
+
const authStorage = AuthStorage.inMemory({});
|
|
29
|
+
// Seed a runtime anthropic API key so modelRegistry.isProviderRequestReady()
|
|
30
|
+
// returns true and setModel() doesn't throw on missing credentials.
|
|
31
|
+
authStorage.setRuntimeApiKey("anthropic", "sk-test-not-used");
|
|
32
|
+
const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
|
|
33
|
+
const settingsManager = SettingsManager.inMemory();
|
|
34
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
35
|
+
cwd: testDir,
|
|
36
|
+
agentDir,
|
|
37
|
+
settingsManager,
|
|
38
|
+
noExtensions: true,
|
|
39
|
+
noPromptTemplates: true,
|
|
40
|
+
noThemes: true,
|
|
41
|
+
});
|
|
42
|
+
await resourceLoader.reload();
|
|
43
|
+
|
|
44
|
+
return new AgentSession({
|
|
45
|
+
agent: new Agent(),
|
|
46
|
+
sessionManager: SessionManager.inMemory(testDir),
|
|
47
|
+
settingsManager,
|
|
48
|
+
cwd: testDir,
|
|
49
|
+
resourceLoader,
|
|
50
|
+
modelRegistry,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("AgentSession — explicit model switch cancels retry before applying new model", () => {
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
testDir = mkdtempSync(join(tmpdir(), "agent-session-model-switch-"));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("setModel() calls _retryHandler.abortRetry() before agent.setModel()", async () => {
|
|
64
|
+
const session = await createSession();
|
|
65
|
+
|
|
66
|
+
const order: string[] = [];
|
|
67
|
+
const retryHandler = (session as any)._retryHandler;
|
|
68
|
+
const originalAbortRetry = retryHandler.abortRetry.bind(retryHandler);
|
|
69
|
+
retryHandler.abortRetry = () => {
|
|
70
|
+
order.push("abortRetry");
|
|
71
|
+
return originalAbortRetry();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
const agent = (session as any).agent;
|
|
75
|
+
const originalSetModel = agent.setModel.bind(agent);
|
|
76
|
+
agent.setModel = (model: unknown) => {
|
|
77
|
+
order.push("setModel");
|
|
78
|
+
return originalSetModel(model);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const newModel = getModel("anthropic", "claude-3-5-sonnet-20241022");
|
|
82
|
+
await session.setModel(newModel, { persist: false });
|
|
5
83
|
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
assert.ok(abortIdx >= 0, "_applyModelChange should cancel any in-flight retry");
|
|
16
|
-
assert.ok(setModelIdx >= 0, "_applyModelChange should set the new model");
|
|
17
|
-
assert.ok(
|
|
18
|
-
abortIdx < setModelIdx,
|
|
19
|
-
"retry cancellation must happen before applying the new model to prevent stale provider retries",
|
|
20
|
-
);
|
|
84
|
+
const abortIdx = order.indexOf("abortRetry");
|
|
85
|
+
const setIdx = order.indexOf("setModel");
|
|
86
|
+
assert.ok(abortIdx >= 0, `setModel should cancel in-flight retry; order=${order.join(",")}`);
|
|
87
|
+
assert.ok(setIdx >= 0, `setModel should call agent.setModel; order=${order.join(",")}`);
|
|
88
|
+
assert.ok(
|
|
89
|
+
abortIdx < setIdx,
|
|
90
|
+
`retry cancellation must happen before applying the new model; order=${order.join(",")}`,
|
|
91
|
+
);
|
|
92
|
+
});
|
|
21
93
|
});
|
|
@@ -1,64 +1,133 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
1
|
+
// Regression test for #3616: newSession() must restore the full tool set
|
|
2
|
+
// when cwd is unchanged.
|
|
3
|
+
//
|
|
4
|
+
// The bug: extensions may narrow the active tool list via setActiveTools()
|
|
5
|
+
// during a session. Without a refresh in the else branch of newSession(),
|
|
6
|
+
// the narrowed set persists into the next session — breaking auto-mode
|
|
7
|
+
// subagent sessions that expect a full tool palette.
|
|
8
|
+
//
|
|
9
|
+
// Verified behaviourally: construct an AgentSession, wrap _refreshToolRegistry
|
|
10
|
+
// to record its args, call newSession() with cwd unchanged, and assert that
|
|
11
|
+
// a refresh was requested with includeAllExtensionTools: true.
|
|
3
12
|
|
|
4
|
-
import test, { describe } from "node:test";
|
|
5
13
|
import assert from "node:assert/strict";
|
|
6
|
-
import {
|
|
14
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
15
|
+
import { tmpdir } from "node:os";
|
|
7
16
|
import { join } from "node:path";
|
|
17
|
+
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
8
18
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
19
|
+
import { Agent } from "@gsd/pi-agent-core";
|
|
20
|
+
import { AgentSession } from "./agent-session.js";
|
|
21
|
+
import { AuthStorage } from "./auth-storage.js";
|
|
22
|
+
import { ModelRegistry } from "./model-registry.js";
|
|
23
|
+
import { DefaultResourceLoader } from "./resource-loader.js";
|
|
24
|
+
import { SessionManager } from "./session-manager.js";
|
|
25
|
+
import { SettingsManager } from "./settings-manager.js";
|
|
13
26
|
|
|
14
|
-
|
|
15
|
-
test("newSession() calls _refreshToolRegistry with includeAllExtensionTools when cwd is unchanged", () => {
|
|
16
|
-
// Find the newSession method
|
|
17
|
-
const newSessionStart = source.indexOf("async newSession(options?:");
|
|
18
|
-
assert.ok(newSessionStart >= 0, "should find newSession method");
|
|
27
|
+
let testDir: string;
|
|
19
28
|
|
|
20
|
-
|
|
21
|
-
|
|
29
|
+
async function createSession(): Promise<AgentSession> {
|
|
30
|
+
const agentDir = join(testDir, "agent-home");
|
|
31
|
+
const authStorage = AuthStorage.inMemory({});
|
|
32
|
+
const modelRegistry = new ModelRegistry(authStorage, join(agentDir, "models.json"));
|
|
33
|
+
const settingsManager = SettingsManager.inMemory();
|
|
34
|
+
const resourceLoader = new DefaultResourceLoader({
|
|
35
|
+
cwd: testDir,
|
|
36
|
+
agentDir,
|
|
37
|
+
settingsManager,
|
|
38
|
+
noExtensions: true,
|
|
39
|
+
noPromptTemplates: true,
|
|
40
|
+
noThemes: true,
|
|
41
|
+
});
|
|
42
|
+
await resourceLoader.reload();
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
44
|
+
return new AgentSession({
|
|
45
|
+
agent: new Agent(),
|
|
46
|
+
sessionManager: SessionManager.inMemory(testDir),
|
|
47
|
+
settingsManager,
|
|
48
|
+
cwd: testDir,
|
|
49
|
+
resourceLoader,
|
|
50
|
+
modelRegistry,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
describe("#3616 — newSession() restores narrowed tool set when cwd unchanged", () => {
|
|
55
|
+
beforeEach(() => {
|
|
56
|
+
testDir = mkdtempSync(join(tmpdir(), "agent-session-tool-refresh-"));
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
afterEach(() => {
|
|
60
|
+
rmSync(testDir, { recursive: true, force: true });
|
|
61
|
+
});
|
|
28
62
|
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
63
|
+
it("calls _refreshToolRegistry with includeAllExtensionTools: true when cwd unchanged", async () => {
|
|
64
|
+
const session = await createSession();
|
|
65
|
+
// Pin _cwd so newSession()'s `process.cwd()` branch takes the
|
|
66
|
+
// cwd-unchanged path. The production code compares `this._cwd !==
|
|
67
|
+
// previousCwd`; we force equality by setting _cwd to current cwd.
|
|
68
|
+
(session as any)._cwd = process.cwd();
|
|
69
|
+
|
|
70
|
+
const refreshCalls: Array<{ includeAllExtensionTools?: boolean }> = [];
|
|
71
|
+
const originalRefresh = (session as any)._refreshToolRegistry.bind(session);
|
|
72
|
+
(session as any)._refreshToolRegistry = (options?: { includeAllExtensionTools?: boolean }) => {
|
|
73
|
+
refreshCalls.push(options ?? {});
|
|
74
|
+
return originalRefresh(options);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const ok = await session.newSession();
|
|
78
|
+
assert.equal(ok, true);
|
|
32
79
|
|
|
33
|
-
const elseBranch = methodBody.slice(elseIdx, elseIdx + 800);
|
|
34
80
|
assert.ok(
|
|
35
|
-
|
|
36
|
-
"
|
|
81
|
+
refreshCalls.length > 0,
|
|
82
|
+
"newSession() should invoke _refreshToolRegistry in the cwd-unchanged branch",
|
|
37
83
|
);
|
|
38
84
|
assert.ok(
|
|
39
|
-
|
|
40
|
-
|
|
85
|
+
refreshCalls.some((o) => o.includeAllExtensionTools === true),
|
|
86
|
+
`at least one _refreshToolRegistry call must pass includeAllExtensionTools: true; observed=${JSON.stringify(refreshCalls)}`,
|
|
41
87
|
);
|
|
42
88
|
});
|
|
43
89
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
90
|
+
it("agent.reset() does not clear _state.tools (tools persist across reset)", () => {
|
|
91
|
+
// Structural invariant protecting #3616: if reset() starts clearing
|
|
92
|
+
// tools, newSession()'s refresh becomes the only defense against loss.
|
|
93
|
+
// Assertion is behavioural — seed tools, call reset(), observe survival.
|
|
94
|
+
const agent = new Agent();
|
|
95
|
+
const tool = {
|
|
96
|
+
name: "test_tool",
|
|
97
|
+
description: "x",
|
|
98
|
+
schema: { type: "object", properties: {}, additionalProperties: false } as any,
|
|
99
|
+
execute: async () => ({ content: [] }),
|
|
100
|
+
};
|
|
101
|
+
(agent as any)._state.tools = [tool];
|
|
102
|
+
agent.reset();
|
|
103
|
+
assert.deepEqual(
|
|
104
|
+
(agent as any)._state.tools,
|
|
105
|
+
[tool],
|
|
106
|
+
"Agent.reset() must preserve _state.tools",
|
|
107
|
+
);
|
|
47
108
|
});
|
|
48
109
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
// the
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
110
|
+
it("takes the cwd-changed branch (rebuilds runtime) when cwd differs", async () => {
|
|
111
|
+
const session = await createSession();
|
|
112
|
+
// Force the cwd-changed branch: set _cwd to something that won't equal process.cwd().
|
|
113
|
+
(session as any)._cwd = join(testDir, "some", "other", "cwd");
|
|
114
|
+
|
|
115
|
+
let buildRuntimeCalled = false;
|
|
116
|
+
let buildRuntimeIncludedAll = false;
|
|
117
|
+
const originalBuild = (session as any)._buildRuntime.bind(session);
|
|
118
|
+
(session as any)._buildRuntime = (options?: { includeAllExtensionTools?: boolean }) => {
|
|
119
|
+
buildRuntimeCalled = true;
|
|
120
|
+
if (options?.includeAllExtensionTools === true) buildRuntimeIncludedAll = true;
|
|
121
|
+
return originalBuild(options);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const ok = await session.newSession();
|
|
125
|
+
assert.equal(ok, true);
|
|
126
|
+
|
|
127
|
+
assert.ok(buildRuntimeCalled, "cwd-changed branch must rebuild the tool runtime");
|
|
59
128
|
assert.ok(
|
|
60
|
-
|
|
61
|
-
"
|
|
129
|
+
buildRuntimeIncludedAll,
|
|
130
|
+
"cwd-changed branch must rebuild with includeAllExtensionTools: true",
|
|
62
131
|
);
|
|
63
132
|
});
|
|
64
133
|
});
|