niuma-codex 0.0.1-beta.23 → 0.0.1-beta.25
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +756 -730
- package/dist/managed-tauri.js +1 -1
- package/dist/managed.js +1 -1
- package/package.json +1 -1
- package/resources/lite-release.json +7 -7
- package/resources/niuma-daemon-arm64.tgz +0 -0
- package/resources/niuma-lite-arm64.dmg +0 -0
package/dist/cli.js
CHANGED
|
@@ -3562,6 +3562,58 @@ var init_app_validation = __esm({
|
|
|
3562
3562
|
}
|
|
3563
3563
|
});
|
|
3564
3564
|
|
|
3565
|
+
// apps/desktop/src/lite-install/intent.ts
|
|
3566
|
+
import fs19 from "node:fs/promises";
|
|
3567
|
+
import path23 from "node:path";
|
|
3568
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
3569
|
+
async function prepareInstallIntent(root, home, version2) {
|
|
3570
|
+
if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(version2)) throw Error("\u9700\u8981\u660E\u786E\u7684\u53D1\u5E03\u7248\u672C");
|
|
3571
|
+
const pending = await readMigration(root);
|
|
3572
|
+
if (pending && !["completed", "skipped"].includes(pending.phase) && pending.version !== version2) throw Error("\u8BF7\u5148\u4F7F\u7528\u539F\u7248\u672C install-app \u5B8C\u6210\u8FC1\u79FB");
|
|
3573
|
+
const file = path23.join(root, "install-intent.json");
|
|
3574
|
+
let intent;
|
|
3575
|
+
try {
|
|
3576
|
+
const stat4 = await fs19.lstat(file);
|
|
3577
|
+
if (!stat4.isFile() || stat4.uid !== process.getuid?.() || stat4.mode & 63) throw Error("\u5B89\u88C5\u610F\u56FE\u6587\u4EF6\u4E0D\u53EF\u4FE1");
|
|
3578
|
+
intent = JSON.parse(await fs19.readFile(file, "utf8"));
|
|
3579
|
+
} catch (e) {
|
|
3580
|
+
if (e.code !== "ENOENT") throw e;
|
|
3581
|
+
let firstInstall = false;
|
|
3582
|
+
try {
|
|
3583
|
+
await fs19.lstat(path23.join(root, "current.json"));
|
|
3584
|
+
} catch (e2) {
|
|
3585
|
+
if (e2.code !== "ENOENT") throw e2;
|
|
3586
|
+
firstInstall = true;
|
|
3587
|
+
}
|
|
3588
|
+
intent = { version: version2, firstInstall, selection: await createInstallSelection(home, true) };
|
|
3589
|
+
await fs19.writeFile(file, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
3590
|
+
}
|
|
3591
|
+
if (!intent || typeof intent.firstInstall !== "boolean" || typeof intent.version !== "string" || !/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(intent.version)) throw Error("\u5B89\u88C5\u610F\u56FE\u8BB0\u5F55\u65E0\u6548");
|
|
3592
|
+
let changed2 = intent.version !== version2;
|
|
3593
|
+
if (intent.selection === void 0) {
|
|
3594
|
+
intent.selection = await createInstallSelection(home, false);
|
|
3595
|
+
changed2 = true;
|
|
3596
|
+
}
|
|
3597
|
+
if (!intent.selection || typeof intent.selection !== "object" || typeof intent.selection.revision !== "string" || !intent.selection.revision || !Number.isSafeInteger(intent.selection.requestedAt) || intent.selection.requestedAt < 0 || !(intent.selection.previousRevision === null || typeof intent.selection.previousRevision === "string")) throw Error("\u5B89\u88C5\u9009\u62E9\u8BB0\u5F55\u65E0\u6548");
|
|
3598
|
+
if (changed2) {
|
|
3599
|
+
intent.version = version2;
|
|
3600
|
+
const temp = file + "." + randomUUID6();
|
|
3601
|
+
try {
|
|
3602
|
+
await fs19.writeFile(temp, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
3603
|
+
await fs19.rename(temp, file);
|
|
3604
|
+
} finally {
|
|
3605
|
+
await fs19.rm(temp, { force: true });
|
|
3606
|
+
}
|
|
3607
|
+
}
|
|
3608
|
+
return { intent, pending };
|
|
3609
|
+
}
|
|
3610
|
+
var init_intent = __esm({
|
|
3611
|
+
"apps/desktop/src/lite-install/intent.ts"() {
|
|
3612
|
+
"use strict";
|
|
3613
|
+
init_migration();
|
|
3614
|
+
}
|
|
3615
|
+
});
|
|
3616
|
+
|
|
3565
3617
|
// apps/desktop/src/lite-install/lifecycle.ts
|
|
3566
3618
|
async function switchNpmDaemon(o) {
|
|
3567
3619
|
const before = await o.read();
|
|
@@ -5419,11 +5471,11 @@ function token(value) {
|
|
|
5419
5471
|
function size(kind, bytes3) {
|
|
5420
5472
|
return (kind === "image" || kind === "file") && integer(bytes3, kind === "image" ? 20971520 : 52428800, kind === "image" ? 1 : 0);
|
|
5421
5473
|
}
|
|
5422
|
-
function dataUrl(value,
|
|
5474
|
+
function dataUrl(value, path71) {
|
|
5423
5475
|
if (typeof value !== "string") return false;
|
|
5424
5476
|
try {
|
|
5425
5477
|
const u = new URL(value);
|
|
5426
|
-
return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (
|
|
5478
|
+
return ["ws:", "wss:"].includes(u.protocol) && !u.username && !u.password && !u.search && !u.hash && (path71 ? u.pathname === path71 : ["/direct/v1/attachment/data", "/ws/v1/attachment/data"].includes(u.pathname));
|
|
5427
5479
|
} catch {
|
|
5428
5480
|
return false;
|
|
5429
5481
|
}
|
|
@@ -10253,7 +10305,7 @@ var init_src = __esm({
|
|
|
10253
10305
|
// apps/desktop/src/release-version.ts
|
|
10254
10306
|
import { readFileSync } from "node:fs";
|
|
10255
10307
|
function desktopReleaseVersion() {
|
|
10256
|
-
return false ? null : "0.0.1-beta.
|
|
10308
|
+
return false ? null : "0.0.1-beta.25";
|
|
10257
10309
|
}
|
|
10258
10310
|
function desktopPresenceVersion() {
|
|
10259
10311
|
return desktopReleaseVersion() ?? sourcePresenceVersion;
|
|
@@ -10444,7 +10496,7 @@ var init_sse_client = __esm({
|
|
|
10444
10496
|
});
|
|
10445
10497
|
|
|
10446
10498
|
// apps/desktop/src/notifications/server-client.ts
|
|
10447
|
-
import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as
|
|
10499
|
+
import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
|
|
10448
10500
|
function invalidPushServerOrigin() {
|
|
10449
10501
|
return new NiumaError(
|
|
10450
10502
|
"INVALID_ARGUMENT",
|
|
@@ -10529,11 +10581,11 @@ var init_server_client = __esm({
|
|
|
10529
10581
|
if (data.binding_revision !== snapshot2.binding_revision) throw new NotificationTransportError("invalid_response");
|
|
10530
10582
|
return { binding_revision: snapshot2.binding_revision };
|
|
10531
10583
|
}
|
|
10532
|
-
async signedPost(
|
|
10584
|
+
async signedPost(path71, input, signal, method2 = "POST") {
|
|
10533
10585
|
if (!this.identity || !this.serverOrigin.startsWith("https://")) throw new NotificationTransportError("business_error", 200, 200004);
|
|
10534
|
-
const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${
|
|
10586
|
+
const query2 = method2 === "GET" ? input : {}, body = method2 === "GET" ? "" : JSON.stringify(input), pathname = `/api/v1/push/${path71}`;
|
|
10535
10587
|
const key_id = createHash4("sha256").update(this.identity.identity_public_key).digest("base64url");
|
|
10536
|
-
const operation_id =
|
|
10588
|
+
const operation_id = randomUUID7(), nonce = encodeBase64Url(randomBytes2(32)), timestamp = Math.floor(Date.now() / 1e3);
|
|
10537
10589
|
const bytes3 = createPushSigningBytes({ audience: this.serverOrigin, method: method2, pathname, query: query2, body_sha256: createHash4("sha256").update(body).digest("base64url"), key_id, operation_id, timestamp, nonce });
|
|
10538
10590
|
let response;
|
|
10539
10591
|
try {
|
|
@@ -10567,71 +10619,71 @@ var init_managed_owner = __esm({
|
|
|
10567
10619
|
});
|
|
10568
10620
|
|
|
10569
10621
|
// apps/desktop/src/platform/posix-runtime-lock.ts
|
|
10570
|
-
import { randomUUID as
|
|
10571
|
-
import
|
|
10572
|
-
import
|
|
10622
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
10623
|
+
import fs20 from "node:fs";
|
|
10624
|
+
import path24 from "node:path";
|
|
10573
10625
|
function publishDaemonLock(lockPath) {
|
|
10574
|
-
const token3 =
|
|
10575
|
-
const temporaryPath =
|
|
10576
|
-
|
|
10577
|
-
`.${
|
|
10626
|
+
const token3 = randomUUID8();
|
|
10627
|
+
const temporaryPath = path24.join(
|
|
10628
|
+
path24.dirname(lockPath),
|
|
10629
|
+
`.${path24.basename(lockPath)}.${randomUUID8()}.tmp`
|
|
10578
10630
|
);
|
|
10579
10631
|
let descriptor = null;
|
|
10580
10632
|
try {
|
|
10581
|
-
descriptor =
|
|
10582
|
-
const stats =
|
|
10633
|
+
descriptor = fs20.openSync(temporaryPath, "wx", 384);
|
|
10634
|
+
const stats = fs20.fstatSync(descriptor);
|
|
10583
10635
|
if (!stats.isFile()) {
|
|
10584
10636
|
throw new Error("daemon \u9501\u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6");
|
|
10585
10637
|
}
|
|
10586
|
-
|
|
10587
|
-
|
|
10588
|
-
|
|
10638
|
+
fs20.writeFileSync(descriptor, JSON.stringify({ token: token3, pid: process.pid }), "utf8");
|
|
10639
|
+
fs20.fchmodSync(descriptor, 384);
|
|
10640
|
+
fs20.closeSync(descriptor);
|
|
10589
10641
|
descriptor = null;
|
|
10590
|
-
|
|
10642
|
+
fs20.linkSync(temporaryPath, lockPath);
|
|
10591
10643
|
} catch (error2) {
|
|
10592
10644
|
if (descriptor !== null) {
|
|
10593
10645
|
try {
|
|
10594
|
-
|
|
10646
|
+
fs20.closeSync(descriptor);
|
|
10595
10647
|
} catch {
|
|
10596
10648
|
}
|
|
10597
10649
|
}
|
|
10598
10650
|
try {
|
|
10599
|
-
|
|
10651
|
+
fs20.unlinkSync(temporaryPath);
|
|
10600
10652
|
} catch {
|
|
10601
10653
|
}
|
|
10602
10654
|
throw error2;
|
|
10603
10655
|
}
|
|
10604
10656
|
try {
|
|
10605
|
-
|
|
10657
|
+
fs20.unlinkSync(temporaryPath);
|
|
10606
10658
|
} catch {
|
|
10607
10659
|
}
|
|
10608
10660
|
return {
|
|
10609
10661
|
token: token3,
|
|
10610
10662
|
release: () => {
|
|
10611
|
-
const snapshotPath =
|
|
10612
|
-
|
|
10613
|
-
`.${
|
|
10663
|
+
const snapshotPath = path24.join(
|
|
10664
|
+
path24.dirname(lockPath),
|
|
10665
|
+
`.${path24.basename(lockPath)}.${randomUUID8()}.snapshot`
|
|
10614
10666
|
);
|
|
10615
10667
|
try {
|
|
10616
|
-
|
|
10668
|
+
fs20.linkSync(lockPath, snapshotPath);
|
|
10617
10669
|
} catch {
|
|
10618
10670
|
return;
|
|
10619
10671
|
}
|
|
10620
10672
|
try {
|
|
10621
|
-
const current2 = JSON.parse(
|
|
10673
|
+
const current2 = JSON.parse(fs20.readFileSync(snapshotPath, "utf8"));
|
|
10622
10674
|
if (current2.token !== token3) {
|
|
10623
10675
|
return;
|
|
10624
10676
|
}
|
|
10625
|
-
const snapshotStats =
|
|
10626
|
-
const canonicalStats =
|
|
10677
|
+
const snapshotStats = fs20.lstatSync(snapshotPath);
|
|
10678
|
+
const canonicalStats = fs20.lstatSync(lockPath);
|
|
10627
10679
|
if (!snapshotStats.isFile() || !canonicalStats.isFile() || canonicalStats.dev !== snapshotStats.dev || canonicalStats.ino !== snapshotStats.ino) {
|
|
10628
10680
|
return;
|
|
10629
10681
|
}
|
|
10630
|
-
|
|
10682
|
+
fs20.unlinkSync(lockPath);
|
|
10631
10683
|
} catch {
|
|
10632
10684
|
} finally {
|
|
10633
10685
|
try {
|
|
10634
|
-
|
|
10686
|
+
fs20.unlinkSync(snapshotPath);
|
|
10635
10687
|
} catch {
|
|
10636
10688
|
}
|
|
10637
10689
|
}
|
|
@@ -10646,8 +10698,8 @@ var init_posix_runtime_lock = __esm({
|
|
|
10646
10698
|
|
|
10647
10699
|
// apps/desktop/src/platform/windows-runtime-lock.ts
|
|
10648
10700
|
import { spawn } from "node:child_process";
|
|
10649
|
-
import { randomUUID as
|
|
10650
|
-
import
|
|
10701
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
10702
|
+
import path25 from "node:path";
|
|
10651
10703
|
async function acquireWindowsRuntimeLease(lockPath, options = {}) {
|
|
10652
10704
|
const now = options.now ?? Date.now;
|
|
10653
10705
|
const assertPending = () => {
|
|
@@ -10655,9 +10707,9 @@ async function acquireWindowsRuntimeLease(lockPath, options = {}) {
|
|
|
10655
10707
|
};
|
|
10656
10708
|
assertPending();
|
|
10657
10709
|
const file = localWindowsPath(lockPath);
|
|
10658
|
-
ensureWindowsPrivateDirectory(
|
|
10710
|
+
ensureWindowsPrivateDirectory(path25.dirname(file));
|
|
10659
10711
|
assertPending();
|
|
10660
|
-
const token3 =
|
|
10712
|
+
const token3 = randomUUID9();
|
|
10661
10713
|
const child = spawn(windowsPowerShell(), windowsScriptArgs(WINDOWS_RUNTIME_LOCK_SCRIPT), {
|
|
10662
10714
|
env: { ...process.env, NIUMA_NATIVE_PATH: file, NIUMA_NATIVE_BODY: JSON.stringify({ token: token3, pid: process.pid }) },
|
|
10663
10715
|
windowsHide: true,
|
|
@@ -10765,11 +10817,11 @@ try {
|
|
|
10765
10817
|
});
|
|
10766
10818
|
|
|
10767
10819
|
// apps/desktop/src/platform/runtime-lock.ts
|
|
10768
|
-
import
|
|
10769
|
-
import
|
|
10820
|
+
import fs21 from "node:fs";
|
|
10821
|
+
import path26 from "node:path";
|
|
10770
10822
|
function ensureRuntimeLeaseDirectory(lockPath) {
|
|
10771
|
-
if (desktopPlatform().id === "windows") ensureWindowsPrivateDirectory(
|
|
10772
|
-
else
|
|
10823
|
+
if (desktopPlatform().id === "windows") ensureWindowsPrivateDirectory(path26.dirname(lockPath));
|
|
10824
|
+
else fs21.mkdirSync(path26.dirname(lockPath), { recursive: true, mode: 448 });
|
|
10773
10825
|
}
|
|
10774
10826
|
async function acquireRuntimeLease(lockPath, options = {}) {
|
|
10775
10827
|
if (desktopPlatform().id === "windows") return acquireWindowsRuntimeLease(lockPath, options);
|
|
@@ -10989,7 +11041,7 @@ var init_startup_coordinator = __esm({
|
|
|
10989
11041
|
|
|
10990
11042
|
// apps/desktop/src/daemon/error-log.ts
|
|
10991
11043
|
import { z } from "zod";
|
|
10992
|
-
import
|
|
11044
|
+
import path27 from "node:path";
|
|
10993
11045
|
function writeErrorAuditBestEffort(logger, entry) {
|
|
10994
11046
|
try {
|
|
10995
11047
|
logger?.write(entry);
|
|
@@ -11188,7 +11240,7 @@ function createLogFile(errorsDir, now, files) {
|
|
|
11188
11240
|
const timestamp = now.toISOString().replace(/[:.]/g, "-");
|
|
11189
11241
|
for (let index = 0; ; index += 1) {
|
|
11190
11242
|
const suffix = index === 0 ? "" : `-${index}`;
|
|
11191
|
-
const filePath =
|
|
11243
|
+
const filePath = path27.join(errorsDir, `${timestamp}-${process.pid}${suffix}.ndjson`);
|
|
11192
11244
|
try {
|
|
11193
11245
|
return files.create(filePath);
|
|
11194
11246
|
} catch (error2) {
|
|
@@ -11202,7 +11254,7 @@ function createErrorAuditLogger(options = {}) {
|
|
|
11202
11254
|
if (!isSafeInteger(maxBytes, 1)) throw new NiumaError("INVALID_ARGUMENT", "\u9519\u8BEF\u5BA1\u8BA1\u65E5\u5FD7\u5BB9\u91CF\u5FC5\u987B\u662F\u6B63\u6574\u6570");
|
|
11203
11255
|
const runtimeDir = options.runtimeDir ?? ensureDaemonRuntimeDir();
|
|
11204
11256
|
const files = options.files ?? privateLogFiles;
|
|
11205
|
-
const errorsDir =
|
|
11257
|
+
const errorsDir = path27.join(runtimeDir, "errors");
|
|
11206
11258
|
files.ensureDirectory(errorsDir);
|
|
11207
11259
|
cleanupExpiredDaemonLogs({ runtimeDir, files, now: () => now().getTime() });
|
|
11208
11260
|
let currentFile = createLogFile(errorsDir, now(), files);
|
|
@@ -11655,13 +11707,13 @@ var init_error_log = __esm({
|
|
|
11655
11707
|
});
|
|
11656
11708
|
|
|
11657
11709
|
// apps/desktop/src/appserver/startup-failure.ts
|
|
11658
|
-
import { randomUUID as
|
|
11710
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
11659
11711
|
import { z as z2 } from "zod";
|
|
11660
11712
|
function codexStartupFailure(reason, logger) {
|
|
11661
11713
|
const error2 = new NiumaError(reason === "missing" ? "CODEX_NOT_FOUND" : "APP_SERVER_START_FAILED", MESSAGES[reason], { reason });
|
|
11662
11714
|
if (logger) writeErrorAuditBestEffort(logger, {
|
|
11663
11715
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11664
|
-
failureId: `fail_${
|
|
11716
|
+
failureId: `fail_${randomUUID10()}`,
|
|
11665
11717
|
service: "desktop",
|
|
11666
11718
|
component: "app_server",
|
|
11667
11719
|
channel: "internal",
|
|
@@ -11675,7 +11727,7 @@ function codexStartupFailure(reason, logger) {
|
|
|
11675
11727
|
function auditCodexStartupCleanupFailure(logger) {
|
|
11676
11728
|
writeErrorAuditBestEffort(logger, {
|
|
11677
11729
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11678
|
-
failureId: `fail_${
|
|
11730
|
+
failureId: `fail_${randomUUID10()}`,
|
|
11679
11731
|
service: "desktop",
|
|
11680
11732
|
component: "app_server",
|
|
11681
11733
|
channel: "internal",
|
|
@@ -11739,9 +11791,9 @@ var init_startup_failure = __esm({
|
|
|
11739
11791
|
|
|
11740
11792
|
// apps/desktop/src/platform/windows-port-owner.ts
|
|
11741
11793
|
import { execFile as execFile4 } from "node:child_process";
|
|
11742
|
-
import
|
|
11794
|
+
import path28 from "node:path";
|
|
11743
11795
|
function execute(file, args) {
|
|
11744
|
-
const executable =
|
|
11796
|
+
const executable = path28.join(process.env.SystemRoot ?? "C:\\Windows", "System32", file);
|
|
11745
11797
|
return new Promise((resolve5, reject3) => execFile4(executable, [...args], {
|
|
11746
11798
|
windowsHide: true,
|
|
11747
11799
|
encoding: "utf8",
|
|
@@ -12227,8 +12279,8 @@ var init_config = __esm({
|
|
|
12227
12279
|
|
|
12228
12280
|
// apps/desktop/src/daemon/launcher.ts
|
|
12229
12281
|
import { spawn as spawn2 } from "node:child_process";
|
|
12230
|
-
import
|
|
12231
|
-
import
|
|
12282
|
+
import fs22 from "node:fs";
|
|
12283
|
+
import path29 from "node:path";
|
|
12232
12284
|
function daemonStartFailed() {
|
|
12233
12285
|
return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
|
|
12234
12286
|
}
|
|
@@ -12254,9 +12306,9 @@ function currentCliScriptPath() {
|
|
|
12254
12306
|
const scriptPath = process.argv[1];
|
|
12255
12307
|
if (!scriptPath) return null;
|
|
12256
12308
|
try {
|
|
12257
|
-
return
|
|
12309
|
+
return fs22.realpathSync(scriptPath);
|
|
12258
12310
|
} catch {
|
|
12259
|
-
return
|
|
12311
|
+
return path29.resolve(scriptPath);
|
|
12260
12312
|
}
|
|
12261
12313
|
}
|
|
12262
12314
|
function isNiumaBackgroundWorkerCommand(commandLine) {
|
|
@@ -12330,7 +12382,7 @@ function spawnBackgroundWorker(input) {
|
|
|
12330
12382
|
if (!command) {
|
|
12331
12383
|
throw new Error("daemon worker \u7F3A\u5C11\u542F\u52A8\u547D\u4EE4");
|
|
12332
12384
|
}
|
|
12333
|
-
const descriptor =
|
|
12385
|
+
const descriptor = fs22.openSync(input.logPath, "a", 384);
|
|
12334
12386
|
try {
|
|
12335
12387
|
const child = spawn2(command, argv, {
|
|
12336
12388
|
detached: input.detached,
|
|
@@ -12365,7 +12417,7 @@ function spawnBackgroundWorker(input) {
|
|
|
12365
12417
|
}
|
|
12366
12418
|
})() };
|
|
12367
12419
|
} finally {
|
|
12368
|
-
|
|
12420
|
+
fs22.closeSync(descriptor);
|
|
12369
12421
|
}
|
|
12370
12422
|
}
|
|
12371
12423
|
function consumeBackgroundWorkerCapability(env = process.env, lockPath = daemonLaunchLockPath()) {
|
|
@@ -12376,7 +12428,7 @@ function consumeBackgroundWorkerCapability(env = process.env, lockPath = daemonL
|
|
|
12376
12428
|
}
|
|
12377
12429
|
try {
|
|
12378
12430
|
validateRuntimeOwnedFile(lockPath);
|
|
12379
|
-
const lock = JSON.parse(
|
|
12431
|
+
const lock = JSON.parse(fs22.readFileSync(lockPath, "utf8"));
|
|
12380
12432
|
return typeof lock.token === "string" && lock.token === capability;
|
|
12381
12433
|
} catch {
|
|
12382
12434
|
return false;
|
|
@@ -13304,11 +13356,11 @@ var init_runtime_version = __esm({
|
|
|
13304
13356
|
retryAt = 0;
|
|
13305
13357
|
pending = null;
|
|
13306
13358
|
controller = null;
|
|
13307
|
-
setConnection(
|
|
13359
|
+
setConnection(path71) {
|
|
13308
13360
|
this.epoch++;
|
|
13309
13361
|
this.controller?.abort();
|
|
13310
13362
|
this.controller = null;
|
|
13311
|
-
this.path =
|
|
13363
|
+
this.path = path71;
|
|
13312
13364
|
this.value = null;
|
|
13313
13365
|
this.pending = null;
|
|
13314
13366
|
this.retryAt = 0;
|
|
@@ -13400,8 +13452,8 @@ var init_private_journal_types = __esm({
|
|
|
13400
13452
|
|
|
13401
13453
|
// apps/desktop/src/platform/windows-private-journal.ts
|
|
13402
13454
|
import { spawn as spawn3 } from "node:child_process";
|
|
13403
|
-
import
|
|
13404
|
-
import
|
|
13455
|
+
import fs23 from "node:fs";
|
|
13456
|
+
import path30 from "node:path";
|
|
13405
13457
|
async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
13406
13458
|
const maxSupportedBytes = (options.discardPreviousSnapshots ? 32 : 16) * 1024 * 1024;
|
|
13407
13459
|
const lockWaitMs = options.lockWaitMs ?? 0;
|
|
@@ -13412,10 +13464,10 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13412
13464
|
let directory3;
|
|
13413
13465
|
try {
|
|
13414
13466
|
file = localWindowsPath(filePath);
|
|
13415
|
-
directory3 = await ensureWindowsPrivateDirectoryAsync(
|
|
13416
|
-
for (const candidate of [file, `${file}-journal`, `${file}-wal`, `${file}-shm`,
|
|
13467
|
+
directory3 = await ensureWindowsPrivateDirectoryAsync(path30.dirname(file));
|
|
13468
|
+
for (const candidate of [file, `${file}-journal`, `${file}-wal`, `${file}-shm`, path30.join(directory3, `.${path30.basename(file)}.lock`)]) {
|
|
13417
13469
|
try {
|
|
13418
|
-
const stats =
|
|
13470
|
+
const stats = fs23.lstatSync(candidate, { bigint: true });
|
|
13419
13471
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n) throw new PrivateJournalError("unavailable");
|
|
13420
13472
|
if ((candidate === file || candidate === `${file}-journal`) && stats.size > BigInt(3 * maxBytes + 524288)) throw new PrivateJournalError("capacity");
|
|
13421
13473
|
} catch (error2) {
|
|
@@ -13425,7 +13477,7 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13425
13477
|
} catch (error2) {
|
|
13426
13478
|
throw error2 instanceof PrivateJournalError ? error2 : new PrivateJournalError("unavailable");
|
|
13427
13479
|
}
|
|
13428
|
-
const directoryIdentity2 =
|
|
13480
|
+
const directoryIdentity2 = fs23.lstatSync(directory3, { bigint: true });
|
|
13429
13481
|
const child = spawn3(windowsPowerShell(), windowsScriptArgs("& ([ScriptBlock]::Create($env:NIUMA_JOURNAL_SCRIPT))"), {
|
|
13430
13482
|
env: {
|
|
13431
13483
|
...process.env,
|
|
@@ -13517,8 +13569,8 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13517
13569
|
let identity6;
|
|
13518
13570
|
function verify() {
|
|
13519
13571
|
if (closing || exited || poisoned) throw unavailable12();
|
|
13520
|
-
const dir =
|
|
13521
|
-
const current2 =
|
|
13572
|
+
const dir = fs23.lstatSync(directory3, { bigint: true });
|
|
13573
|
+
const current2 = fs23.lstatSync(file, { bigint: true });
|
|
13522
13574
|
if (dir.dev !== directoryIdentity2.dev || dir.ino !== directoryIdentity2.ino || !dir.isDirectory() || dir.isSymbolicLink() || current2.dev !== identity6.dev || current2.ino !== identity6.ino || !current2.isFile() || current2.nlink !== 1n || current2.isSymbolicLink()) {
|
|
13523
13575
|
poisoned = true;
|
|
13524
13576
|
throw unavailable12();
|
|
@@ -13526,7 +13578,7 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13526
13578
|
}
|
|
13527
13579
|
try {
|
|
13528
13580
|
if (await response() !== "ready") throw unavailable12();
|
|
13529
|
-
identity6 =
|
|
13581
|
+
identity6 = fs23.lstatSync(file, { bigint: true });
|
|
13530
13582
|
verify();
|
|
13531
13583
|
} catch (error2) {
|
|
13532
13584
|
await close();
|
|
@@ -13760,9 +13812,9 @@ try {
|
|
|
13760
13812
|
});
|
|
13761
13813
|
|
|
13762
13814
|
// apps/desktop/src/platform/private-journal.ts
|
|
13763
|
-
import
|
|
13764
|
-
import
|
|
13765
|
-
import { randomUUID as
|
|
13815
|
+
import fs24 from "node:fs";
|
|
13816
|
+
import path31 from "node:path";
|
|
13817
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
13766
13818
|
function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
13767
13819
|
const policy = platform2.privateJournal;
|
|
13768
13820
|
if (platform2.nodePlatform !== process.platform || platform2.capabilities.submissionJournal !== "implemented") {
|
|
@@ -13770,9 +13822,9 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13770
13822
|
}
|
|
13771
13823
|
if (platform2.id === "windows") return openWindowsPrivateJournal(filePath, maxBytes);
|
|
13772
13824
|
if (policy.lockFlags === null) throw new PrivateJournalError("unavailable");
|
|
13773
|
-
const file =
|
|
13774
|
-
const directory3 =
|
|
13775
|
-
const lockPath =
|
|
13825
|
+
const file = path31.resolve(filePath);
|
|
13826
|
+
const directory3 = path31.dirname(file);
|
|
13827
|
+
const lockPath = path31.join(directory3, `.${path31.basename(file)}.lock`);
|
|
13776
13828
|
let directoryFd;
|
|
13777
13829
|
let lockFd;
|
|
13778
13830
|
let fileStat = null;
|
|
@@ -13782,11 +13834,11 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13782
13834
|
const trusted5 = (stats, directory4 = false) => policy.trustedNode(stats, directory4);
|
|
13783
13835
|
function verifyOwnership() {
|
|
13784
13836
|
if (closed || poisoned) throw new PrivateJournalError("unavailable");
|
|
13785
|
-
const dir =
|
|
13786
|
-
const lock =
|
|
13787
|
-
if (!trusted5(dir, true) || !sameFile(dir,
|
|
13837
|
+
const dir = fs24.lstatSync(directory3);
|
|
13838
|
+
const lock = fs24.lstatSync(lockPath);
|
|
13839
|
+
if (!trusted5(dir, true) || !sameFile(dir, fs24.fstatSync(directoryFd)) || !trusted5(lock) || !sameFile(lock, fs24.fstatSync(lockFd))) throw new PrivateJournalError("unavailable");
|
|
13788
13840
|
try {
|
|
13789
|
-
const current2 =
|
|
13841
|
+
const current2 = fs24.lstatSync(file);
|
|
13790
13842
|
if (!trusted5(current2) || fileStat === null || !sameFile(current2, fileStat)) throw new PrivateJournalError("unavailable");
|
|
13791
13843
|
} catch (error2) {
|
|
13792
13844
|
if (error2.code !== "ENOENT" || fileStat !== null) throw error2;
|
|
@@ -13795,29 +13847,29 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13795
13847
|
function close() {
|
|
13796
13848
|
closed = true;
|
|
13797
13849
|
try {
|
|
13798
|
-
if (lockFd !== void 0)
|
|
13850
|
+
if (lockFd !== void 0) fs24.closeSync(lockFd);
|
|
13799
13851
|
} finally {
|
|
13800
13852
|
lockFd = void 0;
|
|
13801
13853
|
if (directoryFd !== void 0) {
|
|
13802
|
-
|
|
13854
|
+
fs24.closeSync(directoryFd);
|
|
13803
13855
|
directoryFd = void 0;
|
|
13804
13856
|
}
|
|
13805
13857
|
}
|
|
13806
13858
|
}
|
|
13807
13859
|
try {
|
|
13808
|
-
|
|
13809
|
-
if (!trusted5(
|
|
13810
|
-
directoryFd =
|
|
13811
|
-
if (!trusted5(
|
|
13860
|
+
fs24.mkdirSync(directory3, { recursive: true, mode: 448 });
|
|
13861
|
+
if (!trusted5(fs24.lstatSync(directory3), true)) throw new PrivateJournalError("unavailable");
|
|
13862
|
+
directoryFd = fs24.openSync(directory3, fs24.constants.O_RDONLY | fs24.constants.O_NOFOLLOW);
|
|
13863
|
+
if (!trusted5(fs24.fstatSync(directoryFd), true)) throw new PrivateJournalError("unavailable");
|
|
13812
13864
|
try {
|
|
13813
|
-
if (!trusted5(
|
|
13865
|
+
if (!trusted5(fs24.lstatSync(lockPath))) throw new PrivateJournalError("unavailable");
|
|
13814
13866
|
} catch (error2) {
|
|
13815
13867
|
if (error2.code !== "ENOENT") throw error2;
|
|
13816
13868
|
}
|
|
13817
|
-
lockFd =
|
|
13818
|
-
if (!trusted5(
|
|
13869
|
+
lockFd = fs24.openSync(lockPath, policy.lockFlags, 384);
|
|
13870
|
+
if (!trusted5(fs24.fstatSync(lockFd)) || !sameFile(fs24.fstatSync(lockFd), fs24.lstatSync(lockPath))) throw new PrivateJournalError("unavailable");
|
|
13819
13871
|
try {
|
|
13820
|
-
fileStat =
|
|
13872
|
+
fileStat = fs24.lstatSync(file);
|
|
13821
13873
|
if (!trusted5(fileStat)) throw new PrivateJournalError("unavailable");
|
|
13822
13874
|
if (fileStat.size > maxBytes) throw new PrivateJournalError("capacity");
|
|
13823
13875
|
} catch (error2) {
|
|
@@ -13833,45 +13885,45 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13833
13885
|
read() {
|
|
13834
13886
|
verifyOwnership();
|
|
13835
13887
|
if (fileStat === null) return null;
|
|
13836
|
-
const fd =
|
|
13888
|
+
const fd = fs24.openSync(file, fs24.constants.O_RDONLY | fs24.constants.O_NOFOLLOW);
|
|
13837
13889
|
try {
|
|
13838
|
-
if (!trusted5(
|
|
13890
|
+
if (!trusted5(fs24.fstatSync(fd)) || !sameFile(fileStat, fs24.fstatSync(fd))) throw new PrivateJournalError("unavailable");
|
|
13839
13891
|
const buffer = Buffer.alloc(maxBytes + 1);
|
|
13840
|
-
const length =
|
|
13892
|
+
const length = fs24.readSync(fd, buffer, 0, buffer.length, 0);
|
|
13841
13893
|
if (length > maxBytes) throw new PrivateJournalError("capacity");
|
|
13842
13894
|
verifyOwnership();
|
|
13843
13895
|
return buffer.subarray(0, length).toString("utf8");
|
|
13844
13896
|
} finally {
|
|
13845
|
-
|
|
13897
|
+
fs24.closeSync(fd);
|
|
13846
13898
|
}
|
|
13847
13899
|
},
|
|
13848
13900
|
commit(body) {
|
|
13849
13901
|
if (Buffer.byteLength(body) > maxBytes) throw new PrivateJournalError("capacity");
|
|
13850
|
-
const temporary =
|
|
13902
|
+
const temporary = path31.join(directory3, `.${path31.basename(file)}.${randomUUID11()}.tmp`);
|
|
13851
13903
|
let created = false;
|
|
13852
13904
|
try {
|
|
13853
13905
|
verifyOwnership();
|
|
13854
|
-
const fd =
|
|
13906
|
+
const fd = fs24.openSync(temporary, fs24.constants.O_WRONLY | fs24.constants.O_CREAT | fs24.constants.O_EXCL | fs24.constants.O_NOFOLLOW, 384);
|
|
13855
13907
|
created = true;
|
|
13856
13908
|
try {
|
|
13857
|
-
if (!trusted5(
|
|
13858
|
-
|
|
13859
|
-
|
|
13909
|
+
if (!trusted5(fs24.fstatSync(fd))) throw new PrivateJournalError("unavailable");
|
|
13910
|
+
fs24.writeFileSync(fd, body, "utf8");
|
|
13911
|
+
fs24.fsyncSync(fd);
|
|
13860
13912
|
} finally {
|
|
13861
|
-
|
|
13913
|
+
fs24.closeSync(fd);
|
|
13862
13914
|
}
|
|
13863
13915
|
verifyOwnership();
|
|
13864
|
-
|
|
13916
|
+
fs24.renameSync(temporary, file);
|
|
13865
13917
|
created = false;
|
|
13866
|
-
fileStat =
|
|
13867
|
-
|
|
13918
|
+
fileStat = fs24.lstatSync(file);
|
|
13919
|
+
fs24.fsyncSync(directoryFd);
|
|
13868
13920
|
} catch {
|
|
13869
13921
|
poisoned = true;
|
|
13870
13922
|
throw new PrivateJournalError("write_failed");
|
|
13871
13923
|
} finally {
|
|
13872
13924
|
if (created) {
|
|
13873
13925
|
try {
|
|
13874
|
-
|
|
13926
|
+
fs24.unlinkSync(temporary);
|
|
13875
13927
|
} catch {
|
|
13876
13928
|
}
|
|
13877
13929
|
}
|
|
@@ -14219,20 +14271,20 @@ function sendJson(response, httpStatus, body) {
|
|
|
14219
14271
|
}
|
|
14220
14272
|
function zodErrorToHttpApiError(error2) {
|
|
14221
14273
|
const messages = error2.issues.map((issue) => {
|
|
14222
|
-
const
|
|
14274
|
+
const path71 = issue.path.join(".") || "\u53C2\u6570";
|
|
14223
14275
|
if (issue.code === "custom") {
|
|
14224
14276
|
return issue.message;
|
|
14225
14277
|
}
|
|
14226
14278
|
if (issue.code === "invalid_type" && issue.received === "undefined") {
|
|
14227
|
-
return `${
|
|
14279
|
+
return `${path71}\u4E0D\u80FD\u4E3A\u7A7A`;
|
|
14228
14280
|
}
|
|
14229
14281
|
if (issue.code === "invalid_type") {
|
|
14230
|
-
return `${
|
|
14282
|
+
return `${path71}\u7C7B\u578B\u9519\u8BEF`;
|
|
14231
14283
|
}
|
|
14232
14284
|
if (issue.code === "unrecognized_keys") {
|
|
14233
14285
|
return `\u4E0D\u652F\u6301\u7684\u53C2\u6570: ${issue.keys.join(",")}`;
|
|
14234
14286
|
}
|
|
14235
|
-
return `${
|
|
14287
|
+
return `${path71}\u683C\u5F0F\u9519\u8BEF`;
|
|
14236
14288
|
});
|
|
14237
14289
|
const custom = error2.issues.some((issue) => issue.code === "custom");
|
|
14238
14290
|
const missing4 = error2.issues.some(
|
|
@@ -14535,7 +14587,7 @@ var init_transfer_diagnostics = __esm({
|
|
|
14535
14587
|
});
|
|
14536
14588
|
|
|
14537
14589
|
// apps/desktop/src/attachments/transfer-registry.ts
|
|
14538
|
-
import { randomBytes as randomBytes3, randomUUID as
|
|
14590
|
+
import { randomBytes as randomBytes3, randomUUID as randomUUID12 } from "node:crypto";
|
|
14539
14591
|
function fail14(kind) {
|
|
14540
14592
|
const e = ATTACHMENT_TRANSFER_ERRORS[kind];
|
|
14541
14593
|
throw new AttachmentTransferError(e.code, e.message);
|
|
@@ -14704,7 +14756,7 @@ function createAttachmentTransferRegistry(options) {
|
|
|
14704
14756
|
recordAttachmentDiagnostic(options.diagnostic, { phase: "prepare", reason: active2.has(scope.bindingId) ? "active_stream" : "attempt_capacity", code: 400606 });
|
|
14705
14757
|
fail14("capacity");
|
|
14706
14758
|
}
|
|
14707
|
-
const expires = Math.min(scope.expiresAtMs, u.owner.expiresAtMs), transferId =
|
|
14759
|
+
const expires = Math.min(scope.expiresAtMs, u.owner.expiresAtMs), transferId = randomUUID12(), epochId = randomUUID12();
|
|
14708
14760
|
const secret = randomBytes3(32);
|
|
14709
14761
|
const encoded = encodeBase64Url(secret);
|
|
14710
14762
|
secret.fill(0);
|
|
@@ -15101,7 +15153,7 @@ var init_connection_handoff_source = __esm({
|
|
|
15101
15153
|
});
|
|
15102
15154
|
|
|
15103
15155
|
// apps/desktop/src/daemon/project-list-stream.ts
|
|
15104
|
-
import { randomUUID as
|
|
15156
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
15105
15157
|
function createProjectListStreamHub(dependencies) {
|
|
15106
15158
|
const subscriptions = /* @__PURE__ */ new Map();
|
|
15107
15159
|
const sources = /* @__PURE__ */ new Map();
|
|
@@ -15113,7 +15165,7 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15113
15165
|
]);
|
|
15114
15166
|
const nextIds = visibleIds(next.snapshot);
|
|
15115
15167
|
const removed = [...visibleIds(state.source.current.snapshot.snapshot)].some((id5) => !nextIds.has(id5));
|
|
15116
|
-
if (state.handoff && removed) state.source.replaceEpoch(
|
|
15168
|
+
if (state.handoff && removed) state.source.replaceEpoch(randomUUID13(), next);
|
|
15117
15169
|
else state.source.publish(next);
|
|
15118
15170
|
};
|
|
15119
15171
|
const logProjection = (type, revision4, diagnostic) => {
|
|
@@ -15138,7 +15190,7 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15138
15190
|
}
|
|
15139
15191
|
};
|
|
15140
15192
|
const attach = (state, scope, send, kind) => {
|
|
15141
|
-
const subscriptionId =
|
|
15193
|
+
const subscriptionId = randomUUID13();
|
|
15142
15194
|
let revision4 = 0;
|
|
15143
15195
|
let initializing = true;
|
|
15144
15196
|
const pending = [];
|
|
@@ -15342,12 +15394,12 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15342
15394
|
processEvent(state, event);
|
|
15343
15395
|
});
|
|
15344
15396
|
state.snapshot = readSnapshot(state);
|
|
15345
|
-
const sourceId =
|
|
15397
|
+
const sourceId = randomUUID13();
|
|
15346
15398
|
let unregister = () => {
|
|
15347
15399
|
};
|
|
15348
15400
|
state.source = new HandoffSource({
|
|
15349
15401
|
sourceId,
|
|
15350
|
-
epoch:
|
|
15402
|
+
epoch: randomUUID13(),
|
|
15351
15403
|
initial: { snapshot: state.snapshot, windows: {}, update: null },
|
|
15352
15404
|
onUnused: () => {
|
|
15353
15405
|
sources.delete(sourceId);
|
|
@@ -17681,7 +17733,7 @@ var init_routes = __esm({
|
|
|
17681
17733
|
});
|
|
17682
17734
|
|
|
17683
17735
|
// apps/desktop/src/http/sse.ts
|
|
17684
|
-
import { randomUUID as
|
|
17736
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
17685
17737
|
function encodeSseFrame(frame) {
|
|
17686
17738
|
return [
|
|
17687
17739
|
...frame.id ? [`id: ${frame.id}`] : [],
|
|
@@ -18009,7 +18061,7 @@ var init_sse = __esm({
|
|
|
18009
18061
|
throw new HttpApiError(200, 400604, "SSE\u4EA4\u63A5\u5BB9\u91CF\u4E0D\u8DB3");
|
|
18010
18062
|
}
|
|
18011
18063
|
return Array.from({ length: count }, () => {
|
|
18012
|
-
const id5 =
|
|
18064
|
+
const id5 = randomUUID14();
|
|
18013
18065
|
this.reservedSlots.add(id5);
|
|
18014
18066
|
return { id: id5, release: () => {
|
|
18015
18067
|
this.reservedSlots.delete(id5);
|
|
@@ -18055,7 +18107,7 @@ var init_sse = __esm({
|
|
|
18055
18107
|
});
|
|
18056
18108
|
|
|
18057
18109
|
// apps/desktop/src/http/server.ts
|
|
18058
|
-
import { randomUUID as
|
|
18110
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
18059
18111
|
import http from "node:http";
|
|
18060
18112
|
import { isIP as isIP3 } from "node:net";
|
|
18061
18113
|
function safeAuditIdentifier(value) {
|
|
@@ -18609,7 +18661,7 @@ var init_server = __esm({
|
|
|
18609
18661
|
try {
|
|
18610
18662
|
this.errorLogger?.write({
|
|
18611
18663
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18612
|
-
failureId: diagnostic?.failureId ?? `fail_${
|
|
18664
|
+
failureId: diagnostic?.failureId ?? `fail_${randomUUID15()}`,
|
|
18613
18665
|
service: "desktop",
|
|
18614
18666
|
component: "gateway",
|
|
18615
18667
|
channel: request2.channel,
|
|
@@ -18804,7 +18856,7 @@ var init_args = __esm({
|
|
|
18804
18856
|
|
|
18805
18857
|
// apps/desktop/src/autostart/production.ts
|
|
18806
18858
|
import os5 from "node:os";
|
|
18807
|
-
import
|
|
18859
|
+
import path32 from "node:path";
|
|
18808
18860
|
function autostartConfig(args, relayOrigin) {
|
|
18809
18861
|
const version2 = desktopReleaseVersion();
|
|
18810
18862
|
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");
|
|
@@ -18813,7 +18865,7 @@ function autostartConfig(args, relayOrigin) {
|
|
|
18813
18865
|
releaseVersion: version2,
|
|
18814
18866
|
nodeExecutable: process.execPath,
|
|
18815
18867
|
home: os5.homedir(),
|
|
18816
|
-
path: [
|
|
18868
|
+
path: [path32.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
|
|
18817
18869
|
...process.env.CODEX_HOME ? { codexHome: process.env.CODEX_HOME } : {},
|
|
18818
18870
|
relayOrigin: resolveRelayConfig({ relay_origin: relayOrigin ?? resolveRelayStartupOrigin({ env: process.env, cliOrigin: args.flags.relayOrigin }) }).origin,
|
|
18819
18871
|
pushServerOrigin: resolvePushServerOrigin(process.env),
|
|
@@ -18878,19 +18930,19 @@ var init_production = __esm({
|
|
|
18878
18930
|
});
|
|
18879
18931
|
|
|
18880
18932
|
// apps/desktop/src/lite-install/dmg.mjs
|
|
18881
|
-
import
|
|
18933
|
+
import fs25 from "node:fs/promises";
|
|
18882
18934
|
import os6 from "node:os";
|
|
18883
|
-
import
|
|
18935
|
+
import path33 from "node:path";
|
|
18884
18936
|
import { execFile as execFile7 } from "node:child_process";
|
|
18885
18937
|
import { promisify as promisify4 } from "node:util";
|
|
18886
18938
|
async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
18887
|
-
const root = await
|
|
18888
|
-
const mount =
|
|
18889
|
-
await
|
|
18939
|
+
const root = await fs25.realpath(await fs25.mkdtemp(path33.join(os6.tmpdir(), "niuma-lite-mount-")));
|
|
18940
|
+
const mount = path33.join(root, "volume");
|
|
18941
|
+
await fs25.mkdir(mount, { mode: 448 });
|
|
18890
18942
|
let device, attached = false, uncertain = false;
|
|
18891
18943
|
const parse = async (xml2) => {
|
|
18892
|
-
const file =
|
|
18893
|
-
await
|
|
18944
|
+
const file = path33.join(root, "mount.plist");
|
|
18945
|
+
await fs25.writeFile(file, xml2, { mode: 384 });
|
|
18894
18946
|
return JSON.parse(await run("/usr/bin/plutil", ["-convert", "json", "-o", "-", file]));
|
|
18895
18947
|
};
|
|
18896
18948
|
const find = (data) => {
|
|
@@ -18912,13 +18964,13 @@ async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
|
18912
18964
|
}
|
|
18913
18965
|
throw error2;
|
|
18914
18966
|
}
|
|
18915
|
-
const app =
|
|
18916
|
-
if (!(await
|
|
18917
|
-
for (const entry of await
|
|
18967
|
+
const app = path33.join(mount, "Niuma Lite.app");
|
|
18968
|
+
if (!(await fs25.lstat(app)).isDirectory() || await fs25.realpath(app) !== path33.join(await fs25.realpath(mount), "Niuma Lite.app")) throw Error("DMG \u5E94\u7528\u8DEF\u5F84\u65E0\u6548");
|
|
18969
|
+
for (const entry of await fs25.readdir(app, { recursive: true, withFileTypes: true })) {
|
|
18918
18970
|
if (!entry.isDirectory() && !entry.isFile()) throw Error("DMG \u5E94\u7528\u5305\u542B\u94FE\u63A5\u6216\u7279\u6B8A\u6587\u4EF6");
|
|
18919
18971
|
}
|
|
18920
|
-
const destination =
|
|
18921
|
-
await
|
|
18972
|
+
const destination = path33.join(stage, "app");
|
|
18973
|
+
await fs25.cp(app, destination, { recursive: true, errorOnExist: true, force: false });
|
|
18922
18974
|
await verify(destination);
|
|
18923
18975
|
} finally {
|
|
18924
18976
|
if (device) {
|
|
@@ -18928,7 +18980,7 @@ async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
|
18928
18980
|
throw Error(`\u65E0\u6CD5\u5378\u8F7D\u672C\u6B21 DMG ${device} (${mount})\uFF1A${error2.message}`);
|
|
18929
18981
|
}
|
|
18930
18982
|
} else if (uncertain) throw Error(`\u65E0\u6CD5\u786E\u8BA4\u672C\u6B21 DMG \u662F\u5426\u5DF2\u5378\u8F7D\uFF0C\u8BF7\u68C0\u67E5\u6302\u8F7D\u70B9 ${mount}`);
|
|
18931
|
-
await
|
|
18983
|
+
await fs25.rm(root, { recursive: true, force: true });
|
|
18932
18984
|
}
|
|
18933
18985
|
}
|
|
18934
18986
|
var exec3, systemRun;
|
|
@@ -18941,12 +18993,12 @@ var init_dmg = __esm({
|
|
|
18941
18993
|
});
|
|
18942
18994
|
|
|
18943
18995
|
// apps/desktop/src/lite-install/bundled-resources.mjs
|
|
18944
|
-
import
|
|
18996
|
+
import fs26 from "node:fs/promises";
|
|
18945
18997
|
import { createReadStream } from "node:fs";
|
|
18946
|
-
import
|
|
18998
|
+
import path34 from "node:path";
|
|
18947
18999
|
import { createHash as createHash5 } from "node:crypto";
|
|
18948
19000
|
async function verifyLocalArtifact(file, artifact) {
|
|
18949
|
-
const st = await
|
|
19001
|
+
const st = await fs26.lstat(file);
|
|
18950
19002
|
if (!st.isFile() || st.size !== artifact.size) throw Error("\u672C\u5730\u8D44\u6E90\u7C7B\u578B\u6216\u957F\u5EA6\u65E0\u6548");
|
|
18951
19003
|
let size2 = 0;
|
|
18952
19004
|
const hash3 = createHash5("sha256");
|
|
@@ -18959,14 +19011,14 @@ async function verifyLocalArtifact(file, artifact) {
|
|
|
18959
19011
|
}
|
|
18960
19012
|
async function resolveBundledResources(packageRoot, manifest, arch) {
|
|
18961
19013
|
if (manifest.schema !== 2) throw Error("\u9700\u8981\u672C\u5730\u8D44\u6E90\u6E05\u5355");
|
|
18962
|
-
const root = await
|
|
18963
|
-
const resources =
|
|
18964
|
-
if (!(await
|
|
19014
|
+
const root = await fs26.realpath(packageRoot), result = {};
|
|
19015
|
+
const resources = path34.join(root, "resources");
|
|
19016
|
+
if (!(await fs26.lstat(resources)).isDirectory() || await fs26.realpath(resources) !== resources) throw Error("\u8D44\u6E90\u76EE\u5F55\u4E0D\u80FD\u662F\u94FE\u63A5");
|
|
18965
19017
|
for (const kind of ["app", "runtime"]) {
|
|
18966
|
-
const a = manifest.artifacts[`darwin-${arch}`][kind], file =
|
|
18967
|
-
if (
|
|
19018
|
+
const a = manifest.artifacts[`darwin-${arch}`][kind], file = path34.resolve(root, a.path);
|
|
19019
|
+
if (path34.dirname(file) !== resources) throw Error("\u672C\u5730\u8D44\u6E90\u8DEF\u5F84\u9003\u9038");
|
|
18968
19020
|
await verifyLocalArtifact(file, a);
|
|
18969
|
-
if (await
|
|
19021
|
+
if (await fs26.realpath(file) !== file) throw Error("\u8D44\u6E90\u6587\u4EF6\u4E0D\u80FD\u662F\u94FE\u63A5");
|
|
18970
19022
|
result[kind] = file;
|
|
18971
19023
|
}
|
|
18972
19024
|
return result;
|
|
@@ -18983,13 +19035,13 @@ var init_bundled_resources = __esm({
|
|
|
18983
19035
|
});
|
|
18984
19036
|
|
|
18985
19037
|
// apps/desktop/src/lite-install/installer.ts
|
|
18986
|
-
import
|
|
19038
|
+
import fs27 from "node:fs/promises";
|
|
18987
19039
|
import sync from "node:fs";
|
|
18988
|
-
import
|
|
18989
|
-
import { randomUUID as
|
|
19040
|
+
import path35 from "node:path";
|
|
19041
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
18990
19042
|
async function exists(file) {
|
|
18991
19043
|
try {
|
|
18992
|
-
await
|
|
19044
|
+
await fs27.lstat(file);
|
|
18993
19045
|
return true;
|
|
18994
19046
|
} catch (e) {
|
|
18995
19047
|
if (e.code === "ENOENT") return false;
|
|
@@ -18998,61 +19050,61 @@ async function exists(file) {
|
|
|
18998
19050
|
}
|
|
18999
19051
|
async function readConfig(file) {
|
|
19000
19052
|
if (!await exists(file)) return null;
|
|
19001
|
-
const v = JSON.parse(await
|
|
19053
|
+
const v = JSON.parse(await fs27.readFile(file, "utf8"));
|
|
19002
19054
|
if (v.schema !== 1 || typeof v.combinationId !== "string" || typeof v.runtimeDir !== "string" || typeof v.nodePath !== "string") throw Error("\u8FD0\u884C\u914D\u7F6E\u635F\u574F\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u76EE\u5F55");
|
|
19003
19055
|
return v;
|
|
19004
19056
|
}
|
|
19005
19057
|
async function atomic2(file, value) {
|
|
19006
|
-
const temp = file + "." +
|
|
19007
|
-
await
|
|
19008
|
-
const fd = await
|
|
19058
|
+
const temp = file + "." + randomUUID16();
|
|
19059
|
+
await fs27.writeFile(temp, JSON.stringify(value) + "\n", { mode: 384, flag: "wx" });
|
|
19060
|
+
const fd = await fs27.open(temp, "r");
|
|
19009
19061
|
try {
|
|
19010
19062
|
await fd.sync();
|
|
19011
19063
|
} finally {
|
|
19012
19064
|
await fd.close();
|
|
19013
19065
|
}
|
|
19014
|
-
await
|
|
19066
|
+
await fs27.rename(temp, file);
|
|
19015
19067
|
}
|
|
19016
19068
|
async function installLite(o) {
|
|
19017
19069
|
const result = await installLiteLocked(o);
|
|
19018
|
-
await o.open(
|
|
19070
|
+
await o.open(path35.join(o.installRoot, "Niuma Lite.app"));
|
|
19019
19071
|
return result;
|
|
19020
19072
|
}
|
|
19021
19073
|
async function installLiteLocked(o) {
|
|
19022
19074
|
if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(o.version)) throw Error("\u9700\u8981\u660E\u786E\u7684\u53D1\u5E03\u7248\u672C");
|
|
19023
19075
|
await privateDirectory(o.runtimeRoot);
|
|
19024
19076
|
await privateDirectory(o.installRoot);
|
|
19025
|
-
await privateDirectory(
|
|
19026
|
-
const lock = sync.openSync(
|
|
19027
|
-
const app =
|
|
19077
|
+
await privateDirectory(path35.join(o.runtimeRoot, "versions"));
|
|
19078
|
+
const lock = sync.openSync(path35.join(o.runtimeRoot, "install.lock"), sync.constants.O_RDWR | sync.constants.O_CREAT | sync.constants.O_NOFOLLOW | sync.constants.O_NONBLOCK | 32, 384);
|
|
19079
|
+
const app = path35.join(o.installRoot, "Niuma Lite.app"), current2 = path35.join(o.runtimeRoot, "current.json"), journal = path35.join(o.runtimeRoot, "transaction.json");
|
|
19028
19080
|
const recover = async () => {
|
|
19029
19081
|
if (!await exists(journal)) return;
|
|
19030
|
-
const txn = JSON.parse(await
|
|
19031
|
-
if (txn.schema !== 1 ||
|
|
19032
|
-
if (
|
|
19082
|
+
const txn = JSON.parse(await fs27.readFile(journal, "utf8"));
|
|
19083
|
+
if (txn.schema !== 1 || path35.dirname(txn.stage) !== o.runtimeRoot || !path35.basename(txn.stage).startsWith(".stage-")) throw Error("\u66F4\u65B0\u8BB0\u5F55\u65E0\u6548\uFF0C\u62D2\u7EDD\u4FEE\u6539\u5E94\u7528");
|
|
19084
|
+
if (path35.dirname(txn.backup) !== o.installRoot || !path35.basename(txn.backup).startsWith(".Niuma Lite.previous-") || path35.dirname(txn.stagedApp) !== o.installRoot || !path35.basename(txn.stagedApp).startsWith(".Niuma Lite.installing-")) throw Error("\u66F4\u65B0\u8BB0\u5F55\u8DEF\u5F84\u65E0\u6548");
|
|
19033
19085
|
if (await exists(app)) await o.assertOwnedApp(app);
|
|
19034
19086
|
if (await exists(txn.backup)) {
|
|
19035
19087
|
await o.assertOwnedApp(txn.backup);
|
|
19036
|
-
await
|
|
19037
|
-
await
|
|
19088
|
+
await fs27.rm(app, { recursive: true, force: true });
|
|
19089
|
+
await fs27.rename(txn.backup, app);
|
|
19038
19090
|
} else if (!txn.hadApp) {
|
|
19039
|
-
await
|
|
19091
|
+
await fs27.rm(app, { recursive: true, force: true });
|
|
19040
19092
|
}
|
|
19041
19093
|
if (txn.oldConfig) await atomic2(current2, txn.oldConfig);
|
|
19042
|
-
else await
|
|
19043
|
-
await
|
|
19044
|
-
await
|
|
19045
|
-
await
|
|
19094
|
+
else await fs27.rm(current2, { force: true });
|
|
19095
|
+
await fs27.rm(txn.stagedApp, { recursive: true, force: true });
|
|
19096
|
+
await fs27.rm(txn.stage, { recursive: true, force: true });
|
|
19097
|
+
await fs27.rm(journal);
|
|
19046
19098
|
};
|
|
19047
19099
|
try {
|
|
19048
|
-
if (await exists(
|
|
19100
|
+
if (await exists(path35.join(o.runtimeRoot, "uninstall.json"))) throw Error("\u5378\u8F7D\u5C1A\u672A\u5B8C\u6210\uFF0C\u8BF7\u5148\u91CD\u65B0\u8FD0\u884C uninstall-app");
|
|
19049
19101
|
await recover();
|
|
19050
19102
|
const previous = await readConfig(current2);
|
|
19051
19103
|
if (await exists(app)) {
|
|
19052
19104
|
if (!previous) throw Error("\u540C\u540D\u975E\u6258\u7BA1\u5E94\u7528\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6");
|
|
19053
19105
|
await o.assertOwnedApp(app);
|
|
19054
19106
|
}
|
|
19055
|
-
if (previous && !
|
|
19107
|
+
if (previous && !path35.resolve(previous.runtimeDir).startsWith(path35.resolve(o.runtimeRoot, "versions") + path35.sep)) throw Error("\u8FD0\u884C\u914D\u7F6E\u8DEF\u5F84\u4E0D\u53EF\u4FE1");
|
|
19056
19108
|
if (previous && compareVersions(previous.combinationId, o.version) > 0) throw Error("\u5DF2\u5B89\u88C5\u8F83\u65B0\u7248\u672C\uFF0C\u8BF7\u4F7F\u7528 npx niuma-codex@latest install-app");
|
|
19057
19109
|
if (previous?.combinationId === o.version && previous.nodePath === o.nodePath) {
|
|
19058
19110
|
let valid = false;
|
|
@@ -19065,39 +19117,39 @@ async function installLiteLocked(o) {
|
|
|
19065
19117
|
return { installed: false, version: o.version };
|
|
19066
19118
|
}
|
|
19067
19119
|
}
|
|
19068
|
-
const stage =
|
|
19120
|
+
const stage = path35.join(o.runtimeRoot, ".stage-" + randomUUID16());
|
|
19069
19121
|
await privateDirectory(stage);
|
|
19070
19122
|
try {
|
|
19071
19123
|
await o.prepare(stage);
|
|
19072
|
-
await o.verify(
|
|
19124
|
+
await o.verify(path35.join(stage, "app"), path35.join(stage, "runtime"));
|
|
19073
19125
|
if (previous && !await o.confirm()) throw Error("\u5DF2\u53D6\u6D88\u66F4\u65B0");
|
|
19074
19126
|
if (await exists(app)) {
|
|
19075
19127
|
if (!previous) throw Error("\u540C\u540D\u975E\u6258\u7BA1\u5E94\u7528\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6");
|
|
19076
19128
|
await o.assertOwnedApp(app);
|
|
19077
19129
|
}
|
|
19078
19130
|
await o.stopHost();
|
|
19079
|
-
const runtime =
|
|
19080
|
-
const backup =
|
|
19081
|
-
const stagedApp =
|
|
19131
|
+
const runtime = path35.join(o.runtimeRoot, "versions", o.version + "-" + randomUUID16());
|
|
19132
|
+
const backup = path35.join(o.installRoot, ".Niuma Lite.previous-" + randomUUID16() + ".app");
|
|
19133
|
+
const stagedApp = path35.join(o.installRoot, ".Niuma Lite.installing-" + randomUUID16() + ".app");
|
|
19082
19134
|
const txn = { schema: 1, stage, backup, stagedApp, oldConfig: previous, hadApp: await exists(app) };
|
|
19083
19135
|
await atomic2(journal, txn);
|
|
19084
|
-
if (txn.hadApp) await
|
|
19136
|
+
if (txn.hadApp) await fs27.rename(app, backup);
|
|
19085
19137
|
await o.checkpoint?.("app-backed-up");
|
|
19086
19138
|
if (await exists(stagedApp)) throw Error("\u5E94\u7528\u6682\u5B58\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u72B6\u6001");
|
|
19087
|
-
await
|
|
19088
|
-
await
|
|
19139
|
+
await fs27.cp(path35.join(stage, "app"), stagedApp, { recursive: true, errorOnExist: true, force: false });
|
|
19140
|
+
await fs27.rename(stagedApp, app);
|
|
19089
19141
|
await o.checkpoint?.("app-replaced");
|
|
19090
|
-
await
|
|
19142
|
+
await fs27.rename(path35.join(stage, "runtime"), runtime);
|
|
19091
19143
|
const config = { schema: 1, combinationId: o.version, daemonVersion: o.version, runtimeDir: runtime, nodePath: o.nodePath };
|
|
19092
19144
|
await atomic2(current2, config);
|
|
19093
19145
|
await o.checkpoint?.("config-replaced");
|
|
19094
|
-
await
|
|
19146
|
+
await fs27.rm(journal);
|
|
19095
19147
|
return { installed: true, version: o.version };
|
|
19096
19148
|
} catch (error2) {
|
|
19097
19149
|
await recover();
|
|
19098
19150
|
throw error2;
|
|
19099
19151
|
} finally {
|
|
19100
|
-
await
|
|
19152
|
+
await fs27.rm(stage, { recursive: true, force: true });
|
|
19101
19153
|
}
|
|
19102
19154
|
} finally {
|
|
19103
19155
|
sync.closeSync(lock);
|
|
@@ -19150,15 +19202,15 @@ var init_manifest = __esm({
|
|
|
19150
19202
|
});
|
|
19151
19203
|
|
|
19152
19204
|
// apps/desktop/src/lite-install/resources.ts
|
|
19153
|
-
import
|
|
19205
|
+
import path36 from "node:path";
|
|
19154
19206
|
import { createHash as createHash6 } from "node:crypto";
|
|
19155
19207
|
import { createWriteStream } from "node:fs";
|
|
19156
|
-
import
|
|
19208
|
+
import fs28 from "node:fs/promises";
|
|
19157
19209
|
import { Readable } from "node:stream";
|
|
19158
19210
|
import { pipeline } from "node:stream/promises";
|
|
19159
19211
|
import * as tar from "tar";
|
|
19160
19212
|
function safeArchiveEntry(name2, type) {
|
|
19161
|
-
return !name2.includes("\\") && !
|
|
19213
|
+
return !name2.includes("\\") && !path36.posix.isAbsolute(name2) && !name2.split("/").includes("..") && ["File", "Directory", "OldFile", "ContiguousFile"].includes(type);
|
|
19162
19214
|
}
|
|
19163
19215
|
async function download(a, file) {
|
|
19164
19216
|
const signal = AbortSignal.timeout(12e4);
|
|
@@ -19200,7 +19252,7 @@ async function extract(file, destination) {
|
|
|
19200
19252
|
if (!safeArchiveEntry(entry.path, entry.type) || total > 2 * 1024 * 1024 * 1024 || count > 1e5) invalid14 = true;
|
|
19201
19253
|
} });
|
|
19202
19254
|
if (invalid14) throw Error("\u53D1\u884C\u5F52\u6863\u5305\u542B\u4E0D\u5B89\u5168\u8DEF\u5F84\u6216\u94FE\u63A5");
|
|
19203
|
-
await
|
|
19255
|
+
await fs28.mkdir(destination, { recursive: true, mode: 448 });
|
|
19204
19256
|
await tar.x({ file, cwd: destination, strict: true, preservePaths: false, noChmod: true, noMtime: true });
|
|
19205
19257
|
}
|
|
19206
19258
|
var init_resources = __esm({
|
|
@@ -19211,17 +19263,16 @@ var init_resources = __esm({
|
|
|
19211
19263
|
});
|
|
19212
19264
|
|
|
19213
19265
|
// apps/desktop/src/lite-install/production.ts
|
|
19214
|
-
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
19215
19266
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
19216
|
-
import
|
|
19217
|
-
import
|
|
19267
|
+
import fs29 from "node:fs/promises";
|
|
19268
|
+
import path37 from "node:path";
|
|
19218
19269
|
import os7 from "node:os";
|
|
19219
19270
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
19220
19271
|
async function runLiteInstall() {
|
|
19221
19272
|
if (process.platform !== "darwin") throw Error("\u8F7B\u91CF\u684C\u9762\u5E94\u7528\u4EC5\u652F\u6301 macOS\uFF0C\u8BF7\u4F7F\u7528 --background");
|
|
19222
19273
|
const version2 = desktopReleaseVersion();
|
|
19223
19274
|
if (!version2 || false || false) throw Error("\u6B64\u7248\u672C\u5C1A\u672A\u914D\u7F6E Tauri \u8F7B\u91CF\u53D1\u884C\u8D44\u6E90\uFF0C\u6682\u4E0D\u80FD\u901A\u8FC7 install-app \u5B89\u88C5\uFF1B\u7EAF\u540E\u53F0\u8BF7\u4F7F\u7528 --background");
|
|
19224
|
-
const manifest = validateManifest(JSON.parse('{\n "schema": 2,\n "source": "bundled",\n "mode": "experimental",\n "combinationId": "0.0.1-beta.
|
|
19275
|
+
const manifest = validateManifest(JSON.parse('{\n "schema": 2,\n "source": "bundled",\n "mode": "experimental",\n "combinationId": "0.0.1-beta.25",\n "cliVersion": "0.0.1-beta.25",\n "daemonVersion": "0.0.1-beta.25",\n "nodeRange": ">=18.20.5",\n "artifacts": {\n "darwin-arm64": {\n "app": {\n "path": "resources/niuma-lite-arm64.dmg",\n "size": 8125920,\n "sha256": "251727b68ae3f5bdc66ae7ec6e710c25c266cf2e17d940a56ef4adde840b7f4b"\n },\n "runtime": {\n "path": "resources/niuma-daemon-arm64.tgz",\n "size": 18282550,\n "sha256": "47c5651be977d16ee95be1689caa8bd72923710c134f732eb220c7aa8dc42cd1"\n }\n }\n }\n}\n'), version2, process.arch);
|
|
19225
19276
|
if (manifest.schema === 2) await confirmExperimental(manifest.mode, !!process.stdin.isTTY && !!process.stdout.isTTY, async () => {
|
|
19226
19277
|
const prompt = createInterface3({ input: process.stdin, output: process.stdout });
|
|
19227
19278
|
try {
|
|
@@ -19231,26 +19282,26 @@ async function runLiteInstall() {
|
|
|
19231
19282
|
}
|
|
19232
19283
|
});
|
|
19233
19284
|
const local = manifest.schema === 2 ? await resolveBundledResources(fileURLToPath(new URL("../", import.meta.url)), manifest, process.arch) : null;
|
|
19234
|
-
const runtimeRoot =
|
|
19285
|
+
const runtimeRoot = path37.join(os7.homedir(), "Library/Application Support/Niuma/lite-runtime");
|
|
19235
19286
|
try {
|
|
19236
|
-
await
|
|
19287
|
+
await fs29.lstat(path37.join(runtimeRoot, "uninstall.json"));
|
|
19237
19288
|
throw Error("\u5378\u8F7D\u5C1A\u672A\u5B8C\u6210\uFF0C\u8BF7\u5148\u91CD\u65B0\u8FD0\u884C uninstall-app");
|
|
19238
19289
|
} catch (e) {
|
|
19239
19290
|
if (e.code !== "ENOENT") throw e;
|
|
19240
19291
|
}
|
|
19241
19292
|
const assertOwnedApp = async (app) => {
|
|
19242
19293
|
try {
|
|
19243
|
-
const id5 = await runProcess("/usr/libexec/PlistBuddy", ["-c", "Print :CFBundleIdentifier",
|
|
19294
|
+
const id5 = await runProcess("/usr/libexec/PlistBuddy", ["-c", "Print :CFBundleIdentifier", path37.join(app, "Contents/Info.plist")]);
|
|
19244
19295
|
if (id5.trim() !== "com.niuma.macos.lite") throw Error("different identity");
|
|
19245
19296
|
} catch {
|
|
19246
19297
|
throw Error("\u540C\u540D\u5E94\u7528\u5F52\u5C5E\u65E0\u6CD5\u786E\u8BA4\uFF0C\u62D2\u7EDD\u8986\u76D6\uFF1B\u8BF7\u5148\u79FB\u8D70\u8BE5\u5E94\u7528\u540E\u91CD\u8BD5");
|
|
19247
19298
|
}
|
|
19248
19299
|
};
|
|
19249
19300
|
const verifyApp = async (app) => {
|
|
19250
|
-
const id5 = await runProcess("/usr/libexec/PlistBuddy", ["-c", "Print :CFBundleIdentifier",
|
|
19301
|
+
const id5 = await runProcess("/usr/libexec/PlistBuddy", ["-c", "Print :CFBundleIdentifier", path37.join(app, "Contents/Info.plist")]);
|
|
19251
19302
|
if (id5.trim() !== "com.niuma.macos.lite") throw Error("\u5E94\u7528\u6807\u8BC6\u4E0D\u5339\u914D");
|
|
19252
|
-
if (JSON.parse(await
|
|
19253
|
-
const binary =
|
|
19303
|
+
if (JSON.parse(await fs29.readFile(path37.join(app, "Contents/Resources/niuma-release.json"), "utf8")).combinationId !== version2) throw Error("\u5E94\u7528\u53D1\u884C\u7EC4\u5408\u4E0D\u5339\u914D");
|
|
19304
|
+
const binary = path37.join(app, "Contents/MacOS/niuma-lite");
|
|
19254
19305
|
if ((await runProcess(binary, ["--runtime-version"])).trim() !== version2) throw Error("\u5E94\u7528\u4E8C\u8FDB\u5236\u7248\u672C\u4E0D\u5339\u914D");
|
|
19255
19306
|
const arch = (await runProcess("/usr/bin/lipo", ["-archs", binary])).trim().split(/\s+/);
|
|
19256
19307
|
if (!arch.includes(process.arch === "x64" ? "x86_64" : process.arch)) throw Error("\u5E94\u7528\u67B6\u6784\u4E0D\u5339\u914D");
|
|
@@ -19258,10 +19309,10 @@ async function runLiteInstall() {
|
|
|
19258
19309
|
};
|
|
19259
19310
|
const verify = async (app, runtime) => {
|
|
19260
19311
|
await verifyApp(app);
|
|
19261
|
-
const pkg = JSON.parse(await
|
|
19312
|
+
const pkg = JSON.parse(await fs29.readFile(path37.join(runtime, "package.json"), "utf8"));
|
|
19262
19313
|
if (pkg.name !== "niuma-codex" || pkg.version !== version2) throw Error("daemon \u7248\u672C\u4E0D\u5339\u914D");
|
|
19263
|
-
if (!(await
|
|
19264
|
-
await runProcess(process.execPath, ["--input-type=module", "-e", `await import(${JSON.stringify(pathToFileURL(
|
|
19314
|
+
if (!(await fs29.stat(path37.join(runtime, "dist/managed-tauri.js"))).isFile()) throw Error("daemon \u5165\u53E3\u7F3A\u5931");
|
|
19315
|
+
await runProcess(process.execPath, ["--input-type=module", "-e", `await import(${JSON.stringify(pathToFileURL(path37.join(runtime, "node_modules/sharp/lib/index.js")).href)})`]);
|
|
19265
19316
|
};
|
|
19266
19317
|
let confirmed = false;
|
|
19267
19318
|
const confirm = async () => {
|
|
@@ -19276,34 +19327,8 @@ async function runLiteInstall() {
|
|
|
19276
19327
|
}
|
|
19277
19328
|
};
|
|
19278
19329
|
await withInstallCoordination(runtimeRoot, async () => {
|
|
19279
|
-
const
|
|
19280
|
-
|
|
19281
|
-
const intentFile = path36.join(runtimeRoot, "install-intent.json");
|
|
19282
|
-
let intent;
|
|
19283
|
-
try {
|
|
19284
|
-
const stat4 = await fs28.lstat(intentFile);
|
|
19285
|
-
if (!stat4.isFile() || stat4.uid !== process.getuid?.() || stat4.mode & 63) throw Error("\u5B89\u88C5\u610F\u56FE\u6587\u4EF6\u4E0D\u53EF\u4FE1");
|
|
19286
|
-
intent = JSON.parse(await fs28.readFile(intentFile, "utf8"));
|
|
19287
|
-
if (typeof intent.firstInstall !== "boolean" || intent.version !== version2) throw Error("\u8BF7\u5148\u4F7F\u7528\u539F\u7248\u672C\u5B8C\u6210\u5B89\u88C5");
|
|
19288
|
-
} catch (e) {
|
|
19289
|
-
if (e.code !== "ENOENT") throw e;
|
|
19290
|
-
let firstInstall = false;
|
|
19291
|
-
try {
|
|
19292
|
-
await fs28.lstat(path36.join(runtimeRoot, "current.json"));
|
|
19293
|
-
} catch (e2) {
|
|
19294
|
-
if (e2.code !== "ENOENT") throw e2;
|
|
19295
|
-
firstInstall = true;
|
|
19296
|
-
}
|
|
19297
|
-
intent = { version: version2, firstInstall, selection: await createInstallSelection(os7.homedir(), true) };
|
|
19298
|
-
await fs28.writeFile(intentFile, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
19299
|
-
}
|
|
19300
|
-
if (!intent.selection) {
|
|
19301
|
-
intent.selection = await createInstallSelection(os7.homedir(), false);
|
|
19302
|
-
const temp = intentFile + "." + randomUUID16();
|
|
19303
|
-
await fs28.writeFile(temp, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
19304
|
-
await fs28.rename(temp, intentFile);
|
|
19305
|
-
}
|
|
19306
|
-
if (typeof intent.selection.revision !== "string" || !intent.selection.revision || !Number.isSafeInteger(intent.selection.requestedAt) || intent.selection.requestedAt < 0 || !(intent.selection.previousRevision === null || typeof intent.selection.previousRevision === "string")) throw Error("\u5B89\u88C5\u9009\u62E9\u8BB0\u5F55\u65E0\u6548");
|
|
19330
|
+
const intentFile = path37.join(runtimeRoot, "install-intent.json");
|
|
19331
|
+
const { intent, pending } = await prepareInstallIntent(runtimeRoot, os7.homedir(), version2);
|
|
19307
19332
|
const manager = createAutostartManager({ command: null, positionals: [], flags: {} });
|
|
19308
19333
|
const needsSource = intent.firstInstall || !!(pending && !["completed", "skipped"].includes(pending.phase));
|
|
19309
19334
|
const withSource = needsSource ? manager.withMigrationSource.bind(manager) : async (work) => work({ snapshot: async () => ({ fingerprint: "not-migrating", enabled: false }), remove: async () => {
|
|
@@ -19336,27 +19361,27 @@ async function runLiteInstall() {
|
|
|
19336
19361
|
} });
|
|
19337
19362
|
const result = await installLite({
|
|
19338
19363
|
runtimeRoot,
|
|
19339
|
-
installRoot:
|
|
19364
|
+
installRoot: path37.join(os7.homedir(), "Applications"),
|
|
19340
19365
|
version: version2,
|
|
19341
|
-
nodePath: await
|
|
19366
|
+
nodePath: await fs29.realpath(process.execPath),
|
|
19342
19367
|
verify,
|
|
19343
19368
|
assertOwnedApp,
|
|
19344
19369
|
prepare: async (stage) => {
|
|
19345
19370
|
if (manifest.schema === 2 && local) {
|
|
19346
19371
|
const artifacts = manifest.artifacts[`darwin-${process.arch}`];
|
|
19347
19372
|
for (const kind of ["app", "runtime"]) {
|
|
19348
|
-
const file =
|
|
19349
|
-
await
|
|
19373
|
+
const file = path37.join(stage, kind === "app" ? "app.dmg" : "runtime.tgz");
|
|
19374
|
+
await fs29.copyFile(local[kind], file);
|
|
19350
19375
|
await verifyLocalArtifact(file, artifacts[kind]);
|
|
19351
19376
|
}
|
|
19352
|
-
await prepareDmgApp({ dmg:
|
|
19353
|
-
await extract(
|
|
19377
|
+
await prepareDmgApp({ dmg: path37.join(stage, "app.dmg"), stage, verify: verifyApp });
|
|
19378
|
+
await extract(path37.join(stage, "runtime.tgz"), path37.join(stage, "runtime"));
|
|
19354
19379
|
} else if (manifest.schema === 1) {
|
|
19355
19380
|
const artifacts = manifest.artifacts[`darwin-${process.arch}`];
|
|
19356
19381
|
for (const kind of ["app", "runtime"]) {
|
|
19357
|
-
const file =
|
|
19382
|
+
const file = path37.join(stage, kind + ".tgz");
|
|
19358
19383
|
await download(artifacts[kind], file);
|
|
19359
|
-
await extract(file,
|
|
19384
|
+
await extract(file, path37.join(stage, kind));
|
|
19360
19385
|
}
|
|
19361
19386
|
}
|
|
19362
19387
|
},
|
|
@@ -19423,7 +19448,7 @@ async function runLiteInstall() {
|
|
|
19423
19448
|
});
|
|
19424
19449
|
}, "login-settings.lock");
|
|
19425
19450
|
if (migration === "failed") throw Error("\u4E0A\u6B21\u81EA\u542F\u52A8\u8FC1\u79FB\u5931\u8D25\uFF0C\u539F npm \u914D\u7F6E\u4FDD\u7559\uFF1B\u8BF7\u5728 Lite \u8BBE\u7F6E\u4E2D\u660E\u786E\u91CD\u65B0\u5F00\u542F\u540E\u91CD\u8BD5\u5B89\u88C5");
|
|
19426
|
-
if (migration !== "pending" || !historical && sourceBefore.enabled === true) await
|
|
19451
|
+
if (migration !== "pending" || !historical && sourceBefore.enabled === true) await fs29.rm(intentFile, { force: true });
|
|
19427
19452
|
const waiting = historical || sourceBefore.enabled === null ? "\u72B6\u6001\u5F85\u786E\u8BA4\uFF0C\u4FDD\u7559\u539F npm \u914D\u7F6E\uFF1B\u8BF7\u68C0\u67E5\u7CFB\u7EDF\u767B\u5F55\u9879\u540E\u91CD\u8BD5 install-app" : "\u63A5\u7BA1\u5F85\u786E\u8BA4\uFF0C\u4FDD\u7559\u539F npm \u914D\u7F6E\uFF1B\u7CFB\u7EDF\u6279\u51C6\u540E\u7531\u8FD0\u884C\u4E2D\u7684\u5E94\u7528\u6216\u670D\u52A1\u5B8C\u6210\u63A5\u7BA1";
|
|
19428
19453
|
process.stdout.write(`daemon \u5DF2\u5C31\u7EEA\uFF1B\u81EA\u542F\u52A8${migration === "completed" ? "\u5DF2\u8FC1\u79FB" : migration === "skipped" || migration === "superseded" || migration === "cancelled" ? "\u4FDD\u6301\u6700\u65B0\u8BBE\u7F6E" : waiting}\u3002
|
|
19429
19454
|
`);
|
|
@@ -19437,6 +19462,7 @@ var init_production2 = __esm({
|
|
|
19437
19462
|
init_host_control();
|
|
19438
19463
|
init_lock();
|
|
19439
19464
|
init_migration();
|
|
19465
|
+
init_intent();
|
|
19440
19466
|
init_lifecycle();
|
|
19441
19467
|
init_production();
|
|
19442
19468
|
init_client();
|
|
@@ -19849,15 +19875,15 @@ var init_client_turn_query_context = __esm({
|
|
|
19849
19875
|
});
|
|
19850
19876
|
|
|
19851
19877
|
// apps/desktop/src/niuma/session-history-file.ts
|
|
19852
|
-
import
|
|
19853
|
-
import
|
|
19878
|
+
import fs30 from "node:fs/promises";
|
|
19879
|
+
import path38 from "node:path";
|
|
19854
19880
|
import { createHash as createHash7 } from "node:crypto";
|
|
19855
19881
|
function matchesSessionFileIdentity(file, stat4) {
|
|
19856
19882
|
const exact = (value) => typeof value === "number" ? Number.isSafeInteger(value) && value >= 0 ? String(value) : null : /^(0|[1-9]\d{0,39})$/.test(value) ? value : null;
|
|
19857
19883
|
return exact(file.dev) === String(stat4.dev) && exact(file.ino) === String(stat4.ino);
|
|
19858
19884
|
}
|
|
19859
19885
|
async function preciseStat(file) {
|
|
19860
|
-
const stat4 = await
|
|
19886
|
+
const stat4 = await fs30.stat(file, { bigint: true });
|
|
19861
19887
|
const size2 = Number(stat4.size);
|
|
19862
19888
|
if (!Number.isSafeInteger(size2)) throw new SessionHistoryError("RESOURCE_LIMIT", "\u4F1A\u8BDD\u6587\u4EF6\u8D85\u51FA\u8BFB\u53D6\u8303\u56F4");
|
|
19863
19889
|
return { dev: stat4.dev, ino: stat4.ino, size: size2, mtimeMs: Number(stat4.mtimeNs) / 1e6, isFile: () => stat4.isFile() };
|
|
@@ -19873,12 +19899,12 @@ function rethrowUnreadableHistoryPath(error2) {
|
|
|
19873
19899
|
}
|
|
19874
19900
|
function fileIdentity(file) {
|
|
19875
19901
|
const uuid8 = "[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}";
|
|
19876
|
-
const match =
|
|
19902
|
+
const match = path38.basename(file).match(new RegExp(`(${uuid8})(?:_(${uuid8}))?\\.jsonl$`, "i"));
|
|
19877
19903
|
return match ? { owner: match[1], segment: match[2] ?? match[1] } : null;
|
|
19878
19904
|
}
|
|
19879
19905
|
async function readBytes(file, start, length, onRead, signal) {
|
|
19880
19906
|
abortIfRequested(signal);
|
|
19881
|
-
const handle = await
|
|
19907
|
+
const handle = await fs30.open(file, "r").catch(rethrowUnreadableHistoryPath);
|
|
19882
19908
|
try {
|
|
19883
19909
|
const buffer = Buffer.allocUnsafe(length);
|
|
19884
19910
|
let filled = 0;
|
|
@@ -19936,7 +19962,7 @@ async function header(file, size2, onRead, signal) {
|
|
|
19936
19962
|
}
|
|
19937
19963
|
async function openSessionFile(file, threadId2, chunkBytes, end, onRead, signal, onCutoffCaptured) {
|
|
19938
19964
|
abortIfRequested(signal);
|
|
19939
|
-
const resolved3 = await
|
|
19965
|
+
const resolved3 = await fs30.realpath(file).catch(rethrowUnreadableHistoryPath);
|
|
19940
19966
|
const stat4 = await preciseStat(resolved3).catch(rethrowUnreadableHistoryPath);
|
|
19941
19967
|
abortIfRequested(signal);
|
|
19942
19968
|
if (!stat4.isFile()) throw new SessionHistoryError("INVALID_METADATA", "\u4F1A\u8BDD\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
|
|
@@ -22913,10 +22939,10 @@ var init_status = __esm({
|
|
|
22913
22939
|
});
|
|
22914
22940
|
|
|
22915
22941
|
// apps/desktop/src/niuma/thread-summary.ts
|
|
22916
|
-
import
|
|
22942
|
+
import path39 from "node:path";
|
|
22917
22943
|
function pathBelongsToProjectRoot(projectRoot, candidateRoot) {
|
|
22918
|
-
const relative =
|
|
22919
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
22944
|
+
const relative = path39.relative(path39.resolve(projectRoot), path39.resolve(candidateRoot));
|
|
22945
|
+
return relative === "" || !relative.startsWith("..") && !path39.isAbsolute(relative);
|
|
22920
22946
|
}
|
|
22921
22947
|
function toLatestTurn(turns) {
|
|
22922
22948
|
const latest = turns.at(-1);
|
|
@@ -22984,7 +23010,7 @@ function normalizeThreadSummary(thread4, pending = null, options = {}) {
|
|
|
22984
23010
|
id: thread4.id,
|
|
22985
23011
|
title: thread4.name ?? thread4.preview ?? "",
|
|
22986
23012
|
projectRoot: thread4.cwd,
|
|
22987
|
-
projectName:
|
|
23013
|
+
projectName: path39.basename(thread4.cwd) || thread4.cwd,
|
|
22988
23014
|
status: status2,
|
|
22989
23015
|
pending: normalizedPending,
|
|
22990
23016
|
createdAt: thread4.createdAt,
|
|
@@ -26116,9 +26142,9 @@ function resourcePaths(platform2 = process.platform) {
|
|
|
26116
26142
|
toLink(value) {
|
|
26117
26143
|
const parsed = parseLocal(value);
|
|
26118
26144
|
if (parsed === null) return null;
|
|
26119
|
-
const
|
|
26145
|
+
const path71 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
|
|
26120
26146
|
try {
|
|
26121
|
-
return encodeURIComponent(
|
|
26147
|
+
return encodeURIComponent(path71).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
|
|
26122
26148
|
} catch {
|
|
26123
26149
|
return null;
|
|
26124
26150
|
}
|
|
@@ -26262,8 +26288,8 @@ var init_response_annotations = __esm({
|
|
|
26262
26288
|
|
|
26263
26289
|
// apps/desktop/src/attachments/image-identity.ts
|
|
26264
26290
|
import { createHash as createHash12 } from "node:crypto";
|
|
26265
|
-
function unavailableImageId(
|
|
26266
|
-
const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null,
|
|
26291
|
+
function unavailableImageId(path71, itemId, partIndex) {
|
|
26292
|
+
const identity6 = itemId ? JSON.stringify([itemId, partIndex ?? null, path71]) : path71;
|
|
26267
26293
|
return `unavailable:${createHash12("sha256").update(identity6).digest("hex")}`;
|
|
26268
26294
|
}
|
|
26269
26295
|
var init_image_identity = __esm({
|
|
@@ -26357,15 +26383,15 @@ function normalizeMessageContent(value, resolveKnownLocalImage, itemId, original
|
|
|
26357
26383
|
}
|
|
26358
26384
|
return content2;
|
|
26359
26385
|
}
|
|
26360
|
-
function userFile(name2,
|
|
26386
|
+
function userFile(name2, path71) {
|
|
26361
26387
|
const part = { type: "file", name: name2 };
|
|
26362
|
-
userFileSource.set(part,
|
|
26388
|
+
userFileSource.set(part, path71);
|
|
26363
26389
|
return part;
|
|
26364
26390
|
}
|
|
26365
26391
|
function userFileSources(content2 = []) {
|
|
26366
26392
|
return content2.flatMap((part, index) => {
|
|
26367
|
-
const
|
|
26368
|
-
return part.type === "file" && typeof
|
|
26393
|
+
const path71 = userFileSource.get(part);
|
|
26394
|
+
return part.type === "file" && typeof path71 === "string" ? [{ index, path: path71 }] : [];
|
|
26369
26395
|
});
|
|
26370
26396
|
}
|
|
26371
26397
|
function codexImageWrapperFileList(text11) {
|
|
@@ -26402,11 +26428,11 @@ function standardCodexImageFileListEntries(fileList) {
|
|
|
26402
26428
|
break;
|
|
26403
26429
|
}
|
|
26404
26430
|
const name2 = safeCodexFileName(match[1] ?? match[3] ?? "");
|
|
26405
|
-
const
|
|
26406
|
-
if (!name2 || !isRecordedResourcePath(
|
|
26431
|
+
const path71 = match[2] ?? match[4] ?? "";
|
|
26432
|
+
if (!name2 || !isRecordedResourcePath(path71)) {
|
|
26407
26433
|
return null;
|
|
26408
26434
|
}
|
|
26409
|
-
entries.push({ name: name2, path:
|
|
26435
|
+
entries.push({ name: name2, path: path71 });
|
|
26410
26436
|
remaining = remaining.slice(match[0].length);
|
|
26411
26437
|
remaining = remaining.replace(/^Image attachment: true\r?\n/u, "");
|
|
26412
26438
|
}
|
|
@@ -26422,10 +26448,10 @@ function redactCodexImageWrapperPaths(text11) {
|
|
|
26422
26448
|
}
|
|
26423
26449
|
const fileList = wrapper.fileList.replace(
|
|
26424
26450
|
/(^## [^\r\n]+:[ \t]*\r?\n)[ \t]*([^\r\n]+)/gmu,
|
|
26425
|
-
(all, prefix,
|
|
26451
|
+
(all, prefix, path71) => isRecordedResourcePath(path71) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
|
|
26426
26452
|
).replace(
|
|
26427
26453
|
/^(## [^\r\n]+:)[ \t]+([^\r\n]+)$/gmu,
|
|
26428
|
-
(all, prefix,
|
|
26454
|
+
(all, prefix, path71) => isRecordedResourcePath(path71) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
|
|
26429
26455
|
);
|
|
26430
26456
|
const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
|
|
26431
26457
|
return `${wrapper.prefix}${fileList}${text11.slice(fileListEnd)}`;
|
|
@@ -26436,7 +26462,7 @@ function redactKnownCodexWrapperPaths(text11, paths) {
|
|
|
26436
26462
|
return text11;
|
|
26437
26463
|
}
|
|
26438
26464
|
const fileList = paths.reduce(
|
|
26439
|
-
(result,
|
|
26465
|
+
(result, path71) => result.replaceAll(path71, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
|
|
26440
26466
|
wrapper.fileList
|
|
26441
26467
|
);
|
|
26442
26468
|
const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
|
|
@@ -26453,8 +26479,8 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
|
|
|
26453
26479
|
}
|
|
26454
26480
|
const localImagePaths = value.flatMap((part) => {
|
|
26455
26481
|
const record26 = asRecord11(part);
|
|
26456
|
-
const
|
|
26457
|
-
return
|
|
26482
|
+
const path71 = localImagePath(record26);
|
|
26483
|
+
return path71 === null ? [] : [path71];
|
|
26458
26484
|
});
|
|
26459
26485
|
const text11 = redactKnownCodexWrapperPaths(
|
|
26460
26486
|
redactCodexImageWrapperPaths(firstPart2.text),
|
|
@@ -26488,9 +26514,9 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
|
|
|
26488
26514
|
const localImages = value.flatMap((part, index) => {
|
|
26489
26515
|
const partIndex = originalPartIndices?.[index] ?? index;
|
|
26490
26516
|
const record26 = asRecord11(part);
|
|
26491
|
-
const
|
|
26492
|
-
return
|
|
26493
|
-
path:
|
|
26517
|
+
const path71 = localImagePath(record26);
|
|
26518
|
+
return path71 === null ? [] : [{
|
|
26519
|
+
path: path71,
|
|
26494
26520
|
partIndex,
|
|
26495
26521
|
image: record26.type === "historyImage" ? historyImageContent(record26, itemId, partIndex) : null
|
|
26496
26522
|
}];
|
|
@@ -26619,8 +26645,8 @@ function redactRawLocalImagePaths(rawItem) {
|
|
|
26619
26645
|
let containsLocalImage = false;
|
|
26620
26646
|
let containsRedactedWrapperPath = false;
|
|
26621
26647
|
const localImagePaths = item.content.map((part) => asRecord11(part)).flatMap((part) => {
|
|
26622
|
-
const
|
|
26623
|
-
return
|
|
26648
|
+
const path71 = localImagePath(part);
|
|
26649
|
+
return path71 === null ? [] : [path71];
|
|
26624
26650
|
});
|
|
26625
26651
|
const content2 = item.content.map((part) => {
|
|
26626
26652
|
const record26 = asRecord11(part);
|
|
@@ -27588,8 +27614,8 @@ var init_events = __esm({
|
|
|
27588
27614
|
const patches = Array.isArray(change.patches) ? change.patches : [];
|
|
27589
27615
|
for (const patch of patches) {
|
|
27590
27616
|
const candidate = objectRecord6(patch);
|
|
27591
|
-
const
|
|
27592
|
-
if ((candidate.op === "add" || candidate.op === "replace") &&
|
|
27617
|
+
const path71 = Array.isArray(candidate.path) ? candidate.path : [];
|
|
27618
|
+
if ((candidate.op === "add" || candidate.op === "replace") && path71.length === 1 && path71[0] === "threadRuntimeStatus") {
|
|
27593
27619
|
runtimeStatusValue = candidate.value;
|
|
27594
27620
|
}
|
|
27595
27621
|
}
|
|
@@ -29592,13 +29618,13 @@ var init_upload_task_store = __esm({
|
|
|
29592
29618
|
import { execFile as execFile9 } from "node:child_process";
|
|
29593
29619
|
import { constants as constants2 } from "node:fs";
|
|
29594
29620
|
import { lstat, open } from "node:fs/promises";
|
|
29595
|
-
import
|
|
29621
|
+
import path40 from "node:path";
|
|
29596
29622
|
function limit(max) {
|
|
29597
29623
|
if (!Number.isSafeInteger(max) || max < 1 || max > 50 * 1024 * 1024) throw new PrivateBinaryFileError("capacity");
|
|
29598
29624
|
}
|
|
29599
29625
|
function resolved2(file) {
|
|
29600
29626
|
try {
|
|
29601
|
-
return windows() ? localWindowsPath(file) :
|
|
29627
|
+
return windows() ? localWindowsPath(file) : path40.resolve(file);
|
|
29602
29628
|
} catch {
|
|
29603
29629
|
throw unavailable2();
|
|
29604
29630
|
}
|
|
@@ -29641,7 +29667,7 @@ async function windowsMode(file, seal = false) {
|
|
|
29641
29667
|
return output;
|
|
29642
29668
|
}
|
|
29643
29669
|
async function parentIdentity(file) {
|
|
29644
|
-
const directory3 =
|
|
29670
|
+
const directory3 = path40.dirname(file), initial = await lstat(directory3, { bigint: true });
|
|
29645
29671
|
if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable2();
|
|
29646
29672
|
if (windows()) {
|
|
29647
29673
|
try {
|
|
@@ -29708,10 +29734,10 @@ async function openFile(file, options) {
|
|
|
29708
29734
|
let tail = Promise.resolve();
|
|
29709
29735
|
async function guard() {
|
|
29710
29736
|
if (closed || poisoned) throw unavailable2();
|
|
29711
|
-
const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory3 = await lstat(
|
|
29737
|
+
const held = await h.stat({ bigint: true }), current2 = await lstat(file, { bigint: true }), directory3 = await lstat(path40.dirname(file), { bigint: true });
|
|
29712
29738
|
if (!trusted2(held) || !trusted2(current2) || !same3(held, baseline) || !sameSnapshot(held, current2) || !same3(parent, directory3) || !directory3.isDirectory() || directory3.isSymbolicLink() || held.size > BigInt(options.maxBytes) || (!options.writable || mode === "immutable") && !sameSnapshot(baseline, held)) throw unavailable2();
|
|
29713
29739
|
if (!windows() && posixMode(held) !== mode) throw unavailable2();
|
|
29714
|
-
if (!windows()) privateLogFiles.checkDirectory(
|
|
29740
|
+
if (!windows()) privateLogFiles.checkDirectory(path40.dirname(file));
|
|
29715
29741
|
}
|
|
29716
29742
|
await guard();
|
|
29717
29743
|
checkExpected(await status(h), options);
|
|
@@ -29848,11 +29874,11 @@ if($env:NIUMA_BINARY_SEAL -eq '1' -and $mode -ne 'immutable') {
|
|
|
29848
29874
|
handle = await open(file, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (windows() ? 0 : constants2.O_NOFOLLOW), 384);
|
|
29849
29875
|
if (!windows()) await handle.chmod(384);
|
|
29850
29876
|
const held = await handle.stat({ bigint: true }), current2 = await lstat(file, { bigint: true });
|
|
29851
|
-
if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(
|
|
29877
|
+
if (!trusted2(held) || !sameSnapshot(held, current2) || !same3(parent, await lstat(path40.dirname(file), { bigint: true }))) throw unavailable2();
|
|
29852
29878
|
if (windows() && await windowsMode(file) !== "mutable") throw unavailable2();
|
|
29853
29879
|
await handle.sync();
|
|
29854
29880
|
const result = await status(handle);
|
|
29855
|
-
if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(
|
|
29881
|
+
if (!sameSnapshot(await handle.stat({ bigint: true }), await lstat(file, { bigint: true })) || !same3(parent, await lstat(path40.dirname(file), { bigint: true }))) throw unavailable2();
|
|
29856
29882
|
await handle.close();
|
|
29857
29883
|
handle = void 0;
|
|
29858
29884
|
return result;
|
|
@@ -29952,7 +29978,7 @@ import { randomUUID as randomUUID23 } from "node:crypto";
|
|
|
29952
29978
|
import { execFile as execFile11 } from "node:child_process";
|
|
29953
29979
|
import { constants as constants3 } from "node:fs";
|
|
29954
29980
|
import { chmod, lstat as lstat3, mkdir, open as open2, readdir, rename, rm } from "node:fs/promises";
|
|
29955
|
-
import
|
|
29981
|
+
import path41 from "node:path";
|
|
29956
29982
|
function nameOnly(name2) {
|
|
29957
29983
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/u.test(name2)) throw unavailable3();
|
|
29958
29984
|
}
|
|
@@ -29961,7 +29987,7 @@ function budget(maxBytes) {
|
|
|
29961
29987
|
}
|
|
29962
29988
|
async function openDirectories(requested, windowsCandidate) {
|
|
29963
29989
|
const windows2 = process.platform === "win32";
|
|
29964
|
-
const root = windows2 ? localWindowsPath(requested) :
|
|
29990
|
+
const root = windows2 ? localWindowsPath(requested) : path41.resolve(requested);
|
|
29965
29991
|
let rootIdentity;
|
|
29966
29992
|
try {
|
|
29967
29993
|
if (windows2) await ensureWindowsPrivateDirectoryAsync(root);
|
|
@@ -30006,7 +30032,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
30006
30032
|
}
|
|
30007
30033
|
function token3(value) {
|
|
30008
30034
|
const directory3 = Object.freeze({ get sourcePath() {
|
|
30009
|
-
return
|
|
30035
|
+
return path41.join(value.path, "source");
|
|
30010
30036
|
} });
|
|
30011
30037
|
records2.set(directory3, value);
|
|
30012
30038
|
return directory3;
|
|
@@ -30062,7 +30088,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
30062
30088
|
return serial(async () => {
|
|
30063
30089
|
nameOnly(name2);
|
|
30064
30090
|
await guard();
|
|
30065
|
-
const directory3 =
|
|
30091
|
+
const directory3 = path41.join(root, name2);
|
|
30066
30092
|
if (!windows2) privateLogFiles.checkDirectory(directory3);
|
|
30067
30093
|
const identity6 = await lstat3(directory3, { bigint: true });
|
|
30068
30094
|
const result = token3({ name: name2, path: directory3, identity: identity6, staged: false, pending: true, ready: true });
|
|
@@ -30075,7 +30101,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
30075
30101
|
mutable();
|
|
30076
30102
|
nameOnly(name2);
|
|
30077
30103
|
await guard();
|
|
30078
|
-
const directory3 =
|
|
30104
|
+
const directory3 = path41.join(root, ".pending-" + name2);
|
|
30079
30105
|
await mkdir(directory3, { mode: 448 });
|
|
30080
30106
|
const identity6 = await lstat3(directory3, { bigint: true });
|
|
30081
30107
|
if (windows2) {
|
|
@@ -30105,7 +30131,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30105
30131
|
return serial(async () => {
|
|
30106
30132
|
budget(maxBytes);
|
|
30107
30133
|
await guard(directory3);
|
|
30108
|
-
const handle = await privateBinaryFiles.open(
|
|
30134
|
+
const handle = await privateBinaryFiles.open(path41.join(record26(directory3).path, "manifest.json"), { maxBytes, mode: "mutable" });
|
|
30109
30135
|
let failed = false;
|
|
30110
30136
|
const bytes3 = Buffer.alloc(maxBytes);
|
|
30111
30137
|
try {
|
|
@@ -30154,7 +30180,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30154
30180
|
async function currentManifest() {
|
|
30155
30181
|
let stats;
|
|
30156
30182
|
try {
|
|
30157
|
-
stats = await lstat3(
|
|
30183
|
+
stats = await lstat3(path41.join(value.path, "manifest.json"), { bigint: true });
|
|
30158
30184
|
} catch (error2) {
|
|
30159
30185
|
if (error2.code === "ENOENT") return null;
|
|
30160
30186
|
throw error2;
|
|
@@ -30162,7 +30188,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30162
30188
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n || !windows2 && (stats.uid !== BigInt(process.getuid()) || (stats.mode & 0o777n) !== 0o600n)) throw unavailable3();
|
|
30163
30189
|
if (stats.size > BigInt(maxBytes)) throw new PrivateUploadDirectoryError("capacity");
|
|
30164
30190
|
if (windows2) {
|
|
30165
|
-
const handle = await privateBinaryFiles.open(
|
|
30191
|
+
const handle = await privateBinaryFiles.open(path41.join(value.path, "manifest.json"), {
|
|
30166
30192
|
maxBytes,
|
|
30167
30193
|
mode: "mutable",
|
|
30168
30194
|
match: "object",
|
|
@@ -30179,13 +30205,13 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30179
30205
|
} finally {
|
|
30180
30206
|
await handle.close();
|
|
30181
30207
|
}
|
|
30182
|
-
const after = await lstat3(
|
|
30208
|
+
const after = await lstat3(path41.join(value.path, "manifest.json"), { bigint: true });
|
|
30183
30209
|
if (!same4(stats, after) || stats.size !== after.size || stats.mtimeNs !== after.mtimeNs || stats.ctimeNs !== after.ctimeNs) throw unavailable3();
|
|
30184
30210
|
}
|
|
30185
30211
|
return stats;
|
|
30186
30212
|
}
|
|
30187
30213
|
const original = await currentManifest();
|
|
30188
|
-
const temporary =
|
|
30214
|
+
const temporary = path41.join(value.path, ".manifest-" + randomUUID23());
|
|
30189
30215
|
let created = false, published = false, identity6;
|
|
30190
30216
|
try {
|
|
30191
30217
|
if (windows2) {
|
|
@@ -30240,7 +30266,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30240
30266
|
if (!identity6 || !same4(identity6, current2) || !current2.isFile() || current2.isSymbolicLink() || current2.nlink !== 1n || !windows2 && (current2.uid !== BigInt(process.getuid()) || (current2.mode & 0o777n) !== 0o600n)) throw unavailable3();
|
|
30241
30267
|
const previous = await currentManifest();
|
|
30242
30268
|
if (original === null ? previous !== null : previous === null || !same4(original, previous) || original.size !== previous.size || original.mtimeNs !== previous.mtimeNs || original.ctimeNs !== previous.ctimeNs) throw unavailable3();
|
|
30243
|
-
await rename(temporary,
|
|
30269
|
+
await rename(temporary, path41.join(value.path, "manifest.json"));
|
|
30244
30270
|
published = true;
|
|
30245
30271
|
created = false;
|
|
30246
30272
|
value.pending = true;
|
|
@@ -30277,7 +30303,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30277
30303
|
const value = record26(directory3);
|
|
30278
30304
|
if (!value.staged || !value.ready) throw unavailable3();
|
|
30279
30305
|
await finish(directory3);
|
|
30280
|
-
const target =
|
|
30306
|
+
const target = path41.join(root, value.name);
|
|
30281
30307
|
try {
|
|
30282
30308
|
await lstat3(target);
|
|
30283
30309
|
throw unavailable3();
|
|
@@ -30662,7 +30688,7 @@ var init_legacy_upload_contents = __esm({
|
|
|
30662
30688
|
|
|
30663
30689
|
// apps/desktop/src/daemon/runtime/attachment-access.ts
|
|
30664
30690
|
import { createHash as createHash16 } from "node:crypto";
|
|
30665
|
-
import
|
|
30691
|
+
import path42 from "node:path";
|
|
30666
30692
|
import process2 from "node:process";
|
|
30667
30693
|
var RuntimeAttachmentAccess;
|
|
30668
30694
|
var init_attachment_access = __esm({
|
|
@@ -30700,7 +30726,7 @@ var init_attachment_access = __esm({
|
|
|
30700
30726
|
const cached = createCachedUploadTaskStore({
|
|
30701
30727
|
base,
|
|
30702
30728
|
cache: () => cache2 ??= (async () => {
|
|
30703
|
-
const root =
|
|
30729
|
+
const root = path42.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
|
|
30704
30730
|
return createDeviceUploadCache({
|
|
30705
30731
|
storage: composeLegacyUploadContents(await openPrivateUploadDirectories(root), privateBinaryFiles),
|
|
30706
30732
|
admit: (bytes3, operation) => this.ports.attachmentStorage().withAttachmentUploadAdmission(void 0, bytes3, operation)
|
|
@@ -30844,8 +30870,8 @@ var init_attachment_access = __esm({
|
|
|
30844
30870
|
});
|
|
30845
30871
|
|
|
30846
30872
|
// apps/desktop/src/niuma/project-state.ts
|
|
30847
|
-
import
|
|
30848
|
-
import
|
|
30873
|
+
import fs31 from "node:fs/promises";
|
|
30874
|
+
import path43 from "node:path";
|
|
30849
30875
|
import { z as z10 } from "zod";
|
|
30850
30876
|
function emptyProjectState() {
|
|
30851
30877
|
return {
|
|
@@ -30914,9 +30940,9 @@ function isMissingFileError(error2) {
|
|
|
30914
30940
|
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
30915
30941
|
}
|
|
30916
30942
|
async function readProjectState(codexHome) {
|
|
30917
|
-
const statePath =
|
|
30943
|
+
const statePath = path43.join(codexHome, ".codex-global-state.json");
|
|
30918
30944
|
try {
|
|
30919
|
-
const raw = await
|
|
30945
|
+
const raw = await fs31.readFile(statePath, "utf8");
|
|
30920
30946
|
const parsed = RawProjectStateSchema.parse(JSON.parse(raw));
|
|
30921
30947
|
const localProjects = readLocalProjects(parsed["local-projects"]);
|
|
30922
30948
|
const rootsByProjectId = new Map(localProjects.map((project3) => [project3.id, project3.root]));
|
|
@@ -31009,7 +31035,7 @@ var init_project_state = __esm({
|
|
|
31009
31035
|
});
|
|
31010
31036
|
|
|
31011
31037
|
// apps/desktop/src/niuma/session-originator.ts
|
|
31012
|
-
import
|
|
31038
|
+
import fs32 from "node:fs/promises";
|
|
31013
31039
|
function record9(value) {
|
|
31014
31040
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
31015
31041
|
}
|
|
@@ -31026,7 +31052,7 @@ async function readFirstLine(filePath) {
|
|
|
31026
31052
|
let byteCount = 0;
|
|
31027
31053
|
let position = 0;
|
|
31028
31054
|
try {
|
|
31029
|
-
handle = await
|
|
31055
|
+
handle = await fs32.open(filePath, "r");
|
|
31030
31056
|
while (true) {
|
|
31031
31057
|
const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
|
|
31032
31058
|
const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
|
|
@@ -31122,7 +31148,7 @@ var init_session_originator = __esm({
|
|
|
31122
31148
|
});
|
|
31123
31149
|
|
|
31124
31150
|
// apps/desktop/src/niuma/session-timestamps.ts
|
|
31125
|
-
import
|
|
31151
|
+
import fs33 from "node:fs/promises";
|
|
31126
31152
|
import { createInterface as createInterface4 } from "node:readline";
|
|
31127
31153
|
function record10(value) {
|
|
31128
31154
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -31408,7 +31434,7 @@ var init_session_timestamps = __esm({
|
|
|
31408
31434
|
try {
|
|
31409
31435
|
const sessionPath = explicitPath === void 0 ? await this.resolveSessionPath(threadId2) : explicitPath;
|
|
31410
31436
|
if (!sessionPath || this.closed) return "unavailable";
|
|
31411
|
-
const stat4 = await
|
|
31437
|
+
const stat4 = await fs33.stat(sessionPath);
|
|
31412
31438
|
if (this.closed) return "unavailable";
|
|
31413
31439
|
return JSON.stringify([stat4.dev, stat4.ino, stat4.size, stat4.mtimeMs, stat4.ctimeMs]);
|
|
31414
31440
|
} catch {
|
|
@@ -31581,7 +31607,7 @@ var init_session_timestamps = __esm({
|
|
|
31581
31607
|
}
|
|
31582
31608
|
}
|
|
31583
31609
|
async readReplay(sessionPath, threadId2, fingerprint2, empty) {
|
|
31584
|
-
const handle = await
|
|
31610
|
+
const handle = await fs33.open(sessionPath, "r");
|
|
31585
31611
|
if (this.closed) {
|
|
31586
31612
|
await handle.close();
|
|
31587
31613
|
return empty;
|
|
@@ -32176,7 +32202,7 @@ var init_app_server_upgrade = __esm({
|
|
|
32176
32202
|
|
|
32177
32203
|
// apps/desktop/src/daemon/codex-subagent-avatars.ts
|
|
32178
32204
|
import { open as open3 } from "node:fs/promises";
|
|
32179
|
-
import
|
|
32205
|
+
import path44 from "node:path";
|
|
32180
32206
|
import sharp from "sharp";
|
|
32181
32207
|
function record11(value) {
|
|
32182
32208
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -32217,7 +32243,7 @@ async function parseCatalog(source2, readAsset) {
|
|
|
32217
32243
|
}
|
|
32218
32244
|
return new CodexSubagentAvatars(images);
|
|
32219
32245
|
}
|
|
32220
|
-
async function loadCodexSubagentAvatars(archivePath =
|
|
32246
|
+
async function loadCodexSubagentAvatars(archivePath = path44.join(path44.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
|
|
32221
32247
|
let file;
|
|
32222
32248
|
try {
|
|
32223
32249
|
file = await open3(archivePath, "r");
|
|
@@ -32284,8 +32310,8 @@ var init_codex_subagent_avatars = __esm({
|
|
|
32284
32310
|
});
|
|
32285
32311
|
|
|
32286
32312
|
// apps/desktop/src/platform/private-document-files.ts
|
|
32287
|
-
import
|
|
32288
|
-
import
|
|
32313
|
+
import fs34 from "node:fs";
|
|
32314
|
+
import path45 from "node:path";
|
|
32289
32315
|
import { randomUUID as randomUUID25 } from "node:crypto";
|
|
32290
32316
|
function checkLimit(maxBytes) {
|
|
32291
32317
|
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 32 * 1024 * 1024) throw new PrivateDocumentFileError("capacity");
|
|
@@ -32297,7 +32323,7 @@ function trusted3(stats, directory3 = false, strictDirectory = false) {
|
|
|
32297
32323
|
}
|
|
32298
32324
|
function statFile(file, maxBytes) {
|
|
32299
32325
|
try {
|
|
32300
|
-
const stats =
|
|
32326
|
+
const stats = fs34.lstatSync(file, { bigint: true });
|
|
32301
32327
|
if (!trusted3(stats)) throw new PrivateDocumentFileError("unavailable");
|
|
32302
32328
|
if (stats.size > BigInt(maxBytes)) throw new PrivateDocumentFileError("capacity");
|
|
32303
32329
|
return stats;
|
|
@@ -32317,33 +32343,33 @@ function readPosix(file, maxBytes, strictDirectory) {
|
|
|
32317
32343
|
let directoryFd;
|
|
32318
32344
|
let fd;
|
|
32319
32345
|
try {
|
|
32320
|
-
const directory3 =
|
|
32346
|
+
const directory3 = path45.dirname(file);
|
|
32321
32347
|
let parent;
|
|
32322
32348
|
try {
|
|
32323
|
-
parent =
|
|
32349
|
+
parent = fs34.lstatSync(directory3, { bigint: true });
|
|
32324
32350
|
} catch (error2) {
|
|
32325
32351
|
if (missing(error2)) return null;
|
|
32326
32352
|
throw error2;
|
|
32327
32353
|
}
|
|
32328
32354
|
if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
|
|
32329
|
-
directoryFd =
|
|
32330
|
-
if (!same5(parent,
|
|
32355
|
+
directoryFd = fs34.openSync(directory3, fs34.constants.O_RDONLY | fs34.constants.O_NOFOLLOW);
|
|
32356
|
+
if (!same5(parent, fs34.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
|
|
32331
32357
|
const original = statFile(file, maxBytes);
|
|
32332
32358
|
if (original === null) return null;
|
|
32333
|
-
fd =
|
|
32334
|
-
const opened =
|
|
32359
|
+
fd = fs34.openSync(file, fs34.constants.O_RDONLY | fs34.constants.O_NOFOLLOW);
|
|
32360
|
+
const opened = fs34.fstatSync(fd, { bigint: true });
|
|
32335
32361
|
if (!trusted3(opened) || !same5(original, opened) || original.size !== opened.size) throw new PrivateDocumentFileError("unavailable");
|
|
32336
32362
|
const contents = Buffer.alloc(maxBytes + 1);
|
|
32337
32363
|
try {
|
|
32338
32364
|
let length = 0;
|
|
32339
32365
|
while (length < contents.length) {
|
|
32340
|
-
const count =
|
|
32366
|
+
const count = fs34.readSync(fd, contents, length, contents.length - length, null);
|
|
32341
32367
|
if (count === 0) break;
|
|
32342
32368
|
length += count;
|
|
32343
32369
|
}
|
|
32344
32370
|
if (length > maxBytes) throw new PrivateDocumentFileError("capacity");
|
|
32345
32371
|
const current2 = statFile(file, maxBytes);
|
|
32346
|
-
if (current2 === null || !same5(original, current2) || !same5(parent,
|
|
32372
|
+
if (current2 === null || !same5(original, current2) || !same5(parent, fs34.lstatSync(directory3, { bigint: true }))) {
|
|
32347
32373
|
throw new PrivateDocumentFileError("unavailable");
|
|
32348
32374
|
}
|
|
32349
32375
|
return decode(contents.subarray(0, length));
|
|
@@ -32352,42 +32378,42 @@ function readPosix(file, maxBytes, strictDirectory) {
|
|
|
32352
32378
|
}
|
|
32353
32379
|
} finally {
|
|
32354
32380
|
try {
|
|
32355
|
-
if (fd !== void 0)
|
|
32381
|
+
if (fd !== void 0) fs34.closeSync(fd);
|
|
32356
32382
|
} finally {
|
|
32357
|
-
if (directoryFd !== void 0)
|
|
32383
|
+
if (directoryFd !== void 0) fs34.closeSync(directoryFd);
|
|
32358
32384
|
}
|
|
32359
32385
|
}
|
|
32360
32386
|
}
|
|
32361
32387
|
function writePosix(file, body, maxBytes, strictDirectory) {
|
|
32362
|
-
const directory3 =
|
|
32363
|
-
const temporary =
|
|
32388
|
+
const directory3 = path45.dirname(file);
|
|
32389
|
+
const temporary = path45.join(directory3, `.${path45.basename(file)}.${randomUUID25()}.tmp`);
|
|
32364
32390
|
let directoryFd;
|
|
32365
32391
|
let fd;
|
|
32366
32392
|
let created = false;
|
|
32367
32393
|
let renamed = false;
|
|
32368
32394
|
try {
|
|
32369
|
-
|
|
32370
|
-
const parent =
|
|
32395
|
+
fs34.mkdirSync(directory3, { recursive: true, mode: 448 });
|
|
32396
|
+
const parent = fs34.lstatSync(directory3, { bigint: true });
|
|
32371
32397
|
if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
|
|
32372
|
-
directoryFd =
|
|
32373
|
-
if (!same5(parent,
|
|
32398
|
+
directoryFd = fs34.openSync(directory3, fs34.constants.O_RDONLY | fs34.constants.O_NOFOLLOW);
|
|
32399
|
+
if (!same5(parent, fs34.fstatSync(directoryFd, { bigint: true }))) throw new PrivateDocumentFileError("unavailable");
|
|
32374
32400
|
const original = statFile(file, maxBytes);
|
|
32375
|
-
fd =
|
|
32401
|
+
fd = fs34.openSync(temporary, fs34.constants.O_WRONLY | fs34.constants.O_CREAT | fs34.constants.O_EXCL | fs34.constants.O_NOFOLLOW, 384);
|
|
32376
32402
|
created = true;
|
|
32377
|
-
const temporaryIdentity =
|
|
32403
|
+
const temporaryIdentity = fs34.fstatSync(fd, { bigint: true });
|
|
32378
32404
|
if (!trusted3(temporaryIdentity)) throw new PrivateDocumentFileError("unavailable");
|
|
32379
|
-
|
|
32380
|
-
|
|
32381
|
-
|
|
32405
|
+
fs34.writeFileSync(fd, body);
|
|
32406
|
+
fs34.fsyncSync(fd);
|
|
32407
|
+
fs34.closeSync(fd);
|
|
32382
32408
|
fd = void 0;
|
|
32383
32409
|
const current2 = statFile(file, maxBytes);
|
|
32384
|
-
if (!same5(parent,
|
|
32410
|
+
if (!same5(parent, fs34.lstatSync(directory3, { bigint: true })) || !same5(temporaryIdentity, fs34.lstatSync(temporary, { bigint: true })) || (original === null ? current2 !== null : current2 === null || !same5(original, current2))) {
|
|
32385
32411
|
throw new PrivateDocumentFileError("unavailable");
|
|
32386
32412
|
}
|
|
32387
|
-
|
|
32413
|
+
fs34.renameSync(temporary, file);
|
|
32388
32414
|
renamed = true;
|
|
32389
32415
|
created = false;
|
|
32390
|
-
|
|
32416
|
+
fs34.fsyncSync(directoryFd);
|
|
32391
32417
|
} catch (error2) {
|
|
32392
32418
|
if (error2 instanceof PrivateDocumentFileError && !renamed) throw error2;
|
|
32393
32419
|
throw new PrivateDocumentFileError("write_failed", renamed);
|
|
@@ -32395,7 +32421,7 @@ function writePosix(file, body, maxBytes, strictDirectory) {
|
|
|
32395
32421
|
try {
|
|
32396
32422
|
if (fd !== void 0) {
|
|
32397
32423
|
try {
|
|
32398
|
-
|
|
32424
|
+
fs34.closeSync(fd);
|
|
32399
32425
|
} catch {
|
|
32400
32426
|
}
|
|
32401
32427
|
}
|
|
@@ -32403,14 +32429,14 @@ function writePosix(file, body, maxBytes, strictDirectory) {
|
|
|
32403
32429
|
try {
|
|
32404
32430
|
if (directoryFd !== void 0) {
|
|
32405
32431
|
try {
|
|
32406
|
-
|
|
32432
|
+
fs34.closeSync(directoryFd);
|
|
32407
32433
|
} catch {
|
|
32408
32434
|
}
|
|
32409
32435
|
}
|
|
32410
32436
|
} finally {
|
|
32411
32437
|
if (created) {
|
|
32412
32438
|
try {
|
|
32413
|
-
|
|
32439
|
+
fs34.unlinkSync(temporary);
|
|
32414
32440
|
} catch {
|
|
32415
32441
|
}
|
|
32416
32442
|
}
|
|
@@ -32444,7 +32470,7 @@ async function windowsDocument(file, maxBytes, body) {
|
|
|
32444
32470
|
return result;
|
|
32445
32471
|
}
|
|
32446
32472
|
function serialFile(file, operation) {
|
|
32447
|
-
const absolute =
|
|
32473
|
+
const absolute = path45.resolve(file);
|
|
32448
32474
|
const key = desktopPlatform().id === "windows" ? absolute.toLowerCase() : absolute;
|
|
32449
32475
|
const result = (operations.get(key) ?? Promise.resolve()).then(operation);
|
|
32450
32476
|
const tail = result.then(() => {
|
|
@@ -32462,7 +32488,7 @@ function documentFiles(strictDirectory, guard) {
|
|
|
32462
32488
|
return serialFile(file, async () => {
|
|
32463
32489
|
try {
|
|
32464
32490
|
guard?.();
|
|
32465
|
-
const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(
|
|
32491
|
+
const body = desktopPlatform().id === "windows" ? await windowsDocument(file, maxBytes) : readPosix(path45.resolve(file), maxBytes, strictDirectory);
|
|
32466
32492
|
guard?.();
|
|
32467
32493
|
return body;
|
|
32468
32494
|
} catch (error2) {
|
|
@@ -32477,7 +32503,7 @@ function documentFiles(strictDirectory, guard) {
|
|
|
32477
32503
|
await serialFile(file, async () => {
|
|
32478
32504
|
guard?.();
|
|
32479
32505
|
if (desktopPlatform().id === "windows") await windowsDocument(file, maxBytes, body);
|
|
32480
|
-
else writePosix(
|
|
32506
|
+
else writePosix(path45.resolve(file), body, maxBytes, strictDirectory);
|
|
32481
32507
|
try {
|
|
32482
32508
|
guard?.();
|
|
32483
32509
|
} catch {
|
|
@@ -32516,7 +32542,7 @@ var init_private_document_files = __esm({
|
|
|
32516
32542
|
});
|
|
32517
32543
|
|
|
32518
32544
|
// apps/desktop/src/local-state/paths.ts
|
|
32519
|
-
import
|
|
32545
|
+
import path46 from "node:path";
|
|
32520
32546
|
function applicationStateDirectory() {
|
|
32521
32547
|
return desktopPlatform().directories.state;
|
|
32522
32548
|
}
|
|
@@ -32524,37 +32550,37 @@ function cliCacheDirectory() {
|
|
|
32524
32550
|
return desktopPlatform().directories.cliCache;
|
|
32525
32551
|
}
|
|
32526
32552
|
function managedThreadsStatePath() {
|
|
32527
|
-
return
|
|
32553
|
+
return path46.join(applicationStateDirectory(), "managed-threads-v1.json");
|
|
32528
32554
|
}
|
|
32529
32555
|
function threadSettingsStatePath() {
|
|
32530
|
-
return
|
|
32556
|
+
return path46.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
|
|
32531
32557
|
}
|
|
32532
32558
|
function threadListStatePath() {
|
|
32533
|
-
return
|
|
32559
|
+
return path46.join(applicationStateDirectory(), "thread-list-cache-v1.json");
|
|
32534
32560
|
}
|
|
32535
32561
|
function daemonMetricsStatePath() {
|
|
32536
|
-
return
|
|
32562
|
+
return path46.join(applicationStateDirectory(), "daemon-metrics-v1.json");
|
|
32537
32563
|
}
|
|
32538
32564
|
function desktopIdentityCandidatesStatePath() {
|
|
32539
|
-
return
|
|
32565
|
+
return path46.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
|
|
32540
32566
|
}
|
|
32541
32567
|
function pendingRequestsCachePath() {
|
|
32542
|
-
return
|
|
32568
|
+
return path46.join(cliCacheDirectory(), "pending-requests-v1.json");
|
|
32543
32569
|
}
|
|
32544
32570
|
function idempotencyCachePath() {
|
|
32545
|
-
return
|
|
32571
|
+
return path46.join(cliCacheDirectory(), "idempotency-v1.json");
|
|
32546
32572
|
}
|
|
32547
32573
|
function messageSubmissionsStatePath() {
|
|
32548
|
-
return
|
|
32574
|
+
return path46.join(applicationStateDirectory(), "message-submissions-v1.json");
|
|
32549
32575
|
}
|
|
32550
32576
|
function deviceNameStatePath() {
|
|
32551
|
-
return
|
|
32577
|
+
return path46.join(applicationStateDirectory(), "device-name-v1.json");
|
|
32552
32578
|
}
|
|
32553
32579
|
function threadReadReceiptsStatePath() {
|
|
32554
|
-
return
|
|
32580
|
+
return path46.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
|
|
32555
32581
|
}
|
|
32556
32582
|
function asyncQuestionFactsStatePath() {
|
|
32557
|
-
return
|
|
32583
|
+
return path46.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
|
|
32558
32584
|
}
|
|
32559
32585
|
var init_paths2 = __esm({
|
|
32560
32586
|
"apps/desktop/src/local-state/paths.ts"() {
|
|
@@ -34160,7 +34186,7 @@ var init_thread_timeline_cache = __esm({
|
|
|
34160
34186
|
});
|
|
34161
34187
|
|
|
34162
34188
|
// apps/desktop/src/daemon/thread-state-store.ts
|
|
34163
|
-
import
|
|
34189
|
+
import path47 from "node:path";
|
|
34164
34190
|
function projectRecency(entry) {
|
|
34165
34191
|
return entry.threads.reduce(
|
|
34166
34192
|
(latest, thread4) => Math.max(latest, thread4.recencyAt ?? thread4.updatedAt),
|
|
@@ -34269,8 +34295,8 @@ function normalizePathForCompare(value) {
|
|
|
34269
34295
|
if (!value) {
|
|
34270
34296
|
return "";
|
|
34271
34297
|
}
|
|
34272
|
-
const normalized =
|
|
34273
|
-
if (normalized.length > 1 && normalized.endsWith(
|
|
34298
|
+
const normalized = path47.normalize(value);
|
|
34299
|
+
if (normalized.length > 1 && normalized.endsWith(path47.sep)) {
|
|
34274
34300
|
return normalized.slice(0, -1);
|
|
34275
34301
|
}
|
|
34276
34302
|
return normalized;
|
|
@@ -34295,7 +34321,7 @@ function isPathWithinRoot(cwd, root) {
|
|
|
34295
34321
|
if (normalizedCwd === normalizedRoot) {
|
|
34296
34322
|
return true;
|
|
34297
34323
|
}
|
|
34298
|
-
return normalizedCwd.startsWith(`${normalizedRoot}${
|
|
34324
|
+
return normalizedCwd.startsWith(`${normalizedRoot}${path47.sep}`);
|
|
34299
34325
|
}
|
|
34300
34326
|
function findLongestMatchingRoot(cwd, roots) {
|
|
34301
34327
|
let matched = null;
|
|
@@ -34318,7 +34344,7 @@ function labelForRoot(root, labels) {
|
|
|
34318
34344
|
};
|
|
34319
34345
|
}
|
|
34320
34346
|
return {
|
|
34321
|
-
projectName:
|
|
34347
|
+
projectName: path47.basename(root) || root,
|
|
34322
34348
|
projectNameSource: "basename"
|
|
34323
34349
|
};
|
|
34324
34350
|
}
|
|
@@ -35826,10 +35852,10 @@ var init_bootstrap = __esm({
|
|
|
35826
35852
|
});
|
|
35827
35853
|
|
|
35828
35854
|
// apps/desktop/src/platform/private-cache-files.ts
|
|
35829
|
-
import
|
|
35830
|
-
import
|
|
35855
|
+
import fs35 from "node:fs";
|
|
35856
|
+
import path48 from "node:path";
|
|
35831
35857
|
function serialize(file, operation) {
|
|
35832
|
-
const key = process.platform === "win32" ?
|
|
35858
|
+
const key = process.platform === "win32" ? path48.resolve(file).toLowerCase() : path48.resolve(file);
|
|
35833
35859
|
const next = (tails.get(key) ?? Promise.resolve()).then(operation);
|
|
35834
35860
|
const tail = next.catch(() => {
|
|
35835
35861
|
});
|
|
@@ -35844,23 +35870,23 @@ function trusted4(stat4, directory3 = false) {
|
|
|
35844
35870
|
return uid !== void 0 && stat4.uid === BigInt(uid) && (directory3 ? stat4.isDirectory() && (stat4.mode & 0o777n) === 0o700n : stat4.isFile() && stat4.nlink === 1n && (stat4.mode & 0o777n) === 0o600n);
|
|
35845
35871
|
}
|
|
35846
35872
|
async function withMacLock(file, operation) {
|
|
35847
|
-
const directory3 =
|
|
35848
|
-
const lock =
|
|
35849
|
-
|
|
35850
|
-
const parent =
|
|
35873
|
+
const directory3 = path48.dirname(file);
|
|
35874
|
+
const lock = path48.join(directory3, `.${path48.basename(file)}.lock`);
|
|
35875
|
+
fs35.mkdirSync(directory3, { recursive: true, mode: 448 });
|
|
35876
|
+
const parent = fs35.lstatSync(directory3, { bigint: true });
|
|
35851
35877
|
if (!trusted4(parent, true)) throw new PrivateDocumentFileError("unavailable");
|
|
35852
35878
|
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
35853
35879
|
let fd;
|
|
35854
35880
|
for (; ; ) {
|
|
35855
35881
|
let initial = null;
|
|
35856
35882
|
try {
|
|
35857
|
-
initial =
|
|
35883
|
+
initial = fs35.lstatSync(lock, { bigint: true });
|
|
35858
35884
|
} catch (error2) {
|
|
35859
35885
|
if (error2.code !== "ENOENT") throw error2;
|
|
35860
35886
|
}
|
|
35861
35887
|
if (initial && !trusted4(initial)) throw new PrivateDocumentFileError("unavailable");
|
|
35862
35888
|
try {
|
|
35863
|
-
fd =
|
|
35889
|
+
fd = fs35.openSync(lock, fs35.constants.O_RDWR | fs35.constants.O_CREAT | fs35.constants.O_NOFOLLOW | fs35.constants.O_NONBLOCK | 32, 384);
|
|
35864
35890
|
} catch (error2) {
|
|
35865
35891
|
const code = error2.code;
|
|
35866
35892
|
if (code !== "EAGAIN" && code !== "EWOULDBLOCK" || Date.now() >= deadline) throw error2;
|
|
@@ -35868,10 +35894,10 @@ async function withMacLock(file, operation) {
|
|
|
35868
35894
|
continue;
|
|
35869
35895
|
}
|
|
35870
35896
|
try {
|
|
35871
|
-
const opened =
|
|
35897
|
+
const opened = fs35.fstatSync(fd, { bigint: true });
|
|
35872
35898
|
const verify = () => {
|
|
35873
|
-
const current2 =
|
|
35874
|
-
const currentParent =
|
|
35899
|
+
const current2 = fs35.lstatSync(lock, { bigint: true });
|
|
35900
|
+
const currentParent = fs35.lstatSync(directory3, { bigint: true });
|
|
35875
35901
|
if (!trusted4(opened) || !trusted4(current2) || !same6(opened, current2) || initial !== null && !same6(initial, opened) || !trusted4(currentParent, true) || !same6(parent, currentParent)) {
|
|
35876
35902
|
throw new PrivateDocumentFileError("unavailable");
|
|
35877
35903
|
}
|
|
@@ -35881,7 +35907,7 @@ async function withMacLock(file, operation) {
|
|
|
35881
35907
|
verify();
|
|
35882
35908
|
return value;
|
|
35883
35909
|
} finally {
|
|
35884
|
-
|
|
35910
|
+
fs35.closeSync(fd);
|
|
35885
35911
|
}
|
|
35886
35912
|
}
|
|
35887
35913
|
}
|
|
@@ -35912,7 +35938,7 @@ var init_private_cache_files = __esm({
|
|
|
35912
35938
|
return serialize(file, async () => {
|
|
35913
35939
|
checkLimit2(maxBytes);
|
|
35914
35940
|
try {
|
|
35915
|
-
|
|
35941
|
+
fs35.lstatSync(file);
|
|
35916
35942
|
} catch (error2) {
|
|
35917
35943
|
if (error2.code === "ENOENT") return null;
|
|
35918
35944
|
throw error2;
|
|
@@ -35925,7 +35951,7 @@ var init_private_cache_files = __esm({
|
|
|
35925
35951
|
checkLimit2(maxBytes);
|
|
35926
35952
|
if (process.platform === "win32") return windowsTransaction(file, maxBytes, transform);
|
|
35927
35953
|
if (process.platform !== "darwin") throw new PrivateDocumentFileError("unavailable");
|
|
35928
|
-
return withMacLock(
|
|
35954
|
+
return withMacLock(path48.resolve(file), async (verify) => {
|
|
35929
35955
|
const result = transform(await privateStateFiles.read(file, maxBytes));
|
|
35930
35956
|
verify();
|
|
35931
35957
|
if (result.body !== void 0) await privateStateFiles.write(file, Buffer.from(result.body), maxBytes);
|
|
@@ -36209,7 +36235,7 @@ var init_pending_cache = __esm({
|
|
|
36209
36235
|
});
|
|
36210
36236
|
|
|
36211
36237
|
// apps/desktop/src/niuma/session-pending.ts
|
|
36212
|
-
import
|
|
36238
|
+
import fs36 from "node:fs";
|
|
36213
36239
|
function objectRecord7(value) {
|
|
36214
36240
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
36215
36241
|
}
|
|
@@ -36232,7 +36258,7 @@ function inferPendingRequestFromSession(threadId2, sessionPath, latestTurnId = n
|
|
|
36232
36258
|
}
|
|
36233
36259
|
let lines;
|
|
36234
36260
|
try {
|
|
36235
|
-
lines =
|
|
36261
|
+
lines = fs36.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
|
|
36236
36262
|
} catch {
|
|
36237
36263
|
return null;
|
|
36238
36264
|
}
|
|
@@ -37044,7 +37070,7 @@ var init_settings = __esm({
|
|
|
37044
37070
|
|
|
37045
37071
|
// apps/desktop/src/direct-gateway/v5-binding-store.ts
|
|
37046
37072
|
import { randomUUID as randomUUID26, createHash as createHash17 } from "node:crypto";
|
|
37047
|
-
import
|
|
37073
|
+
import path49 from "node:path";
|
|
37048
37074
|
function bindingFileError() {
|
|
37049
37075
|
return new Error("Desktop V5 Binding \u6587\u4EF6\u65E0\u6548");
|
|
37050
37076
|
}
|
|
@@ -37178,7 +37204,7 @@ function parseResetMarker(value, desktopId) {
|
|
|
37178
37204
|
}
|
|
37179
37205
|
}
|
|
37180
37206
|
function resolveDefaultDesktopV5BindingFilePath() {
|
|
37181
|
-
return
|
|
37207
|
+
return path49.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
|
|
37182
37208
|
}
|
|
37183
37209
|
function pushDisplayName(name2) {
|
|
37184
37210
|
let result = "";
|
|
@@ -37245,7 +37271,7 @@ var init_v5_binding_store = __esm({
|
|
|
37245
37271
|
for (const wake of this.pushWaiters) wake();
|
|
37246
37272
|
}
|
|
37247
37273
|
constructor(options = {}) {
|
|
37248
|
-
this.filePath =
|
|
37274
|
+
this.filePath = path49.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
|
|
37249
37275
|
this.files = options.files ?? privateDocumentFiles;
|
|
37250
37276
|
}
|
|
37251
37277
|
async load(desktopId) {
|
|
@@ -37495,7 +37521,7 @@ var init_v5_binding_store = __esm({
|
|
|
37495
37521
|
await this.writeAtomicFile(this.resetMarkerPath(), serializeResetMarker(desktopId), bindingFileError);
|
|
37496
37522
|
}
|
|
37497
37523
|
resetMarkerPath() {
|
|
37498
|
-
return
|
|
37524
|
+
return path49.join(path49.dirname(this.filePath), RESET_MARKER_FILE_NAME);
|
|
37499
37525
|
}
|
|
37500
37526
|
async writeAtomicFile(targetPath2, body, failure) {
|
|
37501
37527
|
try {
|
|
@@ -42700,7 +42726,7 @@ var init_candidate_catalog2 = __esm({
|
|
|
42700
42726
|
});
|
|
42701
42727
|
|
|
42702
42728
|
// apps/desktop/src/direct-gateway/identity-store.ts
|
|
42703
|
-
import
|
|
42729
|
+
import path50 from "node:path";
|
|
42704
42730
|
function copyIdentity(identity6) {
|
|
42705
42731
|
return {
|
|
42706
42732
|
desktop_id: identity6.desktop_id,
|
|
@@ -42755,7 +42781,7 @@ function deserializeIdentity(value) {
|
|
|
42755
42781
|
}
|
|
42756
42782
|
}
|
|
42757
42783
|
function resolveDefaultDesktopIdentityFilePath() {
|
|
42758
|
-
return
|
|
42784
|
+
return path50.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
|
|
42759
42785
|
}
|
|
42760
42786
|
var IDENTITY_KEY_BYTES2, DEFAULT_IDENTITY_FILE_NAME, MAX_IDENTITY_BYTES, FileDesktopIdentityStore;
|
|
42761
42787
|
var init_identity_store = __esm({
|
|
@@ -42771,7 +42797,7 @@ var init_identity_store = __esm({
|
|
|
42771
42797
|
filePath;
|
|
42772
42798
|
files;
|
|
42773
42799
|
constructor(options = {}) {
|
|
42774
|
-
this.filePath =
|
|
42800
|
+
this.filePath = path50.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
|
|
42775
42801
|
this.files = options.files ?? privateDocumentFiles;
|
|
42776
42802
|
}
|
|
42777
42803
|
async load() {
|
|
@@ -46184,7 +46210,7 @@ var init_routes3 = __esm({
|
|
|
46184
46210
|
|
|
46185
46211
|
// apps/desktop/src/pairing-web/server.ts
|
|
46186
46212
|
import http3 from "node:http";
|
|
46187
|
-
import
|
|
46213
|
+
import fs37 from "node:fs/promises";
|
|
46188
46214
|
var ASSETS, PairingWebServer;
|
|
46189
46215
|
var init_server3 = __esm({
|
|
46190
46216
|
"apps/desktop/src/pairing-web/server.ts"() {
|
|
@@ -46268,7 +46294,7 @@ var init_server3 = __esm({
|
|
|
46268
46294
|
}
|
|
46269
46295
|
const asset = ASSETS[raw];
|
|
46270
46296
|
if (request2.method !== "GET" || !asset) throw new HttpApiError(404, 900005, "\u63A5\u53E3\u4E0D\u5B58\u5728");
|
|
46271
|
-
const body = await
|
|
46297
|
+
const body = await fs37.readFile(desktopAssetUrl("pairing-web", asset[0]));
|
|
46272
46298
|
response.writeHead(200, { "Content-Type": asset[1] });
|
|
46273
46299
|
response.end(body);
|
|
46274
46300
|
} catch (error2) {
|
|
@@ -48052,21 +48078,21 @@ var init_desktop_timeline_events = __esm({
|
|
|
48052
48078
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
48053
48079
|
continue;
|
|
48054
48080
|
}
|
|
48055
|
-
const
|
|
48056
|
-
if (
|
|
48081
|
+
const path71 = array2(patch.path);
|
|
48082
|
+
if (path71.length === 4 && path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && typeof path71[3] === "string") {
|
|
48057
48083
|
const turnId = turnIdFromEntity(record14(patch.value));
|
|
48058
48084
|
if (turnId) {
|
|
48059
|
-
this.entityTurnIds.set(this.entityKey(threadId2,
|
|
48085
|
+
this.entityTurnIds.set(this.entityKey(threadId2, path71[3]), turnId);
|
|
48060
48086
|
}
|
|
48061
48087
|
continue;
|
|
48062
48088
|
}
|
|
48063
|
-
if (
|
|
48089
|
+
if (path71.length !== 6 || path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey" || typeof path71[3] !== "string" || path71[4] !== "items" || typeof path71[5] !== "number") {
|
|
48064
48090
|
continue;
|
|
48065
48091
|
}
|
|
48066
48092
|
const occurredAt4 = Math.floor((this.options.now ?? Date.now)() / 1e3);
|
|
48067
48093
|
const item = normalizeTimelineItem(patch.value, {
|
|
48068
48094
|
threadId: threadId2,
|
|
48069
|
-
turnId: this.entityTurnIds.get(this.entityKey(threadId2,
|
|
48095
|
+
turnId: this.entityTurnIds.get(this.entityKey(threadId2, path71[3])) ?? null,
|
|
48070
48096
|
source: "desktop_ipc",
|
|
48071
48097
|
occurredAt: occurredAt4,
|
|
48072
48098
|
resolveKnownLocalImage
|
|
@@ -48112,8 +48138,8 @@ function assignKnownUnreadFields(target, value) {
|
|
|
48112
48138
|
target.unreadMessageCount = value.unreadMessageCount;
|
|
48113
48139
|
}
|
|
48114
48140
|
}
|
|
48115
|
-
function isUnreadFieldPath(
|
|
48116
|
-
return
|
|
48141
|
+
function isUnreadFieldPath(path71, field2) {
|
|
48142
|
+
return path71.length === 1 && path71[0] === field2 || path71.length === 2 && path71[0] === "conversationState" && path71[1] === field2;
|
|
48117
48143
|
}
|
|
48118
48144
|
function hasUpdateFields(update) {
|
|
48119
48145
|
return "hasUnreadTurn" in update || "unreadMessageCount" in update;
|
|
@@ -48139,19 +48165,19 @@ function extractDesktopUnreadUpdate(frame) {
|
|
|
48139
48165
|
}
|
|
48140
48166
|
for (const patchValue of change.patches) {
|
|
48141
48167
|
const patch = record15(patchValue);
|
|
48142
|
-
const
|
|
48168
|
+
const path71 = Array.isArray(patch.path) ? patch.path : [];
|
|
48143
48169
|
const op = patch.op;
|
|
48144
48170
|
if (op !== "add" && op !== "replace" && op !== "remove") {
|
|
48145
48171
|
continue;
|
|
48146
48172
|
}
|
|
48147
|
-
if (isUnreadFieldPath(
|
|
48173
|
+
if (isUnreadFieldPath(path71, "hasUnreadTurn")) {
|
|
48148
48174
|
if (op === "remove") {
|
|
48149
48175
|
update.hasUnreadTurn = null;
|
|
48150
48176
|
} else if (typeof patch.value === "boolean") {
|
|
48151
48177
|
update.hasUnreadTurn = patch.value;
|
|
48152
48178
|
}
|
|
48153
48179
|
}
|
|
48154
|
-
if (isUnreadFieldPath(
|
|
48180
|
+
if (isUnreadFieldPath(path71, "unreadMessageCount")) {
|
|
48155
48181
|
if (op === "remove") {
|
|
48156
48182
|
update.unreadMessageCount = null;
|
|
48157
48183
|
} else if (isMessageCount(patch.value)) {
|
|
@@ -48848,15 +48874,15 @@ function revisionOf(value) {
|
|
|
48848
48874
|
function occurredAt() {
|
|
48849
48875
|
return Math.floor(Date.now() / 1e3);
|
|
48850
48876
|
}
|
|
48851
|
-
function itemTarget(
|
|
48852
|
-
const index =
|
|
48853
|
-
if (
|
|
48877
|
+
function itemTarget(path71) {
|
|
48878
|
+
const index = path71[5];
|
|
48879
|
+
if (path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey" || typeof path71[3] !== "string" || path71[4] !== "items" || typeof index !== "number" || !Number.isInteger(index) || index < 0) {
|
|
48854
48880
|
return null;
|
|
48855
48881
|
}
|
|
48856
|
-
return { entityKey:
|
|
48882
|
+
return { entityKey: path71[3], index, itemPathLength: 6 };
|
|
48857
48883
|
}
|
|
48858
|
-
function entityTarget(
|
|
48859
|
-
return
|
|
48884
|
+
function entityTarget(path71) {
|
|
48885
|
+
return path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && typeof path71[3] === "string" ? path71[3] : null;
|
|
48860
48886
|
}
|
|
48861
48887
|
function phaseOf(status2) {
|
|
48862
48888
|
if (status2 === "failed" || status2 === "error") {
|
|
@@ -49142,15 +49168,15 @@ var init_desktop_activity_events = __esm({
|
|
|
49142
49168
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
49143
49169
|
continue;
|
|
49144
49170
|
}
|
|
49145
|
-
const
|
|
49146
|
-
const targetItem = itemTarget(
|
|
49171
|
+
const path71 = array3(patch.path);
|
|
49172
|
+
const targetItem = itemTarget(path71);
|
|
49147
49173
|
if (targetItem) {
|
|
49148
|
-
signals.push(...this.consumeItemPatch(threadId2, state, targetItem,
|
|
49174
|
+
signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path71, patch.value, patch.op));
|
|
49149
49175
|
continue;
|
|
49150
49176
|
}
|
|
49151
|
-
const targetEntity = entityTarget(
|
|
49177
|
+
const targetEntity = entityTarget(path71);
|
|
49152
49178
|
if (targetEntity) {
|
|
49153
|
-
signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity,
|
|
49179
|
+
signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path71, patch.value));
|
|
49154
49180
|
}
|
|
49155
49181
|
}
|
|
49156
49182
|
return signals;
|
|
@@ -49224,12 +49250,12 @@ var init_desktop_activity_events = __esm({
|
|
|
49224
49250
|
occurredAt: occurredAt()
|
|
49225
49251
|
}];
|
|
49226
49252
|
}
|
|
49227
|
-
consumeItemPatch(threadId2, state, target,
|
|
49253
|
+
consumeItemPatch(threadId2, state, target, path71, value, op) {
|
|
49228
49254
|
const entity = state.entities.get(target.entityKey);
|
|
49229
49255
|
if (!entity || state.currentActiveEntityKey !== target.entityKey || state.currentActiveTurnId !== entity.turnId) {
|
|
49230
49256
|
return [];
|
|
49231
49257
|
}
|
|
49232
|
-
if (
|
|
49258
|
+
if (path71.length === target.itemPathLength) {
|
|
49233
49259
|
return this.prependLiveTurnStart(threadId2, entity, this.consumeWholeItem(
|
|
49234
49260
|
threadId2,
|
|
49235
49261
|
entity,
|
|
@@ -49239,13 +49265,13 @@ var init_desktop_activity_events = __esm({
|
|
|
49239
49265
|
));
|
|
49240
49266
|
}
|
|
49241
49267
|
const existing = entity.items.get(target.index);
|
|
49242
|
-
if (!existing ||
|
|
49268
|
+
if (!existing || path71.length < target.itemPathLength + 1) {
|
|
49243
49269
|
return [];
|
|
49244
49270
|
}
|
|
49245
|
-
const field2 =
|
|
49271
|
+
const field2 = path71[target.itemPathLength];
|
|
49246
49272
|
if (existing.type === "reasoning" && field2 === "summary") {
|
|
49247
49273
|
const summary = structuredClone(existing.summary ?? []);
|
|
49248
|
-
const suffix =
|
|
49274
|
+
const suffix = path71.slice(target.itemPathLength + 1);
|
|
49249
49275
|
if (suffix.length === 0) {
|
|
49250
49276
|
existing.summary = structuredClone(Array.isArray(value) ? value : [value]);
|
|
49251
49277
|
} else {
|
|
@@ -49345,9 +49371,9 @@ var init_desktop_activity_events = __esm({
|
|
|
49345
49371
|
});
|
|
49346
49372
|
return [this.activitySignal(threadId2, entity.turnId, itemId, mapping)];
|
|
49347
49373
|
}
|
|
49348
|
-
consumeEntityPatch(threadId2, state, entityKey,
|
|
49349
|
-
const wholeEntity =
|
|
49350
|
-
const statusField =
|
|
49374
|
+
consumeEntityPatch(threadId2, state, entityKey, path71, value) {
|
|
49375
|
+
const wholeEntity = path71.length === 4;
|
|
49376
|
+
const statusField = path71.length === 5 && path71[4] === "status";
|
|
49351
49377
|
if (!wholeEntity && !statusField) {
|
|
49352
49378
|
return [];
|
|
49353
49379
|
}
|
|
@@ -49527,20 +49553,20 @@ var init_desktop_error_events = __esm({
|
|
|
49527
49553
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
49528
49554
|
continue;
|
|
49529
49555
|
}
|
|
49530
|
-
const
|
|
49531
|
-
if (
|
|
49556
|
+
const path71 = array4(patch.path);
|
|
49557
|
+
if (path71.length === 4 && path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && typeof path71[3] === "string") {
|
|
49532
49558
|
const entity = record17(patch.value);
|
|
49533
49559
|
const turnId2 = turnIdFromEntity2(entity);
|
|
49534
49560
|
if (turnId2) {
|
|
49535
|
-
this.entityTurnIds.set(this.entityKey(threadId2,
|
|
49561
|
+
this.entityTurnIds.set(this.entityKey(threadId2, path71[3]), turnId2);
|
|
49536
49562
|
events.push(...this.errorEvents(threadId2, array4(entity.items), turnId2));
|
|
49537
49563
|
}
|
|
49538
49564
|
continue;
|
|
49539
49565
|
}
|
|
49540
|
-
if (
|
|
49566
|
+
if (path71.length !== 6 || path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey" || typeof path71[3] !== "string" || path71[4] !== "items" || typeof path71[5] !== "number") {
|
|
49541
49567
|
continue;
|
|
49542
49568
|
}
|
|
49543
|
-
const turnId = this.entityTurnIds.get(this.entityKey(threadId2,
|
|
49569
|
+
const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path71[3]));
|
|
49544
49570
|
if (!turnId) {
|
|
49545
49571
|
continue;
|
|
49546
49572
|
}
|
|
@@ -49633,13 +49659,13 @@ function visibleMessage(value, resolveKnownLocalImage) {
|
|
|
49633
49659
|
function occurredAt2() {
|
|
49634
49660
|
return Math.floor(Date.now() / 1e3);
|
|
49635
49661
|
}
|
|
49636
|
-
function itemPath(
|
|
49637
|
-
const index =
|
|
49638
|
-
const itemIndex =
|
|
49639
|
-
return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 &&
|
|
49662
|
+
function itemPath(path71) {
|
|
49663
|
+
const index = path71.lastIndexOf("items");
|
|
49664
|
+
const itemIndex = path71[index + 1];
|
|
49665
|
+
return index >= 0 && typeof itemIndex === "number" && Number.isInteger(itemIndex) && itemIndex >= 0 && path71.length >= index + 2 ? path71.slice(0, index + 2) : null;
|
|
49640
49666
|
}
|
|
49641
|
-
function stateKey(threadId2,
|
|
49642
|
-
return `${threadId2}:${JSON.stringify(
|
|
49667
|
+
function stateKey(threadId2, path71) {
|
|
49668
|
+
return `${threadId2}:${JSON.stringify(path71)}`;
|
|
49643
49669
|
}
|
|
49644
49670
|
function completedKey(threadId2, itemId) {
|
|
49645
49671
|
return `${threadId2}:${itemId}`;
|
|
@@ -49697,35 +49723,35 @@ var init_desktop_stream_events = __esm({
|
|
|
49697
49723
|
if (op !== "add" && op !== "replace" && op !== "remove") {
|
|
49698
49724
|
continue;
|
|
49699
49725
|
}
|
|
49700
|
-
const
|
|
49701
|
-
if (
|
|
49726
|
+
const path71 = array5(patch.path);
|
|
49727
|
+
if (path71[0] === "turnHistory" && (path71.length === 1 || path71[1] === "history" && (path71.length === 2 || path71[2] === "entitiesByKey" && path71.length === 3))) {
|
|
49702
49728
|
this.resetThread(threadId2);
|
|
49703
49729
|
continue;
|
|
49704
49730
|
}
|
|
49705
|
-
if (
|
|
49706
|
-
const values =
|
|
49707
|
-
if (
|
|
49708
|
-
const arrayPath =
|
|
49731
|
+
if (path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey") {
|
|
49732
|
+
const values = path71.length === 4 ? record18(patch.value).items : path71.length === 5 && path71[4] === "items" ? patch.value : void 0;
|
|
49733
|
+
if (path71.length === 4 || path71.length === 5 && path71[4] === "items") {
|
|
49734
|
+
const arrayPath = path71.slice(0, 4).concat("items");
|
|
49709
49735
|
this.replaceArrayStates(threadId2, arrayPath, array5(values), resolveKnownLocalImage);
|
|
49710
49736
|
continue;
|
|
49711
49737
|
}
|
|
49712
49738
|
}
|
|
49713
|
-
const rawIndex =
|
|
49714
|
-
if (op === "add" &&
|
|
49715
|
-
const length = this.arrayLengths.get(stateKey(threadId2,
|
|
49739
|
+
const rawIndex = path71.lastIndexOf("items") + 1;
|
|
49740
|
+
if (op === "add" && path71[rawIndex] === "-" && path71.length === rawIndex + 1) {
|
|
49741
|
+
const length = this.arrayLengths.get(stateKey(threadId2, path71.slice(0, rawIndex)));
|
|
49716
49742
|
if (length === void 0) continue;
|
|
49717
|
-
|
|
49743
|
+
path71[rawIndex] = length;
|
|
49718
49744
|
}
|
|
49719
|
-
const targetItemPath = itemPath(
|
|
49745
|
+
const targetItemPath = itemPath(path71);
|
|
49720
49746
|
if (!targetItemPath) {
|
|
49721
49747
|
continue;
|
|
49722
49748
|
}
|
|
49723
49749
|
const key = stateKey(threadId2, targetItemPath);
|
|
49724
|
-
if (
|
|
49750
|
+
if (path71.length > targetItemPath.length && ["id", "type"].includes(String(path71[targetItemPath.length]))) {
|
|
49725
49751
|
this.states.delete(key);
|
|
49726
49752
|
continue;
|
|
49727
49753
|
}
|
|
49728
|
-
if (
|
|
49754
|
+
if (path71.length === targetItemPath.length) {
|
|
49729
49755
|
const arrayPath = targetItemPath.slice(0, -1);
|
|
49730
49756
|
const index = targetItemPath.at(-1);
|
|
49731
49757
|
if (op === "add" || op === "remove") this.shiftArrayStates(threadId2, arrayPath, index, op);
|
|
@@ -49740,7 +49766,7 @@ var init_desktop_stream_events = __esm({
|
|
|
49740
49766
|
));
|
|
49741
49767
|
continue;
|
|
49742
49768
|
}
|
|
49743
|
-
if (op === "replace" &&
|
|
49769
|
+
if (op === "replace" && path71.length === targetItemPath.length + 1 && path71.at(-1) === "text") {
|
|
49744
49770
|
events.push(...this.consumeTextPatch(threadId2, key, patch.value, revision4));
|
|
49745
49771
|
}
|
|
49746
49772
|
}
|
|
@@ -49752,9 +49778,9 @@ var init_desktop_stream_events = __esm({
|
|
|
49752
49778
|
const prefix = JSON.stringify(arrayPath);
|
|
49753
49779
|
for (const [key2, state] of this.states) {
|
|
49754
49780
|
if (state.threadId !== threadId2) continue;
|
|
49755
|
-
const
|
|
49756
|
-
const at =
|
|
49757
|
-
if (JSON.stringify(
|
|
49781
|
+
const path71 = JSON.parse(key2.slice(threadId2.length + 1));
|
|
49782
|
+
const at = path71.at(-1);
|
|
49783
|
+
if (JSON.stringify(path71.slice(0, -1)) !== prefix || typeof at !== "number" || at < index) continue;
|
|
49758
49784
|
this.states.delete(key2);
|
|
49759
49785
|
if (op === "remove" && at === index) continue;
|
|
49760
49786
|
moved.push([stateKey(threadId2, [...arrayPath, at + (op === "add" ? 1 : -1)]), state]);
|
|
@@ -49765,20 +49791,20 @@ var init_desktop_stream_events = __esm({
|
|
|
49765
49791
|
if (length !== void 0) this.arrayLengths.set(key, Math.max(0, length + (op === "add" ? 1 : -1)));
|
|
49766
49792
|
}
|
|
49767
49793
|
/** 完整数组只重播种本实体的路径;其他轮的正文和按原生身份记录的完成事实不变。 */
|
|
49768
|
-
replaceArrayStates(threadId2,
|
|
49769
|
-
const prefix = JSON.stringify(
|
|
49794
|
+
replaceArrayStates(threadId2, path71, values, resolveKnownLocalImage) {
|
|
49795
|
+
const prefix = JSON.stringify(path71);
|
|
49770
49796
|
for (const [key, state] of this.states) {
|
|
49771
49797
|
if (state.threadId !== threadId2) continue;
|
|
49772
49798
|
const itemPath2 = JSON.parse(key.slice(threadId2.length + 1));
|
|
49773
49799
|
if (JSON.stringify(itemPath2.slice(0, -1)) === prefix) this.states.delete(key);
|
|
49774
49800
|
}
|
|
49775
|
-
this.arrayLengths.set(stateKey(threadId2,
|
|
49801
|
+
this.arrayLengths.set(stateKey(threadId2, path71), values.length);
|
|
49776
49802
|
values.forEach((value, index) => {
|
|
49777
49803
|
const message = visibleMessage(value, resolveKnownLocalImage);
|
|
49778
49804
|
if (!message) return;
|
|
49779
49805
|
if (message.role === "user") this.completed.add(completedKey(threadId2, message.itemId));
|
|
49780
49806
|
else if (!this.completed.has(completedKey(threadId2, message.itemId))) {
|
|
49781
|
-
this.states.set(stateKey(threadId2, [...
|
|
49807
|
+
this.states.set(stateKey(threadId2, [...path71, index]), { threadId: threadId2, ...message, lastText: message.text });
|
|
49782
49808
|
}
|
|
49783
49809
|
});
|
|
49784
49810
|
}
|
|
@@ -50903,8 +50929,8 @@ var init_socket_client = __esm({
|
|
|
50903
50929
|
this.diagnosticProfile = diagnosticProfile;
|
|
50904
50930
|
this.socketPaths = socketPath ? [socketPath] : defaultSocketPaths;
|
|
50905
50931
|
const reader = new DesktopRuntimeVersionReader();
|
|
50906
|
-
this.runtimeVersion = new RuntimeVersionCache(async (
|
|
50907
|
-
const value = versionReader ? await versionReader(
|
|
50932
|
+
this.runtimeVersion = new RuntimeVersionCache(async (path71, signal) => {
|
|
50933
|
+
const value = versionReader ? await versionReader(path71, signal) : await reader.read(path71, signal);
|
|
50908
50934
|
return typeof value === "string" ? { version: value, build: null } : value;
|
|
50909
50935
|
});
|
|
50910
50936
|
}
|
|
@@ -53191,7 +53217,7 @@ var init_desktop_read_refresh_queue = __esm({
|
|
|
53191
53217
|
import { watch } from "node:fs";
|
|
53192
53218
|
import { open as open4, stat as statPath } from "node:fs/promises";
|
|
53193
53219
|
import { createHash as createHash22 } from "node:crypto";
|
|
53194
|
-
import
|
|
53220
|
+
import path51 from "node:path";
|
|
53195
53221
|
function record20(value) {
|
|
53196
53222
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
53197
53223
|
}
|
|
@@ -53335,7 +53361,7 @@ var init_desktop_read_state_file = __esm({
|
|
|
53335
53361
|
async readOnce() {
|
|
53336
53362
|
this.checks++;
|
|
53337
53363
|
try {
|
|
53338
|
-
const filePath =
|
|
53364
|
+
const filePath = path51.join(this.home, ".codex-global-state.json");
|
|
53339
53365
|
const file = await open4(filePath, "r");
|
|
53340
53366
|
let raw, signature;
|
|
53341
53367
|
try {
|
|
@@ -55181,9 +55207,9 @@ var init_protocol = __esm({
|
|
|
55181
55207
|
|
|
55182
55208
|
// apps/desktop/src/daemon/server.ts
|
|
55183
55209
|
import { randomUUID as randomUUID37 } from "node:crypto";
|
|
55184
|
-
import
|
|
55210
|
+
import fs38 from "node:fs";
|
|
55185
55211
|
import net5 from "node:net";
|
|
55186
|
-
import
|
|
55212
|
+
import path52 from "node:path";
|
|
55187
55213
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
55188
55214
|
function createStatusFile(instanceId, mode, socketPath) {
|
|
55189
55215
|
return {
|
|
@@ -55318,10 +55344,10 @@ var init_server4 = __esm({
|
|
|
55318
55344
|
DaemonServer = class {
|
|
55319
55345
|
constructor(options) {
|
|
55320
55346
|
this.options = options;
|
|
55321
|
-
this.socketPath =
|
|
55322
|
-
this.statusPath =
|
|
55347
|
+
this.socketPath = path52.resolve(options.socketPath ?? daemonSocketPath());
|
|
55348
|
+
this.statusPath = path52.resolve(options.statusPath ?? daemonStatusPath());
|
|
55323
55349
|
this.usesDefaultRuntimeDir = options.socketPath === void 0 || options.statusPath === void 0;
|
|
55324
|
-
this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() :
|
|
55350
|
+
this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path52.join(path52.dirname(this.socketPath), ".daemon-lifecycle.lock");
|
|
55325
55351
|
this.transport = createDaemonTransport(this.socketPath);
|
|
55326
55352
|
this.listenSocketPath = this.transport.listenPath;
|
|
55327
55353
|
}
|
|
@@ -55433,22 +55459,22 @@ var init_server4 = __esm({
|
|
|
55433
55459
|
const temporaryPath = `${this.statusPath}.${this.instanceId}.tmp`;
|
|
55434
55460
|
let descriptor = null;
|
|
55435
55461
|
try {
|
|
55436
|
-
descriptor =
|
|
55437
|
-
|
|
55462
|
+
descriptor = fs38.openSync(temporaryPath, "wx", 384);
|
|
55463
|
+
fs38.writeFileSync(
|
|
55438
55464
|
descriptor,
|
|
55439
55465
|
`${JSON.stringify(createStatusFile(this.instanceId, this.options.mode ?? "foreground", this.socketPath), null, 2)}
|
|
55440
55466
|
`,
|
|
55441
55467
|
"utf8"
|
|
55442
55468
|
);
|
|
55443
|
-
|
|
55469
|
+
fs38.closeSync(descriptor);
|
|
55444
55470
|
descriptor = null;
|
|
55445
|
-
|
|
55446
|
-
|
|
55471
|
+
fs38.chmodSync(temporaryPath, 384);
|
|
55472
|
+
fs38.renameSync(temporaryPath, this.statusPath);
|
|
55447
55473
|
} catch (error2) {
|
|
55448
55474
|
if (descriptor !== null) {
|
|
55449
|
-
|
|
55475
|
+
fs38.closeSync(descriptor);
|
|
55450
55476
|
}
|
|
55451
|
-
|
|
55477
|
+
fs38.rmSync(temporaryPath, { force: true });
|
|
55452
55478
|
throw error2;
|
|
55453
55479
|
}
|
|
55454
55480
|
}
|
|
@@ -55473,9 +55499,9 @@ var init_server4 = __esm({
|
|
|
55473
55499
|
this.transport.cleanup(this.socketPath);
|
|
55474
55500
|
if (this.statusOwned) {
|
|
55475
55501
|
try {
|
|
55476
|
-
const status2 = JSON.parse(
|
|
55502
|
+
const status2 = JSON.parse(fs38.readFileSync(this.statusPath, "utf8"));
|
|
55477
55503
|
if (status2.instanceId === this.instanceId) {
|
|
55478
|
-
|
|
55504
|
+
fs38.rmSync(this.statusPath, { force: true });
|
|
55479
55505
|
}
|
|
55480
55506
|
} catch {
|
|
55481
55507
|
}
|
|
@@ -56069,7 +56095,7 @@ var init_push_trigger_projection = __esm({
|
|
|
56069
56095
|
});
|
|
56070
56096
|
|
|
56071
56097
|
// apps/desktop/src/daemon/turn-push-audit.ts
|
|
56072
|
-
import
|
|
56098
|
+
import path53 from "node:path";
|
|
56073
56099
|
function isRecord6(value) {
|
|
56074
56100
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56075
56101
|
}
|
|
@@ -56116,7 +56142,7 @@ function isCoverageReason(value) {
|
|
|
56116
56142
|
return value === "realtime_gap" || value === "historical_gap" || value === "source_unavailable" || value === "reader_limit" || value === "write_failed";
|
|
56117
56143
|
}
|
|
56118
56144
|
function auditDirectory(runtimeDir) {
|
|
56119
|
-
return
|
|
56145
|
+
return path53.join(runtimeDir, AUDIT_DIRECTORY);
|
|
56120
56146
|
}
|
|
56121
56147
|
function dateFileName(timestampMs) {
|
|
56122
56148
|
if (!isFiniteTimestamp(timestampMs)) return null;
|
|
@@ -56219,7 +56245,7 @@ function appendRecord(runtimeDir, timestampMs, record26, files) {
|
|
|
56219
56245
|
files.checkDirectory(runtimeDir);
|
|
56220
56246
|
const directory3 = auditDirectory(runtimeDir);
|
|
56221
56247
|
files.ensureDirectory(directory3);
|
|
56222
|
-
files.append(
|
|
56248
|
+
files.append(path53.join(directory3, fileName), `${JSON.stringify(record26)}
|
|
56223
56249
|
`, MAX_FILE_BYTES);
|
|
56224
56250
|
return true;
|
|
56225
56251
|
} catch {
|
|
@@ -57784,11 +57810,11 @@ function completedHistoryItem(value) {
|
|
|
57784
57810
|
break;
|
|
57785
57811
|
case "fileChange":
|
|
57786
57812
|
copy(raw, item, { status: "status" });
|
|
57787
|
-
item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([
|
|
57813
|
+
item.changes = Array.isArray(raw.changes) ? structuredClone(raw.changes) : Object.entries(record5(raw.changes)).map(([path71, value2]) => {
|
|
57788
57814
|
const change = record5(value2);
|
|
57789
57815
|
const kind = { type: change.type };
|
|
57790
57816
|
if (change.type === "update") kind.movePath = change.move_path ?? null;
|
|
57791
|
-
return { path:
|
|
57817
|
+
return { path: path71, kind, diff: change.unified_diff ?? change.content ?? "" };
|
|
57792
57818
|
});
|
|
57793
57819
|
break;
|
|
57794
57820
|
case "collabAgentToolCall":
|
|
@@ -57925,8 +57951,8 @@ function markdownTargets(text11) {
|
|
|
57925
57951
|
function markdownReferences(text11, paths = localResourcePaths) {
|
|
57926
57952
|
const { tree, references } = markdownTargets(text11);
|
|
57927
57953
|
return { tree, references: references.flatMap((ref) => {
|
|
57928
|
-
const
|
|
57929
|
-
return
|
|
57954
|
+
const path71 = paths.parseLink(ref.url);
|
|
57955
|
+
return path71 === null ? [] : [{ ...ref, path: path71 }];
|
|
57930
57956
|
}) };
|
|
57931
57957
|
}
|
|
57932
57958
|
function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths) {
|
|
@@ -57957,8 +57983,8 @@ function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths)
|
|
|
57957
57983
|
if (item.entitiesByKey && typeof item.entitiesByKey === "object") pending.push(...Object.values(item.entitiesByKey));
|
|
57958
57984
|
if (Array.isArray(item.patches)) {
|
|
57959
57985
|
for (const patch of item.patches) {
|
|
57960
|
-
const
|
|
57961
|
-
if (Array.isArray(
|
|
57986
|
+
const path71 = patch?.path;
|
|
57987
|
+
if (Array.isArray(path71) && path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && (path71.length === 4 || path71[4] === "items")) pending.push(patch.value);
|
|
57962
57988
|
}
|
|
57963
57989
|
}
|
|
57964
57990
|
}
|
|
@@ -58159,11 +58185,11 @@ async function readHistoryImageValue(locator, signal, filePath) {
|
|
|
58159
58185
|
signal?.throwIfAborted();
|
|
58160
58186
|
return value;
|
|
58161
58187
|
}
|
|
58162
|
-
async function assertHistoryImageFileReference(locator,
|
|
58163
|
-
const value = await readHistoryImageValue(locator, signal,
|
|
58188
|
+
async function assertHistoryImageFileReference(locator, path71, signal) {
|
|
58189
|
+
const value = await readHistoryImageValue(locator, signal, path71);
|
|
58164
58190
|
const last = locator.valuePath.at(-1);
|
|
58165
58191
|
const text11 = typeof value === "string" ? value : Array.isArray(value) ? value.map((part) => typeof record5(part).text === "string" ? record5(part).text : "").join("") : null;
|
|
58166
|
-
if (text11 === null || !(last === "path" ? text11 ===
|
|
58192
|
+
if (text11 === null || !(last === "path" ? text11 === path71 : assistantPaths(text11).includes(path71))) {
|
|
58167
58193
|
throw new SessionHistoryError("INVALID_RECORD", "\u56FE\u7247\u6587\u4EF6\u4E0E\u5386\u53F2\u5F15\u7528\u4E0D\u7B26");
|
|
58168
58194
|
}
|
|
58169
58195
|
}
|
|
@@ -58222,7 +58248,7 @@ var init_session_history_images = __esm({
|
|
|
58222
58248
|
const found = [];
|
|
58223
58249
|
if (formal && item.type === "agentMessage") {
|
|
58224
58250
|
const references = [];
|
|
58225
|
-
for (const
|
|
58251
|
+
for (const path71 of assistantPaths(String(item.text ?? ""))) {
|
|
58226
58252
|
references.push({ locator: {
|
|
58227
58253
|
threadId: threadId2,
|
|
58228
58254
|
turnId: "",
|
|
@@ -58235,7 +58261,7 @@ var init_session_history_images = __esm({
|
|
|
58235
58261
|
recordLength: range.length,
|
|
58236
58262
|
recordSha256: range.sha256,
|
|
58237
58263
|
valuePath: ["payload", "item", raw.content !== void 0 ? "content" : "text"]
|
|
58238
|
-
}, nativeMessageId: null, path:
|
|
58264
|
+
}, nativeMessageId: null, path: path71, filePath: path71, callId: null });
|
|
58239
58265
|
}
|
|
58240
58266
|
this.markdownEvidence.set(item, references);
|
|
58241
58267
|
}
|
|
@@ -58264,7 +58290,7 @@ var init_session_history_images = __esm({
|
|
|
58264
58290
|
}
|
|
58265
58291
|
if (!imageUrl(source2)) return;
|
|
58266
58292
|
const previous = index > 0 ? record5(parts[index - 1]).text : null;
|
|
58267
|
-
const
|
|
58293
|
+
const path71 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
|
|
58268
58294
|
found.push({
|
|
58269
58295
|
locator: {
|
|
58270
58296
|
threadId: threadId2,
|
|
@@ -58284,7 +58310,7 @@ var init_session_history_images = __esm({
|
|
|
58284
58310
|
]
|
|
58285
58311
|
},
|
|
58286
58312
|
nativeMessageId: typeof item.clientId === "string" ? item.clientId : null,
|
|
58287
|
-
path:
|
|
58313
|
+
path: path71,
|
|
58288
58314
|
callId: null
|
|
58289
58315
|
});
|
|
58290
58316
|
if (mapped[index]) mapped[index] = { type: "historyImage", resourceKey: null };
|
|
@@ -58346,11 +58372,11 @@ var init_session_history_images = __esm({
|
|
|
58346
58372
|
}
|
|
58347
58373
|
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
58348
58374
|
const references = [];
|
|
58349
|
-
for (const [referenceIndex,
|
|
58375
|
+
for (const [referenceIndex, path71] of assistantPaths(item.text).entries()) {
|
|
58350
58376
|
const calls = fallback.filter((candidate) => {
|
|
58351
58377
|
if (candidate.type !== "functionCall" || !["view_image", "functions.view_image"].includes(String(candidate.name))) return false;
|
|
58352
58378
|
try {
|
|
58353
|
-
return record5(JSON.parse(String(candidate.arguments))).path ===
|
|
58379
|
+
return record5(JSON.parse(String(candidate.arguments))).path === path71;
|
|
58354
58380
|
} catch {
|
|
58355
58381
|
return false;
|
|
58356
58382
|
}
|
|
@@ -58358,9 +58384,9 @@ var init_session_history_images = __esm({
|
|
|
58358
58384
|
const outputs = fallback.filter((candidate) => candidate.type === "functionCallOutput" && calls.some((call) => candidate.id === call.id));
|
|
58359
58385
|
const candidates = outputs.flatMap((output) => this.evidence.get(output) ?? []);
|
|
58360
58386
|
if (candidates.length && (calls.length !== 1 || candidates.length !== 1)) continue;
|
|
58361
|
-
const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath ===
|
|
58387
|
+
const original = candidates[0] ?? this.markdownEvidence.get(item)?.find((value) => value.filePath === path71);
|
|
58362
58388
|
if (!original) continue;
|
|
58363
|
-
const evidence = { ...original, path:
|
|
58389
|
+
const evidence = { ...original, path: path71, referenceKind: "markdown", locator: {
|
|
58364
58390
|
...original.locator,
|
|
58365
58391
|
turnId,
|
|
58366
58392
|
itemId: item.id,
|
|
@@ -58368,7 +58394,7 @@ var init_session_history_images = __esm({
|
|
|
58368
58394
|
} };
|
|
58369
58395
|
try {
|
|
58370
58396
|
const resourceKey = await callback(evidence);
|
|
58371
|
-
if (resourceKey) references.push({ path:
|
|
58397
|
+
if (resourceKey) references.push({ path: path71, resourceKey });
|
|
58372
58398
|
} catch {
|
|
58373
58399
|
}
|
|
58374
58400
|
}
|
|
@@ -58387,7 +58413,7 @@ __export(session_history_reader_exports, {
|
|
|
58387
58413
|
SessionHistoryReader: () => SessionHistoryReader
|
|
58388
58414
|
});
|
|
58389
58415
|
import { randomUUID as randomUUID38 } from "node:crypto";
|
|
58390
|
-
import
|
|
58416
|
+
import fs39 from "node:fs/promises";
|
|
58391
58417
|
function resolveHistoryPath(resolvePath, signal) {
|
|
58392
58418
|
abortIfRequested2(signal);
|
|
58393
58419
|
if (!signal) return resolvePath();
|
|
@@ -58655,7 +58681,7 @@ var init_session_history_reader = __esm({
|
|
|
58655
58681
|
try {
|
|
58656
58682
|
const resolved3 = await resolveHistoryPath(() => this.options.resolveSessionPath(snapshot2.threadId), signal);
|
|
58657
58683
|
abortIfRequested2(signal);
|
|
58658
|
-
const current2 = await
|
|
58684
|
+
const current2 = await fs39.realpath(resolved3);
|
|
58659
58685
|
abortIfRequested2(signal);
|
|
58660
58686
|
if (current2 !== snapshot2.files[0].path) throw new Error("current path changed");
|
|
58661
58687
|
} catch (error2) {
|
|
@@ -63502,10 +63528,10 @@ var init_history_snapshot = __esm({
|
|
|
63502
63528
|
const patches = objectRecord3(objectRecord3(objectRecord3(frame).params).change).patches;
|
|
63503
63529
|
const covered = Array.isArray(patches) && patches.every((raw) => {
|
|
63504
63530
|
const patch = objectRecord3(raw);
|
|
63505
|
-
const
|
|
63506
|
-
if (!Array.isArray(
|
|
63507
|
-
if (
|
|
63508
|
-
return
|
|
63531
|
+
const path71 = patch.path;
|
|
63532
|
+
if (!Array.isArray(path71)) return false;
|
|
63533
|
+
if (path71[0] === "requests") return ["add", "replace", "remove"].includes(String(patch.op));
|
|
63534
|
+
return path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && typeof path71[3] === "string" && path71[3].endsWith(`:${recovery.turnId}`) && path71[4] === "items" && (patch.op === "add" && path71.length === 6 || patch.op === "replace" && path71.length === 7 && path71[6] === "text");
|
|
63509
63535
|
});
|
|
63510
63536
|
const bytes3 = Buffer.byteLength(JSON.stringify(acceptedEvents));
|
|
63511
63537
|
if (!covered || recovery.events.length + events.length > 256 || recovery.bytes + bytes3 > 2 * 1024 * 1024) recovery.valid = false;
|
|
@@ -63874,11 +63900,11 @@ var init_app_server_history_window_reader = __esm({
|
|
|
63874
63900
|
const bound = this.turnMetadata.get(turn);
|
|
63875
63901
|
if (!bound) throw new SessionHistoryError("INVALID_CURSOR", "Turn \u4E0D\u5C5E\u4E8E\u5F53\u524D\u5386\u53F2\u5FEB\u7167");
|
|
63876
63902
|
this.assertEvidenceCurrent(bound);
|
|
63877
|
-
const { createdAt, cwd, path:
|
|
63903
|
+
const { createdAt, cwd, path: path71 } = bound.metadata;
|
|
63878
63904
|
return {
|
|
63879
63905
|
nativeOrder: bound.nativeOrder,
|
|
63880
63906
|
sourceRevision: bound.revision,
|
|
63881
|
-
contentVersion: createHash27("sha256").update(JSON.stringify([turn, createdAt, cwd,
|
|
63907
|
+
contentVersion: createHash27("sha256").update(JSON.stringify([turn, createdAt, cwd, path71])).digest("hex")
|
|
63882
63908
|
};
|
|
63883
63909
|
}
|
|
63884
63910
|
/** 撤销正文提交资格,保留逻辑边界供下次原生读取重新证明。 */
|
|
@@ -66386,7 +66412,7 @@ var init_thread_history_window_projection = __esm({
|
|
|
66386
66412
|
pending: null,
|
|
66387
66413
|
activity: null,
|
|
66388
66414
|
lastError: null,
|
|
66389
|
-
resolveKnownLocalImage: (
|
|
66415
|
+
resolveKnownLocalImage: (path71, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path71, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path71) ?? null : null),
|
|
66390
66416
|
onHistoryItemProjected: (item, normalized) => timeline.push({ id: item.id, timeline: normalized })
|
|
66391
66417
|
}, "history_only");
|
|
66392
66418
|
const items = [...event.baseline.committed_items, ...event.baseline.active_turn?.items ?? []];
|
|
@@ -67260,8 +67286,8 @@ function unreadFrameDiagnostic(frame) {
|
|
|
67260
67286
|
let countValue = values.unreadMessageCount;
|
|
67261
67287
|
if (kind === "patch") {
|
|
67262
67288
|
for (const value of Array.isArray(change.patches) ? change.patches : []) {
|
|
67263
|
-
const patch = object10(value),
|
|
67264
|
-
const name2 =
|
|
67289
|
+
const patch = object10(value), path71 = Array.isArray(patch.path) ? patch.path : [];
|
|
67290
|
+
const name2 = path71.length === 1 ? path71[0] : path71.length === 2 && path71[0] === "conversationState" ? path71[1] : null;
|
|
67265
67291
|
if (name2 !== "hasUnreadTurn" && name2 !== "unreadMessageCount") continue;
|
|
67266
67292
|
const state = patch.op === "remove" ? "removed" : ["add", "replace"].includes(String(patch.op)) ? field(patch.value, Object.hasOwn(patch, "value"), name2 === "unreadMessageCount") : "invalid";
|
|
67267
67293
|
if (name2 === "hasUnreadTurn") unread = state;
|
|
@@ -69265,9 +69291,9 @@ function assertFile(stat4) {
|
|
|
69265
69291
|
if (!stat4.isFile() || stat4.nlink !== 1n) throw missing2();
|
|
69266
69292
|
if (stat4.size > BigInt(MAX_BYTES6)) throw limited();
|
|
69267
69293
|
}
|
|
69268
|
-
async function captureDirectoryChain(snapshot2,
|
|
69294
|
+
async function captureDirectoryChain(snapshot2, path71, signal) {
|
|
69269
69295
|
const paths = /* @__PURE__ */ new Set();
|
|
69270
|
-
for (const start of [dirname2(
|
|
69296
|
+
for (const start of [dirname2(path71)]) {
|
|
69271
69297
|
for (let current2 = start; ; current2 = dirname2(current2)) {
|
|
69272
69298
|
paths.add(current2);
|
|
69273
69299
|
if (paths.size > MAX_DIRECTORY_ENTRIES2) throw limited();
|
|
@@ -69397,9 +69423,9 @@ var init_file_resources = __esm({
|
|
|
69397
69423
|
trim() {
|
|
69398
69424
|
while (this.entries.size > MAX_ENTRIES3 || this.indexBytes > MAX_INDEX_BYTES) this.remove(this.entries.values().next().value);
|
|
69399
69425
|
}
|
|
69400
|
-
assertTarget(entry,
|
|
69426
|
+
assertTarget(entry, path71, signal, isCurrent) {
|
|
69401
69427
|
this.assertVisible(entry, signal, isCurrent);
|
|
69402
|
-
if (entry.targetRealPath !== void 0 && entry.targetRealPath !==
|
|
69428
|
+
if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path71) {
|
|
69403
69429
|
this.remove(entry);
|
|
69404
69430
|
this.options.onReferenceRetired?.({ ...entry.reference, attachmentId: entry.attachmentId });
|
|
69405
69431
|
throw changed();
|
|
@@ -69441,17 +69467,17 @@ var init_file_resources = __esm({
|
|
|
69441
69467
|
if (request2 && (!expected || expected.sha256 !== request2.sha256)) throw changed();
|
|
69442
69468
|
const directories2 = { entries: /* @__PURE__ */ new Map(), bytes: 0 };
|
|
69443
69469
|
await captureDirectoryChain(directories2, entry.reference.path, combined);
|
|
69444
|
-
const
|
|
69470
|
+
const path71 = await realpath2(entry.reference.path);
|
|
69445
69471
|
combined.throwIfAborted();
|
|
69446
|
-
this.assertTarget(entry,
|
|
69447
|
-
await captureDirectoryChain(directories2,
|
|
69448
|
-
const pathBefore = await lstat4(
|
|
69472
|
+
this.assertTarget(entry, path71, combined, isCurrent);
|
|
69473
|
+
await captureDirectoryChain(directories2, path71, combined);
|
|
69474
|
+
const pathBefore = await lstat4(path71, { bigint: true });
|
|
69449
69475
|
assertFile(pathBefore);
|
|
69450
|
-
handle = await open5(
|
|
69476
|
+
handle = await open5(path71, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
69451
69477
|
const before = await handle.stat({ bigint: true });
|
|
69452
69478
|
assertFile(before);
|
|
69453
69479
|
if (identity5(before) !== identity5(pathBefore)) throw changed();
|
|
69454
|
-
const fileIdentity2 = `${
|
|
69480
|
+
const fileIdentity2 = `${path71}\0${identity5(before)}`;
|
|
69455
69481
|
if (request2 && expected.identity !== fileIdentity2) throw changed();
|
|
69456
69482
|
const byteSize2 = Number(before.size);
|
|
69457
69483
|
const chunkCount = Math.ceil(byteSize2 / CHUNK_BYTES);
|
|
@@ -69477,7 +69503,7 @@ var init_file_resources = __esm({
|
|
|
69477
69503
|
const pathAfter = await realpath2(entry.reference.path);
|
|
69478
69504
|
const current2 = await lstat4(pathAfter, { bigint: true });
|
|
69479
69505
|
this.assertTarget(entry, pathAfter, combined, isCurrent);
|
|
69480
|
-
if (pathAfter !==
|
|
69506
|
+
if (pathAfter !== path71 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
|
|
69481
69507
|
const sha2562 = hash3.digest("hex");
|
|
69482
69508
|
if (request2 && sha2562 !== request2.sha256) throw changed();
|
|
69483
69509
|
await handle.close();
|
|
@@ -69493,8 +69519,8 @@ var init_file_resources = __esm({
|
|
|
69493
69519
|
chunkBytes: CHUNK_BYTES,
|
|
69494
69520
|
chunkCount
|
|
69495
69521
|
};
|
|
69496
|
-
this.assertTarget(entry,
|
|
69497
|
-
return { entry, path:
|
|
69522
|
+
this.assertTarget(entry, path71, combined, isCurrent);
|
|
69523
|
+
return { entry, path: path71, info, identity: fileIdentity2, chunk, signal: combined };
|
|
69498
69524
|
} catch (error2) {
|
|
69499
69525
|
combined.throwIfAborted();
|
|
69500
69526
|
if (error2 instanceof NiumaError) throw error2;
|
|
@@ -69526,16 +69552,16 @@ function revisionOf2(value) {
|
|
|
69526
69552
|
function occurredAt3() {
|
|
69527
69553
|
return Math.floor(Date.now() / 1e3);
|
|
69528
69554
|
}
|
|
69529
|
-
function isThreadSettingsPatch(
|
|
69530
|
-
const field2 =
|
|
69555
|
+
function isThreadSettingsPatch(path71) {
|
|
69556
|
+
const field2 = path71.at(-1);
|
|
69531
69557
|
if (typeof field2 !== "string" || !SETTING_FIELD_ALIASES.has(field2)) {
|
|
69532
69558
|
return false;
|
|
69533
69559
|
}
|
|
69534
|
-
return
|
|
69560
|
+
return path71.length === 1 || typeof path71.at(-2) === "string" && SETTINGS_CONTAINERS.has(path71.at(-2));
|
|
69535
69561
|
}
|
|
69536
|
-
function isCurrentPermissionsPatch(
|
|
69537
|
-
const field2 =
|
|
69538
|
-
return
|
|
69562
|
+
function isCurrentPermissionsPatch(path71) {
|
|
69563
|
+
const field2 = path71.at(-1);
|
|
69564
|
+
return path71.length === 2 && path71[0] === CURRENT_PERMISSIONS_CONTAINER && typeof field2 === "string" && CURRENT_PERMISSION_FIELD_ALIASES.has(field2);
|
|
69539
69565
|
}
|
|
69540
69566
|
function hasOwn(value, field2) {
|
|
69541
69567
|
return Object.prototype.hasOwnProperty.call(value, field2);
|
|
@@ -69614,20 +69640,20 @@ function currentPermissionsFromRecord(value) {
|
|
|
69614
69640
|
return settings;
|
|
69615
69641
|
}
|
|
69616
69642
|
function settingsFromPatch(patch) {
|
|
69617
|
-
const
|
|
69618
|
-
if (
|
|
69643
|
+
const path71 = array6(patch.path);
|
|
69644
|
+
if (path71.length === 1 && typeof path71[0] === "string" && SETTINGS_CONTAINERS.has(path71[0])) {
|
|
69619
69645
|
return settingsFromRecord(patch.value, BASE_SETTING_FIELDS);
|
|
69620
69646
|
}
|
|
69621
|
-
if (
|
|
69647
|
+
if (path71.length === 1 && path71[0] === CURRENT_PERMISSIONS_CONTAINER) {
|
|
69622
69648
|
return currentPermissionsFromRecord(patch.value);
|
|
69623
69649
|
}
|
|
69624
|
-
const field2 =
|
|
69650
|
+
const field2 = path71.at(-1);
|
|
69625
69651
|
const settings = {};
|
|
69626
|
-
if (typeof field2 === "string" && isCurrentPermissionsPatch(
|
|
69652
|
+
if (typeof field2 === "string" && isCurrentPermissionsPatch(path71)) {
|
|
69627
69653
|
assignCurrentPermission(settings, field2, patch.value);
|
|
69628
69654
|
return settings;
|
|
69629
69655
|
}
|
|
69630
|
-
if (typeof field2 === "string" && isThreadSettingsPatch(
|
|
69656
|
+
if (typeof field2 === "string" && isThreadSettingsPatch(path71)) {
|
|
69631
69657
|
assignSetting(settings, field2, patch.value);
|
|
69632
69658
|
}
|
|
69633
69659
|
return settings;
|
|
@@ -73045,8 +73071,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73045
73071
|
if (change.type !== "patches" || next === null || previous === void 0 || next <= previous) return [];
|
|
73046
73072
|
const patches = array7(change.patches);
|
|
73047
73073
|
const unknownMembership = patches.some((value) => {
|
|
73048
|
-
const p = record25(value),
|
|
73049
|
-
return
|
|
73074
|
+
const p = record25(value), path71 = array7(p.path);
|
|
73075
|
+
return path71[0] === "turnHistory" && (path71.length < 3 || path71[1] === "history" && (path71[2] === "entitiesByKey" && (path71.length < 4 || path71.length > 4 && ["id", "turnId", "params"].includes(String(path71[4])))));
|
|
73050
73076
|
});
|
|
73051
73077
|
if (next !== previous + 1 || unknownMembership) {
|
|
73052
73078
|
this.idleHistoryBaselines.delete(context.threadId);
|
|
@@ -73056,9 +73082,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73056
73082
|
const mapped = new Map(this.entityTurnIdsByThread.get(context.threadId));
|
|
73057
73083
|
const candidates = /* @__PURE__ */ new Set();
|
|
73058
73084
|
for (const value of patches) {
|
|
73059
|
-
const p = record25(value),
|
|
73060
|
-
if (p.op === "remove" &&
|
|
73061
|
-
const id5 = mapped.get(String(
|
|
73085
|
+
const p = record25(value), path71 = array7(p.path);
|
|
73086
|
+
if (p.op === "remove" && path71.length === 4 && path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey") {
|
|
73087
|
+
const id5 = mapped.get(String(path71[3]));
|
|
73062
73088
|
if (id5) candidates.add(id5);
|
|
73063
73089
|
}
|
|
73064
73090
|
}
|
|
@@ -73069,9 +73095,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73069
73095
|
})).value;
|
|
73070
73096
|
const canDelete = typeof newGeneration === "number" && Number.isSafeInteger(newGeneration) && oldGeneration !== void 0 && newGeneration > oldGeneration;
|
|
73071
73097
|
for (const value of patches) {
|
|
73072
|
-
const p = record25(value),
|
|
73073
|
-
if (
|
|
73074
|
-
const key = String(
|
|
73098
|
+
const p = record25(value), path71 = array7(p.path), entity = record25(p.value);
|
|
73099
|
+
if (path71.length !== 4 || path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey") continue;
|
|
73100
|
+
const key = String(path71[3]);
|
|
73075
73101
|
if (p.op === "remove") mapped.delete(key);
|
|
73076
73102
|
else if (p.op === "add" || p.op === "replace") {
|
|
73077
73103
|
const id5 = nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? nonEmptyString14(record25(entity.params).turnId);
|
|
@@ -73197,8 +73223,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73197
73223
|
const change = record25(record25(frame.params).change);
|
|
73198
73224
|
for (const rawPatch of array7(change.patches)) {
|
|
73199
73225
|
const patch = record25(rawPatch);
|
|
73200
|
-
const
|
|
73201
|
-
if ((patch.op === "add" || patch.op === "replace") && (
|
|
73226
|
+
const path71 = array7(patch.path);
|
|
73227
|
+
if ((patch.op === "add" || patch.op === "replace") && (path71.length === 1 && path71[0] === "recencyAt" || path71.length === 2 && path71[0] === "conversationState" && path71[1] === "recencyAt")) {
|
|
73202
73228
|
this.rememberSidebarRecency(context.threadId, patch.value);
|
|
73203
73229
|
}
|
|
73204
73230
|
}
|
|
@@ -73284,12 +73310,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73284
73310
|
requests = structuredClone(requests);
|
|
73285
73311
|
for (const value of array7(change.patches)) {
|
|
73286
73312
|
const patch = record25(value);
|
|
73287
|
-
const
|
|
73288
|
-
if (
|
|
73289
|
-
if (
|
|
73313
|
+
const path71 = array7(patch.path);
|
|
73314
|
+
if (path71[0] !== "requests") continue;
|
|
73315
|
+
if (path71.length === 1) {
|
|
73290
73316
|
requests = patch.op === "remove" ? [] : structuredClone(array7(patch.value));
|
|
73291
|
-
} else if (
|
|
73292
|
-
const index =
|
|
73317
|
+
} else if (path71.length === 2) {
|
|
73318
|
+
const index = path71[1] === "-" ? requests.length : Number(path71[1]);
|
|
73293
73319
|
if (!Number.isInteger(index) || index < 0 || index > requests.length) continue;
|
|
73294
73320
|
if (patch.op === "remove") requests.splice(index, 1);
|
|
73295
73321
|
else if (patch.op === "add") requests.splice(index, 0, structuredClone(patch.value));
|
|
@@ -73368,19 +73394,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73368
73394
|
}
|
|
73369
73395
|
/** 深层 content 只有局部形状,须等待完整项/快照重新证明;text 更新不能洗掉未知内容。 */
|
|
73370
73396
|
invalidateReadPatch(patch, context) {
|
|
73371
|
-
const
|
|
73372
|
-
if (
|
|
73373
|
-
const turnId = typeof
|
|
73374
|
-
if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (
|
|
73397
|
+
const path71 = array7(patch.path);
|
|
73398
|
+
if (path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey") return;
|
|
73399
|
+
const turnId = typeof path71[3] === "string" ? this.entityTurnIdsByThread.get(context.threadId)?.get(path71[3]) : null;
|
|
73400
|
+
if (turnId && turnId === this.readTurnByThread.get(context.threadId) && this.activeTurnByThread.get(context.threadId) !== turnId && (path71[4] === "items" || path71.length === 4 && hasOwn2(record25(patch.value), "items"))) {
|
|
73375
73401
|
for (const identity7 of this.nativeReadIdentities.get(context.threadId)?.values() ?? []) {
|
|
73376
73402
|
if (identity7.turnId === turnId) identity7.complete = false;
|
|
73377
73403
|
}
|
|
73378
73404
|
return;
|
|
73379
73405
|
}
|
|
73380
|
-
if (
|
|
73406
|
+
if (path71[4] !== "items" || path71[6] !== "content") return;
|
|
73381
73407
|
const order = this.itemOrders.get(context.threadId);
|
|
73382
|
-
if (!order || order.entityKey !==
|
|
73383
|
-
const id5 = typeof
|
|
73408
|
+
if (!order || order.entityKey !== path71[3]) return;
|
|
73409
|
+
const id5 = typeof path71[5] === "number" ? order.ids[path71[5]] : null;
|
|
73384
73410
|
const identity6 = id5 ? this.nativeReadIdentities.get(context.threadId)?.get(id5) : null;
|
|
73385
73411
|
if (identity6) identity6.complete = false;
|
|
73386
73412
|
else if (!id5) {
|
|
@@ -73404,19 +73430,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73404
73430
|
/** 在同一 Store 事务内先更新正文,再发布可信顺序,不让 Web 看见暂存的中间帧。 */
|
|
73405
73431
|
itemOrderEvents(patch, itemEvents, context) {
|
|
73406
73432
|
if (this.itemOrderGaps.has(context.threadId)) return [];
|
|
73407
|
-
const
|
|
73408
|
-
if (
|
|
73433
|
+
const path71 = array7(patch.path);
|
|
73434
|
+
if (path71[0] !== "turnHistory") return [];
|
|
73409
73435
|
const invalidate = () => {
|
|
73410
73436
|
this.itemOrders.delete(context.threadId);
|
|
73411
73437
|
this.itemOrderGaps.add(context.threadId);
|
|
73412
73438
|
return [];
|
|
73413
73439
|
};
|
|
73414
|
-
if (
|
|
73415
|
-
if (
|
|
73416
|
-
if (
|
|
73440
|
+
if (path71.length < 3) return invalidate();
|
|
73441
|
+
if (path71[1] !== "history" || path71[2] !== "entitiesByKey") return [];
|
|
73442
|
+
if (path71.length < 4) return invalidate();
|
|
73417
73443
|
const activeId = this.activeTurnByThread.get(context.threadId);
|
|
73418
73444
|
if (!activeId) return [];
|
|
73419
|
-
const entityKey = String(
|
|
73445
|
+
const entityKey = String(path71[3]);
|
|
73420
73446
|
const events = [];
|
|
73421
73447
|
const emitItem = (value) => {
|
|
73422
73448
|
const item = this.orderedRawItem(value, activeId, context);
|
|
@@ -73433,8 +73459,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73433
73459
|
return item?.id ?? null;
|
|
73434
73460
|
};
|
|
73435
73461
|
let order = this.itemOrders.get(context.threadId);
|
|
73436
|
-
const wholeEntity =
|
|
73437
|
-
const wholeArray =
|
|
73462
|
+
const wholeEntity = path71.length === 4;
|
|
73463
|
+
const wholeArray = path71.length === 5 && path71[4] === "items";
|
|
73438
73464
|
if (wholeEntity || wholeArray) {
|
|
73439
73465
|
const entity = record25(patch.value);
|
|
73440
73466
|
const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) : this.entityTurnIdsByThread.get(context.threadId)?.get(entityKey);
|
|
@@ -73450,12 +73476,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73450
73476
|
}
|
|
73451
73477
|
values.forEach(emitItem);
|
|
73452
73478
|
} else {
|
|
73453
|
-
if (!order || order.turnId !== activeId || order.entityKey !== entityKey ||
|
|
73454
|
-
if (
|
|
73455
|
-
return ["id", "type"].includes(String(
|
|
73479
|
+
if (!order || order.turnId !== activeId || order.entityKey !== entityKey || path71[4] !== "items") return [];
|
|
73480
|
+
if (path71.length > 6) {
|
|
73481
|
+
return ["id", "type"].includes(String(path71[6])) ? invalidate() : [];
|
|
73456
73482
|
}
|
|
73457
|
-
if (
|
|
73458
|
-
const index =
|
|
73483
|
+
if (path71.length !== 6 || !["add", "replace", "remove"].includes(String(patch.op))) return invalidate();
|
|
73484
|
+
const index = path71[5] === "-" && patch.op === "add" ? order.ids.length : path71[5];
|
|
73459
73485
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0 || index > order.ids.length || patch.op !== "add" && index === order.ids.length) return invalidate();
|
|
73460
73486
|
if (patch.op === "add" && order.ids.length >= 8192) return invalidate();
|
|
73461
73487
|
const previousId = order.ids[index];
|
|
@@ -73676,12 +73702,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73676
73702
|
for (const patchValue of patches) {
|
|
73677
73703
|
const patch = record25(patchValue);
|
|
73678
73704
|
if (patch.op !== "add" && patch.op !== "replace") continue;
|
|
73679
|
-
const
|
|
73680
|
-
if (
|
|
73681
|
-
const entityKey =
|
|
73682
|
-
const wholeEntity =
|
|
73683
|
-
const statusField =
|
|
73684
|
-
const startField =
|
|
73705
|
+
const path71 = array7(patch.path);
|
|
73706
|
+
if (path71[0] !== "turnHistory" || path71[1] !== "history" || path71[2] !== "entitiesByKey" || typeof path71[3] !== "string") continue;
|
|
73707
|
+
const entityKey = path71[3];
|
|
73708
|
+
const wholeEntity = path71.length === 4;
|
|
73709
|
+
const statusField = path71.length === 5 && path71[4] === "status";
|
|
73710
|
+
const startField = path71.length === 5 && path71[4] === "turnStartedAtMs";
|
|
73685
73711
|
if (!wholeEntity && !statusField && !startField) continue;
|
|
73686
73712
|
const entity = wholeEntity ? record25(patch.value) : {};
|
|
73687
73713
|
const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? entityTurnIds.get(entityKey) ?? null : entityTurnIds.get(entityKey) ?? null;
|
|
@@ -73886,12 +73912,12 @@ function normalizeFileCitations(text11, paths) {
|
|
|
73886
73912
|
const end = start + match[0].length;
|
|
73887
73913
|
if (!textRanges.some(([a, b]) => a <= start && start < b) || excluded.some(([a, b]) => a < end && b > start)) continue;
|
|
73888
73914
|
const slashes = text11.slice(0, start).match(/\\*$/u)?.[0].length ?? 0;
|
|
73889
|
-
const
|
|
73890
|
-
if (slashes % 2 || paths.parseLocal(
|
|
73915
|
+
const path71 = match[1];
|
|
73916
|
+
if (slashes % 2 || paths.parseLocal(path71) === null) continue;
|
|
73891
73917
|
try {
|
|
73892
|
-
const target = paths.toLink(
|
|
73918
|
+
const target = paths.toLink(path71);
|
|
73893
73919
|
if (target === null) continue;
|
|
73894
|
-
const label2 = fallbackFileName(
|
|
73920
|
+
const label2 = fallbackFileName(path71, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
|
|
73895
73921
|
edits.push({ start, end, value: `[${label2}](<${target}>)` });
|
|
73896
73922
|
} catch {
|
|
73897
73923
|
}
|
|
@@ -73909,9 +73935,9 @@ function fileReferences(text11, paths) {
|
|
|
73909
73935
|
return markdownTargets(text11).references.filter((ref) => !ref.image).flatMap((ref) => {
|
|
73910
73936
|
try {
|
|
73911
73937
|
const target = withoutFileLocation(ref.url);
|
|
73912
|
-
const
|
|
73913
|
-
if (
|
|
73914
|
-
return [{ ...ref, path:
|
|
73938
|
+
const path71 = paths.parseLink(target);
|
|
73939
|
+
if (path71 === null) return [];
|
|
73940
|
+
return [{ ...ref, path: path71 }];
|
|
73915
73941
|
} catch {
|
|
73916
73942
|
return [];
|
|
73917
73943
|
}
|
|
@@ -73921,8 +73947,8 @@ function collectFileLinkPaths(item, paths = localResourcePaths) {
|
|
|
73921
73947
|
if (item.type !== "assistant_message") return [];
|
|
73922
73948
|
return [...new Set(item.content.flatMap((part) => part.type === "text" ? fileReferences(normalizeFileCitations(part.text, paths), paths).map((ref) => ref.path) : []))];
|
|
73923
73949
|
}
|
|
73924
|
-
function fallbackFileName(
|
|
73925
|
-
const name2 = paths.basename(
|
|
73950
|
+
function fallbackFileName(path71, paths) {
|
|
73951
|
+
const name2 = paths.basename(path71).slice(0, 255);
|
|
73926
73952
|
return name2.trim() && !/[\\/\x00-\x1f\x7f-\x9f]/u.test(name2) ? name2 : "\u6587\u4EF6";
|
|
73927
73953
|
}
|
|
73928
73954
|
function projectFileLinks(item, register, isRegistered = () => true, paths = localResourcePaths) {
|
|
@@ -73986,7 +74012,7 @@ var init_thread_view_files = __esm({
|
|
|
73986
74012
|
|
|
73987
74013
|
// apps/desktop/src/daemon/runtime/projection.ts
|
|
73988
74014
|
import { createHash as createHash36 } from "node:crypto";
|
|
73989
|
-
import
|
|
74015
|
+
import path54 from "node:path";
|
|
73990
74016
|
var FILE_REFRESH_MAX_ENTRIES, FILE_REFRESH_MAX_BYTES, FILE_REFRESH_ENTRY_BYTES, FILE_REFRESH_IN_FLIGHT_RESERVE, RuntimeProjection;
|
|
73991
74017
|
var init_projection2 = __esm({
|
|
73992
74018
|
"apps/desktop/src/daemon/runtime/projection.ts"() {
|
|
@@ -74118,14 +74144,14 @@ var init_projection2 = __esm({
|
|
|
74118
74144
|
isFileReferenceVisible(entry) {
|
|
74119
74145
|
if (this.ports.stopping()) return false;
|
|
74120
74146
|
const root = this.ports.projectRoot(entry.threadId);
|
|
74121
|
-
if (!root ||
|
|
74147
|
+
if (!root || path54.resolve(root) !== entry.root) return false;
|
|
74122
74148
|
const item = this.store.getProjectionItem(entry.threadId, entry.itemId);
|
|
74123
74149
|
if (!item) return false;
|
|
74124
74150
|
if (item.type === "user_message") {
|
|
74125
|
-
return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" &&
|
|
74151
|
+
return this.store.nativeFileSources(entry.threadId, entry.itemId).some((source2) => item.content[source2.index]?.type === "file" && path54.resolve(source2.path) === entry.path);
|
|
74126
74152
|
}
|
|
74127
74153
|
if (item.type !== "assistant_message") return false;
|
|
74128
|
-
if (collectFileLinkPaths(item).some((sourcePath) =>
|
|
74154
|
+
if (collectFileLinkPaths(item).some((sourcePath) => path54.resolve(sourcePath) === entry.path)) return true;
|
|
74129
74155
|
return item.content.some((part) => part.type === "file" && part.attachment_id === entry.attachmentId) && hasFileAttachmentLink(item, entry.attachmentId);
|
|
74130
74156
|
}
|
|
74131
74157
|
subagentAvatars = new CodexSubagentAvatars();
|
|
@@ -75663,8 +75689,8 @@ var init_read_receipts = __esm({
|
|
|
75663
75689
|
return;
|
|
75664
75690
|
}
|
|
75665
75691
|
const statusOnly = change.type === "patches" && Array.isArray(change.patches) && change.patches.length > 0 && change.patches.every((value) => {
|
|
75666
|
-
const patch = objectRecord3(value),
|
|
75667
|
-
const fields3 =
|
|
75692
|
+
const patch = objectRecord3(value), path71 = Array.isArray(patch.path) ? patch.path : [];
|
|
75693
|
+
const fields3 = path71[0] === "conversationState" ? path71.slice(1) : path71;
|
|
75668
75694
|
if (!["add", "replace", "remove"].includes(String(patch.op)) || fields3.length !== 1) return false;
|
|
75669
75695
|
if (fields3[0] === "threadRuntimeStatus") return true;
|
|
75670
75696
|
return patch.op !== "remove" && (fields3[0] === "hasUnreadTurn" && patch.value === raw?.hasUnreadTurn || fields3[0] === "unreadMessageCount" && patch.value === raw?.unreadMessageCount);
|
|
@@ -77939,7 +77965,7 @@ var init_image_decoder = __esm({
|
|
|
77939
77965
|
});
|
|
77940
77966
|
|
|
77941
77967
|
// apps/desktop/src/attachments/image-assets.ts
|
|
77942
|
-
import
|
|
77968
|
+
import path55 from "node:path";
|
|
77943
77969
|
function names(id5) {
|
|
77944
77970
|
if (!idPattern.test(id5)) throw unavailable9();
|
|
77945
77971
|
return { metadata: `img_${id5.slice(4)}`, source: `src_${id5.slice(4)}`, preview: `prv_${id5.slice(4)}` };
|
|
@@ -77986,7 +78012,7 @@ var init_image_assets = __esm({
|
|
|
77986
78012
|
}
|
|
77987
78013
|
paths(id5) {
|
|
77988
78014
|
const n = names(id5);
|
|
77989
|
-
return { sourcePath:
|
|
78015
|
+
return { sourcePath: path55.join(this.root, n.source, "source"), previewPath: path55.join(this.root, n.preview, "source") };
|
|
77990
78016
|
}
|
|
77991
78017
|
asset(id5) {
|
|
77992
78018
|
const value = this.assets.get(id5);
|
|
@@ -78118,7 +78144,7 @@ import { constants as constants5 } from "node:fs";
|
|
|
78118
78144
|
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir2, open as open6 } from "node:fs/promises";
|
|
78119
78145
|
import { execFile as execFile13 } from "node:child_process";
|
|
78120
78146
|
import { promisify as promisify6 } from "node:util";
|
|
78121
|
-
import
|
|
78147
|
+
import path56 from "node:path";
|
|
78122
78148
|
async function preparePrivateImageRoot(directory3) {
|
|
78123
78149
|
if (process.platform === "win32") {
|
|
78124
78150
|
await ensureWindowsPrivateDirectoryAsync(directory3);
|
|
@@ -78134,7 +78160,7 @@ async function createPrivateImageDirectory(directory3) {
|
|
|
78134
78160
|
return;
|
|
78135
78161
|
}
|
|
78136
78162
|
directory3 = localWindowsPath(directory3);
|
|
78137
|
-
const parent = await openPrivateImageDirectory(
|
|
78163
|
+
const parent = await openPrivateImageDirectory(path56.dirname(directory3));
|
|
78138
78164
|
try {
|
|
78139
78165
|
await parent.verify();
|
|
78140
78166
|
await mkdir2(directory3, { mode: 448 });
|
|
@@ -78157,7 +78183,7 @@ Check-PrivateDirectory $env:NIUMA_IMAGE_DIRECTORY
|
|
|
78157
78183
|
}
|
|
78158
78184
|
async function openPrivateImageDirectory(requested, openFile2 = open6) {
|
|
78159
78185
|
const windows2 = process.platform === "win32";
|
|
78160
|
-
const directory3 = windows2 ? localWindowsPath(requested) :
|
|
78186
|
+
const directory3 = windows2 ? localWindowsPath(requested) : path56.resolve(requested);
|
|
78161
78187
|
const initial = await lstat5(directory3, { bigint: true });
|
|
78162
78188
|
if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable10();
|
|
78163
78189
|
let handle;
|
|
@@ -78266,7 +78292,7 @@ var init_private_image_files = __esm({
|
|
|
78266
78292
|
// apps/desktop/src/platform/private-image-commit.ts
|
|
78267
78293
|
import { randomUUID as randomUUID50 } from "node:crypto";
|
|
78268
78294
|
import { lstat as lstat6, rename as rename2, rm as rm2 } from "node:fs/promises";
|
|
78269
|
-
import
|
|
78295
|
+
import path57 from "node:path";
|
|
78270
78296
|
async function snapshot(file, maxBytes) {
|
|
78271
78297
|
try {
|
|
78272
78298
|
await lstat6(file);
|
|
@@ -78331,7 +78357,7 @@ var init_private_image_commit = __esm({
|
|
|
78331
78357
|
await this.writeBinary(file, bytes3, maxBytes);
|
|
78332
78358
|
return;
|
|
78333
78359
|
}
|
|
78334
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78360
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78335
78361
|
try {
|
|
78336
78362
|
const handle = await privateBinaryFiles.open(file, { maxBytes, writable: true, mode: "mutable" });
|
|
78337
78363
|
try {
|
|
@@ -78366,7 +78392,7 @@ var init_private_image_commit = __esm({
|
|
|
78366
78392
|
}
|
|
78367
78393
|
},
|
|
78368
78394
|
async writeBinary(file, bytes3, maxBytes) {
|
|
78369
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78395
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78370
78396
|
try {
|
|
78371
78397
|
await directory3.verify();
|
|
78372
78398
|
await writeNew(file, bytes3, maxBytes);
|
|
@@ -78379,8 +78405,8 @@ var init_private_image_commit = __esm({
|
|
|
78379
78405
|
const bytes3 = Buffer.from(input);
|
|
78380
78406
|
let published = false, renameAttempted = false;
|
|
78381
78407
|
let temporaryIdentity;
|
|
78382
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78383
|
-
const temporary =
|
|
78408
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78409
|
+
const temporary = path57.join(path57.dirname(file), `.manifest-${randomUUID50()}.tmp`);
|
|
78384
78410
|
try {
|
|
78385
78411
|
if (bytes3.length > maxBytes) throw new PrivateImageCommitError();
|
|
78386
78412
|
new TextDecoder("utf-8", { fatal: true }).decode(bytes3);
|
|
@@ -78428,14 +78454,14 @@ var init_private_image_commit = __esm({
|
|
|
78428
78454
|
});
|
|
78429
78455
|
|
|
78430
78456
|
// apps/desktop/src/platform/private-document-directory.ts
|
|
78431
|
-
import
|
|
78432
|
-
import
|
|
78457
|
+
import fs40 from "node:fs";
|
|
78458
|
+
import path58 from "node:path";
|
|
78433
78459
|
async function openPrivateDocumentDirectory(root) {
|
|
78434
|
-
const directory3 =
|
|
78460
|
+
const directory3 = path58.resolve(root);
|
|
78435
78461
|
let identity6;
|
|
78436
78462
|
try {
|
|
78437
78463
|
privateLogFiles.ensureDirectory(directory3);
|
|
78438
|
-
identity6 =
|
|
78464
|
+
identity6 = fs40.lstatSync(directory3, { bigint: true });
|
|
78439
78465
|
privateLogFiles.checkDirectory(directory3);
|
|
78440
78466
|
guard();
|
|
78441
78467
|
} catch {
|
|
@@ -78443,7 +78469,7 @@ async function openPrivateDocumentDirectory(root) {
|
|
|
78443
78469
|
}
|
|
78444
78470
|
function guard() {
|
|
78445
78471
|
try {
|
|
78446
|
-
const current2 =
|
|
78472
|
+
const current2 = fs40.lstatSync(directory3, { bigint: true });
|
|
78447
78473
|
if (!current2.isDirectory() || current2.isSymbolicLink() || current2.dev !== identity6.dev || current2.ino !== identity6.ino) {
|
|
78448
78474
|
throw new PrivateDocumentFileError("unavailable");
|
|
78449
78475
|
}
|
|
@@ -78456,7 +78482,7 @@ async function openPrivateDocumentDirectory(root) {
|
|
|
78456
78482
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(name2) || name2 === "." || name2 === "..") {
|
|
78457
78483
|
throw new PrivateDocumentFileError("unavailable");
|
|
78458
78484
|
}
|
|
78459
|
-
return
|
|
78485
|
+
return path58.join(directory3, name2);
|
|
78460
78486
|
}
|
|
78461
78487
|
const files = privateStateFilesWithGuard(guard);
|
|
78462
78488
|
return {
|
|
@@ -78540,36 +78566,36 @@ function decodeBase64(value) {
|
|
|
78540
78566
|
function sha256(value) {
|
|
78541
78567
|
return createHash39("sha256").update(value).digest("hex");
|
|
78542
78568
|
}
|
|
78543
|
-
async function readJsonManifest(
|
|
78569
|
+
async function readJsonManifest(path71, io) {
|
|
78544
78570
|
try {
|
|
78545
78571
|
if (io.controlledFiles) {
|
|
78546
|
-
const { data } = await io.controlledFiles.read(
|
|
78572
|
+
const { data } = await io.controlledFiles.read(path71);
|
|
78547
78573
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(data));
|
|
78548
78574
|
}
|
|
78549
|
-
const status2 = await lstat7(
|
|
78575
|
+
const status2 = await lstat7(path71);
|
|
78550
78576
|
if (!status2.isFile() || status2.isSymbolicLink()) {
|
|
78551
78577
|
return null;
|
|
78552
78578
|
}
|
|
78553
|
-
return JSON.parse(await readFile2(
|
|
78579
|
+
return JSON.parse(await readFile2(path71, "utf8"));
|
|
78554
78580
|
} catch {
|
|
78555
78581
|
return null;
|
|
78556
78582
|
}
|
|
78557
78583
|
}
|
|
78558
|
-
async function assertRegularControlledFile(directoryPath,
|
|
78559
|
-
if (dirname3(
|
|
78584
|
+
async function assertRegularControlledFile(directoryPath, path71) {
|
|
78585
|
+
if (dirname3(path71) !== directoryPath) {
|
|
78560
78586
|
throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
|
|
78561
78587
|
}
|
|
78562
|
-
const status2 = await lstat7(
|
|
78588
|
+
const status2 = await lstat7(path71).catch(() => null);
|
|
78563
78589
|
if (!status2?.isFile() || status2.isSymbolicLink()) {
|
|
78564
78590
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78565
78591
|
}
|
|
78566
78592
|
}
|
|
78567
|
-
async function readRegularFileNoFollow(io, directoryPath,
|
|
78568
|
-
if (dirname3(
|
|
78593
|
+
async function readRegularFileNoFollow(io, directoryPath, path71, expectedIdentity, expectedSize) {
|
|
78594
|
+
if (dirname3(path71) !== directoryPath) {
|
|
78569
78595
|
throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
|
|
78570
78596
|
}
|
|
78571
|
-
if (io.controlledFiles) return io.controlledFiles.read(
|
|
78572
|
-
const handle = await io.open(
|
|
78597
|
+
if (io.controlledFiles) return io.controlledFiles.read(path71, expectedIdentity, expectedSize);
|
|
78598
|
+
const handle = await io.open(path71, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
|
|
78573
78599
|
if (!handle) {
|
|
78574
78600
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78575
78601
|
}
|
|
@@ -78593,8 +78619,8 @@ async function readRegularFileNoFollow(io, directoryPath, path70, expectedIdenti
|
|
|
78593
78619
|
await handle.close();
|
|
78594
78620
|
}
|
|
78595
78621
|
}
|
|
78596
|
-
async function readStableLocalFile(io,
|
|
78597
|
-
const handle = await io.open(
|
|
78622
|
+
async function readStableLocalFile(io, path71) {
|
|
78623
|
+
const handle = await io.open(path71, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
|
|
78598
78624
|
if (!handle) {
|
|
78599
78625
|
throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
|
|
78600
78626
|
}
|
|
@@ -78606,8 +78632,8 @@ async function readStableLocalFile(io, path70) {
|
|
|
78606
78632
|
if (openedStatus.size > BigInt(MAX_IMAGE_BYTES)) {
|
|
78607
78633
|
throw new Error("ATTACHMENT_TOO_LARGE");
|
|
78608
78634
|
}
|
|
78609
|
-
const canonicalPath = await realpath3(
|
|
78610
|
-
const currentStatus = await lstat7(
|
|
78635
|
+
const canonicalPath = await realpath3(path71).catch(() => null);
|
|
78636
|
+
const currentStatus = await lstat7(path71, { bigint: true }).catch(() => null);
|
|
78611
78637
|
if (!canonicalPath || !currentStatus?.isFile() || currentStatus.isSymbolicLink() || currentStatus.dev !== openedStatus.dev || currentStatus.ino !== openedStatus.ino) {
|
|
78612
78638
|
throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
|
|
78613
78639
|
}
|
|
@@ -78620,17 +78646,17 @@ async function readStableLocalFile(io, path70) {
|
|
|
78620
78646
|
await handle.close();
|
|
78621
78647
|
}
|
|
78622
78648
|
}
|
|
78623
|
-
async function pathIsMissing(
|
|
78649
|
+
async function pathIsMissing(path71) {
|
|
78624
78650
|
try {
|
|
78625
|
-
await lstat7(
|
|
78651
|
+
await lstat7(path71);
|
|
78626
78652
|
return false;
|
|
78627
78653
|
} catch (error2) {
|
|
78628
78654
|
return error2.code === "ENOENT";
|
|
78629
78655
|
}
|
|
78630
78656
|
}
|
|
78631
|
-
async function readFileIdentity(io,
|
|
78632
|
-
if (io.controlledFiles) return io.controlledFiles.identity(
|
|
78633
|
-
const handle = await io.open(
|
|
78657
|
+
async function readFileIdentity(io, path71) {
|
|
78658
|
+
if (io.controlledFiles) return io.controlledFiles.identity(path71);
|
|
78659
|
+
const handle = await io.open(path71, constants6.O_RDONLY | constants6.O_NOFOLLOW).catch(() => null);
|
|
78634
78660
|
if (!handle) {
|
|
78635
78661
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78636
78662
|
}
|
|
@@ -78745,7 +78771,7 @@ var init_store = __esm({
|
|
|
78745
78771
|
webp: "image/webp"
|
|
78746
78772
|
};
|
|
78747
78773
|
DEFAULT_ATTACHMENT_STORE_IO = {
|
|
78748
|
-
open: (
|
|
78774
|
+
open: (path71, flags) => open7(path71, flags),
|
|
78749
78775
|
controlledFiles: privateImageFiles
|
|
78750
78776
|
};
|
|
78751
78777
|
AttachmentStore = class _AttachmentStore {
|
|
@@ -78958,15 +78984,15 @@ var init_store = __esm({
|
|
|
78958
78984
|
const allowed = /* @__PURE__ */ new Set([MANIFEST_RELATIVE_PATH, ...next.chunks.map((chunk) => chunk.relativePath)]);
|
|
78959
78985
|
if ((await readdir2(upload.directoryPath)).some((name2) => !allowed.has(name2))) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
|
|
78960
78986
|
for (let offset = 0; offset < chunks.length; offset++) {
|
|
78961
|
-
const
|
|
78987
|
+
const path71 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
|
|
78962
78988
|
let handle;
|
|
78963
78989
|
try {
|
|
78964
|
-
handle = await this.#io.open(
|
|
78990
|
+
handle = await this.#io.open(path71, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
|
|
78965
78991
|
} catch (error2) {
|
|
78966
78992
|
if (error2.code !== "EEXIST") throw error2;
|
|
78967
|
-
const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath,
|
|
78993
|
+
const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path71, void 0, chunk.length);
|
|
78968
78994
|
if (!stored.data.equals(chunk)) throw new Error("CHUNK_CONFLICT");
|
|
78969
|
-
handle = await this.#io.open(
|
|
78995
|
+
handle = await this.#io.open(path71, constants6.O_RDONLY | constants6.O_NOFOLLOW);
|
|
78970
78996
|
}
|
|
78971
78997
|
try {
|
|
78972
78998
|
const status2 = await handle.stat();
|
|
@@ -79346,9 +79372,9 @@ var init_store = __esm({
|
|
|
79346
79372
|
await this.#imageAssets.removeBytes(record26.id);
|
|
79347
79373
|
continue;
|
|
79348
79374
|
}
|
|
79349
|
-
for (const
|
|
79350
|
-
const status2 = await lstat7(
|
|
79351
|
-
if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(
|
|
79375
|
+
for (const path71 of [record26.sourcePath, record26.previewPath]) {
|
|
79376
|
+
const status2 = await lstat7(path71).catch(() => null);
|
|
79377
|
+
if (status2?.isFile() && !status2.isSymbolicLink()) await rm3(path71);
|
|
79352
79378
|
}
|
|
79353
79379
|
}
|
|
79354
79380
|
}
|
|
@@ -79886,10 +79912,10 @@ var init_store = __esm({
|
|
|
79886
79912
|
return bytes3;
|
|
79887
79913
|
}
|
|
79888
79914
|
async #loadBindingIndex() {
|
|
79889
|
-
const
|
|
79890
|
-
const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(
|
|
79915
|
+
const path71 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
|
|
79916
|
+
const manifest = this.#bindingDocuments ? JSON.parse(await this.#bindingDocuments.read(BINDINGS_RELATIVE_PATH, 16 * 1024 * 1024) ?? "null") : await readJsonManifest(path71, this.#io);
|
|
79891
79917
|
if (manifest === null) {
|
|
79892
|
-
if (this.#rawCommit && !await pathIsMissing(
|
|
79918
|
+
if (this.#rawCommit && !await pathIsMissing(path71)) this.#bindingUnavailable = true;
|
|
79893
79919
|
return;
|
|
79894
79920
|
}
|
|
79895
79921
|
if (!isBindingIndexManifest(manifest)) {
|
|
@@ -79949,14 +79975,14 @@ var init_store = __esm({
|
|
|
79949
79975
|
return;
|
|
79950
79976
|
}
|
|
79951
79977
|
const temporaryPath = join2(this.#rootDir, `.bindings-${randomUUID51()}.tmp`);
|
|
79952
|
-
const
|
|
79978
|
+
const path71 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
|
|
79953
79979
|
await writeFile(temporaryPath, `${JSON.stringify(manifest)}
|
|
79954
79980
|
`, {
|
|
79955
79981
|
flag: "wx",
|
|
79956
79982
|
mode: 384
|
|
79957
79983
|
});
|
|
79958
|
-
await rename3(temporaryPath,
|
|
79959
|
-
await chmod3(
|
|
79984
|
+
await rename3(temporaryPath, path71);
|
|
79985
|
+
await chmod3(path71, 384);
|
|
79960
79986
|
}
|
|
79961
79987
|
#commitBindings(bindings) {
|
|
79962
79988
|
this.#bindings.clear();
|
|
@@ -81068,7 +81094,7 @@ var init_managed_store = __esm({
|
|
|
81068
81094
|
});
|
|
81069
81095
|
|
|
81070
81096
|
// apps/desktop/src/daemon/runtime/attachment-storage.ts
|
|
81071
|
-
import
|
|
81097
|
+
import path59 from "node:path";
|
|
81072
81098
|
import { randomUUID as randomUUID53 } from "node:crypto";
|
|
81073
81099
|
var ATTACHMENT_CLEANUP_INTERVAL_MS, RuntimeAttachmentStorage;
|
|
81074
81100
|
var init_attachment_storage = __esm({
|
|
@@ -81210,7 +81236,7 @@ var init_attachment_storage = __esm({
|
|
|
81210
81236
|
requireAttachmentMessageBindings() {
|
|
81211
81237
|
if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
81212
81238
|
if (!this.attachmentMessageBindingsPromise) {
|
|
81213
|
-
this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(
|
|
81239
|
+
this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path59.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
|
|
81214
81240
|
this.attachmentMessageBindings = store;
|
|
81215
81241
|
return store;
|
|
81216
81242
|
}).catch((error2) => {
|
|
@@ -81226,7 +81252,7 @@ var init_attachment_storage = __esm({
|
|
|
81226
81252
|
if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
81227
81253
|
if (!this.managedAttachmentStorePromise) {
|
|
81228
81254
|
const opening = runManagedAttachmentOperation(() => ManagedAttachmentStore.open(
|
|
81229
|
-
|
|
81255
|
+
path59.join(this.ports.dataDirectory(), "attachments", "managed")
|
|
81230
81256
|
)).catch((error2) => {
|
|
81231
81257
|
if (this.managedAttachmentStorePromise === opening) this.managedAttachmentStorePromise = null;
|
|
81232
81258
|
throw error2;
|
|
@@ -82623,9 +82649,9 @@ function sameDeferredIdentity(source2, previous) {
|
|
|
82623
82649
|
if (source2.kind === "history") return previous.kind === "history" && sameLocator(source2.locator, previous.locator);
|
|
82624
82650
|
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);
|
|
82625
82651
|
}
|
|
82626
|
-
async function readSourceFile(
|
|
82652
|
+
async function readSourceFile(path71, signal) {
|
|
82627
82653
|
signal?.throwIfAborted();
|
|
82628
|
-
const handle = await open8(
|
|
82654
|
+
const handle = await open8(path71, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
82629
82655
|
try {
|
|
82630
82656
|
const before = await handle.stat({ bigint: true });
|
|
82631
82657
|
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");
|
|
@@ -82854,12 +82880,12 @@ var init_image_resources = __esm({
|
|
|
82854
82880
|
}, JSON.stringify(identity6));
|
|
82855
82881
|
}
|
|
82856
82882
|
/** 仅供已认证实时消息登记;调用方每次请求仍须验证当前 item/上传暂存资格。 */
|
|
82857
|
-
async registerDeferredFile(threadId2,
|
|
82858
|
-
return this.register({ resourceKey, name: basename4(
|
|
82883
|
+
async registerDeferredFile(threadId2, path71, resourceKey = `live-file:${threadId2}:${path71}`) {
|
|
82884
|
+
return this.register({ resourceKey, name: basename4(path71), source: { kind: "deferred-file", threadId: threadId2, path: path71 } });
|
|
82859
82885
|
}
|
|
82860
|
-
async registerFile(threadId2,
|
|
82886
|
+
async registerFile(threadId2, path71, attachmentId, context) {
|
|
82861
82887
|
if (context && context.visibilityLocator.threadId !== threadId2) throw missing3();
|
|
82862
|
-
const canonical = await realpath4(
|
|
82888
|
+
const canonical = await realpath4(path71);
|
|
82863
82889
|
const file = await readSourceFile(canonical);
|
|
82864
82890
|
return this.register({ attachmentId, resourceKey: context?.resourceKey ?? `file:${threadId2}:${canonical}`, name: basename4(canonical), source: {
|
|
82865
82891
|
kind: "file",
|
|
@@ -82889,9 +82915,9 @@ var init_image_resources = __esm({
|
|
|
82889
82915
|
return sameLocator(this.historyLocator(threadId2, attachmentId) ?? void 0, expectedLocator);
|
|
82890
82916
|
}
|
|
82891
82917
|
/** 保留原件换源时只复用相同受控文件;历史别名和旧暂存不能遮蔽新来源。 */
|
|
82892
|
-
matchesFilePath(threadId2, attachmentId,
|
|
82918
|
+
matchesFilePath(threadId2, attachmentId, path71) {
|
|
82893
82919
|
const entry = this.entries.get(attachmentId);
|
|
82894
|
-
return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path ===
|
|
82920
|
+
return !!entry && threadOf(entry.source) === threadId2 && entry.source.kind === "file" && entry.source.path === path71;
|
|
82895
82921
|
}
|
|
82896
82922
|
has(threadId2, attachmentId) {
|
|
82897
82923
|
const entry = this.entries.get(attachmentId);
|
|
@@ -83297,7 +83323,7 @@ var init_image_confirmation2 = __esm({
|
|
|
83297
83323
|
// apps/desktop/src/daemon/runtime/images.ts
|
|
83298
83324
|
import { createHash as createHash42 } from "node:crypto";
|
|
83299
83325
|
import { realpath as realpath5 } from "node:fs/promises";
|
|
83300
|
-
import
|
|
83326
|
+
import path60 from "node:path";
|
|
83301
83327
|
function objectRecord12(value) {
|
|
83302
83328
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
83303
83329
|
}
|
|
@@ -83416,7 +83442,7 @@ var init_images = __esm({
|
|
|
83416
83442
|
if (itemId && ["userMessage", "UserMessage", "user_message"].includes(String(item.type))) {
|
|
83417
83443
|
if (Array.isArray(item.content)) item.content.forEach((part, index) => {
|
|
83418
83444
|
const input = objectRecord12(part);
|
|
83419
|
-
if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" &&
|
|
83445
|
+
if (["localImage", "local_image"].includes(String(input.type)) && typeof input.path === "string" && path60.isAbsolute(input.path)) registrations.push(this.importThreadImage(threadId2, input.path, itemId, index));
|
|
83420
83446
|
const url = input.type === "image" ? nonEmptyString19(input.url ?? input.image_url) : null;
|
|
83421
83447
|
if (url?.startsWith("data:image/")) registrations.push(this.importThreadImage(threadId2, url, itemId, index));
|
|
83422
83448
|
});
|
|
@@ -83440,7 +83466,7 @@ var init_images = __esm({
|
|
|
83440
83466
|
requireImageResources() {
|
|
83441
83467
|
if (!this.ports.attachmentReady()) throw new Error("\u56FE\u7247\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
83442
83468
|
if (!this.imageResourcesPromise) this.imageResourcesPromise = ImageResources.create({
|
|
83443
|
-
indexPath:
|
|
83469
|
+
indexPath: path60.join(this.ports.dataDirectory(), "image-resources", "index.json"),
|
|
83444
83470
|
readAppServerImage: (source2, signal) => this.readAppServerImage(source2, signal),
|
|
83445
83471
|
onDiagnostic: (event) => this.ports.diagnostic(event)
|
|
83446
83472
|
}).catch((error2) => {
|
|
@@ -83621,7 +83647,7 @@ var init_images = __esm({
|
|
|
83621
83647
|
/** 同一消息引用共享轻量登记;整个 Runtime 最多同时处理四个索引写入。 */
|
|
83622
83648
|
importThreadImage(threadId2, sourcePath, itemId, partIndex, sourceIsCurrent = () => true) {
|
|
83623
83649
|
const embedded = sourcePath.startsWith("data:image/") && Number.isSafeInteger(partIndex) && partIndex >= 0;
|
|
83624
|
-
if (!itemId || !
|
|
83650
|
+
if (!itemId || !path60.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
|
|
83625
83651
|
const generation = this.ports.generation();
|
|
83626
83652
|
const key = this.localImageKey(threadId2, sourcePath, itemId, partIndex);
|
|
83627
83653
|
const routeGeneration = this.ports.controlGeneration(threadId2);
|
|
@@ -83658,7 +83684,7 @@ var init_images = __esm({
|
|
|
83658
83684
|
this.knownLocalImages.set(key, {
|
|
83659
83685
|
type: "image",
|
|
83660
83686
|
attachmentId: registered.attachmentId,
|
|
83661
|
-
name: embedded ? "\u56FE\u7247" :
|
|
83687
|
+
name: embedded ? "\u56FE\u7247" : path60.basename(sourcePath),
|
|
83662
83688
|
previewAvailable: false,
|
|
83663
83689
|
previewState: "deferred"
|
|
83664
83690
|
});
|
|
@@ -85744,18 +85770,18 @@ var init_session_sources = __esm({
|
|
|
85744
85770
|
const isCurrent = () => options.isCurrent?.() !== false;
|
|
85745
85771
|
const paths = /* @__PURE__ */ new Map();
|
|
85746
85772
|
for (const thread4 of threads) {
|
|
85747
|
-
const
|
|
85748
|
-
if (!paths.has(thread4.id)) paths.set(thread4.id,
|
|
85749
|
-
else if (paths.get(thread4.id) !==
|
|
85773
|
+
const path71 = typeof thread4.path === "string" && thread4.path.length > 0 ? thread4.path : null;
|
|
85774
|
+
if (!paths.has(thread4.id)) paths.set(thread4.id, path71);
|
|
85775
|
+
else if (paths.get(thread4.id) !== path71) paths.set(thread4.id, void 0);
|
|
85750
85776
|
}
|
|
85751
|
-
for (const [id5,
|
|
85777
|
+
for (const [id5, path71] of paths) {
|
|
85752
85778
|
const thread4 = { id: id5 };
|
|
85753
85779
|
if (!isCurrent()) return;
|
|
85754
85780
|
const token3 = this.begin(thread4.id);
|
|
85755
85781
|
let resolution = null;
|
|
85756
85782
|
if (resolver) {
|
|
85757
85783
|
try {
|
|
85758
|
-
resolution = await resolver.resolve(thread4.id,
|
|
85784
|
+
resolution = await resolver.resolve(thread4.id, path71);
|
|
85759
85785
|
} catch {
|
|
85760
85786
|
resolution = null;
|
|
85761
85787
|
}
|
|
@@ -85820,7 +85846,7 @@ var init_session_sources = __esm({
|
|
|
85820
85846
|
});
|
|
85821
85847
|
|
|
85822
85848
|
// apps/desktop/src/daemon/runtime/settings-selection.ts
|
|
85823
|
-
import
|
|
85849
|
+
import path61 from "node:path";
|
|
85824
85850
|
var RuntimeSettingsSelection;
|
|
85825
85851
|
var init_settings_selection = __esm({
|
|
85826
85852
|
"apps/desktop/src/daemon/runtime/settings-selection.ts"() {
|
|
@@ -85836,7 +85862,7 @@ var init_settings_selection = __esm({
|
|
|
85836
85862
|
ports;
|
|
85837
85863
|
targetProjectRoot(cwd) {
|
|
85838
85864
|
const matched = this.ports.projectRoots().filter((projectRoot) => pathBelongsToProjectRoot(projectRoot, cwd)).sort((left, right) => right.length - left.length)[0];
|
|
85839
|
-
return matched ??
|
|
85865
|
+
return matched ?? path61.normalize(cwd);
|
|
85840
85866
|
}
|
|
85841
85867
|
inheritedCreate(threadId2) {
|
|
85842
85868
|
const empty = { authorization: null, model: null };
|
|
@@ -86180,7 +86206,7 @@ var init_device_name = __esm({
|
|
|
86180
86206
|
});
|
|
86181
86207
|
|
|
86182
86208
|
// apps/desktop/src/daemon/debug-log.ts
|
|
86183
|
-
import
|
|
86209
|
+
import path62 from "node:path";
|
|
86184
86210
|
function isNotificationDeliveryReason(value) {
|
|
86185
86211
|
return NOTIFICATION_DELIVERY_REASON_CODES.has(value) || /^http_[1-5]\d\d$/.test(value) || /^business_\d{1,6}$/.test(value);
|
|
86186
86212
|
}
|
|
@@ -86219,10 +86245,10 @@ function hasDebugFilter(filter) {
|
|
|
86219
86245
|
return Boolean(filter?.components || filter?.channels || filter?.events);
|
|
86220
86246
|
}
|
|
86221
86247
|
function createSafeFilePath(runtimeDir, files) {
|
|
86222
|
-
const dir =
|
|
86248
|
+
const dir = path62.join(runtimeDir, "debug");
|
|
86223
86249
|
files.ensureDirectory(dir);
|
|
86224
86250
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
86225
|
-
return
|
|
86251
|
+
return path62.join(dir, `${timestamp}-${process.pid}.ndjson`);
|
|
86226
86252
|
}
|
|
86227
86253
|
function createFileDebugLogger(filePath, shouldWrite, files) {
|
|
86228
86254
|
let writer;
|
|
@@ -86828,7 +86854,7 @@ function withoutPersistentImageBytes(value, key = "", seen = /* @__PURE__ */ new
|
|
|
86828
86854
|
function createFileRawDebugLogger(runtimeDir, filter, policy, files) {
|
|
86829
86855
|
const now = policy.now ?? (() => /* @__PURE__ */ new Date());
|
|
86830
86856
|
const manager = new RawDebugFileManager(
|
|
86831
|
-
|
|
86857
|
+
path62.join(runtimeDir, "debug"),
|
|
86832
86858
|
now,
|
|
86833
86859
|
policy.maxSegmentBytes ?? RAW_DEBUG_MAX_SEGMENT_BYTES,
|
|
86834
86860
|
policy.maxSegments ?? RAW_DEBUG_MAX_SEGMENTS,
|
|
@@ -87839,7 +87865,7 @@ var init_debug_log = __esm({
|
|
|
87839
87865
|
}
|
|
87840
87866
|
const timestamp = this.now().toISOString().replace(/[:.]/g, "-");
|
|
87841
87867
|
for (; ; ) {
|
|
87842
|
-
const filePath =
|
|
87868
|
+
const filePath = path62.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
|
|
87843
87869
|
try {
|
|
87844
87870
|
return this.files.create(filePath);
|
|
87845
87871
|
} catch (error2) {
|
|
@@ -87872,7 +87898,7 @@ var init_debug_log = __esm({
|
|
|
87872
87898
|
});
|
|
87873
87899
|
|
|
87874
87900
|
// apps/desktop/src/daemon/control-observability.ts
|
|
87875
|
-
import
|
|
87901
|
+
import path63 from "node:path";
|
|
87876
87902
|
function isRecentControlTimestamp(timestampMs, nowMs) {
|
|
87877
87903
|
return timestampMs <= nowMs && isRetainedDaemonLogTimestamp(timestampMs, nowMs);
|
|
87878
87904
|
}
|
|
@@ -87905,7 +87931,7 @@ function page3(values, params) {
|
|
|
87905
87931
|
};
|
|
87906
87932
|
}
|
|
87907
87933
|
function listControlLogs(input) {
|
|
87908
|
-
const directoryPath =
|
|
87934
|
+
const directoryPath = path63.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
|
|
87909
87935
|
const values = [];
|
|
87910
87936
|
let totalBytes = 0;
|
|
87911
87937
|
let processedLines = 0;
|
|
@@ -88928,7 +88954,7 @@ var init_composition = __esm({
|
|
|
88928
88954
|
refreshFallback: async (id5, token3) => {
|
|
88929
88955
|
await this.historySnapshot.tryRefreshThreadMessages(id5, false, { kind: "fallback", token: token3 });
|
|
88930
88956
|
},
|
|
88931
|
-
resolveKnownLocalImage: (id5,
|
|
88957
|
+
resolveKnownLocalImage: (id5, path71, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path71, itemId, partIndex),
|
|
88932
88958
|
hasDesktopSnapshot: (id5) => this.controlAccess.snapshot(id5).hasCurrentDesktopSnapshot,
|
|
88933
88959
|
followerPhase: (id5) => this.followerCoordination.activeThreadFollowerCoordinatorValue?.phaseFor(id5) ?? null,
|
|
88934
88960
|
generation: () => this.lifecycle.runtimeGenerationValue
|
|
@@ -90524,7 +90550,7 @@ var init_runtime2 = __esm({
|
|
|
90524
90550
|
|
|
90525
90551
|
// apps/desktop/src/daemon/follower-open-trace.ts
|
|
90526
90552
|
import { randomUUID as randomUUID56 } from "node:crypto";
|
|
90527
|
-
import
|
|
90553
|
+
import path64 from "node:path";
|
|
90528
90554
|
function isFiniteTimestamp2(value) {
|
|
90529
90555
|
return typeof value === "number" && Number.isFinite(value) && Number.isSafeInteger(value);
|
|
90530
90556
|
}
|
|
@@ -90662,7 +90688,7 @@ function parseRecord2(line) {
|
|
|
90662
90688
|
function listPrivateTraceFiles(runtimeDir, storage) {
|
|
90663
90689
|
try {
|
|
90664
90690
|
storage.checkDirectory(runtimeDir);
|
|
90665
|
-
const scan = storage.scan(
|
|
90691
|
+
const scan = storage.scan(path64.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
|
|
90666
90692
|
const files = [];
|
|
90667
90693
|
let incomplete = scan.truncated;
|
|
90668
90694
|
for (const entry of scan.entries) {
|
|
@@ -90676,8 +90702,8 @@ function listPrivateTraceFiles(runtimeDir, storage) {
|
|
|
90676
90702
|
}
|
|
90677
90703
|
}
|
|
90678
90704
|
function compareTraceFilePaths(left, right) {
|
|
90679
|
-
const a =
|
|
90680
|
-
const b =
|
|
90705
|
+
const a = path64.basename(left);
|
|
90706
|
+
const b = path64.basename(right);
|
|
90681
90707
|
return a.slice(0, 10).localeCompare(b.slice(0, 10)) || Number(a.slice(11, -7)) - Number(b.slice(11, -7));
|
|
90682
90708
|
}
|
|
90683
90709
|
function readPrivateTraceFile(file, remainingBytes, storage) {
|
|
@@ -91194,7 +91220,7 @@ var init_follower_open_trace = __esm({
|
|
|
91194
91220
|
}
|
|
91195
91221
|
clearAll() {
|
|
91196
91222
|
try {
|
|
91197
|
-
const directoryPath =
|
|
91223
|
+
const directoryPath = path64.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
|
|
91198
91224
|
this.files.checkDirectory(this.runtimeDir);
|
|
91199
91225
|
let scan;
|
|
91200
91226
|
try {
|
|
@@ -91251,7 +91277,7 @@ var init_follower_open_trace = __esm({
|
|
|
91251
91277
|
}
|
|
91252
91278
|
}
|
|
91253
91279
|
append(record26) {
|
|
91254
|
-
const directoryPath =
|
|
91280
|
+
const directoryPath = path64.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
|
|
91255
91281
|
this.ensureTraceDirectory(directoryPath);
|
|
91256
91282
|
const content2 = `${JSON.stringify(record26)}
|
|
91257
91283
|
`;
|
|
@@ -91261,8 +91287,8 @@ var init_follower_open_trace = __esm({
|
|
|
91261
91287
|
selectAppendFile(directoryPath, dateName, bytes3) {
|
|
91262
91288
|
const date = dateName.slice(0, 10);
|
|
91263
91289
|
let filePath = this.appendFilePath;
|
|
91264
|
-
if (!filePath ||
|
|
91265
|
-
filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ??
|
|
91290
|
+
if (!filePath || path64.basename(filePath).slice(0, 10) !== date) {
|
|
91291
|
+
filePath = listPrivateTraceFiles(this.runtimeDir, this.files).files.find((candidate) => candidate.name.slice(0, 10) === date)?.path ?? path64.join(directoryPath, dateName);
|
|
91266
91292
|
}
|
|
91267
91293
|
for (let attempt = 0; attempt < MAX_DIRECTORY_ENTRIES3; attempt += 1) {
|
|
91268
91294
|
let stats;
|
|
@@ -91275,9 +91301,9 @@ var init_follower_open_trace = __esm({
|
|
|
91275
91301
|
this.appendFilePath = filePath;
|
|
91276
91302
|
return filePath;
|
|
91277
91303
|
}
|
|
91278
|
-
const next = Number(
|
|
91304
|
+
const next = Number(path64.basename(filePath).slice(11, -7)) + 1;
|
|
91279
91305
|
if (next > 999999) break;
|
|
91280
|
-
filePath =
|
|
91306
|
+
filePath = path64.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
|
|
91281
91307
|
}
|
|
91282
91308
|
throw new Error("trace segment limit reached");
|
|
91283
91309
|
}
|
|
@@ -92652,7 +92678,7 @@ var init_watch = __esm({
|
|
|
92652
92678
|
});
|
|
92653
92679
|
|
|
92654
92680
|
// apps/desktop/src/relay/relay-origin-store.ts
|
|
92655
|
-
import
|
|
92681
|
+
import path65 from "node:path";
|
|
92656
92682
|
function parseStoredOrigin(value) {
|
|
92657
92683
|
try {
|
|
92658
92684
|
const document = JSON.parse(value);
|
|
@@ -92666,7 +92692,7 @@ function parseStoredOrigin(value) {
|
|
|
92666
92692
|
}
|
|
92667
92693
|
}
|
|
92668
92694
|
function resolveDefaultRelayOriginStorePath() {
|
|
92669
|
-
return
|
|
92695
|
+
return path65.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
|
|
92670
92696
|
}
|
|
92671
92697
|
var DEFAULT_FILE_NAME2, MAX_FILE_BYTES3, FileRelayOriginStore;
|
|
92672
92698
|
var init_relay_origin_store = __esm({
|
|
@@ -92682,7 +92708,7 @@ var init_relay_origin_store = __esm({
|
|
|
92682
92708
|
files;
|
|
92683
92709
|
tail = Promise.resolve();
|
|
92684
92710
|
constructor(options = {}) {
|
|
92685
|
-
this.filePath =
|
|
92711
|
+
this.filePath = path65.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
|
|
92686
92712
|
this.files = options.files ?? privateDocumentFiles;
|
|
92687
92713
|
}
|
|
92688
92714
|
async load() {
|
|
@@ -92718,7 +92744,7 @@ var init_relay_origin_store = __esm({
|
|
|
92718
92744
|
});
|
|
92719
92745
|
|
|
92720
92746
|
// apps/desktop/src/cli/commands/daemon.ts
|
|
92721
|
-
import
|
|
92747
|
+
import path66 from "node:path";
|
|
92722
92748
|
function daemonStartFailed3() {
|
|
92723
92749
|
return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
|
|
92724
92750
|
}
|
|
@@ -92911,7 +92937,7 @@ async function runDaemonCommand(args, options = {}) {
|
|
|
92911
92937
|
loggers.rawDebugLogger?.path,
|
|
92912
92938
|
loggers.errorLogger?.path,
|
|
92913
92939
|
// 后台 worker 的 stdout/stderr descriptor 无法安全重开,只按 daemon 所有权保护固定路径。
|
|
92914
|
-
...options.mode === "background" ? [
|
|
92940
|
+
...options.mode === "background" ? [path66.join(runtimeDir, "daemon-worker.log")] : []
|
|
92915
92941
|
].filter((filePath) => typeof filePath === "string")
|
|
92916
92942
|
});
|
|
92917
92943
|
} catch {
|
|
@@ -93401,7 +93427,7 @@ var init_auth2 = __esm({
|
|
|
93401
93427
|
});
|
|
93402
93428
|
|
|
93403
93429
|
// apps/desktop/src/control/routes.ts
|
|
93404
|
-
import
|
|
93430
|
+
import fs41 from "node:fs";
|
|
93405
93431
|
function daemonStoppedOverview() {
|
|
93406
93432
|
return {
|
|
93407
93433
|
daemon: { state: "stopped" },
|
|
@@ -93420,12 +93446,12 @@ function emptyControlPage(page4, pageSize) {
|
|
|
93420
93446
|
}
|
|
93421
93447
|
function isDaemonRuntimeActive(socketPath = daemonSocketPath(), statusPath = daemonStatusPath()) {
|
|
93422
93448
|
try {
|
|
93423
|
-
const socket =
|
|
93424
|
-
const status2 =
|
|
93449
|
+
const socket = fs41.lstatSync(socketPath);
|
|
93450
|
+
const status2 = fs41.lstatSync(statusPath);
|
|
93425
93451
|
if (!socket.isSocket() || !status2.isFile() || status2.isSymbolicLink() || status2.size > 4 * 1024) {
|
|
93426
93452
|
return false;
|
|
93427
93453
|
}
|
|
93428
|
-
const parsed = JSON.parse(
|
|
93454
|
+
const parsed = JSON.parse(fs41.readFileSync(statusPath, "utf8"));
|
|
93429
93455
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || parsed.socketPath !== socketPath || !Number.isSafeInteger(parsed.pid) || parsed.pid <= 0) return false;
|
|
93430
93456
|
process.kill(parsed.pid, 0);
|
|
93431
93457
|
return true;
|
|
@@ -94978,8 +95004,8 @@ var init_lifecycle3 = __esm({
|
|
|
94978
95004
|
|
|
94979
95005
|
// apps/desktop/src/control/server.ts
|
|
94980
95006
|
import http4 from "node:http";
|
|
94981
|
-
import
|
|
94982
|
-
import
|
|
95007
|
+
import fs42 from "node:fs";
|
|
95008
|
+
import path67 from "node:path";
|
|
94983
95009
|
import { createRequire as createRequire2 } from "node:module";
|
|
94984
95010
|
function isControlApiPath(pathname) {
|
|
94985
95011
|
const [, api, version2, control] = pathname.split("/", 4);
|
|
@@ -95025,15 +95051,15 @@ function requestHasBody(request2) {
|
|
|
95025
95051
|
return Number(contentLength) !== 0;
|
|
95026
95052
|
}
|
|
95027
95053
|
function resolveExactControlWritePath(requestTarget) {
|
|
95028
|
-
for (const
|
|
95029
|
-
if (requestTarget ===
|
|
95054
|
+
for (const path71 of [CONTROL_DEVICE_REVOKE_PATH, CONTROL_DAEMON_ACTION_PATH, CONTROL_TRACE_CLEAR_PATH]) {
|
|
95055
|
+
if (requestTarget === path71 || requestTarget.startsWith(`${path71}?`) && !requestTarget.includes("#")) return path71;
|
|
95030
95056
|
}
|
|
95031
95057
|
return null;
|
|
95032
95058
|
}
|
|
95033
95059
|
function resolveExactControlTraceReadPath(requestTarget) {
|
|
95034
|
-
for (const
|
|
95035
|
-
if (requestTarget ===
|
|
95036
|
-
return
|
|
95060
|
+
for (const path71 of [CONTROL_TRACE_LIST_PATH, CONTROL_TRACE_DETAIL_PATH]) {
|
|
95061
|
+
if (requestTarget === path71 || requestTarget.startsWith(`${path71}?`) && !requestTarget.includes("#")) {
|
|
95062
|
+
return path71;
|
|
95037
95063
|
}
|
|
95038
95064
|
}
|
|
95039
95065
|
return null;
|
|
@@ -95054,9 +95080,9 @@ var init_server5 = __esm({
|
|
|
95054
95080
|
init_lifecycle3();
|
|
95055
95081
|
require2 = createRequire2(import.meta.url);
|
|
95056
95082
|
CONTROL_PAGE_PATHS = ["/", "/connections", "/sessions", "/subscriptions", "/turn-audit", "/logs"];
|
|
95057
|
-
CONTROL_INDEX =
|
|
95058
|
-
BOOTSTRAP_CSS =
|
|
95059
|
-
BOOTSTRAP_BUNDLE =
|
|
95083
|
+
CONTROL_INDEX = fs42.readFileSync(desktopAssetUrl("control", "index.html"));
|
|
95084
|
+
BOOTSTRAP_CSS = fs42.readFileSync(require2.resolve("bootstrap/dist/css/bootstrap.min.css"));
|
|
95085
|
+
BOOTSTRAP_BUNDLE = fs42.readFileSync(require2.resolve("bootstrap/dist/js/bootstrap.bundle.min.js"));
|
|
95060
95086
|
STATIC_ASSETS = Object.freeze({
|
|
95061
95087
|
...Object.fromEntries(CONTROL_PAGE_PATHS.map((pathname) => [pathname, {
|
|
95062
95088
|
contentType: "text/html; charset=utf-8",
|
|
@@ -95064,11 +95090,11 @@ var init_server5 = __esm({
|
|
|
95064
95090
|
}])),
|
|
95065
95091
|
"/app.js": {
|
|
95066
95092
|
contentType: "application/javascript; charset=utf-8",
|
|
95067
|
-
body:
|
|
95093
|
+
body: fs42.readFileSync(desktopAssetUrl("control", "app.js"))
|
|
95068
95094
|
},
|
|
95069
95095
|
"/chart.umd.js": {
|
|
95070
95096
|
contentType: "application/javascript; charset=utf-8",
|
|
95071
|
-
body:
|
|
95097
|
+
body: fs42.readFileSync(path67.join(path67.dirname(require2.resolve("chart.js")), "chart.umd.js"))
|
|
95072
95098
|
},
|
|
95073
95099
|
"/bootstrap.min.css": {
|
|
95074
95100
|
contentType: "text/css; charset=utf-8",
|
|
@@ -95284,41 +95310,41 @@ var init_server5 = __esm({
|
|
|
95284
95310
|
|
|
95285
95311
|
// apps/desktop/src/control/state.ts
|
|
95286
95312
|
import { createHash as createHash44, randomUUID as randomUUID60 } from "node:crypto";
|
|
95287
|
-
import
|
|
95288
|
-
import
|
|
95313
|
+
import fs43 from "node:fs";
|
|
95314
|
+
import path68 from "node:path";
|
|
95289
95315
|
function createControlState(input) {
|
|
95290
95316
|
return createControlStateUnlocked(input);
|
|
95291
95317
|
}
|
|
95292
95318
|
function createControlStateUnlocked(input) {
|
|
95293
95319
|
const state = toControlState(input);
|
|
95294
95320
|
const statePath = controlStatePath(input.runtimeDir);
|
|
95295
|
-
const temporaryPath =
|
|
95296
|
-
|
|
95297
|
-
`.${
|
|
95321
|
+
const temporaryPath = path68.join(
|
|
95322
|
+
path68.dirname(statePath),
|
|
95323
|
+
`.${path68.basename(statePath)}.${randomUUID60()}.tmp`
|
|
95298
95324
|
);
|
|
95299
95325
|
let descriptor = null;
|
|
95300
95326
|
let temporaryIdentity = null;
|
|
95301
95327
|
let published = null;
|
|
95302
95328
|
let operationError;
|
|
95303
95329
|
try {
|
|
95304
|
-
descriptor =
|
|
95305
|
-
if (process.platform !== "win32")
|
|
95306
|
-
const stats =
|
|
95330
|
+
descriptor = fs43.openSync(temporaryPath, "wx", 384);
|
|
95331
|
+
if (process.platform !== "win32") fs43.fchmodSync(descriptor, 384);
|
|
95332
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95307
95333
|
assertRegularControlStateDescriptor(stats);
|
|
95308
95334
|
temporaryIdentity = identityFromStats(stats);
|
|
95309
|
-
|
|
95335
|
+
fs43.writeFileSync(descriptor, `${JSON.stringify(state)}
|
|
95310
95336
|
`, "utf8");
|
|
95311
|
-
|
|
95312
|
-
|
|
95337
|
+
fs43.fsyncSync(descriptor);
|
|
95338
|
+
fs43.closeSync(descriptor);
|
|
95313
95339
|
descriptor = null;
|
|
95314
|
-
|
|
95340
|
+
fs43.linkSync(temporaryPath, statePath);
|
|
95315
95341
|
published = persistedControlState(state, statePath, identityFromStats(stats), "canonical");
|
|
95316
95342
|
} catch (error2) {
|
|
95317
95343
|
operationError = error2;
|
|
95318
95344
|
} finally {
|
|
95319
95345
|
if (descriptor !== null) {
|
|
95320
95346
|
try {
|
|
95321
|
-
|
|
95347
|
+
fs43.closeSync(descriptor);
|
|
95322
95348
|
} catch (error2) {
|
|
95323
95349
|
operationError ??= error2;
|
|
95324
95350
|
}
|
|
@@ -95341,7 +95367,7 @@ function createControlStateUnlocked(input) {
|
|
|
95341
95367
|
return published;
|
|
95342
95368
|
}
|
|
95343
95369
|
function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
|
|
95344
|
-
const stateBasename =
|
|
95370
|
+
const stateBasename = path68.basename(controlStatePath(runtimeDir));
|
|
95345
95371
|
const artifactPattern = new RegExp(
|
|
95346
95372
|
`^\\.${escapeRegExp(stateBasename)}(?:\\.coordination\\.lock)?\\.[0-9a-f-]+\\.(?:tmp|snapshot)$`,
|
|
95347
95373
|
"u"
|
|
@@ -95349,19 +95375,19 @@ function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
|
|
|
95349
95375
|
let removed = 0;
|
|
95350
95376
|
let entries;
|
|
95351
95377
|
try {
|
|
95352
|
-
entries =
|
|
95378
|
+
entries = fs43.readdirSync(runtimeDir);
|
|
95353
95379
|
} catch {
|
|
95354
95380
|
return 0;
|
|
95355
95381
|
}
|
|
95356
95382
|
for (const entry of entries) {
|
|
95357
95383
|
if (entry !== `${stateBasename}.coordination.lock` && !artifactPattern.test(entry)) continue;
|
|
95358
|
-
const artifactPath =
|
|
95384
|
+
const artifactPath = path68.join(runtimeDir, entry);
|
|
95359
95385
|
try {
|
|
95360
|
-
const stats =
|
|
95386
|
+
const stats = fs43.lstatSync(artifactPath, { bigint: true });
|
|
95361
95387
|
if (!stats.isFile() || stats.isSymbolicLink() || process.platform !== "win32" && (stats.mode & 0o777n) !== 0o600n) {
|
|
95362
95388
|
continue;
|
|
95363
95389
|
}
|
|
95364
|
-
|
|
95390
|
+
fs43.unlinkSync(artifactPath);
|
|
95365
95391
|
removed += 1;
|
|
95366
95392
|
} catch {
|
|
95367
95393
|
}
|
|
@@ -95399,7 +95425,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95399
95425
|
if (input.expected.path !== statePath) return false;
|
|
95400
95426
|
const snapshotPath = stateSnapshotPath(statePath);
|
|
95401
95427
|
try {
|
|
95402
|
-
|
|
95428
|
+
fs43.linkSync(statePath, snapshotPath);
|
|
95403
95429
|
} catch (error2) {
|
|
95404
95430
|
if (error2.code === "ENOENT") return false;
|
|
95405
95431
|
return false;
|
|
@@ -95418,7 +95444,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95418
95444
|
return false;
|
|
95419
95445
|
}
|
|
95420
95446
|
if (!canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2)) return false;
|
|
95421
|
-
|
|
95447
|
+
fs43.unlinkSync(statePath);
|
|
95422
95448
|
canonicalRemoved = true;
|
|
95423
95449
|
return true;
|
|
95424
95450
|
} catch {
|
|
@@ -95436,7 +95462,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95436
95462
|
function readControlStateAtPath(filePath, logicalPath) {
|
|
95437
95463
|
const descriptor = openControlStateForRead(filePath);
|
|
95438
95464
|
try {
|
|
95439
|
-
const stats =
|
|
95465
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95440
95466
|
assertRegularControlStateDescriptor(stats);
|
|
95441
95467
|
assertPrivateControlStateMode(stats);
|
|
95442
95468
|
if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
|
|
@@ -95451,14 +95477,14 @@ function readControlStateAtPath(filePath, logicalPath) {
|
|
|
95451
95477
|
throw new CorruptControlStateError(logicalPath, identity6, contents);
|
|
95452
95478
|
}
|
|
95453
95479
|
} finally {
|
|
95454
|
-
|
|
95480
|
+
fs43.closeSync(descriptor);
|
|
95455
95481
|
}
|
|
95456
95482
|
}
|
|
95457
95483
|
function readBoundedControlState(descriptor) {
|
|
95458
95484
|
const buffer = Buffer.alloc(CONTROL_STATE_MAX_BYTES + 1);
|
|
95459
95485
|
let bytesRead = 0;
|
|
95460
95486
|
while (bytesRead < buffer.length) {
|
|
95461
|
-
const count =
|
|
95487
|
+
const count = fs43.readSync(
|
|
95462
95488
|
descriptor,
|
|
95463
95489
|
buffer,
|
|
95464
95490
|
bytesRead,
|
|
@@ -95477,12 +95503,12 @@ function removeCorruptControlState(error2) {
|
|
|
95477
95503
|
const snapshotPath = stateSnapshotPath(error2.statePath);
|
|
95478
95504
|
let canonicalRemoved = false;
|
|
95479
95505
|
try {
|
|
95480
|
-
|
|
95506
|
+
fs43.linkSync(error2.statePath, snapshotPath);
|
|
95481
95507
|
} catch {
|
|
95482
95508
|
return false;
|
|
95483
95509
|
}
|
|
95484
95510
|
try {
|
|
95485
|
-
const snapshotStats =
|
|
95511
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95486
95512
|
if (!snapshotStats.isFile()) return false;
|
|
95487
95513
|
const snapshotIdentity = identityFromStats(snapshotStats);
|
|
95488
95514
|
if (hasUsableInode(error2.fileIdentity) && hasUsableInode(snapshotIdentity) && !sameIdentity(error2.fileIdentity, snapshotIdentity)) {
|
|
@@ -95493,7 +95519,7 @@ function removeCorruptControlState(error2) {
|
|
|
95493
95519
|
if (fingerprint(snapshot2) !== error2.fingerprint) return false;
|
|
95494
95520
|
}
|
|
95495
95521
|
if (!canonicalMatchesSnapshotByIdentity(error2.statePath, snapshotPath)) return false;
|
|
95496
|
-
|
|
95522
|
+
fs43.unlinkSync(error2.statePath);
|
|
95497
95523
|
canonicalRemoved = true;
|
|
95498
95524
|
return true;
|
|
95499
95525
|
} catch {
|
|
@@ -95509,7 +95535,7 @@ function removeCorruptControlState(error2) {
|
|
|
95509
95535
|
function readRawControlState(filePath) {
|
|
95510
95536
|
const descriptor = openControlStateForRead(filePath);
|
|
95511
95537
|
try {
|
|
95512
|
-
const stats =
|
|
95538
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95513
95539
|
assertRegularControlStateDescriptor(stats);
|
|
95514
95540
|
assertPrivateControlStateMode(stats);
|
|
95515
95541
|
if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
|
|
@@ -95517,13 +95543,13 @@ function readRawControlState(filePath) {
|
|
|
95517
95543
|
}
|
|
95518
95544
|
return readBoundedControlState(descriptor);
|
|
95519
95545
|
} finally {
|
|
95520
|
-
|
|
95546
|
+
fs43.closeSync(descriptor);
|
|
95521
95547
|
}
|
|
95522
95548
|
}
|
|
95523
95549
|
function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
|
|
95524
95550
|
if (!canonicalMatchesSnapshotByIdentity(statePath, snapshotPath)) return false;
|
|
95525
|
-
const canonicalStats =
|
|
95526
|
-
const snapshotStats =
|
|
95551
|
+
const canonicalStats = fs43.lstatSync(statePath, { bigint: true });
|
|
95552
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95527
95553
|
if (hasUsableInode(identityFromStats(canonicalStats)) && hasUsableInode(identityFromStats(snapshotStats))) {
|
|
95528
95554
|
return true;
|
|
95529
95555
|
}
|
|
@@ -95531,8 +95557,8 @@ function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
|
|
|
95531
95557
|
return current2.pid === snapshot2.pid && current2.ownershipSecret === snapshot2.ownershipSecret;
|
|
95532
95558
|
}
|
|
95533
95559
|
function canonicalMatchesSnapshotByIdentity(statePath, snapshotPath) {
|
|
95534
|
-
const canonicalStats =
|
|
95535
|
-
const snapshotStats =
|
|
95560
|
+
const canonicalStats = fs43.lstatSync(statePath, { bigint: true });
|
|
95561
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95536
95562
|
if (!canonicalStats.isFile() || !snapshotStats.isFile()) return false;
|
|
95537
95563
|
const canonicalIdentity = identityFromStats(canonicalStats);
|
|
95538
95564
|
const snapshotIdentity = identityFromStats(snapshotStats);
|
|
@@ -95563,9 +95589,9 @@ function sameIdentity(left, right) {
|
|
|
95563
95589
|
return left.device === right.device && left.inode === right.inode;
|
|
95564
95590
|
}
|
|
95565
95591
|
function stateSnapshotPath(statePath) {
|
|
95566
|
-
return
|
|
95567
|
-
|
|
95568
|
-
`.${
|
|
95592
|
+
return path68.join(
|
|
95593
|
+
path68.dirname(statePath),
|
|
95594
|
+
`.${path68.basename(statePath)}.${randomUUID60()}.snapshot`
|
|
95569
95595
|
);
|
|
95570
95596
|
}
|
|
95571
95597
|
function fingerprint(contents) {
|
|
@@ -95576,7 +95602,7 @@ function escapeRegExp(value) {
|
|
|
95576
95602
|
}
|
|
95577
95603
|
function unlinkControlStateTemporary(temporaryPath) {
|
|
95578
95604
|
try {
|
|
95579
|
-
|
|
95605
|
+
fs43.unlinkSync(temporaryPath);
|
|
95580
95606
|
return void 0;
|
|
95581
95607
|
} catch (error2) {
|
|
95582
95608
|
return error2.code === "ENOENT" ? void 0 : error2;
|
|
@@ -95588,28 +95614,28 @@ function eraseControlStateTemporary(temporaryPath, expectedIdentity) {
|
|
|
95588
95614
|
try {
|
|
95589
95615
|
let beforeIdentity = null;
|
|
95590
95616
|
if (process.platform === "win32") {
|
|
95591
|
-
const before =
|
|
95617
|
+
const before = fs43.lstatSync(temporaryPath, { bigint: true });
|
|
95592
95618
|
beforeIdentity = identityFromStats(before);
|
|
95593
95619
|
if (!before.isFile() || before.isSymbolicLink() || !hasUsableInode(beforeIdentity) || !sameIdentity(beforeIdentity, expectedIdentity)) return;
|
|
95594
95620
|
}
|
|
95595
|
-
const noFollow = process.platform === "win32" ? 0 :
|
|
95621
|
+
const noFollow = process.platform === "win32" ? 0 : fs43.constants.O_NOFOLLOW;
|
|
95596
95622
|
if (process.platform !== "win32" && (!noFollow || typeof noFollow !== "number")) return;
|
|
95597
|
-
descriptor =
|
|
95598
|
-
const stats =
|
|
95623
|
+
descriptor = fs43.openSync(temporaryPath, fs43.constants.O_RDWR | noFollow);
|
|
95624
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95599
95625
|
const identity6 = identityFromStats(stats);
|
|
95600
95626
|
if (!stats.isFile() || !hasUsableInode(identity6) || !sameIdentity(identity6, expectedIdentity)) return;
|
|
95601
95627
|
if (process.platform === "win32") {
|
|
95602
|
-
const after =
|
|
95628
|
+
const after = fs43.lstatSync(temporaryPath, { bigint: true });
|
|
95603
95629
|
const afterIdentity = identityFromStats(after);
|
|
95604
95630
|
if (!after.isFile() || after.isSymbolicLink() || !beforeIdentity || !hasUsableInode(afterIdentity) || !sameIdentity(beforeIdentity, identity6) || !sameIdentity(identity6, afterIdentity)) return;
|
|
95605
95631
|
}
|
|
95606
|
-
|
|
95607
|
-
|
|
95632
|
+
fs43.ftruncateSync(descriptor, 0);
|
|
95633
|
+
fs43.fsyncSync(descriptor);
|
|
95608
95634
|
} catch {
|
|
95609
95635
|
} finally {
|
|
95610
95636
|
if (descriptor !== null) {
|
|
95611
95637
|
try {
|
|
95612
|
-
|
|
95638
|
+
fs43.closeSync(descriptor);
|
|
95613
95639
|
} catch {
|
|
95614
95640
|
}
|
|
95615
95641
|
}
|
|
@@ -95656,16 +95682,16 @@ function parseControlState(value) {
|
|
|
95656
95682
|
}
|
|
95657
95683
|
function openControlStateForRead(statePath) {
|
|
95658
95684
|
if (process.platform === "win32") return openControlStateForReadOnWindows(statePath);
|
|
95659
|
-
const noFollow =
|
|
95685
|
+
const noFollow = fs43.constants.O_NOFOLLOW;
|
|
95660
95686
|
if (typeof noFollow !== "number" || noFollow === 0) {
|
|
95661
95687
|
throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NOFOLLOW \u5B89\u5168\u8BFB\u53D6");
|
|
95662
95688
|
}
|
|
95663
|
-
const nonBlock =
|
|
95689
|
+
const nonBlock = fs43.constants.O_NONBLOCK;
|
|
95664
95690
|
if (typeof nonBlock !== "number" || nonBlock === 0) {
|
|
95665
95691
|
throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NONBLOCK \u5B89\u5168\u8BFB\u53D6");
|
|
95666
95692
|
}
|
|
95667
95693
|
try {
|
|
95668
|
-
return
|
|
95694
|
+
return fs43.openSync(statePath, fs43.constants.O_RDONLY | noFollow | nonBlock);
|
|
95669
95695
|
} catch (error2) {
|
|
95670
95696
|
if (error2.code === "ELOOP") {
|
|
95671
95697
|
throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
|
|
@@ -95674,14 +95700,14 @@ function openControlStateForRead(statePath) {
|
|
|
95674
95700
|
}
|
|
95675
95701
|
}
|
|
95676
95702
|
function openControlStateForReadOnWindows(statePath) {
|
|
95677
|
-
const before =
|
|
95703
|
+
const before = fs43.lstatSync(statePath, { bigint: true });
|
|
95678
95704
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
95679
95705
|
throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
|
|
95680
95706
|
}
|
|
95681
|
-
const descriptor =
|
|
95707
|
+
const descriptor = fs43.openSync(statePath, fs43.constants.O_RDONLY);
|
|
95682
95708
|
try {
|
|
95683
|
-
const opened =
|
|
95684
|
-
const after =
|
|
95709
|
+
const opened = fs43.fstatSync(descriptor, { bigint: true });
|
|
95710
|
+
const after = fs43.lstatSync(statePath, { bigint: true });
|
|
95685
95711
|
const beforeIdentity = identityFromStats(before);
|
|
95686
95712
|
const openedIdentity = identityFromStats(opened);
|
|
95687
95713
|
const afterIdentity = identityFromStats(after);
|
|
@@ -95690,7 +95716,7 @@ function openControlStateForReadOnWindows(statePath) {
|
|
|
95690
95716
|
}
|
|
95691
95717
|
return descriptor;
|
|
95692
95718
|
} catch (error2) {
|
|
95693
|
-
|
|
95719
|
+
fs43.closeSync(descriptor);
|
|
95694
95720
|
throw error2;
|
|
95695
95721
|
}
|
|
95696
95722
|
}
|
|
@@ -96132,9 +96158,9 @@ var init_direct2 = __esm({
|
|
|
96132
96158
|
});
|
|
96133
96159
|
|
|
96134
96160
|
// apps/desktop/src/cli/commands/events.ts
|
|
96135
|
-
import
|
|
96161
|
+
import path69 from "node:path";
|
|
96136
96162
|
function normalizedProjectRoot(value) {
|
|
96137
|
-
return typeof value === "string" && value.length > 0 ?
|
|
96163
|
+
return typeof value === "string" && value.length > 0 ? path69.resolve(value) : null;
|
|
96138
96164
|
}
|
|
96139
96165
|
function toOutputEvent(event) {
|
|
96140
96166
|
if (event.ok === true && typeof event.schemaVersion === "number") {
|
|
@@ -96518,7 +96544,7 @@ var init_state2 = __esm({
|
|
|
96518
96544
|
});
|
|
96519
96545
|
|
|
96520
96546
|
// apps/desktop/src/cli/commands/threads.ts
|
|
96521
|
-
import
|
|
96547
|
+
import path70 from "node:path";
|
|
96522
96548
|
function readPositiveInteger2(value, name2, fallback) {
|
|
96523
96549
|
if (value === void 0) {
|
|
96524
96550
|
return fallback;
|
|
@@ -96536,7 +96562,7 @@ async function runThreadsCommand(args, options = {}) {
|
|
|
96536
96562
|
const pageSize = readPositiveInteger2(args.flags.pageSize ?? args.flags.limit, "--page-size", 100);
|
|
96537
96563
|
const maxPages = readPositiveInteger2(args.flags.maxPages, "--max-pages", 20);
|
|
96538
96564
|
const cursor = typeof args.flags.cursor === "string" && args.flags.cursor.length > 0 ? args.flags.cursor : null;
|
|
96539
|
-
const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ?
|
|
96565
|
+
const projectRoot = typeof args.flags.project === "string" && args.flags.project.length > 0 ? path70.resolve(args.flags.project) : null;
|
|
96540
96566
|
const daemon = options.daemonClient ?? new DaemonClient(options.socketPath);
|
|
96541
96567
|
const result = await daemon.request("threads/list", {
|
|
96542
96568
|
pageSize,
|