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