Skip to content

Commit d88ebad

Browse files
Merge pull request #1410 from corbitsdev/cl-10536-toolset-digest
perf(agent): memoize toolSetDigest per tool set
2 parents 39f7736 + 6a3c8ab commit d88ebad

2 files changed

Lines changed: 50 additions & 1 deletion

File tree

‎src/agent/director.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ class ChatDirectorImpl extends DefaultDirector {
475475
private readonly askOperatorCalls = new Set<string>();
476476
private readonly _systemPrompt: string;
477477
private _toolDefinitions: ToolDefinition[];
478+
private _toolSetDigest: string | undefined;
478479
private inactivityTimeoutMs: number | undefined;
479480
private totalTimeoutMs: number | undefined;
480481
// Host-owned live object, attached via setWorkflowCoordinator — never a
@@ -699,9 +700,10 @@ class ChatDirectorImpl extends DefaultDirector {
699700
}
700701

701702
updateToolDefinitions(toolDefinitions: ToolDefinition[]): void {
702-
const before = toolSetDigest(this._toolDefinitions);
703+
const before = this._toolSetDigest ?? toolSetDigest(this._toolDefinitions);
703704
const after = toolSetDigest(toolDefinitions);
704705
this._toolDefinitions = toolDefinitions;
706+
this._toolSetDigest = after;
705707
if (before === after) return;
706708
logger.debug`tool-set-changed count=${String(this._toolDefinitions.length)} before=${before} after=${after}`;
707709
}

‎src/agent/tool-set-digest.test.ts‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { describe, expect, test } from "bun:test";
2+
import { withMockedModule } from "../../testkit/mock-module.js";
3+
4+
let hashCalls = 0;
5+
await withMockedModule<typeof import("node:crypto")>(
6+
import.meta.resolve("node:crypto"),
7+
(real) => ({
8+
...real,
9+
createHash: (algorithm: string) => {
10+
hashCalls += 1;
11+
return real.createHash(algorithm);
12+
},
13+
}),
14+
);
15+
16+
const { createChatDirector } = await import("./director.js");
17+
18+
const base = {
19+
name: "read_file",
20+
description: "read a file",
21+
inputSchema: { type: "object" },
22+
};
23+
24+
describe("toolSetDigest memoization", () => {
25+
test("hashes each installed tool set once per director", () => {
26+
const director = createChatDirector("system", [], {});
27+
const tools = [{ ...base }];
28+
const changed = [{ ...base, description: "changed" }];
29+
30+
director.updateToolDefinitions(tools);
31+
hashCalls = 0;
32+
director.updateToolDefinitions(changed);
33+
expect(hashCalls).toBe(1);
34+
});
35+
36+
test("recomputes when a new tool set arrives", () => {
37+
const director = createChatDirector("system", [], {});
38+
const tools = [{ ...base }];
39+
const changed = [{ ...base, description: "changed" }];
40+
41+
director.updateToolDefinitions(tools);
42+
director.updateToolDefinitions(changed);
43+
hashCalls = 0;
44+
director.updateToolDefinitions([{ ...base }]);
45+
expect(hashCalls).toBe(1);
46+
});
47+
});

0 commit comments

Comments
 (0)