fix: prefer automation transcript output

This commit is contained in:
Jinjing
2026-05-17 17:12:11 -07:00
parent 5642277aaf
commit 52cb2e730a
3 changed files with 64 additions and 13 deletions
@@ -1,5 +1,9 @@
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { createAutomationRunOutputSnapshotBuffer } from './automation-run-output-snapshot'
import {
createAutomationRunOutputSnapshotBuffer,
createAutomationRunOutputSnapshotFromText,
selectAutomationRunOutputSnapshot
} from './automation-run-output-snapshot'
describe('automation run output snapshot buffer', () => {
beforeEach(() => {
@@ -68,4 +72,26 @@ describe('automation run output snapshot buffer', () => {
content: 'LoadingDone'
})
})
it('creates a saved snapshot from agent transcript text', () => {
expect(createAutomationRunOutputSnapshotFromText('\nFinal summary.\n')).toEqual({
format: 'plain_text',
content: 'Final summary.',
capturedAt: new Date('2026-05-16T12:00:00Z').getTime(),
truncated: false
})
})
it('prefers agent transcript text over raw terminal redraw output', () => {
const rawTerminalSnapshot = createAutomationRunOutputSnapshotFromText(
'q;\u2834 orca q\u2022Working q q'
)
expect(selectAutomationRunOutputSnapshot('Posted to #releases.', rawTerminalSnapshot)).toEqual({
format: 'plain_text',
content: 'Posted to #releases.',
capturedAt: new Date('2026-05-16T12:00:00Z').getTime(),
truncated: false
})
})
})
@@ -17,6 +17,31 @@ export type AutomationRunOutputSnapshotBuffer = {
snapshot: () => AutomationRunOutputSnapshot | null
}
export function createAutomationRunOutputSnapshotFromText(
content: string,
truncated = false
): AutomationRunOutputSnapshot | null {
const trimmed = content.trim()
if (!trimmed) {
return null
}
return {
format: 'plain_text',
content: trimmed,
capturedAt: Date.now(),
truncated
}
}
export function selectAutomationRunOutputSnapshot(
assistantMessage: string | null | undefined,
terminalSnapshot: AutomationRunOutputSnapshot | null
): AutomationRunOutputSnapshot | null {
// Why: raw hidden-PTY captures include full-screen TUI redraws; hook
// transcript text is the user-facing automation result when available.
return createAutomationRunOutputSnapshotFromText(assistantMessage ?? '') ?? terminalSnapshot
}
function stripTerminalControls(value: string): string {
return value
.replace(OSC_SEQUENCE_PATTERN, '')
@@ -52,15 +77,7 @@ export function createAutomationRunOutputSnapshotBuffer(): AutomationRunOutputSn
},
snapshot() {
const content = stripTerminalControls(chunks.join('')).trim()
if (!content) {
return null
}
return {
format: 'plain_text',
content,
capturedAt: Date.now(),
truncated
}
return createAutomationRunOutputSnapshotFromText(content, truncated)
}
}
}
@@ -3,7 +3,10 @@ import { launchAgentBackgroundSession } from '@/lib/launch-agent-background-sess
import { useAppStore } from '@/store'
import type { AutomationDispatchResult } from '../../../shared/automations-types'
import { parsePaneKey } from '../../../shared/stable-pane-id'
import { createAutomationRunOutputSnapshotBuffer } from '@/components/automations/automation-run-output-snapshot'
import {
createAutomationRunOutputSnapshotBuffer,
selectAutomationRunOutputSnapshot
} from '@/components/automations/automation-run-output-snapshot'
const AUTOMATIONS_CHANGED_EVENT = 'orca:automations-changed'
@@ -122,6 +125,9 @@ export function useAutomationDispatchEvents(): void {
dispatchWorkspaceDisplayName = worktree.displayName
const outputSnapshotBuffer = createAutomationRunOutputSnapshotBuffer()
let latestAssistantMessage: string | null = null
const getOutputSnapshot = () =>
selectAutomationRunOutputSnapshot(latestAssistantMessage, outputSnapshotBuffer.snapshot())
let dispatchMarked = false
let pendingExitCode: number | null = null
let pendingDone = false
@@ -138,7 +144,7 @@ export function useAutomationDispatchEvents(): void {
status: 'completed',
workspaceId: worktree.id,
workspaceDisplayName: worktree.displayName,
outputSnapshot: outputSnapshotBuffer.snapshot(),
outputSnapshot: getOutputSnapshot(),
error: null
})
}
@@ -149,7 +155,7 @@ export function useAutomationDispatchEvents(): void {
status: code === 0 ? 'completed' : 'dispatch_failed',
workspaceId: worktree.id,
workspaceDisplayName: worktree.displayName,
outputSnapshot: outputSnapshotBuffer.snapshot(),
outputSnapshot: getOutputSnapshot(),
error: code === 0 ? null : `Automation process exited with code ${code}.`
})
}
@@ -169,6 +175,7 @@ export function useAutomationDispatchEvents(): void {
for (const [paneKey, entry] of Object.entries(agentStatusByPaneKey)) {
const parsed = parsePaneKey(paneKey)
if (parsed?.tabId === tabId && entry.state === 'done') {
latestAssistantMessage = entry.lastAssistantMessage?.trim() || latestAssistantMessage
handleAgentDone()
return
}
@@ -189,6 +196,7 @@ export function useAutomationDispatchEvents(): void {
outputSnapshotBuffer.append(chunk)
},
onAgentStatus: (payload) => {
latestAssistantMessage = payload.lastAssistantMessage?.trim() || latestAssistantMessage
if (payload.state !== 'done') {
return
}