gsd-pi 2.80.0-dev.2848d9009 → 2.80.0-dev.3065f7bfa
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 +4 -2
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/gsd/auto/loop.js +32 -1
- package/dist/resources/extensions/gsd/auto/phases.js +178 -108
- package/dist/resources/extensions/gsd/auto/resolve.js +17 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +20 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto-direct-dispatch.js +5 -32
- package/dist/resources/extensions/gsd/auto-dispatch.js +16 -0
- package/dist/resources/extensions/gsd/auto-post-unit.js +17 -4
- package/dist/resources/extensions/gsd/auto-prompts.js +103 -16
- package/dist/resources/extensions/gsd/auto-recovery.js +43 -1
- package/dist/resources/extensions/gsd/auto-start.js +197 -6
- package/dist/resources/extensions/gsd/auto-supervisor.js +8 -1
- package/dist/resources/extensions/gsd/auto-timeout-recovery.js +2 -2
- package/dist/resources/extensions/gsd/auto-worktree.js +111 -1
- package/dist/resources/extensions/gsd/auto.js +86 -26
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +42 -2
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +49 -36
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +15 -5
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +33 -20
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +7 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +9 -3
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +8 -2
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +259 -28
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +82 -23
- package/dist/resources/extensions/gsd/clean-root-preflight.js +24 -6
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/context-budget.js +37 -2
- package/dist/resources/extensions/gsd/crash-recovery.js +56 -10
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +39 -0
- package/dist/resources/extensions/gsd/db-base-schema.js +4 -2
- package/dist/resources/extensions/gsd/db-migration-steps.js +6 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +36 -4
- package/dist/resources/extensions/gsd/gsd-db.js +46 -13
- package/dist/resources/extensions/gsd/guided-flow.js +99 -38
- package/dist/resources/extensions/gsd/memory-store.js +69 -12
- package/dist/resources/extensions/gsd/migrate/command.js +40 -1
- package/dist/resources/extensions/gsd/migration-auto-check.js +87 -0
- package/dist/resources/extensions/gsd/native-git-bridge.js +32 -8
- package/dist/resources/extensions/gsd/orphan-stash-audit.js +101 -0
- package/dist/resources/extensions/gsd/parallel-orchestrator.js +13 -3
- package/dist/resources/extensions/gsd/planning-path-scope.js +26 -0
- package/dist/resources/extensions/gsd/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompt-loader.js +28 -2
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/dist/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/dist/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/dist/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/dist/resources/extensions/gsd/quick.js +34 -2
- package/dist/resources/extensions/gsd/tools/context-mode-tool-result.js +15 -0
- package/dist/resources/extensions/gsd/tools/exec-search-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/exec-tool.js +3 -15
- package/dist/resources/extensions/gsd/tools/memory-tools.js +1 -0
- package/dist/resources/extensions/gsd/tools/plan-slice.js +9 -0
- package/dist/resources/extensions/gsd/tools/plan-task.js +9 -0
- package/dist/resources/extensions/gsd/tools/resume-tool.js +5 -0
- package/dist/resources/extensions/gsd/tools/workflow-tool-executors.js +1 -1
- package/dist/resources/extensions/gsd/unit-context-composer.js +12 -3
- package/dist/resources/extensions/gsd/unit-runtime.js +22 -0
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +68 -21
- 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 +15 -15
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +15 -15
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +3 -3
- package/packages/mcp-server/dist/workflow-tools.d.ts.map +1 -1
- package/packages/mcp-server/dist/workflow-tools.js +22 -17
- package/packages/mcp-server/dist/workflow-tools.js.map +1 -1
- package/packages/mcp-server/src/workflow-tools.test.ts +75 -2
- package/packages/mcp-server/src/workflow-tools.ts +30 -16
- package/packages/mcp-server/tsconfig.tsbuildinfo +1 -1
- package/packages/native/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent-loop.js +4 -1
- package/packages/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/packages/pi-agent-core/dist/agent.d.ts +5 -0
- package/packages/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/agent.js +2 -0
- package/packages/pi-agent-core/dist/agent.js.map +1 -1
- package/packages/pi-agent-core/dist/index.d.ts +1 -0
- package/packages/pi-agent-core/dist/index.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/index.js +2 -0
- package/packages/pi-agent-core/dist/index.js.map +1 -1
- package/packages/pi-agent-core/dist/token-audit.d.ts +47 -0
- package/packages/pi-agent-core/dist/token-audit.d.ts.map +1 -0
- package/packages/pi-agent-core/dist/token-audit.js +221 -0
- package/packages/pi-agent-core/dist/token-audit.js.map +1 -0
- package/packages/pi-agent-core/dist/types.d.ts +9 -0
- package/packages/pi-agent-core/dist/types.d.ts.map +1 -1
- package/packages/pi-agent-core/dist/types.js.map +1 -1
- package/packages/pi-agent-core/src/agent-loop.test.ts +128 -0
- package/packages/pi-agent-core/src/agent-loop.ts +4 -1
- package/packages/pi-agent-core/src/agent.ts +8 -0
- package/packages/pi-agent-core/src/index.ts +2 -0
- package/packages/pi-agent-core/src/token-audit.test.ts +189 -0
- package/packages/pi-agent-core/src/token-audit.ts +287 -0
- package/packages/pi-agent-core/src/types.ts +14 -0
- package/packages/pi-agent-core/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session-abort-order.test.js +32 -0
- 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-tool-refresh.test.js +18 -0
- package/packages/pi-coding-agent/dist/core/agent-session-tool-refresh.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts +12 -0
- package/packages/pi-coding-agent/dist/core/agent-session.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/agent-session.js +44 -7
- package/packages/pi-coding-agent/dist/core/agent-session.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js +3 -1
- package/packages/pi-coding-agent/dist/core/chat-controller-ordering.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts +11 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js +9 -0
- package/packages/pi-coding-agent/dist/core/compaction/compaction.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js +103 -0
- package/packages/pi-coding-agent/dist/core/compaction-threshold.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts +15 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js +66 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js +24 -0
- package/packages/pi-coding-agent/dist/core/db-snapshot.test.js.map +1 -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 +8 -0
- package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts +3 -0
- package/packages/pi-coding-agent/dist/core/extensions/runner.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.js +6 -6
- package/packages/pi-coding-agent/dist/core/extensions/runner.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +5 -3
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts +39 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/types.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js +2 -0
- package/packages/pi-coding-agent/dist/core/hooks-runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js +46 -0
- package/packages/pi-coding-agent/dist/core/sdk-tool-filter.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/sdk.d.ts +10 -2
- package/packages/pi-coding-agent/dist/core/sdk.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/sdk.js +74 -2
- package/packages/pi-coding-agent/dist/core/sdk.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +20 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/settings-manager.js +25 -0
- package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js +22 -0
- package/packages/pi-coding-agent/dist/core/skill-tool.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts +6 -7
- package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/system-prompt.js +2 -3
- package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +1 -0
- 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 +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js +13 -5
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js +53 -0
- package/packages/pi-coding-agent/dist/modes/interactive/controllers/chat-controller.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +3 -0
- package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js +10 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js +3 -2
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.js.map +1 -1
- package/packages/pi-coding-agent/src/core/agent-session-abort-order.test.ts +36 -0
- package/packages/pi-coding-agent/src/core/agent-session-tool-refresh.test.ts +25 -0
- package/packages/pi-coding-agent/src/core/agent-session.ts +48 -7
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/compaction/compaction.ts +18 -0
- package/packages/pi-coding-agent/src/core/compaction-threshold.test.ts +121 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.test.ts +32 -0
- package/packages/pi-coding-agent/src/core/db-snapshot.ts +66 -0
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +5 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +8 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +42 -1
- package/packages/pi-coding-agent/src/core/hooks-runner.test.ts +2 -0
- package/packages/pi-coding-agent/src/core/sdk-tool-filter.test.ts +60 -0
- package/packages/pi-coding-agent/src/core/sdk.ts +85 -3
- package/packages/pi-coding-agent/src/core/settings-manager.ts +39 -1
- package/packages/pi-coding-agent/src/core/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +4 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +56 -0
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +22 -7
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +3 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +14 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.ts +3 -2
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/packages/pi-tui/dist/tui.d.ts.map +1 -1
- package/packages/pi-tui/dist/tui.js +18 -8
- package/packages/pi-tui/dist/tui.js.map +1 -1
- package/packages/pi-tui/src/tui.ts +20 -8
- package/packages/pi-tui/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/loop.ts +50 -8
- package/src/resources/extensions/gsd/auto/phases.ts +251 -172
- package/src/resources/extensions/gsd/auto/resolve.ts +23 -1
- package/src/resources/extensions/gsd/auto/run-unit.ts +25 -30
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto-direct-dispatch.ts +8 -34
- package/src/resources/extensions/gsd/auto-dispatch.ts +16 -0
- package/src/resources/extensions/gsd/auto-post-unit.ts +18 -4
- package/src/resources/extensions/gsd/auto-prompts.ts +112 -15
- package/src/resources/extensions/gsd/auto-recovery.ts +54 -0
- package/src/resources/extensions/gsd/auto-start.ts +230 -9
- package/src/resources/extensions/gsd/auto-supervisor.ts +7 -0
- package/src/resources/extensions/gsd/auto-timeout-recovery.ts +2 -2
- package/src/resources/extensions/gsd/auto-worktree.ts +123 -0
- package/src/resources/extensions/gsd/auto.ts +98 -21
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +49 -1
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +50 -36
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +16 -5
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +34 -19
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +8 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +10 -3
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +9 -2
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +305 -28
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +90 -22
- package/src/resources/extensions/gsd/clean-root-preflight.ts +32 -7
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/context-budget.ts +44 -2
- package/src/resources/extensions/gsd/crash-recovery.ts +67 -10
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +41 -0
- package/src/resources/extensions/gsd/db-base-schema.ts +4 -2
- package/src/resources/extensions/gsd/db-migration-steps.ts +8 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/git-service.ts +46 -8
- package/src/resources/extensions/gsd/gsd-db.ts +50 -13
- package/src/resources/extensions/gsd/guided-flow.ts +123 -45
- package/src/resources/extensions/gsd/memory-store.ts +77 -12
- package/src/resources/extensions/gsd/migrate/command.ts +47 -1
- package/src/resources/extensions/gsd/migration-auto-check.ts +129 -0
- package/src/resources/extensions/gsd/native-git-bridge.ts +39 -6
- package/src/resources/extensions/gsd/orphan-stash-audit.ts +117 -0
- package/src/resources/extensions/gsd/parallel-orchestrator.ts +13 -3
- package/src/resources/extensions/gsd/planning-path-scope.ts +35 -0
- package/src/resources/extensions/gsd/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/preferences-types.ts +1 -1
- package/src/resources/extensions/gsd/prompt-loader.ts +27 -2
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +16 -13
- package/src/resources/extensions/gsd/prompts/complete-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/execute-task.md +4 -2
- package/src/resources/extensions/gsd/prompts/parallel-research-slices.md +1 -1
- package/src/resources/extensions/gsd/prompts/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/quick-task.md +1 -5
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/prompts/validate-milestone.md +2 -2
- package/src/resources/extensions/gsd/quick.ts +37 -2
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +2 -2
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +417 -10
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +56 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +168 -6
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/compaction-snapshot.test.ts +14 -1
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/context-budget.test.ts +10 -1
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/crash-recovery-via-db.test.ts +22 -0
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/dispatch-rule-coverage.test.ts +313 -0
- package/src/resources/extensions/gsd/tests/exec-history.test.ts +15 -0
- package/src/resources/extensions/gsd/tests/exec-sandbox.test.ts +65 -0
- package/src/resources/extensions/gsd/tests/execute-task-rendering.test.ts +5 -2
- package/src/resources/extensions/gsd/tests/fast-forward-reused-milestone-branch.test.ts +219 -0
- package/src/resources/extensions/gsd/tests/finalize-survivor-branch.test.ts +132 -0
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +54 -0
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +6 -3
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +239 -1
- package/src/resources/extensions/gsd/tests/journal-query-tool.test.ts +32 -0
- package/src/resources/extensions/gsd/tests/knowledge.test.ts +47 -0
- package/src/resources/extensions/gsd/tests/memory-decay-factor.test.ts +90 -0
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +48 -0
- package/src/resources/extensions/gsd/tests/migration-auto-check.test.ts +127 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/originalbase-path-comparison.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/orphan-merge-bootstrap.test.ts +133 -0
- package/src/resources/extensions/gsd/tests/orphan-stash-audit.test.ts +201 -0
- package/src/resources/extensions/gsd/tests/parallel-orchestrator-fast-forward.test.ts +113 -0
- package/src/resources/extensions/gsd/tests/plan-slice.test.ts +50 -0
- package/src/resources/extensions/gsd/tests/plan-task.test.ts +21 -0
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-path-audit.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +19 -0
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +3 -3
- package/src/resources/extensions/gsd/tests/quick-external-gsd.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +38 -17
- package/src/resources/extensions/gsd/tests/schema-v27-v28-sequence.test.ts +156 -0
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/signal-handlers.test.ts +27 -0
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +20 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +49 -1
- package/src/resources/extensions/gsd/tests/start-auto-detached.test.ts +55 -0
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +9 -0
- package/src/resources/extensions/gsd/tests/system-context-memory.test.ts +112 -0
- package/src/resources/extensions/gsd/tests/system-context-message-routing.test.ts +7 -9
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/unit-context-composer.test.ts +136 -4
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +30 -0
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +37 -0
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -4
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-tool-executors.test.ts +3 -0
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-path-injection.test.ts +22 -19
- package/src/resources/extensions/gsd/tests/worktree-project-root-degrade.test.ts +66 -0
- package/src/resources/extensions/gsd/tests/worktree-resolver.test.ts +167 -4
- package/src/resources/extensions/gsd/tools/context-mode-tool-result.ts +25 -0
- package/src/resources/extensions/gsd/tools/exec-search-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/exec-tool.ts +4 -23
- package/src/resources/extensions/gsd/tools/memory-tools.ts +1 -0
- package/src/resources/extensions/gsd/tools/plan-slice.ts +13 -0
- package/src/resources/extensions/gsd/tools/plan-task.ts +10 -0
- package/src/resources/extensions/gsd/tools/resume-tool.ts +7 -7
- package/src/resources/extensions/gsd/tools/workflow-tool-executors.ts +1 -1
- package/src/resources/extensions/gsd/unit-context-composer.ts +19 -4
- package/src/resources/extensions/gsd/unit-runtime.ts +25 -0
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +85 -19
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +0 -97
- /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → O2WvnXROue6l7nAp_4dhC}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{vaQ47E8aNlbbNEDoeME6G → O2WvnXROue6l7nAp_4dhC}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { closeSync, fsyncSync, openSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { basename, dirname, join } from "node:path";
|
|
4
|
+
|
|
5
|
+
export type DbSnapshot = Buffer | Uint8Array;
|
|
6
|
+
|
|
7
|
+
function closeBestEffort(fd: number | null): void {
|
|
8
|
+
if (fd === null) return;
|
|
9
|
+
try {
|
|
10
|
+
closeSync(fd);
|
|
11
|
+
} catch {
|
|
12
|
+
// Preserve the original write/rename failure when cleaning up.
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function fsyncDirectoryBestEffort(dirPath: string): void {
|
|
17
|
+
let fd: number | null = null;
|
|
18
|
+
try {
|
|
19
|
+
fd = openSync(dirPath, "r");
|
|
20
|
+
fsyncSync(fd);
|
|
21
|
+
} catch {
|
|
22
|
+
// Directory fsync is unsupported on some platforms/filesystems.
|
|
23
|
+
} finally {
|
|
24
|
+
closeBestEffort(fd);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Persist a sql.js database export without exposing callers to a torn live file.
|
|
30
|
+
*
|
|
31
|
+
* The snapshot is written to a unique temp file in the same directory, flushed,
|
|
32
|
+
* then renamed over the target. A hard kill during the temp write leaves the
|
|
33
|
+
* previous target intact; after rename, readers see the complete new snapshot.
|
|
34
|
+
*
|
|
35
|
+
* The rename replaces the target inode: existing file mode/ownership is not
|
|
36
|
+
* preserved, and a symlink at dbPath is replaced rather than written through.
|
|
37
|
+
* Agent DB snapshots are owned runtime files, so this trade-off favors a
|
|
38
|
+
* private 0600 replacement over retaining prior target metadata.
|
|
39
|
+
*/
|
|
40
|
+
export function atomicWriteDbSnapshotSync(dbPath: string, snapshot: DbSnapshot): void {
|
|
41
|
+
const dirPath = dirname(dbPath);
|
|
42
|
+
const tmpPath = join(dirPath, `.${basename(dbPath)}.${process.pid}.${Date.now()}.${randomUUID()}.tmp`);
|
|
43
|
+
let fd: number | null = null;
|
|
44
|
+
let renamed = false;
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
fd = openSync(tmpPath, "wx", 0o600);
|
|
48
|
+
writeFileSync(fd, Buffer.from(snapshot));
|
|
49
|
+
fsyncSync(fd);
|
|
50
|
+
closeSync(fd);
|
|
51
|
+
fd = null;
|
|
52
|
+
|
|
53
|
+
renameSync(tmpPath, dbPath);
|
|
54
|
+
renamed = true;
|
|
55
|
+
fsyncDirectoryBestEffort(dirPath);
|
|
56
|
+
} finally {
|
|
57
|
+
closeBestEffort(fd);
|
|
58
|
+
if (!renamed) {
|
|
59
|
+
try {
|
|
60
|
+
unlinkSync(tmpPath);
|
|
61
|
+
} catch {
|
|
62
|
+
// The temp file may not have been created yet.
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -415,6 +415,8 @@ export function createExtensionRuntime(): ExtensionRuntime {
|
|
|
415
415
|
getActiveTools: notInitialized,
|
|
416
416
|
getAllTools: notInitialized,
|
|
417
417
|
setActiveTools: notInitialized,
|
|
418
|
+
getVisibleSkills: notInitialized,
|
|
419
|
+
setVisibleSkills: notInitialized,
|
|
418
420
|
// registerTool() is valid during extension load; refresh is only needed post-bind.
|
|
419
421
|
refreshTools: () => {},
|
|
420
422
|
getCommands: notInitialized,
|
|
@@ -566,6 +568,14 @@ function createExtensionAPI(
|
|
|
566
568
|
runtime.setActiveTools(toolNames);
|
|
567
569
|
},
|
|
568
570
|
|
|
571
|
+
getVisibleSkills(): string[] | undefined {
|
|
572
|
+
return runtime.getVisibleSkills();
|
|
573
|
+
},
|
|
574
|
+
|
|
575
|
+
setVisibleSkills(skillNames: string[] | undefined): void {
|
|
576
|
+
runtime.setVisibleSkills(skillNames);
|
|
577
|
+
},
|
|
578
|
+
|
|
569
579
|
getCommands() {
|
|
570
580
|
return runtime.getCommands();
|
|
571
581
|
},
|
|
@@ -141,6 +141,7 @@ describe("ExtensionRunner.emitToolCall", () => {
|
|
|
141
141
|
getContextUsage: () => undefined,
|
|
142
142
|
compact: () => {},
|
|
143
143
|
getSystemPrompt: () => "",
|
|
144
|
+
setCompactionThresholdOverride: () => {},
|
|
144
145
|
});
|
|
145
146
|
|
|
146
147
|
const errors: any[] = [];
|
|
@@ -159,7 +160,7 @@ describe("ExtensionRunner.emitToolCall", () => {
|
|
|
159
160
|
});
|
|
160
161
|
|
|
161
162
|
describe("ExtensionRunner.createContext", () => {
|
|
162
|
-
it("uses the
|
|
163
|
+
it("uses the constructor workspace root instead of ambient process cwd", (t) => {
|
|
163
164
|
const originalCwd = process.cwd();
|
|
164
165
|
const dir = mkdtempSync(join(tmpdir(), "runner-test-"));
|
|
165
166
|
const projectDir = join(dir, "project");
|
|
@@ -178,8 +179,8 @@ describe("ExtensionRunner.createContext", () => {
|
|
|
178
179
|
const realProjectDir = realpathSync(projectDir);
|
|
179
180
|
process.chdir(realProjectDir);
|
|
180
181
|
|
|
181
|
-
assert.equal(runner.createContext().cwd,
|
|
182
|
-
assert.equal(runner.createCommandContext().cwd,
|
|
182
|
+
assert.equal(runner.createContext().cwd, originalCwd);
|
|
183
|
+
assert.equal(runner.createCommandContext().cwd, originalCwd);
|
|
183
184
|
});
|
|
184
185
|
|
|
185
186
|
it("does not let lifecycle event handlers close the TUI", async (t) => {
|
|
@@ -220,6 +221,7 @@ describe("ExtensionRunner.createContext", () => {
|
|
|
220
221
|
getContextUsage: () => undefined,
|
|
221
222
|
compact: () => {},
|
|
222
223
|
getSystemPrompt: () => "",
|
|
224
|
+
setCompactionThresholdOverride: () => {},
|
|
223
225
|
});
|
|
224
226
|
|
|
225
227
|
const errors: any[] = [];
|
|
@@ -173,6 +173,8 @@ export type ExtensionErrorListener = (error: ExtensionError) => void;
|
|
|
173
173
|
export type NewSessionHandler = (options?: {
|
|
174
174
|
parentSession?: string;
|
|
175
175
|
setup?: (sessionManager: SessionManager) => Promise<void>;
|
|
176
|
+
/** Explicit workspace root for the new session/tool runtime. */
|
|
177
|
+
workspaceRoot?: string;
|
|
176
178
|
/** See ExtensionCommandContext.newSession for docs (#3731). */
|
|
177
179
|
abortSignal?: AbortSignal;
|
|
178
180
|
}) => Promise<{ cancelled: boolean }>;
|
|
@@ -235,6 +237,7 @@ export class ExtensionRunner {
|
|
|
235
237
|
private getContextUsageFn: () => ContextUsage | undefined = () => undefined;
|
|
236
238
|
private compactFn: (options?: CompactOptions) => void = () => {};
|
|
237
239
|
private getSystemPromptFn: () => string = () => "";
|
|
240
|
+
private setCompactionThresholdOverrideFn: (percent: number | undefined) => void = () => {};
|
|
238
241
|
private newSessionHandler: NewSessionHandler = async () => {
|
|
239
242
|
throw new Error("Command context not yet bound: newSession is unavailable during early lifecycle");
|
|
240
243
|
};
|
|
@@ -274,11 +277,7 @@ export class ExtensionRunner {
|
|
|
274
277
|
}
|
|
275
278
|
|
|
276
279
|
private currentCwd(): string {
|
|
277
|
-
|
|
278
|
-
return process.cwd();
|
|
279
|
-
} catch {
|
|
280
|
-
return this.cwd;
|
|
281
|
-
}
|
|
280
|
+
return this.cwd;
|
|
282
281
|
}
|
|
283
282
|
|
|
284
283
|
/**
|
|
@@ -413,6 +412,8 @@ export class ExtensionRunner {
|
|
|
413
412
|
this.runtime.getActiveTools = actions.getActiveTools;
|
|
414
413
|
this.runtime.getAllTools = actions.getAllTools;
|
|
415
414
|
this.runtime.setActiveTools = actions.setActiveTools;
|
|
415
|
+
this.runtime.getVisibleSkills = actions.getVisibleSkills;
|
|
416
|
+
this.runtime.setVisibleSkills = actions.setVisibleSkills;
|
|
416
417
|
this.runtime.refreshTools = actions.refreshTools;
|
|
417
418
|
this.runtime.getCommands = actions.getCommands;
|
|
418
419
|
this.runtime.setModel = actions.setModel;
|
|
@@ -428,6 +429,7 @@ export class ExtensionRunner {
|
|
|
428
429
|
this.getContextUsageFn = contextActions.getContextUsage;
|
|
429
430
|
this.compactFn = contextActions.compact;
|
|
430
431
|
this.getSystemPromptFn = contextActions.getSystemPrompt;
|
|
432
|
+
this.setCompactionThresholdOverrideFn = contextActions.setCompactionThresholdOverride;
|
|
431
433
|
|
|
432
434
|
// Flush provider registrations queued during extension loading
|
|
433
435
|
for (const { name, config } of this.runtime.pendingProviderRegistrations) {
|
|
@@ -714,6 +716,7 @@ export class ExtensionRunner {
|
|
|
714
716
|
getContextUsage: () => this.getContextUsageFn(),
|
|
715
717
|
compact: (options) => this.compactFn(options),
|
|
716
718
|
getSystemPrompt: () => this.getSystemPromptFn(),
|
|
719
|
+
setCompactionThresholdOverride: (percent) => this.setCompactionThresholdOverrideFn(percent),
|
|
717
720
|
};
|
|
718
721
|
}
|
|
719
722
|
|
|
@@ -289,6 +289,12 @@ export interface ExtensionContext {
|
|
|
289
289
|
compact(options?: CompactOptions): void;
|
|
290
290
|
/** Get the current effective system prompt. */
|
|
291
291
|
getSystemPrompt(): string;
|
|
292
|
+
/**
|
|
293
|
+
* Set or clear an in-memory compaction threshold-percent override (0 < value < 1).
|
|
294
|
+
* Pass `undefined` to clear. The override is not persisted; host integrations
|
|
295
|
+
* are expected to re-apply on each session_start.
|
|
296
|
+
*/
|
|
297
|
+
setCompactionThresholdOverride(percent: number | undefined): void;
|
|
292
298
|
}
|
|
293
299
|
|
|
294
300
|
/**
|
|
@@ -303,10 +309,13 @@ export interface ExtensionCommandContext extends ExtensionContext {
|
|
|
303
309
|
newSession(options?: {
|
|
304
310
|
parentSession?: string;
|
|
305
311
|
setup?: (sessionManager: SessionManager) => Promise<void>;
|
|
312
|
+
/** Explicit workspace root for the new session/tool runtime.
|
|
313
|
+
* When omitted, newSession() captures process.cwd() for backwards compatibility. */
|
|
314
|
+
workspaceRoot?: string;
|
|
306
315
|
/** When aborted before the session is fully configured, newSession() returns
|
|
307
316
|
* early without rebuilding the tool runtime. Used by runUnit() to discard
|
|
308
317
|
* a late-resolving newSession() after the session-creation timeout fires,
|
|
309
|
-
* preventing the tool runtime from being rebuilt with
|
|
318
|
+
* preventing the tool runtime from being rebuilt with a stale workspace root (#3731). */
|
|
310
319
|
abortSignal?: AbortSignal;
|
|
311
320
|
}): Promise<{ cancelled: boolean }>;
|
|
312
321
|
|
|
@@ -842,6 +851,13 @@ export interface BeforeModelSelectResult {
|
|
|
842
851
|
modelId: string;
|
|
843
852
|
}
|
|
844
853
|
|
|
854
|
+
export interface AdjustToolSetRequestCustomMessage {
|
|
855
|
+
/** Index in the post-transform AgentMessage context. */
|
|
856
|
+
index: number;
|
|
857
|
+
/** Custom message type only; prompt/content text is intentionally omitted. */
|
|
858
|
+
customType: string;
|
|
859
|
+
}
|
|
860
|
+
|
|
845
861
|
/**
|
|
846
862
|
* Fired after model selection to allow extensions to adjust the active tool set (ADR-005 Phase 4).
|
|
847
863
|
* Extensions can add, remove, or reorder tools based on the selected model's provider capabilities.
|
|
@@ -858,6 +874,12 @@ export interface AdjustToolSetEvent {
|
|
|
858
874
|
activeToolNames: string[];
|
|
859
875
|
/** Tools already filtered by provider compatibility */
|
|
860
876
|
filteredTools: string[];
|
|
877
|
+
/**
|
|
878
|
+
* Custom message metadata in the current request tail, measured from the
|
|
879
|
+
* latest assistant message. This is metadata-only so extensions can scope
|
|
880
|
+
* queued custom-message turns without seeing raw prompt content.
|
|
881
|
+
*/
|
|
882
|
+
requestCustomMessages?: AdjustToolSetRequestCustomMessage[];
|
|
861
883
|
}
|
|
862
884
|
|
|
863
885
|
/** Result from adjust_tool_set event handler. Return { toolNames } to override tool set. */
|
|
@@ -1480,6 +1502,20 @@ export interface ExtensionAPI {
|
|
|
1480
1502
|
/** Set the active tools by name. */
|
|
1481
1503
|
setActiveTools(toolNames: string[]): void;
|
|
1482
1504
|
|
|
1505
|
+
/**
|
|
1506
|
+
* Get the prompt-only skill catalog filter, if one is active.
|
|
1507
|
+
* Undefined means all loaded skills remain visible in <available_skills>.
|
|
1508
|
+
*/
|
|
1509
|
+
getVisibleSkills(): string[] | undefined;
|
|
1510
|
+
|
|
1511
|
+
/**
|
|
1512
|
+
* Set or clear the prompt-only skill catalog filter.
|
|
1513
|
+
*
|
|
1514
|
+
* This changes which loaded skills are advertised in <available_skills>;
|
|
1515
|
+
* it does not unload skills or disable the Skill tool.
|
|
1516
|
+
*/
|
|
1517
|
+
setVisibleSkills(skillNames: string[] | undefined): void;
|
|
1518
|
+
|
|
1483
1519
|
/** Get available slash commands in the current session. */
|
|
1484
1520
|
getCommands(): SlashCommandInfo[];
|
|
1485
1521
|
|
|
@@ -1721,6 +1757,8 @@ export interface ExtensionActions {
|
|
|
1721
1757
|
getActiveTools: () => string[];
|
|
1722
1758
|
getAllTools: () => ToolInfo[];
|
|
1723
1759
|
setActiveTools: (toolNames: string[]) => void;
|
|
1760
|
+
getVisibleSkills: () => string[] | undefined;
|
|
1761
|
+
setVisibleSkills: (skillNames: string[] | undefined) => void;
|
|
1724
1762
|
refreshTools: () => void;
|
|
1725
1763
|
getCommands: () => SlashCommandInfo[];
|
|
1726
1764
|
setModel: (model: Model<any>, options?: { persist?: boolean }) => Promise<boolean>;
|
|
@@ -1741,6 +1779,7 @@ export interface ExtensionContextActions {
|
|
|
1741
1779
|
getContextUsage: () => ContextUsage | undefined;
|
|
1742
1780
|
compact: (options?: CompactOptions) => void;
|
|
1743
1781
|
getSystemPrompt: () => string;
|
|
1782
|
+
setCompactionThresholdOverride: (percent: number | undefined) => void;
|
|
1744
1783
|
}
|
|
1745
1784
|
|
|
1746
1785
|
/**
|
|
@@ -1752,6 +1791,8 @@ export interface ExtensionCommandContextActions {
|
|
|
1752
1791
|
newSession: (options?: {
|
|
1753
1792
|
parentSession?: string;
|
|
1754
1793
|
setup?: (sessionManager: SessionManager) => Promise<void>;
|
|
1794
|
+
/** See ExtensionCommandContext.newSession for docs. */
|
|
1795
|
+
workspaceRoot?: string;
|
|
1755
1796
|
/** See ExtensionCommandContext.newSession for docs (#3731). */
|
|
1756
1797
|
abortSignal?: AbortSignal;
|
|
1757
1798
|
}) => Promise<{ cancelled: boolean }>;
|
|
@@ -38,6 +38,8 @@ function stubRuntime(): ExtensionRuntime {
|
|
|
38
38
|
getActiveTools: () => [],
|
|
39
39
|
getAllTools: () => [],
|
|
40
40
|
setActiveTools: () => {},
|
|
41
|
+
getVisibleSkills: () => undefined,
|
|
42
|
+
setVisibleSkills: () => {},
|
|
41
43
|
refreshTools: () => {},
|
|
42
44
|
getCommands: () => [],
|
|
43
45
|
setModel: async () => false,
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Tests final provider request-time tool compatibility filtering.
|
|
3
|
+
|
|
4
|
+
import assert from "node:assert/strict";
|
|
5
|
+
import test from "node:test";
|
|
6
|
+
import { Type } from "@sinclair/typebox";
|
|
7
|
+
import type { AgentTool } from "@gsd/pi-agent-core";
|
|
8
|
+
import { filterToolsForProviderRequest, getAdjustToolSetRequestCustomMessages } from "./sdk.js";
|
|
9
|
+
import { registerToolCompatibility, resetToolCompatibilityRegistry } from "./tools/tool-compatibility-registry.js";
|
|
10
|
+
|
|
11
|
+
function tool(name: string): AgentTool {
|
|
12
|
+
return {
|
|
13
|
+
name,
|
|
14
|
+
label: name,
|
|
15
|
+
description: name,
|
|
16
|
+
parameters: Type.Object({}),
|
|
17
|
+
execute: async () => ({ content: [], details: undefined }),
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
test("filterToolsForProviderRequest removes provider-incompatible tools", () => {
|
|
22
|
+
resetToolCompatibilityRegistry();
|
|
23
|
+
try {
|
|
24
|
+
registerToolCompatibility("image_result_tool", { producesImages: true });
|
|
25
|
+
registerToolCompatibility("complex_schema_tool", { schemaFeatures: ["patternProperties"] });
|
|
26
|
+
|
|
27
|
+
const result = filterToolsForProviderRequest(
|
|
28
|
+
[tool("bash"), tool("image_result_tool"), tool("complex_schema_tool")],
|
|
29
|
+
{ api: "google-generative-ai", provider: "google" },
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
assert.deepEqual(result.compatible.map((entry) => entry.name), ["bash", "image_result_tool"]);
|
|
33
|
+
assert.deepEqual(result.filtered.map((entry) => entry.name), ["complex_schema_tool"]);
|
|
34
|
+
} finally {
|
|
35
|
+
resetToolCompatibilityRegistry();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("filterToolsForProviderRequest enforces provider-specific hard caps at send time", () => {
|
|
40
|
+
const result = filterToolsForProviderRequest(
|
|
41
|
+
Array.from({ length: 130 }, (_, index) => tool(`tool_${index}`)),
|
|
42
|
+
{ api: "openai-completions", provider: "groq" },
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
assert.equal(result.compatible.length, 128);
|
|
46
|
+
assert.deepEqual(result.filtered.map((entry) => entry.name), ["tool_128", "tool_129"]);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("getAdjustToolSetRequestCustomMessages only reports custom messages in the current request tail", () => {
|
|
50
|
+
const messages = [
|
|
51
|
+
{ role: "custom", customType: "gsd-run", content: "old workflow", display: false, timestamp: 1 },
|
|
52
|
+
{ role: "assistant", content: [{ type: "text", text: "done" }], timestamp: 2 },
|
|
53
|
+
{ role: "user", content: [{ type: "text", text: "normal prompt" }], timestamp: 3 },
|
|
54
|
+
{ role: "custom", customType: "gsd-doctor-heal", content: "current workflow", display: false, timestamp: 4 },
|
|
55
|
+
] as any[];
|
|
56
|
+
|
|
57
|
+
assert.deepEqual(getAdjustToolSetRequestCustomMessages(messages), [
|
|
58
|
+
{ index: 3, customType: "gsd-doctor-heal" },
|
|
59
|
+
]);
|
|
60
|
+
});
|
|
@@ -38,8 +38,53 @@ export function canRestoreSessionModel(
|
|
|
38
38
|
): boolean {
|
|
39
39
|
return modelRegistry.isProviderRequestReady(model.provider);
|
|
40
40
|
}
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
|
|
42
|
+
const PROVIDER_TOOL_LIMITS: Record<string, number> = {
|
|
43
|
+
groq: 128,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
function resolveProviderToolLimit(
|
|
47
|
+
providerCaps: ReturnType<typeof getProviderCapabilities>,
|
|
48
|
+
provider: string | undefined,
|
|
49
|
+
): number {
|
|
50
|
+
if (provider && PROVIDER_TOOL_LIMITS[provider]) {
|
|
51
|
+
return PROVIDER_TOOL_LIMITS[provider];
|
|
52
|
+
}
|
|
53
|
+
return providerCaps.maxTools > 0 ? providerCaps.maxTools : 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function filterToolsForProviderRequest(
|
|
57
|
+
tools: AgentTool[],
|
|
58
|
+
model: Pick<Model<any>, "api" | "provider">,
|
|
59
|
+
): { compatible: AgentTool[]; filtered: AgentTool[] } {
|
|
60
|
+
const providerCaps = getProviderCapabilities(model.api);
|
|
61
|
+
if (!providerCaps.toolCalling) {
|
|
62
|
+
return { compatible: [], filtered: tools };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const compatible: AgentTool[] = [];
|
|
66
|
+
const filtered: AgentTool[] = [];
|
|
67
|
+
for (const tool of tools) {
|
|
68
|
+
const compat = getToolCompatibility(tool.name);
|
|
69
|
+
if (
|
|
70
|
+
(compat?.producesImages && !providerCaps.imageToolResults) ||
|
|
71
|
+
compat?.schemaFeatures?.some((feature) => providerCaps.unsupportedSchemaFeatures.includes(feature))
|
|
72
|
+
) {
|
|
73
|
+
filtered.push(tool);
|
|
74
|
+
} else {
|
|
75
|
+
compatible.push(tool);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const toolLimit = resolveProviderToolLimit(providerCaps, model.provider);
|
|
80
|
+
if (toolLimit > 0 && compatible.length > toolLimit) {
|
|
81
|
+
filtered.push(...compatible.splice(toolLimit));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return { compatible, filtered };
|
|
85
|
+
}
|
|
86
|
+
import { Agent, maybeLogProviderPayloadAudit, type AgentMessage, type AgentTool, type ThinkingLevel } from "@gsd/pi-agent-core";
|
|
87
|
+
import { getProviderCapabilities, type Message, type Model } from "@gsd/pi-ai";
|
|
43
88
|
import { getAgentDir, getDocsPath } from "../config.js";
|
|
44
89
|
import { AgentSession } from "./agent-session.js";
|
|
45
90
|
import { AuthStorage } from "./auth-storage.js";
|
|
@@ -82,6 +127,22 @@ import {
|
|
|
82
127
|
type ToolName,
|
|
83
128
|
writeTool,
|
|
84
129
|
} from "./tools/index.js";
|
|
130
|
+
import { getToolCompatibility } from "./tools/tool-compatibility-registry.js";
|
|
131
|
+
|
|
132
|
+
export function getAdjustToolSetRequestCustomMessages(
|
|
133
|
+
messages: readonly AgentMessage[] | undefined,
|
|
134
|
+
): Array<{ index: number; customType: string }> {
|
|
135
|
+
if (!messages) return [];
|
|
136
|
+
const requestMessages: Array<{ index: number; customType: string }> = [];
|
|
137
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
138
|
+
const message = messages[index] as { role?: unknown; customType?: unknown };
|
|
139
|
+
if (message?.role === "assistant") break;
|
|
140
|
+
if (message?.role === "custom" && typeof message.customType === "string") {
|
|
141
|
+
requestMessages.push({ index, customType: message.customType });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return requestMessages.reverse();
|
|
145
|
+
}
|
|
85
146
|
|
|
86
147
|
export interface CreateAgentSessionOptions {
|
|
87
148
|
/** Working directory for project-local discovery. Default: process.cwd() */
|
|
@@ -390,9 +451,12 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
390
451
|
onPayload: async (payload, currentModel) => {
|
|
391
452
|
const runner = extensionRunnerRef.current;
|
|
392
453
|
if (!runner?.hasHandlers("before_provider_request")) {
|
|
454
|
+
maybeLogProviderPayloadAudit(payload, "before_provider_request:unchanged");
|
|
393
455
|
return payload;
|
|
394
456
|
}
|
|
395
|
-
|
|
457
|
+
const nextPayload = await runner.emitBeforeProviderRequest(payload, currentModel);
|
|
458
|
+
maybeLogProviderPayloadAudit(nextPayload, "before_provider_request:after");
|
|
459
|
+
return nextPayload;
|
|
396
460
|
},
|
|
397
461
|
sessionId: sessionManager.getSessionId(),
|
|
398
462
|
transformContext: async (messages) => {
|
|
@@ -400,6 +464,24 @@ export async function createAgentSession(options: CreateAgentSessionOptions = {}
|
|
|
400
464
|
if (!runner) return messages;
|
|
401
465
|
return runner.emitContext(messages);
|
|
402
466
|
},
|
|
467
|
+
filterTools: async (tools, _signal, messages) => {
|
|
468
|
+
const currentModel = agent.state.activeInferenceModel ?? agent.state.model ?? model;
|
|
469
|
+
if (!currentModel) return tools;
|
|
470
|
+
const providerFiltered = filterToolsForProviderRequest(tools, currentModel);
|
|
471
|
+
const runner = extensionRunnerRef.current;
|
|
472
|
+
if (!runner?.hasHandlers("adjust_tool_set")) return providerFiltered.compatible;
|
|
473
|
+
const result = await runner.emitAdjustToolSet({
|
|
474
|
+
selectedModelApi: currentModel.api,
|
|
475
|
+
selectedModelProvider: currentModel.provider,
|
|
476
|
+
selectedModelId: currentModel.id,
|
|
477
|
+
activeToolNames: providerFiltered.compatible.map((tool) => tool.name),
|
|
478
|
+
filteredTools: providerFiltered.filtered.map((tool) => tool.name),
|
|
479
|
+
requestCustomMessages: getAdjustToolSetRequestCustomMessages(messages),
|
|
480
|
+
});
|
|
481
|
+
if (!result?.toolNames) return providerFiltered.compatible;
|
|
482
|
+
const allowedNames = new Set(result.toolNames);
|
|
483
|
+
return providerFiltered.compatible.filter((tool) => allowedNames.has(tool.name));
|
|
484
|
+
},
|
|
403
485
|
steeringMode: settingsManager.getSteeringMode(),
|
|
404
486
|
followUpMode: settingsManager.getFollowUpMode(),
|
|
405
487
|
transport: settingsManager.getTransport(),
|
|
@@ -15,6 +15,13 @@ export interface CompactionSettings {
|
|
|
15
15
|
enabled?: boolean; // default: true
|
|
16
16
|
reserveTokens?: number; // default: 16384
|
|
17
17
|
keepRecentTokens?: number; // default: 20000
|
|
18
|
+
/**
|
|
19
|
+
* Optional percent-of-context-window trigger (0 < value < 1). When set,
|
|
20
|
+
* compaction fires at `contextWindow * thresholdPercent` and overrides
|
|
21
|
+
* `reserveTokens`. Typically set as a runtime override by host integrations
|
|
22
|
+
* (see `setCompactionThresholdOverride`) and not persisted by users directly.
|
|
23
|
+
*/
|
|
24
|
+
thresholdPercent?: number;
|
|
18
25
|
}
|
|
19
26
|
|
|
20
27
|
export interface BranchSummarySettings {
|
|
@@ -812,11 +819,42 @@ export class SettingsManager {
|
|
|
812
819
|
return this.settings.compaction?.keepRecentTokens ?? COMPACTION_KEEP_RECENT_TOKENS;
|
|
813
820
|
}
|
|
814
821
|
|
|
815
|
-
|
|
822
|
+
getCompactionThresholdPercent(): number | undefined {
|
|
823
|
+
return this.settings.compaction?.thresholdPercent;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
/**
|
|
827
|
+
* Set or clear an in-memory compaction threshold-percent override.
|
|
828
|
+
*
|
|
829
|
+
* Applied to `this.settings` only; never persisted to disk. Pass `undefined`
|
|
830
|
+
* to clear a previously set override (necessary for idempotent re-sync from
|
|
831
|
+
* host integrations whose preference may have been removed).
|
|
832
|
+
*
|
|
833
|
+
* Direct mutation is used instead of `applyOverrides()` because deep-merge
|
|
834
|
+
* semantics skip `undefined` values, which would prevent clearing.
|
|
835
|
+
*/
|
|
836
|
+
setCompactionThresholdOverride(percent: number | undefined): void {
|
|
837
|
+
if (!this.settings.compaction) {
|
|
838
|
+
this.settings.compaction = {};
|
|
839
|
+
}
|
|
840
|
+
if (percent === undefined) {
|
|
841
|
+
delete this.settings.compaction.thresholdPercent;
|
|
842
|
+
} else {
|
|
843
|
+
this.settings.compaction.thresholdPercent = percent;
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
getCompactionSettings(): {
|
|
848
|
+
enabled: boolean;
|
|
849
|
+
reserveTokens: number;
|
|
850
|
+
keepRecentTokens: number;
|
|
851
|
+
thresholdPercent?: number;
|
|
852
|
+
} {
|
|
816
853
|
return {
|
|
817
854
|
enabled: this.getCompactionEnabled(),
|
|
818
855
|
reserveTokens: this.getCompactionReserveTokens(),
|
|
819
856
|
keepRecentTokens: this.getCompactionKeepRecentTokens(),
|
|
857
|
+
thresholdPercent: this.getCompactionThresholdPercent(),
|
|
820
858
|
};
|
|
821
859
|
}
|
|
822
860
|
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// Project/App: GSD-2
|
|
2
|
+
// File Purpose: Tests skill invocation and prompt-only skill visibility behavior.
|
|
3
|
+
|
|
1
4
|
import assert from "node:assert/strict";
|
|
2
5
|
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
3
6
|
import { tmpdir } from "node:os";
|
|
@@ -86,4 +89,29 @@ describe("Skill tool", () => {
|
|
|
86
89
|
assert.match(message, /^Skill "nonexistent" not found\. Available skills: /);
|
|
87
90
|
assert.match(message, /swift-testing/);
|
|
88
91
|
});
|
|
92
|
+
|
|
93
|
+
it("filters skill catalog without unloading skills or disabling Skill tool", async () => {
|
|
94
|
+
writeSkill(testDir, "alpha", "Use alpha.");
|
|
95
|
+
writeSkill(testDir, "beta", "Use beta.");
|
|
96
|
+
const session = await createSession();
|
|
97
|
+
|
|
98
|
+
assert.match(session.systemPrompt, /<name>alpha<\/name>/);
|
|
99
|
+
assert.match(session.systemPrompt, /<name>beta<\/name>/);
|
|
100
|
+
|
|
101
|
+
session.setVisibleSkillsByName(["alpha"]);
|
|
102
|
+
assert.deepEqual(session.getVisibleSkillNames(), ["alpha"]);
|
|
103
|
+
assert.match(session.systemPrompt, /<name>alpha<\/name>/);
|
|
104
|
+
assert.doesNotMatch(session.systemPrompt, /<name>beta<\/name>/);
|
|
105
|
+
|
|
106
|
+
const tool = session.state.tools.find((entry) => entry.name === "Skill");
|
|
107
|
+
assert.ok(tool, "Skill tool should remain active");
|
|
108
|
+
const result = await tool.execute("call-3", { skill: "beta" });
|
|
109
|
+
const text = result.content[0]?.type === "text" ? result.content[0].text : "";
|
|
110
|
+
assert.match(text, /<skill name="beta"/);
|
|
111
|
+
|
|
112
|
+
session.setVisibleSkillsByName(undefined);
|
|
113
|
+
assert.equal(session.getVisibleSkillNames(), undefined);
|
|
114
|
+
assert.match(session.systemPrompt, /<name>alpha<\/name>/);
|
|
115
|
+
assert.match(session.systemPrompt, /<name>beta<\/name>/);
|
|
116
|
+
});
|
|
89
117
|
});
|
|
@@ -59,13 +59,12 @@ export interface BuildSystemPromptOptions {
|
|
|
59
59
|
* Append a `Current date and time: <toLocaleString>` line to the system
|
|
60
60
|
* prompt. Default: `false`.
|
|
61
61
|
*
|
|
62
|
-
*
|
|
63
|
-
* Embedding a per-call timestamp in the system prompt invalidates
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
* and inject it via a non-cached channel (user message) when possible.
|
|
62
|
+
* Provider prompt caches generally depend on stable prompt prefixes.
|
|
63
|
+
* Embedding a per-call timestamp in the system prompt invalidates that
|
|
64
|
+
* stability on every request, often forcing full prompt reprocessing.
|
|
65
|
+
* Most agentic flows do not need wall-clock awareness in the system
|
|
66
|
+
* prompt — opt in only when the consumer genuinely needs it, and inject
|
|
67
|
+
* it via a non-cached channel (user message) when possible.
|
|
69
68
|
*/
|
|
70
69
|
includeDateTime?: boolean;
|
|
71
70
|
}
|
|
@@ -86,9 +85,8 @@ export function buildSystemPrompt(options: BuildSystemPromptOptions = {}): strin
|
|
|
86
85
|
} = options;
|
|
87
86
|
const resolvedCwd = toPosixPath(cwd ?? process.cwd());
|
|
88
87
|
|
|
89
|
-
// Per-call timestamps invalidate
|
|
90
|
-
//
|
|
91
|
-
// when explicitly opted in via `includeDateTime`.
|
|
88
|
+
// Per-call timestamps invalidate provider prompt cache stability. Compute
|
|
89
|
+
// lazily and only when explicitly opted in via `includeDateTime`.
|
|
92
90
|
const dateTimeLine = includeDateTime
|
|
93
91
|
? `\nCurrent date and time: ${new Date().toLocaleString("en-US", {
|
|
94
92
|
weekday: "long",
|
|
@@ -1287,6 +1287,10 @@ export class ToolPhaseSummaryComponent extends Container {
|
|
|
1287
1287
|
super();
|
|
1288
1288
|
}
|
|
1289
1289
|
|
|
1290
|
+
getPhases(): ToolExecutionPhase[] {
|
|
1291
|
+
return this.phases.map((phase) => ({ ...phase }));
|
|
1292
|
+
}
|
|
1293
|
+
|
|
1290
1294
|
override render(width: number): string[] {
|
|
1291
1295
|
const frameWidth = Math.max(20, width);
|
|
1292
1296
|
const rows = this.phases.map((phase) => {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
+
import { Container } from "@gsd/pi-tui";
|
|
4
|
+
import stripAnsi from "strip-ansi";
|
|
3
5
|
|
|
4
6
|
import { findLatestPinnableText, handleAgentEvent } from "./chat-controller.js";
|
|
5
7
|
import { initTheme } from "../theme/theme.js";
|
|
@@ -111,3 +113,57 @@ test("handleAgentEvent: agent_start clears stale adaptive blocking error", async
|
|
|
111
113
|
assert.equal(cleared, true);
|
|
112
114
|
assert.equal(requestedRender, true);
|
|
113
115
|
});
|
|
116
|
+
|
|
117
|
+
test("handleAgentEvent: standalone completed tool events roll up incrementally", async () => {
|
|
118
|
+
initTheme("dark", false);
|
|
119
|
+
const chatContainer = new Container();
|
|
120
|
+
let renderCount = 0;
|
|
121
|
+
const host = {
|
|
122
|
+
isInitialized: true,
|
|
123
|
+
footer: { invalidate() {} },
|
|
124
|
+
settingsManager: {
|
|
125
|
+
getTimestampFormat() {
|
|
126
|
+
return "date-time-iso";
|
|
127
|
+
},
|
|
128
|
+
getShowImages() {
|
|
129
|
+
return false;
|
|
130
|
+
},
|
|
131
|
+
},
|
|
132
|
+
getRegisteredToolDefinition() {
|
|
133
|
+
return undefined;
|
|
134
|
+
},
|
|
135
|
+
chatContainer,
|
|
136
|
+
pendingTools: new Map(),
|
|
137
|
+
ui: {
|
|
138
|
+
requestRender() {
|
|
139
|
+
renderCount++;
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
} as any;
|
|
143
|
+
|
|
144
|
+
for (const [toolCallId, toolName] of [
|
|
145
|
+
["read-1", "read"],
|
|
146
|
+
["read-2", "read"],
|
|
147
|
+
["edit-1", "edit"],
|
|
148
|
+
] as const) {
|
|
149
|
+
await handleAgentEvent(host, {
|
|
150
|
+
type: "tool_execution_start",
|
|
151
|
+
toolCallId,
|
|
152
|
+
toolName,
|
|
153
|
+
args: { path: `/tmp/${toolCallId}.txt` },
|
|
154
|
+
} as any);
|
|
155
|
+
await handleAgentEvent(host, {
|
|
156
|
+
type: "tool_execution_end",
|
|
157
|
+
toolCallId,
|
|
158
|
+
toolName,
|
|
159
|
+
result: { content: [], isError: false },
|
|
160
|
+
isError: false,
|
|
161
|
+
} as any);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const rendered = stripAnsi(chatContainer.render(100).join("\n"));
|
|
165
|
+
assert.match(rendered, /Context reads 2 actions\s+success · \d+(ms|s)/);
|
|
166
|
+
assert.match(rendered, /File changes 1 action\s+success · \d+(ms|s)/);
|
|
167
|
+
assert.doesNotMatch(rendered, /\bread\s+success ·/);
|
|
168
|
+
assert.ok(renderCount > 0);
|
|
169
|
+
});
|