import { readFile } from 'node:fs/promises';
import path from 'node:path';
const CONNECTORS_USAGE = `Usage:
  od tools connectors list [--use-case personal_daily_digest] [--format compact]
  od tools connectors execute --connector <id> --tool <name> --input input.json

Environment:
  OD_NODE_BIN     Node-compatible runtime for agent wrapper invocations
  OD_BIN          Open Design CLI script for agent wrapper invocations
  OD_DAEMON_URL   Daemon base URL injected into agent runs
  OD_TOOL_TOKEN   Bearer token injected into agent runs

Agent runtime invocation:
  "$OD_NODE_BIN" "$OD_BIN" tools connectors list --use-case personal_daily_digest --format compact
`;
function writeJson(value, stream = process.stdout) {
    stream.write(`${JSON.stringify(value)}\n`);
}
function fail(message, details) {
    writeJson({ ok: false, error: { message, ...(details === undefined ? {} : { details }) } }, process.stderr);
    return { exitCode: 1 };
}
function parseOptions(args) {
    const [command, ...rest] = args;
    const options = {
        command: command === '-h' || command === '--help' ? undefined : command,
        format: 'compact',
        help: command === '-h' || command === '--help',
    };
    for (let index = 0; index < rest.length; index += 1) {
        const arg = rest[index];
        if (arg === '--connector') {
            const value = rest[++index];
            if (!value)
                return { error: '--connector requires a connector id' };
            options.connectorId = value;
        }
        else if (arg === '--tool') {
            const value = rest[++index];
            if (!value)
                return { error: '--tool requires a tool name' };
            options.toolName = value;
        }
        else if (arg === '--input') {
            const value = rest[++index];
            if (!value)
                return { error: '--input requires a file path' };
            options.inputPath = value;
        }
        else if (arg === '--format') {
            const value = rest[++index];
            if (value !== 'compact' && value !== 'json')
                return { error: '--format must be compact or json' };
            options.format = value;
        }
        else if (arg === '--use-case') {
            const value = rest[++index];
            if (value !== 'personal_daily_digest')
                return { error: '--use-case must be personal_daily_digest' };
            options.useCase = value;
        }
        else if (arg === '-h' || arg === '--help') {
            options.help = true;
        }
        else {
            return { error: `unknown option: ${arg}` };
        }
    }
    return options;
}
function daemonUrl() {
    const rawUrl = process.env.OD_DAEMON_URL;
    if (!rawUrl)
        return { error: 'OD_DAEMON_URL is required' };
    try {
        const url = new URL(rawUrl);
        url.pathname = url.pathname.replace(/\/+$/u, '');
        url.search = '';
        url.hash = '';
        return url;
    }
    catch {
        return { error: 'OD_DAEMON_URL must be a valid URL' };
    }
}
function toolToken() {
    const token = process.env.OD_TOOL_TOKEN;
    if (!token)
        return { error: 'OD_TOOL_TOKEN is required' };
    return token;
}
function endpoint(baseUrl, pathname) {
    const url = new URL(baseUrl.toString());
    const [pathPart, searchPart] = pathname.split('?');
    url.pathname = `${url.pathname}${pathPart ?? ''}`.replace(/\/+/gu, '/');
    url.search = searchPart === undefined ? '' : `?${searchPart}`;
    return url.toString();
}
async function readJsonFile(filePath) {
    const resolved = path.resolve(filePath);
    const text = await readFile(resolved, 'utf8');
    try {
        return JSON.parse(text);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        throw new Error(`invalid JSON in ${resolved}: ${message}`);
    }
}
async function readJsonObject(filePath) {
    const value = await readJsonFile(filePath);
    if (!value || typeof value !== 'object' || Array.isArray(value)) {
        throw new Error(`${path.resolve(filePath)} must contain a JSON object`);
    }
    return value;
}
async function requestJson(baseUrl, token, pathname, init = {}) {
    const response = await fetch(endpoint(baseUrl, pathname), {
        ...init,
        headers: {
            Authorization: `Bearer ${token}`,
            Accept: 'application/json',
            ...(init.body === undefined ? {} : { 'Content-Type': 'application/json' }),
            ...init.headers,
        },
    });
    const text = await response.text();
    let body = text;
    if (text.length > 0) {
        try {
            body = JSON.parse(text);
        }
        catch {
            body = { message: text };
        }
    }
    return { status: response.status, body };
}
function compactTool(value) {
    if (!value || typeof value !== 'object')
        return value;
    const tool = value;
    return {
        name: tool.name,
        description: tool.description,
        safety: tool.safety,
        curation: tool.curation,
        inputSchema: tool.inputSchemaJson ?? tool.inputSchema,
    };
}
function compactConnector(value) {
    if (!value || typeof value !== 'object')
        return value;
    const connector = value;
    const tools = Array.isArray(connector.tools) ? connector.tools : [];
    return {
        id: connector.id,
        name: connector.name,
        provider: connector.provider,
        category: connector.category,
        status: connector.status,
        accountLabel: connector.accountLabel,
        tools: tools.map(compactTool),
    };
}
function compactList(value) {
    if (!value || typeof value !== 'object')
        return value;
    const response = value;
    const connectors = Array.isArray(response.connectors) ? response.connectors : [];
    return { connectors: connectors.map(compactConnector) };
}
function compactExecution(value) {
    if (!value || typeof value !== 'object')
        return value;
    const response = value;
    return {
        connectorId: response.connectorId,
        accountLabel: response.accountLabel,
        toolName: response.toolName,
        safety: response.safety,
        outputSummary: response.outputSummary,
        output: response.output,
        metadata: response.metadata,
    };
}
function compactValidationDetails(details) {
    if (!details || typeof details !== 'object')
        return details;
    const record = details;
    if (record.kind !== 'validation' || !Array.isArray(record.issues))
        return details;
    return {
        kind: 'validation',
        issues: record.issues.map((issue) => {
            if (!issue || typeof issue !== 'object')
                return { message: String(issue) };
            const issueRecord = issue;
            return {
                ...(typeof issueRecord.path === 'string' ? { path: issueRecord.path } : {}),
                message: typeof issueRecord.message === 'string' ? issueRecord.message : String(issueRecord.message ?? 'validation failed'),
                ...(typeof issueRecord.code === 'string' ? { code: issueRecord.code } : {}),
            };
        }),
    };
}
function normalizeCliError(body) {
    const rawError = body && typeof body === 'object' && 'error' in body ? body.error : body;
    if (typeof rawError === 'string')
        return { message: rawError };
    if (!rawError || typeof rawError !== 'object')
        return { message: String(rawError ?? 'request failed') };
    const error = rawError;
    return {
        ...(typeof error.code === 'string' ? { code: error.code } : {}),
        message: typeof error.message === 'string' ? error.message : String(error.error ?? 'request failed'),
        ...(error.details === undefined ? {} : { details: compactValidationDetails(error.details) }),
        ...(typeof error.retryable === 'boolean' ? { retryable: error.retryable } : {}),
        ...(typeof error.requestId === 'string' ? { requestId: error.requestId } : {}),
    };
}
async function printApiResult(response, compact) {
    if (response.status < 200 || response.status >= 300) {
        writeJson({ ok: false, status: response.status, error: normalizeCliError(response.body) }, process.stderr);
        return { exitCode: 1 };
    }
    const body = compact(response.body);
    writeJson(body && typeof body === 'object' && !Array.isArray(body) ? { ok: true, ...body } : { ok: true, result: body });
    return { exitCode: 0 };
}
export async function runConnectorsToolCli(args) {
    const options = parseOptions(args);
    if ('error' in options)
        return fail(options.error);
    if (options.help || !options.command) {
        process.stdout.write(CONNECTORS_USAGE);
        return { exitCode: options.command ? 0 : 1 };
    }
    const baseUrl = daemonUrl();
    if ('error' in baseUrl)
        return fail(baseUrl.error);
    const token = toolToken();
    if (typeof token !== 'string')
        return fail(token.error);
    try {
        if (options.command === 'list') {
            const listPath = options.useCase ? `/api/tools/connectors/list?useCase=${encodeURIComponent(options.useCase)}` : '/api/tools/connectors/list';
            return await printApiResult(await requestJson(baseUrl, token, listPath, { method: 'GET' }), options.format === 'compact' ? compactList : (body) => body);
        }
        if (options.command === 'execute') {
            if (!options.connectorId)
                return fail('execute requires --connector <id>');
            if (!options.toolName)
                return fail('execute requires --tool <name>');
            if (!options.inputPath)
                return fail('execute requires --input input.json');
            const input = await readJsonObject(options.inputPath);
            return await printApiResult(await requestJson(baseUrl, token, '/api/tools/connectors/execute', {
                method: 'POST',
                body: JSON.stringify({ connectorId: options.connectorId, toolName: options.toolName, input }),
            }), options.format === 'compact' ? compactExecution : (body) => body);
        }
        return fail(`unknown connectors command: ${options.command}`);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return fail(message);
    }
}
//# sourceMappingURL=tools-connectors-cli.js.map