Skip to content

Commit 6973b96

Browse files
authored
feat(core): add LocalSessionInvocation (#26665)
1 parent dc47aaa commit 6973b96

4 files changed

Lines changed: 1273 additions & 49 deletions

File tree

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ describe('LocalSubagentInvocation', () => {
121121
);
122122
});
123123

124-
it('should truncate long input values', () => {
124+
it('should not truncate long input values', () => {
125125
const longTask = 'A'.repeat(100);
126126
const params = { task: longTask };
127127
const invocation = new LocalSubagentInvocation(
@@ -131,13 +131,12 @@ describe('LocalSubagentInvocation', () => {
131131
mockMessageBus,
132132
);
133133
const description = invocation.getDescription();
134-
// Default INPUT_PREVIEW_MAX_LENGTH is 50
135134
expect(description).toBe(
136-
`Running subagent 'MockAgent' with inputs: { task: ${'A'.repeat(50)} }`,
135+
`Running subagent 'MockAgent' with inputs: { task: ${'A'.repeat(100)} }`,
137136
);
138137
});
139138

140-
it('should truncate the overall description if it exceeds the limit', () => {
139+
it('should not truncate the overall description', () => {
141140
// Create a definition and inputs that result in a very long description
142141
const longNameDef: LocalAgentDefinition = {
143142
...testDefinition,
@@ -154,8 +153,7 @@ describe('LocalSubagentInvocation', () => {
154153
mockMessageBus,
155154
);
156155
const description = invocation.getDescription();
157-
// Default DESCRIPTION_MAX_LENGTH is 200
158-
expect(description.length).toBe(200);
156+
expect(description.length).toBeGreaterThan(300);
159157
expect(
160158
description.startsWith(
161159
"Running subagent 'VeryLongAgentNameThatTakesUpSpace'",

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

Lines changed: 36 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/**
22
* @license
3-
* Copyright 2025 Google LLC
3+
* Copyright 2026 Google LLC
44
* SPDX-License-Identifier: Apache-2.0
55
*/
66

@@ -35,9 +35,6 @@ import {
3535
} from '../utils/agent-sanitization-utils.js';
3636
import { debugLogger } from '../utils/debugLogger.js';
3737

38-
const INPUT_PREVIEW_MAX_LENGTH = 50;
39-
const DESCRIPTION_MAX_LENGTH = 200;
40-
4138
/**
4239
* Represents a validated, executable instance of a subagent tool.
4340
*
@@ -80,14 +77,10 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
8077
*/
8178
getDescription(): string {
8279
const inputSummary = Object.entries(this.params)
83-
.map(
84-
([key, value]) =>
85-
`${key}: ${String(value).slice(0, INPUT_PREVIEW_MAX_LENGTH)}`,
86-
)
80+
.map(([key, value]) => `${key}: ${String(value)}`)
8781
.join(', ');
8882

89-
const description = `Running subagent '${this.definition.name}' with inputs: { ${inputSummary} }`;
90-
return description.slice(0, DESCRIPTION_MAX_LENGTH);
83+
return `Running subagent '${this.definition.name}' with inputs: { ${inputSummary} }`;
9184
}
9285

9386
private publishActivity(activity: SubagentActivityItem): void {
@@ -168,8 +161,11 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
168161
const args = JSON.stringify(
169162
sanitizeToolArgs(activity.data['args']),
170163
);
164+
const callId = activity.data['callId']
165+
? String(activity.data['callId'])
166+
: randomUUID();
171167
recentActivity.push({
172-
id: randomUUID(),
168+
id: callId,
173169
type: 'tool_call',
174170
content: name,
175171
displayName,
@@ -186,23 +182,28 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
186182
break;
187183
}
188184
case 'TOOL_CALL_END': {
189-
const name = String(activity.data['name']);
190185
const data = activity.data['data'];
191186
const isError = isToolActivityError(data);
192187

193-
for (let i = recentActivity.length - 1; i >= 0; i--) {
194-
if (
195-
recentActivity[i].type === 'tool_call' &&
196-
recentActivity[i].content === name &&
197-
recentActivity[i].status === SubagentState.RUNNING
198-
) {
199-
recentActivity[i].status = isError
200-
? SubagentState.ERROR
201-
: SubagentState.COMPLETED;
202-
updated = true;
203-
204-
this.publishActivity(recentActivity[i]);
205-
break;
188+
const callId = activity.data['id']
189+
? String(activity.data['id'])
190+
: undefined;
191+
192+
if (callId) {
193+
for (let i = recentActivity.length - 1; i >= 0; i--) {
194+
if (
195+
recentActivity[i].type === 'tool_call' &&
196+
recentActivity[i].id === callId &&
197+
recentActivity[i].status === SubagentState.RUNNING
198+
) {
199+
recentActivity[i].status = isError
200+
? SubagentState.ERROR
201+
: SubagentState.COMPLETED;
202+
updated = true;
203+
204+
this.publishActivity(recentActivity[i]);
205+
break;
206+
}
206207
}
207208
}
208209
break;
@@ -218,31 +219,23 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
218219
errorType === SubagentActivityErrorType.REJECTED ||
219220
error.startsWith(SUBAGENT_REJECTED_ERROR_PREFIX);
220221

221-
const toolName = activity.data['name']
222-
? String(activity.data['name'])
222+
const callId = activity.data['callId']
223+
? String(activity.data['callId'])
223224
: undefined;
224225

225-
if (toolName && (isCancellation || isRejection)) {
226-
for (let i = recentActivity.length - 1; i >= 0; i--) {
227-
if (
228-
recentActivity[i].type === 'tool_call' &&
229-
recentActivity[i].content === toolName &&
230-
recentActivity[i].status === SubagentState.RUNNING
231-
) {
232-
recentActivity[i].status = SubagentState.CANCELLED;
233-
updated = true;
234-
break;
235-
}
236-
}
237-
} else if (toolName) {
238-
// Mark non-rejection/non-cancellation errors as 'error'
226+
if (callId) {
227+
const targetStatus =
228+
isCancellation || isRejection
229+
? SubagentState.CANCELLED
230+
: SubagentState.ERROR;
231+
239232
for (let i = recentActivity.length - 1; i >= 0; i--) {
240233
if (
241234
recentActivity[i].type === 'tool_call' &&
242-
recentActivity[i].content === toolName &&
235+
recentActivity[i].id === callId &&
243236
recentActivity[i].status === SubagentState.RUNNING
244237
) {
245-
recentActivity[i].status = SubagentState.ERROR;
238+
recentActivity[i].status = targetStatus;
246239
updated = true;
247240
break;
248241
}

0 commit comments

Comments
 (0)