UNPKG

hataraku

Version:

An autonomous coding agent for building AI-powered development tools. The name "Hataraku" (働く) means "to work" in Japanese.

117 lines 5.36 kB
import { McpError, ErrorCode } from '../types'; import { zodToJsonSchema as zodToJsonSchemaLib } from 'zod-to-json-schema'; import { z } from 'zod'; export class TaskToolAdapter { convertToMcpTool(task) { const info = task.getInfo(); return { name: info.name, description: info.description, parameters: this.generateParameters(task), execute: async (args, options) => { try { const schema = task.inputSchema; const taskDef = task.task; const execOptions = { stream: false, thread: options?.thread }; let input; if (schema) { // If we have a schema, use args (either content or full args) input = schema instanceof z.ZodObject ? args : args.content; if (input === undefined) { // For string schemas with no input, use an empty string input = (schema instanceof z.ZodString ? '' : undefined); } } else { // No schema provided: determine input based on task definition if (typeof taskDef === 'string') { input = taskDef; } else if (typeof taskDef === 'function') { input = args; } else { input = args; } // Attach a default schema to avoid errors during Task.execute task.inputSchema = z.string(); } if (input === undefined) { throw new Error('Task failed'); } const result = await task.run(input, execOptions); const isObject = result !== null && typeof result === 'object'; const text = isObject ? JSON.stringify(result) : String(result); return { data: result, raw: { content: [ { type: 'text', text } ], isError: false } }; } catch (error) { if (error instanceof McpError) { throw error; } const errorMessage = error instanceof Error ? error.message : 'Task execution failed'; if (errorMessage === "Cannot read properties of undefined (reading '_def')") { throw new McpError(ErrorCode.ExecutionError, 'Task failed'); } throw new McpError(ErrorCode.ExecutionError, errorMessage); } } }; } generateParameters(task) { const schema = task.inputSchema; // If no schema, return default content parameter if (!schema || !(schema instanceof z.ZodType)) { return { content: { type: 'string', description: 'Input content' } }; } // Handle non-object schemas as content parameter if (!(schema instanceof z.ZodObject)) { const taskSchema = zodToJsonSchemaLib(schema, { target: 'jsonSchema7' }); const { $schema, ...schemaWithoutSchema } = taskSchema; return { content: { ...schemaWithoutSchema, description: 'Input content' } }; } // For object schemas, convert to JSON schema and return properties directly const taskSchema = zodToJsonSchemaLib(schema, { target: 'jsonSchema7' }); const { $schema, properties = {} } = taskSchema; // Convert properties to MCP format const convertedProperties = {}; for (const [key, value] of Object.entries(properties)) { if (typeof value === 'object' && value !== null) { const { $schema: propSchema, additionalProperties, required, ...rest } = value; if (rest.type === 'object' && rest.properties) { // Handle nested objects by preserving their structure and descriptions convertedProperties[key] = { type: 'object', ...(rest.description && { description: rest.description }), properties: Object.fromEntries(Object.entries(rest.properties).map(([nestedKey, nestedValue]) => { const { $schema: nestedSchema, additionalProperties: nestedAdditional, required: nestedRequired, ...nestedRest } = nestedValue; return [nestedKey, nestedRest]; })) }; } else { convertedProperties[key] = rest; } } } return convertedProperties; } } //# sourceMappingURL=task-tool-adapter.js.map