import { AgentOutputType, ChatMessageBuilder, trimText } from '../agent-core/index.js';
import { AgentFunctionBase } from './utils/index.js';
export class WriteScriptFunction extends AgentFunctionBase {
    static allowedLibs = ['fs', 'axios', 'util', 'path'];
    name = 'writeScript';
    description = 'Writes the function.';
    parameters = {
        type: 'object',
        properties: {
            namespace: {
                type: 'string',
                description: 'The namespace of the function, e.g. fs.readFile',
            },
            description: {
                type: 'string',
                description: 'The detailed description of the function.',
            },
            arguments: {
                type: 'string',
                description: "The arguments of the function. E.g. '{ path: string, encoding: string }'",
            },
            code: {
                type: 'string',
                description: 'The code of the function.',
            },
        },
        required: ['namespace', 'description', 'arguments', 'code'],
        additionalProperties: false,
    };
    buildExecutor({ context }) {
        return async (params, rawParams) => {
            if (params.namespace.startsWith('agent.')) {
                return this.onErrorCannotCreateInAgentNamespace(this.name, params, rawParams, context.variables);
            }
            if (this.extractRequires(params.code).some(x => !WriteScriptFunction.allowedLibs.includes(x))) {
                return this.onErrorCannotRequireLib(this.name, params, rawParams, context.variables);
            }
            await context.workspace.writeFile('index.js', params.code);
            return this.onSuccess(params, rawParams, context.variables);
        };
    }
    onSuccess(params, rawParams, variables) {
        return {
            outputs: [
                {
                    type: AgentOutputType.Success,
                    title: `Wrote function '${params.namespace}'.`,
                    content: `Wrote the function ${params.namespace} to the workspace.`,
                },
            ],
            messages: [ChatMessageBuilder.functionCall(this.name, rawParams), ChatMessageBuilder.functionCallResult(this.name, 'Success.')],
        };
    }
    onError(name, error, args) {
        return `The function '${name}' failed, this is the error:\n\`\`\`\n${error && typeof error === 'string' ? trimText(error, 300) : 'Unknown error.'}\n\`\`\`\n\nArguments:\n\`\`\`\n${JSON.stringify(args, null, 2)}\n\`\`\``;
    }
    extractRequires = (code) => {
        const regex = /\brequire\b\s*\(\s*["']([^"']+)["']\s*\)/g;
        let match;
        const libraries = [];
        while ((match = regex.exec(code)) !== null) {
            libraries.push(match[1]);
        }
        return libraries;
    };
    onErrorCannotCreateInAgentNamespace(functionName, params, rawParams, variables) {
        return {
            outputs: [
                {
                    type: AgentOutputType.Error,
                    title: `Failed to write function '${params.namespace}'!`,
                    content: this.onError(functionName, `Cannot create a function with namespace ${params.namespace}. Namespaces starting with 'agent.' are reserved.`, params),
                },
            ],
            messages: [
                ChatMessageBuilder.functionCall(functionName, rawParams),
                ChatMessageBuilder.functionCallResult(functionName, `Failed writing the function.
Namespaces starting with 'agent.' are reserved.`),
            ],
        };
    }
    onErrorCannotRequireLib(functionName, params, rawParams, variables) {
        return {
            outputs: [
                {
                    type: AgentOutputType.Error,
                    title: `Failed to write function '${params.namespace}'!`,
                    content: this.onError(functionName, `Cannot require libraries other than ${WriteScriptFunction.allowedLibs.join(', ')}.`, params),
                },
            ],
            messages: [
                ChatMessageBuilder.functionCall(functionName, rawParams),
                ChatMessageBuilder.functionCallResult(functionName, `Cannot require libraries other than ${WriteScriptFunction.allowedLibs.join(', ')}.`),
            ],
        };
    }
    static formatSupportedLibraries() {
        const [last] = this.allowedLibs.slice(-1);
        const others = this.allowedLibs.slice(0, -1);
        return others.length ? `"${others.join('", "')}", and "${last}"` : `"${last}"`;
    }
}
