Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
0863377
refactor(core): introduce SubagentState enum for progress
adamfweidman May 12, 2026
435c483
refactor(core): update remaining files to use SubagentState enum
adamfweidman May 12, 2026
206e11e
refactor(cli): update UI components and tests to use SubagentState enum
adamfweidman May 12, 2026
9c026f3
refactor(cli): complete SubagentState enum migration in SubagentGroup…
adamfweidman May 12, 2026
405b02e
refactor(core,cli): fix missed enum usages in SubagentProgressDisplay…
adamfweidman May 12, 2026
dc3c799
refactor: address review comments for local protocol
adamfweidman May 7, 2026
aa1d1c6
refactor: address review follow-ups for local protocol
adamfweidman May 7, 2026
a102843
feat(core): add LocalSessionInvocation — session-based local subagent…
adamfweidman Apr 14, 2026
666d1d2
fix(core): fix imports in local-session-invocation test
adamfweidman May 7, 2026
7bf9d01
Add safe string handling for activity data properties
adamfweidman May 12, 2026
e5b39b3
fix(core): restore fallback serialization in content-utils to avoid t…
adamfweidman May 12, 2026
696bf57
Merge remote-tracking branch 'origin/main' into agent-session/local-i…
adamfweidman May 12, 2026
0b3b5ab
test(core): verify warning log in content-utils fallback test
adamfweidman May 12, 2026
34d41c3
refactor(core): use SubagentState enum in LocalSessionInvocation
adamfweidman May 12, 2026
3229726
chore(core): add TODOs about parallel tool calls and callId in local …
adamfweidman May 13, 2026
eaab123
Merge remote-tracking branch 'origin/main' into agent-session/local-i…
adamfweidman May 18, 2026
3112697
fix(core): address review comments on local session invocation
adamfweidman May 18, 2026
af3aadd
fix(core): address jacob's review comments on local-invocation (licen…
adamfweidman May 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions packages/core/src/agents/local-invocation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ describe('LocalSubagentInvocation', () => {
);
});

it('should truncate long input values', () => {
it('should not truncate long input values', () => {
const longTask = 'A'.repeat(100);
const params = { task: longTask };
const invocation = new LocalSubagentInvocation(
Expand All @@ -131,13 +131,12 @@ describe('LocalSubagentInvocation', () => {
mockMessageBus,
);
const description = invocation.getDescription();
// Default INPUT_PREVIEW_MAX_LENGTH is 50
expect(description).toBe(
`Running subagent 'MockAgent' with inputs: { task: ${'A'.repeat(50)} }`,
`Running subagent 'MockAgent' with inputs: { task: ${'A'.repeat(100)} }`,
);
});

it('should truncate the overall description if it exceeds the limit', () => {
it('should not truncate the overall description', () => {
// Create a definition and inputs that result in a very long description
const longNameDef: LocalAgentDefinition = {
...testDefinition,
Expand All @@ -154,8 +153,7 @@ describe('LocalSubagentInvocation', () => {
mockMessageBus,
);
const description = invocation.getDescription();
// Default DESCRIPTION_MAX_LENGTH is 200
expect(description.length).toBe(200);
expect(description.length).toBeGreaterThan(300);
expect(
description.startsWith(
"Running subagent 'VeryLongAgentNameThatTakesUpSpace'",
Expand Down
79 changes: 36 additions & 43 deletions packages/core/src/agents/local-invocation.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @license
* Copyright 2025 Google LLC
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/

Expand Down Expand Up @@ -35,9 +35,6 @@ import {
} from '../utils/agent-sanitization-utils.js';
import { debugLogger } from '../utils/debugLogger.js';

const INPUT_PREVIEW_MAX_LENGTH = 50;
const DESCRIPTION_MAX_LENGTH = 200;

/**
* Represents a validated, executable instance of a subagent tool.
*
Expand Down Expand Up @@ -80,14 +77,10 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
*/
getDescription(): string {
const inputSummary = Object.entries(this.params)
.map(
([key, value]) =>
`${key}: ${String(value).slice(0, INPUT_PREVIEW_MAX_LENGTH)}`,
)
.map(([key, value]) => `${key}: ${String(value)}`)
.join(', ');

const description = `Running subagent '${this.definition.name}' with inputs: { ${inputSummary} }`;
return description.slice(0, DESCRIPTION_MAX_LENGTH);
return `Running subagent '${this.definition.name}' with inputs: { ${inputSummary} }`;
}

private publishActivity(activity: SubagentActivityItem): void {
Expand Down Expand Up @@ -168,8 +161,11 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
const args = JSON.stringify(
sanitizeToolArgs(activity.data['args']),
);
const callId = activity.data['callId']
? String(activity.data['callId'])
: randomUUID();
recentActivity.push({
id: randomUUID(),
id: callId,
type: 'tool_call',
content: name,
displayName,
Expand All @@ -186,23 +182,28 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
break;
}
case 'TOOL_CALL_END': {
const name = String(activity.data['name']);
const data = activity.data['data'];
const isError = isToolActivityError(data);

for (let i = recentActivity.length - 1; i >= 0; i--) {
if (
recentActivity[i].type === 'tool_call' &&
recentActivity[i].content === name &&
recentActivity[i].status === SubagentState.RUNNING
) {
recentActivity[i].status = isError
? SubagentState.ERROR
: SubagentState.COMPLETED;
updated = true;

this.publishActivity(recentActivity[i]);
break;
const callId = activity.data['id']
? String(activity.data['id'])
: undefined;

if (callId) {
for (let i = recentActivity.length - 1; i >= 0; i--) {
if (
recentActivity[i].type === 'tool_call' &&
recentActivity[i].id === callId &&
recentActivity[i].status === SubagentState.RUNNING
) {
recentActivity[i].status = isError
? SubagentState.ERROR
: SubagentState.COMPLETED;
updated = true;

this.publishActivity(recentActivity[i]);
break;
}
}
}
break;
Expand All @@ -218,31 +219,23 @@ export class LocalSubagentInvocation extends BaseToolInvocation<
errorType === SubagentActivityErrorType.REJECTED ||
error.startsWith(SUBAGENT_REJECTED_ERROR_PREFIX);

const toolName = activity.data['name']
? String(activity.data['name'])
const callId = activity.data['callId']
? String(activity.data['callId'])
: undefined;

if (toolName && (isCancellation || isRejection)) {
for (let i = recentActivity.length - 1; i >= 0; i--) {
if (
recentActivity[i].type === 'tool_call' &&
recentActivity[i].content === toolName &&
recentActivity[i].status === SubagentState.RUNNING
) {
recentActivity[i].status = SubagentState.CANCELLED;
updated = true;
break;
}
}
} else if (toolName) {
// Mark non-rejection/non-cancellation errors as 'error'
if (callId) {
const targetStatus =
isCancellation || isRejection
? SubagentState.CANCELLED
: SubagentState.ERROR;

for (let i = recentActivity.length - 1; i >= 0; i--) {
if (
recentActivity[i].type === 'tool_call' &&
recentActivity[i].content === toolName &&
recentActivity[i].id === callId &&
recentActivity[i].status === SubagentState.RUNNING
) {
recentActivity[i].status = SubagentState.ERROR;
recentActivity[i].status = targetStatus;
updated = true;
break;
}
Expand Down
Loading
Loading