diff --git a/src/renderer/src/lib/agent-row-primary-text.test.ts b/src/renderer/src/lib/agent-row-primary-text.test.ts index b0360588c59..e6a0094a94a 100644 --- a/src/renderer/src/lib/agent-row-primary-text.test.ts +++ b/src/renderer/src/lib/agent-row-primary-text.test.ts @@ -1,7 +1,9 @@ import { describe, expect, it } from 'vitest' +import { normalizeAgentStatusPayload } from '../../../shared/agent-status-types' import { getAgentRowGeneratedTitleText, getAgentRowPrimaryText, + getOrcaDispatchTaskId, isOrcaDispatchPrompt } from './agent-row-primary-text' @@ -72,6 +74,58 @@ Keep the raw preamble out of the sidebar.` it('falls back to the raw prompt outside orchestration workers', () => { expect(getAgentRowPrimaryText({ prompt: 'Fix checkout race' })).toBe('Fix checkout race') }) + + // Why: production status prompts reach these helpers already folded to a + // single line and capped at 200 chars by normalizeAgentStatusPayload. Guard + // the real normalized shape — earlier tests only fed raw multi-line prompts, + // which hid that the task-id parser split on \n and never matched. + it('matches orchestration labels on a normalized single-line dispatch prompt', () => { + const normalized = normalizeAgentStatusPayload({ + state: 'working', + prompt: `You are working inside Orca, a multi-agent IDE. You are a dispatched worker. +Your coordinator's terminal handle is: term_parent +Your task ID is: task_9f3ab2 + +You talk to the coordinator only through the CLI commands below. + +=== TASK === +Fix the checkout race condition in payments` + }) + expect(normalized).not.toBeNull() + expect( + getAgentRowPrimaryText({ + prompt: normalized!.prompt, + orchestration: { + taskId: 'task_9f3ab2', + dispatchId: 'ctx-1', + taskTitle: 'Checkout race', + displayName: 'Fix checkout race' + } + }) + ).toBe('Fix checkout race') + }) +}) + +describe('getOrcaDispatchTaskId', () => { + it('extracts the id when the trailing newline was folded to a space', () => { + const normalized = normalizeAgentStatusPayload({ + state: 'working', + prompt: `You are working inside Orca, a multi-agent IDE. You are a dispatched worker. +Your task ID is: task_9f3ab2 + +=== TASK === +body` + }) + expect(getOrcaDispatchTaskId(normalized!.prompt)).toBe('task_9f3ab2') + }) + + it('extracts the id from a raw multi-line prompt', () => { + expect( + getOrcaDispatchTaskId( + `You are working inside Orca, a multi-agent IDE.\nYour task ID is: task_1\n\n=== TASK ===\nbody` + ) + ).toBe('task_1') + }) }) describe('isOrcaDispatchPrompt / getAgentRowGeneratedTitleText', () => { diff --git a/src/renderer/src/lib/agent-row-primary-text.ts b/src/renderer/src/lib/agent-row-primary-text.ts index 931dd1fbbdc..b75bfafb0b4 100644 --- a/src/renderer/src/lib/agent-row-primary-text.ts +++ b/src/renderer/src/lib/agent-row-primary-text.ts @@ -84,9 +84,13 @@ export function getOrcaDispatchTaskId(prompt: string): string | null { if (markerIndex === -1) { return null } - const afterMarker = scan.slice(markerIndex + ORCA_DISPATCH_TASK_ID_MARKER.length) - const lineEnd = afterMarker.search(/\r|\n/) - const idLine = (lineEnd === -1 ? afterMarker : afterMarker.slice(0, lineEnd)).trim() + // Why: delimit on the first whitespace, not just a newline. The task id is a + // whitespace-free token, and by the time this parses a live status prompt the + // trailing newline has been folded to a space by normalizeSingleLinePreview — + // splitting on \n alone would return the id plus the rest of the preamble. + const afterMarker = scan.slice(markerIndex + ORCA_DISPATCH_TASK_ID_MARKER.length).trimStart() + const idEnd = afterMarker.search(/\s/) + const idLine = idEnd === -1 ? afterMarker : afterMarker.slice(0, idEnd) return idLine || null }