@@ -2061,6 +2061,39 @@ describe("resolvePluginTools optional tools", () => {
|
2061 | 2061 | expect(factory).toHaveBeenCalledTimes(2); |
2062 | 2062 | }); |
2063 | 2063 | |
| 2064 | +it("executes cached healthy tools when a runtime sibling is malformed", async () => { |
| 2065 | +const factory = vi.fn(() => [ |
| 2066 | +createMalformedTool("fuzz_move_angles"), |
| 2067 | +{ |
| 2068 | + ...makeTool("mockplugin_status"), |
| 2069 | +async execute() { |
| 2070 | +return { content: [{ type: "text", text: "mock-status-ok" }] }; |
| 2071 | +}, |
| 2072 | +}, |
| 2073 | +]); |
| 2074 | +setRegistry([ |
| 2075 | +{ |
| 2076 | +pluginId: "fuzzplugin", |
| 2077 | +optional: false, |
| 2078 | +source: "/tmp/fuzzplugin.js", |
| 2079 | +names: ["mockplugin_status"], |
| 2080 | + factory, |
| 2081 | +}, |
| 2082 | +]); |
| 2083 | + |
| 2084 | +const first = resolvePluginTools(createResolveToolsParams()); |
| 2085 | +const second = resolvePluginTools(createResolveToolsParams()); |
| 2086 | +const statusTool = second.find((tool) => tool.name === "mockplugin_status"); |
| 2087 | + |
| 2088 | +expectResolvedToolNames(first, ["mockplugin_status"]); |
| 2089 | +expectResolvedToolNames(second, ["mockplugin_status"]); |
| 2090 | +expect(factory).toHaveBeenCalledTimes(1); |
| 2091 | +await expect(statusTool?.execute("call", {}, undefined)).resolves.toEqual({ |
| 2092 | +content: [{ type: "text", text: "mock-status-ok" }], |
| 2093 | +}); |
| 2094 | +expect(factory).toHaveBeenCalledTimes(2); |
| 2095 | +}); |
| 2096 | + |
2064 | 2097 | it("reuses cached plugin tool descriptors across session identity changes", async () => { |
2065 | 2098 | const factory = vi.fn((rawCtx: unknown) => { |
2066 | 2099 | const ctx = rawCtx as { sessionId?: string }; |
|