"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.claudeOrchestrator = void 0;
exports.registerClaudeMcpServer = registerClaudeMcpServer;
const node_fs_1 = __importDefault(require("node:fs"));
const node_os_1 = __importDefault(require("node:os"));
const node_path_1 = __importDefault(require("node:path"));
const shared_js_1 = require("./shared.js");
const CLAUDE_SETTINGS_PATH = node_path_1.default.join(node_os_1.default.homedir(), '.claude', 'settings.local.json');
const CLAUDE_SLASH_COMMAND_PATH = node_path_1.default.join(node_os_1.default.homedir(), '.claude', 'commands', 'chorus.md');
const CLAUDE_PROJECT_CONFIG_PATH = node_path_1.default.join(node_os_1.default.homedir(), '.claude.json');
function readClaudeSettings() {
    if (!node_fs_1.default.existsSync(CLAUDE_SETTINGS_PATH))
        return {};
    try {
        return JSON.parse(node_fs_1.default.readFileSync(CLAUDE_SETTINGS_PATH, 'utf-8'));
    }
    catch {
        return {};
    }
}
function getClaudeStatus() {
    const config = readClaudeSettings();
    const allow = new Set(config.permissions?.allow ?? []);
    const approved = shared_js_1.CHORUS_TOOLS.filter((t) => allow.has(t)).length;
    return {
        name: 'claude',
        label: 'Claude Code',
        connected: approved === shared_js_1.CHORUS_TOOLS.length,
        approvedTools: approved,
        totalTools: shared_js_1.CHORUS_TOOLS.length,
        note: "Pre-approves the 7 chorus.* tools so Claude Code doesn't prompt per-tool.",
        supported: true,
        firstCallBehavior: 'auto',
    };
}
/**
 * Resolve the bundled `/chorus` slash command markdown shipped in the npm
 * package at `assets/slash-commands/chorus.md`. Works in both dist
 * (`__dirname` = `dist/daemon/orchestrators`) and dev/tsx
 * (`__dirname` = `src/daemon/orchestrators`) — both resolve to
 * `<pkg>/assets/...`.
 */
function resolveChorusSlashAsset() {
    const candidate = node_path_1.default.join(__dirname, '..', '..', '..', 'assets', 'slash-commands', 'chorus.md');
    return node_fs_1.default.existsSync(candidate) ? candidate : null;
}
function installChorusSlashCommand() {
    const source = resolveChorusSlashAsset();
    if (!source)
        return 'skipped';
    const desired = node_fs_1.default.readFileSync(source, 'utf-8');
    if (node_fs_1.default.existsSync(CLAUDE_SLASH_COMMAND_PATH)) {
        const current = node_fs_1.default.readFileSync(CLAUDE_SLASH_COMMAND_PATH, 'utf-8');
        if (current === desired)
            return 'unchanged';
        node_fs_1.default.writeFileSync(CLAUDE_SLASH_COMMAND_PATH, desired, 'utf-8');
        return 'updated';
    }
    node_fs_1.default.mkdirSync(node_path_1.default.dirname(CLAUDE_SLASH_COMMAND_PATH), { recursive: true });
    node_fs_1.default.writeFileSync(CLAUDE_SLASH_COMMAND_PATH, desired, 'utf-8');
    return 'installed';
}
/**
 * Patch Claude Code's local settings to whitelist all 7 Chorus MCP tools, and
 * drop the `/chorus` slash command into `~/.claude/commands/`. Idempotent.
 */
async function connectClaude() {
    const config = readClaudeSettings();
    const permissions = (config.permissions ?? {});
    const existing = new Set(permissions.allow ?? []);
    const added = [];
    const alreadyPresent = [];
    for (const tool of shared_js_1.CHORUS_TOOLS) {
        if (existing.has(tool)) {
            alreadyPresent.push(tool);
        }
        else {
            existing.add(tool);
            added.push(tool);
        }
    }
    if (added.length > 0) {
        node_fs_1.default.mkdirSync(node_path_1.default.dirname(CLAUDE_SETTINGS_PATH), { recursive: true });
        const next = {
            ...config,
            permissions: {
                ...permissions,
                allow: Array.from(existing).sort(),
            },
        };
        node_fs_1.default.writeFileSync(CLAUDE_SETTINGS_PATH, JSON.stringify(next, null, 2) + '\n', 'utf-8');
    }
    const slashCommand = installChorusSlashCommand();
    return {
        added,
        alreadyPresent,
        configPath: CLAUDE_SETTINGS_PATH,
        slashCommand,
        slashCommandPath: CLAUDE_SLASH_COMMAND_PATH,
    };
}
function readUserScopeChorusEntry() {
    const configPath = node_path_1.default.join(node_os_1.default.homedir(), '.claude.json');
    if (!node_fs_1.default.existsSync(configPath))
        return null;
    try {
        const config = JSON.parse(node_fs_1.default.readFileSync(configPath, 'utf-8'));
        const chorus = config.mcpServers?.chorus;
        if (!chorus || !Array.isArray(chorus.args))
            return null;
        const binPath = chorus.args[0];
        return typeof binPath === 'string' ? { binPath } : null;
    }
    catch {
        return null;
    }
}
async function registerClaudeMcpServer(opts) {
    const existing = readUserScopeChorusEntry();
    if (existing && existing.binPath === opts.binPath) {
        return { added: false };
    }
    const execOpts = {
        timeout: 30_000,
        shell: process.platform === 'win32',
    };
    if (existing) {
        try {
            await (0, shared_js_1.execFileAsync)('claude', ['mcp', 'remove', 'chorus', '--scope', 'user'], execOpts);
        }
        catch {
            /* best-effort */
        }
    }
    const daemonUrl = opts.daemonUrl ?? shared_js_1.DEFAULT_DAEMON_URL;
    try {
        await (0, shared_js_1.execFileAsync)('claude', [
            'mcp',
            'add',
            'chorus',
            '--scope',
            'user',
            '--env',
            `CHORUS_DAEMON_URL=${daemonUrl}`,
            '--',
            'node',
            opts.binPath,
            'mcp',
        ], execOpts);
    }
    catch (err) {
        const msg = err instanceof Error ? err.message : String(err);
        throw new Error(`claude mcp add failed: ${msg}\n` +
            `(if your Claude Code is older than ~v1.0, it may not support ` +
            `'mcp add --scope user' — upgrade Claude Code and retry)`);
    }
    return { added: true };
}
exports.claudeOrchestrator = {
    name: 'claude',
    label: 'Claude Code',
    getStatus: getClaudeStatus,
    detect: () => node_fs_1.default.existsSync(CLAUDE_PROJECT_CONFIG_PATH),
    connect: async (opts) => {
        const reg = await registerClaudeMcpServer(opts);
        const conn = await connectClaude();
        return {
            registered: reg.added,
            toolsAdded: conn.added.length,
            slashCommand: conn.slashCommand,
            full: conn,
        };
    },
};
//# sourceMappingURL=claude.js.map