diff --git a/src/renderer/lib/sessionActivity.ts b/src/renderer/lib/sessionActivity.ts index 14bfc5d..73d2cc7 100644 --- a/src/renderer/lib/sessionActivity.ts +++ b/src/renderer/lib/sessionActivity.ts @@ -7,6 +7,7 @@ export interface AgentActivityState { agentName: string; activityType?: SessionEventRecord['activityType']; toolName?: string; + toolArguments?: Record; } export interface SessionUsageState { @@ -45,6 +46,7 @@ export function applySessionEventActivity( agentName: event.agentName?.trim() || event.agentId?.trim() || agentKey, activityType: event.activityType, toolName: event.toolName, + toolArguments: event.toolArguments, }, }, }; diff --git a/src/shared/domain/runTimeline.ts b/src/shared/domain/runTimeline.ts index ffa6cf0..12262ce 100644 --- a/src/shared/domain/runTimeline.ts +++ b/src/shared/domain/runTimeline.ts @@ -494,6 +494,7 @@ function normalizeRunTimelineEvent( targetAgentName: normalizeOptionalString(event.targetAgentName), toolName: normalizeOptionalString(event.toolName), toolCallId: normalizeOptionalString(event.toolCallId), + toolArguments: event.toolArguments, fileChanges: normalizeToolCallFileChanges(event.fileChanges), approvalId: normalizeOptionalString(event.approvalId), approvalKind: event.approvalKind, diff --git a/tests/renderer/sessionActivity.test.ts b/tests/renderer/sessionActivity.test.ts index 40fb16b..13b126a 100644 --- a/tests/renderer/sessionActivity.test.ts +++ b/tests/renderer/sessionActivity.test.ts @@ -99,6 +99,32 @@ describe('session activity helpers', () => { }); }); + test('includes toolArguments in activity state', () => { + const event: SessionEventRecord = { + sessionId: 'session-1', + kind: 'agent-activity', + occurredAt: '2026-03-23T00:00:00.000Z', + activityType: 'tool-calling', + agentId: 'architect', + agentName: 'Architect', + toolName: 'view', + toolArguments: { path: 'src/main.ts', view_range: [1, 50] }, + }; + + const result = applySessionEventActivity({}, event); + expect(result).toEqual({ + 'session-1': { + architect: { + agentId: 'architect', + agentName: 'Architect', + activityType: 'tool-calling', + toolName: 'view', + toolArguments: { path: 'src/main.ts', view_range: [1, 50] }, + }, + }, + }); + }); + test('warns when an agent-activity event is missing identifiers', () => { const originalWarn = console.warn; const warnings: unknown[][] = []; diff --git a/tests/shared/runTimeline.test.ts b/tests/shared/runTimeline.test.ts index 67131cb..8f5b77f 100644 --- a/tests/shared/runTimeline.test.ts +++ b/tests/shared/runTimeline.test.ts @@ -9,6 +9,7 @@ import { upsertRunApprovalEvent, upsertRunMessageEvent, } from '@shared/domain/runTimeline'; +import type { SessionRunRecord } from '@shared/domain/runTimeline'; import type { ProjectRecord } from '@shared/domain/project'; import type { PendingApprovalRecord } from '@shared/domain/approval'; @@ -265,6 +266,71 @@ describe('run timeline helpers', () => { expect(normalizeSessionRunRecords(undefined)).toEqual([]); }); + test('preserves toolArguments through normalization round-trip', () => { + const baseRun = createSessionRunRecord({ + requestId: 'turn-1', + project: createProject(), + workspaceKind: 'project', + workflow: createWorkflow(), + triggerMessageId: 'msg-user-1', + startedAt: '2026-03-23T00:00:01.000Z', + }); + + const run = appendRunActivityEvent(baseRun, { + activityType: 'tool-calling', + occurredAt: '2026-03-23T00:00:02.000Z', + agentId: 'agent-writer', + toolName: 'view', + toolCallId: 'tool-call-view-1', + toolArguments: { path: 'src/main.ts', view_range: [1, 50] }, + }); + + // Simulate persisting and reloading via normalizeSessionRunRecords + const roundTripped = normalizeSessionRunRecords( + JSON.parse(JSON.stringify([run])) as SessionRunRecord[], + ); + + expect(roundTripped).toHaveLength(1); + const toolCallEvent = roundTripped[0].events.find( + (event) => event.kind === 'tool-call', + ); + expect(toolCallEvent).toBeDefined(); + expect(toolCallEvent!.toolArguments).toEqual({ + path: 'src/main.ts', + view_range: [1, 50], + }); + }); + + test('handles missing toolArguments gracefully during normalization', () => { + const baseRun = createSessionRunRecord({ + requestId: 'turn-1', + project: createProject(), + workspaceKind: 'project', + workflow: createWorkflow(), + triggerMessageId: 'msg-user-1', + startedAt: '2026-03-23T00:00:01.000Z', + }); + + const run = appendRunActivityEvent(baseRun, { + activityType: 'tool-calling', + occurredAt: '2026-03-23T00:00:02.000Z', + agentId: 'agent-writer', + toolName: 'rg', + toolCallId: 'tool-call-rg-1', + // No toolArguments provided + }); + + const roundTripped = normalizeSessionRunRecords( + JSON.parse(JSON.stringify([run])) as SessionRunRecord[], + ); + + const toolCallEvent = roundTripped[0].events.find( + (event) => event.kind === 'tool-call', + ); + expect(toolCallEvent).toBeDefined(); + expect(toolCallEvent!.toolArguments).toBeUndefined(); + }); + test('tracks approval checkpoints as a single timeline event that can be resolved later', () => { const baseRun = createSessionRunRecord({ requestId: 'turn-1',