@centralu/win32-x64 0.1.0-beta.28 → 0.1.0-beta.29

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.
@@ -42892,6 +42892,23 @@ function takeLaunchEnv(env = process.env) {
42892
42892
  return launch2;
42893
42893
  }
42894
42894
 
42895
+ // packages/agent-host/src/json-value.ts
42896
+ var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
42897
+ var asObj = (v) => isObj(v) ? v : {};
42898
+ var str = (v, fallback = "") => typeof v === "string" ? v : fallback;
42899
+ var isFilled = (v) => typeof v === "string" && v.length > 0;
42900
+ var filled = (v) => isFilled(v) ? v : null;
42901
+ var trimmed = (v) => typeof v === "string" && v.trim() ? v.trim() : void 0;
42902
+ var finite = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
42903
+ var jsonObject = (v) => {
42904
+ if (typeof v !== "string") return asObj(v);
42905
+ try {
42906
+ return jsonObject(JSON.parse(v));
42907
+ } catch {
42908
+ return {};
42909
+ }
42910
+ };
42911
+
42895
42912
  // packages/agent-host/src/lifecycle/handed-token.ts
42896
42913
  var HANDED_TOKEN_WAIT_MS = 1e4;
42897
42914
  var MAX_TOKEN_LINE = 4096;
@@ -42903,7 +42920,7 @@ async function readHandedToken(input, waitMs = HANDED_TOKEN_WAIT_MS) {
42903
42920
  } catch {
42904
42921
  throw new Error("the token line on stdin is not JSON");
42905
42922
  }
42906
- const token2 = typeof parsed === "object" && parsed !== null ? parsed.token : void 0;
42923
+ const token2 = asObj(parsed).token;
42907
42924
  if (typeof token2 !== "string" || token2.trim() === "") throw new Error("the token line on stdin has no token");
42908
42925
  return token2;
42909
42926
  }
@@ -43012,7 +43029,7 @@ import { mkdirSync as mkdirSync15, writeSync as writeSync3 } from "node:fs";
43012
43029
 
43013
43030
  // packages/protocol/src/brand.ts
43014
43031
  var APP_NAME = "Centralu";
43015
- var APP_VERSION = "0.1.0-beta.28";
43032
+ var APP_VERSION = "0.1.0-beta.29";
43016
43033
  var APP_SLUG = "centralu";
43017
43034
  var CLIENT_INFO = { name: APP_SLUG, title: APP_NAME, version: APP_VERSION };
43018
43035
  var DATA_DIR = ".centralu";
@@ -58461,15 +58478,15 @@ var ApprovalDetail = ApprovalDetailKinds.catch((ctx) => unknownApprovalCard(ctx.
58461
58478
  var UNKNOWN_CARD = "unknown_card";
58462
58479
  var UNKNOWN_CARD_NOTE = "A newer Centralu may have sent it. Allow it only if you know what it asks; updating Centralu shows it in full.";
58463
58480
  var UNREADABLE_CARD_NOTE = "It may come from a newer Centralu, or be malformed. Allow it only if you know what it asks.";
58464
- var str = (v) => typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
58481
+ var str2 = (v) => typeof v === "string" && v.trim() !== "" ? v.trim() : void 0;
58465
58482
  var quoted = (v, max = 500) => {
58466
58483
  const cut = (t) => t.length > max ? `${t.slice(0, max)}\u2026` : t;
58467
58484
  return typeof v === "string" ? JSON.stringify(cut(v)) : cut(JSON.stringify(v) ?? String(v));
58468
58485
  };
58469
- var nameOf = (v) => typeof v === "object" && v !== null ? str(v.name) : void 0;
58486
+ var nameOf = (v) => typeof v === "object" && v !== null ? str2(v.name) : void 0;
58470
58487
  function unknownApprovalCard(raw) {
58471
58488
  const card = typeof raw === "object" && raw !== null ? raw : {};
58472
- const kind = str(card.kind)?.slice(0, 60);
58489
+ const kind = str2(card.kind)?.slice(0, 60);
58473
58490
  const branch = kind ? ApprovalDetailKinds.options.find((o) => o.shape.kind.value === kind) : void 0;
58474
58491
  const lines = [];
58475
58492
  let problems = "";
@@ -58490,11 +58507,11 @@ function unknownApprovalCard(raw) {
58490
58507
  const named = [
58491
58508
  nameOf(card.project) && `project ${quoted(nameOf(card.project), 80)}`,
58492
58509
  nameOf(card.app) && `app ${quoted(nameOf(card.app), 80)}`,
58493
- str(card.machine) && `machine ${quoted(str(card.machine), 80)}`
58510
+ str2(card.machine) && `machine ${quoted(str2(card.machine), 80)}`
58494
58511
  ].filter(Boolean);
58495
58512
  if (named.length) lines.push(`It names ${named.join(", ")}.`);
58496
58513
  for (const [key, label] of [["text", "Its text"], ["raw", "Its text"], ["command", "The command"], ["path", "The file"]]) {
58497
- const v = str(card[key]);
58514
+ const v = str2(card[key]);
58498
58515
  if (v) lines.push(`${label}, as the request gives it (not checked by Centralu): ${quoted(v)}`);
58499
58516
  }
58500
58517
  lines.push(branch ? UNREADABLE_CARD_NOTE : UNKNOWN_CARD_NOTE);
@@ -61529,10 +61546,16 @@ var sessionMethods = {
61529
61546
  * the apps' broker has a trash or purge verb. `agents.deleteSession` is the way in.
61530
61547
  *
61531
61548
  * `bytes` is the total of every session's `bytes` — shown because nothing empties the trash on its own.
61549
+ * `unreached`: the linked machines whose trash could not be read this time (#841 item 4), so the list says it is
61550
+ * not the whole trash. Absent when every machine answered, and from a host before it.
61532
61551
  */
61533
61552
  "trash.list": {
61534
61553
  params: external_exports.object({}),
61535
- result: external_exports.object({ sessions: external_exports.array(TrashedSession), bytes: external_exports.number() })
61554
+ result: external_exports.object({
61555
+ sessions: external_exports.array(TrashedSession),
61556
+ bytes: external_exports.number(),
61557
+ unreached: external_exports.array(external_exports.object({ machineId: external_exports.string(), name: external_exports.string() })).optional()
61558
+ })
61536
61559
  },
61537
61560
  /** A trashed conversation, read-only — the same page shape as `messages.load` */
61538
61561
  "trash.read": {
@@ -62058,6 +62081,9 @@ function appKeyOf(projectId, appId, machine) {
62058
62081
  function appLabel(ref) {
62059
62082
  return `${ref.projectId === null ? "user" : ref.projectId.slice(0, 8)}/${ref.appId}`;
62060
62083
  }
62084
+ function noSuchAppText(ref) {
62085
+ return `There is no such app: ${ref.projectId ?? "user"}/${ref.appId}`;
62086
+ }
62061
62087
 
62062
62088
  // packages/protocol/src/app-frames.ts
62063
62089
  function frameField(value) {
@@ -63178,23 +63204,6 @@ function keeperPtyModule(keeper) {
63178
63204
  };
63179
63205
  }
63180
63206
 
63181
- // packages/agent-host/src/json-value.ts
63182
- var isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
63183
- var asObj = (v) => isObj(v) ? v : {};
63184
- var str2 = (v, fallback = "") => typeof v === "string" ? v : fallback;
63185
- var isFilled = (v) => typeof v === "string" && v.length > 0;
63186
- var filled = (v) => isFilled(v) ? v : null;
63187
- var trimmed = (v) => typeof v === "string" && v.trim() ? v.trim() : void 0;
63188
- var finite = (v) => typeof v === "number" && Number.isFinite(v) ? v : void 0;
63189
- var jsonObject = (v) => {
63190
- if (typeof v !== "string") return asObj(v);
63191
- try {
63192
- return jsonObject(JSON.parse(v));
63193
- } catch {
63194
- return {};
63195
- }
63196
- };
63197
-
63198
63207
  // packages/agent-host/src/keeper/tags.ts
63199
63208
  function parseTag(raw) {
63200
63209
  if (typeof raw !== "object" || raw === null) return null;
@@ -64722,18 +64731,23 @@ function proxyPageHtml(config2) {
64722
64731
 
64723
64732
  // packages/agent-host/src/views/view-document.ts
64724
64733
  var VIEW_MIME_TYPE = "text/html;profile=mcp-app";
64734
+ function isViewMimeType(mimeType) {
64735
+ return typeof mimeType === "string" && mimeType.replace(/\s+/g, "").toLowerCase() === VIEW_MIME_TYPE;
64736
+ }
64737
+ function viewHtmlOf(item) {
64738
+ if (typeof item.text === "string") return item.text;
64739
+ if (typeof item.blob === "string") return Buffer.from(item.blob, "base64").toString("utf8");
64740
+ return null;
64741
+ }
64725
64742
  function viewDocumentFromResource(result, uri) {
64726
64743
  const contents = result?.contents;
64727
64744
  if (!Array.isArray(contents) || contents.length === 0) throw new Error(`${uri}: the app returned no content for this view`);
64728
64745
  const item = contents.find((c) => c?.uri === uri) ?? contents[0];
64729
- const mime = typeof item.mimeType === "string" ? item.mimeType.replace(/\s+/g, "").toLowerCase() : "";
64730
- if (mime !== VIEW_MIME_TYPE) {
64746
+ if (!isViewMimeType(item.mimeType)) {
64731
64747
  throw new Error(`${uri}: not an app view (mimeType ${JSON.stringify(item.mimeType ?? null)}, expected ${VIEW_MIME_TYPE})`);
64732
64748
  }
64733
- let html;
64734
- if (typeof item.text === "string") html = item.text;
64735
- else if (typeof item.blob === "string") html = Buffer.from(item.blob, "base64").toString("utf8");
64736
- else throw new Error(`${uri}: the view has neither text nor blob`);
64749
+ const html = viewHtmlOf(item);
64750
+ if (html === null) throw new Error(`${uri}: the view has neither text nor blob`);
64737
64751
  const ui2 = item._meta?.ui;
64738
64752
  const csp = ui2?.csp && typeof ui2.csp === "object" ? ui2.csp : void 0;
64739
64753
  const permissions = ui2?.permissions && typeof ui2.permissions === "object" ? ui2.permissions : void 0;
@@ -77435,13 +77449,13 @@ function fillCacheFields(method, result) {
77435
77449
  const provided = result;
77436
77450
  const ttlMs = isValidCacheTtlMs(provided["ttlMs"]) ? provided["ttlMs"] : resolveTtlMs(fallback);
77437
77451
  const cacheScope = isValidCacheScope(provided["cacheScope"]) ? provided["cacheScope"] : resolveCacheScope(fallback);
77438
- const filled3 = {
77452
+ const filled2 = {
77439
77453
  ...provided,
77440
77454
  ttlMs,
77441
77455
  cacheScope
77442
77456
  };
77443
- delete filled3[RESULT_CACHE_HINT_FALLBACK];
77444
- return filled3;
77457
+ delete filled2[RESULT_CACHE_HINT_FALLBACK];
77458
+ return filled2;
77445
77459
  }
77446
77460
  function isPlainObject$5(value) {
77447
77461
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -82171,7 +82185,6 @@ function resourceUriOf(tool) {
82171
82185
  }
82172
82186
 
82173
82187
  // packages/agent-host/src/apps/external/check.ts
82174
- var UI_MIME = "text/html;profile=mcp-app";
82175
82188
  var BRIDGE_TAG = "centralu:mcp-app.js";
82176
82189
  var problem = (where, message) => ({ level: "problem", where, message });
82177
82190
  var warning = (where, message) => ({ level: "warning", where, message });
@@ -82228,13 +82241,13 @@ function checkScreen(uri, read) {
82228
82241
  const content = read.contents.find((c) => c.uri === uri) ?? read.contents[0];
82229
82242
  if (!content) return { findings: [problem(where, "it was read but came back empty (no contents)")], chars: 0 };
82230
82243
  const findings = [];
82231
- if (content.mimeType !== UI_MIME) {
82232
- findings.push(problem(where, `its mimeType is ${JSON.stringify(content.mimeType ?? null)} \u2014 a screen must be "${UI_MIME}" (centralu.uiResource sets it)`));
82244
+ if (!isViewMimeType(content.mimeType)) {
82245
+ findings.push(problem(where, `its mimeType is ${JSON.stringify(content.mimeType ?? null)} \u2014 a screen must be "${VIEW_MIME_TYPE}" (centralu.uiResource sets it)`));
82233
82246
  }
82234
- const text2 = "text" in content && typeof content.text === "string" ? content.text : null;
82235
- if (text2 === null) {
82247
+ const text2 = viewHtmlOf(content);
82248
+ if (text2 === null) return { findings: [...findings, problem(where, "it has neither text nor a blob, so it cannot be shown")], chars: 0 };
82249
+ if (!("text" in content) || typeof content.text !== "string") {
82236
82250
  findings.push(warning(where, "the HTML came as a blob, not as text \u2014 Centralu's template sends text"));
82237
- return { findings, chars: 0 };
82238
82251
  }
82239
82252
  if (!text2.trim()) findings.push(problem(where, "the HTML is empty"));
82240
82253
  if (text2.includes(BRIDGE_TAG)) {
@@ -85224,13 +85237,13 @@ function fillCacheFields2(method, result) {
85224
85237
  const provided = result;
85225
85238
  const ttlMs = isValidCacheTtlMs2(provided["ttlMs"]) ? provided["ttlMs"] : resolveTtlMs2(fallback);
85226
85239
  const cacheScope = isValidCacheScope2(provided["cacheScope"]) ? provided["cacheScope"] : resolveCacheScope2(fallback);
85227
- const filled3 = {
85240
+ const filled2 = {
85228
85241
  ...provided,
85229
85242
  ttlMs,
85230
85243
  cacheScope
85231
85244
  };
85232
- delete filled3[RESULT_CACHE_HINT_FALLBACK2];
85233
- return filled3;
85245
+ delete filled2[RESULT_CACHE_HINT_FALLBACK2];
85246
+ return filled2;
85234
85247
  }
85235
85248
  function isPlainObject$42(value) {
85236
85249
  return value !== null && typeof value === "object" && !Array.isArray(value);
@@ -97229,7 +97242,7 @@ var AppProcess = class _AppProcess {
97229
97242
  });
97230
97243
  } catch (e) {
97231
97244
  const shim = /\.(cmd|bat)$/i.test(launch2.command) ? " (a .cmd or .bat that is not a package manager shim needs a shell: name the program it starts)" : "";
97232
- const head = `could not run ${launch2.command}: ${e.message}${shim}`;
97245
+ const head = spec.redact(`could not run ${launch2.command}: ${e.message}${shim}`);
97233
97246
  log.note(head);
97234
97247
  log.close();
97235
97248
  throw new AppStartError(head, head, []);
@@ -97244,7 +97257,7 @@ var AppProcess = class _AppProcess {
97244
97257
  return proc;
97245
97258
  } catch (e) {
97246
97259
  await proc.waitExit(spec.exitWaitMs);
97247
- const head = proc.exit ? `exited before it was ready (${describeExit(proc.exit)})` : e.message;
97260
+ const head = proc.exit ? `exited before it was ready (${describeExit(proc.exit)})` : spec.redact(e.message);
97248
97261
  const reason = proc.reason(head);
97249
97262
  const stderr = proc.log.tailLines();
97250
97263
  await proc.stop(0);
@@ -98529,14 +98542,17 @@ function readZipEntries(buf, maxEntries) {
98529
98542
  if (name.includes("\uFFFD")) throw new ZipError("An entry name is not UTF-8; re-create the archive with UTF-8 names");
98530
98543
  if (flags & 1) throw new ZipError(`Encrypted entries are not supported: ${name}`);
98531
98544
  if (compressedSize === 4294967295 || size === 4294967295 || offset === 4294967295) throw new ZipError("ZIP64 archives are not supported");
98532
- out.push({ name, kind: kindOf(name, madeBy, external), method, compressedSize, size, crc, offset });
98545
+ const mode = unixMode(madeBy, external);
98546
+ out.push({ name, kind: kindOf(name, mode, external), mode, method, compressedSize, size, crc, offset });
98533
98547
  p = nameEnd + extraLen + commentLen;
98534
98548
  }
98535
98549
  return out;
98536
98550
  }
98537
- function kindOf(name, madeBy, external) {
98551
+ function unixMode(madeBy, external) {
98538
98552
  const host = madeBy >> 8;
98539
- const mode = host === 3 || host === 19 ? external >>> 16 : 0;
98553
+ return host === 3 || host === 19 ? external >>> 16 : 0;
98554
+ }
98555
+ function kindOf(name, mode, external) {
98540
98556
  const type = mode & 61440;
98541
98557
  if (type === 40960) return "link";
98542
98558
  if (name.endsWith("/") || type === 16384 || (external & 16) !== 0) return "dir";
@@ -98858,7 +98874,7 @@ function stageZip(buf, dest, limits) {
98858
98874
  } catch (err) {
98859
98875
  throw new ImportRefused(err instanceof ZipError ? err.message : `Could not unpack ${wireJoin(...parts)}: ${err.message}`);
98860
98876
  }
98861
- writeFileSync4(out, data, { mode: 420 });
98877
+ writeFileSync4(out, data, { mode: execBits(e.mode) });
98862
98878
  }
98863
98879
  t.out.files.sort((a, b2) => a.path < b2.path ? -1 : a.path > b2.path ? 1 : 0);
98864
98880
  return t.out;
@@ -99316,7 +99332,7 @@ var AppHandover = class {
99316
99332
  /** An id that already exists — even a folder standing there with an invalid manifest belongs to the person. Never overwritten (the same rule as a new app) */
99317
99333
  refuseTaken(id3) {
99318
99334
  this.host.rescanUser();
99319
- if (this.host.userApp(id3) || existsSync9(join19(this.host.dataRoot, "apps", id3))) {
99335
+ if (this.host.userApp(id3) || existsSync9(join19(this.host.dataRoot, ...USER_APPS_PARTS, id3))) {
99320
99336
  throw new ImportRefused(`An app with the id "${id3}" is already in your apps. Remove it first, or change the id in its manifest`);
99321
99337
  }
99322
99338
  }
@@ -99897,7 +99913,7 @@ var ExternalApps = class {
99897
99913
  // ── Discovery ──────────────────────────────────────────────────────────────────────
99898
99914
  require(ref) {
99899
99915
  const e = this.find(ref);
99900
- if (!e) throw new AppUnavailableError(`There is no such app: ${ref.projectId ?? "user"}/${ref.appId}`);
99916
+ if (!e) throw new AppUnavailableError(noSuchAppText(ref));
99901
99917
  return e;
99902
99918
  }
99903
99919
  find(ref) {
@@ -101172,8 +101188,8 @@ Answer with agent_session(sessionId="${r.sessionId}", action="answer", card=\u20
101172
101188
  }
101173
101189
  var NO_POLLING = "Do not check on it with status meanwhile. With nothing else to do, wait is the one call that blocks until the end:";
101174
101190
  var NEW_ROLE_NEW_AGENT = "For another kind of work (say, editing files after read-only research), start a new agent instead, with the task written in full: it starts without this one's context, and this one's name and role came from its first task.";
101175
- function cleanUpLine(sessionId) {
101176
- return `Once you have used its answer and need nothing more from it, delete it: agent_session(sessionId="${sessionId}", action="delete"). Work not on the trunk is kept in the trash.`;
101191
+ function cleanUpLine(sessionId, call2 = `agent_session(sessionId="${sessionId}", action="delete")`) {
101192
+ return `Once you have used its answer and need nothing more from it, delete it: ${call2}. Work not on the trunk is kept in the trash.`;
101177
101193
  }
101178
101194
  function agentListText(r) {
101179
101195
  if (!r.ok) return { text: r.error, isError: true };
@@ -101749,7 +101765,6 @@ function orchestratorToolSchemas(profile = "orchestrator") {
101749
101765
  }
101750
101766
 
101751
101767
  // packages/agent-host/src/sessions/orchestrator-tools.ts
101752
- var filled2 = (v) => v?.trim() ? v.trim() : void 0;
101753
101768
  function issuesText(error51) {
101754
101769
  return error51.issues.map((i) => `${i.path.join(".") || "(args)"}: ${i.message}`).join("; ");
101755
101770
  }
@@ -101811,20 +101826,20 @@ var HANDLERS = {
101811
101826
  const project2 = args.project.trim();
101812
101827
  if (!project2) return { text: "Give a project \u2014 the name of another Centralu project.", isError: true };
101813
101828
  const task = args.task?.trim() ? args.task : void 0;
101814
- const session2 = filled2(args.session);
101829
+ const session2 = trimmed(args.session);
101815
101830
  const { ifBusy } = args;
101816
101831
  return askProjectText(await tools.askProject({ project: project2, ...session2 ? { session: session2 } : {}, ...task ? { task } : {}, ...ifBusy ? { ifBusy } : {} }, signal));
101817
101832
  },
101818
101833
  async start_agent(args, { tools, signal, caller }) {
101819
101834
  const task = args.task.trim() ? args.task : void 0;
101820
101835
  if (!task) return { text: "Give a task: what the new session should do.", isError: true };
101821
- const tool = filled2(args.tool);
101822
- const model = filled2(args.model);
101823
- const effort = filled2(args.effort);
101836
+ const tool = trimmed(args.tool);
101837
+ const model = trimmed(args.model);
101838
+ const effort = trimmed(args.effort);
101824
101839
  const { difficulty } = args;
101825
- const branch = filled2(args.branch);
101826
- const name = filled2(args.name);
101827
- const machine = filled2(args.machine);
101840
+ const branch = trimmed(args.branch);
101841
+ const name = trimmed(args.name);
101842
+ const machine = trimmed(args.machine);
101828
101843
  return agentCallsFor(caller, agentRunText(
101829
101844
  await tools.startAgent(
101830
101845
  {
@@ -101845,14 +101860,14 @@ var HANDLERS = {
101845
101860
  ));
101846
101861
  },
101847
101862
  async agent_session(args, { tools, signal, caller }) {
101848
- const sessionId = filled2(args.sessionId);
101863
+ const sessionId = trimmed(args.sessionId);
101849
101864
  const { action, ifBusy } = args;
101850
101865
  if (action === "list") return agentCallsFor(caller, agentListText(await tools.listAgents()));
101851
101866
  if (!sessionId) return { text: "Give the sessionId start_agent returned.", isError: true };
101852
101867
  const text2 = args.text?.trim() ? args.text : void 0;
101853
101868
  if (action === "send" && !text2) return { text: "Give text: what to send it.", isError: true };
101854
101869
  if (action === "answer" && !text2) return { text: "Give text: the answer.", isError: true };
101855
- const card = filled2(args.card);
101870
+ const card = trimmed(args.card);
101856
101871
  return agentCallsFor(caller, agentRunText(await tools.agentSession({ sessionId, action, ...text2 ? { text: text2 } : {}, ...card ? { card } : {}, ...ifBusy ? { ifBusy } : {} }, signal)));
101857
101872
  },
101858
101873
  async recall({ query, limit }, { tools }) {
@@ -101872,13 +101887,13 @@ Not searched: ${r.notSearched.join("; ")}.` : "";
101872
101887
  const sessionId = args.sessionId.trim();
101873
101888
  const text2 = args.text.trim();
101874
101889
  if (!sessionId || !text2) return { text: "Give sessionId and text: the session and your answer.", isError: true };
101875
- const card = filled2(args.card);
101890
+ const card = trimmed(args.card);
101876
101891
  const r = await tools.answerQuestion({ sessionId, text: text2, ...card ? { card } : {} });
101877
101892
  if (!r.ok) return { text: r.error, isError: true };
101878
101893
  return { text: `Answered card ${r.state === "answered" ? r.card : ""} in "${r.sessionName}" [${r.sessionId}]; it goes on.` };
101879
101894
  },
101880
101895
  async read_session(args, { tools, caller }) {
101881
- if (caller.profile === "reader" && !args.sessionId) return listSessionsText(tools, caller, filled2(args.project));
101896
+ if (caller.profile === "reader" && !args.sessionId) return listSessionsText(tools, caller, trimmed(args.project));
101882
101897
  const r = await tools.readSession(args.sessionId ?? "", args.limit, {
101883
101898
  around: args.around,
101884
101899
  tools: args.tools === true
@@ -101897,12 +101912,12 @@ ${cardsText(r.cards)}
101897
101912
  },
101898
101913
  async create_project(args, { tools, signal }) {
101899
101914
  const folder = args.name ?? "";
101900
- const git2 = filled2(args.git);
101915
+ const git2 = trimmed(args.git);
101901
101916
  if (!folder.trim() && !git2) return { text: "Give a name \u2014 the new folder is named by it, and so is the project.", isError: true };
101902
- const parent = filled2(args.parent);
101903
- const branch = git2 ? filled2(args.branch) : void 0;
101917
+ const parent = trimmed(args.parent);
101918
+ const branch = git2 ? trimmed(args.branch) : void 0;
101904
101919
  const source = git2 ? { git: git2, ...branch ? { branch } : {} } : void 0;
101905
- const machine = filled2(args.machine);
101920
+ const machine = trimmed(args.machine);
101906
101921
  const r = await tools.createProject({ name: folder, ...parent ? { parent } : {}, ...source ? { source } : {}, ...machine ? { machine } : {} }, signal);
101907
101922
  if (!r.ok) return { text: `No project was made: ${r.error}`, isError: true };
101908
101923
  return {
@@ -101911,7 +101926,7 @@ ${cardsText(r.cards)}
101911
101926
  },
101912
101927
  async handoff_session(args, { tools, caller, signal }) {
101913
101928
  const sessionId = args.sessionId?.trim() ?? "";
101914
- const waitFor = filled2(args.waitFor);
101929
+ const waitFor = trimmed(args.waitFor);
101915
101930
  if (!sessionId && !waitFor) return { text: "Give sessionId: the session to hand off, from list_sessions.", isError: true };
101916
101931
  const { tool, mode } = args;
101917
101932
  const instructions = args.instructions?.trim() ? args.instructions : void 0;
@@ -101955,7 +101970,7 @@ ${cardsText(r.cards)}
101955
101970
  return { text: r.text };
101956
101971
  },
101957
101972
  async create_app(args, { tools }) {
101958
- const spec = { id: args.id.trim(), name: args.name.trim(), project: filled2(args.project), description: args.description, tool: args.tool };
101973
+ const spec = { id: args.id.trim(), name: args.name.trim(), project: trimmed(args.project), description: args.description, tool: args.tool };
101959
101974
  if (!spec.id || !spec.name) return { text: "Give id and name \u2014 a folder name and a name to show the person are needed for the app to stand.", isError: true };
101960
101975
  const r = await tools.createApp(spec);
101961
101976
  if (!r.ok) return { text: `Could not create it \u2014 ${r.error}`, isError: true };
@@ -102335,10 +102350,15 @@ async function isRepo(cwd) {
102335
102350
  try {
102336
102351
  await git(cwd, ["rev-parse", "--git-dir"]);
102337
102352
  return true;
102338
- } catch {
102339
- return false;
102353
+ } catch (e) {
102354
+ if (notARepository(e)) return false;
102355
+ throw e;
102340
102356
  }
102341
102357
  }
102358
+ function notARepository(e) {
102359
+ const err = e;
102360
+ return /not a git repository/i.test(String(err.stderr || err.message || "")) || err.code === "ENOENT";
102361
+ }
102342
102362
  var SUMMARY_CAP = 1e4;
102343
102363
  async function gitSummary(cwd, trust = {}, limits = {}) {
102344
102364
  const cap = limits.cap ?? SUMMARY_CAP;
@@ -102374,7 +102394,7 @@ async function gitSummary(cwd, trust = {}, limits = {}) {
102374
102394
  const err = e;
102375
102395
  const msg = String(err.stderr || err.message || "");
102376
102396
  if (/Operation not permitted|EPERM|EACCES|permission denied/i.test(msg)) return { isRepo: true, branch: "", changedFiles: 0, denied: true };
102377
- if (/not a git repository/i.test(msg) || err.code === "ENOENT") return { isRepo: false, branch: "", changedFiles: 0 };
102397
+ if (notARepository(e)) return { isRepo: false, branch: "", changedFiles: 0 };
102378
102398
  return { isRepo: true, branch: "", changedFiles: 0, unknown: true };
102379
102399
  }
102380
102400
  }
@@ -103003,8 +103023,8 @@ var WorktreeSessions = class {
103003
103023
  const fromTrunk = trunk && await gitRevParse(params.cwd, trunk) ? trunk : null;
103004
103024
  if (trunk && !fromTrunk) console.error(`[worktree] trunk not found, forking from HEAD instead: ${trunk}`);
103005
103025
  const from = asked ?? fromTrunk;
103006
- const baseSha = from ? await gitRevParse(params.cwd, from) : await gitHeadSha(params.cwd);
103007
103026
  try {
103027
+ const baseSha = from ? await gitRevParse(params.cwd, from) : await gitHeadSha(params.cwd);
103008
103028
  worktree = await gitWorktreeAdd(params.cwd, path2, branch, from ?? void 0, { trusted: true });
103009
103029
  if (baseSha) worktree = { ...worktree, base: baseSha };
103010
103030
  } catch (err) {
@@ -103753,7 +103773,7 @@ ${text2}` : text2 });
103753
103773
  const remote = remoteOf(sessionId);
103754
103774
  if (remote) {
103755
103775
  const earlier = host.children.linkedReports.get(sessionId);
103756
- const mine = reportBack ? { orchestratorId, busy: false } : void 0;
103776
+ const mine = reportBack ? { orchestratorId, busy: false, instruction: text2 } : void 0;
103757
103777
  if (mine) host.children.setLinkedReport(sessionId, mine);
103758
103778
  const r = await remote.send(sessionId, text2, host.meta.get(orchestratorId)?.name ?? "Orchestrator");
103759
103779
  const current = host.children.linkedReports.get(sessionId);
@@ -103769,6 +103789,10 @@ ${text2}` : text2 });
103769
103789
  } else if (mine) failedSends.add(mine);
103770
103790
  return r;
103771
103791
  }
103792
+ if (mine?.instruction !== void 0) {
103793
+ console.error(`[links] ${sessionId}: the machine's record of the instruction was not heard; the next turn end reports`);
103794
+ delete mine.instruction;
103795
+ }
103772
103796
  if (!reportBack && earlier?.orchestratorId === orchestratorId && current === earlier) host.children.dropLinkedReport(sessionId);
103773
103797
  return { ok: true };
103774
103798
  }
@@ -106790,7 +106814,7 @@ var RemoteAgents = class {
106790
106814
  this.save([...this.records(), rec]);
106791
106815
  const waiting = opts.wait === false ? void 0 : this.openWait(rec.sessionId);
106792
106816
  if (!waiting) this.host.children.setLinkedReport(rec.sessionId, { orchestratorId: callerId, busy: false });
106793
- const label = labelOf(this.host.store, caller);
106817
+ const label = labelOf(this.host.store.messages, caller);
106794
106818
  const sent = await reader.send(rec.sessionId, remoteAgentFrame(label, opts.task), label, { depth: depthOf(this.host, callerId) + 1 });
106795
106819
  if (!sent.ok) {
106796
106820
  if (waiting && this.waits.get(rec.sessionId) === waiting) this.waits.delete(rec.sessionId);
@@ -106812,7 +106836,7 @@ var RemoteAgents = class {
106812
106836
  if (rec.callerId !== callerId) return { ok: false, error: `${rec.sessionId} is not a session this session started. agent_session works only on sessions start_agent started from here.` };
106813
106837
  const reader = this.host.linkedReader;
106814
106838
  if (!reader) return { ok: false, error: `${rec.sessionId} is on ${rec.machine}, and no machine is linked to this computer now.` };
106815
- const label = labelOf(this.host.store, this.host.meta.get(callerId));
106839
+ const label = labelOf(this.host.store.messages, this.host.meta.get(callerId));
106816
106840
  const stateOf = async () => {
106817
106841
  const r = await reader.read(rec.sessionId, 1);
106818
106842
  return r.ok ? { ok: true, state: r.state ?? "idle" } : { ok: false, error: `${rec.machine} cannot be asked about "${rec.name}" now: ${r.error ?? "no answer"}` };
@@ -107084,8 +107108,10 @@ var RemoteAgents = class {
107084
107108
  }
107085
107109
  };
107086
107110
 
107087
- // packages/agent-host/src/sessions/delegation-flow.ts
107111
+ // packages/agent-host/src/sessions/hub-sender.ts
107088
107112
  var HUB_SENDER = "_hub-orchestrator";
107113
+
107114
+ // packages/agent-host/src/sessions/delegation-flow.ts
107089
107115
  var DelegationFlow = class {
107090
107116
  constructor(host) {
107091
107117
  this.host = host;
@@ -107252,8 +107278,9 @@ var DelegationFlow = class {
107252
107278
  };
107253
107279
 
107254
107280
  // packages/agent-host/src/sessions/child-reports.ts
107255
- function pausedReportLine(running2, stoppable) {
107256
- return `[Centralu] The assigned work paused: its turn ended while its own background work is still running (${taskList(running2)}). If that work is a server or watcher it leaves running, the answer below may be its final one. A final report follows only if that work ends` + (stoppable ? '; agent_session(action="stop") on it stops that work and ends the wait.\n' : ".\n");
107281
+ function pausedReportLine(running2, stop) {
107282
+ return `[Centralu] The assigned work paused: its turn ended while its own background work is still running (${taskList(running2)}). If that work is a server or watcher it leaves running, the answer below may be its final one. A final report follows only if that work ends` + (stop ? `; ${stop} on it stops that work and ends the wait.
107283
+ ` : ".\n");
107257
107284
  }
107258
107285
  function linkLostReportLine(machine, paused) {
107259
107286
  return `[Centralu] The assigned work paused on its own background work (${taskList(paused)}), and the link to ${frameField(machine)} dropped before that work ended, so its end will not be reported. It may still be running there; read the session once the link is back.
@@ -107382,7 +107409,7 @@ var ChildReports = class {
107382
107409
  async deliverReport(orchestratorId, sessionId, name, project2, preview, ending, work) {
107383
107410
  const stop = this.host.meta.get(sessionId)?.interruption;
107384
107411
  const cutShort = stop?.reason === "network" || stop?.reason === "interrupted" || stop?.reason === "quit";
107385
- const outcome = work && "machineRemoved" in work ? machineRemovedReportLine(work.machineRemoved, work.paused) : work && "linkLost" in work ? linkLostReportLine(work.linkLost, work.paused) : work && "paused" in work ? pausedReportLine(work.paused, work.stoppable) : work && "settled" in work ? settledReportLine(work.settled) : stop?.reason === "network" ? `[Centralu] The assigned work stopped before finishing: a network error ended its turn.
107412
+ const outcome = work && "machineRemoved" in work ? machineRemovedReportLine(work.machineRemoved, work.paused) : work && "linkLost" in work ? linkLostReportLine(work.linkLost, work.paused) : work && "paused" in work ? pausedReportLine(work.paused, work.stoppable ? this.agentCall(orchestratorId, { action: "stop" }) : void 0) : work && "settled" in work ? settledReportLine(work.settled) : stop?.reason === "network" ? `[Centralu] The assigned work stopped before finishing: a network error ended its turn.
107386
107413
  ` : stop?.reason === "interrupted" ? `[Centralu] The assigned work stopped before finishing: its tool interrupted the turn.
107387
107414
  ` : stop?.reason === "quit" ? `[Centralu] The assigned work stopped before finishing: Centralu quit or restarted during its turn.
107388
107415
  ` : ending.type === "error" ? `[Centralu] The assigned work failed.
@@ -107423,8 +107450,17 @@ If you need more, you can read that session's recent conversation with read_sess
107423
107450
  if (!child || !cleanUpDue(child, parentId)) return "";
107424
107451
  const others = ownAgents(this.host, parentId).filter((s) => s.id !== childId && agentState(this.host, s) === "finished").length;
107425
107452
  return `
107426
- ${cleanUpLine(childId)}` + (others ? `
107427
- ${others} other finished session${others === 1 ? "" : "s"} you started remain${others === 1 ? "s" : ""}: agent_session(action="list") shows them.` : "");
107453
+ ${cleanUpLine(childId, this.agentCall(parentId, { sessionId: childId, action: "delete" }))}` + (others ? `
107454
+ ${others} other finished session${others === 1 ? "" : "s"} you started remain${others === 1 ? "s" : ""}: ${this.agentCall(parentId, { action: "list" })} shows them.` : "");
107455
+ }
107456
+ /**
107457
+ * An agent_session call a report names, in the form its receiver calls it (#850): the orchestrator reaches agent_session
107458
+ * only through centralu_run in the `commands` tier, where the bare call it would copy from the report is refused. A
107459
+ * seat without the tool keeps the bare form the reports always named.
107460
+ */
107461
+ agentCall(receiverId, args) {
107462
+ const bare2 = `agent_session(${Object.entries(args).map(([k2, v]) => `${k2}=${JSON.stringify(v)}`).join(", ")})`;
107463
+ return callForm(this.host.toolProfileOf(receiverId), "agent_session", args) ?? bare2;
107428
107464
  }
107429
107465
  /**
107430
107466
  * Tells a session something in its conversation (#428): a report, or Centralu's word on a request, a note or a queued
@@ -108746,7 +108782,7 @@ function failure(text2) {
108746
108782
 
108747
108783
  // packages/agent-host/src/sessions/app-access.ts
108748
108784
  var KEY = (sessionId) => `session_apps:${sessionId}`;
108749
- var SHARED_KEY = (ref) => `app_shared:${ref.projectId}/${ref.appId}`;
108785
+ var SHARED_KEY = (ref) => `app_shared:${appKeyOf(ref.projectId, ref.appId)}`;
108750
108786
  var UNUSABLE2 = /* @__PURE__ */ new Set(["invalid", "untrusted", "unconfirmed", "failed"]);
108751
108787
  function readShared(store2, ref) {
108752
108788
  return ref.projectId !== null && store2.appSetting(SHARED_KEY({ projectId: ref.projectId, appId: ref.appId })) === "1";
@@ -108902,7 +108938,7 @@ var AppAccess = class {
108902
108938
  return { ok: true, app: app2 };
108903
108939
  }
108904
108940
  match(mine, ref) {
108905
- return mine.find((r) => r.server === ref || this.refOf(r) === ref || r.projectId !== null && `${r.projectId}/${r.appId}` === ref) ?? mine.find((r) => r.appId === ref);
108941
+ return mine.find((r) => r.server === ref || this.refOf(r) === ref || r.projectId !== null && appKeyOf(r.projectId, r.appId) === ref) ?? mine.find((r) => r.appId === ref);
108906
108942
  }
108907
108943
  describe(a) {
108908
108944
  const known = this.deps.hub.rt.knownTools({ projectId: a.projectId, appId: a.appId }, "model");
@@ -110656,6 +110692,10 @@ ${attachments.map((a) => `@${a.path}`).join("\n")}` : text2;
110656
110692
  };
110657
110693
 
110658
110694
  // packages/agent-host/src/sessions/linked-reports.ts
110695
+ function fromHub(from) {
110696
+ const id3 = from?.sessionId;
110697
+ return typeof id3 === "string" && id3.endsWith(`.${HUB_SENDER}`);
110698
+ }
110659
110699
  var LinkedReports = class {
110660
110700
  constructor(host) {
110661
110701
  this.host = host;
@@ -110701,6 +110741,10 @@ var LinkedReports = class {
110701
110741
  if (wait.paused) this.settleLater(sessionId, wait);
110702
110742
  return;
110703
110743
  }
110744
+ if (wait.instruction !== void 0) {
110745
+ if (e.type === "user_message" && e.text === wait.instruction && fromHub(e.from)) delete wait.instruction;
110746
+ return;
110747
+ }
110704
110748
  const step = linkedTurnEnd(wait.busy, e);
110705
110749
  if (step?.step === "busy") {
110706
110750
  wait.busy = true;
@@ -111622,7 +111666,7 @@ function isCentraluTool(call2, tool) {
111622
111666
  return call2.tool === tool && (!call2.server || call2.server === ORCHESTRATOR_MCP_NAME);
111623
111667
  }
111624
111668
  function centraluRunCommand(args) {
111625
- const command = str2(args.command).trim();
111669
+ const command = str(args.command).trim();
111626
111670
  if (!/^[a-z]+(?:_[a-z]+)*$/.test(command)) return null;
111627
111671
  return { command, args: jsonObject(args.args) };
111628
111672
  }
@@ -111819,16 +111863,16 @@ var ClaudeSchedules = class _ClaudeSchedules {
111819
111863
  push(m) {
111820
111864
  const content = m.message?.content ?? [];
111821
111865
  if (!Array.isArray(content)) return this.prune();
111822
- if (str2(m.type) === "assistant") {
111866
+ if (str(m.type) === "assistant") {
111823
111867
  for (const b2 of content) {
111824
- if (str2(b2.type) === "tool_use" && SCHEDULE_TOOLS.has(str2(b2.name))) this.calls.set(str2(b2.id), { name: str2(b2.name), input: b2.input ?? {} });
111868
+ if (str(b2.type) === "tool_use" && SCHEDULE_TOOLS.has(str(b2.name))) this.calls.set(str(b2.id), { name: str(b2.name), input: b2.input ?? {} });
111825
111869
  }
111826
111870
  return this.prune();
111827
111871
  }
111828
- const results = content.filter((b2) => str2(b2.type) === "tool_result");
111872
+ const results = content.filter((b2) => str(b2.type) === "tool_result");
111829
111873
  let changed = this.prune();
111830
111874
  for (const b2 of results) {
111831
- const id3 = str2(b2.tool_use_id);
111875
+ const id3 = str(b2.tool_use_id);
111832
111876
  const call2 = this.calls.get(id3);
111833
111877
  if (!call2) continue;
111834
111878
  this.calls.delete(id3);
@@ -111848,32 +111892,32 @@ var ClaudeSchedules = class _ClaudeSchedules {
111848
111892
  }
111849
111893
  const asked = typeof call2.input.delaySeconds === "number" ? Math.min(Math.max(call2.input.delaySeconds, 60), WAKEUP_MAX_S) : WAKEUP_MAX_S;
111850
111894
  const due2 = typeof out.scheduledFor === "number" ? out.scheduledFor : now + asked * 1e3;
111851
- const reason = str2(call2.input.reason);
111895
+ const reason = str(call2.input.reason);
111852
111896
  this.wakeups.set(callId, { id: `schedule-wakeup-${callId}`, due: due2, description: `Wakes itself at ${clock(due2)} (/loop)${reason ? `: ${reason}` : ""}` });
111853
111897
  return true;
111854
111898
  }
111855
111899
  if (call2.name === "CronCreate") {
111856
- const jobId = str2(out.id) || callId;
111857
- if (!str2(out.id)) this.unnamed.add(jobId);
111858
- const when = str2(out.humanSchedule) || str2(call2.input.cron);
111900
+ const jobId = str(out.id) || callId;
111901
+ if (!str(out.id)) this.unnamed.add(jobId);
111902
+ const when = str(out.humanSchedule) || str(call2.input.cron);
111859
111903
  this.crons.set(jobId, { id: `schedule-cron-${jobId}`, due: now + CRON_EXPIRY_MS, description: `Scheduled prompt, ${when}` });
111860
111904
  return true;
111861
111905
  }
111862
111906
  if (call2.name === "CronDelete") {
111863
- if (this.crons.delete(str2(call2.input.id) || str2(out.id))) return true;
111907
+ if (this.crons.delete(str(call2.input.id) || str(out.id))) return true;
111864
111908
  const guess = [...this.unnamed].find((k2) => this.crons.has(k2));
111865
111909
  if (!guess) return false;
111866
111910
  this.unnamed.delete(guess);
111867
111911
  return this.crons.delete(guess);
111868
111912
  }
111869
111913
  if (call2.name === "CronList" && Array.isArray(out.jobs)) {
111870
- const listed = new Set(out.jobs.map((j2) => str2(j2.id)));
111914
+ const listed = new Set(out.jobs.map((j2) => str(j2.id)));
111871
111915
  let changed = false;
111872
111916
  for (const id3 of [...this.crons.keys()]) if (!listed.has(id3)) changed = this.crons.delete(id3) || changed;
111873
111917
  for (const j2 of out.jobs) {
111874
- const id3 = str2(j2.id);
111918
+ const id3 = str(j2.id);
111875
111919
  if (!id3 || this.crons.has(id3)) continue;
111876
- this.crons.set(id3, { id: `schedule-cron-${id3}`, due: now + CRON_EXPIRY_MS, description: `Scheduled prompt, ${str2(j2.humanSchedule) || str2(j2.cron)}` });
111920
+ this.crons.set(id3, { id: `schedule-cron-${id3}`, due: now + CRON_EXPIRY_MS, description: `Scheduled prompt, ${str(j2.humanSchedule) || str(j2.cron)}` });
111877
111921
  changed = true;
111878
111922
  }
111879
111923
  return changed;
@@ -111938,6 +111982,34 @@ var ClaudeSchedules = class _ClaudeSchedules {
111938
111982
  }
111939
111983
  };
111940
111984
 
111985
+ // packages/agent-host/src/adapters/background-events.ts
111986
+ var BACKGROUND_SUMMARY_CHARS = 300;
111987
+ function endedSummary(text2) {
111988
+ const summary = (text2 ?? "").slice(0, BACKGROUND_SUMMARY_CHARS);
111989
+ return summary ? { summary } : {};
111990
+ }
111991
+ var BackgroundEvents = class {
111992
+ constructor(sessionId) {
111993
+ this.sessionId = sessionId;
111994
+ }
111995
+ sessionId;
111996
+ last = "[]";
111997
+ event(live2, ended = [], snapshot2 = false) {
111998
+ const key = JSON.stringify(live2);
111999
+ if (key === this.last && ended.length === 0 && !snapshot2) return [];
112000
+ this.last = key;
112001
+ return [
112002
+ {
112003
+ type: "background_tasks",
112004
+ ...snapshot2 ? { snapshot: true } : {},
112005
+ sessionId: this.sessionId,
112006
+ live: live2,
112007
+ ...ended.length ? { ended } : {}
112008
+ }
112009
+ ];
112010
+ }
112011
+ };
112012
+
111941
112013
  // packages/agent-host/src/adapters/claude/background-tracker.ts
111942
112014
  function taskKind(type) {
111943
112015
  if (/agent|teammate/.test(type)) return "agent";
@@ -111946,11 +112018,6 @@ function taskKind(type) {
111946
112018
  return "other";
111947
112019
  }
111948
112020
  var ClaudeBackgroundTracker = class {
111949
- constructor(sessionId, now = Date.now) {
111950
- this.sessionId = sessionId;
111951
- this.schedules = new ClaudeSchedules(now);
111952
- }
111953
- sessionId;
111954
112021
  /** Ids in the last level, in its order. */
111955
112022
  live = [];
111956
112023
  /** Every id the level ever listed — only those are background work (a foreground task's ending is its card's). */
@@ -111958,6 +112025,12 @@ var ClaudeBackgroundTracker = class {
111958
112025
  info = /* @__PURE__ */ new Map();
111959
112026
  /** Timers the CLI holds in this process for the session (`ClaudeSchedules`), listed with the tasks */
111960
112027
  schedules;
112028
+ /** The events, by the rule both adapters share (`BackgroundEvents`): a repeat of the last list is not sent */
112029
+ events;
112030
+ constructor(sessionId, now = Date.now) {
112031
+ this.schedules = new ClaudeSchedules(now);
112032
+ this.events = new BackgroundEvents(sessionId);
112033
+ }
111961
112034
  /** When the earliest scheduled wake-up is due (epoch ms), for a look then (`tick`); null with none */
111962
112035
  nextDue() {
111963
112036
  return this.schedules.nextDue();
@@ -111967,7 +112040,7 @@ var ClaudeBackgroundTracker = class {
111967
112040
  * (`ClaudeSchedules.recover`); the new level when that found any
111968
112041
  */
111969
112042
  recover(messages2) {
111970
- return this.schedules.recover(messages2) ? [this.event()] : [];
112043
+ return this.schedules.recover(messages2) ? this.event() : [];
111971
112044
  }
111972
112045
  /**
111973
112046
  * The tasks the previous host last saw running in an adopted process (#648, `ProcessSource.adopt.backgroundTasks`).
@@ -111993,66 +112066,65 @@ var ClaudeBackgroundTracker = class {
111993
112066
  }
111994
112067
  /** Drops the wake-ups whose time has passed; the new level when that changed anything */
111995
112068
  tick() {
111996
- return this.schedules.prune() ? [this.event()] : [];
112069
+ return this.schedules.prune() ? this.event() : [];
111997
112070
  }
111998
112071
  push(m) {
111999
- if (str2(m.type) === "assistant" || str2(m.type) === "user") {
112072
+ if (str(m.type) === "assistant" || str(m.type) === "user") {
112000
112073
  const changed = this.schedules.push(m);
112001
- return changed ? [this.event()] : [];
112074
+ return changed ? this.event() : [];
112002
112075
  }
112003
- if (str2(m.type) !== "system") return [];
112004
- const subtype = str2(m.subtype);
112076
+ if (str(m.type) !== "system") return [];
112077
+ const subtype = str(m.subtype);
112005
112078
  if (subtype === "background_tasks_changed") {
112006
112079
  const tasks = Array.isArray(m.tasks) ? m.tasks : [];
112007
112080
  this.live = [];
112008
112081
  for (const t of tasks) {
112009
- const id3 = str2(t.task_id);
112082
+ const id3 = str(t.task_id);
112010
112083
  if (!id3) continue;
112011
112084
  const prev = this.info.get(id3);
112012
112085
  this.info.set(id3, {
112013
112086
  ...prev,
112014
- kind: taskKind(str2(t.task_type)),
112015
- description: str2(t.description, prev?.description ?? ""),
112087
+ kind: taskKind(str(t.task_type)),
112088
+ description: str(t.description, prev?.description ?? ""),
112016
112089
  ...t.ambient === true ? { ambient: true } : { ambient: void 0 }
112017
112090
  });
112018
112091
  this.live.push(id3);
112019
112092
  this.seen.add(id3);
112020
112093
  }
112021
- return [this.event(void 0, true)];
112094
+ return this.event(void 0, true);
112022
112095
  }
112023
112096
  if (subtype === "task_started" || subtype === "task_updated") {
112024
- const id3 = str2(m.task_id);
112097
+ const id3 = str(m.task_id);
112025
112098
  const prev = this.info.get(id3);
112026
112099
  if (!id3) return [];
112027
112100
  if (subtype === "task_started") {
112028
- const callId = str2(m.tool_use_id);
112101
+ const callId = str(m.tool_use_id);
112029
112102
  const depth = typeof m.spawn_depth === "number" ? m.spawn_depth : 1;
112030
112103
  this.info.set(id3, {
112031
112104
  ...prev,
112032
- kind: str2(m.task_type) ? taskKind(str2(m.task_type)) : prev?.kind ?? "other",
112033
- description: prev?.description || str2(m.description),
112105
+ kind: str(m.task_type) ? taskKind(str(m.task_type)) : prev?.kind ?? "other",
112106
+ description: prev?.description || str(m.description),
112034
112107
  ...callId ? { parentCallId: callId } : {},
112035
112108
  ...m.owned_by_subagent === true || depth > 1 ? { nested: true } : {},
112036
112109
  ...m.ambient === true ? { ambient: true } : {}
112037
112110
  });
112038
112111
  } else {
112039
- const description = str2(m.patch?.description);
112112
+ const description = str(m.patch?.description);
112040
112113
  if (!prev || !description) return [];
112041
112114
  this.info.set(id3, { ...prev, description });
112042
112115
  }
112043
- return this.live.includes(id3) ? [this.event()] : [];
112116
+ return this.live.includes(id3) ? this.event() : [];
112044
112117
  }
112045
112118
  if (subtype === "task_notification") {
112046
- const id3 = str2(m.task_id);
112119
+ const id3 = str(m.task_id);
112047
112120
  const known = this.info.get(id3);
112048
112121
  this.info.delete(id3);
112049
112122
  if (!this.seen.has(id3)) return [];
112050
112123
  this.seen.delete(id3);
112051
112124
  this.live = this.live.filter((x) => x !== id3);
112052
- const raw = str2(m.status);
112125
+ const raw = str(m.status);
112053
112126
  const status = raw === "failed" || raw === "stopped" ? raw : "completed";
112054
- const summary = str2(m.summary).slice(0, 300);
112055
- return [this.event([{ ...this.entry(id3, known), status, ...summary ? { summary } : {} }])];
112127
+ return this.event([{ ...this.entry(id3, known), status, ...endedSummary(str(m.summary)) }]);
112056
112128
  }
112057
112129
  return [];
112058
112130
  }
@@ -112068,7 +112140,7 @@ var ClaudeBackgroundTracker = class {
112068
112140
  this.live = [];
112069
112141
  this.info.clear();
112070
112142
  this.seen.clear();
112071
- return [this.event(ended)];
112143
+ return this.event(ended);
112072
112144
  }
112073
112145
  entry(id3, i) {
112074
112146
  const kind = i?.kind ?? "other";
@@ -112085,20 +112157,14 @@ var ClaudeBackgroundTracker = class {
112085
112157
  };
112086
112158
  }
112087
112159
  event(ended, snapshot2) {
112088
- return {
112089
- type: "background_tasks",
112090
- ...snapshot2 ? { snapshot: snapshot2 } : {},
112091
- sessionId: this.sessionId,
112092
- live: [...this.live.map((id3) => this.entry(id3, this.info.get(id3))), ...this.schedules.live()],
112093
- ...ended ? { ended } : {}
112094
- };
112160
+ return this.events.event([...this.live.map((id3) => this.entry(id3, this.info.get(id3))), ...this.schedules.live()], ended, snapshot2);
112095
112161
  }
112096
112162
  };
112097
112163
 
112098
112164
  // packages/agent-host/src/adapters/claude/cli-messages.ts
112099
112165
  function conversationResetEvents(m, sessionId) {
112100
112166
  const out = [];
112101
- const trigger = str2(m.trigger);
112167
+ const trigger = str(m.trigger);
112102
112168
  out.push({ type: "conversation_reset", sessionId, ...trigger ? { trigger } : {} });
112103
112169
  return out;
112104
112170
  }
@@ -112109,16 +112175,16 @@ function activeGoalEvents(m, sessionId) {
112109
112175
  type: "goal",
112110
112176
  sessionId,
112111
112177
  goal: v ? {
112112
- objective: str2(v.condition),
112178
+ objective: str(v.condition),
112113
112179
  status: "active",
112114
112180
  ...typeof v.iterations === "number" ? { iterations: v.iterations } : {},
112115
- ...str2(v.last_reason) ? { reason: str2(v.last_reason) } : {}
112181
+ ...str(v.last_reason) ? { reason: str(v.last_reason) } : {}
112116
112182
  } : null
112117
112183
  });
112118
112184
  return out;
112119
112185
  }
112120
112186
  function systemEvents(m, sessionId) {
112121
- switch (str2(m.subtype)) {
112187
+ switch (str(m.subtype)) {
112122
112188
  case "informational":
112123
112189
  return informationalEvents(m, sessionId);
112124
112190
  case "notification":
@@ -112137,8 +112203,8 @@ function systemEvents(m, sessionId) {
112137
112203
  }
112138
112204
  function informationalEvents(m, sessionId) {
112139
112205
  const out = [];
112140
- const text2 = str2(m.content).trim();
112141
- const level = str2(m.level);
112206
+ const text2 = str(m.content).trim();
112207
+ const level = str(m.level);
112142
112208
  if (text2 && level !== "info") {
112143
112209
  const hook = /\bblocked by hook\b/.test(text2);
112144
112210
  out.push({
@@ -112155,10 +112221,10 @@ function informationalEvents(m, sessionId) {
112155
112221
  }
112156
112222
  function notificationEvents(m, sessionId) {
112157
112223
  const out = [];
112158
- const text2 = str2(m.text).trim();
112159
- if (!text2 || str2(m.key) === "error-compacting-conversation") return out;
112160
- const color = str2(m.color);
112161
- const priority = str2(m.priority);
112224
+ const text2 = str(m.text).trim();
112225
+ if (!text2 || str(m.key) === "error-compacting-conversation") return out;
112226
+ const color = str(m.color);
112227
+ const priority = str(m.priority);
112162
112228
  const level = color === "error" ? "error" : color === "warning" || priority === "high" || priority === "immediate" ? "warning" : "info";
112163
112229
  out.push({ type: "notice", sessionId, level, text: text2, from: "Claude Code", label: "notice" });
112164
112230
  return out;
@@ -112168,7 +112234,7 @@ function apiRetryEvents(m, sessionId) {
112168
112234
  const status = typeof m.error_status === "number" ? `${m.error_status} ` : "";
112169
112235
  const delay = typeof m.retry_delay_ms === "number" ? ` in ${m.retry_delay_ms}ms` : "";
112170
112236
  console.error(
112171
- `[claude] ${sessionId.slice(0, 8)} retrying after: ${status}${str2(m.error, "connection error")} (attempt ${String(m.attempt ?? "?")}/${String(m.max_retries ?? "?")}${delay})`
112237
+ `[claude] ${sessionId.slice(0, 8)} retrying after: ${status}${str(m.error, "connection error")} (attempt ${String(m.attempt ?? "?")}/${String(m.max_retries ?? "?")}${delay})`
112172
112238
  );
112173
112239
  out.push({ type: "activity", sessionId, activity: "retrying" });
112174
112240
  return out;
@@ -112176,14 +112242,14 @@ function apiRetryEvents(m, sessionId) {
112176
112242
  function statusEvents(m, sessionId) {
112177
112243
  const out = [];
112178
112244
  out.push({ type: "activity", sessionId, activity: m.status === "compacting" ? "compacting" : null });
112179
- if (str2(m.compact_result) === "failed") {
112180
- out.push({ type: "compaction", sessionId, failed: true, reason: str2(m.compact_error, "Unknown reason") });
112245
+ if (str(m.compact_result) === "failed") {
112246
+ out.push({ type: "compaction", sessionId, failed: true, reason: str(m.compact_error, "Unknown reason") });
112181
112247
  }
112182
112248
  return out;
112183
112249
  }
112184
112250
  function localCommandOutputEvents(m, sessionId) {
112185
112251
  const out = [];
112186
- const content = str2(m.content);
112252
+ const content = str(m.content);
112187
112253
  if (content) out.push({ type: "message_delta", sessionId, role: "assistant", text: content });
112188
112254
  return out;
112189
112255
  }
@@ -112204,7 +112270,7 @@ function compactBoundaryEvents(m, sessionId) {
112204
112270
  function textOfContent(content) {
112205
112271
  if (typeof content === "string") return content;
112206
112272
  if (!Array.isArray(content)) return "";
112207
- return content.filter((b2) => str2(b2?.type) === "text").map((b2) => str2(b2.text)).join("");
112273
+ return content.filter((b2) => str(b2?.type) === "text").map((b2) => str(b2.text)).join("");
112208
112274
  }
112209
112275
  var ClaudeGoalTracker = class {
112210
112276
  constructor(sessionId) {
@@ -112232,13 +112298,13 @@ var ClaudeGoalTracker = class {
112232
112298
  }
112233
112299
  /** Reads one parent-stream message. `streamed`: this assistant message's body came as deltas, i.e. a model call. */
112234
112300
  push(m, opts) {
112235
- const type = str2(m.type);
112301
+ const type = str(m.type);
112236
112302
  if (type === "active_goal") {
112237
112303
  this.announced = true;
112238
112304
  return [];
112239
112305
  }
112240
112306
  if (this.announced) return [];
112241
- if (type === "stream_event" && str2(m.event?.type) === "message_start") {
112307
+ if (type === "stream_event" && str(m.event?.type) === "message_start") {
112242
112308
  if (this.goal) this.drove = true;
112243
112309
  return [];
112244
112310
  }
@@ -112260,7 +112326,7 @@ var ClaudeGoalTracker = class {
112260
112326
  if (type === "result") {
112261
112327
  const drove = this.drove;
112262
112328
  this.drove = false;
112263
- const success2 = str2(m.subtype) === "success" && m.is_error !== true;
112329
+ const success2 = str(m.subtype) === "success" && m.is_error !== true;
112264
112330
  if (this.goal && drove && success2 && !opts.interrupted) return this.set(null);
112265
112331
  }
112266
112332
  return [];
@@ -112318,7 +112384,7 @@ function mcpImageEvents(sessionId, content) {
112318
112384
  if (!Array.isArray(content)) return [];
112319
112385
  const out = [];
112320
112386
  for (const raw of content) {
112321
- const part = typeof raw === "object" && raw !== null ? raw : {};
112387
+ const part = asObj(raw);
112322
112388
  if (part.type !== "image") continue;
112323
112389
  const data = typeof part.data === "string" ? part.data : "";
112324
112390
  const mime = typeof part.mimeType === "string" ? part.mimeType : "";
@@ -112348,7 +112414,7 @@ function stepStatus(raw) {
112348
112414
  }
112349
112415
  function planUpdate(sessionId, raw, textField) {
112350
112416
  const steps = (Array.isArray(raw) ? raw : []).map((s) => {
112351
- const it2 = typeof s === "object" && s !== null ? s : {};
112417
+ const it2 = asObj(s);
112352
112418
  const text2 = it2[textField];
112353
112419
  return { text: typeof text2 === "string" ? text2 : "", status: stepStatus(it2.status) };
112354
112420
  });
@@ -112356,7 +112422,7 @@ function planUpdate(sessionId, raw, textField) {
112356
112422
  }
112357
112423
  function todoWritePlan(sessionId, name, input) {
112358
112424
  if (name !== "TodoWrite") return [];
112359
- const todos = (typeof input === "object" && input !== null ? input : {}).todos;
112425
+ const todos = asObj(input).todos;
112360
112426
  return Array.isArray(todos) ? [planUpdate(sessionId, todos, "content")] : [];
112361
112427
  }
112362
112428
 
@@ -112372,14 +112438,14 @@ function toolSummary(name, input) {
112372
112438
  if (run4) return toolSummary(run4.name, run4.input);
112373
112439
  const paths = [];
112374
112440
  let title = name;
112375
- if (name === "Bash") title = str2(input.command, name);
112441
+ if (name === "Bash") title = str(input.command, name);
112376
112442
  else if (FILE_EDIT_TOOLS.has(name) || name === "Read") {
112377
- const p = str2(input.file_path ?? input.notebook_path);
112443
+ const p = str(input.file_path ?? input.notebook_path);
112378
112444
  if (p) paths.push(p);
112379
112445
  title = `${name}: ${p || "?"}`;
112380
- } else if (name === "Grep" || name === "Glob") title = `${name}: ${str2(input.pattern)}`;
112381
- else if (isCentraluTool({ name }, "ask_project")) title = str2(input.project).trim() || name;
112382
- else if (launchesSubagent(name)) title = str2(input.description, name);
112446
+ } else if (name === "Grep" || name === "Glob") title = `${name}: ${str(input.pattern)}`;
112447
+ else if (isCentraluTool({ name }, "ask_project")) title = str(input.project).trim() || name;
112448
+ else if (launchesSubagent(name)) title = str(input.description, name);
112383
112449
  const parts = mcpNameParts(name);
112384
112450
  const mark = parts ? centraluMark(parts.server, parts.tool, input) : null;
112385
112451
  return { tool: name, title: mark?.title ?? title, paths, ...mark ? { centralu: mark.centralu } : {} };
@@ -112405,29 +112471,29 @@ ${report}` : report;
112405
112471
  function resultOutput(content) {
112406
112472
  if (typeof content === "string") return content;
112407
112473
  if (!Array.isArray(content)) return content == null ? "" : JSON.stringify(content);
112408
- return content.filter((b2) => str2(b2?.type) !== "image" && str2(b2?.source?.type) !== "base64").map((b2) => str2(b2?.type) === "text" ? str2(b2.text) : JSON.stringify(b2)).join("\n");
112474
+ return content.filter((b2) => str(b2?.type) !== "image" && str(b2?.source?.type) !== "base64").map((b2) => str(b2?.type) === "text" ? str(b2.text) : JSON.stringify(b2)).join("\n");
112409
112475
  }
112410
112476
  function claudeFileChange(name, input, isNew) {
112411
- const path2 = str2(input.file_path ?? input.notebook_path);
112477
+ const path2 = str(input.file_path ?? input.notebook_path);
112412
112478
  if (name === "Edit") {
112413
- const diff2 = [diffLines("-", str2(input.old_string)), diffLines("+", str2(input.new_string))].filter(Boolean).join("\n");
112479
+ const diff2 = [diffLines("-", str(input.old_string)), diffLines("+", str(input.new_string))].filter(Boolean).join("\n");
112414
112480
  return { path: path2, diff: input.replace_all === true && diff2 ? `(every occurrence)
112415
112481
  ${diff2}` : diff2 };
112416
112482
  }
112417
112483
  if (name === "Write") {
112418
- const content = str2(input.content);
112484
+ const content = str(input.content);
112419
112485
  if (isNew === true) return { path: path2, diff: diffLines("+", content), change: "add" };
112420
112486
  const head = isNew === false ? "(replaces the whole file)" : "(writes the whole file)";
112421
112487
  return { path: path2, diff: content ? `${head}
112422
112488
  ${content.replace(/\n$/, "")}` : "" };
112423
112489
  }
112424
- const mode = str2(input.edit_mode);
112425
- const diff = diffLines("+", str2(input.new_source));
112426
- return { path: path2, diff: mode === "delete" ? `(deletes cell ${str2(input.cell_id) || "?"})` : mode === "insert" ? `(inserts a cell)
112490
+ const mode = str(input.edit_mode);
112491
+ const diff = diffLines("+", str(input.new_source));
112492
+ return { path: path2, diff: mode === "delete" ? `(deletes cell ${str(input.cell_id) || "?"})` : mode === "insert" ? `(inserts a cell)
112427
112493
  ${diff}` : diff };
112428
112494
  }
112429
112495
  function approvalDetail(name, input, cwd, isNew) {
112430
- if (name === "Bash") return { kind: "command", command: str2(input.command), cwd, ...input.dangerouslyDisableSandbox === true ? { unsandboxed: true } : {} };
112496
+ if (name === "Bash") return { kind: "command", command: str(input.command), cwd, ...input.dangerouslyDisableSandbox === true ? { unsandboxed: true } : {} };
112431
112497
  if (FILE_EDIT_TOOLS.has(name)) {
112432
112498
  const change = claudeFileChange(name, input, isNew);
112433
112499
  return fileEditDetail([change.diff ? change : { ...change, diff: JSON.stringify(input) }]);
@@ -112438,20 +112504,20 @@ function approvalDetail(name, input, cwd, isNew) {
112438
112504
  // packages/agent-host/src/adapters/claude/model-messages.ts
112439
112505
  function backgroundLaunch(m) {
112440
112506
  const r = m.tool_use_result ?? {};
112441
- if (str2(r.status) !== "async_launched" || !str2(r.agentId)) return null;
112442
- const blocks = (m.message?.content ?? []).filter((b2) => str2(b2.type) === "tool_result");
112443
- return blocks.length === 1 ? str2(blocks[0]?.tool_use_id) || null : null;
112507
+ if (str(r.status) !== "async_launched" || !str(r.agentId)) return null;
112508
+ const blocks = (m.message?.content ?? []).filter((b2) => str(b2.type) === "tool_result");
112509
+ return blocks.length === 1 ? str(blocks[0]?.tool_use_id) || null : null;
112444
112510
  }
112445
112511
  function streamEventEvents(m, sessionId) {
112446
112512
  const out = [];
112447
112513
  const e = m.event;
112448
- if (str2(e?.type) === "content_block_delta") {
112514
+ if (str(e?.type) === "content_block_delta") {
112449
112515
  const d2 = e?.delta;
112450
- if (str2(d2?.type) === "text_delta") {
112451
- out.push({ type: "message_delta", sessionId, role: "assistant", text: str2(d2?.text) });
112516
+ if (str(d2?.type) === "text_delta") {
112517
+ out.push({ type: "message_delta", sessionId, role: "assistant", text: str(d2?.text) });
112452
112518
  }
112453
- if (str2(d2?.type) === "thinking_delta") {
112454
- const text2 = str2(d2?.thinking);
112519
+ if (str(d2?.type) === "thinking_delta") {
112520
+ const text2 = str(d2?.thinking);
112455
112521
  const estTokens = typeof d2?.estimated_tokens === "number" ? d2.estimated_tokens : void 0;
112456
112522
  if (text2 || estTokens) {
112457
112523
  out.push({ type: "reasoning_delta", sessionId, ...text2 ? { text: text2 } : {}, ...estTokens ? { estTokens } : {} });
@@ -112464,21 +112530,21 @@ function assistantEvents(m, sessionId, opts) {
112464
112530
  const out = [];
112465
112531
  const content = m.message?.content ?? [];
112466
112532
  if (!opts?.reasoningStreamed) {
112467
- const thinking = content.filter((b2) => str2(b2.type) === "thinking").map((b2) => str2(b2.thinking)).join("");
112533
+ const thinking = content.filter((b2) => str(b2.type) === "thinking").map((b2) => str(b2.thinking)).join("");
112468
112534
  if (thinking) out.push({ type: "reasoning_delta", sessionId, text: thinking });
112469
112535
  }
112470
112536
  if (!opts?.textStreamed) {
112471
- const text2 = content.filter((b2) => str2(b2.type) === "text").map((b2) => str2(b2.text)).join("");
112537
+ const text2 = content.filter((b2) => str(b2.type) === "text").map((b2) => str(b2.text)).join("");
112472
112538
  if (text2) out.push({ type: "message_delta", sessionId, role: "assistant", text: text2 });
112473
112539
  }
112474
112540
  for (const block of content) {
112475
- if (str2(block.type) === "tool_use") {
112476
- const name = str2(block.name);
112541
+ if (str(block.type) === "tool_use") {
112542
+ const name = str(block.name);
112477
112543
  const input = block.input ?? {};
112478
112544
  out.push({
112479
112545
  type: "tool_call",
112480
112546
  sessionId,
112481
- callId: str2(block.id),
112547
+ callId: str(block.id),
112482
112548
  summary: toolSummary(name, input),
112483
112549
  ...block.input !== void 0 ? { input: block.input } : {}
112484
112550
  });
@@ -112490,39 +112556,41 @@ function assistantEvents(m, sessionId, opts) {
112490
112556
  out.push({
112491
112557
  type: "usage_update",
112492
112558
  sessionId,
112493
- tokens: {
112494
- inputTokens: tokenCount(usage.input_tokens),
112495
- outputTokens: tokenCount(usage.output_tokens),
112496
- cacheReadTokens: tokenCount(usage.cache_read_input_tokens),
112497
- cacheCreationTokens: tokenCount(usage.cache_creation_input_tokens)
112498
- }
112559
+ tokens: { ...requestInputTokens(usage), outputTokens: tokenCount(usage.output_tokens) }
112499
112560
  });
112500
112561
  }
112501
112562
  return out;
112502
112563
  }
112564
+ function requestInputTokens(usage) {
112565
+ return {
112566
+ inputTokens: tokenCount(usage.input_tokens),
112567
+ cacheReadTokens: tokenCount(usage.cache_read_input_tokens),
112568
+ cacheCreationTokens: tokenCount(usage.cache_creation_input_tokens)
112569
+ };
112570
+ }
112503
112571
  function userEvents(m, sessionId) {
112504
112572
  const out = [];
112505
112573
  const content = m.message?.content ?? [];
112506
112574
  const launched = backgroundLaunch(m);
112507
112575
  if (launched) return [{ type: "tool_output_delta", sessionId, callId: launched, text: "Running in the background\n" }];
112508
112576
  const agent = m.tool_use_result ?? {};
112509
- const agentDone = str2(agent.status) === "completed" && str2(agent.agentId) && Array.isArray(agent.content) && content.filter((b2) => str2(b2.type) === "tool_result").length === 1 ? agentReport(
112510
- agent.content.map((b2) => str2(b2.text)).join("\n"),
112577
+ const agentDone = str(agent.status) === "completed" && str(agent.agentId) && Array.isArray(agent.content) && content.filter((b2) => str(b2.type) === "tool_result").length === 1 ? agentReport(
112578
+ agent.content.map((b2) => str(b2.text)).join("\n"),
112511
112579
  agentStats(agent.totalToolUseCount, agent.totalDurationMs)
112512
112580
  ) : null;
112513
112581
  for (const block of content) {
112514
- if (str2(block.type) === "tool_result") {
112582
+ if (str(block.type) === "tool_result") {
112515
112583
  const c = block.content;
112516
- out.push(toolResultEvent(sessionId, str2(block.tool_use_id), block.is_error !== true, agentDone ?? resultOutput(c)));
112584
+ out.push(toolResultEvent(sessionId, str(block.tool_use_id), block.is_error !== true, agentDone ?? resultOutput(c)));
112517
112585
  if (Array.isArray(c)) {
112518
112586
  for (const part of c) {
112519
- if (str2(part.type) !== "image") continue;
112587
+ if (str(part.type) !== "image") continue;
112520
112588
  const source = part.source ?? {};
112521
- if (str2(source.type) !== "base64" || !str2(source.data)) {
112522
- out.push(undrawnImageEvent(sessionId, `Cannot display an image of this format yet (source: ${str2(source.type) || "none"})`));
112589
+ if (str(source.type) !== "base64" || !str(source.data)) {
112590
+ out.push(undrawnImageEvent(sessionId, `Cannot display an image of this format yet (source: ${str(source.type) || "none"})`));
112523
112591
  continue;
112524
112592
  }
112525
- out.push(inlineImageEvent(sessionId, str2(source.media_type), str2(source.data)));
112593
+ out.push(inlineImageEvent(sessionId, str(source.media_type), str(source.data)));
112526
112594
  }
112527
112595
  }
112528
112596
  }
@@ -112543,7 +112611,7 @@ var ClaudeTaskPlan = class {
112543
112611
  /** A call was made; the plan tools are remembered until their result */
112544
112612
  call(callId, name, input) {
112545
112613
  if (name !== "TaskCreate" && name !== "TaskUpdate" && name !== "TaskList") return;
112546
- this.open.set(callId, { name, input: typeof input === "object" && input !== null ? input : {} });
112614
+ this.open.set(callId, { name, input: asObj(input) });
112547
112615
  if (this.open.size > 64) this.open.delete(this.open.keys().next().value);
112548
112616
  }
112549
112617
  /**
@@ -112557,21 +112625,21 @@ var ClaudeTaskPlan = class {
112557
112625
  if (!ok) return [];
112558
112626
  if (call2.name === "TaskCreate") {
112559
112627
  const task = record2?.task ?? {};
112560
- const id3 = str2(task.id) || /^Task #(\S+) created/.exec(output)?.[1] || "";
112628
+ const id3 = str(task.id) || /^Task #(\S+) created/.exec(output)?.[1] || "";
112561
112629
  if (!id3) return [];
112562
- this.tasks.set(id3, { text: str2(call2.input.subject) || str2(task.subject), status: "pending" });
112630
+ this.tasks.set(id3, { text: str(call2.input.subject) || str(task.subject), status: "pending" });
112563
112631
  } else if (call2.name === "TaskUpdate") {
112564
- const id3 = str2(call2.input.taskId);
112565
- const status = str2(call2.input.status);
112632
+ const id3 = str(call2.input.taskId);
112633
+ const status = str(call2.input.status);
112566
112634
  const known = this.tasks.get(id3);
112567
112635
  if (status === "deleted") this.tasks.delete(id3);
112568
- else if (known) this.tasks.set(id3, { text: str2(call2.input.subject) || known.text, status: status || known.status });
112569
- else if (str2(call2.input.subject)) this.tasks.set(id3, { text: str2(call2.input.subject), status: status || "pending" });
112636
+ else if (known) this.tasks.set(id3, { text: str(call2.input.subject) || known.text, status: status || known.status });
112637
+ else if (str(call2.input.subject)) this.tasks.set(id3, { text: str(call2.input.subject), status: status || "pending" });
112570
112638
  else return [];
112571
112639
  } else {
112572
112640
  if (!Array.isArray(record2?.tasks)) return [];
112573
112641
  this.tasks.clear();
112574
- for (const t of record2.tasks) if (str2(t.id)) this.tasks.set(str2(t.id), { text: str2(t.subject), status: str2(t.status) });
112642
+ for (const t of record2.tasks) if (str(t.id)) this.tasks.set(str(t.id), { text: str(t.subject), status: str(t.status) });
112575
112643
  }
112576
112644
  return [planUpdate(this.sessionId, [...this.tasks.values()], "text")];
112577
112645
  }
@@ -112581,13 +112649,13 @@ var ClaudeTaskPlan = class {
112581
112649
  function rateLimitEvents(m, sessionId) {
112582
112650
  const out = [];
112583
112651
  const info = m.rate_limit_info ?? {};
112584
- if (str2(info.status) === "rejected") {
112652
+ if (str(info.status) === "rejected") {
112585
112653
  const resetsAt = typeof info.resetsAt === "number" ? new Date(info.resetsAt * 1e3).toISOString() : void 0;
112586
112654
  out.push({
112587
112655
  type: "limit_reached",
112588
112656
  sessionId,
112589
112657
  resumeAt: resetsAt,
112590
- windowMins: str2(info.rateLimitType) === "five_hour" ? 300 : void 0
112658
+ windowMins: str(info.rateLimitType) === "five_hour" ? 300 : void 0
112591
112659
  });
112592
112660
  }
112593
112661
  return out;
@@ -112610,12 +112678,12 @@ function resultEvents(m, sessionId) {
112610
112678
  }
112611
112679
  });
112612
112680
  }
112613
- if (str2(m.subtype) !== "success" || m.is_error === true) {
112681
+ if (str(m.subtype) !== "success" || m.is_error === true) {
112614
112682
  const errors = Array.isArray(m.errors) ? m.errors.filter((x) => typeof x === "string" && x.length > 0) : [];
112615
112683
  out.push({
112616
112684
  type: "error",
112617
112685
  sessionId,
112618
- error: { code: "internal", message: str2(m.result) || errors.join("\n") || `Turn failed: ${str2(m.subtype)}`, retryable: true }
112686
+ error: { code: "internal", message: str(m.result) || errors.join("\n") || `Turn failed: ${str(m.subtype)}`, retryable: true }
112619
112687
  });
112620
112688
  } else {
112621
112689
  out.push(m.structured_output === void 0 ? { type: "turn_complete", sessionId } : { type: "turn_complete", sessionId, output: m.structured_output });
@@ -112626,9 +112694,9 @@ function resultEvents(m, sessionId) {
112626
112694
  // packages/agent-host/src/adapters/claude/normalize.ts
112627
112695
  function normalizeMessage(msg, sessionId, opts) {
112628
112696
  const m = msg;
112629
- const type = str2(m.type);
112697
+ const type = str(m.type);
112630
112698
  const out = [];
112631
- const parent = str2(m.parent_tool_use_id);
112699
+ const parent = str(m.parent_tool_use_id);
112632
112700
  if (parent && (type === "assistant" || type === "user" || type === "stream_event")) {
112633
112701
  if (type === "stream_event") return out;
112634
112702
  return subagentSteps(sessionId, parent, normalizeMessage({ ...m, parent_tool_use_id: null }, sessionId));
@@ -112782,21 +112850,21 @@ var ClaudeStreamNormalizer = class {
112782
112850
  * falls back to the refusal's explanation, then its category.
112783
112851
  */
112784
112852
  refusalEvents(m) {
112785
- const subtype = str2(m.subtype);
112786
- const explanation = str2(m.api_refusal_explanation);
112853
+ const subtype = str(m.subtype);
112854
+ const explanation = str(m.api_refusal_explanation);
112787
112855
  if (subtype === "model_refusal_no_fallback") {
112788
- const category = str2(m.api_refusal_category);
112789
- this.refusal = str2(m.content).trim() || explanation || `The model declined to answer${category ? ` (${category})` : ""}`;
112856
+ const category = str(m.api_refusal_category);
112857
+ this.refusal = str(m.content).trim() || explanation || `The model declined to answer${category ? ` (${category})` : ""}`;
112790
112858
  return [];
112791
112859
  }
112792
- const from = str2(m.original_model, "the model");
112793
- const to = str2(m.fallback_model);
112794
- if (str2(m.scope) === "local") {
112860
+ const from = str(m.original_model, "the model");
112861
+ const to = str(m.fallback_model);
112862
+ if (str(m.scope) === "local") {
112795
112863
  console.error(`[claude] ${this.sessionId.slice(0, 8)} a subagent's answer came from ${to} after ${from} declined`);
112796
112864
  return [];
112797
112865
  }
112798
112866
  if (!to) return [];
112799
- const text2 = str2(m.content).trim() || `${from} declined to answer, so Claude Code switched this session to ${to}${explanation ? `: ${explanation}` : ""}`;
112867
+ const text2 = str(m.content).trim() || `${from} declined to answer, so Claude Code switched this session to ${to}${explanation ? `: ${explanation}` : ""}`;
112800
112868
  return [
112801
112869
  { type: "notice", sessionId: this.sessionId, level: "warning", text: text2, from: "Claude Code", label: "model switch" },
112802
112870
  { type: "settings_changed", sessionId: this.sessionId, ...this.settings(), model: to, by: "tool" }
@@ -112814,7 +112882,7 @@ var ClaudeStreamNormalizer = class {
112814
112882
  */
112815
112883
  withRequest(m, events2, subagent) {
112816
112884
  const message = m.message ?? {};
112817
- const id3 = str2(message.id);
112885
+ const id3 = str(message.id);
112818
112886
  const usage = message.usage;
112819
112887
  const fresh = !!usage && !(id3 && this.requestsSeen.includes(id3));
112820
112888
  if (!subagent) {
@@ -112830,10 +112898,8 @@ var ClaudeStreamNormalizer = class {
112830
112898
  this.requestsSeen.push(id3);
112831
112899
  if (this.requestsSeen.length > 32) this.requestsSeen.shift();
112832
112900
  const request = {
112833
- inputTokens: tokenCount(usage.input_tokens),
112834
- cacheReadTokens: tokenCount(usage.cache_read_input_tokens),
112835
- cacheCreationTokens: tokenCount(usage.cache_creation_input_tokens),
112836
- ...subagent ? { agent: str2(m.parent_tool_use_id) } : {},
112901
+ ...requestInputTokens(usage),
112902
+ ...subagent ? { agent: str(m.parent_tool_use_id) } : {},
112837
112903
  ...ttlOf(usage.cache_creation)
112838
112904
  };
112839
112905
  if (subagent) {
@@ -112860,7 +112926,7 @@ var ClaudeStreamNormalizer = class {
112860
112926
  * session's plan. The message's `tool_use_result` is read only when it carries one result.
112861
112927
  */
112862
112928
  followTasks(m, events2) {
112863
- const results = (m.message?.content ?? []).filter((b2) => str2(b2?.type) === "tool_result");
112929
+ const results = (m.message?.content ?? []).filter((b2) => str(b2?.type) === "tool_result");
112864
112930
  const record2 = results.length === 1 && typeof m.tool_use_result === "object" && m.tool_use_result !== null ? m.tool_use_result : void 0;
112865
112931
  const out = [];
112866
112932
  for (const e of events2) {
@@ -112888,16 +112954,16 @@ var ClaudeStreamNormalizer = class {
112888
112954
  }
112889
112955
  push(msg) {
112890
112956
  const m = msg;
112891
- const type = str2(m.type);
112892
- const subagent = str2(m.parent_tool_use_id) !== "";
112893
- this.unmapped.note(type === "system" ? `system/${str2(m.subtype)}` : type);
112957
+ const type = str(m.type);
112958
+ const subagent = str(m.parent_tool_use_id) !== "";
112959
+ this.unmapped.note(type === "system" ? `system/${str(m.subtype)}` : type);
112894
112960
  const tasks = this.tasks.push(m);
112895
- if (type === "system" && str2(m.subtype) === "task_notification") {
112896
- const callId = str2(m.tool_use_id);
112961
+ if (type === "system" && str(m.subtype) === "task_notification") {
112962
+ const callId = str(m.tool_use_id);
112897
112963
  if (!this.background.delete(callId)) return tasks;
112898
- const status = str2(m.status, "completed");
112964
+ const status = str(m.status, "completed");
112899
112965
  const usage = m.usage ?? {};
112900
- const output = agentReport(str2(m.summary), agentStats(usage.tool_uses, usage.duration_ms, status));
112966
+ const output = agentReport(str(m.summary), agentStats(usage.tool_uses, usage.duration_ms, status));
112901
112967
  const done = toolResultEvent(this.sessionId, callId, status === "completed", output);
112902
112968
  if (!this.textStreamed && !this.reasoningStreamed) return [...tasks, done];
112903
112969
  this.deferred.push(done);
@@ -112907,7 +112973,7 @@ var ClaudeStreamNormalizer = class {
112907
112973
  const launched = backgroundLaunch(m);
112908
112974
  if (launched) this.background.add(launched);
112909
112975
  }
112910
- if (type === "system" && /^model_refusal_(no_)?fallback$/.test(str2(m.subtype))) return [...tasks, ...this.refusalEvents(m)];
112976
+ if (type === "system" && /^model_refusal_(no_)?fallback$/.test(str(m.subtype))) return [...tasks, ...this.refusalEvents(m)];
112911
112977
  let events2 = [
112912
112978
  ...tasks,
112913
112979
  ...normalizeMessage(msg, this.sessionId, {
@@ -112936,9 +113002,9 @@ var ClaudeStreamNormalizer = class {
112936
113002
  }
112937
113003
  if (type === "stream_event") {
112938
113004
  const e = m.event ?? {};
112939
- if (str2(e.type) === "message_start") this.streamMessageId = str2(e.message?.id) || void 0;
113005
+ if (str(e.type) === "message_start") this.streamMessageId = str(e.message?.id) || void 0;
112940
113006
  }
112941
- const wholeId = type === "assistant" ? str2(m.message?.id) || void 0 : void 0;
113007
+ const wholeId = type === "assistant" ? str(m.message?.id) || void 0 : void 0;
112942
113008
  const messageId = type === "stream_event" ? this.streamMessageId : wholeId;
112943
113009
  if (messageId) events2 = events2.map((e) => e.type === "message_delta" && !e.messageId ? { ...e, messageId } : e);
112944
113010
  events2.push(
@@ -112955,7 +113021,7 @@ var ClaudeStreamNormalizer = class {
112955
113021
  }
112956
113022
  if (type === "result" && this.stopping) {
112957
113023
  this.stopping = false;
112958
- if (str2(m.subtype) === "error_during_execution") events2 = events2.filter((e) => e.type !== "error");
113024
+ if (str(m.subtype) === "error_during_execution") events2 = events2.filter((e) => e.type !== "error");
112959
113025
  }
112960
113026
  if ((type === "assistant" || type === "result") && this.deferred.length > 0) events2.push(...this.deferred.splice(0));
112961
113027
  return events2;
@@ -115291,13 +115357,13 @@ async function lastCompactSummary(threadId, sessionsDir) {
115291
115357
 
115292
115358
  // packages/agent-host/src/adapters/codex/items.ts
115293
115359
  function resultSummary(item) {
115294
- const direct = str2(item.aggregatedOutput) || str2(item.output);
115360
+ const direct = str(item.aggregatedOutput) || str(item.output);
115295
115361
  if (direct) return direct;
115296
- const err = str2(asObj(item.error).message);
115362
+ const err = str(asObj(item.error).message);
115297
115363
  if (err) return err;
115298
115364
  const content = asObj(item.result).content;
115299
115365
  if (Array.isArray(content)) {
115300
- const text2 = content.map((c) => str2(asObj(c).text)).filter(Boolean).join("\n");
115366
+ const text2 = content.map((c) => str(asObj(c).text)).filter(Boolean).join("\n");
115301
115367
  if (text2) return text2;
115302
115368
  }
115303
115369
  const structured = asObj(item.result).structuredContent;
@@ -115311,7 +115377,7 @@ function resultSummary(item) {
115311
115377
  return "";
115312
115378
  }
115313
115379
  function codexItemOk(item) {
115314
- const status = str2(item.status);
115380
+ const status = str(item.status);
115315
115381
  return status !== "failed" && status !== "declined" && status !== "interrupted" && item.success !== false;
115316
115382
  }
115317
115383
  var ITEM_OUTCOME = /* @__PURE__ */ new Set([
@@ -115335,9 +115401,9 @@ function itemInput(item) {
115335
115401
  return Object.fromEntries(Object.entries(item).filter(([k2, v]) => !ITEM_OUTCOME.has(k2) && v !== null && v !== void 0));
115336
115402
  }
115337
115403
  function itemSummary(item) {
115338
- const type = str2(item.type);
115404
+ const type = str(item.type);
115339
115405
  if (type === "commandExecution") {
115340
- const cmd = str2(item.command);
115406
+ const cmd = str(item.command);
115341
115407
  return { tool: "Bash", title: cmd, paths: [] };
115342
115408
  }
115343
115409
  if (type === "fileChange") {
@@ -115345,8 +115411,8 @@ function itemSummary(item) {
115345
115411
  return { tool: "Edit", title: paths.join(", ") || "Edit files", paths };
115346
115412
  }
115347
115413
  if (type === "mcpToolCall") {
115348
- const tool = str2(item.tool) || str2(asObj(item.invocation).tool);
115349
- const server2 = str2(item.server);
115414
+ const tool = str(item.tool) || str(asObj(item.invocation).tool);
115415
+ const server2 = str(item.server);
115350
115416
  if (isCentraluTool({ server: server2, tool }, "centralu_run")) {
115351
115417
  const run4 = centraluRunCommand(jsonObject(item.arguments ?? asObj(item.invocation).arguments));
115352
115418
  if (run4) {
@@ -115354,12 +115420,12 @@ function itemSummary(item) {
115354
115420
  }
115355
115421
  }
115356
115422
  if (isCentraluTool({ server: server2, tool }, "ask_project")) {
115357
- const project2 = str2(jsonObject(item.arguments ?? asObj(item.invocation).arguments).project);
115423
+ const project2 = str(jsonObject(item.arguments ?? asObj(item.invocation).arguments).project);
115358
115424
  const mark2 = centraluMark(server2, tool, {});
115359
115425
  return { tool, title: project2 || tool, paths: [], ...mark2 ? { centralu: mark2.centralu } : {} };
115360
115426
  }
115361
115427
  const args = argsPreview(item.arguments ?? asObj(item.invocation).arguments);
115362
- const name = [server2, tool].filter(Boolean).join(": ") || str2(item.title) || "MCP tool";
115428
+ const name = [server2, tool].filter(Boolean).join(": ") || str(item.title) || "MCP tool";
115363
115429
  const mark = tool ? centraluMark(server2, tool, jsonObject(item.arguments ?? asObj(item.invocation).arguments)) : null;
115364
115430
  return {
115365
115431
  tool: tool || "MCP",
@@ -115369,13 +115435,13 @@ function itemSummary(item) {
115369
115435
  };
115370
115436
  }
115371
115437
  if (type === "webSearch") {
115372
- return { tool: "WebSearch", title: str2(item.query), paths: [] };
115438
+ return { tool: "WebSearch", title: str(item.query), paths: [] };
115373
115439
  }
115374
115440
  if (type === "collabAgentToolCall") {
115375
- const tool = str2(item.tool) || type;
115376
- return { tool, title: firstLine2(str2(item.prompt)) || tool, paths: [] };
115441
+ const tool = str(item.tool) || type;
115442
+ return { tool, title: firstLine2(str(item.prompt)) || tool, paths: [] };
115377
115443
  }
115378
- return { tool: type || "tool", title: str2(item.title) || type, paths: [] };
115444
+ return { tool: type || "tool", title: str(item.title) || type, paths: [] };
115379
115445
  }
115380
115446
  function argsPreview(raw) {
115381
115447
  let value = raw;
@@ -115394,12 +115460,12 @@ function argsPreview(raw) {
115394
115460
  }
115395
115461
  function fileChangesOf(item) {
115396
115462
  const changes = Array.isArray(item.changes) ? item.changes : [];
115397
- return changes.map((c) => ({ path: str2(asObj(c).path), diff: str2(asObj(c).diff), ...changeKindOf(asObj(asObj(c).kind)) }));
115463
+ return changes.map((c) => ({ path: str(asObj(c).path), diff: str(asObj(c).diff), ...changeKindOf(asObj(asObj(c).kind)) }));
115398
115464
  }
115399
115465
  function changeKindOf(kind) {
115400
- const type = str2(kind.type);
115466
+ const type = str(kind.type);
115401
115467
  if (type === "add" || type === "delete") return { change: type };
115402
- if (type === "update") return str2(kind.move_path) ? { change: "move", movePath: str2(kind.move_path) } : { change: "update" };
115468
+ if (type === "update") return str(kind.move_path) ? { change: "move", movePath: str(kind.move_path) } : { change: "update" };
115403
115469
  return {};
115404
115470
  }
115405
115471
 
@@ -115533,10 +115599,10 @@ function warnImpossibleContext(used, window2) {
115533
115599
 
115534
115600
  // packages/agent-host/src/adapters/codex/normalize.ts
115535
115601
  function goalFromCodex(g5) {
115536
- if (str2(g5.status) === "complete") return null;
115602
+ if (str(g5.status) === "complete") return null;
115537
115603
  return {
115538
- objective: str2(g5.objective),
115539
- status: str2(g5.status) || "active",
115604
+ objective: str(g5.objective),
115605
+ status: str(g5.status) || "active",
115540
115606
  ...typeof g5.tokenBudget === "number" ? { tokenBudget: g5.tokenBudget } : {},
115541
115607
  ...typeof g5.tokensUsed === "number" ? { tokensUsed: g5.tokensUsed } : {}
115542
115608
  };
@@ -115547,7 +115613,7 @@ var CompactionMarks = class {
115547
115613
  /** Whether this notification's compaction marker should be emitted */
115548
115614
  admit(n) {
115549
115615
  const kind = n.method === "thread/compacted" ? "notice" : "item";
115550
- const turn = str2(asObj(n.params).turnId);
115616
+ const turn = str(asObj(n.params).turnId);
115551
115617
  const waiting = this.open.get(turn);
115552
115618
  if (waiting && waiting.kind !== kind) {
115553
115619
  if (--waiting.count === 0) this.open.delete(turn);
@@ -115573,7 +115639,7 @@ function normalizeNotification(sessionId, n) {
115573
115639
  * polling it again."
115574
115640
  */
115575
115641
  case "item/agentMessage/delta":
115576
- return [{ type: "message_delta", sessionId, role: "assistant", text: str2(p.delta) || str2(p.text), ...messageIdOf(p.itemId) }];
115642
+ return [{ type: "message_delta", sessionId, role: "assistant", text: str(p.delta) || str(p.text), ...messageIdOf(p.itemId) }];
115577
115643
  /*
115578
115644
  * Reasoning summary (measured for #58). This stream only arrives if model_reasoning_summary
115579
115645
  * is turned on in the thread settings — index.ts turns it on. Measured shape:
@@ -115584,7 +115650,7 @@ function normalizeNotification(sessionId, n) {
115584
115650
  * twice (the same rule as agentMessage).
115585
115651
  */
115586
115652
  case "item/reasoning/summaryTextDelta": {
115587
- const text2 = str2(p.delta);
115653
+ const text2 = str(p.delta);
115588
115654
  return text2 ? [{ type: "reasoning_delta", sessionId, text: text2 }] : [];
115589
115655
  }
115590
115656
  case "item/reasoning/summaryPartAdded":
@@ -115607,25 +115673,25 @@ function normalizeNotification(sessionId, n) {
115607
115673
  * the assumption that summing the deltas equals the full output does not hold.)
115608
115674
  */
115609
115675
  case "item/commandExecution/outputDelta": {
115610
- const text2 = str2(p.delta);
115611
- return text2 ? [{ type: "tool_output_delta", sessionId, callId: str2(p.itemId), text: text2 }] : [];
115676
+ const text2 = str(p.delta);
115677
+ return text2 ? [{ type: "tool_output_delta", sessionId, callId: str(p.itemId), text: text2 }] : [];
115612
115678
  }
115613
115679
  case "item/started": {
115614
115680
  const item = asObj(p.item);
115615
- const type = str2(item.type);
115681
+ const type = str(item.type);
115616
115682
  if (type === "userMessage" || type === "reasoning" || type === "agentMessage") return [];
115617
115683
  if (type === "contextCompaction") return [{ type: "activity", sessionId, activity: "compacting" }];
115618
115684
  if (type === "enteredReviewMode") return [{ type: "activity", sessionId, activity: "reviewing" }];
115619
115685
  if (type === "exitedReviewMode") return [{ type: "activity", sessionId, activity: null }];
115620
115686
  if (type === "imageView") return [];
115621
115687
  const s = itemSummary(item);
115622
- return [{ type: "tool_call", sessionId, callId: str2(item.id), summary: s, input: itemInput(item) }];
115688
+ return [{ type: "tool_call", sessionId, callId: str(item.id), summary: s, input: itemInput(item) }];
115623
115689
  }
115624
115690
  case "item/completed": {
115625
115691
  const item = asObj(p.item);
115626
- const type = str2(item.type);
115692
+ const type = str(item.type);
115627
115693
  if (type === "agentMessage") {
115628
- return str2(item.text) ? [{ type: "message_delta", sessionId, role: "assistant", text: "", ...messageIdOf(item.id) }] : [];
115694
+ return str(item.text) ? [{ type: "message_delta", sessionId, role: "assistant", text: "", ...messageIdOf(item.id) }] : [];
115629
115695
  }
115630
115696
  if (type === "userMessage" || type === "reasoning") return [];
115631
115697
  if (type === "contextCompaction") {
@@ -115637,16 +115703,16 @@ function normalizeNotification(sessionId, n) {
115637
115703
  if (type === "exitedReviewMode") return [{ type: "activity", sessionId, activity: null }];
115638
115704
  if (type === "enteredReviewMode") return [];
115639
115705
  if (type === "imageView") {
115640
- const path2 = str2(item.path);
115706
+ const path2 = str(item.path);
115641
115707
  return path2 ? [{ type: "message_image", sessionId, mime: "", data: "", path: path2 }] : [];
115642
115708
  }
115643
115709
  const s = itemSummary(item);
115644
- const ending = str2(item.status) === "declined" ? "declined" : str2(item.status) === "interrupted" ? "interrupted" : void 0;
115645
- const out = [toolResultEvent(sessionId, str2(item.id), codexItemOk(item), resultSummary(item), ending)];
115710
+ const ending = str(item.status) === "declined" ? "declined" : str(item.status) === "interrupted" ? "interrupted" : void 0;
115711
+ const out = [toolResultEvent(sessionId, str(item.id), codexItemOk(item), resultSummary(item), ending)];
115646
115712
  if (type === "mcpToolCall") out.push(...mcpImageEvents(sessionId, asObj(item.result).content));
115647
115713
  const moved = type === "fileChange" ? fileChangesOf(item).flatMap((c) => c.movePath ? [c.movePath] : []) : [];
115648
115714
  const paths = [...s.paths, ...moved];
115649
- if (paths.length > 0 && str2(item.status) !== "declined") out.push({ type: "files_touched", sessionId, paths });
115715
+ if (paths.length > 0 && str(item.status) !== "declined") out.push({ type: "files_touched", sessionId, paths });
115650
115716
  return out;
115651
115717
  }
115652
115718
  /*
@@ -115673,16 +115739,16 @@ function normalizeNotification(sessionId, n) {
115673
115739
  case "turn/completed": {
115674
115740
  const turn = asObj(p.turn);
115675
115741
  const failure3 = asObj(turn.error);
115676
- if (str2(turn.status) === "interrupted" && !failure3.message) return [{ type: "state_change", sessionId, state: "waiting_input", reason: "interrupted" }];
115677
- if (str2(turn.status) !== "failed" && !failure3.message) return [{ type: "turn_complete", sessionId }];
115678
- const detail = str2(failure3.additionalDetails);
115742
+ if (str(turn.status) === "interrupted" && !failure3.message) return [{ type: "state_change", sessionId, state: "waiting_input", reason: "interrupted" }];
115743
+ if (str(turn.status) !== "failed" && !failure3.message) return [{ type: "turn_complete", sessionId }];
115744
+ const detail = str(failure3.additionalDetails);
115679
115745
  return [
115680
115746
  {
115681
115747
  type: "error",
115682
115748
  sessionId,
115683
115749
  error: {
115684
115750
  code: "internal",
115685
- message: [str2(failure3.message) || "The turn failed", detail].filter(Boolean).join("\n"),
115751
+ message: [str(failure3.message) || "The turn failed", detail].filter(Boolean).join("\n"),
115686
115752
  retryable: true
115687
115753
  }
115688
115754
  }
@@ -115707,7 +115773,7 @@ function normalizeNotification(sessionId, n) {
115707
115773
  */
115708
115774
  case "account/rateLimits/updated": {
115709
115775
  const snapshot2 = asObj(p.rateLimits);
115710
- const reached = str2(snapshot2.rateLimitReachedType) !== "" || snapshot2.spendControlReached === true;
115776
+ const reached = str(snapshot2.rateLimitReachedType) !== "" || snapshot2.spendControlReached === true;
115711
115777
  if (!reached) return [];
115712
115778
  const primary = asObj(snapshot2.primary);
115713
115779
  const resetsAt = finite(primary.resetsAt);
@@ -115722,7 +115788,7 @@ function normalizeNotification(sessionId, n) {
115722
115788
  ];
115723
115789
  }
115724
115790
  case "thread/name/updated":
115725
- return [{ type: "session_title", sessionId, title: str2(p.name), auto: true }];
115791
+ return [{ type: "session_title", sessionId, title: str(p.name), auto: true }];
115726
115792
  // Deprecated (0.160.0's binding) and not sent in any measured run — kept for a CLI that still does (#303)
115727
115793
  case "thread/compacted":
115728
115794
  return [{ type: "compaction", sessionId, failed: false }];
@@ -115749,17 +115815,17 @@ function normalizeNotification(sessionId, n) {
115749
115815
  * (`noticeWords`, #342).
115750
115816
  */
115751
115817
  case "warning": {
115752
- const text2 = str2(p.message).trim();
115818
+ const text2 = str(p.message).trim();
115753
115819
  return text2 ? [{ type: "notice", sessionId, level: "warning", text: text2, oncePerSession: true, ...noticeWords("warning", text2) }] : [];
115754
115820
  }
115755
115821
  case "configWarning":
115756
115822
  case "deprecationNotice": {
115757
- const text2 = [str2(p.summary).trim(), str2(p.details).trim()].filter(Boolean).join("\n");
115823
+ const text2 = [str(p.summary).trim(), str(p.details).trim()].filter(Boolean).join("\n");
115758
115824
  return text2 ? [{ type: "notice", sessionId, level: "warning", text: text2, oncePerSession: true, ...noticeWords(n.method, text2) }] : [];
115759
115825
  }
115760
115826
  // The auto-review guardian's warning about an action (generated/v2/GuardianWarningNotification.ts); not exercised
115761
115827
  case "guardianWarning": {
115762
- const text2 = str2(p.message).trim();
115828
+ const text2 = str(p.message).trim();
115763
115829
  return text2 ? [{ type: "notice", sessionId, level: "warning", text: text2, ...noticeWords("guardianWarning", text2) }] : [];
115764
115830
  }
115765
115831
  /*
@@ -115769,10 +115835,10 @@ function normalizeNotification(sessionId, n) {
115769
115835
  * conversation and leaves the model the person picked alone.
115770
115836
  */
115771
115837
  case "model/rerouted": {
115772
- const to = str2(p.toModel);
115838
+ const to = str(p.toModel);
115773
115839
  if (!to) return [];
115774
- const reason = str2(p.reason) === "highRiskCyberActivity" ? "it was flagged as high-risk cyber activity" : str2(p.reason);
115775
- const text2 = `Codex answered this turn with ${to} instead of ${str2(p.fromModel) || "the selected model"}${reason ? ` because ${reason}` : ""}`;
115840
+ const reason = str(p.reason) === "highRiskCyberActivity" ? "it was flagged as high-risk cyber activity" : str(p.reason);
115841
+ const text2 = `Codex answered this turn with ${to} instead of ${str(p.fromModel) || "the selected model"}${reason ? ` because ${reason}` : ""}`;
115776
115842
  return [{ type: "notice", sessionId, level: "warning", text: text2, ...noticeWords("model/rerouted", text2) }];
115777
115843
  }
115778
115844
  /*
@@ -115783,11 +115849,11 @@ function normalizeNotification(sessionId, n) {
115783
115849
  * simply had no such tools. The adapter keeps one line per server until it starts again (index.ts).
115784
115850
  */
115785
115851
  case "mcpServer/startupStatus/updated": {
115786
- if (str2(p.status) !== "failed") return [];
115787
- const name = str2(p.name) || "an MCP server";
115788
- const reauth = str2(p.failureReason) === "reauthenticationRequired" ? " (it needs you to sign in again)" : "";
115789
- const text2 = `${str2(p.error).trim() || `MCP server \`${name}\` failed to start`}${reauth}`;
115790
- return [{ type: "notice", sessionId, level: "warning", text: text2, ...noticeWords("mcpStartup", text2, str2(p.name)) }];
115852
+ if (str(p.status) !== "failed") return [];
115853
+ const name = str(p.name) || "an MCP server";
115854
+ const reauth = str(p.failureReason) === "reauthenticationRequired" ? " (it needs you to sign in again)" : "";
115855
+ const text2 = `${str(p.error).trim() || `MCP server \`${name}\` failed to start`}${reauth}`;
115856
+ return [{ type: "notice", sessionId, level: "warning", text: text2, ...noticeWords("mcpStartup", text2, str(p.name)) }];
115791
115857
  }
115792
115858
  /*
115793
115859
  * The `error` notification has the shape `{ error, willRetry, threadId, turnId }` (generated
@@ -115812,13 +115878,13 @@ function normalizeNotification(sessionId, n) {
115812
115878
  * and sent the last two only.
115813
115879
  */
115814
115880
  case "error": {
115815
- const message = str2(asObj(p.error).message) || str2(p.message) || "Unknown error";
115881
+ const message = str(asObj(p.error).message) || str(p.message) || "Unknown error";
115816
115882
  if (p.willRetry === true) {
115817
- const why = str2(asObj(p.error).additionalDetails);
115883
+ const why = str(asObj(p.error).additionalDetails);
115818
115884
  console.error(`[codex] ${sessionId.slice(0, 8)} retrying after: ${message}${why ? ` (${why})` : ""}`);
115819
115885
  return [{ type: "activity", sessionId, activity: "retrying" }];
115820
115886
  }
115821
- if (str2(p.turnId)) return [];
115887
+ if (str(p.turnId)) return [];
115822
115888
  return [{ type: "error", sessionId, error: { code: "internal", message, retryable: true } }];
115823
115889
  }
115824
115890
  default:
@@ -116103,13 +116169,13 @@ function threadIdOf(res) {
116103
116169
  function childSteps(sessionId, parentCallId, n) {
116104
116170
  if (n.method !== "item/started" && n.method !== "item/completed") return [];
116105
116171
  const item = asObj(asObj(n.params).item);
116106
- const type = str2(item.type);
116172
+ const type = str(item.type);
116107
116173
  if (type === "agentMessage") {
116108
- const text2 = n.method === "item/completed" ? str2(item.text) : "";
116174
+ const text2 = n.method === "item/completed" ? str(item.text) : "";
116109
116175
  return text2 ? subagentSteps(sessionId, parentCallId, [{ type: "message_delta", sessionId, role: "assistant", text: text2, ...messageIdOf(item.id) }]) : [];
116110
116176
  }
116111
116177
  if (type === "reasoning") {
116112
- const parts = n.method === "item/completed" && Array.isArray(item.summary) ? item.summary.map((x) => str2(x)).filter(Boolean) : [];
116178
+ const parts = n.method === "item/completed" && Array.isArray(item.summary) ? item.summary.map((x) => str(x)).filter(Boolean) : [];
116113
116179
  return parts.length ? subagentSteps(sessionId, parentCallId, [{ type: "reasoning_delta", sessionId, text: parts.join("\n\n") }]) : [];
116114
116180
  }
116115
116181
  return subagentSteps(sessionId, parentCallId, normalizeNotification(sessionId, n));
@@ -116117,18 +116183,20 @@ function childSteps(sessionId, parentCallId, n) {
116117
116183
  function launchedThreads(n) {
116118
116184
  if (n.method !== "item/completed") return [];
116119
116185
  const item = asObj(asObj(n.params).item);
116120
- if (str2(item.type) !== "collabAgentToolCall" || str2(item.tool) !== "spawnAgent" || !codexItemOk(item)) return [];
116186
+ if (str(item.type) !== "collabAgentToolCall" || str(item.tool) !== "spawnAgent" || !codexItemOk(item)) return [];
116121
116187
  return (Array.isArray(item.receiverThreadIds) ? item.receiverThreadIds : []).filter((t) => typeof t === "string" && t !== "");
116122
116188
  }
116123
116189
  var CodexChildTracker = class {
116124
116190
  constructor(sessionId) {
116125
116191
  this.sessionId = sessionId;
116192
+ this.events = new BackgroundEvents(sessionId);
116126
116193
  }
116127
116194
  sessionId;
116128
116195
  threads = /* @__PURE__ */ new Map();
116129
116196
  /** Linked children: thread to its launch call and description. Only these are listed. */
116130
116197
  linked = /* @__PURE__ */ new Map();
116131
- lastLive = "[]";
116198
+ /** The events, by the rule both adapters share (`BackgroundEvents`): a repeat of the last list is not sent */
116199
+ events;
116132
116200
  /**
116133
116201
  * Launch cards held open while the children they started run (#843). A `spawnAgent` item completes the moment the
116134
116202
  * child starts (measured: its `item/completed` names the child's thread before the child has done anything), so its
@@ -116169,7 +116237,7 @@ var CodexChildTracker = class {
116169
116237
  const t = this.threads.get(thread) ?? { active: false, turnId: null };
116170
116238
  this.threads.set(thread, t);
116171
116239
  if (n.method === "thread/status/changed") {
116172
- const type = str2(asObj(p.status).type);
116240
+ const type = str(asObj(p.status).type);
116173
116241
  if (type === "active") t.active = true;
116174
116242
  else if (type === "systemError") {
116175
116243
  const was = t.active;
@@ -116181,15 +116249,15 @@ var CodexChildTracker = class {
116181
116249
  }
116182
116250
  if (n.method === "turn/started") {
116183
116251
  t.active = true;
116184
- t.turnId = str2(asObj(p.turn).id) || t.turnId;
116252
+ t.turnId = str(asObj(p.turn).id) || t.turnId;
116185
116253
  return this.changed();
116186
116254
  }
116187
116255
  if (n.method === "turn/completed") {
116188
- const raw = str2(asObj(p.turn).status);
116256
+ const raw = str(asObj(p.turn).status);
116189
116257
  t.active = false;
116190
116258
  t.turnId = null;
116191
116259
  const status = raw === "interrupted" ? "stopped" : raw === "failed" ? "failed" : "completed";
116192
- const message = str2(asObj(asObj(p.turn).error).message);
116260
+ const message = str(asObj(asObj(p.turn).error).message);
116193
116261
  return [...this.changed([this.ended(thread, status, message || void 0)]), ...this.finished(thread)];
116194
116262
  }
116195
116263
  return [];
@@ -116212,7 +116280,7 @@ var CodexChildTracker = class {
116212
116280
  }
116213
116281
  ended(thread, status, summary) {
116214
116282
  const task = this.task(thread);
116215
- return task ? { ...task, status, ...summary ? { summary } : {} } : null;
116283
+ return task ? { ...task, status, ...endedSummary(summary) } : null;
116216
116284
  }
116217
116285
  task(thread) {
116218
116286
  const link = this.linked.get(thread);
@@ -116238,12 +116306,10 @@ var CodexChildTracker = class {
116238
116306
  }
116239
116307
  /** The event when the live set or an ending moved; nothing when neither did. */
116240
116308
  changed(ended = []) {
116241
- const live2 = this.live();
116242
- const done = ended.filter((t) => t !== null);
116243
- const key = JSON.stringify(live2);
116244
- if (key === this.lastLive && done.length === 0) return [];
116245
- this.lastLive = key;
116246
- return [{ type: "background_tasks", sessionId: this.sessionId, live: live2, ...done.length ? { ended: done } : {} }];
116309
+ return this.events.event(
116310
+ this.live(),
116311
+ ended.filter((t) => t !== null)
116312
+ );
116247
116313
  }
116248
116314
  };
116249
116315
 
@@ -116337,20 +116403,20 @@ var CODEX_KNOWN_NOTIFICATIONS = /* @__PURE__ */ new Set([
116337
116403
  function threadSettingsOf(res) {
116338
116404
  if (!res) return null;
116339
116405
  const thread = asObj(res.thread);
116340
- const model = str2(res.model) || str2(thread.model);
116406
+ const model = str(res.model) || str(thread.model);
116341
116407
  if (!model) return null;
116342
116408
  return {
116343
116409
  model,
116344
- effort: str2(res.reasoningEffort) || str2(thread.reasoningEffort) || null,
116345
- serviceTier: str2(res.serviceTier) || null
116410
+ effort: str(res.reasoningEffort) || str(thread.reasoningEffort) || null,
116411
+ serviceTier: str(res.serviceTier) || null
116346
116412
  };
116347
116413
  }
116348
116414
  function threadSettingsChanged(sessionId, before, params, launched) {
116349
116415
  const s = asObj(asObj(params).threadSettings);
116350
116416
  const next = {
116351
- model: str2(s.model) || null,
116352
- effort: str2(s.effort) || null,
116353
- serviceTier: str2(s.serviceTier) || null
116417
+ model: str(s.model) || null,
116418
+ effort: str(s.effort) || null,
116419
+ serviceTier: str(s.serviceTier) || null
116354
116420
  };
116355
116421
  if (!next.model) return { next: before, events: [] };
116356
116422
  if (!before) return { next, events: [] };
@@ -116410,18 +116476,18 @@ function approvalDetailFrom(method, params, itemChanges) {
116410
116476
  const net2 = asObj(params.networkApprovalContext);
116411
116477
  return {
116412
116478
  kind: "command",
116413
- command: str2(item.command) || str2(params.command),
116414
- cwd: str2(item.cwd) || str2(params.cwd),
116415
- ...str2(params.reason) ? { reason: str2(params.reason) } : {},
116416
- ...str2(net2.host) ? { network: { host: str2(net2.host), protocol: str2(net2.protocol) } } : {},
116417
- ...str2(params.kind) === "writeStdin" ? { stdin: true } : {}
116479
+ command: str(item.command) || str(params.command),
116480
+ cwd: str(item.cwd) || str(params.cwd),
116481
+ ...str(params.reason) ? { reason: str(params.reason) } : {},
116482
+ ...str(net2.host) ? { network: { host: str(net2.host), protocol: str(net2.protocol) } } : {},
116483
+ ...str(params.kind) === "writeStdin" ? { stdin: true } : {}
116418
116484
  };
116419
116485
  }
116420
116486
  if (method === "item/fileChange/requestApproval") return fileEditDetail(itemChanges ?? []);
116421
116487
  if (method === "applyPatchApproval") {
116422
116488
  const changes = Object.entries(asObj(params.fileChanges)).map(([path2, c]) => ({
116423
116489
  path: path2,
116424
- diff: str2(asObj(c).unified_diff) || str2(asObj(c).content),
116490
+ diff: str(asObj(c).unified_diff) || str(asObj(c).content),
116425
116491
  // generated FileChange: the same `type` (add, delete, update with move_path) as the v2 kind
116426
116492
  ...changeKindOf(asObj(c))
116427
116493
  }));
@@ -116565,7 +116631,7 @@ function approvalKindOf(meta3) {
116565
116631
  return typeof kind === "string" ? kind : null;
116566
116632
  }
116567
116633
  function appApprovalDetail(server2, message, meta3) {
116568
- const m = typeof meta3 === "object" && meta3 !== null ? meta3 : {};
116634
+ const m = asObj(meta3);
116569
116635
  const title = typeof m.tool_title === "string" && m.tool_title ? m.tool_title : typeof message === "string" ? message : "";
116570
116636
  const params = m.tool_params === void 0 ? "" : ` ${JSON.stringify(m.tool_params).slice(0, 1e3)}`;
116571
116637
  return { kind: "other", raw: `${server2} \xB7 ${title}${params}` };
@@ -117461,7 +117527,7 @@ var CodexSession = class {
117461
117527
  for (const e of normalizeNotification(this.sessionId, n)) {
117462
117528
  if (e.type === "error" && this.inputReceipts.size) this.interrupt(new Error(e.error.message));
117463
117529
  if (e.type === "message_image" && !e.data && e.path) {
117464
- void imageEventFromDisk(this.sessionId, e.path).then((filled3) => this.emit(filled3));
117530
+ void imageEventFromDisk(this.sessionId, e.path).then((filled2) => this.emit(filled2));
117465
117531
  continue;
117466
117532
  }
117467
117533
  if (e.type === "compaction" && !this.compactions.admit(n)) continue;
@@ -118291,6 +118357,7 @@ var HandoffMarkers = class {
118291
118357
  };
118292
118358
 
118293
118359
  // packages/agent-host/src/dev-services/store/settings.ts
118360
+ var SESSION_SETTING_OF = `length(key) > length(@sessionId) + 1 AND substr(key, -length(@sessionId) - 1) = ':' || @sessionId`;
118294
118361
  function flagSetting(settings, key, byDefault) {
118295
118362
  return {
118296
118363
  read: () => {
@@ -118691,13 +118758,26 @@ var MessageRecords = class {
118691
118758
  import Database from "better-sqlite3";
118692
118759
  import { existsSync as existsSync16 } from "node:fs";
118693
118760
 
118694
- // packages/agent-host/src/dev-services/store/migrations/context.ts
118761
+ // packages/agent-host/src/dev-services/store/store-keys.ts
118695
118762
  var APP_SETTINGS_DDL = `
118696
118763
  CREATE TABLE IF NOT EXISTS app_settings (
118697
118764
  key TEXT PRIMARY KEY,
118698
118765
  value TEXT NOT NULL
118699
118766
  );
118700
118767
  `;
118768
+ function readStoreKey(db, key) {
118769
+ const table = db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_settings'`).get();
118770
+ if (!table) return null;
118771
+ const row = db.prepare(`SELECT value FROM app_settings WHERE key = ?`).get(key);
118772
+ return row?.value ?? null;
118773
+ }
118774
+ function writeStoreKey(db, key, value) {
118775
+ db.exec(APP_SETTINGS_DDL);
118776
+ if (value === null) db.prepare(`DELETE FROM app_settings WHERE key = ?`).run(key);
118777
+ else db.prepare(`INSERT INTO app_settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(key, value);
118778
+ }
118779
+
118780
+ // packages/agent-host/src/dev-services/store/migrations/context.ts
118701
118781
  var MigrationRange = class {
118702
118782
  constructor(host) {
118703
118783
  this.host = host;
@@ -118753,15 +118833,12 @@ var ReaderGate = class {
118753
118833
  }
118754
118834
  /** null when nothing is recorded yet: a new store, or one last opened by a host from before #292 */
118755
118835
  storedMinReader() {
118756
- const table = this.db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_settings'`).get();
118757
- if (!table) return null;
118758
- const row = this.db.prepare(`SELECT value FROM app_settings WHERE key = ?`).get(MIN_READER_KEY);
118759
- const n = row ? Number(row.value) : NaN;
118836
+ const raw = readStoreKey(this.db, MIN_READER_KEY);
118837
+ const n = raw !== null ? Number(raw) : NaN;
118760
118838
  return Number.isInteger(n) && n >= 0 ? n : null;
118761
118839
  }
118762
118840
  writeMinReader(version2) {
118763
- this.db.exec(APP_SETTINGS_DDL);
118764
- this.db.prepare(`INSERT INTO app_settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(MIN_READER_KEY, String(version2));
118841
+ writeStoreKey(this.db, MIN_READER_KEY, String(version2));
118765
118842
  }
118766
118843
  };
118767
118844
 
@@ -118776,8 +118853,7 @@ var OwedVacuum = class {
118776
118853
  db;
118777
118854
  /** A `VACUUM` a step queued has not run yet: the host was stopped during it (#396) */
118778
118855
  get vacuumOwed() {
118779
- const table = this.db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_settings'`).get();
118780
- return !!table && !!this.db.prepare(`SELECT 1 FROM app_settings WHERE key = ?`).get(VACUUM_OWED_KEY);
118856
+ return readStoreKey(this.db, VACUUM_OWED_KEY) !== null;
118781
118857
  }
118782
118858
  /**
118783
118859
  * Runs the owed `VACUUM` and deletes the record of it. `why`, when given, is said in host.log on success.
@@ -118798,7 +118874,7 @@ var OwedVacuum = class {
118798
118874
  console.error(`[store] could not vacuum; ${mb(free)} stay free in the file: ${err.message}`);
118799
118875
  return null;
118800
118876
  } finally {
118801
- this.db.prepare(`DELETE FROM app_settings WHERE key = ?`).run(VACUUM_OWED_KEY);
118877
+ writeStoreKey(this.db, VACUUM_OWED_KEY, null);
118802
118878
  }
118803
118879
  const done = { before, after: size(), ms: Date.now() - t02 };
118804
118880
  if (why) console.error(`[store] vacuumed ${mb(done.before)} -> ${mb(done.after)} (${done.ms}ms): ${why}`);
@@ -118925,8 +119001,7 @@ var MigrationRunner = class extends ReaderGate {
118925
119001
  * what the vacuum did when it ran.
118926
119002
  */
118927
119003
  vacuumAfterStep(report) {
118928
- this.db.exec(APP_SETTINGS_DDL);
118929
- this.db.prepare(`INSERT INTO app_settings (key, value) VALUES (?, '1') ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(VACUUM_OWED_KEY);
119004
+ writeStoreKey(this.db, VACUUM_OWED_KEY, "1");
118930
119005
  this.afterStep(() => {
118931
119006
  const done = this.runOwedVacuum();
118932
119007
  if (done) report?.(done);
@@ -119004,18 +119079,10 @@ var MigrationRunner = class extends ReaderGate {
119004
119079
  }
119005
119080
  }
119006
119081
  storedDeferred() {
119007
- const table = this.db.prepare(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'app_settings'`).get();
119008
- if (!table) return [];
119009
- const row = this.db.prepare(`SELECT value FROM app_settings WHERE key = ?`).get(DEFERRED_KEY);
119010
- return readJsonList(row?.value, external_exports.number().int().positive());
119082
+ return readJsonList(readStoreKey(this.db, DEFERRED_KEY), external_exports.number().int().positive());
119011
119083
  }
119012
119084
  writeDeferred(steps) {
119013
- this.db.exec(APP_SETTINGS_DDL);
119014
- if (steps.length === 0) {
119015
- this.db.prepare(`DELETE FROM app_settings WHERE key = ?`).run(DEFERRED_KEY);
119016
- return;
119017
- }
119018
- this.db.prepare(`INSERT INTO app_settings (key, value) VALUES (?, ?) ON CONFLICT(key) DO UPDATE SET value = excluded.value`).run(DEFERRED_KEY, JSON.stringify([...steps].sort((a, b2) => a - b2)));
119085
+ writeStoreKey(this.db, DEFERRED_KEY, steps.length === 0 ? null : JSON.stringify([...steps].sort((a, b2) => a - b2)));
119019
119086
  }
119020
119087
  };
119021
119088
 
@@ -120388,6 +120455,22 @@ var StepsV55 = class extends MigrationRange {
120388
120455
  END`
120389
120456
  ).run({ mark: ASK_PROJECT_MARK });
120390
120457
  }
120458
+ },
120459
+ {
120460
+ to: 56,
120461
+ // Drops `usage_facts`: an older schema.sql recreates it empty, and builds up to beta.10 still ran DELETE FROM it
120462
+ breaksOlderReaders: true,
120463
+ /**
120464
+ * The unused usage aggregate goes (#423). It was planned for the first milestone and never built: no build ever
120465
+ * wrote a row. Deleting a project was the last statement that named it, and #420 removed that; the table has
120466
+ * been left alone by every release since, which is the "one release later" that §5.1 rule 2 asks for.
120467
+ *
120468
+ * `schema.sql` no longer creates it either, so a new store and a migrated one end with the same tables. Nothing
120469
+ * is lost: there is no row to keep. `IF EXISTS` because a fresh store never had the table.
120470
+ */
120471
+ run: () => {
120472
+ this.db.exec(`DROP TABLE IF EXISTS usage_facts`);
120473
+ }
120391
120474
  }
120392
120475
  ];
120393
120476
  }
@@ -120875,14 +120958,13 @@ var SessionRecords = class {
120875
120958
  // packages/agent-host/src/dev-services/store/trash.ts
120876
120959
  function parseTrashRecord(json2) {
120877
120960
  const r = asObj(parseJson(json2));
120878
- const str3 = (v) => typeof v === "string" && v ? v : null;
120879
120961
  return {
120880
- projectId: str3(r.projectId),
120881
- projectName: str3(r.projectName),
120882
- projectPath: str3(r.projectPath),
120962
+ projectId: filled(r.projectId),
120963
+ projectName: filled(r.projectName),
120964
+ projectPath: filled(r.projectPath),
120883
120965
  removeExternal: r.removeExternal === true,
120884
120966
  removeWorktree: r.removeWorktree === true,
120885
- ...r.recovery && typeof r.recovery === "object" && typeof r.recovery.snapshot === "string" && typeof r.recovery.tip === "string" && typeof r.recovery.changedFiles === "number" && typeof r.recovery.commits === "number" ? { recovery: r.recovery } : {}
120967
+ ...isObj(r.recovery) && typeof r.recovery.snapshot === "string" && typeof r.recovery.tip === "string" && typeof r.recovery.changedFiles === "number" && typeof r.recovery.commits === "number" ? { recovery: r.recovery } : {}
120886
120968
  };
120887
120969
  }
120888
120970
  var DELETE_CHUNK = 250;
@@ -120964,6 +121046,10 @@ var TrashRecords = class {
120964
121046
  * the whole took 4.1s, with the event loop turning 231 times). The rows that are not messages, and the session row, go in the same
120965
121047
  * transaction as the last chunk, so a purge cut short leaves the session in the trash with fewer messages, to be
120966
121048
  * purged again, and never messages without a session.
121049
+ *
121050
+ * The settings kept per session go too, all of them by their shape (`SESSION_SETTING_OF`) rather than by name: the
121051
+ * purge used to name two of them, and every key added since stayed behind for good (a process's tool prefix and launch
121052
+ * settings, its fresh-start mark, its last import, a paused report).
120967
121053
  */
120968
121054
  async purgeSession(sessionId, chunk = DELETE_CHUNK) {
120969
121055
  if (!this.isTrashed(sessionId)) return false;
@@ -120990,8 +121076,7 @@ var TrashRecords = class {
120990
121076
  this.db.prepare(`DELETE FROM agent_start_requests WHERE caller_session_id = ?`).run(sessionId);
120991
121077
  this.db.prepare(`DELETE FROM delegated_turns WHERE session_id = ? OR caller_session_id = ?`).run(sessionId, sessionId);
120992
121078
  this.db.prepare(`DELETE FROM queued_requests WHERE session_id = ? OR caller_session_id = ?`).run(sessionId, sessionId);
120993
- this.db.prepare(`DELETE FROM app_settings WHERE key = ?`).run(`agent_depth:${sessionId}`);
120994
- this.db.prepare(`DELETE FROM app_settings WHERE key = ?`).run(`hub_ask_depth:${sessionId}`);
121079
+ this.db.prepare(`DELETE FROM app_settings WHERE ${SESSION_SETTING_OF}`).run({ sessionId });
120995
121080
  this.db.prepare(`DELETE FROM sessions WHERE id = ? AND deleted_at IS NOT NULL`).run(sessionId);
120996
121081
  return true;
120997
121082
  });
@@ -121063,8 +121148,7 @@ var TrashRecords = class {
121063
121148
  * of a session caught here are dropped by hand — a session in the trash must not turn up in a search.
121064
121149
  *
121065
121150
  * The rows that belong to the project go with it as before: project-scope rules, the answers given to its apps, and
121066
- * the app runs and commit links that point at no session still here. (`usage_facts` is not touched: no build ever
121067
- * wrote a row to it, and this build is the first that leaves it alone, so a later step can drop it; schema.sql.) Rows that point at a session in the trash stay with that session until it is
121151
+ * the app runs and commit links that point at no session still here. Rows that point at a session in the trash stay with that session until it is
121068
121152
  * deleted for good: its own rules, its commit links, the app runs it started or ran in. A restore that registers
121069
121153
  * the folder again under the same id finds them where they were.
121070
121154
  */
@@ -121211,22 +121295,6 @@ var Store = class extends MigrationRunner {
121211
121295
  this.checkpoint();
121212
121296
  this.db.close();
121213
121297
  }
121214
- /*
121215
- * Everything below only passes the call on to the module named in its heading. They are the last pass-throughs: #1099,
121216
- * in the merge queue, still calls them on `Store` and hands the whole store to `labelOf` (#428), and they go once it
121217
- * lands. New code names the module.
121218
- */
121219
- // ── MessageRecords (store/messages.ts) ──
121220
- loadMessages(sessionId, limit, beforeSeq, opts) {
121221
- return this.messages.loadMessages(sessionId, limit, beforeSeq, opts);
121222
- }
121223
- loadMessagesFrom(sessionId, afterSeq, limit, opts) {
121224
- return this.messages.loadMessagesFrom(sessionId, afterSeq, limit, opts);
121225
- }
121226
- // ── SettingsRecords (store/settings.ts) ──
121227
- appSetting(key) {
121228
- return this.settings.appSetting(key);
121229
- }
121230
121298
  };
121231
121299
  var WAL_SIZE_LIMIT = 64 * 1024 * 1024;
121232
121300
 
@@ -121314,6 +121382,16 @@ function appSettingRests(settings) {
121314
121382
 
121315
121383
  // packages/agent-host/src/dev-services/git-pr.ts
121316
121384
  var OK2 = { timeout: 1e4, maxBuffer: 32 * 1024 * 1024 };
121385
+ var GH_STDERR_KEEP = 4096;
121386
+ var ghFailuresSaid = /* @__PURE__ */ new Set();
121387
+ function noteGhFailure(branch, e) {
121388
+ const lines = String(e.stderr ?? "").split(/\r?\n/).map((l) => l.trim()).filter(Boolean);
121389
+ if (!lines.length || lines.some((l) => /no pull requests? found/i.test(l))) return;
121390
+ const why = lines[0].slice(0, 300);
121391
+ if (ghFailuresSaid.has(why)) return;
121392
+ ghFailuresSaid.add(why);
121393
+ console.error(`[git] gh could not read the pull request of ${branch}: ${why}`);
121394
+ }
121317
121395
  async function gitBranchPr(projectCwd, branch, signal, timeoutMs = OK2.timeout) {
121318
121396
  const { child } = spawnGrouped(programPath("gh"), ["pr", "view", branch, "--json", "number,state,url,headRefOid"], {
121319
121397
  cwd: projectCwd,
@@ -121325,10 +121403,13 @@ async function gitBranchPr(projectCwd, branch, signal, timeoutMs = OK2.timeout)
121325
121403
  outBytes += chunk.length;
121326
121404
  if (outBytes <= OK2.maxBuffer) out.push(chunk);
121327
121405
  });
121328
- child.stderr.resume();
121406
+ let err = "";
121407
+ child.stderr.on("data", (chunk) => {
121408
+ err = (err + chunk.toString("utf8")).slice(-GH_STDERR_KEEP);
121409
+ });
121329
121410
  const run4 = new Promise((resolve18, reject) => {
121330
121411
  child.once("error", reject);
121331
- child.once("close", (code2) => code2 === 0 ? resolve18(Buffer.concat(out).toString("utf8")) : reject(Object.assign(new Error(`gh exited with ${code2}`), { code: code2 })));
121412
+ child.once("close", (code2) => code2 === 0 ? resolve18(Buffer.concat(out).toString("utf8")) : reject(Object.assign(new Error(`gh exited with ${code2}`), { code: code2, stderr: err })));
121332
121413
  });
121333
121414
  const closed = new Promise((done) => child.once("close", () => done()));
121334
121415
  const exited = new Promise((done) => child.once("exit", () => done()));
@@ -121359,7 +121440,9 @@ async function gitBranchPr(projectCwd, branch, signal, timeoutMs = OK2.timeout)
121359
121440
  ...typeof j2.headRefOid === "string" && j2.headRefOid ? { headOid: j2.headRefOid } : {}
121360
121441
  };
121361
121442
  } catch (e) {
121362
- return e.code === "ENOENT" ? "unavailable" : null;
121443
+ if (e.code === "ENOENT") return "unavailable";
121444
+ noteGhFailure(branch, e);
121445
+ return null;
121363
121446
  } finally {
121364
121447
  clearTimeout(timer);
121365
121448
  if (onAbort) signal?.removeEventListener("abort", onAbort);
@@ -122948,7 +123031,7 @@ var AppSessions = class {
122948
123031
  const rt2 = this.host.appsHub?.rt;
122949
123032
  if (!rt2) throw rpcError("External apps are unavailable");
122950
123033
  const app2 = rt2.list().find((a) => a.appId === ref.appId && a.projectId === ref.projectId);
122951
- if (!app2) throw rpcError(`There is no such app: ${ref.projectId ?? "user"}/${ref.appId}`);
123034
+ if (!app2) throw rpcError(noSuchAppText(ref));
122952
123035
  if (!app2.trusted) {
122953
123036
  throw rpcError("Centralu does not give a builder to an app in a project it does not trust \u2014 trust the project, and the app can start and be tested");
122954
123037
  }
@@ -126416,7 +126499,7 @@ function createRpcHandler(mgr2, adapters2, { terminals: terminals2, updates: upd
126416
126499
  if (projectId === null) return { kind: "snapshots", snapshots: apps.snapshots({ appId, projectId }).map(({ stamp: _stamp, depth: _depth, ...s }) => s) };
126417
126500
  const project2 = (await mgr2.listProjects()).find((x) => x.id === projectId);
126418
126501
  const app2 = apps.list().find((a) => a.appId === appId && a.projectId === projectId);
126419
- if (!project2 || !app2) throw rpcError(`There is no such app: ${projectId}/${appId}`);
126502
+ if (!project2 || !app2) throw rpcError(noSuchAppText({ projectId, appId }));
126420
126503
  const { repo, commits } = await gitLogPath(project2.path, relative6(project2.path, app2.dir), 20);
126421
126504
  return { kind: "git", repo, commits };
126422
126505
  },
@@ -129277,11 +129360,48 @@ var SSH_COMMAND_TIMEOUT_MS = 6e4;
129277
129360
  var SSH_DETACH_TIMEOUT_MS = 12e4;
129278
129361
  var SSH_EXEC_TIMEOUT_MS = 30 * 6e4;
129279
129362
  var FORWARD_STDERR_KEEP = 16 * 1024;
129363
+ var CLIXML_MARK = /<\/?(?:Objs|Obj|S|MS|PR|TN|TNRef|Props|I32|I64|B|AV)[\s>/]|_x00[0-9A-F]{2}_/;
129364
+ var ANSI = /\x1b\[[0-?]*[ -/]*[@-~]|\x1b[@-_]?/g;
129365
+ function powershellErrorLine(line) {
129366
+ const l = line.trim();
129367
+ if (l === "+" || l.startsWith("+ ")) return null;
129368
+ if (/^\S+ \S+:\d+ \S+:\d+$/.test(l) || /^(?:At|위치) .+:\d+ \S+:\d+$/.test(l)) return null;
129369
+ if (/^Line \|$/.test(l) || /^\d+ \|/.test(l) || /^\|\s*~*$/.test(l)) return null;
129370
+ const gutter = /^\| ?(.*)$/.exec(l);
129371
+ return gutter ? gutter[1] : line;
129372
+ }
129373
+ function clixmlErrorText(xml) {
129374
+ return [...xml.matchAll(/<S S="Error">([\s\S]*?)<\/S>/g)].map(
129375
+ (m) => m[1].replace(/_x([0-9A-Fa-f]{4})_/g, (_, hex3) => String.fromCharCode(parseInt(hex3, 16))).replace(/&(lt|gt|quot|apos|amp);/g, (_, e) => ({ lt: "<", gt: ">", quot: '"', apos: "'", amp: "&" })[e])
129376
+ ).join("").replace(ANSI, "").split(/\r?\n/).flatMap((l) => {
129377
+ const kept = powershellErrorLine(l);
129378
+ return kept === null ? [] : [kept];
129379
+ }).join("\n");
129380
+ }
129381
+ function plainPart(text2) {
129382
+ const mark = text2.search(CLIXML_MARK);
129383
+ return mark < 0 ? text2 : text2.slice(0, text2.lastIndexOf("\n", mark) + 1);
129384
+ }
129280
129385
  function withoutClixml(s) {
129281
- let text2 = s.replace(/#< CLIXML[\s\S]*$/, "");
129282
- const xml = text2.search(/<\/?(?:Objs|Obj|S|MS|PR|TN|TNRef|Props|I32|I64|B|AV)[\s>/]|_x000[0-9A-F]_/);
129283
- if (xml >= 0) text2 = text2.slice(0, text2.lastIndexOf("\n", xml) + 1);
129284
- return text2.split(/\r?\n/);
129386
+ let text2 = s.replace(/^#< CLIXML\r?$/gm, "");
129387
+ const parts = [];
129388
+ const firstEnd = text2.indexOf("</Objs>");
129389
+ const firstOpen = text2.search(/<Objs[\s>]/);
129390
+ if (firstEnd >= 0 && (firstOpen < 0 || firstEnd < firstOpen)) {
129391
+ const cut = plainPart(text2.slice(0, firstEnd));
129392
+ parts.push(cut, "\n", clixmlErrorText(text2.slice(cut.length, firstEnd)), "\n");
129393
+ text2 = text2.slice(firstEnd + "</Objs>".length);
129394
+ }
129395
+ for (; ; ) {
129396
+ const open6 = text2.search(/<Objs[\s>]/);
129397
+ if (open6 < 0) break;
129398
+ parts.push(plainPart(text2.slice(0, open6)), "\n");
129399
+ const end = text2.indexOf("</Objs>", open6);
129400
+ parts.push(clixmlErrorText(end < 0 ? text2.slice(open6) : text2.slice(open6, end)), "\n");
129401
+ text2 = end < 0 ? "" : text2.slice(end + "</Objs>".length);
129402
+ }
129403
+ parts.push(plainPart(text2));
129404
+ return parts.join("").replace(ANSI, "").split(/\r?\n/);
129285
129405
  }
129286
129406
  function lastLine(s, ansi = ansiText) {
129287
129407
  const lines = withoutClixml(s).map((l) => l.trim()).filter((l) => l && !l.startsWith("**") && !/^Node\.js v\d/.test(l) && !/^at /.test(l));
@@ -129461,7 +129581,13 @@ try {
129461
129581
  if ($LASTEXITCODE -ne 0) { throw 'node_runs' }
129462
129582
  New-Item -ItemType Directory -Force (Join-Path $r 'node') | Out-Null
129463
129583
  if (Test-Path $n) { Remove-Item -Recurse -Force $n }
129464
- Move-Item $k $n
129584
+ # Windows refuses to rename a folder while something holds a file in it, and an on-access scanner holds the node.exe
129585
+ # just run for a moment ("Access to the path is denied", #368): the rename is tried again for up to 15 s. A rename
129586
+ # and nothing else: Move-Item, refused, went on to move the folder's files one by one and left half of it at $n.
129587
+ # A test's stand-in for the scanner says it holds the file by creating CENTRALU_TEST_NODE_PLACE_GATE; unset, nothing waits.
129588
+ $g = $env:CENTRALU_TEST_NODE_PLACE_GATE
129589
+ if ($g) { $end = (Get-Date).AddSeconds(60); while (-not (Test-Path -LiteralPath $g) -and (Get-Date) -lt $end) { Start-Sleep -Milliseconds 20 } }
129590
+ for ($i = 1; ; $i++) { try { [IO.Directory]::Move($k, $n); break } catch { if ($i -ge 60) { throw }; Start-Sleep -Milliseconds 250 } }
129465
129591
  Say 'node ok'
129466
129592
  } catch {
129467
129593
  $m = if ($_.Exception.Message) { $_.Exception.Message } else { "$_" }
@@ -132401,6 +132527,7 @@ var Router = class {
132401
132527
  const failed3 = Array.isArray(out.failed) ? out.failed : [];
132402
132528
  out = { ...out, failed: [...failed3, ...missed.map((m) => ({ sessionId: m.id, name: m.name, error: "this machine could not be reached, so its trash was not emptied" }))] };
132403
132529
  }
132530
+ if (method === "trash.list" && missed.length && isObj(out)) out = { ...out, unreached: missed.map((m) => ({ machineId: m.id, name: m.name })) };
132404
132531
  return out;
132405
132532
  }
132406
132533
  };
@@ -132737,7 +132864,7 @@ var handedToken = launch.tokenOnStdin ? await readHandedToken(process.stdin).cat
132737
132864
  console.error(`[agent-host] the launcher did not hand over the token: ${e.message}`);
132738
132865
  process.exit(1);
132739
132866
  }) : launch.token;
132740
- var BUILD = true ? "9b15c3f" : "dev";
132867
+ var BUILD = true ? "c807879" : "dev";
132741
132868
  var { values } = parseArgs({
132742
132869
  options: {
132743
132870
  port: { type: "string", default: "5175" },