"use strict";Object.defineProperty(exports, "__esModule", { value: true });exports.formatUploadResultForUser = exports.formatUploadResultAsMarkdown = exports.dispatchToolResultToMessageBlocks = exports.buildToolResultSessionContentBlocks = void 0; var _adpUploadTool = require("./adp-upload-tool.js"); /** * Tool Result Message Blocks * * 用于将工具结果转换为消息块,发送给用户 * 参考 kimi-claw 的 tool-result-message-blocks.js 实现 */ // ==================== 工具函数 ==================== const isRecord = (v) => !!v && typeof v === "object" && !Array.isArray(v); const asTrimmedNonEmptyString = (v) => { if (typeof v !== "string") return undefined; const trimmed = v.trim(); return trimmed || undefined; }; // ==================== 消息块类型 ==================== // ==================== 工具结果处理策略 ==================== /** * ADP 上传工具结果处理策略 */ const ADP_UPLOAD_TOOL_RESULT_BLOCKS_STRATEGY = { canHandle: (toolName, result) => { return ( toolName === _adpUploadTool.ADP_UPLOAD_TOOL_NAME && isRecord(result) && result.ok === true); }, toMessageBlocks: (toolName, result) => { if (!isRecord(result)) return []; const files = result.files; if (!Array.isArray(files)) return []; const blocks = []; for (const file of files) { if (!isRecord(file)) continue; const uri = asTrimmedNonEmptyString(file.uri); if (!uri) continue; const name = asTrimmedNonEmptyString(file.name); const mimeType = asTrimmedNonEmptyString(file.mimeType); const downloadUrl = asTrimmedNonEmptyString(file.downloadUrl); const resourceLink = { type: "resource_link", uri, ...(name ? { name } : {}), ...(mimeType ? { mimeType } : {}), ...(downloadUrl ? { downloadUrl } : {}) }; blocks.push({ type: "content", content: resourceLink }); } return blocks; } }; // 所有支持的工具结果处理策略 const TOOL_RESULT_STRATEGIES = [ ADP_UPLOAD_TOOL_RESULT_BLOCKS_STRATEGY]; // ==================== 公共接口 ==================== /** * 检查工具结果是否成功 */ const isSuccessfulToolResult = (result) => isRecord(result) && result.ok === true; /** * 将工具结果分发到对应的消息块处理器 */ const dispatchToolResultToMessageBlocks = ( toolName, result, strategies = TOOL_RESULT_STRATEGIES) => { if (!isSuccessfulToolResult(result)) return []; const blocks = []; for (const strategy of strategies) { if (strategy.canHandle(toolName, result)) { blocks.push(...strategy.toMessageBlocks(toolName, result)); } } return blocks; }; /** * 从内容数组中解析可能的上传结果 */exports.dispatchToolResultToMessageBlocks = dispatchToolResultToMessageBlocks; const maybeUploadResultFromContent = ( content) => { if (!Array.isArray(content)) return undefined; const files = []; for (const item of content) { if (!isRecord(item)) continue; const uri = asTrimmedNonEmptyString(item.uri); if (!uri) continue; const itemType = asTrimmedNonEmptyString(item.type); if (itemType && itemType !== "resource_link") continue; const fileInfo = { uri, name: asTrimmedNonEmptyString(item.name) || "", mimeType: asTrimmedNonEmptyString(item.mimeType) || "" }; const downloadUrl = asTrimmedNonEmptyString(item.downloadUrl); if (downloadUrl) { fileInfo.downloadUrl = downloadUrl; } files.push(fileInfo); } return files.length ? { ok: true, files } : undefined; }; /** * 从工具结果中提取有效负载 */ const pickToolResultPayload = ( result) => { // 尝试从不同的字段中提取结果 const resultField = result.result; if (isRecord(resultField)) return resultField; const outputField = result.output; if (isRecord(outputField)) return outputField; const detailsField = result.details; if (isRecord(detailsField)) return detailsField; // 尝试从 content 数组中解析 const contentField = result.content; if (isRecord(contentField)) return contentField; const maybeFromContent = maybeUploadResultFromContent(contentField); if (maybeFromContent) return maybeFromContent; return undefined; }; /** * 从工具结果构建会话内容块 * * @param toolName - 工具名称 * @param rawResult - 原始工具结果 * @returns 消息块数组 */ const buildToolResultSessionContentBlocks = ( toolName, rawResult) => { const result = isRecord(rawResult) ? rawResult : undefined; if (!result) return []; const payload = pickToolResultPayload(result); if (!payload) return []; const blocks = dispatchToolResultToMessageBlocks(toolName, payload, TOOL_RESULT_STRATEGIES); return blocks.length ? blocks : []; }; /** * 将上传结果转换为用户可读的文本消息 * * @param result - ADP 上传工具结果 * @returns 用户可读的消息 */exports.buildToolResultSessionContentBlocks = buildToolResultSessionContentBlocks; const formatUploadResultForUser = (result) => { if (!result.ok || !result.files || result.files.length === 0) { const errorMsg = result.error?.data?.reason || result.error?.message || "上传失败"; return `文件上传失败: ${errorMsg}`; } const lines = ["文件上传成功:"]; for (const file of result.files) { if (file.downloadUrl) { lines.push(`📎 ${file.name}: ${file.downloadUrl}`); } else { lines.push(`📎 ${file.name} (${file.uri})`); } } return lines.join("\n"); }; /** * 将上传结果转换为 Markdown 格式的消息 * * @param result - ADP 上传工具结果 * @returns Markdown 格式的消息 */exports.formatUploadResultForUser = formatUploadResultForUser; const formatUploadResultAsMarkdown = (result) => { if (!result.ok || !result.files || result.files.length === 0) { const errorMsg = result.error?.data?.reason || result.error?.message || "上传失败"; return `**文件上传失败**: ${errorMsg}`; } const lines = ["**文件上传成功**:"]; for (const file of result.files) { console.log(`[ADP-UPLOAD] formatUploadResultAsMarkdown - file.downloadUrl: ${file.downloadUrl}`); if (file.downloadUrl) { lines.push(`- [${file.name}](${file.downloadUrl})`); } else { lines.push(`- ${file.name} (\`${file.uri}\`)`); } } return lines.join("\n"); };exports.formatUploadResultAsMarkdown = formatUploadResultAsMarkdown; /* v9-0809aeed796a7a88 */