import { getErrorMessage } from '../../shared/utils/index.js';
import { execKiro } from './process.js';
const KIRO_ABORTED_MESSAGE = 'Kiro execution aborted';
const KIRO_ERROR_DETAIL_MAX_LENGTH = 400;
const KIRO_SESSION_ID_PATTERN = /^[A-Za-z0-9._:-]+$/;
function buildPrompt(prompt, systemPrompt) {
    if (!systemPrompt) {
        return prompt;
    }
    return `${systemPrompt}\n\n${prompt}`;
}
function buildTrustArgs(options) {
    if (options.permissionMode === 'full') {
        return ['--trust-all-tools'];
    }
    if (options.permissionMode === 'edit') {
        return ['--trust-tools=read,grep,write,shell'];
    }
    if (options.permissionMode === 'readonly') {
        return ['--trust-tools=read,grep'];
    }
    return [];
}
function validateSessionId(sessionId) {
    if (!KIRO_SESSION_ID_PATTERN.test(sessionId)) {
        throw new Error('Invalid Kiro session ID. Only letters, numbers, dot, underscore, colon, and hyphen are allowed.');
    }
}
function buildInputArg(prompt) {
    // Kiro documents the prompt as positional INPUT, but does not document a `--` separator.
    return prompt.startsWith('-') ? `\n${prompt}` : prompt;
}
function buildArgs(options, prompt) {
    const args = [
        'chat',
        '--no-interactive',
        ...buildTrustArgs(options),
    ];
    if (options.sessionId) {
        validateSessionId(options.sessionId);
        args.push('--resume-id', options.sessionId);
    }
    args.push(buildInputArg(prompt));
    return args;
}
function trimDetail(value) {
    const normalized = (value ?? '').trim();
    if (!normalized) {
        return '';
    }
    return normalized.length > KIRO_ERROR_DETAIL_MAX_LENGTH
        ? `${normalized.slice(0, KIRO_ERROR_DETAIL_MAX_LENGTH)}...`
        : normalized;
}
function redactDetail(value, kiroApiKey) {
    if (!kiroApiKey) {
        return value;
    }
    return value.split(kiroApiKey).join('[REDACTED]');
}
function redactedTrimmedDetail(value, kiroApiKey) {
    return trimDetail(redactDetail(value ?? '', kiroApiKey));
}
function resolveEffectiveKiroApiKey(kiroApiKey) {
    return kiroApiKey ?? process.env.KIRO_API_KEY;
}
function selectErrorDetail(error) {
    const stderr = trimDetail(error.stderr);
    if (stderr) {
        return error.stderr ?? '';
    }
    const stdout = trimDetail(error.stdout);
    if (stdout) {
        return error.stdout ?? '';
    }
    return getErrorMessage(error);
}
function isAuthenticationError(error) {
    const message = [
        trimDetail(error.message),
        trimDetail(error.stderr),
        trimDetail(error.stdout),
    ].join('\n').toLowerCase();
    const patterns = [
        'authentication',
        'unauthorized',
        'forbidden',
        'api key',
        'kiro_api_key',
        'kiro-api-key',
        'login required',
    ];
    return patterns.some((pattern) => message.includes(pattern));
}
function classifyExecutionError(error, options) {
    if (options.abortSignal?.aborted || error.name === 'AbortError') {
        return KIRO_ABORTED_MESSAGE;
    }
    if (error.code === 'ERR_CHILD_PROCESS_STDIO_MAXBUFFER') {
        return 'Kiro CLI output exceeded buffer limit';
    }
    if (error.code === 'ENOENT') {
        return 'kiro-cli binary not found. Install Kiro CLI and ensure `kiro-cli` is in PATH, or set TAKT_KIRO_CLI_PATH/kiro_cli_path.';
    }
    if (isAuthenticationError(error)) {
        return 'Kiro authentication failed. Set TAKT_KIRO_API_KEY, kiro_api_key, or KIRO_API_KEY.';
    }
    if (typeof error.code === 'number') {
        const detail = redactedTrimmedDetail(selectErrorDetail(error), options.kiroApiKey);
        return `Kiro CLI exited with code ${error.code}: ${detail}`;
    }
    return redactDetail(getErrorMessage(error), options.kiroApiKey);
}
function emitResult(options, result, success, error) {
    options.onStream?.({
        type: 'result',
        data: {
            result,
            success,
            error,
            sessionId: options.sessionId ?? '',
        },
    });
}
export class KiroClient {
    async call(agentType, prompt, options) {
        const promptText = buildPrompt(prompt, options.systemPrompt);
        const effectiveKiroApiKey = resolveEffectiveKiroApiKey(options.kiroApiKey);
        const effectiveOptions = effectiveKiroApiKey === options.kiroApiKey
            ? options
            : { ...options, kiroApiKey: effectiveKiroApiKey };
        try {
            const args = buildArgs(effectiveOptions, promptText);
            const { stdout } = await execKiro(args, effectiveOptions);
            const content = stdout.trim();
            if (!content) {
                const message = 'kiro-cli returned empty output';
                emitResult(options, '', false, message);
                return {
                    persona: agentType,
                    status: 'error',
                    content: message,
                    error: message,
                    timestamp: new Date(),
                    sessionId: options.sessionId,
                };
            }
            options.onStream?.({ type: 'text', data: { text: content } });
            emitResult(options, content, true);
            return {
                persona: agentType,
                status: 'done',
                content,
                timestamp: new Date(),
                sessionId: options.sessionId,
            };
        }
        catch (rawError) {
            const error = rawError;
            const message = classifyExecutionError(error, effectiveOptions);
            emitResult(options, '', false, message);
            return {
                persona: agentType,
                status: 'error',
                content: message,
                error: message,
                timestamp: new Date(),
                sessionId: options.sessionId,
            };
        }
    }
}
const defaultClient = new KiroClient();
export async function callKiro(agentType, prompt, options) {
    return defaultClient.call(agentType, prompt, options);
}
//# sourceMappingURL=client.js.map