lark-remote 0.1.0

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 (201) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE +21 -0
  3. package/README.en.md +162 -0
  4. package/README.md +161 -0
  5. package/dist/binder.d.ts +57 -0
  6. package/dist/binder.js +105 -0
  7. package/dist/bridge/index.d.ts +338 -0
  8. package/dist/bridge/index.js +1281 -0
  9. package/dist/bridge/queue-manager.d.ts +277 -0
  10. package/dist/bridge/queue-manager.js +729 -0
  11. package/dist/card/bash-card-session.d.ts +78 -0
  12. package/dist/card/bash-card-session.js +174 -0
  13. package/dist/card/bash-renderer.d.ts +24 -0
  14. package/dist/card/bash-renderer.js +187 -0
  15. package/dist/card/card-budget.d.ts +31 -0
  16. package/dist/card/card-budget.js +280 -0
  17. package/dist/card/card-session.d.ts +83 -0
  18. package/dist/card/card-session.js +185 -0
  19. package/dist/card/card-shared.d.ts +28 -0
  20. package/dist/card/card-shared.js +99 -0
  21. package/dist/card/collapsible.d.ts +26 -0
  22. package/dist/card/collapsible.js +87 -0
  23. package/dist/card/run-card-session.d.ts +78 -0
  24. package/dist/card/run-card-session.js +165 -0
  25. package/dist/card/run-renderer.d.ts +66 -0
  26. package/dist/card/run-renderer.js +841 -0
  27. package/dist/card/run-state.d.ts +103 -0
  28. package/dist/card/run-state.js +313 -0
  29. package/dist/card/text-truncate.d.ts +56 -0
  30. package/dist/card/text-truncate.js +184 -0
  31. package/dist/card/time.d.ts +1 -0
  32. package/dist/card/time.js +14 -0
  33. package/dist/card/tool-render.d.ts +25 -0
  34. package/dist/card/tool-render.js +176 -0
  35. package/dist/cli.d.ts +28 -0
  36. package/dist/cli.js +89 -0
  37. package/dist/common/guards.d.ts +37 -0
  38. package/dist/common/guards.js +65 -0
  39. package/dist/config/codex-config.d.ts +113 -0
  40. package/dist/config/codex-config.js +428 -0
  41. package/dist/config/dir.d.ts +17 -0
  42. package/dist/config/dir.js +81 -0
  43. package/dist/config/index.d.ts +219 -0
  44. package/dist/config/index.js +388 -0
  45. package/dist/config/kimi-config.d.ts +33 -0
  46. package/dist/config/kimi-config.js +111 -0
  47. package/dist/config/opencode-config.d.ts +20 -0
  48. package/dist/config/opencode-config.js +124 -0
  49. package/dist/config/pi-config.d.ts +49 -0
  50. package/dist/config/pi-config.js +151 -0
  51. package/dist/config/wizard.d.ts +12 -0
  52. package/dist/config/wizard.js +84 -0
  53. package/dist/connector/file-limits.d.ts +7 -0
  54. package/dist/connector/file-limits.js +8 -0
  55. package/dist/connector/index.d.ts +86 -0
  56. package/dist/connector/index.js +340 -0
  57. package/dist/error-classification.d.ts +15 -0
  58. package/dist/error-classification.js +24 -0
  59. package/dist/index.d.ts +1 -0
  60. package/dist/index.js +580 -0
  61. package/dist/instance-lock.d.ts +30 -0
  62. package/dist/instance-lock.js +184 -0
  63. package/dist/logger/index.d.ts +57 -0
  64. package/dist/logger/index.js +178 -0
  65. package/dist/order/index.d.ts +27 -0
  66. package/dist/order/index.js +90 -0
  67. package/dist/persistence/atomic-write.d.ts +10 -0
  68. package/dist/persistence/atomic-write.js +65 -0
  69. package/dist/persistence/load-json-file.d.ts +9 -0
  70. package/dist/persistence/load-json-file.js +23 -0
  71. package/dist/restart.d.ts +24 -0
  72. package/dist/restart.js +73 -0
  73. package/dist/router/card-helpers.d.ts +28 -0
  74. package/dist/router/card-helpers.js +65 -0
  75. package/dist/router/config/claude.d.ts +14 -0
  76. package/dist/router/config/claude.js +72 -0
  77. package/dist/router/config/codex.d.ts +22 -0
  78. package/dist/router/config/codex.js +100 -0
  79. package/dist/router/config/common/render.d.ts +16 -0
  80. package/dist/router/config/common/render.js +158 -0
  81. package/dist/router/config/index.d.ts +18 -0
  82. package/dist/router/config/index.js +38 -0
  83. package/dist/router/config/kimi.d.ts +21 -0
  84. package/dist/router/config/kimi.js +63 -0
  85. package/dist/router/config/opencode.d.ts +12 -0
  86. package/dist/router/config/opencode.js +44 -0
  87. package/dist/router/config/pi.d.ts +12 -0
  88. package/dist/router/config/pi.js +50 -0
  89. package/dist/router/config/types.d.ts +43 -0
  90. package/dist/router/config/types.js +8 -0
  91. package/dist/router/index.d.ts +318 -0
  92. package/dist/router/index.js +2715 -0
  93. package/dist/router/order-exec-dispatch.d.ts +30 -0
  94. package/dist/router/order-exec-dispatch.js +48 -0
  95. package/dist/router/utils.d.ts +44 -0
  96. package/dist/router/utils.js +116 -0
  97. package/dist/runner/bash/index.d.ts +4 -0
  98. package/dist/runner/bash/index.js +5 -0
  99. package/dist/runner/bash/runner.d.ts +55 -0
  100. package/dist/runner/bash/runner.js +213 -0
  101. package/dist/runner/claude/index.d.ts +4 -0
  102. package/dist/runner/claude/index.js +5 -0
  103. package/dist/runner/claude/runner.d.ts +29 -0
  104. package/dist/runner/claude/runner.js +83 -0
  105. package/dist/runner/codex/argv.d.ts +33 -0
  106. package/dist/runner/codex/argv.js +40 -0
  107. package/dist/runner/codex/index.d.ts +1 -0
  108. package/dist/runner/codex/index.js +2 -0
  109. package/dist/runner/codex/jsonl.d.ts +37 -0
  110. package/dist/runner/codex/jsonl.js +221 -0
  111. package/dist/runner/codex/runner.d.ts +65 -0
  112. package/dist/runner/codex/runner.js +124 -0
  113. package/dist/runner/common/exec-translator.d.ts +73 -0
  114. package/dist/runner/common/exec-translator.js +105 -0
  115. package/dist/runner/common/jsonl-stream.d.ts +39 -0
  116. package/dist/runner/common/jsonl-stream.js +203 -0
  117. package/dist/runner/common/process-stopper.d.ts +28 -0
  118. package/dist/runner/common/process-stopper.js +79 -0
  119. package/dist/runner/common/runner-utils.d.ts +21 -0
  120. package/dist/runner/common/runner-utils.js +65 -0
  121. package/dist/runner/common/spawn-heartbeat.d.ts +33 -0
  122. package/dist/runner/common/spawn-heartbeat.js +51 -0
  123. package/dist/runner/common/spawning-runner.d.ts +321 -0
  124. package/dist/runner/common/spawning-runner.js +634 -0
  125. package/dist/runner/common/usage.d.ts +31 -0
  126. package/dist/runner/common/usage.js +29 -0
  127. package/dist/runner/index.d.ts +19 -0
  128. package/dist/runner/index.js +24 -0
  129. package/dist/runner/kimi/index.d.ts +1 -0
  130. package/dist/runner/kimi/index.js +2 -0
  131. package/dist/runner/kimi/jsonl.d.ts +28 -0
  132. package/dist/runner/kimi/jsonl.js +143 -0
  133. package/dist/runner/kimi/runner.d.ts +50 -0
  134. package/dist/runner/kimi/runner.js +105 -0
  135. package/dist/runner/opencode/argv.d.ts +32 -0
  136. package/dist/runner/opencode/argv.js +35 -0
  137. package/dist/runner/opencode/index.d.ts +1 -0
  138. package/dist/runner/opencode/index.js +2 -0
  139. package/dist/runner/opencode/jsonl.d.ts +68 -0
  140. package/dist/runner/opencode/jsonl.js +295 -0
  141. package/dist/runner/opencode/runner.d.ts +63 -0
  142. package/dist/runner/opencode/runner.js +93 -0
  143. package/dist/runner/pi/index.d.ts +1 -0
  144. package/dist/runner/pi/index.js +2 -0
  145. package/dist/runner/pi/jsonl.d.ts +128 -0
  146. package/dist/runner/pi/jsonl.js +249 -0
  147. package/dist/runner/pi/runner.d.ts +37 -0
  148. package/dist/runner/pi/runner.js +76 -0
  149. package/dist/runner/registry.d.ts +54 -0
  150. package/dist/runner/registry.js +75 -0
  151. package/dist/runner/resolve-agent-choices.d.ts +7 -0
  152. package/dist/runner/resolve-agent-choices.js +76 -0
  153. package/dist/runner/sync-agent-choices.d.ts +6 -0
  154. package/dist/runner/sync-agent-choices.js +73 -0
  155. package/dist/runner/types.d.ts +250 -0
  156. package/dist/runner/types.js +8 -0
  157. package/dist/session/claude/index.d.ts +1 -0
  158. package/dist/session/claude/index.js +2 -0
  159. package/dist/session/claude/session-reader.d.ts +34 -0
  160. package/dist/session/claude/session-reader.js +46 -0
  161. package/dist/session/claude/sessions.d.ts +53 -0
  162. package/dist/session/claude/sessions.js +528 -0
  163. package/dist/session/codex/index.d.ts +1 -0
  164. package/dist/session/codex/index.js +2 -0
  165. package/dist/session/codex/rollout-reader.d.ts +88 -0
  166. package/dist/session/codex/rollout-reader.js +473 -0
  167. package/dist/session/codex/sessions.d.ts +21 -0
  168. package/dist/session/codex/sessions.js +40 -0
  169. package/dist/session/common/catch-up.d.ts +12 -0
  170. package/dist/session/common/catch-up.js +31 -0
  171. package/dist/session/common/constants.d.ts +11 -0
  172. package/dist/session/common/constants.js +12 -0
  173. package/dist/session/common/content-blocks.d.ts +37 -0
  174. package/dist/session/common/content-blocks.js +68 -0
  175. package/dist/session/common/jsonl.d.ts +77 -0
  176. package/dist/session/common/jsonl.js +351 -0
  177. package/dist/session/common/usage-accumulator.d.ts +58 -0
  178. package/dist/session/common/usage-accumulator.js +72 -0
  179. package/dist/session/index.d.ts +7 -0
  180. package/dist/session/index.js +11 -0
  181. package/dist/session/kimi/index.d.ts +1 -0
  182. package/dist/session/kimi/index.js +2 -0
  183. package/dist/session/kimi/sessions.d.ts +81 -0
  184. package/dist/session/kimi/sessions.js +527 -0
  185. package/dist/session/opencode/index.d.ts +1 -0
  186. package/dist/session/opencode/index.js +2 -0
  187. package/dist/session/opencode/sessions.d.ts +81 -0
  188. package/dist/session/opencode/sessions.js +388 -0
  189. package/dist/session/pi/index.d.ts +1 -0
  190. package/dist/session/pi/index.js +2 -0
  191. package/dist/session/pi/sessions.d.ts +27 -0
  192. package/dist/session/pi/sessions.js +399 -0
  193. package/dist/session/registry.d.ts +12 -0
  194. package/dist/session/registry.js +20 -0
  195. package/dist/session/session-store.d.ts +86 -0
  196. package/dist/session/session-store.js +450 -0
  197. package/dist/startup-contact.d.ts +18 -0
  198. package/dist/startup-contact.js +51 -0
  199. package/dist/workspace/index.d.ts +19 -0
  200. package/dist/workspace/index.js +53 -0
  201. package/package.json +93 -0
@@ -0,0 +1,321 @@
1
+ import { type ChildProcess } from 'node:child_process';
2
+ import type { Readable } from 'node:stream';
3
+ import { ProcessStopper } from './process-stopper.js';
4
+ import { SpawnHeartbeat } from './spawn-heartbeat.js';
5
+ import type { AgentEvent, SpawnOptions } from '../types.js';
6
+ /**
7
+ * 进程级退出监听单例分发(P1-1 修复,2026-08-02)。
8
+ *
9
+ * 背景:5 个 runner(claude/codex/opencode/pi/kimi)的 registerExitHandlers 曾是
10
+ * 同构复制,每个实例 process.on('exit'|'SIGINT'|'SIGTERM') 注册 3 个永不移除的
11
+ * 闭包(捕获整个 runner 实例 + sessionReader + pidFilePath)。Bridge 每次 run
12
+ * 结束淘汰 (cwd, kind) 槽位、下次 run cache miss 新建实例再注册 → 约第 4 个 run
13
+ * 起 MaxListenersExceededWarning 刷屏,历史实例被闭包永久持有,内存无界增长。
14
+ *
15
+ * 现在:进程级监听只注册一次,内部 Set<SpawningRunner> 管理注册实例;
16
+ * registerExitHandlers() 只把实例加入集合(幂等),桥接层在淘汰槽位时调
17
+ * unregisterExitHandlers() 移除实例,让 runner 可被 GC。SIGINT/SIGTERM 语义
18
+ * 保持原样:cleanup 全部已注册实例后 exit 130/143。
19
+ */
20
+ /**
21
+ * Exit-cleanup contract: anything that spawns a child process group and wants
22
+ * process-level cleanup (agent runners via SpawningRunner, and BashProcessRunner
23
+ * for `!` commands, P1-22) registers with the singleton dispatcher.
24
+ */
25
+ interface ExitCleanupHandler {
26
+ cleanupOnExit(): void;
27
+ }
28
+ /** Register a process-exit cleanup handler (installs listeners at most once). */
29
+ export declare function registerExitCleanup(handler: ExitCleanupHandler): void;
30
+ /** Remove a handler so it can be GC'd (agent slots / finished bash runs). */
31
+ export declare function unregisterExitCleanup(handler: ExitCleanupHandler): void;
32
+ /**
33
+ * Stateful translator contract for runners that need per-run translation state
34
+ * (codex/opencode/pi/kimi). Subclasses return an instance from
35
+ * `createTranslator(opts)`; the base `run()` loop calls `translate(raw)` per
36
+ * event, then folds terminal state into `buildResultEvent(...)` at the end.
37
+ *
38
+ * `translate()` returns `AgentEvent | AgentEvent[] | null` (single event,
39
+ * multiple events, or filtered-out). `isTerminal()` / `finish()` / `getTerminalError()`
40
+ * / `hasAgentTerminalError()` are folded into the unified result event via
41
+ * `resolveTranslatorError()`.
42
+ *
43
+ * `getSessionId()` / `getLastUsage()` are optional because ClaudeRunner uses
44
+ * the stateless `translate()` hook (no translator object) and reads neither.
45
+ */
46
+ export interface RunnerTranslator {
47
+ translate(raw: unknown): AgentEvent | AgentEvent[] | null;
48
+ isTerminal(): boolean;
49
+ finish(reason: 'failed' | 'interrupted' | 'timeout'): void;
50
+ getTerminalError(): string | undefined;
51
+ hasAgentTerminalError(): boolean;
52
+ getSessionId?(): string | undefined;
53
+ getLastUsage?(): Record<string, unknown> | undefined;
54
+ }
55
+ /**
56
+ * Abstract base class for runners that spawn a child process per turn.
57
+ *
58
+ * Encapsulates the spawn + completion + cleanup orchestration shared by
59
+ * Claude/Codex/OpenCode/Pi/Kimi runners. Subclasses override:
60
+ * - buildArgv(opts) → agent-specific CLI flags (required)
61
+ * - createTranslator(opts) → stateful translator (codex/opencode/pi/kimi)
62
+ * OR translate(raw, ctx) → stateless passthrough (claude)
63
+ *
64
+ * Optional hooks (with sensible defaults):
65
+ * - getStdio() → stdio config (default ['ignore','pipe','pipe'])
66
+ * - getSpawnEnv(opts) → env vars (default process.env)
67
+ * - setupStdin(proc, message) → write prompt to stdin (default no-op)
68
+ * - createStreamReader(stdout) → JSONL or readline parser (default createJSONLStream)
69
+ * - validateBeforeRun(opts) → pre-spawn validation (default no-op)
70
+ * - awaitCompletion(proc, p) → wait for exit (default return p; kimi adds 5s race)
71
+ * - awaitSpawnError(proc) → wait for spawn error (default once('error'); kimi adds 5s race)
72
+ * - resolveTranslatorError(t, c) → translatorError precedence (default honors agent errors)
73
+ *
74
+ * The base class always emits a unified result event at the end of `run()`
75
+ * via `buildResultEvent(...)` — never throws on non-zero exit. This matches
76
+ * the contract pinned by codex/opencode/pi/kimi subclass anchors and the
77
+ * bridge's `runAgentStreamToEnd` error handling (which accepts both thrown
78
+ * errors and yielded error-result events).
79
+ */
80
+ export declare abstract class SpawningRunner {
81
+ protected currentProcess: ChildProcess | null;
82
+ protected readonly pidFilePath: string;
83
+ protected readonly stopper: ProcessStopper;
84
+ protected readonly spawnHeartbeat: SpawnHeartbeat;
85
+ protected binary: string;
86
+ protected stopGraceMs: number;
87
+ /**
88
+ * Log prefix used in all operational log lines emitted by this runner
89
+ * (spawn, pid file, non-zero exit, stderr, killOrphan, stop cleanup) and
90
+ * as the SpawnHeartbeat label. Subclasses pass their own tag (e.g.
91
+ * 'claude-runner') so operators can grep agent-specific logs; the default
92
+ * 'spawning-runner' keeps the base-class anchor tests' neutral identity.
93
+ */
94
+ protected readonly logTag: string;
95
+ /**
96
+ * The `message` argument from the most recent `run(message, opts)` call.
97
+ * Set in `run()` before `buildArgv(opts)` is invoked so subclasses can
98
+ * embed the message in their agent-specific argv (e.g. claude's `-p
99
+ * <message>`). This avoids changing the `buildArgv(opts)` signature,
100
+ * which would break existing anchor subclasses.
101
+ */
102
+ protected currentMessage: string;
103
+ /**
104
+ * Whether the current run was interrupted by user-initiated stop().
105
+ * Set to true by stop() when a running process is being terminated;
106
+ * reset to false at the top of run(). `resolveTranslatorError()` and
107
+ * `buildResultEvent()` read this to decide result event subtype
108
+ * (error vs success) and the error message precedence.
109
+ */
110
+ protected stoppedByUser: boolean;
111
+ constructor(opts: {
112
+ binary?: string;
113
+ pidDir?: string;
114
+ workspace: string;
115
+ stopGraceMs?: number;
116
+ spawnHeartbeatMs?: number;
117
+ /**
118
+ * Filename prefix for the pid file. Defaults to 'spawning'. Each
119
+ * subclass should pass its own prefix (e.g. 'claude', 'codex') so
120
+ * multiple runners sharing the same pidDir do not clobber each
121
+ * other's pid files.
122
+ */
123
+ pidFilePrefix?: string;
124
+ /**
125
+ * Log prefix for operational log lines and the SpawnHeartbeat label.
126
+ * Defaults to 'spawning-runner'. Subclasses pass their own tag (e.g.
127
+ * 'claude-runner') so operators can grep agent-specific logs and the
128
+ * spawn-stage-stalled WARN identifies the right agent.
129
+ */
130
+ logTag?: string;
131
+ });
132
+ get isRunning(): boolean;
133
+ /**
134
+ * stdio config for spawn. Default: stdin ignored (claude/kimi/pi pass the
135
+ * prompt via argv). codex/opencode override to ['pipe','pipe','pipe'] so
136
+ * they can write the prompt to stdin via `setupStdin`.
137
+ */
138
+ protected getStdio(): ('ignore' | 'pipe')[];
139
+ /**
140
+ * Env vars for spawn. Default: process.env. opencode overrides to sync
141
+ * PWD=opts.cwd (opencode's directory detection reads PWD, not cwd).
142
+ */
143
+ protected getSpawnEnv(_opts: SpawnOptions): NodeJS.ProcessEnv;
144
+ /**
145
+ * Write the prompt to the child's stdin (called after spawn succeeds).
146
+ * Default: no-op. codex/opencode override to `proc.stdin.end(message)`.
147
+ */
148
+ protected setupStdin(_proc: ChildProcess, _message: string): void;
149
+ /**
150
+ * Create an async iterator over the child's stdout. Default: createJSONLStream
151
+ * (claude/kimi/pi) with P1-4 backpressure enabled (pauseThreshold=100).
152
+ * Subclasses that need to silently skip non-JSON lines should override
153
+ * `handleBadStreamLine` instead of this method.
154
+ */
155
+ protected createStreamReader(stdout: Readable): AsyncGenerator<unknown>;
156
+ /**
157
+ * Hook called when createJSONLStream encounters a line that cannot be parsed
158
+ * as JSON. Default: log a warning via getLogger().warn (same format as
159
+ * jsonl-stream's built-in warning). Subclasses override to change behavior
160
+ * (e.g. codex/opencode silently skip by providing an empty override).
161
+ */
162
+ protected handleBadStreamLine(line: string): void;
163
+ /**
164
+ * Create a stateful translator for this run. Default: null (uses the
165
+ * stateless `translate(raw, ctx)` hook). codex/opencode/pi/kimi override to
166
+ * return their translator instance.
167
+ */
168
+ protected createTranslator(_opts: SpawnOptions): RunnerTranslator | null;
169
+ /**
170
+ * Pre-spawn validation. Return an AgentEvent to yield it and abort run()
171
+ * (e.g. codex's API key check yields an error result and returns).
172
+ * Default: null (no validation).
173
+ */
174
+ protected validateBeforeRun(_opts: SpawnOptions): AgentEvent | null;
175
+ /**
176
+ * Await process completion. Default: return the completion promise as-is.
177
+ * kimi overrides to add a 5s timeout race + SIGKILL fallback (kimi
178
+ * sometimes hangs after stdout closes).
179
+ */
180
+ protected awaitCompletion(_proc: ChildProcess, completion: Promise<{
181
+ code: number | null;
182
+ signal: NodeJS.Signals | null;
183
+ }>): Promise<{
184
+ code: number | null;
185
+ signal: NodeJS.Signals | null;
186
+ }>;
187
+ /**
188
+ * Await the spawn 'error' event when proc.pid === undefined. Races a
189
+ * finite timeout (review P2-11) against the 'error' event: Node guarantees
190
+ * 'error' for ENOENT/EACCES, but some binaries fail silently without ever
191
+ * emitting it (kimi's CLI is documented to do so). Without the race, run()
192
+ * hangs forever → the workspace serial queue never settles → permanent
193
+ * deadlock, and /stop can't recover (ProcessStopper returns early when
194
+ * pid === undefined). The timeout keeps the deadlock bounded.
195
+ */
196
+ protected awaitSpawnError(proc: ChildProcess): Promise<Error | undefined>;
197
+ /**
198
+ * Resolve the translatorError to pass to buildResultEvent. Default
199
+ * precedence (most-specific first):
200
+ * - agent-reported terminal error (translator.hasAgentTerminalError()):
201
+ * always wins — the agent error is the root cause, signal/code is a
202
+ * consequence. E.g. codex `turn.failed` then non-zero exit.
203
+ * - stream-ended-early symptom (translator.getTerminalError() set by
204
+ * finish('failed')): ONLY surfaces when there is no external cause
205
+ * (signal / non-zero code / user stop). The signal/code is the root
206
+ * cause; the early stream-end is a symptom.
207
+ * - otherwise: undefined (signal/code/stoppedByUser drives the message).
208
+ *
209
+ * Subclasses can override for custom precedence but the default matches
210
+ * the contract pinned by codex/opencode subclass anchors.
211
+ */
212
+ protected resolveTranslatorError(translator: RunnerTranslator | null, ctx: {
213
+ code: number | null;
214
+ signal: NodeJS.Signals | null;
215
+ }): string | undefined;
216
+ /**
217
+ * Spawn the agent binary with argv built by buildArgv(opts), iterate its
218
+ * stdout stream, and yield translated events. Always emits a unified
219
+ * result event at the end via `buildResultEvent(...)` — never throws on
220
+ * non-zero exit (the bridge accepts both thrown errors and yielded
221
+ * error-result events, and the latter carries richer diagnostic info).
222
+ *
223
+ * Spawn failures (binary missing, pid undefined) yield an `authErrorEvent`
224
+ * instead of throwing, so the user sees a friendly error card.
225
+ */
226
+ run(message: string, opts: SpawnOptions): AsyncGenerator<AgentEvent>;
227
+ /**
228
+ * Stop the current process if one is running. Delegates the actual
229
+ * SIGTERM → grace → SIGKILL sequence to `this.stopper.stop(proc, opts)`
230
+ * (see `src/runner/common/process-stopper.ts`), forwarding the `immediate`
231
+ * flag verbatim so all 5 subclasses inherit identical stop semantics.
232
+ */
233
+ stop(opts?: {
234
+ immediate?: boolean;
235
+ }): Promise<void>;
236
+ killOrphan(): void;
237
+ /**
238
+ * P1-10: verify the process behind a stale pid file is actually ours before
239
+ * sending any signal. `ps -o command=` (not `comm=`) is used because agent
240
+ * binaries may be bash-wrapped scripts whose comm is the interpreter name
241
+ * (`/bin/bash`); the full command line contains the binary path/basename.
242
+ *
243
+ * Returns:
244
+ * 'match' — ps succeeded and the command line contains this.binary
245
+ * (absolute path) or its basename (PATH lookup).
246
+ * 'mismatch' — ps succeeded but the command line is clearly a different
247
+ * process (pid was recycled to an unrelated process).
248
+ * 'unknown' — ps failed / process gone / output unreadable: cannot tell.
249
+ */
250
+ private matchPidToBinary;
251
+ /**
252
+ * Register this runner with the process-level exit dispatcher (singleton).
253
+ * Process listeners are installed at most once; subsequent calls only add
254
+ * the instance to the internal Set (idempotent — no listener accumulation).
255
+ * Bridge evicts the (cwd, kind) slot after each run; call
256
+ * `unregisterExitHandlers()` there so the instance can be GC'd.
257
+ */
258
+ registerExitHandlers(): void;
259
+ /**
260
+ * Remove this runner from the process-level exit dispatcher. Called when
261
+ * the bridge evicts the runner cache slot (finalizeRun / interruptCurrentRun
262
+ * / clearRunners) so the instance is no longer retained by the dispatcher.
263
+ */
264
+ unregisterExitHandlers(): void;
265
+ /**
266
+ * Current number of runners registered with the process-level exit
267
+ * dispatcher. Diagnostics / test-support introspection (P1-1 anchor asserts
268
+ * the count returns to baseline after bridge eviction).
269
+ */
270
+ static getRegisteredExitHandlerCount(): number;
271
+ /**
272
+ * Shared process-exit cleanup: SIGTERM the still-running child process and
273
+ * remove the pid file. Called by the singleton dispatcher for every
274
+ * registered runner; previously duplicated verbatim in all 5 runner
275
+ * subclasses.
276
+ */
277
+ cleanupOnExit(): void;
278
+ /**
279
+ * Build a unified result event from process exit state. Centralizes the
280
+ * result-event semantics specified in Candidate 2:
281
+ * - stoppedByUser → error ("interrupted by user")
282
+ * - translatorError set → error (translator-supplied message, e.g. codex
283
+ * `turn.failed` or "stream ended before a terminal event")
284
+ * - code !== 0 && code !== null → error (exit code + stderr tail)
285
+ * - signal !== null → error (killed by signal)
286
+ * - otherwise → success (with optional usage)
287
+ *
288
+ * Error message precedence (most-specific first):
289
+ * - stoppedByUser: "{binary} interrupted by user"
290
+ * - translatorError: verbatim translator-supplied message
291
+ * - signal: "{binary} killed by signal {signal}{stderr tail}"
292
+ * - non-zero code: "{binary} exited code={code}{stderr tail}"
293
+ *
294
+ * @param opts.code - Process exit code (null if killed by signal)
295
+ * @param opts.signal - Process signal code (null if exited normally)
296
+ * @param opts.stderr - Accumulated stderr (tail included in code/signal errors)
297
+ * @param opts.sessionId - Session ID to include in the result event
298
+ * @param opts.usage - Token usage to include on success
299
+ * @param opts.translatorError - Agent-specific terminal error message (e.g.
300
+ * codex turn.failed, or "stream ended early")
301
+ * @returns AgentEvent with type='result'
302
+ */
303
+ protected buildResultEvent(opts: {
304
+ code: number | null;
305
+ signal: NodeJS.Signals | null;
306
+ stderr?: string;
307
+ sessionId?: string;
308
+ usage?: Record<string, unknown>;
309
+ translatorError?: string;
310
+ }): AgentEvent;
311
+ protected abstract buildArgv(opts: SpawnOptions): string[];
312
+ /**
313
+ * Stateless passthrough translator hook. Used by ClaudeRunner
314
+ * which does not need per-run translation state. Subclasses that return
315
+ * a translator from `createTranslator(opts)` leave this as the default
316
+ * no-op — the base `run()` loop only calls `translate()` when
317
+ * `createTranslator()` returns null.
318
+ */
319
+ protected translate(_rawEvent: unknown, _ctx: unknown): AgentEvent | AgentEvent[] | null;
320
+ }
321
+ export {};