feat: write_file 全面增强 — base64写二进制/mode(overwrite+append)/覆盖提示/10MB/返回行数+文件大小

This commit is contained in:
thzxx
2026-06-10 14:15:26 +08:00
parent da249d43de
commit 04f2446337
2 changed files with 58 additions and 12 deletions
+53 -9
View File
@@ -154,33 +154,77 @@ function extToMime(ext: string): string {
return map[ext] || 'application/octet-stream';
}
export async function handleWriteFile(params: { path: string; content: string; encoding?: string }): Promise<ToolResult> {
export async function handleWriteFile(params: { path: string; content: string; encoding?: string; mode?: string }): Promise<ToolResult> {
try {
const filePath = resolvePath(params.path);
const allowed = checkPathAllowed(filePath, 'write');
if (!allowed.ok) return { success: false, error: allowed.reason };
if (params.content.length > 5 * 1024 * 1024) {
return { success: false, error: '内容过大,最大支持 5MB' };
const writeMode = params.mode || 'overwrite';
const encoding = (params.encoding as BufferEncoding) || 'utf-8';
// ── base64 解码:支持写入二进制文件 ──
let writeBuffer: Buffer;
let contentLength: number;
if (encoding === 'base64') {
writeBuffer = Buffer.from(params.content, 'base64');
contentLength = writeBuffer.length;
} else {
writeBuffer = Buffer.from(params.content, encoding);
contentLength = Buffer.byteLength(params.content, encoding);
}
let created = false;
const MAX_SIZE = writeMode === 'append' ? 5 * 1024 * 1024 : 10 * 1024 * 1024;
if (contentLength > MAX_SIZE) {
return { success: false, error: `内容过大 (${(contentLength / 1024 / 1024).toFixed(1)}MB),最大支持 ${MAX_SIZE / 1024 / 1024}MB` };
}
// ── 检查目标文件状态 ──
let existed = false;
let prevSize = 0;
let prevLines = 0;
try {
await fs.stat(filePath);
const prevStat = await fs.stat(filePath);
existed = true;
prevSize = prevStat.size;
if (writeMode === 'overwrite' && !params.encoding?.startsWith('base64')) {
const prevContent = await fs.readFile(filePath, 'utf-8');
prevLines = prevContent.split('\n').length;
}
} catch {
created = true;
// 文件不存在,正常
}
const dir = path.dirname(filePath);
await fs.mkdir(dir, { recursive: true });
await fs.writeFile(filePath, params.content, (params.encoding as BufferEncoding) || 'utf-8');
if (writeMode === 'append') {
await fs.appendFile(filePath, writeBuffer);
} else {
await fs.writeFile(filePath, writeBuffer);
}
// ── 读回统计 ──
const stat = await fs.stat(filePath);
const lines = encoding === 'base64' ? 0 : (await fs.readFile(filePath, 'utf-8')).split('\n').length;
return {
success: true,
path: filePath,
bytesWritten: Buffer.byteLength(params.content, (params.encoding as BufferEncoding) || 'utf-8'),
created
bytesWritten: contentLength,
totalSize: stat.size,
lines,
mode: writeMode,
created: !existed,
...(existed && writeMode === 'overwrite' && {
overwrote: true,
prevSize,
...(prevLines > 0 && { prevLines }),
}),
...(writeMode === 'append' && {
appended: true,
prevSize,
}),
};
} catch (err) {
return { success: false, error: (err as Error).message };
+5 -3
View File
@@ -33,13 +33,15 @@ export const TOOL_DEFINITIONS: ToolDefinition[] = [
type: 'function',
function: {
name: 'write_file',
description: 'Write content to a local file. Creates parent directories automatically. Overwrites existing files. Max 5MB content.',
description: 'Write content to a local file. Creates parent directories automatically. Supports text (utf-8/latin1) and binary (base64) modes. Use mode="append" to add to existing file instead of overwriting. Max 10MB (overwrite) or 5MB (append). Returns file stats including overwrite info.',
parameters: {
type: 'object',
required: ['path', 'content'],
properties: {
path: { type: 'string', description: 'The file path to write to.' },
content: { type: 'string', description: 'The content to write.' }
path: { type: 'string', description: 'The file path to write to. Absolute or relative to workspace.' },
content: { type: 'string', description: 'The content to write. For binary files, pass base64-encoded string with encoding="base64".' },
encoding: { type: 'string', enum: ['utf-8', 'latin1', 'base64'], description: 'File encoding. Use "base64" to write binary content (images, PDFs, etc). Default: utf-8.' },
mode: { type: 'string', enum: ['overwrite', 'append'], description: 'Write mode. overwrite = replace file, append = add to end. Default: overwrite.' }
}
}
}