refactor: share terminal agent status parser (#4768)
This commit is contained in:
parent
e180d137e9
commit
773ddccd36
|
|
@ -24,7 +24,10 @@ import type {
|
|||
PtyDataMeta
|
||||
} from './pty-dispatcher'
|
||||
import { createBellDetector } from './bell-detector'
|
||||
import { createAgentStatusOscProcessor, type ProcessedAgentStatusChunk } from './agent-status-osc'
|
||||
import {
|
||||
createAgentStatusOscProcessor,
|
||||
type ProcessedAgentStatusChunk
|
||||
} from '../../../../shared/agent-status-osc'
|
||||
import { extractIpcErrorMessage } from '@/lib/ipc-error'
|
||||
|
||||
// Re-export public API so existing consumers keep working.
|
||||
|
|
@ -373,9 +376,9 @@ export function createPtyOutputProcessor({
|
|||
): void {
|
||||
const rawLength = meta?.rawLength ?? data.length
|
||||
const suppressAttentionEvents = options.suppressAttentionEvents === true
|
||||
// Why: OSC 9999 is a renderer-only control protocol. Parse it before
|
||||
// xterm sees the bytes, and keep parser state across chunks so partial
|
||||
// PTY reads do not drop valid status updates or print escape garbage.
|
||||
// Why: OSC 9999 is an Orca control protocol. Parse it before xterm sees
|
||||
// the bytes, and keep parser state across chunks so partial PTY reads do
|
||||
// not drop valid status updates or print escape garbage.
|
||||
const processed = processAgentStatusChunk(data)
|
||||
data = processed.cleanData
|
||||
// Why: mirror the onBell / onAgentBecameIdle guard below — during eager-buffer
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
import { createAgentStatusOscProcessor } from '@/components/terminal-pane/agent-status-osc'
|
||||
import { subscribeToPtyData, subscribeToPtyExit } from '@/components/terminal-pane/pty-dispatcher'
|
||||
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
|
||||
import { getRemoteRuntimeTerminalMultiplexer } from '@/runtime/remote-runtime-terminal-multiplexer'
|
||||
|
|
@ -8,6 +7,7 @@ import {
|
|||
getRemoteRuntimeTerminalHandle
|
||||
} from '@/runtime/runtime-terminal-stream'
|
||||
import { useAppStore } from '@/store'
|
||||
import { createAgentStatusOscProcessor } from '../../../shared/agent-status-osc'
|
||||
import type { ParsedAgentStatusPayload } from '../../../shared/agent-status-types'
|
||||
|
||||
export async function observeExistingAutomationSession(args: {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import {
|
|||
subscribeToPtyData,
|
||||
subscribeToPtyExit
|
||||
} from '@/components/terminal-pane/pty-dispatcher'
|
||||
import { createAgentStatusOscProcessor } from '@/components/terminal-pane/agent-status-osc'
|
||||
import { callRuntimeRpc, getActiveRuntimeTarget } from '@/runtime/runtime-rpc-client'
|
||||
import { toRuntimeWorktreeSelector } from '@/runtime/runtime-worktree-selector'
|
||||
import { singlePaneLayoutSnapshot } from '@/store/slices/terminal-helpers'
|
||||
|
|
@ -22,6 +21,7 @@ import {
|
|||
subscribeToRuntimeTerminalData,
|
||||
toRemoteRuntimePtyId
|
||||
} from '@/runtime/runtime-terminal-stream'
|
||||
import { createAgentStatusOscProcessor } from '../../../shared/agent-status-osc'
|
||||
import type { ParsedAgentStatusPayload } from '../../../shared/agent-status-types'
|
||||
import type { RuntimeTerminalCreate } from '../../../shared/runtime-types'
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
import { describe, expect, it } from 'vitest'
|
||||
import { createAgentStatusOscProcessor } from './agent-status-osc'
|
||||
|
||||
describe('createAgentStatusOscProcessor', () => {
|
||||
it('strips OSC 9999 payloads from terminal data and returns parsed statuses', () => {
|
||||
const process = createAgentStatusOscProcessor()
|
||||
|
||||
const result = process(
|
||||
'before\x1b]9999;{"state":"working","prompt":"ship it","agentType":"codex"}\x07after'
|
||||
)
|
||||
|
||||
expect(result.cleanData).toBe('beforeafter')
|
||||
expect(result.payloads).toEqual([
|
||||
{
|
||||
state: 'working',
|
||||
prompt: 'ship it',
|
||||
agentType: 'codex'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
it('preserves parser state across split OSC 9999 chunks', () => {
|
||||
const process = createAgentStatusOscProcessor()
|
||||
|
||||
expect(process('before\x1b]999').cleanData).toBe('before')
|
||||
const result = process('9;{"state":"done","prompt":"ok"}\x1b\\after')
|
||||
|
||||
expect(result.cleanData).toBe('after')
|
||||
expect(result.payloads).toEqual([
|
||||
{
|
||||
state: 'done',
|
||||
prompt: 'ok'
|
||||
}
|
||||
])
|
||||
})
|
||||
})
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import type { ParsedAgentStatusPayload } from '../../../../shared/agent-status-types'
|
||||
import { parseAgentStatusPayload } from '../../../../shared/agent-status-types'
|
||||
import type { ParsedAgentStatusPayload } from './agent-status-types'
|
||||
import { parseAgentStatusPayload } from './agent-status-types'
|
||||
|
||||
const OSC_AGENT_STATUS_PREFIX = '\x1b]9999;'
|
||||
|
||||
|
|
@ -28,8 +28,8 @@ function findAgentStatusTerminator(
|
|||
|
||||
/**
|
||||
* Stateful OSC 9999 parser for PTY streams.
|
||||
* Why: automation background launches need the same agent-status parsing as
|
||||
* mounted terminal panes, even when no terminal has been rendered yet.
|
||||
* Why: hidden/model-owned terminal output needs the same agent-status parsing
|
||||
* as mounted terminal panes, even when no terminal view is rendered.
|
||||
*/
|
||||
export function createAgentStatusOscProcessor(): (data: string) => ProcessedAgentStatusChunk {
|
||||
const MAX_PENDING = 64 * 1024
|
||||
Loading…
Reference in New Issue