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

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