@almyty/runner 1.2.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 (59) hide show
  1. package/README.md +72 -0
  2. package/dist/binaries.d.ts +30 -0
  3. package/dist/binaries.js +99 -0
  4. package/dist/binaries.js.map +1 -0
  5. package/dist/cli.d.ts +12 -0
  6. package/dist/cli.js +128 -0
  7. package/dist/cli.js.map +1 -0
  8. package/dist/coding-agents/detect.d.ts +12 -0
  9. package/dist/coding-agents/detect.js +35 -0
  10. package/dist/coding-agents/detect.js.map +1 -0
  11. package/dist/coding-agents/index.d.ts +15 -0
  12. package/dist/coding-agents/index.js +15 -0
  13. package/dist/coding-agents/index.js.map +1 -0
  14. package/dist/coding-agents/registry.d.ts +9 -0
  15. package/dist/coding-agents/registry.js +260 -0
  16. package/dist/coding-agents/registry.js.map +1 -0
  17. package/dist/coding-agents/spawn-spec.d.ts +47 -0
  18. package/dist/coding-agents/spawn-spec.js +58 -0
  19. package/dist/coding-agents/spawn-spec.js.map +1 -0
  20. package/dist/coding-agents/status.d.ts +38 -0
  21. package/dist/coding-agents/status.js +111 -0
  22. package/dist/coding-agents/status.js.map +1 -0
  23. package/dist/coding-agents/types.d.ts +104 -0
  24. package/dist/coding-agents/types.js +18 -0
  25. package/dist/coding-agents/types.js.map +1 -0
  26. package/dist/coding-sessions.d.ts +80 -0
  27. package/dist/coding-sessions.js +121 -0
  28. package/dist/coding-sessions.js.map +1 -0
  29. package/dist/config.d.ts +49 -0
  30. package/dist/config.js +180 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/daemon.d.ts +71 -0
  33. package/dist/daemon.js +353 -0
  34. package/dist/daemon.js.map +1 -0
  35. package/dist/handlers.d.ts +39 -0
  36. package/dist/handlers.js +299 -0
  37. package/dist/handlers.js.map +1 -0
  38. package/dist/index.d.ts +17 -0
  39. package/dist/index.js +18 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/policy.d.ts +16 -0
  42. package/dist/policy.js +134 -0
  43. package/dist/policy.js.map +1 -0
  44. package/dist/process-manager.d.ts +107 -0
  45. package/dist/process-manager.js +334 -0
  46. package/dist/process-manager.js.map +1 -0
  47. package/dist/protocol.d.ts +53 -0
  48. package/dist/protocol.js +39 -0
  49. package/dist/protocol.js.map +1 -0
  50. package/dist/runtime-info.d.ts +23 -0
  51. package/dist/runtime-info.js +35 -0
  52. package/dist/runtime-info.js.map +1 -0
  53. package/dist/streamable-client.d.ts +69 -0
  54. package/dist/streamable-client.js +204 -0
  55. package/dist/streamable-client.js.map +1 -0
  56. package/dist/types.d.ts +112 -0
  57. package/dist/types.js +21 -0
  58. package/dist/types.js.map +1 -0
  59. package/package.json +54 -0
@@ -0,0 +1,334 @@
1
+ import { spawn as cpSpawn } from 'child_process';
2
+ import { randomUUID } from 'crypto';
3
+ import { EventEmitter } from 'events';
4
+ import { execFile } from 'child_process';
5
+ import { promisify } from 'util';
6
+ import { RunnerError, RUNNER_ERROR_CODES, } from './types.js';
7
+ import { lastFrameResetIndex } from './coding-agents/index.js';
8
+ const execFileAsync = promisify(execFile);
9
+ /** Cap on the retained status tail (~ a couple of screenfuls). */
10
+ const RECENT_TAIL_CAP = 8192;
11
+ /**
12
+ * Per-runner process orchestrator.
13
+ *
14
+ * Bookkeeping: every process is namespaced by workspaceId. Cross-
15
+ * workspace lookups error loudly (process_cross_workspace) — this is
16
+ * cheap insurance against an agent in workspace A handing a stale
17
+ * process_id to a tool that runs in workspace B.
18
+ *
19
+ * Buffering: stdout/stderr accumulate in a per-process string buffer.
20
+ * read() drains it; wait_for_idle() reads with idle-detection. We
21
+ * don't try to interpret encodings or framing; the runner's job is
22
+ * to deliver bytes faithfully, not to reason about what they mean.
23
+ */
24
+ export class ProcessManager {
25
+ adapter;
26
+ maxConcurrent;
27
+ processes = new Map();
28
+ constructor(adapter, maxConcurrent) {
29
+ this.adapter = adapter;
30
+ this.maxConcurrent = maxConcurrent;
31
+ }
32
+ // ── snapshots ───────────────────────────────────────────────────────
33
+ inUse() {
34
+ let n = 0;
35
+ for (const p of this.processes.values())
36
+ if (p.handle.status === 'running')
37
+ n++;
38
+ return n;
39
+ }
40
+ list(workspaceId) {
41
+ const handles = [];
42
+ for (const p of this.processes.values()) {
43
+ if (workspaceId && p.handle.workspaceId !== workspaceId)
44
+ continue;
45
+ handles.push(p.handle);
46
+ }
47
+ return handles;
48
+ }
49
+ // ── lifecycle ───────────────────────────────────────────────────────
50
+ async spawn(workspaceId, opts) {
51
+ if (this.inUse() >= this.maxConcurrent) {
52
+ throw new RunnerError(`runner at capacity (${this.maxConcurrent} concurrent processes)`, RUNNER_ERROR_CODES.CAPACITY_EXCEEDED);
53
+ }
54
+ const usePty = opts.pty !== false;
55
+ const adapter = usePty
56
+ ? await this.adapter.spawnPty(opts)
57
+ : await this.adapter.spawnPipe(opts);
58
+ const processId = `proc_${randomUUID()}`;
59
+ const handle = {
60
+ processId,
61
+ binary: opts.binary,
62
+ startedAt: new Date(),
63
+ status: 'running',
64
+ workspaceId,
65
+ };
66
+ let resolveExit;
67
+ const exitPromise = new Promise(r => { resolveExit = r; });
68
+ const running = {
69
+ handle,
70
+ adapter,
71
+ buffer: '',
72
+ recentTail: '',
73
+ lastOutputAt: Date.now(),
74
+ exitPromise,
75
+ exitInfo: null,
76
+ };
77
+ adapter.on('data', (chunk) => {
78
+ const text = typeof chunk === 'string' ? chunk : chunk.toString('utf8');
79
+ running.buffer += text;
80
+ // Maintain the status tail as the latest repaint frame. If this chunk
81
+ // contains a frame-reset (erase-display / cursor-home), the prior frame
82
+ // is stale — keep only from the last reset so a since-cleared status line
83
+ // can't falsely read as busy.
84
+ const reset = lastFrameResetIndex(text);
85
+ running.recentTail =
86
+ reset >= 0
87
+ ? text.slice(reset).slice(-RECENT_TAIL_CAP)
88
+ : (running.recentTail + text).slice(-RECENT_TAIL_CAP);
89
+ running.lastOutputAt = Date.now();
90
+ });
91
+ adapter.on('exit', (info) => {
92
+ running.handle.status = info.signal ? 'killed' : 'exited';
93
+ const exit = {
94
+ exitCode: info.exitCode,
95
+ signal: info.signal,
96
+ };
97
+ running.exitInfo = exit;
98
+ resolveExit(exit);
99
+ });
100
+ this.processes.set(processId, running);
101
+ return handle;
102
+ }
103
+ /** Look up a process; enforces workspace ownership. */
104
+ getOrThrow(workspaceId, processId) {
105
+ const proc = this.processes.get(processId);
106
+ if (!proc) {
107
+ throw new RunnerError(`unknown process ${processId}`, RUNNER_ERROR_CODES.PROCESS_NOT_FOUND);
108
+ }
109
+ if (proc.handle.workspaceId !== workspaceId) {
110
+ // Match the spec: "Calls referencing a resource from a
111
+ // different workspace error loudly with a clear message."
112
+ throw new RunnerError(`process ${processId} is not in workspace ${workspaceId}`, RUNNER_ERROR_CODES.PROCESS_CROSS_WORKSPACE);
113
+ }
114
+ return proc;
115
+ }
116
+ // ── I/O ─────────────────────────────────────────────────────────────
117
+ write(workspaceId, processId, data) {
118
+ const proc = this.getOrThrow(workspaceId, processId);
119
+ if (proc.handle.status !== 'running') {
120
+ throw new RunnerError(`process ${processId} has already exited`, RUNNER_ERROR_CODES.PROCESS_ALREADY_EXITED);
121
+ }
122
+ proc.adapter.write(data);
123
+ }
124
+ /**
125
+ * Drain the output buffer. Returns whatever has accumulated since
126
+ * the last call; future calls return only what's new.
127
+ */
128
+ read(workspaceId, processId) {
129
+ const proc = this.getOrThrow(workspaceId, processId);
130
+ const data = proc.buffer;
131
+ proc.buffer = '';
132
+ return { data, moreAvailable: false };
133
+ }
134
+ /**
135
+ * Non-destructive peek at the recent output tail. Unlike read(), this does
136
+ * NOT drain anything — it's for status classification, which must work even
137
+ * after the agent has drained `buffer` via read(). Returns the rolling tail
138
+ * (capped at RECENT_TAIL_CAP) plus the process status and idle interval.
139
+ */
140
+ snapshot(workspaceId, processId) {
141
+ const proc = this.getOrThrow(workspaceId, processId);
142
+ return {
143
+ tail: proc.recentTail,
144
+ binary: proc.handle.binary,
145
+ status: proc.handle.status,
146
+ idleMs: Date.now() - proc.lastOutputAt,
147
+ };
148
+ }
149
+ /**
150
+ * Subscribe to a process's live output and exit. Push-based counterpart to
151
+ * read(): the coding-session layer streams chunks to the backend as they
152
+ * arrive instead of polling. Does NOT drain the pull buffer — a caller can
153
+ * observe and read() the same process without losing bytes in either place.
154
+ * Returns an unsubscribe function.
155
+ */
156
+ observe(workspaceId, processId, handlers) {
157
+ const proc = this.getOrThrow(workspaceId, processId);
158
+ const onData = (chunk) => {
159
+ handlers.onData?.(typeof chunk === 'string' ? chunk : chunk.toString('utf8'));
160
+ };
161
+ const onExit = (info) => {
162
+ handlers.onExit?.({ exitCode: info.exitCode, signal: info.signal });
163
+ };
164
+ if (handlers.onData)
165
+ proc.adapter.on('data', onData);
166
+ if (handlers.onExit)
167
+ proc.adapter.on('exit', onExit);
168
+ return () => {
169
+ proc.adapter.off('data', onData);
170
+ proc.adapter.off('exit', onExit);
171
+ };
172
+ }
173
+ async waitForIdle(workspaceId, processId, opts) {
174
+ const proc = this.getOrThrow(workspaceId, processId);
175
+ const start = Date.now();
176
+ let captured = '';
177
+ return new Promise(resolve => {
178
+ const drain = () => {
179
+ captured += proc.buffer;
180
+ proc.buffer = '';
181
+ };
182
+ const tick = () => {
183
+ const now = Date.now();
184
+ const sinceLast = now - proc.lastOutputAt;
185
+ const sinceStart = now - start;
186
+ drain();
187
+ if (sinceLast >= opts.idleMs) {
188
+ clearInterval(timer);
189
+ resolve({ data: captured, idle: true });
190
+ return;
191
+ }
192
+ if (sinceStart >= opts.maxWaitMs) {
193
+ clearInterval(timer);
194
+ resolve({ data: captured, idle: false });
195
+ return;
196
+ }
197
+ if (proc.handle.status !== 'running') {
198
+ // Drain whatever's queued, then return idle: true since
199
+ // the process is done producing.
200
+ clearInterval(timer);
201
+ resolve({ data: captured, idle: true });
202
+ return;
203
+ }
204
+ };
205
+ // Poll cadence: 1/4 of idleMs, capped at 250ms. Polling instead
206
+ // of subscribing because we want to wake up at the deadline
207
+ // even if no output is arriving.
208
+ const intervalMs = Math.max(20, Math.min(250, Math.floor(opts.idleMs / 4)));
209
+ const timer = setInterval(tick, intervalMs);
210
+ timer.unref?.();
211
+ });
212
+ }
213
+ closeInput(workspaceId, processId) {
214
+ const proc = this.getOrThrow(workspaceId, processId);
215
+ if (proc.handle.status === 'running')
216
+ proc.adapter.closeInput();
217
+ }
218
+ signal(workspaceId, processId, sig) {
219
+ const proc = this.getOrThrow(workspaceId, processId);
220
+ if (proc.handle.status !== 'running')
221
+ return;
222
+ const mapped = `SIG${sig}`;
223
+ proc.adapter.kill(mapped);
224
+ }
225
+ async wait(workspaceId, processId, timeoutMs) {
226
+ const proc = this.getOrThrow(workspaceId, processId);
227
+ if (proc.exitInfo)
228
+ return proc.exitInfo;
229
+ if (timeoutMs === undefined)
230
+ return proc.exitPromise;
231
+ return Promise.race([
232
+ proc.exitPromise,
233
+ new Promise((_, reject) => {
234
+ const t = setTimeout(() => reject(new RunnerError(`wait timed out after ${timeoutMs}ms`, RUNNER_ERROR_CODES.TIMEOUT)), timeoutMs);
235
+ t.unref?.();
236
+ }),
237
+ ]);
238
+ }
239
+ /** Kill all processes for a workspace and forget them. Used on workspace release. */
240
+ async killWorkspace(workspaceId) {
241
+ let killed = 0;
242
+ for (const [id, proc] of this.processes) {
243
+ if (proc.handle.workspaceId !== workspaceId)
244
+ continue;
245
+ if (proc.handle.status === 'running') {
246
+ try {
247
+ proc.adapter.kill('SIGKILL');
248
+ }
249
+ catch { /* */ }
250
+ }
251
+ this.processes.delete(id);
252
+ killed++;
253
+ }
254
+ return killed;
255
+ }
256
+ }
257
+ // ── Default adapter (real subprocess via node-pty / child_process) ──
258
+ export function createDefaultAdapterFactory() {
259
+ let nodePtyMod = null;
260
+ return {
261
+ async spawnPty(opts) {
262
+ if (!nodePtyMod) {
263
+ // Native dep: load on first use so tests that never request
264
+ // a PTY don't pay the cost or hit the build-toolchain
265
+ // requirement.
266
+ nodePtyMod = await import('node-pty');
267
+ }
268
+ const pty = nodePtyMod.spawn(opts.binary, opts.args, {
269
+ name: 'xterm-color',
270
+ cwd: opts.cwd ?? process.cwd(),
271
+ env: { ...process.env, ...(opts.env ?? {}) },
272
+ cols: 120,
273
+ rows: 30,
274
+ });
275
+ const emitter = new EventEmitter();
276
+ Object.defineProperty(emitter, 'pid', { get: () => pty.pid });
277
+ emitter.write = (data) => pty.write(data);
278
+ emitter.resize = (cols, rows) => pty.resize(cols, rows);
279
+ emitter.kill = (signal) => pty.kill(signal);
280
+ emitter.closeInput = () => {
281
+ // Send EOT (^D); cleanest cross-platform "close stdin" for a PTY.
282
+ pty.write('\x04');
283
+ };
284
+ pty.onData((d) => emitter.emit('data', d));
285
+ pty.onExit(({ exitCode, signal }) => {
286
+ emitter.emit('exit', {
287
+ exitCode: exitCode ?? null,
288
+ signal: signal !== undefined && signal !== 0 ? String(signal) : null,
289
+ });
290
+ });
291
+ return emitter;
292
+ },
293
+ async spawnPipe(opts) {
294
+ const child = cpSpawn(opts.binary, opts.args, {
295
+ stdio: ['pipe', 'pipe', 'pipe'],
296
+ cwd: opts.cwd,
297
+ env: { ...process.env, ...(opts.env ?? {}) },
298
+ });
299
+ const emitter = new EventEmitter();
300
+ Object.defineProperty(emitter, 'pid', { get: () => child.pid });
301
+ emitter.write = (data) => { child.stdin?.write(data); };
302
+ emitter.kill = (signal) => { child.kill(signal); };
303
+ emitter.closeInput = () => { child.stdin?.end(); };
304
+ child.stdout?.on('data', d => emitter.emit('data', d.toString('utf8')));
305
+ child.stderr?.on('data', d => emitter.emit('data', d.toString('utf8')));
306
+ child.on('exit', (code, signal) => {
307
+ emitter.emit('exit', { exitCode: code, signal: signal ?? null });
308
+ });
309
+ child.on('error', () => {
310
+ emitter.emit('exit', { exitCode: 127, signal: null });
311
+ });
312
+ return emitter;
313
+ },
314
+ };
315
+ }
316
+ // ── Standalone shell.exec (no PTY, no buffer; one-shot) ─────────────
317
+ export async function shellExec(cmd, env, timeoutMs = 60_000) {
318
+ try {
319
+ const { stdout, stderr } = await execFileAsync('/bin/sh', ['-c', cmd], {
320
+ env: { ...process.env, ...(env ?? {}) },
321
+ timeout: timeoutMs,
322
+ maxBuffer: 10 * 1024 * 1024,
323
+ });
324
+ return { stdout, stderr, exitCode: 0 };
325
+ }
326
+ catch (err) {
327
+ return {
328
+ stdout: err.stdout?.toString?.() ?? '',
329
+ stderr: err.stderr?.toString?.() ?? '',
330
+ exitCode: err.code ?? null,
331
+ };
332
+ }
333
+ }
334
+ //# sourceMappingURL=process-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"process-manager.js","sourceRoot":"","sources":["../src/process-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Worker-protocol envelope, mirroring backend/src/modules/mcp/types/
3
+ * worker-protocol.types.ts. Duplicated rather than imported because
4
+ * the runner can't depend on the backend package; we keep the two
5
+ * files structurally identical and bump the version constant in
6
+ * lockstep when the shape changes.
7
+ */
8
+ export declare const WORKER_PROTOCOL_VERSION: 1;
9
+ export type WorkerEnvelopeType = 'request' | 'response' | 'event' | 'heartbeat' | 'error';
10
+ export interface WorkerEnvelope<T = unknown> {
11
+ v: typeof WORKER_PROTOCOL_VERSION;
12
+ type: WorkerEnvelopeType;
13
+ id: string;
14
+ seq?: number;
15
+ ts: number;
16
+ payload: T;
17
+ }
18
+ export interface WorkerErrorPayload {
19
+ code: number;
20
+ message: string;
21
+ data?: unknown;
22
+ }
23
+ export declare const WORKER_ERROR_CODES: {
24
+ readonly MALFORMED_ENVELOPE: -32700;
25
+ readonly UNKNOWN_SESSION: -32001;
26
+ readonly REPLAY_UNAVAILABLE: -32002;
27
+ readonly INTERNAL: -32603;
28
+ };
29
+ export declare function isWorkerEnvelope(value: unknown): value is WorkerEnvelope;
30
+ /**
31
+ * Request payload shape: a method name + arbitrary params, just like
32
+ * JSON-RPC. The backend dispatches by method to one of the runner's
33
+ * registered handlers (process.spawn, runner.info, etc.).
34
+ */
35
+ export interface RequestPayload {
36
+ method: string;
37
+ params: unknown;
38
+ /**
39
+ * Optional workspace scope. Most calls require it; runner.info()
40
+ * is the exception (returns global metadata, not workspace-scoped).
41
+ */
42
+ workspaceId?: string;
43
+ }
44
+ export interface ResponsePayload {
45
+ ok: boolean;
46
+ result?: unknown;
47
+ error?: WorkerErrorPayload;
48
+ }
49
+ export interface HeartbeatPayload {
50
+ ts: number;
51
+ /** Number of running processes the runner is currently hosting. */
52
+ inUse?: number;
53
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Worker-protocol envelope, mirroring backend/src/modules/mcp/types/
3
+ * worker-protocol.types.ts. Duplicated rather than imported because
4
+ * the runner can't depend on the backend package; we keep the two
5
+ * files structurally identical and bump the version constant in
6
+ * lockstep when the shape changes.
7
+ */
8
+ export const WORKER_PROTOCOL_VERSION = 1;
9
+ export const WORKER_ERROR_CODES = {
10
+ MALFORMED_ENVELOPE: -32700,
11
+ UNKNOWN_SESSION: -32001,
12
+ REPLAY_UNAVAILABLE: -32002,
13
+ INTERNAL: -32603,
14
+ };
15
+ export function isWorkerEnvelope(value) {
16
+ if (!value || typeof value !== 'object')
17
+ return false;
18
+ const e = value;
19
+ if (e.v !== WORKER_PROTOCOL_VERSION)
20
+ return false;
21
+ if (typeof e.id !== 'string' || e.id.length === 0)
22
+ return false;
23
+ if (typeof e.ts !== 'number' || !Number.isFinite(e.ts))
24
+ return false;
25
+ if (e.seq !== undefined && (typeof e.seq !== 'number' || !Number.isFinite(e.seq)))
26
+ return false;
27
+ switch (e.type) {
28
+ case 'request':
29
+ case 'response':
30
+ case 'event':
31
+ case 'heartbeat':
32
+ case 'error': break;
33
+ default: return false;
34
+ }
35
+ if (!('payload' in e))
36
+ return false;
37
+ return true;
38
+ }
39
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../src/protocol.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAU,CAAC;AAmBlD,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,kBAAkB,EAAE,CAAC,KAAK;IAC1B,eAAe,EAAE,CAAC,KAAK;IACvB,kBAAkB,EAAE,CAAC,KAAK;IAC1B,QAAQ,EAAE,CAAC,KAAK;CACR,CAAC;AAEX,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,IAAI,CAAC,CAAC,CAAC,KAAK,uBAAuB;QAAE,OAAO,KAAK,CAAC;IAClD,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAChE,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,OAAO,KAAK,CAAC;IACrE,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,OAAO,CAAC,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAChG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,SAAS,CAAC;QAAC,KAAK,UAAU,CAAC;QAAC,KAAK,OAAO,CAAC;QAAC,KAAK,WAAW,CAAC;QAAC,KAAK,OAAO,CAAC,CAAC,MAAM;QACrF,OAAO,CAAC,CAAC,OAAO,KAAK,CAAC;IACxB,CAAC;IACD,IAAI,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { ProbeExec } from './binaries.js';
2
+ import { RunnerRuntimeInfo } from './types.js';
3
+ /**
4
+ * Snapshot the runner's runtime characteristics.
5
+ *
6
+ * Every field here is detected, never settable from config. This is
7
+ * the read-only twin of the user's RunnerConfig: routing matches on
8
+ * either, but only the user can change RunnerConfig values, and
9
+ * only the runtime can produce these values.
10
+ *
11
+ * RUNNER_VERSION should track packages/runner/package.json. Bumping
12
+ * the package version without bumping this constant is a benign
13
+ * mismatch; the constant is what the backend records in the runner
14
+ * row's runtimeInfo.runnerVersion.
15
+ */
16
+ export declare const RUNNER_VERSION = "0.1.0";
17
+ export interface DetectInputs {
18
+ /** Override binary list. Defaults to the resolved config's list. */
19
+ binaries: string[];
20
+ /** Test injection point: stub child_process.spawn. */
21
+ exec?: ProbeExec;
22
+ }
23
+ export declare function detectRuntimeInfo(inputs: DetectInputs): Promise<RunnerRuntimeInfo>;
@@ -0,0 +1,35 @@
1
+ import { hostname, arch as osArch, platform as osPlatform, cpus, totalmem } from 'os';
2
+ import { probeAll, realExec } from './binaries.js';
3
+ import { detectCodingAgents } from './coding-agents/index.js';
4
+ /**
5
+ * Snapshot the runner's runtime characteristics.
6
+ *
7
+ * Every field here is detected, never settable from config. This is
8
+ * the read-only twin of the user's RunnerConfig: routing matches on
9
+ * either, but only the user can change RunnerConfig values, and
10
+ * only the runtime can produce these values.
11
+ *
12
+ * RUNNER_VERSION should track packages/runner/package.json. Bumping
13
+ * the package version without bumping this constant is a benign
14
+ * mismatch; the constant is what the backend records in the runner
15
+ * row's runtimeInfo.runnerVersion.
16
+ */
17
+ export const RUNNER_VERSION = '0.1.0';
18
+ export async function detectRuntimeInfo(inputs) {
19
+ const exec = inputs.exec ?? realExec;
20
+ const [binaries, codingAgents] = await Promise.all([
21
+ probeAll(inputs.binaries, exec),
22
+ detectCodingAgents(exec),
23
+ ]);
24
+ return {
25
+ os: osPlatform(),
26
+ arch: osArch(),
27
+ hostname: hostname(),
28
+ cpuCount: cpus().length,
29
+ memoryMb: Math.round(totalmem() / (1024 * 1024)),
30
+ runnerVersion: RUNNER_VERSION,
31
+ binaries,
32
+ codingAgents,
33
+ };
34
+ }
35
+ //# sourceMappingURL=runtime-info.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runtime-info.js","sourceRoot":"","sources":["../src/runtime-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,IAAI,MAAM,EAAE,QAAQ,IAAI,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAEtF,OAAO,EAAE,QAAQ,EAAa,QAAQ,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAG9D;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAStC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAoB;IAC1D,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,IAAI,QAAQ,CAAC;IACrC,MAAM,CAAC,QAAQ,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACjD,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC;QAC/B,kBAAkB,CAAC,IAAI,CAAC;KACzB,CAAC,CAAC;IACH,OAAO;QACL,EAAE,EAAE,UAAU,EAAE;QAChB,IAAI,EAAE,MAAM,EAAE;QACd,QAAQ,EAAE,QAAQ,EAAE;QACpB,QAAQ,EAAE,IAAI,EAAE,CAAC,MAAM;QACvB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC;QAChD,aAAa,EAAE,cAAc;QAC7B,QAAQ;QACR,YAAY;KACb,CAAC;AACJ,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { EventEmitter } from 'events';
2
+ import { WorkerEnvelope } from './protocol.js';
3
+ /**
4
+ * Client for the backend's Streamable HTTP endpoint at /mcp/streamable.
5
+ *
6
+ * Two responsibilities:
7
+ *
8
+ * 1. POST envelopes to the backend (client -> server). Used for
9
+ * heartbeats, responses to dispatched requests, and unsolicited
10
+ * events the runner wants to emit.
11
+ * 2. Maintain a long-lived GET stream (server -> client) that
12
+ * reconnects on disconnect, replaying via Last-Event-ID. Each
13
+ * received envelope is emitted as a typed `envelope` event the
14
+ * handler registry subscribes to.
15
+ *
16
+ * Reconnect policy:
17
+ * - Exponential backoff capped at 30s (1s, 2s, 4s, 8s, 16s, 30s, 30s).
18
+ * - We track the last event id we successfully parsed; on reconnect
19
+ * we send `Last-Event-ID` so the backend can replay anything we
20
+ * missed.
21
+ * - Reconnect attempts emit `reconnect` events for observability;
22
+ * persistent failure emits `fatal` and the daemon exits.
23
+ *
24
+ * Auth: Bearer JWT in the Authorization header. The token comes from
25
+ * @almyty/client's resolveCredentials and is passed in at construct
26
+ * time; rotation isn't a v1.0 concern (the daemon restarts on token
27
+ * rotation anyway because credentials.json was overwritten).
28
+ */
29
+ export interface StreamableClientOptions {
30
+ baseUrl: string;
31
+ token: string;
32
+ /** Test injection: replace the global fetch with a stub. */
33
+ fetch?: typeof globalThis.fetch;
34
+ /** Test injection: replace setTimeout with a controllable timer. */
35
+ setTimeoutFn?: typeof setTimeout;
36
+ }
37
+ export declare class StreamableClient extends EventEmitter {
38
+ private readonly opts;
39
+ private sessionId;
40
+ private lastEventId;
41
+ private streamAbort;
42
+ private stopped;
43
+ private reconnectAttempt;
44
+ private readonly fetchImpl;
45
+ private readonly setTimeoutFn;
46
+ constructor(opts: StreamableClientOptions);
47
+ /** Returns the session id once the first POST has assigned one. */
48
+ getSessionId(): string | null;
49
+ /** Send an envelope. Returns the parsed response envelope when the
50
+ * backend hands one back inline (for unary requests); otherwise null. */
51
+ send<T>(env: WorkerEnvelope<T>): Promise<WorkerEnvelope | null>;
52
+ /** Open the GET stream and dispatch envelopes via emit('envelope'). */
53
+ openStream(): Promise<void>;
54
+ stop(): void;
55
+ /**
56
+ * SSE parser. The MCP Streamable HTTP wire format follows the SSE
57
+ * spec: events are separated by blank lines, fields are `id:`,
58
+ * `event:`, `data:`. We accept arbitrary header order and ignore
59
+ * unknown fields.
60
+ *
61
+ * Buffers across chunk boundaries because TCP doesn't respect SSE
62
+ * frame boundaries; one fetch chunk often contains a half-event.
63
+ */
64
+ private consumeStream;
65
+ private handleFrame;
66
+ private scheduleReconnect;
67
+ }
68
+ /** Helper to mint an envelope on the runner side. */
69
+ export declare function envelope<T>(type: WorkerEnvelope['type'], payload: T, correlationId?: string): WorkerEnvelope<T>;