(options: WriteToolOptions)
| 19 | }); |
| 20 | |
| 21 | export function createWriteTool(options: WriteToolOptions): Tool<z.infer<typeof inputSchema>> { |
| 22 | const { store } = options; |
| 23 | const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES; |
| 24 | |
| 25 | return tool({ |
| 26 | description: "Write content to a file. Overwrites any existing file at the path.", |
| 27 | inputSchema, |
| 28 | execute: async ({ path, content }) => { |
| 29 | const bytes = new TextEncoder().encode(content); |
| 30 | if (bytes.length > maxBytes) { |
| 31 | return { |
| 32 | error: `Content too large: ${bytes.length} bytes exceeds the ${maxBytes}-byte write cap. Use the edit tool for incremental changes to existing files, or split the write into smaller pieces.`, |
| 33 | }; |
| 34 | } |
| 35 | try { |
| 36 | // Preserve the existing file's mode when overwriting so executable |
| 37 | // scripts don't silently lose their +x bit. For new files we leave |
| 38 | // `mode` undefined and let the store apply its own default. |
| 39 | const existing = await store.stat(path); |
| 40 | await store.write(path, bytes, existing ? { mode: existing.mode } : undefined); |
| 41 | return { path, bytesWritten: bytes.length }; |
| 42 | } catch (err) { |
| 43 | return { error: err instanceof Error ? err.message : String(err) }; |
| 44 | } |
| 45 | }, |
| 46 | }); |
| 47 | } |
no test coverage detected