Skip to content

Commit 577ee35

Browse files
authored
fix(core): isolate subagent thread context (google-gemini#26449)
1 parent e86b672 commit 577ee35

4 files changed

Lines changed: 18 additions & 18 deletions

File tree

packages/core/src/agents/local-executor.test.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ vi.mock('../tools/mcp-client-manager.js', () => ({
4949
}));
5050

5151
import { debugLogger } from '../utils/debugLogger.js';
52+
import { runWithToolCallContext } from '../utils/toolCallContext.js';
5253
import { LocalAgentExecutor, type ActivityCallback } from './local-executor.js';
5354
import { makeFakeConfig } from '../test-utils/config.js';
5455
import { ToolRegistry } from '../tools/tool-registry.js';
@@ -708,21 +709,19 @@ describe('LocalAgentExecutor', () => {
708709
expect(agentRegistry.getTool(MOCK_TOOL_NOT_ALLOWED.name)).toBeUndefined();
709710
});
710711

711-
it('should use parentPromptId from context to create agentId', async () => {
712-
const parentId = 'parent-id';
713-
Object.defineProperty(mockConfig, 'promptId', {
714-
get: () => parentId,
715-
configurable: true,
716-
});
717-
712+
it('should not include parentCallId in agentId even when available', async () => {
718713
const definition = createTestDefinition();
719-
const executor = await LocalAgentExecutor.create(
720-
definition,
721-
mockConfig,
722-
onActivity,
714+
const parentCallId = 'parent-call-123';
715+
716+
const executor = await runWithToolCallContext(
717+
{ callId: parentCallId, schedulerId: 'test-scheduler' },
718+
() => LocalAgentExecutor.create(definition, mockConfig, onActivity),
723719
);
724720

725-
expect(executor['agentId']).toBeDefined();
721+
expect(executor['agentId']).not.toContain(parentCallId);
722+
expect(executor['agentId']).toMatch(
723+
/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,
724+
);
726725
});
727726

728727
it('should correctly apply templates to initialMessages', async () => {

packages/core/src/agents/local-executor.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import { type AgentLoopContext } from '../config/agent-loop-context.js';
88
import { reportError } from '../utils/errorReporting.js';
9+
import { randomUUID } from 'node:crypto';
910
import { ApprovalMode } from '../policy/types.js';
1011
import { GeminiChat, StreamEventType } from '../core/geminiChat.js';
1112
import {
@@ -315,7 +316,7 @@ export class LocalAgentExecutor<TOutput extends z.ZodTypeAny> {
315316
this.parentCallId = parentCallId;
316317
this.cache = new LRUCache<string, string>(10);
317318

318-
this.agentId = Math.random().toString(36).slice(2, 8);
319+
this.agentId = randomUUID();
319320
}
320321

321322
/**

packages/sdk/src/skills.integration.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ describe('GeminiCliAgent Skills Integration', () => {
5555

5656
// Expect pirate speak
5757
expect(responseText.toLowerCase()).toContain('arrr');
58-
}, 60000);
58+
}, 120000);
5959

6060
it('loads and activates a skill from a root', async () => {
6161
const goldenFile = getGoldenPath('skill-root-success');
@@ -88,5 +88,5 @@ describe('GeminiCliAgent Skills Integration', () => {
8888

8989
// Expect confirmation or pirate speak
9090
expect(responseText.toLowerCase()).toContain('arrr');
91-
}, 60000);
91+
}, 120000);
9292
});

packages/sdk/src/tool.integration.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ describe('GeminiCliAgent Tool Integration', () => {
5757
.join('');
5858

5959
expect(responseText).toContain('8');
60-
});
60+
}, 20000);
6161

6262
it('handles ModelVisibleError correctly', async () => {
6363
const goldenFile = getGoldenPath('tool-error-recovery');
@@ -103,7 +103,7 @@ describe('GeminiCliAgent Tool Integration', () => {
103103

104104
// The model should see the error "Tool failed visibly" and report it back.
105105
expect(responseText).toContain('Tool failed visibly');
106-
});
106+
}, 20000);
107107

108108
it('handles sendErrorsToModel: true correctly', async () => {
109109
const goldenFile = getGoldenPath('tool-catchall-error');
@@ -145,5 +145,5 @@ describe('GeminiCliAgent Tool Integration', () => {
145145

146146
// The model should report the caught standard error.
147147
expect(responseText.toLowerCase()).toContain('error');
148-
});
148+
}, 20000);
149149
});

0 commit comments

Comments
 (0)