Spracherkennung für: .ts vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
import { afterEach, describe, expect, it, vi } from "vitest";
import type { AnyAgentTool } from "../agents/tools/common.js";
import {
initializeGlobalHookRunner,
resetGlobalHookRunner,
} from "../plugins/hook-runner-global.js";
import { createMockPluginRegistry } from "../plugins/hooks.test-helpers.js";
import { createPluginToolsMcpHandlers } from "./plugin-tools-handlers.js";
const callGatewayTool = vi.hoisted(() => vi.fn());
vi.mock("../agents/tools/gateway.js", () => ({
callGatewayTool,
}));
afterEach(() => {
vi.restoreAllMocks();
callGatewayTool.mockReset();
resetGlobalHookRunner();
});
describe("plugin tools MCP server", () => {
it("lists registered plugin tools and serializes non-array tool content", async () => {
const execute = vi.fn().mockResolvedValue({
content: "Stored.",
});
const tool = {
name: "memory_recall",
description: "Recall stored memory",
parameters: {
type: "object",
properties: {
query: { type: "string" },
},
required: ["query"],
},
execute,
} as unknown as AnyAgentTool;
const handlers = createPluginToolsMcpHandlers([tool]);
const listed = await handlers.listTools();
expect(listed.tools).toEqual([
expect.objectContaining({
name: "memory_recall",
description: "Recall stored memory",
inputSchema: expect.objectContaining({
type: "object",
required: ["query"],
}),
}),
]);
const result = await handlers.callTool({
name: "memory_recall",
arguments: { query: "remember this" },
});
expect(execute).toHaveBeenCalledWith(
expect.stringMatching(/^mcp-\d+$/),
{
query: "remember this",
},
undefined,
undefined,
);
expect(result.content).toEqual([{ type: "text", text: "Stored." }]);
});
it("returns MCP errors for unknown tools and thrown tool errors", async () => {
const failingTool = {
name: "memory_forget",
description: "Forget memory",
parameters: { type: "object", properties: {} },
execute: vi.fn().mockRejectedValue(new Error("boom")),
} as unknown as AnyAgentTool;
const handlers = createPluginToolsMcpHandlers([failingTool]);
const unknown = await handlers.callTool({
name: "missing_tool",
arguments: {},
});
expect(unknown.isError).toBe(true);
expect(unknown.content).toEqual([{ type: "text", text: "Unknown tool: missing_tool" }]);
const failed = await handlers.callTool({
name: "memory_forget",
arguments: {},
});
expect(failed.isError).toBe(true);
expect(failed.content).toEqual([{ type: "text", text: "Tool error: boom" }]);
});
it("blocks tool execution when before_tool_call requires approval on the MCP bridge", async () => {
let hookCalls = 0;
const execute = vi.fn().mockResolvedValue({
content: "Stored.",
});
initializeGlobalHookRunner(
createMockPluginRegistry([
{
hookName: "before_tool_call",
handler: async () => {
hookCalls += 1;
return {
requireApproval: {
pluginId: "test-plugin",
title: "Approval required",
description: "Approval required",
},
};
},
},
]),
);
callGatewayTool.mockRejectedValueOnce(new Error("gateway unavailable"));
const tool = {
name: "memory_store",
description: "Store memory",
parameters: { type: "object", properties: {} },
execute,
} as unknown as AnyAgentTool;
const handlers = createPluginToolsMcpHandlers([tool]);
const result = await handlers.callTool({
name: "memory_store",
arguments: { text: "remember this" },
});
expect(hookCalls).toBe(1);
expect(execute).not.toHaveBeenCalled();
expect(result.isError).toBe(true);
expect(result.content).toEqual([
{ type: "text", text: "Tool error: Plugin approval required (gateway unavailable)" },
]);
});
});
¤ Dauer der Verarbeitung: 0.17 Sekunden
(vorverarbeitet am 2026-04-27)
¤
*© Formatika GbR, Deutschland
|
|