niuma-codex 0.0.1-beta.22 → 0.0.1-beta.24
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 +806 -759
- package/dist/managed-tauri.js +41 -20
- package/dist/managed.js +41 -20
- package/package.json +1 -2
- package/resources/lite-release.json +0 -23
- package/resources/niuma-daemon-arm64.tgz +0 -0
- package/resources/niuma-lite-arm64.dmg +0 -0
package/dist/cli.js
CHANGED
|
@@ -378,6 +378,7 @@ var init_app_bundle = __esm({
|
|
|
378
378
|
|
|
379
379
|
// apps/desktop/src/autostart/manager.ts
|
|
380
380
|
import fs4 from "node:fs";
|
|
381
|
+
import { isDeepStrictEqual } from "node:util";
|
|
381
382
|
import fsp2 from "node:fs/promises";
|
|
382
383
|
import path4 from "node:path";
|
|
383
384
|
import os from "node:os";
|
|
@@ -553,7 +554,7 @@ var init_manager = __esm({
|
|
|
553
554
|
await privateDirectory(this.root);
|
|
554
555
|
const release2 = acquire(path4.join(this.root, "operation.lock"));
|
|
555
556
|
const snapshot2 = async () => {
|
|
556
|
-
if (await
|
|
557
|
+
if (!await this.finishSettledTransaction()) throw new AutostartError(900615, "npm \u81EA\u542F\u52A8\u6709\u672A\u5B8C\u6210\u4E8B\u52A1\uFF0C\u8BF7\u5148\u4FEE\u590D");
|
|
557
558
|
const registration = await readJson(this.metadata);
|
|
558
559
|
const status2 = await this.status();
|
|
559
560
|
const fingerprint2 = createHash2("sha256").update(JSON.stringify({ registration, loaded: status2.loaded, available: status2.available })).digest("hex");
|
|
@@ -616,8 +617,28 @@ var init_manager = __esm({
|
|
|
616
617
|
if (status2.operation?.state === "failed") throw new AutostartError(status2.operation.code, status2.operation.message);
|
|
617
618
|
return status2;
|
|
618
619
|
}
|
|
620
|
+
/** 调用者持有 operation.lock;仅收尾已恢复的同配置原生登记,不改变系统开关。 */
|
|
621
|
+
async finishSettledTransaction() {
|
|
622
|
+
const file = path4.join(this.root, "transaction.json");
|
|
623
|
+
const t2 = await readJson(file);
|
|
624
|
+
if (!t2) return true;
|
|
625
|
+
const previous = t2.previous;
|
|
626
|
+
if (t2.owner !== "niuma-autostart-v1" || !previous || previous.owner !== "niuma-autostart-v1" || previous.service !== "application-agent" || !previous.appPath || (t2.wasRegistered ?? t2.wasLoaded) !== true || !isDeepStrictEqual(previous, t2.next) || !isDeepStrictEqual(previous, await readJson(this.metadata))) return false;
|
|
627
|
+
try {
|
|
628
|
+
await fsp2.lstat(this.plist);
|
|
629
|
+
return false;
|
|
630
|
+
} catch (e) {
|
|
631
|
+
if (e.code !== "ENOENT") throw e;
|
|
632
|
+
}
|
|
633
|
+
const state = await this.registrationState(previous);
|
|
634
|
+
if (state !== 1 && state !== 2) return false;
|
|
635
|
+
if (!isDeepStrictEqual(t2, await readJson(file))) return false;
|
|
636
|
+
await fsp2.rm(file);
|
|
637
|
+
return true;
|
|
638
|
+
}
|
|
619
639
|
/** 注册文件和元数据的两次写入由恢复记录覆盖,崩溃后只恢复可证明自有的内容。 */
|
|
620
640
|
async recoverTransaction() {
|
|
641
|
+
if (await this.finishSettledTransaction()) return;
|
|
621
642
|
const file = path4.join(this.root, "transaction.json");
|
|
622
643
|
const transaction = await readJson(file);
|
|
623
644
|
if (!transaction) return;
|
|
@@ -677,7 +698,7 @@ var init_manager = __esm({
|
|
|
677
698
|
const appPath = await prepareAutostartApp(this.root, config, installed.entryPath);
|
|
678
699
|
await this.options.guard?.();
|
|
679
700
|
next = { owner: "niuma-autostart-v1", service: "application-agent", config, entryPath: installed.entryPath, appPath, plist: renderLaunchAgent(config, installed.entryPath, this.root, true) };
|
|
680
|
-
if (reusable
|
|
701
|
+
if ((reusable || priorState === 2) && isDeepStrictEqual(previous, next)) {
|
|
681
702
|
await this.run(LSREGISTER, ["-f", appPath]);
|
|
682
703
|
return;
|
|
683
704
|
}
|
|
@@ -3541,6 +3562,58 @@ var init_app_validation = __esm({
|
|
|
3541
3562
|
}
|
|
3542
3563
|
});
|
|
3543
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
|
+
|
|
3544
3617
|
// apps/desktop/src/lite-install/lifecycle.ts
|
|
3545
3618
|
async function switchNpmDaemon(o) {
|
|
3546
3619
|
const before = await o.read();
|
|
@@ -5398,11 +5471,11 @@ function token(value) {
|
|
|
5398
5471
|
function size(kind, bytes3) {
|
|
5399
5472
|
return (kind === "image" || kind === "file") && integer(bytes3, kind === "image" ? 20971520 : 52428800, kind === "image" ? 1 : 0);
|
|
5400
5473
|
}
|
|
5401
|
-
function dataUrl(value,
|
|
5474
|
+
function dataUrl(value, path71) {
|
|
5402
5475
|
if (typeof value !== "string") return false;
|
|
5403
5476
|
try {
|
|
5404
5477
|
const u = new URL(value);
|
|
5405
|
-
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));
|
|
5406
5479
|
} catch {
|
|
5407
5480
|
return false;
|
|
5408
5481
|
}
|
|
@@ -10232,7 +10305,7 @@ var init_src = __esm({
|
|
|
10232
10305
|
// apps/desktop/src/release-version.ts
|
|
10233
10306
|
import { readFileSync } from "node:fs";
|
|
10234
10307
|
function desktopReleaseVersion() {
|
|
10235
|
-
return false ? null : "0.0.1-beta.
|
|
10308
|
+
return false ? null : "0.0.1-beta.24";
|
|
10236
10309
|
}
|
|
10237
10310
|
function desktopPresenceVersion() {
|
|
10238
10311
|
return desktopReleaseVersion() ?? sourcePresenceVersion;
|
|
@@ -10423,7 +10496,7 @@ var init_sse_client = __esm({
|
|
|
10423
10496
|
});
|
|
10424
10497
|
|
|
10425
10498
|
// apps/desktop/src/notifications/server-client.ts
|
|
10426
|
-
import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as
|
|
10499
|
+
import { createHash as createHash4, randomBytes as randomBytes2, randomUUID as randomUUID7 } from "node:crypto";
|
|
10427
10500
|
function invalidPushServerOrigin() {
|
|
10428
10501
|
return new NiumaError(
|
|
10429
10502
|
"INVALID_ARGUMENT",
|
|
@@ -10508,11 +10581,11 @@ var init_server_client = __esm({
|
|
|
10508
10581
|
if (data.binding_revision !== snapshot2.binding_revision) throw new NotificationTransportError("invalid_response");
|
|
10509
10582
|
return { binding_revision: snapshot2.binding_revision };
|
|
10510
10583
|
}
|
|
10511
|
-
async signedPost(
|
|
10584
|
+
async signedPost(path71, input, signal, method2 = "POST") {
|
|
10512
10585
|
if (!this.identity || !this.serverOrigin.startsWith("https://")) throw new NotificationTransportError("business_error", 200, 200004);
|
|
10513
|
-
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}`;
|
|
10514
10587
|
const key_id = createHash4("sha256").update(this.identity.identity_public_key).digest("base64url");
|
|
10515
|
-
const operation_id =
|
|
10588
|
+
const operation_id = randomUUID7(), nonce = encodeBase64Url(randomBytes2(32)), timestamp = Math.floor(Date.now() / 1e3);
|
|
10516
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 });
|
|
10517
10590
|
let response;
|
|
10518
10591
|
try {
|
|
@@ -10546,71 +10619,71 @@ var init_managed_owner = __esm({
|
|
|
10546
10619
|
});
|
|
10547
10620
|
|
|
10548
10621
|
// apps/desktop/src/platform/posix-runtime-lock.ts
|
|
10549
|
-
import { randomUUID as
|
|
10550
|
-
import
|
|
10551
|
-
import
|
|
10622
|
+
import { randomUUID as randomUUID8 } from "node:crypto";
|
|
10623
|
+
import fs20 from "node:fs";
|
|
10624
|
+
import path24 from "node:path";
|
|
10552
10625
|
function publishDaemonLock(lockPath) {
|
|
10553
|
-
const token3 =
|
|
10554
|
-
const temporaryPath =
|
|
10555
|
-
|
|
10556
|
-
`.${
|
|
10626
|
+
const token3 = randomUUID8();
|
|
10627
|
+
const temporaryPath = path24.join(
|
|
10628
|
+
path24.dirname(lockPath),
|
|
10629
|
+
`.${path24.basename(lockPath)}.${randomUUID8()}.tmp`
|
|
10557
10630
|
);
|
|
10558
10631
|
let descriptor = null;
|
|
10559
10632
|
try {
|
|
10560
|
-
descriptor =
|
|
10561
|
-
const stats =
|
|
10633
|
+
descriptor = fs20.openSync(temporaryPath, "wx", 384);
|
|
10634
|
+
const stats = fs20.fstatSync(descriptor);
|
|
10562
10635
|
if (!stats.isFile()) {
|
|
10563
10636
|
throw new Error("daemon \u9501\u4E34\u65F6\u6587\u4EF6\u5FC5\u987B\u662F\u666E\u901A\u6587\u4EF6");
|
|
10564
10637
|
}
|
|
10565
|
-
|
|
10566
|
-
|
|
10567
|
-
|
|
10638
|
+
fs20.writeFileSync(descriptor, JSON.stringify({ token: token3, pid: process.pid }), "utf8");
|
|
10639
|
+
fs20.fchmodSync(descriptor, 384);
|
|
10640
|
+
fs20.closeSync(descriptor);
|
|
10568
10641
|
descriptor = null;
|
|
10569
|
-
|
|
10642
|
+
fs20.linkSync(temporaryPath, lockPath);
|
|
10570
10643
|
} catch (error2) {
|
|
10571
10644
|
if (descriptor !== null) {
|
|
10572
10645
|
try {
|
|
10573
|
-
|
|
10646
|
+
fs20.closeSync(descriptor);
|
|
10574
10647
|
} catch {
|
|
10575
10648
|
}
|
|
10576
10649
|
}
|
|
10577
10650
|
try {
|
|
10578
|
-
|
|
10651
|
+
fs20.unlinkSync(temporaryPath);
|
|
10579
10652
|
} catch {
|
|
10580
10653
|
}
|
|
10581
10654
|
throw error2;
|
|
10582
10655
|
}
|
|
10583
10656
|
try {
|
|
10584
|
-
|
|
10657
|
+
fs20.unlinkSync(temporaryPath);
|
|
10585
10658
|
} catch {
|
|
10586
10659
|
}
|
|
10587
10660
|
return {
|
|
10588
10661
|
token: token3,
|
|
10589
10662
|
release: () => {
|
|
10590
|
-
const snapshotPath =
|
|
10591
|
-
|
|
10592
|
-
`.${
|
|
10663
|
+
const snapshotPath = path24.join(
|
|
10664
|
+
path24.dirname(lockPath),
|
|
10665
|
+
`.${path24.basename(lockPath)}.${randomUUID8()}.snapshot`
|
|
10593
10666
|
);
|
|
10594
10667
|
try {
|
|
10595
|
-
|
|
10668
|
+
fs20.linkSync(lockPath, snapshotPath);
|
|
10596
10669
|
} catch {
|
|
10597
10670
|
return;
|
|
10598
10671
|
}
|
|
10599
10672
|
try {
|
|
10600
|
-
const current2 = JSON.parse(
|
|
10673
|
+
const current2 = JSON.parse(fs20.readFileSync(snapshotPath, "utf8"));
|
|
10601
10674
|
if (current2.token !== token3) {
|
|
10602
10675
|
return;
|
|
10603
10676
|
}
|
|
10604
|
-
const snapshotStats =
|
|
10605
|
-
const canonicalStats =
|
|
10677
|
+
const snapshotStats = fs20.lstatSync(snapshotPath);
|
|
10678
|
+
const canonicalStats = fs20.lstatSync(lockPath);
|
|
10606
10679
|
if (!snapshotStats.isFile() || !canonicalStats.isFile() || canonicalStats.dev !== snapshotStats.dev || canonicalStats.ino !== snapshotStats.ino) {
|
|
10607
10680
|
return;
|
|
10608
10681
|
}
|
|
10609
|
-
|
|
10682
|
+
fs20.unlinkSync(lockPath);
|
|
10610
10683
|
} catch {
|
|
10611
10684
|
} finally {
|
|
10612
10685
|
try {
|
|
10613
|
-
|
|
10686
|
+
fs20.unlinkSync(snapshotPath);
|
|
10614
10687
|
} catch {
|
|
10615
10688
|
}
|
|
10616
10689
|
}
|
|
@@ -10625,8 +10698,8 @@ var init_posix_runtime_lock = __esm({
|
|
|
10625
10698
|
|
|
10626
10699
|
// apps/desktop/src/platform/windows-runtime-lock.ts
|
|
10627
10700
|
import { spawn } from "node:child_process";
|
|
10628
|
-
import { randomUUID as
|
|
10629
|
-
import
|
|
10701
|
+
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
10702
|
+
import path25 from "node:path";
|
|
10630
10703
|
async function acquireWindowsRuntimeLease(lockPath, options = {}) {
|
|
10631
10704
|
const now = options.now ?? Date.now;
|
|
10632
10705
|
const assertPending = () => {
|
|
@@ -10634,9 +10707,9 @@ async function acquireWindowsRuntimeLease(lockPath, options = {}) {
|
|
|
10634
10707
|
};
|
|
10635
10708
|
assertPending();
|
|
10636
10709
|
const file = localWindowsPath(lockPath);
|
|
10637
|
-
ensureWindowsPrivateDirectory(
|
|
10710
|
+
ensureWindowsPrivateDirectory(path25.dirname(file));
|
|
10638
10711
|
assertPending();
|
|
10639
|
-
const token3 =
|
|
10712
|
+
const token3 = randomUUID9();
|
|
10640
10713
|
const child = spawn(windowsPowerShell(), windowsScriptArgs(WINDOWS_RUNTIME_LOCK_SCRIPT), {
|
|
10641
10714
|
env: { ...process.env, NIUMA_NATIVE_PATH: file, NIUMA_NATIVE_BODY: JSON.stringify({ token: token3, pid: process.pid }) },
|
|
10642
10715
|
windowsHide: true,
|
|
@@ -10744,11 +10817,11 @@ try {
|
|
|
10744
10817
|
});
|
|
10745
10818
|
|
|
10746
10819
|
// apps/desktop/src/platform/runtime-lock.ts
|
|
10747
|
-
import
|
|
10748
|
-
import
|
|
10820
|
+
import fs21 from "node:fs";
|
|
10821
|
+
import path26 from "node:path";
|
|
10749
10822
|
function ensureRuntimeLeaseDirectory(lockPath) {
|
|
10750
|
-
if (desktopPlatform().id === "windows") ensureWindowsPrivateDirectory(
|
|
10751
|
-
else
|
|
10823
|
+
if (desktopPlatform().id === "windows") ensureWindowsPrivateDirectory(path26.dirname(lockPath));
|
|
10824
|
+
else fs21.mkdirSync(path26.dirname(lockPath), { recursive: true, mode: 448 });
|
|
10752
10825
|
}
|
|
10753
10826
|
async function acquireRuntimeLease(lockPath, options = {}) {
|
|
10754
10827
|
if (desktopPlatform().id === "windows") return acquireWindowsRuntimeLease(lockPath, options);
|
|
@@ -10968,7 +11041,7 @@ var init_startup_coordinator = __esm({
|
|
|
10968
11041
|
|
|
10969
11042
|
// apps/desktop/src/daemon/error-log.ts
|
|
10970
11043
|
import { z } from "zod";
|
|
10971
|
-
import
|
|
11044
|
+
import path27 from "node:path";
|
|
10972
11045
|
function writeErrorAuditBestEffort(logger, entry) {
|
|
10973
11046
|
try {
|
|
10974
11047
|
logger?.write(entry);
|
|
@@ -11167,7 +11240,7 @@ function createLogFile(errorsDir, now, files) {
|
|
|
11167
11240
|
const timestamp = now.toISOString().replace(/[:.]/g, "-");
|
|
11168
11241
|
for (let index = 0; ; index += 1) {
|
|
11169
11242
|
const suffix = index === 0 ? "" : `-${index}`;
|
|
11170
|
-
const filePath =
|
|
11243
|
+
const filePath = path27.join(errorsDir, `${timestamp}-${process.pid}${suffix}.ndjson`);
|
|
11171
11244
|
try {
|
|
11172
11245
|
return files.create(filePath);
|
|
11173
11246
|
} catch (error2) {
|
|
@@ -11181,7 +11254,7 @@ function createErrorAuditLogger(options = {}) {
|
|
|
11181
11254
|
if (!isSafeInteger(maxBytes, 1)) throw new NiumaError("INVALID_ARGUMENT", "\u9519\u8BEF\u5BA1\u8BA1\u65E5\u5FD7\u5BB9\u91CF\u5FC5\u987B\u662F\u6B63\u6574\u6570");
|
|
11182
11255
|
const runtimeDir = options.runtimeDir ?? ensureDaemonRuntimeDir();
|
|
11183
11256
|
const files = options.files ?? privateLogFiles;
|
|
11184
|
-
const errorsDir =
|
|
11257
|
+
const errorsDir = path27.join(runtimeDir, "errors");
|
|
11185
11258
|
files.ensureDirectory(errorsDir);
|
|
11186
11259
|
cleanupExpiredDaemonLogs({ runtimeDir, files, now: () => now().getTime() });
|
|
11187
11260
|
let currentFile = createLogFile(errorsDir, now(), files);
|
|
@@ -11634,13 +11707,13 @@ var init_error_log = __esm({
|
|
|
11634
11707
|
});
|
|
11635
11708
|
|
|
11636
11709
|
// apps/desktop/src/appserver/startup-failure.ts
|
|
11637
|
-
import { randomUUID as
|
|
11710
|
+
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
11638
11711
|
import { z as z2 } from "zod";
|
|
11639
11712
|
function codexStartupFailure(reason, logger) {
|
|
11640
11713
|
const error2 = new NiumaError(reason === "missing" ? "CODEX_NOT_FOUND" : "APP_SERVER_START_FAILED", MESSAGES[reason], { reason });
|
|
11641
11714
|
if (logger) writeErrorAuditBestEffort(logger, {
|
|
11642
11715
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11643
|
-
failureId: `fail_${
|
|
11716
|
+
failureId: `fail_${randomUUID10()}`,
|
|
11644
11717
|
service: "desktop",
|
|
11645
11718
|
component: "app_server",
|
|
11646
11719
|
channel: "internal",
|
|
@@ -11654,7 +11727,7 @@ function codexStartupFailure(reason, logger) {
|
|
|
11654
11727
|
function auditCodexStartupCleanupFailure(logger) {
|
|
11655
11728
|
writeErrorAuditBestEffort(logger, {
|
|
11656
11729
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
11657
|
-
failureId: `fail_${
|
|
11730
|
+
failureId: `fail_${randomUUID10()}`,
|
|
11658
11731
|
service: "desktop",
|
|
11659
11732
|
component: "app_server",
|
|
11660
11733
|
channel: "internal",
|
|
@@ -11718,9 +11791,9 @@ var init_startup_failure = __esm({
|
|
|
11718
11791
|
|
|
11719
11792
|
// apps/desktop/src/platform/windows-port-owner.ts
|
|
11720
11793
|
import { execFile as execFile4 } from "node:child_process";
|
|
11721
|
-
import
|
|
11794
|
+
import path28 from "node:path";
|
|
11722
11795
|
function execute(file, args) {
|
|
11723
|
-
const executable =
|
|
11796
|
+
const executable = path28.join(process.env.SystemRoot ?? "C:\\Windows", "System32", file);
|
|
11724
11797
|
return new Promise((resolve5, reject3) => execFile4(executable, [...args], {
|
|
11725
11798
|
windowsHide: true,
|
|
11726
11799
|
encoding: "utf8",
|
|
@@ -12206,8 +12279,8 @@ var init_config = __esm({
|
|
|
12206
12279
|
|
|
12207
12280
|
// apps/desktop/src/daemon/launcher.ts
|
|
12208
12281
|
import { spawn as spawn2 } from "node:child_process";
|
|
12209
|
-
import
|
|
12210
|
-
import
|
|
12282
|
+
import fs22 from "node:fs";
|
|
12283
|
+
import path29 from "node:path";
|
|
12211
12284
|
function daemonStartFailed() {
|
|
12212
12285
|
return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
|
|
12213
12286
|
}
|
|
@@ -12233,9 +12306,9 @@ function currentCliScriptPath() {
|
|
|
12233
12306
|
const scriptPath = process.argv[1];
|
|
12234
12307
|
if (!scriptPath) return null;
|
|
12235
12308
|
try {
|
|
12236
|
-
return
|
|
12309
|
+
return fs22.realpathSync(scriptPath);
|
|
12237
12310
|
} catch {
|
|
12238
|
-
return
|
|
12311
|
+
return path29.resolve(scriptPath);
|
|
12239
12312
|
}
|
|
12240
12313
|
}
|
|
12241
12314
|
function isNiumaBackgroundWorkerCommand(commandLine) {
|
|
@@ -12309,7 +12382,7 @@ function spawnBackgroundWorker(input) {
|
|
|
12309
12382
|
if (!command) {
|
|
12310
12383
|
throw new Error("daemon worker \u7F3A\u5C11\u542F\u52A8\u547D\u4EE4");
|
|
12311
12384
|
}
|
|
12312
|
-
const descriptor =
|
|
12385
|
+
const descriptor = fs22.openSync(input.logPath, "a", 384);
|
|
12313
12386
|
try {
|
|
12314
12387
|
const child = spawn2(command, argv, {
|
|
12315
12388
|
detached: input.detached,
|
|
@@ -12344,7 +12417,7 @@ function spawnBackgroundWorker(input) {
|
|
|
12344
12417
|
}
|
|
12345
12418
|
})() };
|
|
12346
12419
|
} finally {
|
|
12347
|
-
|
|
12420
|
+
fs22.closeSync(descriptor);
|
|
12348
12421
|
}
|
|
12349
12422
|
}
|
|
12350
12423
|
function consumeBackgroundWorkerCapability(env = process.env, lockPath = daemonLaunchLockPath()) {
|
|
@@ -12355,7 +12428,7 @@ function consumeBackgroundWorkerCapability(env = process.env, lockPath = daemonL
|
|
|
12355
12428
|
}
|
|
12356
12429
|
try {
|
|
12357
12430
|
validateRuntimeOwnedFile(lockPath);
|
|
12358
|
-
const lock = JSON.parse(
|
|
12431
|
+
const lock = JSON.parse(fs22.readFileSync(lockPath, "utf8"));
|
|
12359
12432
|
return typeof lock.token === "string" && lock.token === capability;
|
|
12360
12433
|
} catch {
|
|
12361
12434
|
return false;
|
|
@@ -13283,11 +13356,11 @@ var init_runtime_version = __esm({
|
|
|
13283
13356
|
retryAt = 0;
|
|
13284
13357
|
pending = null;
|
|
13285
13358
|
controller = null;
|
|
13286
|
-
setConnection(
|
|
13359
|
+
setConnection(path71) {
|
|
13287
13360
|
this.epoch++;
|
|
13288
13361
|
this.controller?.abort();
|
|
13289
13362
|
this.controller = null;
|
|
13290
|
-
this.path =
|
|
13363
|
+
this.path = path71;
|
|
13291
13364
|
this.value = null;
|
|
13292
13365
|
this.pending = null;
|
|
13293
13366
|
this.retryAt = 0;
|
|
@@ -13379,8 +13452,8 @@ var init_private_journal_types = __esm({
|
|
|
13379
13452
|
|
|
13380
13453
|
// apps/desktop/src/platform/windows-private-journal.ts
|
|
13381
13454
|
import { spawn as spawn3 } from "node:child_process";
|
|
13382
|
-
import
|
|
13383
|
-
import
|
|
13455
|
+
import fs23 from "node:fs";
|
|
13456
|
+
import path30 from "node:path";
|
|
13384
13457
|
async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
13385
13458
|
const maxSupportedBytes = (options.discardPreviousSnapshots ? 32 : 16) * 1024 * 1024;
|
|
13386
13459
|
const lockWaitMs = options.lockWaitMs ?? 0;
|
|
@@ -13391,10 +13464,10 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13391
13464
|
let directory3;
|
|
13392
13465
|
try {
|
|
13393
13466
|
file = localWindowsPath(filePath);
|
|
13394
|
-
directory3 = await ensureWindowsPrivateDirectoryAsync(
|
|
13395
|
-
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`)]) {
|
|
13396
13469
|
try {
|
|
13397
|
-
const stats =
|
|
13470
|
+
const stats = fs23.lstatSync(candidate, { bigint: true });
|
|
13398
13471
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n) throw new PrivateJournalError("unavailable");
|
|
13399
13472
|
if ((candidate === file || candidate === `${file}-journal`) && stats.size > BigInt(3 * maxBytes + 524288)) throw new PrivateJournalError("capacity");
|
|
13400
13473
|
} catch (error2) {
|
|
@@ -13404,7 +13477,7 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13404
13477
|
} catch (error2) {
|
|
13405
13478
|
throw error2 instanceof PrivateJournalError ? error2 : new PrivateJournalError("unavailable");
|
|
13406
13479
|
}
|
|
13407
|
-
const directoryIdentity2 =
|
|
13480
|
+
const directoryIdentity2 = fs23.lstatSync(directory3, { bigint: true });
|
|
13408
13481
|
const child = spawn3(windowsPowerShell(), windowsScriptArgs("& ([ScriptBlock]::Create($env:NIUMA_JOURNAL_SCRIPT))"), {
|
|
13409
13482
|
env: {
|
|
13410
13483
|
...process.env,
|
|
@@ -13496,8 +13569,8 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13496
13569
|
let identity6;
|
|
13497
13570
|
function verify() {
|
|
13498
13571
|
if (closing || exited || poisoned) throw unavailable12();
|
|
13499
|
-
const dir =
|
|
13500
|
-
const current2 =
|
|
13572
|
+
const dir = fs23.lstatSync(directory3, { bigint: true });
|
|
13573
|
+
const current2 = fs23.lstatSync(file, { bigint: true });
|
|
13501
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()) {
|
|
13502
13575
|
poisoned = true;
|
|
13503
13576
|
throw unavailable12();
|
|
@@ -13505,7 +13578,7 @@ async function openWindowsPrivateJournal(filePath, maxBytes, options = {}) {
|
|
|
13505
13578
|
}
|
|
13506
13579
|
try {
|
|
13507
13580
|
if (await response() !== "ready") throw unavailable12();
|
|
13508
|
-
identity6 =
|
|
13581
|
+
identity6 = fs23.lstatSync(file, { bigint: true });
|
|
13509
13582
|
verify();
|
|
13510
13583
|
} catch (error2) {
|
|
13511
13584
|
await close();
|
|
@@ -13739,9 +13812,9 @@ try {
|
|
|
13739
13812
|
});
|
|
13740
13813
|
|
|
13741
13814
|
// apps/desktop/src/platform/private-journal.ts
|
|
13742
|
-
import
|
|
13743
|
-
import
|
|
13744
|
-
import { randomUUID as
|
|
13815
|
+
import fs24 from "node:fs";
|
|
13816
|
+
import path31 from "node:path";
|
|
13817
|
+
import { randomUUID as randomUUID11 } from "node:crypto";
|
|
13745
13818
|
function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
13746
13819
|
const policy = platform2.privateJournal;
|
|
13747
13820
|
if (platform2.nodePlatform !== process.platform || platform2.capabilities.submissionJournal !== "implemented") {
|
|
@@ -13749,9 +13822,9 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13749
13822
|
}
|
|
13750
13823
|
if (platform2.id === "windows") return openWindowsPrivateJournal(filePath, maxBytes);
|
|
13751
13824
|
if (policy.lockFlags === null) throw new PrivateJournalError("unavailable");
|
|
13752
|
-
const file =
|
|
13753
|
-
const directory3 =
|
|
13754
|
-
const lockPath =
|
|
13825
|
+
const file = path31.resolve(filePath);
|
|
13826
|
+
const directory3 = path31.dirname(file);
|
|
13827
|
+
const lockPath = path31.join(directory3, `.${path31.basename(file)}.lock`);
|
|
13755
13828
|
let directoryFd;
|
|
13756
13829
|
let lockFd;
|
|
13757
13830
|
let fileStat = null;
|
|
@@ -13761,11 +13834,11 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13761
13834
|
const trusted5 = (stats, directory4 = false) => policy.trustedNode(stats, directory4);
|
|
13762
13835
|
function verifyOwnership() {
|
|
13763
13836
|
if (closed || poisoned) throw new PrivateJournalError("unavailable");
|
|
13764
|
-
const dir =
|
|
13765
|
-
const lock =
|
|
13766
|
-
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");
|
|
13767
13840
|
try {
|
|
13768
|
-
const current2 =
|
|
13841
|
+
const current2 = fs24.lstatSync(file);
|
|
13769
13842
|
if (!trusted5(current2) || fileStat === null || !sameFile(current2, fileStat)) throw new PrivateJournalError("unavailable");
|
|
13770
13843
|
} catch (error2) {
|
|
13771
13844
|
if (error2.code !== "ENOENT" || fileStat !== null) throw error2;
|
|
@@ -13774,29 +13847,29 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13774
13847
|
function close() {
|
|
13775
13848
|
closed = true;
|
|
13776
13849
|
try {
|
|
13777
|
-
if (lockFd !== void 0)
|
|
13850
|
+
if (lockFd !== void 0) fs24.closeSync(lockFd);
|
|
13778
13851
|
} finally {
|
|
13779
13852
|
lockFd = void 0;
|
|
13780
13853
|
if (directoryFd !== void 0) {
|
|
13781
|
-
|
|
13854
|
+
fs24.closeSync(directoryFd);
|
|
13782
13855
|
directoryFd = void 0;
|
|
13783
13856
|
}
|
|
13784
13857
|
}
|
|
13785
13858
|
}
|
|
13786
13859
|
try {
|
|
13787
|
-
|
|
13788
|
-
if (!trusted5(
|
|
13789
|
-
directoryFd =
|
|
13790
|
-
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");
|
|
13791
13864
|
try {
|
|
13792
|
-
if (!trusted5(
|
|
13865
|
+
if (!trusted5(fs24.lstatSync(lockPath))) throw new PrivateJournalError("unavailable");
|
|
13793
13866
|
} catch (error2) {
|
|
13794
13867
|
if (error2.code !== "ENOENT") throw error2;
|
|
13795
13868
|
}
|
|
13796
|
-
lockFd =
|
|
13797
|
-
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");
|
|
13798
13871
|
try {
|
|
13799
|
-
fileStat =
|
|
13872
|
+
fileStat = fs24.lstatSync(file);
|
|
13800
13873
|
if (!trusted5(fileStat)) throw new PrivateJournalError("unavailable");
|
|
13801
13874
|
if (fileStat.size > maxBytes) throw new PrivateJournalError("capacity");
|
|
13802
13875
|
} catch (error2) {
|
|
@@ -13812,45 +13885,45 @@ function openPrivateJournal(filePath, maxBytes, platform2 = desktopPlatform()) {
|
|
|
13812
13885
|
read() {
|
|
13813
13886
|
verifyOwnership();
|
|
13814
13887
|
if (fileStat === null) return null;
|
|
13815
|
-
const fd =
|
|
13888
|
+
const fd = fs24.openSync(file, fs24.constants.O_RDONLY | fs24.constants.O_NOFOLLOW);
|
|
13816
13889
|
try {
|
|
13817
|
-
if (!trusted5(
|
|
13890
|
+
if (!trusted5(fs24.fstatSync(fd)) || !sameFile(fileStat, fs24.fstatSync(fd))) throw new PrivateJournalError("unavailable");
|
|
13818
13891
|
const buffer = Buffer.alloc(maxBytes + 1);
|
|
13819
|
-
const length =
|
|
13892
|
+
const length = fs24.readSync(fd, buffer, 0, buffer.length, 0);
|
|
13820
13893
|
if (length > maxBytes) throw new PrivateJournalError("capacity");
|
|
13821
13894
|
verifyOwnership();
|
|
13822
13895
|
return buffer.subarray(0, length).toString("utf8");
|
|
13823
13896
|
} finally {
|
|
13824
|
-
|
|
13897
|
+
fs24.closeSync(fd);
|
|
13825
13898
|
}
|
|
13826
13899
|
},
|
|
13827
13900
|
commit(body) {
|
|
13828
13901
|
if (Buffer.byteLength(body) > maxBytes) throw new PrivateJournalError("capacity");
|
|
13829
|
-
const temporary =
|
|
13902
|
+
const temporary = path31.join(directory3, `.${path31.basename(file)}.${randomUUID11()}.tmp`);
|
|
13830
13903
|
let created = false;
|
|
13831
13904
|
try {
|
|
13832
13905
|
verifyOwnership();
|
|
13833
|
-
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);
|
|
13834
13907
|
created = true;
|
|
13835
13908
|
try {
|
|
13836
|
-
if (!trusted5(
|
|
13837
|
-
|
|
13838
|
-
|
|
13909
|
+
if (!trusted5(fs24.fstatSync(fd))) throw new PrivateJournalError("unavailable");
|
|
13910
|
+
fs24.writeFileSync(fd, body, "utf8");
|
|
13911
|
+
fs24.fsyncSync(fd);
|
|
13839
13912
|
} finally {
|
|
13840
|
-
|
|
13913
|
+
fs24.closeSync(fd);
|
|
13841
13914
|
}
|
|
13842
13915
|
verifyOwnership();
|
|
13843
|
-
|
|
13916
|
+
fs24.renameSync(temporary, file);
|
|
13844
13917
|
created = false;
|
|
13845
|
-
fileStat =
|
|
13846
|
-
|
|
13918
|
+
fileStat = fs24.lstatSync(file);
|
|
13919
|
+
fs24.fsyncSync(directoryFd);
|
|
13847
13920
|
} catch {
|
|
13848
13921
|
poisoned = true;
|
|
13849
13922
|
throw new PrivateJournalError("write_failed");
|
|
13850
13923
|
} finally {
|
|
13851
13924
|
if (created) {
|
|
13852
13925
|
try {
|
|
13853
|
-
|
|
13926
|
+
fs24.unlinkSync(temporary);
|
|
13854
13927
|
} catch {
|
|
13855
13928
|
}
|
|
13856
13929
|
}
|
|
@@ -14198,20 +14271,20 @@ function sendJson(response, httpStatus, body) {
|
|
|
14198
14271
|
}
|
|
14199
14272
|
function zodErrorToHttpApiError(error2) {
|
|
14200
14273
|
const messages = error2.issues.map((issue) => {
|
|
14201
|
-
const
|
|
14274
|
+
const path71 = issue.path.join(".") || "\u53C2\u6570";
|
|
14202
14275
|
if (issue.code === "custom") {
|
|
14203
14276
|
return issue.message;
|
|
14204
14277
|
}
|
|
14205
14278
|
if (issue.code === "invalid_type" && issue.received === "undefined") {
|
|
14206
|
-
return `${
|
|
14279
|
+
return `${path71}\u4E0D\u80FD\u4E3A\u7A7A`;
|
|
14207
14280
|
}
|
|
14208
14281
|
if (issue.code === "invalid_type") {
|
|
14209
|
-
return `${
|
|
14282
|
+
return `${path71}\u7C7B\u578B\u9519\u8BEF`;
|
|
14210
14283
|
}
|
|
14211
14284
|
if (issue.code === "unrecognized_keys") {
|
|
14212
14285
|
return `\u4E0D\u652F\u6301\u7684\u53C2\u6570: ${issue.keys.join(",")}`;
|
|
14213
14286
|
}
|
|
14214
|
-
return `${
|
|
14287
|
+
return `${path71}\u683C\u5F0F\u9519\u8BEF`;
|
|
14215
14288
|
});
|
|
14216
14289
|
const custom = error2.issues.some((issue) => issue.code === "custom");
|
|
14217
14290
|
const missing4 = error2.issues.some(
|
|
@@ -14514,7 +14587,7 @@ var init_transfer_diagnostics = __esm({
|
|
|
14514
14587
|
});
|
|
14515
14588
|
|
|
14516
14589
|
// apps/desktop/src/attachments/transfer-registry.ts
|
|
14517
|
-
import { randomBytes as randomBytes3, randomUUID as
|
|
14590
|
+
import { randomBytes as randomBytes3, randomUUID as randomUUID12 } from "node:crypto";
|
|
14518
14591
|
function fail14(kind) {
|
|
14519
14592
|
const e = ATTACHMENT_TRANSFER_ERRORS[kind];
|
|
14520
14593
|
throw new AttachmentTransferError(e.code, e.message);
|
|
@@ -14683,7 +14756,7 @@ function createAttachmentTransferRegistry(options) {
|
|
|
14683
14756
|
recordAttachmentDiagnostic(options.diagnostic, { phase: "prepare", reason: active2.has(scope.bindingId) ? "active_stream" : "attempt_capacity", code: 400606 });
|
|
14684
14757
|
fail14("capacity");
|
|
14685
14758
|
}
|
|
14686
|
-
const expires = Math.min(scope.expiresAtMs, u.owner.expiresAtMs), transferId =
|
|
14759
|
+
const expires = Math.min(scope.expiresAtMs, u.owner.expiresAtMs), transferId = randomUUID12(), epochId = randomUUID12();
|
|
14687
14760
|
const secret = randomBytes3(32);
|
|
14688
14761
|
const encoded = encodeBase64Url(secret);
|
|
14689
14762
|
secret.fill(0);
|
|
@@ -15080,7 +15153,7 @@ var init_connection_handoff_source = __esm({
|
|
|
15080
15153
|
});
|
|
15081
15154
|
|
|
15082
15155
|
// apps/desktop/src/daemon/project-list-stream.ts
|
|
15083
|
-
import { randomUUID as
|
|
15156
|
+
import { randomUUID as randomUUID13 } from "node:crypto";
|
|
15084
15157
|
function createProjectListStreamHub(dependencies) {
|
|
15085
15158
|
const subscriptions = /* @__PURE__ */ new Map();
|
|
15086
15159
|
const sources = /* @__PURE__ */ new Map();
|
|
@@ -15092,7 +15165,7 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15092
15165
|
]);
|
|
15093
15166
|
const nextIds = visibleIds(next.snapshot);
|
|
15094
15167
|
const removed = [...visibleIds(state.source.current.snapshot.snapshot)].some((id5) => !nextIds.has(id5));
|
|
15095
|
-
if (state.handoff && removed) state.source.replaceEpoch(
|
|
15168
|
+
if (state.handoff && removed) state.source.replaceEpoch(randomUUID13(), next);
|
|
15096
15169
|
else state.source.publish(next);
|
|
15097
15170
|
};
|
|
15098
15171
|
const logProjection = (type, revision4, diagnostic) => {
|
|
@@ -15117,7 +15190,7 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15117
15190
|
}
|
|
15118
15191
|
};
|
|
15119
15192
|
const attach = (state, scope, send, kind) => {
|
|
15120
|
-
const subscriptionId =
|
|
15193
|
+
const subscriptionId = randomUUID13();
|
|
15121
15194
|
let revision4 = 0;
|
|
15122
15195
|
let initializing = true;
|
|
15123
15196
|
const pending = [];
|
|
@@ -15321,12 +15394,12 @@ function createProjectListStreamHub(dependencies) {
|
|
|
15321
15394
|
processEvent(state, event);
|
|
15322
15395
|
});
|
|
15323
15396
|
state.snapshot = readSnapshot(state);
|
|
15324
|
-
const sourceId =
|
|
15397
|
+
const sourceId = randomUUID13();
|
|
15325
15398
|
let unregister = () => {
|
|
15326
15399
|
};
|
|
15327
15400
|
state.source = new HandoffSource({
|
|
15328
15401
|
sourceId,
|
|
15329
|
-
epoch:
|
|
15402
|
+
epoch: randomUUID13(),
|
|
15330
15403
|
initial: { snapshot: state.snapshot, windows: {}, update: null },
|
|
15331
15404
|
onUnused: () => {
|
|
15332
15405
|
sources.delete(sourceId);
|
|
@@ -15579,7 +15652,7 @@ var init_project_list_stream = __esm({
|
|
|
15579
15652
|
});
|
|
15580
15653
|
|
|
15581
15654
|
// apps/desktop/src/daemon/thread-projection-publisher.ts
|
|
15582
|
-
import { isDeepStrictEqual } from "node:util";
|
|
15655
|
+
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
15583
15656
|
function clone2(value) {
|
|
15584
15657
|
return structuredClone(value);
|
|
15585
15658
|
}
|
|
@@ -15608,7 +15681,7 @@ function changesBetween(previous, next) {
|
|
|
15608
15681
|
];
|
|
15609
15682
|
for (const key of keys3) {
|
|
15610
15683
|
if (key === "execution" && next.execution === void 0) continue;
|
|
15611
|
-
if (!
|
|
15684
|
+
if (!isDeepStrictEqual2(previous[key], next[key])) {
|
|
15612
15685
|
changes[key] = clone2(next[key]);
|
|
15613
15686
|
}
|
|
15614
15687
|
}
|
|
@@ -15620,9 +15693,9 @@ function createThreadViewPatch(previous, next) {
|
|
|
15620
15693
|
const nextItems = itemMap(next.items);
|
|
15621
15694
|
const previousProcessGroups = processGroupMap(previous.process_groups);
|
|
15622
15695
|
const nextProcessGroups = processGroupMap(next.process_groups);
|
|
15623
|
-
const upsertItems = next.items.filter((item) => !
|
|
15696
|
+
const upsertItems = next.items.filter((item) => !isDeepStrictEqual2(previousItems.get(item.id), item));
|
|
15624
15697
|
const removeItemIds = previous.items.filter((item) => !nextItems.has(item.id)).map((item) => item.id);
|
|
15625
|
-
const upsertProcessGroups = next.process_groups.filter((group2) => !
|
|
15698
|
+
const upsertProcessGroups = next.process_groups.filter((group2) => !isDeepStrictEqual2(previousProcessGroups.get(group2.id), group2));
|
|
15626
15699
|
const removeProcessGroupIds = previous.process_groups.filter((group2) => !nextProcessGroups.has(group2.id)).map((group2) => group2.id);
|
|
15627
15700
|
const changes = changesBetween(previous, next);
|
|
15628
15701
|
if (Object.keys(changes).length === 0 && upsertItems.length === 0 && removeItemIds.length === 0 && upsertProcessGroups.length === 0 && removeProcessGroupIds.length === 0) {
|
|
@@ -15683,9 +15756,9 @@ function isRunningTextOnlyPatch(patch, previous, next) {
|
|
|
15683
15756
|
const { content: content2, updated_at, ...rest } = value;
|
|
15684
15757
|
return rest;
|
|
15685
15758
|
};
|
|
15686
|
-
if (!
|
|
15759
|
+
if (!isDeepStrictEqual2(withoutContent(oldItem), withoutContent(item))) return false;
|
|
15687
15760
|
const monotonicUpdatedAt2 = oldItem.updated_at === null || item.updated_at === null || item.updated_at >= oldItem.updated_at;
|
|
15688
|
-
return monotonicUpdatedAt2 && !
|
|
15761
|
+
return monotonicUpdatedAt2 && !isDeepStrictEqual2(oldItem.content, item.content) && next.revision === patch.revision;
|
|
15689
15762
|
}
|
|
15690
15763
|
var TEXT_DELTA_THROTTLE_MS, ThreadProjectionPublisher;
|
|
15691
15764
|
var init_thread_projection_publisher = __esm({
|
|
@@ -15889,7 +15962,7 @@ var init_thread_projection_publisher = __esm({
|
|
|
15889
15962
|
}
|
|
15890
15963
|
if (this.closed || !this.publication.latestView) return;
|
|
15891
15964
|
const next = this.currentView();
|
|
15892
|
-
if (!next || !this.publication.needsWindowSnapshot &&
|
|
15965
|
+
if (!next || !this.publication.needsWindowSnapshot && isDeepStrictEqual2({ ...next, revision: 0 }, { ...this.publication.latestView, revision: 0 })) return;
|
|
15893
15966
|
this.flushQueuedPatch();
|
|
15894
15967
|
this.publication.needsWindowSnapshot = false;
|
|
15895
15968
|
this.publication.latestView = clone2(next);
|
|
@@ -17660,7 +17733,7 @@ var init_routes = __esm({
|
|
|
17660
17733
|
});
|
|
17661
17734
|
|
|
17662
17735
|
// apps/desktop/src/http/sse.ts
|
|
17663
|
-
import { randomUUID as
|
|
17736
|
+
import { randomUUID as randomUUID14 } from "node:crypto";
|
|
17664
17737
|
function encodeSseFrame(frame) {
|
|
17665
17738
|
return [
|
|
17666
17739
|
...frame.id ? [`id: ${frame.id}`] : [],
|
|
@@ -17988,7 +18061,7 @@ var init_sse = __esm({
|
|
|
17988
18061
|
throw new HttpApiError(200, 400604, "SSE\u4EA4\u63A5\u5BB9\u91CF\u4E0D\u8DB3");
|
|
17989
18062
|
}
|
|
17990
18063
|
return Array.from({ length: count }, () => {
|
|
17991
|
-
const id5 =
|
|
18064
|
+
const id5 = randomUUID14();
|
|
17992
18065
|
this.reservedSlots.add(id5);
|
|
17993
18066
|
return { id: id5, release: () => {
|
|
17994
18067
|
this.reservedSlots.delete(id5);
|
|
@@ -18034,7 +18107,7 @@ var init_sse = __esm({
|
|
|
18034
18107
|
});
|
|
18035
18108
|
|
|
18036
18109
|
// apps/desktop/src/http/server.ts
|
|
18037
|
-
import { randomUUID as
|
|
18110
|
+
import { randomUUID as randomUUID15 } from "node:crypto";
|
|
18038
18111
|
import http from "node:http";
|
|
18039
18112
|
import { isIP as isIP3 } from "node:net";
|
|
18040
18113
|
function safeAuditIdentifier(value) {
|
|
@@ -18588,7 +18661,7 @@ var init_server = __esm({
|
|
|
18588
18661
|
try {
|
|
18589
18662
|
this.errorLogger?.write({
|
|
18590
18663
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
18591
|
-
failureId: diagnostic?.failureId ?? `fail_${
|
|
18664
|
+
failureId: diagnostic?.failureId ?? `fail_${randomUUID15()}`,
|
|
18592
18665
|
service: "desktop",
|
|
18593
18666
|
component: "gateway",
|
|
18594
18667
|
channel: request2.channel,
|
|
@@ -18783,7 +18856,7 @@ var init_args = __esm({
|
|
|
18783
18856
|
|
|
18784
18857
|
// apps/desktop/src/autostart/production.ts
|
|
18785
18858
|
import os5 from "node:os";
|
|
18786
|
-
import
|
|
18859
|
+
import path32 from "node:path";
|
|
18787
18860
|
function autostartConfig(args, relayOrigin) {
|
|
18788
18861
|
const version2 = desktopReleaseVersion();
|
|
18789
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");
|
|
@@ -18792,7 +18865,7 @@ function autostartConfig(args, relayOrigin) {
|
|
|
18792
18865
|
releaseVersion: version2,
|
|
18793
18866
|
nodeExecutable: process.execPath,
|
|
18794
18867
|
home: os5.homedir(),
|
|
18795
|
-
path: [
|
|
18868
|
+
path: [path32.dirname(process.execPath), process.env.PATH ?? "/usr/bin:/bin"].join(":"),
|
|
18796
18869
|
...process.env.CODEX_HOME ? { codexHome: process.env.CODEX_HOME } : {},
|
|
18797
18870
|
relayOrigin: resolveRelayConfig({ relay_origin: relayOrigin ?? resolveRelayStartupOrigin({ env: process.env, cliOrigin: args.flags.relayOrigin }) }).origin,
|
|
18798
18871
|
pushServerOrigin: resolvePushServerOrigin(process.env),
|
|
@@ -18857,19 +18930,19 @@ var init_production = __esm({
|
|
|
18857
18930
|
});
|
|
18858
18931
|
|
|
18859
18932
|
// apps/desktop/src/lite-install/dmg.mjs
|
|
18860
|
-
import
|
|
18933
|
+
import fs25 from "node:fs/promises";
|
|
18861
18934
|
import os6 from "node:os";
|
|
18862
|
-
import
|
|
18935
|
+
import path33 from "node:path";
|
|
18863
18936
|
import { execFile as execFile7 } from "node:child_process";
|
|
18864
18937
|
import { promisify as promisify4 } from "node:util";
|
|
18865
18938
|
async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
18866
|
-
const root = await
|
|
18867
|
-
const mount =
|
|
18868
|
-
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 });
|
|
18869
18942
|
let device, attached = false, uncertain = false;
|
|
18870
18943
|
const parse = async (xml2) => {
|
|
18871
|
-
const file =
|
|
18872
|
-
await
|
|
18944
|
+
const file = path33.join(root, "mount.plist");
|
|
18945
|
+
await fs25.writeFile(file, xml2, { mode: 384 });
|
|
18873
18946
|
return JSON.parse(await run("/usr/bin/plutil", ["-convert", "json", "-o", "-", file]));
|
|
18874
18947
|
};
|
|
18875
18948
|
const find = (data) => {
|
|
@@ -18891,13 +18964,13 @@ async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
|
18891
18964
|
}
|
|
18892
18965
|
throw error2;
|
|
18893
18966
|
}
|
|
18894
|
-
const app =
|
|
18895
|
-
if (!(await
|
|
18896
|
-
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 })) {
|
|
18897
18970
|
if (!entry.isDirectory() && !entry.isFile()) throw Error("DMG \u5E94\u7528\u5305\u542B\u94FE\u63A5\u6216\u7279\u6B8A\u6587\u4EF6");
|
|
18898
18971
|
}
|
|
18899
|
-
const destination =
|
|
18900
|
-
await
|
|
18972
|
+
const destination = path33.join(stage, "app");
|
|
18973
|
+
await fs25.cp(app, destination, { recursive: true, errorOnExist: true, force: false });
|
|
18901
18974
|
await verify(destination);
|
|
18902
18975
|
} finally {
|
|
18903
18976
|
if (device) {
|
|
@@ -18907,7 +18980,7 @@ async function prepareDmgApp({ dmg, stage, run = systemRun, verify }) {
|
|
|
18907
18980
|
throw Error(`\u65E0\u6CD5\u5378\u8F7D\u672C\u6B21 DMG ${device} (${mount})\uFF1A${error2.message}`);
|
|
18908
18981
|
}
|
|
18909
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}`);
|
|
18910
|
-
await
|
|
18983
|
+
await fs25.rm(root, { recursive: true, force: true });
|
|
18911
18984
|
}
|
|
18912
18985
|
}
|
|
18913
18986
|
var exec3, systemRun;
|
|
@@ -18920,12 +18993,12 @@ var init_dmg = __esm({
|
|
|
18920
18993
|
});
|
|
18921
18994
|
|
|
18922
18995
|
// apps/desktop/src/lite-install/bundled-resources.mjs
|
|
18923
|
-
import
|
|
18996
|
+
import fs26 from "node:fs/promises";
|
|
18924
18997
|
import { createReadStream } from "node:fs";
|
|
18925
|
-
import
|
|
18998
|
+
import path34 from "node:path";
|
|
18926
18999
|
import { createHash as createHash5 } from "node:crypto";
|
|
18927
19000
|
async function verifyLocalArtifact(file, artifact) {
|
|
18928
|
-
const st = await
|
|
19001
|
+
const st = await fs26.lstat(file);
|
|
18929
19002
|
if (!st.isFile() || st.size !== artifact.size) throw Error("\u672C\u5730\u8D44\u6E90\u7C7B\u578B\u6216\u957F\u5EA6\u65E0\u6548");
|
|
18930
19003
|
let size2 = 0;
|
|
18931
19004
|
const hash3 = createHash5("sha256");
|
|
@@ -18938,14 +19011,14 @@ async function verifyLocalArtifact(file, artifact) {
|
|
|
18938
19011
|
}
|
|
18939
19012
|
async function resolveBundledResources(packageRoot, manifest, arch) {
|
|
18940
19013
|
if (manifest.schema !== 2) throw Error("\u9700\u8981\u672C\u5730\u8D44\u6E90\u6E05\u5355");
|
|
18941
|
-
const root = await
|
|
18942
|
-
const resources =
|
|
18943
|
-
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");
|
|
18944
19017
|
for (const kind of ["app", "runtime"]) {
|
|
18945
|
-
const a = manifest.artifacts[`darwin-${arch}`][kind], file =
|
|
18946
|
-
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");
|
|
18947
19020
|
await verifyLocalArtifact(file, a);
|
|
18948
|
-
if (await
|
|
19021
|
+
if (await fs26.realpath(file) !== file) throw Error("\u8D44\u6E90\u6587\u4EF6\u4E0D\u80FD\u662F\u94FE\u63A5");
|
|
18949
19022
|
result[kind] = file;
|
|
18950
19023
|
}
|
|
18951
19024
|
return result;
|
|
@@ -18962,13 +19035,13 @@ var init_bundled_resources = __esm({
|
|
|
18962
19035
|
});
|
|
18963
19036
|
|
|
18964
19037
|
// apps/desktop/src/lite-install/installer.ts
|
|
18965
|
-
import
|
|
19038
|
+
import fs27 from "node:fs/promises";
|
|
18966
19039
|
import sync from "node:fs";
|
|
18967
|
-
import
|
|
18968
|
-
import { randomUUID as
|
|
19040
|
+
import path35 from "node:path";
|
|
19041
|
+
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
18969
19042
|
async function exists(file) {
|
|
18970
19043
|
try {
|
|
18971
|
-
await
|
|
19044
|
+
await fs27.lstat(file);
|
|
18972
19045
|
return true;
|
|
18973
19046
|
} catch (e) {
|
|
18974
19047
|
if (e.code === "ENOENT") return false;
|
|
@@ -18977,61 +19050,61 @@ async function exists(file) {
|
|
|
18977
19050
|
}
|
|
18978
19051
|
async function readConfig(file) {
|
|
18979
19052
|
if (!await exists(file)) return null;
|
|
18980
|
-
const v = JSON.parse(await
|
|
19053
|
+
const v = JSON.parse(await fs27.readFile(file, "utf8"));
|
|
18981
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");
|
|
18982
19055
|
return v;
|
|
18983
19056
|
}
|
|
18984
19057
|
async function atomic2(file, value) {
|
|
18985
|
-
const temp = file + "." +
|
|
18986
|
-
await
|
|
18987
|
-
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");
|
|
18988
19061
|
try {
|
|
18989
19062
|
await fd.sync();
|
|
18990
19063
|
} finally {
|
|
18991
19064
|
await fd.close();
|
|
18992
19065
|
}
|
|
18993
|
-
await
|
|
19066
|
+
await fs27.rename(temp, file);
|
|
18994
19067
|
}
|
|
18995
19068
|
async function installLite(o) {
|
|
18996
19069
|
const result = await installLiteLocked(o);
|
|
18997
|
-
await o.open(
|
|
19070
|
+
await o.open(path35.join(o.installRoot, "Niuma Lite.app"));
|
|
18998
19071
|
return result;
|
|
18999
19072
|
}
|
|
19000
19073
|
async function installLiteLocked(o) {
|
|
19001
19074
|
if (!/^\d+\.\d+\.\d+(?:-[\w.-]+)?$/.test(o.version)) throw Error("\u9700\u8981\u660E\u786E\u7684\u53D1\u5E03\u7248\u672C");
|
|
19002
19075
|
await privateDirectory(o.runtimeRoot);
|
|
19003
19076
|
await privateDirectory(o.installRoot);
|
|
19004
|
-
await privateDirectory(
|
|
19005
|
-
const lock = sync.openSync(
|
|
19006
|
-
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");
|
|
19007
19080
|
const recover = async () => {
|
|
19008
19081
|
if (!await exists(journal)) return;
|
|
19009
|
-
const txn = JSON.parse(await
|
|
19010
|
-
if (txn.schema !== 1 ||
|
|
19011
|
-
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");
|
|
19012
19085
|
if (await exists(app)) await o.assertOwnedApp(app);
|
|
19013
19086
|
if (await exists(txn.backup)) {
|
|
19014
19087
|
await o.assertOwnedApp(txn.backup);
|
|
19015
|
-
await
|
|
19016
|
-
await
|
|
19088
|
+
await fs27.rm(app, { recursive: true, force: true });
|
|
19089
|
+
await fs27.rename(txn.backup, app);
|
|
19017
19090
|
} else if (!txn.hadApp) {
|
|
19018
|
-
await
|
|
19091
|
+
await fs27.rm(app, { recursive: true, force: true });
|
|
19019
19092
|
}
|
|
19020
19093
|
if (txn.oldConfig) await atomic2(current2, txn.oldConfig);
|
|
19021
|
-
else await
|
|
19022
|
-
await
|
|
19023
|
-
await
|
|
19024
|
-
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);
|
|
19025
19098
|
};
|
|
19026
19099
|
try {
|
|
19027
|
-
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");
|
|
19028
19101
|
await recover();
|
|
19029
19102
|
const previous = await readConfig(current2);
|
|
19030
19103
|
if (await exists(app)) {
|
|
19031
19104
|
if (!previous) throw Error("\u540C\u540D\u975E\u6258\u7BA1\u5E94\u7528\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6");
|
|
19032
19105
|
await o.assertOwnedApp(app);
|
|
19033
19106
|
}
|
|
19034
|
-
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");
|
|
19035
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");
|
|
19036
19109
|
if (previous?.combinationId === o.version && previous.nodePath === o.nodePath) {
|
|
19037
19110
|
let valid = false;
|
|
@@ -19044,39 +19117,39 @@ async function installLiteLocked(o) {
|
|
|
19044
19117
|
return { installed: false, version: o.version };
|
|
19045
19118
|
}
|
|
19046
19119
|
}
|
|
19047
|
-
const stage =
|
|
19120
|
+
const stage = path35.join(o.runtimeRoot, ".stage-" + randomUUID16());
|
|
19048
19121
|
await privateDirectory(stage);
|
|
19049
19122
|
try {
|
|
19050
19123
|
await o.prepare(stage);
|
|
19051
|
-
await o.verify(
|
|
19124
|
+
await o.verify(path35.join(stage, "app"), path35.join(stage, "runtime"));
|
|
19052
19125
|
if (previous && !await o.confirm()) throw Error("\u5DF2\u53D6\u6D88\u66F4\u65B0");
|
|
19053
19126
|
if (await exists(app)) {
|
|
19054
19127
|
if (!previous) throw Error("\u540C\u540D\u975E\u6258\u7BA1\u5E94\u7528\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6");
|
|
19055
19128
|
await o.assertOwnedApp(app);
|
|
19056
19129
|
}
|
|
19057
19130
|
await o.stopHost();
|
|
19058
|
-
const runtime =
|
|
19059
|
-
const backup =
|
|
19060
|
-
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");
|
|
19061
19134
|
const txn = { schema: 1, stage, backup, stagedApp, oldConfig: previous, hadApp: await exists(app) };
|
|
19062
19135
|
await atomic2(journal, txn);
|
|
19063
|
-
if (txn.hadApp) await
|
|
19136
|
+
if (txn.hadApp) await fs27.rename(app, backup);
|
|
19064
19137
|
await o.checkpoint?.("app-backed-up");
|
|
19065
19138
|
if (await exists(stagedApp)) throw Error("\u5E94\u7528\u6682\u5B58\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u5B89\u88C5\u72B6\u6001");
|
|
19066
|
-
await
|
|
19067
|
-
await
|
|
19139
|
+
await fs27.cp(path35.join(stage, "app"), stagedApp, { recursive: true, errorOnExist: true, force: false });
|
|
19140
|
+
await fs27.rename(stagedApp, app);
|
|
19068
19141
|
await o.checkpoint?.("app-replaced");
|
|
19069
|
-
await
|
|
19142
|
+
await fs27.rename(path35.join(stage, "runtime"), runtime);
|
|
19070
19143
|
const config = { schema: 1, combinationId: o.version, daemonVersion: o.version, runtimeDir: runtime, nodePath: o.nodePath };
|
|
19071
19144
|
await atomic2(current2, config);
|
|
19072
19145
|
await o.checkpoint?.("config-replaced");
|
|
19073
|
-
await
|
|
19146
|
+
await fs27.rm(journal);
|
|
19074
19147
|
return { installed: true, version: o.version };
|
|
19075
19148
|
} catch (error2) {
|
|
19076
19149
|
await recover();
|
|
19077
19150
|
throw error2;
|
|
19078
19151
|
} finally {
|
|
19079
|
-
await
|
|
19152
|
+
await fs27.rm(stage, { recursive: true, force: true });
|
|
19080
19153
|
}
|
|
19081
19154
|
} finally {
|
|
19082
19155
|
sync.closeSync(lock);
|
|
@@ -19129,15 +19202,15 @@ var init_manifest = __esm({
|
|
|
19129
19202
|
});
|
|
19130
19203
|
|
|
19131
19204
|
// apps/desktop/src/lite-install/resources.ts
|
|
19132
|
-
import
|
|
19205
|
+
import path36 from "node:path";
|
|
19133
19206
|
import { createHash as createHash6 } from "node:crypto";
|
|
19134
19207
|
import { createWriteStream } from "node:fs";
|
|
19135
|
-
import
|
|
19208
|
+
import fs28 from "node:fs/promises";
|
|
19136
19209
|
import { Readable } from "node:stream";
|
|
19137
19210
|
import { pipeline } from "node:stream/promises";
|
|
19138
19211
|
import * as tar from "tar";
|
|
19139
19212
|
function safeArchiveEntry(name2, type) {
|
|
19140
|
-
return !name2.includes("\\") && !
|
|
19213
|
+
return !name2.includes("\\") && !path36.posix.isAbsolute(name2) && !name2.split("/").includes("..") && ["File", "Directory", "OldFile", "ContiguousFile"].includes(type);
|
|
19141
19214
|
}
|
|
19142
19215
|
async function download(a, file) {
|
|
19143
19216
|
const signal = AbortSignal.timeout(12e4);
|
|
@@ -19179,7 +19252,7 @@ async function extract(file, destination) {
|
|
|
19179
19252
|
if (!safeArchiveEntry(entry.path, entry.type) || total > 2 * 1024 * 1024 * 1024 || count > 1e5) invalid14 = true;
|
|
19180
19253
|
} });
|
|
19181
19254
|
if (invalid14) throw Error("\u53D1\u884C\u5F52\u6863\u5305\u542B\u4E0D\u5B89\u5168\u8DEF\u5F84\u6216\u94FE\u63A5");
|
|
19182
|
-
await
|
|
19255
|
+
await fs28.mkdir(destination, { recursive: true, mode: 448 });
|
|
19183
19256
|
await tar.x({ file, cwd: destination, strict: true, preservePaths: false, noChmod: true, noMtime: true });
|
|
19184
19257
|
}
|
|
19185
19258
|
var init_resources = __esm({
|
|
@@ -19190,17 +19263,16 @@ var init_resources = __esm({
|
|
|
19190
19263
|
});
|
|
19191
19264
|
|
|
19192
19265
|
// apps/desktop/src/lite-install/production.ts
|
|
19193
|
-
import { randomUUID as randomUUID16 } from "node:crypto";
|
|
19194
19266
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
19195
|
-
import
|
|
19196
|
-
import
|
|
19267
|
+
import fs29 from "node:fs/promises";
|
|
19268
|
+
import path37 from "node:path";
|
|
19197
19269
|
import os7 from "node:os";
|
|
19198
19270
|
import { createInterface as createInterface3 } from "node:readline/promises";
|
|
19199
19271
|
async function runLiteInstall() {
|
|
19200
19272
|
if (process.platform !== "darwin") throw Error("\u8F7B\u91CF\u684C\u9762\u5E94\u7528\u4EC5\u652F\u6301 macOS\uFF0C\u8BF7\u4F7F\u7528 --background");
|
|
19201
19273
|
const version2 = desktopReleaseVersion();
|
|
19202
|
-
if (!version2 || false ||
|
|
19203
|
-
const manifest = validateManifest(JSON.parse(
|
|
19274
|
+
if (!version2 || false || true) 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");
|
|
19275
|
+
const manifest = validateManifest(JSON.parse(""), version2, process.arch);
|
|
19204
19276
|
if (manifest.schema === 2) await confirmExperimental(manifest.mode, !!process.stdin.isTTY && !!process.stdout.isTTY, async () => {
|
|
19205
19277
|
const prompt = createInterface3({ input: process.stdin, output: process.stdout });
|
|
19206
19278
|
try {
|
|
@@ -19210,26 +19282,26 @@ async function runLiteInstall() {
|
|
|
19210
19282
|
}
|
|
19211
19283
|
});
|
|
19212
19284
|
const local = manifest.schema === 2 ? await resolveBundledResources(fileURLToPath(new URL("../", import.meta.url)), manifest, process.arch) : null;
|
|
19213
|
-
const runtimeRoot =
|
|
19285
|
+
const runtimeRoot = path37.join(os7.homedir(), "Library/Application Support/Niuma/lite-runtime");
|
|
19214
19286
|
try {
|
|
19215
|
-
await
|
|
19287
|
+
await fs29.lstat(path37.join(runtimeRoot, "uninstall.json"));
|
|
19216
19288
|
throw Error("\u5378\u8F7D\u5C1A\u672A\u5B8C\u6210\uFF0C\u8BF7\u5148\u91CD\u65B0\u8FD0\u884C uninstall-app");
|
|
19217
19289
|
} catch (e) {
|
|
19218
19290
|
if (e.code !== "ENOENT") throw e;
|
|
19219
19291
|
}
|
|
19220
19292
|
const assertOwnedApp = async (app) => {
|
|
19221
19293
|
try {
|
|
19222
|
-
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")]);
|
|
19223
19295
|
if (id5.trim() !== "com.niuma.macos.lite") throw Error("different identity");
|
|
19224
19296
|
} catch {
|
|
19225
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");
|
|
19226
19298
|
}
|
|
19227
19299
|
};
|
|
19228
19300
|
const verifyApp = async (app) => {
|
|
19229
|
-
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")]);
|
|
19230
19302
|
if (id5.trim() !== "com.niuma.macos.lite") throw Error("\u5E94\u7528\u6807\u8BC6\u4E0D\u5339\u914D");
|
|
19231
|
-
if (JSON.parse(await
|
|
19232
|
-
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");
|
|
19233
19305
|
if ((await runProcess(binary, ["--runtime-version"])).trim() !== version2) throw Error("\u5E94\u7528\u4E8C\u8FDB\u5236\u7248\u672C\u4E0D\u5339\u914D");
|
|
19234
19306
|
const arch = (await runProcess("/usr/bin/lipo", ["-archs", binary])).trim().split(/\s+/);
|
|
19235
19307
|
if (!arch.includes(process.arch === "x64" ? "x86_64" : process.arch)) throw Error("\u5E94\u7528\u67B6\u6784\u4E0D\u5339\u914D");
|
|
@@ -19237,10 +19309,10 @@ async function runLiteInstall() {
|
|
|
19237
19309
|
};
|
|
19238
19310
|
const verify = async (app, runtime) => {
|
|
19239
19311
|
await verifyApp(app);
|
|
19240
|
-
const pkg = JSON.parse(await
|
|
19312
|
+
const pkg = JSON.parse(await fs29.readFile(path37.join(runtime, "package.json"), "utf8"));
|
|
19241
19313
|
if (pkg.name !== "niuma-codex" || pkg.version !== version2) throw Error("daemon \u7248\u672C\u4E0D\u5339\u914D");
|
|
19242
|
-
if (!(await
|
|
19243
|
-
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)})`]);
|
|
19244
19316
|
};
|
|
19245
19317
|
let confirmed = false;
|
|
19246
19318
|
const confirm = async () => {
|
|
@@ -19255,34 +19327,8 @@ async function runLiteInstall() {
|
|
|
19255
19327
|
}
|
|
19256
19328
|
};
|
|
19257
19329
|
await withInstallCoordination(runtimeRoot, async () => {
|
|
19258
|
-
const
|
|
19259
|
-
|
|
19260
|
-
const intentFile = path36.join(runtimeRoot, "install-intent.json");
|
|
19261
|
-
let intent;
|
|
19262
|
-
try {
|
|
19263
|
-
const stat4 = await fs28.lstat(intentFile);
|
|
19264
|
-
if (!stat4.isFile() || stat4.uid !== process.getuid?.() || stat4.mode & 63) throw Error("\u5B89\u88C5\u610F\u56FE\u6587\u4EF6\u4E0D\u53EF\u4FE1");
|
|
19265
|
-
intent = JSON.parse(await fs28.readFile(intentFile, "utf8"));
|
|
19266
|
-
if (typeof intent.firstInstall !== "boolean" || intent.version !== version2) throw Error("\u8BF7\u5148\u4F7F\u7528\u539F\u7248\u672C\u5B8C\u6210\u5B89\u88C5");
|
|
19267
|
-
} catch (e) {
|
|
19268
|
-
if (e.code !== "ENOENT") throw e;
|
|
19269
|
-
let firstInstall = false;
|
|
19270
|
-
try {
|
|
19271
|
-
await fs28.lstat(path36.join(runtimeRoot, "current.json"));
|
|
19272
|
-
} catch (e2) {
|
|
19273
|
-
if (e2.code !== "ENOENT") throw e2;
|
|
19274
|
-
firstInstall = true;
|
|
19275
|
-
}
|
|
19276
|
-
intent = { version: version2, firstInstall, selection: await createInstallSelection(os7.homedir(), true) };
|
|
19277
|
-
await fs28.writeFile(intentFile, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
19278
|
-
}
|
|
19279
|
-
if (!intent.selection) {
|
|
19280
|
-
intent.selection = await createInstallSelection(os7.homedir(), false);
|
|
19281
|
-
const temp = intentFile + "." + randomUUID16();
|
|
19282
|
-
await fs28.writeFile(temp, JSON.stringify(intent), { flag: "wx", mode: 384 });
|
|
19283
|
-
await fs28.rename(temp, intentFile);
|
|
19284
|
-
}
|
|
19285
|
-
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);
|
|
19286
19332
|
const manager = createAutostartManager({ command: null, positionals: [], flags: {} });
|
|
19287
19333
|
const needsSource = intent.firstInstall || !!(pending && !["completed", "skipped"].includes(pending.phase));
|
|
19288
19334
|
const withSource = needsSource ? manager.withMigrationSource.bind(manager) : async (work) => work({ snapshot: async () => ({ fingerprint: "not-migrating", enabled: false }), remove: async () => {
|
|
@@ -19315,27 +19361,27 @@ async function runLiteInstall() {
|
|
|
19315
19361
|
} });
|
|
19316
19362
|
const result = await installLite({
|
|
19317
19363
|
runtimeRoot,
|
|
19318
|
-
installRoot:
|
|
19364
|
+
installRoot: path37.join(os7.homedir(), "Applications"),
|
|
19319
19365
|
version: version2,
|
|
19320
|
-
nodePath: await
|
|
19366
|
+
nodePath: await fs29.realpath(process.execPath),
|
|
19321
19367
|
verify,
|
|
19322
19368
|
assertOwnedApp,
|
|
19323
19369
|
prepare: async (stage) => {
|
|
19324
19370
|
if (manifest.schema === 2 && local) {
|
|
19325
19371
|
const artifacts = manifest.artifacts[`darwin-${process.arch}`];
|
|
19326
19372
|
for (const kind of ["app", "runtime"]) {
|
|
19327
|
-
const file =
|
|
19328
|
-
await
|
|
19373
|
+
const file = path37.join(stage, kind === "app" ? "app.dmg" : "runtime.tgz");
|
|
19374
|
+
await fs29.copyFile(local[kind], file);
|
|
19329
19375
|
await verifyLocalArtifact(file, artifacts[kind]);
|
|
19330
19376
|
}
|
|
19331
|
-
await prepareDmgApp({ dmg:
|
|
19332
|
-
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"));
|
|
19333
19379
|
} else if (manifest.schema === 1) {
|
|
19334
19380
|
const artifacts = manifest.artifacts[`darwin-${process.arch}`];
|
|
19335
19381
|
for (const kind of ["app", "runtime"]) {
|
|
19336
|
-
const file =
|
|
19382
|
+
const file = path37.join(stage, kind + ".tgz");
|
|
19337
19383
|
await download(artifacts[kind], file);
|
|
19338
|
-
await extract(file,
|
|
19384
|
+
await extract(file, path37.join(stage, kind));
|
|
19339
19385
|
}
|
|
19340
19386
|
}
|
|
19341
19387
|
},
|
|
@@ -19402,7 +19448,7 @@ async function runLiteInstall() {
|
|
|
19402
19448
|
});
|
|
19403
19449
|
}, "login-settings.lock");
|
|
19404
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");
|
|
19405
|
-
if (migration !== "pending" || !historical && sourceBefore.enabled === true) await
|
|
19451
|
+
if (migration !== "pending" || !historical && sourceBefore.enabled === true) await fs29.rm(intentFile, { force: true });
|
|
19406
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";
|
|
19407
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
|
|
19408
19454
|
`);
|
|
@@ -19416,6 +19462,7 @@ var init_production2 = __esm({
|
|
|
19416
19462
|
init_host_control();
|
|
19417
19463
|
init_lock();
|
|
19418
19464
|
init_migration();
|
|
19465
|
+
init_intent();
|
|
19419
19466
|
init_lifecycle();
|
|
19420
19467
|
init_production();
|
|
19421
19468
|
init_client();
|
|
@@ -19828,15 +19875,15 @@ var init_client_turn_query_context = __esm({
|
|
|
19828
19875
|
});
|
|
19829
19876
|
|
|
19830
19877
|
// apps/desktop/src/niuma/session-history-file.ts
|
|
19831
|
-
import
|
|
19832
|
-
import
|
|
19878
|
+
import fs30 from "node:fs/promises";
|
|
19879
|
+
import path38 from "node:path";
|
|
19833
19880
|
import { createHash as createHash7 } from "node:crypto";
|
|
19834
19881
|
function matchesSessionFileIdentity(file, stat4) {
|
|
19835
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;
|
|
19836
19883
|
return exact(file.dev) === String(stat4.dev) && exact(file.ino) === String(stat4.ino);
|
|
19837
19884
|
}
|
|
19838
19885
|
async function preciseStat(file) {
|
|
19839
|
-
const stat4 = await
|
|
19886
|
+
const stat4 = await fs30.stat(file, { bigint: true });
|
|
19840
19887
|
const size2 = Number(stat4.size);
|
|
19841
19888
|
if (!Number.isSafeInteger(size2)) throw new SessionHistoryError("RESOURCE_LIMIT", "\u4F1A\u8BDD\u6587\u4EF6\u8D85\u51FA\u8BFB\u53D6\u8303\u56F4");
|
|
19842
19889
|
return { dev: stat4.dev, ino: stat4.ino, size: size2, mtimeMs: Number(stat4.mtimeNs) / 1e6, isFile: () => stat4.isFile() };
|
|
@@ -19852,12 +19899,12 @@ function rethrowUnreadableHistoryPath(error2) {
|
|
|
19852
19899
|
}
|
|
19853
19900
|
function fileIdentity(file) {
|
|
19854
19901
|
const uuid8 = "[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}";
|
|
19855
|
-
const match =
|
|
19902
|
+
const match = path38.basename(file).match(new RegExp(`(${uuid8})(?:_(${uuid8}))?\\.jsonl$`, "i"));
|
|
19856
19903
|
return match ? { owner: match[1], segment: match[2] ?? match[1] } : null;
|
|
19857
19904
|
}
|
|
19858
19905
|
async function readBytes(file, start, length, onRead, signal) {
|
|
19859
19906
|
abortIfRequested(signal);
|
|
19860
|
-
const handle = await
|
|
19907
|
+
const handle = await fs30.open(file, "r").catch(rethrowUnreadableHistoryPath);
|
|
19861
19908
|
try {
|
|
19862
19909
|
const buffer = Buffer.allocUnsafe(length);
|
|
19863
19910
|
let filled = 0;
|
|
@@ -19915,7 +19962,7 @@ async function header(file, size2, onRead, signal) {
|
|
|
19915
19962
|
}
|
|
19916
19963
|
async function openSessionFile(file, threadId2, chunkBytes, end, onRead, signal, onCutoffCaptured) {
|
|
19917
19964
|
abortIfRequested(signal);
|
|
19918
|
-
const resolved3 = await
|
|
19965
|
+
const resolved3 = await fs30.realpath(file).catch(rethrowUnreadableHistoryPath);
|
|
19919
19966
|
const stat4 = await preciseStat(resolved3).catch(rethrowUnreadableHistoryPath);
|
|
19920
19967
|
abortIfRequested(signal);
|
|
19921
19968
|
if (!stat4.isFile()) throw new SessionHistoryError("INVALID_METADATA", "\u4F1A\u8BDD\u8DEF\u5F84\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
|
|
@@ -22892,10 +22939,10 @@ var init_status = __esm({
|
|
|
22892
22939
|
});
|
|
22893
22940
|
|
|
22894
22941
|
// apps/desktop/src/niuma/thread-summary.ts
|
|
22895
|
-
import
|
|
22942
|
+
import path39 from "node:path";
|
|
22896
22943
|
function pathBelongsToProjectRoot(projectRoot, candidateRoot) {
|
|
22897
|
-
const relative =
|
|
22898
|
-
return relative === "" || !relative.startsWith("..") && !
|
|
22944
|
+
const relative = path39.relative(path39.resolve(projectRoot), path39.resolve(candidateRoot));
|
|
22945
|
+
return relative === "" || !relative.startsWith("..") && !path39.isAbsolute(relative);
|
|
22899
22946
|
}
|
|
22900
22947
|
function toLatestTurn(turns) {
|
|
22901
22948
|
const latest = turns.at(-1);
|
|
@@ -22963,7 +23010,7 @@ function normalizeThreadSummary(thread4, pending = null, options = {}) {
|
|
|
22963
23010
|
id: thread4.id,
|
|
22964
23011
|
title: thread4.name ?? thread4.preview ?? "",
|
|
22965
23012
|
projectRoot: thread4.cwd,
|
|
22966
|
-
projectName:
|
|
23013
|
+
projectName: path39.basename(thread4.cwd) || thread4.cwd,
|
|
22967
23014
|
status: status2,
|
|
22968
23015
|
pending: normalizedPending,
|
|
22969
23016
|
createdAt: thread4.createdAt,
|
|
@@ -26095,9 +26142,9 @@ function resourcePaths(platform2 = process.platform) {
|
|
|
26095
26142
|
toLink(value) {
|
|
26096
26143
|
const parsed = parseLocal(value);
|
|
26097
26144
|
if (parsed === null) return null;
|
|
26098
|
-
const
|
|
26145
|
+
const path71 = windows2 ? parsed.replaceAll("\\", "/") : parsed;
|
|
26099
26146
|
try {
|
|
26100
|
-
return encodeURIComponent(
|
|
26147
|
+
return encodeURIComponent(path71).replace(/%2F/gu, "/").replace(/^([a-z])%3A\//iu, "$1:/");
|
|
26101
26148
|
} catch {
|
|
26102
26149
|
return null;
|
|
26103
26150
|
}
|
|
@@ -26241,8 +26288,8 @@ var init_response_annotations = __esm({
|
|
|
26241
26288
|
|
|
26242
26289
|
// apps/desktop/src/attachments/image-identity.ts
|
|
26243
26290
|
import { createHash as createHash12 } from "node:crypto";
|
|
26244
|
-
function unavailableImageId(
|
|
26245
|
-
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;
|
|
26246
26293
|
return `unavailable:${createHash12("sha256").update(identity6).digest("hex")}`;
|
|
26247
26294
|
}
|
|
26248
26295
|
var init_image_identity = __esm({
|
|
@@ -26336,15 +26383,15 @@ function normalizeMessageContent(value, resolveKnownLocalImage, itemId, original
|
|
|
26336
26383
|
}
|
|
26337
26384
|
return content2;
|
|
26338
26385
|
}
|
|
26339
|
-
function userFile(name2,
|
|
26386
|
+
function userFile(name2, path71) {
|
|
26340
26387
|
const part = { type: "file", name: name2 };
|
|
26341
|
-
userFileSource.set(part,
|
|
26388
|
+
userFileSource.set(part, path71);
|
|
26342
26389
|
return part;
|
|
26343
26390
|
}
|
|
26344
26391
|
function userFileSources(content2 = []) {
|
|
26345
26392
|
return content2.flatMap((part, index) => {
|
|
26346
|
-
const
|
|
26347
|
-
return part.type === "file" && typeof
|
|
26393
|
+
const path71 = userFileSource.get(part);
|
|
26394
|
+
return part.type === "file" && typeof path71 === "string" ? [{ index, path: path71 }] : [];
|
|
26348
26395
|
});
|
|
26349
26396
|
}
|
|
26350
26397
|
function codexImageWrapperFileList(text11) {
|
|
@@ -26381,11 +26428,11 @@ function standardCodexImageFileListEntries(fileList) {
|
|
|
26381
26428
|
break;
|
|
26382
26429
|
}
|
|
26383
26430
|
const name2 = safeCodexFileName(match[1] ?? match[3] ?? "");
|
|
26384
|
-
const
|
|
26385
|
-
if (!name2 || !isRecordedResourcePath(
|
|
26431
|
+
const path71 = match[2] ?? match[4] ?? "";
|
|
26432
|
+
if (!name2 || !isRecordedResourcePath(path71)) {
|
|
26386
26433
|
return null;
|
|
26387
26434
|
}
|
|
26388
|
-
entries.push({ name: name2, path:
|
|
26435
|
+
entries.push({ name: name2, path: path71 });
|
|
26389
26436
|
remaining = remaining.slice(match[0].length);
|
|
26390
26437
|
remaining = remaining.replace(/^Image attachment: true\r?\n/u, "");
|
|
26391
26438
|
}
|
|
@@ -26401,10 +26448,10 @@ function redactCodexImageWrapperPaths(text11) {
|
|
|
26401
26448
|
}
|
|
26402
26449
|
const fileList = wrapper.fileList.replace(
|
|
26403
26450
|
/(^## [^\r\n]+:[ \t]*\r?\n)[ \t]*([^\r\n]+)/gmu,
|
|
26404
|
-
(all, prefix,
|
|
26451
|
+
(all, prefix, path71) => isRecordedResourcePath(path71) ? `${prefix}[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
|
|
26405
26452
|
).replace(
|
|
26406
26453
|
/^(## [^\r\n]+:)[ \t]+([^\r\n]+)$/gmu,
|
|
26407
|
-
(all, prefix,
|
|
26454
|
+
(all, prefix, path71) => isRecordedResourcePath(path71) ? `${prefix} [\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]` : all
|
|
26408
26455
|
);
|
|
26409
26456
|
const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
|
|
26410
26457
|
return `${wrapper.prefix}${fileList}${text11.slice(fileListEnd)}`;
|
|
@@ -26415,7 +26462,7 @@ function redactKnownCodexWrapperPaths(text11, paths) {
|
|
|
26415
26462
|
return text11;
|
|
26416
26463
|
}
|
|
26417
26464
|
const fileList = paths.reduce(
|
|
26418
|
-
(result,
|
|
26465
|
+
(result, path71) => result.replaceAll(path71, "[\u672C\u673A\u56FE\u7247\u8DEF\u5F84\u5DF2\u9690\u85CF]"),
|
|
26419
26466
|
wrapper.fileList
|
|
26420
26467
|
);
|
|
26421
26468
|
const fileListEnd = wrapper.requestIndex === -1 ? text11.length : wrapper.requestIndex;
|
|
@@ -26432,8 +26479,8 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
|
|
|
26432
26479
|
}
|
|
26433
26480
|
const localImagePaths = value.flatMap((part) => {
|
|
26434
26481
|
const record26 = asRecord11(part);
|
|
26435
|
-
const
|
|
26436
|
-
return
|
|
26482
|
+
const path71 = localImagePath(record26);
|
|
26483
|
+
return path71 === null ? [] : [path71];
|
|
26437
26484
|
});
|
|
26438
26485
|
const text11 = redactKnownCodexWrapperPaths(
|
|
26439
26486
|
redactCodexImageWrapperPaths(firstPart2.text),
|
|
@@ -26467,9 +26514,9 @@ function normalizeUserFileMessageContent(value, resolveKnownLocalImage, itemId,
|
|
|
26467
26514
|
const localImages = value.flatMap((part, index) => {
|
|
26468
26515
|
const partIndex = originalPartIndices?.[index] ?? index;
|
|
26469
26516
|
const record26 = asRecord11(part);
|
|
26470
|
-
const
|
|
26471
|
-
return
|
|
26472
|
-
path:
|
|
26517
|
+
const path71 = localImagePath(record26);
|
|
26518
|
+
return path71 === null ? [] : [{
|
|
26519
|
+
path: path71,
|
|
26473
26520
|
partIndex,
|
|
26474
26521
|
image: record26.type === "historyImage" ? historyImageContent(record26, itemId, partIndex) : null
|
|
26475
26522
|
}];
|
|
@@ -26598,8 +26645,8 @@ function redactRawLocalImagePaths(rawItem) {
|
|
|
26598
26645
|
let containsLocalImage = false;
|
|
26599
26646
|
let containsRedactedWrapperPath = false;
|
|
26600
26647
|
const localImagePaths = item.content.map((part) => asRecord11(part)).flatMap((part) => {
|
|
26601
|
-
const
|
|
26602
|
-
return
|
|
26648
|
+
const path71 = localImagePath(part);
|
|
26649
|
+
return path71 === null ? [] : [path71];
|
|
26603
26650
|
});
|
|
26604
26651
|
const content2 = item.content.map((part) => {
|
|
26605
26652
|
const record26 = asRecord11(part);
|
|
@@ -27567,8 +27614,8 @@ var init_events = __esm({
|
|
|
27567
27614
|
const patches = Array.isArray(change.patches) ? change.patches : [];
|
|
27568
27615
|
for (const patch of patches) {
|
|
27569
27616
|
const candidate = objectRecord6(patch);
|
|
27570
|
-
const
|
|
27571
|
-
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") {
|
|
27572
27619
|
runtimeStatusValue = candidate.value;
|
|
27573
27620
|
}
|
|
27574
27621
|
}
|
|
@@ -29571,13 +29618,13 @@ var init_upload_task_store = __esm({
|
|
|
29571
29618
|
import { execFile as execFile9 } from "node:child_process";
|
|
29572
29619
|
import { constants as constants2 } from "node:fs";
|
|
29573
29620
|
import { lstat, open } from "node:fs/promises";
|
|
29574
|
-
import
|
|
29621
|
+
import path40 from "node:path";
|
|
29575
29622
|
function limit(max) {
|
|
29576
29623
|
if (!Number.isSafeInteger(max) || max < 1 || max > 50 * 1024 * 1024) throw new PrivateBinaryFileError("capacity");
|
|
29577
29624
|
}
|
|
29578
29625
|
function resolved2(file) {
|
|
29579
29626
|
try {
|
|
29580
|
-
return windows() ? localWindowsPath(file) :
|
|
29627
|
+
return windows() ? localWindowsPath(file) : path40.resolve(file);
|
|
29581
29628
|
} catch {
|
|
29582
29629
|
throw unavailable2();
|
|
29583
29630
|
}
|
|
@@ -29620,7 +29667,7 @@ async function windowsMode(file, seal = false) {
|
|
|
29620
29667
|
return output;
|
|
29621
29668
|
}
|
|
29622
29669
|
async function parentIdentity(file) {
|
|
29623
|
-
const directory3 =
|
|
29670
|
+
const directory3 = path40.dirname(file), initial = await lstat(directory3, { bigint: true });
|
|
29624
29671
|
if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable2();
|
|
29625
29672
|
if (windows()) {
|
|
29626
29673
|
try {
|
|
@@ -29687,10 +29734,10 @@ async function openFile(file, options) {
|
|
|
29687
29734
|
let tail = Promise.resolve();
|
|
29688
29735
|
async function guard() {
|
|
29689
29736
|
if (closed || poisoned) throw unavailable2();
|
|
29690
|
-
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 });
|
|
29691
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();
|
|
29692
29739
|
if (!windows() && posixMode(held) !== mode) throw unavailable2();
|
|
29693
|
-
if (!windows()) privateLogFiles.checkDirectory(
|
|
29740
|
+
if (!windows()) privateLogFiles.checkDirectory(path40.dirname(file));
|
|
29694
29741
|
}
|
|
29695
29742
|
await guard();
|
|
29696
29743
|
checkExpected(await status(h), options);
|
|
@@ -29827,11 +29874,11 @@ if($env:NIUMA_BINARY_SEAL -eq '1' -and $mode -ne 'immutable') {
|
|
|
29827
29874
|
handle = await open(file, constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (windows() ? 0 : constants2.O_NOFOLLOW), 384);
|
|
29828
29875
|
if (!windows()) await handle.chmod(384);
|
|
29829
29876
|
const held = await handle.stat({ bigint: true }), current2 = await lstat(file, { bigint: true });
|
|
29830
|
-
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();
|
|
29831
29878
|
if (windows() && await windowsMode(file) !== "mutable") throw unavailable2();
|
|
29832
29879
|
await handle.sync();
|
|
29833
29880
|
const result = await status(handle);
|
|
29834
|
-
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();
|
|
29835
29882
|
await handle.close();
|
|
29836
29883
|
handle = void 0;
|
|
29837
29884
|
return result;
|
|
@@ -29931,7 +29978,7 @@ import { randomUUID as randomUUID23 } from "node:crypto";
|
|
|
29931
29978
|
import { execFile as execFile11 } from "node:child_process";
|
|
29932
29979
|
import { constants as constants3 } from "node:fs";
|
|
29933
29980
|
import { chmod, lstat as lstat3, mkdir, open as open2, readdir, rename, rm } from "node:fs/promises";
|
|
29934
|
-
import
|
|
29981
|
+
import path41 from "node:path";
|
|
29935
29982
|
function nameOnly(name2) {
|
|
29936
29983
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]{0,127}$/u.test(name2)) throw unavailable3();
|
|
29937
29984
|
}
|
|
@@ -29940,7 +29987,7 @@ function budget(maxBytes) {
|
|
|
29940
29987
|
}
|
|
29941
29988
|
async function openDirectories(requested, windowsCandidate) {
|
|
29942
29989
|
const windows2 = process.platform === "win32";
|
|
29943
|
-
const root = windows2 ? localWindowsPath(requested) :
|
|
29990
|
+
const root = windows2 ? localWindowsPath(requested) : path41.resolve(requested);
|
|
29944
29991
|
let rootIdentity;
|
|
29945
29992
|
try {
|
|
29946
29993
|
if (windows2) await ensureWindowsPrivateDirectoryAsync(root);
|
|
@@ -29985,7 +30032,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
29985
30032
|
}
|
|
29986
30033
|
function token3(value) {
|
|
29987
30034
|
const directory3 = Object.freeze({ get sourcePath() {
|
|
29988
|
-
return
|
|
30035
|
+
return path41.join(value.path, "source");
|
|
29989
30036
|
} });
|
|
29990
30037
|
records2.set(directory3, value);
|
|
29991
30038
|
return directory3;
|
|
@@ -30041,7 +30088,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
30041
30088
|
return serial(async () => {
|
|
30042
30089
|
nameOnly(name2);
|
|
30043
30090
|
await guard();
|
|
30044
|
-
const directory3 =
|
|
30091
|
+
const directory3 = path41.join(root, name2);
|
|
30045
30092
|
if (!windows2) privateLogFiles.checkDirectory(directory3);
|
|
30046
30093
|
const identity6 = await lstat3(directory3, { bigint: true });
|
|
30047
30094
|
const result = token3({ name: name2, path: directory3, identity: identity6, staged: false, pending: true, ready: true });
|
|
@@ -30054,7 +30101,7 @@ async function openDirectories(requested, windowsCandidate) {
|
|
|
30054
30101
|
mutable();
|
|
30055
30102
|
nameOnly(name2);
|
|
30056
30103
|
await guard();
|
|
30057
|
-
const directory3 =
|
|
30104
|
+
const directory3 = path41.join(root, ".pending-" + name2);
|
|
30058
30105
|
await mkdir(directory3, { mode: 448 });
|
|
30059
30106
|
const identity6 = await lstat3(directory3, { bigint: true });
|
|
30060
30107
|
if (windows2) {
|
|
@@ -30084,7 +30131,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30084
30131
|
return serial(async () => {
|
|
30085
30132
|
budget(maxBytes);
|
|
30086
30133
|
await guard(directory3);
|
|
30087
|
-
const handle = await privateBinaryFiles.open(
|
|
30134
|
+
const handle = await privateBinaryFiles.open(path41.join(record26(directory3).path, "manifest.json"), { maxBytes, mode: "mutable" });
|
|
30088
30135
|
let failed = false;
|
|
30089
30136
|
const bytes3 = Buffer.alloc(maxBytes);
|
|
30090
30137
|
try {
|
|
@@ -30133,7 +30180,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30133
30180
|
async function currentManifest() {
|
|
30134
30181
|
let stats;
|
|
30135
30182
|
try {
|
|
30136
|
-
stats = await lstat3(
|
|
30183
|
+
stats = await lstat3(path41.join(value.path, "manifest.json"), { bigint: true });
|
|
30137
30184
|
} catch (error2) {
|
|
30138
30185
|
if (error2.code === "ENOENT") return null;
|
|
30139
30186
|
throw error2;
|
|
@@ -30141,7 +30188,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30141
30188
|
if (!stats.isFile() || stats.isSymbolicLink() || stats.nlink !== 1n || !windows2 && (stats.uid !== BigInt(process.getuid()) || (stats.mode & 0o777n) !== 0o600n)) throw unavailable3();
|
|
30142
30189
|
if (stats.size > BigInt(maxBytes)) throw new PrivateUploadDirectoryError("capacity");
|
|
30143
30190
|
if (windows2) {
|
|
30144
|
-
const handle = await privateBinaryFiles.open(
|
|
30191
|
+
const handle = await privateBinaryFiles.open(path41.join(value.path, "manifest.json"), {
|
|
30145
30192
|
maxBytes,
|
|
30146
30193
|
mode: "mutable",
|
|
30147
30194
|
match: "object",
|
|
@@ -30158,13 +30205,13 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30158
30205
|
} finally {
|
|
30159
30206
|
await handle.close();
|
|
30160
30207
|
}
|
|
30161
|
-
const after = await lstat3(
|
|
30208
|
+
const after = await lstat3(path41.join(value.path, "manifest.json"), { bigint: true });
|
|
30162
30209
|
if (!same4(stats, after) || stats.size !== after.size || stats.mtimeNs !== after.mtimeNs || stats.ctimeNs !== after.ctimeNs) throw unavailable3();
|
|
30163
30210
|
}
|
|
30164
30211
|
return stats;
|
|
30165
30212
|
}
|
|
30166
30213
|
const original = await currentManifest();
|
|
30167
|
-
const temporary =
|
|
30214
|
+
const temporary = path41.join(value.path, ".manifest-" + randomUUID23());
|
|
30168
30215
|
let created = false, published = false, identity6;
|
|
30169
30216
|
try {
|
|
30170
30217
|
if (windows2) {
|
|
@@ -30219,7 +30266,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30219
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();
|
|
30220
30267
|
const previous = await currentManifest();
|
|
30221
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();
|
|
30222
|
-
await rename(temporary,
|
|
30269
|
+
await rename(temporary, path41.join(value.path, "manifest.json"));
|
|
30223
30270
|
published = true;
|
|
30224
30271
|
created = false;
|
|
30225
30272
|
value.pending = true;
|
|
@@ -30256,7 +30303,7 @@ Check-PrivateDirectory $env:NIUMA_UPLOAD_ENTRY
|
|
|
30256
30303
|
const value = record26(directory3);
|
|
30257
30304
|
if (!value.staged || !value.ready) throw unavailable3();
|
|
30258
30305
|
await finish(directory3);
|
|
30259
|
-
const target =
|
|
30306
|
+
const target = path41.join(root, value.name);
|
|
30260
30307
|
try {
|
|
30261
30308
|
await lstat3(target);
|
|
30262
30309
|
throw unavailable3();
|
|
@@ -30641,7 +30688,7 @@ var init_legacy_upload_contents = __esm({
|
|
|
30641
30688
|
|
|
30642
30689
|
// apps/desktop/src/daemon/runtime/attachment-access.ts
|
|
30643
30690
|
import { createHash as createHash16 } from "node:crypto";
|
|
30644
|
-
import
|
|
30691
|
+
import path42 from "node:path";
|
|
30645
30692
|
import process2 from "node:process";
|
|
30646
30693
|
var RuntimeAttachmentAccess;
|
|
30647
30694
|
var init_attachment_access = __esm({
|
|
@@ -30679,7 +30726,7 @@ var init_attachment_access = __esm({
|
|
|
30679
30726
|
const cached = createCachedUploadTaskStore({
|
|
30680
30727
|
base,
|
|
30681
30728
|
cache: () => cache2 ??= (async () => {
|
|
30682
|
-
const root =
|
|
30729
|
+
const root = path42.join(this.ports.options().niumaDataDirectory ?? desktopPlatform().directories.data, "attachments", "device-cache");
|
|
30683
30730
|
return createDeviceUploadCache({
|
|
30684
30731
|
storage: composeLegacyUploadContents(await openPrivateUploadDirectories(root), privateBinaryFiles),
|
|
30685
30732
|
admit: (bytes3, operation) => this.ports.attachmentStorage().withAttachmentUploadAdmission(void 0, bytes3, operation)
|
|
@@ -30823,8 +30870,8 @@ var init_attachment_access = __esm({
|
|
|
30823
30870
|
});
|
|
30824
30871
|
|
|
30825
30872
|
// apps/desktop/src/niuma/project-state.ts
|
|
30826
|
-
import
|
|
30827
|
-
import
|
|
30873
|
+
import fs31 from "node:fs/promises";
|
|
30874
|
+
import path43 from "node:path";
|
|
30828
30875
|
import { z as z10 } from "zod";
|
|
30829
30876
|
function emptyProjectState() {
|
|
30830
30877
|
return {
|
|
@@ -30893,9 +30940,9 @@ function isMissingFileError(error2) {
|
|
|
30893
30940
|
return error2 instanceof Error && "code" in error2 && error2.code === "ENOENT";
|
|
30894
30941
|
}
|
|
30895
30942
|
async function readProjectState(codexHome) {
|
|
30896
|
-
const statePath =
|
|
30943
|
+
const statePath = path43.join(codexHome, ".codex-global-state.json");
|
|
30897
30944
|
try {
|
|
30898
|
-
const raw = await
|
|
30945
|
+
const raw = await fs31.readFile(statePath, "utf8");
|
|
30899
30946
|
const parsed = RawProjectStateSchema.parse(JSON.parse(raw));
|
|
30900
30947
|
const localProjects = readLocalProjects(parsed["local-projects"]);
|
|
30901
30948
|
const rootsByProjectId = new Map(localProjects.map((project3) => [project3.id, project3.root]));
|
|
@@ -30988,7 +31035,7 @@ var init_project_state = __esm({
|
|
|
30988
31035
|
});
|
|
30989
31036
|
|
|
30990
31037
|
// apps/desktop/src/niuma/session-originator.ts
|
|
30991
|
-
import
|
|
31038
|
+
import fs32 from "node:fs/promises";
|
|
30992
31039
|
function record9(value) {
|
|
30993
31040
|
return value && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
30994
31041
|
}
|
|
@@ -31005,7 +31052,7 @@ async function readFirstLine(filePath) {
|
|
|
31005
31052
|
let byteCount = 0;
|
|
31006
31053
|
let position = 0;
|
|
31007
31054
|
try {
|
|
31008
|
-
handle = await
|
|
31055
|
+
handle = await fs32.open(filePath, "r");
|
|
31009
31056
|
while (true) {
|
|
31010
31057
|
const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
|
|
31011
31058
|
const { bytesRead } = await handle.read(buffer, 0, buffer.length, position);
|
|
@@ -31101,7 +31148,7 @@ var init_session_originator = __esm({
|
|
|
31101
31148
|
});
|
|
31102
31149
|
|
|
31103
31150
|
// apps/desktop/src/niuma/session-timestamps.ts
|
|
31104
|
-
import
|
|
31151
|
+
import fs33 from "node:fs/promises";
|
|
31105
31152
|
import { createInterface as createInterface4 } from "node:readline";
|
|
31106
31153
|
function record10(value) {
|
|
31107
31154
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -31387,7 +31434,7 @@ var init_session_timestamps = __esm({
|
|
|
31387
31434
|
try {
|
|
31388
31435
|
const sessionPath = explicitPath === void 0 ? await this.resolveSessionPath(threadId2) : explicitPath;
|
|
31389
31436
|
if (!sessionPath || this.closed) return "unavailable";
|
|
31390
|
-
const stat4 = await
|
|
31437
|
+
const stat4 = await fs33.stat(sessionPath);
|
|
31391
31438
|
if (this.closed) return "unavailable";
|
|
31392
31439
|
return JSON.stringify([stat4.dev, stat4.ino, stat4.size, stat4.mtimeMs, stat4.ctimeMs]);
|
|
31393
31440
|
} catch {
|
|
@@ -31560,7 +31607,7 @@ var init_session_timestamps = __esm({
|
|
|
31560
31607
|
}
|
|
31561
31608
|
}
|
|
31562
31609
|
async readReplay(sessionPath, threadId2, fingerprint2, empty) {
|
|
31563
|
-
const handle = await
|
|
31610
|
+
const handle = await fs33.open(sessionPath, "r");
|
|
31564
31611
|
if (this.closed) {
|
|
31565
31612
|
await handle.close();
|
|
31566
31613
|
return empty;
|
|
@@ -32155,7 +32202,7 @@ var init_app_server_upgrade = __esm({
|
|
|
32155
32202
|
|
|
32156
32203
|
// apps/desktop/src/daemon/codex-subagent-avatars.ts
|
|
32157
32204
|
import { open as open3 } from "node:fs/promises";
|
|
32158
|
-
import
|
|
32205
|
+
import path44 from "node:path";
|
|
32159
32206
|
import sharp from "sharp";
|
|
32160
32207
|
function record11(value) {
|
|
32161
32208
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
@@ -32196,7 +32243,7 @@ async function parseCatalog(source2, readAsset) {
|
|
|
32196
32243
|
}
|
|
32197
32244
|
return new CodexSubagentAvatars(images);
|
|
32198
32245
|
}
|
|
32199
|
-
async function loadCodexSubagentAvatars(archivePath =
|
|
32246
|
+
async function loadCodexSubagentAvatars(archivePath = path44.join(path44.dirname(resolveDefaultAppServerExecutablePath()), "app.asar")) {
|
|
32200
32247
|
let file;
|
|
32201
32248
|
try {
|
|
32202
32249
|
file = await open3(archivePath, "r");
|
|
@@ -32263,8 +32310,8 @@ var init_codex_subagent_avatars = __esm({
|
|
|
32263
32310
|
});
|
|
32264
32311
|
|
|
32265
32312
|
// apps/desktop/src/platform/private-document-files.ts
|
|
32266
|
-
import
|
|
32267
|
-
import
|
|
32313
|
+
import fs34 from "node:fs";
|
|
32314
|
+
import path45 from "node:path";
|
|
32268
32315
|
import { randomUUID as randomUUID25 } from "node:crypto";
|
|
32269
32316
|
function checkLimit(maxBytes) {
|
|
32270
32317
|
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1 || maxBytes > 32 * 1024 * 1024) throw new PrivateDocumentFileError("capacity");
|
|
@@ -32276,7 +32323,7 @@ function trusted3(stats, directory3 = false, strictDirectory = false) {
|
|
|
32276
32323
|
}
|
|
32277
32324
|
function statFile(file, maxBytes) {
|
|
32278
32325
|
try {
|
|
32279
|
-
const stats =
|
|
32326
|
+
const stats = fs34.lstatSync(file, { bigint: true });
|
|
32280
32327
|
if (!trusted3(stats)) throw new PrivateDocumentFileError("unavailable");
|
|
32281
32328
|
if (stats.size > BigInt(maxBytes)) throw new PrivateDocumentFileError("capacity");
|
|
32282
32329
|
return stats;
|
|
@@ -32296,33 +32343,33 @@ function readPosix(file, maxBytes, strictDirectory) {
|
|
|
32296
32343
|
let directoryFd;
|
|
32297
32344
|
let fd;
|
|
32298
32345
|
try {
|
|
32299
|
-
const directory3 =
|
|
32346
|
+
const directory3 = path45.dirname(file);
|
|
32300
32347
|
let parent;
|
|
32301
32348
|
try {
|
|
32302
|
-
parent =
|
|
32349
|
+
parent = fs34.lstatSync(directory3, { bigint: true });
|
|
32303
32350
|
} catch (error2) {
|
|
32304
32351
|
if (missing(error2)) return null;
|
|
32305
32352
|
throw error2;
|
|
32306
32353
|
}
|
|
32307
32354
|
if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
|
|
32308
|
-
directoryFd =
|
|
32309
|
-
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");
|
|
32310
32357
|
const original = statFile(file, maxBytes);
|
|
32311
32358
|
if (original === null) return null;
|
|
32312
|
-
fd =
|
|
32313
|
-
const opened =
|
|
32359
|
+
fd = fs34.openSync(file, fs34.constants.O_RDONLY | fs34.constants.O_NOFOLLOW);
|
|
32360
|
+
const opened = fs34.fstatSync(fd, { bigint: true });
|
|
32314
32361
|
if (!trusted3(opened) || !same5(original, opened) || original.size !== opened.size) throw new PrivateDocumentFileError("unavailable");
|
|
32315
32362
|
const contents = Buffer.alloc(maxBytes + 1);
|
|
32316
32363
|
try {
|
|
32317
32364
|
let length = 0;
|
|
32318
32365
|
while (length < contents.length) {
|
|
32319
|
-
const count =
|
|
32366
|
+
const count = fs34.readSync(fd, contents, length, contents.length - length, null);
|
|
32320
32367
|
if (count === 0) break;
|
|
32321
32368
|
length += count;
|
|
32322
32369
|
}
|
|
32323
32370
|
if (length > maxBytes) throw new PrivateDocumentFileError("capacity");
|
|
32324
32371
|
const current2 = statFile(file, maxBytes);
|
|
32325
|
-
if (current2 === null || !same5(original, current2) || !same5(parent,
|
|
32372
|
+
if (current2 === null || !same5(original, current2) || !same5(parent, fs34.lstatSync(directory3, { bigint: true }))) {
|
|
32326
32373
|
throw new PrivateDocumentFileError("unavailable");
|
|
32327
32374
|
}
|
|
32328
32375
|
return decode(contents.subarray(0, length));
|
|
@@ -32331,42 +32378,42 @@ function readPosix(file, maxBytes, strictDirectory) {
|
|
|
32331
32378
|
}
|
|
32332
32379
|
} finally {
|
|
32333
32380
|
try {
|
|
32334
|
-
if (fd !== void 0)
|
|
32381
|
+
if (fd !== void 0) fs34.closeSync(fd);
|
|
32335
32382
|
} finally {
|
|
32336
|
-
if (directoryFd !== void 0)
|
|
32383
|
+
if (directoryFd !== void 0) fs34.closeSync(directoryFd);
|
|
32337
32384
|
}
|
|
32338
32385
|
}
|
|
32339
32386
|
}
|
|
32340
32387
|
function writePosix(file, body, maxBytes, strictDirectory) {
|
|
32341
|
-
const directory3 =
|
|
32342
|
-
const temporary =
|
|
32388
|
+
const directory3 = path45.dirname(file);
|
|
32389
|
+
const temporary = path45.join(directory3, `.${path45.basename(file)}.${randomUUID25()}.tmp`);
|
|
32343
32390
|
let directoryFd;
|
|
32344
32391
|
let fd;
|
|
32345
32392
|
let created = false;
|
|
32346
32393
|
let renamed = false;
|
|
32347
32394
|
try {
|
|
32348
|
-
|
|
32349
|
-
const parent =
|
|
32395
|
+
fs34.mkdirSync(directory3, { recursive: true, mode: 448 });
|
|
32396
|
+
const parent = fs34.lstatSync(directory3, { bigint: true });
|
|
32350
32397
|
if (!trusted3(parent, true, strictDirectory)) throw new PrivateDocumentFileError("unavailable");
|
|
32351
|
-
directoryFd =
|
|
32352
|
-
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");
|
|
32353
32400
|
const original = statFile(file, maxBytes);
|
|
32354
|
-
fd =
|
|
32401
|
+
fd = fs34.openSync(temporary, fs34.constants.O_WRONLY | fs34.constants.O_CREAT | fs34.constants.O_EXCL | fs34.constants.O_NOFOLLOW, 384);
|
|
32355
32402
|
created = true;
|
|
32356
|
-
const temporaryIdentity =
|
|
32403
|
+
const temporaryIdentity = fs34.fstatSync(fd, { bigint: true });
|
|
32357
32404
|
if (!trusted3(temporaryIdentity)) throw new PrivateDocumentFileError("unavailable");
|
|
32358
|
-
|
|
32359
|
-
|
|
32360
|
-
|
|
32405
|
+
fs34.writeFileSync(fd, body);
|
|
32406
|
+
fs34.fsyncSync(fd);
|
|
32407
|
+
fs34.closeSync(fd);
|
|
32361
32408
|
fd = void 0;
|
|
32362
32409
|
const current2 = statFile(file, maxBytes);
|
|
32363
|
-
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))) {
|
|
32364
32411
|
throw new PrivateDocumentFileError("unavailable");
|
|
32365
32412
|
}
|
|
32366
|
-
|
|
32413
|
+
fs34.renameSync(temporary, file);
|
|
32367
32414
|
renamed = true;
|
|
32368
32415
|
created = false;
|
|
32369
|
-
|
|
32416
|
+
fs34.fsyncSync(directoryFd);
|
|
32370
32417
|
} catch (error2) {
|
|
32371
32418
|
if (error2 instanceof PrivateDocumentFileError && !renamed) throw error2;
|
|
32372
32419
|
throw new PrivateDocumentFileError("write_failed", renamed);
|
|
@@ -32374,7 +32421,7 @@ function writePosix(file, body, maxBytes, strictDirectory) {
|
|
|
32374
32421
|
try {
|
|
32375
32422
|
if (fd !== void 0) {
|
|
32376
32423
|
try {
|
|
32377
|
-
|
|
32424
|
+
fs34.closeSync(fd);
|
|
32378
32425
|
} catch {
|
|
32379
32426
|
}
|
|
32380
32427
|
}
|
|
@@ -32382,14 +32429,14 @@ function writePosix(file, body, maxBytes, strictDirectory) {
|
|
|
32382
32429
|
try {
|
|
32383
32430
|
if (directoryFd !== void 0) {
|
|
32384
32431
|
try {
|
|
32385
|
-
|
|
32432
|
+
fs34.closeSync(directoryFd);
|
|
32386
32433
|
} catch {
|
|
32387
32434
|
}
|
|
32388
32435
|
}
|
|
32389
32436
|
} finally {
|
|
32390
32437
|
if (created) {
|
|
32391
32438
|
try {
|
|
32392
|
-
|
|
32439
|
+
fs34.unlinkSync(temporary);
|
|
32393
32440
|
} catch {
|
|
32394
32441
|
}
|
|
32395
32442
|
}
|
|
@@ -32423,7 +32470,7 @@ async function windowsDocument(file, maxBytes, body) {
|
|
|
32423
32470
|
return result;
|
|
32424
32471
|
}
|
|
32425
32472
|
function serialFile(file, operation) {
|
|
32426
|
-
const absolute =
|
|
32473
|
+
const absolute = path45.resolve(file);
|
|
32427
32474
|
const key = desktopPlatform().id === "windows" ? absolute.toLowerCase() : absolute;
|
|
32428
32475
|
const result = (operations.get(key) ?? Promise.resolve()).then(operation);
|
|
32429
32476
|
const tail = result.then(() => {
|
|
@@ -32441,7 +32488,7 @@ function documentFiles(strictDirectory, guard) {
|
|
|
32441
32488
|
return serialFile(file, async () => {
|
|
32442
32489
|
try {
|
|
32443
32490
|
guard?.();
|
|
32444
|
-
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);
|
|
32445
32492
|
guard?.();
|
|
32446
32493
|
return body;
|
|
32447
32494
|
} catch (error2) {
|
|
@@ -32456,7 +32503,7 @@ function documentFiles(strictDirectory, guard) {
|
|
|
32456
32503
|
await serialFile(file, async () => {
|
|
32457
32504
|
guard?.();
|
|
32458
32505
|
if (desktopPlatform().id === "windows") await windowsDocument(file, maxBytes, body);
|
|
32459
|
-
else writePosix(
|
|
32506
|
+
else writePosix(path45.resolve(file), body, maxBytes, strictDirectory);
|
|
32460
32507
|
try {
|
|
32461
32508
|
guard?.();
|
|
32462
32509
|
} catch {
|
|
@@ -32495,7 +32542,7 @@ var init_private_document_files = __esm({
|
|
|
32495
32542
|
});
|
|
32496
32543
|
|
|
32497
32544
|
// apps/desktop/src/local-state/paths.ts
|
|
32498
|
-
import
|
|
32545
|
+
import path46 from "node:path";
|
|
32499
32546
|
function applicationStateDirectory() {
|
|
32500
32547
|
return desktopPlatform().directories.state;
|
|
32501
32548
|
}
|
|
@@ -32503,37 +32550,37 @@ function cliCacheDirectory() {
|
|
|
32503
32550
|
return desktopPlatform().directories.cliCache;
|
|
32504
32551
|
}
|
|
32505
32552
|
function managedThreadsStatePath() {
|
|
32506
|
-
return
|
|
32553
|
+
return path46.join(applicationStateDirectory(), "managed-threads-v1.json");
|
|
32507
32554
|
}
|
|
32508
32555
|
function threadSettingsStatePath() {
|
|
32509
|
-
return
|
|
32556
|
+
return path46.join(applicationStateDirectory(), "thread-settings-cache-v1.json");
|
|
32510
32557
|
}
|
|
32511
32558
|
function threadListStatePath() {
|
|
32512
|
-
return
|
|
32559
|
+
return path46.join(applicationStateDirectory(), "thread-list-cache-v1.json");
|
|
32513
32560
|
}
|
|
32514
32561
|
function daemonMetricsStatePath() {
|
|
32515
|
-
return
|
|
32562
|
+
return path46.join(applicationStateDirectory(), "daemon-metrics-v1.json");
|
|
32516
32563
|
}
|
|
32517
32564
|
function desktopIdentityCandidatesStatePath() {
|
|
32518
|
-
return
|
|
32565
|
+
return path46.join(applicationStateDirectory(), "desktop-identity-candidates-v1.json");
|
|
32519
32566
|
}
|
|
32520
32567
|
function pendingRequestsCachePath() {
|
|
32521
|
-
return
|
|
32568
|
+
return path46.join(cliCacheDirectory(), "pending-requests-v1.json");
|
|
32522
32569
|
}
|
|
32523
32570
|
function idempotencyCachePath() {
|
|
32524
|
-
return
|
|
32571
|
+
return path46.join(cliCacheDirectory(), "idempotency-v1.json");
|
|
32525
32572
|
}
|
|
32526
32573
|
function messageSubmissionsStatePath() {
|
|
32527
|
-
return
|
|
32574
|
+
return path46.join(applicationStateDirectory(), "message-submissions-v1.json");
|
|
32528
32575
|
}
|
|
32529
32576
|
function deviceNameStatePath() {
|
|
32530
|
-
return
|
|
32577
|
+
return path46.join(applicationStateDirectory(), "device-name-v1.json");
|
|
32531
32578
|
}
|
|
32532
32579
|
function threadReadReceiptsStatePath() {
|
|
32533
|
-
return
|
|
32580
|
+
return path46.join(applicationStateDirectory(), "thread-read-receipts-v1.json");
|
|
32534
32581
|
}
|
|
32535
32582
|
function asyncQuestionFactsStatePath() {
|
|
32536
|
-
return
|
|
32583
|
+
return path46.join(applicationStateDirectory(), "async-question-facts", "ledger-v1.json");
|
|
32537
32584
|
}
|
|
32538
32585
|
var init_paths2 = __esm({
|
|
32539
32586
|
"apps/desktop/src/local-state/paths.ts"() {
|
|
@@ -32831,7 +32878,7 @@ var init_thread_list_cache = __esm({
|
|
|
32831
32878
|
});
|
|
32832
32879
|
|
|
32833
32880
|
// apps/desktop/src/daemon/thread-settings-cache.ts
|
|
32834
|
-
import { isDeepStrictEqual as
|
|
32881
|
+
import { isDeepStrictEqual as isDeepStrictEqual3 } from "node:util";
|
|
32835
32882
|
function cloneModel(model) {
|
|
32836
32883
|
return model ? { ...model } : null;
|
|
32837
32884
|
}
|
|
@@ -33098,11 +33145,11 @@ var init_thread_settings_cache = __esm({
|
|
|
33098
33145
|
const project3 = this.projects.get(input.projectRoot) ?? this.emptySettingsEntry(now);
|
|
33099
33146
|
const nextThread = this.mergeRememberedEntry(thread4, input, input.projectRoot);
|
|
33100
33147
|
const nextProject = this.mergeRememberedEntry(project3, input);
|
|
33101
|
-
const threadChanged = !
|
|
33148
|
+
const threadChanged = !isDeepStrictEqual3(
|
|
33102
33149
|
publicLayer(thread4),
|
|
33103
33150
|
publicLayer(nextThread)
|
|
33104
33151
|
) || thread4.projectRoot !== nextThread.projectRoot;
|
|
33105
|
-
const projectChanged = !
|
|
33152
|
+
const projectChanged = !isDeepStrictEqual3(publicLayer(project3), publicLayer(nextProject));
|
|
33106
33153
|
if (!threadChanged && !projectChanged) {
|
|
33107
33154
|
const existingThread = this.threads.get(input.threadId);
|
|
33108
33155
|
const existingProject = this.projects.get(input.projectRoot);
|
|
@@ -34139,7 +34186,7 @@ var init_thread_timeline_cache = __esm({
|
|
|
34139
34186
|
});
|
|
34140
34187
|
|
|
34141
34188
|
// apps/desktop/src/daemon/thread-state-store.ts
|
|
34142
|
-
import
|
|
34189
|
+
import path47 from "node:path";
|
|
34143
34190
|
function projectRecency(entry) {
|
|
34144
34191
|
return entry.threads.reduce(
|
|
34145
34192
|
(latest, thread4) => Math.max(latest, thread4.recencyAt ?? thread4.updatedAt),
|
|
@@ -34248,8 +34295,8 @@ function normalizePathForCompare(value) {
|
|
|
34248
34295
|
if (!value) {
|
|
34249
34296
|
return "";
|
|
34250
34297
|
}
|
|
34251
|
-
const normalized =
|
|
34252
|
-
if (normalized.length > 1 && normalized.endsWith(
|
|
34298
|
+
const normalized = path47.normalize(value);
|
|
34299
|
+
if (normalized.length > 1 && normalized.endsWith(path47.sep)) {
|
|
34253
34300
|
return normalized.slice(0, -1);
|
|
34254
34301
|
}
|
|
34255
34302
|
return normalized;
|
|
@@ -34274,7 +34321,7 @@ function isPathWithinRoot(cwd, root) {
|
|
|
34274
34321
|
if (normalizedCwd === normalizedRoot) {
|
|
34275
34322
|
return true;
|
|
34276
34323
|
}
|
|
34277
|
-
return normalizedCwd.startsWith(`${normalizedRoot}${
|
|
34324
|
+
return normalizedCwd.startsWith(`${normalizedRoot}${path47.sep}`);
|
|
34278
34325
|
}
|
|
34279
34326
|
function findLongestMatchingRoot(cwd, roots) {
|
|
34280
34327
|
let matched = null;
|
|
@@ -34297,7 +34344,7 @@ function labelForRoot(root, labels) {
|
|
|
34297
34344
|
};
|
|
34298
34345
|
}
|
|
34299
34346
|
return {
|
|
34300
|
-
projectName:
|
|
34347
|
+
projectName: path47.basename(root) || root,
|
|
34301
34348
|
projectNameSource: "basename"
|
|
34302
34349
|
};
|
|
34303
34350
|
}
|
|
@@ -35805,10 +35852,10 @@ var init_bootstrap = __esm({
|
|
|
35805
35852
|
});
|
|
35806
35853
|
|
|
35807
35854
|
// apps/desktop/src/platform/private-cache-files.ts
|
|
35808
|
-
import
|
|
35809
|
-
import
|
|
35855
|
+
import fs35 from "node:fs";
|
|
35856
|
+
import path48 from "node:path";
|
|
35810
35857
|
function serialize(file, operation) {
|
|
35811
|
-
const key = process.platform === "win32" ?
|
|
35858
|
+
const key = process.platform === "win32" ? path48.resolve(file).toLowerCase() : path48.resolve(file);
|
|
35812
35859
|
const next = (tails.get(key) ?? Promise.resolve()).then(operation);
|
|
35813
35860
|
const tail = next.catch(() => {
|
|
35814
35861
|
});
|
|
@@ -35823,23 +35870,23 @@ function trusted4(stat4, directory3 = false) {
|
|
|
35823
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);
|
|
35824
35871
|
}
|
|
35825
35872
|
async function withMacLock(file, operation) {
|
|
35826
|
-
const directory3 =
|
|
35827
|
-
const lock =
|
|
35828
|
-
|
|
35829
|
-
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 });
|
|
35830
35877
|
if (!trusted4(parent, true)) throw new PrivateDocumentFileError("unavailable");
|
|
35831
35878
|
const deadline = Date.now() + LOCK_WAIT_MS;
|
|
35832
35879
|
let fd;
|
|
35833
35880
|
for (; ; ) {
|
|
35834
35881
|
let initial = null;
|
|
35835
35882
|
try {
|
|
35836
|
-
initial =
|
|
35883
|
+
initial = fs35.lstatSync(lock, { bigint: true });
|
|
35837
35884
|
} catch (error2) {
|
|
35838
35885
|
if (error2.code !== "ENOENT") throw error2;
|
|
35839
35886
|
}
|
|
35840
35887
|
if (initial && !trusted4(initial)) throw new PrivateDocumentFileError("unavailable");
|
|
35841
35888
|
try {
|
|
35842
|
-
fd =
|
|
35889
|
+
fd = fs35.openSync(lock, fs35.constants.O_RDWR | fs35.constants.O_CREAT | fs35.constants.O_NOFOLLOW | fs35.constants.O_NONBLOCK | 32, 384);
|
|
35843
35890
|
} catch (error2) {
|
|
35844
35891
|
const code = error2.code;
|
|
35845
35892
|
if (code !== "EAGAIN" && code !== "EWOULDBLOCK" || Date.now() >= deadline) throw error2;
|
|
@@ -35847,10 +35894,10 @@ async function withMacLock(file, operation) {
|
|
|
35847
35894
|
continue;
|
|
35848
35895
|
}
|
|
35849
35896
|
try {
|
|
35850
|
-
const opened =
|
|
35897
|
+
const opened = fs35.fstatSync(fd, { bigint: true });
|
|
35851
35898
|
const verify = () => {
|
|
35852
|
-
const current2 =
|
|
35853
|
-
const currentParent =
|
|
35899
|
+
const current2 = fs35.lstatSync(lock, { bigint: true });
|
|
35900
|
+
const currentParent = fs35.lstatSync(directory3, { bigint: true });
|
|
35854
35901
|
if (!trusted4(opened) || !trusted4(current2) || !same6(opened, current2) || initial !== null && !same6(initial, opened) || !trusted4(currentParent, true) || !same6(parent, currentParent)) {
|
|
35855
35902
|
throw new PrivateDocumentFileError("unavailable");
|
|
35856
35903
|
}
|
|
@@ -35860,7 +35907,7 @@ async function withMacLock(file, operation) {
|
|
|
35860
35907
|
verify();
|
|
35861
35908
|
return value;
|
|
35862
35909
|
} finally {
|
|
35863
|
-
|
|
35910
|
+
fs35.closeSync(fd);
|
|
35864
35911
|
}
|
|
35865
35912
|
}
|
|
35866
35913
|
}
|
|
@@ -35891,7 +35938,7 @@ var init_private_cache_files = __esm({
|
|
|
35891
35938
|
return serialize(file, async () => {
|
|
35892
35939
|
checkLimit2(maxBytes);
|
|
35893
35940
|
try {
|
|
35894
|
-
|
|
35941
|
+
fs35.lstatSync(file);
|
|
35895
35942
|
} catch (error2) {
|
|
35896
35943
|
if (error2.code === "ENOENT") return null;
|
|
35897
35944
|
throw error2;
|
|
@@ -35904,7 +35951,7 @@ var init_private_cache_files = __esm({
|
|
|
35904
35951
|
checkLimit2(maxBytes);
|
|
35905
35952
|
if (process.platform === "win32") return windowsTransaction(file, maxBytes, transform);
|
|
35906
35953
|
if (process.platform !== "darwin") throw new PrivateDocumentFileError("unavailable");
|
|
35907
|
-
return withMacLock(
|
|
35954
|
+
return withMacLock(path48.resolve(file), async (verify) => {
|
|
35908
35955
|
const result = transform(await privateStateFiles.read(file, maxBytes));
|
|
35909
35956
|
verify();
|
|
35910
35957
|
if (result.body !== void 0) await privateStateFiles.write(file, Buffer.from(result.body), maxBytes);
|
|
@@ -36188,7 +36235,7 @@ var init_pending_cache = __esm({
|
|
|
36188
36235
|
});
|
|
36189
36236
|
|
|
36190
36237
|
// apps/desktop/src/niuma/session-pending.ts
|
|
36191
|
-
import
|
|
36238
|
+
import fs36 from "node:fs";
|
|
36192
36239
|
function objectRecord7(value) {
|
|
36193
36240
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
36194
36241
|
}
|
|
@@ -36211,7 +36258,7 @@ function inferPendingRequestFromSession(threadId2, sessionPath, latestTurnId = n
|
|
|
36211
36258
|
}
|
|
36212
36259
|
let lines;
|
|
36213
36260
|
try {
|
|
36214
|
-
lines =
|
|
36261
|
+
lines = fs36.readFileSync(sessionPath, "utf8").trimEnd().split(/\n/).filter(Boolean);
|
|
36215
36262
|
} catch {
|
|
36216
36263
|
return null;
|
|
36217
36264
|
}
|
|
@@ -36278,7 +36325,7 @@ var init_session_pending = __esm({
|
|
|
36278
36325
|
|
|
36279
36326
|
// apps/desktop/src/remote-session/connection-handoff-service.ts
|
|
36280
36327
|
import { randomBytes as randomBytes4 } from "node:crypto";
|
|
36281
|
-
import { isDeepStrictEqual as
|
|
36328
|
+
import { isDeepStrictEqual as isDeepStrictEqual4 } from "node:util";
|
|
36282
36329
|
function logicalDescriptor(descriptor) {
|
|
36283
36330
|
if (descriptor.pathname !== "/api/v1/thread/open") return descriptor;
|
|
36284
36331
|
const { load_id: _loadId, range_resume_token: _rangeToken, ...query2 } = descriptor.query;
|
|
@@ -36387,7 +36434,7 @@ var init_connection_handoff_service = __esm({
|
|
|
36387
36434
|
this.live(existing);
|
|
36388
36435
|
if (existing.scope.sessionId !== scope.sessionId) fail15(200004, "\u4EA4\u63A5\u4E0D\u53EF\u7528");
|
|
36389
36436
|
if (existing.candidateSession !== request2.target_session_id) fail15(100101, "\u4EA4\u63A5\u76EE\u6807\u51B2\u7A81");
|
|
36390
|
-
if (!
|
|
36437
|
+
if (!isDeepStrictEqual4(existing.response.tickets.map(({ source_id, epoch }) => ({ source_id, epoch })), request2.sources)) fail15(100101, "\u4EA4\u63A5\u5185\u5BB9\u51B2\u7A81");
|
|
36391
36438
|
return structuredClone(existing.response);
|
|
36392
36439
|
}
|
|
36393
36440
|
for (const group3 of [...this.groups.values()]) {
|
|
@@ -36397,7 +36444,7 @@ var init_connection_handoff_service = __esm({
|
|
|
36397
36444
|
const selected = request2.sources.map((identity6) => {
|
|
36398
36445
|
const source2 = this.sources.get(identity6.source_id);
|
|
36399
36446
|
if (!source2 || source2.bindingId !== scope.bindingId || source2.ownerSessionId() !== scope.sessionId) fail15(200004, "\u4EA4\u63A5\u4E0D\u53EF\u7528");
|
|
36400
|
-
if (!
|
|
36447
|
+
if (!isDeepStrictEqual4(source2.identity(), identity6)) fail15(100202, "\u903B\u8F91\u6E90\u5DF2\u5931\u6548");
|
|
36401
36448
|
return { source: source2, identity: identity6 };
|
|
36402
36449
|
});
|
|
36403
36450
|
const target = this.targets.get(this.key(scope, request2.target_session_id));
|
|
@@ -36459,9 +36506,9 @@ var init_connection_handoff_service = __esm({
|
|
|
36459
36506
|
if (group2.scope.bindingId !== scope.bindingId || group2.scope.sessionId === scope.sessionId) fail15(200004, "\u4EA4\u63A5\u4E0D\u53EF\u7528");
|
|
36460
36507
|
const ticket2 = group2.tickets.find((ticket3) => ticket3.token === token3);
|
|
36461
36508
|
if (ticket2.consumer || group2.committed) fail15(100202, "\u4EA4\u63A5\u7968\u636E\u5DF2\u9886\u53D6");
|
|
36462
|
-
if (!
|
|
36509
|
+
if (!isDeepStrictEqual4(logicalDescriptor(ticket2.source.descriptor), logicalDescriptor(descriptor))) fail15(200004, "\u4EA4\u63A5\u4E0D\u53EF\u7528");
|
|
36463
36510
|
if (group2.candidateSession !== scope.sessionId) fail15(200004, "\u4EA4\u63A5\u4E0D\u53EF\u7528");
|
|
36464
|
-
if (!
|
|
36511
|
+
if (!isDeepStrictEqual4(ticket2.source.identity(), ticket2.identity)) fail15(100202, "\u903B\u8F91\u6E90\u5DF2\u5931\u6548");
|
|
36465
36512
|
const claimed = ticket2.reservation.claim(scope, context);
|
|
36466
36513
|
let closed = false;
|
|
36467
36514
|
const consumer = {
|
|
@@ -36496,7 +36543,7 @@ var init_connection_handoff_service = __esm({
|
|
|
36496
36543
|
if (request2.tickets.length !== group2.tickets.length || group2.tickets.some((ticket2) => !request2.tickets.includes(ticket2.token))) fail15(100101, "\u4EA4\u63A5\u7968\u636E\u96C6\u5408\u4E0D\u5339\u914D");
|
|
36497
36544
|
group2.target.assertCurrent();
|
|
36498
36545
|
for (const ticket2 of group2.tickets) {
|
|
36499
|
-
if (!ticket2.consumer || ticket2.sessionId !== scope.sessionId || !
|
|
36546
|
+
if (!ticket2.consumer || ticket2.sessionId !== scope.sessionId || !isDeepStrictEqual4(ticket2.source.identity(), ticket2.identity)) fail15(100202, "\u4EA4\u63A5\u5C1A\u672A\u5C31\u7EEA");
|
|
36500
36547
|
ticket2.consumer.assertCurrent();
|
|
36501
36548
|
}
|
|
36502
36549
|
if (!group2.committed) {
|
|
@@ -37023,7 +37070,7 @@ var init_settings = __esm({
|
|
|
37023
37070
|
|
|
37024
37071
|
// apps/desktop/src/direct-gateway/v5-binding-store.ts
|
|
37025
37072
|
import { randomUUID as randomUUID26, createHash as createHash17 } from "node:crypto";
|
|
37026
|
-
import
|
|
37073
|
+
import path49 from "node:path";
|
|
37027
37074
|
function bindingFileError() {
|
|
37028
37075
|
return new Error("Desktop V5 Binding \u6587\u4EF6\u65E0\u6548");
|
|
37029
37076
|
}
|
|
@@ -37157,7 +37204,7 @@ function parseResetMarker(value, desktopId) {
|
|
|
37157
37204
|
}
|
|
37158
37205
|
}
|
|
37159
37206
|
function resolveDefaultDesktopV5BindingFilePath() {
|
|
37160
|
-
return
|
|
37207
|
+
return path49.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME);
|
|
37161
37208
|
}
|
|
37162
37209
|
function pushDisplayName(name2) {
|
|
37163
37210
|
let result = "";
|
|
@@ -37224,7 +37271,7 @@ var init_v5_binding_store = __esm({
|
|
|
37224
37271
|
for (const wake of this.pushWaiters) wake();
|
|
37225
37272
|
}
|
|
37226
37273
|
constructor(options = {}) {
|
|
37227
|
-
this.filePath =
|
|
37274
|
+
this.filePath = path49.resolve(options.file_path ?? resolveDefaultDesktopV5BindingFilePath());
|
|
37228
37275
|
this.files = options.files ?? privateDocumentFiles;
|
|
37229
37276
|
}
|
|
37230
37277
|
async load(desktopId) {
|
|
@@ -37474,7 +37521,7 @@ var init_v5_binding_store = __esm({
|
|
|
37474
37521
|
await this.writeAtomicFile(this.resetMarkerPath(), serializeResetMarker(desktopId), bindingFileError);
|
|
37475
37522
|
}
|
|
37476
37523
|
resetMarkerPath() {
|
|
37477
|
-
return
|
|
37524
|
+
return path49.join(path49.dirname(this.filePath), RESET_MARKER_FILE_NAME);
|
|
37478
37525
|
}
|
|
37479
37526
|
async writeAtomicFile(targetPath2, body, failure) {
|
|
37480
37527
|
try {
|
|
@@ -42679,7 +42726,7 @@ var init_candidate_catalog2 = __esm({
|
|
|
42679
42726
|
});
|
|
42680
42727
|
|
|
42681
42728
|
// apps/desktop/src/direct-gateway/identity-store.ts
|
|
42682
|
-
import
|
|
42729
|
+
import path50 from "node:path";
|
|
42683
42730
|
function copyIdentity(identity6) {
|
|
42684
42731
|
return {
|
|
42685
42732
|
desktop_id: identity6.desktop_id,
|
|
@@ -42734,7 +42781,7 @@ function deserializeIdentity(value) {
|
|
|
42734
42781
|
}
|
|
42735
42782
|
}
|
|
42736
42783
|
function resolveDefaultDesktopIdentityFilePath() {
|
|
42737
|
-
return
|
|
42784
|
+
return path50.join(desktopPlatform().directories.data, DEFAULT_IDENTITY_FILE_NAME);
|
|
42738
42785
|
}
|
|
42739
42786
|
var IDENTITY_KEY_BYTES2, DEFAULT_IDENTITY_FILE_NAME, MAX_IDENTITY_BYTES, FileDesktopIdentityStore;
|
|
42740
42787
|
var init_identity_store = __esm({
|
|
@@ -42750,7 +42797,7 @@ var init_identity_store = __esm({
|
|
|
42750
42797
|
filePath;
|
|
42751
42798
|
files;
|
|
42752
42799
|
constructor(options = {}) {
|
|
42753
|
-
this.filePath =
|
|
42800
|
+
this.filePath = path50.resolve(options.file_path ?? resolveDefaultDesktopIdentityFilePath());
|
|
42754
42801
|
this.files = options.files ?? privateDocumentFiles;
|
|
42755
42802
|
}
|
|
42756
42803
|
async load() {
|
|
@@ -46163,7 +46210,7 @@ var init_routes3 = __esm({
|
|
|
46163
46210
|
|
|
46164
46211
|
// apps/desktop/src/pairing-web/server.ts
|
|
46165
46212
|
import http3 from "node:http";
|
|
46166
|
-
import
|
|
46213
|
+
import fs37 from "node:fs/promises";
|
|
46167
46214
|
var ASSETS, PairingWebServer;
|
|
46168
46215
|
var init_server3 = __esm({
|
|
46169
46216
|
"apps/desktop/src/pairing-web/server.ts"() {
|
|
@@ -46247,7 +46294,7 @@ var init_server3 = __esm({
|
|
|
46247
46294
|
}
|
|
46248
46295
|
const asset = ASSETS[raw];
|
|
46249
46296
|
if (request2.method !== "GET" || !asset) throw new HttpApiError(404, 900005, "\u63A5\u53E3\u4E0D\u5B58\u5728");
|
|
46250
|
-
const body = await
|
|
46297
|
+
const body = await fs37.readFile(desktopAssetUrl("pairing-web", asset[0]));
|
|
46251
46298
|
response.writeHead(200, { "Content-Type": asset[1] });
|
|
46252
46299
|
response.end(body);
|
|
46253
46300
|
} catch (error2) {
|
|
@@ -48031,21 +48078,21 @@ var init_desktop_timeline_events = __esm({
|
|
|
48031
48078
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
48032
48079
|
continue;
|
|
48033
48080
|
}
|
|
48034
|
-
const
|
|
48035
|
-
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") {
|
|
48036
48083
|
const turnId = turnIdFromEntity(record14(patch.value));
|
|
48037
48084
|
if (turnId) {
|
|
48038
|
-
this.entityTurnIds.set(this.entityKey(threadId2,
|
|
48085
|
+
this.entityTurnIds.set(this.entityKey(threadId2, path71[3]), turnId);
|
|
48039
48086
|
}
|
|
48040
48087
|
continue;
|
|
48041
48088
|
}
|
|
48042
|
-
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") {
|
|
48043
48090
|
continue;
|
|
48044
48091
|
}
|
|
48045
48092
|
const occurredAt4 = Math.floor((this.options.now ?? Date.now)() / 1e3);
|
|
48046
48093
|
const item = normalizeTimelineItem(patch.value, {
|
|
48047
48094
|
threadId: threadId2,
|
|
48048
|
-
turnId: this.entityTurnIds.get(this.entityKey(threadId2,
|
|
48095
|
+
turnId: this.entityTurnIds.get(this.entityKey(threadId2, path71[3])) ?? null,
|
|
48049
48096
|
source: "desktop_ipc",
|
|
48050
48097
|
occurredAt: occurredAt4,
|
|
48051
48098
|
resolveKnownLocalImage
|
|
@@ -48091,8 +48138,8 @@ function assignKnownUnreadFields(target, value) {
|
|
|
48091
48138
|
target.unreadMessageCount = value.unreadMessageCount;
|
|
48092
48139
|
}
|
|
48093
48140
|
}
|
|
48094
|
-
function isUnreadFieldPath(
|
|
48095
|
-
return
|
|
48141
|
+
function isUnreadFieldPath(path71, field2) {
|
|
48142
|
+
return path71.length === 1 && path71[0] === field2 || path71.length === 2 && path71[0] === "conversationState" && path71[1] === field2;
|
|
48096
48143
|
}
|
|
48097
48144
|
function hasUpdateFields(update) {
|
|
48098
48145
|
return "hasUnreadTurn" in update || "unreadMessageCount" in update;
|
|
@@ -48118,19 +48165,19 @@ function extractDesktopUnreadUpdate(frame) {
|
|
|
48118
48165
|
}
|
|
48119
48166
|
for (const patchValue of change.patches) {
|
|
48120
48167
|
const patch = record15(patchValue);
|
|
48121
|
-
const
|
|
48168
|
+
const path71 = Array.isArray(patch.path) ? patch.path : [];
|
|
48122
48169
|
const op = patch.op;
|
|
48123
48170
|
if (op !== "add" && op !== "replace" && op !== "remove") {
|
|
48124
48171
|
continue;
|
|
48125
48172
|
}
|
|
48126
|
-
if (isUnreadFieldPath(
|
|
48173
|
+
if (isUnreadFieldPath(path71, "hasUnreadTurn")) {
|
|
48127
48174
|
if (op === "remove") {
|
|
48128
48175
|
update.hasUnreadTurn = null;
|
|
48129
48176
|
} else if (typeof patch.value === "boolean") {
|
|
48130
48177
|
update.hasUnreadTurn = patch.value;
|
|
48131
48178
|
}
|
|
48132
48179
|
}
|
|
48133
|
-
if (isUnreadFieldPath(
|
|
48180
|
+
if (isUnreadFieldPath(path71, "unreadMessageCount")) {
|
|
48134
48181
|
if (op === "remove") {
|
|
48135
48182
|
update.unreadMessageCount = null;
|
|
48136
48183
|
} else if (isMessageCount(patch.value)) {
|
|
@@ -48827,15 +48874,15 @@ function revisionOf(value) {
|
|
|
48827
48874
|
function occurredAt() {
|
|
48828
48875
|
return Math.floor(Date.now() / 1e3);
|
|
48829
48876
|
}
|
|
48830
|
-
function itemTarget(
|
|
48831
|
-
const index =
|
|
48832
|
-
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) {
|
|
48833
48880
|
return null;
|
|
48834
48881
|
}
|
|
48835
|
-
return { entityKey:
|
|
48882
|
+
return { entityKey: path71[3], index, itemPathLength: 6 };
|
|
48836
48883
|
}
|
|
48837
|
-
function entityTarget(
|
|
48838
|
-
return
|
|
48884
|
+
function entityTarget(path71) {
|
|
48885
|
+
return path71[0] === "turnHistory" && path71[1] === "history" && path71[2] === "entitiesByKey" && typeof path71[3] === "string" ? path71[3] : null;
|
|
48839
48886
|
}
|
|
48840
48887
|
function phaseOf(status2) {
|
|
48841
48888
|
if (status2 === "failed" || status2 === "error") {
|
|
@@ -49121,15 +49168,15 @@ var init_desktop_activity_events = __esm({
|
|
|
49121
49168
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
49122
49169
|
continue;
|
|
49123
49170
|
}
|
|
49124
|
-
const
|
|
49125
|
-
const targetItem = itemTarget(
|
|
49171
|
+
const path71 = array3(patch.path);
|
|
49172
|
+
const targetItem = itemTarget(path71);
|
|
49126
49173
|
if (targetItem) {
|
|
49127
|
-
signals.push(...this.consumeItemPatch(threadId2, state, targetItem,
|
|
49174
|
+
signals.push(...this.consumeItemPatch(threadId2, state, targetItem, path71, patch.value, patch.op));
|
|
49128
49175
|
continue;
|
|
49129
49176
|
}
|
|
49130
|
-
const targetEntity = entityTarget(
|
|
49177
|
+
const targetEntity = entityTarget(path71);
|
|
49131
49178
|
if (targetEntity) {
|
|
49132
|
-
signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity,
|
|
49179
|
+
signals.push(...this.consumeEntityPatch(threadId2, state, targetEntity, path71, patch.value));
|
|
49133
49180
|
}
|
|
49134
49181
|
}
|
|
49135
49182
|
return signals;
|
|
@@ -49203,12 +49250,12 @@ var init_desktop_activity_events = __esm({
|
|
|
49203
49250
|
occurredAt: occurredAt()
|
|
49204
49251
|
}];
|
|
49205
49252
|
}
|
|
49206
|
-
consumeItemPatch(threadId2, state, target,
|
|
49253
|
+
consumeItemPatch(threadId2, state, target, path71, value, op) {
|
|
49207
49254
|
const entity = state.entities.get(target.entityKey);
|
|
49208
49255
|
if (!entity || state.currentActiveEntityKey !== target.entityKey || state.currentActiveTurnId !== entity.turnId) {
|
|
49209
49256
|
return [];
|
|
49210
49257
|
}
|
|
49211
|
-
if (
|
|
49258
|
+
if (path71.length === target.itemPathLength) {
|
|
49212
49259
|
return this.prependLiveTurnStart(threadId2, entity, this.consumeWholeItem(
|
|
49213
49260
|
threadId2,
|
|
49214
49261
|
entity,
|
|
@@ -49218,13 +49265,13 @@ var init_desktop_activity_events = __esm({
|
|
|
49218
49265
|
));
|
|
49219
49266
|
}
|
|
49220
49267
|
const existing = entity.items.get(target.index);
|
|
49221
|
-
if (!existing ||
|
|
49268
|
+
if (!existing || path71.length < target.itemPathLength + 1) {
|
|
49222
49269
|
return [];
|
|
49223
49270
|
}
|
|
49224
|
-
const field2 =
|
|
49271
|
+
const field2 = path71[target.itemPathLength];
|
|
49225
49272
|
if (existing.type === "reasoning" && field2 === "summary") {
|
|
49226
49273
|
const summary = structuredClone(existing.summary ?? []);
|
|
49227
|
-
const suffix =
|
|
49274
|
+
const suffix = path71.slice(target.itemPathLength + 1);
|
|
49228
49275
|
if (suffix.length === 0) {
|
|
49229
49276
|
existing.summary = structuredClone(Array.isArray(value) ? value : [value]);
|
|
49230
49277
|
} else {
|
|
@@ -49324,9 +49371,9 @@ var init_desktop_activity_events = __esm({
|
|
|
49324
49371
|
});
|
|
49325
49372
|
return [this.activitySignal(threadId2, entity.turnId, itemId, mapping)];
|
|
49326
49373
|
}
|
|
49327
|
-
consumeEntityPatch(threadId2, state, entityKey,
|
|
49328
|
-
const wholeEntity =
|
|
49329
|
-
const statusField =
|
|
49374
|
+
consumeEntityPatch(threadId2, state, entityKey, path71, value) {
|
|
49375
|
+
const wholeEntity = path71.length === 4;
|
|
49376
|
+
const statusField = path71.length === 5 && path71[4] === "status";
|
|
49330
49377
|
if (!wholeEntity && !statusField) {
|
|
49331
49378
|
return [];
|
|
49332
49379
|
}
|
|
@@ -49506,20 +49553,20 @@ var init_desktop_error_events = __esm({
|
|
|
49506
49553
|
if (patch.op !== "add" && patch.op !== "replace") {
|
|
49507
49554
|
continue;
|
|
49508
49555
|
}
|
|
49509
|
-
const
|
|
49510
|
-
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") {
|
|
49511
49558
|
const entity = record17(patch.value);
|
|
49512
49559
|
const turnId2 = turnIdFromEntity2(entity);
|
|
49513
49560
|
if (turnId2) {
|
|
49514
|
-
this.entityTurnIds.set(this.entityKey(threadId2,
|
|
49561
|
+
this.entityTurnIds.set(this.entityKey(threadId2, path71[3]), turnId2);
|
|
49515
49562
|
events.push(...this.errorEvents(threadId2, array4(entity.items), turnId2));
|
|
49516
49563
|
}
|
|
49517
49564
|
continue;
|
|
49518
49565
|
}
|
|
49519
|
-
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") {
|
|
49520
49567
|
continue;
|
|
49521
49568
|
}
|
|
49522
|
-
const turnId = this.entityTurnIds.get(this.entityKey(threadId2,
|
|
49569
|
+
const turnId = this.entityTurnIds.get(this.entityKey(threadId2, path71[3]));
|
|
49523
49570
|
if (!turnId) {
|
|
49524
49571
|
continue;
|
|
49525
49572
|
}
|
|
@@ -49612,13 +49659,13 @@ function visibleMessage(value, resolveKnownLocalImage) {
|
|
|
49612
49659
|
function occurredAt2() {
|
|
49613
49660
|
return Math.floor(Date.now() / 1e3);
|
|
49614
49661
|
}
|
|
49615
|
-
function itemPath(
|
|
49616
|
-
const index =
|
|
49617
|
-
const itemIndex =
|
|
49618
|
-
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;
|
|
49619
49666
|
}
|
|
49620
|
-
function stateKey(threadId2,
|
|
49621
|
-
return `${threadId2}:${JSON.stringify(
|
|
49667
|
+
function stateKey(threadId2, path71) {
|
|
49668
|
+
return `${threadId2}:${JSON.stringify(path71)}`;
|
|
49622
49669
|
}
|
|
49623
49670
|
function completedKey(threadId2, itemId) {
|
|
49624
49671
|
return `${threadId2}:${itemId}`;
|
|
@@ -49676,35 +49723,35 @@ var init_desktop_stream_events = __esm({
|
|
|
49676
49723
|
if (op !== "add" && op !== "replace" && op !== "remove") {
|
|
49677
49724
|
continue;
|
|
49678
49725
|
}
|
|
49679
|
-
const
|
|
49680
|
-
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))) {
|
|
49681
49728
|
this.resetThread(threadId2);
|
|
49682
49729
|
continue;
|
|
49683
49730
|
}
|
|
49684
|
-
if (
|
|
49685
|
-
const values =
|
|
49686
|
-
if (
|
|
49687
|
-
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");
|
|
49688
49735
|
this.replaceArrayStates(threadId2, arrayPath, array5(values), resolveKnownLocalImage);
|
|
49689
49736
|
continue;
|
|
49690
49737
|
}
|
|
49691
49738
|
}
|
|
49692
|
-
const rawIndex =
|
|
49693
|
-
if (op === "add" &&
|
|
49694
|
-
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)));
|
|
49695
49742
|
if (length === void 0) continue;
|
|
49696
|
-
|
|
49743
|
+
path71[rawIndex] = length;
|
|
49697
49744
|
}
|
|
49698
|
-
const targetItemPath = itemPath(
|
|
49745
|
+
const targetItemPath = itemPath(path71);
|
|
49699
49746
|
if (!targetItemPath) {
|
|
49700
49747
|
continue;
|
|
49701
49748
|
}
|
|
49702
49749
|
const key = stateKey(threadId2, targetItemPath);
|
|
49703
|
-
if (
|
|
49750
|
+
if (path71.length > targetItemPath.length && ["id", "type"].includes(String(path71[targetItemPath.length]))) {
|
|
49704
49751
|
this.states.delete(key);
|
|
49705
49752
|
continue;
|
|
49706
49753
|
}
|
|
49707
|
-
if (
|
|
49754
|
+
if (path71.length === targetItemPath.length) {
|
|
49708
49755
|
const arrayPath = targetItemPath.slice(0, -1);
|
|
49709
49756
|
const index = targetItemPath.at(-1);
|
|
49710
49757
|
if (op === "add" || op === "remove") this.shiftArrayStates(threadId2, arrayPath, index, op);
|
|
@@ -49719,7 +49766,7 @@ var init_desktop_stream_events = __esm({
|
|
|
49719
49766
|
));
|
|
49720
49767
|
continue;
|
|
49721
49768
|
}
|
|
49722
|
-
if (op === "replace" &&
|
|
49769
|
+
if (op === "replace" && path71.length === targetItemPath.length + 1 && path71.at(-1) === "text") {
|
|
49723
49770
|
events.push(...this.consumeTextPatch(threadId2, key, patch.value, revision4));
|
|
49724
49771
|
}
|
|
49725
49772
|
}
|
|
@@ -49731,9 +49778,9 @@ var init_desktop_stream_events = __esm({
|
|
|
49731
49778
|
const prefix = JSON.stringify(arrayPath);
|
|
49732
49779
|
for (const [key2, state] of this.states) {
|
|
49733
49780
|
if (state.threadId !== threadId2) continue;
|
|
49734
|
-
const
|
|
49735
|
-
const at =
|
|
49736
|
-
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;
|
|
49737
49784
|
this.states.delete(key2);
|
|
49738
49785
|
if (op === "remove" && at === index) continue;
|
|
49739
49786
|
moved.push([stateKey(threadId2, [...arrayPath, at + (op === "add" ? 1 : -1)]), state]);
|
|
@@ -49744,20 +49791,20 @@ var init_desktop_stream_events = __esm({
|
|
|
49744
49791
|
if (length !== void 0) this.arrayLengths.set(key, Math.max(0, length + (op === "add" ? 1 : -1)));
|
|
49745
49792
|
}
|
|
49746
49793
|
/** 完整数组只重播种本实体的路径;其他轮的正文和按原生身份记录的完成事实不变。 */
|
|
49747
|
-
replaceArrayStates(threadId2,
|
|
49748
|
-
const prefix = JSON.stringify(
|
|
49794
|
+
replaceArrayStates(threadId2, path71, values, resolveKnownLocalImage) {
|
|
49795
|
+
const prefix = JSON.stringify(path71);
|
|
49749
49796
|
for (const [key, state] of this.states) {
|
|
49750
49797
|
if (state.threadId !== threadId2) continue;
|
|
49751
49798
|
const itemPath2 = JSON.parse(key.slice(threadId2.length + 1));
|
|
49752
49799
|
if (JSON.stringify(itemPath2.slice(0, -1)) === prefix) this.states.delete(key);
|
|
49753
49800
|
}
|
|
49754
|
-
this.arrayLengths.set(stateKey(threadId2,
|
|
49801
|
+
this.arrayLengths.set(stateKey(threadId2, path71), values.length);
|
|
49755
49802
|
values.forEach((value, index) => {
|
|
49756
49803
|
const message = visibleMessage(value, resolveKnownLocalImage);
|
|
49757
49804
|
if (!message) return;
|
|
49758
49805
|
if (message.role === "user") this.completed.add(completedKey(threadId2, message.itemId));
|
|
49759
49806
|
else if (!this.completed.has(completedKey(threadId2, message.itemId))) {
|
|
49760
|
-
this.states.set(stateKey(threadId2, [...
|
|
49807
|
+
this.states.set(stateKey(threadId2, [...path71, index]), { threadId: threadId2, ...message, lastText: message.text });
|
|
49761
49808
|
}
|
|
49762
49809
|
});
|
|
49763
49810
|
}
|
|
@@ -50882,8 +50929,8 @@ var init_socket_client = __esm({
|
|
|
50882
50929
|
this.diagnosticProfile = diagnosticProfile;
|
|
50883
50930
|
this.socketPaths = socketPath ? [socketPath] : defaultSocketPaths;
|
|
50884
50931
|
const reader = new DesktopRuntimeVersionReader();
|
|
50885
|
-
this.runtimeVersion = new RuntimeVersionCache(async (
|
|
50886
|
-
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);
|
|
50887
50934
|
return typeof value === "string" ? { version: value, build: null } : value;
|
|
50888
50935
|
});
|
|
50889
50936
|
}
|
|
@@ -53170,7 +53217,7 @@ var init_desktop_read_refresh_queue = __esm({
|
|
|
53170
53217
|
import { watch } from "node:fs";
|
|
53171
53218
|
import { open as open4, stat as statPath } from "node:fs/promises";
|
|
53172
53219
|
import { createHash as createHash22 } from "node:crypto";
|
|
53173
|
-
import
|
|
53220
|
+
import path51 from "node:path";
|
|
53174
53221
|
function record20(value) {
|
|
53175
53222
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
53176
53223
|
}
|
|
@@ -53314,7 +53361,7 @@ var init_desktop_read_state_file = __esm({
|
|
|
53314
53361
|
async readOnce() {
|
|
53315
53362
|
this.checks++;
|
|
53316
53363
|
try {
|
|
53317
|
-
const filePath =
|
|
53364
|
+
const filePath = path51.join(this.home, ".codex-global-state.json");
|
|
53318
53365
|
const file = await open4(filePath, "r");
|
|
53319
53366
|
let raw, signature;
|
|
53320
53367
|
try {
|
|
@@ -55160,9 +55207,9 @@ var init_protocol = __esm({
|
|
|
55160
55207
|
|
|
55161
55208
|
// apps/desktop/src/daemon/server.ts
|
|
55162
55209
|
import { randomUUID as randomUUID37 } from "node:crypto";
|
|
55163
|
-
import
|
|
55210
|
+
import fs38 from "node:fs";
|
|
55164
55211
|
import net5 from "node:net";
|
|
55165
|
-
import
|
|
55212
|
+
import path52 from "node:path";
|
|
55166
55213
|
import { StringDecoder as StringDecoder2 } from "node:string_decoder";
|
|
55167
55214
|
function createStatusFile(instanceId, mode, socketPath) {
|
|
55168
55215
|
return {
|
|
@@ -55297,10 +55344,10 @@ var init_server4 = __esm({
|
|
|
55297
55344
|
DaemonServer = class {
|
|
55298
55345
|
constructor(options) {
|
|
55299
55346
|
this.options = options;
|
|
55300
|
-
this.socketPath =
|
|
55301
|
-
this.statusPath =
|
|
55347
|
+
this.socketPath = path52.resolve(options.socketPath ?? daemonSocketPath());
|
|
55348
|
+
this.statusPath = path52.resolve(options.statusPath ?? daemonStatusPath());
|
|
55302
55349
|
this.usesDefaultRuntimeDir = options.socketPath === void 0 || options.statusPath === void 0;
|
|
55303
|
-
this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() :
|
|
55350
|
+
this.lifecycleLockPath = options.socketPath === void 0 ? daemonLifecycleLockPath() : path52.join(path52.dirname(this.socketPath), ".daemon-lifecycle.lock");
|
|
55304
55351
|
this.transport = createDaemonTransport(this.socketPath);
|
|
55305
55352
|
this.listenSocketPath = this.transport.listenPath;
|
|
55306
55353
|
}
|
|
@@ -55412,22 +55459,22 @@ var init_server4 = __esm({
|
|
|
55412
55459
|
const temporaryPath = `${this.statusPath}.${this.instanceId}.tmp`;
|
|
55413
55460
|
let descriptor = null;
|
|
55414
55461
|
try {
|
|
55415
|
-
descriptor =
|
|
55416
|
-
|
|
55462
|
+
descriptor = fs38.openSync(temporaryPath, "wx", 384);
|
|
55463
|
+
fs38.writeFileSync(
|
|
55417
55464
|
descriptor,
|
|
55418
55465
|
`${JSON.stringify(createStatusFile(this.instanceId, this.options.mode ?? "foreground", this.socketPath), null, 2)}
|
|
55419
55466
|
`,
|
|
55420
55467
|
"utf8"
|
|
55421
55468
|
);
|
|
55422
|
-
|
|
55469
|
+
fs38.closeSync(descriptor);
|
|
55423
55470
|
descriptor = null;
|
|
55424
|
-
|
|
55425
|
-
|
|
55471
|
+
fs38.chmodSync(temporaryPath, 384);
|
|
55472
|
+
fs38.renameSync(temporaryPath, this.statusPath);
|
|
55426
55473
|
} catch (error2) {
|
|
55427
55474
|
if (descriptor !== null) {
|
|
55428
|
-
|
|
55475
|
+
fs38.closeSync(descriptor);
|
|
55429
55476
|
}
|
|
55430
|
-
|
|
55477
|
+
fs38.rmSync(temporaryPath, { force: true });
|
|
55431
55478
|
throw error2;
|
|
55432
55479
|
}
|
|
55433
55480
|
}
|
|
@@ -55452,9 +55499,9 @@ var init_server4 = __esm({
|
|
|
55452
55499
|
this.transport.cleanup(this.socketPath);
|
|
55453
55500
|
if (this.statusOwned) {
|
|
55454
55501
|
try {
|
|
55455
|
-
const status2 = JSON.parse(
|
|
55502
|
+
const status2 = JSON.parse(fs38.readFileSync(this.statusPath, "utf8"));
|
|
55456
55503
|
if (status2.instanceId === this.instanceId) {
|
|
55457
|
-
|
|
55504
|
+
fs38.rmSync(this.statusPath, { force: true });
|
|
55458
55505
|
}
|
|
55459
55506
|
} catch {
|
|
55460
55507
|
}
|
|
@@ -56048,7 +56095,7 @@ var init_push_trigger_projection = __esm({
|
|
|
56048
56095
|
});
|
|
56049
56096
|
|
|
56050
56097
|
// apps/desktop/src/daemon/turn-push-audit.ts
|
|
56051
|
-
import
|
|
56098
|
+
import path53 from "node:path";
|
|
56052
56099
|
function isRecord6(value) {
|
|
56053
56100
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56054
56101
|
}
|
|
@@ -56095,7 +56142,7 @@ function isCoverageReason(value) {
|
|
|
56095
56142
|
return value === "realtime_gap" || value === "historical_gap" || value === "source_unavailable" || value === "reader_limit" || value === "write_failed";
|
|
56096
56143
|
}
|
|
56097
56144
|
function auditDirectory(runtimeDir) {
|
|
56098
|
-
return
|
|
56145
|
+
return path53.join(runtimeDir, AUDIT_DIRECTORY);
|
|
56099
56146
|
}
|
|
56100
56147
|
function dateFileName(timestampMs) {
|
|
56101
56148
|
if (!isFiniteTimestamp(timestampMs)) return null;
|
|
@@ -56198,7 +56245,7 @@ function appendRecord(runtimeDir, timestampMs, record26, files) {
|
|
|
56198
56245
|
files.checkDirectory(runtimeDir);
|
|
56199
56246
|
const directory3 = auditDirectory(runtimeDir);
|
|
56200
56247
|
files.ensureDirectory(directory3);
|
|
56201
|
-
files.append(
|
|
56248
|
+
files.append(path53.join(directory3, fileName), `${JSON.stringify(record26)}
|
|
56202
56249
|
`, MAX_FILE_BYTES);
|
|
56203
56250
|
return true;
|
|
56204
56251
|
} catch {
|
|
@@ -57763,11 +57810,11 @@ function completedHistoryItem(value) {
|
|
|
57763
57810
|
break;
|
|
57764
57811
|
case "fileChange":
|
|
57765
57812
|
copy(raw, item, { status: "status" });
|
|
57766
|
-
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]) => {
|
|
57767
57814
|
const change = record5(value2);
|
|
57768
57815
|
const kind = { type: change.type };
|
|
57769
57816
|
if (change.type === "update") kind.movePath = change.move_path ?? null;
|
|
57770
|
-
return { path:
|
|
57817
|
+
return { path: path71, kind, diff: change.unified_diff ?? change.content ?? "" };
|
|
57771
57818
|
});
|
|
57772
57819
|
break;
|
|
57773
57820
|
case "collabAgentToolCall":
|
|
@@ -57904,8 +57951,8 @@ function markdownTargets(text11) {
|
|
|
57904
57951
|
function markdownReferences(text11, paths = localResourcePaths) {
|
|
57905
57952
|
const { tree, references } = markdownTargets(text11);
|
|
57906
57953
|
return { tree, references: references.flatMap((ref) => {
|
|
57907
|
-
const
|
|
57908
|
-
return
|
|
57954
|
+
const path71 = paths.parseLink(ref.url);
|
|
57955
|
+
return path71 === null ? [] : [{ ...ref, path: path71 }];
|
|
57909
57956
|
}) };
|
|
57910
57957
|
}
|
|
57911
57958
|
function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths) {
|
|
@@ -57936,8 +57983,8 @@ function collectAssistantImagePaths(value, resourcePaths2 = localResourcePaths)
|
|
|
57936
57983
|
if (item.entitiesByKey && typeof item.entitiesByKey === "object") pending.push(...Object.values(item.entitiesByKey));
|
|
57937
57984
|
if (Array.isArray(item.patches)) {
|
|
57938
57985
|
for (const patch of item.patches) {
|
|
57939
|
-
const
|
|
57940
|
-
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);
|
|
57941
57988
|
}
|
|
57942
57989
|
}
|
|
57943
57990
|
}
|
|
@@ -58138,11 +58185,11 @@ async function readHistoryImageValue(locator, signal, filePath) {
|
|
|
58138
58185
|
signal?.throwIfAborted();
|
|
58139
58186
|
return value;
|
|
58140
58187
|
}
|
|
58141
|
-
async function assertHistoryImageFileReference(locator,
|
|
58142
|
-
const value = await readHistoryImageValue(locator, signal,
|
|
58188
|
+
async function assertHistoryImageFileReference(locator, path71, signal) {
|
|
58189
|
+
const value = await readHistoryImageValue(locator, signal, path71);
|
|
58143
58190
|
const last = locator.valuePath.at(-1);
|
|
58144
58191
|
const text11 = typeof value === "string" ? value : Array.isArray(value) ? value.map((part) => typeof record5(part).text === "string" ? record5(part).text : "").join("") : null;
|
|
58145
|
-
if (text11 === null || !(last === "path" ? text11 ===
|
|
58192
|
+
if (text11 === null || !(last === "path" ? text11 === path71 : assistantPaths(text11).includes(path71))) {
|
|
58146
58193
|
throw new SessionHistoryError("INVALID_RECORD", "\u56FE\u7247\u6587\u4EF6\u4E0E\u5386\u53F2\u5F15\u7528\u4E0D\u7B26");
|
|
58147
58194
|
}
|
|
58148
58195
|
}
|
|
@@ -58201,7 +58248,7 @@ var init_session_history_images = __esm({
|
|
|
58201
58248
|
const found = [];
|
|
58202
58249
|
if (formal && item.type === "agentMessage") {
|
|
58203
58250
|
const references = [];
|
|
58204
|
-
for (const
|
|
58251
|
+
for (const path71 of assistantPaths(String(item.text ?? ""))) {
|
|
58205
58252
|
references.push({ locator: {
|
|
58206
58253
|
threadId: threadId2,
|
|
58207
58254
|
turnId: "",
|
|
@@ -58214,7 +58261,7 @@ var init_session_history_images = __esm({
|
|
|
58214
58261
|
recordLength: range.length,
|
|
58215
58262
|
recordSha256: range.sha256,
|
|
58216
58263
|
valuePath: ["payload", "item", raw.content !== void 0 ? "content" : "text"]
|
|
58217
|
-
}, nativeMessageId: null, path:
|
|
58264
|
+
}, nativeMessageId: null, path: path71, filePath: path71, callId: null });
|
|
58218
58265
|
}
|
|
58219
58266
|
this.markdownEvidence.set(item, references);
|
|
58220
58267
|
}
|
|
@@ -58243,7 +58290,7 @@ var init_session_history_images = __esm({
|
|
|
58243
58290
|
}
|
|
58244
58291
|
if (!imageUrl(source2)) return;
|
|
58245
58292
|
const previous = index > 0 ? record5(parts[index - 1]).text : null;
|
|
58246
|
-
const
|
|
58293
|
+
const path71 = typeof previous === "string" ? /^<image(?: name=.*?)? path="([^"]+)">$/.exec(previous)?.[1] ?? null : null;
|
|
58247
58294
|
found.push({
|
|
58248
58295
|
locator: {
|
|
58249
58296
|
threadId: threadId2,
|
|
@@ -58263,7 +58310,7 @@ var init_session_history_images = __esm({
|
|
|
58263
58310
|
]
|
|
58264
58311
|
},
|
|
58265
58312
|
nativeMessageId: typeof item.clientId === "string" ? item.clientId : null,
|
|
58266
|
-
path:
|
|
58313
|
+
path: path71,
|
|
58267
58314
|
callId: null
|
|
58268
58315
|
});
|
|
58269
58316
|
if (mapped[index]) mapped[index] = { type: "historyImage", resourceKey: null };
|
|
@@ -58325,11 +58372,11 @@ var init_session_history_images = __esm({
|
|
|
58325
58372
|
}
|
|
58326
58373
|
if (item.type === "agentMessage" && typeof item.text === "string") {
|
|
58327
58374
|
const references = [];
|
|
58328
|
-
for (const [referenceIndex,
|
|
58375
|
+
for (const [referenceIndex, path71] of assistantPaths(item.text).entries()) {
|
|
58329
58376
|
const calls = fallback.filter((candidate) => {
|
|
58330
58377
|
if (candidate.type !== "functionCall" || !["view_image", "functions.view_image"].includes(String(candidate.name))) return false;
|
|
58331
58378
|
try {
|
|
58332
|
-
return record5(JSON.parse(String(candidate.arguments))).path ===
|
|
58379
|
+
return record5(JSON.parse(String(candidate.arguments))).path === path71;
|
|
58333
58380
|
} catch {
|
|
58334
58381
|
return false;
|
|
58335
58382
|
}
|
|
@@ -58337,9 +58384,9 @@ var init_session_history_images = __esm({
|
|
|
58337
58384
|
const outputs = fallback.filter((candidate) => candidate.type === "functionCallOutput" && calls.some((call) => candidate.id === call.id));
|
|
58338
58385
|
const candidates = outputs.flatMap((output) => this.evidence.get(output) ?? []);
|
|
58339
58386
|
if (candidates.length && (calls.length !== 1 || candidates.length !== 1)) continue;
|
|
58340
|
-
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);
|
|
58341
58388
|
if (!original) continue;
|
|
58342
|
-
const evidence = { ...original, path:
|
|
58389
|
+
const evidence = { ...original, path: path71, referenceKind: "markdown", locator: {
|
|
58343
58390
|
...original.locator,
|
|
58344
58391
|
turnId,
|
|
58345
58392
|
itemId: item.id,
|
|
@@ -58347,7 +58394,7 @@ var init_session_history_images = __esm({
|
|
|
58347
58394
|
} };
|
|
58348
58395
|
try {
|
|
58349
58396
|
const resourceKey = await callback(evidence);
|
|
58350
|
-
if (resourceKey) references.push({ path:
|
|
58397
|
+
if (resourceKey) references.push({ path: path71, resourceKey });
|
|
58351
58398
|
} catch {
|
|
58352
58399
|
}
|
|
58353
58400
|
}
|
|
@@ -58366,7 +58413,7 @@ __export(session_history_reader_exports, {
|
|
|
58366
58413
|
SessionHistoryReader: () => SessionHistoryReader
|
|
58367
58414
|
});
|
|
58368
58415
|
import { randomUUID as randomUUID38 } from "node:crypto";
|
|
58369
|
-
import
|
|
58416
|
+
import fs39 from "node:fs/promises";
|
|
58370
58417
|
function resolveHistoryPath(resolvePath, signal) {
|
|
58371
58418
|
abortIfRequested2(signal);
|
|
58372
58419
|
if (!signal) return resolvePath();
|
|
@@ -58634,7 +58681,7 @@ var init_session_history_reader = __esm({
|
|
|
58634
58681
|
try {
|
|
58635
58682
|
const resolved3 = await resolveHistoryPath(() => this.options.resolveSessionPath(snapshot2.threadId), signal);
|
|
58636
58683
|
abortIfRequested2(signal);
|
|
58637
|
-
const current2 = await
|
|
58684
|
+
const current2 = await fs39.realpath(resolved3);
|
|
58638
58685
|
abortIfRequested2(signal);
|
|
58639
58686
|
if (current2 !== snapshot2.files[0].path) throw new Error("current path changed");
|
|
58640
58687
|
} catch (error2) {
|
|
@@ -59923,7 +59970,7 @@ var init_thread_view_reducer = __esm({
|
|
|
59923
59970
|
|
|
59924
59971
|
// apps/desktop/src/daemon/thread-view-store.ts
|
|
59925
59972
|
import { createHash as createHash25, randomUUID as randomUUID39 } from "node:crypto";
|
|
59926
|
-
import { isDeepStrictEqual as
|
|
59973
|
+
import { isDeepStrictEqual as isDeepStrictEqual5 } from "node:util";
|
|
59927
59974
|
function clone5(value) {
|
|
59928
59975
|
return structuredClone(value);
|
|
59929
59976
|
}
|
|
@@ -60167,7 +60214,7 @@ var init_thread_view_store = __esm({
|
|
|
60167
60214
|
const result = [];
|
|
60168
60215
|
for (const item of delivered.filter((item2) => item2.type === "assistant_message" && item2.turn_id === turnId)) {
|
|
60169
60216
|
const original = source2.get(item.id);
|
|
60170
|
-
if (!original || entry.deferredMessageIds?.has(item.id) || original.type !== item.type || original.turn_id !== turnId || !
|
|
60217
|
+
if (!original || entry.deferredMessageIds?.has(item.id) || original.type !== item.type || original.turn_id !== turnId || !isDeepStrictEqual5(this.publicItem(threadId2, original).content, item.content)) return null;
|
|
60171
60218
|
result.push(clone5(original));
|
|
60172
60219
|
}
|
|
60173
60220
|
return result;
|
|
@@ -60737,7 +60784,7 @@ var init_thread_view_store = __esm({
|
|
|
60737
60784
|
const hasBaseline = events.some((event) => event.type === "ThreadBaselineReceived");
|
|
60738
60785
|
const stableContentChanged = previousStableContent.some(({ item, processFact }) => {
|
|
60739
60786
|
const nextItem = nextAggregate.committedItems.get(item.id) ?? nextAggregate.activeTurn?.items.get(item.id);
|
|
60740
|
-
return !nextItem || !
|
|
60787
|
+
return !nextItem || !isDeepStrictEqual5(item, nextItem) || !isDeepStrictEqual5(processFact, nextAggregate.processFacts.get(item.id) ?? null);
|
|
60741
60788
|
});
|
|
60742
60789
|
const stableChanged = historyOrderReset || orderCorrected || stableContentChanged;
|
|
60743
60790
|
const baselineReplaced = stableChanged || hasBaseline;
|
|
@@ -60822,7 +60869,7 @@ var init_thread_view_store = __esm({
|
|
|
60822
60869
|
}
|
|
60823
60870
|
const newlyDeferred = [...deferredMessageIds].filter((id5) => !initialEntry.deferredMessageIds?.has(id5));
|
|
60824
60871
|
if (newlyDeferred.length) this.options.onMessagePublicationDeferred?.(threadId2, newlyDeferred);
|
|
60825
|
-
const samePublicView =
|
|
60872
|
+
const samePublicView = isDeepStrictEqual5(
|
|
60826
60873
|
{ ...previousView, revision: 0 },
|
|
60827
60874
|
{ ...nextView, revision: 0 }
|
|
60828
60875
|
);
|
|
@@ -60848,7 +60895,7 @@ var init_thread_view_store = __esm({
|
|
|
60848
60895
|
const previousItems = new Map(initialEntry.aggregate.projection.items.map((item) => [item.id, item]));
|
|
60849
60896
|
const changed2 = nextAggregate.projection.items.filter((item) => {
|
|
60850
60897
|
const previous = previousItems.get(item.id);
|
|
60851
|
-
return !previous || !
|
|
60898
|
+
return !previous || !isDeepStrictEqual5(previous.content, item.content);
|
|
60852
60899
|
});
|
|
60853
60900
|
if (changed2.length) {
|
|
60854
60901
|
for (const lease of this.subscriptions) {
|
|
@@ -60875,7 +60922,7 @@ var init_thread_view_store = __esm({
|
|
|
60875
60922
|
previous_revision: previousRevision,
|
|
60876
60923
|
baseline_replaced: baselineReplaced,
|
|
60877
60924
|
// 比较完整 committed 层而非公开尾窗,保护 Web 已补页内容与在途分页响应。
|
|
60878
|
-
...baselineReplaced && !stableChanged && nextEntry.baselineContinuityKey !== null && nextEntry.baselineContinuityKey === initialEntry.baselineContinuityKey &&
|
|
60925
|
+
...baselineReplaced && !stableChanged && nextEntry.baselineContinuityKey !== null && nextEntry.baselineContinuityKey === initialEntry.baselineContinuityKey && isDeepStrictEqual5(previousView.window, nextView.window) ? { baseline_patch_safe: true } : {},
|
|
60879
60926
|
// 本次事务已构造公开内容;只补齐提交后的 revision,避免重新解析全部历史。
|
|
60880
60927
|
view: clone5({ ...nextView, revision: nextEntry.revision })
|
|
60881
60928
|
};
|
|
@@ -60951,11 +60998,11 @@ var init_thread_view_store = __esm({
|
|
|
60951
60998
|
this.assertCurrent();
|
|
60952
60999
|
const next = window.getSnapshot();
|
|
60953
61000
|
const previous = this.source.current.snapshot;
|
|
60954
|
-
if (!sourceChanged &&
|
|
61001
|
+
if (!sourceChanged && isDeepStrictEqual5(next, previous)) return;
|
|
60955
61002
|
const nextIds = new Set(next.items.map((item) => item.id));
|
|
60956
61003
|
const installed = installedVersion !== window.installVersion;
|
|
60957
61004
|
installedVersion = window.installVersion;
|
|
60958
|
-
if (installed || sourceChanged || previous.items.some((item) => !nextIds.has(item.id)) || !
|
|
61005
|
+
if (installed || sourceChanged || previous.items.some((item) => !nextIds.has(item.id)) || !isDeepStrictEqual5(previous.capabilities, next.capabilities)) this.source.replaceEpoch(randomUUID39(), next);
|
|
60959
61006
|
else this.source.publish(next);
|
|
60960
61007
|
};
|
|
60961
61008
|
this.unsubscribe = store.subscribe((mutation) => {
|
|
@@ -63481,10 +63528,10 @@ var init_history_snapshot = __esm({
|
|
|
63481
63528
|
const patches = objectRecord3(objectRecord3(objectRecord3(frame).params).change).patches;
|
|
63482
63529
|
const covered = Array.isArray(patches) && patches.every((raw) => {
|
|
63483
63530
|
const patch = objectRecord3(raw);
|
|
63484
|
-
const
|
|
63485
|
-
if (!Array.isArray(
|
|
63486
|
-
if (
|
|
63487
|
-
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");
|
|
63488
63535
|
});
|
|
63489
63536
|
const bytes3 = Buffer.byteLength(JSON.stringify(acceptedEvents));
|
|
63490
63537
|
if (!covered || recovery.events.length + events.length > 256 || recovery.bytes + bytes3 > 2 * 1024 * 1024) recovery.valid = false;
|
|
@@ -63853,11 +63900,11 @@ var init_app_server_history_window_reader = __esm({
|
|
|
63853
63900
|
const bound = this.turnMetadata.get(turn);
|
|
63854
63901
|
if (!bound) throw new SessionHistoryError("INVALID_CURSOR", "Turn \u4E0D\u5C5E\u4E8E\u5F53\u524D\u5386\u53F2\u5FEB\u7167");
|
|
63855
63902
|
this.assertEvidenceCurrent(bound);
|
|
63856
|
-
const { createdAt, cwd, path:
|
|
63903
|
+
const { createdAt, cwd, path: path71 } = bound.metadata;
|
|
63857
63904
|
return {
|
|
63858
63905
|
nativeOrder: bound.nativeOrder,
|
|
63859
63906
|
sourceRevision: bound.revision,
|
|
63860
|
-
contentVersion: createHash27("sha256").update(JSON.stringify([turn, createdAt, cwd,
|
|
63907
|
+
contentVersion: createHash27("sha256").update(JSON.stringify([turn, createdAt, cwd, path71])).digest("hex")
|
|
63861
63908
|
};
|
|
63862
63909
|
}
|
|
63863
63910
|
/** 撤销正文提交资格,保留逻辑边界供下次原生读取重新证明。 */
|
|
@@ -66365,7 +66412,7 @@ var init_thread_history_window_projection = __esm({
|
|
|
66365
66412
|
pending: null,
|
|
66366
66413
|
activity: null,
|
|
66367
66414
|
lastError: null,
|
|
66368
|
-
resolveKnownLocalImage: (
|
|
66415
|
+
resolveKnownLocalImage: (path71, itemId, partIndex) => this.options.resolveKnownLocalImage?.(path71, itemId, partIndex) ?? (itemId ? knownImages.get(itemId)?.get(path71) ?? null : null),
|
|
66369
66416
|
onHistoryItemProjected: (item, normalized) => timeline.push({ id: item.id, timeline: normalized })
|
|
66370
66417
|
}, "history_only");
|
|
66371
66418
|
const items = [...event.baseline.committed_items, ...event.baseline.active_turn?.items ?? []];
|
|
@@ -67239,8 +67286,8 @@ function unreadFrameDiagnostic(frame) {
|
|
|
67239
67286
|
let countValue = values.unreadMessageCount;
|
|
67240
67287
|
if (kind === "patch") {
|
|
67241
67288
|
for (const value of Array.isArray(change.patches) ? change.patches : []) {
|
|
67242
|
-
const patch = object10(value),
|
|
67243
|
-
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;
|
|
67244
67291
|
if (name2 !== "hasUnreadTurn" && name2 !== "unreadMessageCount") continue;
|
|
67245
67292
|
const state = patch.op === "remove" ? "removed" : ["add", "replace"].includes(String(patch.op)) ? field(patch.value, Object.hasOwn(patch, "value"), name2 === "unreadMessageCount") : "invalid";
|
|
67246
67293
|
if (name2 === "hasUnreadTurn") unread = state;
|
|
@@ -69244,9 +69291,9 @@ function assertFile(stat4) {
|
|
|
69244
69291
|
if (!stat4.isFile() || stat4.nlink !== 1n) throw missing2();
|
|
69245
69292
|
if (stat4.size > BigInt(MAX_BYTES6)) throw limited();
|
|
69246
69293
|
}
|
|
69247
|
-
async function captureDirectoryChain(snapshot2,
|
|
69294
|
+
async function captureDirectoryChain(snapshot2, path71, signal) {
|
|
69248
69295
|
const paths = /* @__PURE__ */ new Set();
|
|
69249
|
-
for (const start of [dirname2(
|
|
69296
|
+
for (const start of [dirname2(path71)]) {
|
|
69250
69297
|
for (let current2 = start; ; current2 = dirname2(current2)) {
|
|
69251
69298
|
paths.add(current2);
|
|
69252
69299
|
if (paths.size > MAX_DIRECTORY_ENTRIES2) throw limited();
|
|
@@ -69376,9 +69423,9 @@ var init_file_resources = __esm({
|
|
|
69376
69423
|
trim() {
|
|
69377
69424
|
while (this.entries.size > MAX_ENTRIES3 || this.indexBytes > MAX_INDEX_BYTES) this.remove(this.entries.values().next().value);
|
|
69378
69425
|
}
|
|
69379
|
-
assertTarget(entry,
|
|
69426
|
+
assertTarget(entry, path71, signal, isCurrent) {
|
|
69380
69427
|
this.assertVisible(entry, signal, isCurrent);
|
|
69381
|
-
if (entry.targetRealPath !== void 0 && entry.targetRealPath !==
|
|
69428
|
+
if (entry.targetRealPath !== void 0 && entry.targetRealPath !== path71) {
|
|
69382
69429
|
this.remove(entry);
|
|
69383
69430
|
this.options.onReferenceRetired?.({ ...entry.reference, attachmentId: entry.attachmentId });
|
|
69384
69431
|
throw changed();
|
|
@@ -69420,17 +69467,17 @@ var init_file_resources = __esm({
|
|
|
69420
69467
|
if (request2 && (!expected || expected.sha256 !== request2.sha256)) throw changed();
|
|
69421
69468
|
const directories2 = { entries: /* @__PURE__ */ new Map(), bytes: 0 };
|
|
69422
69469
|
await captureDirectoryChain(directories2, entry.reference.path, combined);
|
|
69423
|
-
const
|
|
69470
|
+
const path71 = await realpath2(entry.reference.path);
|
|
69424
69471
|
combined.throwIfAborted();
|
|
69425
|
-
this.assertTarget(entry,
|
|
69426
|
-
await captureDirectoryChain(directories2,
|
|
69427
|
-
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 });
|
|
69428
69475
|
assertFile(pathBefore);
|
|
69429
|
-
handle = await open5(
|
|
69476
|
+
handle = await open5(path71, constants4.O_RDONLY | constants4.O_NOFOLLOW | constants4.O_NONBLOCK);
|
|
69430
69477
|
const before = await handle.stat({ bigint: true });
|
|
69431
69478
|
assertFile(before);
|
|
69432
69479
|
if (identity5(before) !== identity5(pathBefore)) throw changed();
|
|
69433
|
-
const fileIdentity2 = `${
|
|
69480
|
+
const fileIdentity2 = `${path71}\0${identity5(before)}`;
|
|
69434
69481
|
if (request2 && expected.identity !== fileIdentity2) throw changed();
|
|
69435
69482
|
const byteSize2 = Number(before.size);
|
|
69436
69483
|
const chunkCount = Math.ceil(byteSize2 / CHUNK_BYTES);
|
|
@@ -69456,7 +69503,7 @@ var init_file_resources = __esm({
|
|
|
69456
69503
|
const pathAfter = await realpath2(entry.reference.path);
|
|
69457
69504
|
const current2 = await lstat4(pathAfter, { bigint: true });
|
|
69458
69505
|
this.assertTarget(entry, pathAfter, combined, isCurrent);
|
|
69459
|
-
if (pathAfter !==
|
|
69506
|
+
if (pathAfter !== path71 || identity5(after) !== identity5(before) || identity5(current2) !== identity5(before)) throw changed();
|
|
69460
69507
|
const sha2562 = hash3.digest("hex");
|
|
69461
69508
|
if (request2 && sha2562 !== request2.sha256) throw changed();
|
|
69462
69509
|
await handle.close();
|
|
@@ -69472,8 +69519,8 @@ var init_file_resources = __esm({
|
|
|
69472
69519
|
chunkBytes: CHUNK_BYTES,
|
|
69473
69520
|
chunkCount
|
|
69474
69521
|
};
|
|
69475
|
-
this.assertTarget(entry,
|
|
69476
|
-
return { entry, path:
|
|
69522
|
+
this.assertTarget(entry, path71, combined, isCurrent);
|
|
69523
|
+
return { entry, path: path71, info, identity: fileIdentity2, chunk, signal: combined };
|
|
69477
69524
|
} catch (error2) {
|
|
69478
69525
|
combined.throwIfAborted();
|
|
69479
69526
|
if (error2 instanceof NiumaError) throw error2;
|
|
@@ -69492,7 +69539,7 @@ var init_file_resources = __esm({
|
|
|
69492
69539
|
});
|
|
69493
69540
|
|
|
69494
69541
|
// apps/desktop/src/niuma/desktop-settings-events.ts
|
|
69495
|
-
import { isDeepStrictEqual as
|
|
69542
|
+
import { isDeepStrictEqual as isDeepStrictEqual6 } from "node:util";
|
|
69496
69543
|
function record23(value) {
|
|
69497
69544
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
69498
69545
|
}
|
|
@@ -69505,16 +69552,16 @@ function revisionOf2(value) {
|
|
|
69505
69552
|
function occurredAt3() {
|
|
69506
69553
|
return Math.floor(Date.now() / 1e3);
|
|
69507
69554
|
}
|
|
69508
|
-
function isThreadSettingsPatch(
|
|
69509
|
-
const field2 =
|
|
69555
|
+
function isThreadSettingsPatch(path71) {
|
|
69556
|
+
const field2 = path71.at(-1);
|
|
69510
69557
|
if (typeof field2 !== "string" || !SETTING_FIELD_ALIASES.has(field2)) {
|
|
69511
69558
|
return false;
|
|
69512
69559
|
}
|
|
69513
|
-
return
|
|
69560
|
+
return path71.length === 1 || typeof path71.at(-2) === "string" && SETTINGS_CONTAINERS.has(path71.at(-2));
|
|
69514
69561
|
}
|
|
69515
|
-
function isCurrentPermissionsPatch(
|
|
69516
|
-
const field2 =
|
|
69517
|
-
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);
|
|
69518
69565
|
}
|
|
69519
69566
|
function hasOwn(value, field2) {
|
|
69520
69567
|
return Object.prototype.hasOwnProperty.call(value, field2);
|
|
@@ -69593,20 +69640,20 @@ function currentPermissionsFromRecord(value) {
|
|
|
69593
69640
|
return settings;
|
|
69594
69641
|
}
|
|
69595
69642
|
function settingsFromPatch(patch) {
|
|
69596
|
-
const
|
|
69597
|
-
if (
|
|
69643
|
+
const path71 = array6(patch.path);
|
|
69644
|
+
if (path71.length === 1 && typeof path71[0] === "string" && SETTINGS_CONTAINERS.has(path71[0])) {
|
|
69598
69645
|
return settingsFromRecord(patch.value, BASE_SETTING_FIELDS);
|
|
69599
69646
|
}
|
|
69600
|
-
if (
|
|
69647
|
+
if (path71.length === 1 && path71[0] === CURRENT_PERMISSIONS_CONTAINER) {
|
|
69601
69648
|
return currentPermissionsFromRecord(patch.value);
|
|
69602
69649
|
}
|
|
69603
|
-
const field2 =
|
|
69650
|
+
const field2 = path71.at(-1);
|
|
69604
69651
|
const settings = {};
|
|
69605
|
-
if (typeof field2 === "string" && isCurrentPermissionsPatch(
|
|
69652
|
+
if (typeof field2 === "string" && isCurrentPermissionsPatch(path71)) {
|
|
69606
69653
|
assignCurrentPermission(settings, field2, patch.value);
|
|
69607
69654
|
return settings;
|
|
69608
69655
|
}
|
|
69609
|
-
if (typeof field2 === "string" && isThreadSettingsPatch(
|
|
69656
|
+
if (typeof field2 === "string" && isThreadSettingsPatch(path71)) {
|
|
69610
69657
|
assignSetting(settings, field2, patch.value);
|
|
69611
69658
|
}
|
|
69612
69659
|
return settings;
|
|
@@ -69669,7 +69716,7 @@ var init_desktop_settings_events = __esm({
|
|
|
69669
69716
|
const previous = this.lastSettingsByThread.get(threadId2) ?? {};
|
|
69670
69717
|
const next = { ...previous, ...settings };
|
|
69671
69718
|
this.lastSettingsByThread.set(threadId2, next);
|
|
69672
|
-
if (source2 === "patch" &&
|
|
69719
|
+
if (source2 === "patch" && isDeepStrictEqual6(previous, next)) {
|
|
69673
69720
|
return [];
|
|
69674
69721
|
}
|
|
69675
69722
|
return [{ threadId: threadId2, settings, source: source2, occurredAt: occurredAt3() }];
|
|
@@ -73024,8 +73071,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73024
73071
|
if (change.type !== "patches" || next === null || previous === void 0 || next <= previous) return [];
|
|
73025
73072
|
const patches = array7(change.patches);
|
|
73026
73073
|
const unknownMembership = patches.some((value) => {
|
|
73027
|
-
const p = record25(value),
|
|
73028
|
-
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])))));
|
|
73029
73076
|
});
|
|
73030
73077
|
if (next !== previous + 1 || unknownMembership) {
|
|
73031
73078
|
this.idleHistoryBaselines.delete(context.threadId);
|
|
@@ -73035,9 +73082,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73035
73082
|
const mapped = new Map(this.entityTurnIdsByThread.get(context.threadId));
|
|
73036
73083
|
const candidates = /* @__PURE__ */ new Set();
|
|
73037
73084
|
for (const value of patches) {
|
|
73038
|
-
const p = record25(value),
|
|
73039
|
-
if (p.op === "remove" &&
|
|
73040
|
-
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]));
|
|
73041
73088
|
if (id5) candidates.add(id5);
|
|
73042
73089
|
}
|
|
73043
73090
|
}
|
|
@@ -73048,9 +73095,9 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73048
73095
|
})).value;
|
|
73049
73096
|
const canDelete = typeof newGeneration === "number" && Number.isSafeInteger(newGeneration) && oldGeneration !== void 0 && newGeneration > oldGeneration;
|
|
73050
73097
|
for (const value of patches) {
|
|
73051
|
-
const p = record25(value),
|
|
73052
|
-
if (
|
|
73053
|
-
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]);
|
|
73054
73101
|
if (p.op === "remove") mapped.delete(key);
|
|
73055
73102
|
else if (p.op === "add" || p.op === "replace") {
|
|
73056
73103
|
const id5 = nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? nonEmptyString14(record25(entity.params).turnId);
|
|
@@ -73176,8 +73223,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73176
73223
|
const change = record25(record25(frame.params).change);
|
|
73177
73224
|
for (const rawPatch of array7(change.patches)) {
|
|
73178
73225
|
const patch = record25(rawPatch);
|
|
73179
|
-
const
|
|
73180
|
-
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")) {
|
|
73181
73228
|
this.rememberSidebarRecency(context.threadId, patch.value);
|
|
73182
73229
|
}
|
|
73183
73230
|
}
|
|
@@ -73263,12 +73310,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73263
73310
|
requests = structuredClone(requests);
|
|
73264
73311
|
for (const value of array7(change.patches)) {
|
|
73265
73312
|
const patch = record25(value);
|
|
73266
|
-
const
|
|
73267
|
-
if (
|
|
73268
|
-
if (
|
|
73313
|
+
const path71 = array7(patch.path);
|
|
73314
|
+
if (path71[0] !== "requests") continue;
|
|
73315
|
+
if (path71.length === 1) {
|
|
73269
73316
|
requests = patch.op === "remove" ? [] : structuredClone(array7(patch.value));
|
|
73270
|
-
} else if (
|
|
73271
|
-
const index =
|
|
73317
|
+
} else if (path71.length === 2) {
|
|
73318
|
+
const index = path71[1] === "-" ? requests.length : Number(path71[1]);
|
|
73272
73319
|
if (!Number.isInteger(index) || index < 0 || index > requests.length) continue;
|
|
73273
73320
|
if (patch.op === "remove") requests.splice(index, 1);
|
|
73274
73321
|
else if (patch.op === "add") requests.splice(index, 0, structuredClone(patch.value));
|
|
@@ -73347,19 +73394,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73347
73394
|
}
|
|
73348
73395
|
/** 深层 content 只有局部形状,须等待完整项/快照重新证明;text 更新不能洗掉未知内容。 */
|
|
73349
73396
|
invalidateReadPatch(patch, context) {
|
|
73350
|
-
const
|
|
73351
|
-
if (
|
|
73352
|
-
const turnId = typeof
|
|
73353
|
-
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"))) {
|
|
73354
73401
|
for (const identity7 of this.nativeReadIdentities.get(context.threadId)?.values() ?? []) {
|
|
73355
73402
|
if (identity7.turnId === turnId) identity7.complete = false;
|
|
73356
73403
|
}
|
|
73357
73404
|
return;
|
|
73358
73405
|
}
|
|
73359
|
-
if (
|
|
73406
|
+
if (path71[4] !== "items" || path71[6] !== "content") return;
|
|
73360
73407
|
const order = this.itemOrders.get(context.threadId);
|
|
73361
|
-
if (!order || order.entityKey !==
|
|
73362
|
-
const id5 = typeof
|
|
73408
|
+
if (!order || order.entityKey !== path71[3]) return;
|
|
73409
|
+
const id5 = typeof path71[5] === "number" ? order.ids[path71[5]] : null;
|
|
73363
73410
|
const identity6 = id5 ? this.nativeReadIdentities.get(context.threadId)?.get(id5) : null;
|
|
73364
73411
|
if (identity6) identity6.complete = false;
|
|
73365
73412
|
else if (!id5) {
|
|
@@ -73383,19 +73430,19 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73383
73430
|
/** 在同一 Store 事务内先更新正文,再发布可信顺序,不让 Web 看见暂存的中间帧。 */
|
|
73384
73431
|
itemOrderEvents(patch, itemEvents, context) {
|
|
73385
73432
|
if (this.itemOrderGaps.has(context.threadId)) return [];
|
|
73386
|
-
const
|
|
73387
|
-
if (
|
|
73433
|
+
const path71 = array7(patch.path);
|
|
73434
|
+
if (path71[0] !== "turnHistory") return [];
|
|
73388
73435
|
const invalidate = () => {
|
|
73389
73436
|
this.itemOrders.delete(context.threadId);
|
|
73390
73437
|
this.itemOrderGaps.add(context.threadId);
|
|
73391
73438
|
return [];
|
|
73392
73439
|
};
|
|
73393
|
-
if (
|
|
73394
|
-
if (
|
|
73395
|
-
if (
|
|
73440
|
+
if (path71.length < 3) return invalidate();
|
|
73441
|
+
if (path71[1] !== "history" || path71[2] !== "entitiesByKey") return [];
|
|
73442
|
+
if (path71.length < 4) return invalidate();
|
|
73396
73443
|
const activeId = this.activeTurnByThread.get(context.threadId);
|
|
73397
73444
|
if (!activeId) return [];
|
|
73398
|
-
const entityKey = String(
|
|
73445
|
+
const entityKey = String(path71[3]);
|
|
73399
73446
|
const events = [];
|
|
73400
73447
|
const emitItem = (value) => {
|
|
73401
73448
|
const item = this.orderedRawItem(value, activeId, context);
|
|
@@ -73412,8 +73459,8 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73412
73459
|
return item?.id ?? null;
|
|
73413
73460
|
};
|
|
73414
73461
|
let order = this.itemOrders.get(context.threadId);
|
|
73415
|
-
const wholeEntity =
|
|
73416
|
-
const wholeArray =
|
|
73462
|
+
const wholeEntity = path71.length === 4;
|
|
73463
|
+
const wholeArray = path71.length === 5 && path71[4] === "items";
|
|
73417
73464
|
if (wholeEntity || wholeArray) {
|
|
73418
73465
|
const entity = record25(patch.value);
|
|
73419
73466
|
const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) : this.entityTurnIdsByThread.get(context.threadId)?.get(entityKey);
|
|
@@ -73429,12 +73476,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73429
73476
|
}
|
|
73430
73477
|
values.forEach(emitItem);
|
|
73431
73478
|
} else {
|
|
73432
|
-
if (!order || order.turnId !== activeId || order.entityKey !== entityKey ||
|
|
73433
|
-
if (
|
|
73434
|
-
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() : [];
|
|
73435
73482
|
}
|
|
73436
|
-
if (
|
|
73437
|
-
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];
|
|
73438
73485
|
if (typeof index !== "number" || !Number.isSafeInteger(index) || index < 0 || index > order.ids.length || patch.op !== "add" && index === order.ids.length) return invalidate();
|
|
73439
73486
|
if (patch.op === "add" && order.ids.length >= 8192) return invalidate();
|
|
73440
73487
|
const previousId = order.ids[index];
|
|
@@ -73655,12 +73702,12 @@ var init_desktop_ipc_thread_view_adapter = __esm({
|
|
|
73655
73702
|
for (const patchValue of patches) {
|
|
73656
73703
|
const patch = record25(patchValue);
|
|
73657
73704
|
if (patch.op !== "add" && patch.op !== "replace") continue;
|
|
73658
|
-
const
|
|
73659
|
-
if (
|
|
73660
|
-
const entityKey =
|
|
73661
|
-
const wholeEntity =
|
|
73662
|
-
const statusField =
|
|
73663
|
-
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";
|
|
73664
73711
|
if (!wholeEntity && !statusField && !startField) continue;
|
|
73665
73712
|
const entity = wholeEntity ? record25(patch.value) : {};
|
|
73666
73713
|
const turnId = wholeEntity ? nonEmptyString14(entity.id) ?? nonEmptyString14(entity.turnId) ?? entityTurnIds.get(entityKey) ?? null : entityTurnIds.get(entityKey) ?? null;
|
|
@@ -73865,12 +73912,12 @@ function normalizeFileCitations(text11, paths) {
|
|
|
73865
73912
|
const end = start + match[0].length;
|
|
73866
73913
|
if (!textRanges.some(([a, b]) => a <= start && start < b) || excluded.some(([a, b]) => a < end && b > start)) continue;
|
|
73867
73914
|
const slashes = text11.slice(0, start).match(/\\*$/u)?.[0].length ?? 0;
|
|
73868
|
-
const
|
|
73869
|
-
if (slashes % 2 || paths.parseLocal(
|
|
73915
|
+
const path71 = match[1];
|
|
73916
|
+
if (slashes % 2 || paths.parseLocal(path71) === null) continue;
|
|
73870
73917
|
try {
|
|
73871
|
-
const target = paths.toLink(
|
|
73918
|
+
const target = paths.toLink(path71);
|
|
73872
73919
|
if (target === null) continue;
|
|
73873
|
-
const label2 = fallbackFileName(
|
|
73920
|
+
const label2 = fallbackFileName(path71, paths).replace(/[\\`*_[\]<> &]/gu, (value) => `&#${value.codePointAt(0)};`);
|
|
73874
73921
|
edits.push({ start, end, value: `[${label2}](<${target}>)` });
|
|
73875
73922
|
} catch {
|
|
73876
73923
|
}
|
|
@@ -73888,9 +73935,9 @@ function fileReferences(text11, paths) {
|
|
|
73888
73935
|
return markdownTargets(text11).references.filter((ref) => !ref.image).flatMap((ref) => {
|
|
73889
73936
|
try {
|
|
73890
73937
|
const target = withoutFileLocation(ref.url);
|
|
73891
|
-
const
|
|
73892
|
-
if (
|
|
73893
|
-
return [{ ...ref, path:
|
|
73938
|
+
const path71 = paths.parseLink(target);
|
|
73939
|
+
if (path71 === null) return [];
|
|
73940
|
+
return [{ ...ref, path: path71 }];
|
|
73894
73941
|
} catch {
|
|
73895
73942
|
return [];
|
|
73896
73943
|
}
|
|
@@ -73900,8 +73947,8 @@ function collectFileLinkPaths(item, paths = localResourcePaths) {
|
|
|
73900
73947
|
if (item.type !== "assistant_message") return [];
|
|
73901
73948
|
return [...new Set(item.content.flatMap((part) => part.type === "text" ? fileReferences(normalizeFileCitations(part.text, paths), paths).map((ref) => ref.path) : []))];
|
|
73902
73949
|
}
|
|
73903
|
-
function fallbackFileName(
|
|
73904
|
-
const name2 = paths.basename(
|
|
73950
|
+
function fallbackFileName(path71, paths) {
|
|
73951
|
+
const name2 = paths.basename(path71).slice(0, 255);
|
|
73905
73952
|
return name2.trim() && !/[\\/\x00-\x1f\x7f-\x9f]/u.test(name2) ? name2 : "\u6587\u4EF6";
|
|
73906
73953
|
}
|
|
73907
73954
|
function projectFileLinks(item, register, isRegistered = () => true, paths = localResourcePaths) {
|
|
@@ -73965,7 +74012,7 @@ var init_thread_view_files = __esm({
|
|
|
73965
74012
|
|
|
73966
74013
|
// apps/desktop/src/daemon/runtime/projection.ts
|
|
73967
74014
|
import { createHash as createHash36 } from "node:crypto";
|
|
73968
|
-
import
|
|
74015
|
+
import path54 from "node:path";
|
|
73969
74016
|
var FILE_REFRESH_MAX_ENTRIES, FILE_REFRESH_MAX_BYTES, FILE_REFRESH_ENTRY_BYTES, FILE_REFRESH_IN_FLIGHT_RESERVE, RuntimeProjection;
|
|
73970
74017
|
var init_projection2 = __esm({
|
|
73971
74018
|
"apps/desktop/src/daemon/runtime/projection.ts"() {
|
|
@@ -74097,14 +74144,14 @@ var init_projection2 = __esm({
|
|
|
74097
74144
|
isFileReferenceVisible(entry) {
|
|
74098
74145
|
if (this.ports.stopping()) return false;
|
|
74099
74146
|
const root = this.ports.projectRoot(entry.threadId);
|
|
74100
|
-
if (!root ||
|
|
74147
|
+
if (!root || path54.resolve(root) !== entry.root) return false;
|
|
74101
74148
|
const item = this.store.getProjectionItem(entry.threadId, entry.itemId);
|
|
74102
74149
|
if (!item) return false;
|
|
74103
74150
|
if (item.type === "user_message") {
|
|
74104
|
-
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);
|
|
74105
74152
|
}
|
|
74106
74153
|
if (item.type !== "assistant_message") return false;
|
|
74107
|
-
if (collectFileLinkPaths(item).some((sourcePath) =>
|
|
74154
|
+
if (collectFileLinkPaths(item).some((sourcePath) => path54.resolve(sourcePath) === entry.path)) return true;
|
|
74108
74155
|
return item.content.some((part) => part.type === "file" && part.attachment_id === entry.attachmentId) && hasFileAttachmentLink(item, entry.attachmentId);
|
|
74109
74156
|
}
|
|
74110
74157
|
subagentAvatars = new CodexSubagentAvatars();
|
|
@@ -75642,8 +75689,8 @@ var init_read_receipts = __esm({
|
|
|
75642
75689
|
return;
|
|
75643
75690
|
}
|
|
75644
75691
|
const statusOnly = change.type === "patches" && Array.isArray(change.patches) && change.patches.length > 0 && change.patches.every((value) => {
|
|
75645
|
-
const patch = objectRecord3(value),
|
|
75646
|
-
const fields3 =
|
|
75692
|
+
const patch = objectRecord3(value), path71 = Array.isArray(patch.path) ? patch.path : [];
|
|
75693
|
+
const fields3 = path71[0] === "conversationState" ? path71.slice(1) : path71;
|
|
75647
75694
|
if (!["add", "replace", "remove"].includes(String(patch.op)) || fields3.length !== 1) return false;
|
|
75648
75695
|
if (fields3[0] === "threadRuntimeStatus") return true;
|
|
75649
75696
|
return patch.op !== "remove" && (fields3[0] === "hasUnreadTurn" && patch.value === raw?.hasUnreadTurn || fields3[0] === "unreadMessageCount" && patch.value === raw?.unreadMessageCount);
|
|
@@ -77918,7 +77965,7 @@ var init_image_decoder = __esm({
|
|
|
77918
77965
|
});
|
|
77919
77966
|
|
|
77920
77967
|
// apps/desktop/src/attachments/image-assets.ts
|
|
77921
|
-
import
|
|
77968
|
+
import path55 from "node:path";
|
|
77922
77969
|
function names(id5) {
|
|
77923
77970
|
if (!idPattern.test(id5)) throw unavailable9();
|
|
77924
77971
|
return { metadata: `img_${id5.slice(4)}`, source: `src_${id5.slice(4)}`, preview: `prv_${id5.slice(4)}` };
|
|
@@ -77965,7 +78012,7 @@ var init_image_assets = __esm({
|
|
|
77965
78012
|
}
|
|
77966
78013
|
paths(id5) {
|
|
77967
78014
|
const n = names(id5);
|
|
77968
|
-
return { sourcePath:
|
|
78015
|
+
return { sourcePath: path55.join(this.root, n.source, "source"), previewPath: path55.join(this.root, n.preview, "source") };
|
|
77969
78016
|
}
|
|
77970
78017
|
asset(id5) {
|
|
77971
78018
|
const value = this.assets.get(id5);
|
|
@@ -78097,7 +78144,7 @@ import { constants as constants5 } from "node:fs";
|
|
|
78097
78144
|
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir2, open as open6 } from "node:fs/promises";
|
|
78098
78145
|
import { execFile as execFile13 } from "node:child_process";
|
|
78099
78146
|
import { promisify as promisify6 } from "node:util";
|
|
78100
|
-
import
|
|
78147
|
+
import path56 from "node:path";
|
|
78101
78148
|
async function preparePrivateImageRoot(directory3) {
|
|
78102
78149
|
if (process.platform === "win32") {
|
|
78103
78150
|
await ensureWindowsPrivateDirectoryAsync(directory3);
|
|
@@ -78113,7 +78160,7 @@ async function createPrivateImageDirectory(directory3) {
|
|
|
78113
78160
|
return;
|
|
78114
78161
|
}
|
|
78115
78162
|
directory3 = localWindowsPath(directory3);
|
|
78116
|
-
const parent = await openPrivateImageDirectory(
|
|
78163
|
+
const parent = await openPrivateImageDirectory(path56.dirname(directory3));
|
|
78117
78164
|
try {
|
|
78118
78165
|
await parent.verify();
|
|
78119
78166
|
await mkdir2(directory3, { mode: 448 });
|
|
@@ -78136,7 +78183,7 @@ Check-PrivateDirectory $env:NIUMA_IMAGE_DIRECTORY
|
|
|
78136
78183
|
}
|
|
78137
78184
|
async function openPrivateImageDirectory(requested, openFile2 = open6) {
|
|
78138
78185
|
const windows2 = process.platform === "win32";
|
|
78139
|
-
const directory3 = windows2 ? localWindowsPath(requested) :
|
|
78186
|
+
const directory3 = windows2 ? localWindowsPath(requested) : path56.resolve(requested);
|
|
78140
78187
|
const initial = await lstat5(directory3, { bigint: true });
|
|
78141
78188
|
if (!initial.isDirectory() || initial.isSymbolicLink()) throw unavailable10();
|
|
78142
78189
|
let handle;
|
|
@@ -78245,7 +78292,7 @@ var init_private_image_files = __esm({
|
|
|
78245
78292
|
// apps/desktop/src/platform/private-image-commit.ts
|
|
78246
78293
|
import { randomUUID as randomUUID50 } from "node:crypto";
|
|
78247
78294
|
import { lstat as lstat6, rename as rename2, rm as rm2 } from "node:fs/promises";
|
|
78248
|
-
import
|
|
78295
|
+
import path57 from "node:path";
|
|
78249
78296
|
async function snapshot(file, maxBytes) {
|
|
78250
78297
|
try {
|
|
78251
78298
|
await lstat6(file);
|
|
@@ -78310,7 +78357,7 @@ var init_private_image_commit = __esm({
|
|
|
78310
78357
|
await this.writeBinary(file, bytes3, maxBytes);
|
|
78311
78358
|
return;
|
|
78312
78359
|
}
|
|
78313
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78360
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78314
78361
|
try {
|
|
78315
78362
|
const handle = await privateBinaryFiles.open(file, { maxBytes, writable: true, mode: "mutable" });
|
|
78316
78363
|
try {
|
|
@@ -78345,7 +78392,7 @@ var init_private_image_commit = __esm({
|
|
|
78345
78392
|
}
|
|
78346
78393
|
},
|
|
78347
78394
|
async writeBinary(file, bytes3, maxBytes) {
|
|
78348
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78395
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78349
78396
|
try {
|
|
78350
78397
|
await directory3.verify();
|
|
78351
78398
|
await writeNew(file, bytes3, maxBytes);
|
|
@@ -78358,8 +78405,8 @@ var init_private_image_commit = __esm({
|
|
|
78358
78405
|
const bytes3 = Buffer.from(input);
|
|
78359
78406
|
let published = false, renameAttempted = false;
|
|
78360
78407
|
let temporaryIdentity;
|
|
78361
|
-
const directory3 = await openPrivateImageDirectory(
|
|
78362
|
-
const temporary =
|
|
78408
|
+
const directory3 = await openPrivateImageDirectory(path57.dirname(file));
|
|
78409
|
+
const temporary = path57.join(path57.dirname(file), `.manifest-${randomUUID50()}.tmp`);
|
|
78363
78410
|
try {
|
|
78364
78411
|
if (bytes3.length > maxBytes) throw new PrivateImageCommitError();
|
|
78365
78412
|
new TextDecoder("utf-8", { fatal: true }).decode(bytes3);
|
|
@@ -78407,14 +78454,14 @@ var init_private_image_commit = __esm({
|
|
|
78407
78454
|
});
|
|
78408
78455
|
|
|
78409
78456
|
// apps/desktop/src/platform/private-document-directory.ts
|
|
78410
|
-
import
|
|
78411
|
-
import
|
|
78457
|
+
import fs40 from "node:fs";
|
|
78458
|
+
import path58 from "node:path";
|
|
78412
78459
|
async function openPrivateDocumentDirectory(root) {
|
|
78413
|
-
const directory3 =
|
|
78460
|
+
const directory3 = path58.resolve(root);
|
|
78414
78461
|
let identity6;
|
|
78415
78462
|
try {
|
|
78416
78463
|
privateLogFiles.ensureDirectory(directory3);
|
|
78417
|
-
identity6 =
|
|
78464
|
+
identity6 = fs40.lstatSync(directory3, { bigint: true });
|
|
78418
78465
|
privateLogFiles.checkDirectory(directory3);
|
|
78419
78466
|
guard();
|
|
78420
78467
|
} catch {
|
|
@@ -78422,7 +78469,7 @@ async function openPrivateDocumentDirectory(root) {
|
|
|
78422
78469
|
}
|
|
78423
78470
|
function guard() {
|
|
78424
78471
|
try {
|
|
78425
|
-
const current2 =
|
|
78472
|
+
const current2 = fs40.lstatSync(directory3, { bigint: true });
|
|
78426
78473
|
if (!current2.isDirectory() || current2.isSymbolicLink() || current2.dev !== identity6.dev || current2.ino !== identity6.ino) {
|
|
78427
78474
|
throw new PrivateDocumentFileError("unavailable");
|
|
78428
78475
|
}
|
|
@@ -78435,7 +78482,7 @@ async function openPrivateDocumentDirectory(root) {
|
|
|
78435
78482
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/u.test(name2) || name2 === "." || name2 === "..") {
|
|
78436
78483
|
throw new PrivateDocumentFileError("unavailable");
|
|
78437
78484
|
}
|
|
78438
|
-
return
|
|
78485
|
+
return path58.join(directory3, name2);
|
|
78439
78486
|
}
|
|
78440
78487
|
const files = privateStateFilesWithGuard(guard);
|
|
78441
78488
|
return {
|
|
@@ -78519,36 +78566,36 @@ function decodeBase64(value) {
|
|
|
78519
78566
|
function sha256(value) {
|
|
78520
78567
|
return createHash39("sha256").update(value).digest("hex");
|
|
78521
78568
|
}
|
|
78522
|
-
async function readJsonManifest(
|
|
78569
|
+
async function readJsonManifest(path71, io) {
|
|
78523
78570
|
try {
|
|
78524
78571
|
if (io.controlledFiles) {
|
|
78525
|
-
const { data } = await io.controlledFiles.read(
|
|
78572
|
+
const { data } = await io.controlledFiles.read(path71);
|
|
78526
78573
|
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(data));
|
|
78527
78574
|
}
|
|
78528
|
-
const status2 = await lstat7(
|
|
78575
|
+
const status2 = await lstat7(path71);
|
|
78529
78576
|
if (!status2.isFile() || status2.isSymbolicLink()) {
|
|
78530
78577
|
return null;
|
|
78531
78578
|
}
|
|
78532
|
-
return JSON.parse(await readFile2(
|
|
78579
|
+
return JSON.parse(await readFile2(path71, "utf8"));
|
|
78533
78580
|
} catch {
|
|
78534
78581
|
return null;
|
|
78535
78582
|
}
|
|
78536
78583
|
}
|
|
78537
|
-
async function assertRegularControlledFile(directoryPath,
|
|
78538
|
-
if (dirname3(
|
|
78584
|
+
async function assertRegularControlledFile(directoryPath, path71) {
|
|
78585
|
+
if (dirname3(path71) !== directoryPath) {
|
|
78539
78586
|
throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
|
|
78540
78587
|
}
|
|
78541
|
-
const status2 = await lstat7(
|
|
78588
|
+
const status2 = await lstat7(path71).catch(() => null);
|
|
78542
78589
|
if (!status2?.isFile() || status2.isSymbolicLink()) {
|
|
78543
78590
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78544
78591
|
}
|
|
78545
78592
|
}
|
|
78546
|
-
async function readRegularFileNoFollow(io, directoryPath,
|
|
78547
|
-
if (dirname3(
|
|
78593
|
+
async function readRegularFileNoFollow(io, directoryPath, path71, expectedIdentity, expectedSize) {
|
|
78594
|
+
if (dirname3(path71) !== directoryPath) {
|
|
78548
78595
|
throw new Error("ATTACHMENT_PATH_OUTSIDE_ROOT");
|
|
78549
78596
|
}
|
|
78550
|
-
if (io.controlledFiles) return io.controlledFiles.read(
|
|
78551
|
-
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);
|
|
78552
78599
|
if (!handle) {
|
|
78553
78600
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78554
78601
|
}
|
|
@@ -78572,8 +78619,8 @@ async function readRegularFileNoFollow(io, directoryPath, path70, expectedIdenti
|
|
|
78572
78619
|
await handle.close();
|
|
78573
78620
|
}
|
|
78574
78621
|
}
|
|
78575
|
-
async function readStableLocalFile(io,
|
|
78576
|
-
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);
|
|
78577
78624
|
if (!handle) {
|
|
78578
78625
|
throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
|
|
78579
78626
|
}
|
|
@@ -78585,8 +78632,8 @@ async function readStableLocalFile(io, path70) {
|
|
|
78585
78632
|
if (openedStatus.size > BigInt(MAX_IMAGE_BYTES)) {
|
|
78586
78633
|
throw new Error("ATTACHMENT_TOO_LARGE");
|
|
78587
78634
|
}
|
|
78588
|
-
const canonicalPath = await realpath3(
|
|
78589
|
-
const currentStatus = await lstat7(
|
|
78635
|
+
const canonicalPath = await realpath3(path71).catch(() => null);
|
|
78636
|
+
const currentStatus = await lstat7(path71, { bigint: true }).catch(() => null);
|
|
78590
78637
|
if (!canonicalPath || !currentStatus?.isFile() || currentStatus.isSymbolicLink() || currentStatus.dev !== openedStatus.dev || currentStatus.ino !== openedStatus.ino) {
|
|
78591
78638
|
throw new Error("LOCAL_IMAGE_NOT_REGULAR_FILE");
|
|
78592
78639
|
}
|
|
@@ -78599,17 +78646,17 @@ async function readStableLocalFile(io, path70) {
|
|
|
78599
78646
|
await handle.close();
|
|
78600
78647
|
}
|
|
78601
78648
|
}
|
|
78602
|
-
async function pathIsMissing(
|
|
78649
|
+
async function pathIsMissing(path71) {
|
|
78603
78650
|
try {
|
|
78604
|
-
await lstat7(
|
|
78651
|
+
await lstat7(path71);
|
|
78605
78652
|
return false;
|
|
78606
78653
|
} catch (error2) {
|
|
78607
78654
|
return error2.code === "ENOENT";
|
|
78608
78655
|
}
|
|
78609
78656
|
}
|
|
78610
|
-
async function readFileIdentity(io,
|
|
78611
|
-
if (io.controlledFiles) return io.controlledFiles.identity(
|
|
78612
|
-
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);
|
|
78613
78660
|
if (!handle) {
|
|
78614
78661
|
throw new Error("ATTACHMENT_FILE_NOT_AVAILABLE");
|
|
78615
78662
|
}
|
|
@@ -78724,7 +78771,7 @@ var init_store = __esm({
|
|
|
78724
78771
|
webp: "image/webp"
|
|
78725
78772
|
};
|
|
78726
78773
|
DEFAULT_ATTACHMENT_STORE_IO = {
|
|
78727
|
-
open: (
|
|
78774
|
+
open: (path71, flags) => open7(path71, flags),
|
|
78728
78775
|
controlledFiles: privateImageFiles
|
|
78729
78776
|
};
|
|
78730
78777
|
AttachmentStore = class _AttachmentStore {
|
|
@@ -78937,15 +78984,15 @@ var init_store = __esm({
|
|
|
78937
78984
|
const allowed = /* @__PURE__ */ new Set([MANIFEST_RELATIVE_PATH, ...next.chunks.map((chunk) => chunk.relativePath)]);
|
|
78938
78985
|
if ((await readdir2(upload.directoryPath)).some((name2) => !allowed.has(name2))) throw new Error("UPLOAD_DIRECTORY_NOT_VERIFIED");
|
|
78939
78986
|
for (let offset = 0; offset < chunks.length; offset++) {
|
|
78940
|
-
const
|
|
78987
|
+
const path71 = join2(upload.directoryPath, `chunk-${input.startIndex + offset}`), chunk = chunks[offset];
|
|
78941
78988
|
let handle;
|
|
78942
78989
|
try {
|
|
78943
|
-
handle = await this.#io.open(
|
|
78990
|
+
handle = await this.#io.open(path71, constants6.O_WRONLY | constants6.O_CREAT | constants6.O_EXCL | constants6.O_NOFOLLOW);
|
|
78944
78991
|
} catch (error2) {
|
|
78945
78992
|
if (error2.code !== "EEXIST") throw error2;
|
|
78946
|
-
const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath,
|
|
78993
|
+
const stored = await readRegularFileNoFollow(this.#io, upload.directoryPath, path71, void 0, chunk.length);
|
|
78947
78994
|
if (!stored.data.equals(chunk)) throw new Error("CHUNK_CONFLICT");
|
|
78948
|
-
handle = await this.#io.open(
|
|
78995
|
+
handle = await this.#io.open(path71, constants6.O_RDONLY | constants6.O_NOFOLLOW);
|
|
78949
78996
|
}
|
|
78950
78997
|
try {
|
|
78951
78998
|
const status2 = await handle.stat();
|
|
@@ -79325,9 +79372,9 @@ var init_store = __esm({
|
|
|
79325
79372
|
await this.#imageAssets.removeBytes(record26.id);
|
|
79326
79373
|
continue;
|
|
79327
79374
|
}
|
|
79328
|
-
for (const
|
|
79329
|
-
const status2 = await lstat7(
|
|
79330
|
-
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);
|
|
79331
79378
|
}
|
|
79332
79379
|
}
|
|
79333
79380
|
}
|
|
@@ -79865,10 +79912,10 @@ var init_store = __esm({
|
|
|
79865
79912
|
return bytes3;
|
|
79866
79913
|
}
|
|
79867
79914
|
async #loadBindingIndex() {
|
|
79868
|
-
const
|
|
79869
|
-
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);
|
|
79870
79917
|
if (manifest === null) {
|
|
79871
|
-
if (this.#rawCommit && !await pathIsMissing(
|
|
79918
|
+
if (this.#rawCommit && !await pathIsMissing(path71)) this.#bindingUnavailable = true;
|
|
79872
79919
|
return;
|
|
79873
79920
|
}
|
|
79874
79921
|
if (!isBindingIndexManifest(manifest)) {
|
|
@@ -79928,14 +79975,14 @@ var init_store = __esm({
|
|
|
79928
79975
|
return;
|
|
79929
79976
|
}
|
|
79930
79977
|
const temporaryPath = join2(this.#rootDir, `.bindings-${randomUUID51()}.tmp`);
|
|
79931
|
-
const
|
|
79978
|
+
const path71 = join2(this.#rootDir, BINDINGS_RELATIVE_PATH);
|
|
79932
79979
|
await writeFile(temporaryPath, `${JSON.stringify(manifest)}
|
|
79933
79980
|
`, {
|
|
79934
79981
|
flag: "wx",
|
|
79935
79982
|
mode: 384
|
|
79936
79983
|
});
|
|
79937
|
-
await rename3(temporaryPath,
|
|
79938
|
-
await chmod3(
|
|
79984
|
+
await rename3(temporaryPath, path71);
|
|
79985
|
+
await chmod3(path71, 384);
|
|
79939
79986
|
}
|
|
79940
79987
|
#commitBindings(bindings) {
|
|
79941
79988
|
this.#bindings.clear();
|
|
@@ -81047,7 +81094,7 @@ var init_managed_store = __esm({
|
|
|
81047
81094
|
});
|
|
81048
81095
|
|
|
81049
81096
|
// apps/desktop/src/daemon/runtime/attachment-storage.ts
|
|
81050
|
-
import
|
|
81097
|
+
import path59 from "node:path";
|
|
81051
81098
|
import { randomUUID as randomUUID53 } from "node:crypto";
|
|
81052
81099
|
var ATTACHMENT_CLEANUP_INTERVAL_MS, RuntimeAttachmentStorage;
|
|
81053
81100
|
var init_attachment_storage = __esm({
|
|
@@ -81189,7 +81236,7 @@ var init_attachment_storage = __esm({
|
|
|
81189
81236
|
requireAttachmentMessageBindings() {
|
|
81190
81237
|
if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
81191
81238
|
if (!this.attachmentMessageBindingsPromise) {
|
|
81192
|
-
this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(
|
|
81239
|
+
this.attachmentMessageBindingsPromise = AttachmentMessageBindings.open(path59.join(this.ports.dataDirectory(), "attachments", "bindings")).then((store) => {
|
|
81193
81240
|
this.attachmentMessageBindings = store;
|
|
81194
81241
|
return store;
|
|
81195
81242
|
}).catch((error2) => {
|
|
@@ -81205,7 +81252,7 @@ var init_attachment_storage = __esm({
|
|
|
81205
81252
|
if (!this.attachmentCodexHome) throw new NiumaError("SYSTEM_ERROR", "\u9644\u4EF6\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
81206
81253
|
if (!this.managedAttachmentStorePromise) {
|
|
81207
81254
|
const opening = runManagedAttachmentOperation(() => ManagedAttachmentStore.open(
|
|
81208
|
-
|
|
81255
|
+
path59.join(this.ports.dataDirectory(), "attachments", "managed")
|
|
81209
81256
|
)).catch((error2) => {
|
|
81210
81257
|
if (this.managedAttachmentStorePromise === opening) this.managedAttachmentStorePromise = null;
|
|
81211
81258
|
throw error2;
|
|
@@ -82602,9 +82649,9 @@ function sameDeferredIdentity(source2, previous) {
|
|
|
82602
82649
|
if (source2.kind === "history") return previous.kind === "history" && sameLocator(source2.locator, previous.locator);
|
|
82603
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);
|
|
82604
82651
|
}
|
|
82605
|
-
async function readSourceFile(
|
|
82652
|
+
async function readSourceFile(path71, signal) {
|
|
82606
82653
|
signal?.throwIfAborted();
|
|
82607
|
-
const handle = await open8(
|
|
82654
|
+
const handle = await open8(path71, constants7.O_RDONLY | constants7.O_NOFOLLOW);
|
|
82608
82655
|
try {
|
|
82609
82656
|
const before = await handle.stat({ bigint: true });
|
|
82610
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");
|
|
@@ -82833,12 +82880,12 @@ var init_image_resources = __esm({
|
|
|
82833
82880
|
}, JSON.stringify(identity6));
|
|
82834
82881
|
}
|
|
82835
82882
|
/** 仅供已认证实时消息登记;调用方每次请求仍须验证当前 item/上传暂存资格。 */
|
|
82836
|
-
async registerDeferredFile(threadId2,
|
|
82837
|
-
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 } });
|
|
82838
82885
|
}
|
|
82839
|
-
async registerFile(threadId2,
|
|
82886
|
+
async registerFile(threadId2, path71, attachmentId, context) {
|
|
82840
82887
|
if (context && context.visibilityLocator.threadId !== threadId2) throw missing3();
|
|
82841
|
-
const canonical = await realpath4(
|
|
82888
|
+
const canonical = await realpath4(path71);
|
|
82842
82889
|
const file = await readSourceFile(canonical);
|
|
82843
82890
|
return this.register({ attachmentId, resourceKey: context?.resourceKey ?? `file:${threadId2}:${canonical}`, name: basename4(canonical), source: {
|
|
82844
82891
|
kind: "file",
|
|
@@ -82868,9 +82915,9 @@ var init_image_resources = __esm({
|
|
|
82868
82915
|
return sameLocator(this.historyLocator(threadId2, attachmentId) ?? void 0, expectedLocator);
|
|
82869
82916
|
}
|
|
82870
82917
|
/** 保留原件换源时只复用相同受控文件;历史别名和旧暂存不能遮蔽新来源。 */
|
|
82871
|
-
matchesFilePath(threadId2, attachmentId,
|
|
82918
|
+
matchesFilePath(threadId2, attachmentId, path71) {
|
|
82872
82919
|
const entry = this.entries.get(attachmentId);
|
|
82873
|
-
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;
|
|
82874
82921
|
}
|
|
82875
82922
|
has(threadId2, attachmentId) {
|
|
82876
82923
|
const entry = this.entries.get(attachmentId);
|
|
@@ -83276,7 +83323,7 @@ var init_image_confirmation2 = __esm({
|
|
|
83276
83323
|
// apps/desktop/src/daemon/runtime/images.ts
|
|
83277
83324
|
import { createHash as createHash42 } from "node:crypto";
|
|
83278
83325
|
import { realpath as realpath5 } from "node:fs/promises";
|
|
83279
|
-
import
|
|
83326
|
+
import path60 from "node:path";
|
|
83280
83327
|
function objectRecord12(value) {
|
|
83281
83328
|
return value && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
83282
83329
|
}
|
|
@@ -83395,7 +83442,7 @@ var init_images = __esm({
|
|
|
83395
83442
|
if (itemId && ["userMessage", "UserMessage", "user_message"].includes(String(item.type))) {
|
|
83396
83443
|
if (Array.isArray(item.content)) item.content.forEach((part, index) => {
|
|
83397
83444
|
const input = objectRecord12(part);
|
|
83398
|
-
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));
|
|
83399
83446
|
const url = input.type === "image" ? nonEmptyString19(input.url ?? input.image_url) : null;
|
|
83400
83447
|
if (url?.startsWith("data:image/")) registrations.push(this.importThreadImage(threadId2, url, itemId, index));
|
|
83401
83448
|
});
|
|
@@ -83419,7 +83466,7 @@ var init_images = __esm({
|
|
|
83419
83466
|
requireImageResources() {
|
|
83420
83467
|
if (!this.ports.attachmentReady()) throw new Error("\u56FE\u7247\u5B58\u50A8\u5C1A\u672A\u521D\u59CB\u5316");
|
|
83421
83468
|
if (!this.imageResourcesPromise) this.imageResourcesPromise = ImageResources.create({
|
|
83422
|
-
indexPath:
|
|
83469
|
+
indexPath: path60.join(this.ports.dataDirectory(), "image-resources", "index.json"),
|
|
83423
83470
|
readAppServerImage: (source2, signal) => this.readAppServerImage(source2, signal),
|
|
83424
83471
|
onDiagnostic: (event) => this.ports.diagnostic(event)
|
|
83425
83472
|
}).catch((error2) => {
|
|
@@ -83600,7 +83647,7 @@ var init_images = __esm({
|
|
|
83600
83647
|
/** 同一消息引用共享轻量登记;整个 Runtime 最多同时处理四个索引写入。 */
|
|
83601
83648
|
importThreadImage(threadId2, sourcePath, itemId, partIndex, sourceIsCurrent = () => true) {
|
|
83602
83649
|
const embedded = sourcePath.startsWith("data:image/") && Number.isSafeInteger(partIndex) && partIndex >= 0;
|
|
83603
|
-
if (!itemId || !
|
|
83650
|
+
if (!itemId || !path60.isAbsolute(sourcePath) && !embedded) return Promise.resolve();
|
|
83604
83651
|
const generation = this.ports.generation();
|
|
83605
83652
|
const key = this.localImageKey(threadId2, sourcePath, itemId, partIndex);
|
|
83606
83653
|
const routeGeneration = this.ports.controlGeneration(threadId2);
|
|
@@ -83637,7 +83684,7 @@ var init_images = __esm({
|
|
|
83637
83684
|
this.knownLocalImages.set(key, {
|
|
83638
83685
|
type: "image",
|
|
83639
83686
|
attachmentId: registered.attachmentId,
|
|
83640
|
-
name: embedded ? "\u56FE\u7247" :
|
|
83687
|
+
name: embedded ? "\u56FE\u7247" : path60.basename(sourcePath),
|
|
83641
83688
|
previewAvailable: false,
|
|
83642
83689
|
previewState: "deferred"
|
|
83643
83690
|
});
|
|
@@ -85723,18 +85770,18 @@ var init_session_sources = __esm({
|
|
|
85723
85770
|
const isCurrent = () => options.isCurrent?.() !== false;
|
|
85724
85771
|
const paths = /* @__PURE__ */ new Map();
|
|
85725
85772
|
for (const thread4 of threads) {
|
|
85726
|
-
const
|
|
85727
|
-
if (!paths.has(thread4.id)) paths.set(thread4.id,
|
|
85728
|
-
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);
|
|
85729
85776
|
}
|
|
85730
|
-
for (const [id5,
|
|
85777
|
+
for (const [id5, path71] of paths) {
|
|
85731
85778
|
const thread4 = { id: id5 };
|
|
85732
85779
|
if (!isCurrent()) return;
|
|
85733
85780
|
const token3 = this.begin(thread4.id);
|
|
85734
85781
|
let resolution = null;
|
|
85735
85782
|
if (resolver) {
|
|
85736
85783
|
try {
|
|
85737
|
-
resolution = await resolver.resolve(thread4.id,
|
|
85784
|
+
resolution = await resolver.resolve(thread4.id, path71);
|
|
85738
85785
|
} catch {
|
|
85739
85786
|
resolution = null;
|
|
85740
85787
|
}
|
|
@@ -85799,7 +85846,7 @@ var init_session_sources = __esm({
|
|
|
85799
85846
|
});
|
|
85800
85847
|
|
|
85801
85848
|
// apps/desktop/src/daemon/runtime/settings-selection.ts
|
|
85802
|
-
import
|
|
85849
|
+
import path61 from "node:path";
|
|
85803
85850
|
var RuntimeSettingsSelection;
|
|
85804
85851
|
var init_settings_selection = __esm({
|
|
85805
85852
|
"apps/desktop/src/daemon/runtime/settings-selection.ts"() {
|
|
@@ -85815,7 +85862,7 @@ var init_settings_selection = __esm({
|
|
|
85815
85862
|
ports;
|
|
85816
85863
|
targetProjectRoot(cwd) {
|
|
85817
85864
|
const matched = this.ports.projectRoots().filter((projectRoot) => pathBelongsToProjectRoot(projectRoot, cwd)).sort((left, right) => right.length - left.length)[0];
|
|
85818
|
-
return matched ??
|
|
85865
|
+
return matched ?? path61.normalize(cwd);
|
|
85819
85866
|
}
|
|
85820
85867
|
inheritedCreate(threadId2) {
|
|
85821
85868
|
const empty = { authorization: null, model: null };
|
|
@@ -86159,7 +86206,7 @@ var init_device_name = __esm({
|
|
|
86159
86206
|
});
|
|
86160
86207
|
|
|
86161
86208
|
// apps/desktop/src/daemon/debug-log.ts
|
|
86162
|
-
import
|
|
86209
|
+
import path62 from "node:path";
|
|
86163
86210
|
function isNotificationDeliveryReason(value) {
|
|
86164
86211
|
return NOTIFICATION_DELIVERY_REASON_CODES.has(value) || /^http_[1-5]\d\d$/.test(value) || /^business_\d{1,6}$/.test(value);
|
|
86165
86212
|
}
|
|
@@ -86198,10 +86245,10 @@ function hasDebugFilter(filter) {
|
|
|
86198
86245
|
return Boolean(filter?.components || filter?.channels || filter?.events);
|
|
86199
86246
|
}
|
|
86200
86247
|
function createSafeFilePath(runtimeDir, files) {
|
|
86201
|
-
const dir =
|
|
86248
|
+
const dir = path62.join(runtimeDir, "debug");
|
|
86202
86249
|
files.ensureDirectory(dir);
|
|
86203
86250
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
86204
|
-
return
|
|
86251
|
+
return path62.join(dir, `${timestamp}-${process.pid}.ndjson`);
|
|
86205
86252
|
}
|
|
86206
86253
|
function createFileDebugLogger(filePath, shouldWrite, files) {
|
|
86207
86254
|
let writer;
|
|
@@ -86807,7 +86854,7 @@ function withoutPersistentImageBytes(value, key = "", seen = /* @__PURE__ */ new
|
|
|
86807
86854
|
function createFileRawDebugLogger(runtimeDir, filter, policy, files) {
|
|
86808
86855
|
const now = policy.now ?? (() => /* @__PURE__ */ new Date());
|
|
86809
86856
|
const manager = new RawDebugFileManager(
|
|
86810
|
-
|
|
86857
|
+
path62.join(runtimeDir, "debug"),
|
|
86811
86858
|
now,
|
|
86812
86859
|
policy.maxSegmentBytes ?? RAW_DEBUG_MAX_SEGMENT_BYTES,
|
|
86813
86860
|
policy.maxSegments ?? RAW_DEBUG_MAX_SEGMENTS,
|
|
@@ -87818,7 +87865,7 @@ var init_debug_log = __esm({
|
|
|
87818
87865
|
}
|
|
87819
87866
|
const timestamp = this.now().toISOString().replace(/[:.]/g, "-");
|
|
87820
87867
|
for (; ; ) {
|
|
87821
|
-
const filePath =
|
|
87868
|
+
const filePath = path62.join(this.directory, `${timestamp}-${process.pid}-raw-${this.sequence++}.ndjson`);
|
|
87822
87869
|
try {
|
|
87823
87870
|
return this.files.create(filePath);
|
|
87824
87871
|
} catch (error2) {
|
|
@@ -87851,7 +87898,7 @@ var init_debug_log = __esm({
|
|
|
87851
87898
|
});
|
|
87852
87899
|
|
|
87853
87900
|
// apps/desktop/src/daemon/control-observability.ts
|
|
87854
|
-
import
|
|
87901
|
+
import path63 from "node:path";
|
|
87855
87902
|
function isRecentControlTimestamp(timestampMs, nowMs) {
|
|
87856
87903
|
return timestampMs <= nowMs && isRetainedDaemonLogTimestamp(timestampMs, nowMs);
|
|
87857
87904
|
}
|
|
@@ -87884,7 +87931,7 @@ function page3(values, params) {
|
|
|
87884
87931
|
};
|
|
87885
87932
|
}
|
|
87886
87933
|
function listControlLogs(input) {
|
|
87887
|
-
const directoryPath =
|
|
87934
|
+
const directoryPath = path63.join(input.runtimeDir, input.kind === "error" ? "errors" : "debug");
|
|
87888
87935
|
const values = [];
|
|
87889
87936
|
let totalBytes = 0;
|
|
87890
87937
|
let processedLines = 0;
|
|
@@ -88907,7 +88954,7 @@ var init_composition = __esm({
|
|
|
88907
88954
|
refreshFallback: async (id5, token3) => {
|
|
88908
88955
|
await this.historySnapshot.tryRefreshThreadMessages(id5, false, { kind: "fallback", token: token3 });
|
|
88909
88956
|
},
|
|
88910
|
-
resolveKnownLocalImage: (id5,
|
|
88957
|
+
resolveKnownLocalImage: (id5, path71, itemId, partIndex) => this.images.resolveKnownLocalImage(id5, path71, itemId, partIndex),
|
|
88911
88958
|
hasDesktopSnapshot: (id5) => this.controlAccess.snapshot(id5).hasCurrentDesktopSnapshot,
|
|
88912
88959
|
followerPhase: (id5) => this.followerCoordination.activeThreadFollowerCoordinatorValue?.phaseFor(id5) ?? null,
|
|
88913
88960
|
generation: () => this.lifecycle.runtimeGenerationValue
|
|
@@ -90503,7 +90550,7 @@ var init_runtime2 = __esm({
|
|
|
90503
90550
|
|
|
90504
90551
|
// apps/desktop/src/daemon/follower-open-trace.ts
|
|
90505
90552
|
import { randomUUID as randomUUID56 } from "node:crypto";
|
|
90506
|
-
import
|
|
90553
|
+
import path64 from "node:path";
|
|
90507
90554
|
function isFiniteTimestamp2(value) {
|
|
90508
90555
|
return typeof value === "number" && Number.isFinite(value) && Number.isSafeInteger(value);
|
|
90509
90556
|
}
|
|
@@ -90641,7 +90688,7 @@ function parseRecord2(line) {
|
|
|
90641
90688
|
function listPrivateTraceFiles(runtimeDir, storage) {
|
|
90642
90689
|
try {
|
|
90643
90690
|
storage.checkDirectory(runtimeDir);
|
|
90644
|
-
const scan = storage.scan(
|
|
90691
|
+
const scan = storage.scan(path64.join(runtimeDir, TRACE_DIRECTORY_NAME), MAX_DIRECTORY_ENTRIES3);
|
|
90645
90692
|
const files = [];
|
|
90646
90693
|
let incomplete = scan.truncated;
|
|
90647
90694
|
for (const entry of scan.entries) {
|
|
@@ -90655,8 +90702,8 @@ function listPrivateTraceFiles(runtimeDir, storage) {
|
|
|
90655
90702
|
}
|
|
90656
90703
|
}
|
|
90657
90704
|
function compareTraceFilePaths(left, right) {
|
|
90658
|
-
const a =
|
|
90659
|
-
const b =
|
|
90705
|
+
const a = path64.basename(left);
|
|
90706
|
+
const b = path64.basename(right);
|
|
90660
90707
|
return a.slice(0, 10).localeCompare(b.slice(0, 10)) || Number(a.slice(11, -7)) - Number(b.slice(11, -7));
|
|
90661
90708
|
}
|
|
90662
90709
|
function readPrivateTraceFile(file, remainingBytes, storage) {
|
|
@@ -91173,7 +91220,7 @@ var init_follower_open_trace = __esm({
|
|
|
91173
91220
|
}
|
|
91174
91221
|
clearAll() {
|
|
91175
91222
|
try {
|
|
91176
|
-
const directoryPath =
|
|
91223
|
+
const directoryPath = path64.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
|
|
91177
91224
|
this.files.checkDirectory(this.runtimeDir);
|
|
91178
91225
|
let scan;
|
|
91179
91226
|
try {
|
|
@@ -91230,7 +91277,7 @@ var init_follower_open_trace = __esm({
|
|
|
91230
91277
|
}
|
|
91231
91278
|
}
|
|
91232
91279
|
append(record26) {
|
|
91233
|
-
const directoryPath =
|
|
91280
|
+
const directoryPath = path64.join(this.runtimeDir, TRACE_DIRECTORY_NAME);
|
|
91234
91281
|
this.ensureTraceDirectory(directoryPath);
|
|
91235
91282
|
const content2 = `${JSON.stringify(record26)}
|
|
91236
91283
|
`;
|
|
@@ -91240,8 +91287,8 @@ var init_follower_open_trace = __esm({
|
|
|
91240
91287
|
selectAppendFile(directoryPath, dateName, bytes3) {
|
|
91241
91288
|
const date = dateName.slice(0, 10);
|
|
91242
91289
|
let filePath = this.appendFilePath;
|
|
91243
|
-
if (!filePath ||
|
|
91244
|
-
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);
|
|
91245
91292
|
}
|
|
91246
91293
|
for (let attempt = 0; attempt < MAX_DIRECTORY_ENTRIES3; attempt += 1) {
|
|
91247
91294
|
let stats;
|
|
@@ -91254,9 +91301,9 @@ var init_follower_open_trace = __esm({
|
|
|
91254
91301
|
this.appendFilePath = filePath;
|
|
91255
91302
|
return filePath;
|
|
91256
91303
|
}
|
|
91257
|
-
const next = Number(
|
|
91304
|
+
const next = Number(path64.basename(filePath).slice(11, -7)) + 1;
|
|
91258
91305
|
if (next > 999999) break;
|
|
91259
|
-
filePath =
|
|
91306
|
+
filePath = path64.join(directoryPath, `${date}.${String(next).padStart(6, "0")}.ndjson`);
|
|
91260
91307
|
}
|
|
91261
91308
|
throw new Error("trace segment limit reached");
|
|
91262
91309
|
}
|
|
@@ -92631,7 +92678,7 @@ var init_watch = __esm({
|
|
|
92631
92678
|
});
|
|
92632
92679
|
|
|
92633
92680
|
// apps/desktop/src/relay/relay-origin-store.ts
|
|
92634
|
-
import
|
|
92681
|
+
import path65 from "node:path";
|
|
92635
92682
|
function parseStoredOrigin(value) {
|
|
92636
92683
|
try {
|
|
92637
92684
|
const document = JSON.parse(value);
|
|
@@ -92645,7 +92692,7 @@ function parseStoredOrigin(value) {
|
|
|
92645
92692
|
}
|
|
92646
92693
|
}
|
|
92647
92694
|
function resolveDefaultRelayOriginStorePath() {
|
|
92648
|
-
return
|
|
92695
|
+
return path65.join(desktopPlatform().directories.data, DEFAULT_FILE_NAME2);
|
|
92649
92696
|
}
|
|
92650
92697
|
var DEFAULT_FILE_NAME2, MAX_FILE_BYTES3, FileRelayOriginStore;
|
|
92651
92698
|
var init_relay_origin_store = __esm({
|
|
@@ -92661,7 +92708,7 @@ var init_relay_origin_store = __esm({
|
|
|
92661
92708
|
files;
|
|
92662
92709
|
tail = Promise.resolve();
|
|
92663
92710
|
constructor(options = {}) {
|
|
92664
|
-
this.filePath =
|
|
92711
|
+
this.filePath = path65.resolve(options.file_path ?? resolveDefaultRelayOriginStorePath());
|
|
92665
92712
|
this.files = options.files ?? privateDocumentFiles;
|
|
92666
92713
|
}
|
|
92667
92714
|
async load() {
|
|
@@ -92697,7 +92744,7 @@ var init_relay_origin_store = __esm({
|
|
|
92697
92744
|
});
|
|
92698
92745
|
|
|
92699
92746
|
// apps/desktop/src/cli/commands/daemon.ts
|
|
92700
|
-
import
|
|
92747
|
+
import path66 from "node:path";
|
|
92701
92748
|
function daemonStartFailed3() {
|
|
92702
92749
|
return new NiumaError("DAEMON_START_FAILED", "niuma daemon \u542F\u52A8\u5931\u8D25");
|
|
92703
92750
|
}
|
|
@@ -92890,7 +92937,7 @@ async function runDaemonCommand(args, options = {}) {
|
|
|
92890
92937
|
loggers.rawDebugLogger?.path,
|
|
92891
92938
|
loggers.errorLogger?.path,
|
|
92892
92939
|
// 后台 worker 的 stdout/stderr descriptor 无法安全重开,只按 daemon 所有权保护固定路径。
|
|
92893
|
-
...options.mode === "background" ? [
|
|
92940
|
+
...options.mode === "background" ? [path66.join(runtimeDir, "daemon-worker.log")] : []
|
|
92894
92941
|
].filter((filePath) => typeof filePath === "string")
|
|
92895
92942
|
});
|
|
92896
92943
|
} catch {
|
|
@@ -93380,7 +93427,7 @@ var init_auth2 = __esm({
|
|
|
93380
93427
|
});
|
|
93381
93428
|
|
|
93382
93429
|
// apps/desktop/src/control/routes.ts
|
|
93383
|
-
import
|
|
93430
|
+
import fs41 from "node:fs";
|
|
93384
93431
|
function daemonStoppedOverview() {
|
|
93385
93432
|
return {
|
|
93386
93433
|
daemon: { state: "stopped" },
|
|
@@ -93399,12 +93446,12 @@ function emptyControlPage(page4, pageSize) {
|
|
|
93399
93446
|
}
|
|
93400
93447
|
function isDaemonRuntimeActive(socketPath = daemonSocketPath(), statusPath = daemonStatusPath()) {
|
|
93401
93448
|
try {
|
|
93402
|
-
const socket =
|
|
93403
|
-
const status2 =
|
|
93449
|
+
const socket = fs41.lstatSync(socketPath);
|
|
93450
|
+
const status2 = fs41.lstatSync(statusPath);
|
|
93404
93451
|
if (!socket.isSocket() || !status2.isFile() || status2.isSymbolicLink() || status2.size > 4 * 1024) {
|
|
93405
93452
|
return false;
|
|
93406
93453
|
}
|
|
93407
|
-
const parsed = JSON.parse(
|
|
93454
|
+
const parsed = JSON.parse(fs41.readFileSync(statusPath, "utf8"));
|
|
93408
93455
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed) || parsed.socketPath !== socketPath || !Number.isSafeInteger(parsed.pid) || parsed.pid <= 0) return false;
|
|
93409
93456
|
process.kill(parsed.pid, 0);
|
|
93410
93457
|
return true;
|
|
@@ -94957,8 +95004,8 @@ var init_lifecycle3 = __esm({
|
|
|
94957
95004
|
|
|
94958
95005
|
// apps/desktop/src/control/server.ts
|
|
94959
95006
|
import http4 from "node:http";
|
|
94960
|
-
import
|
|
94961
|
-
import
|
|
95007
|
+
import fs42 from "node:fs";
|
|
95008
|
+
import path67 from "node:path";
|
|
94962
95009
|
import { createRequire as createRequire2 } from "node:module";
|
|
94963
95010
|
function isControlApiPath(pathname) {
|
|
94964
95011
|
const [, api, version2, control] = pathname.split("/", 4);
|
|
@@ -95004,15 +95051,15 @@ function requestHasBody(request2) {
|
|
|
95004
95051
|
return Number(contentLength) !== 0;
|
|
95005
95052
|
}
|
|
95006
95053
|
function resolveExactControlWritePath(requestTarget) {
|
|
95007
|
-
for (const
|
|
95008
|
-
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;
|
|
95009
95056
|
}
|
|
95010
95057
|
return null;
|
|
95011
95058
|
}
|
|
95012
95059
|
function resolveExactControlTraceReadPath(requestTarget) {
|
|
95013
|
-
for (const
|
|
95014
|
-
if (requestTarget ===
|
|
95015
|
-
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;
|
|
95016
95063
|
}
|
|
95017
95064
|
}
|
|
95018
95065
|
return null;
|
|
@@ -95033,9 +95080,9 @@ var init_server5 = __esm({
|
|
|
95033
95080
|
init_lifecycle3();
|
|
95034
95081
|
require2 = createRequire2(import.meta.url);
|
|
95035
95082
|
CONTROL_PAGE_PATHS = ["/", "/connections", "/sessions", "/subscriptions", "/turn-audit", "/logs"];
|
|
95036
|
-
CONTROL_INDEX =
|
|
95037
|
-
BOOTSTRAP_CSS =
|
|
95038
|
-
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"));
|
|
95039
95086
|
STATIC_ASSETS = Object.freeze({
|
|
95040
95087
|
...Object.fromEntries(CONTROL_PAGE_PATHS.map((pathname) => [pathname, {
|
|
95041
95088
|
contentType: "text/html; charset=utf-8",
|
|
@@ -95043,11 +95090,11 @@ var init_server5 = __esm({
|
|
|
95043
95090
|
}])),
|
|
95044
95091
|
"/app.js": {
|
|
95045
95092
|
contentType: "application/javascript; charset=utf-8",
|
|
95046
|
-
body:
|
|
95093
|
+
body: fs42.readFileSync(desktopAssetUrl("control", "app.js"))
|
|
95047
95094
|
},
|
|
95048
95095
|
"/chart.umd.js": {
|
|
95049
95096
|
contentType: "application/javascript; charset=utf-8",
|
|
95050
|
-
body:
|
|
95097
|
+
body: fs42.readFileSync(path67.join(path67.dirname(require2.resolve("chart.js")), "chart.umd.js"))
|
|
95051
95098
|
},
|
|
95052
95099
|
"/bootstrap.min.css": {
|
|
95053
95100
|
contentType: "text/css; charset=utf-8",
|
|
@@ -95263,41 +95310,41 @@ var init_server5 = __esm({
|
|
|
95263
95310
|
|
|
95264
95311
|
// apps/desktop/src/control/state.ts
|
|
95265
95312
|
import { createHash as createHash44, randomUUID as randomUUID60 } from "node:crypto";
|
|
95266
|
-
import
|
|
95267
|
-
import
|
|
95313
|
+
import fs43 from "node:fs";
|
|
95314
|
+
import path68 from "node:path";
|
|
95268
95315
|
function createControlState(input) {
|
|
95269
95316
|
return createControlStateUnlocked(input);
|
|
95270
95317
|
}
|
|
95271
95318
|
function createControlStateUnlocked(input) {
|
|
95272
95319
|
const state = toControlState(input);
|
|
95273
95320
|
const statePath = controlStatePath(input.runtimeDir);
|
|
95274
|
-
const temporaryPath =
|
|
95275
|
-
|
|
95276
|
-
`.${
|
|
95321
|
+
const temporaryPath = path68.join(
|
|
95322
|
+
path68.dirname(statePath),
|
|
95323
|
+
`.${path68.basename(statePath)}.${randomUUID60()}.tmp`
|
|
95277
95324
|
);
|
|
95278
95325
|
let descriptor = null;
|
|
95279
95326
|
let temporaryIdentity = null;
|
|
95280
95327
|
let published = null;
|
|
95281
95328
|
let operationError;
|
|
95282
95329
|
try {
|
|
95283
|
-
descriptor =
|
|
95284
|
-
if (process.platform !== "win32")
|
|
95285
|
-
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 });
|
|
95286
95333
|
assertRegularControlStateDescriptor(stats);
|
|
95287
95334
|
temporaryIdentity = identityFromStats(stats);
|
|
95288
|
-
|
|
95335
|
+
fs43.writeFileSync(descriptor, `${JSON.stringify(state)}
|
|
95289
95336
|
`, "utf8");
|
|
95290
|
-
|
|
95291
|
-
|
|
95337
|
+
fs43.fsyncSync(descriptor);
|
|
95338
|
+
fs43.closeSync(descriptor);
|
|
95292
95339
|
descriptor = null;
|
|
95293
|
-
|
|
95340
|
+
fs43.linkSync(temporaryPath, statePath);
|
|
95294
95341
|
published = persistedControlState(state, statePath, identityFromStats(stats), "canonical");
|
|
95295
95342
|
} catch (error2) {
|
|
95296
95343
|
operationError = error2;
|
|
95297
95344
|
} finally {
|
|
95298
95345
|
if (descriptor !== null) {
|
|
95299
95346
|
try {
|
|
95300
|
-
|
|
95347
|
+
fs43.closeSync(descriptor);
|
|
95301
95348
|
} catch (error2) {
|
|
95302
95349
|
operationError ??= error2;
|
|
95303
95350
|
}
|
|
@@ -95320,7 +95367,7 @@ function createControlStateUnlocked(input) {
|
|
|
95320
95367
|
return published;
|
|
95321
95368
|
}
|
|
95322
95369
|
function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
|
|
95323
|
-
const stateBasename =
|
|
95370
|
+
const stateBasename = path68.basename(controlStatePath(runtimeDir));
|
|
95324
95371
|
const artifactPattern = new RegExp(
|
|
95325
95372
|
`^\\.${escapeRegExp(stateBasename)}(?:\\.coordination\\.lock)?\\.[0-9a-f-]+\\.(?:tmp|snapshot)$`,
|
|
95326
95373
|
"u"
|
|
@@ -95328,19 +95375,19 @@ function cleanupControlStateArtifactsForOwnedListener(runtimeDir) {
|
|
|
95328
95375
|
let removed = 0;
|
|
95329
95376
|
let entries;
|
|
95330
95377
|
try {
|
|
95331
|
-
entries =
|
|
95378
|
+
entries = fs43.readdirSync(runtimeDir);
|
|
95332
95379
|
} catch {
|
|
95333
95380
|
return 0;
|
|
95334
95381
|
}
|
|
95335
95382
|
for (const entry of entries) {
|
|
95336
95383
|
if (entry !== `${stateBasename}.coordination.lock` && !artifactPattern.test(entry)) continue;
|
|
95337
|
-
const artifactPath =
|
|
95384
|
+
const artifactPath = path68.join(runtimeDir, entry);
|
|
95338
95385
|
try {
|
|
95339
|
-
const stats =
|
|
95386
|
+
const stats = fs43.lstatSync(artifactPath, { bigint: true });
|
|
95340
95387
|
if (!stats.isFile() || stats.isSymbolicLink() || process.platform !== "win32" && (stats.mode & 0o777n) !== 0o600n) {
|
|
95341
95388
|
continue;
|
|
95342
95389
|
}
|
|
95343
|
-
|
|
95390
|
+
fs43.unlinkSync(artifactPath);
|
|
95344
95391
|
removed += 1;
|
|
95345
95392
|
} catch {
|
|
95346
95393
|
}
|
|
@@ -95378,7 +95425,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95378
95425
|
if (input.expected.path !== statePath) return false;
|
|
95379
95426
|
const snapshotPath = stateSnapshotPath(statePath);
|
|
95380
95427
|
try {
|
|
95381
|
-
|
|
95428
|
+
fs43.linkSync(statePath, snapshotPath);
|
|
95382
95429
|
} catch (error2) {
|
|
95383
95430
|
if (error2.code === "ENOENT") return false;
|
|
95384
95431
|
return false;
|
|
@@ -95397,7 +95444,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95397
95444
|
return false;
|
|
95398
95445
|
}
|
|
95399
95446
|
if (!canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2)) return false;
|
|
95400
|
-
|
|
95447
|
+
fs43.unlinkSync(statePath);
|
|
95401
95448
|
canonicalRemoved = true;
|
|
95402
95449
|
return true;
|
|
95403
95450
|
} catch {
|
|
@@ -95415,7 +95462,7 @@ function removeControlStateUnlocked(input) {
|
|
|
95415
95462
|
function readControlStateAtPath(filePath, logicalPath) {
|
|
95416
95463
|
const descriptor = openControlStateForRead(filePath);
|
|
95417
95464
|
try {
|
|
95418
|
-
const stats =
|
|
95465
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95419
95466
|
assertRegularControlStateDescriptor(stats);
|
|
95420
95467
|
assertPrivateControlStateMode(stats);
|
|
95421
95468
|
if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
|
|
@@ -95430,14 +95477,14 @@ function readControlStateAtPath(filePath, logicalPath) {
|
|
|
95430
95477
|
throw new CorruptControlStateError(logicalPath, identity6, contents);
|
|
95431
95478
|
}
|
|
95432
95479
|
} finally {
|
|
95433
|
-
|
|
95480
|
+
fs43.closeSync(descriptor);
|
|
95434
95481
|
}
|
|
95435
95482
|
}
|
|
95436
95483
|
function readBoundedControlState(descriptor) {
|
|
95437
95484
|
const buffer = Buffer.alloc(CONTROL_STATE_MAX_BYTES + 1);
|
|
95438
95485
|
let bytesRead = 0;
|
|
95439
95486
|
while (bytesRead < buffer.length) {
|
|
95440
|
-
const count =
|
|
95487
|
+
const count = fs43.readSync(
|
|
95441
95488
|
descriptor,
|
|
95442
95489
|
buffer,
|
|
95443
95490
|
bytesRead,
|
|
@@ -95456,12 +95503,12 @@ function removeCorruptControlState(error2) {
|
|
|
95456
95503
|
const snapshotPath = stateSnapshotPath(error2.statePath);
|
|
95457
95504
|
let canonicalRemoved = false;
|
|
95458
95505
|
try {
|
|
95459
|
-
|
|
95506
|
+
fs43.linkSync(error2.statePath, snapshotPath);
|
|
95460
95507
|
} catch {
|
|
95461
95508
|
return false;
|
|
95462
95509
|
}
|
|
95463
95510
|
try {
|
|
95464
|
-
const snapshotStats =
|
|
95511
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95465
95512
|
if (!snapshotStats.isFile()) return false;
|
|
95466
95513
|
const snapshotIdentity = identityFromStats(snapshotStats);
|
|
95467
95514
|
if (hasUsableInode(error2.fileIdentity) && hasUsableInode(snapshotIdentity) && !sameIdentity(error2.fileIdentity, snapshotIdentity)) {
|
|
@@ -95472,7 +95519,7 @@ function removeCorruptControlState(error2) {
|
|
|
95472
95519
|
if (fingerprint(snapshot2) !== error2.fingerprint) return false;
|
|
95473
95520
|
}
|
|
95474
95521
|
if (!canonicalMatchesSnapshotByIdentity(error2.statePath, snapshotPath)) return false;
|
|
95475
|
-
|
|
95522
|
+
fs43.unlinkSync(error2.statePath);
|
|
95476
95523
|
canonicalRemoved = true;
|
|
95477
95524
|
return true;
|
|
95478
95525
|
} catch {
|
|
@@ -95488,7 +95535,7 @@ function removeCorruptControlState(error2) {
|
|
|
95488
95535
|
function readRawControlState(filePath) {
|
|
95489
95536
|
const descriptor = openControlStateForRead(filePath);
|
|
95490
95537
|
try {
|
|
95491
|
-
const stats =
|
|
95538
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95492
95539
|
assertRegularControlStateDescriptor(stats);
|
|
95493
95540
|
assertPrivateControlStateMode(stats);
|
|
95494
95541
|
if (stats.size > BigInt(CONTROL_STATE_MAX_BYTES)) {
|
|
@@ -95496,13 +95543,13 @@ function readRawControlState(filePath) {
|
|
|
95496
95543
|
}
|
|
95497
95544
|
return readBoundedControlState(descriptor);
|
|
95498
95545
|
} finally {
|
|
95499
|
-
|
|
95546
|
+
fs43.closeSync(descriptor);
|
|
95500
95547
|
}
|
|
95501
95548
|
}
|
|
95502
95549
|
function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
|
|
95503
95550
|
if (!canonicalMatchesSnapshotByIdentity(statePath, snapshotPath)) return false;
|
|
95504
|
-
const canonicalStats =
|
|
95505
|
-
const snapshotStats =
|
|
95551
|
+
const canonicalStats = fs43.lstatSync(statePath, { bigint: true });
|
|
95552
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95506
95553
|
if (hasUsableInode(identityFromStats(canonicalStats)) && hasUsableInode(identityFromStats(snapshotStats))) {
|
|
95507
95554
|
return true;
|
|
95508
95555
|
}
|
|
@@ -95510,8 +95557,8 @@ function canonicalMatchesSnapshot(statePath, snapshotPath, snapshot2) {
|
|
|
95510
95557
|
return current2.pid === snapshot2.pid && current2.ownershipSecret === snapshot2.ownershipSecret;
|
|
95511
95558
|
}
|
|
95512
95559
|
function canonicalMatchesSnapshotByIdentity(statePath, snapshotPath) {
|
|
95513
|
-
const canonicalStats =
|
|
95514
|
-
const snapshotStats =
|
|
95560
|
+
const canonicalStats = fs43.lstatSync(statePath, { bigint: true });
|
|
95561
|
+
const snapshotStats = fs43.lstatSync(snapshotPath, { bigint: true });
|
|
95515
95562
|
if (!canonicalStats.isFile() || !snapshotStats.isFile()) return false;
|
|
95516
95563
|
const canonicalIdentity = identityFromStats(canonicalStats);
|
|
95517
95564
|
const snapshotIdentity = identityFromStats(snapshotStats);
|
|
@@ -95542,9 +95589,9 @@ function sameIdentity(left, right) {
|
|
|
95542
95589
|
return left.device === right.device && left.inode === right.inode;
|
|
95543
95590
|
}
|
|
95544
95591
|
function stateSnapshotPath(statePath) {
|
|
95545
|
-
return
|
|
95546
|
-
|
|
95547
|
-
`.${
|
|
95592
|
+
return path68.join(
|
|
95593
|
+
path68.dirname(statePath),
|
|
95594
|
+
`.${path68.basename(statePath)}.${randomUUID60()}.snapshot`
|
|
95548
95595
|
);
|
|
95549
95596
|
}
|
|
95550
95597
|
function fingerprint(contents) {
|
|
@@ -95555,7 +95602,7 @@ function escapeRegExp(value) {
|
|
|
95555
95602
|
}
|
|
95556
95603
|
function unlinkControlStateTemporary(temporaryPath) {
|
|
95557
95604
|
try {
|
|
95558
|
-
|
|
95605
|
+
fs43.unlinkSync(temporaryPath);
|
|
95559
95606
|
return void 0;
|
|
95560
95607
|
} catch (error2) {
|
|
95561
95608
|
return error2.code === "ENOENT" ? void 0 : error2;
|
|
@@ -95567,28 +95614,28 @@ function eraseControlStateTemporary(temporaryPath, expectedIdentity) {
|
|
|
95567
95614
|
try {
|
|
95568
95615
|
let beforeIdentity = null;
|
|
95569
95616
|
if (process.platform === "win32") {
|
|
95570
|
-
const before =
|
|
95617
|
+
const before = fs43.lstatSync(temporaryPath, { bigint: true });
|
|
95571
95618
|
beforeIdentity = identityFromStats(before);
|
|
95572
95619
|
if (!before.isFile() || before.isSymbolicLink() || !hasUsableInode(beforeIdentity) || !sameIdentity(beforeIdentity, expectedIdentity)) return;
|
|
95573
95620
|
}
|
|
95574
|
-
const noFollow = process.platform === "win32" ? 0 :
|
|
95621
|
+
const noFollow = process.platform === "win32" ? 0 : fs43.constants.O_NOFOLLOW;
|
|
95575
95622
|
if (process.platform !== "win32" && (!noFollow || typeof noFollow !== "number")) return;
|
|
95576
|
-
descriptor =
|
|
95577
|
-
const stats =
|
|
95623
|
+
descriptor = fs43.openSync(temporaryPath, fs43.constants.O_RDWR | noFollow);
|
|
95624
|
+
const stats = fs43.fstatSync(descriptor, { bigint: true });
|
|
95578
95625
|
const identity6 = identityFromStats(stats);
|
|
95579
95626
|
if (!stats.isFile() || !hasUsableInode(identity6) || !sameIdentity(identity6, expectedIdentity)) return;
|
|
95580
95627
|
if (process.platform === "win32") {
|
|
95581
|
-
const after =
|
|
95628
|
+
const after = fs43.lstatSync(temporaryPath, { bigint: true });
|
|
95582
95629
|
const afterIdentity = identityFromStats(after);
|
|
95583
95630
|
if (!after.isFile() || after.isSymbolicLink() || !beforeIdentity || !hasUsableInode(afterIdentity) || !sameIdentity(beforeIdentity, identity6) || !sameIdentity(identity6, afterIdentity)) return;
|
|
95584
95631
|
}
|
|
95585
|
-
|
|
95586
|
-
|
|
95632
|
+
fs43.ftruncateSync(descriptor, 0);
|
|
95633
|
+
fs43.fsyncSync(descriptor);
|
|
95587
95634
|
} catch {
|
|
95588
95635
|
} finally {
|
|
95589
95636
|
if (descriptor !== null) {
|
|
95590
95637
|
try {
|
|
95591
|
-
|
|
95638
|
+
fs43.closeSync(descriptor);
|
|
95592
95639
|
} catch {
|
|
95593
95640
|
}
|
|
95594
95641
|
}
|
|
@@ -95635,16 +95682,16 @@ function parseControlState(value) {
|
|
|
95635
95682
|
}
|
|
95636
95683
|
function openControlStateForRead(statePath) {
|
|
95637
95684
|
if (process.platform === "win32") return openControlStateForReadOnWindows(statePath);
|
|
95638
|
-
const noFollow =
|
|
95685
|
+
const noFollow = fs43.constants.O_NOFOLLOW;
|
|
95639
95686
|
if (typeof noFollow !== "number" || noFollow === 0) {
|
|
95640
95687
|
throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NOFOLLOW \u5B89\u5168\u8BFB\u53D6");
|
|
95641
95688
|
}
|
|
95642
|
-
const nonBlock =
|
|
95689
|
+
const nonBlock = fs43.constants.O_NONBLOCK;
|
|
95643
95690
|
if (typeof nonBlock !== "number" || nonBlock === 0) {
|
|
95644
95691
|
throw new Error("\u5F53\u524D\u5E73\u53F0\u4E0D\u652F\u6301 Control \u72B6\u6001\u6587\u4EF6\u7684 O_NONBLOCK \u5B89\u5168\u8BFB\u53D6");
|
|
95645
95692
|
}
|
|
95646
95693
|
try {
|
|
95647
|
-
return
|
|
95694
|
+
return fs43.openSync(statePath, fs43.constants.O_RDONLY | noFollow | nonBlock);
|
|
95648
95695
|
} catch (error2) {
|
|
95649
95696
|
if (error2.code === "ELOOP") {
|
|
95650
95697
|
throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
|
|
@@ -95653,14 +95700,14 @@ function openControlStateForRead(statePath) {
|
|
|
95653
95700
|
}
|
|
95654
95701
|
}
|
|
95655
95702
|
function openControlStateForReadOnWindows(statePath) {
|
|
95656
|
-
const before =
|
|
95703
|
+
const before = fs43.lstatSync(statePath, { bigint: true });
|
|
95657
95704
|
if (!before.isFile() || before.isSymbolicLink()) {
|
|
95658
95705
|
throw new Error("Control \u72B6\u6001\u5FC5\u987B\u662F\u79C1\u6709\u666E\u901A\u6587\u4EF6\uFF0C\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5");
|
|
95659
95706
|
}
|
|
95660
|
-
const descriptor =
|
|
95707
|
+
const descriptor = fs43.openSync(statePath, fs43.constants.O_RDONLY);
|
|
95661
95708
|
try {
|
|
95662
|
-
const opened =
|
|
95663
|
-
const after =
|
|
95709
|
+
const opened = fs43.fstatSync(descriptor, { bigint: true });
|
|
95710
|
+
const after = fs43.lstatSync(statePath, { bigint: true });
|
|
95664
95711
|
const beforeIdentity = identityFromStats(before);
|
|
95665
95712
|
const openedIdentity = identityFromStats(opened);
|
|
95666
95713
|
const afterIdentity = identityFromStats(after);
|
|
@@ -95669,7 +95716,7 @@ function openControlStateForReadOnWindows(statePath) {
|
|
|
95669
95716
|
}
|
|
95670
95717
|
return descriptor;
|
|
95671
95718
|
} catch (error2) {
|
|
95672
|
-
|
|
95719
|
+
fs43.closeSync(descriptor);
|
|
95673
95720
|
throw error2;
|
|
95674
95721
|
}
|
|
95675
95722
|
}
|
|
@@ -96111,9 +96158,9 @@ var init_direct2 = __esm({
|
|
|
96111
96158
|
});
|
|
96112
96159
|
|
|
96113
96160
|
// apps/desktop/src/cli/commands/events.ts
|
|
96114
|
-
import
|
|
96161
|
+
import path69 from "node:path";
|
|
96115
96162
|
function normalizedProjectRoot(value) {
|
|
96116
|
-
return typeof value === "string" && value.length > 0 ?
|
|
96163
|
+
return typeof value === "string" && value.length > 0 ? path69.resolve(value) : null;
|
|
96117
96164
|
}
|
|
96118
96165
|
function toOutputEvent(event) {
|
|
96119
96166
|
if (event.ok === true && typeof event.schemaVersion === "number") {
|
|
@@ -96497,7 +96544,7 @@ var init_state2 = __esm({
|
|
|
96497
96544
|
});
|
|
96498
96545
|
|
|
96499
96546
|
// apps/desktop/src/cli/commands/threads.ts
|
|
96500
|
-
import
|
|
96547
|
+
import path70 from "node:path";
|
|
96501
96548
|
function readPositiveInteger2(value, name2, fallback) {
|
|
96502
96549
|
if (value === void 0) {
|
|
96503
96550
|
return fallback;
|
|
@@ -96515,7 +96562,7 @@ async function runThreadsCommand(args, options = {}) {
|
|
|
96515
96562
|
const pageSize = readPositiveInteger2(args.flags.pageSize ?? args.flags.limit, "--page-size", 100);
|
|
96516
96563
|
const maxPages = readPositiveInteger2(args.flags.maxPages, "--max-pages", 20);
|
|
96517
96564
|
const cursor = typeof args.flags.cursor === "string" && args.flags.cursor.length > 0 ? args.flags.cursor : null;
|
|
96518
|
-
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;
|
|
96519
96566
|
const daemon = options.daemonClient ?? new DaemonClient(options.socketPath);
|
|
96520
96567
|
const result = await daemon.request("threads/list", {
|
|
96521
96568
|
pageSize,
|