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.
@@ -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":"AAiCA,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,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;AAsBD,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"}
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 also
23
- * carry a fingerprint/length of the explicit `botmux send` body; when
24
- * the transcript final is available, suppress only if the explicit
25
- * send appears to cover that final. This prevents progress updates
26
- * from hiding a later substantive final answer. Boundary handling
27
- * intentionally also considers
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 => typeof m.contentFingerprint !== 'string' || typeof m.contentLength !== 'number')) {
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
- if (markers.some(m => m.contentFingerprint && finalNormalized.includes(m.contentFingerprint))) {
45
- return true;
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AAsBjE,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,OAAO,CAAC,CAAC,kBAAkB,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,CAAC,EAAE,CAAC;QACvG,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,eAAe,GAAG,uBAAuB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IACjE,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC;IAElC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC;QAC9F,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1F,OAAO,UAAU,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;AAChE,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"}
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, contentFingerprint?, contentLength?}\n` to
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 = readSendMarkers().some(m => m.sentAtMs >= startedAtMs && m.sentAtMs <= completedAtMs + 5_000);
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;