// @ts-nocheck -- mechanically split from OrcaRuntimeService; behavior is covered by AST equivalence and characterization tests. import { OrcaRuntimeWithApplyTrackedPtyTitle } from './orca-runtime-apply-tracked-pty-title' import type { RuntimePtyTitleTrackerEntry, RuntimePtyWorktreeRecord } from './runtime-terminal-state-records' import { createCommandCodeOutputStatusDetector } from '../../shared/command-code-output-status' import { extractLastOsc7Uri, extractOscScanTail } from '../daemon/osc7-uri-extraction' import { parseFileUriPathParts } from '../daemon/osc7-file-uri' import { splitWorktreeIdForFilesystem } from '../../shared/worktree/id' import { isWindowsAbsolutePathLike } from '../../shared/cross-platform-path' import type { ProcessedAgentStatusChunk } from '../../shared/agent-status-osc' import { mapExplicitAgentStateToRuntimeTerminalStatus } from './runtime-worktree-status-projection' import type { ParsedAgentStatusPayload } from '../../shared/agent-status-types' export class OrcaRuntimeWithCreateTerminalSideEffectCommandCodeDetector extends OrcaRuntimeWithApplyTrackedPtyTitle { protected createTerminalSideEffectCommandCodeDetector( ptyId: string ): NonNullable { return createCommandCodeOutputStatusDetector({ startupCommand: this.terminalSpawnCommandsByPtyId.get(ptyId) ?? null, onWorking: (prompt) => { this.recordTerminalSideEffectFact(ptyId, { kind: 'command-code-working', prompt }) }, onDone: (prompt) => { this.recordTerminalSideEffectFact(ptyId, { kind: 'command-code-done', prompt }) } }) } protected extractLastOsc7CwdForPty( ptyId: string, data: string ): { path: string; hostname: string } | null { const previousTail = this.osc7ScanTailByPtyId.get(ptyId) if (!previousTail && !data.includes('\x1b]7;')) { return null } const input = `${previousTail ?? ''}${data}` const scanTail = extractOscScanTail(input, 4096) if (scanTail.length > 0) { this.osc7ScanTailByPtyId.set(ptyId, scanTail) } else { this.osc7ScanTailByPtyId.delete(ptyId) } const uri = extractLastOsc7Uri(input) const pty = this.ptysById.get(ptyId) const pathFlavor = this.pathFlavorForPty(pty) return uri ? parseFileUriPathParts(uri, { pathFlavor, remotePosixAuthority: !!pty?.connectionId && pathFlavor !== 'win32', wslDistro: pty?.connectionId ? undefined : (this.wslDistroByPtyId.get(ptyId) ?? pty?.wslDistro ?? undefined) }) : null } protected recordOsc7MetadataForPty( ptyId: string, data: string ): { cwd: string | null; cwdChanged: boolean } { const osc7 = this.extractLastOsc7CwdForPty(ptyId, data) const cwd = osc7?.path ?? null const cwdChanged = cwd !== null && cwd.trim().length > 0 && this.terminalCwdByPtyId.get(ptyId) !== cwd if (cwdChanged) { this.terminalCwdByPtyId.set(ptyId, cwd) } if (osc7) { if (osc7.hostname) { this.terminalFileUriHostnameByPtyId.set(ptyId, osc7.hostname) } else { this.terminalFileUriHostnameByPtyId.delete(ptyId) } } return { cwd, cwdChanged } } protected pathFlavorForPty(pty?: RuntimePtyWorktreeRecord | null): 'posix' | 'win32' { if (!pty?.connectionId) { return process.platform === 'win32' ? 'win32' : 'posix' } const worktreePath = splitWorktreeIdForFilesystem(pty.worktreeId)?.worktreePath return worktreePath && isWindowsAbsolutePathLike(worktreePath) ? 'win32' : 'posix' } /** Returns true when any retained agent-row snapshot changed in a * client-visible way, so the caller can republish session snapshots. */ protected emitTerminalAgentStatusEvents( ptyId: string, chunk: ProcessedAgentStatusChunk ): boolean { // Why: snapshot retention (for mobile worktree.ps) must run even when no // renderer listener is attached, so we don't early-return on a missing // onTerminalAgentStatus — only the per-target emit below is gated on it. if (chunk.payloads.length === 0) { return false } const targets = new Map< string, { source: 'mounted-leaf' | 'pty-record' paneKey: string tabId?: string worktreeId?: string connectionId?: string | null } >() const pty = this.ptysById.get(ptyId) const connectionId = pty?.connectionId ?? null for (const leaf of this.getLeavesForPty(ptyId)) { const paneKey = this.makeRuntimePaneKey(leaf) targets.set(paneKey, { source: 'mounted-leaf', paneKey, tabId: leaf.tabId, worktreeId: leaf.worktreeId, connectionId }) } if (targets.size === 0 && pty?.paneKey) { targets.set(pty.paneKey, { source: 'pty-record', paneKey: pty.paneKey, tabId: pty.tabId ?? undefined, worktreeId: pty.worktreeId, connectionId }) } let retainedChanged = false for (const payload of chunk.payloads) { this.recordAgentPromptLifecycleState( ptyId, mapExplicitAgentStateToRuntimeTerminalStatus(payload.state) ) for (const target of targets.values()) { retainedChanged = this.retainAgentRowSnapshot( ptyId, target.paneKey, target.worktreeId, target.tabId, target.connectionId ?? null, payload ) || retainedChanged if (!this.onTerminalAgentStatus) { continue } try { this.onTerminalAgentStatus({ ptyId, ...target, payload }) } catch (err) { console.error('[runtime] terminal agent status listener threw', { ptyId, paneKey: target.paneKey, state: payload.state, agentType: payload.agentType, err }) } } } return retainedChanged } protected retainAgentRowSnapshot( ptyId: string, paneKey: string, worktreeId: string | undefined, tabId: string | undefined, connectionId: string | null, payload: ParsedAgentStatusPayload ): boolean { return this.agentRows.retain({ ptyId, paneKey, worktreeId, tabId, connectionId, payload }) } protected clearAgentRowSnapshotsForPty(ptyId: string): void { this.agentRows.clearPty(ptyId) } }