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/README.md +4 -2
- package/dist/assets/autostart/Niuma +0 -0
- package/dist/assets/autostart/Niuma.icns +0 -0
- package/dist/cli.js +834 -683
- package/package.json +1 -1
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,
|
|
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 && (
|
|
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.
|
|
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(
|
|
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/${
|
|
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(
|
|
11895
|
+
setConnection(path56) {
|
|
11896
11896
|
this.epoch++;
|
|
11897
11897
|
this.controller?.abort();
|
|
11898
11898
|
this.controller = null;
|
|
11899
|
-
this.path =
|
|
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
|
|
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 `${
|
|
12815
|
+
return `${path56}\u4E0D\u80FD\u4E3A\u7A7A`;
|
|
12816
12816
|
}
|
|
12817
12817
|
if (issue.code === "invalid_type") {
|
|
12818
|
-
return `${
|
|
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 `${
|
|
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
|
-
|
|
17435
|
-
|
|
17436
|
-
|
|
17437
|
-
|
|
17438
|
-
|
|
17439
|
-
|
|
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
|
|
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("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
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
|
|
17635
|
+
import fs16 from "node:fs";
|
|
17516
17636
|
import fsp from "node:fs/promises";
|
|
17517
|
-
import
|
|
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 =
|
|
17541
|
-
const s =
|
|
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
|
-
|
|
17664
|
+
fs16.closeSync(fd);
|
|
17544
17665
|
throw Error("unsafe");
|
|
17545
17666
|
}
|
|
17546
|
-
return () =>
|
|
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 =
|
|
17562
|
-
this.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
|
|
17700
|
+
return path21.join(this.root, "registration.json");
|
|
17579
17701
|
}
|
|
17580
17702
|
get operationFile() {
|
|
17581
|
-
return
|
|
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
|
-
|
|
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
|
|
17721
|
+
return 1;
|
|
17590
17722
|
} catch (e) {
|
|
17591
|
-
return e.code === 113 ?
|
|
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 ?? "\
|
|
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(
|
|
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
|
-
|
|
17611
|
-
|
|
17612
|
-
|
|
17613
|
-
|
|
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 ?? "\
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
17699
|
-
if (
|
|
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
|
|
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.
|
|
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(
|
|
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
|
-
|
|
17730
|
-
|
|
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
|
-
|
|
17737
|
-
const installed = await (this.options.install?.(config) ?? installRelease({ root: this.root, version: config.releaseVersion, node: config.nodeExecutable, npm:
|
|
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(
|
|
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 =
|
|
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 (
|
|
17915
|
+
if (next?.appPath) await this.run(LSREGISTER, ["-f", next.appPath]);
|
|
17916
|
+
if (wasRegistered) await this.unload(previous);
|
|
17749
17917
|
if (next) {
|
|
17750
|
-
await
|
|
17918
|
+
await fsp.rm(this.plist, { force: true });
|
|
17751
17919
|
await atomic(this.metadata, JSON.stringify(next));
|
|
17752
|
-
await this.
|
|
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
|
-
|
|
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
|
|
17780
|
-
import
|
|
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:
|
|
17789
|
-
path: [
|
|
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:
|
|
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
|
|
18228
|
-
import
|
|
18229
|
-
import { createHash as
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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) =>
|
|
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
|
|
20757
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
20596
20758
|
function submissionId(input) {
|
|
20597
|
-
const h =
|
|
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 =
|
|
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,
|
|
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
|
|
21453
|
+
import path24 from "node:path";
|
|
21292
21454
|
function pathBelongsToProjectRoot(projectRoot, candidateRoot) {
|
|
21293
|
-
const relative =
|
|
21294
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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_${
|
|
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
|
|
24656
|
+
const path56 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
|
|
24495
24657
|
try {
|
|
24496
|
-
return encodeURIComponent(
|
|
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
|
|
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:
|
|
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
|
|
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
|
|
24640
|
-
function unavailableImageId(
|
|
24641
|
-
const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null,
|
|
24642
|
-
return `unavailable:${
|
|
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,
|
|
24897
|
+
function userFile(name2, path56) {
|
|
24736
24898
|
const part = { type: "file", name: name2 };
|
|
24737
|
-
userFileSource.set(part,
|
|
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
|
|
24743
|
-
return part.type === "file" && typeof
|
|
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
|
|
24781
|
-
if (!name2 || !isRecordedResourcePath(
|
|
24942
|
+
const path56 = match[2] ?? match[4] ?? "";
|
|
24943
|
+
if (!name2 || !isRecordedResourcePath(path56)) {
|
|
24782
24944
|
return null;
|
|
24783
24945
|
}
|
|
24784
|
-
entries.push({ name: name2, path:
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
|
24832
|
-
return
|
|
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
|
|
24867
|
-
return
|
|
24868
|
-
path:
|
|
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
|
|
24998
|
-
return
|
|
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
|
|
25967
|
-
if ((candidate.op === "add" || candidate.op === "replace") &&
|
|
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
|
|
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) =>
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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) :
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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
|
|
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) :
|
|
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
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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,
|
|
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 =
|
|
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
|
|
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" :
|
|
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
|
|
29040
|
-
import
|
|
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 =
|
|
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 = () =>
|
|
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
|
|
29222
|
-
import
|
|
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 =
|
|
29453
|
+
const statePath = path28.join(codexHome, ".codex-global-state.json");
|
|
29292
29454
|
try {
|
|
29293
|
-
const raw = await
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
30662
|
-
import
|
|
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 =
|
|
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 =
|
|
30856
|
+
const directory = path30.dirname(file);
|
|
30695
30857
|
let parent;
|
|
30696
30858
|
try {
|
|
30697
|
-
parent =
|
|
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 =
|
|
30704
|
-
if (!same5(parent,
|
|
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 =
|
|
30708
|
-
const opened =
|
|
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 =
|
|
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,
|
|
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)
|
|
30891
|
+
if (fd !== void 0) fs21.closeSync(fd);
|
|
30730
30892
|
} finally {
|
|
30731
|
-
if (directoryFd !== void 0)
|
|
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 =
|
|
30737
|
-
const temporary =
|
|
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
|
-
|
|
30744
|
-
const parent =
|
|
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 =
|
|
30747
|
-
if (!same5(parent,
|
|
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 =
|
|
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 =
|
|
30913
|
+
const temporaryIdentity = fs21.fstatSync(fd, { bigint: true });
|
|
30752
30914
|
if (!trusted3(temporaryIdentity)) throw new PrivateDocumentFileError("unavailable");
|
|
30753
|
-
|
|
30754
|
-
|
|
30755
|
-
|
|
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,
|
|
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
|
-
|
|
30923
|
+
fs21.renameSync(temporary, file);
|
|
30762
30924
|
renamed = true;
|
|
30763
30925
|
created = false;
|
|
30764
|
-
|
|
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
|
-
|
|
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
|
-
|
|
30942
|
+
fs21.closeSync(directoryFd);
|
|
30781
30943
|
} catch {
|
|
30782
30944
|
}
|
|
30783
30945
|
}
|
|
30784
30946
|
} finally {
|
|
30785
30947
|
if (created) {
|
|
30786
30948
|
try {
|
|
30787
|
-
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|
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
|
|
31063
|
+
return path31.join(applicationStateDirectory(), "managed-threads-v1.json");
|
|
30902
31064
|
}
|
|
30903
31065
|
function threadSettingsStatePath() {
|
|
30904
|
-
return
|
|
31066
|
+
return path31.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
|
|
30905
31067
|
}
|
|
30906
31068
|
function threadListStatePath() {
|
|
30907
|
-
return
|
|
31069
|
+
return path31.join(applicationStateDirectory(), "thread-list-cache-v1.json");
|
|
30908
31070
|
}
|
|
30909
31071
|
function daemonMetricsStatePath() {
|
|
30910
|
-
return
|
|
31072
|
+
return path31.join(applicationStateDirectory(), "daemon-metrics-v1.json");
|
|
30911
31073
|
}
|
|
30912
31074
|
function desktopIdentityCandidatesStatePath() {
|
|
30913
|
-
return
|
|
31075
|
+
return path31.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
|
|
30914
31076
|
}
|
|
30915
31077
|
function pendingRequestsCachePath() {
|
|
30916
|
-
return
|
|
31078
|
+
return path31.join(cliCacheDirectory(), "pending-requests-v1.json");
|
|
30917
31079
|
}
|
|
30918
31080
|
function idempotencyCachePath() {
|
|
30919
|
-
return
|
|
31081
|
+
return path31.join(cliCacheDirectory(), "idempotency-v1.json");
|
|
30920
31082
|
}
|
|
30921
31083
|
function messageSubmissionsStatePath() {
|
|
30922
|
-
return
|
|
31084
|
+
return path31.join(applicationStateDirectory(), "message-submissions-v1.json");
|
|
30923
31085
|
}
|
|
30924
31086
|
function deviceNameStatePath() {
|
|
30925
|
-
return
|
|
31087
|
+
return path31.join(applicationStateDirectory(), "device-name-v1.json");
|
|
30926
31088
|
}
|
|
30927
31089
|
function threadReadReceiptsStatePath() {
|
|
30928
|
-
return
|
|
31090
|
+
return path31.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
|
|
30929
31091
|
}
|
|
30930
31092
|
function asyncQuestionFactsStatePath() {
|
|
30931
|
-
return
|
|
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
|
|
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 =
|
|
32647
|
-
if (normalized.length > 1 && normalized.endsWith(
|
|
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}${
|
|
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:
|
|
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
|
|
34204
|
-
import
|
|
34365
|
+
import fs22 from "node:fs";
|
|
34366
|
+
import path33 from "node:path";
|
|
34205
34367
|
function serialize(file, operation) {
|
|
34206
|
-
const key = process.platform === "win32" ?
|
|
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 =
|
|
34222
|
-
const lock =
|
|
34223
|
-
|
|
34224
|
-
const parent =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
34407
|
+
const opened = fs22.fstatSync(fd, { bigint: true });
|
|
34246
34408
|
const verify = () => {
|
|
34247
|
-
const current2 =
|
|
34248
|
-
const currentParent =
|
|
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
|
-
|
|
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
|
-
|
|
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(
|
|
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
|
|
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 =
|
|
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
|
|
35353
|
-
import
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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
|
|
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 =
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
46431
|
-
if (
|
|
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,
|
|
46585
|
+
this.entityTurnIds.set(this.entityKey(threadId2, path56[3]), turnId);
|
|
46435
46586
|
}
|
|
46436
46587
|
continue;
|
|
46437
46588
|
}
|
|
46438
|
-
if (
|
|
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,
|
|
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(
|
|
46491
|
-
return
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
47227
|
-
const index =
|
|
47228
|
-
if (
|
|
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:
|
|
47382
|
+
return { entityKey: path56[3], index, itemPathLength: 6 };
|
|
47232
47383
|
}
|
|
47233
|
-
function entityTarget(
|
|
47234
|
-
return
|
|
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
|
|
47521
|
-
const targetItem = itemTarget(
|
|
47671
|
+
const path56 = array3(patch.path);
|
|
47672
|
+
const targetItem = itemTarget(path56);
|
|
47522
47673
|
if (targetItem) {
|
|
47523
|
-
signals.push(...this.consumeItemPatch(threadId2, state, targetItem,
|
|
47674
|
+
signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path56, patch.value, patch.op));
|
|
47524
47675
|
continue;
|
|
47525
47676
|
}
|
|
47526
|
-
const targetEntity = entityTarget(
|
|
47677
|
+
const targetEntity = entityTarget(path56);
|
|
47527
47678
|
if (targetEntity) {
|
|
47528
|
-
signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity,
|
|
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,
|
|
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 (
|
|
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 ||
|
|
47768
|
+
if (!existing || path56.length < target.itemPathLength + 1) {
|
|
47618
47769
|
return [];
|
|
47619
47770
|
}
|
|
47620
|
-
const field2 =
|
|
47771
|
+
const field2 = path56[target.itemPathLength];
|
|
47621
47772
|
if (existing.type === "reasoning" && field2 === "summary") {
|
|
47622
47773
|
const summary = structuredClone(existing.summary ?? []);
|
|
47623
|
-
const suffix =
|
|
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,
|
|
47724
|
-
const wholeEntity =
|
|
47725
|
-
const statusField =
|
|
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
|
|
47906
|
-
if (
|
|
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,
|
|
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 (
|
|
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,
|
|
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(
|
|
48012
|
-
const index =
|
|
48013
|
-
const itemIndex =
|
|
48014
|
-
return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 &&
|
|
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,
|
|
48017
|
-
return `${threadId2}:${JSON.stringify(
|
|
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
|
|
48076
|
-
if (
|
|
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 (
|
|
48081
|
-
const values =
|
|
48082
|
-
if (
|
|
48083
|
-
const arrayPath =
|
|
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 =
|
|
48089
|
-
if (op === "add" &&
|
|
48090
|
-
const length = this.arrayLengths.get(stateKey(threadId2,
|
|
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
|
-
|
|
48243
|
+
path56[rawIndex] = length;
|
|
48093
48244
|
}
|
|
48094
|
-
const targetItemPath = itemPath(
|
|
48245
|
+
const targetItemPath = itemPath(path56);
|
|
48095
48246
|
if (!targetItemPath) {
|
|
48096
48247
|
continue;
|
|
48097
48248
|
}
|
|
48098
48249
|
const key = stateKey(threadId2, targetItemPath);
|
|
48099
|
-
if (
|
|
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 (
|
|
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" &&
|
|
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
|
|
48131
|
-
const at =
|
|
48132
|
-
if (JSON.stringify(
|
|
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,
|
|
48144
|
-
const prefix = JSON.stringify(
|
|
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,
|
|
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, [...
|
|
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
|
|
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:
|
|
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 (
|
|
49282
|
-
const value = versionReader ? await versionReader(
|
|
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
|
|
51569
|
-
import
|
|
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:${
|
|
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 =
|
|
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
|
|
53710
|
+
import fs25 from "node:fs";
|
|
53560
53711
|
import net4 from "node:net";
|
|
53561
|
-
import
|
|
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 =
|
|
53697
|
-
this.statusPath =
|
|
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() :
|
|
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 =
|
|
53812
|
-
|
|
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
|
-
|
|
53969
|
+
fs25.closeSync(descriptor);
|
|
53819
53970
|
descriptor = null;
|
|
53820
|
-
|
|
53821
|
-
|
|
53971
|
+
fs25.chmodSync(temporaryPath, 384);
|
|
53972
|
+
fs25.renameSync(temporaryPath, this.statusPath);
|
|
53822
53973
|
} catch (error2) {
|
|
53823
53974
|
if (descriptor !== null) {
|
|
53824
|
-
|
|
53975
|
+
fs25.closeSync(descriptor);
|
|
53825
53976
|
}
|
|
53826
|
-
|
|
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(
|
|
54002
|
+
const status2 = JSON.parse(fs25.readFileSync(this.statusPath, "utf8"));
|
|
53852
54003
|
if (status2.instanceId === this.instanceId) {
|
|
53853
|
-
|
|
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
|
|
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
|
|
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(
|
|
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
|
|
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(([
|
|
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:
|
|
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-${
|
|
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
|
|
56303
|
-
return
|
|
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
|
|
56335
|
-
if (Array.isArray(
|
|
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
|
|
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 (
|
|
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,
|
|
56537
|
-
const value = await readHistoryImageValue(locator, signal,
|
|
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 ===
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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,
|
|
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 ===
|
|
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 ===
|
|
56886
|
+
const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path56);
|
|
56736
56887
|
if (!original) continue;
|
|
56737
|
-
const evidence = { ...original, path:
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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:${
|
|
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
|
|
61880
|
-
if (!Array.isArray(
|
|
61881
|
-
if (
|
|
61882
|
-
return
|
|
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
|
|
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:
|
|
62402
|
+
const { createdAt, cwd, path: path56 } = bound.metadata;
|
|
62252
62403
|
return {
|
|
62253
62404
|
nativeOrder: bound.nativeOrder,
|
|
62254
62405
|
sourceRevision: bound.revision,
|
|
62255
|
-
contentVersion:
|
|
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),
|
|
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
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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: (
|
|
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
|
|
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),
|
|
65638
|
-
const name2 =
|
|
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" ?
|
|
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
|
|
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_" +
|
|
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:
|
|
66261
|
-
thread:
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
67793
|
+
async function captureDirectoryChain(snapshot2, path56, signal) {
|
|
67643
67794
|
const paths = /* @__PURE__ */ new Set();
|
|
67644
|
-
for (const start of [dirname2(
|
|
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,
|
|
67925
|
+
assertTarget(entry, path56, signal, isCurrent) {
|
|
67775
67926
|
this.assertVisible(entry, signal, isCurrent);
|
|
67776
|
-
if (entry.targetRealPath !== void 0 && entry.targetRealPath !==
|
|
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
|
|
67969
|
+
const path56 = await realpath2(entry.reference.path);
|
|
67819
67970
|
combined.throwIfAborted();
|
|
67820
|
-
this.assertTarget(entry,
|
|
67821
|
-
await captureDirectoryChain(directories2,
|
|
67822
|
-
const pathBefore = await lstat4(
|
|
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(
|
|
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 = `${
|
|
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 =
|
|
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 !==
|
|
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,
|
|
67871
|
-
return { entry, path:
|
|
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(
|
|
67904
|
-
const field2 =
|
|
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
|
|
68059
|
+
return path56.length === 1 || typeof path56.at(-2) === "string" && SETTINGS_CONTAINERS.has(path56.at(-2));
|
|
67909
68060
|
}
|
|
67910
|
-
function isCurrentPermissionsPatch(
|
|
67911
|
-
const field2 =
|
|
67912
|
-
return
|
|
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
|
|
67992
|
-
if (
|
|
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 (
|
|
68146
|
+
if (path56.length === 1 && path56[0] === CURRENT_PERMISSIONS_CONTAINER) {
|
|
67996
68147
|
return currentPermissionsFromRecord(patch.value);
|
|
67997
68148
|
}
|
|
67998
|
-
const field2 =
|
|
68149
|
+
const field2 = path56.at(-1);
|
|
67999
68150
|
const settings = {};
|
|
68000
|
-
if (typeof field2 === "string" && isCurrentPermissionsPatch(
|
|
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(
|
|
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),
|
|
71423
|
-
return
|
|
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),
|
|
71434
|
-
if (p.op === "remove" &&
|
|
71435
|
-
const id5 = mapped.get(String(
|
|
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),
|
|
71447
|
-
if (
|
|
71448
|
-
const key = String(
|
|
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
|
|
71575
|
-
if ((patch.op === "add" || patch.op === "replace") && (
|
|
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
|
|
71662
|
-
if (
|
|
71663
|
-
if (
|
|
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 (
|
|
71666
|
-
const index =
|
|
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
|
|
71746
|
-
if (
|
|
71747
|
-
const turnId = typeof
|
|
71748
|
-
if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (
|
|
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 (
|
|
71905
|
+
if (path56[4] !== "items" || path56[6] !== "content") return;
|
|
71755
71906
|
const order = this.itemOrders.get(context.threadId);
|
|
71756
|
-
if (!order || order.entityKey !==
|
|
71757
|
-
const id5 = typeof
|
|
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
|
|
71782
|
-
if (
|
|
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 (
|
|
71789
|
-
if (
|
|
71790
|
-
if (
|
|
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(
|
|
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 =
|
|
71811
|
-
const wholeArray =
|
|
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 ||
|
|
71828
|
-
if (
|
|
71829
|
-
return ["id", "type"].includes(String(
|
|
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 (
|
|
71832
|
-
const index =
|
|
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
|
|
72054
|
-
if (
|
|
72055
|
-
const entityKey =
|
|
72056
|
-
const wholeEntity =
|
|
72057
|
-
const statusField =
|
|
72058
|
-
const startField =
|
|
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
|
|
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
|
|
72264
|
-
if (slashes % 2 || paths.parseLocal(
|
|
72414
|
+
const path56 = match[1];
|
|
72415
|
+
if (slashes % 2 || paths.parseLocal(path56) === null) continue;
|
|
72265
72416
|
try {
|
|
72266
|
-
const target = paths.toLink(
|
|
72417
|
+
const target = paths.toLink(path56);
|
|
72267
72418
|
if (target === null) continue;
|
|
72268
|
-
const label = fallbackFileName(
|
|
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
|
|
72287
|
-
if (
|
|
72288
|
-
return [{ ...ref, path:
|
|
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(
|
|
72299
|
-
const name2 = paths.basename(
|
|
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_${
|
|
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_${
|
|
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
|
|
72363
|
-
import
|
|
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:
|
|
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 ||
|
|
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 ||
|
|
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" &&
|
|
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) =>
|
|
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
|
|
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),
|
|
74041
|
-
const fields3 =
|
|
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 =
|
|
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
|
|
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:
|
|
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
|
|
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:
|
|
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
|
|
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(
|
|
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) :
|
|
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
|
|
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(
|
|
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(
|
|
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(
|
|
76757
|
-
const temporary =
|
|
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
|
|
76806
|
-
import
|
|
76956
|
+
import fs27 from "node:fs";
|
|
76957
|
+
import path43 from "node:path";
|
|
76807
76958
|
async function openPrivateDocumentDirectory(root) {
|
|
76808
|
-
const directory =
|
|
76959
|
+
const directory = path43.resolve(root);
|
|
76809
76960
|
let identity6;
|
|
76810
76961
|
try {
|
|
76811
76962
|
privateLogFiles.ensureDirectory(directory);
|
|
76812
|
-
identity6 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
77066
|
+
return createHash35("sha256").update(value).digest("hex");
|
|
76916
77067
|
}
|
|
76917
|
-
async function readJsonManifest(
|
|
77068
|
+
async function readJsonManifest(path56, io) {
|
|
76918
77069
|
try {
|
|
76919
77070
|
if (io.controlledFiles) {
|
|
76920
|
-
const { data } = await io.controlledFiles.read(
|
|
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(
|
|
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(
|
|
77078
|
+
return JSON.parse(await readFile2(path56, "utf8"));
|
|
76928
77079
|
} catch {
|
|
76929
77080
|
return null;
|
|
76930
77081
|
}
|
|
76931
77082
|
}
|
|
76932
|
-
async function assertRegularControlledFile(directoryPath,
|
|
76933
|
-
if (dirname3(
|
|
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(
|
|
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,
|
|
76942
|
-
if (dirname3(
|
|
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(
|
|
76946
|
-
const handle = await io.open(
|
|
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,
|
|
76971
|
-
const handle = await io.open(
|
|
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(
|
|
76984
|
-
const currentStatus = await lstat7(
|
|
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(
|
|
77148
|
+
async function pathIsMissing(path56) {
|
|
76998
77149
|
try {
|
|
76999
|
-
await lstat7(
|
|
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,
|
|
77006
|
-
if (io.controlledFiles) return io.controlledFiles.identity(
|
|
77007
|
-
const handle = await io.open(
|
|
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: (
|
|
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
|
|
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(
|
|
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,
|
|
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(
|
|
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 =
|
|
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
|
|
77724
|
-
const status2 = await lstat7(
|
|
77725
|
-
if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(
|
|
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
|
|
78264
|
-
const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(
|
|
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(
|
|
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
|
|
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,
|
|
78333
|
-
await chmod3(
|
|
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
|
|
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) =>
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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
|
-
|
|
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
|
|
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 ??
|
|
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
|
|
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(
|
|
81151
|
+
async function readSourceFile(path56, signal) {
|
|
81001
81152
|
signal?.throwIfAborted();
|
|
81002
|
-
const handle = await open8(
|
|
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) =>
|
|
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,
|
|
81232
|
-
return this.register({ resourceKey, name: basename4(
|
|
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,
|
|
81385
|
+
async registerFile(threadId2, path56, attachmentId, context) {
|
|
81235
81386
|
if (context && context.visibilityLocator.threadId !== threadId2) throw missing3();
|
|
81236
|
-
const canonical = await realpath4(
|
|
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,
|
|
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 ===
|
|
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
|
|
81823
|
+
import { createHash as createHash38 } from "node:crypto";
|
|
81673
81824
|
import { realpath as realpath5 } from "node:fs/promises";
|
|
81674
|
-
import
|
|
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 =
|
|
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 ?
|
|
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" &&
|
|
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:
|
|
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 ||
|
|
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 || !
|
|
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:
|
|
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" :
|
|
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
|
|
84122
|
-
if (!paths.has(thread4.id)) paths.set(thread4.id,
|
|
84123
|
-
else if (paths.get(thread4.id) !==
|
|
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,
|
|
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,
|
|
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
|
|
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 ??
|
|
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
|
|
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
|
|
84597
|
+
return os5.hostname();
|
|
84447
84598
|
}
|
|
84448
84599
|
function systemHostname() {
|
|
84449
|
-
return
|
|
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
|
|
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 =
|
|
84747
|
+
const dir = path47.join(runtimeDir, "debug");
|
|
84597
84748
|
files.ensureDirectory(dir);
|
|
84598
84749
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
84599
|
-
return
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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 =
|
|
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,
|
|
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
|
|
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(
|
|
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 =
|
|
89054
|
-
const b =
|
|
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 =
|
|
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 =
|
|
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 ||
|
|
89639
|
-
filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ??
|
|
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(
|
|
89803
|
+
const next = Number(path49.basename(filePath).slice(11, -7)) + 1;
|
|
89653
89804
|
if (next > 999999) break;
|
|
89654
|
-
filePath =
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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" ? [
|
|
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
|
|
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 =
|
|
91758
|
-
const status2 =
|
|
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(
|
|
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
|
|
93316
|
-
import
|
|
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
|
|
93363
|
-
if (requestTarget ===
|
|
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
|
|
93369
|
-
if (requestTarget ===
|
|
93370
|
-
return
|
|
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 =
|
|
93392
|
-
BOOTSTRAP_CSS =
|
|
93393
|
-
BOOTSTRAP_BUNDLE =
|
|
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:
|
|
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:
|
|
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
|
|
93621
|
-
import
|
|
93622
|
-
import
|
|
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 =
|
|
93630
|
-
|
|
93631
|
-
`.${
|
|
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 =
|
|
93639
|
-
if (process.platform !== "win32")
|
|
93640
|
-
const stats =
|
|
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
|
-
|
|
93794
|
+
fs30.writeFileSync(descriptor, `${JSON.stringify(state)}
|
|
93644
93795
|
`, "utf8");
|
|
93645
|
-
|
|
93646
|
-
|
|
93796
|
+
fs30.fsyncSync(descriptor);
|
|
93797
|
+
fs30.closeSync(descriptor);
|
|
93647
93798
|
descriptor = null;
|
|
93648
|
-
|
|
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
|
-
|
|
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 =
|
|
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 =
|
|
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 =
|
|
93843
|
+
const artifactPath = path53.join(runtimeDir, entry);
|
|
93693
93844
|
try {
|
|
93694
|
-
const stats =
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
93965
|
+
fs30.linkSync(error2.statePath, snapshotPath);
|
|
93815
93966
|
} catch {
|
|
93816
93967
|
return false;
|
|
93817
93968
|
}
|
|
93818
93969
|
try {
|
|
93819
|
-
const snapshotStats =
|
|
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
|
-
|
|
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 =
|
|
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
|
-
|
|
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 =
|
|
93860
|
-
const snapshotStats =
|
|
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 =
|
|
93869
|
-
const snapshotStats =
|
|
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
|
|
93901
|
-
|
|
93902
|
-
`.${
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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 :
|
|
94080
|
+
const noFollow = process.platform === "win32" ? 0 : fs30.constants.O_NOFOLLOW;
|
|
93930
94081
|
if (process.platform !== "win32" && (!noFollow || typeof noFollow !== "number")) return;
|
|
93931
|
-
descriptor =
|
|
93932
|
-
const stats =
|
|
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 =
|
|
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
|
-
|
|
93941
|
-
|
|
94091
|
+
fs30.ftruncateSync(descriptor, 0);
|
|
94092
|
+
fs30.fsyncSync(descriptor);
|
|
93942
94093
|
} catch {
|
|
93943
94094
|
} finally {
|
|
93944
94095
|
if (descriptor !== null) {
|
|
93945
94096
|
try {
|
|
93946
|
-
|
|
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 =
|
|
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 =
|
|
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
|
|
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 =
|
|
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 =
|
|
94166
|
+
const descriptor = fs30.openSync(statePath, fs30.constants.O_RDONLY);
|
|
94016
94167
|
try {
|
|
94017
|
-
const opened =
|
|
94018
|
-
const after =
|
|
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
|
-
|
|
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
|
|
94620
|
+
import path54 from "node:path";
|
|
94470
94621
|
function normalizedProjectRoot(value) {
|
|
94471
|
-
return typeof value === "string" && value.length > 0 ?
|
|
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
|
|
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 ?
|
|
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,
|