import { copyFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, writeFileSync } from 'node:fs';
import { createRequire } from 'node:module';
import { basename, extname, isAbsolute, resolve } from 'node:path';
import { join } from 'node:path';
import { createSdkMcpServer, tool } from '@anthropic-ai/claude-agent-sdk';
import { isAnthropicBridgeProvider } from './types.js';
const require = createRequire(import.meta.url);
const CLAUDE_BUILT_IN_DIRS = ['agents', 'commands'];
export function buildEnv(config, configDir, override) {
    const usesAnthropicBridge = isAnthropicBridgeProvider(config.provider);
    return {
        ...process.env,
        CLAUDE_CONFIG_DIR: configDir || process.env.CLAUDE_CONFIG_DIR,
        ANTHROPIC_API_KEY: override?.apiKey || config.apiKey || process.env.ANTHROPIC_API_KEY,
        ANTHROPIC_AUTH_TOKEN: override?.apiKey || config.apiKey || process.env.ANTHROPIC_AUTH_TOKEN,
        ANTHROPIC_BASE_URL: override?.baseURL || config.baseURL || process.env.ANTHROPIC_BASE_URL,
        ANTHROPIC_DEFAULT_OPUS_MODEL: usesAnthropicBridge ? undefined : config.model || process.env.ANTHROPIC_DEFAULT_OPUS_MODEL,
        ANTHROPIC_DEFAULT_SONNET_MODEL: usesAnthropicBridge ? undefined : config.model || process.env.ANTHROPIC_DEFAULT_SONNET_MODEL,
        ANTHROPIC_DEFAULT_HAIKU_MODEL: usesAnthropicBridge ? undefined : config.model || process.env.ANTHROPIC_DEFAULT_HAIKU_MODEL,
        CLAUDE_AGENT_SDK_CLIENT_APP: process.env.CLAUDE_AGENT_SDK_CLIENT_APP || 'agent-spaces/server',
        IS_SANDBOX: '1',
    };
}
export function normalizeMcpServers(servers, functionTools) {
    if ((!servers || Object.keys(servers).length === 0) && !functionTools?.length)
        return undefined;
    const normalized = { ...(servers ?? {}) };
    if (functionTools?.length) {
        normalized['agent-spaces'] = createSdkMcpServer({
            name: 'agent-spaces',
            version: '0.1.0',
            alwaysLoad: true,
            tools: functionTools.map(createSdkTool),
        });
    }
    return normalized;
}
function createSdkTool(functionTool) {
    return tool(functionTool.name, functionTool.description, jsonSchemaToZodRawShape(functionTool.inputSchema), async (args) => ({
        content: [
            {
                type: 'text',
                text: JSON.stringify(await functionTool.execute(args), null, 2),
            },
        ],
    }), { annotations: toSdkToolAnnotations(functionTool), alwaysLoad: true });
}
function toSdkToolAnnotations(functionTool) {
    if (!functionTool.annotations)
        return undefined;
    return {
        readOnlyHint: functionTool.annotations.readOnly,
        destructiveHint: functionTool.annotations.destructive,
        openWorldHint: functionTool.annotations.openWorld,
    };
}
function jsonSchemaToZodRawShape(schema) {
    const properties = schema.properties && typeof schema.properties === 'object'
        ? schema.properties
        : {};
    const required = new Set(Array.isArray(schema.required) ? schema.required.map(String) : []);
    const shape = {};
    for (const [name, property] of Object.entries(properties)) {
        const field = jsonSchemaPropertyToZod(property);
        shape[name] = required.has(name) ? field : field.optional();
    }
    return shape;
}
function jsonSchemaPropertyToZod(property) {
    const zod = require('zod');
    switch (property.type) {
        case 'number':
            return zod.number();
        case 'integer':
            return zod.number().int();
        case 'boolean':
            return zod.boolean();
        case 'array':
            return zod.array(zod.unknown());
        case 'object':
            return zod.record(zod.string(), zod.unknown());
        case 'string':
        default:
            return zod.string();
    }
}
export function resolveBundledClaudeExecutable() {
    const packageName = getBundledClaudePackageName();
    if (!packageName)
        return undefined;
    try {
        return require.resolve(`${packageName}/claude`);
    }
    catch {
        return undefined;
    }
}
function getBundledClaudePackageName() {
    const platform = process.platform;
    const arch = process.arch;
    if (platform === 'darwin') {
        if (arch === 'arm64')
            return '@anthropic-ai/claude-agent-sdk-darwin-arm64';
        if (arch === 'x64')
            return '@anthropic-ai/claude-agent-sdk-darwin-x64';
    }
    if (platform === 'linux') {
        if (arch === 'arm64')
            return isMuslRuntime() ? '@anthropic-ai/claude-agent-sdk-linux-arm64-musl' : '@anthropic-ai/claude-agent-sdk-linux-arm64';
        if (arch === 'x64')
            return isMuslRuntime() ? '@anthropic-ai/claude-agent-sdk-linux-x64-musl' : '@anthropic-ai/claude-agent-sdk-linux-x64';
    }
    if (platform === 'win32') {
        if (arch === 'arm64')
            return '@anthropic-ai/claude-agent-sdk-win32-arm64';
        if (arch === 'x64')
            return '@anthropic-ai/claude-agent-sdk-win32-x64';
    }
    return undefined;
}
function isMuslRuntime() {
    const report = process.report?.getReport();
    return !report?.header?.glibcVersionRuntime;
}
export function normalizeSkillNames(skills, configDir) {
    if (!Array.isArray(skills))
        return [];
    return skills
        .map(sanitizeSkillName)
        .filter((skill) => Boolean(skill) && hasSkillContent(skill, configDir));
}
export function prepareConfigDir(configDir, agentDir) {
    mkdirSync(configDir, { recursive: true });
    if (!agentDir)
        return;
    copyClaudeBuiltInDirs(agentDir, configDir);
    const sourceSkillsDir = join(agentDir, 'skills');
    const targetSkillsDir = join(configDir, 'skills');
    rmSync(targetSkillsDir, { recursive: true, force: true });
    mkdirSync(targetSkillsDir, { recursive: true });
    if (!existsSync(sourceSkillsDir))
        return;
    for (const entry of readdirSync(sourceSkillsDir)) {
        const source = join(sourceSkillsDir, entry);
        const sourceStat = statSync(source);
        if (sourceStat.isDirectory()) {
            const skillName = sanitizeSkillName(entry);
            if (!skillName)
                continue;
            const sourceSkillFile = join(source, 'SKILL.md');
            const targetSkillDir = join(targetSkillsDir, skillName);
            if (existsSync(sourceSkillFile) && statSync(sourceSkillFile).size > 0) {
                cpSync(source, targetSkillDir, { recursive: true, force: true });
            }
            continue;
        }
        if (!sourceStat.isFile() || extname(entry).toLowerCase() !== '.md')
            continue;
        const skillName = sanitizeSkillName(entry);
        if (!skillName || sourceStat.size === 0)
            continue;
        const targetSkillDir = join(targetSkillsDir, skillName);
        mkdirSync(targetSkillDir, { recursive: true });
        writeFileSync(join(targetSkillDir, 'SKILL.md'), readFileSync(source, 'utf-8'), 'utf-8');
        copyFileSync(source, join(targetSkillsDir, `${skillName}.md`));
    }
}
function copyClaudeBuiltInDirs(agentDir, configDir) {
    for (const dir of CLAUDE_BUILT_IN_DIRS) {
        const sourceDir = join(agentDir, dir);
        const targetDir = join(configDir, dir);
        rmSync(targetDir, { recursive: true, force: true });
        if (!existsSync(sourceDir) || !statSync(sourceDir).isDirectory())
            continue;
        cpSync(sourceDir, targetDir, { recursive: true, force: true });
    }
}
function hasSkillContent(skill, configDir) {
    if (!configDir)
        return true;
    const skillFile = join(configDir, 'skills', skill, 'SKILL.md');
    if (existsSync(skillFile) && statSync(skillFile).size > 0)
        return true;
    const legacySkillFile = join(configDir, 'skills', `${skill}.md`);
    return existsSync(legacySkillFile) && statSync(legacySkillFile).size > 0;
}
function sanitizeSkillName(name) {
    const raw = basename(name).replace(/\.md$/i, '').trim();
    return raw.replace(/[^a-zA-Z0-9._-]+/g, '-').replace(/^-+|-+$/g, '');
}
export function normalizePermissionMode(permissionMode) {
    if (permissionMode === 'default' ||
        permissionMode === 'acceptEdits' ||
        permissionMode === 'bypassPermissions' ||
        permissionMode === 'plan' ||
        permissionMode === 'dontAsk') {
        return permissionMode;
    }
    return 'bypassPermissions';
}
export function normalizeAdditionalDirectories(cwd, sandboxDirs) {
    const seen = new Set();
    const dirs = [cwd, ...(sandboxDirs ?? [])]
        .map((dir) => dir.trim())
        .filter(Boolean)
        .map((dir) => isAbsolute(dir) ? resolve(dir) : resolve(cwd, dir));
    return dirs.filter((dir) => {
        if (seen.has(dir))
            return false;
        seen.add(dir);
        return true;
    });
}
//# sourceMappingURL=sdk-config.js.map