tarsk 0.6.87 → 0.6.89
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -24
- package/dist/bundled-skills/email-me/SKILL.md +15 -0
- package/dist/bundled-skills/email-me/scripts/__tests__/email_me.test.js +64 -0
- package/dist/bundled-skills/email-me/scripts/email_me.js +45 -0
- package/dist/bundled-skills/handoff/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-agent/SKILL.md +372 -0
- package/dist/bundled-skills/tarsk-ask-user/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-ask-user/scripts/ask_user.js +101 -0
- package/dist/bundled-skills/tarsk-bash/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-bash/scripts/bash.js +248 -0
- package/dist/bundled-skills/tarsk-browser/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-browser/scripts/browser.js +252 -0
- package/dist/bundled-skills/tarsk-chat-title/SKILL.md +14 -0
- package/dist/bundled-skills/tarsk-chat-title/scripts/chat_title.js +37 -0
- package/dist/bundled-skills/tarsk-connect-mcp/SKILL.md +23 -0
- package/dist/bundled-skills/tarsk-connect-mcp/scripts/__tests__/connect_mcp.test.js +68 -0
- package/dist/bundled-skills/tarsk-connect-mcp/scripts/connect_mcp.js +119 -0
- package/dist/bundled-skills/tarsk-create-project/SKILL.md +25 -0
- package/dist/bundled-skills/tarsk-create-project/scripts/__tests__/create_project.test.js +94 -0
- package/dist/bundled-skills/tarsk-create-project/scripts/create_project.js +88 -0
- package/dist/bundled-skills/tarsk-edit/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-edit/scripts/edit.js +118 -0
- package/dist/bundled-skills/tarsk-execute-skill-script/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-execute-skill-script/scripts/execute_skill_script.js +77 -0
- package/dist/bundled-skills/tarsk-fetch/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-fetch/scripts/fetch.js +38 -0
- package/dist/bundled-skills/tarsk-find/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-find/scripts/find.js +78 -0
- package/dist/bundled-skills/tarsk-find-images/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-find-images/scripts/find_images.js +78 -0
- package/dist/bundled-skills/tarsk-generate-image/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-generate-image/scripts/generate_image.js +55 -0
- package/dist/bundled-skills/tarsk-get-observation/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-get-observation/scripts/get_observation.js +293 -0
- package/dist/bundled-skills/tarsk-grep/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-grep/scripts/grep.js +174 -0
- package/dist/bundled-skills/tarsk-history/SKILL.md +15 -0
- package/dist/bundled-skills/tarsk-history/scripts/history.js +68 -0
- package/dist/bundled-skills/tarsk-improve/SKILL.md +232 -0
- package/dist/bundled-skills/tarsk-improve/references/signals.md +16 -0
- package/dist/bundled-skills/tarsk-improve/scripts/durable-runs.ts +635 -0
- package/dist/bundled-skills/tarsk-improve/scripts/ensure-exported.ts +238 -0
- package/dist/bundled-skills/tarsk-improve/scripts/export-tool-skills-lib.ts +299 -0
- package/dist/bundled-skills/tarsk-improve/scripts/summarize-session.ts +126 -0
- package/dist/bundled-skills/tarsk-jobs/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_kill.js +45 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_list.js +64 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_output.js +66 -0
- package/dist/bundled-skills/tarsk-notes/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-notes/scripts/notes.js +86 -0
- package/dist/bundled-skills/tarsk-projects/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-projects/scripts/projects.js +54 -0
- package/dist/bundled-skills/tarsk-prompt-project/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-prompt-project/scripts/prompt_project.js +58 -0
- package/dist/bundled-skills/tarsk-propose-branch/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-propose-branch/scripts/propose_branch.js +45 -0
- package/dist/bundled-skills/tarsk-read/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-read/scripts/read.js +331 -0
- package/dist/bundled-skills/tarsk-read-skill/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-read-skill/scripts/read_skill.js +37 -0
- package/dist/bundled-skills/tarsk-read-skill-reference/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-read-skill-reference/scripts/read_skill_reference.js +60 -0
- package/dist/bundled-skills/tarsk-run-js/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-run-js/scripts/run_js.js +192 -0
- package/dist/bundled-skills/tarsk-tasks/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-tasks/scripts/tasks.js +96 -0
- package/dist/bundled-skills/tarsk-todo/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-todo/scripts/todo.js +165 -0
- package/dist/bundled-skills/tarsk-web-search/SKILL.md +15 -0
- package/dist/bundled-skills/tarsk-web-search/scripts/web_search.js +120 -0
- package/dist/bundled-skills/tarsk-write/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-write/scripts/write.js +57 -0
- package/dist/index.js +217754 -211927
- package/dist/public/assets/{alert-dialog-DVaEQlVa.js → alert-dialog-BcZULJsX.js} +1 -1
- package/dist/public/assets/api-8Rp2LlXt.js +1 -0
- package/dist/public/assets/api-Cp9I7CxD.js +2 -0
- package/dist/public/assets/{async-error-boundary-DH6Sqgmt.js → async-error-boundary-CFVUPiuG.js} +1 -1
- package/dist/public/assets/browser-tab-CPPorbL6.js +12 -0
- package/dist/public/assets/button-DDaJhJP1.js +1 -0
- package/dist/public/assets/{card-BkOGFps5.js → card-DAc45J1v.js} +1 -1
- package/dist/public/assets/chat-dock-context-DbiJNr3O.js +1 -0
- package/dist/public/assets/chat-handlers-context-DYU2LQ5V.js +9 -0
- package/dist/public/assets/commit-dialog-DPaci3dp.js +1 -0
- package/dist/public/assets/{commit-error-dialog-D3S6kRVr.js → commit-error-dialog-Dnlkgb_H.js} +1 -1
- package/dist/public/assets/{commit-method-fields-BEKfSRyW.js → commit-method-fields-Xt3vbwUg.js} +1 -1
- package/dist/public/assets/conversation-history-view-CqIugfyO.js +1 -0
- package/dist/public/assets/{create-project-dialog-nquqlloK.js → create-project-dialog-DStWPoDE.js} +2 -2
- package/dist/public/assets/{create-project-workspace-C4tXAUWJ.js → create-project-workspace-CJ94yHAB.js} +2 -2
- package/dist/public/assets/create-repo-dialog-B_QiEz-v.js +1 -0
- package/dist/public/assets/{delete-confirm-dialog-SpYpU1AX.js → delete-confirm-dialog-D1N86piR.js} +1 -1
- package/dist/public/assets/dialog-D_12AsZd.js +1 -0
- package/dist/public/assets/diff-view-4koPcOcE.js +4 -0
- package/dist/public/assets/{dist-NcyjV9Gu.js → dist-2xH_pFmV.js} +1 -1
- package/dist/public/assets/{dist-BTu7PDzc.js → dist-AbkJBHH5.js} +1 -1
- package/dist/public/assets/{dist-lFBinzor.js → dist-B-h6Wj39.js} +1 -1
- package/dist/public/assets/dist-CgbWuuq4.js +1 -0
- package/dist/public/assets/{dist-f54JuzFV.js → dist-DOz2WXwX.js} +1 -1
- package/dist/public/assets/{dist-CqrmQxmV.js → dist-DfnQ9YJh.js} +1 -1
- package/dist/public/assets/{dist-BOfRC57H.js → dist-JGbQ_EJY.js} +1 -1
- package/dist/public/assets/{dist-ButPmyjr.js → dist-pCVg1Jdl.js} +1 -1
- package/dist/public/assets/dist-v_MvKS2-.js +2 -0
- package/dist/public/assets/{es2015-CE7VcoOH.js → es2015-eNVkKfFF.js} +1 -1
- package/dist/public/assets/{explorer-file-drop-CEbBlDEp.js → explorer-file-drop-DAP7ha-E.js} +1 -1
- package/dist/public/assets/{explorer-monaco-editor-Bgo9Y1cP.js → explorer-monaco-editor-ChJZBFy5.js} +1 -1
- package/dist/public/assets/explorer-tab-view-Bt9hRZUm.js +2 -0
- package/dist/public/assets/explorer-tree-CAs89lPz.js +1 -0
- package/dist/public/assets/{explorer-view-BuTa_0Uq.js → explorer-view-B1JuejkU.js} +3 -3
- package/dist/public/assets/git-history-dialog-Dqj1p35g.js +1 -0
- package/dist/public/assets/index-CcAwxnT5.js +97 -0
- package/dist/public/assets/index-dNrgKdYv.css +1 -0
- package/dist/public/assets/{label-C31qF5zZ.js → label-BCs5CZEs.js} +1 -1
- package/dist/public/assets/markdown-renderer-DQONI6WG.js +10 -0
- package/dist/public/assets/{mcp-manager-C3K_62H2.js → mcp-manager-D2FG-h2e.js} +1 -1
- package/dist/public/assets/{minus-l6BdrAEk.js → minus-CgQcbBQT.js} +1 -1
- package/dist/public/assets/{model-list-controls-DwW8S18v.js → model-list-controls-B6ofHWh3.js} +1 -1
- package/dist/public/assets/onboarding-dialog-DAut3X4K.js +1 -0
- package/dist/public/assets/{pill-tabs-CmvvHdKG.js → pill-tabs-BAhOHad7.js} +1 -1
- package/dist/public/assets/progress-indicator-hJ74ac5W.js +1 -0
- package/dist/public/assets/project-coding-view-B2FpHeiO.js +1 -0
- package/dist/public/assets/{project-danger-zone-view-D18k4pUF.js → project-danger-zone-view-BqP1dcRT.js} +1 -1
- package/dist/public/assets/{project-env-vars-view-BWFqoaFD.js → project-env-vars-view-zhigkQFG.js} +1 -1
- package/dist/public/assets/project-model-aliases-view-APAVFfym.js +1 -0
- package/dist/public/assets/project-settings-view-FnK-LRsv.js +1 -0
- package/dist/public/assets/project-tools-view-Dmp5ViRC.js +1 -0
- package/dist/public/assets/providers-list-view-Clbp73Hh.js +1 -0
- package/dist/public/assets/pull-request-dialog-D40BQPMk.js +1 -0
- package/dist/public/assets/pull-with-changes-dialog-pkXK-VP2.js +1 -0
- package/dist/public/assets/push-before-pr-dialog-DH91JHEC.js +1 -0
- package/dist/public/assets/query-keys-CcnonAAG.js +1 -0
- package/dist/public/assets/remote-media-url-C-GdJb-D.js +1 -0
- package/dist/public/assets/{scroll-area-BWc4OPsj.js → scroll-area-DGF9wUqQ.js} +1 -1
- package/dist/public/assets/{select-B6RizwDW.js → select-DMcNYwgt.js} +1 -1
- package/dist/public/assets/settings-general-tabs-view-DBZQbihJ.js +2 -0
- package/dist/public/assets/settings-general-view-0dhBET2R.js +1 -0
- package/dist/public/assets/{settings-list-D35rpAof.js → settings-list-Co3JPr9w.js} +1 -1
- package/dist/public/assets/settings-logs-view-DvHXUDko.js +5 -0
- package/dist/public/assets/settings-mcp-servers-view-414Dt5py.js +5 -0
- package/dist/public/assets/settings-models-view-ByeR7Enb.js +1 -0
- package/dist/public/assets/settings-plugins-view-8te2MPyh.js +2 -0
- package/dist/public/assets/settings-providers-view-BAuv9gam.js +2 -0
- package/dist/public/assets/settings-remote-machines-view-CHyywazU.js +1 -0
- package/dist/public/assets/settings-setup-view-Btp46Vh_.js +2 -0
- package/dist/public/assets/settings-skills-view-BNVx4bZl.js +2 -0
- package/dist/public/assets/{settings-slack-view-DkclyaBc.js → settings-slack-view-Caly5yGt.js} +1 -1
- package/dist/public/assets/settings-slash-commands-view-m6mp1knu.js +1 -0
- package/dist/public/assets/{settings-statistics-view-B03ZZjEy.js → settings-statistics-view-BnOxr4sZ.js} +1 -1
- package/dist/public/assets/settings-storage-view-Dg8xfpTG.js +1 -0
- package/dist/public/assets/settings-subagents-view-CucwEk2A.js +2 -0
- package/dist/public/assets/settings-system-prompt-view-CEDU2saT.js +1 -0
- package/dist/public/assets/{settings-tab-bar-ajzyt79U.js → settings-tab-bar-CdIbQ0WI.js} +1 -1
- package/dist/public/assets/settings-view-XcJhRclT.js +2 -0
- package/dist/public/assets/{slug-utils-D2jhPz-o.js → slug-utils-CO6nui1C.js} +1 -1
- package/dist/public/assets/square-CtxvwmM2.js +1 -0
- package/dist/public/assets/store-W78TGOIO.js +8 -0
- package/dist/public/assets/{table-C3Hc0Gwy.js → table-CQMqIW_-.js} +1 -1
- package/dist/public/assets/task-utils-Cnq9Eszt.js +1 -0
- package/dist/public/assets/tasks-view-B8_jkq_a.js +1 -0
- package/dist/public/assets/{terminal-panel-DCKqScJu.js → terminal-panel-xoLVfA-h.js} +2 -2
- package/dist/public/assets/{toggle-group-DqSxGqvP.js → toggle-group-CPmseZfb.js} +1 -1
- package/dist/public/assets/{tooltip-CJKJfu0l.js → tooltip-CqwCZ7wt.js} +1 -1
- package/dist/public/assets/{use-account-settings-query-AUeOqKvo.js → use-account-settings-query-D_qL1I4w.js} +1 -1
- package/dist/public/assets/{use-active-dock-panel-instance-BvAhUd_V.js → use-active-dock-panel-instance-kmJOnmL7.js} +1 -1
- package/dist/public/assets/use-browser-overlay-block-CO1pUEAZ.js +1 -0
- package/dist/public/assets/{use-git-check-B_5Jak2s.js → use-git-check-BD9gdXpK.js} +1 -1
- package/dist/public/assets/{use-installed-ai-files-iy_AB0dN.js → use-installed-ai-files-Nn-sN_V2.js} +1 -1
- package/dist/public/assets/use-open-chat-dock-panel-CXzpgxVs.js +1 -0
- package/dist/public/assets/{use-projects-BmhAMgxB.js → use-projects-B0xTjTaA.js} +2 -2
- package/dist/public/assets/utils-CqsIXqSC.js +1 -0
- package/dist/public/assets/web-BNWoiS4w.js +1 -0
- package/dist/public/assets/web-C1tBQoCB.js +1 -0
- package/dist/public/assets/web-Dlo3GwCf.js +1 -0
- package/dist/public/assets/web-cJXG33sT.js +1 -0
- package/dist/public/fonts/schibsted-grotesk-latin-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/public/index.html +46 -46
- package/package.json +9 -9
- package/dist/public/assets/account-view-5q3pHEHY.js +0 -1
- package/dist/public/assets/ai-spinner-DHwhlk4j.js +0 -1
- package/dist/public/assets/api-BdebJfuN.js +0 -1
- package/dist/public/assets/api-COO2LfdU.js +0 -2
- package/dist/public/assets/browser-overlay-block-CiDtkfup.js +0 -1
- package/dist/public/assets/browser-tab-CVdYLmW5.js +0 -12
- package/dist/public/assets/button-Dp5XDZNR.js +0 -1
- package/dist/public/assets/chat-dock-context-ymLoO90X.js +0 -1
- package/dist/public/assets/checkbox-D-BV8-Z_.js +0 -1
- package/dist/public/assets/commit-dialog-CEbCFh1x.js +0 -1
- package/dist/public/assets/conversation-history-view-CVMD8hUU.js +0 -1
- package/dist/public/assets/create-repo-dialog-B5IE3pUJ.js +0 -1
- package/dist/public/assets/dialog-pHPeIGaB.js +0 -1
- package/dist/public/assets/diff-view-Cy6nPdX-.js +0 -4
- package/dist/public/assets/dist-D5vgS4RP.js +0 -2
- package/dist/public/assets/explorer-tab-view-C-8QZO9S.js +0 -2
- package/dist/public/assets/explorer-tree-HrLSFgcI.js +0 -1
- package/dist/public/assets/git-history-dialog-ClfF5IOn.js +0 -1
- package/dist/public/assets/index-BBLA5zVt.css +0 -1
- package/dist/public/assets/index-CalVAwXj.js +0 -104
- package/dist/public/assets/markdown-renderer-DXRBG7uP.js +0 -10
- package/dist/public/assets/onboarding-dialog-BtLy0wjC.js +0 -1
- package/dist/public/assets/progress-indicator-4zQXqOqP.js +0 -1
- package/dist/public/assets/project-coding-view-CyJwnJes.js +0 -1
- package/dist/public/assets/project-model-aliases-view-D3tYNkkM.js +0 -1
- package/dist/public/assets/project-settings-view-0oN9vFvD.js +0 -1
- package/dist/public/assets/project-tools-view-DT87KPjE.js +0 -1
- package/dist/public/assets/providers-list-view-DCnh0W-5.js +0 -1
- package/dist/public/assets/pull-request-dialog-BdJxYQwu.js +0 -1
- package/dist/public/assets/pull-with-changes-dialog-Do9x9neW.js +0 -1
- package/dist/public/assets/push-before-pr-dialog-C-9z2O0-.js +0 -1
- package/dist/public/assets/query-keys-BwswkbMn.js +0 -1
- package/dist/public/assets/remote-media-url-B8OFqxOM.js +0 -1
- package/dist/public/assets/settings-general-tabs-view-Dcek-ysB.js +0 -2
- package/dist/public/assets/settings-general-view-DhA2N6G5.js +0 -1
- package/dist/public/assets/settings-logs-view-eEUTIMeb.js +0 -5
- package/dist/public/assets/settings-mcp-servers-view-_oeuVkUe.js +0 -5
- package/dist/public/assets/settings-models-view-DW-ZmVup.js +0 -1
- package/dist/public/assets/settings-plugins-view-DTooco_c.js +0 -2
- package/dist/public/assets/settings-providers-view-CEeJkhg9.js +0 -2
- package/dist/public/assets/settings-remote-machines-view--UB8GlCK.js +0 -1
- package/dist/public/assets/settings-setup-view-DFL6DlYS.js +0 -2
- package/dist/public/assets/settings-skills-view-xS569-Kb.js +0 -2
- package/dist/public/assets/settings-slash-commands-view-DrCiayfq.js +0 -1
- package/dist/public/assets/settings-storage-view-CQnaVOt_.js +0 -1
- package/dist/public/assets/settings-subagents-view-DIctUJcE.js +0 -2
- package/dist/public/assets/settings-system-prompt-view-BMDbrFRR.js +0 -1
- package/dist/public/assets/settings-view-8M6sbGiX.js +0 -2
- package/dist/public/assets/store-CxUwqrZ5.js +0 -8
- package/dist/public/assets/task-utils-WAei2PDi.js +0 -1
- package/dist/public/assets/tasks-view-DKyqgGdE.js +0 -1
- package/dist/public/assets/use-browser-overlay-block-z9imTmiZ.js +0 -1
- package/dist/public/assets/use-open-chat-dock-panel-w3hc5Vxn.js +0 -1
- package/dist/public/assets/utils-mYB1USG6.js +0 -1
- package/dist/public/assets/web-C6Gm4nQ0.js +0 -1
- package/dist/public/assets/web-DFlyNg8o.js +0 -1
- package/dist/public/assets/web-DlEPs8Xe.js +0 -1
- package/dist/public/assets/web-Gx3xReQH.js +0 -1
- package/dist/public/backgrounds/arctic-tundra.avif +0 -0
- package/dist/public/backgrounds/autumn-leaves.avif +0 -0
- package/dist/public/backgrounds/coastal-cliff.avif +0 -0
- package/dist/public/backgrounds/floating-waterfall.avif +0 -0
- package/dist/public/backgrounds/forest-path.avif +0 -0
- package/dist/public/backgrounds/garden-path.avif +0 -0
- package/dist/public/backgrounds/glow-marsh.avif +0 -0
- package/dist/public/backgrounds/golden-wheat.avif +0 -0
- package/dist/public/backgrounds/moon-desert.avif +0 -0
- package/dist/public/backgrounds/night-pond.avif +0 -0
- package/dist/public/backgrounds/prairie-grassland.avif +0 -0
- package/dist/public/backgrounds/river-winding.avif +0 -0
- package/dist/public/backgrounds/salt-flat.avif +0 -0
- package/dist/public/backgrounds/salt-marsh.avif +0 -0
- package/dist/public/backgrounds/sandy-beach.avif +0 -0
- package/dist/public/backgrounds/snow-river.avif +0 -0
- package/dist/public/backgrounds/sunset-pond.avif +0 -0
- package/dist/public/fonts/plus-jakarta-sans-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
- package/dist/public/fonts/plus-jakarta-sans-vietnamese-wght-normal.woff2 +0 -0
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* get_observation — paging, JSON path, and model copy live here (malleable).
|
|
3
|
+
* Host: context.observations resolveId / fetch / recordRetrieved (DB only).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const description =
|
|
7
|
+
"Page a narrow slice of a stored observation by ID (tool output or over-threshold user message). Never walk the whole body with repeated max pages — prefer path (JSON), a small limit, or re-run the producing tool with a tighter command. Default 40 lines; max 80 lines / 50.0KB per ID. Batch with ids (max 20) — ids wins over a stray id. offset/limit are stored-output line indexes, not source-file or grep line numbers. Do not use for read results — call read on the file. Extra or missing hex in the id is repaired. Thread-scoped.";
|
|
8
|
+
|
|
9
|
+
export const parameters = {
|
|
10
|
+
type: "object",
|
|
11
|
+
properties: {
|
|
12
|
+
id: {
|
|
13
|
+
description:
|
|
14
|
+
"Observation ID from a tool-result or user-message preview (obs_ + 64 hex). Extra or missing hex is repaired.",
|
|
15
|
+
maxLength: 200,
|
|
16
|
+
minLength: 12,
|
|
17
|
+
type: "string",
|
|
18
|
+
},
|
|
19
|
+
ids: {
|
|
20
|
+
minItems: 1,
|
|
21
|
+
maxItems: 20,
|
|
22
|
+
description: "Batch retrieval; prefer this over parallel calls.",
|
|
23
|
+
type: "array",
|
|
24
|
+
items: {
|
|
25
|
+
description:
|
|
26
|
+
"Observation ID from a tool-result or user-message preview (obs_ + 64 hex). Extra or missing hex is repaired.",
|
|
27
|
+
maxLength: 200,
|
|
28
|
+
minLength: 12,
|
|
29
|
+
type: "string",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
offset: { minimum: 1, type: "integer" },
|
|
33
|
+
limit: { maximum: 80, minimum: 1, type: "integer" },
|
|
34
|
+
path: { minLength: 1, maxLength: 500, type: "string" },
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
/** Keep miss guidance byte-stable so prompt-cache prefixes stay warm. */
|
|
39
|
+
const MISS_RETRY =
|
|
40
|
+
"Thread-scoped: the id may be from another thread or expired. Re-run the producing tool or page a recent observation id; do not retry this id verbatim.";
|
|
41
|
+
|
|
42
|
+
function resolveJsonSegment(path, segment, value) {
|
|
43
|
+
if (segment.length === 0) {
|
|
44
|
+
throw new Error(`JSON path "${path}" empty segment.`);
|
|
45
|
+
}
|
|
46
|
+
if (Array.isArray(value)) {
|
|
47
|
+
if (!/^\d+$/.test(segment)) {
|
|
48
|
+
throw new Error(`JSON path "${path}" expected an array index at "${segment}".`);
|
|
49
|
+
}
|
|
50
|
+
const index = Number(segment);
|
|
51
|
+
if (index >= value.length) {
|
|
52
|
+
throw new Error(`JSON path "${path}" array index ${index} is out of bounds.`);
|
|
53
|
+
}
|
|
54
|
+
return value[index];
|
|
55
|
+
}
|
|
56
|
+
if (value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, segment)) {
|
|
57
|
+
return value[segment];
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`JSON path "${path}" does not contain segment "${segment}".`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function selectJsonPath(content, path) {
|
|
63
|
+
let value;
|
|
64
|
+
try {
|
|
65
|
+
value = JSON.parse(content);
|
|
66
|
+
} catch {
|
|
67
|
+
throw new Error("Observation content is not valid JSON; omit path to retrieve it by lines.");
|
|
68
|
+
}
|
|
69
|
+
for (const segment of path.split(".")) {
|
|
70
|
+
value = resolveJsonSegment(path, segment, value);
|
|
71
|
+
}
|
|
72
|
+
return typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function resolveIds(args) {
|
|
76
|
+
// `ids` wins over a stray `id`: both keys together is a common habit, and
|
|
77
|
+
// failing the call costs a turn when the batch is already unambiguous.
|
|
78
|
+
if (Array.isArray(args.ids) && args.ids.length > 0) {
|
|
79
|
+
return args.ids.map(String);
|
|
80
|
+
}
|
|
81
|
+
if (typeof args.id === "string" && args.id) return [args.id];
|
|
82
|
+
throw new Error("Provide id or ids.");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function assembleBlock(id, lineRange, content, jsonPath, suffix) {
|
|
86
|
+
const parts = [
|
|
87
|
+
`<observation_data id="${id}" lines="${lineRange}">`,
|
|
88
|
+
jsonPath ? `[JSON path: ${jsonPath}]` : undefined,
|
|
89
|
+
content,
|
|
90
|
+
"</observation_data>",
|
|
91
|
+
];
|
|
92
|
+
if (suffix !== undefined) parts.push(suffix);
|
|
93
|
+
return parts.filter((line) => line !== undefined).join("\n");
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function lineByteLength(line) {
|
|
97
|
+
return Buffer.byteLength(line, "utf-8");
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function formatOversizedLine(lineNumber, line, maxBytes, formatSize) {
|
|
101
|
+
return `Line ${lineNumber} is ${formatSize(lineByteLength(line))} and exceeds the ${formatSize(maxBytes)} retrieval limit (elided)`;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function nextReadableOffset(lines, fromOneIndexed, maxBytes) {
|
|
105
|
+
const start = Math.max(0, fromOneIndexed - 1);
|
|
106
|
+
for (let i = start; i < lines.length; i++) {
|
|
107
|
+
if (lineByteLength(lines[i] ?? "") <= maxBytes) return i + 1;
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function formatContinuation(lines, offset, endLine, maxBytes, formatSize) {
|
|
113
|
+
const total = lines.length;
|
|
114
|
+
if (endLine >= total) {
|
|
115
|
+
return `\n\n[Showing lines ${offset}-${endLine} of ${total}.]`;
|
|
116
|
+
}
|
|
117
|
+
const nextLine = lines[endLine];
|
|
118
|
+
if (nextLine === undefined || lineByteLength(nextLine) <= maxBytes) {
|
|
119
|
+
return `\n\n[Showing lines ${offset}-${endLine} of ${total}. Use offset=${endLine + 1} to continue.]`;
|
|
120
|
+
}
|
|
121
|
+
const skipped = [];
|
|
122
|
+
let index = endLine;
|
|
123
|
+
while (index < lines.length) {
|
|
124
|
+
const line = lines[index];
|
|
125
|
+
if (line === undefined || lineByteLength(line) <= maxBytes) break;
|
|
126
|
+
skipped.push(formatOversizedLine(index + 1, line, maxBytes, formatSize));
|
|
127
|
+
index += 1;
|
|
128
|
+
}
|
|
129
|
+
const skipNote = skipped.join(". ");
|
|
130
|
+
if (index < lines.length) {
|
|
131
|
+
return `\n\n[Showing lines ${offset}-${endLine} of ${total}. ${skipNote}. Use offset=${index + 1} to continue.]`;
|
|
132
|
+
}
|
|
133
|
+
return `\n\n[Showing lines ${offset}-${endLine} of ${total}. ${skipNote}.]`;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function pageOversizedStart(id, offset, lines, maxBytes, formatSize) {
|
|
137
|
+
const line = lines[offset - 1] ?? "";
|
|
138
|
+
const note = formatOversizedLine(offset, line, maxBytes, formatSize);
|
|
139
|
+
const nextOffset = nextReadableOffset(lines, offset + 1, maxBytes);
|
|
140
|
+
const continueHint = nextOffset ? ` Use offset=${nextOffset} to continue.` : "";
|
|
141
|
+
const text = [
|
|
142
|
+
`<observation_data id="${id}" lines="${offset}-${offset}">`,
|
|
143
|
+
`[${note}]`,
|
|
144
|
+
"</observation_data>",
|
|
145
|
+
"",
|
|
146
|
+
`[${note}.${continueHint}]`,
|
|
147
|
+
].join("\n");
|
|
148
|
+
return { text, outputBytes: Buffer.byteLength(text, "utf-8") };
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function pageObservation(stored, offset, limit, jsonPath, maxBytes, formatSize, truncateHead) {
|
|
152
|
+
if (stored.toolName === "read") {
|
|
153
|
+
const text =
|
|
154
|
+
`This observation came from read. Use the read tool on the original file ` +
|
|
155
|
+
`instead of get_observation (offset=${offset}). Do not page this stored output.`;
|
|
156
|
+
return { id: stored.id, text, outputBytes: Buffer.byteLength(text, "utf-8") };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const selected = jsonPath ? selectJsonPath(stored.content, jsonPath) : stored.content;
|
|
160
|
+
const lines = selected.split("\n");
|
|
161
|
+
const lineCount = lines.length;
|
|
162
|
+
|
|
163
|
+
if (lines.length > 0 && offset === lineCount + 1) {
|
|
164
|
+
const lastLine = lines[lineCount - 1] ?? "";
|
|
165
|
+
const text = [
|
|
166
|
+
`Offset ${offset} is one past the end of observation ${stored.id} (${lineCount === 1 ? "1 line" : `${lineCount} lines`} total). Showing the last line. There is no further page.`,
|
|
167
|
+
`<observation_data id="${stored.id}" lines="${lineCount}-${lineCount}">`,
|
|
168
|
+
lastLine,
|
|
169
|
+
"</observation_data>",
|
|
170
|
+
].join("\n");
|
|
171
|
+
return { id: stored.id, text, outputBytes: Buffer.byteLength(text, "utf-8") };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (offset > lineCount) {
|
|
175
|
+
const parts = [
|
|
176
|
+
`Offset ${offset} is beyond end of observation ${stored.id} (${lineCount === 1 ? "1 line" : `${lineCount} lines`} total).`,
|
|
177
|
+
"Observation offset is 1-indexed within the stored observation, not a source-file line number and not a character offset.",
|
|
178
|
+
];
|
|
179
|
+
if (lineCount === 1) parts.push("This observation is a single line; there is no further page.");
|
|
180
|
+
else if (lineCount > 0)
|
|
181
|
+
parts.push(`Valid offsets are 1-${lineCount}. Use offset=1 to read from the start.`);
|
|
182
|
+
else parts.push("Observation is empty.");
|
|
183
|
+
if (stored.toolName === "read") {
|
|
184
|
+
parts.push(
|
|
185
|
+
`If you meant a source-file line, call read with that file's path and offset=${offset} instead of paging this observation.`,
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
const message = parts.join(" ");
|
|
189
|
+
if (lineCount === 1) {
|
|
190
|
+
const truncation = truncateHead(lines[0] ?? "", { maxBytes, maxLines: 1 });
|
|
191
|
+
const text = [message, assembleBlock(stored.id, "1-1", truncation.content, jsonPath)].join(
|
|
192
|
+
"\n",
|
|
193
|
+
);
|
|
194
|
+
return { id: stored.id, text, outputBytes: Buffer.byteLength(text, "utf-8") };
|
|
195
|
+
}
|
|
196
|
+
if (lineCount === 0) {
|
|
197
|
+
throw new Error(message);
|
|
198
|
+
}
|
|
199
|
+
const tailStart = Math.max(1, lineCount - limit + 1);
|
|
200
|
+
const tail = pageObservation(
|
|
201
|
+
stored,
|
|
202
|
+
tailStart,
|
|
203
|
+
limit,
|
|
204
|
+
jsonPath,
|
|
205
|
+
maxBytes,
|
|
206
|
+
formatSize,
|
|
207
|
+
truncateHead,
|
|
208
|
+
);
|
|
209
|
+
const text =
|
|
210
|
+
`${message}\n` +
|
|
211
|
+
`[Offset ${offset} is past the end; showing the last page (lines ${tailStart}-${lineCount}) instead.]\n\n` +
|
|
212
|
+
tail.text;
|
|
213
|
+
return { id: stored.id, text, outputBytes: Buffer.byteLength(text, "utf-8") };
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
const startIndex = offset - 1;
|
|
217
|
+
const selectedText = lines.slice(startIndex, startIndex + limit).join("\n");
|
|
218
|
+
const truncation = truncateHead(selectedText, { maxBytes, maxLines: limit });
|
|
219
|
+
if (truncation.firstLineExceedsLimit) {
|
|
220
|
+
return pageOversizedStart(stored.id, offset, lines, maxBytes, formatSize);
|
|
221
|
+
}
|
|
222
|
+
const endLine = offset + truncation.outputLines - 1;
|
|
223
|
+
const suffix = formatContinuation(lines, offset, endLine, maxBytes, formatSize);
|
|
224
|
+
const text = assembleBlock(
|
|
225
|
+
stored.id,
|
|
226
|
+
`${offset}-${endLine}`,
|
|
227
|
+
truncation.content,
|
|
228
|
+
jsonPath,
|
|
229
|
+
suffix,
|
|
230
|
+
);
|
|
231
|
+
return { id: stored.id, text, outputBytes: truncation.outputBytes };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context */
|
|
235
|
+
export async function execute(args, context) {
|
|
236
|
+
const { limits } = context.observations;
|
|
237
|
+
const rawIds = resolveIds(args);
|
|
238
|
+
const offset = typeof args.offset === "number" ? args.offset : 1;
|
|
239
|
+
const requestedLimit = typeof args.limit === "number" ? args.limit : limits.defaultLines;
|
|
240
|
+
const limit = Math.min(Math.max(1, requestedLimit), limits.maxLines);
|
|
241
|
+
const jsonPath = typeof args.path === "string" ? args.path : undefined;
|
|
242
|
+
|
|
243
|
+
const pages = [];
|
|
244
|
+
for (const rawId of rawIds) {
|
|
245
|
+
const resolved = await context.observations.resolveId(rawId);
|
|
246
|
+
if (!resolved.ok) {
|
|
247
|
+
if (resolved.reason === "ambiguous") {
|
|
248
|
+
throw new Error(
|
|
249
|
+
`Ambiguous observation ID prefix "${rawId}". Matches: ${(resolved.matches ?? []).join(", ")}. ${MISS_RETRY}`,
|
|
250
|
+
);
|
|
251
|
+
}
|
|
252
|
+
if (resolved.reason === "invalid") {
|
|
253
|
+
throw new Error(`Invalid observation ID. ${MISS_RETRY}`);
|
|
254
|
+
}
|
|
255
|
+
throw new Error(`Observation not found: ${rawId}. ${MISS_RETRY}`);
|
|
256
|
+
}
|
|
257
|
+
const stored = await context.observations.fetch(resolved.id);
|
|
258
|
+
if (!stored) {
|
|
259
|
+
throw new Error(`Observation not found: ${resolved.id}. ${MISS_RETRY}`);
|
|
260
|
+
}
|
|
261
|
+
pages.push(
|
|
262
|
+
pageObservation(
|
|
263
|
+
stored,
|
|
264
|
+
offset,
|
|
265
|
+
limit,
|
|
266
|
+
jsonPath,
|
|
267
|
+
limits.maxBytes,
|
|
268
|
+
context.util.formatSize,
|
|
269
|
+
context.util.truncateHead,
|
|
270
|
+
),
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
for (const page of pages) {
|
|
275
|
+
await context.observations.recordRetrieved(page.outputBytes);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const output = pages.map((page) => page.text).join("\n\n");
|
|
279
|
+
const truncation = context.util.truncateHead(output, {
|
|
280
|
+
maxBytes: limits.maxBytes * Math.max(1, pages.length),
|
|
281
|
+
maxLines: limits.maxLines * Math.max(1, pages.length),
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
const details =
|
|
285
|
+
pages.length === 1
|
|
286
|
+
? { observationId: pages[0].id, jsonPath, truncation }
|
|
287
|
+
: { observationIds: pages.map((page) => page.id), jsonPath, truncation };
|
|
288
|
+
|
|
289
|
+
return {
|
|
290
|
+
content: [{ type: "text", text: truncation.content }],
|
|
291
|
+
details,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tarsk-grep
|
|
3
|
+
description: >-
|
|
4
|
+
Tarsk Tool skill publishing: grep.
|
|
5
|
+
version: 2.0.0
|
|
6
|
+
tools:
|
|
7
|
+
- grep
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# tarsk-grep
|
|
12
|
+
|
|
13
|
+
Publishes: grep.
|
|
14
|
+
|
|
15
|
+
Empty/pagination/banner copy in `scripts/grep.js`. Host `context.fs.grep`
|
|
16
|
+
returns structured rows (cwd checks + ripgrep only).
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* grep — success/empty/pagination copy in the Skill; host runs path-safe ripgrep.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const description =
|
|
6
|
+
"Search file contents (not paths; use find for path globs) with regex (ripgrep-compatible). Content mode defaults to match lines only (-C 0); pass -C 3 (or -A/-B/context) when you need nearby lines for a unique edit hunk. output_mode: content (default; -A/-B/-C/context/-n apply here, -n defaults true), files_with_matches, count. Scope with path; glob for name/extension (*.ts, **/*.tsx)—not a path substitute. type = rg --type. head_limit default 25 (0=unlimited); offset skips. multiline: . matches newlines. Respects .gitignore. For many hits→reads, prefer one run_js over serial turns.";
|
|
7
|
+
|
|
8
|
+
export const parameters = {
|
|
9
|
+
type: "object",
|
|
10
|
+
required: ["pattern"],
|
|
11
|
+
properties: {
|
|
12
|
+
pattern: { type: "string" },
|
|
13
|
+
path: { type: "string" },
|
|
14
|
+
glob: {
|
|
15
|
+
description: "name/extension filter, e.g. *.ts. Prefer path for a directory.",
|
|
16
|
+
type: "string",
|
|
17
|
+
},
|
|
18
|
+
output_mode: {
|
|
19
|
+
anyOf: [
|
|
20
|
+
{ const: "content", type: "string" },
|
|
21
|
+
{ const: "files_with_matches", type: "string" },
|
|
22
|
+
{ const: "count", type: "string" },
|
|
23
|
+
],
|
|
24
|
+
},
|
|
25
|
+
"-B": { type: "number" },
|
|
26
|
+
"-A": { type: "number" },
|
|
27
|
+
"-C": {
|
|
28
|
+
description: "Lines of context around each match (default 0 = match lines only).",
|
|
29
|
+
type: "number",
|
|
30
|
+
},
|
|
31
|
+
context: {
|
|
32
|
+
description: "Alias for -C (default 0 = match lines only).",
|
|
33
|
+
type: "number",
|
|
34
|
+
},
|
|
35
|
+
"-n": { type: "boolean" },
|
|
36
|
+
"-i": { type: "boolean" },
|
|
37
|
+
type: { type: "string" },
|
|
38
|
+
head_limit: { type: "number" },
|
|
39
|
+
offset: { type: "number" },
|
|
40
|
+
multiline: {
|
|
41
|
+
description: ". matches newlines",
|
|
42
|
+
type: "boolean",
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const LITERAL_FALLBACK_NOTICE = "[Pattern was not valid regex; searched as a literal string]";
|
|
48
|
+
/** Matches shared MAX_GREP_CONTENT_CONTEXT — Skill-owned notice copy. */
|
|
49
|
+
const MAX_GREP_CONTENT_CONTEXT = 2;
|
|
50
|
+
|
|
51
|
+
function emptyMatchText(pathScopedGlob) {
|
|
52
|
+
if (pathScopedGlob) {
|
|
53
|
+
return (
|
|
54
|
+
"No matches found. Tip: prefer path for file/directory scope " +
|
|
55
|
+
'(e.g. path="app/components") and extension globs like "*.tsx" or "**/*.ts"; ' +
|
|
56
|
+
"path-prefixed globs can miss matches depending on the search root."
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
return "No matches found";
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function formatLimitInfo(appliedLimit, appliedOffset) {
|
|
63
|
+
const parts = [];
|
|
64
|
+
if (appliedLimit !== undefined) parts.push(`limit: ${appliedLimit}`);
|
|
65
|
+
if (appliedOffset) parts.push(`offset: ${appliedOffset}`);
|
|
66
|
+
return parts.join(", ");
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function formatBudgetNotice(budget) {
|
|
70
|
+
const parts = [];
|
|
71
|
+
if (budget.contextClamped) {
|
|
72
|
+
parts.push(`Context limited to ${MAX_GREP_CONTENT_CONTEXT} lines per side.`);
|
|
73
|
+
}
|
|
74
|
+
if (budget.headLimitScaled && budget.headLimit) {
|
|
75
|
+
parts.push(`Output line budget scaled to ${budget.headLimit}.`);
|
|
76
|
+
}
|
|
77
|
+
if (parts.length === 0) return "";
|
|
78
|
+
return `[${parts.join(" ")}]`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function formatSkippedNotice(skippedPaths) {
|
|
82
|
+
if (!skippedPaths || skippedPaths.length === 0) return undefined;
|
|
83
|
+
return `[Skipped missing path(s): ${skippedPaths.join(", ")}]`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function buildPrefix(searchedAsLiteral, skippedPaths) {
|
|
87
|
+
const notices = [];
|
|
88
|
+
if (searchedAsLiteral) notices.push(LITERAL_FALLBACK_NOTICE);
|
|
89
|
+
const skipped = formatSkippedNotice(skippedPaths);
|
|
90
|
+
if (skipped) notices.push(skipped);
|
|
91
|
+
return notices.length > 0 ? `${notices.join("\n")}\n` : "";
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function formatContent(result, context) {
|
|
95
|
+
const emptyText = emptyMatchText(result.pathScopedGlob);
|
|
96
|
+
if (result.lines.length === 0) return emptyText;
|
|
97
|
+
|
|
98
|
+
const compressed = context.util.compressGrepContent(result.lines);
|
|
99
|
+
let text = compressed.applied ? `${compressed.banner}\n${compressed.text}` : compressed.text;
|
|
100
|
+
const budgetNotice = formatBudgetNotice(result.budget);
|
|
101
|
+
if (budgetNotice) text += `\n\n${budgetNotice}`;
|
|
102
|
+
const limitInfo = formatLimitInfo(result.appliedLimit, result.appliedOffset);
|
|
103
|
+
if (limitInfo) text += `\n\n[Showing results with pagination = ${limitInfo}]`;
|
|
104
|
+
return text;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function formatCount(result, context) {
|
|
108
|
+
const emptyText = emptyMatchText(result.pathScopedGlob);
|
|
109
|
+
if (result.lines.length === 0) return emptyText;
|
|
110
|
+
|
|
111
|
+
const compressed = context.util.compressGrepCount(result.lines);
|
|
112
|
+
let text = compressed.applied ? `${compressed.banner}\n${compressed.text}` : compressed.text;
|
|
113
|
+
const totalMatches = result.totalMatches ?? 0;
|
|
114
|
+
const fileCount = result.fileCount ?? 0;
|
|
115
|
+
const occurrenceLabel = totalMatches === 1 ? "occurrence" : "occurrences";
|
|
116
|
+
const fileLabel = fileCount === 1 ? "file" : "files";
|
|
117
|
+
text += `\n\nFound ${totalMatches} total ${occurrenceLabel} across ${fileCount} ${fileLabel}.`;
|
|
118
|
+
const limitInfo = formatLimitInfo(result.appliedLimit, result.appliedOffset);
|
|
119
|
+
if (limitInfo) text += ` with pagination = ${limitInfo}`;
|
|
120
|
+
return text;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function formatFiles(result, context) {
|
|
124
|
+
const emptyText = emptyMatchText(result.pathScopedGlob);
|
|
125
|
+
if (result.lines.length === 0) {
|
|
126
|
+
return emptyText === "No matches found"
|
|
127
|
+
? "No files found"
|
|
128
|
+
: emptyText.replace("No matches found", "No files found");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const fileLabel = result.lines.length === 1 ? "file" : "files";
|
|
132
|
+
const compressed = context.util.compressGrepFiles(result.lines);
|
|
133
|
+
const listing = compressed.applied ? `${compressed.banner}\n${compressed.text}` : compressed.text;
|
|
134
|
+
const limitInfo = formatLimitInfo(result.appliedLimit, result.appliedOffset);
|
|
135
|
+
return `Found ${result.lines.length} ${fileLabel}${limitInfo ? ` ${limitInfo}` : ""}\n${listing}`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context @param {{ signal?: AbortSignal }} [options] */
|
|
139
|
+
export async function execute(args, context, options) {
|
|
140
|
+
const result = await context.fs.grep(args, { signal: options?.signal });
|
|
141
|
+
|
|
142
|
+
let body;
|
|
143
|
+
if (result.mode === "count") {
|
|
144
|
+
body = formatCount(result, context);
|
|
145
|
+
} else if (result.mode === "files_with_matches") {
|
|
146
|
+
body = formatFiles(result, context);
|
|
147
|
+
} else {
|
|
148
|
+
body = formatContent(result, context);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const truncation = context.util.truncateHead(body);
|
|
152
|
+
const trailing = truncation.truncated
|
|
153
|
+
? `\n\n[${context.util.formatSize(context.util.maxBytes)} limit reached]`
|
|
154
|
+
: "";
|
|
155
|
+
const text = `${buildPrefix(result.searchedAsLiteral, result.skippedPaths)}${truncation.content}${trailing}`;
|
|
156
|
+
|
|
157
|
+
const details = {
|
|
158
|
+
mode: result.mode,
|
|
159
|
+
};
|
|
160
|
+
if (result.mode === "content") details.numLines = result.lines.length;
|
|
161
|
+
if (result.mode === "count") {
|
|
162
|
+
details.numFiles = result.fileCount;
|
|
163
|
+
details.numMatches = result.totalMatches;
|
|
164
|
+
}
|
|
165
|
+
if (result.mode === "files_with_matches") details.numFiles = result.lines.length;
|
|
166
|
+
if (result.appliedLimit !== undefined) details.appliedLimit = result.appliedLimit;
|
|
167
|
+
if (result.appliedOffset !== undefined) details.appliedOffset = result.appliedOffset;
|
|
168
|
+
if (truncation.truncated) details.truncation = truncation;
|
|
169
|
+
|
|
170
|
+
return {
|
|
171
|
+
content: [{ type: "text", text }],
|
|
172
|
+
details,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* history Tool — logic in the Skill; transcript store is context.history (host).
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const description =
|
|
6
|
+
"Search and read the complete durable agent transcript, including content outside the current model context window. Use search to find exact earlier instructions, tool results, commands, errors, or decisions, then read an entry by id for more detail. Reads are paged by character offset. Search the current conversation by default; set allConversations only when older conversations in this thread are relevant.";
|
|
7
|
+
|
|
8
|
+
export const parameters = {
|
|
9
|
+
type: "object",
|
|
10
|
+
required: ["op"],
|
|
11
|
+
properties: {
|
|
12
|
+
op: {
|
|
13
|
+
anyOf: [
|
|
14
|
+
{ const: "search", type: "string" },
|
|
15
|
+
{ const: "read", type: "string" },
|
|
16
|
+
],
|
|
17
|
+
},
|
|
18
|
+
query: { description: "Text to find for search", type: "string" },
|
|
19
|
+
entryId: { description: "Entry id returned by search", type: "string" },
|
|
20
|
+
offset: { minimum: 0, description: "Character offset for read", type: "integer" },
|
|
21
|
+
limit: { minimum: 1, maximum: 25, type: "integer" },
|
|
22
|
+
allConversations: {
|
|
23
|
+
description: "Search every conversation in this thread",
|
|
24
|
+
type: "boolean",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
function textResult(text) {
|
|
30
|
+
return {
|
|
31
|
+
content: [{ type: "text", text }],
|
|
32
|
+
details: undefined,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function requireValue(value, field) {
|
|
37
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
38
|
+
throw new Error(`${field} is required for this operation`);
|
|
39
|
+
}
|
|
40
|
+
return value;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context */
|
|
44
|
+
export async function execute(args, context) {
|
|
45
|
+
if (!context.history.available) {
|
|
46
|
+
return textResult("Conversation history is unavailable for this session.");
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (args.op === "search") {
|
|
50
|
+
const results = await context.history.search({
|
|
51
|
+
query: requireValue(args.query, "query"),
|
|
52
|
+
allConversations: Boolean(args.allConversations),
|
|
53
|
+
limit: typeof args.limit === "number" ? args.limit : undefined,
|
|
54
|
+
});
|
|
55
|
+
return textResult(JSON.stringify(results));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (args.op === "read") {
|
|
59
|
+
const result = await context.history.read({
|
|
60
|
+
entryId: requireValue(args.entryId, "entryId"),
|
|
61
|
+
allConversations: Boolean(args.allConversations),
|
|
62
|
+
offset: typeof args.offset === "number" ? args.offset : undefined,
|
|
63
|
+
});
|
|
64
|
+
return textResult(result ? JSON.stringify(result) : "History entry not found.");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
throw new Error(`Unknown history op: ${String(args.op)}`);
|
|
68
|
+
}
|