@agimon-ai/po-runner 0.0.0-alpha.21 → 0.0.0-alpha.22

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 (49) hide show
  1. package/dist/{bashRunService-Ci0cGdYO.d.mts → bashRunService-BL4JIUi2.d.mts} +6 -1
  2. package/dist/bashRunService-BL4JIUi2.d.mts.map +1 -0
  3. package/dist/{bashRunService-DjOH5kye.cjs → bashRunService-CJhMNrPz.cjs} +8 -4
  4. package/dist/bashRunService-CJhMNrPz.cjs.map +1 -0
  5. package/dist/{bashRunService-Cl3pYccr.mjs → bashRunService-DbYsj1zc.mjs} +8 -4
  6. package/dist/bashRunService-DbYsj1zc.mjs.map +1 -0
  7. package/dist/bashRunService.cjs +1 -1
  8. package/dist/bashRunService.d.mts +1 -1
  9. package/dist/bashRunService.d.mts.map +1 -1
  10. package/dist/bashRunService.mjs +1 -1
  11. package/dist/bashTool.cjs +1 -1
  12. package/dist/bashTool.d.mts +2 -2
  13. package/dist/bashTool.mjs +1 -1
  14. package/dist/bin/cli.cjs +1 -1
  15. package/dist/bin/cli.mjs +1 -1
  16. package/dist/extensions/native.mjs +212 -203
  17. package/dist/extensions/native.mjs.map +1 -1
  18. package/dist/extensions/server.cjs +2 -2
  19. package/dist/extensions/server.mjs +2 -2
  20. package/dist/extensions/web.mjs +334 -500
  21. package/dist/extensions/web.mjs.map +1 -1
  22. package/dist/{headless-Dko_yBiy.cjs → headless-C4Bvl2B-.cjs} +8 -4
  23. package/dist/headless-C4Bvl2B-.cjs.map +1 -0
  24. package/dist/{headless-DOlCixyf.mjs → headless-DidUBSSf.mjs} +8 -4
  25. package/dist/headless-DidUBSSf.mjs.map +1 -0
  26. package/dist/{index--xF7DvsE.d.mts → index-CXbcmf-G.d.mts} +2 -2
  27. package/dist/{index--xF7DvsE.d.mts.map → index-CXbcmf-G.d.mts.map} +1 -1
  28. package/dist/{index-BzeXJk6V.d.mts → index-DJkjYgir.d.mts} +3 -3
  29. package/dist/{index-BzeXJk6V.d.mts.map → index-DJkjYgir.d.mts.map} +1 -1
  30. package/dist/index.cjs +2 -2
  31. package/dist/index.d.mts +2 -2
  32. package/dist/index.mjs +2 -2
  33. package/dist/responseEnvelope.d.mts +1 -1
  34. package/dist/{runnerDependencies-7h_cxOva.mjs → runnerDependencies-CamKwphq.mjs} +2 -2
  35. package/dist/{runnerDependencies-7h_cxOva.mjs.map → runnerDependencies-CamKwphq.mjs.map} +1 -1
  36. package/dist/{runnerDependencies-DSun3xO-.cjs → runnerDependencies-vkpJfxZZ.cjs} +2 -2
  37. package/dist/{runnerDependencies-DSun3xO-.cjs.map → runnerDependencies-vkpJfxZZ.cjs.map} +1 -1
  38. package/dist/runnerDependencies.cjs +1 -1
  39. package/dist/runnerDependencies.d.mts +1 -1
  40. package/dist/runnerDependencies.mjs +1 -1
  41. package/dist/{type-Do0YxwVQ.d.mts → type-BQ2shEB5.d.mts} +2 -2
  42. package/dist/{type-Do0YxwVQ.d.mts.map → type-BQ2shEB5.d.mts.map} +1 -1
  43. package/dist/types.d.mts +1 -1
  44. package/package.json +17 -17
  45. package/dist/bashRunService-Ci0cGdYO.d.mts.map +0 -1
  46. package/dist/bashRunService-Cl3pYccr.mjs.map +0 -1
  47. package/dist/bashRunService-DjOH5kye.cjs.map +0 -1
  48. package/dist/headless-DOlCixyf.mjs.map +0 -1
  49. package/dist/headless-Dko_yBiy.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"native.mjs","names":["isRecord","SessionFrameSender","fontOf","Button","Input","Label","Sheet","SheetBody","SheetContent","SheetHeader","SheetTitle","Textarea","PoNativeTheme","useState","StyleSheet","launchProblems","runnerLaunchLine","requestRunnerStart","LaunchRunnerSheet","sessionId","send","defaultCwd","onClose","command","setCommand","cwd","setCwd","name","setName","interactive","setInteractive","request","problems","open","styles","form","checked","value","line","length","error","join","meta","create","theme","gap","spacing","uni__dependencies","color","colors","green","fontFamily","mono","fontSize","sm","red","sans","base","dim","styles","WebPluginSlotProps","fontOf","Button","Input","Label","PoNativeTheme","useEffect","useState","StyleSheet","RunnerLogResponse","RunnerRunView","logViewLines","tailLineNumbers","fetchRunnerLog","requestRunnerStop","useRunners","runnerLogTab","run","id","label","name","panel","props","RunnerLogPanel","sessionId","runId","sendSessionFrame","session","runs","find","candidate","typed","setTyped","query","setQuery","ignoreCase","setIgnoreCase","context","setContext","following","setFollowing","requestKey","loaded","setLoaded","key","slice","error","undefined","timer","setTimeout","clearTimeout","controller","AbortController","ReturnType","read","result","lines","grep","contextLines","signal","aborted","running","abort","text","numbers","totalLines","length","lineNumbers","stopping","stopRequested","includes","styles","title","meta","state","command","cwd","actions","selected","value","lineCount","log","exists","map","line","index","logPath","path","create","theme","flex","gap","spacing","padding","backgroundColor","colors","bg","uni__dependencies","color","hi","fontWeight","fontFamily","sans","fontSize","base","dim","sm","lineHeight","red","flexDirection","flexWrap","deep","styles","WebPluginSlotProps","fontOf","PoNativeTheme","useMemo","StyleSheet","RunnerRunView","readRunnerScreen","sendRunnerInput","runnerShellTab","run","id","label","name","panel","props","RunnerShellPanel","sessionId","runId","renderRunnerTerminal","request","undefined","key","read","from","generation","signal","AbortSignal","write","text","styles","meta","create","theme","flex","backgroundColor","colors","bg","uni__dependencies","color","dim","fontFamily","sans","fontSize","sm","styles","WebPluginSlotProps","fontOf","Button","Dot","ListRow","PoNativeTheme","useEffect","useRef","useState","StyleSheet","RunnerRunView","formatRunnerUptime","RUNNER_SHELL_REQUEST","requestRunnerStart","requestRunnerStop","LaunchRunnerSheet","useRunners","useRunnerTail","runnerLogTab","runnerShellTab","runnersTab","id","label","panel","RunnersPanel","RunnerRow","run","props","stopping","now","detail","tail","sessionId","state","styles","row","name","startedAt","interactive","openTransientTab","undefined","meta","command","cwd","actions","sendSessionFrame","RunnersActivitySection","session","running","runs","filter","setNow","Date","timer","setInterval","clearInterval","length","map","stopRequested","includes","launching","setLaunching","baseline","ReadonlySet","timeout","ReturnType","setTimeout","current","shell","find","has","clearTimeout","title","Set","create","theme","flex","gap","spacing","padding","backgroundColor","colors","bg","uni__dependencies","paddingVertical","flexDirection","flexWrap","color","hi","fontFamily","sans","fontSize","base","fontWeight","dim","sm","lineHeight","activityGroupRunners","channelRunnerRuns","fillRunners"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/format.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/launchLine.ts","../../src/constants/webRunners.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/runnersStore.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/LaunchRunnerSheet.native.tsx","../../src/constants/webRunnerLog.ts","../../src/types/webRunnerLog.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/logApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/runnerHooks.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnerLogPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/_lib/screenApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnerShellPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnersPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/activity-group/runners.native.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/runner-runs.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/Runners.activity.runners.native.tsx","../../generated/native.ts"],"sourcesContent":["/**\n * Local copy of the runtime's formatUptime (src/services/bashResult/index.ts):\n * the web plugin may reach only src/types, so the one helper it needs lives here.\n */\nexport function formatRunnerUptime(startedAt: string, now: number): string {\n const started = Date.parse(startedAt);\n if (Number.isNaN(started)) return 'unknown';\n const seconds = Math.max(0, Math.floor((now - started) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;\n}\n\n/** A bounded log view: what to render, and what the bound left out. */\nexport interface LogView {\n lines: string[];\n /** Lines dropped off the top to stay within the bound. */\n hidden: number;\n}\n\nexport interface LogViewOptions {\n /**\n * Drop the slice's last line because it is a fragment the follow stream will\n * deliver again, whole. Set only while following: a finished run's last line\n * may legitimately lack a newline, and dropping it would hide real output.\n */\n dropPartialTail?: boolean;\n}\n\n/**\n * The lines a log view shows: the slice's text, then whatever the follow\n * stream appended, bounded to the newest `max`.\n *\n * A log file ends with a newline, and the reader hands its text back with that\n * newline intact, so a naive split reports one blank line more than the file\n * has. Dropping exactly one trailing empty entry keeps the count the reader\n * sees equal to the count the server reported.\n */\nexport function logViewLines(\n text: string,\n appended: readonly string[],\n max: number,\n options: LogViewOptions = {},\n): LogView {\n const split = text.split('\\n');\n if (split.length > 0 && split[split.length - 1] === '') split.pop();\n if (options.dropPartialTail === true && split.length > 0) split.pop();\n const all = [...split, ...appended];\n const lines = all.slice(-max);\n return { lines, hidden: all.length - lines.length };\n}\n\n/**\n * Absolute 1-based numbers for a tail, counted back from the last line.\n *\n * A tail is contiguous, so only its end has to be known. Grep results are not\n * contiguous and carry their own numbers from the reader instead.\n */\nexport function tailLineNumbers(lastLineNumber: number, count: number): number[] {\n const first = Math.max(1, lastLineNumber - count + 1);\n return Array.from({ length: count }, (_, index) => first + index);\n}\n\n/**\n * Whether the view is actually following a growing log.\n *\n * Three things must hold: the reader asked to follow, no query is set (a\n * filtered view is a snapshot of the whole file, which a stream cannot\n * assemble a chunk at a time), and the runner is still writing. Without the\n * last one a finished run would claim to be tailing a file nothing will ever\n * append to.\n */\nexport function isFollowingLive(following: boolean, filtering: boolean, running: boolean): boolean {\n return following && !filtering && running;\n}\n","/**\n * The `/runners start` line the launch form sends.\n *\n * WHY THE BUILDER LIVES HERE AND THE PARSER DOES NOT:\n * Cockpit code is compiled into the host bundle and may import only this\n * package's own web and type modules, so it cannot share the session's parser\n * in src/services. The two are pinned together by a test that parses what this\n * writes, which is the only guarantee that matters: the line has to survive\n * the trip.\n */\n\nexport const RUNNERS_START_LINE = '/runners start';\n/** A persistent login shell for the direct shell action in Runner Space. */\nexport const RUNNER_SHELL_COMMAND = 'exec \"${SHELL:-/bin/bash}\" -l';\n/** Ends the options and begins the command; the command may hold `=` and flags of its own. */\nexport const RUNNERS_COMMAND_SEPARATOR = '--';\n\nexport interface RunnerLaunchRequest {\n command: string;\n cwd?: string;\n name?: string;\n interactive?: boolean;\n}\n\n/** The no-form launch used when a reader asks for a shell rather than a command. */\nexport const RUNNER_SHELL_REQUEST: RunnerLaunchRequest = {\n command: RUNNER_SHELL_COMMAND,\n name: 'shell',\n interactive: true,\n};\n\n/** Quotes a value that carries whitespace, which is how a value survives tokenizing. */\nfunction quote(value: string): string {\n return /\\s/u.test(value) ? `\"${value}\"` : value;\n}\n\nexport function runnerLaunchLine(request: RunnerLaunchRequest): string {\n const cwd = request.cwd?.trim() ?? '';\n const name = request.name?.trim() ?? '';\n const pairs = [\n ...(name === '' ? [] : [`name=${quote(name)}`]),\n ...(cwd === '' ? [] : [`cwd=${quote(cwd)}`]),\n ...(request.interactive === true ? ['interactive=true'] : []),\n ];\n // The separator is always written, even with no options before it, so the\n // command is never re-read as a `key=value` pair.\n return [RUNNERS_START_LINE, ...pairs, RUNNERS_COMMAND_SEPARATOR, request.command.trim()].join(' ');\n}\n\n/** What the form will not let a reader send, worded the way the session would answer. */\nexport function launchProblems(request: RunnerLaunchRequest): string[] {\n const problems: string[] = [];\n if (request.command.trim() === '') problems.push('A runner needs a command to run.');\n return problems;\n}\n","export const RUNNER_RUNS_TYPE = 'runner_runs';\n","import { defineSessionStore, type SessionFrameSender } from '@agimon-ai/po-core/native';\n\nimport { RUNNER_RUNS_TYPE } from '../../../../../constants/webRunners';\nimport { type RunnerRunView } from '../../../../../types/webRunners';\nimport { type RunnerLaunchRequest, runnerLaunchLine } from './launchLine';\n\n/** The runtime's slash verb that stops one runner headlessly. */\nconst STOP_COMMAND = '/runners stop';\n\n/** One session's record: the hub's last report plus what this page asked for. */\nexport interface RunnersSession {\n /** The runners the hub last reported; presented order preserved. */\n runs: RunnerRunView[];\n /** Runners a stop was asked for and that have not yet reported an exit. */\n stopRequested: string[];\n}\n\nexport const runners = defineSessionStore<RunnersSession>({ runs: [], stopRequested: [] });\n\n/** The runner channel keeps the dock's busy state aligned with its rendered run list. */\nexport const runnerActivitySource = {\n subscribe(listener: () => void) {\n const subscription = runners.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return runners.select(runners.store.state, sessionId).runs.some((run) => run.state === 'running');\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Asks the runtime to stop a runner through the same slash command the TUI's\n * Runner Space uses. The request is remembered until the runner's record\n * reports an exit; the runtime, not this click, decides when that is.\n */\nexport function requestRunnerStop(send: SessionFrameSender, sessionId: string, id: string): void {\n send(sessionId, { type: 'prompt', message: `${STOP_COMMAND} ${id}` });\n runners.update(sessionId, (current) => ({\n ...current,\n stopRequested: [...current.stopRequested.filter((known) => known !== id), id],\n }));\n}\n\n/**\n * Asks the runtime to start a runner, through the same prompt frame the stop\n * request uses and the same way agents and workflows launch their own work.\n *\n * Nothing is recorded as pending here. The runtime names the run, and it\n * arrives in the feed on its own; guessing at an id before it exists would\n * only have to be reconciled later.\n */\nexport function requestRunnerStart(send: SessionFrameSender, sessionId: string, request: RunnerLaunchRequest): void {\n send(sessionId, { type: 'prompt', message: runnerLaunchLine(request) });\n}\n\nexport interface RunnerRunsPayload {\n runs: RunnerRunView[];\n}\n\n/** The plugin's session data channel: 'runner_runs' payloads into the store. */\nexport const runnerRunsChannel = runners.channel<RunnerRunsPayload>({\n channel: RUNNER_RUNS_TYPE,\n parse(input) {\n if (!isRecord(input) || !Array.isArray(input.runs)) return null;\n return { runs: input.runs.filter(isRecord) as unknown as RunnerRunView[] };\n },\n reduce(current, { runs }) {\n // A stop request is spent once the runner reports an exit or leaves the feed.\n const stillRunning = new Set(runs.filter((run) => run.state === 'running').map((run) => run.id));\n return { runs, stopRequested: current.stopRequested.filter((id) => stillRunning.has(id)) };\n },\n});\n","import type { SessionFrameSender } from '@agimon-ai/po-core/native';\nimport {\n fontOf,\n Button,\n Input,\n Label,\n Sheet,\n SheetBody,\n SheetContent,\n SheetHeader,\n SheetTitle,\n Textarea,\n} from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useState } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport { launchProblems, runnerLaunchLine } from '../_lib/launchLine';\nimport { requestRunnerStart } from '../_lib/runnersStore.native';\n\nexport function LaunchRunnerSheet({\n sessionId,\n send,\n defaultCwd,\n onClose,\n}: {\n sessionId: string;\n send: SessionFrameSender;\n defaultCwd?: string;\n onClose: () => void;\n}) {\n const [command, setCommand] = useState('');\n const [cwd, setCwd] = useState(defaultCwd ?? '');\n const [name, setName] = useState('');\n const [interactive, setInteractive] = useState(false);\n const request = { command, cwd, name, interactive };\n const problems = launchProblems(request);\n return (\n <Sheet\n open\n onOpenChange={(open) => {\n if (!open) onClose();\n }}\n >\n <SheetContent>\n <SheetHeader>\n <SheetTitle>Launch a runner</SheetTitle>\n </SheetHeader>\n <SheetBody>\n <View style={styles.form}>\n <Label>Command</Label>\n <Textarea\n testID=\"runner-launch-command\"\n value={command}\n onChangeText={setCommand}\n placeholder=\"pnpm test\"\n />\n <Label>Cwd</Label>\n <Input\n testID=\"runner-launch-cwd\"\n value={cwd}\n onChangeText={setCwd}\n placeholder=\"the session's own directory\"\n />\n <Label>Name</Label>\n <Input\n testID=\"runner-launch-name\"\n value={name}\n onChangeText={setName}\n placeholder=\"chosen for you when empty\"\n />\n <Label>Needs a terminal, for a command that prompts (requires rmux or tmux)</Label>\n <Button\n testID=\"runner-launch-interactive\"\n variant=\"outline\"\n accessibilityState={{ checked: interactive }}\n onPress={() => setInteractive((value) => !value)}\n >\n {interactive ? 'Terminal enabled' : 'Terminal off'}\n </Button>\n <Label>Sent to the session</Label>\n <Text selectable testID=\"runner-launch-line\" style={styles.line}>\n {runnerLaunchLine(request)}\n </Text>\n {problems.length > 0 ? <Text style={styles.error}>{problems.join(' ')}</Text> : null}\n <Button variant=\"outline\" onPress={onClose}>\n Cancel\n </Button>\n <Button\n testID=\"runner-launch-submit\"\n disabled={problems.length > 0}\n onPress={() => {\n if (problems.length > 0) return;\n requestRunnerStart(send, sessionId, request);\n onClose();\n }}\n >\n Launch\n </Button>\n <Text style={styles.meta}>It appears above once the runtime starts it.</Text>\n </View>\n </SheetBody>\n </SheetContent>\n </Sheet>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n form: { gap: theme.spacing(2) },\n line: { color: theme.colors.green, fontFamily: fontOf(theme.fontFamily.mono), fontSize: theme.fontSize.sm },\n error: { color: theme.colors.red, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.base },\n meta: { color: theme.colors.dim, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.sm },\n}));\n","export const RUNNER_API_BASE_PATH = 'runner';\nexport const RUN_ID_PARAM = 'runId';\nexport const RUNNER_SCREEN_EVENT = 'screen';\nexport const RUNNER_LOG_STREAM_EVENT = 'append';\nexport const RUNNER_LOG_PING_EVENT = 'ping';\n","import type { LogSlice } from './logReader';\n\n/**\n * The runner log API, shared by this package's session-scoped routes and its\n * cockpit plugin. The two halves run in different processes, so the wire\n * vocabulary is declared here: the browser half may reach `src/types` and\n * nothing else on the server side.\n *\n * Where the routes live is not here. That is `src/types/apiRoutes`, which both\n * halves read, and the generated client turns into the URLs the page addresses.\n * The file a run writes to is still read from its metadata record by the server\n * alone.\n */\n\n/**\n * One chunk of an attached pane's output.\n *\n * Base64 because these are terminal bytes, escape sequences and all, and a\n * server-sent event is a line-oriented text frame that would mangle them.\n */\nexport interface RunnerScreenEvent {\n chunk: string;\n /** Byte offset just past this chunk, so a reconnect resumes rather than replays. */\n offset?: number;\n /** Set once the runner exits, so the page can stop watching. */\n ended?: boolean;\n}\n\n/** A finite byte slice for sealed HTTP followers. Decode chunks incrementally, not independently. */\nexport interface RunnerOutputResponse {\n /** Base64 bytes, preserving split UTF-8 characters and terminal escape sequences. */\n chunk: string;\n offset: number;\n /** The file was replaced or became shorter than the requested offset; discard the previous display/decoder state. */\n reset: boolean;\n /** Opaque raw file identity. Send back on screen/read to detect replacement, including regrowth. */\n generation?: string;\n exists: boolean;\n /** More bytes were present at read time; request the next slice before waiting. */\n hasMore: boolean;\n /** True only once the runner ended and all available bytes have been read. */\n ended: boolean;\n}\n\n/** The body of a keystroke POST. Text, not key codes: the pane wants bytes. */\nexport interface RunnerInputRequest {\n text: string;\n}\n\n/** The named SSE event carrying a RunnerScreenEvent payload. */\n\n/**\n * A log request as query parameters. `grep` is a literal substring, not a\n * regular expression, because that is what the reader matches; `lines` bounds\n * the answer to the last N lines of whatever survived the filter.\n */\nexport interface RunnerLogQueryParams {\n lines?: number;\n grep?: string;\n ignoreCase?: boolean;\n contextLines?: number;\n}\n\n/** The slice the log route answers with, plus which runner it came from. */\nexport interface RunnerLogResponse extends LogSlice {\n runId: string;\n /** True while the runner is still writing, so the page knows following is worth offering. */\n running: boolean;\n}\n\n/**\n * One server-sent event on the follow stream: the lines appended since the last\n * one. The stream never filters: a page that sets a query stops following and\n * reads a filtered slice instead, because grep with context is a whole-file\n * answer and cannot be assembled from a chunk at a time.\n */\nexport interface RunnerLogStreamEvent {\n /** Appended lines, in order; empty when the event only reports the runner ending. */\n lines: string[];\n /**\n * Byte offset just past the last line in this event.\n *\n * A follower that loses the stream resumes here. Without it the page could\n * only fall back to the offset its last slice reported, which every line\n * delivered since has already moved past, so a reconnect would replay them.\n */\n offset?: number;\n /** Set once the runner exits, so the page can stop following without polling the run list. */\n ended?: boolean;\n}\n\n/** The named SSE event carrying a RunnerLogStreamEvent payload. */\n\n/**\n * The named SSE event that carries nothing.\n *\n * A runner can be alive and silent for minutes, which on the wire is\n * indistinguishable from a connection that died. This is sent on a timer so\n * the socket keeps proving itself. Readers that only listen for `append`\n * ignore it, which is what makes it safe to add.\n */\n\n/** Query parameter names, shared so the page and the route cannot drift apart. */\nexport const RUNNER_LOG_PARAMS = {\n lines: 'lines',\n grep: 'grep',\n ignoreCase: 'ignoreCase',\n contextLines: 'contextLines',\n from: 'from',\n generation: 'generation',\n} as const;\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport { RUN_ID_PARAM } from '../constants/webRunnerLog';\nimport { RUNNER_LOG_PARAMS, type RunnerLogResponse, type RunnerOutputResponse } from './webRunnerLog';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path: the build reads both off\n * `src/extensions/workspaces/sessions/(backend)/api/runner/`, so the mount is\n * stated once, by the folder that creates it. This package stated it four times\n * before, once per URL builder, each of them re-spelling `/plugins/` and the\n * session prefix by hand.\n *\n * The Hono app registers these paths verbatim and the browser addresses them,\n * so a path cannot move on one side alone. `:runId` is Hono's own parameter\n * syntax for that reason; a caller supplies the value as `params`, and the\n * client encodes the segment.\n */\nconst routes = {\n log: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log`,\n query: [\n RUNNER_LOG_PARAMS.lines,\n RUNNER_LOG_PARAMS.grep,\n RUNNER_LOG_PARAMS.ignoreCase,\n RUNNER_LOG_PARAMS.contextLines,\n ],\n response: undefined as unknown as ApiResponseOf<RunnerLogResponse>,\n },\n /**\n * The live tail of that same log.\n *\n * `stream: true`, so the client exposes a URL and no call method: the\n * consumer is the browser’s own SSE reader, and a relayed call would\n * buffer a stream that never ends.\n */\n logStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n /** The unscrubbed pane bytes, for a terminal emulator rather than a reader. */\n screenStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/screen/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n /** Finite byte reads keep sealed HTTP exchanges bounded, unlike SSE. */\n logRead: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log/read`,\n query: [RUNNER_LOG_PARAMS.from],\n response: undefined as unknown as ApiResponseOf<RunnerOutputResponse>,\n },\n screenRead: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/screen/read`,\n query: [RUNNER_LOG_PARAMS.from, RUNNER_LOG_PARAMS.generation],\n response: undefined as unknown as ApiResponseOf<RunnerOutputResponse>,\n },\n input: {\n method: 'POST',\n path: `/runners/:${RUN_ID_PARAM}/screen/input`,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, nativeApiTransport, sessionApiAddress } from '@agimon-ai/po-core/native';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'runner' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'runner',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../generated/client.native';\nimport { RUN_ID_PARAM } from '../../../../../constants/webRunnerLog';\nimport {\n RUNNER_LOG_PARAMS,\n type RunnerLogQueryParams,\n type RunnerLogResponse,\n} from '../../../../../types/webRunnerLog';\n\n/**\n * The page's half of this package's log API. The only place the cockpit talks\n * HTTP to the hub for a runner, so if the transport ever changes, it changes\n * here alone.\n *\n * The generated client owns every URL: a route is named, a session id selects\n * that session's own copy of the API, and the run id is a path parameter the\n * client substitutes and encodes. Nothing here spells a mount, a prefix or a\n * proxy parameter, which is what the four deleted URL builders each did by\n * hand.\n */\n\nexport type RunnerLogResult = { slice: RunnerLogResponse } | { error: string };\n\nconst UNREACHABLE = 'The cockpit hub is unreachable.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Reads one runner's log: the last N lines, or the lines matching a substring with context. */\nexport async function fetchRunnerLog(\n sessionId: string,\n runId: string,\n params: RunnerLogQueryParams = {},\n signal?: AbortSignal,\n): Promise<RunnerLogResult> {\n const result = await api.session(sessionId).log({\n params: { [RUN_ID_PARAM]: runId },\n // An unset parameter is left out rather than sent empty: the route reads a\n // missing one as its own default, and an empty grep as no filter at all.\n query: {\n [RUNNER_LOG_PARAMS.lines]: params.lines,\n [RUNNER_LOG_PARAMS.grep]: params.grep === '' ? undefined : params.grep,\n [RUNNER_LOG_PARAMS.ignoreCase]: params.ignoreCase === true ? true : undefined,\n [RUNNER_LOG_PARAMS.contextLines]: params.contextLines,\n },\n ...(signal === undefined ? {} : { signal }),\n });\n if (!result.ok) {\n // Status 0 is the transport never answering, which covers both a dead hub\n // and the caller replacing this request. An abort is the caller's own doing\n // and is reported as no answer rather than as a failure to show.\n if (result.status === 0) return { error: signal?.aborted === true ? '' : UNREACHABLE };\n return { error: result.error === '' ? `The hub answered ${String(result.status)}.` : result.error };\n }\n if (!isRecord(result.data) || typeof result.data.text !== 'string') {\n return { error: `The hub answered ${String(result.status)}.` };\n }\n return { slice: result.data };\n}\n","import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';\n\nimport { fetchRunnerLog } from '../_lib/logApi.native';\nimport { runners } from '../_lib/runnersStore.native';\n\nexport function useRunners(sessionId: string | null) {\n const subscribe = useCallback((listener: () => void) => {\n const subscription = runners.store.subscribe(listener);\n return () => subscription.unsubscribe();\n }, []);\n return useSyncExternalStore(subscribe, () => runners.select(runners.store.state, sessionId));\n}\n\n/** Native uses finite reads instead of browser SSE. Read a bounded tail through the host's sealed transport. */\nexport function useRunnerTail(sessionId: string | null, runId: string, running: boolean) {\n const [tail, setTail] = useState<{ id: string; text: string }>();\n useEffect(() => {\n if (sessionId === null || !running) return;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const read = async () => {\n try {\n const result = await fetchRunnerLog(sessionId, runId, { lines: 5 }, controller.signal);\n if (controller.signal.aborted) return;\n if ('slice' in result) {\n const text = result.slice.text\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .at(-1);\n if (text !== undefined) setTail({ id: `${sessionId}:${runId}`, text });\n if (!result.slice.running) return;\n }\n } catch {\n // A glance keeps the last known output when a read is unavailable.\n }\n if (!controller.signal.aborted) timer = setTimeout(() => void read(), 2_000);\n };\n void read();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [sessionId, runId, running]);\n return running && tail?.id === `${sessionId}:${runId}` ? tail.text : undefined;\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf, Button, Input, Label } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerLogResponse } from '../../../../../types/webRunnerLog';\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { logViewLines, tailLineNumbers } from '../_lib/format';\nimport { fetchRunnerLog } from '../_lib/logApi.native';\nimport { requestRunnerStop } from '../_lib/runnersStore.native';\nimport { useRunners } from './runnerHooks.native';\n\nexport function runnerLogTab(run: RunnerRunView) {\n return {\n id: `runner-log-${run.id}`,\n label: `log · ${run.name}`,\n panel: (props: WebPluginSlotProps) => <RunnerLogPanel {...props} runId={run.id} />,\n };\n}\n\nexport function RunnerLogPanel({ sessionId, runId, sendSessionFrame }: WebPluginSlotProps & { runId: string }) {\n const session = useRunners(sessionId);\n const run = session.runs.find((candidate) => candidate.id === runId);\n const [typed, setTyped] = useState('');\n const [query, setQuery] = useState('');\n const [ignoreCase, setIgnoreCase] = useState(false);\n const [context, setContext] = useState(2);\n const [following, setFollowing] = useState(true);\n const requestKey = `${sessionId}:${runId}:${query}:${ignoreCase}:${context}:${following}`;\n const [loaded, setLoaded] = useState<{ key: string; slice?: RunnerLogResponse; error: string }>();\n const slice = loaded?.key === requestKey ? loaded.slice : undefined;\n const error = loaded?.key === requestKey ? loaded.error : '';\n useEffect(() => {\n const timer = setTimeout(() => setQuery(typed), 200);\n return () => clearTimeout(timer);\n }, [typed]);\n useEffect(() => {\n if (sessionId === null) return;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const read = async () => {\n const result = await fetchRunnerLog(\n sessionId,\n runId,\n { lines: 2000, grep: query, ignoreCase, contextLines: context },\n controller.signal,\n );\n if (controller.signal.aborted) return;\n setLoaded(\n 'error' in result\n ? { key: requestKey, error: result.error }\n : { key: requestKey, slice: result.slice, error: '' },\n );\n if (following && query === '' && ('error' in result || result.slice.running))\n timer = setTimeout(() => void read(), 2_000);\n };\n void read();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [sessionId, runId, query, ignoreCase, context, following, requestKey]);\n const lines = logViewLines(slice?.text ?? '', [], 2000).lines;\n const numbers = query === '' ? tailLineNumbers(slice?.totalLines ?? 0, lines.length) : (slice?.lineNumbers ?? []);\n const stopping = session.stopRequested.includes(runId);\n return (\n <View testID=\"runner-log-panel\" style={styles.panel}>\n <Text style={styles.title}>{run?.name ?? runId}</Text>\n <Text style={styles.meta}>{run?.state ?? 'no longer listed; its log stays readable'}</Text>\n {run ? (\n <>\n <Text selectable style={styles.meta}>\n {run.command}\n </Text>\n <Text selectable style={styles.meta}>\n {run.cwd}\n </Text>\n </>\n ) : null}\n {run?.state === 'running' && sessionId !== null ? (\n <Button\n variant=\"danger-outline\"\n disabled={stopping}\n onPress={() => requestRunnerStop(sendSessionFrame, sessionId, runId)}\n >\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n ) : null}\n <Label>Search this log</Label>\n <Input testID=\"runner-log-search\" value={typed} onChangeText={setTyped} />\n <View style={styles.actions}>\n <Button\n variant=\"outline\"\n accessibilityState={{ selected: ignoreCase }}\n onPress={() => setIgnoreCase((value) => !value)}\n >\n aA\n </Button>\n <Button variant=\"outline\" disabled={query === ''} onPress={() => setContext((value) => (value === 0 ? 2 : 0))}>\n ± {context} lines\n </Button>\n <Button\n variant=\"outline\"\n disabled={query !== '' || slice?.running !== true}\n accessibilityState={{ selected: following }}\n onPress={() => setFollowing((value) => !value)}\n >\n {query !== '' ? 'Follow · paused' : 'Follow'}\n </Button>\n </View>\n <Text style={styles.meta}>\n {slice === undefined\n ? 'Reading…'\n : query !== ''\n ? `${slice.lineCount} matching of ${slice.totalLines} lines`\n : `${following && slice.running ? 'Tailing' : 'Showing'} last ${lines.length} of ${slice.totalLines} lines`}\n </Text>\n <ScrollView style={styles.log}>\n {error !== '' ? (\n <Text accessibilityRole=\"alert\" style={styles.error}>\n {error}\n </Text>\n ) : slice?.exists === false ? (\n <Text style={styles.meta}>This runner has not written a log yet.</Text>\n ) : slice && lines.length === 0 ? (\n <Text style={styles.meta}>{query === '' ? 'The log is empty.' : 'Nothing matched.'}</Text>\n ) : (\n lines.map((line, index) => (\n <Text selectable key={`${numbers[index] ?? index}`} style={styles.meta}>\n {numbers[index]} {line}\n </Text>\n ))\n )}\n </ScrollView>\n <Text selectable style={styles.meta}>\n {run?.logPath ?? slice?.path ?? ''}\n </Text>\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, gap: theme.spacing(2), padding: theme.spacing(3), backgroundColor: theme.colors.bg },\n title: {\n color: theme.colors.hi,\n fontWeight: '600',\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n },\n meta: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n error: { color: theme.colors.red, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.base },\n actions: { flexDirection: 'row', gap: theme.spacing(2), flexWrap: 'wrap' },\n log: { flex: 1, backgroundColor: theme.colors.deep },\n}));\n","import { api } from '../../../../../../generated/client.native';\nimport { RUN_ID_PARAM } from '../../../../../constants/webRunnerLog';\nimport { RUNNER_LOG_PARAMS, type RunnerOutputResponse } from '../../../../../types/webRunnerLog';\n\n/** Finite native reads preserve raw terminal bytes and generation-based replacement detection. */\nexport async function readRunnerScreen(\n sessionId: string,\n runId: string,\n from: number,\n generation: string | undefined,\n signal: AbortSignal,\n): Promise<RunnerOutputResponse> {\n const result = await api.session(sessionId).screenRead({\n params: { [RUN_ID_PARAM]: runId },\n query: { [RUNNER_LOG_PARAMS.from]: from, [RUNNER_LOG_PARAMS.generation]: generation },\n signal,\n });\n if (!result.ok) throw new Error(result.error || 'The connection to this pane dropped.');\n return result.data;\n}\nexport async function sendRunnerInput(sessionId: string, runId: string, text: string): Promise<void> {\n const result = await api.session(sessionId).input({ params: { [RUN_ID_PARAM]: runId }, body: { text } });\n if (!result.ok) throw new Error(result.error || 'This runner is no longer accepting input.');\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useMemo } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { readRunnerScreen, sendRunnerInput } from '../_lib/screenApi.native';\n\n/** The host renders genuine terminal bytes; this package owns every scoped API call. */\nexport function runnerShellTab(run: RunnerRunView) {\n return {\n id: `runner-shell-${run.id}`,\n label: `shell · ${run.name}`,\n panel: (props: WebPluginSlotProps) => <RunnerShellPanel {...props} runId={run.id} />,\n };\n}\nexport function RunnerShellPanel({ sessionId, runId, renderRunnerTerminal }: WebPluginSlotProps & { runId: string }) {\n const request = useMemo(\n () =>\n sessionId === null\n ? undefined\n : {\n key: `${sessionId}:${runId}`,\n read: (from: number, generation: string | undefined, signal: AbortSignal) =>\n readRunnerScreen(sessionId, runId, from, generation, signal),\n write: (text: string) => sendRunnerInput(sessionId, runId, text),\n },\n [sessionId, runId],\n );\n return (\n <View style={styles.panel}>\n {request === undefined ? (\n <Text style={styles.meta}>Select a session to attach to this runner.</Text>\n ) : (\n renderRunnerTerminal?.(request)\n )}\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, backgroundColor: theme.colors.bg },\n meta: { color: theme.colors.dim, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.sm },\n}));\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf, Button, Dot, ListRow } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useRef, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { formatRunnerUptime } from '../_lib/format';\nimport { RUNNER_SHELL_REQUEST } from '../_lib/launchLine';\nimport { requestRunnerStart, requestRunnerStop } from '../_lib/runnersStore.native';\nimport { LaunchRunnerSheet } from './LaunchRunnerSheet.native';\nimport { useRunners, useRunnerTail } from './runnerHooks.native';\nimport { runnerLogTab } from './RunnerLogPanel.native';\nimport { runnerShellTab } from './RunnerShellPanel.native';\n\nexport function runnersTab() {\n return { id: 'runner-runs', label: 'runners', panel: RunnersPanel };\n}\n\nfunction RunnerRow({\n run,\n props,\n stopping,\n now,\n detail = false,\n}: {\n run: RunnerRunView;\n props: WebPluginSlotProps;\n stopping: boolean;\n now: number;\n detail?: boolean;\n}) {\n const tail = useRunnerTail(props.sessionId, run.id, run.state === 'running');\n return (\n <View testID={`activity-runner-${run.id}`} style={styles.row}>\n <ListRow\n leading={<Dot tone=\"yellow\" pulse />}\n title={run.name}\n description={`${formatRunnerUptime(run.startedAt, now)}${run.interactive ? ' · tty' : ''}`}\n onPress={() => props.openTransientTab(runnerLogTab(run))}\n />\n <Text numberOfLines={detail ? undefined : 1} style={styles.meta}>\n {tail ?? run.command}\n </Text>\n {detail ? (\n <>\n <Text selectable style={styles.meta}>\n {run.command}\n </Text>\n <Text selectable style={styles.meta}>\n {run.cwd}\n </Text>\n </>\n ) : null}\n <View style={styles.actions}>\n {detail ? (\n <Button variant=\"outline\" onPress={() => props.openTransientTab(runnerLogTab(run))}>\n Log\n </Button>\n ) : null}\n {detail && run.interactive && props.sessionId !== null ? (\n <Button variant=\"outline\" onPress={() => props.openTransientTab(runnerShellTab(run))}>\n Shell\n </Button>\n ) : null}\n {props.sessionId !== null ? (\n <Button\n testID={`activity-runner-stop-${run.id}`}\n variant={stopping ? 'outline' : 'danger-outline'}\n disabled={stopping}\n onPress={() => {\n if (props.sessionId !== null) requestRunnerStop(props.sendSessionFrame, props.sessionId, run.id);\n }}\n >\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n ) : null}\n </View>\n </View>\n );\n}\n\nexport function RunnersActivitySection(props: WebPluginSlotProps) {\n const session = useRunners(props.sessionId);\n const running = session.runs.filter((run) => run.state === 'running');\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 10_000);\n return () => clearInterval(timer);\n }, []);\n return running.length === 0 ? (\n <View style={styles.row}>\n <Text style={styles.meta}>Idle</Text>\n {props.sessionId !== null ? (\n <Button variant=\"ghost\" testID=\"activity-runner-launch\" onPress={() => props.openTransientTab(runnersTab())}>\n Launch a runner\n </Button>\n ) : null}\n </View>\n ) : (\n <View>\n {running.map((run) => (\n <RunnerRow key={run.id} run={run} props={props} now={now} stopping={session.stopRequested.includes(run.id)} />\n ))}\n </View>\n );\n}\n\nexport function RunnersPanel(props: WebPluginSlotProps) {\n const { openTransientTab } = props;\n const session = useRunners(props.sessionId);\n const running = session.runs.filter((run) => run.state === 'running');\n const [launching, setLaunching] = useState(false);\n const [now, setNow] = useState(() => Date.now());\n const baseline = useRef<ReadonlySet<string> | null>(null);\n const timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 10_000);\n return () => clearInterval(timer);\n }, []);\n useEffect(() => {\n if (baseline.current === null) return;\n const shell = session.runs.find(\n (run) => run.state === 'running' && run.interactive && !baseline.current?.has(run.id),\n );\n if (shell === undefined) return;\n baseline.current = null;\n clearTimeout(timeout.current);\n openTransientTab(runnerShellTab(shell));\n }, [session.runs, openTransientTab]);\n useEffect(() => () => clearTimeout(timeout.current), []);\n return (\n <View style={styles.panel}>\n <Text style={styles.title}>{running.length === 0 ? 'Nothing running' : `${running.length} running`}</Text>\n {props.sessionId !== null ? (\n <View style={styles.actions}>\n <Button\n variant=\"outline\"\n onPress={() => {\n if (props.sessionId === null) return;\n baseline.current = new Set(session.runs.map((run) => run.id));\n clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n baseline.current = null;\n }, 30_000);\n requestRunnerStart(props.sendSessionFrame, props.sessionId, RUNNER_SHELL_REQUEST);\n }}\n >\n Start shell\n </Button>\n <Button onPress={() => setLaunching(true)}>Run command</Button>\n </View>\n ) : null}\n <ScrollView>\n {running.length === 0 ? (\n <Text style={styles.meta}>\n A command that outlives its turn moves to a runner and appears here while it works.\n </Text>\n ) : (\n running.map((run) => (\n <RunnerRow\n key={run.id}\n run={run}\n props={props}\n now={now}\n stopping={session.stopRequested.includes(run.id)}\n detail\n />\n ))\n )}\n </ScrollView>\n {launching && props.sessionId !== null ? (\n <LaunchRunnerSheet\n sessionId={props.sessionId}\n send={props.sendSessionFrame}\n defaultCwd={running[0]?.cwd}\n onClose={() => setLaunching(false)}\n />\n ) : null}\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, gap: theme.spacing(2), padding: theme.spacing(3), backgroundColor: theme.colors.bg },\n row: { gap: theme.spacing(1), paddingVertical: theme.spacing(2) },\n actions: { flexDirection: 'row', flexWrap: 'wrap', gap: theme.spacing(2) },\n title: {\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n fontWeight: '600',\n },\n meta: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n}));\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { runnersTab } from '../_components/RunnersPanel.native';\nimport { runnerActivitySource } from '../_lib/runnersStore.native';\n\nexport default defineActivityGroup({\n name: 'runners',\n keys: 'r l',\n statusKey: 'po-runner-runners',\n activeSource: runnerActivitySource,\n transientTab: runnersTab,\n order: 20,\n});\n","import { defineChannelFile } from '@agimon-ai/po-core/native';\n\nimport { runnerRunsChannel } from '../_lib/runnersStore.native';\nexport default defineChannelFile(runnerRunsChannel);\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { RunnersActivitySection } from '../_components/RunnersPanel.native';\n\nexport default defineFill({ slot: 'activity.runners', id: 'runners', component: RunnersActivitySection });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport activityGroupRunners from '../src/extensions/workspaces/sessions/(frontend)/activity-group/runners.native';\nimport channelRunnerRuns from '../src/extensions/workspaces/sessions/(frontend)/channel/runner-runs.native';\nimport fillRunners from '../src/extensions/workspaces/sessions/(frontend)/fill/Runners.activity.runners.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'runner',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'runners' }, activityGroupRunners)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'runner_runs' }, channelRunnerRuns)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.runners', id: 'runners' }, fillRunners)]; },\n },\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"native.mjs","names":["isRecord","WebPluginSlotProps","fontOf","Button","Input","Label","PoNativeTheme","useEffect","useState","StyleSheet","RunnerLogResponse","RunnerRunView","logViewLines","tailLineNumbers","fetchRunnerLog","requestRunnerStop","useRunners","runnerLogTab","run","id","label","name","panel","props","RunnerLogPanel","sessionId","runId","sendSessionFrame","session","runs","find","candidate","typed","setTyped","query","setQuery","ignoreCase","setIgnoreCase","context","setContext","following","setFollowing","requestKey","loaded","setLoaded","key","slice","error","undefined","timer","setTimeout","clearTimeout","controller","AbortController","ReturnType","read","result","lines","grep","contextLines","signal","aborted","running","abort","text","numbers","totalLines","length","lineNumbers","stopping","stopRequested","includes","styles","title","meta","state","command","cwd","actions","selected","value","lineCount","log","exists","map","line","index","logPath","path","create","theme","flex","gap","spacing","padding","backgroundColor","colors","bg","uni__dependencies","color","hi","fontWeight","fontFamily","sans","fontSize","base","dim","sm","lineHeight","red","flexDirection","flexWrap","deep","styles","WebPluginSlotProps","fontOf","Button","StatusBadge","PoNativeTheme","useMemo","StyleSheet","RunnerRunView","requestRunnerStop","readRunnerScreen","sendRunnerInput","useRunners","runnerLogTab","runnerShellTab","run","id","label","name","panel","props","RunnerShellPanel","sessionId","runId","renderRunnerTerminal","sendSessionFrame","openTransientTab","session","runs","find","candidate","live","state","stopping","stopRequested","includes","request","undefined","key","read","from","generation","signal","AbortSignal","write","text","styles","header","title","grow","command","terminal","meta","actions","create","theme","flex","gap","spacing","padding","backgroundColor","colors","bg","uni__dependencies","flexDirection","alignItems","flexShrink","color","hi","fontFamily","sans","fontSize","lg","fontWeight","dim","mono","sm","styles","WebPluginSlotProps","fontOf","Button","Dot","Input","ListRow","PoNativeTheme","useEffect","useRef","useState","StyleSheet","RunnerRunView","formatRunnerUptime","runnerRunRequest","requestRunnerStart","requestRunnerStop","useRunners","useRunnerTail","runnerLogTab","runnerShellTab","runnerTab","run","interactive","runnersTab","id","label","panel","RunnersPanel","RunnerRow","props","stopping","now","tail","sessionId","state","styles","row","name","command","startedAt","openTransientTab","undefined","meta","actions","sendSessionFrame","RunnersActivitySection","session","running","runs","filter","setNow","Date","timer","setInterval","clearInterval","length","map","stopRequested","includes","setCommand","baseline","ReadonlySet","timeout","ReturnType","setTimeout","current","started","find","has","clearTimeout","launch","Set","header","title","bar","grow","trim","create","theme","flex","gap","spacing","padding","backgroundColor","colors","bg","uni__dependencies","flexDirection","alignItems","paddingVertical","color","hi","fontFamily","sans","fontSize","lg","fontWeight","dim","sm","lineHeight","activityGroupRunners","channelRunnerRuns","fillRunners"],"sources":["../../src/extensions/workspaces/sessions/(frontend)/_lib/format.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/launchLine.ts","../../src/constants/webRunners.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/runnersStore.native.ts","../../src/constants/webRunnerLog.ts","../../src/types/webRunnerLog.ts","../../src/types/apiRoutes.ts","../../generated/client.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_lib/logApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/runnerHooks.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnerLogPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/_lib/screenApi.native.ts","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnerShellPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/_components/RunnersPanel.native.tsx","../../src/extensions/workspaces/sessions/(frontend)/activity-group/runners.native.ts","../../src/extensions/workspaces/sessions/(frontend)/channel/runner-runs.native.ts","../../src/extensions/workspaces/sessions/(frontend)/fill/Runners.activity.runners.native.tsx","../../generated/native.ts"],"sourcesContent":["/**\n * Local copy of the runtime's formatUptime (src/services/bashResult/index.ts):\n * the web plugin may reach only src/types, so the one helper it needs lives here.\n */\nexport function formatRunnerUptime(startedAt: string, now: number): string {\n const started = Date.parse(startedAt);\n if (Number.isNaN(started)) return 'unknown';\n const seconds = Math.max(0, Math.floor((now - started) / 1000));\n if (seconds < 60) return `${seconds}s`;\n const minutes = Math.floor(seconds / 60);\n if (minutes < 60) return `${minutes}m`;\n const hours = Math.floor(minutes / 60);\n return hours < 24 ? `${hours}h` : `${Math.floor(hours / 24)}d`;\n}\n\n/** A bounded log view: what to render, and what the bound left out. */\nexport interface LogView {\n lines: string[];\n /** Lines dropped off the top to stay within the bound. */\n hidden: number;\n}\n\nexport interface LogViewOptions {\n /**\n * Drop the slice's last line because it is a fragment the follow stream will\n * deliver again, whole. Set only while following: a finished run's last line\n * may legitimately lack a newline, and dropping it would hide real output.\n */\n dropPartialTail?: boolean;\n}\n\n/**\n * The lines a log view shows: the slice's text, then whatever the follow\n * stream appended, bounded to the newest `max`.\n *\n * A log file ends with a newline, and the reader hands its text back with that\n * newline intact, so a naive split reports one blank line more than the file\n * has. Dropping exactly one trailing empty entry keeps the count the reader\n * sees equal to the count the server reported.\n */\nexport function logViewLines(\n text: string,\n appended: readonly string[],\n max: number,\n options: LogViewOptions = {},\n): LogView {\n const split = text.split('\\n');\n if (split.length > 0 && split[split.length - 1] === '') split.pop();\n if (options.dropPartialTail === true && split.length > 0) split.pop();\n const all = [...split, ...appended];\n const lines = all.slice(-max);\n return { lines, hidden: all.length - lines.length };\n}\n\n/**\n * Absolute 1-based numbers for a tail, counted back from the last line.\n *\n * A tail is contiguous, so only its end has to be known. Grep results are not\n * contiguous and carry their own numbers from the reader instead.\n */\nexport function tailLineNumbers(lastLineNumber: number, count: number): number[] {\n const first = Math.max(1, lastLineNumber - count + 1);\n return Array.from({ length: count }, (_, index) => first + index);\n}\n\n/**\n * Whether the view is actually following a growing log.\n *\n * Three things must hold: the reader asked to follow, no query is set (a\n * filtered view is a snapshot of the whole file, which a stream cannot\n * assemble a chunk at a time), and the runner is still writing. Without the\n * last one a finished run would claim to be tailing a file nothing will ever\n * append to.\n */\nexport function isFollowingLive(following: boolean, filtering: boolean, running: boolean): boolean {\n return following && !filtering && running;\n}\n","/**\n * The `/runners start` line the runners panel's command bar sends.\n *\n * WHY THE BUILDER LIVES HERE AND THE PARSER DOES NOT:\n * Cockpit code is compiled into the host bundle and may import only this\n * package's own web and type modules, so it cannot share the session's parser\n * in src/services. The two are pinned together by a test that parses what this\n * writes, which is the only guarantee that matters: the line has to survive\n * the trip.\n */\n\nexport const RUNNERS_START_LINE = '/runners start';\n/** A persistent login shell for the direct shell action in Runner Space. */\nexport const RUNNER_SHELL_COMMAND = 'exec \"${SHELL:-/bin/bash}\" -l';\n/** Ends the options and begins the command; the command may hold `=` and flags of its own. */\nexport const RUNNERS_COMMAND_SEPARATOR = '--';\n\nexport interface RunnerLaunchRequest {\n command: string;\n cwd?: string;\n name?: string;\n interactive?: boolean;\n /** A terminal when rmux or tmux is available, plain output otherwise. */\n preferInteractive?: boolean;\n}\n\n/** The no-form launch used when a reader asks for a shell rather than a command. */\nexport const RUNNER_SHELL_REQUEST: RunnerLaunchRequest = {\n command: RUNNER_SHELL_COMMAND,\n name: 'shell',\n interactive: true,\n};\n\n/**\n * What the runners panel's Run sends: the typed command on a terminal when\n * one is available, or a login shell when nothing was typed.\n */\nexport function runnerRunRequest(command: string, cwd: string): RunnerLaunchRequest {\n const where = cwd.trim() === '' ? {} : { cwd };\n return command.trim() === '' ? { ...RUNNER_SHELL_REQUEST, ...where } : { command, ...where, preferInteractive: true };\n}\n\n/** Quotes a value that carries whitespace, which is how a value survives tokenizing. */\nfunction quote(value: string): string {\n return /\\s/u.test(value) ? `\"${value}\"` : value;\n}\n\nexport function runnerLaunchLine(request: RunnerLaunchRequest): string {\n const cwd = request.cwd?.trim() ?? '';\n const name = request.name?.trim() ?? '';\n const pairs = [\n ...(name === '' ? [] : [`name=${quote(name)}`]),\n ...(cwd === '' ? [] : [`cwd=${quote(cwd)}`]),\n ...(request.interactive === true\n ? ['interactive=true']\n : request.preferInteractive === true\n ? ['interactive=prefer']\n : []),\n ];\n // The separator is always written, even with no options before it, so the\n // command is never re-read as a `key=value` pair.\n return [RUNNERS_START_LINE, ...pairs, RUNNERS_COMMAND_SEPARATOR, request.command.trim()].join(' ');\n}\n","export const RUNNER_RUNS_TYPE = 'runner_runs';\n","import { defineSessionStore, type SessionFrameSender } from '@agimon-ai/po-core/native';\n\nimport { RUNNER_RUNS_TYPE } from '../../../../../constants/webRunners';\nimport { type RunnerRunView } from '../../../../../types/webRunners';\nimport { type RunnerLaunchRequest, runnerLaunchLine } from './launchLine';\n\n/** The runtime's slash verb that stops one runner headlessly. */\nconst STOP_COMMAND = '/runners stop';\n\n/** One session's record: the hub's last report plus what this page asked for. */\nexport interface RunnersSession {\n /** The runners the hub last reported; presented order preserved. */\n runs: RunnerRunView[];\n /** Runners a stop was asked for and that have not yet reported an exit. */\n stopRequested: string[];\n}\n\nexport const runners = defineSessionStore<RunnersSession>({ runs: [], stopRequested: [] });\n\n/** The runner channel keeps the dock's busy state aligned with its rendered run list. */\nexport const runnerActivitySource = {\n subscribe(listener: () => void) {\n const subscription = runners.store.subscribe(listener);\n return () => subscription.unsubscribe();\n },\n isActive(sessionId: string | null) {\n return runners.select(runners.store.state, sessionId).runs.some((run) => run.state === 'running');\n },\n};\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/**\n * Asks the runtime to stop a runner through the same slash command the TUI's\n * Runner Space uses. The request is remembered until the runner's record\n * reports an exit; the runtime, not this click, decides when that is.\n */\nexport function requestRunnerStop(send: SessionFrameSender, sessionId: string, id: string): void {\n send(sessionId, { type: 'prompt', message: `${STOP_COMMAND} ${id}` });\n runners.update(sessionId, (current) => ({\n ...current,\n stopRequested: [...current.stopRequested.filter((known) => known !== id), id],\n }));\n}\n\n/**\n * Asks the runtime to start a runner, through the same prompt frame the stop\n * request uses and the same way agents and workflows launch their own work.\n *\n * Nothing is recorded as pending here. The runtime names the run, and it\n * arrives in the feed on its own; guessing at an id before it exists would\n * only have to be reconciled later.\n */\nexport function requestRunnerStart(send: SessionFrameSender, sessionId: string, request: RunnerLaunchRequest): void {\n send(sessionId, { type: 'prompt', message: runnerLaunchLine(request) });\n}\n\nexport interface RunnerRunsPayload {\n runs: RunnerRunView[];\n}\n\n/** The plugin's session data channel: 'runner_runs' payloads into the store. */\nexport const runnerRunsChannel = runners.channel<RunnerRunsPayload>({\n channel: RUNNER_RUNS_TYPE,\n parse(input) {\n if (!isRecord(input) || !Array.isArray(input.runs)) return null;\n return { runs: input.runs.filter(isRecord) as unknown as RunnerRunView[] };\n },\n reduce(current, { runs }) {\n // A stop request is spent once the runner reports an exit or leaves the feed.\n const stillRunning = new Set(runs.filter((run) => run.state === 'running').map((run) => run.id));\n return { runs, stopRequested: current.stopRequested.filter((id) => stillRunning.has(id)) };\n },\n});\n","export const RUNNER_API_BASE_PATH = 'runner';\nexport const RUN_ID_PARAM = 'runId';\nexport const RUNNER_SCREEN_EVENT = 'screen';\nexport const RUNNER_LOG_STREAM_EVENT = 'append';\nexport const RUNNER_LOG_PING_EVENT = 'ping';\n","import type { LogSlice } from './logReader';\n\n/**\n * The runner log API, shared by this package's session-scoped routes and its\n * cockpit plugin. The two halves run in different processes, so the wire\n * vocabulary is declared here: the browser half may reach `src/types` and\n * nothing else on the server side.\n *\n * Where the routes live is not here. That is `src/types/apiRoutes`, which both\n * halves read, and the generated client turns into the URLs the page addresses.\n * The file a run writes to is still read from its metadata record by the server\n * alone.\n */\n\n/**\n * One chunk of an attached pane's output.\n *\n * Base64 because these are terminal bytes, escape sequences and all, and a\n * server-sent event is a line-oriented text frame that would mangle them.\n */\nexport interface RunnerScreenEvent {\n chunk: string;\n /** Byte offset just past this chunk, so a reconnect resumes rather than replays. */\n offset?: number;\n /** Set once the runner exits, so the page can stop watching. */\n ended?: boolean;\n}\n\n/** A finite byte slice for sealed HTTP followers. Decode chunks incrementally, not independently. */\nexport interface RunnerOutputResponse {\n /** Base64 bytes, preserving split UTF-8 characters and terminal escape sequences. */\n chunk: string;\n offset: number;\n /** The file was replaced or became shorter than the requested offset; discard the previous display/decoder state. */\n reset: boolean;\n /** Opaque raw file identity. Send back on screen/read to detect replacement, including regrowth. */\n generation?: string;\n exists: boolean;\n /** More bytes were present at read time; request the next slice before waiting. */\n hasMore: boolean;\n /** True only once the runner ended and all available bytes have been read. */\n ended: boolean;\n}\n\n/** The body of a keystroke POST. Text, not key codes: the pane wants bytes. */\nexport interface RunnerInputRequest {\n text: string;\n}\n\n/** The named SSE event carrying a RunnerScreenEvent payload. */\n\n/**\n * A log request as query parameters. `grep` is a literal substring, not a\n * regular expression, because that is what the reader matches; `lines` bounds\n * the answer to the last N lines of whatever survived the filter.\n */\nexport interface RunnerLogQueryParams {\n lines?: number;\n grep?: string;\n ignoreCase?: boolean;\n contextLines?: number;\n}\n\n/** The slice the log route answers with, plus which runner it came from. */\nexport interface RunnerLogResponse extends LogSlice {\n runId: string;\n /** True while the runner is still writing, so the page knows following is worth offering. */\n running: boolean;\n}\n\n/**\n * One server-sent event on the follow stream: the lines appended since the last\n * one. The stream never filters: a page that sets a query stops following and\n * reads a filtered slice instead, because grep with context is a whole-file\n * answer and cannot be assembled from a chunk at a time.\n */\nexport interface RunnerLogStreamEvent {\n /** Appended lines, in order; empty when the event only reports the runner ending. */\n lines: string[];\n /**\n * Byte offset just past the last line in this event.\n *\n * A follower that loses the stream resumes here. Without it the page could\n * only fall back to the offset its last slice reported, which every line\n * delivered since has already moved past, so a reconnect would replay them.\n */\n offset?: number;\n /** Set once the runner exits, so the page can stop following without polling the run list. */\n ended?: boolean;\n}\n\n/** The named SSE event carrying a RunnerLogStreamEvent payload. */\n\n/**\n * The named SSE event that carries nothing.\n *\n * A runner can be alive and silent for minutes, which on the wire is\n * indistinguishable from a connection that died. This is sent on a timer so\n * the socket keeps proving itself. Readers that only listen for `append`\n * ignore it, which is what makes it safe to add.\n */\n\n/** Query parameter names, shared so the page and the route cannot drift apart. */\nexport const RUNNER_LOG_PARAMS = {\n lines: 'lines',\n grep: 'grep',\n ignoreCase: 'ignoreCase',\n contextLines: 'contextLines',\n from: 'from',\n generation: 'generation',\n} as const;\n","import type { ApiResponseOf, ApiRoutes } from '@agimon-ai/po-core/web';\n\nimport { RUN_ID_PARAM } from '../constants/webRunnerLog';\nimport { RUNNER_LOG_PARAMS, type RunnerLogResponse, type RunnerOutputResponse } from './webRunnerLog';\n\n/**\n * This package's routes, as data.\n *\n * No scope and no base path: the build reads both off\n * `src/extensions/workspaces/sessions/(backend)/api/runner/`, so the mount is\n * stated once, by the folder that creates it. This package stated it four times\n * before, once per URL builder, each of them re-spelling `/plugins/` and the\n * session prefix by hand.\n *\n * The Hono app registers these paths verbatim and the browser addresses them,\n * so a path cannot move on one side alone. `:runId` is Hono's own parameter\n * syntax for that reason; a caller supplies the value as `params`, and the\n * client encodes the segment.\n */\nconst routes = {\n log: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log`,\n query: [\n RUNNER_LOG_PARAMS.lines,\n RUNNER_LOG_PARAMS.grep,\n RUNNER_LOG_PARAMS.ignoreCase,\n RUNNER_LOG_PARAMS.contextLines,\n ],\n response: undefined as unknown as ApiResponseOf<RunnerLogResponse>,\n },\n /**\n * The live tail of that same log.\n *\n * `stream: true`, so the client exposes a URL and no call method: the\n * consumer is the browser’s own SSE reader, and a relayed call would\n * buffer a stream that never ends.\n */\n logStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n /** The unscrubbed pane bytes, for a terminal emulator rather than a reader. */\n screenStream: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/screen/stream`,\n query: [RUNNER_LOG_PARAMS.from],\n stream: true,\n },\n /** Finite byte reads keep sealed HTTP exchanges bounded, unlike SSE. */\n logRead: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/log/read`,\n query: [RUNNER_LOG_PARAMS.from],\n response: undefined as unknown as ApiResponseOf<RunnerOutputResponse>,\n },\n screenRead: {\n method: 'GET',\n path: `/runners/:${RUN_ID_PARAM}/screen/read`,\n query: [RUNNER_LOG_PARAMS.from, RUNNER_LOG_PARAMS.generation],\n response: undefined as unknown as ApiResponseOf<RunnerOutputResponse>,\n },\n input: {\n method: 'POST',\n path: `/runners/:${RUN_ID_PARAM}/screen/input`,\n },\n} as const satisfies ApiRoutes;\n\nexport default routes;\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { createApiClient, nativeApiTransport, sessionApiAddress } from '@agimon-ai/po-core/native';\n\nimport routes from '../src/types/apiRoutes';\n\n/** Scopes the tree mounts 'runner' at. */\nexport const apiScopes = ['session'] as const;\n\nexport const api = createApiClient(routes, {\n scopes: apiScopes,\n basePath: 'runner',\n transport: nativeApiTransport,\n sessionAddress: sessionApiAddress,\n});\n","import { api } from '../../../../../../generated/client.native';\nimport { RUN_ID_PARAM } from '../../../../../constants/webRunnerLog';\nimport {\n RUNNER_LOG_PARAMS,\n type RunnerLogQueryParams,\n type RunnerLogResponse,\n} from '../../../../../types/webRunnerLog';\n\n/**\n * The page's half of this package's log API. The only place the cockpit talks\n * HTTP to the hub for a runner, so if the transport ever changes, it changes\n * here alone.\n *\n * The generated client owns every URL: a route is named, a session id selects\n * that session's own copy of the API, and the run id is a path parameter the\n * client substitutes and encodes. Nothing here spells a mount, a prefix or a\n * proxy parameter, which is what the four deleted URL builders each did by\n * hand.\n */\n\nexport type RunnerLogResult = { slice: RunnerLogResponse } | { error: string };\n\nconst UNREACHABLE = 'The cockpit hub is unreachable.';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\n/** Reads one runner's log: the last N lines, or the lines matching a substring with context. */\nexport async function fetchRunnerLog(\n sessionId: string,\n runId: string,\n params: RunnerLogQueryParams = {},\n signal?: AbortSignal,\n): Promise<RunnerLogResult> {\n const result = await api.session(sessionId).log({\n params: { [RUN_ID_PARAM]: runId },\n // An unset parameter is left out rather than sent empty: the route reads a\n // missing one as its own default, and an empty grep as no filter at all.\n query: {\n [RUNNER_LOG_PARAMS.lines]: params.lines,\n [RUNNER_LOG_PARAMS.grep]: params.grep === '' ? undefined : params.grep,\n [RUNNER_LOG_PARAMS.ignoreCase]: params.ignoreCase === true ? true : undefined,\n [RUNNER_LOG_PARAMS.contextLines]: params.contextLines,\n },\n ...(signal === undefined ? {} : { signal }),\n });\n if (!result.ok) {\n // Status 0 is the transport never answering, which covers both a dead hub\n // and the caller replacing this request. An abort is the caller's own doing\n // and is reported as no answer rather than as a failure to show.\n if (result.status === 0) return { error: signal?.aborted === true ? '' : UNREACHABLE };\n return { error: result.error === '' ? `The hub answered ${String(result.status)}.` : result.error };\n }\n if (!isRecord(result.data) || typeof result.data.text !== 'string') {\n return { error: `The hub answered ${String(result.status)}.` };\n }\n return { slice: result.data };\n}\n","import { useCallback, useEffect, useState, useSyncExternalStore } from 'react';\n\nimport { fetchRunnerLog } from '../_lib/logApi.native';\nimport { runners } from '../_lib/runnersStore.native';\n\nexport function useRunners(sessionId: string | null) {\n const subscribe = useCallback((listener: () => void) => {\n const subscription = runners.store.subscribe(listener);\n return () => subscription.unsubscribe();\n }, []);\n return useSyncExternalStore(subscribe, () => runners.select(runners.store.state, sessionId));\n}\n\n/** Native uses finite reads instead of browser SSE. Read a bounded tail through the host's sealed transport. */\nexport function useRunnerTail(sessionId: string | null, runId: string, running: boolean) {\n const [tail, setTail] = useState<{ id: string; text: string }>();\n useEffect(() => {\n if (sessionId === null || !running) return;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const read = async () => {\n try {\n const result = await fetchRunnerLog(sessionId, runId, { lines: 5 }, controller.signal);\n if (controller.signal.aborted) return;\n if ('slice' in result) {\n const text = result.slice.text\n .split('\\n')\n .map((line) => line.trim())\n .filter(Boolean)\n .at(-1);\n if (text !== undefined) setTail({ id: `${sessionId}:${runId}`, text });\n if (!result.slice.running) return;\n }\n } catch {\n // A glance keeps the last known output when a read is unavailable.\n }\n if (!controller.signal.aborted) timer = setTimeout(() => void read(), 2_000);\n };\n void read();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [sessionId, runId, running]);\n return running && tail?.id === `${sessionId}:${runId}` ? tail.text : undefined;\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf, Button, Input, Label } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerLogResponse } from '../../../../../types/webRunnerLog';\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { logViewLines, tailLineNumbers } from '../_lib/format';\nimport { fetchRunnerLog } from '../_lib/logApi.native';\nimport { requestRunnerStop } from '../_lib/runnersStore.native';\nimport { useRunners } from './runnerHooks.native';\n\nexport function runnerLogTab(run: RunnerRunView) {\n return {\n id: `runner-log-${run.id}`,\n label: `log · ${run.name}`,\n panel: (props: WebPluginSlotProps) => <RunnerLogPanel {...props} runId={run.id} />,\n };\n}\n\nexport function RunnerLogPanel({ sessionId, runId, sendSessionFrame }: WebPluginSlotProps & { runId: string }) {\n const session = useRunners(sessionId);\n const run = session.runs.find((candidate) => candidate.id === runId);\n const [typed, setTyped] = useState('');\n const [query, setQuery] = useState('');\n const [ignoreCase, setIgnoreCase] = useState(false);\n const [context, setContext] = useState(2);\n const [following, setFollowing] = useState(true);\n const requestKey = `${sessionId}:${runId}:${query}:${ignoreCase}:${context}:${following}`;\n const [loaded, setLoaded] = useState<{ key: string; slice?: RunnerLogResponse; error: string }>();\n const slice = loaded?.key === requestKey ? loaded.slice : undefined;\n const error = loaded?.key === requestKey ? loaded.error : '';\n useEffect(() => {\n const timer = setTimeout(() => setQuery(typed), 200);\n return () => clearTimeout(timer);\n }, [typed]);\n useEffect(() => {\n if (sessionId === null) return;\n const controller = new AbortController();\n let timer: ReturnType<typeof setTimeout> | undefined;\n const read = async () => {\n const result = await fetchRunnerLog(\n sessionId,\n runId,\n { lines: 2000, grep: query, ignoreCase, contextLines: context },\n controller.signal,\n );\n if (controller.signal.aborted) return;\n setLoaded(\n 'error' in result\n ? { key: requestKey, error: result.error }\n : { key: requestKey, slice: result.slice, error: '' },\n );\n if (following && query === '' && ('error' in result || result.slice.running))\n timer = setTimeout(() => void read(), 2_000);\n };\n void read();\n return () => {\n controller.abort();\n clearTimeout(timer);\n };\n }, [sessionId, runId, query, ignoreCase, context, following, requestKey]);\n const lines = logViewLines(slice?.text ?? '', [], 2000).lines;\n const numbers = query === '' ? tailLineNumbers(slice?.totalLines ?? 0, lines.length) : (slice?.lineNumbers ?? []);\n const stopping = session.stopRequested.includes(runId);\n return (\n <View testID=\"runner-log-panel\" style={styles.panel}>\n <Text style={styles.title}>{run?.name ?? runId}</Text>\n <Text style={styles.meta}>{run?.state ?? 'no longer listed; its log stays readable'}</Text>\n {run ? (\n <>\n <Text selectable style={styles.meta}>\n {run.command}\n </Text>\n <Text selectable style={styles.meta}>\n {run.cwd}\n </Text>\n </>\n ) : null}\n {run?.state === 'running' && sessionId !== null ? (\n <Button\n variant=\"danger-outline\"\n disabled={stopping}\n onPress={() => requestRunnerStop(sendSessionFrame, sessionId, runId)}\n >\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n ) : null}\n <Label>Search this log</Label>\n <Input testID=\"runner-log-search\" value={typed} onChangeText={setTyped} />\n <View style={styles.actions}>\n <Button\n variant=\"outline\"\n accessibilityState={{ selected: ignoreCase }}\n onPress={() => setIgnoreCase((value) => !value)}\n >\n aA\n </Button>\n <Button variant=\"outline\" disabled={query === ''} onPress={() => setContext((value) => (value === 0 ? 2 : 0))}>\n ± {context} lines\n </Button>\n <Button\n variant=\"outline\"\n disabled={query !== '' || slice?.running !== true}\n accessibilityState={{ selected: following }}\n onPress={() => setFollowing((value) => !value)}\n >\n {query !== '' ? 'Follow · paused' : 'Follow'}\n </Button>\n </View>\n <Text style={styles.meta}>\n {slice === undefined\n ? 'Reading…'\n : query !== ''\n ? `${slice.lineCount} matching of ${slice.totalLines} lines`\n : `${following && slice.running ? 'Tailing' : 'Showing'} last ${lines.length} of ${slice.totalLines} lines`}\n </Text>\n <ScrollView style={styles.log}>\n {error !== '' ? (\n <Text accessibilityRole=\"alert\" style={styles.error}>\n {error}\n </Text>\n ) : slice?.exists === false ? (\n <Text style={styles.meta}>This runner has not written a log yet.</Text>\n ) : slice && lines.length === 0 ? (\n <Text style={styles.meta}>{query === '' ? 'The log is empty.' : 'Nothing matched.'}</Text>\n ) : (\n lines.map((line, index) => (\n <Text selectable key={`${numbers[index] ?? index}`} style={styles.meta}>\n {numbers[index]} {line}\n </Text>\n ))\n )}\n </ScrollView>\n <Text selectable style={styles.meta}>\n {run?.logPath ?? slice?.path ?? ''}\n </Text>\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, gap: theme.spacing(2), padding: theme.spacing(3), backgroundColor: theme.colors.bg },\n title: {\n color: theme.colors.hi,\n fontWeight: '600',\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.base,\n },\n meta: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n error: { color: theme.colors.red, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.base },\n actions: { flexDirection: 'row', gap: theme.spacing(2), flexWrap: 'wrap' },\n log: { flex: 1, backgroundColor: theme.colors.deep },\n}));\n","import { api } from '../../../../../../generated/client.native';\nimport { RUN_ID_PARAM } from '../../../../../constants/webRunnerLog';\nimport { RUNNER_LOG_PARAMS, type RunnerOutputResponse } from '../../../../../types/webRunnerLog';\n\n/** Finite native reads preserve raw terminal bytes and generation-based replacement detection. */\nexport async function readRunnerScreen(\n sessionId: string,\n runId: string,\n from: number,\n generation: string | undefined,\n signal: AbortSignal,\n): Promise<RunnerOutputResponse> {\n const result = await api.session(sessionId).screenRead({\n params: { [RUN_ID_PARAM]: runId },\n query: { [RUNNER_LOG_PARAMS.from]: from, [RUNNER_LOG_PARAMS.generation]: generation },\n signal,\n });\n if (!result.ok) throw new Error(result.error || 'The connection to this pane dropped.');\n return result.data;\n}\nexport async function sendRunnerInput(sessionId: string, runId: string, text: string): Promise<void> {\n const result = await api.session(sessionId).input({ params: { [RUN_ID_PARAM]: runId }, body: { text } });\n if (!result.ok) throw new Error(result.error || 'This runner is no longer accepting input.');\n}\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf, Button, StatusBadge } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useMemo } from 'react';\nimport { Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { requestRunnerStop } from '../_lib/runnersStore.native';\nimport { readRunnerScreen, sendRunnerInput } from '../_lib/screenApi.native';\nimport { useRunners } from './runnerHooks.native';\nimport { runnerLogTab } from './RunnerLogPanel.native';\n\n/** The host renders genuine terminal bytes; this package owns every scoped API call. */\nexport function runnerShellTab(run: RunnerRunView) {\n return {\n id: `runner-shell-${run.id}`,\n label: `shell · ${run.name}`,\n panel: (props: WebPluginSlotProps) => <RunnerShellPanel {...props} runId={run.id} />,\n };\n}\n\n/**\n * One terminal runner, full screen. A phone keyboard has no Ctrl key, so\n * Ctrl-C is a button; Search opens the runner's log, which the sink keeps\n * scrubbed beside the raw bytes for exactly that.\n */\nexport function RunnerShellPanel({\n sessionId,\n runId,\n renderRunnerTerminal,\n sendSessionFrame,\n openTransientTab,\n}: WebPluginSlotProps & { runId: string }) {\n const session = useRunners(sessionId);\n const run = session.runs.find((candidate) => candidate.id === runId);\n const live = run?.state === 'running';\n const stopping = session.stopRequested.includes(runId);\n const request = useMemo(\n () =>\n sessionId === null\n ? undefined\n : {\n key: `${sessionId}:${runId}`,\n read: (from: number, generation: string | undefined, signal: AbortSignal) =>\n readRunnerScreen(sessionId, runId, from, generation, signal),\n write: (text: string) => sendRunnerInput(sessionId, runId, text),\n },\n [sessionId, runId],\n );\n return (\n <View style={styles.panel}>\n <View style={styles.header}>\n <Text numberOfLines={1} style={styles.title}>\n {run?.name ?? runId}\n </Text>\n <StatusBadge tone={live ? 'running' : 'neutral'}>{live ? 'Running' : 'Ended'}</StatusBadge>\n <View style={styles.grow} />\n {live && sessionId !== null ? (\n <Button\n testID=\"runner-shell-stop\"\n variant={stopping ? 'outline' : 'danger-outline'}\n disabled={stopping}\n onPress={() => requestRunnerStop(sendSessionFrame, sessionId, runId)}\n >\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n ) : null}\n </View>\n {run ? (\n <Text numberOfLines={1} style={styles.command}>\n {run.command}\n </Text>\n ) : null}\n <View style={styles.terminal}>\n {request === undefined ? (\n <Text style={styles.meta}>Select a session to attach to this runner.</Text>\n ) : (\n renderRunnerTerminal?.(request)\n )}\n </View>\n <View style={styles.actions}>\n {live && sessionId !== null ? (\n <Button\n testID=\"runner-shell-interrupt\"\n variant=\"outline\"\n onPress={() => void sendRunnerInput(sessionId, runId, '\\u0003')}\n >\n Ctrl-C\n </Button>\n ) : null}\n {run ? (\n <Button testID=\"runner-shell-search\" variant=\"outline\" onPress={() => openTransientTab(runnerLogTab(run))}>\n Search output\n </Button>\n ) : null}\n </View>\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, gap: theme.spacing(2), padding: theme.spacing(3), backgroundColor: theme.colors.bg },\n header: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2) },\n actions: { flexDirection: 'row', gap: theme.spacing(2) },\n grow: { flex: 1 },\n terminal: { flex: 1 },\n title: {\n flexShrink: 1,\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.lg,\n fontWeight: '600',\n },\n command: { color: theme.colors.dim, fontFamily: fontOf(theme.fontFamily.mono), fontSize: theme.fontSize.sm },\n meta: { color: theme.colors.dim, fontFamily: fontOf(theme.fontFamily.sans), fontSize: theme.fontSize.sm },\n}));\n","import type { WebPluginSlotProps } from '@agimon-ai/po-core/native';\nimport { fontOf, Button, Dot, Input, ListRow } from '@agimon-ai/po-native-components';\nimport type { PoNativeTheme } from '@agimon-ai/po-web-components/nativeTheme';\nimport { useEffect, useRef, useState } from 'react';\nimport { ScrollView, Text, View } from 'react-native';\nimport { StyleSheet } from 'react-native-unistyles';\n\nimport type { RunnerRunView } from '../../../../../types/webRunners';\nimport { formatRunnerUptime } from '../_lib/format';\nimport { runnerRunRequest } from '../_lib/launchLine';\nimport { requestRunnerStart, requestRunnerStop } from '../_lib/runnersStore.native';\nimport { useRunners, useRunnerTail } from './runnerHooks.native';\nimport { runnerLogTab } from './RunnerLogPanel.native';\nimport { runnerShellTab } from './RunnerShellPanel.native';\n\n/** A runner's own screen: its terminal when it has one, its log when it does not. */\nfunction runnerTab(run: RunnerRunView) {\n return run.interactive ? runnerShellTab(run) : runnerLogTab(run);\n}\n\nexport function runnersTab() {\n return { id: 'runner-runs', label: 'runners', panel: RunnersPanel };\n}\n\nfunction RunnerRow({\n run,\n props,\n stopping,\n now,\n}: {\n run: RunnerRunView;\n props: WebPluginSlotProps;\n stopping: boolean;\n now: number;\n}) {\n const tail = useRunnerTail(props.sessionId, run.id, run.state === 'running');\n return (\n <View testID={`activity-runner-${run.id}`} style={styles.row}>\n <ListRow\n leading={<Dot tone=\"yellow\" pulse />}\n title={run.name}\n description={`${run.command} · ${formatRunnerUptime(run.startedAt, now)}`}\n disclosure\n onPress={() => props.openTransientTab(runnerTab(run))}\n />\n {tail === undefined ? null : (\n <Text numberOfLines={1} style={styles.meta}>\n {tail}\n </Text>\n )}\n {props.sessionId !== null ? (\n <View style={styles.actions}>\n <Button\n testID={`activity-runner-stop-${run.id}`}\n variant={stopping ? 'outline' : 'danger-outline'}\n disabled={stopping}\n onPress={() => {\n if (props.sessionId !== null) requestRunnerStop(props.sendSessionFrame, props.sessionId, run.id);\n }}\n >\n {stopping ? 'Stopping…' : 'Stop'}\n </Button>\n </View>\n ) : null}\n </View>\n );\n}\n\nexport function RunnersActivitySection(props: WebPluginSlotProps) {\n const session = useRunners(props.sessionId);\n const running = session.runs.filter((run) => run.state === 'running');\n const [now, setNow] = useState(() => Date.now());\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 10_000);\n return () => clearInterval(timer);\n }, []);\n return running.length === 0 ? (\n <View style={styles.row}>\n <Text style={styles.meta}>Idle</Text>\n {props.sessionId !== null ? (\n <Button variant=\"ghost\" testID=\"activity-runner-launch\" onPress={() => props.openTransientTab(runnersTab())}>\n Launch a runner\n </Button>\n ) : null}\n </View>\n ) : (\n <View>\n {running.map((run) => (\n <RunnerRow key={run.id} run={run} props={props} now={now} stopping={session.stopRequested.includes(run.id)} />\n ))}\n </View>\n );\n}\n\n/**\n * Every running runner and the one place to start another: type a command\n * and Run hosts it on a terminal (plain output when the host has no rmux or\n * tmux), or leave it empty for a login shell. The started runner opens on\n * its own screen.\n */\nexport function RunnersPanel(props: WebPluginSlotProps) {\n const { openTransientTab } = props;\n const session = useRunners(props.sessionId);\n const running = session.runs.filter((run) => run.state === 'running');\n const [command, setCommand] = useState('');\n const [now, setNow] = useState(() => Date.now());\n const baseline = useRef<ReadonlySet<string> | null>(null);\n const timeout = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);\n useEffect(() => {\n const timer = setInterval(() => setNow(Date.now()), 10_000);\n return () => clearInterval(timer);\n }, []);\n // ponytail: the first runner to appear after a launch is taken to be it, the\n // same guess the web panel makes.\n useEffect(() => {\n if (baseline.current === null) return;\n const started = session.runs.find((run) => run.state === 'running' && !baseline.current?.has(run.id));\n if (started === undefined) return;\n baseline.current = null;\n clearTimeout(timeout.current);\n openTransientTab(runnerTab(started));\n }, [session.runs, openTransientTab]);\n useEffect(() => () => clearTimeout(timeout.current), []);\n const launch = () => {\n if (props.sessionId === null) return;\n baseline.current = new Set(session.runs.map((run) => run.id));\n clearTimeout(timeout.current);\n timeout.current = setTimeout(() => {\n baseline.current = null;\n }, 30_000);\n requestRunnerStart(props.sendSessionFrame, props.sessionId, runnerRunRequest(command, ''));\n setCommand('');\n };\n return (\n <View style={styles.panel}>\n <View style={styles.header}>\n <Text style={styles.title}>Runners</Text>\n <Text style={styles.meta}>{running.length === 0 ? 'Nothing running' : `${running.length} running`}</Text>\n </View>\n {props.sessionId !== null ? (\n <View style={styles.bar}>\n <View style={styles.actions}>\n <View style={styles.grow}>\n <Input\n testID=\"runners-panel-command\"\n accessibilityLabel=\"Command to run\"\n size=\"lg\"\n value={command}\n onChangeText={setCommand}\n onSubmitEditing={launch}\n placeholder=\"a command, like pnpm dev\"\n autoCapitalize=\"none\"\n autoCorrect={false}\n returnKeyType=\"go\"\n />\n </View>\n <Button testID=\"runners-panel-run\" variant=\"primary\" size=\"lg\" onPress={launch}>\n {command.trim() === '' ? 'Open shell' : 'Run'}\n </Button>\n </View>\n <Text style={styles.meta}>Runs in the session's directory. Leave it empty for a plain shell.</Text>\n </View>\n ) : null}\n <ScrollView>\n {running.length === 0 ? (\n <Text style={styles.meta}>\n {props.sessionId === null\n ? 'Open a session to start a runner.'\n : 'Nothing running yet. Type a command above, like pnpm dev, and it opens as a live terminal.'}\n </Text>\n ) : (\n running.map((run) => (\n <ListRow\n key={run.id}\n leading={<Dot tone=\"yellow\" pulse />}\n title={run.name}\n description={`${run.command} · ${formatRunnerUptime(run.startedAt, now)}`}\n disclosure\n onPress={() => openTransientTab(runnerTab(run))}\n />\n ))\n )}\n </ScrollView>\n </View>\n );\n}\nconst styles = StyleSheet.create((theme: PoNativeTheme) => ({\n panel: { flex: 1, gap: theme.spacing(3), padding: theme.spacing(4), backgroundColor: theme.colors.bg },\n header: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2) },\n bar: { gap: theme.spacing(1.5) },\n grow: { flex: 1 },\n row: { gap: theme.spacing(1), paddingVertical: theme.spacing(2) },\n actions: { flexDirection: 'row', alignItems: 'center', gap: theme.spacing(2) },\n title: {\n color: theme.colors.hi,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.lg,\n fontWeight: '600',\n },\n meta: {\n color: theme.colors.dim,\n fontFamily: fontOf(theme.fontFamily.sans),\n fontSize: theme.fontSize.sm,\n lineHeight: theme.lineHeight.sm,\n },\n}));\n","import { defineActivityGroup } from '@agimon-ai/po-core/native';\n\nimport { runnersTab } from '../_components/RunnersPanel.native';\nimport { runnerActivitySource } from '../_lib/runnersStore.native';\n\nexport default defineActivityGroup({\n name: 'runners',\n keys: 'r l',\n statusKey: 'po-runner-runners',\n activeSource: runnerActivitySource,\n transientTab: runnersTab,\n order: 20,\n});\n","import { defineChannelFile } from '@agimon-ai/po-core/native';\n\nimport { runnerRunsChannel } from '../_lib/runnersStore.native';\nexport default defineChannelFile(runnerRunsChannel);\n","import { defineFill } from '@agimon-ai/po-core/native';\n\nimport { RunnersActivitySection } from '../_components/RunnersPanel.native';\n\nexport default defineFill({ slot: 'activity.runners', id: 'runners', component: RunnersActivitySection });\n","// Generated by @agimon-ai/po-build. Do not edit by hand.\nimport { defineNativePlugin, type WebPluginContributions } from '@agimon-ai/po-core/native';\n\nimport activityGroupRunners from '../src/extensions/workspaces/sessions/(frontend)/activity-group/runners.native';\nimport channelRunnerRuns from '../src/extensions/workspaces/sessions/(frontend)/channel/runner-runs.native';\nimport fillRunners from '../src/extensions/workspaces/sessions/(frontend)/fill/Runners.activity.runners.native';\n\nconst via = <T>(identity: Record<string, unknown>, value: unknown): T =>\n (value === undefined ? undefined : { ...identity, ...(value as object) }) as T;\n\nexport const nativePlugin = defineNativePlugin({\n id: 'runner',\n session: {\n get activityGroups(): WebPluginContributions['activityGroups'] { return [via({ name: 'runners' }, activityGroupRunners)]; },\n get channels(): WebPluginContributions['channels'] { return [via({ channel: 'runner_runs' }, channelRunnerRuns)]; },\n get fills(): WebPluginContributions['fills'] { return [via({ slot: 'activity.runners', id: 'runners' }, fillRunners)]; },\n },\n});\n"],"mappings":"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"}
@@ -5,13 +5,13 @@ Object.defineProperties(exports, {
5
5
  const require_rolldown_runtime = require("../rolldown-runtime-VH7oDXx4.cjs");
6
6
  const require_runnerConfig = require("../runnerConfig-BoLMinlx.cjs");
7
7
  const require_logReader = require("../logReader-DHCK2BEr.cjs");
8
- const require_headless = require("../headless-Dko_yBiy.cjs");
8
+ const require_headless = require("../headless-C4Bvl2B-.cjs");
9
9
  const require_reconcile = require("../reconcile-5cZ11jSD.cjs");
10
10
  const require_clock = require("../clock-jqnLWziT.cjs");
11
11
  const require_compaction = require("../compaction-Cduebib_.cjs");
12
12
  const require_rmuxBackend = require("../rmuxBackend-Dh0CYVAL.cjs");
13
13
  const require_launcher = require("../launcher-ZgDdyXpq.cjs");
14
- const require_runnerDependencies = require("../runnerDependencies-DSun3xO-.cjs");
14
+ const require_runnerDependencies = require("../runnerDependencies-vkpJfxZZ.cjs");
15
15
  const require_runnerPaths = require("../runnerPaths-B41rMOY6.cjs");
16
16
  const require_runnerRegistry = require("../runnerRegistry-dQYlMSpQ.cjs");
17
17
  let node_fs = require("node:fs");
@@ -1,12 +1,12 @@
1
1
  import { c as getLogTtlMs } from "../runnerConfig-XXMq4VQA.mjs";
2
2
  import { r as summarizeLog, t as LogReader } from "../logReader-mq9uVurh.mjs";
3
- import { n as createHeadlessRunnersCommand, t as createHeadlessBashTool } from "../headless-DOlCixyf.mjs";
3
+ import { n as createHeadlessRunnersCommand, t as createHeadlessBashTool } from "../headless-DidUBSSf.mjs";
4
4
  import { n as stopRunnerProcess, t as reconcileActiveRunners } from "../reconcile-wNYQJZF-.mjs";
5
5
  import { t as SystemClock } from "../clock-Cv2pddgo.mjs";
6
6
  import { t as activeRunnerRecovery } from "../compaction-nNlE6e5I.mjs";
7
7
  import { t as RmuxBackend } from "../rmuxBackend-rjrVTG6K.mjs";
8
8
  import { n as TERM_GRACE_MS } from "../launcher-CCYsFBM9.mjs";
9
- import { n as TmuxBackend, r as PtyBackendChain, t as createRunnerDependencies } from "../runnerDependencies-7h_cxOva.mjs";
9
+ import { n as TmuxBackend, r as PtyBackendChain, t as createRunnerDependencies } from "../runnerDependencies-CamKwphq.mjs";
10
10
  import { n as resolveRunnerStoreDirectory, r as runnerStateDirFor, t as RunnerPaths } from "../runnerPaths-Dibbvyx_.mjs";
11
11
  import { a as formatRunnerStatus, i as formatRunnerFinishedNotice, n as createDefaultProcessRegistry, o as isRunnerRecord, r as formatRunnerFinished } from "../runnerRegistry-BgaR5O86.mjs";
12
12
  import fs from "node:fs";