niuma-codex 0.0.1-beta.12 → 0.0.1-beta.13

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.
package/dist/cli.js CHANGED
@@ -1963,11 +1963,11 @@ function token(value) {
1963
1963
  function size(kind, bytes3) {
1964
1964
  return (kind === "image" || kind === "file") && integer(bytes3, kind === "image" ? 20971520 : 52428800, kind === "image" ? 1 : 0);
1965
1965
  }
1966
- function dataUrl(value, path55) {
1966
+ function dataUrl(value, path56) {
1967
1967
  if (typeof value !== "string") return false;
1968
1968
  try {
1969
1969
  const u = new URL(value);
1970
- return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (path55 ? u.pathname === path55 : ["/direct/v1/attachment/data", "/ws/v1/attachment/data"].includes(u.pathname));
1970
+ return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (path56 ? u.pathname === path56 : ["/direct/v1/attachment/data", "/ws/v1/attachment/data"].includes(u.pathname));
1971
1971
  } catch {
1972
1972
  return false;
1973
1973
  }
@@ -6797,7 +6797,7 @@ var init_src = __esm({
6797
6797
  // apps/desktop/src/release-version.ts
6798
6798
  import { readFileSync } from "node:fs";
6799
6799
  function desktopReleaseVersion() {
6800
- return false ? null : "0.0.1-beta.12";
6800
+ return false ? null : "0.0.1-beta.13";
6801
6801
  }
6802
6802
  function desktopPresenceVersion() {
6803
6803
  return desktopReleaseVersion() ?? sourcePresenceVersion;
@@ -9132,9 +9132,9 @@ var init_server_client = __esm({
9132
9132
  if (data.binding_revision !== snapshot2.binding_revision) throw new NotificationTransportError("invalid_response");
9133
9133
  return { binding_revision: snapshot2.binding_revision };
9134
9134
  }
9135
- async signedPost(path55, input, signal, method2 = "POST") {
9135
+ async signedPost(path56, input, signal, method2 = "POST") {
9136
9136
  if (!this.identity || !this.serverOrigin.startsWith("https://")) throw new NotificationTransportError("business_error", 200, 200004);
9137
- const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${path55}`;
9137
+ const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${path56}`;
9138
9138
  const key_id = createHash("sha256").update(this.identity.identity_public_key).digest("base64url");
9139
9139
  const operation_id = randomUUID(), nonce = encodeBase64Url(randomBytes2(32)), timestamp = Math.floor(Date.now() / 1e3);
9140
9140
  const bytes3 = createPushSigningBytes({ audience: this.serverOrigin, method: method2, pathname, query: query2, body_sha256: createHash("sha256").update(body).digest("base64url"), key_id, operation_id, timestamp, nonce });
@@ -11892,11 +11892,11 @@ var init_runtime_version = __esm({
11892
11892
  retryAt = 0;
11893
11893
  pending = null;
11894
11894
  controller = null;
11895
- setConnection(path55) {
11895
+ setConnection(path56) {
11896
11896
  this.epoch++;
11897
11897
  this.controller?.abort();
11898
11898
  this.controller = null;
11899
- this.path = path55;
11899
+ this.path = path56;
11900
11900
  this.value = null;
11901
11901
  this.pending = null;
11902
11902
  this.retryAt = 0;
@@ -12807,20 +12807,20 @@ function sendJson(response, httpStatus, body) {
12807
12807
  }
12808
12808
  function zodErrorToHttpApiError(error2) {
12809
12809
  const messages = error2.issues.map((issue) => {
12810
- const path55 = issue.path.join(".") || "\u53C2\u6570";
12810
+ const path56 = issue.path.join(".") || "\u53C2\u6570";
12811
12811
  if (issue.code === "custom") {
12812
12812
  return issue.message;
12813
12813
  }
12814
12814
  if (issue.code === "invalid_type" && issue.received === "undefined") {
12815
- return `${path55}\u4E0D\u80FD\u4E3A\u7A7A`;
12815
+ return `${path56}\u4E0D\u80FD\u4E3A\u7A7A`;
12816
12816
  }
12817
12817
  if (issue.code === "invalid_type") {
12818
- return `${path55}\u7C7B\u578B\u9519\u8BEF`;
12818
+ return `${path56}\u7C7B\u578B\u9519\u8BEF`;
12819
12819
  }
12820
12820
  if (issue.code === "unrecognized_keys") {
12821
12821
  return `\u4E0D\u652F\u6301\u7684\u53C2\u6570: ${issue.keys.join(",")}`;
12822
12822
  }
12823
- return `${path55}\u683C\u5F0F\u9519\u8BEF`;
12823
+ return `${path56}\u683C\u5F0F\u9519\u8BEF`;
12824
12824
  });
12825
12825
  const custom = error2.issues.some((issue) => issue.code === "custom");
12826
12826
  const missing4 = error2.issues.some(
@@ -17490,7 +17490,7 @@ var init_installer = __esm({
17490
17490
  });
17491
17491
 
17492
17492
  // apps/desktop/src/autostart/launch-agent.ts
17493
- function renderLaunchAgent(config, entry, logs) {
17493
+ function autostartEnvironment(config) {
17494
17494
  const env = {
17495
17495
  HOME: config.home,
17496
17496
  PATH: config.path,
@@ -17500,12 +17500,16 @@ function renderLaunchAgent(config, entry, logs) {
17500
17500
  };
17501
17501
  if (config.codexHome) env.CODEX_HOME = config.codexHome;
17502
17502
  if (config.pushServerOrigin) env.NIUMA_PUSH_SERVER_ORIGIN = config.pushServerOrigin;
17503
+ return env;
17504
+ }
17505
+ function renderLaunchAgent(config, entry, logs, application = false) {
17506
+ const env = autostartEnvironment(config);
17503
17507
  const str = (v) => `<string>${xml(v)}</string>`;
17504
17508
  return `<?xml version="1.0" encoding="UTF-8"?>
17505
17509
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
17506
17510
  <plist version="1.0"><dict>
17507
- <key>Label</key>${str(AUTOSTART_LABEL)}
17508
- <key>ProgramArguments</key><array>${[config.nodeExecutable, entry, "--background"].map(str).join("")}</array>
17511
+ <key>Label</key>${str(application ? AUTOSTART_APP_LABEL : AUTOSTART_LABEL)}
17512
+ ${application ? "<key>BundleProgram</key><string>Contents/MacOS/Niuma</string>" : `<key>ProgramArguments</key><array>${[config.nodeExecutable, entry, "--background"].map(str).join("")}</array>`}
17509
17513
  <key>RunAtLoad</key><true/>
17510
17514
  <key>WorkingDirectory</key>${str(config.home)}
17511
17515
  <key>EnvironmentVariables</key><dict>${Object.entries(env).map(([k, v]) => `<key>${k}</key>${str(v)}`).join("")}</dict>
@@ -17514,19 +17518,124 @@ function renderLaunchAgent(config, entry, logs) {
17514
17518
  </dict></plist>
17515
17519
  `;
17516
17520
  }
17517
- var AUTOSTART_LABEL, xml;
17521
+ var AUTOSTART_LABEL, AUTOSTART_APP_ID, AUTOSTART_APP_LABEL, xml;
17518
17522
  var init_launch_agent = __esm({
17519
17523
  "apps/desktop/src/autostart/launch-agent.ts"() {
17520
17524
  "use strict";
17521
17525
  AUTOSTART_LABEL = "com.niuma.desktop";
17526
+ AUTOSTART_APP_ID = "com.niuma.npm-autostart";
17527
+ AUTOSTART_APP_LABEL = "com.niuma.npm-autostart.agent";
17522
17528
  xml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
17523
17529
  }
17524
17530
  });
17525
17531
 
17532
+ // apps/desktop/src/assets.ts
17533
+ function desktopAssetUrl(area, file) {
17534
+ const release2 = true;
17535
+ return new URL(release2 ? `./assets/${area}/${file}` : `./${area}/static/${file}`, import.meta.url);
17536
+ }
17537
+ var init_assets = __esm({
17538
+ "apps/desktop/src/assets.ts"() {
17539
+ "use strict";
17540
+ }
17541
+ });
17542
+
17543
+ // apps/desktop/src/autostart/app-bundle.ts
17544
+ import fs15 from "node:fs/promises";
17545
+ import path20 from "node:path";
17546
+ import { createHash as createHash2 } from "node:crypto";
17547
+ async function checkAutostartApp(app) {
17548
+ for (const directory of [app, ...["Contents", "Contents/MacOS", "Contents/Resources", "Contents/Library", "Contents/Library/LaunchAgents"].map((item) => path20.join(app, item))]) {
17549
+ const stat3 = await fs15.lstat(directory);
17550
+ if (!stat3.isDirectory() || stat3.uid !== process.getuid?.() || stat3.mode & 18) throw new AutostartError(900611, "\u81EA\u542F\u52A8\u5E94\u7528\u5305\u76EE\u5F55\u4E0D\u5B89\u5168");
17551
+ }
17552
+ for (const file of bundleFiles) {
17553
+ const stat3 = await fs15.lstat(path20.join(app, file));
17554
+ if (!stat3.isFile() || stat3.uid !== process.getuid?.() || stat3.mode & 18) throw new AutostartError(900611, "\u81EA\u542F\u52A8\u5E94\u7528\u5305\u6587\u4EF6\u4E0D\u5B89\u5168");
17555
+ }
17556
+ await fs15.access(path20.join(app, "Contents/MacOS/Niuma"), 1);
17557
+ try {
17558
+ await runProcess("/usr/bin/codesign", ["--verify", "--strict", app]);
17559
+ } catch {
17560
+ throw new AutostartError(900611, "\u81EA\u542F\u52A8\u5E94\u7528\u5305\u7B7E\u540D\u9A8C\u8BC1\u5931\u8D25\uFF0C\u672A\u8986\u76D6");
17561
+ }
17562
+ }
17563
+ async function prepareAutostartApp(root, config, entry) {
17564
+ const icon = await fs15.readFile(desktopAssetUrl("autostart", "Niuma.icns"));
17565
+ const launcher = await fs15.readFile(desktopAssetUrl("autostart", "Niuma"));
17566
+ const plist = Buffer.from(`<?xml version="1.0" encoding="UTF-8"?>
17567
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
17568
+ <plist version="1.0"><dict>
17569
+ <key>CFBundleIdentifier</key><string>${AUTOSTART_APP_ID}</string>
17570
+ <key>CFBundleName</key><string>Niuma</string>
17571
+ <key>CFBundleDisplayName</key><string>Niuma</string>
17572
+ <key>CFBundleExecutable</key><string>Niuma</string>
17573
+ <key>CFBundleIconFile</key><string>Niuma.icns</string>
17574
+ <key>CFBundlePackageType</key><string>APPL</string>
17575
+ <key>CFBundleVersion</key><string>1</string>
17576
+ <key>LSUIElement</key><true/>
17577
+ </dict></plist>
17578
+ `);
17579
+ const script3 = Buffer.from(`#!/bin/sh
17580
+ # \u4EC5\u542F\u52A8\u5DF2\u9A8C\u8BC1\u7684\u56FA\u5B9A npm \u7248\u672C\uFF0C\u73AF\u5883\u4E0E\u767B\u5F55\u9879\u4F7F\u7528\u540C\u4E00\u767D\u540D\u5355\u3002
17581
+ ${Object.entries(autostartEnvironment(config)).map(([key, value]) => `export ${key}=${quote(value)}`).join("\n")}
17582
+ cd ${quote(config.home)} || exit 1
17583
+ exec ${quote(config.nodeExecutable)} ${quote(entry)} --background
17584
+ `);
17585
+ const contents = [plist, launcher, icon, script3, Buffer.from(renderLaunchAgent(config, entry, root, true))];
17586
+ const digest5 = createHash2("sha256");
17587
+ for (const data of contents) digest5.update(data);
17588
+ const parent = path20.join(root, "applications");
17589
+ await privateDirectory(parent);
17590
+ const directory = path20.join(parent, digest5.digest("hex"));
17591
+ await privateDirectory(directory);
17592
+ const app = path20.join(directory, "Niuma.app");
17593
+ let exists = false;
17594
+ try {
17595
+ await fs15.lstat(app);
17596
+ exists = true;
17597
+ } catch (error2) {
17598
+ if (error2.code !== "ENOENT") throw error2;
17599
+ }
17600
+ if (exists) {
17601
+ await checkAutostartApp(app);
17602
+ for (let i = 0; i < bundleFiles.length; i++) if (i !== 1 && !(await fs15.readFile(path20.join(app, bundleFiles[i]))).equals(contents[i])) throw new AutostartError(900611, "\u81EA\u542F\u52A8\u5E94\u7528\u5305\u5DF2\u88AB\u4FEE\u6539\uFF0C\u672A\u8986\u76D6");
17603
+ return app;
17604
+ }
17605
+ const staging = await fs15.mkdtemp(path20.join(directory, ".prepare-"));
17606
+ const temporary = path20.join(staging, "Niuma.app");
17607
+ try {
17608
+ await fs15.mkdir(path20.join(temporary, "Contents/MacOS"), { recursive: true, mode: 448 });
17609
+ await fs15.mkdir(path20.join(temporary, "Contents/Resources"), { mode: 448 });
17610
+ await fs15.mkdir(path20.join(temporary, "Contents/Library/LaunchAgents"), { recursive: true, mode: 448 });
17611
+ for (let i = 0; i < bundleFiles.length; i++) await fs15.writeFile(path20.join(temporary, bundleFiles[i]), contents[i], { flag: "wx", mode: i === 1 ? 448 : 384 });
17612
+ await runProcess("/usr/bin/codesign", ["--force", "--sign", "-", temporary]);
17613
+ await checkAutostartApp(temporary);
17614
+ await fs15.rename(temporary, app);
17615
+ return app;
17616
+ } finally {
17617
+ await fs15.rm(staging, { recursive: true, force: true });
17618
+ }
17619
+ }
17620
+ var LSREGISTER, quote, bundleFiles;
17621
+ var init_app_bundle = __esm({
17622
+ "apps/desktop/src/autostart/app-bundle.ts"() {
17623
+ "use strict";
17624
+ init_assets();
17625
+ init_installer();
17626
+ init_launch_agent();
17627
+ init_types2();
17628
+ LSREGISTER = "/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister";
17629
+ quote = (value) => `'${value.replaceAll("'", "'\\''")}'`;
17630
+ bundleFiles = ["Contents/Info.plist", "Contents/MacOS/Niuma", "Contents/Resources/Niuma.icns", "Contents/Resources/launch.sh", `Contents/Library/LaunchAgents/${AUTOSTART_APP_LABEL}.plist`];
17631
+ }
17632
+ });
17633
+
17526
17634
  // apps/desktop/src/autostart/manager.ts
17527
- import fs15 from "node:fs";
17635
+ import fs16 from "node:fs";
17528
17636
  import fsp from "node:fs/promises";
17529
- import path20 from "node:path";
17637
+ import path21 from "node:path";
17638
+ import os2 from "node:os";
17530
17639
  import { randomUUID as randomUUID11 } from "node:crypto";
17531
17640
  async function readJson(file) {
17532
17641
  try {
@@ -17549,13 +17658,13 @@ async function atomic(file, value) {
17549
17658
  }
17550
17659
  function acquire(file) {
17551
17660
  try {
17552
- const fd = fs15.openSync(file, fs15.constants.O_CREAT | fs15.constants.O_RDWR | fs15.constants.O_NOFOLLOW | fs15.constants.O_NONBLOCK | 32, 384);
17553
- const s = fs15.fstatSync(fd);
17661
+ const fd = fs16.openSync(file, fs16.constants.O_CREAT | fs16.constants.O_RDWR | fs16.constants.O_NOFOLLOW | fs16.constants.O_NONBLOCK | 32, 384);
17662
+ const s = fs16.fstatSync(fd);
17554
17663
  if (!s.isFile() || s.uid !== process.getuid?.() || s.mode & 63) {
17555
- fs15.closeSync(fd);
17664
+ fs16.closeSync(fd);
17556
17665
  throw Error("unsafe");
17557
17666
  }
17558
- return () => fs15.closeSync(fd);
17667
+ return () => fs16.closeSync(fd);
17559
17668
  } catch {
17560
17669
  throw new AutostartError(900511, "\u5DF2\u6709\u81EA\u542F\u52A8\u64CD\u4F5C\u6B63\u5728\u8FDB\u884C\uFF0C\u6216\u64CD\u4F5C\u9501\u4E0D\u53EF\u7528");
17561
17670
  }
@@ -17566,12 +17675,13 @@ var init_manager = __esm({
17566
17675
  "use strict";
17567
17676
  init_installer();
17568
17677
  init_launch_agent();
17678
+ init_app_bundle();
17569
17679
  init_types2();
17570
17680
  AutostartManager = class {
17571
17681
  constructor(options) {
17572
17682
  this.options = options;
17573
- this.root = path20.join(options.home, "Library/Application Support/Niuma/autostart");
17574
- this.plist = path20.join(options.home, "Library/LaunchAgents", `${AUTOSTART_LABEL}.plist`);
17683
+ this.root = path21.join(options.home, "Library/Application Support/Niuma/autostart");
17684
+ this.plist = path21.join(options.home, "Library/LaunchAgents", `${AUTOSTART_LABEL}.plist`);
17575
17685
  this.run = options.run ?? runProcess;
17576
17686
  }
17577
17687
  options;
@@ -17587,29 +17697,62 @@ var init_manager = __esm({
17587
17697
  return `${this.domain}/${AUTOSTART_LABEL}`;
17588
17698
  }
17589
17699
  get metadata() {
17590
- return path20.join(this.root, "registration.json");
17700
+ return path21.join(this.root, "registration.json");
17591
17701
  }
17592
17702
  get operationFile() {
17593
- return path20.join(this.root, "operation.json");
17703
+ return path21.join(this.root, "operation.json");
17594
17704
  }
17595
17705
  supported() {
17596
- return (this.options.platform ?? process.platform) === "darwin";
17706
+ return (this.options.platform ?? process.platform) === "darwin" && Number((this.options.osRelease ?? os2.release()).split(".")[0]) >= 22;
17597
17707
  }
17598
- async loaded() {
17708
+ // 2 表示已注册但待批准,不能等同于未注册;未知状态不能触发破坏性恢复。
17709
+ async registrationState(registration) {
17710
+ if (registration?.service === "application-agent" && registration.appPath) {
17711
+ try {
17712
+ await checkAutostartApp(registration.appPath);
17713
+ const result = JSON.parse(await this.run(path21.join(registration.appPath, "Contents/MacOS/Niuma"), ["--autostart-status"]));
17714
+ return [0, 1, 2, 3].includes(result.status) ? result.status : null;
17715
+ } catch {
17716
+ return null;
17717
+ }
17718
+ }
17599
17719
  try {
17600
17720
  await this.run("/bin/launchctl", ["print", this.target]);
17601
- return true;
17721
+ return 1;
17602
17722
  } catch (e) {
17603
- return e.code === 113 ? false : null;
17723
+ return e.code === 113 ? 0 : null;
17604
17724
  }
17605
17725
  }
17726
+ async loaded(registration) {
17727
+ const state = await this.registrationState(registration);
17728
+ return state === null ? null : state === 1;
17729
+ }
17730
+ async stopRegistration(registration) {
17731
+ const state = await this.registrationState(registration);
17732
+ if (state === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u72B6\u6001\uFF0C\u4FDD\u7559\u539F\u6CE8\u518C");
17733
+ if (state === 1 || state === 2) await this.unload(registration);
17734
+ }
17735
+ /** 应用注册由 ServiceManagement 持有;legacy 注册继续用原 launchctl 路径回滚。 */
17736
+ async load(registration, allowPending = false) {
17737
+ if (registration.service === "application-agent" && registration.appPath) {
17738
+ await checkAutostartApp(registration.appPath);
17739
+ const result = JSON.parse(await this.run(path21.join(registration.appPath, "Contents/MacOS/Niuma"), ["--autostart-register"]));
17740
+ if (result.status !== 1 && !(allowPending && result.status === 2)) throw new AutostartError(900614, "\u8BF7\u5728\u7CFB\u7EDF\u8BBE\u7F6E\u7684\u767B\u5F55\u9879\u4E2D\u5141\u8BB8 Niuma \u5728\u540E\u53F0\u8FD0\u884C\u540E\u91CD\u8BD5");
17741
+ } else await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17742
+ }
17743
+ async unload(registration) {
17744
+ if (registration?.service === "application-agent" && registration.appPath) {
17745
+ await checkAutostartApp(registration.appPath);
17746
+ await this.run(path21.join(registration.appPath, "Contents/MacOS/Niuma"), ["--autostart-unregister"]);
17747
+ } else await this.run("/bin/launchctl", ["bootout", this.target]);
17748
+ }
17606
17749
  async status() {
17607
- if (!this.supported() || this.options.unavailableReason) return { supported: false, registered: false, loaded: null, available: false, registeredVersion: null, runningVersion: null, running: null, reason: this.options.unavailableReason ?? "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8", logPath: this.root, operation: null };
17750
+ if (!this.supported() || this.options.unavailableReason) return { supported: false, registered: false, loaded: null, available: false, registeredVersion: null, runningVersion: null, running: null, reason: this.options.unavailableReason ?? "\u767B\u5F55\u81EA\u542F\u52A8\u9700\u8981 macOS 13 \u6216\u66F4\u65B0\u7248\u672C", logPath: this.root, operation: null };
17608
17751
  const registration = await readJson(this.metadata);
17609
17752
  let operation = await readJson(this.operationFile);
17610
17753
  if (operation?.state === "running" && !this.busy) {
17611
17754
  try {
17612
- const release2 = acquire(path20.join(this.root, "operation.lock"));
17755
+ const release2 = acquire(path21.join(this.root, "operation.lock"));
17613
17756
  release2();
17614
17757
  operation = { ...operation, state: "interrupted", code: 900615, message: "\u4E0A\u6B21\u81EA\u542F\u52A8\u64CD\u4F5C\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5" };
17615
17758
  } catch {
@@ -17619,17 +17762,21 @@ var init_manager = __esm({
17619
17762
  if (registration) {
17620
17763
  if (registration.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u81EA\u542F\u52A8\u914D\u7F6E\u4E0D\u5C5E\u4E8E Niuma");
17621
17764
  try {
17622
- const stat3 = await fsp.lstat(this.plist);
17623
- registered = stat3.isFile() && await fsp.readFile(this.plist, "utf8") === registration.plist;
17624
- await fsp.access(registration.config.nodeExecutable, fs15.constants.X_OK);
17625
- await fsp.access(registration.entryPath, fs15.constants.R_OK);
17765
+ if (registration.service === "application-agent") registered = true;
17766
+ else {
17767
+ const stat3 = await fsp.lstat(this.plist);
17768
+ registered = stat3.isFile() && await fsp.readFile(this.plist, "utf8") === registration.plist;
17769
+ }
17770
+ await fsp.access(registration.config.nodeExecutable, fs16.constants.X_OK);
17771
+ await fsp.access(registration.entryPath, fs16.constants.R_OK);
17772
+ if (registration.appPath) await checkAutostartApp(registration.appPath);
17626
17773
  available = registered;
17627
17774
  } catch {
17628
17775
  reason = "\u81EA\u542F\u52A8\u8FD0\u884C\u6587\u4EF6\u6216 Node \u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E";
17629
17776
  }
17630
17777
  }
17631
17778
  const running = await this.options.running?.().catch(() => ({ running: null, version: null })) ?? { running: null, version: null };
17632
- const loaded = await this.loaded();
17779
+ const loaded = await this.loaded(registration);
17633
17780
  if (registered && loaded !== true) {
17634
17781
  available = false;
17635
17782
  reason = "\u542F\u52A8\u9879\u672A\u52A0\u8F7D\u6216\u65E0\u6CD5\u67E5\u8BE2\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E";
@@ -17648,13 +17795,13 @@ var init_manager = __esm({
17648
17795
  };
17649
17796
  }
17650
17797
  async beginSetEnabled(enabled, config) {
17651
- if (!this.supported() || this.options.unavailableReason) throw new AutostartError(900611, this.options.unavailableReason ?? "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8");
17798
+ if (!this.supported() || this.options.unavailableReason) throw new AutostartError(900611, this.options.unavailableReason ?? "\u767B\u5F55\u81EA\u542F\u52A8\u9700\u8981 macOS 13 \u6216\u66F4\u65B0\u7248\u672C");
17652
17799
  if (this.busy) throw new AutostartError(900511, "\u5DF2\u6709\u81EA\u542F\u52A8\u64CD\u4F5C\u6B63\u5728\u8FDB\u884C");
17653
17800
  this.busy = true;
17654
17801
  let release2;
17655
17802
  try {
17656
17803
  await privateDirectory(this.root);
17657
- release2 = acquire(path20.join(this.root, "operation.lock"));
17804
+ release2 = acquire(path21.join(this.root, "operation.lock"));
17658
17805
  const operation = { id: randomUUID11(), targetEnabled: enabled, state: "running", startedAt: Date.now(), finishedAt: null, pid: process.pid };
17659
17806
  await atomic(this.operationFile, JSON.stringify(operation));
17660
17807
  this.active = (async () => {
@@ -17694,7 +17841,7 @@ var init_manager = __esm({
17694
17841
  }
17695
17842
  /** 注册文件和元数据的两次写入由恢复记录覆盖,崩溃后只恢复可证明自有的内容。 */
17696
17843
  async recoverTransaction() {
17697
- const file = path20.join(this.root, "transaction.json");
17844
+ const file = path21.join(this.root, "transaction.json");
17698
17845
  const transaction = await readJson(file);
17699
17846
  if (!transaction) return;
17700
17847
  if (transaction.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u6CE8\u518C\u6062\u590D\u8BB0\u5F55\u65E0\u6548");
@@ -17707,21 +17854,22 @@ var init_manager = __esm({
17707
17854
  if (e.code !== "ENOENT") throw new AutostartError(900611, "\u65E0\u6CD5\u5B89\u5168\u6062\u590D\u542F\u52A8\u9879");
17708
17855
  }
17709
17856
  if (current2 !== null && current2 !== transaction.previous?.plist && current2 !== transaction.next?.plist) throw new AutostartError(900611, "\u542F\u52A8\u9879\u5DF2\u88AB\u5176\u4ED6\u7A0B\u5E8F\u4FEE\u6539\uFF0C\u672A\u8986\u76D6");
17710
- const loaded = await this.loaded();
17711
- if (loaded === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u72B6\u6001\uFF0C\u6062\u590D\u672A\u5B8C\u6210");
17712
- if (loaded) await this.run("/bin/launchctl", ["bootout", this.target]);
17857
+ if (transaction.next) await this.stopRegistration(transaction.next);
17858
+ if (transaction.previous) await this.stopRegistration(transaction.previous);
17713
17859
  if (transaction.previous) {
17714
- await atomic(this.plist, transaction.previous.plist);
17860
+ if (transaction.previous.service === "application-agent") await fsp.rm(this.plist, { force: true });
17861
+ else await atomic(this.plist, transaction.previous.plist);
17715
17862
  await atomic(this.metadata, JSON.stringify(transaction.previous));
17716
17863
  } else {
17717
17864
  await fsp.rm(this.plist, { force: true });
17718
17865
  await fsp.rm(this.metadata, { force: true });
17719
17866
  }
17720
- if (transaction.wasLoaded) await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17867
+ if (transaction.previous?.appPath) await this.run(LSREGISTER, ["-f", transaction.previous.appPath]);
17868
+ if ((transaction.wasRegistered ?? transaction.wasLoaded) && transaction.previous) await this.load(transaction.previous, !transaction.wasLoaded);
17721
17869
  await fsp.rm(file);
17722
17870
  }
17723
17871
  async change(enabled, input) {
17724
- await privateDirectory(path20.dirname(this.plist));
17872
+ await privateDirectory(path21.dirname(this.plist));
17725
17873
  await this.recoverTransaction();
17726
17874
  const previous = await readJson(this.metadata);
17727
17875
  let existing = null;
@@ -17738,30 +17886,38 @@ var init_manager = __esm({
17738
17886
  } catch {
17739
17887
  throw new AutostartError(900611, "\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 macOS \u56FE\u5F62\u767B\u5F55\u4F1A\u8BDD");
17740
17888
  }
17741
- const wasLoaded = await this.loaded();
17742
- if (wasLoaded === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u52A0\u8F7D\u72B6\u6001");
17889
+ if (previous && previous.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u81EA\u542F\u52A8\u914D\u7F6E\u4E0D\u5C5E\u4E8E Niuma");
17890
+ const priorState = await this.registrationState(previous);
17891
+ const wasLoaded = priorState === 1, wasRegistered = priorState === 1 || priorState === 2;
17892
+ if (priorState === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u52A0\u8F7D\u72B6\u6001");
17743
17893
  if (wasLoaded && !previous) throw new AutostartError(900611, "\u5DF2\u52A0\u8F7D\u7684\u540C\u540D\u670D\u52A1\u7F3A\u5C11 Niuma \u5F52\u5C5E\u8BB0\u5F55\uFF0C\u672A\u63A5\u7BA1");
17744
17894
  let next = null;
17745
17895
  if (enabled) {
17746
17896
  const config = input ?? this.options.config();
17747
17897
  await this.options.guard?.();
17748
- if (previous && existing === previous.plist && JSON.stringify(config) === JSON.stringify(previous.config) && (await this.status()).available) return;
17749
- const installed = await (this.options.install?.(config) ?? installRelease({ root: this.root, version: config.releaseVersion, node: config.nodeExecutable, npm: path20.join(path20.dirname(config.nodeExecutable), "npm"), run: this.run }));
17898
+ const reusable = previous && (previous.service === "application-agent" ? existing === null : existing === previous.plist) && JSON.stringify(config) === JSON.stringify(previous.config) && (await this.status()).available;
17899
+ const installed = reusable ? { entryPath: previous.entryPath } : await (this.options.install?.(config) ?? installRelease({ root: this.root, version: config.releaseVersion, node: config.nodeExecutable, npm: path21.join(path21.dirname(config.nodeExecutable), "npm"), run: this.run }));
17900
+ const appPath = await prepareAutostartApp(this.root, config, installed.entryPath);
17750
17901
  await this.options.guard?.();
17751
- next = { owner: "niuma-autostart-v1", config, entryPath: installed.entryPath, plist: renderLaunchAgent(config, installed.entryPath, this.root) };
17902
+ next = { owner: "niuma-autostart-v1", service: "application-agent", config, entryPath: installed.entryPath, appPath, plist: renderLaunchAgent(config, installed.entryPath, this.root, true) };
17903
+ if (reusable && previous.service === next.service && previous.appPath === appPath && previous.plist === next.plist) {
17904
+ await this.run(LSREGISTER, ["-f", appPath]);
17905
+ return;
17906
+ }
17752
17907
  for (const name2 of ["stdout.log", "stderr.log"]) {
17753
- const handle = await fsp.open(path20.join(this.root, name2), fs15.constants.O_WRONLY | fs15.constants.O_APPEND | fs15.constants.O_CREAT | fs15.constants.O_NOFOLLOW, 384);
17908
+ const handle = await fsp.open(path21.join(this.root, name2), fs16.constants.O_WRONLY | fs16.constants.O_APPEND | fs16.constants.O_CREAT | fs16.constants.O_NOFOLLOW, 384);
17754
17909
  await handle.close();
17755
17910
  }
17756
17911
  }
17757
- const transactionFile = path20.join(this.root, "transaction.json");
17758
- await atomic(transactionFile, JSON.stringify({ owner: "niuma-autostart-v1", previous, next, wasLoaded }));
17912
+ const transactionFile = path21.join(this.root, "transaction.json");
17913
+ await atomic(transactionFile, JSON.stringify({ owner: "niuma-autostart-v1", previous, next, wasLoaded, wasRegistered }));
17759
17914
  try {
17760
- if (wasLoaded) await this.run("/bin/launchctl", ["bootout", this.target]);
17915
+ if (next?.appPath) await this.run(LSREGISTER, ["-f", next.appPath]);
17916
+ if (wasRegistered) await this.unload(previous);
17761
17917
  if (next) {
17762
- await atomic(this.plist, next.plist);
17918
+ await fsp.rm(this.plist, { force: true });
17763
17919
  await atomic(this.metadata, JSON.stringify(next));
17764
- await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17920
+ await this.load(next);
17765
17921
  } else {
17766
17922
  await fsp.rm(this.plist, { force: true });
17767
17923
  await fsp.rm(this.metadata, { force: true });
@@ -17770,13 +17926,7 @@ var init_manager = __esm({
17770
17926
  } catch {
17771
17927
  let restored = true;
17772
17928
  try {
17773
- if (await this.loaded()) await this.run("/bin/launchctl", ["bootout", this.target]);
17774
- if (existing !== null) await atomic(this.plist, existing);
17775
- else await fsp.rm(this.plist, { force: true });
17776
- if (previous) await atomic(this.metadata, JSON.stringify(previous));
17777
- else await fsp.rm(this.metadata, { force: true });
17778
- if (wasLoaded) await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17779
- await fsp.rm(transactionFile, { force: true });
17929
+ await this.recoverTransaction();
17780
17930
  } catch {
17781
17931
  restored = false;
17782
17932
  }
@@ -17788,8 +17938,8 @@ var init_manager = __esm({
17788
17938
  });
17789
17939
 
17790
17940
  // apps/desktop/src/autostart/production.ts
17791
- import os2 from "node:os";
17792
- import path21 from "node:path";
17941
+ import os3 from "node:os";
17942
+ import path22 from "node:path";
17793
17943
  function autostartConfig(args, relayOrigin) {
17794
17944
  const version2 = desktopReleaseVersion();
17795
17945
  if (!version2) throw new AutostartError(900611, "\u6E90\u7801\u8FD0\u884C\u4E0D\u652F\u6301\u6CE8\u518C\u81EA\u542F\u52A8\uFF0C\u8BF7\u4F7F\u7528\u5DF2\u53D1\u5E03\u7684 niuma-codex");
@@ -17797,8 +17947,8 @@ function autostartConfig(args, relayOrigin) {
17797
17947
  return {
17798
17948
  releaseVersion: version2,
17799
17949
  nodeExecutable: process.execPath,
17800
- home: os2.homedir(),
17801
- path: [path21.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
17950
+ home: os3.homedir(),
17951
+ path: [path22.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
17802
17952
  ...process.env.CODEX_HOME ? { codexHome: process.env.CODEX_HOME } : {},
17803
17953
  relayOrigin: resolveRelayConfig({ relay_origin: relayOrigin ?? resolveRelayStartupOrigin({ env: process.env, cliOrigin: args.flags.relayOrigin }) }).origin,
17804
17954
  pushServerOrigin: resolvePushServerOrigin(process.env),
@@ -17813,7 +17963,7 @@ function statusRecord(value) {
17813
17963
  function createAutostartManager(args = parseRootArgs(process.argv.slice(2)), page4 = false, relayOrigin) {
17814
17964
  const client = new DaemonClient();
17815
17965
  return new AutostartManager({
17816
- home: os2.homedir(),
17966
+ home: os3.homedir(),
17817
17967
  ...page4 && !desktopReleaseVersion() ? { unavailableReason: "\u6E90\u7801\u8FD0\u884C\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8\uFF0C\u8BF7\u4F7F\u7528\u5DF2\u53D1\u5E03\u7684 niuma-codex" } : {},
17818
17968
  config: () => autostartConfig(args, relayOrigin),
17819
17969
  running: async () => {
@@ -18236,15 +18386,15 @@ var init_client_turn_query_context = __esm({
18236
18386
  });
18237
18387
 
18238
18388
  // apps/desktop/src/niuma/session-history-file.ts
18239
- import fs16 from "node:fs/promises";
18240
- import path22 from "node:path";
18241
- import { createHash as createHash2 } from "node:crypto";
18389
+ import fs17 from "node:fs/promises";
18390
+ import path23 from "node:path";
18391
+ import { createHash as createHash3 } from "node:crypto";
18242
18392
  function matchesSessionFileIdentity(file, stat3) {
18243
18393
  const exact = (value) => typeof value === "number" ? Number.isSafeInteger(value) && value >= 0 ? String(value) : null : /^(0|[1-9]\d{0,39})$/.test(value) ? value : null;
18244
18394
  return exact(file.dev) === String(stat3.dev) && exact(file.ino) === String(stat3.ino);
18245
18395
  }
18246
18396
  async function preciseStat(file) {
18247
- const stat3 = await fs16.stat(file, { bigint: true });
18397
+ const stat3 = await fs17.stat(file, { bigint: true });
18248
18398
  const size2 = Number(stat3.size);
18249
18399
  if (!Number.isSafeInteger(size2)) throw new SessionHistoryError("RESOURCE_LIMIT", "\u4F1A\u8BDD\u6587\u4EF6\u8D85\u51FA\u8BFB\u53D6\u8303\u56F4");
18250
18400
  return { dev: stat3.dev, ino: stat3.ino, size: size2, mtimeMs: Number(stat3.mtimeNs) / 1e6, isFile: () => stat3.isFile() };
@@ -18260,12 +18410,12 @@ function rethrowUnreadableHistoryPath(error2) {
18260
18410
  }
18261
18411
  function fileIdentity(file) {
18262
18412
  const uuid7 = "[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}";
18263
- const match = path22.basename(file).match(new RegExp(`(${uuid7})(?:_(${uuid7}))?\\.jsonl$`, "i"));
18413
+ const match = path23.basename(file).match(new RegExp(`(${uuid7})(?:_(${uuid7}))?\\.jsonl$`, "i"));
18264
18414
  return match ? { owner: match[1], segment: match[2] ?? match[1] } : null;
18265
18415
  }
18266
18416
  async function readBytes(file, start, length, onRead, signal) {
18267
18417
  abortIfRequested(signal);
18268
- const handle = await fs16.open(file, "r").catch(rethrowUnreadableHistoryPath);
18418
+ const handle = await fs17.open(file, "r").catch(rethrowUnreadableHistoryPath);
18269
18419
  try {
18270
18420
  const buffer = Buffer.allocUnsafe(length);
18271
18421
  let filled = 0;
@@ -18323,7 +18473,7 @@ async function header(file, size2, onRead, signal) {
18323
18473
  }
18324
18474
  async function openSessionFile(file, threadId2, chunkBytes, end, onRead, signal, onCutoffCaptured) {
18325
18475
  abortIfRequested(signal);
18326
- const resolved3 = await fs16.realpath(file).catch(rethrowUnreadableHistoryPath);
18476
+ const resolved3 = await fs17.realpath(file).catch(rethrowUnreadableHistoryPath);
18327
18477
  const stat3 = await preciseStat(resolved3).catch(rethrowUnreadableHistoryPath);
18328
18478
  abortIfRequested(signal);
18329
18479
  if (!stat3.isFile()) throw new SessionHistoryError("INVALID_METADATA", "\u4F1A\u8BDD\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
@@ -18470,7 +18620,7 @@ var init_session_history_file = __esm({
18470
18620
  nonempty = (value) => typeof value === "string" && value.length > 0 ? value : null;
18471
18621
  SESSION_RECORD_LOCATION = /* @__PURE__ */ Symbol("sessionHistoryLocation");
18472
18622
  SESSION_RECORD_RANGE = /* @__PURE__ */ Symbol("sessionHistoryRange");
18473
- hash = (value) => createHash2("sha256").update(value).digest("hex");
18623
+ hash = (value) => createHash3("sha256").update(value).digest("hex");
18474
18624
  }
18475
18625
  });
18476
18626
 
@@ -20604,9 +20754,9 @@ var init_create = __esm({
20604
20754
  });
20605
20755
 
20606
20756
  // apps/desktop/src/daemon/async-question-response.ts
20607
- import { createHash as createHash3 } from "node:crypto";
20757
+ import { createHash as createHash4 } from "node:crypto";
20608
20758
  function submissionId(input) {
20609
- const h = createHash3("sha256").update(JSON.stringify([input.principal, input.threadId, input.idempotencyKey])).digest("hex");
20759
+ const h = createHash4("sha256").update(JSON.stringify([input.principal, input.threadId, input.idempotencyKey])).digest("hex");
20610
20760
  return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-8${h.slice(17, 20)}-${h.slice(20, 32)}`;
20611
20761
  }
20612
20762
  function questionWasNotDispatched(result) {
@@ -20614,7 +20764,7 @@ function questionWasNotDispatched(result) {
20614
20764
  }
20615
20765
  async function respondAsyncQuestion(options) {
20616
20766
  const { store, input } = options;
20617
- const fingerprint2 = createHash3("sha256").update(JSON.stringify([input.questionId, input.answer])).digest("hex");
20767
+ const fingerprint2 = createHash4("sha256").update(JSON.stringify([input.questionId, input.answer])).digest("hex");
20618
20768
  const key = { principal: input.principal, threadId: input.threadId, clientMessageId: submissionId(input) };
20619
20769
  if (store.get(key).state !== "untracked") {
20620
20770
  const existing = await store.reserve({ ...key, questionId: input.questionId, fingerprint: fingerprint2, nativeToken: key.clientMessageId });
@@ -21137,7 +21287,7 @@ function formatRedactedSeparator(separator) {
21137
21287
  function cleanDetail(detail) {
21138
21288
  return detail.replace(/<!--[\s\S]*?-->/g, " ").replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(
21139
21289
  SENSITIVE_KEY_PATTERN,
21140
- (_match, prefix, quote, key, separator) => `${prefix}${quote}${key}${quote}${formatRedactedSeparator(separator)}[REDACTED]`
21290
+ (_match, prefix, quote2, key, separator) => `${prefix}${quote2}${key}${quote2}${formatRedactedSeparator(separator)}[REDACTED]`
21141
21291
  ).replace(
21142
21292
  BEARER_PATTERN,
21143
21293
  (_match, prefix, scheme, separator) => `${prefix}${scheme}${formatRedactedSeparator(separator)}[REDACTED]`
@@ -21300,10 +21450,10 @@ var init_status = __esm({
21300
21450
  });
21301
21451
 
21302
21452
  // apps/desktop/src/niuma/thread-summary.ts
21303
- import path23 from "node:path";
21453
+ import path24 from "node:path";
21304
21454
  function pathBelongsToProjectRoot(projectRoot, candidateRoot) {
21305
- const relative = path23.relative(path23.resolve(projectRoot), path23.resolve(candidateRoot));
21306
- return relative === "" || !relative.startsWith("..") && !path23.isAbsolute(relative);
21455
+ const relative = path24.relative(path24.resolve(projectRoot), path24.resolve(candidateRoot));
21456
+ return relative === "" || !relative.startsWith("..") && !path24.isAbsolute(relative);
21307
21457
  }
21308
21458
  function toLatestTurn(turns) {
21309
21459
  const latest = turns.at(-1);
@@ -21371,7 +21521,7 @@ function normalizeThreadSummary(thread4, pending = null, options = {}) {
21371
21521
  id: thread4.id,
21372
21522
  title: thread4.name ?? thread4.preview ?? "",
21373
21523
  projectRoot: thread4.cwd,
21374
- projectName: path23.basename(thread4.cwd) || thread4.cwd,
21524
+ projectName: path24.basename(thread4.cwd) || thread4.cwd,
21375
21525
  status: status2,
21376
21526
  pending: normalizedPending,
21377
21527
  createdAt: thread4.createdAt,
@@ -22691,7 +22841,7 @@ var init_codex_input = __esm({
22691
22841
  });
22692
22842
 
22693
22843
  // apps/desktop/src/daemon/runtime/message-send-operation.ts
22694
- import { createHash as createHash4, randomUUID as randomUUID15 } from "node:crypto";
22844
+ import { createHash as createHash5, randomUUID as randomUUID15 } from "node:crypto";
22695
22845
  function createMessageSendOperation(ports) {
22696
22846
  return async (params, options) => ports.runResponseOperation(async (generation) => {
22697
22847
  const threadId2 = params.threadId;
@@ -22833,7 +22983,7 @@ function createMessageSendOperation(ports) {
22833
22983
  attachmentId: part.attachmentId,
22834
22984
  clientMessageId: clientUserMessageId ?? `legacy-${randomUUID15()}`,
22835
22985
  partIndex,
22836
- sha256: createHash4("sha256").update(Buffer.from(native.url.slice(native.url.indexOf(",") + 1), "base64")).digest("hex")
22986
+ sha256: createHash5("sha256").update(Buffer.from(native.url.slice(native.url.indexOf(",") + 1), "base64")).digest("hex")
22837
22987
  });
22838
22988
  dispatchedImageIds.add(part.attachmentId);
22839
22989
  }
@@ -24390,12 +24540,12 @@ var init_requests = __esm({
24390
24540
  });
24391
24541
 
24392
24542
  // apps/desktop/src/niuma/async-questions.ts
24393
- import { createHash as createHash5 } from "node:crypto";
24543
+ import { createHash as createHash6 } from "node:crypto";
24394
24544
  function asyncQuestionId(rawId, index) {
24395
24545
  if (!rawId || !Number.isSafeInteger(index) || index < 0 || index > 2) {
24396
24546
  throw new TypeError("invalid_async_question_identity");
24397
24547
  }
24398
- return `aq_${createHash5("sha256").update(JSON.stringify([rawId, index])).digest("base64url")}`;
24548
+ return `aq_${createHash6("sha256").update(JSON.stringify([rawId, index])).digest("base64url")}`;
24399
24549
  }
24400
24550
  function exactRecord2(value, keys3) {
24401
24551
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
@@ -24503,9 +24653,9 @@ function resourcePaths(platform2 = process.platform) {
24503
24653
  toLink(value) {
24504
24654
  const parsed = parseLocal(value);
24505
24655
  if (parsed === null) return null;
24506
- const path55 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
24656
+ const path56 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
24507
24657
  try {
24508
- return encodeURIComponent(path55).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
24658
+ return encodeURIComponent(path56).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
24509
24659
  } catch {
24510
24660
  return null;
24511
24661
  }
@@ -24536,7 +24686,7 @@ var init_resource_paths = __esm({
24536
24686
  });
24537
24687
 
24538
24688
  // apps/desktop/src/attachments/file-input.ts
24539
- import { createHash as createHash6 } from "node:crypto";
24689
+ import { createHash as createHash7 } from "node:crypto";
24540
24690
  function desktopFileAttachments(content2) {
24541
24691
  return content2.flatMap((part) => (desktopFiles.get(part) ?? []).map((file) => ({ ...file })));
24542
24692
  }
@@ -24572,12 +24722,12 @@ function nativeInputFingerprint(value) {
24572
24722
  if (previous?.type === "text") previous.value += part.text;
24573
24723
  else canonical.push({ type: "text", value: part.text });
24574
24724
  } else if (part.type === "image" && typeof (part.url ?? part.image_url) === "string") {
24575
- canonical.push({ type: "image", value: createHash6("sha256").update(part.url ?? part.image_url).digest("hex") });
24725
+ canonical.push({ type: "image", value: createHash7("sha256").update(part.url ?? part.image_url).digest("hex") });
24576
24726
  } else if (["localImage", "local_image"].includes(String(part.type)) && typeof part.path === "string") {
24577
24727
  canonical.push({ type: "localImage", value: part.path });
24578
24728
  } else return null;
24579
24729
  }
24580
- return createHash6("sha256").update(JSON.stringify(canonical)).digest("hex");
24730
+ return createHash7("sha256").update(JSON.stringify(canonical)).digest("hex");
24581
24731
  }
24582
24732
  function cloneWithNativeInputEvidence(value) {
24583
24733
  const copy2 = structuredClone(value);
@@ -24648,10 +24798,10 @@ var init_response_annotations = __esm({
24648
24798
  });
24649
24799
 
24650
24800
  // apps/desktop/src/attachments/image-identity.ts
24651
- import { createHash as createHash7 } from "node:crypto";
24652
- function unavailableImageId(path55, itemId, partIndex) {
24653
- const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null, path55]) : path55;
24654
- return `unavailable:${createHash7("sha256").update(identity6).digest("hex")}`;
24801
+ import { createHash as createHash8 } from "node:crypto";
24802
+ function unavailableImageId(path56, itemId, partIndex) {
24803
+ const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null, path56]) : path56;
24804
+ return `unavailable:${createHash8("sha256").update(identity6).digest("hex")}`;
24655
24805
  }
24656
24806
  var init_image_identity = __esm({
24657
24807
  "apps/desktop/src/attachments/image-identity.ts"() {
@@ -24744,15 +24894,15 @@ function normalizeMessageContent(value, resolveKnownLocalImage, itemId, original
24744
24894
  }
24745
24895
  return content2;
24746
24896
  }
24747
- function userFile(name2, path55) {
24897
+ function userFile(name2, path56) {
24748
24898
  const part = { type: "file", name: name2 };
24749
- userFileSource.set(part, path55);
24899
+ userFileSource.set(part, path56);
24750
24900
  return part;
24751
24901
  }
24752
24902
  function userFileSources(content2 = []) {
24753
24903
  return content2.flatMap((part, index) => {
24754
- const path55 = userFileSource.get(part);
24755
- return part.type === "file" && typeof path55 === "string" ? [{ index, path: path55 }] : [];
24904
+ const path56 = userFileSource.get(part);
24905
+ return part.type === "file" && typeof path56 === "string" ? [{ index, path: path56 }] : [];
24756
24906
  });
24757
24907
  }
24758
24908
  function codexImageWrapperFileList(text11) {
@@ -24789,11 +24939,11 @@ function standardCodexImageFileListEntries(fileList) {
24789
24939
  break;
24790
24940
  }
24791
24941
  const name2 = safeCodexFileName(match[1] ?? match[3] ?? "");
24792
- const path55 = match[2] ?? match[4] ?? "";
24793
- if (!name2 || !isRecordedResourcePath(path55)) {
24942
+ const path56 = match[2] ?? match[4] ?? "";
24943
+ if (!name2 || !isRecordedResourcePath(path56)) {
24794
24944
  return null;
24795
24945
  }
24796
- entries.push({ name: name2, path: path55 });
24946
+ entries.push({ name: name2, path: path56 });
24797
24947
  remaining = remaining.slice(match[0].length);
24798
24948
  remaining = remaining.replace(/^Image attachment: true\r?\n/u, "");
24799
24949
  }
@@ -24809,10 +24959,10 @@ function redactCodexImageWrapperPaths(text11) {
24809
24959
  }
24810
24960
  const fileList = wrapper.fileList.replace(
24811
24961
  /(^## [^\r\n]+:[ \t]*\r?\n)[ \t]*([^\r\n]+)/gmu,
24812
- (all, prefix, path55) => isRecordedResourcePath(path55) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24962
+ (all, prefix, path56) => isRecordedResourcePath(path56) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24813
24963
  ).replace(
24814
24964
  /^(## [^\r\n]+:)[ \t]+([^\r\n]+)$/gmu,
24815
- (all, prefix, path55) => isRecordedResourcePath(path55) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24965
+ (all, prefix, path56) => isRecordedResourcePath(path56) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24816
24966
  );
24817
24967
  const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
24818
24968
  return `${wrapper.prefix}${fileList}${text11.slice(fileListEnd)}`;
@@ -24823,7 +24973,7 @@ function redactKnownCodexWrapperPaths(text11, paths) {
24823
24973
  return text11;
24824
24974
  }
24825
24975
  const fileList = paths.reduce(
24826
- (result, path55) => result.replaceAll(path55, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
24976
+ (result, path56) => result.replaceAll(path56, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
24827
24977
  wrapper.fileList
24828
24978
  );
24829
24979
  const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
@@ -24840,8 +24990,8 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
24840
24990
  }
24841
24991
  const localImagePaths = value.flatMap((part) => {
24842
24992
  const record26 = asRecord11(part);
24843
- const path55 = localImagePath(record26);
24844
- return path55 === null ? [] : [path55];
24993
+ const path56 = localImagePath(record26);
24994
+ return path56 === null ? [] : [path56];
24845
24995
  });
24846
24996
  const text11 = redactKnownCodexWrapperPaths(
24847
24997
  redactCodexImageWrapperPaths(firstPart2.text),
@@ -24875,9 +25025,9 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
24875
25025
  const localImages = value.flatMap((part, index) => {
24876
25026
  const partIndex = originalPartIndices?.[index] ?? index;
24877
25027
  const record26 = asRecord11(part);
24878
- const path55 = localImagePath(record26);
24879
- return path55 === null ? [] : [{
24880
- path: path55,
25028
+ const path56 = localImagePath(record26);
25029
+ return path56 === null ? [] : [{
25030
+ path: path56,
24881
25031
  partIndex,
24882
25032
  image: record26.type === "historyImage" ? historyImageContent(record26, itemId, partIndex) : null
24883
25033
  }];
@@ -25006,8 +25156,8 @@ function redactRawLocalImagePaths(rawItem) {
25006
25156
  let containsLocalImage = false;
25007
25157
  let containsRedactedWrapperPath = false;
25008
25158
  const localImagePaths = item.content.map((part) => asRecord11(part)).flatMap((part) => {
25009
- const path55 = localImagePath(part);
25010
- return path55 === null ? [] : [path55];
25159
+ const path56 = localImagePath(part);
25160
+ return path56 === null ? [] : [path56];
25011
25161
  });
25012
25162
  const content2 = item.content.map((part) => {
25013
25163
  const record26 = asRecord11(part);
@@ -25975,8 +26125,8 @@ var init_events = __esm({
25975
26125
  const patches = Array.isArray(change.patches) ? change.patches : [];
25976
26126
  for (const patch of patches) {
25977
26127
  const candidate = objectRecord6(patch);
25978
- const path55 = Array.isArray(candidate.path) ? candidate.path : [];
25979
- if ((candidate.op === "add" || candidate.op === "replace") && path55.length === 1 && path55[0] === "threadRuntimeStatus") {
26128
+ const path56 = Array.isArray(candidate.path) ? candidate.path : [];
26129
+ if ((candidate.op === "add" || candidate.op === "replace") && path56.length === 1 && path56[0] === "threadRuntimeStatus") {
25980
26130
  runtimeStatusValue = candidate.value;
25981
26131
  }
25982
26132
  }
@@ -26943,7 +27093,7 @@ var init_device_upload_cache_policy = __esm({
26943
27093
  });
26944
27094
 
26945
27095
  // apps/desktop/src/attachments/device-upload-cache-store.ts
26946
- import { createHash as createHash8 } from "node:crypto";
27096
+ import { createHash as createHash9 } from "node:crypto";
26947
27097
  async function cacheReadBlock(storage, entry, index, size2) {
26948
27098
  const snapshot2 = await storage.readDocument(entry, 131072);
26949
27099
  const handle = await storage.openContent(entry, { expected: snapshot2.content, match: "object", maxBytes: Math.max(1, size2) });
@@ -26963,12 +27113,12 @@ var init_device_upload_cache_store = __esm({
26963
27113
  "apps/desktop/src/attachments/device-upload-cache-store.ts"() {
26964
27114
  "use strict";
26965
27115
  CACHE_CHUNK_BYTES = 49152;
26966
- cacheDigest = (bytes3) => createHash8("sha256").update(bytes3).digest("hex");
27116
+ cacheDigest = (bytes3) => createHash9("sha256").update(bytes3).digest("hex");
26967
27117
  }
26968
27118
  });
26969
27119
 
26970
27120
  // apps/desktop/src/attachments/device-upload-cache.ts
26971
- import { randomUUID as randomUUID16, createHash as createHash9 } from "node:crypto";
27121
+ import { randomUUID as randomUUID16, createHash as createHash10 } from "node:crypto";
26972
27122
  import { setTimeout as sleep2 } from "node:timers/promises";
26973
27123
  import { z as z9 } from "zod";
26974
27124
  async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVICE_UPLOAD_CACHE_POLICY, admit = async (_bytes, work) => work() }) {
@@ -27040,7 +27190,7 @@ async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVIC
27040
27190
  continue;
27041
27191
  }
27042
27192
  let next = 0;
27043
- const hash3 = createHash9("sha256");
27193
+ const hash3 = createHash10("sha256");
27044
27194
  for (; next < m.chunks.length; next++) {
27045
27195
  try {
27046
27196
  const b = await cacheReadBlock(storage, handle, next, m.key.byteSize);
@@ -27143,7 +27293,7 @@ async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVIC
27143
27293
  seal: (lease) => serial(async () => {
27144
27294
  const e = owned(lease), m = e.manifest;
27145
27295
  if (m.chunks.length !== Math.ceil(m.key.byteSize / CACHE_CHUNK_BYTES)) throw busy();
27146
- const hash3 = createHash9("sha256");
27296
+ const hash3 = createHash10("sha256");
27147
27297
  for (let i = 0; i < m.chunks.length; i++) {
27148
27298
  const b = await cacheReadBlock(storage, e.handle, i, m.key.byteSize);
27149
27299
  if (cacheDigest(b) !== m.chunks[i]) throw busy();
@@ -27979,13 +28129,13 @@ var init_upload_task_store = __esm({
27979
28129
  import { execFile as execFile7 } from "node:child_process";
27980
28130
  import { constants as constants2 } from "node:fs";
27981
28131
  import { lstat, open } from "node:fs/promises";
27982
- import path24 from "node:path";
28132
+ import path25 from "node:path";
27983
28133
  function limit(max) {
27984
28134
  if (!Number.isSafeInteger(max) || max < 1 || max > 50 * 1024 * 1024) throw new PrivateBinaryFileError("capacity");
27985
28135
  }
27986
28136
  function resolved2(file) {
27987
28137
  try {
27988
- return windows() ? localWindowsPath(file) : path24.resolve(file);
28138
+ return windows() ? localWindowsPath(file) : path25.resolve(file);
27989
28139
  } catch {
27990
28140
  throw unavailable2();
27991
28141
  }
@@ -28028,7 +28178,7 @@ async function windowsMode(file, seal = false) {
28028
28178
  return output;
28029
28179
  }
28030
28180
  async function parentIdentity(file) {
28031
- const directory = path24.dirname(file), initial = await lstat(directory, { bigint: true });
28181
+ const directory = path25.dirname(file), initial = await lstat(directory, { bigint: true });
28032
28182
  if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable2();
28033
28183
  if (windows()) {
28034
28184
  try {
@@ -28095,10 +28245,10 @@ async function openFile(file, options) {
28095
28245
  let tail = Promise.resolve();
28096
28246
  async function guard() {
28097
28247
  if (closed || poisoned) throw unavailable2();
28098
- const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory = await lstat(path24.dirname(file), { bigint: true });
28248
+ const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory = await lstat(path25.dirname(file), { bigint: true });
28099
28249
  if (!trusted2(held) || !trusted2(current2) || !same3(held, baseline) || !sameSnapshot(held, current2) || !same3(parent, directory) || !directory.isDirectory() || directory.isSymbolicLink() || held.size > BigInt(options.maxBytes) || (!options.writable || mode === "immutable") && !sameSnapshot(baseline, held)) throw unavailable2();
28100
28250
  if (!windows() && posixMode(held) !== mode) throw unavailable2();
28101
- if (!windows()) privateLogFiles.checkDirectory(path24.dirname(file));
28251
+ if (!windows()) privateLogFiles.checkDirectory(path25.dirname(file));
28102
28252
  }
28103
28253
  await guard();
28104
28254
  checkExpected(await status(h), options);
@@ -28235,11 +28385,11 @@ if($env:NIUMA_BINARY_SEAL -eq '1' -and $mode -ne 'immutable') {
28235
28385
  handle = await open(file, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (windows() ? 0 : constants2.O_NOFOLLOW), 384);
28236
28386
  if (!windows()) await handle.chmod(384);
28237
28387
  const held = await handle.stat({ bigint: true }), current2 = await lstat(file, { bigint: true });
28238
- if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(path24.dirname(file), { bigint: true }))) throw unavailable2();
28388
+ if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(path25.dirname(file), { bigint: true }))) throw unavailable2();
28239
28389
  if (windows() && await windowsMode(file) !== "mutable") throw unavailable2();
28240
28390
  await handle.sync();
28241
28391
  const result = await status(handle);
28242
- if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(path24.dirname(file), { bigint: true }))) throw unavailable2();
28392
+ if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(path25.dirname(file), { bigint: true }))) throw unavailable2();
28243
28393
  await handle.close();
28244
28394
  handle = void 0;
28245
28395
  return result;
@@ -28339,7 +28489,7 @@ import { randomUUID as randomUUID18 } from "node:crypto";
28339
28489
  import { execFile as execFile9 } from "node:child_process";
28340
28490
  import { constants as constants3 } from "node:fs";
28341
28491
  import { chmod, lstat as lstat3, mkdir, open as open2, readdir, rename, rm } from "node:fs/promises";
28342
- import path25 from "node:path";
28492
+ import path26 from "node:path";
28343
28493
  function nameOnly(name2) {
28344
28494
  if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/u.test(name2)) throw unavailable3();
28345
28495
  }
@@ -28348,7 +28498,7 @@ function budget(maxBytes) {
28348
28498
  }
28349
28499
  async function openDirectories(requested, windowsCandidate) {
28350
28500
  const windows2 = process.platform === "win32";
28351
- const root = windows2 ? localWindowsPath(requested) : path25.resolve(requested);
28501
+ const root = windows2 ? localWindowsPath(requested) : path26.resolve(requested);
28352
28502
  let rootIdentity;
28353
28503
  try {
28354
28504
  if (windows2) await ensureWindowsPrivateDirectoryAsync(root);
@@ -28393,7 +28543,7 @@ async function openDirectories(requested, windowsCandidate) {
28393
28543
  }
28394
28544
  function token3(value) {
28395
28545
  const directory = Object.freeze({ get sourcePath() {
28396
- return path25.join(value.path, "source");
28546
+ return path26.join(value.path, "source");
28397
28547
  } });
28398
28548
  records.set(directory, value);
28399
28549
  return directory;
@@ -28449,7 +28599,7 @@ async function openDirectories(requested, windowsCandidate) {
28449
28599
  return serial(async () => {
28450
28600
  nameOnly(name2);
28451
28601
  await guard();
28452
- const directory = path25.join(root, name2);
28602
+ const directory = path26.join(root, name2);
28453
28603
  if (!windows2) privateLogFiles.checkDirectory(directory);
28454
28604
  const identity6 = await lstat3(directory, { bigint: true });
28455
28605
  const result = token3({ name: name2, path: directory, identity: identity6, staged: false, pending: true, ready: true });
@@ -28462,7 +28612,7 @@ async function openDirectories(requested, windowsCandidate) {
28462
28612
  mutable();
28463
28613
  nameOnly(name2);
28464
28614
  await guard();
28465
- const directory = path25.join(root, ".pending-" + name2);
28615
+ const directory = path26.join(root, ".pending-" + name2);
28466
28616
  await mkdir(directory, { mode: 448 });
28467
28617
  const identity6 = await lstat3(directory, { bigint: true });
28468
28618
  if (windows2) {
@@ -28492,7 +28642,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28492
28642
  return serial(async () => {
28493
28643
  budget(maxBytes);
28494
28644
  await guard(directory);
28495
- const handle = await privateBinaryFiles.open(path25.join(record26(directory).path, "manifest.json"), { maxBytes, mode: "mutable" });
28645
+ const handle = await privateBinaryFiles.open(path26.join(record26(directory).path, "manifest.json"), { maxBytes, mode: "mutable" });
28496
28646
  let failed = false;
28497
28647
  const bytes3 = Buffer.alloc(maxBytes);
28498
28648
  try {
@@ -28541,7 +28691,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28541
28691
  async function currentManifest() {
28542
28692
  let stats;
28543
28693
  try {
28544
- stats = await lstat3(path25.join(value.path, "manifest.json"), { bigint: true });
28694
+ stats = await lstat3(path26.join(value.path, "manifest.json"), { bigint: true });
28545
28695
  } catch (error2) {
28546
28696
  if (error2.code === "ENOENT") return null;
28547
28697
  throw error2;
@@ -28549,7 +28699,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28549
28699
  if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n || !windows2 && (stats.uid !== BigInt(process.getuid()) || (stats.mode & 0o777n) !== 0o600n)) throw unavailable3();
28550
28700
  if (stats.size > BigInt(maxBytes)) throw new PrivateUploadDirectoryError("capacity");
28551
28701
  if (windows2) {
28552
- const handle = await privateBinaryFiles.open(path25.join(value.path, "manifest.json"), {
28702
+ const handle = await privateBinaryFiles.open(path26.join(value.path, "manifest.json"), {
28553
28703
  maxBytes,
28554
28704
  mode: "mutable",
28555
28705
  match: "object",
@@ -28566,13 +28716,13 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28566
28716
  } finally {
28567
28717
  await handle.close();
28568
28718
  }
28569
- const after = await lstat3(path25.join(value.path, "manifest.json"), { bigint: true });
28719
+ const after = await lstat3(path26.join(value.path, "manifest.json"), { bigint: true });
28570
28720
  if (!same4(stats, after) || stats.size !== after.size || stats.mtimeNs !== after.mtimeNs || stats.ctimeNs !== after.ctimeNs) throw unavailable3();
28571
28721
  }
28572
28722
  return stats;
28573
28723
  }
28574
28724
  const original = await currentManifest();
28575
- const temporary = path25.join(value.path, ".manifest-" + randomUUID18());
28725
+ const temporary = path26.join(value.path, ".manifest-" + randomUUID18());
28576
28726
  let created = false, published = false, identity6;
28577
28727
  try {
28578
28728
  if (windows2) {
@@ -28627,7 +28777,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28627
28777
  if (!identity6 || !same4(identity6, current2) || !current2.isFile() || current2.isSymbolicLink() || current2.nlink !== 1n || !windows2 && (current2.uid !== BigInt(process.getuid()) || (current2.mode & 0o777n) !== 0o600n)) throw unavailable3();
28628
28778
  const previous = await currentManifest();
28629
28779
  if (original === null ? previous !== null : previous === null || !same4(original, previous) || original.size !== previous.size || original.mtimeNs !== previous.mtimeNs || original.ctimeNs !== previous.ctimeNs) throw unavailable3();
28630
- await rename(temporary, path25.join(value.path, "manifest.json"));
28780
+ await rename(temporary, path26.join(value.path, "manifest.json"));
28631
28781
  published = true;
28632
28782
  created = false;
28633
28783
  value.pending = true;
@@ -28664,7 +28814,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28664
28814
  const value = record26(directory);
28665
28815
  if (!value.staged || !value.ready) throw unavailable3();
28666
28816
  await finish(directory);
28667
- const target = path25.join(root, value.name);
28817
+ const target = path26.join(root, value.name);
28668
28818
  try {
28669
28819
  await lstat3(target);
28670
28820
  throw unavailable3();
@@ -28739,7 +28889,7 @@ var init_private_upload_content_types = __esm({
28739
28889
  });
28740
28890
 
28741
28891
  // apps/desktop/src/platform/legacy-upload-contents.ts
28742
- import { createHash as createHash10 } from "node:crypto";
28892
+ import { createHash as createHash11 } from "node:crypto";
28743
28893
  async function using(handle, operation) {
28744
28894
  let failed = false;
28745
28895
  try {
@@ -29042,14 +29192,14 @@ var init_legacy_upload_contents = __esm({
29042
29192
  init_private_binary_files();
29043
29193
  init_private_upload_directories();
29044
29194
  init_private_upload_content_types();
29045
- revision = (body) => body === null ? "empty" : createHash10("sha256").update(body).digest("hex");
29195
+ revision = (body) => body === null ? "empty" : createHash11("sha256").update(body).digest("hex");
29046
29196
  unavailable4 = () => new PrivateUploadContentError("unavailable");
29047
29197
  }
29048
29198
  });
29049
29199
 
29050
29200
  // apps/desktop/src/daemon/runtime/attachment-access.ts
29051
- import { createHash as createHash11 } from "node:crypto";
29052
- import path26 from "node:path";
29201
+ import { createHash as createHash12 } from "node:crypto";
29202
+ import path27 from "node:path";
29053
29203
  import process2 from "node:process";
29054
29204
  var RuntimeAttachmentAccess;
29055
29205
  var init_attachment_access = __esm({
@@ -29087,7 +29237,7 @@ var init_attachment_access = __esm({
29087
29237
  const cached = createCachedUploadTaskStore({
29088
29238
  base,
29089
29239
  cache: () => cache2 ??= (async () => {
29090
- const root = path26.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
29240
+ const root = path27.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
29091
29241
  return createDeviceUploadCache({
29092
29242
  storage: composeLegacyUploadContents(await openPrivateUploadDirectories(root), privateBinaryFiles),
29093
29243
  admit: (bytes3, operation) => this.ports.attachmentStorage().withAttachmentUploadAdmission(void 0, bytes3, operation)
@@ -29182,7 +29332,7 @@ var init_attachment_access = __esm({
29182
29332
  captureFileResourceSource(threadId2) {
29183
29333
  const generation = this.ports.lifecycle().runtimeGenerationValue, resources = this.ports.projection().resources, viewStore = this.ports.projection().store;
29184
29334
  const source2 = viewStore.getOrderSource(threadId2);
29185
- const projectFingerprint = () => createHash11("sha256").update(this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 })?.projectRoot ?? "").digest("hex");
29335
+ const projectFingerprint = () => createHash12("sha256").update(this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 })?.projectRoot ?? "").digest("hex");
29186
29336
  const project3 = projectFingerprint();
29187
29337
  const appGeneration = this.ports.appServerLoads().connectionGeneration, ipcGeneration = this.ports.desktopSession().ipcConnectionGenerationValue;
29188
29338
  const appAuthority = this.ports.appProjection().authorityFor(threadId2);
@@ -29230,8 +29380,8 @@ var init_attachment_access = __esm({
29230
29380
  });
29231
29381
 
29232
29382
  // apps/desktop/src/niuma/project-state.ts
29233
- import fs17 from "node:fs/promises";
29234
- import path27 from "node:path";
29383
+ import fs18 from "node:fs/promises";
29384
+ import path28 from "node:path";
29235
29385
  import { z as z10 } from "zod";
29236
29386
  function emptyProjectState() {
29237
29387
  return {
@@ -29300,9 +29450,9 @@ function isMissingFileError(error2) {
29300
29450
  return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
29301
29451
  }
29302
29452
  async function readProjectState(codexHome) {
29303
- const statePath = path27.join(codexHome, ".codex-global-state.json");
29453
+ const statePath = path28.join(codexHome, ".codex-global-state.json");
29304
29454
  try {
29305
- const raw = await fs17.readFile(statePath, "utf8");
29455
+ const raw = await fs18.readFile(statePath, "utf8");
29306
29456
  const parsed = RawProjectStateSchema.parse(JSON.parse(raw));
29307
29457
  const localProjects = readLocalProjects(parsed["local-projects"]);
29308
29458
  const rootsByProjectId = new Map(localProjects.map((project3) => [project3.id, project3.root]));
@@ -29395,7 +29545,7 @@ var init_project_state = __esm({
29395
29545
  });
29396
29546
 
29397
29547
  // apps/desktop/src/niuma/session-originator.ts
29398
- import fs18 from "node:fs/promises";
29548
+ import fs19 from "node:fs/promises";
29399
29549
  function record9(value) {
29400
29550
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
29401
29551
  }
@@ -29412,7 +29562,7 @@ async function readFirstLine(filePath) {
29412
29562
  let byteCount = 0;
29413
29563
  let position = 0;
29414
29564
  try {
29415
- handle = await fs18.open(filePath, "r");
29565
+ handle = await fs19.open(filePath, "r");
29416
29566
  while (true) {
29417
29567
  const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
29418
29568
  const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
@@ -29508,7 +29658,7 @@ var init_session_originator = __esm({
29508
29658
  });
29509
29659
 
29510
29660
  // apps/desktop/src/niuma/session-timestamps.ts
29511
- import fs19 from "node:fs/promises";
29661
+ import fs20 from "node:fs/promises";
29512
29662
  import { createInterface as createInterface2 } from "node:readline";
29513
29663
  function record10(value) {
29514
29664
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -29794,7 +29944,7 @@ var init_session_timestamps = __esm({
29794
29944
  try {
29795
29945
  const sessionPath = explicitPath === void 0 ? await this.resolveSessionPath(threadId2) : explicitPath;
29796
29946
  if (!sessionPath || this.closed) return "unavailable";
29797
- const stat3 = await fs19.stat(sessionPath);
29947
+ const stat3 = await fs20.stat(sessionPath);
29798
29948
  if (this.closed) return "unavailable";
29799
29949
  return JSON.stringify([stat3.dev, stat3.ino, stat3.size, stat3.mtimeMs, stat3.ctimeMs]);
29800
29950
  } catch {
@@ -29967,7 +30117,7 @@ var init_session_timestamps = __esm({
29967
30117
  }
29968
30118
  }
29969
30119
  async readReplay(sessionPath, threadId2, fingerprint2, empty) {
29970
- const handle = await fs19.open(sessionPath, "r");
30120
+ const handle = await fs20.open(sessionPath, "r");
29971
30121
  if (this.closed) {
29972
30122
  await handle.close();
29973
30123
  return empty;
@@ -30562,7 +30712,7 @@ var init_app_server_upgrade = __esm({
30562
30712
 
30563
30713
  // apps/desktop/src/daemon/codex-subagent-avatars.ts
30564
30714
  import { open as open3 } from "node:fs/promises";
30565
- import path28 from "node:path";
30715
+ import path29 from "node:path";
30566
30716
  import sharp from "sharp";
30567
30717
  function record11(value) {
30568
30718
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -30603,7 +30753,7 @@ async function parseCatalog(source2, readAsset) {
30603
30753
  }
30604
30754
  return new CodexSubagentAvatars(images);
30605
30755
  }
30606
- async function loadCodexSubagentAvatars(archivePath = path28.join(path28.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
30756
+ async function loadCodexSubagentAvatars(archivePath = path29.join(path29.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
30607
30757
  let file;
30608
30758
  try {
30609
30759
  file = await open3(archivePath, "r");
@@ -30670,8 +30820,8 @@ var init_codex_subagent_avatars = __esm({
30670
30820
  });
30671
30821
 
30672
30822
  // apps/desktop/src/platform/private-document-files.ts
30673
- import fs20 from "node:fs";
30674
- import path29 from "node:path";
30823
+ import fs21 from "node:fs";
30824
+ import path30 from "node:path";
30675
30825
  import { randomUUID as randomUUID20 } from "node:crypto";
30676
30826
  function checkLimit(maxBytes) {
30677
30827
  if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 32 * 1024 * 1024) throw new PrivateDocumentFileError("capacity");
@@ -30683,7 +30833,7 @@ function trusted3(stats, directory = false, strictDirectory = false) {
30683
30833
  }
30684
30834
  function statFile(file, maxBytes) {
30685
30835
  try {
30686
- const stats = fs20.lstatSync(file, { bigint: true });
30836
+ const stats = fs21.lstatSync(file, { bigint: true });
30687
30837
  if (!trusted3(stats)) throw new PrivateDocumentFileError("unavailable");
30688
30838
  if (stats.size > BigInt(maxBytes)) throw new PrivateDocumentFileError("capacity");
30689
30839
  return stats;
@@ -30703,33 +30853,33 @@ function readPosix(file, maxBytes, strictDirectory) {
30703
30853
  let directoryFd;
30704
30854
  let fd;
30705
30855
  try {
30706
- const directory = path29.dirname(file);
30856
+ const directory = path30.dirname(file);
30707
30857
  let parent;
30708
30858
  try {
30709
- parent = fs20.lstatSync(directory, { bigint: true });
30859
+ parent = fs21.lstatSync(directory, { bigint: true });
30710
30860
  } catch (error2) {
30711
30861
  if (missing(error2)) return null;
30712
30862
  throw error2;
30713
30863
  }
30714
30864
  if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
30715
- directoryFd = fs20.openSync(directory, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30716
- if (!same5(parent, fs20.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30865
+ directoryFd = fs21.openSync(directory, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30866
+ if (!same5(parent, fs21.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30717
30867
  const original = statFile(file, maxBytes);
30718
30868
  if (original === null) return null;
30719
- fd = fs20.openSync(file, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30720
- const opened = fs20.fstatSync(fd, { bigint: true });
30869
+ fd = fs21.openSync(file, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30870
+ const opened = fs21.fstatSync(fd, { bigint: true });
30721
30871
  if (!trusted3(opened) || !same5(original, opened) || original.size !== opened.size) throw new PrivateDocumentFileError("unavailable");
30722
30872
  const contents = Buffer.alloc(maxBytes + 1);
30723
30873
  try {
30724
30874
  let length = 0;
30725
30875
  while (length < contents.length) {
30726
- const count = fs20.readSync(fd, contents, length, contents.length - length, null);
30876
+ const count = fs21.readSync(fd, contents, length, contents.length - length, null);
30727
30877
  if (count === 0) break;
30728
30878
  length += count;
30729
30879
  }
30730
30880
  if (length > maxBytes) throw new PrivateDocumentFileError("capacity");
30731
30881
  const current2 = statFile(file, maxBytes);
30732
- if (current2 === null || !same5(original, current2) || !same5(parent, fs20.lstatSync(directory, { bigint: true }))) {
30882
+ if (current2 === null || !same5(original, current2) || !same5(parent, fs21.lstatSync(directory, { bigint: true }))) {
30733
30883
  throw new PrivateDocumentFileError("unavailable");
30734
30884
  }
30735
30885
  return decode(contents.subarray(0, length));
@@ -30738,42 +30888,42 @@ function readPosix(file, maxBytes, strictDirectory) {
30738
30888
  }
30739
30889
  } finally {
30740
30890
  try {
30741
- if (fd !== void 0) fs20.closeSync(fd);
30891
+ if (fd !== void 0) fs21.closeSync(fd);
30742
30892
  } finally {
30743
- if (directoryFd !== void 0) fs20.closeSync(directoryFd);
30893
+ if (directoryFd !== void 0) fs21.closeSync(directoryFd);
30744
30894
  }
30745
30895
  }
30746
30896
  }
30747
30897
  function writePosix(file, body, maxBytes, strictDirectory) {
30748
- const directory = path29.dirname(file);
30749
- const temporary = path29.join(directory, `.${path29.basename(file)}.${randomUUID20()}.tmp`);
30898
+ const directory = path30.dirname(file);
30899
+ const temporary = path30.join(directory, `.${path30.basename(file)}.${randomUUID20()}.tmp`);
30750
30900
  let directoryFd;
30751
30901
  let fd;
30752
30902
  let created = false;
30753
30903
  let renamed = false;
30754
30904
  try {
30755
- fs20.mkdirSync(directory, { recursive: true, mode: 448 });
30756
- const parent = fs20.lstatSync(directory, { bigint: true });
30905
+ fs21.mkdirSync(directory, { recursive: true, mode: 448 });
30906
+ const parent = fs21.lstatSync(directory, { bigint: true });
30757
30907
  if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
30758
- directoryFd = fs20.openSync(directory, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30759
- if (!same5(parent, fs20.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30908
+ directoryFd = fs21.openSync(directory, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30909
+ if (!same5(parent, fs21.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30760
30910
  const original = statFile(file, maxBytes);
30761
- fd = fs20.openSync(temporary, fs20.constants.O_WRONLY | fs20.constants.O_CREAT | fs20.constants.O_EXCL | fs20.constants.O_NOFOLLOW, 384);
30911
+ fd = fs21.openSync(temporary, fs21.constants.O_WRONLY | fs21.constants.O_CREAT | fs21.constants.O_EXCL | fs21.constants.O_NOFOLLOW, 384);
30762
30912
  created = true;
30763
- const temporaryIdentity = fs20.fstatSync(fd, { bigint: true });
30913
+ const temporaryIdentity = fs21.fstatSync(fd, { bigint: true });
30764
30914
  if (!trusted3(temporaryIdentity)) throw new PrivateDocumentFileError("unavailable");
30765
- fs20.writeFileSync(fd, body);
30766
- fs20.fsyncSync(fd);
30767
- fs20.closeSync(fd);
30915
+ fs21.writeFileSync(fd, body);
30916
+ fs21.fsyncSync(fd);
30917
+ fs21.closeSync(fd);
30768
30918
  fd = void 0;
30769
30919
  const current2 = statFile(file, maxBytes);
30770
- if (!same5(parent, fs20.lstatSync(directory, { bigint: true })) || !same5(temporaryIdentity, fs20.lstatSync(temporary, { bigint: true })) || (original === null ? current2 !== null : current2 === null || !same5(original, current2))) {
30920
+ if (!same5(parent, fs21.lstatSync(directory, { bigint: true })) || !same5(temporaryIdentity, fs21.lstatSync(temporary, { bigint: true })) || (original === null ? current2 !== null : current2 === null || !same5(original, current2))) {
30771
30921
  throw new PrivateDocumentFileError("unavailable");
30772
30922
  }
30773
- fs20.renameSync(temporary, file);
30923
+ fs21.renameSync(temporary, file);
30774
30924
  renamed = true;
30775
30925
  created = false;
30776
- fs20.fsyncSync(directoryFd);
30926
+ fs21.fsyncSync(directoryFd);
30777
30927
  } catch (error2) {
30778
30928
  if (error2 instanceof PrivateDocumentFileError && !renamed) throw error2;
30779
30929
  throw new PrivateDocumentFileError("write_failed", renamed);
@@ -30781,7 +30931,7 @@ function writePosix(file, body, maxBytes, strictDirectory) {
30781
30931
  try {
30782
30932
  if (fd !== void 0) {
30783
30933
  try {
30784
- fs20.closeSync(fd);
30934
+ fs21.closeSync(fd);
30785
30935
  } catch {
30786
30936
  }
30787
30937
  }
@@ -30789,14 +30939,14 @@ function writePosix(file, body, maxBytes, strictDirectory) {
30789
30939
  try {
30790
30940
  if (directoryFd !== void 0) {
30791
30941
  try {
30792
- fs20.closeSync(directoryFd);
30942
+ fs21.closeSync(directoryFd);
30793
30943
  } catch {
30794
30944
  }
30795
30945
  }
30796
30946
  } finally {
30797
30947
  if (created) {
30798
30948
  try {
30799
- fs20.unlinkSync(temporary);
30949
+ fs21.unlinkSync(temporary);
30800
30950
  } catch {
30801
30951
  }
30802
30952
  }
@@ -30830,7 +30980,7 @@ async function windowsDocument(file, maxBytes, body) {
30830
30980
  return result;
30831
30981
  }
30832
30982
  function serialFile(file, operation) {
30833
- const absolute = path29.resolve(file);
30983
+ const absolute = path30.resolve(file);
30834
30984
  const key = desktopPlatform().id === "windows" ? absolute.toLowerCase() : absolute;
30835
30985
  const result = (operations.get(key) ?? Promise.resolve()).then(operation);
30836
30986
  const tail = result.then(() => {
@@ -30848,7 +30998,7 @@ function documentFiles(strictDirectory, guard) {
30848
30998
  return serialFile(file, async () => {
30849
30999
  try {
30850
31000
  guard?.();
30851
- const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(path29.resolve(file), maxBytes, strictDirectory);
31001
+ const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(path30.resolve(file), maxBytes, strictDirectory);
30852
31002
  guard?.();
30853
31003
  return body;
30854
31004
  } catch (error2) {
@@ -30863,7 +31013,7 @@ function documentFiles(strictDirectory, guard) {
30863
31013
  await serialFile(file, async () => {
30864
31014
  guard?.();
30865
31015
  if (desktopPlatform().id === "windows") await windowsDocument(file, maxBytes, body);
30866
- else writePosix(path29.resolve(file), body, maxBytes, strictDirectory);
31016
+ else writePosix(path30.resolve(file), body, maxBytes, strictDirectory);
30867
31017
  try {
30868
31018
  guard?.();
30869
31019
  } catch {
@@ -30902,7 +31052,7 @@ var init_private_document_files = __esm({
30902
31052
  });
30903
31053
 
30904
31054
  // apps/desktop/src/local-state/paths.ts
30905
- import path30 from "node:path";
31055
+ import path31 from "node:path";
30906
31056
  function applicationStateDirectory() {
30907
31057
  return desktopPlatform().directories.state;
30908
31058
  }
@@ -30910,37 +31060,37 @@ function cliCacheDirectory() {
30910
31060
  return desktopPlatform().directories.cliCache;
30911
31061
  }
30912
31062
  function managedThreadsStatePath() {
30913
- return path30.join(applicationStateDirectory(), "managed-threads-v1.json");
31063
+ return path31.join(applicationStateDirectory(), "managed-threads-v1.json");
30914
31064
  }
30915
31065
  function threadSettingsStatePath() {
30916
- return path30.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
31066
+ return path31.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
30917
31067
  }
30918
31068
  function threadListStatePath() {
30919
- return path30.join(applicationStateDirectory(), "thread-list-cache-v1.json");
31069
+ return path31.join(applicationStateDirectory(), "thread-list-cache-v1.json");
30920
31070
  }
30921
31071
  function daemonMetricsStatePath() {
30922
- return path30.join(applicationStateDirectory(), "daemon-metrics-v1.json");
31072
+ return path31.join(applicationStateDirectory(), "daemon-metrics-v1.json");
30923
31073
  }
30924
31074
  function desktopIdentityCandidatesStatePath() {
30925
- return path30.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
31075
+ return path31.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
30926
31076
  }
30927
31077
  function pendingRequestsCachePath() {
30928
- return path30.join(cliCacheDirectory(), "pending-requests-v1.json");
31078
+ return path31.join(cliCacheDirectory(), "pending-requests-v1.json");
30929
31079
  }
30930
31080
  function idempotencyCachePath() {
30931
- return path30.join(cliCacheDirectory(), "idempotency-v1.json");
31081
+ return path31.join(cliCacheDirectory(), "idempotency-v1.json");
30932
31082
  }
30933
31083
  function messageSubmissionsStatePath() {
30934
- return path30.join(applicationStateDirectory(), "message-submissions-v1.json");
31084
+ return path31.join(applicationStateDirectory(), "message-submissions-v1.json");
30935
31085
  }
30936
31086
  function deviceNameStatePath() {
30937
- return path30.join(applicationStateDirectory(), "device-name-v1.json");
31087
+ return path31.join(applicationStateDirectory(), "device-name-v1.json");
30938
31088
  }
30939
31089
  function threadReadReceiptsStatePath() {
30940
- return path30.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
31090
+ return path31.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
30941
31091
  }
30942
31092
  function asyncQuestionFactsStatePath() {
30943
- return path30.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
31093
+ return path31.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
30944
31094
  }
30945
31095
  var init_paths2 = __esm({
30946
31096
  "apps/desktop/src/local-state/paths.ts"() {
@@ -32546,7 +32696,7 @@ var init_thread_timeline_cache = __esm({
32546
32696
  });
32547
32697
 
32548
32698
  // apps/desktop/src/daemon/thread-state-store.ts
32549
- import path31 from "node:path";
32699
+ import path32 from "node:path";
32550
32700
  function projectRecency(entry) {
32551
32701
  return entry.threads.reduce(
32552
32702
  (latest, thread4) => Math.max(latest, thread4.recencyAt ?? thread4.updatedAt),
@@ -32655,8 +32805,8 @@ function normalizePathForCompare(value) {
32655
32805
  if (!value) {
32656
32806
  return "";
32657
32807
  }
32658
- const normalized = path31.normalize(value);
32659
- if (normalized.length > 1 && normalized.endsWith(path31.sep)) {
32808
+ const normalized = path32.normalize(value);
32809
+ if (normalized.length > 1 && normalized.endsWith(path32.sep)) {
32660
32810
  return normalized.slice(0, -1);
32661
32811
  }
32662
32812
  return normalized;
@@ -32681,7 +32831,7 @@ function isPathWithinRoot(cwd, root) {
32681
32831
  if (normalizedCwd === normalizedRoot) {
32682
32832
  return true;
32683
32833
  }
32684
- return normalizedCwd.startsWith(`${normalizedRoot}${path31.sep}`);
32834
+ return normalizedCwd.startsWith(`${normalizedRoot}${path32.sep}`);
32685
32835
  }
32686
32836
  function findLongestMatchingRoot(cwd, roots) {
32687
32837
  let matched = null;
@@ -32704,7 +32854,7 @@ function labelForRoot(root, labels) {
32704
32854
  };
32705
32855
  }
32706
32856
  return {
32707
- projectName: path31.basename(root) || root,
32857
+ projectName: path32.basename(root) || root,
32708
32858
  projectNameSource: "basename"
32709
32859
  };
32710
32860
  }
@@ -34212,10 +34362,10 @@ var init_bootstrap = __esm({
34212
34362
  });
34213
34363
 
34214
34364
  // apps/desktop/src/platform/private-cache-files.ts
34215
- import fs21 from "node:fs";
34216
- import path32 from "node:path";
34365
+ import fs22 from "node:fs";
34366
+ import path33 from "node:path";
34217
34367
  function serialize(file, operation) {
34218
- const key = process.platform === "win32" ? path32.resolve(file).toLowerCase() : path32.resolve(file);
34368
+ const key = process.platform === "win32" ? path33.resolve(file).toLowerCase() : path33.resolve(file);
34219
34369
  const next = (tails.get(key) ?? Promise.resolve()).then(operation);
34220
34370
  const tail = next.catch(() => {
34221
34371
  });
@@ -34230,23 +34380,23 @@ function trusted4(stat3, directory = false) {
34230
34380
  return uid !== void 0 && stat3.uid === BigInt(uid) && (directory ? stat3.isDirectory() && (stat3.mode & 0o777n) === 0o700n : stat3.isFile() && stat3.nlink === 1n && (stat3.mode & 0o777n) === 0o600n);
34231
34381
  }
34232
34382
  async function withMacLock(file, operation) {
34233
- const directory = path32.dirname(file);
34234
- const lock = path32.join(directory, `.${path32.basename(file)}.lock`);
34235
- fs21.mkdirSync(directory, { recursive: true, mode: 448 });
34236
- const parent = fs21.lstatSync(directory, { bigint: true });
34383
+ const directory = path33.dirname(file);
34384
+ const lock = path33.join(directory, `.${path33.basename(file)}.lock`);
34385
+ fs22.mkdirSync(directory, { recursive: true, mode: 448 });
34386
+ const parent = fs22.lstatSync(directory, { bigint: true });
34237
34387
  if (!trusted4(parent, true)) throw new PrivateDocumentFileError("unavailable");
34238
34388
  const deadline = Date.now() + LOCK_WAIT_MS;
34239
34389
  let fd;
34240
34390
  for (; ; ) {
34241
34391
  let initial = null;
34242
34392
  try {
34243
- initial = fs21.lstatSync(lock, { bigint: true });
34393
+ initial = fs22.lstatSync(lock, { bigint: true });
34244
34394
  } catch (error2) {
34245
34395
  if (error2.code !== "ENOENT") throw error2;
34246
34396
  }
34247
34397
  if (initial && !trusted4(initial)) throw new PrivateDocumentFileError("unavailable");
34248
34398
  try {
34249
- fd = fs21.openSync(lock, fs21.constants.O_RDWR | fs21.constants.O_CREAT | fs21.constants.O_NOFOLLOW | fs21.constants.O_NONBLOCK | 32, 384);
34399
+ fd = fs22.openSync(lock, fs22.constants.O_RDWR | fs22.constants.O_CREAT | fs22.constants.O_NOFOLLOW | fs22.constants.O_NONBLOCK | 32, 384);
34250
34400
  } catch (error2) {
34251
34401
  const code = error2.code;
34252
34402
  if (code !== "EAGAIN" && code !== "EWOULDBLOCK" || Date.now() >= deadline) throw error2;
@@ -34254,10 +34404,10 @@ async function withMacLock(file, operation) {
34254
34404
  continue;
34255
34405
  }
34256
34406
  try {
34257
- const opened = fs21.fstatSync(fd, { bigint: true });
34407
+ const opened = fs22.fstatSync(fd, { bigint: true });
34258
34408
  const verify = () => {
34259
- const current2 = fs21.lstatSync(lock, { bigint: true });
34260
- const currentParent = fs21.lstatSync(directory, { bigint: true });
34409
+ const current2 = fs22.lstatSync(lock, { bigint: true });
34410
+ const currentParent = fs22.lstatSync(directory, { bigint: true });
34261
34411
  if (!trusted4(opened) || !trusted4(current2) || !same6(opened, current2) || initial !== null && !same6(initial, opened) || !trusted4(currentParent, true) || !same6(parent, currentParent)) {
34262
34412
  throw new PrivateDocumentFileError("unavailable");
34263
34413
  }
@@ -34267,7 +34417,7 @@ async function withMacLock(file, operation) {
34267
34417
  verify();
34268
34418
  return value;
34269
34419
  } finally {
34270
- fs21.closeSync(fd);
34420
+ fs22.closeSync(fd);
34271
34421
  }
34272
34422
  }
34273
34423
  }
@@ -34298,7 +34448,7 @@ var init_private_cache_files = __esm({
34298
34448
  return serialize(file, async () => {
34299
34449
  checkLimit2(maxBytes);
34300
34450
  try {
34301
- fs21.lstatSync(file);
34451
+ fs22.lstatSync(file);
34302
34452
  } catch (error2) {
34303
34453
  if (error2.code === "ENOENT") return null;
34304
34454
  throw error2;
@@ -34311,7 +34461,7 @@ var init_private_cache_files = __esm({
34311
34461
  checkLimit2(maxBytes);
34312
34462
  if (process.platform === "win32") return windowsTransaction(file, maxBytes, transform);
34313
34463
  if (process.platform !== "darwin") throw new PrivateDocumentFileError("unavailable");
34314
- return withMacLock(path32.resolve(file), async (verify) => {
34464
+ return withMacLock(path33.resolve(file), async (verify) => {
34315
34465
  const result = transform(await privateStateFiles.read(file, maxBytes));
34316
34466
  verify();
34317
34467
  if (result.body !== void 0) await privateStateFiles.write(file, Buffer.from(result.body), maxBytes);
@@ -34595,7 +34745,7 @@ var init_pending_cache = __esm({
34595
34745
  });
34596
34746
 
34597
34747
  // apps/desktop/src/niuma/session-pending.ts
34598
- import fs22 from "node:fs";
34748
+ import fs23 from "node:fs";
34599
34749
  function objectRecord7(value) {
34600
34750
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
34601
34751
  }
@@ -34618,7 +34768,7 @@ function inferPendingRequestFromSession(threadId2, sessionPath, latestTurnId = n
34618
34768
  }
34619
34769
  let lines;
34620
34770
  try {
34621
- lines = fs22.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
34771
+ lines = fs23.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
34622
34772
  } catch {
34623
34773
  return null;
34624
34774
  }
@@ -35361,8 +35511,8 @@ var init_catalog = __esm({
35361
35511
  });
35362
35512
 
35363
35513
  // apps/desktop/src/direct-gateway/v5-binding-store.ts
35364
- import { randomUUID as randomUUID21, createHash as createHash12 } from "node:crypto";
35365
- import path33 from "node:path";
35514
+ import { randomUUID as randomUUID21, createHash as createHash13 } from "node:crypto";
35515
+ import path34 from "node:path";
35366
35516
  function bindingFileError() {
35367
35517
  return new Error("Desktop V5 Binding \u6587\u4EF6\u65E0\u6548");
35368
35518
  }
@@ -35496,7 +35646,7 @@ function parseResetMarker(value, desktopId) {
35496
35646
  }
35497
35647
  }
35498
35648
  function resolveDefaultDesktopV5BindingFilePath() {
35499
- return path33.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
35649
+ return path34.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
35500
35650
  }
35501
35651
  function pushDisplayName(name2) {
35502
35652
  let result = "";
@@ -35563,7 +35713,7 @@ var init_v5_binding_store = __esm({
35563
35713
  for (const wake of this.pushWaiters) wake();
35564
35714
  }
35565
35715
  constructor(options = {}) {
35566
- this.filePath = path33.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
35716
+ this.filePath = path34.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
35567
35717
  this.files = options.files ?? privateDocumentFiles;
35568
35718
  }
35569
35719
  async load(desktopId) {
@@ -35626,7 +35776,7 @@ var init_v5_binding_store = __esm({
35626
35776
  revision: this.presence.revision,
35627
35777
  grants: this.presence.grants.map((row) => ({
35628
35778
  grant_id: row.grant.grant_id,
35629
- token_sha256: createHash12("sha256").update(row.grant.token, "utf8").digest("base64url"),
35779
+ token_sha256: createHash13("sha256").update(row.grant.token, "utf8").digest("base64url"),
35630
35780
  binding_id: row.binding_id,
35631
35781
  generation: row.generation,
35632
35782
  expires_at: row.grant.expires_at
@@ -35813,7 +35963,7 @@ var init_v5_binding_store = __esm({
35813
35963
  await this.writeAtomicFile(this.resetMarkerPath(), serializeResetMarker(desktopId), bindingFileError);
35814
35964
  }
35815
35965
  resetMarkerPath() {
35816
- return path33.join(path33.dirname(this.filePath), RESET_MARKER_FILE_NAME);
35966
+ return path34.join(path34.dirname(this.filePath), RESET_MARKER_FILE_NAME);
35817
35967
  }
35818
35968
  async writeAtomicFile(targetPath, body, failure) {
35819
35969
  try {
@@ -35944,7 +36094,7 @@ var init_desktop_service = __esm({
35944
36094
  });
35945
36095
 
35946
36096
  // apps/desktop/src/presence/server-client.ts
35947
- import { createHash as createHash13, randomBytes as randomBytes5, randomUUID as randomUUID22 } from "node:crypto";
36097
+ import { createHash as createHash14, randomBytes as randomBytes5, randomUUID as randomUUID22 } from "node:crypto";
35948
36098
  var PresenceServerClient;
35949
36099
  var init_server_client2 = __esm({
35950
36100
  "apps/desktop/src/presence/server-client.ts"() {
@@ -35967,14 +36117,14 @@ var init_server_client2 = __esm({
35967
36117
  if (snapshot2.desktop_id !== this.identity.desktop_id || snapshot2.public_key !== encodeBase64Url(this.identity.identity_public_key)) throw new HttpApiError(200, 200004, "\u65E0\u6743\u9650\u8BBF\u95EE");
35968
36118
  const body = JSON.stringify(snapshot2), pathname = "/api/v1/presence/desktops/grants/sync";
35969
36119
  if (Buffer.byteLength(body) > 65536) throw new HttpApiError(200, 900608, "\u8BBE\u5907\u72B6\u6001\u67E5\u8BE2\u9891\u7387\u6216\u5BB9\u91CF\u8D85\u9650");
35970
- const key_id = createHash13("sha256").update(this.identity.identity_public_key).digest("base64url");
36120
+ const key_id = createHash14("sha256").update(this.identity.identity_public_key).digest("base64url");
35971
36121
  const operation_id = randomUUID22(), nonce = encodeBase64Url(randomBytes5(32)), timestamp = Math.floor(Date.now() / 1e3);
35972
36122
  const bytes3 = createPresenceSigningBytes({
35973
36123
  audience: this.origin,
35974
36124
  method: "POST",
35975
36125
  pathname,
35976
36126
  query: {},
35977
- body_sha256: createHash13("sha256").update(body).digest("base64url"),
36127
+ body_sha256: createHash14("sha256").update(body).digest("base64url"),
35978
36128
  key_id,
35979
36129
  operation_id,
35980
36130
  timestamp,
@@ -36123,7 +36273,7 @@ var init_binding_sync = __esm({
36123
36273
  });
36124
36274
 
36125
36275
  // apps/desktop/src/notifications/desktop-service.ts
36126
- import { createHash as createHash14 } from "node:crypto";
36276
+ import { createHash as createHash15 } from "node:crypto";
36127
36277
  var DesktopNotificationService;
36128
36278
  var init_desktop_service2 = __esm({
36129
36279
  "apps/desktop/src/notifications/desktop-service.ts"() {
@@ -36159,7 +36309,7 @@ var init_desktop_service2 = __esm({
36159
36309
  if (remaining <= 0) throw new NotificationTransportError("business_error", 200, 901002);
36160
36310
  const bounded = signal ? AbortSignal.any([signal, AbortSignal.timeout(Math.min(remaining, 12e3))]) : AbortSignal.timeout(Math.min(remaining, 12e3));
36161
36311
  const data = request2.data;
36162
- const event = parsePushEventInput({ desktop_id: this.identity.desktop_id, event_id: createHash14("sha256").update(JSON.stringify([data.event_type, data.thread_id, data.turn_id ?? data.request_id])).digest("base64url"), notification: request2.notification, data: { ...data, version: 1 }, trace: request2.trace });
36312
+ const event = parsePushEventInput({ desktop_id: this.identity.desktop_id, event_id: createHash15("sha256").update(JSON.stringify([data.event_type, data.thread_id, data.turn_id ?? data.request_id])).digest("base64url"), notification: request2.notification, data: { ...data, version: 1 }, trace: request2.trace });
36163
36313
  do {
36164
36314
  if (Date.now() >= (request2.trace?.deadline_at_ms ?? 0)) throw new NotificationTransportError("business_error", 200, 901002);
36165
36315
  if (bounded.aborted) throw new NotificationTransportError("business_error", 200, 900004);
@@ -37155,7 +37305,7 @@ var init_device_connection_stream2 = __esm({
37155
37305
  });
37156
37306
 
37157
37307
  // apps/desktop/src/remote-session/idempotency.ts
37158
- import { createHash as createHash15 } from "node:crypto";
37308
+ import { createHash as createHash16 } from "node:crypto";
37159
37309
  var REMOTE_SESSION_MAX_IDEMPOTENT_WRITES_PER_BINDING, REMOTE_SESSION_IDEMPOTENT_WRITE_TTL_MS, RemoteSessionIdempotency;
37160
37310
  var init_idempotency = __esm({
37161
37311
  "apps/desktop/src/remote-session/idempotency.ts"() {
@@ -37174,7 +37324,7 @@ var init_idempotency = __esm({
37174
37324
  }
37175
37325
  run(input) {
37176
37326
  const now = this.nowMs();
37177
- const fingerprint2 = createHash15("sha256").update(canonicalizeJson(input.payload)).digest("hex");
37327
+ const fingerprint2 = createHash16("sha256").update(canonicalizeJson(input.payload)).digest("hex");
37178
37328
  const cacheKey = input.scope_id === void 0 ? input.request_id : `${input.scope_id}\0${input.request_id}`;
37179
37329
  const bindingEntries = this.entries.get(input.binding_id) ?? /* @__PURE__ */ new Map();
37180
37330
  this.removeExpired(input.binding_id, bindingEntries, now);
@@ -41018,7 +41168,7 @@ var init_candidate_catalog2 = __esm({
41018
41168
  });
41019
41169
 
41020
41170
  // apps/desktop/src/direct-gateway/identity-store.ts
41021
- import path34 from "node:path";
41171
+ import path35 from "node:path";
41022
41172
  function copyIdentity(identity6) {
41023
41173
  return {
41024
41174
  desktop_id: identity6.desktop_id,
@@ -41073,7 +41223,7 @@ function deserializeIdentity(value) {
41073
41223
  }
41074
41224
  }
41075
41225
  function resolveDefaultDesktopIdentityFilePath() {
41076
- return path34.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
41226
+ return path35.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
41077
41227
  }
41078
41228
  var IDENTITY_KEY_BYTES2, DEFAULT_IDENTITY_FILE_NAME, MAX_IDENTITY_BYTES, FileDesktopIdentityStore;
41079
41229
  var init_identity_store = __esm({
@@ -41089,7 +41239,7 @@ var init_identity_store = __esm({
41089
41239
  filePath;
41090
41240
  files;
41091
41241
  constructor(options = {}) {
41092
- this.filePath = path34.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
41242
+ this.filePath = path35.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
41093
41243
  this.files = options.files ?? privateDocumentFiles;
41094
41244
  }
41095
41245
  async load() {
@@ -44443,17 +44593,6 @@ var init_settings = __esm({
44443
44593
  }
44444
44594
  });
44445
44595
 
44446
- // apps/desktop/src/assets.ts
44447
- function desktopAssetUrl(area, file) {
44448
- const release2 = true;
44449
- return new URL(release2 ? `./assets/${area}/${file}` : `./${area}/static/${file}`, import.meta.url);
44450
- }
44451
- var init_assets = __esm({
44452
- "apps/desktop/src/assets.ts"() {
44453
- "use strict";
44454
- }
44455
- });
44456
-
44457
44596
  // apps/desktop/src/pairing-web/auth.ts
44458
44597
  function authorizePairingRequest(request2, port, api) {
44459
44598
  const origin3 = `http://127.0.0.1:${port}`;
@@ -44572,7 +44711,7 @@ var init_routes3 = __esm({
44572
44711
 
44573
44712
  // apps/desktop/src/pairing-web/server.ts
44574
44713
  import http3 from "node:http";
44575
- import fs23 from "node:fs/promises";
44714
+ import fs24 from "node:fs/promises";
44576
44715
  var ASSETS, PairingWebServer;
44577
44716
  var init_server3 = __esm({
44578
44717
  "apps/desktop/src/pairing-web/server.ts"() {
@@ -44656,7 +44795,7 @@ var init_server3 = __esm({
44656
44795
  }
44657
44796
  const asset = ASSETS[raw];
44658
44797
  if (request2.method !== "GET" || !asset) throw new HttpApiError(404, 900005, "\u63A5\u53E3\u4E0D\u5B58\u5728");
44659
- const body = await fs23.readFile(desktopAssetUrl("pairing-web", asset[0]));
44798
+ const body = await fs24.readFile(desktopAssetUrl("pairing-web", asset[0]));
44660
44799
  response.writeHead(200, { "Content-Type": asset[1] });
44661
44800
  response.end(body);
44662
44801
  } catch (error2) {
@@ -46439,21 +46578,21 @@ var init_desktop_timeline_events = __esm({
46439
46578
  if (patch.op !== "add" && patch.op !== "replace") {
46440
46579
  continue;
46441
46580
  }
46442
- const path55 = array2(patch.path);
46443
- if (path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string") {
46581
+ const path56 = array2(patch.path);
46582
+ if (path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string") {
46444
46583
  const turnId = turnIdFromEntity(record14(patch.value));
46445
46584
  if (turnId) {
46446
- this.entityTurnIds.set(this.entityKey(threadId2, path55[3]), turnId);
46585
+ this.entityTurnIds.set(this.entityKey(threadId2, path56[3]), turnId);
46447
46586
  }
46448
46587
  continue;
46449
46588
  }
46450
- if (path55.length !== 6 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof path55[5] !== "number") {
46589
+ if (path56.length !== 6 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof path56[5] !== "number") {
46451
46590
  continue;
46452
46591
  }
46453
46592
  const occurredAt4 = Math.floor((this.options.now ?? Date.now)() / 1e3);
46454
46593
  const item = normalizeTimelineItem(patch.value, {
46455
46594
  threadId: threadId2,
46456
- turnId: this.entityTurnIds.get(this.entityKey(threadId2, path55[3])) ?? null,
46595
+ turnId: this.entityTurnIds.get(this.entityKey(threadId2, path56[3])) ?? null,
46457
46596
  source: "desktop_ipc",
46458
46597
  occurredAt: occurredAt4,
46459
46598
  resolveKnownLocalImage
@@ -46499,8 +46638,8 @@ function assignKnownUnreadFields(target, value) {
46499
46638
  target.unreadMessageCount = value.unreadMessageCount;
46500
46639
  }
46501
46640
  }
46502
- function isUnreadFieldPath(path55, field2) {
46503
- return path55.length === 1 && path55[0] === field2 || path55.length === 2 && path55[0] === "conversationState" && path55[1] === field2;
46641
+ function isUnreadFieldPath(path56, field2) {
46642
+ return path56.length === 1 && path56[0] === field2 || path56.length === 2 && path56[0] === "conversationState" && path56[1] === field2;
46504
46643
  }
46505
46644
  function hasUpdateFields(update) {
46506
46645
  return "hasUnreadTurn" in update || "unreadMessageCount" in update;
@@ -46526,19 +46665,19 @@ function extractDesktopUnreadUpdate(frame) {
46526
46665
  }
46527
46666
  for (const patchValue of change.patches) {
46528
46667
  const patch = record15(patchValue);
46529
- const path55 = Array.isArray(patch.path) ? patch.path : [];
46668
+ const path56 = Array.isArray(patch.path) ? patch.path : [];
46530
46669
  const op = patch.op;
46531
46670
  if (op !== "add" && op !== "replace" && op !== "remove") {
46532
46671
  continue;
46533
46672
  }
46534
- if (isUnreadFieldPath(path55, "hasUnreadTurn")) {
46673
+ if (isUnreadFieldPath(path56, "hasUnreadTurn")) {
46535
46674
  if (op === "remove") {
46536
46675
  update.hasUnreadTurn = null;
46537
46676
  } else if (typeof patch.value === "boolean") {
46538
46677
  update.hasUnreadTurn = patch.value;
46539
46678
  }
46540
46679
  }
46541
- if (isUnreadFieldPath(path55, "unreadMessageCount")) {
46680
+ if (isUnreadFieldPath(path56, "unreadMessageCount")) {
46542
46681
  if (op === "remove") {
46543
46682
  update.unreadMessageCount = null;
46544
46683
  } else if (isMessageCount(patch.value)) {
@@ -47235,15 +47374,15 @@ function revisionOf(value) {
47235
47374
  function occurredAt() {
47236
47375
  return Math.floor(Date.now() / 1e3);
47237
47376
  }
47238
- function itemTarget(path55) {
47239
- const index = path55[5];
47240
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof index !== "number" || !Number.isInteger(index) || index < 0) {
47377
+ function itemTarget(path56) {
47378
+ const index = path56[5];
47379
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof index !== "number" || !Number.isInteger(index) || index < 0) {
47241
47380
  return null;
47242
47381
  }
47243
- return { entityKey: path55[3], index, itemPathLength: 6 };
47382
+ return { entityKey: path56[3], index, itemPathLength: 6 };
47244
47383
  }
47245
- function entityTarget(path55) {
47246
- return path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string" ? path55[3] : null;
47384
+ function entityTarget(path56) {
47385
+ return path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string" ? path56[3] : null;
47247
47386
  }
47248
47387
  function phaseOf(status2) {
47249
47388
  if (status2 === "failed" || status2 === "error") {
@@ -47529,15 +47668,15 @@ var init_desktop_activity_events = __esm({
47529
47668
  if (patch.op !== "add" && patch.op !== "replace") {
47530
47669
  continue;
47531
47670
  }
47532
- const path55 = array3(patch.path);
47533
- const targetItem = itemTarget(path55);
47671
+ const path56 = array3(patch.path);
47672
+ const targetItem = itemTarget(path56);
47534
47673
  if (targetItem) {
47535
- signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path55, patch.value, patch.op));
47674
+ signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path56, patch.value, patch.op));
47536
47675
  continue;
47537
47676
  }
47538
- const targetEntity = entityTarget(path55);
47677
+ const targetEntity = entityTarget(path56);
47539
47678
  if (targetEntity) {
47540
- signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path55, patch.value));
47679
+ signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path56, patch.value));
47541
47680
  }
47542
47681
  }
47543
47682
  return signals;
@@ -47611,12 +47750,12 @@ var init_desktop_activity_events = __esm({
47611
47750
  occurredAt: occurredAt()
47612
47751
  }];
47613
47752
  }
47614
- consumeItemPatch(threadId2, state, target, path55, value, op) {
47753
+ consumeItemPatch(threadId2, state, target, path56, value, op) {
47615
47754
  const entity = state.entities.get(target.entityKey);
47616
47755
  if (!entity || state.currentActiveEntityKey !== target.entityKey || state.currentActiveTurnId !== entity.turnId) {
47617
47756
  return [];
47618
47757
  }
47619
- if (path55.length === target.itemPathLength) {
47758
+ if (path56.length === target.itemPathLength) {
47620
47759
  return this.prependLiveTurnStart(threadId2, entity, this.consumeWholeItem(
47621
47760
  threadId2,
47622
47761
  entity,
@@ -47626,13 +47765,13 @@ var init_desktop_activity_events = __esm({
47626
47765
  ));
47627
47766
  }
47628
47767
  const existing = entity.items.get(target.index);
47629
- if (!existing || path55.length < target.itemPathLength + 1) {
47768
+ if (!existing || path56.length < target.itemPathLength + 1) {
47630
47769
  return [];
47631
47770
  }
47632
- const field2 = path55[target.itemPathLength];
47771
+ const field2 = path56[target.itemPathLength];
47633
47772
  if (existing.type === "reasoning" && field2 === "summary") {
47634
47773
  const summary = structuredClone(existing.summary ?? []);
47635
- const suffix = path55.slice(target.itemPathLength + 1);
47774
+ const suffix = path56.slice(target.itemPathLength + 1);
47636
47775
  if (suffix.length === 0) {
47637
47776
  existing.summary = structuredClone(Array.isArray(value) ? value : [value]);
47638
47777
  } else {
@@ -47732,9 +47871,9 @@ var init_desktop_activity_events = __esm({
47732
47871
  });
47733
47872
  return [this.activitySignal(threadId2, entity.turnId, itemId, mapping)];
47734
47873
  }
47735
- consumeEntityPatch(threadId2, state, entityKey, path55, value) {
47736
- const wholeEntity = path55.length === 4;
47737
- const statusField = path55.length === 5 && path55[4] === "status";
47874
+ consumeEntityPatch(threadId2, state, entityKey, path56, value) {
47875
+ const wholeEntity = path56.length === 4;
47876
+ const statusField = path56.length === 5 && path56[4] === "status";
47738
47877
  if (!wholeEntity && !statusField) {
47739
47878
  return [];
47740
47879
  }
@@ -47914,20 +48053,20 @@ var init_desktop_error_events = __esm({
47914
48053
  if (patch.op !== "add" && patch.op !== "replace") {
47915
48054
  continue;
47916
48055
  }
47917
- const path55 = array4(patch.path);
47918
- if (path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string") {
48056
+ const path56 = array4(patch.path);
48057
+ if (path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string") {
47919
48058
  const entity = record17(patch.value);
47920
48059
  const turnId2 = turnIdFromEntity2(entity);
47921
48060
  if (turnId2) {
47922
- this.entityTurnIds.set(this.entityKey(threadId2, path55[3]), turnId2);
48061
+ this.entityTurnIds.set(this.entityKey(threadId2, path56[3]), turnId2);
47923
48062
  events.push(...this.errorEvents(threadId2, array4(entity.items), turnId2));
47924
48063
  }
47925
48064
  continue;
47926
48065
  }
47927
- if (path55.length !== 6 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof path55[5] !== "number") {
48066
+ if (path56.length !== 6 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof path56[5] !== "number") {
47928
48067
  continue;
47929
48068
  }
47930
- const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path55[3]));
48069
+ const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path56[3]));
47931
48070
  if (!turnId) {
47932
48071
  continue;
47933
48072
  }
@@ -48020,13 +48159,13 @@ function visibleMessage(value, resolveKnownLocalImage) {
48020
48159
  function occurredAt2() {
48021
48160
  return Math.floor(Date.now() / 1e3);
48022
48161
  }
48023
- function itemPath(path55) {
48024
- const index = path55.lastIndexOf("items");
48025
- const itemIndex = path55[index + 1];
48026
- return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 && path55.length >= index + 2 ? path55.slice(0, index + 2) : null;
48162
+ function itemPath(path56) {
48163
+ const index = path56.lastIndexOf("items");
48164
+ const itemIndex = path56[index + 1];
48165
+ return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 && path56.length >= index + 2 ? path56.slice(0, index + 2) : null;
48027
48166
  }
48028
- function stateKey(threadId2, path55) {
48029
- return `${threadId2}:${JSON.stringify(path55)}`;
48167
+ function stateKey(threadId2, path56) {
48168
+ return `${threadId2}:${JSON.stringify(path56)}`;
48030
48169
  }
48031
48170
  function completedKey(threadId2, itemId) {
48032
48171
  return `${threadId2}:${itemId}`;
@@ -48084,35 +48223,35 @@ var init_desktop_stream_events = __esm({
48084
48223
  if (op !== "add" && op !== "replace" && op !== "remove") {
48085
48224
  continue;
48086
48225
  }
48087
- const path55 = array5(patch.path);
48088
- if (path55[0] === "turnHistory" && (path55.length === 1 || path55[1] === "history" && (path55.length === 2 || path55[2] === "entitiesByKey" && path55.length === 3))) {
48226
+ const path56 = array5(patch.path);
48227
+ if (path56[0] === "turnHistory" && (path56.length === 1 || path56[1] === "history" && (path56.length === 2 || path56[2] === "entitiesByKey" && path56.length === 3))) {
48089
48228
  this.resetThread(threadId2);
48090
48229
  continue;
48091
48230
  }
48092
- if (path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey") {
48093
- const values = path55.length === 4 ? record18(patch.value).items : path55.length === 5 && path55[4] === "items" ? patch.value : void 0;
48094
- if (path55.length === 4 || path55.length === 5 && path55[4] === "items") {
48095
- const arrayPath = path55.slice(0, 4).concat("items");
48231
+ if (path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey") {
48232
+ const values = path56.length === 4 ? record18(patch.value).items : path56.length === 5 && path56[4] === "items" ? patch.value : void 0;
48233
+ if (path56.length === 4 || path56.length === 5 && path56[4] === "items") {
48234
+ const arrayPath = path56.slice(0, 4).concat("items");
48096
48235
  this.replaceArrayStates(threadId2, arrayPath, array5(values), resolveKnownLocalImage);
48097
48236
  continue;
48098
48237
  }
48099
48238
  }
48100
- const rawIndex = path55.lastIndexOf("items") + 1;
48101
- if (op === "add" && path55[rawIndex] === "-" && path55.length === rawIndex + 1) {
48102
- const length = this.arrayLengths.get(stateKey(threadId2, path55.slice(0, rawIndex)));
48239
+ const rawIndex = path56.lastIndexOf("items") + 1;
48240
+ if (op === "add" && path56[rawIndex] === "-" && path56.length === rawIndex + 1) {
48241
+ const length = this.arrayLengths.get(stateKey(threadId2, path56.slice(0, rawIndex)));
48103
48242
  if (length === void 0) continue;
48104
- path55[rawIndex] = length;
48243
+ path56[rawIndex] = length;
48105
48244
  }
48106
- const targetItemPath = itemPath(path55);
48245
+ const targetItemPath = itemPath(path56);
48107
48246
  if (!targetItemPath) {
48108
48247
  continue;
48109
48248
  }
48110
48249
  const key = stateKey(threadId2, targetItemPath);
48111
- if (path55.length > targetItemPath.length && ["id", "type"].includes(String(path55[targetItemPath.length]))) {
48250
+ if (path56.length > targetItemPath.length && ["id", "type"].includes(String(path56[targetItemPath.length]))) {
48112
48251
  this.states.delete(key);
48113
48252
  continue;
48114
48253
  }
48115
- if (path55.length === targetItemPath.length) {
48254
+ if (path56.length === targetItemPath.length) {
48116
48255
  const arrayPath = targetItemPath.slice(0, -1);
48117
48256
  const index = targetItemPath.at(-1);
48118
48257
  if (op === "add" || op === "remove") this.shiftArrayStates(threadId2, arrayPath, index, op);
@@ -48127,7 +48266,7 @@ var init_desktop_stream_events = __esm({
48127
48266
  ));
48128
48267
  continue;
48129
48268
  }
48130
- if (op === "replace" && path55.length === targetItemPath.length + 1 && path55.at(-1) === "text") {
48269
+ if (op === "replace" && path56.length === targetItemPath.length + 1 && path56.at(-1) === "text") {
48131
48270
  events.push(...this.consumeTextPatch(threadId2, key, patch.value, revision4));
48132
48271
  }
48133
48272
  }
@@ -48139,9 +48278,9 @@ var init_desktop_stream_events = __esm({
48139
48278
  const prefix = JSON.stringify(arrayPath);
48140
48279
  for (const [key2, state] of this.states) {
48141
48280
  if (state.threadId !== threadId2) continue;
48142
- const path55 = JSON.parse(key2.slice(threadId2.length + 1));
48143
- const at = path55.at(-1);
48144
- if (JSON.stringify(path55.slice(0, -1)) !== prefix || typeof at !== "number" || at < index) continue;
48281
+ const path56 = JSON.parse(key2.slice(threadId2.length + 1));
48282
+ const at = path56.at(-1);
48283
+ if (JSON.stringify(path56.slice(0, -1)) !== prefix || typeof at !== "number" || at < index) continue;
48145
48284
  this.states.delete(key2);
48146
48285
  if (op === "remove" && at === index) continue;
48147
48286
  moved.push([stateKey(threadId2, [...arrayPath, at + (op === "add" ? 1 : -1)]), state]);
@@ -48152,20 +48291,20 @@ var init_desktop_stream_events = __esm({
48152
48291
  if (length !== void 0) this.arrayLengths.set(key, Math.max(0, length + (op === "add" ? 1 : -1)));
48153
48292
  }
48154
48293
  /** 完整数组只重播种本实体的路径;其他轮的正文和按原生身份记录的完成事实不变。 */
48155
- replaceArrayStates(threadId2, path55, values, resolveKnownLocalImage) {
48156
- const prefix = JSON.stringify(path55);
48294
+ replaceArrayStates(threadId2, path56, values, resolveKnownLocalImage) {
48295
+ const prefix = JSON.stringify(path56);
48157
48296
  for (const [key, state] of this.states) {
48158
48297
  if (state.threadId !== threadId2) continue;
48159
48298
  const itemPath2 = JSON.parse(key.slice(threadId2.length + 1));
48160
48299
  if (JSON.stringify(itemPath2.slice(0, -1)) === prefix) this.states.delete(key);
48161
48300
  }
48162
- this.arrayLengths.set(stateKey(threadId2, path55), values.length);
48301
+ this.arrayLengths.set(stateKey(threadId2, path56), values.length);
48163
48302
  values.forEach((value, index) => {
48164
48303
  const message = visibleMessage(value, resolveKnownLocalImage);
48165
48304
  if (!message) return;
48166
48305
  if (message.role === "user") this.completed.add(completedKey(threadId2, message.itemId));
48167
48306
  else if (!this.completed.has(completedKey(threadId2, message.itemId))) {
48168
- this.states.set(stateKey(threadId2, [...path55, index]), { threadId: threadId2, ...message, lastText: message.text });
48307
+ this.states.set(stateKey(threadId2, [...path56, index]), { threadId: threadId2, ...message, lastText: message.text });
48169
48308
  }
48170
48309
  });
48171
48310
  }
@@ -48464,7 +48603,7 @@ var init_method_codecs = __esm({
48464
48603
  });
48465
48604
 
48466
48605
  // apps/desktop/src/desktop-ipc/profiles.ts
48467
- import { createHash as createHash16 } from "node:crypto";
48606
+ import { createHash as createHash17 } from "node:crypto";
48468
48607
  function method(name2, direction, version2, codec = {}, receiveOnly = false) {
48469
48608
  return {
48470
48609
  method: name2,
@@ -48514,7 +48653,7 @@ var init_profiles = __esm({
48514
48653
  id: "current-methods-2026-10-20",
48515
48654
  version: "1.0",
48516
48655
  // codec 修订随方案发布固定,不能从函数源码生成不稳定指纹。
48517
- fingerprint: createHash16("sha256").update(JSON.stringify({ codecRevision: "1.0", methods: definitions.map((d) => [d.method, d.direction, d.sendVersion, d.acceptedVersions]) })).digest("hex"),
48656
+ fingerprint: createHash17("sha256").update(JSON.stringify({ codecRevision: "1.0", methods: definitions.map((d) => [d.method, d.direction, d.sendVersion, d.acceptedVersions]) })).digest("hex"),
48518
48657
  methods: new Map(definitions.map((value) => [value.method, value])),
48519
48658
  // 当前只有安装包静态核对与回归;实际 Desktop 业务验收完成前不登记 verifiedDesktop。
48520
48659
  verifiedDesktop: []
@@ -49290,8 +49429,8 @@ var init_socket_client = __esm({
49290
49429
  this.diagnosticProfile = diagnosticProfile;
49291
49430
  this.socketPaths = socketPath ? [socketPath] : defaultSocketPaths;
49292
49431
  const reader = new DesktopRuntimeVersionReader();
49293
- this.runtimeVersion = new RuntimeVersionCache(async (path55, signal) => {
49294
- const value = versionReader ? await versionReader(path55, signal) : await reader.read(path55, signal);
49432
+ this.runtimeVersion = new RuntimeVersionCache(async (path56, signal) => {
49433
+ const value = versionReader ? await versionReader(path56, signal) : await reader.read(path56, signal);
49295
49434
  return typeof value === "string" ? { version: value, build: null } : value;
49296
49435
  });
49297
49436
  }
@@ -51577,8 +51716,8 @@ var init_desktop_read_refresh_queue = __esm({
51577
51716
  // apps/desktop/src/daemon/desktop-read-state-file.ts
51578
51717
  import { watch } from "node:fs";
51579
51718
  import { open as open4, stat as statPath } from "node:fs/promises";
51580
- import { createHash as createHash17 } from "node:crypto";
51581
- import path35 from "node:path";
51719
+ import { createHash as createHash18 } from "node:crypto";
51720
+ import path36 from "node:path";
51582
51721
  function record20(value) {
51583
51722
  return !!value && typeof value === "object" && !Array.isArray(value);
51584
51723
  }
@@ -51620,7 +51759,7 @@ var LOCAL_STDIO_HOST, MAX_BYTES2, DesktopReadStateFile;
51620
51759
  var init_desktop_read_state_file = __esm({
51621
51760
  "apps/desktop/src/daemon/desktop-read-state-file.ts"() {
51622
51761
  "use strict";
51623
- LOCAL_STDIO_HOST = `local:${createHash17("sha256").update(JSON.stringify(["local", "local", null])).digest("hex")}`;
51762
+ LOCAL_STDIO_HOST = `local:${createHash18("sha256").update(JSON.stringify(["local", "local", null])).digest("hex")}`;
51624
51763
  MAX_BYTES2 = 16 * 1024 * 1024;
51625
51764
  DesktopReadStateFile = class {
51626
51765
  constructor(home, changed2, options = {}) {
@@ -51722,7 +51861,7 @@ var init_desktop_read_state_file = __esm({
51722
51861
  async readOnce() {
51723
51862
  this.checks++;
51724
51863
  try {
51725
- const filePath = path35.join(this.home, ".codex-global-state.json");
51864
+ const filePath = path36.join(this.home, ".codex-global-state.json");
51726
51865
  const file = await open4(filePath, "r");
51727
51866
  let raw, signature;
51728
51867
  try {
@@ -53568,9 +53707,9 @@ var init_protocol = __esm({
53568
53707
 
53569
53708
  // apps/desktop/src/daemon/server.ts
53570
53709
  import { randomUUID as randomUUID32 } from "node:crypto";
53571
- import fs24 from "node:fs";
53710
+ import fs25 from "node:fs";
53572
53711
  import net4 from "node:net";
53573
- import path36 from "node:path";
53712
+ import path37 from "node:path";
53574
53713
  import { StringDecoder as StringDecoder2 } from "node:string_decoder";
53575
53714
  function createStatusFile(instanceId, mode, socketPath) {
53576
53715
  return {
@@ -53705,10 +53844,10 @@ var init_server4 = __esm({
53705
53844
  DaemonServer = class {
53706
53845
  constructor(options) {
53707
53846
  this.options = options;
53708
- this.socketPath = path36.resolve(options.socketPath ?? daemonSocketPath());
53709
- this.statusPath = path36.resolve(options.statusPath ?? daemonStatusPath());
53847
+ this.socketPath = path37.resolve(options.socketPath ?? daemonSocketPath());
53848
+ this.statusPath = path37.resolve(options.statusPath ?? daemonStatusPath());
53710
53849
  this.usesDefaultRuntimeDir = options.socketPath === void 0 || options.statusPath === void 0;
53711
- this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path36.join(path36.dirname(this.socketPath), ".daemon-lifecycle.lock");
53850
+ this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path37.join(path37.dirname(this.socketPath), ".daemon-lifecycle.lock");
53712
53851
  this.transport = createDaemonTransport(this.socketPath);
53713
53852
  this.listenSocketPath = this.transport.listenPath;
53714
53853
  }
@@ -53820,22 +53959,22 @@ var init_server4 = __esm({
53820
53959
  const temporaryPath = `${this.statusPath}.${this.instanceId}.tmp`;
53821
53960
  let descriptor = null;
53822
53961
  try {
53823
- descriptor = fs24.openSync(temporaryPath, "wx", 384);
53824
- fs24.writeFileSync(
53962
+ descriptor = fs25.openSync(temporaryPath, "wx", 384);
53963
+ fs25.writeFileSync(
53825
53964
  descriptor,
53826
53965
  `${JSON.stringify(createStatusFile(this.instanceId, this.options.mode ?? "foreground", this.socketPath), null, 2)}
53827
53966
  `,
53828
53967
  "utf8"
53829
53968
  );
53830
- fs24.closeSync(descriptor);
53969
+ fs25.closeSync(descriptor);
53831
53970
  descriptor = null;
53832
- fs24.chmodSync(temporaryPath, 384);
53833
- fs24.renameSync(temporaryPath, this.statusPath);
53971
+ fs25.chmodSync(temporaryPath, 384);
53972
+ fs25.renameSync(temporaryPath, this.statusPath);
53834
53973
  } catch (error2) {
53835
53974
  if (descriptor !== null) {
53836
- fs24.closeSync(descriptor);
53975
+ fs25.closeSync(descriptor);
53837
53976
  }
53838
- fs24.rmSync(temporaryPath, { force: true });
53977
+ fs25.rmSync(temporaryPath, { force: true });
53839
53978
  throw error2;
53840
53979
  }
53841
53980
  }
@@ -53860,9 +53999,9 @@ var init_server4 = __esm({
53860
53999
  this.transport.cleanup(this.socketPath);
53861
54000
  if (this.statusOwned) {
53862
54001
  try {
53863
- const status2 = JSON.parse(fs24.readFileSync(this.statusPath, "utf8"));
54002
+ const status2 = JSON.parse(fs25.readFileSync(this.statusPath, "utf8"));
53864
54003
  if (status2.instanceId === this.instanceId) {
53865
- fs24.rmSync(this.statusPath, { force: true });
54004
+ fs25.rmSync(this.statusPath, { force: true });
53866
54005
  }
53867
54006
  } catch {
53868
54007
  }
@@ -54456,7 +54595,7 @@ var init_push_trigger_projection = __esm({
54456
54595
  });
54457
54596
 
54458
54597
  // apps/desktop/src/daemon/turn-push-audit.ts
54459
- import path37 from "node:path";
54598
+ import path38 from "node:path";
54460
54599
  function isRecord6(value) {
54461
54600
  return typeof value === "object" && value !== null && !Array.isArray(value);
54462
54601
  }
@@ -54503,7 +54642,7 @@ function isCoverageReason(value) {
54503
54642
  return value === "realtime_gap" || value === "historical_gap" || value === "source_unavailable" || value === "reader_limit" || value === "write_failed";
54504
54643
  }
54505
54644
  function auditDirectory(runtimeDir) {
54506
- return path37.join(runtimeDir, AUDIT_DIRECTORY);
54645
+ return path38.join(runtimeDir, AUDIT_DIRECTORY);
54507
54646
  }
54508
54647
  function dateFileName(timestampMs) {
54509
54648
  if (!isFiniteTimestamp(timestampMs)) return null;
@@ -54606,7 +54745,7 @@ function appendRecord(runtimeDir, timestampMs, record26, files) {
54606
54745
  files.checkDirectory(runtimeDir);
54607
54746
  const directory = auditDirectory(runtimeDir);
54608
54747
  files.ensureDirectory(directory);
54609
- files.append(path37.join(directory, fileName), `${JSON.stringify(record26)}
54748
+ files.append(path38.join(directory, fileName), `${JSON.stringify(record26)}
54610
54749
  `, MAX_FILE_BYTES);
54611
54750
  return true;
54612
54751
  } catch {
@@ -56103,7 +56242,7 @@ var init_events2 = __esm({
56103
56242
  });
56104
56243
 
56105
56244
  // apps/desktop/src/niuma/session-history-items.ts
56106
- import { createHash as createHash18 } from "node:crypto";
56245
+ import { createHash as createHash19 } from "node:crypto";
56107
56246
  function copyTimelineStatus(raw, item) {
56108
56247
  if (!Object.hasOwn(raw, "status")) return;
56109
56248
  if (raw.status === null || raw.status === void 0) return;
@@ -56170,11 +56309,11 @@ function completedHistoryItem(value) {
56170
56309
  break;
56171
56310
  case "fileChange":
56172
56311
  copy(raw, item, { status: "status" });
56173
- item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([path55, value2]) => {
56312
+ item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([path56, value2]) => {
56174
56313
  const change = record5(value2);
56175
56314
  const kind = { type: change.type };
56176
56315
  if (change.type === "update") kind.movePath = change.move_path ?? null;
56177
- return { path: path55, kind, diff: change.unified_diff ?? change.content ?? "" };
56316
+ return { path: path56, kind, diff: change.unified_diff ?? change.content ?? "" };
56178
56317
  });
56179
56318
  break;
56180
56319
  case "collabAgentToolCall":
@@ -56222,7 +56361,7 @@ function responseHistoryItem(value, location) {
56222
56361
  const type = raw.type;
56223
56362
  if (type === "message") {
56224
56363
  if (raw.role !== "user" && raw.role !== "assistant") return null;
56225
- const id5 = nonempty(raw.id) ?? `session-${createHash18("sha256").update(location).digest("hex")}`;
56364
+ const id5 = nonempty(raw.id) ?? `session-${createHash19("sha256").update(location).digest("hex")}`;
56226
56365
  return { ...completedHistoryItem({ ...raw, id: id5, type: raw.role === "user" ? "UserMessage" : "AgentMessage" }), historySource: "response_item" };
56227
56366
  }
56228
56367
  if (type === "web_search_call") {
@@ -56311,8 +56450,8 @@ function markdownTargets(text11) {
56311
56450
  function markdownReferences(text11, paths = localResourcePaths) {
56312
56451
  const { tree, references } = markdownTargets(text11);
56313
56452
  return { tree, references: references.flatMap((ref) => {
56314
- const path55 = paths.parseLink(ref.url);
56315
- return path55 === null ? [] : [{ ...ref, path: path55 }];
56453
+ const path56 = paths.parseLink(ref.url);
56454
+ return path56 === null ? [] : [{ ...ref, path: path56 }];
56316
56455
  }) };
56317
56456
  }
56318
56457
  function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths) {
@@ -56343,8 +56482,8 @@ function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths)
56343
56482
  if (item.entitiesByKey && typeof item.entitiesByKey === "object") pending.push(...Object.values(item.entitiesByKey));
56344
56483
  if (Array.isArray(item.patches)) {
56345
56484
  for (const patch of item.patches) {
56346
- const path55 = patch?.path;
56347
- if (Array.isArray(path55) && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && (path55.length === 4 || path55[4] === "items")) pending.push(patch.value);
56485
+ const path56 = patch?.path;
56486
+ if (Array.isArray(path56) && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && (path56.length === 4 || path56[4] === "items")) pending.push(patch.value);
56348
56487
  }
56349
56488
  }
56350
56489
  }
@@ -56435,7 +56574,7 @@ var init_thread_view_images = __esm({
56435
56574
  });
56436
56575
 
56437
56576
  // apps/desktop/src/niuma/session-history-images.ts
56438
- import { createHash as createHash19 } from "node:crypto";
56577
+ import { createHash as createHash20 } from "node:crypto";
56439
56578
  import { stat as stat2 } from "node:fs/promises";
56440
56579
  async function historyFingerprint(snapshots2, signal) {
56441
56580
  signal?.throwIfAborted();
@@ -56531,7 +56670,7 @@ async function readHistoryImageValue(locator, signal, filePath) {
56531
56670
  }
56532
56671
  await validateSessionFile(snapshot2);
56533
56672
  const bytes3 = await readBytes(snapshot2.path, offset, length);
56534
- if (createHash19("sha256").update(bytes3).digest("hex") !== locator.recordSha256) {
56673
+ if (createHash20("sha256").update(bytes3).digest("hex") !== locator.recordSha256) {
56535
56674
  throw new SessionHistoryError("SNAPSHOT_CHANGED", "\u56FE\u7247\u5386\u53F2\u8BB0\u5F55\u5DF2\u53D8\u5316");
56536
56675
  }
56537
56676
  let value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes3));
@@ -56545,11 +56684,11 @@ async function readHistoryImageValue(locator, signal, filePath) {
56545
56684
  signal?.throwIfAborted();
56546
56685
  return value;
56547
56686
  }
56548
- async function assertHistoryImageFileReference(locator, path55, signal) {
56549
- const value = await readHistoryImageValue(locator, signal, path55);
56687
+ async function assertHistoryImageFileReference(locator, path56, signal) {
56688
+ const value = await readHistoryImageValue(locator, signal, path56);
56550
56689
  const last = locator.valuePath.at(-1);
56551
56690
  const text11 = typeof value === "string" ? value : Array.isArray(value) ? value.map((part) => typeof record5(part).text === "string" ? record5(part).text : "").join("") : null;
56552
- if (text11 === null || !(last === "path" ? text11 === path55 : assistantPaths(text11).includes(path55))) {
56691
+ if (text11 === null || !(last === "path" ? text11 === path56 : assistantPaths(text11).includes(path56))) {
56553
56692
  throw new SessionHistoryError("INVALID_RECORD", "\u56FE\u7247\u6587\u4EF6\u4E0E\u5386\u53F2\u5F15\u7528\u4E0D\u7B26");
56554
56693
  }
56555
56694
  }
@@ -56608,7 +56747,7 @@ var init_session_history_images = __esm({
56608
56747
  const found = [];
56609
56748
  if (formal && item.type === "agentMessage") {
56610
56749
  const references = [];
56611
- for (const path55 of assistantPaths(String(item.text ?? ""))) {
56750
+ for (const path56 of assistantPaths(String(item.text ?? ""))) {
56612
56751
  references.push({ locator: {
56613
56752
  threadId: threadId2,
56614
56753
  turnId: "",
@@ -56621,7 +56760,7 @@ var init_session_history_images = __esm({
56621
56760
  recordLength: range.length,
56622
56761
  recordSha256: range.sha256,
56623
56762
  valuePath: ["payload", "item", raw.content !== void 0 ? "content" : "text"]
56624
- }, nativeMessageId: null, path: path55, filePath: path55, callId: null });
56763
+ }, nativeMessageId: null, path: path56, filePath: path56, callId: null });
56625
56764
  }
56626
56765
  this.markdownEvidence.set(item, references);
56627
56766
  }
@@ -56650,7 +56789,7 @@ var init_session_history_images = __esm({
56650
56789
  }
56651
56790
  if (!imageUrl(source2)) return;
56652
56791
  const previous = index > 0 ? record5(parts[index - 1]).text : null;
56653
- const path55 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
56792
+ const path56 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
56654
56793
  found.push({
56655
56794
  locator: {
56656
56795
  threadId: threadId2,
@@ -56670,7 +56809,7 @@ var init_session_history_images = __esm({
56670
56809
  ]
56671
56810
  },
56672
56811
  nativeMessageId: typeof item.clientId === "string" ? item.clientId : null,
56673
- path: path55,
56812
+ path: path56,
56674
56813
  callId: null
56675
56814
  });
56676
56815
  if (mapped[index]) mapped[index] = { type: "historyImage", resourceKey: null };
@@ -56732,11 +56871,11 @@ var init_session_history_images = __esm({
56732
56871
  }
56733
56872
  if (item.type === "agentMessage" && typeof item.text === "string") {
56734
56873
  const references = [];
56735
- for (const [referenceIndex, path55] of assistantPaths(item.text).entries()) {
56874
+ for (const [referenceIndex, path56] of assistantPaths(item.text).entries()) {
56736
56875
  const calls = fallback.filter((candidate) => {
56737
56876
  if (candidate.type !== "functionCall" || !["view_image", "functions.view_image"].includes(String(candidate.name))) return false;
56738
56877
  try {
56739
- return record5(JSON.parse(String(candidate.arguments))).path === path55;
56878
+ return record5(JSON.parse(String(candidate.arguments))).path === path56;
56740
56879
  } catch {
56741
56880
  return false;
56742
56881
  }
@@ -56744,9 +56883,9 @@ var init_session_history_images = __esm({
56744
56883
  const outputs = fallback.filter((candidate) => candidate.type === "functionCallOutput" && calls.some((call) => candidate.id === call.id));
56745
56884
  const candidates = outputs.flatMap((output) => this.evidence.get(output) ?? []);
56746
56885
  if (candidates.length && (calls.length !== 1 || candidates.length !== 1)) continue;
56747
- const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path55);
56886
+ const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path56);
56748
56887
  if (!original) continue;
56749
- const evidence = { ...original, path: path55, referenceKind: "markdown", locator: {
56888
+ const evidence = { ...original, path: path56, referenceKind: "markdown", locator: {
56750
56889
  ...original.locator,
56751
56890
  turnId,
56752
56891
  itemId: item.id,
@@ -56754,7 +56893,7 @@ var init_session_history_images = __esm({
56754
56893
  } };
56755
56894
  try {
56756
56895
  const resourceKey = await callback(evidence);
56757
- if (resourceKey) references.push({ path: path55, resourceKey });
56896
+ if (resourceKey) references.push({ path: path56, resourceKey });
56758
56897
  } catch {
56759
56898
  }
56760
56899
  }
@@ -56773,7 +56912,7 @@ __export(session_history_reader_exports, {
56773
56912
  SessionHistoryReader: () => SessionHistoryReader
56774
56913
  });
56775
56914
  import { randomUUID as randomUUID33 } from "node:crypto";
56776
- import fs25 from "node:fs/promises";
56915
+ import fs26 from "node:fs/promises";
56777
56916
  function resolveHistoryPath(resolvePath, signal) {
56778
56917
  abortIfRequested2(signal);
56779
56918
  if (!signal) return resolvePath();
@@ -57041,7 +57180,7 @@ var init_session_history_reader = __esm({
57041
57180
  try {
57042
57181
  const resolved3 = await resolveHistoryPath(() => this.options.resolveSessionPath(snapshot2.threadId), signal);
57043
57182
  abortIfRequested2(signal);
57044
- const current2 = await fs25.realpath(resolved3);
57183
+ const current2 = await fs26.realpath(resolved3);
57045
57184
  abortIfRequested2(signal);
57046
57185
  if (current2 !== snapshot2.files[0].path) throw new Error("current path changed");
57047
57186
  } catch (error2) {
@@ -58329,7 +58468,7 @@ var init_thread_view_reducer = __esm({
58329
58468
  });
58330
58469
 
58331
58470
  // apps/desktop/src/daemon/thread-view-store.ts
58332
- import { createHash as createHash20, randomUUID as randomUUID34 } from "node:crypto";
58471
+ import { createHash as createHash21, randomUUID as randomUUID34 } from "node:crypto";
58333
58472
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
58334
58473
  function clone5(value) {
58335
58474
  return structuredClone(value);
@@ -59199,7 +59338,7 @@ var init_thread_view_store = __esm({
59199
59338
  const facts = asyncQuestionFactItems(nextAggregate);
59200
59339
  if (facts.length) {
59201
59340
  const observation = nextEntry.questionObservation ??= { confirmed: null, latest: null, pending: /* @__PURE__ */ new Map() };
59202
- const fingerprint2 = createHash20("sha256").update(JSON.stringify(facts)).digest("hex");
59341
+ const fingerprint2 = createHash21("sha256").update(JSON.stringify(facts)).digest("hex");
59203
59342
  observation.latest = observation.pending.get(fingerprint2) ?? null;
59204
59343
  if (fingerprint2 !== observation.confirmed && !observation.pending.has(fingerprint2) && observation.pending.size < 32) {
59205
59344
  const token3 = /* @__PURE__ */ Symbol();
@@ -60398,7 +60537,7 @@ var init_async_question_batch_store = __esm({
60398
60537
  });
60399
60538
 
60400
60539
  // apps/desktop/src/daemon/runtime/handlers/interactions.ts
60401
- import { createHash as createHash21 } from "node:crypto";
60540
+ import { createHash as createHash22 } from "node:crypto";
60402
60541
  function createInteractionsHandlers(ports) {
60403
60542
  const handlers = {
60404
60543
  "thread/async-question-groups": async (params, _socket, options) => ports.interactions.managedQuestionOperation(async () => {
@@ -60438,7 +60577,7 @@ function createInteractionsHandlers(ports) {
60438
60577
  content: [{ type: "text", text: text11 }],
60439
60578
  mode,
60440
60579
  turnId: mode === "steer" ? action2.activeTurnId : null,
60441
- idempotencyKey: `managed-question:${createHash21("sha256").update(JSON.stringify([principal, batch.thread_id, batch.idempotency_key])).digest("hex")}`,
60580
+ idempotencyKey: `managed-question:${createHash22("sha256").update(JSON.stringify([principal, batch.thread_id, batch.idempotency_key])).digest("hex")}`,
60442
60581
  [MANAGED_QUESTION_BATCH]: true
60443
60582
  }, { ...options, onNativeMessageDispatch: () => {
60444
60583
  ports.interactions.assertManagedQuestionAccess(batch.thread_id, options, generation);
@@ -61888,10 +62027,10 @@ var init_history_snapshot = __esm({
61888
62027
  const patches = objectRecord3(objectRecord3(objectRecord3(frame).params).change).patches;
61889
62028
  const covered = Array.isArray(patches) && patches.every((raw) => {
61890
62029
  const patch = objectRecord3(raw);
61891
- const path55 = patch.path;
61892
- if (!Array.isArray(path55)) return false;
61893
- if (path55[0] === "requests") return ["add", "replace", "remove"].includes(String(patch.op));
61894
- return path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string" && path55[3].endsWith(`:${recovery.turnId}`) && path55[4] === "items" && (patch.op === "add" && path55.length === 6 || patch.op === "replace" && path55.length === 7 && path55[6] === "text");
62030
+ const path56 = patch.path;
62031
+ if (!Array.isArray(path56)) return false;
62032
+ if (path56[0] === "requests") return ["add", "replace", "remove"].includes(String(patch.op));
62033
+ return path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string" && path56[3].endsWith(`:${recovery.turnId}`) && path56[4] === "items" && (patch.op === "add" && path56.length === 6 || patch.op === "replace" && path56.length === 7 && path56[6] === "text");
61895
62034
  });
61896
62035
  const bytes3 = Buffer.byteLength(JSON.stringify(acceptedEvents));
61897
62036
  if (!covered || recovery.events.length + events.length > 256 || recovery.bytes + bytes3 > 2 * 1024 * 1024) recovery.valid = false;
@@ -62105,7 +62244,7 @@ var init_history_state_reads = __esm({
62105
62244
  });
62106
62245
 
62107
62246
  // apps/desktop/src/daemon/app-server-history-window-reader.ts
62108
- import { createHash as createHash22, randomUUID as randomUUID38 } from "node:crypto";
62247
+ import { createHash as createHash23, randomUUID as randomUUID38 } from "node:crypto";
62109
62248
  function awaitResponse(promise, signal) {
62110
62249
  if (!signal) return promise;
62111
62250
  signal.throwIfAborted();
@@ -62260,11 +62399,11 @@ var init_app_server_history_window_reader = __esm({
62260
62399
  const bound = this.turnMetadata.get(turn);
62261
62400
  if (!bound) throw new SessionHistoryError("INVALID_CURSOR", "Turn \u4E0D\u5C5E\u4E8E\u5F53\u524D\u5386\u53F2\u5FEB\u7167");
62262
62401
  this.assertEvidenceCurrent(bound);
62263
- const { createdAt, cwd, path: path55 } = bound.metadata;
62402
+ const { createdAt, cwd, path: path56 } = bound.metadata;
62264
62403
  return {
62265
62404
  nativeOrder: bound.nativeOrder,
62266
62405
  sourceRevision: bound.revision,
62267
- contentVersion: createHash22("sha256").update(JSON.stringify([turn, createdAt, cwd, path55])).digest("hex")
62406
+ contentVersion: createHash23("sha256").update(JSON.stringify([turn, createdAt, cwd, path56])).digest("hex")
62268
62407
  };
62269
62408
  }
62270
62409
  /** 撤销正文提交资格,保留逻辑边界供下次原生读取重新证明。 */
@@ -62477,7 +62616,7 @@ var init_app_server_history_window_reader = __esm({
62477
62616
  this.nativeMetrics.peakCandidateBytes = Math.max(this.nativeMetrics.peakCandidateBytes, source2.rawBytes);
62478
62617
  source2.nativeVersions = new Map(source2.rawTurns.map((raw) => {
62479
62618
  const value = raw;
62480
- return [String(value.id), createHash22("sha256").update(JSON.stringify(raw)).digest("hex")];
62619
+ return [String(value.id), createHash23("sha256").update(JSON.stringify(raw)).digest("hex")];
62481
62620
  }));
62482
62621
  source2.nativeEdges = this.proveNativeEdges([...source2.nativeVersions.keys()], source2.eof === true, !hint);
62483
62622
  const ids = /* @__PURE__ */ new Set();
@@ -62881,7 +63020,7 @@ var init_thread_history_snapshot_cache = __esm({
62881
63020
  });
62882
63021
 
62883
63022
  // apps/desktop/src/daemon/thread-history-window-loader.ts
62884
- import { createHash as createHash23, randomUUID as randomUUID39 } from "node:crypto";
63023
+ import { createHash as createHash24, randomUUID as randomUUID39 } from "node:crypto";
62885
63024
  function abortable(promise, signal) {
62886
63025
  signal.throwIfAborted();
62887
63026
  return new Promise((resolve5, reject3) => {
@@ -63177,7 +63316,7 @@ var init_thread_history_window_loader = __esm({
63177
63316
  token3.addTurnIds([turn.id]);
63178
63317
  const identity6 = JSON.stringify([threadId2, turn.id]);
63179
63318
  const description = this.reader.describeTurn?.(turn) ?? {
63180
- contentVersion: createHash23("sha256").update(JSON.stringify(turn)).digest("hex"),
63319
+ contentVersion: createHash24("sha256").update(JSON.stringify(turn)).digest("hex"),
63181
63320
  nativeOrder: 0,
63182
63321
  sourceRevision: 0
63183
63322
  };
@@ -63259,7 +63398,7 @@ var init_thread_history_window_loader = __esm({
63259
63398
  async measure(turn, signal) {
63260
63399
  const epoch = this.sourceEpoch;
63261
63400
  this.currentProtection.addTurnIds([turn.id]);
63262
- const description = this.reader.describeTurn?.(turn) ?? { contentVersion: createHash23("sha256").update(JSON.stringify(turn)).digest("hex") };
63401
+ const description = this.reader.describeTurn?.(turn) ?? { contentVersion: createHash24("sha256").update(JSON.stringify(turn)).digest("hex") };
63263
63402
  const timing = await this.timestampVersion(turn, signal);
63264
63403
  this.assertSource(epoch);
63265
63404
  signal.throwIfAborted();
@@ -63385,7 +63524,7 @@ var init_thread_history = __esm({
63385
63524
  });
63386
63525
 
63387
63526
  // apps/desktop/src/daemon/thread-read-checkpoint.ts
63388
- import { createHash as createHash24 } from "node:crypto";
63527
+ import { createHash as createHash25 } from "node:crypto";
63389
63528
  function stableContent2(part) {
63390
63529
  if (part.type === "text") return { type: part.type, text: part.text };
63391
63530
  if (part.type === "file") return { type: part.type, name: part.name, attachment_id: part.attachment_id ?? null };
@@ -63400,7 +63539,7 @@ function createContentCheckpoint(input) {
63400
63539
  namespace: input.namespace,
63401
63540
  threadId: input.threadId,
63402
63541
  turnId: input.turnId,
63403
- fingerprint: createHash24("sha256").update(JSON.stringify(body)).digest("hex")
63542
+ fingerprint: createHash25("sha256").update(JSON.stringify(body)).digest("hex")
63404
63543
  };
63405
63544
  }
63406
63545
  function nativeReadIdentity(input) {
@@ -64772,7 +64911,7 @@ var init_thread_history_window_projection = __esm({
64772
64911
  pending: null,
64773
64912
  activity: null,
64774
64913
  lastError: null,
64775
- resolveKnownLocalImage: (path55, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path55, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path55) ?? null : null),
64914
+ resolveKnownLocalImage: (path56, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path56, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path56) ?? null : null),
64776
64915
  onHistoryItemProjected: (item, normalized) => timeline.push({ id: item.id, timeline: normalized })
64777
64916
  }, "history_only");
64778
64917
  const items = [...event.baseline.committed_items, ...event.baseline.active_turn?.items ?? []];
@@ -65593,7 +65732,7 @@ var init_thread_read_state = __esm({
65593
65732
  });
65594
65733
 
65595
65734
  // apps/desktop/src/daemon/thread-read-diagnostics.ts
65596
- import { createHash as createHash25 } from "node:crypto";
65735
+ import { createHash as createHash26 } from "node:crypto";
65597
65736
  function unreadDiagnosticValues(before, after) {
65598
65737
  return {
65599
65738
  beforeUnread: before?.hasUnreadTurn ?? null,
@@ -65646,8 +65785,8 @@ function unreadFrameDiagnostic(frame) {
65646
65785
  let countValue = values.unreadMessageCount;
65647
65786
  if (kind === "patch") {
65648
65787
  for (const value of Array.isArray(change.patches) ? change.patches : []) {
65649
- const patch = object10(value), path55 = Array.isArray(patch.path) ? patch.path : [];
65650
- const name2 = path55.length === 1 ? path55[0] : path55.length === 2 && path55[0] === "conversationState" ? path55[1] : null;
65788
+ const patch = object10(value), path56 = Array.isArray(patch.path) ? patch.path : [];
65789
+ const name2 = path56.length === 1 ? path56[0] : path56.length === 2 && path56[0] === "conversationState" ? path56[1] : null;
65651
65790
  if (name2 !== "hasUnreadTurn" && name2 !== "unreadMessageCount") continue;
65652
65791
  const state = patch.op === "remove" ? "removed" : ["add", "replace"].includes(String(patch.op)) ? field(patch.value, Object.hasOwn(patch, "value"), name2 === "unreadMessageCount") : "invalid";
65653
65792
  if (name2 === "hasUnreadTurn") unread = state;
@@ -65665,7 +65804,7 @@ function unreadFrameDiagnostic(frame) {
65665
65804
  wireCountValue: count === "value" ? countValue : null,
65666
65805
  version: typeof frame.version === "number" && Number.isSafeInteger(frame.version) && frame.version >= 0 ? frame.version : null,
65667
65806
  revision: typeof change.revision === "number" && Number.isSafeInteger(change.revision) && change.revision >= 0 ? change.revision : null,
65668
- sourceClient: typeof frame.sourceClientId === "string" ? createHash25("sha256").update(frame.sourceClientId).digest("hex").slice(0, 16) : null
65807
+ sourceClient: typeof frame.sourceClientId === "string" ? createHash26("sha256").update(frame.sourceClientId).digest("hex").slice(0, 16) : null
65669
65808
  };
65670
65809
  }
65671
65810
  function safeReadDiagnosticAttribute(key, value) {
@@ -66218,7 +66357,7 @@ var init_async_question_collector = __esm({
66218
66357
  });
66219
66358
 
66220
66359
  // apps/desktop/src/daemon/managed-async-question-groups.ts
66221
- import { createHash as createHash26 } from "node:crypto";
66360
+ import { createHash as createHash27 } from "node:crypto";
66222
66361
  import { z as z14 } from "zod";
66223
66362
  function compactNewTurns(turns) {
66224
66363
  const latest = /* @__PURE__ */ new Map();
@@ -66232,7 +66371,7 @@ function unavailable8() {
66232
66371
  throw new HttpApiError(500, 900004, "\u9898\u7EC4\u5B58\u50A8\u6682\u4E0D\u53EF\u7528");
66233
66372
  }
66234
66373
  function groupId(source2) {
66235
- return "aqg_" + createHash26("sha256").update(source2).digest("base64url");
66374
+ return "aqg_" + createHash27("sha256").update(source2).digest("base64url");
66236
66375
  }
66237
66376
  function project2(t, g) {
66238
66377
  return { thread_id: t.id, group_id: groupId(g.source), revision: g.revision, list: g.list.filter((q) => !q.closed).map(({ id: id5, title, options }) => ({ id: id5, title, options })) };
@@ -66269,8 +66408,8 @@ var init_managed_async_question_groups = __esm({
66269
66408
  trace(phase, batch, extra = {}) {
66270
66409
  try {
66271
66410
  this.diagnostic?.(phase, {
66272
- batch: createHash26("sha256").update(batch.idempotency_key).digest("hex").slice(0, 16),
66273
- thread: createHash26("sha256").update(batch.thread_id).digest("hex").slice(0, 16),
66411
+ batch: createHash27("sha256").update(batch.idempotency_key).digest("hex").slice(0, 16),
66412
+ thread: createHash27("sha256").update(batch.thread_id).digest("hex").slice(0, 16),
66274
66413
  revision: batch.revision,
66275
66414
  answerCount: batch.answers.length,
66276
66415
  ...extra
@@ -66577,7 +66716,7 @@ var init_managed_async_question_groups = __esm({
66577
66716
  });
66578
66717
 
66579
66718
  // apps/desktop/src/daemon/async-question-evidence.ts
66580
- import { createHash as createHash27 } from "node:crypto";
66719
+ import { createHash as createHash28 } from "node:crypto";
66581
66720
  function projectAsyncQuestionEvidence(input) {
66582
66721
  const collection = input.evidence?.collection;
66583
66722
  if (collection && collection.thread_id !== input.threadId) throw new TypeError("invalid_evidence_thread");
@@ -66594,7 +66733,7 @@ function projectAsyncQuestionEvidence(input) {
66594
66733
  list: (collection?.list ?? []).map((q) => ({ id: q.id, title: q.title, options: [...q.options], source_turn_id: q.source_turn_id, answer: q.answer, answer_turn_id: q.answer_turn_id })),
66595
66734
  total: collection?.list.length ?? 0
66596
66735
  };
66597
- const evidence_id = createHash27("sha256").update(JSON.stringify([input.runtimeGeneration, full])).digest("base64url");
66736
+ const evidence_id = createHash28("sha256").update(JSON.stringify([input.runtimeGeneration, full])).digest("base64url");
66598
66737
  const offset = (input.page - 1) * input.pageSize;
66599
66738
  return parseAsyncQuestionEvidencePage({ ...full, evidence_id, page: input.page, page_size: input.pageSize, list: full.list.slice(offset, offset + input.pageSize) });
66600
66739
  }
@@ -66606,7 +66745,7 @@ var init_async_question_evidence2 = __esm({
66606
66745
  });
66607
66746
 
66608
66747
  // apps/desktop/src/daemon/runtime/interactions.ts
66609
- import { createHash as createHash28 } from "node:crypto";
66748
+ import { createHash as createHash29 } from "node:crypto";
66610
66749
  var RuntimeInteractions;
66611
66750
  var init_interactions2 = __esm({
66612
66751
  "apps/desktop/src/daemon/runtime/interactions.ts"() {
@@ -66633,7 +66772,7 @@ var init_interactions2 = __esm({
66633
66772
  // 与持久通知账本的身份上限一致;不淘汰当前轮次来为重复事件续期。
66634
66773
  liveQuestionDeadlines = /* @__PURE__ */ new Map();
66635
66774
  questionKey(threadId2, turnId, rawId) {
66636
- return createHash28("sha256").update(JSON.stringify([threadId2, turnId, rawId])).digest("hex");
66775
+ return createHash29("sha256").update(JSON.stringify([threadId2, turnId, rawId])).digest("hex");
66637
66776
  }
66638
66777
  clearWaiting() {
66639
66778
  this.asyncInputWaitingQuestions.clear();
@@ -67640,7 +67779,7 @@ var init_projection_context = __esm({
67640
67779
  });
67641
67780
 
67642
67781
  // apps/desktop/src/attachments/file-resources.ts
67643
- import { createHash as createHash29, randomUUID as randomUUID42 } from "node:crypto";
67782
+ import { createHash as createHash30, randomUUID as randomUUID42 } from "node:crypto";
67644
67783
  import { constants as constants4 } from "node:fs";
67645
67784
  import { lstat as lstat4, open as open5, realpath as realpath2 } from "node:fs/promises";
67646
67785
  import { basename as basename2, dirname as dirname2, resolve as resolve3 } from "node:path";
@@ -67651,9 +67790,9 @@ function assertFile(stat3) {
67651
67790
  if (!stat3.isFile() || stat3.nlink !== 1n) throw missing2();
67652
67791
  if (stat3.size > BigInt(MAX_BYTES6)) throw limited();
67653
67792
  }
67654
- async function captureDirectoryChain(snapshot2, path55, signal) {
67793
+ async function captureDirectoryChain(snapshot2, path56, signal) {
67655
67794
  const paths = /* @__PURE__ */ new Set();
67656
- for (const start of [dirname2(path55)]) {
67795
+ for (const start of [dirname2(path56)]) {
67657
67796
  for (let current2 = start; ; current2 = dirname2(current2)) {
67658
67797
  paths.add(current2);
67659
67798
  if (paths.size > MAX_DIRECTORY_ENTRIES2) throw limited();
@@ -67783,9 +67922,9 @@ var init_file_resources = __esm({
67783
67922
  trim() {
67784
67923
  while (this.entries.size > MAX_ENTRIES3 || this.indexBytes > MAX_INDEX_BYTES) this.remove(this.entries.values().next().value);
67785
67924
  }
67786
- assertTarget(entry, path55, signal, isCurrent) {
67925
+ assertTarget(entry, path56, signal, isCurrent) {
67787
67926
  this.assertVisible(entry, signal, isCurrent);
67788
- if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path55) {
67927
+ if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path56) {
67789
67928
  this.remove(entry);
67790
67929
  this.options.onReferenceRetired?.({ ...entry.reference, attachmentId: entry.attachmentId });
67791
67930
  throw changed();
@@ -67827,22 +67966,22 @@ var init_file_resources = __esm({
67827
67966
  if (request2 && (!expected || expected.sha256 !== request2.sha256)) throw changed();
67828
67967
  const directories2 = { entries: /* @__PURE__ */ new Map(), bytes: 0 };
67829
67968
  await captureDirectoryChain(directories2, entry.reference.path, combined);
67830
- const path55 = await realpath2(entry.reference.path);
67969
+ const path56 = await realpath2(entry.reference.path);
67831
67970
  combined.throwIfAborted();
67832
- this.assertTarget(entry, path55, combined, isCurrent);
67833
- await captureDirectoryChain(directories2, path55, combined);
67834
- const pathBefore = await lstat4(path55, { bigint: true });
67971
+ this.assertTarget(entry, path56, combined, isCurrent);
67972
+ await captureDirectoryChain(directories2, path56, combined);
67973
+ const pathBefore = await lstat4(path56, { bigint: true });
67835
67974
  assertFile(pathBefore);
67836
- handle = await open5(path55, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
67975
+ handle = await open5(path56, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
67837
67976
  const before = await handle.stat({ bigint: true });
67838
67977
  assertFile(before);
67839
67978
  if (identity5(before) !== identity5(pathBefore)) throw changed();
67840
- const fileIdentity2 = `${path55}\0${identity5(before)}`;
67979
+ const fileIdentity2 = `${path56}\0${identity5(before)}`;
67841
67980
  if (request2 && expected.identity !== fileIdentity2) throw changed();
67842
67981
  const byteSize2 = Number(before.size);
67843
67982
  const chunkCount = Math.ceil(byteSize2 / CHUNK_BYTES);
67844
67983
  if (request2 && request2.index >= chunkCount) throw invalid13();
67845
- const hash3 = createHash29("sha256");
67984
+ const hash3 = createHash30("sha256");
67846
67985
  const buffer = Buffer.alloc(Math.min(CHUNK_BYTES, byteSize2));
67847
67986
  let chunk;
67848
67987
  for (let offset = 0; offset < byteSize2; ) {
@@ -67863,7 +68002,7 @@ var init_file_resources = __esm({
67863
68002
  const pathAfter = await realpath2(entry.reference.path);
67864
68003
  const current2 = await lstat4(pathAfter, { bigint: true });
67865
68004
  this.assertTarget(entry, pathAfter, combined, isCurrent);
67866
- if (pathAfter !== path55 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
68005
+ if (pathAfter !== path56 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
67867
68006
  const sha2562 = hash3.digest("hex");
67868
68007
  if (request2 && sha2562 !== request2.sha256) throw changed();
67869
68008
  await handle.close();
@@ -67879,8 +68018,8 @@ var init_file_resources = __esm({
67879
68018
  chunkBytes: CHUNK_BYTES,
67880
68019
  chunkCount
67881
68020
  };
67882
- this.assertTarget(entry, path55, combined, isCurrent);
67883
- return { entry, path: path55, info, identity: fileIdentity2, chunk, signal: combined };
68021
+ this.assertTarget(entry, path56, combined, isCurrent);
68022
+ return { entry, path: path56, info, identity: fileIdentity2, chunk, signal: combined };
67884
68023
  } catch (error2) {
67885
68024
  combined.throwIfAborted();
67886
68025
  if (error2 instanceof NiumaError) throw error2;
@@ -67912,16 +68051,16 @@ function revisionOf2(value) {
67912
68051
  function occurredAt3() {
67913
68052
  return Math.floor(Date.now() / 1e3);
67914
68053
  }
67915
- function isThreadSettingsPatch(path55) {
67916
- const field2 = path55.at(-1);
68054
+ function isThreadSettingsPatch(path56) {
68055
+ const field2 = path56.at(-1);
67917
68056
  if (typeof field2 !== "string" || !SETTING_FIELD_ALIASES.has(field2)) {
67918
68057
  return false;
67919
68058
  }
67920
- return path55.length === 1 || typeof path55.at(-2) === "string" && SETTINGS_CONTAINERS.has(path55.at(-2));
68059
+ return path56.length === 1 || typeof path56.at(-2) === "string" && SETTINGS_CONTAINERS.has(path56.at(-2));
67921
68060
  }
67922
- function isCurrentPermissionsPatch(path55) {
67923
- const field2 = path55.at(-1);
67924
- return path55.length === 2 && path55[0] === CURRENT_PERMISSIONS_CONTAINER && typeof field2 === "string" && CURRENT_PERMISSION_FIELD_ALIASES.has(field2);
68061
+ function isCurrentPermissionsPatch(path56) {
68062
+ const field2 = path56.at(-1);
68063
+ return path56.length === 2 && path56[0] === CURRENT_PERMISSIONS_CONTAINER && typeof field2 === "string" && CURRENT_PERMISSION_FIELD_ALIASES.has(field2);
67925
68064
  }
67926
68065
  function hasOwn(value, field2) {
67927
68066
  return Object.prototype.hasOwnProperty.call(value, field2);
@@ -68000,20 +68139,20 @@ function currentPermissionsFromRecord(value) {
68000
68139
  return settings;
68001
68140
  }
68002
68141
  function settingsFromPatch(patch) {
68003
- const path55 = array6(patch.path);
68004
- if (path55.length === 1 && typeof path55[0] === "string" && SETTINGS_CONTAINERS.has(path55[0])) {
68142
+ const path56 = array6(patch.path);
68143
+ if (path56.length === 1 && typeof path56[0] === "string" && SETTINGS_CONTAINERS.has(path56[0])) {
68005
68144
  return settingsFromRecord(patch.value, BASE_SETTING_FIELDS);
68006
68145
  }
68007
- if (path55.length === 1 && path55[0] === CURRENT_PERMISSIONS_CONTAINER) {
68146
+ if (path56.length === 1 && path56[0] === CURRENT_PERMISSIONS_CONTAINER) {
68008
68147
  return currentPermissionsFromRecord(patch.value);
68009
68148
  }
68010
- const field2 = path55.at(-1);
68149
+ const field2 = path56.at(-1);
68011
68150
  const settings = {};
68012
- if (typeof field2 === "string" && isCurrentPermissionsPatch(path55)) {
68151
+ if (typeof field2 === "string" && isCurrentPermissionsPatch(path56)) {
68013
68152
  assignCurrentPermission(settings, field2, patch.value);
68014
68153
  return settings;
68015
68154
  }
68016
- if (typeof field2 === "string" && isThreadSettingsPatch(path55)) {
68155
+ if (typeof field2 === "string" && isThreadSettingsPatch(path56)) {
68017
68156
  assignSetting(settings, field2, patch.value);
68018
68157
  }
68019
68158
  return settings;
@@ -71431,8 +71570,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71431
71570
  if (change.type !== "patches" || next === null || previous === void 0 || next <= previous) return [];
71432
71571
  const patches = array7(change.patches);
71433
71572
  const unknownMembership = patches.some((value) => {
71434
- const p = record25(value), path55 = array7(p.path);
71435
- return path55[0] === "turnHistory" && (path55.length < 3 || path55[1] === "history" && (path55[2] === "entitiesByKey" && (path55.length < 4 || path55.length > 4 && ["id", "turnId", "params"].includes(String(path55[4])))));
71573
+ const p = record25(value), path56 = array7(p.path);
71574
+ return path56[0] === "turnHistory" && (path56.length < 3 || path56[1] === "history" && (path56[2] === "entitiesByKey" && (path56.length < 4 || path56.length > 4 && ["id", "turnId", "params"].includes(String(path56[4])))));
71436
71575
  });
71437
71576
  if (next !== previous + 1 || unknownMembership) {
71438
71577
  this.idleHistoryBaselines.delete(context.threadId);
@@ -71442,9 +71581,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71442
71581
  const mapped = new Map(this.entityTurnIdsByThread.get(context.threadId));
71443
71582
  const candidates = /* @__PURE__ */ new Set();
71444
71583
  for (const value of patches) {
71445
- const p = record25(value), path55 = array7(p.path);
71446
- if (p.op === "remove" && path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey") {
71447
- const id5 = mapped.get(String(path55[3]));
71584
+ const p = record25(value), path56 = array7(p.path);
71585
+ if (p.op === "remove" && path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey") {
71586
+ const id5 = mapped.get(String(path56[3]));
71448
71587
  if (id5) candidates.add(id5);
71449
71588
  }
71450
71589
  }
@@ -71455,9 +71594,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71455
71594
  })).value;
71456
71595
  const canDelete = typeof newGeneration === "number" && Number.isSafeInteger(newGeneration) && oldGeneration !== void 0 && newGeneration > oldGeneration;
71457
71596
  for (const value of patches) {
71458
- const p = record25(value), path55 = array7(p.path), entity = record25(p.value);
71459
- if (path55.length !== 4 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey") continue;
71460
- const key = String(path55[3]);
71597
+ const p = record25(value), path56 = array7(p.path), entity = record25(p.value);
71598
+ if (path56.length !== 4 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey") continue;
71599
+ const key = String(path56[3]);
71461
71600
  if (p.op === "remove") mapped.delete(key);
71462
71601
  else if (p.op === "add" || p.op === "replace") {
71463
71602
  const id5 = nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? nonEmptyString14(record25(entity.params).turnId);
@@ -71583,8 +71722,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71583
71722
  const change = record25(record25(frame.params).change);
71584
71723
  for (const rawPatch of array7(change.patches)) {
71585
71724
  const patch = record25(rawPatch);
71586
- const path55 = array7(patch.path);
71587
- if ((patch.op === "add" || patch.op === "replace") && (path55.length === 1 && path55[0] === "recencyAt" || path55.length === 2 && path55[0] === "conversationState" && path55[1] === "recencyAt")) {
71725
+ const path56 = array7(patch.path);
71726
+ if ((patch.op === "add" || patch.op === "replace") && (path56.length === 1 && path56[0] === "recencyAt" || path56.length === 2 && path56[0] === "conversationState" && path56[1] === "recencyAt")) {
71588
71727
  this.rememberSidebarRecency(context.threadId, patch.value);
71589
71728
  }
71590
71729
  }
@@ -71670,12 +71809,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71670
71809
  requests = structuredClone(requests);
71671
71810
  for (const value of array7(change.patches)) {
71672
71811
  const patch = record25(value);
71673
- const path55 = array7(patch.path);
71674
- if (path55[0] !== "requests") continue;
71675
- if (path55.length === 1) {
71812
+ const path56 = array7(patch.path);
71813
+ if (path56[0] !== "requests") continue;
71814
+ if (path56.length === 1) {
71676
71815
  requests = patch.op === "remove" ? [] : structuredClone(array7(patch.value));
71677
- } else if (path55.length === 2) {
71678
- const index = path55[1] === "-" ? requests.length : Number(path55[1]);
71816
+ } else if (path56.length === 2) {
71817
+ const index = path56[1] === "-" ? requests.length : Number(path56[1]);
71679
71818
  if (!Number.isInteger(index) || index < 0 || index > requests.length) continue;
71680
71819
  if (patch.op === "remove") requests.splice(index, 1);
71681
71820
  else if (patch.op === "add") requests.splice(index, 0, structuredClone(patch.value));
@@ -71754,19 +71893,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71754
71893
  }
71755
71894
  /** 深层 content 只有局部形状,须等待完整项/快照重新证明;text 更新不能洗掉未知内容。 */
71756
71895
  invalidateReadPatch(patch, context) {
71757
- const path55 = array7(patch.path);
71758
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey") return;
71759
- const turnId = typeof path55[3] === "string" ? this.entityTurnIdsByThread.get(context.threadId)?.get(path55[3]) : null;
71760
- if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (path55[4] === "items" || path55.length === 4 && hasOwn2(record25(patch.value), "items"))) {
71896
+ const path56 = array7(patch.path);
71897
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey") return;
71898
+ const turnId = typeof path56[3] === "string" ? this.entityTurnIdsByThread.get(context.threadId)?.get(path56[3]) : null;
71899
+ if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (path56[4] === "items" || path56.length === 4 && hasOwn2(record25(patch.value), "items"))) {
71761
71900
  for (const identity7 of this.nativeReadIdentities.get(context.threadId)?.values() ?? []) {
71762
71901
  if (identity7.turnId === turnId) identity7.complete = false;
71763
71902
  }
71764
71903
  return;
71765
71904
  }
71766
- if (path55[4] !== "items" || path55[6] !== "content") return;
71905
+ if (path56[4] !== "items" || path56[6] !== "content") return;
71767
71906
  const order = this.itemOrders.get(context.threadId);
71768
- if (!order || order.entityKey !== path55[3]) return;
71769
- const id5 = typeof path55[5] === "number" ? order.ids[path55[5]] : null;
71907
+ if (!order || order.entityKey !== path56[3]) return;
71908
+ const id5 = typeof path56[5] === "number" ? order.ids[path56[5]] : null;
71770
71909
  const identity6 = id5 ? this.nativeReadIdentities.get(context.threadId)?.get(id5) : null;
71771
71910
  if (identity6) identity6.complete = false;
71772
71911
  else if (!id5) {
@@ -71790,19 +71929,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71790
71929
  /** 在同一 Store 事务内先更新正文,再发布可信顺序,不让 Web 看见暂存的中间帧。 */
71791
71930
  itemOrderEvents(patch, itemEvents, context) {
71792
71931
  if (this.itemOrderGaps.has(context.threadId)) return [];
71793
- const path55 = array7(patch.path);
71794
- if (path55[0] !== "turnHistory") return [];
71932
+ const path56 = array7(patch.path);
71933
+ if (path56[0] !== "turnHistory") return [];
71795
71934
  const invalidate = () => {
71796
71935
  this.itemOrders.delete(context.threadId);
71797
71936
  this.itemOrderGaps.add(context.threadId);
71798
71937
  return [];
71799
71938
  };
71800
- if (path55.length < 3) return invalidate();
71801
- if (path55[1] !== "history" || path55[2] !== "entitiesByKey") return [];
71802
- if (path55.length < 4) return invalidate();
71939
+ if (path56.length < 3) return invalidate();
71940
+ if (path56[1] !== "history" || path56[2] !== "entitiesByKey") return [];
71941
+ if (path56.length < 4) return invalidate();
71803
71942
  const activeId = this.activeTurnByThread.get(context.threadId);
71804
71943
  if (!activeId) return [];
71805
- const entityKey = String(path55[3]);
71944
+ const entityKey = String(path56[3]);
71806
71945
  const events = [];
71807
71946
  const emitItem = (value) => {
71808
71947
  const item = this.orderedRawItem(value, activeId, context);
@@ -71819,8 +71958,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71819
71958
  return item?.id ?? null;
71820
71959
  };
71821
71960
  let order = this.itemOrders.get(context.threadId);
71822
- const wholeEntity = path55.length === 4;
71823
- const wholeArray = path55.length === 5 && path55[4] === "items";
71961
+ const wholeEntity = path56.length === 4;
71962
+ const wholeArray = path56.length === 5 && path56[4] === "items";
71824
71963
  if (wholeEntity || wholeArray) {
71825
71964
  const entity = record25(patch.value);
71826
71965
  const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) : this.entityTurnIdsByThread.get(context.threadId)?.get(entityKey);
@@ -71836,12 +71975,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71836
71975
  }
71837
71976
  values.forEach(emitItem);
71838
71977
  } else {
71839
- if (!order || order.turnId !== activeId || order.entityKey !== entityKey || path55[4] !== "items") return [];
71840
- if (path55.length > 6) {
71841
- return ["id", "type"].includes(String(path55[6])) ? invalidate() : [];
71978
+ if (!order || order.turnId !== activeId || order.entityKey !== entityKey || path56[4] !== "items") return [];
71979
+ if (path56.length > 6) {
71980
+ return ["id", "type"].includes(String(path56[6])) ? invalidate() : [];
71842
71981
  }
71843
- if (path55.length !== 6 || !["add", "replace", "remove"].includes(String(patch.op))) return invalidate();
71844
- const index = path55[5] === "-" && patch.op === "add" ? order.ids.length : path55[5];
71982
+ if (path56.length !== 6 || !["add", "replace", "remove"].includes(String(patch.op))) return invalidate();
71983
+ const index = path56[5] === "-" && patch.op === "add" ? order.ids.length : path56[5];
71845
71984
  if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0 || index > order.ids.length || patch.op !== "add" && index === order.ids.length) return invalidate();
71846
71985
  if (patch.op === "add" && order.ids.length >= 8192) return invalidate();
71847
71986
  const previousId = order.ids[index];
@@ -72062,12 +72201,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
72062
72201
  for (const patchValue of patches) {
72063
72202
  const patch = record25(patchValue);
72064
72203
  if (patch.op !== "add" && patch.op !== "replace") continue;
72065
- const path55 = array7(patch.path);
72066
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string") continue;
72067
- const entityKey = path55[3];
72068
- const wholeEntity = path55.length === 4;
72069
- const statusField = path55.length === 5 && path55[4] === "status";
72070
- const startField = path55.length === 5 && path55[4] === "turnStartedAtMs";
72204
+ const path56 = array7(patch.path);
72205
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string") continue;
72206
+ const entityKey = path56[3];
72207
+ const wholeEntity = path56.length === 4;
72208
+ const statusField = path56.length === 5 && path56[4] === "status";
72209
+ const startField = path56.length === 5 && path56[4] === "turnStartedAtMs";
72071
72210
  if (!wholeEntity && !statusField && !startField) continue;
72072
72211
  const entity = wholeEntity ? record25(patch.value) : {};
72073
72212
  const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? entityTurnIds.get(entityKey) ?? null : entityTurnIds.get(entityKey) ?? null;
@@ -72250,7 +72389,7 @@ var init_desktop_ipc_thread_view_adapter = __esm({
72250
72389
  });
72251
72390
 
72252
72391
  // apps/desktop/src/daemon/thread-view-files.ts
72253
- import { createHash as createHash30 } from "node:crypto";
72392
+ import { createHash as createHash31 } from "node:crypto";
72254
72393
  function normalizeFileCitations(text11, paths) {
72255
72394
  if (!text11.includes(":codex-file-citation{")) return text11;
72256
72395
  const edits = [];
@@ -72272,12 +72411,12 @@ function normalizeFileCitations(text11, paths) {
72272
72411
  const end = start + match[0].length;
72273
72412
  if (!textRanges.some(([a, b]) => a <= start && start < b) || excluded.some(([a, b]) => a < end && b > start)) continue;
72274
72413
  const slashes = text11.slice(0, start).match(/\\*$/u)?.[0].length ?? 0;
72275
- const path55 = match[1];
72276
- if (slashes % 2 || paths.parseLocal(path55) === null) continue;
72414
+ const path56 = match[1];
72415
+ if (slashes % 2 || paths.parseLocal(path56) === null) continue;
72277
72416
  try {
72278
- const target = paths.toLink(path55);
72417
+ const target = paths.toLink(path56);
72279
72418
  if (target === null) continue;
72280
- const label = fallbackFileName(path55, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
72419
+ const label = fallbackFileName(path56, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
72281
72420
  edits.push({ start, end, value: `[${label}](<${target}>)` });
72282
72421
  } catch {
72283
72422
  }
@@ -72295,9 +72434,9 @@ function fileReferences(text11, paths) {
72295
72434
  return markdownTargets(text11).references.filter((ref) => !ref.image).flatMap((ref) => {
72296
72435
  try {
72297
72436
  const target = withoutFileLocation(ref.url);
72298
- const path55 = paths.parseLink(target);
72299
- if (path55 === null) return [];
72300
- return [{ ...ref, path: path55 }];
72437
+ const path56 = paths.parseLink(target);
72438
+ if (path56 === null) return [];
72439
+ return [{ ...ref, path: path56 }];
72301
72440
  } catch {
72302
72441
  return [];
72303
72442
  }
@@ -72307,8 +72446,8 @@ function collectFileLinkPaths(item, paths = localResourcePaths) {
72307
72446
  if (item.type !== "assistant_message") return [];
72308
72447
  return [...new Set(item.content.flatMap((part) => part.type === "text" ? fileReferences(normalizeFileCitations(part.text, paths), paths).map((ref) => ref.path) : []))];
72309
72448
  }
72310
- function fallbackFileName(path55, paths) {
72311
- const name2 = paths.basename(path55).slice(0, 255);
72449
+ function fallbackFileName(path56, paths) {
72450
+ const name2 = paths.basename(path56).slice(0, 255);
72312
72451
  return name2.trim() && !/[\\/\x00-\x1f\x7f-\x9f]/u.test(name2) ? name2 : "\u6587\u4EF6";
72313
72452
  }
72314
72453
  function projectFileLinks(item, register, isRegistered = () => true, paths = localResourcePaths) {
@@ -72318,7 +72457,7 @@ function projectFileLinks(item, register, isRegistered = () => true, paths = loc
72318
72457
  const original = item.content.map((part) => {
72319
72458
  if (part.type !== "file" || !part.attachment_id || isRegistered(part.attachment_id)) return part;
72320
72459
  const { attachment_id: id5, ...unavailable12 } = part;
72321
- retired.set(`niuma-file:${id5}`, `niuma-file:unavailable_${createHash30("sha256").update(id5).digest("hex")}`);
72460
+ retired.set(`niuma-file:${id5}`, `niuma-file:unavailable_${createHash31("sha256").update(id5).digest("hex")}`);
72322
72461
  return unavailable12;
72323
72462
  });
72324
72463
  const content2 = original.map((part) => {
@@ -72327,7 +72466,7 @@ function projectFileLinks(item, register, isRegistered = () => true, paths = loc
72327
72466
  const targets = new Map(retired);
72328
72467
  for (const ref of fileReferences(text11, paths)) {
72329
72468
  const registered = register(ref.path);
72330
- const id5 = registered?.attachmentId ?? `unavailable_${createHash30("sha256").update(JSON.stringify([item.id, ref.path])).digest("hex")}`;
72469
+ const id5 = registered?.attachmentId ?? `unavailable_${createHash31("sha256").update(JSON.stringify([item.id, ref.path])).digest("hex")}`;
72331
72470
  targets.set(ref.url, `niuma-file:${id5}`);
72332
72471
  if (!files.has(id5)) files.set(id5, {
72333
72472
  type: "file",
@@ -72371,8 +72510,8 @@ var init_thread_view_files = __esm({
72371
72510
  });
72372
72511
 
72373
72512
  // apps/desktop/src/daemon/runtime/projection.ts
72374
- import { createHash as createHash31 } from "node:crypto";
72375
- import path38 from "node:path";
72513
+ import { createHash as createHash32 } from "node:crypto";
72514
+ import path39 from "node:path";
72376
72515
  var FILE_REFRESH_MAX_ENTRIES, FILE_REFRESH_MAX_BYTES, FILE_REFRESH_ENTRY_BYTES, FILE_REFRESH_IN_FLIGHT_RESERVE, RuntimeProjection;
72377
72516
  var init_projection2 = __esm({
72378
72517
  "apps/desktop/src/daemon/runtime/projection.ts"() {
@@ -72419,7 +72558,7 @@ var init_projection2 = __esm({
72419
72558
  }
72420
72559
  pendingRetirements.set(threadId2, {
72421
72560
  itemId,
72422
- fingerprint: createHash31("sha256").update(JSON.stringify(item)).digest("hex"),
72561
+ fingerprint: createHash32("sha256").update(JSON.stringify(item)).digest("hex"),
72423
72562
  isCurrent: this.ports.captureFileResourceSource(threadId2)
72424
72563
  });
72425
72564
  if (alreadyPending) return;
@@ -72428,7 +72567,7 @@ var init_projection2 = __esm({
72428
72567
  pendingRetirements.delete(threadId2);
72429
72568
  if (!retired?.isCurrent()) return;
72430
72569
  const current2 = viewStore2.getProjectionItem(threadId2, retired.itemId);
72431
- if (!current2 || createHash31("sha256").update(JSON.stringify(current2)).digest("hex") !== retired.fingerprint) return;
72570
+ if (!current2 || createHash32("sha256").update(JSON.stringify(current2)).digest("hex") !== retired.fingerprint) return;
72432
72571
  viewStore2.refreshResourceProjection(threadId2);
72433
72572
  });
72434
72573
  }
@@ -72504,14 +72643,14 @@ var init_projection2 = __esm({
72504
72643
  isFileReferenceVisible(entry) {
72505
72644
  if (this.ports.stopping()) return false;
72506
72645
  const root = this.ports.projectRoot(entry.threadId);
72507
- if (!root || path38.resolve(root) !== entry.root) return false;
72646
+ if (!root || path39.resolve(root) !== entry.root) return false;
72508
72647
  const item = this.store.getProjectionItem(entry.threadId, entry.itemId);
72509
72648
  if (!item) return false;
72510
72649
  if (item.type === "user_message") {
72511
- return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" && path38.resolve(source2.path) === entry.path);
72650
+ return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" && path39.resolve(source2.path) === entry.path);
72512
72651
  }
72513
72652
  if (item.type !== "assistant_message") return false;
72514
- if (collectFileLinkPaths(item).some((sourcePath) => path38.resolve(sourcePath) === entry.path)) return true;
72653
+ if (collectFileLinkPaths(item).some((sourcePath) => path39.resolve(sourcePath) === entry.path)) return true;
72515
72654
  return item.content.some((part) => part.type === "file" && part.attachment_id === entry.attachmentId) && hasFileAttachmentLink(item, entry.attachmentId);
72516
72655
  }
72517
72656
  subagentAvatars = new CodexSubagentAvatars();
@@ -73875,7 +74014,7 @@ var init_thread_read_receipts2 = __esm({
73875
74014
  });
73876
74015
 
73877
74016
  // apps/desktop/src/daemon/runtime/read-receipts.ts
73878
- import { createHash as createHash32 } from "node:crypto";
74017
+ import { createHash as createHash33 } from "node:crypto";
73879
74018
  function nowSeconds14() {
73880
74019
  return Math.floor(Date.now() / 1e3);
73881
74020
  }
@@ -74049,8 +74188,8 @@ var init_read_receipts = __esm({
74049
74188
  return;
74050
74189
  }
74051
74190
  const statusOnly = change.type === "patches" && Array.isArray(change.patches) && change.patches.length > 0 && change.patches.every((value) => {
74052
- const patch = objectRecord3(value), path55 = Array.isArray(patch.path) ? patch.path : [];
74053
- const fields3 = path55[0] === "conversationState" ? path55.slice(1) : path55;
74191
+ const patch = objectRecord3(value), path56 = Array.isArray(patch.path) ? patch.path : [];
74192
+ const fields3 = path56[0] === "conversationState" ? path56.slice(1) : path56;
74054
74193
  if (!["add", "replace", "remove"].includes(String(patch.op)) || fields3.length !== 1) return false;
74055
74194
  if (fields3[0] === "threadRuntimeStatus") return true;
74056
74195
  return patch.op !== "remove" && (fields3[0] === "hasUnreadTurn" && patch.value === raw?.hasUnreadTurn || fields3[0] === "unreadMessageCount" && patch.value === raw?.unreadMessageCount);
@@ -74133,7 +74272,7 @@ var init_read_receipts = __esm({
74133
74272
  this.publishThreadReadChange(threadId2);
74134
74273
  }
74135
74274
  async initialize(codexHome, receiptPath, diagnostics = false) {
74136
- this.namespace = createHash32("sha256").update(codexHome).digest("hex");
74275
+ this.namespace = createHash33("sha256").update(codexHome).digest("hex");
74137
74276
  this.receipts = new ThreadReadReceipts(
74138
74277
  new ReadReceiptStore(
74139
74278
  this.namespace,
@@ -74595,7 +74734,7 @@ var init_message_submission_attempt = __esm({
74595
74734
  });
74596
74735
 
74597
74736
  // apps/desktop/src/daemon/runtime/submission.ts
74598
- import { createHash as createHash33 } from "node:crypto";
74737
+ import { createHash as createHash34 } from "node:crypto";
74599
74738
  var RuntimeSubmission;
74600
74739
  var init_submission2 = __esm({
74601
74740
  "apps/desktop/src/daemon/runtime/submission.ts"() {
@@ -74790,7 +74929,7 @@ var init_submission2 = __esm({
74790
74929
  const reservation = await store.reserve({
74791
74930
  ...key,
74792
74931
  nativeToken: clientMessageId,
74793
- fingerprint: createHash33("sha256").update(JSON.stringify(content2)).digest("hex")
74932
+ fingerprint: createHash34("sha256").update(JSON.stringify(content2)).digest("hex")
74794
74933
  });
74795
74934
  if (!reservation.dispatch) {
74796
74935
  existingSubmission = true;
@@ -76325,7 +76464,7 @@ var init_image_decoder = __esm({
76325
76464
  });
76326
76465
 
76327
76466
  // apps/desktop/src/attachments/image-assets.ts
76328
- import path39 from "node:path";
76467
+ import path40 from "node:path";
76329
76468
  function names(id5) {
76330
76469
  if (!idPattern.test(id5)) throw unavailable9();
76331
76470
  return { metadata: `img_${id5.slice(4)}`, source: `src_${id5.slice(4)}`, preview: `prv_${id5.slice(4)}` };
@@ -76372,7 +76511,7 @@ var init_image_assets = __esm({
76372
76511
  }
76373
76512
  paths(id5) {
76374
76513
  const n = names(id5);
76375
- return { sourcePath: path39.join(this.root, n.source, "source"), previewPath: path39.join(this.root, n.preview, "source") };
76514
+ return { sourcePath: path40.join(this.root, n.source, "source"), previewPath: path40.join(this.root, n.preview, "source") };
76376
76515
  }
76377
76516
  asset(id5) {
76378
76517
  const value = this.assets.get(id5);
@@ -76504,7 +76643,7 @@ import { constants as constants5 } from "node:fs";
76504
76643
  import { chmod as chmod2, lstat as lstat5, mkdir as mkdir2, open as open6 } from "node:fs/promises";
76505
76644
  import { execFile as execFile11 } from "node:child_process";
76506
76645
  import { promisify as promisify4 } from "node:util";
76507
- import path40 from "node:path";
76646
+ import path41 from "node:path";
76508
76647
  async function preparePrivateImageRoot(directory) {
76509
76648
  if (process.platform === "win32") {
76510
76649
  await ensureWindowsPrivateDirectoryAsync(directory);
@@ -76520,7 +76659,7 @@ async function createPrivateImageDirectory(directory) {
76520
76659
  return;
76521
76660
  }
76522
76661
  directory = localWindowsPath(directory);
76523
- const parent = await openPrivateImageDirectory(path40.dirname(directory));
76662
+ const parent = await openPrivateImageDirectory(path41.dirname(directory));
76524
76663
  try {
76525
76664
  await parent.verify();
76526
76665
  await mkdir2(directory, { mode: 448 });
@@ -76543,7 +76682,7 @@ Check-PrivateDirectory $env:NIUMA_IMAGE_DIRECTORY
76543
76682
  }
76544
76683
  async function openPrivateImageDirectory(requested, openFile2 = open6) {
76545
76684
  const windows2 = process.platform === "win32";
76546
- const directory = windows2 ? localWindowsPath(requested) : path40.resolve(requested);
76685
+ const directory = windows2 ? localWindowsPath(requested) : path41.resolve(requested);
76547
76686
  const initial = await lstat5(directory, { bigint: true });
76548
76687
  if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable10();
76549
76688
  let handle;
@@ -76652,7 +76791,7 @@ var init_private_image_files = __esm({
76652
76791
  // apps/desktop/src/platform/private-image-commit.ts
76653
76792
  import { randomUUID as randomUUID45 } from "node:crypto";
76654
76793
  import { lstat as lstat6, rename as rename2, rm as rm2 } from "node:fs/promises";
76655
- import path41 from "node:path";
76794
+ import path42 from "node:path";
76656
76795
  async function snapshot(file, maxBytes) {
76657
76796
  try {
76658
76797
  await lstat6(file);
@@ -76717,7 +76856,7 @@ var init_private_image_commit = __esm({
76717
76856
  await this.writeBinary(file, bytes3, maxBytes);
76718
76857
  return;
76719
76858
  }
76720
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76859
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76721
76860
  try {
76722
76861
  const handle = await privateBinaryFiles.open(file, { maxBytes, writable: true, mode: "mutable" });
76723
76862
  try {
@@ -76752,7 +76891,7 @@ var init_private_image_commit = __esm({
76752
76891
  }
76753
76892
  },
76754
76893
  async writeBinary(file, bytes3, maxBytes) {
76755
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76894
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76756
76895
  try {
76757
76896
  await directory.verify();
76758
76897
  await writeNew(file, bytes3, maxBytes);
@@ -76765,8 +76904,8 @@ var init_private_image_commit = __esm({
76765
76904
  const bytes3 = Buffer.from(input);
76766
76905
  let published = false, renameAttempted = false;
76767
76906
  let temporaryIdentity;
76768
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76769
- const temporary = path41.join(path41.dirname(file), `.manifest-${randomUUID45()}.tmp`);
76907
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76908
+ const temporary = path42.join(path42.dirname(file), `.manifest-${randomUUID45()}.tmp`);
76770
76909
  try {
76771
76910
  if (bytes3.length > maxBytes) throw new PrivateImageCommitError();
76772
76911
  new TextDecoder("utf-8", { fatal: true }).decode(bytes3);
@@ -76814,14 +76953,14 @@ var init_private_image_commit = __esm({
76814
76953
  });
76815
76954
 
76816
76955
  // apps/desktop/src/platform/private-document-directory.ts
76817
- import fs26 from "node:fs";
76818
- import path42 from "node:path";
76956
+ import fs27 from "node:fs";
76957
+ import path43 from "node:path";
76819
76958
  async function openPrivateDocumentDirectory(root) {
76820
- const directory = path42.resolve(root);
76959
+ const directory = path43.resolve(root);
76821
76960
  let identity6;
76822
76961
  try {
76823
76962
  privateLogFiles.ensureDirectory(directory);
76824
- identity6 = fs26.lstatSync(directory, { bigint: true });
76963
+ identity6 = fs27.lstatSync(directory, { bigint: true });
76825
76964
  privateLogFiles.checkDirectory(directory);
76826
76965
  guard();
76827
76966
  } catch {
@@ -76829,7 +76968,7 @@ async function openPrivateDocumentDirectory(root) {
76829
76968
  }
76830
76969
  function guard() {
76831
76970
  try {
76832
- const current2 = fs26.lstatSync(directory, { bigint: true });
76971
+ const current2 = fs27.lstatSync(directory, { bigint: true });
76833
76972
  if (!current2.isDirectory() || current2.isSymbolicLink() || current2.dev !== identity6.dev || current2.ino !== identity6.ino) {
76834
76973
  throw new PrivateDocumentFileError("unavailable");
76835
76974
  }
@@ -76842,7 +76981,7 @@ async function openPrivateDocumentDirectory(root) {
76842
76981
  if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(name2) || name2 === "." || name2 === "..") {
76843
76982
  throw new PrivateDocumentFileError("unavailable");
76844
76983
  }
76845
- return path42.join(directory, name2);
76984
+ return path43.join(directory, name2);
76846
76985
  }
76847
76986
  const files = privateStateFilesWithGuard(guard);
76848
76987
  return {
@@ -76874,7 +77013,7 @@ var init_private_document_directory = __esm({
76874
77013
  });
76875
77014
 
76876
77015
  // apps/desktop/src/attachments/store.ts
76877
- import { createHash as createHash34, randomUUID as randomUUID46 } from "node:crypto";
77016
+ import { createHash as createHash35, randomUUID as randomUUID46 } from "node:crypto";
76878
77017
  import { constants as constants6 } from "node:fs";
76879
77018
  import {
76880
77019
  chmod as chmod3,
@@ -76924,38 +77063,38 @@ function decodeBase64(value) {
76924
77063
  return decoded;
76925
77064
  }
76926
77065
  function sha256(value) {
76927
- return createHash34("sha256").update(value).digest("hex");
77066
+ return createHash35("sha256").update(value).digest("hex");
76928
77067
  }
76929
- async function readJsonManifest(path55, io) {
77068
+ async function readJsonManifest(path56, io) {
76930
77069
  try {
76931
77070
  if (io.controlledFiles) {
76932
- const { data } = await io.controlledFiles.read(path55);
77071
+ const { data } = await io.controlledFiles.read(path56);
76933
77072
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(data));
76934
77073
  }
76935
- const status2 = await lstat7(path55);
77074
+ const status2 = await lstat7(path56);
76936
77075
  if (!status2.isFile() || status2.isSymbolicLink()) {
76937
77076
  return null;
76938
77077
  }
76939
- return JSON.parse(await readFile2(path55, "utf8"));
77078
+ return JSON.parse(await readFile2(path56, "utf8"));
76940
77079
  } catch {
76941
77080
  return null;
76942
77081
  }
76943
77082
  }
76944
- async function assertRegularControlledFile(directoryPath, path55) {
76945
- if (dirname3(path55) !== directoryPath) {
77083
+ async function assertRegularControlledFile(directoryPath, path56) {
77084
+ if (dirname3(path56) !== directoryPath) {
76946
77085
  throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
76947
77086
  }
76948
- const status2 = await lstat7(path55).catch(() => null);
77087
+ const status2 = await lstat7(path56).catch(() => null);
76949
77088
  if (!status2?.isFile() || status2.isSymbolicLink()) {
76950
77089
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
76951
77090
  }
76952
77091
  }
76953
- async function readRegularFileNoFollow(io, directoryPath, path55, expectedIdentity, expectedSize) {
76954
- if (dirname3(path55) !== directoryPath) {
77092
+ async function readRegularFileNoFollow(io, directoryPath, path56, expectedIdentity, expectedSize) {
77093
+ if (dirname3(path56) !== directoryPath) {
76955
77094
  throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
76956
77095
  }
76957
- if (io.controlledFiles) return io.controlledFiles.read(path55, expectedIdentity, expectedSize);
76958
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77096
+ if (io.controlledFiles) return io.controlledFiles.read(path56, expectedIdentity, expectedSize);
77097
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
76959
77098
  if (!handle) {
76960
77099
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
76961
77100
  }
@@ -76979,8 +77118,8 @@ async function readRegularFileNoFollow(io, directoryPath, path55, expectedIdenti
76979
77118
  await handle.close();
76980
77119
  }
76981
77120
  }
76982
- async function readStableLocalFile(io, path55) {
76983
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77121
+ async function readStableLocalFile(io, path56) {
77122
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
76984
77123
  if (!handle) {
76985
77124
  throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
76986
77125
  }
@@ -76992,8 +77131,8 @@ async function readStableLocalFile(io, path55) {
76992
77131
  if (openedStatus.size > BigInt(MAX_IMAGE_BYTES)) {
76993
77132
  throw new Error("ATTACHMENT_TOO_LARGE");
76994
77133
  }
76995
- const canonicalPath = await realpath3(path55).catch(() => null);
76996
- const currentStatus = await lstat7(path55, { bigint: true }).catch(() => null);
77134
+ const canonicalPath = await realpath3(path56).catch(() => null);
77135
+ const currentStatus = await lstat7(path56, { bigint: true }).catch(() => null);
76997
77136
  if (!canonicalPath || !currentStatus?.isFile() || currentStatus.isSymbolicLink() || currentStatus.dev !== openedStatus.dev || currentStatus.ino !== openedStatus.ino) {
76998
77137
  throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
76999
77138
  }
@@ -77006,17 +77145,17 @@ async function readStableLocalFile(io, path55) {
77006
77145
  await handle.close();
77007
77146
  }
77008
77147
  }
77009
- async function pathIsMissing(path55) {
77148
+ async function pathIsMissing(path56) {
77010
77149
  try {
77011
- await lstat7(path55);
77150
+ await lstat7(path56);
77012
77151
  return false;
77013
77152
  } catch (error2) {
77014
77153
  return error2.code === "ENOENT";
77015
77154
  }
77016
77155
  }
77017
- async function readFileIdentity(io, path55) {
77018
- if (io.controlledFiles) return io.controlledFiles.identity(path55);
77019
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77156
+ async function readFileIdentity(io, path56) {
77157
+ if (io.controlledFiles) return io.controlledFiles.identity(path56);
77158
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77020
77159
  if (!handle) {
77021
77160
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
77022
77161
  }
@@ -77131,7 +77270,7 @@ var init_store = __esm({
77131
77270
  webp: "image/webp"
77132
77271
  };
77133
77272
  DEFAULT_ATTACHMENT_STORE_IO = {
77134
- open: (path55, flags) => open7(path55, flags),
77273
+ open: (path56, flags) => open7(path56, flags),
77135
77274
  controlledFiles: privateImageFiles
77136
77275
  };
77137
77276
  AttachmentStore = class _AttachmentStore {
@@ -77344,15 +77483,15 @@ var init_store = __esm({
77344
77483
  const allowed = /* @__PURE__ */ new Set([MANIFEST_RELATIVE_PATH, ...next.chunks.map((chunk) => chunk.relativePath)]);
77345
77484
  if ((await readdir2(upload.directoryPath)).some((name2) => !allowed.has(name2))) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
77346
77485
  for (let offset = 0; offset < chunks.length; offset++) {
77347
- const path55 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
77486
+ const path56 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
77348
77487
  let handle;
77349
77488
  try {
77350
- handle = await this.#io.open(path55, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
77489
+ handle = await this.#io.open(path56, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
77351
77490
  } catch (error2) {
77352
77491
  if (error2.code !== "EEXIST") throw error2;
77353
- const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path55, void 0, chunk.length);
77492
+ const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path56, void 0, chunk.length);
77354
77493
  if (!stored.data.equals(chunk)) throw new Error("CHUNK_CONFLICT");
77355
- handle = await this.#io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW);
77494
+ handle = await this.#io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW);
77356
77495
  }
77357
77496
  try {
77358
77497
  const status2 = await handle.stat();
@@ -77458,7 +77597,7 @@ var init_store = __esm({
77458
77597
  if (!await this.#isVerifiedUpload(upload)) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
77459
77598
  const chunks = [...upload.manifest.chunks].sort((a, b) => a.index - b.index);
77460
77599
  if (chunks.length !== Math.ceil(upload.manifest.byteSize / MAX_CHUNK_BYTES) || chunks.some((chunk, i) => chunk.index !== i)) throw new Error("UPLOAD_SIZE_MISMATCH");
77461
- const hash3 = createHash34("sha256");
77600
+ const hash3 = createHash35("sha256");
77462
77601
  for (const chunk of chunks) {
77463
77602
  hash3.update(await this.#readUploadChunk(upload, chunk));
77464
77603
  }
@@ -77732,9 +77871,9 @@ var init_store = __esm({
77732
77871
  await this.#imageAssets.removeBytes(record26.id);
77733
77872
  continue;
77734
77873
  }
77735
- for (const path55 of [record26.sourcePath, record26.previewPath]) {
77736
- const status2 = await lstat7(path55).catch(() => null);
77737
- if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(path55);
77874
+ for (const path56 of [record26.sourcePath, record26.previewPath]) {
77875
+ const status2 = await lstat7(path56).catch(() => null);
77876
+ if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(path56);
77738
77877
  }
77739
77878
  }
77740
77879
  }
@@ -78272,10 +78411,10 @@ var init_store = __esm({
78272
78411
  return bytes3;
78273
78412
  }
78274
78413
  async #loadBindingIndex() {
78275
- const path55 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78276
- const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(path55, this.#io);
78414
+ const path56 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78415
+ const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(path56, this.#io);
78277
78416
  if (manifest === null) {
78278
- if (this.#rawCommit && !await pathIsMissing(path55)) this.#bindingUnavailable = true;
78417
+ if (this.#rawCommit && !await pathIsMissing(path56)) this.#bindingUnavailable = true;
78279
78418
  return;
78280
78419
  }
78281
78420
  if (!isBindingIndexManifest(manifest)) {
@@ -78335,14 +78474,14 @@ var init_store = __esm({
78335
78474
  return;
78336
78475
  }
78337
78476
  const temporaryPath = join2(this.#rootDir, `.bindings-${randomUUID46()}.tmp`);
78338
- const path55 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78477
+ const path56 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78339
78478
  await writeFile(temporaryPath, `${JSON.stringify(manifest)}
78340
78479
  `, {
78341
78480
  flag: "wx",
78342
78481
  mode: 384
78343
78482
  });
78344
- await rename3(temporaryPath, path55);
78345
- await chmod3(path55, 384);
78483
+ await rename3(temporaryPath, path56);
78484
+ await chmod3(path56, 384);
78346
78485
  }
78347
78486
  #commitBindings(bindings) {
78348
78487
  this.#bindings.clear();
@@ -78918,7 +79057,7 @@ var init_message_bindings = __esm({
78918
79057
  });
78919
79058
 
78920
79059
  // apps/desktop/src/attachments/managed-store.ts
78921
- import { createHash as createHash35, randomUUID as randomUUID47 } from "node:crypto";
79060
+ import { createHash as createHash36, randomUUID as randomUUID47 } from "node:crypto";
78922
79061
  function storedIdentity(identity6) {
78923
79062
  return identity6.kind === "native" ? identity6.file : identity6;
78924
79063
  }
@@ -78977,7 +79116,7 @@ var init_managed_store = __esm({
78977
79116
  refPattern = /^(?:attf_|att_)[0-9a-f-]{36}$/;
78978
79117
  digestPattern = /^[0-9a-f]{64}$/;
78979
79118
  error = (kind) => new Error("MANAGED_ATTACHMENT_" + kind);
78980
- digest3 = (bytes3) => createHash35("sha256").update(bytes3).digest("hex");
79119
+ digest3 = (bytes3) => createHash36("sha256").update(bytes3).digest("hex");
78981
79120
  ManagedAttachmentStore = class _ManagedAttachmentStore {
78982
79121
  constructor(contents, now, sourceFiles) {
78983
79122
  this.contents = contents;
@@ -79236,7 +79375,7 @@ var init_managed_store = __esm({
79236
79375
  await this.mutate(async () => {
79237
79376
  const entry = this.entryForUpload(threadId2, uploadId), m = entry.manifest;
79238
79377
  if (m.createdAt + HOUR <= this.now() || Object.keys(m.chunks).length !== Math.ceil(m.byteSize / 49152)) throw error("INVALID");
79239
- const h = await this.sourceHandle(entry), hash3 = createHash35("sha256");
79378
+ const h = await this.sourceHandle(entry), hash3 = createHash36("sha256");
79240
79379
  await withBinaryHandle(h, async () => {
79241
79380
  if ((await h.status()).size !== m.byteSize) throw error("INVALID");
79242
79381
  const block = Buffer.alloc(49152);
@@ -79270,7 +79409,7 @@ var init_managed_store = __esm({
79270
79409
  }
79271
79410
  if (m.createdAt + HOUR <= this.now() || Object.keys(m.chunks).length !== Math.ceil(m.byteSize / 49152)) throw error("INVALID");
79272
79411
  const h = await this.sourceHandle(entry);
79273
- const hash3 = createHash35("sha256");
79412
+ const hash3 = createHash36("sha256");
79274
79413
  await withBinaryHandle(h, async () => {
79275
79414
  const status2 = await h.status();
79276
79415
  if (status2.size !== m.byteSize) throw error("INVALID");
@@ -79454,7 +79593,7 @@ var init_managed_store = __esm({
79454
79593
  });
79455
79594
 
79456
79595
  // apps/desktop/src/daemon/runtime/attachment-storage.ts
79457
- import path43 from "node:path";
79596
+ import path44 from "node:path";
79458
79597
  import { randomUUID as randomUUID48 } from "node:crypto";
79459
79598
  var ATTACHMENT_CLEANUP_INTERVAL_MS, RuntimeAttachmentStorage;
79460
79599
  var init_attachment_storage = __esm({
@@ -79596,7 +79735,7 @@ var init_attachment_storage = __esm({
79596
79735
  requireAttachmentMessageBindings() {
79597
79736
  if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
79598
79737
  if (!this.attachmentMessageBindingsPromise) {
79599
- this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path43.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
79738
+ this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path44.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
79600
79739
  this.attachmentMessageBindings = store;
79601
79740
  return store;
79602
79741
  }).catch((error2) => {
@@ -79612,7 +79751,7 @@ var init_attachment_storage = __esm({
79612
79751
  if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
79613
79752
  if (!this.managedAttachmentStorePromise) {
79614
79753
  const opening = runManagedAttachmentOperation(() => ManagedAttachmentStore.open(
79615
- path43.join(this.ports.dataDirectory(), "attachments", "managed")
79754
+ path44.join(this.ports.dataDirectory(), "attachments", "managed")
79616
79755
  )).catch((error2) => {
79617
79756
  if (this.managedAttachmentStorePromise === opening) this.managedAttachmentStorePromise = null;
79618
79757
  throw error2;
@@ -80672,7 +80811,7 @@ var init_daemon_metrics_store = __esm({
80672
80811
  });
80673
80812
 
80674
80813
  // apps/desktop/src/daemon/daemon-metrics.ts
80675
- import os3 from "node:os";
80814
+ import os4 from "node:os";
80676
80815
  import process7 from "node:process";
80677
80816
  function roundMetric(value) {
80678
80817
  return Math.round(value * 10) / 10;
@@ -80721,7 +80860,7 @@ var init_daemon_metrics = __esm({
80721
80860
  this.nowMs = options.nowMs ?? (() => Date.now());
80722
80861
  this.cpuUsage = options.cpuUsage ?? (() => process7.cpuUsage());
80723
80862
  this.memoryUsage = options.memoryUsage ?? (() => process7.memoryUsage());
80724
- this.cpuCount = Math.max(1, options.cpuCount ?? os3.cpus().length);
80863
+ this.cpuCount = Math.max(1, options.cpuCount ?? os4.cpus().length);
80725
80864
  this.pid = options.pid ?? process7.pid;
80726
80865
  this.sampleIntervalMs = options.sampleIntervalMs ?? DAEMON_METRICS_SAMPLE_INTERVAL_MS;
80727
80866
  this.retentionMs = Math.min(options.retentionMs ?? DAEMON_METRICS_RETENTION_MS, DAEMON_METRICS_RETENTION_MS);
@@ -80974,7 +81113,7 @@ var init_control_read = __esm({
80974
81113
  });
80975
81114
 
80976
81115
  // apps/desktop/src/attachments/image-resources.ts
80977
- import { createHash as createHash36, randomUUID as randomUUID49 } from "node:crypto";
81116
+ import { createHash as createHash37, randomUUID as randomUUID49 } from "node:crypto";
80978
81117
  import { constants as constants7 } from "node:fs";
80979
81118
  import { lstat as lstat8, open as open8, realpath as realpath4 } from "node:fs/promises";
80980
81119
  import { basename as basename4, dirname as dirname4 } from "node:path";
@@ -81009,9 +81148,9 @@ function sameDeferredIdentity(source2, previous) {
81009
81148
  if (source2.kind === "history") return previous.kind === "history" && sameLocator(source2.locator, previous.locator);
81010
81149
  return source2.kind === "deferred-file" && Boolean(source2.visibilityLocator) && previous.kind !== "history" && previous.kind !== "app-server-image" && (previous.kind === "file" || source2.path === previous.path) && sameLocator(source2.visibilityLocator, previous.visibilityLocator);
81011
81150
  }
81012
- async function readSourceFile(path55, signal) {
81151
+ async function readSourceFile(path56, signal) {
81013
81152
  signal?.throwIfAborted();
81014
- const handle = await open8(path55, constants7.O_RDONLY | constants7.O_NOFOLLOW);
81153
+ const handle = await open8(path56, constants7.O_RDONLY | constants7.O_NOFOLLOW);
81015
81154
  try {
81016
81155
  const before = await handle.stat({ bigint: true });
81017
81156
  if (!before.isFile() || before.size <= 0 || before.size > MAX_BYTES9) throw new NiumaError("ATTACHMENT_RESOURCE_LIMIT", "\u56FE\u7247\u8BFB\u53D6\u8D85\u51FA\u8D44\u6E90\u9650\u5236");
@@ -81068,7 +81207,7 @@ var init_image_resources = __esm({
81068
81207
  INDEX_BYTES = 16 * 1024 * 1024;
81069
81208
  CHUNK_BYTES2 = 256 * 1024;
81070
81209
  ID = /^att_[0-9a-f-]{36}$/;
81071
- digest4 = (bytes3) => createHash36("sha256").update(bytes3).digest("hex");
81210
+ digest4 = (bytes3) => createHash37("sha256").update(bytes3).digest("hex");
81072
81211
  hashSchema = z16.string().regex(/^[0-9a-f]{64}$/);
81073
81212
  natural = z16.number().int().nonnegative();
81074
81213
  absolutePath = z16.string().max(16384).refine((value) => localResourcePaths.parseLocal(value) !== null);
@@ -81240,12 +81379,12 @@ var init_image_resources = __esm({
81240
81379
  }, JSON.stringify(identity6));
81241
81380
  }
81242
81381
  /** 仅供已认证实时消息登记;调用方每次请求仍须验证当前 item/上传暂存资格。 */
81243
- async registerDeferredFile(threadId2, path55, resourceKey = `live-file:${threadId2}:${path55}`) {
81244
- return this.register({ resourceKey, name: basename4(path55), source: { kind: "deferred-file", threadId: threadId2, path: path55 } });
81382
+ async registerDeferredFile(threadId2, path56, resourceKey = `live-file:${threadId2}:${path56}`) {
81383
+ return this.register({ resourceKey, name: basename4(path56), source: { kind: "deferred-file", threadId: threadId2, path: path56 } });
81245
81384
  }
81246
- async registerFile(threadId2, path55, attachmentId, context) {
81385
+ async registerFile(threadId2, path56, attachmentId, context) {
81247
81386
  if (context && context.visibilityLocator.threadId !== threadId2) throw missing3();
81248
- const canonical = await realpath4(path55);
81387
+ const canonical = await realpath4(path56);
81249
81388
  const file = await readSourceFile(canonical);
81250
81389
  return this.register({ attachmentId, resourceKey: context?.resourceKey ?? `file:${threadId2}:${canonical}`, name: basename4(canonical), source: {
81251
81390
  kind: "file",
@@ -81275,9 +81414,9 @@ var init_image_resources = __esm({
81275
81414
  return sameLocator(this.historyLocator(threadId2, attachmentId) ?? void 0, expectedLocator);
81276
81415
  }
81277
81416
  /** 保留原件换源时只复用相同受控文件;历史别名和旧暂存不能遮蔽新来源。 */
81278
- matchesFilePath(threadId2, attachmentId, path55) {
81417
+ matchesFilePath(threadId2, attachmentId, path56) {
81279
81418
  const entry = this.entries.get(attachmentId);
81280
- return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path === path55;
81419
+ return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path === path56;
81281
81420
  }
81282
81421
  has(threadId2, attachmentId) {
81283
81422
  const entry = this.entries.get(attachmentId);
@@ -81681,9 +81820,9 @@ var init_image_confirmation2 = __esm({
81681
81820
  });
81682
81821
 
81683
81822
  // apps/desktop/src/daemon/runtime/images.ts
81684
- import { createHash as createHash37 } from "node:crypto";
81823
+ import { createHash as createHash38 } from "node:crypto";
81685
81824
  import { realpath as realpath5 } from "node:fs/promises";
81686
- import path44 from "node:path";
81825
+ import path45 from "node:path";
81687
81826
  function objectRecord12(value) {
81688
81827
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
81689
81828
  }
@@ -81764,7 +81903,7 @@ var init_images = __esm({
81764
81903
  if (!url?.startsWith("data:image/")) continue;
81765
81904
  const resources = await this.requireImageResources();
81766
81905
  assertCurrent();
81767
- const sourceHash = createHash37("sha256").update(url).digest("hex");
81906
+ const sourceHash = createHash38("sha256").update(url).digest("hex");
81768
81907
  const registered = await resources.register({
81769
81908
  resourceKey: `app-server:${threadId2}:${turn.id}:${item.id}:${partIndex}:${sourceHash}`,
81770
81909
  name: "\u56FE\u7247",
@@ -81783,7 +81922,7 @@ var init_images = __esm({
81783
81922
  }
81784
81923
  localImageKey(threadId2, sourcePath, itemId, partIndex) {
81785
81924
  const embedded = sourcePath.startsWith("data:image/");
81786
- const source2 = embedded ? createHash37("sha256").update(sourcePath).digest("hex") : sourcePath;
81925
+ const source2 = embedded ? createHash38("sha256").update(sourcePath).digest("hex") : sourcePath;
81787
81926
  return `${threadId2}\0${itemId ? JSON.stringify(embedded ? [itemId, partIndex, source2] : [itemId, partIndex ?? source2]) : source2}`;
81788
81927
  }
81789
81928
  resolveKnownLocalImage(threadId2, sourcePath, itemId, partIndex) {
@@ -81802,7 +81941,7 @@ var init_images = __esm({
81802
81941
  if (itemId && ["userMessage", "UserMessage", "user_message"].includes(String(item.type))) {
81803
81942
  if (Array.isArray(item.content)) item.content.forEach((part, index) => {
81804
81943
  const input = objectRecord12(part);
81805
- if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" && path44.isAbsolute(input.path)) registrations.push(this.importThreadImage(threadId2, input.path, itemId, index));
81944
+ if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" && path45.isAbsolute(input.path)) registrations.push(this.importThreadImage(threadId2, input.path, itemId, index));
81806
81945
  const url = input.type === "image" ? nonEmptyString19(input.url ?? input.image_url) : null;
81807
81946
  if (url?.startsWith("data:image/")) registrations.push(this.importThreadImage(threadId2, url, itemId, index));
81808
81947
  });
@@ -81826,7 +81965,7 @@ var init_images = __esm({
81826
81965
  requireImageResources() {
81827
81966
  if (!this.ports.attachmentReady()) throw new Error("\u56FE\u7247\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
81828
81967
  if (!this.imageResourcesPromise) this.imageResourcesPromise = ImageResources.create({
81829
- indexPath: path44.join(this.ports.dataDirectory(), "image-resources", "index.json"),
81968
+ indexPath: path45.join(this.ports.dataDirectory(), "image-resources", "index.json"),
81830
81969
  readAppServerImage: (source2, signal) => this.readAppServerImage(source2, signal),
81831
81970
  onDiagnostic: (event) => this.ports.diagnostic(event)
81832
81971
  }).catch((error2) => {
@@ -81863,7 +82002,7 @@ var init_images = __esm({
81863
82002
  const items = source2.turnId !== void 0 && turns.length !== 1 ? [] : turns.flatMap((turn) => Array.isArray(turn.items) ? turn.items.map(objectRecord12).filter((item) => item.id === source2.itemId && item.type === "userMessage") : []);
81864
82003
  const part = objectRecord12(items.length === 1 && Array.isArray(items[0].content) ? items[0].content[source2.partIndex] : null);
81865
82004
  const url = part.type === "image" ? nonEmptyString19(part.url ?? part.image_url) : null;
81866
- if (!url || url.length > Math.ceil(20 * 1024 * 1024 / 3) * 4 + 64 || createHash37("sha256").update(url).digest("hex") !== source2.sourceHash) {
82005
+ if (!url || url.length > Math.ceil(20 * 1024 * 1024 / 3) * 4 + 64 || createHash38("sha256").update(url).digest("hex") !== source2.sourceHash) {
81867
82006
  throw new NiumaError("ATTACHMENT_VERSION_CHANGED", "\u56FE\u7247\u7248\u672C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D");
81868
82007
  }
81869
82008
  const match = /^data:image\/(?:png|jpeg|webp|gif);base64,([A-Za-z0-9+/]+={0,2})$/.exec(url);
@@ -82007,7 +82146,7 @@ var init_images = __esm({
82007
82146
  /** 同一消息引用共享轻量登记;整个 Runtime 最多同时处理四个索引写入。 */
82008
82147
  importThreadImage(threadId2, sourcePath, itemId, partIndex, sourceIsCurrent = () => true) {
82009
82148
  const embedded = sourcePath.startsWith("data:image/") && Number.isSafeInteger(partIndex) && partIndex >= 0;
82010
- if (!itemId || !path44.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
82149
+ if (!itemId || !path45.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
82011
82150
  const generation = this.ports.generation();
82012
82151
  const key = this.localImageKey(threadId2, sourcePath, itemId, partIndex);
82013
82152
  const routeGeneration = this.ports.controlGeneration(threadId2);
@@ -82038,13 +82177,13 @@ var init_images = __esm({
82038
82177
  threadId: threadId2,
82039
82178
  itemId,
82040
82179
  partIndex,
82041
- sourceHash: createHash37("sha256").update(sourcePath).digest("hex")
82180
+ sourceHash: createHash38("sha256").update(sourcePath).digest("hex")
82042
82181
  } }) : await resources.registerDeferredFile(threadId2, sourcePath, `live:${key}`);
82043
82182
  if (!current2()) return;
82044
82183
  this.knownLocalImages.set(key, {
82045
82184
  type: "image",
82046
82185
  attachmentId: registered.attachmentId,
82047
- name: embedded ? "\u56FE\u7247" : path44.basename(sourcePath),
82186
+ name: embedded ? "\u56FE\u7247" : path45.basename(sourcePath),
82048
82187
  previewAvailable: false,
82049
82188
  previewState: "deferred"
82050
82189
  });
@@ -84130,18 +84269,18 @@ var init_session_sources = __esm({
84130
84269
  const isCurrent = () => options.isCurrent?.() !== false;
84131
84270
  const paths = /* @__PURE__ */ new Map();
84132
84271
  for (const thread4 of threads) {
84133
- const path55 = typeof thread4.path === "string" && thread4.path.length > 0 ? thread4.path : null;
84134
- if (!paths.has(thread4.id)) paths.set(thread4.id, path55);
84135
- else if (paths.get(thread4.id) !== path55) paths.set(thread4.id, void 0);
84272
+ const path56 = typeof thread4.path === "string" && thread4.path.length > 0 ? thread4.path : null;
84273
+ if (!paths.has(thread4.id)) paths.set(thread4.id, path56);
84274
+ else if (paths.get(thread4.id) !== path56) paths.set(thread4.id, void 0);
84136
84275
  }
84137
- for (const [id5, path55] of paths) {
84276
+ for (const [id5, path56] of paths) {
84138
84277
  const thread4 = { id: id5 };
84139
84278
  if (!isCurrent()) return;
84140
84279
  const token3 = this.begin(thread4.id);
84141
84280
  let resolution = null;
84142
84281
  if (resolver) {
84143
84282
  try {
84144
- resolution = await resolver.resolve(thread4.id, path55);
84283
+ resolution = await resolver.resolve(thread4.id, path56);
84145
84284
  } catch {
84146
84285
  resolution = null;
84147
84286
  }
@@ -84206,7 +84345,7 @@ var init_session_sources = __esm({
84206
84345
  });
84207
84346
 
84208
84347
  // apps/desktop/src/daemon/runtime/settings-selection.ts
84209
- import path45 from "node:path";
84348
+ import path46 from "node:path";
84210
84349
  var RuntimeSettingsSelection;
84211
84350
  var init_settings_selection = __esm({
84212
84351
  "apps/desktop/src/daemon/runtime/settings-selection.ts"() {
@@ -84222,7 +84361,7 @@ var init_settings_selection = __esm({
84222
84361
  ports;
84223
84362
  targetProjectRoot(cwd) {
84224
84363
  const matched = this.ports.projectRoots().filter((projectRoot) => pathBelongsToProjectRoot(projectRoot, cwd)).sort((left, right) => right.length - left.length)[0];
84225
- return matched ?? path45.normalize(cwd);
84364
+ return matched ?? path46.normalize(cwd);
84226
84365
  }
84227
84366
  inheritedCreate(threadId2) {
84228
84367
  const empty = { authorization: null, model: null };
@@ -84440,7 +84579,7 @@ var init_thread_routing = __esm({
84440
84579
  });
84441
84580
 
84442
84581
  // apps/desktop/src/platform/computer-name.ts
84443
- import os4 from "node:os";
84582
+ import os5 from "node:os";
84444
84583
  import { execFileSync as execFileSync3 } from "node:child_process";
84445
84584
  function systemComputerName() {
84446
84585
  if (desktopPlatform().id === "macos") {
@@ -84455,10 +84594,10 @@ function systemComputerName() {
84455
84594
  } catch {
84456
84595
  }
84457
84596
  }
84458
- return os4.hostname();
84597
+ return os5.hostname();
84459
84598
  }
84460
84599
  function systemHostname() {
84461
- return os4.hostname();
84600
+ return os5.hostname();
84462
84601
  }
84463
84602
  var init_computer_name = __esm({
84464
84603
  "apps/desktop/src/platform/computer-name.ts"() {
@@ -84566,7 +84705,7 @@ var init_device_name = __esm({
84566
84705
  });
84567
84706
 
84568
84707
  // apps/desktop/src/daemon/debug-log.ts
84569
- import path46 from "node:path";
84708
+ import path47 from "node:path";
84570
84709
  function isNotificationDeliveryReason(value) {
84571
84710
  return NOTIFICATION_DELIVERY_REASON_CODES.has(value) || /^http_[1-5]\d\d$/.test(value) || /^business_\d{1,6}$/.test(value);
84572
84711
  }
@@ -84605,10 +84744,10 @@ function hasDebugFilter(filter) {
84605
84744
  return Boolean(filter?.components || filter?.channels || filter?.events);
84606
84745
  }
84607
84746
  function createSafeFilePath(runtimeDir, files) {
84608
- const dir = path46.join(runtimeDir, "debug");
84747
+ const dir = path47.join(runtimeDir, "debug");
84609
84748
  files.ensureDirectory(dir);
84610
84749
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
84611
- return path46.join(dir, `${timestamp}-${process.pid}.ndjson`);
84750
+ return path47.join(dir, `${timestamp}-${process.pid}.ndjson`);
84612
84751
  }
84613
84752
  function createFileDebugLogger(filePath, shouldWrite, files) {
84614
84753
  let writer;
@@ -85214,7 +85353,7 @@ function withoutPersistentImageBytes(value, key = "", seen = /* @__PURE__ */ new
85214
85353
  function createFileRawDebugLogger(runtimeDir, filter, policy, files) {
85215
85354
  const now = policy.now ?? (() => /* @__PURE__ */ new Date());
85216
85355
  const manager = new RawDebugFileManager(
85217
- path46.join(runtimeDir, "debug"),
85356
+ path47.join(runtimeDir, "debug"),
85218
85357
  now,
85219
85358
  policy.maxSegmentBytes ?? RAW_DEBUG_MAX_SEGMENT_BYTES,
85220
85359
  policy.maxSegments ?? RAW_DEBUG_MAX_SEGMENTS,
@@ -86225,7 +86364,7 @@ var init_debug_log = __esm({
86225
86364
  }
86226
86365
  const timestamp = this.now().toISOString().replace(/[:.]/g, "-");
86227
86366
  for (; ; ) {
86228
- const filePath = path46.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
86367
+ const filePath = path47.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
86229
86368
  try {
86230
86369
  return this.files.create(filePath);
86231
86370
  } catch (error2) {
@@ -86258,7 +86397,7 @@ var init_debug_log = __esm({
86258
86397
  });
86259
86398
 
86260
86399
  // apps/desktop/src/daemon/control-observability.ts
86261
- import path47 from "node:path";
86400
+ import path48 from "node:path";
86262
86401
  function isRecentControlTimestamp(timestampMs, nowMs) {
86263
86402
  return timestampMs <= nowMs && isRetainedDaemonLogTimestamp(timestampMs, nowMs);
86264
86403
  }
@@ -86291,7 +86430,7 @@ function page3(values, params) {
86291
86430
  };
86292
86431
  }
86293
86432
  function listControlLogs(input) {
86294
- const directoryPath = path47.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
86433
+ const directoryPath = path48.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
86295
86434
  const values = [];
86296
86435
  let totalBytes = 0;
86297
86436
  let processedLines = 0;
@@ -87314,7 +87453,7 @@ var init_composition = __esm({
87314
87453
  refreshFallback: async (id5, token3) => {
87315
87454
  await this.historySnapshot.tryRefreshThreadMessages(id5, false, { kind: "fallback", token: token3 });
87316
87455
  },
87317
- resolveKnownLocalImage: (id5, path55, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path55, itemId, partIndex),
87456
+ resolveKnownLocalImage: (id5, path56, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path56, itemId, partIndex),
87318
87457
  hasDesktopSnapshot: (id5) => this.controlAccess.snapshot(id5).hasCurrentDesktopSnapshot,
87319
87458
  followerPhase: (id5) => this.followerCoordination.activeThreadFollowerCoordinatorValue?.phaseFor(id5) ?? null,
87320
87459
  generation: () => this.lifecycle.runtimeGenerationValue
@@ -88910,7 +89049,7 @@ var init_runtime2 = __esm({
88910
89049
 
88911
89050
  // apps/desktop/src/daemon/follower-open-trace.ts
88912
89051
  import { randomUUID as randomUUID51 } from "node:crypto";
88913
- import path48 from "node:path";
89052
+ import path49 from "node:path";
88914
89053
  function isFiniteTimestamp2(value) {
88915
89054
  return typeof value === "number" && Number.isFinite(value) && Number.isSafeInteger(value);
88916
89055
  }
@@ -89048,7 +89187,7 @@ function parseRecord2(line) {
89048
89187
  function listPrivateTraceFiles(runtimeDir, storage) {
89049
89188
  try {
89050
89189
  storage.checkDirectory(runtimeDir);
89051
- const scan = storage.scan(path48.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
89190
+ const scan = storage.scan(path49.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
89052
89191
  const files = [];
89053
89192
  let incomplete = scan.truncated;
89054
89193
  for (const entry of scan.entries) {
@@ -89062,8 +89201,8 @@ function listPrivateTraceFiles(runtimeDir, storage) {
89062
89201
  }
89063
89202
  }
89064
89203
  function compareTraceFilePaths(left, right) {
89065
- const a = path48.basename(left);
89066
- const b = path48.basename(right);
89204
+ const a = path49.basename(left);
89205
+ const b = path49.basename(right);
89067
89206
  return a.slice(0, 10).localeCompare(b.slice(0, 10)) || Number(a.slice(11, -7)) - Number(b.slice(11, -7));
89068
89207
  }
89069
89208
  function readPrivateTraceFile(file, remainingBytes, storage) {
@@ -89580,7 +89719,7 @@ var init_follower_open_trace = __esm({
89580
89719
  }
89581
89720
  clearAll() {
89582
89721
  try {
89583
- const directoryPath = path48.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89722
+ const directoryPath = path49.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89584
89723
  this.files.checkDirectory(this.runtimeDir);
89585
89724
  let scan;
89586
89725
  try {
@@ -89637,7 +89776,7 @@ var init_follower_open_trace = __esm({
89637
89776
  }
89638
89777
  }
89639
89778
  append(record26) {
89640
- const directoryPath = path48.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89779
+ const directoryPath = path49.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89641
89780
  this.ensureTraceDirectory(directoryPath);
89642
89781
  const content2 = `${JSON.stringify(record26)}
89643
89782
  `;
@@ -89647,8 +89786,8 @@ var init_follower_open_trace = __esm({
89647
89786
  selectAppendFile(directoryPath, dateName, bytes3) {
89648
89787
  const date = dateName.slice(0, 10);
89649
89788
  let filePath = this.appendFilePath;
89650
- if (!filePath || path48.basename(filePath).slice(0, 10) !== date) {
89651
- filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ?? path48.join(directoryPath, dateName);
89789
+ if (!filePath || path49.basename(filePath).slice(0, 10) !== date) {
89790
+ filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ?? path49.join(directoryPath, dateName);
89652
89791
  }
89653
89792
  for (let attempt = 0; attempt < MAX_DIRECTORY_ENTRIES3; attempt += 1) {
89654
89793
  let stats;
@@ -89661,9 +89800,9 @@ var init_follower_open_trace = __esm({
89661
89800
  this.appendFilePath = filePath;
89662
89801
  return filePath;
89663
89802
  }
89664
- const next = Number(path48.basename(filePath).slice(11, -7)) + 1;
89803
+ const next = Number(path49.basename(filePath).slice(11, -7)) + 1;
89665
89804
  if (next > 999999) break;
89666
- filePath = path48.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
89805
+ filePath = path49.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
89667
89806
  }
89668
89807
  throw new Error("trace segment limit reached");
89669
89808
  }
@@ -89835,7 +89974,7 @@ var init_local_gateway_supervisor = __esm({
89835
89974
  });
89836
89975
 
89837
89976
  // apps/desktop/src/daemon/async-input-notification-store.ts
89838
- import { createHash as createHash38 } from "node:crypto";
89977
+ import { createHash as createHash39 } from "node:crypto";
89839
89978
  import { z as z17 } from "zod";
89840
89979
  var ASYNC_INPUT_NOTIFICATION_MAX_BYTES, identityText, entrySchema2, documentSchema2, AsyncInputNotificationStore;
89841
89980
  var init_async_input_notification_store = __esm({
@@ -89903,7 +90042,7 @@ var init_async_input_notification_store = __esm({
89903
90042
  const { threadId: threadId2, turnId, rawQuestionId } = identity6;
89904
90043
  return this.run(async () => {
89905
90044
  for (const value of [threadId2, turnId, rawQuestionId]) identityText.parse(value);
89906
- const key = createHash38("sha256").update(JSON.stringify([threadId2, turnId, rawQuestionId])).digest("hex");
90045
+ const key = createHash39("sha256").update(JSON.stringify([threadId2, turnId, rawQuestionId])).digest("hex");
89907
90046
  if (this.document.entries.some((entry) => entry.key === key)) return null;
89908
90047
  await this.persist({ version: 1, entries: [...this.document.entries, { key, threadId: threadId2, turnId, stage: "admitted" }] });
89909
90048
  return key;
@@ -91038,7 +91177,7 @@ var init_watch = __esm({
91038
91177
  });
91039
91178
 
91040
91179
  // apps/desktop/src/relay/relay-origin-store.ts
91041
- import path49 from "node:path";
91180
+ import path50 from "node:path";
91042
91181
  function parseStoredOrigin(value) {
91043
91182
  try {
91044
91183
  const document = JSON.parse(value);
@@ -91052,7 +91191,7 @@ function parseStoredOrigin(value) {
91052
91191
  }
91053
91192
  }
91054
91193
  function resolveDefaultRelayOriginStorePath() {
91055
- return path49.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
91194
+ return path50.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
91056
91195
  }
91057
91196
  var DEFAULT_FILE_NAME2, MAX_FILE_BYTES3, FileRelayOriginStore;
91058
91197
  var init_relay_origin_store = __esm({
@@ -91068,7 +91207,7 @@ var init_relay_origin_store = __esm({
91068
91207
  files;
91069
91208
  tail = Promise.resolve();
91070
91209
  constructor(options = {}) {
91071
- this.filePath = path49.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
91210
+ this.filePath = path50.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
91072
91211
  this.files = options.files ?? privateDocumentFiles;
91073
91212
  }
91074
91213
  async load() {
@@ -91104,7 +91243,7 @@ var init_relay_origin_store = __esm({
91104
91243
  });
91105
91244
 
91106
91245
  // apps/desktop/src/cli/commands/daemon.ts
91107
- import path50 from "node:path";
91246
+ import path51 from "node:path";
91108
91247
  function daemonStartFailed3() {
91109
91248
  return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
91110
91249
  }
@@ -91288,7 +91427,7 @@ async function runDaemonCommand(args, options = {}) {
91288
91427
  loggers.rawDebugLogger?.path,
91289
91428
  loggers.errorLogger?.path,
91290
91429
  // 后台 worker 的 stdout/stderr descriptor 无法安全重开,只按 daemon 所有权保护固定路径。
91291
- ...options.mode === "background" ? [path50.join(runtimeDir, "daemon-worker.log")] : []
91430
+ ...options.mode === "background" ? [path51.join(runtimeDir, "daemon-worker.log")] : []
91292
91431
  ].filter((filePath) => typeof filePath === "string")
91293
91432
  });
91294
91433
  } catch {
@@ -91747,7 +91886,7 @@ var init_auth2 = __esm({
91747
91886
  });
91748
91887
 
91749
91888
  // apps/desktop/src/control/routes.ts
91750
- import fs27 from "node:fs";
91889
+ import fs28 from "node:fs";
91751
91890
  function daemonStoppedOverview() {
91752
91891
  return {
91753
91892
  daemon: { state: "stopped" },
@@ -91766,12 +91905,12 @@ function emptyControlPage(page4, pageSize) {
91766
91905
  }
91767
91906
  function isDaemonRuntimeActive(socketPath = daemonSocketPath(), statusPath = daemonStatusPath()) {
91768
91907
  try {
91769
- const socket = fs27.lstatSync(socketPath);
91770
- const status2 = fs27.lstatSync(statusPath);
91908
+ const socket = fs28.lstatSync(socketPath);
91909
+ const status2 = fs28.lstatSync(statusPath);
91771
91910
  if (!socket.isSocket() || !status2.isFile() || status2.isSymbolicLink() || status2.size > 4 * 1024) {
91772
91911
  return false;
91773
91912
  }
91774
- const parsed = JSON.parse(fs27.readFileSync(statusPath, "utf8"));
91913
+ const parsed = JSON.parse(fs28.readFileSync(statusPath, "utf8"));
91775
91914
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || parsed.socketPath !== socketPath || !Number.isSafeInteger(parsed.pid) || parsed.pid <= 0) return false;
91776
91915
  process.kill(parsed.pid, 0);
91777
91916
  return true;
@@ -93324,8 +93463,8 @@ var init_lifecycle2 = __esm({
93324
93463
 
93325
93464
  // apps/desktop/src/control/server.ts
93326
93465
  import http4 from "node:http";
93327
- import fs28 from "node:fs";
93328
- import path51 from "node:path";
93466
+ import fs29 from "node:fs";
93467
+ import path52 from "node:path";
93329
93468
  import { createRequire as createRequire2 } from "node:module";
93330
93469
  function isControlApiPath(pathname) {
93331
93470
  const [, api, version2, control] = pathname.split("/", 4);
@@ -93371,15 +93510,15 @@ function requestHasBody(request2) {
93371
93510
  return Number(contentLength) !== 0;
93372
93511
  }
93373
93512
  function resolveExactControlWritePath(requestTarget) {
93374
- for (const path55 of [CONTROL_DEVICE_REVOKE_PATH, CONTROL_DAEMON_ACTION_PATH, CONTROL_TRACE_CLEAR_PATH]) {
93375
- if (requestTarget === path55 || requestTarget.startsWith(`${path55}?`) && !requestTarget.includes("#")) return path55;
93513
+ for (const path56 of [CONTROL_DEVICE_REVOKE_PATH, CONTROL_DAEMON_ACTION_PATH, CONTROL_TRACE_CLEAR_PATH]) {
93514
+ if (requestTarget === path56 || requestTarget.startsWith(`${path56}?`) && !requestTarget.includes("#")) return path56;
93376
93515
  }
93377
93516
  return null;
93378
93517
  }
93379
93518
  function resolveExactControlTraceReadPath(requestTarget) {
93380
- for (const path55 of [CONTROL_TRACE_LIST_PATH, CONTROL_TRACE_DETAIL_PATH]) {
93381
- if (requestTarget === path55 || requestTarget.startsWith(`${path55}?`) && !requestTarget.includes("#")) {
93382
- return path55;
93519
+ for (const path56 of [CONTROL_TRACE_LIST_PATH, CONTROL_TRACE_DETAIL_PATH]) {
93520
+ if (requestTarget === path56 || requestTarget.startsWith(`${path56}?`) && !requestTarget.includes("#")) {
93521
+ return path56;
93383
93522
  }
93384
93523
  }
93385
93524
  return null;
@@ -93400,9 +93539,9 @@ var init_server5 = __esm({
93400
93539
  init_lifecycle2();
93401
93540
  require2 = createRequire2(import.meta.url);
93402
93541
  CONTROL_PAGE_PATHS = ["/", "/connections", "/sessions", "/subscriptions", "/turn-audit", "/logs"];
93403
- CONTROL_INDEX = fs28.readFileSync(desktopAssetUrl("control", "index.html"));
93404
- BOOTSTRAP_CSS = fs28.readFileSync(require2.resolve("bootstrap/dist/css/bootstrap.min.css"));
93405
- BOOTSTRAP_BUNDLE = fs28.readFileSync(require2.resolve("bootstrap/dist/js/bootstrap.bundle.min.js"));
93542
+ CONTROL_INDEX = fs29.readFileSync(desktopAssetUrl("control", "index.html"));
93543
+ BOOTSTRAP_CSS = fs29.readFileSync(require2.resolve("bootstrap/dist/css/bootstrap.min.css"));
93544
+ BOOTSTRAP_BUNDLE = fs29.readFileSync(require2.resolve("bootstrap/dist/js/bootstrap.bundle.min.js"));
93406
93545
  STATIC_ASSETS = Object.freeze({
93407
93546
  ...Object.fromEntries(CONTROL_PAGE_PATHS.map((pathname) => [pathname, {
93408
93547
  contentType: "text/html; charset=utf-8",
@@ -93410,11 +93549,11 @@ var init_server5 = __esm({
93410
93549
  }])),
93411
93550
  "/app.js": {
93412
93551
  contentType: "application/javascript; charset=utf-8",
93413
- body: fs28.readFileSync(desktopAssetUrl("control", "app.js"))
93552
+ body: fs29.readFileSync(desktopAssetUrl("control", "app.js"))
93414
93553
  },
93415
93554
  "/chart.umd.js": {
93416
93555
  contentType: "application/javascript; charset=utf-8",
93417
- body: fs28.readFileSync(path51.join(path51.dirname(require2.resolve("chart.js")), "chart.umd.js"))
93556
+ body: fs29.readFileSync(path52.join(path52.dirname(require2.resolve("chart.js")), "chart.umd.js"))
93418
93557
  },
93419
93558
  "/bootstrap.min.css": {
93420
93559
  contentType: "text/css; charset=utf-8",
@@ -93629,42 +93768,42 @@ var init_server5 = __esm({
93629
93768
  });
93630
93769
 
93631
93770
  // apps/desktop/src/control/state.ts
93632
- import { createHash as createHash39, randomUUID as randomUUID55 } from "node:crypto";
93633
- import fs29 from "node:fs";
93634
- import path52 from "node:path";
93771
+ import { createHash as createHash40, randomUUID as randomUUID55 } from "node:crypto";
93772
+ import fs30 from "node:fs";
93773
+ import path53 from "node:path";
93635
93774
  function createControlState(input) {
93636
93775
  return createControlStateUnlocked(input);
93637
93776
  }
93638
93777
  function createControlStateUnlocked(input) {
93639
93778
  const state = toControlState(input);
93640
93779
  const statePath = controlStatePath(input.runtimeDir);
93641
- const temporaryPath = path52.join(
93642
- path52.dirname(statePath),
93643
- `.${path52.basename(statePath)}.${randomUUID55()}.tmp`
93780
+ const temporaryPath = path53.join(
93781
+ path53.dirname(statePath),
93782
+ `.${path53.basename(statePath)}.${randomUUID55()}.tmp`
93644
93783
  );
93645
93784
  let descriptor = null;
93646
93785
  let temporaryIdentity = null;
93647
93786
  let published = null;
93648
93787
  let operationError;
93649
93788
  try {
93650
- descriptor = fs29.openSync(temporaryPath, "wx", 384);
93651
- if (process.platform !== "win32") fs29.fchmodSync(descriptor, 384);
93652
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93789
+ descriptor = fs30.openSync(temporaryPath, "wx", 384);
93790
+ if (process.platform !== "win32") fs30.fchmodSync(descriptor, 384);
93791
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93653
93792
  assertRegularControlStateDescriptor(stats);
93654
93793
  temporaryIdentity = identityFromStats(stats);
93655
- fs29.writeFileSync(descriptor, `${JSON.stringify(state)}
93794
+ fs30.writeFileSync(descriptor, `${JSON.stringify(state)}
93656
93795
  `, "utf8");
93657
- fs29.fsyncSync(descriptor);
93658
- fs29.closeSync(descriptor);
93796
+ fs30.fsyncSync(descriptor);
93797
+ fs30.closeSync(descriptor);
93659
93798
  descriptor = null;
93660
- fs29.linkSync(temporaryPath, statePath);
93799
+ fs30.linkSync(temporaryPath, statePath);
93661
93800
  published = persistedControlState(state, statePath, identityFromStats(stats), "canonical");
93662
93801
  } catch (error2) {
93663
93802
  operationError = error2;
93664
93803
  } finally {
93665
93804
  if (descriptor !== null) {
93666
93805
  try {
93667
- fs29.closeSync(descriptor);
93806
+ fs30.closeSync(descriptor);
93668
93807
  } catch (error2) {
93669
93808
  operationError ??= error2;
93670
93809
  }
@@ -93687,7 +93826,7 @@ function createControlStateUnlocked(input) {
93687
93826
  return published;
93688
93827
  }
93689
93828
  function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
93690
- const stateBasename = path52.basename(controlStatePath(runtimeDir));
93829
+ const stateBasename = path53.basename(controlStatePath(runtimeDir));
93691
93830
  const artifactPattern = new RegExp(
93692
93831
  `^\\.${escapeRegExp(stateBasename)}(?:\\.coordination\\.lock)?\\.[0-9a-f-]+\\.(?:tmp|snapshot)$`,
93693
93832
  "u"
@@ -93695,19 +93834,19 @@ function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
93695
93834
  let removed = 0;
93696
93835
  let entries;
93697
93836
  try {
93698
- entries = fs29.readdirSync(runtimeDir);
93837
+ entries = fs30.readdirSync(runtimeDir);
93699
93838
  } catch {
93700
93839
  return 0;
93701
93840
  }
93702
93841
  for (const entry of entries) {
93703
93842
  if (entry !== `${stateBasename}.coordination.lock` && !artifactPattern.test(entry)) continue;
93704
- const artifactPath = path52.join(runtimeDir, entry);
93843
+ const artifactPath = path53.join(runtimeDir, entry);
93705
93844
  try {
93706
- const stats = fs29.lstatSync(artifactPath, { bigint: true });
93845
+ const stats = fs30.lstatSync(artifactPath, { bigint: true });
93707
93846
  if (!stats.isFile() || stats.isSymbolicLink() || process.platform !== "win32" && (stats.mode & 0o777n) !== 0o600n) {
93708
93847
  continue;
93709
93848
  }
93710
- fs29.unlinkSync(artifactPath);
93849
+ fs30.unlinkSync(artifactPath);
93711
93850
  removed += 1;
93712
93851
  } catch {
93713
93852
  }
@@ -93745,7 +93884,7 @@ function removeControlStateUnlocked(input) {
93745
93884
  if (input.expected.path !== statePath) return false;
93746
93885
  const snapshotPath = stateSnapshotPath(statePath);
93747
93886
  try {
93748
- fs29.linkSync(statePath, snapshotPath);
93887
+ fs30.linkSync(statePath, snapshotPath);
93749
93888
  } catch (error2) {
93750
93889
  if (error2.code === "ENOENT") return false;
93751
93890
  return false;
@@ -93764,7 +93903,7 @@ function removeControlStateUnlocked(input) {
93764
93903
  return false;
93765
93904
  }
93766
93905
  if (!canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2)) return false;
93767
- fs29.unlinkSync(statePath);
93906
+ fs30.unlinkSync(statePath);
93768
93907
  canonicalRemoved = true;
93769
93908
  return true;
93770
93909
  } catch {
@@ -93782,7 +93921,7 @@ function removeControlStateUnlocked(input) {
93782
93921
  function readControlStateAtPath(filePath, logicalPath) {
93783
93922
  const descriptor = openControlStateForRead(filePath);
93784
93923
  try {
93785
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93924
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93786
93925
  assertRegularControlStateDescriptor(stats);
93787
93926
  assertPrivateControlStateMode(stats);
93788
93927
  if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
@@ -93797,14 +93936,14 @@ function readControlStateAtPath(filePath, logicalPath) {
93797
93936
  throw new CorruptControlStateError(logicalPath, identity6, contents);
93798
93937
  }
93799
93938
  } finally {
93800
- fs29.closeSync(descriptor);
93939
+ fs30.closeSync(descriptor);
93801
93940
  }
93802
93941
  }
93803
93942
  function readBoundedControlState(descriptor) {
93804
93943
  const buffer = Buffer.alloc(CONTROL_STATE_MAX_BYTES + 1);
93805
93944
  let bytesRead = 0;
93806
93945
  while (bytesRead < buffer.length) {
93807
- const count = fs29.readSync(
93946
+ const count = fs30.readSync(
93808
93947
  descriptor,
93809
93948
  buffer,
93810
93949
  bytesRead,
@@ -93823,12 +93962,12 @@ function removeCorruptControlState(error2) {
93823
93962
  const snapshotPath = stateSnapshotPath(error2.statePath);
93824
93963
  let canonicalRemoved = false;
93825
93964
  try {
93826
- fs29.linkSync(error2.statePath, snapshotPath);
93965
+ fs30.linkSync(error2.statePath, snapshotPath);
93827
93966
  } catch {
93828
93967
  return false;
93829
93968
  }
93830
93969
  try {
93831
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
93970
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93832
93971
  if (!snapshotStats.isFile()) return false;
93833
93972
  const snapshotIdentity = identityFromStats(snapshotStats);
93834
93973
  if (hasUsableInode(error2.fileIdentity) && hasUsableInode(snapshotIdentity) && !sameIdentity(error2.fileIdentity, snapshotIdentity)) {
@@ -93839,7 +93978,7 @@ function removeCorruptControlState(error2) {
93839
93978
  if (fingerprint(snapshot2) !== error2.fingerprint) return false;
93840
93979
  }
93841
93980
  if (!canonicalMatchesSnapshotByIdentity(error2.statePath, snapshotPath)) return false;
93842
- fs29.unlinkSync(error2.statePath);
93981
+ fs30.unlinkSync(error2.statePath);
93843
93982
  canonicalRemoved = true;
93844
93983
  return true;
93845
93984
  } catch {
@@ -93855,7 +93994,7 @@ function removeCorruptControlState(error2) {
93855
93994
  function readRawControlState(filePath) {
93856
93995
  const descriptor = openControlStateForRead(filePath);
93857
93996
  try {
93858
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93997
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93859
93998
  assertRegularControlStateDescriptor(stats);
93860
93999
  assertPrivateControlStateMode(stats);
93861
94000
  if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
@@ -93863,13 +94002,13 @@ function readRawControlState(filePath) {
93863
94002
  }
93864
94003
  return readBoundedControlState(descriptor);
93865
94004
  } finally {
93866
- fs29.closeSync(descriptor);
94005
+ fs30.closeSync(descriptor);
93867
94006
  }
93868
94007
  }
93869
94008
  function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
93870
94009
  if (!canonicalMatchesSnapshotByIdentity(statePath, snapshotPath)) return false;
93871
- const canonicalStats = fs29.lstatSync(statePath, { bigint: true });
93872
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
94010
+ const canonicalStats = fs30.lstatSync(statePath, { bigint: true });
94011
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93873
94012
  if (hasUsableInode(identityFromStats(canonicalStats)) && hasUsableInode(identityFromStats(snapshotStats))) {
93874
94013
  return true;
93875
94014
  }
@@ -93877,8 +94016,8 @@ function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
93877
94016
  return current2.pid === snapshot2.pid && current2.ownershipSecret === snapshot2.ownershipSecret;
93878
94017
  }
93879
94018
  function canonicalMatchesSnapshotByIdentity(statePath, snapshotPath) {
93880
- const canonicalStats = fs29.lstatSync(statePath, { bigint: true });
93881
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
94019
+ const canonicalStats = fs30.lstatSync(statePath, { bigint: true });
94020
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93882
94021
  if (!canonicalStats.isFile() || !snapshotStats.isFile()) return false;
93883
94022
  const canonicalIdentity = identityFromStats(canonicalStats);
93884
94023
  const snapshotIdentity = identityFromStats(snapshotStats);
@@ -93909,20 +94048,20 @@ function sameIdentity(left, right) {
93909
94048
  return left.device === right.device && left.inode === right.inode;
93910
94049
  }
93911
94050
  function stateSnapshotPath(statePath) {
93912
- return path52.join(
93913
- path52.dirname(statePath),
93914
- `.${path52.basename(statePath)}.${randomUUID55()}.snapshot`
94051
+ return path53.join(
94052
+ path53.dirname(statePath),
94053
+ `.${path53.basename(statePath)}.${randomUUID55()}.snapshot`
93915
94054
  );
93916
94055
  }
93917
94056
  function fingerprint(contents) {
93918
- return createHash39("sha256").update(contents).digest("hex");
94057
+ return createHash40("sha256").update(contents).digest("hex");
93919
94058
  }
93920
94059
  function escapeRegExp(value) {
93921
94060
  return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
93922
94061
  }
93923
94062
  function unlinkControlStateTemporary(temporaryPath) {
93924
94063
  try {
93925
- fs29.unlinkSync(temporaryPath);
94064
+ fs30.unlinkSync(temporaryPath);
93926
94065
  return void 0;
93927
94066
  } catch (error2) {
93928
94067
  return error2.code === "ENOENT" ? void 0 : error2;
@@ -93934,28 +94073,28 @@ function eraseControlStateTemporary(temporaryPath, expectedIdentity) {
93934
94073
  try {
93935
94074
  let beforeIdentity = null;
93936
94075
  if (process.platform === "win32") {
93937
- const before = fs29.lstatSync(temporaryPath, { bigint: true });
94076
+ const before = fs30.lstatSync(temporaryPath, { bigint: true });
93938
94077
  beforeIdentity = identityFromStats(before);
93939
94078
  if (!before.isFile() || before.isSymbolicLink() || !hasUsableInode(beforeIdentity) || !sameIdentity(beforeIdentity, expectedIdentity)) return;
93940
94079
  }
93941
- const noFollow = process.platform === "win32" ? 0 : fs29.constants.O_NOFOLLOW;
94080
+ const noFollow = process.platform === "win32" ? 0 : fs30.constants.O_NOFOLLOW;
93942
94081
  if (process.platform !== "win32" && (!noFollow || typeof noFollow !== "number")) return;
93943
- descriptor = fs29.openSync(temporaryPath, fs29.constants.O_RDWR | noFollow);
93944
- const stats = fs29.fstatSync(descriptor, { bigint: true });
94082
+ descriptor = fs30.openSync(temporaryPath, fs30.constants.O_RDWR | noFollow);
94083
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93945
94084
  const identity6 = identityFromStats(stats);
93946
94085
  if (!stats.isFile() || !hasUsableInode(identity6) || !sameIdentity(identity6, expectedIdentity)) return;
93947
94086
  if (process.platform === "win32") {
93948
- const after = fs29.lstatSync(temporaryPath, { bigint: true });
94087
+ const after = fs30.lstatSync(temporaryPath, { bigint: true });
93949
94088
  const afterIdentity = identityFromStats(after);
93950
94089
  if (!after.isFile() || after.isSymbolicLink() || !beforeIdentity || !hasUsableInode(afterIdentity) || !sameIdentity(beforeIdentity, identity6) || !sameIdentity(identity6, afterIdentity)) return;
93951
94090
  }
93952
- fs29.ftruncateSync(descriptor, 0);
93953
- fs29.fsyncSync(descriptor);
94091
+ fs30.ftruncateSync(descriptor, 0);
94092
+ fs30.fsyncSync(descriptor);
93954
94093
  } catch {
93955
94094
  } finally {
93956
94095
  if (descriptor !== null) {
93957
94096
  try {
93958
- fs29.closeSync(descriptor);
94097
+ fs30.closeSync(descriptor);
93959
94098
  } catch {
93960
94099
  }
93961
94100
  }
@@ -94002,16 +94141,16 @@ function parseControlState(value) {
94002
94141
  }
94003
94142
  function openControlStateForRead(statePath) {
94004
94143
  if (process.platform === "win32") return openControlStateForReadOnWindows(statePath);
94005
- const noFollow = fs29.constants.O_NOFOLLOW;
94144
+ const noFollow = fs30.constants.O_NOFOLLOW;
94006
94145
  if (typeof noFollow !== "number" || noFollow === 0) {
94007
94146
  throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NOFOLLOW \u5B89\u5168\u8BFB\u53D6");
94008
94147
  }
94009
- const nonBlock = fs29.constants.O_NONBLOCK;
94148
+ const nonBlock = fs30.constants.O_NONBLOCK;
94010
94149
  if (typeof nonBlock !== "number" || nonBlock === 0) {
94011
94150
  throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NONBLOCK \u5B89\u5168\u8BFB\u53D6");
94012
94151
  }
94013
94152
  try {
94014
- return fs29.openSync(statePath, fs29.constants.O_RDONLY | noFollow | nonBlock);
94153
+ return fs30.openSync(statePath, fs30.constants.O_RDONLY | noFollow | nonBlock);
94015
94154
  } catch (error2) {
94016
94155
  if (error2.code === "ELOOP") {
94017
94156
  throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
@@ -94020,14 +94159,14 @@ function openControlStateForRead(statePath) {
94020
94159
  }
94021
94160
  }
94022
94161
  function openControlStateForReadOnWindows(statePath) {
94023
- const before = fs29.lstatSync(statePath, { bigint: true });
94162
+ const before = fs30.lstatSync(statePath, { bigint: true });
94024
94163
  if (!before.isFile() || before.isSymbolicLink()) {
94025
94164
  throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
94026
94165
  }
94027
- const descriptor = fs29.openSync(statePath, fs29.constants.O_RDONLY);
94166
+ const descriptor = fs30.openSync(statePath, fs30.constants.O_RDONLY);
94028
94167
  try {
94029
- const opened = fs29.fstatSync(descriptor, { bigint: true });
94030
- const after = fs29.lstatSync(statePath, { bigint: true });
94168
+ const opened = fs30.fstatSync(descriptor, { bigint: true });
94169
+ const after = fs30.lstatSync(statePath, { bigint: true });
94031
94170
  const beforeIdentity = identityFromStats(before);
94032
94171
  const openedIdentity = identityFromStats(opened);
94033
94172
  const afterIdentity = identityFromStats(after);
@@ -94036,7 +94175,7 @@ function openControlStateForReadOnWindows(statePath) {
94036
94175
  }
94037
94176
  return descriptor;
94038
94177
  } catch (error2) {
94039
- fs29.closeSync(descriptor);
94178
+ fs30.closeSync(descriptor);
94040
94179
  throw error2;
94041
94180
  }
94042
94181
  }
@@ -94478,9 +94617,9 @@ var init_direct2 = __esm({
94478
94617
  });
94479
94618
 
94480
94619
  // apps/desktop/src/cli/commands/events.ts
94481
- import path53 from "node:path";
94620
+ import path54 from "node:path";
94482
94621
  function normalizedProjectRoot(value) {
94483
- return typeof value === "string" && value.length > 0 ? path53.resolve(value) : null;
94622
+ return typeof value === "string" && value.length > 0 ? path54.resolve(value) : null;
94484
94623
  }
94485
94624
  function toOutputEvent(event) {
94486
94625
  if (event.ok === true && typeof event.schemaVersion === "number") {
@@ -94864,7 +95003,7 @@ var init_state2 = __esm({
94864
95003
  });
94865
95004
 
94866
95005
  // apps/desktop/src/cli/commands/threads.ts
94867
- import path54 from "node:path";
95006
+ import path55 from "node:path";
94868
95007
  function readPositiveInteger2(value, name2, fallback) {
94869
95008
  if (value === void 0) {
94870
95009
  return fallback;
@@ -94882,7 +95021,7 @@ async function runThreadsCommand(args, options = {}) {
94882
95021
  const pageSize = readPositiveInteger2(args.flags.pageSize ?? args.flags.limit, "--page-size", 100);
94883
95022
  const maxPages = readPositiveInteger2(args.flags.maxPages, "--max-pages", 20);
94884
95023
  const cursor = typeof args.flags.cursor === "string" && args.flags.cursor.length > 0 ? args.flags.cursor : null;
94885
- const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ? path54.resolve(args.flags.project) : null;
95024
+ const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ? path55.resolve(args.flags.project) : null;
94886
95025
  const daemon = options.daemonClient ?? new DaemonClient(options.socketPath);
94887
95026
  const result = await daemon.request("threads/list", {
94888
95027
  pageSize,