eve
Version:
Filesystem-first framework for durable backend AI agents that run anywhere.
1 lines • 3.04 kB
JavaScript
import{defineTool}from"eve/tools";const inputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`,minLength:1,description:`Absolute path below /source to edit.`},edits:{type:`array`,minItems:1,items:{type:`object`,additionalProperties:!1,properties:{oldText:{type:`string`,minLength:1,description:`Unique exact text from the current file. Encode control characters, quotes, and backslashes as JSON escapes.`},newText:{type:`string`,description:`Exact replacement text. Encode control characters, quotes, and backslashes as JSON escapes.`}},required:[`oldText`,`newText`]},description:`One or more targeted replacements. Each edit is matched against the original file, not incrementally. Do not include overlapping or nested edits. If two changes touch the same block or nearby lines, merge them into one edit instead.`}},required:[`path`,`edits`]},outputSchema={type:`object`,additionalProperties:!1,properties:{path:{type:`string`},replacements:{type:`integer`,minimum:1}},required:[`path`,`replacements`]};function applyExactEdits(e,t){if(t.length===0)throw Error(`edits must contain at least one replacement.`);let n=[...t.map((t,n)=>{if(t.oldText.length===0)throw Error(`edits[${n}].oldText must not be empty.`);let r=e.indexOf(t.oldText);if(r===-1)throw Error(`edits[${n}].oldText was not found in the current file. Read the file and try again.`);if(e.indexOf(t.oldText,r+1)!==-1)throw Error(`edits[${n}].oldText occurs more than once. Include more surrounding text to make it unique.`);return{...t,end:r+t.oldText.length,index:n,start:r}})].sort((e,t)=>e.start-t.start);for(let e=1;e<n.length;e+=1){let t=n[e-1],r=n[e];if(t!==void 0&&r!==void 0&&r.start<t.end)throw Error(`edits[${t.index}] and edits[${r.index}] overlap. Merge them into one edit.`)}return n.toReversed().reduce((e,t)=>e.slice(0,t.start)+t.newText+e.slice(t.end),e)}var edit_file_default=defineTool({description:`Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file. If two changes affect the same block or nearby lines, merge them into one edit instead of emitting overlapping edits. Do not include large unchanged regions just to connect distant changes.`,inputSchema,outputSchema,async execute(e,t){let{edits:n,path:r}=e;if(typeof r!=`string`||!Array.isArray(n)||n.some(e=>typeof e!=`object`||!e||typeof e.oldText!=`string`||typeof e.newText!=`string`))throw Error(`path must be a string and edits must contain oldText and newText strings.`);let i=await t.getSandbox(),a=i.resolvePath(r);if(!a.startsWith(`/source/`)||a.split(`/`).some(e=>e===`..`))throw Error(`Self-modification file edits must stay below /source.`);let o=await i.readTextFile({path:a});if(o===null)throw Error(`File not found: ${r}.`);if(o.includes(`\0`))throw Error(`File "${r}" contains NUL bytes and appears to be binary.`);return await i.writeTextFile({content:applyExactEdits(o,n),path:a}),{path:a,replacements:n.length}}});export{applyExactEdits,edit_file_default as default};