/**
 * Provider Adapter 抽象层类型定义
 * SDK 架构核心 —— 统一事件流接口
 *
 * 参考自 SpectrAI 项目的 adapter 设计，用于支持多种 AI Provider
 */
import { EventEmitter } from "node:events";
const TEMP_CLIPBOARD_PASTE_PLACEHOLDER = "[temp clipboard paste file]";
const WINDOWS_TEMP_CLIPBOARD_PASTE_PATH = /[A-Z]:(?:\\\\|\\)[^\r\n"'`]*?(?:\\\\|\\)mini-term-clipboard(?:\\\\|\\)paste-\d+\.txt/gi;
const POSIX_TEMP_CLIPBOARD_PASTE_PATH = /\/[^\r\n"'`]*?\/mini-term-clipboard\/paste-\d+\.txt/gi;
const BARE_TEMP_CLIPBOARD_PASTE_PATH = /mini-term-clipboard[\\/]paste-\d+\.txt/gi;
/**
 * 脱敏终端剪贴板生成的临时 paste 文件路径。
 * 主流程：匹配 Windows/POSIX/裸目录形式 -> 替换为稳定占位符，避免临时文件路径进入日志与状态详情。
 */
export function redactTransientClipboardPastePaths(text) {
    return text
        .replace(WINDOWS_TEMP_CLIPBOARD_PASTE_PATH, TEMP_CLIPBOARD_PASTE_PLACEHOLDER)
        .replace(POSIX_TEMP_CLIPBOARD_PASTE_PATH, TEMP_CLIPBOARD_PASTE_PLACEHOLDER)
        .replace(BARE_TEMP_CLIPBOARD_PASTE_PATH, TEMP_CLIPBOARD_PASTE_PLACEHOLDER);
}
/**
 * 判断输入是否只是终端剪贴板生成的临时 paste 文件路径。
 * 主流程：剥离包裹引号 -> 要求整串匹配，避免误拦截显式读取该文件的正常命令。
 */
export function isTransientClipboardPasteFilePath(text) {
    const trimmed = text.trim().replace(/^(["'])(.*)\1$/, "$2");
    return [
        WINDOWS_TEMP_CLIPBOARD_PASTE_PATH,
        POSIX_TEMP_CLIPBOARD_PASTE_PATH,
        BARE_TEMP_CLIPBOARD_PASTE_PATH,
    ].some((pattern) => {
        pattern.lastIndex = 0;
        const match = pattern.exec(trimmed);
        return Boolean(match && match[0] === trimmed);
    });
}
/**
 * 递归脱敏工具展示参数，保留真实执行输入不变，仅用于日志/状态/时间线展示。
 */
export function redactTransientClipboardPastePathsInValue(value) {
    if (typeof value === "string") {
        return redactTransientClipboardPastePaths(value);
    }
    if (Array.isArray(value)) {
        return value.map((item) => redactTransientClipboardPastePathsInValue(item));
    }
    if (value && typeof value === "object") {
        return Object.fromEntries(Object.entries(value).map(([key, item]) => [
            key,
            redactTransientClipboardPastePathsInValue(item),
        ]));
    }
    return value;
}
/**
 * 已知的 MCP 工具名映射表
 * 用于识别 MCP 工具并确定其来源 server
 *
 * 格式: { 工具名: MCP server 名称 }
 */
const KNOWN_MCP_TOOLS = {
    // aws-mcp 工具
    get_colleague: "aws-mcp",
    get_group_rooms: "aws-mcp",
    get_profile: "aws-mcp",
    get_status: "aws-mcp",
    hire_colleague: "aws-mcp",
    hire_colleagues_batch: "aws-mcp",
    send_group: "aws-mcp",
    send_private: "aws-mcp",
    poll_message: "aws-mcp",
    get_message: "aws-mcp",
    get_dm_history: "aws-mcp",
    get_group_history: "aws-mcp",
    my_task: "aws-mcp",
    submit_task_result: "aws-mcp",
    reject_task: "aws-mcp",
    terminate_task: "aws-mcp",
};
const AGENTSWORK_MCP_SERVER_ALIASES = new Set([
    "aws-mcp",
    "agents-work-studio",
]);
function canonicalizeMcpServer(serverName, toolName) {
    const knownMcpServer = KNOWN_MCP_TOOLS[toolName.toLowerCase()];
    if (knownMcpServer &&
        AGENTSWORK_MCP_SERVER_ALIASES.has(serverName.toLowerCase())) {
        return knownMcpServer;
    }
    return serverName;
}
export function getCanonicalMcpDetail(rawToolName) {
    const normalizedRawToolName = rawToolName.trim();
    if (!normalizedRawToolName)
        return normalizedRawToolName;
    if (normalizedRawToolName.includes("__")) {
        const parts = normalizedRawToolName.split("__").filter(Boolean);
        if (parts.length >= 3 && parts[0].toLowerCase() === "mcp") {
            const serverName = parts[1];
            const toolName = parts.slice(2).join("__");
            return `${canonicalizeMcpServer(serverName, toolName)}/${toolName}`;
        }
        if (parts.length >= 2) {
            const serverName = parts[0];
            const toolName = parts.slice(1).join("__");
            return `${canonicalizeMcpServer(serverName, toolName)}/${toolName}`;
        }
    }
    const knownMcpServer = KNOWN_MCP_TOOLS[normalizedRawToolName.toLowerCase()];
    return knownMcpServer
        ? `${knownMcpServer}/${normalizedRawToolName}`
        : normalizedRawToolName;
}
function formatCanonicalMcpDetail(serverName, toolName) {
    if (!serverName)
        return toolName;
    if (!toolName)
        return serverName;
    return `${canonicalizeMcpServer(serverName, toolName)}/${toolName}`;
}
/**
 * 根据工具名称获取动作类型信息
 * @param toolName 工具名称
 * @param toolInput 工具输入参数
 * @param metadata SDK 提供的元数据（可能包含 MCP server 信息）
 */
export function getToolActionInfo(toolName, toolInput, metadata) {
    if (!toolName) {
        return { actionType: "other", actionLabel: "调用工具" };
    }
    const name = toolName.toLowerCase();
    const normalizedName = name.replace(/[_-]/g, "");
    const semanticToolName = name.startsWith("mcp__")
        ? name.split("__").slice(2).join("__")
        : name.startsWith("builtin__")
            ? name.split("__").slice(1).join("__")
            : name.includes("-mcp__")
                ? name.slice(name.indexOf("-mcp__") + 6)
                : name.includes("/")
                    ? name.split("/").filter(Boolean).at(-1) || name
                    : name;
    const normalizedSemanticToolName = semanticToolName.replace(/[_-]/g, "");
    const normalizeSkillList = (value) => {
        if (!Array.isArray(value)) {
            return [];
        }
        return value
            .map((item) => String(item ?? "").trim())
            .filter((item) => item.length > 0);
    };
    const firstString = (...values) => {
        for (const value of values) {
            if (typeof value === "string" && value.trim()) {
                return redactTransientClipboardPastePaths(value);
            }
            if (Array.isArray(value) && value.length > 0) {
                const first = value[0];
                if (typeof first === "string" && first.trim()) {
                    return redactTransientClipboardPastePaths(first);
                }
            }
        }
        return undefined;
    };
    const matchesToolName = (...toolNames) => {
        const normalizedToolNames = toolNames.map((item) => item.replace(/[_-]/g, ""));
        return (normalizedToolNames.includes(normalizedName) ||
            normalizedToolNames.includes(normalizedSemanticToolName));
    };
    const loadSkills = normalizeSkillList(toolInput?.load_skills);
    if ((name === "task" || name === "task()") && loadSkills.length > 0) {
        return {
            actionType: "skill",
            actionLabel: "加载技能",
            actionDetail: loadSkills.join(", "),
        };
    }
    // Skill 调用
    // 识别策略：
    // 1. 工具名是 'skill' (官方 Skill 工具)
    // 2. 工具名包含 'skill' 关键词（如 load_skill, skill-trigger 等）
    // 3. 排除 mcp 工具（mcp__xxx__skill 格式是 MCP 工具，不是 Skill）
    //
    // 注意：SDK 发送的 tool_name 可能是 'Skill'（大写）或 'skill'（小写）
    // 使用 toLowerCase() 统一处理
    const isSkillTool = name === "skill" ||
        name === "load_skill" ||
        name === "disclosecontext" ||
        (name.includes("skill") &&
            !name.startsWith("mcp__") &&
            !name.includes("mcp_"));
    if (isSkillTool) {
        // Skill 参数可能有多种格式：
        // 1. { skill: "skillName" }
        // 2. { name: "skillName" }
        // 3. { args: { name: "skillName", ... } }  // task() 格式
        // 4. { load_skills: ["skill1", "skill2"] } // task() 加载技能格式
        let skillName = "";
        // 检查 load_skills 格式（task 工具）
        if (Array.isArray(toolInput?.load_skills) &&
            toolInput.load_skills.length > 0) {
            skillName = toolInput.load_skills.join(", ");
        }
        // 检查 skill 参数
        else if (typeof toolInput?.skill === "string") {
            skillName = toolInput.skill;
        }
        // 检查 name 参数
        else if (typeof toolInput?.name === "string") {
            skillName = toolInput.name;
        }
        // 检查嵌套的 args.name
        else if (toolInput?.args && typeof toolInput.args === "object") {
            const args = toolInput.args;
            if (typeof args.name === "string") {
                skillName = args.name;
            }
            else if (typeof args.skill === "string") {
                skillName = args.skill;
            }
        }
        return {
            actionType: "skill",
            actionLabel: "使用技能",
            actionDetail: skillName || undefined,
        };
    }
    // 文件/命令工具即使走 MCP 命名，也优先按语义显示为读取/编辑/命令执行。
    if (matchesToolName("edit", "editfile", "strreplace", "editcode", "apply_patch", "multiedit", "replace")) {
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "edit_file",
            actionLabel: "编辑文件",
            actionDetail: filePath,
        };
    }
    if (matchesToolName("write", "writefile", "fswrite")) {
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "write_file",
            actionLabel: "写入文件",
            actionDetail: filePath,
        };
    }
    if (matchesToolName("read", "readfile", "readcode", "readmultiplefiles", "read_file")) {
        if (Array.isArray(toolInput?.paths)) {
            return {
                actionType: "read_file",
                actionLabel: "读取文件",
                actionDetail: `${toolInput.paths.length}个文件`,
            };
        }
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.paths, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "read_file",
            actionLabel: "读取文件",
            actionDetail: filePath,
        };
    }
    if (matchesToolName("bash", "shell", "command", "executepwsh", "controlpwshprocess", "execute", "run_command", "execute_command")) {
        const command = firstString(toolInput?.command, toolInput?.cmd, toolInput?.argv);
        return {
            actionType: "bash",
            actionLabel: "执行命令",
            actionDetail: command?.slice(0, 50),
        };
    }
    if (matchesToolName("poll_message", "get_message")) {
        return {
            actionType: "idle",
            actionLabel: "监听消息",
            actionDetail: getCanonicalMcpDetail(toolName),
        };
    }
    // MCP 工具调用
    // 优先使用 metadata 中的 mcpServer 信息（SDK 直接提供）
    // 格式包括：
    // 1. metadata.mcpServer（SDK 提供的 MCP server 名称）
    // 2. 已知 MCP 工具名白名单（KNOWN_MCP_TOOLS）
    // 3. mcp__server__tool (标准格式)
    // 4. xxx-mcp__tool (自定义格式，如 aws-mcp__get_profile)
    // 5. 包含 'mcp_' 的工具名
    // 6. Kiro 的 kiroPowers
    //
    // actionDetail 格式: server/tool（包含 MCP server 名称，便于用户识别工具来源）
    // 优先检查 metadata 中的 MCP server 信息
    if (metadata?.mcpServer) {
        const mcpServer = metadata.mcpServer;
        const mcpTool = toolName || "";
        const detail = formatCanonicalMcpDetail(mcpServer, mcpTool);
        return { actionType: "mcp", actionLabel: "调用MCP", actionDetail: detail };
    }
    // 检查是否在已知 MCP 工具列表中
    const knownMcpServer = KNOWN_MCP_TOOLS[toolName];
    if (knownMcpServer) {
        const detail = `${knownMcpServer}/${toolName}`;
        return { actionType: "mcp", actionLabel: "调用MCP", actionDetail: detail };
    }
    const isMcpTool = name.startsWith("mcp__") ||
        name.includes("-mcp__") ||
        (name.includes("mcp_") && !name.includes("skill")) ||
        name === "kiropowers";
    if (isMcpTool) {
        let mcpServer = "";
        let mcpTool = "";
        if (name.startsWith("mcp__")) {
            // 标准格式: mcp__server__tool
            const parts = toolName.split("__");
            mcpServer = parts[1] || "";
            mcpTool = parts.slice(2).join("__") || "";
        }
        else if (name.includes("-mcp__")) {
            // 自定义格式: xxx-mcp__tool (如 aws-mcp__get_profile)
            const idx = name.indexOf("-mcp__");
            mcpServer = name.substring(0, idx + 4); // "xxx-mcp"（保留完整 server 名）
            mcpTool = name.substring(idx + 6); // 去掉 "-mcp__" 前缀，得到工具名
        }
        else if (name === "kiropowers") {
            mcpServer = "kiro";
            mcpTool = (toolInput?.powerName || toolInput?.action) || "";
        }
        else {
            // 其他包含 mcp_ 的格式
            mcpServer = "mcp";
            mcpTool = toolName;
        }
        // 格式: server/tool（便于用户识别 MCP server 来源）
        const detail = formatCanonicalMcpDetail(mcpServer, mcpTool) || toolName;
        return { actionType: "mcp", actionLabel: "调用MCP", actionDetail: detail };
    }
    // 文件编辑 (Kiro: strReplace, editCode)
    if (matchesToolName("edit", "editfile", "strreplace", "editcode", "apply_patch", "multiedit", "replace")) {
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "edit_file",
            actionLabel: "编辑文件",
            actionDetail: filePath,
        };
    }
    // 文件写入 (Kiro: fsWrite)
    if (matchesToolName("write", "writefile", "fswrite")) {
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "write_file",
            actionLabel: "写入文件",
            actionDetail: filePath,
        };
    }
    // 文件读取 (Kiro: readFile, readCode, readMultipleFiles)
    if (matchesToolName("read", "readfile", "readcode", "readmultiplefiles", "read_file")) {
        if (Array.isArray(toolInput?.paths)) {
            return {
                actionType: "read_file",
                actionLabel: "读取文件",
                actionDetail: `${toolInput.paths.length}个文件`,
            };
        }
        const filePath = firstString(toolInput?.file_path, toolInput?.filePath, toolInput?.path, toolInput?.paths, toolInput?.target_file, toolInput?.targetFile);
        return {
            actionType: "read_file",
            actionLabel: "读取文件",
            actionDetail: filePath,
        };
    }
    // Bash 命令 (Kiro: executePwsh, controlPwshProcess)
    if (matchesToolName("bash", "shell", "command", "executepwsh", "controlpwshprocess", "execute", "run_command", "execute_command")) {
        const command = firstString(toolInput?.command, toolInput?.cmd, toolInput?.argv);
        return {
            actionType: "bash",
            actionLabel: "执行命令",
            actionDetail: command?.slice(0, 50),
        };
    }
    // 文件搜索 (Kiro: grepSearch, fileSearch)
    if (name === "glob" ||
        name === "grep" ||
        name === "find" ||
        name === "search" ||
        name === "grepsearch" ||
        name === "filesearch") {
        const query = (toolInput?.query || toolInput?.pattern);
        return {
            actionType: "search",
            actionLabel: "搜索文件",
            actionDetail: query?.slice(0, 30),
        };
    }
    // 网络操作 (Kiro: webFetch, remote_web_search)
    if (name === "webfetch" ||
        name === "websearch" ||
        name === "fetch" ||
        name === "http" ||
        name === "remote_web_search") {
        const url = (toolInput?.url || toolInput?.query);
        return {
            actionType: "web",
            actionLabel: "网络请求",
            actionDetail: url?.slice(0, 50),
        };
    }
    // LSP 操作
    if (name.startsWith("lsp") || name.includes("language_server")) {
        return { actionType: "lsp", actionLabel: "LSP操作" };
    }
    // Notebook 编辑
    if (name === "notebookedit" || name.includes("notebook")) {
        return { actionType: "notebook", actionLabel: "编辑Notebook" };
    }
    // 其他工具
    return {
        actionType: "other",
        actionLabel: "调用工具",
        actionDetail: toolName,
    };
}
// ============ Adapter 基类 ============
/**
 * Provider Adapter 基类
 *
 * 每个 AI CLI 工具对应一个 Adapter 实现，负责：
 * 1. 管理 CLI 进程/SDK 客户端的生命周期
 * 2. 将 Provider 特定的消息格式转换为统一的 ProviderEvent
 * 3. 维护对话消息历史
 *
 * 事件:
 * - 'event'(ProviderEvent) — 统一事件流
 * - 'status-change'(sessionId, SessionStatus) — 会话状态变更
 * - 'permission-request'(PermissionRequest) — 权限确认请求
 * - 'ask-user-question'(AskUserQuestionRequest) — 用户问答请求
 */
export class BaseProviderAdapter extends EventEmitter {
}
