-- Write text to a file, creating parent directories as needed. Keep the -- description terse because every byte of every tool description rides -- in the system prompt on every turn. local std = require("_std") local tool = { name = "std.write", description = "Save content to a path. Overwrites existing files; missing parent directories are created automatically.", schema = { type = "object", properties = { path = { type = "string", description = "Path to the file (relative or absolute)." }, content = { type = "string", description = "Exact bytes to write. No newline is added." }, }, required = { "path", "content" }, }, } tool.handler = function(input) local path = input.path local content = input.content if type(path) ~= "string" or path == "" then return "Error: `path` must be a non-empty string." end if type(content) ~= "string" then return "Error: `content` must be a string." end local parent = std.dirname(path) if parent then local ok, err = std.mkdir_p_async(parent) if not ok then return "Error: could not create parent directory " .. parent .. ": " .. tostring(err) end end local open_err, fd = std.fs_open(path, "w", tonumber("644", 8)) if not fd then return "Error: " .. (open_err or ("could not open " .. path .. " for writing")) end -- A single `fs_write` may short-write; loop until all bytes land. local offset = 0 while offset < #content do local werr, n = std.fs_write(fd, content:sub(offset + 1), offset) if not n then std.fs_close(fd) return "Error: write failed: " .. tostring(werr) end offset = offset + n end local close_err = std.fs_close(fd) if close_err then return "Error: close failed: " .. tostring(close_err) end return string.format("Wrote %d bytes to %s.", #content, path) end std.install_renderer(tool.name, function(st) local obj = std.decode(st.input) return "write " .. tostring(obj and obj.path or "") end) return tool