botmux 2.63.0 → 2.63.1
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/cli.d.ts.map +1 -1
- package/dist/cli.js +2 -6
- package/dist/cli.js.map +1 -1
- package/dist/services/bridge-fallback-gate.d.ts +1 -1
- package/dist/services/bridge-fallback-gate.d.ts.map +1 -1
- package/dist/services/bridge-fallback-gate.js +26 -13
- package/dist/services/bridge-fallback-gate.js.map +1 -1
- package/dist/worker.js +2 -2
- package/dist/worker.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
export interface BridgeSendMarker {
|
|
2
2
|
sentAtMs: number;
|
|
3
3
|
messageId?: string;
|
|
4
|
-
contentFingerprint?: string;
|
|
5
4
|
contentLength?: number;
|
|
6
5
|
}
|
|
7
6
|
export interface BridgeGateInput {
|
|
@@ -16,5 +15,6 @@ export interface BridgeGateInput {
|
|
|
16
15
|
* send markers distinguish final-answer sends from earlier progress sends. */
|
|
17
16
|
finalText?: string;
|
|
18
17
|
}
|
|
18
|
+
export declare function buildBridgeSendMarkerContent(content: string): Pick<BridgeSendMarker, 'contentLength'> | undefined;
|
|
19
19
|
export declare function shouldSuppressBridgeEmit(turn: BridgeGateInput, nextBoundaryMs: number | undefined, markers: readonly BridgeSendMarker[], adoptMode: boolean): boolean;
|
|
20
20
|
//# sourceMappingURL=bridge-fallback-gate.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-fallback-gate.d.ts","sourceRoot":"","sources":["../../src/services/bridge-fallback-gate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"bridge-fallback-gate.d.ts","sourceRoot":"","sources":["../../src/services/bridge-fallback-gate.ts"],"names":[],"mappings":"AAqCA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B;;yCAEqC;IACrC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B;qDACiD;IACjD,OAAO,EAAE,OAAO,GAAG,SAAS,CAAC;IAC7B;mFAC+E;IAC/E,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,gBAAgB,EAAE,eAAe,CAAC,GAAG,SAAS,CAIjH;AA8BD,wBAAgB,wBAAwB,CACtC,IAAI,EAAE,eAAe,EACrB,cAAc,EAAE,MAAM,GAAG,SAAS,EAClC,OAAO,EAAE,SAAS,gBAAgB,EAAE,EACpC,SAAS,EAAE,OAAO,GACjB,OAAO,CAQT"}
|
|
@@ -19,33 +19,46 @@
|
|
|
19
19
|
* reason to push it back to the Lark thread.
|
|
20
20
|
* - Non-adopt + send observed in window: suppress. The window is
|
|
21
21
|
* [turn.markTimeMs, nextBoundaryMs). Legacy markers only carry time,
|
|
22
|
-
* so any marker in the window still suppresses. Newer markers
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
22
|
+
* so any marker in the window still suppresses. Newer markers carry the
|
|
23
|
+
* normalized length of the explicit `botmux send` body. When the
|
|
24
|
+
* transcript final is available, only emit fallback if that final is
|
|
25
|
+
* materially longer than any single explicit send in the same window.
|
|
26
|
+
* This lets short progress updates surface a later substantive final
|
|
27
|
+
* answer, while same-size rewrites and short acknowledgements stay
|
|
28
|
+
* suppressed. Boundary handling intentionally also considers
|
|
28
29
|
* queue items that haven't reached "ready" yet (passed in via
|
|
29
30
|
* nextBoundaryMs) — without that, a model that's still mid-tool-use
|
|
30
31
|
* for turn N+1 could leak a send credit into turn N's window.
|
|
31
32
|
*/
|
|
32
33
|
import { normaliseForFingerprint } from './bridge-turn-queue.js';
|
|
34
|
+
const MATERIAL_FINAL_LENGTH_RATIO = 2;
|
|
35
|
+
const MATERIAL_FINAL_MIN_EXTRA_CHARS = 120;
|
|
36
|
+
export function buildBridgeSendMarkerContent(content) {
|
|
37
|
+
const normalized = normaliseForFingerprint(content);
|
|
38
|
+
if (!normalized)
|
|
39
|
+
return undefined;
|
|
40
|
+
return { contentLength: normalized.length };
|
|
41
|
+
}
|
|
42
|
+
function hasStructuredContentMarker(marker) {
|
|
43
|
+
return typeof marker.contentLength === 'number';
|
|
44
|
+
}
|
|
45
|
+
function finalIsMateriallyLongerThanSends(finalLength, markers) {
|
|
46
|
+
const maxSentLength = markers.reduce((max, marker) => Math.max(max, marker.contentLength), 0);
|
|
47
|
+
return finalLength >= maxSentLength * MATERIAL_FINAL_LENGTH_RATIO
|
|
48
|
+
&& finalLength - maxSentLength >= MATERIAL_FINAL_MIN_EXTRA_CHARS;
|
|
49
|
+
}
|
|
33
50
|
function markerSetCoversFinal(markers, finalText) {
|
|
34
51
|
if (markers.length === 0)
|
|
35
52
|
return false;
|
|
36
53
|
// Back-compat: old marker files only have sentAtMs/messageId. Keep the old
|
|
37
54
|
// conservative behavior for those entries instead of risking duplicates.
|
|
38
|
-
if (markers.some(m =>
|
|
55
|
+
if (markers.some(m => !hasStructuredContentMarker(m)))
|
|
39
56
|
return true;
|
|
40
|
-
}
|
|
41
57
|
const finalNormalized = normaliseForFingerprint(finalText ?? '');
|
|
42
58
|
if (!finalNormalized)
|
|
43
59
|
return true;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
const sentLength = markers.reduce((sum, m) => sum + Math.max(0, m.contentLength ?? 0), 0);
|
|
48
|
-
return sentLength >= Math.floor(finalNormalized.length * 0.8);
|
|
60
|
+
const structuredMarkers = markers.filter(hasStructuredContentMarker);
|
|
61
|
+
return !finalIsMateriallyLongerThanSends(finalNormalized.length, structuredMarkers);
|
|
49
62
|
}
|
|
50
63
|
export function shouldSuppressBridgeEmit(turn, nextBoundaryMs, markers, adoptMode) {
|
|
51
64
|
if (adoptMode)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge-fallback-gate.js","sourceRoot":"","sources":["../../src/services/bridge-fallback-gate.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"bridge-fallback-gate.js","sourceRoot":"","sources":["../../src/services/bridge-fallback-gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAEjE,MAAM,2BAA2B,GAAG,CAAC,CAAC;AACtC,MAAM,8BAA8B,GAAG,GAAG,CAAC;AAqB3C,MAAM,UAAU,4BAA4B,CAAC,OAAe;IAC1D,MAAM,UAAU,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,OAAO,EAAE,aAAa,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;AAC9C,CAAC;AAMD,SAAS,0BAA0B,CAAC,MAAwB;IAC1D,OAAO,OAAO,MAAM,CAAC,aAAa,KAAK,QAAQ,CAAC;AAClD,CAAC;AAED,SAAS,gCAAgC,CAAC,WAAmB,EAAE,OAA8C;IAC3G,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;IAC9F,OAAO,WAAW,IAAI,aAAa,GAAG,2BAA2B;WAC5D,WAAW,GAAG,aAAa,IAAI,8BAA8B,CAAC;AACrE,CAAC;AAED,SAAS,oBAAoB,CAAC,OAAoC,EAAE,SAA6B;IAC/F,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAEvC,2EAA2E;IAC3E,yEAAyE;IACzE,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnE,MAAM,eAAe,GAAG,uBAAuB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC,0BAA0B,CAAC,CAAC;IACrE,OAAO,CAAC,gCAAgC,CAAC,eAAe,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;AACtF,CAAC;AAED,MAAM,UAAU,wBAAwB,CACtC,IAAqB,EACrB,cAAkC,EAClC,OAAoC,EACpC,SAAkB;IAElB,IAAI,SAAS;QAAE,OAAO,KAAK,CAAC;IAC5B,IAAI,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC;IAC9B,MAAM,KAAK,GAAG,cAAc,IAAI,MAAM,CAAC,iBAAiB,CAAC;IACzD,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,IAAI,KAAK,IAAI,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC;IACvF,OAAO,oBAAoB,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;AAC/D,CAAC"}
|
package/dist/worker.js
CHANGED
|
@@ -306,7 +306,7 @@ function formatHeadlessLocalTurnContent(assistantText) {
|
|
|
306
306
|
// ─── Bridge fallback marker (non-adopt) ────────────────────────────────────
|
|
307
307
|
//
|
|
308
308
|
// `botmux send` (cli.ts cmdSend) appends a line
|
|
309
|
-
// `{sentAtMs, messageId,
|
|
309
|
+
// `{sentAtMs, messageId, contentLength?}\n` to
|
|
310
310
|
// `<DATA_DIR>/turn-sends/<sid>.jsonl` every time the model successfully posts
|
|
311
311
|
// a reply to its OWN session thread. The worker reads these markers at idle
|
|
312
312
|
// and suppresses transcript-driven final_output for any turn whose time window
|
|
@@ -2507,7 +2507,7 @@ function handleCodexAppMarker(body) {
|
|
|
2507
2507
|
const startedAtMs = typeof payload.startedAtMs === 'number' ? payload.startedAtMs : undefined;
|
|
2508
2508
|
const completedAtMs = typeof payload.completedAtMs === 'number' ? payload.completedAtMs : Date.now();
|
|
2509
2509
|
if (startedAtMs !== undefined) {
|
|
2510
|
-
const sentByModel =
|
|
2510
|
+
const sentByModel = shouldSuppressBridgeEmit({ markTimeMs: startedAtMs, isLocal: false, finalText: payload.content }, completedAtMs + 5_001, readSendMarkers(), false);
|
|
2511
2511
|
if (sentByModel) {
|
|
2512
2512
|
log(`${cliName()} final_output suppressed (model already called botmux send)`);
|
|
2513
2513
|
return;
|