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
JavaScript
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