aws-runtime-bridge 1.9.151 → 1.9.162
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/CHANGELOG.md +560 -0
- package/dist/adapter/AcodeSdkAdapter.d.ts +51 -1
- package/dist/adapter/AcodeSdkAdapter.js +6 -5
- package/dist/adapter/prompts.d.ts +1 -1
- package/dist/adapter/prompts.js +1 -1
- package/dist/desktop/built-in-desktop-tools.js +1 -1
- package/dist/routes/acode-todos.js +1 -1
- package/dist/routes/ltr.js +1 -1
- package/dist/routes/sessions.d.ts +31 -0
- package/dist/routes/sessions.js +1 -1
- package/dist/routes/terminal.d.ts +8 -0
- package/dist/routes/terminal.js +25 -25
- package/dist/services/instance-features.d.ts +25 -1
- package/dist/services/instance-features.js +1 -1
- package/dist/services/workspace-files.js +1 -1
- package/dist/services/workspace-watch.js +1 -1
- package/dist/utils/file-utils.d.ts +2 -0
- package/dist/utils/file-utils.js +2 -2
- package/package/acode/dist/ask-user-question-tool.js +1 -1
- package/package/acode/dist/await-complete-tool.js +1 -1
- package/package/acode/dist/background-command-manager.js +1 -1
- package/package/acode/dist/background-command-tools.js +1 -1
- package/package/acode/dist/built-in-file-tools.d.ts +18 -2
- package/package/acode/dist/built-in-file-tools.js +2 -2
- package/package/acode/dist/built-in-symbols-tool.js +1 -1
- package/package/acode/dist/context-overflow.d.ts +19 -0
- package/package/acode/dist/context-overflow.js +2 -0
- package/package/acode/dist/grammars/grammars/tree-sitter-lua.wasm +0 -0
- package/package/acode/dist/index.d.ts +3 -1
- package/package/acode/dist/index.js +1 -1
- package/package/acode/dist/parsers/ast-cache.d.ts +12 -1
- package/package/acode/dist/parsers/ast-cache.js +1 -1
- package/package/acode/dist/parsers/language-queries.js +1 -1
- package/package/acode/dist/parsers/symbol-extractor.js +2 -2
- package/package/acode/dist/parsers/tree-sitter-loader.d.ts +1 -1
- package/package/acode/dist/parsers/tree-sitter-loader.js +1 -1
- package/package/acode/dist/plugin-types.d.ts +5 -0
- package/package/acode/dist/plugin-types.js +1 -0
- package/package/acode/dist/read-file-state.d.ts +48 -0
- package/package/acode/dist/read-file-state.js +2 -0
- package/package/acode/dist/runtime.d.ts +63 -3
- package/package/acode/dist/runtime.js +30 -26
- package/package/acode/dist/skill-tool.js +3 -3
- package/package/acode/dist/sub-agent-manager.js +1 -1
- package/package/acode/dist/sub-agent-tools.js +5 -5
- package/package/acode/dist/todo-tool.js +3 -3
- package/package/acode/dist/tool-concurrency/index.d.ts +5 -0
- package/package/acode/dist/tool-concurrency/index.js +2 -0
- package/package/acode/dist/tool-concurrency/observability.d.ts +46 -0
- package/package/acode/dist/tool-concurrency/observability.js +3 -0
- package/package/acode/dist/tool-concurrency/resource-lock.d.ts +25 -0
- package/package/acode/dist/tool-concurrency/resource-lock.js +2 -0
- package/package/acode/dist/tool-concurrency/scheduler.d.ts +30 -0
- package/package/acode/dist/tool-concurrency/scheduler.js +2 -0
- package/package/acode/dist/tool-concurrency/types.d.ts +80 -0
- package/package/acode/dist/tool-concurrency/types.js +2 -0
- package/package/acode/dist/tool-group-manager.d.ts +116 -0
- package/package/acode/dist/tool-group-manager.js +14 -0
- package/package/acode/dist/types.d.ts +14 -1
- package/package/acode/package.json +2 -2
- package/package/aws-client-agent-mcp/dist/agent-client.d.ts +4 -4
- package/package/aws-client-agent-mcp/dist/agent-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.d.ts +1 -1
- package/package/aws-client-agent-mcp/dist/http-client.js +1 -1
- package/package/aws-client-agent-mcp/dist/mcp-server.d.ts +62 -17
- package/package/aws-client-agent-mcp/dist/mcp-server.js +29 -29
- package/package/aws-client-agent-mcp/dist/mcp-tools.d.ts +46 -0
- package/package/aws-client-agent-mcp/dist/mcp-tools.js +149 -7
- package/package/aws-client-agent-mcp/dist/office/office-equation.d.ts +5 -0
- package/package/aws-client-agent-mcp/dist/office/office-equation.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.d.ts +12 -0
- package/package/aws-client-agent-mcp/dist/office/office-image.js +2 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.d.ts +25 -0
- package/package/aws-client-agent-mcp/dist/office/office-workspace.js +2 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.d.ts +57 -0
- package/package/aws-client-agent-mcp/dist/tool-groups.js +3 -0
- package/package/aws-client-agent-mcp/dist/types.d.ts +27 -0
- package/package/aws-client-agent-mcp/package.json +2 -1
- package/package.json +1 -1
- package/package/acode/dist/plugin-tools.d.ts +0 -14
- package/package/acode/dist/plugin-tools.js +0 -9
package/dist/utils/file-utils.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{spawn as
|
|
2
|
-
`}function
|
|
1
|
+
import{spawn as $}from"node:child_process";import{createHash as h}from"node:crypto";import{createWriteStream as B,mkdirSync as b,renameSync as z,rmSync as U,writeFileSync as k,promises as l}from"node:fs";import a from"node:path";import{Readable as T,Transform as y}from"node:stream";import{pipeline as F}from"node:stream/promises";import S from"axios";import v from"unzipper";import{DEFAULT_SCHEDULER_BASE_URL as L,schedulerBaseUrl as _}from"../config.js";import{getRuntimeAccessToken as p,loadRuntimeBinding as A}from"../services/runtime-binding.js";const d=new Map;function g(){const e=String(process.env.AWS_RUNTIME_SCHEDULER_BASE_URL||"").trim();if(e)return e;const t=A(),r=String(t.schedulerBaseUrl||"").trim();return t.status==="paired"&&r?r:_||L}async function W(e){return await l.mkdir(e,{recursive:!0}),e}async function Q(e,t){const r=a.resolve(e),n=d.get(r)??Promise.resolve();let i;const o=new Promise(u=>{i=u}),s=n.then(()=>o);d.set(r,s),await n;try{return await t()}finally{i(),d.get(r)===s&&d.delete(r)}}function j(e){if(!e||typeof e!="object")return!1;const t=Object.getPrototypeOf(e);return t===Object.prototype||t===null}function w(e){return Array.isArray(e)?e.map(t=>w(t)):j(e)?Object.keys(e).sort().reduce((t,r)=>(t[r]=w(e[r]),t),{}):e}function C(e){return`${JSON.stringify(w(e),null,2)}
|
|
2
|
+
`}function P(e){return String(e??"").replace(/[^a-zA-Z0-9_.-]/g,"_").replace(/^\.+/g,"").slice(0,128)}function E(e,t){const r=String(e??"").trim();if(!r||/[\\/]/.test(r))return t;const n=a.basename(r);return!n||n==="."||n===".."?t:n}async function N(e,t){await W(a.dirname(e));const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{await l.writeFile(i,t,"utf-8"),await D(i,e)}catch(o){throw await l.rm(i,{force:!0}).catch(()=>{}),o}}async function D(e,t,r=3){for(let n=1;;n++)try{await l.rename(e,t);return}catch(i){const o=i.code,s=o==="EPERM"||o==="EBUSY"||o==="EACCES";if(n>=r||!s)throw i;await new Promise(u=>setTimeout(u,40*n))}}function ee(e,t){b(a.dirname(e),{recursive:!0});const r=a.dirname(e),n=a.basename(e),i=a.join(r,`.${n}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`);try{k(i,t,"utf-8"),z(i,e)}catch(o){try{U(i,{force:!0})}catch{}throw o}}async function re(e,t){await N(e,C(t))}async function te(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=E(e.fileName,"skill-package.zip"),s=a.join(t,o),u=p(n)||p();if(!u)throw new Error("runtime access token is required to download skill package");const c=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":u}}),m=Buffer.from(c.data);if(await l.writeFile(s,m),e.sha256&&h("sha256").update(m).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error("skill zip checksum mismatch");return{fileName:o,outputPath:s,bytes:m.length}}async function ne(e,t){await new Promise((r,n)=>{const i=$(e,t,{stdio:["ignore","pipe","pipe"]});let o="";i.stderr?.on("data",s=>{o+=String(s||"")}),i.on("error",s=>{n(s)}),i.on("close",s=>{if(s!==0){n(new Error(o||`${e} exited with code ${s}`));return}r()})})}function ie(e){return String(e||"").replace(/'/g,"''")}const f={maxEntries:2e3,maxFileBytes:100*1024*1024,maxTotalBytes:200*1024*1024,maxPathLength:400,maxPathDepth:24};function I(e,t){const r=String(t||"").replace(/\\/g,"/");if(!r||r.startsWith("/")||/^[A-Za-z]:/.test(r)||r.split("/").includes(".."))throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u975E\u6CD5: ${t}`);if(r.length>f.maxPathLength)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u957F: ${t}`);if(r.split("/").filter(Boolean).length>f.maxPathDepth)throw new Error(`skill zip \u6761\u76EE\u8DEF\u5F84\u8FC7\u6DF1: ${t}`);const n=a.resolve(e,r),i=a.resolve(e)+a.sep;if(n!==a.resolve(e)&&!n.startsWith(i))throw new Error(`skill zip \u6761\u76EE\u8D8A\u754C\uFF08zip-slip\uFF09: ${t}`);return n}function R(e,t){let r=0;return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}function M(e,t){let r=0;return{transform(){return new y({transform(n,i,o){if(r+=n.length,r>e){o(new Error(`${t} \u8D85\u51FA\u603B\u91CF\u4E0A\u9650\uFF08${e} \u5B57\u8282\uFF09`));return}o(null,n)}})}}}async function oe(e,t){await l.rm(t,{recursive:!0,force:!0}),await l.mkdir(t,{recursive:!0});const r=await l.readFile(e),n=T.from([r]),i=n.pipe(v.Parse({forceStream:!0}));let o=0,s=0;const u=M(f.maxTotalBytes,"skill zip \u89E3\u538B\u603B\u91CF");try{for await(const c of i){const m=I(t,c.path);if(c.type==="Directory"){await l.mkdir(m,{recursive:!0}),c.autodrain?.();continue}if(c.type!=="File"){c.autodrain?.();continue}if(o++,o>f.maxEntries)throw new Error(`skill zip \u6761\u76EE\u6570\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxEntries}\uFF09`);if(s+=Number(c.size??0),s>f.maxTotalBytes)throw new Error(`skill zip \u603B\u91CF\u8D85\u51FA\u4E0A\u9650\uFF08${f.maxTotalBytes} \u5B57\u8282\uFF09`);await l.mkdir(a.dirname(m),{recursive:!0}),await F(c,R(f.maxFileBytes,`skill zip \u6761\u76EE ${c.path}`),u.transform(),B(m))}}catch(c){throw await l.rm(t,{recursive:!0,force:!0}).catch(()=>{}),c}finally{n.destroy(),i.destroy?.()}}async function se(e){const r=(await l.readdir(e,{withFileTypes:!0})).filter(n=>!n.name.startsWith("."));return r.length===1&&r[0].isDirectory()?a.join(e,r[0].name):e}async function ae(e,t){if(!e||!e.downloadUrl)return null;const r=String(e.downloadUrl).trim();if(!r)return null;const n=g();let i=r;i.startsWith("/")&&(i=`${n}${i}`);const o=E(e.fileName,"plugin-package.zip"),s=a.join(t,o),u=p(n)||p();if(!u)throw new Error("runtime access token is required to download plugin package");const c=await S.get(i,{responseType:"arraybuffer",timeout:3e4,headers:{"X-Runtime-Token":u}}),m=Buffer.from(c.data);if(await l.writeFile(s,m),e.sha256&&h("sha256").update(m).digest("hex")!==String(e.sha256).trim().toLowerCase())throw new Error(`plugin package sha256 mismatch: ${o}`);return{fileName:o,outputPath:s,bytes:m.length}}export{N as atomicWriteFile,ee as atomicWriteFileSync,re as atomicWriteJsonFile,ae as downloadPluginZip,te as downloadSkillZip,W as ensureDir,ie as escapePowerShellLiteral,oe as extractSkillZip,D as renameFileWithRetry,se as resolveSkillSourceDirFromExtractRoot,ne as runCommand,P as sanitizeAgentId,E as sanitizeArchiveFileName,C as stringifyStableJson,Q as withFileLock};
|
|
3
3
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
const c="ask_user_question",f=["\u5411\u7528\u6237\u63D0\u51FA\u95EE\u9898\uFF0C\u6536\u96C6\u66F4\u591A\u4FE1\u606F\u4E3A\u505A\u51B3\u7B56\u63D0\u4F9B\u66F4\u591A\u7684\u65B9\u5411\u9009\u62E9\uFF0C\u6BCF\u4E2A\u95EE\u9898\u4F1A\u81EA\u52A8\u8FFD\u52A0\u201C\u5176\u5B83\u201D\u9009\u9879\u4F9B\u7528\u6237\u81EA\u5B9A\u4E49\u8F93\u5165\u3002","\u591A\u4E2A\u95EE\u9898\u65F6\u4E0D\u5F97\u4F9D\u8D56\u524D\u9762\u95EE\u9898\u7684\u7B54\u6848\uFF0C\u82E5\u67D0\u95EE\u9898\u4F9D\u8D56\u53E6\u4E00\u95EE\u9898\u7684\u7B54\u6848\uFF0C\u5E94\u62C6\u6210\u591A\u8F6E\u5206\u522B\u8C03\u7528\u672C\u5DE5\u5177\u3002","\u63D0\u4EA4\u540E\u8FDB\u5165\u7528\u6237\u5BA1\u6279\uFF0C\u5BA1\u6279\u901A\u8FC7\u7684\u9879\u4F1A\u76F4\u63A5\u521B\u5EFA\uFF08\u7ED3\u679C\u968F\u5DE5\u5177\u8FD4\u56DE\uFF09\u3002","\u5982\u679C\u63A8\u8350\u67D0\u4E2A\u9009\u9879\uFF0C\u628A\u5B83\u653E\u5728\u7B2C\u4E00\u4F4D\u5E76\u5728 label \u672B\u5C3E\u52A0\u201C\uFF08\u63A8\u8350\uFF09\u201D\u3002"].join(`
|
|
2
|
-
`);function I(o,e){return{kind:"builtin",toolName:c,exposedName:c,description:f,inputSchema:m(),async execute(n,t){const r=t?.toolCallId;if(!r)return{ok:!1,tool:c,error:"missing toolCallId in execution context"};const s=y(n.questions);if(s.length===0)return{ok:!1,tool:c,error:"questions must be a non-empty array"};o.onQuestion(r,s);const u=e();let i;try{i=await o.waitForAnswer(r,u)}catch(p){const a=p instanceof Error?p.message:String(p);return{ok:!1,tool:c,error:a}}const l=b(s,i);return{ok:!0,tool:c,answers:i,summary:l}}}}function m(){return{type:"object",properties:{questions:{type:"array",description:"\u8981\u63D0\u95EE\u7684\u95EE\u9898\u5217\u8868\uFF08\u81F3\u5C11 1 \u4E2A\uFF0C\u6570\u91CF\u4E0D\u8BBE\u4E0A\u9650\uFF09\uFF1B\u591A\u4E2A\u95EE\u9898\u65F6\u5FC5\u987B\u76F8\u4E92\u72EC\u7ACB\u3001\u5E76\u5217\u63D0\u95EE\uFF0C\u540E\u7EED\u95EE\u9898\u4E0D\u5F97\u4F9D\u8D56\u524D\u9762\u95EE\u9898\u7684\u7B54\u6848\uFF0C\u6709\u4F9D\u8D56\u5173\u7CFB\u65F6\u5E94\u62C6\u6210\u591A\u6B21\u8C03\u7528",minItems:1,items:{type:"object",properties:{question:{type:"string",description:"\u5B8C\u6574\u95EE\u9898\u6587\u672C\uFF0C\u5EFA\u8BAE\u4EE5\u95EE\u53F7\u7ED3\u5C3E"},header:{type:"string",description:"\u226412 \u5B57\u7B26\u7684\u7B80\u77ED\u6807\u7B7E\uFF0C\u7528\u4E8E UI chip \u663E\u793A"},options:{type:"array",description:"2-4 \u4E2A\u4E92\u65A5\u9009\u9879\uFF08multiSelect=true \u65F6\u53EF\u4E0D\u4E92\u65A5\uFF09",minItems:2,maxItems:4,items:{type:"object",properties:{label:{type:"string",description:"1-5 \u8BCD\u7684\u7B80\u77ED\u6807\u7B7E"},description:{type:"string",description:"\u9009\u9879\u542B\u4E49\u6216\u6743\u8861\u8BF4\u660E"},requiresCustomInput:{type:"boolean",description:"\u9009\u4E2D\u6B64\u9879\u65F6 UI \u663E\u793A\u81EA\u5B9A\u4E49\u8F93\u5165\u6846"}},required:["label"]}},multiple:{type:"boolean",description:"\u662F\u5426\u5141\u8BB8\u591A\u9009\uFF1B\u9ED8\u8BA4 false"}},required:["question","options"]}},custom:{type:"boolean",description:"\u662F\u5426\u5141\u8BB8\u7528\u6237\u8865\u5145\u81EA\u5B9A\u4E49\u8F93\u5165\uFF1B\u9ED8\u8BA4 true"}},required:["questions"]}}function y(o){if(!Array.isArray(o)||o.length===0)return[];const e=[];for(const n of o){if(!n||typeof n!="object")continue;const t=n,r=typeof t.question=="string"?t.question.trim():"";if(!r)continue;const s=d(t.options);if(s.length<2)continue;const u=typeof t.header=="string"&&t.header.trim()?t.header.trim():void 0,i=t.multiple===!0||t.multiSelect===!0;e.push({question:r,header:u,options:s,multiple:i})}return e}function d(o){if(!Array.isArray(o))return[];const e=[];for(const n of o){if(typeof n=="string"){const i=n.trim();i&&e.push({label:i});continue}if(!n||typeof n!="object")continue;const t=n,r=typeof t.label=="string"?t.label.trim():typeof t.value=="string"?t.value.trim():typeof t.text=="string"?t.text.trim():"";if(!r)continue;const s=typeof t.description=="string"&&t.description.trim()?t.description.trim():void 0,u=t.requiresCustomInput===!0||t.requireCustomInput===!0||t.allowCustomInput===!0;if(e.push({label:r,...s?{description:s}:{},...u?{requiresCustomInput:u}:{}}),e.length>=4)break}return e}function b(o,e){const n=["\u7528\u6237\u5DF2\u56DE\u7B54\u4E86\u60A8\u7684\u95EE\u9898\uFF1A"];return o.forEach((t,r)=>{const s=String(r),u=e[s]||(t.header?e[t.header]:"")||e[t.question]||"\uFF08\u672A\u586B\u5199\uFF09",i=t.header||t.question;n.push(`\u2022 ${i}\uFF1A${u}`)}),n.join(`
|
|
2
|
+
`);function I(o,e){return{kind:"builtin",toolName:c,exposedName:c,concurrencyMode:"blocking",description:f,inputSchema:m(),async execute(n,t){const r=t?.toolCallId;if(!r)return{ok:!1,tool:c,error:"missing toolCallId in execution context"};const s=y(n.questions);if(s.length===0)return{ok:!1,tool:c,error:"questions must be a non-empty array"};o.onQuestion(r,s);const u=e();let i;try{i=await o.waitForAnswer(r,u)}catch(p){const a=p instanceof Error?p.message:String(p);return{ok:!1,tool:c,error:a}}const l=b(s,i);return{ok:!0,tool:c,answers:i,summary:l}}}}function m(){return{type:"object",properties:{questions:{type:"array",description:"\u8981\u63D0\u95EE\u7684\u95EE\u9898\u5217\u8868\uFF08\u81F3\u5C11 1 \u4E2A\uFF0C\u6570\u91CF\u4E0D\u8BBE\u4E0A\u9650\uFF09\uFF1B\u591A\u4E2A\u95EE\u9898\u65F6\u5FC5\u987B\u76F8\u4E92\u72EC\u7ACB\u3001\u5E76\u5217\u63D0\u95EE\uFF0C\u540E\u7EED\u95EE\u9898\u4E0D\u5F97\u4F9D\u8D56\u524D\u9762\u95EE\u9898\u7684\u7B54\u6848\uFF0C\u6709\u4F9D\u8D56\u5173\u7CFB\u65F6\u5E94\u62C6\u6210\u591A\u6B21\u8C03\u7528",minItems:1,items:{type:"object",properties:{question:{type:"string",description:"\u5B8C\u6574\u95EE\u9898\u6587\u672C\uFF0C\u5EFA\u8BAE\u4EE5\u95EE\u53F7\u7ED3\u5C3E"},header:{type:"string",description:"\u226412 \u5B57\u7B26\u7684\u7B80\u77ED\u6807\u7B7E\uFF0C\u7528\u4E8E UI chip \u663E\u793A"},options:{type:"array",description:"2-4 \u4E2A\u4E92\u65A5\u9009\u9879\uFF08multiSelect=true \u65F6\u53EF\u4E0D\u4E92\u65A5\uFF09",minItems:2,maxItems:4,items:{type:"object",properties:{label:{type:"string",description:"1-5 \u8BCD\u7684\u7B80\u77ED\u6807\u7B7E"},description:{type:"string",description:"\u9009\u9879\u542B\u4E49\u6216\u6743\u8861\u8BF4\u660E"},requiresCustomInput:{type:"boolean",description:"\u9009\u4E2D\u6B64\u9879\u65F6 UI \u663E\u793A\u81EA\u5B9A\u4E49\u8F93\u5165\u6846"}},required:["label"]}},multiple:{type:"boolean",description:"\u662F\u5426\u5141\u8BB8\u591A\u9009\uFF1B\u9ED8\u8BA4 false"}},required:["question","options"]}},custom:{type:"boolean",description:"\u662F\u5426\u5141\u8BB8\u7528\u6237\u8865\u5145\u81EA\u5B9A\u4E49\u8F93\u5165\uFF1B\u9ED8\u8BA4 true"}},required:["questions"]}}function y(o){if(!Array.isArray(o)||o.length===0)return[];const e=[];for(const n of o){if(!n||typeof n!="object")continue;const t=n,r=typeof t.question=="string"?t.question.trim():"";if(!r)continue;const s=d(t.options);if(s.length<2)continue;const u=typeof t.header=="string"&&t.header.trim()?t.header.trim():void 0,i=t.multiple===!0||t.multiSelect===!0;e.push({question:r,header:u,options:s,multiple:i})}return e}function d(o){if(!Array.isArray(o))return[];const e=[];for(const n of o){if(typeof n=="string"){const i=n.trim();i&&e.push({label:i});continue}if(!n||typeof n!="object")continue;const t=n,r=typeof t.label=="string"?t.label.trim():typeof t.value=="string"?t.value.trim():typeof t.text=="string"?t.text.trim():"";if(!r)continue;const s=typeof t.description=="string"&&t.description.trim()?t.description.trim():void 0,u=t.requiresCustomInput===!0||t.requireCustomInput===!0||t.allowCustomInput===!0;if(e.push({label:r,...s?{description:s}:{},...u?{requiresCustomInput:u}:{}}),e.length>=4)break}return e}function b(o,e){const n=["\u7528\u6237\u5DF2\u56DE\u7B54\u4E86\u60A8\u7684\u95EE\u9898\uFF1A"];return o.forEach((t,r)=>{const s=String(r),u=e[s]||(t.header?e[t.header]:"")||e[t.question]||"\uFF08\u672A\u586B\u5199\uFF09",i=t.header||t.question;n.push(`\u2022 ${i}\uFF1A${u}`)}),n.join(`
|
|
3
3
|
`)}function q(o){if(!o||typeof o!="object")return!1;const e=o;return e.ok===!0&&e.tool===c&&typeof e.answers=="object"&&e.answers!==null&&typeof e.summary=="string"}function j(o){const e={ok:!0,tool:c,answers:g(o.answers),summary:o.summary};return JSON.stringify(e)}function g(o){const e={};for(const[n,t]of Object.entries(o))e[n]=t;return e}export{c as ASK_USER_QUESTION_TOOL_NAME,I as createAskUserQuestionTool,q as isAskUserQuestionResult,j as serializeAskUserQuestionResult};
|
|
4
4
|
|
|
@@ -16,6 +16,6 @@ Guidelines:
|
|
|
16
16
|
- Pass sub-agent IDs in 'sub_agent_ids' and/or background command task_ids in 'bg_cmd_ids'
|
|
17
17
|
- At least one of the two arrays must be non-empty
|
|
18
18
|
- Use timeout_ms to bound the wait (default 600000 = 10 minutes; 0 = wait forever)
|
|
19
|
-
- After this returns, call poll_message to receive any pending messages`;function h(o){return{kind:"builtin",toolName:"await_complete",exposedName:"await_complete",description:g,inputSchema:{type:"object",properties:{sub_agent_ids:{type:"array",items:{type:"string"},description:"Array of sub-agent IDs to wait for (from sub_agent). Empty if none."},bg_cmd_ids:{type:"array",items:{type:"string"},description:"Array of background command task_ids to wait for (from Bash wait_seconds or list_background_commands). Empty if none."},timeout_ms:{type:"number",description:"Maximum time to wait in milliseconds, applied to the whole JOIN. 0 = no timeout (wait forever). Default: 600000 (10 minutes)."}},additionalProperties:!1},async execute(
|
|
19
|
+
- After this returns, call poll_message to receive any pending messages`;function h(o){return{kind:"builtin",toolName:"await_complete",exposedName:"await_complete",concurrencyMode:"blocking",description:g,inputSchema:{type:"object",properties:{sub_agent_ids:{type:"array",items:{type:"string"},description:"Array of sub-agent IDs to wait for (from sub_agent). Empty if none."},bg_cmd_ids:{type:"array",items:{type:"string"},description:"Array of background command task_ids to wait for (from Bash wait_seconds or list_background_commands). Empty if none."},timeout_ms:{type:"number",description:"Maximum time to wait in milliseconds, applied to the whole JOIN. 0 = no timeout (wait forever). Default: 600000 (10 minutes)."}},additionalProperties:!1},async execute(n){const l=typeof n.timeout_ms=="number"?n.timeout_ms:6e5,m=n.sub_agent_ids,c=n.bg_cmd_ids,i=Array.isArray(m)?m.filter(t=>typeof t=="string"&&t.trim().length>0):[],u=Array.isArray(c)?c.filter(t=>typeof t=="string"&&t.trim().length>0):[];if(i.length===0&&u.length===0)return{title:"await_complete validation error",output:"Invalid input: provide at least one of 'sub_agent_ids' or 'bg_cmd_ids'.",metadata:{error:!0}};if(i.length>0&&!o.awaitSubAgents)return{title:"await_complete error",output:"sub_agent_ids provided but sub-agent manager is not enabled for this agent.",metadata:{error:!0}};try{let t=[];i.length>0&&o.awaitSubAgents&&(t=await o.awaitSubAgents(i,l)??[]);let a=[];u.length>0&&(a=await o.awaitBgCommands(u,l));const s=[],p=[],d=[];if(t.length>0){s.push(`=== ${t.length} sub-agent(s) ===`);for(const e of t)s.push(`[${e.status}] ${e.subId}`),e.error?(s.push("<task_error>"),s.push(e.error),s.push("</task_error>")):(s.push("<task_result>"),s.push(e.output||"(empty output)"),s.push("</task_result>")),s.push(""),p.push(e)}if(a.length>0){s.push(`=== ${a.length} background command(s) ===`);for(const e of a){if(!e){s.push("[not_found] (unknown task_id)"),s.push(""),d.push(null);continue}const r=[];e.timedOut&&r.push("timed_out"),e.aborted&&r.push("aborted"),s.push(`[${e.status}] ${e.taskId} exit=${e.exitCode??"?"}`+(r.length?` (${r.join(",")})`:"")+(e.outputFilePath?` output=${e.outputFilePath}`:"")),s.push(""),d.push(e)}}return{title:`awaited ${t.length+a.length} item(s)`,output:s.join(`
|
|
20
20
|
`),metadata:{total:t.length+a.length,sub_agents:p,bg_cmds:d}}}catch(t){return{title:"await_complete error",output:`Failed to await: ${t instanceof Error?t.message:String(t)}`,metadata:{error:!0}}}}}}export{h as createAwaitCompleteTool};
|
|
21
21
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{spawn as E}from"node:child_process";import{promises as S}from"node:fs";import{createInterface as R}from"node:readline";import{randomBytes as M}from"node:crypto";import{prepareShellCommand as O,shellExecutable as D}from"./builtins/shellCommandPreparation.js";import{createShellOutputDecoder as b,decodeShellOutputChunk as A}from"./builtins/shellOutputDecoder.js";import{BackgroundOutputRingBuffer as G}from"./background-output-ringbuffer.js";import{BackgroundCommandStore as z}from"./background-command-store.js";const F=1e3,N=
|
|
1
|
+
import{spawn as E}from"node:child_process";import{promises as S}from"node:fs";import{createInterface as R}from"node:readline";import{randomBytes as M}from"node:crypto";import{prepareShellCommand as O,shellExecutable as D}from"./builtins/shellCommandPreparation.js";import{createShellOutputDecoder as b,decodeShellOutputChunk as A}from"./builtins/shellOutputDecoder.js";import{BackgroundOutputRingBuffer as G}from"./background-output-ringbuffer.js";import{BackgroundCommandStore as z}from"./background-command-store.js";const F=1e3,N=3*60*1e3,W=24*60*60*1e3,$=5*1e3,k=64*1024,X=2e3,C=50*1024*1024,_=16,P=256,q=256*1024,K=100,U=5e3,Y=256,v=20,B=5*60*1e3,L=1024*1024,x=`pid-${process.pid}-${Date.now().toString(36)}`;class H{constructor(){this.tasksByAgent=new Map,this.store=new z}globalCount(){let t=0;for(const i of this.tasksByAgent.values())t+=i.size;return t}startCommand(t){const i=t.agentId,e=this.getOrCreateBucket(i);if(e.size>=_)throw new I("too_many_tasks",`Agent ${i} has ${e.size} background tasks (limit ${_}). Kill or wait for completion first.`);if(this.globalCount()>=P)throw new I("global_limit_reached",`Global background task limit ${P} reached.`);const n=this.generateTaskId(e),r=t.timeoutMs===void 0?N:t.timeoutMs>0?Math.min(t.timeoutMs,W):0,s=typeof t.inactivityTimeoutMs=="number"&&Number.isFinite(t.inactivityTimeoutMs)&&t.inactivityTimeoutMs>0?t.inactivityTimeoutMs:0,o=this.store.outputPathFor(i,n),a=t.commandText.length>80?`${t.commandText.slice(0,77)}...`:t.commandText,u={taskId:n,agentId:i,command:t.commandText,commandPreview:a,description:t.description,cwd:t.cwd,status:"running",startedAt:Date.now(),finishedAt:null,exitCode:null,signal:null,killedReason:null,timeoutMs:r,inactivityTimeoutMs:s,child:null,ringBuffer:new G,outputPath:o,outputWriteChain:Promise.resolve(),outputTruncated:!1,outputLineCount:0,outputBytes:0,notified:!1,completionWaiters:[],onCompleted:t.onCompleted,onOutput:t.onOutput,outputSeq:0,outputSubscribers:new Set,timeoutTimer:null,killEscalationTimer:null,retentionTimer:null,inactivityTimer:null,exitGraceTimer:null,inactivityTimedOut:!1,finalized:!1,stdoutDecoder:b(),stderrDecoder:b(),stdoutText:"",stderrText:"",commandLineCount:0,bootId:x,lastPulseAt:Date.now(),lastPulseBytes:0,backgrounded:!1},l=new Promise(c=>{u.completionResolve=c});return e.set(n,u),r>0&&(u.timeoutTimer=setTimeout(()=>{u.finalized||(u.killedReason="timeout",u.child?this.killProcessGroup(u.child):this.finalizeTask(u,null,null,"timeout"))},r),u.timeoutTimer.unref?.()),this.spawnAndAttach(u,t).catch(c=>{u.ringBuffer.push(`[ACode] spawn failed: ${c?.message??String(c)}
|
|
2
2
|
`),this.finalizeTask(u,-1,null,"spawn_error")}),this.persistTaskSafe(u),{taskId:n,completion:l}}async spawnAndAttach(t,i){const e=D(),n=await O(i.commandText,i.workspaceRoot,e),r=process.platform==="win32",s=E(e.command,[...e.argsPrefix,n.commandText],{cwd:i.cwd,env:process.env,detached:!r,stdio:["ignore","pipe","pipe"],windowsVerbatimArguments:r,windowsHide:!0});t.child=s,t.commandFilePath=n.commandFilePath,t.commandLineCount=n.commandLineCount,t.inactivityTimeoutMs>0&&this.scheduleInactivity(t),s.stdout?.on("data",o=>{const a=A(t.stdoutDecoder,o);this.onOutput(t,"stdout",a)}),s.stderr?.on("data",o=>{const a=A(t.stderrDecoder,o);this.onOutput(t,"stderr",a)}),s.on("error",o=>{this.onOutput(t,"stderr",`[ACode] child error: ${o.message}
|
|
3
3
|
`),t.finalized||this.finalizeTask(t,-1,null,"child_error")}),s.on("exit",(o,a)=>{if(t.finalized)return;const u=()=>{if(t.finalized||!t.child)return;const l=A(t.stdoutDecoder,void 0,!0),c=A(t.stderrDecoder,void 0,!0);l&&this.onOutput(t,"stdout",l),c&&this.onOutput(t,"stderr",c),t.ringBuffer.flush();const p=t.killedReason??null;this.finalizeTask(t,o,a,p??void 0)};t.exitGraceTimer=setTimeout(u,X),t.exitGraceTimer.unref?.()}),s.on("close",(o,a)=>{t.exitGraceTimer&&(clearTimeout(t.exitGraceTimer),t.exitGraceTimer=null);const u=A(t.stdoutDecoder,void 0,!0),l=A(t.stderrDecoder,void 0,!0);if(u&&this.onOutput(t,"stdout",u),l&&this.onOutput(t,"stderr",l),t.ringBuffer.flush(),!t.finalized){const c=t.killedReason??null;this.finalizeTask(t,o,a,c??void 0)}})}disableInactivityTimeout(t,i){const e=this.getTask(t,i);return e?(e.inactivityTimeoutMs=0,e.inactivityTimer&&(clearTimeout(e.inactivityTimer),e.inactivityTimer=null),!0):!1}async markBackgrounded(t,i){const e=this.getTask(t,i);return e?(e.backgrounded=!0,await this.persistTask(e),!0):!1}onOutput(t,i,e){if(!e)return;t.outputSeq++;const n=t.outputSeq;if(t.outputSubscribers.size>0)for(const o of t.outputSubscribers)try{o.onLine({stream:i,text:e,seq:n})}catch{}const r=i==="stdout"?"stdoutText":"stderrText";if(Buffer.byteLength(t[r],"utf-8")<L){const o=L-Buffer.byteLength(t[r],"utf-8");t[r]+=o>0?e.slice(0,o):""}if(t.inactivityTimeoutMs>0&&this.scheduleInactivity(t),t.status==="running"){const o=Date.now(),a=t.outputBytes-t.lastPulseBytes;(o-t.lastPulseAt>=$||a>=k)&&(t.lastPulseAt=o,t.lastPulseBytes=t.outputBytes,this.persistTaskSafe(t))}if(t.outputBytes>=C){if(!t.outputTruncated){t.outputTruncated=!0;const o=`
|
|
4
4
|
[ACode] output truncated at 50MB
|
|
@@ -13,6 +13,6 @@ Modes:
|
|
|
13
13
|
- tail (default): last N lines (live view; no paging anchor).
|
|
14
14
|
|
|
15
15
|
Every returned line is { line, text }: line is the 0-based absolute line number in the command output. Use the line number to locate the same content in the output / files, and lines(start_line=..., line_size=...) to expand around a match.
|
|
16
|
-
Output capped at 256KB / line_size lines per call; truncated=true means more is available (grep: continue from nextStartLine).`;function u(a,o){return{kind:"builtin",toolName:"list_background_commands",exposedName:"list_background_commands",description:r,inputSchema:{type:"object",properties:{status_filter:{type:"string",enum:["running","completed","failed","killed","all"],description:"Filter by status. Defaults to 'all'.",default:"all"}},additionalProperties:!1},async execute(e){const n=typeof e.status_filter=="string"?e.status_filter:"all",i=o.manager.listTasks(a,n);return{title:`${i.length} background commands`,output:JSON.stringify(i.map(t=>({taskId:t.taskId,status:t.status,command:t.commandPreview,cwd:t.cwd,startedAt:new Date(t.startedAt).toISOString(),finishedAt:t.finishedAt?new Date(t.finishedAt).toISOString():null,exitCode:t.exitCode,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes})),null,2),metadata:{tasks:i,count:i.length}}}}}function l(a,o){return{kind:"builtin",toolName:"kill_background_command",exposedName:"kill_background_command",description:s,inputSchema:{type:"object",properties:{task_id:{type:"string",description:"The task_id returned by Bash(wait_seconds=...) or list_background_commands."}},required:["task_id"],additionalProperties:!1},async execute(e){const n=typeof e.task_id=="string"?e.task_id:"",i=await o.manager.killTask(a,n);return{title:`kill ${n}: ${i.status}`,output:JSON.stringify(i,null,2),metadata:i}}}}function c(a,o){return{kind:"builtin",toolName:"read_background_output",exposedName:"read_background_output",description:d,inputSchema:{type:"object",properties:{task_id:{type:"string",description:"The task_id to read output from."},mode:{type:"string",enum:["lines","grep","tail"],description:"lines=read range by absolute line numbers, grep=search matching lines with context, tail=last N lines (default).",default:"tail"},line_size:{type:"integer",description:"lines/tail: number of lines to return; grep: max total lines returned (including context). Default 100, max 100.",default:100,minimum:1,maximum:100},start_line:{type:"integer",description:"lines: 0-based absolute line to start from; grep: scan start line (pass nextStartLine to page).",minimum:0},pattern:{type:"string",description:"grep: regex pattern (JS syntax, case-insensitive)."},context_before:{type:"integer",description:"grep: lines of context before each match (0-20, default 0).",minimum:0,maximum:20,default:0},context_after:{type:"integer",description:"grep: lines of context after each match (0-20, default 0).",minimum:0,maximum:20,default:0},include_metadata:{type:"boolean",description:"Include totalLines/totalBytes/truncated/outputTruncated/hasMore/nextStartLine/outputFile in response.",default:!0}},required:["task_id"],additionalProperties:!1},async execute(e){const n=await o.manager.readOutput(a,{task_id:typeof e.task_id=="string"?e.task_id:"",mode:e.mode==="lines"||e.mode==="grep"||e.mode==="tail"?e.mode:"tail",line_size:typeof e.line_size=="number"?e.line_size:void 0,start_line:typeof e.start_line=="number"?e.start_line:void 0,pattern:typeof e.pattern=="string"?e.pattern:void 0,context_before:typeof e.context_before=="number"?e.context_before:void 0,context_after:typeof e.context_after=="number"?e.context_after:void 0,include_metadata:e.include_metadata!==!1});return{title:`read ${n.taskId} (${n.mode}): ${n.lineCount} lines`,output:n.lines.map(({line:i,text:t})=>`${i}: ${t}`).join(`
|
|
16
|
+
Output capped at 256KB / line_size lines per call; truncated=true means more is available (grep: continue from nextStartLine).`;function u(a,o){return{kind:"builtin",toolName:"list_background_commands",exposedName:"list_background_commands",concurrencyMode:"read",resourceKeys:()=>[{key:"runtime:background",access:"read"}],description:r,inputSchema:{type:"object",properties:{status_filter:{type:"string",enum:["running","completed","failed","killed","all"],description:"Filter by status. Defaults to 'all'.",default:"all"}},additionalProperties:!1},async execute(e){const n=typeof e.status_filter=="string"?e.status_filter:"all",i=o.manager.listTasks(a,n);return{title:`${i.length} background commands`,output:JSON.stringify(i.map(t=>({taskId:t.taskId,status:t.status,command:t.commandPreview,cwd:t.cwd,startedAt:new Date(t.startedAt).toISOString(),finishedAt:t.finishedAt?new Date(t.finishedAt).toISOString():null,exitCode:t.exitCode,outputLineCount:t.outputLineCount,outputBytes:t.outputBytes})),null,2),metadata:{tasks:i,count:i.length}}}}}function l(a,o){return{kind:"builtin",toolName:"kill_background_command",exposedName:"kill_background_command",description:s,inputSchema:{type:"object",properties:{task_id:{type:"string",description:"The task_id returned by Bash(wait_seconds=...) or list_background_commands."}},required:["task_id"],additionalProperties:!1},async execute(e){const n=typeof e.task_id=="string"?e.task_id:"",i=await o.manager.killTask(a,n);return{title:`kill ${n}: ${i.status}`,output:JSON.stringify(i,null,2),metadata:i}}}}function c(a,o){return{kind:"builtin",toolName:"read_background_output",exposedName:"read_background_output",concurrencyMode:"read",resourceKeys:()=>[{key:"runtime:background",access:"read"}],description:d,inputSchema:{type:"object",properties:{task_id:{type:"string",description:"The task_id to read output from."},mode:{type:"string",enum:["lines","grep","tail"],description:"lines=read range by absolute line numbers, grep=search matching lines with context, tail=last N lines (default).",default:"tail"},line_size:{type:"integer",description:"lines/tail: number of lines to return; grep: max total lines returned (including context). Default 100, max 100.",default:100,minimum:1,maximum:100},start_line:{type:"integer",description:"lines: 0-based absolute line to start from; grep: scan start line (pass nextStartLine to page).",minimum:0},pattern:{type:"string",description:"grep: regex pattern (JS syntax, case-insensitive)."},context_before:{type:"integer",description:"grep: lines of context before each match (0-20, default 0).",minimum:0,maximum:20,default:0},context_after:{type:"integer",description:"grep: lines of context after each match (0-20, default 0).",minimum:0,maximum:20,default:0},include_metadata:{type:"boolean",description:"Include totalLines/totalBytes/truncated/outputTruncated/hasMore/nextStartLine/outputFile in response.",default:!0}},required:["task_id"],additionalProperties:!1},async execute(e){const n=await o.manager.readOutput(a,{task_id:typeof e.task_id=="string"?e.task_id:"",mode:e.mode==="lines"||e.mode==="grep"||e.mode==="tail"?e.mode:"tail",line_size:typeof e.line_size=="number"?e.line_size:void 0,start_line:typeof e.start_line=="number"?e.start_line:void 0,pattern:typeof e.pattern=="string"?e.pattern:void 0,context_before:typeof e.context_before=="number"?e.context_before:void 0,context_after:typeof e.context_after=="number"?e.context_after:void 0,include_metadata:e.include_metadata!==!1});return{title:`read ${n.taskId} (${n.mode}): ${n.lineCount} lines`,output:n.lines.map(({line:i,text:t})=>`${i}: ${t}`).join(`
|
|
17
17
|
`),metadata:n}}}}export{l as createKillBackgroundCommandTool,u as createListBackgroundCommandsTool,c as createReadBackgroundOutputTool};
|
|
18
18
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { type CommandOutputSink } from "./builtins/shellCommandRunner.js";
|
|
2
|
+
import { type StaleFileGuardDeps } from "./read-file-state.js";
|
|
2
3
|
import type { BackgroundCommandManager, BackgroundCompletedEvent } from "./background-command-manager.js";
|
|
4
|
+
import type { ResourceClaim, ResourceScope, ToolConcurrencyMode } from "./tool-concurrency/types.js";
|
|
3
5
|
|
|
4
6
|
export interface BackgroundToolDeps {
|
|
5
7
|
manager: BackgroundCommandManager;
|
|
@@ -20,6 +22,14 @@ export interface ACodeBuiltInTool {
|
|
|
20
22
|
inputSchema: JsonObject;
|
|
21
23
|
|
|
22
24
|
category?: string;
|
|
25
|
+
|
|
26
|
+
group?: string;
|
|
27
|
+
|
|
28
|
+
concurrencyMode?: ToolConcurrencyMode;
|
|
29
|
+
|
|
30
|
+
resourceKeys?: (args: JsonObject) => ResourceClaim[];
|
|
31
|
+
|
|
32
|
+
resourceScope?: ResourceScope;
|
|
23
33
|
execute(args: JsonObject, context?: ACodeBuiltInToolExecutionContext): Promise<unknown>;
|
|
24
34
|
}
|
|
25
35
|
export interface ACodeBuiltInToolExecutionContext {
|
|
@@ -32,7 +42,7 @@ export interface ACodeBuiltInToolExecutionContext {
|
|
|
32
42
|
|
|
33
43
|
export type ToolPermissionLevel = "allow" | "ask" | "deny";
|
|
34
44
|
|
|
35
|
-
export type ToolPermissionCapability = "fileReadOutside" | "commandExecution" | "fileModification";
|
|
45
|
+
export type ToolPermissionCapability = "fileReadOutside" | "commandExecution" | "fileModification" | "fileModificationOutside";
|
|
36
46
|
export type ToolPermissionPolicy = Record<ToolPermissionCapability, ToolPermissionLevel>;
|
|
37
47
|
|
|
38
48
|
export declare const DEFAULT_TOOL_PERMISSION_POLICY: ToolPermissionPolicy;
|
|
@@ -67,8 +77,14 @@ export interface ResolvedWorkspaceTarget {
|
|
|
67
77
|
workspaceRoot: string;
|
|
68
78
|
requestedPath: string;
|
|
69
79
|
targetPath: string;
|
|
80
|
+
|
|
81
|
+
outsideWorkspace?: boolean;
|
|
70
82
|
}
|
|
71
83
|
export declare function ensureInsideWorkspace(workspaceRoot: string, targetPath: string): string;
|
|
72
84
|
|
|
85
|
+
export declare function buildFileResourceKey(workingDirectory: string, rawFilePath: string): string;
|
|
86
|
+
|
|
87
|
+
export declare function fileResourceClaim(workingDirectory: string, rawFilePath: string, access: "read" | "write"): ResourceClaim;
|
|
88
|
+
|
|
73
89
|
export declare function resolveWorkspaceTarget(workingDirectory: string, rawFilePath: string): Promise<ResolvedWorkspaceTarget>;
|
|
74
|
-
export declare function createBuiltInFileTools(workingDirectory: string, agentId?: string, onFileChange?: OnAgentFileChange, backgroundDeps?: BackgroundToolDeps, permissionController?: ToolPermissionController): ACodeBuiltInTool[];
|
|
90
|
+
export declare function createBuiltInFileTools(workingDirectory: string, agentId?: string, onFileChange?: OnAgentFileChange, backgroundDeps?: BackgroundToolDeps, permissionController?: ToolPermissionController, staleGuard?: StaleFileGuardDeps): ACodeBuiltInTool[];
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{randomUUID as
|
|
1
|
+
import{randomUUID as ht}from"node:crypto";import{promises as h,createReadStream as Z}from"node:fs";import ft from"node:os";import d from"node:path";import Q from"node:readline";import{runShellCommand as pt}from"./builtins/shellCommandRunner.js";import{createOutputEventCollector as wt}from"./builtins/commandOutputEvents.js";import{buildCommandOutputSpilloverContent as gt,COMMAND_OUTPUT_SPILLOVER_LINE_LIMIT as yt,countOutputLines as tt,formatCommandOutputSpilloverStdout as _t,writeCommandArtifactFile as bt}from"./builtins/commandArtifacts.js";import{symbolsTool as kt}from"./built-in-symbols-tool.js";import{buildRevisionId as W,checkFileFreshForWrite as et,createReadFileEntry as K,STALE_FILE_WRITE_REASON as ot,toStateKey as N}from"./read-file-state.js";import{createListBackgroundCommandsTool as vt,createKillBackgroundCommandTool as Pt,createReadBackgroundOutputTool as Et}from"./background-command-tools.js";import{detectImageFormatFromBuffer as St,formatBytes as T,imageMediaType as it,readImageDimensions as xt,tryCompressImageWithSharp as Tt,tryResizeWithSharp as Mt}from"./image-utils.js";const Rt=2e3,L=2e3,at=50*1024,rt=4096,$t=.3,Ot=new Set([".png",".jpg",".jpeg",".gif",".bmp",".ico",".webp",".tiff",".tif",".zip",".gz",".tar",".rar",".7z",".bz2",".xz",".lz",".exe",".dll",".so",".dylib",".bin",".o",".a",".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".mp3",".mp4",".avi",".mov",".wav",".flv",".mkv",".ogg",".woff",".woff2",".ttf",".otf",".eot",".class",".jar",".war",".ear",".pyc",".pyo",".node",".sqlite",".db",".mdb",".wasm"]),It=new Set(["png","jpg","jpeg","gif","webp"]),nt=20*1024*1024,F=10*1024*1024,X=Math.floor(3.75*1024*1024),U=2e3,At=50*1024,Lt=100*1024,Ft=15e3,Bt=1e3,Nt=1024*1024,Ct=256*1024,Wt=1e3,Ut=new Set([".git","node_modules","dist","build",".next",".nuxt",".cache",".turbo",".output","coverage",".nyc_output"]),Se={fileReadOutside:"allow",commandExecution:"allow",fileModification:"allow",fileModificationOutside:"allow"};async function B(e,t,o){if(!e)return;const i=e.getLevel(t);if(i==="deny")throw new Error(`Operation blocked by tool permission policy (${t} = deny). Explain this restriction to the user if needed.`);if(i==="ask"&&!await e.requestPermission(t,o))throw new Error(`Operation denied by the user (${t}). Do not retry the same operation without asking the user.`)}function M(e){return e.replace(/\\/g,"/")}async function Y(e){try{return await h.access(e),!0}catch{return!1}}function zt(e,t){if(!t)return 0;let o=0,i=e.indexOf(t);for(;i>=0;)o+=1,i=e.indexOf(t,i+t.length);return o}function $(e,t,o){for(const i of t){const a=e[i];if(typeof a=="string")return a}throw new Error(`${o} is required`)}function O(e,t){for(const o of t){const i=e[o];if(typeof i=="string"&&i.trim())return i}}function z(e,t,o){for(const i of t){const a=e[i],n=typeof a=="number"?a:typeof a=="string"?Number(a):NaN;if(Number.isFinite(n)&&n>0)return Math.floor(n)}return o}function Dt(e,t,o){for(const i of t){const a=e[i],n=typeof a=="number"?a:typeof a=="string"?Number(a):NaN;if(Number.isFinite(n)&&n>0)return Math.floor(n);if(Number.isFinite(n)&&n===0)return 0}return o}function qt(e){const t=e.compress;if(t==null)return"auto";if(typeof t=="boolean")return t;if(t==="auto")return"auto";if(t==="true")return!0;if(t==="false")return!1;throw new Error(`Invalid compress argument: ${JSON.stringify(t)} (expected true, false, or "auto")`)}async function st(e){const t=d.extname(e).toLowerCase();if(Ot.has(t))return!0;const o=await h.open(e,"r");try{const i=Buffer.alloc(rt),{bytesRead:a}=await o.read(i,0,rt,0);if(a===0)return!1;const n=i.subarray(0,a);if(n.includes(0))return!0;let s=0;for(let c=0;c<a;c++){const r=n[c];(r<9||r>13&&r<32)&&s++}return s/a>$t}finally{await o.close()}}function I(e,t){const o=d.resolve(t),i=d.relative(e,o);if(i.startsWith("..")||d.isAbsolute(i))throw new Error(`Target path is outside workspace: ${o}`);return o}function jt(e,t){const o=d.resolve(String(e||"").trim()),i=C(String(t??"").trim());return`file:${(d.isAbsolute(i)?d.resolve(i):d.resolve(o,i)).replace(/\\/g,"/")}`}function D(e,t,o){return{key:jt(e,t),access:o}}function q(e){const t=e.file_path??e.filePath;if(typeof t!="string")return null;const o=t.trim();return o.length>0?o:null}function C(e){return e==="~"||e.startsWith("~/")?d.join(ft.homedir(),e.slice(1)):e}async function Kt(e,t){const o=d.resolve(String(e||"").trim()),i=await h.realpath(o);if(!(await h.stat(i)).isDirectory())throw new Error(`Workspace path is not a directory: ${o}`);if(!t?.trim())return{workspaceRoot:i,cwd:i};const n=C(t.trim()),s=d.isAbsolute(n)?d.resolve(n):d.resolve(o,n),c=d.relative(o,s);if(c.startsWith("..")||d.isAbsolute(c))throw new Error(`Command cwd is outside workspace: ${s}`);const r=I(i,await h.realpath(s));if(!(await h.stat(r)).isDirectory())throw new Error(`Command cwd is not a directory: ${r}`);return{workspaceRoot:i,cwd:r}}async function Xt(e){try{if((await h.lstat(e)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${e}`)}catch(t){if((typeof t=="object"&&t!==null?Reflect.get(t,"code"):void 0)!=="ENOENT")throw t}}async function Yt(e,t){const o=await h.realpath(d.dirname(t));I(e,o);try{if((await h.lstat(t)).isSymbolicLink())throw new Error(`Refusing to write through symbolic link: ${t}`)}catch(i){if((typeof i=="object"&&i!==null?Reflect.get(i,"code"):void 0)!=="ENOENT")throw i}}async function ct(e,t){const o=d.resolve(String(e||"").trim()),i=await h.realpath(o);if(!(await h.stat(i)).isDirectory())throw new Error(`Workspace path is not a directory: ${o}`);const n=C(t.trim());if(!n)throw new Error("file_path is required");const s=d.isAbsolute(n)?d.resolve(n):d.resolve(o,n),c=d.relative(o,s);if(c.startsWith("..")||d.isAbsolute(c))throw new Error(`Target path is outside workspace: ${s}`);return{workspaceRoot:i,requestedPath:s,targetPath:I(i,d.join(i,c))}}async function lt(e,t,o){const i=d.resolve(String(e||"").trim()),a=await h.realpath(i);if(!(await h.stat(a)).isDirectory())throw new Error(`Workspace path is not a directory: ${i}`);const s=C(t.trim());if(!s)throw new Error("file_path is required");const c=d.isAbsolute(s)?d.resolve(s):d.resolve(i,s),r=d.relative(i,c),u=await h.realpath(c).catch(()=>c),l=d.relative(a,u);if(r.startsWith("..")||d.isAbsolute(r)||l.startsWith("..")||d.isAbsolute(l)){if(!o)throw new Error(`Target path is outside workspace: ${c}`);return await B(o,"fileReadOutside",{path:c}),{workspaceRoot:a,requestedPath:c,targetPath:u}}return{workspaceRoot:a,requestedPath:c,targetPath:I(a,u)}}async function Gt(e,t){let o=d.dirname(e);for(;;){const i=d.dirname(o);try{return await h.realpath(o)}catch{if(i===o)return t;o=i}}}async function G(e,t,o,i){const a=d.resolve(String(e||"").trim()),n=await h.realpath(a);if(!(await h.stat(n)).isDirectory())throw new Error(`Workspace path is not a directory: ${a}`);const c=C(t.trim());if(!c)throw new Error("file_path is required");const r=d.isAbsolute(c)?d.resolve(c):d.resolve(a,c),u=d.relative(a,r),l=u.startsWith("..")||d.isAbsolute(u),w=await h.realpath(r).catch(async()=>Gt(r,n)),_=d.relative(n,w),f=_.startsWith("..")||d.isAbsolute(_);if(!l&&!f)return{workspaceRoot:n,requestedPath:r,targetPath:I(n,d.join(n,u))};if(!i)throw new Error(`Target path is outside workspace: ${r}`);await B(i,"fileModificationOutside",{operation:o,path:r});const p=await Y(r);return{workspaceRoot:n,requestedPath:r,targetPath:p?w:r,outsideWorkspace:!0}}async function ut(e,t){const o=d.dirname(e.targetPath),i=!await Y(o);await h.mkdir(o,{recursive:!0}),e.outsideWorkspace?await Xt(e.targetPath):await Yt(e.workspaceRoot,e.targetPath);const a=d.join(o,`.${d.basename(e.targetPath)}.${process.pid}.${ht()}.tmp`);try{await h.writeFile(a,t,"utf-8"),await h.rename(a,e.targetPath)}catch(n){throw await h.rm(a,{force:!0}),n}return{workspaceRoot:e.workspaceRoot,targetPath:e.targetPath,bytes:Buffer.byteLength(t,"utf-8"),createdParentDirectory:i,outsideWorkspace:e.outsideWorkspace===!0}}async function Ht(e,t){const o=await ct(e,t),i=I(o.workspaceRoot,await h.realpath(o.targetPath)),a=await h.stat(i);if(!a.isFile())throw new Error(`Path is not a file: ${i}`);return{workspaceRoot:o.workspaceRoot,targetPath:i,content:await h.readFile(i,"utf-8"),stat:{mtimeMs:a.mtimeMs,size:a.size}}}async function Vt(e){const t=await h.realpath(e).catch(()=>e),o=await h.stat(t);if(!o.isFile())throw new Error(`Path is not a file: ${t}`);return{workspaceRoot:d.dirname(t),targetPath:t,content:await h.readFile(t,"utf-8"),stat:{mtimeMs:o.mtimeMs,size:o.size}}}async function dt(e,t,o){if(e?.tracker)try{const i=await h.realpath(t),a=await h.stat(i);e.tracker.record(N(i),K(a,o,!1))}catch{}}async function Jt(e,t,o,i,a){const n=await lt(e,t,a),s=n.targetPath,c=await h.stat(s);if(!c.isFile())throw new Error(`Path is not a file: ${s}`);if(await st(s))return{workspaceRoot:n.workspaceRoot,targetPath:s,content:"[Binary file, content skipped]",isBinary:!0,truncated:!1,totalLines:0,shownFromLine:0,shownToLine:0,mtimeMs:c.mtimeMs,sizeBytes:c.size};const r=Z(s,{encoding:"utf-8"}),u=Q.createInterface({input:r,crlfDelay:1/0});try{const l=[];let w=0,_=0,f=0,p=!1,m=!1;const x=o-1;for await(const y of u){if(_++,w<x){w++;continue}if(l.length>=i){p=!0,w++;continue}let E=y;E.length>L&&(E=E.slice(0,L)+`... (line truncated to ${L} chars)`);const k=`${w+1}: ${E}`,b=Buffer.byteLength(k,"utf-8")+1;if(f+b>at){m=!0;break}l.push(k),f+=b,w++}if(_>0&&l.length===0&&!p&&!m&&x>=_)throw new Error(`offset ${o} exceeds total line count ${_} in file: ${s}`);const g=l.length>0?o:0,v=l.length>0?o+l.length-1:0;let P;m?P=`Output capped at 50 KB. Showing lines ${g}-${v}. Use offset=${v+1} to continue.`:p?P=`Showing lines ${g}-${v} of ${_}. Use offset=${v+1} to continue.`:P=`End of file - total ${_} lines`;const S=l.length>0?l.join(`
|
|
2
2
|
`)+`
|
|
3
|
-
`+E:E;return{workspaceRoot:a.workspaceRoot,targetPath:s,content:T,isBinary:!1,truncated:y||m,totalLines:m?-1:g,shownFromLine:h,shownToLine:v}}finally{l.close(),c.destroy()}}function z(n){return/^https?:\/\//i.test(n)}async function Ut(n){let e;try{e=new URL(n)}catch{throw new Error(`Invalid image URL: ${n}`)}if(e.protocol!=="http:"&&e.protocol!=="https:")throw new Error(`Unsupported image URL protocol: ${e.protocol} (only http/https)`);let o;try{o=await fetch(n,{signal:AbortSignal.timeout(Pt)})}catch(l){const u=l instanceof Error?l.message:String(l);throw new Error(`Image URL fetch failed: ${n} (${u})`)}if(!o.ok)throw new Error(`Image URL fetch failed: ${n} (HTTP ${o.status})`);const t=(o.headers.get("content-type")||"").split(";")[0]?.trim().toLowerCase()||"";if(t&&!t.startsWith("image/"))throw new Error(`URL did not return an image (content-type: ${t}): ${n}`);const i=Number(o.headers.get("content-length")||"");if(Number.isFinite(i)&&i>A)throw new Error(`Image too large to fetch: ${n} (${S(i)} > ${S(A)})`);const a=o.body;if(!a){const l=await o.arrayBuffer();if(l.byteLength>A)throw new Error(`Image too large to fetch: ${n} (${S(l.byteLength)} > ${S(A)})`);return Buffer.from(l)}const s=a.getReader(),r=[];let c=0;for(;;){const{done:l,value:u}=await s.read();if(l)break;if(u){if(c+=u.byteLength,c>A)throw s.cancel().catch(()=>{}),new Error(`Image too large to fetch: ${n} (${S(c)} > ${S(A)})`);r.push(Buffer.from(u))}}return Buffer.concat(r,c)}async function Dt(n,e,o,t="auto"){let i,a;if(z(e))i=await Ut(e),a=e;else{const x=(await tt(n,e,o)).targetPath,k=await p.stat(x);if(!k.isFile())throw new Error(`Path is not a file: ${x}`);if(k.size>J)throw new Error(`Image file too large to read: ${$(x)} (${S(k.size)} > ${S(J)}). Downscale it first.`);i=await p.readFile(x),a=$(x)}if(i.length===0)throw new Error(`Image file is empty: ${a}`);const s=pt(i);if(!s)throw new Error(`Unsupported or corrupt image (unrecognized format): ${a}`);const r=gt(i);let c=s,l=i,u=r?.width,w=r?.height,g=null;if(t!==!1){const b=await wt(i,s,{normalMaxBytes:xt,clearMaxBytes:Tt});b?.compressed&&(l=b.buffer,c=b.mediaType,u=b.width,w=b.height,g={level:b.level,originalSize:b.originalSize})}let _=!1;const y=await _t(l,c,{maxWidth:C,maxHeight:C,maxBytes:D});if(y)l=y.buffer,c=y.mediaType,u=y.width,w=y.height,_=y.changed;else if(l.length>D)throw new Error(`Image too large to inline: ${a} (${S(l.length)} > ${S(D)}). Downscale it first, e.g. via Bash: magick "${e}" -resize ${C}x${C} "${e}". Installing sharp enables automatic downscaling.`);const m=u&&w?`${u}x${w}`:"unknown dimensions",P=_&&r&&r.width!==u?` (resized from ${r.width}x${r.height})`:_?" (resized)":"",h=g!==null?g.level:null,v=g!==null?Math.max(1,Math.round((1-l.length/g.originalSize)*100)):0,E=g!==null?`${S(l.length)} (compressed from ${S(g.originalSize)}, saved ${v}%, ${h} level)`:S(l.length),T=`[Image: ${a}, ${m}${P}, ${E}]`,f=z(e)?d.basename(new URL(e).pathname)||"image":d.basename(a);return{ok:!0,filePath:a,content:T,isBinary:!1,image:{mediaType:K(c),width:u??null,height:w??null,originalWidth:r?.width??null,originalHeight:r?.height??null,resized:_,size:l.length,compressed:g!==null,compressionLevel:h,compressionRatio:g!==null?Math.round((1-l.length/g.originalSize)*100)/100:null,originalSize:i.length},attachments:[{type:"image",name:f,mediaType:K(c),base64Data:l.toString("base64")}]}}function ot(n){let e="",o=0;for(;o<n.length;){const t=n[o];if(t==="*")e+="[^/]*";else if(t==="?")e+="[^/]";else if(t==="{"){const i=n.indexOf("}",o);if(i>=0){const a=n.slice(o+1,i);e+=`(${a.split(",").join("|")})`,o=i}else e+="\\{"}else if(t==="["){const i=n.indexOf("]",o);i>=0?(e+=n.slice(o,i+1),o=i):e+="\\["}else"+^$.()|\\".includes(t)?e+="\\"+t:e+=t;o++}return new RegExp(`^${e}$`)}async function Wt(n,e,o,t){const i=[];async function a(s){if(i.length>=t)return;const r=await p.readdir(s,{withFileTypes:!0});for(const c of r){if(i.length>=t)return;if(c.name.startsWith(".")&&c.isDirectory())continue;const l=d.join(s,c.name);if(c.isDirectory()){if(It.has(c.name))continue;await a(l)}else if(c.isFile()){if(e&&!e.test(c.name)||o&&o.test(c.name))continue;i.push(l)}}}return await a(n),i}async function zt(n,e,o){if((await p.stat(n)).size>$t)return{matches:[],count:0};if(await Q(n))return{matches:[],count:0};const i=d.relative(e,n).replace(/\\/g,"/"),a=[];let s=0;const r=X(n,{encoding:"utf-8"}),c=Y.createInterface({input:r,crlfDelay:1/0});try{let l=0;for await(const u of c)if(l++,o.regex.test(u)){if(s++,o.collectContent){let w=u;if(w.length>L&&(w=w.slice(0,L)+`... (line truncated to ${L} chars)`),a.push({file:i,line:l,content:w}),a.length>=o.maxResults)break}if(o.stopOnFirstMatch)break}}finally{c.close(),r.destroy()}return{matches:a,count:s}}const qt=12*60*6e4,jt=30*6e4,Gt=6e4,Xt=10*6e4;function Yt(n,e,o){return{kind:"builtin",toolName:"write_file",exposedName:"write_file",description:"Create or overwrite a UTF-8 text file inside the current workspace. Parent directories are created automatically.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to write."},content:{type:"string",description:"Complete UTF-8 file content."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","content"],additionalProperties:!1},async execute(t){const i=M(t,["file_path","filePath"],"file_path"),a=M(t,["content"],"content"),s=R(t,["reason"]),r=await B(n,i);await N(o,"fileModification",{operation:"write",path:r.targetPath});const c=await Z(r.targetPath),l=c?await p.readFile(r.targetPath,"utf-8").catch(()=>null):null,u=await et(n,i,a);if(e){const w=d.relative(u.workspaceRoot,u.targetPath).replace(/\\/g,"/");await e({filePath:w,operation:c?"UPDATE":"CREATE",beforeContent:l,afterContent:a,reason:s})}return{ok:!0,filePath:$(u.targetPath),bytes:u.bytes,createdParentDirectory:u.createdParentDirectory}}}}function Ht(n,e,o){return{kind:"builtin",toolName:"edit_file",exposedName:"edit_file",description:"Replace exactly one occurrence of old_string with new_string in a UTF-8 workspace text file.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to edit."},old_string:{type:"string",description:"Existing text to replace. Must occur exactly once."},new_string:{type:"string",description:"Replacement text."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","old_string","new_string"],additionalProperties:!1},async execute(t){const i=M(t,["file_path","filePath"],"file_path"),a=M(t,["old_string","oldString"],"old_string"),s=M(t,["new_string","newString"],"new_string"),r=R(t,["reason"]);if(!a)throw new Error("old_string must not be empty");const c=await B(n,i);await N(o,"fileModification",{operation:"edit",path:c.targetPath});const l=await Ft(n,i),u=Ot(l.content,a);if(u===0)throw new Error("old_string was not found in file");if(u>1)throw new Error(`old_string occurs ${u} times; provide a unique match`);const w=l.content.replace(a,s),g=await et(n,i,w);if(e){const _=d.relative(g.workspaceRoot,g.targetPath).replace(/\\/g,"/");await e({filePath:_,operation:"UPDATE",beforeContent:l.content,afterContent:w,reason:r})}return{ok:!0,filePath:$(g.targetPath),bytes:g.bytes}}}}function Kt(n,e,o){return{kind:"builtin",toolName:"delete_file",exposedName:"delete_file",description:"Delete a file inside the current workspace. Returns an error if the file does not exist.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to delete."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path"],additionalProperties:!1},async execute(t){const i=M(t,["file_path","filePath"],"file_path"),a=R(t,["reason"]),s=await B(n,i);await N(o,"fileModification",{operation:"delete",path:s.targetPath});const r=O(s.workspaceRoot,await p.realpath(s.targetPath).catch(()=>s.targetPath)),c=await p.stat(r).catch(()=>null);if(!c)throw new Error(`File does not exist: ${r}`);if(!c.isFile())throw new Error(`Path is not a file: ${r}`);const l=await p.readFile(r,"utf-8").catch(()=>null);if(await p.rm(r,{force:!0}),e){const u=d.relative(s.workspaceRoot,r).replace(/\\/g,"/");await e({filePath:u,operation:"DELETE",beforeContent:l,afterContent:null,reason:a})}return{ok:!0,filePath:$(r),deleted:!0}}}}function Vt(n,e){return{kind:"builtin",toolName:"read_file",exposedName:"read_file",description:"Read a UTF-8 text file inside the current workspace. Returns content with line numbers in the format '<line>: <content>'. Supports offset (1-indexed line number to start from) and limit (max lines to return, default 2000). Output is capped at 2000 lines or 50 KB, whichever is reached first. Individual lines longer than 2000 characters are truncated. Avoid tiny repeated slices (e.g. 30-line chunks); read a larger window if more context is needed. Images (.png/.jpg/.jpeg/.gif/.webp) and http(s) image URLs are also supported: the image is inlined into the conversation so you can see it (requires a model with image input). offset/limit are ignored for images. By default (compress='auto') images are compressed before inlining using a tiered ladder that judges by the compressed result, not the original size: lossless first (pixel-exact, dimensions preserved), then high-quality lossy downscaling only if the lossless result is still over 50 KB (normal level), then more aggressive downscaling if still over 100 KB (clear level). When compression applies, the result reports the compression level, compressed size, and compression ratio (e.g. saved 80%). Pass compress=true to also attempt compression, or compress=false to disable it (images exceeding the hard 2000px / 3.75MB inline limits are still auto-downscaled when sharp is available).",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to read. Also accepts an http(s) URL pointing to an image."},offset:{type:"number",description:"Line number to start reading from (1-indexed). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to return. Defaults to 2000."},compress:{anyOf:[{type:"boolean"},{type:"string",enum:["auto"]}],description:'Image compression mode (ignored for text files). "auto" (default): compress with a tiered ladder driven by the compressed result \u2014 lossless, then high-quality downscale if still >50 KB, then more aggressive if still >100 KB. true: same as auto. false: skip tiered compression entirely (hard inline limits still apply).'}},required:["file_path"],additionalProperties:!1},async execute(o){const t=M(o,["file_path","filePath"],"file_path"),i=d.extname(t).toLowerCase().slice(1);if(z(t)||Et.has(i))return await Dt(n,t,e,At(o));const a=U(o,["offset"],1),s=U(o,["limit"],yt),r=await Ct(n,t,a,s,e);return{ok:!0,filePath:$(r.targetPath),content:r.content,isBinary:r.isBinary,truncated:r.truncated,totalLines:r.totalLines,shownFromLine:r.shownFromLine,shownToLine:r.shownToLine}}}}function Jt(n,e,o,t){return{kind:"builtin",toolName:"Bash",exposedName:"Bash",description:"Execute a shell command in the current workspace. Use for local diagnostics, builds, tests, and OS commands. The command runs with a bounded total timeout (timeout_ms) measured from command start \u2014 by default 30 minutes, after which the process is force-terminated; timeout_ms can raise this (up to 12 hours) or set 0 to disable. The tool returns stdout, stderr, exit code, and (if converted to background) a task_id. By default (wait_seconds omitted or -1) the command runs in the FOREGROUND and streams output in real time; if the 5-minute adapter watchdog fires while it is still running, the command is moved to the BACKGROUND and the tool returns a task_id plus an explanation (backgrounded=true, reason=watchdog_timeout). The background command stays bound by the same total timeout (timeout_ms, default 30 minutes, still measured from command start) and can be managed via await_complete / list_background_commands / read_background_output / kill_background_command. For immediate backgrounding use wait_seconds=0, or wait_seconds=n>0 to wait n seconds then background.",inputSchema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute."},cwd:{type:"string",description:"Optional workspace-relative working directory. Defaults to the workspace root."},timeout_ms:{type:"number",description:"Optional total command timeout in milliseconds, measured from command start. Defaults to 1800000 (30 minutes) and is capped at 43200000 (12 hours). Set 0 to disable the timeout entirely (run until finished or killed)."},inactivity_timeout_ms:{type:"number",description:"Optional no-output timeout in milliseconds. Defaults to 60000 and is capped at 600000."},wait_seconds:{type:"number",description:"How to wait for the command to finish. Omitted values (or -1, the default): run in the FOREGROUND until completion; if the 5-minute adapter watchdog fires first, the command is moved to the background and a task_id is returned (backgrounded=true, reason=watchdog_timeout). 0: spawn and immediately execute in the background, return task_id. n>0: wait up to n seconds; if still running, move to the background and return task_id. The command remains bound by the total timeout (timeout_ms, default 30 minutes, measured from command start) whether foreground or background; inactivity_timeout_ms is ignored once backgrounded.",minimum:-1},description:{type:"string",description:"Short reason for running this command (what it does and why it is needed), shown to the user in the background commands panel. Always provide a concise reason, e.g. 'Start local dev server for manual verification'."}},required:["command"],additionalProperties:!1},async execute(i,a){const s=M(i,["command"],"command").trim();if(!s)throw new Error("command must not be empty");const r=Lt(i,["timeout_ms","timeoutMs"],jt),c=r===0?0:Math.min(r,qt),l=U(i,["inactivity_timeout_ms","inactivityTimeoutMs"],Gt),u=Math.min(l,Xt),w=R(i,["cwd"]),g=R(i,["description"]),_=await Bt(n,w);await N(t,"commandExecution",{command:s,cwd:$(_.cwd)});const y=i.wait_seconds,P=typeof y=="number"&&Number.isFinite(y)?y:-1;if(o)return await Zt({deps:o,command:s,agentId:e,workspaceRoot:_.workspaceRoot,cwd:_.cwd,timeoutMs:c,inactivityTimeoutMs:u,waitSeconds:P,description:g,onOutput:a?.onOutput,settleSignal:a?.settleSignal});const h=await at({commandText:s,agentId:e,workspaceRoot:_.workspaceRoot,cwd:_.cwd,timeoutMs:c,inactivityTimeoutMs:u,onOutput:a?.onOutput,watchdogSignal:a?.settleSignal}),v={ok:h.exitCode===0&&!h.timedOut,tool:"Bash",command:s,cwd:$(_.cwd),exitCode:h.exitCode,signal:h.signal,timedOut:h.timedOut,inactivityTimedOut:h.inactivityTimedOut,watchdogInterrupted:h.watchdogInterrupted,timeoutMs:c,inactivityTimeoutMs:u,durationMs:h.durationMs,outputSpilled:h.outputSpilled,outputFilePath:h.outputFilePath,outputLineCount:h.outputLineCount,commandFilePath:h.commandFilePath,commandLineCount:h.commandLineCount,stdout:h.stdout,stderr:h.stderr};return h.watchdogInterrupted?{...v,message:"Command was interrupted by the adapter watchdog after ~5 minutes of synchronous (foreground) execution. Only the partial output produced so far is returned above"+(h.outputFilePath?` (full output spilled to "${h.outputFilePath}"; read it if you need more)`:"")+". For long-running commands, re-run with wait_seconds=0 (or n>0) to execute in the background, then manage via await_complete / list_background_commands / read_background_output / kill_background_command."}:v}}}async function Zt(n){const{deps:e,command:o,agentId:t,workspaceRoot:i,cwd:a,timeoutMs:s,inactivityTimeoutMs:r,waitSeconds:c,description:l,onOutput:u,settleSignal:w}=n,g=u?rt({cwd:a,commandLineCount:0,onOutput:u}):void 0;let _=!!g;const y=()=>{_&&(_=!1,g?.close())};try{const{taskId:m,completion:P}=e.manager.startCommand({commandText:o,agentId:t,workspaceRoot:i,cwd:a,description:l,timeoutMs:s,inactivityTimeoutMs:r,onOutput:_?T=>{_&&g?.push(T.stream,T.text)}:void 0,onCompleted:e.emitCompleted});if(c===0)return e.manager.disableInactivityTimeout(t,m),await e.manager.markBackgrounded(t,m).catch(()=>{}),y(),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"immediate",message:`Command moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, list_background_commands to view all, or kill_background_command(task_id="${m}") to stop.`};const h=c===-1?0:Math.max(0,Math.floor(c*1e3)),v=[P];let E;c!==-1&&v.push(new Promise(T=>{E=setTimeout(()=>T("__timeout__"),h),E.unref?.()})),w&&v.push(w.then(()=>"__settle__"));try{const T=await Promise.race(v);if(T==="__settle__")return e.manager.disableInactivityTimeout(t,m),await e.manager.markBackgrounded(t,m).catch(()=>{}),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"watchdog_timeout",waitedMs:h,message:`Command still running after watchdog timeout; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, or kill_background_command(task_id="${m}") to stop.`};if(T==="__timeout__")return e.manager.disableInactivityTimeout(t,m),await e.manager.markBackgrounded(t,m).catch(()=>{}),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"timeout",waitedMs:h,message:`Command still running after ${c}s; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, or read_background_output(task_id="${m}", mode="tail") / kill_background_command(task_id="${m}") to inspect.`};const f=T;let b=f.stdout,x=f.stderr,k=f.outputSpilled,F=f.outputFilePath;if(!k&&H(`${f.stdout}${f.stderr}`)>ct){const I=await ut(t,"cmd","out",st({commandText:o,commandFilePath:f.commandFilePath,commandLineCount:f.commandLineCount,cwd:a,startedAt:new Date(Date.now()-f.durationMs),endedAt:new Date,exitCode:f.exitCode,signal:f.signal??null,timedOut:f.timedOut,inactivityTimedOut:f.inactivityTimedOut??!1,stdout:b,stderr:x}));b=lt($(I),H(`${f.stdout}${f.stderr}`)),k=!0,F=$(I)}return{ok:f.exitCode===0&&!f.timedOut,tool:"Bash",command:o,backgrounded:!1,taskId:m,exitCode:f.exitCode,signal:f.signal,timedOut:f.timedOut,inactivityTimedOut:f.inactivityTimedOut,timeoutMs:f.timeoutMs,inactivityTimeoutMs:f.inactivityTimeoutMs,durationMs:f.durationMs,outputSpilled:k,outputFilePath:F,outputLineCount:f.outputLineCount,commandFilePath:f.commandFilePath,commandLineCount:f.commandLineCount,stdout:b,stderr:x}}finally{E&&clearTimeout(E),y()}}catch(m){if(m?.code==="too_many_tasks"||m?.code==="global_limit_reached")return{ok:!1,tool:"Bash",command:o,backgrounded:!1,status:"not_executed",error:m.code,message:`Command was NOT executed: ${m.message}. Wait for some background tasks to finish/cleanup (per-agent limit 16, global 256), or reduce concurrent background commands, then retry.`};throw m}}function Qt(n){return{kind:"builtin",toolName:"grep",exposedName:"grep",description:"Search file contents using regular expressions within the workspace. Returns matched lines with file paths and line numbers. Supports include/exclude glob patterns, case-insensitive matching, and three output modes (content, files_with_matches, count). Searches recursively through directories, skipping binary files, hidden directories, and common build/dependency directories (node_modules, .git, dist, etc.).",inputSchema:{type:"object",properties:{pattern:{type:"string",description:"Regular expression pattern to search for in file contents."},path:{type:"string",description:"Workspace-relative file or directory path to search in. Defaults to the workspace root."},include:{type:"string",description:"Glob pattern to filter files by name (e.g. '*.ts', '*.{js,ts}'). Only matching files are searched."},exclude:{type:"string",description:"Glob pattern to exclude files by name (e.g. '*.test.ts'). Matching files are skipped."},case_insensitive:{type:"boolean",description:"Case-insensitive matching. Default false."},output_mode:{type:"string",enum:["content","files_with_matches","count"],description:"Output format: 'content' returns matched lines with line numbers (default), 'files_with_matches' returns only file paths with matches, 'count' returns match counts per file."},max_results:{type:"number",description:"Maximum number of matched lines to return (content mode). Default 1000."}},required:["pattern"],additionalProperties:!1},async execute(e){const o=M(e,["pattern"],"pattern"),t=R(e,["path"])||".",i=R(e,["include"]),a=R(e,["exclude"]),s=e.case_insensitive===!0,r=(()=>{const k=e.output_mode;return k==="files_with_matches"||k==="count"?k:"content"})(),c=U(e,["max_results"],Rt),l=s?"i":"";let u;try{u=new RegExp(o,l)}catch(k){throw new Error(`Invalid regex pattern: ${k instanceof Error?k.message:String(k)}`)}const w=i?ot(i):null,g=a?ot(a):null,_=await B(n,t),y=O(_.workspaceRoot,await p.realpath(_.targetPath)),m=await p.stat(y);let P;if(m.isFile())P=[y];else if(m.isDirectory())P=await Wt(y,w,g,St);else throw new Error(`Path is neither a file nor a directory: ${y}`);const h=[],v=[],E=[];let T=0,f=0,b=!1;for(const k of P){if(r==="content"&&h.length>=c){b=!0;break}const F={regex:u,maxResults:r==="content"?c-h.length:Number.MAX_SAFE_INTEGER,collectContent:r==="content",stopOnFirstMatch:r==="files_with_matches"},I=await zt(k,_.workspaceRoot,F);if(I.count>0){const q=d.relative(_.workspaceRoot,k).replace(/\\/g,"/");if(E.push(q),T+=I.count,r==="content"){for(const j of I.matches){const G=Buffer.byteLength(j.content,"utf-8")+64;if(f+G>Mt){b=!0;break}f+=G,h.push(j)}if(b)break;if(h.length>=c){b=!0;break}}else r==="count"&&v.push({file:q,count:I.count})}}const x={ok:!0,tool:"grep",pattern:o,searchPath:$(_.targetPath),outputMode:r,filesSearched:P.length,filesMatched:E.length,totalMatches:T,truncated:b};return r==="content"?x.matches=h:r==="files_with_matches"?x.matches=E:x.matches=v,x}}}function me(n,e,o,t,i){const a=e||"unknown",s=[Vt(n,i),Yt(n,o,i),Ht(n,o,i),Kt(n,o,i),Qt(n),Jt(n,a,t,i),dt(n)];return t&&s.push(mt(a,t),ht(a,t),ft(a,t)),s}export{de as DEFAULT_TOOL_PERMISSION_POLICY,me as createBuiltInFileTools,O as ensureInsideWorkspace,B as resolveWorkspaceTarget};
|
|
3
|
+
`+P:P;return{workspaceRoot:n.workspaceRoot,targetPath:s,content:S,isBinary:!1,truncated:p||m,totalLines:m?-1:_,shownFromLine:g,shownToLine:v,mtimeMs:Math.trunc(c.mtimeMs),sizeBytes:c.size}}finally{u.close(),r.destroy()}}function j(e){return/^https?:\/\//i.test(e)}async function Zt(e){let t;try{t=new URL(e)}catch{throw new Error(`Invalid image URL: ${e}`)}if(t.protocol!=="http:"&&t.protocol!=="https:")throw new Error(`Unsupported image URL protocol: ${t.protocol} (only http/https)`);let o;try{o=await fetch(e,{signal:AbortSignal.timeout(Ft)})}catch(u){const l=u instanceof Error?u.message:String(u);throw new Error(`Image URL fetch failed: ${e} (${l})`)}if(!o.ok)throw new Error(`Image URL fetch failed: ${e} (HTTP ${o.status})`);const i=(o.headers.get("content-type")||"").split(";")[0]?.trim().toLowerCase()||"";if(i&&!i.startsWith("image/"))throw new Error(`URL did not return an image (content-type: ${i}): ${e}`);const a=Number(o.headers.get("content-length")||"");if(Number.isFinite(a)&&a>F)throw new Error(`Image too large to fetch: ${e} (${T(a)} > ${T(F)})`);const n=o.body;if(!n){const u=await o.arrayBuffer();if(u.byteLength>F)throw new Error(`Image too large to fetch: ${e} (${T(u.byteLength)} > ${T(F)})`);return Buffer.from(u)}const s=n.getReader(),c=[];let r=0;for(;;){const{done:u,value:l}=await s.read();if(u)break;if(l){if(r+=l.byteLength,r>F)throw s.cancel().catch(()=>{}),new Error(`Image too large to fetch: ${e} (${T(r)} > ${T(F)})`);c.push(Buffer.from(l))}}return Buffer.concat(c,r)}async function Qt(e,t,o,i="auto",a){let n,s;if(j(t))n=await Zt(t),s=t;else{const b=(await lt(e,t,o)).targetPath,R=await h.stat(b);if(!R.isFile())throw new Error(`Path is not a file: ${b}`);if(R.size>nt)throw new Error(`Image file too large to read: ${M(b)} (${T(R.size)} > ${T(nt)}). Downscale it first.`);n=await h.readFile(b),s=M(b),a?.tracker&&a.tracker.record(N(b),K(R,null,!0))}if(n.length===0)throw new Error(`Image file is empty: ${s}`);const c=St(n);if(!c)throw new Error(`Unsupported or corrupt image (unrecognized format): ${s}`);const r=xt(n);let u=c,l=n,w=r?.width,_=r?.height,f=null;if(i!==!1){const k=await Tt(n,c,{normalMaxBytes:At,clearMaxBytes:Lt});k?.compressed&&(l=k.buffer,u=k.mediaType,w=k.width,_=k.height,f={level:k.level,originalSize:k.originalSize})}let p=!1;const m=await Mt(l,u,{maxWidth:U,maxHeight:U,maxBytes:X});if(m)l=m.buffer,u=m.mediaType,w=m.width,_=m.height,p=m.changed;else if(l.length>X)throw new Error(`Image too large to inline: ${s} (${T(l.length)} > ${T(X)}). Downscale it first, e.g. via Bash: magick "${t}" -resize ${U}x${U} "${t}". Installing sharp enables automatic downscaling.`);const x=w&&_?`${w}x${_}`:"unknown dimensions",g=p&&r&&r.width!==w?` (resized from ${r.width}x${r.height})`:p?" (resized)":"",v=f!==null?f.level:null,P=f!==null?Math.max(1,Math.round((1-l.length/f.originalSize)*100)):0,S=f!==null?`${T(l.length)} (compressed from ${T(f.originalSize)}, saved ${P}%, ${v} level)`:T(l.length),y=`[Image: ${s}, ${x}${g}, ${S}]`,E=j(t)?d.basename(new URL(t).pathname)||"image":d.basename(s);return{ok:!0,filePath:s,content:y,isBinary:!1,image:{mediaType:it(u),width:w??null,height:_??null,originalWidth:r?.width??null,originalHeight:r?.height??null,resized:p,size:l.length,compressed:f!==null,compressionLevel:v,compressionRatio:f!==null?Math.round((1-l.length/f.originalSize)*100)/100:null,originalSize:n.length},attachments:[{type:"image",name:E,mediaType:it(u),base64Data:l.toString("base64")}]}}function mt(e){let t="",o=0;for(;o<e.length;){const i=e[o];if(i==="*")t+="[^/]*";else if(i==="?")t+="[^/]";else if(i==="{"){const a=e.indexOf("}",o);if(a>=0){const n=e.slice(o+1,a);t+=`(${n.split(",").join("|")})`,o=a}else t+="\\{"}else if(i==="["){const a=e.indexOf("]",o);a>=0?(t+=e.slice(o,a+1),o=a):t+="\\["}else"+^$.()|\\".includes(i)?t+="\\"+i:t+=i;o++}return new RegExp(`^${t}$`)}async function te(e,t,o,i){const a=[];async function n(s){if(a.length>=i)return;const c=await h.readdir(s,{withFileTypes:!0});for(const r of c){if(a.length>=i)return;if(r.name.startsWith(".")&&r.isDirectory())continue;const u=d.join(s,r.name);if(r.isDirectory()){if(Ut.has(r.name))continue;await n(u)}else if(r.isFile()){if(t&&!t.test(r.name)||o&&o.test(r.name))continue;a.push(u)}}}return await n(e),a}async function ee(e,t,o){if((await h.stat(e)).size>Nt)return{matches:[],count:0};if(await st(e))return{matches:[],count:0};const a=d.relative(t,e).replace(/\\/g,"/"),n=[];let s=0;const c=Z(e,{encoding:"utf-8"}),r=Q.createInterface({input:c,crlfDelay:1/0});try{let u=0;for await(const l of r)if(u++,o.regex.test(l)){if(s++,o.collectContent){let w=l;if(w.length>L&&(w=w.slice(0,L)+`... (line truncated to ${L} chars)`),n.push({file:a,line:u,content:w}),n.length>=o.maxResults)break}if(o.stopOnFirstMatch)break}}finally{r.close(),c.destroy()}return{matches:n,count:s}}const oe=12*60*6e4,ie=3*6e4,ae=6e4,re=10*6e4;function ne(e,t,o,i){return{kind:"builtin",toolName:"write_file",exposedName:"write_file",concurrencyMode:"write",resourceKeys:a=>{const n=q(a);return n?[D(e,n,"write")]:[]},description:"Create or overwrite a UTF-8 text file inside the current workspace. Parent directories are created automatically.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to write."},content:{type:"string",description:"Complete UTF-8 file content."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","content"],additionalProperties:!1},async execute(a){const n=$(a,["file_path","filePath"],"file_path"),s=$(a,["content"],"content"),c=O(a,["reason"]),r=await G(e,n,"write",o);await B(o,"fileModification",{operation:"write",path:r.targetPath});const u=await Y(r.targetPath),l=u?await h.readFile(r.targetPath,"utf-8").catch(()=>null):null,w=u?await h.realpath(r.targetPath).catch(()=>r.targetPath):r.targetPath;let _=null;if(i?.enabled&&u){const p=await h.stat(w);_=W(p.mtimeMs,p.size);const m=et(i.tracker,N(w),p,l);if(!m.ok)throw new Error(m.reason)}if(i?.enabled&&_){const p=await h.stat(w).catch(()=>null);if(!p||W(p.mtimeMs,p.size)!==_)throw new Error(ot)}const f=await ut(r,s);if(await dt(i,f.targetPath,s),t&&!f.outsideWorkspace){const p=d.relative(f.workspaceRoot,f.targetPath).replace(/\\/g,"/");await t({filePath:p,operation:u?"UPDATE":"CREATE",beforeContent:l,afterContent:s,reason:c})}return{ok:!0,filePath:M(f.targetPath),bytes:f.bytes,createdParentDirectory:f.createdParentDirectory}}}}function se(e,t,o,i){return{kind:"builtin",toolName:"edit_file",exposedName:"edit_file",concurrencyMode:"write",resourceKeys:a=>{const n=q(a);return n?[D(e,n,"write")]:[]},description:"Replace exactly one occurrence of old_string with new_string in a UTF-8 workspace text file.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to edit."},old_string:{type:"string",description:"Existing text to replace. Must occur exactly once."},new_string:{type:"string",description:"Replacement text."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path","old_string","new_string"],additionalProperties:!1},async execute(a){const n=$(a,["file_path","filePath"],"file_path"),s=$(a,["old_string","oldString"],"old_string"),c=$(a,["new_string","newString"],"new_string"),r=O(a,["reason"]);if(!s)throw new Error("old_string must not be empty");const u=await G(e,n,"edit",o);await B(o,"fileModification",{operation:"edit",path:u.targetPath});const l=u.outsideWorkspace?await Vt(u.targetPath):await Ht(e,n),w=N(l.targetPath);if(i?.enabled){const m=et(i.tracker,w,l.stat,l.content);if(!m.ok)throw new Error(m.reason)}const _=zt(l.content,s);if(_===0)throw new Error("old_string was not found in file");if(_>1)throw new Error(`old_string occurs ${_} times; provide a unique match`);const f=l.content.replace(s,c);if(i?.enabled){const m=await h.stat(l.targetPath).catch(()=>null);if(!m||W(m.mtimeMs,m.size)!==W(l.stat.mtimeMs,l.stat.size))throw new Error(ot)}const p=await ut(u,f);if(await dt(i,p.targetPath,f),t&&!p.outsideWorkspace){const m=d.relative(p.workspaceRoot,p.targetPath).replace(/\\/g,"/");await t({filePath:m,operation:"UPDATE",beforeContent:l.content,afterContent:f,reason:r})}return{ok:!0,filePath:M(p.targetPath),bytes:p.bytes}}}}function ce(e,t,o){return{kind:"builtin",toolName:"delete_file",exposedName:"delete_file",concurrencyMode:"write",resourceKeys:i=>{const a=q(i);return a?[D(e,a,"write")]:[]},description:"Delete a file inside the current workspace. Returns an error if the file does not exist.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to delete."},reason:{type:"string",description:"Optional reason for this change, e.g. what bug is being fixed. Helps humans understand the change later."}},required:["file_path"],additionalProperties:!1},async execute(i){const a=$(i,["file_path","filePath"],"file_path"),n=O(i,["reason"]),s=await G(e,a,"delete",o);await B(o,"fileModification",{operation:"delete",path:s.targetPath});const c=s.outsideWorkspace?await h.realpath(s.targetPath).catch(()=>s.targetPath):I(s.workspaceRoot,await h.realpath(s.targetPath).catch(()=>s.targetPath)),r=await h.stat(c).catch(()=>null);if(!r)throw new Error(`File does not exist: ${c}`);if(!r.isFile())throw new Error(`Path is not a file: ${c}`);const u=await h.readFile(c,"utf-8").catch(()=>null);if(await h.rm(c,{force:!0}),t&&!s.outsideWorkspace){const l=d.relative(s.workspaceRoot,c).replace(/\\/g,"/");await t({filePath:l,operation:"DELETE",beforeContent:u,afterContent:null,reason:n})}return{ok:!0,filePath:M(c),deleted:!0}}}}function le(e,t,o){return{kind:"builtin",toolName:"read_file",exposedName:"read_file",concurrencyMode:"read",resourceKeys:i=>{const a=q(i);return!a||j(a)?[]:[D(e,a,"read")]},description:"Read a UTF-8 text file inside the current workspace. Returns content with line numbers in the format '<line>: <content>'. Supports offset (1-indexed line number to start from) and limit (max lines to return, default 2000). Output is capped at 2000 lines or 50 KB, whichever is reached first. Individual lines longer than 2000 characters are truncated. Avoid tiny repeated slices (e.g. 30-line chunks); read a larger window if more context is needed. Images (.png/.jpg/.jpeg/.gif/.webp) and http(s) image URLs are also supported: the image is inlined into the conversation so you can see it (requires a model with image input). offset/limit are ignored for images. By default (compress='auto') images are compressed before inlining using a tiered ladder that judges by the compressed result, not the original size: lossless first (pixel-exact, dimensions preserved), then high-quality lossy downscaling only if the lossless result is still over 50 KB (normal level), then more aggressive downscaling if still over 100 KB (clear level). When compression applies, the result reports the compression level, compressed size, and compression ratio (e.g. saved 80%). Pass compress=true to also attempt compression, or compress=false to disable it (images exceeding the hard 2000px / 3.75MB inline limits are still auto-downscaled when sharp is available). You may issue several read_file calls in ONE message; independent reads run in parallel.",inputSchema:{type:"object",properties:{file_path:{type:"string",description:"Workspace-relative file path to read. Also accepts an http(s) URL pointing to an image."},offset:{type:"number",description:"Line number to start reading from (1-indexed). Defaults to 1."},limit:{type:"number",description:"Maximum number of lines to return. Defaults to 2000."},compress:{anyOf:[{type:"boolean"},{type:"string",enum:["auto"]}],description:'Image compression mode (ignored for text files). "auto" (default): compress with a tiered ladder driven by the compressed result \u2014 lossless, then high-quality downscale if still >50 KB, then more aggressive if still >100 KB. true: same as auto. false: skip tiered compression entirely (hard inline limits still apply).'}},required:["file_path"],additionalProperties:!1},async execute(i){const a=$(i,["file_path","filePath"],"file_path"),n=d.extname(a).toLowerCase().slice(1);if(j(a)||It.has(n))return await Qt(e,a,t,qt(i),o);const s=z(i,["offset"],1),c=z(i,["limit"],Rt),r=await Jt(e,a,s,c,t);if(o?.tracker){let u=null,l=s!==1||r.truncated||r.isBinary;l||(u=await h.readFile(r.targetPath,"utf-8").catch(()=>null),(u==null||u.length>at)&&(u=null,l=!0)),o.tracker.record(N(r.targetPath),K({mtimeMs:r.mtimeMs,size:r.sizeBytes},u,l))}return{ok:!0,filePath:M(r.targetPath),content:r.content,isBinary:r.isBinary,truncated:r.truncated,totalLines:r.totalLines,shownFromLine:r.shownFromLine,shownToLine:r.shownToLine}}}}function ue(e,t,o,i){return{kind:"builtin",toolName:"Bash",exposedName:"Bash",concurrencyMode:"write",resourceScope:"workspace",resourceKeys:()=>[{key:`workspace:${d.resolve(String(e||"").trim()).replace(/\\/g,"/")}`,access:"write"}],description:"Execute a shell command in the current workspace. Use for local diagnostics, builds, tests, and OS commands. The command runs with a bounded total timeout (timeout_ms) measured from command start \u2014 by default 3 minutes, after which the process is force-terminated; timeout_ms can raise this (up to 12 hours) or set 0 to disable. The tool returns stdout, stderr, exit code, and (if converted to background) a task_id. By default (wait_seconds omitted or -1) the command runs in the FOREGROUND and streams output in real time; if the 5-minute adapter watchdog fires while it is still running, the command is moved to the BACKGROUND and the tool returns a task_id plus an explanation (backgrounded=true, reason=watchdog_timeout). The background command stays bound by the same total timeout (timeout_ms, default 3 minutes, still measured from command start) and can be managed via await_complete / list_background_commands / read_background_output / kill_background_command. For immediate backgrounding use wait_seconds=0, or wait_seconds=n>0 to wait n seconds then background.",inputSchema:{type:"object",properties:{command:{type:"string",description:"Shell command to execute."},cwd:{type:"string",description:"Optional workspace-relative working directory. Defaults to the workspace root."},timeout_ms:{type:"number",description:"Optional total command timeout in milliseconds, measured from command start. Defaults to 180000 (3 minutes) and is capped at 43200000 (12 hours). Set 0 to disable the timeout entirely (run until finished or killed)."},inactivity_timeout_ms:{type:"number",description:"Optional no-output timeout in milliseconds. Defaults to 60000 and is capped at 600000."},wait_seconds:{type:"number",description:"How to wait for the command to finish. Omitted values (or -1, the default): run in the FOREGROUND until completion; if the 5-minute adapter watchdog fires first, the command is moved to the background and a task_id is returned (backgrounded=true, reason=watchdog_timeout). 0: spawn and immediately execute in the background, return task_id. n>0: wait up to n seconds; if still running, move to the background and return task_id. The command remains bound by the total timeout (timeout_ms, default 3 minutes, measured from command start) whether foreground or background; inactivity_timeout_ms is ignored once backgrounded.",minimum:-1},description:{type:"string",description:"Short reason for running this command (what it does and why it is needed), shown to the user in the background commands panel. Always provide a concise reason, e.g. 'Start local dev server for manual verification'."}},required:["command"],additionalProperties:!1},async execute(a,n){const s=$(a,["command"],"command").trim();if(!s)throw new Error("command must not be empty");const c=Dt(a,["timeout_ms","timeoutMs"],ie),r=c===0?0:Math.min(c,oe),u=z(a,["inactivity_timeout_ms","inactivityTimeoutMs"],ae),l=Math.min(u,re),w=O(a,["cwd"]),_=O(a,["description"]),f=await Kt(e,w);await B(i,"commandExecution",{command:s,cwd:M(f.cwd)});const p=a.wait_seconds,x=typeof p=="number"&&Number.isFinite(p)?p:-1;if(o)return await de({deps:o,command:s,agentId:t,workspaceRoot:f.workspaceRoot,cwd:f.cwd,timeoutMs:r,inactivityTimeoutMs:l,waitSeconds:x,description:_,onOutput:n?.onOutput,settleSignal:n?.settleSignal});const g=await pt({commandText:s,agentId:t,workspaceRoot:f.workspaceRoot,cwd:f.cwd,timeoutMs:r,inactivityTimeoutMs:l,onOutput:n?.onOutput,watchdogSignal:n?.settleSignal}),v={ok:g.exitCode===0&&!g.timedOut,tool:"Bash",command:s,cwd:M(f.cwd),exitCode:g.exitCode,signal:g.signal,timedOut:g.timedOut,inactivityTimedOut:g.inactivityTimedOut,watchdogInterrupted:g.watchdogInterrupted,timeoutMs:r,inactivityTimeoutMs:l,durationMs:g.durationMs,outputSpilled:g.outputSpilled,outputFilePath:g.outputFilePath,outputLineCount:g.outputLineCount,commandFilePath:g.commandFilePath,commandLineCount:g.commandLineCount,stdout:g.stdout,stderr:g.stderr};return g.watchdogInterrupted?{...v,message:"Command was interrupted by the adapter watchdog after ~5 minutes of synchronous (foreground) execution. Only the partial output produced so far is returned above"+(g.outputFilePath?` (full output spilled to "${g.outputFilePath}"; read it if you need more)`:"")+". For long-running commands, re-run with wait_seconds=0 (or n>0) to execute in the background, then manage via await_complete / list_background_commands / read_background_output / kill_background_command."}:v}}}async function de(e){const{deps:t,command:o,agentId:i,workspaceRoot:a,cwd:n,timeoutMs:s,inactivityTimeoutMs:c,waitSeconds:r,description:u,onOutput:l,settleSignal:w}=e,_=l?wt({cwd:n,commandLineCount:0,onOutput:l}):void 0;let f=!!_;const p=()=>{f&&(f=!1,_?.close())};try{const{taskId:m,completion:x}=t.manager.startCommand({commandText:o,agentId:i,workspaceRoot:a,cwd:n,description:u,timeoutMs:s,inactivityTimeoutMs:c,onOutput:f?S=>{f&&_?.push(S.stream,S.text)}:void 0,onCompleted:t.emitCompleted});if(r===0)return t.manager.disableInactivityTimeout(i,m),await t.manager.markBackgrounded(i,m).catch(()=>{}),p(),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"immediate",message:`Command moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, list_background_commands to view all, or kill_background_command(task_id="${m}") to stop.`};const g=r===-1?0:Math.max(0,Math.floor(r*1e3)),v=[x];let P;r!==-1&&v.push(new Promise(S=>{P=setTimeout(()=>S("__timeout__"),g),P.unref?.()})),w&&v.push(w.then(()=>"__settle__"));try{const S=await Promise.race(v);if(S==="__settle__")return t.manager.disableInactivityTimeout(i,m),await t.manager.markBackgrounded(i,m).catch(()=>{}),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"watchdog_timeout",waitedMs:g,message:`Command still running after watchdog timeout; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, read_background_output(task_id="${m}", mode="tail") to read output, or kill_background_command(task_id="${m}") to stop.`};if(S==="__timeout__")return t.manager.disableInactivityTimeout(i,m),await t.manager.markBackgrounded(i,m).catch(()=>{}),{ok:!0,tool:"Bash",command:o,backgrounded:!0,taskId:m,status:"backgrounded",reason:"timeout",waitedMs:g,message:`Command still running after ${r}s; moved to background. Use await_complete(bg_cmd_ids=["${m}"]) to block until it finishes, or read_background_output(task_id="${m}", mode="tail") / kill_background_command(task_id="${m}") to inspect.`};const y=S;let E=y.stdout,k=y.stderr,b=y.outputSpilled,R=y.outputFilePath;if(!b&&tt(`${y.stdout}${y.stderr}`)>yt){const A=await bt(i,"cmd","out",gt({commandText:o,commandFilePath:y.commandFilePath,commandLineCount:y.commandLineCount,cwd:n,startedAt:new Date(Date.now()-y.durationMs),endedAt:new Date,exitCode:y.exitCode,signal:y.signal??null,timedOut:y.timedOut,inactivityTimedOut:y.inactivityTimedOut??!1,stdout:E,stderr:k}));E=_t(M(A),tt(`${y.stdout}${y.stderr}`)),b=!0,R=M(A)}return{ok:y.exitCode===0&&!y.timedOut,tool:"Bash",command:o,backgrounded:!1,taskId:m,exitCode:y.exitCode,signal:y.signal,timedOut:y.timedOut,inactivityTimedOut:y.inactivityTimedOut,timeoutMs:y.timeoutMs,inactivityTimeoutMs:y.inactivityTimeoutMs,durationMs:y.durationMs,outputSpilled:b,outputFilePath:R,outputLineCount:y.outputLineCount,commandFilePath:y.commandFilePath,commandLineCount:y.commandLineCount,stdout:E,stderr:k}}finally{P&&clearTimeout(P),p()}}catch(m){if(m?.code==="too_many_tasks"||m?.code==="global_limit_reached")return{ok:!1,tool:"Bash",command:o,backgrounded:!1,status:"not_executed",error:m.code,message:`Command was NOT executed: ${m.message}. Wait for some background tasks to finish/cleanup (per-agent limit 16, global 256), or reduce concurrent background commands, then retry.`};throw m}}function me(e){return{kind:"builtin",toolName:"grep",exposedName:"grep",concurrencyMode:"read",resourceScope:"workspace",resourceKeys:()=>[{key:`workspace:${d.resolve(String(e||"").trim()).replace(/\\/g,"/")}`,access:"read"}],description:"Search file contents using regular expressions within the workspace. Returns matched lines with file paths and line numbers. Supports include/exclude glob patterns, case-insensitive matching, and three output modes (content, files_with_matches, count). Searches recursively through directories, skipping binary files, hidden directories, and common build/dependency directories (node_modules, .git, dist, etc.). You may issue several grep/read_file calls in ONE message; independent searches run in parallel.",inputSchema:{type:"object",properties:{pattern:{type:"string",description:"Regular expression pattern to search for in file contents."},path:{type:"string",description:"Workspace-relative file or directory path to search in. Defaults to the workspace root."},include:{type:"string",description:"Glob pattern to filter files by name (e.g. '*.ts', '*.{js,ts}'). Only matching files are searched."},exclude:{type:"string",description:"Glob pattern to exclude files by name (e.g. '*.test.ts'). Matching files are skipped."},case_insensitive:{type:"boolean",description:"Case-insensitive matching. Default false."},output_mode:{type:"string",enum:["content","files_with_matches","count"],description:"Output format: 'content' returns matched lines with line numbers (default), 'files_with_matches' returns only file paths with matches, 'count' returns match counts per file."},max_results:{type:"number",description:"Maximum number of matched lines to return (content mode). Default 1000."}},required:["pattern"],additionalProperties:!1},async execute(t){const o=$(t,["pattern"],"pattern"),i=O(t,["path"])||".",a=O(t,["include"]),n=O(t,["exclude"]),s=t.case_insensitive===!0,c=(()=>{const b=t.output_mode;return b==="files_with_matches"||b==="count"?b:"content"})(),r=z(t,["max_results"],Wt),u=s?"i":"";let l;try{l=new RegExp(o,u)}catch(b){throw new Error(`Invalid regex pattern: ${b instanceof Error?b.message:String(b)}`)}const w=a?mt(a):null,_=n?mt(n):null,f=await ct(e,i),p=I(f.workspaceRoot,await h.realpath(f.targetPath)),m=await h.stat(p);let x;if(m.isFile())x=[p];else if(m.isDirectory())x=await te(p,w,_,Bt);else throw new Error(`Path is neither a file nor a directory: ${p}`);const g=[],v=[],P=[];let S=0,y=0,E=!1;for(const b of x){if(c==="content"&&g.length>=r){E=!0;break}const R={regex:l,maxResults:c==="content"?r-g.length:Number.MAX_SAFE_INTEGER,collectContent:c==="content",stopOnFirstMatch:c==="files_with_matches"},A=await ee(b,f.workspaceRoot,R);if(A.count>0){const H=d.relative(f.workspaceRoot,b).replace(/\\/g,"/");if(P.push(H),S+=A.count,c==="content"){for(const V of A.matches){const J=Buffer.byteLength(V.content,"utf-8")+64;if(y+J>Ct){E=!0;break}y+=J,g.push(V)}if(E)break;if(g.length>=r){E=!0;break}}else c==="count"&&v.push({file:H,count:A.count})}}const k={ok:!0,tool:"grep",pattern:o,searchPath:M(f.targetPath),outputMode:c,filesSearched:x.length,filesMatched:P.length,totalMatches:S,truncated:E};return c==="content"?k.matches=g:c==="files_with_matches"?k.matches=P:k.matches=v,k}}}function xe(e,t,o,i,a,n){const s=t||"unknown",c=[le(e,a,n),ne(e,o,a,n),se(e,o,a,n),ce(e,o,a),me(e),ue(e,s,i,a),kt(e)];return i&&c.push(vt(s,i),Pt(s,i),Et(s,i)),c}export{Se as DEFAULT_TOOL_PERMISSION_POLICY,jt as buildFileResourceKey,xe as createBuiltInFileTools,I as ensureInsideWorkspace,D as fileResourceClaim,ct as resolveWorkspaceTarget};
|
|
4
4
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{buildFileResourceKey as a}from"./built-in-file-tools.js";import{extractSymbols as l}from"./parsers/symbol-extractor.js";const u="Query code symbols (definitions, references, outline) by parsing file AST via tree-sitter. Unlike grep (text matching), this tool understands syntax structure \u2014 no false positives from comments/strings, and it knows whether 'foo' is a function, class, variable, or method. Supports 13 languages: TypeScript, JavaScript, Python, Go, Rust, Java, C, C++, C#, Ruby, PHP, Lua, Bash. Single-file scope (no cross-file reference resolution). Falls back to grep for files in unsupported languages.\n\nWhen to use `symbols` vs `grep`:\n- Use `symbols` when you need to find function/class/method **declarations** or their **type-aware usages** in supported languages. It avoids false positives from comments/strings.\n- Use `grep` for: cross-file text search, unsupported languages (e.g., Markdown, YAML), searching non-symbol patterns (TODOs, log strings, config values), or when `symbols` returns \"unsupported language\".";function h(t){return{kind:"builtin",toolName:"symbols",exposedName:"symbols",concurrencyMode:"read",resourceKeys:e=>{const n=e.path;return typeof n!="string"||n.trim().length===0?[]:[{key:a(t,n.trim()),access:"read"}]},description:u,inputSchema:{type:"object",properties:{path:{type:"string",description:"Workspace-relative file path to analyze. Must be a single file (not a directory)."},mode:{type:"string",enum:["definitions","references","outline"],description:"Query mode: 'definitions' finds symbol declarations matching pattern/kind (e.g., function/class/method declarations); 'references' finds all usages of symbols matching pattern (e.g., calls, type annotations, assignments); 'outline' returns the full symbol structure of the file (ignores pattern/kind filters)."},pattern:{type:"string",description:"Optional regex to filter symbol names (case-sensitive by default; use (?i) prefix for case-insensitive). In 'outline' mode this is ignored. Example: '^getUser' matches getUserById, getUserByEmail."},kind:{type:"string",enum:["function","class","method","variable","import","all"],description:"Symbol kind filter. 'all' (default) returns all kinds. Note: not all languages distinguish all kinds (e.g., Bash has no 'class')."},max_results:{type:"number",description:"Maximum number of symbols to return. Default 100."}},required:["path","mode"],additionalProperties:!1},async execute(e){const n=c(e,["path"],"path"),s=d(e),r=f(e,["pattern"]),o=m(e),i=p(e,["max_results"],100);return l(t,n,s,{pattern:r,kind:o,maxResults:i})}}}function c(t,e,n){for(const s of e){const r=t[s];if(typeof r=="string")return r}throw new Error(`${n} is required`)}function f(t,e){for(const n of e){const s=t[n];if(typeof s=="string"&&s.trim())return s}}function d(t){const e=t.mode;if(e==="definitions"||e==="references"||e==="outline")return e;throw new Error("mode must be one of: definitions, references, outline")}function m(t){const e=t.kind;if(e==null||e==="all")return"all";if(e==="function"||e==="class"||e==="method"||e==="variable"||e==="import"||e==="error")return e;throw new Error("kind must be one of: function, class, method, variable, import, all")}function p(t,e,n){for(const s of e){const r=t[s],o=typeof r=="number"?r:typeof r=="string"?Number(r):NaN;if(Number.isFinite(o)&&o>0)return Math.floor(o)}return n}export{h as symbolsTool};
|
|
2
2
|
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export type FinishReasonOverflowDecision = {
|
|
4
|
+
kind: "none";
|
|
5
|
+
} | {
|
|
6
|
+
kind: "output_limit";
|
|
7
|
+
marker: string;
|
|
8
|
+
} | {
|
|
9
|
+
kind: "context_overflow";
|
|
10
|
+
marker: string;
|
|
11
|
+
source: "finish_reason" | "stop_reason";
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export declare function resolveFinishReasonOverflow(input: {
|
|
15
|
+
finishReason?: string | null;
|
|
16
|
+
stopReason?: string | null;
|
|
17
|
+
}): FinishReasonOverflowDecision;
|
|
18
|
+
|
|
19
|
+
export declare function isContextOverflowError(error: unknown): boolean;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const m=new Set(["length","max_tokens","max_output_tokens","max_completion_tokens","max_tokens_reached","output_limit","output_token_limit","token_limit"]),f=new Set(["context_exceeded","context_length_exceeded","context_window_exceeded","model_context_window_exceeded","max_context_length_exceeded","context_overflow","prompt_too_long","input_too_long"]),x=["context_length_exceeded","context length","maximum context","max context","token limit","tokens exceed","too many tokens","input is too long","prompt is too long","request too large","413"],p=6,d=["type","code","reason","stopReason","stop_reason","name"];function R(e){const t=[{source:"finish_reason",value:e.finishReason},{source:"stop_reason",value:e.stopReason}];for(const o of t){const n=i(o.value);if(n&&m.has(n))return{kind:"output_limit",marker:n}}for(const o of t){const n=i(o.value);if(n&&f.has(n))return{kind:"context_overflow",marker:n,source:o.source}}return{kind:"none"}}function h(e){let t=e;const o=new WeakSet;for(let n=0;n<=p;n+=1){if(t==null)return!1;if(typeof t=="string")return!!_(t);if(typeof t!="object"||o.has(t))return!1;o.add(t);const r=t;for(const c of d){const s=i(u(r[c]));if(s&&f.has(s))return!0}for(const c of["context","error","details"]){const s=r[c];if(k(s))for(const l of d){const a=i(u(s[l]));if(a&&f.has(a))return!0}}if(_(u(r.message)))return!0;t=r.cause??r.lastError??r.error}return!1}function i(e){if(e==null)return;const t=e.trim().toLowerCase();return t.length>0?t:void 0}function u(e){if(typeof e=="string")return e;if(typeof e=="number"&&Number.isFinite(e))return String(e)}function _(e){if(!e)return!1;const t=e.toLowerCase();return x.some(o=>t.includes(o))}function k(e){return!!(e&&typeof e=="object"&&!Array.isArray(e))}export{h as isContextOverflowError,R as resolveFinishReasonOverflow};
|
|
2
|
+
|
|
Binary file
|
|
@@ -10,9 +10,11 @@ export * from './sub-agent-store.js';
|
|
|
10
10
|
export * from './sub-agent-manager.js';
|
|
11
11
|
export * from './sub-agent-tools.js';
|
|
12
12
|
export * from './built-in-file-tools.js';
|
|
13
|
+
export * from './read-file-state.js';
|
|
14
|
+
export * from './tool-concurrency/index.js';
|
|
13
15
|
export * from './terminal-types.js';
|
|
14
16
|
export * from './plugin-types.js';
|
|
15
|
-
export * from './
|
|
17
|
+
export * from './tool-group-manager.js';
|
|
16
18
|
export * from './parsers/types.js';
|
|
17
19
|
export * from './parsers/tree-sitter-loader.js';
|
|
18
20
|
export * from './parsers/ast-cache.js';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export*from"./commands/commandRegistry.js";export*from"./commands/commandLoader.js";export*from"./commands/commandParser.js";export*from"./config.js";export*from"./hooks/hookBus.js";export*from"./runtime.js";export*from"./types.js";export*from"./sub-agent-types.js";export*from"./sub-agent-store.js";export*from"./sub-agent-manager.js";export*from"./sub-agent-tools.js";export*from"./built-in-file-tools.js";export*from"./terminal-types.js";export*from"./plugin-types.js";export*from"./
|
|
1
|
+
export*from"./commands/commandRegistry.js";export*from"./commands/commandLoader.js";export*from"./commands/commandParser.js";export*from"./config.js";export*from"./hooks/hookBus.js";export*from"./runtime.js";export*from"./types.js";export*from"./sub-agent-types.js";export*from"./sub-agent-store.js";export*from"./sub-agent-manager.js";export*from"./sub-agent-tools.js";export*from"./built-in-file-tools.js";export*from"./read-file-state.js";export*from"./tool-concurrency/index.js";export*from"./terminal-types.js";export*from"./plugin-types.js";export*from"./tool-group-manager.js";export*from"./parsers/types.js";export*from"./parsers/tree-sitter-loader.js";export*from"./parsers/ast-cache.js";export*from"./parsers/language-detector.js";export*from"./parsers/language-queries.js";export*from"./parsers/symbol-extractor.js";export*from"./built-in-symbols-tool.js";
|
|
2
2
|
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import type { Tree } from "web-tree-sitter";
|
|
2
2
|
|
|
3
|
+
export interface AcquiredTree {
|
|
4
|
+
readonly tree: Tree;
|
|
5
|
+
release(): void;
|
|
6
|
+
}
|
|
7
|
+
|
|
3
8
|
export declare class AstCache {
|
|
4
9
|
private map;
|
|
5
10
|
private readonly capacity;
|
|
6
11
|
constructor(capacity?: number);
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
private dispose;
|
|
14
|
+
|
|
15
|
+
acquire(absolutePath: string, mtimeMs: number, size: number, language?: string): AcquiredTree | null;
|
|
16
|
+
|
|
17
|
+
store(absolutePath: string, tree: Tree, language: string, mtimeMs: number, size: number): AcquiredTree | null;
|
|
18
|
+
|
|
19
|
+
get(absolutePath: string, mtimeMs: number, size: number, language?: string): Tree | null;
|
|
9
20
|
|
|
10
21
|
set(absolutePath: string, tree: Tree, language: string, mtimeMs: number, size: number): void;
|
|
11
22
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class
|
|
1
|
+
class f{constructor(e=100){if(this.map=new Map,e<1)throw new Error(`capacity must be >= 1, got ${e}`);this.capacity=e}dispose(e){if(e.refs>0){e.pendingDelete=!0;return}e.tree.delete(),e.pendingDelete=!0}acquire(e,i,n,s){const t=this.map.get(e);if(!t)return null;if(t.mtimeMs!==i||t.size!==n||s!==void 0&&t.language!==s)return this.dispose(t),this.map.delete(e),null;this.map.delete(e),this.map.set(e,t),t.refs+=1;let r=!1;return{tree:t.tree,release:()=>{r||(r=!0,t.refs-=1,t.refs<=0&&t.pendingDelete&&t.tree.delete())}}}store(e,i,n,s,t){const r=this.map.get(e);return r&&r.mtimeMs===s&&r.size===t&&r.language===n?null:(this.set(e,i,n,s,t),this.acquire(e,s,t,n))}get(e,i,n,s){const t=this.map.get(e);return t?t.mtimeMs!==i||t.size!==n||s!==void 0&&t.language!==s?(this.dispose(t),this.map.delete(e),null):(this.map.delete(e),this.map.set(e,t),t.tree):null}set(e,i,n,s,t){const r=this.map.get(e);for(r&&(this.dispose(r),this.map.delete(e)),this.map.set(e,{tree:i,language:n,mtimeMs:s,size:t,refs:0,pendingDelete:!1});this.map.size>this.capacity;){const p=this.map.keys().next().value;if(p===void 0)break;const d=this.map.get(p);d&&this.dispose(d),this.map.delete(p)}}invalidate(e){const i=this.map.get(e);i&&(this.dispose(i),this.map.delete(e))}clear(){for(const e of this.map.values())this.dispose(e);this.map.clear()}size(){return this.map.size}}const l=new f(100);export{f as AstCache,l as astCache};
|
|
2
2
|
|
|
@@ -46,5 +46,5 @@ const e={definitions:[{kind:"function",hasEndLine:!0,query:"(function_declaratio
|
|
|
46
46
|
`},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_declaration name: (identifier) @name) @node"}]},i={definitions:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_definition name: (identifier) @name) @node"},{kind:"import",query:"(import_statement name: (dotted_name) @name) @node"},{kind:"import",query:`
|
|
47
47
|
(import_from_statement
|
|
48
48
|
module_name: (dotted_name) @name) @node
|
|
49
|
-
`}],references:[{kind:"function",query:"(call function: (identifier) @name) @node"},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_definition name: (identifier) @name) @node"}]},a={definitions:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(type_declaration (type_spec name: (type_identifier) @name) @node)"},{kind:"method",hasEndLine:!0,query:"(method_declaration name: (field_identifier) @name) @node"},{kind:"import",query:"(import_declaration (import_spec path: (interpreted_string_literal) @name) @node)"}],references:[{kind:"function",query:"(call_expression function: (identifier) @name) @node"},{kind:"function",query:"(call_expression function: (selector_expression field: (field_identifier) @name) @node)"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(type_declaration (type_spec name: (type_identifier) @name) @node)"}]},
|
|
49
|
+
`}],references:[{kind:"function",query:"(call function: (identifier) @name) @node"},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_definition name: (identifier) @name) @node"}]},a={definitions:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(type_declaration (type_spec name: (type_identifier) @name) @node)"},{kind:"method",hasEndLine:!0,query:"(method_declaration name: (field_identifier) @name) @node"},{kind:"import",query:"(import_declaration (import_spec path: (interpreted_string_literal) @name) @node)"}],references:[{kind:"function",query:"(call_expression function: (identifier) @name) @node"},{kind:"function",query:"(call_expression function: (selector_expression field: (field_identifier) @name) @node)"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(type_declaration (type_spec name: (type_identifier) @name) @node)"}]},d={definitions:[{kind:"function",hasEndLine:!0,query:"(function_item name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(struct_item name: (type_identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(trait_item name: (type_identifier) @name) @node"},{kind:"function",hasEndLine:!0,query:"(impl_item body: (declaration_list (function_item name: (identifier) @name) @node))"},{kind:"import",query:"(use_declaration argument: [(identifier) (scoped_identifier)] @name) @node"}],references:[{kind:"function",query:"(call_expression function: (identifier) @name) @node"},{kind:"function",query:"(call_expression function: (field_expression field: (field_identifier) @name) @node)"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_item name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(struct_item name: (type_identifier) @name) @node"}]},t={definitions:[{kind:"function",hasEndLine:!0,query:"(method_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(interface_declaration name: (identifier) @name) @node"},{kind:"import",query:"(import_declaration [(scoped_identifier) (identifier)] @name) @node"}],references:[{kind:"function",query:"(method_invocation name: (identifier) @name) @node"},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"class",hasEndLine:!0,query:"(class_declaration name: (identifier) @name) @node"},{kind:"function",hasEndLine:!0,query:"(method_declaration name: (identifier) @name) @node"}]},r={definitions:[{kind:"function",hasEndLine:!0,query:"(function_definition declarator: (function_declarator declarator: (identifier) @name) @node)"},{kind:"variable",hasEndLine:!0,query:"(declaration declarator: (init_declarator declarator: (identifier) @name) @node)"}],references:[{kind:"function",query:"(call_expression function: (identifier) @name) @node"},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition declarator: (function_declarator declarator: (identifier) @name) @node)"}]},o={definitions:[{kind:"function",hasEndLine:!0,query:"(function_definition declarator: (function_declarator declarator: (identifier) @name) @node)"},{kind:"class",hasEndLine:!0,query:"(class_specifier name: (type_identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(struct_specifier name: (type_identifier) @name) @node"},{kind:"function",hasEndLine:!0,query:"(declaration declarator: (function_declarator declarator: (identifier) @name) @node)"}],references:[{kind:"function",query:"(call_expression function: (identifier) @name) @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition declarator: (function_declarator declarator: (identifier) @name) @node)"},{kind:"class",hasEndLine:!0,query:"(class_specifier name: (type_identifier) @name) @node"}]},s={definitions:[{kind:"function",hasEndLine:!0,query:"(method_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_declaration name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(interface_declaration name: (identifier) @name) @node"},{kind:"import",query:"(using_directive [(qualified_name) (identifier)] @name) @node"}],references:[{kind:"function",query:"(invocation_expression function: (identifier) @name) @node"}],outline:[{kind:"class",hasEndLine:!0,query:"(class_declaration name: (identifier) @name) @node"},{kind:"function",hasEndLine:!0,query:"(method_declaration name: (identifier) @name) @node"}]},u={definitions:[{kind:"function",hasEndLine:!0,query:"(method name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class name: (constant) @name) @node"},{kind:"class",hasEndLine:!0,query:"(module name: (constant) @name) @node"}],references:[{kind:"function",query:"(call method: (identifier) @name) @node"},{kind:"variable",query:"(identifier) @name @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(method name: (identifier) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class name: (constant) @name) @node"}]},c={definitions:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (name) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_declaration name: (name) @name) @node"},{kind:"method",hasEndLine:!0,query:"(method_declaration name: (name) @name) @node"}],references:[{kind:"function",query:"(function_call_expression function: (name) @name) @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (name) @name) @node"},{kind:"class",hasEndLine:!0,query:"(class_declaration name: (name) @name) @node"}]},m={definitions:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"method",hasEndLine:!0,query:"(function_declaration name: (dot_index_expression field: (identifier) @name)) @node"},{kind:"variable",query:"(variable_declaration (assignment_statement (variable_list name: (identifier) @name))) @node"}],references:[{kind:"function",query:"(function_call name: (identifier) @name) @node"},{kind:"method",query:"(function_call name: (dot_index_expression field: (identifier) @name)) @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_declaration name: (identifier) @name) @node"},{kind:"method",hasEndLine:!0,query:"(function_declaration name: (dot_index_expression field: (identifier) @name)) @node"}]},f={definitions:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (word) @name) @node"},{kind:"variable",query:"(variable_assignment name: (variable_name) @name) @node"}],references:[{kind:"function",query:"(command name: (command_name) @name) @node"},{kind:"variable",query:"(simple_expansion (variable_name) @name) @node"}],outline:[{kind:"function",hasEndLine:!0,query:"(function_definition name: (word) @name) @node"}]},l={typescript:e,tsx:e,javascript:n,jsx:n,python:i,go:a,rust:d,java:t,c:r,cpp:o,"c-sharp":s,ruby:u,php:c,lua:m,bash:f},_=Object.keys(l);export{l as LANGUAGE_QUERIES,_ as SUPPORTED_LANGUAGES};
|
|
50
50
|
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{promises as
|
|
2
|
-
`);let
|
|
1
|
+
import{promises as b}from"node:fs";import{resolveWorkspaceTarget as F,ensureInsideWorkspace as O}from"../built-in-file-tools.js";import{astCache as U}from"./ast-cache.js";import{detectLanguage as I}from"./language-detector.js";import{LANGUAGE_QUERIES as N}from"./language-queries.js";import{getParserForLanguage as P,loadLanguage as X}from"./tree-sitter-loader.js";const $=1024*1024,z=256*1024,Q=100,W=500,B=new WeakMap;function Y(r){let e=0;for(let t=0;t<r.length;t++)e=(e<<5)-e+r.charCodeAt(t)|0;return e.toString(16)}async function v(r,e,t){let o=B.get(r);o||(o=new Map,B.set(r,o));const n=`${e}:${Y(t)}`,a=o.get(n);if(a)return a;const{Query:d}=await import("web-tree-sitter"),i=new d(r,t);return o.set(n,i),i}function m(r){return r.replace(/\\/g,"/")}function D(r,e,t,o){const n={kind:t.kind,name:e,line:r.startPosition.row+1};if(t.hasEndLine&&(n.endLine=r.endPosition.row+1),n.column=r.startPosition.column+1,t.hasEndLine||t.kind==="import"){const a=o[r.startPosition.row]??"";n.signature=a.trim()}if(!t.hasEndLine&&t.kind!=="import"){const a=o[r.startPosition.row]??"";n.context=a}return n}async function tt(r,e,t,o){const n=Math.min(o.maxResults??Q,W),a=o.kind??"all",d=await F(r,e),i=O(d.workspaceRoot,await b.realpath(d.targetPath)),l=await b.stat(i);if(!l.isFile())throw new Error(`Path is not a file: ${e}`);if(l.size>$)return{ok:!0,tool:"symbols",path:m(e),mode:t,language:"unknown",symbols:[],truncated:!1,error:"file too large"};const s=I(i);if(!s)return{ok:!0,tool:"symbols",path:m(e),mode:t,language:"unknown",symbols:[],truncated:!1,error:"unsupported language"};const L=await X(s);if(!L)return{ok:!0,tool:"symbols",path:m(e),mode:t,language:s,symbols:[],truncated:!1,error:"grammar load failed"};const h=U.acquire(i,l.mtimeMs,l.size,s);let S=!1,p;if(h)p=h.tree;else{const y=await P(s);if(!y)return{ok:!0,tool:"symbols",path:m(e),mode:t,language:s,symbols:[],truncated:!1,error:"grammar load failed"};const u=await b.readFile(i,"utf-8"),g=y.parse(u);if(!g)return{ok:!0,tool:"symbols",path:m(e),mode:t,language:s,symbols:[],truncated:!1,error:"parse failed"};const f=U.store(i,g,s,l.mtimeMs,l.size);p=g,S=f===null}const C=()=>{S?p.delete():h?.release()};try{const y=N[s]?.[t]??[],u=[],g=p.rootNode.text.split(`
|
|
2
|
+
`);let f=!1,E=0,w=null;if(o.pattern)try{w=new RegExp(o.pattern)}catch(c){throw new Error(`Invalid pattern regex: ${c instanceof Error?c.message:String(c)}`)}for(const c of y){if(u.length>=n){f=!0;break}if(a!=="all"&&c.kind!==a)continue;const q=(await v(L,t,c.query)).matches(p.rootNode);for(const M of q){if(u.length>=n){f=!0;break}const _=M.captures.find(k=>k.name==="name"),x=M.captures.find(k=>k.name==="node");if(!_||!x)continue;const T=_.node.text;if(w&&!w.test(T))continue;const A=D(x.node,T,c,g),R=Buffer.byteLength(JSON.stringify(A),"utf-8")+64;if(E+R>z){f=!0;break}E+=R,u.push(A)}}return{ok:!0,tool:"symbols",path:m(e),mode:t,language:s,symbols:u,truncated:f}}finally{C()}}export{tt as extractSymbols};
|
|
3
3
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Parser, Language } from "web-tree-sitter";
|
|
2
2
|
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function getParserForLanguage(language: string): Promise<Parser | null>;
|
|
4
4
|
|
|
5
5
|
export declare function loadLanguage(language: string): Promise<Language | null>;
|
|
6
6
|
|