@sentropic/h2a-runtime 0.88.0 → 0.90.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/attach.d.ts +21 -0
- package/dist/attach.d.ts.map +1 -1
- package/dist/attach.js +69 -1
- package/dist/attach.js.map +1 -1
- package/dist/file-lock.d.ts +34 -0
- package/dist/file-lock.d.ts.map +1 -0
- package/dist/file-lock.js +96 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/index.d.ts +30 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +492 -50
- package/dist/index.js.map +1 -1
- package/dist/llm-gateway-runtime/accounts.d.ts.map +1 -1
- package/dist/llm-gateway-runtime/accounts.js +3 -0
- package/dist/llm-gateway-runtime/accounts.js.map +1 -1
- package/dist/llm-gateway-runtime/proxy-anthropic.d.ts.map +1 -1
- package/dist/llm-gateway-runtime/proxy-anthropic.js +24 -0
- package/dist/llm-gateway-runtime/proxy-anthropic.js.map +1 -1
- package/dist/llm-gateway-runtime/proxy-openai.d.ts.map +1 -1
- package/dist/llm-gateway-runtime/proxy-openai.js +53 -2
- package/dist/llm-gateway-runtime/proxy-openai.js.map +1 -1
- package/dist/proc-cpu.d.ts +55 -0
- package/dist/proc-cpu.d.ts.map +1 -0
- package/dist/proc-cpu.js +133 -0
- package/dist/proc-cpu.js.map +1 -0
- package/dist/prompt-delivery.d.ts +159 -0
- package/dist/prompt-delivery.d.ts.map +1 -0
- package/dist/prompt-delivery.js +469 -0
- package/dist/prompt-delivery.js.map +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +7 -69
- package/dist/registry.js.map +1 -1
- package/dist/relaunch.d.ts +20 -1
- package/dist/relaunch.d.ts.map +1 -1
- package/dist/relaunch.js +31 -10
- package/dist/relaunch.js.map +1 -1
- package/dist/restore.d.ts +20 -4
- package/dist/restore.d.ts.map +1 -1
- package/dist/restore.js +26 -4
- package/dist/restore.js.map +1 -1
- package/dist/session-lease.d.ts +266 -0
- package/dist/session-lease.d.ts.map +1 -0
- package/dist/session-lease.js +342 -0
- package/dist/session-lease.js.map +1 -0
- package/dist/tmux.d.ts +77 -2
- package/dist/tmux.d.ts.map +1 -1
- package/dist/tmux.js +269 -23
- package/dist/tmux.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,469 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Initial-prompt delivery for managed INTERACTIVE sessions.
|
|
3
|
+
*
|
|
4
|
+
* Measured on the real hosts (codex-cli 0.145.0, Claude Code 2.1.220) on
|
|
5
|
+
* 2026-07-29, through the real `h2a run` path:
|
|
6
|
+
*
|
|
7
|
+
* - `tmux new-session -d` returns as soon as the PANE exists. 15ms later the
|
|
8
|
+
* pane is still EMPTY: the CLI has drawn nothing. A prompt pasted then is
|
|
9
|
+
* ECHOED BY THE RAW TERMINAL — it is visibly "in the pane" while no composer
|
|
10
|
+
* exists to hold it — and the TUI discards it when it takes over the screen.
|
|
11
|
+
* Both profiles lost their brief that way and sat on their placeholder with
|
|
12
|
+
* ~0s of CPU while `run` reported state:"started".
|
|
13
|
+
* - `paste-buffer` WITHOUT `-p` submits a multi-line brief line by line: line 1
|
|
14
|
+
* became its own request while line 2 stayed in the composer. With `-p` the
|
|
15
|
+
* whole block lands as one entry that a single Enter submits.
|
|
16
|
+
* - An Enter fired while the host was still rendering was swallowed, leaving
|
|
17
|
+
* the brief composed but unsent — and the startup CPU burn (+1950ms) looked
|
|
18
|
+
* exactly like work.
|
|
19
|
+
* - Host modals swallow the brief the same silent way. THREE showed up in one
|
|
20
|
+
* afternoon: directory trust, "Update available!", "Hooks need review".
|
|
21
|
+
*
|
|
22
|
+
* Hence the shape of this module: type ONCE, into a host that has drawn its UI
|
|
23
|
+
* and gone quiet, then prove the text is there, then submit, then judge work
|
|
24
|
+
* against the host's own idle rate. Nothing here reports success because a tmux
|
|
25
|
+
* command exited 0 — that is what let a launch claim `started` while the agent
|
|
26
|
+
* was inert for 33 minutes.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* A numbered choice list waiting on a key press. GENERIC on purpose: three
|
|
30
|
+
* different codex modals were measured in one afternoon, so enumerating known
|
|
31
|
+
* wordings would only ever list the ones that already bit us. What they share is
|
|
32
|
+
* the shape — `› 1.` choices plus an explicit "press enter to …".
|
|
33
|
+
*/
|
|
34
|
+
const MODAL_CHOICE = /(^|\n)\s*[›>]?\s*1\.\s+\S/;
|
|
35
|
+
const MODAL_CONFIRM = /press (?:enter|return) to (?:continue|confirm|select)/i;
|
|
36
|
+
const NAMED_MODALS = [
|
|
37
|
+
{
|
|
38
|
+
// Recorded per repository root, so a workspace outside an approved repo
|
|
39
|
+
// blocks here — and nobody will ever answer it in a background lane.
|
|
40
|
+
match: /do you trust the contents of this directory/i,
|
|
41
|
+
modal: {
|
|
42
|
+
reason: "the host is waiting on its directory-trust prompt",
|
|
43
|
+
hint: "approve this directory once in an interactive session (the host records trust per repository root), then relaunch",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
match: /update available/i,
|
|
48
|
+
modal: {
|
|
49
|
+
reason: "the host is waiting on its update prompt",
|
|
50
|
+
hint: "answer the host update prompt once in an interactive session (or update the CLI), then relaunch",
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
match: /hooks (?:need review|are new or changed)|hook is new or changed/i,
|
|
55
|
+
modal: {
|
|
56
|
+
reason: "the host is waiting on its hook-review prompt",
|
|
57
|
+
hint: "review/trust the changed hooks once in an interactive session in this workspace, then relaunch",
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
];
|
|
61
|
+
/**
|
|
62
|
+
* Is the pane sitting on a host modal that consumes the brief? Returns the
|
|
63
|
+
* exact reason so the launch can FAIL LOUDLY instead of waiting forever.
|
|
64
|
+
*/
|
|
65
|
+
export function detectHostModal(capture) {
|
|
66
|
+
// A modal is a choice list AWAITING a key press. Requiring both halves keeps
|
|
67
|
+
// passive banners (an "Update available!" notice above a live composer) from
|
|
68
|
+
// failing a perfectly healthy launch.
|
|
69
|
+
if (!MODAL_CHOICE.test(capture) || !MODAL_CONFIRM.test(capture)) {
|
|
70
|
+
return undefined;
|
|
71
|
+
}
|
|
72
|
+
for (const entry of NAMED_MODALS) {
|
|
73
|
+
if (entry.match.test(capture))
|
|
74
|
+
return entry.modal;
|
|
75
|
+
}
|
|
76
|
+
return {
|
|
77
|
+
reason: "the host is waiting on a modal choice prompt",
|
|
78
|
+
hint: "attach to the session, answer the host prompt once, then relaunch the lane",
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** Collapse every whitespace run so a soft-wrapped composer still matches. */
|
|
82
|
+
export function normalizePaneText(text) {
|
|
83
|
+
return text.replace(/\s+/g, " ");
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Fingerprints used to PROVE the pasted text reached the composer — one from
|
|
87
|
+
* each end.
|
|
88
|
+
*
|
|
89
|
+
* A composer that overflows shows only part of the brief, and which part it
|
|
90
|
+
* keeps is a host rendering choice (measured: Claude Code keeps the HEAD and
|
|
91
|
+
* cuts the tail). Looking for either end means the proof does not depend on
|
|
92
|
+
* that choice.
|
|
93
|
+
*/
|
|
94
|
+
export function promptProbes(prompt) {
|
|
95
|
+
const tokens = prompt.trim().split(/\s+/).filter((t) => t.length > 0);
|
|
96
|
+
const pick = (ordered) => {
|
|
97
|
+
for (const token of ordered) {
|
|
98
|
+
if (token.length >= 4) {
|
|
99
|
+
return token.length > 20 ? token.slice(0, 20) : token;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return undefined;
|
|
103
|
+
};
|
|
104
|
+
const probes = [pick(tokens), pick([...tokens].reverse())].filter((p) => p !== undefined);
|
|
105
|
+
if (probes.length > 0)
|
|
106
|
+
return [...new Set(probes)];
|
|
107
|
+
return [prompt.replace(/\s+/g, "").slice(-8)];
|
|
108
|
+
}
|
|
109
|
+
export function detectCollapsedPaste(capture) {
|
|
110
|
+
const chars = /\[pasted\s+content\s+(\d+)\s+chars?\]/i.exec(capture);
|
|
111
|
+
if (chars)
|
|
112
|
+
return { kind: "chars", value: Number.parseInt(chars[1], 10) };
|
|
113
|
+
const lines = /\[pasted\s+text[^\]]*?\+(\d+)\s+lines?\]/i.exec(capture);
|
|
114
|
+
if (lines)
|
|
115
|
+
return { kind: "lines", value: Number.parseInt(lines[1], 10) };
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Does a collapsed-paste marker account for the brief we sent? Compared with a
|
|
120
|
+
* tolerance: hosts differ on counting UTF-8 bytes vs code points, and the line
|
|
121
|
+
* count is reported as "additional" lines.
|
|
122
|
+
*/
|
|
123
|
+
export function collapsedPasteMatches(marker, prompt) {
|
|
124
|
+
if (marker.kind === "chars") {
|
|
125
|
+
const codePoints = [...prompt].length;
|
|
126
|
+
const bytes = Buffer.byteLength(prompt, "utf8");
|
|
127
|
+
// ABSOLUTE, and small. A proportional tolerance was a hole: 2% of a 10000
|
|
128
|
+
// character brief accepted a 200-character truncation — and the missing 200
|
|
129
|
+
// characters are the END of the brief, which is where its instructions sit.
|
|
130
|
+
// Both counting conventions are compared exactly; the slack only absorbs a
|
|
131
|
+
// host counting a trailing newline differently.
|
|
132
|
+
const tolerance = 8;
|
|
133
|
+
return (Math.abs(marker.value - codePoints) <= tolerance ||
|
|
134
|
+
Math.abs(marker.value - bytes) <= tolerance);
|
|
135
|
+
}
|
|
136
|
+
const lineCount = prompt.split("\n").length;
|
|
137
|
+
// "+N lines" counts the lines beyond the first.
|
|
138
|
+
return Math.abs(marker.value - (lineCount - 1)) <= 1;
|
|
139
|
+
}
|
|
140
|
+
/** How many times does the fingerprint appear in a pane capture? */
|
|
141
|
+
export function countOccurrences(capture, probe) {
|
|
142
|
+
if (probe.length === 0)
|
|
143
|
+
return 0;
|
|
144
|
+
const haystack = normalizePaneText(capture);
|
|
145
|
+
const needle = normalizePaneText(probe);
|
|
146
|
+
let count = 0;
|
|
147
|
+
let from = 0;
|
|
148
|
+
for (;;) {
|
|
149
|
+
const at = haystack.indexOf(needle, from);
|
|
150
|
+
if (at === -1)
|
|
151
|
+
return count;
|
|
152
|
+
count += 1;
|
|
153
|
+
from = at + needle.length;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Has the host actually DRAWN its interface?
|
|
158
|
+
*
|
|
159
|
+
* 15ms after `new-session` the pane is still empty, and a paste there is merely
|
|
160
|
+
* echoed by the raw terminal. Requiring real drawn content is what separates
|
|
161
|
+
* "the composer holds my brief" from "the terminal echoed my keystrokes".
|
|
162
|
+
*/
|
|
163
|
+
export function paneHasDrawnUi(capture, minLines = 3) {
|
|
164
|
+
return (capture.split("\n").filter((line) => line.trim().length > 0).length >=
|
|
165
|
+
minLines);
|
|
166
|
+
}
|
|
167
|
+
const DEFAULTS = {
|
|
168
|
+
timeoutMs: 90_000,
|
|
169
|
+
pollMs: 750,
|
|
170
|
+
activityMs: 30_000,
|
|
171
|
+
// A booting TUI burns ~2s of CPU rendering its splash; an idle one burns ~0
|
|
172
|
+
// (measured: 0s over 28s on a lane parked on its placeholder).
|
|
173
|
+
activityCpuMs: 300,
|
|
174
|
+
quietMs: 2_000,
|
|
175
|
+
quietCpuMs: 40,
|
|
176
|
+
maxIdleRate: 0.3,
|
|
177
|
+
landedMs: 8_000,
|
|
178
|
+
};
|
|
179
|
+
/**
|
|
180
|
+
* Highest idle rate allowed to EXCUSE missing work (ms of CPU per ms of clock).
|
|
181
|
+
*
|
|
182
|
+
* Readiness may admit a host burning up to `maxIdleRate` steadily, because a
|
|
183
|
+
* level burn still means it is drawn and accepting input. But that same rate
|
|
184
|
+
* must not then be used to explain away silence: a host genuinely waiting for
|
|
185
|
+
* input burns a few percent of a core (measured ~0 to 2.5%), so anything higher
|
|
186
|
+
* is startup, and startup may never stand in for an answer.
|
|
187
|
+
*/
|
|
188
|
+
const IDLE_RATE_CAP = 0.05;
|
|
189
|
+
/**
|
|
190
|
+
* Sleep without spinning. `Atomics.wait` on a private SharedArrayBuffer is the
|
|
191
|
+
* repo's synchronous-wait primitive (same as the local-files lock), so delivery
|
|
192
|
+
* stays synchronous instead of rippling async through the launch path.
|
|
193
|
+
*/
|
|
194
|
+
export function sleepSync(ms) {
|
|
195
|
+
const end = Date.now() + ms;
|
|
196
|
+
const view = new Int32Array(new SharedArrayBuffer(4));
|
|
197
|
+
for (;;) {
|
|
198
|
+
const remaining = end - Date.now();
|
|
199
|
+
if (remaining <= 0)
|
|
200
|
+
return;
|
|
201
|
+
Atomics.wait(view, 0, 0, Math.min(remaining, 25));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
/** Last non-empty lines of a capture, for an actionable failure message. */
|
|
205
|
+
export function captureTail(capture, lines = 6) {
|
|
206
|
+
return capture
|
|
207
|
+
.split("\n")
|
|
208
|
+
.map((line) => line.trimEnd())
|
|
209
|
+
.filter((line) => line.length > 0)
|
|
210
|
+
.slice(-lines)
|
|
211
|
+
.join("\n");
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Wait until the host has drawn its UI AND stopped burning CPU — booted, and
|
|
215
|
+
* genuinely waiting for input. Returns the idle CPU RATE (ms of CPU per ms of
|
|
216
|
+
* wall clock) measured on the quiet window, which calibrates what counts as
|
|
217
|
+
* real work later.
|
|
218
|
+
*/
|
|
219
|
+
function waitUntilReady(pane, deps, options) {
|
|
220
|
+
const deadline = deps.now() + options.timeoutMs;
|
|
221
|
+
let unreadable = 0;
|
|
222
|
+
let previousRate;
|
|
223
|
+
for (;;) {
|
|
224
|
+
const capture = deps.capturePane(pane);
|
|
225
|
+
if (capture === undefined) {
|
|
226
|
+
unreadable += 1;
|
|
227
|
+
if (unreadable >= 3)
|
|
228
|
+
return { ok: false, unreadable: true };
|
|
229
|
+
}
|
|
230
|
+
else if (paneHasDrawnUi(capture)) {
|
|
231
|
+
unreadable = 0;
|
|
232
|
+
const before = deps.cpuMs(pane);
|
|
233
|
+
const startedAt = deps.now();
|
|
234
|
+
deps.sleep(options.quietMs);
|
|
235
|
+
const after = deps.cpuMs(pane);
|
|
236
|
+
const elapsed = Math.max(1, deps.now() - startedAt);
|
|
237
|
+
if (before !== undefined && after !== undefined) {
|
|
238
|
+
const delta = after - before;
|
|
239
|
+
if (delta < 0) {
|
|
240
|
+
// The tree total FELL, so a process left it: only live descendants are
|
|
241
|
+
// counted, and the total is therefore not a monotonic counter. A
|
|
242
|
+
// negative delta says the tree was recomposed, not that it went quiet —
|
|
243
|
+
// reading it as quiet clamped the idle rate to zero and let leftover
|
|
244
|
+
// startup CPU pass for work.
|
|
245
|
+
previousRate = undefined;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
const rate = delta / elapsed;
|
|
249
|
+
// Clearly quiet: the common case, and the fastest path.
|
|
250
|
+
if (delta <= options.quietCpuMs)
|
|
251
|
+
return { ok: true, idleRate: rate };
|
|
252
|
+
// Or STABLE AND LOW: a host idling at a steady few percent of a core
|
|
253
|
+
// never meets an absolute threshold, and refusing it was a
|
|
254
|
+
// deterministic false negative. But "stable" alone is not enough — a
|
|
255
|
+
// host steadily burning most of a core is BUSY, not waiting for input,
|
|
256
|
+
// and typing into it is how an Enter gets swallowed. Measured spread:
|
|
257
|
+
// a booting TUI runs near a full core, an idle one near zero.
|
|
258
|
+
// 10%, not 25%: a quarter is wide enough for a host whose burn is
|
|
259
|
+
// still DRIFTING downward out of startup to read as level, and typing
|
|
260
|
+
// into it is how an Enter gets swallowed.
|
|
261
|
+
if (rate <= options.maxIdleRate &&
|
|
262
|
+
previousRate !== undefined &&
|
|
263
|
+
Math.abs(rate - previousRate) <=
|
|
264
|
+
0.1 * Math.max(rate, previousRate, Number.EPSILON)) {
|
|
265
|
+
// Keep the HIGHER of the two: an over-estimated idle rate risks a
|
|
266
|
+
// refusal, an under-estimated one manufactures a false "working".
|
|
267
|
+
return { ok: true, idleRate: Math.max(rate, previousRate) };
|
|
268
|
+
}
|
|
269
|
+
previousRate = rate;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
previousRate = undefined; // unknown stays unknown
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
if (deps.now() >= deadline)
|
|
277
|
+
return { ok: false, unreadable: false };
|
|
278
|
+
deps.sleep(options.pollMs);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Deliver `prompt` to a live agent pane and REPORT WHAT WAS OBSERVED.
|
|
283
|
+
*
|
|
284
|
+
* Types the brief EXACTLY ONCE. Retrying a paste is what stacked twelve copies
|
|
285
|
+
* of a brief into one composer when a wipe silently failed, so a brief that
|
|
286
|
+
* cannot be proven present is a failure to report, never a paste to repeat.
|
|
287
|
+
*/
|
|
288
|
+
export function deliverInitialPrompt(pane, prompt, deps, options = {}) {
|
|
289
|
+
const timeoutMs = options.timeoutMs ?? DEFAULTS.timeoutMs;
|
|
290
|
+
const pollMs = options.pollMs ?? DEFAULTS.pollMs;
|
|
291
|
+
const activityMs = options.activityMs ?? DEFAULTS.activityMs;
|
|
292
|
+
const activityCpuMs = options.activityCpuMs ?? DEFAULTS.activityCpuMs;
|
|
293
|
+
const quietMs = options.quietMs ?? DEFAULTS.quietMs;
|
|
294
|
+
const quietCpuMs = options.quietCpuMs ?? DEFAULTS.quietCpuMs;
|
|
295
|
+
const maxIdleRate = options.maxIdleRate ?? DEFAULTS.maxIdleRate;
|
|
296
|
+
const landedMs = options.landedMs ?? DEFAULTS.landedMs;
|
|
297
|
+
const probes = promptProbes(prompt);
|
|
298
|
+
const startedAt = deps.now();
|
|
299
|
+
// 1. Only ever type into a host that has drawn its UI and gone quiet.
|
|
300
|
+
const ready = waitUntilReady(pane, deps, {
|
|
301
|
+
quietMs,
|
|
302
|
+
quietCpuMs,
|
|
303
|
+
maxIdleRate,
|
|
304
|
+
timeoutMs,
|
|
305
|
+
pollMs,
|
|
306
|
+
});
|
|
307
|
+
if (!ready.ok) {
|
|
308
|
+
return {
|
|
309
|
+
state: "undelivered",
|
|
310
|
+
reason: ready.unreadable
|
|
311
|
+
? "the agent pane could not be read (tmux capture-pane failed)"
|
|
312
|
+
: "the host never finished starting up (no drawn interface at rest), so the prompt was never typed",
|
|
313
|
+
waitedMs: deps.now() - startedAt,
|
|
314
|
+
capture: captureTail(deps.capturePane(pane) ?? ""),
|
|
315
|
+
};
|
|
316
|
+
}
|
|
317
|
+
// 2. A modal will never be answered by a background lane.
|
|
318
|
+
const before = deps.capturePane(pane) ?? "";
|
|
319
|
+
const modal = detectHostModal(before);
|
|
320
|
+
if (modal) {
|
|
321
|
+
return {
|
|
322
|
+
state: "host-modal",
|
|
323
|
+
reason: modal.reason,
|
|
324
|
+
hint: modal.hint,
|
|
325
|
+
capture: captureTail(before),
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
// 3. Type once, as one bracketed block.
|
|
329
|
+
const baseline = probes.map((probe) => countOccurrences(before, probe));
|
|
330
|
+
// A marker ALREADY on screen belongs to an earlier paste. Left unrecorded it
|
|
331
|
+
// cuts both ways: one whose size happens to match would prove a delivery that
|
|
332
|
+
// never happened, and one that does not match would condemn a perfectly good
|
|
333
|
+
// paste. Only a marker that is NEW, or one that changed, is evidence.
|
|
334
|
+
const markerBefore = detectCollapsedPaste(before);
|
|
335
|
+
deps.clearComposer(pane);
|
|
336
|
+
if (!deps.pasteBlock(pane, prompt)) {
|
|
337
|
+
return {
|
|
338
|
+
state: "undelivered",
|
|
339
|
+
reason: "tmux refused to paste the prompt into the agent pane",
|
|
340
|
+
waitedMs: deps.now() - startedAt,
|
|
341
|
+
capture: captureTail(before),
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
// 4. Prove it landed. The composer needs a moment to RENDER what it received:
|
|
345
|
+
// reading the pane back instantly declared a perfectly good paste lost on
|
|
346
|
+
// Claude Code. So poll — never paste again, only look again.
|
|
347
|
+
let after = "";
|
|
348
|
+
let landed = false;
|
|
349
|
+
let collapsed;
|
|
350
|
+
const landedDeadline = deps.now() + landedMs;
|
|
351
|
+
for (;;) {
|
|
352
|
+
after = deps.capturePane(pane) ?? after;
|
|
353
|
+
// A modal raised by the paste hides the composer: name that case rather
|
|
354
|
+
// than blaming a lost paste.
|
|
355
|
+
const pasteModal = detectHostModal(after);
|
|
356
|
+
if (pasteModal) {
|
|
357
|
+
return {
|
|
358
|
+
state: "host-modal",
|
|
359
|
+
reason: pasteModal.reason,
|
|
360
|
+
hint: pasteModal.hint,
|
|
361
|
+
capture: captureTail(after),
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
// A collapsed-paste marker takes PRECEDENCE over a fingerprint search: it is
|
|
365
|
+
// quantitative (it states the size the host received) and it is the only
|
|
366
|
+
// evidence a long brief ever produces. It also has to be able to REFUSE — a
|
|
367
|
+
// marker accounting for less than what was sent means the host holds a
|
|
368
|
+
// truncated brief, and an amputated brief produces plausible wrong work.
|
|
369
|
+
// Fingerprints are a fallback, and only when no marker is on screen: a short
|
|
370
|
+
// probe can otherwise match a word inside the marker itself.
|
|
371
|
+
const marker = detectCollapsedPaste(after);
|
|
372
|
+
const markerIsStale = marker !== undefined &&
|
|
373
|
+
markerBefore !== undefined &&
|
|
374
|
+
marker.kind === markerBefore.kind &&
|
|
375
|
+
marker.value === markerBefore.value;
|
|
376
|
+
if (marker && !markerIsStale) {
|
|
377
|
+
if (collapsedPasteMatches(marker, prompt)) {
|
|
378
|
+
landed = true;
|
|
379
|
+
collapsed = marker;
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
else if (marker === undefined) {
|
|
383
|
+
landed = probes.some((probe, index) => countOccurrences(after, probe) > baseline[index]);
|
|
384
|
+
}
|
|
385
|
+
if (landed || deps.now() >= landedDeadline)
|
|
386
|
+
break;
|
|
387
|
+
deps.sleep(pollMs);
|
|
388
|
+
}
|
|
389
|
+
if (!landed) {
|
|
390
|
+
deps.clearComposer(pane); // leave nothing half-typed behind
|
|
391
|
+
return {
|
|
392
|
+
state: "undelivered",
|
|
393
|
+
reason: "the brief never appeared in the composer, so it was not submitted (nothing was retyped: a second paste would stack a duplicate)",
|
|
394
|
+
waitedMs: deps.now() - startedAt,
|
|
395
|
+
capture: captureTail(after),
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
// 5. One Enter submits the whole block.
|
|
399
|
+
// The pre-submit CPU baseline must be REAL. Coercing an unreadable sample to
|
|
400
|
+
// zero turned the process's whole lifetime CPU into a post-submit delta, which
|
|
401
|
+
// reported "working" over a brief that was still sitting unsent.
|
|
402
|
+
const cpuBefore = deps.cpuMs(pane);
|
|
403
|
+
if (cpuBefore === undefined) {
|
|
404
|
+
return {
|
|
405
|
+
state: "undelivered",
|
|
406
|
+
reason: "the agent's CPU could not be read before submitting, so no work could be proven afterwards",
|
|
407
|
+
waitedMs: deps.now() - startedAt,
|
|
408
|
+
capture: captureTail(after),
|
|
409
|
+
};
|
|
410
|
+
}
|
|
411
|
+
const submittedAt = deps.now();
|
|
412
|
+
if (!deps.submit(pane)) {
|
|
413
|
+
return {
|
|
414
|
+
state: "undelivered",
|
|
415
|
+
reason: "the prompt reached the composer but tmux could not submit it",
|
|
416
|
+
waitedMs: deps.now() - startedAt,
|
|
417
|
+
capture: captureTail(after),
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
// 6. Judge work against THE HOST'S OWN idle rate, never a flat number: an
|
|
421
|
+
// idling codex still burned 420ms over 30s, which a fixed threshold read as
|
|
422
|
+
// "working" while nothing had been submitted at all.
|
|
423
|
+
const evidence = collapsed
|
|
424
|
+
? "collapsed-paste"
|
|
425
|
+
: "composer-text";
|
|
426
|
+
// Work is CPU the host's idling cannot explain. Two measured failures shaped
|
|
427
|
+
// this, one on each side:
|
|
428
|
+
// - an idle host still burns a little, so a bare threshold called it working
|
|
429
|
+
// (an idling codex reached 420ms over 30s with nothing submitted);
|
|
430
|
+
// - and subtracting an idle budget built from the CALIBRATED rate called a
|
|
431
|
+
// working agent idle, because a host still finishing its startup calibrates
|
|
432
|
+
// as a "stable burn" far above real idle. Measured on this branch's own
|
|
433
|
+
// review launch: an agent visibly reading the PR, 12.2s of tree CPU,
|
|
434
|
+
// reported "submitted-idle" — which in a real launch kills a good lane.
|
|
435
|
+
// So the idle rate used to excuse missing work is CAPPED: a host that is truly
|
|
436
|
+
// waiting for input burns a few percent of a core at most (measured ~0 to 2.5%),
|
|
437
|
+
// and anything above that is startup, which must never excuse silence.
|
|
438
|
+
const idleRateForWork = Math.min(ready.idleRate, IDLE_RATE_CAP);
|
|
439
|
+
const activityDeadline = submittedAt + activityMs;
|
|
440
|
+
let cpuDeltaMs = 0;
|
|
441
|
+
for (;;) {
|
|
442
|
+
deps.sleep(pollMs);
|
|
443
|
+
const cpuNow = deps.cpuMs(pane);
|
|
444
|
+
// An unreadable sample proves nothing, and a NEGATIVE delta means the tree
|
|
445
|
+
// lost a process rather than that work happened. Neither may advance the
|
|
446
|
+
// evidence: keep the last provable delta and keep waiting.
|
|
447
|
+
if (cpuNow !== undefined && cpuNow - cpuBefore > cpuDeltaMs) {
|
|
448
|
+
cpuDeltaMs = cpuNow - cpuBefore;
|
|
449
|
+
}
|
|
450
|
+
const idleBudget = idleRateForWork * (deps.now() - submittedAt);
|
|
451
|
+
if (cpuDeltaMs - idleBudget >= activityCpuMs) {
|
|
452
|
+
return {
|
|
453
|
+
state: "working",
|
|
454
|
+
waitedMs: deps.now() - startedAt,
|
|
455
|
+
cpuDeltaMs,
|
|
456
|
+
evidence,
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
if (deps.now() >= activityDeadline) {
|
|
460
|
+
return {
|
|
461
|
+
state: "submitted-idle",
|
|
462
|
+
waitedMs: deps.now() - startedAt,
|
|
463
|
+
cpuDeltaMs,
|
|
464
|
+
evidence,
|
|
465
|
+
};
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
//# sourceMappingURL=prompt-delivery.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-delivery.js","sourceRoot":"","sources":["../src/prompt-delivery.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/registry.js
CHANGED
|
@@ -13,10 +13,11 @@
|
|
|
13
13
|
* config dir (default path honors REMOTE_CLI_CONFIG_HOME like config.ts).
|
|
14
14
|
*/
|
|
15
15
|
import { spawnSync } from "node:child_process";
|
|
16
|
-
import {
|
|
16
|
+
import { mkdirSync, readFileSync, renameSync, writeFileSync, } from "node:fs";
|
|
17
17
|
import { uptime } from "node:os";
|
|
18
18
|
import { dirname, join } from "node:path";
|
|
19
19
|
import { getLayoutConfig, resolveConfigPath } from "./config.js";
|
|
20
|
+
import { acquireFileLock, releaseFileLock } from "./file-lock.js";
|
|
20
21
|
import { managedSessionCandidates, parseManagedSessionName, listLocalSessions, } from "./tmux.js";
|
|
21
22
|
/** System boot time in ms epoch (now minus uptime). */
|
|
22
23
|
function defaultBootTimeMs() {
|
|
@@ -124,73 +125,10 @@ function saveRegistry(entries, path) {
|
|
|
124
125
|
//
|
|
125
126
|
// The registry is LOCAL ONLY (the CLI writes it; pods never touch it — they have
|
|
126
127
|
// no access to ~/.config/.../registry.json), so a LOCAL file lock is sufficient
|
|
127
|
-
// — there is no cross-host writer to coordinate with.
|
|
128
|
-
//
|
|
129
|
-
//
|
|
130
|
-
// portable primitive here (Node has no flock), and a crashed holder is recovered
|
|
131
|
-
// by the staleness break below.
|
|
128
|
+
// — there is no cross-host writer to coordinate with. The primitive itself lives
|
|
129
|
+
// in `file-lock.ts` (shared with the session-lease side-store); its bounded,
|
|
130
|
+
// best-effort contract is documented there.
|
|
132
131
|
// ---------------------------------------------------------------------------
|
|
133
|
-
/** Spin parameters for the lockfile (bounded — a deadlock must never hang a hook). */
|
|
134
|
-
const LOCK_STALE_MS = 10_000; // a lockfile older than this is assumed orphaned
|
|
135
|
-
const LOCK_SPIN_MS = 5; // busy-wait granularity between acquire attempts
|
|
136
|
-
const LOCK_MAX_WAIT_MS = 4_000; // give up waiting after this (then proceed best-effort)
|
|
137
|
-
function lockPath(path) {
|
|
138
|
-
return `${path}.lock`;
|
|
139
|
-
}
|
|
140
|
-
/** Busy-wait `ms` without a timer (we are holding a process-wide critical section). */
|
|
141
|
-
function spinSleep(ms) {
|
|
142
|
-
const end = Date.now() + ms;
|
|
143
|
-
while (Date.now() < end) {
|
|
144
|
-
// tight spin — ms is tiny (LOCK_SPIN_MS); a registry mutation is sub-ms.
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Acquire the registry lockfile (exclusive create). Returns the fd on success,
|
|
149
|
-
* or undefined if it could not be acquired within LOCK_MAX_WAIT_MS (the caller
|
|
150
|
-
* then proceeds best-effort — a slow lock must NEVER take down a claude hook).
|
|
151
|
-
* Breaks a STALE lock (holder crashed) by age.
|
|
152
|
-
*/
|
|
153
|
-
function acquireLock(path) {
|
|
154
|
-
const lp = lockPath(path);
|
|
155
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
156
|
-
const deadline = Date.now() + LOCK_MAX_WAIT_MS;
|
|
157
|
-
for (;;) {
|
|
158
|
-
try {
|
|
159
|
-
const fd = openSync(lp, "wx"); // O_CREAT|O_EXCL|O_WRONLY
|
|
160
|
-
return fd;
|
|
161
|
-
}
|
|
162
|
-
catch {
|
|
163
|
-
// Held — break it if it is stale (a crashed holder left it behind).
|
|
164
|
-
try {
|
|
165
|
-
const age = Date.now() - statSync(lp).mtimeMs;
|
|
166
|
-
if (age > LOCK_STALE_MS) {
|
|
167
|
-
rmSync(lp, { force: true });
|
|
168
|
-
continue; // retry the exclusive create immediately
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
catch {
|
|
172
|
-
// raced with the holder releasing it → just retry the create
|
|
173
|
-
}
|
|
174
|
-
if (Date.now() >= deadline)
|
|
175
|
-
return undefined; // give up, proceed best-effort
|
|
176
|
-
spinSleep(LOCK_SPIN_MS);
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
function releaseLock(fd, path) {
|
|
181
|
-
try {
|
|
182
|
-
closeSync(fd);
|
|
183
|
-
}
|
|
184
|
-
catch {
|
|
185
|
-
// already closed
|
|
186
|
-
}
|
|
187
|
-
try {
|
|
188
|
-
rmSync(lockPath(path), { force: true });
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
// already gone
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
132
|
/**
|
|
195
133
|
* Run `fn` under the registry lock: load the current entries, let `fn` mutate
|
|
196
134
|
* them (and compute a return value), then persist atomically — all inside ONE
|
|
@@ -203,7 +141,7 @@ function releaseLock(fd, path) {
|
|
|
203
141
|
* last-writer-wins as before. Exported for tests.
|
|
204
142
|
*/
|
|
205
143
|
export function withRegistryLock(path, fn) {
|
|
206
|
-
const fd =
|
|
144
|
+
const fd = acquireFileLock(path);
|
|
207
145
|
try {
|
|
208
146
|
const { entries, result, save } = fn(loadRegistry(path));
|
|
209
147
|
if (save !== false)
|
|
@@ -212,7 +150,7 @@ export function withRegistryLock(path, fn) {
|
|
|
212
150
|
}
|
|
213
151
|
finally {
|
|
214
152
|
if (fd !== undefined)
|
|
215
|
-
|
|
153
|
+
releaseFileLock(fd, path);
|
|
216
154
|
}
|
|
217
155
|
}
|
|
218
156
|
/**
|