/**
 * MCP Server 实现
 * 提供 MCP Tools 供 AI Agent 调用
 */
import path from "node:path";
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
import { AgentClient } from "./agent-client.js";
import { MCP_SERVER_NAME, MCP_SERVER_VERSION, REGISTER_RETRY_INTERVAL_MS, } from "./constants.js";
import { logger } from "./logger.js";
import { MCP_TOOLS } from "./mcp-tools.js";
import { MessageBuffer } from "./message-buffer.js";
import { MemoryCapacityError, MemoryStore, } from "./memory-store.js";
import { ServerMemoryStore } from "./server-memory-store.js";
const DEFAULT_POLL_MESSAGE_BLOCK_WAIT_MS = 30_000;
const DEFAULT_POLL_MESSAGE_EMPTY_RETRY_DELAY_MS = 100;
const DEFAULT_POLL_MESSAGE_ERROR_RETRY_DELAY_MS = 5_000;
const DEFAULT_MCP_HTTP_REQUEST_TIMEOUT_MS = 120_000;
const POLL_MESSAGE_HTTP_TIMEOUT_BUFFER_MS = 1_000;
const PATH_UNSAFE_CHARACTERS = new Set([
    "<",
    ">",
    ":",
    '"',
    "/",
    "\\",
    "|",
    "?",
    "*",
]);
export class McpServer {
    server;
    agentClient;
    messageBuffer;
    memoryStore;
    roleMemoryStore;
    memoryStoresShareFile;
    /**
     * 记忆写入成功后的 MCP 响应 DTO。
     * 主流程：保留定位与版本元数据，刻意不包含 content，避免 create/update 回显大段提交内容。
     */
    toMemoryWriteResult(record) {
        return {
            id: record.id,
            uri: record.uri,
            domain: record.domain,
            path: record.path,
            memory_type: record.memory_type,
            createdAt: record.createdAt,
            updatedAt: record.updatedAt,
            version: record.version,
        };
    }
    constructor() {
        this.agentClient = new AgentClient();
        this.messageBuffer = new MessageBuffer();
        const memoryStorePaths = McpServer.resolveMemoryStorePaths();
        this.memoryStore = new ServerMemoryStore(this.agentClient);
        this.roleMemoryStore = new MemoryStore(memoryStorePaths.rolePath);
        this.memoryStoresShareFile = false;
        this.server = new Server({
            name: MCP_SERVER_NAME,
            version: MCP_SERVER_VERSION,
        }, {
            capabilities: {
                tools: {},
            },
        });
        this.setupHandlers();
    }
    setupHandlers() {
        this.server.setRequestHandler(ListToolsRequestSchema, async () => {
            return { tools: MCP_TOOLS };
        });
        this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
            const { name, arguments: args } = request.params;
            try {
                const result = await this.handleToolCall(name, args);
                return {
                    content: [
                        {
                            type: "text",
                            text: JSON.stringify(result, null, 2),
                        },
                    ],
                };
            }
            catch (error) {
                const errorMessage = error instanceof Error ? error.message : String(error);
                const errorPayload = error instanceof MemoryCapacityError
                    ? {
                        error: errorMessage,
                        ...error.details,
                    }
                    : { error: errorMessage };
                return {
                    content: [
                        {
                            type: "text",
                            text: JSON.stringify(errorPayload, null, 2),
                        },
                    ],
                    isError: true,
                };
            }
        });
    }
    /**
     * 处理工具调用
     */
    async handleToolCall(name, args) {
        // 报告工具调用状态
        const statusReporter = this.agentClient.getStatusReporter();
        if (statusReporter) {
            statusReporter.reportToolUse(name, this.sanitizeToolUseArgs(name, args));
        }
        try {
            const result = await this.executeToolCall(name, args);
            // 工具调用完成后，先上报返回数据供时间线日志查看，再切换为思考状态
            // （Agent 正在处理工具结果、决定下一步动作，而非真正的空闲等待）
            if (statusReporter) {
                statusReporter.reportToolResult(result);
                statusReporter.reportThinking();
            }
            return result;
        }
        catch (error) {
            // 工具调用失败，报告错误状态
            if (statusReporter) {
                statusReporter.reportToolError(error);
            }
            throw error;
        }
    }
    /**
     * 执行具体的工具调用
     */
    async executeToolCall(name, args) {
        switch (name) {
            case "get_colleague":
                return await this.agentClient.discoverColleagues();
            case "get_group_rooms":
                return await this.agentClient.discoverGroupRooms();
            case "get_profile": {
                return await this.agentClient.getProfile();
            }
            case "get_status":
                return this.agentClient.getState();
            case "hire_colleague":
                return await this.handleHireColleague(args);
            case "hire_colleagues_batch":
                return await this.handleHireColleaguesBatch(args);
            case "send_group":
                return await this.handleSendGroup(args);
            case "send_private":
                return await this.handleSendPrivate(args);
            case "poll_message":
                return await this.handlePollMessage();
            case "get_message":
                return this.handleGetMessage();
            case "get_dm_history":
                return await this.handleGetDmHistory(args);
            case "get_group_history":
                return await this.handleGetGroupHistory(args);
            case "my_task":
                return await this.agentClient.getMyTasks();
            case "create_task_instance_comment":
                return await this.handleCreateTaskInstanceComment(args);
            case "submit_task_result":
                return await this.handleSubmitTaskResult(args);
            case "record_task_change":
                return await this.handleRecordTaskChange(args);
            case "start_task_rollback":
                return await this.handleStartTaskRollback(args);
            case "finish_task_rollback":
                return await this.handleFinishTaskRollback(args);
            case "reject_task":
                return await this.handleRejectTask(args);
            case "terminate_task":
                return await this.handleTerminateTask(args);
            case "create_memory":
                return await this.handleCreateMemory(args);
            case "read_memory":
                return await this.handleReadMemory(args);
            case "update_memory":
                return await this.handleUpdateMemory(args);
            case "delete_memory":
                return await this.handleDeleteMemory(args);
            case "search_memory":
                return await this.handleSearchMemory(args);
            case "list_memories":
                return await this.handleListMemories(args);
            case "get_memory_stats":
                return await this.handleGetMemoryStats(args);
            case "remove_task_list_memory":
                return await this.handleRemoveTaskListMemory(args);
            case "archive_recently_memory":
                return await this.handleArchiveRecentlyMemory(args);
            default:
                throw new Error(`Unknown tool: ${name}`);
        }
    }
    // ============ 工具处理方法 ============
    static MEMORY_TYPES = [
        "task_list",
        "recently_memory",
        "memory",
    ];
    static MEMORY_TOOL_NAMES = new Set([
        "create_memory",
        "read_memory",
        "update_memory",
        "delete_memory",
        "search_memory",
        "list_memories",
        "get_memory_stats",
        "remove_task_list_memory",
        "archive_recently_memory",
    ]);
    /**
     * 解析角色级记忆目录名。
     * 主流程：优先使用 AWS_ROLE_NAME，清理路径分隔符等非法字符，避免不同角色的长期 memory 混写。
     */
    static resolveRoleMemoryDirectoryName() {
        const roleName = String(process.env.AWS_ROLE_NAME || "").trim();
        const safeRoleName = roleName
            .split("")
            .map((character) => PATH_UNSAFE_CHARACTERS.has(character) || character.charCodeAt(0) < 32
            ? "_"
            : character)
            .join("")
            .replace(/^\.+|\.+$/g, "")
            .trim();
        return safeRoleName || "default-role";
    }
    /**
     * 解析记忆存储路径。
     * 主流程：task_list/recently_memory 走 server 数据库；长期 memory 默认写入项目 .agentswork/memory/memory/<roleName>/<domain>.json。
     */
    static resolveMemoryStorePaths() {
        const configuredPath = String(process.env.AWS_MEMORY_STORE_PATH || "").trim();
        if (configuredPath) {
            return { instancePath: configuredPath, rolePath: configuredPath };
        }
        const workspacePath = process.env.AWS_WORKSPACE_PATH || process.cwd();
        const instancePath = String(process.env.AWS_INSTANCE_MEMORY_STORE_PATH || "").trim() ||
            path.join(workspacePath, ".agentswork", "memory", "server-managed");
        const rolePath = String(process.env.AWS_ROLE_MEMORY_STORE_PATH || "").trim() ||
            path.join(workspacePath, ".agentswork", "memory", "memory", McpServer.resolveRoleMemoryDirectoryName());
        return { instancePath, rolePath };
    }
    getRequiredString(args, key) {
        const value = args[key];
        if (typeof value !== "string" || value.trim().length === 0) {
            throw new Error(`${key} is required`);
        }
        return value;
    }
    getOptionalString(args, key) {
        const value = args[key];
        return typeof value === "string" ? value : undefined;
    }
    getOptionalNumber(args, key) {
        const value = args[key];
        return typeof value === "number" ? value : undefined;
    }
    getOptionalMemoryType(args) {
        const value = args.memory_type;
        if (value === undefined) {
            return undefined;
        }
        return this.parseMemoryType(value);
    }
    parseMemoryType(value) {
        if (typeof value !== "string") {
            throw new Error(`Invalid memory_type: ${String(value)}`);
        }
        const normalized = value.trim();
        if (!this.isMemoryType(normalized)) {
            throw new Error(`Invalid memory_type: ${value}`);
        }
        return normalized;
    }
    isMemoryType(value) {
        return McpServer.MEMORY_TYPES.some((memoryType) => memoryType === value);
    }
    /**
     * 按记忆生命周期选择存储作用域。
     * 主流程：长期 memory 走角色级 store；task_list/recently_memory 走当前 Agent 实例级 store。
     */
    getMemoryStoreForType(memoryType) {
        return memoryType === "memory" ? this.roleMemoryStore : this.memoryStore;
    }
    /**
     * 在未显式指定类型时按两个作用域读取。
     * 主流程：先查角色级长期记忆 -> 再查实例级临时/近期记忆，保持旧工具参数可选语义。
     */
    async readMemoryFromScopedStores(input) {
        if (this.memoryStoresShareFile) {
            return await this.memoryStore.readMemory(input);
        }
        if (input.memory_type) {
            return await this.getMemoryStoreForType(input.memory_type).readMemory(input);
        }
        const longTermRecord = await this.roleMemoryStore.readMemory({
            ...input,
            memory_type: "memory",
        });
        if (longTermRecord) {
            return longTermRecord;
        }
        return await this.memoryStore.readMemory(input);
    }
    /**
     * 在未显式指定类型时定位可更新/删除的存储。
     * 主流程：按读取优先级查找记录 -> 返回命中的 store 与规范化类型，避免跨作用域误写。
     */
    async findMemoryStoreForMutation(input) {
        if (this.memoryStoresShareFile) {
            return { store: this.memoryStore, memory_type: input.memory_type };
        }
        if (input.memory_type) {
            return {
                store: this.getMemoryStoreForType(input.memory_type),
                memory_type: input.memory_type,
            };
        }
        const longTermRecord = await this.roleMemoryStore.readMemory({
            uri: input.uri,
            memory_type: "memory",
        });
        if (longTermRecord) {
            return { store: this.roleMemoryStore, memory_type: "memory" };
        }
        return { store: this.memoryStore };
    }
    /**
     * 合并角色级长期记忆与实例级短期记忆容量统计。
     * 主流程：实例 store 负责 listable 限额；角色 store 只贡献长期 memory 数量。
     */
    combineMemoryStats(instanceStats, roleStats) {
        if (this.memoryStoresShareFile) {
            return instanceStats;
        }
        return {
            total: instanceStats.total + roleStats.by_type.memory.count,
            listable: instanceStats.listable,
            by_type: {
                task_list: instanceStats.by_type.task_list,
                recently_memory: instanceStats.by_type.recently_memory,
                memory: {
                    ...roleStats.by_type.memory,
                    count: roleStats.by_type.memory.count,
                },
            },
        };
    }
    /**
     * 上报当前合并后的记忆统计。
     * 主流程：读取实例级与角色级统计 -> 合并长期 memory count -> 通过 server 广播给 Dashboard。
     */
    async reportCombinedMemoryStats() {
        const [instanceStats, roleStats] = await Promise.all([
            this.memoryStore.getStats(),
            this.roleMemoryStore.getStats(),
        ]);
        try {
            await this.agentClient.reportMemoryStats(this.combineMemoryStats(instanceStats, roleStats));
        }
        catch (error) {
            logger.warn("[McpServer] 上报合并 memory 统计失败，已保留本地记忆写入结果:", error);
        }
    }
    /**
     * 生成安全的工具状态上报参数。
     * 主流程：memory 工具只上报元数据，避免 content/query/old_string/new_string/append 离开本地记忆边界。
     */
    sanitizeToolUseArgs(name, args) {
        if (!McpServer.MEMORY_TOOL_NAMES.has(name)) {
            return args;
        }
        const sanitized = {};
        const uri = this.getOptionalString(args, "uri");
        const memoryType = this.getOptionalString(args, "memory_type");
        const limit = this.getOptionalNumber(args, "limit");
        if (uri) {
            sanitized.uri = uri;
        }
        if (memoryType) {
            sanitized.memory_type = memoryType;
        }
        if (typeof limit === "number") {
            sanitized.limit = limit;
        }
        if (name === "search_memory") {
            sanitized.queryProvided =
                typeof args.query === "string" && args.query.length > 0;
        }
        return sanitized;
    }
    /**
     * 创建本地记忆。
     * 主流程：校验必填字段 -> 交给 MemoryStore 规范化 URI 和类型 -> 返回不含 content 的写入结果。
     */
    async handleCreateMemory(args) {
        const input = {
            memory_type: this.parseMemoryType(this.getRequiredString(args, "memory_type")),
            uri: this.getRequiredString(args, "uri"),
            content: this.getRequiredString(args, "content"),
        };
        const created = await this.getMemoryStoreForType(input.memory_type).createMemory(input);
        await this.reportCombinedMemoryStats();
        return this.toMemoryWriteResult(created);
    }
    /**
     * 读取本地记忆。
     * 主流程：按 uri 读取；如果传入 memory_type，则由 MemoryStore 执行类型一致性校验。
     */
    async handleReadMemory(args) {
        const input = {
            uri: this.getRequiredString(args, "uri"),
            memory_type: this.getOptionalMemoryType(args),
        };
        return await this.readMemoryFromScopedStores(input);
    }
    /**
     * 更新本地记忆。
     * 主流程：要求至少一种变更方式 -> MemoryStore 执行精确替换/追加和版本递增 -> 返回不含 content 的写入结果。
     */
    async handleUpdateMemory(args) {
        const hasReplace = typeof args.old_string === "string" ||
            typeof args.new_string === "string";
        const hasCompleteReplace = typeof args.old_string === "string" &&
            typeof args.new_string === "string";
        const append = this.getOptionalString(args, "append");
        if (hasReplace && !hasCompleteReplace) {
            throw new Error("old_string and new_string must be provided together");
        }
        if (!hasCompleteReplace &&
            (typeof append !== "string" || append.length === 0)) {
            throw new Error("Provide either old_string/new_string or append");
        }
        const input = {
            uri: this.getRequiredString(args, "uri"),
            memory_type: this.getOptionalMemoryType(args),
            old_string: this.getOptionalString(args, "old_string"),
            new_string: this.getOptionalString(args, "new_string"),
            append,
        };
        const target = await this.findMemoryStoreForMutation(input);
        const updated = await target.store.updateMemory({
            ...input,
            memory_type: target.memory_type ?? input.memory_type,
        });
        await this.reportCombinedMemoryStats();
        return this.toMemoryWriteResult(updated);
    }
    /**
     * 删除本地记忆。
     * 主流程：按 uri 删除；如果传入 memory_type，则先校验分类，最后返回 deleted 布尔值。
     */
    async handleDeleteMemory(args) {
        const input = {
            uri: this.getRequiredString(args, "uri"),
            memory_type: this.getOptionalMemoryType(args),
        };
        const target = await this.findMemoryStoreForMutation(input);
        const deleted = await target.store.deleteMemory({
            ...input,
            memory_type: target.memory_type ?? input.memory_type,
        });
        if (deleted) {
            await this.reportCombinedMemoryStats();
        }
        return { deleted };
    }
    /**
     * 搜索本地记忆。
     * 主流程：校验 query -> MemoryStore 对 uri/content 做大小写不敏感匹配和排序。
     */
    async handleSearchMemory(args) {
        const input = {
            query: this.getRequiredString(args, "query"),
            limit: this.getOptionalNumber(args, "limit"),
            memory_type: this.getOptionalMemoryType(args),
        };
        if (input.memory_type) {
            return await this.getMemoryStoreForType(input.memory_type).searchMemory(input);
        }
        if (this.memoryStoresShareFile) {
            return await this.memoryStore.searchMemory(input);
        }
        const [roleResult, instanceResult] = await Promise.all([
            this.roleMemoryStore.searchMemory({ ...input, memory_type: "memory" }),
            this.memoryStore.searchMemory(input),
        ]);
        const seen = new Set();
        const limit = typeof input.limit === "number" && input.limit > 0 ? input.limit : 10;
        const results = [...roleResult.results, ...instanceResult.results]
            .filter((record) => {
            const key = `${record.memory_type}:${record.uri}`;
            if (seen.has(key)) {
                return false;
            }
            seen.add(key);
            return true;
        })
            .sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))
            .slice(0, limit);
        return { query: roleResult.query || instanceResult.query, results };
    }
    /**
     * 列出短期类型记忆。
     * 主流程：只允许 task_list/recently_memory，由 MemoryStore 阻止长期 memory 的全量列出。
     */
    async handleListMemories(args) {
        return await this.memoryStore.listByType(this.getRequiredString(args, "memory_type"));
    }
    /**
     * 获取本地记忆容量统计。
     * 主流程：读取 MemoryStore 统计结果，供 Agent 在创建前判断 listable/type 容量。
     */
    async handleGetMemoryStats(args) {
        const [instanceStats, roleStats] = await Promise.all([
            this.memoryStore.getStats(),
            this.roleMemoryStore.getStats(),
        ]);
        const stats = this.combineMemoryStats(instanceStats, roleStats);
        const memoryType = this.getOptionalMemoryType(args);
        if (!memoryType) {
            return stats;
        }
        return {
            memory_type: memoryType,
            total: stats.by_type[memoryType].count,
            by_type: {
                [memoryType]: stats.by_type[memoryType],
            },
        };
    }
    /**
     * 移除任务清单记忆。
     * 主流程：按 uri 读取并校验 task_list 类型后删除，避免误删长期记忆。
     */
    async handleRemoveTaskListMemory(args) {
        const removed = await this.memoryStore.removeTaskListMemory(this.getRequiredString(args, "uri"));
        return { removed };
    }
    /**
     * 归档近期记忆。
     * 主流程：将 recently_memory 原地转换为长期 memory，并递增版本号。
     */
    async handleArchiveRecentlyMemory(args) {
        const uri = this.getRequiredString(args, "uri");
        if (this.memoryStoresShareFile) {
            return await this.memoryStore.archiveRecentlyMemory(uri);
        }
        const record = await this.memoryStore.readMemory({
            uri,
            memory_type: "recently_memory",
        });
        if (!record) {
            throw new Error(`Memory not found: ${uri}`);
        }
        const archived = await this.roleMemoryStore.createMemory({
            memory_type: "memory",
            uri: record.uri,
            content: record.content,
        });
        await this.memoryStore.deleteMemory({
            uri: record.uri,
            memory_type: "recently_memory",
        });
        await this.reportCombinedMemoryStats();
        return archived;
    }
    async handleSendGroup(args) {
        if (!args.content || typeof args.content !== "string") {
            throw new Error("content is required");
        }
        return await this.agentClient.sendGroupMessage(args.content, args.projectName, args.roomId);
    }
    async handleHireColleague(args) {
        if (!args.workspacePath || typeof args.workspacePath !== "string") {
            throw new Error("workspacePath is required");
        }
        return await this.agentClient.hireColleague(args);
    }
    async handleHireColleaguesBatch(args) {
        if (!Array.isArray(args.items) || args.items.length === 0) {
            throw new Error("items is required and must contain at least one hire item");
        }
        args.items.forEach((item, index) => {
            if (!item.workspacePath || typeof item.workspacePath !== "string") {
                throw new Error(`items[${index}].workspacePath is required`);
            }
        });
        return await this.agentClient.hireColleaguesBatch(args);
    }
    async handleSendPrivate(args) {
        if (!args.targetId || typeof args.targetId !== "string") {
            throw new Error("targetId is required");
        }
        if (!args.content || typeof args.content !== "string") {
            throw new Error("content is required");
        }
        return await this.agentClient.sendDirectMessage(args.targetId, args.content, args.waitReply, args.replyToCallId, args.timeoutMs);
    }
    async handleCreateTaskInstanceComment(args) {
        const taskInstanceId = this.getRequiredString(args, "taskInstanceId");
        const content = this.getRequiredString(args, "content");
        return await this.agentClient.createTaskInstanceComment({
            taskInstanceId,
            content,
        });
    }
    async handlePollMessage() {
        await this.hydrateUnreadMessagesFromServer({
            blockIfEmpty: false,
            includePipelineTasks: true,
        });
        const immediateMemoryNotification = await this.buildMemoryCleanupNotification();
        if (immediateMemoryNotification) {
            const messages = this.messageBuffer.get();
            messages.directMessages.unshift(immediateMemoryNotification);
            return {
                directMessages: messages.directMessages,
                groupMessages: messages.groupMessages,
                fromBuffer: true,
            };
        }
        await this.hydrateUnreadMessagesUntilAvailable();
        const messages = this.messageBuffer.get();
        const memoryNotification = await this.buildMemoryCleanupNotification();
        if (memoryNotification) {
            messages.directMessages.unshift(memoryNotification);
        }
        return {
            directMessages: messages.directMessages,
            groupMessages: messages.groupMessages,
            fromBuffer: true,
        };
    }
    /**
     * 持续补拉未读消息直到有消息可返回。
     * 主流程：用有限后端长轮询分片阻塞补拉 -> 空返回时短暂退避 -> 继续等待，避免 poll_message 空轮询唤醒模型。
     * 注意：poll_message 是 Agent 主循环的永久阻塞入口，不能恢复为按总时长限时返回空结果。
     */
    async hydrateUnreadMessagesUntilAvailable() {
        while (this.messageBuffer.size() === 0) {
            const hydrated = await this.hydrateUnreadMessagesIfNeeded({
                blockIfEmpty: true,
                blockTimeoutMs: this.resolvePollMessageBlockWaitMs(),
                includePipelineTasks: true,
            });
            if (this.messageBuffer.size() === 0) {
                await this.sleep(hydrated
                    ? this.resolvePollMessageEmptyRetryDelayMs()
                    : this.resolvePollMessageErrorRetryDelayMs());
            }
        }
    }
    resolvePollMessageBlockWaitMs() {
        const blockWaitMs = this.parsePositiveIntegerEnv("AWS_POLL_MESSAGE_BLOCK_WAIT_MS", DEFAULT_POLL_MESSAGE_BLOCK_WAIT_MS);
        const httpTimeoutMs = this.parsePositiveIntegerEnv("AWS_MCP_HTTP_REQUEST_TIMEOUT_MS", DEFAULT_MCP_HTTP_REQUEST_TIMEOUT_MS);
        const maxSafeBlockWaitMs = Math.max(1, httpTimeoutMs - POLL_MESSAGE_HTTP_TIMEOUT_BUFFER_MS);
        if (blockWaitMs >= httpTimeoutMs) {
            logger.warn(`[McpServer] AWS_POLL_MESSAGE_BLOCK_WAIT_MS=${blockWaitMs}ms 不应大于等于 AWS_MCP_HTTP_REQUEST_TIMEOUT_MS=${httpTimeoutMs}ms，已夹紧为 ${maxSafeBlockWaitMs}ms`);
            return maxSafeBlockWaitMs;
        }
        return blockWaitMs;
    }
    resolvePollMessageEmptyRetryDelayMs() {
        return this.parsePositiveIntegerEnv("AWS_POLL_MESSAGE_EMPTY_RETRY_DELAY_MS", DEFAULT_POLL_MESSAGE_EMPTY_RETRY_DELAY_MS);
    }
    resolvePollMessageErrorRetryDelayMs() {
        return this.parsePositiveIntegerEnv("AWS_POLL_MESSAGE_ERROR_RETRY_DELAY_MS", DEFAULT_POLL_MESSAGE_ERROR_RETRY_DELAY_MS);
    }
    /**
     * 解析正整数环境变量。
     * 主流程：读取环境变量 -> 转成整数 -> 非法值使用默认值。
     */
    parsePositiveIntegerEnv(name, defaultValue) {
        const raw = process.env[name];
        if (!raw || !raw.trim()) {
            return defaultValue;
        }
        const parsed = Number.parseInt(raw, 10);
        if (!Number.isFinite(parsed) || parsed <= 0) {
            logger.warn(`[McpServer] ${name} 无效，使用默认值 ${defaultValue}ms`);
            return defaultValue;
        }
        return parsed;
    }
    sleep(delayMs) {
        if (delayMs <= 0) {
            return Promise.resolve();
        }
        return new Promise((resolve) => setTimeout(resolve, delayMs));
    }
    /**
     * 构建本地记忆整理提醒。
     * 主流程：读取容量统计 -> 找出超过软限制的 listable 类型 -> 注入一条非持久化系统私信提醒 Agent 整理。
     */
    async buildMemoryCleanupNotification() {
        try {
            const stats = await this.memoryStore.getStats();
            const exceededTypes = Object.entries(stats.by_type).filter(([, typeStats]) => typeStats.listable && typeStats.exceeded);
            const exceededDomains = Object.entries(stats.by_type).flatMap(([memoryType, typeStats]) => typeStats.listable
                ? Object.entries(typeStats.by_domain)
                    .filter(([, domainStats]) => domainStats.exceeded)
                    .map(([domain, domainStats]) => ({
                    memoryType,
                    domain,
                    domainStats,
                }))
                : []);
            if (exceededTypes.length === 0 && exceededDomains.length === 0) {
                return null;
            }
            const typeDetails = exceededTypes.map(([memoryType, typeStats]) => `${memoryType} 当前 ${typeStats.domainCount} 个 URI domain 类型，建议上限 ${typeStats.limit} 个，硬上限 ${typeStats.hardLimit} 个`);
            const domainDetails = exceededDomains.map(({ memoryType, domain, domainStats }) => `${memoryType}/${domain} 类型下当前 ${domainStats.count} 条 memory，建议上限 ${domainStats.limit} 条，硬上限 ${domainStats.hardLimit} 条`);
            const cleanupActions = [
                "请调用 get_memory_stats 查看容量详情",
                "调用 list_memories 按类型查看超限记忆",
                "删除不再需要的 task_list",
                "删除或 archive_recently_memory 归档 recently_memory 为长期 memory",
            ].join("；");
            return {
                msgId: `memory-cleanup-${Date.now()}`,
                senderId: "MCP-System",
                senderName: "系统",
                receiverId: this.getCurrentAgentId() || undefined,
                content: `本地 memory 已超过建议容量，需要整理。${[...typeDetails, ...domainDetails].join("；")}。${cleanupActions}。`,
                requireReply: false,
                prompt: "这是一条本地 memory 容量整理提醒，自动生成，无需持久化。请优先整理已超过建议上限的短期/近期 memory 类型，或具体类型下的 memory 条目。",
                timestamp: new Date().toISOString(),
            };
        }
        catch (error) {
            logger.warn("[McpServer] 构建本地 memory 整理提醒失败:", error);
            return null;
        }
    }
    async handleGetMessage() {
        await this.hydrateUnreadMessagesIfNeeded();
        const messages = this.messageBuffer.get();
        const memoryNotification = await this.buildMemoryCleanupNotification();
        if (memoryNotification) {
            messages.directMessages.unshift(memoryNotification);
        }
        return {
            directMessages: messages.directMessages,
            groupMessages: messages.groupMessages,
            fromBuffer: this.messageBuffer.size() > 0 || !!memoryNotification,
        };
    }
    /**
     * 在本地缓冲区为空时，从服务端补拉离线期间积累的未读消息。
     * 这样 Agent 重启或重连后，poll_message/get_message 仍能取到持久化未读消息。
     */
    async hydrateUnreadMessagesIfNeeded(options = {}) {
        if (this.messageBuffer.size() > 0) {
            return true;
        }
        return await this.hydrateUnreadMessagesFromServer(options);
    }
    /**
     * 从服务端补拉未读消息并写入本地缓冲。
     * 主流程：按调用方指定的阻塞/流程线任务参数请求服务端 -> 过滤本地不可投递消息 -> 追加到当前消息缓存。
     */
    async hydrateUnreadMessagesFromServer(options = {}) {
        try {
            const unreadMessages = await this.agentClient.fetchUnreadMessages({
                blockIfEmpty: options.blockIfEmpty ?? false,
                blockTimeoutMs: options.blockTimeoutMs,
                includePipelineTasks: options.includePipelineTasks,
            });
            if (unreadMessages.directMessages.length === 0 &&
                unreadMessages.groupMessages.length === 0) {
                return true;
            }
            const filteredDirectMessages = unreadMessages.directMessages.filter((message) => this.shouldBufferIncomingMessage(message));
            const filteredGroupMessages = unreadMessages.groupMessages.filter((message) => this.shouldBufferIncomingMessage(message));
            filteredDirectMessages.forEach((message) => {
                this.messageBuffer.push(message);
            });
            filteredGroupMessages.forEach((message) => {
                this.messageBuffer.push(message);
            });
            logger.info(`[McpServer] 已补拉未读消息，私聊: ${filteredDirectMessages.length}，群聊: ${filteredGroupMessages.length}`);
            return true;
        }
        catch (error) {
            logger.error("[McpServer] 补拉未读消息失败:", error);
            return false;
        }
    }
    async handleGetDmHistory(args) {
        return await this.agentClient.getDmHistory(args.targetUserId, args.limit, args.since);
    }
    async handleGetGroupHistory(args) {
        return await this.agentClient.getGroupHistory(args.limit, args.roomId, args.since);
    }
    async handleSubmitTaskResult(args) {
        if (!args.nodeId || typeof args.nodeId !== "string") {
            throw new Error("nodeId is required");
        }
        if (!args.outputPayload || typeof args.outputPayload !== "string") {
            throw new Error("outputPayload is required");
        }
        return await this.agentClient.submitTaskResult(args.nodeId, args.outputPayload);
    }
    async handleRecordTaskChange(args) {
        const nodeId = this.getRequiredString(args, "nodeId");
        const operation = this.getRequiredString(args, "operation");
        const targetType = this.getRequiredString(args, "targetType");
        const path = this.getRequiredString(args, "path");
        const input = {
            taskInstanceId: this.getOptionalString(args, "taskInstanceId"),
            nodeId,
            operation,
            targetType,
            path,
            summary: this.getOptionalString(args, "summary"),
            beforeHash: this.getOptionalString(args, "beforeHash"),
            afterHash: this.getOptionalString(args, "afterHash"),
            metadata: this.getOptionalString(args, "metadata"),
        };
        return await this.agentClient.recordTaskChange(input);
    }
    async handleStartTaskRollback(args) {
        const input = {
            rollbackTaskId: this.getRequiredString(args, "rollbackTaskId"),
        };
        return await this.agentClient.startTaskRollback(input);
    }
    async handleFinishTaskRollback(args) {
        const input = {
            rollbackTaskId: this.getRequiredString(args, "rollbackTaskId"),
            resultMessage: this.getOptionalString(args, "resultMessage"),
        };
        return await this.agentClient.finishTaskRollback(input);
    }
    async handleRejectTask(args) {
        if (!args.nodeId || typeof args.nodeId !== "string") {
            throw new Error("nodeId is required");
        }
        if (!args.reason || typeof args.reason !== "string") {
            throw new Error("reason is required");
        }
        return await this.agentClient.rejectTask(args.nodeId, args.reason);
    }
    async handleTerminateTask(args) {
        if (!args.taskInstanceId || typeof args.taskInstanceId !== "string") {
            throw new Error("taskInstanceId is required");
        }
        if (!args.reason || typeof args.reason !== "string") {
            throw new Error("reason is required");
        }
        return await this.agentClient.terminateTask(args.taskInstanceId, args.reason);
    }
    /**
     * 处理接收到的消息（WebSocket 推送）
     */
    async handleIncomingMessage(message) {
        if (!this.shouldBufferIncomingMessage(message)) {
            return undefined;
        }
        logger.info(`[McpServer] 收到消息: ${message.content?.substring(0, 50) || "(无内容)"}`);
        this.messageBuffer.push(message);
        return undefined;
    }
    /**
     * 判断消息是否应该进入本地缓冲区。
     * 主流程：过滤结构异常消息 -> 过滤当前 Agent 自发消息 -> 过滤持久化流程线唤醒私信。
     */
    shouldBufferIncomingMessage(message) {
        if (!message || typeof message !== "object") {
            logger.warn("[McpServer] 忽略结构异常的消息，避免缓冲区污染");
            return false;
        }
        if (this.isSelfSentMessage(message)) {
            logger.info("[McpServer] 忽略当前 Agent 自己发送的消息，避免 poll_message/get_message 回环");
            return false;
        }
        if (!this.isGroupMessage(message)) {
            if (this.isPipelineTaskAssignedNotification(message)) {
                logger.info("[McpServer] 忽略持久化 pipeline_task_assigned 私信，仅作为 poll_message 唤醒信号处理");
                return false;
            }
            return true;
        }
        return true;
    }
    /**
     * 判断是否为群消息。
     * 通过 msgId 类型进行收窄，便于后续安全执行群消息专属过滤逻辑。
     */
    isGroupMessage(message) {
        return !!message && typeof message === "object" && typeof message.msgId === "number";
    }
    /**
     * 判断是否为持久化流程线任务待领取私信。
     * 主流程：同时检查 content 与 prompt，只要包含 pipeline_task_assigned 就不进入本地缓冲，避免未抢占成功 Agent 收到系统任务提醒。
     */
    isPipelineTaskAssignedNotification(message) {
        const content = typeof message.content === "string" ? message.content : "";
        const prompt = typeof message.prompt === "string" ? message.prompt : "";
        return (content.includes("pipeline_task_assigned") ||
            prompt.includes("pipeline_task_assigned"));
    }
    /**
     * 判断消息是否由当前 Agent 自己发送。
     * 主流程：读取当前 Agent 状态 -> 比较 senderId -> 返回过滤结果。
     */
    isSelfSentMessage(message) {
        if (!message || typeof message !== "object") {
            return false;
        }
        const currentAgentId = this.getCurrentAgentId();
        return (!!currentAgentId &&
            typeof message.senderId === "string" &&
            message.senderId === currentAgentId);
    }
    /**
     * 安全读取当前 Agent ID。
     * 测试替身或异常场景下如果 agentClient 未提供 getState，则返回 null，避免影响消息主流程。
     */
    getCurrentAgentId() {
        const maybeAgentClient = this.agentClient;
        if (typeof maybeAgentClient.getState !== "function") {
            return null;
        }
        return maybeAgentClient.getState().agentId ?? null;
    }
    // ============ 生命周期 ============
    async start() {
        const transport = new StdioServerTransport();
        await this.server.connect(transport);
        await this.agentClient.initialize();
        logger.info("[McpServer] MCP Server 已启动，等待连接...");
        logger.info(`[McpServer] 可用工具: ${MCP_TOOLS.map((t) => t.name).join(", ")}`);
        logger.info(`[McpServer] 工作目录: ${process.env.AWS_WORKSPACE_PATH || process.cwd()}`);
        await this.autoRegister();
    }
    async autoRegister() {
        const agentConfig = this.agentClient.getAgentConfig();
        logger.info(`[McpServer] 角色: "${agentConfig.roleName}"`);
        logger.info(`[McpServer] AgentID: "${agentConfig.agentId || "(自动分配)"}"`);
        logger.info("[McpServer] 正在请求调度中心注册...");
        let retryCount = 0;
        while (true) {
            try {
                const result = await this.agentClient.register();
                logger.info(`[McpServer] 注册成功: ${result.displayName} (${result.agentId})`);
                logger.info(`[McpServer] 状态: ${result.status}`);
                // 注册成功后自动启动消息监听
                this.startListeningInternal();
                logger.info("[McpServer] 消息监听已自动启动");
                // 报告 Agent 已启动并等待输入
                const statusReporter = this.agentClient.getStatusReporter();
                if (statusReporter) {
                    statusReporter.reportWaitingInput();
                }
                await this.reportCombinedMemoryStats();
                return;
            }
            catch (error) {
                const errorMessage = error instanceof Error ? error.message : String(error);
                retryCount++;
                logger.warn(`[McpServer] 注册失败，等待重试... (${retryCount}次): ${errorMessage}`);
                await this.delay(REGISTER_RETRY_INTERVAL_MS);
            }
        }
    }
    /**
     * 内部方法：启动消息监听（不返回 MCP 响应）
     */
    startListeningInternal() {
        logger.info("[McpServer] startListeningInternal 被调用");
        this.agentClient.start(this.handleIncomingMessage.bind(this), {
            pollMode: false,
            profileHandler: (profile) => {
                // 收到 Profile 信息后，存储到消息缓冲区
                logger.info(`[McpServer] profileHandler 被调用，displayName: ${profile.displayName}`);
                this.messageBuffer.setProfileMessage(profile);
            },
        });
    }
    delay(ms) {
        return new Promise((resolve) => setTimeout(resolve, ms));
    }
}
//# sourceMappingURL=mcp-server.js.map