@bridge4dev/runner 0.59.1 → 0.61.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.
- package/dist/adapters/claude.js +197 -21
- package/dist/adapters/codex.js +22 -2
- package/dist/adapters/questions.js +1 -0
- package/dist/adapters/types.d.ts +42 -1
- package/dist/agent-binary.d.ts +45 -4
- package/dist/agent-binary.js +53 -4
- package/dist/attachments.d.ts +6 -0
- package/dist/attachments.js +162 -11
- package/dist/commit-message.js +8 -1
- package/dist/index.js +59 -2
- package/dist/journal.d.ts +40 -0
- package/dist/journal.js +82 -0
- package/dist/protocol.d.ts +52 -0
- package/dist/protocol.js +14 -0
- package/dist/self-update.d.ts +22 -0
- package/dist/self-update.js +22 -0
- package/dist/supervisor.d.ts +123 -2
- package/dist/supervisor.js +598 -91
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/self-update.d.ts
CHANGED
|
@@ -116,6 +116,28 @@ export declare function installIsWritable(packageDir?: string | null): boolean;
|
|
|
116
116
|
* that would work is recoverable, disappearing from the user's server is not.
|
|
117
117
|
*/
|
|
118
118
|
export declare function isSupervisedProcess(env?: NodeJS.ProcessEnv): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* The `hello` pair that decides whether the card draws a «Restart runner»
|
|
121
|
+
* button (#396, plan `workflow-stage-restart` R13).
|
|
122
|
+
*
|
|
123
|
+
* The same shape as `selfUpdate` / `selfUpdateBlocked`, and for the same
|
|
124
|
+
* reason: an older runner drops a command it cannot parse without answering, so
|
|
125
|
+
* the dashboard must gate on an announced capability rather than on a version.
|
|
126
|
+
*
|
|
127
|
+
* Only `isSupervisedProcess()`, and NOT `selfUpdatable()`: replacing the
|
|
128
|
+
* package needs an installed, writable npm package, restarting needs only
|
|
129
|
+
* something that will start us again. A daemon run from a source checkout under
|
|
130
|
+
* systemd — the dogfood box — restarts perfectly well and must get the button.
|
|
131
|
+
*
|
|
132
|
+
* Lives here rather than beside the other capabilities in `index.ts` because
|
|
133
|
+
* that file exports nothing and is the CLI entry point: a key spelled wrong
|
|
134
|
+
* there is caught by nobody, and `capabilities` is an untyped bag on both ends.
|
|
135
|
+
*/
|
|
136
|
+
export declare function restartCapability(env?: NodeJS.ProcessEnv): {
|
|
137
|
+
restart: true;
|
|
138
|
+
} | {
|
|
139
|
+
restartBlocked: 'unsupervised';
|
|
140
|
+
};
|
|
119
141
|
/**
|
|
120
142
|
* Same origin as the API we are paired with, and it really is a tarball.
|
|
121
143
|
*
|
package/dist/self-update.js
CHANGED
|
@@ -148,6 +148,28 @@ export function installIsWritable(packageDir = resolveInstalledPackageDir()) {
|
|
|
148
148
|
export function isSupervisedProcess(env = process.env) {
|
|
149
149
|
return typeof env['INVOCATION_ID'] === 'string' && env['INVOCATION_ID'].length > 0;
|
|
150
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* The `hello` pair that decides whether the card draws a «Restart runner»
|
|
153
|
+
* button (#396, plan `workflow-stage-restart` R13).
|
|
154
|
+
*
|
|
155
|
+
* The same shape as `selfUpdate` / `selfUpdateBlocked`, and for the same
|
|
156
|
+
* reason: an older runner drops a command it cannot parse without answering, so
|
|
157
|
+
* the dashboard must gate on an announced capability rather than on a version.
|
|
158
|
+
*
|
|
159
|
+
* Only `isSupervisedProcess()`, and NOT `selfUpdatable()`: replacing the
|
|
160
|
+
* package needs an installed, writable npm package, restarting needs only
|
|
161
|
+
* something that will start us again. A daemon run from a source checkout under
|
|
162
|
+
* systemd — the dogfood box — restarts perfectly well and must get the button.
|
|
163
|
+
*
|
|
164
|
+
* Lives here rather than beside the other capabilities in `index.ts` because
|
|
165
|
+
* that file exports nothing and is the CLI entry point: a key spelled wrong
|
|
166
|
+
* there is caught by nobody, and `capabilities` is an untyped bag on both ends.
|
|
167
|
+
*/
|
|
168
|
+
export function restartCapability(env = process.env) {
|
|
169
|
+
// The literal string matters: the dashboard renders the explanatory sentence
|
|
170
|
+
// for exactly this value and silently draws nothing for any other.
|
|
171
|
+
return isSupervisedProcess(env) ? { restart: true } : { restartBlocked: 'unsupervised' };
|
|
172
|
+
}
|
|
151
173
|
/**
|
|
152
174
|
* Same origin as the API we are paired with, and it really is a tarball.
|
|
153
175
|
*
|
package/dist/supervisor.d.ts
CHANGED
|
@@ -39,6 +39,20 @@ export interface SupervisorOptions {
|
|
|
39
39
|
* reports the new version only after the next manual restart.
|
|
40
40
|
*/
|
|
41
41
|
onRestartRequested?: (outcome: SelfUpdateOutcome) => void;
|
|
42
|
+
/**
|
|
43
|
+
* Called after a `runner_restart` the machine agreed to, once the reply is on
|
|
44
|
+
* the wire (#396). Separate from `onRestartRequested` rather than folded into
|
|
45
|
+
* it: that one is typed on `SelfUpdateOutcome` and its handler logs the
|
|
46
|
+
* version it is restarting INTO, which a plain restart has no answer for.
|
|
47
|
+
*/
|
|
48
|
+
onRestartCommanded?: (note: string | null) => void;
|
|
49
|
+
/**
|
|
50
|
+
* Build an adapter for an agent that was not on PATH when the daemon started
|
|
51
|
+
* (#395). Returning `null` means «still not here», and the session is refused
|
|
52
|
+
* in the same words as before. Only the entry point can supply this: it owns
|
|
53
|
+
* the config the adapters are built from.
|
|
54
|
+
*/
|
|
55
|
+
makeAdapter?: (agent: 'CLAUDE' | 'CODEX') => AgentAdapter | null;
|
|
42
56
|
/**
|
|
43
57
|
* Local ceiling on concurrent agent processes, from the runner's own config
|
|
44
58
|
* (layer 1). When set it wins over the API's number if it is stricter — the
|
|
@@ -216,6 +230,8 @@ export interface SupervisorOptions {
|
|
|
216
230
|
* `BACKGROUND_TASKS_HEARTBEAT_MS`. Real one is five minutes.
|
|
217
231
|
*/
|
|
218
232
|
backgroundTasksHeartbeatMs?: number;
|
|
233
|
+
/** #348: the compaction net, as a test seam over `COMPACTION_WATCHDOG_MS`. */
|
|
234
|
+
compactionWatchdogMs?: number;
|
|
219
235
|
}
|
|
220
236
|
/**
|
|
221
237
|
* How often a resting session says «I still hold N background tasks» — the
|
|
@@ -260,6 +276,8 @@ export declare class Supervisor {
|
|
|
260
276
|
private static readonly EMPTY_TURN_SETTLE_MS;
|
|
261
277
|
/** The window actually used — the constant, or a test's own shorter one. */
|
|
262
278
|
private readonly emptyTurnSettleMs;
|
|
279
|
+
/** The compaction net actually used — the constant, or a test's own. */
|
|
280
|
+
private readonly compactionWatchdogMs;
|
|
263
281
|
private readonly rateLimitsResendMs;
|
|
264
282
|
/** The stop-settle window actually used — the constant, or a test's own. */
|
|
265
283
|
private readonly stopSettleMs;
|
|
@@ -305,8 +323,31 @@ export declare class Supervisor {
|
|
|
305
323
|
* which of the two is running.
|
|
306
324
|
*/
|
|
307
325
|
private installInFlight;
|
|
326
|
+
/**
|
|
327
|
+
* A `runner_restart` has been agreed to and the exit is coming (#396).
|
|
328
|
+
*
|
|
329
|
+
* Never cleared: the process has ~1.5 s left, and everything it must refuse in
|
|
330
|
+
* that window it must refuse for good.
|
|
331
|
+
*/
|
|
332
|
+
private restarting;
|
|
308
333
|
/** A restore-point collection is running; a second reconnect must not start another (#388). */
|
|
309
334
|
private checkpointGcInFlight;
|
|
335
|
+
/**
|
|
336
|
+
* Sessions the current `hello_ack` names, while `reconcile` is walking them
|
|
337
|
+
* (#392).
|
|
338
|
+
*
|
|
339
|
+
* The unacked replay at the top of `reconcile` sends every journal's
|
|
340
|
+
* leftovers before a single session is registered, and the acks come back
|
|
341
|
+
* while the loop is still awaiting an earlier session's worktree. The ack
|
|
342
|
+
* handler deletes the journal of a session it does not know once nothing is
|
|
343
|
+
* unacked — which used to be exactly the journal the loop was about to
|
|
344
|
+
* restore from: its open cards, its queued messages, its anchor, gone a
|
|
345
|
+
* moment before they were read. Membership here is what «this session is
|
|
346
|
+
* known» means until the loop reaches it.
|
|
347
|
+
*/
|
|
348
|
+
private readonly reconciling;
|
|
349
|
+
/** How long a dashboard-requested compaction may go unreported before the session is handed back. */
|
|
350
|
+
private static readonly COMPACTION_WATCHDOG_MS;
|
|
310
351
|
/** Session 14: one project-recipe run per machine, and its verdict queue. */
|
|
311
352
|
private readonly verify;
|
|
312
353
|
private readonly verifyReports;
|
|
@@ -322,6 +363,21 @@ export declare class Supervisor {
|
|
|
322
363
|
* sent — the next `hello_ack` or the hourly tick carries the same fact, and
|
|
323
364
|
* the measurement behind it is cached, so retrying is nearly free.
|
|
324
365
|
*/
|
|
366
|
+
/**
|
|
367
|
+
* The adapter for this agent — built now if it was not there at boot (#395).
|
|
368
|
+
*
|
|
369
|
+
* `opts.adapters` is assembled once, when the daemon starts, from what was on
|
|
370
|
+
* PATH at that moment. That is the SAME frozen snapshot `capabilities.agents`
|
|
371
|
+
* was, one layer down: press «Install Codex» on a running machine and the
|
|
372
|
+
* measurement updates, the card lights up, the API lets the session through —
|
|
373
|
+
* and this map still has no CODEX in it, so the session is created and dies
|
|
374
|
+
* at once. Asking the factory closes the last of the three lists.
|
|
375
|
+
*
|
|
376
|
+
* Built at most once per process and remembered: preparing Codex's isolated
|
|
377
|
+
* home clones ~90 MB on a machine that has never run it, and that is a price
|
|
378
|
+
* to pay on the first session, not on every one.
|
|
379
|
+
*/
|
|
380
|
+
private adapterFor;
|
|
325
381
|
/**
|
|
326
382
|
* Why an install cannot start right now, in words for the person who pressed.
|
|
327
383
|
*
|
|
@@ -877,6 +933,26 @@ export declare class Supervisor {
|
|
|
877
933
|
* chance, and the alternative there is a card that stays clickable forever.
|
|
878
934
|
*/
|
|
879
935
|
private withdrawOpenQuestions;
|
|
936
|
+
/**
|
|
937
|
+
* Close out the asks a PREVIOUS process of this runner left open (#392).
|
|
938
|
+
*
|
|
939
|
+
* `withdrawOpenQuestions` above reads `running.openQuestions`, and that set
|
|
940
|
+
* is memory: a process that died without reaching `shutdown()` — killed,
|
|
941
|
+
* crashed, machine rebooted — took it along, and the restore used to create
|
|
942
|
+
* a fresh empty set and write only «Runner reconnected». The card in the
|
|
943
|
+
* browser is closed by one thing, a `question_resolved` with its askId in
|
|
944
|
+
* the feed, so it stayed answerable for ever, and everything typed into it
|
|
945
|
+
* was lost (the 07.09.2026 session in the ticket: six restarts, zero
|
|
946
|
+
* tombstones).
|
|
947
|
+
*
|
|
948
|
+
* The journal is the set that survived: `SessionJournal.append` notes every
|
|
949
|
+
* card this runner published and every resolution it published, whoever
|
|
950
|
+
* wrote it. That is also the «already closed» check the plan asks to name:
|
|
951
|
+
* a graceful `shutdown()` sends its `question_resolved` through the same
|
|
952
|
+
* `append`, so by the time a restore runs, a card closed that way is no
|
|
953
|
+
* longer in the set — one tombstone per card, never two.
|
|
954
|
+
*/
|
|
955
|
+
private withdrawJournaledQuestions;
|
|
880
956
|
/**
|
|
881
957
|
* Deliver messages that were held because every slot was taken.
|
|
882
958
|
*
|
|
@@ -983,6 +1059,23 @@ export declare class Supervisor {
|
|
|
983
1059
|
* phantom can never fire after the turn it belonged to has closed properly.
|
|
984
1060
|
*/
|
|
985
1061
|
private clearEmptyTurn;
|
|
1062
|
+
/**
|
|
1063
|
+
* A compaction is over for a reason other than the agent saying so (#348):
|
|
1064
|
+
* the turn it rode on ended, the process died, a new process was launched.
|
|
1065
|
+
* The feed gets its closing line so the pair is complete, and the runner's
|
|
1066
|
+
* own state is dropped so the NEXT compaction opens a new pair — left set,
|
|
1067
|
+
* every later start would be read as a repeat and written nowhere (QA S4).
|
|
1068
|
+
*/
|
|
1069
|
+
private endCompaction;
|
|
1070
|
+
/** A compaction has begun: say so in the feed, once, and remember who started it (#348). */
|
|
1071
|
+
private openCompaction;
|
|
1072
|
+
/**
|
|
1073
|
+
* The net under a dashboard-requested compaction (#348) — see
|
|
1074
|
+
* `RunningSession.compactionWatchdog`. Fires only into a session that has
|
|
1075
|
+
* said nothing since: every agent event and every ending clears it.
|
|
1076
|
+
*/
|
|
1077
|
+
private armCompactionWatchdog;
|
|
1078
|
+
private clearCompactionWatchdog;
|
|
986
1079
|
/**
|
|
987
1080
|
* Record how many subagents are alive, and say so when it matters (#236).
|
|
988
1081
|
*
|
|
@@ -1024,8 +1117,9 @@ export declare class Supervisor {
|
|
|
1024
1117
|
* It happens for real: a background subagent's report wakes a new turn inside
|
|
1025
1118
|
* the agent process (SDK 0.3.226 emits a second `system:init` and a `result`
|
|
1026
1119
|
* carrying `origin: {kind:'task-notification'}`), and nothing here reports a
|
|
1027
|
-
* turn the runner did not start.
|
|
1028
|
-
*
|
|
1120
|
+
* turn the runner did not start. So does a question this runner withdraws by
|
|
1121
|
+
* itself. (A compaction used to be the third case; `compact_context` reports
|
|
1122
|
+
* RUNNING itself now, and #348 gave the compaction lines of its own.)
|
|
1029
1123
|
*
|
|
1030
1124
|
* An open question is the one thing that must survive: there, WAITING_INPUT
|
|
1031
1125
|
* means a tool call is parked on a person, and the agent narrating around its
|
|
@@ -1376,7 +1470,34 @@ export declare class Supervisor {
|
|
|
1376
1470
|
* anything down. The name says what it does.
|
|
1377
1471
|
*/
|
|
1378
1472
|
private finishSession;
|
|
1473
|
+
/**
|
|
1474
|
+
* The terminal status a reconnect should replay for this session instead
|
|
1475
|
+
* of restoring it, or null (QA-96 F1).
|
|
1476
|
+
*
|
|
1477
|
+
* Only a terminal status from THIS life of the session. A resumed session
|
|
1478
|
+
* carries a higher epoch, and replaying the FAILED it was resumed from would
|
|
1479
|
+
* kill it again the moment the runner reconnects. A journal written by a
|
|
1480
|
+
* runner from before session 13 could hold a `DONE` — it is no longer a
|
|
1481
|
+
* status this runner may report, and replaying one would close the session
|
|
1482
|
+
* for the user. Drop it and let the session be picked back up like any
|
|
1483
|
+
* other. Pure: reads the journal and decides, so the pre-registration pass
|
|
1484
|
+
* and the loop answer the question the same way.
|
|
1485
|
+
*/
|
|
1486
|
+
private terminalStatusToReplay;
|
|
1487
|
+
/**
|
|
1488
|
+
* Build and register the entry for a session a runner restart interrupted,
|
|
1489
|
+
* and close the cards its dead process left open (#392).
|
|
1490
|
+
*
|
|
1491
|
+
* Synchronous on purpose, and called for EVERY such session before the
|
|
1492
|
+
* reconnect awaits anything: registered, the session is known (a message
|
|
1493
|
+
* for it waits in its queue behind the `starting` gate of #401 instead of
|
|
1494
|
+
* coming back as `session_unknown`), and its cards go dark first thing —
|
|
1495
|
+
* above the line about the restart, so a person reading down sees the card
|
|
1496
|
+
* close before they read why.
|
|
1497
|
+
*/
|
|
1498
|
+
private registerRestoredSession;
|
|
1379
1499
|
private reconcile;
|
|
1500
|
+
private reconcileKnown;
|
|
1380
1501
|
/**
|
|
1381
1502
|
* Housekeeping for the journal directory. Safe to call any time: live
|
|
1382
1503
|
* sessions are skipped and a journal still holding unacked events survives
|