tesseract-agent 0.4.3 → 0.4.6

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 +840 -449
  2. package/package.json +1 -1
@@ -11517,8 +11517,8 @@ var capitalizeFirstCharacter, error28;
11517
11517
  var init_lt = __esm({
11518
11518
  "../../node_modules/zod/v4/locales/lt.js"() {
11519
11519
  init_util();
11520
- capitalizeFirstCharacter = (text) => {
11521
- return text.charAt(0).toUpperCase() + text.slice(1);
11520
+ capitalizeFirstCharacter = (text2) => {
11521
+ return text2.charAt(0).toUpperCase() + text2.slice(1);
11522
11522
  };
11523
11523
  error28 = () => {
11524
11524
  const Sizable = {
@@ -19350,6 +19350,213 @@ var init_cron_tools = __esm({
19350
19350
  }
19351
19351
  });
19352
19352
 
19353
+ // ../../packages/agent-core/dist/design-tokens.js
19354
+ function colorVar(name, c) {
19355
+ return c.cssVar ?? `--color-${name}`;
19356
+ }
19357
+ function tokensToCss(tokens) {
19358
+ const lines = [
19359
+ "/* GENERATED from design-system/tokens.json \u2014 do not edit by hand. */",
19360
+ ":root {"
19361
+ ];
19362
+ const push = (k, v) => lines.push(` ${k}: ${v};`);
19363
+ for (const [name, c] of Object.entries(tokens.colors ?? {}))
19364
+ push(colorVar(name, c), c.value);
19365
+ for (const [role, fam] of Object.entries(tokens.typography?.fontFamilies ?? {}))
19366
+ push(`--font-${role}`, fam);
19367
+ for (const [step, s] of Object.entries(tokens.typography?.scale ?? {}))
19368
+ push(`--text-${step}`, s.size);
19369
+ for (const [name, w] of Object.entries(tokens.typography?.weights ?? {}))
19370
+ push(`--weight-${name}`, String(w));
19371
+ for (const [step, v] of Object.entries(tokens.spacing ?? {}))
19372
+ push(`--space-${step}`, v);
19373
+ for (const [name, v] of Object.entries(tokens.radius ?? {}))
19374
+ push(`--radius-${name}`, v);
19375
+ for (const [name, v] of Object.entries(tokens.shadow ?? {}))
19376
+ push(`--shadow-${name}`, v);
19377
+ lines.push("}", "");
19378
+ return lines.join("\n");
19379
+ }
19380
+ function getTokenPath(tokens, dotPath) {
19381
+ let cur = tokens;
19382
+ for (const key2 of dotPath.split(".")) {
19383
+ if (cur == null || typeof cur !== "object")
19384
+ return void 0;
19385
+ cur = cur[key2];
19386
+ }
19387
+ return cur;
19388
+ }
19389
+ function setTokenPath(tokens, dotPath, value) {
19390
+ const keys = dotPath.split(".").filter(Boolean);
19391
+ if (keys.length === 0)
19392
+ throw new Error("empty token path");
19393
+ const root = { ...tokens };
19394
+ let cur = root;
19395
+ for (let i = 0; i < keys.length - 1; i++) {
19396
+ const k = keys[i];
19397
+ const next = cur[k];
19398
+ cur[k] = next && typeof next === "object" ? { ...next } : {};
19399
+ cur = cur[k];
19400
+ }
19401
+ cur[keys[keys.length - 1]] = value;
19402
+ return root;
19403
+ }
19404
+ var DESIGN_DIR, TOKENS_FILE, TOKENS_CSS_FILE, DESIGN_CLAUDE_MD, ColorToken, TypeStep, Component, DesignTokensSchema;
19405
+ var init_design_tokens = __esm({
19406
+ "../../packages/agent-core/dist/design-tokens.js"() {
19407
+ "use strict";
19408
+ init_zod();
19409
+ DESIGN_DIR = "design-system";
19410
+ TOKENS_FILE = "design-system/tokens.json";
19411
+ TOKENS_CSS_FILE = "design-system/tokens.css";
19412
+ DESIGN_CLAUDE_MD = "design-system/CLAUDE.md";
19413
+ ColorToken = external_exports.object({ value: external_exports.string(), cssVar: external_exports.string().optional(), role: external_exports.string().optional() });
19414
+ TypeStep = external_exports.object({ size: external_exports.string(), lineHeight: external_exports.string().optional(), weight: external_exports.number().optional() });
19415
+ Component = external_exports.object({
19416
+ selectorHint: external_exports.string().optional(),
19417
+ sourceFiles: external_exports.array(external_exports.string()).optional(),
19418
+ tokensUsed: external_exports.array(external_exports.string()).optional()
19419
+ });
19420
+ DesignTokensSchema = external_exports.object({
19421
+ $schema: external_exports.string().optional(),
19422
+ meta: external_exports.object({
19423
+ name: external_exports.string().optional(),
19424
+ framework: external_exports.enum(["tailwind", "css", "css-modules", "unknown"]).optional(),
19425
+ generatedAt: external_exports.string().optional()
19426
+ }).optional(),
19427
+ colors: external_exports.record(external_exports.string(), ColorToken).optional(),
19428
+ typography: external_exports.object({
19429
+ fontFamilies: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19430
+ scale: external_exports.record(external_exports.string(), TypeStep).optional(),
19431
+ weights: external_exports.record(external_exports.string(), external_exports.number()).optional()
19432
+ }).optional(),
19433
+ spacing: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19434
+ radius: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19435
+ shadow: external_exports.record(external_exports.string(), external_exports.string()).optional(),
19436
+ components: external_exports.record(external_exports.string(), Component).optional()
19437
+ });
19438
+ }
19439
+ });
19440
+
19441
+ // ../../packages/agent-core/dist/design-tools.js
19442
+ import { tool as tool2 } from "@anthropic-ai/claude-agent-sdk";
19443
+ import { readFile, writeFile, mkdir } from "node:fs/promises";
19444
+ import { join as join4, resolve as resolve2, relative as relative2, isAbsolute as isAbsolute2 } from "node:path";
19445
+ function within(root, p) {
19446
+ const rel = relative2(resolve2(root), resolve2(p));
19447
+ return rel !== "" && !rel.startsWith("..") && !isAbsolute2(rel);
19448
+ }
19449
+ async function loadTokens(root) {
19450
+ try {
19451
+ const parsed = DesignTokensSchema.safeParse(JSON.parse(await readFile(join4(root, TOKENS_FILE), "utf8")));
19452
+ return parsed.success ? parsed.data : {};
19453
+ } catch {
19454
+ return {};
19455
+ }
19456
+ }
19457
+ async function saveTokens(root, tokens, regenerateCss) {
19458
+ const tokensAbs = join4(root, TOKENS_FILE);
19459
+ const cssAbs = join4(root, TOKENS_CSS_FILE);
19460
+ if (!within(root, tokensAbs) || !within(root, cssAbs))
19461
+ throw new Error("refusing to write outside the project root");
19462
+ await mkdir(join4(root, DESIGN_DIR), { recursive: true });
19463
+ await writeFile(tokensAbs, JSON.stringify(tokens, null, 2) + "\n", "utf8");
19464
+ if (regenerateCss)
19465
+ await writeFile(cssAbs, tokensToCss(tokens), "utf8");
19466
+ }
19467
+ function buildDesignTools(deps) {
19468
+ const needRoot = () => {
19469
+ const root = deps.getProjectDir();
19470
+ if (!root)
19471
+ throw new Error("No project directory is open.");
19472
+ return root;
19473
+ };
19474
+ return [
19475
+ tool2("read_design_tokens", "Read the project design system from design-system/tokens.json (colors, typography, spacing, radius, shadow, components). Call this ONCE when you need token values \u2014 do not guess hardcoded hex/sizes.", { section: external_exports.enum(["all", "colors", "typography", "spacing", "radius", "shadow", "components"]).optional().describe("Limit to one section (default: all)") }, async (args) => {
19476
+ const tokens = await loadTokens(needRoot());
19477
+ const out = !args.section || args.section === "all" ? tokens : { [args.section]: tokens[args.section] ?? {} };
19478
+ return text(JSON.stringify(out, null, 2));
19479
+ }),
19480
+ tool2("write_design_token", 'Set one or more design tokens by dot-path (e.g. "colors.primary.value" = "#d97757", "spacing.2" = "0.5rem") and regenerate design-system/tokens.css. Batch related edits in one call. Path-guarded to the project root.', {
19481
+ edits: external_exports.array(external_exports.object({
19482
+ path: external_exports.string().describe("Dot-path into tokens.json, e.g. colors.primary.value"),
19483
+ value: external_exports.union([external_exports.string(), external_exports.number()]).describe("The new value")
19484
+ })).describe("Edits to apply"),
19485
+ regenerateCss: external_exports.boolean().optional().describe("Regenerate tokens.css from the result (default: true)")
19486
+ }, async (args) => {
19487
+ const root = needRoot();
19488
+ let tokens = await loadTokens(root);
19489
+ for (const e of args.edits)
19490
+ tokens = setTokenPath(tokens, e.path, e.value);
19491
+ const validated = DesignTokensSchema.safeParse(tokens);
19492
+ if (!validated.success)
19493
+ return text(`Edit produced an invalid tokens document: ${validated.error.message}`, true);
19494
+ const regen = args.regenerateCss !== false;
19495
+ await saveTokens(root, validated.data, regen);
19496
+ return text(`Updated ${args.edits.length} token(s): ${args.edits.map((e) => e.path).join(", ")}${regen ? " and regenerated tokens.css" : ""}.`);
19497
+ }),
19498
+ tool2("capture_element_styles", "Read the computed CSS of an element on the live preview by CSS selector (cheap \u2014 returns text, not a screenshot). Use to learn what styles/tokens an element currently uses before editing.", {
19499
+ selector: external_exports.string().describe("CSS selector of the element to inspect"),
19500
+ properties: external_exports.array(external_exports.string()).optional().describe("CSS properties to read (default: a common set)")
19501
+ }, async (args) => {
19502
+ const props = args.properties?.length ? args.properties : STYLE_PROPS;
19503
+ const expr = `(() => { const el = document.querySelector(${JSON.stringify(args.selector)}); if (!el) return { error: 'no element matches ${JSON.stringify(args.selector)}' }; const cs = getComputedStyle(el); const out = {}; for (const p of ${JSON.stringify(props)}) out[p] = cs.getPropertyValue(p).trim(); return { tag: el.tagName.toLowerCase(), styles: out }; })()`;
19504
+ try {
19505
+ const result = await deps.driveBrowser("evaluate", { expression: expr });
19506
+ return text(typeof result === "string" ? result : JSON.stringify(result, null, 2));
19507
+ } catch (err) {
19508
+ return text(`Could not read styles (is a preview open?): ${err instanceof Error ? err.message : String(err)}`, true);
19509
+ }
19510
+ }),
19511
+ tool2("notify_preview_ready", "Announce that a live preview / dev server / build is now running and reachable at a URL. Call this once the app is up (e.g. after starting a web build) \u2014 the desktop opens it in the device canvas, the mobile client shows it in-chat, and a build-ready push is sent.", {
19512
+ url: external_exports.string().describe("The reachable preview URL, e.g. http://localhost:3000"),
19513
+ kind: external_exports.enum(["web", "mobile"]).optional().describe("Framing hint (default: web)")
19514
+ }, async (args) => {
19515
+ deps.notifyPreviewReady?.(args.url, args.kind);
19516
+ return text(`Preview announced: ${args.url}`);
19517
+ }),
19518
+ tool2("list_components", "List the design-system components recorded in tokens.json (name, source files, tokens used).", {}, async () => {
19519
+ const comps = (await loadTokens(needRoot())).components ?? {};
19520
+ const names = Object.keys(comps);
19521
+ if (!names.length)
19522
+ return text('No components recorded yet. Run the "Import Design System" skill to populate them.');
19523
+ return text(names.map((n) => {
19524
+ const c = comps[n];
19525
+ const src = c.sourceFiles?.length ? ` (${c.sourceFiles.join(", ")})` : "";
19526
+ const used = c.tokensUsed?.length ? ` \u2014 uses ${c.tokensUsed.join(", ")}` : "";
19527
+ return `- ${n}${src}${used}`;
19528
+ }).join("\n"));
19529
+ })
19530
+ ];
19531
+ }
19532
+ var STYLE_PROPS, text;
19533
+ var init_design_tools = __esm({
19534
+ "../../packages/agent-core/dist/design-tools.js"() {
19535
+ "use strict";
19536
+ init_zod();
19537
+ init_design_tokens();
19538
+ STYLE_PROPS = [
19539
+ "color",
19540
+ "background-color",
19541
+ "font-family",
19542
+ "font-size",
19543
+ "font-weight",
19544
+ "line-height",
19545
+ "letter-spacing",
19546
+ "padding",
19547
+ "margin",
19548
+ "border",
19549
+ "border-radius",
19550
+ "box-shadow",
19551
+ "width",
19552
+ "height",
19553
+ "display",
19554
+ "gap"
19555
+ ];
19556
+ text = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
19557
+ }
19558
+ });
19559
+
19353
19560
  // ../../packages/agent-core/dist/narrator.js
19354
19561
  var COALESCE_MS, LOG_CAP, ACT_CAP, NARRATE_CAP, Narrator;
19355
19562
  var init_narrator = __esm({
@@ -19449,13 +19656,13 @@ ${s.log.map((l) => `- ${l}`).join("\n")}` : "",
19449
19656
  ${activity}`,
19450
19657
  "One-line status of what it is doing now:"
19451
19658
  ].filter(Boolean).join("\n\n");
19452
- const text = (await cfg2.complete({ system, prompt, maxTokens: 40 }))?.trim().replace(/^["']|["']$/g, "");
19453
- if (text && text !== s.lastText) {
19454
- s.lastText = text;
19455
- s.log.push(text);
19659
+ const text2 = (await cfg2.complete({ system, prompt, maxTokens: 40 }))?.trim().replace(/^["']|["']$/g, "");
19660
+ if (text2 && text2 !== s.lastText) {
19661
+ s.lastText = text2;
19662
+ s.log.push(text2);
19456
19663
  if (s.log.length > LOG_CAP)
19457
19664
  s.log.shift();
19458
- this.emit(id, text, cfg2.engineLabel);
19665
+ this.emit(id, text2, cfg2.engineLabel);
19459
19666
  }
19460
19667
  } catch {
19461
19668
  } finally {
@@ -19562,12 +19769,12 @@ var init_trace_store = __esm({
19562
19769
 
19563
19770
  // ../../packages/agent-core/dist/session-transfer.js
19564
19771
  import { homedir } from "node:os";
19565
- import { join as join4, dirname as dirname3, sep, resolve as resolve2 } from "node:path";
19566
- import { readFile, writeFile, mkdir, readdir } from "node:fs/promises";
19772
+ import { join as join5, dirname as dirname3, sep, resolve as resolve3 } from "node:path";
19773
+ import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, readdir } from "node:fs/promises";
19567
19774
  import { existsSync } from "node:fs";
19568
19775
  function isInside(parent, child) {
19569
- const p = resolve2(parent);
19570
- const c = resolve2(child);
19776
+ const p = resolve3(parent);
19777
+ const c = resolve3(child);
19571
19778
  return c === p || c.startsWith(p + sep);
19572
19779
  }
19573
19780
  function cwdHash(cwd) {
@@ -19581,13 +19788,13 @@ function sanitizeProjectDir(cwd) {
19581
19788
  return s.length <= MAX_PROJECT_DIR_LEN ? s : `${s.slice(0, MAX_PROJECT_DIR_LEN)}-${cwdHash(cwd)}`;
19582
19789
  }
19583
19790
  function projectsRoot() {
19584
- return join4(homedir(), ".claude", "projects");
19791
+ return join5(homedir(), ".claude", "projects");
19585
19792
  }
19586
19793
  function sessionDir(cwd) {
19587
- return join4(projectsRoot(), sanitizeProjectDir(cwd));
19794
+ return join5(projectsRoot(), sanitizeProjectDir(cwd));
19588
19795
  }
19589
19796
  function sessionFile(cwd, sessionId) {
19590
- return join4(sessionDir(cwd), `${sessionId}.jsonl`);
19797
+ return join5(sessionDir(cwd), `${sessionId}.jsonl`);
19591
19798
  }
19592
19799
  async function walkFiles(root) {
19593
19800
  const out = [];
@@ -19596,7 +19803,7 @@ async function walkFiles(root) {
19596
19803
  for (const e of entries) {
19597
19804
  const rel = prefix ? `${prefix}/${e.name}` : e.name;
19598
19805
  if (e.isDirectory())
19599
- await rec(join4(dir, e.name), rel);
19806
+ await rec(join5(dir, e.name), rel);
19600
19807
  else if (e.isFile())
19601
19808
  out.push(rel);
19602
19809
  }
@@ -19608,13 +19815,13 @@ async function exportSession(sessionId, fromCwd) {
19608
19815
  const file2 = sessionFile(fromCwd, sessionId);
19609
19816
  if (!existsSync(file2))
19610
19817
  return null;
19611
- const raw = await readFile(file2, "utf-8");
19818
+ const raw = await readFile2(file2, "utf-8");
19612
19819
  const lines = raw.split("\n").filter((l) => l.trim().length > 0);
19613
19820
  const sidecar = [];
19614
- const sideDir = join4(sessionDir(fromCwd), sessionId);
19821
+ const sideDir = join5(sessionDir(fromCwd), sessionId);
19615
19822
  if (existsSync(sideDir)) {
19616
19823
  for (const rel of await walkFiles(sideDir)) {
19617
- sidecar.push({ rel, data: await readFile(join4(sideDir, rel.split("/").join(sep))) });
19824
+ sidecar.push({ rel, data: await readFile2(join5(sideDir, rel.split("/").join(sep))) });
19618
19825
  }
19619
19826
  }
19620
19827
  return { sessionId, fromCwd, lines, sidecar };
@@ -19622,22 +19829,22 @@ async function exportSession(sessionId, fromCwd) {
19622
19829
  function escapeRe(s) {
19623
19830
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
19624
19831
  }
19625
- function rekey(text, fromCwd, toCwd) {
19626
- return text.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
19832
+ function rekey(text2, fromCwd, toCwd) {
19833
+ return text2.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
19627
19834
  }
19628
19835
  async function importSession(exp, toCwd) {
19629
19836
  const destDir = sessionDir(toCwd);
19630
- await mkdir(destDir, { recursive: true });
19631
- const destFile = join4(destDir, `${exp.sessionId}.jsonl`);
19632
- await writeFile(destFile, exp.lines.map((l) => rekey(l, exp.fromCwd, toCwd)).join("\n") + "\n");
19633
- const sideRoot = join4(destDir, exp.sessionId);
19837
+ await mkdir2(destDir, { recursive: true });
19838
+ const destFile = join5(destDir, `${exp.sessionId}.jsonl`);
19839
+ await writeFile2(destFile, exp.lines.map((l) => rekey(l, exp.fromCwd, toCwd)).join("\n") + "\n");
19840
+ const sideRoot = join5(destDir, exp.sessionId);
19634
19841
  for (const s of exp.sidecar) {
19635
- const dest = join4(sideRoot, s.rel.split("/").join(sep));
19842
+ const dest = join5(sideRoot, s.rel.split("/").join(sep));
19636
19843
  if (!isInside(sideRoot, dest))
19637
19844
  continue;
19638
- await mkdir(dirname3(dest), { recursive: true });
19845
+ await mkdir2(dirname3(dest), { recursive: true });
19639
19846
  const data = s.rel.endsWith(".jsonl") || s.rel.endsWith(".json") ? Buffer.from(rekey(s.data.toString("utf-8"), exp.fromCwd, toCwd), "utf-8") : s.data;
19640
- await writeFile(dest, data);
19847
+ await writeFile2(dest, data);
19641
19848
  }
19642
19849
  return destFile;
19643
19850
  }
@@ -19656,7 +19863,7 @@ var init_session_transfer = __esm({
19656
19863
  });
19657
19864
 
19658
19865
  // ../../packages/agent-core/dist/session-store.js
19659
- import { readFile as readFile2, stat } from "node:fs/promises";
19866
+ import { readFile as readFile3, stat } from "node:fs/promises";
19660
19867
  import { listSessions, getSessionMessages, forkSession } from "@anthropic-ai/claude-agent-sdk";
19661
19868
  function toSessionInfo(s) {
19662
19869
  const fromFirst = stripPromptPrefix(s.firstPrompt ?? "").slice(0, 80);
@@ -19702,9 +19909,9 @@ function transcriptMatches(raw, q) {
19702
19909
  }
19703
19910
  return false;
19704
19911
  }
19705
- function stripPromptPrefix(text) {
19912
+ function stripPromptPrefix(text2) {
19706
19913
  const isMetadata = (l) => l.startsWith("I'm working on the page:") || l.startsWith("Selected elements:") || l.startsWith("Element ") || l.startsWith(" DOM Path:") || l.startsWith(" XPath:") || l.startsWith(" CSS:") || l.startsWith(" HTML:") || l.startsWith(" Text:") || l.startsWith(" Position:") || l.startsWith("Use the xpath") || l.startsWith("[") && l.includes("image(s) attached");
19707
- const userLines = text.split("\n").filter((l) => !isMetadata(l));
19914
+ const userLines = text2.split("\n").filter((l) => !isMetadata(l));
19708
19915
  return userLines.join("\n").trim();
19709
19916
  }
19710
19917
  function extractBlocks(message) {
@@ -19723,13 +19930,13 @@ function extractBlocks(message) {
19723
19930
  continue;
19724
19931
  const b = block;
19725
19932
  if (b.type === "thinking" && typeof b.thinking === "string") {
19726
- const text = b.thinking.trim();
19727
- if (text)
19728
- blocks.push({ kind: "thinking", content: text });
19933
+ const text2 = b.thinking.trim();
19934
+ if (text2)
19935
+ blocks.push({ kind: "thinking", content: text2 });
19729
19936
  } else if (b.type === "text" && typeof b.text === "string") {
19730
- const text = b.text.trim();
19731
- if (text && !text.startsWith("<ide_") && !text.startsWith("<system-reminder>")) {
19732
- blocks.push({ kind: "text", content: text });
19937
+ const text2 = b.text.trim();
19938
+ if (text2 && !text2.startsWith("<ide_") && !text2.startsWith("<system-reminder>")) {
19939
+ blocks.push({ kind: "text", content: text2 });
19733
19940
  }
19734
19941
  } else if (b.type === "tool_use") {
19735
19942
  const name = b.name ?? "tool";
@@ -19821,7 +20028,7 @@ var init_session_store = __esm({
19821
20028
  const file2 = sessionFile(s.cwd, s.sessionId);
19822
20029
  const st = await stat(file2);
19823
20030
  if (st.size <= SEARCH_MAX_FILE_BYTES) {
19824
- const raw = await readFile2(file2, "utf-8");
20031
+ const raw = await readFile3(file2, "utf-8");
19825
20032
  if (transcriptMatches(raw, q))
19826
20033
  out.push(info);
19827
20034
  }
@@ -19891,11 +20098,11 @@ var init_log = __esm({
19891
20098
  });
19892
20099
 
19893
20100
  // ../../packages/agent-core/dist/session-usage.js
19894
- import { readFile as readFile3 } from "node:fs/promises";
20101
+ import { readFile as readFile4 } from "node:fs/promises";
19895
20102
  import { execFile } from "node:child_process";
19896
20103
  import { promisify } from "node:util";
19897
20104
  import { homedir as homedir2 } from "node:os";
19898
- import { join as join5 } from "node:path";
20105
+ import { join as join6 } from "node:path";
19899
20106
  function tokenFromCredsBlob(raw) {
19900
20107
  try {
19901
20108
  const j = JSON.parse(raw);
@@ -19909,7 +20116,7 @@ async function tokenFromConfigDir(dir) {
19909
20116
  if (!d)
19910
20117
  return null;
19911
20118
  try {
19912
- return tokenFromCredsBlob(await readFile3(join5(d, ".credentials.json"), "utf8"));
20119
+ return tokenFromCredsBlob(await readFile4(join6(d, ".credentials.json"), "utf8"));
19913
20120
  } catch {
19914
20121
  return null;
19915
20122
  }
@@ -19924,7 +20131,7 @@ async function resolveOauthToken(env) {
19924
20131
  const ambientTok = process.env.CLAUDE_CODE_OAUTH_TOKEN?.trim();
19925
20132
  if (ambientTok)
19926
20133
  return ambientTok;
19927
- const fromAmbientDir = await tokenFromConfigDir(process.env.CLAUDE_CONFIG_DIR ?? join5(homedir2(), ".claude"));
20134
+ const fromAmbientDir = await tokenFromConfigDir(process.env.CLAUDE_CONFIG_DIR ?? join6(homedir2(), ".claude"));
19928
20135
  if (fromAmbientDir)
19929
20136
  return fromAmbientDir;
19930
20137
  if (process.platform === "darwin") {
@@ -20042,11 +20249,11 @@ var init_session_usage = __esm({
20042
20249
 
20043
20250
  // ../../packages/agent-core/dist/agent-manager.js
20044
20251
  import { query, createSdkMcpServer } from "@anthropic-ai/claude-agent-sdk";
20045
- import { writeFile as writeFile2, mkdir as mkdir2, readFile as readFile4 } from "node:fs/promises";
20252
+ import { writeFile as writeFile3, mkdir as mkdir3, readFile as readFile5 } from "node:fs/promises";
20046
20253
  import { randomUUID as randomUUID2 } from "node:crypto";
20047
20254
  import { tmpdir } from "node:os";
20048
- import { join as join6, dirname as dirname4 } from "node:path";
20049
- import { existsSync as existsSync2 } from "node:fs";
20255
+ import { join as join7, dirname as dirname4 } from "node:path";
20256
+ import { existsSync as existsSync2, readFileSync as readFileSync3 } from "node:fs";
20050
20257
  import { fileURLToPath } from "node:url";
20051
20258
  import { createRequire } from "node:module";
20052
20259
  import { createServer } from "node:net";
@@ -20054,7 +20261,7 @@ import { spawn, execSync } from "node:child_process";
20054
20261
  function findClaudeCliJs() {
20055
20262
  const require2 = createRequire(import.meta.url);
20056
20263
  const sdkMain = require2.resolve("@anthropic-ai/claude-agent-sdk");
20057
- const cliJs = join6(dirname4(sdkMain), "cli.js");
20264
+ const cliJs = join7(dirname4(sdkMain), "cli.js");
20058
20265
  if (!existsSync2(cliJs)) {
20059
20266
  throw new Error(`Claude Agent SDK cli.js not found at ${cliJs}. The installed SDK version may not ship cli.js \u2014 apps/host/package.json pins @anthropic-ai/claude-agent-sdk to a version that includes it.`);
20060
20267
  }
@@ -20158,15 +20365,15 @@ ${plan}`;
20158
20365
  }
20159
20366
  }
20160
20367
  function flattenToolResultContent(content) {
20161
- let text = "";
20368
+ let text2 = "";
20162
20369
  if (typeof content === "string")
20163
- text = content;
20370
+ text2 = content;
20164
20371
  else if (Array.isArray(content)) {
20165
- text = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
20372
+ text2 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
20166
20373
  }
20167
- if (text.length > TOOL_RESULT_CAP)
20168
- return { text: text.slice(0, TOOL_RESULT_CAP), truncated: true };
20169
- return { text, truncated: false };
20374
+ if (text2.length > TOOL_RESULT_CAP)
20375
+ return { text: text2.slice(0, TOOL_RESULT_CAP), truncated: true };
20376
+ return { text: text2, truncated: false };
20170
20377
  }
20171
20378
  function extractImages(content) {
20172
20379
  if (!Array.isArray(content))
@@ -20209,7 +20416,7 @@ function editedPathOf(toolInput) {
20209
20416
  }
20210
20417
  async function snapshotFile(path5) {
20211
20418
  try {
20212
- const buf = await readFile4(path5);
20419
+ const buf = await readFile5(path5);
20213
20420
  if (buf.length > EDIT_PREVIEW_CAP)
20214
20421
  return { noPreview: true };
20215
20422
  if (buf.subarray(0, 8192).includes(0))
@@ -20229,12 +20436,42 @@ function sourcesEqual(a, b) {
20229
20436
  return false;
20230
20437
  return true;
20231
20438
  }
20439
+ function buildMobileClause(dir) {
20440
+ try {
20441
+ let fw = "";
20442
+ let runCmd = "";
20443
+ if (existsSync2(join7(dir, "pubspec.yaml"))) {
20444
+ fw = "Flutter";
20445
+ runCmd = "flutter run -d chrome";
20446
+ } else if (existsSync2(join7(dir, "package.json"))) {
20447
+ const pkg = JSON.parse(readFileSync3(join7(dir, "package.json"), "utf8"));
20448
+ const deps = { ...pkg.dependencies, ...pkg.devDependencies };
20449
+ if (deps.expo) {
20450
+ fw = "Expo";
20451
+ runCmd = "npx expo start --web";
20452
+ } else if (deps["react-native"]) {
20453
+ fw = "React Native";
20454
+ runCmd = "npm run web (react-native-web)";
20455
+ }
20456
+ }
20457
+ if (!fw)
20458
+ return "";
20459
+ return `
20460
+
20461
+ MOBILE (${fw}):
20462
+ - For a fast live preview, run the app AS WEB (\`${runCmd}\`) and tell the user the localhost URL \u2014 Tesseract shows it in a phone-framed canvas where elements can be picked and edited. Use a real device/simulator only when native-specific behavior matters.`;
20463
+ } catch {
20464
+ return "";
20465
+ }
20466
+ }
20232
20467
  var cachedNodeExe, HUMAN_READABLE_FIELDS, TOOL_RESULT_CAP, MAX_RESULT_IMAGES, MAX_IMAGE_BASE64, PERMISSION_MODES, EDIT_PREVIEW_CAP, AsyncMessagePump, IDLE_REAP_MS, MODERATE_IDLE_MS, STEER_COALESCE_MS, AgentManager;
20233
20468
  var init_agent_manager = __esm({
20234
20469
  "../../packages/agent-core/dist/agent-manager.js"() {
20235
20470
  "use strict";
20236
20471
  init_dist();
20237
20472
  init_cron_tools();
20473
+ init_design_tools();
20474
+ init_design_tokens();
20238
20475
  init_narrator();
20239
20476
  init_plan_splitter();
20240
20477
  init_trace_store();
@@ -20277,7 +20514,7 @@ var init_agent_manager = __esm({
20277
20514
  if (this.closed) {
20278
20515
  return Promise.resolve({ value: void 0, done: true });
20279
20516
  }
20280
- return new Promise((resolve8) => this.resolvers.push(resolve8));
20517
+ return new Promise((resolve9) => this.resolvers.push(resolve9));
20281
20518
  },
20282
20519
  return: () => {
20283
20520
  this.end();
@@ -20303,6 +20540,10 @@ var init_agent_manager = __esm({
20303
20540
  /** requestId → the originating browser-cli socket, for unicast responses.
20304
20541
  * browser-cli is one-shot, so the entry is deleted on the first write. */
20305
20542
  pendingResponses = /* @__PURE__ */ new Map();
20543
+ /** Resolvers for HOST-originated browser requests (design tools), keyed by
20544
+ * requestId — disjoint from pendingResponses (browser-cli sockets). Resolved by
20545
+ * sendBrowserResponse when the host replies. */
20546
+ pendingBrowserResolvers = /* @__PURE__ */ new Map();
20306
20547
  /** requestId → a parked canUseTool decision. The Promise resolves when the
20307
20548
  * client replies with chat:permission (→ respondToPermission) or the turn is
20308
20549
  * aborted (→ deny). `suggestions` is echoed back as updatedPermissions when the
@@ -20415,8 +20656,8 @@ var init_agent_manager = __esm({
20415
20656
  this.send = send2;
20416
20657
  this.onBrowserRequest = onBrowserRequest;
20417
20658
  const __dirname = dirname4(fileURLToPath(import.meta.url));
20418
- this.browserCliPath = join6(__dirname, "browser-cli.js");
20419
- this.narrator = new Narrator((sessionId, text, engineLabel) => this.send({ type: "agent:narration", sessionId, text, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
20659
+ this.browserCliPath = join7(__dirname, "browser-cli.js");
20660
+ this.narrator = new Narrator((sessionId, text2, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text2, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
20420
20661
  }
20421
20662
  /** Inject (or clear) the cheap model used for the live status narration. The
20422
20663
  * host resolves creds and builds the completion fn (keeping secrets host-side). */
@@ -20443,7 +20684,7 @@ var init_agent_manager = __esm({
20443
20684
  * (no shared-socket "which session?" race) with ZERO changes to browser-cli.
20444
20685
  */
20445
20686
  startSessionListener(live) {
20446
- return new Promise((resolve8) => {
20687
+ return new Promise((resolve9) => {
20447
20688
  const server = createServer((socket2) => {
20448
20689
  live.ipcSockets.add(socket2);
20449
20690
  let buffer = "";
@@ -20475,11 +20716,21 @@ var init_agent_manager = __esm({
20475
20716
  const addr = server.address();
20476
20717
  live.ipcPort = typeof addr === "object" && addr ? addr.port : 0;
20477
20718
  log("Session IPC listener on port", live.ipcPort, "for", live.sessionId || live.clientRequestId || "(pending)");
20478
- resolve8();
20719
+ resolve9();
20479
20720
  });
20480
20721
  });
20481
20722
  }
20482
20723
  sendBrowserResponse(requestId, result, error51) {
20724
+ const pending = this.pendingBrowserResolvers.get(requestId);
20725
+ if (pending) {
20726
+ this.pendingBrowserResolvers.delete(requestId);
20727
+ clearTimeout(pending.timer);
20728
+ if (error51)
20729
+ pending.reject(new Error(error51));
20730
+ else
20731
+ pending.resolve(result);
20732
+ return;
20733
+ }
20483
20734
  const socket2 = this.pendingResponses.get(requestId);
20484
20735
  if (!socket2)
20485
20736
  return;
@@ -20489,6 +20740,28 @@ var init_agent_manager = __esm({
20489
20740
  } catch {
20490
20741
  }
20491
20742
  }
20743
+ /** Drive THIS session's connected browser from host-side tool code and await the
20744
+ * result (mirrors the browser-cli round-trip, but in-process). Used by the design
20745
+ * MCP tools (capture_element_styles). Rejects after 15s if the host never replies
20746
+ * (e.g. no preview open). Reuses the existing onBrowserRequest/sendBrowserResponse
20747
+ * pair — the host neither knows nor cares the requestId originated here. */
20748
+ requestBrowser(live, action, params) {
20749
+ return new Promise((resolve9, reject) => {
20750
+ const requestId = `design:${randomUUID2()}`;
20751
+ const timer = setTimeout(() => {
20752
+ this.pendingBrowserResolvers.delete(requestId);
20753
+ reject(new Error("browser request timed out"));
20754
+ }, 15e3);
20755
+ this.pendingBrowserResolvers.set(requestId, { resolve: resolve9, reject, timer });
20756
+ try {
20757
+ this.onBrowserRequest(requestId, action, params, live.browserId, live.windowId);
20758
+ } catch (err) {
20759
+ this.pendingBrowserResolvers.delete(requestId);
20760
+ clearTimeout(timer);
20761
+ reject(err instanceof Error ? err : new Error(String(err)));
20762
+ }
20763
+ });
20764
+ }
20492
20765
  /** Resolve a parked canUseTool decision (client replied with chat:permission).
20493
20766
  * No-op if the request is unknown (already resolved / aborted). On "allow &
20494
20767
  * don't ask again" (persist) we hand the SDK its own suggested permission
@@ -20595,9 +20868,9 @@ var init_agent_manager = __esm({
20595
20868
  const transcripts = [];
20596
20869
  for (const sid of sessionIds) {
20597
20870
  const msgs = await this.sessionStore.getSessionMessages(sid).catch(() => []);
20598
- const text = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n").slice(0, PER_SOURCE_CAP);
20599
- if (text.trim())
20600
- transcripts.push(text);
20871
+ const text2 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${m.content}`).join("\n").slice(0, PER_SOURCE_CAP);
20872
+ if (text2.trim())
20873
+ transcripts.push(text2);
20601
20874
  }
20602
20875
  if (transcripts.length === 0)
20603
20876
  return;
@@ -20676,6 +20949,11 @@ ${t}`)
20676
20949
  const cli = `ELECTRON_RUN_AS_NODE=1 "${process.execPath}" "${this.browserCliPath}"`;
20677
20950
  const pageInfo = url2 ? `
20678
20951
  The user's current browser tab is: ${url2}` : "";
20952
+ const designClause = this.projectDir && existsSync2(join7(this.projectDir, TOKENS_FILE)) ? `
20953
+
20954
+ DESIGN SYSTEM:
20955
+ - 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.` : "";
20956
+ const mobileClause = this.projectDir ? buildMobileClause(this.projectDir) : "";
20679
20957
  return `You are Fineguide Tesseract, an AI assistant helping developers inspect and fix web pages.
20680
20958
  You have direct access to the browser connected to this conversation via CLI tools. Use the Bash tool to call them:${pageInfo}
20681
20959
 
@@ -20692,19 +20970,19 @@ CRITICAL RULES:
20692
20970
  - Use screenshot to see the visual state.
20693
20971
  - When element selectors are provided, use click or evaluate to interact.
20694
20972
  - You can read and edit project source files if a project directory is configured.
20695
- - Always confirm before making destructive changes to source files.`;
20973
+ - Always confirm before making destructive changes to source files.${designClause}${mobileClause}`;
20696
20974
  }
20697
20975
  async sendMessage(params) {
20698
20976
  if (params.images && params.images.length > 0) {
20699
- const imgDir = join6(tmpdir(), "ccb-images");
20700
- await mkdir2(imgDir, { recursive: true });
20977
+ const imgDir = join7(tmpdir(), "ccb-images");
20978
+ await mkdir3(imgDir, { recursive: true });
20701
20979
  const paths = [];
20702
20980
  for (let i = 0; i < params.images.length; i++) {
20703
20981
  const match = params.images[i].match(/^data:image\/(\w+);base64,(.+)$/);
20704
20982
  if (match) {
20705
20983
  const ext = match[1] === "jpeg" ? "jpg" : match[1];
20706
- const filePath = join6(imgDir, `img-${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}.${ext}`);
20707
- await writeFile2(filePath, Buffer.from(match[2], "base64"));
20984
+ const filePath = join7(imgDir, `img-${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}.${ext}`);
20985
+ await writeFile3(filePath, Buffer.from(match[2], "base64"));
20708
20986
  paths.push(filePath);
20709
20987
  }
20710
20988
  }
@@ -20713,8 +20991,8 @@ CRITICAL RULES:
20713
20991
  }
20714
20992
  }
20715
20993
  if (params.files && params.files.length > 0) {
20716
- const fileDir = join6(tmpdir(), "ccb-files");
20717
- await mkdir2(fileDir, { recursive: true });
20994
+ const fileDir = join7(tmpdir(), "ccb-files");
20995
+ await mkdir3(fileDir, { recursive: true });
20718
20996
  const paths = [];
20719
20997
  for (let i = 0; i < params.files.length; i++) {
20720
20998
  const f = params.files[i];
@@ -20722,8 +21000,8 @@ CRITICAL RULES:
20722
21000
  if (!match)
20723
21001
  continue;
20724
21002
  const safe = (f.name || `file-${i}`).replace(/[^\w.\-]+/g, "_").slice(-100);
20725
- const filePath = join6(fileDir, `${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}-${safe}`);
20726
- await writeFile2(filePath, Buffer.from(match[1], "base64"));
21003
+ const filePath = join7(fileDir, `${process.pid}-${Date.now()}-${randomUUID2().slice(0, 8)}-${i}-${safe}`);
21004
+ await writeFile3(filePath, Buffer.from(match[1], "base64"));
20727
21005
  paths.push(filePath);
20728
21006
  }
20729
21007
  if (paths.length > 0) {
@@ -20901,6 +21179,15 @@ CRITICAL RULES:
20901
21179
  const cronTools = buildCronTools({ store: this.cronStore, pushEnabled: this.cronToolsDeps.pushEnabled, dispatchPush: this.cronToolsDeps.dispatchPush, getSessionId: () => live.sessionId || void 0 });
20902
21180
  mcp["tesseract-cron"] = createSdkMcpServer({ name: "tesseract-cron", version: "0.1.0", tools: cronTools });
20903
21181
  }
21182
+ if (this.projectDir) {
21183
+ const designTools = buildDesignTools({
21184
+ getProjectDir: () => this.projectDir,
21185
+ driveBrowser: (action, params2) => this.requestBrowser(live, action, params2),
21186
+ getSessionId: () => live.sessionId || void 0,
21187
+ notifyPreviewReady: (url2, kind) => this.send({ type: "agent:preview_ready", sessionId: live.sessionId, previewUrl: url2, kind, ts: Date.now() }, live.origin)
21188
+ });
21189
+ mcp["tesseract-design"] = createSdkMcpServer({ name: "tesseract-design", version: "0.1.0", tools: designTools });
21190
+ }
20904
21191
  return Object.keys(mcp).length > 0 ? { mcpServers: mcp } : {};
20905
21192
  })(),
20906
21193
  // Skills (Epic H): a local plugin bundling the enabled ClawHub skills, so the SDK
@@ -20914,20 +21201,20 @@ CRITICAL RULES:
20914
21201
  // in acceptEdits, everything risky in default/auto). We park a Promise and
20915
21202
  // resolve it when the client replies via chat:permission (respondToPermission),
20916
21203
  // or deny on abort so an interrupted turn never leaks a pending decision.
20917
- canUseTool: (toolName, input, opts) => new Promise((resolve8) => {
21204
+ canUseTool: (toolName, input, opts) => new Promise((resolve9) => {
20918
21205
  const requestId = randomUUID2();
20919
21206
  const onAbort = () => {
20920
21207
  if (this.pendingPermissions.delete(requestId)) {
20921
- resolve8({ behavior: "deny", message: "Interrupted.", interrupt: true });
21208
+ resolve9({ behavior: "deny", message: "Interrupted.", interrupt: true });
20922
21209
  }
20923
21210
  };
20924
21211
  const cleanup2 = () => opts.signal.removeEventListener("abort", onAbort);
20925
21212
  if (opts.signal.aborted) {
20926
- resolve8({ behavior: "deny", message: "Interrupted.", interrupt: true });
21213
+ resolve9({ behavior: "deny", message: "Interrupted.", interrupt: true });
20927
21214
  return;
20928
21215
  }
20929
21216
  opts.signal.addEventListener("abort", onAbort, { once: true });
20930
- this.pendingPermissions.set(requestId, { resolve: resolve8, suggestions: opts.suggestions, cleanup: cleanup2, origin: live.origin });
21217
+ this.pendingPermissions.set(requestId, { resolve: resolve9, suggestions: opts.suggestions, cleanup: cleanup2, origin: live.origin });
20931
21218
  const evt = {
20932
21219
  type: "agent:permission_request",
20933
21220
  sessionId: live.sessionId,
@@ -20953,19 +21240,19 @@ CRITICAL RULES:
20953
21240
  // M5 H6 — an MCP server requesting user input (a form, or url-based OAuth).
20954
21241
  // Default is auto-cancel; we park a Promise and raise an inline card, then
20955
21242
  // resolve it from chat:elicitation (respondToElicitation). Mirrors canUseTool.
20956
- onElicitation: (request, opts) => new Promise((resolve8) => {
21243
+ onElicitation: (request, opts) => new Promise((resolve9) => {
20957
21244
  const requestId = randomUUID2();
20958
21245
  const onAbort = () => {
20959
21246
  if (this.pendingElicitations.delete(requestId))
20960
- resolve8({ action: "cancel" });
21247
+ resolve9({ action: "cancel" });
20961
21248
  };
20962
21249
  const cleanup2 = () => opts.signal.removeEventListener("abort", onAbort);
20963
21250
  if (opts.signal.aborted) {
20964
- resolve8({ action: "cancel" });
21251
+ resolve9({ action: "cancel" });
20965
21252
  return;
20966
21253
  }
20967
21254
  opts.signal.addEventListener("abort", onAbort, { once: true });
20968
- this.pendingElicitations.set(requestId, { resolve: resolve8, cleanup: cleanup2, origin: live.origin });
21255
+ this.pendingElicitations.set(requestId, { resolve: resolve9, cleanup: cleanup2, origin: live.origin });
20969
21256
  const evt = {
20970
21257
  type: "agent:elicitation_request",
20971
21258
  sessionId: live.sessionId,
@@ -21185,26 +21472,26 @@ CRITICAL RULES:
21185
21472
  emit({ type: "chat:stream", sessionId: sid, delta: event.delta.thinking, messageId: message.uuid, kind: "thinking", ...parentField });
21186
21473
  }
21187
21474
  if (event.delta?.type === "text_delta" && event.delta.text) {
21188
- const text = event.delta.text;
21189
- if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text)) {
21475
+ const text2 = event.delta.text;
21476
+ if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text2)) {
21190
21477
  insideXmlByKey.set(key2, true);
21191
21478
  break;
21192
21479
  }
21193
21480
  if (insideXmlByKey.get(key2)) {
21194
- if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text)) {
21481
+ if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text2)) {
21195
21482
  insideXmlByKey.set(key2, false);
21196
21483
  }
21197
21484
  break;
21198
21485
  }
21199
- if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text))
21486
+ if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text2))
21200
21487
  break;
21201
- if (/<parameter\s+name=/.test(text))
21488
+ if (/<parameter\s+name=/.test(text2))
21202
21489
  break;
21203
- if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text))
21490
+ if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text2))
21204
21491
  break;
21205
21492
  if (parentToolUseId === void 0)
21206
21493
  turnStreamed = true;
21207
- emit({ type: "chat:stream", sessionId: sid, delta: text, messageId: message.uuid, kind: "text", ...parentField });
21494
+ emit({ type: "chat:stream", sessionId: sid, delta: text2, messageId: message.uuid, kind: "text", ...parentField });
21208
21495
  }
21209
21496
  if (event.delta?.type === "input_json_delta" && event.delta.partial_json) {
21210
21497
  const acc = blockAcc.get(key2);
@@ -21447,11 +21734,11 @@ Compacted earlier context.` });
21447
21734
  case "files_persisted":
21448
21735
  break;
21449
21736
  default: {
21450
- const text = extractHumanReadable(m);
21737
+ const text2 = extractHumanReadable(m);
21451
21738
  const header = systemHeader("system", subtype);
21452
- const body = text ? `${header}
21739
+ const body = text2 ? `${header}
21453
21740
 
21454
- ${text}` : header;
21741
+ ${text2}` : header;
21455
21742
  emit({ type: "agent:tool_use", sessionId: sid, toolName: "_notice_", summary: body });
21456
21743
  log("best-effort surfaced unknown system subtype:", subtype ?? "?");
21457
21744
  break;
@@ -21487,12 +21774,12 @@ ${text}` : header;
21487
21774
  const tn = toolNameByUseId.get(toolUseId);
21488
21775
  if (tn === "Edit" || tn === "Write" || tn === "MultiEdit" || tn === "NotebookEdit")
21489
21776
  continue;
21490
- const { text, truncated } = flattenToolResultContent(blk.content);
21777
+ const { text: text2, truncated } = flattenToolResultContent(blk.content);
21491
21778
  const images = extractImages(blk.content);
21492
21779
  const isError = blk.is_error === true;
21493
- if (!text && images.length === 0 && !isError)
21780
+ if (!text2 && images.length === 0 && !isError)
21494
21781
  continue;
21495
- emit({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text, images, truncated, ...agentId ? { agentId } : {} });
21782
+ emit({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text2, images, truncated, ...agentId ? { agentId } : {} });
21496
21783
  } else if (blk?.type === "web_search_tool_result") {
21497
21784
  const toolUseId = blk.tool_use_id;
21498
21785
  if (!toolUseId)
@@ -21509,11 +21796,11 @@ ${text}` : header;
21509
21796
  break;
21510
21797
  default: {
21511
21798
  const m = message;
21512
- const text = extractHumanReadable(m);
21799
+ const text2 = extractHumanReadable(m);
21513
21800
  const header = systemHeader(m.type || "unknown");
21514
- const body = text ? `${header}
21801
+ const body = text2 ? `${header}
21515
21802
 
21516
- ${text}` : header;
21803
+ ${text2}` : header;
21517
21804
  emit({ type: "agent:tool_use", sessionId: sid, toolName: "_notice_", summary: body });
21518
21805
  log("best-effort surfaced unknown SDK message type:", m.type || "?");
21519
21806
  break;
@@ -21818,6 +22105,8 @@ Element ${i + 1}:`);
21818
22105
  parts.push(` XPath: ${a.xpath}`, ` CSS: ${a.selector}`, ` HTML: ${a.htmlSnippet}`);
21819
22106
  if (a.textPreview)
21820
22107
  parts.push(` Text: "${a.textPreview}"`);
22108
+ if (a.sourceLoc)
22109
+ parts.push(` Source: ${a.sourceLoc.file}:${a.sourceLoc.line}${a.sourceLoc.column != null ? `:${a.sourceLoc.column}` : ""} (edit the element here)`);
21821
22110
  }
21822
22111
  }
21823
22112
  return parts.join("\n");
@@ -21830,15 +22119,23 @@ Element ${i + 1}:`);
21830
22119
  var dist_exports = {};
21831
22120
  __export(dist_exports, {
21832
22121
  AgentManager: () => AgentManager,
22122
+ DESIGN_CLAUDE_MD: () => DESIGN_CLAUDE_MD,
22123
+ DESIGN_DIR: () => DESIGN_DIR,
22124
+ DesignTokensSchema: () => DesignTokensSchema,
21833
22125
  SessionStore: () => SessionStore,
22126
+ TOKENS_CSS_FILE: () => TOKENS_CSS_FILE,
22127
+ TOKENS_FILE: () => TOKENS_FILE,
21834
22128
  buildClaudeNarrationLlm: () => buildClaudeNarrationLlm,
21835
22129
  exportSession: () => exportSession,
22130
+ getTokenPath: () => getTokenPath,
21836
22131
  importSession: () => importSession,
21837
22132
  log: () => log,
21838
22133
  resolveOauthToken: () => resolveOauthToken,
21839
22134
  sanitizeProjectDir: () => sanitizeProjectDir,
21840
22135
  sessionDir: () => sessionDir,
21841
22136
  sessionFile: () => sessionFile,
22137
+ setTokenPath: () => setTokenPath,
22138
+ tokensToCss: () => tokensToCss,
21842
22139
  transferSession: () => transferSession
21843
22140
  });
21844
22141
  var init_dist2 = __esm({
@@ -21849,6 +22146,7 @@ var init_dist2 = __esm({
21849
22146
  init_session_usage();
21850
22147
  init_session_transfer();
21851
22148
  init_log();
22149
+ init_design_tokens();
21852
22150
  }
21853
22151
  });
21854
22152
 
@@ -23056,11 +23354,11 @@ function __metadata(metadataKey, metadataValue) {
23056
23354
  }
23057
23355
  function __awaiter(thisArg, _arguments, P, generator) {
23058
23356
  function adopt(value) {
23059
- return value instanceof P ? value : new P(function(resolve8) {
23060
- resolve8(value);
23357
+ return value instanceof P ? value : new P(function(resolve9) {
23358
+ resolve9(value);
23061
23359
  });
23062
23360
  }
23063
- return new (P || (P = Promise))(function(resolve8, reject) {
23361
+ return new (P || (P = Promise))(function(resolve9, reject) {
23064
23362
  function fulfilled(value) {
23065
23363
  try {
23066
23364
  step(generator.next(value));
@@ -23076,7 +23374,7 @@ function __awaiter(thisArg, _arguments, P, generator) {
23076
23374
  }
23077
23375
  }
23078
23376
  function step(result) {
23079
- result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
23377
+ result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
23080
23378
  }
23081
23379
  step((generator = generator.apply(thisArg, _arguments || [])).next());
23082
23380
  });
@@ -23267,14 +23565,14 @@ function __asyncValues(o) {
23267
23565
  }, i);
23268
23566
  function verb(n) {
23269
23567
  i[n] = o[n] && function(v) {
23270
- return new Promise(function(resolve8, reject) {
23271
- v = o[n](v), settle(resolve8, reject, v.done, v.value);
23568
+ return new Promise(function(resolve9, reject) {
23569
+ v = o[n](v), settle(resolve9, reject, v.done, v.value);
23272
23570
  });
23273
23571
  };
23274
23572
  }
23275
- function settle(resolve8, reject, d, v) {
23573
+ function settle(resolve9, reject, d, v) {
23276
23574
  Promise.resolve(v).then(function(v2) {
23277
- resolve8({ value: v2, done: d });
23575
+ resolve9({ value: v2, done: d });
23278
23576
  }, reject);
23279
23577
  }
23280
23578
  }
@@ -23552,8 +23850,8 @@ var require_build = __commonJS({
23552
23850
  var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
23553
23851
  var BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
23554
23852
  var Utf8Converter = class {
23555
- static fromString(text) {
23556
- const s = unescape(encodeURIComponent(text));
23853
+ static fromString(text2) {
23854
+ const s = unescape(encodeURIComponent(text2));
23557
23855
  const uintArray = new Uint8Array(s.length);
23558
23856
  for (let i = 0; i < s.length; i++) {
23559
23857
  uintArray[i] = s.charCodeAt(i);
@@ -23581,11 +23879,11 @@ var require_build = __commonJS({
23581
23879
  }
23582
23880
  return res;
23583
23881
  }
23584
- static fromString(text, littleEndian = false) {
23585
- const res = new ArrayBuffer(text.length * 2);
23882
+ static fromString(text2, littleEndian = false) {
23883
+ const res = new ArrayBuffer(text2.length * 2);
23586
23884
  const dataView = new DataView(res);
23587
- for (let i = 0; i < text.length; i++) {
23588
- dataView.setUint16(i * 2, text.charCodeAt(i), littleEndian);
23885
+ for (let i = 0; i < text2.length; i++) {
23886
+ dataView.setUint16(i * 2, text2.charCodeAt(i), littleEndian);
23589
23887
  }
23590
23888
  return res;
23591
23889
  }
@@ -23682,18 +23980,18 @@ var require_build = __commonJS({
23682
23980
  static ToBase64Url(data) {
23683
23981
  return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
23684
23982
  }
23685
- static FromUtf8String(text, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
23983
+ static FromUtf8String(text2, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
23686
23984
  switch (encoding) {
23687
23985
  case "ascii":
23688
- return this.FromBinary(text);
23986
+ return this.FromBinary(text2);
23689
23987
  case "utf8":
23690
- return Utf8Converter.fromString(text);
23988
+ return Utf8Converter.fromString(text2);
23691
23989
  case "utf16":
23692
23990
  case "utf16be":
23693
- return Utf16Converter.fromString(text);
23991
+ return Utf16Converter.fromString(text2);
23694
23992
  case "utf16le":
23695
23993
  case "usc2":
23696
- return Utf16Converter.fromString(text, true);
23994
+ return Utf16Converter.fromString(text2, true);
23697
23995
  default:
23698
23996
  throw new Error(`Unknown type of encoding '${encoding}'`);
23699
23997
  }
@@ -23714,11 +24012,11 @@ var require_build = __commonJS({
23714
24012
  throw new Error(`Unknown type of encoding '${encoding}'`);
23715
24013
  }
23716
24014
  }
23717
- static FromBinary(text) {
23718
- const stringLength = text.length;
24015
+ static FromBinary(text2) {
24016
+ const stringLength = text2.length;
23719
24017
  const resultView = new Uint8Array(stringLength);
23720
24018
  for (let i = 0; i < stringLength; i++) {
23721
- resultView[i] = text.charCodeAt(i);
24019
+ resultView[i] = text2.charCodeAt(i);
23722
24020
  }
23723
24021
  return resultView.buffer;
23724
24022
  }
@@ -23764,8 +24062,8 @@ var require_build = __commonJS({
23764
24062
  static ToUtf16String(buffer, littleEndian = false) {
23765
24063
  return Utf16Converter.toString(buffer, littleEndian);
23766
24064
  }
23767
- static FromUtf16String(text, littleEndian = false) {
23768
- return Utf16Converter.fromString(text, littleEndian);
24065
+ static FromUtf16String(text2, littleEndian = false) {
24066
+ return Utf16Converter.fromString(text2, littleEndian);
23769
24067
  }
23770
24068
  static Base64Padding(base643) {
23771
24069
  const padCount = 4 - base643.length % 4;
@@ -27526,15 +27824,15 @@ var require_sequence = __commonJS({
27526
27824
  }
27527
27825
  return normalized;
27528
27826
  }
27529
- function encodeAscii(text) {
27530
- const bytes = new Uint8Array(text.length);
27531
- for (let i = 0; i < text.length; i++) {
27532
- bytes[i] = text.charCodeAt(i) & 255;
27827
+ function encodeAscii(text2) {
27828
+ const bytes = new Uint8Array(text2.length);
27829
+ for (let i = 0; i < text2.length; i++) {
27830
+ bytes[i] = text2.charCodeAt(i) & 255;
27533
27831
  }
27534
27832
  return bytes;
27535
27833
  }
27536
- function encodeUtf8(text) {
27537
- return new TextEncoder().encode(text);
27834
+ function encodeUtf8(text2) {
27835
+ return new TextEncoder().encode(text2);
27538
27836
  }
27539
27837
  function toPatternBytes(pattern, options) {
27540
27838
  if (typeof pattern === "string") {
@@ -28909,15 +29207,15 @@ var require_binary = __commonJS({
28909
29207
  }
28910
29208
  return result;
28911
29209
  }
28912
- function decode3(text) {
28913
- const result = new Uint8Array(text.length);
28914
- for (let i = 0; i < text.length; i++) {
28915
- result[i] = text.charCodeAt(i) & 255;
29210
+ function decode3(text2) {
29211
+ const result = new Uint8Array(text2.length);
29212
+ for (let i = 0; i < text2.length; i++) {
29213
+ result[i] = text2.charCodeAt(i) & 255;
28916
29214
  }
28917
29215
  return result;
28918
29216
  }
28919
- function is(text) {
28920
- return typeof text === "string";
29217
+ function is(text2) {
29218
+ return typeof text2 === "string";
28921
29219
  }
28922
29220
  exports.binary = { encode: encode3, decode: decode3, is };
28923
29221
  }
@@ -28952,31 +29250,31 @@ var require_hex = __commonJS({
28952
29250
  throw new TypeError("Hex separators must be non-empty strings");
28953
29251
  }
28954
29252
  }
28955
- function matchSeparator(text, index, separators) {
29253
+ function matchSeparator(text2, index, separators) {
28956
29254
  for (const separator of separators) {
28957
- if (text.startsWith(separator, index)) {
29255
+ if (text2.startsWith(separator, index)) {
28958
29256
  return separator;
28959
29257
  }
28960
29258
  }
28961
29259
  return void 0;
28962
29260
  }
28963
- function detectCase(text) {
28964
- const hasUpper = /[A-F]/.test(text);
28965
- const hasLower = /[a-f]/.test(text);
29261
+ function detectCase(text2) {
29262
+ const hasUpper = /[A-F]/.test(text2);
29263
+ const hasLower = /[a-f]/.test(text2);
28966
29264
  return hasUpper && !hasLower ? "upper" : "lower";
28967
29265
  }
28968
- function detectLineSeparator(text) {
28969
- const match = /\r\n|\n/.exec(text);
29266
+ function detectLineSeparator(text2) {
29267
+ const match = /\r\n|\n/.exec(text2);
28970
29268
  if (!match) {
28971
29269
  return void 0;
28972
29270
  }
28973
29271
  return match[0] === "\r\n" ? "\r\n" : "\n";
28974
29272
  }
28975
- function compactForDetection(text) {
28976
- return text.replace(/[^0-9a-f]/gi, "");
29273
+ function compactForDetection(text2) {
29274
+ return text2.replace(/[^0-9a-f]/gi, "");
28977
29275
  }
28978
- function detectGroup(text) {
28979
- const segments = text.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
29276
+ function detectGroup(text2) {
29277
+ const segments = text2.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
28980
29278
  if (segments.length < 3) {
28981
29279
  return void 0;
28982
29280
  }
@@ -29004,8 +29302,8 @@ var require_hex = __commonJS({
29004
29302
  separator
29005
29303
  };
29006
29304
  }
29007
- function detectFormat(text) {
29008
- const trimmed = text.trim();
29305
+ function detectFormat(text2) {
29306
+ const trimmed = text2.trim();
29009
29307
  const prefix = /^0x/i.test(trimmed) ? "0x" : "";
29010
29308
  const body = prefix ? trimmed.slice(2) : trimmed;
29011
29309
  const lineSeparator = detectLineSeparator(body);
@@ -29030,13 +29328,13 @@ var require_hex = __commonJS({
29030
29328
  }
29031
29329
  return format2;
29032
29330
  }
29033
- function normalizeText(text, options) {
29331
+ function normalizeText(text2, options) {
29034
29332
  const allowPrefix = options.allowPrefix ?? true;
29035
29333
  const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
29036
29334
  for (const separator of separators) {
29037
29335
  validateSeparator(separator);
29038
29336
  }
29039
- let working = text.trim();
29337
+ let working = text2.trim();
29040
29338
  if (/^0x/i.test(working)) {
29041
29339
  if (!allowPrefix) {
29042
29340
  throw new TypeError("Hexadecimal text must not include a 0x prefix");
@@ -29087,15 +29385,15 @@ var require_hex = __commonJS({
29087
29385
  }
29088
29386
  return chunks.join(group.separator);
29089
29387
  }
29090
- function normalize2(text, options = {}) {
29091
- return normalizeText(text, options);
29388
+ function normalize2(text2, options = {}) {
29389
+ return normalizeText(text2, options);
29092
29390
  }
29093
- function is(text, options = {}) {
29094
- if (typeof text !== "string") {
29391
+ function is(text2, options = {}) {
29392
+ if (typeof text2 !== "string") {
29095
29393
  return false;
29096
29394
  }
29097
29395
  try {
29098
- normalize2(text, options);
29396
+ normalize2(text2, options);
29099
29397
  return true;
29100
29398
  } catch {
29101
29399
  return false;
@@ -29105,8 +29403,8 @@ var require_hex = __commonJS({
29105
29403
  const bytes = (0, index_js_1.toUint8Array)(data);
29106
29404
  const casing = options.case ?? "lower";
29107
29405
  const pairs = Array.from(bytes, (byte) => {
29108
- const text = byte.toString(16).padStart(2, "0");
29109
- return casing === "upper" ? text.toUpperCase() : text;
29406
+ const text2 = byte.toString(16).padStart(2, "0");
29407
+ return casing === "upper" ? text2.toUpperCase() : text2;
29110
29408
  });
29111
29409
  let body = "";
29112
29410
  if (options.line) {
@@ -29125,19 +29423,19 @@ var require_hex = __commonJS({
29125
29423
  }
29126
29424
  return `${options.prefix ?? ""}${body}`;
29127
29425
  }
29128
- function decode3(text, options = {}) {
29129
- const normalized = normalize2(text, options);
29426
+ function decode3(text2, options = {}) {
29427
+ const normalized = normalize2(text2, options);
29130
29428
  const result = new Uint8Array(normalized.length / 2);
29131
29429
  for (let i = 0; i < normalized.length; i += 2) {
29132
29430
  result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
29133
29431
  }
29134
29432
  return result;
29135
29433
  }
29136
- function parse3(text, options = {}) {
29137
- const normalized = normalize2(text, options);
29434
+ function parse3(text2, options = {}) {
29435
+ const normalized = normalize2(text2, options);
29138
29436
  return {
29139
29437
  bytes: decode3(normalized),
29140
- format: detectFormat(text),
29438
+ format: detectFormat(text2),
29141
29439
  normalized
29142
29440
  };
29143
29441
  }
@@ -29165,8 +29463,8 @@ var require_utf8 = __commonJS({
29165
29463
  exports.encode = encode3;
29166
29464
  exports.decode = decode3;
29167
29465
  var index_js_1 = require_bytes();
29168
- function encode3(text) {
29169
- return new TextEncoder().encode(text);
29466
+ function encode3(text2) {
29467
+ return new TextEncoder().encode(text2);
29170
29468
  }
29171
29469
  function decode3(data) {
29172
29470
  return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
@@ -29184,11 +29482,11 @@ var require_utf16 = __commonJS({
29184
29482
  exports.encode = encode3;
29185
29483
  exports.decode = decode3;
29186
29484
  var index_js_1 = require_bytes();
29187
- function encode3(text, options = {}) {
29188
- const result = new ArrayBuffer(text.length * 2);
29485
+ function encode3(text2, options = {}) {
29486
+ const result = new ArrayBuffer(text2.length * 2);
29189
29487
  const view = new DataView(result);
29190
- for (let i = 0; i < text.length; i++) {
29191
- view.setUint16(i * 2, text.charCodeAt(i), options.littleEndian ?? false);
29488
+ for (let i = 0; i < text2.length; i++) {
29489
+ view.setUint16(i * 2, text2.charCodeAt(i), options.littleEndian ?? false);
29192
29490
  }
29193
29491
  return new Uint8Array(result);
29194
29492
  }
@@ -29222,18 +29520,18 @@ var require_base64 = __commonJS({
29222
29520
  function nodeBuffer() {
29223
29521
  return globalThis.Buffer;
29224
29522
  }
29225
- function normalize2(text) {
29226
- return text.replace(/[\n\r\t ]/g, "");
29523
+ function normalize2(text2) {
29524
+ return text2.replace(/[\n\r\t ]/g, "");
29227
29525
  }
29228
- function pad(text) {
29229
- const remainder = text.length % 4;
29230
- return remainder ? text + "=".repeat(4 - remainder) : text;
29526
+ function pad(text2) {
29527
+ const remainder = text2.length % 4;
29528
+ return remainder ? text2 + "=".repeat(4 - remainder) : text2;
29231
29529
  }
29232
- function is(text) {
29233
- if (typeof text !== "string") {
29530
+ function is(text2) {
29531
+ if (typeof text2 !== "string") {
29234
29532
  return false;
29235
29533
  }
29236
- const normalized = normalize2(text);
29534
+ const normalized = normalize2(text2);
29237
29535
  return normalized === "" || BASE64_REGEX.test(normalized);
29238
29536
  }
29239
29537
  function encode3(data, _options) {
@@ -29244,8 +29542,8 @@ var require_base64 = __commonJS({
29244
29542
  }
29245
29543
  return btoa((0, binary_js_1.encode)(bytes));
29246
29544
  }
29247
- function decode3(text, _options) {
29248
- const normalized = normalize2(text);
29545
+ function decode3(text2, _options) {
29546
+ const normalized = normalize2(text2);
29249
29547
  if (!is(normalized)) {
29250
29548
  throw new TypeError("Input is not valid Base64 text");
29251
29549
  }
@@ -29271,17 +29569,17 @@ var require_base64url = __commonJS({
29271
29569
  exports.decode = decode3;
29272
29570
  var base64_js_1 = require_base64();
29273
29571
  var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
29274
- function normalize2(text) {
29275
- return text.replace(/[\n\r\t ]/g, "");
29572
+ function normalize2(text2) {
29573
+ return text2.replace(/[\n\r\t ]/g, "");
29276
29574
  }
29277
- function is(text) {
29278
- return typeof text === "string" && BASE64URL_REGEX.test(normalize2(text));
29575
+ function is(text2) {
29576
+ return typeof text2 === "string" && BASE64URL_REGEX.test(normalize2(text2));
29279
29577
  }
29280
29578
  function encode3(data, _options) {
29281
29579
  return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
29282
29580
  }
29283
- function decode3(text, _options) {
29284
- const normalized = normalize2(text);
29581
+ function decode3(text2, _options) {
29582
+ const normalized = normalize2(text2);
29285
29583
  if (!is(normalized)) {
29286
29584
  throw new TypeError("Input is not valid Base64Url text");
29287
29585
  }
@@ -29402,8 +29700,8 @@ var require_ip_converter = __commonJS({
29402
29700
  }
29403
29701
  return ip;
29404
29702
  }
29405
- static parseCIDR(text) {
29406
- const [addr, prefixStr] = text.split("/");
29703
+ static parseCIDR(text2) {
29704
+ const [addr, prefixStr] = text2.split("/");
29407
29705
  const prefix = parseInt(prefixStr, 10);
29408
29706
  if (this.isIPv4(addr)) {
29409
29707
  if (prefix < 0 || prefix > 32) {
@@ -29456,9 +29754,9 @@ var require_ip_converter = __commonJS({
29456
29754
  }
29457
29755
  return this.decodeIP(encoding_1.hex.encode(buf));
29458
29756
  }
29459
- static fromString(text) {
29460
- if (text.includes("/")) {
29461
- const [addr, prefix] = this.parseCIDR(text);
29757
+ static fromString(text2) {
29758
+ if (text2.includes("/")) {
29759
+ const [addr, prefix] = this.parseCIDR(text2);
29462
29760
  const maskBytes = new Uint8Array(addr.length);
29463
29761
  let bitsLeft = prefix;
29464
29762
  for (let i = 0; i < maskBytes.length; i++) {
@@ -29475,7 +29773,7 @@ var require_ip_converter = __commonJS({
29475
29773
  out.set(maskBytes, addr.length);
29476
29774
  return out.buffer;
29477
29775
  }
29478
- const bytes = this.isIPv4(text) ? this.parseIPv4(text) : this.parseIPv6(text);
29776
+ const bytes = this.isIPv4(text2) ? this.parseIPv4(text2) : this.parseIPv6(text2);
29479
29777
  return new Uint8Array(bytes).buffer;
29480
29778
  }
29481
29779
  };
@@ -34286,11 +34584,11 @@ function __metadata2(metadataKey, metadataValue) {
34286
34584
  }
34287
34585
  function __awaiter2(thisArg, _arguments, P, generator) {
34288
34586
  function adopt(value) {
34289
- return value instanceof P ? value : new P(function(resolve8) {
34290
- resolve8(value);
34587
+ return value instanceof P ? value : new P(function(resolve9) {
34588
+ resolve9(value);
34291
34589
  });
34292
34590
  }
34293
- return new (P || (P = Promise))(function(resolve8, reject) {
34591
+ return new (P || (P = Promise))(function(resolve9, reject) {
34294
34592
  function fulfilled(value) {
34295
34593
  try {
34296
34594
  step(generator.next(value));
@@ -34306,7 +34604,7 @@ function __awaiter2(thisArg, _arguments, P, generator) {
34306
34604
  }
34307
34605
  }
34308
34606
  function step(result) {
34309
- result.done ? resolve8(result.value) : adopt(result.value).then(fulfilled, rejected);
34607
+ result.done ? resolve9(result.value) : adopt(result.value).then(fulfilled, rejected);
34310
34608
  }
34311
34609
  step((generator = generator.apply(thisArg, _arguments || [])).next());
34312
34610
  });
@@ -34484,14 +34782,14 @@ function __asyncValues2(o) {
34484
34782
  }, i);
34485
34783
  function verb(n) {
34486
34784
  i[n] = o[n] && function(v) {
34487
- return new Promise(function(resolve8, reject) {
34488
- v = o[n](v), settle(resolve8, reject, v.done, v.value);
34785
+ return new Promise(function(resolve9, reject) {
34786
+ v = o[n](v), settle(resolve9, reject, v.done, v.value);
34489
34787
  });
34490
34788
  };
34491
34789
  }
34492
- function settle(resolve8, reject, d, v) {
34790
+ function settle(resolve9, reject, d, v) {
34493
34791
  Promise.resolve(v).then(function(v2) {
34494
- resolve8({ value: v2, done: d });
34792
+ resolve9({ value: v2, done: d });
34495
34793
  }, reject);
34496
34794
  }
34497
34795
  }
@@ -37155,24 +37453,24 @@ var require_x509_cjs = __commonJS({
37155
37453
  names.register("I", "2.5.4.43");
37156
37454
  names.register("SN", "2.5.4.4");
37157
37455
  names.register("T", "2.5.4.12");
37158
- function replaceUnknownCharacter(text, char) {
37456
+ function replaceUnknownCharacter(text2, char) {
37159
37457
  return `\\${pvtsutils.Convert.ToHex(pvtsutils.Convert.FromUtf8String(char)).toUpperCase()}`;
37160
37458
  }
37161
37459
  function escape2(data) {
37162
37460
  return data.replace(/([,+"\\<>;])/g, "\\$1").replace(/^([ #])/, "\\$1").replace(/([ ]$)/, "\\$1").replace(/([\r\n\t])/, replaceUnknownCharacter);
37163
37461
  }
37164
37462
  var Name = class _Name {
37165
- static isASCII(text) {
37166
- for (let i = 0; i < text.length; i++) {
37167
- const code = text.charCodeAt(i);
37463
+ static isASCII(text2) {
37464
+ for (let i = 0; i < text2.length; i++) {
37465
+ const code = text2.charCodeAt(i);
37168
37466
  if (code > 255) {
37169
37467
  return false;
37170
37468
  }
37171
37469
  }
37172
37470
  return true;
37173
37471
  }
37174
- static isPrintableString(text) {
37175
- return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text);
37472
+ static isPrintableString(text2) {
37473
+ return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text2);
37176
37474
  }
37177
37475
  constructor(data, extraNames = {}) {
37178
37476
  this.extraNames = new NameIdentifier();
@@ -40394,7 +40692,6 @@ var init_stun = __esm({
40394
40692
  // ../../packages/host-core/dist/peer-link/quic-transport.js
40395
40693
  var quic_transport_exports = {};
40396
40694
  __export(quic_transport_exports, {
40397
- QUIC_ENABLED: () => QUIC_ENABLED,
40398
40695
  discoverSrflx: () => discoverSrflx,
40399
40696
  makeQuicSocket: () => makeQuicSocket,
40400
40697
  nudgePunch: () => nudgePunch,
@@ -40404,7 +40701,6 @@ __export(quic_transport_exports, {
40404
40701
  import { webcrypto } from "node:crypto";
40405
40702
  import { createHmac } from "node:crypto";
40406
40703
  import { EventEmitter } from "node:events";
40407
- import { QUICClient, QUICServer, QUICSocket, events as quicEvents } from "@matrixai/quic";
40408
40704
  function serverCrypto() {
40409
40705
  const key2 = webcrypto.getRandomValues(new Uint8Array(32));
40410
40706
  return {
@@ -40487,12 +40783,14 @@ function pinningVerify(expectedFingerprint256) {
40487
40783
  };
40488
40784
  }
40489
40785
  async function makeQuicSocket(localPort) {
40490
- const socket2 = new QUICSocket({});
40786
+ const { QUICSocket: QUICSocketCtor } = await loadQuic();
40787
+ const socket2 = new QUICSocketCtor({});
40491
40788
  await socket2.start({ host: "0.0.0.0", port: localPort, reuseAddr: true });
40492
40789
  return socket2;
40493
40790
  }
40494
40791
  async function quicDialLink(opts) {
40495
- const client = await QUICClient.createQUICClient({
40792
+ const { QUICClient: QUICClientCtor } = await loadQuic();
40793
+ const client = await QUICClientCtor.createQUICClient({
40496
40794
  socket: opts.socket,
40497
40795
  host: opts.host,
40498
40796
  port: opts.port,
@@ -40505,7 +40803,8 @@ async function quicDialLink(opts) {
40505
40803
  return link;
40506
40804
  }
40507
40805
  async function startQuicServerOnSocket(opts) {
40508
- const server = new QUICServer({
40806
+ const { QUICServer: QUICServerCtor, events: quicEvents } = await loadQuic();
40807
+ const server = new QUICServerCtor({
40509
40808
  crypto: serverCrypto(),
40510
40809
  config: { applicationProtos: ALPN, key: opts.identity.key, cert: opts.identity.cert, verifyPeer: false },
40511
40810
  socket: opts.socket
@@ -40523,7 +40822,7 @@ async function startQuicServerOnSocket(opts) {
40523
40822
  function discoverSrflx(socket2, stunHost, stunPort, timeoutMs = 3e3) {
40524
40823
  const dgramSock = socket2.socket;
40525
40824
  const { packet, txId } = encodeBindingRequest();
40526
- return new Promise((resolve8, reject) => {
40825
+ return new Promise((resolve9, reject) => {
40527
40826
  const timer = setTimeout(() => {
40528
40827
  dgramSock.removeListener("message", onMsg);
40529
40828
  reject(new Error("quic: STUN timeout"));
@@ -40533,7 +40832,7 @@ function discoverSrflx(socket2, stunHost, stunPort, timeoutMs = 3e3) {
40533
40832
  if (mapped) {
40534
40833
  clearTimeout(timer);
40535
40834
  dgramSock.removeListener("message", onMsg);
40536
- resolve8(`${mapped.ip}:${mapped.port}`);
40835
+ resolve9(`${mapped.ip}:${mapped.port}`);
40537
40836
  }
40538
40837
  };
40539
40838
  dgramSock.on("message", onMsg);
@@ -40554,14 +40853,15 @@ async function nudgePunch(socket2, peerIp, peerPort, count = 12, intervalMs = 10
40554
40853
  await new Promise((r) => setTimeout(r, intervalMs));
40555
40854
  }
40556
40855
  }
40557
- var QUIC_ENABLED, ALPN, clientCrypto;
40856
+ var ALPN, quicModP, loadQuic, clientCrypto;
40558
40857
  var init_quic_transport = __esm({
40559
40858
  "../../packages/host-core/dist/peer-link/quic-transport.js"() {
40560
40859
  "use strict";
40561
40860
  init_transport();
40562
40861
  init_stun();
40563
- QUIC_ENABLED = process.env.CCB_P2P_QUIC === "1";
40564
40862
  ALPN = ["tesseract-peer"];
40863
+ quicModP = null;
40864
+ loadQuic = () => quicModP ??= import("@matrixai/quic");
40565
40865
  clientCrypto = {
40566
40866
  ops: { randomBytes: async (data) => {
40567
40867
  webcrypto.getRandomValues(new Uint8Array(data));
@@ -41641,17 +41941,17 @@ var require_main = __commonJS({
41641
41941
  });
41642
41942
 
41643
41943
  // src/cli.ts
41644
- import { readFileSync as readFileSync12 } from "node:fs";
41944
+ import { readFileSync as readFileSync13 } from "node:fs";
41645
41945
  import { createHash as createHash5 } from "node:crypto";
41646
41946
  import { spawn as spawn7 } from "node:child_process";
41647
41947
  import { fileURLToPath as fileURLToPath2 } from "node:url";
41648
41948
  import { homedir as homedir14 } from "node:os";
41649
- import { dirname as dirname16, join as join32, resolve as resolve7 } from "node:path";
41949
+ import { dirname as dirname16, join as join33, resolve as resolve8 } from "node:path";
41650
41950
  import { createInterface } from "node:readline/promises";
41651
41951
 
41652
41952
  // ../../packages/host-core/dist/control-link.js
41653
41953
  import { hostname as hostname3, homedir as homedir10 } from "node:os";
41654
- import { join as join25, basename as basename5 } from "node:path";
41954
+ import { join as join26, basename as basename5 } from "node:path";
41655
41955
  import { mkdirSync as mkdirSync9 } from "node:fs";
41656
41956
 
41657
41957
  // ../../node_modules/ws/wrapper.mjs
@@ -41699,7 +41999,7 @@ function isInsideRoot(p, root) {
41699
41999
  }
41700
42000
 
41701
42001
  // ../../packages/host-core/dist/daemon-agent.js
41702
- import { join as join14 } from "node:path";
42002
+ import { join as join15 } from "node:path";
41703
42003
 
41704
42004
  // ../../packages/host-core/dist/agent-backend.js
41705
42005
  async function createClaudeCodeBackend(send2, onBrowserRequest, loadPluginRuntime2) {
@@ -41768,10 +42068,10 @@ var CliAgentBackend = class {
41768
42068
  id;
41769
42069
  capabilities;
41770
42070
  live = /* @__PURE__ */ new Map();
41771
- constructor(adapter, send2, resolve8) {
42071
+ constructor(adapter, send2, resolve9) {
41772
42072
  this.adapter = adapter;
41773
42073
  this.send = send2;
41774
- this.resolve = resolve8;
42074
+ this.resolve = resolve9;
41775
42075
  this.id = adapter.id;
41776
42076
  this.capabilities = adapter.capabilities;
41777
42077
  }
@@ -42039,9 +42339,9 @@ var geminiAdapter = {
42039
42339
  },
42040
42340
  translate(event, raw, emit, ctx) {
42041
42341
  const o = asObj3(event);
42042
- const text = o ? typeof o.response === "string" ? o.response : bestEffortText(o) : typeof event === "string" ? event : raw;
42043
- if (text)
42044
- emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text, messageId: ctx.messageId, kind: "text" });
42342
+ const text2 = o ? typeof o.response === "string" ? o.response : bestEffortText(o) : typeof event === "string" ? event : raw;
42343
+ if (text2)
42344
+ emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text2, messageId: ctx.messageId, kind: "text" });
42045
42345
  const tools = o?.tools;
42046
42346
  if (Array.isArray(tools)) {
42047
42347
  for (const t of tools) {
@@ -42067,25 +42367,25 @@ var openclawAdapter = {
42067
42367
  translate(event, raw, emit, ctx) {
42068
42368
  const o = asObj4(event);
42069
42369
  const result = asObj4(o?.result) ?? o;
42070
- let text = "";
42370
+ let text2 = "";
42071
42371
  const payloads = result?.payloads;
42072
42372
  if (Array.isArray(payloads)) {
42073
- text = payloads.map((p) => {
42373
+ text2 = payloads.map((p) => {
42074
42374
  const t = asObj4(p)?.text;
42075
42375
  return typeof t === "string" ? t : "";
42076
42376
  }).filter(Boolean).join("\n");
42077
42377
  }
42078
- if (!text) {
42378
+ if (!text2) {
42079
42379
  const fav = asObj4(result?.meta)?.finalAssistantVisibleText;
42080
42380
  if (typeof fav === "string")
42081
- text = fav;
42381
+ text2 = fav;
42082
42382
  }
42083
- if (!text)
42084
- text = o ? bestEffortText(result ?? o) : typeof event === "string" ? event : raw;
42085
- if (text)
42086
- emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text, messageId: ctx.messageId, kind: "text" });
42383
+ if (!text2)
42384
+ text2 = o ? bestEffortText(result ?? o) : typeof event === "string" ? event : raw;
42385
+ if (text2)
42386
+ emit({ type: "chat:stream", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, delta: text2, messageId: ctx.messageId, kind: "text" });
42087
42387
  const status2 = typeof o?.status === "string" ? o.status : void 0;
42088
- if (!text && status2 && status2 !== "ok" && status2 !== "accepted") {
42388
+ if (!text2 && status2 && status2 !== "ok" && status2 !== "accepted") {
42089
42389
  const summary = typeof o?.summary === "string" && o.summary ? o.summary : `OpenClaw run ${status2}.`;
42090
42390
  emit({ type: "chat:error", sessionId: ctx.sessionId, clientRequestId: ctx.clientRequestId, error: summary });
42091
42391
  }
@@ -42133,7 +42433,7 @@ init_dist2();
42133
42433
 
42134
42434
  // ../../packages/host-core/dist/plugin-tools.js
42135
42435
  import { existsSync as existsSync3 } from "node:fs";
42136
- import { join as join7 } from "node:path";
42436
+ import { join as join8 } from "node:path";
42137
42437
 
42138
42438
  // ../../packages/plugin-host/dist/discovery.js
42139
42439
  import fs2 from "node:fs";
@@ -42303,8 +42603,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry2) {
42303
42603
  pluginId,
42304
42604
  config: config2,
42305
42605
  secret: (envKey2) => secretResolver(pluginId, envKey2),
42306
- registerTool: (tool2) => {
42307
- const got = typeof tool2 === "function" ? tool2({}) : tool2;
42606
+ registerTool: (tool3) => {
42607
+ const got = typeof tool3 === "function" ? tool3({}) : tool3;
42308
42608
  const arr = Array.isArray(got) ? got : got ? [got] : [];
42309
42609
  for (const t of arr) {
42310
42610
  const c = convertTool(t);
@@ -42373,10 +42673,10 @@ var HostPluginApi = class {
42373
42673
  secret(envKey2) {
42374
42674
  return this.secretResolver(this.pluginId, envKey2);
42375
42675
  }
42376
- registerTool(tool2) {
42676
+ registerTool(tool3) {
42377
42677
  const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
42378
- const name = tool2.name.startsWith(`${prefix}_`) ? tool2.name : `${prefix}_${tool2.name}`;
42379
- this.registry.tools.push({ ...tool2, name });
42678
+ const name = tool3.name.startsWith(`${prefix}_`) ? tool3.name : `${prefix}_${tool3.name}`;
42679
+ this.registry.tools.push({ ...tool3, name });
42380
42680
  }
42381
42681
  registerHook(reg) {
42382
42682
  this.registry.hooks.push(reg);
@@ -42481,7 +42781,7 @@ async function loadPluginRuntime(opts) {
42481
42781
  }
42482
42782
  function buildDaemonPluginLoader(pluginsDir) {
42483
42783
  return async () => {
42484
- const scan = join7(pluginsDir, "node_modules");
42784
+ const scan = join8(pluginsDir, "node_modules");
42485
42785
  if (!existsSync3(scan))
42486
42786
  return { tools: [], hooks: [], engines: [] };
42487
42787
  writeOpenClawShim(pluginsDir);
@@ -42493,18 +42793,18 @@ function buildDaemonPluginLoader(pluginsDir) {
42493
42793
  }
42494
42794
 
42495
42795
  // ../../packages/host-core/dist/credentials.js
42496
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4, renameSync as renameSync3, chmodSync } from "node:fs";
42497
- import { join as join8 } from "node:path";
42796
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync4, renameSync as renameSync3, chmodSync } from "node:fs";
42797
+ import { join as join9 } from "node:path";
42498
42798
  import { homedir as homedir3 } from "node:os";
42499
42799
  function daemonDir() {
42500
- return process.env.CCB_DAEMON_DIR ?? join8(homedir3(), ".tesseract", "daemon");
42800
+ return process.env.CCB_DAEMON_DIR ?? join9(homedir3(), ".tesseract", "daemon");
42501
42801
  }
42502
42802
  function credentialsPath() {
42503
- return join8(daemonDir(), "credentials.json");
42803
+ return join9(daemonDir(), "credentials.json");
42504
42804
  }
42505
42805
  function readCredentials() {
42506
42806
  try {
42507
- const c = JSON.parse(readFileSync3(credentialsPath(), "utf-8"));
42807
+ const c = JSON.parse(readFileSync4(credentialsPath(), "utf-8"));
42508
42808
  if (c.accessToken && c.refreshSecret && c.dtid && c.deviceId && c.userId && c.backendOrigin && c.apiOrigin) {
42509
42809
  return c;
42510
42810
  }
@@ -42808,13 +43108,13 @@ async function closeEnginePage(browserId) {
42808
43108
  }
42809
43109
 
42810
43110
  // ../../packages/host-core/dist/daemon-settings.js
42811
- import { readFileSync as readFileSync6 } from "node:fs";
42812
- import { join as join13 } from "node:path";
43111
+ import { readFileSync as readFileSync7 } from "node:fs";
43112
+ import { join as join14 } from "node:path";
42813
43113
 
42814
43114
  // ../../packages/host-core/dist/runners/resolve.js
42815
- import { readFileSync as readFileSync4, existsSync as existsSync6, statSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
43115
+ import { readFileSync as readFileSync5, existsSync as existsSync6, statSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
42816
43116
  import { homedir as homedir5 } from "node:os";
42817
- import { join as join10 } from "node:path";
43117
+ import { join as join11 } from "node:path";
42818
43118
  import { createHash as createHash2 } from "node:crypto";
42819
43119
 
42820
43120
  // ../../packages/shared/dist/ws-protocol.js
@@ -42837,6 +43137,8 @@ var MIRRORED_AGENT_EVENTS = /* @__PURE__ */ new Set([
42837
43137
  // plan review — co-viewers see the sectioned plan
42838
43138
  "agent:narration",
42839
43139
  // live status strip — co-viewers see "what it's doing now"
43140
+ "agent:preview_ready",
43141
+ // co-viewers (incl. mobile) see the preview the moment it's ready
42840
43142
  "agent:elicitation_complete",
42841
43143
  // M5 — co-viewers clear a resolved url-mode card
42842
43144
  "chat:echoed",
@@ -43286,22 +43588,22 @@ import { createRequire as createRequire2 } from "node:module";
43286
43588
  import { randomUUID as randomUUID4, createHash } from "node:crypto";
43287
43589
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
43288
43590
  import { homedir as homedir4 } from "node:os";
43289
- import { join as join9, dirname as dirname5, sep as sep2 } from "node:path";
43591
+ import { join as join10, dirname as dirname5, sep as sep2 } from "node:path";
43290
43592
  import { request as httpRequest } from "node:http";
43291
43593
  var requireFromHere = createRequire2(import.meta.url);
43292
43594
  var ROUTER_PORT = 8787;
43293
43595
  var BIND_HOST = "127.0.0.1";
43294
43596
  var ROUTER_TOKEN = randomUUID4();
43295
- var routerHomeDir = join9(homedir4(), ".tesseract", "router-home");
43597
+ var routerHomeDir = join10(homedir4(), ".tesseract", "router-home");
43296
43598
  var lastConfigHash = "";
43297
43599
  var running = false;
43298
43600
  var starting = null;
43299
43601
  function configPath() {
43300
- return join9(routerHomeDir, ".claude-code-router", "config.json");
43602
+ return join10(routerHomeDir, ".claude-code-router", "config.json");
43301
43603
  }
43302
43604
  function ccrCliPath() {
43303
43605
  const pkg = requireFromHere.resolve("@musistudio/claude-code-router/package.json");
43304
- const cli = join9(dirname5(pkg), "dist", "cli.js");
43606
+ const cli = join10(dirname5(pkg), "dist", "cli.js");
43305
43607
  return cli.replace(`app.asar${sep2}`, `app.asar.unpacked${sep2}`);
43306
43608
  }
43307
43609
  var cachedNodeExe2;
@@ -43391,39 +43693,39 @@ function buildRouterConfig(d) {
43391
43693
  };
43392
43694
  }
43393
43695
  function writeConfig(cfg2) {
43394
- const dir = join9(routerHomeDir, ".claude-code-router");
43696
+ const dir = join10(routerHomeDir, ".claude-code-router");
43395
43697
  if (!existsSync5(dir))
43396
43698
  mkdirSync3(dir, { recursive: true });
43397
43699
  writeFileSync4(configPath(), JSON.stringify(cfg2, null, 2), { mode: 384 });
43398
43700
  }
43399
43701
  function ccr(args, timeout = 8e3) {
43400
43702
  const { exe, asNode } = nodeExe();
43401
- return new Promise((resolve8) => {
43703
+ return new Promise((resolve9) => {
43402
43704
  execFile2(exe, [ccrCliPath(), ...args], { env: ccrEnv(asNode), timeout }, (err, stdout, stderr) => {
43403
- resolve8({ ok: !err, out: `${stdout || ""}${stderr || ""}` });
43705
+ resolve9({ ok: !err, out: `${stdout || ""}${stderr || ""}` });
43404
43706
  });
43405
43707
  });
43406
43708
  }
43407
43709
  function waitHealthy(timeoutMs = 8e3) {
43408
43710
  const deadline = Date.now() + timeoutMs;
43409
- const ping = () => new Promise((resolve8) => {
43711
+ const ping = () => new Promise((resolve9) => {
43410
43712
  const req = httpRequest({ host: BIND_HOST, port: ROUTER_PORT, path: "/", method: "GET", timeout: 1e3 }, (res) => {
43411
43713
  res.resume();
43412
- resolve8(true);
43714
+ resolve9(true);
43413
43715
  });
43414
- req.on("error", () => resolve8(false));
43716
+ req.on("error", () => resolve9(false));
43415
43717
  req.on("timeout", () => {
43416
43718
  req.destroy();
43417
- resolve8(false);
43719
+ resolve9(false);
43418
43720
  });
43419
43721
  req.end();
43420
43722
  });
43421
- return new Promise((resolve8) => {
43723
+ return new Promise((resolve9) => {
43422
43724
  const tick = async () => {
43423
43725
  if (await ping())
43424
- return resolve8(true);
43726
+ return resolve9(true);
43425
43727
  if (Date.now() > deadline)
43426
- return resolve8(false);
43728
+ return resolve9(false);
43427
43729
  setTimeout(() => void tick(), 400);
43428
43730
  };
43429
43731
  void tick();
@@ -43463,13 +43765,13 @@ function routerEndpointSync(desired) {
43463
43765
  }
43464
43766
 
43465
43767
  // ../../packages/host-core/dist/runners/resolve.js
43466
- var runnerHomeBase = join10(homedir5(), ".tesseract", "runner-home");
43768
+ var runnerHomeBase = join11(homedir5(), ".tesseract", "runner-home");
43467
43769
  function materializeClaudeAuthHome(contents) {
43468
43770
  const id = createHash2("sha256").update(contents).digest("hex").slice(0, 16);
43469
- const home = join10(runnerHomeBase, id);
43771
+ const home = join11(runnerHomeBase, id);
43470
43772
  try {
43471
43773
  mkdirSync4(home, { recursive: true });
43472
- writeFileSync5(join10(home, ".credentials.json"), contents, { mode: 384 });
43774
+ writeFileSync5(join11(home, ".credentials.json"), contents, { mode: 384 });
43473
43775
  } catch {
43474
43776
  }
43475
43777
  return home;
@@ -43519,7 +43821,7 @@ function resolveRunnerEnv(spec) {
43519
43821
  return { ANTHROPIC_BASE_URL: endpoint.baseUrl, ANTHROPIC_AUTH_TOKEN: endpoint.authToken, ANTHROPIC_API_KEY: "" };
43520
43822
  }
43521
43823
  function overridePath() {
43522
- return join10(process.env.CCB_TESSERACT_DIR ?? join10(homedir5(), ".tesseract"), "runners.json");
43824
+ return join11(process.env.CCB_TESSERACT_DIR ?? join11(homedir5(), ".tesseract"), "runners.json");
43523
43825
  }
43524
43826
  var cache2 = null;
43525
43827
  var cachedMtime = -1;
@@ -43533,7 +43835,7 @@ function readOverride() {
43533
43835
  }
43534
43836
  const m = statSync(p).mtimeMs;
43535
43837
  if (cachedMtime !== m) {
43536
- cache2 = JSON.parse(readFileSync4(p, "utf-8"));
43838
+ cache2 = JSON.parse(readFileSync5(p, "utf-8"));
43537
43839
  cachedMtime = m;
43538
43840
  }
43539
43841
  } catch {
@@ -43560,11 +43862,11 @@ function resolveOverrideEngineEnv() {
43560
43862
  }
43561
43863
 
43562
43864
  // ../../packages/host-core/dist/runners/pool.js
43563
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync6, existsSync as existsSync7, statSync as statSync2, mkdirSync as mkdirSync5, chmodSync as chmodSync2, renameSync as renameSync4 } from "node:fs";
43564
- import { join as join11 } from "node:path";
43865
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync6, existsSync as existsSync7, statSync as statSync2, mkdirSync as mkdirSync5, chmodSync as chmodSync2, renameSync as renameSync4 } from "node:fs";
43866
+ import { join as join12 } from "node:path";
43565
43867
  import { randomUUID as randomUUID5 } from "node:crypto";
43566
43868
  function poolPath() {
43567
- return join11(daemonDir(), "runner-configs.json");
43869
+ return join12(daemonDir(), "runner-configs.json");
43568
43870
  }
43569
43871
  var cache3 = null;
43570
43872
  var cachedMtime2 = -1;
@@ -43581,7 +43883,7 @@ function load() {
43581
43883
  }
43582
43884
  const m = statSync2(p).mtimeMs;
43583
43885
  if (cachedMtime2 !== m || !cache3) {
43584
- const parsed = JSON.parse(readFileSync5(p, "utf-8"));
43886
+ const parsed = JSON.parse(readFileSync6(p, "utf-8"));
43585
43887
  cache3 = parsed && parsed.version === 1 && Array.isArray(parsed.configs) ? parsed : emptyStore();
43586
43888
  cachedMtime2 = m;
43587
43889
  }
@@ -43747,7 +44049,7 @@ function setActiveConfig(id) {
43747
44049
  // ../../packages/host-core/dist/daemon-engine-spawn.js
43748
44050
  import { execFileSync } from "node:child_process";
43749
44051
  import { homedir as homedir6 } from "node:os";
43750
- import { join as join12 } from "node:path";
44052
+ import { join as join13 } from "node:path";
43751
44053
  function envKey(id) {
43752
44054
  return id.toUpperCase().replace(/[^A-Z0-9]/g, "_");
43753
44055
  }
@@ -43758,10 +44060,10 @@ function augmentedPath() {
43758
44060
  "/opt/homebrew/bin",
43759
44061
  "/usr/bin",
43760
44062
  "/bin",
43761
- join12(homedir6(), ".local", "bin"),
43762
- join12(homedir6(), "bin"),
43763
- join12(homedir6(), ".bun", "bin"),
43764
- join12(homedir6(), ".npm-global", "bin")
44063
+ join13(homedir6(), ".local", "bin"),
44064
+ join13(homedir6(), "bin"),
44065
+ join13(homedir6(), ".bun", "bin"),
44066
+ join13(homedir6(), ".npm-global", "bin")
43765
44067
  ];
43766
44068
  const seen = /* @__PURE__ */ new Set();
43767
44069
  const parts = [];
@@ -43774,9 +44076,9 @@ function augmentedPath() {
43774
44076
  return parts.join(sep7);
43775
44077
  }
43776
44078
  function which(bin, path5) {
43777
- const tool2 = process.platform === "win32" ? "where" : "which";
44079
+ const tool3 = process.platform === "win32" ? "where" : "which";
43778
44080
  try {
43779
- const out = execFileSync(tool2, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
44081
+ const out = execFileSync(tool3, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
43780
44082
  return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
43781
44083
  } catch {
43782
44084
  return void 0;
@@ -43818,14 +44120,14 @@ function readDaemonEngineSpawn(engineId) {
43818
44120
  return readDaemonAgentSettings().engineSpawn?.[engineId] ?? resolveDaemonEngineSpawn(engineId);
43819
44121
  }
43820
44122
  function agentSettingsPath() {
43821
- return join13(daemonDir(), "agent-settings.json");
44123
+ return join14(daemonDir(), "agent-settings.json");
43822
44124
  }
43823
44125
  function readDaemonSchedulingEnabled() {
43824
44126
  return readDaemonAgentSettings().schedulingEnabled === true;
43825
44127
  }
43826
44128
  function readDaemonAgentSettings() {
43827
44129
  try {
43828
- return JSON.parse(readFileSync6(agentSettingsPath(), "utf-8"));
44130
+ return JSON.parse(readFileSync7(agentSettingsPath(), "utf-8"));
43829
44131
  } catch {
43830
44132
  const snap = {};
43831
44133
  const raw = process.env.CCB_MCP_SERVERS;
@@ -43932,7 +44234,7 @@ function buildSharedBackend(engineId) {
43932
44234
  },
43933
44235
  resolver,
43934
44236
  // Daemon plugins (review #3): operator-controlled <daemonDir>/plugins, env-var secrets.
43935
- buildDaemonPluginLoader(join14(daemonDir(), "plugins"))
44237
+ buildDaemonPluginLoader(join15(daemonDir(), "plugins"))
43936
44238
  ).then((b) => {
43937
44239
  if (token !== buildToken)
43938
44240
  return b;
@@ -43983,16 +44285,16 @@ function refreshDaemonScheduling(b) {
43983
44285
  }
43984
44286
  b.configureScheduling({
43985
44287
  enabled,
43986
- file: join14(dir, "scheduled_tasks.json"),
44288
+ file: join15(dir, "scheduled_tasks.json"),
43987
44289
  // projectDir omitted ⇒ fires track the daemon's currently-open project (setConfig).
43988
44290
  isOwner: schedulingLock ? () => schedulingLock.isOwner() : void 0
43989
44291
  });
43990
44292
  }
43991
44293
 
43992
44294
  // ../../packages/host-core/dist/fs-remote.js
43993
- import { readdir as readdir2, readFile as readFile5, writeFile as writeFile3, mkdir as mkdir3, cp, rm, rename as renameAsync, stat as stat2 } from "node:fs/promises";
44295
+ import { readdir as readdir2, readFile as readFile6, writeFile as writeFile4, mkdir as mkdir4, cp, rm, rename as renameAsync, stat as stat2 } from "node:fs/promises";
43994
44296
  import { openSync as openSync2, readSync, closeSync as closeSync2, statSync as statSync3, existsSync as existsSync8, watch } from "node:fs";
43995
- import { basename as basename2, dirname as dirname6, join as join15, relative as relative2, resolve as resolve3, sep as sep3, isAbsolute as isAbsolute2 } from "node:path";
44297
+ import { basename as basename2, dirname as dirname6, join as join16, relative as relative3, resolve as resolve4, sep as sep3, isAbsolute as isAbsolute3 } from "node:path";
43996
44298
  import { execFile as execFile3 } from "node:child_process";
43997
44299
  import { promisify as promisify2 } from "node:util";
43998
44300
  var execFileAsync = promisify2(execFile3);
@@ -44039,12 +44341,12 @@ async function listAllFilesUnder(dir) {
44039
44341
  return;
44040
44342
  if (ent.name === ".DS_Store")
44041
44343
  continue;
44042
- const full = join15(d, ent.name);
44344
+ const full = join16(d, ent.name);
44043
44345
  if (ent.isDirectory()) {
44044
44346
  if (!LISTALL_SKIP_DIRS.has(ent.name))
44045
44347
  await walk(full);
44046
44348
  } else if (ent.isFile())
44047
- out.push(relative2(dir, full).split(sep3).join("/"));
44349
+ out.push(relative3(dir, full).split(sep3).join("/"));
44048
44350
  }
44049
44351
  };
44050
44352
  await walk(dir);
@@ -44155,18 +44457,18 @@ function resolveParent(raw, root) {
44155
44457
  if (raw === "" || raw === "~")
44156
44458
  return root;
44157
44459
  if (raw.startsWith("~/"))
44158
- return join15(root, raw.slice(2));
44159
- return isAbsolute2(raw) ? raw : join15(root, raw);
44460
+ return join16(root, raw.slice(2));
44461
+ return isAbsolute3(raw) ? raw : join16(root, raw);
44160
44462
  }
44161
44463
  function resolveUniqueName(dir, name) {
44162
- const direct = join15(dir, name);
44464
+ const direct = join16(dir, name);
44163
44465
  if (!existsSync8(direct))
44164
44466
  return direct;
44165
44467
  const dot = name.lastIndexOf(".");
44166
44468
  const base = dot > 0 ? name.slice(0, dot) : name;
44167
44469
  const ext = dot > 0 ? name.slice(dot) : "";
44168
44470
  for (let i = 2; i < 1e4; i++) {
44169
- const candidate = join15(dir, `${base} ${i}${ext}`);
44471
+ const candidate = join16(dir, `${base} ${i}${ext}`);
44170
44472
  if (!existsSync8(candidate))
44171
44473
  return candidate;
44172
44474
  }
@@ -44183,7 +44485,7 @@ async function readRemoteBytes(root, path5) {
44183
44485
  return { error: "Not a file" };
44184
44486
  if (s.size > REMOTE_READ_CAP)
44185
44487
  return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
44186
- return { bytes: await readFile5(path5), size: s.size };
44488
+ return { bytes: await readFile6(path5), size: s.size };
44187
44489
  } catch (err) {
44188
44490
  return { error: String(err.message) };
44189
44491
  }
@@ -44198,7 +44500,7 @@ async function runRemoteFsOp(root, op, args) {
44198
44500
  try {
44199
44501
  const entries = (await readdir2(dir, { withFileTypes: true })).filter((e) => e.name !== ".DS_Store");
44200
44502
  const ignored = await gitIgnoredNames(dir, entries.map((e) => e.name));
44201
- return entries.map((e) => ({ name: e.name, path: join15(dir, e.name), isDir: e.isDirectory(), ignored: ignored.has(e.name) })).sort((x, y) => x.isDir === y.isDir ? x.name.localeCompare(y.name) : x.isDir ? -1 : 1);
44503
+ return entries.map((e) => ({ name: e.name, path: join16(dir, e.name), isDir: e.isDirectory(), ignored: ignored.has(e.name) })).sort((x, y) => x.isDir === y.isDir ? x.name.localeCompare(y.name) : x.isDir ? -1 : 1);
44202
44504
  } catch {
44203
44505
  return [];
44204
44506
  }
@@ -44224,7 +44526,7 @@ async function runRemoteFsOp(root, op, args) {
44224
44526
  const s = statSync3(p);
44225
44527
  if (s.size > TEXT_SIZE_LIMIT)
44226
44528
  return { error: "File too large for text view." };
44227
- return { content: await readFile5(p, "utf-8") };
44529
+ return { content: await readFile6(p, "utf-8") };
44228
44530
  } catch (err) {
44229
44531
  return { error: String(err.message) };
44230
44532
  }
@@ -44235,8 +44537,8 @@ async function runRemoteFsOp(root, op, args) {
44235
44537
  if (!isInsideRoot(p, root))
44236
44538
  return OUTSIDE("write");
44237
44539
  try {
44238
- await mkdir3(dirname6(p), { recursive: true });
44239
- await writeFile3(p, content, "utf-8");
44540
+ await mkdir4(dirname6(p), { recursive: true });
44541
+ await writeFile4(p, content, "utf-8");
44240
44542
  return { ok: true };
44241
44543
  } catch (err) {
44242
44544
  return { ok: false, error: String(err.message) };
@@ -44248,8 +44550,8 @@ async function runRemoteFsOp(root, op, args) {
44248
44550
  if (!isInsideRoot(p, root))
44249
44551
  return OUTSIDE("write");
44250
44552
  try {
44251
- await mkdir3(dirname6(p), { recursive: true });
44252
- await writeFile3(p, Buffer.from(base643, "base64"));
44553
+ await mkdir4(dirname6(p), { recursive: true });
44554
+ await writeFile4(p, Buffer.from(base643, "base64"));
44253
44555
  return { ok: true };
44254
44556
  } catch (err) {
44255
44557
  return { ok: false, error: String(err.message) };
@@ -44301,7 +44603,7 @@ async function runRemoteFsOp(root, op, args) {
44301
44603
  const s = statSync3(p);
44302
44604
  if (s.size > REMOTE_READ_CAP)
44303
44605
  return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
44304
- return { base64: (await readFile5(p)).toString("base64"), size: s.size };
44606
+ return { base64: (await readFile6(p)).toString("base64"), size: s.size };
44305
44607
  } catch (err) {
44306
44608
  return { error: String(err.message) };
44307
44609
  }
@@ -44311,13 +44613,13 @@ async function runRemoteFsOp(root, op, args) {
44311
44613
  const name = String(a[1] ?? "").trim();
44312
44614
  if (!validName(name))
44313
44615
  return { ok: false, error: "Invalid project name." };
44314
- const target = join15(parent, name);
44616
+ const target = join16(parent, name);
44315
44617
  if (!isInsideRoot(target, root))
44316
44618
  return { ok: false, error: "Refusing to create a project outside the shared root." };
44317
44619
  if (existsSync8(target))
44318
44620
  return { ok: false, error: `A folder named "${name}" already exists.` };
44319
44621
  try {
44320
- await mkdir3(target, { recursive: true });
44622
+ await mkdir4(target, { recursive: true });
44321
44623
  return { ok: true, path: target };
44322
44624
  } catch (err) {
44323
44625
  return { ok: false, error: String(err.message) };
@@ -44331,14 +44633,14 @@ async function runRemoteFsOp(root, op, args) {
44331
44633
  return { ok: false, error: "Invalid name." };
44332
44634
  if (!isInsideRoot(parent, root))
44333
44635
  return OUTSIDE("create");
44334
- const target = join15(parent, name);
44636
+ const target = join16(parent, name);
44335
44637
  if (existsSync8(target))
44336
44638
  return { ok: false, error: `"${name}" already exists.` };
44337
44639
  try {
44338
44640
  if (op === "createFile")
44339
- await writeFile3(target, "", "utf-8");
44641
+ await writeFile4(target, "", "utf-8");
44340
44642
  else
44341
- await mkdir3(target);
44643
+ await mkdir4(target);
44342
44644
  return { ok: true, path: target };
44343
44645
  } catch (err) {
44344
44646
  return { ok: false, error: String(err.message) };
@@ -44351,7 +44653,7 @@ async function runRemoteFsOp(root, op, args) {
44351
44653
  return { ok: false, error: "Invalid name." };
44352
44654
  if (!isInsideRoot(oldPath, root))
44353
44655
  return OUTSIDE("rename");
44354
- const newPath = join15(dirname6(oldPath), newName);
44656
+ const newPath = join16(dirname6(oldPath), newName);
44355
44657
  if (existsSync8(newPath))
44356
44658
  return { ok: false, error: `A file named "${newName}" already exists.` };
44357
44659
  try {
@@ -44367,7 +44669,7 @@ async function runRemoteFsOp(root, op, args) {
44367
44669
  return { ok: false, error: "Bad request" };
44368
44670
  if (!isInsideRoot(p, root))
44369
44671
  return OUTSIDE("delete");
44370
- if (resolve3(p) === resolve3(root))
44672
+ if (resolve4(p) === resolve4(root))
44371
44673
  return { ok: false, error: "Refusing to delete the shared root." };
44372
44674
  try {
44373
44675
  await rm(p, { recursive: true, force: false });
@@ -44413,7 +44715,7 @@ async function runRemoteFsOp(root, op, args) {
44413
44715
  const s = await stat2(p);
44414
44716
  if (!s.isDirectory())
44415
44717
  return { error: "not_dir" };
44416
- return { root: resolve3(p), name: basename2(p) };
44718
+ return { root: resolve4(p), name: basename2(p) };
44417
44719
  } catch {
44418
44720
  return { error: "not_found" };
44419
44721
  }
@@ -44421,14 +44723,14 @@ async function runRemoteFsOp(root, op, args) {
44421
44723
  case "currentRoot":
44422
44724
  return { root, name: basename2(root) };
44423
44725
  case "homeDir":
44424
- return { root: resolve3(root), name: basename2(root) };
44726
+ return { root: resolve4(root), name: basename2(root) };
44425
44727
  default:
44426
44728
  return { error: `Unsupported fs op: ${op}` };
44427
44729
  }
44428
44730
  }
44429
44731
  var remoteWatches = /* @__PURE__ */ new Map();
44430
44732
  function watchRemoteRoot(root, key2, onChange) {
44431
- const resolved = resolve3(root);
44733
+ const resolved = resolve4(root);
44432
44734
  const existing = remoteWatches.get(resolved);
44433
44735
  if (existing) {
44434
44736
  existing.listeners.set(key2, onChange);
@@ -44443,7 +44745,7 @@ function watchRemoteRoot(root, key2, onChange) {
44443
44745
  const rel = String(filename);
44444
44746
  if (rel.split(sep3).some((seg) => IGNORED.has(seg)))
44445
44747
  return;
44446
- pending.add(join15(resolved, rel));
44748
+ pending.add(join16(resolved, rel));
44447
44749
  if (timer)
44448
44750
  clearTimeout(timer);
44449
44751
  timer = setTimeout(() => {
@@ -44688,15 +44990,15 @@ function dynamicMetrics() {
44688
44990
  }
44689
44991
 
44690
44992
  // ../../packages/host-core/dist/fs-transfer.js
44691
- import { readdir as readdir3, lstat, mkdir as mkdir4, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
44993
+ import { readdir as readdir3, lstat, mkdir as mkdir5, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
44692
44994
  import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, existsSync as existsSync9, createWriteStream } from "node:fs";
44693
- import { dirname as dirname7, join as join17, relative as relative4, sep as sep5 } from "node:path";
44995
+ import { dirname as dirname7, join as join18, relative as relative5, sep as sep5 } from "node:path";
44694
44996
 
44695
44997
  // ../../packages/host-core/dist/active-link/paths.js
44696
44998
  import { homedir as homedir7 } from "node:os";
44697
- import { join as join16, relative as relative3, sep as sep4 } from "node:path";
44999
+ import { join as join17, relative as relative4, sep as sep4 } from "node:path";
44698
45000
  function activeLinkEnabled() {
44699
- return process.env.CCB_ACTIVE_LINK === "1";
45001
+ return process.env.CCB_ACTIVE_LINK !== "0";
44700
45002
  }
44701
45003
  var HEAVY_DIRS = /* @__PURE__ */ new Set([
44702
45004
  ".git",
@@ -44717,10 +45019,10 @@ function isExcludedName(name) {
44717
45019
  return HEAVY_DIRS.has(name) || ALWAYS_SKIP.has(name);
44718
45020
  }
44719
45021
  function toPosixRel(root, abs) {
44720
- return relative3(root, abs).split(sep4).join("/");
45022
+ return relative4(root, abs).split(sep4).join("/");
44721
45023
  }
44722
45024
  function fromPosixRel(root, rel) {
44723
- return join16(root, rel.split("/").join(sep4));
45025
+ return join17(root, rel.split("/").join(sep4));
44724
45026
  }
44725
45027
  function isExcludedAbs(abs, root) {
44726
45028
  const rel = toPosixRel(root, abs);
@@ -44729,10 +45031,10 @@ function isExcludedAbs(abs, root) {
44729
45031
  return rel.split("/").some(isExcludedName);
44730
45032
  }
44731
45033
  function activeLinkRoot() {
44732
- return process.env.CCB_ACTIVE_LINK_DIR ?? join16(homedir7(), ".tesseract", "active-link");
45034
+ return process.env.CCB_ACTIVE_LINK_DIR ?? join17(homedir7(), ".tesseract", "active-link");
44733
45035
  }
44734
45036
  function linkStateDir(linkId) {
44735
- return join16(activeLinkRoot(), linkId);
45037
+ return join17(activeLinkRoot(), linkId);
44736
45038
  }
44737
45039
 
44738
45040
  // ../../packages/host-core/dist/fs-transfer.js
@@ -44745,9 +45047,9 @@ function clearTimer(t) {
44745
45047
  return null;
44746
45048
  }
44747
45049
  function uniqueDir(parent, name) {
44748
- let candidate = join17(parent, name);
45050
+ let candidate = join18(parent, name);
44749
45051
  for (let i = 2; existsSync9(candidate) && i < 1e4; i++)
44750
- candidate = join17(parent, `${name} ${i}`);
45052
+ candidate = join18(parent, `${name} ${i}`);
44751
45053
  return candidate;
44752
45054
  }
44753
45055
  var producers = /* @__PURE__ */ new Map();
@@ -44790,8 +45092,8 @@ async function buildManifest(root, followSymlinks, excludeHeavy) {
44790
45092
  continue;
44791
45093
  if (e.isDirectory() && excludeHeavy && HEAVY_DIRS.has(e.name))
44792
45094
  continue;
44793
- const abs = join17(dir, e.name);
44794
- const rel = relative4(root, abs).split(sep5).join("/");
45095
+ const abs = join18(dir, e.name);
45096
+ const rel = relative5(root, abs).split(sep5).join("/");
44795
45097
  const st = await lstat(abs).catch(() => null);
44796
45098
  if (!st)
44797
45099
  continue;
@@ -44851,17 +45153,17 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
44851
45153
  totalBytes: manifest.totalBytes,
44852
45154
  dirs: manifest.dirs
44853
45155
  }, { hostId: toHost });
44854
- const waitWindow = () => state.sentBytes - state.ackedBytes < MAX_INFLIGHT ? Promise.resolve() : new Promise((resolve8) => {
44855
- state.wake = resolve8;
45156
+ const waitWindow = () => state.sentBytes - state.ackedBytes < MAX_INFLIGHT ? Promise.resolve() : new Promise((resolve9) => {
45157
+ state.wake = resolve9;
44856
45158
  });
44857
45159
  for (let fileIx = 0; fileIx < manifest.files.length && !state.cancelled; fileIx++) {
44858
45160
  const f = manifest.files[fileIx];
44859
45161
  if (f.kind === "symlink") {
44860
- const target = await readlink(join17(srcPath, f.rel.split("/").join(sep5))).catch(() => "");
45162
+ const target = await readlink(join18(srcPath, f.rel.split("/").join(sep5))).catch(() => "");
44861
45163
  send2({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "symlink", offset: 0, base64: Buffer.from(target, "utf-8").toString("base64"), eof: true }, { hostId: toHost });
44862
45164
  continue;
44863
45165
  }
44864
- const abs = join17(srcPath, f.rel.split("/").join(sep5));
45166
+ const abs = join18(srcPath, f.rel.split("/").join(sep5));
44865
45167
  let fd = null;
44866
45168
  try {
44867
45169
  fd = openSync3(abs, "r");
@@ -44973,7 +45275,7 @@ async function beginInboundTransfer(msg, hostRoot, send2) {
44973
45275
  failNoState("Invalid destination name.");
44974
45276
  return;
44975
45277
  }
44976
- let destRoot = join17(parent, msg.destName);
45278
+ let destRoot = join18(parent, msg.destName);
44977
45279
  let createdRoot = false;
44978
45280
  if (existsSync9(destRoot)) {
44979
45281
  if (msg.onCollision === "abort") {
@@ -45013,11 +45315,11 @@ async function beginInboundTransfer(msg, hostRoot, send2) {
45013
45315
  return;
45014
45316
  }
45015
45317
  try {
45016
- await mkdir4(destRoot, { recursive: true });
45318
+ await mkdir5(destRoot, { recursive: true });
45017
45319
  for (const d of msg.dirs) {
45018
- const abs = join17(destRoot, d.rel.split("/").join(sep5));
45320
+ const abs = join18(destRoot, d.rel.split("/").join(sep5));
45019
45321
  if (isInsideRoot(abs, destRoot))
45020
- await mkdir4(abs, { recursive: true }).catch(() => {
45322
+ await mkdir5(abs, { recursive: true }).catch(() => {
45021
45323
  });
45022
45324
  }
45023
45325
  } catch (e) {
@@ -45029,7 +45331,7 @@ async function writeInboundChunk(msg, send2) {
45029
45331
  if (!s || s.cancelled)
45030
45332
  return;
45031
45333
  armConsumerWatchdog(msg.transferId, send2);
45032
- const abs = join17(s.destRoot, msg.rel.split("/").join(sep5));
45334
+ const abs = join18(s.destRoot, msg.rel.split("/").join(sep5));
45033
45335
  if (msg.rel.includes("..") || !isInsideRoot(abs, s.destRoot)) {
45034
45336
  failConsumer(msg.transferId, `Refusing a path outside the destination: ${msg.rel}`, send2);
45035
45337
  return;
@@ -45037,9 +45339,9 @@ async function writeInboundChunk(msg, send2) {
45037
45339
  try {
45038
45340
  if (msg.kind === "symlink") {
45039
45341
  const target = Buffer.from(msg.base64, "base64").toString("utf-8");
45040
- const resolved = join17(dirname7(abs), target);
45342
+ const resolved = join18(dirname7(abs), target);
45041
45343
  if (isInsideRoot(resolved, s.destRoot)) {
45042
- await mkdir4(dirname7(abs), { recursive: true }).catch(() => {
45344
+ await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
45043
45345
  });
45044
45346
  await symlink(target, abs).catch(() => {
45045
45347
  });
@@ -45052,14 +45354,14 @@ async function writeInboundChunk(msg, send2) {
45052
45354
  if (s.curIx !== msg.fileIx || !s.curStream) {
45053
45355
  if (s.curStream)
45054
45356
  await new Promise((r) => s.curStream.end(r));
45055
- await mkdir4(dirname7(abs), { recursive: true }).catch(() => {
45357
+ await mkdir5(dirname7(abs), { recursive: true }).catch(() => {
45056
45358
  });
45057
45359
  s.curStream = createWriteStream(abs);
45058
45360
  s.curIx = msg.fileIx;
45059
45361
  }
45060
45362
  if (msg.base64) {
45061
45363
  const buf = Buffer.from(msg.base64, "base64");
45062
- await new Promise((resolve8, reject) => s.curStream.write(buf, (err) => err ? reject(err) : resolve8()));
45364
+ await new Promise((resolve9, reject) => s.curStream.write(buf, (err) => err ? reject(err) : resolve9()));
45063
45365
  s.bytesDone += buf.length;
45064
45366
  }
45065
45367
  if (msg.eof) {
@@ -45113,7 +45415,7 @@ function cancelTransfersForClient(clientId, send2) {
45113
45415
 
45114
45416
  // ../../packages/host-core/dist/peer-link/index.js
45115
45417
  import { homedir as homedir8 } from "node:os";
45116
- import { join as join18 } from "node:path";
45418
+ import { join as join19 } from "node:path";
45117
45419
 
45118
45420
  // ../../packages/host-core/dist/peer-link/manager.js
45119
45421
  import { randomBytes as randomBytes2 } from "node:crypto";
@@ -45122,15 +45424,15 @@ import { randomBytes as randomBytes2 } from "node:crypto";
45122
45424
  var import_selfsigned = __toESM(require_selfsigned(), 1);
45123
45425
  import tls from "node:tls";
45124
45426
  import { X509Certificate } from "node:crypto";
45125
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync7, existsSync as existsSync10, mkdirSync as mkdirSync6 } from "node:fs";
45427
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync10, mkdirSync as mkdirSync6 } from "node:fs";
45126
45428
  import { dirname as dirname8 } from "node:path";
45127
45429
  function fingerprintOf(certPem) {
45128
45430
  return new X509Certificate(certPem).fingerprint256;
45129
45431
  }
45130
45432
  async function loadOrCreateIdentity(certPath, keyPath) {
45131
45433
  if (existsSync10(certPath) && existsSync10(keyPath)) {
45132
- const cert = readFileSync7(certPath, "utf8");
45133
- const key2 = readFileSync7(keyPath, "utf8");
45434
+ const cert = readFileSync8(certPath, "utf8");
45435
+ const key2 = readFileSync8(keyPath, "utf8");
45134
45436
  return { cert, key: key2, fingerprint256: fingerprintOf(cert) };
45135
45437
  }
45136
45438
  const tenYears = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1e3);
@@ -45147,7 +45449,7 @@ async function loadOrCreateIdentity(certPath, keyPath) {
45147
45449
  return { cert: pems.cert, key: pems.private, fingerprint256: fingerprintOf(pems.cert) };
45148
45450
  }
45149
45451
  function pinnedConnect(opts) {
45150
- return new Promise((resolve8, reject) => {
45452
+ return new Promise((resolve9, reject) => {
45151
45453
  let settled = false;
45152
45454
  const done = (err, sock) => {
45153
45455
  if (settled)
@@ -45160,7 +45462,7 @@ function pinnedConnect(opts) {
45160
45462
  }
45161
45463
  reject(err);
45162
45464
  } else
45163
- resolve8(sock);
45465
+ resolve9(sock);
45164
45466
  };
45165
45467
  const socket2 = tls.connect({
45166
45468
  host: opts.host,
@@ -45276,6 +45578,11 @@ var PeerLinkManager = class {
45276
45578
  quicSrflx = null;
45277
45579
  quicInitP = null;
45278
45580
  quicKeepalive = null;
45581
+ /** Set once if the QUIC native dep (@matrixai/quic) can't be loaded on this host —
45582
+ * e.g. the desktop app doesn't ship it, or an arch with no prebuilt binding. The
45583
+ * QUIC tier then no-ops permanently and the TCP tiers carry every link (fail-closed,
45584
+ * exactly what the lazy-load design in quic-transport.ts promises). */
45585
+ quicUnavailable = false;
45279
45586
  constructor(certPath, keyPath) {
45280
45587
  this.certPath = certPath;
45281
45588
  this.keyPath = keyPath;
@@ -45322,22 +45629,28 @@ var PeerLinkManager = class {
45322
45629
  return;
45323
45630
  const stunPort = Number(process.env.CCB_STUN_PORT ?? 3478);
45324
45631
  const identity = await this.identity();
45325
- const q = await Promise.resolve().then(() => (init_quic_transport(), quic_transport_exports));
45326
- const socket2 = await q.makeQuicSocket(this.udpPort);
45327
- this.quicSocket = socket2;
45328
- await q.startQuicServerOnSocket({ socket: socket2, identity, onStream: (bs) => this.acceptInbound(bs, "punch") });
45329
- const refresh = async () => {
45330
- try {
45331
- const s = await q.discoverSrflx(socket2, stunHost, stunPort);
45332
- const i = s.lastIndexOf(":");
45333
- this.quicSrflx = { type: "srflx", ip: s.slice(0, i), port: Number(s.slice(i + 1)), proto: "udp", priority: 40 };
45334
- } catch {
45335
- }
45336
- };
45337
- await refresh();
45338
- this.quicKeepalive = setInterval(() => {
45339
- void refresh();
45340
- }, 2e4);
45632
+ try {
45633
+ const q = await Promise.resolve().then(() => (init_quic_transport(), quic_transport_exports));
45634
+ const socket2 = await q.makeQuicSocket(this.udpPort);
45635
+ this.quicSocket = socket2;
45636
+ await q.startQuicServerOnSocket({ socket: socket2, identity, onStream: (bs) => this.acceptInbound(bs, "punch") });
45637
+ const refresh = async () => {
45638
+ try {
45639
+ const s = await q.discoverSrflx(socket2, stunHost, stunPort);
45640
+ const i = s.lastIndexOf(":");
45641
+ this.quicSrflx = { type: "srflx", ip: s.slice(0, i), port: Number(s.slice(i + 1)), proto: "udp", priority: 40 };
45642
+ } catch {
45643
+ }
45644
+ };
45645
+ await refresh();
45646
+ this.quicKeepalive = setInterval(() => {
45647
+ void refresh();
45648
+ }, 2e4);
45649
+ } catch (e) {
45650
+ this.quicUnavailable = true;
45651
+ this.quicSocket = null;
45652
+ console.warn(`[peer-link] QUIC tier unavailable \u2014 using TCP tiers only: ${e?.message ?? e}`);
45653
+ }
45341
45654
  }
45342
45655
  async nudgeQuic(peer) {
45343
45656
  if (!this.quicSocket)
@@ -45367,7 +45680,7 @@ var PeerLinkManager = class {
45367
45680
  if (this.server)
45368
45681
  return this.listenPort;
45369
45682
  this.server = createListener(identity, LISTEN_PORT, (sock) => this.acceptInbound(sock, "reverse"));
45370
- await new Promise((resolve8) => this.server.once("listening", () => resolve8()));
45683
+ await new Promise((resolve9) => this.server.once("listening", () => resolve9()));
45371
45684
  const addr = this.server.address();
45372
45685
  if (addr && typeof addr === "object")
45373
45686
  this.listenPort = addr.port;
@@ -45434,12 +45747,12 @@ var PeerLinkManager = class {
45434
45747
  * peer to dial in. Resolves with the authed link, or rejects on timeout. */
45435
45748
  awaitInbound(token, peerHostId) {
45436
45749
  const h = toHex(token);
45437
- return new Promise((resolve8, reject) => {
45750
+ return new Promise((resolve9, reject) => {
45438
45751
  const timer = setTimeout(() => {
45439
45752
  this.pendingInbound.delete(h);
45440
45753
  reject(new Error("peer-link: inbound dial-in timeout"));
45441
45754
  }, INBOUND_WAIT_MS);
45442
- this.pendingInbound.set(h, { peerHostId, resolve: resolve8, reject, timer });
45755
+ this.pendingInbound.set(h, { peerHostId, resolve: resolve9, reject, timer });
45443
45756
  });
45444
45757
  }
45445
45758
  /** Obey one `p2p:go` (initiator OR unsolicited responder): dial the peer's
@@ -45453,7 +45766,7 @@ var PeerLinkManager = class {
45453
45766
  async handleGo(msg) {
45454
45767
  const token = Buffer.from(msg.token, "hex");
45455
45768
  const udp = msg.peerCandidates.filter((c) => c.proto === "udp");
45456
- const quicOn = this.quicEnabled() && udp.length > 0;
45769
+ const quicOn = this.quicEnabled() && udp.length > 0 && !this.quicUnavailable;
45457
45770
  if (msg.role === "listen") {
45458
45771
  if (quicOn) {
45459
45772
  await this.initQuic();
@@ -45466,7 +45779,7 @@ var PeerLinkManager = class {
45466
45779
  ];
45467
45780
  if (quicOn)
45468
45781
  attempts.push(this.quicDial(msg, token, udp[0]));
45469
- return new Promise((resolve8, reject) => {
45782
+ return new Promise((resolve9, reject) => {
45470
45783
  let done = false, failed = 0;
45471
45784
  const errs = [];
45472
45785
  for (const p of attempts) {
@@ -45480,7 +45793,7 @@ var PeerLinkManager = class {
45480
45793
  }
45481
45794
  done = true;
45482
45795
  this.cache(msg.peerHostId, l);
45483
- resolve8(l);
45796
+ resolve9(l);
45484
45797
  }, (e) => {
45485
45798
  errs.push(e);
45486
45799
  if (++failed === attempts.length && !done)
@@ -45531,7 +45844,7 @@ var PeerLinkManager = class {
45531
45844
  const myFingerprint = (await this.identity()).fingerprint256;
45532
45845
  const rid = randomBytes2(8).toString("hex");
45533
45846
  const myCandidates = gatherTcpCandidates(this.listenPort, this.observedIp);
45534
- return new Promise((resolve8, reject) => {
45847
+ return new Promise((resolve9, reject) => {
45535
45848
  let settled = false;
45536
45849
  const overall = setTimeout(() => finish(new Error("peer-link: rendezvous timeout")), RENDEZVOUS_TIMEOUT_MS);
45537
45850
  const finish = (err, link) => {
@@ -45543,7 +45856,7 @@ var PeerLinkManager = class {
45543
45856
  if (err || !link)
45544
45857
  reject(err ?? new Error("peer-link: no link"));
45545
45858
  else
45546
- resolve8(link);
45859
+ resolve9(link);
45547
45860
  };
45548
45861
  this.pendingOpens.set(rid, {
45549
45862
  // Our attempt failed: tell the broker (it forwards `failed` to the peer +
@@ -45613,8 +45926,8 @@ var PeerLinkManager = class {
45613
45926
  // ../../packages/host-core/dist/peer-link/index.js
45614
45927
  var P2P_ENABLED = process.env.CCB_P2P !== "0";
45615
45928
  function identityPaths() {
45616
- const dir = process.env.CCB_P2P_DIR ?? join18(homedir8(), ".tesseract");
45617
- return { certPath: join18(dir, "peer-cert.pem"), keyPath: join18(dir, "peer-key.pem") };
45929
+ const dir = process.env.CCB_P2P_DIR ?? join19(homedir8(), ".tesseract");
45930
+ return { certPath: join19(dir, "peer-cert.pem"), keyPath: join19(dir, "peer-key.pem") };
45618
45931
  }
45619
45932
  var manager = null;
45620
45933
  function peerLinkManager() {
@@ -45629,14 +45942,14 @@ async function openPeerLink(peerHostId, ctx) {
45629
45942
  }
45630
45943
 
45631
45944
  // ../../packages/host-core/dist/active-link/engine.js
45632
- import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as mkdir6, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile4 } from "node:fs/promises";
45945
+ import { lstat as lstat6, readlink as readlink4, rm as rm3, mkdir as mkdir7, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile5 } from "node:fs/promises";
45633
45946
  import { existsSync as existsSync12 } from "node:fs";
45634
- import { dirname as dirname12, join as join23, resolve as resolve6 } from "node:path";
45947
+ import { dirname as dirname12, join as join24, resolve as resolve7 } from "node:path";
45635
45948
 
45636
45949
  // ../../packages/host-core/dist/active-link/blocks.js
45637
45950
  import { createHash as createHash3 } from "node:crypto";
45638
45951
  import { createReadStream } from "node:fs";
45639
- import { open, mkdir as mkdir5, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
45952
+ import { open, mkdir as mkdir6, rename, chmod as chmod2, utimes, unlink } from "node:fs/promises";
45640
45953
  import { dirname as dirname9 } from "node:path";
45641
45954
  var CHUNK3 = 1024 * 1024;
45642
45955
  var MAX_INFLIGHT2 = 8 * CHUNK3;
@@ -45648,16 +45961,16 @@ function hashString(s) {
45648
45961
  return createHash3("sha256").update(s, "utf-8").digest("hex");
45649
45962
  }
45650
45963
  function hashFile(abs) {
45651
- return new Promise((resolve8, reject) => {
45964
+ return new Promise((resolve9, reject) => {
45652
45965
  const h = createHash3("sha256");
45653
45966
  const rs = createReadStream(abs);
45654
45967
  rs.on("data", (d) => h.update(d));
45655
- rs.on("end", () => resolve8(h.digest("hex")));
45968
+ rs.on("end", () => resolve9(h.digest("hex")));
45656
45969
  rs.on("error", reject);
45657
45970
  });
45658
45971
  }
45659
45972
  function hashFileBlocks(abs) {
45660
- return new Promise((resolve8, reject) => {
45973
+ return new Promise((resolve9, reject) => {
45661
45974
  const whole = createHash3("sha256");
45662
45975
  const blocks = [];
45663
45976
  let cur = createHash3("sha256");
@@ -45684,7 +45997,7 @@ function hashFileBlocks(abs) {
45684
45997
  rs.on("end", () => {
45685
45998
  if (curLen > 0)
45686
45999
  blocks.push(cur.digest("hex"));
45687
- resolve8({ wholeHash: whole.digest("hex"), blocks, size });
46000
+ resolve9({ wholeHash: whole.digest("hex"), blocks, size });
45688
46001
  });
45689
46002
  rs.on("error", reject);
45690
46003
  });
@@ -45715,8 +46028,8 @@ var SendWindow = class {
45715
46028
  wait() {
45716
46029
  if (this.cancelled || this.sent - this.acked < this.maxInflight)
45717
46030
  return Promise.resolve();
45718
- return new Promise((resolve8) => {
45719
- this.wake = resolve8;
46031
+ return new Promise((resolve9) => {
46032
+ this.wake = resolve9;
45720
46033
  });
45721
46034
  }
45722
46035
  cancel() {
@@ -45765,7 +46078,7 @@ var StagingWriter = class {
45765
46078
  }
45766
46079
  async ensureOpen() {
45767
46080
  if (!this.fh) {
45768
- await mkdir5(dirname9(this.stagingPath), { recursive: true });
46081
+ await mkdir6(dirname9(this.stagingPath), { recursive: true });
45769
46082
  this.fh = await open(this.stagingPath, "w");
45770
46083
  }
45771
46084
  return this.fh;
@@ -45795,7 +46108,7 @@ var StagingWriter = class {
45795
46108
  });
45796
46109
  await fh.close();
45797
46110
  this.fh = null;
45798
- await mkdir5(dirname9(dest), { recursive: true });
46111
+ await mkdir6(dirname9(dest), { recursive: true });
45799
46112
  await chmod2(this.stagingPath, mode & 511).catch(() => {
45800
46113
  });
45801
46114
  const secs = mtimeMs / 1e3;
@@ -45828,7 +46141,7 @@ var BlockAssembler = class {
45828
46141
  this.stagingPath = stagingPath;
45829
46142
  }
45830
46143
  async open() {
45831
- await mkdir5(dirname9(this.stagingPath), { recursive: true });
46144
+ await mkdir6(dirname9(this.stagingPath), { recursive: true });
45832
46145
  this.fh = await open(this.stagingPath, "w");
45833
46146
  }
45834
46147
  /** Write a received block at its byte offset (index * CHUNK). */
@@ -45872,7 +46185,7 @@ var BlockAssembler = class {
45872
46185
  });
45873
46186
  return false;
45874
46187
  }
45875
- await mkdir5(dirname9(dest), { recursive: true });
46188
+ await mkdir6(dirname9(dest), { recursive: true });
45876
46189
  await chmod2(this.stagingPath, mode & 511).catch(() => {
45877
46190
  });
45878
46191
  const secs = mtimeMs / 1e3;
@@ -45895,8 +46208,8 @@ var BlockAssembler = class {
45895
46208
  };
45896
46209
 
45897
46210
  // ../../packages/host-core/dist/active-link/manifest.js
45898
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync11, renameSync as renameSync5 } from "node:fs";
45899
- import { join as join19 } from "node:path";
46211
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync7, existsSync as existsSync11, renameSync as renameSync5 } from "node:fs";
46212
+ import { join as join20 } from "node:path";
45900
46213
 
45901
46214
  // ../../packages/host-core/dist/active-link/reconcile.js
45902
46215
  var ABSENT = { kind: "absent", t: -Infinity, hash: "" };
@@ -45932,11 +46245,11 @@ var LinkManifest = class {
45932
46245
  this.dir = dir;
45933
46246
  }
45934
46247
  file() {
45935
- return join19(this.dir, "manifest.json");
46248
+ return join20(this.dir, "manifest.json");
45936
46249
  }
45937
46250
  load() {
45938
46251
  try {
45939
- const raw = JSON.parse(readFileSync8(this.file(), "utf-8"));
46252
+ const raw = JSON.parse(readFileSync9(this.file(), "utf-8"));
45940
46253
  this.records = new Map(Object.entries(raw.records ?? {}));
45941
46254
  this.tombstones = new Map(Object.entries(raw.tombstones ?? {}));
45942
46255
  } catch {
@@ -46034,7 +46347,7 @@ var LinkManifest = class {
46034
46347
 
46035
46348
  // ../../packages/host-core/dist/active-link/scanner.js
46036
46349
  import { readdir as readdir4, lstat as lstat2, readlink as readlink2 } from "node:fs/promises";
46037
- import { join as join20, sep as sep6 } from "node:path";
46350
+ import { join as join21, sep as sep6 } from "node:path";
46038
46351
  async function walkRels(root, extraIgnore) {
46039
46352
  const out = [];
46040
46353
  async function rec(dir) {
@@ -46049,7 +46362,7 @@ async function walkRels(root, extraIgnore) {
46049
46362
  continue;
46050
46363
  if (e.isDirectory() && HEAVY_DIRS.has(e.name))
46051
46364
  continue;
46052
- const abs = join20(dir, e.name);
46365
+ const abs = join21(dir, e.name);
46053
46366
  if (extraIgnore?.(abs))
46054
46367
  continue;
46055
46368
  if (e.isDirectory())
@@ -46088,7 +46401,7 @@ async function scanTree(root, prior, allow, extraIgnore) {
46088
46401
  return { records };
46089
46402
  }
46090
46403
  function absOf(root, rel) {
46091
- return join20(root, rel.split("/").join(sep6));
46404
+ return join21(root, rel.split("/").join(sep6));
46092
46405
  }
46093
46406
 
46094
46407
  // ../../packages/host-core/dist/active-link/gitignore.js
@@ -47151,7 +47464,7 @@ var NodeFsHandler = class {
47151
47464
  this._addToNodeFs(path5, initialAdd, wh, depth + 1);
47152
47465
  }
47153
47466
  }).on(EV.ERROR, this._boundHandleError);
47154
- return new Promise((resolve8, reject) => {
47467
+ return new Promise((resolve9, reject) => {
47155
47468
  if (!stream)
47156
47469
  return reject();
47157
47470
  stream.once(STR_END, () => {
@@ -47160,7 +47473,7 @@ var NodeFsHandler = class {
47160
47473
  return;
47161
47474
  }
47162
47475
  const wasThrottled = throttler ? throttler.clear() : false;
47163
- resolve8(void 0);
47476
+ resolve9(void 0);
47164
47477
  previous.getChildren().filter((item) => {
47165
47478
  return item !== directory && !current.has(item);
47166
47479
  }).forEach((item) => {
@@ -47304,11 +47617,11 @@ function createPattern(matcher) {
47304
47617
  if (matcher.path === string4)
47305
47618
  return true;
47306
47619
  if (matcher.recursive) {
47307
- const relative7 = sysPath2.relative(matcher.path, string4);
47308
- if (!relative7) {
47620
+ const relative8 = sysPath2.relative(matcher.path, string4);
47621
+ if (!relative8) {
47309
47622
  return false;
47310
47623
  }
47311
- return !relative7.startsWith("..") && !sysPath2.isAbsolute(relative7);
47624
+ return !relative8.startsWith("..") && !sysPath2.isAbsolute(relative8);
47312
47625
  }
47313
47626
  return false;
47314
47627
  };
@@ -48016,8 +48329,8 @@ var LinkWatcher = class {
48016
48329
  this.fsw.on("unlinkDir", onEvent);
48017
48330
  this.fsw.on("error", () => {
48018
48331
  });
48019
- await new Promise((resolve8) => {
48020
- this.fsw.once("ready", () => resolve8());
48332
+ await new Promise((resolve9) => {
48333
+ this.fsw.once("ready", () => resolve9());
48021
48334
  });
48022
48335
  }
48023
48336
  enqueue(abs) {
@@ -48105,7 +48418,7 @@ var ActiveLinkEngine = class {
48105
48418
  }
48106
48419
  async start() {
48107
48420
  this.emit({ type: "status", linkId: this.opts.linkId, state: "scanning" });
48108
- await rm3(join23(this.stateDir, ".staging"), { recursive: true, force: true }).catch(() => {
48421
+ await rm3(join24(this.stateDir, ".staging"), { recursive: true, force: true }).catch(() => {
48109
48422
  });
48110
48423
  this.manifest.load();
48111
48424
  await this.reconcileScan();
@@ -48498,20 +48811,20 @@ var ActiveLinkEngine = class {
48498
48811
  * file so the path still exists — recorded as a FILE matching disk so the local
48499
48812
  * watcher doesn't churn. The target is containment-checked, never dereferenced. */
48500
48813
  async applySymlink(rel, dest, target, mtimeMs, mode) {
48501
- const resolved = resolve6(dirname12(dest), target);
48814
+ const resolved = resolve7(dirname12(dest), target);
48502
48815
  if (!isInsideRoot(resolved, this.opts.localRoot))
48503
48816
  return;
48504
48817
  const hash2 = hashString(target);
48505
48818
  const secs = mtimeMs / 1e3;
48506
48819
  try {
48507
- await mkdir6(dirname12(dest), { recursive: true });
48820
+ await mkdir7(dirname12(dest), { recursive: true });
48508
48821
  await rm3(dest, { force: true, recursive: true });
48509
48822
  try {
48510
48823
  await symlink2(target, dest);
48511
48824
  this.manifest.setRecord(rel, { kind: "symlink", mtimeMs, size: 0, mode, hash: hash2, blocks: [] });
48512
48825
  } catch {
48513
48826
  const buf = Buffer.from(target, "utf-8");
48514
- await writeFile4(dest, buf);
48827
+ await writeFile5(dest, buf);
48515
48828
  await utimes2(dest, secs, secs).catch(() => {
48516
48829
  });
48517
48830
  this.manifest.setRecord(rel, { kind: "file", mtimeMs, size: buf.length, mode, hash: hash2, blocks: [hash2] });
@@ -48554,7 +48867,7 @@ var ActiveLinkEngine = class {
48554
48867
  return;
48555
48868
  if (fromRec && fromRec.kind === "file") {
48556
48869
  try {
48557
- await mkdir6(dirname12(toAbs), { recursive: true });
48870
+ await mkdir7(dirname12(toAbs), { recursive: true });
48558
48871
  await rename2(fromAbs, toAbs);
48559
48872
  const secs = mtimeMs / 1e3;
48560
48873
  await utimes2(toAbs, secs, secs).catch(() => {
@@ -48729,7 +49042,7 @@ var ActiveLinkEngine = class {
48729
49042
  this.inboundWatchdog.clear();
48730
49043
  }
48731
49044
  stagingPath(rel, tag) {
48732
- return join23(this.stateDir, ".staging", `${hashString(rel)}.${tag}`);
49045
+ return join24(this.stateDir, ".staging", `${hashString(rel)}.${tag}`);
48733
49046
  }
48734
49047
  pruneSuppress() {
48735
49048
  const now = this.now();
@@ -48754,14 +49067,14 @@ var ActiveLinkEngine = class {
48754
49067
  };
48755
49068
 
48756
49069
  // ../../packages/host-core/dist/active-link/config.js
48757
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
48758
- import { join as join24 } from "node:path";
49070
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync9, mkdirSync as mkdirSync8, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
49071
+ import { join as join25 } from "node:path";
48759
49072
  function configPath2() {
48760
- return join24(activeLinkRoot(), "links.json");
49073
+ return join25(activeLinkRoot(), "links.json");
48761
49074
  }
48762
49075
  function loadLinkConfigs() {
48763
49076
  try {
48764
- const raw = JSON.parse(readFileSync9(configPath2(), "utf-8"));
49077
+ const raw = JSON.parse(readFileSync10(configPath2(), "utf-8"));
48765
49078
  if (!Array.isArray(raw.links))
48766
49079
  return [];
48767
49080
  return raw.links.filter((c) => c && c.linkId && c.localRoot && c.peerHostId);
@@ -48782,9 +49095,42 @@ function writeAll(links) {
48782
49095
  }
48783
49096
  function saveLinkConfig(cfg2) {
48784
49097
  const links = loadLinkConfigs().filter((c) => c.linkId !== cfg2.linkId);
48785
- links.push({ linkId: cfg2.linkId, localRoot: cfg2.localRoot, peerHostId: cfg2.peerHostId, ...cfg2.initiated ? { initiated: true } : {} });
49098
+ links.push({
49099
+ linkId: cfg2.linkId,
49100
+ localRoot: cfg2.localRoot,
49101
+ peerHostId: cfg2.peerHostId,
49102
+ ...cfg2.initiated ? { initiated: true } : {},
49103
+ ...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {},
49104
+ ...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
49105
+ ...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {}
49106
+ });
48786
49107
  writeAll(links);
48787
49108
  }
49109
+ function pendingPath() {
49110
+ return join25(activeLinkRoot(), "pending-deprovisions.json");
49111
+ }
49112
+ function loadPendingDeprovisions() {
49113
+ try {
49114
+ const raw = JSON.parse(readFileSync10(pendingPath(), "utf-8"));
49115
+ return Array.isArray(raw.pending) ? raw.pending.filter((p) => p && p.linkId && p.peerHostId) : [];
49116
+ } catch {
49117
+ return [];
49118
+ }
49119
+ }
49120
+ function writePending(pending) {
49121
+ try {
49122
+ const dir = activeLinkRoot();
49123
+ if (!existsSync13(dir))
49124
+ mkdirSync8(dir, { recursive: true });
49125
+ const tmp = `${pendingPath()}.tmp`;
49126
+ writeFileSync9(tmp, JSON.stringify({ pending }, null, 2));
49127
+ renameSync6(tmp, pendingPath());
49128
+ } catch {
49129
+ }
49130
+ }
49131
+ function removePendingDeprovision(linkId) {
49132
+ writePending(loadPendingDeprovisions().filter((p) => p.linkId !== linkId));
49133
+ }
48788
49134
  function removeLinkConfig(linkId) {
48789
49135
  writeAll(loadLinkConfigs().filter((c) => c.linkId !== linkId));
48790
49136
  }
@@ -49437,6 +49783,7 @@ function resumeActiveLinks() {
49437
49783
  if (cfg2.initiated && isHostOnline(cfg2.peerHostId))
49438
49784
  sendActiveLinkProvision(cfg2);
49439
49785
  }
49786
+ flushPendingDeprovisions();
49440
49787
  } catch (e) {
49441
49788
  console.warn("[active-link] resume failed:", e.message);
49442
49789
  }
@@ -49445,11 +49792,21 @@ function isHostOnline(hostId) {
49445
49792
  return serverHosts.some((h) => h.hostId === hostId && h.online);
49446
49793
  }
49447
49794
  function sendActiveLinkProvision(cfg2) {
49448
- send("activelink", { type: "provision", linkId: cfg2.linkId, fromHost: ownHostId(), projectName: basename5(cfg2.localRoot) }, { hostId: cfg2.peerHostId });
49795
+ send("activelink", {
49796
+ type: "provision",
49797
+ linkId: cfg2.linkId,
49798
+ fromHost: ownHostId(),
49799
+ projectName: cfg2.remoteSubfolder ?? basename5(cfg2.localRoot),
49800
+ ...cfg2.remoteParent ? { remoteParent: cfg2.remoteParent } : {},
49801
+ ...cfg2.remoteSubfolder ? { remoteSubfolder: cfg2.remoteSubfolder } : {},
49802
+ ...cfg2.workspaceLinkId ? { workspaceLinkId: cfg2.workspaceLinkId } : {}
49803
+ }, { hostId: cfg2.peerHostId });
49449
49804
  }
49450
49805
  function safeFolderName(name) {
49451
49806
  const cleaned = name.replace(/[/\\]/g, "-").replace(/\.\.+/g, ".").trim();
49452
- return cleaned || "project";
49807
+ if (!cleaned || /^\.+$/.test(cleaned))
49808
+ return "project";
49809
+ return cleaned;
49453
49810
  }
49454
49811
  function provisionActiveLinkMirror(payload) {
49455
49812
  if (!activeLinkEnabled())
@@ -49461,9 +49818,17 @@ function provisionActiveLinkMirror(payload) {
49461
49818
  resumeActiveLinks();
49462
49819
  return;
49463
49820
  }
49464
- let localRoot = join25(HOST_ROOT, "Tesseract Mirrors", safeFolderName(projectName));
49821
+ const workspaceLinkId = typeof payload.workspaceLinkId === "string" ? payload.workspaceLinkId : void 0;
49822
+ const remoteParent = typeof payload.remoteParent === "string" ? payload.remoteParent : void 0;
49823
+ const remoteSubfolder = typeof payload.remoteSubfolder === "string" ? payload.remoteSubfolder : void 0;
49824
+ let localRoot;
49825
+ if (remoteParent && remoteSubfolder) {
49826
+ localRoot = join26(remoteParent, safeFolderName(remoteSubfolder));
49827
+ } else {
49828
+ localRoot = join26(HOST_ROOT, "Tesseract Mirrors", safeFolderName(projectName));
49829
+ }
49465
49830
  if (loadLinkConfigs().some((c) => c.localRoot === localRoot && c.linkId !== linkId)) {
49466
- localRoot = join25(HOST_ROOT, "Tesseract Mirrors", `${safeFolderName(projectName)}-${linkId.slice(0, 6)}`);
49831
+ localRoot = `${localRoot}-${linkId.slice(0, 6)}`;
49467
49832
  }
49468
49833
  if (!isInsideRoot(localRoot, HOST_ROOT))
49469
49834
  return;
@@ -49471,9 +49836,31 @@ function provisionActiveLinkMirror(payload) {
49471
49836
  mkdirSync9(localRoot, { recursive: true });
49472
49837
  } catch {
49473
49838
  }
49474
- saveLinkConfig({ linkId, localRoot, peerHostId: fromHost });
49839
+ saveLinkConfig({
49840
+ linkId,
49841
+ localRoot,
49842
+ peerHostId: fromHost,
49843
+ ...workspaceLinkId ? { workspaceLinkId } : {},
49844
+ ...remoteParent ? { remoteParent } : {},
49845
+ ...remoteSubfolder ? { remoteSubfolder } : {}
49846
+ });
49475
49847
  resumeActiveLinks();
49476
49848
  }
49849
+ function flushPendingDeprovisions() {
49850
+ for (const d of loadPendingDeprovisions()) {
49851
+ if (isHostOnline(d.peerHostId))
49852
+ send("activelink", { type: "deprovision", linkId: d.linkId, fromHost: ownHostId() }, { hostId: d.peerHostId });
49853
+ }
49854
+ }
49855
+ function deprovisionActiveLinkMirror(payload) {
49856
+ const { linkId, fromHost } = payload;
49857
+ if (typeof linkId !== "string")
49858
+ return;
49859
+ void disconnectActiveLink(linkId);
49860
+ removeLinkConfig(linkId);
49861
+ if (typeof fromHost === "string")
49862
+ send("activelink", { type: "deprovisionAck", linkId }, { hostId: fromHost });
49863
+ }
49477
49864
  function handleActiveLinkChannel(payload, inbound) {
49478
49865
  if (!inbound)
49479
49866
  return;
@@ -49481,8 +49868,12 @@ function handleActiveLinkChannel(payload, inbound) {
49481
49868
  const p = payload;
49482
49869
  if (p?.type === "provision")
49483
49870
  provisionActiveLinkMirror(p);
49871
+ else if (p?.type === "deprovision")
49872
+ deprovisionActiveLinkMirror(p);
49873
+ else if (p?.type === "deprovisionAck" && typeof p.linkId === "string")
49874
+ removePendingDeprovision(p.linkId);
49484
49875
  } catch (e) {
49485
- console.warn("[active-link] provision failed:", e.message);
49876
+ console.warn("[active-link] channel handler failed:", e.message);
49486
49877
  }
49487
49878
  }
49488
49879
  async function beginOutboundTransfer(p, clientId) {
@@ -49498,8 +49889,8 @@ async function beginOutboundTransfer(p, clientId) {
49498
49889
  }
49499
49890
  var fsWaiters = /* @__PURE__ */ new Map();
49500
49891
  function rejectAllFsWaiters() {
49501
- for (const [, resolve8] of fsWaiters)
49502
- resolve8({ error: "Disconnected from the remote machine." });
49892
+ for (const [, resolve9] of fsWaiters)
49893
+ resolve9({ error: "Disconnected from the remote machine." });
49503
49894
  fsWaiters.clear();
49504
49895
  }
49505
49896
  function clientIdFor(msg) {
@@ -49834,7 +50225,8 @@ function stopHeartbeat() {
49834
50225
  function registerAsHost() {
49835
50226
  void ensureP2pReady();
49836
50227
  const kind = process.env.CCB_HOST_KIND === "cloud" ? "cloud" : void 0;
49837
- send("host", { type: "host:register", name: hostname3(), platform: process.platform, deviceId, caps: ["agent", "fs", "term"], ...kind ? { kind } : {}, ...staticMetrics(hostVersion), ...p2pAdvert ?? {} });
50228
+ const name = kind === "cloud" ? "Cloud agent" : hostname3();
50229
+ send("host", { type: "host:register", name, platform: process.platform, deviceId, caps: ["agent", "fs", "term"], ...kind ? { kind } : {}, ...staticMetrics(hostVersion), ...p2pAdvert ?? {} });
49838
50230
  if (!heartbeat)
49839
50231
  heartbeat = setInterval(() => send("host", { type: "host:heartbeat", ...dynamicMetrics() }), 2e4);
49840
50232
  }
@@ -50132,8 +50524,8 @@ async function startLocalServer(opts) {
50132
50524
  const log3 = opts.log ?? (() => {
50133
50525
  });
50134
50526
  const wss = new import_websocket_server.default({ host: "127.0.0.1", port: 0 });
50135
- await new Promise((resolve8, reject) => {
50136
- wss.once("listening", resolve8);
50527
+ await new Promise((resolve9, reject) => {
50528
+ wss.once("listening", resolve9);
50137
50529
  wss.once("error", reject);
50138
50530
  });
50139
50531
  const addr = wss.address();
@@ -50368,8 +50760,8 @@ async function startLocalServer(opts) {
50368
50760
  }
50369
50761
 
50370
50762
  // ../../packages/host-core/dist/daemon-runtime.js
50371
- import { readFileSync as readFileSync10, writeFileSync as writeFileSync10, existsSync as existsSync15, mkdirSync as mkdirSync10, unlinkSync as unlinkSync2, chmodSync as chmodSync3 } from "node:fs";
50372
- import { join as join26 } from "node:path";
50763
+ import { readFileSync as readFileSync11, writeFileSync as writeFileSync10, existsSync as existsSync15, mkdirSync as mkdirSync10, unlinkSync as unlinkSync2, chmodSync as chmodSync3 } from "node:fs";
50764
+ import { join as join27 } from "node:path";
50373
50765
  import { homedir as homedir11 } from "node:os";
50374
50766
  import { randomBytes as randomBytes3 } from "node:crypto";
50375
50767
 
@@ -50436,8 +50828,8 @@ async function runDaemon(opts = {}) {
50436
50828
  const VERSION = opts.version ?? process.env.CCB_DAEMON_VERSION ?? "dev";
50437
50829
  const TAG = opts.tag ?? "host-daemon";
50438
50830
  const log3 = (...args) => console.log(`[${TAG} ${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args);
50439
- const pidfile = () => join26(daemonDir(), "daemon.lock");
50440
- const statusFile = () => join26(daemonDir(), "status.json");
50831
+ const pidfile = () => join27(daemonDir(), "daemon.lock");
50832
+ const statusFile = () => join27(daemonDir(), "status.json");
50441
50833
  const isAlive2 = (pid) => {
50442
50834
  try {
50443
50835
  process.kill(pid, 0);
@@ -50450,7 +50842,7 @@ async function runDaemon(opts = {}) {
50450
50842
  const f = pidfile();
50451
50843
  try {
50452
50844
  if (existsSync15(f)) {
50453
- const prev = Number(readFileSync10(f, "utf-8").trim());
50845
+ const prev = Number(readFileSync11(f, "utf-8").trim());
50454
50846
  if (prev && prev !== process.pid && isAlive2(prev))
50455
50847
  return false;
50456
50848
  }
@@ -50467,14 +50859,14 @@ async function runDaemon(opts = {}) {
50467
50859
  function releaseLock() {
50468
50860
  try {
50469
50861
  const f = pidfile();
50470
- if (existsSync15(f) && Number(readFileSync10(f, "utf-8").trim()) === process.pid)
50862
+ if (existsSync15(f) && Number(readFileSync11(f, "utf-8").trim()) === process.pid)
50471
50863
  unlinkSync2(f);
50472
50864
  } catch {
50473
50865
  }
50474
50866
  }
50475
50867
  function writeStatus(s) {
50476
50868
  try {
50477
- writeFileSync10(statusFile(), JSON.stringify({ pid: process.pid, version: VERSION, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...localInfo ?? {}, ...s }));
50869
+ writeFileSync10(statusFile(), JSON.stringify({ pid: process.pid, version: VERSION, execPath: process.execPath, updatedAt: (/* @__PURE__ */ new Date()).toISOString(), ...localInfo ?? {}, ...s }));
50478
50870
  chmodSync3(statusFile(), 384);
50479
50871
  } catch {
50480
50872
  }
@@ -50537,7 +50929,7 @@ async function runDaemon(opts = {}) {
50537
50929
  if (r.status === 401) {
50538
50930
  log3("device token no longer valid \u2014 dropping to local-only on restart");
50539
50931
  try {
50540
- unlinkSync2(join26(daemonDir(), "credentials.json"));
50932
+ unlinkSync2(join27(daemonDir(), "credentials.json"));
50541
50933
  } catch {
50542
50934
  }
50543
50935
  shutdown(0);
@@ -50583,7 +50975,7 @@ import { platform as platform2 } from "node:os";
50583
50975
 
50584
50976
  // ../../packages/host-core/dist/service/launchd.js
50585
50977
  import { writeFileSync as writeFileSync11, existsSync as existsSync16, mkdirSync as mkdirSync11, unlinkSync as unlinkSync3 } from "node:fs";
50586
- import { dirname as dirname13, join as join27 } from "node:path";
50978
+ import { dirname as dirname13, join as join28 } from "node:path";
50587
50979
  import { homedir as homedir12, userInfo } from "node:os";
50588
50980
 
50589
50981
  // ../../packages/host-core/dist/service/exec.js
@@ -50591,10 +50983,10 @@ import { execFile as execFile5, spawn as spawn5 } from "node:child_process";
50591
50983
  import { promisify as promisify4 } from "node:util";
50592
50984
  var run = promisify4(execFile5);
50593
50985
  function runInherit(cmd, args) {
50594
- return new Promise((resolve8) => {
50986
+ return new Promise((resolve9) => {
50595
50987
  const p = spawn5(cmd, args, { stdio: "inherit" });
50596
- p.on("error", () => resolve8());
50597
- p.on("close", () => resolve8());
50988
+ p.on("error", () => resolve9());
50989
+ p.on("close", () => resolve9());
50598
50990
  });
50599
50991
  }
50600
50992
 
@@ -50607,10 +50999,10 @@ function xml(s) {
50607
50999
  }
50608
51000
  function makeLaunchd(instanceId) {
50609
51001
  const label = SERVICE_LABEL_BASE + (instanceId ? `.${instanceId}` : "");
50610
- const plistPath = () => join27(homedir12(), "Library", "LaunchAgents", `${label}.plist`);
51002
+ const plistPath = () => join28(homedir12(), "Library", "LaunchAgents", `${label}.plist`);
50611
51003
  const domainTarget = () => `gui/${userInfo().uid}`;
50612
51004
  const serviceTarget = () => `${domainTarget()}/${label}`;
50613
- const logFile = () => join27(daemonDir(), "daemon.log");
51005
+ const logFile = () => join28(daemonDir(), "daemon.log");
50614
51006
  function buildPlist(spec) {
50615
51007
  const args = [spec.exec, ...spec.args].map((a) => ` <string>${xml(a)}</string>`).join("\n");
50616
51008
  const env = Object.entries(spec.env).map(([k, v]) => ` <key>${xml(k)}</key>
@@ -50703,7 +51095,7 @@ ${env}
50703
51095
 
50704
51096
  // ../../packages/host-core/dist/service/systemd.js
50705
51097
  import { writeFileSync as writeFileSync12, existsSync as existsSync17, mkdirSync as mkdirSync12, unlinkSync as unlinkSync4 } from "node:fs";
50706
- import { dirname as dirname14, join as join28 } from "node:path";
51098
+ import { dirname as dirname14, join as join29 } from "node:path";
50707
51099
  import { homedir as homedir13, userInfo as userInfo2 } from "node:os";
50708
51100
  function shq(s) {
50709
51101
  return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
@@ -50711,8 +51103,8 @@ function shq(s) {
50711
51103
  function makeSystemd(instanceId) {
50712
51104
  const unit = `tesseract-host${instanceId ? `-${instanceId}` : ""}.service`;
50713
51105
  const unitPath = () => {
50714
- const base = process.env.XDG_CONFIG_HOME || join28(homedir13(), ".config");
50715
- return join28(base, "systemd", "user", unit);
51106
+ const base = process.env.XDG_CONFIG_HOME || join29(homedir13(), ".config");
51107
+ return join29(base, "systemd", "user", unit);
50716
51108
  };
50717
51109
  function buildUnit(spec) {
50718
51110
  const execStart = [spec.exec, ...spec.args].map(shq).join(" ");
@@ -50783,11 +51175,11 @@ WantedBy=default.target
50783
51175
 
50784
51176
  // ../../packages/host-core/dist/service/windows.js
50785
51177
  import { writeFileSync as writeFileSync13, existsSync as existsSync18, mkdirSync as mkdirSync13, unlinkSync as unlinkSync5 } from "node:fs";
50786
- import { dirname as dirname15, join as join29 } from "node:path";
51178
+ import { dirname as dirname15, join as join30 } from "node:path";
50787
51179
  function makeWindowsTask(instanceId) {
50788
51180
  const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
50789
- const wrapperPath = () => join29(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
50790
- const logFile = () => join29(daemonDir(), "daemon.log");
51181
+ const wrapperPath = () => join30(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
51182
+ const logFile = () => join30(daemonDir(), "daemon.log");
50791
51183
  function buildWrapper(spec) {
50792
51184
  const env = Object.entries(spec.env).map(([k, v]) => `set "${k}=${v}"`).join("\r\n");
50793
51185
  const cmd = [spec.exec, ...spec.args].map((a) => `"${a}"`).join(" ");
@@ -50866,7 +51258,7 @@ function getServiceController(instanceId) {
50866
51258
  var import_qrcode_terminal = __toESM(require_main(), 1);
50867
51259
  import { randomUUID as randomUUID6 } from "node:crypto";
50868
51260
  import { existsSync as existsSync19, rmSync } from "node:fs";
50869
- import { join as join30 } from "node:path";
51261
+ import { join as join31 } from "node:path";
50870
51262
 
50871
51263
  // src/config.ts
50872
51264
  import { hostname as hostname4 } from "node:os";
@@ -50898,7 +51290,7 @@ var BS = String.fromCharCode(8);
50898
51290
  var ERASE = BS + " " + BS;
50899
51291
  function ask(question) {
50900
51292
  const { stdin, stdout } = process;
50901
- return new Promise((resolve8) => {
51293
+ return new Promise((resolve9) => {
50902
51294
  stdout.write(question);
50903
51295
  stdin.setEncoding("utf8");
50904
51296
  if (!stdin.isTTY || typeof stdin.setRawMode !== "function") {
@@ -50911,7 +51303,7 @@ function ask(question) {
50911
51303
  stdin.pause();
50912
51304
  let line = data.slice(0, nl);
50913
51305
  if (line.endsWith(CR)) line = line.slice(0, -1);
50914
- resolve8(line.trim());
51306
+ resolve9(line.trim());
50915
51307
  }
50916
51308
  };
50917
51309
  stdin.resume();
@@ -50926,7 +51318,7 @@ function ask(question) {
50926
51318
  stdin.pause();
50927
51319
  stdin.removeListener("data", onData);
50928
51320
  stdout.write(LF);
50929
- resolve8(buf.trim());
51321
+ resolve9(buf.trim());
50930
51322
  }
50931
51323
  function onData(chunk) {
50932
51324
  for (const ch of chunk) {
@@ -50982,7 +51374,7 @@ function persist2(api, relay, deviceId2, dt) {
50982
51374
  async function login(opts) {
50983
51375
  const api = (opts.api ?? DEFAULT_API).replace(/\/$/, "");
50984
51376
  const relay = (opts.relay ?? defaultRelay(api)).replace(/\/$/, "");
50985
- const deviceId2 = readCredentials()?.deviceId ?? randomUUID6().slice(0, 8);
51377
+ const deviceId2 = readCredentials()?.deviceId ?? process.env.CCB_DEVICE_ID ?? randomUUID6().slice(0, 8);
50986
51378
  const label = opts.name ?? defaultLabel();
50987
51379
  if (opts.token) {
50988
51380
  const dt = await fetchJson(`${api}/auth/device-token`, {
@@ -51043,7 +51435,7 @@ async function logout() {
51043
51435
  }
51044
51436
  for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
51045
51437
  try {
51046
- const p = join30(daemonDir(), f);
51438
+ const p = join31(daemonDir(), f);
51047
51439
  if (existsSync19(p)) rmSync(p);
51048
51440
  } catch {
51049
51441
  }
@@ -51105,7 +51497,7 @@ async function fetchLatest() {
51105
51497
  }
51106
51498
  }
51107
51499
  function installVersion(target) {
51108
- return new Promise((resolve8) => {
51500
+ return new Promise((resolve9) => {
51109
51501
  const npm = process.platform === "win32" ? "npm.cmd" : "npm";
51110
51502
  log2(`installing tesseract-agent@${target} \u2026`);
51111
51503
  let child;
@@ -51113,20 +51505,20 @@ function installVersion(target) {
51113
51505
  child = spawn6(npm, ["install", "-g", `tesseract-agent@${target}`], { stdio: ["ignore", "inherit", "inherit"] });
51114
51506
  } catch (e) {
51115
51507
  log2("npm spawn threw:", e instanceof Error ? e.message : String(e));
51116
- resolve8(false);
51508
+ resolve9(false);
51117
51509
  return;
51118
51510
  }
51119
51511
  child.on("error", (e) => {
51120
51512
  log2("npm not runnable:", e.message);
51121
- resolve8(false);
51513
+ resolve9(false);
51122
51514
  });
51123
51515
  child.on("close", (code) => {
51124
51516
  if (code === 0) {
51125
51517
  log2(`installed ${target}`);
51126
- resolve8(true);
51518
+ resolve9(true);
51127
51519
  } else {
51128
51520
  log2(`npm install exited ${code} \u2014 staying on the current version`);
51129
- resolve8(false);
51521
+ resolve9(false);
51130
51522
  }
51131
51523
  });
51132
51524
  });
@@ -51167,9 +51559,9 @@ function startSelfUpdater(current) {
51167
51559
  }
51168
51560
 
51169
51561
  // src/service.ts
51170
- import { join as join31 } from "node:path";
51562
+ import { join as join32 } from "node:path";
51171
51563
  import { platform as platform3 } from "node:os";
51172
- import { existsSync as existsSync20, readFileSync as readFileSync11 } from "node:fs";
51564
+ import { existsSync as existsSync20, readFileSync as readFileSync12 } from "node:fs";
51173
51565
  function controller(instanceId) {
51174
51566
  const c = getServiceController(instanceId);
51175
51567
  if (!c) {
@@ -51182,7 +51574,7 @@ function buildSpec(cliEntry) {
51182
51574
  exec: process.execPath,
51183
51575
  args: [cliEntry, "run"],
51184
51576
  env: { CCB_DAEMON_DIR: daemonDir() },
51185
- logPath: join31(daemonDir(), "daemon.log")
51577
+ logPath: join32(daemonDir(), "daemon.log")
51186
51578
  };
51187
51579
  }
51188
51580
  var isAlive = (pid) => {
@@ -51194,10 +51586,10 @@ var isAlive = (pid) => {
51194
51586
  }
51195
51587
  };
51196
51588
  function runningDaemonInfo() {
51197
- const lock = join31(daemonDir(), "daemon.lock");
51589
+ const lock = join32(daemonDir(), "daemon.lock");
51198
51590
  try {
51199
51591
  if (!existsSync20(lock)) return null;
51200
- const pid = Number(readFileSync11(lock, "utf-8").trim());
51592
+ const pid = Number(readFileSync12(lock, "utf-8").trim());
51201
51593
  if (!pid || !isAlive(pid)) return null;
51202
51594
  return { pid, device: readCredentials()?.deviceId };
51203
51595
  } catch {
@@ -51233,8 +51625,8 @@ async function logs(instanceId, follow) {
51233
51625
  // src/cli.ts
51234
51626
  function pkgVersion() {
51235
51627
  try {
51236
- const p = join32(dirname16(fileURLToPath2(import.meta.url)), "..", "package.json");
51237
- return JSON.parse(readFileSync12(p, "utf8")).version ?? "0.0.0";
51628
+ const p = join33(dirname16(fileURLToPath2(import.meta.url)), "..", "package.json");
51629
+ return JSON.parse(readFileSync13(p, "utf8")).version ?? "0.0.0";
51238
51630
  } catch {
51239
51631
  return "0.0.0";
51240
51632
  }
@@ -51285,7 +51677,6 @@ function applyRunFlags(rest, flags) {
51285
51677
  }
51286
51678
  if (flags["no-active-link"] === true) process.env.CCB_ACTIVE_LINK = "0";
51287
51679
  else if (flags["active-link"] === true) process.env.CCB_ACTIVE_LINK = "1";
51288
- else if (process.env.CCB_ACTIVE_LINK === void 0) process.env.CCB_ACTIVE_LINK = "1";
51289
51680
  }
51290
51681
  async function superviseDaemon(cliEntry) {
51291
51682
  let stopping = false;
@@ -51400,7 +51791,7 @@ async function linkCommand(rest, flags) {
51400
51791
  return;
51401
51792
  }
51402
51793
  if (sub === "add") {
51403
- const folder = rest[1] && !rest[1].startsWith("--") ? resolve7(rest[1]) : void 0;
51794
+ const folder = rest[1] && !rest[1].startsWith("--") ? resolve8(rest[1]) : void 0;
51404
51795
  const peer = typeof flags.peer === "string" ? flags.peer : void 0;
51405
51796
  if (!folder || !peer) {
51406
51797
  console.error("Usage: tesseract-agent link add <folder> --peer <hostId> (--name <shared> | --id <sharedId>)");
@@ -51497,7 +51888,7 @@ async function main() {
51497
51888
  process.exit(1);
51498
51889
  }
51499
51890
  instance = flags.instance;
51500
- process.env.CCB_DAEMON_DIR = join32(homedir14(), ".tesseract", `daemon-${instance}`);
51891
+ process.env.CCB_DAEMON_DIR = join33(homedir14(), ".tesseract", `daemon-${instance}`);
51501
51892
  }
51502
51893
  const force = flags.yes === true || flags.force === true;
51503
51894
  const cliEntry = fileURLToPath2(import.meta.url);