tesseract-agent 0.7.4 → 0.8.0

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 +529 -400
  2. package/package.json +1 -1
@@ -13087,8 +13087,8 @@ var capitalizeFirstCharacter, error28;
13087
13087
  var init_lt = __esm({
13088
13088
  "../../node_modules/zod/v4/locales/lt.js"() {
13089
13089
  init_util();
13090
- capitalizeFirstCharacter = (text3) => {
13091
- return text3.charAt(0).toUpperCase() + text3.slice(1);
13090
+ capitalizeFirstCharacter = (text4) => {
13091
+ return text4.charAt(0).toUpperCase() + text4.slice(1);
13092
13092
  };
13093
13093
  error28 = () => {
13094
13094
  const Sizable = {
@@ -21598,16 +21598,54 @@ var init_design_tools = __esm({
21598
21598
  }
21599
21599
  });
21600
21600
 
21601
- // ../../packages/agent-core/dist/imagegen-tools.js
21601
+ // ../../packages/agent-core/dist/support-tools.js
21602
21602
  import { tool as tool3 } from "@anthropic-ai/claude-agent-sdk";
21603
+ function buildSupportTools(submit) {
21604
+ return [
21605
+ tool3("submit_issue", [
21606
+ "File a bug report or feature request for the Tesseract app itself (not the user's project).",
21607
+ "Creates a PUBLIC GitHub issue from the title + description you pass, and privately attaches full",
21608
+ "technical diagnostics (app version, OS, logs, settings) for the team. Requires the user to be signed in.",
21609
+ "IMPORTANT: the title and description are PUBLIC \u2014 never put secrets, credentials, tokens, or personal",
21610
+ "information in them. Confirm the wording with the user before filing. Returns the created issue link."
21611
+ ].join(" "), {
21612
+ type: external_exports.enum(["issue", "feature"]).describe("'issue' for a bug/problem, 'feature' for a request/idea"),
21613
+ title: external_exports.string().min(3).describe("A short, specific title (public)."),
21614
+ description: external_exports.string().min(10).describe("A clear description \u2014 what happened / what is wanted, and why (public, markdown ok).")
21615
+ }, async (args) => {
21616
+ try {
21617
+ const res = await submit({
21618
+ type: args.type,
21619
+ title: args.title.trim(),
21620
+ description: args.description.trim()
21621
+ });
21622
+ const kind = args.type === "feature" ? "feature request" : "bug report";
21623
+ return text2(`Filed your ${kind}: ${res.issueUrl} (#${res.issueNumber}). Full technical diagnostics were attached privately for the team.`);
21624
+ } catch (e) {
21625
+ return text2(`Could not file the report: ${e instanceof Error ? e.message : String(e)}`, true);
21626
+ }
21627
+ })
21628
+ ];
21629
+ }
21630
+ var text2;
21631
+ var init_support_tools = __esm({
21632
+ "../../packages/agent-core/dist/support-tools.js"() {
21633
+ "use strict";
21634
+ init_zod();
21635
+ text2 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
21636
+ }
21637
+ });
21638
+
21639
+ // ../../packages/agent-core/dist/imagegen-tools.js
21640
+ import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
21603
21641
  function buildImagegenTools(deps) {
21604
21642
  return [
21605
- tool3("image_providers_status", "Check which AI image-generation providers have an API key configured (OpenAI gpt-image-2 and/or Google Nano Banana Pro). Call this BEFORE generate_image to decide whether to generate, to ask the user which provider to use, or to ask them to add a key.", {}, async () => {
21643
+ tool4("image_providers_status", "Check which AI image-generation providers have an API key configured (OpenAI gpt-image-2 and/or Google Nano Banana Pro). Call this BEFORE generate_image to decide whether to generate, to ask the user which provider to use, or to ask them to add a key.", {}, async () => {
21606
21644
  const s = await deps.status();
21607
21645
  const configured = [s.openai && "openai", s.google && "google"].filter(Boolean);
21608
- return text2(JSON.stringify({ openai: s.openai, google: s.google, anyConfigured: configured.length > 0, configured }));
21646
+ return text3(JSON.stringify({ openai: s.openai, google: s.google, anyConfigured: configured.length > 0, configured }));
21609
21647
  }),
21610
- tool3("generate_image", "Generate images from a text prompt (text-to-image) and display them to the user in the chat. Generates 4 by default. When source_image is set, generates variations seeded by that image (image-to-image). Requires a configured provider \u2014 call image_providers_status first; if none is configured do NOT call this, instead tell the user to add a key.", {
21648
+ tool4("generate_image", "Generate images from a text prompt (text-to-image) and display them to the user in the chat. Generates 4 by default. When source_image is set, generates variations seeded by that image (image-to-image). Requires a configured provider \u2014 call image_providers_status first; if none is configured do NOT call this, instead tell the user to add a key.", {
21611
21649
  prompt: external_exports.string().describe("What to generate \u2014 be descriptive."),
21612
21650
  provider: external_exports.enum(["openai", "google", "both"]).optional().describe("Which provider to use. Omit to auto-pick the only configured one. 'both' generates `count` images from each configured provider."),
21613
21651
  count: external_exports.number().int().min(1).max(8).optional().describe("How many images to generate (default 4)."),
@@ -21618,7 +21656,7 @@ function buildImagegenTools(deps) {
21618
21656
  const configured = ["openai", "google"].filter((p) => status2[p]);
21619
21657
  const want = args.provider === "both" ? [...configured] : args.provider ? [args.provider] : configured.slice(0, 1);
21620
21658
  if (!want.length) {
21621
- return text2("No image-generation provider is configured. Ask the user to add an OpenAI or Google key in Settings \u2192 Image editing before generating.", true);
21659
+ return text3("No image-generation provider is configured. Ask the user to add an OpenAI or Google key in Settings \u2192 Image editing before generating.", true);
21622
21660
  }
21623
21661
  const results = await Promise.all(want.map(async (provider) => {
21624
21662
  if (!status2[provider])
@@ -21631,11 +21669,11 @@ function buildImagegenTools(deps) {
21631
21669
  return { ok: false, summary: `${PROVIDER_LABEL[provider]}: failed \u2014 ${res.error ?? "unknown error"}` };
21632
21670
  }));
21633
21671
  const any2 = results.some((r) => r.ok);
21634
- return text2((any2 ? "Generated and displayed the images in the chat.\n" : "Image generation failed.\n") + results.map((r) => r.summary).join("\n"), !any2);
21672
+ return text3((any2 ? "Generated and displayed the images in the chat.\n" : "Image generation failed.\n") + results.map((r) => r.summary).join("\n"), !any2);
21635
21673
  })
21636
21674
  ];
21637
21675
  }
21638
- var PROVIDER_LABEL, text2;
21676
+ var PROVIDER_LABEL, text3;
21639
21677
  var init_imagegen_tools = __esm({
21640
21678
  "../../packages/agent-core/dist/imagegen-tools.js"() {
21641
21679
  "use strict";
@@ -21644,12 +21682,12 @@ var init_imagegen_tools = __esm({
21644
21682
  openai: "OpenAI (gpt-image-2)",
21645
21683
  google: "Google Nano Banana Pro (gemini-3-pro-image)"
21646
21684
  };
21647
- text2 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
21685
+ text3 = (t, isError = false) => ({ content: [{ type: "text", text: t }], ...isError ? { isError: true } : {} });
21648
21686
  }
21649
21687
  });
21650
21688
 
21651
21689
  // ../../packages/agent-core/dist/canvas-tools.js
21652
- import { tool as tool4 } from "@anthropic-ai/claude-agent-sdk";
21690
+ import { tool as tool5 } from "@anthropic-ai/claude-agent-sdk";
21653
21691
  import { mkdirSync as mkdirSync2, writeFileSync as writeFileSync3 } from "node:fs";
21654
21692
  import { join as join5 } from "node:path";
21655
21693
  function slugify3(s) {
@@ -21657,7 +21695,7 @@ function slugify3(s) {
21657
21695
  }
21658
21696
  function buildCanvasTools(deps) {
21659
21697
  return [
21660
- tool4("render_canvas", "Render an HTML document as a live, sandboxed Canvas docked beside the chat (like OpenAI Canvas), for INTERACTIVE or multi-part PROJECTS (apps, tools, dashboards, anything the user will interact with at size). For a SMALL self-contained snippet or animation, do NOT use this \u2014 instead just include it as a fenced ```html (or ```svg) code block in your reply; it renders live inline in the message. To TRANSFORM an existing canvas, call again with the SAME id and the full updated HTML \u2014 it re-renders in place. Before composing the HTML, consult the canvas-design skill for design fundamentals (and chart-design / diagram-design when the canvas is a chart or a diagram) so the result looks deliberately designed. Returns the canvas file path.", {
21698
+ tool5("render_canvas", "Render an HTML document as a live, sandboxed Canvas docked beside the chat (like OpenAI Canvas), for INTERACTIVE or multi-part PROJECTS (apps, tools, dashboards, anything the user will interact with at size). For a SMALL self-contained snippet or animation, do NOT use this \u2014 instead just include it as a fenced ```html (or ```svg) code block in your reply; it renders live inline in the message. To TRANSFORM an existing canvas, call again with the SAME id and the full updated HTML \u2014 it re-renders in place. Before composing the HTML, consult the canvas-design skill for design fundamentals (and chart-design / diagram-design when the canvas is a chart or a diagram) so the result looks deliberately designed. Returns the canvas file path.", {
21661
21699
  html: external_exports.string().describe("The full HTML document to render (include <html>/<body>; put CSS/JS inline)."),
21662
21700
  title: external_exports.string().optional().describe("Short title for the canvas tab."),
21663
21701
  id: external_exports.string().optional().describe("Stable id to UPDATE an existing canvas; omit to create a new one.")
@@ -21680,10 +21718,10 @@ var init_canvas_tools = __esm({
21680
21718
  });
21681
21719
 
21682
21720
  // ../../packages/agent-core/dist/surface-tools.js
21683
- import { tool as tool5 } from "@anthropic-ai/claude-agent-sdk";
21721
+ import { tool as tool6 } from "@anthropic-ai/claude-agent-sdk";
21684
21722
  function buildSurfaceTools(deps) {
21685
21723
  return [
21686
- tool5("open_surface", "Open a rich, live UI surface in the chat and return its surfaceId. Use for anything richer than text that the user watches or interacts with: a streaming progress panel, a table/chart that grows, a report, an interactive HTML/canvas mini-app. `content` carries the kind-specific body \u2014 markdown:{markdown}, html/canvas:{html}, image:{images:[{path,mime,alt?}]}, video:{src}, progress:{stages:[{label,status}],note?}, table:{columns,rows}, chart:{chart,series}, report:{report}, stream:{chunk|rows}. `placement`: inline (in the feed) | pinned (kept at the top while you keep working) | docked (side panel). Set `indefinite:true` for a live monitor that should keep updating past this turn. Then call update_surface to stream/patch it, and close_surface when done. For a small static snippet, just include it as a fenced code block instead.", {
21724
+ tool6("open_surface", "Open a rich, live UI surface in the chat and return its surfaceId. Use for anything richer than text that the user watches or interacts with: a streaming progress panel, a table/chart that grows, a report, an interactive HTML/canvas mini-app. `content` carries the kind-specific body \u2014 markdown:{markdown}, html/canvas:{html}, image:{images:[{path,mime,alt?}]}, video:{src}, progress:{stages:[{label,status}],note?}, table:{columns,rows}, chart:{chart,series}, report:{report}, stream:{chunk|rows}. `placement`: inline (in the feed) | pinned (kept at the top while you keep working) | docked (side panel). Set `indefinite:true` for a live monitor that should keep updating past this turn. Then call update_surface to stream/patch it, and close_surface when done. For a small static snippet, just include it as a fenced code block instead.", {
21687
21725
  kind: external_exports.enum(KINDS),
21688
21726
  title: external_exports.string().optional().describe("Short title shown on the surface."),
21689
21727
  placement: external_exports.enum(PLACEMENTS).optional().describe("inline | pinned | docked (default inline)."),
@@ -21697,7 +21735,7 @@ function buildSurfaceTools(deps) {
21697
21735
  return { content: [{ type: "text", text: `Could not open surface: ${e instanceof Error ? e.message : String(e)}` }] };
21698
21736
  }
21699
21737
  }),
21700
- tool5("update_surface", "Update an open surface. `op`: replace (swap the whole payload), patch (shallow-merge changed fields \u2014 e.g. a progress note), append (add a stream chunk / table rows / chart points). Set final:true when the surface is finished (it stops accepting updates and, if pinned, unpins into history).", {
21738
+ tool6("update_surface", "Update an open surface. `op`: replace (swap the whole payload), patch (shallow-merge changed fields \u2014 e.g. a progress note), append (add a stream chunk / table rows / chart points). Set final:true when the surface is finished (it stops accepting updates and, if pinned, unpins into history).", {
21701
21739
  surfaceId: external_exports.string(),
21702
21740
  op: external_exports.enum(OPS).optional().describe("replace | patch | append (default patch)."),
21703
21741
  content: external_exports.any().optional().describe("Kind-specific payload body or delta."),
@@ -21711,11 +21749,11 @@ function buildSurfaceTools(deps) {
21711
21749
  return { content: [{ type: "text", text: `Could not update surface ${args.surfaceId}: ${e instanceof Error ? e.message : String(e)}` }] };
21712
21750
  }
21713
21751
  }),
21714
- tool5("close_surface", "Close and dispose an open surface.", { surfaceId: external_exports.string() }, async (args) => {
21752
+ tool6("close_surface", "Close and dispose an open surface.", { surfaceId: external_exports.string() }, async (args) => {
21715
21753
  deps.close(args.surfaceId);
21716
21754
  return { content: [{ type: "text", text: `Closed surface ${args.surfaceId}.` }] };
21717
21755
  }),
21718
- tool5("wait_for_surface_event", 'Block until the next interaction on an interactive surface, then return it \u2014 e.g. the user makes a chess move, clicks, or submits a form. Drive an interactive surface in a loop: open_surface (HTML that calls window.tessSurface.emit(name,detail) on interaction) \u2192 wait_for_surface_event \u2192 act + update_surface(op:"patch", content:{data:{...}}) to redraw in place \u2192 wait again. Returns {name, detail}, or a note if the surface closed / timed out.', { surfaceId: external_exports.string(), timeoutSeconds: external_exports.number().optional().describe("Max seconds to wait (default 300).") }, async (args) => {
21756
+ tool6("wait_for_surface_event", 'Block until the next interaction on an interactive surface, then return it \u2014 e.g. the user makes a chess move, clicks, or submits a form. Drive an interactive surface in a loop: open_surface (HTML that calls window.tessSurface.emit(name,detail) on interaction) \u2192 wait_for_surface_event \u2192 act + update_surface(op:"patch", content:{data:{...}}) to redraw in place \u2192 wait again. Returns {name, detail}, or a note if the surface closed / timed out.', { surfaceId: external_exports.string(), timeoutSeconds: external_exports.number().optional().describe("Max seconds to wait (default 300).") }, async (args) => {
21719
21757
  const ev = await deps.waitForEvent(args.surfaceId, args.timeoutSeconds ? Math.round(args.timeoutSeconds * 1e3) : void 0);
21720
21758
  return { content: [{ type: "text", text: ev ? `Surface event on ${args.surfaceId}: ${JSON.stringify(ev)}` : `No event on ${args.surfaceId} (surface closed or timed out).` }] };
21721
21759
  })
@@ -21742,7 +21780,7 @@ var init_chess_surface_html_generated = __esm({
21742
21780
  });
21743
21781
 
21744
21782
  // ../../packages/agent-core/dist/chess-tools.js
21745
- import { tool as tool6 } from "@anthropic-ai/claude-agent-sdk";
21783
+ import { tool as tool7 } from "@anthropic-ai/claude-agent-sdk";
21746
21784
  async function commandRoundTrip(deps, surfaceId, command, replyName, timeoutMs = 2e4) {
21747
21785
  const seq2 = Date.now();
21748
21786
  deps.update(surfaceId, { op: "patch", content: { data: { command, seq: seq2 } } });
@@ -21758,7 +21796,7 @@ async function commandRoundTrip(deps, surfaceId, command, replyName, timeoutMs =
21758
21796
  }
21759
21797
  function buildChessTools(deps) {
21760
21798
  return [
21761
- tool6("play_chess", `Open an interactive chess board in the conversation so the user can play a full game against a built-in chess engine. The user plays White and moves by clicking a piece then its destination; the engine (Black) replies automatically \u2014 the board runs itself, so you do NOT make or narrate the moves. Call this whenever the user wants to play chess (e.g. "let's play chess", "start a game"). After it opens, briefly tell them the board is ready. To answer questions about the game or give a hint, call chess_status / chess_hint \u2014 do not guess the position.`, {}, async () => {
21799
+ tool7("play_chess", `Open an interactive chess board in the conversation so the user can play a full game against a built-in chess engine. The user plays White and moves by clicking a piece then its destination; the engine (Black) replies automatically \u2014 the board runs itself, so you do NOT make or narrate the moves. Call this whenever the user wants to play chess (e.g. "let's play chess", "start a game"). After it opens, briefly tell them the board is ready. To answer questions about the game or give a hint, call chess_status / chess_hint \u2014 do not guess the position.`, {}, async () => {
21762
21800
  try {
21763
21801
  liveChessSurfaceId = deps.open({
21764
21802
  kind: "html",
@@ -21776,7 +21814,7 @@ function buildChessTools(deps) {
21776
21814
  return { content: [{ type: "text", text: `Could not open the chess board: ${e instanceof Error ? e.message : String(e)}` }] };
21777
21815
  }
21778
21816
  }),
21779
- tool6("chess_status", 'Read the CURRENT state of the running chess board \u2014 FEN, move list (PGN/SAN), whose turn it is, and the result if the game is over. Use this before answering any question about the position ("whose turn?", "what happened?", "am I winning?") instead of guessing. Returns nothing useful if no board is open (call play_chess first).', {}, async () => {
21817
+ tool7("chess_status", 'Read the CURRENT state of the running chess board \u2014 FEN, move list (PGN/SAN), whose turn it is, and the result if the game is over. Use this before answering any question about the position ("whose turn?", "what happened?", "am I winning?") instead of guessing. Returns nothing useful if no board is open (call play_chess first).', {}, async () => {
21780
21818
  if (!liveChessSurfaceId)
21781
21819
  return { content: [{ type: "text", text: "No chess board is open. Call play_chess first." }] };
21782
21820
  const st = await commandRoundTrip(deps, liveChessSurfaceId, "report", "state");
@@ -21785,7 +21823,7 @@ function buildChessTools(deps) {
21785
21823
  return { content: [{ type: "text", text: `Current chess position:
21786
21824
  ${JSON.stringify(st, null, 2)}` }] };
21787
21825
  }),
21788
- tool6("chess_hint", `Ask the built-in engine for the best move in the CURRENT position and highlight it on the board for the user. Use when the user asks for a hint / help / "what should I play?". Returns the engine's suggested move (from-to). Only meaningful when it's the user's (White's) turn and a board is open.`, {}, async () => {
21826
+ tool7("chess_hint", `Ask the built-in engine for the best move in the CURRENT position and highlight it on the board for the user. Use when the user asks for a hint / help / "what should I play?". Returns the engine's suggested move (from-to). Only meaningful when it's the user's (White's) turn and a board is open.`, {}, async () => {
21789
21827
  if (!liveChessSurfaceId)
21790
21828
  return { content: [{ type: "text", text: "No chess board is open. Call play_chess first." }] };
21791
21829
  const hint = await commandRoundTrip(deps, liveChessSurfaceId, "hint", "hint", 25e3);
@@ -21793,13 +21831,13 @@ ${JSON.stringify(st, null, 2)}` }] };
21793
21831
  return { content: [{ type: "text", text: "Could not get a hint (the board may be mid-move or closed)." }] };
21794
21832
  return { content: [{ type: "text", text: `Engine hint (highlighted on the board): ${JSON.stringify(hint)}` }] };
21795
21833
  }),
21796
- tool6("chess_new_game", "Reset the open chess board to a fresh starting position (the user plays White and moves first). Use when the user wants to start over / play again / rematch.", {}, async () => {
21834
+ tool7("chess_new_game", "Reset the open chess board to a fresh starting position (the user plays White and moves first). Use when the user wants to start over / play again / rematch.", {}, async () => {
21797
21835
  if (!liveChessSurfaceId)
21798
21836
  return { content: [{ type: "text", text: "No chess board is open. Call play_chess first." }] };
21799
21837
  deps.update(liveChessSurfaceId, { op: "patch", content: { data: { command: "newgame", seq: Date.now() } } });
21800
21838
  return { content: [{ type: "text", text: "Started a fresh game \u2014 the board is reset, the user plays White and moves first." }] };
21801
21839
  }),
21802
- tool6("chess_set_difficulty", `Set the chess engine's strength on the open board. Use when the user asks to make it easier or harder (e.g. "go easy on me", "make it harder", "play your best"). Levels: easy (weak) \xB7 medium (default) \xB7 hard \xB7 max (full strength). Takes effect on the engine's next move.`, { level: external_exports.enum(["easy", "medium", "hard", "max"]) }, async (args) => {
21840
+ tool7("chess_set_difficulty", `Set the chess engine's strength on the open board. Use when the user asks to make it easier or harder (e.g. "go easy on me", "make it harder", "play your best"). Levels: easy (weak) \xB7 medium (default) \xB7 hard \xB7 max (full strength). Takes effect on the engine's next move.`, { level: external_exports.enum(["easy", "medium", "hard", "max"]) }, async (args) => {
21803
21841
  if (!liveChessSurfaceId)
21804
21842
  return { content: [{ type: "text", text: "No chess board is open. Call play_chess first." }] };
21805
21843
  deps.update(liveChessSurfaceId, { op: "patch", content: { data: { command: "level", level: args.level, seq: Date.now() } } });
@@ -21929,8 +21967,8 @@ function makeApi(deps, toolId, tier) {
21929
21967
  await h.close();
21930
21968
  return r.cancelled ? null : r.value ?? [];
21931
21969
  },
21932
- notify: async (text3, opts) => {
21933
- await api.open({ kind: "markdown", initial: { markdown: text3, level: opts?.level } });
21970
+ notify: async (text4, opts) => {
21971
+ await api.open({ kind: "markdown", initial: { markdown: text4, level: opts?.level } });
21934
21972
  }
21935
21973
  };
21936
21974
  return api;
@@ -21941,11 +21979,11 @@ function buildToolCtx(deps, sessionId, toolId, log4 = NOOP_LOG, tier = "third-pa
21941
21979
  return getSid();
21942
21980
  }, toolId, log: log4 };
21943
21981
  }
21944
- function wrapCtxTool(tool11, ctx2) {
21945
- const raw = tool11.__ctxHandler;
21982
+ function wrapCtxTool(tool12, ctx2) {
21983
+ const raw = tool12.__ctxHandler;
21946
21984
  if (typeof raw !== "function")
21947
- return tool11;
21948
- return { ...tool11, handler: async (args) => raw(args, ctx2) };
21985
+ return tool12;
21986
+ return { ...tool12, handler: async (args) => raw(args, ctx2) };
21949
21987
  }
21950
21988
  var NOOP_LOG;
21951
21989
  var init_surface_ctx = __esm({
@@ -22101,7 +22139,7 @@ var init_hook_bus = __esm({
22101
22139
  });
22102
22140
 
22103
22141
  // ../../packages/agent-core/dist/screen-control-tools.js
22104
- import { tool as tool7 } from "@anthropic-ai/claude-agent-sdk";
22142
+ import { tool as tool8 } from "@anthropic-ai/claude-agent-sdk";
22105
22143
  function specParametersJsonSchema(spec) {
22106
22144
  const properties = {};
22107
22145
  const required2 = [];
@@ -22122,9 +22160,9 @@ function zodShapeFromParams(params) {
22122
22160
  return shape;
22123
22161
  }
22124
22162
  function buildScreenControlSdkTools(p) {
22125
- return SCREEN_CONTROL_SPECS.map((spec) => tool7(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
22126
- const text3 = await p.exec(spec.name, args ?? {});
22127
- return { content: [{ type: "text", text: text3 || "Done." }] };
22163
+ return SCREEN_CONTROL_SPECS.map((spec) => tool8(spec.name, spec.description, zodShapeFromParams(spec.params), async (args) => {
22164
+ const text4 = await p.exec(spec.name, args ?? {});
22165
+ return { content: [{ type: "text", text: text4 || "Done." }] };
22128
22166
  }));
22129
22167
  }
22130
22168
  var ANNOTATE_STYLES, SCREEN_CONTROL_SPECS;
@@ -22239,7 +22277,7 @@ var init_screen_control_tools = __esm({
22239
22277
  });
22240
22278
 
22241
22279
  // ../../packages/agent-core/dist/computer-control-tools.js
22242
- import { tool as tool8 } from "@anthropic-ai/claude-agent-sdk";
22280
+ import { tool as tool9 } from "@anthropic-ai/claude-agent-sdk";
22243
22281
  function computerSpecParametersJsonSchema(spec) {
22244
22282
  const properties = {};
22245
22283
  const required2 = [];
@@ -22260,7 +22298,7 @@ function zodShapeFromParams2(params) {
22260
22298
  return shape;
22261
22299
  }
22262
22300
  function buildComputerControlSdkTools(p) {
22263
- return COMPUTER_CONTROL_SPECS.map((spec) => tool8(spec.name, spec.description, zodShapeFromParams2(spec.params), async (args) => {
22301
+ return COMPUTER_CONTROL_SPECS.map((spec) => tool9(spec.name, spec.description, zodShapeFromParams2(spec.params), async (args) => {
22264
22302
  if (spec.name === "see_screen") {
22265
22303
  const a = args ?? {};
22266
22304
  const region = a.x1 !== void 0 && a.y1 !== void 0 && a.x2 !== void 0 && a.y2 !== void 0 ? [a.y1, a.x1, a.y2, a.x2] : void 0;
@@ -22404,13 +22442,13 @@ WHEN YOUR REPLIES ARE READ ALOUD (voice): keep them SHORT and conversational \u2
22404
22442
  });
22405
22443
 
22406
22444
  // ../../packages/agent-core/dist/report-tools.js
22407
- import { tool as tool9 } from "@anthropic-ai/claude-agent-sdk";
22445
+ import { tool as tool10 } from "@anthropic-ai/claude-agent-sdk";
22408
22446
  function slug(s) {
22409
22447
  return s.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 40) || "mission";
22410
22448
  }
22411
22449
  function buildReportTools(deps) {
22412
22450
  return [
22413
- tool9("emit_report", `Deliver the structured findings of a mission playbook run as a Report card in the chat (this is the deliverable \u2014 do NOT just write findings as prose). Call it ONCE near the end with all findings grouped into the playbook's sections. To UPDATE after fixing/verifying a finding (Fix / Re-run), call again with the SAME id and finding ids, changing each finding's status \u2014 it re-renders in place. For "legal" bucket reports, never claim the site is compliant/certified; describe risks and route the verdict to a human.`, {
22451
+ tool10("emit_report", `Deliver the structured findings of a mission playbook run as a Report card in the chat (this is the deliverable \u2014 do NOT just write findings as prose). Call it ONCE near the end with all findings grouped into the playbook's sections. To UPDATE after fixing/verifying a finding (Fix / Re-run), call again with the SAME id and finding ids, changing each finding's status \u2014 it re-renders in place. For "legal" bucket reports, never claim the site is compliant/certified; describe risks and route the verdict to a human.`, {
22414
22452
  id: external_exports.string().optional().describe("Stable report id to UPDATE an existing report; omit on the first call to create one."),
22415
22453
  playbookId: external_exports.string().describe("The playbook id this report belongs to."),
22416
22454
  title: external_exports.string().describe("Report title (usually the playbook name)."),
@@ -22463,10 +22501,10 @@ var init_report_tools = __esm({
22463
22501
  });
22464
22502
 
22465
22503
  // ../../packages/agent-core/dist/interactive-ui-tools.js
22466
- import { tool as tool10 } from "@anthropic-ai/claude-agent-sdk";
22504
+ import { tool as tool11 } from "@anthropic-ai/claude-agent-sdk";
22467
22505
  function buildInteractiveUiTools(deps) {
22468
22506
  return [
22469
- tool10("ask_form", "Show the user a FORM in the chat and wait for them to fill it in. Use this to collect structured input mid-task (settings, scope, details) instead of asking in prose. Returns the submitted values (or that the user cancelled). Prefer this over free-text questions when the answer is structured.", {
22507
+ tool11("ask_form", "Show the user a FORM in the chat and wait for them to fill it in. Use this to collect structured input mid-task (settings, scope, details) instead of asking in prose. Returns the submitted values (or that the user cancelled). Prefer this over free-text questions when the answer is structured.", {
22470
22508
  title: external_exports.string().describe("Form heading (plain language)."),
22471
22509
  description: external_exports.string().optional().describe("Short explanation shown above the fields."),
22472
22510
  submitLabel: external_exports.string().optional().describe('Submit button label (default "Submit").'),
@@ -22480,7 +22518,7 @@ function buildInteractiveUiTools(deps) {
22480
22518
  return { content: [{ type: "text", text: `The user submitted the form:
22481
22519
  ${JSON.stringify(res.values ?? {}, null, 2)}` }] };
22482
22520
  }),
22483
- tool10("present_choices", "Show the user a CHOICE picker in the chat and wait for them to choose. Use this to let the user make a decision or pick from options (single or multi-select). Returns the selected value(s) (or cancellation).", {
22521
+ tool11("present_choices", "Show the user a CHOICE picker in the chat and wait for them to choose. Use this to let the user make a decision or pick from options (single or multi-select). Returns the selected value(s) (or cancellation).", {
22484
22522
  title: external_exports.string().describe("The question / heading."),
22485
22523
  description: external_exports.string().optional(),
22486
22524
  options: external_exports.array(choiceOption).min(1),
@@ -22493,7 +22531,7 @@ ${JSON.stringify(res.values ?? {}, null, 2)}` }] };
22493
22531
  return { content: [{ type: "text", text: "The user cancelled the choice (nothing selected)." }] };
22494
22532
  return { content: [{ type: "text", text: `The user selected: ${JSON.stringify(res.selected ?? [])}` }] };
22495
22533
  }),
22496
- tool10("update_progress", `Update the live Mission card so the user sees ongoing status. Call this whenever you move between stages (and once at the start). Pass the FULL ordered stage list each time with each stage's current status, plus a short "what I'm doing now" note. This is a one-way feedback channel \u2014 it returns immediately, does not wait for the user.`, {
22534
+ tool11("update_progress", `Update the live Mission card so the user sees ongoing status. Call this whenever you move between stages (and once at the start). Pass the FULL ordered stage list each time with each stage's current status, plus a short "what I'm doing now" note. This is a one-way feedback channel \u2014 it returns immediately, does not wait for the user.`, {
22497
22535
  stages: external_exports.array(external_exports.object({
22498
22536
  label: external_exports.string(),
22499
22537
  status: external_exports.enum(["pending", "active", "done"])
@@ -22608,8 +22646,8 @@ async function exportSession(sessionId, fromCwd) {
22608
22646
  function escapeRe(s) {
22609
22647
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
22610
22648
  }
22611
- function rekey(text3, fromCwd, toCwd) {
22612
- return text3.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
22649
+ function rekey(text4, fromCwd, toCwd) {
22650
+ return text4.replace(new RegExp(escapeRe(fromCwd) + '(?=["/\\\\]|$)', "g"), () => toCwd);
22613
22651
  }
22614
22652
  async function importSession(exp, toCwd) {
22615
22653
  const destDir = sessionDir(toCwd);
@@ -22862,13 +22900,13 @@ ${s.log.map((l) => `- ${l}`).join("\n")}` : "",
22862
22900
  ${activity}`,
22863
22901
  "One-line status of what it is doing now:"
22864
22902
  ].filter(Boolean).join("\n\n");
22865
- const text3 = (await cfg2.complete({ system, prompt, maxTokens: 48 }))?.trim().replace(/^["']|["']$/g, "");
22866
- if (text3 && text3 !== s.lastText) {
22867
- s.lastText = text3;
22868
- s.log.push(text3);
22903
+ const text4 = (await cfg2.complete({ system, prompt, maxTokens: 48 }))?.trim().replace(/^["']|["']$/g, "");
22904
+ if (text4 && text4 !== s.lastText) {
22905
+ s.lastText = text4;
22906
+ s.log.push(text4);
22869
22907
  if (s.log.length > LOG_CAP)
22870
22908
  s.log.shift();
22871
- this.emit(id, text3, cfg2.engineLabel);
22909
+ this.emit(id, text4, cfg2.engineLabel);
22872
22910
  }
22873
22911
  } catch {
22874
22912
  } finally {
@@ -23020,9 +23058,9 @@ function transcriptMatches(raw, q) {
23020
23058
  }
23021
23059
  return false;
23022
23060
  }
23023
- function stripPromptPrefix(text3) {
23061
+ function stripPromptPrefix(text4) {
23024
23062
  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");
23025
- const userLines = text3.split("\n").filter((l) => !isMetadata(l));
23063
+ const userLines = text4.split("\n").filter((l) => !isMetadata(l));
23026
23064
  return userLines.join("\n").trim();
23027
23065
  }
23028
23066
  function extractBlocks(message) {
@@ -23041,13 +23079,13 @@ function extractBlocks(message) {
23041
23079
  continue;
23042
23080
  const b = block;
23043
23081
  if (b.type === "thinking" && typeof b.thinking === "string") {
23044
- const text3 = b.thinking.trim();
23045
- if (text3)
23046
- blocks.push({ kind: "thinking", content: text3 });
23082
+ const text4 = b.thinking.trim();
23083
+ if (text4)
23084
+ blocks.push({ kind: "thinking", content: text4 });
23047
23085
  } else if (b.type === "text" && typeof b.text === "string") {
23048
- const text3 = b.text.trim();
23049
- if (text3 && !text3.startsWith("<ide_") && !text3.startsWith("<system-reminder>")) {
23050
- blocks.push({ kind: "text", content: text3 });
23086
+ const text4 = b.text.trim();
23087
+ if (text4 && !text4.startsWith("<ide_") && !text4.startsWith("<system-reminder>")) {
23088
+ blocks.push({ kind: "text", content: text4 });
23051
23089
  }
23052
23090
  } else if (b.type === "tool_use") {
23053
23091
  const name = b.name ?? "tool";
@@ -23093,9 +23131,9 @@ ${input.command}
23093
23131
  blocks.push({ kind: "tool_use", content: detail });
23094
23132
  } else if (b.type === "advisor_tool_result") {
23095
23133
  const c = b.content;
23096
- const text3 = c?.type === "advisor_result" ? (c.text ?? "").trim() : "";
23097
- if (text3)
23098
- blocks.push({ kind: "advisor", content: text3 });
23134
+ const text4 = c?.type === "advisor_result" ? (c.text ?? "").trim() : "";
23135
+ if (text4)
23136
+ blocks.push({ kind: "advisor", content: text4 });
23099
23137
  }
23100
23138
  }
23101
23139
  return blocks;
@@ -23762,8 +23800,8 @@ function describeSystemSubtype(subtype, m) {
23762
23800
  const updateKey = category === "hook" ? `hook:${String(m.hook_name ?? m.hook_event_name ?? subtype)}` : category === "task" ? `task:${String(m.task_id ?? subtype)}` : category === "telemetry" ? `sys:${subtype}` : void 0;
23763
23801
  return { category, name: subtype, title: humanizeName(subtype), fields: salientFields(m), ...updateKey ? { updateKey } : {} };
23764
23802
  }
23765
- const text3 = extractHumanReadable(m);
23766
- return { category: "unknown", name: subtype, title: `system/${subtype}`, ...text3 ? { detail: text3 } : {}, raw: rawFramePreview(m) };
23803
+ const text4 = extractHumanReadable(m);
23804
+ return { category: "unknown", name: subtype, title: `system/${subtype}`, ...text4 ? { detail: text4 } : {}, raw: rawFramePreview(m) };
23767
23805
  }
23768
23806
  function sstr(v) {
23769
23807
  return typeof v === "string" ? v : "";
@@ -23781,24 +23819,24 @@ function prettifyModel(id) {
23781
23819
  return known[id] ?? id.replace(/^claude-/, "").replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
23782
23820
  }
23783
23821
  function taskNotificationNotices(content) {
23784
- let text3 = "";
23822
+ let text4 = "";
23785
23823
  if (typeof content === "string")
23786
- text3 = content;
23824
+ text4 = content;
23787
23825
  else if (Array.isArray(content)) {
23788
23826
  for (const b of content) {
23789
23827
  if (b && typeof b === "object" && b.type === "text")
23790
- text3 += `${sstr(b.text)}
23828
+ text4 += `${sstr(b.text)}
23791
23829
  `;
23792
23830
  }
23793
23831
  }
23794
- if (!text3.includes("<task-notification>"))
23832
+ if (!text4.includes("<task-notification>"))
23795
23833
  return [];
23796
23834
  const tag = (xml2, name) => {
23797
23835
  const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(xml2);
23798
23836
  return m ? m[1].trim() : "";
23799
23837
  };
23800
23838
  const specs = [];
23801
- for (const m of text3.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
23839
+ for (const m of text4.matchAll(/<task-notification>([\s\S]*?)<\/task-notification>/g)) {
23802
23840
  const status2 = (tag(m[1], "status") || "completed").toLowerCase();
23803
23841
  const summary = tag(m[1], "summary") || "Background task finished.";
23804
23842
  const failed = /fail|error/.test(status2);
@@ -23809,10 +23847,10 @@ function taskNotificationNotices(content) {
23809
23847
  }
23810
23848
  return specs;
23811
23849
  }
23812
- function cleanTaskNotifications(text3) {
23813
- if (!text3.includes("<task-notification>"))
23814
- return text3;
23815
- return text3.replace(/<task-notification>([\s\S]*?)<\/task-notification>/g, (_all, inner) => {
23850
+ function cleanTaskNotifications(text4) {
23851
+ if (!text4.includes("<task-notification>"))
23852
+ return text4;
23853
+ return text4.replace(/<task-notification>([\s\S]*?)<\/task-notification>/g, (_all, inner) => {
23816
23854
  const g = (name) => {
23817
23855
  const m = new RegExp(`<${name}>([\\s\\S]*?)</${name}>`).exec(inner);
23818
23856
  return m ? m[1].trim() : "";
@@ -23825,10 +23863,10 @@ function cleanTaskNotifications(text3) {
23825
23863
  function buildNotice(subtype, m) {
23826
23864
  switch (subtype) {
23827
23865
  case "notification": {
23828
- const text3 = sstr(m.text) || "Notification";
23866
+ const text4 = sstr(m.text) || "Notification";
23829
23867
  const priority = ["low", "medium", "high", "immediate"].includes(sstr(m.priority)) ? m.priority : "medium";
23830
23868
  const level = priority === "immediate" ? "error" : priority === "high" ? "warning" : priority === "low" ? "info" : "notice";
23831
- return { category: "notification", level, priority, title: text3, toast: true, inline: true, ...typeof m.timeout_ms === "number" ? { timeoutMs: m.timeout_ms } : {} };
23869
+ return { category: "notification", level, priority, title: text4, toast: true, inline: true, ...typeof m.timeout_ms === "number" ? { timeoutMs: m.timeout_ms } : {} };
23832
23870
  }
23833
23871
  case "informational": {
23834
23872
  const content = sstr(m.content).trim();
@@ -23859,9 +23897,9 @@ function buildNotice(subtype, m) {
23859
23897
  return { category: "memory", level: "info", title: `Recalled ${memories.length} ${memories.length === 1 ? "memory" : "memories"}`, ...names.length ? { body: names.join(" \xB7 ") } : {}, toast: false, inline: true };
23860
23898
  }
23861
23899
  case "permission_denied": {
23862
- const tool11 = sstr(m.tool_name) || "a tool";
23900
+ const tool12 = sstr(m.tool_name) || "a tool";
23863
23901
  const reason = sstr(m.decision_reason) || sstr(m.message);
23864
- return { category: "permission", level: "warning", title: `Blocked: ${tool11}`, ...reason ? { body: reason } : {}, ...sstr(m.tool_use_id) ? { toolUseId: sstr(m.tool_use_id) } : {}, toast: true, inline: true };
23902
+ return { category: "permission", level: "warning", title: `Blocked: ${tool12}`, ...reason ? { body: reason } : {}, ...sstr(m.tool_use_id) ? { toolUseId: sstr(m.tool_use_id) } : {}, toast: true, inline: true };
23865
23903
  }
23866
23904
  case "model_refusal_fallback": {
23867
23905
  const orig = sstr(m.original_model);
@@ -23975,9 +24013,9 @@ ${plan}`;
23975
24013
  return name;
23976
24014
  }
23977
24015
  }
23978
- function computerToolPhrase(tool11, input) {
24016
+ function computerToolPhrase(tool12, input) {
23979
24017
  const s = (v) => typeof v === "string" ? v : "";
23980
- switch (tool11) {
24018
+ switch (tool12) {
23981
24019
  case "see_screen":
23982
24020
  return input.x1 !== void 0 ? "Looking closely at part of the screen" : "Looking at the screen";
23983
24021
  case "click":
@@ -24013,15 +24051,15 @@ function computerToolPhrase(tool11, input) {
24013
24051
  }
24014
24052
  }
24015
24053
  function flattenToolResultContent(content) {
24016
- let text3 = "";
24054
+ let text4 = "";
24017
24055
  if (typeof content === "string")
24018
- text3 = content;
24056
+ text4 = content;
24019
24057
  else if (Array.isArray(content)) {
24020
- text3 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
24058
+ text4 = content.filter((b) => b && typeof b === "object" && b.type === "text").map((b) => String(b.text ?? "")).join("\n");
24021
24059
  }
24022
- if (text3.length > TOOL_RESULT_CAP)
24023
- return { text: text3.slice(0, TOOL_RESULT_CAP), truncated: true };
24024
- return { text: text3, truncated: false };
24060
+ if (text4.length > TOOL_RESULT_CAP)
24061
+ return { text: text4.slice(0, TOOL_RESULT_CAP), truncated: true };
24062
+ return { text: text4, truncated: false };
24025
24063
  }
24026
24064
  function extractImages(content) {
24027
24065
  if (!Array.isArray(content))
@@ -24119,6 +24157,7 @@ var init_agent_manager = __esm({
24119
24157
  init_dist2();
24120
24158
  init_cron_tools();
24121
24159
  init_design_tools();
24160
+ init_support_tools();
24122
24161
  init_imagegen_tools();
24123
24162
  init_canvas_tools();
24124
24163
  init_surface_tools();
@@ -24281,6 +24320,9 @@ var init_agent_manager = __esm({
24281
24320
  hookBus = null;
24282
24321
  screenControlProvider = null;
24283
24322
  computerControlProvider = null;
24323
+ /** In-app issue reporter (`tesseract-support`: submit_issue). Non-null ⇒ NEW
24324
+ * conversations get the tool; the host does the collect-diagnostics + authed POST. */
24325
+ supportSubmit = null;
24284
24326
  /** M6 — scheduling. Built lazily by setCronConfig when cron is enabled. */
24285
24327
  cronStore = null;
24286
24328
  cronScheduler = null;
@@ -24402,6 +24444,11 @@ var init_agent_manager = __esm({
24402
24444
  setComputerControl(provider) {
24403
24445
  this.computerControlProvider = provider;
24404
24446
  }
24447
+ /** Inject the in-app issue reporter (`tesseract-support`: submit_issue). The provider
24448
+ * collects diagnostics + POSTs to the cloud API host-side (auth stays host-side). */
24449
+ setSupportSubmit(provider) {
24450
+ this.supportSubmit = provider;
24451
+ }
24405
24452
  /** M6 — enable/disable model-facing scheduling. When enabled, builds a CronStore
24406
24453
  * (durable at `file`/`storeDir` if given, else session-only), starts the scheduler
24407
24454
  * whose fires dispatch a turn, and exposes the Cron / Sleep / PushNotification tools
@@ -24473,7 +24520,7 @@ var init_agent_manager = __esm({
24473
24520
  this.onBrowserRequest = onBrowserRequest;
24474
24521
  const __dirname = dirname5(fileURLToPath(import.meta.url));
24475
24522
  this.browserCliPath = join9(__dirname, "browser-cli.js");
24476
- this.narrator = new Narrator((sessionId, text3, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text3, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
24523
+ this.narrator = new Narrator((sessionId, text4, engineLabel) => this.send({ type: "agent:narration", sessionId, text: text4, ...engineLabel ? { engineLabel } : {} }, this.liveSessions.get(sessionId)?.origin));
24477
24524
  }
24478
24525
  /** Inject (or clear) the cheap model used for the live status narration. The
24479
24526
  * host resolves creds and builds the completion fn (keeping secrets host-side). */
@@ -24686,10 +24733,10 @@ ${full.slice(-8e3)}`;
24686
24733
  parts.push(`The user's current request:
24687
24734
  ${live.lastPrompt.slice(0, 1400)}`);
24688
24735
  if (Array.isArray(live.lastAssistantContent)) {
24689
- const text3 = live.lastAssistantContent.filter((b) => b?.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
24690
- if (text3)
24736
+ const text4 = live.lastAssistantContent.filter((b) => b?.type === "text" && typeof b.text === "string").map((b) => b.text).join("\n").trim();
24737
+ if (text4)
24691
24738
  parts.push(`What the assistant just said (leading to this question):
24692
- ${text3.slice(0, 1600)}`);
24739
+ ${text4.slice(0, 1600)}`);
24693
24740
  }
24694
24741
  return parts.join("\n\n") || "No additional context available beyond the question itself.";
24695
24742
  }
@@ -24905,9 +24952,9 @@ ${qText}`;
24905
24952
  const transcripts = [];
24906
24953
  for (const sid of sessionIds) {
24907
24954
  const msgs = await this.sessionStore.getSessionMessages(sid).catch(() => []);
24908
- const text3 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${cleanTaskNotifications(m.content)}`).join("\n").slice(0, PER_SOURCE_CAP);
24909
- if (text3.trim())
24910
- transcripts.push(text3);
24955
+ const text4 = msgs.map((m) => `${m.role === "user" ? "User" : "Assistant"}: ${cleanTaskNotifications(m.content)}`).join("\n").slice(0, PER_SOURCE_CAP);
24956
+ if (text4.trim())
24957
+ transcripts.push(text4);
24911
24958
  }
24912
24959
  if (transcripts.length === 0)
24913
24960
  return;
@@ -25224,13 +25271,13 @@ CRITICAL RULES:
25224
25271
  ls.steerFlushTimer = setTimeout(() => this.flushSteer(ls), STEER_COALESCE_MS);
25225
25272
  return;
25226
25273
  }
25227
- const tail2 = live.queue[live.queue.length - 1];
25228
- if (tail2 && (tail2.origin ?? void 0) === (params.origin ?? void 0) && (tail2.sources === void 0 && params.sources === void 0 || tail2.sources !== void 0 && params.sources !== void 0 && sourcesEqual(tail2.sources, params.sources)) && typeof tail2.msg.message.content === "string") {
25229
- tail2.msg.message.content += "\n\n" + userText;
25274
+ const tail3 = live.queue[live.queue.length - 1];
25275
+ if (tail3 && (tail3.origin ?? void 0) === (params.origin ?? void 0) && (tail3.sources === void 0 && params.sources === void 0 || tail3.sources !== void 0 && params.sources !== void 0 && sourcesEqual(tail3.sources, params.sources)) && typeof tail3.msg.message.content === "string") {
25276
+ tail3.msg.message.content += "\n\n" + userText;
25230
25277
  if (params.browserId !== void 0)
25231
- tail2.browserId = params.browserId;
25278
+ tail3.browserId = params.browserId;
25232
25279
  if (params.windowId !== void 0)
25233
- tail2.windowId = params.windowId;
25280
+ tail3.windowId = params.windowId;
25234
25281
  return;
25235
25282
  }
25236
25283
  live.queue.push({
@@ -25440,6 +25487,9 @@ CRITICAL RULES:
25440
25487
  if (this.computerControlProvider) {
25441
25488
  mcp["tesseract-computer"] = createSdkMcpServer({ name: "tesseract-computer", version: "0.1.0", tools: buildComputerControlSdkTools(this.computerControlProvider) });
25442
25489
  }
25490
+ if (this.supportSubmit) {
25491
+ mcp["tesseract-support"] = createSdkMcpServer({ name: "tesseract-support", version: "0.1.0", tools: buildSupportTools(this.supportSubmit) });
25492
+ }
25443
25493
  {
25444
25494
  const projectDir = this.projectDir;
25445
25495
  const canvasTools = buildCanvasTools({
@@ -25867,9 +25917,9 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
25867
25917
  emit2({ type: "chat:stream", sessionId: sid, delta: "[thinking redacted]", messageId: message.uuid, kind: "thinking", ...parentField });
25868
25918
  } else if (cbt === "advisor_tool_result") {
25869
25919
  const res = event.content_block.content;
25870
- const text3 = res?.type === "advisor_result" ? (res.text ?? "").trim() : "";
25871
- if (text3 && parentToolUseId === void 0)
25872
- emit2({ type: "agent:advisor", sessionId: sid, text: text3 });
25920
+ const text4 = res?.type === "advisor_result" ? (res.text ?? "").trim() : "";
25921
+ if (text4 && parentToolUseId === void 0)
25922
+ emit2({ type: "agent:advisor", sessionId: sid, text: text4 });
25873
25923
  }
25874
25924
  }
25875
25925
  if (event.type === "content_block_delta") {
@@ -25884,26 +25934,26 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
25884
25934
  }
25885
25935
  }
25886
25936
  if (event.delta?.type === "text_delta" && event.delta.text) {
25887
- const text3 = event.delta.text;
25888
- if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text3)) {
25937
+ const text4 = event.delta.text;
25938
+ if (/<(?:tool_call|tool_result|function_calls|antml:function_calls)[\s>]/i.test(text4)) {
25889
25939
  insideXmlByKey.set(key2, true);
25890
25940
  break;
25891
25941
  }
25892
25942
  if (insideXmlByKey.get(key2)) {
25893
- if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text3)) {
25943
+ if (/<\/(?:tool_call|tool_result|function_calls|antml:function_calls)\s*>/i.test(text4)) {
25894
25944
  insideXmlByKey.set(key2, false);
25895
25945
  }
25896
25946
  break;
25897
25947
  }
25898
- if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text3))
25948
+ if (/<\/?(?:invoke|antml:invoke|antml:parameter)[\s>]/.test(text4))
25899
25949
  break;
25900
- if (/<parameter\s+name=/.test(text3))
25950
+ if (/<parameter\s+name=/.test(text4))
25901
25951
  break;
25902
- if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text3))
25952
+ if (/^\s*<\/(?:parameter|invoke|function_calls)>\s*$/.test(text4))
25903
25953
  break;
25904
25954
  if (parentToolUseId === void 0)
25905
25955
  turnStreamed = true;
25906
- const d = this.applyDeltaHook(text3, "text", sid);
25956
+ const d = this.applyDeltaHook(text4, "text", sid);
25907
25957
  if (d !== null)
25908
25958
  emit2({ type: "chat:stream", sessionId: sid, delta: d, messageId: message.uuid, kind: "text", ...parentField });
25909
25959
  }
@@ -26294,14 +26344,14 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
26294
26344
  const tn = toolNameByUseId.get(toolUseId);
26295
26345
  if (tn === "Edit" || tn === "Write" || tn === "MultiEdit" || tn === "NotebookEdit")
26296
26346
  continue;
26297
- const { text: text3, truncated } = flattenToolResultContent(blk.content);
26347
+ const { text: text4, truncated } = flattenToolResultContent(blk.content);
26298
26348
  const images = extractImages(blk.content);
26299
26349
  const isError = blk.is_error === true;
26300
- if (!text3 && images.length === 0 && !isError)
26350
+ if (!text4 && images.length === 0 && !isError)
26301
26351
  continue;
26302
- emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text3, images, truncated, ...agentId ? { agentId } : {} });
26352
+ emit2({ type: "agent:tool_result", sessionId: sid, toolUseId, isError, output: text4, images, truncated, ...agentId ? { agentId } : {} });
26303
26353
  if (isError && !agentId) {
26304
- const why = (text3 || "").replace(/```[\s\S]*?```/g, " ").replace(/[`*]/g, "").replace(/\s+/g, " ").trim().slice(0, 160);
26354
+ const why = (text4 || "").replace(/```[\s\S]*?```/g, " ").replace(/[`*]/g, "").replace(/\s+/g, " ").trim().slice(0, 160);
26305
26355
  this.narrator.observe(sid, `\u2192 that didn't work${why ? `: ${why}` : ""}`);
26306
26356
  }
26307
26357
  } else if (blk?.type === "web_search_tool_result") {
@@ -26333,12 +26383,12 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
26333
26383
  }
26334
26384
  default: {
26335
26385
  const m = message;
26336
- const text3 = extractHumanReadable(m);
26386
+ const text4 = extractHumanReadable(m);
26337
26387
  emitEvent({
26338
26388
  category: "unknown",
26339
26389
  name: m.type || "unknown",
26340
26390
  title: m.type || "unknown frame",
26341
- ...text3 ? { detail: text3 } : {},
26391
+ ...text4 ? { detail: text4 } : {},
26342
26392
  raw: rawFramePreview(m)
26343
26393
  }, parentToolUseId);
26344
26394
  log("unknown SDK message type surfaced with raw data:", m.type || "?");
@@ -26731,6 +26781,7 @@ __export(dist_exports, {
26731
26781
  buildComputerControlSdkTools: () => buildComputerControlSdkTools,
26732
26782
  buildImagegenTools: () => buildImagegenTools,
26733
26783
  buildScreenControlSdkTools: () => buildScreenControlSdkTools,
26784
+ buildSupportTools: () => buildSupportTools,
26734
26785
  buildToolCtx: () => buildToolCtx,
26735
26786
  bumpVersion: () => bumpVersion,
26736
26787
  computerSpecParametersJsonSchema: () => computerSpecParametersJsonSchema,
@@ -26782,6 +26833,7 @@ var init_dist4 = __esm({
26782
26833
  init_imagegen_tools();
26783
26834
  init_screen_control_tools();
26784
26835
  init_computer_control_tools();
26836
+ init_support_tools();
26785
26837
  init_design_tokens2();
26786
26838
  }
26787
26839
  });
@@ -28486,8 +28538,8 @@ var require_build = __commonJS({
28486
28538
  var BASE64_REGEX = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;
28487
28539
  var BASE64URL_REGEX = /^[a-zA-Z0-9-_]+$/;
28488
28540
  var Utf8Converter = class {
28489
- static fromString(text3) {
28490
- const s = unescape(encodeURIComponent(text3));
28541
+ static fromString(text4) {
28542
+ const s = unescape(encodeURIComponent(text4));
28491
28543
  const uintArray = new Uint8Array(s.length);
28492
28544
  for (let i = 0; i < s.length; i++) {
28493
28545
  uintArray[i] = s.charCodeAt(i);
@@ -28515,11 +28567,11 @@ var require_build = __commonJS({
28515
28567
  }
28516
28568
  return res;
28517
28569
  }
28518
- static fromString(text3, littleEndian = false) {
28519
- const res = new ArrayBuffer(text3.length * 2);
28570
+ static fromString(text4, littleEndian = false) {
28571
+ const res = new ArrayBuffer(text4.length * 2);
28520
28572
  const dataView = new DataView(res);
28521
- for (let i = 0; i < text3.length; i++) {
28522
- dataView.setUint16(i * 2, text3.charCodeAt(i), littleEndian);
28573
+ for (let i = 0; i < text4.length; i++) {
28574
+ dataView.setUint16(i * 2, text4.charCodeAt(i), littleEndian);
28523
28575
  }
28524
28576
  return res;
28525
28577
  }
@@ -28616,18 +28668,18 @@ var require_build = __commonJS({
28616
28668
  static ToBase64Url(data) {
28617
28669
  return this.ToBase64(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/\=/g, "");
28618
28670
  }
28619
- static FromUtf8String(text3, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
28671
+ static FromUtf8String(text4, encoding = _Convert.DEFAULT_UTF8_ENCODING) {
28620
28672
  switch (encoding) {
28621
28673
  case "ascii":
28622
- return this.FromBinary(text3);
28674
+ return this.FromBinary(text4);
28623
28675
  case "utf8":
28624
- return Utf8Converter.fromString(text3);
28676
+ return Utf8Converter.fromString(text4);
28625
28677
  case "utf16":
28626
28678
  case "utf16be":
28627
- return Utf16Converter.fromString(text3);
28679
+ return Utf16Converter.fromString(text4);
28628
28680
  case "utf16le":
28629
28681
  case "usc2":
28630
- return Utf16Converter.fromString(text3, true);
28682
+ return Utf16Converter.fromString(text4, true);
28631
28683
  default:
28632
28684
  throw new Error(`Unknown type of encoding '${encoding}'`);
28633
28685
  }
@@ -28648,11 +28700,11 @@ var require_build = __commonJS({
28648
28700
  throw new Error(`Unknown type of encoding '${encoding}'`);
28649
28701
  }
28650
28702
  }
28651
- static FromBinary(text3) {
28652
- const stringLength = text3.length;
28703
+ static FromBinary(text4) {
28704
+ const stringLength = text4.length;
28653
28705
  const resultView = new Uint8Array(stringLength);
28654
28706
  for (let i = 0; i < stringLength; i++) {
28655
- resultView[i] = text3.charCodeAt(i);
28707
+ resultView[i] = text4.charCodeAt(i);
28656
28708
  }
28657
28709
  return resultView.buffer;
28658
28710
  }
@@ -28698,8 +28750,8 @@ var require_build = __commonJS({
28698
28750
  static ToUtf16String(buffer, littleEndian = false) {
28699
28751
  return Utf16Converter.toString(buffer, littleEndian);
28700
28752
  }
28701
- static FromUtf16String(text3, littleEndian = false) {
28702
- return Utf16Converter.fromString(text3, littleEndian);
28753
+ static FromUtf16String(text4, littleEndian = false) {
28754
+ return Utf16Converter.fromString(text4, littleEndian);
28703
28755
  }
28704
28756
  static Base64Padding(base643) {
28705
28757
  const padCount = 4 - base643.length % 4;
@@ -32426,7 +32478,7 @@ var require_sequence = __commonJS({
32426
32478
  exports.startsWith = startsWith;
32427
32479
  exports.endsWith = endsWith;
32428
32480
  exports.slice = slice;
32429
- exports.tail = tail2;
32481
+ exports.tail = tail3;
32430
32482
  exports.copy = copy;
32431
32483
  exports.compare = compare;
32432
32484
  var buffer_source_js_1 = require_buffer_source();
@@ -32460,15 +32512,15 @@ var require_sequence = __commonJS({
32460
32512
  }
32461
32513
  return normalized;
32462
32514
  }
32463
- function encodeAscii(text3) {
32464
- const bytes = new Uint8Array(text3.length);
32465
- for (let i = 0; i < text3.length; i++) {
32466
- bytes[i] = text3.charCodeAt(i) & 255;
32515
+ function encodeAscii(text4) {
32516
+ const bytes = new Uint8Array(text4.length);
32517
+ for (let i = 0; i < text4.length; i++) {
32518
+ bytes[i] = text4.charCodeAt(i) & 255;
32467
32519
  }
32468
32520
  return bytes;
32469
32521
  }
32470
- function encodeUtf8(text3) {
32471
- return new TextEncoder().encode(text3);
32522
+ function encodeUtf8(text4) {
32523
+ return new TextEncoder().encode(text4);
32472
32524
  }
32473
32525
  function toPatternBytes(pattern, options) {
32474
32526
  if (typeof pattern === "string") {
@@ -32548,7 +32600,7 @@ var require_sequence = __commonJS({
32548
32600
  }
32549
32601
  return bytes.subarray(normalizedStart, normalizedEnd);
32550
32602
  }
32551
- function tail2(data, length) {
32603
+ function tail3(data, length) {
32552
32604
  const bytes = (0, buffer_source_js_1.toUint8Array)(data);
32553
32605
  const normalizedLength = Number.isFinite(length) ? Math.max(0, Math.trunc(length)) : 0;
32554
32606
  if (normalizedLength >= bytes.byteLength) {
@@ -33843,15 +33895,15 @@ var require_binary = __commonJS({
33843
33895
  }
33844
33896
  return result;
33845
33897
  }
33846
- function decode3(text3) {
33847
- const result = new Uint8Array(text3.length);
33848
- for (let i = 0; i < text3.length; i++) {
33849
- result[i] = text3.charCodeAt(i) & 255;
33898
+ function decode3(text4) {
33899
+ const result = new Uint8Array(text4.length);
33900
+ for (let i = 0; i < text4.length; i++) {
33901
+ result[i] = text4.charCodeAt(i) & 255;
33850
33902
  }
33851
33903
  return result;
33852
33904
  }
33853
- function is(text3) {
33854
- return typeof text3 === "string";
33905
+ function is(text4) {
33906
+ return typeof text4 === "string";
33855
33907
  }
33856
33908
  exports.binary = { encode: encode3, decode: decode3, is };
33857
33909
  }
@@ -33886,31 +33938,31 @@ var require_hex = __commonJS({
33886
33938
  throw new TypeError("Hex separators must be non-empty strings");
33887
33939
  }
33888
33940
  }
33889
- function matchSeparator(text3, index, separators) {
33941
+ function matchSeparator(text4, index, separators) {
33890
33942
  for (const separator of separators) {
33891
- if (text3.startsWith(separator, index)) {
33943
+ if (text4.startsWith(separator, index)) {
33892
33944
  return separator;
33893
33945
  }
33894
33946
  }
33895
33947
  return void 0;
33896
33948
  }
33897
- function detectCase(text3) {
33898
- const hasUpper = /[A-F]/.test(text3);
33899
- const hasLower = /[a-f]/.test(text3);
33949
+ function detectCase(text4) {
33950
+ const hasUpper = /[A-F]/.test(text4);
33951
+ const hasLower = /[a-f]/.test(text4);
33900
33952
  return hasUpper && !hasLower ? "upper" : "lower";
33901
33953
  }
33902
- function detectLineSeparator(text3) {
33903
- const match = /\r\n|\n/.exec(text3);
33954
+ function detectLineSeparator(text4) {
33955
+ const match = /\r\n|\n/.exec(text4);
33904
33956
  if (!match) {
33905
33957
  return void 0;
33906
33958
  }
33907
33959
  return match[0] === "\r\n" ? "\r\n" : "\n";
33908
33960
  }
33909
- function compactForDetection(text3) {
33910
- return text3.replace(/[^0-9a-f]/gi, "");
33961
+ function compactForDetection(text4) {
33962
+ return text4.replace(/[^0-9a-f]/gi, "");
33911
33963
  }
33912
- function detectGroup(text3) {
33913
- const segments = text3.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
33964
+ function detectGroup(text4) {
33965
+ const segments = text4.match(/[0-9A-Fa-f]+|[^0-9A-Fa-f]+/g) ?? [];
33914
33966
  if (segments.length < 3) {
33915
33967
  return void 0;
33916
33968
  }
@@ -33938,8 +33990,8 @@ var require_hex = __commonJS({
33938
33990
  separator
33939
33991
  };
33940
33992
  }
33941
- function detectFormat(text3) {
33942
- const trimmed = text3.trim();
33993
+ function detectFormat(text4) {
33994
+ const trimmed = text4.trim();
33943
33995
  const prefix = /^0x/i.test(trimmed) ? "0x" : "";
33944
33996
  const body = prefix ? trimmed.slice(2) : trimmed;
33945
33997
  const lineSeparator = detectLineSeparator(body);
@@ -33964,13 +34016,13 @@ var require_hex = __commonJS({
33964
34016
  }
33965
34017
  return format2;
33966
34018
  }
33967
- function normalizeText(text3, options) {
34019
+ function normalizeText(text4, options) {
33968
34020
  const allowPrefix = options.allowPrefix ?? true;
33969
34021
  const separators = [...resolveSeparators(options)].sort((left, right) => right.length - left.length);
33970
34022
  for (const separator of separators) {
33971
34023
  validateSeparator(separator);
33972
34024
  }
33973
- let working = text3.trim();
34025
+ let working = text4.trim();
33974
34026
  if (/^0x/i.test(working)) {
33975
34027
  if (!allowPrefix) {
33976
34028
  throw new TypeError("Hexadecimal text must not include a 0x prefix");
@@ -34021,15 +34073,15 @@ var require_hex = __commonJS({
34021
34073
  }
34022
34074
  return chunks.join(group.separator);
34023
34075
  }
34024
- function normalize2(text3, options = {}) {
34025
- return normalizeText(text3, options);
34076
+ function normalize2(text4, options = {}) {
34077
+ return normalizeText(text4, options);
34026
34078
  }
34027
- function is(text3, options = {}) {
34028
- if (typeof text3 !== "string") {
34079
+ function is(text4, options = {}) {
34080
+ if (typeof text4 !== "string") {
34029
34081
  return false;
34030
34082
  }
34031
34083
  try {
34032
- normalize2(text3, options);
34084
+ normalize2(text4, options);
34033
34085
  return true;
34034
34086
  } catch {
34035
34087
  return false;
@@ -34039,8 +34091,8 @@ var require_hex = __commonJS({
34039
34091
  const bytes = (0, index_js_1.toUint8Array)(data);
34040
34092
  const casing = options.case ?? "lower";
34041
34093
  const pairs = Array.from(bytes, (byte) => {
34042
- const text3 = byte.toString(16).padStart(2, "0");
34043
- return casing === "upper" ? text3.toUpperCase() : text3;
34094
+ const text4 = byte.toString(16).padStart(2, "0");
34095
+ return casing === "upper" ? text4.toUpperCase() : text4;
34044
34096
  });
34045
34097
  let body = "";
34046
34098
  if (options.line) {
@@ -34059,19 +34111,19 @@ var require_hex = __commonJS({
34059
34111
  }
34060
34112
  return `${options.prefix ?? ""}${body}`;
34061
34113
  }
34062
- function decode3(text3, options = {}) {
34063
- const normalized = normalize2(text3, options);
34114
+ function decode3(text4, options = {}) {
34115
+ const normalized = normalize2(text4, options);
34064
34116
  const result = new Uint8Array(normalized.length / 2);
34065
34117
  for (let i = 0; i < normalized.length; i += 2) {
34066
34118
  result[i / 2] = Number.parseInt(normalized.slice(i, i + 2), 16);
34067
34119
  }
34068
34120
  return result;
34069
34121
  }
34070
- function parse3(text3, options = {}) {
34071
- const normalized = normalize2(text3, options);
34122
+ function parse3(text4, options = {}) {
34123
+ const normalized = normalize2(text4, options);
34072
34124
  return {
34073
34125
  bytes: decode3(normalized),
34074
- format: detectFormat(text3),
34126
+ format: detectFormat(text4),
34075
34127
  normalized
34076
34128
  };
34077
34129
  }
@@ -34099,8 +34151,8 @@ var require_utf8 = __commonJS({
34099
34151
  exports.encode = encode3;
34100
34152
  exports.decode = decode3;
34101
34153
  var index_js_1 = require_bytes();
34102
- function encode3(text3) {
34103
- return new TextEncoder().encode(text3);
34154
+ function encode3(text4) {
34155
+ return new TextEncoder().encode(text4);
34104
34156
  }
34105
34157
  function decode3(data) {
34106
34158
  return new TextDecoder("utf-8", { fatal: false }).decode((0, index_js_1.toUint8Array)(data));
@@ -34118,11 +34170,11 @@ var require_utf16 = __commonJS({
34118
34170
  exports.encode = encode3;
34119
34171
  exports.decode = decode3;
34120
34172
  var index_js_1 = require_bytes();
34121
- function encode3(text3, options = {}) {
34122
- const result = new ArrayBuffer(text3.length * 2);
34173
+ function encode3(text4, options = {}) {
34174
+ const result = new ArrayBuffer(text4.length * 2);
34123
34175
  const view = new DataView(result);
34124
- for (let i = 0; i < text3.length; i++) {
34125
- view.setUint16(i * 2, text3.charCodeAt(i), options.littleEndian ?? false);
34176
+ for (let i = 0; i < text4.length; i++) {
34177
+ view.setUint16(i * 2, text4.charCodeAt(i), options.littleEndian ?? false);
34126
34178
  }
34127
34179
  return new Uint8Array(result);
34128
34180
  }
@@ -34156,18 +34208,18 @@ var require_base64 = __commonJS({
34156
34208
  function nodeBuffer() {
34157
34209
  return globalThis.Buffer;
34158
34210
  }
34159
- function normalize2(text3) {
34160
- return text3.replace(/[\n\r\t ]/g, "");
34211
+ function normalize2(text4) {
34212
+ return text4.replace(/[\n\r\t ]/g, "");
34161
34213
  }
34162
- function pad(text3) {
34163
- const remainder = text3.length % 4;
34164
- return remainder ? text3 + "=".repeat(4 - remainder) : text3;
34214
+ function pad(text4) {
34215
+ const remainder = text4.length % 4;
34216
+ return remainder ? text4 + "=".repeat(4 - remainder) : text4;
34165
34217
  }
34166
- function is(text3) {
34167
- if (typeof text3 !== "string") {
34218
+ function is(text4) {
34219
+ if (typeof text4 !== "string") {
34168
34220
  return false;
34169
34221
  }
34170
- const normalized = normalize2(text3);
34222
+ const normalized = normalize2(text4);
34171
34223
  return normalized === "" || BASE64_REGEX.test(normalized);
34172
34224
  }
34173
34225
  function encode3(data, _options) {
@@ -34178,8 +34230,8 @@ var require_base64 = __commonJS({
34178
34230
  }
34179
34231
  return btoa((0, binary_js_1.encode)(bytes));
34180
34232
  }
34181
- function decode3(text3, _options) {
34182
- const normalized = normalize2(text3);
34233
+ function decode3(text4, _options) {
34234
+ const normalized = normalize2(text4);
34183
34235
  if (!is(normalized)) {
34184
34236
  throw new TypeError("Input is not valid Base64 text");
34185
34237
  }
@@ -34205,17 +34257,17 @@ var require_base64url = __commonJS({
34205
34257
  exports.decode = decode3;
34206
34258
  var base64_js_1 = require_base64();
34207
34259
  var BASE64URL_REGEX = /^[A-Za-z0-9_-]*$/;
34208
- function normalize2(text3) {
34209
- return text3.replace(/[\n\r\t ]/g, "");
34260
+ function normalize2(text4) {
34261
+ return text4.replace(/[\n\r\t ]/g, "");
34210
34262
  }
34211
- function is(text3) {
34212
- return typeof text3 === "string" && BASE64URL_REGEX.test(normalize2(text3));
34263
+ function is(text4) {
34264
+ return typeof text4 === "string" && BASE64URL_REGEX.test(normalize2(text4));
34213
34265
  }
34214
34266
  function encode3(data, _options) {
34215
34267
  return base64_js_1.base64.encode(data).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
34216
34268
  }
34217
- function decode3(text3, _options) {
34218
- const normalized = normalize2(text3);
34269
+ function decode3(text4, _options) {
34270
+ const normalized = normalize2(text4);
34219
34271
  if (!is(normalized)) {
34220
34272
  throw new TypeError("Input is not valid Base64Url text");
34221
34273
  }
@@ -34336,8 +34388,8 @@ var require_ip_converter = __commonJS({
34336
34388
  }
34337
34389
  return ip;
34338
34390
  }
34339
- static parseCIDR(text3) {
34340
- const [addr, prefixStr] = text3.split("/");
34391
+ static parseCIDR(text4) {
34392
+ const [addr, prefixStr] = text4.split("/");
34341
34393
  const prefix = parseInt(prefixStr, 10);
34342
34394
  if (this.isIPv4(addr)) {
34343
34395
  if (prefix < 0 || prefix > 32) {
@@ -34390,9 +34442,9 @@ var require_ip_converter = __commonJS({
34390
34442
  }
34391
34443
  return this.decodeIP(encoding_1.hex.encode(buf));
34392
34444
  }
34393
- static fromString(text3) {
34394
- if (text3.includes("/")) {
34395
- const [addr, prefix] = this.parseCIDR(text3);
34445
+ static fromString(text4) {
34446
+ if (text4.includes("/")) {
34447
+ const [addr, prefix] = this.parseCIDR(text4);
34396
34448
  const maskBytes = new Uint8Array(addr.length);
34397
34449
  let bitsLeft = prefix;
34398
34450
  for (let i = 0; i < maskBytes.length; i++) {
@@ -34409,7 +34461,7 @@ var require_ip_converter = __commonJS({
34409
34461
  out.set(maskBytes, addr.length);
34410
34462
  return out.buffer;
34411
34463
  }
34412
- const bytes = this.isIPv4(text3) ? this.parseIPv4(text3) : this.parseIPv6(text3);
34464
+ const bytes = this.isIPv4(text4) ? this.parseIPv4(text4) : this.parseIPv6(text4);
34413
34465
  return new Uint8Array(bytes).buffer;
34414
34466
  }
34415
34467
  };
@@ -42089,24 +42141,24 @@ var require_x509_cjs = __commonJS({
42089
42141
  names.register("I", "2.5.4.43");
42090
42142
  names.register("SN", "2.5.4.4");
42091
42143
  names.register("T", "2.5.4.12");
42092
- function replaceUnknownCharacter(text3, char) {
42144
+ function replaceUnknownCharacter(text4, char) {
42093
42145
  return `\\${pvtsutils.Convert.ToHex(pvtsutils.Convert.FromUtf8String(char)).toUpperCase()}`;
42094
42146
  }
42095
42147
  function escape2(data) {
42096
42148
  return data.replace(/([,+"\\<>;])/g, "\\$1").replace(/^([ #])/, "\\$1").replace(/([ ]$)/, "\\$1").replace(/([\r\n\t])/, replaceUnknownCharacter);
42097
42149
  }
42098
42150
  var Name = class _Name {
42099
- static isASCII(text3) {
42100
- for (let i = 0; i < text3.length; i++) {
42101
- const code = text3.charCodeAt(i);
42151
+ static isASCII(text4) {
42152
+ for (let i = 0; i < text4.length; i++) {
42153
+ const code = text4.charCodeAt(i);
42102
42154
  if (code > 255) {
42103
42155
  return false;
42104
42156
  }
42105
42157
  }
42106
42158
  return true;
42107
42159
  }
42108
- static isPrintableString(text3) {
42109
- return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text3);
42160
+ static isPrintableString(text4) {
42161
+ return /^[A-Za-z0-9 '()+,-./:=?]*$/g.test(text4);
42110
42162
  }
42111
42163
  constructor(data, extraNames = {}) {
42112
42164
  this.extraNames = new NameIdentifier();
@@ -46707,12 +46759,12 @@ import { createHash as createHash5 } from "node:crypto";
46707
46759
  import { spawn as spawn9 } from "node:child_process";
46708
46760
  import { fileURLToPath as fileURLToPath2 } from "node:url";
46709
46761
  import { homedir as homedir16 } from "node:os";
46710
- import { dirname as dirname17, join as join40, resolve as resolve9 } from "node:path";
46762
+ import { dirname as dirname17, join as join41, resolve as resolve9 } from "node:path";
46711
46763
  import { createInterface } from "node:readline/promises";
46712
46764
 
46713
46765
  // ../../packages/host-core/dist/control-link.js
46714
46766
  import { hostname as hostname3 } from "node:os";
46715
- import { join as join31, basename as basename6 } from "node:path";
46767
+ import { join as join32, basename as basename6 } from "node:path";
46716
46768
  import { mkdirSync as mkdirSync12 } from "node:fs";
46717
46769
 
46718
46770
  // ../../node_modules/ws/wrapper.mjs
@@ -46734,15 +46786,15 @@ function canonicalForGuard(p) {
46734
46786
  const abs = resolve(p);
46735
46787
  let dir2 = dirname(abs);
46736
46788
  const leaf = basename(abs);
46737
- const tail2 = [];
46789
+ const tail3 = [];
46738
46790
  for (; ; ) {
46739
46791
  try {
46740
- return join(realpathSync.native(dir2), ...tail2, leaf);
46792
+ return join(realpathSync.native(dir2), ...tail3, leaf);
46741
46793
  } catch {
46742
46794
  const parent = dirname(dir2);
46743
46795
  if (parent === dir2)
46744
46796
  return abs;
46745
- tail2.unshift(basename(dir2));
46797
+ tail3.unshift(basename(dir2));
46746
46798
  dir2 = parent;
46747
46799
  }
46748
46800
  }
@@ -47135,7 +47187,7 @@ var E2ESessions = class {
47135
47187
  };
47136
47188
 
47137
47189
  // ../../packages/host-core/dist/daemon-agent.js
47138
- import { join as join19 } from "node:path";
47190
+ import { join as join20 } from "node:path";
47139
47191
 
47140
47192
  // ../../packages/host-core/dist/surface-hub.js
47141
47193
  init_dist();
@@ -47630,6 +47682,7 @@ async function createClaudeCodeBackend(send3, onBrowserRequest, loadPluginRuntim
47630
47682
  setImageGen: (runner3) => manager2.setImageGen(runner3),
47631
47683
  setScreenControl: (provider) => manager2.setScreenControl(provider),
47632
47684
  setComputerControl: (provider) => manager2.setComputerControl(provider),
47685
+ setSupportSubmit: (provider) => manager2.setSupportSubmit(provider),
47633
47686
  setRunMode: (sessionId, opts) => manager2.setRunMode(sessionId, opts),
47634
47687
  setSessionKeepAlive: (sessionId, keep, holder) => manager2.setSessionKeepAlive(sessionId, keep, holder),
47635
47688
  warmSession: (params) => manager2.warmSession(params),
@@ -47959,9 +48012,9 @@ var geminiAdapter = {
47959
48012
  },
47960
48013
  translate(event, raw, emit2, ctx2) {
47961
48014
  const o = asObj3(event);
47962
- const text3 = o ? typeof o.response === "string" ? o.response : bestEffortText(o) : typeof event === "string" ? event : raw;
47963
- if (text3)
47964
- emit2({ type: "chat:stream", sessionId: ctx2.sessionId, clientRequestId: ctx2.clientRequestId, delta: text3, messageId: ctx2.messageId, kind: "text" });
48015
+ const text4 = o ? typeof o.response === "string" ? o.response : bestEffortText(o) : typeof event === "string" ? event : raw;
48016
+ if (text4)
48017
+ emit2({ type: "chat:stream", sessionId: ctx2.sessionId, clientRequestId: ctx2.clientRequestId, delta: text4, messageId: ctx2.messageId, kind: "text" });
47965
48018
  const tools = o?.tools;
47966
48019
  if (Array.isArray(tools)) {
47967
48020
  for (const t of tools) {
@@ -47987,25 +48040,25 @@ var openclawAdapter = {
47987
48040
  translate(event, raw, emit2, ctx2) {
47988
48041
  const o = asObj4(event);
47989
48042
  const result = asObj4(o?.result) ?? o;
47990
- let text3 = "";
48043
+ let text4 = "";
47991
48044
  const payloads = result?.payloads;
47992
48045
  if (Array.isArray(payloads)) {
47993
- text3 = payloads.map((p) => {
48046
+ text4 = payloads.map((p) => {
47994
48047
  const t = asObj4(p)?.text;
47995
48048
  return typeof t === "string" ? t : "";
47996
48049
  }).filter(Boolean).join("\n");
47997
48050
  }
47998
- if (!text3) {
48051
+ if (!text4) {
47999
48052
  const fav = asObj4(result?.meta)?.finalAssistantVisibleText;
48000
48053
  if (typeof fav === "string")
48001
- text3 = fav;
48054
+ text4 = fav;
48002
48055
  }
48003
- if (!text3)
48004
- text3 = o ? bestEffortText(result ?? o) : typeof event === "string" ? event : raw;
48005
- if (text3)
48006
- emit2({ type: "chat:stream", sessionId: ctx2.sessionId, clientRequestId: ctx2.clientRequestId, delta: text3, messageId: ctx2.messageId, kind: "text" });
48056
+ if (!text4)
48057
+ text4 = o ? bestEffortText(result ?? o) : typeof event === "string" ? event : raw;
48058
+ if (text4)
48059
+ emit2({ type: "chat:stream", sessionId: ctx2.sessionId, clientRequestId: ctx2.clientRequestId, delta: text4, messageId: ctx2.messageId, kind: "text" });
48007
48060
  const status2 = typeof o?.status === "string" ? o.status : void 0;
48008
- if (!text3 && status2 && status2 !== "ok" && status2 !== "accepted") {
48061
+ if (!text4 && status2 && status2 !== "ok" && status2 !== "accepted") {
48009
48062
  const summary = typeof o?.summary === "string" && o.summary ? o.summary : `OpenClaw run ${status2}.`;
48010
48063
  emit2({ type: "chat:error", sessionId: ctx2.sessionId, clientRequestId: ctx2.clientRequestId, error: summary });
48011
48064
  }
@@ -48057,8 +48110,8 @@ var seq = 0;
48057
48110
  var now = () => (/* @__PURE__ */ new Date()).toISOString();
48058
48111
  var ctx = [];
48059
48112
  var CTX_MAX = 60;
48060
- function pushCtx(role, text3) {
48061
- const t = (text3 ?? "").trim();
48113
+ function pushCtx(role, text4) {
48114
+ const t = (text4 ?? "").trim();
48062
48115
  if (!t)
48063
48116
  return;
48064
48117
  ctx.push({ role, text: t.length > 300 ? `${t.slice(0, 300)}\u2026` : t });
@@ -48300,23 +48353,23 @@ var HostPluginApi = class {
48300
48353
  secret(envKey2) {
48301
48354
  return this.secretResolver(this.pluginId, envKey2);
48302
48355
  }
48303
- registerTool(tool11) {
48356
+ registerTool(tool12) {
48304
48357
  const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
48305
- const name = tool11.name.startsWith(`${prefix}_`) ? tool11.name : `${prefix}_${tool11.name}`;
48306
- this.registry.tools.push({ ...tool11, name });
48358
+ const name = tool12.name.startsWith(`${prefix}_`) ? tool12.name : `${prefix}_${tool12.name}`;
48359
+ this.registry.tools.push({ ...tool12, name });
48307
48360
  }
48308
- registerUiTool(tool11) {
48309
- if (!this.requireGrant("surfaces", `UI tool "${tool11.name}"`))
48361
+ registerUiTool(tool12) {
48362
+ if (!this.requireGrant("surfaces", `UI tool "${tool12.name}"`))
48310
48363
  return;
48311
48364
  const prefix = this.pluginId.replace(/[^a-zA-Z0-9_]/g, "_");
48312
- const name = tool11.name.startsWith(`${prefix}_`) ? tool11.name : `${prefix}_${tool11.name}`;
48365
+ const name = tool12.name.startsWith(`${prefix}_`) ? tool12.name : `${prefix}_${tool12.name}`;
48313
48366
  const tier = this.hasGrant("customUI") ? "verified" : "third-party";
48314
48367
  this.registry.tools.push({
48315
48368
  name,
48316
- description: tool11.description,
48317
- inputSchema: tool11.inputSchema,
48318
- handler: async (args) => toResult(await tool11.handler(args, NOOP_UI_CTX)),
48319
- __ctxHandler: async (args, ctx2) => toResult(await tool11.handler(args, ctx2)),
48369
+ description: tool12.description,
48370
+ inputSchema: tool12.inputSchema,
48371
+ handler: async (args) => toResult(await tool12.handler(args, NOOP_UI_CTX)),
48372
+ __ctxHandler: async (args, ctx2) => toResult(await tool12.handler(args, ctx2)),
48320
48373
  __tier: tier
48321
48374
  });
48322
48375
  }
@@ -48426,8 +48479,8 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry2) {
48426
48479
  pluginId,
48427
48480
  config: config2,
48428
48481
  secret: (envKey2) => secretResolver(pluginId, envKey2),
48429
- registerTool: (tool11) => {
48430
- const got = typeof tool11 === "function" ? tool11({}) : tool11;
48482
+ registerTool: (tool12) => {
48483
+ const got = typeof tool12 === "function" ? tool12({}) : tool12;
48431
48484
  const arr = Array.isArray(got) ? got : got ? [got] : [];
48432
48485
  for (const t of arr) {
48433
48486
  const c = convertTool(t);
@@ -49124,9 +49177,9 @@ function augmentedPath() {
49124
49177
  return parts.join(sep8);
49125
49178
  }
49126
49179
  function which(bin, path5) {
49127
- const tool11 = process.platform === "win32" ? "where" : "which";
49180
+ const tool12 = process.platform === "win32" ? "where" : "which";
49128
49181
  try {
49129
- const out = execFileSync2(tool11, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
49182
+ const out = execFileSync2(tool12, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
49130
49183
  return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
49131
49184
  } catch {
49132
49185
  return void 0;
@@ -49841,8 +49894,8 @@ function iso639(lang) {
49841
49894
  // ../../packages/voice-core/dist/pipeline/history.js
49842
49895
  function formatHistoryLines(turns, maxLineChars = 300) {
49843
49896
  return turns.map((t) => {
49844
- const text3 = t.text.replace(/\s+/g, " ").trim();
49845
- const capped = text3.length > maxLineChars ? text3.slice(0, maxLineChars - 1).trimEnd() + "\u2026" : text3;
49897
+ const text4 = t.text.replace(/\s+/g, " ").trim();
49898
+ const capped = text4.length > maxLineChars ? text4.slice(0, maxLineChars - 1).trimEnd() + "\u2026" : text4;
49846
49899
  return `${t.role.toUpperCase()}: ${capped}`;
49847
49900
  }).join("\n");
49848
49901
  }
@@ -50131,15 +50184,15 @@ ${truncate(input.result, 4e3)}`
50131
50184
  }
50132
50185
  };
50133
50186
  function ruleBasedTurn(input) {
50134
- const text3 = input.result.trim();
50135
- const lower = text3.toLowerCase();
50187
+ const text4 = input.result.trim();
50188
+ const lower = text4.toLowerCase();
50136
50189
  let status2 = "done";
50137
50190
  if (/\b(error|failed|could not|cannot|unable to)\b/.test(lower))
50138
50191
  status2 = "error";
50139
- else if (text3.endsWith("?") || /\b(which|should i|do you want|would you like|please confirm|clarif)\b/.test(lower)) {
50192
+ else if (text4.endsWith("?") || /\b(which|should i|do you want|would you like|please confirm|clarif)\b/.test(lower)) {
50140
50193
  status2 = "needs_input";
50141
50194
  }
50142
- const line = firstSentences(stripForSpeech(text3)) || input.recentActivity.slice(-1)[0] || "Done.";
50195
+ const line = firstSentences(stripForSpeech(text4)) || input.recentActivity.slice(-1)[0] || "Done.";
50143
50196
  return { line, status: status2 };
50144
50197
  }
50145
50198
  function stripForSpeech(s) {
@@ -50224,8 +50277,8 @@ var VoiceGuideOrchestrator = class {
50224
50277
  /** The bridge feeds every finalized transcript line here (capped buffer). An
50225
50278
  * assistant line means the guide finished speaking — drain the next queued
50226
50279
  * update immediately instead of waiting out the gap timer. */
50227
- noteTranscript(role, text3) {
50228
- const t = text3.trim();
50280
+ noteTranscript(role, text4) {
50281
+ const t = text4.trim();
50229
50282
  if (!t)
50230
50283
  return;
50231
50284
  this.conversation.push({ role, text: t });
@@ -50759,26 +50812,26 @@ Additional context: ${context}` : task;
50759
50812
  this.deps.emit({ type: "voice:milestone", text: spoken });
50760
50813
  this.say(spoken, { urgent: focused });
50761
50814
  }
50762
- speakMilestone(text3) {
50763
- this.deps.emit({ type: "voice:milestone", text: text3 });
50764
- this.say(text3);
50815
+ speakMilestone(text4) {
50816
+ this.deps.emit({ type: "voice:milestone", text: text4 });
50817
+ this.say(text4);
50765
50818
  }
50766
50819
  // ── One mouth, N sessions: serialized speech ───────────────────────────────
50767
50820
  /** Speak `text`, serializing non-urgent lines so concurrent sessions don't
50768
50821
  * talk over each other. Urgent lines (blocking questions, the focused
50769
50822
  * session's result, critical notices) always go out immediately. */
50770
- say(text3, opts = {}) {
50771
- if (!text3)
50823
+ say(text4, opts = {}) {
50824
+ if (!text4)
50772
50825
  return;
50773
50826
  const now2 = this.now();
50774
50827
  if (opts.urgent || this.sayQueue.length === 0 && now2 - this.lastSayAt >= SPEAK_GAP_MS) {
50775
50828
  this.lastSayAt = now2;
50776
- this.voice?.speakNow(text3);
50829
+ this.voice?.speakNow(text4);
50777
50830
  return;
50778
50831
  }
50779
50832
  if (this.sayQueue.length >= SPEAK_QUEUE_CAP)
50780
50833
  this.sayQueue.shift();
50781
- this.sayQueue.push(text3);
50834
+ this.sayQueue.push(text4);
50782
50835
  this.armSayTimer();
50783
50836
  }
50784
50837
  armSayTimer() {
@@ -50908,11 +50961,11 @@ var ClientProxyProvider = class {
50908
50961
  /** Audio is client↔provider direct — the daemon never sees mic/model PCM. */
50909
50962
  sendAudio(_pcm24k) {
50910
50963
  }
50911
- respondToTool(callId, text3, isError) {
50912
- this.deps.send({ type: "voice:cd:respondToTool", callId, text: text3, isError });
50964
+ respondToTool(callId, text4, isError) {
50965
+ this.deps.send({ type: "voice:cd:respondToTool", callId, text: text4, isError });
50913
50966
  }
50914
- speakNow(text3) {
50915
- this.deps.send({ type: "voice:cd:speak", text: text3 });
50967
+ speakNow(text4) {
50968
+ this.deps.send({ type: "voice:cd:speak", text: text4 });
50916
50969
  }
50917
50970
  close() {
50918
50971
  this.settleConnect(new Error("closed before connect"));
@@ -50932,11 +50985,11 @@ var ClientProxyProvider = class {
50932
50985
  handleToolCall(inv) {
50933
50986
  this.cb.onToolCall(inv);
50934
50987
  }
50935
- handleTranscript(speaker, text3) {
50988
+ handleTranscript(speaker, text4) {
50936
50989
  if (speaker === "user")
50937
- this.cb.onUserTranscript(text3);
50990
+ this.cb.onUserTranscript(text4);
50938
50991
  else
50939
- this.cb.onAgentTranscript(text3);
50992
+ this.cb.onAgentTranscript(text4);
50940
50993
  }
50941
50994
  handleProviderEvent(event, message) {
50942
50995
  switch (event) {
@@ -51151,7 +51204,7 @@ var VoiceControl = class {
51151
51204
  }
51152
51205
  /** Run a direct screen-control tool (os-control) and answer the operator's tool-call. */
51153
51206
  async runScreenControl(callId, name, args) {
51154
- let text3;
51207
+ let text4;
51155
51208
  let isError = false;
51156
51209
  let finished = false, nudges = 0;
51157
51210
  let slowTimer = null;
@@ -51167,18 +51220,18 @@ var VoiceControl = class {
51167
51220
  };
51168
51221
  scheduleNudge(2e4);
51169
51222
  try {
51170
- text3 = await this.deps.execScreenControl(name, args);
51223
+ text4 = await this.deps.execScreenControl(name, args);
51171
51224
  } catch (e) {
51172
- text3 = e instanceof Error ? e.message : "screen action failed";
51225
+ text4 = e instanceof Error ? e.message : "screen action failed";
51173
51226
  isError = true;
51174
51227
  } finally {
51175
51228
  finished = true;
51176
51229
  if (slowTimer)
51177
51230
  clearTimeout(slowTimer);
51178
51231
  }
51179
- log(`voice: screen-control ${name} \u2192 ${isError ? "ERROR " : ""}${text3}`);
51180
- recordEvent("tool_result", { name, text: text3, isError });
51181
- this.deps.send({ type: "voice:cd:respondToTool", callId, text: text3, isError });
51232
+ log(`voice: screen-control ${name} \u2192 ${isError ? "ERROR " : ""}${text4}`);
51233
+ recordEvent("tool_result", { name, text: text4, isError });
51234
+ this.deps.send({ type: "voice:cd:respondToTool", callId, text: text4, isError });
51182
51235
  }
51183
51236
  async start(msg) {
51184
51237
  if (this.starting)
@@ -51300,13 +51353,13 @@ ${priorText}` : "";
51300
51353
  const callbacks = {
51301
51354
  onOutputAudio: () => {
51302
51355
  },
51303
- onUserTranscript: (text3) => {
51304
- orchestrator.noteTranscript("user", text3);
51305
- this.deps.send({ type: "voice:transcript", speaker: "user", text: text3 });
51356
+ onUserTranscript: (text4) => {
51357
+ orchestrator.noteTranscript("user", text4);
51358
+ this.deps.send({ type: "voice:transcript", speaker: "user", text: text4 });
51306
51359
  },
51307
- onAgentTranscript: (text3) => {
51308
- orchestrator.noteTranscript("assistant", text3);
51309
- this.deps.send({ type: "voice:transcript", speaker: "agent", text: text3 });
51360
+ onAgentTranscript: (text4) => {
51361
+ orchestrator.noteTranscript("assistant", text4);
51362
+ this.deps.send({ type: "voice:transcript", speaker: "agent", text: text4 });
51310
51363
  },
51311
51364
  onToolCall: (inv) => orchestrator.handleToolCall(inv),
51312
51365
  onInterruption: () => this.deps.send({ type: "voice:clearPlayback" }),
@@ -51639,6 +51692,109 @@ function createDaemonImageGenRunner() {
51639
51692
  };
51640
51693
  }
51641
51694
 
51695
+ // ../../packages/host-core/dist/support-submit.js
51696
+ import { openSync as openSync2, fstatSync, readSync, closeSync as closeSync2 } from "node:fs";
51697
+ import { join as join19 } from "node:path";
51698
+
51699
+ // ../../packages/host-core/dist/host-metrics.js
51700
+ import os from "node:os";
51701
+ function primaryIpv4(ifaces = os.networkInterfaces()) {
51702
+ for (const name of Object.keys(ifaces)) {
51703
+ for (const ni of ifaces[name] ?? []) {
51704
+ if (ni.family === "IPv4" && !ni.internal)
51705
+ return ni.address;
51706
+ }
51707
+ }
51708
+ return void 0;
51709
+ }
51710
+ function staticMetrics(version2) {
51711
+ const cpus = os.cpus();
51712
+ return {
51713
+ version: version2 || void 0,
51714
+ arch: os.arch(),
51715
+ cpuModel: cpus[0]?.model?.trim() || void 0,
51716
+ cpuCount: cpus.length || void 0,
51717
+ totalMem: os.totalmem() || void 0,
51718
+ ip: primaryIpv4()
51719
+ };
51720
+ }
51721
+ function dynamicMetrics() {
51722
+ const la = os.loadavg();
51723
+ return {
51724
+ load: la[0] > 0 ? Number(la[0].toFixed(2)) : void 0,
51725
+ // loadavg is [0,0,0] on Windows
51726
+ freeMem: os.freemem() || void 0,
51727
+ uptime: Math.round(os.uptime()) || void 0
51728
+ };
51729
+ }
51730
+
51731
+ // ../../packages/host-core/dist/support-submit.js
51732
+ var LOG_TAIL_BYTES = 64 * 1024;
51733
+ function tail2(path5, bytes = LOG_TAIL_BYTES) {
51734
+ let fd = null;
51735
+ try {
51736
+ fd = openSync2(path5, "r");
51737
+ const size = fstatSync(fd).size;
51738
+ const len = Math.min(size, bytes);
51739
+ const start2 = Math.max(0, size - len);
51740
+ const buf = Buffer.alloc(len);
51741
+ readSync(fd, buf, 0, len, start2);
51742
+ return buf.toString("utf8");
51743
+ } catch {
51744
+ return "";
51745
+ } finally {
51746
+ if (fd !== null) {
51747
+ try {
51748
+ closeSync2(fd);
51749
+ } catch {
51750
+ }
51751
+ }
51752
+ }
51753
+ }
51754
+ function createDaemonSupportSubmit() {
51755
+ return async (input) => {
51756
+ const creds2 = readCredentials();
51757
+ if (!creds2) {
51758
+ throw new Error("Not signed in on this machine \u2014 sign in (or share this machine) to file a report from chat.");
51759
+ }
51760
+ const daemonLog = tail2(join19(daemonDir(), "daemon.log"));
51761
+ const diagnostics = {
51762
+ collectedAt: (/* @__PURE__ */ new Date()).toISOString(),
51763
+ source: "daemon",
51764
+ host: { ...staticMetrics(), ...dynamicMetrics() },
51765
+ platform: process.platform,
51766
+ arch: process.arch,
51767
+ node: process.versions.node,
51768
+ userId: creds2.userId,
51769
+ logs: { daemon: daemonLog }
51770
+ };
51771
+ const res = await fetch(`${creds2.apiOrigin.replace(/\/$/, "")}/api/core/tesseract/support/issue`, {
51772
+ method: "POST",
51773
+ headers: { "Content-Type": "application/json", Authorization: `Bearer ${creds2.accessToken}` },
51774
+ body: JSON.stringify({
51775
+ type: input.type === "feature" ? "feature" : "issue",
51776
+ title: input.title,
51777
+ description: input.description,
51778
+ // NEVER route logs to the PUBLIC issue on the agent path: they're auto-collected
51779
+ // (not human-reviewed) and can carry usernames/paths/ids. The daemon log is already
51780
+ // attached PRIVATELY via `diagnostics` above. Public logs are the desktop form's
51781
+ // job (human-reviewed opt-in) only.
51782
+ includeLogsInIssue: false,
51783
+ diagnostics
51784
+ }),
51785
+ signal: AbortSignal.timeout(3e4)
51786
+ });
51787
+ if (!res.ok) {
51788
+ const text4 = await res.text().catch(() => "");
51789
+ throw new Error(`Report submission failed (${res.status}). ${text4.slice(0, 200)}`);
51790
+ }
51791
+ const body = await res.json();
51792
+ if (!body.issueUrl || typeof body.issueNumber !== "number")
51793
+ throw new Error("Malformed response from the report API.");
51794
+ return { issueUrl: body.issueUrl, issueNumber: body.issueNumber };
51795
+ };
51796
+ }
51797
+
51642
51798
  // ../../packages/host-core/dist/daemon-agent.js
51643
51799
  init_dist2();
51644
51800
  var sinks = /* @__PURE__ */ new Set();
@@ -51700,7 +51856,7 @@ function buildSharedBackend(engineId) {
51700
51856
  },
51701
51857
  resolver,
51702
51858
  // Daemon plugins (review #3): operator-controlled <daemonDir>/plugins, env-var secrets.
51703
- buildDaemonPluginLoader(join19(daemonDir(), "plugins"))
51859
+ buildDaemonPluginLoader(join20(daemonDir(), "plugins"))
51704
51860
  ).then((b) => {
51705
51861
  if (token2 !== buildToken)
51706
51862
  return b;
@@ -51728,6 +51884,11 @@ function buildSharedBackend(engineId) {
51728
51884
  } catch (e) {
51729
51885
  log("imagegen: setup failed:", e instanceof Error ? e.message : String(e));
51730
51886
  }
51887
+ try {
51888
+ b.setSupportSubmit?.(createDaemonSupportSubmit());
51889
+ } catch (e) {
51890
+ log("support: setup failed:", e instanceof Error ? e.message : String(e));
51891
+ }
51731
51892
  return b;
51732
51893
  });
51733
51894
  }
@@ -51766,7 +51927,7 @@ function refreshDaemonScheduling(b) {
51766
51927
  }
51767
51928
  b.configureScheduling({
51768
51929
  enabled,
51769
- file: join19(dir2, "scheduled_tasks.json"),
51930
+ file: join20(dir2, "scheduled_tasks.json"),
51770
51931
  // projectDir omitted ⇒ fires track the daemon's currently-open project (setConfig).
51771
51932
  isOwner: schedulingLock ? () => schedulingLock.isOwner() : void 0
51772
51933
  });
@@ -51775,16 +51936,16 @@ var VOICE_GATEWAY = process.env.CCB_VOICE_GATEWAY !== "0";
51775
51936
 
51776
51937
  // ../../packages/host-core/dist/fs-remote.js
51777
51938
  import { readdir as readdir3, readFile as readFile8, writeFile as writeFile5, mkdir as mkdir5, cp, rm, rename as renameAsync, stat as stat2 } from "node:fs/promises";
51778
- import { openSync as openSync2, readSync, writeSync, closeSync as closeSync2, statSync as statSync4, existsSync as existsSync8, mkdtempSync, rmSync as rmSync2, readFileSync as readFileSync9, readdirSync as readdirSync4, watch, realpathSync as realpathSync2, constants as fsConstants } from "node:fs";
51939
+ import { openSync as openSync3, readSync as readSync2, writeSync, closeSync as closeSync3, statSync as statSync4, existsSync as existsSync8, mkdtempSync, rmSync as rmSync2, readFileSync as readFileSync9, readdirSync as readdirSync4, watch, realpathSync as realpathSync2, constants as fsConstants } from "node:fs";
51779
51940
  import { tmpdir as tmpdir2 } from "node:os";
51780
- import { basename as basename3, dirname as dirname7, join as join21, relative as relative4, resolve as resolve5, sep as sep4, isAbsolute as isAbsolute4 } from "node:path";
51941
+ import { basename as basename3, dirname as dirname7, join as join22, relative as relative4, resolve as resolve5, sep as sep4, isAbsolute as isAbsolute4 } from "node:path";
51781
51942
  import { execFile as execFile3 } from "node:child_process";
51782
51943
  import { promisify as promisify2 } from "node:util";
51783
51944
 
51784
51945
  // ../../packages/host-core/dist/fs-stats.js
51785
51946
  init_dist();
51786
51947
  import { readdir as readdir2, lstat, readFile as readFile7 } from "node:fs/promises";
51787
- import { join as join20 } from "node:path";
51948
+ import { join as join21 } from "node:path";
51788
51949
  var TEXT_CAP = 5 * 1024 * 1024;
51789
51950
  async function dirStats(root, opts) {
51790
51951
  const start2 = Date.now();
@@ -51815,11 +51976,11 @@ async function dirStats(root, opts) {
51815
51976
  if (opts?.excludeHeavy && STATS_HEAVY_DIRS.has(e.name))
51816
51977
  continue;
51817
51978
  dirCount++;
51818
- stack.push(join20(dir2, e.name));
51979
+ stack.push(join21(dir2, e.name));
51819
51980
  } else if (e.isFile()) {
51820
51981
  fileCount++;
51821
51982
  try {
51822
- totalBytes += (await lstat(join20(dir2, e.name))).size;
51983
+ totalBytes += (await lstat(join21(dir2, e.name))).size;
51823
51984
  } catch {
51824
51985
  }
51825
51986
  }
@@ -51854,7 +52015,7 @@ async function codeStats(root) {
51854
52015
  continue;
51855
52016
  if (e.isDirectory()) {
51856
52017
  if (!STATS_HEAVY_DIRS.has(e.name))
51857
- stack.push(join20(dir2, e.name));
52018
+ stack.push(join21(dir2, e.name));
51858
52019
  continue;
51859
52020
  }
51860
52021
  if (!e.isFile())
@@ -51862,7 +52023,7 @@ async function codeStats(root) {
51862
52023
  const lang = langForFilename(e.name);
51863
52024
  if (!lang)
51864
52025
  continue;
51865
- const full = join20(dir2, e.name);
52026
+ const full = join21(dir2, e.name);
51866
52027
  let size = 0;
51867
52028
  try {
51868
52029
  size = (await lstat(full)).size;
@@ -51955,7 +52116,7 @@ async function listAllFilesUnder(dir2) {
51955
52116
  return;
51956
52117
  if (ent.name === ".DS_Store")
51957
52118
  continue;
51958
- const full = join21(d, ent.name);
52119
+ const full = join22(d, ent.name);
51959
52120
  if (ent.isDirectory()) {
51960
52121
  if (!LISTALL_SKIP_DIRS.has(ent.name))
51961
52122
  await walk(full);
@@ -52072,18 +52233,18 @@ function resolveParent(raw, root) {
52072
52233
  if (raw === "" || raw === "~")
52073
52234
  return root;
52074
52235
  if (raw.startsWith("~/"))
52075
- return join21(root, raw.slice(2));
52076
- return isAbsolute4(raw) ? raw : join21(root, raw);
52236
+ return join22(root, raw.slice(2));
52237
+ return isAbsolute4(raw) ? raw : join22(root, raw);
52077
52238
  }
52078
52239
  function resolveUniqueName(dir2, name) {
52079
- const direct = join21(dir2, name);
52240
+ const direct = join22(dir2, name);
52080
52241
  if (!existsSync8(direct))
52081
52242
  return direct;
52082
52243
  const dot = name.lastIndexOf(".");
52083
52244
  const base = dot > 0 ? name.slice(0, dot) : name;
52084
52245
  const ext = dot > 0 ? name.slice(dot) : "";
52085
52246
  for (let i = 2; i < 1e4; i++) {
52086
- const candidate = join21(dir2, `${base} ${i}${ext}`);
52247
+ const candidate = join22(dir2, `${base} ${i}${ext}`);
52087
52248
  if (!existsSync8(candidate))
52088
52249
  return candidate;
52089
52250
  }
@@ -52156,12 +52317,12 @@ async function renderThumbnailImpl(real, maxPx) {
52156
52317
  return { error: "Thumbnails are only available on macOS hosts." };
52157
52318
  let dir2 = null;
52158
52319
  try {
52159
- dir2 = mkdtempSync(join21(tmpdir2(), "fp-thumb-"));
52320
+ dir2 = mkdtempSync(join22(tmpdir2(), "fp-thumb-"));
52160
52321
  await execFileAsync("qlmanage", ["-t", "-s", String(maxPx), "-o", dir2, real], { timeout: 1e4, killSignal: "SIGKILL" }).catch(() => void 0);
52161
52322
  const produced = readdirSync4(dir2).find((f) => f.toLowerCase().endsWith(".png"));
52162
52323
  if (!produced)
52163
52324
  return { error: "No thumbnail available." };
52164
- return { png: readFileSync9(join21(dir2, produced)).toString("base64") };
52325
+ return { png: readFileSync9(join22(dir2, produced)).toString("base64") };
52165
52326
  } catch (err) {
52166
52327
  return { error: String(err.message) };
52167
52328
  } finally {
@@ -52201,7 +52362,7 @@ var MAX_STAT_PATHS = 4096;
52201
52362
  var SAFE_SEG = /^[A-Za-z0-9._-]+$/;
52202
52363
  var TRASH_RETENTION_MS = 14 * 24 * 60 * 60 * 1e3;
52203
52364
  function pruneTrash(root) {
52204
- const trashDir = join21(root, TRASH_DIR);
52365
+ const trashDir = join22(root, TRASH_DIR);
52205
52366
  if (!existsSync8(trashDir))
52206
52367
  return;
52207
52368
  const cutoff = Date.now() - TRASH_RETENTION_MS;
@@ -52210,9 +52371,9 @@ function pruneTrash(root) {
52210
52371
  if (!e.isDirectory())
52211
52372
  continue;
52212
52373
  try {
52213
- const meta4 = JSON.parse(readFileSync9(join21(trashDir, e.name, ".fp-meta.json"), "utf-8"));
52374
+ const meta4 = JSON.parse(readFileSync9(join22(trashDir, e.name, ".fp-meta.json"), "utf-8"));
52214
52375
  if ((meta4.deletedAt ?? 0) < cutoff)
52215
- rmSync2(join21(trashDir, e.name), { recursive: true, force: true });
52376
+ rmSync2(join22(trashDir, e.name), { recursive: true, force: true });
52216
52377
  } catch {
52217
52378
  }
52218
52379
  }
@@ -52238,12 +52399,12 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52238
52399
  return entries.map((e) => {
52239
52400
  let id = null;
52240
52401
  try {
52241
- id = statId(join21(real, e.name));
52402
+ id = statId(join22(real, e.name));
52242
52403
  } catch {
52243
52404
  }
52244
52405
  return {
52245
52406
  name: e.name,
52246
- path: join21(dir2, e.name),
52407
+ path: join22(dir2, e.name),
52247
52408
  isDir: e.isDirectory(),
52248
52409
  ignored: ignored.has(e.name),
52249
52410
  size: id?.size,
@@ -52324,9 +52485,9 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52324
52485
  try {
52325
52486
  if (off === 0) {
52326
52487
  await mkdir5(dirname7(real), { recursive: true });
52327
- fd = openSync2(real, "w");
52488
+ fd = openSync3(real, "w");
52328
52489
  } else
52329
- fd = openSync2(real, "r+");
52490
+ fd = openSync3(real, "r+");
52330
52491
  if (buf.length > 0)
52331
52492
  writeSync(fd, buf, 0, buf.length, off);
52332
52493
  return { ok: true, bytesWritten: buf.length };
@@ -52335,7 +52496,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52335
52496
  } finally {
52336
52497
  if (fd != null)
52337
52498
  try {
52338
- closeSync2(fd);
52499
+ closeSync3(fd);
52339
52500
  } catch {
52340
52501
  }
52341
52502
  }
@@ -52377,16 +52538,16 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52377
52538
  return { base64: "", bytesRead: 0 };
52378
52539
  let fd = null;
52379
52540
  try {
52380
- fd = openSync2(real, "r");
52541
+ fd = openSync3(real, "r");
52381
52542
  const buf = Buffer.alloc(len);
52382
- const bytesRead = readSync(fd, buf, 0, len, off);
52543
+ const bytesRead = readSync2(fd, buf, 0, len, off);
52383
52544
  return { base64: buf.subarray(0, bytesRead).toString("base64"), bytesRead };
52384
52545
  } catch (err) {
52385
52546
  return { error: String(err.message) };
52386
52547
  } finally {
52387
52548
  if (fd != null)
52388
52549
  try {
52389
- closeSync2(fd);
52550
+ closeSync3(fd);
52390
52551
  } catch {
52391
52552
  }
52392
52553
  }
@@ -52410,7 +52571,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52410
52571
  const name = String(a[1] ?? "").trim();
52411
52572
  if (!validName(name))
52412
52573
  return { ok: false, error: "Invalid project name." };
52413
- const target = join21(parent, name);
52574
+ const target = join22(parent, name);
52414
52575
  if (!insideOk(target))
52415
52576
  return { ok: false, error: "Refusing to create a project outside the shared root." };
52416
52577
  if (existsSync8(target))
@@ -52428,7 +52589,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52428
52589
  const name = String(a[1] ?? "").trim();
52429
52590
  if (!validName(name))
52430
52591
  return { ok: false, error: "Invalid name." };
52431
- const target = join21(parent, name);
52592
+ const target = join22(parent, name);
52432
52593
  if (!insideOk(target))
52433
52594
  return OUTSIDE("create");
52434
52595
  if (existsSync8(target))
@@ -52450,7 +52611,7 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52450
52611
  return { ok: false, error: "Invalid name." };
52451
52612
  if (!insideOk(oldPath))
52452
52613
  return OUTSIDE("rename");
52453
- const newPath = join21(dirname7(oldPath), newName);
52614
+ const newPath = join22(dirname7(oldPath), newName);
52454
52615
  if (existsSync8(newPath))
52455
52616
  return { ok: false, error: `A file named "${newName}" already exists.` };
52456
52617
  try {
@@ -52484,19 +52645,19 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52484
52645
  try {
52485
52646
  pruneTrash(root);
52486
52647
  const id = `${Date.now().toString(36)}-${(trashSeq++).toString(36)}`;
52487
- const itemDir = join21(root, TRASH_DIR, id);
52648
+ const itemDir = join22(root, TRASH_DIR, id);
52488
52649
  await mkdir5(itemDir, { recursive: true });
52489
52650
  const name = basename3(p);
52490
- const trashedPath = join21(itemDir, name);
52651
+ const trashedPath = join22(itemDir, name);
52491
52652
  await moveItem(p, trashedPath);
52492
- await writeFile5(join21(itemDir, ".fp-meta.json"), JSON.stringify({ originalPath: resolve5(p), name, deletedAt: Date.now() }));
52653
+ await writeFile5(join22(itemDir, ".fp-meta.json"), JSON.stringify({ originalPath: resolve5(p), name, deletedAt: Date.now() }));
52493
52654
  return { ok: true, trashId: id, path: trashedPath };
52494
52655
  } catch (err) {
52495
52656
  return { ok: false, error: String(err.message) };
52496
52657
  }
52497
52658
  }
52498
52659
  case "listTrash": {
52499
- const trashDir = join21(root, TRASH_DIR);
52660
+ const trashDir = join22(root, TRASH_DIR);
52500
52661
  if (!existsSync8(trashDir))
52501
52662
  return [];
52502
52663
  try {
@@ -52505,8 +52666,8 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52505
52666
  if (!e.isDirectory())
52506
52667
  continue;
52507
52668
  try {
52508
- const meta4 = JSON.parse(readFileSync9(join21(trashDir, e.name, ".fp-meta.json"), "utf-8"));
52509
- out.push({ trashId: e.name, name: meta4.name, path: join21(trashDir, e.name, meta4.name), originalPath: meta4.originalPath, deletedAt: meta4.deletedAt });
52669
+ const meta4 = JSON.parse(readFileSync9(join22(trashDir, e.name, ".fp-meta.json"), "utf-8"));
52670
+ out.push({ trashId: e.name, name: meta4.name, path: join22(trashDir, e.name, meta4.name), originalPath: meta4.originalPath, deletedAt: meta4.deletedAt });
52510
52671
  } catch {
52511
52672
  }
52512
52673
  }
@@ -52519,14 +52680,14 @@ async function runRemoteFsOp(root, op, args, quotaKey) {
52519
52680
  const id = String(a[0] ?? "");
52520
52681
  if (!SAFE_SEG.test(id))
52521
52682
  return { ok: false, error: "Bad trash id." };
52522
- const itemDir = join21(root, TRASH_DIR, id);
52683
+ const itemDir = join22(root, TRASH_DIR, id);
52523
52684
  if (!existsSync8(itemDir))
52524
52685
  return { ok: false, error: "Not in trash." };
52525
52686
  try {
52526
- const meta4 = JSON.parse(readFileSync9(join21(itemDir, ".fp-meta.json"), "utf-8"));
52687
+ const meta4 = JSON.parse(readFileSync9(join22(itemDir, ".fp-meta.json"), "utf-8"));
52527
52688
  if (!validName(meta4.name))
52528
52689
  return { ok: false, error: "Bad trashed name." };
52529
- const src = join21(itemDir, meta4.name);
52690
+ const src = join22(itemDir, meta4.name);
52530
52691
  let dest = meta4.originalPath;
52531
52692
  if (!insideOk(dest))
52532
52693
  return OUTSIDE("restore");
@@ -52620,7 +52781,7 @@ function watchRemoteRoot(root, key2, onChange) {
52620
52781
  const rel = String(filename);
52621
52782
  if (rel.split(sep4).some((seg) => IGNORED.has(seg)))
52622
52783
  return;
52623
- pending.add(join21(resolved, rel));
52784
+ pending.add(join22(resolved, rel));
52624
52785
  if (timer)
52625
52786
  clearTimeout(timer);
52626
52787
  timer = setTimeout(() => {
@@ -52832,46 +52993,14 @@ function releaseDcClient(clientId) {
52832
52993
  }
52833
52994
  }
52834
52995
 
52835
- // ../../packages/host-core/dist/host-metrics.js
52836
- import os from "node:os";
52837
- function primaryIpv4(ifaces = os.networkInterfaces()) {
52838
- for (const name of Object.keys(ifaces)) {
52839
- for (const ni of ifaces[name] ?? []) {
52840
- if (ni.family === "IPv4" && !ni.internal)
52841
- return ni.address;
52842
- }
52843
- }
52844
- return void 0;
52845
- }
52846
- function staticMetrics(version2) {
52847
- const cpus = os.cpus();
52848
- return {
52849
- version: version2 || void 0,
52850
- arch: os.arch(),
52851
- cpuModel: cpus[0]?.model?.trim() || void 0,
52852
- cpuCount: cpus.length || void 0,
52853
- totalMem: os.totalmem() || void 0,
52854
- ip: primaryIpv4()
52855
- };
52856
- }
52857
- function dynamicMetrics() {
52858
- const la = os.loadavg();
52859
- return {
52860
- load: la[0] > 0 ? Number(la[0].toFixed(2)) : void 0,
52861
- // loadavg is [0,0,0] on Windows
52862
- freeMem: os.freemem() || void 0,
52863
- uptime: Math.round(os.uptime()) || void 0
52864
- };
52865
- }
52866
-
52867
52996
  // ../../packages/host-core/dist/fs-transfer.js
52868
52997
  import { readdir as readdir4, lstat as lstat2, mkdir as mkdir6, chmod, rm as rm2, readlink, symlink, stat as stat3 } from "node:fs/promises";
52869
- import { openSync as openSync3, readSync as readSync2, closeSync as closeSync3, existsSync as existsSync9, createWriteStream } from "node:fs";
52870
- import { dirname as dirname8, join as join23, relative as relative6, sep as sep6 } from "node:path";
52998
+ import { openSync as openSync4, readSync as readSync3, closeSync as closeSync4, existsSync as existsSync9, createWriteStream } from "node:fs";
52999
+ import { dirname as dirname8, join as join24, relative as relative6, sep as sep6 } from "node:path";
52871
53000
 
52872
53001
  // ../../packages/host-core/dist/active-link/paths.js
52873
53002
  import { homedir as homedir11 } from "node:os";
52874
- import { join as join22, relative as relative5, sep as sep5 } from "node:path";
53003
+ import { join as join23, relative as relative5, sep as sep5 } from "node:path";
52875
53004
  function activeLinkEnabled() {
52876
53005
  return process.env.CCB_ACTIVE_LINK !== "0";
52877
53006
  }
@@ -52897,7 +53026,7 @@ function toPosixRel(root, abs) {
52897
53026
  return relative5(root, abs).split(sep5).join("/");
52898
53027
  }
52899
53028
  function fromPosixRel(root, rel) {
52900
- return join22(root, rel.split("/").join(sep5));
53029
+ return join23(root, rel.split("/").join(sep5));
52901
53030
  }
52902
53031
  function isExcludedAbs(abs, root) {
52903
53032
  const rel = toPosixRel(root, abs);
@@ -52906,10 +53035,10 @@ function isExcludedAbs(abs, root) {
52906
53035
  return rel.split("/").some(isExcludedName);
52907
53036
  }
52908
53037
  function activeLinkRoot() {
52909
- return process.env.CCB_ACTIVE_LINK_DIR ?? join22(homedir11(), ".tesseract", "active-link");
53038
+ return process.env.CCB_ACTIVE_LINK_DIR ?? join23(homedir11(), ".tesseract", "active-link");
52910
53039
  }
52911
53040
  function linkStateDir(linkId) {
52912
- return join22(activeLinkRoot(), linkId);
53041
+ return join23(activeLinkRoot(), linkId);
52913
53042
  }
52914
53043
 
52915
53044
  // ../../packages/host-core/dist/fs-transfer.js
@@ -52922,9 +53051,9 @@ function clearTimer(t) {
52922
53051
  return null;
52923
53052
  }
52924
53053
  function uniqueDir(parent, name) {
52925
- let candidate = join23(parent, name);
53054
+ let candidate = join24(parent, name);
52926
53055
  for (let i = 2; existsSync9(candidate) && i < 1e4; i++)
52927
- candidate = join23(parent, `${name} ${i}`);
53056
+ candidate = join24(parent, `${name} ${i}`);
52928
53057
  return candidate;
52929
53058
  }
52930
53059
  var producers = /* @__PURE__ */ new Map();
@@ -52967,7 +53096,7 @@ async function buildManifest(root, followSymlinks, excludeHeavy) {
52967
53096
  continue;
52968
53097
  if (e.isDirectory() && excludeHeavy && HEAVY_DIRS.has(e.name))
52969
53098
  continue;
52970
- const abs = join23(dir2, e.name);
53099
+ const abs = join24(dir2, e.name);
52971
53100
  const rel = relative6(root, abs).split(sep6).join("/");
52972
53101
  const st = await lstat2(abs).catch(() => null);
52973
53102
  if (!st)
@@ -53034,14 +53163,14 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
53034
53163
  for (let fileIx = 0; fileIx < manifest.files.length && !state.cancelled; fileIx++) {
53035
53164
  const f = manifest.files[fileIx];
53036
53165
  if (f.kind === "symlink") {
53037
- const target = await readlink(join23(srcPath, f.rel.split("/").join(sep6))).catch(() => "");
53166
+ const target = await readlink(join24(srcPath, f.rel.split("/").join(sep6))).catch(() => "");
53038
53167
  send3({ 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 });
53039
53168
  continue;
53040
53169
  }
53041
- const abs = join23(srcPath, f.rel.split("/").join(sep6));
53170
+ const abs = join24(srcPath, f.rel.split("/").join(sep6));
53042
53171
  let fd = null;
53043
53172
  try {
53044
- fd = openSync3(abs, "r");
53173
+ fd = openSync4(abs, "r");
53045
53174
  if (f.size === 0) {
53046
53175
  send3({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset: 0, base64: "", eof: true }, { hostId: toHost });
53047
53176
  } else {
@@ -53051,7 +53180,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
53051
53180
  break;
53052
53181
  const len = Math.min(CHUNK2, f.size - offset);
53053
53182
  const buf = Buffer.alloc(len);
53054
- const read = readSync2(fd, buf, 0, len, offset);
53183
+ const read = readSync3(fd, buf, 0, len, offset);
53055
53184
  send3({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset, base64: buf.subarray(0, read).toString("base64"), eof: offset + len >= f.size }, { hostId: toHost });
53056
53185
  state.sentBytes += read;
53057
53186
  }
@@ -53059,7 +53188,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
53059
53188
  } catch (e) {
53060
53189
  if (fd != null)
53061
53190
  try {
53062
- closeSync3(fd);
53191
+ closeSync4(fd);
53063
53192
  } catch {
53064
53193
  }
53065
53194
  failProducer(transferId, `Couldn't read ${f.rel}: ${e.message}`);
@@ -53067,7 +53196,7 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
53067
53196
  } finally {
53068
53197
  if (fd != null)
53069
53198
  try {
53070
- closeSync3(fd);
53199
+ closeSync4(fd);
53071
53200
  } catch {
53072
53201
  }
53073
53202
  }
@@ -53150,7 +53279,7 @@ async function beginInboundTransfer(msg, hostRoot, send3) {
53150
53279
  failNoState("Invalid destination name.");
53151
53280
  return;
53152
53281
  }
53153
- let destRoot = join23(parent, msg.destName);
53282
+ let destRoot = join24(parent, msg.destName);
53154
53283
  let createdRoot = false;
53155
53284
  if (existsSync9(destRoot)) {
53156
53285
  if (msg.onCollision === "abort") {
@@ -53192,7 +53321,7 @@ async function beginInboundTransfer(msg, hostRoot, send3) {
53192
53321
  try {
53193
53322
  await mkdir6(destRoot, { recursive: true });
53194
53323
  for (const d of msg.dirs) {
53195
- const abs = join23(destRoot, d.rel.split("/").join(sep6));
53324
+ const abs = join24(destRoot, d.rel.split("/").join(sep6));
53196
53325
  if (isInsideRoot(abs, destRoot))
53197
53326
  await mkdir6(abs, { recursive: true }).catch(() => {
53198
53327
  });
@@ -53206,7 +53335,7 @@ async function writeInboundChunk(msg, send3) {
53206
53335
  if (!s || s.cancelled)
53207
53336
  return;
53208
53337
  armConsumerWatchdog(msg.transferId, send3);
53209
- const abs = join23(s.destRoot, msg.rel.split("/").join(sep6));
53338
+ const abs = join24(s.destRoot, msg.rel.split("/").join(sep6));
53210
53339
  if (msg.rel.includes("..") || !isInsideRoot(abs, s.destRoot)) {
53211
53340
  failConsumer(msg.transferId, `Refusing a path outside the destination: ${msg.rel}`, send3);
53212
53341
  return;
@@ -53214,7 +53343,7 @@ async function writeInboundChunk(msg, send3) {
53214
53343
  try {
53215
53344
  if (msg.kind === "symlink") {
53216
53345
  const target = Buffer.from(msg.base64, "base64").toString("utf-8");
53217
- const resolved = join23(dirname8(abs), target);
53346
+ const resolved = join24(dirname8(abs), target);
53218
53347
  if (isInsideRoot(resolved, s.destRoot)) {
53219
53348
  await mkdir6(dirname8(abs), { recursive: true }).catch(() => {
53220
53349
  });
@@ -53301,7 +53430,7 @@ function cancelTransfersForClient(clientId, send3) {
53301
53430
 
53302
53431
  // ../../packages/host-core/dist/peer-link/index.js
53303
53432
  import { homedir as homedir12 } from "node:os";
53304
- import { join as join24 } from "node:path";
53433
+ import { join as join25 } from "node:path";
53305
53434
 
53306
53435
  // ../../packages/host-core/dist/peer-link/manager.js
53307
53436
  init_tls_direct();
@@ -53798,8 +53927,8 @@ var PeerLinkManager = class {
53798
53927
  // ../../packages/host-core/dist/peer-link/index.js
53799
53928
  var P2P_ENABLED = process.env.CCB_P2P !== "0";
53800
53929
  function identityPaths() {
53801
- const dir2 = process.env.CCB_P2P_DIR ?? join24(homedir12(), ".tesseract");
53802
- return { certPath: join24(dir2, "peer-cert.pem"), keyPath: join24(dir2, "peer-key.pem") };
53930
+ const dir2 = process.env.CCB_P2P_DIR ?? join25(homedir12(), ".tesseract");
53931
+ return { certPath: join25(dir2, "peer-cert.pem"), keyPath: join25(dir2, "peer-key.pem") };
53803
53932
  }
53804
53933
  var manager = null;
53805
53934
  function peerLinkManager() {
@@ -53816,7 +53945,7 @@ async function openPeerLink(peerHostId, ctx2) {
53816
53945
  // ../../packages/host-core/dist/active-link/engine.js
53817
53946
  import { lstat as lstat7, readlink as readlink4, rm as rm3, mkdir as mkdir8, symlink as symlink2, rename as rename2, utimes as utimes2, writeFile as writeFile6 } from "node:fs/promises";
53818
53947
  import { existsSync as existsSync12 } from "node:fs";
53819
- import { dirname as dirname13, join as join29, resolve as resolve8 } from "node:path";
53948
+ import { dirname as dirname13, join as join30, resolve as resolve8 } from "node:path";
53820
53949
 
53821
53950
  // ../../packages/host-core/dist/active-link/blocks.js
53822
53951
  import { createHash as createHash3 } from "node:crypto";
@@ -54081,7 +54210,7 @@ var BlockAssembler = class {
54081
54210
 
54082
54211
  // ../../packages/host-core/dist/active-link/manifest.js
54083
54212
  import { readFileSync as readFileSync11, writeFileSync as writeFileSync11, mkdirSync as mkdirSync10, existsSync as existsSync11, renameSync as renameSync5 } from "node:fs";
54084
- import { join as join25 } from "node:path";
54213
+ import { join as join26 } from "node:path";
54085
54214
 
54086
54215
  // ../../packages/host-core/dist/active-link/reconcile.js
54087
54216
  var ABSENT = { kind: "absent", t: -Infinity, hash: "" };
@@ -54117,7 +54246,7 @@ var LinkManifest = class {
54117
54246
  this.dir = dir2;
54118
54247
  }
54119
54248
  file() {
54120
- return join25(this.dir, "manifest.json");
54249
+ return join26(this.dir, "manifest.json");
54121
54250
  }
54122
54251
  load() {
54123
54252
  try {
@@ -54219,7 +54348,7 @@ var LinkManifest = class {
54219
54348
 
54220
54349
  // ../../packages/host-core/dist/active-link/scanner.js
54221
54350
  import { readdir as readdir5, lstat as lstat3, readlink as readlink2 } from "node:fs/promises";
54222
- import { join as join26, sep as sep7 } from "node:path";
54351
+ import { join as join27, sep as sep7 } from "node:path";
54223
54352
  async function walkRels(root, extraIgnore) {
54224
54353
  const out = [];
54225
54354
  async function rec(dir2) {
@@ -54234,7 +54363,7 @@ async function walkRels(root, extraIgnore) {
54234
54363
  continue;
54235
54364
  if (e.isDirectory() && HEAVY_DIRS.has(e.name))
54236
54365
  continue;
54237
- const abs = join26(dir2, e.name);
54366
+ const abs = join27(dir2, e.name);
54238
54367
  if (extraIgnore?.(abs))
54239
54368
  continue;
54240
54369
  if (e.isDirectory())
@@ -54273,7 +54402,7 @@ async function scanTree(root, prior, allow, extraIgnore) {
54273
54402
  return { records };
54274
54403
  }
54275
54404
  function absOf(root, rel) {
54276
- return join26(root, rel.split("/").join(sep7));
54405
+ return join27(root, rel.split("/").join(sep7));
54277
54406
  }
54278
54407
 
54279
54408
  // ../../packages/host-core/dist/active-link/gitignore.js
@@ -56298,7 +56427,7 @@ var ActiveLinkEngine = class {
56298
56427
  }
56299
56428
  async start() {
56300
56429
  this.emit({ type: "status", linkId: this.opts.linkId, state: "scanning" });
56301
- await rm3(join29(this.stateDir, ".staging"), { recursive: true, force: true }).catch(() => {
56430
+ await rm3(join30(this.stateDir, ".staging"), { recursive: true, force: true }).catch(() => {
56302
56431
  });
56303
56432
  this.manifest.load();
56304
56433
  await this.reconcileScan();
@@ -56926,7 +57055,7 @@ var ActiveLinkEngine = class {
56926
57055
  this.inboundWatchdog.clear();
56927
57056
  }
56928
57057
  stagingPath(rel, tag) {
56929
- return join29(this.stateDir, ".staging", `${hashString(rel)}.${tag}`);
57058
+ return join30(this.stateDir, ".staging", `${hashString(rel)}.${tag}`);
56930
57059
  }
56931
57060
  pruneSuppress() {
56932
57061
  const now2 = this.now();
@@ -56952,9 +57081,9 @@ var ActiveLinkEngine = class {
56952
57081
 
56953
57082
  // ../../packages/host-core/dist/active-link/config.js
56954
57083
  import { readFileSync as readFileSync12, writeFileSync as writeFileSync12, mkdirSync as mkdirSync11, existsSync as existsSync13, renameSync as renameSync6, watch as watch3 } from "node:fs";
56955
- import { join as join30 } from "node:path";
57084
+ import { join as join31 } from "node:path";
56956
57085
  function configPath2() {
56957
- return join30(activeLinkRoot(), "links.json");
57086
+ return join31(activeLinkRoot(), "links.json");
56958
57087
  }
56959
57088
  function loadLinkConfigs() {
56960
57089
  try {
@@ -56991,7 +57120,7 @@ function saveLinkConfig(cfg2) {
56991
57120
  writeAll(links);
56992
57121
  }
56993
57122
  function pendingPath() {
56994
- return join30(activeLinkRoot(), "pending-deprovisions.json");
57123
+ return join31(activeLinkRoot(), "pending-deprovisions.json");
56995
57124
  }
56996
57125
  function loadPendingDeprovisions() {
56997
57126
  try {
@@ -57810,9 +57939,9 @@ function provisionActiveLinkMirror(payload) {
57810
57939
  const remoteSubfolder = typeof payload.remoteSubfolder === "string" ? payload.remoteSubfolder : void 0;
57811
57940
  let localRoot;
57812
57941
  if (remoteParent && remoteSubfolder) {
57813
- localRoot = join31(remoteParent, safeFolderName(remoteSubfolder));
57942
+ localRoot = join32(remoteParent, safeFolderName(remoteSubfolder));
57814
57943
  } else {
57815
- localRoot = join31(HOST_ROOT, "Tesseract Mirrors", safeFolderName(projectName));
57944
+ localRoot = join32(HOST_ROOT, "Tesseract Mirrors", safeFolderName(projectName));
57816
57945
  }
57817
57946
  if (loadLinkConfigs().some((c) => c.localRoot === localRoot && c.linkId !== linkId)) {
57818
57947
  localRoot = `${localRoot}-${linkId.slice(0, 6)}`;
@@ -59015,16 +59144,16 @@ async function startLocalServer(opts) {
59015
59144
 
59016
59145
  // ../../packages/host-core/dist/daemon-runtime.js
59017
59146
  import { readFileSync as readFileSync14, writeFileSync as writeFileSync15, existsSync as existsSync17, mkdirSync as mkdirSync15, unlinkSync as unlinkSync2, chmodSync as chmodSync4 } from "node:fs";
59018
- import { join as join34 } from "node:path";
59147
+ import { join as join35 } from "node:path";
59019
59148
  import { randomBytes as randomBytes5 } from "node:crypto";
59020
59149
  import { hostname as hostname4 } from "node:os";
59021
59150
 
59022
59151
  // ../../packages/host-core/dist/device-identity.js
59023
- import { join as join32 } from "node:path";
59152
+ import { join as join33 } from "node:path";
59024
59153
  import { readFileSync as readFileSync13, writeFileSync as writeFileSync13, existsSync as existsSync15, mkdirSync as mkdirSync13, renameSync as renameSync7, chmodSync as chmodSync3 } from "node:fs";
59025
59154
  var cached2 = null;
59026
59155
  function identityPath() {
59027
- return join32(daemonDir(), "identity.json");
59156
+ return join33(daemonDir(), "identity.json");
59028
59157
  }
59029
59158
  async function loadOrCreateDeviceIdentity() {
59030
59159
  if (cached2)
@@ -59289,9 +59418,9 @@ function createNodePowerController() {
59289
59418
 
59290
59419
  // ../../packages/host-core/dist/activity/activity-tracker.js
59291
59420
  import { promises as fsp, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, existsSync as existsSync16 } from "node:fs";
59292
- import { join as join33 } from "node:path";
59421
+ import { join as join34 } from "node:path";
59293
59422
  function activityProfilePath() {
59294
- return join33(daemonDir(), "activity-profile.json");
59423
+ return join34(daemonDir(), "activity-profile.json");
59295
59424
  }
59296
59425
  var MAX_APPS = 300;
59297
59426
  var MAX_AGE_DAYS = 120;
@@ -59423,8 +59552,8 @@ async function runDaemon(opts = {}) {
59423
59552
  const VERSION = opts.version ?? process.env.CCB_DAEMON_VERSION ?? "dev";
59424
59553
  const TAG = opts.tag ?? "host-daemon";
59425
59554
  const log4 = (...args) => console.log(`[${TAG} ${(/* @__PURE__ */ new Date()).toISOString()}]`, ...args);
59426
- const pidfile = () => join34(daemonDir(), "daemon.lock");
59427
- const statusFile = () => join34(daemonDir(), "status.json");
59555
+ const pidfile = () => join35(daemonDir(), "daemon.lock");
59556
+ const statusFile = () => join35(daemonDir(), "status.json");
59428
59557
  const isAlive2 = (pid) => {
59429
59558
  try {
59430
59559
  process.kill(pid, 0);
@@ -59571,7 +59700,7 @@ async function runDaemon(opts = {}) {
59571
59700
  if (r.status === 401) {
59572
59701
  log4("device token no longer valid \u2014 dropping to local-only on restart");
59573
59702
  try {
59574
- unlinkSync2(join34(daemonDir(), "credentials.json"));
59703
+ unlinkSync2(join35(daemonDir(), "credentials.json"));
59575
59704
  } catch {
59576
59705
  }
59577
59706
  shutdown(0);
@@ -59643,7 +59772,7 @@ import { platform as platform2 } from "node:os";
59643
59772
 
59644
59773
  // ../../packages/host-core/dist/service/launchd.js
59645
59774
  import { writeFileSync as writeFileSync16, existsSync as existsSync18, mkdirSync as mkdirSync16, unlinkSync as unlinkSync3 } from "node:fs";
59646
- import { dirname as dirname14, join as join35 } from "node:path";
59775
+ import { dirname as dirname14, join as join36 } from "node:path";
59647
59776
  import { homedir as homedir14, userInfo } from "node:os";
59648
59777
 
59649
59778
  // ../../packages/host-core/dist/service/exec.js
@@ -59667,10 +59796,10 @@ function xml(s) {
59667
59796
  }
59668
59797
  function makeLaunchd(instanceId) {
59669
59798
  const label = SERVICE_LABEL_BASE + (instanceId ? `.${instanceId}` : "");
59670
- const plistPath = () => join35(homedir14(), "Library", "LaunchAgents", `${label}.plist`);
59799
+ const plistPath = () => join36(homedir14(), "Library", "LaunchAgents", `${label}.plist`);
59671
59800
  const domainTarget = () => `gui/${userInfo().uid}`;
59672
59801
  const serviceTarget = () => `${domainTarget()}/${label}`;
59673
- const logFile = () => join35(daemonDir(), "daemon.log");
59802
+ const logFile = () => join36(daemonDir(), "daemon.log");
59674
59803
  function buildPlist(spec) {
59675
59804
  const args = [spec.exec, ...spec.args].map((a) => ` <string>${xml(a)}</string>`).join("\n");
59676
59805
  const env = Object.entries(spec.env).map(([k, v]) => ` <key>${xml(k)}</key>
@@ -59765,7 +59894,7 @@ ${env}
59765
59894
 
59766
59895
  // ../../packages/host-core/dist/service/systemd.js
59767
59896
  import { writeFileSync as writeFileSync17, existsSync as existsSync19, mkdirSync as mkdirSync17, unlinkSync as unlinkSync4 } from "node:fs";
59768
- import { dirname as dirname15, join as join36 } from "node:path";
59897
+ import { dirname as dirname15, join as join37 } from "node:path";
59769
59898
  import { homedir as homedir15, userInfo as userInfo2 } from "node:os";
59770
59899
  function shq(s) {
59771
59900
  return `"${s.replace(/(["\\$`])/g, "\\$1")}"`;
@@ -59773,8 +59902,8 @@ function shq(s) {
59773
59902
  function makeSystemd(instanceId) {
59774
59903
  const unit = `tesseract-host${instanceId ? `-${instanceId}` : ""}.service`;
59775
59904
  const unitPath = () => {
59776
- const base = process.env.XDG_CONFIG_HOME || join36(homedir15(), ".config");
59777
- return join36(base, "systemd", "user", unit);
59905
+ const base = process.env.XDG_CONFIG_HOME || join37(homedir15(), ".config");
59906
+ return join37(base, "systemd", "user", unit);
59778
59907
  };
59779
59908
  function buildUnit(spec) {
59780
59909
  const execStart = [spec.exec, ...spec.args].map(shq).join(" ");
@@ -59845,11 +59974,11 @@ WantedBy=default.target
59845
59974
 
59846
59975
  // ../../packages/host-core/dist/service/windows.js
59847
59976
  import { writeFileSync as writeFileSync18, existsSync as existsSync20, mkdirSync as mkdirSync18, unlinkSync as unlinkSync5 } from "node:fs";
59848
- import { dirname as dirname16, join as join37 } from "node:path";
59977
+ import { dirname as dirname16, join as join38 } from "node:path";
59849
59978
  function makeWindowsTask(instanceId) {
59850
59979
  const task = `Fineguide\\TesseractHost${instanceId ? `-${instanceId}` : ""}`;
59851
- const wrapperPath = () => join37(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
59852
- const logFile = () => join37(daemonDir(), "daemon.log");
59980
+ const wrapperPath = () => join38(daemonDir(), `run-host${instanceId ? `-${instanceId}` : ""}.cmd`);
59981
+ const logFile = () => join38(daemonDir(), "daemon.log");
59853
59982
  const oneLine2 = (s) => s.replace(/[\r\n]+/g, " ");
59854
59983
  const envVal = (v) => oneLine2(v).replace(/%/g, "%%").replace(/"/g, "");
59855
59984
  const cmdArg = (a) => `"${oneLine2(a).replace(/"/g, "")}"`;
@@ -59931,7 +60060,7 @@ function getServiceController(instanceId) {
59931
60060
  var import_qrcode_terminal = __toESM(require_main(), 1);
59932
60061
  import { randomUUID as randomUUID9 } from "node:crypto";
59933
60062
  import { existsSync as existsSync21, rmSync as rmSync3 } from "node:fs";
59934
- import { join as join38 } from "node:path";
60063
+ import { join as join39 } from "node:path";
59935
60064
 
59936
60065
  // src/config.ts
59937
60066
  import { hostname as hostname5 } from "node:os";
@@ -60132,7 +60261,7 @@ async function logout() {
60132
60261
  }
60133
60262
  for (const f of ["credentials.json", "status.json", "daemon.lock"]) {
60134
60263
  try {
60135
- const p = join38(daemonDir(), f);
60264
+ const p = join39(daemonDir(), f);
60136
60265
  if (existsSync21(p)) rmSync3(p);
60137
60266
  } catch {
60138
60267
  }
@@ -60291,7 +60420,7 @@ function startSelfUpdater(current) {
60291
60420
  }
60292
60421
 
60293
60422
  // src/service.ts
60294
- import { join as join39 } from "node:path";
60423
+ import { join as join40 } from "node:path";
60295
60424
  import { platform as platform3 } from "node:os";
60296
60425
  import { existsSync as existsSync22, readFileSync as readFileSync15 } from "node:fs";
60297
60426
  function controller(instanceId) {
@@ -60306,7 +60435,7 @@ function buildSpec(cliEntry) {
60306
60435
  exec: process.execPath,
60307
60436
  args: [cliEntry, "run"],
60308
60437
  env: { CCB_DAEMON_DIR: daemonDir() },
60309
- logPath: join39(daemonDir(), "daemon.log")
60438
+ logPath: join40(daemonDir(), "daemon.log")
60310
60439
  };
60311
60440
  }
60312
60441
  var isAlive = (pid) => {
@@ -60318,7 +60447,7 @@ var isAlive = (pid) => {
60318
60447
  }
60319
60448
  };
60320
60449
  function runningDaemonInfo() {
60321
- const lock = join39(daemonDir(), "daemon.lock");
60450
+ const lock = join40(daemonDir(), "daemon.lock");
60322
60451
  try {
60323
60452
  if (!existsSync22(lock)) return null;
60324
60453
  const pid = Number(readFileSync15(lock, "utf-8").trim());
@@ -60357,7 +60486,7 @@ async function logs(instanceId, follow) {
60357
60486
  // src/cli.ts
60358
60487
  function pkgVersion() {
60359
60488
  try {
60360
- const p = join40(dirname17(fileURLToPath2(import.meta.url)), "..", "package.json");
60489
+ const p = join41(dirname17(fileURLToPath2(import.meta.url)), "..", "package.json");
60361
60490
  return JSON.parse(readFileSync16(p, "utf8")).version ?? "0.0.0";
60362
60491
  } catch {
60363
60492
  return "0.0.0";
@@ -60620,7 +60749,7 @@ async function main() {
60620
60749
  process.exit(1);
60621
60750
  }
60622
60751
  instance = flags.instance;
60623
- process.env.CCB_DAEMON_DIR = join40(homedir16(), ".tesseract", `daemon-${instance}`);
60752
+ process.env.CCB_DAEMON_DIR = join41(homedir16(), ".tesseract", `daemon-${instance}`);
60624
60753
  }
60625
60754
  const force = flags.yes === true || flags.force === true;
60626
60755
  const cliEntry = fileURLToPath2(import.meta.url);