test: add Object.create context regression test and tool confirmation integration test (#22356)

This commit is contained in:
Gaurav 2026-03-13 10:49:33 -07:00 committed by GitHub
parent bbd80c9393
commit d368997ca3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 69 additions and 6 deletions

View file

@ -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}}]}

View file

@ -203,4 +203,33 @@ describe.skipIf(!chromeAvailable)('browser-agent', () => {
// Should successfully complete all operations // Should successfully complete all operations
assertModelHasOutput(result); 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);
});
}); });

View file

@ -10,7 +10,7 @@ import {
type ToolInvocation, type ToolInvocation,
type ToolResult, type ToolResult,
} from '../tools/tools.js'; } from '../tools/tools.js';
import type { Config } from '../config/config.js';
import { type AgentLoopContext } from '../config/agent-loop-context.js'; import { type AgentLoopContext } from '../config/agent-loop-context.js';
import type { AgentDefinition, AgentInputs } from './types.js'; import type { AgentDefinition, AgentInputs } from './types.js';
import { LocalSubagentInvocation } from './local-invocation.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. * 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 // Special handling for browser agent - needs async MCP setup
if (definition.name === BROWSER_AGENT_NAME) { if (definition.name === BROWSER_AGENT_NAME) {
return new BrowserAgentInvocation( return new BrowserAgentInvocation(
this.config, this.context,
params, params,
effectiveMessageBus, effectiveMessageBus,
_toolName, _toolName,

View file

@ -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<Config>;
const mockMessageBus = {
publish: vi.fn(),
} as unknown as Mocked<MessageBus>;
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', () => { describe('getPolicyDenialError', () => {