From d368997ca3bdf9cc3e99b79cf73c894e278a6d2b Mon Sep 17 00:00:00 2001 From: Gaurav <39389231+gsquared94@users.noreply.github.com> Date: Fri, 13 Mar 2026 10:49:33 -0700 Subject: [PATCH] test: add Object.create context regression test and tool confirmation integration test (#22356) --- .../browser-agent.confirmation.responses | 1 + integration-tests/browser-agent.test.ts | 29 +++++++++++++++ .../core/src/agents/subagent-tool-wrapper.ts | 8 +--- packages/core/src/scheduler/policy.test.ts | 37 +++++++++++++++++++ 4 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 integration-tests/browser-agent.confirmation.responses diff --git a/integration-tests/browser-agent.confirmation.responses b/integration-tests/browser-agent.confirmation.responses new file mode 100644 index 0000000000..4f645c6531 --- /dev/null +++ b/integration-tests/browser-agent.confirmation.responses @@ -0,0 +1 @@ +{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"functionCall":{"name":"write_file","args":{"file_path":"test.txt","content":"hello"}}},{"text":"I've successfully written \"hello\" to test.txt. The file has been created with the specified content."}],"role":"model"},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":100,"candidatesTokenCount":50,"totalTokenCount":150}}]} diff --git a/integration-tests/browser-agent.test.ts b/integration-tests/browser-agent.test.ts index 0fdb3e717b..f9f07d4c9e 100644 --- a/integration-tests/browser-agent.test.ts +++ b/integration-tests/browser-agent.test.ts @@ -203,4 +203,33 @@ describe.skipIf(!chromeAvailable)('browser-agent', () => { // Should successfully complete all operations assertModelHasOutput(result); }); + + it('should handle tool confirmation for write_file without crashing', async () => { + rig.setup('tool-confirmation', { + fakeResponsesPath: join( + __dirname, + 'browser-agent.confirmation.responses', + ), + settings: { + agents: { + browser_agent: { + headless: true, + sessionMode: 'isolated', + }, + }, + }, + }); + + const run = await rig.runInteractive({ approvalMode: 'default' }); + + await run.type('Write hello to test.txt'); + await run.type('\r'); + + await run.expectText('Allow', 15000); + + await run.type('y'); + await run.type('\r'); + + await run.expectText('successfully written', 15000); + }); }); diff --git a/packages/core/src/agents/subagent-tool-wrapper.ts b/packages/core/src/agents/subagent-tool-wrapper.ts index ff64d4a03f..cf6d1e7112 100644 --- a/packages/core/src/agents/subagent-tool-wrapper.ts +++ b/packages/core/src/agents/subagent-tool-wrapper.ts @@ -10,7 +10,7 @@ import { type ToolInvocation, type ToolResult, } from '../tools/tools.js'; -import type { Config } from '../config/config.js'; + import { type AgentLoopContext } from '../config/agent-loop-context.js'; import type { AgentDefinition, AgentInputs } from './types.js'; import { LocalSubagentInvocation } from './local-invocation.js'; @@ -54,10 +54,6 @@ export class SubagentToolWrapper extends BaseDeclarativeTool< ); } - private get config(): Config { - return this.context.config; - } - /** * Creates an invocation instance for executing the subagent. * @@ -89,7 +85,7 @@ export class SubagentToolWrapper extends BaseDeclarativeTool< // Special handling for browser agent - needs async MCP setup if (definition.name === BROWSER_AGENT_NAME) { return new BrowserAgentInvocation( - this.config, + this.context, params, effectiveMessageBus, _toolName, diff --git a/packages/core/src/scheduler/policy.test.ts b/packages/core/src/scheduler/policy.test.ts index 750b14c2ed..e802a4b220 100644 --- a/packages/core/src/scheduler/policy.test.ts +++ b/packages/core/src/scheduler/policy.test.ts @@ -676,6 +676,43 @@ describe('policy.ts', () => { }), ); }); + + it('should work when context is created via Object.create (prototype chain)', async () => { + const mockConfig = { + setApprovalMode: vi.fn(), + } as unknown as Mocked; + const mockMessageBus = { + publish: vi.fn(), + } as unknown as Mocked; + + const baseContext = { + config: mockConfig, + messageBus: mockMessageBus, + }; + const protoContext: AgentLoopContext = Object.create(baseContext); + + expect(Object.keys(protoContext)).toHaveLength(0); + expect(protoContext.config).toBe(mockConfig); + expect(protoContext.messageBus).toBe(mockMessageBus); + + const tool = { name: 'test-tool' } as AnyDeclarativeTool; + + await updatePolicy( + tool, + ToolConfirmationOutcome.ProceedAlways, + undefined, + protoContext, + mockMessageBus, + ); + + expect(mockMessageBus.publish).toHaveBeenCalledWith( + expect.objectContaining({ + type: MessageBusType.UPDATE_POLICY, + toolName: 'test-tool', + persist: false, + }), + ); + }); }); describe('getPolicyDenialError', () => {