@robota-sdk/agent-transport 3.0.0-beta.64 → 3.0.0-beta.65

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/node/headless/index.cjs +1 -1
  2. package/dist/node/{headless-CsZFelG9.cjs → headless-DJ5pnxM6.cjs} +1 -1
  3. package/dist/node/http/index.cjs +1 -1
  4. package/dist/node/{http-CM3TJhrF.cjs → http-CuQE6V6t.cjs} +1 -1
  5. package/dist/node/{index-CAr3ioVh.d.ts → index-CSgNoyPK.d.ts} +23 -2
  6. package/dist/node/index-CSgNoyPK.d.ts.map +1 -0
  7. package/dist/node/{index--Ti9NzQX.d.ts → index-_dNm-2J3.d.ts} +23 -2
  8. package/dist/node/index-_dNm-2J3.d.ts.map +1 -0
  9. package/dist/node/index.cjs +1 -1
  10. package/dist/node/index.d.ts +2 -2
  11. package/dist/node/index.js +1 -1
  12. package/dist/node/mcp/index.cjs +1 -1
  13. package/dist/node/{mcp-DcHuGokt.cjs → mcp-BiJsIywJ.cjs} +1 -1
  14. package/dist/node/tui/index.cjs +1 -1
  15. package/dist/node/tui/index.d.ts +2 -2
  16. package/dist/node/tui/index.js +1 -1
  17. package/dist/node/tui-BIpIcT7-.cjs +24 -0
  18. package/dist/node/tui-DBLn1T15.js +25 -0
  19. package/dist/node/tui-DBLn1T15.js.map +1 -0
  20. package/dist/node/ws/index.cjs +1 -1
  21. package/dist/node/{ws-COnIgnmn.cjs → ws-XRTSFZOK.cjs} +1 -1
  22. package/package.json +5 -5
  23. package/src/tui/App.tsx +3 -0
  24. package/src/tui/InputArea.tsx +64 -5
  25. package/src/tui/SlashAutocomplete.tsx +2 -3
  26. package/src/tui/__tests__/input-area-flow.test.ts +19 -0
  27. package/src/tui/command-interaction.ts +35 -0
  28. package/src/tui/flows/input-area-flow.ts +8 -1
  29. package/src/tui/index.ts +8 -0
  30. package/src/tui/interactions/CommandConfirm.tsx +35 -0
  31. package/src/tui/interactions/CommandPicker.tsx +76 -0
  32. package/src/tui/render.tsx +2 -0
  33. package/dist/node/index--Ti9NzQX.d.ts.map +0 -1
  34. package/dist/node/index-CAr3ioVh.d.ts.map +0 -1
  35. package/dist/node/tui-CeD_6rSo.cjs +0 -24
  36. package/dist/node/tui-zmDTPk4b.js +0 -25
  37. package/dist/node/tui-zmDTPk4b.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tui-DBLn1T15.js","names":["formatStatusLabel","MAX_VISIBLE","OUTER_CHROME","MIN_ROW_WIDTH","useRowWidth"],"sources":["../../src/tui/hooks/useSlashRouting.ts","../../src/tui/hooks/usePermissionQueue.ts","../../src/tui/tui-state-manager.ts","../../src/tui/hooks/command-effect-queue.ts","../../src/tui/hooks/use-interactive-session-init.ts","../../src/tui/hooks/useInteractiveSession.ts","../../src/tui/hooks/usePluginCallbacks.ts","../../src/tui/hooks/command-effect-handler.ts","../../src/tui/tui-cli-adapter-context.tsx","../../src/tui/hooks/model-change-side-effect.ts","../../src/tui/hooks/useSideEffects.ts","../../src/tui/hooks/useStatusLineSettings.ts","../../src/tui/render-markdown.ts","../../src/tui/utils/tool-diff-summary.ts","../../src/tui/ToolDiffBlock.tsx","../../src/tui/UsageSummaryEntry.tsx","../../src/tui/command-output-summary.ts","../../src/tui/ToolCommandOutput.tsx","../../src/tui/MessageList.tsx","../../src/tui/status-activity.ts","../../src/tui/StatusBar.tsx","../../src/tui/SessionStatusBar.tsx","../../src/tui/flows/cjk-text-input-flow.ts","../../src/tui/CjkTextInput.tsx","../../src/tui/WaveText.tsx","../../src/tui/SlashAutocomplete.tsx","../../src/tui/interactions/CommandPicker.tsx","../../src/tui/interactions/CommandConfirm.tsx","../../src/tui/utils/paste-labels.ts","../../src/tui/hooks/useAutocomplete.ts","../../src/tui/flows/input-area-flow.ts","../../src/tui/command-interaction.ts","../../src/tui/InputArea.tsx","../../src/tui/flows/selection-flow.ts","../../src/tui/flows/confirm-prompt-flow.ts","../../src/tui/ConfirmPrompt.tsx","../../src/tui/ListPicker.tsx","../../src/tui/flows/text-prompt-flow.ts","../../src/tui/TextPrompt.tsx","../../src/tui/InteractivePrompt.tsx","../../src/tui/flows/permission-prompt-flow.ts","../../src/tui/PermissionPrompt.tsx","../../src/tui/StreamingIndicator.tsx","../../src/tui/MenuSelect.tsx","../../src/tui/plugin-tui-handlers.ts","../../src/tui/hooks/usePluginScreenData.ts","../../src/tui/PluginTUI.tsx","../../src/tui/TransportTUI.tsx","../../src/tui/SessionPicker.tsx","../../src/tui/execution-workspace-view-model.ts","../../src/tui/background-task-row-format.ts","../../src/tui/BackgroundTaskPanel.tsx","../../src/tui/ExecutionWorkspaceSwitcher.tsx","../../src/tui/ExecutionWorkspaceDetailPane.tsx","../../src/tui/UpdateNotice.tsx","../../src/tui/App.tsx","../../src/tui/render.tsx","../../src/tui/tui-transport.ts"],"sourcesContent":["/**\n * Slash command routing logic for the TUI.\n * Extracted from useInteractiveSession for single-responsibility.\n */\n\nimport { useCallback } from 'react';\nimport type {\n IInteractiveSession,\n CommandRegistry,\n ICommandResult,\n TCommandEffect,\n} from '@robota-sdk/agent-framework';\nimport { createSystemMessage, messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { TuiStateManager } from '../tui-state-manager.js';\nimport type { ICommandEffectQueue } from './command-effect-queue.js';\n\nexport function useSlashRouting(\n interactiveSession: IInteractiveSession,\n registry: CommandRegistry,\n manager: TuiStateManager,\n commandEffectQueue: ICommandEffectQueue,\n reloadPluginCommandSource?: (registry: CommandRegistry) => void,\n): (input: string) => Promise<void> {\n return useCallback(\n async (input: string) => {\n if (!input.startsWith('/')) {\n await interactiveSession.submit(input);\n manager.setPendingPrompt(interactiveSession.getPendingPrompt());\n return;\n }\n\n const parts = input.slice(1).split(/\\s+/);\n const cmd = parts[0]?.toLowerCase() ?? '';\n const args = parts.slice(1).join(' ');\n\n // Try system command first\n const result = await interactiveSession.executeCommand(cmd, args);\n if (result) {\n if (result.effects?.some((effect) => effect.type === 'session-execution-started')) {\n manager.setPendingPrompt(interactiveSession.getPendingPrompt());\n return;\n }\n applySystemCommandResult(\n result,\n interactiveSession,\n registry,\n manager,\n commandEffectQueue,\n reloadPluginCommandSource,\n );\n return;\n }\n\n manager.addEntry(\n messageToHistoryEntry(\n createSystemMessage(`Unknown command \"/${cmd}\". Type /help for help.`),\n ),\n );\n },\n [interactiveSession, registry, manager, commandEffectQueue, reloadPluginCommandSource],\n );\n}\n\nexport function applySystemCommandResult(\n result: ICommandResult,\n interactiveSession: IInteractiveSession,\n registry: CommandRegistry,\n manager: TuiStateManager,\n commandEffectQueue: ICommandEffectQueue,\n reloadPluginCommandSource?: (registry: CommandRegistry) => void,\n): void {\n const pendingEffects = applyImmediateCommandEffects(\n result.effects,\n registry,\n manager,\n reloadPluginCommandSource,\n );\n manager.addEntry(messageToHistoryEntry(createSystemMessage(result.message)));\n\n if (result.interaction !== undefined) {\n commandEffectQueue.enqueueInteraction(result.interaction);\n }\n if (pendingEffects.length > 0) {\n commandEffectQueue.enqueueEffects(pendingEffects);\n }\n\n if (interactiveSession.isInitialized) {\n const ctx = interactiveSession.getContextState();\n manager.setContextState({\n percentage: ctx.usedPercentage,\n usedTokens: ctx.usedTokens,\n maxTokens: ctx.maxTokens,\n });\n }\n}\n\nfunction applyImmediateCommandEffects(\n effects: readonly TCommandEffect[] | undefined,\n registry: CommandRegistry,\n manager: TuiStateManager,\n reloadPluginCommandSource?: (registry: CommandRegistry) => void,\n): TCommandEffect[] {\n if (effects === undefined || effects.length === 0) return [];\n const pendingEffects: TCommandEffect[] = [];\n for (const effect of effects) {\n if (effect.type === 'conversation-history-cleared') {\n manager.clearHistory();\n continue;\n }\n if (effect.type === 'plugin-registry-reload-requested') {\n reloadPluginCommandSource?.(registry);\n continue;\n }\n pendingEffects.push(effect);\n }\n return pendingEffects;\n}\n","import { useState, useRef, useCallback } from 'react';\nimport type { TToolArgs } from '@robota-sdk/agent-core';\nimport type { TPermissionResultValue } from '@robota-sdk/agent-framework';\nimport type { IPermissionRequest } from '../types.js';\n\nexport function usePermissionQueue(): {\n permissionHandler: (toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResultValue>;\n permissionRequest: IPermissionRequest | null;\n} {\n const [permissionRequest, setPermissionRequest] = useState<IPermissionRequest | null>(null);\n const permissionQueueRef = useRef<\n Array<{\n toolName: string;\n toolArgs: TToolArgs;\n resolve: (result: TPermissionResultValue) => void;\n }>\n >([]);\n const processingRef = useRef(false);\n\n const processNextPermission = useCallback(() => {\n if (processingRef.current) return;\n const next = permissionQueueRef.current[0];\n if (!next) {\n setPermissionRequest(null);\n return;\n }\n processingRef.current = true;\n setPermissionRequest({\n toolName: next.toolName,\n toolArgs: next.toolArgs,\n resolve: (result: TPermissionResultValue) => {\n permissionQueueRef.current.shift();\n processingRef.current = false;\n setPermissionRequest(null);\n next.resolve(result);\n setTimeout(() => processNextPermission(), 0);\n },\n });\n }, []);\n\n const permissionHandler = useCallback(\n (toolName: string, toolArgs: TToolArgs): Promise<TPermissionResultValue> =>\n new Promise<TPermissionResultValue>((resolve) => {\n permissionQueueRef.current.push({ toolName, toolArgs, resolve });\n processNextPermission();\n }),\n [processNextPermission],\n );\n\n return { permissionHandler, permissionRequest };\n}\n","/**\n * TuiStateManager — pure TypeScript rendering state manager.\n *\n * Converts InteractiveSession events into rendering state.\n * No React dependency. Fully unit-testable.\n *\n * React hook (useInteractiveSession) subscribes to onChange\n * and reads state for rendering.\n */\n\nimport type { IContextWindowState, IHistoryEntry } from '@robota-sdk/agent-core';\nimport type {\n IToolState,\n IExecutionResult,\n IExecutionWorkspaceSnapshot,\n} from '@robota-sdk/agent-framework';\n\n/** Max messages kept in rendering state */\nconst MAX_RENDERED_MESSAGES = 100;\n\n/** Debounce interval for streaming text notify (limits renderMarkdown frequency) */\nconst STREAMING_DEBOUNCE_MS = 300;\nexport interface IContextState {\n percentage: number;\n usedTokens: number;\n maxTokens: number;\n}\n\n/** Create a debounced notify — schedules at most one call per interval. */\nfunction createDebouncedNotify(\n notify: () => void,\n ms: number,\n): { schedule: () => void; flush: () => void } {\n let timer: ReturnType<typeof setTimeout> | null = null;\n return {\n schedule() {\n if (!timer) {\n timer = setTimeout(() => {\n timer = null;\n notify();\n }, ms);\n }\n },\n flush() {\n if (timer) {\n clearTimeout(timer);\n timer = null;\n }\n },\n };\n}\n\nexport class TuiStateManager {\n // ── Rendering state ───────────────────────────────────────────\n history: IHistoryEntry[] = [];\n streamingText = '';\n activeTools: IToolState[] = [];\n isThinking = false;\n isAborting = false;\n pendingPrompt: string | null = null;\n contextState: IContextState = { percentage: 0, usedTokens: 0, maxTokens: 0 };\n executionWorkspaceSnapshot: IExecutionWorkspaceSnapshot | null = null;\n selectedExecutionEntryId: string | undefined;\n\n /** Called after any state change. React hook sets this to trigger re-render. */\n onChange: (() => void) | null = null;\n\n // ── Internal ──────────────────────────────────────────────────\n private streamBuf = '';\n private debouncedStreamNotify = createDebouncedNotify(() => this.notify(), STREAMING_DEBOUNCE_MS);\n\n private notify(): void {\n this.onChange?.();\n }\n\n // ── Event handlers (InteractiveSession → state) ───────────────\n\n onTextDelta = (delta: string): void => {\n this.streamBuf += delta;\n this.streamingText = this.streamBuf;\n this.debouncedStreamNotify.schedule();\n };\n\n onToolStart = (state: IToolState): void => {\n this.activeTools = [...this.activeTools, state];\n this.notify();\n };\n\n onToolEnd = (state: IToolState): void => {\n // findLastIndex: when same tool runs concurrently, match the most recently started instance\n const idx = this.activeTools.findLastIndex((t) => t.toolName === state.toolName && t.isRunning);\n if (idx !== -1) {\n const updated = [...this.activeTools];\n updated[idx] = state;\n this.activeTools = updated;\n }\n this.notify();\n };\n\n onThinking = (thinking: boolean): void => {\n this.isThinking = thinking;\n if (thinking) {\n // Clear at START of new execution (preserves previous result until next)\n this.debouncedStreamNotify.flush();\n this.streamBuf = '';\n this.streamingText = '';\n this.activeTools = [];\n } else {\n this.isAborting = false;\n }\n this.notify();\n };\n\n onComplete = (result: IExecutionResult): void => {\n // Tool summary is now in messages (pushed by InteractiveSession)\n // Clear streaming display\n this.debouncedStreamNotify.flush();\n this.streamBuf = '';\n this.streamingText = '';\n this.activeTools = [];\n this.contextState = {\n percentage: result.contextState.usedPercentage,\n usedTokens: result.contextState.usedTokens,\n maxTokens: result.contextState.maxTokens,\n };\n this.notify();\n };\n\n onInterrupted = (): void => {\n // Tool summary is now in messages\n this.debouncedStreamNotify.flush();\n this.streamBuf = '';\n this.streamingText = '';\n this.activeTools = [];\n this.notify();\n };\n\n onError = (): void => {\n // Tool summary is now in messages\n this.debouncedStreamNotify.flush();\n this.streamBuf = '';\n this.streamingText = '';\n this.activeTools = [];\n this.notify();\n };\n\n onContextUpdate = (state: IContextWindowState): void => {\n this.setContextState({\n percentage: state.usedPercentage,\n usedTokens: state.usedTokens,\n maxTokens: state.maxTokens,\n });\n };\n\n // ── State updates from external sources ───────────────────────\n\n /** Sync history from InteractiveSession */\n syncHistory(entries: IHistoryEntry[]): void {\n if (entries.length === 0) return;\n this.history =\n entries.length > MAX_RENDERED_MESSAGES ? entries.slice(-MAX_RENDERED_MESSAGES) : [...entries];\n this.notify();\n }\n\n /** Add a single history entry */\n addEntry(entry: IHistoryEntry): void {\n const updated = [...this.history, entry];\n this.history =\n updated.length > MAX_RENDERED_MESSAGES ? updated.slice(-MAX_RENDERED_MESSAGES) : updated;\n this.notify();\n }\n\n clearHistory(): void {\n this.history = [];\n this.debouncedStreamNotify.flush();\n this.streamBuf = '';\n this.streamingText = '';\n this.activeTools = [];\n this.notify();\n }\n\n /** Update pending prompt state */\n setPendingPrompt(prompt: string | null): void {\n this.pendingPrompt = prompt;\n this.notify();\n }\n\n /** Set aborting flag */\n setAborting(aborting: boolean): void {\n this.isAborting = aborting;\n this.notify();\n }\n\n /** Update context state */\n setContextState(state: IContextState): void {\n this.contextState = state;\n this.notify();\n }\n\n syncExecutionWorkspaceSnapshot(snapshot: IExecutionWorkspaceSnapshot): void {\n const currentSelection = this.selectedExecutionEntryId;\n const hasCurrentSelection =\n currentSelection !== undefined &&\n snapshot.entries.some((entry) => entry.id === currentSelection);\n const selectedExecutionEntryId = hasCurrentSelection\n ? currentSelection\n : (snapshot.selectedEntryId ?? snapshot.entries[0]?.id);\n this.executionWorkspaceSnapshot = {\n ...snapshot,\n ...(selectedExecutionEntryId ? { selectedEntryId: selectedExecutionEntryId } : {}),\n };\n this.selectedExecutionEntryId = selectedExecutionEntryId;\n this.notify();\n }\n\n selectExecutionWorkspaceEntry(entryId: string): void {\n if (!this.executionWorkspaceSnapshot?.entries.some((entry) => entry.id === entryId)) return;\n this.selectedExecutionEntryId = entryId;\n this.executionWorkspaceSnapshot = {\n ...this.executionWorkspaceSnapshot,\n selectedEntryId: entryId,\n };\n this.notify();\n }\n}\n","import type { ICommandInteraction, TCommandEffect } from '@robota-sdk/agent-framework';\n\nexport type TQueuedCommandState =\n | {\n type: 'interaction';\n interaction: ICommandInteraction;\n }\n | {\n type: 'effects';\n effects: readonly TCommandEffect[];\n };\n\nexport interface ICommandEffectQueue {\n enqueueInteraction(interaction: ICommandInteraction): void;\n enqueueEffects(effects: readonly TCommandEffect[]): void;\n drain(): TQueuedCommandState | undefined;\n clear(): void;\n}\n\nexport class CommandEffectQueue implements ICommandEffectQueue {\n private readonly queue: TQueuedCommandState[] = [];\n\n enqueueInteraction(interaction: ICommandInteraction): void {\n this.queue.push({ type: 'interaction', interaction });\n }\n\n enqueueEffects(effects: readonly TCommandEffect[]): void {\n if (effects.length === 0) return;\n this.queue.push({ type: 'effects', effects: [...effects] });\n }\n\n drain(): TQueuedCommandState | undefined {\n return this.queue.shift();\n }\n\n clear(): void {\n this.queue.length = 0;\n }\n}\n","import { InteractiveSession, CommandRegistry } from '@robota-sdk/agent-framework';\nimport type { TToolArgs } from '@robota-sdk/agent-core';\nimport type { TPermissionResultValue } from '@robota-sdk/agent-framework';\nimport { TuiStateManager } from '../tui-state-manager.js';\nimport { CommandEffectQueue, type ICommandEffectQueue } from './command-effect-queue.js';\nimport type { IInteractiveSessionProps } from './useInteractiveSession.js';\n\nexport interface IInitState {\n interactiveSession: InteractiveSession;\n registry: CommandRegistry;\n commandEffectQueue: ICommandEffectQueue;\n manager: TuiStateManager;\n}\n\nexport function initializeSession(\n props: IInteractiveSessionProps,\n permissionHandler: (toolName: string, toolArgs: TToolArgs) => Promise<TPermissionResultValue>,\n): IInitState {\n const interactiveSession = new InteractiveSession({\n cwd: props.cwd,\n provider: props.provider,\n permissionMode: props.permissionMode,\n maxTurns: props.maxTurns,\n permissionHandler,\n sessionStore: props.sessionStore,\n resumeSessionId: props.resumeSessionId,\n forkSession: props.forkSession,\n sessionName: props.sessionName,\n backgroundTaskRunners: props.backgroundTaskRunners,\n subagentRunnerFactory: props.subagentRunnerFactory,\n commandModules: props.commandModules,\n commandHostAdapters: props.commandHostAdapters,\n shellExec: props.shellExec,\n language: props.language,\n agentName: props.agentName,\n });\n\n const registry = new CommandRegistry();\n for (const module of props.commandModules ?? []) {\n registry.addModule(module);\n }\n props.reloadPluginCommandSource?.(registry);\n\n return {\n interactiveSession,\n registry,\n manager: new TuiStateManager(),\n commandEffectQueue: new CommandEffectQueue(),\n };\n}\n","import { useState, useCallback, useEffect } from 'react';\nimport { InteractiveSession, CommandRegistry } from '@robota-sdk/agent-framework';\nimport type { ITransportRegistryView } from '@robota-sdk/agent-interface-transport';\nimport type {\n IBackgroundTaskRunner,\n ICommandHostAdapters,\n ICommandModule,\n IInteractiveSession,\n IInteractiveSessionStore,\n TSubagentRunnerFactory,\n IExecutionDetailPage,\n IExecutionWorkspaceSnapshot,\n TShellExecFn,\n} from '@robota-sdk/agent-framework';\nimport type {\n IAIProvider,\n TPermissionMode,\n IHistoryEntry,\n TSessionEndReason,\n} from '@robota-sdk/agent-core';\nimport { createSystemMessage, messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { IPermissionRequest } from '../types.js';\nimport { TuiStateManager } from '../tui-state-manager.js';\nimport { useSlashRouting } from './useSlashRouting.js';\nimport { CommandEffectQueue, type ICommandEffectQueue } from './command-effect-queue.js';\nimport { usePermissionQueue } from './usePermissionQueue.js';\nimport { initializeSession, type IInitState } from './use-interactive-session-init.js';\n\nconst SESSION_INIT_POLL_MS = 200;\n\nexport interface IInteractiveSessionProps {\n cwd: string;\n provider: IAIProvider;\n permissionMode?: TPermissionMode;\n maxTurns?: number;\n sessionStore?: IInteractiveSessionStore;\n resumeSessionId?: string;\n forkSession?: boolean;\n sessionName?: string;\n backgroundTaskRunners?: IBackgroundTaskRunner[];\n subagentRunnerFactory?: TSubagentRunnerFactory;\n commandModules?: readonly ICommandModule[];\n commandHostAdapters?: ICommandHostAdapters;\n shellExec?: TShellExecFn;\n transportRegistry?: ITransportRegistryView<IInteractiveSession>;\n language?: string;\n reloadPluginCommandSource?: (registry: CommandRegistry) => void;\n agentName?: string;\n}\n\nexport interface IInteractiveSessionState {\n interactiveSession: InteractiveSession;\n registry: CommandRegistry;\n commandEffectQueue: ICommandEffectQueue;\n history: IHistoryEntry[];\n addEntry: (entry: IHistoryEntry) => void;\n streamingText: string;\n activeTools: import('@robota-sdk/agent-framework').IToolState[];\n isThinking: boolean;\n isAborting: boolean;\n isShuttingDown: boolean;\n pendingPrompt: string | null;\n executionWorkspaceSnapshot: IExecutionWorkspaceSnapshot | null;\n selectedExecutionEntryId?: string;\n permissionRequest: IPermissionRequest | null;\n contextState: { percentage: number; usedTokens: number; maxTokens: number };\n handleSubmit: (input: string) => Promise<void>;\n handleAbort: () => void;\n handleCancelQueue: () => void;\n handleShutdown: (reason?: TSessionEndReason) => Promise<void>;\n selectExecutionWorkspaceEntry: (entryId: string) => void;\n readExecutionWorkspaceDetail: (entryId: string) => Promise<IExecutionDetailPage>;\n}\n\ninterface IHistoryReadableSession {\n getFullHistory(): IHistoryEntry[];\n}\n\ninterface IHistorySyncManager {\n syncHistory(entries: IHistoryEntry[]): void;\n}\n\nexport function applyCompactEventToManager(\n interactiveSession: IHistoryReadableSession,\n manager: IHistorySyncManager,\n): void {\n manager.syncHistory(interactiveSession.getFullHistory());\n}\n\nexport function applySkillActivationEventToManager(\n interactiveSession: IHistoryReadableSession,\n manager: IHistorySyncManager,\n): void {\n manager.syncHistory(interactiveSession.getFullHistory());\n}\n\nfunction syncExecutionWorkspaceFromSession(\n interactiveSession: InteractiveSession,\n manager: TuiStateManager,\n): void {\n try {\n manager.syncExecutionWorkspaceSnapshot(\n interactiveSession.getExecutionWorkspaceSnapshot({\n selectedEntryId: manager.selectedExecutionEntryId,\n }),\n );\n } catch {\n // allow-fallback: session may not be initialized yet; swallow until ready\n /* Session not initialized yet */\n }\n}\n\nexport function useInteractiveSession(props: IInteractiveSessionProps): IInteractiveSessionState {\n const [, forceRender] = useState(0);\n const [isShuttingDown, setIsShuttingDown] = useState(false);\n const { permissionHandler, permissionRequest } = usePermissionQueue();\n\n // Initialize once — useState lazy initializer runs exactly once per mount, safe for Concurrent Mode\n const [initState] = useState<IInitState>(() => initializeSession(props, permissionHandler));\n const { interactiveSession, registry, manager, commandEffectQueue } = initState;\n\n manager.onChange = () => forceRender((n) => n + 1);\n\n // Sync restored history immediately (session resume restores history in constructor)\n if (manager.history.length === 0) {\n const restored = interactiveSession.getFullHistory();\n if (restored.length > 0) {\n manager.syncHistory(restored);\n }\n }\n\n // Start transports (settings-driven: WS + web-monitor based on registry config).\n useEffect(() => {\n if (!props.transportRegistry) return;\n const reg = props.transportRegistry;\n reg.startAll(interactiveSession).catch(() => undefined);\n return () => {\n reg.stopAll().catch(() => undefined);\n };\n }, [interactiveSession, props.transportRegistry]);\n\n // Connect InteractiveSession events to TuiStateManager\n useEffect(() => {\n const onCompact = (): void => applyCompactEventToManager(interactiveSession, manager);\n const onSkillActivation = (): void =>\n applySkillActivationEventToManager(interactiveSession, manager);\n const onExecutionWorkspaceEvent = (\n event: import('@robota-sdk/agent-framework').IExecutionWorkspaceEvent,\n ): void => manager.syncExecutionWorkspaceSnapshot(event.snapshot);\n\n interactiveSession.on('text_delta', manager.onTextDelta);\n interactiveSession.on('tool_start', manager.onToolStart);\n interactiveSession.on('tool_end', manager.onToolEnd);\n interactiveSession.on('thinking', manager.onThinking);\n interactiveSession.on('complete', manager.onComplete);\n interactiveSession.on('interrupted', manager.onInterrupted);\n interactiveSession.on('error', manager.onError);\n interactiveSession.on('context_update', manager.onContextUpdate);\n interactiveSession.on('compact', onCompact);\n interactiveSession.on('skill_activation', onSkillActivation);\n interactiveSession.on('execution_workspace_event', onExecutionWorkspaceEvent);\n\n // Sync context state and restored history after async initialization\n const initCheck = setInterval(() => {\n try {\n const ctx = interactiveSession.getContextState();\n manager.setContextState({\n percentage: ctx.usedPercentage,\n usedTokens: ctx.usedTokens,\n maxTokens: ctx.maxTokens,\n });\n const restored = interactiveSession.getFullHistory();\n if (restored.length > 0) {\n manager.syncHistory(restored);\n }\n syncExecutionWorkspaceFromSession(interactiveSession, manager);\n clearInterval(initCheck);\n } catch {\n // allow-fallback: session initializes asynchronously; poll until ready\n /* Not yet initialized */\n }\n }, SESSION_INIT_POLL_MS);\n\n return () => {\n clearInterval(initCheck);\n interactiveSession.off('text_delta', manager.onTextDelta);\n interactiveSession.off('tool_start', manager.onToolStart);\n interactiveSession.off('tool_end', manager.onToolEnd);\n interactiveSession.off('thinking', manager.onThinking);\n interactiveSession.off('complete', manager.onComplete);\n interactiveSession.off('interrupted', manager.onInterrupted);\n interactiveSession.off('error', manager.onError);\n interactiveSession.off('context_update', manager.onContextUpdate);\n interactiveSession.off('compact', onCompact);\n interactiveSession.off('skill_activation', onSkillActivation);\n interactiveSession.off('execution_workspace_event', onExecutionWorkspaceEvent);\n };\n }, [interactiveSession, manager]);\n\n // Sync messages on every thinking state change:\n // - thinking=true: \"You:\" and \"System: Invoking...\" are already in messages\n // - thinking=false: complete/interrupted messages are in messages\n useEffect(() => {\n manager.syncHistory(interactiveSession.getFullHistory());\n syncExecutionWorkspaceFromSession(interactiveSession, manager);\n if (!manager.isThinking) {\n manager.setPendingPrompt(interactiveSession.getPendingPrompt());\n }\n }, [manager.isThinking, interactiveSession, manager]);\n\n const handleSubmit = useSlashRouting(\n interactiveSession,\n registry,\n manager,\n commandEffectQueue,\n props.reloadPluginCommandSource,\n );\n\n const handleAbort = useCallback(() => {\n manager.setAborting(true);\n interactiveSession.abort();\n }, [interactiveSession, manager]);\n\n const handleCancelQueue = useCallback(() => {\n interactiveSession.cancelQueue();\n manager.setPendingPrompt(null);\n }, [interactiveSession, manager]);\n\n const handleShutdown = useCallback(\n async (reason: TSessionEndReason = 'prompt_input_exit'): Promise<void> => {\n if (isShuttingDown) return;\n setIsShuttingDown(true);\n manager.addEntry(messageToHistoryEntry(createSystemMessage('Shutting down...')));\n await interactiveSession.shutdown({ reason, message: 'CLI shutdown' });\n },\n [interactiveSession, manager, isShuttingDown],\n );\n\n const selectExecutionWorkspaceEntry = useCallback(\n (entryId: string): void => manager.selectExecutionWorkspaceEntry(entryId),\n [manager],\n );\n\n const readExecutionWorkspaceDetail = useCallback(\n (entryId: string): Promise<IExecutionDetailPage> =>\n interactiveSession.readExecutionWorkspaceDetail(entryId),\n [interactiveSession],\n );\n\n return {\n interactiveSession,\n registry,\n commandEffectQueue,\n history: manager.history,\n addEntry: (entry: IHistoryEntry) => manager.addEntry(entry),\n streamingText: manager.streamingText,\n activeTools: manager.activeTools,\n isThinking: manager.isThinking,\n isAborting: manager.isAborting,\n isShuttingDown,\n pendingPrompt: manager.pendingPrompt,\n executionWorkspaceSnapshot: manager.executionWorkspaceSnapshot,\n selectedExecutionEntryId: manager.selectedExecutionEntryId,\n permissionRequest,\n contextState: manager.contextState,\n handleSubmit,\n handleAbort,\n handleCancelQueue,\n handleShutdown,\n selectExecutionWorkspaceEntry,\n readExecutionWorkspaceDetail,\n };\n}\n","/**\n * Hook: returns a no-op ICommandPluginAdapter for when no plugin adapter is provided.\n *\n * In normal usage, App receives commandHostAdapters.plugin from the CLI (agent-cli), which\n * constructs the real adapter. This fallback exists only for test environments where no adapter\n * is injected.\n */\n\nimport { useMemo } from 'react';\nimport type { ICommandPluginAdapter } from '@robota-sdk/agent-framework';\n\nfunction createNoOpPluginAdapter(): ICommandPluginAdapter {\n return {\n listInstalled: async () => [],\n listAvailablePlugins: async () => [],\n install: async () => undefined,\n uninstall: async () => undefined,\n enable: async () => undefined,\n disable: async () => undefined,\n marketplaceAdd: async () => '',\n marketplaceRemove: async () => undefined,\n marketplaceUpdate: async () => undefined,\n marketplaceList: async () => [],\n reloadPlugins: async () => ({ loadedPluginCount: 0 }),\n };\n}\n\nexport function usePluginCallbacks(_cwd: string): ICommandPluginAdapter {\n return useMemo(() => createNoOpPluginAdapter(), []);\n}\n","import type { TCommandEffect, TStatusLineCommandSettingsPatch } from '@robota-sdk/agent-framework';\nimport { isStatusLineCommandSettingsPatch } from '@robota-sdk/agent-framework';\nimport { createSystemMessage, messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { IHistoryEntry, TSessionEndReason } from '@robota-sdk/agent-core';\nimport type { ITuiCliAdapter } from '../tui-cli-adapter.js';\n\nexport interface ICommandEffectHandlerDeps {\n addEntry: (entry: IHistoryEntry) => void;\n requestShutdown: (reason: TSessionEndReason, message: string) => void;\n requestModelChange: (modelId: string) => void;\n openPluginTUI: () => void;\n openSessionPicker: () => void;\n openTransportTUI: () => void;\n openAgentSwitcher: () => void;\n renameSession: (name: string) => void;\n applyStatusLinePatch: (patch: TStatusLineCommandSettingsPatch) => boolean;\n cliAdapter: ITuiCliAdapter;\n}\n\nexport function applyCommandEffects(\n effects: readonly TCommandEffect[],\n deps: ICommandEffectHandlerDeps,\n): boolean {\n for (const effect of effects) {\n if (effect.type === 'model-change-requested') {\n deps.requestModelChange(effect.modelId);\n return true;\n }\n if (effect.type === 'language-change-requested') {\n applyLanguageEffect(effect.language, deps);\n return true;\n }\n if (effect.type === 'settings-reset-requested') {\n applySettingsResetEffect(deps);\n return true;\n }\n if (effect.type === 'session-exit-requested') {\n deps.requestShutdown(\n effect.reason ?? 'prompt_input_exit',\n effect.message ?? 'User requested exit',\n );\n return true;\n }\n if (effect.type === 'session-restart-requested') {\n deps.requestShutdown(effect.reason, effect.message);\n return true;\n }\n if (effect.type === 'plugin-tui-requested') {\n deps.openPluginTUI();\n return true;\n }\n if (effect.type === 'settings-tui-requested') {\n deps.openTransportTUI();\n return true;\n }\n if (effect.type === 'agent-switcher-requested') {\n deps.openAgentSwitcher();\n return true;\n }\n if (effect.type === 'session-picker-requested') {\n deps.openSessionPicker();\n return true;\n }\n if (effect.type === 'session-renamed') {\n deps.renameSession(effect.name);\n return true;\n }\n if (effect.type === 'statusline-settings-patch') {\n if (isStatusLineCommandSettingsPatch(effect.patch)) {\n return deps.applyStatusLinePatch(effect.patch);\n }\n }\n }\n return false;\n}\n\nfunction applyLanguageEffect(language: string, deps: ICommandEffectHandlerDeps): void {\n const settingsPath = deps.cliAdapter.getUserSettingsPath();\n const settings = deps.cliAdapter.readSettings(settingsPath);\n settings.language = language;\n deps.cliAdapter.writeSettings(settingsPath, settings);\n deps.addEntry(\n messageToHistoryEntry(createSystemMessage(`Language set to \"${language}\". Restarting...`)),\n );\n deps.requestShutdown('other', 'Language change restart');\n}\n\nfunction applySettingsResetEffect(deps: ICommandEffectHandlerDeps): void {\n const settingsPath = deps.cliAdapter.getUserSettingsPath();\n if (deps.cliAdapter.deleteSettings(settingsPath)) {\n deps.addEntry(\n messageToHistoryEntry(createSystemMessage(`Deleted ${settingsPath}. Exiting...`)),\n );\n } else {\n deps.addEntry(messageToHistoryEntry(createSystemMessage('No user settings found.')));\n }\n deps.requestShutdown('other', 'Reset settings restart');\n}\n","import { createContext, useContext } from 'react';\nimport type { ITuiCliAdapter } from './tui-cli-adapter.js';\n\nconst TuiCliAdapterContext = createContext<ITuiCliAdapter | null>(null);\n\nexport const TuiCliAdapterProvider = TuiCliAdapterContext.Provider;\n\nexport function useTuiCliAdapter(): ITuiCliAdapter {\n const adapter = useContext(TuiCliAdapterContext);\n if (!adapter) throw new Error('TuiCliAdapterContext not provided');\n return adapter;\n}\n","import {\n createSystemMessage,\n getModelName,\n messageToHistoryEntry,\n type IHistoryEntry,\n type TSessionEndReason,\n} from '@robota-sdk/agent-core';\n\ntype TApplyModelChange = (\n cwd: string,\n modelId: string,\n options?: { providerOverride?: string },\n) => { applied: boolean };\n\nexport interface IApplyConfirmedModelChangeDeps {\n cwd: string;\n modelId: string;\n providerOverride?: string | undefined;\n addEntry: (entry: IHistoryEntry) => void;\n requestShutdown: (reason: TSessionEndReason, message: string) => void;\n applyModelChange?: TApplyModelChange;\n}\n\nexport function formatModelChangeConfirmationMessage(modelId: string): string {\n return `Change model to ${getModelName(modelId)}? This will exit the current session so the next session uses it.`;\n}\n\nexport function formatModelChangeExitMessage(modelId: string): string {\n return `Model changed to ${getModelName(modelId)}. Exiting so the next session uses it.`;\n}\n\nexport function applyConfirmedModelChange(deps: IApplyConfirmedModelChangeDeps): void {\n const applyModelChange = deps.applyModelChange;\n if (!applyModelChange) {\n deps.addEntry(\n messageToHistoryEntry(createSystemMessage('Model change unavailable: no adapter provided.')),\n );\n return;\n }\n\n const options =\n deps.providerOverride !== undefined ? { providerOverride: deps.providerOverride } : undefined;\n\n try {\n // allow-fallback: user-facing error display for model change failure\n applyModelChange(deps.cwd, deps.modelId, options);\n deps.addEntry(\n messageToHistoryEntry(createSystemMessage(formatModelChangeExitMessage(deps.modelId))),\n );\n deps.requestShutdown('other', 'Model change applied');\n } catch (error) {\n // allow-fallback: user-facing error display for model change failure\n deps.addEntry(\n messageToHistoryEntry(\n createSystemMessage(`Failed: ${error instanceof Error ? error.message : String(error)}`),\n ),\n );\n }\n}\n\nexport function addModelChangeCancelledMessage(addEntry: (entry: IHistoryEntry) => void): void {\n addEntry(messageToHistoryEntry(createSystemMessage('Model change cancelled.')));\n}\n","import { useState, useRef, useCallback } from 'react';\nimport { useApp } from 'ink';\nimport type { ICommandInteraction, ICommandResult } from '@robota-sdk/agent-framework';\nimport { createSystemMessage, messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { TSessionEndReason } from '@robota-sdk/agent-core';\nimport type { TInteractivePrompt } from './side-effects-types.js';\nimport type { IUseSideEffectsOptions, IUseSideEffectsResult } from './side-effects-types.js';\nimport { applyCommandEffects } from './command-effect-handler.js';\nimport { useTuiCliAdapter } from '../tui-cli-adapter-context.js';\nimport {\n addModelChangeCancelledMessage,\n applyConfirmedModelChange,\n} from './model-change-side-effect.js';\n\nconst EXIT_DELAY_MS = 500;\n\nexport function useSideEffects({\n cwd,\n providerOverride,\n interactiveSession,\n commandEffectQueue,\n addEntry,\n baseHandleSubmit,\n setSessionName,\n setStatusLineSettings,\n showSessionPickerOnStart,\n openAgentSwitcher,\n}: IUseSideEffectsOptions): IUseSideEffectsResult {\n const { exit } = useApp();\n const cliAdapter = useTuiCliAdapter();\n const [pendingModelId, setPendingModelId] = useState<string | null>(null);\n const pendingModelChangeRef = useRef<string | null>(null);\n const [pendingInteractionPrompt, setPendingInteractionPrompt] =\n useState<TInteractivePrompt | null>(null);\n const commandInteractionRef = useRef<ICommandInteraction | null>(null);\n const [showPluginTUI, setShowPluginTUI] = useState(false);\n const [showSessionPicker, setShowSessionPicker] = useState(showSessionPickerOnStart ?? false);\n const [showTransportTUI, setShowTransportTUI] = useState(false);\n\n const requestShutdown = useCallback(\n (reason: TSessionEndReason, message: string): void => {\n addEntry(messageToHistoryEntry(createSystemMessage('Shutting down...')));\n setTimeout(() => {\n void interactiveSession.shutdown({ reason, message }).finally(() => exit());\n }, EXIT_DELAY_MS);\n },\n [interactiveSession, addEntry, exit],\n );\n\n const applyEffects = useCallback(\n (effects: Parameters<typeof applyCommandEffects>[0]): boolean =>\n applyCommandEffects(effects, {\n addEntry,\n requestShutdown,\n requestModelChange: (modelId) => {\n pendingModelChangeRef.current = modelId;\n setPendingModelId(modelId);\n },\n openPluginTUI: () => setShowPluginTUI(true),\n openSessionPicker: () => setShowSessionPicker(true),\n openTransportTUI: () => setShowTransportTUI(true),\n openAgentSwitcher: () => openAgentSwitcher?.(),\n renameSession: (name) => {\n interactiveSession.setName(name);\n setSessionName(name);\n },\n applyStatusLinePatch: (patch) => {\n setStatusLineSettings(\n cliAdapter.applyStatusLineSettings(cliAdapter.getUserSettingsPath(), patch),\n );\n return true;\n },\n cliAdapter,\n }),\n [\n addEntry,\n cliAdapter,\n interactiveSession,\n requestShutdown,\n setSessionName,\n setStatusLineSettings,\n ],\n );\n\n const applyCommandResult = useCallback(\n (result: ICommandResult): void => {\n if (result.message.length > 0) {\n addEntry(messageToHistoryEntry(createSystemMessage(result.message)));\n }\n if (result.interaction !== undefined) {\n commandInteractionRef.current = result.interaction;\n setPendingInteractionPrompt(result.interaction.prompt);\n return;\n }\n commandInteractionRef.current = null;\n setPendingInteractionPrompt(null);\n if (result.effects !== undefined && result.effects.length > 0) {\n applyEffects(result.effects);\n }\n },\n [addEntry, applyEffects],\n );\n\n const applyQueuedCommandState = useCallback((): boolean => {\n const queued = commandEffectQueue.drain();\n if (queued === undefined) {\n return false;\n }\n if (queued.type === 'interaction') {\n const { interaction } = queued;\n commandInteractionRef.current = interaction;\n setPendingInteractionPrompt(interaction.prompt);\n return true;\n }\n return applyEffects(queued.effects);\n }, [applyEffects, commandEffectQueue]);\n\n const handleSubmit = useCallback(\n async (input: string): Promise<void> => {\n await baseHandleSubmit(input);\n applyQueuedCommandState();\n },\n [baseHandleSubmit, applyQueuedCommandState],\n );\n\n const handleModelConfirm = useCallback(\n (index: number) => {\n const modelId = pendingModelChangeRef.current;\n setPendingModelId(null);\n pendingModelChangeRef.current = null;\n if (index === 0 && modelId) {\n applyConfirmedModelChange({\n cwd,\n modelId,\n providerOverride,\n addEntry,\n requestShutdown,\n applyModelChange: (c, m, opts) => {\n cliAdapter.applyActiveModelChange(c, m, opts);\n return { applied: true };\n },\n });\n } else {\n addModelChangeCancelledMessage(addEntry);\n }\n },\n [cwd, providerOverride, addEntry, cliAdapter, requestShutdown],\n );\n\n const handleInteractionSubmit = useCallback(\n async (value: string): Promise<void> => {\n const interaction = commandInteractionRef.current;\n if (interaction === null) {\n setPendingInteractionPrompt(null);\n return;\n }\n try {\n // allow-fallback: user-facing error display for plugin interaction submit\n const result = await interaction.submit(value);\n applyCommandResult(result);\n } catch (err) {\n // allow-fallback: user-facing error display for plugin interaction submit\n commandInteractionRef.current = null;\n setPendingInteractionPrompt(null);\n addEntry(\n messageToHistoryEntry(\n createSystemMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`),\n ),\n );\n }\n },\n [addEntry, applyCommandResult],\n );\n\n const handleInteractionCancel = useCallback(() => {\n const interaction = commandInteractionRef.current;\n commandInteractionRef.current = null;\n setPendingInteractionPrompt(null);\n if (interaction?.cancel === undefined) {\n addEntry(messageToHistoryEntry(createSystemMessage('Command interaction cancelled.')));\n return;\n }\n Promise.resolve(interaction.cancel())\n .then((result) => applyCommandResult(result))\n .catch((err) => {\n // allow-fallback: user-facing error display for interaction cancel\n addEntry(\n messageToHistoryEntry(\n createSystemMessage(`Failed: ${err instanceof Error ? err.message : String(err)}`),\n ),\n );\n });\n }, [addEntry, applyCommandResult]);\n\n return {\n handleSubmit,\n pendingModelId,\n pendingInteractionPrompt,\n showPluginTUI,\n showSessionPicker,\n showTransportTUI,\n setPendingModelId,\n setShowPluginTUI,\n setShowSessionPicker,\n setShowTransportTUI,\n handleModelConfirm,\n handleInteractionSubmit,\n handleInteractionCancel,\n };\n}\n","import { useState } from 'react';\nimport type { IStatusLineCommandSettings } from '@robota-sdk/agent-framework';\nimport { DEFAULT_STATUS_LINE_COMMAND_SETTINGS } from '@robota-sdk/agent-framework';\nimport { useTuiCliAdapter } from '../tui-cli-adapter-context.js';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\n\nfunction readStatusLineSettings(\n settings: Record<string, TUniversalValue>,\n): IStatusLineCommandSettings {\n const defaults = { ...DEFAULT_STATUS_LINE_COMMAND_SETTINGS };\n const raw = settings.statusline;\n if (!isRecord(raw)) {\n return defaults;\n }\n return {\n enabled: typeof raw.enabled === 'boolean' ? raw.enabled : defaults.enabled,\n gitBranch: typeof raw.gitBranch === 'boolean' ? raw.gitBranch : defaults.gitBranch,\n };\n}\n\nfunction isRecord(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return (\n value !== null && typeof value === 'object' && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nexport function useStatusLineSettings(): [\n IStatusLineCommandSettings,\n (settings: IStatusLineCommandSettings) => void,\n] {\n const cliAdapter = useTuiCliAdapter();\n return useState<IStatusLineCommandSettings>(() =>\n readStatusLineSettings(cliAdapter.readSettings(cliAdapter.getUserSettingsPath())),\n );\n}\n","import { marked } from 'marked';\nimport type { Renderer } from 'marked';\n// @ts-expect-error — marked-terminal has no type declarations\nimport TerminalRenderer from 'marked-terminal';\n\nconst ANSI_LIGHT_RED = '\\u001b[38;5;210m';\nconst ANSI_LIGHT_GREEN = '\\u001b[38;5;120m';\nconst ANSI_CYAN = '\\u001b[36m';\nconst ANSI_DIM = '\\u001b[2m';\nconst ANSI_DARK_RED_BACKGROUND = '\\u001b[48;5;52m';\nconst ANSI_DARK_GREEN_BACKGROUND = '\\u001b[48;5;22m';\nconst ANSI_RESET = '\\u001b[0m';\nconst CODE_BLOCK_INDENT = ' ';\nconst ZERO_COLOR = '0';\n\ninterface IRenderMarkdownOptions {\n color?: boolean;\n codeBlockWidth?: number;\n}\n\ninterface ITerminalRendererOptions {\n code?: (text: string) => string;\n}\n\ninterface IHighlightOptions {\n ignoreIllegals?: boolean;\n}\n\ntype TTerminalRendererConstructor = new (\n options?: ITerminalRendererOptions,\n highlightOptions?: IHighlightOptions,\n) => Renderer;\n\nconst TerminalRendererConstructor = TerminalRenderer as TTerminalRendererConstructor;\n\nfunction shouldUseColor(option: boolean | undefined): boolean {\n if (option !== undefined) {\n return option;\n }\n if (process.env.NO_COLOR || process.env.FORCE_COLOR === ZERO_COLOR) {\n return false;\n }\n if (process.env.FORCE_COLOR) {\n return true;\n }\n return Boolean(process.stdout.isTTY);\n}\n\nfunction isDiffLanguage(language: string | undefined): boolean {\n return language?.trim().toLowerCase() === 'diff';\n}\n\nfunction styleAddedOrRemovedDiffRow(line: string, rowWidth: number, color: boolean): string {\n const row = `${CODE_BLOCK_INDENT}${line}`.padEnd(rowWidth);\n if (!color) {\n return row.trimEnd();\n }\n if (line.startsWith('+')) {\n return `${ANSI_DARK_GREEN_BACKGROUND}${ANSI_LIGHT_GREEN}${row}${ANSI_RESET}`;\n }\n if (line.startsWith('-')) {\n return `${ANSI_DARK_RED_BACKGROUND}${ANSI_LIGHT_RED}${row}${ANSI_RESET}`;\n }\n return row.trimEnd();\n}\n\nfunction colorizeDiffLine(line: string, color: boolean, rowWidth: number): string {\n if (line.startsWith('+') || line.startsWith('-')) {\n return styleAddedOrRemovedDiffRow(line, rowWidth, color);\n }\n const row = `${CODE_BLOCK_INDENT}${line}`;\n if (!color) {\n return row;\n }\n if (line.startsWith('@@')) {\n return `${ANSI_CYAN}${row}${ANSI_RESET}`;\n }\n if (line.startsWith('diff ') || line.startsWith('index ')) {\n return `${ANSI_DIM}${row}${ANSI_RESET}`;\n }\n return row;\n}\n\nfunction resolveDiffRowWidth(lines: readonly string[], requestedWidth: number | undefined): number {\n const minimumWidth = lines.reduce(\n (maxWidth, line) => Math.max(maxWidth, CODE_BLOCK_INDENT.length + line.length),\n 0,\n );\n if (requestedWidth === undefined) {\n return minimumWidth;\n }\n return Math.max(minimumWidth, requestedWidth);\n}\n\nfunction renderDiffCodeBlock(\n code: string,\n color: boolean,\n codeBlockWidth: number | undefined,\n): string {\n const lines = code.split('\\n');\n const rowWidth = resolveDiffRowWidth(lines, codeBlockWidth);\n const body = lines.map((line) => colorizeDiffLine(line, color, rowWidth)).join('\\n');\n return `${body}\\n\\n`;\n}\n\nfunction createTerminalRenderer(color: boolean, codeBlockWidth: number | undefined): Renderer {\n const renderer = new TerminalRendererConstructor(undefined, { ignoreIllegals: true });\n const renderCode = renderer.code.bind(renderer);\n\n renderer.code = (code: string, language: string | undefined, escaped: boolean): string => {\n if (isDiffLanguage(language)) {\n return renderDiffCodeBlock(code, color, codeBlockWidth);\n }\n return renderCode(code, language, escaped);\n };\n\n return renderer;\n}\n\n/**\n * Render markdown to a terminal-formatted string with colors, bold, etc.\n * Returns the rendered string (may include ANSI escape codes).\n */\nexport function renderMarkdown(md: string, options: IRenderMarkdownOptions = {}): string {\n const result = marked.parse(md, {\n renderer: createTerminalRenderer(shouldUseColor(options.color), options.codeBlockWidth),\n });\n return typeof result === 'string' ? result.trimEnd() : md;\n}\n","import type { IDiffLine } from './edit-diff.js';\n\nconst MAX_DIFF_LINES = 12;\nconst TRUNCATED_SHOW = 10;\n\nexport interface IToolDiffSummaryInput {\n file?: string;\n lines: readonly IDiffLine[];\n}\n\nexport interface IToolDiffSummary {\n file?: string;\n markdown: string;\n truncated: boolean;\n remainingLineCount: number;\n}\n\nexport function buildToolDiffSummary(input: IToolDiffSummaryInput): IToolDiffSummary {\n const visibleLines =\n input.lines.length > MAX_DIFF_LINES ? selectVisibleDiffLines(input.lines) : input.lines;\n const lineNumberWidth = Math.max(...visibleLines.map((line) => line.lineNumber), 0).toString()\n .length;\n const body = visibleLines.map((line) => formatDiffLine(line, lineNumberWidth));\n const truncated = input.lines.length > MAX_DIFF_LINES;\n\n return {\n file: input.file,\n markdown: ['```diff', ...body, '```'].join('\\n'),\n truncated,\n remainingLineCount: truncated ? input.lines.length - visibleLines.length : 0,\n };\n}\n\nfunction formatDiffLine(line: IDiffLine, lineNumberWidth: number): string {\n if (line.type === 'hunk') return line.text;\n const lineNumber = line.lineNumber.toString().padStart(lineNumberWidth, ' ');\n if (line.type === 'remove') return `- ${lineNumber} | ${line.text}`;\n if (line.type === 'add') return `+ ${lineNumber} | ${line.text}`;\n return ` ${lineNumber} | ${line.text}`;\n}\n\nfunction selectVisibleDiffLines(lines: readonly IDiffLine[]): readonly IDiffLine[] {\n const groups = groupByHunk(lines);\n const visible: IDiffLine[] = [];\n\n for (const group of groups) {\n if (visible.length === 0 && group.length > TRUNCATED_SHOW) {\n return group.slice(0, TRUNCATED_SHOW);\n }\n if (visible.length + group.length > TRUNCATED_SHOW) break;\n visible.push(...group);\n }\n\n return visible.length > 0 ? visible : lines.slice(0, TRUNCATED_SHOW);\n}\n\nfunction groupByHunk(lines: readonly IDiffLine[]): IDiffLine[][] {\n const groups: IDiffLine[][] = [];\n let current: IDiffLine[] = [];\n\n for (const line of lines) {\n if (line.type === 'hunk' && current.length > 0) {\n groups.push(current);\n current = [line];\n continue;\n }\n current.push(line);\n }\n\n if (current.length > 0) {\n groups.push(current);\n }\n\n return groups;\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport { buildToolDiffSummary } from './utils/tool-diff-summary.js';\nimport { renderMarkdown } from './render-markdown.js';\nimport type { IDiffLine } from './utils/edit-diff.js';\n\ninterface IProps {\n file?: string;\n lines: readonly IDiffLine[];\n}\n\nexport default function ToolDiffBlock({ file, lines }: IProps): React.ReactElement {\n const summary = buildToolDiffSummary({ file, lines });\n\n return (\n <Box flexDirection=\"column\" marginLeft={4}>\n {summary.file && (\n <Text color=\"white\" dimColor>\n │ {summary.file}\n </Text>\n )}\n <Text>{renderMarkdown(summary.markdown)}</Text>\n {summary.truncated && (\n <Text color=\"white\" dimColor>\n │ ... and {summary.remainingLineCount} more lines\n </Text>\n )}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { IHistoryEntry } from '@robota-sdk/agent-core';\nimport { formatTokenCount } from '@robota-sdk/agent-core';\nimport type { IUsageSnapshot } from '@robota-sdk/agent-framework';\n\nconst TOKEN_COMPACT_THRESHOLD = 1000;\n\nexport default function UsageSummaryEntry({ entry }: { entry: IHistoryEntry }): React.ReactElement {\n const usage = entry.data as IUsageSnapshot | undefined;\n if (!usage) return <></>;\n const prompt = usage.promptTokens !== undefined ? formatUsageTokenCount(usage.promptTokens) : '?';\n const completion =\n usage.completionTokens !== undefined ? formatUsageTokenCount(usage.completionTokens) : '?';\n const total = formatUsageTokenCount(usage.totalTokens);\n const context = `${Math.round(usage.contextUsedPercentage)}% (${formatTokenCount(\n usage.contextUsedTokens,\n )}/${formatTokenCount(usage.contextMaxTokens)})`;\n const costLabel = usage.costStatus === 'unknown' ? 'cost unknown' : `cost ${usage.costStatus}`;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"white\" bold>\n Usage:{' '}\n </Text>\n <Text dimColor>\n {usage.kind} {total} tokens (in {prompt} / out {completion}) · Context {context} ·{' '}\n {costLabel}\n </Text>\n </Box>\n </Box>\n );\n}\n\nfunction formatUsageTokenCount(tokens: number): string {\n return tokens < TOKEN_COMPACT_THRESHOLD ? tokens.toLocaleString() : formatTokenCount(tokens);\n}\n","import type { TUniversalValue } from '@robota-sdk/agent-core';\n\nconst MAX_PREVIEW_LINES = 4;\nconst SUCCESS_EXIT_CODE = 0;\nconst COMMAND_TOOL_NAMES = new Set(['Bash', 'BackgroundProcess']);\n\nexport interface ICommandOutputInput {\n toolName: string;\n firstArg?: string;\n isRunning?: boolean;\n result?: string;\n toolResultData?: string;\n}\n\nexport interface ICommandOutputSummary {\n status: 'success' | 'error';\n statusLabel: string;\n previewLines: string[];\n omittedLineCount: number;\n transcriptHint?: string;\n}\n\nexport function formatCommandOutputSummary(\n tool: ICommandOutputInput,\n): ICommandOutputSummary | undefined {\n if (!COMMAND_TOOL_NAMES.has(tool.toolName) || !tool.toolResultData) return undefined;\n\n const parsed = parseToolResultData(tool.toolResultData);\n const exitCode = getNumberValue(parsed, 'exitCode');\n const successValue = getBooleanValue(parsed, 'success');\n const output = buildOutputText(tool.toolResultData, parsed);\n const lines = trimTrailingBlankLines(splitOutputLines(output));\n const previewLines = lines.slice(0, MAX_PREVIEW_LINES);\n const omittedLineCount = Math.max(0, lines.length - previewLines.length);\n const isFailed =\n tool.result === 'error' ||\n successValue === false ||\n (exitCode !== undefined && exitCode !== SUCCESS_EXIT_CODE);\n\n return {\n status: isFailed ? 'error' : 'success',\n statusLabel: formatStatusLabel(isFailed, exitCode),\n previewLines,\n omittedLineCount,\n transcriptHint:\n omittedLineCount > 0\n ? `... +${omittedLineCount} lines (full output in session transcript)`\n : undefined,\n };\n}\n\nfunction parseToolResultData(value: string): TUniversalValue {\n try {\n return JSON.parse(value) as TUniversalValue;\n } catch {\n return value;\n }\n}\n\nfunction buildOutputText(raw: string, parsed: TUniversalValue): string {\n if (!isUniversalObject(parsed)) return raw;\n\n const output = getStringValue(parsed, 'output');\n if (output !== undefined) return output;\n\n const stdout = getStringValue(parsed, 'stdout');\n const stderr = getStringValue(parsed, 'stderr');\n const error = getStringValue(parsed, 'error');\n const lines: string[] = [];\n if (stdout) lines.push(stdout);\n if (stderr) lines.push(prefixLines(stderr, '[stderr] '));\n if (!stdout && !stderr && error) lines.push(error);\n return lines.join('\\n');\n}\n\nfunction formatStatusLabel(isFailed: boolean, exitCode: number | undefined): string {\n if (exitCode !== undefined && exitCode !== SUCCESS_EXIT_CODE) return `exit ${exitCode}`;\n return isFailed ? 'error' : 'ok';\n}\n\nfunction splitOutputLines(output: string): string[] {\n if (!output) return [];\n return output.replace(/\\r\\n/g, '\\n').split('\\n');\n}\n\nfunction trimTrailingBlankLines(lines: string[]): string[] {\n let end = lines.length;\n while (end > 0 && lines[end - 1]!.trim().length === 0) {\n end -= 1;\n }\n return lines.slice(0, end);\n}\n\nfunction prefixLines(value: string, prefix: string): string {\n return splitOutputLines(value)\n .map((line) => `${prefix}${line}`)\n .join('\\n');\n}\n\nfunction isUniversalObject(value: TUniversalValue): value is Record<string, TUniversalValue> {\n return (\n typeof value === 'object' && value !== null && !Array.isArray(value) && !(value instanceof Date)\n );\n}\n\nfunction getStringValue(source: TUniversalValue, key: string): string | undefined {\n if (!isUniversalObject(source)) return undefined;\n const value = source[key];\n return typeof value === 'string' ? value : undefined;\n}\n\nfunction getNumberValue(source: TUniversalValue, key: string): number | undefined {\n if (!isUniversalObject(source)) return undefined;\n const value = source[key];\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined;\n}\n\nfunction getBooleanValue(source: TUniversalValue, key: string): boolean | undefined {\n if (!isUniversalObject(source)) return undefined;\n const value = source[key];\n return typeof value === 'boolean' ? value : undefined;\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { ICommandOutputInput } from './command-output-summary.js';\nimport { formatCommandOutputSummary } from './command-output-summary.js';\n\ninterface IProps {\n tool: ICommandOutputInput;\n}\n\nexport default function ToolCommandOutput({ tool }: IProps): React.ReactElement | null {\n const summary = formatCommandOutputSummary(tool);\n if (!summary) return null;\n if (\n summary.statusLabel === 'ok' &&\n summary.previewLines.length === 0 &&\n !summary.transcriptHint\n ) {\n return null;\n }\n const color = summary.status === 'error' ? 'red' : 'white';\n\n return (\n <Box flexDirection=\"column\" marginLeft={4}>\n {summary.statusLabel !== 'ok' && (\n <Text color={color} dimColor>\n {summary.statusLabel}\n </Text>\n )}\n {summary.previewLines.map((line, index) => (\n <Text key={`${line}-${index}`} color={color} dimColor>\n {line}\n </Text>\n ))}\n {summary.transcriptHint && <Text dimColor>{summary.transcriptHint}</Text>}\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { IHistoryEntry, TUniversalMessage, TUniversalValue } from '@robota-sdk/agent-core';\nimport { isToolMessage, isAssistantMessage } from '@robota-sdk/agent-core';\nimport { renderMarkdown } from './render-markdown.js';\nimport type { IToolCallSummary } from './utils/tool-call-extractor.js';\nimport ToolDiffBlock from './ToolDiffBlock.js';\nimport UsageSummaryEntry from './UsageSummaryEntry.js';\nimport { formatCommandOutputSummary } from './command-output-summary.js';\nimport ToolCommandOutput from './ToolCommandOutput.js';\n\ninterface IProps {\n history: IHistoryEntry[];\n}\n\ntype TToolSummaryItem = {\n toolName: string;\n firstArg?: string;\n isRunning?: boolean;\n result?: string;\n diffLines?: IToolCallSummary['diffLines'];\n diffFile?: string;\n toolResultData?: string;\n};\n\nfunction getToolSummaryStatus(tool: TToolSummaryItem): string {\n if (formatCommandOutputSummary(tool)?.status === 'error') return '✗';\n if (tool.isRunning) return '⟳';\n if (tool.result === 'error') return '✗';\n if (tool.result === 'denied') return '⊘';\n return '✓';\n}\n\nfunction getToolSummaryColor(tool: TToolSummaryItem): string {\n if (formatCommandOutputSummary(tool)?.status === 'error' || tool.result === 'error') return 'red';\n if (tool.isRunning || tool.result === 'denied') return 'yellow';\n return 'green';\n}\n\nfunction getToolSummaryLabel(tool: TToolSummaryItem): string {\n return `${getToolSummaryStatus(tool)} ${tool.toolName}${tool.firstArg ? `(${tool.firstArg})` : ''}`;\n}\n\nfunction RoleLabel({ role }: { role: TUniversalMessage['role'] }): React.ReactElement {\n switch (role) {\n case 'user':\n return (\n <Text color=\"green\" bold>\n You:{' '}\n </Text>\n );\n case 'assistant':\n return (\n <Text color=\"cyan\" bold>\n Robota:{' '}\n </Text>\n );\n case 'system':\n return (\n <Text color=\"yellow\" bold>\n System:{' '}\n </Text>\n );\n case 'tool':\n return (\n <Text color=\"white\" bold>\n Tool:{' '}\n </Text>\n );\n }\n}\n\nfunction ToolMessage({ message }: { message: TUniversalMessage }): React.ReactElement {\n if (!isToolMessage(message)) {\n return <></>;\n }\n const toolName = message.name;\n const content = message.content;\n\n // Try to parse structured tool summaries (with diff info)\n let summaries: IToolCallSummary[] | null = null;\n try {\n const parsed = JSON.parse(content) as IToolCallSummary[];\n if (Array.isArray(parsed) && parsed.length > 0 && typeof parsed[0].line === 'string') {\n summaries = parsed as IToolCallSummary[];\n }\n } catch {\n // Not JSON — fall back to plain text lines\n }\n\n if (summaries) {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"white\" bold>\n Tool:{' '}\n </Text>\n {toolName && (\n <Text color=\"white\" dimColor>\n [{toolName}]\n </Text>\n )}\n </Box>\n <Text> </Text>\n {summaries.map((s, i) => (\n <Box key={i} flexDirection=\"column\">\n <Text color=\"green\">\n {' '}\n {'✓'} {s.line}\n </Text>\n {s.diffLines && s.diffLines.length > 0 && (\n <ToolDiffBlock file={s.diffFile} lines={s.diffLines} />\n )}\n </Box>\n ))}\n </Box>\n );\n }\n\n // Fallback: plain text lines\n const lines = content.split('\\n').filter((l) => l.trim());\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"white\" bold>\n Tool:{' '}\n </Text>\n {toolName && (\n <Text color=\"white\" dimColor>\n [{toolName}]\n </Text>\n )}\n </Box>\n <Text> </Text>\n {lines.map((line, i) => (\n <Text key={i} color=\"green\">\n {' '}\n {'✓'} {line}\n </Text>\n ))}\n </Box>\n );\n}\n\nconst MessageItem = React.memo(function MessageItem({\n message,\n}: {\n message: TUniversalMessage;\n}): React.ReactElement {\n if (isToolMessage(message)) {\n return <ToolMessage message={message} />;\n }\n\n const content = message.content ?? '';\n const isInterrupted = message.state === 'interrupted';\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <RoleLabel role={message.role} />\n </Box>\n <Text> </Text>\n <Box marginLeft={2}>\n <Text wrap=\"wrap\">\n {isAssistantMessage(message)\n ? renderMarkdown(content + (isInterrupted ? '\\n\\n_(interrupted)_' : ''))\n : content}\n </Text>\n </Box>\n </Box>\n );\n});\n\nfunction ToolSummaryEntry({ entry }: { entry: IHistoryEntry }): React.ReactElement {\n const data = entry.data as\n | {\n summary?: string;\n tools?: TToolSummaryItem[];\n }\n | undefined;\n const tools = data?.tools;\n const lines = data?.summary?.split('\\n') ?? [];\n\n if (tools && tools.length > 0) {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"white\" bold>\n Tool:{' '}\n </Text>\n </Box>\n <Text> </Text>\n {tools.map((tool, i) => (\n <Box key={i} flexDirection=\"column\">\n <Text color={getToolSummaryColor(tool)}>\n {' '}\n {getToolSummaryLabel(tool)}\n </Text>\n <ToolCommandOutput tool={tool} />\n {tool.diffLines && tool.diffLines.length > 0 && (\n <ToolDiffBlock file={tool.diffFile} lines={tool.diffLines} />\n )}\n </Box>\n ))}\n </Box>\n );\n }\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"white\" bold>\n Tool:{' '}\n </Text>\n </Box>\n <Text> </Text>\n {lines.map((line, i) => (\n <Text key={i} color=\"green\">\n {' '}\n {line}\n </Text>\n ))}\n </Box>\n );\n}\n\nfunction EventEntry({ entry }: { entry: IHistoryEntry }): React.ReactElement {\n const eventData = entry.data as Record<string, TUniversalValue> | undefined;\n const eventMessage =\n typeof eventData?.message === 'string'\n ? eventData.message\n : typeof eventData?.content === 'string'\n ? eventData.content\n : entry.type;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Box>\n <Text color=\"yellow\" bold>\n System:{' '}\n </Text>\n </Box>\n <Text> </Text>\n <Box marginLeft={2}>\n <Text wrap=\"wrap\">{eventMessage}</Text>\n </Box>\n </Box>\n );\n}\n\nfunction EntryItem({ entry }: { entry: IHistoryEntry }): React.ReactElement {\n if (entry.category === 'chat') {\n const message = entry.data as TUniversalMessage;\n return <MessageItem message={message} />;\n }\n\n if (entry.type === 'tool-summary') {\n return <ToolSummaryEntry entry={entry} />;\n }\n\n if (entry.type === 'usage-summary') {\n return <UsageSummaryEntry entry={entry} />;\n }\n\n // tool-start/tool-end are recorded in history for persistence but not rendered\n // (StreamingIndicator shows them during streaming, tool-summary shows them after)\n if (entry.type === 'tool-start' || entry.type === 'tool-end') {\n return <></>;\n }\n\n return <EventEntry entry={entry} />;\n}\n\nexport default function MessageList({ history }: IProps): React.ReactElement {\n return (\n <Box flexDirection=\"column\">\n {history.map((entry) => (\n <EntryItem key={entry.id} entry={entry} />\n ))}\n </Box>\n );\n}\n","export type TStatusActivityKind = 'tools' | 'thinking' | 'background' | 'queued' | 'idle';\n\nexport interface IStatusActivityInput {\n isThinking: boolean;\n activeToolCount: number;\n activeBackgroundTaskCount: number;\n hasPendingPrompt: boolean;\n}\n\nexport interface IStatusActivity {\n kind: TStatusActivityKind;\n label: string;\n color: string;\n segments: string[];\n text: string;\n}\n\nconst NO_ACTIVE_ITEMS = 0;\n\nexport function formatStatusActivity(input: IStatusActivityInput): IStatusActivity {\n const base = getPrimaryActivity(input);\n const segments = input.hasPendingPrompt && base.kind !== 'queued' ? ['queued'] : [];\n const text = [base.label, ...segments].join(' · ');\n return { ...base, segments, text };\n}\n\nfunction getPrimaryActivity(\n input: IStatusActivityInput,\n): Omit<IStatusActivity, 'segments' | 'text'> {\n if (input.activeToolCount > NO_ACTIVE_ITEMS) {\n return {\n kind: 'tools',\n label: `Tools x${input.activeToolCount}`,\n color: 'cyan',\n };\n }\n if (input.isThinking) {\n return {\n kind: 'thinking',\n label: 'Thinking',\n color: 'yellow',\n };\n }\n if (input.activeBackgroundTaskCount > NO_ACTIVE_ITEMS) {\n return {\n kind: 'background',\n label: `Background x${input.activeBackgroundTaskCount}`,\n color: 'cyan',\n };\n }\n if (input.hasPendingPrompt) {\n return {\n kind: 'queued',\n label: 'Queued',\n color: 'yellow',\n };\n }\n return {\n kind: 'idle',\n label: 'Idle',\n color: 'gray',\n };\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { TPermissionMode } from '@robota-sdk/agent-core';\nimport { formatTokenCount } from '@robota-sdk/agent-core';\nimport { formatStatusActivity } from './status-activity.js';\n\n/** Threshold boundaries for context percentage color coding */\nconst CONTEXT_YELLOW_THRESHOLD = 70;\nconst CONTEXT_RED_THRESHOLD = 90;\n\ninterface IProps {\n permissionMode: TPermissionMode;\n modelName: string;\n providerDisplayName?: string | undefined;\n sessionId: string;\n isThinking: boolean;\n activeToolCount?: number;\n activeBackgroundTaskCount?: number;\n hasPendingPrompt?: boolean;\n contextPercentage: number;\n contextUsedTokens: number;\n contextMaxTokens: number;\n sessionName?: string;\n gitBranch?: string;\n showGitBranch?: boolean;\n activeAgentLabel?: string;\n}\n\ninterface IStatusLeftProps {\n permissionMode: TPermissionMode;\n modelName: string;\n providerDisplayName?: string | undefined;\n isThinking: boolean;\n activeToolCount: number;\n activeBackgroundTaskCount: number;\n hasPendingPrompt: boolean;\n contextPercentage: number;\n contextUsedTokens: number;\n contextMaxTokens: number;\n sessionName?: string;\n gitBranch?: string;\n showGitBranch: boolean;\n}\n\n/** Return the color for the context percentage indicator */\nfunction getContextColor(percentage: number): string {\n if (percentage >= CONTEXT_RED_THRESHOLD) return 'red';\n if (percentage >= CONTEXT_YELLOW_THRESHOLD) return 'yellow';\n return 'green';\n}\n\nfunction StatusActivityText({\n isThinking,\n activeToolCount,\n activeBackgroundTaskCount,\n hasPendingPrompt,\n}: Pick<\n IStatusLeftProps,\n 'isThinking' | 'activeToolCount' | 'activeBackgroundTaskCount' | 'hasPendingPrompt'\n>): React.ReactElement {\n const activity = formatStatusActivity({\n isThinking,\n activeToolCount,\n activeBackgroundTaskCount,\n hasPendingPrompt,\n });\n\n return (\n <Text color={activity.color} bold={activity.kind !== 'idle'}>\n {activity.text}\n </Text>\n );\n}\n\nfunction ContextText({\n percentage,\n usedTokens,\n maxTokens,\n}: {\n percentage: number;\n usedTokens: number;\n maxTokens: number;\n}): React.ReactElement {\n return (\n <Text color={getContextColor(percentage)}>\n Context: {Math.round(percentage)}% ({formatTokenCount(usedTokens)}/\n {formatTokenCount(maxTokens)})\n </Text>\n );\n}\n\nfunction ModeText({ permissionMode }: { permissionMode: TPermissionMode }): React.ReactElement {\n return (\n <>\n <Text color=\"cyan\" bold>\n Mode:\n </Text>{' '}\n <Text>{permissionMode}</Text>\n </>\n );\n}\n\nfunction shouldShowPermissionMode(permissionMode: TPermissionMode): boolean {\n return permissionMode !== 'default';\n}\n\nfunction ProviderText({\n modelName,\n providerDisplayName,\n}: {\n modelName: string;\n providerDisplayName?: string | undefined;\n}): React.ReactElement {\n if (providerDisplayName !== undefined) {\n return (\n <Text dimColor>\n {providerDisplayName} {modelName}\n </Text>\n );\n }\n return <Text dimColor>{modelName}</Text>;\n}\n\nfunction StatusLeft(props: IStatusLeftProps): React.ReactElement {\n const shouldShowGitBranch =\n props.showGitBranch && props.gitBranch !== undefined && props.gitBranch.length > 0;\n const showPermissionMode = shouldShowPermissionMode(props.permissionMode);\n return (\n <Text>\n <StatusActivityText\n isThinking={props.isThinking}\n activeToolCount={props.activeToolCount}\n activeBackgroundTaskCount={props.activeBackgroundTaskCount}\n hasPendingPrompt={props.hasPendingPrompt}\n />\n {showPermissionMode && (\n <>\n {' | '}\n <ModeText permissionMode={props.permissionMode} />\n </>\n )}\n {props.sessionName && (\n <>\n {' | '}\n <Text color=\"magenta\">{props.sessionName}</Text>\n </>\n )}\n {shouldShowGitBranch && (\n <>\n {' | '}\n <Text dimColor>git: {props.gitBranch}</Text>\n </>\n )}\n {' | '}\n <ProviderText modelName={props.modelName} providerDisplayName={props.providerDisplayName} />\n {' | '}\n <ContextText\n percentage={props.contextPercentage}\n usedTokens={props.contextUsedTokens}\n maxTokens={props.contextMaxTokens}\n />\n </Text>\n );\n}\n\nexport default function StatusBar({\n permissionMode,\n modelName,\n providerDisplayName,\n sessionId: _sessionId,\n isThinking,\n activeToolCount = 0,\n activeBackgroundTaskCount = 0,\n hasPendingPrompt = false,\n contextPercentage,\n contextUsedTokens,\n contextMaxTokens,\n sessionName,\n gitBranch,\n showGitBranch = true,\n activeAgentLabel,\n}: IProps): React.ReactElement {\n return (\n <Box\n borderStyle=\"single\"\n borderColor=\"gray\"\n paddingLeft={1}\n paddingRight={1}\n justifyContent=\"space-between\"\n >\n <StatusLeft\n permissionMode={permissionMode}\n modelName={modelName}\n providerDisplayName={providerDisplayName}\n isThinking={isThinking}\n activeToolCount={activeToolCount}\n activeBackgroundTaskCount={activeBackgroundTaskCount}\n hasPendingPrompt={hasPendingPrompt}\n contextPercentage={contextPercentage}\n contextUsedTokens={contextUsedTokens}\n contextMaxTokens={contextMaxTokens}\n sessionName={sessionName}\n gitBranch={gitBranch}\n showGitBranch={showGitBranch}\n />\n {activeAgentLabel !== undefined && (\n <Text color=\"yellow\" bold>\n [{activeAgentLabel}]\n </Text>\n )}\n </Box>\n );\n}\n","import React, { useMemo } from 'react';\nimport type { TPermissionMode } from '@robota-sdk/agent-core';\nimport type { IStatusLineCommandSettings } from '@robota-sdk/agent-framework';\nimport { useTuiCliAdapter } from './tui-cli-adapter-context.js';\nimport StatusBar from './StatusBar.js';\n\ninterface IProps {\n cwd: string;\n permissionMode: TPermissionMode;\n modelId?: string;\n providerType?: string | undefined;\n sessionId: string;\n isThinking: boolean;\n activeToolCount: number;\n activeBackgroundTaskCount: number;\n hasPendingPrompt: boolean;\n contextState: { percentage: number; usedTokens: number; maxTokens: number };\n sessionName?: string;\n settings: IStatusLineCommandSettings;\n activeAgentLabel?: string;\n}\n\nexport default function SessionStatusBar({\n cwd,\n permissionMode,\n modelId,\n providerType,\n sessionId,\n isThinking,\n activeToolCount,\n activeBackgroundTaskCount,\n hasPendingPrompt,\n contextState,\n sessionName,\n settings,\n activeAgentLabel,\n}: IProps): React.ReactElement | null {\n const cliAdapter = useTuiCliAdapter();\n const gitBranch = useMemo(() => cliAdapter.getGitBranch(cwd), [cliAdapter, cwd]);\n const providerDisplayName = useMemo(\n () =>\n providerType !== undefined ? cliAdapter.getProviderDisplayName(providerType) : undefined,\n [cliAdapter, providerType],\n );\n if (!settings.enabled) return null;\n\n return (\n <StatusBar\n permissionMode={permissionMode}\n modelName={modelId ?? ''}\n providerDisplayName={providerDisplayName}\n sessionId={sessionId}\n isThinking={isThinking}\n activeToolCount={activeToolCount}\n activeBackgroundTaskCount={activeBackgroundTaskCount}\n hasPendingPrompt={hasPendingPrompt}\n contextPercentage={contextState.percentage}\n contextUsedTokens={contextState.usedTokens}\n contextMaxTokens={contextState.maxTokens}\n sessionName={sessionName}\n gitBranch={gitBranch}\n showGitBranch={settings.gitBranch}\n activeAgentLabel={activeAgentLabel}\n />\n );\n}\n","import stringWidth from 'string-width';\n\nconst PASTE_START = '[200~';\nconst PASTE_END = '[201~';\nconst LAST_ASCII_CONTROL_CODE = 0x1f;\nconst DELETE_CONTROL_CODE = 0x7f;\n\nexport interface ICjkTextInputFlowState {\n value: string;\n cursor: number;\n isPasting: boolean;\n pasteBuffer: string;\n}\n\nexport interface ICjkTextInputKey {\n ctrl?: boolean;\n tab?: boolean;\n shift?: boolean;\n upArrow?: boolean;\n downArrow?: boolean;\n return?: boolean;\n leftArrow?: boolean;\n rightArrow?: boolean;\n backspace?: boolean;\n delete?: boolean;\n}\n\nexport interface ICjkTextInputFlowOptions {\n availableWidth?: number;\n canPaste: boolean;\n enableVerticalNavigation?: boolean;\n}\n\nexport type TCjkTextInputEffect =\n | { type: 'none' }\n | { type: 'change'; value: string }\n | { type: 'submit'; value: string }\n | { type: 'paste'; text: string; cursor: number }\n | { type: 'render' };\n\ninterface ICjkTextInputFlowResult {\n state: ICjkTextInputFlowState;\n effect: TCjkTextInputEffect;\n}\n\nexport function createCjkTextInputFlowState(value: string): ICjkTextInputFlowState {\n return { value, cursor: value.length, isPasting: false, pasteBuffer: '' };\n}\n\nexport function syncCjkTextInputFlowState(\n state: ICjkTextInputFlowState,\n value: string,\n cursorHint: number | null,\n): ICjkTextInputFlowState {\n if (value === state.value) {\n return state;\n }\n return {\n ...state,\n value,\n cursor: cursorHint != null ? Math.min(cursorHint, value.length) : value.length,\n };\n}\n\nexport function applyCjkTextInput(\n state: ICjkTextInputFlowState,\n input: string,\n key: ICjkTextInputKey,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult {\n const pasteResult = applyPasteBoundaryInput(state, input, options);\n if (pasteResult !== undefined) return pasteResult;\n const controlResult = applyControlInput(state, input, key, options);\n if (controlResult !== undefined) return controlResult;\n const cursorResult = applyCursorInput(state, key, options);\n if (cursorResult !== undefined) return cursorResult;\n return insertPrintableInput(state, input);\n}\n\nexport function applyCjkTextPaste(\n state: ICjkTextInputFlowState,\n text: string,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult {\n const normalizedText = text.replace(/\\r\\n?/g, '\\n');\n if (normalizedText.length === 0) {\n return { state, effect: { type: 'none' } };\n }\n if (normalizedText.includes('\\n') && options.canPaste) {\n return { state, effect: { type: 'paste', text: normalizedText, cursor: state.cursor } };\n }\n return insertPrintableInput(state, normalizedText);\n}\n\nfunction applyPasteBoundaryInput(\n state: ICjkTextInputFlowState,\n input: string,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult | undefined {\n if (input === PASTE_START || input.startsWith(PASTE_START)) {\n return startBracketedPaste(state, input);\n }\n if (state.isPasting) {\n return continueBracketedPaste(state, input, options);\n }\n return undefined;\n}\n\nfunction applyControlInput(\n state: ICjkTextInputFlowState,\n input: string,\n key: ICjkTextInputKey,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult | undefined {\n if ((key.ctrl === true && input === 'c') || key.tab === true) {\n return { state, effect: { type: 'none' } };\n }\n if (key.return === true) {\n return { state, effect: { type: 'submit', value: state.value } };\n }\n if (input.length > 1 && (input.includes('\\n') || input.includes('\\r')) && options.canPaste) {\n return {\n state,\n effect: { type: 'paste', text: input.replace(/\\r\\n?/g, '\\n'), cursor: state.cursor },\n };\n }\n return undefined;\n}\n\nfunction applyCursorInput(\n state: ICjkTextInputFlowState,\n key: ICjkTextInputKey,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult | undefined {\n if (key.upArrow === true || key.downArrow === true) {\n if (options.enableVerticalNavigation === false) {\n return { state, effect: { type: 'none' } };\n }\n return moveCursorVertically(\n state,\n key.upArrow === true ? 'up' : 'down',\n options.availableWidth,\n );\n }\n if (key.leftArrow === true) {\n return moveCursorHorizontally(state, 'left');\n }\n if (key.rightArrow === true) {\n return moveCursorHorizontally(state, 'right');\n }\n if (key.backspace === true || key.delete === true) {\n return deleteBeforeCursor(state);\n }\n return undefined;\n}\n\nexport function filterPrintable(input: string | null | undefined): string {\n if (!input || input.length === 0) return '';\n let output = '';\n for (const char of input) {\n const code = char.charCodeAt(0);\n if (code > LAST_ASCII_CONTROL_CODE && code !== DELETE_CONTROL_CODE) {\n output += char;\n }\n }\n return output;\n}\n\nexport function insertAtCursor(\n value: string,\n cursor: number,\n input: string,\n): { value: string; cursor: number } {\n const next = value.slice(0, cursor) + input + value.slice(cursor);\n return { value: next, cursor: cursor + input.length };\n}\n\nexport function displayOffset(chars: string[], charIndex: number, width: number): number {\n let offset = 0;\n for (let i = 0; i < charIndex && i < chars.length; i++) {\n const w = stringWidth(chars[i]!);\n const col = offset % width;\n if (col + w > width) offset += width - col;\n offset += w;\n }\n return offset;\n}\n\nexport function charIndexAtDisplayOffset(chars: string[], target: number, width: number): number {\n let offset = 0;\n for (let i = 0; i < chars.length; i++) {\n if (offset >= target) return i;\n const w = stringWidth(chars[i]!);\n const col = offset % width;\n if (col + w > width) offset += width - col;\n offset += w;\n }\n return chars.length;\n}\n\nfunction startBracketedPaste(\n state: ICjkTextInputFlowState,\n input: string,\n): ICjkTextInputFlowResult {\n return {\n state: { ...state, isPasting: true, pasteBuffer: input.slice(PASTE_START.length) },\n effect: { type: 'none' },\n };\n}\n\nfunction continueBracketedPaste(\n state: ICjkTextInputFlowState,\n input: string,\n options: ICjkTextInputFlowOptions,\n): ICjkTextInputFlowResult {\n if (input !== PASTE_END && !input.includes(PASTE_END)) {\n return {\n state: { ...state, pasteBuffer: state.pasteBuffer + input },\n effect: { type: 'none' },\n };\n }\n const beforeMarker = input.split(PASTE_END)[0] ?? '';\n const nextState = { ...state, isPasting: false, pasteBuffer: '' };\n return applyCjkTextPaste(nextState, state.pasteBuffer + beforeMarker, options);\n}\n\nfunction moveCursorVertically(\n state: ICjkTextInputFlowState,\n direction: 'up' | 'down',\n availableWidth: number | undefined,\n): ICjkTextInputFlowResult {\n if (!availableWidth || availableWidth <= 0) {\n return { state, effect: { type: 'none' } };\n }\n const chars = [...state.value];\n const offset = displayOffset(chars, state.cursor, availableWidth);\n const target = direction === 'up' ? offset - availableWidth : offset + availableWidth;\n if (target < 0) {\n return { state, effect: { type: 'none' } };\n }\n const cursor = charIndexAtDisplayOffset(chars, target, availableWidth);\n if (cursor === state.cursor) {\n return { state, effect: { type: 'none' } };\n }\n return { state: { ...state, cursor }, effect: { type: 'render' } };\n}\n\nfunction moveCursorHorizontally(\n state: ICjkTextInputFlowState,\n direction: 'left' | 'right',\n): ICjkTextInputFlowResult {\n if (direction === 'left' && state.cursor > 0) {\n return { state: { ...state, cursor: state.cursor - 1 }, effect: { type: 'render' } };\n }\n if (direction === 'right' && state.cursor < state.value.length) {\n return { state: { ...state, cursor: state.cursor + 1 }, effect: { type: 'render' } };\n }\n return { state, effect: { type: 'none' } };\n}\n\nfunction deleteBeforeCursor(state: ICjkTextInputFlowState): ICjkTextInputFlowResult {\n if (state.cursor === 0) {\n return { state, effect: { type: 'none' } };\n }\n const value = state.value.slice(0, state.cursor - 1) + state.value.slice(state.cursor);\n return {\n state: { ...state, value, cursor: state.cursor - 1 },\n effect: { type: 'change', value },\n };\n}\n\nfunction insertPrintableInput(\n state: ICjkTextInputFlowState,\n input: string,\n): ICjkTextInputFlowResult {\n const printable = filterPrintable(input);\n if (printable.length === 0) {\n return { state, effect: { type: 'none' } };\n }\n const result = insertAtCursor(state.value, state.cursor, printable);\n return {\n state: { ...state, value: result.value, cursor: result.cursor },\n effect: { type: 'change', value: result.value },\n };\n}\n","/**\n * CJK-aware TextInput component for Ink.\n *\n * Replaces ink-text-input with proper wide character support:\n * - Uses string-width for display width calculation\n * - Cursor position based on character index (not display columns)\n * - Renders CJK characters correctly (2 columns each)\n * - Uses refs for value/cursor to avoid React state batching issues\n * (IME sends multiple keystrokes synchronously, state updates are async)\n *\n * Drop-in replacement: same props as ink-text-input.\n */\n\nimport React, { useRef, useState } from 'react';\nimport { Text, useInput, usePaste } from 'ink';\nimport chalk from 'chalk';\nimport {\n applyCjkTextInput,\n applyCjkTextPaste,\n createCjkTextInputFlowState,\n syncCjkTextInputFlowState,\n type ICjkTextInputFlowState,\n} from './flows/cjk-text-input-flow.js';\n\ninterface IProps {\n value: string;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n onPaste?: (text: string, cursorPosition: number) => void;\n placeholder?: string;\n focus?: boolean;\n showCursor?: boolean;\n /** Available width in columns for visual line wrapping navigation */\n availableWidth?: number;\n /** Cursor position hint for external value changes. null = end (default). */\n cursorHint?: number | null;\n /** When false, parent flows own up/down arrow behavior. */\n enableVerticalNavigation?: boolean;\n}\n\ninterface IInputHandlerOptions {\n stateRef: React.MutableRefObject<ICjkTextInputFlowState>;\n onChange: (value: string) => void;\n onSubmit?: (value: string) => void;\n onPaste?: (text: string, cursorPosition: number) => void;\n availableWidth?: number;\n focus: boolean;\n enableVerticalNavigation: boolean;\n forceRender: React.Dispatch<React.SetStateAction<number>>;\n}\n\nexport default function CjkTextInput({\n value,\n onChange,\n onSubmit,\n onPaste,\n placeholder = '',\n focus = true,\n showCursor = true,\n availableWidth,\n cursorHint = null,\n enableVerticalNavigation = true,\n}: IProps): React.ReactElement {\n const stateRef = useRef<ICjkTextInputFlowState>(createCjkTextInputFlowState(value));\n const [, forceRender] = useState(0);\n\n // useCursor removed — see comment below about Terminal.app SIGSEGV\n\n // Sync ref when value changes from parent (e.g., setValue(''), tab completion, paste)\n stateRef.current = syncCjkTextInputFlowState(stateRef.current, value, cursorHint);\n\n useCjkTextInputHandlers({\n stateRef,\n onChange,\n onSubmit,\n onPaste,\n availableWidth,\n focus,\n enableVerticalNavigation,\n forceRender,\n });\n\n // Do NOT call setCursorPosition() — passing y:0 moves the real terminal cursor\n // to the top of the entire ink output (logo area), which causes Terminal.app to\n // SIGSEGV when Korean IME queries attributedSubstringFromRange: at that position.\n // Without setCursorPosition, the IME candidate window appears at bottom-left\n // (same behavior as Claude Code, issue #19207), but Terminal.app does not crash.\n //\n // A correct fix would require knowing the total rendered height to pass the right\n // y coordinate, which ink does not expose to components.\n\n return (\n <Text>\n {renderWithCursor(\n stateRef.current.value,\n stateRef.current.cursor,\n placeholder,\n showCursor && focus,\n )}\n </Text>\n );\n}\n\nfunction useCjkTextInputHandlers(options: IInputHandlerOptions): void {\n usePaste(\n (text) => {\n applyCjkFlowSafely(options, () =>\n applyCjkTextPaste(options.stateRef.current, text, createFlowOptions(options)),\n );\n },\n { isActive: options.focus },\n );\n\n useInput(\n (input, key) => {\n applyCjkFlowSafely(options, () =>\n applyCjkTextInput(options.stateRef.current, input, key, createFlowOptions(options)),\n );\n },\n { isActive: options.focus },\n );\n}\n\nfunction createFlowOptions(options: IInputHandlerOptions): {\n availableWidth?: number;\n canPaste: boolean;\n enableVerticalNavigation: boolean;\n} {\n return {\n availableWidth: options.availableWidth,\n canPaste: options.onPaste !== undefined,\n enableVerticalNavigation: options.enableVerticalNavigation,\n };\n}\n\nfunction applyCjkFlowSafely(\n options: IInputHandlerOptions,\n run: () => ReturnType<typeof applyCjkTextInput>,\n): void {\n try {\n const result = run();\n options.stateRef.current = result.state;\n applyCjkTextInputEffect(\n result.effect,\n options.onChange,\n options.onSubmit,\n options.onPaste,\n options.forceRender,\n );\n } catch {\n // Korean IME in raw mode can produce unexpected byte sequences.\n }\n}\n\nfunction applyCjkTextInputEffect(\n effect: ReturnType<typeof applyCjkTextInput>['effect'],\n onChange: (value: string) => void,\n onSubmit: ((value: string) => void) | undefined,\n onPaste: ((text: string, cursorPosition: number) => void) | undefined,\n forceRender: React.Dispatch<React.SetStateAction<number>>,\n): void {\n if (effect.type === 'change') {\n onChange(effect.value);\n } else if (effect.type === 'submit') {\n onSubmit?.(effect.value);\n } else if (effect.type === 'paste') {\n onPaste?.(effect.text, effect.cursor);\n } else if (effect.type === 'render') {\n forceRender((n) => n + 1);\n }\n}\n\n/** Render text with an inverse-style cursor at the correct position */\nfunction renderWithCursor(\n value: string,\n cursorOffset: number,\n placeholder: string,\n showCursor: boolean,\n): string {\n if (!showCursor) {\n return value.length > 0 ? value : placeholder ? chalk.gray(placeholder) : '';\n }\n\n if (value.length === 0) {\n if (placeholder.length > 0) {\n return chalk.inverse(placeholder[0]) + chalk.gray(placeholder.slice(1));\n }\n return chalk.inverse(' ');\n }\n\n const chars = [...value];\n let rendered = '';\n\n for (let i = 0; i < chars.length; i++) {\n const char = chars[i] ?? '';\n rendered += i === cursorOffset ? chalk.inverse(char) : char;\n }\n\n if (cursorOffset >= chars.length) {\n rendered += chalk.inverse(' ');\n }\n\n return rendered;\n}\n","/**\n * WaveText — renders text with a subtle wave color animation.\n * Groups of 3-4 characters share the same color, creating a soft flowing effect.\n * Colors stay in a narrow range (dim grays) to avoid harsh contrast.\n */\n\nimport React, { useState, useEffect } from 'react';\nimport { Text } from 'ink';\n\n// Subtle gray tones — minimal contrast, soft wave\nconst WAVE_COLORS = ['#666666', '#888888', '#aaaaaa', '#888888'] as const;\nconst INTERVAL_MS = 400;\nconst CHARS_PER_GROUP = 4;\n\ninterface IProps {\n text: string;\n}\n\nexport default function WaveText({ text }: IProps): React.ReactElement {\n const [tick, setTick] = useState(0);\n\n useEffect(() => {\n const timer = setInterval(() => {\n setTick((prev) => prev + 1);\n }, INTERVAL_MS);\n return () => clearInterval(timer);\n }, []);\n\n const chars = [...text];\n\n return (\n <Text>\n {chars.map((char, i) => {\n const group = Math.floor(i / CHARS_PER_GROUP);\n const colorIndex = (tick + group) % WAVE_COLORS.length;\n return (\n <Text key={i} color={WAVE_COLORS[colorIndex]}>\n {char}\n </Text>\n );\n })}\n </Text>\n );\n}\n","import React, { useState, useEffect } from 'react';\nimport { Box, Text, useStdout } from 'ink';\nimport type { ICommand } from '@robota-sdk/agent-framework';\n\ninterface IProps {\n /** Filtered list of commands to display */\n commands: ICommand[];\n /** Currently highlighted item index */\n selectedIndex: number;\n /** Whether to show the popup */\n visible: boolean;\n /** Whether showing subcommands (no slash prefix) */\n isSubcommandMode?: boolean;\n}\n\nconst MAX_VISIBLE = 8;\n// border(1×2) + paddingX(1×2) consumed by outer box\nconst OUTER_CHROME = 4;\nconst MIN_ROW_WIDTH = 40;\nconst NAME_COL_MAX = 20;\n\nfunction useRowWidth(): number {\n const { stdout } = useStdout();\n const measure = () => Math.max(MIN_ROW_WIDTH, (stdout.columns ?? 80) - OUTER_CHROME);\n const [width, setWidth] = useState(measure);\n\n useEffect(() => {\n const onResize = () => setWidth(measure());\n stdout.on('resize', onResize);\n return () => {\n stdout.off('resize', onResize);\n };\n }, [stdout]);\n\n return width;\n}\n\nfunction capName(name: string, colWidth: number): string {\n return name.length > colWidth ? `${name.slice(0, colWidth - 1)}…` : name.padEnd(colWidth);\n}\n\n/** Render a single command row */\nfunction CommandRow(props: {\n cmd: ICommand;\n isSelected: boolean;\n showSlash: boolean;\n rowWidth: number;\n nameColWidth: number;\n}): React.ReactElement {\n const { cmd, isSelected, showSlash, rowWidth, nameColWidth } = props;\n const indicator = isSelected ? '▸ ' : ' ';\n const nameColor = isSelected ? 'cyan' : undefined;\n const dimmed = !isSelected;\n const namePart = capName(cmd.name, nameColWidth);\n const text = showSlash\n ? `${indicator}/${namePart} ${cmd.description ?? ''}`\n : `${indicator}${namePart} ${cmd.description ?? ''}`;\n\n return (\n <Box width={rowWidth}>\n <Text color={nameColor} dimColor={dimmed} wrap=\"truncate-end\">\n {text}\n </Text>\n </Box>\n );\n}\n\n/** Autocomplete popup showing matching slash commands */\nexport default function SlashAutocomplete({\n commands,\n selectedIndex,\n visible,\n isSubcommandMode,\n}: IProps): React.ReactElement | null {\n const rowWidth = useRowWidth();\n\n if (!visible || commands.length === 0) return null;\n\n const scrollOffset = computeScrollOffset(selectedIndex, commands.length);\n const visibleCommands = commands.slice(scrollOffset, scrollOffset + MAX_VISIBLE);\n\n const nameColWidth = Math.min(\n NAME_COL_MAX,\n Math.max(...visibleCommands.map((c) => c.name.length)),\n );\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"gray\" paddingX={1}>\n {visibleCommands.map((cmd, i) => (\n <CommandRow\n key={cmd.name}\n cmd={cmd}\n isSelected={scrollOffset + i === selectedIndex}\n showSlash={!isSubcommandMode}\n rowWidth={rowWidth}\n nameColWidth={nameColWidth}\n />\n ))}\n </Box>\n );\n}\n\n/** Compute scroll offset to keep selectedIndex visible */\nfunction computeScrollOffset(selectedIndex: number, total: number): number {\n if (total <= MAX_VISIBLE) return 0;\n if (selectedIndex < MAX_VISIBLE) return 0;\n const maxOffset = total - MAX_VISIBLE;\n return Math.min(selectedIndex - MAX_VISIBLE + 1, maxOffset);\n}\n","import React, { useState } from 'react';\nimport { Box, Text, useInput, useStdout } from 'ink';\nimport type { ITuiPickerInteraction, ITuiPickerItem } from '../command-interaction.js';\n\ninterface IProps {\n commandName: string;\n interaction: ITuiPickerInteraction;\n onSelect: (item: ITuiPickerItem) => void;\n onCancel: () => void;\n}\n\nconst MAX_VISIBLE = 8;\nconst OUTER_CHROME = 4;\nconst MIN_ROW_WIDTH = 40;\n\nfunction useRowWidth(): number {\n const { stdout } = useStdout();\n return Math.max(MIN_ROW_WIDTH, (stdout.columns ?? 80) - OUTER_CHROME);\n}\n\nexport default function CommandPicker({\n commandName,\n interaction,\n onSelect,\n onCancel,\n}: IProps): React.ReactElement {\n const items = interaction.getItems();\n const [selectedIndex, setSelectedIndex] = useState(0);\n const rowWidth = useRowWidth();\n\n useInput((input, key) => {\n if (key.upArrow) {\n setSelectedIndex((i) => (i > 0 ? i - 1 : items.length - 1));\n } else if (key.downArrow) {\n setSelectedIndex((i) => (i < items.length - 1 ? i + 1 : 0));\n } else if (key.return) {\n const item = items[selectedIndex];\n if (item) onSelect(item);\n } else if (key.escape || input === 'q') {\n onCancel();\n }\n });\n\n const scrollOffset = (() => {\n if (items.length <= MAX_VISIBLE) return 0;\n if (selectedIndex < MAX_VISIBLE) return 0;\n return Math.min(selectedIndex - MAX_VISIBLE + 1, items.length - MAX_VISIBLE);\n })();\n const visibleItems = items.slice(scrollOffset, scrollOffset + MAX_VISIBLE);\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text bold color=\"cyan\">\n /{commandName}\n </Text>\n {visibleItems.map((item, i) => {\n const isSelected = scrollOffset + i === selectedIndex;\n const indicator = isSelected ? '▸ ' : ' ';\n return (\n <Box key={item.value} width={rowWidth}>\n <Text\n color={isSelected ? 'cyan' : undefined}\n dimColor={!isSelected}\n wrap=\"truncate-end\"\n >\n {indicator}\n {item.label}\n {item.description != null ? ` ${item.description}` : ''}\n </Text>\n </Box>\n );\n })}\n <Text dimColor>↑↓ navigate · Enter select · Esc cancel</Text>\n </Box>\n );\n}\n","import React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { ITuiConfirmInteraction } from '../command-interaction.js';\n\ninterface IProps {\n commandName: string;\n interaction: ITuiConfirmInteraction;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\nexport default function CommandConfirm({\n commandName,\n interaction,\n onConfirm,\n onCancel,\n}: IProps): React.ReactElement {\n useInput((input, key) => {\n if (key.return || input === 'y' || input === 'Y') {\n onConfirm();\n } else if (key.escape || input === 'n' || input === 'N') {\n onCancel();\n }\n });\n\n return (\n <Box paddingX={1}>\n <Text bold color=\"yellow\">\n /{commandName}:{' '}\n </Text>\n <Text>{interaction.message} </Text>\n <Text dimColor>[y/n]</Text>\n </Box>\n );\n}\n","const PASTE_LABEL_RE = /\\[Pasted text #(\\d+)(?: \\+\\d+ lines)?\\]/g;\n\n/**\n * Replace paste label placeholders with their original content from the store.\n * Labels that have no matching store entry are replaced with empty string.\n */\nexport function expandPasteLabels(text: string, store: Map<number, string>): string {\n return text.replace(PASTE_LABEL_RE, (_, id: string) => store.get(Number(id)) ?? '');\n}\n","/**\n * Slash command autocomplete hook.\n * Extracted from InputArea.tsx for single-responsibility.\n */\n\nimport React, { useState, useMemo } from 'react';\nimport type { CommandRegistry, ICommand } from '@robota-sdk/agent-framework';\n\n/** Parse input to determine autocomplete state */\nexport function parseSlashInput(value: string): {\n isSlash: boolean;\n parentCommand: string;\n filter: string;\n} {\n if (!value.startsWith('/')) return { isSlash: false, parentCommand: '', filter: '' };\n const afterSlash = value.slice(1);\n const spaceIndex = afterSlash.indexOf(' ');\n if (spaceIndex === -1) return { isSlash: true, parentCommand: '', filter: afterSlash };\n const parent = afterSlash.slice(0, spaceIndex);\n const rest = afterSlash.slice(spaceIndex + 1);\n return { isSlash: true, parentCommand: parent, filter: rest };\n}\n\n/** Hook: manage autocomplete state */\nexport function useAutocomplete(\n value: string,\n registry: CommandRegistry | undefined,\n): {\n showPopup: boolean;\n filteredCommands: ICommand[];\n selectedIndex: number;\n setSelectedIndex: React.Dispatch<React.SetStateAction<number>>;\n isSubcommandMode: boolean;\n setShowPopup: React.Dispatch<React.SetStateAction<boolean>>;\n} {\n const [selectedIndex, setSelectedIndex] = useState(0);\n const [dismissed, setDismissed] = useState(false);\n\n // Reset dismissed when input changes\n const prevValueRef = React.useRef(value);\n if (prevValueRef.current !== value) {\n prevValueRef.current = value;\n if (dismissed) setDismissed(false);\n }\n\n const parsed = parseSlashInput(value);\n const isSubcommandMode = parsed.isSlash && parsed.parentCommand.length > 0;\n\n const filteredCommands = useMemo(() => {\n if (!registry || !parsed.isSlash || dismissed) return [];\n if (isSubcommandMode) {\n const subs = registry.getSubcommands(parsed.parentCommand);\n if (subs.length === 0) return [];\n if (!parsed.filter) return subs;\n const lower = parsed.filter.toLowerCase();\n return subs.filter((c) => c.name.toLowerCase().startsWith(lower));\n }\n return registry.getCommands(parsed.filter);\n }, [registry, parsed.isSlash, parsed.parentCommand, parsed.filter, dismissed, isSubcommandMode]);\n\n const showPopup = parsed.isSlash && filteredCommands.length > 0 && !dismissed;\n\n // Clamp selectedIndex\n if (selectedIndex >= filteredCommands.length && filteredCommands.length > 0) {\n setSelectedIndex(filteredCommands.length - 1);\n }\n\n return {\n showPopup,\n filteredCommands,\n selectedIndex,\n setSelectedIndex,\n isSubcommandMode,\n setShowPopup: (val) => {\n if (typeof val === 'function') {\n setDismissed((prev) => {\n const nextVal = (val as (prev: boolean) => boolean)(!prev);\n return !nextVal;\n });\n } else {\n setDismissed(!val);\n }\n },\n };\n}\n","import type { IHistoryEntry, TUniversalValue } from '@robota-sdk/agent-core';\nimport type { ICommand } from '@robota-sdk/agent-framework';\nimport { parseSlashInput } from '../hooks/useAutocomplete.js';\nimport type { ITuiCommandInteraction } from '../command-interaction.js';\n\nexport interface IAutocompleteInputKey {\n upArrow?: boolean;\n downArrow?: boolean;\n escape?: boolean;\n tab?: boolean;\n backspace?: boolean;\n delete?: boolean;\n}\n\nexport type TAutocompletePopupAction = 'previous' | 'next' | 'close' | 'complete';\nexport type TPendingPromptInputAction = 'cancelQueue';\nexport type TPromptHistoryInputAction = 'previous' | 'next';\n\nexport type TCommandSelectionResult =\n | { type: 'insert'; value: string; selectedIndex?: number }\n | { type: 'submit'; value: string }\n | { type: 'open-interaction'; commandName: string };\n\nexport interface IPasteLabelChange {\n value: string;\n cursorHint: number;\n label: string;\n lineCount: number;\n}\n\nexport interface IPromptHistoryNavigationState {\n selectedIndex: number | null;\n draft: string;\n}\n\nexport interface IPromptHistoryNavigationResult {\n value: string;\n cursorHint: number;\n state: IPromptHistoryNavigationState;\n}\n\nexport function getAutocompletePopupAction(\n key: IAutocompleteInputKey,\n): TAutocompletePopupAction | undefined {\n if (key.upArrow === true) return 'previous';\n if (key.downArrow === true) return 'next';\n if (key.escape === true) return 'close';\n if (key.tab === true) return 'complete';\n return undefined;\n}\n\nexport function getPendingPromptInputAction(\n key: IAutocompleteInputKey,\n): TPendingPromptInputAction | undefined {\n if (key.backspace === true || key.delete === true) {\n return 'cancelQueue';\n }\n return undefined;\n}\n\nexport function getPromptHistoryInputAction(\n key: IAutocompleteInputKey,\n): TPromptHistoryInputAction | undefined {\n if (key.upArrow === true) return 'previous';\n if (key.downArrow === true) return 'next';\n return undefined;\n}\n\nexport function createPromptHistoryNavigationState(): IPromptHistoryNavigationState {\n return { selectedIndex: null, draft: '' };\n}\n\nexport function navigatePromptHistory(\n value: string,\n history: readonly string[],\n state: IPromptHistoryNavigationState,\n action: TPromptHistoryInputAction,\n): IPromptHistoryNavigationResult {\n if (history.length === 0) {\n return { value, cursorHint: value.length, state };\n }\n\n if (action === 'previous') {\n const selectedIndex =\n state.selectedIndex === null ? history.length - 1 : Math.max(0, state.selectedIndex - 1);\n const nextValue = history[selectedIndex] ?? value;\n return {\n value: nextValue,\n cursorHint: nextValue.length,\n state: { selectedIndex, draft: state.selectedIndex === null ? value : state.draft },\n };\n }\n\n if (state.selectedIndex === null) {\n return { value, cursorHint: value.length, state };\n }\n\n if (state.selectedIndex < history.length - 1) {\n const selectedIndex = state.selectedIndex + 1;\n const nextValue = history[selectedIndex] ?? value;\n return {\n value: nextValue,\n cursorHint: nextValue.length,\n state: { ...state, selectedIndex },\n };\n }\n\n return {\n value: state.draft,\n cursorHint: state.draft.length,\n state: createPromptHistoryNavigationState(),\n };\n}\n\nexport function appendPromptHistory(history: readonly string[], value: string): string[] {\n const prompt = value.trim();\n if (prompt.length === 0) return [...history];\n if (history[history.length - 1] === prompt) return [...history];\n return [...history, prompt];\n}\n\nexport function extractPromptHistory(entries: readonly IHistoryEntry[]): string[] {\n let prompts: string[] = [];\n for (const entry of entries) {\n if (entry.category !== 'chat' || entry.type !== 'user') continue;\n const data = entry.data as Record<string, TUniversalValue> | undefined;\n if (typeof data?.content !== 'string') continue;\n prompts = appendPromptHistory(prompts, data.content);\n }\n return prompts;\n}\n\nexport function moveAutocompleteSelection(\n selectedIndex: number,\n commandCount: number,\n direction: 'previous' | 'next',\n): number {\n if (commandCount === 0) return 0;\n if (direction === 'previous') {\n return selectedIndex > 0 ? selectedIndex - 1 : commandCount - 1;\n }\n return selectedIndex < commandCount - 1 ? selectedIndex + 1 : 0;\n}\n\nexport function resolveTabCompletion(value: string, command: ICommand): TCommandSelectionResult {\n const parsed = parseSlashInput(value);\n if (parsed.parentCommand) {\n return { type: 'insert', value: `/${parsed.parentCommand} ${command.name} ` };\n }\n if (command.subcommands && command.subcommands.length > 0) {\n return { type: 'insert', value: `/${command.name} `, selectedIndex: 0 };\n }\n return { type: 'insert', value: `/${command.name} ` };\n}\n\nexport function resolveEnterCommandSelection(\n value: string,\n command: ICommand,\n interaction?: ITuiCommandInteraction,\n): TCommandSelectionResult {\n const parsed = parseSlashInput(value);\n if (parsed.parentCommand) {\n return { type: 'submit', value: `/${parsed.parentCommand} ${command.name}` };\n }\n // parentCommand is empty → no args provided beyond the command name itself\n if (interaction?.onMissingArgs) {\n return { type: 'open-interaction', commandName: command.name };\n }\n if (command.subcommands && command.subcommands.length > 0) {\n return { type: 'insert', value: `/${command.name} `, selectedIndex: 0 };\n }\n return { type: 'submit', value: `/${command.name}` };\n}\n\nexport function createPasteLabelChange(\n value: string,\n cursorPosition: number,\n pasteId: number,\n text: string,\n): IPasteLabelChange {\n const lineCount = text.split('\\n').length;\n const label = `[Pasted text #${pasteId} +${lineCount} lines]`;\n return {\n value: value.slice(0, cursorPosition) + label + value.slice(cursorPosition),\n cursorHint: cursorPosition + label.length,\n label,\n lineCount,\n };\n}\n\nexport function shouldSubmitInput(text: string): boolean {\n return text.trim().length > 0;\n}\n","export type TOnMissingArgsAction = 'picker' | 'wizard' | 'confirm';\n\nexport interface ITuiPickerItem {\n label: string;\n value: string;\n description?: string;\n}\n\nexport interface ITuiCommandInteraction {\n onMissingArgs?: TOnMissingArgsAction;\n}\n\nexport interface ITuiPickerInteraction extends ITuiCommandInteraction {\n onMissingArgs: 'picker';\n getItems(): ITuiPickerItem[];\n}\n\nexport interface ITuiConfirmInteraction extends ITuiCommandInteraction {\n onMissingArgs: 'confirm';\n message: string;\n}\n\nexport type TAnyTuiCommandInteraction = ITuiPickerInteraction | ITuiConfirmInteraction;\n\nexport function isPickerInteraction(\n interaction: ITuiCommandInteraction,\n): interaction is ITuiPickerInteraction {\n return interaction.onMissingArgs === 'picker';\n}\n\nexport function isConfirmInteraction(\n interaction: ITuiCommandInteraction,\n): interaction is ITuiConfirmInteraction {\n return interaction.onMissingArgs === 'confirm';\n}\n","import React, { useState, useCallback, useRef, useMemo } from 'react';\n\nconst PENDING_PROMPT_DISPLAY_MAX = 50;\nconst PENDING_PROMPT_TAIL_KEEP = 47;\nimport { Box, Text, useInput, useWindowSize } from 'ink';\nimport type { IHistoryEntry } from '@robota-sdk/agent-core';\nimport type { CommandRegistry, ICommand } from '@robota-sdk/agent-framework';\nimport CjkTextInput from './CjkTextInput.js';\nimport WaveText from './WaveText.js';\nimport SlashAutocomplete from './SlashAutocomplete.js';\nimport CommandPicker from './interactions/CommandPicker.js';\nimport CommandConfirm from './interactions/CommandConfirm.js';\nimport { expandPasteLabels } from './utils/paste-labels.js';\nimport { useAutocomplete } from './hooks/useAutocomplete.js';\nimport {\n appendPromptHistory,\n createPasteLabelChange,\n createPromptHistoryNavigationState,\n extractPromptHistory,\n getAutocompletePopupAction,\n getPendingPromptInputAction,\n getPromptHistoryInputAction,\n moveAutocompleteSelection,\n navigatePromptHistory,\n resolveEnterCommandSelection,\n resolveTabCompletion,\n shouldSubmitInput,\n} from './flows/input-area-flow.js';\nimport {\n isPickerInteraction,\n isConfirmInteraction,\n type ITuiCommandInteraction,\n type ITuiPickerItem,\n} from './command-interaction.js';\n\ninterface IActiveInteraction {\n commandName: string;\n interaction: ITuiCommandInteraction;\n}\n\ninterface IProps {\n onSubmit: (value: string) => void;\n onCancelQueue?: () => void;\n isDisabled: boolean;\n isAborting?: boolean;\n pendingPrompt?: string | null;\n registry?: CommandRegistry;\n sessionName?: string;\n history?: readonly IHistoryEntry[];\n resolveInteraction?: (commandName: string) => ITuiCommandInteraction | undefined;\n}\n\n/**\n * Known limitation: Korean IME last character may be dropped on Enter.\n * This is an Ink raw mode limitation — no compositionstart/compositionend\n * events are available in terminal raw mode.\n * Reference: https://github.com/anthropics/claude-code/issues/3045\n */\n/**\n * Layout constants for InputArea border box (columns).\n * Used to compute available text width from terminal columns.\n *\n * Box borderStyle=\"single\" adds 1 column per side (left + right).\n * paddingLeft={1} adds 1 column inside the box.\n * Prompt \"> \" takes 2 columns.\n */\nconst BORDER_HORIZONTAL = 2;\nconst PADDING_LEFT = 1;\nconst PROMPT_WIDTH = 2;\nconst INPUT_AREA_OVERHEAD = BORDER_HORIZONTAL + PADDING_LEFT + PROMPT_WIDTH;\nconst DEFAULT_TERMINAL_COLUMNS = 80;\n\nexport default function InputArea({\n onSubmit,\n onCancelQueue,\n isDisabled,\n isAborting,\n pendingPrompt,\n registry,\n sessionName,\n history,\n resolveInteraction,\n}: IProps): React.ReactElement {\n const [value, setValue] = useState('');\n const [cursorHint, setCursorHint] = useState<number | null>(null);\n const [activeInteraction, setActiveInteraction] = useState<IActiveInteraction | null>(null);\n const [historyState, setHistoryState] = useState(createPromptHistoryNavigationState);\n const [localPromptHistory, setLocalPromptHistory] = useState<string[]>([]);\n const restoredPromptHistory = useMemo(() => extractPromptHistory(history ?? []), [history]);\n const promptHistory = useMemo(\n () =>\n localPromptHistory.reduce<string[]>(\n (prompts, prompt) => appendPromptHistory(prompts, prompt),\n restoredPromptHistory,\n ),\n [restoredPromptHistory, localPromptHistory],\n );\n const pasteStore = useRef<Map<number, string>>(new Map());\n const { columns } = useWindowSize();\n const terminalColumns = columns > 0 ? columns : DEFAULT_TERMINAL_COLUMNS;\n const availableWidth = Math.max(1, terminalColumns - INPUT_AREA_OVERHEAD);\n const pasteIdRef = useRef(0);\n\n const {\n showPopup,\n filteredCommands,\n selectedIndex,\n setSelectedIndex,\n isSubcommandMode,\n setShowPopup,\n } = useAutocomplete(value, registry);\n\n const handlePaste = useCallback((text: string, cursorPosition: number) => {\n pasteIdRef.current += 1;\n const id = pasteIdRef.current;\n pasteStore.current.set(id, text);\n setValue((prev) => {\n const change = createPasteLabelChange(prev, cursorPosition, id, text);\n setCursorHint(change.cursorHint);\n return change.value;\n });\n }, []);\n\n const resetHistoryNavigation = useCallback(() => {\n setHistoryState(createPromptHistoryNavigationState());\n }, []);\n\n const recordPromptHistory = useCallback((prompt: string): void => {\n setLocalPromptHistory((prev) => appendPromptHistory(prev, prompt));\n }, []);\n\n const submitPrompt = useCallback(\n (prompt: string): void => {\n recordPromptHistory(prompt);\n resetHistoryNavigation();\n onSubmit(prompt);\n },\n [onSubmit, recordPromptHistory, resetHistoryNavigation],\n );\n\n /** Tab: insert command into input field without executing */\n const tabCompleteCommand = useCallback(\n (cmd: ICommand): void => {\n const result = resolveTabCompletion(value, cmd);\n if (result.type === 'insert') {\n setValue(result.value);\n if (result.selectedIndex !== undefined) {\n setSelectedIndex(result.selectedIndex);\n }\n }\n },\n [value, setSelectedIndex],\n );\n\n /** Enter: insert and execute command immediately */\n const enterSelectCommand = useCallback(\n (cmd: ICommand): void => {\n const interaction = resolveInteraction?.(cmd.name);\n const result = resolveEnterCommandSelection(value, cmd, interaction);\n if (result.type === 'insert') {\n setValue(result.value);\n if (result.selectedIndex !== undefined) {\n setSelectedIndex(result.selectedIndex);\n }\n return;\n }\n if (result.type === 'open-interaction' && interaction?.onMissingArgs) {\n setShowPopup(false);\n setActiveInteraction({ commandName: result.commandName, interaction });\n return;\n }\n if (result.type === 'submit') {\n setValue('');\n submitPrompt(result.value);\n }\n },\n [value, submitPrompt, setSelectedIndex, resolveInteraction, setShowPopup],\n );\n\n const handleSubmit = useCallback(\n (text: string): void => {\n if (!shouldSubmitInput(text)) return;\n\n if (showPopup && filteredCommands[selectedIndex]) {\n enterSelectCommand(filteredCommands[selectedIndex]);\n return;\n }\n\n // Expand paste labels before submitting\n const expanded = expandPasteLabels(text.trim(), pasteStore.current);\n\n setValue('');\n // Reset paste state\n pasteStore.current.clear();\n pasteIdRef.current = 0;\n\n submitPrompt(expanded);\n },\n [showPopup, filteredCommands, selectedIndex, enterSelectCommand, submitPrompt],\n );\n\n useInput(\n (\n _input: string,\n key: { upArrow: boolean; downArrow: boolean; escape: boolean; tab: boolean },\n ) => {\n if (!showPopup) return;\n const action = getAutocompletePopupAction(key);\n if (action === 'previous' || action === 'next') {\n setSelectedIndex((prev) =>\n moveAutocompleteSelection(prev, filteredCommands.length, action),\n );\n } else if (action === 'close') {\n setShowPopup(false);\n } else if (action === 'complete') {\n const cmd = filteredCommands[selectedIndex];\n if (cmd) tabCompleteCommand(cmd);\n }\n },\n { isActive: showPopup && !isDisabled },\n );\n\n useInput(\n (_input, key) => {\n const action = getPromptHistoryInputAction(key);\n if (!action) return;\n const result = navigatePromptHistory(value, promptHistory, historyState, action);\n setValue(result.value);\n setCursorHint(result.cursorHint);\n setHistoryState(result.state);\n },\n { isActive: !showPopup && !isDisabled && !pendingPrompt },\n );\n\n // Backspace cancels queued prompt\n useInput(\n (_input, key) => {\n if (getPendingPromptInputAction(key) === 'cancelQueue' && pendingPrompt) {\n onCancelQueue?.();\n }\n },\n { isActive: !!pendingPrompt },\n );\n\n const borderColor = isAborting\n ? 'yellow'\n : pendingPrompt\n ? 'cyan'\n : isDisabled\n ? 'gray'\n : 'green';\n const innerWidth = Math.max(1, terminalColumns - BORDER_HORIZONTAL);\n\n // Build top border with optional session name title (right-aligned, 2 chars from edge)\n const topBorder = (() => {\n if (sessionName) {\n const label = ` \"${sessionName}\" `;\n const rightPad = 2;\n const leftLen = Math.max(0, innerWidth - label.length - rightPad);\n return { left: '┌' + '─'.repeat(leftLen), label, right: '─'.repeat(rightPad) + '┐' };\n }\n return { left: '┌' + '─'.repeat(innerWidth), label: '', right: '┐' };\n })();\n\n const handlePickerSelect = useCallback(\n (item: ITuiPickerItem): void => {\n if (!activeInteraction) return;\n setActiveInteraction(null);\n submitPrompt(`/${activeInteraction.commandName} ${item.value}`);\n },\n [activeInteraction, submitPrompt],\n );\n\n const handleConfirm = useCallback((): void => {\n if (!activeInteraction) return;\n setActiveInteraction(null);\n submitPrompt(`/${activeInteraction.commandName}`);\n }, [activeInteraction, submitPrompt]);\n\n const handleInteractionCancel = useCallback((): void => {\n setActiveInteraction(null);\n }, []);\n\n return (\n <Box flexDirection=\"column\">\n {activeInteraction && isPickerInteraction(activeInteraction.interaction) && (\n <CommandPicker\n commandName={activeInteraction.commandName}\n interaction={activeInteraction.interaction}\n onSelect={handlePickerSelect}\n onCancel={handleInteractionCancel}\n />\n )}\n {activeInteraction && isConfirmInteraction(activeInteraction.interaction) && (\n <CommandConfirm\n commandName={activeInteraction.commandName}\n interaction={activeInteraction.interaction}\n onConfirm={handleConfirm}\n onCancel={handleInteractionCancel}\n />\n )}\n {!activeInteraction && showPopup && (\n <SlashAutocomplete\n commands={filteredCommands}\n selectedIndex={selectedIndex}\n visible={showPopup}\n isSubcommandMode={isSubcommandMode}\n />\n )}\n <Text color={borderColor}>\n {topBorder.left}\n {topBorder.label ? (\n <Text backgroundColor={borderColor} color=\"black\" bold>\n {topBorder.label}\n </Text>\n ) : null}\n {topBorder.right}\n </Text>\n <Box borderStyle=\"single\" borderTop={false} borderColor={borderColor} paddingLeft={1}>\n {isAborting ? (\n <Text color=\"yellow\"> Interrupting...</Text>\n ) : pendingPrompt ? (\n <Text color=\"cyan\">\n {' '}\n Queued:{' '}\n {pendingPrompt.length > PENDING_PROMPT_DISPLAY_MAX\n ? pendingPrompt.slice(0, PENDING_PROMPT_TAIL_KEEP) + '...'\n : pendingPrompt}{' '}\n <Text dimColor>(Backspace to cancel)</Text>\n </Text>\n ) : isDisabled ? (\n <WaveText text=\" Waiting for response... (ESC to interrupt)\" />\n ) : (\n <Box>\n <Text color=\"green\" bold>\n {'> '}\n </Text>\n <CjkTextInput\n value={value}\n onChange={(v) => {\n setValue(v);\n resetHistoryNavigation();\n setCursorHint(null); // reset after normal typing\n }}\n onSubmit={handleSubmit}\n onPaste={handlePaste}\n placeholder=\"Type a message or /help\"\n availableWidth={availableWidth}\n cursorHint={cursorHint}\n enableVerticalNavigation={false}\n />\n </Box>\n )}\n </Box>\n </Box>\n );\n}\n","export interface ISelectionFlowState {\n selectedIndex: number;\n scrollOffset: number;\n resolved: boolean;\n}\n\nexport interface ISelectionInputKey {\n escape?: boolean;\n return?: boolean;\n upArrow?: boolean;\n downArrow?: boolean;\n leftArrow?: boolean;\n rightArrow?: boolean;\n}\n\nexport type TSelectionInputAction = 'cancel' | 'select' | 'previous' | 'next';\n\nexport type TSelectionEffect =\n | { type: 'none' }\n | { type: 'cancel' }\n | { type: 'select'; index: number };\n\nexport interface ISelectionFlowOptions {\n itemCount: number;\n maxVisible?: number;\n wrap?: boolean;\n enabled?: boolean;\n}\n\nexport function createSelectionFlowState(): ISelectionFlowState {\n return { selectedIndex: 0, scrollOffset: 0, resolved: false };\n}\n\nexport function getVerticalSelectionInputAction(\n key: ISelectionInputKey,\n): TSelectionInputAction | undefined {\n if (key.escape === true) return 'cancel';\n if (key.upArrow === true) return 'previous';\n if (key.downArrow === true) return 'next';\n if (key.return === true) return 'select';\n return undefined;\n}\n\nexport function getDirectionalSelectionInputAction(\n key: ISelectionInputKey,\n): TSelectionInputAction | undefined {\n if (key.escape === true) return 'cancel';\n if (key.leftArrow === true || key.upArrow === true) return 'previous';\n if (key.rightArrow === true || key.downArrow === true) return 'next';\n if (key.return === true) return 'select';\n return undefined;\n}\n\nexport function applySelectionInput(\n state: ISelectionFlowState,\n action: TSelectionInputAction,\n options: ISelectionFlowOptions,\n): { state: ISelectionFlowState; effect: TSelectionEffect } {\n if (state.resolved) {\n return { state, effect: { type: 'none' } };\n }\n if (action === 'cancel') {\n return { state: { ...state, resolved: true }, effect: { type: 'cancel' } };\n }\n if (options.enabled === false || options.itemCount === 0) {\n return { state, effect: { type: 'none' } };\n }\n if (action === 'select') {\n const index = clampIndex(state.selectedIndex, options.itemCount);\n return {\n state: { ...state, selectedIndex: index, resolved: true },\n effect: { type: 'select', index },\n };\n }\n const selectedIndex = moveSelection(state.selectedIndex, action, options);\n const scrollOffset = resolveScrollOffset(selectedIndex, state.scrollOffset, options);\n return { state: { ...state, selectedIndex, scrollOffset }, effect: { type: 'none' } };\n}\n\nexport function normalizeSelectionState(\n state: ISelectionFlowState,\n options: ISelectionFlowOptions,\n): ISelectionFlowState {\n if (options.itemCount === 0) {\n return { ...state, selectedIndex: 0, scrollOffset: 0 };\n }\n const selectedIndex = clampIndex(state.selectedIndex, options.itemCount);\n const scrollOffset = resolveScrollOffset(selectedIndex, state.scrollOffset, options);\n if (selectedIndex === state.selectedIndex && scrollOffset === state.scrollOffset) {\n return state;\n }\n return {\n ...state,\n selectedIndex,\n scrollOffset,\n };\n}\n\nfunction moveSelection(\n selectedIndex: number,\n action: TSelectionInputAction,\n options: ISelectionFlowOptions,\n): number {\n if (action === 'previous') {\n if (options.wrap === true && selectedIndex === 0) return options.itemCount - 1;\n return Math.max(0, selectedIndex - 1);\n }\n if (options.wrap === true && selectedIndex === options.itemCount - 1) return 0;\n return Math.min(options.itemCount - 1, selectedIndex + 1);\n}\n\nfunction resolveScrollOffset(\n selectedIndex: number,\n scrollOffset: number,\n options: ISelectionFlowOptions,\n): number {\n const maxVisible = options.maxVisible ?? options.itemCount;\n if (maxVisible <= 0) return 0;\n if (selectedIndex < scrollOffset) return selectedIndex;\n if (selectedIndex >= scrollOffset + maxVisible) return selectedIndex - maxVisible + 1;\n return Math.max(0, scrollOffset);\n}\n\nfunction clampIndex(index: number, itemCount: number): number {\n return Math.min(Math.max(index, 0), itemCount - 1);\n}\n","import {\n applySelectionInput,\n getDirectionalSelectionInputAction,\n type ISelectionFlowState,\n type ISelectionInputKey,\n type TSelectionEffect,\n type TSelectionInputAction,\n} from './selection-flow.js';\n\nexport type TConfirmPromptInputAction = TSelectionInputAction | { type: 'shortcut'; index: number };\n\nexport function getConfirmPromptInputAction(\n input: string,\n key: ISelectionInputKey,\n optionCount: number,\n): TConfirmPromptInputAction | undefined {\n const action = getDirectionalSelectionInputAction({ ...key, escape: false });\n if (action !== undefined) {\n return action;\n }\n if (optionCount === 2 && input === 'y') {\n return { type: 'shortcut', index: 0 };\n }\n if (optionCount === 2 && input === 'n') {\n return { type: 'shortcut', index: 1 };\n }\n return undefined;\n}\n\nexport function applyConfirmPromptInput(\n state: ISelectionFlowState,\n action: TConfirmPromptInputAction,\n optionCount: number,\n): { state: ISelectionFlowState; effect: TSelectionEffect } {\n if (state.resolved) {\n return { state, effect: { type: 'none' } };\n }\n if (typeof action !== 'string') {\n return {\n state: { ...state, selectedIndex: action.index, resolved: true },\n effect: { type: 'select', index: action.index },\n };\n }\n return applySelectionInput(state, action, { itemCount: optionCount });\n}\n","/**\n * Reusable confirmation prompt with arrow-key selection.\n * Used by model change, permission prompts, and other yes/no confirmations.\n */\n\nimport React, { useState, useRef, useCallback } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n applyConfirmPromptInput,\n getConfirmPromptInputAction,\n type TConfirmPromptInputAction,\n} from './flows/confirm-prompt-flow.js';\nimport { createSelectionFlowState, type ISelectionFlowState } from './flows/selection-flow.js';\n\ninterface IProps {\n /** Message to display above the options */\n message: string;\n /** Options to select from (default: ['Yes', 'No']) */\n options?: string[];\n /** Callback with the selected index */\n onSelect: (index: number) => void;\n}\n\nexport default function ConfirmPrompt({\n message,\n options = ['Yes', 'No'],\n onSelect,\n}: IProps): React.ReactElement {\n const [state, setState] = useState<ISelectionFlowState>(() => createSelectionFlowState());\n const stateRef = useRef(state);\n const applyAction = useCallback(\n (action: TConfirmPromptInputAction): void => {\n const result = applyConfirmPromptInput(stateRef.current, action, options.length);\n stateRef.current = result.state;\n setState(result.state);\n if (result.effect.type === 'select') {\n onSelect(result.effect.index);\n }\n },\n [onSelect, options.length],\n );\n\n useInput((input, key) => {\n const action = getConfirmPromptInputAction(input, key, options.length);\n if (action !== undefined) {\n applyAction(action);\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\">{message}</Text>\n <Box marginTop={1}>\n {options.map((opt, i) => (\n <Box key={opt} marginRight={2}>\n <Text\n color={i === state.selectedIndex ? 'cyan' : undefined}\n bold={i === state.selectedIndex}\n >\n {i === state.selectedIndex ? '> ' : ' '}\n {opt}\n </Text>\n </Box>\n ))}\n </Box>\n <Text dimColor> arrow keys to select, Enter to confirm</Text>\n </Box>\n );\n}\n","/**\n * Generic list picker with arrow-key navigation and viewport scrolling.\n * Renders items via a user-supplied renderItem function.\n * Shows a limited number of items at a time; scrolls as the cursor moves.\n */\n\nimport React, { useState, useRef, useCallback } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n applySelectionInput,\n createSelectionFlowState,\n getVerticalSelectionInputAction,\n normalizeSelectionState,\n type ISelectionFlowState,\n type TSelectionInputAction,\n} from './flows/selection-flow.js';\n\n/** Default number of visible items */\nconst DEFAULT_MAX_VISIBLE = 3;\n\nexport interface IListPickerProps<T> {\n /** Items to display in the list */\n items: T[];\n /** Render function for each item — receives the item and whether it is currently selected */\n renderItem: (item: T, isSelected: boolean) => React.ReactElement;\n /** Called when the user presses Enter on the highlighted item */\n onSelect: (item: T) => void;\n /** Called when the user presses Escape */\n onCancel: () => void;\n /** Maximum number of items visible at once (default: 10) */\n maxVisible?: number;\n}\n\nexport default function ListPicker<T>({\n items,\n renderItem,\n onSelect,\n onCancel,\n maxVisible = DEFAULT_MAX_VISIBLE,\n}: IListPickerProps<T>): React.ReactElement {\n const [state, setState] = useState<ISelectionFlowState>(() => createSelectionFlowState());\n const stateRef = useRef(state);\n const applyAction = useCallback(\n (action: TSelectionInputAction): void => {\n const result = applySelectionInput(stateRef.current, action, {\n itemCount: items.length,\n maxVisible,\n });\n stateRef.current = result.state;\n setState(result.state);\n if (result.effect.type === 'cancel') {\n onCancel();\n } else if (result.effect.type === 'select') {\n const item = items[result.effect.index];\n if (item !== undefined) {\n onSelect(item);\n }\n }\n },\n [items, maxVisible, onCancel, onSelect],\n );\n\n useInput((_input, key) => {\n const action = getVerticalSelectionInputAction(key);\n if (action !== undefined) {\n applyAction(action);\n }\n });\n\n if (items.length === 0) {\n return <Box />;\n }\n\n const normalizedState = normalizeSelectionState(state, { itemCount: items.length, maxVisible });\n if (normalizedState !== state) {\n stateRef.current = normalizedState;\n }\n const { selectedIndex, scrollOffset } = normalizedState;\n const visibleItems = items.slice(scrollOffset, scrollOffset + maxVisible);\n const hasMore = scrollOffset + maxVisible < items.length;\n const hasLess = scrollOffset > 0;\n\n return (\n <Box flexDirection=\"column\">\n {hasLess && <Text dimColor> ↑ {scrollOffset} more above</Text>}\n {visibleItems.map((item, index) => (\n <Box key={scrollOffset + index} marginBottom={1}>\n {renderItem(item, scrollOffset + index === selectedIndex)}\n </Box>\n ))}\n {hasMore && <Text dimColor> ↓ {items.length - scrollOffset - maxVisible} more below</Text>}\n </Box>\n );\n}\n","export interface ITextPromptFlowState {\n value: string;\n error?: string;\n resolved: boolean;\n}\n\nexport interface ITextPromptInputKey {\n escape?: boolean;\n return?: boolean;\n backspace?: boolean;\n delete?: boolean;\n ctrl?: boolean;\n meta?: boolean;\n}\n\nexport type TTextPromptInputAction =\n | { type: 'cancel' }\n | { type: 'submit' }\n | { type: 'delete' }\n | { type: 'insert'; value: string };\n\nexport type TTextPromptEffect =\n | { type: 'none' }\n | { type: 'cancel' }\n | { type: 'submit'; value: string };\n\nexport interface ITextPromptFlowOptions {\n allowEmpty: boolean;\n validate?: (value: string) => string | undefined;\n}\n\nexport function createTextPromptFlowState(): ITextPromptFlowState {\n return { value: '', resolved: false };\n}\n\nexport function getTextPromptInputAction(\n input: string,\n key: ITextPromptInputKey,\n): TTextPromptInputAction | undefined {\n if (key.escape === true) {\n return { type: 'cancel' };\n }\n if (key.return === true) {\n return { type: 'submit' };\n }\n if (key.backspace === true || key.delete === true) {\n return { type: 'delete' };\n }\n if (input && key.ctrl !== true && key.meta !== true) {\n return { type: 'insert', value: input };\n }\n return undefined;\n}\n\nexport function applyTextPromptInput(\n state: ITextPromptFlowState,\n action: TTextPromptInputAction,\n options: ITextPromptFlowOptions,\n): { state: ITextPromptFlowState; effect: TTextPromptEffect } {\n if (state.resolved) {\n return { state, effect: { type: 'none' } };\n }\n if (action.type === 'cancel') {\n return { state: { ...state, resolved: true }, effect: { type: 'cancel' } };\n }\n if (action.type === 'delete') {\n return {\n state: { ...state, value: state.value.slice(0, -1), error: undefined },\n effect: { type: 'none' },\n };\n }\n if (action.type === 'insert') {\n return {\n state: { ...state, value: state.value + action.value, error: undefined },\n effect: { type: 'none' },\n };\n }\n return submitTextPromptValue(state, options);\n}\n\nfunction submitTextPromptValue(\n state: ITextPromptFlowState,\n options: ITextPromptFlowOptions,\n): { state: ITextPromptFlowState; effect: TTextPromptEffect } {\n const trimmed = state.value.trim();\n if (!trimmed && !options.allowEmpty) {\n const emptyError = options.validate?.(trimmed);\n return {\n state: emptyError ? { ...state, error: emptyError } : state,\n effect: { type: 'none' },\n };\n }\n const error = options.validate?.(trimmed);\n if (error !== undefined) {\n return { state: { ...state, error }, effect: { type: 'none' } };\n }\n return { state: { ...state, resolved: true }, effect: { type: 'submit', value: trimmed } };\n}\n","import React, { useState, useRef, useCallback } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n applyTextPromptInput,\n createTextPromptFlowState,\n getTextPromptInputAction,\n type ITextPromptFlowState,\n type TTextPromptInputAction,\n} from './flows/text-prompt-flow.js';\n\ninterface IProps {\n title: string;\n description?: string;\n placeholder?: string;\n onSubmit: (value: string) => void;\n onCancel: () => void;\n validate?: (value: string) => string | undefined;\n allowEmpty?: boolean;\n masked?: boolean;\n}\n\nexport default function TextPrompt({\n title,\n description,\n placeholder,\n onSubmit,\n onCancel,\n validate,\n allowEmpty = false,\n masked = false,\n}: IProps): React.ReactElement {\n const [state, setState] = useState<ITextPromptFlowState>(() => createTextPromptFlowState());\n const stateRef = useRef(state);\n const applyAction = useCallback(\n (action: TTextPromptInputAction): void => {\n const result = applyTextPromptInput(stateRef.current, action, { allowEmpty, validate });\n stateRef.current = result.state;\n setState(result.state);\n if (result.effect.type === 'cancel') {\n onCancel();\n } else if (result.effect.type === 'submit') {\n onSubmit(result.effect.value);\n }\n },\n [allowEmpty, validate, onCancel, onSubmit],\n );\n\n useInput((input, key) => {\n const action = getTextPromptInputAction(input, key);\n if (action !== undefined) applyAction(action);\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\" bold>\n {title}\n </Text>\n <PromptDescription description={description} />\n <Box marginTop={1}>\n <Text color=\"cyan\">&gt; </Text>\n {state.value ? (\n <Text>{masked ? '*'.repeat(state.value.length) : state.value}</Text>\n ) : placeholder ? (\n <Text dimColor>{placeholder}</Text>\n ) : null}\n <Text color=\"cyan\">█</Text>\n </Box>\n {state.error && <Text color=\"red\">{state.error}</Text>}\n <Text dimColor> Enter Submit Esc Cancel</Text>\n </Box>\n );\n}\n\nfunction PromptDescription({ description }: { description?: string }): React.ReactElement | null {\n if (description === undefined || description.length === 0) {\n return null;\n }\n\n return <Text dimColor>{description}</Text>;\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type {\n TCommandInteractionPrompt as TInteractivePrompt,\n ICommandChoicePromptOption as IChoicePromptOption,\n} from '@robota-sdk/agent-framework';\nimport ListPicker from './ListPicker.js';\nimport TextPrompt from './TextPrompt.js';\n\ninterface IInteractivePromptProps {\n prompt: TInteractivePrompt;\n onSubmit: (value: string) => void;\n onCancel: () => void;\n}\n\nexport default function InteractivePrompt({\n prompt,\n onSubmit,\n onCancel,\n}: IInteractivePromptProps): React.ReactElement {\n if (prompt.kind === 'text') {\n return (\n <TextPrompt\n key={`text:${prompt.title}`}\n title={prompt.title}\n description={prompt.description}\n placeholder={prompt.placeholder}\n allowEmpty={prompt.allowEmpty}\n masked={prompt.masked}\n validate={prompt.validate}\n onSubmit={onSubmit}\n onCancel={onCancel}\n />\n );\n }\n\n return (\n <Box flexDirection=\"column\">\n <Text bold>{prompt.title}</Text>\n {prompt.description !== undefined && prompt.description.length > 0 && (\n <Text dimColor>{prompt.description}</Text>\n )}\n <ListPicker<IChoicePromptOption>\n items={[...prompt.options]}\n maxVisible={prompt.maxVisible}\n renderItem={(option, isSelected) => (\n <Text color={isSelected ? 'cyan' : undefined}>\n {isSelected ? '> ' : ' '}\n {option.label}\n </Text>\n )}\n onSelect={(option) => onSubmit(option.value)}\n onCancel={onCancel}\n />\n </Box>\n );\n}\n","import {\n applySelectionInput,\n getDirectionalSelectionInputAction,\n type ISelectionFlowState,\n type ISelectionInputKey,\n type TSelectionInputAction,\n} from './selection-flow.js';\n\nexport const PERMISSION_PROMPT_OPTIONS = ['Allow', 'Allow always (this session)', 'Deny'] as const;\n\nexport type TPermissionPromptDecision = true | 'allow-session' | false;\nexport type TPermissionPromptInputAction =\n | TSelectionInputAction\n | { type: 'shortcut'; index: number };\n\nexport type TPermissionPromptEffect =\n | { type: 'none' }\n | { type: 'resolve'; decision: TPermissionPromptDecision };\n\nexport function getPermissionPromptInputAction(\n input: string,\n key: ISelectionInputKey,\n): TPermissionPromptInputAction | undefined {\n const action = getDirectionalSelectionInputAction({ ...key, escape: false });\n if (action !== undefined) {\n return action;\n }\n if (input === 'y' || input === '1') {\n return { type: 'shortcut', index: 0 };\n }\n if (input === 'a' || input === '2') {\n return { type: 'shortcut', index: 1 };\n }\n if (input === 'n' || input === 'd' || input === '3') {\n return { type: 'shortcut', index: 2 };\n }\n return undefined;\n}\n\nexport function applyPermissionPromptInput(\n state: ISelectionFlowState,\n action: TPermissionPromptInputAction,\n): { state: ISelectionFlowState; effect: TPermissionPromptEffect } {\n if (state.resolved) {\n return { state, effect: { type: 'none' } };\n }\n if (typeof action !== 'string') {\n return resolvePermissionIndex(state, action.index);\n }\n const result = applySelectionInput(state, action, {\n itemCount: PERMISSION_PROMPT_OPTIONS.length,\n });\n if (result.effect.type !== 'select') {\n return { state: result.state, effect: { type: 'none' } };\n }\n return {\n state: result.state,\n effect: { type: 'resolve', decision: getPermissionDecision(result.effect.index) },\n };\n}\n\nexport function getPermissionDecision(index: number): TPermissionPromptDecision {\n if (index === 0) return true;\n if (index === 1) return 'allow-session';\n return false;\n}\n\nfunction resolvePermissionIndex(\n state: ISelectionFlowState,\n index: number,\n): { state: ISelectionFlowState; effect: TPermissionPromptEffect } {\n return {\n state: { ...state, selectedIndex: index, resolved: true },\n effect: { type: 'resolve', decision: getPermissionDecision(index) },\n };\n}\n","import React from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type { IPermissionRequest } from './types.js';\nimport type { TToolArgs } from '@robota-sdk/agent-core';\nimport {\n applyPermissionPromptInput,\n getPermissionPromptInputAction,\n PERMISSION_PROMPT_OPTIONS,\n type TPermissionPromptInputAction,\n} from './flows/permission-prompt-flow.js';\nimport { createSelectionFlowState, type ISelectionFlowState } from './flows/selection-flow.js';\n\ninterface IProps {\n request: IPermissionRequest;\n}\n\nfunction formatArgs(args: TToolArgs): string {\n const entries = Object.entries(args);\n if (entries.length === 0) return '(no arguments)';\n return entries\n .map(([k, v]) => `${k}: ${typeof v === 'string' ? v : JSON.stringify(v)}`)\n .join(', ');\n}\n\nexport default function PermissionPrompt({ request }: IProps): React.ReactElement {\n const [state, setState] = React.useState<ISelectionFlowState>(() => createSelectionFlowState());\n const stateRef = React.useRef(state);\n const prevRequestRef = React.useRef(request);\n\n if (prevRequestRef.current !== request) {\n prevRequestRef.current = request;\n const nextState = createSelectionFlowState();\n stateRef.current = nextState;\n setState(nextState);\n }\n\n const applyAction = React.useCallback(\n (action: TPermissionPromptInputAction): void => {\n const result = applyPermissionPromptInput(stateRef.current, action);\n stateRef.current = result.state;\n setState(result.state);\n if (result.effect.type === 'resolve') {\n request.resolve(result.effect.decision);\n }\n },\n [request],\n );\n\n useInput((input, key) => {\n const action = getPermissionPromptInputAction(input, key);\n if (action !== undefined) {\n applyAction(action);\n }\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\" bold>\n [Permission Required]\n </Text>\n <Text>\n Tool:{' '}\n <Text color=\"cyan\" bold>\n {request.toolName}\n </Text>\n </Text>\n <Text dimColor> {formatArgs(request.toolArgs)}</Text>\n <Box marginTop={1}>\n {PERMISSION_PROMPT_OPTIONS.map((opt, i) => (\n <Box key={opt} marginRight={2}>\n <Text\n color={i === state.selectedIndex ? 'cyan' : undefined}\n bold={i === state.selectedIndex}\n >\n {i === state.selectedIndex ? '> ' : ' '}\n {opt}\n </Text>\n </Box>\n ))}\n </Box>\n <Text dimColor> left/right to select, Enter to confirm</Text>\n </Box>\n );\n}\n","/**\n * Streaming indicator — shows real-time tool execution and AI response text.\n * Displayed during session.run() execution.\n */\n\nimport React from 'react';\nimport { Box, Text } from 'ink';\nimport type { IToolState } from '@robota-sdk/agent-framework';\nimport { renderMarkdown } from './render-markdown.js';\nimport ToolDiffBlock from './ToolDiffBlock.js';\n\nfunction getToolStyle(t: IToolState): {\n color: string;\n icon: string;\n strikethrough: boolean;\n} {\n if (t.isRunning) return { color: 'yellow', icon: '⟳', strikethrough: false };\n if (t.result === 'error') return { color: 'red', icon: '✗', strikethrough: true };\n if (t.result === 'denied') return { color: 'yellowBright', icon: '⊘', strikethrough: true };\n return { color: 'green', icon: '✓', strikethrough: false };\n}\n\ninterface IProps {\n text: string;\n activeTools: IToolState[];\n isThinking?: boolean;\n}\n\nfunction renderThinkingFallback(isThinking: boolean): React.ReactElement {\n if (!isThinking) return <></>;\n return (\n <Box marginBottom={1}>\n <Text color=\"yellow\">Thinking...</Text>\n </Box>\n );\n}\n\nfunction renderTools(activeTools: IToolState[]): React.ReactElement {\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"white\" bold>\n Tools:\n </Text>\n <Text> </Text>\n {activeTools.map((t, i) => {\n const { color, icon, strikethrough } = getToolStyle(t);\n return (\n <Box key={`${t.toolName}-${i}`} flexDirection=\"column\">\n <Text color={color} strikethrough={strikethrough}>\n {' '}\n {icon} {t.toolName}({t.firstArg})\n </Text>\n {t.diffLines && t.diffLines.length > 0 && (\n <ToolDiffBlock file={t.diffFile} lines={t.diffLines} />\n )}\n </Box>\n );\n })}\n </Box>\n );\n}\n\nexport default function StreamingIndicator({\n text,\n activeTools,\n isThinking = false,\n}: IProps): React.ReactElement {\n const hasTools = activeTools.length > 0;\n const hasText = text.length > 0;\n\n if (!hasTools && !hasText) {\n return renderThinkingFallback(isThinking);\n }\n\n return (\n <Box flexDirection=\"column\">\n {hasTools && renderTools(activeTools)}\n {hasText && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"cyan\" bold>\n Robota:\n </Text>\n <Text> </Text>\n <Box marginLeft={2}>\n <Text wrap=\"wrap\">{renderMarkdown(text)}</Text>\n </Box>\n </Box>\n )}\n </Box>\n );\n}\n","import React, { useState, useCallback, useRef } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport {\n applySelectionInput,\n createSelectionFlowState,\n getVerticalSelectionInputAction,\n normalizeSelectionState,\n type ISelectionFlowState,\n type TSelectionInputAction,\n} from './flows/selection-flow.js';\n\nexport interface IMenuSelectItem {\n label: string;\n value: string;\n hint?: string;\n}\n\ninterface IProps {\n title: string;\n items: IMenuSelectItem[];\n onSelect: (value: string) => void;\n onBack: () => void;\n loading?: boolean;\n error?: string;\n}\n\nexport default function MenuSelect({\n title,\n items,\n onSelect,\n onBack,\n loading,\n error,\n}: IProps): React.ReactElement {\n const [state, setState] = useState<ISelectionFlowState>(() => createSelectionFlowState());\n const stateRef = useRef(state);\n const isEnabled = !loading && !error;\n const applyAction = useCallback(\n (action: TSelectionInputAction): void => {\n const result = applySelectionInput(stateRef.current, action, {\n itemCount: items.length,\n enabled: isEnabled,\n });\n stateRef.current = result.state;\n setState(result.state);\n if (result.effect.type === 'cancel') {\n onBack();\n } else if (result.effect.type === 'select') {\n const item = items[result.effect.index];\n if (item !== undefined) {\n onSelect(item.value);\n }\n }\n },\n [isEnabled, items, onBack, onSelect],\n );\n\n useInput((input, key) => {\n const action = getVerticalSelectionInputAction(key);\n if (action !== undefined) {\n applyAction(action);\n }\n });\n\n const normalizedState = normalizeSelectionState(state, { itemCount: items.length });\n if (normalizedState !== state) {\n stateRef.current = normalizedState;\n }\n const selected = normalizedState.selectedIndex;\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"yellow\" paddingX={1}>\n <Text color=\"yellow\" bold>\n {title}\n </Text>\n {loading && (\n <Box marginTop={1}>\n <Text dimColor>Loading...</Text>\n </Box>\n )}\n {error && (\n <Box marginTop={1} flexDirection=\"column\">\n <Text color=\"red\">{error}</Text>\n <Text dimColor>Press Esc to go back</Text>\n </Box>\n )}\n {!loading && !error && (\n <Box flexDirection=\"column\" marginTop={1}>\n {items.map((item, i) => (\n <Box key={item.value}>\n <Text color={i === selected ? 'cyan' : undefined} bold={i === selected}>\n {i === selected ? '> ' : ' '}\n {item.label}\n </Text>\n {item.hint && <Text dimColor> {item.hint}</Text>}\n </Box>\n ))}\n </Box>\n )}\n <Text dimColor>{loading || error ? '' : ' ↑↓ Navigate Enter Select Esc Back'}</Text>\n </Box>\n );\n}\n","/**\n * Screen-specific selection handlers for PluginTUI.\n * Extracted to keep PluginTUI.tsx under 300 lines.\n */\n\nimport type { IMenuSelectItem } from './MenuSelect.js';\nimport type { ICommandPluginAdapter } from '@robota-sdk/agent-framework';\n\ninterface IConfirmState {\n message: string;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\ninterface IMenuContext {\n marketplace?: string;\n pluginId?: string;\n}\n\ninterface INavActions {\n push: (state: { screen: string; context?: IMenuContext }) => void;\n pop: () => void;\n popN: (n: number) => void;\n notify: (content: string) => void;\n setConfirm: (state: IConfirmState | undefined) => void;\n refresh: () => void;\n}\n\nexport function handleMainSelect(value: string, nav: Pick<INavActions, 'push'>): void {\n if (value === 'marketplace') {\n nav.push({ screen: 'marketplace-list' });\n } else if (value === 'installed') {\n nav.push({ screen: 'installed-list' });\n }\n}\n\nexport function handleMarketplaceListSelect(value: string, nav: Pick<INavActions, 'push'>): void {\n if (value === '__add__') {\n nav.push({ screen: 'marketplace-add' });\n } else {\n nav.push({ screen: 'marketplace-action', context: { marketplace: value } });\n }\n}\n\nexport function handleMarketplaceActionSelect(\n value: string,\n marketplace: string,\n callbacks: ICommandPluginAdapter,\n nav: Pick<INavActions, 'push' | 'pop' | 'popN' | 'notify' | 'setConfirm'>,\n): void {\n if (value === 'browse') {\n nav.push({ screen: 'marketplace-browse', context: { marketplace } });\n } else if (value === 'update') {\n callbacks\n .marketplaceUpdate(marketplace)\n .then(() => {\n nav.notify(`Updated marketplace \"${marketplace}\".`);\n nav.pop();\n })\n .catch((err) => {\n nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n });\n } else if (value === 'remove') {\n nav.setConfirm({\n message: `Remove marketplace \"${marketplace}\" and all its plugins?`,\n onConfirm: () => {\n nav.setConfirm(undefined);\n callbacks\n .marketplaceRemove(marketplace)\n .then(() => {\n nav.notify(`Removed marketplace \"${marketplace}\".`);\n nav.popN(2);\n })\n .catch((err) => {\n nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n });\n },\n onCancel: () => nav.setConfirm(undefined),\n });\n }\n}\n\nexport function handleMarketplaceBrowseSelect(\n value: string,\n marketplace: string,\n items: IMenuSelectItem[],\n nav: Pick<INavActions, 'push'>,\n): void {\n const fullId = `${value}@${marketplace}`;\n const item = items.find((i) => i.value === value);\n if (item?.hint === 'installed') {\n nav.push({ screen: 'installed-action', context: { pluginId: fullId } });\n } else {\n nav.push({ screen: 'marketplace-install-scope', context: { marketplace, pluginId: fullId } });\n }\n}\n\nexport function handleInstallScopeSelect(\n value: string,\n pluginId: string,\n callbacks: ICommandPluginAdapter,\n nav: Pick<INavActions, 'popN' | 'notify'>,\n): void {\n const scope = value as 'user' | 'project';\n callbacks\n .install(pluginId, scope)\n .then(() => {\n nav.notify(`Installed plugin \"${pluginId}\" (${scope} scope).`);\n nav.popN(2);\n })\n .catch((err) => {\n nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n });\n}\n\nexport function handleInstalledListSelect(\n value: string,\n callbacks: ICommandPluginAdapter,\n nav: Pick<INavActions, 'notify' | 'setConfirm' | 'refresh'>,\n): void {\n nav.setConfirm({\n message: `Uninstall plugin \"${value}\"?`,\n onConfirm: () => {\n nav.setConfirm(undefined);\n callbacks\n .uninstall(value)\n .then(() => {\n nav.notify(`Uninstalled plugin \"${value}\".`);\n nav.refresh();\n })\n .catch((err) => {\n nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n });\n },\n onCancel: () => nav.setConfirm(undefined),\n });\n}\n\nexport function handleInstalledActionSelect(\n value: string,\n pluginId: string,\n callbacks: ICommandPluginAdapter,\n nav: Pick<INavActions, 'popN' | 'notify' | 'setConfirm'>,\n): void {\n if (value === 'uninstall') {\n nav.setConfirm({\n message: `Uninstall plugin \"${pluginId}\"?`,\n onConfirm: () => {\n nav.setConfirm(undefined);\n callbacks\n .uninstall(pluginId)\n .then(() => {\n nav.notify(`Uninstalled plugin \"${pluginId}\".`);\n nav.popN(2);\n })\n .catch((err) => {\n nav.notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n });\n },\n onCancel: () => nav.setConfirm(undefined),\n });\n }\n}\n","/**\n * Hook: fetch data for PluginTUI screens.\n * Extracted from PluginTUI.tsx for single-responsibility.\n */\n\nimport { useState, useEffect } from 'react';\nimport type { ICommandPluginAdapter } from '@robota-sdk/agent-framework';\nimport type { IMenuSelectItem } from '../MenuSelect.js';\n\nexport function usePluginScreenData(\n screen: string,\n marketplace: string | undefined,\n callbacks: ICommandPluginAdapter,\n refreshCounter: number,\n stackLength: number,\n): { items: IMenuSelectItem[]; loading: boolean; error: string | undefined } {\n const [items, setItems] = useState<IMenuSelectItem[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | undefined>();\n\n useEffect(() => {\n setItems([]);\n setError(undefined);\n\n if (screen === 'marketplace-list') {\n setLoading(true);\n callbacks\n .marketplaceList()\n .then((sources) => {\n const baseItems: IMenuSelectItem[] = [{ label: 'Add Marketplace', value: '__add__' }];\n const sourceItems: IMenuSelectItem[] = sources.map((s) => ({\n label: s.name,\n value: s.name,\n hint: s.type,\n }));\n setItems([...baseItems, ...sourceItems]);\n setLoading(false);\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : String(err));\n setLoading(false);\n });\n } else if (screen === 'marketplace-browse') {\n const mp = marketplace ?? '';\n setLoading(true);\n callbacks\n .listAvailablePlugins(mp)\n .then((plugins) => {\n setItems(\n plugins.map((p) => ({\n label: p.name,\n value: p.name,\n hint: p.installed ? 'installed' : p.description,\n })),\n );\n setLoading(false);\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : String(err));\n setLoading(false);\n });\n } else if (screen === 'installed-list') {\n setLoading(true);\n callbacks\n .listInstalled()\n .then((plugins) => {\n setItems(\n plugins.map((p) => ({\n label: p.name,\n value: p.name,\n hint: p.description,\n })),\n );\n setLoading(false);\n })\n .catch((err) => {\n setError(err instanceof Error ? err.message : String(err));\n setLoading(false);\n });\n }\n }, [stackLength, screen, marketplace, callbacks, refreshCounter]);\n\n return { items, loading, error };\n}\n","/**\n * PluginTUI — Main orchestrator component for plugin management.\n * Manages a stack of screens: main, marketplace, installed plugins, etc.\n */\n\nimport React, { useState, useCallback } from 'react';\nimport MenuSelect from './MenuSelect.js';\nimport TextPrompt from './TextPrompt.js';\nimport ConfirmPrompt from './ConfirmPrompt.js';\nimport {\n handleMainSelect,\n handleMarketplaceListSelect,\n handleMarketplaceActionSelect,\n handleMarketplaceBrowseSelect,\n handleInstallScopeSelect,\n handleInstalledListSelect,\n handleInstalledActionSelect,\n} from './plugin-tui-handlers.js';\nimport type { IMenuSelectItem } from './MenuSelect.js';\nimport type { ICommandPluginAdapter } from '@robota-sdk/agent-framework';\nimport { usePluginScreenData } from './hooks/usePluginScreenData.js';\n\ntype TScreenId =\n | 'main'\n | 'marketplace-list'\n | 'marketplace-action'\n | 'marketplace-browse'\n | 'marketplace-install-scope'\n | 'marketplace-add'\n | 'installed-list'\n | 'installed-action';\n\ninterface IMenuContext {\n marketplace?: string;\n pluginId?: string;\n}\n\ninterface IMenuState {\n screen: TScreenId;\n context?: IMenuContext;\n}\n\ninterface IConfirmState {\n message: string;\n onConfirm: () => void;\n onCancel: () => void;\n}\n\ninterface IProps {\n callbacks: ICommandPluginAdapter;\n onClose: () => void;\n addMessage?: (msg: { role: string; content: string }) => void;\n}\n\nexport default function PluginTUI({ callbacks, onClose, addMessage }: IProps): React.ReactElement {\n const [stack, setStack] = useState<IMenuState[]>([{ screen: 'main' }]);\n const [confirm, setConfirm] = useState<IConfirmState | undefined>();\n const [refreshCounter, setRefreshCounter] = useState(0);\n\n const current = stack[stack.length - 1] ?? { screen: 'main' };\n\n const push = useCallback((state: IMenuState) => {\n setStack((prev) => [...prev, state]);\n }, []);\n\n const pop = useCallback(() => {\n setStack((prev) => {\n if (prev.length <= 1) {\n onClose();\n return prev;\n }\n return prev.slice(0, -1);\n });\n }, [onClose]);\n\n const popN = useCallback(\n (n: number) => {\n setStack((prev) => {\n const next = prev.slice(0, Math.max(1, prev.length - n));\n if (next.length === 0) {\n onClose();\n return prev;\n }\n return next;\n });\n },\n [onClose],\n );\n\n const notify = useCallback(\n (content: string) => {\n addMessage?.({ role: 'system', content });\n },\n [addMessage],\n );\n\n const refresh = useCallback(() => {\n setRefreshCounter((c) => c + 1);\n }, []);\n\n const setConfirmNav = useCallback(\n (state: IConfirmState | undefined) => setConfirm(state),\n [setConfirm],\n );\n // nav.push accepts a loose { screen: string } shape to satisfy plugin-tui-handlers types;\n // we cast screen to TScreenId which is safe because handlers only push valid screen names.\n const pushNav = useCallback(\n (state: { screen: string; context?: IMenuContext }) =>\n push({ screen: state.screen as TScreenId, context: state.context }),\n [push],\n );\n const nav = { push: pushNav, pop, popN, notify, setConfirm: setConfirmNav, refresh };\n\n const { items, loading, error } = usePluginScreenData(\n current.screen,\n current.context?.marketplace,\n callbacks,\n refreshCounter,\n stack.length,\n );\n\n const handleSelect = useCallback(\n (value: string) => {\n const screen = current.screen;\n const ctx = current.context;\n\n if (screen === 'main') handleMainSelect(value, nav);\n else if (screen === 'marketplace-list') handleMarketplaceListSelect(value, nav);\n else if (screen === 'marketplace-action')\n handleMarketplaceActionSelect(value, ctx?.marketplace ?? '', callbacks, nav);\n else if (screen === 'marketplace-browse')\n handleMarketplaceBrowseSelect(value, ctx?.marketplace ?? '', items, nav);\n else if (screen === 'marketplace-install-scope')\n handleInstallScopeSelect(value, ctx?.pluginId ?? '', callbacks, nav);\n else if (screen === 'installed-list') handleInstalledListSelect(value, callbacks, nav);\n else if (screen === 'installed-action')\n handleInstalledActionSelect(value, ctx?.pluginId ?? '', callbacks, nav);\n },\n [current, items, callbacks, push, pop, popN, notify, setConfirm, refresh],\n );\n\n const handleTextSubmit = useCallback(\n (value: string) => {\n if (current.screen === 'marketplace-add') {\n callbacks\n .marketplaceAdd(value)\n .then((name) => {\n notify(`Added marketplace \"${name}\" from ${value}.`);\n pop();\n })\n .catch((err) => {\n notify(`Error: ${err instanceof Error ? err.message : String(err)}`);\n pop();\n });\n }\n },\n [current.screen, callbacks, notify, pop],\n );\n\n // Confirm overlay intercepts everything\n if (confirm) {\n return (\n <ConfirmPrompt\n message={confirm.message}\n onSelect={(index) => {\n if (index === 0) confirm.onConfirm();\n else confirm.onCancel();\n }}\n />\n );\n }\n\n const screen = current.screen;\n\n if (screen === 'marketplace-add') {\n return (\n <TextPrompt\n title=\"Add Marketplace Source\"\n placeholder=\"owner/repo or git URL\"\n onSubmit={handleTextSubmit}\n onCancel={pop}\n validate={(v) => (!v.includes('/') ? 'Must be owner/repo or a git URL' : undefined)}\n />\n );\n }\n\n if (screen === 'marketplace-action') {\n return (\n <MenuSelect\n key={stack.length}\n title={`Marketplace: ${current.context?.marketplace ?? ''}`}\n items={[\n { label: 'Browse plugins', value: 'browse' },\n { label: 'Update', value: 'update' },\n { label: 'Remove', value: 'remove' },\n ]}\n onSelect={handleSelect}\n onBack={pop}\n />\n );\n }\n\n if (screen === 'marketplace-install-scope') {\n return (\n <MenuSelect\n key={stack.length}\n title={`Install scope for \"${current.context?.pluginId ?? ''}\"`}\n items={[\n { label: 'User scope', value: 'user' },\n { label: 'Project scope', value: 'project' },\n ]}\n onSelect={handleSelect}\n onBack={pop}\n />\n );\n }\n\n if (screen === 'installed-action') {\n return (\n <MenuSelect\n key={stack.length}\n title={`Plugin: ${current.context?.pluginId ?? ''}`}\n items={[{ label: 'Uninstall', value: 'uninstall' }]}\n onSelect={handleSelect}\n onBack={pop}\n />\n );\n }\n\n // Screens with async items: main, marketplace-list, marketplace-browse, installed-list\n const titleMap: Record<string, string> = {\n main: 'Plugin Management',\n 'marketplace-list': 'Marketplace',\n 'marketplace-browse': `Browse: ${current.context?.marketplace ?? ''}`,\n 'installed-list': 'Installed Plugins',\n };\n\n const staticItemsMap: Record<string, IMenuSelectItem[]> = {\n main: [\n { label: 'Marketplace', value: 'marketplace' },\n { label: 'Installed Plugins', value: 'installed' },\n ],\n };\n\n return (\n <MenuSelect\n key={`${screen}-${stack.length}-${refreshCounter}`}\n title={titleMap[screen] ?? 'Plugin Management'}\n items={staticItemsMap[screen] ?? items}\n onSelect={handleSelect}\n onBack={pop}\n loading={loading}\n error={error}\n />\n );\n}\n","/**\n * TransportTUI — interactive overlay for transport enable/disable settings.\n *\n * Arrow keys navigate the list, space toggles enabled/disabled, enter/esc closes.\n */\n\nimport React, { useState, useCallback } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type {\n ITransportEntry,\n ITransportRegistryView,\n} from '@robota-sdk/agent-interface-transport';\nimport type { IInteractiveSession } from '@robota-sdk/agent-framework';\n\nconst TRANSPORT_NAME_WIDTH = 18;\n\ninterface IEntryRowProps {\n entry: ITransportEntry<IInteractiveSession>;\n selected: boolean;\n}\n\nfunction TransportEntryRow({ entry, selected }: IEntryRowProps): React.ReactElement {\n const enabled = entry.config.enabled;\n const dot = enabled ? '●' : '○';\n const badge = enabled ? '[enabled] ' : '[disabled]';\n const portOpt = entry.config.options?.port;\n const portHint = typeof portOpt === 'number' ? `port: ${portOpt}` : '';\n return (\n <Box>\n <Text color={selected ? 'cyan' : undefined} bold={selected}>\n {`${dot} ${entry.transport.name.padEnd(TRANSPORT_NAME_WIDTH)} ${badge} ${portHint}`}\n </Text>\n </Box>\n );\n}\n\ntype TKey = { upArrow: boolean; downArrow: boolean; escape: boolean; return: boolean };\n\nfunction useTransportInput(\n entries: ITransportEntry<IInteractiveSession>[],\n cursor: number,\n saving: boolean,\n registry: ITransportRegistryView<IInteractiveSession>,\n setCursor: (fn: (c: number) => number) => void,\n setSaving: (v: boolean) => void,\n onClose: () => void,\n refresh: () => void,\n): void {\n useInput(\n useCallback(\n (_input: string, key: TKey) => {\n if (saving) return;\n if (key.upArrow) {\n setCursor((c) => Math.max(0, c - 1));\n return;\n }\n if (key.downArrow) {\n setCursor((c) => Math.min(entries.length - 1, c + 1));\n return;\n }\n if (key.escape || key.return) {\n onClose();\n return;\n }\n if (_input === ' ') {\n const entry = entries[cursor];\n if (!entry) return;\n setSaving(true);\n registry\n .setEnabled(entry.transport.name, !entry.config.enabled)\n .then(() => {\n refresh();\n setSaving(false);\n })\n .catch(() => setSaving(false));\n }\n },\n [saving, entries, cursor, registry, onClose, refresh, setCursor, setSaving],\n ),\n );\n}\n\ninterface IProps {\n registry: ITransportRegistryView<IInteractiveSession>;\n onClose: () => void;\n}\n\nexport default function TransportTUI({ registry, onClose }: IProps): React.ReactElement {\n const [entries, setEntries] = useState(() => registry.getAll());\n const [cursor, setCursor] = useState(0);\n const [saving, setSaving] = useState(false);\n const refresh = useCallback((): void => {\n setEntries(registry.getAll());\n }, [registry]);\n\n useTransportInput(entries, cursor, saving, registry, setCursor, setSaving, onClose, refresh);\n\n return (\n <Box flexDirection=\"column\" paddingX={2} paddingY={1}>\n <Text bold>Settings › Transports</Text>\n <Box marginTop={1} flexDirection=\"column\">\n {entries.map((entry, i) => (\n <TransportEntryRow key={entry.transport.name} entry={entry} selected={i === cursor} />\n ))}\n </Box>\n <Box marginTop={1}>\n <Text dimColor>↑↓ select space toggle enter/esc close</Text>\n </Box>\n {saving && (\n <Box marginTop={1}>\n <Text color=\"yellow\">Saving…</Text>\n </Box>\n )}\n </Box>\n );\n}\n","/**\n * Session picker component for /resume command.\n * Shows a list of sessions for the current cwd.\n */\n\nimport React from 'react';\nimport { Box, Text } from 'ink';\nimport type { IResumableSessionSummary } from '@robota-sdk/agent-framework';\nimport ListPicker from './ListPicker.js';\n\nconst SESSION_ID_DISPLAY_LENGTH = 8;\nconst SESSION_PREVIEW_DISPLAY_LENGTH = 60;\n\ninterface IProps {\n sessions: readonly IResumableSessionSummary[];\n onSelect: (sessionId: string) => void;\n onCancel: () => void;\n}\n\nexport default function SessionPicker({\n sessions,\n onSelect,\n onCancel,\n}: IProps): React.ReactElement {\n return (\n <Box flexDirection=\"column\" paddingX={1} marginBottom={1}>\n <Text bold color=\"cyan\">\n Select a session to resume (ESC to cancel):\n </Text>\n <ListPicker<IResumableSessionSummary>\n items={[...sessions]}\n renderItem={(session: IResumableSessionSummary, isSelected: boolean) => {\n const preview = session.preview\n ? session.preview.slice(0, SESSION_PREVIEW_DISPLAY_LENGTH) +\n (session.preview.length > SESSION_PREVIEW_DISPLAY_LENGTH ? '...' : '')\n : '';\n return (\n <Text>\n {isSelected ? '> ' : ' '}\n <Text bold>{session.name ?? session.id.slice(0, SESSION_ID_DISPLAY_LENGTH)}</Text>\n {' '}\n <Text dimColor>\n {new Date(session.updatedAt).toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit',\n })}\n </Text>\n {' '}\n <Text dimColor>msgs: {session.messageCount}</Text>\n {preview ? (\n <>\n {'\\n '}\n <Text color=\"gray\">{preview}</Text>\n </>\n ) : null}\n </Text>\n );\n }}\n onSelect={(session: IResumableSessionSummary) => onSelect(session.id)}\n onCancel={onCancel}\n />\n </Box>\n );\n}\n","import type {\n IExecutionDetailRecord,\n IExecutionWorkspaceEntry,\n IExecutionWorkspaceSnapshot,\n TExecutionWorkspaceStatus,\n} from '@robota-sdk/agent-framework';\n\nconst ACTIVE_STATUSES: readonly TExecutionWorkspaceStatus[] = [\n 'active',\n 'queued',\n 'running',\n 'waiting_permission',\n 'sleeping',\n];\nconst DETAIL_RECORD_TEXT_LIMIT = 160;\nconst PREVIEW_WHITESPACE = /\\s+/g;\nconst PREVIEW_SEPARATOR = ' ';\n\nexport interface IExecutionWorkspaceEntryRow {\n id: string;\n radio: '●' | '○';\n title: string;\n subtitle?: string;\n statusLabel: string;\n preview?: string;\n color: string;\n isSelected: boolean;\n accessibleText: string;\n}\n\nexport interface IExecutionWorkspaceEntryRowOptions {\n selectedEntryId?: string;\n}\n\nexport function getDefaultBackgroundWorkspaceEntries(\n snapshot: IExecutionWorkspaceSnapshot | null,\n): IExecutionWorkspaceEntry[] {\n return (snapshot?.entries ?? []).filter(\n (entry) => entry.kind === 'background_task' && entry.visibility === 'default',\n );\n}\n\nexport function countActiveBackgroundWorkspaceEntries(\n snapshot: IExecutionWorkspaceSnapshot | null,\n): number {\n return getDefaultBackgroundWorkspaceEntries(snapshot).filter((entry) =>\n ACTIVE_STATUSES.includes(entry.status),\n ).length;\n}\n\nexport function formatExecutionWorkspaceEntryRow(\n entry: IExecutionWorkspaceEntry,\n options: IExecutionWorkspaceEntryRowOptions = {},\n): IExecutionWorkspaceEntryRow {\n const isSelected = entry.id === options.selectedEntryId;\n const row = {\n id: entry.id,\n radio: isSelected ? '●' : '○',\n title: formatEntryTitle(entry),\n subtitle: formatEntrySubtitle(entry),\n statusLabel: formatStatusLabel(entry.status),\n preview: trimPreview(entry.preview ?? entry.currentAction),\n color: getEntryColor(entry),\n isSelected,\n } satisfies Omit<IExecutionWorkspaceEntryRow, 'accessibleText'>;\n return { ...row, accessibleText: formatAccessibleText(row) };\n}\n\nexport function formatExecutionDetailRecord(record: IExecutionDetailRecord): string {\n const text = record.text.trim().replace(PREVIEW_WHITESPACE, PREVIEW_SEPARATOR);\n if (!text) return record.kind;\n return text.length > DETAIL_RECORD_TEXT_LIMIT\n ? `${text.slice(0, DETAIL_RECORD_TEXT_LIMIT)}...`\n : text;\n}\n\nfunction formatEntryTitle(entry: IExecutionWorkspaceEntry): string {\n if (entry.kind === 'main_thread') return entry.title;\n if (entry.kind === 'background_group') return `${entry.title} group`;\n if (entry.taskKind === 'agent') return `${entry.title} agent`;\n if (entry.taskKind === 'process') return entry.title || 'Process';\n if (entry.taskKind === 'scheduled') return entry.title || 'Scheduled';\n return entry.title;\n}\n\nfunction formatEntrySubtitle(entry: IExecutionWorkspaceEntry): string | undefined {\n if (entry.kind === 'main_thread') return entry.subtitle;\n const parts = [\n entry.taskKind,\n entry.subtitle,\n entry.attention === 'none' ? undefined : entry.attention,\n ];\n return (\n parts\n .filter((part): part is string => typeof part === 'string' && part.length > 0)\n .join(' · ') || undefined\n );\n}\n\nfunction formatStatusLabel(status: TExecutionWorkspaceStatus): string {\n return status.replace(/_/g, ' ');\n}\n\nfunction getEntryColor(entry: IExecutionWorkspaceEntry): string {\n if (entry.attention === 'failed' || entry.status === 'failed') return 'red';\n if (entry.attention === 'permission' || entry.status === 'waiting_permission') return 'yellow';\n if (entry.status === 'completed') return 'green';\n if (entry.status === 'cancelled') return 'yellow';\n if (ACTIVE_STATUSES.includes(entry.status)) return 'cyan';\n return 'white';\n}\n\nfunction trimPreview(value: string | undefined): string | undefined {\n const preview = value?.trim().replace(PREVIEW_WHITESPACE, PREVIEW_SEPARATOR);\n return preview || undefined;\n}\n\nfunction formatAccessibleText(row: Omit<IExecutionWorkspaceEntryRow, 'accessibleText'>): string {\n const parts = [row.radio, row.title, row.statusLabel, row.subtitle, row.preview];\n return parts\n .filter((part): part is string => typeof part === 'string' && part.length > 0)\n .join(' · ');\n}\n","import type { IExecutionWorkspaceEntry } from '@robota-sdk/agent-framework';\nimport { formatExecutionWorkspaceEntryRow } from './execution-workspace-view-model.js';\n\nexport interface IBackgroundTaskRow {\n connector: '├' | '└';\n marker: '□' | '■';\n color: string;\n label: string;\n segments: string[];\n preview?: string;\n accessibleText: string;\n}\n\nexport interface IBackgroundTaskRowOptions {\n isLast?: boolean;\n}\n\nexport function formatBackgroundTaskRow(\n entry: IExecutionWorkspaceEntry,\n options: IBackgroundTaskRowOptions = {},\n): IBackgroundTaskRow {\n const row = formatExecutionWorkspaceEntryRow(entry);\n const marker = isActiveEntry(entry) ? '□' : '■';\n const segments = [row.statusLabel, row.subtitle].filter(\n (segment): segment is string => typeof segment === 'string' && segment.length > 0,\n );\n return {\n connector: options.isLast === false ? '├' : '└',\n marker,\n color: row.color,\n label: row.title,\n segments,\n preview: row.preview,\n accessibleText: [\n `${options.isLast === false ? '├' : '└'} ${marker} ${row.title}`,\n ...segments,\n row.preview,\n ]\n .filter((part): part is string => typeof part === 'string' && part.length > 0)\n .join(' · '),\n };\n}\n\nfunction isActiveEntry(entry: IExecutionWorkspaceEntry): boolean {\n return (\n entry.status === 'active' ||\n entry.status === 'queued' ||\n entry.status === 'running' ||\n entry.status === 'waiting_permission' ||\n entry.status === 'sleeping'\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type { IExecutionWorkspaceEntry } from '@robota-sdk/agent-framework';\nimport { formatBackgroundTaskRow } from './background-task-row-format.js';\n\ninterface IProps {\n entries: IExecutionWorkspaceEntry[];\n}\n\nexport default function BackgroundTaskPanel({ entries }: IProps): React.ReactElement | null {\n if (entries.length === 0) return null;\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"cyan\" bold>\n Background work\n </Text>\n {entries.map((entry, index) => {\n const row = formatBackgroundTaskRow(entry, { isLast: index === entries.length - 1 });\n return (\n <Text key={entry.id}>\n {`${row.connector} `}\n <Text color={row.color}>{row.marker}</Text>\n {` ${row.label}`}\n {row.segments.map((segment, segmentIndex) => (\n <Text key={`${segment}-${segmentIndex}`} dimColor>{` · ${segment}`}</Text>\n ))}\n {row.preview ? <Text dimColor>{` · ${row.preview}`}</Text> : null}\n </Text>\n );\n })}\n </Box>\n );\n}\n","import React, { useEffect, useRef, useState } from 'react';\nimport { Box, Text, useInput } from 'ink';\nimport type {\n IExecutionWorkspaceEntry,\n IExecutionWorkspaceSnapshot,\n} from '@robota-sdk/agent-framework';\nimport {\n applySelectionInput,\n createSelectionFlowState,\n getVerticalSelectionInputAction,\n normalizeSelectionState,\n type ISelectionFlowState,\n type TSelectionInputAction,\n} from './flows/selection-flow.js';\nimport { formatExecutionWorkspaceEntryRow } from './execution-workspace-view-model.js';\n\nconst MAX_VISIBLE_WORKSPACE_ENTRIES = 8;\n\ninterface IProps {\n snapshot: IExecutionWorkspaceSnapshot | null;\n selectedEntryId?: string;\n onSelect: (entryId: string) => void;\n onClose: () => void;\n}\n\nexport default function ExecutionWorkspaceSwitcher({\n snapshot,\n selectedEntryId,\n onSelect,\n onClose,\n}: IProps): React.ReactElement {\n const entries = [...(snapshot?.entries ?? [])];\n const { normalized, visibleEntries, applyAction } = useWorkspaceSwitcherSelection({\n entries,\n selectedEntryId,\n onSelect,\n onClose,\n });\n\n useInput((_input, key) => {\n const action = getVerticalSelectionInputAction(key);\n if (action !== undefined) applyAction(action);\n });\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor=\"cyan\" paddingX={1}>\n <Text color=\"cyan\" bold>\n Execution workspace\n </Text>\n <Box flexDirection=\"column\" marginTop={1}>\n {visibleEntries.length === 0 ? (\n <Text dimColor>No workspace entries</Text>\n ) : (\n visibleEntries.map((entry, index) => (\n <ExecutionWorkspaceSwitcherRow\n key={entry.id}\n entry={entry}\n isFocused={normalized.scrollOffset + index === normalized.selectedIndex}\n selectedEntryId={selectedEntryId}\n />\n ))\n )}\n </Box>\n <Text dimColor>Ctrl+B Close ↑↓ Navigate Enter Switch Esc Close</Text>\n </Box>\n );\n}\n\ninterface IUseWorkspaceSwitcherSelectionInput {\n entries: IExecutionWorkspaceEntry[];\n selectedEntryId?: string;\n onSelect: (entryId: string) => void;\n onClose: () => void;\n}\n\nfunction useWorkspaceSwitcherSelection({\n entries,\n selectedEntryId,\n onSelect,\n onClose,\n}: IUseWorkspaceSwitcherSelectionInput): {\n normalized: ISelectionFlowState;\n visibleEntries: IExecutionWorkspaceEntry[];\n applyAction: (action: TSelectionInputAction) => void;\n} {\n const [state, setState] = useState<ISelectionFlowState>(() => createSelectionFlowState());\n const stateRef = useRef(state);\n\n useEffect(() => {\n const selectedIndex = Math.max(\n 0,\n entries.findIndex((entry) => entry.id === selectedEntryId),\n );\n const nextState = createNormalizedSelection({ selectedIndex, itemCount: entries.length });\n stateRef.current = nextState;\n setState(nextState);\n }, [entries.length, selectedEntryId]);\n\n const normalized = createNormalizedSelection({\n selectedIndex: state.selectedIndex,\n scrollOffset: state.scrollOffset,\n itemCount: entries.length,\n });\n if (normalized !== state) stateRef.current = normalized;\n return {\n normalized,\n visibleEntries: entries.slice(\n normalized.scrollOffset,\n normalized.scrollOffset + MAX_VISIBLE_WORKSPACE_ENTRIES,\n ),\n applyAction: createApplyAction({ entries, stateRef, setState, onSelect, onClose }),\n };\n}\n\nfunction createApplyAction({\n entries,\n stateRef,\n setState,\n onSelect,\n onClose,\n}: {\n entries: IExecutionWorkspaceEntry[];\n stateRef: React.MutableRefObject<ISelectionFlowState>;\n setState: React.Dispatch<React.SetStateAction<ISelectionFlowState>>;\n onSelect: (entryId: string) => void;\n onClose: () => void;\n}): (action: TSelectionInputAction) => void {\n return (action): void => {\n const result = applySelectionInput(stateRef.current, action, {\n itemCount: entries.length,\n maxVisible: MAX_VISIBLE_WORKSPACE_ENTRIES,\n });\n const nextState =\n result.effect.type === 'select' || result.effect.type === 'cancel'\n ? { ...result.state, resolved: false }\n : result.state;\n stateRef.current = nextState;\n setState(nextState);\n if (result.effect.type === 'cancel') {\n onClose();\n } else if (result.effect.type === 'select') {\n const entry = entries[result.effect.index];\n if (entry) onSelect(entry.id);\n }\n };\n}\n\nfunction createNormalizedSelection(input: {\n selectedIndex: number;\n scrollOffset?: number;\n itemCount: number;\n}): ISelectionFlowState {\n return normalizeSelectionState(\n {\n selectedIndex: input.selectedIndex,\n scrollOffset: input.scrollOffset ?? 0,\n resolved: false,\n },\n { itemCount: input.itemCount, maxVisible: MAX_VISIBLE_WORKSPACE_ENTRIES },\n );\n}\n\nfunction ExecutionWorkspaceSwitcherRow({\n entry,\n isFocused,\n selectedEntryId,\n}: {\n entry: IExecutionWorkspaceEntry;\n isFocused: boolean;\n selectedEntryId?: string;\n}): React.ReactElement {\n const row = formatExecutionWorkspaceEntryRow(entry, { selectedEntryId });\n return (\n <Text>\n <Text color={isFocused ? 'cyan' : undefined} bold={isFocused}>\n {isFocused ? '> ' : ' '}\n </Text>\n <Text color={row.color}>{row.radio}</Text>\n <Text color={isFocused ? 'cyan' : undefined} bold={isFocused}>{` ${row.title}`}</Text>\n <Text dimColor>{` · ${row.statusLabel}`}</Text>\n {row.subtitle ? <Text dimColor>{` · ${row.subtitle}`}</Text> : null}\n {row.preview ? <Text dimColor>{` · ${row.preview}`}</Text> : null}\n </Text>\n );\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\nimport type {\n IExecutionDetailPage,\n IExecutionWorkspaceEntry,\n TExecutionDetailRecordKind,\n} from '@robota-sdk/agent-framework';\nimport {\n formatExecutionDetailRecord,\n formatExecutionWorkspaceEntryRow,\n} from './execution-workspace-view-model.js';\n\nconst MAX_VISIBLE_DETAIL_RECORDS = 12;\n\ninterface IProps {\n entry: IExecutionWorkspaceEntry;\n page: IExecutionDetailPage | null;\n loading?: boolean;\n error?: string;\n}\n\nexport default function ExecutionWorkspaceDetailPane({\n entry,\n page,\n loading,\n error,\n}: IProps): React.ReactElement {\n const row = formatExecutionWorkspaceEntryRow(entry, { selectedEntryId: entry.id });\n const records = page?.records.slice(-MAX_VISIBLE_DETAIL_RECORDS) ?? [];\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text color=\"cyan\" bold>\n {`Viewing ${row.title}`}\n </Text>\n <Text dimColor>\n {row.statusLabel}\n {row.subtitle ? ` · ${row.subtitle}` : ''}\n {row.preview ? ` · ${row.preview}` : ''}\n </Text>\n {loading ? <Text dimColor>Loading workspace detail...</Text> : null}\n {error ? <Text color=\"red\">{error}</Text> : null}\n {!loading && !error && records.length === 0 ? <Text dimColor>No detail yet</Text> : null}\n {!loading &&\n !error &&\n records.map((record) => (\n <Text key={record.id} color={getDetailRecordColor(record.kind)}>\n {formatExecutionDetailRecord(record)}\n </Text>\n ))}\n {page?.nextCursor ? <Text dimColor>... more detail available</Text> : null}\n </Box>\n );\n}\n\nfunction getDetailRecordColor(kind: TExecutionDetailRecordKind): string | undefined {\n if (kind === 'error') return 'red';\n if (kind === 'result') return 'green';\n if (kind === 'process_output') return 'white';\n if (kind === 'group_summary') return 'cyan';\n return undefined;\n}\n","import React from 'react';\nimport { Box, Text } from 'ink';\n\ninterface IProps {\n message: string;\n}\n\nexport default function UpdateNotice({ message }: IProps): React.ReactElement {\n return (\n <Box paddingX={1} marginBottom={1}>\n <Text color=\"yellow\">{message}</Text>\n </Box>\n );\n}\n","import React, { useState, useEffect, useMemo, useCallback } from 'react';\nimport { Box, Text, useApp, useInput } from 'ink';\nimport type { IAIProvider } from '@robota-sdk/agent-core';\nimport type { TPermissionMode } from '@robota-sdk/agent-core';\nimport type {\n IBackgroundTaskRunner,\n ICommandHostAdapters,\n ICommandModule,\n IInteractiveSession,\n IInteractiveSessionStore,\n TSubagentRunnerFactory,\n TShellExecFn,\n IExecutionDetailPage,\n} from '@robota-sdk/agent-framework';\nimport { listResumableSessionSummaries } from '@robota-sdk/agent-framework';\nimport { createSystemMessage, messageToHistoryEntry } from '@robota-sdk/agent-core';\nimport type { ITransportRegistryView } from '@robota-sdk/agent-interface-transport';\nimport { useInteractiveSession } from './hooks/useInteractiveSession.js';\nimport { usePluginCallbacks } from './hooks/usePluginCallbacks.js';\nimport { useSideEffects } from './hooks/useSideEffects.js';\nimport { useStatusLineSettings } from './hooks/useStatusLineSettings.js';\nimport MessageList from './MessageList.js';\nimport SessionStatusBar from './SessionStatusBar.js';\nimport InputArea from './InputArea.js';\nimport ConfirmPrompt from './ConfirmPrompt.js';\nimport InteractivePrompt from './InteractivePrompt.js';\nimport PermissionPrompt from './PermissionPrompt.js';\nimport StreamingIndicator from './StreamingIndicator.js';\nimport PluginTUI from './PluginTUI.js';\nimport TransportTUI from './TransportTUI.js';\nimport SessionPicker from './SessionPicker.js';\nimport BackgroundTaskPanel from './BackgroundTaskPanel.js';\nimport ExecutionWorkspaceSwitcher from './ExecutionWorkspaceSwitcher.js';\nimport ExecutionWorkspaceDetailPane from './ExecutionWorkspaceDetailPane.js';\nimport UpdateNotice from './UpdateNotice.js';\nimport { formatModelChangeConfirmationMessage } from './hooks/model-change-side-effect.js';\nimport {\n countActiveBackgroundWorkspaceEntries,\n getDefaultBackgroundWorkspaceEntries,\n} from './execution-workspace-view-model.js';\nimport { TuiCliAdapterProvider } from './tui-cli-adapter-context.js';\nimport type { ITuiCliAdapter } from './tui-cli-adapter.js';\nimport type { CommandRegistry } from '@robota-sdk/agent-framework';\nimport type { ITuiCommandInteraction } from './command-interaction.js';\n\ninterface IProps {\n cwd: string;\n provider: IAIProvider;\n providerOverride?: string | undefined;\n providerType?: string | undefined;\n modelId?: string;\n language?: string;\n permissionMode?: TPermissionMode;\n maxTurns?: number;\n version?: string;\n sessionStore?: IInteractiveSessionStore;\n resumeSessionId?: string;\n showSessionPickerOnStart?: boolean;\n forkSession?: boolean;\n sessionName?: string;\n backgroundTaskRunners?: IBackgroundTaskRunner[];\n subagentRunnerFactory?: TSubagentRunnerFactory;\n commandModules?: readonly ICommandModule[];\n commandHostAdapters?: ICommandHostAdapters;\n shellExec?: TShellExecFn;\n startupUpdateNotice?: Promise<string | undefined>;\n transportRegistry?: ITransportRegistryView<IInteractiveSession>;\n cliAdapter: ITuiCliAdapter;\n reloadPluginCommandSource?: (registry: CommandRegistry) => void;\n agentName?: string;\n resolveInteraction?: (commandName: string) => ITuiCommandInteraction | undefined;\n}\n\nexport default function App(props: IProps): React.ReactElement {\n const [activeSessionId, setActiveSessionId] = useState<string | undefined>(props.resumeSessionId);\n const [showInitialSessionPicker, setShowInitialSessionPicker] = useState(\n props.showSessionPickerOnStart ?? false,\n );\n\n return (\n <TuiCliAdapterProvider value={props.cliAdapter}>\n <AppInner\n key={activeSessionId ?? '__new__'}\n {...props}\n showSessionPickerOnStart={showInitialSessionPicker}\n resumeSessionId={activeSessionId}\n onSessionSwitch={(sessionId) => {\n setShowInitialSessionPicker(false);\n setActiveSessionId(sessionId);\n }}\n />\n </TuiCliAdapterProvider>\n );\n}\n\nfunction AppInner(\n props: IProps & { onSessionSwitch: (sessionId: string) => void },\n): React.ReactElement {\n const cwd = props.cwd;\n\n const {\n interactiveSession,\n registry,\n commandEffectQueue,\n history,\n addEntry,\n streamingText,\n activeTools,\n isThinking,\n isAborting,\n isShuttingDown,\n pendingPrompt,\n executionWorkspaceSnapshot,\n selectedExecutionEntryId,\n selectExecutionWorkspaceEntry,\n readExecutionWorkspaceDetail,\n permissionRequest,\n contextState,\n handleSubmit: baseHandleSubmit,\n handleAbort,\n handleCancelQueue,\n handleShutdown,\n } = useInteractiveSession({\n cwd,\n provider: props.provider,\n permissionMode: props.permissionMode,\n maxTurns: props.maxTurns,\n sessionStore: props.sessionStore,\n resumeSessionId: props.resumeSessionId,\n forkSession: props.forkSession,\n sessionName: props.sessionName,\n backgroundTaskRunners: props.backgroundTaskRunners,\n subagentRunnerFactory: props.subagentRunnerFactory,\n commandModules: props.commandModules,\n commandHostAdapters: props.commandHostAdapters,\n shellExec: props.shellExec,\n transportRegistry: props.transportRegistry,\n language: props.language,\n reloadPluginCommandSource: props.reloadPluginCommandSource,\n agentName: props.agentName,\n });\n\n const fallbackPluginCallbacks = usePluginCallbacks(cwd);\n const pluginCallbacks = props.commandHostAdapters?.plugin ?? fallbackPluginCallbacks;\n const { exit } = useApp();\n const [sessionName, setSessionName] = useState<string | undefined>(props.sessionName);\n const [updateNotice, setUpdateNotice] = useState<string | undefined>();\n const [showExecutionWorkspaceSwitcher, setShowExecutionWorkspaceSwitcher] = useState(false);\n const [executionDetailPage, setExecutionDetailPage] = useState<IExecutionDetailPage | null>(null);\n const [executionDetailError, setExecutionDetailError] = useState<string | undefined>();\n const [isExecutionDetailLoading, setIsExecutionDetailLoading] = useState(false);\n const [statusLineSettings, setStatusLineSettings] = useStatusLineSettings();\n const backgroundWorkspaceEntries = useMemo(\n () => getDefaultBackgroundWorkspaceEntries(executionWorkspaceSnapshot),\n [executionWorkspaceSnapshot],\n );\n const activeBackgroundTaskCount = countActiveBackgroundWorkspaceEntries(\n executionWorkspaceSnapshot,\n );\n const selectedExecutionEntry = useMemo(\n () =>\n executionWorkspaceSnapshot?.entries.find((entry) => entry.id === selectedExecutionEntryId),\n [executionWorkspaceSnapshot, selectedExecutionEntryId],\n );\n\n const {\n handleSubmit,\n pendingModelId,\n pendingInteractionPrompt,\n showPluginTUI,\n showSessionPicker,\n showTransportTUI,\n setShowPluginTUI,\n setShowSessionPicker,\n setShowTransportTUI,\n handleModelConfirm,\n handleInteractionSubmit,\n handleInteractionCancel,\n } = useSideEffects({\n cwd,\n providerOverride: props.providerOverride,\n interactiveSession,\n commandEffectQueue,\n addEntry,\n baseHandleSubmit,\n setSessionName,\n setStatusLineSettings,\n showSessionPickerOnStart: props.showSessionPickerOnStart,\n openAgentSwitcher: () => setShowExecutionWorkspaceSwitcher(true),\n });\n\n const isSelectedEntryInteractive =\n !selectedExecutionEntry ||\n selectedExecutionEntry.kind === 'main_thread' ||\n selectedExecutionEntry.controls.includes('send');\n\n const activeAgentLabel =\n selectedExecutionEntry && selectedExecutionEntry.kind !== 'main_thread'\n ? selectedExecutionEntry.title\n : undefined;\n\n const mainThreadEntryId = useMemo(\n () => executionWorkspaceSnapshot?.entries.find((e) => e.kind === 'main_thread')?.id,\n [executionWorkspaceSnapshot],\n );\n\n const handleSubmitWithRouting = useCallback(\n async (input: string): Promise<void> => {\n if (\n selectedExecutionEntry &&\n selectedExecutionEntry.kind !== 'main_thread' &&\n selectedExecutionEntry.controls.includes('send')\n ) {\n await interactiveSession.sendAgentJob(selectedExecutionEntry.sourceId, input);\n } else {\n await handleSubmit(input);\n }\n },\n [selectedExecutionEntry, handleSubmit, interactiveSession],\n );\n\n // Sync session name from InteractiveSession when resuming\n useEffect(() => {\n const name = interactiveSession?.getName?.();\n if (name && !sessionName) setSessionName(name);\n }, [interactiveSession, sessionName]);\n\n useEffect(() => {\n let isMounted = true;\n props.startupUpdateNotice\n ?.then((notice) => {\n if (isMounted && notice !== undefined) {\n setUpdateNotice(notice);\n }\n })\n .catch(() => {\n // Startup update checks are best-effort and must not disrupt the TUI.\n });\n return () => {\n isMounted = false;\n };\n }, [props.startupUpdateNotice]);\n\n // Update terminal title\n useEffect(() => {\n const title = sessionName ? `Robota — ${sessionName}` : 'Robota';\n process.stdout.write(`\\x1b]0;${title}\\x07`);\n }, [sessionName]);\n\n // ESC abort\n useInput((_input: string, key: { escape: boolean }) => {\n if (!key.escape || !isThinking) return;\n if (\n permissionRequest ||\n showPluginTUI ||\n showTransportTUI ||\n showSessionPicker ||\n showExecutionWorkspaceSwitcher\n ) {\n return;\n }\n handleAbort();\n });\n\n // Ctrl+B toggles the execution workspace switcher.\n useInput((input: string, key: { ctrl?: boolean }) => {\n if (!key.ctrl || input !== 'b') return;\n if (permissionRequest || showPluginTUI || showSessionPicker || isShuttingDown) return;\n setShowExecutionWorkspaceSwitcher((shown) => !shown);\n });\n\n // ESC returns to main thread when a background entry is selected (and not thinking).\n useInput((_input: string, key: { escape: boolean }) => {\n if (!key.escape || isThinking) return;\n if (\n permissionRequest ||\n showPluginTUI ||\n showTransportTUI ||\n showSessionPicker ||\n showExecutionWorkspaceSwitcher\n ) {\n return;\n }\n if (\n selectedExecutionEntry &&\n selectedExecutionEntry.kind !== 'main_thread' &&\n mainThreadEntryId !== undefined\n ) {\n selectExecutionWorkspaceEntry(mainThreadEntryId);\n }\n });\n\n // Ctrl+C graceful shutdown\n useInput((input: string, key: { ctrl?: boolean }) => {\n if (!key.ctrl || input !== 'c' || isShuttingDown) return;\n void handleShutdown('prompt_input_exit').finally(() => exit());\n });\n\n useEffect(() => {\n const onSigterm = (): void => {\n if (isShuttingDown) return;\n void handleShutdown('other').finally(() => exit());\n };\n process.once('SIGINT', onSigterm);\n process.once('SIGTERM', onSigterm);\n return () => {\n process.off('SIGINT', onSigterm);\n process.off('SIGTERM', onSigterm);\n };\n }, [handleShutdown, exit, isShuttingDown]);\n\n useEffect(() => {\n if (!selectedExecutionEntry || selectedExecutionEntry.kind === 'main_thread') {\n setExecutionDetailPage(null);\n setExecutionDetailError(undefined);\n setIsExecutionDetailLoading(false);\n return;\n }\n\n let isCurrent = true;\n setIsExecutionDetailLoading(true);\n setExecutionDetailError(undefined);\n readExecutionWorkspaceDetail(selectedExecutionEntry.id)\n .then((page) => {\n if (!isCurrent) return;\n setExecutionDetailPage(page);\n setIsExecutionDetailLoading(false);\n })\n .catch((error: Error) => {\n if (!isCurrent) return;\n setExecutionDetailError(error.message);\n setIsExecutionDetailLoading(false);\n });\n\n return () => {\n isCurrent = false;\n };\n }, [executionWorkspaceSnapshot, readExecutionWorkspaceDetail, selectedExecutionEntry]);\n\n // Session may not be initialized yet\n let permissionMode: TPermissionMode = props.permissionMode ?? 'default';\n let sessionId = '';\n try {\n // allow-fallback: session initializes asynchronously; use defaults until ready\n const session = interactiveSession.getSession();\n permissionMode = session.getPermissionMode();\n sessionId = session.getSessionId();\n } catch {\n // allow-fallback: session initializes asynchronously; use defaults until ready\n // Not yet initialized\n }\n\n return (\n <Box flexDirection=\"column\">\n <Box flexDirection=\"column\" paddingX={1} marginBottom={1}>\n <Text color=\"cyan\" bold>{`\n ____ ___ ____ ___ _____ _\n | _ \\\\ / _ \\\\| __ ) / _ \\\\_ _|/ \\\\\n | |_) | | | | _ \\\\| | | || | / _ \\\\\n | _ <| |_| | |_) | |_| || |/ ___ \\\\\n |_| \\\\_\\\\\\\\___/|____/ \\\\___/ |_/_/ \\\\_\\\\\n`}</Text>\n <Text dimColor> v{props.version ?? '0.0.0'}</Text>\n </Box>\n {updateNotice && <UpdateNotice message={updateNotice} />}\n <Box flexDirection=\"column\" paddingX={1} flexGrow={1}>\n {selectedExecutionEntry && selectedExecutionEntry.kind !== 'main_thread' ? (\n <ExecutionWorkspaceDetailPane\n entry={selectedExecutionEntry}\n page={executionDetailPage}\n loading={isExecutionDetailLoading}\n error={executionDetailError}\n />\n ) : (\n <MessageList history={history} />\n )}\n {isShuttingDown && (\n <Box marginBottom={1}>\n <Text color=\"yellow\">Shutting down...</Text>\n </Box>\n )}\n {(isThinking || activeTools.length > 0) && (\n <Box flexDirection=\"column\" marginBottom={1}>\n <StreamingIndicator\n text={streamingText}\n activeTools={activeTools}\n isThinking={isThinking}\n />\n </Box>\n )}\n <BackgroundTaskPanel entries={backgroundWorkspaceEntries} />\n </Box>\n {showExecutionWorkspaceSwitcher && (\n <ExecutionWorkspaceSwitcher\n snapshot={executionWorkspaceSnapshot}\n selectedEntryId={selectedExecutionEntryId}\n onSelect={selectExecutionWorkspaceEntry}\n onClose={() => setShowExecutionWorkspaceSwitcher(false)}\n />\n )}\n {permissionRequest && <PermissionPrompt request={permissionRequest} />}\n {pendingModelId && (\n <ConfirmPrompt\n message={formatModelChangeConfirmationMessage(pendingModelId)}\n onSelect={handleModelConfirm}\n />\n )}\n {pendingInteractionPrompt && (\n <InteractivePrompt\n prompt={pendingInteractionPrompt}\n onSubmit={handleInteractionSubmit}\n onCancel={handleInteractionCancel}\n />\n )}\n {showPluginTUI && (\n <PluginTUI\n callbacks={pluginCallbacks}\n onClose={() => setShowPluginTUI(false)}\n addMessage={(msg) => addEntry(messageToHistoryEntry(createSystemMessage(msg.content)))}\n />\n )}\n {showTransportTUI && props.transportRegistry && (\n <TransportTUI\n registry={props.transportRegistry}\n onClose={() => setShowTransportTUI(false)}\n />\n )}\n {showSessionPicker && (\n <SessionPicker\n sessions={listResumableSessionSummaries(props.sessionStore, props.cwd)}\n onSelect={(id) => {\n setShowSessionPicker(false);\n props.onSessionSwitch(id);\n }}\n onCancel={() => {\n setShowSessionPicker(false);\n addEntry(messageToHistoryEntry(createSystemMessage('Session resume cancelled.')));\n }}\n />\n )}\n <SessionStatusBar\n cwd={cwd}\n permissionMode={permissionMode}\n modelId={props.modelId}\n providerType={props.providerType}\n sessionId={sessionId}\n isThinking={isThinking}\n activeToolCount={activeTools.length}\n activeBackgroundTaskCount={activeBackgroundTaskCount}\n hasPendingPrompt={pendingPrompt !== null}\n contextState={contextState}\n sessionName={sessionName}\n settings={statusLineSettings}\n activeAgentLabel={activeAgentLabel}\n />\n <InputArea\n onSubmit={handleSubmitWithRouting}\n onCancelQueue={handleCancelQueue}\n isDisabled={\n !!permissionRequest ||\n showPluginTUI ||\n showTransportTUI ||\n showSessionPicker ||\n showExecutionWorkspaceSwitcher ||\n isShuttingDown ||\n pendingInteractionPrompt !== null ||\n (isThinking && !!pendingPrompt) ||\n !isSelectedEntryInteractive\n }\n isAborting={isAborting}\n pendingPrompt={pendingPrompt}\n registry={registry}\n sessionName={sessionName}\n history={history}\n resolveInteraction={props.resolveInteraction}\n />\n {/* Permanent blank line below input — required for Korean IME stability. */}\n <Text> </Text>\n </Box>\n );\n}\n","/**\n * Ink render entry point.\n */\n\nimport React from 'react';\nimport { render } from 'ink';\nimport App from './App.js';\nimport type { IAIProvider } from '@robota-sdk/agent-core';\nimport type { TPermissionMode } from '@robota-sdk/agent-core';\nimport type {\n IBackgroundTaskRunner,\n ICommandHostAdapters,\n ICommandModule,\n IInteractiveSession,\n IInteractiveSessionStore,\n TSubagentRunnerFactory,\n TShellExecFn,\n CommandRegistry,\n} from '@robota-sdk/agent-framework';\nimport type { ITransportRegistryView } from '@robota-sdk/agent-interface-transport';\nimport type { ITuiCliAdapter } from './tui-cli-adapter.js';\nimport type { ITuiCommandInteraction } from './command-interaction.js';\n\nexport interface IRenderOptions {\n cwd: string;\n provider: IAIProvider;\n providerOverride?: string | undefined;\n providerType?: string | undefined;\n modelId?: string;\n language?: string;\n permissionMode?: TPermissionMode;\n maxTurns?: number;\n version?: string;\n sessionStore?: IInteractiveSessionStore;\n resumeSessionId?: string;\n showSessionPickerOnStart?: boolean;\n forkSession?: boolean;\n sessionName?: string;\n backgroundTaskRunners?: IBackgroundTaskRunner[];\n subagentRunnerFactory?: TSubagentRunnerFactory;\n commandModules?: readonly ICommandModule[];\n commandHostAdapters?: ICommandHostAdapters;\n shellExec?: TShellExecFn;\n startupUpdateNotice?: Promise<string | undefined>;\n transportRegistry?: ITransportRegistryView<IInteractiveSession>;\n cliAdapter: ITuiCliAdapter;\n reloadPluginCommandSource?: (registry: CommandRegistry) => void;\n agentName?: string;\n resolveInteraction?: (commandName: string) => ITuiCommandInteraction | undefined;\n}\n\nexport async function renderApp(options: IRenderOptions): Promise<void> {\n process.on('unhandledRejection', (reason) => {\n process.stderr.write(`\\n[UNHANDLED REJECTION] ${reason}\\n`);\n if (reason instanceof Error) {\n process.stderr.write(`${reason.stack}\\n`);\n }\n });\n\n const instance = render(<App {...options} />, { exitOnCtrlC: false });\n await instance.waitUntilExit();\n}\n","import type { IInteractiveSession } from '@robota-sdk/agent-framework';\nimport type { IConfigurableTransport } from '@robota-sdk/agent-interface-transport';\nimport type { TUniversalValue } from '@robota-sdk/agent-core';\nimport { renderApp, type IRenderOptions } from './render.js';\n\nexport class TuiTransport implements IConfigurableTransport<IInteractiveSession> {\n readonly name = 'tui';\n readonly defaultEnabled = true;\n readonly optionsSchema = {};\n\n private readonly options: IRenderOptions;\n\n constructor(options: IRenderOptions) {\n this.options = options;\n }\n\n attach(_session: IInteractiveSession): void {\n // TuiTransport creates its own InteractiveSession internally via useInteractiveSession.\n }\n\n async start(): Promise<void> {\n await renderApp(this.options);\n }\n\n async stop(): Promise<void> {\n // Ink exits when the user triggers shutdown from within the TUI.\n }\n\n validateOptions(_options: Record<string, TUniversalValue>): boolean {\n return true;\n }\n}\n"],"mappings":"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"}