zidane 7.2.4 → 8.0.4
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/LICENSE +21 -0
- package/README.md +34 -6
- package/dist/{acp-D-tVyUjw.js → acp-DQDhi2dj.js} +230 -77
- package/dist/acp-DQDhi2dj.js.map +1 -0
- package/dist/acp-cli.d.ts +1 -1
- package/dist/acp-cli.js +9 -66
- package/dist/acp-cli.js.map +1 -1
- package/dist/acp.d.ts +10 -590
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +3 -3
- package/dist/{agent-D0zZnGbt.js → agent-DSLNmBp0.js} +14401 -13214
- package/dist/agent-DSLNmBp0.js.map +1 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -2
- package/dist/aliasing-lVFbm81n.js +217 -0
- package/dist/aliasing-lVFbm81n.js.map +1 -0
- package/dist/{anthropic-C2aole0G.js → anthropic-CD00LhUP.js} +1442 -1264
- package/dist/anthropic-CD00LhUP.js.map +1 -0
- package/dist/artifacts-CV2hUKnL.js.map +1 -1
- package/dist/{atomic-write-B7zr1ddF.js → atomic-write-Ijgf2Mhc.js} +13 -3
- package/dist/atomic-write-Ijgf2Mhc.js.map +1 -0
- package/dist/call-tool-dHlbGOIY.js +70 -0
- package/dist/call-tool-dHlbGOIY.js.map +1 -0
- package/dist/chat/pure.d.ts +372 -6
- package/dist/chat/pure.d.ts.map +1 -1
- package/dist/chat/pure.js +35 -244
- package/dist/chat/pure.js.map +1 -1
- package/dist/{approvals-DKaJZYlm.js → chat-JPJJ8uu5.js} +15879 -14631
- package/dist/chat-JPJJ8uu5.js.map +1 -0
- package/dist/chat.d.ts +4 -6
- package/dist/chat.js +23 -12
- package/dist/cli-shared-C-YCaglL.js +159 -0
- package/dist/cli-shared-C-YCaglL.js.map +1 -0
- package/dist/client-core-BQSyDALT.d.ts +2115 -0
- package/dist/client-core-BQSyDALT.d.ts.map +1 -0
- package/dist/codemode-worker.d.ts +1 -0
- package/dist/codemode-worker.js +155 -0
- package/dist/codemode-worker.js.map +1 -0
- package/dist/codemode.d.ts +352 -0
- package/dist/codemode.d.ts.map +1 -0
- package/dist/codemode.js +5 -0
- package/dist/connection-Dr-Js4yZ.d.ts +28 -0
- package/dist/connection-Dr-Js4yZ.d.ts.map +1 -0
- package/dist/connection-loop-gdh22LTI.js +112 -0
- package/dist/connection-loop-gdh22LTI.js.map +1 -0
- package/dist/context-segments-BHKlagL6.js +1016 -0
- package/dist/context-segments-BHKlagL6.js.map +1 -0
- package/dist/{context-transport-T_6AYIvy.js → context-transport-DSMTUsK1.js} +3 -3
- package/dist/{context-transport-T_6AYIvy.js.map → context-transport-DSMTUsK1.js.map} +1 -1
- package/dist/contexts/daytona.d.ts +19 -8
- package/dist/contexts/daytona.d.ts.map +1 -1
- package/dist/contexts/daytona.js +1 -440
- package/dist/contexts/docker.d.ts +36 -7
- package/dist/contexts/docker.d.ts.map +1 -1
- package/dist/contexts/docker.js +1 -456
- package/dist/contexts/e2b.d.ts +68 -13
- package/dist/contexts/e2b.d.ts.map +1 -1
- package/dist/contexts/e2b.js +1 -382
- package/dist/contexts/sandbox.d.ts +1 -1
- package/dist/contexts/sandbox.js +5 -0
- package/dist/contexts/sandbox.js.map +1 -1
- package/dist/{contexts-CRE9pw07.js → contexts-d7UolYot.js} +1059 -524
- package/dist/contexts-d7UolYot.js.map +1 -0
- package/dist/contexts.d.ts +3 -3
- package/dist/contexts.js +1 -1
- package/dist/cred-keys-GpBg71cP.js +105 -0
- package/dist/cred-keys-GpBg71cP.js.map +1 -0
- package/dist/{auth-BG2rVKSt.js → credentials-JttEuRON.js} +55 -206
- package/dist/credentials-JttEuRON.js.map +1 -0
- package/dist/{cursor-iojRXHF9.js → cursor-CdjaQTBW.js} +3 -3
- package/dist/{cursor-iojRXHF9.js.map → cursor-CdjaQTBW.js.map} +1 -1
- package/dist/daemon-cli.d.ts +1 -1
- package/dist/daemon-cli.js +3 -2
- package/dist/daemon-cli.js.map +1 -1
- package/dist/daytona-DG3omipZ.js +513 -0
- package/dist/daytona-DG3omipZ.js.map +1 -0
- package/dist/defaults-Cx3zvDOV.js +23 -0
- package/dist/defaults-Cx3zvDOV.js.map +1 -0
- package/dist/dispatcher-BMlu2BmZ.js +4941 -0
- package/dist/dispatcher-BMlu2BmZ.js.map +1 -0
- package/dist/docker-BZhMMJUp.js +727 -0
- package/dist/docker-BZhMMJUp.js.map +1 -0
- package/dist/e2b-CEVOdRib.js +480 -0
- package/dist/e2b-CEVOdRib.js.map +1 -0
- package/dist/edit-utils-EGosADZq.js +234 -0
- package/dist/edit-utils-EGosADZq.js.map +1 -0
- package/dist/environment-8wsKE2Ln.js +214 -0
- package/dist/environment-8wsKE2Ln.js.map +1 -0
- package/dist/eval-BNcvle_J.js +1595 -0
- package/dist/eval-BNcvle_J.js.map +1 -0
- package/dist/eval.d.ts +2 -2
- package/dist/eval.js +1 -1489
- package/dist/executor-Cx5-8yqi.js +621 -0
- package/dist/executor-Cx5-8yqi.js.map +1 -0
- package/dist/extension-authoring-DyGGmq9V.js +385 -0
- package/dist/extension-authoring-DyGGmq9V.js.map +1 -0
- package/dist/extensions.d.ts +2 -2
- package/dist/extensions.js +3 -3
- package/dist/{fetch-url-DX75gpL0.js → fetch-url-Ct2TjDWt.js} +4 -4
- package/dist/{fetch-url-DX75gpL0.js.map → fetch-url-Ct2TjDWt.js.map} +1 -1
- package/dist/{format-BF745pLL.js → format-C2NQEVUH.js} +39 -2
- package/dist/format-C2NQEVUH.js.map +1 -0
- package/dist/format-bytes-C7tfc3Zm.js +55 -0
- package/dist/format-bytes-C7tfc3Zm.js.map +1 -0
- package/dist/headless-C_rNUuYC.js +960 -0
- package/dist/headless-C_rNUuYC.js.map +1 -0
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -413
- package/dist/{history-search-C4bk1Wz_.js → history-search-CcYzF8-0.js} +7 -3
- package/dist/history-search-CcYzF8-0.js.map +1 -0
- package/dist/history-search-worker.d.ts +1 -1
- package/dist/history-search-worker.js +1 -1
- package/dist/host-D7NrI03V.js +378 -0
- package/dist/host-D7NrI03V.js.map +1 -0
- package/dist/host-signals-BcP5QKUD.js +118 -0
- package/dist/host-signals-BcP5QKUD.js.map +1 -0
- package/dist/identity-CwfO8K-t.js +26 -0
- package/dist/identity-CwfO8K-t.js.map +1 -0
- package/dist/{index-BgN1T3lk.d.ts → index-BGe1fQT7.d.ts} +10987 -9320
- package/dist/index-BGe1fQT7.d.ts.map +1 -0
- package/dist/index-BVQsIKGn.d.ts +448 -0
- package/dist/index-BVQsIKGn.d.ts.map +1 -0
- package/dist/{index-C6NEd5y_.d.ts → index-CHABJd-L.d.ts} +3386 -502
- package/dist/index-CHABJd-L.d.ts.map +1 -0
- package/dist/{index-C37_ppWv.d.ts → index-D6a7qXpg.d.ts} +2 -3
- package/dist/index-D6a7qXpg.d.ts.map +1 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +27 -23
- package/dist/{completion-core-BRo86R_L.js → inline-ghost-BVRQeGoL.js} +50 -2
- package/dist/inline-ghost-BVRQeGoL.js.map +1 -0
- package/dist/ipc/remote.d.ts +313 -0
- package/dist/ipc/remote.d.ts.map +1 -0
- package/dist/ipc/remote.js +4 -0
- package/dist/ipc.d.ts +6 -964
- package/dist/ipc.js +403 -4
- package/dist/ipc.js.map +1 -0
- package/dist/{isolation-Kfoof0MM.d.ts → isolation-D9L650W5.d.ts} +100 -15
- package/dist/isolation-D9L650W5.d.ts.map +1 -0
- package/dist/json-rpc--HXQti1E.js +350 -0
- package/dist/json-rpc--HXQti1E.js.map +1 -0
- package/dist/links-j8rED1sR.js +603 -0
- package/dist/links-j8rED1sR.js.map +1 -0
- package/dist/local-terminal-D8QThwo_.js +252 -0
- package/dist/local-terminal-D8QThwo_.js.map +1 -0
- package/dist/{logger--C1VQjwJ.js → logger-Gtqlayx8.js} +199 -173
- package/dist/logger-Gtqlayx8.js.map +1 -0
- package/dist/logs-view-CWG8aUAG.js.map +1 -1
- package/dist/{mcp-CgNd-f3F.js → mcp-_wecH9Qe.js} +608 -562
- package/dist/mcp-_wecH9Qe.js.map +1 -0
- package/dist/mcp.d.ts +2 -2
- package/dist/mcp.js +2 -2
- package/dist/media-sniff-UKijEaiQ.js.map +1 -1
- package/dist/{messages-2jcOA_5R.js → messages-BqiwcD2Q.js} +1017 -1014
- package/dist/messages-BqiwcD2Q.js.map +1 -0
- package/dist/{oauth-DxHO17JE.js → oauth-Px_pBB9W.js} +5 -5
- package/dist/{oauth-DxHO17JE.js.map → oauth-Px_pBB9W.js.map} +1 -1
- package/dist/{openai-compat-Dy56weK8.js → openai-compat-CFrpH7uq.js} +432 -589
- package/dist/openai-compat-CFrpH7uq.js.map +1 -0
- package/dist/orchestration-BCGmB8Ps.js +511 -0
- package/dist/orchestration-BCGmB8Ps.js.map +1 -0
- package/dist/output/stream-json.d.ts +1 -2
- package/dist/output/stream-json.d.ts.map +1 -1
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +1 -2
- package/dist/output/terminal.d.ts.map +1 -1
- package/dist/output/terminal.js +13 -7
- package/dist/output/terminal.js.map +1 -1
- package/dist/{plugins-gbI7SBA6.js → plugins-DS7mahzZ.js} +20 -101
- package/dist/plugins-DS7mahzZ.js.map +1 -0
- package/dist/plugins.d.ts +1 -1
- package/dist/plugins.js +1 -2
- package/dist/prelude-Cxo4t74B.js +517 -0
- package/dist/prelude-Cxo4t74B.js.map +1 -0
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -2
- package/dist/project-root-B8zADr4o.js +167 -0
- package/dist/project-root-B8zADr4o.js.map +1 -0
- package/dist/project-user-paths-BSgtrRxl.js +58 -0
- package/dist/project-user-paths-BSgtrRxl.js.map +1 -0
- package/dist/{prompts-Pqc3JdW_.d.ts → prompts-DYcvqShf.d.ts} +14 -11
- package/dist/prompts-DYcvqShf.d.ts.map +1 -0
- package/dist/protocol-DnhqqSmE.js +13 -0
- package/dist/protocol-DnhqqSmE.js.map +1 -0
- package/dist/providers/anthropic.d.ts +2 -2
- package/dist/providers/anthropic.js +1 -2
- package/dist/providers/arcee.d.ts +1 -1
- package/dist/providers/arcee.js +1 -1
- package/dist/providers/baseten.d.ts +1 -1
- package/dist/providers/baseten.js +1 -1
- package/dist/providers/cerebras.d.ts +1 -1
- package/dist/providers/cerebras.js +3 -2
- package/dist/providers/cerebras.js.map +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/local.js +1 -1
- package/dist/providers/openai-compat.d.ts +1 -1
- package/dist/providers/openai-compat.js +1 -2
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +15 -12
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +1 -1
- package/dist/providers/openrouter.js +3 -2
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +3 -3
- package/dist/{providers-BVhnFyiY.js → providers-XUR7F4Hi.js} +4 -4
- package/dist/{providers-BVhnFyiY.js.map → providers-XUR7F4Hi.js.map} +1 -1
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +4 -4
- package/dist/registry-D6ShBWJU.js +5234 -0
- package/dist/registry-D6ShBWJU.js.map +1 -0
- package/dist/remote-hosts-BtA_9ZGp.js +97 -0
- package/dist/remote-hosts-BtA_9ZGp.js.map +1 -0
- package/dist/restate.d.ts +2 -3
- package/dist/restate.d.ts.map +1 -1
- package/dist/restate.js +631 -572
- package/dist/restate.js.map +1 -1
- package/dist/run-summary-CklLiZ4y.js +288 -0
- package/dist/run-summary-CklLiZ4y.js.map +1 -0
- package/dist/{sandbox-BH0WQkXn.d.ts → sandbox-C5dR5DwQ.d.ts} +6 -3
- package/dist/sandbox-C5dR5DwQ.d.ts.map +1 -0
- package/dist/session/sqlite.d.ts +1 -2
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +1 -616
- package/dist/session-factory-BUGY5P40.js +1576 -0
- package/dist/session-factory-BUGY5P40.js.map +1 -0
- package/dist/{session-BqRP1hS7.js → session-xh9JXu6i.js} +94 -52
- package/dist/session-xh9JXu6i.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/settings-keys-Ckf29NeM.js +677 -0
- package/dist/settings-keys-Ckf29NeM.js.map +1 -0
- package/dist/shell-path-Dqaoow2J.js +412 -0
- package/dist/shell-path-Dqaoow2J.js.map +1 -0
- package/dist/{skills-BC3dodWp.js → skills-DKqZJm4X.js} +430 -470
- package/dist/skills-DKqZJm4X.js.map +1 -0
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -2
- package/dist/source-mPExaUm8.js +381 -0
- package/dist/source-mPExaUm8.js.map +1 -0
- package/dist/sqlite-DV1DQzN2.js +698 -0
- package/dist/sqlite-DV1DQzN2.js.map +1 -0
- package/dist/{src-CkNQKFKr.js → src-BRMYRJib.js} +903 -1121
- package/dist/src-BRMYRJib.js.map +1 -0
- package/dist/{stdio-DPpBDPx5.js → stdio-C6YyoW3I.js} +4 -4
- package/dist/{stdio-DPpBDPx5.js.map → stdio-C6YyoW3I.js.map} +1 -1
- package/dist/{stdio-loader-Bbx19dMZ.js → stdio-loader-C830Vg-Z.js} +4 -4
- package/dist/{stdio-loader-Bbx19dMZ.js.map → stdio-loader-C830Vg-Z.js.map} +1 -1
- package/dist/system-prompt-MNVHatSD.d.ts.map +1 -1
- package/dist/timeout-DEaqslLO.d.ts.map +1 -1
- package/dist/todo-edits-Dn251YUP.js +1790 -0
- package/dist/todo-edits-Dn251YUP.js.map +1 -0
- package/dist/{turn-operations-DrbJlpq9.js → tool-formatters-IQFDrdrs.js} +1456 -2120
- package/dist/tool-formatters-IQFDrdrs.js.map +1 -0
- package/dist/tool-state-Dku6YqAB.js +989 -0
- package/dist/tool-state-Dku6YqAB.js.map +1 -0
- package/dist/tools/fetch-url.d.ts +1 -2
- package/dist/tools/fetch-url.d.ts.map +1 -1
- package/dist/tools/fetch-url.js +1 -2
- package/dist/tools/prompts.d.ts +1 -1
- package/dist/tools/prompts.js +7 -7
- package/dist/tools/prompts.js.map +1 -1
- package/dist/tools/web-search.d.ts +1 -2
- package/dist/tools/web-search.d.ts.map +1 -1
- package/dist/tools/web-search.js +2 -2
- package/dist/tools/web-search.js.map +1 -1
- package/dist/tools-_DnT3AGM.js +578 -0
- package/dist/tools-_DnT3AGM.js.map +1 -0
- package/dist/tools.d.ts +3 -3
- package/dist/tools.js +4 -2
- package/dist/tui.d.ts +534 -517
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +34933 -27242
- package/dist/tui.js.map +1 -1
- package/dist/turn-operations-B8sokwi5.js +333 -0
- package/dist/turn-operations-B8sokwi5.js.map +1 -0
- package/dist/turn-operations-DQX5ZZni.d.ts +3089 -0
- package/dist/turn-operations-DQX5ZZni.d.ts.map +1 -0
- package/dist/types-C7ZFOztE.d.ts +132 -0
- package/dist/types-C7ZFOztE.d.ts.map +1 -0
- package/dist/types-CH5XpIHw.js +114 -0
- package/dist/types-CH5XpIHw.js.map +1 -0
- package/dist/{types-CWgENVLY.js → types-Cu0ZGDu9.js} +10 -6
- package/dist/types-Cu0ZGDu9.js.map +1 -0
- package/dist/types-IqegbJEE.d.ts +624 -0
- package/dist/types-IqegbJEE.d.ts.map +1 -0
- package/dist/types.d.ts +4 -4
- package/dist/types.js +1 -1
- package/dist/url-D8HCl65b.js +1259 -0
- package/dist/url-D8HCl65b.js.map +1 -0
- package/dist/wasm-BVT-j5cl.js +33 -0
- package/dist/wasm-BVT-j5cl.js.map +1 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js +355 -0
- package/dist/workspace-exec-stream-SV2R9d5S.js.map +1 -0
- package/dist/ws-CIHMvlSh.js +952 -0
- package/dist/ws-CIHMvlSh.js.map +1 -0
- package/dist/ws-client-N7NxzvQp.js +230 -0
- package/dist/ws-client-N7NxzvQp.js.map +1 -0
- package/dist/{xai-CazjStOK.js → xai-CvJTeLrI.js} +165 -5
- package/dist/xai-CvJTeLrI.js.map +1 -0
- package/dist/xdg-zweed0-t.js +117 -0
- package/dist/xdg-zweed0-t.js.map +1 -0
- package/docs/ACP.md +52 -0
- package/docs/ARCHITECTURE.md +103 -6
- package/docs/ARTIFACTS.md +8 -4
- package/docs/CHAT.md +165 -14
- package/docs/EXECUTION_CONTEXT.md +8 -0
- package/docs/EXTENSIONS.md +123 -2
- package/docs/HEADLESS.md +2 -0
- package/docs/IPC.md +775 -64
- package/docs/MACHINES.md +456 -0
- package/docs/PANELS.md +3 -0
- package/docs/README.md +4 -0
- package/docs/RESTATE.md +3 -2
- package/docs/RUN_IN_BACKGROUND.md +10 -2
- package/docs/SERVER.md +1085 -0
- package/docs/SKILL.md +6 -1
- package/docs/TERMINAL.md +75 -0
- package/docs/TUI.md +65 -14
- package/package.json +58 -26
- package/scripts/eval.ts +4 -0
- package/dist/acp-D-tVyUjw.js.map +0 -1
- package/dist/agent-D0zZnGbt.js.map +0 -1
- package/dist/anthropic-C2aole0G.js.map +0 -1
- package/dist/approvals-DKaJZYlm.js.map +0 -1
- package/dist/atomic-write-B7zr1ddF.js.map +0 -1
- package/dist/auth-BG2rVKSt.js.map +0 -1
- package/dist/completion-core-BRo86R_L.js.map +0 -1
- package/dist/contexts/daytona.js.map +0 -1
- package/dist/contexts/docker.js.map +0 -1
- package/dist/contexts/e2b.js.map +0 -1
- package/dist/contexts-CRE9pw07.js.map +0 -1
- package/dist/eval.js.map +0 -1
- package/dist/format-BF745pLL.js.map +0 -1
- package/dist/glob-DluQFSw1.js +0 -270
- package/dist/glob-DluQFSw1.js.map +0 -1
- package/dist/headless.js.map +0 -1
- package/dist/history-search-C4bk1Wz_.js.map +0 -1
- package/dist/index-BgN1T3lk.d.ts.map +0 -1
- package/dist/index-C37_ppWv.d.ts.map +0 -1
- package/dist/index-C6NEd5y_.d.ts.map +0 -1
- package/dist/ipc-zVSyo6K1.js +0 -331
- package/dist/ipc-zVSyo6K1.js.map +0 -1
- package/dist/ipc.d.ts.map +0 -1
- package/dist/isolation-Kfoof0MM.d.ts.map +0 -1
- package/dist/json-rpc-rSWMUh9b.js +0 -192
- package/dist/json-rpc-rSWMUh9b.js.map +0 -1
- package/dist/logger--C1VQjwJ.js.map +0 -1
- package/dist/mcp-CgNd-f3F.js.map +0 -1
- package/dist/messages-2jcOA_5R.js.map +0 -1
- package/dist/openai-compat-Dy56weK8.js.map +0 -1
- package/dist/output-cap-C9zukcCj.js +0 -100
- package/dist/output-cap-C9zukcCj.js.map +0 -1
- package/dist/panels-B6gRk4bf.js +0 -789
- package/dist/panels-B6gRk4bf.js.map +0 -1
- package/dist/plugins-gbI7SBA6.js.map +0 -1
- package/dist/prompts-Pqc3JdW_.d.ts.map +0 -1
- package/dist/run-summary-BU_NgwUT.js +0 -269
- package/dist/run-summary-BU_NgwUT.js.map +0 -1
- package/dist/sandbox-BH0WQkXn.d.ts.map +0 -1
- package/dist/session/sqlite.js.map +0 -1
- package/dist/session-BqRP1hS7.js.map +0 -1
- package/dist/shell-path-h5czzllR.js +0 -1549
- package/dist/shell-path-h5czzllR.js.map +0 -1
- package/dist/skills-BC3dodWp.js.map +0 -1
- package/dist/src-CkNQKFKr.js.map +0 -1
- package/dist/todo-edits-UOwgxGKu.js +0 -528
- package/dist/todo-edits-UOwgxGKu.js.map +0 -1
- package/dist/tool-formatters-DoRLnfuD.d.ts +0 -759
- package/dist/tool-formatters-DoRLnfuD.d.ts.map +0 -1
- package/dist/transcript-anchors-BeudMbXx.d.ts +0 -1762
- package/dist/transcript-anchors-BeudMbXx.d.ts.map +0 -1
- package/dist/turn-operations-C8bMBDl_.d.ts +0 -1258
- package/dist/turn-operations-C8bMBDl_.d.ts.map +0 -1
- package/dist/turn-operations-DrbJlpq9.js.map +0 -1
- package/dist/types-CWgENVLY.js.map +0 -1
- package/dist/xai-CazjStOK.js.map +0 -1
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import { d as isAbortLikeError, u as errorMessage } from "./errors-DKiMrOKq.js";
|
|
2
|
+
import { n as shellQuote } from "./shell-quote-BmnhZmdM.js";
|
|
3
|
+
import { toolPrompts } from "./tools/prompts.js";
|
|
4
|
+
import { i as parseGitLsFiles, r as GIT_LS_FILES_COMMAND } from "./contexts-d7UolYot.js";
|
|
5
|
+
import { Buffer } from "node:buffer";
|
|
6
|
+
//#region src/tools/glob.ts
|
|
7
|
+
/**
|
|
8
|
+
* Glob-pattern file matching.
|
|
9
|
+
*
|
|
10
|
+
* Delegates matching to {@link ExecutionContext.listFiles} with `{ glob:
|
|
11
|
+
* true }`. This keeps filesystem semantics inside the execution context
|
|
12
|
+
* (process / docker / sandbox) instead of reaching around it from the tool.
|
|
13
|
+
*
|
|
14
|
+
* Results are capped at 1000 entries to keep model input bounded. The
|
|
15
|
+
* cap applies after the directory filter, so dirs don't consume the
|
|
16
|
+
* file budget.
|
|
17
|
+
*
|
|
18
|
+
* Patterns are deliberately NOT confined to the workspace: like
|
|
19
|
+
* `read_file`, `../`-prefixed patterns may match outside the cwd — the
|
|
20
|
+
* execution context is the sandbox boundary, not this tool.
|
|
21
|
+
*
|
|
22
|
+
* By default, contexts that can cheaply provide metadata return
|
|
23
|
+
* `<path>\t<size>\t<mtime>` rows. Contexts without cheap metadata support return
|
|
24
|
+
* paths only. Pass `metadata: false` to request plain newline-separated paths.
|
|
25
|
+
*/
|
|
26
|
+
const DEFAULT_LIMIT = 1e3;
|
|
27
|
+
/** Backstop so a pathological walk can never hang the agent's turn. */
|
|
28
|
+
const GLOB_TIMEOUT_MS = 2e4;
|
|
29
|
+
function entryPath(entry) {
|
|
30
|
+
return typeof entry === "string" ? entry : entry.path;
|
|
31
|
+
}
|
|
32
|
+
function entryMetadata(entry) {
|
|
33
|
+
return typeof entry === "string" ? void 0 : entry;
|
|
34
|
+
}
|
|
35
|
+
function renderEntry(entry, wantMetadata) {
|
|
36
|
+
const path = entryPath(entry);
|
|
37
|
+
const meta = entryMetadata(entry);
|
|
38
|
+
if (!wantMetadata || typeof meta?.size !== "number" || typeof meta.mtimeMs !== "number") return path;
|
|
39
|
+
return `${path}\t${meta.size}\t${new Date(meta.mtimeMs).toISOString()}`;
|
|
40
|
+
}
|
|
41
|
+
const glob = {
|
|
42
|
+
isConcurrencySafe: true,
|
|
43
|
+
spec: {
|
|
44
|
+
name: "glob",
|
|
45
|
+
description: toolPrompts.glob,
|
|
46
|
+
inputSchema: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
pattern: {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "Glob pattern (e.g. \"src/**/*.ts\", \"*.md\", \"test/**/fixtures/*\")."
|
|
52
|
+
},
|
|
53
|
+
limit: {
|
|
54
|
+
type: "number",
|
|
55
|
+
description: `Maximum number of matches to return. Default: ${DEFAULT_LIMIT}.`
|
|
56
|
+
},
|
|
57
|
+
metadata: {
|
|
58
|
+
type: "boolean",
|
|
59
|
+
description: "Append size (bytes) and mtime (ISO) per row, tab-separated. Default: true. In-process only; non-process execution contexts always return paths."
|
|
60
|
+
},
|
|
61
|
+
gitignore: {
|
|
62
|
+
type: "boolean",
|
|
63
|
+
description: "Skip files git ignores (.gitignore, .git/info/exclude, global excludes). Default: true. Set false to include ignored files like node_modules. Honored where git is available; a no-op otherwise."
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
required: ["pattern"]
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
async execute({ pattern, limit, metadata, gitignore }, ctx) {
|
|
70
|
+
const pat = pattern;
|
|
71
|
+
const max = typeof limit === "number" && limit > 0 ? limit : DEFAULT_LIMIT;
|
|
72
|
+
const wantMetadata = metadata !== false;
|
|
73
|
+
try {
|
|
74
|
+
if (ctx.execution.capabilities.glob !== true) throw new Error(`The active execution context (${ctx.execution.type}) does not support glob matching.`);
|
|
75
|
+
const controller = new AbortController();
|
|
76
|
+
const onAbort = () => controller.abort();
|
|
77
|
+
ctx.signal.addEventListener("abort", onAbort, { once: true });
|
|
78
|
+
let timer;
|
|
79
|
+
const timeout = new Promise((resolve) => {
|
|
80
|
+
timer = setTimeout(() => {
|
|
81
|
+
controller.abort();
|
|
82
|
+
resolve("timeout");
|
|
83
|
+
}, GLOB_TIMEOUT_MS);
|
|
84
|
+
});
|
|
85
|
+
try {
|
|
86
|
+
const outcome = await Promise.race([ctx.execution.listFiles(ctx.handle, pat, {
|
|
87
|
+
glob: true,
|
|
88
|
+
limit: max,
|
|
89
|
+
metadata: wantMetadata,
|
|
90
|
+
gitignore,
|
|
91
|
+
signal: controller.signal
|
|
92
|
+
}), timeout]);
|
|
93
|
+
if (outcome === "timeout") return `Glob timed out after ${GLOB_TIMEOUT_MS}ms: narrow the pattern (anchor a literal prefix like \`src/**\`) or scope it to a subdirectory.`;
|
|
94
|
+
if (outcome.length === 0) return "(no matches)";
|
|
95
|
+
return outcome.map((entry) => renderEntry(entry, wantMetadata)).join("\n");
|
|
96
|
+
} finally {
|
|
97
|
+
clearTimeout(timer);
|
|
98
|
+
ctx.signal.removeEventListener("abort", onAbort);
|
|
99
|
+
}
|
|
100
|
+
} catch (err) {
|
|
101
|
+
return `Glob error: ${errorMessage(err)}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
//#endregion
|
|
106
|
+
//#region src/tools/grep.ts
|
|
107
|
+
/**
|
|
108
|
+
* Search file contents by regex.
|
|
109
|
+
*
|
|
110
|
+
* Wraps ripgrep (`rg`) when available; when it's not, falls back to a
|
|
111
|
+
* regex search that enumerates files via the execution context's shell
|
|
112
|
+
* (`find` over `exec`) and reads them via `ctx.execution.readFile`. Both
|
|
113
|
+
* legs go through the {@link ToolContext.execution} seam, so the search
|
|
114
|
+
* runs wherever the context's files actually live — in-process, a
|
|
115
|
+
* container, or a remote sandbox — without the tool ever touching the host
|
|
116
|
+
* filesystem directly.
|
|
117
|
+
*
|
|
118
|
+
* The tool surface mirrors Claude Code's `Grep` so models authored against the
|
|
119
|
+
* Anthropic tool surface need no relearning. Output modes:
|
|
120
|
+
* - `files_with_matches` (default) — newline-separated paths.
|
|
121
|
+
* - `content` — `path:line:match` (line numbers on by default).
|
|
122
|
+
* - `count` — `path:N` per matching file.
|
|
123
|
+
*
|
|
124
|
+
* Results are capped via `head_limit` (default 250) to keep model input
|
|
125
|
+
* bounded; `offset` lets the caller page through. Pagination operates on
|
|
126
|
+
* OUTPUT LINES, not match groups — in content mode, context lines and `--`
|
|
127
|
+
* separators consume the budget too (documented in the schema).
|
|
128
|
+
*
|
|
129
|
+
* A line cap is not enough on its own: ripgrep is line-oriented, so a minified
|
|
130
|
+
* / single-line file collapses to ONE match line that is the entire file, and
|
|
131
|
+
* `head_limit` would happily return megabytes — enough to blow the model's
|
|
132
|
+
* context window. Output is therefore ALSO byte-bounded: each line is clipped
|
|
133
|
+
* to `MAX_LINE_BYTES` and the total to `OUTPUT_BYTE_CAP`, mirroring the byte
|
|
134
|
+
* discipline `read_file` already enforces.
|
|
135
|
+
*
|
|
136
|
+
* `path` is deliberately NOT confined to the workspace: like `read_file`,
|
|
137
|
+
* absolute paths and `../` traversal are allowed — the execution context is
|
|
138
|
+
* the sandbox boundary, not this tool.
|
|
139
|
+
*/
|
|
140
|
+
const DEFAULT_HEAD_LIMIT = 250;
|
|
141
|
+
/**
|
|
142
|
+
* Per-line byte cap. ripgrep reports a match as the whole matching LINE, so a
|
|
143
|
+
* minified / single-line file (one line = the entire file) would otherwise be
|
|
144
|
+
* returned in full. Clip each line so a single line can't dump unbounded bytes
|
|
145
|
+
* into the model context.
|
|
146
|
+
*/
|
|
147
|
+
const MAX_LINE_BYTES = 2e3;
|
|
148
|
+
/**
|
|
149
|
+
* OOM guard for the no-ripgrep fallback: it reads each candidate WHOLE
|
|
150
|
+
* into memory (the execution interface has no streaming read), so one
|
|
151
|
+
* multi-GB artifact would take the process down. Enforced twice — the
|
|
152
|
+
* `find` walk excludes oversized files via the portable `-size`
|
|
153
|
+
* predicate (POSIX `c` suffix, GNU + BSD), and the read loop probes
|
|
154
|
+
* process-local sizes to cover the single-file fast path that bypasses
|
|
155
|
+
* the walk. A documented divergence from the ripgrep path, which
|
|
156
|
+
* streams and searches such files fine.
|
|
157
|
+
*/
|
|
158
|
+
const FALLBACK_MAX_FILE_BYTES = 16777216;
|
|
159
|
+
/** Total output byte cap, mirroring read_file's `DEFAULT_BYTE_CAP`. */
|
|
160
|
+
const OUTPUT_BYTE_CAP = 262144;
|
|
161
|
+
const DEFAULT_OUTPUT_MODE = "files_with_matches";
|
|
162
|
+
const grep = {
|
|
163
|
+
isConcurrencySafe: true,
|
|
164
|
+
spec: {
|
|
165
|
+
name: "grep",
|
|
166
|
+
description: toolPrompts.grep,
|
|
167
|
+
inputSchema: {
|
|
168
|
+
type: "object",
|
|
169
|
+
properties: {
|
|
170
|
+
"pattern": {
|
|
171
|
+
type: "string",
|
|
172
|
+
description: "Regex (PCRE-flavored via ripgrep, JS regex via fallback)."
|
|
173
|
+
},
|
|
174
|
+
"patterns": {
|
|
175
|
+
type: "array",
|
|
176
|
+
items: { type: "string" },
|
|
177
|
+
description: "More regexes; a line matches if it matches `pattern` OR any of these (like `rg -e a -e b`)."
|
|
178
|
+
},
|
|
179
|
+
"exclude": {
|
|
180
|
+
type: "string",
|
|
181
|
+
description: "Drop output lines matching this regex (applied to the whole output line, like piping through `grep -v`)."
|
|
182
|
+
},
|
|
183
|
+
"fixed_strings": {
|
|
184
|
+
type: "boolean",
|
|
185
|
+
description: "Treat patterns as literal strings, not regexes (`-F`)."
|
|
186
|
+
},
|
|
187
|
+
"-w": {
|
|
188
|
+
type: "boolean",
|
|
189
|
+
description: "Match whole words only."
|
|
190
|
+
},
|
|
191
|
+
"path": {
|
|
192
|
+
type: "string",
|
|
193
|
+
description: "File or directory to search. Default: \".\". May be absolute or outside the workspace (no confinement; consistent with read_file)."
|
|
194
|
+
},
|
|
195
|
+
"paths": {
|
|
196
|
+
type: "array",
|
|
197
|
+
items: { type: "string" },
|
|
198
|
+
description: "Several files or directories to search in one call (combined with `path` when both are set)."
|
|
199
|
+
},
|
|
200
|
+
"glob": {
|
|
201
|
+
type: "string",
|
|
202
|
+
description: "Restrict to files matching this glob, e.g. \"**/*.ts\"."
|
|
203
|
+
},
|
|
204
|
+
"type": {
|
|
205
|
+
type: "string",
|
|
206
|
+
description: "rg file type filter, e.g. \"ts\", \"py\", \"rust\". Ignored by the fallback."
|
|
207
|
+
},
|
|
208
|
+
"output_mode": {
|
|
209
|
+
type: "string",
|
|
210
|
+
enum: [
|
|
211
|
+
"content",
|
|
212
|
+
"files_with_matches",
|
|
213
|
+
"count"
|
|
214
|
+
],
|
|
215
|
+
description: "Default: \"files_with_matches\"."
|
|
216
|
+
},
|
|
217
|
+
"-i": {
|
|
218
|
+
type: "boolean",
|
|
219
|
+
description: "Case-insensitive match."
|
|
220
|
+
},
|
|
221
|
+
"-n": {
|
|
222
|
+
type: "boolean",
|
|
223
|
+
description: "Show line numbers (content mode). Default: true."
|
|
224
|
+
},
|
|
225
|
+
"-A": {
|
|
226
|
+
type: "integer",
|
|
227
|
+
description: "Lines of trailing context (content mode)."
|
|
228
|
+
},
|
|
229
|
+
"-B": {
|
|
230
|
+
type: "integer",
|
|
231
|
+
description: "Lines of leading context (content mode)."
|
|
232
|
+
},
|
|
233
|
+
"-C": {
|
|
234
|
+
type: "integer",
|
|
235
|
+
description: "Lines of surrounding context (content mode). Overridden by -A/-B if set."
|
|
236
|
+
},
|
|
237
|
+
"multiline": {
|
|
238
|
+
type: "boolean",
|
|
239
|
+
description: "Allow patterns to match across line boundaries."
|
|
240
|
+
},
|
|
241
|
+
"gitignore": {
|
|
242
|
+
type: "boolean",
|
|
243
|
+
description: "Skip files git ignores (.gitignore, .git/info/exclude, global excludes). Default: true. Set false to also search ignored files like node_modules."
|
|
244
|
+
},
|
|
245
|
+
"head_limit": {
|
|
246
|
+
type: "integer",
|
|
247
|
+
description: `Cap output lines. Default: 250. Set 0 for unlimited lines. In content mode, context lines (-A/-B/-C) and "--" separators count toward the cap, so the number of matches shown may be lower. Output is independently byte-bounded: each line is clipped to ${MAX_LINE_BYTES} bytes and the total to ${OUTPUT_BYTE_CAP} bytes, so long (e.g. minified) lines never overflow the context window.`
|
|
248
|
+
},
|
|
249
|
+
"offset": {
|
|
250
|
+
type: "integer",
|
|
251
|
+
description: "Skip first N output lines. Default: 0."
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
required: ["pattern"]
|
|
255
|
+
}
|
|
256
|
+
},
|
|
257
|
+
async execute(rawInput, ctx) {
|
|
258
|
+
const input = rawInput;
|
|
259
|
+
const invalid = validateInput(input);
|
|
260
|
+
if (invalid) return `grep error: ${invalid}`;
|
|
261
|
+
try {
|
|
262
|
+
if (await isRipgrepAvailable(ctx)) return await runViaRipgrep(input, ctx);
|
|
263
|
+
return await runFallback(input, ctx);
|
|
264
|
+
} catch (err) {
|
|
265
|
+
if (isAbortLikeError(err)) throw err;
|
|
266
|
+
return `grep error: ${errorMessage(err)}`;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
/**
|
|
271
|
+
* Probe ripgrep availability **per call**. The probe is intentionally not
|
|
272
|
+
* cached: caching at module scope would leak across execution contexts (an
|
|
273
|
+
* orchestrator running an in-process agent and a docker agent in the same
|
|
274
|
+
* Node process must be able to differ on whether `rg` exists), and caching
|
|
275
|
+
* per handle adds bookkeeping for negligible savings — `rg --version` is
|
|
276
|
+
* ~5 ms, and grep is invoked at most a few times per turn.
|
|
277
|
+
*/
|
|
278
|
+
async function isRipgrepAvailable(ctx) {
|
|
279
|
+
return (await ctx.execution.exec(ctx.handle, "rg --version", { signal: ctx.signal })).exitCode === 0;
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Every regex the call matches on: `pattern` plus non-empty `patterns`. An
|
|
283
|
+
* empty `pattern` next to non-empty `patterns` is dropped: it would match
|
|
284
|
+
* every line.
|
|
285
|
+
*/
|
|
286
|
+
function allPatterns(input) {
|
|
287
|
+
const extra = Array.isArray(input.patterns) ? input.patterns.filter((p) => typeof p === "string" && p.length > 0) : [];
|
|
288
|
+
if (input.pattern === "" && extra.length > 0) return extra;
|
|
289
|
+
return [input.pattern, ...extra];
|
|
290
|
+
}
|
|
291
|
+
/** Search roots: `path` and `paths` combined, defaulting to `.`. */
|
|
292
|
+
function searchRoots(input) {
|
|
293
|
+
const roots = [...typeof input.path === "string" && input.path.length > 0 ? [input.path] : [], ...Array.isArray(input.paths) ? input.paths.filter((p) => typeof p === "string" && p.length > 0) : []];
|
|
294
|
+
return roots.length > 0 ? [...new Set(roots)] : ["."];
|
|
295
|
+
}
|
|
296
|
+
function validateInput(input) {
|
|
297
|
+
if (typeof input.pattern !== "string") return "`pattern` must be a string.";
|
|
298
|
+
if (input.patterns !== void 0 && (!Array.isArray(input.patterns) || input.patterns.some((p) => typeof p !== "string"))) return "`patterns` must be an array of strings.";
|
|
299
|
+
if (input.paths !== void 0 && (!Array.isArray(input.paths) || input.paths.some((p) => typeof p !== "string"))) return "`paths` must be an array of strings.";
|
|
300
|
+
if (input.exclude !== void 0) {
|
|
301
|
+
if (typeof input.exclude !== "string") return "`exclude` must be a string.";
|
|
302
|
+
try {
|
|
303
|
+
new RegExp(input.exclude);
|
|
304
|
+
} catch (err) {
|
|
305
|
+
return `invalid exclude regex: ${errorMessage(err)}`;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
async function runViaRipgrep(input, ctx) {
|
|
310
|
+
const args = ["rg"];
|
|
311
|
+
const mode = input.output_mode ?? DEFAULT_OUTPUT_MODE;
|
|
312
|
+
if (mode === "files_with_matches") args.push("--files-with-matches");
|
|
313
|
+
else if (mode === "count") args.push("--count");
|
|
314
|
+
else args.push(input["-n"] ?? true ? "--line-number" : "--no-line-number");
|
|
315
|
+
if (input["-i"]) args.push("-i");
|
|
316
|
+
if (input.fixed_strings) args.push("--fixed-strings");
|
|
317
|
+
if (input["-w"]) args.push("--word-regexp");
|
|
318
|
+
if (mode === "content") {
|
|
319
|
+
if (typeof input["-A"] === "number") args.push("-A", String(input["-A"]));
|
|
320
|
+
if (typeof input["-B"] === "number") args.push("-B", String(input["-B"]));
|
|
321
|
+
if (typeof input["-C"] === "number" && typeof input["-A"] !== "number" && typeof input["-B"] !== "number") args.push("-C", String(input["-C"]));
|
|
322
|
+
}
|
|
323
|
+
if (input.multiline) args.push("--multiline", "--multiline-dotall");
|
|
324
|
+
if (input.gitignore === false) args.push("--no-ignore");
|
|
325
|
+
if (input.glob) args.push("--glob", input.glob);
|
|
326
|
+
if (input.type) args.push("--type", input.type);
|
|
327
|
+
for (const pattern of allPatterns(input)) args.push("-e", pattern);
|
|
328
|
+
args.push("--", ...searchRoots(input));
|
|
329
|
+
const command = args.map(shellQuote).join(" ");
|
|
330
|
+
const result = await ctx.execution.exec(ctx.handle, command, { signal: ctx.signal });
|
|
331
|
+
if (result.exitCode !== 0 && result.exitCode !== 1) return `grep error: ${result.stderr.trim() || `rg exited with code ${result.exitCode}`}`;
|
|
332
|
+
return formatPaginated(result.stdout, input);
|
|
333
|
+
}
|
|
334
|
+
async function runFallback(input, ctx) {
|
|
335
|
+
const mode = input.output_mode ?? DEFAULT_OUTPUT_MODE;
|
|
336
|
+
const flags = `${input["-i"] ? "i" : ""}${input.multiline ? "s" : ""}${mode !== "content" ? "" : "g"}`;
|
|
337
|
+
let regex;
|
|
338
|
+
try {
|
|
339
|
+
regex = new RegExp(fallbackSource(input), flags || void 0);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
return `grep error: invalid regex: ${errorMessage(err)}`;
|
|
342
|
+
}
|
|
343
|
+
const multilineRegex = input.multiline ? new RegExp(regex.source, `${flags.replace(/g/, "")}g`) : void 0;
|
|
344
|
+
const files = [];
|
|
345
|
+
for (const root of searchRoots(input)) for (const file of await enumerateFiles(input, root, ctx)) if (!files.includes(file)) files.push(file);
|
|
346
|
+
const showLineNumbers = input["-n"] ?? true;
|
|
347
|
+
const before = input["-B"] ?? input["-C"] ?? 0;
|
|
348
|
+
const after = input["-A"] ?? input["-C"] ?? 0;
|
|
349
|
+
if (files.length === 1 && searchRoots(input).includes(files[0])) {
|
|
350
|
+
const size = await ctx.execution.fileSize?.(ctx.handle, files[0]) ?? null;
|
|
351
|
+
if (size !== null && size > FALLBACK_MAX_FILE_BYTES) return "(no matches)";
|
|
352
|
+
}
|
|
353
|
+
const lines = [];
|
|
354
|
+
for (const path of files) {
|
|
355
|
+
let content;
|
|
356
|
+
try {
|
|
357
|
+
content = await ctx.execution.readFile(ctx.handle, path);
|
|
358
|
+
} catch (err) {
|
|
359
|
+
if (isAbortLikeError(err)) throw err;
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
if (multilineRegex) {
|
|
363
|
+
const allMatches = [...content.matchAll(multilineRegex)];
|
|
364
|
+
if (allMatches.length === 0) continue;
|
|
365
|
+
if (mode === "files_with_matches") {
|
|
366
|
+
lines.push(path);
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
if (mode === "count") {
|
|
370
|
+
lines.push(`${path}:${allMatches.length}`);
|
|
371
|
+
continue;
|
|
372
|
+
}
|
|
373
|
+
let lineNo = 1;
|
|
374
|
+
let scannedTo = 0;
|
|
375
|
+
for (const m of allMatches) {
|
|
376
|
+
const lineStart = content.lastIndexOf("\n", m.index - 1) + 1;
|
|
377
|
+
const lineEnd = content.indexOf("\n", m.index);
|
|
378
|
+
const snippet = content.slice(lineStart, lineEnd === -1 ? void 0 : lineEnd);
|
|
379
|
+
for (let nl = content.indexOf("\n", scannedTo); nl !== -1 && nl < m.index; nl = content.indexOf("\n", nl + 1)) lineNo++;
|
|
380
|
+
scannedTo = m.index;
|
|
381
|
+
lines.push(formatContentLine(path, lineNo, snippet, showLineNumbers));
|
|
382
|
+
}
|
|
383
|
+
continue;
|
|
384
|
+
}
|
|
385
|
+
const fileLines = content.split("\n");
|
|
386
|
+
const matched = [];
|
|
387
|
+
for (let i = 0; i < fileLines.length; i++) {
|
|
388
|
+
regex.lastIndex = 0;
|
|
389
|
+
if (regex.test(fileLines[i])) matched.push(i);
|
|
390
|
+
}
|
|
391
|
+
if (matched.length === 0) continue;
|
|
392
|
+
if (mode === "files_with_matches") {
|
|
393
|
+
lines.push(path);
|
|
394
|
+
continue;
|
|
395
|
+
}
|
|
396
|
+
if (mode === "count") {
|
|
397
|
+
lines.push(`${path}:${matched.length}`);
|
|
398
|
+
continue;
|
|
399
|
+
}
|
|
400
|
+
const includeLineNos = /* @__PURE__ */ new Set();
|
|
401
|
+
for (const m of matched) for (let i = Math.max(0, m - before); i <= Math.min(fileLines.length - 1, m + after); i++) includeLineNos.add(i);
|
|
402
|
+
const sorted = [...includeLineNos].sort((a, b) => a - b);
|
|
403
|
+
let prev = -2;
|
|
404
|
+
for (const lineNo of sorted) {
|
|
405
|
+
if (lineNo > prev + 1 && lines.length > 0) lines.push("--");
|
|
406
|
+
const snippet = fileLines[lineNo];
|
|
407
|
+
lines.push(formatContentLine(path, lineNo + 1, snippet, showLineNumbers));
|
|
408
|
+
prev = lineNo;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
return formatPaginated(lines.join("\n"), input);
|
|
412
|
+
}
|
|
413
|
+
function formatContentLine(path, lineNo, snippet, showLineNumbers) {
|
|
414
|
+
return showLineNumbers ? `${path}:${lineNo}:${snippet}` : `${path}:${snippet}`;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* JS regex source for the fallback: patterns OR'ed together, escaped under
|
|
418
|
+
* `fixed_strings`, wrapped in word boundaries under `-w`.
|
|
419
|
+
*/
|
|
420
|
+
function fallbackSource(input) {
|
|
421
|
+
const parts = allPatterns(input).map((p) => input.fixed_strings ? p.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") : p);
|
|
422
|
+
const joined = parts.length === 1 ? parts[0] : parts.map((p) => `(?:${p})`).join("|");
|
|
423
|
+
return input["-w"] ? `\\b(?:${joined})\\b` : joined;
|
|
424
|
+
}
|
|
425
|
+
async function enumerateFiles(input, root, ctx) {
|
|
426
|
+
if (root !== "." && !root.includes("*") && !root.includes("?")) {
|
|
427
|
+
if ((await ctx.execution.exec(ctx.handle, `test -f ${shellQuote(root)} && echo file || echo dir`, { signal: ctx.signal })).stdout.trim() === "file") return [root];
|
|
428
|
+
}
|
|
429
|
+
const result = await ctx.execution.exec(ctx.handle, buildFindCommand(root, input.glob), { signal: ctx.signal });
|
|
430
|
+
if (result.exitCode !== 0 && !result.stdout.trim()) throw new Error(result.stderr.trim() || `find exited with code ${result.exitCode}`);
|
|
431
|
+
const files = result.stdout.split("\n").map((line) => line.replace(/^\.\//, "")).filter((line) => line.length > 0).sort();
|
|
432
|
+
if (input.gitignore === false) return files;
|
|
433
|
+
return filterByGitignore(files, root, ctx);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Best-effort intersection of `files` with `git ls-files` (non-ignored set).
|
|
437
|
+
* Returns `files` unchanged when git is unavailable, the dir isn't a repo, or
|
|
438
|
+
* `root` escapes the repo (absolute / `..`) — the filter can only fail open.
|
|
439
|
+
*/
|
|
440
|
+
async function filterByGitignore(files, root, ctx) {
|
|
441
|
+
if (files.length === 0) return files;
|
|
442
|
+
if (root !== "." && (root.startsWith("/") || root.split("/").includes(".."))) return files;
|
|
443
|
+
try {
|
|
444
|
+
const res = await ctx.execution.exec(ctx.handle, GIT_LS_FILES_COMMAND, { signal: ctx.signal });
|
|
445
|
+
if (res.exitCode !== 0) return files;
|
|
446
|
+
const allowed = new Set(parseGitLsFiles(res.stdout));
|
|
447
|
+
if (allowed.size === 0) return files;
|
|
448
|
+
return files.filter((file) => allowed.has(file));
|
|
449
|
+
} catch {
|
|
450
|
+
return files;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Build a `find` command listing files under `root`, optionally filtered by
|
|
455
|
+
* `glob`. Mirrors `glob`'s shell fallback:
|
|
456
|
+
* - a bare basename, or one behind a leading recursive-wildcard segment,
|
|
457
|
+
* with no inner slash → `-name` (matches at any depth, including the top
|
|
458
|
+
* level — preserving the recursive-glob semantics).
|
|
459
|
+
* - anything with a slash → `-path` against the full relative path. `find`'s
|
|
460
|
+
* `*` spans `/`, so the single- and double-star forms collapse to the
|
|
461
|
+
* same matcher; close enough for the no-`rg` fallback.
|
|
462
|
+
*/
|
|
463
|
+
function buildFindCommand(root, glob) {
|
|
464
|
+
const findRoot = normalizeFindRoot(root);
|
|
465
|
+
const base = shellQuote(findRoot);
|
|
466
|
+
const sizeGuard = `! -size +${FALLBACK_MAX_FILE_BYTES}c`;
|
|
467
|
+
if (!glob) return `find ${base} -type f ${sizeGuard}`;
|
|
468
|
+
const anyDepth = glob.match(/^(?:\*\*\/)?([^/]+)$/);
|
|
469
|
+
if (anyDepth) return `find ${base} -type f ${sizeGuard} -name ${shellQuote(anyDepth[1])}`;
|
|
470
|
+
const normRoot = findRoot.replace(/\/$/, "");
|
|
471
|
+
const pathPattern = root === "." ? `./${glob}` : `${normRoot}/${glob}`;
|
|
472
|
+
return `find ${base} -type f ${sizeGuard} -path ${shellQuote(pathPattern)}`;
|
|
473
|
+
}
|
|
474
|
+
function normalizeFindRoot(root) {
|
|
475
|
+
return root.startsWith("-") ? `./${root}` : root;
|
|
476
|
+
}
|
|
477
|
+
function formatPaginated(text, input) {
|
|
478
|
+
const headLimit = typeof input.head_limit === "number" && input.head_limit >= 0 ? input.head_limit : DEFAULT_HEAD_LIMIT;
|
|
479
|
+
const offset = typeof input.offset === "number" && input.offset > 0 ? Math.floor(input.offset) : 0;
|
|
480
|
+
if (!text.trim()) return "(no matches)";
|
|
481
|
+
const lines = applyExclude(text.split("\n").filter((l) => l.length > 0), input.exclude);
|
|
482
|
+
if (lines.length === 0) return "(no matches after exclude)";
|
|
483
|
+
const total = lines.length;
|
|
484
|
+
const sliced = headLimit === 0 ? lines.slice(offset) : lines.slice(offset, offset + headLimit);
|
|
485
|
+
if (sliced.length === 0) return "(no matches in this slice)";
|
|
486
|
+
const capped = [];
|
|
487
|
+
let bytesUsed = 0;
|
|
488
|
+
let byteCut = false;
|
|
489
|
+
for (const line of sliced) {
|
|
490
|
+
const clipped = clipLine(line);
|
|
491
|
+
const lineBytes = Buffer.byteLength(clipped) + 1;
|
|
492
|
+
if (bytesUsed + lineBytes > OUTPUT_BYTE_CAP && capped.length > 0) {
|
|
493
|
+
byteCut = true;
|
|
494
|
+
break;
|
|
495
|
+
}
|
|
496
|
+
capped.push(clipped);
|
|
497
|
+
bytesUsed += lineBytes;
|
|
498
|
+
}
|
|
499
|
+
const shown = capped.length;
|
|
500
|
+
const truncatedHead = offset > 0;
|
|
501
|
+
const lineCutTail = headLimit > 0 && offset + headLimit < total;
|
|
502
|
+
let out = capped.join("\n");
|
|
503
|
+
if (truncatedHead) out = `…(${offset} earlier lines skipped)…\n${out}`;
|
|
504
|
+
if (byteCut) out = `${out}\n…(output truncated at ${OUTPUT_BYTE_CAP} bytes after ${shown} of ${total - offset} matching lines; narrow the pattern or page with offset=${offset + shown})`;
|
|
505
|
+
else if (lineCutTail) out = `${out}\n…(${total - offset - headLimit} more lines; re-run with offset=${offset + headLimit} or larger head_limit)`;
|
|
506
|
+
return out;
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Drop output lines matching `exclude` (validated upfront). Context-group
|
|
510
|
+
* `--` separators are kept only between surviving lines, never doubled or at
|
|
511
|
+
* the edges.
|
|
512
|
+
*/
|
|
513
|
+
function applyExclude(lines, exclude) {
|
|
514
|
+
if (!exclude) return lines;
|
|
515
|
+
const re = new RegExp(exclude);
|
|
516
|
+
const kept = [];
|
|
517
|
+
for (const line of lines) {
|
|
518
|
+
if (line === "--") {
|
|
519
|
+
if (kept.length > 0 && kept[kept.length - 1] !== "--") kept.push(line);
|
|
520
|
+
continue;
|
|
521
|
+
}
|
|
522
|
+
if (!re.test(line)) kept.push(line);
|
|
523
|
+
}
|
|
524
|
+
while (kept.length > 0 && kept[kept.length - 1] === "--") kept.pop();
|
|
525
|
+
return kept;
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Clip one output line to `MAX_LINE_BYTES` at a UTF-8-safe boundary, appending
|
|
529
|
+
* a marker that reports how many bytes were withheld. Lines within budget pass
|
|
530
|
+
* through untouched.
|
|
531
|
+
*/
|
|
532
|
+
function clipLine(line) {
|
|
533
|
+
if (Buffer.byteLength(line) <= MAX_LINE_BYTES) return line;
|
|
534
|
+
let cut = Math.min(line.length, MAX_LINE_BYTES);
|
|
535
|
+
while (cut > 0 && Buffer.byteLength(line.slice(0, cut)) > MAX_LINE_BYTES) cut--;
|
|
536
|
+
const omitted = Buffer.byteLength(line) - Buffer.byteLength(line.slice(0, cut));
|
|
537
|
+
return `${line.slice(0, cut)}… [line clipped, ${omitted} more bytes]`;
|
|
538
|
+
}
|
|
539
|
+
//#endregion
|
|
540
|
+
//#region src/tools/interaction.ts
|
|
541
|
+
function abortReason(signal) {
|
|
542
|
+
return typeof signal.reason === "string" && signal.reason.length > 0 ? signal.reason : "Interaction aborted";
|
|
543
|
+
}
|
|
544
|
+
/**
|
|
545
|
+
* Create an interaction tool that lets the agent request structured input.
|
|
546
|
+
*
|
|
547
|
+
* The model calls this tool with a payload matching the schema.
|
|
548
|
+
* `onRequest` is called with the payload and should return the response
|
|
549
|
+
* (string or object) that gets sent back to the model as the tool result.
|
|
550
|
+
*/
|
|
551
|
+
function createInteractionTool(options) {
|
|
552
|
+
return {
|
|
553
|
+
spec: {
|
|
554
|
+
name: options.name ?? "interaction",
|
|
555
|
+
description: options.description ?? toolPrompts.interaction,
|
|
556
|
+
inputSchema: options.schema
|
|
557
|
+
},
|
|
558
|
+
async execute(input, ctx) {
|
|
559
|
+
const { signal } = ctx;
|
|
560
|
+
if (signal?.aborted) throw new Error(abortReason(signal));
|
|
561
|
+
let onAbort;
|
|
562
|
+
const abortPromise = signal ? new Promise((_, reject) => {
|
|
563
|
+
onAbort = () => reject(new Error(abortReason(signal)));
|
|
564
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
565
|
+
}) : void 0;
|
|
566
|
+
try {
|
|
567
|
+
const result = abortPromise ? await Promise.race([options.onRequest(input, ctx), abortPromise]) : await options.onRequest(input, ctx);
|
|
568
|
+
return typeof result === "string" ? result : JSON.stringify(result);
|
|
569
|
+
} finally {
|
|
570
|
+
if (signal && onAbort) signal.removeEventListener("abort", onAbort);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
};
|
|
574
|
+
}
|
|
575
|
+
//#endregion
|
|
576
|
+
export { grep as n, glob as r, createInteractionTool as t };
|
|
577
|
+
|
|
578
|
+
//# sourceMappingURL=tools-_DnT3AGM.js.map
|