Skip to content

Commit 3f5f48c

Browse files
committed
Preserve extension tools across harness mode switches
1 parent 58218b8 commit 3f5f48c

2 files changed

Lines changed: 36 additions & 2 deletions

File tree

packages/agent/src/agent.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -783,9 +783,21 @@ export class CuaAgentHarness<
783783
*/
784784
async setMode(mode: CuaMode): Promise<void> {
785785
if (mode === this.runtime.mode) return;
786-
const previousNames = new Set(this.getTools().map((tool) => tool.name));
786+
const previousTools = this.getTools();
787+
const previousNames = new Set(previousTools.map((tool) => tool.name));
788+
const previousRuntimeNames = new Set(this.runtime.tools().map((tool) => tool.name));
787789
this.runtime.setMode(mode);
788-
const tools = this.runtime.tools();
790+
const runtimeTools = this.runtime.tools();
791+
const runtimeNames = new Set(runtimeTools.map((tool) => tool.name));
792+
// Keep externally registered tools (extensions/add_tool/manual setTools)
793+
// while swapping only CUA runtime-owned tools for the new mode.
794+
const tools = [
795+
...runtimeTools,
796+
...previousTools.filter(
797+
(tool) =>
798+
!previousRuntimeNames.has(tool.name) && !runtimeNames.has(tool.name),
799+
),
800+
];
789801
// Tools that survive the mode switch (extraTools, shared names) keep
790802
// their requested activation state; names new in this mode activate.
791803
const requested = this.requestedActiveToolNames;

packages/agent/test/agent.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1820,6 +1820,28 @@ describe("CuaAgentHarness", () => {
18201820
expect(names).toContain("browser_snapshot");
18211821
});
18221822

1823+
it("setMode keeps non-CUA tools registered on the harness", async () => {
1824+
const harness = new CuaAgentHarness({
1825+
...(await createHarnessServices()),
1826+
browser,
1827+
client,
1828+
model: "anthropic:claude-opus-4-5",
1829+
});
1830+
const extensionTool = createCustomTool("extension_custom");
1831+
const mergedTools = [...harness.getTools(), extensionTool];
1832+
await harness.setTools(
1833+
mergedTools,
1834+
mergedTools.map((tool) => tool.name),
1835+
);
1836+
1837+
await harness.setMode("browser");
1838+
1839+
const names = harness.getTools().map((tool) => tool.name);
1840+
const active = harness.getActiveTools().map((tool) => tool.name);
1841+
expect(names).toContain("extension_custom");
1842+
expect(active).toContain("extension_custom");
1843+
});
1844+
18231845
it("setMode keeps the requested activation state of surviving tools", async () => {
18241846
const harness = new CuaAgentHarness({
18251847
...(await createHarnessServices()),

0 commit comments

Comments
 (0)