@unified-llm/core
Version:
Unified LLM interface (in-memory).
115 lines • 4.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NOOP_LOGGER = void 0;
exports.executeToolCalls = executeToolCalls;
const mcp_utils_js_1 = require("../mcp-utils.js");
const logging_js_1 = require("../logging.js");
const timing_js_1 = require("../timing.js");
exports.NOOP_LOGGER = {
debug: () => { },
info: () => { },
warn: () => { },
error: () => { },
child: () => exports.NOOP_LOGGER,
};
function safeJsonParse(value, fallback) {
if (!value)
return fallback;
try {
return JSON.parse(value);
}
catch (_a) {
return fallback;
}
}
/**
* tool call を実行して結果を文字列として返す(プロバイダー非依存)。
*
* - localToolHandlers が該当すれば優先
* - それ以外は MCP に委譲
* - 例外は握りつぶして `{ ok:false, error }` を output に詰める(LLMループを止めない)
* - sanitizeToolCallResult を適用して安全化
*/
async function executeToolCalls(toolCalls, toolNameToClient, localToolHandlers, options) {
var _a, _b;
const logger = (_a = options === null || options === void 0 ? void 0 : options.logger) !== null && _a !== void 0 ? _a : exports.NOOP_LOGGER;
const clock = (_b = options === null || options === void 0 ? void 0 : options.clock) !== null && _b !== void 0 ? _b : (0, timing_js_1.createDefaultClock)();
const tasks = toolCalls.map(async (call) => {
var _a;
if (!call.callId) {
throw new Error(`Missing callId for tool call: ${call.name}`);
}
const args = typeof call.arguments === "string"
? safeJsonParse(call.arguments, {})
: (_a = call.arguments) !== null && _a !== void 0 ? _a : {};
try {
const localHandler = localToolHandlers === null || localToolHandlers === void 0 ? void 0 : localToolHandlers.get(call.name);
if (localHandler) {
logger.info("tool.call.request", {
tool: call.name,
call_id: call.callId,
kind: "local",
args: JSON.stringify(args),
});
const result = await (0, logging_js_1.logTimed)(logger, clock, "tool.call.completed", {
tool: call.name,
call_id: call.callId,
kind: "local",
args_keys_count: Object.keys(args).length,
}, async () => localHandler(args), "info");
const outputText = typeof result === "string"
? result
: JSON.stringify(result !== null && result !== void 0 ? result : { ok: true });
logger.info("tool.call.result", {
tool: call.name,
call_id: call.callId,
kind: "local",
result: outputText,
});
return { name: call.name, callId: call.callId, output: outputText };
}
const mcpClient = toolNameToClient.get(call.name);
if (!mcpClient) {
throw new Error(`No MCP client registered for tool: ${call.name}`);
}
logger.info("tool.call.request", {
tool: call.name,
call_id: call.callId,
kind: "mcp",
args: JSON.stringify(args),
});
const result = await (0, logging_js_1.logTimed)(logger, clock, "tool.call.completed", {
tool: call.name,
call_id: call.callId,
kind: "mcp",
args_keys_count: Object.keys(args).length,
}, async () => mcpClient.callTool({ name: call.name, arguments: args }), "info");
const { sanitizedResult } = (0, mcp_utils_js_1.sanitizeToolCallResult)(result);
logger.info("tool.call.result", {
tool: call.name,
call_id: call.callId,
kind: "mcp",
result: JSON.stringify(sanitizedResult),
});
return {
name: call.name,
callId: call.callId,
output: JSON.stringify(sanitizedResult),
};
}
catch (err) {
logger.error("tool.call.failed", {
tool: call.name,
call_id: call.callId,
error: (0, logging_js_1.toModelSafeError)(err),
});
return {
name: call.name,
callId: call.callId,
output: JSON.stringify({ ok: false, error: (0, logging_js_1.toModelSafeError)(err) }),
};
}
});
return Promise.all(tasks);
}
//# sourceMappingURL=execute-tool-calls.js.map