tesseract-agent 0.8.0 → 0.8.2

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 +441 -307
  2. package/package.json +1 -1
@@ -3805,7 +3805,7 @@ var init_permissions = __esm({
3805
3805
  {
3806
3806
  id: "full-disk-access",
3807
3807
  label: "Full Disk Access",
3808
- why: "Show the folders you pinned in Finder\u2019s sidebar.",
3808
+ why: "Show the folders you pinned in Finder\u2019s sidebar, and import your Safari logins.",
3809
3809
  icon: "FolderLock",
3810
3810
  category: "system",
3811
3811
  applicablePlatforms: ["darwin"],
@@ -3849,7 +3849,7 @@ var init_permissions = __esm({
3849
3849
  });
3850
3850
 
3851
3851
  // ../../packages/shared/dist/ws-protocol.js
3852
- var MIRRORED_AGENT_EVENTS;
3852
+ var MIRRORED_AGENT_EVENTS, OWN_STUN_HOST, OWN_STUN_PORT, OWN_STUN_URL, PUBLIC_STUN_URLS, DEFAULT_ICE_SERVERS;
3853
3853
  var init_ws_protocol = __esm({
3854
3854
  "../../packages/shared/dist/ws-protocol.js"() {
3855
3855
  "use strict";
@@ -3899,6 +3899,18 @@ var init_ws_protocol = __esm({
3899
3899
  // would stomp a co-viewer's own picker with the driver's host); session:forked
3900
3900
  // and agent:context_usage are driver-only correlation/host-local replies.
3901
3901
  ]);
3902
+ OWN_STUN_HOST = "bridge.fineguide.ai";
3903
+ OWN_STUN_PORT = 3478;
3904
+ OWN_STUN_URL = `stun:${OWN_STUN_HOST}:${OWN_STUN_PORT}`;
3905
+ PUBLIC_STUN_URLS = [
3906
+ "stun:stun.l.google.com:19302",
3907
+ "stun:stun1.l.google.com:19302",
3908
+ "stun:stun.cloudflare.com:3478"
3909
+ ];
3910
+ DEFAULT_ICE_SERVERS = [
3911
+ { urls: OWN_STUN_URL },
3912
+ ...PUBLIC_STUN_URLS.map((urls) => ({ urls }))
3913
+ ];
3902
3914
  }
3903
3915
  });
3904
3916
 
@@ -4545,17 +4557,17 @@ function tessExt(token2) {
4545
4557
  }
4546
4558
  function walkTokens(tree) {
4547
4559
  const out = [];
4548
- const rec = (node, path5) => {
4560
+ const rec = (node, path6) => {
4549
4561
  if (!isObj(node))
4550
4562
  return;
4551
4563
  if (isToken(node)) {
4552
- out.push({ path: path5, token: node });
4564
+ out.push({ path: path6, token: node });
4553
4565
  return;
4554
4566
  }
4555
4567
  for (const key2 of Object.keys(node)) {
4556
4568
  if (key2.startsWith("$"))
4557
4569
  continue;
4558
- rec(node[key2], [...path5, key2]);
4570
+ rec(node[key2], [...path6, key2]);
4559
4571
  }
4560
4572
  };
4561
4573
  rec(tree, []);
@@ -4571,13 +4583,13 @@ function stringifyValue(v) {
4571
4583
  return String(v);
4572
4584
  }
4573
4585
  function flattenForDisplay(tree) {
4574
- return walkTokens(tree).map(({ path: path5, token: token2 }) => {
4586
+ return walkTokens(tree).map(({ path: path6, token: token2 }) => {
4575
4587
  const dark = tessExt(token2)?.modes?.dark;
4576
4588
  return {
4577
- path: path5,
4578
- dotPath: path5.join("."),
4579
- group: path5.slice(0, -1).join(" \xB7 "),
4580
- label: path5[path5.length - 1] ?? "",
4589
+ path: path6,
4590
+ dotPath: path6.join("."),
4591
+ group: path6.slice(0, -1).join(" \xB7 "),
4592
+ label: path6[path6.length - 1] ?? "",
4581
4593
  type: token2.$type,
4582
4594
  value: stringifyValue(token2.$value),
4583
4595
  isColor: token2.$type === "color",
@@ -4588,7 +4600,7 @@ function flattenForDisplay(tree) {
4588
4600
  function kebab(s) {
4589
4601
  return s.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/[^a-zA-Z0-9]+/g, "-").replace(/^-+|-+$/g, "").toLowerCase();
4590
4602
  }
4591
- function tokenCssVarName(path5, token2) {
4603
+ function tokenCssVarName(path6, token2) {
4592
4604
  const override = token2 ? tessExt(token2)?.cssVar : void 0;
4593
4605
  if (override) {
4594
4606
  const name = override.startsWith("--") ? override : `--${override}`;
@@ -4596,12 +4608,12 @@ function tokenCssVarName(path5, token2) {
4596
4608
  return name;
4597
4609
  }
4598
4610
  for (const { match, prefix } of VAR_ALIASES) {
4599
- if (match.length <= path5.length && match.every((seg, i) => path5[i] === seg)) {
4600
- const rest = path5.slice(match.length).map(kebab).filter(Boolean);
4611
+ if (match.length <= path6.length && match.every((seg, i) => path6[i] === seg)) {
4612
+ const rest = path6.slice(match.length).map(kebab).filter(Boolean);
4601
4613
  return ["--" + prefix, ...rest].join("-");
4602
4614
  }
4603
4615
  }
4604
- return ["--token", ...path5.map(kebab).filter(Boolean)].join("-");
4616
+ return ["--token", ...path6.map(kebab).filter(Boolean)].join("-");
4605
4617
  }
4606
4618
  function categoryRank(top) {
4607
4619
  const i = CATEGORY_ORDER.indexOf(top ?? "");
@@ -4635,8 +4647,8 @@ function tokensToCss(input) {
4635
4647
  const ordered = rows.map((r, i) => ({ r, i })).sort((a, b) => categoryRank(a.r.path[0]) - categoryRank(b.r.path[0]) || a.i - b.i).map((x) => x.r);
4636
4648
  const root = [];
4637
4649
  const dark = [];
4638
- for (const { path: path5, token: token2 } of ordered) {
4639
- const name = tokenCssVarName(path5, token2);
4650
+ for (const { path: path6, token: token2 } of ordered) {
4651
+ const name = tokenCssVarName(path6, token2);
4640
4652
  root.push(` ${name}: ${cssValue(token2.$type, token2.$value)};`);
4641
4653
  const d = tessExt(token2)?.modes?.dark;
4642
4654
  if (d !== void 0)
@@ -4890,10 +4902,10 @@ function applyDesignPack(current, packTokens, info, opts) {
4890
4902
  const { mode } = opts;
4891
4903
  const writeLeaves = (base, keep) => {
4892
4904
  let acc = base;
4893
- for (const { path: path5, token: token2 } of walkTokens(pack)) {
4894
- if (keep && !keep(path5))
4905
+ for (const { path: path6, token: token2 } of walkTokens(pack)) {
4906
+ if (keep && !keep(path6))
4895
4907
  continue;
4896
- acc = setTokenSegments(acc, path5, token2);
4908
+ acc = setTokenSegments(acc, path6, token2);
4897
4909
  }
4898
4910
  return acc;
4899
4911
  };
@@ -4978,14 +4990,14 @@ function setNested(obj, segs, value) {
4978
4990
  function tokensToTailwindTheme(input) {
4979
4991
  const tokens = normalizeTokens(input);
4980
4992
  const extend2 = {};
4981
- for (const { path: path5, token: token2 } of walkTokens(tokens)) {
4982
- const bucket2 = TW_BUCKETS.find((b) => b.match.length <= path5.length && b.match.every((seg, i) => path5[i] === seg));
4993
+ for (const { path: path6, token: token2 } of walkTokens(tokens)) {
4994
+ const bucket2 = TW_BUCKETS.find((b) => b.match.length <= path6.length && b.match.every((seg, i) => path6[i] === seg));
4983
4995
  if (!bucket2)
4984
4996
  continue;
4985
- const rest = path5.slice(bucket2.match.length).map(kebab).filter(Boolean);
4997
+ const rest = path6.slice(bucket2.match.length).map(kebab).filter(Boolean);
4986
4998
  if (rest.length === 0)
4987
4999
  continue;
4988
- const ref = `var(${tokenCssVarName(path5, token2)})`;
5000
+ const ref = `var(${tokenCssVarName(path6, token2)})`;
4989
5001
  if (!extend2[bucket2.key])
4990
5002
  extend2[bucket2.key] = {};
4991
5003
  if (bucket2.flat)
@@ -5016,8 +5028,8 @@ function leafSignature(token2) {
5016
5028
  }
5017
5029
  function indexLeaves(t) {
5018
5030
  const m = /* @__PURE__ */ new Map();
5019
- for (const { path: path5, token: token2 } of walkTokens(t)) {
5020
- m.set(path5.join("."), { sig: leafSignature(token2), disp: stringifyValue(token2.$value) });
5031
+ for (const { path: path6, token: token2 } of walkTokens(t)) {
5032
+ m.set(path6.join("."), { sig: leafSignature(token2), disp: stringifyValue(token2.$value) });
5021
5033
  }
5022
5034
  return m;
5023
5035
  }
@@ -5266,6 +5278,7 @@ var init_dist = __esm({
5266
5278
  init_surface_merge();
5267
5279
  init_permissions();
5268
5280
  init_ws_protocol();
5281
+ init_ws_protocol();
5269
5282
  init_frame();
5270
5283
  init_domain_id();
5271
5284
  init_plans();
@@ -6027,10 +6040,10 @@ function mergeDefs(...defs) {
6027
6040
  function cloneDef(schema) {
6028
6041
  return mergeDefs(schema._zod.def);
6029
6042
  }
6030
- function getElementAtPath(obj, path5) {
6031
- if (!path5)
6043
+ function getElementAtPath(obj, path6) {
6044
+ if (!path6)
6032
6045
  return obj;
6033
- return path5.reduce((acc, key2) => acc?.[key2], obj);
6046
+ return path6.reduce((acc, key2) => acc?.[key2], obj);
6034
6047
  }
6035
6048
  function promiseAllObject(promisesObj) {
6036
6049
  const keys = Object.keys(promisesObj);
@@ -6358,11 +6371,11 @@ function explicitlyAborted(x, startIndex = 0) {
6358
6371
  }
6359
6372
  return false;
6360
6373
  }
6361
- function prefixIssues(path5, issues) {
6374
+ function prefixIssues(path6, issues) {
6362
6375
  return issues.map((iss) => {
6363
6376
  var _a3;
6364
6377
  (_a3 = iss).path ?? (_a3.path = []);
6365
- iss.path.unshift(path5);
6378
+ iss.path.unshift(path6);
6366
6379
  return iss;
6367
6380
  });
6368
6381
  }
@@ -6579,16 +6592,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
6579
6592
  }
6580
6593
  function formatError(error51, mapper = (issue2) => issue2.message) {
6581
6594
  const fieldErrors = { _errors: [] };
6582
- const processError = (error52, path5 = []) => {
6595
+ const processError = (error52, path6 = []) => {
6583
6596
  for (const issue2 of error52.issues) {
6584
6597
  if (issue2.code === "invalid_union" && issue2.errors.length) {
6585
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
6598
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
6586
6599
  } else if (issue2.code === "invalid_key") {
6587
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
6600
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
6588
6601
  } else if (issue2.code === "invalid_element") {
6589
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
6602
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
6590
6603
  } else {
6591
- const fullpath = [...path5, ...issue2.path];
6604
+ const fullpath = [...path6, ...issue2.path];
6592
6605
  if (fullpath.length === 0) {
6593
6606
  fieldErrors._errors.push(mapper(issue2));
6594
6607
  } else {
@@ -6615,17 +6628,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
6615
6628
  }
6616
6629
  function treeifyError(error51, mapper = (issue2) => issue2.message) {
6617
6630
  const result = { errors: [] };
6618
- const processError = (error52, path5 = []) => {
6631
+ const processError = (error52, path6 = []) => {
6619
6632
  var _a3, _b;
6620
6633
  for (const issue2 of error52.issues) {
6621
6634
  if (issue2.code === "invalid_union" && issue2.errors.length) {
6622
- issue2.errors.map((issues) => processError({ issues }, [...path5, ...issue2.path]));
6635
+ issue2.errors.map((issues) => processError({ issues }, [...path6, ...issue2.path]));
6623
6636
  } else if (issue2.code === "invalid_key") {
6624
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
6637
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
6625
6638
  } else if (issue2.code === "invalid_element") {
6626
- processError({ issues: issue2.issues }, [...path5, ...issue2.path]);
6639
+ processError({ issues: issue2.issues }, [...path6, ...issue2.path]);
6627
6640
  } else {
6628
- const fullpath = [...path5, ...issue2.path];
6641
+ const fullpath = [...path6, ...issue2.path];
6629
6642
  if (fullpath.length === 0) {
6630
6643
  result.errors.push(mapper(issue2));
6631
6644
  continue;
@@ -6657,8 +6670,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
6657
6670
  }
6658
6671
  function toDotPath(_path) {
6659
6672
  const segs = [];
6660
- const path5 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6661
- for (const seg of path5) {
6673
+ const path6 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
6674
+ for (const seg of path6) {
6662
6675
  if (typeof seg === "number")
6663
6676
  segs.push(`[${seg}]`);
6664
6677
  else if (typeof seg === "symbol")
@@ -20088,13 +20101,13 @@ function resolveRef(ref, ctx2) {
20088
20101
  if (!ref.startsWith("#")) {
20089
20102
  throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
20090
20103
  }
20091
- const path5 = ref.slice(1).split("/").filter(Boolean);
20092
- if (path5.length === 0) {
20104
+ const path6 = ref.slice(1).split("/").filter(Boolean);
20105
+ if (path6.length === 0) {
20093
20106
  return ctx2.rootSchema;
20094
20107
  }
20095
20108
  const defsKey = ctx2.version === "draft-2020-12" ? "$defs" : "definitions";
20096
- if (path5[0] === defsKey) {
20097
- const key2 = path5[1];
20109
+ if (path6[0] === defsKey) {
20110
+ const key2 = path6[1];
20098
20111
  if (!key2 || !ctx2.defs[key2]) {
20099
20112
  throw new Error(`Reference not found: ${ref}`);
20100
20113
  }
@@ -21703,10 +21716,10 @@ function buildCanvasTools(deps) {
21703
21716
  const id = args.id ? slugify3(args.id) : `${slugify3(args.title ?? "canvas")}-${Math.random().toString(36).slice(2, 8)}`;
21704
21717
  const dir2 = await deps.canvasDir();
21705
21718
  mkdirSync2(dir2, { recursive: true });
21706
- const path5 = join5(dir2, `${id}.html`);
21707
- writeFileSync3(path5, args.html, "utf8");
21708
- deps.emitCanvasReady({ path: path5, title: args.title, id });
21709
- return { content: [{ type: "text", text: `Rendered canvas "${args.title ?? id}" in the side panel (${path5}). Call render_canvas again with id "${id}" to transform it.` }] };
21719
+ const path6 = join5(dir2, `${id}.html`);
21720
+ writeFileSync3(path6, args.html, "utf8");
21721
+ deps.emitCanvasReady({ path: path6, title: args.title, id });
21722
+ return { content: [{ type: "text", text: `Rendered canvas "${args.title ?? id}" in the side panel (${path6}). Call render_canvas again with id "${id}" to transform it.` }] };
21710
21723
  })
21711
21724
  ];
21712
21725
  }
@@ -23011,9 +23024,57 @@ var init_trace_store = __esm({
23011
23024
  }
23012
23025
  });
23013
23026
 
23027
+ // ../../packages/agent-core/dist/cost-ledger.js
23028
+ import { promises as fs2 } from "node:fs";
23029
+ import path2 from "node:path";
23030
+ var DIR2, CostLedger;
23031
+ var init_cost_ledger = __esm({
23032
+ "../../packages/agent-core/dist/cost-ledger.js"() {
23033
+ "use strict";
23034
+ DIR2 = ".ccb-traces";
23035
+ CostLedger = class {
23036
+ fileFor(projectDir, sessionId) {
23037
+ return path2.join(projectDir, DIR2, sessionId, "cost.jsonl");
23038
+ }
23039
+ /** Append one turn's cost. Creates the dir + a `.gitignore` (the traces dir is inside the
23040
+ * user's project, usually a git repo) on first write. */
23041
+ async append(projectDir, sessionId, entry) {
23042
+ try {
23043
+ const file2 = this.fileFor(projectDir, sessionId);
23044
+ await fs2.mkdir(path2.dirname(file2), { recursive: true });
23045
+ await fs2.writeFile(path2.join(projectDir, DIR2, ".gitignore"), "*\n", "utf8").catch(() => {
23046
+ });
23047
+ await fs2.appendFile(file2, JSON.stringify(entry) + "\n", "utf8");
23048
+ } catch {
23049
+ }
23050
+ }
23051
+ /** Cumulative session cost = sum of every recorded turn. 0 if the ledger is missing. */
23052
+ async total(projectDir, sessionId) {
23053
+ try {
23054
+ const raw = await fs2.readFile(this.fileFor(projectDir, sessionId), "utf8");
23055
+ let sum = 0;
23056
+ for (const line of raw.split("\n")) {
23057
+ if (!line.trim())
23058
+ continue;
23059
+ try {
23060
+ const e = JSON.parse(line);
23061
+ if (typeof e.costUsd === "number" && Number.isFinite(e.costUsd))
23062
+ sum += e.costUsd;
23063
+ } catch {
23064
+ }
23065
+ }
23066
+ return sum;
23067
+ } catch {
23068
+ return 0;
23069
+ }
23070
+ }
23071
+ };
23072
+ }
23073
+ });
23074
+
23014
23075
  // ../../packages/agent-core/dist/session-store.js
23015
23076
  import { readFile as readFile4, stat } from "node:fs/promises";
23016
- import { listSessions, getSessionMessages, forkSession } from "@anthropic-ai/claude-agent-sdk";
23077
+ import { listSessions, getSessionMessages, getSubagentMessages as sdkGetSubagentMessages, forkSession } from "@anthropic-ai/claude-agent-sdk";
23017
23078
  function toSessionInfo(s) {
23018
23079
  const fromFirst = stripPromptPrefix(s.firstPrompt ?? "").slice(0, 80);
23019
23080
  const fromSummary = stripPromptPrefix(s.summary ?? "").slice(0, 80);
@@ -23128,7 +23189,7 @@ ${input.command}
23128
23189
  }
23129
23190
  }
23130
23191
  }
23131
- blocks.push({ kind: "tool_use", content: detail });
23192
+ blocks.push({ kind: "tool_use", content: detail, name });
23132
23193
  } else if (b.type === "advisor_tool_result") {
23133
23194
  const c = b.content;
23134
23195
  const text4 = c?.type === "advisor_result" ? (c.text ?? "").trim() : "";
@@ -23199,32 +23260,46 @@ var init_session_store = __esm({
23199
23260
  }
23200
23261
  async getSessionMessages(sessionId) {
23201
23262
  try {
23202
- const raw = await getSessionMessages(sessionId);
23203
- const messages = [];
23204
- for (const entry of raw) {
23205
- const blocks = extractBlocks(entry.message);
23206
- if (blocks.length === 0 && entry.type === "user")
23207
- continue;
23208
- let textContent = blocks.filter((b) => b.kind === "text").map((b) => b.content).join("\n");
23209
- if (entry.type === "user") {
23210
- textContent = stripPromptPrefix(textContent);
23211
- }
23212
- messages.push({
23213
- role: entry.type === "user" ? "user" : "assistant",
23214
- // Flat content feeds summaries/merge seeds — keep advisor reviews OUT of it
23215
- // (they're a side-channel review, rendered as their own card, like tool_use).
23216
- content: textContent || blocks.find((b) => b.kind !== "advisor")?.content || "",
23217
- blocks: entry.type === "assistant" ? blocks : void 0,
23218
- // Thread the per-message SDK uuid so the renderer can pass it as
23219
- // session:fork.upToMessageId ("fork from here").
23220
- uuid: typeof entry.uuid === "string" ? entry.uuid : void 0
23221
- });
23222
- }
23223
- return messages;
23263
+ return this.rawToMessages(await getSessionMessages(sessionId));
23264
+ } catch {
23265
+ return [];
23266
+ }
23267
+ }
23268
+ /** Read a SUBAGENT's (Task tool) transcript from its sidecar JSONL — the granular
23269
+ * activity that never streams to the client. `agentId` is the subagent's id (the app's
23270
+ * subagent-card `taskId`, which equals `task_started.task_id` and the sidecar filename);
23271
+ * `projectDir` scopes the lookup to the right project (required on a remote host). */
23272
+ async getSubagentMessages(sessionId, agentId, projectDir) {
23273
+ try {
23274
+ return this.rawToMessages(await sdkGetSubagentMessages(sessionId, agentId, projectDir ? { dir: projectDir } : void 0));
23224
23275
  } catch {
23225
23276
  return [];
23226
23277
  }
23227
23278
  }
23279
+ /** Shared normalization: raw SDK transcript entries → the app's SessionMessage shape. */
23280
+ rawToMessages(raw) {
23281
+ const messages = [];
23282
+ for (const entry of raw) {
23283
+ const blocks = extractBlocks(entry.message);
23284
+ if (blocks.length === 0 && entry.type === "user")
23285
+ continue;
23286
+ let textContent = blocks.filter((b) => b.kind === "text").map((b) => b.content).join("\n");
23287
+ if (entry.type === "user") {
23288
+ textContent = stripPromptPrefix(textContent);
23289
+ }
23290
+ messages.push({
23291
+ role: entry.type === "user" ? "user" : "assistant",
23292
+ // Flat content feeds summaries/merge seeds — keep advisor reviews OUT of it
23293
+ // (they're a side-channel review, rendered as their own card, like tool_use).
23294
+ content: textContent || blocks.find((b) => b.kind !== "advisor")?.content || "",
23295
+ blocks: entry.type === "assistant" ? blocks : void 0,
23296
+ // Thread the per-message SDK uuid so the renderer can pass it as
23297
+ // session:fork.upToMessageId ("fork from here").
23298
+ uuid: typeof entry.uuid === "string" ? entry.uuid : void 0
23299
+ });
23300
+ }
23301
+ return messages;
23302
+ }
23228
23303
  /** Fork a session into a NEW session id (non-destructive — the source transcript
23229
23304
  * is preserved). `upToMessageId` slices the fork at a message uuid; `title` names
23230
23305
  * the fork; `projectDir` scopes the lookup to the right project's session store.
@@ -23670,14 +23745,14 @@ function newestVersionManagerNode() {
23670
23745
  continue;
23671
23746
  }
23672
23747
  for (const name of names) {
23673
- const path5 = bin(join9(dir2, name));
23674
- if (!existsSync2(path5))
23748
+ const path6 = bin(join9(dir2, name));
23749
+ if (!existsSync2(path6))
23675
23750
  continue;
23676
23751
  const parts = name.replace(/^v/, "").split(".").map((n) => Number.parseInt(n, 10) || 0);
23677
23752
  const ver = [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
23678
23753
  const gt = !best || ver[0] > best.ver[0] || ver[0] === best.ver[0] && (ver[1] > best.ver[1] || ver[1] === best.ver[1] && ver[2] > best.ver[2]);
23679
23754
  if (gt)
23680
- best = { ver, path: path5 };
23755
+ best = { ver, path: path6 };
23681
23756
  }
23682
23757
  }
23683
23758
  return best?.path ?? null;
@@ -23690,8 +23765,8 @@ function loginShellNode() {
23690
23765
  return null;
23691
23766
  try {
23692
23767
  const out = execFileSync(shell, ["-lic", `printf '<<NODE:%s>>' "$(command -v node 2>/dev/null)"`], { encoding: "utf8", timeout: 4e3, stdio: ["ignore", "pipe", "ignore"] });
23693
- const path5 = out.match(/<<NODE:(.*?)>>/)?.[1]?.trim();
23694
- return path5 && existsSync2(path5) ? path5 : null;
23768
+ const path6 = out.match(/<<NODE:(.*?)>>/)?.[1]?.trim();
23769
+ return path6 && existsSync2(path6) ? path6 : null;
23695
23770
  } catch {
23696
23771
  return null;
23697
23772
  }
@@ -23743,6 +23818,29 @@ function traceFrame(message) {
23743
23818
  }
23744
23819
  const sub = typeof message.subtype === "string" ? `/${message.subtype}` : "";
23745
23820
  const parent = message.parent_tool_use_id ? " (subagent)" : "";
23821
+ if (type === "system" && typeof message.subtype === "string" && message.subtype.startsWith("task_")) {
23822
+ const m = message;
23823
+ const u = m.usage ?? {};
23824
+ let patch = "";
23825
+ if (m.patch && typeof m.patch === "object") {
23826
+ try {
23827
+ patch = `patch=${JSON.stringify(m.patch).slice(0, 200)}`;
23828
+ } catch {
23829
+ patch = "patch=?";
23830
+ }
23831
+ }
23832
+ const bits = [
23833
+ typeof m.task_id === "string" ? `id=${m.task_id.slice(0, 8)}` : "",
23834
+ typeof m.status === "string" ? `status=${m.status}` : "",
23835
+ typeof m.subagent_type === "string" ? `agent=${m.subagent_type}` : "",
23836
+ typeof m.last_tool_name === "string" ? `last=${m.last_tool_name}` : "",
23837
+ typeof u.tool_uses === "number" ? `tools=${u.tool_uses}` : "",
23838
+ typeof u.total_tokens === "number" ? `tok=${u.total_tokens}` : "",
23839
+ patch
23840
+ ].filter(Boolean).join(" ");
23841
+ log(`frame ${type}${sub}${parent}${bits ? " \u2014 " + bits : ""}`);
23842
+ return;
23843
+ }
23746
23844
  log(`frame ${type}${sub}${parent}`);
23747
23845
  }
23748
23846
  function rawFramePreview(message, limit = 2e3) {
@@ -24100,9 +24198,9 @@ function editedPathOf(toolInput) {
24100
24198
  const p = i?.file_path ?? i?.notebook_path;
24101
24199
  return typeof p === "string" && p.length > 0 ? p : null;
24102
24200
  }
24103
- async function snapshotFile(path5) {
24201
+ async function snapshotFile(path6) {
24104
24202
  try {
24105
- const buf = await readFile6(path5);
24203
+ const buf = await readFile6(path6);
24106
24204
  if (buf.length > EDIT_PREVIEW_CAP)
24107
24205
  return { noPreview: true };
24108
24206
  if (buf.subarray(0, 8192).includes(0))
@@ -24150,7 +24248,7 @@ MOBILE (${fw}):
24150
24248
  return "";
24151
24249
  }
24152
24250
  }
24153
- var cachedClaudeExe, cachedNodeExe, HUMAN_READABLE_FIELDS, THINKING_THROTTLE_MS, SYSTEM_EVENT_CATEGORY, TOOL_RESULT_CAP, MAX_RESULT_IMAGES, MAX_IMAGE_BASE64, PERMISSION_MODES, EDIT_PREVIEW_CAP, AsyncMessagePump, IDLE_REAP_MS, MODERATE_IDLE_MS, STEER_COALESCE_MS, STOP_HARD_KILL_AFTER_MS, AgentManager;
24251
+ var cachedClaudeExe, cachedNodeExe, HUMAN_READABLE_FIELDS, SYSTEM_EVENT_CATEGORY, TOOL_RESULT_CAP, MAX_RESULT_IMAGES, MAX_IMAGE_BASE64, PERMISSION_MODES, EDIT_PREVIEW_CAP, AsyncMessagePump, IDLE_REAP_MS, MODERATE_IDLE_MS, STEER_COALESCE_MS, STOP_HARD_KILL_AFTER_MS, AgentManager;
24154
24252
  var init_agent_manager = __esm({
24155
24253
  "../../packages/agent-core/dist/agent-manager.js"() {
24156
24254
  "use strict";
@@ -24173,13 +24271,13 @@ var init_agent_manager = __esm({
24173
24271
  init_narrator();
24174
24272
  init_plan_splitter();
24175
24273
  init_trace_store();
24274
+ init_cost_ledger();
24176
24275
  init_session_store();
24177
24276
  init_session_usage();
24178
24277
  init_kill_tree();
24179
24278
  init_log();
24180
24279
  init_sources();
24181
24280
  HUMAN_READABLE_FIELDS = ["message", "text", "content", "summary", "description", "output", "stdout", "error", "reason", "name"];
24182
- THINKING_THROTTLE_MS = 2e3;
24183
24281
  SYSTEM_EVENT_CATEGORY = {
24184
24282
  hook_started: "hook",
24185
24283
  hook_progress: "hook",
@@ -24242,6 +24340,7 @@ var init_agent_manager = __esm({
24242
24340
  projectDir;
24243
24341
  /** Per-generation trace persistence (.ccb-traces on the agent's disk). */
24244
24342
  traceStore = new TraceStore();
24343
+ costLedger = new CostLedger();
24245
24344
  /** On-disk session transcripts — used by mergeSessions to gather context. */
24246
24345
  sessionStore = new SessionStore();
24247
24346
  liveSessions = /* @__PURE__ */ new Map();
@@ -24942,6 +25041,21 @@ ${qText}`;
24942
25041
  return null;
24943
25042
  return this.traceStore.readTurn(dir2, sessionId, turnId);
24944
25043
  }
25044
+ /** A subagent's activity transcript (from its sidecar JSONL) — the granular frames the
25045
+ * Task tool never streams to the client. `agentId` == the subagent-card taskId. Falls
25046
+ * back to the resident session's cwd / configured project for the file lookup. */
25047
+ async getSubagentMessages(sessionId, agentId, projectDir) {
25048
+ const dir2 = this.liveSessions.get(sessionId)?.cwd ?? projectDir ?? this.projectDir ?? void 0;
25049
+ return this.sessionStore.getSubagentMessages(sessionId, agentId, dir2);
25050
+ }
25051
+ /** Authoritative cumulative cost (USD) for a session, summed from the durable per-turn cost
25052
+ * ledger — survives reload/resume (unlike a client-side sum of the text-only transcript). */
25053
+ async getSessionCost(sessionId, projectDir) {
25054
+ const dir2 = this.liveSessions.get(sessionId)?.cwd ?? projectDir ?? this.projectDir ?? void 0;
25055
+ if (!dir2)
25056
+ return 0;
25057
+ return this.costLedger.total(dir2, sessionId);
25058
+ }
24945
25059
  /** Merge sessions into a NEW one: gather each transcript, seed a fresh session with
24946
25060
  * the combined context + an instruction to summarize-and-continue. The new session
24947
25061
  * resolves via session:created (clientRequestId-keyed) exactly like a brand-new
@@ -25668,10 +25782,10 @@ CRITICAL RULES:
25668
25782
  matcher: "Edit|Write|MultiEdit|NotebookEdit",
25669
25783
  hooks: [async (input) => {
25670
25784
  if (input.hook_event_name === "PreToolUse" && !input.agent_id) {
25671
- const path5 = editedPathOf(input.tool_input);
25672
- if (path5) {
25673
- const snap = await snapshotFile(path5);
25674
- pendingEdits.set(input.tool_use_id, { path: path5, before: snap.content, created: snap.created, noPreview: snap.noPreview });
25785
+ const path6 = editedPathOf(input.tool_input);
25786
+ if (path6) {
25787
+ const snap = await snapshotFile(path6);
25788
+ pendingEdits.set(input.tool_use_id, { path: path6, before: snap.content, created: snap.created, noPreview: snap.noPreview });
25675
25789
  }
25676
25790
  }
25677
25791
  return {};
@@ -25683,14 +25797,14 @@ CRITICAL RULES:
25683
25797
  if (input.hook_event_name === "PostToolUse" && !input.agent_id) {
25684
25798
  const pre = pendingEdits.get(input.tool_use_id);
25685
25799
  pendingEdits.delete(input.tool_use_id);
25686
- const path5 = pre?.path ?? editedPathOf(input.tool_input);
25687
- if (path5) {
25688
- const post = await snapshotFile(path5);
25800
+ const path6 = pre?.path ?? editedPathOf(input.tool_input);
25801
+ if (path6) {
25802
+ const post = await snapshotFile(path6);
25689
25803
  emitFileEdit({
25690
25804
  type: "agent:file_edit",
25691
25805
  sessionId: live.sessionId,
25692
25806
  toolName: input.tool_name,
25693
- path: path5,
25807
+ path: path6,
25694
25808
  before: pre?.before,
25695
25809
  after: post.content,
25696
25810
  created: pre?.created || void 0,
@@ -25717,6 +25831,9 @@ CRITICAL RULES:
25717
25831
  const spawnEnv = {
25718
25832
  ...process.env,
25719
25833
  ...options.env,
25834
+ // params.env carries CLAUDE_AUTOCOMPACT_PCT_OVERRIDE from the user's setting
25835
+ // (getAgentSettings) — IF this CLI honours it, native mid-run compaction fires
25836
+ // at the same threshold as our renderer-side proactive `/compact`.
25720
25837
  ...params.env ?? {},
25721
25838
  ...params.engineEnv ?? {},
25722
25839
  CCB_IPC_PORT: String(live.ipcPort)
@@ -25840,17 +25957,8 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
25840
25957
  };
25841
25958
  const emitEvent = (spec, parentId) => {
25842
25959
  const payload = { ...spec, ...parentId ? { parentToolUseId: parentId } : {} };
25843
- if (spec.updateKey === "thinking_tokens") {
25844
- const now2 = Date.now();
25845
- if (now2 - (live.lastThinkingEmitAt ?? 0) >= THINKING_THROTTLE_MS) {
25846
- live.lastThinkingEmitAt = now2;
25847
- live.pendingThinking = void 0;
25848
- sendEvent(payload);
25849
- } else {
25850
- live.pendingThinking = payload;
25851
- }
25960
+ if (spec.updateKey === "thinking_tokens")
25852
25961
  return;
25853
- }
25854
25962
  flushPendingThinking();
25855
25963
  sendEvent(payload);
25856
25964
  };
@@ -26027,6 +26135,16 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
26027
26135
  frames: finishedTrace.frames
26028
26136
  });
26029
26137
  }
26138
+ if (typeof r.total_cost_usd === "number" && r.total_cost_usd > 0 && live.cwd) {
26139
+ const uc = r.usage;
26140
+ void this.costLedger.append(live.cwd, turnSid, {
26141
+ ...traceTurnId ? { turnId: traceTurnId } : {},
26142
+ ts: Date.now(),
26143
+ costUsd: r.total_cost_usd,
26144
+ ...typeof uc?.input_tokens === "number" ? { inputTokens: uc.input_tokens } : {},
26145
+ ...typeof uc?.output_tokens === "number" ? { outputTokens: uc.output_tokens } : {}
26146
+ });
26147
+ }
26030
26148
  if (r.subtype === "success") {
26031
26149
  if (!turnStreamed && Array.isArray(live.lastAssistantContent)) {
26032
26150
  for (const blk of live.lastAssistantContent) {
@@ -26135,6 +26253,7 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
26135
26253
  ...sstr(m.tool_use_id) ? { toolUseId: sstr(m.tool_use_id) } : {},
26136
26254
  ...parentToolUseId ? { parentToolUseId } : {},
26137
26255
  description: sstr(m.description) || "subagent task",
26256
+ ...sstr(m.prompt) ? { prompt: sstr(m.prompt) } : {},
26138
26257
  ...sstr(m.subagent_type) ? { subagentType: sstr(m.subagent_type) } : {},
26139
26258
  ...sstr(m.workflow_name) ? { workflowName: sstr(m.workflow_name) } : {}
26140
26259
  });
@@ -26409,7 +26528,7 @@ ${params.appendSystemPrompt}` : ""), live.sessionId) },
26409
26528
  const detail = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
26410
26529
  ${err.stack}` : ""}` : String(err);
26411
26530
  log("Session iterator error:", sid, detail);
26412
- emit2({ type: "chat:error", sessionId: sid, error: detail });
26531
+ emit2({ type: "chat:error", sessionId: sid, error: detail, transient: true });
26413
26532
  emit2({ type: "agent:status", sessionId: sid, status: "error" });
26414
26533
  }
26415
26534
  } finally {
@@ -28352,13 +28471,13 @@ function __disposeResources(env) {
28352
28471
  }
28353
28472
  return next();
28354
28473
  }
28355
- function __rewriteRelativeImportExtension(path5, preserveJsx) {
28356
- if (typeof path5 === "string" && /^\.\.?\//.test(path5)) {
28357
- return path5.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
28474
+ function __rewriteRelativeImportExtension(path6, preserveJsx) {
28475
+ if (typeof path6 === "string" && /^\.\.?\//.test(path6)) {
28476
+ return path6.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
28358
28477
  return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
28359
28478
  });
28360
28479
  }
28361
- return path5;
28480
+ return path6;
28362
28481
  }
28363
28482
  var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
28364
28483
  var init_tslib_es6 = __esm({
@@ -39953,14 +40072,14 @@ var require_dependency_container = __commonJS({
39953
40072
  provider = providerOrConstructor;
39954
40073
  }
39955
40074
  if (providers_1.isTokenProvider(provider)) {
39956
- const path5 = [token2];
40075
+ const path6 = [token2];
39957
40076
  let tokenProvider = provider;
39958
40077
  while (tokenProvider != null) {
39959
40078
  const currentToken = tokenProvider.useToken;
39960
- if (path5.includes(currentToken)) {
39961
- throw new Error(`Token registration cycle detected! ${[...path5, currentToken].join(" -> ")}`);
40079
+ if (path6.includes(currentToken)) {
40080
+ throw new Error(`Token registration cycle detected! ${[...path6, currentToken].join(" -> ")}`);
39962
40081
  }
39963
- path5.push(currentToken);
40082
+ path6.push(currentToken);
39964
40083
  const registration = this._registry.get(currentToken);
39965
40084
  if (registration && providers_1.isTokenProvider(registration.provider)) {
39966
40085
  tokenProvider = registration.provider;
@@ -45305,7 +45424,7 @@ var init_framing = __esm({
45305
45424
  });
45306
45425
 
45307
45426
  // ../../packages/host-core/dist/peer-link/transport.js
45308
- function socketPeerLink(socket2, peerHostId, path5, opts) {
45427
+ function socketPeerLink(socket2, peerHostId, path6, opts) {
45309
45428
  const dec = new FrameDecoder();
45310
45429
  const dataCbs = /* @__PURE__ */ new Set();
45311
45430
  const closeCbs = /* @__PURE__ */ new Set();
@@ -45379,7 +45498,7 @@ function socketPeerLink(socket2, peerHostId, path5, opts) {
45379
45498
  }
45380
45499
  const link = {
45381
45500
  peerHostId,
45382
- path: path5,
45501
+ path: path6,
45383
45502
  send(chunk) {
45384
45503
  if (!closed)
45385
45504
  socket2.write(encodeFrame2(chunk));
@@ -47670,6 +47789,8 @@ async function createClaudeCodeBackend(send3, onBrowserRequest, loadPluginRuntim
47670
47789
  listSessions: (projectDir) => store.getSessions(projectDir),
47671
47790
  searchSessions: (query2, projectDir) => store.searchSessions(query2, projectDir),
47672
47791
  getMessages: (sessionId) => store.getSessionMessages(sessionId),
47792
+ getSubagentMessages: (sessionId, agentId, projectDir) => manager2.getSubagentMessages(sessionId, agentId, projectDir),
47793
+ getSessionCost: (sessionId, projectDir) => manager2.getSessionCost(sessionId, projectDir),
47673
47794
  getSessionArtifacts: (sessionId, projectDir) => readSessionArtifacts2(sessionId, projectDir),
47674
47795
  summarizeSession: async (sessionId) => manager2.summarizeSession(await store.getSessionMessages(sessionId)),
47675
47796
  setConfig: (projectDir) => {
@@ -48146,15 +48267,15 @@ import { homedir as homedir9 } from "node:os";
48146
48267
  init_dist();
48147
48268
 
48148
48269
  // ../../packages/plugin-host/dist/discovery.js
48149
- import fs2 from "node:fs";
48150
- import path2 from "node:path";
48270
+ import fs3 from "node:fs";
48271
+ import path3 from "node:path";
48151
48272
  var isWindows = process.platform === "win32";
48152
48273
  function checkTrust(rootDir, trusted, relaxHardlink = false) {
48153
48274
  if (trusted)
48154
48275
  return null;
48155
48276
  let st;
48156
48277
  try {
48157
- st = fs2.statSync(rootDir);
48278
+ st = fs3.statSync(rootDir);
48158
48279
  } catch {
48159
48280
  return "unreadable";
48160
48281
  }
@@ -48168,7 +48289,7 @@ function checkTrust(rootDir, trusted, relaxHardlink = false) {
48168
48289
  if (!relaxHardlink) {
48169
48290
  for (const name of ["package.json"]) {
48170
48291
  try {
48171
- const f = fs2.statSync(path2.join(rootDir, name));
48292
+ const f = fs3.statSync(path3.join(rootDir, name));
48172
48293
  if (f.nlink > 1)
48173
48294
  return `${name} is a hardlink`;
48174
48295
  } catch {
@@ -48183,20 +48304,20 @@ function discover(roots) {
48183
48304
  for (const root of roots) {
48184
48305
  let entries;
48185
48306
  try {
48186
- entries = fs2.readdirSync(root.dir, { withFileTypes: true });
48307
+ entries = fs3.readdirSync(root.dir, { withFileTypes: true });
48187
48308
  } catch {
48188
48309
  continue;
48189
48310
  }
48190
48311
  for (const ent of entries) {
48191
48312
  if (!ent.isDirectory() && !ent.isSymbolicLink())
48192
48313
  continue;
48193
- const rootDir = path2.join(root.dir, ent.name);
48194
- if (!fs2.existsSync(path2.join(rootDir, "package.json"))) {
48314
+ const rootDir = path3.join(root.dir, ent.name);
48315
+ if (!fs3.existsSync(path3.join(rootDir, "package.json"))) {
48195
48316
  if (ent.name.startsWith("@")) {
48196
48317
  try {
48197
- for (const sub of fs2.readdirSync(rootDir, { withFileTypes: true })) {
48198
- const subDir = path2.join(rootDir, sub.name);
48199
- if (fs2.existsSync(path2.join(subDir, "package.json")))
48318
+ for (const sub of fs3.readdirSync(rootDir, { withFileTypes: true })) {
48319
+ const subDir = path3.join(rootDir, sub.name);
48320
+ if (fs3.existsSync(path3.join(subDir, "package.json")))
48200
48321
  pushCandidate(subDir, root, candidates, diagnostics);
48201
48322
  }
48202
48323
  } catch {
@@ -48218,13 +48339,13 @@ function pushCandidate(rootDir, root, candidates, diagnostics) {
48218
48339
  }
48219
48340
 
48220
48341
  // ../../packages/plugin-host/dist/manifest.js
48221
- import fs3 from "node:fs";
48222
- import path3 from "node:path";
48342
+ import fs4 from "node:fs";
48343
+ import path4 from "node:path";
48223
48344
  function resolveEntry(rootDir, rel, pkg) {
48224
48345
  const candidates = [rel, pkg.module, pkg.main, "index.js", "index.ts", "dist/index.js"].filter(Boolean);
48225
48346
  for (const c of candidates) {
48226
- const abs = path3.resolve(rootDir, c);
48227
- if (fs3.existsSync(abs))
48347
+ const abs = path4.resolve(rootDir, c);
48348
+ if (fs4.existsSync(abs))
48228
48349
  return abs;
48229
48350
  }
48230
48351
  return null;
@@ -48232,7 +48353,7 @@ function resolveEntry(rootDir, rel, pkg) {
48232
48353
  function readManifest2(rootDir) {
48233
48354
  let pkg;
48234
48355
  try {
48235
- pkg = JSON.parse(fs3.readFileSync(path3.join(rootDir, "package.json"), "utf8"));
48356
+ pkg = JSON.parse(fs4.readFileSync(path4.join(rootDir, "package.json"), "utf8"));
48236
48357
  } catch {
48237
48358
  return { manifest: null, diagnostic: `${rootDir}: unreadable package.json` };
48238
48359
  }
@@ -48557,12 +48678,12 @@ function createOpenClawAdapter(pluginId, config2, secretResolver, registry2) {
48557
48678
  }
48558
48679
 
48559
48680
  // ../../packages/plugin-host/dist/openclaw-stub.js
48560
- import fs4 from "node:fs";
48561
- import path4 from "node:path";
48681
+ import fs5 from "node:fs";
48682
+ import path5 from "node:path";
48562
48683
  function writeOpenClawShim(pluginsDir) {
48563
- const stubDir = path4.join(pluginsDir, "node_modules", "openclaw");
48564
- fs4.mkdirSync(stubDir, { recursive: true });
48565
- fs4.writeFileSync(path4.join(stubDir, "package.json"), JSON.stringify({
48684
+ const stubDir = path5.join(pluginsDir, "node_modules", "openclaw");
48685
+ fs5.mkdirSync(stubDir, { recursive: true });
48686
+ fs5.writeFileSync(path5.join(stubDir, "package.json"), JSON.stringify({
48566
48687
  name: "openclaw",
48567
48688
  version: "0.0.0-tesseract-compat",
48568
48689
  type: "module",
@@ -48579,8 +48700,8 @@ function writeOpenClawShim(pluginsDir) {
48579
48700
  "export default { definePluginEntry };",
48580
48701
  ""
48581
48702
  ].join("\n");
48582
- fs4.writeFileSync(path4.join(stubDir, "plugin-entry.mjs"), entrySrc);
48583
- fs4.writeFileSync(path4.join(stubDir, "plugin-sdk.mjs"), "export * from './plugin-entry.mjs';\nexport { default } from './plugin-entry.mjs';\n");
48703
+ fs5.writeFileSync(path5.join(stubDir, "plugin-entry.mjs"), entrySrc);
48704
+ fs5.writeFileSync(path5.join(stubDir, "plugin-sdk.mjs"), "export * from './plugin-entry.mjs';\nexport { default } from './plugin-entry.mjs';\n");
48584
48705
  return stubDir;
48585
48706
  }
48586
48707
 
@@ -49176,10 +49297,10 @@ function augmentedPath() {
49176
49297
  }
49177
49298
  return parts.join(sep8);
49178
49299
  }
49179
- function which(bin, path5) {
49300
+ function which(bin, path6) {
49180
49301
  const tool12 = process.platform === "win32" ? "where" : "which";
49181
49302
  try {
49182
- const out = execFileSync2(tool12, [bin], { env: { ...process.env, PATH: path5 }, timeout: 4e3, encoding: "utf-8" });
49303
+ const out = execFileSync2(tool12, [bin], { env: { ...process.env, PATH: path6 }, timeout: 4e3, encoding: "utf-8" });
49183
49304
  return out.split(/\r?\n/).map((l) => l.trim()).find(Boolean) || void 0;
49184
49305
  } catch {
49185
49306
  return void 0;
@@ -49191,12 +49312,12 @@ function compute(engineId) {
49191
49312
  const desc = engineById(engineId);
49192
49313
  if (!desc)
49193
49314
  return null;
49194
- const path5 = augmentedPath();
49315
+ const path6 = augmentedPath();
49195
49316
  const explicit = process.env[`CCB_ENGINE_PATH_${envKey(engineId)}`]?.trim();
49196
- const command = explicit || which(desc.cliBinary, path5);
49317
+ const command = explicit || which(desc.cliBinary, path6);
49197
49318
  if (!command)
49198
49319
  return null;
49199
- const env = { PATH: path5 };
49320
+ const env = { PATH: path6 };
49200
49321
  const prefix = "CCB_ENGINE_ENV_";
49201
49322
  for (const [k, v] of Object.entries(process.env)) {
49202
49323
  if (v !== void 0 && k.startsWith(prefix))
@@ -51680,9 +51801,9 @@ function createDaemonImageGenRunner() {
51680
51801
  mkdirSync8(dir2, { recursive: true });
51681
51802
  const files = images.map((img, i) => {
51682
51803
  const ext = img.mime.split("/")[1]?.split("+")[0] || "png";
51683
- const path5 = join18(dir2, `${i + 1}.${ext}`);
51684
- writeFileSync9(path5, img.bytes);
51685
- return { path: path5, mime: img.mime };
51804
+ const path6 = join18(dir2, `${i + 1}.${ext}`);
51805
+ writeFileSync9(path6, img.bytes);
51806
+ return { path: path6, mime: img.mime };
51686
51807
  });
51687
51808
  return { ok: true, files, usedProviderId: id };
51688
51809
  } catch (e) {
@@ -51730,10 +51851,10 @@ function dynamicMetrics() {
51730
51851
 
51731
51852
  // ../../packages/host-core/dist/support-submit.js
51732
51853
  var LOG_TAIL_BYTES = 64 * 1024;
51733
- function tail2(path5, bytes = LOG_TAIL_BYTES) {
51854
+ function tail2(path6, bytes = LOG_TAIL_BYTES) {
51734
51855
  let fd = null;
51735
51856
  try {
51736
- fd = openSync2(path5, "r");
51857
+ fd = openSync2(path6, "r");
51737
51858
  const size = fstatSync(fd).size;
51738
51859
  const len = Math.min(size, bytes);
51739
51860
  const start2 = Math.max(0, size - len);
@@ -52274,8 +52395,8 @@ function releaseFsClient(key2) {
52274
52395
  }
52275
52396
  var OUTSIDE = (verb) => ({ ok: false, error: `Refusing to ${verb} outside the shared root.` });
52276
52397
  var validName = (n) => !!n && !n.includes("/") && !n.includes("\\") && n !== "." && n !== "..";
52277
- async function readRemoteBytes(root, path5) {
52278
- const real = safeContentPath(path5);
52398
+ async function readRemoteBytes(root, path6) {
52399
+ const real = safeContentPath(path6);
52279
52400
  if (!real)
52280
52401
  return { error: "Path is outside the shared root." };
52281
52402
  try {
@@ -52865,8 +52986,8 @@ var CHUNK = 64 * 1024;
52865
52986
  var MAX_MSG = 256 * 1024;
52866
52987
  var HIGH_WATER = 8 * 1024 * 1024;
52867
52988
  var drainers = /* @__PURE__ */ new WeakMap();
52868
- async function serveGet(dc, id, path5, root) {
52869
- const res = await readRemoteBytes(root, path5);
52989
+ async function serveGet(dc, id, path6, root) {
52990
+ const res = await readRemoteBytes(root, path6);
52870
52991
  if (!dc.isOpen())
52871
52992
  return;
52872
52993
  if (res.error || !res.bytes) {
@@ -53490,12 +53611,17 @@ async function dialLadder(opts) {
53490
53611
  }
53491
53612
 
53492
53613
  // ../../packages/host-core/dist/peer-link/manager.js
53614
+ init_dist();
53493
53615
  var LISTEN_PORT = Number(process.env.CCB_P2P_PORT ?? 0);
53494
53616
  var UDP_PORT = Number(process.env.CCB_P2P_UDP_PORT ?? 0);
53495
53617
  var RENDEZVOUS_TIMEOUT_MS = 25e3;
53496
53618
  var INBOUND_WAIT_MS = 2e4;
53497
- var DEFAULT_STUN_HOST = "stun.l.google.com";
53498
- var DEFAULT_STUN_PORT = 19302;
53619
+ var DEFAULT_STUN_SERVERS = [
53620
+ { host: OWN_STUN_HOST, port: OWN_STUN_PORT },
53621
+ // our coturn first
53622
+ { host: "stun.l.google.com", port: 19302 }
53623
+ // public fallback
53624
+ ];
53499
53625
  var provisionedStun = null;
53500
53626
  function provisionStun(host, port = 3478) {
53501
53627
  if (host)
@@ -53510,7 +53636,7 @@ function resolveStunServers() {
53510
53636
  list.push({ host: env, port: Number(process.env.CCB_STUN_PORT ?? 3478) });
53511
53637
  if (provisionedStun)
53512
53638
  list.push(provisionedStun);
53513
- list.push({ host: DEFAULT_STUN_HOST, port: DEFAULT_STUN_PORT });
53639
+ list.push(...DEFAULT_STUN_SERVERS);
53514
53640
  const seen = /* @__PURE__ */ new Set();
53515
53641
  return list.filter((s) => {
53516
53642
  const k = `${s.host}:${s.port}`;
@@ -53679,9 +53805,9 @@ var PeerLinkManager = class {
53679
53805
  * match, hand the authed link to its waiter. Shared by both transports so a
53680
53806
  * listener doesn't care HOW the peer dialed in — the token in pendingInbound
53681
53807
  * matches either. */
53682
- acceptInbound(sock, path5) {
53808
+ acceptInbound(sock, path6) {
53683
53809
  let matchedHex;
53684
- const { link, ready } = socketPeerLink(sock, "", path5, {
53810
+ const { link, ready } = socketPeerLink(sock, "", path6, {
53685
53811
  expectToken: (f) => {
53686
53812
  const hb = Buffer.from(toHex(f));
53687
53813
  for (const key2 of this.pendingInbound.keys()) {
@@ -54695,7 +54821,7 @@ var ReaddirpStream = class extends Readable {
54695
54821
  this._directoryFilter = normalizeFilter(opts.directoryFilter);
54696
54822
  const statMethod = opts.lstat ? lstat5 : stat4;
54697
54823
  if (wantBigintFsStats) {
54698
- this._stat = (path5) => statMethod(path5, { bigint: true });
54824
+ this._stat = (path6) => statMethod(path6, { bigint: true });
54699
54825
  } else {
54700
54826
  this._stat = statMethod;
54701
54827
  }
@@ -54720,8 +54846,8 @@ var ReaddirpStream = class extends Readable {
54720
54846
  const par = this.parent;
54721
54847
  const fil = par && par.files;
54722
54848
  if (fil && fil.length > 0) {
54723
- const { path: path5, depth } = par;
54724
- const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path5));
54849
+ const { path: path6, depth } = par;
54850
+ const slice = fil.splice(0, batch).map((dirent) => this._formatEntry(dirent, path6));
54725
54851
  const awaited = await Promise.all(slice);
54726
54852
  for (const entry of awaited) {
54727
54853
  if (!entry)
@@ -54761,20 +54887,20 @@ var ReaddirpStream = class extends Readable {
54761
54887
  this.reading = false;
54762
54888
  }
54763
54889
  }
54764
- async _exploreDir(path5, depth) {
54890
+ async _exploreDir(path6, depth) {
54765
54891
  let files;
54766
54892
  try {
54767
- files = await readdir6(path5, this._rdOptions);
54893
+ files = await readdir6(path6, this._rdOptions);
54768
54894
  } catch (error51) {
54769
54895
  this._onError(error51);
54770
54896
  }
54771
- return { files, depth, path: path5 };
54897
+ return { files, depth, path: path6 };
54772
54898
  }
54773
- async _formatEntry(dirent, path5) {
54899
+ async _formatEntry(dirent, path6) {
54774
54900
  let entry;
54775
54901
  const basename7 = this._isDirent ? dirent.name : dirent;
54776
54902
  try {
54777
- const fullPath = presolve(pjoin(path5, basename7));
54903
+ const fullPath = presolve(pjoin(path6, basename7));
54778
54904
  entry = { path: prelative(this._root, fullPath), fullPath, basename: basename7 };
54779
54905
  entry[this._statsProp] = this._isDirent ? dirent : await this._stat(fullPath);
54780
54906
  } catch (err) {
@@ -55174,16 +55300,16 @@ var delFromSet = (main2, prop, item) => {
55174
55300
  };
55175
55301
  var isEmptySet = (val) => val instanceof Set ? val.size === 0 : !val;
55176
55302
  var FsWatchInstances = /* @__PURE__ */ new Map();
55177
- function createFsWatchInstance(path5, options, listener, errHandler, emitRaw) {
55303
+ function createFsWatchInstance(path6, options, listener, errHandler, emitRaw) {
55178
55304
  const handleEvent = (rawEvent, evPath) => {
55179
- listener(path5);
55180
- emitRaw(rawEvent, evPath, { watchedPath: path5 });
55181
- if (evPath && path5 !== evPath) {
55182
- fsWatchBroadcast(sysPath.resolve(path5, evPath), KEY_LISTENERS, sysPath.join(path5, evPath));
55305
+ listener(path6);
55306
+ emitRaw(rawEvent, evPath, { watchedPath: path6 });
55307
+ if (evPath && path6 !== evPath) {
55308
+ fsWatchBroadcast(sysPath.resolve(path6, evPath), KEY_LISTENERS, sysPath.join(path6, evPath));
55183
55309
  }
55184
55310
  };
55185
55311
  try {
55186
- return fs_watch(path5, {
55312
+ return fs_watch(path6, {
55187
55313
  persistent: options.persistent
55188
55314
  }, handleEvent);
55189
55315
  } catch (error51) {
@@ -55199,12 +55325,12 @@ var fsWatchBroadcast = (fullPath, listenerType, val1, val2, val3) => {
55199
55325
  listener(val1, val2, val3);
55200
55326
  });
55201
55327
  };
55202
- var setFsWatchListener = (path5, fullPath, options, handlers) => {
55328
+ var setFsWatchListener = (path6, fullPath, options, handlers) => {
55203
55329
  const { listener, errHandler, rawEmitter } = handlers;
55204
55330
  let cont = FsWatchInstances.get(fullPath);
55205
55331
  let watcher;
55206
55332
  if (!options.persistent) {
55207
- watcher = createFsWatchInstance(path5, options, listener, errHandler, rawEmitter);
55333
+ watcher = createFsWatchInstance(path6, options, listener, errHandler, rawEmitter);
55208
55334
  if (!watcher)
55209
55335
  return;
55210
55336
  return watcher.close.bind(watcher);
@@ -55215,7 +55341,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
55215
55341
  addAndConvert(cont, KEY_RAW, rawEmitter);
55216
55342
  } else {
55217
55343
  watcher = createFsWatchInstance(
55218
- path5,
55344
+ path6,
55219
55345
  options,
55220
55346
  fsWatchBroadcast.bind(null, fullPath, KEY_LISTENERS),
55221
55347
  errHandler,
@@ -55230,7 +55356,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
55230
55356
  cont.watcherUnusable = true;
55231
55357
  if (isWindows2 && error51.code === "EPERM") {
55232
55358
  try {
55233
- const fd = await open3(path5, "r");
55359
+ const fd = await open3(path6, "r");
55234
55360
  await fd.close();
55235
55361
  broadcastErr(error51);
55236
55362
  } catch (err) {
@@ -55261,7 +55387,7 @@ var setFsWatchListener = (path5, fullPath, options, handlers) => {
55261
55387
  };
55262
55388
  };
55263
55389
  var FsWatchFileInstances = /* @__PURE__ */ new Map();
55264
- var setFsWatchFileListener = (path5, fullPath, options, handlers) => {
55390
+ var setFsWatchFileListener = (path6, fullPath, options, handlers) => {
55265
55391
  const { listener, rawEmitter } = handlers;
55266
55392
  let cont = FsWatchFileInstances.get(fullPath);
55267
55393
  const copts = cont && cont.options;
@@ -55283,7 +55409,7 @@ var setFsWatchFileListener = (path5, fullPath, options, handlers) => {
55283
55409
  });
55284
55410
  const currmtime = curr.mtimeMs;
55285
55411
  if (curr.size !== prev.size || currmtime > prev.mtimeMs || currmtime === 0) {
55286
- foreach(cont.listeners, (listener2) => listener2(path5, curr));
55412
+ foreach(cont.listeners, (listener2) => listener2(path6, curr));
55287
55413
  }
55288
55414
  })
55289
55415
  };
@@ -55311,13 +55437,13 @@ var NodeFsHandler = class {
55311
55437
  * @param listener on fs change
55312
55438
  * @returns closer for the watcher instance
55313
55439
  */
55314
- _watchWithNodeFs(path5, listener) {
55440
+ _watchWithNodeFs(path6, listener) {
55315
55441
  const opts = this.fsw.options;
55316
- const directory = sysPath.dirname(path5);
55317
- const basename7 = sysPath.basename(path5);
55442
+ const directory = sysPath.dirname(path6);
55443
+ const basename7 = sysPath.basename(path6);
55318
55444
  const parent = this.fsw._getWatchedDir(directory);
55319
55445
  parent.add(basename7);
55320
- const absolutePath = sysPath.resolve(path5);
55446
+ const absolutePath = sysPath.resolve(path6);
55321
55447
  const options = {
55322
55448
  persistent: opts.persistent
55323
55449
  };
@@ -55327,12 +55453,12 @@ var NodeFsHandler = class {
55327
55453
  if (opts.usePolling) {
55328
55454
  const enableBin = opts.interval !== opts.binaryInterval;
55329
55455
  options.interval = enableBin && isBinaryPath(basename7) ? opts.binaryInterval : opts.interval;
55330
- closer = setFsWatchFileListener(path5, absolutePath, options, {
55456
+ closer = setFsWatchFileListener(path6, absolutePath, options, {
55331
55457
  listener,
55332
55458
  rawEmitter: this.fsw._emitRaw
55333
55459
  });
55334
55460
  } else {
55335
- closer = setFsWatchListener(path5, absolutePath, options, {
55461
+ closer = setFsWatchListener(path6, absolutePath, options, {
55336
55462
  listener,
55337
55463
  errHandler: this._boundHandleError,
55338
55464
  rawEmitter: this.fsw._emitRaw
@@ -55354,7 +55480,7 @@ var NodeFsHandler = class {
55354
55480
  let prevStats = stats;
55355
55481
  if (parent.has(basename7))
55356
55482
  return;
55357
- const listener = async (path5, newStats) => {
55483
+ const listener = async (path6, newStats) => {
55358
55484
  if (!this.fsw._throttle(THROTTLE_MODE_WATCH, file2, 5))
55359
55485
  return;
55360
55486
  if (!newStats || newStats.mtimeMs === 0) {
@@ -55368,11 +55494,11 @@ var NodeFsHandler = class {
55368
55494
  this.fsw._emit(EV.CHANGE, file2, newStats2);
55369
55495
  }
55370
55496
  if ((isMacos || isLinux || isFreeBSD) && prevStats.ino !== newStats2.ino) {
55371
- this.fsw._closeFile(path5);
55497
+ this.fsw._closeFile(path6);
55372
55498
  prevStats = newStats2;
55373
55499
  const closer2 = this._watchWithNodeFs(file2, listener);
55374
55500
  if (closer2)
55375
- this.fsw._addPathCloser(path5, closer2);
55501
+ this.fsw._addPathCloser(path6, closer2);
55376
55502
  } else {
55377
55503
  prevStats = newStats2;
55378
55504
  }
@@ -55404,7 +55530,7 @@ var NodeFsHandler = class {
55404
55530
  * @param item basename of this item
55405
55531
  * @returns true if no more processing is needed for this entry.
55406
55532
  */
55407
- async _handleSymlink(entry, directory, path5, item) {
55533
+ async _handleSymlink(entry, directory, path6, item) {
55408
55534
  if (this.fsw.closed) {
55409
55535
  return;
55410
55536
  }
@@ -55414,7 +55540,7 @@ var NodeFsHandler = class {
55414
55540
  this.fsw._incrReadyCount();
55415
55541
  let linkPath;
55416
55542
  try {
55417
- linkPath = await fsrealpath(path5);
55543
+ linkPath = await fsrealpath(path6);
55418
55544
  } catch (e) {
55419
55545
  this.fsw._emitReady();
55420
55546
  return true;
@@ -55424,12 +55550,12 @@ var NodeFsHandler = class {
55424
55550
  if (dir2.has(item)) {
55425
55551
  if (this.fsw._symlinkPaths.get(full) !== linkPath) {
55426
55552
  this.fsw._symlinkPaths.set(full, linkPath);
55427
- this.fsw._emit(EV.CHANGE, path5, entry.stats);
55553
+ this.fsw._emit(EV.CHANGE, path6, entry.stats);
55428
55554
  }
55429
55555
  } else {
55430
55556
  dir2.add(item);
55431
55557
  this.fsw._symlinkPaths.set(full, linkPath);
55432
- this.fsw._emit(EV.ADD, path5, entry.stats);
55558
+ this.fsw._emit(EV.ADD, path6, entry.stats);
55433
55559
  }
55434
55560
  this.fsw._emitReady();
55435
55561
  return true;
@@ -55458,9 +55584,9 @@ var NodeFsHandler = class {
55458
55584
  return;
55459
55585
  }
55460
55586
  const item = entry.path;
55461
- let path5 = sysPath.join(directory, item);
55587
+ let path6 = sysPath.join(directory, item);
55462
55588
  current.add(item);
55463
- if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path5, item)) {
55589
+ if (entry.stats.isSymbolicLink() && await this._handleSymlink(entry, directory, path6, item)) {
55464
55590
  return;
55465
55591
  }
55466
55592
  if (this.fsw.closed) {
@@ -55469,8 +55595,8 @@ var NodeFsHandler = class {
55469
55595
  }
55470
55596
  if (item === target || !target && !previous.has(item)) {
55471
55597
  this.fsw._incrReadyCount();
55472
- path5 = sysPath.join(dir2, sysPath.relative(dir2, path5));
55473
- this._addToNodeFs(path5, initialAdd, wh, depth + 1);
55598
+ path6 = sysPath.join(dir2, sysPath.relative(dir2, path6));
55599
+ this._addToNodeFs(path6, initialAdd, wh, depth + 1);
55474
55600
  }
55475
55601
  }).on(EV.ERROR, this._boundHandleError);
55476
55602
  return new Promise((resolve10, reject) => {
@@ -55539,13 +55665,13 @@ var NodeFsHandler = class {
55539
55665
  * @param depth Child path actually targeted for watch
55540
55666
  * @param target Child path actually targeted for watch
55541
55667
  */
55542
- async _addToNodeFs(path5, initialAdd, priorWh, depth, target) {
55668
+ async _addToNodeFs(path6, initialAdd, priorWh, depth, target) {
55543
55669
  const ready = this.fsw._emitReady;
55544
- if (this.fsw._isIgnored(path5) || this.fsw.closed) {
55670
+ if (this.fsw._isIgnored(path6) || this.fsw.closed) {
55545
55671
  ready();
55546
55672
  return false;
55547
55673
  }
55548
- const wh = this.fsw._getWatchHelpers(path5);
55674
+ const wh = this.fsw._getWatchHelpers(path6);
55549
55675
  if (priorWh) {
55550
55676
  wh.filterPath = (entry) => priorWh.filterPath(entry);
55551
55677
  wh.filterDir = (entry) => priorWh.filterDir(entry);
@@ -55561,8 +55687,8 @@ var NodeFsHandler = class {
55561
55687
  const follow = this.fsw.options.followSymlinks;
55562
55688
  let closer;
55563
55689
  if (stats.isDirectory()) {
55564
- const absPath = sysPath.resolve(path5);
55565
- const targetPath = follow ? await fsrealpath(path5) : path5;
55690
+ const absPath = sysPath.resolve(path6);
55691
+ const targetPath = follow ? await fsrealpath(path6) : path6;
55566
55692
  if (this.fsw.closed)
55567
55693
  return;
55568
55694
  closer = await this._handleDir(wh.watchPath, stats, initialAdd, depth, target, wh, targetPath);
@@ -55572,29 +55698,29 @@ var NodeFsHandler = class {
55572
55698
  this.fsw._symlinkPaths.set(absPath, targetPath);
55573
55699
  }
55574
55700
  } else if (stats.isSymbolicLink()) {
55575
- const targetPath = follow ? await fsrealpath(path5) : path5;
55701
+ const targetPath = follow ? await fsrealpath(path6) : path6;
55576
55702
  if (this.fsw.closed)
55577
55703
  return;
55578
55704
  const parent = sysPath.dirname(wh.watchPath);
55579
55705
  this.fsw._getWatchedDir(parent).add(wh.watchPath);
55580
55706
  this.fsw._emit(EV.ADD, wh.watchPath, stats);
55581
- closer = await this._handleDir(parent, stats, initialAdd, depth, path5, wh, targetPath);
55707
+ closer = await this._handleDir(parent, stats, initialAdd, depth, path6, wh, targetPath);
55582
55708
  if (this.fsw.closed)
55583
55709
  return;
55584
55710
  if (targetPath !== void 0) {
55585
- this.fsw._symlinkPaths.set(sysPath.resolve(path5), targetPath);
55711
+ this.fsw._symlinkPaths.set(sysPath.resolve(path6), targetPath);
55586
55712
  }
55587
55713
  } else {
55588
55714
  closer = this._handleFile(wh.watchPath, stats, initialAdd);
55589
55715
  }
55590
55716
  ready();
55591
55717
  if (closer)
55592
- this.fsw._addPathCloser(path5, closer);
55718
+ this.fsw._addPathCloser(path6, closer);
55593
55719
  return false;
55594
55720
  } catch (error51) {
55595
55721
  if (this.fsw._handleError(error51)) {
55596
55722
  ready();
55597
- return path5;
55723
+ return path6;
55598
55724
  }
55599
55725
  }
55600
55726
  }
@@ -55637,26 +55763,26 @@ function createPattern(matcher) {
55637
55763
  }
55638
55764
  return () => false;
55639
55765
  }
55640
- function normalizePath(path5) {
55641
- if (typeof path5 !== "string")
55766
+ function normalizePath(path6) {
55767
+ if (typeof path6 !== "string")
55642
55768
  throw new Error("string expected");
55643
- path5 = sysPath2.normalize(path5);
55644
- path5 = path5.replace(/\\/g, "/");
55769
+ path6 = sysPath2.normalize(path6);
55770
+ path6 = path6.replace(/\\/g, "/");
55645
55771
  let prepend = false;
55646
- if (path5.startsWith("//"))
55772
+ if (path6.startsWith("//"))
55647
55773
  prepend = true;
55648
55774
  const DOUBLE_SLASH_RE2 = /\/\//;
55649
- while (path5.match(DOUBLE_SLASH_RE2))
55650
- path5 = path5.replace(DOUBLE_SLASH_RE2, "/");
55775
+ while (path6.match(DOUBLE_SLASH_RE2))
55776
+ path6 = path6.replace(DOUBLE_SLASH_RE2, "/");
55651
55777
  if (prepend)
55652
- path5 = "/" + path5;
55653
- return path5;
55778
+ path6 = "/" + path6;
55779
+ return path6;
55654
55780
  }
55655
55781
  function matchPatterns(patterns, testString, stats) {
55656
- const path5 = normalizePath(testString);
55782
+ const path6 = normalizePath(testString);
55657
55783
  for (let index = 0; index < patterns.length; index++) {
55658
55784
  const pattern = patterns[index];
55659
- if (pattern(path5, stats)) {
55785
+ if (pattern(path6, stats)) {
55660
55786
  return true;
55661
55787
  }
55662
55788
  }
@@ -55696,19 +55822,19 @@ var toUnix = (string4) => {
55696
55822
  }
55697
55823
  return str2;
55698
55824
  };
55699
- var normalizePathToUnix = (path5) => toUnix(sysPath2.normalize(toUnix(path5)));
55700
- var normalizeIgnored = (cwd = "") => (path5) => {
55701
- if (typeof path5 === "string") {
55702
- return normalizePathToUnix(sysPath2.isAbsolute(path5) ? path5 : sysPath2.join(cwd, path5));
55825
+ var normalizePathToUnix = (path6) => toUnix(sysPath2.normalize(toUnix(path6)));
55826
+ var normalizeIgnored = (cwd = "") => (path6) => {
55827
+ if (typeof path6 === "string") {
55828
+ return normalizePathToUnix(sysPath2.isAbsolute(path6) ? path6 : sysPath2.join(cwd, path6));
55703
55829
  } else {
55704
- return path5;
55830
+ return path6;
55705
55831
  }
55706
55832
  };
55707
- var getAbsolutePath = (path5, cwd) => {
55708
- if (sysPath2.isAbsolute(path5)) {
55709
- return path5;
55833
+ var getAbsolutePath = (path6, cwd) => {
55834
+ if (sysPath2.isAbsolute(path6)) {
55835
+ return path6;
55710
55836
  }
55711
- return sysPath2.join(cwd, path5);
55837
+ return sysPath2.join(cwd, path6);
55712
55838
  };
55713
55839
  var EMPTY_SET = Object.freeze(/* @__PURE__ */ new Set());
55714
55840
  var DirEntry = class {
@@ -55763,10 +55889,10 @@ var DirEntry = class {
55763
55889
  var STAT_METHOD_F = "stat";
55764
55890
  var STAT_METHOD_L = "lstat";
55765
55891
  var WatchHelper = class {
55766
- constructor(path5, follow, fsw) {
55892
+ constructor(path6, follow, fsw) {
55767
55893
  this.fsw = fsw;
55768
- const watchPath = path5;
55769
- this.path = path5 = path5.replace(REPLACER_RE, "");
55894
+ const watchPath = path6;
55895
+ this.path = path6 = path6.replace(REPLACER_RE, "");
55770
55896
  this.watchPath = watchPath;
55771
55897
  this.fullWatchPath = sysPath2.resolve(watchPath);
55772
55898
  this.dirParts = [];
@@ -55888,20 +56014,20 @@ var FSWatcher = class extends EventEmitter2 {
55888
56014
  this._closePromise = void 0;
55889
56015
  let paths = unifyPaths(paths_);
55890
56016
  if (cwd) {
55891
- paths = paths.map((path5) => {
55892
- const absPath = getAbsolutePath(path5, cwd);
56017
+ paths = paths.map((path6) => {
56018
+ const absPath = getAbsolutePath(path6, cwd);
55893
56019
  return absPath;
55894
56020
  });
55895
56021
  }
55896
- paths.forEach((path5) => {
55897
- this._removeIgnoredPath(path5);
56022
+ paths.forEach((path6) => {
56023
+ this._removeIgnoredPath(path6);
55898
56024
  });
55899
56025
  this._userIgnored = void 0;
55900
56026
  if (!this._readyCount)
55901
56027
  this._readyCount = 0;
55902
56028
  this._readyCount += paths.length;
55903
- Promise.all(paths.map(async (path5) => {
55904
- const res = await this._nodeFsHandler._addToNodeFs(path5, !_internal, void 0, 0, _origAdd);
56029
+ Promise.all(paths.map(async (path6) => {
56030
+ const res = await this._nodeFsHandler._addToNodeFs(path6, !_internal, void 0, 0, _origAdd);
55905
56031
  if (res)
55906
56032
  this._emitReady();
55907
56033
  return res;
@@ -55923,17 +56049,17 @@ var FSWatcher = class extends EventEmitter2 {
55923
56049
  return this;
55924
56050
  const paths = unifyPaths(paths_);
55925
56051
  const { cwd } = this.options;
55926
- paths.forEach((path5) => {
55927
- if (!sysPath2.isAbsolute(path5) && !this._closers.has(path5)) {
56052
+ paths.forEach((path6) => {
56053
+ if (!sysPath2.isAbsolute(path6) && !this._closers.has(path6)) {
55928
56054
  if (cwd)
55929
- path5 = sysPath2.join(cwd, path5);
55930
- path5 = sysPath2.resolve(path5);
56055
+ path6 = sysPath2.join(cwd, path6);
56056
+ path6 = sysPath2.resolve(path6);
55931
56057
  }
55932
- this._closePath(path5);
55933
- this._addIgnoredPath(path5);
55934
- if (this._watched.has(path5)) {
56058
+ this._closePath(path6);
56059
+ this._addIgnoredPath(path6);
56060
+ if (this._watched.has(path6)) {
55935
56061
  this._addIgnoredPath({
55936
- path: path5,
56062
+ path: path6,
55937
56063
  recursive: true
55938
56064
  });
55939
56065
  }
@@ -55997,38 +56123,38 @@ var FSWatcher = class extends EventEmitter2 {
55997
56123
  * @param stats arguments to be passed with event
55998
56124
  * @returns the error if defined, otherwise the value of the FSWatcher instance's `closed` flag
55999
56125
  */
56000
- async _emit(event, path5, stats) {
56126
+ async _emit(event, path6, stats) {
56001
56127
  if (this.closed)
56002
56128
  return;
56003
56129
  const opts = this.options;
56004
56130
  if (isWindows2)
56005
- path5 = sysPath2.normalize(path5);
56131
+ path6 = sysPath2.normalize(path6);
56006
56132
  if (opts.cwd)
56007
- path5 = sysPath2.relative(opts.cwd, path5);
56008
- const args = [path5];
56133
+ path6 = sysPath2.relative(opts.cwd, path6);
56134
+ const args = [path6];
56009
56135
  if (stats != null)
56010
56136
  args.push(stats);
56011
56137
  const awf = opts.awaitWriteFinish;
56012
56138
  let pw;
56013
- if (awf && (pw = this._pendingWrites.get(path5))) {
56139
+ if (awf && (pw = this._pendingWrites.get(path6))) {
56014
56140
  pw.lastChange = /* @__PURE__ */ new Date();
56015
56141
  return this;
56016
56142
  }
56017
56143
  if (opts.atomic) {
56018
56144
  if (event === EVENTS.UNLINK) {
56019
- this._pendingUnlinks.set(path5, [event, ...args]);
56145
+ this._pendingUnlinks.set(path6, [event, ...args]);
56020
56146
  setTimeout(() => {
56021
- this._pendingUnlinks.forEach((entry, path6) => {
56147
+ this._pendingUnlinks.forEach((entry, path7) => {
56022
56148
  this.emit(...entry);
56023
56149
  this.emit(EVENTS.ALL, ...entry);
56024
- this._pendingUnlinks.delete(path6);
56150
+ this._pendingUnlinks.delete(path7);
56025
56151
  });
56026
56152
  }, typeof opts.atomic === "number" ? opts.atomic : 100);
56027
56153
  return this;
56028
56154
  }
56029
- if (event === EVENTS.ADD && this._pendingUnlinks.has(path5)) {
56155
+ if (event === EVENTS.ADD && this._pendingUnlinks.has(path6)) {
56030
56156
  event = EVENTS.CHANGE;
56031
- this._pendingUnlinks.delete(path5);
56157
+ this._pendingUnlinks.delete(path6);
56032
56158
  }
56033
56159
  }
56034
56160
  if (awf && (event === EVENTS.ADD || event === EVENTS.CHANGE) && this._readyEmitted) {
@@ -56046,16 +56172,16 @@ var FSWatcher = class extends EventEmitter2 {
56046
56172
  this.emitWithAll(event, args);
56047
56173
  }
56048
56174
  };
56049
- this._awaitWriteFinish(path5, awf.stabilityThreshold, event, awfEmit);
56175
+ this._awaitWriteFinish(path6, awf.stabilityThreshold, event, awfEmit);
56050
56176
  return this;
56051
56177
  }
56052
56178
  if (event === EVENTS.CHANGE) {
56053
- const isThrottled = !this._throttle(EVENTS.CHANGE, path5, 50);
56179
+ const isThrottled = !this._throttle(EVENTS.CHANGE, path6, 50);
56054
56180
  if (isThrottled)
56055
56181
  return this;
56056
56182
  }
56057
56183
  if (opts.alwaysStat && stats === void 0 && (event === EVENTS.ADD || event === EVENTS.ADD_DIR || event === EVENTS.CHANGE)) {
56058
- const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path5) : path5;
56184
+ const fullPath = opts.cwd ? sysPath2.join(opts.cwd, path6) : path6;
56059
56185
  let stats2;
56060
56186
  try {
56061
56187
  stats2 = await stat6(fullPath);
@@ -56086,23 +56212,23 @@ var FSWatcher = class extends EventEmitter2 {
56086
56212
  * @param timeout duration of time to suppress duplicate actions
56087
56213
  * @returns tracking object or false if action should be suppressed
56088
56214
  */
56089
- _throttle(actionType, path5, timeout) {
56215
+ _throttle(actionType, path6, timeout) {
56090
56216
  if (!this._throttled.has(actionType)) {
56091
56217
  this._throttled.set(actionType, /* @__PURE__ */ new Map());
56092
56218
  }
56093
56219
  const action = this._throttled.get(actionType);
56094
56220
  if (!action)
56095
56221
  throw new Error("invalid throttle");
56096
- const actionPath = action.get(path5);
56222
+ const actionPath = action.get(path6);
56097
56223
  if (actionPath) {
56098
56224
  actionPath.count++;
56099
56225
  return false;
56100
56226
  }
56101
56227
  let timeoutObject;
56102
56228
  const clear = () => {
56103
- const item = action.get(path5);
56229
+ const item = action.get(path6);
56104
56230
  const count = item ? item.count : 0;
56105
- action.delete(path5);
56231
+ action.delete(path6);
56106
56232
  clearTimeout(timeoutObject);
56107
56233
  if (item)
56108
56234
  clearTimeout(item.timeoutObject);
@@ -56110,7 +56236,7 @@ var FSWatcher = class extends EventEmitter2 {
56110
56236
  };
56111
56237
  timeoutObject = setTimeout(clear, timeout);
56112
56238
  const thr = { timeoutObject, clear, count: 0 };
56113
- action.set(path5, thr);
56239
+ action.set(path6, thr);
56114
56240
  return thr;
56115
56241
  }
56116
56242
  _incrReadyCount() {
@@ -56124,44 +56250,44 @@ var FSWatcher = class extends EventEmitter2 {
56124
56250
  * @param event
56125
56251
  * @param awfEmit Callback to be called when ready for event to be emitted.
56126
56252
  */
56127
- _awaitWriteFinish(path5, threshold, event, awfEmit) {
56253
+ _awaitWriteFinish(path6, threshold, event, awfEmit) {
56128
56254
  const awf = this.options.awaitWriteFinish;
56129
56255
  if (typeof awf !== "object")
56130
56256
  return;
56131
56257
  const pollInterval = awf.pollInterval;
56132
56258
  let timeoutHandler;
56133
- let fullPath = path5;
56134
- if (this.options.cwd && !sysPath2.isAbsolute(path5)) {
56135
- fullPath = sysPath2.join(this.options.cwd, path5);
56259
+ let fullPath = path6;
56260
+ if (this.options.cwd && !sysPath2.isAbsolute(path6)) {
56261
+ fullPath = sysPath2.join(this.options.cwd, path6);
56136
56262
  }
56137
56263
  const now2 = /* @__PURE__ */ new Date();
56138
56264
  const writes = this._pendingWrites;
56139
56265
  function awaitWriteFinishFn(prevStat) {
56140
56266
  statcb(fullPath, (err, curStat) => {
56141
- if (err || !writes.has(path5)) {
56267
+ if (err || !writes.has(path6)) {
56142
56268
  if (err && err.code !== "ENOENT")
56143
56269
  awfEmit(err);
56144
56270
  return;
56145
56271
  }
56146
56272
  const now3 = Number(/* @__PURE__ */ new Date());
56147
56273
  if (prevStat && curStat.size !== prevStat.size) {
56148
- writes.get(path5).lastChange = now3;
56274
+ writes.get(path6).lastChange = now3;
56149
56275
  }
56150
- const pw = writes.get(path5);
56276
+ const pw = writes.get(path6);
56151
56277
  const df = now3 - pw.lastChange;
56152
56278
  if (df >= threshold) {
56153
- writes.delete(path5);
56279
+ writes.delete(path6);
56154
56280
  awfEmit(void 0, curStat);
56155
56281
  } else {
56156
56282
  timeoutHandler = setTimeout(awaitWriteFinishFn, pollInterval, curStat);
56157
56283
  }
56158
56284
  });
56159
56285
  }
56160
- if (!writes.has(path5)) {
56161
- writes.set(path5, {
56286
+ if (!writes.has(path6)) {
56287
+ writes.set(path6, {
56162
56288
  lastChange: now2,
56163
56289
  cancelWait: () => {
56164
- writes.delete(path5);
56290
+ writes.delete(path6);
56165
56291
  clearTimeout(timeoutHandler);
56166
56292
  return event;
56167
56293
  }
@@ -56172,8 +56298,8 @@ var FSWatcher = class extends EventEmitter2 {
56172
56298
  /**
56173
56299
  * Determines whether user has asked to ignore this path.
56174
56300
  */
56175
- _isIgnored(path5, stats) {
56176
- if (this.options.atomic && DOT_RE.test(path5))
56301
+ _isIgnored(path6, stats) {
56302
+ if (this.options.atomic && DOT_RE.test(path6))
56177
56303
  return true;
56178
56304
  if (!this._userIgnored) {
56179
56305
  const { cwd } = this.options;
@@ -56183,17 +56309,17 @@ var FSWatcher = class extends EventEmitter2 {
56183
56309
  const list = [...ignoredPaths.map(normalizeIgnored(cwd)), ...ignored];
56184
56310
  this._userIgnored = anymatch(list, void 0);
56185
56311
  }
56186
- return this._userIgnored(path5, stats);
56312
+ return this._userIgnored(path6, stats);
56187
56313
  }
56188
- _isntIgnored(path5, stat7) {
56189
- return !this._isIgnored(path5, stat7);
56314
+ _isntIgnored(path6, stat7) {
56315
+ return !this._isIgnored(path6, stat7);
56190
56316
  }
56191
56317
  /**
56192
56318
  * Provides a set of common helpers and properties relating to symlink handling.
56193
56319
  * @param path file or directory pattern being watched
56194
56320
  */
56195
- _getWatchHelpers(path5) {
56196
- return new WatchHelper(path5, this.options.followSymlinks, this);
56321
+ _getWatchHelpers(path6) {
56322
+ return new WatchHelper(path6, this.options.followSymlinks, this);
56197
56323
  }
56198
56324
  // Directory helpers
56199
56325
  // -----------------
@@ -56225,63 +56351,63 @@ var FSWatcher = class extends EventEmitter2 {
56225
56351
  * @param item base path of item/directory
56226
56352
  */
56227
56353
  _remove(directory, item, isDirectory) {
56228
- const path5 = sysPath2.join(directory, item);
56229
- const fullPath = sysPath2.resolve(path5);
56230
- isDirectory = isDirectory != null ? isDirectory : this._watched.has(path5) || this._watched.has(fullPath);
56231
- if (!this._throttle("remove", path5, 100))
56354
+ const path6 = sysPath2.join(directory, item);
56355
+ const fullPath = sysPath2.resolve(path6);
56356
+ isDirectory = isDirectory != null ? isDirectory : this._watched.has(path6) || this._watched.has(fullPath);
56357
+ if (!this._throttle("remove", path6, 100))
56232
56358
  return;
56233
56359
  if (!isDirectory && this._watched.size === 1) {
56234
56360
  this.add(directory, item, true);
56235
56361
  }
56236
- const wp = this._getWatchedDir(path5);
56362
+ const wp = this._getWatchedDir(path6);
56237
56363
  const nestedDirectoryChildren = wp.getChildren();
56238
- nestedDirectoryChildren.forEach((nested) => this._remove(path5, nested));
56364
+ nestedDirectoryChildren.forEach((nested) => this._remove(path6, nested));
56239
56365
  const parent = this._getWatchedDir(directory);
56240
56366
  const wasTracked = parent.has(item);
56241
56367
  parent.remove(item);
56242
56368
  if (this._symlinkPaths.has(fullPath)) {
56243
56369
  this._symlinkPaths.delete(fullPath);
56244
56370
  }
56245
- let relPath = path5;
56371
+ let relPath = path6;
56246
56372
  if (this.options.cwd)
56247
- relPath = sysPath2.relative(this.options.cwd, path5);
56373
+ relPath = sysPath2.relative(this.options.cwd, path6);
56248
56374
  if (this.options.awaitWriteFinish && this._pendingWrites.has(relPath)) {
56249
56375
  const event = this._pendingWrites.get(relPath).cancelWait();
56250
56376
  if (event === EVENTS.ADD)
56251
56377
  return;
56252
56378
  }
56253
- this._watched.delete(path5);
56379
+ this._watched.delete(path6);
56254
56380
  this._watched.delete(fullPath);
56255
56381
  const eventName = isDirectory ? EVENTS.UNLINK_DIR : EVENTS.UNLINK;
56256
- if (wasTracked && !this._isIgnored(path5))
56257
- this._emit(eventName, path5);
56258
- this._closePath(path5);
56382
+ if (wasTracked && !this._isIgnored(path6))
56383
+ this._emit(eventName, path6);
56384
+ this._closePath(path6);
56259
56385
  }
56260
56386
  /**
56261
56387
  * Closes all watchers for a path
56262
56388
  */
56263
- _closePath(path5) {
56264
- this._closeFile(path5);
56265
- const dir2 = sysPath2.dirname(path5);
56266
- this._getWatchedDir(dir2).remove(sysPath2.basename(path5));
56389
+ _closePath(path6) {
56390
+ this._closeFile(path6);
56391
+ const dir2 = sysPath2.dirname(path6);
56392
+ this._getWatchedDir(dir2).remove(sysPath2.basename(path6));
56267
56393
  }
56268
56394
  /**
56269
56395
  * Closes only file-specific watchers
56270
56396
  */
56271
- _closeFile(path5) {
56272
- const closers = this._closers.get(path5);
56397
+ _closeFile(path6) {
56398
+ const closers = this._closers.get(path6);
56273
56399
  if (!closers)
56274
56400
  return;
56275
56401
  closers.forEach((closer) => closer());
56276
- this._closers.delete(path5);
56402
+ this._closers.delete(path6);
56277
56403
  }
56278
- _addPathCloser(path5, closer) {
56404
+ _addPathCloser(path6, closer) {
56279
56405
  if (!closer)
56280
56406
  return;
56281
- let list = this._closers.get(path5);
56407
+ let list = this._closers.get(path6);
56282
56408
  if (!list) {
56283
56409
  list = [];
56284
- this._closers.set(path5, list);
56410
+ this._closers.set(path6, list);
56285
56411
  }
56286
56412
  list.push(closer);
56287
56413
  }
@@ -57446,9 +57572,9 @@ function friendlyLabel(id, label) {
57446
57572
  return `Command line (${label})`;
57447
57573
  }
57448
57574
  }
57449
- function mk(id, path5, isDefault, label) {
57575
+ function mk(id, path6, isDefault, label) {
57450
57576
  const lbl = label ?? id;
57451
- return { id, label: lbl, friendly: friendlyLabel(id, lbl), path: path5, default: isDefault || void 0 };
57577
+ return { id, label: lbl, friendly: friendlyLabel(id, lbl), path: path6, default: isDefault || void 0 };
57452
57578
  }
57453
57579
  function listInterpreters() {
57454
57580
  return process.platform === "win32" ? listWindows() : listUnix();
@@ -57457,11 +57583,11 @@ function listUnix() {
57457
57583
  const out = [];
57458
57584
  const seen = /* @__PURE__ */ new Set();
57459
57585
  const loginShell = process.env.SHELL || "";
57460
- const add = (id, path5) => {
57461
- if (!path5 || seen.has(path5) || !existsSync14(path5))
57586
+ const add = (id, path6) => {
57587
+ if (!path6 || seen.has(path6) || !existsSync14(path6))
57462
57588
  return;
57463
- seen.add(path5);
57464
- out.push(mk(id, path5, path5 === loginShell));
57589
+ seen.add(path6);
57590
+ out.push(mk(id, path6, path6 === loginShell));
57465
57591
  };
57466
57592
  if (loginShell)
57467
57593
  add(idForPath(loginShell), loginShell);
@@ -57489,9 +57615,9 @@ function listWindows() {
57489
57615
  const pf = process.env.ProgramFiles || "C:\\Program Files";
57490
57616
  const gitBash = `${pf}\\Git\\bin\\bash.exe`;
57491
57617
  const pwsh7 = `${pf}\\PowerShell\\7\\pwsh.exe`;
57492
- const add = (id, path5, label, isDefault = false) => {
57493
- if (path5 && existsSync14(path5))
57494
- out.push(mk(id, path5, isDefault, label));
57618
+ const add = (id, path6, label, isDefault = false) => {
57619
+ if (path6 && existsSync14(path6))
57620
+ out.push(mk(id, path6, isDefault, label));
57495
57621
  };
57496
57622
  add("powershell", winPwsh, "Windows PowerShell", true);
57497
57623
  add("pwsh", pwsh7, "pwsh");
@@ -57755,7 +57881,7 @@ function fetchIceServers() {
57755
57881
  const i = iceWaiters.indexOf(resolve10);
57756
57882
  if (i >= 0) {
57757
57883
  iceWaiters.splice(i, 1);
57758
- resolve10([{ urls: "stun:stun.l.google.com:19302" }]);
57884
+ resolve10(DEFAULT_ICE_SERVERS);
57759
57885
  }
57760
57886
  }, 2500);
57761
57887
  });
@@ -58187,7 +58313,8 @@ async function handleInboundAgent(msg, driverClientId) {
58187
58313
  driverBySession.set(msg.sessionId, driverClientId);
58188
58314
  const messages = await b.getMessages(msg.sessionId).catch(() => []);
58189
58315
  const artifacts = await (b.getSessionArtifacts?.(msg.sessionId, msg.projectDir).catch(() => []) ?? Promise.resolve([]));
58190
- send2("agent", { type: "session:messages", sessionId: msg.sessionId, messages, artifacts }, route2);
58316
+ const sessionCostUsd = await (b.getSessionCost?.(msg.sessionId, msg.projectDir).catch(() => 0) ?? Promise.resolve(0));
58317
+ send2("agent", { type: "session:messages", sessionId: msg.sessionId, messages, artifacts, ...sessionCostUsd > 0 ? { sessionCostUsd } : {} }, route2);
58191
58318
  break;
58192
58319
  }
58193
58320
  case "session:summarize": {
@@ -58209,6 +58336,9 @@ async function handleInboundAgent(msg, driverClientId) {
58209
58336
  case "agent:trace":
58210
58337
  void Promise.resolve(b.getTrace?.(msg.sessionId, msg.turnId, msg.projectDir) ?? null).then((trace) => send2("agent", { type: "agent:trace", sessionId: msg.sessionId, turnId: msg.turnId, clientRequestId: msg.clientRequestId, trace: trace ?? null }, route2));
58211
58338
  break;
58339
+ case "agent:subagentMessages":
58340
+ void Promise.resolve(b.getSubagentMessages?.(msg.sessionId, msg.agentId, msg.projectDir) ?? []).then((messages) => send2("agent", { type: "agent:subagentMessages", sessionId: msg.sessionId, agentId: msg.agentId, clientRequestId: msg.clientRequestId, messages }, route2));
58341
+ break;
58212
58342
  case "session:merge":
58213
58343
  void b.mergeSessions?.(msg.sessionIds, { projectDir: msg.projectDir, title: msg.title, clientRequestId: msg.clientRequestId, origin }).catch(() => {
58214
58344
  });
@@ -58961,7 +59091,8 @@ async function startLocalServer(opts) {
58961
59091
  case "session:resume": {
58962
59092
  const messages = await b.getMessages(msg.sessionId).catch(() => []);
58963
59093
  const artifacts = await (b.getSessionArtifacts?.(msg.sessionId, msg.projectDir).catch(() => []) ?? Promise.resolve([]));
58964
- send3("agent", { type: "session:messages", sessionId: msg.sessionId, messages, artifacts });
59094
+ const sessionCostUsd = await (b.getSessionCost?.(msg.sessionId, msg.projectDir).catch(() => 0) ?? Promise.resolve(0));
59095
+ send3("agent", { type: "session:messages", sessionId: msg.sessionId, messages, artifacts, ...sessionCostUsd > 0 ? { sessionCostUsd } : {} });
58965
59096
  break;
58966
59097
  }
58967
59098
  case "session:summarize": {
@@ -58983,6 +59114,9 @@ async function startLocalServer(opts) {
58983
59114
  case "agent:trace":
58984
59115
  void Promise.resolve(b.getTrace?.(msg.sessionId, msg.turnId, msg.projectDir) ?? null).then((trace) => send3("agent", { type: "agent:trace", sessionId: msg.sessionId, turnId: msg.turnId, clientRequestId: msg.clientRequestId, trace: trace ?? null }));
58985
59116
  break;
59117
+ case "agent:subagentMessages":
59118
+ void Promise.resolve(b.getSubagentMessages?.(msg.sessionId, msg.agentId, msg.projectDir) ?? []).then((messages) => send3("agent", { type: "agent:subagentMessages", sessionId: msg.sessionId, agentId: msg.agentId, clientRequestId: msg.clientRequestId, messages }));
59119
+ break;
58986
59120
  case "session:merge":
58987
59121
  void b.mergeSessions?.(msg.sessionIds, { projectDir: msg.projectDir, title: msg.title, clientRequestId: msg.clientRequestId, origin: loopbackOrigin }).catch(() => {
58988
59122
  });