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.
- package/dist-bundle/cli.js +237 -56
- package/package.json +1 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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)
|
|
34675
|
-
// at the
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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) => {
|