tesseract-agent 0.9.33 → 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 +1328 -514
  2. package/package.json +1 -1
@@ -27453,10 +27453,10 @@ var init_client = __esm({
27453
27453
  * collect the result of an `async: true` submission. */
27454
27454
  async archive(searchId, output2 = "json") {
27455
27455
  const { apiKey, baseUrl } = await this.creds();
27456
- const safe = String(searchId).trim();
27457
- if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe))
27456
+ const safe2 = String(searchId).trim();
27457
+ if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe2))
27458
27458
  throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
27459
- const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe}.${output2 === "md" ? "md" : "json"}`);
27459
+ const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.${output2 === "md" ? "md" : "json"}`);
27460
27460
  u.searchParams.set("api_key", apiKey);
27461
27461
  return this.getJson(u.toString(), "archive", {}, { billed: false });
27462
27462
  }
@@ -27465,10 +27465,10 @@ var init_client = __esm({
27465
27465
  * the body is text, and feeding it to JSON.parse is how the markdown path used to throw. */
27466
27466
  async archiveMarkdown(searchId) {
27467
27467
  const { apiKey, baseUrl } = await this.creds();
27468
- const safe = String(searchId).trim();
27469
- if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe))
27468
+ const safe2 = String(searchId).trim();
27469
+ if (!/^[A-Za-z0-9_-]{6,128}$/.test(safe2))
27470
27470
  throw new SerpApiError(`Invalid search id "${searchId}".`, "bad_request");
27471
- const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe}.md`);
27471
+ const u = _SerpClient.join(baseUrl ?? DEFAULT_BASE_URL, `searches/${safe2}.md`);
27472
27472
  u.searchParams.set("api_key", apiKey);
27473
27473
  const { text: text9 } = await this.fetchWithRetry(u.toString(), "archive", {}, false);
27474
27474
  return { markdown: text9 };
@@ -29181,7 +29181,123 @@ var init_plan_splitter = __esm({
29181
29181
  }
29182
29182
  });
29183
29183
 
29184
+ // ../../packages/agent-core/dist/unattended-log.js
29185
+ var unattended_log_exports = {};
29186
+ __export(unattended_log_exports, {
29187
+ readUnattendedDecisions: () => readUnattendedDecisions,
29188
+ recordUnattendedDecision: () => recordUnattendedDecision,
29189
+ recordVerificationDecision: () => recordVerificationDecision,
29190
+ setUnattendedLogSink: () => setUnattendedLogSink,
29191
+ unattendedLogPath: () => unattendedLogPath
29192
+ });
29193
+ import { appendFileSync, closeSync as closeSync3, existsSync as existsSync7, mkdirSync as mkdirSync9, openSync as openSync3, readFileSync as readFileSync13, readSync as readSync2, renameSync as renameSync6, statSync as statSync5 } from "node:fs";
29194
+ import { dirname as dirname7 } from "node:path";
29195
+ function unattendedLogPath() {
29196
+ return daemonPath("unattended.jsonl");
29197
+ }
29198
+ function rolledPath() {
29199
+ return `${unattendedLogPath()}.1`;
29200
+ }
29201
+ function healPrefix(file2) {
29202
+ if (appended)
29203
+ return "";
29204
+ appended = true;
29205
+ try {
29206
+ const size = statSync5(file2).size;
29207
+ if (size === 0)
29208
+ return "";
29209
+ const fd = openSync3(file2, "r");
29210
+ try {
29211
+ const buf = Buffer.alloc(1);
29212
+ readSync2(fd, buf, 0, 1, size - 1);
29213
+ return buf[0] === 10 ? "" : "\n";
29214
+ } finally {
29215
+ closeSync3(fd);
29216
+ }
29217
+ } catch {
29218
+ return "";
29219
+ }
29220
+ }
29221
+ function setUnattendedLogSink(fn) {
29222
+ sink = fn;
29223
+ warned = false;
29224
+ appended = false;
29225
+ }
29226
+ function rotateIfNeeded(file2) {
29227
+ try {
29228
+ if (!existsSync7(file2) || statSync5(file2).size < MAX_BYTES)
29229
+ return;
29230
+ renameSync6(file2, rolledPath());
29231
+ } catch {
29232
+ }
29233
+ }
29234
+ function recordUnattendedDecision(entry) {
29235
+ if (sink) {
29236
+ try {
29237
+ sink(entry);
29238
+ } catch {
29239
+ }
29240
+ return;
29241
+ }
29242
+ try {
29243
+ const file2 = unattendedLogPath();
29244
+ mkdirSync9(dirname7(file2), { recursive: true });
29245
+ rotateIfNeeded(file2);
29246
+ appendFileSync(file2, `${healPrefix(file2)}${JSON.stringify(entry)}
29247
+ `, { mode: 384 });
29248
+ } catch (err2) {
29249
+ if (warned)
29250
+ return;
29251
+ warned = true;
29252
+ console.error("[unattended] decision log unavailable:", err2 instanceof Error ? err2.message : err2);
29253
+ }
29254
+ }
29255
+ function recordVerificationDecision(entry) {
29256
+ recordUnattendedDecision({ ts: (/* @__PURE__ */ new Date()).toISOString(), source: "verification", ...entry });
29257
+ }
29258
+ function readUnattendedDecisions(limit = 200, opts) {
29259
+ const out = [];
29260
+ for (const file2 of [rolledPath(), unattendedLogPath()]) {
29261
+ let text9;
29262
+ try {
29263
+ if (!existsSync7(file2))
29264
+ continue;
29265
+ text9 = readFileSync13(file2, "utf8");
29266
+ } catch {
29267
+ continue;
29268
+ }
29269
+ for (const line of text9.split("\n")) {
29270
+ if (!line.trim())
29271
+ continue;
29272
+ try {
29273
+ const entry = JSON.parse(line);
29274
+ if (opts?.sessionId && entry.sessionId !== opts.sessionId)
29275
+ continue;
29276
+ if (opts?.source && entry.source !== opts.source)
29277
+ continue;
29278
+ out.push(entry);
29279
+ } catch {
29280
+ }
29281
+ }
29282
+ }
29283
+ return limit > 0 && out.length > limit ? out.slice(-limit) : out;
29284
+ }
29285
+ var MAX_BYTES, appended, warned, sink;
29286
+ var init_unattended_log = __esm({
29287
+ "../../packages/agent-core/dist/unattended-log.js"() {
29288
+ "use strict";
29289
+ init_base_paths();
29290
+ MAX_BYTES = 4 * 1024 * 1024;
29291
+ appended = false;
29292
+ warned = false;
29293
+ sink = null;
29294
+ }
29295
+ });
29296
+
29184
29297
  // ../../packages/agent-core/dist/unattended.js
29298
+ function errText(err2) {
29299
+ return err2 instanceof Error ? err2.message : String(err2);
29300
+ }
29185
29301
  function unattendedModeFor(o) {
29186
29302
  if (o.optedIn === true)
29187
29303
  return "auto";
@@ -29232,18 +29348,48 @@ function unattendedAnswer(mode, prompt, opts) {
29232
29348
  }
29233
29349
  }
29234
29350
  }
29351
+ function logSubject(prompt) {
29352
+ switch (prompt.kind) {
29353
+ case "permission":
29354
+ case "question":
29355
+ case "plan":
29356
+ return prompt.tool;
29357
+ case "elicitation":
29358
+ return prompt.serverName;
29359
+ case "dialog":
29360
+ return prompt.dialogKind;
29361
+ default:
29362
+ return void 0;
29363
+ }
29364
+ }
29235
29365
  function scheduleUnattendedAnswer(prompt, deps) {
29236
29366
  if (deps.mode() === "off")
29237
29367
  return;
29368
+ const record2 = (mode, outcome, extra = {}) => {
29369
+ recordUnattendedDecision({
29370
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
29371
+ source: "prompt",
29372
+ ...deps.context?.sessionId ? { sessionId: deps.context.sessionId } : {},
29373
+ ...deps.context?.engine ? { engine: deps.context.engine } : {},
29374
+ mode,
29375
+ kind: prompt.kind,
29376
+ ...logSubject(prompt) ? { subject: logSubject(prompt) } : {},
29377
+ outcome,
29378
+ ...extra
29379
+ });
29380
+ };
29238
29381
  const timer2 = setTimeout(() => {
29239
29382
  const mode = deps.mode();
29240
- if (mode === "off")
29383
+ if (mode === "off") {
29384
+ record2("off", "skipped", { reason: "unattended switched off before the answer landed" });
29241
29385
  return;
29386
+ }
29242
29387
  let spent;
29243
29388
  try {
29244
29389
  spent = deps.charge();
29245
29390
  } catch (err2) {
29246
29391
  deps.log?.("unattended budget charge failed:", err2);
29392
+ record2(mode, "failed", { reason: `budget charge failed: ${errText(err2)}` });
29247
29393
  return;
29248
29394
  }
29249
29395
  const cappedOut = spent > UNATTENDED_MAX_DECISIONS;
@@ -29253,6 +29399,7 @@ function scheduleUnattendedAnswer(prompt, deps) {
29253
29399
  deps.refund();
29254
29400
  } catch {
29255
29401
  }
29402
+ record2(mode, "skipped", { reason: "no policy answer for this prompt kind", spent });
29256
29403
  return;
29257
29404
  }
29258
29405
  let applied = false;
@@ -29260,6 +29407,13 @@ function scheduleUnattendedAnswer(prompt, deps) {
29260
29407
  applied = deps.apply(answer);
29261
29408
  } catch (err2) {
29262
29409
  deps.log?.("unattended auto-answer failed:", err2);
29410
+ record2(mode, "failed", {
29411
+ reason: `apply failed: ${errText(err2)}`,
29412
+ behavior: answer.behavior,
29413
+ decision: answer.decision,
29414
+ spent,
29415
+ ...cappedOut ? { cappedOut } : {}
29416
+ });
29263
29417
  return;
29264
29418
  }
29265
29419
  if (!applied) {
@@ -29267,9 +29421,21 @@ function scheduleUnattendedAnswer(prompt, deps) {
29267
29421
  deps.refund();
29268
29422
  } catch {
29269
29423
  }
29424
+ record2(mode, "skipped", {
29425
+ reason: "prompt already resolved \u2014 answered by a human, or the turn ended",
29426
+ behavior: answer.behavior,
29427
+ decision: answer.decision,
29428
+ spent
29429
+ });
29270
29430
  return;
29271
29431
  }
29272
29432
  deps.log?.(`unattended (${mode}) answered ${prompt.kind}: ${answer.behavior}${cappedOut ? " (budget spent)" : ""} \u2014 ${answer.decision}`);
29433
+ record2(mode, "answered", {
29434
+ behavior: answer.behavior,
29435
+ decision: answer.decision,
29436
+ spent,
29437
+ ...cappedOut ? { cappedOut } : {}
29438
+ });
29273
29439
  try {
29274
29440
  deps.report(answer, cappedOut);
29275
29441
  } catch (err2) {
@@ -29283,6 +29449,7 @@ var init_unattended = __esm({
29283
29449
  "../../packages/agent-core/dist/unattended.js"() {
29284
29450
  "use strict";
29285
29451
  init_dist();
29452
+ init_unattended_log();
29286
29453
  UNATTENDED_ANSWER_DELAY_MS = 700;
29287
29454
  UNATTENDED_MAX_DECISIONS = 100;
29288
29455
  UNATTENDED_DECIDE_NOTE = "This is an unattended run \u2014 nobody is at the keyboard to answer, and no answer is coming. Choose the best option yourself, proceed, and briefly note which decision you made and why.";
@@ -29304,8 +29471,11 @@ var init_unattended = __esm({
29304
29471
  var reinforced_verification_exports = {};
29305
29472
  __export(reinforced_verification_exports, {
29306
29473
  RV_CLEAN_STREAK_TO_STOP: () => RV_CLEAN_STREAK_TO_STOP,
29474
+ RV_HISTORY_MAX: () => RV_HISTORY_MAX,
29307
29475
  RV_MAX_CYCLES: () => RV_MAX_CYCLES,
29308
29476
  RV_MIN_REVIEWED_PCT: () => RV_MIN_REVIEWED_PCT,
29477
+ RV_PHASE_DIRECTIVE: () => RV_PHASE_DIRECTIVE,
29478
+ RV_PHASE_EVIDENCE_ASKS: () => RV_PHASE_EVIDENCE_ASKS,
29309
29479
  VERDICT_JSON_SCHEMA: () => VERDICT_JSON_SCHEMA,
29310
29480
  blockingIssues: () => blockingIssues,
29311
29481
  completenessGrade: () => completenessGrade,
@@ -29313,13 +29483,15 @@ __export(reinforced_verification_exports, {
29313
29483
  fixPrompt: () => fixPrompt,
29314
29484
  newRvState: () => newRvState,
29315
29485
  parseVerdict: () => parseVerdict,
29486
+ phaseGrade: () => phaseGrade,
29487
+ phaseReviewPrompt: () => phaseReviewPrompt,
29316
29488
  reviewGrade: () => reviewGrade,
29317
29489
  reviewPrompt: () => reviewPrompt,
29318
29490
  rvAdvance: () => rvAdvance,
29319
29491
  rvDecision: () => rvDecision
29320
29492
  });
29321
29493
  function newRvState(task) {
29322
- return { cycles: 0, phase: "idle", cleanStreak: 0, ...task ? { task } : {} };
29494
+ return { cycles: 0, phase: "idle", cleanStreak: 0, phasesDone: 0, phaseAsks: 0, history: [], ...task ? { task } : {} };
29323
29495
  }
29324
29496
  function blockingIssues(v) {
29325
29497
  return v.issues.filter((i) => i.severity === "critical" || i.severity === "major");
@@ -29339,20 +29511,43 @@ function rvDecision(verdict, state3) {
29339
29511
  return { kind: "review", prompt: reviewPrompt(state3, verdict) };
29340
29512
  return { kind: "done" };
29341
29513
  }
29342
- if (!verdict.taskComplete)
29514
+ if (state3.phase === "phase-review") {
29515
+ if (blocking.length > 0)
29516
+ return { kind: "fix", prompt: fixPrompt(verdict, state3) };
29517
+ if (!verdict.exercised && state3.phaseAsks < RV_PHASE_EVIDENCE_ASKS) {
29518
+ return { kind: "phase-review", prompt: phaseReviewPrompt(state3, verdict) };
29519
+ }
29520
+ return verdict.taskComplete ? { kind: "review", prompt: reviewPrompt(state3) } : { kind: "continue", prompt: continuePrompt(verdict, state3) };
29521
+ }
29522
+ if (!verdict.taskComplete) {
29523
+ if (verdict.phaseComplete)
29524
+ return { kind: "phase-review", prompt: phaseReviewPrompt(state3, verdict) };
29343
29525
  return { kind: "continue", prompt: continuePrompt(verdict, state3) };
29526
+ }
29344
29527
  if (blocking.length > 0)
29345
29528
  return { kind: "fix", prompt: fixPrompt(verdict, state3) };
29346
29529
  return { kind: "review", prompt: reviewPrompt(state3) };
29347
29530
  })();
29348
- if (action.kind === "done" || action.kind === "review")
29531
+ if (action.kind === "done" || action.kind === "review" || action.kind === "phase-review")
29349
29532
  return action;
29350
29533
  return state3.cycles >= RV_MAX_CYCLES ? { kind: "capped" } : action;
29351
29534
  }
29352
29535
  function rvAdvance(state3, action, verdict) {
29353
29536
  const clean2 = verdict.taskComplete && blockingIssues(verdict).length === 0;
29354
29537
  const cleanStreak = state3.phase === "review" ? clean2 ? state3.cleanStreak + 1 : 0 : clean2 ? state3.cleanStreak : 0;
29355
- const next = { ...state3, lastVerdict: verdict, cleanStreak };
29538
+ const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
29539
+ const next = {
29540
+ ...state3,
29541
+ lastVerdict: verdict,
29542
+ cleanStreak,
29543
+ history: [...state3.history, {
29544
+ gate,
29545
+ phaseName: verdict.phaseName,
29546
+ taskComplete: verdict.taskComplete,
29547
+ exercised: verdict.exercised,
29548
+ summary: verdict.summary.slice(0, 200)
29549
+ }].slice(-RV_HISTORY_MAX)
29550
+ };
29356
29551
  switch (action.kind) {
29357
29552
  // Sending the agent back to work is what the budget counts — a review pass is the
29358
29553
  // loop doing its own job, not the agent being given another attempt.
@@ -29361,12 +29556,59 @@ function rvAdvance(state3, action, verdict) {
29361
29556
  return { ...next, cycles: state3.cycles + 1, phase: "idle" };
29362
29557
  case "review":
29363
29558
  return { ...next, phase: "review" };
29559
+ // No cycle, for the same reason a review costs none: the loop asking for evidence is not
29560
+ // the agent being given another attempt. The budget still binds, because every `continue`
29561
+ // and `fix` between phases charges one.
29562
+ case "phase-review":
29563
+ return {
29564
+ ...next,
29565
+ phase: "phase-review",
29566
+ // Counted on ENTRY to a checkpoint only. The evidence re-ask stays inside the same
29567
+ // checkpoint, and phaseGrade is explicitly asked to answer `phaseComplete` there too —
29568
+ // so counting it again scored one phase twice, and did it for the phase that had just
29569
+ // failed to produce any evidence at all.
29570
+ phasesDone: state3.phasesDone + (state3.phase !== "phase-review" && verdict.phaseComplete ? 1 : 0),
29571
+ // Entering a checkpoint resets the counter; re-asking within one increments it.
29572
+ phaseAsks: state3.phase === "phase-review" ? state3.phaseAsks + 1 : 0
29573
+ };
29364
29574
  case "done":
29365
29575
  return { ...next, phase: "done" };
29366
29576
  case "capped":
29367
29577
  return { ...next, phase: "capped" };
29368
29578
  }
29369
29579
  }
29580
+ function phaseReviewPrompt(state3, verdict) {
29581
+ const name = verdict?.phaseName?.trim();
29582
+ const notRun = verdict && verdict.exercised === false;
29583
+ return promptLines([
29584
+ "AUTOMATED PHASE CHECKPOINT \u2014 prove this phase before building on it.",
29585
+ "",
29586
+ state3.task ? `The request you are working on:
29587
+ ${state3.task}` : void 0,
29588
+ "",
29589
+ name ? `The phase you just finished: ${name}` : "You have just finished a phase of the work.",
29590
+ "",
29591
+ notRun ? "Your last pass did not RUN anything. Reading the code again is not a checkpoint \u2014 run it." : void 0,
29592
+ notRun ? "" : void 0,
29593
+ "Do these, in this order:",
29594
+ "1. RUN it. Execute the tests that cover this phase, or the command/script/request that",
29595
+ " exercises it. Actually run them \u2014 do not describe what would happen.",
29596
+ "2. Paste the command you ran and its real output. If it failed, that is the finding.",
29597
+ "3. Check that what worked BEFORE this phase still works: run the wider test suite, or",
29598
+ " the parts of it this phase could plausibly have broken, and say which you ran.",
29599
+ "4. Only then read the phase's diff for defects the run would not surface.",
29600
+ "",
29601
+ "If this phase genuinely cannot be exercised on its own, say so and say WHY, in one line.",
29602
+ "Do not substitute a description of the code for evidence that it works.",
29603
+ "",
29604
+ SERIOUSNESS_BAR,
29605
+ "",
29606
+ "Report, briefly:",
29607
+ "- what you ran, and the outcome",
29608
+ '- anything serious you found (or "nothing serious")',
29609
+ "- whether the phase is sound enough to build the next one on top of"
29610
+ ]);
29611
+ }
29370
29612
  function continuePrompt(verdict, state3) {
29371
29613
  const missing = verdict.unfinished.length > 0 ? verdict.unfinished.map((u) => `- ${u}`).join("\n") : "- (the request has not been fully delivered \u2014 re-read it and identify what is missing)";
29372
29614
  const defects = blockingIssues(verdict);
@@ -29459,21 +29701,42 @@ ${verdict.unfinished.map((u) => `- ${u}`).join("\n")}` : void 0,
29459
29701
  function issueLine(i) {
29460
29702
  return `- [${i.severity}/${i.kind}] ${i.summary}${i.where ? ` (${i.where})` : ""} \u2014 ${i.impact}`;
29461
29703
  }
29462
- function completenessGrade(task, finalText, todos) {
29463
- const plan = todos && todos.length > 0 ? `
29464
-
29465
- ## The agent's own checklist at the end of the turn
29466
- ${todos.map((t) => `- [${t.status}] ${t.content}`).join("\n")}` : "";
29704
+ function gradeContext(state3, todos) {
29705
+ const out = [
29706
+ "## What the user asked for",
29707
+ state3.task || "(not captured \u2014 judge from the account below)"
29708
+ ];
29709
+ if (state3.plan) {
29710
+ out.push("", "## The plan the agent laid out at the start", state3.plan.slice(0, 4e3));
29711
+ }
29712
+ if (state3.history.length > 0) {
29713
+ out.push("", "## What has already been established, oldest first");
29714
+ for (const h of state3.history) {
29715
+ const bits = [
29716
+ `[${h.gate}]`,
29717
+ h.phaseName ? `phase "${h.phaseName}"` : null,
29718
+ h.taskComplete ? "request complete" : "request outstanding",
29719
+ h.gate === "phase" ? h.exercised ? "RAN it" : "did NOT run it" : null,
29720
+ h.summary || null
29721
+ ].filter(Boolean);
29722
+ out.push(`- ${bits.join(" \xB7 ")}`);
29723
+ }
29724
+ out.push("", "Use this to judge PROGRESS. If the same claim keeps recurring with nothing", "new established, say so in `summary` and do not keep the run open on it.");
29725
+ }
29726
+ if (todos && todos.length > 0) {
29727
+ out.push("", "## The agent's own checklist at the end of the turn", ...todos.map((t) => `- [${t.status}] ${t.content}`));
29728
+ }
29729
+ return out.join("\n");
29730
+ }
29731
+ function completenessGrade(state3, finalText, todos) {
29467
29732
  return {
29468
29733
  system: GRADER_SYSTEM,
29469
29734
  schema: VERDICT_JSON_SCHEMA,
29470
29735
  prompt: [
29471
- "## What the user asked for",
29472
- task || "(not captured \u2014 judge completeness from the agent's own account below)",
29736
+ gradeContext(state3, todos),
29473
29737
  "",
29474
29738
  "## What the agent said when it stopped",
29475
29739
  finalText.slice(0, 24e3) || "(the agent produced no closing message)",
29476
- plan,
29477
29740
  "",
29478
29741
  "## Your task",
29479
29742
  "Decide whether the user's request has actually been delivered. Set `taskComplete`",
@@ -29482,18 +29745,68 @@ ${todos.map((t) => `- [${t.status}] ${t.content}`).join("\n")}` : "";
29482
29745
  "expected here unless the account admits to something broken. Fill the percentages from",
29483
29746
  'what the account evidences; if it evidences nothing, use 0 and confidence "low".',
29484
29747
  "",
29748
+ "## The phase checkpoint",
29749
+ "This run is verified AS IT IS BUILT. Separately from whether the whole request is",
29750
+ "done, decide whether the agent has just finished one testable PHASE of it \u2014 a slice",
29751
+ "that leaves the project working and can be exercised on its own.",
29752
+ "",
29753
+ "Set `phaseComplete` true only when BOTH hold:",
29754
+ '- the account describes a coherent slice as finished (not "started", not "in progress"), and',
29755
+ "- `taskComplete` is false \u2014 the whole request is still outstanding.",
29756
+ "A finished REQUEST is not a phase checkpoint; the ordinary completeness path handles it.",
29757
+ "Name that slice in `phaseName` (a few words, the agent's own framing), and put the",
29758
+ "number of phases it still expects in `phasesRemaining` (null if it has not said).",
29759
+ "",
29760
+ "Set `exercised` true only if the account shows the work was actually RUN \u2014 a command",
29761
+ 'and its output, a test that executed, an observed result. "I reviewed it", "this should',
29762
+ 'work", or a description of what the code does is NOT exercised. When in doubt, false.',
29763
+ "",
29485
29764
  "Return ONLY this JSON:",
29486
29765
  VERDICT_SCHEMA
29487
29766
  ].join("\n")
29488
29767
  };
29489
29768
  }
29490
- function reviewGrade(task, reviewText) {
29769
+ function phaseGrade(state3, phaseName, reportText, todos) {
29491
29770
  return {
29492
29771
  system: GRADER_SYSTEM,
29493
29772
  schema: VERDICT_JSON_SCHEMA,
29494
29773
  prompt: [
29495
- "## What the user asked for",
29496
- task || "(not captured)",
29774
+ gradeContext(state3, todos),
29775
+ "",
29776
+ phaseName ? `## The phase being checked
29777
+ ${phaseName}` : "## The phase being checked\n(unnamed)",
29778
+ "",
29779
+ "## The agent's checkpoint report",
29780
+ reportText.slice(0, 24e3) || "(the agent produced no report)",
29781
+ "",
29782
+ "## Your task",
29783
+ "This was a CHECKPOINT: the agent was told to prove the phase by running it.",
29784
+ "",
29785
+ "`exercised` is the field that matters. Set it true ONLY if the report shows something",
29786
+ "was actually executed \u2014 a command with its real output, a test run with a result, an",
29787
+ 'observed behaviour. A description of the code, a claim that it "should work", or a',
29788
+ "read-through of the diff is NOT exercised, however confident it sounds. A report that",
29789
+ "says the phase cannot be exercised on its own, and says why, is also not exercised \u2014",
29790
+ "but that is an honest answer, so do not manufacture issues over it.",
29791
+ "",
29792
+ "Record in `issues` only what the report shows is genuinely broken \u2014 a failing test, a",
29793
+ "command that errored, a regression it found. Do not invent findings from silence.",
29794
+ "",
29795
+ "Set `taskComplete` for the WHOLE request (usually false at a phase checkpoint), and",
29796
+ "`phaseComplete` true if this phase is now sound enough to build on.",
29797
+ "Fill `manuallyTestedPct` from what was actually run, not from what exists.",
29798
+ "",
29799
+ "Return ONLY this JSON:",
29800
+ VERDICT_SCHEMA
29801
+ ].join("\n")
29802
+ };
29803
+ }
29804
+ function reviewGrade(state3, reviewText, todos) {
29805
+ return {
29806
+ system: GRADER_SYSTEM,
29807
+ schema: VERDICT_JSON_SCHEMA,
29808
+ prompt: [
29809
+ gradeContext(state3, todos),
29497
29810
  "",
29498
29811
  "## The agent's review of its own work",
29499
29812
  reviewText.slice(0, 32e3) || "(the agent produced no review)",
@@ -29535,6 +29848,15 @@ function parseVerdict(raw) {
29535
29848
  })).slice(0, 40);
29536
29849
  return {
29537
29850
  taskComplete: o.taskComplete === true,
29851
+ // All four default to the CONSERVATIVE reading. `phaseComplete: false` means "no
29852
+ // checkpoint yet", which costs nothing; a defaulted `true` would fire a phase review at
29853
+ // every turn end. `exercised: false` means "nothing was run", which sends the phase
29854
+ // review back once — the safe direction, because the opposite lets "tested" quietly
29855
+ // come to mean "read", which is the one thing this gate exists to prevent.
29856
+ phaseComplete: o.phaseComplete === true,
29857
+ phaseName: typeof o.phaseName === "string" ? o.phaseName.trim().slice(0, 120) : "",
29858
+ phasesRemaining: typeof o.phasesRemaining === "number" && Number.isFinite(o.phasesRemaining) ? Math.max(0, Math.min(99, Math.round(o.phasesRemaining))) : null,
29859
+ exercised: o.exercised === true,
29538
29860
  confidence: o.confidence === "high" || o.confidence === "medium" ? o.confidence : "low",
29539
29861
  unfinished: strList(o.unfinished),
29540
29862
  issues,
@@ -29549,13 +29871,14 @@ function parseVerdict(raw) {
29549
29871
  summary: typeof o.summary === "string" ? o.summary.trim().slice(0, 2e3) : ""
29550
29872
  };
29551
29873
  }
29552
- var RV_MIN_REVIEWED_PCT, RV_CLEAN_STREAK_TO_STOP, SEVERITY_LIST, KIND_LIST, SEVERITIES, KINDS2, SERIOUSNESS_BAR, promptLines, VERDICT_SCHEMA, GRADER_SYSTEM, VERDICT_JSON_SCHEMA, NON_BLOCKING_WORDS, pct, tri, strList;
29874
+ var RV_MIN_REVIEWED_PCT, RV_PHASE_EVIDENCE_ASKS, RV_CLEAN_STREAK_TO_STOP, SEVERITY_LIST, KIND_LIST, SEVERITIES, KINDS2, RV_HISTORY_MAX, SERIOUSNESS_BAR, RV_PHASE_DIRECTIVE, promptLines, VERDICT_SCHEMA, GRADER_SYSTEM, VERDICT_JSON_SCHEMA, NON_BLOCKING_WORDS, pct, tri, strList;
29553
29875
  var init_reinforced_verification = __esm({
29554
29876
  "../../packages/agent-core/dist/reinforced-verification.js"() {
29555
29877
  "use strict";
29556
29878
  init_dist();
29557
29879
  init_dist();
29558
29880
  RV_MIN_REVIEWED_PCT = 90;
29881
+ RV_PHASE_EVIDENCE_ASKS = 1;
29559
29882
  RV_CLEAN_STREAK_TO_STOP = 2;
29560
29883
  SEVERITY_LIST = ["critical", "major", "minor"];
29561
29884
  KIND_LIST = [
@@ -29570,6 +29893,7 @@ var init_reinforced_verification = __esm({
29570
29893
  ];
29571
29894
  SEVERITIES = new Set(SEVERITY_LIST);
29572
29895
  KINDS2 = new Set(KIND_LIST);
29896
+ RV_HISTORY_MAX = 12;
29573
29897
  SERIOUSNESS_BAR = `Only these count as problems worth reporting:
29574
29898
  - It breaks functionality that is supposed to work \u2014 now, or for a realistic input.
29575
29899
  - It is a regression: something that worked before this run does not work now.
@@ -29584,9 +29908,26 @@ var init_reinforced_verification = __esm({
29584
29908
  Explicitly DO NOT report, and do not spend time on: naming, formatting, comment wording,
29585
29909
  documentation gaps, test style, micro-optimisation, hypothetical futures, "could be
29586
29910
  cleaner", or anything you would not stop a release for. Reporting those wastes the run.`;
29911
+ RV_PHASE_DIRECTIVE = `This run is verified as you build it. Work in PHASES.
29912
+
29913
+ Before you start, split the request into the smallest sequence of phases where each one:
29914
+ - leaves the project in a WORKING state (it builds, and what worked before still works), and
29915
+ - can be EXERCISED on its own \u2014 a test you can run, a command with observable output, a
29916
+ script, a request against a running service. Not "read the diff and see that it is right".
29917
+
29918
+ Then build one phase at a time. When a phase is done, say so plainly \u2014 name the phase, and
29919
+ say how it can be exercised. Do not start the next phase in the same turn: finishing one is
29920
+ a checkpoint, and the checkpoint is where it gets proven.
29921
+
29922
+ If the request is genuinely a single small change, that is one phase. Do not invent phases to
29923
+ look thorough; a phase that cannot be run on its own is not a phase.`;
29587
29924
  promptLines = (lines) => lines.filter((l) => l !== void 0).join("\n");
29588
29925
  VERDICT_SCHEMA = `{
29589
29926
  "taskComplete": boolean,
29927
+ "phaseComplete": boolean,
29928
+ "phaseName": string,
29929
+ "phasesRemaining": number | null,
29930
+ "exercised": boolean,
29590
29931
  "confidence": "low" | "medium" | "high",
29591
29932
  "unfinished": string[],
29592
29933
  "issues": [{
@@ -29625,9 +29966,16 @@ Respond with ONLY a JSON object matching the schema. No prose, no markdown fence
29625
29966
  VERDICT_JSON_SCHEMA = {
29626
29967
  type: "object",
29627
29968
  additionalProperties: false,
29628
- required: ["taskComplete", "confidence", "unfinished", "issues", "reviewedPct", "testCoveragePct", "manuallyTestedPct", "buildsClean", "testsPass", "verdict", "summary"],
29969
+ required: ["taskComplete", "phaseComplete", "phaseName", "phasesRemaining", "exercised", "confidence", "unfinished", "issues", "reviewedPct", "testCoveragePct", "manuallyTestedPct", "buildsClean", "testsPass", "verdict", "summary"],
29629
29970
  properties: {
29630
29971
  taskComplete: { type: "boolean" },
29972
+ // REQUIRED, so the grader has to take a position on the checkpoint every time rather
29973
+ // than omitting it and leaving the loop to guess (an omitted field parses to `false`,
29974
+ // which is silently "no checkpoint" — fine as a failure mode, useless as a default).
29975
+ phaseComplete: { type: "boolean" },
29976
+ phaseName: { type: "string" },
29977
+ phasesRemaining: { type: ["integer", "null"] },
29978
+ exercised: { type: "boolean" },
29631
29979
  confidence: { type: "string", enum: ["low", "medium", "high"] },
29632
29980
  unfinished: { type: "array", items: { type: "string" } },
29633
29981
  issues: {
@@ -29667,6 +30015,90 @@ Respond with ONLY a JSON object matching the schema. No prose, no markdown fence
29667
30015
  }
29668
30016
  });
29669
30017
 
30018
+ // ../../packages/agent-core/dist/context-recovery.js
30019
+ async function recoverFromContextOverflow(deps) {
30020
+ const mode = safe(deps.mode, "off");
30021
+ if (mode === "off")
30022
+ return false;
30023
+ const record2 = (action, attempt2, reason) => {
30024
+ recordUnattendedDecision({
30025
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
30026
+ source: "recovery",
30027
+ ...deps.context?.sessionId ? { sessionId: deps.context.sessionId } : {},
30028
+ ...deps.context?.engine ? { engine: deps.context.engine } : {},
30029
+ mode,
30030
+ kind: "context-overflow",
30031
+ action,
30032
+ attempt: attempt2,
30033
+ ...reason ? { reason } : {}
30034
+ });
30035
+ };
30036
+ if (!safe(deps.canCompact, false)) {
30037
+ record2("gave-up", safe(deps.tries, 0), "this engine cannot be asked to compact");
30038
+ return false;
30039
+ }
30040
+ const attempt = safe(deps.tries, 0) + 1;
30041
+ if (attempt > OVERFLOW_MAX_TRIES) {
30042
+ record2("gave-up", attempt, `compaction did not reclaim enough after ${OVERFLOW_MAX_TRIES} attempts`);
30043
+ deps.log?.(`context overflow: giving up after ${OVERFLOW_MAX_TRIES} compaction attempts`);
30044
+ return false;
30045
+ }
30046
+ try {
30047
+ deps.bump();
30048
+ } catch {
30049
+ }
30050
+ try {
30051
+ await deps.compactAndResume();
30052
+ } catch (err2) {
30053
+ deps.log?.("context overflow: compact-and-resume failed", err2);
30054
+ record2("gave-up", attempt, `compact-and-resume failed: ${err2 instanceof Error ? err2.message : String(err2)}`);
30055
+ return false;
30056
+ }
30057
+ record2("compact-and-resume", attempt);
30058
+ deps.log?.(`context overflow: compacting and resuming (attempt ${attempt}/${OVERFLOW_MAX_TRIES})`);
30059
+ return true;
30060
+ }
30061
+ function safe(fn, fallback) {
30062
+ try {
30063
+ return fn();
30064
+ } catch {
30065
+ return fallback;
30066
+ }
30067
+ }
30068
+ function autoCompactEnvFor(pct2, supplied) {
30069
+ if (supplied?.CLAUDE_AUTOCOMPACT_PCT_OVERRIDE)
30070
+ return {};
30071
+ if (typeof pct2 !== "number" || !Number.isFinite(pct2) || pct2 <= 0 || pct2 >= 100)
30072
+ return {};
30073
+ return { CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: String(Math.round(pct2)) };
30074
+ }
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;
30091
+ var init_context_recovery = __esm({
30092
+ "../../packages/agent-core/dist/context-recovery.js"() {
30093
+ "use strict";
30094
+ init_unattended_log();
30095
+ OVERFLOW_MAX_TRIES = 3;
30096
+ OVERFLOW_COMPACT_MESSAGE = "/compact";
30097
+ OVERFLOW_RESUME_MESSAGE = "Continue.";
30098
+ PROACTIVE_REGROWTH_POINTS = 5;
30099
+ }
30100
+ });
30101
+
29670
30102
  // ../../packages/agent-core/dist/session-edit.js
29671
30103
  function deleteTranscriptEntry(entries, uuid3, mode = "single") {
29672
30104
  const target = entries.find((e) => e.uuid === uuid3);
@@ -29833,7 +30265,7 @@ var init_session_edit = __esm({
29833
30265
  });
29834
30266
 
29835
30267
  // ../../packages/agent-core/dist/session-mirror.js
29836
- import { appendFileSync, existsSync as existsSync7, mkdirSync as mkdirSync9, readFileSync as readFileSync13, readdirSync, statSync as statSync5, unlinkSync as unlinkSync2 } from "node:fs";
30268
+ import { appendFileSync as appendFileSync2, existsSync as existsSync8, mkdirSync as mkdirSync10, readFileSync as readFileSync14, readdirSync, statSync as statSync6, unlinkSync as unlinkSync2 } from "node:fs";
29837
30269
  import { join as join16 } from "node:path";
29838
30270
  function sessionsRoot() {
29839
30271
  return tessPath("sessions");
@@ -29861,8 +30293,8 @@ function loadSeen(file2) {
29861
30293
  if (cached3)
29862
30294
  return cached3;
29863
30295
  const set2 = /* @__PURE__ */ new Set();
29864
- if (existsSync7(file2)) {
29865
- for (const line of readFileSync13(file2, "utf8").split("\n")) {
30296
+ if (existsSync8(file2)) {
30297
+ for (const line of readFileSync14(file2, "utf8").split("\n")) {
29866
30298
  if (!line.trim())
29867
30299
  continue;
29868
30300
  try {
@@ -29883,7 +30315,7 @@ function createLocalSessionStore(opts = {}) {
29883
30315
  return;
29884
30316
  const file2 = fileFor(key2);
29885
30317
  try {
29886
- mkdirSync9(join16(file2, ".."), { recursive: true });
30318
+ mkdirSync10(join16(file2, ".."), { recursive: true });
29887
30319
  withLock(`session-store-${safeSegment(key2.projectKey)}-${safeSegment(key2.sessionId)}`, () => {
29888
30320
  const seen = loadSeen(file2);
29889
30321
  const lines = [];
@@ -29897,7 +30329,7 @@ function createLocalSessionStore(opts = {}) {
29897
30329
  lines.push(JSON.stringify(e));
29898
30330
  }
29899
30331
  if (lines.length)
29900
- appendFileSync(file2, `${lines.join("\n")}
30332
+ appendFileSync2(file2, `${lines.join("\n")}
29901
30333
  `, { mode: 384 });
29902
30334
  }, 5e3);
29903
30335
  } catch (err2) {
@@ -29906,11 +30338,11 @@ function createLocalSessionStore(opts = {}) {
29906
30338
  },
29907
30339
  async load(key2) {
29908
30340
  const file2 = fileFor(key2);
29909
- if (!existsSync7(file2))
30341
+ if (!existsSync8(file2))
29910
30342
  return null;
29911
30343
  try {
29912
30344
  const out = [];
29913
- for (const line of readFileSync13(file2, "utf8").split("\n")) {
30345
+ for (const line of readFileSync14(file2, "utf8").split("\n")) {
29914
30346
  if (!line.trim())
29915
30347
  continue;
29916
30348
  try {
@@ -29926,7 +30358,7 @@ function createLocalSessionStore(opts = {}) {
29926
30358
  },
29927
30359
  async listSessions(projectKey) {
29928
30360
  const dir2 = join16(sessionsRoot(), safeSegment(projectKey));
29929
- if (!existsSync7(dir2))
30361
+ if (!existsSync8(dir2))
29930
30362
  return [];
29931
30363
  const out = [];
29932
30364
  for (const name of readdirSync(dir2)) {
@@ -29936,7 +30368,7 @@ function createLocalSessionStore(opts = {}) {
29936
30368
  if (base.includes("__"))
29937
30369
  continue;
29938
30370
  try {
29939
- out.push({ sessionId: base, mtime: Math.floor(statSync5(join16(dir2, name)).mtimeMs) });
30371
+ out.push({ sessionId: base, mtime: Math.floor(statSync6(join16(dir2, name)).mtimeMs) });
29940
30372
  } catch {
29941
30373
  }
29942
30374
  }
@@ -29944,7 +30376,7 @@ function createLocalSessionStore(opts = {}) {
29944
30376
  },
29945
30377
  async listSubkeys(key2) {
29946
30378
  const dir2 = join16(sessionsRoot(), safeSegment(key2.projectKey));
29947
- if (!existsSync7(dir2))
30379
+ if (!existsSync8(dir2))
29948
30380
  return [];
29949
30381
  const prefix = `${safeSegment(key2.sessionId)}__`;
29950
30382
  return readdirSync(dir2).filter((n) => n.startsWith(prefix) && n.endsWith(".jsonl")).map((n) => n.slice(prefix.length, -".jsonl".length));
@@ -29952,13 +30384,13 @@ function createLocalSessionStore(opts = {}) {
29952
30384
  async delete(key2) {
29953
30385
  const file2 = fileFor(key2);
29954
30386
  try {
29955
- if (existsSync7(file2))
30387
+ if (existsSync8(file2))
29956
30388
  unlinkSync2(file2);
29957
30389
  seenUuids.delete(file2);
29958
30390
  if (!key2.subpath) {
29959
30391
  const dir2 = join16(sessionsRoot(), safeSegment(key2.projectKey));
29960
30392
  const prefix = `${safeSegment(key2.sessionId)}__`;
29961
- if (existsSync7(dir2)) {
30393
+ if (existsSync8(dir2)) {
29962
30394
  for (const n of readdirSync(dir2)) {
29963
30395
  if (n.startsWith(prefix) && n.endsWith(".jsonl")) {
29964
30396
  try {
@@ -30835,8 +31267,8 @@ import { query, createSdkMcpServer, startup } from "@anthropic-ai/claude-agent-s
30835
31267
  import { writeFile as writeFile4, mkdir as mkdir4, readFile as readFile6 } from "node:fs/promises";
30836
31268
  import { randomUUID as randomUUID6 } from "node:crypto";
30837
31269
  import { tmpdir as tmpdir3, homedir as homedir4, userInfo } from "node:os";
30838
- import { join as join18, dirname as dirname7 } from "node:path";
30839
- import { existsSync as existsSync8, readFileSync as readFileSync14, readdirSync as readdirSync2, openSync as openSync3, readSync as readSync2, closeSync as closeSync3, statSync as statSync6, writeFileSync as writeFileSync10, mkdirSync as mkdirSync10, copyFileSync, renameSync as renameSync6 } from "node:fs";
31270
+ import { join as join18, dirname as dirname8 } from "node:path";
31271
+ import { existsSync as existsSync9, readFileSync as readFileSync15, readdirSync as readdirSync2, openSync as openSync4, readSync as readSync3, closeSync as closeSync4, statSync as statSync7, writeFileSync as writeFileSync10, mkdirSync as mkdirSync11, copyFileSync, renameSync as renameSync7 } from "node:fs";
30840
31272
  import { fileURLToPath } from "node:url";
30841
31273
  import { createRequire as createRequire2 } from "node:module";
30842
31274
  import { createServer as createServer2 } from "node:net";
@@ -30860,11 +31292,11 @@ function findUserInstalledClaude(binName) {
30860
31292
  "/usr/bin/" + binName
30861
31293
  ];
30862
31294
  for (const p of abs)
30863
- if (existsSync8(p))
31295
+ if (existsSync9(p))
30864
31296
  return p;
30865
31297
  try {
30866
31298
  const out = execFileSync2(process.platform === "win32" ? "where" : "which", [binName], { encoding: "utf8" }).split("\n")[0]?.trim();
30867
- if (out && existsSync8(out))
31299
+ if (out && existsSync9(out))
30868
31300
  return out;
30869
31301
  } catch {
30870
31302
  }
@@ -30889,8 +31321,8 @@ function resolveClaudeCodeExecutable() {
30889
31321
  for (const key2 of keys) {
30890
31322
  try {
30891
31323
  const pkgJson = require2.resolve(`@anthropic-ai/claude-agent-sdk-${key2}/package.json`);
30892
- const bin = join18(dirname7(pkgJson), binName);
30893
- if (existsSync8(bin))
31324
+ const bin = join18(dirname8(pkgJson), binName);
31325
+ if (existsSync9(bin))
30894
31326
  return cachedClaudeExe = bin;
30895
31327
  } catch {
30896
31328
  }
@@ -30900,7 +31332,7 @@ function resolveClaudeCodeExecutable() {
30900
31332
  const platKey = process.platform === "darwin" ? "mac" : process.platform === "win32" ? "win" : "linux";
30901
31333
  for (const dir2 of [`${platKey}-${process.arch}`, platKey]) {
30902
31334
  const bundled = join18(resourcesPath, "claude-cli", dir2, binName);
30903
- if (existsSync8(bundled))
31335
+ if (existsSync9(bundled))
30904
31336
  return cachedClaudeExe = bundled;
30905
31337
  }
30906
31338
  }
@@ -30927,7 +31359,7 @@ function engineCapsPath() {
30927
31359
  function claudeBinaryStamp() {
30928
31360
  try {
30929
31361
  const path6 = resolveClaudeCodeExecutable();
30930
- const st = statSync6(path6);
31362
+ const st = statSync7(path6);
30931
31363
  return `${path6}:${st.size}:${Math.round(st.mtimeMs)}`;
30932
31364
  } catch {
30933
31365
  return null;
@@ -30941,7 +31373,7 @@ function loadEngineCaps() {
30941
31373
  if (!stamp2)
30942
31374
  return;
30943
31375
  try {
30944
- const store = JSON.parse(readFileSync14(engineCapsPath(), "utf8"));
31376
+ const store = JSON.parse(readFileSync15(engineCapsPath(), "utf8"));
30945
31377
  const entry = store[stamp2];
30946
31378
  if (entry && (entry.v ?? 1) !== CAPS_VERSION) {
30947
31379
  log(`Engine caps: discarding a v${entry.v ?? 1} entry for this binary \u2014 its flags cannot be read under the current rules; they will be re-learned if they still apply.`);
@@ -30965,7 +31397,7 @@ function saveEngineCaps() {
30965
31397
  try {
30966
31398
  let store = {};
30967
31399
  try {
30968
- store = JSON.parse(readFileSync14(engineCapsPath(), "utf8"));
31400
+ store = JSON.parse(readFileSync15(engineCapsPath(), "utf8"));
30969
31401
  } catch {
30970
31402
  }
30971
31403
  store[stamp2] = {
@@ -30973,7 +31405,7 @@ function saveEngineCaps() {
30973
31405
  unsupported: [...unsupportedCliOptions],
30974
31406
  rejectedArgs: Object.fromEntries([...rejectedCliArgs].map(([f, v]) => [f, [...v]]))
30975
31407
  };
30976
- mkdirSync10(tessPath(), { recursive: true });
31408
+ mkdirSync11(tessPath(), { recursive: true });
30977
31409
  writeFileSync10(engineCapsPath(), JSON.stringify(store, null, 2), { mode: 384 });
30978
31410
  } catch {
30979
31411
  }
@@ -31106,13 +31538,13 @@ function findSessionCwd(sessionId, configDir) {
31106
31538
  }
31107
31539
  for (const slug2 of slugs) {
31108
31540
  const file2 = join18(base, slug2, `${sessionId}.jsonl`);
31109
- if (!existsSync8(file2))
31541
+ if (!existsSync9(file2))
31110
31542
  continue;
31111
31543
  try {
31112
- const fd = openSync3(file2, "r");
31544
+ const fd = openSync4(file2, "r");
31113
31545
  const buf = Buffer.alloc(65536);
31114
- const n = readSync2(fd, buf, 0, buf.length, 0);
31115
- closeSync3(fd);
31546
+ const n = readSync3(fd, buf, 0, buf.length, 0);
31547
+ closeSync4(fd);
31116
31548
  for (const line of buf.toString("utf-8", 0, n).split("\n")) {
31117
31549
  if (!line.trim())
31118
31550
  continue;
@@ -31138,7 +31570,7 @@ function newestVersionManagerNode() {
31138
31570
  join18(home, "Library", "pnpm", "node"),
31139
31571
  join18(home, ".local", "bin", "node")
31140
31572
  ])
31141
- if (existsSync8(p))
31573
+ if (existsSync9(p))
31142
31574
  return p;
31143
31575
  const roots = [
31144
31576
  { dir: join18(home, ".nvm", "versions", "node"), bin: (v) => join18(v, "bin", "node") },
@@ -31156,7 +31588,7 @@ function newestVersionManagerNode() {
31156
31588
  }
31157
31589
  for (const name of names) {
31158
31590
  const path6 = bin(join18(dir2, name));
31159
- if (!existsSync8(path6))
31591
+ if (!existsSync9(path6))
31160
31592
  continue;
31161
31593
  const parts = name.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10) || 0);
31162
31594
  const ver = [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
@@ -31171,12 +31603,12 @@ function loginShellNode() {
31171
31603
  if (process.platform === "win32")
31172
31604
  return null;
31173
31605
  const shell = process.env.SHELL || "/bin/zsh";
31174
- if (!existsSync8(shell))
31606
+ if (!existsSync9(shell))
31175
31607
  return null;
31176
31608
  try {
31177
31609
  const out = execFileSync2(shell, ["-lic", `printf '<<NODE:%s>>' "$(command -v node 2>/dev/null)"`], { encoding: "utf8", timeout: 4e3, stdio: ["ignore", "pipe", "ignore"] });
31178
31610
  const path6 = out.match(/<<NODE:(.*?)>>/)?.[1]?.trim();
31179
- return path6 && existsSync8(path6) ? path6 : null;
31611
+ return path6 && existsSync9(path6) ? path6 : null;
31180
31612
  } catch {
31181
31613
  return null;
31182
31614
  }
@@ -31187,12 +31619,12 @@ function resolveNodeExecutable() {
31187
31619
  if (!process.versions.electron)
31188
31620
  return cachedNodeExe2 = process.execPath;
31189
31621
  for (const p of [process.env.CCB_NODE_PATH, "/opt/homebrew/bin/node", "/usr/local/bin/node", "/usr/bin/node"]) {
31190
- if (p && existsSync8(p))
31622
+ if (p && existsSync9(p))
31191
31623
  return cachedNodeExe2 = p;
31192
31624
  }
31193
31625
  try {
31194
31626
  const found = execSync2(process.platform === "win32" ? "where node" : "command -v node", { encoding: "utf8", timeout: 3e3 }).split(/\r?\n/)[0].trim();
31195
- if (found && existsSync8(found))
31627
+ if (found && existsSync9(found))
31196
31628
  return cachedNodeExe2 = found;
31197
31629
  } catch {
31198
31630
  }
@@ -31626,11 +32058,11 @@ function buildMobileClause(dir2) {
31626
32058
  try {
31627
32059
  let fw = "";
31628
32060
  let runCmd = "";
31629
- if (existsSync8(join18(dir2, "pubspec.yaml"))) {
32061
+ if (existsSync9(join18(dir2, "pubspec.yaml"))) {
31630
32062
  fw = "Flutter";
31631
32063
  runCmd = "flutter run -d chrome";
31632
- } else if (existsSync8(join18(dir2, "package.json"))) {
31633
- const pkg = JSON.parse(readFileSync14(join18(dir2, "package.json"), "utf8"));
32064
+ } else if (existsSync9(join18(dir2, "package.json"))) {
32065
+ const pkg = JSON.parse(readFileSync15(join18(dir2, "package.json"), "utf8"));
31634
32066
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
31635
32067
  if (deps.expo) {
31636
32068
  fw = "Expo";
@@ -31713,6 +32145,8 @@ var init_agent_manager = __esm({
31713
32145
  init_plan_splitter();
31714
32146
  init_unattended();
31715
32147
  init_reinforced_verification();
32148
+ init_unattended_log();
32149
+ init_context_recovery();
31716
32150
  init_dist();
31717
32151
  init_dist();
31718
32152
  init_base_paths();
@@ -31887,6 +32321,15 @@ var init_agent_manager = __esm({
31887
32321
  * the host (setVerifierLlm); null ⇒ reinforced verification cannot grade, and says so
31888
32322
  * rather than letting a run pass unverified. */
31889
32323
  verifierLlm = null;
32324
+ /** The user's auto-compact threshold, read from the DAEMON's settings snapshot.
32325
+ *
32326
+ * Exists because the desktop-only route does not cover an unattended run. The threshold
32327
+ * normally reaches the CLI as `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` inside `params.env`,
32328
+ * which the desktop main process fills in per send (`getAgentSettings`) — so a turn the
32329
+ * DAEMON originates (a cron fire, or anything sent while the app is closed) carried no
32330
+ * threshold at all and ran at the CLI's own default instead of the number the user set.
32331
+ * The other three engines already read this daemon-side at spawn; this is Claude's. */
32332
+ autoCompactPct = null;
31890
32333
  /** Plugin-contributed Pre/PostToolUse hooks (Epic G). Appended (never replacing) the
31891
32334
  * built-in edit-capture hooks at session start. */
31892
32335
  pluginHooks = [];
@@ -32158,7 +32601,7 @@ var init_agent_manager = __esm({
32158
32601
  constructor(rawSend2, onBrowserRequest) {
32159
32602
  this.rawSend = rawSend2;
32160
32603
  this.onBrowserRequest = onBrowserRequest;
32161
- const __dirname = dirname7(fileURLToPath(import.meta.url));
32604
+ const __dirname = dirname8(fileURLToPath(import.meta.url));
32162
32605
  this.browserCliPath = join18(__dirname, "browser-cli.js");
32163
32606
  this.narrator = new Narrator((sessionId, text9, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text9, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
32164
32607
  }
@@ -32168,6 +32611,131 @@ var init_agent_manager = __esm({
32168
32611
  setVerifierLlm(fn) {
32169
32612
  this.verifierLlm = fn;
32170
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
+ }
32673
+ /**
32674
+ * Compact and resume after this session outgrew the window, when nobody is watching.
32675
+ *
32676
+ * Returns true when the recovery was dispatched, in which case the caller must NOT report
32677
+ * the turn as finished — the run continues on a reclaimed window.
32678
+ *
32679
+ * The two sends mirror the renderer's `continueLastTurn(id, 'context_window')` exactly,
32680
+ * because they have to agree: `/compact` alone just compacts and stops, and the resume
32681
+ * alone overflows again. Both ride `autoContinuation`, which is what tells the rest of
32682
+ * the manager this is the SAME run — without it the verification loop would re-anchor on
32683
+ * the literal request "Continue.", which the very next turn satisfies by construction.
32684
+ */
32685
+ async recoverContextOverflow(live, turnSid) {
32686
+ return recoverFromContextOverflow({
32687
+ mode: () => live.unattended ?? "off",
32688
+ // Claude takes `/compact` as a real slash command.
32689
+ canCompact: () => true,
32690
+ tries: () => live.overflowTries ?? 0,
32691
+ bump: () => {
32692
+ live.overflowTries = (live.overflowTries ?? 0) + 1;
32693
+ },
32694
+ context: { sessionId: turnSid, engine: "claude-code" },
32695
+ log: (m, err2) => log(m, err2 instanceof Error ? err2.message : err2 !== void 0 ? String(err2) : ""),
32696
+ compactAndResume: async () => {
32697
+ const base = {
32698
+ url: "",
32699
+ sessionId: live.sessionId,
32700
+ projectDir: live.cwd,
32701
+ origin: live.origin,
32702
+ browserId: live.browserId,
32703
+ windowId: live.windowId,
32704
+ autoContinuation: true,
32705
+ ...live.unattended === "auto" ? { unattended: true } : {},
32706
+ ...live.model ? { model: live.model } : {}
32707
+ };
32708
+ live.overflowCompacting = true;
32709
+ try {
32710
+ await this.sendMessage({ ...base, message: OVERFLOW_COMPACT_MESSAGE });
32711
+ } finally {
32712
+ live.overflowCompacting = false;
32713
+ }
32714
+ await this.sendMessage({ ...base, message: OVERFLOW_RESUME_MESSAGE });
32715
+ }
32716
+ });
32717
+ }
32718
+ /** Inject the daemon's view of the auto-compact threshold. Read at SPAWN, never
32719
+ * captured, so flipping the slider at 23:00 reaches a session started at 03:00. */
32720
+ setAutoCompactPct(fn) {
32721
+ this.autoCompactPct = fn;
32722
+ }
32723
+ /**
32724
+ * `CLAUDE_AUTOCOMPACT_PCT_OVERRIDE` for a spawn the desktop did not configure.
32725
+ *
32726
+ * Empty whenever the caller already supplied one (the desktop's per-send env wins), when
32727
+ * no provider is wired, or when the number is not a usable percentage — 0 and 100 both
32728
+ * mean "no proactive compaction", and writing either would turn the CLI's own default
32729
+ * OFF rather than leaving it alone. Never throws: a settings read that fails must not
32730
+ * take the spawn with it.
32731
+ */
32732
+ daemonCompactEnv(supplied) {
32733
+ try {
32734
+ return autoCompactEnvFor(this.autoCompactPct?.(), supplied);
32735
+ } catch {
32736
+ return {};
32737
+ }
32738
+ }
32171
32739
  setNarrationLlm(cfg2) {
32172
32740
  this.narrator.setConfig(cfg2);
32173
32741
  this.cheapLlm = cfg2?.complete ?? null;
@@ -32353,7 +32921,7 @@ ${full.slice(-8e3)}`;
32353
32921
  if (live.rvGrading === rv)
32354
32922
  return;
32355
32923
  live.rvGrading = rv;
32356
- const gate = rv.phase === "review" ? "review" : "completeness";
32924
+ const gate = rv.phase === "review" ? "review" : rv.phase === "phase-review" ? "phase" : "completeness";
32357
32925
  let owned = rv;
32358
32926
  const evtSessionId = live.sessionId;
32359
32927
  const evtCrid = live.clientRequestId;
@@ -32366,7 +32934,7 @@ ${full.slice(-8e3)}`;
32366
32934
  this.send(evt, evtOrigin);
32367
32935
  };
32368
32936
  try {
32369
- if (!didWork && gate !== "review") {
32937
+ if (!didWork && gate === "completeness") {
32370
32938
  emitVerification({ action: "done", gate, cycle: rv.cycles, maxCycles: RV_MAX_CYCLES, unavailable: "This turn used no tools, so there was nothing to verify." });
32371
32939
  return;
32372
32940
  }
@@ -32377,7 +32945,7 @@ ${full.slice(-8e3)}`;
32377
32945
  return;
32378
32946
  }
32379
32947
  const todos = live.todos?.map((t) => ({ content: t.content, status: String(t.status) }));
32380
- const call3 = gate === "review" ? reviewGrade(rv.task, finalText) : completenessGrade(rv.task, finalText, todos);
32948
+ const call3 = gate === "review" ? reviewGrade(rv, finalText, todos) : gate === "phase" ? phaseGrade(rv, rv.lastVerdict?.phaseName ?? "", finalText, todos) : completenessGrade(rv, finalText, todos);
32381
32949
  const raw = await llm({ model: live.model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema });
32382
32950
  if (live.rv !== rv || live.reaped) {
32383
32951
  if (live.reaped || live.rv === void 0) {
@@ -32391,14 +32959,31 @@ ${full.slice(-8e3)}`;
32391
32959
  live.rv = { ...rv, phase: "done" };
32392
32960
  return;
32393
32961
  }
32962
+ if (!rv.plan && finalText.trim())
32963
+ rv.plan = finalText.slice(0, 4e3);
32394
32964
  const action = rvDecision(verdict, rv);
32395
32965
  const nextState = rvAdvance(rv, action, verdict);
32396
32966
  live.rv = nextState;
32397
32967
  owned = nextState;
32398
32968
  emitVerification({ action: action.kind, gate, cycle: nextState.cycles, maxCycles: RV_MAX_CYCLES, verdict });
32399
32969
  log(`reinforced-verification: ${gate} \u2192 ${action.kind} (cycle ${nextState.cycles}/${RV_MAX_CYCLES}, ${verdict.issues.length} issue(s), complete=${verdict.taskComplete})`);
32970
+ recordVerificationDecision({
32971
+ sessionId: live.sessionId,
32972
+ engine: "claude-code",
32973
+ gate,
32974
+ action: action.kind,
32975
+ cycle: nextState.cycles,
32976
+ phasesDone: nextState.phasesDone,
32977
+ phaseName: verdict.phaseName,
32978
+ taskComplete: verdict.taskComplete,
32979
+ phaseComplete: verdict.phaseComplete,
32980
+ exercised: verdict.exercised,
32981
+ blocking: blockingIssues(verdict).length,
32982
+ summary: verdict.summary
32983
+ });
32400
32984
  if (action.kind === "done" || action.kind === "capped")
32401
32985
  return;
32986
+ await this.maybeCompactProactively(live);
32402
32987
  await this.sendMessage({
32403
32988
  message: action.prompt,
32404
32989
  url: "",
@@ -32476,6 +33061,7 @@ ${full.slice(-8e3)}`;
32476
33061
  * Abandoning it is a hang — the precise failure this whole path exists to prevent. */
32477
33062
  autoAnswerPrompt(live, requestId, prompt, apply2) {
32478
33063
  scheduleUnattendedAnswer(prompt, {
33064
+ context: { sessionId: live.sessionId, engine: "claude-code" },
32479
33065
  mode: () => live.unattended ?? "off",
32480
33066
  charge: () => live.autoDecisions = (live.autoDecisions ?? 0) + 1,
32481
33067
  // Relative, not absolute — siblings can be mid-window; see the deps doc.
@@ -32890,7 +33476,7 @@ ${qText}`;
32890
33476
  if (!file2)
32891
33477
  return { ok: false, reason: "This conversation has no transcript on this machine." };
32892
33478
  try {
32893
- const before = parseTranscript(readFileSync14(file2, "utf8"));
33479
+ const before = parseTranscript(readFileSync15(file2, "utf8"));
32894
33480
  const want = typeof locator === "string" ? { uuid: locator } : locator;
32895
33481
  const uuid3 = want.uuid ?? (want.text ? findUserEntryByText(before, want.text)?.uuid : void 0);
32896
33482
  if (!uuid3) {
@@ -32905,7 +33491,7 @@ ${qText}`;
32905
33491
  }
32906
33492
  const tmp = `${file2}.tmp-${randomUUID6().slice(0, 8)}`;
32907
33493
  writeFileSync10(tmp, serializeTranscript(res.entries), { mode: 384 });
32908
- renameSync6(tmp, file2);
33494
+ renameSync7(tmp, file2);
32909
33495
  log(`Removed ${res.removed.length} transcript entr${res.removed.length === 1 ? "y" : "ies"} from ${sessionId}; re-parented ${res.relinked.length}.`);
32910
33496
  if (live) {
32911
33497
  try {
@@ -33300,12 +33886,12 @@ ${qText}`;
33300
33886
  const cli = `ELECTRON_RUN_AS_NODE=1 "${process.execPath}" "${this.browserCliPath}"`;
33301
33887
  const pageInfo = url2 ? `
33302
33888
  The user's current browser tab is: ${url2}` : "";
33303
- const designClause = this.projectDir && existsSync8(join18(this.projectDir, TOKENS_FILE)) ? `
33889
+ const designClause = this.projectDir && existsSync9(join18(this.projectDir, TOKENS_FILE)) ? `
33304
33890
 
33305
33891
  DESIGN SYSTEM:
33306
33892
  - This project has a design system at design-system/tokens.json. For any UI you build or edit, use those tokens (colors, spacing, typography, radius) \u2014 call read_design_tokens to read values, set them with write_design_token, and NEVER hardcode hex/sizes that duplicate a token.` : "";
33307
33893
  const mobileClause = this.projectDir ? buildMobileClause(this.projectDir) : "";
33308
- const buildClause = this.projectDir && existsSync8(join18(this.projectDir, ".tesseract", "brief.md")) ? `
33894
+ const buildClause = this.projectDir && existsSync9(join18(this.projectDir, ".tesseract", "brief.md")) ? `
33309
33895
 
33310
33896
  WEBSITE BUILD MODE:
33311
33897
  This is a guided website build. Read \`.tesseract/brief.md\` (the user's brief), \`design-system/reference.html\` (the chosen template \u2014 the visual/structural spec) and \`design-system/tokens.json\` (the theme). Protocol:
@@ -33359,8 +33945,8 @@ CRITICAL RULES:
33359
33945
  const match = f.dataUrl.match(/^data:[^;]*;base64,(.+)$/);
33360
33946
  if (!match)
33361
33947
  continue;
33362
- const safe = (f.name || `file-${i}`).replace(/[^\w.\-]+/g, "_").slice(-100);
33363
- const filePath = join18(fileDir, `${process.pid}-${Date.now()}-${randomUUID6().slice(0, 8)}-${i}-${safe}`);
33948
+ const safe2 = (f.name || `file-${i}`).replace(/[^\w.\-]+/g, "_").slice(-100);
33949
+ const filePath = join18(fileDir, `${process.pid}-${Date.now()}-${randomUUID6().slice(0, 8)}-${i}-${safe2}`);
33364
33950
  await writeFile4(filePath, Buffer.from(match[1], "base64"));
33365
33951
  paths.push(filePath);
33366
33952
  }
@@ -33518,7 +34104,7 @@ CRITICAL RULES:
33518
34104
  let pinnedSource;
33519
34105
  if (params.sessionId) {
33520
34106
  const originCwd = findSessionCwd(params.sessionId, params.engineEnv?.CLAUDE_CONFIG_DIR ?? params.env?.CLAUDE_CONFIG_DIR);
33521
- if (originCwd && originCwd !== openProject && existsSync8(originCwd)) {
34107
+ if (originCwd && originCwd !== openProject && existsSync9(originCwd)) {
33522
34108
  log(`Resuming ${params.sessionId} in its ORIGINAL cwd ${originCwd} (open project ${openProject} added as a source)`);
33523
34109
  cwd = originCwd;
33524
34110
  pinnedSource = openProject;
@@ -34166,9 +34752,18 @@ CRITICAL RULES:
34166
34752
  ...identityEnv(),
34167
34753
  ...options.env,
34168
34754
  // params.env carries CLAUDE_AUTOCOMPACT_PCT_OVERRIDE from the user's setting
34169
- // (getAgentSettings) — IF this CLI honours it, native mid-run compaction fires
34170
- // 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.
34171
34761
  ...params.env ?? {},
34762
+ // FALLBACK, not an override: `params.env` wins whenever the desktop supplied a
34763
+ // threshold. This fills the gap for a turn the daemon originated itself, which
34764
+ // carries no env — without it an unattended run compacts at the CLI's default
34765
+ // rather than the number in the run-mode menu.
34766
+ ...this.daemonCompactEnv(params.env),
34172
34767
  ...params.engineEnv ?? {},
34173
34768
  CCB_IPC_PORT: String(live.ipcPort)
34174
34769
  };
@@ -34208,9 +34803,16 @@ CRITICAL RULES:
34208
34803
  // restores the SDK's dynamic command list, gitStatus/date context,
34209
34804
  // env-info and memory/CLAUDE.md preamble that a bare custom string
34210
34805
  // prompt suppresses — while `append` keeps the Tesseract browser tools.
34806
+ // The phase directive rides here when verification is armed. It has to be in the
34807
+ // SYSTEM prompt, not prepended to the user's message: the loop only speaks at turn
34808
+ // END, so without this the agent has already built the whole thing monolithically by
34809
+ // the time anything can ask it to work in slices — and rewriting the user's message
34810
+ // is the mistake that made `/compact` the graded task.
34211
34811
  systemPrompt: { type: "preset", preset: "claude_code", append: this.applyPromptHook(this.buildSystemPrompt(params.url) + (params.appendSystemPrompt ? `
34212
34812
 
34213
- ${params.appendSystemPrompt}` : ""), live.sessionId) },
34813
+ ${params.appendSystemPrompt}` : "") + (params.reinforcedVerification ? `
34814
+
34815
+ ${RV_PHASE_DIRECTIVE}` : ""), live.sessionId) },
34214
34816
  includePartialMessages: true,
34215
34817
  // Emit a predicted follow-up prompt after each turn (git/context-aware) — rendered
34216
34818
  // as a clickable suggestion chip. Off by default in the SDK, so opt in here.
@@ -34566,9 +35168,13 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
34566
35168
  });
34567
35169
  }
34568
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);
34569
35173
  if (limitRejection) {
34570
35174
  reportUsageLimit(limitRejection, turnSid);
34571
- } else if (r.subtype === "success") {
35175
+ } else if (r.subtype === "success" && !textOverflow) {
35176
+ if (!live.overflowCompacting)
35177
+ live.overflowTries = 0;
34572
35178
  if (!turnStreamed && Array.isArray(live.lastAssistantContent)) {
34573
35179
  for (const blk of live.lastAssistantContent) {
34574
35180
  if (blk?.type === "thinking" && typeof blk.thinking === "string" && blk.thinking) {
@@ -34605,6 +35211,8 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
34605
35211
  const didWork = typeof r.num_turns !== "number" || r.num_turns > 1;
34606
35212
  if (live.rv && !continuable)
34607
35213
  void this.runVerification(live, typeof r.result === "string" ? r.result : "", didWork);
35214
+ else
35215
+ void this.maybeCompactProactively(live);
34608
35216
  } else if (live.interrupted) {
34609
35217
  live.interrupted = false;
34610
35218
  this.clearStopWatchdog(live);
@@ -34613,13 +35221,16 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
34613
35221
  emit2({ type: "agent:status", sessionId: turnSid, status: "idle" });
34614
35222
  } else {
34615
35223
  const errors = Array.isArray(r.errors) ? r.errors.map(String).filter(Boolean) : [];
34616
- const detail = errors.length > 0 ? errors.join("\n") : `Agent returned ${r.subtype}${r.stop_reason ? ` (stop_reason: ${r.stop_reason})` : ""}`;
34617
- 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;
34618
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);
34619
35227
  log("Session result error:", turnSid, JSON.stringify({ subtype: r.subtype, stop_reason: r.stop_reason, errors, looksTransient }));
34620
35228
  live.resultErrorReported = true;
34621
- emit2({ type: "chat:error", sessionId: turnSid, error: detail, ...contextHit ? { continuable: true, continueReason: contextHit } : looksTransient ? { transient: true } : {} });
34622
- emit2({ type: "agent:status", sessionId: turnSid, status: contextHit ? "idle" : "error" });
35229
+ const recovered = contextHit === "context_window" && await this.recoverContextOverflow(live, turnSid);
35230
+ if (!recovered) {
35231
+ emit2({ type: "chat:error", sessionId: turnSid, error: detail, ...contextHit ? { continuable: true, continueReason: contextHit } : looksTransient ? { transient: true } : {} });
35232
+ emit2({ type: "agent:status", sessionId: turnSid, status: contextHit ? "idle" : "error" });
35233
+ }
34623
35234
  }
34624
35235
  blockAcc.clear();
34625
35236
  insideXmlByKey.clear();
@@ -35678,8 +36289,12 @@ __export(dist_exports2, {
35678
36289
  DesignTokensSchema: () => DesignTokensSchema,
35679
36290
  DtcgTokensSchema: () => DtcgTokensSchema,
35680
36291
  HookBus: () => HookBus,
36292
+ OVERFLOW_COMPACT_MESSAGE: () => OVERFLOW_COMPACT_MESSAGE,
36293
+ OVERFLOW_MAX_TRIES: () => OVERFLOW_MAX_TRIES,
36294
+ OVERFLOW_RESUME_MESSAGE: () => OVERFLOW_RESUME_MESSAGE,
35681
36295
  PRESENT_TOOL_NAMES: () => PRESENT_TOOL_NAMES,
35682
36296
  PRESENT_TOOL_SPECS: () => PRESENT_TOOL_SPECS,
36297
+ PROACTIVE_REGROWTH_POINTS: () => PROACTIVE_REGROWTH_POINTS,
35683
36298
  SCREEN_CONTROL_SPECS: () => SCREEN_CONTROL_SPECS,
35684
36299
  SessionStore: () => SessionStore,
35685
36300
  TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
@@ -35691,6 +36306,7 @@ __export(dist_exports2, {
35691
36306
  appendImageArtifact: () => appendImageArtifact,
35692
36307
  appendSurfaceArtifact: () => appendSurfaceArtifact,
35693
36308
  applyDesignPack: () => applyDesignPack,
36309
+ autoCompactEnvFor: () => autoCompactEnvFor,
35694
36310
  buildAppControlTools: () => buildAppControlTools,
35695
36311
  buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
35696
36312
  buildClaudeSmartLlm: () => buildClaudeSmartLlm,
@@ -35724,6 +36340,9 @@ __export(dist_exports2, {
35724
36340
  normalizeTokens: () => normalizeTokens,
35725
36341
  parseColorToRgb: () => parseColorToRgb,
35726
36342
  readSessionArtifacts: () => readSessionArtifacts,
36343
+ readUnattendedDecisions: () => readUnattendedDecisions,
36344
+ recordUnattendedDecision: () => recordUnattendedDecision,
36345
+ recoverFromContextOverflow: () => recoverFromContextOverflow,
35727
36346
  renderAppControlReference: () => renderAppControlReference,
35728
36347
  resolveNodeExecutable: () => resolveNodeExecutable,
35729
36348
  resolveOauthToken: () => resolveOauthToken,
@@ -35737,6 +36356,8 @@ __export(dist_exports2, {
35737
36356
  setBrowserExtensionProbe: () => setBrowserExtensionProbe,
35738
36357
  setTokenPath: () => setTokenPath,
35739
36358
  setTokenSegments: () => setTokenSegments,
36359
+ setUnattendedLogSink: () => setUnattendedLogSink,
36360
+ shouldCompactProactively: () => shouldCompactProactively,
35740
36361
  specParametersJsonSchema: () => specParametersJsonSchema,
35741
36362
  stringifyValue: () => stringifyValue,
35742
36363
  stripPromptPrefix: () => stripPromptPrefix,
@@ -35747,6 +36368,7 @@ __export(dist_exports2, {
35747
36368
  toolSpecJsonSchema: () => specParametersJsonSchema,
35748
36369
  transferSession: () => transferSession,
35749
36370
  unattendedAnswer: () => unattendedAnswer,
36371
+ unattendedLogPath: () => unattendedLogPath,
35750
36372
  unattendedModeFor: () => unattendedModeFor,
35751
36373
  walkTokens: () => walkTokens,
35752
36374
  wrapCtxTool: () => wrapCtxTool,
@@ -35759,6 +36381,8 @@ var init_dist5 = __esm({
35759
36381
  init_session_store();
35760
36382
  init_session_usage();
35761
36383
  init_unattended();
36384
+ init_unattended_log();
36385
+ init_context_recovery();
35762
36386
  init_session_transfer();
35763
36387
  init_log();
35764
36388
  init_kill_tree();
@@ -35789,7 +36413,7 @@ __export(tesseract_mcp_endpoint_exports, {
35789
36413
  startTesseractMcpEndpoint: () => startTesseractMcpEndpoint
35790
36414
  });
35791
36415
  import { createServer as createServer3 } from "node:http";
35792
- import { readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "node:fs";
36416
+ import { readFileSync as readFileSync16, writeFileSync as writeFileSync11 } from "node:fs";
35793
36417
  import { join as join20 } from "node:path";
35794
36418
  function readBody2(req, limitBytes = 4 * 1024 * 1024) {
35795
36419
  return new Promise((resolve16, reject) => {
@@ -35818,7 +36442,7 @@ function portFile() {
35818
36442
  }
35819
36443
  function rememberedPort() {
35820
36444
  try {
35821
- const o = JSON.parse(readFileSync15(portFile(), "utf8"));
36445
+ const o = JSON.parse(readFileSync16(portFile(), "utf8"));
35822
36446
  return typeof o.port === "number" && o.port > 1024 ? o.port : 0;
35823
36447
  } catch {
35824
36448
  return 0;
@@ -35959,7 +36583,7 @@ __export(serpapi_runner_exports, {
35959
36583
  createDaemonSerpClient: () => createDaemonSerpClient,
35960
36584
  resolveSerpCreds: () => resolveSerpCreds
35961
36585
  });
35962
- import { existsSync as existsSync9, readFileSync as readFileSync16 } from "node:fs";
36586
+ import { existsSync as existsSync10, readFileSync as readFileSync17 } from "node:fs";
35963
36587
  function resolveSerpCreds() {
35964
36588
  const snap = readDaemonAgentSettings().serp;
35965
36589
  if (snap?.apiKey?.trim()) {
@@ -35974,8 +36598,8 @@ function resolveSerpCreds() {
35974
36598
  };
35975
36599
  }
35976
36600
  const file2 = daemonPath("serpapi.key");
35977
- if (existsSync9(file2)) {
35978
- const k = readFileSync16(file2, "utf-8").trim();
36601
+ if (existsSync10(file2)) {
36602
+ const k = readFileSync17(file2, "utf-8").trim();
35979
36603
  if (k)
35980
36604
  return { apiKey: k, tier: "own", source: "key-file" };
35981
36605
  }
@@ -62997,8 +63621,8 @@ var require_selfsigned = __commonJS({
62997
63621
  // ../../packages/host-core/dist/peer-link/tls-direct.js
62998
63622
  import tls from "node:tls";
62999
63623
  import { X509Certificate, timingSafeEqual as timingSafeEqual2 } from "node:crypto";
63000
- import { readFileSync as readFileSync32, writeFileSync as writeFileSync22, existsSync as existsSync19, mkdirSync as mkdirSync22 } from "node:fs";
63001
- import { dirname as dirname17 } from "node:path";
63624
+ import { readFileSync as readFileSync33, writeFileSync as writeFileSync22, existsSync as existsSync20, mkdirSync as mkdirSync23 } from "node:fs";
63625
+ import { dirname as dirname18 } from "node:path";
63002
63626
  function fingerprintOf(certPem) {
63003
63627
  return new X509Certificate(certPem).fingerprint256;
63004
63628
  }
@@ -63010,15 +63634,15 @@ function fingerprintsEqual(a, b) {
63010
63634
  return ba.length === bb.length && timingSafeEqual2(ba, bb);
63011
63635
  }
63012
63636
  async function loadOrCreateIdentity(certPath, keyPath) {
63013
- if (existsSync19(certPath) && existsSync19(keyPath)) {
63014
- const cert = readFileSync32(certPath, "utf8");
63015
- const key2 = readFileSync32(keyPath, "utf8");
63637
+ if (existsSync20(certPath) && existsSync20(keyPath)) {
63638
+ const cert = readFileSync33(certPath, "utf8");
63639
+ const key2 = readFileSync33(keyPath, "utf8");
63016
63640
  return { cert, key: key2, fingerprint256: fingerprintOf(cert) };
63017
63641
  }
63018
63642
  const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
63019
63643
  const pems = await (0, import_selfsigned.generate)([{ name: "commonName", value: "tesseract-peer" }], { keySize: 2048, notAfterDate: tenYears, algorithm: "sha256" });
63020
63644
  try {
63021
- mkdirSync22(dirname17(certPath), { recursive: true });
63645
+ mkdirSync23(dirname18(certPath), { recursive: true });
63022
63646
  } catch {
63023
63647
  }
63024
63648
  try {
@@ -70813,7 +71437,7 @@ var mesh_ca_exports = {};
70813
71437
  __export(mesh_ca_exports, {
70814
71438
  netCaCommand: () => netCaCommand
70815
71439
  });
70816
- import { chmodSync as chmodSync8, existsSync as existsSync41, mkdirSync as mkdirSync41, readFileSync as readFileSync47, writeFileSync as writeFileSync42 } from "node:fs";
71440
+ import { chmodSync as chmodSync8, existsSync as existsSync42, mkdirSync as mkdirSync42, readFileSync as readFileSync48, writeFileSync as writeFileSync42 } from "node:fs";
70817
71441
  import { join as join76, resolve as resolve13 } from "node:path";
70818
71442
  import { createInterface } from "node:readline";
70819
71443
  function die(msg) {
@@ -70852,7 +71476,7 @@ function writeSecretFile(p, bytes2) {
70852
71476
  }
70853
71477
  }
70854
71478
  function ensureDir(p) {
70855
- mkdirSync41(p, { recursive: true, mode: 448 });
71479
+ mkdirSync42(p, { recursive: true, mode: 448 });
70856
71480
  try {
70857
71481
  chmodSync8(p, 448);
70858
71482
  } catch {
@@ -70861,12 +71485,12 @@ function ensureDir(p) {
70861
71485
  async function openCa(dir2) {
70862
71486
  const gPath = join76(dir2, "genesis.bin");
70863
71487
  const sPath = join76(dir2, "ca.sealed");
70864
- if (!existsSync41(gPath) || !existsSync41(sPath)) {
71488
+ if (!existsSync42(gPath) || !existsSync42(sPath)) {
70865
71489
  die(`No mesh CA in ${dir2}. Run: tesseract-agent net init --org NAME --ca-dir ${dir2}`);
70866
71490
  }
70867
- const genesisBytes = new Uint8Array(readFileSync47(gPath));
71491
+ const genesisBytes = new Uint8Array(readFileSync48(gPath));
70868
71492
  const genesis = decodeGenesis(genesisBytes);
70869
- const sealed = decodeRecoveryBundle(new Uint8Array(readFileSync47(sPath)));
71493
+ const sealed = decodeRecoveryBundle(new Uint8Array(readFileSync48(sPath)));
70870
71494
  const pass = await readPassphrase("CA passphrase: ");
70871
71495
  let seed;
70872
71496
  try {
@@ -70882,7 +71506,7 @@ async function netCaCommand(rest, flags) {
70882
71506
  if (sub === "init") {
70883
71507
  const org = typeof flags.org === "string" ? flags.org.trim() : "";
70884
71508
  if (!org) die("Usage: tesseract-agent net init --org NAME [--ca-dir DIR]");
70885
- if (existsSync41(join76(caDir, "ca.sealed"))) {
71509
+ if (existsSync42(join76(caDir, "ca.sealed"))) {
70886
71510
  die(`A mesh CA already exists in ${caDir}. Refusing to overwrite it.`);
70887
71511
  }
70888
71512
  const pass = await readPassphrase("New CA passphrase: ");
@@ -71040,12 +71664,12 @@ var init_mesh_ca = __esm({
71040
71664
 
71041
71665
  // src/cli.ts
71042
71666
  init_base_paths();
71043
- import { existsSync as existsSync42, mkdtempSync as mkdtempSync2, readFileSync as readFileSync49, rmSync as rmSync11 } from "node:fs";
71667
+ import { existsSync as existsSync43, mkdtempSync as mkdtempSync2, readFileSync as readFileSync50, rmSync as rmSync11 } from "node:fs";
71044
71668
  import { createHash as createHash8 } from "node:crypto";
71045
71669
  import { execFileSync as execFileSync6, spawn as spawn16 } from "node:child_process";
71046
71670
  import { fileURLToPath as fileURLToPath6 } from "node:url";
71047
71671
  import { tmpdir as tmpdir6 } from "node:os";
71048
- import { dirname as dirname31, join as join77, resolve as resolve15 } from "node:path";
71672
+ import { dirname as dirname32, join as join77, resolve as resolve15 } from "node:path";
71049
71673
  import { createInterface as createInterface2 } from "node:readline/promises";
71050
71674
 
71051
71675
  // ../../packages/host-core/dist/control-link.js
@@ -71075,7 +71699,7 @@ function toRewindOutcome(res, noHistory) {
71075
71699
  // ../../packages/host-core/dist/control-link.js
71076
71700
  import { join as join53, basename as basename11 } from "node:path";
71077
71701
  import { randomUUID as randomUUID22 } from "node:crypto";
71078
- import { mkdirSync as mkdirSync26 } from "node:fs";
71702
+ import { mkdirSync as mkdirSync27 } from "node:fs";
71079
71703
 
71080
71704
  // ../../node_modules/ws/wrapper.mjs
71081
71705
  var import_stream = __toESM(require_stream(), 1);
@@ -72384,6 +73008,7 @@ async function createClaudeCodeBackend(send4, onBrowserRequest, loadPluginRuntim
72384
73008
  send4(msg, origin);
72385
73009
  };
72386
73010
  const manager2 = new AgentManager2(sendWatchingSessions, onBrowserRequest);
73011
+ manager2.setAutoCompactPct(() => readDaemonAgentSettings().autoCompactPct);
72387
73012
  const claudeSnapshots = createSnapshotStore(join19(daemonDir(), "engine-snapshots", "claude-code.json"));
72388
73013
  const claudeTurnSeq = /* @__PURE__ */ new Map();
72389
73014
  const pendingAlias = /* @__PURE__ */ new Map();
@@ -73162,7 +73787,7 @@ function geminiMessageText(m) {
73162
73787
  }
73163
73788
 
73164
73789
  // ../../packages/host-core/dist/engines/hosted-verification.js
73165
- function createHostedVerification() {
73790
+ function createHostedVerification(engineId) {
73166
73791
  let verifier = null;
73167
73792
  return {
73168
73793
  setVerifier: (fn) => {
@@ -73171,6 +73796,7 @@ function createHostedVerification() {
73171
73796
  canGrade: () => verifier !== null,
73172
73797
  async run({ sessionId, task, finalText, todos, reprompt, emit: emit2, model, clientRequestId, cancelled }) {
73173
73798
  const rv = await Promise.resolve().then(() => (init_reinforced_verification(), reinforced_verification_exports));
73799
+ const ulog = await Promise.resolve().then(() => (init_unattended_log(), unattended_log_exports));
73174
73800
  const base = { type: "agent:verification", sessionId, ...clientRequestId ? { clientRequestId } : {}, maxCycles: rv.RV_MAX_CYCLES };
73175
73801
  const standDown = (cycle, unavailable) => {
73176
73802
  emit2({ ...base, action: "done", gate: "completeness", cycle, unavailable });
@@ -73189,11 +73815,14 @@ function createHostedVerification() {
73189
73815
  }
73190
73816
  const grade = verifier;
73191
73817
  let state3 = rv.newRvState(task);
73818
+ if (finalText.trim())
73819
+ state3 = { ...state3, plan: finalText.slice(0, 4e3) };
73192
73820
  let text9 = finalText;
73193
73821
  let reviewText = "";
73194
- for (let i = 0; i < rv.RV_MAX_CYCLES * 2 + 2; i++) {
73195
- const gate = state3.phase === "review" ? "review" : "completeness";
73196
- const call3 = gate === "review" ? rv.reviewGrade(task, reviewText || text9) : rv.completenessGrade(task, text9, todos);
73822
+ let phaseText = "";
73823
+ for (let i = 0; i < rv.RV_MAX_CYCLES * 5 + 4; i++) {
73824
+ const gate = state3.phase === "review" ? "review" : state3.phase === "phase-review" ? "phase" : "completeness";
73825
+ const call3 = gate === "review" ? rv.reviewGrade(state3, reviewText || text9, todos) : gate === "phase" ? rv.phaseGrade(state3, state3.lastVerdict?.phaseName ?? "", phaseText || text9, todos) : rv.completenessGrade(state3, text9, todos);
73197
73826
  let verdict = null;
73198
73827
  try {
73199
73828
  verdict = rv.parseVerdict(await grade({ model, system: call3.system, prompt: call3.prompt, maxTokens: 16e3, schema: call3.schema }));
@@ -73214,6 +73843,20 @@ function createHostedVerification() {
73214
73843
  const action = rv.rvDecision(verdict, state3);
73215
73844
  state3 = rv.rvAdvance(state3, action, verdict);
73216
73845
  emit2({ ...base, action: action.kind, gate, cycle: state3.cycles, verdict });
73846
+ ulog.recordVerificationDecision({
73847
+ sessionId,
73848
+ ...engineId ? { engine: engineId } : {},
73849
+ gate,
73850
+ action: action.kind,
73851
+ cycle: state3.cycles,
73852
+ phasesDone: state3.phasesDone,
73853
+ phaseName: verdict.phaseName,
73854
+ taskComplete: verdict.taskComplete,
73855
+ phaseComplete: verdict.phaseComplete,
73856
+ exercised: verdict.exercised,
73857
+ blocking: rv.blockingIssues(verdict).length,
73858
+ summary: verdict.summary
73859
+ });
73217
73860
  if (action.kind === "done" || action.kind === "capped")
73218
73861
  return text9;
73219
73862
  try {
@@ -73224,15 +73867,18 @@ function createHostedVerification() {
73224
73867
  return text9;
73225
73868
  }
73226
73869
  }
73227
- const before = action.kind === "review" ? reviewText : text9;
73870
+ const before = action.kind === "review" ? reviewText : action.kind === "phase-review" ? phaseText : text9;
73228
73871
  const reply3 = await reprompt(action.prompt);
73229
73872
  if (!reply3 || reply3 === before) {
73230
73873
  standDown(state3.cycles, "The agent did not produce anything new when sent back, so this run was not verified.");
73231
73874
  return text9;
73232
73875
  }
73233
- if (action.kind !== "review")
73876
+ if (action.kind === "review")
73877
+ reviewText = reply3;
73878
+ else if (action.kind === "phase-review")
73879
+ phaseText = reply3;
73880
+ else
73234
73881
  text9 = reply3;
73235
- reviewText = action.kind === "review" ? reply3 : reviewText;
73236
73882
  } catch {
73237
73883
  standDown(state3.cycles, "Verification could not be completed, so this run was not verified.");
73238
73884
  return text9;
@@ -73246,7 +73892,7 @@ function createHostedVerification() {
73246
73892
 
73247
73893
  // ../../packages/host-core/dist/engines/model-pricing.js
73248
73894
  init_credentials();
73249
- import { readFileSync as readFileSync17, writeFileSync as writeFileSync12 } from "node:fs";
73895
+ import { readFileSync as readFileSync18, writeFileSync as writeFileSync12 } from "node:fs";
73250
73896
  import { join as join22 } from "node:path";
73251
73897
  var LITELLM_URL = "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json";
73252
73898
  var MODELS_DEV_URL = "https://models.dev/api.json";
@@ -73278,7 +73924,7 @@ var Source = class {
73278
73924
  if (this.data || this.pinned)
73279
73925
  return;
73280
73926
  try {
73281
- const o = JSON.parse(readFileSync17(this.path, "utf8"));
73927
+ const o = JSON.parse(readFileSync18(this.path, "utf8"));
73282
73928
  if (o.map && this.sane(o.map)) {
73283
73929
  this.data = o.map;
73284
73930
  this.fetchedAt = o.fetchedAt ?? 0;
@@ -73577,7 +74223,7 @@ var AcpTransport = class {
73577
74223
  import { spawn as spawn5 } from "node:child_process";
73578
74224
  import { mkdir as mkdir5, readFile as readFile8, writeFile as writeFile6 } from "node:fs/promises";
73579
74225
  import { realpathSync as realpathSync3 } from "node:fs";
73580
- import { basename as basename3, dirname as dirname8, isAbsolute as isAbsolute4, resolve as resolve6, sep as sep4 } from "node:path";
74226
+ import { basename as basename3, dirname as dirname9, isAbsolute as isAbsolute4, resolve as resolve6, sep as sep4 } from "node:path";
73581
74227
  var DEFAULT_OUTPUT_BYTE_LIMIT = 1024 * 1024;
73582
74228
  var MAX_OUTPUT_BYTE_LIMIT = 8 * 1024 * 1024;
73583
74229
  var MAX_TERMINALS = 16;
@@ -73597,7 +74243,7 @@ function realpathDeep(abs) {
73597
74243
  return tail3.length ? resolve6(real, ...tail3) : real;
73598
74244
  } catch {
73599
74245
  }
73600
- const parent = dirname8(head);
74246
+ const parent = dirname9(head);
73601
74247
  if (parent === head)
73602
74248
  return abs;
73603
74249
  tail3.unshift(basename3(head));
@@ -73665,7 +74311,7 @@ function installWorkspaceHandlers(t, opts) {
73665
74311
  if (!target)
73666
74312
  return null;
73667
74313
  const content = p.content ?? "";
73668
- await mkdir5(dirname8(target), { recursive: true }).catch(() => {
74314
+ await mkdir5(dirname9(target), { recursive: true }).catch(() => {
73669
74315
  });
73670
74316
  await writeFile6(target, content, "utf8").catch(() => {
73671
74317
  });
@@ -73784,9 +74430,9 @@ function installWorkspaceHandlers(t, opts) {
73784
74430
  }
73785
74431
 
73786
74432
  // ../../packages/host-core/dist/engines/mcp-injection.js
73787
- import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync11, readFileSync as readFileSync18, readdirSync as readdirSync3, symlinkSync as symlinkSync2, writeFileSync as writeFileSync13 } from "node:fs";
74433
+ import { copyFileSync as copyFileSync2, existsSync as existsSync11, mkdirSync as mkdirSync12, readFileSync as readFileSync19, readdirSync as readdirSync3, symlinkSync as symlinkSync2, writeFileSync as writeFileSync13 } from "node:fs";
73788
74434
  import { homedir as homedir6 } from "node:os";
73789
- import { dirname as dirname9, join as join23, resolve as resolve7 } from "node:path";
74435
+ import { dirname as dirname10, join as join23, resolve as resolve7 } from "node:path";
73790
74436
  import { fileURLToPath as fileURLToPath2 } from "node:url";
73791
74437
  var BUNDLED_MCP_SERVERS = [
73792
74438
  { name: "tesseract-serp", basename: "serpapi-mcp.js", envOverride: "CCB_SERPAPI_MCP_JS" }
@@ -73804,7 +74450,7 @@ function resolveBundledMcpBin(basename14, envOverride) {
73804
74450
  if (rp)
73805
74451
  candidates.push(join23(rp, "host-daemon", basename14));
73806
74452
  try {
73807
- const here = dirname9(fileURLToPath2(import.meta.url));
74453
+ const here = dirname10(fileURLToPath2(import.meta.url));
73808
74454
  candidates.push(join23(here, basename14));
73809
74455
  candidates.push(resolve7(here, "../../../../apps/host-daemon/dist-bundle", basename14));
73810
74456
  candidates.push(resolve7(here, "../../../../apps/host-daemon/dist", basename14));
@@ -73812,7 +74458,7 @@ function resolveBundledMcpBin(basename14, envOverride) {
73812
74458
  } catch {
73813
74459
  }
73814
74460
  for (const c of candidates) {
73815
- if (existsSync10(c)) {
74461
+ if (existsSync11(c)) {
73816
74462
  resolvedBins.set(basename14, c);
73817
74463
  return c;
73818
74464
  }
@@ -73874,7 +74520,7 @@ function specToSettingsServer(spec) {
73874
74520
  }
73875
74521
  function readJson(path6) {
73876
74522
  try {
73877
- return JSON.parse(readFileSync18(path6, "utf8"));
74523
+ return JSON.parse(readFileSync19(path6, "utf8"));
73878
74524
  } catch {
73879
74525
  return {};
73880
74526
  }
@@ -73883,9 +74529,9 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
73883
74529
  try {
73884
74530
  const home = join23(baseDir, "engine-mcp-home", engineId);
73885
74531
  const cfg2 = join23(home, layout.configDir);
73886
- mkdirSync11(cfg2, { recursive: true });
74532
+ mkdirSync12(cfg2, { recursive: true });
73887
74533
  if (layout.linkSiblingConfigs) {
73888
- const realRoot = dirname9(join23(userHome2, layout.userConfigDirRel ?? layout.configDir));
74534
+ const realRoot = dirname10(join23(userHome2, layout.userConfigDirRel ?? layout.configDir));
73889
74535
  let entries = [];
73890
74536
  try {
73891
74537
  entries = readdirSync3(realRoot);
@@ -73896,7 +74542,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
73896
74542
  if (name === layout.configDir)
73897
74543
  continue;
73898
74544
  const link = join23(home, name);
73899
- if (existsSync10(link))
74545
+ if (existsSync11(link))
73900
74546
  continue;
73901
74547
  try {
73902
74548
  symlinkSync2(join23(realRoot, name), link);
@@ -73920,7 +74566,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
73920
74566
  if ((layout.seedFiles ?? []).includes(name))
73921
74567
  continue;
73922
74568
  const link = join23(cfg2, name);
73923
- if (existsSync10(link))
74569
+ if (existsSync11(link))
73924
74570
  continue;
73925
74571
  try {
73926
74572
  symlinkSync2(join23(userCfg, name), link);
@@ -73931,7 +74577,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
73931
74577
  for (const f of layout.seedFiles ?? []) {
73932
74578
  const src = join23(userCfg, f);
73933
74579
  const dst = join23(cfg2, f);
73934
- if (existsSync10(src) && !existsSync10(dst)) {
74580
+ if (existsSync11(src) && !existsSync11(dst)) {
73935
74581
  try {
73936
74582
  copyFileSync2(src, dst);
73937
74583
  } catch {
@@ -73940,7 +74586,7 @@ function writeManagedMcpHome(engineId, layout, servers, projectDir, baseDir, use
73940
74586
  }
73941
74587
  for (const f of layout.mirrorFiles ?? []) {
73942
74588
  const src = join23(userCfg, f);
73943
- if (!existsSync10(src))
74589
+ if (!existsSync11(src))
73944
74590
  continue;
73945
74591
  try {
73946
74592
  copyFileSync2(src, join23(cfg2, f));
@@ -74537,7 +75183,7 @@ function httpApiArgs(spec, port) {
74537
75183
  }
74538
75184
 
74539
75185
  // ../../packages/host-core/dist/engines/session-index.js
74540
- import { mkdirSync as mkdirSync12, readFileSync as readFileSync19, writeFileSync as writeFileSync14 } from "node:fs";
75186
+ import { mkdirSync as mkdirSync13, readFileSync as readFileSync20, writeFileSync as writeFileSync14 } from "node:fs";
74541
75187
  import { join as join24 } from "node:path";
74542
75188
  var MAX_ROWS = 500;
74543
75189
  function createSessionIndex(engineId, baseDir, now2 = Date.now) {
@@ -74547,7 +75193,7 @@ function createSessionIndex(engineId, baseDir, now2 = Date.now) {
74547
75193
  if (rows)
74548
75194
  return rows;
74549
75195
  try {
74550
- const parsed = JSON.parse(readFileSync19(file2, "utf8"));
75196
+ const parsed = JSON.parse(readFileSync20(file2, "utf8"));
74551
75197
  rows = (parsed.sessions ?? []).filter((r) => r && typeof r.id === "string");
74552
75198
  } catch {
74553
75199
  rows = [];
@@ -74561,7 +75207,7 @@ function createSessionIndex(engineId, baseDir, now2 = Date.now) {
74561
75207
  if (rows.length > MAX_ROWS)
74562
75208
  rows = rows.slice(0, MAX_ROWS);
74563
75209
  try {
74564
- mkdirSync12(join24(baseDir, "engine-sessions"), { recursive: true });
75210
+ mkdirSync13(join24(baseDir, "engine-sessions"), { recursive: true });
74565
75211
  writeFileSync14(file2, JSON.stringify({ sessions: rows }, null, 2), { mode: 384 });
74566
75212
  } catch {
74567
75213
  }
@@ -74637,7 +75283,7 @@ function wrapWithSeatbelt(command, args, profile) {
74637
75283
 
74638
75284
  // ../../packages/host-core/dist/engines/opencode-acp.js
74639
75285
  init_dist5();
74640
- import { mkdirSync as mkdirSync13, writeFileSync as writeFileSync15, readFileSync as readFileSync20 } from "node:fs";
75286
+ import { mkdirSync as mkdirSync14, writeFileSync as writeFileSync15, readFileSync as readFileSync21 } from "node:fs";
74641
75287
  import { join as join25, relative as relative4 } from "node:path";
74642
75288
  import { homedir as homedir7, tmpdir as tmpdir4 } from "node:os";
74643
75289
  var TESSERACT_INTERNAL_SECRET2 = /^(CCB_JWT_SECRET|JWT_SECRET|TESSERACT_TOKEN|CCB_RELAY_SECRET|TURN_SECRET|LIVEKIT_API_SECRET)$/;
@@ -74686,7 +75332,7 @@ function modelMemoPath(engineId) {
74686
75332
  }
74687
75333
  function lastKnownModel(engineId) {
74688
75334
  try {
74689
- return readFileSync20(modelMemoPath(engineId), "utf8").trim() || void 0;
75335
+ return readFileSync21(modelMemoPath(engineId), "utf8").trim() || void 0;
74690
75336
  } catch {
74691
75337
  return void 0;
74692
75338
  }
@@ -74695,7 +75341,7 @@ function rememberModel(engineId, modelId) {
74695
75341
  if (!modelId || modelId === lastKnownModel(engineId))
74696
75342
  return;
74697
75343
  try {
74698
- mkdirSync13(join25(daemonDir2(), "engine-config", engineId), { recursive: true });
75344
+ mkdirSync14(join25(daemonDir2(), "engine-config", engineId), { recursive: true });
74699
75345
  writeFileSync15(modelMemoPath(engineId), modelId, { mode: 384 });
74700
75346
  } catch {
74701
75347
  }
@@ -74711,7 +75357,7 @@ async function writeTokenCompactionConfig(engineId, spec, modelId, pct2, baseDir
74711
75357
  return {};
74712
75358
  try {
74713
75359
  const dir2 = join25(baseDir, "engine-config", engineId);
74714
- mkdirSync13(dir2, { recursive: true });
75360
+ mkdirSync14(dir2, { recursive: true });
74715
75361
  const file2 = join25(dir2, "tesseract.json");
74716
75362
  const cfg2 = {};
74717
75363
  let node = cfg2;
@@ -74796,7 +75442,15 @@ var OPENCODE_ACP = {
74796
75442
  // Its own threshold, since ACP gives us no way to ASK it to compact. Without this the
74797
75443
  // auto-compact slider could not reach OpenCode at all and it compacted only at its own
74798
75444
  // hardcoded 95%.
74799
- 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"] },
74800
75454
  compactCommand: "/compact",
74801
75455
  // ACP fallback; the HTTP RPC below is preferred
74802
75456
  // `opencode acp` serves the full HTTP API on the same process — verified: the ACP session
@@ -75082,7 +75736,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
75082
75736
  let hostTasks = null;
75083
75737
  let refreshHostedTools = null;
75084
75738
  const lastTurnText = /* @__PURE__ */ new Map();
75085
- const verification = createHostedVerification();
75739
+ const verification = createHostedVerification(engine.id);
75086
75740
  const scheduling = createHostedScheduling(async (task) => {
75087
75741
  const pol = scheduling.policy();
75088
75742
  try {
@@ -75133,10 +75787,10 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
75133
75787
  collectReplay(replay, u);
75134
75788
  return;
75135
75789
  }
75136
- const sink = subagentSinks.get(sid);
75137
- if (sink) {
75790
+ const sink2 = subagentSinks.get(sid);
75791
+ if (sink2) {
75138
75792
  if (u.sessionUpdate === "agent_message_chunk")
75139
- sink.push(u.content?.text ?? "");
75793
+ sink2.push(u.content?.text ?? "");
75140
75794
  return;
75141
75795
  }
75142
75796
  if (u.sessionUpdate === "usage_update") {
@@ -75257,6 +75911,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
75257
75911
  if (!turn)
75258
75912
  return;
75259
75913
  scheduleUnattendedAnswer({ kind: "elicitation", serverName: engine.label }, {
75914
+ context: { sessionId: sid, engine: engine.id },
75260
75915
  mode: () => turn.unattended,
75261
75916
  charge: () => turn.autoDecisions += 1,
75262
75917
  refund: () => {
@@ -75434,6 +76089,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
75434
76089
  }, turn?.origin);
75435
76090
  if (turn) {
75436
76091
  scheduleUnattendedAnswer({ kind: "permission", tool: toolName }, {
76092
+ context: { sessionId: psid, engine: engine.id },
75437
76093
  mode: () => turn.unattended,
75438
76094
  charge: () => turn.autoDecisions += 1,
75439
76095
  refund: () => {
@@ -75493,6 +76149,7 @@ function createAcpBackend(engine, send4, resolve16, onBrowserRequest, loadPlugin
75493
76149
  if (!turn)
75494
76150
  return;
75495
76151
  scheduleUnattendedAnswer({ kind: "elicitation", serverName: "connector" }, {
76152
+ context: { sessionId: esid, engine: engine.id },
75496
76153
  mode: () => turn.unattended,
75497
76154
  charge: () => turn.autoDecisions += 1,
75498
76155
  refund: () => {
@@ -75780,11 +76437,11 @@ ${text9}`);
75780
76437
  await replayLoad(conn, sessionId);
75781
76438
  }
75782
76439
  async function promptForText(t, sid, prompt) {
75783
- const sink = [];
75784
- subagentSinks.set(sid, sink);
76440
+ const sink2 = [];
76441
+ subagentSinks.set(sid, sink2);
75785
76442
  try {
75786
76443
  for (let attempt = 0; attempt < RESEED_SUMMARY_ATTEMPTS; attempt++) {
75787
- sink.length = 0;
76444
+ sink2.length = 0;
75788
76445
  let timer2;
75789
76446
  const timedOut = Symbol("timeout");
75790
76447
  const outcome = await Promise.race([
@@ -75807,7 +76464,7 @@ ${text9}`);
75807
76464
  }
75808
76465
  return null;
75809
76466
  }
75810
- const out = sink.join("").trim();
76467
+ const out = sink2.join("").trim();
75811
76468
  if (out)
75812
76469
  return out;
75813
76470
  if (attempt < RESEED_SUMMARY_ATTEMPTS - 1)
@@ -75889,6 +76546,56 @@ ${text9}`);
75889
76546
  const all = await listSessionsFor(projectDir);
75890
76547
  return all.filter((row) => row.title.toLowerCase().includes(q) || (sessionBodies.get(row.id) ?? "").includes(q));
75891
76548
  }
76549
+ const proactiveCompactedAt = /* @__PURE__ */ new Map();
76550
+ const sessionRekey = /* @__PURE__ */ new Map();
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
+ }
75892
76599
  async function sendMessage(params) {
75893
76600
  const origin = params.origin;
75894
76601
  const fail4 = (sessionId, error51, transient = false) => send4({ type: "chat:error", sessionId, clientRequestId: params.clientRequestId, error: error51, ...transient ? { transient: true } : {} }, origin);
@@ -76004,6 +76711,12 @@ ${text9}`);
76004
76711
  }
76005
76712
  sessionIndex.record({ id: next, cwd: params.projectDir, title, updatedAt: Date.now() });
76006
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
+ }
76007
76720
  send4({ type: "session:created", sessionId: next, clientRequestId: params.clientRequestId }, origin);
76008
76721
  send4({ type: "chat:complete", sessionId: next, clientRequestId: params.clientRequestId, messageId: randomUUID11(), result: "Compacted this conversation to free up context.", turnId: randomUUID11() }, origin);
76009
76722
  send4({ type: "agent:status", sessionId: next, clientRequestId: params.clientRequestId, status: "idle" }, origin);
@@ -76163,6 +76876,10 @@ ${text9}`);
76163
76876
  }
76164
76877
  }
76165
76878
  }
76879
+ void maybeCompactProactively(sid, params);
76880
+ if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
76881
+ overflowTries.delete(sid);
76882
+ }
76166
76883
  send4({ type: "chat:complete", sessionId: sid, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...res?.stopReason ? { stopReason: res.stopReason } : {} }, origin);
76167
76884
  send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
76168
76885
  } catch (e) {
@@ -76170,6 +76887,19 @@ ${text9}`);
76170
76887
  const detail = String(e?.message ?? e);
76171
76888
  const overflow = isContextOverflow(detail);
76172
76889
  if (overflow && declared.contextCompaction) {
76890
+ const recovered = await recoverFromContextOverflow({
76891
+ mode: () => unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
76892
+ canCompact: () => true,
76893
+ tries: () => overflowTries.get(sid) ?? 0,
76894
+ bump: () => overflowTries.set(sid, (overflowTries.get(sid) ?? 0) + 1),
76895
+ context: { sessionId: sid, engine: engine.id },
76896
+ compactAndResume: async () => {
76897
+ await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: sid, autoContinuation: true });
76898
+ await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: sessionRekey.get(sid) ?? sid, autoContinuation: true });
76899
+ }
76900
+ });
76901
+ if (recovered)
76902
+ return;
76173
76903
  send4({ type: "chat:error", sessionId: sid, clientRequestId: params.clientRequestId, error: detail, continuable: true, continueReason: "context_window" }, origin);
76174
76904
  send4({ type: "agent:status", sessionId: sid, clientRequestId: params.clientRequestId, status: "idle" }, origin);
76175
76905
  return;
@@ -76443,21 +77173,7 @@ ${detail}` : detail, !overflow);
76443
77173
  }
76444
77174
  },
76445
77175
  ...declared.contextUsage ? {
76446
- getContextUsage: async (sessionId) => {
76447
- const model = sessionResolvedModel.get(sessionId) ?? sessionConfig.get(sessionId)?.currentModel;
76448
- const rep = sessionReported.get(sessionId);
76449
- const total = rep?.used ?? sessionUsage.get(sessionId)?.total;
76450
- const maxTokens = rep?.size ?? contextWindowFor(model) ?? void 0;
76451
- if (total === void 0 || !maxTokens)
76452
- return null;
76453
- const usage2 = {
76454
- totalTokens: total,
76455
- maxTokens,
76456
- percentage: Math.min(100, Math.round(total / maxTokens * 1e3) / 10),
76457
- ...model ? { model } : {}
76458
- };
76459
- return usage2;
76460
- }
77176
+ getContextUsage: async (sessionId) => contextUsageFor(sessionId)
76461
77177
  } : {},
76462
77178
  ...declared.costTracking ? {
76463
77179
  getSessionCost: async (sessionId) => {
@@ -76889,7 +77605,7 @@ init_dist();
76889
77605
  init_credentials();
76890
77606
  import { spawn as spawn8 } from "node:child_process";
76891
77607
  import { randomUUID as randomUUID12 } from "node:crypto";
76892
- import { mkdirSync as mkdirSync14, readFileSync as readFileSync21, writeFileSync as writeFileSync16 } from "node:fs";
77608
+ import { mkdirSync as mkdirSync15, readFileSync as readFileSync22, writeFileSync as writeFileSync16 } from "node:fs";
76893
77609
  import { join as join26 } from "node:path";
76894
77610
  init_daemon_settings();
76895
77611
  init_dist5();
@@ -77147,7 +77863,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77147
77863
  let hostedBearer = null;
77148
77864
  let refreshHostedTools = null;
77149
77865
  const lastTurnText = /* @__PURE__ */ new Map();
77150
- const verification = createHostedVerification();
77866
+ const verification = createHostedVerification("codex");
77151
77867
  const scheduling = createHostedScheduling(async (task) => {
77152
77868
  try {
77153
77869
  await sendMessage({ message: task.prompt, url: "", projectDir: spawnedCwd ?? void 0, sessionId: task.sessionId, origin: "cron" });
@@ -77220,6 +77936,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77220
77936
  if (!turn)
77221
77937
  return;
77222
77938
  scheduleUnattendedAnswer({ kind: "permission", tool: toolName }, {
77939
+ context: { sessionId: turn.threadId, engine: "codex" },
77223
77940
  mode: () => turn.unattended,
77224
77941
  charge: () => turn.autoDecisions += 1,
77225
77942
  refund: () => {
@@ -77253,6 +77970,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77253
77970
  if (!turn)
77254
77971
  return;
77255
77972
  scheduleUnattendedAnswer(prompt, {
77973
+ context: { sessionId: turn.threadId, engine: "codex" },
77256
77974
  mode: () => turn.unattended,
77257
77975
  charge: () => turn.autoDecisions += 1,
77258
77976
  refund: () => {
@@ -77284,10 +78002,10 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77284
78002
  function onNotification(method, raw) {
77285
78003
  const p = raw ?? {};
77286
78004
  const threadId = String(p.threadId ?? "");
77287
- const sink = subagentSinks.get(threadId);
77288
- if (sink) {
78005
+ const sink2 = subagentSinks.get(threadId);
78006
+ if (sink2) {
77289
78007
  if (method === "item/agentMessage/delta")
77290
- sink.push(String(p.delta ?? ""));
78008
+ sink2.push(String(p.delta ?? ""));
77291
78009
  if (method === "turn/completed" || method === "error")
77292
78010
  subagentDone.get(threadId)?.();
77293
78011
  return;
@@ -77425,7 +78143,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77425
78143
  lastWindow = window2;
77426
78144
  try {
77427
78145
  const dir2 = join26(daemonDir2(), "engine-config", "openai-codex");
77428
- mkdirSync14(dir2, { recursive: true });
78146
+ mkdirSync15(dir2, { recursive: true });
77429
78147
  writeFileSync16(join26(dir2, "window"), String(window2), { mode: 384 });
77430
78148
  } catch {
77431
78149
  }
@@ -77434,7 +78152,7 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77434
78152
  if (lastWindow)
77435
78153
  return lastWindow;
77436
78154
  try {
77437
- const n = Number(readFileSync21(join26(daemonDir2(), "engine-config", "openai-codex", "window"), "utf8").trim());
78155
+ const n = Number(readFileSync22(join26(daemonDir2(), "engine-config", "openai-codex", "window"), "utf8").trim());
77438
78156
  return Number.isFinite(n) && n > 0 ? lastWindow = n : void 0;
77439
78157
  } catch {
77440
78158
  return void 0;
@@ -77599,6 +78317,61 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77599
78317
  })();
77600
78318
  return initPromise;
77601
78319
  }
78320
+ const proactiveCompactedAt = /* @__PURE__ */ new Map();
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
+ }
77602
78375
  async function sendMessage(params) {
77603
78376
  const origin = params.origin;
77604
78377
  const cfg2 = resolve16(ENGINE_ID2);
@@ -77788,12 +78561,30 @@ function createCodexAppServerBackend(send4, resolve16, onBrowserRequest, loadPlu
77788
78561
  }
77789
78562
  });
77790
78563
  }
78564
+ void maybeCompactProactively(threadId, params);
78565
+ if (!(params.autoContinuation === true && params.message === OVERFLOW_COMPACT_MESSAGE)) {
78566
+ overflowTries.delete(threadId);
78567
+ }
77791
78568
  send4({ type: "chat:complete", sessionId: threadId, clientRequestId: params.clientRequestId, messageId, result: finalText, turnId, ...stopReason ? { stopReason } : {} }, origin);
77792
78569
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
77793
78570
  } catch (e) {
77794
78571
  turns.delete(threadId);
77795
78572
  const detail = String(e?.message ?? e);
77796
78573
  if (isContextOverflow(detail)) {
78574
+ const recovered = await recoverFromContextOverflow({
78575
+ mode: () => unattendedModeFor({ optedIn: params.unattended, origin: params.origin }),
78576
+ canCompact: () => true,
78577
+ // Codex maps '/compact' to thread/compact/start
78578
+ tries: () => overflowTries.get(threadId) ?? 0,
78579
+ bump: () => overflowTries.set(threadId, (overflowTries.get(threadId) ?? 0) + 1),
78580
+ context: { sessionId: threadId, engine: "codex" },
78581
+ compactAndResume: async () => {
78582
+ await sendMessage({ ...params, message: OVERFLOW_COMPACT_MESSAGE, sessionId: threadId, autoContinuation: true });
78583
+ await sendMessage({ ...params, message: OVERFLOW_RESUME_MESSAGE, sessionId: threadId, autoContinuation: true });
78584
+ }
78585
+ });
78586
+ if (recovered)
78587
+ return;
77797
78588
  send4({ type: "chat:error", sessionId: threadId, clientRequestId: params.clientRequestId, error: detail, continuable: true, continueReason: "context_window" }, origin);
77798
78589
  send4({ type: "agent:status", sessionId: threadId, clientRequestId: params.clientRequestId, status: "idle" }, origin);
77799
78590
  return;
@@ -78117,34 +78908,7 @@ ${text9}`;
78117
78908
  await transport.request("config/mcpServer/reload", {}).catch(() => {
78118
78909
  });
78119
78910
  },
78120
- getContextUsage: async (sessionId) => {
78121
- const u = tokenUsage.get(sessionId);
78122
- if (!u?.window)
78123
- return null;
78124
- const current = u.lastTotal || u.total;
78125
- const usage2 = {
78126
- // `last`, NOT `total`. Measured: `total` is CUMULATIVE over the conversation and grows
78127
- // by exactly the previous turn's tokens (142,394 → 162,119 after a 19,725-token turn),
78128
- // so it can never fall. Reporting it as context usage meant the meter climbed past
78129
- // 100% of a 258k window on a conversation nowhere near full, never came down after a
78130
- // compaction, and — because this figure is what the proactive threshold reads — asked
78131
- // for compaction after compaction with the number refusing to move.
78132
- //
78133
- // `last.totalTokens` is the CURRENT context: the input the model actually saw on the
78134
- // most recent turn, which is what a window is measured against and what drops when a
78135
- // compaction succeeds.
78136
- // `|| u.total`, not `?? u.total`: the single writer stores `u.last?.totalTokens ?? 0`,
78137
- // so a missing `last` arrives here as 0 — which `??` passes straight through and the
78138
- // meter reads 0% on a full conversation. Under-reporting is the dangerous direction,
78139
- // because the proactive threshold then never fires and the context hits a hard
78140
- // overflow instead of compacting. Observed live: a `thread/tokenUsage/updated` whose
78141
- // `total` was all zeros while `last.totalTokens` was 4666, and the reverse.
78142
- totalTokens: current,
78143
- maxTokens: u.window,
78144
- percentage: Math.min(100, Math.round(current / u.window * 1e3) / 10)
78145
- };
78146
- return usage2;
78147
- },
78911
+ getContextUsage: async (sessionId) => contextUsageFor(sessionId),
78148
78912
  /** toolInjection, host half. Codex reads MCP servers from its config, so a change takes
78149
78913
  * effect on the next install (the flag is reset so the write actually re-runs). */
78150
78914
  setInjectedMcpServers: (servers) => {
@@ -78445,7 +79209,7 @@ async function createBackend(engineId, send4, onBrowserRequest, resolver, loadPl
78445
79209
  // ../../packages/host-core/dist/session-recorder.js
78446
79210
  init_base_paths();
78447
79211
  import { join as join27 } from "node:path";
78448
- import { mkdirSync as mkdirSync15, writeFileSync as writeFileSync17, appendFileSync as appendFileSync2, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync7 } from "node:fs";
79212
+ import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync17, appendFileSync as appendFileSync3, readdirSync as readdirSync4, rmSync as rmSync2, statSync as statSync8 } from "node:fs";
78449
79213
  init_dist5();
78450
79214
  var dir = null;
78451
79215
  var seq = 0;
@@ -78470,7 +79234,7 @@ function recordEvent(type, data = {}) {
78470
79234
  if (!dir)
78471
79235
  return;
78472
79236
  try {
78473
- appendFileSync2(join27(dir, "events.jsonl"), `${JSON.stringify({ ts: now(), seq: seq++, type, ...data })}
79237
+ appendFileSync3(join27(dir, "events.jsonl"), `${JSON.stringify({ ts: now(), seq: seq++, type, ...data })}
78474
79238
  `);
78475
79239
  } catch {
78476
79240
  }
@@ -78481,8 +79245,8 @@ init_dist5();
78481
79245
 
78482
79246
  // ../../packages/host-core/dist/plugin-tools.js
78483
79247
  init_base_paths();
78484
- import { existsSync as existsSync11, readdirSync as readdirSync5 } from "node:fs";
78485
- import { join as join28, dirname as dirname10 } from "node:path";
79248
+ import { existsSync as existsSync12, readdirSync as readdirSync5 } from "node:fs";
79249
+ import { join as join28, dirname as dirname11 } from "node:path";
78486
79250
 
78487
79251
  // ../../packages/plugin-host/dist/index.js
78488
79252
  init_dist();
@@ -78816,7 +79580,7 @@ function convertTool(t) {
78816
79580
  };
78817
79581
  }
78818
79582
  function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
78819
- const warned = /* @__PURE__ */ new Set();
79583
+ const warned2 = /* @__PURE__ */ new Set();
78820
79584
  const impl = {
78821
79585
  pluginId,
78822
79586
  config: config2,
@@ -78887,8 +79651,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry3) {
78887
79651
  return Reflect.get(target, prop, recv);
78888
79652
  if (typeof prop === "string") {
78889
79653
  return (..._args) => {
78890
- if (!warned.has(prop)) {
78891
- warned.add(prop);
79654
+ if (!warned2.has(prop)) {
79655
+ warned2.add(prop);
78892
79656
  registry3.diagnostics.push(`[${pluginId}] api.${prop}() is not supported by the Tesseract host \u2014 ignored`);
78893
79657
  }
78894
79658
  };
@@ -79000,7 +79764,7 @@ function buildDaemonPluginLoader(pluginsDir) {
79000
79764
  return async () => {
79001
79765
  const skillsPlugin = daemonSkillsPluginConfig();
79002
79766
  const snap = readDaemonAgentSettings();
79003
- const desktopRoots = (snap.pluginRoots ?? []).filter((r) => r?.dir && existsSync11(r.dir));
79767
+ const desktopRoots = (snap.pluginRoots ?? []).filter((r) => r?.dir && existsSync12(r.dir));
79004
79768
  if (desktopRoots.length > 0) {
79005
79769
  const resDir = process.resourcesPath;
79006
79770
  for (const r of desktopRoots) {
@@ -79009,7 +79773,7 @@ function buildDaemonPluginLoader(pluginsDir) {
79009
79773
  if (resDir && r.dir.startsWith(resDir))
79010
79774
  continue;
79011
79775
  try {
79012
- writeOpenClawShim(r.dir.endsWith("node_modules") ? dirname10(r.dir) : r.dir);
79776
+ writeOpenClawShim(r.dir.endsWith("node_modules") ? dirname11(r.dir) : r.dir);
79013
79777
  } catch {
79014
79778
  }
79015
79779
  }
@@ -79023,7 +79787,7 @@ function buildDaemonPluginLoader(pluginsDir) {
79023
79787
  return { ...rt2, skillsPlugin };
79024
79788
  }
79025
79789
  const scan = join28(pluginsDir, "node_modules");
79026
- if (!existsSync11(scan))
79790
+ if (!existsSync12(scan))
79027
79791
  return { tools: [], hooks: [], messageHooks: [], commands: [], themeOps: [], engines: [], skillsPlugin };
79028
79792
  writeOpenClawShim(pluginsDir);
79029
79793
  const rt = await loadPluginRuntime({
@@ -79035,11 +79799,11 @@ function buildDaemonPluginLoader(pluginsDir) {
79035
79799
  }
79036
79800
  function daemonSkillsPluginConfig() {
79037
79801
  const root = readDaemonAgentSettings().skillsRoot ?? tessPath("extensions-skills");
79038
- if (!existsSync11(join28(root, ".claude-plugin", "plugin.json")))
79802
+ if (!existsSync12(join28(root, ".claude-plugin", "plugin.json")))
79039
79803
  return null;
79040
79804
  const enabled = join28(root, "skills");
79041
79805
  try {
79042
- const hasSkill = readdirSync5(enabled).some((slug2) => existsSync11(join28(enabled, slug2, "SKILL.md")));
79806
+ const hasSkill = readdirSync5(enabled).some((slug2) => existsSync12(join28(enabled, slug2, "SKILL.md")));
79043
79807
  return hasSkill ? { type: "local", path: root } : null;
79044
79808
  } catch {
79045
79809
  return null;
@@ -79241,10 +80005,10 @@ async function enableEditorMirror(browserId, onEvent) {
79241
80005
  });
79242
80006
  page.on("pageerror", (err2) => relay({ level: "error", kind: "console", message: err2.message }));
79243
80007
  page.on("requestfailed", (req) => {
79244
- const errText = req.failure()?.errorText ?? "request failed";
79245
- if (errText.includes("ERR_ABORTED"))
80008
+ const errText2 = req.failure()?.errorText ?? "request failed";
80009
+ if (errText2.includes("ERR_ABORTED"))
79246
80010
  return;
79247
- relay({ level: "error", kind: "network", message: `Failed to load ${req.url()} \u2014 ${errText}` });
80011
+ relay({ level: "error", kind: "network", message: `Failed to load ${req.url()} \u2014 ${errText2}` });
79248
80012
  });
79249
80013
  page.on("close", () => editorErrorTaps.delete(browserId));
79250
80014
  }
@@ -79339,10 +80103,10 @@ import { join as join30 } from "node:path";
79339
80103
 
79340
80104
  // ../../packages/host-core/dist/gui/daemon-gui.js
79341
80105
  init_credentials();
79342
- import { join as join29, dirname as dirname11 } from "node:path";
80106
+ import { join as join29, dirname as dirname12 } from "node:path";
79343
80107
  import { fileURLToPath as fileURLToPath4 } from "node:url";
79344
80108
  import { spawn as spawn9, spawnSync } from "node:child_process";
79345
- import { existsSync as existsSync12 } from "node:fs";
80109
+ import { existsSync as existsSync13 } from "node:fs";
79346
80110
 
79347
80111
  // ../../packages/host-core/dist/gui/main-app-launch.js
79348
80112
  var LAUNCH_MARKERS = [
@@ -79578,14 +80342,14 @@ function daemonUiDir() {
79578
80342
  return resolvedUiDir;
79579
80343
  const ok = (d) => {
79580
80344
  try {
79581
- return existsSync12(join29(d, "preload.cjs"));
80345
+ return existsSync13(join29(d, "preload.cjs"));
79582
80346
  } catch {
79583
80347
  return false;
79584
80348
  }
79585
80349
  };
79586
80350
  let here = null;
79587
80351
  try {
79588
- here = dirname11(fileURLToPath4(import.meta.url));
80352
+ here = dirname12(fileURLToPath4(import.meta.url));
79589
80353
  } catch {
79590
80354
  here = null;
79591
80355
  }
@@ -79617,8 +80381,8 @@ function devAppPath() {
79617
80381
  return env;
79618
80382
  const daemonEntry = process.argv[1];
79619
80383
  if (daemonEntry) {
79620
- const cand = join29(dirname11(daemonEntry), "..", "..", "desktop");
79621
- if (existsSync12(join29(cand, "package.json")))
80384
+ const cand = join29(dirname12(daemonEntry), "..", "..", "desktop");
80385
+ if (existsSync13(join29(cand, "package.json")))
79622
80386
  return cand;
79623
80387
  }
79624
80388
  return null;
@@ -80001,7 +80765,7 @@ function widgetDisplayBounds(w) {
80001
80765
  }
80002
80766
 
80003
80767
  // ../../packages/host-core/dist/gui/ai-control.js
80004
- import { join as join31, dirname as dirname12 } from "node:path";
80768
+ import { join as join31, dirname as dirname13 } from "node:path";
80005
80769
  import { randomUUID as randomUUID14 } from "node:crypto";
80006
80770
  init_dist5();
80007
80771
  init_credentials();
@@ -80081,7 +80845,7 @@ var MOONDREAM_URL = (process.env.CCB_MOONDREAM_URL?.trim() || "http://127.0.0.1:
80081
80845
 
80082
80846
  // ../../packages/host-core/dist/voice-control.js
80083
80847
  init_base_paths();
80084
- import { existsSync as existsSync13, readFileSync as readFileSync22 } from "node:fs";
80848
+ import { existsSync as existsSync14, readFileSync as readFileSync23 } from "node:fs";
80085
80849
  import { basename as basename4, join as join32 } from "node:path";
80086
80850
 
80087
80851
  // ../../packages/voice-core/dist/providers/tool-adapters.js
@@ -81332,8 +82096,8 @@ function readGeminiKeyFile() {
81332
82096
  try {
81333
82097
  const home = tesseractHome();
81334
82098
  const f = join32(home, "daemon", "gemini.key");
81335
- if (existsSync13(f)) {
81336
- const k = readFileSync22(f, "utf-8").trim();
82099
+ if (existsSync14(f)) {
82100
+ const k = readFileSync23(f, "utf-8").trim();
81337
82101
  if (k)
81338
82102
  return k;
81339
82103
  }
@@ -81751,13 +82515,13 @@ ${priorText}` : "";
81751
82515
  };
81752
82516
 
81753
82517
  // ../../packages/host-core/dist/daemon-agent.js
81754
- import { mkdirSync as mkdirSync21 } from "node:fs";
82518
+ import { mkdirSync as mkdirSync22 } from "node:fs";
81755
82519
  init_pool();
81756
82520
 
81757
82521
  // ../../packages/host-core/dist/image-gen-runner.js
81758
82522
  init_base_paths();
81759
82523
  import { randomUUID as randomUUID16 } from "node:crypto";
81760
- import { mkdirSync as mkdirSync16, writeFileSync as writeFileSync18, readFileSync as readFileSync23 } from "node:fs";
82524
+ import { mkdirSync as mkdirSync17, writeFileSync as writeFileSync18, readFileSync as readFileSync24 } from "node:fs";
81761
82525
  import { join as join33 } from "node:path";
81762
82526
 
81763
82527
  // ../../packages/image-edit-core/dist/transparent.js
@@ -82246,7 +83010,7 @@ function createDaemonImageGenRunner() {
82246
83010
  let inputMime;
82247
83011
  if (req.sourceImagePath) {
82248
83012
  try {
82249
- inputImageB64 = readFileSync23(req.sourceImagePath).toString("base64");
83013
+ inputImageB64 = readFileSync24(req.sourceImagePath).toString("base64");
82250
83014
  const lower = req.sourceImagePath.toLowerCase();
82251
83015
  inputMime = lower.endsWith(".jpg") || lower.endsWith(".jpeg") ? "image/jpeg" : lower.endsWith(".webp") ? "image/webp" : "image/png";
82252
83016
  } catch (e) {
@@ -82267,7 +83031,7 @@ function createDaemonImageGenRunner() {
82267
83031
  if (!images.length)
82268
83032
  return { ok: false, error: "The provider returned no image." };
82269
83033
  const dir2 = req.outDir ?? join33(generatedImagesDir(), randomUUID16());
82270
- mkdirSync16(dir2, { recursive: true });
83034
+ mkdirSync17(dir2, { recursive: true });
82271
83035
  const files = images.map((img, i) => {
82272
83036
  const ext = img.mime.split("/")[1]?.split("+")[0] || "png";
82273
83037
  const path6 = join33(dir2, `${i + 1}.${ext}`);
@@ -82287,7 +83051,7 @@ function createDaemonImageGenRunner() {
82287
83051
  init_serpapi_runner();
82288
83052
 
82289
83053
  // ../../packages/host-core/dist/video-gen-runner.js
82290
- import { readFileSync as readFileSync25 } from "node:fs";
83054
+ import { readFileSync as readFileSync26 } from "node:fs";
82291
83055
 
82292
83056
  // ../../packages/video-core/dist/cost.js
82293
83057
  var VEO_RATES = [
@@ -83687,9 +84451,9 @@ init_daemon_settings();
83687
84451
 
83688
84452
  // ../../packages/host-core/dist/video-jobs.js
83689
84453
  init_base_paths();
83690
- import { mkdirSync as mkdirSync17, readdirSync as readdirSync6, readFileSync as readFileSync24, writeFileSync as writeFileSync19, rmSync as rmSync3 } from "node:fs";
84454
+ import { mkdirSync as mkdirSync18, readdirSync as readdirSync6, readFileSync as readFileSync25, writeFileSync as writeFileSync19, rmSync as rmSync3 } from "node:fs";
83691
84455
  import { mkdir as mkdir6, writeFile as writeFile7 } from "node:fs/promises";
83692
- import { dirname as dirname13, join as join34 } from "node:path";
84456
+ import { dirname as dirname14, join as join34 } from "node:path";
83693
84457
  import { randomUUID as randomUUID17 } from "node:crypto";
83694
84458
  function mediaJobsDir() {
83695
84459
  const home = tesseractHome();
@@ -83738,7 +84502,7 @@ var VideoJobRegistry = class {
83738
84502
  if (mem)
83739
84503
  return { ...mem };
83740
84504
  try {
83741
- const raw = readFileSync24(join34(mediaJobsDir(), `${jobId}.json`), "utf-8");
84505
+ const raw = readFileSync25(join34(mediaJobsDir(), `${jobId}.json`), "utf-8");
83742
84506
  return JSON.parse(raw);
83743
84507
  } catch {
83744
84508
  return null;
@@ -83790,7 +84554,7 @@ var VideoJobRegistry = class {
83790
84554
  for (const f of files) {
83791
84555
  const fp = join34(mediaJobsDir(), f);
83792
84556
  try {
83793
- const job = JSON.parse(readFileSync24(fp, "utf-8"));
84557
+ const job = JSON.parse(readFileSync25(fp, "utf-8"));
83794
84558
  if (TERMINAL.has(job.state)) {
83795
84559
  if (now2 - (job.updatedAt ?? job.createdAt ?? now2) > DISK_RETENTION_MS)
83796
84560
  rmSync3(fp, { force: true });
@@ -83874,7 +84638,7 @@ var VideoJobRegistry = class {
83874
84638
  this.materializing.add(job.id);
83875
84639
  try {
83876
84640
  const res = await provider.fetchResult({ providerId: job.providerId, model: job.model, operationName: job.operationName });
83877
- await mkdir6(dirname13(job.outPath), { recursive: true });
84641
+ await mkdir6(dirname14(job.outPath), { recursive: true });
83878
84642
  await writeFile7(job.outPath, res.bytes);
83879
84643
  this.update(job, { state: "succeeded", mime: res.mime, progressPct: 100 });
83880
84644
  } catch (e) {
@@ -83910,7 +84674,7 @@ var VideoJobRegistry = class {
83910
84674
  persist(job) {
83911
84675
  this.jobs.set(job.id, job);
83912
84676
  try {
83913
- mkdirSync17(mediaJobsDir(), { recursive: true });
84677
+ mkdirSync18(mediaJobsDir(), { recursive: true });
83914
84678
  writeFileSync19(join34(mediaJobsDir(), `${job.id}.json`), JSON.stringify(job, null, 2));
83915
84679
  } catch {
83916
84680
  }
@@ -83955,7 +84719,7 @@ function buildProvider(id, pc, model) {
83955
84719
  function readFrame(path6) {
83956
84720
  const lower = path6.toLowerCase();
83957
84721
  const mime = lower.endsWith(".jpg") || lower.endsWith(".jpeg") ? "image/jpeg" : lower.endsWith(".webp") ? "image/webp" : "image/png";
83958
- return { bytes: new Uint8Array(readFileSync25(path6)), mime };
84722
+ return { bytes: new Uint8Array(readFileSync26(path6)), mime };
83959
84723
  }
83960
84724
  function providerForJob(providerId, model) {
83961
84725
  const c = creds2();
@@ -84063,7 +84827,7 @@ function createDaemonVideoGenRunner() {
84063
84827
 
84064
84828
  // ../../packages/host-core/dist/video-edit-runner.js
84065
84829
  init_base_paths();
84066
- import { existsSync as existsSync16, readFileSync as readFileSync30 } from "node:fs";
84830
+ import { existsSync as existsSync17, readFileSync as readFileSync31 } from "node:fs";
84067
84831
  import { mkdir as mkdir7, writeFile as writeFile8 } from "node:fs/promises";
84068
84832
  import { join as join38, basename as basename6 } from "node:path";
84069
84833
  import { randomUUID as randomUUID19 } from "node:crypto";
@@ -84072,12 +84836,12 @@ init_daemon_settings();
84072
84836
  // ../../packages/host-core/dist/video-edit.js
84073
84837
  init_base_paths();
84074
84838
  import { spawn as spawn11 } from "node:child_process";
84075
- import { mkdirSync as mkdirSync18, readFileSync as readFileSync26, rmSync as rmSync4, writeFileSync as writeFileSync20 } from "node:fs";
84839
+ import { mkdirSync as mkdirSync19, readFileSync as readFileSync27, rmSync as rmSync4, writeFileSync as writeFileSync20 } from "node:fs";
84076
84840
  import { join as join35, isAbsolute as isAbsolute5 } from "node:path";
84077
84841
  import { randomUUID as randomUUID18 } from "node:crypto";
84078
84842
 
84079
84843
  // ../../packages/host-core/dist/ffmpeg.js
84080
- import { existsSync as existsSync14 } from "node:fs";
84844
+ import { existsSync as existsSync15 } from "node:fs";
84081
84845
  import { spawnSync as spawnSync2 } from "node:child_process";
84082
84846
  import { sep as sep5 } from "node:path";
84083
84847
  import { createRequire as createRequire3 } from "node:module";
@@ -84090,7 +84854,7 @@ function fromPackage(name) {
84090
84854
  if (typeof raw !== "string")
84091
84855
  return null;
84092
84856
  const p = unpacked(raw);
84093
- return existsSync14(p) ? p : null;
84857
+ return existsSync15(p) ? p : null;
84094
84858
  } catch {
84095
84859
  return null;
84096
84860
  }
@@ -84106,7 +84870,7 @@ function fromPath(cmd) {
84106
84870
  function resolveBinary(envVar, pkg, cmd, hint) {
84107
84871
  const env = process.env[envVar]?.trim();
84108
84872
  if (env) {
84109
- if (existsSync14(env) || fromPath(env))
84873
+ if (existsSync15(env) || fromPath(env))
84110
84874
  return env;
84111
84875
  throw new Error(`${envVar}=${env} does not exist or is not executable.`);
84112
84876
  }
@@ -84148,14 +84912,14 @@ var mediaCwd;
84148
84912
  function mediaSpawnCwd() {
84149
84913
  if (!mediaCwd) {
84150
84914
  mediaCwd = tessPath("media-work");
84151
- mkdirSync18(mediaCwd, { recursive: true });
84915
+ mkdirSync19(mediaCwd, { recursive: true });
84152
84916
  }
84153
84917
  return mediaCwd;
84154
84918
  }
84155
84919
  var workDir = () => {
84156
84920
  const home = tesseractHome();
84157
84921
  const dir2 = join35(home, "media-work", randomUUID18());
84158
- mkdirSync18(dir2, { recursive: true });
84922
+ mkdirSync19(dir2, { recursive: true });
84159
84923
  return dir2;
84160
84924
  };
84161
84925
  var MIME_BY_EXT = {
@@ -84244,7 +85008,7 @@ async function renderEdl(edl, opts) {
84244
85008
  }
84245
85009
  }
84246
85010
  const dir2 = opts.outDir ?? workDir();
84247
- mkdirSync18(dir2, { recursive: true });
85011
+ mkdirSync19(dir2, { recursive: true });
84248
85012
  const format = edl.output?.format ?? "mp4";
84249
85013
  const outPath = join35(dir2, `edit.${format}`);
84250
85014
  let assFile;
@@ -84318,7 +85082,7 @@ async function enhanceVideo(path6, spec, opts) {
84318
85082
  throw new Error("Nothing to enhance \u2014 request at least one of: upscale, denoise, deblock, deband, sharpen, or interpolate.");
84319
85083
  }
84320
85084
  const dir2 = opts?.outDir ?? workDir();
84321
- mkdirSync18(dir2, { recursive: true });
85085
+ mkdirSync19(dir2, { recursive: true });
84322
85086
  const outPath = join35(dir2, "enhanced.mp4");
84323
85087
  const audioArgs = probe.hasAudio ? ["-c:a", "copy"] : ["-an"];
84324
85088
  const args = [
@@ -84396,7 +85160,7 @@ ${stderrTail}`));
84396
85160
  async function extractFrames(path6, timestamps, outDir) {
84397
85161
  path6 = requireAbsolutePath(path6, "path");
84398
85162
  const dir2 = outDir ?? workDir();
84399
- mkdirSync18(dir2, { recursive: true });
85163
+ mkdirSync19(dir2, { recursive: true });
84400
85164
  const out = [];
84401
85165
  for (const [i, ts] of timestamps.slice(0, 20).entries()) {
84402
85166
  const file2 = join35(dir2, `frame-${i + 1}-${Math.round(ts * 1e3)}ms.jpg`);
@@ -84431,7 +85195,7 @@ async function detectSilence(path6, opts) {
84431
85195
  async function extractAudio(path6, format, outDir, opts) {
84432
85196
  path6 = requireAbsolutePath(path6, "path");
84433
85197
  const dir2 = outDir ?? workDir();
84434
- mkdirSync18(dir2, { recursive: true });
85198
+ mkdirSync19(dir2, { recursive: true });
84435
85199
  const out = join35(dir2, `audio.${format}`);
84436
85200
  const codec2 = format === "mp3" ? ["-c:a", "libmp3lame", "-q:a", "2"] : format === "wav" ? ["-c:a", "pcm_s16le"] : ["-c:a", "aac", "-b:a", "192k"];
84437
85201
  const gain = opts?.gainDb ? ["-af", `volume=${opts.gainDb}dB`] : [];
@@ -84447,7 +85211,7 @@ async function isolateSpeakerAudio(path6, windows2, outDir) {
84447
85211
  const merged = mergeWindows(windows2).slice(0, 200);
84448
85212
  const enable = merged.map((w) => `between(t,${w.startSec},${w.endSec})`).join("+");
84449
85213
  const dir2 = outDir ?? workDir();
84450
- mkdirSync18(dir2, { recursive: true });
85214
+ mkdirSync19(dir2, { recursive: true });
84451
85215
  const out = join35(dir2, "speaker.m4a");
84452
85216
  const r = await run2(resolveFfmpeg(), ["-y", "-i", path6, "-vn", "-af", `volume=enable='1-min(1,${enable})':volume=0`, "-c:a", "aac", "-b:a", "192k", out], {
84453
85217
  timeoutMs: LONG_TIMEOUT_MS
@@ -84501,19 +85265,19 @@ function cleanupDir(dir2) {
84501
85265
  }
84502
85266
  }
84503
85267
  function readChunkBase64(path6) {
84504
- return readFileSync26(path6).toString("base64");
85268
+ return readFileSync27(path6).toString("base64");
84505
85269
  }
84506
85270
 
84507
85271
  // ../../packages/host-core/dist/video-upscale.js
84508
85272
  init_base_paths();
84509
85273
  import { spawn as spawn12 } from "node:child_process";
84510
- import { existsSync as existsSync15, mkdirSync as mkdirSync19, readFileSync as readFileSync27, readdirSync as readdirSync7 } from "node:fs";
84511
- import { join as join36, dirname as dirname14 } from "node:path";
85274
+ import { existsSync as existsSync16, mkdirSync as mkdirSync20, readFileSync as readFileSync28, readdirSync as readdirSync7 } from "node:fs";
85275
+ import { join as join36, dirname as dirname15 } from "node:path";
84512
85276
  var upscaleCwd;
84513
85277
  function upscaleSpawnCwd() {
84514
85278
  if (!upscaleCwd) {
84515
85279
  upscaleCwd = tessPath("media-work");
84516
- mkdirSync19(upscaleCwd, { recursive: true });
85280
+ mkdirSync20(upscaleCwd, { recursive: true });
84517
85281
  }
84518
85282
  return upscaleCwd;
84519
85283
  }
@@ -84525,12 +85289,12 @@ function resolveRealesrgan() {
84525
85289
  envBin,
84526
85290
  // Packaged app: extraResources → Resources/vendor/realesrgan/<plat>/…
84527
85291
  process.resourcesPath ? join36(process.resourcesPath, "vendor", "realesrgan", platDir, exe) : void 0
84528
- ].filter((p) => !!p && existsSync15(p));
85292
+ ].filter((p) => !!p && existsSync16(p));
84529
85293
  const bin = candidates[0] ?? fromPath2("realesrgan-ncnn-vulkan");
84530
85294
  if (!bin)
84531
85295
  return null;
84532
- const models = process.env.TESSERACT_REALESRGAN_MODELS?.trim() || join36(dirname14(bin), "models");
84533
- return existsSync15(models) ? { bin, models } : null;
85296
+ const models = process.env.TESSERACT_REALESRGAN_MODELS?.trim() || join36(dirname15(bin), "models");
85297
+ return existsSync16(models) ? { bin, models } : null;
84534
85298
  }
84535
85299
  function fromPath2(cmd) {
84536
85300
  try {
@@ -84552,8 +85316,8 @@ function installedRealesrModels() {
84552
85316
  return [];
84553
85317
  return REALESRGAN_MODELS.filter((m) => {
84554
85318
  if (m.scales.length > 1)
84555
- return m.scales.some((s) => existsSync15(join36(re.models, `${m.id}-x${s}.bin`)));
84556
- return existsSync15(join36(re.models, `${m.id}.bin`));
85319
+ return m.scales.some((s) => existsSync16(join36(re.models, `${m.id}-x${s}.bin`)));
85320
+ return existsSync16(join36(re.models, `${m.id}.bin`));
84557
85321
  }).map((m) => m.id);
84558
85322
  }
84559
85323
  function upscaleAdvert() {
@@ -84574,7 +85338,7 @@ async function realesrganGpuWorks() {
84574
85338
  const dir2 = workDir();
84575
85339
  const inP = join36(dir2, "p.png"), outP = join36(dir2, "p2.png");
84576
85340
  const gen = await run2(resolveFfmpeg(), ["-y", "-f", "lavfi", "-i", "testsrc=size=64x64:duration=1", "-frames:v", "1", inP], { timeoutMs: 15e3 });
84577
- if (!gen.ok || !existsSync15(inP)) {
85341
+ if (!gen.ok || !existsSync16(inP)) {
84578
85342
  gpuProbe = false;
84579
85343
  return false;
84580
85344
  }
@@ -84593,7 +85357,7 @@ async function realesrganGpuWorks() {
84593
85357
  code === 0 ? resolve16() : reject(new Error(`exit ${code}`));
84594
85358
  });
84595
85359
  });
84596
- gpuProbe = existsSync15(outP);
85360
+ gpuProbe = existsSync16(outP);
84597
85361
  } catch {
84598
85362
  gpuProbe = false;
84599
85363
  }
@@ -84612,8 +85376,8 @@ async function upscaleCapabilities(opts) {
84612
85376
  function resolveFalKey() {
84613
85377
  const home = tesseractHome();
84614
85378
  const file2 = join36(home, "daemon", "fal.key");
84615
- if (existsSync15(file2)) {
84616
- const k = readFileSync27(file2, "utf-8").trim();
85379
+ if (existsSync16(file2)) {
85380
+ const k = readFileSync28(file2, "utf-8").trim();
84617
85381
  if (k)
84618
85382
  return k;
84619
85383
  }
@@ -84660,8 +85424,8 @@ async function realesrganUpscale(path6, opts) {
84660
85424
  const scale = opts.scale ?? 2;
84661
85425
  const dir2 = opts.outDir ?? workDir();
84662
85426
  const fin = join36(dir2, "in"), fup = join36(dir2, "up");
84663
- mkdirSync19(fin, { recursive: true });
84664
- mkdirSync19(fup, { recursive: true });
85427
+ mkdirSync20(fin, { recursive: true });
85428
+ mkdirSync20(fup, { recursive: true });
84665
85429
  const fps = p.fps ?? 30;
84666
85430
  const src = path6;
84667
85431
  let extractSrc = src;
@@ -84728,7 +85492,7 @@ async function falTopazEnhance(path6, spec, opts) {
84728
85492
  path6 = requireAbsolutePath(path6, "path");
84729
85493
  const p = await probeMedia(path6);
84730
85494
  opts.onProgress?.(3, "Uploading to fal\u2026");
84731
- const bytes2 = readFileSync27(path6);
85495
+ const bytes2 = readFileSync28(path6);
84732
85496
  const videoUrl = await falUploadVideo(new Uint8Array(bytes2), "video/mp4", { apiKey: opts.apiKey });
84733
85497
  opts.onProgress?.(12, "Submitting Topaz job\u2026");
84734
85498
  const sub = await falTopazSubmit({ ...spec, videoUrl }, { apiKey: opts.apiKey });
@@ -84755,7 +85519,7 @@ async function falTopazEnhance(path6, spec, opts) {
84755
85519
  if (!dl.ok)
84756
85520
  throw new Error(`Downloading the fal result failed (HTTP ${dl.status}).`);
84757
85521
  const dir2 = opts.outDir ?? workDir();
84758
- mkdirSync19(dir2, { recursive: true });
85522
+ mkdirSync20(dir2, { recursive: true });
84759
85523
  const outPath = join36(dir2, "enhanced.mp4");
84760
85524
  const { writeFileSync: writeFileSync43 } = await import("node:fs");
84761
85525
  writeFileSync43(outPath, Buffer.from(await dl.arrayBuffer()));
@@ -84801,7 +85565,7 @@ async function smartEnhance(path6, args) {
84801
85565
  }
84802
85566
 
84803
85567
  // ../../packages/host-core/dist/video-effects.js
84804
- import { readFileSync as readFileSync28, mkdirSync as mkdirSync20, writeFileSync as writeFileSync21 } from "node:fs";
85568
+ import { readFileSync as readFileSync29, mkdirSync as mkdirSync21, writeFileSync as writeFileSync21 } from "node:fs";
84805
85569
  import { join as join37, basename as basename5, extname } from "node:path";
84806
85570
  init_daemon_settings();
84807
85571
  var IMG_MIME = { jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", webp: "image/webp", heic: "image/heic" };
@@ -84840,11 +85604,11 @@ async function applyEffect(effectId, inputs, opts) {
84840
85604
  const imageUrls = [];
84841
85605
  for (const p of imgs.slice(0, needImgs || imgs.length)) {
84842
85606
  const ext2 = extname(p).slice(1).toLowerCase();
84843
- imageUrls.push(await falUploadVideo(new Uint8Array(readFileSync28(p)), IMG_MIME[ext2] ?? "image/jpeg", { apiKey: key2, fileName: basename5(p) }));
85607
+ imageUrls.push(await falUploadVideo(new Uint8Array(readFileSync29(p)), IMG_MIME[ext2] ?? "image/jpeg", { apiKey: key2, fileName: basename5(p) }));
84844
85608
  }
84845
85609
  let videoUrl;
84846
85610
  if (inputs.videoPath)
84847
- videoUrl = await falUploadVideo(new Uint8Array(readFileSync28(inputs.videoPath)), "video/mp4", { apiKey: key2, fileName: basename5(inputs.videoPath) });
85611
+ videoUrl = await falUploadVideo(new Uint8Array(readFileSync29(inputs.videoPath)), "video/mp4", { apiKey: key2, fileName: basename5(inputs.videoPath) });
84848
85612
  const body = { ...def.params };
84849
85613
  const usesImageArray = def.modelPath.includes("/vidu/") || def.modelPath.includes("/kling-video/") || def.modelPath.includes("nano-banana");
84850
85614
  const arrayKey = def.modelPath.includes("nano-banana") ? "image_urls" : "input_image_urls";
@@ -84888,7 +85652,7 @@ async function applyEffect(effectId, inputs, opts) {
84888
85652
  if (!dl.ok)
84889
85653
  throw new Error(`Downloading the result failed (HTTP ${dl.status}).`);
84890
85654
  const dir2 = opts?.outDir ?? workDir();
84891
- mkdirSync20(dir2, { recursive: true });
85655
+ mkdirSync21(dir2, { recursive: true });
84892
85656
  const ext = media.isVideo ? "mp4" : extname(new URL(media.url).pathname).slice(1) || "png";
84893
85657
  const outPath = join37(dir2, `${effectId}.${ext}`);
84894
85658
  writeFileSync21(outPath, Buffer.from(await dl.arrayBuffer()));
@@ -84913,9 +85677,9 @@ async function applyGeminiImageEffect(def, inputs, opts) {
84913
85677
  ${inputs.prompt}` : "");
84914
85678
  opts?.onProgress?.(10, `Generating ${def.label}\u2026`);
84915
85679
  const provider = createImageEditProvider("google", { apiKey: key2, model: def.modelPath });
84916
- const out = await runImageEdit(provider, { op: "prompt", imageB64: readFileSync28(imgPath).toString("base64"), mime: IMG_MIME[ext] ?? "image/jpeg", prompt });
85680
+ const out = await runImageEdit(provider, { op: "prompt", imageB64: readFileSync29(imgPath).toString("base64"), mime: IMG_MIME[ext] ?? "image/jpeg", prompt });
84917
85681
  const dir2 = opts?.outDir ?? workDir();
84918
- mkdirSync20(dir2, { recursive: true });
85682
+ mkdirSync21(dir2, { recursive: true });
84919
85683
  const outPath = join37(dir2, `${def.id}.png`);
84920
85684
  writeFileSync21(outPath, Buffer.from(out.bytes));
84921
85685
  opts?.onProgress?.(100, "Done");
@@ -85035,13 +85799,13 @@ ${compact2}`;
85035
85799
  }
85036
85800
 
85037
85801
  // ../../packages/host-core/dist/video-vision.js
85038
- import { readFileSync as readFileSync29 } from "node:fs";
85802
+ import { readFileSync as readFileSync30 } from "node:fs";
85039
85803
  var BASE_URL3 = "https://generativelanguage.googleapis.com/v1beta";
85040
85804
  var MODEL = "gemini-3.5-flash";
85041
85805
  var TIMEOUT_MS = 6e4;
85042
85806
  async function reviewFrameGemini(framePath, intent, apiKey) {
85043
85807
  try {
85044
- const b642 = readFileSync29(framePath).toString("base64");
85808
+ const b642 = readFileSync30(framePath).toString("base64");
85045
85809
  const prompt = `This is a frame from an AI-generated video clip meant to show: "${intent}". Judge ONLY for obvious defects: melted/warped faces or hands, garbled text, broken anatomy, severe artifacts. Reply with STRICT JSON: {"acceptable": <true|false>, "note": "<\u226412 words, only if not acceptable>"}.`;
85046
85810
  const res = await fetch(`${BASE_URL3}/models/${MODEL}:generateContent`, {
85047
85811
  method: "POST",
@@ -85088,8 +85852,8 @@ function readDaemonKeyFile(name) {
85088
85852
  try {
85089
85853
  const home = tesseractHome();
85090
85854
  const f = join38(home, "daemon", name);
85091
- if (existsSync16(f)) {
85092
- const k = readFileSync30(f, "utf-8").trim();
85855
+ if (existsSync17(f)) {
85856
+ const k = readFileSync31(f, "utf-8").trim();
85093
85857
  if (k)
85094
85858
  return k;
85095
85859
  }
@@ -85248,7 +86012,7 @@ function createDaemonVideoEditRunner() {
85248
86012
  if (!apiKey)
85249
86013
  return { ok: false, error: "Voice cloning needs an ElevenLabs key (Settings \u2192 Voice)." };
85250
86014
  try {
85251
- const samples = sampleAudioPaths.slice(0, 25).map((p) => requireAbsolutePath(p, "sample audio path")).map((p) => ({ bytes: new Uint8Array(readFileSync30(p)), mime: audioMimeForPath(p), filename: basename6(p) }));
86015
+ const samples = sampleAudioPaths.slice(0, 25).map((p) => requireAbsolutePath(p, "sample audio path")).map((p) => ({ bytes: new Uint8Array(readFileSync31(p)), mime: audioMimeForPath(p), filename: basename6(p) }));
85252
86016
  const v = await cloneVoiceElevenLabs(name, samples, { apiKey, description });
85253
86017
  return { ok: true, voiceId: v.voiceId, name: v.name };
85254
86018
  } catch (e) {
@@ -85344,7 +86108,7 @@ function createDaemonVideoEditRunner() {
85344
86108
 
85345
86109
  // ../../packages/host-core/dist/support-submit.js
85346
86110
  init_credentials();
85347
- import { openSync as openSync4, fstatSync, readSync as readSync3, closeSync as closeSync4 } from "node:fs";
86111
+ import { openSync as openSync5, fstatSync, readSync as readSync4, closeSync as closeSync5 } from "node:fs";
85348
86112
  import { join as join39 } from "node:path";
85349
86113
 
85350
86114
  // ../../packages/host-core/dist/host-metrics.js
@@ -85384,19 +86148,19 @@ var LOG_TAIL_BYTES = 64 * 1024;
85384
86148
  function tail2(path6, bytes2 = LOG_TAIL_BYTES) {
85385
86149
  let fd = null;
85386
86150
  try {
85387
- fd = openSync4(path6, "r");
86151
+ fd = openSync5(path6, "r");
85388
86152
  const size = fstatSync(fd).size;
85389
86153
  const len = Math.min(size, bytes2);
85390
86154
  const start3 = Math.max(0, size - len);
85391
86155
  const buf = Buffer.alloc(len);
85392
- readSync3(fd, buf, 0, len, start3);
86156
+ readSync4(fd, buf, 0, len, start3);
85393
86157
  return buf.toString("utf8");
85394
86158
  } catch {
85395
86159
  return "";
85396
86160
  } finally {
85397
86161
  if (fd !== null) {
85398
86162
  try {
85399
- closeSync4(fd);
86163
+ closeSync5(fd);
85400
86164
  } catch {
85401
86165
  }
85402
86166
  }
@@ -86291,9 +87055,9 @@ async function replayTurn(turn) {
86291
87055
  } catch {
86292
87056
  }
86293
87057
  for (const msg of terminal) {
86294
- for (const sink of [...sinks]) {
87058
+ for (const sink2 of [...sinks]) {
86295
87059
  try {
86296
- sink(msg, turn.params.origin);
87060
+ sink2(msg, turn.params.origin);
86297
87061
  } catch {
86298
87062
  }
86299
87063
  }
@@ -86333,10 +87097,10 @@ function drainBrowserEvents(params) {
86333
87097
  return events;
86334
87098
  }
86335
87099
  setBrowserExtensionProbe(() => extensionBrowserConn != null);
86336
- function registerAgentSink(sink) {
86337
- sinks.add(sink);
87100
+ function registerAgentSink(sink2) {
87101
+ sinks.add(sink2);
86338
87102
  return () => {
86339
- sinks.delete(sink);
87103
+ sinks.delete(sink2);
86340
87104
  };
86341
87105
  }
86342
87106
  function emitAgentEvent(msg, origin) {
@@ -86587,7 +87351,7 @@ function refreshDaemonScheduling(b) {
86587
87351
  function daemonWorkspaceDir() {
86588
87352
  const dir2 = tessPath("workspace");
86589
87353
  try {
86590
- mkdirSync21(dir2, { recursive: true });
87354
+ mkdirSync22(dir2, { recursive: true });
86591
87355
  } catch {
86592
87356
  }
86593
87357
  return dir2;
@@ -86619,9 +87383,9 @@ function voiceUnavailableFrames(err2, reason) {
86619
87383
 
86620
87384
  // ../../packages/host-core/dist/fs-remote.js
86621
87385
  import { readdir as readdir4, readFile as readFile10, writeFile as writeFile9, mkdir as mkdir8, cp, rm as rm2, rename as renameAsync, stat as stat3 } from "node:fs/promises";
86622
- import { openSync as openSync5, readSync as readSync4, writeSync, closeSync as closeSync5, statSync as statSync8, existsSync as existsSync17, mkdtempSync, rmSync as rmSync5, readFileSync as readFileSync31, readdirSync as readdirSync8, watch, realpathSync as realpathSync4, constants as fsConstants } from "node:fs";
87386
+ import { openSync as openSync6, readSync as readSync5, writeSync, closeSync as closeSync6, statSync as statSync9, existsSync as existsSync18, mkdtempSync, rmSync as rmSync5, readFileSync as readFileSync32, readdirSync as readdirSync8, watch, realpathSync as realpathSync4, constants as fsConstants } from "node:fs";
86623
87387
  import { tmpdir as tmpdir5 } from "node:os";
86624
- import { basename as basename7, dirname as dirname15, join as join42, relative as relative5, resolve as resolve8, sep as sep6, isAbsolute as isAbsolute6 } from "node:path";
87388
+ import { basename as basename7, dirname as dirname16, join as join42, relative as relative5, resolve as resolve8, sep as sep6, isAbsolute as isAbsolute6 } from "node:path";
86625
87389
  import { execFile as execFile5 } from "node:child_process";
86626
87390
  import { promisify as promisify2 } from "node:util";
86627
87391
 
@@ -86673,12 +87437,12 @@ async function dirStats(root, opts) {
86673
87437
  }
86674
87438
  async function codeStats(root) {
86675
87439
  const start3 = Date.now();
86676
- const MAX_FILES = 25e3, MAX_BYTES2 = 256 * 1024 * 1024, TIME_MS = 12e3;
87440
+ const MAX_FILES = 25e3, MAX_BYTES3 = 256 * 1024 * 1024, TIME_MS = 12e3;
86677
87441
  const byLang = /* @__PURE__ */ new Map();
86678
87442
  let totalFiles = 0, totalLines = 0, bytes2 = 0, truncated = false;
86679
87443
  const stack = [root];
86680
87444
  while (stack.length) {
86681
- if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES2 || Date.now() - start3 > TIME_MS) {
87445
+ if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES3 || Date.now() - start3 > TIME_MS) {
86682
87446
  truncated = true;
86683
87447
  break;
86684
87448
  }
@@ -86690,7 +87454,7 @@ async function codeStats(root) {
86690
87454
  continue;
86691
87455
  }
86692
87456
  for (const e of ents) {
86693
- if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES2 || Date.now() - start3 > TIME_MS) {
87457
+ if (totalFiles >= MAX_FILES || bytes2 >= MAX_BYTES3 || Date.now() - start3 > TIME_MS) {
86694
87458
  truncated = true;
86695
87459
  break;
86696
87460
  }
@@ -86921,14 +87685,14 @@ function resolveParent(raw, root) {
86921
87685
  }
86922
87686
  function resolveUniqueName(dir2, name) {
86923
87687
  const direct = join42(dir2, name);
86924
- if (!existsSync17(direct))
87688
+ if (!existsSync18(direct))
86925
87689
  return direct;
86926
87690
  const dot = name.lastIndexOf(".");
86927
87691
  const base = dot > 0 ? name.slice(0, dot) : name;
86928
87692
  const ext = dot > 0 ? name.slice(dot) : "";
86929
87693
  for (let i = 2; i < 1e4; i++) {
86930
87694
  const candidate = join42(dir2, `${base} ${i}${ext}`);
86931
- if (!existsSync17(candidate))
87695
+ if (!existsSync18(candidate))
86932
87696
  return candidate;
86933
87697
  }
86934
87698
  return direct;
@@ -86962,7 +87726,7 @@ async function readRemoteBytes(root, path6) {
86962
87726
  if (!real)
86963
87727
  return { error: "Path is outside the shared root." };
86964
87728
  try {
86965
- const s = statSync8(real);
87729
+ const s = statSync9(real);
86966
87730
  if (!s.isFile())
86967
87731
  return { error: "Not a file" };
86968
87732
  if (s.size > REMOTE_READ_CAP)
@@ -86974,7 +87738,7 @@ async function readRemoteBytes(root, path6) {
86974
87738
  }
86975
87739
  var trashSeq = 0;
86976
87740
  function statId(real) {
86977
- const s = statSync8(real, { bigint: true });
87741
+ const s = statSync9(real, { bigint: true });
86978
87742
  return {
86979
87743
  size: Number(s.size),
86980
87744
  mtimeMs: Number(s.mtimeMs),
@@ -87005,7 +87769,7 @@ async function renderThumbnailImpl(real, maxPx) {
87005
87769
  const produced = readdirSync8(dir2).find((f) => f.toLowerCase().endsWith(".png"));
87006
87770
  if (!produced)
87007
87771
  return { error: "No thumbnail available." };
87008
- return { png: readFileSync31(join42(dir2, produced)).toString("base64") };
87772
+ return { png: readFileSync32(join42(dir2, produced)).toString("base64") };
87009
87773
  } catch (err2) {
87010
87774
  return { error: String(err2.message) };
87011
87775
  } finally {
@@ -87046,7 +87810,7 @@ var SAFE_SEG = /^[A-Za-z0-9._-]+$/;
87046
87810
  var TRASH_RETENTION_MS = 14 * 24 * 60 * 60 * 1e3;
87047
87811
  function pruneTrash(root) {
87048
87812
  const trashDir = join42(root, TRASH_DIR);
87049
- if (!existsSync17(trashDir))
87813
+ if (!existsSync18(trashDir))
87050
87814
  return;
87051
87815
  const cutoff = Date.now() - TRASH_RETENTION_MS;
87052
87816
  try {
@@ -87054,7 +87818,7 @@ function pruneTrash(root) {
87054
87818
  if (!e.isDirectory())
87055
87819
  continue;
87056
87820
  try {
87057
- const meta4 = JSON.parse(readFileSync31(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
87821
+ const meta4 = JSON.parse(readFileSync32(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
87058
87822
  if ((meta4.deletedAt ?? 0) < cutoff)
87059
87823
  rmSync5(join42(trashDir, e.name), { recursive: true, force: true });
87060
87824
  } catch {
@@ -87121,7 +87885,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87121
87885
  if (BINARY_EXT.has(ext))
87122
87886
  return { error: "Binary file \u2014 not shown in the editor." };
87123
87887
  try {
87124
- const s = statSync8(real);
87888
+ const s = statSync9(real);
87125
87889
  if (s.size > TEXT_SIZE_LIMIT)
87126
87890
  return { error: "File too large for text view." };
87127
87891
  return { content: await readFile10(real, "utf-8") };
@@ -87136,7 +87900,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87136
87900
  if (!real)
87137
87901
  return OUTSIDE("write");
87138
87902
  try {
87139
- await mkdir8(dirname15(real), { recursive: true });
87903
+ await mkdir8(dirname16(real), { recursive: true });
87140
87904
  await writeFile9(real, content, "utf-8");
87141
87905
  return { ok: true };
87142
87906
  } catch (err2) {
@@ -87150,7 +87914,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87150
87914
  if (!real)
87151
87915
  return OUTSIDE("write");
87152
87916
  try {
87153
- await mkdir8(dirname15(real), { recursive: true });
87917
+ await mkdir8(dirname16(real), { recursive: true });
87154
87918
  await writeFile9(real, Buffer.from(base643, "base64"));
87155
87919
  return { ok: true };
87156
87920
  } catch (err2) {
@@ -87167,10 +87931,10 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87167
87931
  let fd = null;
87168
87932
  try {
87169
87933
  if (off === 0) {
87170
- await mkdir8(dirname15(real), { recursive: true });
87171
- fd = openSync5(real, "w");
87934
+ await mkdir8(dirname16(real), { recursive: true });
87935
+ fd = openSync6(real, "w");
87172
87936
  } else
87173
- fd = openSync5(real, "r+");
87937
+ fd = openSync6(real, "r+");
87174
87938
  if (buf.length > 0)
87175
87939
  writeSync(fd, buf, 0, buf.length, off);
87176
87940
  return { ok: true, bytesWritten: buf.length };
@@ -87179,7 +87943,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87179
87943
  } finally {
87180
87944
  if (fd != null)
87181
87945
  try {
87182
- closeSync5(fd);
87946
+ closeSync6(fd);
87183
87947
  } catch {
87184
87948
  }
87185
87949
  }
@@ -87221,16 +87985,16 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87221
87985
  return { base64: "", bytesRead: 0 };
87222
87986
  let fd = null;
87223
87987
  try {
87224
- fd = openSync5(real, "r");
87988
+ fd = openSync6(real, "r");
87225
87989
  const buf = Buffer.alloc(len);
87226
- const bytesRead = readSync4(fd, buf, 0, len, off);
87990
+ const bytesRead = readSync5(fd, buf, 0, len, off);
87227
87991
  return { base64: buf.subarray(0, bytesRead).toString("base64"), bytesRead };
87228
87992
  } catch (err2) {
87229
87993
  return { error: String(err2.message) };
87230
87994
  } finally {
87231
87995
  if (fd != null)
87232
87996
  try {
87233
- closeSync5(fd);
87997
+ closeSync6(fd);
87234
87998
  } catch {
87235
87999
  }
87236
88000
  }
@@ -87241,7 +88005,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87241
88005
  if (!real)
87242
88006
  return { error: "Path is outside the shared root." };
87243
88007
  try {
87244
- const s = statSync8(real);
88008
+ const s = statSync9(real);
87245
88009
  if (s.size > REMOTE_READ_CAP)
87246
88010
  return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
87247
88011
  return { base64: (await readFile10(real)).toString("base64"), size: s.size };
@@ -87257,7 +88021,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87257
88021
  const target = join42(parent, name);
87258
88022
  if (!insideOk(target))
87259
88023
  return { ok: false, error: "Refusing to create a project outside the shared root." };
87260
- if (existsSync17(target))
88024
+ if (existsSync18(target))
87261
88025
  return { ok: false, error: `A folder named "${name}" already exists.` };
87262
88026
  try {
87263
88027
  await mkdir8(target, { recursive: true });
@@ -87275,7 +88039,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87275
88039
  const target = join42(parent, name);
87276
88040
  if (!insideOk(target))
87277
88041
  return OUTSIDE("create");
87278
- if (existsSync17(target))
88042
+ if (existsSync18(target))
87279
88043
  return { ok: false, error: `"${name}" already exists.` };
87280
88044
  try {
87281
88045
  if (op === "createFile")
@@ -87294,8 +88058,8 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87294
88058
  return { ok: false, error: "Invalid name." };
87295
88059
  if (!insideOk(oldPath))
87296
88060
  return OUTSIDE("rename");
87297
- const newPath = join42(dirname15(oldPath), newName);
87298
- if (existsSync17(newPath))
88061
+ const newPath = join42(dirname16(oldPath), newName);
88062
+ if (existsSync18(newPath))
87299
88063
  return { ok: false, error: `A file named "${newName}" already exists.` };
87300
88064
  try {
87301
88065
  await renameAsync(oldPath, newPath);
@@ -87341,7 +88105,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87341
88105
  }
87342
88106
  case "listTrash": {
87343
88107
  const trashDir = join42(root, TRASH_DIR);
87344
- if (!existsSync17(trashDir))
88108
+ if (!existsSync18(trashDir))
87345
88109
  return [];
87346
88110
  try {
87347
88111
  const out = [];
@@ -87349,7 +88113,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87349
88113
  if (!e.isDirectory())
87350
88114
  continue;
87351
88115
  try {
87352
- const meta4 = JSON.parse(readFileSync31(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
88116
+ const meta4 = JSON.parse(readFileSync32(join42(trashDir, e.name, ".fp-meta.json"), "utf-8"));
87353
88117
  out.push({ trashId: e.name, name: meta4.name, path: join42(trashDir, e.name, meta4.name), originalPath: meta4.originalPath, deletedAt: meta4.deletedAt });
87354
88118
  } catch {
87355
88119
  }
@@ -87364,19 +88128,19 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87364
88128
  if (!SAFE_SEG.test(id))
87365
88129
  return { ok: false, error: "Bad trash id." };
87366
88130
  const itemDir = join42(root, TRASH_DIR, id);
87367
- if (!existsSync17(itemDir))
88131
+ if (!existsSync18(itemDir))
87368
88132
  return { ok: false, error: "Not in trash." };
87369
88133
  try {
87370
- const meta4 = JSON.parse(readFileSync31(join42(itemDir, ".fp-meta.json"), "utf-8"));
88134
+ const meta4 = JSON.parse(readFileSync32(join42(itemDir, ".fp-meta.json"), "utf-8"));
87371
88135
  if (!validName(meta4.name))
87372
88136
  return { ok: false, error: "Bad trashed name." };
87373
88137
  const src = join42(itemDir, meta4.name);
87374
88138
  let dest = meta4.originalPath;
87375
88139
  if (!insideOk(dest))
87376
88140
  return OUTSIDE("restore");
87377
- if (existsSync17(dest))
87378
- dest = resolveUniqueName(dirname15(dest), meta4.name);
87379
- await mkdir8(dirname15(dest), { recursive: true });
88141
+ if (existsSync18(dest))
88142
+ dest = resolveUniqueName(dirname16(dest), meta4.name);
88143
+ await mkdir8(dirname16(dest), { recursive: true });
87380
88144
  await moveItem(src, dest);
87381
88145
  rmSync5(itemDir, { recursive: true, force: true });
87382
88146
  return { ok: true, path: dest };
@@ -87397,7 +88161,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
87397
88161
  continue;
87398
88162
  if (!insideOk(src))
87399
88163
  return OUTSIDE(op === "copyPaths" ? "copy from" : "move from");
87400
- if (op === "movePaths" && dirname15(src) === destDir) {
88164
+ if (op === "movePaths" && dirname16(src) === destDir) {
87401
88165
  newPaths.push(src);
87402
88166
  continue;
87403
88167
  }
@@ -87678,8 +88442,8 @@ function releaseDcClient(clientId) {
87678
88442
 
87679
88443
  // ../../packages/host-core/dist/fs-transfer.js
87680
88444
  import { readdir as readdir5, lstat as lstat2, mkdir as mkdir9, chmod, rm as rm3, readlink, symlink, stat as stat4 } from "node:fs/promises";
87681
- import { openSync as openSync6, readSync as readSync5, closeSync as closeSync6, existsSync as existsSync18, createWriteStream } from "node:fs";
87682
- import { basename as basename8, dirname as dirname16, join as join44, relative as relative7, sep as sep8 } from "node:path";
88445
+ import { openSync as openSync7, readSync as readSync6, closeSync as closeSync7, existsSync as existsSync19, createWriteStream } from "node:fs";
88446
+ import { basename as basename8, dirname as dirname17, join as join44, relative as relative7, sep as sep8 } from "node:path";
87683
88447
 
87684
88448
  // ../../packages/host-core/dist/active-link/paths.js
87685
88449
  init_base_paths();
@@ -87735,7 +88499,7 @@ function clearTimer(t) {
87735
88499
  }
87736
88500
  function uniqueDir(parent, name) {
87737
88501
  let candidate = join44(parent, name);
87738
- for (let i = 2; existsSync18(candidate) && i < 1e4; i++)
88502
+ for (let i = 2; existsSync19(candidate) && i < 1e4; i++)
87739
88503
  candidate = join44(parent, `${name} ${i}`);
87740
88504
  return candidate;
87741
88505
  }
@@ -87744,7 +88508,7 @@ function uniqueFile(parent, name) {
87744
88508
  const stem = dot > 0 ? name.slice(0, dot) : name;
87745
88509
  const ext = dot > 0 ? name.slice(dot) : "";
87746
88510
  let candidate = join44(parent, name);
87747
- for (let i = 2; existsSync18(candidate) && i < 1e4; i++)
88511
+ for (let i = 2; existsSync19(candidate) && i < 1e4; i++)
87748
88512
  candidate = join44(parent, `${stem} ${i}${ext}`);
87749
88513
  return candidate;
87750
88514
  }
@@ -87874,7 +88638,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
87874
88638
  producers.delete(transferId);
87875
88639
  return;
87876
88640
  }
87877
- const srcBase = manifest.singleFile ? dirname16(srcPath) : srcPath;
88641
+ const srcBase = manifest.singleFile ? dirname17(srcPath) : srcPath;
87878
88642
  send4({
87879
88643
  type: "fs:transferManifest",
87880
88644
  transferId,
@@ -87902,7 +88666,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
87902
88666
  const abs = join44(srcBase, f.rel.split("/").join(sep8));
87903
88667
  let fd = null;
87904
88668
  try {
87905
- fd = openSync6(abs, "r");
88669
+ fd = openSync7(abs, "r");
87906
88670
  if (f.size === 0) {
87907
88671
  send4({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset: 0, base64: "", eof: true }, { hostId: toHost });
87908
88672
  } else {
@@ -87912,7 +88676,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
87912
88676
  break;
87913
88677
  const len = Math.min(CHUNK2, f.size - offset);
87914
88678
  const buf = Buffer.alloc(len);
87915
- const read = readSync5(fd, buf, 0, len, offset);
88679
+ const read = readSync6(fd, buf, 0, len, offset);
87916
88680
  send4({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset, base64: buf.subarray(0, read).toString("base64"), eof: offset + len >= f.size }, { hostId: toHost });
87917
88681
  state3.sentBytes += read;
87918
88682
  }
@@ -87920,7 +88684,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
87920
88684
  } catch (e) {
87921
88685
  if (fd != null)
87922
88686
  try {
87923
- closeSync6(fd);
88687
+ closeSync7(fd);
87924
88688
  } catch {
87925
88689
  }
87926
88690
  failProducer(transferId, `Couldn't read ${f.rel}: ${e.message}`);
@@ -87928,7 +88692,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
87928
88692
  } finally {
87929
88693
  if (fd != null)
87930
88694
  try {
87931
- closeSync6(fd);
88695
+ closeSync7(fd);
87932
88696
  } catch {
87933
88697
  }
87934
88698
  }
@@ -88041,7 +88805,7 @@ async function beginInboundTransfer(msg, hostRoot, send4) {
88041
88805
  if (msg.singleFile) {
88042
88806
  let destFile = join44(parent, msg.destName);
88043
88807
  let createdFile = true;
88044
- if (existsSync18(destFile)) {
88808
+ if (existsSync19(destFile)) {
88045
88809
  if (msg.onCollision === "abort") {
88046
88810
  failNoState(`"${msg.destName}" already exists on the destination.`);
88047
88811
  return;
@@ -88066,7 +88830,7 @@ async function beginInboundTransfer(msg, hostRoot, send4) {
88066
88830
  }
88067
88831
  let destRoot = join44(parent, msg.destName);
88068
88832
  let createdRoot = false;
88069
- if (existsSync18(destRoot)) {
88833
+ if (existsSync19(destRoot)) {
88070
88834
  if (msg.onCollision === "abort") {
88071
88835
  failNoState(`"${msg.destName}" already exists on the destination.`);
88072
88836
  return;
@@ -88112,9 +88876,9 @@ async function writeInboundChunk(msg, send4) {
88112
88876
  try {
88113
88877
  if (msg.kind === "symlink") {
88114
88878
  const target = Buffer.from(msg.base64, "base64").toString("utf-8");
88115
- const resolved = join44(dirname16(abs), target);
88879
+ const resolved = join44(dirname17(abs), target);
88116
88880
  if (isInsideRoot(resolved, s.destRoot)) {
88117
- await mkdir9(dirname16(abs), { recursive: true }).catch(() => {
88881
+ await mkdir9(dirname17(abs), { recursive: true }).catch(() => {
88118
88882
  });
88119
88883
  await symlink(target, abs).catch(() => {
88120
88884
  });
@@ -88127,7 +88891,7 @@ async function writeInboundChunk(msg, send4) {
88127
88891
  if (s.curIx !== msg.fileIx || !s.curStream) {
88128
88892
  if (s.curStream)
88129
88893
  await new Promise((r) => s.curStream.end(r));
88130
- await mkdir9(dirname16(abs), { recursive: true }).catch(() => {
88894
+ await mkdir9(dirname17(abs), { recursive: true }).catch(() => {
88131
88895
  });
88132
88896
  s.curStream = createWriteStream(abs);
88133
88897
  s.curIx = msg.fileIx;
@@ -88723,12 +89487,12 @@ init_credentials();
88723
89487
  init_credentials();
88724
89488
  import { hostname as hostname3, platform } from "node:os";
88725
89489
  import { randomUUID as randomUUID21 } from "node:crypto";
88726
- import { chmodSync as chmodSync3, existsSync as existsSync20, mkdirSync as mkdirSync23, readFileSync as readFileSync33, writeFileSync as writeFileSync23 } from "node:fs";
89490
+ import { chmodSync as chmodSync3, existsSync as existsSync21, mkdirSync as mkdirSync24, readFileSync as readFileSync34, writeFileSync as writeFileSync23 } from "node:fs";
88727
89491
  import { join as join46 } from "node:path";
88728
89492
  var FILE = () => join46(daemonDir2(), "machine-identity.json");
88729
89493
  function readMachineIdentity() {
88730
89494
  try {
88731
- const m = JSON.parse(readFileSync33(FILE(), "utf-8"));
89495
+ const m = JSON.parse(readFileSync34(FILE(), "utf-8"));
88732
89496
  return m?.deviceToken && m?.publicId ? m : null;
88733
89497
  } catch {
88734
89498
  return null;
@@ -88736,7 +89500,7 @@ function readMachineIdentity() {
88736
89500
  }
88737
89501
  function write(m) {
88738
89502
  try {
88739
- mkdirSync23(daemonDir2(), { recursive: true, mode: 448 });
89503
+ mkdirSync24(daemonDir2(), { recursive: true, mode: 448 });
88740
89504
  writeFileSync23(FILE(), JSON.stringify(m, null, 2), { mode: 384 });
88741
89505
  chmodSync3(FILE(), 384);
88742
89506
  } catch {
@@ -88832,14 +89596,14 @@ function getMachinePublicId() {
88832
89596
 
88833
89597
  // ../../packages/host-core/dist/active-link/engine.js
88834
89598
  import { lstat as lstat7, readlink as readlink4, rm as rm4, mkdir as mkdir11, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile10 } from "node:fs/promises";
88835
- import { existsSync as existsSync22 } from "node:fs";
88836
- import { dirname as dirname21, join as join51, resolve as resolve11 } from "node:path";
89599
+ import { existsSync as existsSync23 } from "node:fs";
89600
+ import { dirname as dirname22, join as join51, resolve as resolve11 } from "node:path";
88837
89601
 
88838
89602
  // ../../packages/host-core/dist/active-link/blocks.js
88839
89603
  import { createHash as createHash4 } from "node:crypto";
88840
89604
  import { createReadStream } from "node:fs";
88841
89605
  import { open, mkdir as mkdir10, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
88842
- import { dirname as dirname18 } from "node:path";
89606
+ import { dirname as dirname19 } from "node:path";
88843
89607
  var CHUNK3 = 1024 * 1024;
88844
89608
  var MAX_INFLIGHT2 = 8 * CHUNK3;
88845
89609
  var IDLE_MS2 = 6e4;
@@ -88967,7 +89731,7 @@ var StagingWriter = class {
88967
89731
  }
88968
89732
  async ensureOpen() {
88969
89733
  if (!this.fh) {
88970
- await mkdir10(dirname18(this.stagingPath), { recursive: true });
89734
+ await mkdir10(dirname19(this.stagingPath), { recursive: true });
88971
89735
  this.fh = await open(this.stagingPath, "w");
88972
89736
  }
88973
89737
  return this.fh;
@@ -88997,7 +89761,7 @@ var StagingWriter = class {
88997
89761
  });
88998
89762
  await fh.close();
88999
89763
  this.fh = null;
89000
- await mkdir10(dirname18(dest), { recursive: true });
89764
+ await mkdir10(dirname19(dest), { recursive: true });
89001
89765
  await chmod2(this.stagingPath, mode & 511).catch(() => {
89002
89766
  });
89003
89767
  const secs = mtimeMs / 1e3;
@@ -89030,7 +89794,7 @@ var BlockAssembler = class {
89030
89794
  this.stagingPath = stagingPath;
89031
89795
  }
89032
89796
  async open() {
89033
- await mkdir10(dirname18(this.stagingPath), { recursive: true });
89797
+ await mkdir10(dirname19(this.stagingPath), { recursive: true });
89034
89798
  this.fh = await open(this.stagingPath, "w");
89035
89799
  }
89036
89800
  /** Write a received block at its byte offset (index * CHUNK). */
@@ -89074,7 +89838,7 @@ var BlockAssembler = class {
89074
89838
  });
89075
89839
  return false;
89076
89840
  }
89077
- await mkdir10(dirname18(dest), { recursive: true });
89841
+ await mkdir10(dirname19(dest), { recursive: true });
89078
89842
  await chmod2(this.stagingPath, mode & 511).catch(() => {
89079
89843
  });
89080
89844
  const secs = mtimeMs / 1e3;
@@ -89097,7 +89861,7 @@ var BlockAssembler = class {
89097
89861
  };
89098
89862
 
89099
89863
  // ../../packages/host-core/dist/active-link/manifest.js
89100
- import { readFileSync as readFileSync34, writeFileSync as writeFileSync24, mkdirSync as mkdirSync24, existsSync as existsSync21, renameSync as renameSync7 } from "node:fs";
89864
+ import { readFileSync as readFileSync35, writeFileSync as writeFileSync24, mkdirSync as mkdirSync25, existsSync as existsSync22, renameSync as renameSync8 } from "node:fs";
89101
89865
  import { join as join47 } from "node:path";
89102
89866
 
89103
89867
  // ../../packages/host-core/dist/active-link/reconcile.js
@@ -89138,7 +89902,7 @@ var LinkManifest = class {
89138
89902
  }
89139
89903
  load() {
89140
89904
  try {
89141
- const raw = JSON.parse(readFileSync34(this.file(), "utf-8"));
89905
+ const raw = JSON.parse(readFileSync35(this.file(), "utf-8"));
89142
89906
  this.records = new Map(Object.entries(raw.records ?? {}));
89143
89907
  this.tombstones = new Map(Object.entries(raw.tombstones ?? {}));
89144
89908
  } catch {
@@ -89219,15 +89983,15 @@ var LinkManifest = class {
89219
89983
  if (!this.dirty)
89220
89984
  return;
89221
89985
  try {
89222
- if (!existsSync21(this.dir))
89223
- mkdirSync24(this.dir, { recursive: true });
89986
+ if (!existsSync22(this.dir))
89987
+ mkdirSync25(this.dir, { recursive: true });
89224
89988
  const json3 = {
89225
89989
  records: Object.fromEntries(this.records),
89226
89990
  tombstones: Object.fromEntries(this.tombstones)
89227
89991
  };
89228
89992
  const tmp = `${this.file()}.tmp`;
89229
89993
  writeFileSync24(tmp, JSON.stringify(json3));
89230
- renameSync7(tmp, this.file());
89994
+ renameSync8(tmp, this.file());
89231
89995
  this.dirty = false;
89232
89996
  } catch {
89233
89997
  }
@@ -90236,9 +91000,9 @@ var NodeFsHandler = class {
90236
91000
  if (this.fsw.closed) {
90237
91001
  return;
90238
91002
  }
90239
- const dirname32 = sysPath.dirname(file2);
91003
+ const dirname33 = sysPath.dirname(file2);
90240
91004
  const basename14 = sysPath.basename(file2);
90241
- const parent = this.fsw._getWatchedDir(dirname32);
91005
+ const parent = this.fsw._getWatchedDir(dirname33);
90242
91006
  let prevStats = stats;
90243
91007
  if (parent.has(basename14))
90244
91008
  return;
@@ -90265,7 +91029,7 @@ var NodeFsHandler = class {
90265
91029
  prevStats = newStats2;
90266
91030
  }
90267
91031
  } catch (error51) {
90268
- this.fsw._remove(dirname32, basename14);
91032
+ this.fsw._remove(dirname33, basename14);
90269
91033
  }
90270
91034
  } else if (parent.has(basename14)) {
90271
91035
  const at = newStats.atimeMs;
@@ -91710,13 +92474,13 @@ var ActiveLinkEngine = class {
91710
92474
  * file so the path still exists — recorded as a FILE matching disk so the local
91711
92475
  * watcher doesn't churn. The target is containment-checked, never dereferenced. */
91712
92476
  async applySymlink(rel, dest, target, mtimeMs, mode) {
91713
- const resolved = resolve11(dirname21(dest), target);
92477
+ const resolved = resolve11(dirname22(dest), target);
91714
92478
  if (!isInsideRoot(resolved, this.opts.localRoot))
91715
92479
  return;
91716
92480
  const hash2 = hashString(target);
91717
92481
  const secs = mtimeMs / 1e3;
91718
92482
  try {
91719
- await mkdir11(dirname21(dest), { recursive: true });
92483
+ await mkdir11(dirname22(dest), { recursive: true });
91720
92484
  await rm4(dest, { force: true, recursive: true });
91721
92485
  try {
91722
92486
  await symlink2(target, dest);
@@ -91768,7 +92532,7 @@ var ActiveLinkEngine = class {
91768
92532
  return;
91769
92533
  if (fromRec && fromRec.kind === "file") {
91770
92534
  try {
91771
- await mkdir11(dirname21(toAbs2), { recursive: true });
92535
+ await mkdir11(dirname22(toAbs2), { recursive: true });
91772
92536
  await rename2(fromAbs, toAbs2);
91773
92537
  const secs = mtimeMs / 1e3;
91774
92538
  await utimes2(toAbs2, secs, secs).catch(() => {
@@ -91793,7 +92557,7 @@ var ActiveLinkEngine = class {
91793
92557
  await this.maybeRefreshAllow(rels);
91794
92558
  const state3 = /* @__PURE__ */ new Map();
91795
92559
  for (const rel of rels) {
91796
- if (existsSync22(absOf(this.opts.localRoot, rel)) && !this.isSynced(rel)) {
92560
+ if (existsSync23(absOf(this.opts.localRoot, rel)) && !this.isSynced(rel)) {
91797
92561
  this.manifest.dropRecord(rel);
91798
92562
  continue;
91799
92563
  }
@@ -91897,7 +92661,7 @@ var ActiveLinkEngine = class {
91897
92661
  for (const rel of this.manifest.recordRels()) {
91898
92662
  if (records.has(rel))
91899
92663
  continue;
91900
- if (existsSync22(absOf(this.opts.localRoot, rel)))
92664
+ if (existsSync23(absOf(this.opts.localRoot, rel)))
91901
92665
  this.manifest.dropRecord(rel);
91902
92666
  else
91903
92667
  this.manifest.setTombstone(rel, now2);
@@ -91968,14 +92732,14 @@ var ActiveLinkEngine = class {
91968
92732
  };
91969
92733
 
91970
92734
  // ../../packages/host-core/dist/active-link/config.js
91971
- import { readFileSync as readFileSync35, writeFileSync as writeFileSync25, mkdirSync as mkdirSync25, existsSync as existsSync23, renameSync as renameSync8, watch as watch3 } from "node:fs";
92735
+ import { readFileSync as readFileSync36, writeFileSync as writeFileSync25, mkdirSync as mkdirSync26, existsSync as existsSync24, renameSync as renameSync9, watch as watch3 } from "node:fs";
91972
92736
  import { join as join52 } from "node:path";
91973
92737
  function configPath2() {
91974
92738
  return join52(activeLinkRoot(), "links.json");
91975
92739
  }
91976
92740
  function loadLinkConfigs() {
91977
92741
  try {
91978
- const raw = JSON.parse(readFileSync35(configPath2(), "utf-8"));
92742
+ const raw = JSON.parse(readFileSync36(configPath2(), "utf-8"));
91979
92743
  if (!Array.isArray(raw.links))
91980
92744
  return [];
91981
92745
  return raw.links.filter((c) => c && c.linkId && c.localRoot && c.peerHostId);
@@ -91986,11 +92750,11 @@ function loadLinkConfigs() {
91986
92750
  function writeAll(links) {
91987
92751
  try {
91988
92752
  const dir2 = activeLinkRoot();
91989
- if (!existsSync23(dir2))
91990
- mkdirSync25(dir2, { recursive: true });
92753
+ if (!existsSync24(dir2))
92754
+ mkdirSync26(dir2, { recursive: true });
91991
92755
  const tmp = `${configPath2()}.tmp`;
91992
92756
  writeFileSync25(tmp, JSON.stringify({ links }, null, 2));
91993
- renameSync8(tmp, configPath2());
92757
+ renameSync9(tmp, configPath2());
91994
92758
  } catch {
91995
92759
  }
91996
92760
  }
@@ -92012,7 +92776,7 @@ function pendingPath() {
92012
92776
  }
92013
92777
  function loadPendingDeprovisions() {
92014
92778
  try {
92015
- const raw = JSON.parse(readFileSync35(pendingPath(), "utf-8"));
92779
+ const raw = JSON.parse(readFileSync36(pendingPath(), "utf-8"));
92016
92780
  return Array.isArray(raw.pending) ? raw.pending.filter((p) => p && p.linkId && p.peerHostId) : [];
92017
92781
  } catch {
92018
92782
  return [];
@@ -92021,11 +92785,11 @@ function loadPendingDeprovisions() {
92021
92785
  function writePending(pending2) {
92022
92786
  try {
92023
92787
  const dir2 = activeLinkRoot();
92024
- if (!existsSync23(dir2))
92025
- mkdirSync25(dir2, { recursive: true });
92788
+ if (!existsSync24(dir2))
92789
+ mkdirSync26(dir2, { recursive: true });
92026
92790
  const tmp = `${pendingPath()}.tmp`;
92027
92791
  writeFileSync25(tmp, JSON.stringify({ pending: pending2 }, null, 2));
92028
- renameSync8(tmp, pendingPath());
92792
+ renameSync9(tmp, pendingPath());
92029
92793
  } catch {
92030
92794
  }
92031
92795
  }
@@ -92037,8 +92801,8 @@ function removeLinkConfig(linkId) {
92037
92801
  }
92038
92802
  function watchLinkConfigs(onChange) {
92039
92803
  const dir2 = activeLinkRoot();
92040
- if (!existsSync23(dir2))
92041
- mkdirSync25(dir2, { recursive: true });
92804
+ if (!existsSync24(dir2))
92805
+ mkdirSync26(dir2, { recursive: true });
92042
92806
  let timer2 = null;
92043
92807
  let watcher = null;
92044
92808
  try {
@@ -92183,7 +92947,7 @@ function routeInboundLinkFrame(frame) {
92183
92947
  init_dist5();
92184
92948
 
92185
92949
  // ../../packages/host-core/dist/pty-manager.js
92186
- import { existsSync as existsSync24 } from "node:fs";
92950
+ import { existsSync as existsSync25 } from "node:fs";
92187
92951
  import { homedir as homedir8 } from "node:os";
92188
92952
  var ptyPromise = null;
92189
92953
  function loadPty() {
@@ -92205,7 +92969,7 @@ function key(clientId, ptyId) {
92205
92969
  var sessions2 = /* @__PURE__ */ new Map();
92206
92970
  var FLUSH_MS = 8;
92207
92971
  var FLUSH_BYTES = 64 * 1024;
92208
- function flush(ptyId, s, sink) {
92972
+ function flush(ptyId, s, sink2) {
92209
92973
  if (s.timer) {
92210
92974
  clearTimeout(s.timer);
92211
92975
  s.timer = null;
@@ -92215,9 +92979,9 @@ function flush(ptyId, s, sink) {
92215
92979
  const joined = s.buf.join("");
92216
92980
  s.buf = [];
92217
92981
  s.bytes = 0;
92218
- sink.output(ptyId, Buffer.from(joined, "utf8").toString("base64"));
92982
+ sink2.output(ptyId, Buffer.from(joined, "utf8").toString("base64"));
92219
92983
  }
92220
- async function openPty(opts, sink) {
92984
+ async function openPty(opts, sink2) {
92221
92985
  const pty = await loadPty();
92222
92986
  if (!pty)
92223
92987
  throw new Error("Terminal support is unavailable on this machine.");
@@ -92247,14 +93011,14 @@ async function openPty(opts, sink) {
92247
93011
  s.buf.push(data);
92248
93012
  s.bytes += data.length;
92249
93013
  if (s.bytes >= FLUSH_BYTES)
92250
- flush(opts.ptyId, s, sink);
93014
+ flush(opts.ptyId, s, sink2);
92251
93015
  else if (!s.timer)
92252
- s.timer = setTimeout(() => flush(opts.ptyId, s, sink), FLUSH_MS);
93016
+ s.timer = setTimeout(() => flush(opts.ptyId, s, sink2), FLUSH_MS);
92253
93017
  });
92254
93018
  proc.onExit(({ exitCode, signal }) => {
92255
- flush(opts.ptyId, s, sink);
93019
+ flush(opts.ptyId, s, sink2);
92256
93020
  sessions2.delete(k);
92257
- sink.exit(opts.ptyId, exitCode ?? null, signal ?? null);
93021
+ sink2.exit(opts.ptyId, exitCode ?? null, signal ?? null);
92258
93022
  });
92259
93023
  return { pid: proc.pid };
92260
93024
  }
@@ -92346,7 +93110,7 @@ function listUnix() {
92346
93110
  const seen = /* @__PURE__ */ new Set();
92347
93111
  const loginShell = process.env.SHELL || "";
92348
93112
  const add2 = (id, path6) => {
92349
- if (!path6 || seen.has(path6) || !existsSync24(path6))
93113
+ if (!path6 || seen.has(path6) || !existsSync25(path6))
92350
93114
  return;
92351
93115
  seen.add(path6);
92352
93116
  out.push(mk(id, path6, path6 === loginShell));
@@ -92378,7 +93142,7 @@ function listWindows() {
92378
93142
  const gitBash = `${pf}\\Git\\bin\\bash.exe`;
92379
93143
  const pwsh7 = `${pf}\\PowerShell\\7\\pwsh.exe`;
92380
93144
  const add2 = (id, path6, label, isDefault = false) => {
92381
- if (path6 && existsSync24(path6))
93145
+ if (path6 && existsSync25(path6))
92382
93146
  out.push(mk(id, path6, isDefault, label));
92383
93147
  };
92384
93148
  add2("powershell", winPwsh, "Windows PowerShell", true);
@@ -92437,7 +93201,7 @@ function resolveCwd(cwd, hostRoot) {
92437
93201
  const fallback = hostRoot || homedir8();
92438
93202
  if (!cwd)
92439
93203
  return fallback;
92440
- if (!existsSync24(cwd))
93204
+ if (!existsSync25(cwd))
92441
93205
  return fallback;
92442
93206
  if (hostRoot && !isInsideRoot(cwd, hostRoot))
92443
93207
  return hostRoot;
@@ -92498,7 +93262,12 @@ function setHostDaemonRole(on) {
92498
93262
  teardownHostRole();
92499
93263
  }
92500
93264
  }
93265
+ function rdeskOrMeshOnlyBuild() {
93266
+ return process.env.CCB_RDESK_ONLY === "1" || process.env.CCB_MESH_ONLY === "1";
93267
+ }
92501
93268
  function sharingEnabled() {
93269
+ if (rdeskOrMeshOnlyBuild())
93270
+ return false;
92502
93271
  return sharing || hostDaemonRole || process.env.CCB_HOST_DAEMON === "1";
92503
93272
  }
92504
93273
  var serverSelected = false;
@@ -92900,7 +93669,7 @@ function provisionActiveLinkMirror(payload) {
92900
93669
  if (!isInsideRoot(localRoot, HOST_ROOT))
92901
93670
  return;
92902
93671
  try {
92903
- mkdirSync26(localRoot, { recursive: true });
93672
+ mkdirSync27(localRoot, { recursive: true });
92904
93673
  } catch {
92905
93674
  }
92906
93675
  saveLinkConfig({
@@ -93325,12 +94094,12 @@ async function serveInboundTerm(p, driverClientId) {
93325
94094
  const route2 = driverClientId ? { clientId: driverClientId } : {};
93326
94095
  switch (p.type) {
93327
94096
  case "term:open": {
93328
- const sink = {
94097
+ const sink2 = {
93329
94098
  output: (ptyId, base643) => send3("term", { type: "term:output", ptyId, base64: base643 }, route2),
93330
94099
  exit: (ptyId, exitCode, signal) => send3("term", { type: "term:exit", ptyId, exitCode, signal }, route2)
93331
94100
  };
93332
94101
  try {
93333
- const { pid } = await openPty({ ptyId: p.ptyId, clientId: driverClientId, shell: p.shell, args: p.args, cwd: p.cwd, cols: p.cols, rows: p.rows, env: p.env, hostRoot: HOST_CONTAIN }, sink);
94102
+ const { pid } = await openPty({ ptyId: p.ptyId, clientId: driverClientId, shell: p.shell, args: p.args, cwd: p.cwd, cols: p.cols, rows: p.rows, env: p.env, hostRoot: HOST_CONTAIN }, sink2);
93334
94103
  send3("term", { type: "term:opened", ptyId: p.ptyId, requestId: p.requestId, pid }, route2);
93335
94104
  } catch (err2) {
93336
94105
  send3("term", { type: "term:openError", ptyId: p.ptyId, requestId: p.requestId, error: err2 instanceof Error ? err2.message : String(err2) }, route2);
@@ -93474,6 +94243,8 @@ function stopHeartbeat() {
93474
94243
  }
93475
94244
  }
93476
94245
  function registerAsHost() {
94246
+ if (rdeskOrMeshOnlyBuild())
94247
+ return;
93477
94248
  void ensureP2pReady();
93478
94249
  const kind = process.env.CCB_HOST_KIND === "cloud" ? "cloud" : void 0;
93479
94250
  const name = kind === "cloud" ? "Cloud agent" : hostname4();
@@ -95313,7 +96084,7 @@ function setInProcConnector(fn) {
95313
96084
 
95314
96085
  // ../../packages/host-core/dist/rdesk/server-prefs.js
95315
96086
  init_credentials();
95316
- import { readFileSync as readFileSync36, writeFileSync as writeFileSync26 } from "node:fs";
96087
+ import { readFileSync as readFileSync37, writeFileSync as writeFileSync26 } from "node:fs";
95317
96088
  import { join as join55 } from "node:path";
95318
96089
  function rdeskServerPrefsPath() {
95319
96090
  return join55(daemonDir2(), "rdesk-server.json");
@@ -95328,7 +96099,7 @@ var DEFAULTS2 = {
95328
96099
  };
95329
96100
  function readRdeskServerPrefs() {
95330
96101
  try {
95331
- const p = JSON.parse(readFileSync36(rdeskServerPrefsPath(), "utf8"));
96102
+ const p = JSON.parse(readFileSync37(rdeskServerPrefsPath(), "utf8"));
95332
96103
  return {
95333
96104
  // `!== false` (not `?? true`): only an explicit opt-out disables sharing, so a
95334
96105
  // partially-written or older prefs file never silently turns the machine off.
@@ -95361,7 +96132,7 @@ function rdeskSharingEnabled() {
95361
96132
  // ../../packages/host-core/dist/rdesk/password.js
95362
96133
  init_credentials();
95363
96134
  import { scryptSync, randomBytes as randomBytes5, timingSafeEqual as timingSafeEqual4, randomInt } from "node:crypto";
95364
- import { readFileSync as readFileSync37, writeFileSync as writeFileSync27, existsSync as existsSync25, unlinkSync as unlinkSync3 } from "node:fs";
96135
+ import { readFileSync as readFileSync38, writeFileSync as writeFileSync27, existsSync as existsSync26, unlinkSync as unlinkSync3 } from "node:fs";
95365
96136
  import { join as join56 } from "node:path";
95366
96137
  function pwFile() {
95367
96138
  return join56(daemonDir2(), "rdesk-password.json");
@@ -95379,27 +96150,27 @@ function generatePassword() {
95379
96150
  }
95380
96151
  function writePlain(password) {
95381
96152
  try {
95382
- const safe = electronModule()?.safeStorage;
95383
- if (!safe?.isEncryptionAvailable())
96153
+ const safe2 = electronModule()?.safeStorage;
96154
+ if (!safe2?.isEncryptionAvailable())
95384
96155
  return;
95385
- writeFileSync27(pwPlainFile(), safe.encryptString(password), { mode: 384 });
96156
+ writeFileSync27(pwPlainFile(), safe2.encryptString(password), { mode: 384 });
95386
96157
  } catch {
95387
96158
  }
95388
96159
  }
95389
96160
  function canRevealRdeskPassword() {
95390
96161
  try {
95391
- const safe = electronModule()?.safeStorage;
95392
- return !!safe?.isEncryptionAvailable() && existsSync25(pwPlainFile());
96162
+ const safe2 = electronModule()?.safeStorage;
96163
+ return !!safe2?.isEncryptionAvailable() && existsSync26(pwPlainFile());
95393
96164
  } catch {
95394
96165
  return false;
95395
96166
  }
95396
96167
  }
95397
96168
  function readRdeskPasswordPlain() {
95398
96169
  try {
95399
- const safe = electronModule()?.safeStorage;
95400
- if (!safe?.isEncryptionAvailable())
96170
+ const safe2 = electronModule()?.safeStorage;
96171
+ if (!safe2?.isEncryptionAvailable())
95401
96172
  return null;
95402
- return safe.decryptString(readFileSync37(pwPlainFile()));
96173
+ return safe2.decryptString(readFileSync38(pwPlainFile()));
95403
96174
  } catch {
95404
96175
  return null;
95405
96176
  }
@@ -95432,7 +96203,7 @@ function ensureRdeskPassword() {
95432
96203
  return regenerateRdeskPassword();
95433
96204
  }
95434
96205
  function hasRdeskPassword() {
95435
- return !!process.env.CCB_RDESK_PASSWORD || existsSync25(pwFile());
96206
+ return !!process.env.CCB_RDESK_PASSWORD || existsSync26(pwFile());
95436
96207
  }
95437
96208
  function verifyRdeskPassword(password) {
95438
96209
  if (!password)
@@ -95441,7 +96212,7 @@ function verifyRdeskPassword(password) {
95441
96212
  if (override)
95442
96213
  return password.length === override.length && timingSafeEqual4(Buffer.from(password), Buffer.from(override));
95443
96214
  try {
95444
- const { salt, hash: hash2 } = JSON.parse(readFileSync37(pwFile(), "utf8"));
96215
+ const { salt, hash: hash2 } = JSON.parse(readFileSync38(pwFile(), "utf8"));
95445
96216
  const got = scryptSync(password, Buffer.from(salt, "hex"), 32);
95446
96217
  const want = Buffer.from(hash2, "hex");
95447
96218
  return got.length === want.length && timingSafeEqual4(got, want);
@@ -96007,8 +96778,8 @@ function createPasskeyRegistration(rpId) {
96007
96778
 
96008
96779
  // ../../packages/host-core/dist/vault/manager.js
96009
96780
  init_base_paths();
96010
- import { mkdirSync as mkdirSync29, readFileSync as readFileSync40, writeFileSync as writeFileSync30 } from "node:fs";
96011
- import { dirname as dirname23 } from "node:path";
96781
+ import { mkdirSync as mkdirSync30, readFileSync as readFileSync41, writeFileSync as writeFileSync30 } from "node:fs";
96782
+ import { dirname as dirname24 } from "node:path";
96012
96783
 
96013
96784
  // ../../packages/vault-core/dist/crypto.js
96014
96785
  init_argon2();
@@ -97032,8 +97803,8 @@ function makeDaemonVaultApi(getOrigin, getToken2) {
97032
97803
 
97033
97804
  // ../../packages/host-core/dist/vault/persistence.js
97034
97805
  init_base_paths();
97035
- import { existsSync as existsSync26, mkdirSync as mkdirSync27, readFileSync as readFileSync38, writeFileSync as writeFileSync28, unlinkSync as unlinkSync4 } from "node:fs";
97036
- import { dirname as dirname22 } from "node:path";
97806
+ import { existsSync as existsSync27, mkdirSync as mkdirSync28, readFileSync as readFileSync39, writeFileSync as writeFileSync28, unlinkSync as unlinkSync4 } from "node:fs";
97807
+ import { dirname as dirname23 } from "node:path";
97037
97808
  function vaultStoreFile() {
97038
97809
  return homePath(".tesseract", "vault", "vault.json");
97039
97810
  }
@@ -97044,9 +97815,9 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
97044
97815
  return {
97045
97816
  load() {
97046
97817
  try {
97047
- if (!existsSync26(file2()))
97818
+ if (!existsSync27(file2()))
97048
97819
  return null;
97049
- const parsed = JSON.parse(readFileSync38(file2(), "utf8"));
97820
+ const parsed = JSON.parse(readFileSync39(file2(), "utf8"));
97050
97821
  if (!parsed || typeof parsed !== "object")
97051
97822
  return null;
97052
97823
  return { meta: parsed.meta ?? null, items: Array.isArray(parsed.items) ? parsed.items : [] };
@@ -97056,28 +97827,28 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
97056
97827
  },
97057
97828
  save(state3) {
97058
97829
  try {
97059
- mkdirSync27(dirname22(file2()), { recursive: true, mode: 448 });
97830
+ mkdirSync28(dirname23(file2()), { recursive: true, mode: 448 });
97060
97831
  writeFileSync28(file2(), JSON.stringify(state3), { mode: 384 });
97061
97832
  } catch {
97062
97833
  }
97063
97834
  },
97064
97835
  loadDeviceKey() {
97065
97836
  try {
97066
- return existsSync26(deviceKeyFile()) ? readFileSync38(deviceKeyFile(), "utf8").trim() || null : null;
97837
+ return existsSync27(deviceKeyFile()) ? readFileSync39(deviceKeyFile(), "utf8").trim() || null : null;
97067
97838
  } catch {
97068
97839
  return null;
97069
97840
  }
97070
97841
  },
97071
97842
  saveDeviceKey(base64Key) {
97072
97843
  try {
97073
- mkdirSync27(dirname22(deviceKeyFile()), { recursive: true, mode: 448 });
97844
+ mkdirSync28(dirname23(deviceKeyFile()), { recursive: true, mode: 448 });
97074
97845
  writeFileSync28(deviceKeyFile(), base64Key, { mode: 384 });
97075
97846
  } catch {
97076
97847
  }
97077
97848
  },
97078
97849
  clearDeviceKey() {
97079
97850
  try {
97080
- if (existsSync26(deviceKeyFile()))
97851
+ if (existsSync27(deviceKeyFile()))
97081
97852
  unlinkSync4(deviceKeyFile());
97082
97853
  } catch {
97083
97854
  }
@@ -97087,7 +97858,7 @@ function makeVaultPersistence(file2 = vaultStoreFile, deviceKeyFile = vaultDevic
97087
97858
 
97088
97859
  // ../../packages/host-core/dist/vault/biometric.js
97089
97860
  init_base_paths();
97090
- import { existsSync as existsSync27, mkdirSync as mkdirSync28, readFileSync as readFileSync39, rmSync as rmSync6, writeFileSync as writeFileSync29 } from "node:fs";
97861
+ import { existsSync as existsSync28, mkdirSync as mkdirSync29, readFileSync as readFileSync40, rmSync as rmSync6, writeFileSync as writeFileSync29 } from "node:fs";
97091
97862
  import { join as join57 } from "node:path";
97092
97863
  async function electronBio() {
97093
97864
  if (!electronModule())
@@ -97105,7 +97876,7 @@ async function electronBio() {
97105
97876
  }
97106
97877
  function bioDir() {
97107
97878
  const d = homePath(".tesseract", "vault-bio");
97108
- mkdirSync28(d, { recursive: true, mode: 448 });
97879
+ mkdirSync29(d, { recursive: true, mode: 448 });
97109
97880
  return d;
97110
97881
  }
97111
97882
  function bioFile(id) {
@@ -97124,7 +97895,7 @@ async function biometricAvailable() {
97124
97895
  }
97125
97896
  }
97126
97897
  function biometricEnrolled(id) {
97127
- return existsSync27(bioFile(id));
97898
+ return existsSync28(bioFile(id));
97128
97899
  }
97129
97900
  async function biometricEnroll(id, base64Key) {
97130
97901
  const bio = await electronBio();
@@ -97135,13 +97906,13 @@ async function biometricEnroll(id, base64Key) {
97135
97906
  }
97136
97907
  async function biometricUnlock(id) {
97137
97908
  const f = bioFile(id);
97138
- if (!existsSync27(f))
97909
+ if (!existsSync28(f))
97139
97910
  throw new Error("Touch ID is not set up for this vault.");
97140
97911
  const bio = await electronBio();
97141
97912
  if (!bio)
97142
97913
  throw new Error("Touch ID is not available on this device.");
97143
97914
  await bio.systemPreferences.promptTouchID("unlock your vault");
97144
- return bio.safeStorage.decryptString(readFileSync39(f));
97915
+ return bio.safeStorage.decryptString(readFileSync40(f));
97145
97916
  }
97146
97917
  function biometricDisable(id) {
97147
97918
  try {
@@ -97171,7 +97942,7 @@ var VaultManager = class {
97171
97942
  // ── auto-lock ────────────────────────────────────────────────────────────────────
97172
97943
  loadAutoLock() {
97173
97944
  try {
97174
- const raw = JSON.parse(readFileSync40(settingsFile(), "utf8"));
97945
+ const raw = JSON.parse(readFileSync41(settingsFile(), "utf8"));
97175
97946
  return Number.isFinite(raw.autoLockMinutes) ? Math.max(0, raw.autoLockMinutes) : 0;
97176
97947
  } catch {
97177
97948
  return 0;
@@ -97179,7 +97950,7 @@ var VaultManager = class {
97179
97950
  }
97180
97951
  saveAutoLock() {
97181
97952
  try {
97182
- mkdirSync29(dirname23(settingsFile()), { recursive: true, mode: 448 });
97953
+ mkdirSync30(dirname24(settingsFile()), { recursive: true, mode: 448 });
97183
97954
  writeFileSync30(settingsFile(), JSON.stringify({ autoLockMinutes: this.autoLockMinutes }), { mode: 384 });
97184
97955
  } catch {
97185
97956
  }
@@ -98218,7 +98989,7 @@ async function startLocalServer(opts) {
98218
98989
 
98219
98990
  // ../../packages/host-core/dist/daemon-runtime.js
98220
98991
  init_base_paths();
98221
- import { readFileSync as readFileSync45, writeFileSync as writeFileSync38, existsSync as existsSync35, mkdirSync as mkdirSync37, unlinkSync as unlinkSync6, chmodSync as chmodSync7, statSync as statSync9 } from "node:fs";
98992
+ import { readFileSync as readFileSync46, writeFileSync as writeFileSync38, existsSync as existsSync36, mkdirSync as mkdirSync38, unlinkSync as unlinkSync6, chmodSync as chmodSync7, statSync as statSync10 } from "node:fs";
98222
98993
  import { execFileSync as execFileSync5 } from "node:child_process";
98223
98994
  import { join as join70 } from "node:path";
98224
98995
  import { randomBytes as randomBytes10 } from "node:crypto";
@@ -98227,7 +98998,7 @@ import { hostname as hostname5 } from "node:os";
98227
98998
  // ../../packages/shared/dist/daemon-registry.js
98228
98999
  init_base_paths();
98229
99000
  import { execFileSync as execFileSync3 } from "node:child_process";
98230
- import { existsSync as existsSync28, mkdirSync as mkdirSync30, readdirSync as readdirSync9, readFileSync as readFileSync41, readlinkSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync31 } from "node:fs";
99001
+ import { existsSync as existsSync29, mkdirSync as mkdirSync31, readdirSync as readdirSync9, readFileSync as readFileSync42, readlinkSync, unlinkSync as unlinkSync5, writeFileSync as writeFileSync31 } from "node:fs";
98231
99002
  import { join as join58 } from "node:path";
98232
99003
  var SUPERVISOR_PID = Number(process.env.CCB_DAEMON_SUPERVISOR_PID ?? 0) || 0;
98233
99004
  delete process.env.CCB_DAEMON_SUPERVISOR_PID;
@@ -98323,7 +99094,7 @@ function pidStillMatches(pid, rec) {
98323
99094
  }
98324
99095
  function registerSelfAsDaemon(version2) {
98325
99096
  try {
98326
- mkdirSync30(registryDir(), { recursive: true, mode: 448 });
99097
+ mkdirSync31(registryDir(), { recursive: true, mode: 448 });
98327
99098
  const rec = {
98328
99099
  pid: process.pid,
98329
99100
  startedAt: procStartedAt(process.pid),
@@ -98352,7 +99123,7 @@ function unregisterSelfAsDaemon() {
98352
99123
  }
98353
99124
  function readRecord(pid) {
98354
99125
  try {
98355
- return JSON.parse(readFileSync41(recordPath(pid), "utf-8"));
99126
+ return JSON.parse(readFileSync42(recordPath(pid), "utf-8"));
98356
99127
  } catch {
98357
99128
  return null;
98358
99129
  }
@@ -98366,7 +99137,7 @@ function allRegisteredPids() {
98366
99137
  }
98367
99138
  function registeredDaemons(selfPid) {
98368
99139
  const out = [];
98369
- if (!existsSync28(registryDir()))
99140
+ if (!existsSync29(registryDir()))
98370
99141
  return out;
98371
99142
  for (const pid of allRegisteredPids()) {
98372
99143
  if (pid === selfPid)
@@ -98458,7 +99229,7 @@ function liveDaemons() {
98458
99229
 
98459
99230
  // ../../packages/host-core/dist/device-identity.js
98460
99231
  import { join as join59 } from "node:path";
98461
- import { readFileSync as readFileSync42, writeFileSync as writeFileSync32, existsSync as existsSync29, mkdirSync as mkdirSync31, renameSync as renameSync9, chmodSync as chmodSync4 } from "node:fs";
99232
+ import { readFileSync as readFileSync43, writeFileSync as writeFileSync32, existsSync as existsSync30, mkdirSync as mkdirSync32, renameSync as renameSync10, chmodSync as chmodSync4 } from "node:fs";
98462
99233
  init_credentials();
98463
99234
  var cached2 = null;
98464
99235
  function identityPath() {
@@ -98468,7 +99239,7 @@ async function loadOrCreateDeviceIdentity() {
98468
99239
  if (cached2)
98469
99240
  return cached2;
98470
99241
  try {
98471
- const stored = JSON.parse(readFileSync42(identityPath(), "utf-8"));
99242
+ const stored = JSON.parse(readFileSync43(identityPath(), "utf-8"));
98472
99243
  if (stored?.privateJwk) {
98473
99244
  cached2 = await importIdentity(stored.privateJwk);
98474
99245
  return cached2;
@@ -98478,11 +99249,11 @@ async function loadOrCreateDeviceIdentity() {
98478
99249
  const kp = await generateIdentityKeyPair(true);
98479
99250
  const { privateJwk, publicRaw } = await exportIdentity(kp);
98480
99251
  const dir2 = daemonDir2();
98481
- if (!existsSync29(dir2))
98482
- mkdirSync31(dir2, { recursive: true, mode: 448 });
99252
+ if (!existsSync30(dir2))
99253
+ mkdirSync32(dir2, { recursive: true, mode: 448 });
98483
99254
  const tmp = `${identityPath()}.tmp`;
98484
99255
  writeFileSync32(tmp, JSON.stringify({ privateJwk, publicRaw, alg: "P256-ECDSA" }, null, 2), { mode: 384 });
98485
- renameSync9(tmp, identityPath());
99256
+ renameSync10(tmp, identityPath());
98486
99257
  try {
98487
99258
  chmodSync4(identityPath(), 384);
98488
99259
  } catch {
@@ -98500,7 +99271,7 @@ async function loadOrCreateSealingKey() {
98500
99271
  return sealingCached;
98501
99272
  const { subtle: subtle5 } = globalThis.crypto;
98502
99273
  try {
98503
- const stored = JSON.parse(readFileSync42(sealingPath(), "utf-8"));
99274
+ const stored = JSON.parse(readFileSync43(sealingPath(), "utf-8"));
98504
99275
  if (stored?.privateJwk && stored.publicRaw) {
98505
99276
  const privateKey = await subtle5.importKey("jwk", stored.privateJwk, EC_DH, true, ["deriveBits"]);
98506
99277
  sealingCached = { privateKey, publicRaw: unb64u(stored.publicRaw) };
@@ -98512,11 +99283,11 @@ async function loadOrCreateSealingKey() {
98512
99283
  const publicRaw = new Uint8Array(await subtle5.exportKey("raw", kp.publicKey));
98513
99284
  const privateJwk = await subtle5.exportKey("jwk", kp.privateKey);
98514
99285
  const dir2 = daemonDir2();
98515
- if (!existsSync29(dir2))
98516
- mkdirSync31(dir2, { recursive: true, mode: 448 });
99286
+ if (!existsSync30(dir2))
99287
+ mkdirSync32(dir2, { recursive: true, mode: 448 });
98517
99288
  const tmp = `${sealingPath()}.tmp`;
98518
99289
  writeFileSync32(tmp, JSON.stringify({ privateJwk, publicRaw: b64u(publicRaw), alg: "P256-ECDH" }, null, 2), { mode: 384 });
98519
- renameSync9(tmp, sealingPath());
99290
+ renameSync10(tmp, sealingPath());
98520
99291
  try {
98521
99292
  chmodSync4(sealingPath(), 384);
98522
99293
  } catch {
@@ -98579,8 +99350,8 @@ import { createRequire as createRequire4 } from "node:module";
98579
99350
 
98580
99351
  // ../../packages/host-core/dist/mesh/config.js
98581
99352
  init_credentials();
98582
- import { chmodSync as chmodSync5, existsSync as existsSync30, mkdirSync as mkdirSync32, readdirSync as readdirSync10, readFileSync as readFileSync43, renameSync as renameSync10, rmSync as rmSync7, writeFileSync as writeFileSync33 } from "node:fs";
98583
- import { dirname as dirname24, join as join60 } from "node:path";
99353
+ import { chmodSync as chmodSync5, existsSync as existsSync31, mkdirSync as mkdirSync33, readdirSync as readdirSync10, readFileSync as readFileSync44, renameSync as renameSync11, rmSync as rmSync7, writeFileSync as writeFileSync33 } from "node:fs";
99354
+ import { dirname as dirname25, join as join60 } from "node:path";
98584
99355
  function meshDir() {
98585
99356
  return join60(daemonDir2(), "mesh");
98586
99357
  }
@@ -98623,27 +99394,27 @@ var FILES = {
98623
99394
  function readIfPresent(name, dir2 = meshDir()) {
98624
99395
  const p = join60(dir2, name);
98625
99396
  try {
98626
- return existsSync30(p) ? new Uint8Array(readFileSync43(p)) : void 0;
99397
+ return existsSync31(p) ? new Uint8Array(readFileSync44(p)) : void 0;
98627
99398
  } catch {
98628
99399
  return void 0;
98629
99400
  }
98630
99401
  }
98631
99402
  function migrateSingleMesh() {
98632
99403
  const legacyGenesis = join60(meshDir(), FILES.genesis);
98633
- if (!existsSync30(legacyGenesis))
99404
+ if (!existsSync31(legacyGenesis))
98634
99405
  return null;
98635
99406
  const id = meshIdFromCert(readIfPresent(FILES.cert)) ?? LEGACY_MESH_ID;
98636
99407
  const dest = oneMeshDir(id);
98637
99408
  try {
98638
- mkdirSync32(dest, { recursive: true, mode: 448 });
99409
+ mkdirSync33(dest, { recursive: true, mode: 448 });
98639
99410
  chmodSync5(dest, 448);
98640
99411
  for (const f of Object.values(FILES)) {
98641
99412
  const from = join60(meshDir(), f);
98642
- if (existsSync30(from))
98643
- renameSync10(from, join60(dest, f));
99413
+ if (existsSync31(from))
99414
+ renameSync11(from, join60(dest, f));
98644
99415
  }
98645
99416
  const key2 = join60(dest, FILES.key);
98646
- if (existsSync30(key2))
99417
+ if (existsSync31(key2))
98647
99418
  chmodSync5(key2, 384);
98648
99419
  } catch {
98649
99420
  return null;
@@ -98666,14 +99437,14 @@ function listMeshIds() {
98666
99437
  }
98667
99438
  function readLocal(meshId) {
98668
99439
  try {
98669
- return JSON.parse(readFileSync43(join60(oneMeshDir(meshId), FILES.local), "utf8"));
99440
+ return JSON.parse(readFileSync44(join60(oneMeshDir(meshId), FILES.local), "utf8"));
98670
99441
  } catch {
98671
99442
  return null;
98672
99443
  }
98673
99444
  }
98674
99445
  function writeLocal(meshId, state3) {
98675
99446
  try {
98676
- mkdirSync32(oneMeshDir(meshId), { recursive: true, mode: 448 });
99447
+ mkdirSync33(oneMeshDir(meshId), { recursive: true, mode: 448 });
98677
99448
  writeFileSync33(join60(oneMeshDir(meshId), FILES.local), JSON.stringify(state3, null, 2), { mode: 384 });
98678
99449
  } catch {
98679
99450
  }
@@ -98720,7 +99491,7 @@ function saveMeshIdentity(id) {
98720
99491
  saveMesh(meshId, id);
98721
99492
  return;
98722
99493
  }
98723
- mkdirSync32(meshDir(), { recursive: true, mode: 448 });
99494
+ mkdirSync33(meshDir(), { recursive: true, mode: 448 });
98724
99495
  try {
98725
99496
  chmodSync5(meshDir(), 448);
98726
99497
  } catch {
@@ -98733,7 +99504,7 @@ function saveMeshIdentity(id) {
98733
99504
  }
98734
99505
  function saveMesh(meshId, id) {
98735
99506
  const dir2 = oneMeshDir(meshId);
98736
- mkdirSync32(dir2, { recursive: true, mode: 448 });
99507
+ mkdirSync33(dir2, { recursive: true, mode: 448 });
98737
99508
  try {
98738
99509
  chmodSync5(meshDir(), 448);
98739
99510
  } catch {
@@ -98767,7 +99538,7 @@ function statusPath(meshId) {
98767
99538
  function writeStatus(status2, meshId) {
98768
99539
  try {
98769
99540
  const p = statusPath(meshId);
98770
- mkdirSync32(dirname24(p), { recursive: true, mode: 448 });
99541
+ mkdirSync33(dirname25(p), { recursive: true, mode: 448 });
98771
99542
  writeFileSync33(p, JSON.stringify({ ...status2, at: Date.now() }, null, 2));
98772
99543
  } catch {
98773
99544
  }
@@ -98780,7 +99551,7 @@ function clearStatus(meshId) {
98780
99551
  }
98781
99552
  function readStatus(meshId) {
98782
99553
  try {
98783
- const raw = JSON.parse(readFileSync43(statusPath(meshId), "utf8"));
99554
+ const raw = JSON.parse(readFileSync44(statusPath(meshId), "utf8"));
98784
99555
  if (typeof raw.at !== "number")
98785
99556
  return null;
98786
99557
  return { ...raw, at: raw.at, stale: Date.now() - raw.at > STATUS_STALE_MS };
@@ -98792,7 +99563,7 @@ function cacheBundle(bundle, meshId) {
98792
99563
  try {
98793
99564
  const id = meshId ?? listMeshIds()[0];
98794
99565
  const dir2 = id === void 0 ? meshDir() : oneMeshDir(id);
98795
- mkdirSync32(dir2, { recursive: true, mode: 448 });
99566
+ mkdirSync33(dir2, { recursive: true, mode: 448 });
98796
99567
  writeFileSync33(join60(dir2, FILES.bundle), bundle);
98797
99568
  } catch {
98798
99569
  }
@@ -99845,7 +100616,7 @@ function startNodes(log9) {
99845
100616
  }
99846
100617
 
99847
100618
  // ../../packages/host-core/dist/drops/receive-ui.js
99848
- import { basename as basename12, dirname as dirname25 } from "node:path";
100619
+ import { basename as basename12, dirname as dirname26 } from "node:path";
99849
100620
  var log5 = (...a) => console.log("[drops]", ...a);
99850
100621
  function formatBytes(n) {
99851
100622
  if (!Number.isFinite(n) || n <= 0)
@@ -100187,7 +100958,7 @@ function createDropHandler(deps) {
100187
100958
  // ../../packages/host-core/dist/drops/blob-fetch.js
100188
100959
  import { createWriteStream as createWriteStream2 } from "node:fs";
100189
100960
  import { mkdir as mkdir13, rm as rm5, chmod as chmod3 } from "node:fs/promises";
100190
- import { dirname as dirname26, join as join63 } from "node:path";
100961
+ import { dirname as dirname27, join as join63 } from "node:path";
100191
100962
  import { Readable as Readable2 } from "node:stream";
100192
100963
  import { pipeline } from "node:stream/promises";
100193
100964
 
@@ -100385,7 +101156,7 @@ async function fetchBlobDrop(opts) {
100385
101156
  log7(`drop ${opts.dropId}: refusing a path outside the destination`);
100386
101157
  continue;
100387
101158
  }
100388
- await mkdir13(dirname26(abs), { recursive: true });
101159
+ await mkdir13(dirname27(abs), { recursive: true });
100389
101160
  abs = await uniqueDropPath(abs);
100390
101161
  const res = await fetchFn(new URL(item.url, opts.apiOrigin).toString(), { signal: opts.signal });
100391
101162
  if (!res.ok || !res.body)
@@ -100657,13 +101428,13 @@ var RdeskServerChannel = class {
100657
101428
  };
100658
101429
 
100659
101430
  // ../../packages/host-core/dist/rdesk/channel-client.js
100660
- import { readFileSync as readFileSync44 } from "node:fs";
101431
+ import { readFileSync as readFileSync45 } from "node:fs";
100661
101432
  import { join as join64 } from "node:path";
100662
101433
  var RECONNECT_MS = 2e3;
100663
101434
  var CLAIM_RETRY_MS = 5e3;
100664
101435
  function readEndpoint(dir2, selfPid) {
100665
101436
  try {
100666
- const s = JSON.parse(readFileSync44(join64(dir2, "status.json"), "utf8"));
101437
+ const s = JSON.parse(readFileSync45(join64(dir2, "status.json"), "utf8"));
100667
101438
  if (selfPid && s.pid === selfPid)
100668
101439
  return null;
100669
101440
  return s.localPort && s.localToken ? `ws://127.0.0.1:${s.localPort}/?token=${s.localToken}` : null;
@@ -101097,16 +101868,16 @@ function registerRdpEngine() {
101097
101868
  init_credentials();
101098
101869
  import { appendFile, stat as stat8, rename as rename3 } from "node:fs/promises";
101099
101870
  import { join as join65 } from "node:path";
101100
- var MAX_BYTES = 2 * 1024 * 1024;
101871
+ var MAX_BYTES2 = 2 * 1024 * 1024;
101101
101872
  function rdeskAuditPath() {
101102
101873
  return join65(daemonDir2(), "rdesk-audit.jsonl");
101103
101874
  }
101104
101875
  var queue = [];
101105
101876
  var draining = false;
101106
- async function rotateIfNeeded(path6) {
101877
+ async function rotateIfNeeded2(path6) {
101107
101878
  try {
101108
101879
  const st = await stat8(path6);
101109
- if (st.size < MAX_BYTES)
101880
+ if (st.size < MAX_BYTES2)
101110
101881
  return;
101111
101882
  await rename3(path6, `${path6}.1`);
101112
101883
  } catch {
@@ -101121,7 +101892,7 @@ async function drain() {
101121
101892
  const batch = queue.join("");
101122
101893
  queue = [];
101123
101894
  const path6 = rdeskAuditPath();
101124
- await rotateIfNeeded(path6);
101895
+ await rotateIfNeeded2(path6);
101125
101896
  await appendFile(path6, batch, { mode: 384 });
101126
101897
  }
101127
101898
  } catch {
@@ -101140,7 +101911,7 @@ function appendRdeskAudit(e) {
101140
101911
  }
101141
101912
 
101142
101913
  // ../../packages/host-core/dist/fileprovider-bridge.js
101143
- import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync33, rmSync as rmSync8, existsSync as existsSync31 } from "node:fs";
101914
+ import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync34, rmSync as rmSync8, existsSync as existsSync32 } from "node:fs";
101144
101915
  import { homedir as homedir9 } from "node:os";
101145
101916
  import { join as join66 } from "node:path";
101146
101917
  var APPEX_BUNDLE_ID = "dev.tesseract.FileProvider";
@@ -101313,7 +102084,7 @@ function stopFileProviderBridge() {
101313
102084
 
101314
102085
  // ../../packages/host-core/dist/vault/autofill-bridge.js
101315
102086
  import { randomBytes as randomBytes9 } from "node:crypto";
101316
- import { existsSync as existsSync32, mkdirSync as mkdirSync34, writeFileSync as writeFileSync35, rmSync as rmSync9 } from "node:fs";
102087
+ import { existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync35, rmSync as rmSync9 } from "node:fs";
101317
102088
  import { homedir as homedir10 } from "node:os";
101318
102089
  import { join as join67 } from "node:path";
101319
102090
 
@@ -101388,7 +102159,7 @@ function writeBridgeInfo(port, token3, log9) {
101388
102159
  return;
101389
102160
  const containerData = appexContainerData();
101390
102161
  try {
101391
- if (!existsSync32(containerData)) {
102162
+ if (!existsSync33(containerData)) {
101392
102163
  if (!infoLoggedOnce) {
101393
102164
  infoLoggedOnce = true;
101394
102165
  log9("autofill bridge-info SKIP: no appex container yet at", containerData);
@@ -101396,7 +102167,7 @@ function writeBridgeInfo(port, token3, log9) {
101396
102167
  return;
101397
102168
  }
101398
102169
  const dir2 = join67(containerData, "Library", "Application Support");
101399
- mkdirSync34(dir2, { recursive: true });
102170
+ mkdirSync35(dir2, { recursive: true });
101400
102171
  writeFileSync35(bridgeInfoPath(), JSON.stringify({ port, token: token3, pid: process.pid, ts: Date.now() }), { mode: 384 });
101401
102172
  if (!infoLoggedOnce) {
101402
102173
  infoLoggedOnce = true;
@@ -101639,9 +102410,9 @@ function createNodePowerController() {
101639
102410
 
101640
102411
  // ../../packages/host-core/dist/native-host.js
101641
102412
  import { execFileSync as execFileSync4 } from "node:child_process";
101642
- import { chmodSync as chmodSync6, existsSync as existsSync33, mkdirSync as mkdirSync35, writeFileSync as writeFileSync36 } from "node:fs";
102413
+ import { chmodSync as chmodSync6, existsSync as existsSync34, mkdirSync as mkdirSync36, writeFileSync as writeFileSync36 } from "node:fs";
101643
102414
  import { homedir as homedir11, platform as platform5 } from "node:os";
101644
- import { dirname as dirname27, join as join68, resolve as resolve12 } from "node:path";
102415
+ import { dirname as dirname28, join as join68, resolve as resolve12 } from "node:path";
101645
102416
  import { fileURLToPath as fileURLToPath5 } from "node:url";
101646
102417
  var HOST_NAME = "com.tesseract.companion";
101647
102418
  var EXTENSION_IDS = ["icpnghhpcmaonjckkpilpajblfehpplo", "giolfpookdhjfafcchaflhmigghaeffn"];
@@ -101664,13 +102435,13 @@ function resolveBridge(log9) {
101664
102435
  process.resourcesPath ? join68(process.resourcesPath, "companion-host", BRIDGE_BASENAME) : void 0
101665
102436
  ];
101666
102437
  try {
101667
- const here = dirname27(fileURLToPath5(import.meta.url));
102438
+ const here = dirname28(fileURLToPath5(import.meta.url));
101668
102439
  candidates.push(resolve12(here, "../../../apps/companion-host/dist", BRIDGE_BASENAME));
101669
102440
  candidates.push(resolve12(here, "../../apps/companion-host/dist", BRIDGE_BASENAME));
101670
102441
  } catch {
101671
102442
  }
101672
102443
  for (const c of candidates)
101673
- if (c && existsSync33(c))
102444
+ if (c && existsSync34(c))
101674
102445
  return c;
101675
102446
  log9("companion native-host: bridge not found; skipping registration (looked in", candidates.filter(Boolean).join(" , "), ")");
101676
102447
  return null;
@@ -101699,7 +102470,7 @@ function registerNativeHost(opts) {
101699
102470
  if (!bridge)
101700
102471
  return;
101701
102472
  const runtime = opts.runtime ?? process.execPath;
101702
- mkdirSync35(opts.daemonDir, { recursive: true });
102473
+ mkdirSync36(opts.daemonDir, { recursive: true });
101703
102474
  const launcher = writeLauncher(opts.daemonDir, bridge, runtime);
101704
102475
  const manifestJson = JSON.stringify({
101705
102476
  name: HOST_NAME,
@@ -101712,11 +102483,11 @@ function registerNativeHost(opts) {
101712
102483
  return registerWindows(opts.daemonDir, manifestJson, log9);
101713
102484
  let wrote = 0;
101714
102485
  for (const profile of browserProfileDirs()) {
101715
- if (!existsSync33(profile))
102486
+ if (!existsSync34(profile))
101716
102487
  continue;
101717
102488
  try {
101718
102489
  const dir2 = join68(profile, "NativeMessagingHosts");
101719
- mkdirSync35(dir2, { recursive: true });
102490
+ mkdirSync36(dir2, { recursive: true });
101720
102491
  writeFileSync36(join68(dir2, `${HOST_NAME}.json`), manifestJson);
101721
102492
  wrote++;
101722
102493
  } catch {
@@ -101748,7 +102519,7 @@ init_daemon_settings();
101748
102519
 
101749
102520
  // ../../packages/host-core/dist/activity/activity-tracker.js
101750
102521
  init_credentials();
101751
- import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as mkdirSync36, existsSync as existsSync34 } from "node:fs";
102522
+ import { promises as fsp, writeFileSync as writeFileSync37, mkdirSync as mkdirSync37, existsSync as existsSync35 } from "node:fs";
101752
102523
  import { join as join69 } from "node:path";
101753
102524
  function activityProfilePath() {
101754
102525
  return join69(daemonDir2(), "activity-profile.json");
@@ -101826,7 +102597,7 @@ function createActivityTracker(opts = {}) {
101826
102597
  return;
101827
102598
  const key2 = front.bundleId || front.name;
101828
102599
  await ensureLoaded();
101829
- if (profile && Object.keys(profile.apps).length && !existsSync34(activityProfilePath())) {
102600
+ if (profile && Object.keys(profile.apps).length && !existsSync35(activityProfilePath())) {
101830
102601
  log9("activity profile cleared externally \u2014 resetting in-memory");
101831
102602
  profile = { version: 1, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), apps: {} };
101832
102603
  }
@@ -101862,7 +102633,7 @@ function createActivityTracker(opts = {}) {
101862
102633
  if (profile) {
101863
102634
  pruneProfile(profile);
101864
102635
  profile.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
101865
- mkdirSync36(daemonDir2(), { recursive: true, mode: 448 });
102636
+ mkdirSync37(daemonDir2(), { recursive: true, mode: 448 });
101866
102637
  writeFileSync37(activityProfilePath(), JSON.stringify(profile), { mode: 384 });
101867
102638
  dirty = 0;
101868
102639
  }
@@ -101933,13 +102704,21 @@ var reporting = false;
101933
102704
  var surface = "daemon";
101934
102705
  var logFn = () => {
101935
102706
  };
101936
- function endpoint() {
101937
- const e = process.env.CCB_ERROR_ENDPOINT?.replace(/\/$/, "");
101938
- return e ? `${e}/v1/reports` : null;
102707
+ function endpoint(apiOrigin) {
102708
+ const explicit = process.env.CCB_ERROR_ENDPOINT?.trim().replace(/\/$/, "");
102709
+ if (explicit)
102710
+ return `${explicit}/v1/reports`;
102711
+ const origin = apiOrigin?.trim().replace(/\/$/, "");
102712
+ return origin ? `${origin}/api/errors/v1/reports` : null;
101939
102713
  }
101940
102714
  function hasConsent() {
101941
102715
  return process.env.CCB_CRASH_REPORT_CONSENT === "1";
101942
102716
  }
102717
+ var LAUNCHER_SURFACES = /* @__PURE__ */ new Set(["daemon", "rdesk", "mesh"]);
102718
+ function surfaceFromEnv() {
102719
+ const s = process.env.CCB_ERROR_SURFACE?.trim();
102720
+ return s && LAUNCHER_SURFACES.has(s) ? s : "daemon";
102721
+ }
101943
102722
  function initDaemonErrorReporter(opts = {}) {
101944
102723
  if (timer)
101945
102724
  return;
@@ -101990,16 +102769,16 @@ function captureDaemonError(error51, opts = {}) {
101990
102769
  ...opts.context ? { context: opts.context } : {},
101991
102770
  fingerprint: ""
101992
102771
  };
101993
- const safe = redactError(report);
101994
- safe.fingerprint = computeFingerprint({
102772
+ const safe2 = redactError(report);
102773
+ safe2.fingerprint = computeFingerprint({
101995
102774
  surface,
101996
- type: safe.exception.type,
101997
- message: safe.exception.message,
101998
- stacktrace: safe.exception.stacktrace
102775
+ type: safe2.exception.type,
102776
+ message: safe2.exception.message,
102777
+ stacktrace: safe2.exception.stacktrace
101999
102778
  });
102000
102779
  if (!hasConsent())
102001
102780
  return;
102002
- queue2.push(safe);
102781
+ queue2.push(safe2);
102003
102782
  if (queue2.length > MAX_QUEUE)
102004
102783
  queue2.splice(0, queue2.length - MAX_QUEUE);
102005
102784
  if (queue2.length >= 10)
@@ -102016,12 +102795,12 @@ async function flush2() {
102016
102795
  return;
102017
102796
  if (Date.now() < nextAttemptAt)
102018
102797
  return;
102019
- const url2 = endpoint();
102020
- if (!url2)
102021
- return;
102022
102798
  const creds3 = readCredentials();
102023
102799
  if (!creds3?.accessToken)
102024
102800
  return;
102801
+ const url2 = endpoint(creds3.apiOrigin);
102802
+ if (!url2)
102803
+ return;
102025
102804
  sending = true;
102026
102805
  const batch = queue2.slice(0, 20);
102027
102806
  try {
@@ -102072,7 +102851,7 @@ async function runDaemon(opts = {}) {
102072
102851
  };
102073
102852
  const lockHeldByAnother = () => {
102074
102853
  try {
102075
- const pid = Number(readFileSync45(pidfile(), "utf-8").trim());
102854
+ const pid = Number(readFileSync46(pidfile(), "utf-8").trim());
102076
102855
  return Number.isFinite(pid) && pid > 0 && pid !== process.pid && isAlive2(pid);
102077
102856
  } catch {
102078
102857
  return false;
@@ -102081,8 +102860,8 @@ async function runDaemon(opts = {}) {
102081
102860
  function acquireLock2() {
102082
102861
  const f = pidfile();
102083
102862
  try {
102084
- if (!existsSync35(daemonDir2()))
102085
- mkdirSync37(daemonDir2(), { recursive: true, mode: 448 });
102863
+ if (!existsSync36(daemonDir2()))
102864
+ mkdirSync38(daemonDir2(), { recursive: true, mode: 448 });
102086
102865
  } catch {
102087
102866
  }
102088
102867
  for (let attempt = 0; attempt < 2; attempt++) {
@@ -102091,7 +102870,7 @@ async function runDaemon(opts = {}) {
102091
102870
  return true;
102092
102871
  } catch {
102093
102872
  try {
102094
- const prev = Number(readFileSync45(f, "utf-8").trim());
102873
+ const prev = Number(readFileSync46(f, "utf-8").trim());
102095
102874
  if (!prev)
102096
102875
  return false;
102097
102876
  if (prev !== process.pid && isAlive2(prev))
@@ -102107,7 +102886,7 @@ async function runDaemon(opts = {}) {
102107
102886
  function releaseLock() {
102108
102887
  try {
102109
102888
  const f = pidfile();
102110
- if (existsSync35(f) && Number(readFileSync45(f, "utf-8").trim()) === process.pid)
102889
+ if (existsSync36(f) && Number(readFileSync46(f, "utf-8").trim()) === process.pid)
102111
102890
  unlinkSync6(f);
102112
102891
  } catch {
102113
102892
  }
@@ -102117,11 +102896,11 @@ async function runDaemon(opts = {}) {
102117
102896
  let lockPid = 0;
102118
102897
  let status2 = {};
102119
102898
  try {
102120
- lockPid = Number(readFileSync45(pidfile(), "utf-8").trim());
102899
+ lockPid = Number(readFileSync46(pidfile(), "utf-8").trim());
102121
102900
  } catch {
102122
102901
  }
102123
102902
  try {
102124
- status2 = JSON.parse(readFileSync45(statusFile(), "utf-8"));
102903
+ status2 = JSON.parse(readFileSync46(statusFile(), "utf-8"));
102125
102904
  } catch {
102126
102905
  }
102127
102906
  const statusPid = Number(status2.pid ?? 0);
@@ -102183,7 +102962,7 @@ async function runDaemon(opts = {}) {
102183
102962
  forgetDaemon(p);
102184
102963
  }
102185
102964
  try {
102186
- if (existsSync35(pidfile()))
102965
+ if (existsSync36(pidfile()))
102187
102966
  unlinkSync6(pidfile());
102188
102967
  } catch {
102189
102968
  }
@@ -102392,7 +103171,7 @@ async function runDaemon(opts = {}) {
102392
103171
  });
102393
103172
  } catch {
102394
103173
  }
102395
- initDaemonErrorReporter({ surface: "daemon", log: log9 });
103174
+ initDaemonErrorReporter({ surface: surfaceFromEnv(), log: log9 });
102396
103175
  process.on("uncaughtException", (e) => {
102397
103176
  try {
102398
103177
  captureDaemonError(e, { severity: "error", context: { handler: "uncaughtException", keptAlive: true } });
@@ -102554,7 +103333,7 @@ async function runDaemon(opts = {}) {
102554
103333
  }
102555
103334
  } catch {
102556
103335
  }
102557
- if (ownsMachine)
103336
+ if (ownsMachine && !WE_ARE_RDESK_ONLY)
102558
103337
  setHostDaemonRole(true);
102559
103338
  const localToken = randomBytes10(24).toString("hex");
102560
103339
  const sendToViewer = (kind, sessionId, clientId, msg) => {
@@ -103008,7 +103787,7 @@ async function runDaemon(opts = {}) {
103008
103787
  let freeTicks = 0;
103009
103788
  const lockHolder = () => {
103010
103789
  try {
103011
- return Number(readFileSync45(pidfile(), "utf-8").trim()) || 0;
103790
+ return Number(readFileSync46(pidfile(), "utf-8").trim()) || 0;
103012
103791
  } catch {
103013
103792
  return 0;
103014
103793
  }
@@ -103213,7 +103992,7 @@ async function runDaemon(opts = {}) {
103213
103992
  if (appPid > 0 && appPid !== process.pid) {
103214
103993
  const quitMarker = () => {
103215
103994
  try {
103216
- return Number(readFileSync45(join70(daemonDir2(), "app-quit.marker"), "utf-8").trim()) || 0;
103995
+ return Number(readFileSync46(join70(daemonDir2(), "app-quit.marker"), "utf-8").trim()) || 0;
103217
103996
  } catch {
103218
103997
  return 0;
103219
103998
  }
@@ -103238,7 +104017,7 @@ async function runDaemon(opts = {}) {
103238
104017
  log9(`desktop app (pid ${appPid}) is gone with NO clean-quit marker \u2014 reporting`);
103239
104018
  const tail3 = (name) => {
103240
104019
  try {
103241
- const buf = readFileSync45(join70(daemonDir2(), name), "utf-8");
104020
+ const buf = readFileSync46(join70(daemonDir2(), name), "utf-8");
103242
104021
  return buf.length > 4096 ? buf.slice(-4096) : buf;
103243
104022
  } catch {
103244
104023
  return void 0;
@@ -103272,8 +104051,8 @@ async function runDaemon(opts = {}) {
103272
104051
  const daemonLogFile = join70(daemonDir2(), "daemon.log");
103273
104052
  const capTimer = setInterval(() => {
103274
104053
  try {
103275
- if (existsSync35(daemonLogFile) && statSync9(daemonLogFile).size > DAEMON_LOG_CAP) {
103276
- const buf = readFileSync45(daemonLogFile, "utf-8");
104054
+ if (existsSync36(daemonLogFile) && statSync10(daemonLogFile).size > DAEMON_LOG_CAP) {
104055
+ const buf = readFileSync46(daemonLogFile, "utf-8");
103277
104056
  const kept = `\u2026[daemon.log capped at ${(/* @__PURE__ */ new Date()).toISOString()}]\u2026
103278
104057
  ` + buf.slice(-DAEMON_LOG_CAP / 2);
103279
104058
  writeFileSync38(daemonLogFile, kept);
@@ -103604,8 +104383,8 @@ import { platform as platform6 } from "node:os";
103604
104383
 
103605
104384
  // ../../packages/host-core/dist/service/launchd.js
103606
104385
  init_credentials();
103607
- import { writeFileSync as writeFileSync39, existsSync as existsSync36, mkdirSync as mkdirSync38, unlinkSync as unlinkSync7 } from "node:fs";
103608
- import { dirname as dirname28, join as join71 } from "node:path";
104386
+ import { writeFileSync as writeFileSync39, existsSync as existsSync37, mkdirSync as mkdirSync39, unlinkSync as unlinkSync7 } from "node:fs";
104387
+ import { dirname as dirname29, join as join71 } from "node:path";
103609
104388
  import { homedir as homedir12, userInfo as userInfo2 } from "node:os";
103610
104389
 
103611
104390
  // ../../packages/host-core/dist/service/types.js
@@ -103665,9 +104444,9 @@ ${env}
103665
104444
  }
103666
104445
  return {
103667
104446
  async install(spec) {
103668
- mkdirSync38(workDirOf(spec), { recursive: true });
103669
- mkdirSync38(dirname28(plistPath()), { recursive: true });
103670
- mkdirSync38(dirname28(spec.logPath), { recursive: true });
104447
+ mkdirSync39(workDirOf(spec), { recursive: true });
104448
+ mkdirSync39(dirname29(plistPath()), { recursive: true });
104449
+ mkdirSync39(dirname29(spec.logPath), { recursive: true });
103671
104450
  writeFileSync39(plistPath(), buildPlist(spec));
103672
104451
  await run4("launchctl", ["bootout", serviceTarget()]).catch(() => {
103673
104452
  });
@@ -103680,7 +104459,7 @@ ${env}
103680
104459
  async uninstall() {
103681
104460
  await run4("launchctl", ["bootout", serviceTarget()]).catch(() => {
103682
104461
  });
103683
- if (existsSync36(plistPath())) {
104462
+ if (existsSync37(plistPath())) {
103684
104463
  try {
103685
104464
  unlinkSync7(plistPath());
103686
104465
  } catch {
@@ -103691,7 +104470,7 @@ ${env}
103691
104470
  await this.install(spec);
103692
104471
  },
103693
104472
  async isInstalled() {
103694
- return existsSync36(plistPath());
104473
+ return existsSync37(plistPath());
103695
104474
  },
103696
104475
  async start() {
103697
104476
  await run4("launchctl", ["bootstrap", domainTarget(), plistPath()]).catch(() => {
@@ -103708,7 +104487,7 @@ ${env}
103708
104487
  },
103709
104488
  async logs(follow) {
103710
104489
  const f = logFile();
103711
- if (!existsSync36(f)) {
104490
+ if (!existsSync37(f)) {
103712
104491
  console.log(`No log yet at ${f} \u2014 has the service started?`);
103713
104492
  return;
103714
104493
  }
@@ -103719,8 +104498,8 @@ ${env}
103719
104498
 
103720
104499
  // ../../packages/host-core/dist/service/systemd.js
103721
104500
  init_credentials();
103722
- import { writeFileSync as writeFileSync40, existsSync as existsSync37, mkdirSync as mkdirSync39, unlinkSync as unlinkSync8 } from "node:fs";
103723
- import { dirname as dirname29, join as join72 } from "node:path";
104501
+ import { writeFileSync as writeFileSync40, existsSync as existsSync38, mkdirSync as mkdirSync40, unlinkSync as unlinkSync8 } from "node:fs";
104502
+ import { dirname as dirname30, join as join72 } from "node:path";
103724
104503
  import { homedir as homedir13, userInfo as userInfo3 } from "node:os";
103725
104504
  function unitVal(v) {
103726
104505
  return v.replace(/%/g, "%%");
@@ -103759,9 +104538,9 @@ WantedBy=default.target
103759
104538
  }
103760
104539
  return {
103761
104540
  async install(spec) {
103762
- mkdirSync39(workDirOf(spec), { recursive: true });
103763
- mkdirSync39(dirname29(unitPath()), { recursive: true });
103764
- mkdirSync39(dirname29(spec.logPath), { recursive: true });
104541
+ mkdirSync40(workDirOf(spec), { recursive: true });
104542
+ mkdirSync40(dirname30(unitPath()), { recursive: true });
104543
+ mkdirSync40(dirname30(spec.logPath), { recursive: true });
103765
104544
  writeFileSync40(unitPath(), buildUnit2(spec));
103766
104545
  await run4("loginctl", ["enable-linger", userInfo3().username]).catch(() => {
103767
104546
  });
@@ -103774,7 +104553,7 @@ WantedBy=default.target
103774
104553
  async uninstall() {
103775
104554
  await run4("systemctl", ["--user", "disable", "--now", unit]).catch(() => {
103776
104555
  });
103777
- if (existsSync37(unitPath())) {
104556
+ if (existsSync38(unitPath())) {
103778
104557
  try {
103779
104558
  unlinkSync8(unitPath());
103780
104559
  } catch {
@@ -103787,7 +104566,7 @@ WantedBy=default.target
103787
104566
  await this.install(spec);
103788
104567
  },
103789
104568
  async isInstalled() {
103790
- return existsSync37(unitPath());
104569
+ return existsSync38(unitPath());
103791
104570
  },
103792
104571
  async start() {
103793
104572
  await run4("systemctl", ["--user", "start", unit]);
@@ -103806,8 +104585,8 @@ WantedBy=default.target
103806
104585
 
103807
104586
  // ../../packages/host-core/dist/service/windows.js
103808
104587
  init_credentials();
103809
- import { writeFileSync as writeFileSync41, existsSync as existsSync38, mkdirSync as mkdirSync40, unlinkSync as unlinkSync9 } from "node:fs";
103810
- import { dirname as dirname30, join as join73 } from "node:path";
104588
+ import { writeFileSync as writeFileSync41, existsSync as existsSync39, mkdirSync as mkdirSync41, unlinkSync as unlinkSync9 } from "node:fs";
104589
+ import { dirname as dirname31, join as join73 } from "node:path";
103811
104590
  function makeWindowsTask(instanceId) {
103812
104591
  const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
103813
104592
  const wrapperPath = () => join73(daemonDir2(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
@@ -103827,9 +104606,9 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
103827
104606
  }
103828
104607
  return {
103829
104608
  async install(spec) {
103830
- mkdirSync40(spec.workingDirectory ?? daemonDir2(), { recursive: true });
103831
- mkdirSync40(dirname30(spec.logPath), { recursive: true });
103832
- mkdirSync40(dirname30(wrapperPath()), { recursive: true });
104609
+ mkdirSync41(spec.workingDirectory ?? daemonDir2(), { recursive: true });
104610
+ mkdirSync41(dirname31(spec.logPath), { recursive: true });
104611
+ mkdirSync41(dirname31(wrapperPath()), { recursive: true });
103833
104612
  writeFileSync41(wrapperPath(), buildWrapper(spec));
103834
104613
  await run4("schtasks", ["/Create", "/TN", task, "/SC", "ONLOGON", "/RL", "LIMITED", "/F", "/TR", `"${wrapperPath()}"`]);
103835
104614
  await run4("schtasks", ["/Run", "/TN", task]).catch(() => {
@@ -103838,7 +104617,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
103838
104617
  async uninstall() {
103839
104618
  await run4("schtasks", ["/Delete", "/TN", task, "/F"]).catch(() => {
103840
104619
  });
103841
- if (existsSync38(wrapperPath())) {
104620
+ if (existsSync39(wrapperPath())) {
103842
104621
  try {
103843
104622
  unlinkSync9(wrapperPath());
103844
104623
  } catch {
@@ -103868,7 +104647,7 @@ start "" /b ${cmd} >> "${oneLine2(spec.logPath).replace(/"/g, "")}" 2>&1\r
103868
104647
  },
103869
104648
  async logs(follow) {
103870
104649
  const f = logFile();
103871
- if (!existsSync38(f)) {
104650
+ if (!existsSync39(f)) {
103872
104651
  console.log(`No log yet at ${f} \u2014 has the task run?`);
103873
104652
  return;
103874
104653
  }
@@ -103899,7 +104678,7 @@ init_serpapi_runner();
103899
104678
  // src/auth.ts
103900
104679
  var import_qrcode_terminal = __toESM(require_main(), 1);
103901
104680
  import { randomUUID as randomUUID27 } from "node:crypto";
103902
- import { existsSync as existsSync39, rmSync as rmSync10 } from "node:fs";
104681
+ import { existsSync as existsSync40, rmSync as rmSync10 } from "node:fs";
103903
104682
  import { join as join74 } from "node:path";
103904
104683
 
103905
104684
  // src/config.ts
@@ -104102,7 +104881,7 @@ async function logout() {
104102
104881
  for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
104103
104882
  try {
104104
104883
  const p = join74(daemonDir2(), f);
104105
- if (existsSync39(p)) rmSync10(p);
104884
+ if (existsSync40(p)) rmSync10(p);
104106
104885
  } catch {
104107
104886
  }
104108
104887
  }
@@ -104262,7 +105041,7 @@ function startSelfUpdater(current) {
104262
105041
  // src/service.ts
104263
105042
  import { join as join75 } from "node:path";
104264
105043
  import { platform as platform7 } from "node:os";
104265
- import { existsSync as existsSync40, readFileSync as readFileSync46 } from "node:fs";
105044
+ import { existsSync as existsSync41, readFileSync as readFileSync47 } from "node:fs";
104266
105045
  function controller(instanceId) {
104267
105046
  const c = getServiceController(instanceId);
104268
105047
  if (!c) {
@@ -104289,8 +105068,8 @@ var isAlive = (pid) => {
104289
105068
  function runningDaemonInfo() {
104290
105069
  const lock = join75(daemonDir2(), "daemon.lock");
104291
105070
  try {
104292
- if (!existsSync40(lock)) return null;
104293
- const pid = Number(readFileSync46(lock, "utf-8").trim());
105071
+ if (!existsSync41(lock)) return null;
105072
+ const pid = Number(readFileSync47(lock, "utf-8").trim());
104294
105073
  if (!pid || !isAlive(pid)) return null;
104295
105074
  return { pid, device: readCredentials()?.deviceId };
104296
105075
  } catch {
@@ -104324,7 +105103,7 @@ async function logs(instanceId, follow) {
104324
105103
  }
104325
105104
 
104326
105105
  // src/net.ts
104327
- import { readFileSync as readFileSync48 } from "node:fs";
105106
+ import { readFileSync as readFileSync49 } from "node:fs";
104328
105107
  import { randomBytes as randomBytes11 } from "node:crypto";
104329
105108
  import { hostname as hostname7 } from "node:os";
104330
105109
  import { resolve as resolve14 } from "node:path";
@@ -104379,7 +105158,7 @@ function readOrDie(label, p) {
104379
105158
  process.exit(1);
104380
105159
  }
104381
105160
  try {
104382
- return new Uint8Array(readFileSync48(resolve14(p)));
105161
+ return new Uint8Array(readFileSync49(resolve14(p)));
104383
105162
  } catch (e) {
104384
105163
  console.error(`net enroll: could not read --${label} ${p}: ${e instanceof Error ? e.message : e}`);
104385
105164
  process.exit(1);
@@ -104845,8 +105624,8 @@ async function netCommand(rest, flags) {
104845
105624
  // src/cli.ts
104846
105625
  function pkgVersion() {
104847
105626
  try {
104848
- const p = join77(dirname31(fileURLToPath6(import.meta.url)), "..", "package.json");
104849
- return JSON.parse(readFileSync49(p, "utf8")).version ?? "0.0.0";
105627
+ const p = join77(dirname32(fileURLToPath6(import.meta.url)), "..", "package.json");
105628
+ return JSON.parse(readFileSync50(p, "utf8")).version ?? "0.0.0";
104850
105629
  } catch {
104851
105630
  return "0.0.0";
104852
105631
  }
@@ -104949,6 +105728,8 @@ Usage:
104949
105728
  tesseract-agent start | stop | restart Control the service
104950
105729
  tesseract-agent status Show the service status
104951
105730
  tesseract-agent logs [--no-follow] Tail the service logs
105731
+ tesseract-agent decisions [--session ID] [--source prompt|verification|recovery] [-n N] [--json]
105732
+ What unattended mode decided while nobody was watching
104952
105733
  tesseract-agent run [--engine ID] [--engine-path BIN] [--engine-env K=V ...] [--no-active-link]
104953
105734
  Run the daemon in the foreground (Docker/manual)
104954
105735
  tesseract-agent link add <folder> --peer <hostId> (--name <shared> | --id <id>)
@@ -105000,6 +105781,36 @@ async function confirm(question) {
105000
105781
  rl.close();
105001
105782
  }
105002
105783
  }
105784
+ async function decisionsCommand(flags) {
105785
+ const { readUnattendedDecisions: readUnattendedDecisions2, unattendedLogPath: unattendedLogPath2 } = await Promise.resolve().then(() => (init_unattended_log(), unattended_log_exports));
105786
+ const limit = typeof flags.n === "string" ? Math.max(1, Number.parseInt(flags.n, 10) || 200) : 200;
105787
+ const source = flags.source === "prompt" || flags.source === "verification" || flags.source === "recovery" ? flags.source : void 0;
105788
+ const sessionId = typeof flags.session === "string" ? flags.session : void 0;
105789
+ const rows = readUnattendedDecisions2(limit, { ...sessionId ? { sessionId } : {}, ...source ? { source } : {} });
105790
+ if (flags.json === true) {
105791
+ for (const r of rows) console.log(JSON.stringify(r));
105792
+ return;
105793
+ }
105794
+ if (!rows.length) {
105795
+ console.log(`No unattended decisions recorded yet (${unattendedLogPath2()}).`);
105796
+ return;
105797
+ }
105798
+ for (const r of rows) {
105799
+ const when = r.ts.replace("T", " ").replace(/\.\d+Z$/, "");
105800
+ const who = r.engine ? ` ${r.engine}` : "";
105801
+ if (r.source === "verification") {
105802
+ const flag = r.exercised === false ? " NOT-RUN" : "";
105803
+ console.log(`${when}${who} verify ${r.gate} \u2192 ${r.action} (cycle ${r.cycle}${r.phaseName ? `, ${r.phaseName}` : ""}${r.blocking ? `, ${r.blocking} blocking` : ""})${flag}`);
105804
+ } else if (r.source === "recovery") {
105805
+ console.log(`${when}${who} recover ${r.kind} \u2192 ${r.action} (attempt ${r.attempt})${r.reason ? ` ${r.reason}` : ""}`);
105806
+ } else {
105807
+ const why = r.outcome === "answered" ? r.decision ?? "" : `${r.outcome}: ${r.reason ?? ""}`;
105808
+ console.log(`${when}${who} ${r.mode} ${r.kind}${r.subject ? `(${r.subject})` : ""} \u2192 ${r.behavior ?? "\u2014"}${r.cappedOut ? " [budget spent]" : ""} ${why}`);
105809
+ }
105810
+ }
105811
+ console.log(`
105812
+ ${rows.length} decision(s) \u2014 ${unattendedLogPath2()}`);
105813
+ }
105003
105814
  async function linkCommand(rest, flags) {
105004
105815
  const sub = rest[0];
105005
105816
  if (sub === "list") {
@@ -105060,7 +105871,7 @@ async function captureClaudeSubscription(flags) {
105060
105871
  });
105061
105872
  if (code !== 0) throw new Error(`Claude sign-in did not complete (exit ${code}).`);
105062
105873
  const file2 = join77(home, ".credentials.json");
105063
- if (existsSync42(file2)) return readFileSync49(file2, "utf8");
105874
+ if (existsSync43(file2)) return readFileSync50(file2, "utf8");
105064
105875
  if (process.platform === "darwin") {
105065
105876
  const value = execFileSync6("security", [
105066
105877
  "find-generic-password",
@@ -105142,7 +105953,7 @@ async function runnerCommand(rest, flags) {
105142
105953
  process.exit(1);
105143
105954
  }
105144
105955
  const oauthFilePath = typeof flags["oauth-file"] === "string" ? resolve15(flags["oauth-file"]) : void 0;
105145
- const oauthAuthFile = oauthFilePath ? readFileSync49(oauthFilePath, "utf8") : void 0;
105956
+ const oauthAuthFile = oauthFilePath ? readFileSync50(oauthFilePath, "utf8") : void 0;
105146
105957
  if (oauthAuthFile) {
105147
105958
  try {
105148
105959
  JSON.parse(oauthAuthFile);
@@ -105251,6 +106062,9 @@ Re-run with --yes to replace it, or --instance <id> to install a SEPARATE agent.
105251
106062
  case "logs":
105252
106063
  await logs(instance, flags["no-follow"] !== true);
105253
106064
  break;
106065
+ case "decisions":
106066
+ await decisionsCommand(flags);
106067
+ break;
105254
106068
  case "link":
105255
106069
  await linkCommand(rest, flags);
105256
106070
  break;