tesseract-agent 0.9.34 → 0.9.35

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.
Files changed (2) hide show
  1. package/dist-bundle/cli.js +237 -56
  2. package/package.json +1 -1
@@ -30072,7 +30072,22 @@ function autoCompactEnvFor(pct2, supplied) {
30072
30072
  return {};
30073
30073
  return { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(Math.round(pct2)) };
30074
30074
  }
30075
- var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE;
30075
+ function shouldCompactProactively(a) {
30076
+ if (a.mode === "off")
30077
+ return "skip";
30078
+ if (a.inFlight)
30079
+ return "skip";
30080
+ if (typeof a.pct !== "number" || !Number.isFinite(a.pct) || a.pct <= 0 || a.pct >= 100)
30081
+ return "skip";
30082
+ if (typeof a.usagePct !== "number" || !Number.isFinite(a.usagePct))
30083
+ return "skip";
30084
+ if (a.usagePct < a.pct)
30085
+ return "reset";
30086
+ if (typeof a.lastCompactPct === "number" && a.usagePct < a.lastCompactPct + PROACTIVE_REGROWTH_POINTS)
30087
+ return "skip";
30088
+ return "compact";
30089
+ }
30090
+ var OVERFLOW_MAX_TRIES, OVERFLOW_COMPACT_MESSAGE, OVERFLOW_RESUME_MESSAGE, PROACTIVE_REGROWTH_POINTS;
30076
30091
  var init_context_recovery = __esm({
30077
30092
  "../../packages/agent-core/dist/context-recovery.js"() {
30078
30093
  "use strict";
@@ -30080,6 +30095,7 @@ var init_context_recovery = __esm({
30080
30095
  OVERFLOW_MAX_TRIES = 3;
30081
30096
  OVERFLOW_COMPACT_MESSAGE = "/compact";
30082
30097
  OVERFLOW_RESUME_MESSAGE = "Continue.";
30098
+ PROACTIVE_REGROWTH_POINTS = 5;
30083
30099
  }
30084
30100
  });
30085
30101
 
@@ -32595,6 +32611,65 @@ var init_agent_manager = __esm({
32595
32611
  setVerifierLlm(fn) {
32596
32612
  this.verifierLlm = fn;
32597
32613
  }
32614
+ /**
32615
+ * PROACTIVE compaction: keep an unattended run comfortably inside the window instead of
32616
+ * letting it walk into the wall.
32617
+ *
32618
+ * The renderer already does this at the user's threshold — but only for a conversation
32619
+ * it has on screen. Headless there was nothing, and the fallback everyone assumed
32620
+ * (`CLAUDE_AUTOCOMPACT_PCT_OVERRIDE`, which the desktop also sets) turns out to be inert:
32621
+ * measured against Claude Code 2.1.241, setting it to 25 left `autoCompactThreshold` at
32622
+ * the CLI's own 167000 and the context climbed straight past 25%, 33%, 42%, 52% without
32623
+ * compacting. So an unattended run honoured no threshold at all; its only protection was
32624
+ * the wall-hit recovery, which is a last resort, not a setting.
32625
+ *
32626
+ * Only when NOBODY IS WATCHING. With a client attached the renderer owns this, and both
32627
+ * doing it would spend two turns on one reclaim.
32628
+ */
32629
+ async maybeCompactProactively(live) {
32630
+ const pct2 = (() => {
32631
+ try {
32632
+ return this.autoCompactPct?.();
32633
+ } catch {
32634
+ return void 0;
32635
+ }
32636
+ })();
32637
+ const usage2 = await this.getContextUsage(live.sessionId).catch(() => null);
32638
+ const verdict = shouldCompactProactively({
32639
+ mode: live.unattended ?? "off",
32640
+ pct: pct2,
32641
+ usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
32642
+ lastCompactPct: live.proactiveCompactedAt ?? null,
32643
+ inFlight: live.overflowCompacting === true
32644
+ });
32645
+ if (verdict === "reset") {
32646
+ live.proactiveCompactedAt = void 0;
32647
+ return;
32648
+ }
32649
+ if (verdict !== "compact")
32650
+ return;
32651
+ live.proactiveCompactedAt = usage2?.percentage ?? 0;
32652
+ live.overflowCompacting = true;
32653
+ try {
32654
+ log(`auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used (threshold ${String(pct2)}%) \u2014 compacting`);
32655
+ await this.sendMessage({
32656
+ message: OVERFLOW_COMPACT_MESSAGE,
32657
+ url: "",
32658
+ sessionId: live.sessionId,
32659
+ projectDir: live.cwd,
32660
+ origin: live.origin,
32661
+ browserId: live.browserId,
32662
+ windowId: live.windowId,
32663
+ autoContinuation: true,
32664
+ ...live.unattended === "auto" ? { unattended: true } : {},
32665
+ ...live.model ? { model: live.model } : {}
32666
+ });
32667
+ } catch (err2) {
32668
+ log("auto-compact failed:", err2 instanceof Error ? err2.message : String(err2));
32669
+ } finally {
32670
+ live.overflowCompacting = false;
32671
+ }
32672
+ }
32598
32673
  /**
32599
32674
  * Compact and resume after this session outgrew the window, when nobody is watching.
32600
32675
  *
@@ -32630,7 +32705,12 @@ var init_agent_manager = __esm({
32630
32705
  ...live.unattended === "auto" ? { unattended: true } : {},
32631
32706
  ...live.model ? { model: live.model } : {}
32632
32707
  };
32633
- await this.sendMessage({ ...base, message: OVERFLOW_COMPACT_MESSAGE });
32708
+ live.overflowCompacting = true;
32709
+ try {
32710
+ await this.sendMessage({ ...base, message: OVERFLOW_COMPACT_MESSAGE });
32711
+ } finally {
32712
+ live.overflowCompacting = false;
32713
+ }
32634
32714
  await this.sendMessage({ ...base, message: OVERFLOW_RESUME_MESSAGE });
32635
32715
  }
32636
32716
  });
@@ -32903,6 +32983,7 @@ ${full.slice(-8e3)}`;
32903
32983
  });
32904
32984
  if (action.kind === "done" || action.kind === "capped")
32905
32985
  return;
32986
+ await this.maybeCompactProactively(live);
32906
32987
  await this.sendMessage({
32907
32988
  message: action.prompt,
32908
32989
  url: "",
@@ -34671,8 +34752,12 @@ CRITICAL RULES:
34671
34752
  ...identityEnv(),
34672
34753
  ...options.env,
34673
34754
  // params.env carries CLAUDE_AUTOCOMPACT_PCT_OVERRIDE from the user's setting
34674
- // (getAgentSettings) — IF this CLI honours it, native mid-run compaction fires
34675
- // at the same threshold as our renderer-side proactive `/compact`.
34755
+ // (getAgentSettings). MEASURED INERT on Claude Code 2.1.241: set to 25, the
34756
+ // reported `autoCompactThreshold` stayed at the CLI's own 167000 and the
34757
+ // conversation climbed past 25%, 33%, 42%, 52% without compacting once. Kept
34758
+ // because it costs nothing and other CLI versions may honour it — but nothing
34759
+ // depends on it: `maybeCompactProactively` is what actually holds an unattended
34760
+ // run to the user's threshold.
34676
34761
  ...params.env ?? {},
34677
34762
  // FALLBACK, not an override: `params.env` wins whenever the desktop supplied a
34678
34763
  // threshold. This fills the gap for a turn the daemon originated itself, which
@@ -35083,10 +35168,13 @@ ${RV_PHASE_DIRECTIVE}` : ""), live.sessionId) },
35083
35168
  });
35084
35169
  }
35085
35170
  const limitRejection = live.usageLimitRejection ?? (r.subtype === "success" ? assistantUsageLimitFallback(live.lastAssistantContent) : void 0);
35171
+ const resultText = typeof r.result === "string" ? r.result : "";
35172
+ const textOverflow = r.is_error === true && isContextOverflow(resultText);
35086
35173
  if (limitRejection) {
35087
35174
  reportUsageLimit(limitRejection, turnSid);
35088
- } else if (r.subtype === "success") {
35089
- live.overflowTries = 0;
35175
+ } else if (r.subtype === "success" && !textOverflow) {
35176
+ if (!live.overflowCompacting)
35177
+ live.overflowTries = 0;
35090
35178
  if (!turnStreamed && Array.isArray(live.lastAssistantContent)) {
35091
35179
  for (const blk of live.lastAssistantContent) {
35092
35180
  if (blk?.type === "thinking" && typeof blk.thinking === "string" && blk.thinking) {
@@ -35123,6 +35211,8 @@ ${RV_PHASE_DIRECTIVE}` : ""), live.sessionId) },
35123
35211
  const didWork = typeof r.num_turns !== "number" || r.num_turns > 1;
35124
35212
  if (live.rv && !continuable)
35125
35213
  void this.runVerification(live, typeof r.result === "string" ? r.result : "", didWork);
35214
+ else
35215
+ void this.maybeCompactProactively(live);
35126
35216
  } else if (live.interrupted) {
35127
35217
  live.interrupted = false;
35128
35218
  this.clearStopWatchdog(live);
@@ -35131,8 +35221,8 @@ ${RV_PHASE_DIRECTIVE}` : ""), live.sessionId) },
35131
35221
  emit2({ type: "agent:status", sessionId: turnSid, status: "idle" });
35132
35222
  } else {
35133
35223
  const errors = Array.isArray(r.errors) ? r.errors.map(String).filter(Boolean) : [];
35134
- const detail = errors.length > 0 ? errors.join("\n") : `Agent returned ${r.subtype}${r.stop_reason ? ` (stop_reason: ${r.stop_reason})` : ""}`;
35135
- const contextHit = r.subtype === "error_max_turns" ? "max_turns" : String(r.subtype).includes("context") || r.stop_reason === "model_context_window_exceeded" ? "context_window" : void 0;
35224
+ const detail = textOverflow ? resultText : errors.length > 0 ? errors.join("\n") : `Agent returned ${r.subtype}${r.stop_reason ? ` (stop_reason: ${r.stop_reason})` : ""}`;
35225
+ const contextHit = r.subtype === "error_max_turns" ? "max_turns" : textOverflow || String(r.subtype).includes("context") || r.stop_reason === "model_context_window_exceeded" ? "context_window" : void 0;
35136
35226
  const looksTransient = !contextHit && /overloaded|\b429\b|\b529\b|rate.?limit|too many requests|throttl|\b50[0234]\b|service unavailable|bad gateway|gateway timeout|timed? ?out|ETIMEDOUT|ECONNRESET|ECONNREFUSED|EPIPE|ENOTFOUND|ENETUNREACH|EAI_AGAIN|socket hang up|network error|temporarily unavailable/i.test(detail);
35137
35227
  log("Session result error:", turnSid, JSON.stringify({ subtype: r.subtype, stop_reason: r.stop_reason, errors, looksTransient }));
35138
35228
  live.resultErrorReported = true;
@@ -36204,6 +36294,7 @@ __export(dist_exports2, {
36204
36294
  OVERFLOW_RESUME_MESSAGE: () => OVERFLOW_RESUME_MESSAGE,
36205
36295
  PRESENT_TOOL_NAMES: () => PRESENT_TOOL_NAMES,
36206
36296
  PRESENT_TOOL_SPECS: () => PRESENT_TOOL_SPECS,
36297
+ PROACTIVE_REGROWTH_POINTS: () => PROACTIVE_REGROWTH_POINTS,
36207
36298
  SCREEN_CONTROL_SPECS: () => SCREEN_CONTROL_SPECS,
36208
36299
  SessionStore: () => SessionStore,
36209
36300
  TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
@@ -36266,6 +36357,7 @@ __export(dist_exports2, {
36266
36357
  setTokenPath: () => setTokenPath,
36267
36358
  setTokenSegments: () => setTokenSegments,
36268
36359
  setUnattendedLogSink: () => setUnattendedLogSink,
36360
+ shouldCompactProactively: () => shouldCompactProactively,
36269
36361
  specParametersJsonSchema: () => specParametersJsonSchema,
36270
36362
  stringifyValue: () => stringifyValue,
36271
36363
  stripPromptPrefix: () => stripPromptPrefix,
@@ -75350,7 +75442,15 @@ var OPENCODE_ACP = {
75350
75442
  // Its own threshold, since ACP gives us no way to ASK it to compact. Without this the
75351
75443
  // auto-compact slider could not reach OpenCode at all and it compacted only at its own
75352
75444
  // hardcoded 95%.
75353
- tokenCompaction: { configEnv: "OPENCODE_CONFIG", bufferPath: ["compaction", "buffer"] },
75445
+ // `reserved`, not `buffer` — read out of OpenCode's own bundle (1.18.21):
75446
+ // let l = cfg.compaction?.reserved ?? Math.min(20000, maxOutputTokens(model))
75447
+ // return model.limit.input ? max(0, model.limit.input - l) : max(0, context - maxOutput)
75448
+ // `buffer` was not a key it knows, so this reserve had never once taken effect. Note the
75449
+ // second branch: even under the right name the reserve is IGNORED for a model that does
75450
+ // not declare `limit.input` — which is most of them (1329 of 7482 on models.dev), gpt-4o
75451
+ // and gpt-4o-mini included. So this is worth writing correctly, and is NOT something the
75452
+ // slider can rely on; `shouldCompactProactively` is what actually holds the line.
75453
+ tokenCompaction: { configEnv: "OPENCODE_CONFIG", bufferPath: ["compaction", "reserved"] },
75354
75454
  compactCommand: "/compact",
75355
75455
  // ACP fallback; the HTTP RPC below is preferred
75356
75456
  // `opencode acp` serves the full HTTP API on the same process — verified: the ACP session
@@ -76446,7 +76546,56 @@ ${text9}`);
76446
76546
  const all = await listSessionsFor(projectDir);
76447
76547
  return all.filter((row) => row.title.toLowerCase().includes(q) || (sessionBodies.get(row.id) ?? "").includes(q));
76448
76548
  }
76549
+ const proactiveCompactedAt = /* @__PURE__ */ new Map();
76550
+ const sessionRekey = /* @__PURE__ */ new Map();
76449
76551
  const overflowTries = /* @__PURE__ */ new Map();
76552
+ function contextUsageFor(sessionId) {
76553
+ const model = sessionResolvedModel.get(sessionId) ?? sessionConfig.get(sessionId)?.currentModel;
76554
+ const rep = sessionReported.get(sessionId);
76555
+ const total = rep?.used ?? sessionUsage.get(sessionId)?.total;
76556
+ const maxTokens = rep?.size ?? contextWindowFor(model) ?? void 0;
76557
+ if (total === void 0 || !maxTokens)
76558
+ return null;
76559
+ return {
76560
+ totalTokens: total,
76561
+ maxTokens,
76562
+ percentage: Math.min(100, Math.round(total / maxTokens * 1e3) / 10),
76563
+ ...model ? { model } : {}
76564
+ };
76565
+ }
76566
+ async function maybeCompactProactively(sid, params) {
76567
+ try {
76568
+ if (params.autoContinuation)
76569
+ return;
76570
+ if (!declared.contextCompaction)
76571
+ return;
76572
+ const live = sessionRekey.get(sid) ?? sid;
76573
+ const usage2 = contextUsageFor(live);
76574
+ const verdict = shouldCompactProactively({
76575
+ mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
76576
+ pct: readDaemonAgentSettings().autoCompactPct,
76577
+ usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
76578
+ lastCompactPct: proactiveCompactedAt.get(live) ?? null,
76579
+ inFlight: false
76580
+ });
76581
+ if (verdict === "reset") {
76582
+ proactiveCompactedAt.delete(live);
76583
+ return;
76584
+ }
76585
+ if (verdict !== "compact")
76586
+ return;
76587
+ proactiveCompactedAt.set(live, usage2?.percentage ?? 0);
76588
+ console.warn(`[${LABEL2}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
76589
+ await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: live, autoContinuation: true });
76590
+ const now2 = sessionRekey.get(live) ?? live;
76591
+ if (now2 !== live) {
76592
+ proactiveCompactedAt.set(now2, proactiveCompactedAt.get(live) ?? 0);
76593
+ proactiveCompactedAt.delete(live);
76594
+ }
76595
+ } catch (err2) {
76596
+ console.warn(`[${LABEL2}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
76597
+ }
76598
+ }
76450
76599
  async function sendMessage(params) {
76451
76600
  const origin = params.origin;
76452
76601
  const fail4 = (sessionId, error51, transient = false) => send4({ type: "chat:error", sessionId, clientRequestId: params.clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
@@ -76562,6 +76711,12 @@ ${text9}`);
76562
76711
  }
76563
76712
  sessionIndex.record({ id: next, cwd: params.projectDir, title, updatedAt: Date.now() });
76564
76713
  sessionIndex.forget(from);
76714
+ sessionRekey.set(from, next);
76715
+ const spentTries = overflowTries.get(from);
76716
+ if (spentTries !== void 0) {
76717
+ overflowTries.set(next, spentTries);
76718
+ overflowTries.delete(from);
76719
+ }
76565
76720
  send4({ type: "session:created", sessionId: next, clientRequestId: params.clientRequestId }, origin);
76566
76721
  send4({ type: "chat:complete", sessionId: next, clientRequestId: params.clientRequestId, messageId: randomUUID11(), result: "Compacted this conversation to free up context.", turnId: randomUUID11() }, origin);
76567
76722
  send4({ type: "agent:status", sessionId: next, clientRequestId: params.clientRequestId, status: "idle" }, origin);
@@ -76721,7 +76876,10 @@ ${text9}`);
76721
76876
  }
76722
76877
  }
76723
76878
  }
76724
- overflowTries.delete(sid);
76879
+ void maybeCompactProactively(sid, params);
76880
+ if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
76881
+ overflowTries.delete(sid);
76882
+ }
76725
76883
  send4({ type: "chat:complete", sessionId: sid, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...res?.stopReason ? { stopReason: res.stopReason } : {} }, origin);
76726
76884
  send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
76727
76885
  } catch (e) {
@@ -76737,7 +76895,7 @@ ${text9}`);
76737
76895
  context: { sessionId: sid, engine: engine.id },
76738
76896
  compactAndResume: async () => {
76739
76897
  await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: sid, autoContinuation: true });
76740
- await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: sid, autoContinuation: true });
76898
+ await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: sessionRekey.get(sid) ?? sid, autoContinuation: true });
76741
76899
  }
76742
76900
  });
76743
76901
  if (recovered)
@@ -77015,21 +77173,7 @@ ${detail}` : detail, !overflow);
77015
77173
  }
77016
77174
  },
77017
77175
  ...declared.contextUsage ? {
77018
- getContextUsage: async (sessionId) => {
77019
- const model = sessionResolvedModel.get(sessionId) ?? sessionConfig.get(sessionId)?.currentModel;
77020
- const rep = sessionReported.get(sessionId);
77021
- const total = rep?.used ?? sessionUsage.get(sessionId)?.total;
77022
- const maxTokens = rep?.size ?? contextWindowFor(model) ?? void 0;
77023
- if (total === void 0 || !maxTokens)
77024
- return null;
77025
- const usage2 = {
77026
- totalTokens: total,
77027
- maxTokens,
77028
- percentage: Math.min(100, Math.round(total / maxTokens * 1e3) / 10),
77029
- ...model ? { model } : {}
77030
- };
77031
- return usage2;
77032
- }
77176
+ getContextUsage: async (sessionId) => contextUsageFor(sessionId)
77033
77177
  } : {},
77034
77178
  ...declared.costTracking ? {
77035
77179
  getSessionCost: async (sessionId) => {
@@ -78173,7 +78317,61 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
78173
78317
  })();
78174
78318
  return initPromise;
78175
78319
  }
78320
+ const proactiveCompactedAt = /* @__PURE__ */ new Map();
78176
78321
  const overflowTries = /* @__PURE__ */ new Map();
78322
+ function contextUsageFor(sessionId) {
78323
+ const u = tokenUsage.get(sessionId);
78324
+ if (!u?.window)
78325
+ return null;
78326
+ const current = u.lastTotal || u.total;
78327
+ const usage2 = {
78328
+ // `last`, NOT `total`. Measured: `total` is CUMULATIVE over the conversation and grows
78329
+ // by exactly the previous turn's tokens (142,394 → 162,119 after a 19,725-token turn),
78330
+ // so it can never fall. Reporting it as context usage meant the meter climbed past
78331
+ // 100% of a 258k window on a conversation nowhere near full, never came down after a
78332
+ // compaction, and — because this figure is what the proactive threshold reads — asked
78333
+ // for compaction after compaction with the number refusing to move.
78334
+ //
78335
+ // `last.totalTokens` is the CURRENT context: the input the model actually saw on the
78336
+ // most recent turn, which is what a window is measured against and what drops when a
78337
+ // compaction succeeds.
78338
+ // `|| u.total`, not `?? u.total`: the single writer stores `u.last?.totalTokens ?? 0`,
78339
+ // so a missing `last` arrives here as 0 — which `??` passes straight through and the
78340
+ // meter reads 0% on a full conversation. Under-reporting is the dangerous direction,
78341
+ // because the proactive threshold then never fires and the context hits a hard
78342
+ // overflow instead of compacting. Observed live: a `thread/tokenUsage/updated` whose
78343
+ // `total` was all zeros while `last.totalTokens` was 4666, and the reverse.
78344
+ totalTokens: current,
78345
+ maxTokens: u.window,
78346
+ percentage: Math.min(100, Math.round(current / u.window * 1e3) / 10)
78347
+ };
78348
+ return usage2;
78349
+ }
78350
+ async function maybeCompactProactively(threadId, params) {
78351
+ try {
78352
+ if (params.autoContinuation)
78353
+ return;
78354
+ const usage2 = contextUsageFor(threadId);
78355
+ const verdict = shouldCompactProactively({
78356
+ mode: unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
78357
+ pct: readDaemonAgentSettings().autoCompactPct,
78358
+ usagePct: typeof usage2?.percentage === "number" ? usage2.percentage : null,
78359
+ lastCompactPct: proactiveCompactedAt.get(threadId) ?? null,
78360
+ inFlight: false
78361
+ });
78362
+ if (verdict === "reset") {
78363
+ proactiveCompactedAt.delete(threadId);
78364
+ return;
78365
+ }
78366
+ if (verdict !== "compact")
78367
+ return;
78368
+ proactiveCompactedAt.set(threadId, usage2?.percentage ?? 0);
78369
+ console.warn(`[${LABEL2}] auto-compact: ${Math.round(usage2?.percentage ?? 0)}% of the window used \u2014 compacting`);
78370
+ await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
78371
+ } catch (err2) {
78372
+ console.warn(`[${LABEL2}] auto-compact failed:`, err2 instanceof Error ? err2.message : String(err2));
78373
+ }
78374
+ }
78177
78375
  async function sendMessage(params) {
78178
78376
  const origin = params.origin;
78179
78377
  const cfg2 = resolve16(ENGINE_ID2);
@@ -78363,7 +78561,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
78363
78561
  }
78364
78562
  });
78365
78563
  }
78366
- overflowTries.delete(threadId);
78564
+ void maybeCompactProactively(threadId, params);
78565
+ if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
78566
+ overflowTries.delete(threadId);
78567
+ }
78367
78568
  send4({ type: "chat:complete", sessionId: threadId, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...stopReason ? { stopReason } : {} }, origin);
78368
78569
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
78369
78570
  } catch (e) {
@@ -78707,34 +78908,7 @@ ${text9}`;
78707
78908
  await transport.request("config/mcpServer/reload", {}).catch(() => {
78708
78909
  });
78709
78910
  },
78710
- getContextUsage: async (sessionId) => {
78711
- const u = tokenUsage.get(sessionId);
78712
- if (!u?.window)
78713
- return null;
78714
- const current = u.lastTotal || u.total;
78715
- const usage2 = {
78716
- // `last`, NOT `total`. Measured: `total` is CUMULATIVE over the conversation and grows
78717
- // by exactly the previous turn's tokens (142,394 → 162,119 after a 19,725-token turn),
78718
- // so it can never fall. Reporting it as context usage meant the meter climbed past
78719
- // 100% of a 258k window on a conversation nowhere near full, never came down after a
78720
- // compaction, and — because this figure is what the proactive threshold reads — asked
78721
- // for compaction after compaction with the number refusing to move.
78722
- //
78723
- // `last.totalTokens` is the CURRENT context: the input the model actually saw on the
78724
- // most recent turn, which is what a window is measured against and what drops when a
78725
- // compaction succeeds.
78726
- // `|| u.total`, not `?? u.total`: the single writer stores `u.last?.totalTokens ?? 0`,
78727
- // so a missing `last` arrives here as 0 — which `??` passes straight through and the
78728
- // meter reads 0% on a full conversation. Under-reporting is the dangerous direction,
78729
- // because the proactive threshold then never fires and the context hits a hard
78730
- // overflow instead of compacting. Observed live: a `thread/tokenUsage/updated` whose
78731
- // `total` was all zeros while `last.totalTokens` was 4666, and the reverse.
78732
- totalTokens: current,
78733
- maxTokens: u.window,
78734
- percentage: Math.min(100, Math.round(current / u.window * 1e3) / 10)
78735
- };
78736
- return usage2;
78737
- },
78911
+ getContextUsage: async (sessionId) => contextUsageFor(sessionId),
78738
78912
  /** toolInjection, host half. Codex reads MCP servers from its config, so a change takes
78739
78913
  * effect on the next install (the flag is reset so the write actually re-runs). */
78740
78914
  setInjectedMcpServers: (servers) => {
@@ -93088,7 +93262,12 @@ function setHostDaemonRole(on) {
93088
93262
  teardownHostRole();
93089
93263
  }
93090
93264
  }
93265
+ function rdeskOrMeshOnlyBuild() {
93266
+ return process.env.CCB_RDESK_ONLY === "1" || process.env.CCB_MESH_ONLY === "1";
93267
+ }
93091
93268
  function sharingEnabled() {
93269
+ if (rdeskOrMeshOnlyBuild())
93270
+ return false;
93092
93271
  return sharing || hostDaemonRole || process.env.CCB_HOST_DAEMON === "1";
93093
93272
  }
93094
93273
  var serverSelected = false;
@@ -94064,6 +94243,8 @@ function stopHeartbeat() {
94064
94243
  }
94065
94244
  }
94066
94245
  function registerAsHost() {
94246
+ if (rdeskOrMeshOnlyBuild())
94247
+ return;
94067
94248
  void ensureP2pReady();
94068
94249
  const kind = process.env.CCB_HOST_KIND === "cloud" ? "cloud" : void 0;
94069
94250
  const name = kind === "cloud" ? "Cloud agent" : hostname4();
@@ -103152,7 +103333,7 @@ async function runDaemon(opts = {}) {
103152
103333
  }
103153
103334
  } catch {
103154
103335
  }
103155
- if (ownsMachine)
103336
+ if (ownsMachine && !WE_ARE_RDESK_ONLY)
103156
103337
  setHostDaemonRole(true);
103157
103338
  const localToken = randomBytes10(24).toString("hex");
103158
103339
  const sendToViewer = (kind, sessionId, clientId, msg) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.9.34",
3
+ "version": "0.9.35",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public",