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