openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
95 lines (94 loc) • 3.65 kB
JavaScript
import { c as isRecord } from "./record-coerce-DItp3I4t.js";
import { t as formatErrorMessage } from "./errors-Db3Ymjlb.js";
import { n as isAutomationsToolName } from "./automations-tool-name-DBMZPbPL.js";
import { Y as consumeAdjustedParamsForToolCall, l as rewrapToolWithBeforeToolCallHook, u as wrapToolWithBeforeToolCallHook } from "./agent-tools.before-tool-call-Bb7DJuFB.js";
import { t as coerceChatContentText } from "./chat-content-DNdfeXZh.js";
import { m as BEFORE_TOOL_CALL_HOOK_CONTEXT, x as isToolWrappedWithBeforeToolCallHook } from "./agent-tool-metadata-CZvIgxro.js";
import { r as isToolResultError } from "./tool-result-error-CbDLJzG-.js";
import { randomUUID } from "node:crypto";
//#region src/mcp/plugin-tools-handlers.ts
function toMcpContentBlock(block) {
if (!isRecord(block)) return {
type: "text",
text: coerceChatContentText(block)
};
if (block.type !== "image") return block;
if (typeof block.data === "string" && typeof block.mimeType === "string") return block;
const source = block.source;
if (isRecord(source) && source.type === "base64" && typeof source.data === "string" && typeof source.media_type === "string") return {
type: "image",
data: source.data,
mimeType: source.media_type
};
return {
type: "text",
text: coerceChatContentText(block)
};
}
function resolveJsonSchemaForTool(tool) {
const params = tool.parameters;
if (params && typeof params === "object" && "type" in params) return params;
return {
type: "object",
properties: {}
};
}
function resolveBeforeToolCallRunId(tool) {
const context = tool[BEFORE_TOOL_CALL_HOOK_CONTEXT];
return isRecord(context) && typeof context.runId === "string" ? context.runId : void 0;
}
function createPluginToolsMcpHandlers(tools) {
const wrappedTools = tools.map((tool) => {
if (isToolWrappedWithBeforeToolCallHook(tool)) return rewrapToolWithBeforeToolCallHook(tool, void 0, { approvalMode: "report" });
return wrapToolWithBeforeToolCallHook(tool, void 0, { approvalMode: "report" });
});
const toolMap = /* @__PURE__ */ new Map();
for (const tool of wrappedTools) toolMap.set(tool.name, {
tool,
runId: resolveBeforeToolCallRunId(tool)
});
const automationsName = wrappedTools.find((tool) => isAutomationsToolName(tool.name))?.name;
const automationsEntry = automationsName ? toolMap.get(automationsName) : void 0;
return {
listTools: async () => ({ tools: wrappedTools.map((tool) => ({
name: tool.name,
description: tool.description ?? "",
inputSchema: resolveJsonSchemaForTool(tool)
})) }),
callTool: async (params, signal) => {
const entry = toolMap.get(params.name) ?? (isAutomationsToolName(params.name) ? automationsEntry : void 0);
if (!entry) return {
content: [{
type: "text",
text: `Unknown tool: ${params.name}`
}],
isError: true
};
const toolCallId = `mcp-${randomUUID()}`;
try {
const result = await entry.tool.execute(toolCallId, params.arguments ?? {}, signal);
const isError = isToolResultError(result);
const rawContent = result && typeof result === "object" && "content" in result ? result.content : result;
return {
content: Array.isArray(rawContent) ? rawContent.map(toMcpContentBlock) : [{
type: "text",
text: coerceChatContentText(rawContent)
}],
...isError ? { isError: true } : {}
};
} catch (err) {
return {
content: [{
type: "text",
text: `Tool error: ${formatErrorMessage(err)}`
}],
isError: true
};
} finally {
consumeAdjustedParamsForToolCall(toolCallId, entry.runId);
}
}
};
}
//#endregion
export { createPluginToolsMcpHandlers as t };