gsd-pi 2.80.0-dev.42bd34838 → 2.80.0-dev.488219eb6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/claude-cli-check.d.ts +30 -0
- package/dist/claude-cli-check.js +18 -7
- package/dist/cli.js +0 -19
- package/dist/headless-query.d.ts +10 -0
- package/dist/headless-query.js +6 -4
- package/dist/loader-entrypoint.d.ts +8 -0
- package/dist/loader-entrypoint.js +27 -0
- package/dist/loader.js +2 -11
- package/dist/mcp-server.d.ts +1 -0
- package/dist/mcp-server.js +6 -3
- package/dist/resources/.managed-resources-content-hash +1 -1
- package/dist/resources/extensions/claude-code-cli/readiness.js +18 -7
- package/dist/resources/extensions/claude-code-cli/stream-adapter.js +29 -0
- package/dist/resources/extensions/github-sync/sync.js +4 -1
- package/dist/resources/extensions/gsd/auto/loop.js +71 -8
- package/dist/resources/extensions/gsd/auto/phases.js +179 -99
- package/dist/resources/extensions/gsd/auto/resolve.js +12 -0
- package/dist/resources/extensions/gsd/auto/run-unit.js +10 -30
- package/dist/resources/extensions/gsd/auto/session.js +8 -0
- package/dist/resources/extensions/gsd/auto/workflow-dispatch-claim.js +33 -1
- package/dist/resources/extensions/gsd/auto/workflow-worker-heartbeat.js +9 -1
- 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 +94 -76
- package/dist/resources/extensions/gsd/auto-prompts.js +90 -15
- package/dist/resources/extensions/gsd/auto-start.js +238 -12
- package/dist/resources/extensions/gsd/auto-worktree.js +209 -81
- package/dist/resources/extensions/gsd/auto.js +95 -44
- package/dist/resources/extensions/gsd/bootstrap/agent-end-recovery.js +96 -26
- package/dist/resources/extensions/gsd/bootstrap/db-tools.js +44 -37
- package/dist/resources/extensions/gsd/bootstrap/dynamic-tools.js +37 -10
- package/dist/resources/extensions/gsd/bootstrap/exec-tools.js +6 -3
- package/dist/resources/extensions/gsd/bootstrap/journal-tools.js +4 -1
- package/dist/resources/extensions/gsd/bootstrap/memory-tools.js +6 -4
- package/dist/resources/extensions/gsd/bootstrap/query-tools.js +5 -3
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +1 -1
- package/dist/resources/extensions/gsd/bootstrap/register-hooks.js +298 -54
- package/dist/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.js +4 -0
- 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/ops.js +2 -2
- package/dist/resources/extensions/gsd/commands-config.js +1 -1
- package/dist/resources/extensions/gsd/commands-eval-review.js +2 -2
- package/dist/resources/extensions/gsd/commands-handlers.js +23 -9
- package/dist/resources/extensions/gsd/dashboard-overlay.js +1 -1
- package/dist/resources/extensions/gsd/db/unit-dispatches.js +53 -0
- package/dist/resources/extensions/gsd/ecosystem/gsd-extension-api.js +2 -0
- package/dist/resources/extensions/gsd/git-service.js +37 -1
- package/dist/resources/extensions/gsd/guided-flow.js +61 -32
- package/dist/resources/extensions/gsd/init-wizard.js +4 -1
- 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/pre-execution-checks.js +22 -0
- package/dist/resources/extensions/gsd/prompts/complete-milestone.md +8 -4
- 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/plan-slice.md +1 -1
- package/dist/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/dist/resources/extensions/gsd/slice-cadence.js +45 -2
- package/dist/resources/extensions/gsd/slice-parallel-orchestrator.js +15 -9
- package/dist/resources/extensions/gsd/tools/complete-milestone.js +6 -7
- package/dist/resources/extensions/gsd/tools/complete-task.js +1 -1
- package/dist/resources/extensions/gsd/workflow-protocol.js +131 -0
- package/dist/resources/extensions/gsd/worktree-resolver.js +57 -5
- package/dist/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/tsconfig.extensions.tsbuildinfo +1 -1
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- 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/react-loadable-manifest.json +2 -2
- package/dist/web/standalone/.next/required-server-files.json +1 -1
- 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_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 +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 +2 -2
- 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 +2 -2
- 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/page_client-reference-manifest.js +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-react-loadable-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware.js +3 -3
- 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/8359.e059d86b255fce1c.js +10 -0
- package/dist/web/standalone/.next/static/chunks/app/{page-fab3ebb85b006001.js → page-752f1e2ebdaa3e45.js} +1 -1
- package/dist/web/standalone/.next/static/chunks/{webpack-0481f1221120a7c6.js → webpack-de742b64187e13fe.js} +1 -1
- package/dist/web/standalone/server.js +1 -1
- package/dist/welcome-screen.d.ts +2 -0
- package/dist/welcome-screen.js +9 -7
- package/package.json +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-ai/dist/providers/anthropic-auth.test.js +35 -13
- package/packages/pi-ai/dist/providers/anthropic-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js +21 -11
- package/packages/pi-ai/dist/providers/anthropic-bearer-auth.test.js.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.d.ts +7 -0
- package/packages/pi-ai/dist/providers/anthropic.d.ts.map +1 -1
- package/packages/pi-ai/dist/providers/anthropic.js +9 -7
- package/packages/pi-ai/dist/providers/anthropic.js.map +1 -1
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js +23 -14
- package/packages/pi-ai/dist/providers/minimax-tool-name.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js +48 -21
- package/packages/pi-ai/dist/utils/oauth/github-copilot.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-antigravity.test.js.map +1 -1
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js +22 -21
- package/packages/pi-ai/dist/utils/oauth/google-gemini-cli.test.js.map +1 -1
- package/packages/pi-ai/src/providers/anthropic-auth.test.ts +39 -25
- package/packages/pi-ai/src/providers/anthropic-bearer-auth.test.ts +26 -22
- package/packages/pi-ai/src/providers/anthropic.ts +22 -9
- package/packages/pi-ai/src/providers/minimax-tool-name.test.ts +34 -21
- package/packages/pi-ai/src/utils/oauth/github-copilot.test.ts +56 -22
- package/packages/pi-ai/src/utils/oauth/google-antigravity.test.ts +24 -28
- package/packages/pi-ai/src/utils/oauth/google-gemini-cli.test.ts +24 -28
- package/packages/pi-ai/tsconfig.tsbuildinfo +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 +36 -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/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 +2 -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 +3 -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 +3 -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 +34 -3
- 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/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/core/tools/bash-spawn-windows.test.js +22 -56
- package/packages/pi-coding-agent/dist/core/tools/bash-spawn-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts +1 -0
- package/packages/pi-coding-agent/dist/core/tools/bash.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/bash.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/edit.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js +12 -1
- package/packages/pi-coding-agent/dist/core/tools/edit.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/find.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/find.js +14 -6
- package/packages/pi-coding-agent/dist/core/tools/find.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/grep.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/grep.js +12 -3
- package/packages/pi-coding-agent/dist/core/tools/grep.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/hashline-read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts +2 -1
- package/packages/pi-coding-agent/dist/core/tools/index.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/index.js +1 -0
- package/packages/pi-coding-agent/dist/core/tools/index.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/ls.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/ls.js +10 -3
- package/packages/pi-coding-agent/dist/core/tools/ls.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/read.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js +3 -1
- package/packages/pi-coding-agent/dist/core/tools/read.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js +7 -62
- package/packages/pi-coding-agent/dist/core/tools/spawn-shell-windows.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts +2 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js +115 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target-metadata.test.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts +19 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.d.ts.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js +20 -0
- package/packages/pi-coding-agent/dist/core/tools/tool-target.js.map +1 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts +4 -0
- package/packages/pi-coding-agent/dist/core/tools/write.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js +9 -1
- package/packages/pi-coding-agent/dist/core/tools/write.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/__tests__/tool-execution.test.js +89 -2
- 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/tool-card-cleanup-and-success-runtime.test.js +25 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/modes/interactive/components/tool-execution.d.ts +5 -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 +153 -8
- 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 +18 -1
- 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 +23 -5
- 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 +2 -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 +19 -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.js +23 -5
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage-safety-guard.test.js.map +1 -1
- 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 +40 -7
- package/packages/pi-coding-agent/src/core/chat-controller-ordering.test.ts +3 -1
- package/packages/pi-coding-agent/src/core/extensions/loader.ts +10 -0
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +3 -3
- package/packages/pi-coding-agent/src/core/extensions/runner.ts +5 -5
- package/packages/pi-coding-agent/src/core/extensions/types.ts +37 -2
- 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/skill-tool.test.ts +28 -0
- package/packages/pi-coding-agent/src/core/system-prompt.ts +8 -10
- package/packages/pi-coding-agent/src/core/tools/bash-spawn-windows.test.ts +22 -66
- package/packages/pi-coding-agent/src/core/tools/bash.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/edit.ts +13 -1
- package/packages/pi-coding-agent/src/core/tools/find.ts +15 -6
- package/packages/pi-coding-agent/src/core/tools/grep.ts +13 -3
- package/packages/pi-coding-agent/src/core/tools/hashline-read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/index.ts +8 -0
- package/packages/pi-coding-agent/src/core/tools/ls.ts +11 -3
- package/packages/pi-coding-agent/src/core/tools/read.ts +4 -1
- package/packages/pi-coding-agent/src/core/tools/spawn-shell-windows.test.ts +11 -72
- package/packages/pi-coding-agent/src/core/tools/tool-target-metadata.test.ts +127 -0
- package/packages/pi-coding-agent/src/core/tools/tool-target.ts +48 -0
- package/packages/pi-coding-agent/src/core/tools/write.ts +14 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/__tests__/tool-execution.test.ts +119 -2
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-card-cleanup-and-success-runtime.test.ts +31 -1
- package/packages/pi-coding-agent/src/modes/interactive/components/tool-execution.ts +177 -8
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.test.ts +24 -5
- package/packages/pi-coding-agent/src/modes/interactive/controllers/chat-controller.ts +17 -1
- package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +21 -0
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage-safety-guard.test.ts +25 -8
- package/packages/pi-coding-agent/tsconfig.tsbuildinfo +1 -1
- package/src/resources/extensions/claude-code-cli/readiness.ts +25 -7
- package/src/resources/extensions/claude-code-cli/stream-adapter.ts +30 -0
- package/src/resources/extensions/claude-code-cli/tests/stream-adapter.test.ts +26 -0
- package/src/resources/extensions/github-sync/sync.ts +8 -1
- package/src/resources/extensions/github-sync/tests/sync-source.test.ts +6 -18
- package/src/resources/extensions/gsd/auto/loop-deps.ts +2 -2
- package/src/resources/extensions/gsd/auto/loop.ts +84 -8
- package/src/resources/extensions/gsd/auto/phases.ts +258 -159
- package/src/resources/extensions/gsd/auto/resolve.ts +19 -0
- package/src/resources/extensions/gsd/auto/run-unit.ts +10 -29
- package/src/resources/extensions/gsd/auto/session.ts +8 -0
- package/src/resources/extensions/gsd/auto/workflow-dispatch-claim.ts +63 -1
- package/src/resources/extensions/gsd/auto/workflow-worker-heartbeat.ts +14 -1
- 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 +107 -78
- package/src/resources/extensions/gsd/auto-prompts.ts +95 -14
- package/src/resources/extensions/gsd/auto-start.ts +286 -15
- package/src/resources/extensions/gsd/auto-worktree.ts +241 -72
- package/src/resources/extensions/gsd/auto.ts +132 -40
- package/src/resources/extensions/gsd/bootstrap/agent-end-recovery.ts +116 -24
- package/src/resources/extensions/gsd/bootstrap/db-tools.ts +45 -37
- package/src/resources/extensions/gsd/bootstrap/dynamic-tools.ts +36 -10
- package/src/resources/extensions/gsd/bootstrap/exec-tools.ts +8 -3
- package/src/resources/extensions/gsd/bootstrap/journal-tools.ts +5 -1
- package/src/resources/extensions/gsd/bootstrap/memory-tools.ts +7 -4
- package/src/resources/extensions/gsd/bootstrap/query-tools.ts +6 -3
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +1 -1
- package/src/resources/extensions/gsd/bootstrap/register-hooks.ts +347 -54
- package/src/resources/extensions/gsd/bootstrap/sanitize-complete-milestone.ts +4 -0
- 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/ops.ts +4 -2
- package/src/resources/extensions/gsd/commands-config.ts +1 -1
- package/src/resources/extensions/gsd/commands-eval-review.ts +2 -2
- package/src/resources/extensions/gsd/commands-handlers.ts +34 -15
- package/src/resources/extensions/gsd/dashboard-overlay.ts +1 -1
- package/src/resources/extensions/gsd/db/unit-dispatches.ts +66 -0
- package/src/resources/extensions/gsd/ecosystem/gsd-extension-api.ts +3 -0
- package/src/resources/extensions/gsd/git-service.ts +41 -2
- package/src/resources/extensions/gsd/guided-flow.ts +71 -39
- package/src/resources/extensions/gsd/init-wizard.ts +5 -1
- 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/pre-execution-checks.ts +23 -0
- package/src/resources/extensions/gsd/prompts/complete-milestone.md +8 -4
- 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/plan-slice.md +1 -1
- package/src/resources/extensions/gsd/prompts/replan-slice.md +2 -2
- package/src/resources/extensions/gsd/slice-cadence.ts +49 -2
- package/src/resources/extensions/gsd/slice-parallel-orchestrator.ts +23 -9
- package/src/resources/extensions/gsd/tests/agent-end-retry.test.ts +59 -89
- package/src/resources/extensions/gsd/tests/artifact-retry-cap.test.ts +47 -172
- package/src/resources/extensions/gsd/tests/artifacts-table-preserved-on-cache-invalidate.test.ts +0 -35
- package/src/resources/extensions/gsd/tests/auto-dashboard.test.ts +35 -9
- package/src/resources/extensions/gsd/tests/auto-loop.test.ts +361 -10
- package/src/resources/extensions/gsd/tests/auto-model-selection.test.ts +80 -59
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +3 -47
- package/src/resources/extensions/gsd/tests/auto-paused-ui-cleanup.test.ts +76 -18
- package/src/resources/extensions/gsd/tests/auto-phases-lifecycle.test.ts +106 -0
- package/src/resources/extensions/gsd/tests/auto-pr-bugs.test.ts +54 -95
- package/src/resources/extensions/gsd/tests/auto-project-root-env.test.ts +67 -26
- package/src/resources/extensions/gsd/tests/auto-remediate-slice-status.test.ts +32 -30
- package/src/resources/extensions/gsd/tests/auto-start-bootstrap-await-3420.test.ts +32 -128
- package/src/resources/extensions/gsd/tests/auto-start-clean-runtime-db-gated.test.ts +20 -54
- package/src/resources/extensions/gsd/tests/auto-start-cold-db-bootstrap.test.ts +20 -30
- package/src/resources/extensions/gsd/tests/auto-start-index-lock.test.ts +17 -29
- package/src/resources/extensions/gsd/tests/auto-start-orphan-bootstrap.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/auto-start-time-persistence.test.ts +21 -39
- package/src/resources/extensions/gsd/tests/auto-start-worktree-db-path.test.ts +15 -24
- package/src/resources/extensions/gsd/tests/auto-thinking-restore.test.ts +44 -29
- package/src/resources/extensions/gsd/tests/auto-warning-noise-regression.test.ts +39 -51
- package/src/resources/extensions/gsd/tests/auto-wrapup-inflight-guard.test.ts +159 -213
- package/src/resources/extensions/gsd/tests/bootstrap-derive-state-db-open.test.ts +15 -32
- package/src/resources/extensions/gsd/tests/browser-teardown.test.ts +0 -41
- package/src/resources/extensions/gsd/tests/clean-root-preflight.test.ts +15 -6
- package/src/resources/extensions/gsd/tests/clear-stale-autostart.test.ts +34 -27
- package/src/resources/extensions/gsd/tests/cmux.test.ts +51 -53
- package/src/resources/extensions/gsd/tests/cold-resume-db-reopen.test.ts +39 -61
- package/src/resources/extensions/gsd/tests/commands-config.test.ts +26 -19
- package/src/resources/extensions/gsd/tests/complete-milestone-excerpt.test.ts +31 -0
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +140 -0
- package/src/resources/extensions/gsd/tests/complete-slice-composer.test.ts +3 -2
- package/src/resources/extensions/gsd/tests/complete-task-normalize-lists.test.ts +29 -33
- package/src/resources/extensions/gsd/tests/completed-units-metrics-sync.test.ts +45 -108
- package/src/resources/extensions/gsd/tests/context-store.test.ts +7 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +35 -31
- package/src/resources/extensions/gsd/tests/custom-engine-loop-integration.test.ts +5 -1
- package/src/resources/extensions/gsd/tests/cwd-fallback-hardening.test.ts +138 -0
- package/src/resources/extensions/gsd/tests/dashboard-custom-engine.test.ts +4 -68
- package/src/resources/extensions/gsd/tests/deep-project-auto-loop.test.ts +4 -9
- package/src/resources/extensions/gsd/tests/deferred-milestone-dir-4996.test.ts +14 -65
- package/src/resources/extensions/gsd/tests/discuss-tool-scoping.test.ts +44 -37
- package/src/resources/extensions/gsd/tests/dispatch-complete-milestone-guard.test.ts +58 -40
- package/src/resources/extensions/gsd/tests/dispatch-guard-closed-status.test.ts +25 -15
- package/src/resources/extensions/gsd/tests/dispatcher-stuck-planning.test.ts +35 -17
- package/src/resources/extensions/gsd/tests/error-success-mask.test.ts +16 -21
- package/src/resources/extensions/gsd/tests/est-annotation-timeout.test.ts +15 -82
- 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/flat-rate-routing-guard.test.ts +2 -20
- package/src/resources/extensions/gsd/tests/frontmatter-parse-noise.test.ts +18 -26
- package/src/resources/extensions/gsd/tests/init-skip-git.test.ts +9 -12
- package/src/resources/extensions/gsd/tests/integration/auto-worktree-milestone-merge.test.ts +40 -0
- package/src/resources/extensions/gsd/tests/integration/commands-eval-review.integration.test.ts +4 -2
- package/src/resources/extensions/gsd/tests/integration/git-locale.test.ts +31 -20
- package/src/resources/extensions/gsd/tests/integration/git-service.test.ts +12 -0
- package/src/resources/extensions/gsd/tests/integration/milestone-transition-worktree.test.ts +0 -47
- package/src/resources/extensions/gsd/tests/interactive-routing-bypass.test.ts +60 -202
- package/src/resources/extensions/gsd/tests/isolation-none-branch-guard.test.ts +13 -56
- package/src/resources/extensions/gsd/tests/journal-integration.test.ts +5 -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/lazy-pi-tui-import.test.ts +44 -6
- package/src/resources/extensions/gsd/tests/memory-pressure-stuck-state.test.ts +21 -35
- package/src/resources/extensions/gsd/tests/merge-conflict-stops-loop.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/milestone-merge-stash-restore.test.ts +242 -0
- package/src/resources/extensions/gsd/tests/milestone-transition-state-rebuild.test.ts +79 -98
- package/src/resources/extensions/gsd/tests/model-unittype-mapping.test.ts +70 -278
- package/src/resources/extensions/gsd/tests/native-git-bridge-exec-fallback.test.ts +34 -2
- package/src/resources/extensions/gsd/tests/needs-remediation-revalidation.test.ts +37 -30
- package/src/resources/extensions/gsd/tests/note-captures-executed.test.ts +32 -28
- 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/phantom-ghost-detection.test.ts +24 -37
- package/src/resources/extensions/gsd/tests/phantom-milestone-default-queued.test.ts +9 -24
- package/src/resources/extensions/gsd/tests/phases-merge-error-stops-auto.test.ts +91 -75
- package/src/resources/extensions/gsd/tests/post-unit-state-rebuild.test.ts +36 -22
- package/src/resources/extensions/gsd/tests/pre-exec-backtick-strip.test.ts +36 -30
- package/src/resources/extensions/gsd/tests/pre-execution-checks.test.ts +45 -5
- package/src/resources/extensions/gsd/tests/pre-execution-pause-wiring.test.ts +74 -4
- package/src/resources/extensions/gsd/tests/preferences-worktree-sync.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/prefs-wizard-coverage.test.ts +130 -32
- package/src/resources/extensions/gsd/tests/project-root-cwd-crash.test.ts +18 -36
- package/src/resources/extensions/gsd/tests/projection-no-plan-overwrite.test.ts +35 -73
- package/src/resources/extensions/gsd/tests/prompt-budget-enforcement.test.ts +76 -138
- package/src/resources/extensions/gsd/tests/prompt-duplication-cuts.test.ts +230 -0
- package/src/resources/extensions/gsd/tests/prompt-step-ordering.test.ts +70 -125
- package/src/resources/extensions/gsd/tests/provider-errors.test.ts +59 -161
- package/src/resources/extensions/gsd/tests/query-tools-db-open.test.ts +33 -29
- package/src/resources/extensions/gsd/tests/queue-auto-guard.test.ts +22 -196
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +23 -93
- package/src/resources/extensions/gsd/tests/quick-turn-end-cleanup.test.ts +50 -79
- package/src/resources/extensions/gsd/tests/reassess-default-optin.test.ts +27 -13
- package/src/resources/extensions/gsd/tests/remote-questions.test.ts +151 -251
- package/src/resources/extensions/gsd/tests/resource-loader-import-path.test.ts +41 -29
- package/src/resources/extensions/gsd/tests/restore-tools-after-discuss.test.ts +58 -69
- package/src/resources/extensions/gsd/tests/resume-dispatch-worktree.test.ts +32 -164
- package/src/resources/extensions/gsd/tests/run-uat-replay-cap.test.ts +57 -41
- package/src/resources/extensions/gsd/tests/select-resumable-milestone.test.ts +96 -0
- package/src/resources/extensions/gsd/tests/session-model-override.test.ts +14 -9
- package/src/resources/extensions/gsd/tests/session-start-footer.test.ts +77 -0
- package/src/resources/extensions/gsd/tests/session-switch-abort-misclassification.test.ts +166 -0
- package/src/resources/extensions/gsd/tests/show-config-command.test.ts +44 -42
- package/src/resources/extensions/gsd/tests/skip-slice-state-rebuild.test.ts +56 -24
- package/src/resources/extensions/gsd/tests/skipped-validation-db-atomicity.test.ts +51 -11
- package/src/resources/extensions/gsd/tests/slice-cadence.test.ts +23 -0
- package/src/resources/extensions/gsd/tests/slice-context-injection.test.ts +66 -50
- package/src/resources/extensions/gsd/tests/slice-parallel-orchestrator.test.ts +68 -107
- package/src/resources/extensions/gsd/tests/slice-sequence-insert.test.ts +115 -42
- package/src/resources/extensions/gsd/tests/smart-entry-complete.test.ts +21 -97
- package/src/resources/extensions/gsd/tests/smart-entry-draft.test.ts +25 -116
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +21 -57
- package/src/resources/extensions/gsd/tests/stale-dirlistcache-4648.test.ts +29 -76
- package/src/resources/extensions/gsd/tests/stale-lockfile-recovery.test.ts +33 -24
- package/src/resources/extensions/gsd/tests/stale-slice-rows.test.ts +39 -30
- package/src/resources/extensions/gsd/tests/state-corruption-2945.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/status-db-open.test.ts +33 -47
- package/src/resources/extensions/gsd/tests/stop-auto-merge-back.test.ts +48 -46
- package/src/resources/extensions/gsd/tests/stop-auto-race-null-unit.test.ts +14 -102
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +78 -232
- package/src/resources/extensions/gsd/tests/sync-worktree-skip-current.test.ts +32 -35
- 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-profile.test.ts +84 -309
- package/src/resources/extensions/gsd/tests/token-tool-gating.test.ts +291 -0
- package/src/resources/extensions/gsd/tests/triage-dispatch.test.ts +134 -341
- package/src/resources/extensions/gsd/tests/unit-context-manifest.test.ts +8 -25
- package/src/resources/extensions/gsd/tests/unit-dispatches.test.ts +50 -1
- package/src/resources/extensions/gsd/tests/unstructured-continue-context-injection.test.ts +5 -99
- package/src/resources/extensions/gsd/tests/uok-plan-v2-wiring.test.ts +43 -36
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -444
- package/src/resources/extensions/gsd/tests/workflow-dispatch-claim.test.ts +142 -0
- package/src/resources/extensions/gsd/tests/workflow-logger-wiring.test.ts +44 -189
- package/src/resources/extensions/gsd/tests/workflow-mcp.test.ts +2 -57
- package/src/resources/extensions/gsd/tests/workflow-protocol-excerpt.test.ts +99 -0
- package/src/resources/extensions/gsd/tests/workflow-worker-heartbeat.test.ts +32 -1
- package/src/resources/extensions/gsd/tests/worktree-db-same-file.test.ts +21 -44
- package/src/resources/extensions/gsd/tests/worktree-expected-warnings.test.ts +27 -26
- package/src/resources/extensions/gsd/tests/worktree-health-dispatch.test.ts +14 -13
- package/src/resources/extensions/gsd/tests/worktree-journal-events.test.ts +1 -0
- package/src/resources/extensions/gsd/tests/worktree-main-branch.test.ts +20 -18
- 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 +140 -3
- package/src/resources/extensions/gsd/tests/zero-slice-roadmap-guided.test.ts +19 -13
- package/src/resources/extensions/gsd/tools/complete-milestone.ts +14 -15
- package/src/resources/extensions/gsd/tools/complete-task.ts +1 -1
- package/src/resources/extensions/gsd/workflow-protocol.ts +160 -0
- package/src/resources/extensions/gsd/worktree-resolver.ts +83 -5
- package/src/resources/skills/create-gsd-extension/templates/templates.test.ts +86 -40
- package/src/resources/skills/web-quality-audit/scripts/analyze.sh +0 -0
- package/dist/web/standalone/.next/static/chunks/8336.631939fb583761fa.js +0 -10
- /package/dist/web/standalone/.next/static/{tht0ltP8EIjsohPOA_WZf → G68KoLv5claox_Dyd4pZn}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{tht0ltP8EIjsohPOA_WZf → G68KoLv5claox_Dyd4pZn}/_ssgManifest.js +0 -0
|
@@ -19,9 +19,8 @@ const toolDescriptions = {
|
|
|
19
19
|
export function buildSystemPrompt(options = {}) {
|
|
20
20
|
const { customPrompt, selectedTools, toolSnippets, promptGuidelines, appendSystemPrompt, cwd, contextFiles: providedContextFiles, skills: providedSkills, skillFilter, includeDateTime = false, } = options;
|
|
21
21
|
const resolvedCwd = toPosixPath(cwd ?? process.cwd());
|
|
22
|
-
// Per-call timestamps invalidate
|
|
23
|
-
//
|
|
24
|
-
// when explicitly opted in via `includeDateTime`.
|
|
22
|
+
// Per-call timestamps invalidate provider prompt cache stability. Compute
|
|
23
|
+
// lazily and only when explicitly opted in via `includeDateTime`.
|
|
25
24
|
const dateTimeLine = includeDateTime
|
|
26
25
|
? `\nCurrent date and time: ${new Date().toLocaleString("en-US", {
|
|
27
26
|
weekday: "long",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { toPosixPath } from \"../utils/path-display.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<string, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n\tlsp: \"Code intelligence via Language Server Protocol (go-to-definition, references, diagnostics, hover, rename, symbols)\",\n};\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. Default: process.cwd() */\n\tcwd?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/**\n\t * Optional predicate applied to the `skills` list before rendering the\n\t * <available_skills> catalog. Returning `false` omits a skill from the\n\t * prompt (the skill remains loaded and invocable by name — only the\n\t * catalog listing is suppressed).\n\t *\n\t * Intended for consumers that can narrow the relevant skill surface\n\t * (e.g. per-unit-type manifests) to reduce cached system-prompt bloat.\n\t * When omitted, all non-`disableModelInvocation` skills render — i.e.\n\t * behavior is unchanged from before this option existed.\n\t *\n\t * Contract: the predicate must be **pure and synchronous**. It may be\n\t * invoked on every system-prompt rebuild (tool-set changes and\n\t * runtime resource-loader extensions both trigger one), so any state\n\t * the closure captures should be stable across the rebuild window.\n\t * If the predicate throws, `buildSystemPrompt` logs a warning and\n\t * falls back to the unfiltered skill list — callers never see the\n\t * exception and the session stays consistent.\n\t */\n\tskillFilter?: (skill: Skill) => boolean;\n\t/**\n\t * Append a `Current date and time: <toLocaleString>` line to the system\n\t * prompt. Default: `false`.\n\t *\n\t * Anthropic prompt caching matches on byte-for-byte prefix equality.\n\t * Embedding a per-call timestamp in the system prompt invalidates the\n\t * cache on every request, forcing a full re-write that costs *more*\n\t * than an uncached call (cache-write premium). Most agentic flows do\n\t * not need wall-clock awareness in the system prompt — opt in only\n\t * when the consumer genuinely needs it (e.g. a clock-sensitive agent),\n\t * and inject it via a non-cached channel (user message) when possible.\n\t */\n\tincludeDateTime?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tskillFilter,\n\t\tincludeDateTime = false,\n\t} = options;\n\tconst resolvedCwd = toPosixPath(cwd ?? process.cwd());\n\n\t// Per-call timestamps invalidate Anthropic prompt caching (the cache\n\t// matches on byte-for-byte prefix equality). Compute lazily and only\n\t// when explicitly opted in via `includeDateTime`.\n\tconst dateTimeLine = includeDateTime\n\t\t? `\\nCurrent date and time: ${new Date().toLocaleString(\"en-US\", {\n\t\t\tweekday: \"long\",\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"long\",\n\t\t\tday: \"numeric\",\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t\tsecond: \"2-digit\",\n\t\t\ttimeZoneName: \"short\",\n\t\t})}`\n\t\t: \"\";\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skillsBase = providedSkills ?? [];\n\tlet skills = skillsBase;\n\tif (skillFilter) {\n\t\ttry {\n\t\t\tskills = skillsBase.filter(skillFilter);\n\t\t} catch (error) {\n\t\t\t// A consumer's predicate threw. Fall back to the unfiltered list so\n\t\t\t// the session stays consistent — callers (e.g. AgentSession.setTools)\n\t\t\t// must not be left with updated tools but a stale system prompt.\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`buildSystemPrompt: skillFilter threw; falling back to unfiltered skills. Error: ${message}`);\n\t\t\tskills = skillsBase;\n\t\t}\n\t}\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (if read or Skill tool is available)\n\t\tconst customPromptHasSkillAccess = !selectedTools || selectedTools.includes(\"read\") || selectedTools.includes(\"Skill\");\n\t\tif (customPromptHasSkillAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date/time (only when opted in — see includeDateTime docs) and working directory last\n\t\tprompt += dateTimeLine;\n\t\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\t\t// Append promptGuidelines from extension-registered tools.\n\t\t// Without this, tools registered via pi.registerTool() with promptGuidelines\n\t\t// have their definitions reach the API but the model has no guidance on when\n\t\t// to use them (#1184).\n\t\tif (promptGuidelines && promptGuidelines.length > 0) {\n\t\t\tprompt += \"\\n\\n\";\n\t\t\tfor (const guideline of promptGuidelines) {\n\t\t\t\tprompt += guideline + \"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = toPosixPath(getReadmePath());\n\tconst docsPath = toPosixPath(getDocsPath());\n\tconst examplesPath = toPosixPath(getExamplesPath());\n\n\t// Build tools list based on selected tools.\n\t// Built-ins use toolDescriptions. Custom tools can provide one-line snippets.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst toolsList =\n\t\ttools.length > 0\n\t\t\t? tools\n\t\t\t\t\t.map((name) => {\n\t\t\t\t\t\tconst snippet = toolSnippets?.[name] ?? toolDescriptions[name] ?? name;\n\t\t\t\t\t\treturn `- ${name}: ${snippet}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")\n\t\t\t: \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\tconst hasLsp = tools.includes(\"lsp\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\taddGuideline(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\taddGuideline(\"Use read to examine files before editing. You must use this tool instead of cat or sed.\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\taddGuideline(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\taddGuideline(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// LSP guideline\n\tif (hasLsp) {\n\t\taddGuideline(\n\t\t\t`Use lsp as the primary tool for code navigation in typed codebases:\n- Navigation: definition, type_definition, implementation, references, incoming_calls, outgoing_calls\n- Understanding: hover (types + docs), signature (parameter info), symbols (file/workspace search)\n- Refactoring: rename (project-wide), code_actions (quick-fixes, imports, refactors), format (formatter)\n- Verification: diagnostics after edits to catch type errors immediately\n- Never grep for a symbol definition when lsp can resolve it semantically\n- Never shell out to a formatter when lsp format is available`,\n\t\t);\n\t}\n\n\t// Output guideline (only when actually writing or executing)\n\tif (hasEdit || hasWrite) {\n\t\taddGuideline(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (if read or Skill tool is available)\n\tconst hasSkill = tools.includes(\"Skill\");\n\tif ((hasRead || hasSkill) && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time (only when opted in — see includeDateTime docs) and working directory last\n\tprompt += dateTimeLine;\n\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.js\";\nimport { toPosixPath } from \"../utils/path-display.js\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.js\";\n\n/** Tool descriptions for system prompt */\nconst toolDescriptions: Record<string, string> = {\n\tread: \"Read file contents\",\n\tbash: \"Execute bash commands (ls, grep, find, etc.)\",\n\tedit: \"Make surgical edits to files (find exact text and replace)\",\n\twrite: \"Create or overwrite files\",\n\tgrep: \"Search file contents for patterns (respects .gitignore)\",\n\tfind: \"Find files by glob pattern (respects .gitignore)\",\n\tls: \"List directory contents\",\n\tlsp: \"Code intelligence via Language Server Protocol (go-to-definition, references, diagnostics, hover, rename, symbols)\",\n};\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. Default: process.cwd() */\n\tcwd?: string;\n\t/** Pre-loaded context files. */\n\tcontextFiles?: Array<{ path: string; content: string }>;\n\t/** Pre-loaded skills. */\n\tskills?: Skill[];\n\t/**\n\t * Optional predicate applied to the `skills` list before rendering the\n\t * <available_skills> catalog. Returning `false` omits a skill from the\n\t * prompt (the skill remains loaded and invocable by name — only the\n\t * catalog listing is suppressed).\n\t *\n\t * Intended for consumers that can narrow the relevant skill surface\n\t * (e.g. per-unit-type manifests) to reduce cached system-prompt bloat.\n\t * When omitted, all non-`disableModelInvocation` skills render — i.e.\n\t * behavior is unchanged from before this option existed.\n\t *\n\t * Contract: the predicate must be **pure and synchronous**. It may be\n\t * invoked on every system-prompt rebuild (tool-set changes and\n\t * runtime resource-loader extensions both trigger one), so any state\n\t * the closure captures should be stable across the rebuild window.\n\t * If the predicate throws, `buildSystemPrompt` logs a warning and\n\t * falls back to the unfiltered skill list — callers never see the\n\t * exception and the session stays consistent.\n\t */\n\tskillFilter?: (skill: Skill) => boolean;\n\t/**\n\t * Append a `Current date and time: <toLocaleString>` line to the system\n\t * prompt. Default: `false`.\n\t *\n\t * Provider prompt caches generally depend on stable prompt prefixes.\n\t * Embedding a per-call timestamp in the system prompt invalidates that\n\t * stability on every request, often forcing full prompt reprocessing.\n\t * Most agentic flows do not need wall-clock awareness in the system\n\t * prompt — opt in only when the consumer genuinely needs it, and inject\n\t * it via a non-cached channel (user message) when possible.\n\t */\n\tincludeDateTime?: boolean;\n}\n\n/** Build the system prompt with tools, guidelines, and context */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions = {}): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t\tskillFilter,\n\t\tincludeDateTime = false,\n\t} = options;\n\tconst resolvedCwd = toPosixPath(cwd ?? process.cwd());\n\n\t// Per-call timestamps invalidate provider prompt cache stability. Compute\n\t// lazily and only when explicitly opted in via `includeDateTime`.\n\tconst dateTimeLine = includeDateTime\n\t\t? `\\nCurrent date and time: ${new Date().toLocaleString(\"en-US\", {\n\t\t\tweekday: \"long\",\n\t\t\tyear: \"numeric\",\n\t\t\tmonth: \"long\",\n\t\t\tday: \"numeric\",\n\t\t\thour: \"2-digit\",\n\t\t\tminute: \"2-digit\",\n\t\t\tsecond: \"2-digit\",\n\t\t\ttimeZoneName: \"short\",\n\t\t})}`\n\t\t: \"\";\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skillsBase = providedSkills ?? [];\n\tlet skills = skillsBase;\n\tif (skillFilter) {\n\t\ttry {\n\t\t\tskills = skillsBase.filter(skillFilter);\n\t\t} catch (error) {\n\t\t\t// A consumer's predicate threw. Fall back to the unfiltered list so\n\t\t\t// the session stays consistent — callers (e.g. AgentSession.setTools)\n\t\t\t// must not be left with updated tools but a stale system prompt.\n\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\tconsole.warn(`buildSystemPrompt: skillFilter threw; falling back to unfiltered skills. Error: ${message}`);\n\t\t\tskills = skillsBase;\n\t\t}\n\t}\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\t// Append project context files\n\t\tif (contextFiles.length > 0) {\n\t\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t\t}\n\t\t}\n\n\t\t// Append skills section (if read or Skill tool is available)\n\t\tconst customPromptHasSkillAccess = !selectedTools || selectedTools.includes(\"read\") || selectedTools.includes(\"Skill\");\n\t\tif (customPromptHasSkillAccess && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Add date/time (only when opted in — see includeDateTime docs) and working directory last\n\t\tprompt += dateTimeLine;\n\t\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\t\t// Append promptGuidelines from extension-registered tools.\n\t\t// Without this, tools registered via pi.registerTool() with promptGuidelines\n\t\t// have their definitions reach the API but the model has no guidance on when\n\t\t// to use them (#1184).\n\t\tif (promptGuidelines && promptGuidelines.length > 0) {\n\t\t\tprompt += \"\\n\\n\";\n\t\t\tfor (const guideline of promptGuidelines) {\n\t\t\t\tprompt += guideline + \"\\n\";\n\t\t\t}\n\t\t}\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = toPosixPath(getReadmePath());\n\tconst docsPath = toPosixPath(getDocsPath());\n\tconst examplesPath = toPosixPath(getExamplesPath());\n\n\t// Build tools list based on selected tools.\n\t// Built-ins use toolDescriptions. Custom tools can provide one-line snippets.\n\tconst tools = selectedTools || [\"read\", \"bash\", \"edit\", \"write\"];\n\tconst toolsList =\n\t\ttools.length > 0\n\t\t\t? tools\n\t\t\t\t\t.map((name) => {\n\t\t\t\t\t\tconst snippet = toolSnippets?.[name] ?? toolDescriptions[name] ?? name;\n\t\t\t\t\t\treturn `- ${name}: ${snippet}`;\n\t\t\t\t\t})\n\t\t\t\t\t.join(\"\\n\")\n\t\t\t: \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = tools.includes(\"bash\");\n\tconst hasEdit = tools.includes(\"edit\");\n\tconst hasWrite = tools.includes(\"write\");\n\tconst hasGrep = tools.includes(\"grep\");\n\tconst hasFind = tools.includes(\"find\");\n\tconst hasLs = tools.includes(\"ls\");\n\tconst hasRead = tools.includes(\"read\");\n\tconst hasLsp = tools.includes(\"lsp\");\n\n\t// File exploration guidelines\n\tif (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t} else if (hasBash && (hasGrep || hasFind || hasLs)) {\n\t\taddGuideline(\"Prefer grep/find/ls tools over bash for file exploration (faster, respects .gitignore)\");\n\t}\n\n\t// Read before edit guideline\n\tif (hasRead && hasEdit) {\n\t\taddGuideline(\"Use read to examine files before editing. You must use this tool instead of cat or sed.\");\n\t}\n\n\t// Edit guideline\n\tif (hasEdit) {\n\t\taddGuideline(\"Use edit for precise changes (old text must match exactly)\");\n\t}\n\n\t// Write guideline\n\tif (hasWrite) {\n\t\taddGuideline(\"Use write only for new files or complete rewrites\");\n\t}\n\n\t// LSP guideline\n\tif (hasLsp) {\n\t\taddGuideline(\n\t\t\t`Use lsp as the primary tool for code navigation in typed codebases:\n- Navigation: definition, type_definition, implementation, references, incoming_calls, outgoing_calls\n- Understanding: hover (types + docs), signature (parameter info), symbols (file/workspace search)\n- Refactoring: rename (project-wide), code_actions (quick-fixes, imports, refactors), format (formatter)\n- Verification: diagnostics after edits to catch type errors immediately\n- Never grep for a symbol definition when lsp can resolve it semantically\n- Never shell out to a formatter when lsp format is available`,\n\t\t);\n\t}\n\n\t// Output guideline (only when actually writing or executing)\n\tif (hasEdit || hasWrite) {\n\t\taddGuideline(\n\t\t\t\"When summarizing your actions, output plain text directly - do NOT use cat or bash to display what you did\",\n\t\t);\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\t// Always include these\n\taddGuideline(\"Be concise in your responses\");\n\taddGuideline(\"Show file paths clearly when working with files\");\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\n\tlet prompt = `You are an expert coding assistant operating inside pi, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.\n\nAvailable tools:\n${toolsList}\n\nIn addition to the tools above, you may have access to other custom tools depending on the project.\n\nGuidelines:\n${guidelines}\n\nPi documentation (read only when the user asks about pi itself, its SDK, extensions, themes, skills, or TUI):\n- Main documentation: ${readmePath}\n- Additional docs: ${docsPath}\n- Examples: ${examplesPath} (extensions, custom tools, SDK)\n- When asked about: extensions (docs/extensions.md, examples/extensions/), themes (docs/themes.md), skills (docs/skills.md), prompt templates (docs/prompt-templates.md), TUI components (docs/tui.md), keybindings (docs/keybindings.md), SDK integrations (docs/sdk.md), custom providers (docs/custom-provider.md), adding models (docs/models.md), pi packages (docs/packages.md)\n- When working on pi topics, read the docs and examples, and follow .md cross-references before implementing\n- Always read pi .md files completely and follow links to related docs (e.g., tui.md for TUI API details)`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\t// Append project context files\n\tif (contextFiles.length > 0) {\n\t\tprompt += \"\\n\\n# Project Context\\n\\n\";\n\t\tprompt += \"Project-specific instructions and guidelines:\\n\\n\";\n\t\tfor (const { path: filePath, content } of contextFiles) {\n\t\t\tprompt += `## ${filePath}\\n\\n${content}\\n\\n`;\n\t\t}\n\t}\n\n\t// Append skills section (if read or Skill tool is available)\n\tconst hasSkill = tools.includes(\"Skill\");\n\tif ((hasRead || hasSkill) && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Add date/time (only when opted in — see includeDateTime docs) and working directory last\n\tprompt += dateTimeLine;\n\tprompt += `\\nCurrent working directory: ${resolvedCwd}`;\n\n\treturn prompt;\n}\n"]}
|
|
@@ -18,63 +18,29 @@
|
|
|
18
18
|
import test from "node:test";
|
|
19
19
|
import assert from "node:assert/strict";
|
|
20
20
|
import { spawn } from "node:child_process";
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
for (const candidate of candidates) {
|
|
39
|
-
if (requiredFiles.every((file) => existsSync(join(candidate, file)))) {
|
|
40
|
-
return candidate;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
throw new Error(`Unable to resolve repository root from ${__dirname}`);
|
|
44
|
-
}
|
|
45
|
-
const REPO_ROOT = findRepoRoot();
|
|
46
|
-
const SPAWN_FILES = [
|
|
47
|
-
join(REPO_ROOT, "packages/pi-coding-agent/src/core/tools/bash.ts"),
|
|
48
|
-
join(REPO_ROOT, "packages/pi-coding-agent/src/core/bash-executor.ts"),
|
|
49
|
-
join(REPO_ROOT, "packages/pi-coding-agent/src/utils/shell.ts"),
|
|
50
|
-
];
|
|
51
|
-
test("spawn calls use platform-guarded detached flag (no unconditional detached: true)", () => {
|
|
52
|
-
for (const file of SPAWN_FILES) {
|
|
53
|
-
const content = readFileSync(file, "utf-8");
|
|
54
|
-
const lines = content.split("\n");
|
|
55
|
-
for (let i = 0; i < lines.length; i++) {
|
|
56
|
-
const line = lines[i];
|
|
57
|
-
// Skip comments
|
|
58
|
-
if (line.trim().startsWith("//") || line.trim().startsWith("*"))
|
|
59
|
-
continue;
|
|
60
|
-
// Check for unconditional `detached: true`
|
|
61
|
-
if (/detached:\s*true\b/.test(line)) {
|
|
62
|
-
assert.fail(`${file}:${i + 1} has unconditional 'detached: true' — ` +
|
|
63
|
-
`must use 'detached: process.platform !== "win32"' ` +
|
|
64
|
-
`to prevent EINVAL on Windows (ConPTY / VSCode terminal)`);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
});
|
|
69
|
-
test("killProcessTree does not use detached: true for taskkill on Windows", () => {
|
|
70
|
-
const shellFile = join(REPO_ROOT, "packages/pi-coding-agent/src/utils/shell.ts");
|
|
71
|
-
const content = readFileSync(shellFile, "utf-8");
|
|
72
|
-
// Find the taskkill spawn call and ensure it doesn't have detached: true
|
|
73
|
-
const taskkillRegion = content.match(/spawn\("taskkill"[\s\S]*?\}\)/);
|
|
74
|
-
if (taskkillRegion) {
|
|
75
|
-
assert.ok(!/detached:\s*true/.test(taskkillRegion[0]), "taskkill spawn should not use detached: true — " +
|
|
76
|
-
"it can cause EINVAL on Windows and is unnecessary for a utility process");
|
|
21
|
+
import { createBashTool } from "./bash.js";
|
|
22
|
+
test("bash tool delegates command execution through operations without forcing process detachment", async () => {
|
|
23
|
+
const calls = [];
|
|
24
|
+
const tool = createBashTool(process.cwd(), {
|
|
25
|
+
operations: {
|
|
26
|
+
async exec(command, cwd, options) {
|
|
27
|
+
calls.push({ command, cwd, env: options.env });
|
|
28
|
+
options.onData(Buffer.from("ok\n"));
|
|
29
|
+
return { exitCode: 0 };
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
const result = await tool.execute("tool-call", { command: "echo ok" });
|
|
34
|
+
const firstContent = result.content[0];
|
|
35
|
+
assert.ok(firstContent);
|
|
36
|
+
if (firstContent.type !== "text") {
|
|
37
|
+
assert.fail(`Expected text content, got ${firstContent.type}`);
|
|
77
38
|
}
|
|
39
|
+
assert.equal(firstContent.text, "ok\n");
|
|
40
|
+
assert.deepEqual(calls.map((call) => ({ command: call.command, cwd: call.cwd })), [
|
|
41
|
+
{ command: "echo ok", cwd: process.cwd() },
|
|
42
|
+
]);
|
|
43
|
+
assert.ok(calls[0]?.env, "default bash context should provide an execution environment");
|
|
78
44
|
});
|
|
79
45
|
// Smoke test: spawn with platform-guarded detached flag actually works
|
|
80
46
|
test("spawn with detached: process.platform !== 'win32' succeeds", async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash-spawn-windows.test.js","sourceRoot":"","sources":["../../../src/core/tools/bash-spawn-windows.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"bash-spawn-windows.test.js","sourceRoot":"","sources":["../../../src/core/tools/bash-spawn-windows.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAE3C,IAAI,CAAC,6FAA6F,EAAE,KAAK,IAAI,EAAE;IAC9G,MAAM,KAAK,GAAqE,EAAE,CAAC;IACnF,MAAM,IAAI,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE;QAC1C,UAAU,EAAE;YACX,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,OAAO;gBAC/B,KAAK,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;gBAC/C,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;gBACpC,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;YACxB,CAAC;SACD;KACD,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;IACvE,MAAM,YAAY,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAEvC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC;IACxB,IAAI,YAAY,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;QAClC,MAAM,CAAC,IAAI,CAAC,8BAA8B,YAAY,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACxC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE;QACjF,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;KAC1C,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,8DAA8D,CAAC,CAAC;AAC1F,CAAC,CAAC,CAAC;AAEH,uEAAuE;AACvE,IAAI,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;IAC7E,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,aAAa,EAAQ,CAAC;IAEnE,MAAM,KAAK,GAAG,KAAK,CAClB,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAC3C,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EACpE;QACC,QAAQ,EAAE,OAAO,CAAC,QAAQ,KAAK,OAAO;QACtC,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC;KACjC,CACD,CAAC;IAEF,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,GAAG,MAAM,IAAI,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1B,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QAC1B,IAAI,CAAC;YACJ,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,sBAAsB,CAAC,CAAC;YAC9C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,iCAAiC,MAAM,EAAE,CAAC,CAAC;YACnF,OAAO,EAAE,CAAC;QACX,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACZ,MAAM,CAAC,CAAC,CAAC,CAAC;QACX,CAAC;IACF,CAAC,CAAC,CAAC;IAEH,MAAM,OAAO,CAAC;AACf,CAAC,CAAC,CAAC","sourcesContent":["/**\n * bash-spawn-windows.test.ts — Regression test for Windows spawn EINVAL.\n *\n * Verifies that bash tool spawn options disable `detached: true` on Windows\n * to prevent EINVAL errors in ConPTY / VSCode terminal contexts.\n *\n * Background:\n * On Windows, `spawn()` with `detached: true` sets the\n * CREATE_NEW_PROCESS_GROUP flag in CreateProcess. In certain terminal\n * contexts (VSCode integrated terminal, ConPTY, Windows Terminal) this\n * flag conflicts with the parent process group and causes a synchronous\n * EINVAL from libuv. The bg-shell extension already guards against this\n * with `detached: process.platform !== \"win32\"` (process-manager.ts);\n * this test ensures all other spawn sites are aligned.\n *\n * See: gsd-build/gsd-2#XXXX\n */\n\nimport test from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { spawn } from \"node:child_process\";\nimport { createBashTool } from \"./bash.js\";\n\ntest(\"bash tool delegates command execution through operations without forcing process detachment\", async () => {\n\tconst calls: Array<{ command: string; cwd: string; env?: NodeJS.ProcessEnv }> = [];\n\tconst tool = createBashTool(process.cwd(), {\n\t\toperations: {\n\t\t\tasync exec(command, cwd, options) {\n\t\t\t\tcalls.push({ command, cwd, env: options.env });\n\t\t\t\toptions.onData(Buffer.from(\"ok\\n\"));\n\t\t\t\treturn { exitCode: 0 };\n\t\t\t},\n\t\t},\n\t});\n\n\tconst result = await tool.execute(\"tool-call\", { command: \"echo ok\" });\n\tconst firstContent = result.content[0];\n\n\tassert.ok(firstContent);\n\tif (firstContent.type !== \"text\") {\n\t\tassert.fail(`Expected text content, got ${firstContent.type}`);\n\t}\n\tassert.equal(firstContent.text, \"ok\\n\");\n\tassert.deepEqual(calls.map((call) => ({ command: call.command, cwd: call.cwd })), [\n\t\t{ command: \"echo ok\", cwd: process.cwd() },\n\t]);\n\tassert.ok(calls[0]?.env, \"default bash context should provide an execution environment\");\n});\n\n// Smoke test: spawn with platform-guarded detached flag actually works\ntest(\"spawn with detached: process.platform !== 'win32' succeeds\", async () => {\n\tconst { promise, resolve, reject } = Promise.withResolvers<void>();\n\n\tconst child = spawn(\n\t\tprocess.platform === \"win32\" ? \"cmd\" : \"sh\",\n\t\tprocess.platform === \"win32\" ? [\"/c\", \"echo ok\"] : [\"-c\", \"echo ok\"],\n\t\t{\n\t\t\tdetached: process.platform !== \"win32\",\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t},\n\t);\n\n\tlet output = \"\";\n\tchild.stdout?.on(\"data\", (d: Buffer) => { output += d.toString(); });\n\tchild.on(\"error\", reject);\n\tchild.on(\"close\", (code) => {\n\t\ttry {\n\t\t\tassert.equal(code, 0, \"spawn should succeed\");\n\t\t\tassert.ok(output.trim().includes(\"ok\"), `Expected 'ok' in output, got: ${output}`);\n\t\t\tresolve();\n\t\t} catch (e) {\n\t\t\treject(e);\n\t\t}\n\t});\n\n\tawait promise;\n});\n"]}
|
|
@@ -27,6 +27,7 @@ declare const bashSchema: import("@sinclair/typebox").TObject<{
|
|
|
27
27
|
}>;
|
|
28
28
|
export type BashToolInput = Static<typeof bashSchema>;
|
|
29
29
|
export interface BashToolDetails {
|
|
30
|
+
cwd?: string;
|
|
30
31
|
truncation?: TruncationResult;
|
|
31
32
|
fullOutputPath?: string;
|
|
32
33
|
artifactId?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,KAAK,mBAAmB,EAAsD,MAAM,uBAAuB,CAAC;AACrH,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AACtH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AA0D9D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAyBjG;AAED,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;OAMG;IACH,IAAI,EAAE,CACL,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QACR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,KACG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1C;AA2FD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAY5E,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oGAAoG;IACpG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,sGAAsG;IACtG,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,sFAAsF;IACtF,WAAW,CAAC,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;KAC9B,CAAC;IACF,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;CACjD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAGtD,OAAO,EAAE,KAAK,mBAAmB,EAAsD,MAAM,uBAAuB,CAAC;AACrH,OAAO,EAAoD,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AACtH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AA0D9D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,MAAM,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAyBjG;AAED,QAAA,MAAM,UAAU;;;EAGd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B;;;;;;OAMG;IACH,IAAI,EAAE,CACL,OAAO,EAAE,MAAM,EACf,GAAG,EAAE,MAAM,EACX,OAAO,EAAE;QACR,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,WAAW,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACxB,KACG,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CAC1C;AA2FD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACvB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,gBAAgB,KAAK,gBAAgB,CAAC;AAY5E,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,oGAAoG;IACpG,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,sGAAsG;IACtG,eAAe,CAAC,EAAE,eAAe,CAAC;IAClC,sFAAsF;IACtF,WAAW,CAAC,EAAE;QACb,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;KAC9B,CAAC;IACF,uGAAuG;IACvG,kBAAkB,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC;CACjD;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAyMnG;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;QAAgC,CAAC"}
|
|
@@ -289,6 +289,7 @@ export function createBashTool(cwd, options) {
|
|
|
289
289
|
onUpdate({
|
|
290
290
|
content: [{ type: "text", text: truncation.content || "" }],
|
|
291
291
|
details: {
|
|
292
|
+
cwd: spawnContext.cwd,
|
|
292
293
|
truncation: truncation.truncated ? truncation : undefined,
|
|
293
294
|
fullOutputPath: spillFilePath,
|
|
294
295
|
},
|
|
@@ -313,9 +314,10 @@ export function createBashTool(cwd, options) {
|
|
|
313
314
|
const truncation = truncateTail(fullOutput);
|
|
314
315
|
let outputText = truncation.content || "(no output)";
|
|
315
316
|
// Build details with truncation info
|
|
316
|
-
let details;
|
|
317
|
+
let details = { cwd: spawnContext.cwd };
|
|
317
318
|
if (truncation.truncated) {
|
|
318
319
|
details = {
|
|
320
|
+
...details,
|
|
319
321
|
truncation,
|
|
320
322
|
fullOutputPath: spillFilePath,
|
|
321
323
|
...(spillArtifactId ? { artifactId: spillArtifactId } : {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { createWriteStream, existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@gsd/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { spawn } from \"child_process\";\nimport { getShellConfig, getShellEnv, killProcessTree, sanitizeCommand } from \"../../utils/shell.js\";\nimport { type BashInterceptorRule, compileInterceptor, DEFAULT_BASH_INTERCEPTOR_RULES } from \"./bash-interceptor.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateTail } from \"./truncate.js\";\nimport type { ArtifactManager } from \"../artifact-manager.js\";\n\n// Cached Win32 FFI handles for restoring VT input after child processes\nlet _vtHandles: { GetConsoleMode: any; SetConsoleMode: any; handle: any } | null = null;\nfunction restoreWindowsVTInput(): void {\n\tif (process.platform !== \"win32\") return;\n\ttry {\n\t\tif (!_vtHandles) {\n\t\t\tconst cjsRequire = createRequire(import.meta.url);\n\t\t\tconst koffi = cjsRequire(\"koffi\");\n\t\t\tconst k32 = koffi.load(\"kernel32.dll\");\n\t\t\tconst GetStdHandle = k32.func(\"void* __stdcall GetStdHandle(int)\");\n\t\t\tconst GetConsoleMode = k32.func(\"bool __stdcall GetConsoleMode(void*, _Out_ uint32_t*)\");\n\t\t\tconst SetConsoleMode = k32.func(\"bool __stdcall SetConsoleMode(void*, uint32_t)\");\n\t\t\tconst handle = GetStdHandle(-10);\n\t\t\t_vtHandles = { GetConsoleMode, SetConsoleMode, handle };\n\t\t}\n\t\tconst ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;\n\t\tconst mode = new Uint32Array(1);\n\t\t_vtHandles.GetConsoleMode(_vtHandles.handle, mode);\n\t\tif (!(mode[0]! & ENABLE_VIRTUAL_TERMINAL_INPUT)) {\n\t\t\t_vtHandles.SetConsoleMode(_vtHandles.handle, mode[0]! | ENABLE_VIRTUAL_TERMINAL_INPUT);\n\t\t}\n\t} catch { /* koffi not available */ }\n}\n\n/**\n * Generate a unique temp file path for bash output\n */\nfunction getTempFilePath(): string {\n\tconst id = randomBytes(8).toString(\"hex\");\n\treturn join(tmpdir(), `pi-bash-${id}.log`);\n}\n\n/**\n * Detect whether a command fragment ends with an unquoted & (background operator).\n * Returns true for patterns like: `cmd &`, `cmd arg &`, `cmd & disown`, `(cmd) &`.\n * Returns false when & appears inside a string literal or as &&.\n */\nfunction endsWithBackgroundOperator(fragment: string): boolean {\n\t// Remove content inside single-quoted strings to avoid false positives\n\tconst stripped = fragment.replace(/'[^']*'/g, \"''\");\n\t// Match trailing & not preceded by another & (i.e., not &&)\n\treturn /(?<!&)&\\s*(?:disown\\s*)?(?:#.*)?$/.test(stripped.trim());\n}\n\n/**\n * Determine whether a command segment already redirects stdout away from the terminal.\n * Checks for >, >>, &>, |, /dev/null redirects.\n */\nfunction hasOutputRedirect(segment: string): boolean {\n\t// Remove single-quoted strings to avoid matching inside them\n\tconst stripped = segment.replace(/'[^']*'/g, \"''\");\n\t// Match >, >> not preceded by 2 (stderr-only) — we only care about stdout\n\t// Also match &> (combined), >&, or a pipe | which routes stdout elsewhere\n\treturn /(?<!\\d)(?:>>?|&>|>&|\\|)/.test(stripped);\n}\n\n/**\n * Rewrite a command that uses & for backgrounding so the background process\n * does not inherit the bash tool's stdout/stderr pipes.\n *\n * Without this, `python -m http.server 8080 &` causes the bash tool to hang\n * indefinitely because Node.js keeps the pipe open until every process that\n * inherited it exits — including the long-running server.\n *\n * The rewrite adds `>/dev/null 2>&1` before each & where stdout is not already\n * redirected, ensuring the background process detaches from the pipes while\n * still producing a human-readable notice in the tool output.\n *\n * Returns { command: string; rewritten: boolean }.\n */\nexport function rewriteBackgroundCommand(command: string): { command: string; rewritten: boolean } {\n\t// Quick pre-check: if there's no & at all, skip the more expensive processing\n\tif (!command.includes(\"&\")) return { command, rewritten: false };\n\n\t// Split on ; and newlines to handle compound commands.\n\t// We rewrite each segment independently.\n\t// Note: this is intentionally simple and covers the common LLM patterns.\n\t// It does not attempt to parse complex nested subshells.\n\tconst segments = command.split(/(?<=[;\\n])/);\n\tlet anyRewritten = false;\n\n\tconst rewrittenSegments = segments.map((segment) => {\n\t\tif (!endsWithBackgroundOperator(segment)) return segment;\n\t\tif (hasOutputRedirect(segment)) return segment;\n\n\t\tanyRewritten = true;\n\t\t// Insert >/dev/null 2>&1 before the trailing & (and optional disown/comment)\n\t\treturn segment.replace(\n\t\t\t/(?<!&)(&\\s*(?:disown\\s*)?(?:#.*)?)$/,\n\t\t\t\">/dev/null 2>&1 $1\",\n\t\t);\n\t});\n\n\tif (!anyRewritten) return { command, rewritten: false };\n\treturn { command: rewrittenSegments.join(\"\"), rewritten: true };\n}\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\tartifactId?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (e.g., SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command - The command to execute\n\t * @param cwd - Working directory\n\t * @param options - Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Default bash operations using local shell\n */\nconst defaultBashOperations: BashOperations = {\n\texec: (command, cwd, { onData, signal, timeout, env }) => {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst { shell, args } = getShellConfig();\n\n\t\t\tif (!existsSync(cwd)) {\n\t\t\t\treject(new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// On Windows, detached: true sets CREATE_NEW_PROCESS_GROUP which can\n\t\t\t// cause EINVAL in VSCode/ConPTY terminal contexts. The bg-shell\n\t\t\t// extension already guards this (process-manager.ts); align here.\n\t\t\t// Process-tree cleanup uses taskkill /F /T on Windows regardless.\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t});\n\n\t\t\tlet timedOut = false;\n\n\t\t\t// Set timeout if provided\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tif (child.pid) {\n\t\t\t\t\t\tkillProcessTree(child.pid);\n\t\t\t\t\t}\n\t\t\t\t}, timeout * 1000);\n\t\t\t}\n\n\t\t\t// Stream stdout and stderr\n\t\t\tif (child.stdout) {\n\t\t\t\tchild.stdout.on(\"data\", onData);\n\t\t\t}\n\t\t\tif (child.stderr) {\n\t\t\t\tchild.stderr.on(\"data\", onData);\n\t\t\t}\n\n\t\t\t// Handle shell spawn errors\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\t// Handle abort signal - kill entire process tree\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) {\n\t\t\t\t\tkillProcessTree(child.pid);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (signal) {\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\tonAbort();\n\t\t\t\t} else {\n\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle process exit\n\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\trestoreWindowsVTInput();\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (timedOut) {\n\t\t\t\t\treject(new Error(`timeout:${timeout}`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tresolve({ exitCode: code });\n\t\t\t});\n\t\t});\n\t},\n};\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = {\n\t\tcommand,\n\t\tcwd,\n\t\tenv: { ...getShellEnv() },\n\t};\n\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (e.g., \"shopt -s expand_aliases\" for alias support) */\n\tcommandPrefix?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/** Session-scoped artifact storage. When provided, spills to artifact files instead of temp files. */\n\tartifactManager?: ArtifactManager;\n\t/** Bash interceptor configuration — blocks commands that duplicate dedicated tools */\n\tinterceptor?: {\n\t\tenabled: boolean;\n\t\trules?: BashInterceptorRule[];\n\t};\n\t/** Tool names available in the session, used by the interceptor to check if replacement tools exist */\n\tavailableToolNames?: string[] | (() => string[]);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst ops = options?.operations ?? defaultBashOperations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst artifactManager = options?.artifactManager;\n\n\t// Pre-compile interceptor rules once at construction time\n\tconst interceptorInstance =\n\t\toptions?.interceptor?.enabled\n\t\t\t? compileInterceptor(options.interceptor.rules ?? DEFAULT_BASH_INTERCEPTOR_RULES)\n\t\t\t: null;\n\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tparameters: bashSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t) => {\n\t\t\t// Check bash interceptor — block commands that duplicate dedicated tools\n\t\t\tif (interceptorInstance) {\n\t\t\t\tconst toolNames =\n\t\t\t\t\ttypeof options!.availableToolNames === \"function\"\n\t\t\t\t\t\t? options!.availableToolNames()\n\t\t\t\t\t\t: options!.availableToolNames ?? [];\n\t\t\t\tconst interception = interceptorInstance.check(command, toolNames);\n\t\t\t\tif (interception.block) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: interception.message ?? \"Command blocked by interceptor\" }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Rewrite background commands (&) to redirect output away from the pipes.\n\t\t\t// Without this, `cmd &` causes the tool to hang because the background\n\t\t\t// process inherits the piped stdout/stderr and keeps them open indefinitely.\n\t\t\tconst bgResult = rewriteBackgroundCommand(command);\n\t\t\tconst effectiveCommand = bgResult.command;\n\t\t\tif (bgResult.rewritten) {\n\t\t\t\t// Surface a brief advisory so the LLM knows what happened.\n\t\t\t\t// The rewrite is transparent for the common case; explicit detachment\n\t\t\t\t// (nohup, start_new_session) is preferred for robustness.\n\t\t\t\tonUpdate?.({\n\t\t\t\t\tcontent: [{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: \"Note: Background command output redirected to /dev/null to prevent pipe hang. Use nohup or setsid for reliable detachment.\",\n\t\t\t\t\t}],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Apply command prefix if configured (e.g., \"shopt -s expand_aliases\" for alias support)\n\t\t\tconst resolvedCommand = sanitizeCommand(commandPrefix ? `${commandPrefix}\\n${effectiveCommand}` : effectiveCommand);\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// We'll stream to a file if output gets large\n\t\t\t\tlet spillFilePath: string | undefined;\n\t\t\t\tlet spillArtifactId: string | undefined;\n\t\t\t\tlet spillFileStream: ReturnType<typeof createWriteStream> | undefined;\n\t\t\t\tlet totalBytes = 0;\n\n\t\t\t\t// Keep a rolling buffer of the last chunk for tail truncation\n\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\tlet chunksBytes = 0;\n\t\t\t\t// Keep more than we need so we have enough for truncation\n\t\t\t\tconst maxChunksBytes = DEFAULT_MAX_BYTES * 2;\n\n\t\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\t\ttotalBytes += data.length;\n\n\t\t\t\t\t// Start writing to file once we exceed the threshold\n\t\t\t\t\tif (totalBytes > DEFAULT_MAX_BYTES && !spillFilePath) {\n\t\t\t\t\t\tif (artifactManager) {\n\t\t\t\t\t\t\tconst allocated = artifactManager.allocatePath(\"bash\");\n\t\t\t\t\t\t\tspillFilePath = allocated.path;\n\t\t\t\t\t\t\tspillArtifactId = allocated.id;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tspillFilePath = getTempFilePath();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tspillFileStream = createWriteStream(spillFilePath);\n\t\t\t\t\t\t// Write all buffered chunks to the file\n\t\t\t\t\t\tfor (const chunk of chunks) {\n\t\t\t\t\t\t\tspillFileStream.write(chunk);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Write to temp file if we have one\n\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\tspillFileStream.write(data);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Keep rolling buffer of recent data\n\t\t\t\t\tchunks.push(data);\n\t\t\t\t\tchunksBytes += data.length;\n\n\t\t\t\t\t// Trim old chunks if buffer is too large\n\t\t\t\t\twhile (chunksBytes > maxChunksBytes && chunks.length > 1) {\n\t\t\t\t\t\tconst removed = chunks.shift()!;\n\t\t\t\t\t\tchunksBytes -= removed.length;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Stream partial output to callback (truncated rolling buffer)\n\t\t\t\t\tif (onUpdate) {\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tconst fullText = fullBuffer.toString(\"utf-8\");\n\t\t\t\t\t\tconst truncation = truncateTail(fullText);\n\t\t\t\t\t\tonUpdate({\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: truncation.content || \"\" }],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\ttruncation: truncation.truncated ? truncation : undefined,\n\t\t\t\t\t\t\t\tfullOutputPath: spillFilePath,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\tonData: handleData,\n\t\t\t\t\tsignal,\n\t\t\t\t\ttimeout,\n\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t})\n\t\t\t\t\t.then(({ exitCode }) => {\n\t\t\t\t\t\t// Close temp file stream\n\t\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\t\tspillFileStream.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Combine all buffered chunks\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tconst fullOutput = fullBuffer.toString(\"utf-8\");\n\n\t\t\t\t\t\t// Apply tail truncation\n\t\t\t\t\t\tconst truncation = truncateTail(fullOutput);\n\t\t\t\t\t\tlet outputText = truncation.content || \"(no output)\";\n\n\t\t\t\t\t\t// Build details with truncation info\n\t\t\t\t\t\tlet details: BashToolDetails | undefined;\n\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tdetails = {\n\t\t\t\t\t\t\t\ttruncation,\n\t\t\t\t\t\t\t\tfullOutputPath: spillFilePath,\n\t\t\t\t\t\t\t\t...(spillArtifactId ? { artifactId: spillArtifactId } : {}),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Build actionable notice\n\t\t\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\t\t\tconst outputRef = spillArtifactId ? `artifact://${spillArtifactId}` : spillFilePath;\n\n\t\t\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\t\t\tconst lastLineSize = formatSize(Buffer.byteLength(fullOutput.split(\"\\n\").pop() || \"\", \"utf-8\"));\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\t\t\toutputText += `\\n\\nCommand exited with code ${exitCode}`;\n\t\t\t\t\t\t\treject(new Error(outputText));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: outputText }], details });\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err: Error) => {\n\t\t\t\t\t\t// Close temp file stream\n\t\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\t\tspillFileStream.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Combine all buffered chunks for error output\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tlet output = fullBuffer.toString(\"utf-8\");\n\n\t\t\t\t\t\tif (err.message === \"aborted\") {\n\t\t\t\t\t\t\tif (output) output += \"\\n\\n\";\n\t\t\t\t\t\t\toutput += \"Command aborted\";\n\t\t\t\t\t\t\treject(new Error(output));\n\t\t\t\t\t\t} else if (err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\t\tif (output) output += \"\\n\\n\";\n\t\t\t\t\t\t\toutput += `Command timed out after ${timeoutSecs} seconds`;\n\t\t\t\t\t\t\treject(new Error(output));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treject(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default bash tool using process.cwd() - for backwards compatibility */\nexport const bashTool = createBashTool(process.cwd());\n"]}
|
|
1
|
+
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../src/core/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { createWriteStream, existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@gsd/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { spawn } from \"child_process\";\nimport { getShellConfig, getShellEnv, killProcessTree, sanitizeCommand } from \"../../utils/shell.js\";\nimport { type BashInterceptorRule, compileInterceptor, DEFAULT_BASH_INTERCEPTOR_RULES } from \"./bash-interceptor.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateTail } from \"./truncate.js\";\nimport type { ArtifactManager } from \"../artifact-manager.js\";\n\n// Cached Win32 FFI handles for restoring VT input after child processes\nlet _vtHandles: { GetConsoleMode: any; SetConsoleMode: any; handle: any } | null = null;\nfunction restoreWindowsVTInput(): void {\n\tif (process.platform !== \"win32\") return;\n\ttry {\n\t\tif (!_vtHandles) {\n\t\t\tconst cjsRequire = createRequire(import.meta.url);\n\t\t\tconst koffi = cjsRequire(\"koffi\");\n\t\t\tconst k32 = koffi.load(\"kernel32.dll\");\n\t\t\tconst GetStdHandle = k32.func(\"void* __stdcall GetStdHandle(int)\");\n\t\t\tconst GetConsoleMode = k32.func(\"bool __stdcall GetConsoleMode(void*, _Out_ uint32_t*)\");\n\t\t\tconst SetConsoleMode = k32.func(\"bool __stdcall SetConsoleMode(void*, uint32_t)\");\n\t\t\tconst handle = GetStdHandle(-10);\n\t\t\t_vtHandles = { GetConsoleMode, SetConsoleMode, handle };\n\t\t}\n\t\tconst ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;\n\t\tconst mode = new Uint32Array(1);\n\t\t_vtHandles.GetConsoleMode(_vtHandles.handle, mode);\n\t\tif (!(mode[0]! & ENABLE_VIRTUAL_TERMINAL_INPUT)) {\n\t\t\t_vtHandles.SetConsoleMode(_vtHandles.handle, mode[0]! | ENABLE_VIRTUAL_TERMINAL_INPUT);\n\t\t}\n\t} catch { /* koffi not available */ }\n}\n\n/**\n * Generate a unique temp file path for bash output\n */\nfunction getTempFilePath(): string {\n\tconst id = randomBytes(8).toString(\"hex\");\n\treturn join(tmpdir(), `pi-bash-${id}.log`);\n}\n\n/**\n * Detect whether a command fragment ends with an unquoted & (background operator).\n * Returns true for patterns like: `cmd &`, `cmd arg &`, `cmd & disown`, `(cmd) &`.\n * Returns false when & appears inside a string literal or as &&.\n */\nfunction endsWithBackgroundOperator(fragment: string): boolean {\n\t// Remove content inside single-quoted strings to avoid false positives\n\tconst stripped = fragment.replace(/'[^']*'/g, \"''\");\n\t// Match trailing & not preceded by another & (i.e., not &&)\n\treturn /(?<!&)&\\s*(?:disown\\s*)?(?:#.*)?$/.test(stripped.trim());\n}\n\n/**\n * Determine whether a command segment already redirects stdout away from the terminal.\n * Checks for >, >>, &>, |, /dev/null redirects.\n */\nfunction hasOutputRedirect(segment: string): boolean {\n\t// Remove single-quoted strings to avoid matching inside them\n\tconst stripped = segment.replace(/'[^']*'/g, \"''\");\n\t// Match >, >> not preceded by 2 (stderr-only) — we only care about stdout\n\t// Also match &> (combined), >&, or a pipe | which routes stdout elsewhere\n\treturn /(?<!\\d)(?:>>?|&>|>&|\\|)/.test(stripped);\n}\n\n/**\n * Rewrite a command that uses & for backgrounding so the background process\n * does not inherit the bash tool's stdout/stderr pipes.\n *\n * Without this, `python -m http.server 8080 &` causes the bash tool to hang\n * indefinitely because Node.js keeps the pipe open until every process that\n * inherited it exits — including the long-running server.\n *\n * The rewrite adds `>/dev/null 2>&1` before each & where stdout is not already\n * redirected, ensuring the background process detaches from the pipes while\n * still producing a human-readable notice in the tool output.\n *\n * Returns { command: string; rewritten: boolean }.\n */\nexport function rewriteBackgroundCommand(command: string): { command: string; rewritten: boolean } {\n\t// Quick pre-check: if there's no & at all, skip the more expensive processing\n\tif (!command.includes(\"&\")) return { command, rewritten: false };\n\n\t// Split on ; and newlines to handle compound commands.\n\t// We rewrite each segment independently.\n\t// Note: this is intentionally simple and covers the common LLM patterns.\n\t// It does not attempt to parse complex nested subshells.\n\tconst segments = command.split(/(?<=[;\\n])/);\n\tlet anyRewritten = false;\n\n\tconst rewrittenSegments = segments.map((segment) => {\n\t\tif (!endsWithBackgroundOperator(segment)) return segment;\n\t\tif (hasOutputRedirect(segment)) return segment;\n\n\t\tanyRewritten = true;\n\t\t// Insert >/dev/null 2>&1 before the trailing & (and optional disown/comment)\n\t\treturn segment.replace(\n\t\t\t/(?<!&)(&\\s*(?:disown\\s*)?(?:#.*)?)$/,\n\t\t\t\">/dev/null 2>&1 $1\",\n\t\t);\n\t});\n\n\tif (!anyRewritten) return { command, rewritten: false };\n\treturn { command: rewrittenSegments.join(\"\"), rewritten: true };\n}\n\nconst bashSchema = Type.Object({\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\nexport type BashToolInput = Static<typeof bashSchema>;\n\nexport interface BashToolDetails {\n\tcwd?: string;\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n\tartifactId?: string;\n}\n\n/**\n * Pluggable operations for the bash tool.\n * Override these to delegate command execution to remote systems (e.g., SSH).\n */\nexport interface BashOperations {\n\t/**\n\t * Execute a command and stream output.\n\t * @param command - The command to execute\n\t * @param cwd - Working directory\n\t * @param options - Execution options\n\t * @returns Promise resolving to exit code (null if killed)\n\t */\n\texec: (\n\t\tcommand: string,\n\t\tcwd: string,\n\t\toptions: {\n\t\t\tonData: (data: Buffer) => void;\n\t\t\tsignal?: AbortSignal;\n\t\t\ttimeout?: number;\n\t\t\tenv?: NodeJS.ProcessEnv;\n\t\t},\n\t) => Promise<{ exitCode: number | null }>;\n}\n\n/**\n * Default bash operations using local shell\n */\nconst defaultBashOperations: BashOperations = {\n\texec: (command, cwd, { onData, signal, timeout, env }) => {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst { shell, args } = getShellConfig();\n\n\t\t\tif (!existsSync(cwd)) {\n\t\t\t\treject(new Error(`Working directory does not exist: ${cwd}\\nCannot execute bash commands.`));\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// On Windows, detached: true sets CREATE_NEW_PROCESS_GROUP which can\n\t\t\t// cause EINVAL in VSCode/ConPTY terminal contexts. The bg-shell\n\t\t\t// extension already guards this (process-manager.ts); align here.\n\t\t\t// Process-tree cleanup uses taskkill /F /T on Windows regardless.\n\t\t\tconst child = spawn(shell, [...args, command], {\n\t\t\t\tcwd,\n\t\t\t\tdetached: process.platform !== \"win32\",\n\t\t\t\tenv: env ?? getShellEnv(),\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t\t});\n\n\t\t\tlet timedOut = false;\n\n\t\t\t// Set timeout if provided\n\t\t\tlet timeoutHandle: NodeJS.Timeout | undefined;\n\t\t\tif (timeout !== undefined && timeout > 0) {\n\t\t\t\ttimeoutHandle = setTimeout(() => {\n\t\t\t\t\ttimedOut = true;\n\t\t\t\t\tif (child.pid) {\n\t\t\t\t\t\tkillProcessTree(child.pid);\n\t\t\t\t\t}\n\t\t\t\t}, timeout * 1000);\n\t\t\t}\n\n\t\t\t// Stream stdout and stderr\n\t\t\tif (child.stdout) {\n\t\t\t\tchild.stdout.on(\"data\", onData);\n\t\t\t}\n\t\t\tif (child.stderr) {\n\t\t\t\tchild.stderr.on(\"data\", onData);\n\t\t\t}\n\n\t\t\t// Handle shell spawn errors\n\t\t\tchild.on(\"error\", (err) => {\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(err);\n\t\t\t});\n\n\t\t\t// Handle abort signal - kill entire process tree\n\t\t\tconst onAbort = () => {\n\t\t\t\tif (child.pid) {\n\t\t\t\t\tkillProcessTree(child.pid);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tif (signal) {\n\t\t\t\tif (signal.aborted) {\n\t\t\t\t\tonAbort();\n\t\t\t\t} else {\n\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Handle process exit\n\t\t\tchild.on(\"close\", (code) => {\n\t\t\t\trestoreWindowsVTInput();\n\t\t\t\tif (timeoutHandle) clearTimeout(timeoutHandle);\n\t\t\t\tif (signal) signal.removeEventListener(\"abort\", onAbort);\n\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif (timedOut) {\n\t\t\t\t\treject(new Error(`timeout:${timeout}`));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tresolve({ exitCode: code });\n\t\t\t});\n\t\t});\n\t},\n};\n\nexport interface BashSpawnContext {\n\tcommand: string;\n\tcwd: string;\n\tenv: NodeJS.ProcessEnv;\n}\n\nexport type BashSpawnHook = (context: BashSpawnContext) => BashSpawnContext;\n\nfunction resolveSpawnContext(command: string, cwd: string, spawnHook?: BashSpawnHook): BashSpawnContext {\n\tconst baseContext: BashSpawnContext = {\n\t\tcommand,\n\t\tcwd,\n\t\tenv: { ...getShellEnv() },\n\t};\n\n\treturn spawnHook ? spawnHook(baseContext) : baseContext;\n}\n\nexport interface BashToolOptions {\n\t/** Custom operations for command execution. Default: local shell */\n\toperations?: BashOperations;\n\t/** Command prefix prepended to every command (e.g., \"shopt -s expand_aliases\" for alias support) */\n\tcommandPrefix?: string;\n\t/** Hook to adjust command, cwd, or env before execution */\n\tspawnHook?: BashSpawnHook;\n\t/** Session-scoped artifact storage. When provided, spills to artifact files instead of temp files. */\n\tartifactManager?: ArtifactManager;\n\t/** Bash interceptor configuration — blocks commands that duplicate dedicated tools */\n\tinterceptor?: {\n\t\tenabled: boolean;\n\t\trules?: BashInterceptorRule[];\n\t};\n\t/** Tool names available in the session, used by the interceptor to check if replacement tools exist */\n\tavailableToolNames?: string[] | (() => string[]);\n}\n\nexport function createBashTool(cwd: string, options?: BashToolOptions): AgentTool<typeof bashSchema> {\n\tconst ops = options?.operations ?? defaultBashOperations;\n\tconst commandPrefix = options?.commandPrefix;\n\tconst spawnHook = options?.spawnHook;\n\tconst artifactManager = options?.artifactManager;\n\n\t// Pre-compile interceptor rules once at construction time\n\tconst interceptorInstance =\n\t\toptions?.interceptor?.enabled\n\t\t\t? compileInterceptor(options.interceptor.rules ?? DEFAULT_BASH_INTERCEPTOR_RULES)\n\t\t\t: null;\n\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tparameters: bashSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ command, timeout }: { command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t\tonUpdate?,\n\t\t) => {\n\t\t\t// Check bash interceptor — block commands that duplicate dedicated tools\n\t\t\tif (interceptorInstance) {\n\t\t\t\tconst toolNames =\n\t\t\t\t\ttypeof options!.availableToolNames === \"function\"\n\t\t\t\t\t\t? options!.availableToolNames()\n\t\t\t\t\t\t: options!.availableToolNames ?? [];\n\t\t\t\tconst interception = interceptorInstance.check(command, toolNames);\n\t\t\t\tif (interception.block) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tcontent: [{ type: \"text\" as const, text: interception.message ?? \"Command blocked by interceptor\" }],\n\t\t\t\t\t\tdetails: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Rewrite background commands (&) to redirect output away from the pipes.\n\t\t\t// Without this, `cmd &` causes the tool to hang because the background\n\t\t\t// process inherits the piped stdout/stderr and keeps them open indefinitely.\n\t\t\tconst bgResult = rewriteBackgroundCommand(command);\n\t\t\tconst effectiveCommand = bgResult.command;\n\t\t\tif (bgResult.rewritten) {\n\t\t\t\t// Surface a brief advisory so the LLM knows what happened.\n\t\t\t\t// The rewrite is transparent for the common case; explicit detachment\n\t\t\t\t// (nohup, start_new_session) is preferred for robustness.\n\t\t\t\tonUpdate?.({\n\t\t\t\t\tcontent: [{\n\t\t\t\t\t\ttype: \"text\" as const,\n\t\t\t\t\t\ttext: \"Note: Background command output redirected to /dev/null to prevent pipe hang. Use nohup or setsid for reliable detachment.\",\n\t\t\t\t\t}],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t});\n\t\t\t}\n\t\t\t// Apply command prefix if configured (e.g., \"shopt -s expand_aliases\" for alias support)\n\t\t\tconst resolvedCommand = sanitizeCommand(commandPrefix ? `${commandPrefix}\\n${effectiveCommand}` : effectiveCommand);\n\t\t\tconst spawnContext = resolveSpawnContext(resolvedCommand, cwd, spawnHook);\n\n\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t// We'll stream to a file if output gets large\n\t\t\t\tlet spillFilePath: string | undefined;\n\t\t\t\tlet spillArtifactId: string | undefined;\n\t\t\t\tlet spillFileStream: ReturnType<typeof createWriteStream> | undefined;\n\t\t\t\tlet totalBytes = 0;\n\n\t\t\t\t// Keep a rolling buffer of the last chunk for tail truncation\n\t\t\t\tconst chunks: Buffer[] = [];\n\t\t\t\tlet chunksBytes = 0;\n\t\t\t\t// Keep more than we need so we have enough for truncation\n\t\t\t\tconst maxChunksBytes = DEFAULT_MAX_BYTES * 2;\n\n\t\t\t\tconst handleData = (data: Buffer) => {\n\t\t\t\t\ttotalBytes += data.length;\n\n\t\t\t\t\t// Start writing to file once we exceed the threshold\n\t\t\t\t\tif (totalBytes > DEFAULT_MAX_BYTES && !spillFilePath) {\n\t\t\t\t\t\tif (artifactManager) {\n\t\t\t\t\t\t\tconst allocated = artifactManager.allocatePath(\"bash\");\n\t\t\t\t\t\t\tspillFilePath = allocated.path;\n\t\t\t\t\t\t\tspillArtifactId = allocated.id;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tspillFilePath = getTempFilePath();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tspillFileStream = createWriteStream(spillFilePath);\n\t\t\t\t\t\t// Write all buffered chunks to the file\n\t\t\t\t\t\tfor (const chunk of chunks) {\n\t\t\t\t\t\t\tspillFileStream.write(chunk);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Write to temp file if we have one\n\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\tspillFileStream.write(data);\n\t\t\t\t\t}\n\n\t\t\t\t\t// Keep rolling buffer of recent data\n\t\t\t\t\tchunks.push(data);\n\t\t\t\t\tchunksBytes += data.length;\n\n\t\t\t\t\t// Trim old chunks if buffer is too large\n\t\t\t\t\twhile (chunksBytes > maxChunksBytes && chunks.length > 1) {\n\t\t\t\t\t\tconst removed = chunks.shift()!;\n\t\t\t\t\t\tchunksBytes -= removed.length;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Stream partial output to callback (truncated rolling buffer)\n\t\t\t\t\tif (onUpdate) {\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tconst fullText = fullBuffer.toString(\"utf-8\");\n\t\t\t\t\t\tconst truncation = truncateTail(fullText);\n\t\t\t\t\t\tonUpdate({\n\t\t\t\t\t\t\tcontent: [{ type: \"text\", text: truncation.content || \"\" }],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tcwd: spawnContext.cwd,\n\t\t\t\t\t\t\t\ttruncation: truncation.truncated ? truncation : undefined,\n\t\t\t\t\t\t\t\tfullOutputPath: spillFilePath,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tops.exec(spawnContext.command, spawnContext.cwd, {\n\t\t\t\t\tonData: handleData,\n\t\t\t\t\tsignal,\n\t\t\t\t\ttimeout,\n\t\t\t\t\tenv: spawnContext.env,\n\t\t\t\t})\n\t\t\t\t\t.then(({ exitCode }) => {\n\t\t\t\t\t\t// Close temp file stream\n\t\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\t\tspillFileStream.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Combine all buffered chunks\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tconst fullOutput = fullBuffer.toString(\"utf-8\");\n\n\t\t\t\t\t\t// Apply tail truncation\n\t\t\t\t\t\tconst truncation = truncateTail(fullOutput);\n\t\t\t\t\t\tlet outputText = truncation.content || \"(no output)\";\n\n\t\t\t\t\t\t// Build details with truncation info\n\t\t\t\t\t\tlet details: BashToolDetails | undefined = { cwd: spawnContext.cwd };\n\n\t\t\t\t\t\tif (truncation.truncated) {\n\t\t\t\t\t\t\tdetails = {\n\t\t\t\t\t\t\t\t...details,\n\t\t\t\t\t\t\t\ttruncation,\n\t\t\t\t\t\t\t\tfullOutputPath: spillFilePath,\n\t\t\t\t\t\t\t\t...(spillArtifactId ? { artifactId: spillArtifactId } : {}),\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// Build actionable notice\n\t\t\t\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\t\t\t\tconst endLine = truncation.totalLines;\n\t\t\t\t\t\t\tconst outputRef = spillArtifactId ? `artifact://${spillArtifactId}` : spillFilePath;\n\n\t\t\t\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t\t\t\tconst lastLineSize = formatSize(Buffer.byteLength(fullOutput.split(\"\\n\").pop() || \"\", \"utf-8\"));\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${outputRef}]`;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (exitCode !== 0 && exitCode !== null) {\n\t\t\t\t\t\t\toutputText += `\\n\\nCommand exited with code ${exitCode}`;\n\t\t\t\t\t\t\treject(new Error(outputText));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve({ content: [{ type: \"text\", text: outputText }], details });\n\t\t\t\t\t\t}\n\t\t\t\t\t})\n\t\t\t\t\t.catch((err: Error) => {\n\t\t\t\t\t\t// Close temp file stream\n\t\t\t\t\t\tif (spillFileStream) {\n\t\t\t\t\t\t\tspillFileStream.end();\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Combine all buffered chunks for error output\n\t\t\t\t\t\tconst fullBuffer = Buffer.concat(chunks);\n\t\t\t\t\t\tlet output = fullBuffer.toString(\"utf-8\");\n\n\t\t\t\t\t\tif (err.message === \"aborted\") {\n\t\t\t\t\t\t\tif (output) output += \"\\n\\n\";\n\t\t\t\t\t\t\toutput += \"Command aborted\";\n\t\t\t\t\t\t\treject(new Error(output));\n\t\t\t\t\t\t} else if (err.message.startsWith(\"timeout:\")) {\n\t\t\t\t\t\t\tconst timeoutSecs = err.message.split(\":\")[1];\n\t\t\t\t\t\t\tif (output) output += \"\\n\\n\";\n\t\t\t\t\t\t\toutput += `Command timed out after ${timeoutSecs} seconds`;\n\t\t\t\t\t\t\treject(new Error(output));\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\treject(err);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default bash tool using process.cwd() - for backwards compatibility */\nexport const bashTool = createBashTool(process.cwd());\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentTool } from "@gsd/pi-agent-core";
|
|
2
2
|
import { type Static } from "@sinclair/typebox";
|
|
3
|
+
import { type ToolTargetMetadata } from "./tool-target.js";
|
|
3
4
|
declare const editSchema: import("@sinclair/typebox").TObject<{
|
|
4
5
|
path: import("@sinclair/typebox").TString;
|
|
5
6
|
oldText: import("@sinclair/typebox").TString;
|
|
@@ -11,6 +12,7 @@ export interface EditToolDetails {
|
|
|
11
12
|
diff: string;
|
|
12
13
|
/** Line number of the first change in the new file (for editor navigation) */
|
|
13
14
|
firstChangedLine?: number;
|
|
15
|
+
target?: ToolTargetMetadata;
|
|
14
16
|
}
|
|
15
17
|
/**
|
|
16
18
|
* Pluggable operations for the edit tool.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AActD,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE7E,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAEtD,MAAM,WAAW,eAAe;IAC/B,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,kBAAkB,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,qCAAqC;IACrC,QAAQ,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACpD,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,4DAA4D;IAC5D,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAQD,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAqLnG;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;;QAAgC,CAAC"}
|
|
@@ -4,6 +4,7 @@ import { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile }
|
|
|
4
4
|
import { detectLineEnding, fuzzyFindText, generateDiffString, normalizeForFuzzyMatch, normalizeToLF, restoreLineEndings, stripBom, } from "./edit-diff.js";
|
|
5
5
|
import { notifyFileChanged } from "../lsp/client.js";
|
|
6
6
|
import { resolveToCwd } from "./path-utils.js";
|
|
7
|
+
import { createToolTarget } from "./tool-target.js";
|
|
7
8
|
const editSchema = Type.Object({
|
|
8
9
|
path: Type.String({ description: "Path to the file to edit (relative or absolute)" }),
|
|
9
10
|
oldText: Type.String({ description: "Exact text to find and replace (must match exactly)" }),
|
|
@@ -129,7 +130,17 @@ export function createEditTool(cwd, options) {
|
|
|
129
130
|
text: `Successfully replaced text in ${path}.`,
|
|
130
131
|
},
|
|
131
132
|
],
|
|
132
|
-
details: {
|
|
133
|
+
details: {
|
|
134
|
+
diff: diffResult.diff,
|
|
135
|
+
firstChangedLine: diffResult.firstChangedLine,
|
|
136
|
+
target: createToolTarget({
|
|
137
|
+
kind: "file",
|
|
138
|
+
action: "edit",
|
|
139
|
+
inputPath: path,
|
|
140
|
+
resolvedPath: absolutePath,
|
|
141
|
+
line: diffResult.firstChangedLine,
|
|
142
|
+
}),
|
|
143
|
+
},
|
|
133
144
|
});
|
|
134
145
|
}
|
|
135
146
|
catch (error) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAe,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,EAAE,MAAM,IAAI,QAAQ,EAAE,QAAQ,IAAI,UAAU,EAAE,SAAS,IAAI,WAAW,EAAE,MAAM,aAAa,CAAC;AACnG,OAAO,EACN,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,QAAQ,GACR,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;IACrF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;IAC5F,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;CAC9E,CAAC,CAAC;AAwBH,MAAM,qBAAqB,GAAmB;IAC7C,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;IACpC,SAAS,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC;IACjE,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC;CACjE,CAAC;AAOF,MAAM,UAAU,cAAc,CAAC,GAAW,EAAE,OAAyB;IACpE,MAAM,GAAG,GAAG,OAAO,EAAE,UAAU,IAAI,qBAAqB,CAAC;IAEzD,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EACV,mIAAmI;QACpI,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,KAAK,EACb,WAAmB,EACnB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAsD,EAC9E,MAAoB,EACnB,EAAE;YACH,MAAM,YAAY,GAAG,YAAY,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;YAE7C,OAAO,IAAI,OAAO,CAGf,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACtB,2BAA2B;gBAC3B,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;oBACrB,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;oBACvC,OAAO;gBACR,CAAC;gBAED,IAAI,OAAO,GAAG,KAAK,CAAC;gBAEpB,uBAAuB;gBACvB,MAAM,OAAO,GAAG,GAAG,EAAE;oBACpB,OAAO,GAAG,IAAI,CAAC;oBACf,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBACxC,CAAC,CAAC;gBAEF,IAAI,MAAM,EAAE,CAAC;oBACZ,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;gBAC3D,CAAC;gBAED,6BAA6B;gBAC7B,CAAC,KAAK,IAAI,EAAE;oBACX,IAAI,CAAC;wBACJ,uBAAuB;wBACvB,IAAI,CAAC;4BACJ,MAAM,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;wBAChC,CAAC;wBAAC,MAAM,CAAC;4BACR,IAAI,MAAM,EAAE,CAAC;gCACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;4BAC9C,CAAC;4BACD,MAAM,CAAC,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC,CAAC;4BAC7C,OAAO;wBACR,CAAC;wBAED,kCAAkC;wBAClC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,gBAAgB;wBAChB,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;wBAChD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;wBAE5C,iCAAiC;wBACjC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,yEAAyE;wBACzE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC,UAAU,CAAC,CAAC;wBAEpD,MAAM,cAAc,GAAG,gBAAgB,CAAC,OAAO,CAAC,CAAC;wBACjD,MAAM,iBAAiB,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;wBACjD,MAAM,iBAAiB,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;wBACjD,MAAM,iBAAiB,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;wBAEjD,+EAA+E;wBAC/E,MAAM,WAAW,GAAG,aAAa,CAAC,iBAAiB,EAAE,iBAAiB,CAAC,CAAC;wBAExE,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;4BACxB,IAAI,MAAM,EAAE,CAAC;gCACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;4BAC9C,CAAC;4BACD,MAAM,CACL,IAAI,KAAK,CACR,oCAAoC,IAAI,0EAA0E,CAClH,CACD,CAAC;4BACF,OAAO;wBACR,CAAC;wBAED,mEAAmE;wBACnE,MAAM,YAAY,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;wBAC/D,MAAM,YAAY,GAAG,sBAAsB,CAAC,iBAAiB,CAAC,CAAC;wBAC/D,MAAM,WAAW,GAAG,YAAY,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;wBAEhE,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;4BACrB,IAAI,MAAM,EAAE,CAAC;gCACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;4BAC9C,CAAC;4BACD,MAAM,CACL,IAAI,KAAK,CACR,SAAS,WAAW,+BAA+B,IAAI,2EAA2E,CAClI,CACD,CAAC;4BACF,OAAO;wBACR,CAAC;wBAED,kCAAkC;wBAClC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,sDAAsD;wBACtD,gFAAgF;wBAChF,MAAM,WAAW,GAAG,WAAW,CAAC,qBAAqB,CAAC;wBACtD,MAAM,UAAU,GACf,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,KAAK,CAAC;4BAC3C,iBAAiB;4BACjB,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,KAAK,GAAG,WAAW,CAAC,WAAW,CAAC,CAAC;wBAEpE,oDAAoD;wBACpD,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;4BAChC,IAAI,MAAM,EAAE,CAAC;gCACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;4BAC9C,CAAC;4BACD,MAAM,CACL,IAAI,KAAK,CACR,sBAAsB,IAAI,0IAA0I,CACpK,CACD,CAAC;4BACF,OAAO;wBACR,CAAC;wBAED,MAAM,YAAY,GAAG,GAAG,GAAG,kBAAkB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;wBAC1E,MAAM,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;wBAEhD,IAAI,CAAC;4BAAC,iBAAiB,CAAC,YAAY,CAAC,CAAC;wBAAC,CAAC;wBAAC,MAAM,CAAC,CAAC,iBAAiB,CAAC,CAAC;wBAEpE,iCAAiC;wBACjC,IAAI,OAAO,EAAE,CAAC;4BACb,OAAO;wBACR,CAAC;wBAED,yBAAyB;wBACzB,IAAI,MAAM,EAAE,CAAC;4BACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBAC9C,CAAC;wBAED,MAAM,UAAU,GAAG,kBAAkB,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;wBAC/D,OAAO,CAAC;4BACP,OAAO,EAAE;gCACR;oCACC,IAAI,EAAE,MAAM;oCACZ,IAAI,EAAE,iCAAiC,IAAI,GAAG;iCAC9C;6BACD;4BACD,OAAO,EAAE,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,gBAAgB,EAAE,UAAU,CAAC,gBAAgB,EAAE;yBACjF,CAAC,CAAC;oBACJ,CAAC;oBAAC,OAAO,KAAU,EAAE,CAAC;wBACrB,yBAAyB;wBACzB,IAAI,MAAM,EAAE,CAAC;4BACZ,MAAM,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;wBAC9C,CAAC;wBAED,IAAI,CAAC,OAAO,EAAE,CAAC;4BACd,MAAM,CAAC,KAAK,CAAC,CAAC;wBACf,CAAC;oBACF,CAAC;gBACF,CAAC,CAAC,EAAE,CAAC;YACN,CAAC,CAAC,CAAC;QACJ,CAAC;KACD,CAAC;AACH,CAAC;AAED,0EAA0E;AAC1E,MAAM,CAAC,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC","sourcesContent":["import type { AgentTool } from \"@gsd/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from \"fs/promises\";\nimport {\n\tdetectLineEnding,\n\tfuzzyFindText,\n\tgenerateDiffString,\n\tnormalizeForFuzzyMatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n\tstripBom,\n} from \"./edit-diff.js\";\nimport { notifyFileChanged } from \"../lsp/client.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\n\nconst editSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\toldText: Type.String({ description: \"Exact text to find and replace (must match exactly)\" }),\n\tnewText: Type.String({ description: \"New text to replace the old text with\" }),\n});\n\nexport type EditToolInput = Static<typeof editSchema>;\n\nexport interface EditToolDetails {\n\t/** Unified diff of the changes made */\n\tdiff: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (e.g., SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a file by replacing exact text. The oldText must match exactly (including whitespace). Use this for precise, surgical edits.\",\n\t\tparameters: editSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, oldText, newText }: { path: string; oldText: string; newText: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\n\t\t\treturn new Promise<{\n\t\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\t\tdetails: EditToolDetails | undefined;\n\t\t\t}>((resolve, reject) => {\n\t\t\t\t// Check if already aborted\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet aborted = false;\n\n\t\t\t\t// Set up abort handler\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\taborted = true;\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t};\n\n\t\t\t\tif (signal) {\n\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\n\t\t\t\t// Perform the edit operation\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Check if file exists\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(new Error(`File not found: ${path}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if aborted before reading\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read the file\n\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\n\t\t\t\t\t\t// Check if aborted after reading\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Strip BOM before matching (LLM won't include invisible BOM in oldText)\n\t\t\t\t\t\tconst { bom, text: content } = stripBom(rawContent);\n\n\t\t\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\t\t\tconst normalizedOldText = normalizeToLF(oldText);\n\t\t\t\t\t\tconst normalizedNewText = normalizeToLF(newText);\n\n\t\t\t\t\t\t// Find the old text using fuzzy matching (tries exact match first, then fuzzy)\n\t\t\t\t\t\tconst matchResult = fuzzyFindText(normalizedContent, normalizedOldText);\n\n\t\t\t\t\t\tif (!matchResult.found) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Count occurrences using fuzzy-normalized content for consistency\n\t\t\t\t\t\tconst fuzzyContent = normalizeForFuzzyMatch(normalizedContent);\n\t\t\t\t\t\tconst fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);\n\t\t\t\t\t\tconst occurrences = fuzzyContent.split(fuzzyOldText).length - 1;\n\n\t\t\t\t\t\tif (occurrences > 1) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if aborted before writing\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Perform replacement using the matched text position\n\t\t\t\t\t\t// When fuzzy matching was used, contentForReplacement is the normalized version\n\t\t\t\t\t\tconst baseContent = matchResult.contentForReplacement;\n\t\t\t\t\t\tconst newContent =\n\t\t\t\t\t\t\tbaseContent.substring(0, matchResult.index) +\n\t\t\t\t\t\t\tnormalizedNewText +\n\t\t\t\t\t\t\tbaseContent.substring(matchResult.index + matchResult.matchLength);\n\n\t\t\t\t\t\t// Verify the replacement actually changed something\n\t\t\t\t\t\tif (baseContent === newContent) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\t\t\tawait ops.writeFile(absolutePath, finalContent);\n\n\t\t\t\t\t\ttry { notifyFileChanged(absolutePath); } catch { /* best-effort */ }\n\n\t\t\t\t\t\t// Check if aborted after writing\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\ttext: `Successfully replaced text in ${path}.`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdetails: { diff: diffResult.diff, firstChangedLine: diffResult.firstChangedLine },\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!aborted) {\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default edit tool using process.cwd() - for backwards compatibility */\nexport const editTool = createEditTool(process.cwd());\n"]}
|
|
1
|
+
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../../src/core/tools/edit.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@gsd/pi-agent-core\";\nimport { type Static, Type } from \"@sinclair/typebox\";\nimport { constants } from \"fs\";\nimport { access as fsAccess, readFile as fsReadFile, writeFile as fsWriteFile } from \"fs/promises\";\nimport {\n\tdetectLineEnding,\n\tfuzzyFindText,\n\tgenerateDiffString,\n\tnormalizeForFuzzyMatch,\n\tnormalizeToLF,\n\trestoreLineEndings,\n\tstripBom,\n} from \"./edit-diff.js\";\nimport { notifyFileChanged } from \"../lsp/client.js\";\nimport { resolveToCwd } from \"./path-utils.js\";\nimport { createToolTarget, type ToolTargetMetadata } from \"./tool-target.js\";\n\nconst editSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\toldText: Type.String({ description: \"Exact text to find and replace (must match exactly)\" }),\n\tnewText: Type.String({ description: \"New text to replace the old text with\" }),\n});\n\nexport type EditToolInput = Static<typeof editSchema>;\n\nexport interface EditToolDetails {\n\t/** Unified diff of the changes made */\n\tdiff: string;\n\t/** Line number of the first change in the new file (for editor navigation) */\n\tfirstChangedLine?: number;\n\ttarget?: ToolTargetMetadata;\n}\n\n/**\n * Pluggable operations for the edit tool.\n * Override these to delegate file editing to remote systems (e.g., SSH).\n */\nexport interface EditOperations {\n\t/** Read file contents as a Buffer */\n\treadFile: (absolutePath: string) => Promise<Buffer>;\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Check if file is readable and writable (throw if not) */\n\taccess: (absolutePath: string) => Promise<void>;\n}\n\nconst defaultEditOperations: EditOperations = {\n\treadFile: (path) => fsReadFile(path),\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\taccess: (path) => fsAccess(path, constants.R_OK | constants.W_OK),\n};\n\nexport interface EditToolOptions {\n\t/** Custom operations for file editing. Default: local filesystem */\n\toperations?: EditOperations;\n}\n\nexport function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema> {\n\tconst ops = options?.operations ?? defaultEditOperations;\n\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a file by replacing exact text. The oldText must match exactly (including whitespace). Use this for precise, surgical edits.\",\n\t\tparameters: editSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, oldText, newText }: { path: string; oldText: string; newText: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tconst absolutePath = resolveToCwd(path, cwd);\n\n\t\t\treturn new Promise<{\n\t\t\t\tcontent: Array<{ type: \"text\"; text: string }>;\n\t\t\t\tdetails: EditToolDetails | undefined;\n\t\t\t}>((resolve, reject) => {\n\t\t\t\t// Check if already aborted\n\t\t\t\tif (signal?.aborted) {\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tlet aborted = false;\n\n\t\t\t\t// Set up abort handler\n\t\t\t\tconst onAbort = () => {\n\t\t\t\t\taborted = true;\n\t\t\t\t\treject(new Error(\"Operation aborted\"));\n\t\t\t\t};\n\n\t\t\t\tif (signal) {\n\t\t\t\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t\t\t}\n\n\t\t\t\t// Perform the edit operation\n\t\t\t\t(async () => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\t// Check if file exists\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tawait ops.access(absolutePath);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(new Error(`File not found: ${path}`));\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if aborted before reading\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Read the file\n\t\t\t\t\t\tconst buffer = await ops.readFile(absolutePath);\n\t\t\t\t\t\tconst rawContent = buffer.toString(\"utf-8\");\n\n\t\t\t\t\t\t// Check if aborted after reading\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Strip BOM before matching (LLM won't include invisible BOM in oldText)\n\t\t\t\t\t\tconst { bom, text: content } = stripBom(rawContent);\n\n\t\t\t\t\t\tconst originalEnding = detectLineEnding(content);\n\t\t\t\t\t\tconst normalizedContent = normalizeToLF(content);\n\t\t\t\t\t\tconst normalizedOldText = normalizeToLF(oldText);\n\t\t\t\t\t\tconst normalizedNewText = normalizeToLF(newText);\n\n\t\t\t\t\t\t// Find the old text using fuzzy matching (tries exact match first, then fuzzy)\n\t\t\t\t\t\tconst matchResult = fuzzyFindText(normalizedContent, normalizedOldText);\n\n\t\t\t\t\t\tif (!matchResult.found) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Count occurrences using fuzzy-normalized content for consistency\n\t\t\t\t\t\tconst fuzzyContent = normalizeForFuzzyMatch(normalizedContent);\n\t\t\t\t\t\tconst fuzzyOldText = normalizeForFuzzyMatch(normalizedOldText);\n\t\t\t\t\t\tconst occurrences = fuzzyContent.split(fuzzyOldText).length - 1;\n\n\t\t\t\t\t\tif (occurrences > 1) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Check if aborted before writing\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Perform replacement using the matched text position\n\t\t\t\t\t\t// When fuzzy matching was used, contentForReplacement is the normalized version\n\t\t\t\t\t\tconst baseContent = matchResult.contentForReplacement;\n\t\t\t\t\t\tconst newContent =\n\t\t\t\t\t\t\tbaseContent.substring(0, matchResult.index) +\n\t\t\t\t\t\t\tnormalizedNewText +\n\t\t\t\t\t\t\tbaseContent.substring(matchResult.index + matchResult.matchLength);\n\n\t\t\t\t\t\t// Verify the replacement actually changed something\n\t\t\t\t\t\tif (baseContent === newContent) {\n\t\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treject(\n\t\t\t\t\t\t\t\tnew Error(\n\t\t\t\t\t\t\t\t\t`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`,\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst finalContent = bom + restoreLineEndings(newContent, originalEnding);\n\t\t\t\t\t\tawait ops.writeFile(absolutePath, finalContent);\n\n\t\t\t\t\t\ttry { notifyFileChanged(absolutePath); } catch { /* best-effort */ }\n\n\t\t\t\t\t\t// Check if aborted after writing\n\t\t\t\t\t\tif (aborted) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tconst diffResult = generateDiffString(baseContent, newContent);\n\t\t\t\t\t\tresolve({\n\t\t\t\t\t\t\tcontent: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\t\t\ttext: `Successfully replaced text in ${path}.`,\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\tdetails: {\n\t\t\t\t\t\t\t\tdiff: diffResult.diff,\n\t\t\t\t\t\t\t\tfirstChangedLine: diffResult.firstChangedLine,\n\t\t\t\t\t\t\t\ttarget: createToolTarget({\n\t\t\t\t\t\t\t\t\tkind: \"file\",\n\t\t\t\t\t\t\t\t\taction: \"edit\",\n\t\t\t\t\t\t\t\t\tinputPath: path,\n\t\t\t\t\t\t\t\t\tresolvedPath: absolutePath,\n\t\t\t\t\t\t\t\t\tline: diffResult.firstChangedLine,\n\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t} catch (error: any) {\n\t\t\t\t\t\t// Clean up abort handler\n\t\t\t\t\t\tif (signal) {\n\t\t\t\t\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tif (!aborted) {\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t})();\n\t\t\t});\n\t\t},\n\t};\n}\n\n/** Default edit tool using process.cwd() - for backwards compatibility */\nexport const editTool = createEditTool(process.cwd());\n"]}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { AgentTool } from "@gsd/pi-agent-core";
|
|
2
2
|
import { type Static } from "@sinclair/typebox";
|
|
3
|
+
import { type ToolTargetMetadata } from "./tool-target.js";
|
|
3
4
|
import { type TruncationResult } from "./truncate.js";
|
|
4
5
|
declare const findSchema: import("@sinclair/typebox").TObject<{
|
|
5
6
|
pattern: import("@sinclair/typebox").TString;
|
|
@@ -8,6 +9,7 @@ declare const findSchema: import("@sinclair/typebox").TObject<{
|
|
|
8
9
|
}>;
|
|
9
10
|
export type FindToolInput = Static<typeof findSchema>;
|
|
10
11
|
export interface FindToolDetails {
|
|
12
|
+
target?: ToolTargetMetadata;
|
|
11
13
|
truncation?: TruncationResult;
|
|
12
14
|
resultLimitReached?: number;
|
|
13
15
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAKtD,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,UAAU;;;;EAMd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAItD,MAAM,WAAW,eAAe;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gEAAgE;IAChE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACnH;AAUD,MAAM,WAAW,eAAe;IAC/B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,
|
|
1
|
+
{"version":3,"file":"find.d.ts","sourceRoot":"","sources":["../../../src/core/tools/find.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,KAAK,MAAM,EAAQ,MAAM,mBAAmB,CAAC;AAKtD,OAAO,EAAoB,KAAK,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAiC,KAAK,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AAEnG,QAAA,MAAM,UAAU;;;;EAMd,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,UAAU,CAAC,CAAC;AAItD,MAAM,WAAW,eAAe;IAC/B,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,UAAU,CAAC,EAAE,gBAAgB,CAAC;IAC9B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED;;;GAGG;AACH,MAAM,WAAW,cAAc;IAC9B,2BAA2B;IAC3B,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;IAC7D,gEAAgE;IAChE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC;CACnH;AAUD,MAAM,WAAW,eAAe;IAC/B,0EAA0E;IAC1E,UAAU,CAAC,EAAE,cAAc,CAAC;CAC5B;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAyJnG;AAED,0EAA0E;AAC1E,eAAO,MAAM,QAAQ;;;;QAAgC,CAAC"}
|