@bridge4dev/runner 0.39.0 → 0.40.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 +35 -4
- package/dist/attachments.js +35 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/dist/adapters/claude.js
CHANGED
|
@@ -287,6 +287,15 @@ class ClaudeSession {
|
|
|
287
287
|
mcpFallbackNotice = null;
|
|
288
288
|
/** Guards against overlapping capability probes. */
|
|
289
289
|
capabilitiesInFlight = false;
|
|
290
|
+
/**
|
|
291
|
+
* Has the first main-loop answer of this process already asked for the
|
|
292
|
+
* context window? (ticket #223)
|
|
293
|
+
*
|
|
294
|
+
* `q` is `readonly` — one adapter per CLI process — so this never needs
|
|
295
|
+
* resetting: a restarted process is a new instance with the flag back to
|
|
296
|
+
* false, which is exactly the moment the meter needs a fresh number.
|
|
297
|
+
*/
|
|
298
|
+
contextProbedAfterFirstReply = false;
|
|
290
299
|
mode;
|
|
291
300
|
/**
|
|
292
301
|
* A launch-time mode this workspace does not allow, remembered so the feed
|
|
@@ -559,6 +568,13 @@ class ClaudeSession {
|
|
|
559
568
|
// message would otherwise show no model list at all — while the control
|
|
560
569
|
// requests themselves work as soon as the CLI is up.
|
|
561
570
|
this.refreshCapabilities();
|
|
571
|
+
// Same reasoning for the context meter (ticket #223). It used to be asked
|
|
572
|
+
// for only at the END of a turn, so a session that had not finished its
|
|
573
|
+
// first one had no numbers at all and the gauge did not exist — worst in a
|
|
574
|
+
// session that parked a question, which can sit there for hours. This probe
|
|
575
|
+
// costs one control round-trip and gives the meter its denominator (the
|
|
576
|
+
// model's window) from the moment the process is up.
|
|
577
|
+
this.refreshContextUsage();
|
|
562
578
|
}
|
|
563
579
|
/**
|
|
564
580
|
* Write this session's MCP config to a 0600 file and return its path, or null
|
|
@@ -623,10 +639,14 @@ class ClaudeSession {
|
|
|
623
639
|
this.output.push(maskSecrets(event));
|
|
624
640
|
}
|
|
625
641
|
/**
|
|
626
|
-
* How full the context window is
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
642
|
+
* How full the context window is. Fire-and-forget with a timeout on purpose:
|
|
643
|
+
* this is one more control round-trip on a channel that can hang, and it must
|
|
644
|
+
* never be able to stall the event loop that carries the conversation.
|
|
645
|
+
*
|
|
646
|
+
* Called from four places, each answering a different gap: process start and
|
|
647
|
+
* first main-loop reply (ticket #223 — otherwise a session shows no gauge at
|
|
648
|
+
* all until its first turn ends), model change (the window's size differs 5x
|
|
649
|
+
* between 200k and 1M), and end of turn.
|
|
630
650
|
*/
|
|
631
651
|
refreshContextUsage() {
|
|
632
652
|
if (this.stopped)
|
|
@@ -1845,6 +1865,17 @@ class ClaudeSession {
|
|
|
1845
1865
|
});
|
|
1846
1866
|
}
|
|
1847
1867
|
}
|
|
1868
|
+
// Ticket #223. The startup probe fires before the CLI has read
|
|
1869
|
+
// anything, so its number is the empty window; this one lands after
|
|
1870
|
+
// the agent has actually said something and is the first figure
|
|
1871
|
+
// worth showing. Once per process, and only for the main loop: it is
|
|
1872
|
+
// a control round-trip on a channel that can hang, subagent chatter
|
|
1873
|
+
// is not this session's context, and the end-of-turn probe covers
|
|
1874
|
+
// everything after.
|
|
1875
|
+
if (!fromSubagent && !this.contextProbedAfterFirstReply) {
|
|
1876
|
+
this.contextProbedAfterFirstReply = true;
|
|
1877
|
+
this.refreshContextUsage();
|
|
1878
|
+
}
|
|
1848
1879
|
break;
|
|
1849
1880
|
}
|
|
1850
1881
|
case 'user': {
|
package/dist/attachments.js
CHANGED
|
@@ -18,9 +18,32 @@ const execFileAsync = promisify(execFile);
|
|
|
18
18
|
*/
|
|
19
19
|
/** Directory inside the worktree; also the line written to info/exclude. */
|
|
20
20
|
export const ATTACHMENT_DIR = '.devbridge/attachments';
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
/**
|
|
22
|
+
* Hard ceiling per file; the API allows 10 MB for images and 50 MB otherwise.
|
|
23
|
+
*
|
|
24
|
+
* Mirror of `MAX_DOCUMENT_ATTACHMENT_SIZE_BYTES` in `@devbridge/shared` plus a
|
|
25
|
+
* megabyte of slack — the runner cannot import that package (see
|
|
26
|
+
* `recipe-schema.ts`: the published tarball would not resolve it). The slack is
|
|
27
|
+
* what keeps the two halves from disagreeing on a rounding: the API refuses
|
|
28
|
+
* first, with an error the person actually sees, and this only catches bytes
|
|
29
|
+
* that no upload path should have produced.
|
|
30
|
+
*
|
|
31
|
+
* Raise the API side and this one in the SAME runner release. A ceiling that
|
|
32
|
+
* moves only in DevBridge lets a file upload and then vanish: the refusal below
|
|
33
|
+
* is a warning line in the session, not something the uploader is shown.
|
|
34
|
+
*/
|
|
35
|
+
const MAX_ATTACHMENT_BYTES = 51 * 1024 * 1024;
|
|
36
|
+
/**
|
|
37
|
+
* A minute was plenty while the ceiling was 26 MB; at 50 MB it is a coin flip.
|
|
38
|
+
*
|
|
39
|
+
* The whole file is buffered by the API and pushed through nginx in one
|
|
40
|
+
* response, so this timeout covers the entire transfer, not idle time between
|
|
41
|
+
* packets. 60 s for 50 MB demands ~7 Mbit/s sustained end to end — ordinary for
|
|
42
|
+
* two VPSes, not ordinary for a dev server on a home uplink or behind a
|
|
43
|
+
* throttled proxy. Three minutes covers ~2.3 Mbit/s, and the cost of being
|
|
44
|
+
* generous is nil: a stalled download fails the same way, just later.
|
|
45
|
+
*/
|
|
46
|
+
const DOWNLOAD_TIMEOUT_MS = 180_000;
|
|
24
47
|
/**
|
|
25
48
|
* A file name that is safe to write and unambiguous to read.
|
|
26
49
|
*
|
|
@@ -153,9 +176,16 @@ export async function saveAttachments(input) {
|
|
|
153
176
|
pruneAttachmentDir(dir);
|
|
154
177
|
return { saved, failed };
|
|
155
178
|
}
|
|
156
|
-
/**
|
|
179
|
+
/**
|
|
180
|
+
* Keep at most this much history in one worktree's attachment folder.
|
|
181
|
+
*
|
|
182
|
+
* Sized in files, not in bytes: 512 MB was twenty attachments at the old 25 MB
|
|
183
|
+
* ceiling and would be ten at the new one — an afternoon of work, after which
|
|
184
|
+
* the folder starts evicting documents a running session may still be told to
|
|
185
|
+
* open. A gigabyte restores the same twenty-file depth.
|
|
186
|
+
*/
|
|
157
187
|
const ATTACHMENT_RETENTION_MS = 14 * 24 * 60 * 60 * 1000;
|
|
158
|
-
const ATTACHMENT_DIR_BUDGET_BYTES =
|
|
188
|
+
const ATTACHMENT_DIR_BUDGET_BYTES = 1024 * 1024 * 1024;
|
|
159
189
|
/**
|
|
160
190
|
* Delete old attachments from a session worktree.
|
|
161
191
|
*
|
package/dist/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const RUNNER_VERSION = "0.
|
|
1
|
+
export declare const RUNNER_VERSION = "0.40.0";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/version.js
CHANGED
package/package.json
CHANGED