diff --git a/src/filesystem/__tests__/structured-content.test.ts b/src/filesystem/__tests__/structured-content.test.ts index 4b8f92b0a3..5f9d01c943 100644 --- a/src/filesystem/__tests__/structured-content.test.ts +++ b/src/filesystem/__tests__/structured-content.test.ts @@ -62,6 +62,7 @@ describe('structuredContent schema compliance', () => { // structuredContent.content should be a string (matching outputSchema: { content: z.string() }) const structuredContent = result.structuredContent as { content: unknown }; + expect(Object.keys(structuredContent)).toEqual(['content']); expect(typeof structuredContent.content).toBe('string'); // It should NOT be an array @@ -85,6 +86,7 @@ describe('structuredContent schema compliance', () => { // structuredContent.content should be a string (matching outputSchema: { content: z.string() }) const structuredContent = result.structuredContent as { content: unknown }; + expect(Object.keys(structuredContent)).toEqual(['content']); expect(typeof structuredContent.content).toBe('string'); // It should NOT be an array @@ -113,6 +115,7 @@ describe('structuredContent schema compliance', () => { // structuredContent.content should be a string (matching outputSchema: { content: z.string() }) const structuredContent = result.structuredContent as { content: unknown }; + expect(Object.keys(structuredContent)).toEqual(['content']); expect(typeof structuredContent.content).toBe('string'); // It should NOT be an array @@ -133,6 +136,7 @@ describe('structuredContent schema compliance', () => { expect(result.structuredContent).toBeDefined(); const structuredContent = result.structuredContent as { content: unknown }; + expect(Object.keys(structuredContent)).toEqual(['content']); expect(typeof structuredContent.content).toBe('string'); expect(Array.isArray(structuredContent.content)).toBe(false); }); @@ -151,6 +155,7 @@ describe('structuredContent schema compliance', () => { expect(result.structuredContent).toBeDefined(); const structuredContent = result.structuredContent as { content: unknown }; + expect(Object.keys(structuredContent)).toEqual(['content']); expect(typeof structuredContent.content).toBe('string'); expect(Array.isArray(structuredContent.content)).toBe(false); }); diff --git a/src/filesystem/index.ts b/src/filesystem/index.ts index 7b67e63e58..7faf5e0661 100644 --- a/src/filesystem/index.ts +++ b/src/filesystem/index.ts @@ -185,6 +185,13 @@ async function readFileAsBase64Stream(filePath: string): Promise { }); } +function asTextToolResult(text: string): CallToolResult { + return { + content: [{ type: "text", text }], + structuredContent: { content: text }, + }; +} + // Tool registrations // read_file (deprecated) and read_text_file @@ -204,10 +211,7 @@ const readTextFileHandler = async (args: z.infer) content = await readFileContent(validPath); } - return { - content: [{ type: "text" as const, text: content }], - structuredContent: { content } - }; + return asTextToolResult(content); }; server.registerTool( @@ -329,10 +333,7 @@ server.registerTool( }), ); const text = results.join("\n---\n"); - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -355,10 +356,7 @@ server.registerTool( const validPath = await validatePath(args.path); await writeFileContent(validPath, args.content); const text = `Successfully wrote to ${args.path}`; - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -384,10 +382,7 @@ server.registerTool( async (args: z.infer) => { const validPath = await validatePath(args.path); const result = await applyFileEdits(validPath, args.edits, args.dryRun); - return { - content: [{ type: "text" as const, text: result }], - structuredContent: { content: result } - }; + return asTextToolResult(result); } ); @@ -410,10 +405,7 @@ server.registerTool( const validPath = await validatePath(args.path); await fs.mkdir(validPath, { recursive: true }); const text = `Successfully created directory ${args.path}`; - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -438,10 +430,7 @@ server.registerTool( const formatted = entries .map((entry) => `${entry.isDirectory() ? "[DIR]" : "[FILE]"} ${entry.name}`) .join("\n"); - return { - content: [{ type: "text" as const, text: formatted }], - structuredContent: { content: formatted } - }; + return asTextToolResult(formatted); } ); @@ -516,11 +505,7 @@ server.registerTool( ]; const text = [...formattedEntries, ...summary].join("\n"); - const contentBlock = { type: "text" as const, text }; - return { - content: [contentBlock], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -586,11 +571,7 @@ server.registerTool( const treeData = await buildTree(rootPath, args.excludePatterns); const text = JSON.stringify(treeData, null, 2); - const contentBlock = { type: "text" as const, text }; - return { - content: [contentBlock], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -615,11 +596,7 @@ server.registerTool( const validDestPath = await validatePath(args.destination); await fs.rename(validSourcePath, validDestPath); const text = `Successfully moved ${args.source} to ${args.destination}`; - const contentBlock = { type: "text" as const, text }; - return { - content: [contentBlock], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -645,10 +622,7 @@ server.registerTool( const validPath = await validatePath(args.path); const results = await searchFilesWithValidation(validPath, args.pattern, allowedDirectories, { excludePatterns: args.excludePatterns }); const text = results.length > 0 ? results.join("\n") : "No matches found"; - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -673,10 +647,7 @@ server.registerTool( const text = Object.entries(info) .map(([key, value]) => `${key}: ${value}`) .join("\n"); - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } ); @@ -695,10 +666,7 @@ server.registerTool( }, async () => { const text = `Allowed directories:\n${allowedDirectories.join('\n')}`; - return { - content: [{ type: "text" as const, text }], - structuredContent: { content: text } - }; + return asTextToolResult(text); } );