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,331 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read — listing / footnote / unchanged copy in the Skill; host does cwd + bytes.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const description =
|
|
6
|
+
"Read a file or list a directory when the path is known. Text caps at 1000 lines / 32KB; continue via reported offset only when a footnote says more remains. Window text with top-level offset/limit. Do not combine offset/limit with select.range; use one or the other. Read returns text, not JSON, so do not apply select.range or guess a JSON path. Do not reread an unchanged range already in context. For a large file, grep to locate the region and read a window (offset/limit) instead of the whole file — whole-file reads of several files bloat context. Listings are non-recursive (dirs end with `/`). Use find for path globs and grep for contents. Images (PNG/JPEG/GIF/WebP under 5 MiB) return as vision attachments. Issue independent reads in the same turn.";
|
|
7
|
+
|
|
8
|
+
export const parameters = {
|
|
9
|
+
type: "object",
|
|
10
|
+
required: ["path"],
|
|
11
|
+
properties: {
|
|
12
|
+
path: {
|
|
13
|
+
description:
|
|
14
|
+
"File or directory path relative to the repository root, starting with `./` (for example `./shared/src/index.ts`). Absolute paths outside the project are denied; use bash to view those.",
|
|
15
|
+
type: "string",
|
|
16
|
+
},
|
|
17
|
+
offset: {
|
|
18
|
+
description: "Starting line, 1-indexed. Past the last line returns the last page.",
|
|
19
|
+
type: "number",
|
|
20
|
+
},
|
|
21
|
+
limit: {
|
|
22
|
+
description: "Maximum lines or directory entries",
|
|
23
|
+
minimum: 1,
|
|
24
|
+
type: "number",
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const READ_UNCHANGED_MARKER_PREFIX = "[Unchanged since toolCallId=";
|
|
30
|
+
|
|
31
|
+
function formatUnchangedStub(toolCallId, path) {
|
|
32
|
+
return `${READ_UNCHANGED_MARKER_PREFIX}${toolCallId}. ${path} is identical; request a different offset/limit to page.]`;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function formatDirectoryText(window) {
|
|
36
|
+
if (window.total === 0) return "(empty directory)";
|
|
37
|
+
if (window.entryCount === 0) return "(no entries shown)";
|
|
38
|
+
const output = window.entries.map(function formatEntry(entry) {
|
|
39
|
+
return `${entry.name}${entry.isDirectory ? "/" : ""}`;
|
|
40
|
+
});
|
|
41
|
+
if (
|
|
42
|
+
window.entryLimitReached !== undefined &&
|
|
43
|
+
window.startEntry !== undefined &&
|
|
44
|
+
window.endEntry !== undefined
|
|
45
|
+
) {
|
|
46
|
+
output.push(
|
|
47
|
+
`\n[Showing entries ${window.startEntry}-${window.endEntry} of ${window.total}. Use offset=${window.endEntry + 1} to continue.]`,
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
const listing = output.join("\n");
|
|
51
|
+
if (
|
|
52
|
+
window.pastEnd &&
|
|
53
|
+
window.requestedOffset !== undefined &&
|
|
54
|
+
window.startEntry !== undefined &&
|
|
55
|
+
window.endEntry !== undefined
|
|
56
|
+
) {
|
|
57
|
+
return `Offset ${window.requestedOffset} is beyond end of directory (${window.total} entries). Showing entries ${window.startEntry}-${window.endEntry}. Offset is 1-indexed.\n\n${listing}`;
|
|
58
|
+
}
|
|
59
|
+
return listing;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function formatOffsetPastEnd(requestedOffset, totalLines, shownStart, shownEnd) {
|
|
63
|
+
if (totalLines === 0) {
|
|
64
|
+
return `Offset ${requestedOffset} is beyond end of file (0 lines total). File is empty.`;
|
|
65
|
+
}
|
|
66
|
+
return (
|
|
67
|
+
`Offset ${requestedOffset} is beyond end of file (${totalLines} lines total). ` +
|
|
68
|
+
`Showing lines ${shownStart}-${shownEnd}. Offset is 1-indexed.`
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function formatText(structured, context) {
|
|
73
|
+
const {
|
|
74
|
+
path,
|
|
75
|
+
resourcePath,
|
|
76
|
+
selectedContent,
|
|
77
|
+
startLine,
|
|
78
|
+
totalFileLines,
|
|
79
|
+
userLimitedLines,
|
|
80
|
+
pastEndOffset,
|
|
81
|
+
firstLineByteLength,
|
|
82
|
+
} = structured;
|
|
83
|
+
const startLineDisplay = startLine + 1;
|
|
84
|
+
|
|
85
|
+
if (totalFileLines === 0) {
|
|
86
|
+
return {
|
|
87
|
+
content: [{ type: "text", text: formatOffsetPastEnd(pastEndOffset ?? 1, 0, 0, 0) }],
|
|
88
|
+
details: {},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const truncation = context.util.truncateHead(selectedContent);
|
|
93
|
+
let composed;
|
|
94
|
+
let details = {};
|
|
95
|
+
|
|
96
|
+
if (truncation.firstLineExceedsLimit) {
|
|
97
|
+
composed = `[Line ${startLineDisplay} is ${context.util.formatSize(firstLineByteLength)}, exceeds ${context.util.formatSize(context.util.maxBytes)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${context.util.maxBytes}]`;
|
|
98
|
+
details = { truncation };
|
|
99
|
+
} else if (truncation.truncated) {
|
|
100
|
+
const endLineDisplay = startLineDisplay + truncation.outputLines - 1;
|
|
101
|
+
const nextOffset = endLineDisplay + 1;
|
|
102
|
+
composed = truncation.content;
|
|
103
|
+
if (truncation.truncatedBy === "lines") {
|
|
104
|
+
composed += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue.]`;
|
|
105
|
+
} else {
|
|
106
|
+
composed += `\n\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${context.util.formatSize(context.util.maxBytes)} limit). Use offset=${nextOffset} to continue.]`;
|
|
107
|
+
}
|
|
108
|
+
details = { truncation };
|
|
109
|
+
} else if (userLimitedLines !== undefined && startLine + userLimitedLines < totalFileLines) {
|
|
110
|
+
const remaining = totalFileLines - (startLine + userLimitedLines);
|
|
111
|
+
const nextOffset = startLine + userLimitedLines + 1;
|
|
112
|
+
composed = `${truncation.content}\n\n[${remaining} more lines in file. Use offset=${nextOffset} to continue.]`;
|
|
113
|
+
} else {
|
|
114
|
+
composed = truncation.content;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const shownEnd = Math.min(
|
|
118
|
+
totalFileLines,
|
|
119
|
+
startLine + (truncation.outputLines || userLimitedLines || totalFileLines - startLine),
|
|
120
|
+
);
|
|
121
|
+
const raw =
|
|
122
|
+
pastEndOffset === undefined
|
|
123
|
+
? composed
|
|
124
|
+
: `${formatOffsetPastEnd(pastEndOffset, totalFileLines, startLineDisplay, shownEnd)}\n\n${composed}`;
|
|
125
|
+
const compressed = context.util.compressUnifiedDiffPreservingFootnotes(raw);
|
|
126
|
+
const outputText = compressed.applied ? compressed.text : raw;
|
|
127
|
+
|
|
128
|
+
let outputLines = 0;
|
|
129
|
+
if (!truncation.firstLineExceedsLimit && userLimitedLines !== 0) {
|
|
130
|
+
outputLines =
|
|
131
|
+
truncation.outputLines || userLimitedLines || Math.max(1, totalFileLines - startLine);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const detailsOut = { ...details };
|
|
135
|
+
if (outputLines > 0) {
|
|
136
|
+
const endLine = Math.min(totalFileLines, startLineDisplay + outputLines - 1);
|
|
137
|
+
detailsOut.supersession = {
|
|
138
|
+
kind: "read",
|
|
139
|
+
resourcePath,
|
|
140
|
+
coverage: {
|
|
141
|
+
kind: "text",
|
|
142
|
+
startLine: startLineDisplay,
|
|
143
|
+
endLine,
|
|
144
|
+
complete: startLineDisplay === 1 && endLine >= totalFileLines,
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return {
|
|
150
|
+
content: [{ type: "text", text: outputText }],
|
|
151
|
+
details: detailsOut,
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const SELECT_PATH_SEGMENT = /^[A-Za-z0-9_$-]+$/;
|
|
156
|
+
|
|
157
|
+
/** Mirrors the host dot-path grammar: `.`-separated segments, `*` and `[]` wildcards. */
|
|
158
|
+
function isValidSelectPath(path) {
|
|
159
|
+
for (const segment of path.split(".")) {
|
|
160
|
+
if (segment === "*" || segment === "[]") continue;
|
|
161
|
+
if (segment.length === 0) return false;
|
|
162
|
+
if (segment.endsWith("[]")) {
|
|
163
|
+
const key = segment.slice(0, -2);
|
|
164
|
+
if (key.length === 0 || !SELECT_PATH_SEGMENT.test(key)) return false;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (!SELECT_PATH_SEGMENT.test(segment)) return false;
|
|
168
|
+
}
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function sanitizeSelectRange(value, dropped) {
|
|
173
|
+
if (value === null || typeof value !== "object" || Array.isArray(value)) {
|
|
174
|
+
dropped.push("select.range");
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
const range = {};
|
|
178
|
+
for (const [key, raw] of Object.entries(value)) {
|
|
179
|
+
if (key === "path") {
|
|
180
|
+
if (typeof raw === "string" && raw.trim() !== "" && isValidSelectPath(raw)) range.path = raw;
|
|
181
|
+
else dropped.push("select.range.path");
|
|
182
|
+
} else if (key === "offset" || key === "limit") {
|
|
183
|
+
if (typeof raw === "number" && Number.isInteger(raw) && raw >= 1) range[key] = raw;
|
|
184
|
+
else dropped.push(`select.range.${key}`);
|
|
185
|
+
} else {
|
|
186
|
+
dropped.push(`select.range.${key}`);
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
if (range.offset === undefined && range.limit === undefined) {
|
|
190
|
+
dropped.push("select.range");
|
|
191
|
+
return undefined;
|
|
192
|
+
}
|
|
193
|
+
return range;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* The host rejects a malformed `select` before the tool runs, which loses the
|
|
198
|
+
* whole result over a stray argument (most often a non-string `range.path`).
|
|
199
|
+
* Drop the offending axis, keep the call, and say what was dropped.
|
|
200
|
+
*/
|
|
201
|
+
function withSanitizedSelect(args) {
|
|
202
|
+
const select = args.select;
|
|
203
|
+
if (select === undefined) return { args, note: undefined };
|
|
204
|
+
const dropped = [];
|
|
205
|
+
let next;
|
|
206
|
+
if (select === null || typeof select !== "object" || Array.isArray(select)) {
|
|
207
|
+
dropped.push("select");
|
|
208
|
+
} else {
|
|
209
|
+
next = {};
|
|
210
|
+
for (const [key, value] of Object.entries(select)) {
|
|
211
|
+
if (key === "range") {
|
|
212
|
+
const range = sanitizeSelectRange(value, dropped);
|
|
213
|
+
if (range) next.range = range;
|
|
214
|
+
} else {
|
|
215
|
+
dropped.push(`select.${key}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
if (dropped.length === 0) return { args, note: undefined };
|
|
220
|
+
const rest = Object.fromEntries(Object.entries(args).filter(([key]) => key !== "select"));
|
|
221
|
+
const kept = next && Object.keys(next).length > 0 ? next : undefined;
|
|
222
|
+
return {
|
|
223
|
+
args: kept ? { ...rest, select: kept } : rest,
|
|
224
|
+
note: `[select adjusted: dropped invalid ${dropped.join(", ")} — the host rejects the whole call, so that axis was ignored. Window text in the command (sed -n/head/tail) or read the stored output.]`,
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Top-level offset/limit wins over select.range when both are sent. The host
|
|
230
|
+
* rejects a conflicting pair; this drops the range so the read still runs.
|
|
231
|
+
*/
|
|
232
|
+
function resolveWindowConflict(args) {
|
|
233
|
+
const select = args.select;
|
|
234
|
+
const hasWindow = args.offset !== undefined || args.limit !== undefined;
|
|
235
|
+
if (!select || typeof select !== "object" || select.range === undefined || !hasWindow) {
|
|
236
|
+
return { args, note: undefined };
|
|
237
|
+
}
|
|
238
|
+
const restSelect = Object.fromEntries(Object.entries(select).filter(([key]) => key !== "range"));
|
|
239
|
+
const rest = Object.fromEntries(Object.entries(args).filter(([key]) => key !== "select"));
|
|
240
|
+
const hasOtherAxes = Object.keys(restSelect).length > 0;
|
|
241
|
+
const nextArgs = hasOtherAxes ? { ...rest, select: restSelect } : rest;
|
|
242
|
+
return {
|
|
243
|
+
args: nextArgs,
|
|
244
|
+
note: "[select.range ignored: offset/limit and select.range are mutually exclusive; used offset/limit.]",
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function withNote(result, note) {
|
|
249
|
+
if (!note || !Array.isArray(result.content)) return result;
|
|
250
|
+
const first = result.content[0];
|
|
251
|
+
if (first?.type !== "text") {
|
|
252
|
+
return { ...result, content: [{ type: "text", text: note }, ...result.content] };
|
|
253
|
+
}
|
|
254
|
+
return {
|
|
255
|
+
...result,
|
|
256
|
+
content: [{ ...first, text: `${note}\n\n${first.text}` }, ...result.content.slice(1)],
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context @param {{ signal?: AbortSignal, toolCallId?: string, onUpdate?: Function }} [options] */
|
|
261
|
+
export async function execute(args, context, options) {
|
|
262
|
+
const sanitized = withSanitizedSelect(args);
|
|
263
|
+
const resolved = resolveWindowConflict(sanitized.args);
|
|
264
|
+
const note = [sanitized.note, resolved.note].filter(Boolean).join("\n");
|
|
265
|
+
const result = await executeRead(resolved.args, context, options);
|
|
266
|
+
return withNote(result, note === "" ? undefined : note);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
async function executeRead(args, context, options) {
|
|
270
|
+
const structured = await context.fs.read(args, {
|
|
271
|
+
signal: options?.signal,
|
|
272
|
+
onUpdate: options?.onUpdate,
|
|
273
|
+
toolCallId: options?.toolCallId,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
if (structured.status === "aborted") {
|
|
277
|
+
return { content: [], details: undefined };
|
|
278
|
+
}
|
|
279
|
+
if (structured.status === "raw") {
|
|
280
|
+
return { content: structured.content, details: structured.details };
|
|
281
|
+
}
|
|
282
|
+
if (structured.status === "unchanged") {
|
|
283
|
+
return {
|
|
284
|
+
content: [
|
|
285
|
+
{
|
|
286
|
+
type: "text",
|
|
287
|
+
text: formatUnchangedStub(structured.cachedToolCallId, structured.path),
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
details: undefined,
|
|
291
|
+
};
|
|
292
|
+
}
|
|
293
|
+
if (structured.status === "directory") {
|
|
294
|
+
const text = formatDirectoryText(structured.window);
|
|
295
|
+
const window = structured.window;
|
|
296
|
+
return {
|
|
297
|
+
content: [{ type: "text", text }],
|
|
298
|
+
details: {
|
|
299
|
+
...(window.entryLimitReached !== undefined
|
|
300
|
+
? { entryLimitReached: window.entryLimitReached }
|
|
301
|
+
: {}),
|
|
302
|
+
supersession: {
|
|
303
|
+
kind: "read",
|
|
304
|
+
resourcePath: structured.resourcePath,
|
|
305
|
+
coverage: {
|
|
306
|
+
kind: "directory",
|
|
307
|
+
entryCount: window.entryCount,
|
|
308
|
+
complete: window.complete,
|
|
309
|
+
...(window.startEntry !== undefined && window.endEntry !== undefined
|
|
310
|
+
? { startEntry: window.startEntry, endEntry: window.endEntry }
|
|
311
|
+
: {}),
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
if (structured.status === "image") {
|
|
318
|
+
return {
|
|
319
|
+
content: [{ type: "image", data: structured.data, mimeType: structured.mimeType }],
|
|
320
|
+
details: {
|
|
321
|
+
supersession: {
|
|
322
|
+
kind: "read",
|
|
323
|
+
resourcePath: structured.resourcePath,
|
|
324
|
+
coverage: { kind: "image" },
|
|
325
|
+
},
|
|
326
|
+
},
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return formatText(structured, context);
|
|
331
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tarsk-read-skill
|
|
3
|
+
description: >-
|
|
4
|
+
Tarsk Tool skill publishing: read_skill.
|
|
5
|
+
version: 2.0.0
|
|
6
|
+
tools:
|
|
7
|
+
- read_skill
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# tarsk-read-skill
|
|
12
|
+
|
|
13
|
+
Publishes: read_skill.
|
|
14
|
+
|
|
15
|
+
Miss copy in `scripts/read_skill.js`. Host `context.skillsCatalog.read`
|
|
16
|
+
(load + preprocess).
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read_skill — miss copy in the Skill; host loads + preprocesses the body.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const description =
|
|
6
|
+
"Load the full instructions for an activated skill. Use this when you need to understand how to use a skill whose metadata (name, description, whenToUse) was shown in the Available Skills section.";
|
|
7
|
+
|
|
8
|
+
export const parameters = {
|
|
9
|
+
type: "object",
|
|
10
|
+
required: ["skillName"],
|
|
11
|
+
properties: {
|
|
12
|
+
skillName: {
|
|
13
|
+
description: "Skill name",
|
|
14
|
+
type: "string",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context */
|
|
20
|
+
export async function execute(args, context) {
|
|
21
|
+
const result = await context.skillsCatalog.read(args);
|
|
22
|
+
if (!result.ok) {
|
|
23
|
+
return {
|
|
24
|
+
content: [
|
|
25
|
+
{
|
|
26
|
+
type: "text",
|
|
27
|
+
text: `Skill not found: ${result.skillName}. Available skills: ${result.available.join(", ")}`,
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
details: undefined,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
content: [{ type: "text", text: result.text }],
|
|
35
|
+
details: undefined,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tarsk-read-skill-reference
|
|
3
|
+
description: >-
|
|
4
|
+
Tarsk Tool skill publishing: read_skill_reference.
|
|
5
|
+
version: 2.0.0
|
|
6
|
+
tools:
|
|
7
|
+
- read_skill_reference
|
|
8
|
+
deferred-tools:
|
|
9
|
+
- read_skill_reference
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# tarsk-read-skill-reference
|
|
14
|
+
|
|
15
|
+
Publishes: read_skill_reference.
|
|
16
|
+
|
|
17
|
+
Miss / path-error copy in `scripts/read_skill_reference.js`. Host
|
|
18
|
+
`context.skillsCatalog.readReference` returns structured load results (path
|
|
19
|
+
containment stays in the host).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* read_skill_reference — miss copy in the Skill; host holds path containment + read.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export const description =
|
|
6
|
+
"Read a reference file from an activated skill. Skills provide additional documentation in their references/ directory.";
|
|
7
|
+
|
|
8
|
+
export const parameters = {
|
|
9
|
+
type: "object",
|
|
10
|
+
required: ["skillName", "referencePath"],
|
|
11
|
+
properties: {
|
|
12
|
+
skillName: {
|
|
13
|
+
description: "Skill name",
|
|
14
|
+
type: "string",
|
|
15
|
+
},
|
|
16
|
+
referencePath: {
|
|
17
|
+
description:
|
|
18
|
+
'Path to the reference file relative to the skill\'s references/ directory (e.g., "api-reference.md" or "guides/setup.md")',
|
|
19
|
+
type: "string",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context */
|
|
25
|
+
export async function execute(args, context) {
|
|
26
|
+
const result = await context.skillsCatalog.readReference(args);
|
|
27
|
+
if (result.ok) {
|
|
28
|
+
return {
|
|
29
|
+
content: [{ type: "text", text: result.text }],
|
|
30
|
+
details: undefined,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
let text;
|
|
34
|
+
switch (result.reason) {
|
|
35
|
+
case "skill_not_found":
|
|
36
|
+
text = `Skill not found: ${result.skillName}. Available skills: ${result.available.join(", ")}`;
|
|
37
|
+
break;
|
|
38
|
+
case "no_references":
|
|
39
|
+
text = `Skill '${result.skillName}' has no references directory`;
|
|
40
|
+
break;
|
|
41
|
+
case "invalid_path":
|
|
42
|
+
text = `Invalid reference path: ${result.referencePath}. Path must be within the skill's references directory.`;
|
|
43
|
+
break;
|
|
44
|
+
case "not_found":
|
|
45
|
+
text =
|
|
46
|
+
result.available.length > 0
|
|
47
|
+
? `Reference file '${result.referencePath}' not found in skill '${result.skillName}'. Available references:\n${result.available.join("\n")}`
|
|
48
|
+
: `Reference file '${result.referencePath}' not found in skill '${result.skillName}'`;
|
|
49
|
+
break;
|
|
50
|
+
case "read_error":
|
|
51
|
+
text = `Failed to read reference file: ${result.message}`;
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
text = "Failed to read skill reference";
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
content: [{ type: "text", text }],
|
|
58
|
+
details: undefined,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tarsk-run-js
|
|
3
|
+
description: >-
|
|
4
|
+
Tarsk Tool skill publishing: run_js.
|
|
5
|
+
version: 3.1.0
|
|
6
|
+
tools:
|
|
7
|
+
- run_js
|
|
8
|
+
disable-model-invocation: true
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# tarsk-run-js
|
|
12
|
+
|
|
13
|
+
Publishes: run_js.
|
|
14
|
+
|
|
15
|
+
Truncation / trivial-read redirect notice in `scripts/run_js.js`. Host
|
|
16
|
+
`context.js.run` returns structured ok / trivial_read (worker + proxy catalog).
|
|
17
|
+
Failure diagnostics still throw from the host (recovery policy, like
|
|
18
|
+
`shell.resolveExit`).
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* run_js — truncation / trivial-read notice in the Skill; host holds worker +
|
|
3
|
+
* proxy catalog + failure diagnostics (still thrown from host).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const description =
|
|
7
|
+
"Default for multi-hop work: when one result decides the next call, or you would loop (grep→read each, list→act), put the whole chain here so intermediates stay out of chat. Independent known-arg calls stay parallel direct tools. Single known-file window → read, not run_js. Prefer `plan` (foreach + return) or `code` with chain/readMany/grepMany/locate/callTool. Cannot call run_js/ask_user/agent/tool_search, and deferred tools (notes, tasks, projects, history, browser, fetch, chat_title, images, execute_skill_script) join the catalog only after tool_search surfaces them — call those directly. Return once; on failure retry with patches and omit code. `code` is plain JavaScript only (async body, `await callTool(...)`, `return`): no shell commands, markdown fences, or prose. A syntax error is reported before the run. `code` must return a value explicitly; an undefined or null return fails the call. `intention` is required on every call, including `patches` retries.";
|
|
8
|
+
|
|
9
|
+
export const parameters = {
|
|
10
|
+
type: "object",
|
|
11
|
+
required: ["intention"],
|
|
12
|
+
properties: {
|
|
13
|
+
intention: {
|
|
14
|
+
description:
|
|
15
|
+
"Why this code is being run. Required on every call, including `patches` retries.",
|
|
16
|
+
type: "string",
|
|
17
|
+
},
|
|
18
|
+
code: {
|
|
19
|
+
description:
|
|
20
|
+
"JS to chain tools / reduce output (not Node APIs). Omit when using patches. await callTool(name, params) → {text, error}. Prefer read/find/grep helpers over bash. No file writes (use the write/edit tools) and no TextEncoder/btoa/atob — compute text/JSON only. End with an explicit `return` of the reduced answer; undefined or null return values fail.",
|
|
21
|
+
type: "string",
|
|
22
|
+
},
|
|
23
|
+
plan: {
|
|
24
|
+
additionalProperties: false,
|
|
25
|
+
description:
|
|
26
|
+
"Declarative tool graph with foreach instead of code. Args are tool parameters; refs infer dependsOn.",
|
|
27
|
+
type: "object",
|
|
28
|
+
required: ["steps"],
|
|
29
|
+
properties: {
|
|
30
|
+
steps: {
|
|
31
|
+
minItems: 1,
|
|
32
|
+
maxItems: 100,
|
|
33
|
+
type: "array",
|
|
34
|
+
items: {
|
|
35
|
+
additionalProperties: false,
|
|
36
|
+
type: "object",
|
|
37
|
+
required: ["id", "tool"],
|
|
38
|
+
properties: {
|
|
39
|
+
id: {
|
|
40
|
+
pattern: "^[A-Za-z_][A-Za-z0-9_-]*$",
|
|
41
|
+
type: "string",
|
|
42
|
+
},
|
|
43
|
+
tool: {
|
|
44
|
+
minLength: 1,
|
|
45
|
+
type: "string",
|
|
46
|
+
},
|
|
47
|
+
args: {
|
|
48
|
+
type: "object",
|
|
49
|
+
patternProperties: {
|
|
50
|
+
"^(.*)$": {},
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
foreach: {
|
|
54
|
+
description: "Array or $step; args may use $item / $index.",
|
|
55
|
+
anyOf: [
|
|
56
|
+
{
|
|
57
|
+
type: "string",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
type: "array",
|
|
61
|
+
items: {},
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
dependsOn: {
|
|
66
|
+
description: "Extra ordering edges.",
|
|
67
|
+
type: "array",
|
|
68
|
+
items: {
|
|
69
|
+
type: "string",
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
return: {
|
|
76
|
+
description:
|
|
77
|
+
"Projection (default last step). Refs: $id.text, $id.lines, $id.json.key. `.json` parses that step's text and fails if it is not JSON (grep content/read are text) — use $id.text for those.",
|
|
78
|
+
},
|
|
79
|
+
maxChars: {
|
|
80
|
+
minimum: 128,
|
|
81
|
+
maximum: 64000,
|
|
82
|
+
default: 16000,
|
|
83
|
+
description: "Final JSON character budget.",
|
|
84
|
+
type: "integer",
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
patches: {
|
|
89
|
+
description: "Retry edits on the last failed script; omit code. Each old matches once.",
|
|
90
|
+
type: "array",
|
|
91
|
+
items: {
|
|
92
|
+
type: "object",
|
|
93
|
+
required: ["old", "new"],
|
|
94
|
+
properties: {
|
|
95
|
+
old: {
|
|
96
|
+
description:
|
|
97
|
+
"Exact unique substring from the last failed run_js code (include enough context).",
|
|
98
|
+
type: "string",
|
|
99
|
+
},
|
|
100
|
+
new: {
|
|
101
|
+
description: "Replacement text; empty deletes the match.",
|
|
102
|
+
type: "string",
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const TRIVIAL_RUN_JS_READ_NOTICE =
|
|
111
|
+
"[Redirected trivial run_js to read. Use read({ path, offset, limit }) for a known file window.]";
|
|
112
|
+
|
|
113
|
+
const RUN_JS_CODE_RESULT_MAX_CHARS = 16000;
|
|
114
|
+
|
|
115
|
+
function formatRunJsResultText(result) {
|
|
116
|
+
if (typeof result === "string") {
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
return JSON.stringify(result, null, 2) || "undefined";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function truncationNotice(shownChars, totalChars) {
|
|
123
|
+
return (
|
|
124
|
+
`\n\n[Truncated run_js result: showing ${shownChars} of ${totalChars} chars. ` +
|
|
125
|
+
`Return a reduced answer (sliceText), or use read({ path, offset, limit }) for a known file window.]`
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function capRunJsCodeResultText(text, maxChars = RUN_JS_CODE_RESULT_MAX_CHARS) {
|
|
130
|
+
if (text.length <= maxChars) {
|
|
131
|
+
return text;
|
|
132
|
+
}
|
|
133
|
+
const placeholderNotice = truncationNotice(maxChars, text.length);
|
|
134
|
+
const budget = Math.max(0, maxChars - placeholderNotice.length);
|
|
135
|
+
const head = text.slice(0, budget);
|
|
136
|
+
return `${head}${truncationNotice(head.length, text.length)}`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function formatOk(value) {
|
|
140
|
+
return capRunJsCodeResultText(formatRunJsResultText(value));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function formatTrivialRead(structured) {
|
|
144
|
+
const first = structured.content[0];
|
|
145
|
+
const body = first?.type === "text" && typeof first.text === "string" ? first.text : "";
|
|
146
|
+
const text = body ? `${TRIVIAL_RUN_JS_READ_NOTICE}\n\n${body}` : TRIVIAL_RUN_JS_READ_NOTICE;
|
|
147
|
+
const rest = structured.content.slice(1);
|
|
148
|
+
return {
|
|
149
|
+
content: [{ type: "text", text }, ...rest],
|
|
150
|
+
details: structured.details,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Compile the `code` body as an async function body so a syntax error returns
|
|
156
|
+
* with its message before the worker starts. Skipped when the engine blocks
|
|
157
|
+
* the constructor (the host still reports its own compile error).
|
|
158
|
+
*/
|
|
159
|
+
function compileCheckCode(code) {
|
|
160
|
+
if (typeof code !== "string" || code.trim() === "") return undefined;
|
|
161
|
+
let AsyncFunction;
|
|
162
|
+
try {
|
|
163
|
+
AsyncFunction = Object.getPrototypeOf(async function probe() {}).constructor;
|
|
164
|
+
} catch {
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
new AsyncFunction("callTool", code);
|
|
169
|
+
return undefined;
|
|
170
|
+
} catch (error) {
|
|
171
|
+
if (error instanceof SyntaxError) {
|
|
172
|
+
return `[run_js syntax error: ${error.message}. Fix the code and retry; do not repeat the same body. Use patches to edit the last failed script.]`;
|
|
173
|
+
}
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/** @param {Record<string, unknown>} args @param {import("../../../../src/tools/agent-runtime/types.js").AgentRuntime} context @param {{ signal?: AbortSignal, toolCallId?: string }} [options] */
|
|
179
|
+
export async function execute(args, context, options) {
|
|
180
|
+
const syntaxNotice = compileCheckCode(args.code);
|
|
181
|
+
if (syntaxNotice) {
|
|
182
|
+
throw new Error(syntaxNotice);
|
|
183
|
+
}
|
|
184
|
+
const structured = await context.js.run(args, options);
|
|
185
|
+
if (structured.status === "trivial_read") {
|
|
186
|
+
return formatTrivialRead(structured);
|
|
187
|
+
}
|
|
188
|
+
return {
|
|
189
|
+
content: [{ type: "text", text: formatOk(structured.value) }],
|
|
190
|
+
details: undefined,
|
|
191
|
+
};
|
|
192
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tarsk-tasks
|
|
3
|
+
description: >-
|
|
4
|
+
Tarsk Tool skill publishing: tasks.
|
|
5
|
+
version: 2.0.0
|
|
6
|
+
tools:
|
|
7
|
+
- tasks
|
|
8
|
+
deferred-tools:
|
|
9
|
+
- tasks
|
|
10
|
+
disable-model-invocation: true
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# tarsk-tasks
|
|
14
|
+
|
|
15
|
+
Publishes: tasks.
|
|
16
|
+
|
|
17
|
+
Ok/error JSON copy in `scripts/tasks.js`. Host `context.tasks.query` (DB +
|
|
18
|
+
launch).
|