Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/agent/director.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ class ChatDirectorImpl extends DefaultDirector {
private readonly askOperatorCalls = new Set<string>();
private readonly _systemPrompt: string;
private _toolDefinitions: ToolDefinition[];
private _toolSetDigest: string | undefined;
private inactivityTimeoutMs: number | undefined;
private totalTimeoutMs: number | undefined;
// Host-owned live object, attached via setWorkflowCoordinator — never a
Expand Down Expand Up @@ -699,9 +700,10 @@ class ChatDirectorImpl extends DefaultDirector {
}

updateToolDefinitions(toolDefinitions: ToolDefinition[]): void {
const before = toolSetDigest(this._toolDefinitions);
const before = this._toolSetDigest ?? toolSetDigest(this._toolDefinitions);
const after = toolSetDigest(toolDefinitions);
this._toolDefinitions = toolDefinitions;
this._toolSetDigest = after;
if (before === after) return;
logger.debug`tool-set-changed count=${String(this._toolDefinitions.length)} before=${before} after=${after}`;
}
Expand Down
47 changes: 47 additions & 0 deletions src/agent/tool-set-digest.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { describe, expect, test } from "bun:test";
import { withMockedModule } from "../../testkit/mock-module.js";

let hashCalls = 0;
await withMockedModule<typeof import("node:crypto")>(
import.meta.resolve("node:crypto"),
(real) => ({
...real,
createHash: (algorithm: string) => {
hashCalls += 1;
return real.createHash(algorithm);
},
}),
);

const { createChatDirector } = await import("./director.js");

const base = {
name: "read_file",
description: "read a file",
inputSchema: { type: "object" },
};

describe("toolSetDigest memoization", () => {
test("hashes each installed tool set once per director", () => {
const director = createChatDirector("system", [], {});
const tools = [{ ...base }];
const changed = [{ ...base, description: "changed" }];

director.updateToolDefinitions(tools);
hashCalls = 0;
director.updateToolDefinitions(changed);
expect(hashCalls).toBe(1);
});

test("recomputes when a new tool set arrives", () => {
const director = createChatDirector("system", [], {});
const tools = [{ ...base }];
const changed = [{ ...base, description: "changed" }];

director.updateToolDefinitions(tools);
director.updateToolDefinitions(changed);
hashCalls = 0;
director.updateToolDefinitions([{ ...base }]);
expect(hashCalls).toBe(1);
});
});
Loading