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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1963,11 +1963,11 @@ function token(value) {
1963
1963
  function size(kind, bytes3) {
1964
1964
  return (kind === "image" || kind === "file") && integer(bytes3, kind === "image" ? 20971520 : 52428800, kind === "image" ? 1 : 0);
1965
1965
  }
1966
- function dataUrl(value, path55) {
1966
+ function dataUrl(value, path56) {
1967
1967
  if (typeof value !== "string") return false;
1968
1968
  try {
1969
1969
  const u = new URL(value);
1970
- return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (path55 ? u.pathname === path55 : ["/direct/v1/attachment/data", "/ws/v1/attachment/data"].includes(u.pathname));
1970
+ return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (path56 ? u.pathname === path56 : ["/direct/v1/attachment/data", "/ws/v1/attachment/data"].includes(u.pathname));
1971
1971
  } catch {
1972
1972
  return false;
1973
1973
  }
@@ -6797,7 +6797,7 @@ var init_src = __esm({
6797
6797
  // apps/desktop/src/release-version.ts
6798
6798
  import { readFileSync } from "node:fs";
6799
6799
  function desktopReleaseVersion() {
6800
- return false ? null : "0.0.1-beta.11";
6800
+ return false ? null : "0.0.1-beta.13";
6801
6801
  }
6802
6802
  function desktopPresenceVersion() {
6803
6803
  return desktopReleaseVersion() ?? sourcePresenceVersion;
@@ -9132,9 +9132,9 @@ var init_server_client = __esm({
9132
9132
  if (data.binding_revision !== snapshot2.binding_revision) throw new NotificationTransportError("invalid_response");
9133
9133
  return { binding_revision: snapshot2.binding_revision };
9134
9134
  }
9135
- async signedPost(path55, input, signal, method2 = "POST") {
9135
+ async signedPost(path56, input, signal, method2 = "POST") {
9136
9136
  if (!this.identity || !this.serverOrigin.startsWith("https://")) throw new NotificationTransportError("business_error", 200, 200004);
9137
- const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${path55}`;
9137
+ const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${path56}`;
9138
9138
  const key_id = createHash("sha256").update(this.identity.identity_public_key).digest("base64url");
9139
9139
  const operation_id = randomUUID(), nonce = encodeBase64Url(randomBytes2(32)), timestamp = Math.floor(Date.now() / 1e3);
9140
9140
  const bytes3 = createPushSigningBytes({ audience: this.serverOrigin, method: method2, pathname, query: query2, body_sha256: createHash("sha256").update(body).digest("base64url"), key_id, operation_id, timestamp, nonce });
@@ -11892,11 +11892,11 @@ var init_runtime_version = __esm({
11892
11892
  retryAt = 0;
11893
11893
  pending = null;
11894
11894
  controller = null;
11895
- setConnection(path55) {
11895
+ setConnection(path56) {
11896
11896
  this.epoch++;
11897
11897
  this.controller?.abort();
11898
11898
  this.controller = null;
11899
- this.path = path55;
11899
+ this.path = path56;
11900
11900
  this.value = null;
11901
11901
  this.pending = null;
11902
11902
  this.retryAt = 0;
@@ -12807,20 +12807,20 @@ function sendJson(response, httpStatus, body) {
12807
12807
  }
12808
12808
  function zodErrorToHttpApiError(error2) {
12809
12809
  const messages = error2.issues.map((issue) => {
12810
- const path55 = issue.path.join(".") || "\u53C2\u6570";
12810
+ const path56 = issue.path.join(".") || "\u53C2\u6570";
12811
12811
  if (issue.code === "custom") {
12812
12812
  return issue.message;
12813
12813
  }
12814
12814
  if (issue.code === "invalid_type" && issue.received === "undefined") {
12815
- return `${path55}\u4E0D\u80FD\u4E3A\u7A7A`;
12815
+ return `${path56}\u4E0D\u80FD\u4E3A\u7A7A`;
12816
12816
  }
12817
12817
  if (issue.code === "invalid_type") {
12818
- return `${path55}\u7C7B\u578B\u9519\u8BEF`;
12818
+ return `${path56}\u7C7B\u578B\u9519\u8BEF`;
12819
12819
  }
12820
12820
  if (issue.code === "unrecognized_keys") {
12821
12821
  return `\u4E0D\u652F\u6301\u7684\u53C2\u6570: ${issue.keys.join(",")}`;
12822
12822
  }
12823
- return `${path55}\u683C\u5F0F\u9519\u8BEF`;
12823
+ return `${path56}\u683C\u5F0F\u9519\u8BEF`;
12824
12824
  });
12825
12825
  const custom = error2.issues.some((issue) => issue.code === "custom");
12826
12826
  const missing4 = error2.issues.some(
@@ -17431,12 +17431,24 @@ async function installRelease(options) {
17431
17431
  const manifest = JSON.parse(await fs14.readFile(path19.join(pkg, "package.json"), "utf8"));
17432
17432
  if (manifest.name !== "niuma-codex" || manifest.version !== options.version) throw Error("version");
17433
17433
  if (!(await fs14.lstat(entry(dir))).isFile()) throw Error("entry");
17434
- await options.run(options.node, [
17435
- "--input-type=module",
17436
- "-e",
17437
- 'import {createRequire} from "node:module";const r=createRequire(process.argv[1]);const p=r("./package.json");for(const name of Object.keys(p.dependencies||{}))r.resolve(name);if(p.dependencies?.sharp)r("sharp");',
17438
- path19.join(pkg, "package.json")
17439
- ], 3e4);
17434
+ const probe = path19.join(pkg, `.verify-${randomUUID10()}.mjs`);
17435
+ await fs14.writeFile(probe, `
17436
+ import { createRequire } from 'node:module';
17437
+ import { access } from 'node:fs/promises';
17438
+ import { fileURLToPath } from 'node:url';
17439
+ const require = createRequire(import.meta.url);
17440
+ const manifest = require('./package.json');
17441
+ for (const name of Object.keys(manifest.dependencies || {})) {
17442
+ await access(fileURLToPath(import.meta.resolve(name)));
17443
+ }
17444
+ // sharp \u4ECD\u987B\u5B9E\u9645\u52A0\u8F7D\uFF1B\u5176\u4F59\u670D\u52A1\u7AEF\u5BFC\u5165\u94FE\u7531 CLI \u5E2E\u52A9\u9A8C\u8BC1\u3002
17445
+ if (manifest.dependencies?.sharp) require('sharp');
17446
+ `, { flag: "wx", mode: 384 });
17447
+ try {
17448
+ await options.run(options.node, [probe], 3e4);
17449
+ } finally {
17450
+ await fs14.rm(probe, { force: true });
17451
+ }
17440
17452
  await options.run(options.node, [entry(dir), "--help"], 3e4);
17441
17453
  }
17442
17454
  let exists = false;
@@ -17478,7 +17490,7 @@ var init_installer = __esm({
17478
17490
  });
17479
17491
 
17480
17492
  // apps/desktop/src/autostart/launch-agent.ts
17481
- function renderLaunchAgent(config, entry, logs) {
17493
+ function autostartEnvironment(config) {
17482
17494
  const env = {
17483
17495
  HOME: config.home,
17484
17496
  PATH: config.path,
@@ -17488,12 +17500,16 @@ function renderLaunchAgent(config, entry, logs) {
17488
17500
  };
17489
17501
  if (config.codexHome) env.CODEX_HOME = config.codexHome;
17490
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);
17491
17507
  const str = (v) => `<string>${xml(v)}</string>`;
17492
17508
  return `<?xml version="1.0" encoding="UTF-8"?>
17493
17509
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
17494
17510
  <plist version="1.0"><dict>
17495
- <key>Label</key>${str(AUTOSTART_LABEL)}
17496
- <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>`}
17497
17513
  <key>RunAtLoad</key><true/>
17498
17514
  <key>WorkingDirectory</key>${str(config.home)}
17499
17515
  <key>EnvironmentVariables</key><dict>${Object.entries(env).map(([k, v]) => `<key>${k}</key>${str(v)}`).join("")}</dict>
@@ -17502,19 +17518,124 @@ function renderLaunchAgent(config, entry, logs) {
17502
17518
  </dict></plist>
17503
17519
  `;
17504
17520
  }
17505
- var AUTOSTART_LABEL, xml;
17521
+ var AUTOSTART_LABEL, AUTOSTART_APP_ID, AUTOSTART_APP_LABEL, xml;
17506
17522
  var init_launch_agent = __esm({
17507
17523
  "apps/desktop/src/autostart/launch-agent.ts"() {
17508
17524
  "use strict";
17509
17525
  AUTOSTART_LABEL = "com.niuma.desktop";
17526
+ AUTOSTART_APP_ID = "com.niuma.npm-autostart";
17527
+ AUTOSTART_APP_LABEL = "com.niuma.npm-autostart.agent";
17510
17528
  xml = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll('"', "&quot;").replaceAll("'", "&apos;");
17511
17529
  }
17512
17530
  });
17513
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
+
17514
17634
  // apps/desktop/src/autostart/manager.ts
17515
- import fs15 from "node:fs";
17635
+ import fs16 from "node:fs";
17516
17636
  import fsp from "node:fs/promises";
17517
- import path20 from "node:path";
17637
+ import path21 from "node:path";
17638
+ import os2 from "node:os";
17518
17639
  import { randomUUID as randomUUID11 } from "node:crypto";
17519
17640
  async function readJson(file) {
17520
17641
  try {
@@ -17537,13 +17658,13 @@ async function atomic(file, value) {
17537
17658
  }
17538
17659
  function acquire(file) {
17539
17660
  try {
17540
- const fd = fs15.openSync(file, fs15.constants.O_CREAT | fs15.constants.O_RDWR | fs15.constants.O_NOFOLLOW | fs15.constants.O_NONBLOCK | 32, 384);
17541
- 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);
17542
17663
  if (!s.isFile() || s.uid !== process.getuid?.() || s.mode & 63) {
17543
- fs15.closeSync(fd);
17664
+ fs16.closeSync(fd);
17544
17665
  throw Error("unsafe");
17545
17666
  }
17546
- return () => fs15.closeSync(fd);
17667
+ return () => fs16.closeSync(fd);
17547
17668
  } catch {
17548
17669
  throw new AutostartError(900511, "\u5DF2\u6709\u81EA\u542F\u52A8\u64CD\u4F5C\u6B63\u5728\u8FDB\u884C\uFF0C\u6216\u64CD\u4F5C\u9501\u4E0D\u53EF\u7528");
17549
17670
  }
@@ -17554,12 +17675,13 @@ var init_manager = __esm({
17554
17675
  "use strict";
17555
17676
  init_installer();
17556
17677
  init_launch_agent();
17678
+ init_app_bundle();
17557
17679
  init_types2();
17558
17680
  AutostartManager = class {
17559
17681
  constructor(options) {
17560
17682
  this.options = options;
17561
- this.root = path20.join(options.home, "Library/Application Support/Niuma/autostart");
17562
- 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`);
17563
17685
  this.run = options.run ?? runProcess;
17564
17686
  }
17565
17687
  options;
@@ -17575,29 +17697,62 @@ var init_manager = __esm({
17575
17697
  return `${this.domain}/${AUTOSTART_LABEL}`;
17576
17698
  }
17577
17699
  get metadata() {
17578
- return path20.join(this.root, "registration.json");
17700
+ return path21.join(this.root, "registration.json");
17579
17701
  }
17580
17702
  get operationFile() {
17581
- return path20.join(this.root, "operation.json");
17703
+ return path21.join(this.root, "operation.json");
17582
17704
  }
17583
17705
  supported() {
17584
- return (this.options.platform ?? process.platform) === "darwin";
17706
+ return (this.options.platform ?? process.platform) === "darwin" && Number((this.options.osRelease ?? os2.release()).split(".")[0]) >= 22;
17585
17707
  }
17586
- 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
+ }
17587
17719
  try {
17588
17720
  await this.run("/bin/launchctl", ["print", this.target]);
17589
- return true;
17721
+ return 1;
17590
17722
  } catch (e) {
17591
- return e.code === 113 ? false : null;
17723
+ return e.code === 113 ? 0 : null;
17592
17724
  }
17593
17725
  }
17726
+ async loaded(registration) {
17727
+ const state = await this.registrationState(registration);
17728
+ return state === null ? null : state === 1;
17729
+ }
17730
+ async stopRegistration(registration) {
17731
+ const state = await this.registrationState(registration);
17732
+ if (state === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u72B6\u6001\uFF0C\u4FDD\u7559\u539F\u6CE8\u518C");
17733
+ if (state === 1 || state === 2) await this.unload(registration);
17734
+ }
17735
+ /** 应用注册由 ServiceManagement 持有;legacy 注册继续用原 launchctl 路径回滚。 */
17736
+ async load(registration, allowPending = false) {
17737
+ if (registration.service === "application-agent" && registration.appPath) {
17738
+ await checkAutostartApp(registration.appPath);
17739
+ const result = JSON.parse(await this.run(path21.join(registration.appPath, "Contents/MacOS/Niuma"), ["--autostart-register"]));
17740
+ if (result.status !== 1 && !(allowPending && result.status === 2)) throw new AutostartError(900614, "\u8BF7\u5728\u7CFB\u7EDF\u8BBE\u7F6E\u7684\u767B\u5F55\u9879\u4E2D\u5141\u8BB8 Niuma \u5728\u540E\u53F0\u8FD0\u884C\u540E\u91CD\u8BD5");
17741
+ } else await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17742
+ }
17743
+ async unload(registration) {
17744
+ if (registration?.service === "application-agent" && registration.appPath) {
17745
+ await checkAutostartApp(registration.appPath);
17746
+ await this.run(path21.join(registration.appPath, "Contents/MacOS/Niuma"), ["--autostart-unregister"]);
17747
+ } else await this.run("/bin/launchctl", ["bootout", this.target]);
17748
+ }
17594
17749
  async status() {
17595
- if (!this.supported() || this.options.unavailableReason) return { supported: false, registered: false, loaded: null, available: false, registeredVersion: null, runningVersion: null, running: null, reason: this.options.unavailableReason ?? "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8", logPath: this.root, operation: null };
17750
+ if (!this.supported() || this.options.unavailableReason) return { supported: false, registered: false, loaded: null, available: false, registeredVersion: null, runningVersion: null, running: null, reason: this.options.unavailableReason ?? "\u767B\u5F55\u81EA\u542F\u52A8\u9700\u8981 macOS 13 \u6216\u66F4\u65B0\u7248\u672C", logPath: this.root, operation: null };
17596
17751
  const registration = await readJson(this.metadata);
17597
17752
  let operation = await readJson(this.operationFile);
17598
17753
  if (operation?.state === "running" && !this.busy) {
17599
17754
  try {
17600
- const release2 = acquire(path20.join(this.root, "operation.lock"));
17755
+ const release2 = acquire(path21.join(this.root, "operation.lock"));
17601
17756
  release2();
17602
17757
  operation = { ...operation, state: "interrupted", code: 900615, message: "\u4E0A\u6B21\u81EA\u542F\u52A8\u64CD\u4F5C\u5DF2\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5" };
17603
17758
  } catch {
@@ -17607,17 +17762,21 @@ var init_manager = __esm({
17607
17762
  if (registration) {
17608
17763
  if (registration.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u81EA\u542F\u52A8\u914D\u7F6E\u4E0D\u5C5E\u4E8E Niuma");
17609
17764
  try {
17610
- const stat3 = await fsp.lstat(this.plist);
17611
- registered = stat3.isFile() && await fsp.readFile(this.plist, "utf8") === registration.plist;
17612
- await fsp.access(registration.config.nodeExecutable, fs15.constants.X_OK);
17613
- await fsp.access(registration.entryPath, fs15.constants.R_OK);
17765
+ if (registration.service === "application-agent") registered = true;
17766
+ else {
17767
+ const stat3 = await fsp.lstat(this.plist);
17768
+ registered = stat3.isFile() && await fsp.readFile(this.plist, "utf8") === registration.plist;
17769
+ }
17770
+ await fsp.access(registration.config.nodeExecutable, fs16.constants.X_OK);
17771
+ await fsp.access(registration.entryPath, fs16.constants.R_OK);
17772
+ if (registration.appPath) await checkAutostartApp(registration.appPath);
17614
17773
  available = registered;
17615
17774
  } catch {
17616
17775
  reason = "\u81EA\u542F\u52A8\u8FD0\u884C\u6587\u4EF6\u6216 Node \u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E";
17617
17776
  }
17618
17777
  }
17619
17778
  const running = await this.options.running?.().catch(() => ({ running: null, version: null })) ?? { running: null, version: null };
17620
- const loaded = await this.loaded();
17779
+ const loaded = await this.loaded(registration);
17621
17780
  if (registered && loaded !== true) {
17622
17781
  available = false;
17623
17782
  reason = "\u542F\u52A8\u9879\u672A\u52A0\u8F7D\u6216\u65E0\u6CD5\u67E5\u8BE2\uFF0C\u8BF7\u91CD\u65B0\u914D\u7F6E";
@@ -17636,13 +17795,13 @@ var init_manager = __esm({
17636
17795
  };
17637
17796
  }
17638
17797
  async beginSetEnabled(enabled, config) {
17639
- if (!this.supported() || this.options.unavailableReason) throw new AutostartError(900611, this.options.unavailableReason ?? "\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8");
17798
+ if (!this.supported() || this.options.unavailableReason) throw new AutostartError(900611, this.options.unavailableReason ?? "\u767B\u5F55\u81EA\u542F\u52A8\u9700\u8981 macOS 13 \u6216\u66F4\u65B0\u7248\u672C");
17640
17799
  if (this.busy) throw new AutostartError(900511, "\u5DF2\u6709\u81EA\u542F\u52A8\u64CD\u4F5C\u6B63\u5728\u8FDB\u884C");
17641
17800
  this.busy = true;
17642
17801
  let release2;
17643
17802
  try {
17644
17803
  await privateDirectory(this.root);
17645
- release2 = acquire(path20.join(this.root, "operation.lock"));
17804
+ release2 = acquire(path21.join(this.root, "operation.lock"));
17646
17805
  const operation = { id: randomUUID11(), targetEnabled: enabled, state: "running", startedAt: Date.now(), finishedAt: null, pid: process.pid };
17647
17806
  await atomic(this.operationFile, JSON.stringify(operation));
17648
17807
  this.active = (async () => {
@@ -17682,7 +17841,7 @@ var init_manager = __esm({
17682
17841
  }
17683
17842
  /** 注册文件和元数据的两次写入由恢复记录覆盖,崩溃后只恢复可证明自有的内容。 */
17684
17843
  async recoverTransaction() {
17685
- const file = path20.join(this.root, "transaction.json");
17844
+ const file = path21.join(this.root, "transaction.json");
17686
17845
  const transaction = await readJson(file);
17687
17846
  if (!transaction) return;
17688
17847
  if (transaction.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u6CE8\u518C\u6062\u590D\u8BB0\u5F55\u65E0\u6548");
@@ -17695,21 +17854,22 @@ var init_manager = __esm({
17695
17854
  if (e.code !== "ENOENT") throw new AutostartError(900611, "\u65E0\u6CD5\u5B89\u5168\u6062\u590D\u542F\u52A8\u9879");
17696
17855
  }
17697
17856
  if (current2 !== null && current2 !== transaction.previous?.plist && current2 !== transaction.next?.plist) throw new AutostartError(900611, "\u542F\u52A8\u9879\u5DF2\u88AB\u5176\u4ED6\u7A0B\u5E8F\u4FEE\u6539\uFF0C\u672A\u8986\u76D6");
17698
- const loaded = await this.loaded();
17699
- if (loaded === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u72B6\u6001\uFF0C\u6062\u590D\u672A\u5B8C\u6210");
17700
- if (loaded) await this.run("/bin/launchctl", ["bootout", this.target]);
17857
+ if (transaction.next) await this.stopRegistration(transaction.next);
17858
+ if (transaction.previous) await this.stopRegistration(transaction.previous);
17701
17859
  if (transaction.previous) {
17702
- await atomic(this.plist, transaction.previous.plist);
17860
+ if (transaction.previous.service === "application-agent") await fsp.rm(this.plist, { force: true });
17861
+ else await atomic(this.plist, transaction.previous.plist);
17703
17862
  await atomic(this.metadata, JSON.stringify(transaction.previous));
17704
17863
  } else {
17705
17864
  await fsp.rm(this.plist, { force: true });
17706
17865
  await fsp.rm(this.metadata, { force: true });
17707
17866
  }
17708
- if (transaction.wasLoaded) await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17867
+ if (transaction.previous?.appPath) await this.run(LSREGISTER, ["-f", transaction.previous.appPath]);
17868
+ if ((transaction.wasRegistered ?? transaction.wasLoaded) && transaction.previous) await this.load(transaction.previous, !transaction.wasLoaded);
17709
17869
  await fsp.rm(file);
17710
17870
  }
17711
17871
  async change(enabled, input) {
17712
- await privateDirectory(path20.dirname(this.plist));
17872
+ await privateDirectory(path21.dirname(this.plist));
17713
17873
  await this.recoverTransaction();
17714
17874
  const previous = await readJson(this.metadata);
17715
17875
  let existing = null;
@@ -17726,30 +17886,38 @@ var init_manager = __esm({
17726
17886
  } catch {
17727
17887
  throw new AutostartError(900611, "\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 macOS \u56FE\u5F62\u767B\u5F55\u4F1A\u8BDD");
17728
17888
  }
17729
- const wasLoaded = await this.loaded();
17730
- if (wasLoaded === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u52A0\u8F7D\u72B6\u6001");
17889
+ if (previous && previous.owner !== "niuma-autostart-v1") throw new AutostartError(900611, "\u81EA\u542F\u52A8\u914D\u7F6E\u4E0D\u5C5E\u4E8E Niuma");
17890
+ const priorState = await this.registrationState(previous);
17891
+ const wasLoaded = priorState === 1, wasRegistered = priorState === 1 || priorState === 2;
17892
+ if (priorState === null) throw new AutostartError(900614, "\u65E0\u6CD5\u786E\u8BA4\u542F\u52A8\u9879\u52A0\u8F7D\u72B6\u6001");
17731
17893
  if (wasLoaded && !previous) throw new AutostartError(900611, "\u5DF2\u52A0\u8F7D\u7684\u540C\u540D\u670D\u52A1\u7F3A\u5C11 Niuma \u5F52\u5C5E\u8BB0\u5F55\uFF0C\u672A\u63A5\u7BA1");
17732
17894
  let next = null;
17733
17895
  if (enabled) {
17734
17896
  const config = input ?? this.options.config();
17735
17897
  await this.options.guard?.();
17736
- if (previous && existing === previous.plist && JSON.stringify(config) === JSON.stringify(previous.config) && (await this.status()).available) return;
17737
- const installed = await (this.options.install?.(config) ?? installRelease({ root: this.root, version: config.releaseVersion, node: config.nodeExecutable, npm: path20.join(path20.dirname(config.nodeExecutable), "npm"), run: this.run }));
17898
+ const reusable = previous && (previous.service === "application-agent" ? existing === null : existing === previous.plist) && JSON.stringify(config) === JSON.stringify(previous.config) && (await this.status()).available;
17899
+ const installed = reusable ? { entryPath: previous.entryPath } : await (this.options.install?.(config) ?? installRelease({ root: this.root, version: config.releaseVersion, node: config.nodeExecutable, npm: path21.join(path21.dirname(config.nodeExecutable), "npm"), run: this.run }));
17900
+ const appPath = await prepareAutostartApp(this.root, config, installed.entryPath);
17738
17901
  await this.options.guard?.();
17739
- next = { owner: "niuma-autostart-v1", config, entryPath: installed.entryPath, plist: renderLaunchAgent(config, installed.entryPath, this.root) };
17902
+ next = { owner: "niuma-autostart-v1", service: "application-agent", config, entryPath: installed.entryPath, appPath, plist: renderLaunchAgent(config, installed.entryPath, this.root, true) };
17903
+ if (reusable && previous.service === next.service && previous.appPath === appPath && previous.plist === next.plist) {
17904
+ await this.run(LSREGISTER, ["-f", appPath]);
17905
+ return;
17906
+ }
17740
17907
  for (const name2 of ["stdout.log", "stderr.log"]) {
17741
- const handle = await fsp.open(path20.join(this.root, name2), fs15.constants.O_WRONLY | fs15.constants.O_APPEND | fs15.constants.O_CREAT | fs15.constants.O_NOFOLLOW, 384);
17908
+ const handle = await fsp.open(path21.join(this.root, name2), fs16.constants.O_WRONLY | fs16.constants.O_APPEND | fs16.constants.O_CREAT | fs16.constants.O_NOFOLLOW, 384);
17742
17909
  await handle.close();
17743
17910
  }
17744
17911
  }
17745
- const transactionFile = path20.join(this.root, "transaction.json");
17746
- await atomic(transactionFile, JSON.stringify({ owner: "niuma-autostart-v1", previous, next, wasLoaded }));
17912
+ const transactionFile = path21.join(this.root, "transaction.json");
17913
+ await atomic(transactionFile, JSON.stringify({ owner: "niuma-autostart-v1", previous, next, wasLoaded, wasRegistered }));
17747
17914
  try {
17748
- if (wasLoaded) await this.run("/bin/launchctl", ["bootout", this.target]);
17915
+ if (next?.appPath) await this.run(LSREGISTER, ["-f", next.appPath]);
17916
+ if (wasRegistered) await this.unload(previous);
17749
17917
  if (next) {
17750
- await atomic(this.plist, next.plist);
17918
+ await fsp.rm(this.plist, { force: true });
17751
17919
  await atomic(this.metadata, JSON.stringify(next));
17752
- await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17920
+ await this.load(next);
17753
17921
  } else {
17754
17922
  await fsp.rm(this.plist, { force: true });
17755
17923
  await fsp.rm(this.metadata, { force: true });
@@ -17758,13 +17926,7 @@ var init_manager = __esm({
17758
17926
  } catch {
17759
17927
  let restored = true;
17760
17928
  try {
17761
- if (await this.loaded()) await this.run("/bin/launchctl", ["bootout", this.target]);
17762
- if (existing !== null) await atomic(this.plist, existing);
17763
- else await fsp.rm(this.plist, { force: true });
17764
- if (previous) await atomic(this.metadata, JSON.stringify(previous));
17765
- else await fsp.rm(this.metadata, { force: true });
17766
- if (wasLoaded) await this.run("/bin/launchctl", ["bootstrap", this.domain, this.plist]);
17767
- await fsp.rm(transactionFile, { force: true });
17929
+ await this.recoverTransaction();
17768
17930
  } catch {
17769
17931
  restored = false;
17770
17932
  }
@@ -17776,8 +17938,8 @@ var init_manager = __esm({
17776
17938
  });
17777
17939
 
17778
17940
  // apps/desktop/src/autostart/production.ts
17779
- import os2 from "node:os";
17780
- import path21 from "node:path";
17941
+ import os3 from "node:os";
17942
+ import path22 from "node:path";
17781
17943
  function autostartConfig(args, relayOrigin) {
17782
17944
  const version2 = desktopReleaseVersion();
17783
17945
  if (!version2) throw new AutostartError(900611, "\u6E90\u7801\u8FD0\u884C\u4E0D\u652F\u6301\u6CE8\u518C\u81EA\u542F\u52A8\uFF0C\u8BF7\u4F7F\u7528\u5DF2\u53D1\u5E03\u7684 niuma-codex");
@@ -17785,8 +17947,8 @@ function autostartConfig(args, relayOrigin) {
17785
17947
  return {
17786
17948
  releaseVersion: version2,
17787
17949
  nodeExecutable: process.execPath,
17788
- home: os2.homedir(),
17789
- path: [path21.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
17950
+ home: os3.homedir(),
17951
+ path: [path22.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
17790
17952
  ...process.env.CODEX_HOME ? { codexHome: process.env.CODEX_HOME } : {},
17791
17953
  relayOrigin: resolveRelayConfig({ relay_origin: relayOrigin ?? resolveRelayStartupOrigin({ env: process.env, cliOrigin: args.flags.relayOrigin }) }).origin,
17792
17954
  pushServerOrigin: resolvePushServerOrigin(process.env),
@@ -17801,7 +17963,7 @@ function statusRecord(value) {
17801
17963
  function createAutostartManager(args = parseRootArgs(process.argv.slice(2)), page4 = false, relayOrigin) {
17802
17964
  const client = new DaemonClient();
17803
17965
  return new AutostartManager({
17804
- home: os2.homedir(),
17966
+ home: os3.homedir(),
17805
17967
  ...page4 && !desktopReleaseVersion() ? { unavailableReason: "\u6E90\u7801\u8FD0\u884C\u4E0D\u652F\u6301\u767B\u5F55\u81EA\u542F\u52A8\uFF0C\u8BF7\u4F7F\u7528\u5DF2\u53D1\u5E03\u7684 niuma-codex" } : {},
17806
17968
  config: () => autostartConfig(args, relayOrigin),
17807
17969
  running: async () => {
@@ -18224,15 +18386,15 @@ var init_client_turn_query_context = __esm({
18224
18386
  });
18225
18387
 
18226
18388
  // apps/desktop/src/niuma/session-history-file.ts
18227
- import fs16 from "node:fs/promises";
18228
- import path22 from "node:path";
18229
- import { createHash as createHash2 } from "node:crypto";
18389
+ import fs17 from "node:fs/promises";
18390
+ import path23 from "node:path";
18391
+ import { createHash as createHash3 } from "node:crypto";
18230
18392
  function matchesSessionFileIdentity(file, stat3) {
18231
18393
  const exact = (value) => typeof value === "number" ? Number.isSafeInteger(value) && value >= 0 ? String(value) : null : /^(0|[1-9]\d{0,39})$/.test(value) ? value : null;
18232
18394
  return exact(file.dev) === String(stat3.dev) && exact(file.ino) === String(stat3.ino);
18233
18395
  }
18234
18396
  async function preciseStat(file) {
18235
- const stat3 = await fs16.stat(file, { bigint: true });
18397
+ const stat3 = await fs17.stat(file, { bigint: true });
18236
18398
  const size2 = Number(stat3.size);
18237
18399
  if (!Number.isSafeInteger(size2)) throw new SessionHistoryError("RESOURCE_LIMIT", "\u4F1A\u8BDD\u6587\u4EF6\u8D85\u51FA\u8BFB\u53D6\u8303\u56F4");
18238
18400
  return { dev: stat3.dev, ino: stat3.ino, size: size2, mtimeMs: Number(stat3.mtimeNs) / 1e6, isFile: () => stat3.isFile() };
@@ -18248,12 +18410,12 @@ function rethrowUnreadableHistoryPath(error2) {
18248
18410
  }
18249
18411
  function fileIdentity(file) {
18250
18412
  const uuid7 = "[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}";
18251
- const match = path22.basename(file).match(new RegExp(`(${uuid7})(?:_(${uuid7}))?\\.jsonl$`, "i"));
18413
+ const match = path23.basename(file).match(new RegExp(`(${uuid7})(?:_(${uuid7}))?\\.jsonl$`, "i"));
18252
18414
  return match ? { owner: match[1], segment: match[2] ?? match[1] } : null;
18253
18415
  }
18254
18416
  async function readBytes(file, start, length, onRead, signal) {
18255
18417
  abortIfRequested(signal);
18256
- const handle = await fs16.open(file, "r").catch(rethrowUnreadableHistoryPath);
18418
+ const handle = await fs17.open(file, "r").catch(rethrowUnreadableHistoryPath);
18257
18419
  try {
18258
18420
  const buffer = Buffer.allocUnsafe(length);
18259
18421
  let filled = 0;
@@ -18311,7 +18473,7 @@ async function header(file, size2, onRead, signal) {
18311
18473
  }
18312
18474
  async function openSessionFile(file, threadId2, chunkBytes, end, onRead, signal, onCutoffCaptured) {
18313
18475
  abortIfRequested(signal);
18314
- const resolved3 = await fs16.realpath(file).catch(rethrowUnreadableHistoryPath);
18476
+ const resolved3 = await fs17.realpath(file).catch(rethrowUnreadableHistoryPath);
18315
18477
  const stat3 = await preciseStat(resolved3).catch(rethrowUnreadableHistoryPath);
18316
18478
  abortIfRequested(signal);
18317
18479
  if (!stat3.isFile()) throw new SessionHistoryError("INVALID_METADATA", "\u4F1A\u8BDD\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
@@ -18458,7 +18620,7 @@ var init_session_history_file = __esm({
18458
18620
  nonempty = (value) => typeof value === "string" && value.length > 0 ? value : null;
18459
18621
  SESSION_RECORD_LOCATION = /* @__PURE__ */ Symbol("sessionHistoryLocation");
18460
18622
  SESSION_RECORD_RANGE = /* @__PURE__ */ Symbol("sessionHistoryRange");
18461
- hash = (value) => createHash2("sha256").update(value).digest("hex");
18623
+ hash = (value) => createHash3("sha256").update(value).digest("hex");
18462
18624
  }
18463
18625
  });
18464
18626
 
@@ -20592,9 +20754,9 @@ var init_create = __esm({
20592
20754
  });
20593
20755
 
20594
20756
  // apps/desktop/src/daemon/async-question-response.ts
20595
- import { createHash as createHash3 } from "node:crypto";
20757
+ import { createHash as createHash4 } from "node:crypto";
20596
20758
  function submissionId(input) {
20597
- const h = createHash3("sha256").update(JSON.stringify([input.principal, input.threadId, input.idempotencyKey])).digest("hex");
20759
+ const h = createHash4("sha256").update(JSON.stringify([input.principal, input.threadId, input.idempotencyKey])).digest("hex");
20598
20760
  return `${h.slice(0, 8)}-${h.slice(8, 12)}-4${h.slice(13, 16)}-8${h.slice(17, 20)}-${h.slice(20, 32)}`;
20599
20761
  }
20600
20762
  function questionWasNotDispatched(result) {
@@ -20602,7 +20764,7 @@ function questionWasNotDispatched(result) {
20602
20764
  }
20603
20765
  async function respondAsyncQuestion(options) {
20604
20766
  const { store, input } = options;
20605
- const fingerprint2 = createHash3("sha256").update(JSON.stringify([input.questionId, input.answer])).digest("hex");
20767
+ const fingerprint2 = createHash4("sha256").update(JSON.stringify([input.questionId, input.answer])).digest("hex");
20606
20768
  const key = { principal: input.principal, threadId: input.threadId, clientMessageId: submissionId(input) };
20607
20769
  if (store.get(key).state !== "untracked") {
20608
20770
  const existing = await store.reserve({ ...key, questionId: input.questionId, fingerprint: fingerprint2, nativeToken: key.clientMessageId });
@@ -21125,7 +21287,7 @@ function formatRedactedSeparator(separator) {
21125
21287
  function cleanDetail(detail) {
21126
21288
  return detail.replace(/<!--[\s\S]*?-->/g, " ").replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(
21127
21289
  SENSITIVE_KEY_PATTERN,
21128
- (_match, prefix, quote, key, separator) => `${prefix}${quote}${key}${quote}${formatRedactedSeparator(separator)}[REDACTED]`
21290
+ (_match, prefix, quote2, key, separator) => `${prefix}${quote2}${key}${quote2}${formatRedactedSeparator(separator)}[REDACTED]`
21129
21291
  ).replace(
21130
21292
  BEARER_PATTERN,
21131
21293
  (_match, prefix, scheme, separator) => `${prefix}${scheme}${formatRedactedSeparator(separator)}[REDACTED]`
@@ -21288,10 +21450,10 @@ var init_status = __esm({
21288
21450
  });
21289
21451
 
21290
21452
  // apps/desktop/src/niuma/thread-summary.ts
21291
- import path23 from "node:path";
21453
+ import path24 from "node:path";
21292
21454
  function pathBelongsToProjectRoot(projectRoot, candidateRoot) {
21293
- const relative = path23.relative(path23.resolve(projectRoot), path23.resolve(candidateRoot));
21294
- return relative === "" || !relative.startsWith("..") && !path23.isAbsolute(relative);
21455
+ const relative = path24.relative(path24.resolve(projectRoot), path24.resolve(candidateRoot));
21456
+ return relative === "" || !relative.startsWith("..") && !path24.isAbsolute(relative);
21295
21457
  }
21296
21458
  function toLatestTurn(turns) {
21297
21459
  const latest = turns.at(-1);
@@ -21359,7 +21521,7 @@ function normalizeThreadSummary(thread4, pending = null, options = {}) {
21359
21521
  id: thread4.id,
21360
21522
  title: thread4.name ?? thread4.preview ?? "",
21361
21523
  projectRoot: thread4.cwd,
21362
- projectName: path23.basename(thread4.cwd) || thread4.cwd,
21524
+ projectName: path24.basename(thread4.cwd) || thread4.cwd,
21363
21525
  status: status2,
21364
21526
  pending: normalizedPending,
21365
21527
  createdAt: thread4.createdAt,
@@ -22679,7 +22841,7 @@ var init_codex_input = __esm({
22679
22841
  });
22680
22842
 
22681
22843
  // apps/desktop/src/daemon/runtime/message-send-operation.ts
22682
- import { createHash as createHash4, randomUUID as randomUUID15 } from "node:crypto";
22844
+ import { createHash as createHash5, randomUUID as randomUUID15 } from "node:crypto";
22683
22845
  function createMessageSendOperation(ports) {
22684
22846
  return async (params, options) => ports.runResponseOperation(async (generation) => {
22685
22847
  const threadId2 = params.threadId;
@@ -22821,7 +22983,7 @@ function createMessageSendOperation(ports) {
22821
22983
  attachmentId: part.attachmentId,
22822
22984
  clientMessageId: clientUserMessageId ?? `legacy-${randomUUID15()}`,
22823
22985
  partIndex,
22824
- sha256: createHash4("sha256").update(Buffer.from(native.url.slice(native.url.indexOf(",") + 1), "base64")).digest("hex")
22986
+ sha256: createHash5("sha256").update(Buffer.from(native.url.slice(native.url.indexOf(",") + 1), "base64")).digest("hex")
22825
22987
  });
22826
22988
  dispatchedImageIds.add(part.attachmentId);
22827
22989
  }
@@ -24378,12 +24540,12 @@ var init_requests = __esm({
24378
24540
  });
24379
24541
 
24380
24542
  // apps/desktop/src/niuma/async-questions.ts
24381
- import { createHash as createHash5 } from "node:crypto";
24543
+ import { createHash as createHash6 } from "node:crypto";
24382
24544
  function asyncQuestionId(rawId, index) {
24383
24545
  if (!rawId || !Number.isSafeInteger(index) || index < 0 || index > 2) {
24384
24546
  throw new TypeError("invalid_async_question_identity");
24385
24547
  }
24386
- return `aq_${createHash5("sha256").update(JSON.stringify([rawId, index])).digest("base64url")}`;
24548
+ return `aq_${createHash6("sha256").update(JSON.stringify([rawId, index])).digest("base64url")}`;
24387
24549
  }
24388
24550
  function exactRecord2(value, keys3) {
24389
24551
  if (!value || typeof value !== "object" || Array.isArray(value)) return false;
@@ -24491,9 +24653,9 @@ function resourcePaths(platform2 = process.platform) {
24491
24653
  toLink(value) {
24492
24654
  const parsed = parseLocal(value);
24493
24655
  if (parsed === null) return null;
24494
- const path55 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
24656
+ const path56 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
24495
24657
  try {
24496
- return encodeURIComponent(path55).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
24658
+ return encodeURIComponent(path56).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
24497
24659
  } catch {
24498
24660
  return null;
24499
24661
  }
@@ -24524,7 +24686,7 @@ var init_resource_paths = __esm({
24524
24686
  });
24525
24687
 
24526
24688
  // apps/desktop/src/attachments/file-input.ts
24527
- import { createHash as createHash6 } from "node:crypto";
24689
+ import { createHash as createHash7 } from "node:crypto";
24528
24690
  function desktopFileAttachments(content2) {
24529
24691
  return content2.flatMap((part) => (desktopFiles.get(part) ?? []).map((file) => ({ ...file })));
24530
24692
  }
@@ -24560,12 +24722,12 @@ function nativeInputFingerprint(value) {
24560
24722
  if (previous?.type === "text") previous.value += part.text;
24561
24723
  else canonical.push({ type: "text", value: part.text });
24562
24724
  } else if (part.type === "image" && typeof (part.url ?? part.image_url) === "string") {
24563
- canonical.push({ type: "image", value: createHash6("sha256").update(part.url ?? part.image_url).digest("hex") });
24725
+ canonical.push({ type: "image", value: createHash7("sha256").update(part.url ?? part.image_url).digest("hex") });
24564
24726
  } else if (["localImage", "local_image"].includes(String(part.type)) && typeof part.path === "string") {
24565
24727
  canonical.push({ type: "localImage", value: part.path });
24566
24728
  } else return null;
24567
24729
  }
24568
- return createHash6("sha256").update(JSON.stringify(canonical)).digest("hex");
24730
+ return createHash7("sha256").update(JSON.stringify(canonical)).digest("hex");
24569
24731
  }
24570
24732
  function cloneWithNativeInputEvidence(value) {
24571
24733
  const copy2 = structuredClone(value);
@@ -24636,10 +24798,10 @@ var init_response_annotations = __esm({
24636
24798
  });
24637
24799
 
24638
24800
  // apps/desktop/src/attachments/image-identity.ts
24639
- import { createHash as createHash7 } from "node:crypto";
24640
- function unavailableImageId(path55, itemId, partIndex) {
24641
- const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null, path55]) : path55;
24642
- return `unavailable:${createHash7("sha256").update(identity6).digest("hex")}`;
24801
+ import { createHash as createHash8 } from "node:crypto";
24802
+ function unavailableImageId(path56, itemId, partIndex) {
24803
+ const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null, path56]) : path56;
24804
+ return `unavailable:${createHash8("sha256").update(identity6).digest("hex")}`;
24643
24805
  }
24644
24806
  var init_image_identity = __esm({
24645
24807
  "apps/desktop/src/attachments/image-identity.ts"() {
@@ -24732,15 +24894,15 @@ function normalizeMessageContent(value, resolveKnownLocalImage, itemId, original
24732
24894
  }
24733
24895
  return content2;
24734
24896
  }
24735
- function userFile(name2, path55) {
24897
+ function userFile(name2, path56) {
24736
24898
  const part = { type: "file", name: name2 };
24737
- userFileSource.set(part, path55);
24899
+ userFileSource.set(part, path56);
24738
24900
  return part;
24739
24901
  }
24740
24902
  function userFileSources(content2 = []) {
24741
24903
  return content2.flatMap((part, index) => {
24742
- const path55 = userFileSource.get(part);
24743
- return part.type === "file" && typeof path55 === "string" ? [{ index, path: path55 }] : [];
24904
+ const path56 = userFileSource.get(part);
24905
+ return part.type === "file" && typeof path56 === "string" ? [{ index, path: path56 }] : [];
24744
24906
  });
24745
24907
  }
24746
24908
  function codexImageWrapperFileList(text11) {
@@ -24777,11 +24939,11 @@ function standardCodexImageFileListEntries(fileList) {
24777
24939
  break;
24778
24940
  }
24779
24941
  const name2 = safeCodexFileName(match[1] ?? match[3] ?? "");
24780
- const path55 = match[2] ?? match[4] ?? "";
24781
- if (!name2 || !isRecordedResourcePath(path55)) {
24942
+ const path56 = match[2] ?? match[4] ?? "";
24943
+ if (!name2 || !isRecordedResourcePath(path56)) {
24782
24944
  return null;
24783
24945
  }
24784
- entries.push({ name: name2, path: path55 });
24946
+ entries.push({ name: name2, path: path56 });
24785
24947
  remaining = remaining.slice(match[0].length);
24786
24948
  remaining = remaining.replace(/^Image attachment: true\r?\n/u, "");
24787
24949
  }
@@ -24797,10 +24959,10 @@ function redactCodexImageWrapperPaths(text11) {
24797
24959
  }
24798
24960
  const fileList = wrapper.fileList.replace(
24799
24961
  /(^## [^\r\n]+:[ \t]*\r?\n)[ \t]*([^\r\n]+)/gmu,
24800
- (all, prefix, path55) => isRecordedResourcePath(path55) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24962
+ (all, prefix, path56) => isRecordedResourcePath(path56) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24801
24963
  ).replace(
24802
24964
  /^(## [^\r\n]+:)[ \t]+([^\r\n]+)$/gmu,
24803
- (all, prefix, path55) => isRecordedResourcePath(path55) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24965
+ (all, prefix, path56) => isRecordedResourcePath(path56) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
24804
24966
  );
24805
24967
  const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
24806
24968
  return `${wrapper.prefix}${fileList}${text11.slice(fileListEnd)}`;
@@ -24811,7 +24973,7 @@ function redactKnownCodexWrapperPaths(text11, paths) {
24811
24973
  return text11;
24812
24974
  }
24813
24975
  const fileList = paths.reduce(
24814
- (result, path55) => result.replaceAll(path55, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
24976
+ (result, path56) => result.replaceAll(path56, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
24815
24977
  wrapper.fileList
24816
24978
  );
24817
24979
  const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
@@ -24828,8 +24990,8 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
24828
24990
  }
24829
24991
  const localImagePaths = value.flatMap((part) => {
24830
24992
  const record26 = asRecord11(part);
24831
- const path55 = localImagePath(record26);
24832
- return path55 === null ? [] : [path55];
24993
+ const path56 = localImagePath(record26);
24994
+ return path56 === null ? [] : [path56];
24833
24995
  });
24834
24996
  const text11 = redactKnownCodexWrapperPaths(
24835
24997
  redactCodexImageWrapperPaths(firstPart2.text),
@@ -24863,9 +25025,9 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
24863
25025
  const localImages = value.flatMap((part, index) => {
24864
25026
  const partIndex = originalPartIndices?.[index] ?? index;
24865
25027
  const record26 = asRecord11(part);
24866
- const path55 = localImagePath(record26);
24867
- return path55 === null ? [] : [{
24868
- path: path55,
25028
+ const path56 = localImagePath(record26);
25029
+ return path56 === null ? [] : [{
25030
+ path: path56,
24869
25031
  partIndex,
24870
25032
  image: record26.type === "historyImage" ? historyImageContent(record26, itemId, partIndex) : null
24871
25033
  }];
@@ -24994,8 +25156,8 @@ function redactRawLocalImagePaths(rawItem) {
24994
25156
  let containsLocalImage = false;
24995
25157
  let containsRedactedWrapperPath = false;
24996
25158
  const localImagePaths = item.content.map((part) => asRecord11(part)).flatMap((part) => {
24997
- const path55 = localImagePath(part);
24998
- return path55 === null ? [] : [path55];
25159
+ const path56 = localImagePath(part);
25160
+ return path56 === null ? [] : [path56];
24999
25161
  });
25000
25162
  const content2 = item.content.map((part) => {
25001
25163
  const record26 = asRecord11(part);
@@ -25963,8 +26125,8 @@ var init_events = __esm({
25963
26125
  const patches = Array.isArray(change.patches) ? change.patches : [];
25964
26126
  for (const patch of patches) {
25965
26127
  const candidate = objectRecord6(patch);
25966
- const path55 = Array.isArray(candidate.path) ? candidate.path : [];
25967
- if ((candidate.op === "add" || candidate.op === "replace") && path55.length === 1 && path55[0] === "threadRuntimeStatus") {
26128
+ const path56 = Array.isArray(candidate.path) ? candidate.path : [];
26129
+ if ((candidate.op === "add" || candidate.op === "replace") && path56.length === 1 && path56[0] === "threadRuntimeStatus") {
25968
26130
  runtimeStatusValue = candidate.value;
25969
26131
  }
25970
26132
  }
@@ -26931,7 +27093,7 @@ var init_device_upload_cache_policy = __esm({
26931
27093
  });
26932
27094
 
26933
27095
  // apps/desktop/src/attachments/device-upload-cache-store.ts
26934
- import { createHash as createHash8 } from "node:crypto";
27096
+ import { createHash as createHash9 } from "node:crypto";
26935
27097
  async function cacheReadBlock(storage, entry, index, size2) {
26936
27098
  const snapshot2 = await storage.readDocument(entry, 131072);
26937
27099
  const handle = await storage.openContent(entry, { expected: snapshot2.content, match: "object", maxBytes: Math.max(1, size2) });
@@ -26951,12 +27113,12 @@ var init_device_upload_cache_store = __esm({
26951
27113
  "apps/desktop/src/attachments/device-upload-cache-store.ts"() {
26952
27114
  "use strict";
26953
27115
  CACHE_CHUNK_BYTES = 49152;
26954
- cacheDigest = (bytes3) => createHash8("sha256").update(bytes3).digest("hex");
27116
+ cacheDigest = (bytes3) => createHash9("sha256").update(bytes3).digest("hex");
26955
27117
  }
26956
27118
  });
26957
27119
 
26958
27120
  // apps/desktop/src/attachments/device-upload-cache.ts
26959
- import { randomUUID as randomUUID16, createHash as createHash9 } from "node:crypto";
27121
+ import { randomUUID as randomUUID16, createHash as createHash10 } from "node:crypto";
26960
27122
  import { setTimeout as sleep2 } from "node:timers/promises";
26961
27123
  import { z as z9 } from "zod";
26962
27124
  async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVICE_UPLOAD_CACHE_POLICY, admit = async (_bytes, work) => work() }) {
@@ -27028,7 +27190,7 @@ async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVIC
27028
27190
  continue;
27029
27191
  }
27030
27192
  let next = 0;
27031
- const hash3 = createHash9("sha256");
27193
+ const hash3 = createHash10("sha256");
27032
27194
  for (; next < m.chunks.length; next++) {
27033
27195
  try {
27034
27196
  const b = await cacheReadBlock(storage, handle, next, m.key.byteSize);
@@ -27131,7 +27293,7 @@ async function createDeviceUploadCache({ storage, now = Date.now, policy = DEVIC
27131
27293
  seal: (lease) => serial(async () => {
27132
27294
  const e = owned(lease), m = e.manifest;
27133
27295
  if (m.chunks.length !== Math.ceil(m.key.byteSize / CACHE_CHUNK_BYTES)) throw busy();
27134
- const hash3 = createHash9("sha256");
27296
+ const hash3 = createHash10("sha256");
27135
27297
  for (let i = 0; i < m.chunks.length; i++) {
27136
27298
  const b = await cacheReadBlock(storage, e.handle, i, m.key.byteSize);
27137
27299
  if (cacheDigest(b) !== m.chunks[i]) throw busy();
@@ -27967,13 +28129,13 @@ var init_upload_task_store = __esm({
27967
28129
  import { execFile as execFile7 } from "node:child_process";
27968
28130
  import { constants as constants2 } from "node:fs";
27969
28131
  import { lstat, open } from "node:fs/promises";
27970
- import path24 from "node:path";
28132
+ import path25 from "node:path";
27971
28133
  function limit(max) {
27972
28134
  if (!Number.isSafeInteger(max) || max < 1 || max > 50 * 1024 * 1024) throw new PrivateBinaryFileError("capacity");
27973
28135
  }
27974
28136
  function resolved2(file) {
27975
28137
  try {
27976
- return windows() ? localWindowsPath(file) : path24.resolve(file);
28138
+ return windows() ? localWindowsPath(file) : path25.resolve(file);
27977
28139
  } catch {
27978
28140
  throw unavailable2();
27979
28141
  }
@@ -28016,7 +28178,7 @@ async function windowsMode(file, seal = false) {
28016
28178
  return output;
28017
28179
  }
28018
28180
  async function parentIdentity(file) {
28019
- const directory = path24.dirname(file), initial = await lstat(directory, { bigint: true });
28181
+ const directory = path25.dirname(file), initial = await lstat(directory, { bigint: true });
28020
28182
  if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable2();
28021
28183
  if (windows()) {
28022
28184
  try {
@@ -28083,10 +28245,10 @@ async function openFile(file, options) {
28083
28245
  let tail = Promise.resolve();
28084
28246
  async function guard() {
28085
28247
  if (closed || poisoned) throw unavailable2();
28086
- const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory = await lstat(path24.dirname(file), { bigint: true });
28248
+ const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory = await lstat(path25.dirname(file), { bigint: true });
28087
28249
  if (!trusted2(held) || !trusted2(current2) || !same3(held, baseline) || !sameSnapshot(held, current2) || !same3(parent, directory) || !directory.isDirectory() || directory.isSymbolicLink() || held.size > BigInt(options.maxBytes) || (!options.writable || mode === "immutable") && !sameSnapshot(baseline, held)) throw unavailable2();
28088
28250
  if (!windows() && posixMode(held) !== mode) throw unavailable2();
28089
- if (!windows()) privateLogFiles.checkDirectory(path24.dirname(file));
28251
+ if (!windows()) privateLogFiles.checkDirectory(path25.dirname(file));
28090
28252
  }
28091
28253
  await guard();
28092
28254
  checkExpected(await status(h), options);
@@ -28223,11 +28385,11 @@ if($env:NIUMA_BINARY_SEAL -eq '1' -and $mode -ne 'immutable') {
28223
28385
  handle = await open(file, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (windows() ? 0 : constants2.O_NOFOLLOW), 384);
28224
28386
  if (!windows()) await handle.chmod(384);
28225
28387
  const held = await handle.stat({ bigint: true }), current2 = await lstat(file, { bigint: true });
28226
- if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(path24.dirname(file), { bigint: true }))) throw unavailable2();
28388
+ if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(path25.dirname(file), { bigint: true }))) throw unavailable2();
28227
28389
  if (windows() && await windowsMode(file) !== "mutable") throw unavailable2();
28228
28390
  await handle.sync();
28229
28391
  const result = await status(handle);
28230
- if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(path24.dirname(file), { bigint: true }))) throw unavailable2();
28392
+ if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(path25.dirname(file), { bigint: true }))) throw unavailable2();
28231
28393
  await handle.close();
28232
28394
  handle = void 0;
28233
28395
  return result;
@@ -28327,7 +28489,7 @@ import { randomUUID as randomUUID18 } from "node:crypto";
28327
28489
  import { execFile as execFile9 } from "node:child_process";
28328
28490
  import { constants as constants3 } from "node:fs";
28329
28491
  import { chmod, lstat as lstat3, mkdir, open as open2, readdir, rename, rm } from "node:fs/promises";
28330
- import path25 from "node:path";
28492
+ import path26 from "node:path";
28331
28493
  function nameOnly(name2) {
28332
28494
  if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/u.test(name2)) throw unavailable3();
28333
28495
  }
@@ -28336,7 +28498,7 @@ function budget(maxBytes) {
28336
28498
  }
28337
28499
  async function openDirectories(requested, windowsCandidate) {
28338
28500
  const windows2 = process.platform === "win32";
28339
- const root = windows2 ? localWindowsPath(requested) : path25.resolve(requested);
28501
+ const root = windows2 ? localWindowsPath(requested) : path26.resolve(requested);
28340
28502
  let rootIdentity;
28341
28503
  try {
28342
28504
  if (windows2) await ensureWindowsPrivateDirectoryAsync(root);
@@ -28381,7 +28543,7 @@ async function openDirectories(requested, windowsCandidate) {
28381
28543
  }
28382
28544
  function token3(value) {
28383
28545
  const directory = Object.freeze({ get sourcePath() {
28384
- return path25.join(value.path, "source");
28546
+ return path26.join(value.path, "source");
28385
28547
  } });
28386
28548
  records.set(directory, value);
28387
28549
  return directory;
@@ -28437,7 +28599,7 @@ async function openDirectories(requested, windowsCandidate) {
28437
28599
  return serial(async () => {
28438
28600
  nameOnly(name2);
28439
28601
  await guard();
28440
- const directory = path25.join(root, name2);
28602
+ const directory = path26.join(root, name2);
28441
28603
  if (!windows2) privateLogFiles.checkDirectory(directory);
28442
28604
  const identity6 = await lstat3(directory, { bigint: true });
28443
28605
  const result = token3({ name: name2, path: directory, identity: identity6, staged: false, pending: true, ready: true });
@@ -28450,7 +28612,7 @@ async function openDirectories(requested, windowsCandidate) {
28450
28612
  mutable();
28451
28613
  nameOnly(name2);
28452
28614
  await guard();
28453
- const directory = path25.join(root, ".pending-" + name2);
28615
+ const directory = path26.join(root, ".pending-" + name2);
28454
28616
  await mkdir(directory, { mode: 448 });
28455
28617
  const identity6 = await lstat3(directory, { bigint: true });
28456
28618
  if (windows2) {
@@ -28480,7 +28642,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28480
28642
  return serial(async () => {
28481
28643
  budget(maxBytes);
28482
28644
  await guard(directory);
28483
- const handle = await privateBinaryFiles.open(path25.join(record26(directory).path, "manifest.json"), { maxBytes, mode: "mutable" });
28645
+ const handle = await privateBinaryFiles.open(path26.join(record26(directory).path, "manifest.json"), { maxBytes, mode: "mutable" });
28484
28646
  let failed = false;
28485
28647
  const bytes3 = Buffer.alloc(maxBytes);
28486
28648
  try {
@@ -28529,7 +28691,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28529
28691
  async function currentManifest() {
28530
28692
  let stats;
28531
28693
  try {
28532
- stats = await lstat3(path25.join(value.path, "manifest.json"), { bigint: true });
28694
+ stats = await lstat3(path26.join(value.path, "manifest.json"), { bigint: true });
28533
28695
  } catch (error2) {
28534
28696
  if (error2.code === "ENOENT") return null;
28535
28697
  throw error2;
@@ -28537,7 +28699,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28537
28699
  if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n || !windows2 && (stats.uid !== BigInt(process.getuid()) || (stats.mode & 0o777n) !== 0o600n)) throw unavailable3();
28538
28700
  if (stats.size > BigInt(maxBytes)) throw new PrivateUploadDirectoryError("capacity");
28539
28701
  if (windows2) {
28540
- const handle = await privateBinaryFiles.open(path25.join(value.path, "manifest.json"), {
28702
+ const handle = await privateBinaryFiles.open(path26.join(value.path, "manifest.json"), {
28541
28703
  maxBytes,
28542
28704
  mode: "mutable",
28543
28705
  match: "object",
@@ -28554,13 +28716,13 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28554
28716
  } finally {
28555
28717
  await handle.close();
28556
28718
  }
28557
- const after = await lstat3(path25.join(value.path, "manifest.json"), { bigint: true });
28719
+ const after = await lstat3(path26.join(value.path, "manifest.json"), { bigint: true });
28558
28720
  if (!same4(stats, after) || stats.size !== after.size || stats.mtimeNs !== after.mtimeNs || stats.ctimeNs !== after.ctimeNs) throw unavailable3();
28559
28721
  }
28560
28722
  return stats;
28561
28723
  }
28562
28724
  const original = await currentManifest();
28563
- const temporary = path25.join(value.path, ".manifest-" + randomUUID18());
28725
+ const temporary = path26.join(value.path, ".manifest-" + randomUUID18());
28564
28726
  let created = false, published = false, identity6;
28565
28727
  try {
28566
28728
  if (windows2) {
@@ -28615,7 +28777,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28615
28777
  if (!identity6 || !same4(identity6, current2) || !current2.isFile() || current2.isSymbolicLink() || current2.nlink !== 1n || !windows2 && (current2.uid !== BigInt(process.getuid()) || (current2.mode & 0o777n) !== 0o600n)) throw unavailable3();
28616
28778
  const previous = await currentManifest();
28617
28779
  if (original === null ? previous !== null : previous === null || !same4(original, previous) || original.size !== previous.size || original.mtimeNs !== previous.mtimeNs || original.ctimeNs !== previous.ctimeNs) throw unavailable3();
28618
- await rename(temporary, path25.join(value.path, "manifest.json"));
28780
+ await rename(temporary, path26.join(value.path, "manifest.json"));
28619
28781
  published = true;
28620
28782
  created = false;
28621
28783
  value.pending = true;
@@ -28652,7 +28814,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
28652
28814
  const value = record26(directory);
28653
28815
  if (!value.staged || !value.ready) throw unavailable3();
28654
28816
  await finish(directory);
28655
- const target = path25.join(root, value.name);
28817
+ const target = path26.join(root, value.name);
28656
28818
  try {
28657
28819
  await lstat3(target);
28658
28820
  throw unavailable3();
@@ -28727,7 +28889,7 @@ var init_private_upload_content_types = __esm({
28727
28889
  });
28728
28890
 
28729
28891
  // apps/desktop/src/platform/legacy-upload-contents.ts
28730
- import { createHash as createHash10 } from "node:crypto";
28892
+ import { createHash as createHash11 } from "node:crypto";
28731
28893
  async function using(handle, operation) {
28732
28894
  let failed = false;
28733
28895
  try {
@@ -29030,14 +29192,14 @@ var init_legacy_upload_contents = __esm({
29030
29192
  init_private_binary_files();
29031
29193
  init_private_upload_directories();
29032
29194
  init_private_upload_content_types();
29033
- revision = (body) => body === null ? "empty" : createHash10("sha256").update(body).digest("hex");
29195
+ revision = (body) => body === null ? "empty" : createHash11("sha256").update(body).digest("hex");
29034
29196
  unavailable4 = () => new PrivateUploadContentError("unavailable");
29035
29197
  }
29036
29198
  });
29037
29199
 
29038
29200
  // apps/desktop/src/daemon/runtime/attachment-access.ts
29039
- import { createHash as createHash11 } from "node:crypto";
29040
- import path26 from "node:path";
29201
+ import { createHash as createHash12 } from "node:crypto";
29202
+ import path27 from "node:path";
29041
29203
  import process2 from "node:process";
29042
29204
  var RuntimeAttachmentAccess;
29043
29205
  var init_attachment_access = __esm({
@@ -29075,7 +29237,7 @@ var init_attachment_access = __esm({
29075
29237
  const cached = createCachedUploadTaskStore({
29076
29238
  base,
29077
29239
  cache: () => cache2 ??= (async () => {
29078
- const root = path26.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
29240
+ const root = path27.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
29079
29241
  return createDeviceUploadCache({
29080
29242
  storage: composeLegacyUploadContents(await openPrivateUploadDirectories(root), privateBinaryFiles),
29081
29243
  admit: (bytes3, operation) => this.ports.attachmentStorage().withAttachmentUploadAdmission(void 0, bytes3, operation)
@@ -29170,7 +29332,7 @@ var init_attachment_access = __esm({
29170
29332
  captureFileResourceSource(threadId2) {
29171
29333
  const generation = this.ports.lifecycle().runtimeGenerationValue, resources = this.ports.projection().resources, viewStore = this.ports.projection().store;
29172
29334
  const source2 = viewStore.getOrderSource(threadId2);
29173
- const projectFingerprint = () => createHash11("sha256").update(this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 })?.projectRoot ?? "").digest("hex");
29335
+ const projectFingerprint = () => createHash12("sha256").update(this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 })?.projectRoot ?? "").digest("hex");
29174
29336
  const project3 = projectFingerprint();
29175
29337
  const appGeneration = this.ports.appServerLoads().connectionGeneration, ipcGeneration = this.ports.desktopSession().ipcConnectionGenerationValue;
29176
29338
  const appAuthority = this.ports.appProjection().authorityFor(threadId2);
@@ -29218,8 +29380,8 @@ var init_attachment_access = __esm({
29218
29380
  });
29219
29381
 
29220
29382
  // apps/desktop/src/niuma/project-state.ts
29221
- import fs17 from "node:fs/promises";
29222
- import path27 from "node:path";
29383
+ import fs18 from "node:fs/promises";
29384
+ import path28 from "node:path";
29223
29385
  import { z as z10 } from "zod";
29224
29386
  function emptyProjectState() {
29225
29387
  return {
@@ -29288,9 +29450,9 @@ function isMissingFileError(error2) {
29288
29450
  return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
29289
29451
  }
29290
29452
  async function readProjectState(codexHome) {
29291
- const statePath = path27.join(codexHome, ".codex-global-state.json");
29453
+ const statePath = path28.join(codexHome, ".codex-global-state.json");
29292
29454
  try {
29293
- const raw = await fs17.readFile(statePath, "utf8");
29455
+ const raw = await fs18.readFile(statePath, "utf8");
29294
29456
  const parsed = RawProjectStateSchema.parse(JSON.parse(raw));
29295
29457
  const localProjects = readLocalProjects(parsed["local-projects"]);
29296
29458
  const rootsByProjectId = new Map(localProjects.map((project3) => [project3.id, project3.root]));
@@ -29383,7 +29545,7 @@ var init_project_state = __esm({
29383
29545
  });
29384
29546
 
29385
29547
  // apps/desktop/src/niuma/session-originator.ts
29386
- import fs18 from "node:fs/promises";
29548
+ import fs19 from "node:fs/promises";
29387
29549
  function record9(value) {
29388
29550
  return value && typeof value === "object" && !Array.isArray(value) ? value : null;
29389
29551
  }
@@ -29400,7 +29562,7 @@ async function readFirstLine(filePath) {
29400
29562
  let byteCount = 0;
29401
29563
  let position = 0;
29402
29564
  try {
29403
- handle = await fs18.open(filePath, "r");
29565
+ handle = await fs19.open(filePath, "r");
29404
29566
  while (true) {
29405
29567
  const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
29406
29568
  const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
@@ -29496,7 +29658,7 @@ var init_session_originator = __esm({
29496
29658
  });
29497
29659
 
29498
29660
  // apps/desktop/src/niuma/session-timestamps.ts
29499
- import fs19 from "node:fs/promises";
29661
+ import fs20 from "node:fs/promises";
29500
29662
  import { createInterface as createInterface2 } from "node:readline";
29501
29663
  function record10(value) {
29502
29664
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -29782,7 +29944,7 @@ var init_session_timestamps = __esm({
29782
29944
  try {
29783
29945
  const sessionPath = explicitPath === void 0 ? await this.resolveSessionPath(threadId2) : explicitPath;
29784
29946
  if (!sessionPath || this.closed) return "unavailable";
29785
- const stat3 = await fs19.stat(sessionPath);
29947
+ const stat3 = await fs20.stat(sessionPath);
29786
29948
  if (this.closed) return "unavailable";
29787
29949
  return JSON.stringify([stat3.dev, stat3.ino, stat3.size, stat3.mtimeMs, stat3.ctimeMs]);
29788
29950
  } catch {
@@ -29955,7 +30117,7 @@ var init_session_timestamps = __esm({
29955
30117
  }
29956
30118
  }
29957
30119
  async readReplay(sessionPath, threadId2, fingerprint2, empty) {
29958
- const handle = await fs19.open(sessionPath, "r");
30120
+ const handle = await fs20.open(sessionPath, "r");
29959
30121
  if (this.closed) {
29960
30122
  await handle.close();
29961
30123
  return empty;
@@ -30550,7 +30712,7 @@ var init_app_server_upgrade = __esm({
30550
30712
 
30551
30713
  // apps/desktop/src/daemon/codex-subagent-avatars.ts
30552
30714
  import { open as open3 } from "node:fs/promises";
30553
- import path28 from "node:path";
30715
+ import path29 from "node:path";
30554
30716
  import sharp from "sharp";
30555
30717
  function record11(value) {
30556
30718
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
@@ -30591,7 +30753,7 @@ async function parseCatalog(source2, readAsset) {
30591
30753
  }
30592
30754
  return new CodexSubagentAvatars(images);
30593
30755
  }
30594
- async function loadCodexSubagentAvatars(archivePath = path28.join(path28.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
30756
+ async function loadCodexSubagentAvatars(archivePath = path29.join(path29.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
30595
30757
  let file;
30596
30758
  try {
30597
30759
  file = await open3(archivePath, "r");
@@ -30658,8 +30820,8 @@ var init_codex_subagent_avatars = __esm({
30658
30820
  });
30659
30821
 
30660
30822
  // apps/desktop/src/platform/private-document-files.ts
30661
- import fs20 from "node:fs";
30662
- import path29 from "node:path";
30823
+ import fs21 from "node:fs";
30824
+ import path30 from "node:path";
30663
30825
  import { randomUUID as randomUUID20 } from "node:crypto";
30664
30826
  function checkLimit(maxBytes) {
30665
30827
  if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 32 * 1024 * 1024) throw new PrivateDocumentFileError("capacity");
@@ -30671,7 +30833,7 @@ function trusted3(stats, directory = false, strictDirectory = false) {
30671
30833
  }
30672
30834
  function statFile(file, maxBytes) {
30673
30835
  try {
30674
- const stats = fs20.lstatSync(file, { bigint: true });
30836
+ const stats = fs21.lstatSync(file, { bigint: true });
30675
30837
  if (!trusted3(stats)) throw new PrivateDocumentFileError("unavailable");
30676
30838
  if (stats.size > BigInt(maxBytes)) throw new PrivateDocumentFileError("capacity");
30677
30839
  return stats;
@@ -30691,33 +30853,33 @@ function readPosix(file, maxBytes, strictDirectory) {
30691
30853
  let directoryFd;
30692
30854
  let fd;
30693
30855
  try {
30694
- const directory = path29.dirname(file);
30856
+ const directory = path30.dirname(file);
30695
30857
  let parent;
30696
30858
  try {
30697
- parent = fs20.lstatSync(directory, { bigint: true });
30859
+ parent = fs21.lstatSync(directory, { bigint: true });
30698
30860
  } catch (error2) {
30699
30861
  if (missing(error2)) return null;
30700
30862
  throw error2;
30701
30863
  }
30702
30864
  if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
30703
- directoryFd = fs20.openSync(directory, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30704
- if (!same5(parent, fs20.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30865
+ directoryFd = fs21.openSync(directory, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30866
+ if (!same5(parent, fs21.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30705
30867
  const original = statFile(file, maxBytes);
30706
30868
  if (original === null) return null;
30707
- fd = fs20.openSync(file, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30708
- const opened = fs20.fstatSync(fd, { bigint: true });
30869
+ fd = fs21.openSync(file, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30870
+ const opened = fs21.fstatSync(fd, { bigint: true });
30709
30871
  if (!trusted3(opened) || !same5(original, opened) || original.size !== opened.size) throw new PrivateDocumentFileError("unavailable");
30710
30872
  const contents = Buffer.alloc(maxBytes + 1);
30711
30873
  try {
30712
30874
  let length = 0;
30713
30875
  while (length < contents.length) {
30714
- const count = fs20.readSync(fd, contents, length, contents.length - length, null);
30876
+ const count = fs21.readSync(fd, contents, length, contents.length - length, null);
30715
30877
  if (count === 0) break;
30716
30878
  length += count;
30717
30879
  }
30718
30880
  if (length > maxBytes) throw new PrivateDocumentFileError("capacity");
30719
30881
  const current2 = statFile(file, maxBytes);
30720
- if (current2 === null || !same5(original, current2) || !same5(parent, fs20.lstatSync(directory, { bigint: true }))) {
30882
+ if (current2 === null || !same5(original, current2) || !same5(parent, fs21.lstatSync(directory, { bigint: true }))) {
30721
30883
  throw new PrivateDocumentFileError("unavailable");
30722
30884
  }
30723
30885
  return decode(contents.subarray(0, length));
@@ -30726,42 +30888,42 @@ function readPosix(file, maxBytes, strictDirectory) {
30726
30888
  }
30727
30889
  } finally {
30728
30890
  try {
30729
- if (fd !== void 0) fs20.closeSync(fd);
30891
+ if (fd !== void 0) fs21.closeSync(fd);
30730
30892
  } finally {
30731
- if (directoryFd !== void 0) fs20.closeSync(directoryFd);
30893
+ if (directoryFd !== void 0) fs21.closeSync(directoryFd);
30732
30894
  }
30733
30895
  }
30734
30896
  }
30735
30897
  function writePosix(file, body, maxBytes, strictDirectory) {
30736
- const directory = path29.dirname(file);
30737
- const temporary = path29.join(directory, `.${path29.basename(file)}.${randomUUID20()}.tmp`);
30898
+ const directory = path30.dirname(file);
30899
+ const temporary = path30.join(directory, `.${path30.basename(file)}.${randomUUID20()}.tmp`);
30738
30900
  let directoryFd;
30739
30901
  let fd;
30740
30902
  let created = false;
30741
30903
  let renamed = false;
30742
30904
  try {
30743
- fs20.mkdirSync(directory, { recursive: true, mode: 448 });
30744
- const parent = fs20.lstatSync(directory, { bigint: true });
30905
+ fs21.mkdirSync(directory, { recursive: true, mode: 448 });
30906
+ const parent = fs21.lstatSync(directory, { bigint: true });
30745
30907
  if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
30746
- directoryFd = fs20.openSync(directory, fs20.constants.O_RDONLY | fs20.constants.O_NOFOLLOW);
30747
- if (!same5(parent, fs20.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30908
+ directoryFd = fs21.openSync(directory, fs21.constants.O_RDONLY | fs21.constants.O_NOFOLLOW);
30909
+ if (!same5(parent, fs21.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
30748
30910
  const original = statFile(file, maxBytes);
30749
- fd = fs20.openSync(temporary, fs20.constants.O_WRONLY | fs20.constants.O_CREAT | fs20.constants.O_EXCL | fs20.constants.O_NOFOLLOW, 384);
30911
+ fd = fs21.openSync(temporary, fs21.constants.O_WRONLY | fs21.constants.O_CREAT | fs21.constants.O_EXCL | fs21.constants.O_NOFOLLOW, 384);
30750
30912
  created = true;
30751
- const temporaryIdentity = fs20.fstatSync(fd, { bigint: true });
30913
+ const temporaryIdentity = fs21.fstatSync(fd, { bigint: true });
30752
30914
  if (!trusted3(temporaryIdentity)) throw new PrivateDocumentFileError("unavailable");
30753
- fs20.writeFileSync(fd, body);
30754
- fs20.fsyncSync(fd);
30755
- fs20.closeSync(fd);
30915
+ fs21.writeFileSync(fd, body);
30916
+ fs21.fsyncSync(fd);
30917
+ fs21.closeSync(fd);
30756
30918
  fd = void 0;
30757
30919
  const current2 = statFile(file, maxBytes);
30758
- if (!same5(parent, fs20.lstatSync(directory, { bigint: true })) || !same5(temporaryIdentity, fs20.lstatSync(temporary, { bigint: true })) || (original === null ? current2 !== null : current2 === null || !same5(original, current2))) {
30920
+ if (!same5(parent, fs21.lstatSync(directory, { bigint: true })) || !same5(temporaryIdentity, fs21.lstatSync(temporary, { bigint: true })) || (original === null ? current2 !== null : current2 === null || !same5(original, current2))) {
30759
30921
  throw new PrivateDocumentFileError("unavailable");
30760
30922
  }
30761
- fs20.renameSync(temporary, file);
30923
+ fs21.renameSync(temporary, file);
30762
30924
  renamed = true;
30763
30925
  created = false;
30764
- fs20.fsyncSync(directoryFd);
30926
+ fs21.fsyncSync(directoryFd);
30765
30927
  } catch (error2) {
30766
30928
  if (error2 instanceof PrivateDocumentFileError && !renamed) throw error2;
30767
30929
  throw new PrivateDocumentFileError("write_failed", renamed);
@@ -30769,7 +30931,7 @@ function writePosix(file, body, maxBytes, strictDirectory) {
30769
30931
  try {
30770
30932
  if (fd !== void 0) {
30771
30933
  try {
30772
- fs20.closeSync(fd);
30934
+ fs21.closeSync(fd);
30773
30935
  } catch {
30774
30936
  }
30775
30937
  }
@@ -30777,14 +30939,14 @@ function writePosix(file, body, maxBytes, strictDirectory) {
30777
30939
  try {
30778
30940
  if (directoryFd !== void 0) {
30779
30941
  try {
30780
- fs20.closeSync(directoryFd);
30942
+ fs21.closeSync(directoryFd);
30781
30943
  } catch {
30782
30944
  }
30783
30945
  }
30784
30946
  } finally {
30785
30947
  if (created) {
30786
30948
  try {
30787
- fs20.unlinkSync(temporary);
30949
+ fs21.unlinkSync(temporary);
30788
30950
  } catch {
30789
30951
  }
30790
30952
  }
@@ -30818,7 +30980,7 @@ async function windowsDocument(file, maxBytes, body) {
30818
30980
  return result;
30819
30981
  }
30820
30982
  function serialFile(file, operation) {
30821
- const absolute = path29.resolve(file);
30983
+ const absolute = path30.resolve(file);
30822
30984
  const key = desktopPlatform().id === "windows" ? absolute.toLowerCase() : absolute;
30823
30985
  const result = (operations.get(key) ?? Promise.resolve()).then(operation);
30824
30986
  const tail = result.then(() => {
@@ -30836,7 +30998,7 @@ function documentFiles(strictDirectory, guard) {
30836
30998
  return serialFile(file, async () => {
30837
30999
  try {
30838
31000
  guard?.();
30839
- const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(path29.resolve(file), maxBytes, strictDirectory);
31001
+ const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(path30.resolve(file), maxBytes, strictDirectory);
30840
31002
  guard?.();
30841
31003
  return body;
30842
31004
  } catch (error2) {
@@ -30851,7 +31013,7 @@ function documentFiles(strictDirectory, guard) {
30851
31013
  await serialFile(file, async () => {
30852
31014
  guard?.();
30853
31015
  if (desktopPlatform().id === "windows") await windowsDocument(file, maxBytes, body);
30854
- else writePosix(path29.resolve(file), body, maxBytes, strictDirectory);
31016
+ else writePosix(path30.resolve(file), body, maxBytes, strictDirectory);
30855
31017
  try {
30856
31018
  guard?.();
30857
31019
  } catch {
@@ -30890,7 +31052,7 @@ var init_private_document_files = __esm({
30890
31052
  });
30891
31053
 
30892
31054
  // apps/desktop/src/local-state/paths.ts
30893
- import path30 from "node:path";
31055
+ import path31 from "node:path";
30894
31056
  function applicationStateDirectory() {
30895
31057
  return desktopPlatform().directories.state;
30896
31058
  }
@@ -30898,37 +31060,37 @@ function cliCacheDirectory() {
30898
31060
  return desktopPlatform().directories.cliCache;
30899
31061
  }
30900
31062
  function managedThreadsStatePath() {
30901
- return path30.join(applicationStateDirectory(), "managed-threads-v1.json");
31063
+ return path31.join(applicationStateDirectory(), "managed-threads-v1.json");
30902
31064
  }
30903
31065
  function threadSettingsStatePath() {
30904
- return path30.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
31066
+ return path31.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
30905
31067
  }
30906
31068
  function threadListStatePath() {
30907
- return path30.join(applicationStateDirectory(), "thread-list-cache-v1.json");
31069
+ return path31.join(applicationStateDirectory(), "thread-list-cache-v1.json");
30908
31070
  }
30909
31071
  function daemonMetricsStatePath() {
30910
- return path30.join(applicationStateDirectory(), "daemon-metrics-v1.json");
31072
+ return path31.join(applicationStateDirectory(), "daemon-metrics-v1.json");
30911
31073
  }
30912
31074
  function desktopIdentityCandidatesStatePath() {
30913
- return path30.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
31075
+ return path31.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
30914
31076
  }
30915
31077
  function pendingRequestsCachePath() {
30916
- return path30.join(cliCacheDirectory(), "pending-requests-v1.json");
31078
+ return path31.join(cliCacheDirectory(), "pending-requests-v1.json");
30917
31079
  }
30918
31080
  function idempotencyCachePath() {
30919
- return path30.join(cliCacheDirectory(), "idempotency-v1.json");
31081
+ return path31.join(cliCacheDirectory(), "idempotency-v1.json");
30920
31082
  }
30921
31083
  function messageSubmissionsStatePath() {
30922
- return path30.join(applicationStateDirectory(), "message-submissions-v1.json");
31084
+ return path31.join(applicationStateDirectory(), "message-submissions-v1.json");
30923
31085
  }
30924
31086
  function deviceNameStatePath() {
30925
- return path30.join(applicationStateDirectory(), "device-name-v1.json");
31087
+ return path31.join(applicationStateDirectory(), "device-name-v1.json");
30926
31088
  }
30927
31089
  function threadReadReceiptsStatePath() {
30928
- return path30.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
31090
+ return path31.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
30929
31091
  }
30930
31092
  function asyncQuestionFactsStatePath() {
30931
- return path30.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
31093
+ return path31.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
30932
31094
  }
30933
31095
  var init_paths2 = __esm({
30934
31096
  "apps/desktop/src/local-state/paths.ts"() {
@@ -32534,7 +32696,7 @@ var init_thread_timeline_cache = __esm({
32534
32696
  });
32535
32697
 
32536
32698
  // apps/desktop/src/daemon/thread-state-store.ts
32537
- import path31 from "node:path";
32699
+ import path32 from "node:path";
32538
32700
  function projectRecency(entry) {
32539
32701
  return entry.threads.reduce(
32540
32702
  (latest, thread4) => Math.max(latest, thread4.recencyAt ?? thread4.updatedAt),
@@ -32643,8 +32805,8 @@ function normalizePathForCompare(value) {
32643
32805
  if (!value) {
32644
32806
  return "";
32645
32807
  }
32646
- const normalized = path31.normalize(value);
32647
- if (normalized.length > 1 && normalized.endsWith(path31.sep)) {
32808
+ const normalized = path32.normalize(value);
32809
+ if (normalized.length > 1 && normalized.endsWith(path32.sep)) {
32648
32810
  return normalized.slice(0, -1);
32649
32811
  }
32650
32812
  return normalized;
@@ -32669,7 +32831,7 @@ function isPathWithinRoot(cwd, root) {
32669
32831
  if (normalizedCwd === normalizedRoot) {
32670
32832
  return true;
32671
32833
  }
32672
- return normalizedCwd.startsWith(`${normalizedRoot}${path31.sep}`);
32834
+ return normalizedCwd.startsWith(`${normalizedRoot}${path32.sep}`);
32673
32835
  }
32674
32836
  function findLongestMatchingRoot(cwd, roots) {
32675
32837
  let matched = null;
@@ -32692,7 +32854,7 @@ function labelForRoot(root, labels) {
32692
32854
  };
32693
32855
  }
32694
32856
  return {
32695
- projectName: path31.basename(root) || root,
32857
+ projectName: path32.basename(root) || root,
32696
32858
  projectNameSource: "basename"
32697
32859
  };
32698
32860
  }
@@ -34200,10 +34362,10 @@ var init_bootstrap = __esm({
34200
34362
  });
34201
34363
 
34202
34364
  // apps/desktop/src/platform/private-cache-files.ts
34203
- import fs21 from "node:fs";
34204
- import path32 from "node:path";
34365
+ import fs22 from "node:fs";
34366
+ import path33 from "node:path";
34205
34367
  function serialize(file, operation) {
34206
- const key = process.platform === "win32" ? path32.resolve(file).toLowerCase() : path32.resolve(file);
34368
+ const key = process.platform === "win32" ? path33.resolve(file).toLowerCase() : path33.resolve(file);
34207
34369
  const next = (tails.get(key) ?? Promise.resolve()).then(operation);
34208
34370
  const tail = next.catch(() => {
34209
34371
  });
@@ -34218,23 +34380,23 @@ function trusted4(stat3, directory = false) {
34218
34380
  return uid !== void 0 && stat3.uid === BigInt(uid) && (directory ? stat3.isDirectory() && (stat3.mode & 0o777n) === 0o700n : stat3.isFile() && stat3.nlink === 1n && (stat3.mode & 0o777n) === 0o600n);
34219
34381
  }
34220
34382
  async function withMacLock(file, operation) {
34221
- const directory = path32.dirname(file);
34222
- const lock = path32.join(directory, `.${path32.basename(file)}.lock`);
34223
- fs21.mkdirSync(directory, { recursive: true, mode: 448 });
34224
- const parent = fs21.lstatSync(directory, { bigint: true });
34383
+ const directory = path33.dirname(file);
34384
+ const lock = path33.join(directory, `.${path33.basename(file)}.lock`);
34385
+ fs22.mkdirSync(directory, { recursive: true, mode: 448 });
34386
+ const parent = fs22.lstatSync(directory, { bigint: true });
34225
34387
  if (!trusted4(parent, true)) throw new PrivateDocumentFileError("unavailable");
34226
34388
  const deadline = Date.now() + LOCK_WAIT_MS;
34227
34389
  let fd;
34228
34390
  for (; ; ) {
34229
34391
  let initial = null;
34230
34392
  try {
34231
- initial = fs21.lstatSync(lock, { bigint: true });
34393
+ initial = fs22.lstatSync(lock, { bigint: true });
34232
34394
  } catch (error2) {
34233
34395
  if (error2.code !== "ENOENT") throw error2;
34234
34396
  }
34235
34397
  if (initial && !trusted4(initial)) throw new PrivateDocumentFileError("unavailable");
34236
34398
  try {
34237
- fd = fs21.openSync(lock, fs21.constants.O_RDWR | fs21.constants.O_CREAT | fs21.constants.O_NOFOLLOW | fs21.constants.O_NONBLOCK | 32, 384);
34399
+ fd = fs22.openSync(lock, fs22.constants.O_RDWR | fs22.constants.O_CREAT | fs22.constants.O_NOFOLLOW | fs22.constants.O_NONBLOCK | 32, 384);
34238
34400
  } catch (error2) {
34239
34401
  const code = error2.code;
34240
34402
  if (code !== "EAGAIN" && code !== "EWOULDBLOCK" || Date.now() >= deadline) throw error2;
@@ -34242,10 +34404,10 @@ async function withMacLock(file, operation) {
34242
34404
  continue;
34243
34405
  }
34244
34406
  try {
34245
- const opened = fs21.fstatSync(fd, { bigint: true });
34407
+ const opened = fs22.fstatSync(fd, { bigint: true });
34246
34408
  const verify = () => {
34247
- const current2 = fs21.lstatSync(lock, { bigint: true });
34248
- const currentParent = fs21.lstatSync(directory, { bigint: true });
34409
+ const current2 = fs22.lstatSync(lock, { bigint: true });
34410
+ const currentParent = fs22.lstatSync(directory, { bigint: true });
34249
34411
  if (!trusted4(opened) || !trusted4(current2) || !same6(opened, current2) || initial !== null && !same6(initial, opened) || !trusted4(currentParent, true) || !same6(parent, currentParent)) {
34250
34412
  throw new PrivateDocumentFileError("unavailable");
34251
34413
  }
@@ -34255,7 +34417,7 @@ async function withMacLock(file, operation) {
34255
34417
  verify();
34256
34418
  return value;
34257
34419
  } finally {
34258
- fs21.closeSync(fd);
34420
+ fs22.closeSync(fd);
34259
34421
  }
34260
34422
  }
34261
34423
  }
@@ -34286,7 +34448,7 @@ var init_private_cache_files = __esm({
34286
34448
  return serialize(file, async () => {
34287
34449
  checkLimit2(maxBytes);
34288
34450
  try {
34289
- fs21.lstatSync(file);
34451
+ fs22.lstatSync(file);
34290
34452
  } catch (error2) {
34291
34453
  if (error2.code === "ENOENT") return null;
34292
34454
  throw error2;
@@ -34299,7 +34461,7 @@ var init_private_cache_files = __esm({
34299
34461
  checkLimit2(maxBytes);
34300
34462
  if (process.platform === "win32") return windowsTransaction(file, maxBytes, transform);
34301
34463
  if (process.platform !== "darwin") throw new PrivateDocumentFileError("unavailable");
34302
- return withMacLock(path32.resolve(file), async (verify) => {
34464
+ return withMacLock(path33.resolve(file), async (verify) => {
34303
34465
  const result = transform(await privateStateFiles.read(file, maxBytes));
34304
34466
  verify();
34305
34467
  if (result.body !== void 0) await privateStateFiles.write(file, Buffer.from(result.body), maxBytes);
@@ -34583,7 +34745,7 @@ var init_pending_cache = __esm({
34583
34745
  });
34584
34746
 
34585
34747
  // apps/desktop/src/niuma/session-pending.ts
34586
- import fs22 from "node:fs";
34748
+ import fs23 from "node:fs";
34587
34749
  function objectRecord7(value) {
34588
34750
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
34589
34751
  }
@@ -34606,7 +34768,7 @@ function inferPendingRequestFromSession(threadId2, sessionPath, latestTurnId = n
34606
34768
  }
34607
34769
  let lines;
34608
34770
  try {
34609
- lines = fs22.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
34771
+ lines = fs23.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
34610
34772
  } catch {
34611
34773
  return null;
34612
34774
  }
@@ -35349,8 +35511,8 @@ var init_catalog = __esm({
35349
35511
  });
35350
35512
 
35351
35513
  // apps/desktop/src/direct-gateway/v5-binding-store.ts
35352
- import { randomUUID as randomUUID21, createHash as createHash12 } from "node:crypto";
35353
- import path33 from "node:path";
35514
+ import { randomUUID as randomUUID21, createHash as createHash13 } from "node:crypto";
35515
+ import path34 from "node:path";
35354
35516
  function bindingFileError() {
35355
35517
  return new Error("Desktop V5 Binding \u6587\u4EF6\u65E0\u6548");
35356
35518
  }
@@ -35484,7 +35646,7 @@ function parseResetMarker(value, desktopId) {
35484
35646
  }
35485
35647
  }
35486
35648
  function resolveDefaultDesktopV5BindingFilePath() {
35487
- return path33.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
35649
+ return path34.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
35488
35650
  }
35489
35651
  function pushDisplayName(name2) {
35490
35652
  let result = "";
@@ -35551,7 +35713,7 @@ var init_v5_binding_store = __esm({
35551
35713
  for (const wake of this.pushWaiters) wake();
35552
35714
  }
35553
35715
  constructor(options = {}) {
35554
- this.filePath = path33.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
35716
+ this.filePath = path34.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
35555
35717
  this.files = options.files ?? privateDocumentFiles;
35556
35718
  }
35557
35719
  async load(desktopId) {
@@ -35614,7 +35776,7 @@ var init_v5_binding_store = __esm({
35614
35776
  revision: this.presence.revision,
35615
35777
  grants: this.presence.grants.map((row) => ({
35616
35778
  grant_id: row.grant.grant_id,
35617
- token_sha256: createHash12("sha256").update(row.grant.token, "utf8").digest("base64url"),
35779
+ token_sha256: createHash13("sha256").update(row.grant.token, "utf8").digest("base64url"),
35618
35780
  binding_id: row.binding_id,
35619
35781
  generation: row.generation,
35620
35782
  expires_at: row.grant.expires_at
@@ -35801,7 +35963,7 @@ var init_v5_binding_store = __esm({
35801
35963
  await this.writeAtomicFile(this.resetMarkerPath(), serializeResetMarker(desktopId), bindingFileError);
35802
35964
  }
35803
35965
  resetMarkerPath() {
35804
- return path33.join(path33.dirname(this.filePath), RESET_MARKER_FILE_NAME);
35966
+ return path34.join(path34.dirname(this.filePath), RESET_MARKER_FILE_NAME);
35805
35967
  }
35806
35968
  async writeAtomicFile(targetPath, body, failure) {
35807
35969
  try {
@@ -35932,7 +36094,7 @@ var init_desktop_service = __esm({
35932
36094
  });
35933
36095
 
35934
36096
  // apps/desktop/src/presence/server-client.ts
35935
- import { createHash as createHash13, randomBytes as randomBytes5, randomUUID as randomUUID22 } from "node:crypto";
36097
+ import { createHash as createHash14, randomBytes as randomBytes5, randomUUID as randomUUID22 } from "node:crypto";
35936
36098
  var PresenceServerClient;
35937
36099
  var init_server_client2 = __esm({
35938
36100
  "apps/desktop/src/presence/server-client.ts"() {
@@ -35955,14 +36117,14 @@ var init_server_client2 = __esm({
35955
36117
  if (snapshot2.desktop_id !== this.identity.desktop_id || snapshot2.public_key !== encodeBase64Url(this.identity.identity_public_key)) throw new HttpApiError(200, 200004, "\u65E0\u6743\u9650\u8BBF\u95EE");
35956
36118
  const body = JSON.stringify(snapshot2), pathname = "/api/v1/presence/desktops/grants/sync";
35957
36119
  if (Buffer.byteLength(body) > 65536) throw new HttpApiError(200, 900608, "\u8BBE\u5907\u72B6\u6001\u67E5\u8BE2\u9891\u7387\u6216\u5BB9\u91CF\u8D85\u9650");
35958
- const key_id = createHash13("sha256").update(this.identity.identity_public_key).digest("base64url");
36120
+ const key_id = createHash14("sha256").update(this.identity.identity_public_key).digest("base64url");
35959
36121
  const operation_id = randomUUID22(), nonce = encodeBase64Url(randomBytes5(32)), timestamp = Math.floor(Date.now() / 1e3);
35960
36122
  const bytes3 = createPresenceSigningBytes({
35961
36123
  audience: this.origin,
35962
36124
  method: "POST",
35963
36125
  pathname,
35964
36126
  query: {},
35965
- body_sha256: createHash13("sha256").update(body).digest("base64url"),
36127
+ body_sha256: createHash14("sha256").update(body).digest("base64url"),
35966
36128
  key_id,
35967
36129
  operation_id,
35968
36130
  timestamp,
@@ -36111,7 +36273,7 @@ var init_binding_sync = __esm({
36111
36273
  });
36112
36274
 
36113
36275
  // apps/desktop/src/notifications/desktop-service.ts
36114
- import { createHash as createHash14 } from "node:crypto";
36276
+ import { createHash as createHash15 } from "node:crypto";
36115
36277
  var DesktopNotificationService;
36116
36278
  var init_desktop_service2 = __esm({
36117
36279
  "apps/desktop/src/notifications/desktop-service.ts"() {
@@ -36147,7 +36309,7 @@ var init_desktop_service2 = __esm({
36147
36309
  if (remaining <= 0) throw new NotificationTransportError("business_error", 200, 901002);
36148
36310
  const bounded = signal ? AbortSignal.any([signal, AbortSignal.timeout(Math.min(remaining, 12e3))]) : AbortSignal.timeout(Math.min(remaining, 12e3));
36149
36311
  const data = request2.data;
36150
- const event = parsePushEventInput({ desktop_id: this.identity.desktop_id, event_id: createHash14("sha256").update(JSON.stringify([data.event_type, data.thread_id, data.turn_id ?? data.request_id])).digest("base64url"), notification: request2.notification, data: { ...data, version: 1 }, trace: request2.trace });
36312
+ const event = parsePushEventInput({ desktop_id: this.identity.desktop_id, event_id: createHash15("sha256").update(JSON.stringify([data.event_type, data.thread_id, data.turn_id ?? data.request_id])).digest("base64url"), notification: request2.notification, data: { ...data, version: 1 }, trace: request2.trace });
36151
36313
  do {
36152
36314
  if (Date.now() >= (request2.trace?.deadline_at_ms ?? 0)) throw new NotificationTransportError("business_error", 200, 901002);
36153
36315
  if (bounded.aborted) throw new NotificationTransportError("business_error", 200, 900004);
@@ -37143,7 +37305,7 @@ var init_device_connection_stream2 = __esm({
37143
37305
  });
37144
37306
 
37145
37307
  // apps/desktop/src/remote-session/idempotency.ts
37146
- import { createHash as createHash15 } from "node:crypto";
37308
+ import { createHash as createHash16 } from "node:crypto";
37147
37309
  var REMOTE_SESSION_MAX_IDEMPOTENT_WRITES_PER_BINDING, REMOTE_SESSION_IDEMPOTENT_WRITE_TTL_MS, RemoteSessionIdempotency;
37148
37310
  var init_idempotency = __esm({
37149
37311
  "apps/desktop/src/remote-session/idempotency.ts"() {
@@ -37162,7 +37324,7 @@ var init_idempotency = __esm({
37162
37324
  }
37163
37325
  run(input) {
37164
37326
  const now = this.nowMs();
37165
- const fingerprint2 = createHash15("sha256").update(canonicalizeJson(input.payload)).digest("hex");
37327
+ const fingerprint2 = createHash16("sha256").update(canonicalizeJson(input.payload)).digest("hex");
37166
37328
  const cacheKey = input.scope_id === void 0 ? input.request_id : `${input.scope_id}\0${input.request_id}`;
37167
37329
  const bindingEntries = this.entries.get(input.binding_id) ?? /* @__PURE__ */ new Map();
37168
37330
  this.removeExpired(input.binding_id, bindingEntries, now);
@@ -41006,7 +41168,7 @@ var init_candidate_catalog2 = __esm({
41006
41168
  });
41007
41169
 
41008
41170
  // apps/desktop/src/direct-gateway/identity-store.ts
41009
- import path34 from "node:path";
41171
+ import path35 from "node:path";
41010
41172
  function copyIdentity(identity6) {
41011
41173
  return {
41012
41174
  desktop_id: identity6.desktop_id,
@@ -41061,7 +41223,7 @@ function deserializeIdentity(value) {
41061
41223
  }
41062
41224
  }
41063
41225
  function resolveDefaultDesktopIdentityFilePath() {
41064
- return path34.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
41226
+ return path35.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
41065
41227
  }
41066
41228
  var IDENTITY_KEY_BYTES2, DEFAULT_IDENTITY_FILE_NAME, MAX_IDENTITY_BYTES, FileDesktopIdentityStore;
41067
41229
  var init_identity_store = __esm({
@@ -41077,7 +41239,7 @@ var init_identity_store = __esm({
41077
41239
  filePath;
41078
41240
  files;
41079
41241
  constructor(options = {}) {
41080
- this.filePath = path34.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
41242
+ this.filePath = path35.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
41081
41243
  this.files = options.files ?? privateDocumentFiles;
41082
41244
  }
41083
41245
  async load() {
@@ -44431,17 +44593,6 @@ var init_settings = __esm({
44431
44593
  }
44432
44594
  });
44433
44595
 
44434
- // apps/desktop/src/assets.ts
44435
- function desktopAssetUrl(area, file) {
44436
- const release2 = true;
44437
- return new URL(release2 ? `./assets/${area}/${file}` : `./${area}/static/${file}`, import.meta.url);
44438
- }
44439
- var init_assets = __esm({
44440
- "apps/desktop/src/assets.ts"() {
44441
- "use strict";
44442
- }
44443
- });
44444
-
44445
44596
  // apps/desktop/src/pairing-web/auth.ts
44446
44597
  function authorizePairingRequest(request2, port, api) {
44447
44598
  const origin3 = `http://127.0.0.1:${port}`;
@@ -44560,7 +44711,7 @@ var init_routes3 = __esm({
44560
44711
 
44561
44712
  // apps/desktop/src/pairing-web/server.ts
44562
44713
  import http3 from "node:http";
44563
- import fs23 from "node:fs/promises";
44714
+ import fs24 from "node:fs/promises";
44564
44715
  var ASSETS, PairingWebServer;
44565
44716
  var init_server3 = __esm({
44566
44717
  "apps/desktop/src/pairing-web/server.ts"() {
@@ -44644,7 +44795,7 @@ var init_server3 = __esm({
44644
44795
  }
44645
44796
  const asset = ASSETS[raw];
44646
44797
  if (request2.method !== "GET" || !asset) throw new HttpApiError(404, 900005, "\u63A5\u53E3\u4E0D\u5B58\u5728");
44647
- const body = await fs23.readFile(desktopAssetUrl("pairing-web", asset[0]));
44798
+ const body = await fs24.readFile(desktopAssetUrl("pairing-web", asset[0]));
44648
44799
  response.writeHead(200, { "Content-Type": asset[1] });
44649
44800
  response.end(body);
44650
44801
  } catch (error2) {
@@ -46427,21 +46578,21 @@ var init_desktop_timeline_events = __esm({
46427
46578
  if (patch.op !== "add" && patch.op !== "replace") {
46428
46579
  continue;
46429
46580
  }
46430
- const path55 = array2(patch.path);
46431
- if (path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string") {
46581
+ const path56 = array2(patch.path);
46582
+ if (path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string") {
46432
46583
  const turnId = turnIdFromEntity(record14(patch.value));
46433
46584
  if (turnId) {
46434
- this.entityTurnIds.set(this.entityKey(threadId2, path55[3]), turnId);
46585
+ this.entityTurnIds.set(this.entityKey(threadId2, path56[3]), turnId);
46435
46586
  }
46436
46587
  continue;
46437
46588
  }
46438
- if (path55.length !== 6 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof path55[5] !== "number") {
46589
+ if (path56.length !== 6 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof path56[5] !== "number") {
46439
46590
  continue;
46440
46591
  }
46441
46592
  const occurredAt4 = Math.floor((this.options.now ?? Date.now)() / 1e3);
46442
46593
  const item = normalizeTimelineItem(patch.value, {
46443
46594
  threadId: threadId2,
46444
- turnId: this.entityTurnIds.get(this.entityKey(threadId2, path55[3])) ?? null,
46595
+ turnId: this.entityTurnIds.get(this.entityKey(threadId2, path56[3])) ?? null,
46445
46596
  source: "desktop_ipc",
46446
46597
  occurredAt: occurredAt4,
46447
46598
  resolveKnownLocalImage
@@ -46487,8 +46638,8 @@ function assignKnownUnreadFields(target, value) {
46487
46638
  target.unreadMessageCount = value.unreadMessageCount;
46488
46639
  }
46489
46640
  }
46490
- function isUnreadFieldPath(path55, field2) {
46491
- return path55.length === 1 && path55[0] === field2 || path55.length === 2 && path55[0] === "conversationState" && path55[1] === field2;
46641
+ function isUnreadFieldPath(path56, field2) {
46642
+ return path56.length === 1 && path56[0] === field2 || path56.length === 2 && path56[0] === "conversationState" && path56[1] === field2;
46492
46643
  }
46493
46644
  function hasUpdateFields(update) {
46494
46645
  return "hasUnreadTurn" in update || "unreadMessageCount" in update;
@@ -46514,19 +46665,19 @@ function extractDesktopUnreadUpdate(frame) {
46514
46665
  }
46515
46666
  for (const patchValue of change.patches) {
46516
46667
  const patch = record15(patchValue);
46517
- const path55 = Array.isArray(patch.path) ? patch.path : [];
46668
+ const path56 = Array.isArray(patch.path) ? patch.path : [];
46518
46669
  const op = patch.op;
46519
46670
  if (op !== "add" && op !== "replace" && op !== "remove") {
46520
46671
  continue;
46521
46672
  }
46522
- if (isUnreadFieldPath(path55, "hasUnreadTurn")) {
46673
+ if (isUnreadFieldPath(path56, "hasUnreadTurn")) {
46523
46674
  if (op === "remove") {
46524
46675
  update.hasUnreadTurn = null;
46525
46676
  } else if (typeof patch.value === "boolean") {
46526
46677
  update.hasUnreadTurn = patch.value;
46527
46678
  }
46528
46679
  }
46529
- if (isUnreadFieldPath(path55, "unreadMessageCount")) {
46680
+ if (isUnreadFieldPath(path56, "unreadMessageCount")) {
46530
46681
  if (op === "remove") {
46531
46682
  update.unreadMessageCount = null;
46532
46683
  } else if (isMessageCount(patch.value)) {
@@ -47223,15 +47374,15 @@ function revisionOf(value) {
47223
47374
  function occurredAt() {
47224
47375
  return Math.floor(Date.now() / 1e3);
47225
47376
  }
47226
- function itemTarget(path55) {
47227
- const index = path55[5];
47228
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof index !== "number" || !Number.isInteger(index) || index < 0) {
47377
+ function itemTarget(path56) {
47378
+ const index = path56[5];
47379
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof index !== "number" || !Number.isInteger(index) || index < 0) {
47229
47380
  return null;
47230
47381
  }
47231
- return { entityKey: path55[3], index, itemPathLength: 6 };
47382
+ return { entityKey: path56[3], index, itemPathLength: 6 };
47232
47383
  }
47233
- function entityTarget(path55) {
47234
- return path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string" ? path55[3] : null;
47384
+ function entityTarget(path56) {
47385
+ return path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string" ? path56[3] : null;
47235
47386
  }
47236
47387
  function phaseOf(status2) {
47237
47388
  if (status2 === "failed" || status2 === "error") {
@@ -47517,15 +47668,15 @@ var init_desktop_activity_events = __esm({
47517
47668
  if (patch.op !== "add" && patch.op !== "replace") {
47518
47669
  continue;
47519
47670
  }
47520
- const path55 = array3(patch.path);
47521
- const targetItem = itemTarget(path55);
47671
+ const path56 = array3(patch.path);
47672
+ const targetItem = itemTarget(path56);
47522
47673
  if (targetItem) {
47523
- signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path55, patch.value, patch.op));
47674
+ signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path56, patch.value, patch.op));
47524
47675
  continue;
47525
47676
  }
47526
- const targetEntity = entityTarget(path55);
47677
+ const targetEntity = entityTarget(path56);
47527
47678
  if (targetEntity) {
47528
- signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path55, patch.value));
47679
+ signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path56, patch.value));
47529
47680
  }
47530
47681
  }
47531
47682
  return signals;
@@ -47599,12 +47750,12 @@ var init_desktop_activity_events = __esm({
47599
47750
  occurredAt: occurredAt()
47600
47751
  }];
47601
47752
  }
47602
- consumeItemPatch(threadId2, state, target, path55, value, op) {
47753
+ consumeItemPatch(threadId2, state, target, path56, value, op) {
47603
47754
  const entity = state.entities.get(target.entityKey);
47604
47755
  if (!entity || state.currentActiveEntityKey !== target.entityKey || state.currentActiveTurnId !== entity.turnId) {
47605
47756
  return [];
47606
47757
  }
47607
- if (path55.length === target.itemPathLength) {
47758
+ if (path56.length === target.itemPathLength) {
47608
47759
  return this.prependLiveTurnStart(threadId2, entity, this.consumeWholeItem(
47609
47760
  threadId2,
47610
47761
  entity,
@@ -47614,13 +47765,13 @@ var init_desktop_activity_events = __esm({
47614
47765
  ));
47615
47766
  }
47616
47767
  const existing = entity.items.get(target.index);
47617
- if (!existing || path55.length < target.itemPathLength + 1) {
47768
+ if (!existing || path56.length < target.itemPathLength + 1) {
47618
47769
  return [];
47619
47770
  }
47620
- const field2 = path55[target.itemPathLength];
47771
+ const field2 = path56[target.itemPathLength];
47621
47772
  if (existing.type === "reasoning" && field2 === "summary") {
47622
47773
  const summary = structuredClone(existing.summary ?? []);
47623
- const suffix = path55.slice(target.itemPathLength + 1);
47774
+ const suffix = path56.slice(target.itemPathLength + 1);
47624
47775
  if (suffix.length === 0) {
47625
47776
  existing.summary = structuredClone(Array.isArray(value) ? value : [value]);
47626
47777
  } else {
@@ -47720,9 +47871,9 @@ var init_desktop_activity_events = __esm({
47720
47871
  });
47721
47872
  return [this.activitySignal(threadId2, entity.turnId, itemId, mapping)];
47722
47873
  }
47723
- consumeEntityPatch(threadId2, state, entityKey, path55, value) {
47724
- const wholeEntity = path55.length === 4;
47725
- const statusField = path55.length === 5 && path55[4] === "status";
47874
+ consumeEntityPatch(threadId2, state, entityKey, path56, value) {
47875
+ const wholeEntity = path56.length === 4;
47876
+ const statusField = path56.length === 5 && path56[4] === "status";
47726
47877
  if (!wholeEntity && !statusField) {
47727
47878
  return [];
47728
47879
  }
@@ -47902,20 +48053,20 @@ var init_desktop_error_events = __esm({
47902
48053
  if (patch.op !== "add" && patch.op !== "replace") {
47903
48054
  continue;
47904
48055
  }
47905
- const path55 = array4(patch.path);
47906
- if (path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string") {
48056
+ const path56 = array4(patch.path);
48057
+ if (path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string") {
47907
48058
  const entity = record17(patch.value);
47908
48059
  const turnId2 = turnIdFromEntity2(entity);
47909
48060
  if (turnId2) {
47910
- this.entityTurnIds.set(this.entityKey(threadId2, path55[3]), turnId2);
48061
+ this.entityTurnIds.set(this.entityKey(threadId2, path56[3]), turnId2);
47911
48062
  events.push(...this.errorEvents(threadId2, array4(entity.items), turnId2));
47912
48063
  }
47913
48064
  continue;
47914
48065
  }
47915
- if (path55.length !== 6 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string" || path55[4] !== "items" || typeof path55[5] !== "number") {
48066
+ if (path56.length !== 6 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string" || path56[4] !== "items" || typeof path56[5] !== "number") {
47916
48067
  continue;
47917
48068
  }
47918
- const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path55[3]));
48069
+ const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path56[3]));
47919
48070
  if (!turnId) {
47920
48071
  continue;
47921
48072
  }
@@ -48008,13 +48159,13 @@ function visibleMessage(value, resolveKnownLocalImage) {
48008
48159
  function occurredAt2() {
48009
48160
  return Math.floor(Date.now() / 1e3);
48010
48161
  }
48011
- function itemPath(path55) {
48012
- const index = path55.lastIndexOf("items");
48013
- const itemIndex = path55[index + 1];
48014
- return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 && path55.length >= index + 2 ? path55.slice(0, index + 2) : null;
48162
+ function itemPath(path56) {
48163
+ const index = path56.lastIndexOf("items");
48164
+ const itemIndex = path56[index + 1];
48165
+ return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 && path56.length >= index + 2 ? path56.slice(0, index + 2) : null;
48015
48166
  }
48016
- function stateKey(threadId2, path55) {
48017
- return `${threadId2}:${JSON.stringify(path55)}`;
48167
+ function stateKey(threadId2, path56) {
48168
+ return `${threadId2}:${JSON.stringify(path56)}`;
48018
48169
  }
48019
48170
  function completedKey(threadId2, itemId) {
48020
48171
  return `${threadId2}:${itemId}`;
@@ -48072,35 +48223,35 @@ var init_desktop_stream_events = __esm({
48072
48223
  if (op !== "add" && op !== "replace" && op !== "remove") {
48073
48224
  continue;
48074
48225
  }
48075
- const path55 = array5(patch.path);
48076
- if (path55[0] === "turnHistory" && (path55.length === 1 || path55[1] === "history" && (path55.length === 2 || path55[2] === "entitiesByKey" && path55.length === 3))) {
48226
+ const path56 = array5(patch.path);
48227
+ if (path56[0] === "turnHistory" && (path56.length === 1 || path56[1] === "history" && (path56.length === 2 || path56[2] === "entitiesByKey" && path56.length === 3))) {
48077
48228
  this.resetThread(threadId2);
48078
48229
  continue;
48079
48230
  }
48080
- if (path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey") {
48081
- const values = path55.length === 4 ? record18(patch.value).items : path55.length === 5 && path55[4] === "items" ? patch.value : void 0;
48082
- if (path55.length === 4 || path55.length === 5 && path55[4] === "items") {
48083
- const arrayPath = path55.slice(0, 4).concat("items");
48231
+ if (path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey") {
48232
+ const values = path56.length === 4 ? record18(patch.value).items : path56.length === 5 && path56[4] === "items" ? patch.value : void 0;
48233
+ if (path56.length === 4 || path56.length === 5 && path56[4] === "items") {
48234
+ const arrayPath = path56.slice(0, 4).concat("items");
48084
48235
  this.replaceArrayStates(threadId2, arrayPath, array5(values), resolveKnownLocalImage);
48085
48236
  continue;
48086
48237
  }
48087
48238
  }
48088
- const rawIndex = path55.lastIndexOf("items") + 1;
48089
- if (op === "add" && path55[rawIndex] === "-" && path55.length === rawIndex + 1) {
48090
- const length = this.arrayLengths.get(stateKey(threadId2, path55.slice(0, rawIndex)));
48239
+ const rawIndex = path56.lastIndexOf("items") + 1;
48240
+ if (op === "add" && path56[rawIndex] === "-" && path56.length === rawIndex + 1) {
48241
+ const length = this.arrayLengths.get(stateKey(threadId2, path56.slice(0, rawIndex)));
48091
48242
  if (length === void 0) continue;
48092
- path55[rawIndex] = length;
48243
+ path56[rawIndex] = length;
48093
48244
  }
48094
- const targetItemPath = itemPath(path55);
48245
+ const targetItemPath = itemPath(path56);
48095
48246
  if (!targetItemPath) {
48096
48247
  continue;
48097
48248
  }
48098
48249
  const key = stateKey(threadId2, targetItemPath);
48099
- if (path55.length > targetItemPath.length && ["id", "type"].includes(String(path55[targetItemPath.length]))) {
48250
+ if (path56.length > targetItemPath.length && ["id", "type"].includes(String(path56[targetItemPath.length]))) {
48100
48251
  this.states.delete(key);
48101
48252
  continue;
48102
48253
  }
48103
- if (path55.length === targetItemPath.length) {
48254
+ if (path56.length === targetItemPath.length) {
48104
48255
  const arrayPath = targetItemPath.slice(0, -1);
48105
48256
  const index = targetItemPath.at(-1);
48106
48257
  if (op === "add" || op === "remove") this.shiftArrayStates(threadId2, arrayPath, index, op);
@@ -48115,7 +48266,7 @@ var init_desktop_stream_events = __esm({
48115
48266
  ));
48116
48267
  continue;
48117
48268
  }
48118
- if (op === "replace" && path55.length === targetItemPath.length + 1 && path55.at(-1) === "text") {
48269
+ if (op === "replace" && path56.length === targetItemPath.length + 1 && path56.at(-1) === "text") {
48119
48270
  events.push(...this.consumeTextPatch(threadId2, key, patch.value, revision4));
48120
48271
  }
48121
48272
  }
@@ -48127,9 +48278,9 @@ var init_desktop_stream_events = __esm({
48127
48278
  const prefix = JSON.stringify(arrayPath);
48128
48279
  for (const [key2, state] of this.states) {
48129
48280
  if (state.threadId !== threadId2) continue;
48130
- const path55 = JSON.parse(key2.slice(threadId2.length + 1));
48131
- const at = path55.at(-1);
48132
- if (JSON.stringify(path55.slice(0, -1)) !== prefix || typeof at !== "number" || at < index) continue;
48281
+ const path56 = JSON.parse(key2.slice(threadId2.length + 1));
48282
+ const at = path56.at(-1);
48283
+ if (JSON.stringify(path56.slice(0, -1)) !== prefix || typeof at !== "number" || at < index) continue;
48133
48284
  this.states.delete(key2);
48134
48285
  if (op === "remove" && at === index) continue;
48135
48286
  moved.push([stateKey(threadId2, [...arrayPath, at + (op === "add" ? 1 : -1)]), state]);
@@ -48140,20 +48291,20 @@ var init_desktop_stream_events = __esm({
48140
48291
  if (length !== void 0) this.arrayLengths.set(key, Math.max(0, length + (op === "add" ? 1 : -1)));
48141
48292
  }
48142
48293
  /** 完整数组只重播种本实体的路径;其他轮的正文和按原生身份记录的完成事实不变。 */
48143
- replaceArrayStates(threadId2, path55, values, resolveKnownLocalImage) {
48144
- const prefix = JSON.stringify(path55);
48294
+ replaceArrayStates(threadId2, path56, values, resolveKnownLocalImage) {
48295
+ const prefix = JSON.stringify(path56);
48145
48296
  for (const [key, state] of this.states) {
48146
48297
  if (state.threadId !== threadId2) continue;
48147
48298
  const itemPath2 = JSON.parse(key.slice(threadId2.length + 1));
48148
48299
  if (JSON.stringify(itemPath2.slice(0, -1)) === prefix) this.states.delete(key);
48149
48300
  }
48150
- this.arrayLengths.set(stateKey(threadId2, path55), values.length);
48301
+ this.arrayLengths.set(stateKey(threadId2, path56), values.length);
48151
48302
  values.forEach((value, index) => {
48152
48303
  const message = visibleMessage(value, resolveKnownLocalImage);
48153
48304
  if (!message) return;
48154
48305
  if (message.role === "user") this.completed.add(completedKey(threadId2, message.itemId));
48155
48306
  else if (!this.completed.has(completedKey(threadId2, message.itemId))) {
48156
- this.states.set(stateKey(threadId2, [...path55, index]), { threadId: threadId2, ...message, lastText: message.text });
48307
+ this.states.set(stateKey(threadId2, [...path56, index]), { threadId: threadId2, ...message, lastText: message.text });
48157
48308
  }
48158
48309
  });
48159
48310
  }
@@ -48452,7 +48603,7 @@ var init_method_codecs = __esm({
48452
48603
  });
48453
48604
 
48454
48605
  // apps/desktop/src/desktop-ipc/profiles.ts
48455
- import { createHash as createHash16 } from "node:crypto";
48606
+ import { createHash as createHash17 } from "node:crypto";
48456
48607
  function method(name2, direction, version2, codec = {}, receiveOnly = false) {
48457
48608
  return {
48458
48609
  method: name2,
@@ -48502,7 +48653,7 @@ var init_profiles = __esm({
48502
48653
  id: "current-methods-2026-10-20",
48503
48654
  version: "1.0",
48504
48655
  // codec 修订随方案发布固定,不能从函数源码生成不稳定指纹。
48505
- fingerprint: createHash16("sha256").update(JSON.stringify({ codecRevision: "1.0", methods: definitions.map((d) => [d.method, d.direction, d.sendVersion, d.acceptedVersions]) })).digest("hex"),
48656
+ fingerprint: createHash17("sha256").update(JSON.stringify({ codecRevision: "1.0", methods: definitions.map((d) => [d.method, d.direction, d.sendVersion, d.acceptedVersions]) })).digest("hex"),
48506
48657
  methods: new Map(definitions.map((value) => [value.method, value])),
48507
48658
  // 当前只有安装包静态核对与回归;实际 Desktop 业务验收完成前不登记 verifiedDesktop。
48508
48659
  verifiedDesktop: []
@@ -49278,8 +49429,8 @@ var init_socket_client = __esm({
49278
49429
  this.diagnosticProfile = diagnosticProfile;
49279
49430
  this.socketPaths = socketPath ? [socketPath] : defaultSocketPaths;
49280
49431
  const reader = new DesktopRuntimeVersionReader();
49281
- this.runtimeVersion = new RuntimeVersionCache(async (path55, signal) => {
49282
- const value = versionReader ? await versionReader(path55, signal) : await reader.read(path55, signal);
49432
+ this.runtimeVersion = new RuntimeVersionCache(async (path56, signal) => {
49433
+ const value = versionReader ? await versionReader(path56, signal) : await reader.read(path56, signal);
49283
49434
  return typeof value === "string" ? { version: value, build: null } : value;
49284
49435
  });
49285
49436
  }
@@ -51565,8 +51716,8 @@ var init_desktop_read_refresh_queue = __esm({
51565
51716
  // apps/desktop/src/daemon/desktop-read-state-file.ts
51566
51717
  import { watch } from "node:fs";
51567
51718
  import { open as open4, stat as statPath } from "node:fs/promises";
51568
- import { createHash as createHash17 } from "node:crypto";
51569
- import path35 from "node:path";
51719
+ import { createHash as createHash18 } from "node:crypto";
51720
+ import path36 from "node:path";
51570
51721
  function record20(value) {
51571
51722
  return !!value && typeof value === "object" && !Array.isArray(value);
51572
51723
  }
@@ -51608,7 +51759,7 @@ var LOCAL_STDIO_HOST, MAX_BYTES2, DesktopReadStateFile;
51608
51759
  var init_desktop_read_state_file = __esm({
51609
51760
  "apps/desktop/src/daemon/desktop-read-state-file.ts"() {
51610
51761
  "use strict";
51611
- LOCAL_STDIO_HOST = `local:${createHash17("sha256").update(JSON.stringify(["local", "local", null])).digest("hex")}`;
51762
+ LOCAL_STDIO_HOST = `local:${createHash18("sha256").update(JSON.stringify(["local", "local", null])).digest("hex")}`;
51612
51763
  MAX_BYTES2 = 16 * 1024 * 1024;
51613
51764
  DesktopReadStateFile = class {
51614
51765
  constructor(home, changed2, options = {}) {
@@ -51710,7 +51861,7 @@ var init_desktop_read_state_file = __esm({
51710
51861
  async readOnce() {
51711
51862
  this.checks++;
51712
51863
  try {
51713
- const filePath = path35.join(this.home, ".codex-global-state.json");
51864
+ const filePath = path36.join(this.home, ".codex-global-state.json");
51714
51865
  const file = await open4(filePath, "r");
51715
51866
  let raw, signature;
51716
51867
  try {
@@ -53556,9 +53707,9 @@ var init_protocol = __esm({
53556
53707
 
53557
53708
  // apps/desktop/src/daemon/server.ts
53558
53709
  import { randomUUID as randomUUID32 } from "node:crypto";
53559
- import fs24 from "node:fs";
53710
+ import fs25 from "node:fs";
53560
53711
  import net4 from "node:net";
53561
- import path36 from "node:path";
53712
+ import path37 from "node:path";
53562
53713
  import { StringDecoder as StringDecoder2 } from "node:string_decoder";
53563
53714
  function createStatusFile(instanceId, mode, socketPath) {
53564
53715
  return {
@@ -53693,10 +53844,10 @@ var init_server4 = __esm({
53693
53844
  DaemonServer = class {
53694
53845
  constructor(options) {
53695
53846
  this.options = options;
53696
- this.socketPath = path36.resolve(options.socketPath ?? daemonSocketPath());
53697
- this.statusPath = path36.resolve(options.statusPath ?? daemonStatusPath());
53847
+ this.socketPath = path37.resolve(options.socketPath ?? daemonSocketPath());
53848
+ this.statusPath = path37.resolve(options.statusPath ?? daemonStatusPath());
53698
53849
  this.usesDefaultRuntimeDir = options.socketPath === void 0 || options.statusPath === void 0;
53699
- this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path36.join(path36.dirname(this.socketPath), ".daemon-lifecycle.lock");
53850
+ this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path37.join(path37.dirname(this.socketPath), ".daemon-lifecycle.lock");
53700
53851
  this.transport = createDaemonTransport(this.socketPath);
53701
53852
  this.listenSocketPath = this.transport.listenPath;
53702
53853
  }
@@ -53808,22 +53959,22 @@ var init_server4 = __esm({
53808
53959
  const temporaryPath = `${this.statusPath}.${this.instanceId}.tmp`;
53809
53960
  let descriptor = null;
53810
53961
  try {
53811
- descriptor = fs24.openSync(temporaryPath, "wx", 384);
53812
- fs24.writeFileSync(
53962
+ descriptor = fs25.openSync(temporaryPath, "wx", 384);
53963
+ fs25.writeFileSync(
53813
53964
  descriptor,
53814
53965
  `${JSON.stringify(createStatusFile(this.instanceId, this.options.mode ?? "foreground", this.socketPath), null, 2)}
53815
53966
  `,
53816
53967
  "utf8"
53817
53968
  );
53818
- fs24.closeSync(descriptor);
53969
+ fs25.closeSync(descriptor);
53819
53970
  descriptor = null;
53820
- fs24.chmodSync(temporaryPath, 384);
53821
- fs24.renameSync(temporaryPath, this.statusPath);
53971
+ fs25.chmodSync(temporaryPath, 384);
53972
+ fs25.renameSync(temporaryPath, this.statusPath);
53822
53973
  } catch (error2) {
53823
53974
  if (descriptor !== null) {
53824
- fs24.closeSync(descriptor);
53975
+ fs25.closeSync(descriptor);
53825
53976
  }
53826
- fs24.rmSync(temporaryPath, { force: true });
53977
+ fs25.rmSync(temporaryPath, { force: true });
53827
53978
  throw error2;
53828
53979
  }
53829
53980
  }
@@ -53848,9 +53999,9 @@ var init_server4 = __esm({
53848
53999
  this.transport.cleanup(this.socketPath);
53849
54000
  if (this.statusOwned) {
53850
54001
  try {
53851
- const status2 = JSON.parse(fs24.readFileSync(this.statusPath, "utf8"));
54002
+ const status2 = JSON.parse(fs25.readFileSync(this.statusPath, "utf8"));
53852
54003
  if (status2.instanceId === this.instanceId) {
53853
- fs24.rmSync(this.statusPath, { force: true });
54004
+ fs25.rmSync(this.statusPath, { force: true });
53854
54005
  }
53855
54006
  } catch {
53856
54007
  }
@@ -54444,7 +54595,7 @@ var init_push_trigger_projection = __esm({
54444
54595
  });
54445
54596
 
54446
54597
  // apps/desktop/src/daemon/turn-push-audit.ts
54447
- import path37 from "node:path";
54598
+ import path38 from "node:path";
54448
54599
  function isRecord6(value) {
54449
54600
  return typeof value === "object" && value !== null && !Array.isArray(value);
54450
54601
  }
@@ -54491,7 +54642,7 @@ function isCoverageReason(value) {
54491
54642
  return value === "realtime_gap" || value === "historical_gap" || value === "source_unavailable" || value === "reader_limit" || value === "write_failed";
54492
54643
  }
54493
54644
  function auditDirectory(runtimeDir) {
54494
- return path37.join(runtimeDir, AUDIT_DIRECTORY);
54645
+ return path38.join(runtimeDir, AUDIT_DIRECTORY);
54495
54646
  }
54496
54647
  function dateFileName(timestampMs) {
54497
54648
  if (!isFiniteTimestamp(timestampMs)) return null;
@@ -54594,7 +54745,7 @@ function appendRecord(runtimeDir, timestampMs, record26, files) {
54594
54745
  files.checkDirectory(runtimeDir);
54595
54746
  const directory = auditDirectory(runtimeDir);
54596
54747
  files.ensureDirectory(directory);
54597
- files.append(path37.join(directory, fileName), `${JSON.stringify(record26)}
54748
+ files.append(path38.join(directory, fileName), `${JSON.stringify(record26)}
54598
54749
  `, MAX_FILE_BYTES);
54599
54750
  return true;
54600
54751
  } catch {
@@ -56091,7 +56242,7 @@ var init_events2 = __esm({
56091
56242
  });
56092
56243
 
56093
56244
  // apps/desktop/src/niuma/session-history-items.ts
56094
- import { createHash as createHash18 } from "node:crypto";
56245
+ import { createHash as createHash19 } from "node:crypto";
56095
56246
  function copyTimelineStatus(raw, item) {
56096
56247
  if (!Object.hasOwn(raw, "status")) return;
56097
56248
  if (raw.status === null || raw.status === void 0) return;
@@ -56158,11 +56309,11 @@ function completedHistoryItem(value) {
56158
56309
  break;
56159
56310
  case "fileChange":
56160
56311
  copy(raw, item, { status: "status" });
56161
- item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([path55, value2]) => {
56312
+ item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([path56, value2]) => {
56162
56313
  const change = record5(value2);
56163
56314
  const kind = { type: change.type };
56164
56315
  if (change.type === "update") kind.movePath = change.move_path ?? null;
56165
- return { path: path55, kind, diff: change.unified_diff ?? change.content ?? "" };
56316
+ return { path: path56, kind, diff: change.unified_diff ?? change.content ?? "" };
56166
56317
  });
56167
56318
  break;
56168
56319
  case "collabAgentToolCall":
@@ -56210,7 +56361,7 @@ function responseHistoryItem(value, location) {
56210
56361
  const type = raw.type;
56211
56362
  if (type === "message") {
56212
56363
  if (raw.role !== "user" && raw.role !== "assistant") return null;
56213
- const id5 = nonempty(raw.id) ?? `session-${createHash18("sha256").update(location).digest("hex")}`;
56364
+ const id5 = nonempty(raw.id) ?? `session-${createHash19("sha256").update(location).digest("hex")}`;
56214
56365
  return { ...completedHistoryItem({ ...raw, id: id5, type: raw.role === "user" ? "UserMessage" : "AgentMessage" }), historySource: "response_item" };
56215
56366
  }
56216
56367
  if (type === "web_search_call") {
@@ -56299,8 +56450,8 @@ function markdownTargets(text11) {
56299
56450
  function markdownReferences(text11, paths = localResourcePaths) {
56300
56451
  const { tree, references } = markdownTargets(text11);
56301
56452
  return { tree, references: references.flatMap((ref) => {
56302
- const path55 = paths.parseLink(ref.url);
56303
- return path55 === null ? [] : [{ ...ref, path: path55 }];
56453
+ const path56 = paths.parseLink(ref.url);
56454
+ return path56 === null ? [] : [{ ...ref, path: path56 }];
56304
56455
  }) };
56305
56456
  }
56306
56457
  function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths) {
@@ -56331,8 +56482,8 @@ function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths)
56331
56482
  if (item.entitiesByKey && typeof item.entitiesByKey === "object") pending.push(...Object.values(item.entitiesByKey));
56332
56483
  if (Array.isArray(item.patches)) {
56333
56484
  for (const patch of item.patches) {
56334
- const path55 = patch?.path;
56335
- if (Array.isArray(path55) && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && (path55.length === 4 || path55[4] === "items")) pending.push(patch.value);
56485
+ const path56 = patch?.path;
56486
+ if (Array.isArray(path56) && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && (path56.length === 4 || path56[4] === "items")) pending.push(patch.value);
56336
56487
  }
56337
56488
  }
56338
56489
  }
@@ -56423,7 +56574,7 @@ var init_thread_view_images = __esm({
56423
56574
  });
56424
56575
 
56425
56576
  // apps/desktop/src/niuma/session-history-images.ts
56426
- import { createHash as createHash19 } from "node:crypto";
56577
+ import { createHash as createHash20 } from "node:crypto";
56427
56578
  import { stat as stat2 } from "node:fs/promises";
56428
56579
  async function historyFingerprint(snapshots2, signal) {
56429
56580
  signal?.throwIfAborted();
@@ -56519,7 +56670,7 @@ async function readHistoryImageValue(locator, signal, filePath) {
56519
56670
  }
56520
56671
  await validateSessionFile(snapshot2);
56521
56672
  const bytes3 = await readBytes(snapshot2.path, offset, length);
56522
- if (createHash19("sha256").update(bytes3).digest("hex") !== locator.recordSha256) {
56673
+ if (createHash20("sha256").update(bytes3).digest("hex") !== locator.recordSha256) {
56523
56674
  throw new SessionHistoryError("SNAPSHOT_CHANGED", "\u56FE\u7247\u5386\u53F2\u8BB0\u5F55\u5DF2\u53D8\u5316");
56524
56675
  }
56525
56676
  let value = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes3));
@@ -56533,11 +56684,11 @@ async function readHistoryImageValue(locator, signal, filePath) {
56533
56684
  signal?.throwIfAborted();
56534
56685
  return value;
56535
56686
  }
56536
- async function assertHistoryImageFileReference(locator, path55, signal) {
56537
- const value = await readHistoryImageValue(locator, signal, path55);
56687
+ async function assertHistoryImageFileReference(locator, path56, signal) {
56688
+ const value = await readHistoryImageValue(locator, signal, path56);
56538
56689
  const last = locator.valuePath.at(-1);
56539
56690
  const text11 = typeof value === "string" ? value : Array.isArray(value) ? value.map((part) => typeof record5(part).text === "string" ? record5(part).text : "").join("") : null;
56540
- if (text11 === null || !(last === "path" ? text11 === path55 : assistantPaths(text11).includes(path55))) {
56691
+ if (text11 === null || !(last === "path" ? text11 === path56 : assistantPaths(text11).includes(path56))) {
56541
56692
  throw new SessionHistoryError("INVALID_RECORD", "\u56FE\u7247\u6587\u4EF6\u4E0E\u5386\u53F2\u5F15\u7528\u4E0D\u7B26");
56542
56693
  }
56543
56694
  }
@@ -56596,7 +56747,7 @@ var init_session_history_images = __esm({
56596
56747
  const found = [];
56597
56748
  if (formal && item.type === "agentMessage") {
56598
56749
  const references = [];
56599
- for (const path55 of assistantPaths(String(item.text ?? ""))) {
56750
+ for (const path56 of assistantPaths(String(item.text ?? ""))) {
56600
56751
  references.push({ locator: {
56601
56752
  threadId: threadId2,
56602
56753
  turnId: "",
@@ -56609,7 +56760,7 @@ var init_session_history_images = __esm({
56609
56760
  recordLength: range.length,
56610
56761
  recordSha256: range.sha256,
56611
56762
  valuePath: ["payload", "item", raw.content !== void 0 ? "content" : "text"]
56612
- }, nativeMessageId: null, path: path55, filePath: path55, callId: null });
56763
+ }, nativeMessageId: null, path: path56, filePath: path56, callId: null });
56613
56764
  }
56614
56765
  this.markdownEvidence.set(item, references);
56615
56766
  }
@@ -56638,7 +56789,7 @@ var init_session_history_images = __esm({
56638
56789
  }
56639
56790
  if (!imageUrl(source2)) return;
56640
56791
  const previous = index > 0 ? record5(parts[index - 1]).text : null;
56641
- const path55 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
56792
+ const path56 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
56642
56793
  found.push({
56643
56794
  locator: {
56644
56795
  threadId: threadId2,
@@ -56658,7 +56809,7 @@ var init_session_history_images = __esm({
56658
56809
  ]
56659
56810
  },
56660
56811
  nativeMessageId: typeof item.clientId === "string" ? item.clientId : null,
56661
- path: path55,
56812
+ path: path56,
56662
56813
  callId: null
56663
56814
  });
56664
56815
  if (mapped[index]) mapped[index] = { type: "historyImage", resourceKey: null };
@@ -56720,11 +56871,11 @@ var init_session_history_images = __esm({
56720
56871
  }
56721
56872
  if (item.type === "agentMessage" && typeof item.text === "string") {
56722
56873
  const references = [];
56723
- for (const [referenceIndex, path55] of assistantPaths(item.text).entries()) {
56874
+ for (const [referenceIndex, path56] of assistantPaths(item.text).entries()) {
56724
56875
  const calls = fallback.filter((candidate) => {
56725
56876
  if (candidate.type !== "functionCall" || !["view_image", "functions.view_image"].includes(String(candidate.name))) return false;
56726
56877
  try {
56727
- return record5(JSON.parse(String(candidate.arguments))).path === path55;
56878
+ return record5(JSON.parse(String(candidate.arguments))).path === path56;
56728
56879
  } catch {
56729
56880
  return false;
56730
56881
  }
@@ -56732,9 +56883,9 @@ var init_session_history_images = __esm({
56732
56883
  const outputs = fallback.filter((candidate) => candidate.type === "functionCallOutput" && calls.some((call) => candidate.id === call.id));
56733
56884
  const candidates = outputs.flatMap((output) => this.evidence.get(output) ?? []);
56734
56885
  if (candidates.length && (calls.length !== 1 || candidates.length !== 1)) continue;
56735
- const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path55);
56886
+ const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path56);
56736
56887
  if (!original) continue;
56737
- const evidence = { ...original, path: path55, referenceKind: "markdown", locator: {
56888
+ const evidence = { ...original, path: path56, referenceKind: "markdown", locator: {
56738
56889
  ...original.locator,
56739
56890
  turnId,
56740
56891
  itemId: item.id,
@@ -56742,7 +56893,7 @@ var init_session_history_images = __esm({
56742
56893
  } };
56743
56894
  try {
56744
56895
  const resourceKey = await callback(evidence);
56745
- if (resourceKey) references.push({ path: path55, resourceKey });
56896
+ if (resourceKey) references.push({ path: path56, resourceKey });
56746
56897
  } catch {
56747
56898
  }
56748
56899
  }
@@ -56761,7 +56912,7 @@ __export(session_history_reader_exports, {
56761
56912
  SessionHistoryReader: () => SessionHistoryReader
56762
56913
  });
56763
56914
  import { randomUUID as randomUUID33 } from "node:crypto";
56764
- import fs25 from "node:fs/promises";
56915
+ import fs26 from "node:fs/promises";
56765
56916
  function resolveHistoryPath(resolvePath, signal) {
56766
56917
  abortIfRequested2(signal);
56767
56918
  if (!signal) return resolvePath();
@@ -57029,7 +57180,7 @@ var init_session_history_reader = __esm({
57029
57180
  try {
57030
57181
  const resolved3 = await resolveHistoryPath(() => this.options.resolveSessionPath(snapshot2.threadId), signal);
57031
57182
  abortIfRequested2(signal);
57032
- const current2 = await fs25.realpath(resolved3);
57183
+ const current2 = await fs26.realpath(resolved3);
57033
57184
  abortIfRequested2(signal);
57034
57185
  if (current2 !== snapshot2.files[0].path) throw new Error("current path changed");
57035
57186
  } catch (error2) {
@@ -58317,7 +58468,7 @@ var init_thread_view_reducer = __esm({
58317
58468
  });
58318
58469
 
58319
58470
  // apps/desktop/src/daemon/thread-view-store.ts
58320
- import { createHash as createHash20, randomUUID as randomUUID34 } from "node:crypto";
58471
+ import { createHash as createHash21, randomUUID as randomUUID34 } from "node:crypto";
58321
58472
  import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
58322
58473
  function clone5(value) {
58323
58474
  return structuredClone(value);
@@ -59187,7 +59338,7 @@ var init_thread_view_store = __esm({
59187
59338
  const facts = asyncQuestionFactItems(nextAggregate);
59188
59339
  if (facts.length) {
59189
59340
  const observation = nextEntry.questionObservation ??= { confirmed: null, latest: null, pending: /* @__PURE__ */ new Map() };
59190
- const fingerprint2 = createHash20("sha256").update(JSON.stringify(facts)).digest("hex");
59341
+ const fingerprint2 = createHash21("sha256").update(JSON.stringify(facts)).digest("hex");
59191
59342
  observation.latest = observation.pending.get(fingerprint2) ?? null;
59192
59343
  if (fingerprint2 !== observation.confirmed && !observation.pending.has(fingerprint2) && observation.pending.size < 32) {
59193
59344
  const token3 = /* @__PURE__ */ Symbol();
@@ -60386,7 +60537,7 @@ var init_async_question_batch_store = __esm({
60386
60537
  });
60387
60538
 
60388
60539
  // apps/desktop/src/daemon/runtime/handlers/interactions.ts
60389
- import { createHash as createHash21 } from "node:crypto";
60540
+ import { createHash as createHash22 } from "node:crypto";
60390
60541
  function createInteractionsHandlers(ports) {
60391
60542
  const handlers = {
60392
60543
  "thread/async-question-groups": async (params, _socket, options) => ports.interactions.managedQuestionOperation(async () => {
@@ -60426,7 +60577,7 @@ function createInteractionsHandlers(ports) {
60426
60577
  content: [{ type: "text", text: text11 }],
60427
60578
  mode,
60428
60579
  turnId: mode === "steer" ? action2.activeTurnId : null,
60429
- idempotencyKey: `managed-question:${createHash21("sha256").update(JSON.stringify([principal, batch.thread_id, batch.idempotency_key])).digest("hex")}`,
60580
+ idempotencyKey: `managed-question:${createHash22("sha256").update(JSON.stringify([principal, batch.thread_id, batch.idempotency_key])).digest("hex")}`,
60430
60581
  [MANAGED_QUESTION_BATCH]: true
60431
60582
  }, { ...options, onNativeMessageDispatch: () => {
60432
60583
  ports.interactions.assertManagedQuestionAccess(batch.thread_id, options, generation);
@@ -61876,10 +62027,10 @@ var init_history_snapshot = __esm({
61876
62027
  const patches = objectRecord3(objectRecord3(objectRecord3(frame).params).change).patches;
61877
62028
  const covered = Array.isArray(patches) && patches.every((raw) => {
61878
62029
  const patch = objectRecord3(raw);
61879
- const path55 = patch.path;
61880
- if (!Array.isArray(path55)) return false;
61881
- if (path55[0] === "requests") return ["add", "replace", "remove"].includes(String(patch.op));
61882
- return path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey" && typeof path55[3] === "string" && path55[3].endsWith(`:${recovery.turnId}`) && path55[4] === "items" && (patch.op === "add" && path55.length === 6 || patch.op === "replace" && path55.length === 7 && path55[6] === "text");
62030
+ const path56 = patch.path;
62031
+ if (!Array.isArray(path56)) return false;
62032
+ if (path56[0] === "requests") return ["add", "replace", "remove"].includes(String(patch.op));
62033
+ return path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey" && typeof path56[3] === "string" && path56[3].endsWith(`:${recovery.turnId}`) && path56[4] === "items" && (patch.op === "add" && path56.length === 6 || patch.op === "replace" && path56.length === 7 && path56[6] === "text");
61883
62034
  });
61884
62035
  const bytes3 = Buffer.byteLength(JSON.stringify(acceptedEvents));
61885
62036
  if (!covered || recovery.events.length + events.length > 256 || recovery.bytes + bytes3 > 2 * 1024 * 1024) recovery.valid = false;
@@ -62093,7 +62244,7 @@ var init_history_state_reads = __esm({
62093
62244
  });
62094
62245
 
62095
62246
  // apps/desktop/src/daemon/app-server-history-window-reader.ts
62096
- import { createHash as createHash22, randomUUID as randomUUID38 } from "node:crypto";
62247
+ import { createHash as createHash23, randomUUID as randomUUID38 } from "node:crypto";
62097
62248
  function awaitResponse(promise, signal) {
62098
62249
  if (!signal) return promise;
62099
62250
  signal.throwIfAborted();
@@ -62248,11 +62399,11 @@ var init_app_server_history_window_reader = __esm({
62248
62399
  const bound = this.turnMetadata.get(turn);
62249
62400
  if (!bound) throw new SessionHistoryError("INVALID_CURSOR", "Turn \u4E0D\u5C5E\u4E8E\u5F53\u524D\u5386\u53F2\u5FEB\u7167");
62250
62401
  this.assertEvidenceCurrent(bound);
62251
- const { createdAt, cwd, path: path55 } = bound.metadata;
62402
+ const { createdAt, cwd, path: path56 } = bound.metadata;
62252
62403
  return {
62253
62404
  nativeOrder: bound.nativeOrder,
62254
62405
  sourceRevision: bound.revision,
62255
- contentVersion: createHash22("sha256").update(JSON.stringify([turn, createdAt, cwd, path55])).digest("hex")
62406
+ contentVersion: createHash23("sha256").update(JSON.stringify([turn, createdAt, cwd, path56])).digest("hex")
62256
62407
  };
62257
62408
  }
62258
62409
  /** 撤销正文提交资格,保留逻辑边界供下次原生读取重新证明。 */
@@ -62465,7 +62616,7 @@ var init_app_server_history_window_reader = __esm({
62465
62616
  this.nativeMetrics.peakCandidateBytes = Math.max(this.nativeMetrics.peakCandidateBytes, source2.rawBytes);
62466
62617
  source2.nativeVersions = new Map(source2.rawTurns.map((raw) => {
62467
62618
  const value = raw;
62468
- return [String(value.id), createHash22("sha256").update(JSON.stringify(raw)).digest("hex")];
62619
+ return [String(value.id), createHash23("sha256").update(JSON.stringify(raw)).digest("hex")];
62469
62620
  }));
62470
62621
  source2.nativeEdges = this.proveNativeEdges([...source2.nativeVersions.keys()], source2.eof === true, !hint);
62471
62622
  const ids = /* @__PURE__ */ new Set();
@@ -62869,7 +63020,7 @@ var init_thread_history_snapshot_cache = __esm({
62869
63020
  });
62870
63021
 
62871
63022
  // apps/desktop/src/daemon/thread-history-window-loader.ts
62872
- import { createHash as createHash23, randomUUID as randomUUID39 } from "node:crypto";
63023
+ import { createHash as createHash24, randomUUID as randomUUID39 } from "node:crypto";
62873
63024
  function abortable(promise, signal) {
62874
63025
  signal.throwIfAborted();
62875
63026
  return new Promise((resolve5, reject3) => {
@@ -63165,7 +63316,7 @@ var init_thread_history_window_loader = __esm({
63165
63316
  token3.addTurnIds([turn.id]);
63166
63317
  const identity6 = JSON.stringify([threadId2, turn.id]);
63167
63318
  const description = this.reader.describeTurn?.(turn) ?? {
63168
- contentVersion: createHash23("sha256").update(JSON.stringify(turn)).digest("hex"),
63319
+ contentVersion: createHash24("sha256").update(JSON.stringify(turn)).digest("hex"),
63169
63320
  nativeOrder: 0,
63170
63321
  sourceRevision: 0
63171
63322
  };
@@ -63247,7 +63398,7 @@ var init_thread_history_window_loader = __esm({
63247
63398
  async measure(turn, signal) {
63248
63399
  const epoch = this.sourceEpoch;
63249
63400
  this.currentProtection.addTurnIds([turn.id]);
63250
- const description = this.reader.describeTurn?.(turn) ?? { contentVersion: createHash23("sha256").update(JSON.stringify(turn)).digest("hex") };
63401
+ const description = this.reader.describeTurn?.(turn) ?? { contentVersion: createHash24("sha256").update(JSON.stringify(turn)).digest("hex") };
63251
63402
  const timing = await this.timestampVersion(turn, signal);
63252
63403
  this.assertSource(epoch);
63253
63404
  signal.throwIfAborted();
@@ -63373,7 +63524,7 @@ var init_thread_history = __esm({
63373
63524
  });
63374
63525
 
63375
63526
  // apps/desktop/src/daemon/thread-read-checkpoint.ts
63376
- import { createHash as createHash24 } from "node:crypto";
63527
+ import { createHash as createHash25 } from "node:crypto";
63377
63528
  function stableContent2(part) {
63378
63529
  if (part.type === "text") return { type: part.type, text: part.text };
63379
63530
  if (part.type === "file") return { type: part.type, name: part.name, attachment_id: part.attachment_id ?? null };
@@ -63388,7 +63539,7 @@ function createContentCheckpoint(input) {
63388
63539
  namespace: input.namespace,
63389
63540
  threadId: input.threadId,
63390
63541
  turnId: input.turnId,
63391
- fingerprint: createHash24("sha256").update(JSON.stringify(body)).digest("hex")
63542
+ fingerprint: createHash25("sha256").update(JSON.stringify(body)).digest("hex")
63392
63543
  };
63393
63544
  }
63394
63545
  function nativeReadIdentity(input) {
@@ -64760,7 +64911,7 @@ var init_thread_history_window_projection = __esm({
64760
64911
  pending: null,
64761
64912
  activity: null,
64762
64913
  lastError: null,
64763
- resolveKnownLocalImage: (path55, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path55, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path55) ?? null : null),
64914
+ resolveKnownLocalImage: (path56, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path56, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path56) ?? null : null),
64764
64915
  onHistoryItemProjected: (item, normalized) => timeline.push({ id: item.id, timeline: normalized })
64765
64916
  }, "history_only");
64766
64917
  const items = [...event.baseline.committed_items, ...event.baseline.active_turn?.items ?? []];
@@ -65581,7 +65732,7 @@ var init_thread_read_state = __esm({
65581
65732
  });
65582
65733
 
65583
65734
  // apps/desktop/src/daemon/thread-read-diagnostics.ts
65584
- import { createHash as createHash25 } from "node:crypto";
65735
+ import { createHash as createHash26 } from "node:crypto";
65585
65736
  function unreadDiagnosticValues(before, after) {
65586
65737
  return {
65587
65738
  beforeUnread: before?.hasUnreadTurn ?? null,
@@ -65634,8 +65785,8 @@ function unreadFrameDiagnostic(frame) {
65634
65785
  let countValue = values.unreadMessageCount;
65635
65786
  if (kind === "patch") {
65636
65787
  for (const value of Array.isArray(change.patches) ? change.patches : []) {
65637
- const patch = object10(value), path55 = Array.isArray(patch.path) ? patch.path : [];
65638
- const name2 = path55.length === 1 ? path55[0] : path55.length === 2 && path55[0] === "conversationState" ? path55[1] : null;
65788
+ const patch = object10(value), path56 = Array.isArray(patch.path) ? patch.path : [];
65789
+ const name2 = path56.length === 1 ? path56[0] : path56.length === 2 && path56[0] === "conversationState" ? path56[1] : null;
65639
65790
  if (name2 !== "hasUnreadTurn" && name2 !== "unreadMessageCount") continue;
65640
65791
  const state = patch.op === "remove" ? "removed" : ["add", "replace"].includes(String(patch.op)) ? field(patch.value, Object.hasOwn(patch, "value"), name2 === "unreadMessageCount") : "invalid";
65641
65792
  if (name2 === "hasUnreadTurn") unread = state;
@@ -65653,7 +65804,7 @@ function unreadFrameDiagnostic(frame) {
65653
65804
  wireCountValue: count === "value" ? countValue : null,
65654
65805
  version: typeof frame.version === "number" && Number.isSafeInteger(frame.version) && frame.version >= 0 ? frame.version : null,
65655
65806
  revision: typeof change.revision === "number" && Number.isSafeInteger(change.revision) && change.revision >= 0 ? change.revision : null,
65656
- sourceClient: typeof frame.sourceClientId === "string" ? createHash25("sha256").update(frame.sourceClientId).digest("hex").slice(0, 16) : null
65807
+ sourceClient: typeof frame.sourceClientId === "string" ? createHash26("sha256").update(frame.sourceClientId).digest("hex").slice(0, 16) : null
65657
65808
  };
65658
65809
  }
65659
65810
  function safeReadDiagnosticAttribute(key, value) {
@@ -66206,7 +66357,7 @@ var init_async_question_collector = __esm({
66206
66357
  });
66207
66358
 
66208
66359
  // apps/desktop/src/daemon/managed-async-question-groups.ts
66209
- import { createHash as createHash26 } from "node:crypto";
66360
+ import { createHash as createHash27 } from "node:crypto";
66210
66361
  import { z as z14 } from "zod";
66211
66362
  function compactNewTurns(turns) {
66212
66363
  const latest = /* @__PURE__ */ new Map();
@@ -66220,7 +66371,7 @@ function unavailable8() {
66220
66371
  throw new HttpApiError(500, 900004, "\u9898\u7EC4\u5B58\u50A8\u6682\u4E0D\u53EF\u7528");
66221
66372
  }
66222
66373
  function groupId(source2) {
66223
- return "aqg_" + createHash26("sha256").update(source2).digest("base64url");
66374
+ return "aqg_" + createHash27("sha256").update(source2).digest("base64url");
66224
66375
  }
66225
66376
  function project2(t, g) {
66226
66377
  return { thread_id: t.id, group_id: groupId(g.source), revision: g.revision, list: g.list.filter((q) => !q.closed).map(({ id: id5, title, options }) => ({ id: id5, title, options })) };
@@ -66257,8 +66408,8 @@ var init_managed_async_question_groups = __esm({
66257
66408
  trace(phase, batch, extra = {}) {
66258
66409
  try {
66259
66410
  this.diagnostic?.(phase, {
66260
- batch: createHash26("sha256").update(batch.idempotency_key).digest("hex").slice(0, 16),
66261
- thread: createHash26("sha256").update(batch.thread_id).digest("hex").slice(0, 16),
66411
+ batch: createHash27("sha256").update(batch.idempotency_key).digest("hex").slice(0, 16),
66412
+ thread: createHash27("sha256").update(batch.thread_id).digest("hex").slice(0, 16),
66262
66413
  revision: batch.revision,
66263
66414
  answerCount: batch.answers.length,
66264
66415
  ...extra
@@ -66565,7 +66716,7 @@ var init_managed_async_question_groups = __esm({
66565
66716
  });
66566
66717
 
66567
66718
  // apps/desktop/src/daemon/async-question-evidence.ts
66568
- import { createHash as createHash27 } from "node:crypto";
66719
+ import { createHash as createHash28 } from "node:crypto";
66569
66720
  function projectAsyncQuestionEvidence(input) {
66570
66721
  const collection = input.evidence?.collection;
66571
66722
  if (collection && collection.thread_id !== input.threadId) throw new TypeError("invalid_evidence_thread");
@@ -66582,7 +66733,7 @@ function projectAsyncQuestionEvidence(input) {
66582
66733
  list: (collection?.list ?? []).map((q) => ({ id: q.id, title: q.title, options: [...q.options], source_turn_id: q.source_turn_id, answer: q.answer, answer_turn_id: q.answer_turn_id })),
66583
66734
  total: collection?.list.length ?? 0
66584
66735
  };
66585
- const evidence_id = createHash27("sha256").update(JSON.stringify([input.runtimeGeneration, full])).digest("base64url");
66736
+ const evidence_id = createHash28("sha256").update(JSON.stringify([input.runtimeGeneration, full])).digest("base64url");
66586
66737
  const offset = (input.page - 1) * input.pageSize;
66587
66738
  return parseAsyncQuestionEvidencePage({ ...full, evidence_id, page: input.page, page_size: input.pageSize, list: full.list.slice(offset, offset + input.pageSize) });
66588
66739
  }
@@ -66594,7 +66745,7 @@ var init_async_question_evidence2 = __esm({
66594
66745
  });
66595
66746
 
66596
66747
  // apps/desktop/src/daemon/runtime/interactions.ts
66597
- import { createHash as createHash28 } from "node:crypto";
66748
+ import { createHash as createHash29 } from "node:crypto";
66598
66749
  var RuntimeInteractions;
66599
66750
  var init_interactions2 = __esm({
66600
66751
  "apps/desktop/src/daemon/runtime/interactions.ts"() {
@@ -66621,7 +66772,7 @@ var init_interactions2 = __esm({
66621
66772
  // 与持久通知账本的身份上限一致;不淘汰当前轮次来为重复事件续期。
66622
66773
  liveQuestionDeadlines = /* @__PURE__ */ new Map();
66623
66774
  questionKey(threadId2, turnId, rawId) {
66624
- return createHash28("sha256").update(JSON.stringify([threadId2, turnId, rawId])).digest("hex");
66775
+ return createHash29("sha256").update(JSON.stringify([threadId2, turnId, rawId])).digest("hex");
66625
66776
  }
66626
66777
  clearWaiting() {
66627
66778
  this.asyncInputWaitingQuestions.clear();
@@ -67628,7 +67779,7 @@ var init_projection_context = __esm({
67628
67779
  });
67629
67780
 
67630
67781
  // apps/desktop/src/attachments/file-resources.ts
67631
- import { createHash as createHash29, randomUUID as randomUUID42 } from "node:crypto";
67782
+ import { createHash as createHash30, randomUUID as randomUUID42 } from "node:crypto";
67632
67783
  import { constants as constants4 } from "node:fs";
67633
67784
  import { lstat as lstat4, open as open5, realpath as realpath2 } from "node:fs/promises";
67634
67785
  import { basename as basename2, dirname as dirname2, resolve as resolve3 } from "node:path";
@@ -67639,9 +67790,9 @@ function assertFile(stat3) {
67639
67790
  if (!stat3.isFile() || stat3.nlink !== 1n) throw missing2();
67640
67791
  if (stat3.size > BigInt(MAX_BYTES6)) throw limited();
67641
67792
  }
67642
- async function captureDirectoryChain(snapshot2, path55, signal) {
67793
+ async function captureDirectoryChain(snapshot2, path56, signal) {
67643
67794
  const paths = /* @__PURE__ */ new Set();
67644
- for (const start of [dirname2(path55)]) {
67795
+ for (const start of [dirname2(path56)]) {
67645
67796
  for (let current2 = start; ; current2 = dirname2(current2)) {
67646
67797
  paths.add(current2);
67647
67798
  if (paths.size > MAX_DIRECTORY_ENTRIES2) throw limited();
@@ -67771,9 +67922,9 @@ var init_file_resources = __esm({
67771
67922
  trim() {
67772
67923
  while (this.entries.size > MAX_ENTRIES3 || this.indexBytes > MAX_INDEX_BYTES) this.remove(this.entries.values().next().value);
67773
67924
  }
67774
- assertTarget(entry, path55, signal, isCurrent) {
67925
+ assertTarget(entry, path56, signal, isCurrent) {
67775
67926
  this.assertVisible(entry, signal, isCurrent);
67776
- if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path55) {
67927
+ if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path56) {
67777
67928
  this.remove(entry);
67778
67929
  this.options.onReferenceRetired?.({ ...entry.reference, attachmentId: entry.attachmentId });
67779
67930
  throw changed();
@@ -67815,22 +67966,22 @@ var init_file_resources = __esm({
67815
67966
  if (request2 && (!expected || expected.sha256 !== request2.sha256)) throw changed();
67816
67967
  const directories2 = { entries: /* @__PURE__ */ new Map(), bytes: 0 };
67817
67968
  await captureDirectoryChain(directories2, entry.reference.path, combined);
67818
- const path55 = await realpath2(entry.reference.path);
67969
+ const path56 = await realpath2(entry.reference.path);
67819
67970
  combined.throwIfAborted();
67820
- this.assertTarget(entry, path55, combined, isCurrent);
67821
- await captureDirectoryChain(directories2, path55, combined);
67822
- const pathBefore = await lstat4(path55, { bigint: true });
67971
+ this.assertTarget(entry, path56, combined, isCurrent);
67972
+ await captureDirectoryChain(directories2, path56, combined);
67973
+ const pathBefore = await lstat4(path56, { bigint: true });
67823
67974
  assertFile(pathBefore);
67824
- handle = await open5(path55, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
67975
+ handle = await open5(path56, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
67825
67976
  const before = await handle.stat({ bigint: true });
67826
67977
  assertFile(before);
67827
67978
  if (identity5(before) !== identity5(pathBefore)) throw changed();
67828
- const fileIdentity2 = `${path55}\0${identity5(before)}`;
67979
+ const fileIdentity2 = `${path56}\0${identity5(before)}`;
67829
67980
  if (request2 && expected.identity !== fileIdentity2) throw changed();
67830
67981
  const byteSize2 = Number(before.size);
67831
67982
  const chunkCount = Math.ceil(byteSize2 / CHUNK_BYTES);
67832
67983
  if (request2 && request2.index >= chunkCount) throw invalid13();
67833
- const hash3 = createHash29("sha256");
67984
+ const hash3 = createHash30("sha256");
67834
67985
  const buffer = Buffer.alloc(Math.min(CHUNK_BYTES, byteSize2));
67835
67986
  let chunk;
67836
67987
  for (let offset = 0; offset < byteSize2; ) {
@@ -67851,7 +68002,7 @@ var init_file_resources = __esm({
67851
68002
  const pathAfter = await realpath2(entry.reference.path);
67852
68003
  const current2 = await lstat4(pathAfter, { bigint: true });
67853
68004
  this.assertTarget(entry, pathAfter, combined, isCurrent);
67854
- if (pathAfter !== path55 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
68005
+ if (pathAfter !== path56 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
67855
68006
  const sha2562 = hash3.digest("hex");
67856
68007
  if (request2 && sha2562 !== request2.sha256) throw changed();
67857
68008
  await handle.close();
@@ -67867,8 +68018,8 @@ var init_file_resources = __esm({
67867
68018
  chunkBytes: CHUNK_BYTES,
67868
68019
  chunkCount
67869
68020
  };
67870
- this.assertTarget(entry, path55, combined, isCurrent);
67871
- return { entry, path: path55, info, identity: fileIdentity2, chunk, signal: combined };
68021
+ this.assertTarget(entry, path56, combined, isCurrent);
68022
+ return { entry, path: path56, info, identity: fileIdentity2, chunk, signal: combined };
67872
68023
  } catch (error2) {
67873
68024
  combined.throwIfAborted();
67874
68025
  if (error2 instanceof NiumaError) throw error2;
@@ -67900,16 +68051,16 @@ function revisionOf2(value) {
67900
68051
  function occurredAt3() {
67901
68052
  return Math.floor(Date.now() / 1e3);
67902
68053
  }
67903
- function isThreadSettingsPatch(path55) {
67904
- const field2 = path55.at(-1);
68054
+ function isThreadSettingsPatch(path56) {
68055
+ const field2 = path56.at(-1);
67905
68056
  if (typeof field2 !== "string" || !SETTING_FIELD_ALIASES.has(field2)) {
67906
68057
  return false;
67907
68058
  }
67908
- return path55.length === 1 || typeof path55.at(-2) === "string" && SETTINGS_CONTAINERS.has(path55.at(-2));
68059
+ return path56.length === 1 || typeof path56.at(-2) === "string" && SETTINGS_CONTAINERS.has(path56.at(-2));
67909
68060
  }
67910
- function isCurrentPermissionsPatch(path55) {
67911
- const field2 = path55.at(-1);
67912
- return path55.length === 2 && path55[0] === CURRENT_PERMISSIONS_CONTAINER && typeof field2 === "string" && CURRENT_PERMISSION_FIELD_ALIASES.has(field2);
68061
+ function isCurrentPermissionsPatch(path56) {
68062
+ const field2 = path56.at(-1);
68063
+ return path56.length === 2 && path56[0] === CURRENT_PERMISSIONS_CONTAINER && typeof field2 === "string" && CURRENT_PERMISSION_FIELD_ALIASES.has(field2);
67913
68064
  }
67914
68065
  function hasOwn(value, field2) {
67915
68066
  return Object.prototype.hasOwnProperty.call(value, field2);
@@ -67988,20 +68139,20 @@ function currentPermissionsFromRecord(value) {
67988
68139
  return settings;
67989
68140
  }
67990
68141
  function settingsFromPatch(patch) {
67991
- const path55 = array6(patch.path);
67992
- if (path55.length === 1 && typeof path55[0] === "string" && SETTINGS_CONTAINERS.has(path55[0])) {
68142
+ const path56 = array6(patch.path);
68143
+ if (path56.length === 1 && typeof path56[0] === "string" && SETTINGS_CONTAINERS.has(path56[0])) {
67993
68144
  return settingsFromRecord(patch.value, BASE_SETTING_FIELDS);
67994
68145
  }
67995
- if (path55.length === 1 && path55[0] === CURRENT_PERMISSIONS_CONTAINER) {
68146
+ if (path56.length === 1 && path56[0] === CURRENT_PERMISSIONS_CONTAINER) {
67996
68147
  return currentPermissionsFromRecord(patch.value);
67997
68148
  }
67998
- const field2 = path55.at(-1);
68149
+ const field2 = path56.at(-1);
67999
68150
  const settings = {};
68000
- if (typeof field2 === "string" && isCurrentPermissionsPatch(path55)) {
68151
+ if (typeof field2 === "string" && isCurrentPermissionsPatch(path56)) {
68001
68152
  assignCurrentPermission(settings, field2, patch.value);
68002
68153
  return settings;
68003
68154
  }
68004
- if (typeof field2 === "string" && isThreadSettingsPatch(path55)) {
68155
+ if (typeof field2 === "string" && isThreadSettingsPatch(path56)) {
68005
68156
  assignSetting(settings, field2, patch.value);
68006
68157
  }
68007
68158
  return settings;
@@ -71419,8 +71570,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71419
71570
  if (change.type !== "patches" || next === null || previous === void 0 || next <= previous) return [];
71420
71571
  const patches = array7(change.patches);
71421
71572
  const unknownMembership = patches.some((value) => {
71422
- const p = record25(value), path55 = array7(p.path);
71423
- return path55[0] === "turnHistory" && (path55.length < 3 || path55[1] === "history" && (path55[2] === "entitiesByKey" && (path55.length < 4 || path55.length > 4 && ["id", "turnId", "params"].includes(String(path55[4])))));
71573
+ const p = record25(value), path56 = array7(p.path);
71574
+ return path56[0] === "turnHistory" && (path56.length < 3 || path56[1] === "history" && (path56[2] === "entitiesByKey" && (path56.length < 4 || path56.length > 4 && ["id", "turnId", "params"].includes(String(path56[4])))));
71424
71575
  });
71425
71576
  if (next !== previous + 1 || unknownMembership) {
71426
71577
  this.idleHistoryBaselines.delete(context.threadId);
@@ -71430,9 +71581,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71430
71581
  const mapped = new Map(this.entityTurnIdsByThread.get(context.threadId));
71431
71582
  const candidates = /* @__PURE__ */ new Set();
71432
71583
  for (const value of patches) {
71433
- const p = record25(value), path55 = array7(p.path);
71434
- if (p.op === "remove" && path55.length === 4 && path55[0] === "turnHistory" && path55[1] === "history" && path55[2] === "entitiesByKey") {
71435
- const id5 = mapped.get(String(path55[3]));
71584
+ const p = record25(value), path56 = array7(p.path);
71585
+ if (p.op === "remove" && path56.length === 4 && path56[0] === "turnHistory" && path56[1] === "history" && path56[2] === "entitiesByKey") {
71586
+ const id5 = mapped.get(String(path56[3]));
71436
71587
  if (id5) candidates.add(id5);
71437
71588
  }
71438
71589
  }
@@ -71443,9 +71594,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71443
71594
  })).value;
71444
71595
  const canDelete = typeof newGeneration === "number" && Number.isSafeInteger(newGeneration) && oldGeneration !== void 0 && newGeneration > oldGeneration;
71445
71596
  for (const value of patches) {
71446
- const p = record25(value), path55 = array7(p.path), entity = record25(p.value);
71447
- if (path55.length !== 4 || path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey") continue;
71448
- const key = String(path55[3]);
71597
+ const p = record25(value), path56 = array7(p.path), entity = record25(p.value);
71598
+ if (path56.length !== 4 || path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey") continue;
71599
+ const key = String(path56[3]);
71449
71600
  if (p.op === "remove") mapped.delete(key);
71450
71601
  else if (p.op === "add" || p.op === "replace") {
71451
71602
  const id5 = nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? nonEmptyString14(record25(entity.params).turnId);
@@ -71571,8 +71722,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71571
71722
  const change = record25(record25(frame.params).change);
71572
71723
  for (const rawPatch of array7(change.patches)) {
71573
71724
  const patch = record25(rawPatch);
71574
- const path55 = array7(patch.path);
71575
- if ((patch.op === "add" || patch.op === "replace") && (path55.length === 1 && path55[0] === "recencyAt" || path55.length === 2 && path55[0] === "conversationState" && path55[1] === "recencyAt")) {
71725
+ const path56 = array7(patch.path);
71726
+ if ((patch.op === "add" || patch.op === "replace") && (path56.length === 1 && path56[0] === "recencyAt" || path56.length === 2 && path56[0] === "conversationState" && path56[1] === "recencyAt")) {
71576
71727
  this.rememberSidebarRecency(context.threadId, patch.value);
71577
71728
  }
71578
71729
  }
@@ -71658,12 +71809,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71658
71809
  requests = structuredClone(requests);
71659
71810
  for (const value of array7(change.patches)) {
71660
71811
  const patch = record25(value);
71661
- const path55 = array7(patch.path);
71662
- if (path55[0] !== "requests") continue;
71663
- if (path55.length === 1) {
71812
+ const path56 = array7(patch.path);
71813
+ if (path56[0] !== "requests") continue;
71814
+ if (path56.length === 1) {
71664
71815
  requests = patch.op === "remove" ? [] : structuredClone(array7(patch.value));
71665
- } else if (path55.length === 2) {
71666
- const index = path55[1] === "-" ? requests.length : Number(path55[1]);
71816
+ } else if (path56.length === 2) {
71817
+ const index = path56[1] === "-" ? requests.length : Number(path56[1]);
71667
71818
  if (!Number.isInteger(index) || index < 0 || index > requests.length) continue;
71668
71819
  if (patch.op === "remove") requests.splice(index, 1);
71669
71820
  else if (patch.op === "add") requests.splice(index, 0, structuredClone(patch.value));
@@ -71742,19 +71893,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71742
71893
  }
71743
71894
  /** 深层 content 只有局部形状,须等待完整项/快照重新证明;text 更新不能洗掉未知内容。 */
71744
71895
  invalidateReadPatch(patch, context) {
71745
- const path55 = array7(patch.path);
71746
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey") return;
71747
- const turnId = typeof path55[3] === "string" ? this.entityTurnIdsByThread.get(context.threadId)?.get(path55[3]) : null;
71748
- if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (path55[4] === "items" || path55.length === 4 && hasOwn2(record25(patch.value), "items"))) {
71896
+ const path56 = array7(patch.path);
71897
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey") return;
71898
+ const turnId = typeof path56[3] === "string" ? this.entityTurnIdsByThread.get(context.threadId)?.get(path56[3]) : null;
71899
+ if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (path56[4] === "items" || path56.length === 4 && hasOwn2(record25(patch.value), "items"))) {
71749
71900
  for (const identity7 of this.nativeReadIdentities.get(context.threadId)?.values() ?? []) {
71750
71901
  if (identity7.turnId === turnId) identity7.complete = false;
71751
71902
  }
71752
71903
  return;
71753
71904
  }
71754
- if (path55[4] !== "items" || path55[6] !== "content") return;
71905
+ if (path56[4] !== "items" || path56[6] !== "content") return;
71755
71906
  const order = this.itemOrders.get(context.threadId);
71756
- if (!order || order.entityKey !== path55[3]) return;
71757
- const id5 = typeof path55[5] === "number" ? order.ids[path55[5]] : null;
71907
+ if (!order || order.entityKey !== path56[3]) return;
71908
+ const id5 = typeof path56[5] === "number" ? order.ids[path56[5]] : null;
71758
71909
  const identity6 = id5 ? this.nativeReadIdentities.get(context.threadId)?.get(id5) : null;
71759
71910
  if (identity6) identity6.complete = false;
71760
71911
  else if (!id5) {
@@ -71778,19 +71929,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71778
71929
  /** 在同一 Store 事务内先更新正文,再发布可信顺序,不让 Web 看见暂存的中间帧。 */
71779
71930
  itemOrderEvents(patch, itemEvents, context) {
71780
71931
  if (this.itemOrderGaps.has(context.threadId)) return [];
71781
- const path55 = array7(patch.path);
71782
- if (path55[0] !== "turnHistory") return [];
71932
+ const path56 = array7(patch.path);
71933
+ if (path56[0] !== "turnHistory") return [];
71783
71934
  const invalidate = () => {
71784
71935
  this.itemOrders.delete(context.threadId);
71785
71936
  this.itemOrderGaps.add(context.threadId);
71786
71937
  return [];
71787
71938
  };
71788
- if (path55.length < 3) return invalidate();
71789
- if (path55[1] !== "history" || path55[2] !== "entitiesByKey") return [];
71790
- if (path55.length < 4) return invalidate();
71939
+ if (path56.length < 3) return invalidate();
71940
+ if (path56[1] !== "history" || path56[2] !== "entitiesByKey") return [];
71941
+ if (path56.length < 4) return invalidate();
71791
71942
  const activeId = this.activeTurnByThread.get(context.threadId);
71792
71943
  if (!activeId) return [];
71793
- const entityKey = String(path55[3]);
71944
+ const entityKey = String(path56[3]);
71794
71945
  const events = [];
71795
71946
  const emitItem = (value) => {
71796
71947
  const item = this.orderedRawItem(value, activeId, context);
@@ -71807,8 +71958,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71807
71958
  return item?.id ?? null;
71808
71959
  };
71809
71960
  let order = this.itemOrders.get(context.threadId);
71810
- const wholeEntity = path55.length === 4;
71811
- const wholeArray = path55.length === 5 && path55[4] === "items";
71961
+ const wholeEntity = path56.length === 4;
71962
+ const wholeArray = path56.length === 5 && path56[4] === "items";
71812
71963
  if (wholeEntity || wholeArray) {
71813
71964
  const entity = record25(patch.value);
71814
71965
  const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) : this.entityTurnIdsByThread.get(context.threadId)?.get(entityKey);
@@ -71824,12 +71975,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
71824
71975
  }
71825
71976
  values.forEach(emitItem);
71826
71977
  } else {
71827
- if (!order || order.turnId !== activeId || order.entityKey !== entityKey || path55[4] !== "items") return [];
71828
- if (path55.length > 6) {
71829
- return ["id", "type"].includes(String(path55[6])) ? invalidate() : [];
71978
+ if (!order || order.turnId !== activeId || order.entityKey !== entityKey || path56[4] !== "items") return [];
71979
+ if (path56.length > 6) {
71980
+ return ["id", "type"].includes(String(path56[6])) ? invalidate() : [];
71830
71981
  }
71831
- if (path55.length !== 6 || !["add", "replace", "remove"].includes(String(patch.op))) return invalidate();
71832
- const index = path55[5] === "-" && patch.op === "add" ? order.ids.length : path55[5];
71982
+ if (path56.length !== 6 || !["add", "replace", "remove"].includes(String(patch.op))) return invalidate();
71983
+ const index = path56[5] === "-" && patch.op === "add" ? order.ids.length : path56[5];
71833
71984
  if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0 || index > order.ids.length || patch.op !== "add" && index === order.ids.length) return invalidate();
71834
71985
  if (patch.op === "add" && order.ids.length >= 8192) return invalidate();
71835
71986
  const previousId = order.ids[index];
@@ -72050,12 +72201,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
72050
72201
  for (const patchValue of patches) {
72051
72202
  const patch = record25(patchValue);
72052
72203
  if (patch.op !== "add" && patch.op !== "replace") continue;
72053
- const path55 = array7(patch.path);
72054
- if (path55[0] !== "turnHistory" || path55[1] !== "history" || path55[2] !== "entitiesByKey" || typeof path55[3] !== "string") continue;
72055
- const entityKey = path55[3];
72056
- const wholeEntity = path55.length === 4;
72057
- const statusField = path55.length === 5 && path55[4] === "status";
72058
- const startField = path55.length === 5 && path55[4] === "turnStartedAtMs";
72204
+ const path56 = array7(patch.path);
72205
+ if (path56[0] !== "turnHistory" || path56[1] !== "history" || path56[2] !== "entitiesByKey" || typeof path56[3] !== "string") continue;
72206
+ const entityKey = path56[3];
72207
+ const wholeEntity = path56.length === 4;
72208
+ const statusField = path56.length === 5 && path56[4] === "status";
72209
+ const startField = path56.length === 5 && path56[4] === "turnStartedAtMs";
72059
72210
  if (!wholeEntity && !statusField && !startField) continue;
72060
72211
  const entity = wholeEntity ? record25(patch.value) : {};
72061
72212
  const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? entityTurnIds.get(entityKey) ?? null : entityTurnIds.get(entityKey) ?? null;
@@ -72238,7 +72389,7 @@ var init_desktop_ipc_thread_view_adapter = __esm({
72238
72389
  });
72239
72390
 
72240
72391
  // apps/desktop/src/daemon/thread-view-files.ts
72241
- import { createHash as createHash30 } from "node:crypto";
72392
+ import { createHash as createHash31 } from "node:crypto";
72242
72393
  function normalizeFileCitations(text11, paths) {
72243
72394
  if (!text11.includes(":codex-file-citation{")) return text11;
72244
72395
  const edits = [];
@@ -72260,12 +72411,12 @@ function normalizeFileCitations(text11, paths) {
72260
72411
  const end = start + match[0].length;
72261
72412
  if (!textRanges.some(([a, b]) => a <= start && start < b) || excluded.some(([a, b]) => a < end && b > start)) continue;
72262
72413
  const slashes = text11.slice(0, start).match(/\\*$/u)?.[0].length ?? 0;
72263
- const path55 = match[1];
72264
- if (slashes % 2 || paths.parseLocal(path55) === null) continue;
72414
+ const path56 = match[1];
72415
+ if (slashes % 2 || paths.parseLocal(path56) === null) continue;
72265
72416
  try {
72266
- const target = paths.toLink(path55);
72417
+ const target = paths.toLink(path56);
72267
72418
  if (target === null) continue;
72268
- const label = fallbackFileName(path55, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
72419
+ const label = fallbackFileName(path56, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
72269
72420
  edits.push({ start, end, value: `[${label}](<${target}>)` });
72270
72421
  } catch {
72271
72422
  }
@@ -72283,9 +72434,9 @@ function fileReferences(text11, paths) {
72283
72434
  return markdownTargets(text11).references.filter((ref) => !ref.image).flatMap((ref) => {
72284
72435
  try {
72285
72436
  const target = withoutFileLocation(ref.url);
72286
- const path55 = paths.parseLink(target);
72287
- if (path55 === null) return [];
72288
- return [{ ...ref, path: path55 }];
72437
+ const path56 = paths.parseLink(target);
72438
+ if (path56 === null) return [];
72439
+ return [{ ...ref, path: path56 }];
72289
72440
  } catch {
72290
72441
  return [];
72291
72442
  }
@@ -72295,8 +72446,8 @@ function collectFileLinkPaths(item, paths = localResourcePaths) {
72295
72446
  if (item.type !== "assistant_message") return [];
72296
72447
  return [...new Set(item.content.flatMap((part) => part.type === "text" ? fileReferences(normalizeFileCitations(part.text, paths), paths).map((ref) => ref.path) : []))];
72297
72448
  }
72298
- function fallbackFileName(path55, paths) {
72299
- const name2 = paths.basename(path55).slice(0, 255);
72449
+ function fallbackFileName(path56, paths) {
72450
+ const name2 = paths.basename(path56).slice(0, 255);
72300
72451
  return name2.trim() && !/[\\/\x00-\x1f\x7f-\x9f]/u.test(name2) ? name2 : "\u6587\u4EF6";
72301
72452
  }
72302
72453
  function projectFileLinks(item, register, isRegistered = () => true, paths = localResourcePaths) {
@@ -72306,7 +72457,7 @@ function projectFileLinks(item, register, isRegistered = () => true, paths = loc
72306
72457
  const original = item.content.map((part) => {
72307
72458
  if (part.type !== "file" || !part.attachment_id || isRegistered(part.attachment_id)) return part;
72308
72459
  const { attachment_id: id5, ...unavailable12 } = part;
72309
- retired.set(`niuma-file:${id5}`, `niuma-file:unavailable_${createHash30("sha256").update(id5).digest("hex")}`);
72460
+ retired.set(`niuma-file:${id5}`, `niuma-file:unavailable_${createHash31("sha256").update(id5).digest("hex")}`);
72310
72461
  return unavailable12;
72311
72462
  });
72312
72463
  const content2 = original.map((part) => {
@@ -72315,7 +72466,7 @@ function projectFileLinks(item, register, isRegistered = () => true, paths = loc
72315
72466
  const targets = new Map(retired);
72316
72467
  for (const ref of fileReferences(text11, paths)) {
72317
72468
  const registered = register(ref.path);
72318
- const id5 = registered?.attachmentId ?? `unavailable_${createHash30("sha256").update(JSON.stringify([item.id, ref.path])).digest("hex")}`;
72469
+ const id5 = registered?.attachmentId ?? `unavailable_${createHash31("sha256").update(JSON.stringify([item.id, ref.path])).digest("hex")}`;
72319
72470
  targets.set(ref.url, `niuma-file:${id5}`);
72320
72471
  if (!files.has(id5)) files.set(id5, {
72321
72472
  type: "file",
@@ -72359,8 +72510,8 @@ var init_thread_view_files = __esm({
72359
72510
  });
72360
72511
 
72361
72512
  // apps/desktop/src/daemon/runtime/projection.ts
72362
- import { createHash as createHash31 } from "node:crypto";
72363
- import path38 from "node:path";
72513
+ import { createHash as createHash32 } from "node:crypto";
72514
+ import path39 from "node:path";
72364
72515
  var FILE_REFRESH_MAX_ENTRIES, FILE_REFRESH_MAX_BYTES, FILE_REFRESH_ENTRY_BYTES, FILE_REFRESH_IN_FLIGHT_RESERVE, RuntimeProjection;
72365
72516
  var init_projection2 = __esm({
72366
72517
  "apps/desktop/src/daemon/runtime/projection.ts"() {
@@ -72407,7 +72558,7 @@ var init_projection2 = __esm({
72407
72558
  }
72408
72559
  pendingRetirements.set(threadId2, {
72409
72560
  itemId,
72410
- fingerprint: createHash31("sha256").update(JSON.stringify(item)).digest("hex"),
72561
+ fingerprint: createHash32("sha256").update(JSON.stringify(item)).digest("hex"),
72411
72562
  isCurrent: this.ports.captureFileResourceSource(threadId2)
72412
72563
  });
72413
72564
  if (alreadyPending) return;
@@ -72416,7 +72567,7 @@ var init_projection2 = __esm({
72416
72567
  pendingRetirements.delete(threadId2);
72417
72568
  if (!retired?.isCurrent()) return;
72418
72569
  const current2 = viewStore2.getProjectionItem(threadId2, retired.itemId);
72419
- if (!current2 || createHash31("sha256").update(JSON.stringify(current2)).digest("hex") !== retired.fingerprint) return;
72570
+ if (!current2 || createHash32("sha256").update(JSON.stringify(current2)).digest("hex") !== retired.fingerprint) return;
72420
72571
  viewStore2.refreshResourceProjection(threadId2);
72421
72572
  });
72422
72573
  }
@@ -72492,14 +72643,14 @@ var init_projection2 = __esm({
72492
72643
  isFileReferenceVisible(entry) {
72493
72644
  if (this.ports.stopping()) return false;
72494
72645
  const root = this.ports.projectRoot(entry.threadId);
72495
- if (!root || path38.resolve(root) !== entry.root) return false;
72646
+ if (!root || path39.resolve(root) !== entry.root) return false;
72496
72647
  const item = this.store.getProjectionItem(entry.threadId, entry.itemId);
72497
72648
  if (!item) return false;
72498
72649
  if (item.type === "user_message") {
72499
- return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" && path38.resolve(source2.path) === entry.path);
72650
+ return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" && path39.resolve(source2.path) === entry.path);
72500
72651
  }
72501
72652
  if (item.type !== "assistant_message") return false;
72502
- if (collectFileLinkPaths(item).some((sourcePath) => path38.resolve(sourcePath) === entry.path)) return true;
72653
+ if (collectFileLinkPaths(item).some((sourcePath) => path39.resolve(sourcePath) === entry.path)) return true;
72503
72654
  return item.content.some((part) => part.type === "file" && part.attachment_id === entry.attachmentId) && hasFileAttachmentLink(item, entry.attachmentId);
72504
72655
  }
72505
72656
  subagentAvatars = new CodexSubagentAvatars();
@@ -73863,7 +74014,7 @@ var init_thread_read_receipts2 = __esm({
73863
74014
  });
73864
74015
 
73865
74016
  // apps/desktop/src/daemon/runtime/read-receipts.ts
73866
- import { createHash as createHash32 } from "node:crypto";
74017
+ import { createHash as createHash33 } from "node:crypto";
73867
74018
  function nowSeconds14() {
73868
74019
  return Math.floor(Date.now() / 1e3);
73869
74020
  }
@@ -74037,8 +74188,8 @@ var init_read_receipts = __esm({
74037
74188
  return;
74038
74189
  }
74039
74190
  const statusOnly = change.type === "patches" && Array.isArray(change.patches) && change.patches.length > 0 && change.patches.every((value) => {
74040
- const patch = objectRecord3(value), path55 = Array.isArray(patch.path) ? patch.path : [];
74041
- const fields3 = path55[0] === "conversationState" ? path55.slice(1) : path55;
74191
+ const patch = objectRecord3(value), path56 = Array.isArray(patch.path) ? patch.path : [];
74192
+ const fields3 = path56[0] === "conversationState" ? path56.slice(1) : path56;
74042
74193
  if (!["add", "replace", "remove"].includes(String(patch.op)) || fields3.length !== 1) return false;
74043
74194
  if (fields3[0] === "threadRuntimeStatus") return true;
74044
74195
  return patch.op !== "remove" && (fields3[0] === "hasUnreadTurn" && patch.value === raw?.hasUnreadTurn || fields3[0] === "unreadMessageCount" && patch.value === raw?.unreadMessageCount);
@@ -74121,7 +74272,7 @@ var init_read_receipts = __esm({
74121
74272
  this.publishThreadReadChange(threadId2);
74122
74273
  }
74123
74274
  async initialize(codexHome, receiptPath, diagnostics = false) {
74124
- this.namespace = createHash32("sha256").update(codexHome).digest("hex");
74275
+ this.namespace = createHash33("sha256").update(codexHome).digest("hex");
74125
74276
  this.receipts = new ThreadReadReceipts(
74126
74277
  new ReadReceiptStore(
74127
74278
  this.namespace,
@@ -74583,7 +74734,7 @@ var init_message_submission_attempt = __esm({
74583
74734
  });
74584
74735
 
74585
74736
  // apps/desktop/src/daemon/runtime/submission.ts
74586
- import { createHash as createHash33 } from "node:crypto";
74737
+ import { createHash as createHash34 } from "node:crypto";
74587
74738
  var RuntimeSubmission;
74588
74739
  var init_submission2 = __esm({
74589
74740
  "apps/desktop/src/daemon/runtime/submission.ts"() {
@@ -74778,7 +74929,7 @@ var init_submission2 = __esm({
74778
74929
  const reservation = await store.reserve({
74779
74930
  ...key,
74780
74931
  nativeToken: clientMessageId,
74781
- fingerprint: createHash33("sha256").update(JSON.stringify(content2)).digest("hex")
74932
+ fingerprint: createHash34("sha256").update(JSON.stringify(content2)).digest("hex")
74782
74933
  });
74783
74934
  if (!reservation.dispatch) {
74784
74935
  existingSubmission = true;
@@ -76313,7 +76464,7 @@ var init_image_decoder = __esm({
76313
76464
  });
76314
76465
 
76315
76466
  // apps/desktop/src/attachments/image-assets.ts
76316
- import path39 from "node:path";
76467
+ import path40 from "node:path";
76317
76468
  function names(id5) {
76318
76469
  if (!idPattern.test(id5)) throw unavailable9();
76319
76470
  return { metadata: `img_${id5.slice(4)}`, source: `src_${id5.slice(4)}`, preview: `prv_${id5.slice(4)}` };
@@ -76360,7 +76511,7 @@ var init_image_assets = __esm({
76360
76511
  }
76361
76512
  paths(id5) {
76362
76513
  const n = names(id5);
76363
- return { sourcePath: path39.join(this.root, n.source, "source"), previewPath: path39.join(this.root, n.preview, "source") };
76514
+ return { sourcePath: path40.join(this.root, n.source, "source"), previewPath: path40.join(this.root, n.preview, "source") };
76364
76515
  }
76365
76516
  asset(id5) {
76366
76517
  const value = this.assets.get(id5);
@@ -76492,7 +76643,7 @@ import { constants as constants5 } from "node:fs";
76492
76643
  import { chmod as chmod2, lstat as lstat5, mkdir as mkdir2, open as open6 } from "node:fs/promises";
76493
76644
  import { execFile as execFile11 } from "node:child_process";
76494
76645
  import { promisify as promisify4 } from "node:util";
76495
- import path40 from "node:path";
76646
+ import path41 from "node:path";
76496
76647
  async function preparePrivateImageRoot(directory) {
76497
76648
  if (process.platform === "win32") {
76498
76649
  await ensureWindowsPrivateDirectoryAsync(directory);
@@ -76508,7 +76659,7 @@ async function createPrivateImageDirectory(directory) {
76508
76659
  return;
76509
76660
  }
76510
76661
  directory = localWindowsPath(directory);
76511
- const parent = await openPrivateImageDirectory(path40.dirname(directory));
76662
+ const parent = await openPrivateImageDirectory(path41.dirname(directory));
76512
76663
  try {
76513
76664
  await parent.verify();
76514
76665
  await mkdir2(directory, { mode: 448 });
@@ -76531,7 +76682,7 @@ Check-PrivateDirectory $env:NIUMA_IMAGE_DIRECTORY
76531
76682
  }
76532
76683
  async function openPrivateImageDirectory(requested, openFile2 = open6) {
76533
76684
  const windows2 = process.platform === "win32";
76534
- const directory = windows2 ? localWindowsPath(requested) : path40.resolve(requested);
76685
+ const directory = windows2 ? localWindowsPath(requested) : path41.resolve(requested);
76535
76686
  const initial = await lstat5(directory, { bigint: true });
76536
76687
  if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable10();
76537
76688
  let handle;
@@ -76640,7 +76791,7 @@ var init_private_image_files = __esm({
76640
76791
  // apps/desktop/src/platform/private-image-commit.ts
76641
76792
  import { randomUUID as randomUUID45 } from "node:crypto";
76642
76793
  import { lstat as lstat6, rename as rename2, rm as rm2 } from "node:fs/promises";
76643
- import path41 from "node:path";
76794
+ import path42 from "node:path";
76644
76795
  async function snapshot(file, maxBytes) {
76645
76796
  try {
76646
76797
  await lstat6(file);
@@ -76705,7 +76856,7 @@ var init_private_image_commit = __esm({
76705
76856
  await this.writeBinary(file, bytes3, maxBytes);
76706
76857
  return;
76707
76858
  }
76708
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76859
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76709
76860
  try {
76710
76861
  const handle = await privateBinaryFiles.open(file, { maxBytes, writable: true, mode: "mutable" });
76711
76862
  try {
@@ -76740,7 +76891,7 @@ var init_private_image_commit = __esm({
76740
76891
  }
76741
76892
  },
76742
76893
  async writeBinary(file, bytes3, maxBytes) {
76743
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76894
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76744
76895
  try {
76745
76896
  await directory.verify();
76746
76897
  await writeNew(file, bytes3, maxBytes);
@@ -76753,8 +76904,8 @@ var init_private_image_commit = __esm({
76753
76904
  const bytes3 = Buffer.from(input);
76754
76905
  let published = false, renameAttempted = false;
76755
76906
  let temporaryIdentity;
76756
- const directory = await openPrivateImageDirectory(path41.dirname(file));
76757
- const temporary = path41.join(path41.dirname(file), `.manifest-${randomUUID45()}.tmp`);
76907
+ const directory = await openPrivateImageDirectory(path42.dirname(file));
76908
+ const temporary = path42.join(path42.dirname(file), `.manifest-${randomUUID45()}.tmp`);
76758
76909
  try {
76759
76910
  if (bytes3.length > maxBytes) throw new PrivateImageCommitError();
76760
76911
  new TextDecoder("utf-8", { fatal: true }).decode(bytes3);
@@ -76802,14 +76953,14 @@ var init_private_image_commit = __esm({
76802
76953
  });
76803
76954
 
76804
76955
  // apps/desktop/src/platform/private-document-directory.ts
76805
- import fs26 from "node:fs";
76806
- import path42 from "node:path";
76956
+ import fs27 from "node:fs";
76957
+ import path43 from "node:path";
76807
76958
  async function openPrivateDocumentDirectory(root) {
76808
- const directory = path42.resolve(root);
76959
+ const directory = path43.resolve(root);
76809
76960
  let identity6;
76810
76961
  try {
76811
76962
  privateLogFiles.ensureDirectory(directory);
76812
- identity6 = fs26.lstatSync(directory, { bigint: true });
76963
+ identity6 = fs27.lstatSync(directory, { bigint: true });
76813
76964
  privateLogFiles.checkDirectory(directory);
76814
76965
  guard();
76815
76966
  } catch {
@@ -76817,7 +76968,7 @@ async function openPrivateDocumentDirectory(root) {
76817
76968
  }
76818
76969
  function guard() {
76819
76970
  try {
76820
- const current2 = fs26.lstatSync(directory, { bigint: true });
76971
+ const current2 = fs27.lstatSync(directory, { bigint: true });
76821
76972
  if (!current2.isDirectory() || current2.isSymbolicLink() || current2.dev !== identity6.dev || current2.ino !== identity6.ino) {
76822
76973
  throw new PrivateDocumentFileError("unavailable");
76823
76974
  }
@@ -76830,7 +76981,7 @@ async function openPrivateDocumentDirectory(root) {
76830
76981
  if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(name2) || name2 === "." || name2 === "..") {
76831
76982
  throw new PrivateDocumentFileError("unavailable");
76832
76983
  }
76833
- return path42.join(directory, name2);
76984
+ return path43.join(directory, name2);
76834
76985
  }
76835
76986
  const files = privateStateFilesWithGuard(guard);
76836
76987
  return {
@@ -76862,7 +77013,7 @@ var init_private_document_directory = __esm({
76862
77013
  });
76863
77014
 
76864
77015
  // apps/desktop/src/attachments/store.ts
76865
- import { createHash as createHash34, randomUUID as randomUUID46 } from "node:crypto";
77016
+ import { createHash as createHash35, randomUUID as randomUUID46 } from "node:crypto";
76866
77017
  import { constants as constants6 } from "node:fs";
76867
77018
  import {
76868
77019
  chmod as chmod3,
@@ -76912,38 +77063,38 @@ function decodeBase64(value) {
76912
77063
  return decoded;
76913
77064
  }
76914
77065
  function sha256(value) {
76915
- return createHash34("sha256").update(value).digest("hex");
77066
+ return createHash35("sha256").update(value).digest("hex");
76916
77067
  }
76917
- async function readJsonManifest(path55, io) {
77068
+ async function readJsonManifest(path56, io) {
76918
77069
  try {
76919
77070
  if (io.controlledFiles) {
76920
- const { data } = await io.controlledFiles.read(path55);
77071
+ const { data } = await io.controlledFiles.read(path56);
76921
77072
  return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(data));
76922
77073
  }
76923
- const status2 = await lstat7(path55);
77074
+ const status2 = await lstat7(path56);
76924
77075
  if (!status2.isFile() || status2.isSymbolicLink()) {
76925
77076
  return null;
76926
77077
  }
76927
- return JSON.parse(await readFile2(path55, "utf8"));
77078
+ return JSON.parse(await readFile2(path56, "utf8"));
76928
77079
  } catch {
76929
77080
  return null;
76930
77081
  }
76931
77082
  }
76932
- async function assertRegularControlledFile(directoryPath, path55) {
76933
- if (dirname3(path55) !== directoryPath) {
77083
+ async function assertRegularControlledFile(directoryPath, path56) {
77084
+ if (dirname3(path56) !== directoryPath) {
76934
77085
  throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
76935
77086
  }
76936
- const status2 = await lstat7(path55).catch(() => null);
77087
+ const status2 = await lstat7(path56).catch(() => null);
76937
77088
  if (!status2?.isFile() || status2.isSymbolicLink()) {
76938
77089
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
76939
77090
  }
76940
77091
  }
76941
- async function readRegularFileNoFollow(io, directoryPath, path55, expectedIdentity, expectedSize) {
76942
- if (dirname3(path55) !== directoryPath) {
77092
+ async function readRegularFileNoFollow(io, directoryPath, path56, expectedIdentity, expectedSize) {
77093
+ if (dirname3(path56) !== directoryPath) {
76943
77094
  throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
76944
77095
  }
76945
- if (io.controlledFiles) return io.controlledFiles.read(path55, expectedIdentity, expectedSize);
76946
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77096
+ if (io.controlledFiles) return io.controlledFiles.read(path56, expectedIdentity, expectedSize);
77097
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
76947
77098
  if (!handle) {
76948
77099
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
76949
77100
  }
@@ -76967,8 +77118,8 @@ async function readRegularFileNoFollow(io, directoryPath, path55, expectedIdenti
76967
77118
  await handle.close();
76968
77119
  }
76969
77120
  }
76970
- async function readStableLocalFile(io, path55) {
76971
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77121
+ async function readStableLocalFile(io, path56) {
77122
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
76972
77123
  if (!handle) {
76973
77124
  throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
76974
77125
  }
@@ -76980,8 +77131,8 @@ async function readStableLocalFile(io, path55) {
76980
77131
  if (openedStatus.size > BigInt(MAX_IMAGE_BYTES)) {
76981
77132
  throw new Error("ATTACHMENT_TOO_LARGE");
76982
77133
  }
76983
- const canonicalPath = await realpath3(path55).catch(() => null);
76984
- const currentStatus = await lstat7(path55, { bigint: true }).catch(() => null);
77134
+ const canonicalPath = await realpath3(path56).catch(() => null);
77135
+ const currentStatus = await lstat7(path56, { bigint: true }).catch(() => null);
76985
77136
  if (!canonicalPath || !currentStatus?.isFile() || currentStatus.isSymbolicLink() || currentStatus.dev !== openedStatus.dev || currentStatus.ino !== openedStatus.ino) {
76986
77137
  throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
76987
77138
  }
@@ -76994,17 +77145,17 @@ async function readStableLocalFile(io, path55) {
76994
77145
  await handle.close();
76995
77146
  }
76996
77147
  }
76997
- async function pathIsMissing(path55) {
77148
+ async function pathIsMissing(path56) {
76998
77149
  try {
76999
- await lstat7(path55);
77150
+ await lstat7(path56);
77000
77151
  return false;
77001
77152
  } catch (error2) {
77002
77153
  return error2.code === "ENOENT";
77003
77154
  }
77004
77155
  }
77005
- async function readFileIdentity(io, path55) {
77006
- if (io.controlledFiles) return io.controlledFiles.identity(path55);
77007
- const handle = await io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77156
+ async function readFileIdentity(io, path56) {
77157
+ if (io.controlledFiles) return io.controlledFiles.identity(path56);
77158
+ const handle = await io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
77008
77159
  if (!handle) {
77009
77160
  throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
77010
77161
  }
@@ -77119,7 +77270,7 @@ var init_store = __esm({
77119
77270
  webp: "image/webp"
77120
77271
  };
77121
77272
  DEFAULT_ATTACHMENT_STORE_IO = {
77122
- open: (path55, flags) => open7(path55, flags),
77273
+ open: (path56, flags) => open7(path56, flags),
77123
77274
  controlledFiles: privateImageFiles
77124
77275
  };
77125
77276
  AttachmentStore = class _AttachmentStore {
@@ -77332,15 +77483,15 @@ var init_store = __esm({
77332
77483
  const allowed = /* @__PURE__ */ new Set([MANIFEST_RELATIVE_PATH, ...next.chunks.map((chunk) => chunk.relativePath)]);
77333
77484
  if ((await readdir2(upload.directoryPath)).some((name2) => !allowed.has(name2))) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
77334
77485
  for (let offset = 0; offset < chunks.length; offset++) {
77335
- const path55 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
77486
+ const path56 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
77336
77487
  let handle;
77337
77488
  try {
77338
- handle = await this.#io.open(path55, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
77489
+ handle = await this.#io.open(path56, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
77339
77490
  } catch (error2) {
77340
77491
  if (error2.code !== "EEXIST") throw error2;
77341
- const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path55, void 0, chunk.length);
77492
+ const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path56, void 0, chunk.length);
77342
77493
  if (!stored.data.equals(chunk)) throw new Error("CHUNK_CONFLICT");
77343
- handle = await this.#io.open(path55, constants6.O_RDONLY | constants6.O_NOFOLLOW);
77494
+ handle = await this.#io.open(path56, constants6.O_RDONLY | constants6.O_NOFOLLOW);
77344
77495
  }
77345
77496
  try {
77346
77497
  const status2 = await handle.stat();
@@ -77446,7 +77597,7 @@ var init_store = __esm({
77446
77597
  if (!await this.#isVerifiedUpload(upload)) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
77447
77598
  const chunks = [...upload.manifest.chunks].sort((a, b) => a.index - b.index);
77448
77599
  if (chunks.length !== Math.ceil(upload.manifest.byteSize / MAX_CHUNK_BYTES) || chunks.some((chunk, i) => chunk.index !== i)) throw new Error("UPLOAD_SIZE_MISMATCH");
77449
- const hash3 = createHash34("sha256");
77600
+ const hash3 = createHash35("sha256");
77450
77601
  for (const chunk of chunks) {
77451
77602
  hash3.update(await this.#readUploadChunk(upload, chunk));
77452
77603
  }
@@ -77720,9 +77871,9 @@ var init_store = __esm({
77720
77871
  await this.#imageAssets.removeBytes(record26.id);
77721
77872
  continue;
77722
77873
  }
77723
- for (const path55 of [record26.sourcePath, record26.previewPath]) {
77724
- const status2 = await lstat7(path55).catch(() => null);
77725
- if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(path55);
77874
+ for (const path56 of [record26.sourcePath, record26.previewPath]) {
77875
+ const status2 = await lstat7(path56).catch(() => null);
77876
+ if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(path56);
77726
77877
  }
77727
77878
  }
77728
77879
  }
@@ -78260,10 +78411,10 @@ var init_store = __esm({
78260
78411
  return bytes3;
78261
78412
  }
78262
78413
  async #loadBindingIndex() {
78263
- const path55 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78264
- const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(path55, this.#io);
78414
+ const path56 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78415
+ const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(path56, this.#io);
78265
78416
  if (manifest === null) {
78266
- if (this.#rawCommit && !await pathIsMissing(path55)) this.#bindingUnavailable = true;
78417
+ if (this.#rawCommit && !await pathIsMissing(path56)) this.#bindingUnavailable = true;
78267
78418
  return;
78268
78419
  }
78269
78420
  if (!isBindingIndexManifest(manifest)) {
@@ -78323,14 +78474,14 @@ var init_store = __esm({
78323
78474
  return;
78324
78475
  }
78325
78476
  const temporaryPath = join2(this.#rootDir, `.bindings-${randomUUID46()}.tmp`);
78326
- const path55 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78477
+ const path56 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
78327
78478
  await writeFile(temporaryPath, `${JSON.stringify(manifest)}
78328
78479
  `, {
78329
78480
  flag: "wx",
78330
78481
  mode: 384
78331
78482
  });
78332
- await rename3(temporaryPath, path55);
78333
- await chmod3(path55, 384);
78483
+ await rename3(temporaryPath, path56);
78484
+ await chmod3(path56, 384);
78334
78485
  }
78335
78486
  #commitBindings(bindings) {
78336
78487
  this.#bindings.clear();
@@ -78906,7 +79057,7 @@ var init_message_bindings = __esm({
78906
79057
  });
78907
79058
 
78908
79059
  // apps/desktop/src/attachments/managed-store.ts
78909
- import { createHash as createHash35, randomUUID as randomUUID47 } from "node:crypto";
79060
+ import { createHash as createHash36, randomUUID as randomUUID47 } from "node:crypto";
78910
79061
  function storedIdentity(identity6) {
78911
79062
  return identity6.kind === "native" ? identity6.file : identity6;
78912
79063
  }
@@ -78965,7 +79116,7 @@ var init_managed_store = __esm({
78965
79116
  refPattern = /^(?:attf_|att_)[0-9a-f-]{36}$/;
78966
79117
  digestPattern = /^[0-9a-f]{64}$/;
78967
79118
  error = (kind) => new Error("MANAGED_ATTACHMENT_" + kind);
78968
- digest3 = (bytes3) => createHash35("sha256").update(bytes3).digest("hex");
79119
+ digest3 = (bytes3) => createHash36("sha256").update(bytes3).digest("hex");
78969
79120
  ManagedAttachmentStore = class _ManagedAttachmentStore {
78970
79121
  constructor(contents, now, sourceFiles) {
78971
79122
  this.contents = contents;
@@ -79224,7 +79375,7 @@ var init_managed_store = __esm({
79224
79375
  await this.mutate(async () => {
79225
79376
  const entry = this.entryForUpload(threadId2, uploadId), m = entry.manifest;
79226
79377
  if (m.createdAt + HOUR <= this.now() || Object.keys(m.chunks).length !== Math.ceil(m.byteSize / 49152)) throw error("INVALID");
79227
- const h = await this.sourceHandle(entry), hash3 = createHash35("sha256");
79378
+ const h = await this.sourceHandle(entry), hash3 = createHash36("sha256");
79228
79379
  await withBinaryHandle(h, async () => {
79229
79380
  if ((await h.status()).size !== m.byteSize) throw error("INVALID");
79230
79381
  const block = Buffer.alloc(49152);
@@ -79258,7 +79409,7 @@ var init_managed_store = __esm({
79258
79409
  }
79259
79410
  if (m.createdAt + HOUR <= this.now() || Object.keys(m.chunks).length !== Math.ceil(m.byteSize / 49152)) throw error("INVALID");
79260
79411
  const h = await this.sourceHandle(entry);
79261
- const hash3 = createHash35("sha256");
79412
+ const hash3 = createHash36("sha256");
79262
79413
  await withBinaryHandle(h, async () => {
79263
79414
  const status2 = await h.status();
79264
79415
  if (status2.size !== m.byteSize) throw error("INVALID");
@@ -79442,7 +79593,7 @@ var init_managed_store = __esm({
79442
79593
  });
79443
79594
 
79444
79595
  // apps/desktop/src/daemon/runtime/attachment-storage.ts
79445
- import path43 from "node:path";
79596
+ import path44 from "node:path";
79446
79597
  import { randomUUID as randomUUID48 } from "node:crypto";
79447
79598
  var ATTACHMENT_CLEANUP_INTERVAL_MS, RuntimeAttachmentStorage;
79448
79599
  var init_attachment_storage = __esm({
@@ -79584,7 +79735,7 @@ var init_attachment_storage = __esm({
79584
79735
  requireAttachmentMessageBindings() {
79585
79736
  if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
79586
79737
  if (!this.attachmentMessageBindingsPromise) {
79587
- this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path43.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
79738
+ this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path44.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
79588
79739
  this.attachmentMessageBindings = store;
79589
79740
  return store;
79590
79741
  }).catch((error2) => {
@@ -79600,7 +79751,7 @@ var init_attachment_storage = __esm({
79600
79751
  if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
79601
79752
  if (!this.managedAttachmentStorePromise) {
79602
79753
  const opening = runManagedAttachmentOperation(() => ManagedAttachmentStore.open(
79603
- path43.join(this.ports.dataDirectory(), "attachments", "managed")
79754
+ path44.join(this.ports.dataDirectory(), "attachments", "managed")
79604
79755
  )).catch((error2) => {
79605
79756
  if (this.managedAttachmentStorePromise === opening) this.managedAttachmentStorePromise = null;
79606
79757
  throw error2;
@@ -80660,7 +80811,7 @@ var init_daemon_metrics_store = __esm({
80660
80811
  });
80661
80812
 
80662
80813
  // apps/desktop/src/daemon/daemon-metrics.ts
80663
- import os3 from "node:os";
80814
+ import os4 from "node:os";
80664
80815
  import process7 from "node:process";
80665
80816
  function roundMetric(value) {
80666
80817
  return Math.round(value * 10) / 10;
@@ -80709,7 +80860,7 @@ var init_daemon_metrics = __esm({
80709
80860
  this.nowMs = options.nowMs ?? (() => Date.now());
80710
80861
  this.cpuUsage = options.cpuUsage ?? (() => process7.cpuUsage());
80711
80862
  this.memoryUsage = options.memoryUsage ?? (() => process7.memoryUsage());
80712
- this.cpuCount = Math.max(1, options.cpuCount ?? os3.cpus().length);
80863
+ this.cpuCount = Math.max(1, options.cpuCount ?? os4.cpus().length);
80713
80864
  this.pid = options.pid ?? process7.pid;
80714
80865
  this.sampleIntervalMs = options.sampleIntervalMs ?? DAEMON_METRICS_SAMPLE_INTERVAL_MS;
80715
80866
  this.retentionMs = Math.min(options.retentionMs ?? DAEMON_METRICS_RETENTION_MS, DAEMON_METRICS_RETENTION_MS);
@@ -80962,7 +81113,7 @@ var init_control_read = __esm({
80962
81113
  });
80963
81114
 
80964
81115
  // apps/desktop/src/attachments/image-resources.ts
80965
- import { createHash as createHash36, randomUUID as randomUUID49 } from "node:crypto";
81116
+ import { createHash as createHash37, randomUUID as randomUUID49 } from "node:crypto";
80966
81117
  import { constants as constants7 } from "node:fs";
80967
81118
  import { lstat as lstat8, open as open8, realpath as realpath4 } from "node:fs/promises";
80968
81119
  import { basename as basename4, dirname as dirname4 } from "node:path";
@@ -80997,9 +81148,9 @@ function sameDeferredIdentity(source2, previous) {
80997
81148
  if (source2.kind === "history") return previous.kind === "history" && sameLocator(source2.locator, previous.locator);
80998
81149
  return source2.kind === "deferred-file" && Boolean(source2.visibilityLocator) && previous.kind !== "history" && previous.kind !== "app-server-image" && (previous.kind === "file" || source2.path === previous.path) && sameLocator(source2.visibilityLocator, previous.visibilityLocator);
80999
81150
  }
81000
- async function readSourceFile(path55, signal) {
81151
+ async function readSourceFile(path56, signal) {
81001
81152
  signal?.throwIfAborted();
81002
- const handle = await open8(path55, constants7.O_RDONLY | constants7.O_NOFOLLOW);
81153
+ const handle = await open8(path56, constants7.O_RDONLY | constants7.O_NOFOLLOW);
81003
81154
  try {
81004
81155
  const before = await handle.stat({ bigint: true });
81005
81156
  if (!before.isFile() || before.size <= 0 || before.size > MAX_BYTES9) throw new NiumaError("ATTACHMENT_RESOURCE_LIMIT", "\u56FE\u7247\u8BFB\u53D6\u8D85\u51FA\u8D44\u6E90\u9650\u5236");
@@ -81056,7 +81207,7 @@ var init_image_resources = __esm({
81056
81207
  INDEX_BYTES = 16 * 1024 * 1024;
81057
81208
  CHUNK_BYTES2 = 256 * 1024;
81058
81209
  ID = /^att_[0-9a-f-]{36}$/;
81059
- digest4 = (bytes3) => createHash36("sha256").update(bytes3).digest("hex");
81210
+ digest4 = (bytes3) => createHash37("sha256").update(bytes3).digest("hex");
81060
81211
  hashSchema = z16.string().regex(/^[0-9a-f]{64}$/);
81061
81212
  natural = z16.number().int().nonnegative();
81062
81213
  absolutePath = z16.string().max(16384).refine((value) => localResourcePaths.parseLocal(value) !== null);
@@ -81228,12 +81379,12 @@ var init_image_resources = __esm({
81228
81379
  }, JSON.stringify(identity6));
81229
81380
  }
81230
81381
  /** 仅供已认证实时消息登记;调用方每次请求仍须验证当前 item/上传暂存资格。 */
81231
- async registerDeferredFile(threadId2, path55, resourceKey = `live-file:${threadId2}:${path55}`) {
81232
- return this.register({ resourceKey, name: basename4(path55), source: { kind: "deferred-file", threadId: threadId2, path: path55 } });
81382
+ async registerDeferredFile(threadId2, path56, resourceKey = `live-file:${threadId2}:${path56}`) {
81383
+ return this.register({ resourceKey, name: basename4(path56), source: { kind: "deferred-file", threadId: threadId2, path: path56 } });
81233
81384
  }
81234
- async registerFile(threadId2, path55, attachmentId, context) {
81385
+ async registerFile(threadId2, path56, attachmentId, context) {
81235
81386
  if (context && context.visibilityLocator.threadId !== threadId2) throw missing3();
81236
- const canonical = await realpath4(path55);
81387
+ const canonical = await realpath4(path56);
81237
81388
  const file = await readSourceFile(canonical);
81238
81389
  return this.register({ attachmentId, resourceKey: context?.resourceKey ?? `file:${threadId2}:${canonical}`, name: basename4(canonical), source: {
81239
81390
  kind: "file",
@@ -81263,9 +81414,9 @@ var init_image_resources = __esm({
81263
81414
  return sameLocator(this.historyLocator(threadId2, attachmentId) ?? void 0, expectedLocator);
81264
81415
  }
81265
81416
  /** 保留原件换源时只复用相同受控文件;历史别名和旧暂存不能遮蔽新来源。 */
81266
- matchesFilePath(threadId2, attachmentId, path55) {
81417
+ matchesFilePath(threadId2, attachmentId, path56) {
81267
81418
  const entry = this.entries.get(attachmentId);
81268
- return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path === path55;
81419
+ return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path === path56;
81269
81420
  }
81270
81421
  has(threadId2, attachmentId) {
81271
81422
  const entry = this.entries.get(attachmentId);
@@ -81669,9 +81820,9 @@ var init_image_confirmation2 = __esm({
81669
81820
  });
81670
81821
 
81671
81822
  // apps/desktop/src/daemon/runtime/images.ts
81672
- import { createHash as createHash37 } from "node:crypto";
81823
+ import { createHash as createHash38 } from "node:crypto";
81673
81824
  import { realpath as realpath5 } from "node:fs/promises";
81674
- import path44 from "node:path";
81825
+ import path45 from "node:path";
81675
81826
  function objectRecord12(value) {
81676
81827
  return value && typeof value === "object" && !Array.isArray(value) ? value : {};
81677
81828
  }
@@ -81752,7 +81903,7 @@ var init_images = __esm({
81752
81903
  if (!url?.startsWith("data:image/")) continue;
81753
81904
  const resources = await this.requireImageResources();
81754
81905
  assertCurrent();
81755
- const sourceHash = createHash37("sha256").update(url).digest("hex");
81906
+ const sourceHash = createHash38("sha256").update(url).digest("hex");
81756
81907
  const registered = await resources.register({
81757
81908
  resourceKey: `app-server:${threadId2}:${turn.id}:${item.id}:${partIndex}:${sourceHash}`,
81758
81909
  name: "\u56FE\u7247",
@@ -81771,7 +81922,7 @@ var init_images = __esm({
81771
81922
  }
81772
81923
  localImageKey(threadId2, sourcePath, itemId, partIndex) {
81773
81924
  const embedded = sourcePath.startsWith("data:image/");
81774
- const source2 = embedded ? createHash37("sha256").update(sourcePath).digest("hex") : sourcePath;
81925
+ const source2 = embedded ? createHash38("sha256").update(sourcePath).digest("hex") : sourcePath;
81775
81926
  return `${threadId2}\0${itemId ? JSON.stringify(embedded ? [itemId, partIndex, source2] : [itemId, partIndex ?? source2]) : source2}`;
81776
81927
  }
81777
81928
  resolveKnownLocalImage(threadId2, sourcePath, itemId, partIndex) {
@@ -81790,7 +81941,7 @@ var init_images = __esm({
81790
81941
  if (itemId && ["userMessage", "UserMessage", "user_message"].includes(String(item.type))) {
81791
81942
  if (Array.isArray(item.content)) item.content.forEach((part, index) => {
81792
81943
  const input = objectRecord12(part);
81793
- if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" && path44.isAbsolute(input.path)) registrations.push(this.importThreadImage(threadId2, input.path, itemId, index));
81944
+ if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" && path45.isAbsolute(input.path)) registrations.push(this.importThreadImage(threadId2, input.path, itemId, index));
81794
81945
  const url = input.type === "image" ? nonEmptyString19(input.url ?? input.image_url) : null;
81795
81946
  if (url?.startsWith("data:image/")) registrations.push(this.importThreadImage(threadId2, url, itemId, index));
81796
81947
  });
@@ -81814,7 +81965,7 @@ var init_images = __esm({
81814
81965
  requireImageResources() {
81815
81966
  if (!this.ports.attachmentReady()) throw new Error("\u56FE\u7247\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
81816
81967
  if (!this.imageResourcesPromise) this.imageResourcesPromise = ImageResources.create({
81817
- indexPath: path44.join(this.ports.dataDirectory(), "image-resources", "index.json"),
81968
+ indexPath: path45.join(this.ports.dataDirectory(), "image-resources", "index.json"),
81818
81969
  readAppServerImage: (source2, signal) => this.readAppServerImage(source2, signal),
81819
81970
  onDiagnostic: (event) => this.ports.diagnostic(event)
81820
81971
  }).catch((error2) => {
@@ -81851,7 +82002,7 @@ var init_images = __esm({
81851
82002
  const items = source2.turnId !== void 0 && turns.length !== 1 ? [] : turns.flatMap((turn) => Array.isArray(turn.items) ? turn.items.map(objectRecord12).filter((item) => item.id === source2.itemId && item.type === "userMessage") : []);
81852
82003
  const part = objectRecord12(items.length === 1 && Array.isArray(items[0].content) ? items[0].content[source2.partIndex] : null);
81853
82004
  const url = part.type === "image" ? nonEmptyString19(part.url ?? part.image_url) : null;
81854
- if (!url || url.length > Math.ceil(20 * 1024 * 1024 / 3) * 4 + 64 || createHash37("sha256").update(url).digest("hex") !== source2.sourceHash) {
82005
+ if (!url || url.length > Math.ceil(20 * 1024 * 1024 / 3) * 4 + 64 || createHash38("sha256").update(url).digest("hex") !== source2.sourceHash) {
81855
82006
  throw new NiumaError("ATTACHMENT_VERSION_CHANGED", "\u56FE\u7247\u7248\u672C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u52A0\u8F7D");
81856
82007
  }
81857
82008
  const match = /^data:image\/(?:png|jpeg|webp|gif);base64,([A-Za-z0-9+/]+={0,2})$/.exec(url);
@@ -81995,7 +82146,7 @@ var init_images = __esm({
81995
82146
  /** 同一消息引用共享轻量登记;整个 Runtime 最多同时处理四个索引写入。 */
81996
82147
  importThreadImage(threadId2, sourcePath, itemId, partIndex, sourceIsCurrent = () => true) {
81997
82148
  const embedded = sourcePath.startsWith("data:image/") && Number.isSafeInteger(partIndex) && partIndex >= 0;
81998
- if (!itemId || !path44.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
82149
+ if (!itemId || !path45.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
81999
82150
  const generation = this.ports.generation();
82000
82151
  const key = this.localImageKey(threadId2, sourcePath, itemId, partIndex);
82001
82152
  const routeGeneration = this.ports.controlGeneration(threadId2);
@@ -82026,13 +82177,13 @@ var init_images = __esm({
82026
82177
  threadId: threadId2,
82027
82178
  itemId,
82028
82179
  partIndex,
82029
- sourceHash: createHash37("sha256").update(sourcePath).digest("hex")
82180
+ sourceHash: createHash38("sha256").update(sourcePath).digest("hex")
82030
82181
  } }) : await resources.registerDeferredFile(threadId2, sourcePath, `live:${key}`);
82031
82182
  if (!current2()) return;
82032
82183
  this.knownLocalImages.set(key, {
82033
82184
  type: "image",
82034
82185
  attachmentId: registered.attachmentId,
82035
- name: embedded ? "\u56FE\u7247" : path44.basename(sourcePath),
82186
+ name: embedded ? "\u56FE\u7247" : path45.basename(sourcePath),
82036
82187
  previewAvailable: false,
82037
82188
  previewState: "deferred"
82038
82189
  });
@@ -84118,18 +84269,18 @@ var init_session_sources = __esm({
84118
84269
  const isCurrent = () => options.isCurrent?.() !== false;
84119
84270
  const paths = /* @__PURE__ */ new Map();
84120
84271
  for (const thread4 of threads) {
84121
- const path55 = typeof thread4.path === "string" && thread4.path.length > 0 ? thread4.path : null;
84122
- if (!paths.has(thread4.id)) paths.set(thread4.id, path55);
84123
- else if (paths.get(thread4.id) !== path55) paths.set(thread4.id, void 0);
84272
+ const path56 = typeof thread4.path === "string" && thread4.path.length > 0 ? thread4.path : null;
84273
+ if (!paths.has(thread4.id)) paths.set(thread4.id, path56);
84274
+ else if (paths.get(thread4.id) !== path56) paths.set(thread4.id, void 0);
84124
84275
  }
84125
- for (const [id5, path55] of paths) {
84276
+ for (const [id5, path56] of paths) {
84126
84277
  const thread4 = { id: id5 };
84127
84278
  if (!isCurrent()) return;
84128
84279
  const token3 = this.begin(thread4.id);
84129
84280
  let resolution = null;
84130
84281
  if (resolver) {
84131
84282
  try {
84132
- resolution = await resolver.resolve(thread4.id, path55);
84283
+ resolution = await resolver.resolve(thread4.id, path56);
84133
84284
  } catch {
84134
84285
  resolution = null;
84135
84286
  }
@@ -84194,7 +84345,7 @@ var init_session_sources = __esm({
84194
84345
  });
84195
84346
 
84196
84347
  // apps/desktop/src/daemon/runtime/settings-selection.ts
84197
- import path45 from "node:path";
84348
+ import path46 from "node:path";
84198
84349
  var RuntimeSettingsSelection;
84199
84350
  var init_settings_selection = __esm({
84200
84351
  "apps/desktop/src/daemon/runtime/settings-selection.ts"() {
@@ -84210,7 +84361,7 @@ var init_settings_selection = __esm({
84210
84361
  ports;
84211
84362
  targetProjectRoot(cwd) {
84212
84363
  const matched = this.ports.projectRoots().filter((projectRoot) => pathBelongsToProjectRoot(projectRoot, cwd)).sort((left, right) => right.length - left.length)[0];
84213
- return matched ?? path45.normalize(cwd);
84364
+ return matched ?? path46.normalize(cwd);
84214
84365
  }
84215
84366
  inheritedCreate(threadId2) {
84216
84367
  const empty = { authorization: null, model: null };
@@ -84428,7 +84579,7 @@ var init_thread_routing = __esm({
84428
84579
  });
84429
84580
 
84430
84581
  // apps/desktop/src/platform/computer-name.ts
84431
- import os4 from "node:os";
84582
+ import os5 from "node:os";
84432
84583
  import { execFileSync as execFileSync3 } from "node:child_process";
84433
84584
  function systemComputerName() {
84434
84585
  if (desktopPlatform().id === "macos") {
@@ -84443,10 +84594,10 @@ function systemComputerName() {
84443
84594
  } catch {
84444
84595
  }
84445
84596
  }
84446
- return os4.hostname();
84597
+ return os5.hostname();
84447
84598
  }
84448
84599
  function systemHostname() {
84449
- return os4.hostname();
84600
+ return os5.hostname();
84450
84601
  }
84451
84602
  var init_computer_name = __esm({
84452
84603
  "apps/desktop/src/platform/computer-name.ts"() {
@@ -84554,7 +84705,7 @@ var init_device_name = __esm({
84554
84705
  });
84555
84706
 
84556
84707
  // apps/desktop/src/daemon/debug-log.ts
84557
- import path46 from "node:path";
84708
+ import path47 from "node:path";
84558
84709
  function isNotificationDeliveryReason(value) {
84559
84710
  return NOTIFICATION_DELIVERY_REASON_CODES.has(value) || /^http_[1-5]\d\d$/.test(value) || /^business_\d{1,6}$/.test(value);
84560
84711
  }
@@ -84593,10 +84744,10 @@ function hasDebugFilter(filter) {
84593
84744
  return Boolean(filter?.components || filter?.channels || filter?.events);
84594
84745
  }
84595
84746
  function createSafeFilePath(runtimeDir, files) {
84596
- const dir = path46.join(runtimeDir, "debug");
84747
+ const dir = path47.join(runtimeDir, "debug");
84597
84748
  files.ensureDirectory(dir);
84598
84749
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
84599
- return path46.join(dir, `${timestamp}-${process.pid}.ndjson`);
84750
+ return path47.join(dir, `${timestamp}-${process.pid}.ndjson`);
84600
84751
  }
84601
84752
  function createFileDebugLogger(filePath, shouldWrite, files) {
84602
84753
  let writer;
@@ -85202,7 +85353,7 @@ function withoutPersistentImageBytes(value, key = "", seen = /* @__PURE__ */ new
85202
85353
  function createFileRawDebugLogger(runtimeDir, filter, policy, files) {
85203
85354
  const now = policy.now ?? (() => /* @__PURE__ */ new Date());
85204
85355
  const manager = new RawDebugFileManager(
85205
- path46.join(runtimeDir, "debug"),
85356
+ path47.join(runtimeDir, "debug"),
85206
85357
  now,
85207
85358
  policy.maxSegmentBytes ?? RAW_DEBUG_MAX_SEGMENT_BYTES,
85208
85359
  policy.maxSegments ?? RAW_DEBUG_MAX_SEGMENTS,
@@ -86213,7 +86364,7 @@ var init_debug_log = __esm({
86213
86364
  }
86214
86365
  const timestamp = this.now().toISOString().replace(/[:.]/g, "-");
86215
86366
  for (; ; ) {
86216
- const filePath = path46.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
86367
+ const filePath = path47.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
86217
86368
  try {
86218
86369
  return this.files.create(filePath);
86219
86370
  } catch (error2) {
@@ -86246,7 +86397,7 @@ var init_debug_log = __esm({
86246
86397
  });
86247
86398
 
86248
86399
  // apps/desktop/src/daemon/control-observability.ts
86249
- import path47 from "node:path";
86400
+ import path48 from "node:path";
86250
86401
  function isRecentControlTimestamp(timestampMs, nowMs) {
86251
86402
  return timestampMs <= nowMs && isRetainedDaemonLogTimestamp(timestampMs, nowMs);
86252
86403
  }
@@ -86279,7 +86430,7 @@ function page3(values, params) {
86279
86430
  };
86280
86431
  }
86281
86432
  function listControlLogs(input) {
86282
- const directoryPath = path47.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
86433
+ const directoryPath = path48.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
86283
86434
  const values = [];
86284
86435
  let totalBytes = 0;
86285
86436
  let processedLines = 0;
@@ -87302,7 +87453,7 @@ var init_composition = __esm({
87302
87453
  refreshFallback: async (id5, token3) => {
87303
87454
  await this.historySnapshot.tryRefreshThreadMessages(id5, false, { kind: "fallback", token: token3 });
87304
87455
  },
87305
- resolveKnownLocalImage: (id5, path55, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path55, itemId, partIndex),
87456
+ resolveKnownLocalImage: (id5, path56, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path56, itemId, partIndex),
87306
87457
  hasDesktopSnapshot: (id5) => this.controlAccess.snapshot(id5).hasCurrentDesktopSnapshot,
87307
87458
  followerPhase: (id5) => this.followerCoordination.activeThreadFollowerCoordinatorValue?.phaseFor(id5) ?? null,
87308
87459
  generation: () => this.lifecycle.runtimeGenerationValue
@@ -88898,7 +89049,7 @@ var init_runtime2 = __esm({
88898
89049
 
88899
89050
  // apps/desktop/src/daemon/follower-open-trace.ts
88900
89051
  import { randomUUID as randomUUID51 } from "node:crypto";
88901
- import path48 from "node:path";
89052
+ import path49 from "node:path";
88902
89053
  function isFiniteTimestamp2(value) {
88903
89054
  return typeof value === "number" && Number.isFinite(value) && Number.isSafeInteger(value);
88904
89055
  }
@@ -89036,7 +89187,7 @@ function parseRecord2(line) {
89036
89187
  function listPrivateTraceFiles(runtimeDir, storage) {
89037
89188
  try {
89038
89189
  storage.checkDirectory(runtimeDir);
89039
- const scan = storage.scan(path48.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
89190
+ const scan = storage.scan(path49.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
89040
89191
  const files = [];
89041
89192
  let incomplete = scan.truncated;
89042
89193
  for (const entry of scan.entries) {
@@ -89050,8 +89201,8 @@ function listPrivateTraceFiles(runtimeDir, storage) {
89050
89201
  }
89051
89202
  }
89052
89203
  function compareTraceFilePaths(left, right) {
89053
- const a = path48.basename(left);
89054
- const b = path48.basename(right);
89204
+ const a = path49.basename(left);
89205
+ const b = path49.basename(right);
89055
89206
  return a.slice(0, 10).localeCompare(b.slice(0, 10)) || Number(a.slice(11, -7)) - Number(b.slice(11, -7));
89056
89207
  }
89057
89208
  function readPrivateTraceFile(file, remainingBytes, storage) {
@@ -89568,7 +89719,7 @@ var init_follower_open_trace = __esm({
89568
89719
  }
89569
89720
  clearAll() {
89570
89721
  try {
89571
- const directoryPath = path48.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89722
+ const directoryPath = path49.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89572
89723
  this.files.checkDirectory(this.runtimeDir);
89573
89724
  let scan;
89574
89725
  try {
@@ -89625,7 +89776,7 @@ var init_follower_open_trace = __esm({
89625
89776
  }
89626
89777
  }
89627
89778
  append(record26) {
89628
- const directoryPath = path48.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89779
+ const directoryPath = path49.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
89629
89780
  this.ensureTraceDirectory(directoryPath);
89630
89781
  const content2 = `${JSON.stringify(record26)}
89631
89782
  `;
@@ -89635,8 +89786,8 @@ var init_follower_open_trace = __esm({
89635
89786
  selectAppendFile(directoryPath, dateName, bytes3) {
89636
89787
  const date = dateName.slice(0, 10);
89637
89788
  let filePath = this.appendFilePath;
89638
- if (!filePath || path48.basename(filePath).slice(0, 10) !== date) {
89639
- filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ?? path48.join(directoryPath, dateName);
89789
+ if (!filePath || path49.basename(filePath).slice(0, 10) !== date) {
89790
+ filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ?? path49.join(directoryPath, dateName);
89640
89791
  }
89641
89792
  for (let attempt = 0; attempt < MAX_DIRECTORY_ENTRIES3; attempt += 1) {
89642
89793
  let stats;
@@ -89649,9 +89800,9 @@ var init_follower_open_trace = __esm({
89649
89800
  this.appendFilePath = filePath;
89650
89801
  return filePath;
89651
89802
  }
89652
- const next = Number(path48.basename(filePath).slice(11, -7)) + 1;
89803
+ const next = Number(path49.basename(filePath).slice(11, -7)) + 1;
89653
89804
  if (next > 999999) break;
89654
- filePath = path48.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
89805
+ filePath = path49.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
89655
89806
  }
89656
89807
  throw new Error("trace segment limit reached");
89657
89808
  }
@@ -89823,7 +89974,7 @@ var init_local_gateway_supervisor = __esm({
89823
89974
  });
89824
89975
 
89825
89976
  // apps/desktop/src/daemon/async-input-notification-store.ts
89826
- import { createHash as createHash38 } from "node:crypto";
89977
+ import { createHash as createHash39 } from "node:crypto";
89827
89978
  import { z as z17 } from "zod";
89828
89979
  var ASYNC_INPUT_NOTIFICATION_MAX_BYTES, identityText, entrySchema2, documentSchema2, AsyncInputNotificationStore;
89829
89980
  var init_async_input_notification_store = __esm({
@@ -89891,7 +90042,7 @@ var init_async_input_notification_store = __esm({
89891
90042
  const { threadId: threadId2, turnId, rawQuestionId } = identity6;
89892
90043
  return this.run(async () => {
89893
90044
  for (const value of [threadId2, turnId, rawQuestionId]) identityText.parse(value);
89894
- const key = createHash38("sha256").update(JSON.stringify([threadId2, turnId, rawQuestionId])).digest("hex");
90045
+ const key = createHash39("sha256").update(JSON.stringify([threadId2, turnId, rawQuestionId])).digest("hex");
89895
90046
  if (this.document.entries.some((entry) => entry.key === key)) return null;
89896
90047
  await this.persist({ version: 1, entries: [...this.document.entries, { key, threadId: threadId2, turnId, stage: "admitted" }] });
89897
90048
  return key;
@@ -91026,7 +91177,7 @@ var init_watch = __esm({
91026
91177
  });
91027
91178
 
91028
91179
  // apps/desktop/src/relay/relay-origin-store.ts
91029
- import path49 from "node:path";
91180
+ import path50 from "node:path";
91030
91181
  function parseStoredOrigin(value) {
91031
91182
  try {
91032
91183
  const document = JSON.parse(value);
@@ -91040,7 +91191,7 @@ function parseStoredOrigin(value) {
91040
91191
  }
91041
91192
  }
91042
91193
  function resolveDefaultRelayOriginStorePath() {
91043
- return path49.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
91194
+ return path50.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
91044
91195
  }
91045
91196
  var DEFAULT_FILE_NAME2, MAX_FILE_BYTES3, FileRelayOriginStore;
91046
91197
  var init_relay_origin_store = __esm({
@@ -91056,7 +91207,7 @@ var init_relay_origin_store = __esm({
91056
91207
  files;
91057
91208
  tail = Promise.resolve();
91058
91209
  constructor(options = {}) {
91059
- this.filePath = path49.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
91210
+ this.filePath = path50.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
91060
91211
  this.files = options.files ?? privateDocumentFiles;
91061
91212
  }
91062
91213
  async load() {
@@ -91092,7 +91243,7 @@ var init_relay_origin_store = __esm({
91092
91243
  });
91093
91244
 
91094
91245
  // apps/desktop/src/cli/commands/daemon.ts
91095
- import path50 from "node:path";
91246
+ import path51 from "node:path";
91096
91247
  function daemonStartFailed3() {
91097
91248
  return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
91098
91249
  }
@@ -91276,7 +91427,7 @@ async function runDaemonCommand(args, options = {}) {
91276
91427
  loggers.rawDebugLogger?.path,
91277
91428
  loggers.errorLogger?.path,
91278
91429
  // 后台 worker 的 stdout/stderr descriptor 无法安全重开,只按 daemon 所有权保护固定路径。
91279
- ...options.mode === "background" ? [path50.join(runtimeDir, "daemon-worker.log")] : []
91430
+ ...options.mode === "background" ? [path51.join(runtimeDir, "daemon-worker.log")] : []
91280
91431
  ].filter((filePath) => typeof filePath === "string")
91281
91432
  });
91282
91433
  } catch {
@@ -91735,7 +91886,7 @@ var init_auth2 = __esm({
91735
91886
  });
91736
91887
 
91737
91888
  // apps/desktop/src/control/routes.ts
91738
- import fs27 from "node:fs";
91889
+ import fs28 from "node:fs";
91739
91890
  function daemonStoppedOverview() {
91740
91891
  return {
91741
91892
  daemon: { state: "stopped" },
@@ -91754,12 +91905,12 @@ function emptyControlPage(page4, pageSize) {
91754
91905
  }
91755
91906
  function isDaemonRuntimeActive(socketPath = daemonSocketPath(), statusPath = daemonStatusPath()) {
91756
91907
  try {
91757
- const socket = fs27.lstatSync(socketPath);
91758
- const status2 = fs27.lstatSync(statusPath);
91908
+ const socket = fs28.lstatSync(socketPath);
91909
+ const status2 = fs28.lstatSync(statusPath);
91759
91910
  if (!socket.isSocket() || !status2.isFile() || status2.isSymbolicLink() || status2.size > 4 * 1024) {
91760
91911
  return false;
91761
91912
  }
91762
- const parsed = JSON.parse(fs27.readFileSync(statusPath, "utf8"));
91913
+ const parsed = JSON.parse(fs28.readFileSync(statusPath, "utf8"));
91763
91914
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || parsed.socketPath !== socketPath || !Number.isSafeInteger(parsed.pid) || parsed.pid <= 0) return false;
91764
91915
  process.kill(parsed.pid, 0);
91765
91916
  return true;
@@ -93312,8 +93463,8 @@ var init_lifecycle2 = __esm({
93312
93463
 
93313
93464
  // apps/desktop/src/control/server.ts
93314
93465
  import http4 from "node:http";
93315
- import fs28 from "node:fs";
93316
- import path51 from "node:path";
93466
+ import fs29 from "node:fs";
93467
+ import path52 from "node:path";
93317
93468
  import { createRequire as createRequire2 } from "node:module";
93318
93469
  function isControlApiPath(pathname) {
93319
93470
  const [, api, version2, control] = pathname.split("/", 4);
@@ -93359,15 +93510,15 @@ function requestHasBody(request2) {
93359
93510
  return Number(contentLength) !== 0;
93360
93511
  }
93361
93512
  function resolveExactControlWritePath(requestTarget) {
93362
- for (const path55 of [CONTROL_DEVICE_REVOKE_PATH, CONTROL_DAEMON_ACTION_PATH, CONTROL_TRACE_CLEAR_PATH]) {
93363
- if (requestTarget === path55 || requestTarget.startsWith(`${path55}?`) && !requestTarget.includes("#")) return path55;
93513
+ for (const path56 of [CONTROL_DEVICE_REVOKE_PATH, CONTROL_DAEMON_ACTION_PATH, CONTROL_TRACE_CLEAR_PATH]) {
93514
+ if (requestTarget === path56 || requestTarget.startsWith(`${path56}?`) && !requestTarget.includes("#")) return path56;
93364
93515
  }
93365
93516
  return null;
93366
93517
  }
93367
93518
  function resolveExactControlTraceReadPath(requestTarget) {
93368
- for (const path55 of [CONTROL_TRACE_LIST_PATH, CONTROL_TRACE_DETAIL_PATH]) {
93369
- if (requestTarget === path55 || requestTarget.startsWith(`${path55}?`) && !requestTarget.includes("#")) {
93370
- return path55;
93519
+ for (const path56 of [CONTROL_TRACE_LIST_PATH, CONTROL_TRACE_DETAIL_PATH]) {
93520
+ if (requestTarget === path56 || requestTarget.startsWith(`${path56}?`) && !requestTarget.includes("#")) {
93521
+ return path56;
93371
93522
  }
93372
93523
  }
93373
93524
  return null;
@@ -93388,9 +93539,9 @@ var init_server5 = __esm({
93388
93539
  init_lifecycle2();
93389
93540
  require2 = createRequire2(import.meta.url);
93390
93541
  CONTROL_PAGE_PATHS = ["/", "/connections", "/sessions", "/subscriptions", "/turn-audit", "/logs"];
93391
- CONTROL_INDEX = fs28.readFileSync(desktopAssetUrl("control", "index.html"));
93392
- BOOTSTRAP_CSS = fs28.readFileSync(require2.resolve("bootstrap/dist/css/bootstrap.min.css"));
93393
- BOOTSTRAP_BUNDLE = fs28.readFileSync(require2.resolve("bootstrap/dist/js/bootstrap.bundle.min.js"));
93542
+ CONTROL_INDEX = fs29.readFileSync(desktopAssetUrl("control", "index.html"));
93543
+ BOOTSTRAP_CSS = fs29.readFileSync(require2.resolve("bootstrap/dist/css/bootstrap.min.css"));
93544
+ BOOTSTRAP_BUNDLE = fs29.readFileSync(require2.resolve("bootstrap/dist/js/bootstrap.bundle.min.js"));
93394
93545
  STATIC_ASSETS = Object.freeze({
93395
93546
  ...Object.fromEntries(CONTROL_PAGE_PATHS.map((pathname) => [pathname, {
93396
93547
  contentType: "text/html; charset=utf-8",
@@ -93398,11 +93549,11 @@ var init_server5 = __esm({
93398
93549
  }])),
93399
93550
  "/app.js": {
93400
93551
  contentType: "application/javascript; charset=utf-8",
93401
- body: fs28.readFileSync(desktopAssetUrl("control", "app.js"))
93552
+ body: fs29.readFileSync(desktopAssetUrl("control", "app.js"))
93402
93553
  },
93403
93554
  "/chart.umd.js": {
93404
93555
  contentType: "application/javascript; charset=utf-8",
93405
- body: fs28.readFileSync(path51.join(path51.dirname(require2.resolve("chart.js")), "chart.umd.js"))
93556
+ body: fs29.readFileSync(path52.join(path52.dirname(require2.resolve("chart.js")), "chart.umd.js"))
93406
93557
  },
93407
93558
  "/bootstrap.min.css": {
93408
93559
  contentType: "text/css; charset=utf-8",
@@ -93617,42 +93768,42 @@ var init_server5 = __esm({
93617
93768
  });
93618
93769
 
93619
93770
  // apps/desktop/src/control/state.ts
93620
- import { createHash as createHash39, randomUUID as randomUUID55 } from "node:crypto";
93621
- import fs29 from "node:fs";
93622
- import path52 from "node:path";
93771
+ import { createHash as createHash40, randomUUID as randomUUID55 } from "node:crypto";
93772
+ import fs30 from "node:fs";
93773
+ import path53 from "node:path";
93623
93774
  function createControlState(input) {
93624
93775
  return createControlStateUnlocked(input);
93625
93776
  }
93626
93777
  function createControlStateUnlocked(input) {
93627
93778
  const state = toControlState(input);
93628
93779
  const statePath = controlStatePath(input.runtimeDir);
93629
- const temporaryPath = path52.join(
93630
- path52.dirname(statePath),
93631
- `.${path52.basename(statePath)}.${randomUUID55()}.tmp`
93780
+ const temporaryPath = path53.join(
93781
+ path53.dirname(statePath),
93782
+ `.${path53.basename(statePath)}.${randomUUID55()}.tmp`
93632
93783
  );
93633
93784
  let descriptor = null;
93634
93785
  let temporaryIdentity = null;
93635
93786
  let published = null;
93636
93787
  let operationError;
93637
93788
  try {
93638
- descriptor = fs29.openSync(temporaryPath, "wx", 384);
93639
- if (process.platform !== "win32") fs29.fchmodSync(descriptor, 384);
93640
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93789
+ descriptor = fs30.openSync(temporaryPath, "wx", 384);
93790
+ if (process.platform !== "win32") fs30.fchmodSync(descriptor, 384);
93791
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93641
93792
  assertRegularControlStateDescriptor(stats);
93642
93793
  temporaryIdentity = identityFromStats(stats);
93643
- fs29.writeFileSync(descriptor, `${JSON.stringify(state)}
93794
+ fs30.writeFileSync(descriptor, `${JSON.stringify(state)}
93644
93795
  `, "utf8");
93645
- fs29.fsyncSync(descriptor);
93646
- fs29.closeSync(descriptor);
93796
+ fs30.fsyncSync(descriptor);
93797
+ fs30.closeSync(descriptor);
93647
93798
  descriptor = null;
93648
- fs29.linkSync(temporaryPath, statePath);
93799
+ fs30.linkSync(temporaryPath, statePath);
93649
93800
  published = persistedControlState(state, statePath, identityFromStats(stats), "canonical");
93650
93801
  } catch (error2) {
93651
93802
  operationError = error2;
93652
93803
  } finally {
93653
93804
  if (descriptor !== null) {
93654
93805
  try {
93655
- fs29.closeSync(descriptor);
93806
+ fs30.closeSync(descriptor);
93656
93807
  } catch (error2) {
93657
93808
  operationError ??= error2;
93658
93809
  }
@@ -93675,7 +93826,7 @@ function createControlStateUnlocked(input) {
93675
93826
  return published;
93676
93827
  }
93677
93828
  function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
93678
- const stateBasename = path52.basename(controlStatePath(runtimeDir));
93829
+ const stateBasename = path53.basename(controlStatePath(runtimeDir));
93679
93830
  const artifactPattern = new RegExp(
93680
93831
  `^\\.${escapeRegExp(stateBasename)}(?:\\.coordination\\.lock)?\\.[0-9a-f-]+\\.(?:tmp|snapshot)$`,
93681
93832
  "u"
@@ -93683,19 +93834,19 @@ function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
93683
93834
  let removed = 0;
93684
93835
  let entries;
93685
93836
  try {
93686
- entries = fs29.readdirSync(runtimeDir);
93837
+ entries = fs30.readdirSync(runtimeDir);
93687
93838
  } catch {
93688
93839
  return 0;
93689
93840
  }
93690
93841
  for (const entry of entries) {
93691
93842
  if (entry !== `${stateBasename}.coordination.lock` && !artifactPattern.test(entry)) continue;
93692
- const artifactPath = path52.join(runtimeDir, entry);
93843
+ const artifactPath = path53.join(runtimeDir, entry);
93693
93844
  try {
93694
- const stats = fs29.lstatSync(artifactPath, { bigint: true });
93845
+ const stats = fs30.lstatSync(artifactPath, { bigint: true });
93695
93846
  if (!stats.isFile() || stats.isSymbolicLink() || process.platform !== "win32" && (stats.mode & 0o777n) !== 0o600n) {
93696
93847
  continue;
93697
93848
  }
93698
- fs29.unlinkSync(artifactPath);
93849
+ fs30.unlinkSync(artifactPath);
93699
93850
  removed += 1;
93700
93851
  } catch {
93701
93852
  }
@@ -93733,7 +93884,7 @@ function removeControlStateUnlocked(input) {
93733
93884
  if (input.expected.path !== statePath) return false;
93734
93885
  const snapshotPath = stateSnapshotPath(statePath);
93735
93886
  try {
93736
- fs29.linkSync(statePath, snapshotPath);
93887
+ fs30.linkSync(statePath, snapshotPath);
93737
93888
  } catch (error2) {
93738
93889
  if (error2.code === "ENOENT") return false;
93739
93890
  return false;
@@ -93752,7 +93903,7 @@ function removeControlStateUnlocked(input) {
93752
93903
  return false;
93753
93904
  }
93754
93905
  if (!canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2)) return false;
93755
- fs29.unlinkSync(statePath);
93906
+ fs30.unlinkSync(statePath);
93756
93907
  canonicalRemoved = true;
93757
93908
  return true;
93758
93909
  } catch {
@@ -93770,7 +93921,7 @@ function removeControlStateUnlocked(input) {
93770
93921
  function readControlStateAtPath(filePath, logicalPath) {
93771
93922
  const descriptor = openControlStateForRead(filePath);
93772
93923
  try {
93773
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93924
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93774
93925
  assertRegularControlStateDescriptor(stats);
93775
93926
  assertPrivateControlStateMode(stats);
93776
93927
  if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
@@ -93785,14 +93936,14 @@ function readControlStateAtPath(filePath, logicalPath) {
93785
93936
  throw new CorruptControlStateError(logicalPath, identity6, contents);
93786
93937
  }
93787
93938
  } finally {
93788
- fs29.closeSync(descriptor);
93939
+ fs30.closeSync(descriptor);
93789
93940
  }
93790
93941
  }
93791
93942
  function readBoundedControlState(descriptor) {
93792
93943
  const buffer = Buffer.alloc(CONTROL_STATE_MAX_BYTES + 1);
93793
93944
  let bytesRead = 0;
93794
93945
  while (bytesRead < buffer.length) {
93795
- const count = fs29.readSync(
93946
+ const count = fs30.readSync(
93796
93947
  descriptor,
93797
93948
  buffer,
93798
93949
  bytesRead,
@@ -93811,12 +93962,12 @@ function removeCorruptControlState(error2) {
93811
93962
  const snapshotPath = stateSnapshotPath(error2.statePath);
93812
93963
  let canonicalRemoved = false;
93813
93964
  try {
93814
- fs29.linkSync(error2.statePath, snapshotPath);
93965
+ fs30.linkSync(error2.statePath, snapshotPath);
93815
93966
  } catch {
93816
93967
  return false;
93817
93968
  }
93818
93969
  try {
93819
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
93970
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93820
93971
  if (!snapshotStats.isFile()) return false;
93821
93972
  const snapshotIdentity = identityFromStats(snapshotStats);
93822
93973
  if (hasUsableInode(error2.fileIdentity) && hasUsableInode(snapshotIdentity) && !sameIdentity(error2.fileIdentity, snapshotIdentity)) {
@@ -93827,7 +93978,7 @@ function removeCorruptControlState(error2) {
93827
93978
  if (fingerprint(snapshot2) !== error2.fingerprint) return false;
93828
93979
  }
93829
93980
  if (!canonicalMatchesSnapshotByIdentity(error2.statePath, snapshotPath)) return false;
93830
- fs29.unlinkSync(error2.statePath);
93981
+ fs30.unlinkSync(error2.statePath);
93831
93982
  canonicalRemoved = true;
93832
93983
  return true;
93833
93984
  } catch {
@@ -93843,7 +93994,7 @@ function removeCorruptControlState(error2) {
93843
93994
  function readRawControlState(filePath) {
93844
93995
  const descriptor = openControlStateForRead(filePath);
93845
93996
  try {
93846
- const stats = fs29.fstatSync(descriptor, { bigint: true });
93997
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93847
93998
  assertRegularControlStateDescriptor(stats);
93848
93999
  assertPrivateControlStateMode(stats);
93849
94000
  if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
@@ -93851,13 +94002,13 @@ function readRawControlState(filePath) {
93851
94002
  }
93852
94003
  return readBoundedControlState(descriptor);
93853
94004
  } finally {
93854
- fs29.closeSync(descriptor);
94005
+ fs30.closeSync(descriptor);
93855
94006
  }
93856
94007
  }
93857
94008
  function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
93858
94009
  if (!canonicalMatchesSnapshotByIdentity(statePath, snapshotPath)) return false;
93859
- const canonicalStats = fs29.lstatSync(statePath, { bigint: true });
93860
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
94010
+ const canonicalStats = fs30.lstatSync(statePath, { bigint: true });
94011
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93861
94012
  if (hasUsableInode(identityFromStats(canonicalStats)) && hasUsableInode(identityFromStats(snapshotStats))) {
93862
94013
  return true;
93863
94014
  }
@@ -93865,8 +94016,8 @@ function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
93865
94016
  return current2.pid === snapshot2.pid && current2.ownershipSecret === snapshot2.ownershipSecret;
93866
94017
  }
93867
94018
  function canonicalMatchesSnapshotByIdentity(statePath, snapshotPath) {
93868
- const canonicalStats = fs29.lstatSync(statePath, { bigint: true });
93869
- const snapshotStats = fs29.lstatSync(snapshotPath, { bigint: true });
94019
+ const canonicalStats = fs30.lstatSync(statePath, { bigint: true });
94020
+ const snapshotStats = fs30.lstatSync(snapshotPath, { bigint: true });
93870
94021
  if (!canonicalStats.isFile() || !snapshotStats.isFile()) return false;
93871
94022
  const canonicalIdentity = identityFromStats(canonicalStats);
93872
94023
  const snapshotIdentity = identityFromStats(snapshotStats);
@@ -93897,20 +94048,20 @@ function sameIdentity(left, right) {
93897
94048
  return left.device === right.device && left.inode === right.inode;
93898
94049
  }
93899
94050
  function stateSnapshotPath(statePath) {
93900
- return path52.join(
93901
- path52.dirname(statePath),
93902
- `.${path52.basename(statePath)}.${randomUUID55()}.snapshot`
94051
+ return path53.join(
94052
+ path53.dirname(statePath),
94053
+ `.${path53.basename(statePath)}.${randomUUID55()}.snapshot`
93903
94054
  );
93904
94055
  }
93905
94056
  function fingerprint(contents) {
93906
- return createHash39("sha256").update(contents).digest("hex");
94057
+ return createHash40("sha256").update(contents).digest("hex");
93907
94058
  }
93908
94059
  function escapeRegExp(value) {
93909
94060
  return value.replace(/[.*+?^${}()|[\]\\]/gu, "\\$&");
93910
94061
  }
93911
94062
  function unlinkControlStateTemporary(temporaryPath) {
93912
94063
  try {
93913
- fs29.unlinkSync(temporaryPath);
94064
+ fs30.unlinkSync(temporaryPath);
93914
94065
  return void 0;
93915
94066
  } catch (error2) {
93916
94067
  return error2.code === "ENOENT" ? void 0 : error2;
@@ -93922,28 +94073,28 @@ function eraseControlStateTemporary(temporaryPath, expectedIdentity) {
93922
94073
  try {
93923
94074
  let beforeIdentity = null;
93924
94075
  if (process.platform === "win32") {
93925
- const before = fs29.lstatSync(temporaryPath, { bigint: true });
94076
+ const before = fs30.lstatSync(temporaryPath, { bigint: true });
93926
94077
  beforeIdentity = identityFromStats(before);
93927
94078
  if (!before.isFile() || before.isSymbolicLink() || !hasUsableInode(beforeIdentity) || !sameIdentity(beforeIdentity, expectedIdentity)) return;
93928
94079
  }
93929
- const noFollow = process.platform === "win32" ? 0 : fs29.constants.O_NOFOLLOW;
94080
+ const noFollow = process.platform === "win32" ? 0 : fs30.constants.O_NOFOLLOW;
93930
94081
  if (process.platform !== "win32" && (!noFollow || typeof noFollow !== "number")) return;
93931
- descriptor = fs29.openSync(temporaryPath, fs29.constants.O_RDWR | noFollow);
93932
- const stats = fs29.fstatSync(descriptor, { bigint: true });
94082
+ descriptor = fs30.openSync(temporaryPath, fs30.constants.O_RDWR | noFollow);
94083
+ const stats = fs30.fstatSync(descriptor, { bigint: true });
93933
94084
  const identity6 = identityFromStats(stats);
93934
94085
  if (!stats.isFile() || !hasUsableInode(identity6) || !sameIdentity(identity6, expectedIdentity)) return;
93935
94086
  if (process.platform === "win32") {
93936
- const after = fs29.lstatSync(temporaryPath, { bigint: true });
94087
+ const after = fs30.lstatSync(temporaryPath, { bigint: true });
93937
94088
  const afterIdentity = identityFromStats(after);
93938
94089
  if (!after.isFile() || after.isSymbolicLink() || !beforeIdentity || !hasUsableInode(afterIdentity) || !sameIdentity(beforeIdentity, identity6) || !sameIdentity(identity6, afterIdentity)) return;
93939
94090
  }
93940
- fs29.ftruncateSync(descriptor, 0);
93941
- fs29.fsyncSync(descriptor);
94091
+ fs30.ftruncateSync(descriptor, 0);
94092
+ fs30.fsyncSync(descriptor);
93942
94093
  } catch {
93943
94094
  } finally {
93944
94095
  if (descriptor !== null) {
93945
94096
  try {
93946
- fs29.closeSync(descriptor);
94097
+ fs30.closeSync(descriptor);
93947
94098
  } catch {
93948
94099
  }
93949
94100
  }
@@ -93990,16 +94141,16 @@ function parseControlState(value) {
93990
94141
  }
93991
94142
  function openControlStateForRead(statePath) {
93992
94143
  if (process.platform === "win32") return openControlStateForReadOnWindows(statePath);
93993
- const noFollow = fs29.constants.O_NOFOLLOW;
94144
+ const noFollow = fs30.constants.O_NOFOLLOW;
93994
94145
  if (typeof noFollow !== "number" || noFollow === 0) {
93995
94146
  throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NOFOLLOW \u5B89\u5168\u8BFB\u53D6");
93996
94147
  }
93997
- const nonBlock = fs29.constants.O_NONBLOCK;
94148
+ const nonBlock = fs30.constants.O_NONBLOCK;
93998
94149
  if (typeof nonBlock !== "number" || nonBlock === 0) {
93999
94150
  throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NONBLOCK \u5B89\u5168\u8BFB\u53D6");
94000
94151
  }
94001
94152
  try {
94002
- return fs29.openSync(statePath, fs29.constants.O_RDONLY | noFollow | nonBlock);
94153
+ return fs30.openSync(statePath, fs30.constants.O_RDONLY | noFollow | nonBlock);
94003
94154
  } catch (error2) {
94004
94155
  if (error2.code === "ELOOP") {
94005
94156
  throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
@@ -94008,14 +94159,14 @@ function openControlStateForRead(statePath) {
94008
94159
  }
94009
94160
  }
94010
94161
  function openControlStateForReadOnWindows(statePath) {
94011
- const before = fs29.lstatSync(statePath, { bigint: true });
94162
+ const before = fs30.lstatSync(statePath, { bigint: true });
94012
94163
  if (!before.isFile() || before.isSymbolicLink()) {
94013
94164
  throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
94014
94165
  }
94015
- const descriptor = fs29.openSync(statePath, fs29.constants.O_RDONLY);
94166
+ const descriptor = fs30.openSync(statePath, fs30.constants.O_RDONLY);
94016
94167
  try {
94017
- const opened = fs29.fstatSync(descriptor, { bigint: true });
94018
- const after = fs29.lstatSync(statePath, { bigint: true });
94168
+ const opened = fs30.fstatSync(descriptor, { bigint: true });
94169
+ const after = fs30.lstatSync(statePath, { bigint: true });
94019
94170
  const beforeIdentity = identityFromStats(before);
94020
94171
  const openedIdentity = identityFromStats(opened);
94021
94172
  const afterIdentity = identityFromStats(after);
@@ -94024,7 +94175,7 @@ function openControlStateForReadOnWindows(statePath) {
94024
94175
  }
94025
94176
  return descriptor;
94026
94177
  } catch (error2) {
94027
- fs29.closeSync(descriptor);
94178
+ fs30.closeSync(descriptor);
94028
94179
  throw error2;
94029
94180
  }
94030
94181
  }
@@ -94466,9 +94617,9 @@ var init_direct2 = __esm({
94466
94617
  });
94467
94618
 
94468
94619
  // apps/desktop/src/cli/commands/events.ts
94469
- import path53 from "node:path";
94620
+ import path54 from "node:path";
94470
94621
  function normalizedProjectRoot(value) {
94471
- return typeof value === "string" && value.length > 0 ? path53.resolve(value) : null;
94622
+ return typeof value === "string" && value.length > 0 ? path54.resolve(value) : null;
94472
94623
  }
94473
94624
  function toOutputEvent(event) {
94474
94625
  if (event.ok === true && typeof event.schemaVersion === "number") {
@@ -94852,7 +95003,7 @@ var init_state2 = __esm({
94852
95003
  });
94853
95004
 
94854
95005
  // apps/desktop/src/cli/commands/threads.ts
94855
- import path54 from "node:path";
95006
+ import path55 from "node:path";
94856
95007
  function readPositiveInteger2(value, name2, fallback) {
94857
95008
  if (value === void 0) {
94858
95009
  return fallback;
@@ -94870,7 +95021,7 @@ async function runThreadsCommand(args, options = {}) {
94870
95021
  const pageSize = readPositiveInteger2(args.flags.pageSize ?? args.flags.limit, "--page-size", 100);
94871
95022
  const maxPages = readPositiveInteger2(args.flags.maxPages, "--max-pages", 20);
94872
95023
  const cursor = typeof args.flags.cursor === "string" && args.flags.cursor.length > 0 ? args.flags.cursor : null;
94873
- const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ? path54.resolve(args.flags.project) : null;
95024
+ const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ? path55.resolve(args.flags.project) : null;
94874
95025
  const daemon = options.daemonClient ?? new DaemonClient(options.socketPath);
94875
95026
  const result = await daemon.request("threads/list", {
94876
95027
  pageSize,