niuma-codex 0.0.1-beta.28 → 0.0.1-beta.29
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/assets/control/app.js +8 -0
- package/dist/assets/control/index.html +4 -0
- package/dist/assets/control/thread-loads.js +175 -0
- package/dist/cli.js +1943 -1421
- package/dist/managed-tauri.js +593 -129
- package/dist/managed.js +564 -123
- package/package.json +1 -1
- package/resources/lite-release.json +7 -7
- package/resources/niuma-daemon-arm64.tgz +0 -0
- package/resources/niuma-lite-arm64.dmg +0 -0
package/dist/managed.js
CHANGED
|
@@ -8485,9 +8485,42 @@ function parseAttachmentTaskV2StatusQuery(value) {
|
|
|
8485
8485
|
return { ...parseAttachmentTaskStatusQuery(normalize(value, true)), version: 2 };
|
|
8486
8486
|
}
|
|
8487
8487
|
|
|
8488
|
+
// packages/protocol/src/thread-load-trace.ts
|
|
8489
|
+
var CLIENT_LOAD_PHASES = ["selected", "restored", "request_started", "snapshot_received", "history_ready", "content_presented"];
|
|
8490
|
+
function object8(value, required, optional = []) {
|
|
8491
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) throw new TypeError("invalid_load_report");
|
|
8492
|
+
const descriptors = Object.getOwnPropertyDescriptors(value);
|
|
8493
|
+
if (Reflect.ownKeys(value).some((key) => typeof key !== "string" || ![...required, ...optional].includes(key)) || required.some((key) => !Object.hasOwn(descriptors, key)) || Object.values(descriptors).some((d) => !d.enumerable || !("value" in d))) throw new TypeError("invalid_load_report");
|
|
8494
|
+
return value;
|
|
8495
|
+
}
|
|
8496
|
+
function timing(value) {
|
|
8497
|
+
if (!Number.isInteger(value.elapsed_ms) || value.elapsed_ms < 0 || value.elapsed_ms > 9e5 || value.occurred_at_ms !== void 0 && (!Number.isInteger(value.occurred_at_ms) || value.occurred_at_ms < 1 || value.occurred_at_ms > 864e13)) throw new TypeError("invalid_load_timing");
|
|
8498
|
+
}
|
|
8499
|
+
function parseThreadLoadReportV2(value) {
|
|
8500
|
+
const v = object8(value, ["version", "thread_id", "load_id", "client_class", "samples"], ["terminal"]);
|
|
8501
|
+
if (v.version !== 2 || typeof v.thread_id !== "string" || !v.thread_id.length || v.thread_id.length > 256 || typeof v.load_id !== "string" || !/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(v.load_id) || !["web", "ios", "other"].includes(v.client_class) || !Array.isArray(v.samples) || v.samples.length > 6 || !v.samples.length && v.terminal === void 0) throw new TypeError("invalid_load_report");
|
|
8502
|
+
for (const sample of v.samples) {
|
|
8503
|
+
const s = object8(sample, ["phase", "elapsed_ms"], ["occurred_at_ms"]);
|
|
8504
|
+
timing(s);
|
|
8505
|
+
if (!CLIENT_LOAD_PHASES.includes(s.phase)) throw new TypeError("invalid_load_phase");
|
|
8506
|
+
}
|
|
8507
|
+
if (v.terminal !== void 0) {
|
|
8508
|
+
const t = object8(v.terminal, ["kind", "phase", "reason", "elapsed_ms"], ["occurred_at_ms"]);
|
|
8509
|
+
timing(t);
|
|
8510
|
+
const reasons = { failed: ["open_rejected", "history_failed"], cancelled: ["left_view", "user_cancelled"], superseded: ["stream_replaced"] };
|
|
8511
|
+
if (!["request_started", "snapshot_received", "history_ready"].includes(t.phase) || !Object.hasOwn(reasons, t.kind) || !reasons[t.kind]?.includes(t.reason) || v.samples.some((s) => s.phase === "content_presented")) throw new TypeError("invalid_load_terminal");
|
|
8512
|
+
}
|
|
8513
|
+
return v;
|
|
8514
|
+
}
|
|
8515
|
+
function reduceThreadLoadOutcome(current2, event) {
|
|
8516
|
+
if (event === "closed" || event === "expired") return current2.status === "loading" ? { ...current2, status: "incomplete" } : current2;
|
|
8517
|
+
if (current2.status === "loading" || current2.status === "incomplete" && ["cancelled", "superseded"].includes(event)) return { ...current2, status: event };
|
|
8518
|
+
return current2.status === event ? current2 : { ...current2, conflict: true };
|
|
8519
|
+
}
|
|
8520
|
+
|
|
8488
8521
|
// apps/desktop/src/release-version.ts
|
|
8489
8522
|
function desktopReleaseVersion() {
|
|
8490
|
-
return false ? null : "0.0.1-beta.
|
|
8523
|
+
return false ? null : "0.0.1-beta.29";
|
|
8491
8524
|
}
|
|
8492
8525
|
var sourcePresenceVersion = (() => {
|
|
8493
8526
|
if (true) return null;
|
|
@@ -11986,6 +12019,59 @@ function discoverDirectGatewayOrigins(host, port, interfaces = networkInterfaces
|
|
|
11986
12019
|
// apps/desktop/src/daemon/launcher.ts
|
|
11987
12020
|
var BACKGROUND_DAEMON_STARTUP_TIMEOUT_MS = Math.max(6e4, desktopPlatform().daemon.startupTimeoutMs);
|
|
11988
12021
|
|
|
12022
|
+
// apps/desktop/src/daemon/runtime/ipc-thread-discovery.ts
|
|
12023
|
+
var RuntimeIpcThreadDiscovery = class {
|
|
12024
|
+
constructor(ports) {
|
|
12025
|
+
this.ports = ports;
|
|
12026
|
+
}
|
|
12027
|
+
ports;
|
|
12028
|
+
pending = /* @__PURE__ */ new Map();
|
|
12029
|
+
discover(id5) {
|
|
12030
|
+
const started2 = Date.now();
|
|
12031
|
+
const report = (phase) => {
|
|
12032
|
+
try {
|
|
12033
|
+
this.ports.diagnostic(id5, phase, Date.now() - started2);
|
|
12034
|
+
} catch {
|
|
12035
|
+
}
|
|
12036
|
+
};
|
|
12037
|
+
if (!this.ports.eligible(id5)) {
|
|
12038
|
+
report("ignored");
|
|
12039
|
+
return;
|
|
12040
|
+
}
|
|
12041
|
+
if (this.pending.has(id5)) {
|
|
12042
|
+
report("deduplicated");
|
|
12043
|
+
return;
|
|
12044
|
+
}
|
|
12045
|
+
if (this.pending.size >= 66) {
|
|
12046
|
+
report("capacity");
|
|
12047
|
+
return;
|
|
12048
|
+
}
|
|
12049
|
+
const current2 = this.ports.capture();
|
|
12050
|
+
report("received");
|
|
12051
|
+
const task = this.run(id5, current2, report).catch(() => report("failed")).finally(() => {
|
|
12052
|
+
if (this.pending.get(id5) === task) this.pending.delete(id5);
|
|
12053
|
+
});
|
|
12054
|
+
this.pending.set(id5, task);
|
|
12055
|
+
}
|
|
12056
|
+
async run(id5, current2, report) {
|
|
12057
|
+
const result = await this.ports.read(id5);
|
|
12058
|
+
report("read_completed");
|
|
12059
|
+
const valid = () => current2() && this.ports.eligible(id5) && result.kind === "ordinary" && result.summary?.id === id5 && !!result.token && this.ports.current(result.token);
|
|
12060
|
+
if (!valid()) {
|
|
12061
|
+
report("rejected");
|
|
12062
|
+
return;
|
|
12063
|
+
}
|
|
12064
|
+
await this.ports.enqueue(() => {
|
|
12065
|
+
if (!valid()) {
|
|
12066
|
+
report("stale");
|
|
12067
|
+
return;
|
|
12068
|
+
}
|
|
12069
|
+
this.ports.commit(result.summary);
|
|
12070
|
+
report("published");
|
|
12071
|
+
});
|
|
12072
|
+
}
|
|
12073
|
+
};
|
|
12074
|
+
|
|
11989
12075
|
// apps/desktop/src/daemon/async-question-response.ts
|
|
11990
12076
|
import { createHash } from "node:crypto";
|
|
11991
12077
|
function submissionId(input) {
|
|
@@ -14763,11 +14849,11 @@ var RuntimeActivityPublication = class {
|
|
|
14763
14849
|
if (!thread4) {
|
|
14764
14850
|
return null;
|
|
14765
14851
|
}
|
|
14766
|
-
const
|
|
14767
|
-
const timingFields =
|
|
14768
|
-
turnStartedAt:
|
|
14769
|
-
...
|
|
14770
|
-
...
|
|
14852
|
+
const timing2 = this.ports.turnTiming(signal.threadId, signal.turnId);
|
|
14853
|
+
const timingFields = timing2 ? {
|
|
14854
|
+
turnStartedAt: timing2.startedAt,
|
|
14855
|
+
...timing2.endedAt !== void 0 ? { turnEndedAt: timing2.endedAt } : {},
|
|
14856
|
+
...timing2.outcome !== void 0 ? { turnOutcome: timing2.outcome } : {}
|
|
14771
14857
|
} : {};
|
|
14772
14858
|
if (signal.type === "turn_aborted") {
|
|
14773
14859
|
return {
|
|
@@ -20297,7 +20383,7 @@ function fail14(reason) {
|
|
|
20297
20383
|
var clone = (value) => structuredClone(value);
|
|
20298
20384
|
var diskEntry = (entry) => ({ ...entry, nativeToken: entry.nativeToken !== null });
|
|
20299
20385
|
var byteSize = (value) => Buffer.byteLength(JSON.stringify(value));
|
|
20300
|
-
function
|
|
20386
|
+
function object9(value, keys3, optional = []) {
|
|
20301
20387
|
if (!value || typeof value !== "object" || Array.isArray(value)) return fail14("invalid");
|
|
20302
20388
|
const record25 = value;
|
|
20303
20389
|
if (Object.keys(record25).some((key) => !keys3.includes(key) && !optional.includes(key)) || !keys3.every((key) => Object.hasOwn(record25, key))) return fail14("invalid");
|
|
@@ -20331,7 +20417,7 @@ function parseReceipt(value, clientMessageId) {
|
|
|
20331
20417
|
return receipt;
|
|
20332
20418
|
}
|
|
20333
20419
|
function parsePost(value, clientMessageId) {
|
|
20334
|
-
const record25 =
|
|
20420
|
+
const record25 = object9(value, ["httpStatus", "code", "message", "data"]);
|
|
20335
20421
|
if (![200, 400, 404, 500].includes(record25.httpStatus) || !Number.isInteger(record25.code) || record25.code !== 0 && (record25.code < 1e5 || record25.code > 999999) || typeof record25.message !== "string" || record25.message.length === 0 || Buffer.byteLength(record25.message) > MAX_MESSAGE_BYTES || byteSize(record25.message) > MAX_MESSAGE_BYTES + 2) fail14("invalid");
|
|
20336
20422
|
if (record25.code === 0) {
|
|
20337
20423
|
if (record25.httpStatus !== 200) fail14("invalid");
|
|
@@ -20344,10 +20430,10 @@ function parsePost(value, clientMessageId) {
|
|
|
20344
20430
|
} else if (record25.data !== null) {
|
|
20345
20431
|
const data = record25.data;
|
|
20346
20432
|
if (data.state === "unknown") {
|
|
20347
|
-
|
|
20433
|
+
object9(data, ["client_message_id", "state"]);
|
|
20348
20434
|
if (data.client_message_id !== clientMessageId) fail14("invalid");
|
|
20349
20435
|
} else {
|
|
20350
|
-
|
|
20436
|
+
object9(data, ["dispatch_state"]);
|
|
20351
20437
|
if (data.dispatch_state !== "not_dispatched") fail14("invalid");
|
|
20352
20438
|
}
|
|
20353
20439
|
}
|
|
@@ -20380,13 +20466,13 @@ function parseDocument(raw, maxEntries) {
|
|
|
20380
20466
|
} catch {
|
|
20381
20467
|
return fail14("invalid");
|
|
20382
20468
|
}
|
|
20383
|
-
const document =
|
|
20469
|
+
const document = object9(value, ["version", "entries"]);
|
|
20384
20470
|
if (document.version !== 1 || !Array.isArray(document.entries)) fail14("invalid");
|
|
20385
20471
|
if (document.entries.length > maxEntries) fail14("capacity");
|
|
20386
20472
|
const entries = /* @__PURE__ */ new Map();
|
|
20387
20473
|
const nativeItems = /* @__PURE__ */ new Set();
|
|
20388
20474
|
for (const value2 of document.entries) {
|
|
20389
|
-
const record25 =
|
|
20475
|
+
const record25 = object9(value2, ["principal", "threadId", "clientMessageId", "fingerprint", "nativeToken", "receipt", "firstResult", "createdAt", "updatedAt"], ["questionId"]);
|
|
20390
20476
|
if (typeof record25.nativeToken !== "boolean" || !Number.isSafeInteger(record25.createdAt) || record25.createdAt < 0 || !Number.isSafeInteger(record25.updatedAt) || record25.updatedAt < 0) fail14("invalid");
|
|
20391
20477
|
const entry = { ...record25, nativeToken: record25.nativeToken ? record25.clientMessageId : null };
|
|
20392
20478
|
validateReservation(entry);
|
|
@@ -20478,7 +20564,7 @@ async function openMessageSubmissionStore(options) {
|
|
|
20478
20564
|
reserve(input) {
|
|
20479
20565
|
const captured = clone(input);
|
|
20480
20566
|
return enqueue(async () => {
|
|
20481
|
-
|
|
20567
|
+
object9(captured, ["principal", "threadId", "clientMessageId", "fingerprint", "nativeToken"], ["questionId"]);
|
|
20482
20568
|
validateReservation(captured);
|
|
20483
20569
|
const existing = entries.get(captured.clientMessageId);
|
|
20484
20570
|
if (existing) {
|
|
@@ -23728,8 +23814,8 @@ var AppServerTransport = class {
|
|
|
23728
23814
|
/** 慢响应只保留每分钟首条及抑制数;超时和协议失败仍逐次保留。 */
|
|
23729
23815
|
auditSlowResponse(id5, pending, bytes3, failed) {
|
|
23730
23816
|
if (!Number.isFinite(pending.startedAtMs)) return;
|
|
23731
|
-
const
|
|
23732
|
-
if (
|
|
23817
|
+
const timing2 = this.requestTiming(pending), now = performance.now();
|
|
23818
|
+
if (timing2.elapsedMs < 5e3) return;
|
|
23733
23819
|
if (now - this.lastSlowAuditAtMs < 6e4) {
|
|
23734
23820
|
this.suppressedSlowAudits++;
|
|
23735
23821
|
return;
|
|
@@ -23740,7 +23826,7 @@ var AppServerTransport = class {
|
|
|
23740
23826
|
...typeof id5 === "number" ? { requestId: id5 } : {},
|
|
23741
23827
|
...isSafeErrorAuditOperation(pending.method) ? { method: pending.method } : {},
|
|
23742
23828
|
bytes: bytes3,
|
|
23743
|
-
requestTiming:
|
|
23829
|
+
requestTiming: timing2,
|
|
23744
23830
|
responseDisposition: failed ? "error" : "success",
|
|
23745
23831
|
suppressedCount: this.suppressedSlowAudits
|
|
23746
23832
|
});
|
|
@@ -28051,7 +28137,7 @@ import { randomBytes as randomBytes3 } from "node:crypto";
|
|
|
28051
28137
|
import { isDeepStrictEqual as isDeepStrictEqual2 } from "node:util";
|
|
28052
28138
|
function logicalDescriptor(descriptor) {
|
|
28053
28139
|
if (descriptor.pathname !== "/api/v1/thread/open") return descriptor;
|
|
28054
|
-
const { load_id: _loadId, range_resume_token: _rangeToken, ...query2 } = descriptor.query;
|
|
28140
|
+
const { load_id: _loadId, load_trace: _loadTrace, range_resume_token: _rangeToken, ...query2 } = descriptor.query;
|
|
28055
28141
|
return { pathname: descriptor.pathname, query: query2 };
|
|
28056
28142
|
}
|
|
28057
28143
|
function fail15(code, message) {
|
|
@@ -30258,8 +30344,7 @@ function invalidPushServerOrigin() {
|
|
|
30258
30344
|
function resolvePushServerOrigin(environment) {
|
|
30259
30345
|
const value = environment.NIUMA_PUSH_SERVER_ORIGIN;
|
|
30260
30346
|
if (value === void 0 || isBlankConfigValue(value)) {
|
|
30261
|
-
|
|
30262
|
-
return release2 ? DEFAULT_PUSH_PUBLIC_URL : resolveLocalServerOrigin(environment);
|
|
30347
|
+
return DEFAULT_PUSH_PUBLIC_URL;
|
|
30263
30348
|
}
|
|
30264
30349
|
if (URL_CONTROL_OR_SPACE_PATTERN.test(value)) {
|
|
30265
30350
|
throw invalidPushServerOrigin();
|
|
@@ -30362,6 +30447,20 @@ var ThreadLoadReportSchema = z8.object({
|
|
|
30362
30447
|
load_id: z8.string().uuid(),
|
|
30363
30448
|
samples: z8.array(LoadSampleSchema).min(1).max(6)
|
|
30364
30449
|
}).strict();
|
|
30450
|
+
var ThreadLoadReportV2Schema = z8.object({
|
|
30451
|
+
version: z8.literal(2),
|
|
30452
|
+
thread_id: z8.string().min(1).max(256),
|
|
30453
|
+
load_id: z8.string().uuid(),
|
|
30454
|
+
client_class: z8.enum(["web", "ios", "other"]),
|
|
30455
|
+
samples: z8.array(LoadSampleSchema).max(6),
|
|
30456
|
+
terminal: z8.object({ kind: z8.enum(["failed", "cancelled", "superseded"]), phase: z8.enum(["request_started", "snapshot_received", "history_ready"]), reason: z8.enum(["open_rejected", "history_failed", "left_view", "user_cancelled", "stream_replaced"]), elapsed_ms: z8.number().int().min(0).max(9e5), occurred_at_ms: occurredAtSchema }).strict().optional()
|
|
30457
|
+
}).strict().superRefine((value, context) => {
|
|
30458
|
+
try {
|
|
30459
|
+
parseThreadLoadReportV2(value);
|
|
30460
|
+
} catch {
|
|
30461
|
+
context.addIssue({ code: "custom", message: "\u52A0\u8F7D\u91C7\u6837\u7EC4\u5408\u65E0\u6548" });
|
|
30462
|
+
}
|
|
30463
|
+
});
|
|
30365
30464
|
var LoadingTraceSchema = z8.object({
|
|
30366
30465
|
load_id: z8.string().uuid(),
|
|
30367
30466
|
lease_id: z8.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u),
|
|
@@ -30371,27 +30470,128 @@ var LoadingTraceSchema = z8.object({
|
|
|
30371
30470
|
occurred_at_ms: occurredAtSchema
|
|
30372
30471
|
}).strict().refine((value) => value.clock === "browser" ? ClientLoadPhaseSchema.safeParse(value.phase).success : ["open_received", "identity_ready", "lease_acquired", "shell_sent", "history_sent", "stream_closed"].includes(value.phase));
|
|
30373
30472
|
var ThreadLoadReports = class {
|
|
30374
|
-
constructor(now = Date.now) {
|
|
30473
|
+
constructor(now = Date.now, audit = () => void 0) {
|
|
30375
30474
|
this.now = now;
|
|
30475
|
+
this.audit = audit;
|
|
30376
30476
|
}
|
|
30377
30477
|
now;
|
|
30478
|
+
audit;
|
|
30378
30479
|
entries = /* @__PURE__ */ new Map();
|
|
30379
|
-
|
|
30480
|
+
used = /* @__PURE__ */ new Set();
|
|
30481
|
+
clear() {
|
|
30482
|
+
this.entries.clear();
|
|
30483
|
+
}
|
|
30484
|
+
begin(input) {
|
|
30485
|
+
for (const [key, value] of this.entries) if (value.expires < this.now()) this.entries.delete(key);
|
|
30486
|
+
if (!z8.string().uuid().safeParse(input.loadId).success || this.entries.size >= 256 || this.used.size >= 1e4 || this.used.has(input.loadId)) return null;
|
|
30487
|
+
const id5 = input.loadId;
|
|
30488
|
+
const writer = this.audit();
|
|
30489
|
+
if (writer?.reserveLoadId && !writer.reserveLoadId(id5)) {
|
|
30490
|
+
this.used.add(id5);
|
|
30491
|
+
return null;
|
|
30492
|
+
}
|
|
30493
|
+
this.used.add(id5);
|
|
30494
|
+
const epoch = writer?.loadGeneration?.();
|
|
30495
|
+
let outcome = { status: "loading", conflict: false };
|
|
30496
|
+
let lease, trace;
|
|
30497
|
+
const entry = { threadId: input.threadId, owner: input.owner, expires: input.nowMs + 9e5, seen: /* @__PURE__ */ new Set(), record: () => {
|
|
30498
|
+
}, valid: () => this.entries.get(id5) === entry && writer?.loadGeneration?.() === epoch && this.now() <= entry.expires };
|
|
30499
|
+
const write = (record25) => {
|
|
30500
|
+
if (!entry.valid?.()) return;
|
|
30501
|
+
try {
|
|
30502
|
+
writer?.recordLoad?.({ ...record25, load_id: id5, thread_id: input.threadId, occurred_at_ms: this.now(), ...lease ? { lease_id: lease } : {}, ...trace ? { trace_id: trace } : {} });
|
|
30503
|
+
} catch {
|
|
30504
|
+
}
|
|
30505
|
+
};
|
|
30506
|
+
const end = (event) => {
|
|
30507
|
+
outcome = reduceThreadLoadOutcome(outcome, event);
|
|
30508
|
+
entry.expires = Math.min(entry.expires, this.now() + 3e4);
|
|
30509
|
+
};
|
|
30510
|
+
const elapsed = () => Math.max(0, Math.min(9e5, this.now() - input.nowMs));
|
|
30511
|
+
const handle = {
|
|
30512
|
+
markDaemon: (phase, elapsedMs, occurredAtMs = this.now()) => {
|
|
30513
|
+
if (!entry.valid?.() || entry.seen.has("daemon:" + phase)) return;
|
|
30514
|
+
entry.seen.add("daemon:" + phase);
|
|
30515
|
+
write({ record_type: "load_sample", clock: "daemon", phase, elapsed_ms: elapsedMs, event_at_ms: occurredAtMs });
|
|
30516
|
+
},
|
|
30517
|
+
attachLease: (leaseId, traceId) => {
|
|
30518
|
+
lease = leaseId;
|
|
30519
|
+
trace = traceId;
|
|
30520
|
+
},
|
|
30521
|
+
// 每种确定终态只记一次;保留不同证据供 reducer 标示冲突,不延长授权期限。
|
|
30522
|
+
finish: (kind, evidence = {}) => {
|
|
30523
|
+
if (!entry.valid?.() || entry.seen.has("terminal:" + kind)) return;
|
|
30524
|
+
entry.seen.add("terminal:" + kind);
|
|
30525
|
+
write({ record_type: "load_terminal", clock: "daemon", phase: kind, elapsed_ms: elapsed(), ...evidence });
|
|
30526
|
+
end(kind);
|
|
30527
|
+
},
|
|
30528
|
+
close: () => {
|
|
30529
|
+
if (!entry.valid?.() || entry.seen.has("closed")) return;
|
|
30530
|
+
entry.seen.add("closed");
|
|
30531
|
+
write({ record_type: "load_close", clock: "daemon", phase: "closed", elapsed_ms: elapsed() });
|
|
30532
|
+
end("closed");
|
|
30533
|
+
},
|
|
30534
|
+
outcome: () => outcome
|
|
30535
|
+
};
|
|
30536
|
+
entry.handle = handle;
|
|
30537
|
+
entry.accept = (samples, client, terminal) => {
|
|
30538
|
+
for (const sample of samples) if (!entry.seen.has("client:" + sample.phase)) {
|
|
30539
|
+
entry.seen.add("client:" + sample.phase);
|
|
30540
|
+
write({ record_type: "load_sample", clock: "client", phase: sample.phase, elapsed_ms: sample.elapsed_ms, ...sample.occurred_at_ms ? { event_at_ms: sample.occurred_at_ms } : {}, ...client ? { client_class: client } : {} });
|
|
30541
|
+
if (sample.phase === "content_presented") end("presented");
|
|
30542
|
+
try {
|
|
30543
|
+
entry.record(sample);
|
|
30544
|
+
} catch {
|
|
30545
|
+
}
|
|
30546
|
+
}
|
|
30547
|
+
if (terminal && !entry.seen.has("terminal")) {
|
|
30548
|
+
entry.seen.add("terminal");
|
|
30549
|
+
write({ record_type: "load_terminal", clock: "client", phase: terminal.kind, terminal_phase: terminal.phase, reason: terminal.reason, elapsed_ms: terminal.elapsed_ms, ...terminal.occurred_at_ms ? { event_at_ms: terminal.occurred_at_ms } : {}, ...client ? { client_class: client } : {} });
|
|
30550
|
+
end(terminal.kind);
|
|
30551
|
+
}
|
|
30552
|
+
};
|
|
30553
|
+
this.entries.set(id5, entry);
|
|
30554
|
+
write({ record_type: "load_start", clock: "daemon", phase: "open_received", elapsed_ms: 0, source_transport: input.transport });
|
|
30555
|
+
return handle;
|
|
30556
|
+
}
|
|
30557
|
+
register(loadId, threadId2, owner2, record25, attempt) {
|
|
30380
30558
|
for (const [key, value] of this.entries) if (value.expires < this.now()) this.entries.delete(key);
|
|
30381
|
-
|
|
30559
|
+
const existing = this.entries.get(loadId);
|
|
30560
|
+
if (existing?.handle && existing.handle === attempt && existing.threadId === threadId2 && existing.owner === owner2) {
|
|
30561
|
+
existing.record = record25;
|
|
30562
|
+
return () => {
|
|
30563
|
+
};
|
|
30564
|
+
}
|
|
30565
|
+
if (!z8.string().uuid().safeParse(loadId).success || this.entries.size >= 256 || this.used.size >= 1e4 || this.entries.has(loadId) || this.used.has(loadId)) return () => {
|
|
30382
30566
|
};
|
|
30383
|
-
const
|
|
30567
|
+
const writer = this.audit(), epoch = writer?.loadGeneration?.();
|
|
30568
|
+
if (writer?.reserveLoadId && !writer.reserveLoadId(loadId)) {
|
|
30569
|
+
this.used.add(loadId);
|
|
30570
|
+
return () => {
|
|
30571
|
+
};
|
|
30572
|
+
}
|
|
30573
|
+
this.used.add(loadId);
|
|
30574
|
+
const entry = { threadId: threadId2, owner: owner2, expires: this.now() + 9e5, record: record25, seen: /* @__PURE__ */ new Set(), valid: () => this.entries.get(loadId) === entry && writer?.loadGeneration?.() === epoch && this.now() <= entry.expires };
|
|
30384
30575
|
this.entries.set(loadId, entry);
|
|
30385
30576
|
return () => {
|
|
30386
30577
|
if (this.entries.get(loadId) === entry) this.entries.delete(loadId);
|
|
30387
30578
|
};
|
|
30388
30579
|
}
|
|
30389
30580
|
report(input, owner2) {
|
|
30390
|
-
|
|
30581
|
+
let parsed;
|
|
30582
|
+
try {
|
|
30583
|
+
parsed = input?.version === 2 ? { success: true, data: parseThreadLoadReportV2(input) } : ThreadLoadReportSchema.safeParse(input);
|
|
30584
|
+
} catch {
|
|
30585
|
+
parsed = { success: false };
|
|
30586
|
+
}
|
|
30391
30587
|
if (!parsed.success) return { accepted: false };
|
|
30392
30588
|
const { load_id, thread_id, samples } = parsed.data;
|
|
30393
30589
|
const entry = this.entries.get(load_id);
|
|
30394
|
-
if (!entry || entry.threadId !== thread_id || entry.owner !== owner2 || entry.expires < this.now()) return { accepted: false };
|
|
30590
|
+
if (!entry || entry.threadId !== thread_id || entry.owner !== owner2 || entry.expires < this.now() || entry.valid && !entry.valid()) return { accepted: false };
|
|
30591
|
+
if (entry.accept) {
|
|
30592
|
+
entry.accept(samples, parsed.data.client_class, parsed.data.terminal);
|
|
30593
|
+
return { accepted: true };
|
|
30594
|
+
}
|
|
30395
30595
|
for (const sample of samples) if (!entry.seen.has(sample.phase)) {
|
|
30396
30596
|
entry.seen.add(sample.phase);
|
|
30397
30597
|
try {
|
|
@@ -30618,6 +30818,8 @@ var ThreadOpenQuerySchema = z9.object({
|
|
|
30618
30818
|
range_resume_version: z9.literal("1").transform(() => 1).optional(),
|
|
30619
30819
|
range_resume_token: z9.string().regex(/^[A-Za-z0-9_-]{43}$/).optional(),
|
|
30620
30820
|
load_id: z9.string().uuid().optional(),
|
|
30821
|
+
// 恢复关联仍保留,只有首屏采样可显式关闭。
|
|
30822
|
+
load_trace: z9.literal("false").transform(() => false).optional(),
|
|
30621
30823
|
include_execution: z9.literal("true").transform(() => true).optional(),
|
|
30622
30824
|
include_message_times: z9.literal("true").transform(() => true).optional(),
|
|
30623
30825
|
include_async_questions: z9.literal("true").transform(() => true).optional(),
|
|
@@ -31738,6 +31940,7 @@ function createThreadOpenSseProjection(rawQuery, options = {}) {
|
|
|
31738
31940
|
...query2.range_resume_version ? { rangeResumeVersion: 1 } : {},
|
|
31739
31941
|
...query2.range_resume_token ? { rangeResumeToken: query2.range_resume_token } : {},
|
|
31740
31942
|
...query2.load_id ? { loadId: query2.load_id } : {},
|
|
31943
|
+
...query2.load_trace === false ? { loadTrace: false } : {},
|
|
31741
31944
|
viewVersion: THREAD_VIEW_VERSION,
|
|
31742
31945
|
...query2.include_async_questions ? { includeAsyncQuestions: true } : {},
|
|
31743
31946
|
...query2.include_read_receipts ? { includeReadReceipts: true } : {},
|
|
@@ -32772,7 +32975,7 @@ async function dispatchRestRoute(request2, dependencies) {
|
|
|
32772
32975
|
}
|
|
32773
32976
|
}
|
|
32774
32977
|
if (route === "POST /api/v1/thread/load/report") {
|
|
32775
|
-
const body = ThreadLoadReportSchema.parse(request2.body);
|
|
32978
|
+
const body = request2.body?.version === 2 ? ThreadLoadReportV2Schema.parse(request2.body) : ThreadLoadReportSchema.parse(request2.body);
|
|
32776
32979
|
const result = await daemonClient.request("thread/load/report", body, {
|
|
32777
32980
|
...daemonRequestOptions(5e3, request2.signal),
|
|
32778
32981
|
...request2.authenticatedMessageSubmissionScope !== void 0 ? { authenticatedMessageSubmissionScope: request2.authenticatedMessageSubmissionScope } : {}
|
|
@@ -43068,8 +43271,8 @@ function createRelayAttachmentDataLink(options) {
|
|
|
43068
43271
|
const child = { permit, lease: null, ws: null, receiver: null, closed: false, paired: false, ready: false, opening: null, cleanup: null, unregister: null };
|
|
43069
43272
|
children.set(permit.transfer_id, child);
|
|
43070
43273
|
const registrationStarted = Date.now();
|
|
43071
|
-
const
|
|
43072
|
-
recordAttachmentDiagnostic(options.diagnostic, { phase: "file.register", reason: "started", ...
|
|
43274
|
+
const timing2 = () => ({ attach_remaining_ms: permit.attach_expires_at - Date.now(), transfer_remaining_ms: permit.expires_at - Date.now(), registration_elapsed_ms: Date.now() - registrationStarted });
|
|
43275
|
+
recordAttachmentDiagnostic(options.diagnostic, { phase: "file.register", reason: "started", ...timing2() });
|
|
43073
43276
|
try {
|
|
43074
43277
|
const reply = await options.control.requestFileControl("file.register", {
|
|
43075
43278
|
version: 1,
|
|
@@ -43081,7 +43284,7 @@ function createRelayAttachmentDataLink(options) {
|
|
|
43081
43284
|
max_wire_bytes: attachmentTransferWireBudget(permit.context.byte_size)
|
|
43082
43285
|
});
|
|
43083
43286
|
if (reply.code !== 0) {
|
|
43084
|
-
recordAttachmentDiagnostic(options.diagnostic, { phase: "file.register", reason: "failed", code: reply.code, ...
|
|
43287
|
+
recordAttachmentDiagnostic(options.diagnostic, { phase: "file.register", reason: "failed", code: reply.code, ...timing2() });
|
|
43085
43288
|
const error2 = unavailable7();
|
|
43086
43289
|
error2.cause = { stage: "file.register", relayCode: reply.code };
|
|
43087
43290
|
throw error2;
|
|
@@ -46646,7 +46849,7 @@ var RuntimeDesktopIngress = class {
|
|
|
46646
46849
|
resetMethodValidity() {
|
|
46647
46850
|
this.ipcMethodInvalidatedThreads.clear();
|
|
46648
46851
|
}
|
|
46649
|
-
async process(frame, ownClientId = this.ports.ipc()?.getClientId?.() ?? null, receivedIpcGeneration = this.ports.ipcConnectionGeneration(),
|
|
46852
|
+
async process(frame, ownClientId = this.ports.ipc()?.getClientId?.() ?? null, receivedIpcGeneration = this.ports.ipcConnectionGeneration(), timing2, readDiagnostic) {
|
|
46650
46853
|
this.ports.writeDebug({
|
|
46651
46854
|
component: "daemon",
|
|
46652
46855
|
channel: "ipc",
|
|
@@ -46656,7 +46859,7 @@ var RuntimeDesktopIngress = class {
|
|
|
46656
46859
|
attributes: {
|
|
46657
46860
|
type: frame.type,
|
|
46658
46861
|
...typeof frame.method === "string" ? { method: frame.method } : {},
|
|
46659
|
-
...
|
|
46862
|
+
...timing2
|
|
46660
46863
|
}
|
|
46661
46864
|
});
|
|
46662
46865
|
this.ports.writeRawDebug({
|
|
@@ -46688,6 +46891,9 @@ var RuntimeDesktopIngress = class {
|
|
|
46688
46891
|
}
|
|
46689
46892
|
const status2 = objectRecord(frame.params);
|
|
46690
46893
|
const methodThreadId = extractThreadIdFromIpcFrame(frame);
|
|
46894
|
+
if (!this.ports.stopping() && receivedIpcGeneration === this.ports.ipcConnectionGeneration() && this.ports.desktopIpcState() === "ready" && ownClientId && frame.type === "broadcast" && frame.sourceClientId && frame.sourceClientId !== ownClientId && status2.hostId === "local" && methodThreadId && (frame.method === "thread-stream-following-status-requested" || frame.method === "thread-stream-following-changed" && status2.following === true)) {
|
|
46895
|
+
this.ports.discoverThread(methodThreadId);
|
|
46896
|
+
}
|
|
46691
46897
|
if (frame.method === "thread-stream-state-changed" && methodThreadId && this.ipcMethodInvalidatedThreads.has(methodThreadId) && objectRecord(status2.change).type !== "snapshot") {
|
|
46692
46898
|
if (readDiagnostic) readDiagnostic.reason = "baseline_required";
|
|
46693
46899
|
return;
|
|
@@ -47343,19 +47549,19 @@ var DesktopIpcClient = class {
|
|
|
47343
47549
|
this.events.on("requestDiagnostic", listener);
|
|
47344
47550
|
return () => this.events.off("requestDiagnostic", listener);
|
|
47345
47551
|
}
|
|
47346
|
-
emitRequestDiagnostic(
|
|
47552
|
+
emitRequestDiagnostic(timing2, phase, outcome) {
|
|
47347
47553
|
this.events.emit("requestDiagnostic", {
|
|
47348
|
-
requestId:
|
|
47349
|
-
method:
|
|
47350
|
-
threadId:
|
|
47554
|
+
requestId: timing2.requestId,
|
|
47555
|
+
method: timing2.method,
|
|
47556
|
+
threadId: timing2.threadId,
|
|
47351
47557
|
phase,
|
|
47352
47558
|
outcome,
|
|
47353
|
-
durationMs: Math.max(0, Math.floor(performance.now() -
|
|
47559
|
+
durationMs: Math.max(0, Math.floor(performance.now() - timing2.startedAt))
|
|
47354
47560
|
});
|
|
47355
47561
|
}
|
|
47356
47562
|
pruneTimedOutRequests() {
|
|
47357
|
-
for (const [id5,
|
|
47358
|
-
if (performance.now() -
|
|
47563
|
+
for (const [id5, timing2] of this.timedOutRequests) {
|
|
47564
|
+
if (performance.now() - timing2.startedAt > 12e4) this.timedOutRequests.delete(id5);
|
|
47359
47565
|
}
|
|
47360
47566
|
while (this.timedOutRequests.size > 128) this.timedOutRequests.delete(this.timedOutRequests.keys().next().value);
|
|
47361
47567
|
}
|
|
@@ -47492,20 +47698,20 @@ var DesktopIpcClient = class {
|
|
|
47492
47698
|
this.pruneTimedOutRequests();
|
|
47493
47699
|
const localParams = params && typeof params === "object" ? params : {};
|
|
47494
47700
|
const threadId2 = typeof localParams.threadId === "string" ? localParams.threadId : typeof localParams.conversationId === "string" ? localParams.conversationId : void 0;
|
|
47495
|
-
const
|
|
47701
|
+
const timing2 = { requestId, method: method2, threadId: threadId2, startedAt: performance.now() };
|
|
47496
47702
|
const responsePromise = new Promise((resolve5, reject3) => {
|
|
47497
47703
|
const timer = setTimeout(() => {
|
|
47498
47704
|
this.pending.delete(requestId);
|
|
47499
|
-
this.timedOutRequests.set(requestId,
|
|
47705
|
+
this.timedOutRequests.set(requestId, timing2);
|
|
47500
47706
|
this.pruneTimedOutRequests();
|
|
47501
|
-
this.emitRequestDiagnostic(
|
|
47707
|
+
this.emitRequestDiagnostic(timing2, "timeout", "unknown");
|
|
47502
47708
|
reject3(new NiumaError("UNKNOWN_RESULT", `IPC \u8BF7\u6C42\u8D85\u65F6: ${method2}`, { method: method2 }));
|
|
47503
47709
|
}, options.timeoutMs ?? this.requestTimeoutMs);
|
|
47504
|
-
this.pending.set(requestId, { timer, resolve: resolve5, reject: reject3, timing });
|
|
47710
|
+
this.pending.set(requestId, { timer, resolve: resolve5, reject: reject3, timing: timing2 });
|
|
47505
47711
|
});
|
|
47506
47712
|
try {
|
|
47507
47713
|
await this.write(frame);
|
|
47508
|
-
this.emitRequestDiagnostic(
|
|
47714
|
+
this.emitRequestDiagnostic(timing2, "sent", "pending");
|
|
47509
47715
|
} catch (error2) {
|
|
47510
47716
|
this.clearPending(requestId);
|
|
47511
47717
|
throw error2 instanceof Error ? new NiumaError("IPC_NOT_INITIALIZED", error2.message) : new NiumaError("IPC_NOT_INITIALIZED", String(error2));
|
|
@@ -47604,10 +47810,10 @@ var DesktopIpcClient = class {
|
|
|
47604
47810
|
this.pruneTimedOutRequests();
|
|
47605
47811
|
const outcome = frame.resultType === "error" ? "error" : "success";
|
|
47606
47812
|
if (!pending) {
|
|
47607
|
-
const
|
|
47608
|
-
if (
|
|
47813
|
+
const timing2 = this.timedOutRequests.get(requestId);
|
|
47814
|
+
if (timing2) {
|
|
47609
47815
|
this.timedOutRequests.delete(requestId);
|
|
47610
|
-
this.emitRequestDiagnostic(
|
|
47816
|
+
this.emitRequestDiagnostic(timing2, "late_response", outcome);
|
|
47611
47817
|
}
|
|
47612
47818
|
return;
|
|
47613
47819
|
}
|
|
@@ -56320,15 +56526,46 @@ function createHistoryHandlers(ports) {
|
|
|
56320
56526
|
if (negotiated && (!handoffScope || !scope || scope.bindingId !== handoffScope.bindingId)) {
|
|
56321
56527
|
throw new HttpApiError(200, 200004, "\u6B63\u6587\u4EA4\u63A5\u9700\u8981\u8BA4\u8BC1\u4F1A\u8BDD");
|
|
56322
56528
|
}
|
|
56529
|
+
const loadStartedAt = performance.now();
|
|
56530
|
+
const loadAttempt = params.loadTrace === false ? null : ports.threadLoadReports().begin?.({ loadId: params.loadId, threadId: threadId2, owner: scope ? `binding:${scope.bindingId.toLowerCase()}` : "local", transport: scope?.transport ?? "local", nowMs: Date.now() });
|
|
56531
|
+
const loadElapsed = () => Math.max(0, Math.min(9e5, Math.round(performance.now() - loadStartedAt)));
|
|
56532
|
+
let loadFailurePhase = "open_received";
|
|
56533
|
+
const failOpen = (error2) => {
|
|
56534
|
+
if (!options.signal?.aborted && normalizeHttpError(error2).httpStatus === 200) loadAttempt?.finish("failed", { terminal_phase: loadFailurePhase, reason: "open_rejected" });
|
|
56535
|
+
};
|
|
56323
56536
|
if (negotiated && typeof params.handoffTicket === "string") {
|
|
56324
|
-
if (options.signal?.aborted || socket.destroyed || socket.writableEnded)
|
|
56325
|
-
|
|
56326
|
-
|
|
56327
|
-
|
|
56328
|
-
|
|
56329
|
-
|
|
56330
|
-
|
|
56331
|
-
|
|
56537
|
+
if (options.signal?.aborted || socket.destroyed || socket.writableEnded) {
|
|
56538
|
+
loadAttempt?.close();
|
|
56539
|
+
return STREAMING_RESPONSE;
|
|
56540
|
+
}
|
|
56541
|
+
let consumer;
|
|
56542
|
+
try {
|
|
56543
|
+
consumer = ports.connectionHandoff().claim(
|
|
56544
|
+
handoffScope,
|
|
56545
|
+
params.handoffDescriptor,
|
|
56546
|
+
params.handoffTicket,
|
|
56547
|
+
{ emit: (frame) => {
|
|
56548
|
+
socket.write(`${JSON.stringify(successEnvelope(frame))}
|
|
56549
|
+
`);
|
|
56550
|
+
if (frame.type === "thread_view_snapshot") {
|
|
56551
|
+
loadFailurePhase = "shell_sent";
|
|
56552
|
+
loadAttempt?.markDaemon("shell_sent", loadElapsed());
|
|
56553
|
+
}
|
|
56554
|
+
const view = frame.data;
|
|
56555
|
+
if (view?.availability?.state === "ready") {
|
|
56556
|
+
loadFailurePhase = "history_sent";
|
|
56557
|
+
loadAttempt?.markDaemon("history_sent", loadElapsed());
|
|
56558
|
+
}
|
|
56559
|
+
}, onClose: () => {
|
|
56560
|
+
loadAttempt?.close();
|
|
56561
|
+
socket.end();
|
|
56562
|
+
} }
|
|
56563
|
+
);
|
|
56564
|
+
} catch (error2) {
|
|
56565
|
+
failOpen(error2);
|
|
56566
|
+
loadAttempt?.close();
|
|
56567
|
+
throw error2;
|
|
56568
|
+
}
|
|
56332
56569
|
let recoveryClosed = false;
|
|
56333
56570
|
let unregisterRecovery2 = () => {
|
|
56334
56571
|
};
|
|
@@ -56341,12 +56578,14 @@ function createHistoryHandlers(ports) {
|
|
|
56341
56578
|
}) : () => {
|
|
56342
56579
|
};
|
|
56343
56580
|
} catch (error2) {
|
|
56581
|
+
loadAttempt?.close();
|
|
56344
56582
|
consumer.close();
|
|
56345
56583
|
throw error2;
|
|
56346
56584
|
}
|
|
56347
56585
|
let unregisterArchive2 = () => {
|
|
56348
56586
|
};
|
|
56349
56587
|
const close2 = () => {
|
|
56588
|
+
loadAttempt?.close();
|
|
56350
56589
|
unregisterArchive2();
|
|
56351
56590
|
recoveryClosed = true;
|
|
56352
56591
|
unregisterRecovery2();
|
|
@@ -56373,7 +56612,6 @@ function createHistoryHandlers(ports) {
|
|
|
56373
56612
|
`);
|
|
56374
56613
|
return STREAMING_RESPONSE;
|
|
56375
56614
|
}
|
|
56376
|
-
const loadStartedAt = performance.now();
|
|
56377
56615
|
let loadTrace = null;
|
|
56378
56616
|
let loadLeaseId = null;
|
|
56379
56617
|
let unregisterLoad = () => {
|
|
@@ -56383,7 +56621,9 @@ function createHistoryHandlers(ports) {
|
|
|
56383
56621
|
const pendingLoad = [];
|
|
56384
56622
|
const loadSeen = /* @__PURE__ */ new Set();
|
|
56385
56623
|
const recordLoad = (phase, clock = "daemon", elapsed = Math.round(performance.now() - loadStartedAt), occurredAt4 = clock === "daemon" ? Date.now() : void 0) => {
|
|
56386
|
-
if (
|
|
56624
|
+
if (clock === "daemon" && ["open_received", "identity_ready", "lease_acquired", "shell_sent", "history_sent"].includes(phase)) loadFailurePhase = phase;
|
|
56625
|
+
if (params.loadTrace === false || typeof params.loadId !== "string" || elapsed < 0 || elapsed > 9e5) return;
|
|
56626
|
+
if (clock === "daemon") loadAttempt?.markDaemon(phase, elapsed, occurredAt4);
|
|
56387
56627
|
if (!loadLeaseId) {
|
|
56388
56628
|
if (pendingLoad.length < 8) pendingLoad.push({ phase, elapsed, occurredAt: occurredAt4 });
|
|
56389
56629
|
return;
|
|
@@ -56472,6 +56712,7 @@ function createHistoryHandlers(ports) {
|
|
|
56472
56712
|
readReceiptTimer = null;
|
|
56473
56713
|
}
|
|
56474
56714
|
recordLoad("stream_closed");
|
|
56715
|
+
loadAttempt?.close();
|
|
56475
56716
|
unregisterLoad();
|
|
56476
56717
|
unregisterRecovery();
|
|
56477
56718
|
closed = true;
|
|
@@ -56508,6 +56749,7 @@ function createHistoryHandlers(ports) {
|
|
|
56508
56749
|
const close = () => {
|
|
56509
56750
|
if (physicalClosed) return;
|
|
56510
56751
|
physicalClosed = true;
|
|
56752
|
+
loadAttempt?.close();
|
|
56511
56753
|
unregisterRecovery();
|
|
56512
56754
|
options.signal?.removeEventListener("abort", close);
|
|
56513
56755
|
publisher?.close();
|
|
@@ -56524,7 +56766,14 @@ function createHistoryHandlers(ports) {
|
|
|
56524
56766
|
return STREAMING_RESPONSE;
|
|
56525
56767
|
}
|
|
56526
56768
|
if (!ports.store().getThread(threadId2, { tailCount: 0 })) {
|
|
56527
|
-
|
|
56769
|
+
try {
|
|
56770
|
+
await ports.verifyThreadForOpen(threadId2);
|
|
56771
|
+
} catch (error2) {
|
|
56772
|
+
failOpen(error2);
|
|
56773
|
+
loadAttempt?.close();
|
|
56774
|
+
detachClose();
|
|
56775
|
+
throw error2;
|
|
56776
|
+
}
|
|
56528
56777
|
}
|
|
56529
56778
|
if (closed || socketIsClosed()) {
|
|
56530
56779
|
closed = true;
|
|
@@ -56573,13 +56822,15 @@ function createHistoryHandlers(ports) {
|
|
|
56573
56822
|
}
|
|
56574
56823
|
for (const sample of pendingLoad) recordLoad(sample.phase, "daemon", sample.elapsed, sample.occurredAt);
|
|
56575
56824
|
pendingLoad.length = 0;
|
|
56825
|
+
if (loadLeaseId && loadTrace) loadAttempt?.attachLease(loadLeaseId, loadTrace.traceId);
|
|
56576
56826
|
recordLoad("lease_acquired");
|
|
56577
56827
|
try {
|
|
56578
|
-
if (loadLeaseId && loadTrace) unregisterLoad = ports.threadLoadReports().register(
|
|
56828
|
+
if (loadAttempt && loadLeaseId && loadTrace) unregisterLoad = ports.threadLoadReports().register(
|
|
56579
56829
|
params.loadId,
|
|
56580
56830
|
threadId2,
|
|
56581
56831
|
scope ? `binding:${scope.bindingId.toLowerCase()}` : "local",
|
|
56582
|
-
(sample) => recordLoad(sample.phase, "browser", sample.elapsed_ms, sample.occurred_at_ms)
|
|
56832
|
+
(sample) => recordLoad(sample.phase, "browser", sample.elapsed_ms, sample.occurred_at_ms),
|
|
56833
|
+
loadAttempt
|
|
56583
56834
|
);
|
|
56584
56835
|
} catch {
|
|
56585
56836
|
}
|
|
@@ -56693,6 +56944,7 @@ function createHistoryHandlers(ports) {
|
|
|
56693
56944
|
ports.requestThreadAuthorityRecovery(threadId2, true);
|
|
56694
56945
|
ports.history().onHistoryLeaseStateChanged(threadId2, ports.activeThreadFollowerCoordinator()?.leaseKindsFor(threadId2) ?? []);
|
|
56695
56946
|
unsubscribeHistoryWindow = historyWindow.subscribe(() => {
|
|
56947
|
+
if (historyWindow?.initialWindowState === "failed") loadAttempt?.finish("failed", { terminal_phase: "shell_sent", reason: "history_failed" });
|
|
56696
56948
|
if (rangeClaim && historyWindow?.initialWindowState === "failed") {
|
|
56697
56949
|
socket.write(`${JSON.stringify(errorEnvelope(new NiumaError("HISTORY_SNAPSHOT_EXPIRED", "\u5386\u53F2\u6062\u590D\u8303\u56F4\u4E0D\u53EF\u7528\u6216\u5DF2\u8FC7\u671F")))}
|
|
56698
56950
|
`);
|
|
@@ -56767,6 +57019,7 @@ function createHistoryHandlers(ports) {
|
|
|
56767
57019
|
`);
|
|
56768
57020
|
}
|
|
56769
57021
|
} catch (error2) {
|
|
57022
|
+
failOpen(error2);
|
|
56770
57023
|
try {
|
|
56771
57024
|
const sites = [
|
|
56772
57025
|
["historySourceAssertion", "Object.sourceCurrent"],
|
|
@@ -56838,20 +57091,20 @@ function text10(value) {
|
|
|
56838
57091
|
return false;
|
|
56839
57092
|
}
|
|
56840
57093
|
}
|
|
56841
|
-
function
|
|
57094
|
+
function object10(value, keys3) {
|
|
56842
57095
|
if (!value || typeof value !== "object" || Array.isArray(value) || ![Object.prototype, null].includes(Object.getPrototypeOf(value))) return fail16("invalid");
|
|
56843
57096
|
const own = Reflect.ownKeys(value);
|
|
56844
57097
|
if (own.length !== keys3.length || !own.every((key) => typeof key === "string" && keys3.includes(key) && "value" in Object.getOwnPropertyDescriptor(value, key))) return fail16("invalid");
|
|
56845
57098
|
return value;
|
|
56846
57099
|
}
|
|
56847
57100
|
function parseAsyncQuestionBatch(value) {
|
|
56848
|
-
const raw =
|
|
57101
|
+
const raw = object10(value, ["thread_id", "group_id", "revision", "idempotency_key", "question_ids", "answers"]);
|
|
56849
57102
|
if (!id3(raw.thread_id) || !id3(raw.group_id) || !id3(raw.idempotency_key) || !Number.isSafeInteger(raw.revision) || raw.revision < 0 || !Array.isArray(raw.question_ids) || !raw.question_ids.length || raw.question_ids.length > 256 || !Array.isArray(raw.answers) || raw.answers.length > raw.question_ids.length) return fail16("invalid");
|
|
56850
57103
|
const questionIds = Array.from(raw.question_ids);
|
|
56851
57104
|
if (!questionIds.every(id3) || new Set(questionIds).size !== questionIds.length) return fail16("invalid");
|
|
56852
57105
|
const seen = /* @__PURE__ */ new Set();
|
|
56853
57106
|
const answers = Array.from(raw.answers, (value2) => {
|
|
56854
|
-
const answer =
|
|
57107
|
+
const answer = object10(value2, ["question_id", "title", "answer"]);
|
|
56855
57108
|
if (!id3(answer.question_id) || !questionIds.includes(answer.question_id) || seen.has(answer.question_id) || !text10(answer.title) || !text10(answer.answer)) return fail16("invalid");
|
|
56856
57109
|
seen.add(answer.question_id);
|
|
56857
57110
|
return { question_id: answer.question_id, title: answer.title, answer: answer.answer };
|
|
@@ -59640,10 +59893,10 @@ var ThreadHistoryWindowLoader = class {
|
|
|
59640
59893
|
sourceRevision: 0
|
|
59641
59894
|
};
|
|
59642
59895
|
for (let attempt = 0; attempt < 2; attempt++) {
|
|
59643
|
-
const
|
|
59896
|
+
const timing2 = await this.timestampVersion(turn, signal);
|
|
59644
59897
|
this.assertSource(epoch);
|
|
59645
59898
|
signal.throwIfAborted();
|
|
59646
|
-
const versionKey = JSON.stringify([epoch, description.contentVersion,
|
|
59899
|
+
const versionKey = JSON.stringify([epoch, description.contentVersion, timing2]);
|
|
59647
59900
|
let cached = this.turns.get(identity6);
|
|
59648
59901
|
if (cached?.current?.version === versionKey) {
|
|
59649
59902
|
if (description.sourceRevision >= cached.sourceRevision && cached.nativeOrder !== description.nativeOrder) {
|
|
@@ -59660,7 +59913,7 @@ var ThreadHistoryWindowLoader = class {
|
|
|
59660
59913
|
this.assertSource(epoch);
|
|
59661
59914
|
signal.throwIfAborted();
|
|
59662
59915
|
if (enriched.turnId !== turn.id) throw new RangeError("\u7A97\u53E3\u65F6\u95F4\u8865\u9F50 Turn \u8EAB\u4EFD\u4E0D\u5339\u914D");
|
|
59663
|
-
if (await this.timestampVersion(turn, signal) !==
|
|
59916
|
+
if (await this.timestampVersion(turn, signal) !== timing2) continue;
|
|
59664
59917
|
this.assertSource(epoch);
|
|
59665
59918
|
signal.throwIfAborted();
|
|
59666
59919
|
const freeze = (value) => {
|
|
@@ -59718,11 +59971,11 @@ var ThreadHistoryWindowLoader = class {
|
|
|
59718
59971
|
const epoch = this.sourceEpoch;
|
|
59719
59972
|
this.currentProtection.addTurnIds([turn.id]);
|
|
59720
59973
|
const description = this.reader.describeTurn?.(turn) ?? { contentVersion: createHash26("sha256").update(JSON.stringify(turn)).digest("hex") };
|
|
59721
|
-
const
|
|
59974
|
+
const timing2 = await this.timestampVersion(turn, signal);
|
|
59722
59975
|
this.assertSource(epoch);
|
|
59723
59976
|
signal.throwIfAborted();
|
|
59724
59977
|
const cached = this.turns.get(JSON.stringify([this.currentThreadId, turn.id]));
|
|
59725
|
-
if (cached?.current?.version === JSON.stringify([epoch, description.contentVersion,
|
|
59978
|
+
if (cached?.current?.version === JSON.stringify([epoch, description.contentVersion, timing2])) {
|
|
59726
59979
|
this.holdVersion(this.currentProtection, cached.current);
|
|
59727
59980
|
return cached.current.projection.displayItemCount;
|
|
59728
59981
|
}
|
|
@@ -60942,17 +61195,17 @@ var AppServerThreadViewAdapter = class {
|
|
|
60942
61195
|
lastError: null
|
|
60943
61196
|
}).status;
|
|
60944
61197
|
const terminalStatus = failed || aborted || status2 === "completed" ? lifecycleStatus : "completed";
|
|
60945
|
-
const
|
|
61198
|
+
const timing2 = context.getTurnLifecycle?.(turnId);
|
|
60946
61199
|
return [{
|
|
60947
61200
|
type: "ThreadStatusChanged",
|
|
60948
61201
|
thread_id: context.threadId,
|
|
60949
61202
|
status: terminalStatus,
|
|
60950
61203
|
turn_id: turnId,
|
|
60951
61204
|
terminal_item_state: terminalStatus === "error" ? "failed" : "completed",
|
|
60952
|
-
...
|
|
60953
|
-
startedAt: lifecycleTime(
|
|
60954
|
-
endedAt: lifecycleTime(
|
|
60955
|
-
outcome:
|
|
61205
|
+
...timing2 ? { process_lifecycle: {
|
|
61206
|
+
startedAt: lifecycleTime(timing2.startedAt),
|
|
61207
|
+
endedAt: lifecycleTime(timing2.endedAt),
|
|
61208
|
+
outcome: timing2.outcome
|
|
60956
61209
|
} } : {},
|
|
60957
61210
|
last_error: terminalStatus === "error" ? {
|
|
60958
61211
|
code: 900001,
|
|
@@ -61207,10 +61460,10 @@ var ThreadHistoryWindowProjection = class {
|
|
|
61207
61460
|
const enriched = this.options.enrichTimeline ? await this.options.enrichTimeline(sources.map((source2) => source2.timeline), startedAt) : this.timestamps.enrichTimelineFromReplay(sources.map((source2) => source2.timeline), startedAt, replay);
|
|
61208
61461
|
const timingById = new Map(sources.map((source2, index) => [source2.id, enriched[index]]));
|
|
61209
61462
|
const items = projected.items.map((item) => {
|
|
61210
|
-
const
|
|
61463
|
+
const timing2 = timingById.get(item.id);
|
|
61211
61464
|
const fact = item.process_fact;
|
|
61212
|
-
if (!
|
|
61213
|
-
const merged = mergeThreadHistoryTimelineLifecycle(
|
|
61465
|
+
if (!timing2 || !fact) return item;
|
|
61466
|
+
const merged = mergeThreadHistoryTimelineLifecycle(timing2, {
|
|
61214
61467
|
...fact.startedAt !== null ? { turnStartedAt: fact.startedAt } : {},
|
|
61215
61468
|
...fact.endedAt !== null ? { turnEndedAt: fact.endedAt } : {},
|
|
61216
61469
|
...fact.durationMs != null ? { turnDurationMs: fact.durationMs } : {},
|
|
@@ -62059,7 +62312,7 @@ function readStateDiagnostic(before, after, candidate = after.confirmed) {
|
|
|
62059
62312
|
sameCycle: candidate ? candidate.cycle === after.cycle : null
|
|
62060
62313
|
};
|
|
62061
62314
|
}
|
|
62062
|
-
function
|
|
62315
|
+
function object11(value) {
|
|
62063
62316
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
62064
62317
|
}
|
|
62065
62318
|
function field(value, present, count) {
|
|
@@ -62069,15 +62322,15 @@ function field(value, present, count) {
|
|
|
62069
62322
|
}
|
|
62070
62323
|
function unreadFrameDiagnostic(frame) {
|
|
62071
62324
|
if (frame.method !== "thread-stream-state-changed") return null;
|
|
62072
|
-
const params =
|
|
62325
|
+
const params = object11(frame.params), change = object11(params.change);
|
|
62073
62326
|
const kind = change.type === "snapshot" ? "snapshot" : change.type === "patches" ? "patch" : "invalid";
|
|
62074
|
-
const values = kind === "snapshot" ?
|
|
62327
|
+
const values = kind === "snapshot" ? object11(change.conversationState) : {};
|
|
62075
62328
|
let unread = field(values.hasUnreadTurn, Object.hasOwn(values, "hasUnreadTurn"), false);
|
|
62076
62329
|
let count = field(values.unreadMessageCount, Object.hasOwn(values, "unreadMessageCount"), true);
|
|
62077
62330
|
let countValue = values.unreadMessageCount;
|
|
62078
62331
|
if (kind === "patch") {
|
|
62079
62332
|
for (const value of Array.isArray(change.patches) ? change.patches : []) {
|
|
62080
|
-
const patch =
|
|
62333
|
+
const patch = object11(value), path54 = Array.isArray(patch.path) ? patch.path : [];
|
|
62081
62334
|
const name2 = path54.length === 1 ? path54[0] : path54.length === 2 && path54[0] === "conversationState" ? path54[1] : null;
|
|
62082
62335
|
if (name2 !== "hasUnreadTurn" && name2 !== "unreadMessageCount") continue;
|
|
62083
62336
|
const state = patch.op === "remove" ? "removed" : ["add", "replace"].includes(String(patch.op)) ? field(patch.value, Object.hasOwn(patch, "value"), name2 === "unreadMessageCount") : "invalid";
|
|
@@ -62119,10 +62372,10 @@ var RuntimeIngressDispatch = class {
|
|
|
62119
62372
|
}
|
|
62120
62373
|
ports;
|
|
62121
62374
|
/** 单帧入站与最终结果成对记录;原始字段与业务结果分开,拒绝帧同样留证。 */
|
|
62122
|
-
async handleIpcFrame(frame, ownClientId = this.ports.desktopSession().ipcValue?.getClientId?.() ?? null, receivedIpcGeneration = this.ports.desktopSession().ipcConnectionGenerationValue,
|
|
62375
|
+
async handleIpcFrame(frame, ownClientId = this.ports.desktopSession().ipcValue?.getClientId?.() ?? null, receivedIpcGeneration = this.ports.desktopSession().ipcConnectionGenerationValue, timing2) {
|
|
62123
62376
|
const attributes = this.ports.options().debugLogger ? unreadFrameDiagnostic(frame) : null;
|
|
62124
62377
|
const threadId2 = attributes ? extractThreadIdFromIpcFrame(frame) : null;
|
|
62125
|
-
if (!attributes || !threadId2) return this.ports.desktopIngress().process(frame, ownClientId, receivedIpcGeneration,
|
|
62378
|
+
if (!attributes || !threadId2) return this.ports.desktopIngress().process(frame, ownClientId, receivedIpcGeneration, timing2);
|
|
62126
62379
|
const before = this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 })?.unread;
|
|
62127
62380
|
const diagnostic = { reason: "processed" };
|
|
62128
62381
|
const metadata = { ...attributes, sequence: this.ports.diagnostics().threadReadDiagnosticSequenceValue++, generation: receivedIpcGeneration, currentGeneration: this.ports.desktopSession().ipcConnectionGenerationValue };
|
|
@@ -62135,7 +62388,7 @@ var RuntimeIngressDispatch = class {
|
|
|
62135
62388
|
}
|
|
62136
62389
|
});
|
|
62137
62390
|
try {
|
|
62138
|
-
await this.ports.desktopIngress().process(frame, ownClientId, receivedIpcGeneration,
|
|
62391
|
+
await this.ports.desktopIngress().process(frame, ownClientId, receivedIpcGeneration, timing2, diagnostic);
|
|
62139
62392
|
} catch (error2) {
|
|
62140
62393
|
diagnostic.reason = "processing_failed";
|
|
62141
62394
|
throw error2;
|
|
@@ -63863,11 +64116,11 @@ var RuntimeProjectionContext = class {
|
|
|
63863
64116
|
} : null),
|
|
63864
64117
|
enrichTimelineItemTiming: (item) => this.ports.timelinePublication().enrichTimelineItemTiming(item, timelineItems),
|
|
63865
64118
|
getTurnLifecycle: (turnId) => {
|
|
63866
|
-
const
|
|
63867
|
-
return
|
|
63868
|
-
startedAt:
|
|
63869
|
-
endedAt:
|
|
63870
|
-
outcome:
|
|
64119
|
+
const timing2 = this.ports.timelinePublication().turnTiming(threadId2, turnId);
|
|
64120
|
+
return timing2 ? {
|
|
64121
|
+
startedAt: timing2.startedAt,
|
|
64122
|
+
endedAt: timing2.endedAt ?? null,
|
|
64123
|
+
outcome: timing2.outcome ?? null
|
|
63871
64124
|
} : null;
|
|
63872
64125
|
},
|
|
63873
64126
|
resolveKnownLocalImage: (sourcePath, itemId, partIndex) => this.ports.resolveThreadViewImage(threadId2, sourcePath, () => this.ports.isCurrentAppServerAsyncFence(threadId2, fence), itemId, partIndex)
|
|
@@ -64396,7 +64649,7 @@ var DesktopThreadSettingsTracker = class {
|
|
|
64396
64649
|
|
|
64397
64650
|
// apps/desktop/src/daemon/active-thread-follower-coordinator.ts
|
|
64398
64651
|
init_session_history_file();
|
|
64399
|
-
var ACTIVE_THREAD_SCAN_INTERVAL_MS =
|
|
64652
|
+
var ACTIVE_THREAD_SCAN_INTERVAL_MS = 6e4;
|
|
64400
64653
|
var ACTIVE_THREAD_READ_CONCURRENCY = 4;
|
|
64401
64654
|
var ACTIVE_FOLLOWER_SNAPSHOT_TIMEOUT_MS = 12e3;
|
|
64402
64655
|
var ACTIVE_FOLLOWER_RETRY_DELAYS_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
@@ -71378,7 +71631,7 @@ var RuntimeThreadStateCoordination = class {
|
|
|
71378
71631
|
return token3;
|
|
71379
71632
|
}
|
|
71380
71633
|
/** 仅供已核验的同轮终态使用;同时收敛列表与详情,不伪造新的完成通知。 */
|
|
71381
|
-
applyRecoveredTerminal(threadId2, turnId, outcome, occurredAt4, message,
|
|
71634
|
+
applyRecoveredTerminal(threadId2, turnId, outcome, occurredAt4, message, timing2) {
|
|
71382
71635
|
const previous = this.ports.catalog().storeValue.getThread(threadId2, { tailCount: 0 });
|
|
71383
71636
|
const mutation = this.ports.catalog().storeValue.applyActivitySignal({
|
|
71384
71637
|
type: "snapshot",
|
|
@@ -71398,7 +71651,7 @@ var RuntimeThreadStateCoordination = class {
|
|
|
71398
71651
|
turn_id: turnId,
|
|
71399
71652
|
status: outcome === "aborted" ? "idle" : outcome === "failed" ? "error" : "completed",
|
|
71400
71653
|
terminal_item_state: outcome === "failed" ? "failed" : "completed",
|
|
71401
|
-
process_lifecycle: { startedAt:
|
|
71654
|
+
process_lifecycle: { startedAt: timing2?.startedAt ?? null, endedAt: timing2?.endedAt ?? null, outcome },
|
|
71402
71655
|
last_error: outcome === "failed" && message ? { code: 900001, message, occurred_at: occurredAt4, turn_id: turnId } : null
|
|
71403
71656
|
},
|
|
71404
71657
|
{ type: "ThreadActivityChanged", thread_id: threadId2, turn_id: turnId, activity: null },
|
|
@@ -71637,15 +71890,15 @@ var RuntimeTimelinePublication = class {
|
|
|
71637
71890
|
if (!item.turnId) {
|
|
71638
71891
|
return item;
|
|
71639
71892
|
}
|
|
71640
|
-
const
|
|
71641
|
-
if (!
|
|
71893
|
+
const timing2 = this.liveTurnTimings.get(this.turnTimingKey(item.threadId, item.turnId));
|
|
71894
|
+
if (!timing2) {
|
|
71642
71895
|
return item;
|
|
71643
71896
|
}
|
|
71644
71897
|
return {
|
|
71645
71898
|
...item,
|
|
71646
|
-
...item.turnStartedAt === void 0 ? { turnStartedAt:
|
|
71647
|
-
...item.turnEndedAt === void 0 &&
|
|
71648
|
-
...item.turnOutcome === void 0 &&
|
|
71899
|
+
...item.turnStartedAt === void 0 ? { turnStartedAt: timing2.startedAt } : {},
|
|
71900
|
+
...item.turnEndedAt === void 0 && timing2.endedAt !== void 0 ? { turnEndedAt: timing2.endedAt } : {},
|
|
71901
|
+
...item.turnOutcome === void 0 && timing2.outcome !== void 0 ? { turnOutcome: timing2.outcome } : {}
|
|
71649
71902
|
};
|
|
71650
71903
|
}
|
|
71651
71904
|
enrichTimelineItemTiming(item, historyItems = []) {
|
|
@@ -71665,9 +71918,9 @@ var RuntimeTimelinePublication = class {
|
|
|
71665
71918
|
turnTimingKey(threadId2, turnId) {
|
|
71666
71919
|
return `${threadId2}:${turnId}`;
|
|
71667
71920
|
}
|
|
71668
|
-
setLiveTurnTiming(key,
|
|
71921
|
+
setLiveTurnTiming(key, timing2) {
|
|
71669
71922
|
this.liveTurnTimings.delete(key);
|
|
71670
|
-
this.liveTurnTimings.set(key,
|
|
71923
|
+
this.liveTurnTimings.set(key, timing2);
|
|
71671
71924
|
while (this.liveTurnTimings.size > LIVE_TURN_TIMING_LIMIT) {
|
|
71672
71925
|
const oldestKey = this.liveTurnTimings.keys().next().value;
|
|
71673
71926
|
if (typeof oldestKey !== "string") break;
|
|
@@ -79790,8 +80043,7 @@ var RuntimeNativeAdmission = class {
|
|
|
79790
80043
|
else if (kind === "ordinary") this.hidden.delete(thread4.id);
|
|
79791
80044
|
const old = this.entries.get(thread4.id);
|
|
79792
80045
|
this.failures.delete(thread4.id);
|
|
79793
|
-
|
|
79794
|
-
const token3 = { threadId: thread4.id, generation: ++this.sequence, executionGeneration };
|
|
80046
|
+
const token3 = old && old.kind === kind ? old.token : { threadId: thread4.id, generation: ++this.sequence, executionGeneration };
|
|
79795
80047
|
this.entries.set(thread4.id, { token: token3, kind });
|
|
79796
80048
|
try {
|
|
79797
80049
|
if (kind !== previous) this.ports.onChange?.(thread4.id, previous, kind);
|
|
@@ -79801,7 +80053,7 @@ var RuntimeNativeAdmission = class {
|
|
|
79801
80053
|
}
|
|
79802
80054
|
const pending = this.jobs.get(thread4.id);
|
|
79803
80055
|
if (pending) {
|
|
79804
|
-
this.finishWait(pending, kind);
|
|
80056
|
+
this.finishWait(pending, kind, thread4, token3);
|
|
79805
80057
|
if (!pending.started) {
|
|
79806
80058
|
this.removeQueued(pending);
|
|
79807
80059
|
this.removeJob(pending);
|
|
@@ -79809,13 +80061,20 @@ var RuntimeNativeAdmission = class {
|
|
|
79809
80061
|
}
|
|
79810
80062
|
return token3;
|
|
79811
80063
|
}
|
|
79812
|
-
ensure(id5, executionGeneration) {
|
|
79813
|
-
|
|
80064
|
+
async ensure(id5, executionGeneration) {
|
|
80065
|
+
return (await this.query(id5, executionGeneration, false)).kind;
|
|
80066
|
+
}
|
|
80067
|
+
/** 目录缺项时请求摘要,与未知准入共用单飞、退避和物理槽。 */
|
|
80068
|
+
ensureSummary(id5, executionGeneration) {
|
|
80069
|
+
return this.query(id5, executionGeneration, true);
|
|
80070
|
+
}
|
|
80071
|
+
query(id5, executionGeneration, needSummary) {
|
|
80072
|
+
if (executionGeneration !== this.execution) return Promise.resolve({ kind: "unknown" });
|
|
79814
80073
|
const known = this.kind(id5);
|
|
79815
|
-
if (known !== "unknown") return Promise.resolve(known);
|
|
80074
|
+
if (known !== "unknown" && (!needSummary || known === "subagent")) return Promise.resolve({ kind: known });
|
|
79816
80075
|
const pending = this.jobs.get(id5);
|
|
79817
|
-
if (pending) return pending.execution === this.execution ? pending.promise : Promise.resolve("unknown");
|
|
79818
|
-
if ((this.failures.get(id5) ?? 0) > this.now() || this.queue.length >= 64) return Promise.resolve("unknown");
|
|
80076
|
+
if (pending) return pending.execution === this.execution ? pending.promise : Promise.resolve({ kind: "unknown" });
|
|
80077
|
+
if ((this.failures.get(id5) ?? 0) > this.now() || this.queue.length >= 64) return Promise.resolve({ kind: "unknown" });
|
|
79819
80078
|
let resolve5;
|
|
79820
80079
|
const promise = new Promise((done) => {
|
|
79821
80080
|
resolve5 = done;
|
|
@@ -79872,11 +80131,11 @@ var RuntimeNativeAdmission = class {
|
|
|
79872
80131
|
removeJob(job) {
|
|
79873
80132
|
if (this.jobs.get(job.id) === job) this.jobs.delete(job.id);
|
|
79874
80133
|
}
|
|
79875
|
-
finishWait(job, kind) {
|
|
80134
|
+
finishWait(job, kind, summary, token3) {
|
|
79876
80135
|
if (job.settled) return;
|
|
79877
80136
|
job.settled = true;
|
|
79878
80137
|
job.cancel();
|
|
79879
|
-
job.resolve(kind);
|
|
80138
|
+
job.resolve({ kind, ...summary ? { summary, token: token3 } : {} });
|
|
79880
80139
|
}
|
|
79881
80140
|
fail(job) {
|
|
79882
80141
|
if (job.execution === this.execution) {
|
|
@@ -79910,7 +80169,7 @@ var RuntimeNativeAdmission = class {
|
|
|
79910
80169
|
this.observe(result.thread, job.execution);
|
|
79911
80170
|
const kind = this.kind(job.id);
|
|
79912
80171
|
if (kind === "unknown") this.fail(job);
|
|
79913
|
-
this.finishWait(job, kind);
|
|
80172
|
+
this.finishWait(job, kind, result.thread, this.token(job.id));
|
|
79914
80173
|
}).catch(() => {
|
|
79915
80174
|
if (!job.settled) {
|
|
79916
80175
|
this.fail(job);
|
|
@@ -80273,6 +80532,7 @@ var DEBUG_EVENTS = [
|
|
|
80273
80532
|
"ipc_recovery",
|
|
80274
80533
|
"ipc_forwarding_flow",
|
|
80275
80534
|
"notification_delivery",
|
|
80535
|
+
"ipc_thread_discovery",
|
|
80276
80536
|
"startup_timing",
|
|
80277
80537
|
"thread_settings_cache",
|
|
80278
80538
|
"thread_list_cache",
|
|
@@ -80506,6 +80766,7 @@ var SAFE_ATTRIBUTE_KEYS = {
|
|
|
80506
80766
|
"inFlight"
|
|
80507
80767
|
],
|
|
80508
80768
|
// 启动性能仅保留固定阶段耗时和汇总计数,禁止记录路径、会话或异常原文。
|
|
80769
|
+
ipc_thread_discovery: ["durationMs"],
|
|
80509
80770
|
startup_timing: [
|
|
80510
80771
|
"durationMs",
|
|
80511
80772
|
"threadCount",
|
|
@@ -81055,6 +81316,7 @@ var SAFE_PHASES = {
|
|
|
81055
81316
|
"dropped_busy",
|
|
81056
81317
|
"deadline_expired"
|
|
81057
81318
|
],
|
|
81319
|
+
ipc_thread_discovery: ["received", "ignored", "deduplicated", "capacity", "read_completed", "rejected", "stale", "published", "failed"],
|
|
81058
81320
|
startup_timing: [
|
|
81059
81321
|
"app_server_initialized",
|
|
81060
81322
|
"thread_baseline_scanned",
|
|
@@ -81748,19 +82010,19 @@ function withoutPersistentImageBytes(value, key = "", seen = /* @__PURE__ */ new
|
|
|
81748
82010
|
if (seen.has(value)) return "[circular]";
|
|
81749
82011
|
seen.add(value);
|
|
81750
82012
|
try {
|
|
81751
|
-
const
|
|
81752
|
-
if (
|
|
81753
|
-
return { type: "binary_omitted", byteSize:
|
|
82013
|
+
const object12 = value;
|
|
82014
|
+
if (object12.type === "Buffer" && Array.isArray(object12.data)) {
|
|
82015
|
+
return { type: "binary_omitted", byteSize: object12.data.length };
|
|
81754
82016
|
}
|
|
81755
|
-
if (
|
|
81756
|
-
const payload =
|
|
81757
|
-
const metadata = Object.fromEntries(Object.entries(
|
|
82017
|
+
if (object12.event === "app_server_stdout") {
|
|
82018
|
+
const payload = object12.rawPayload;
|
|
82019
|
+
const metadata = Object.fromEntries(Object.entries(object12).filter(([name2]) => name2 !== "rawPayload").map(([name2, entry]) => [name2, withoutPersistentImageBytes(entry, name2, seen)]));
|
|
81758
82020
|
return { ...metadata, rawPayload: { type: "stdout_fragment", bytes: typeof payload?.bytes === "number" ? payload.bytes : typeof payload?.fragment === "string" ? Buffer.byteLength(payload.fragment) : 0 } };
|
|
81759
82021
|
}
|
|
81760
82022
|
if (Array.isArray(value)) return value.map((entry) => withoutPersistentImageBytes(entry, key, seen));
|
|
81761
|
-
return Object.fromEntries(Object.entries(
|
|
82023
|
+
return Object.fromEntries(Object.entries(object12).map(([name2, entry]) => [
|
|
81762
82024
|
name2,
|
|
81763
|
-
withoutPersistentImageBytes(entry,
|
|
82025
|
+
withoutPersistentImageBytes(entry, object12.type === "image" && name2 === "data" ? "base64" : name2, seen)
|
|
81764
82026
|
]));
|
|
81765
82027
|
} finally {
|
|
81766
82028
|
seen.delete(value);
|
|
@@ -82854,6 +83116,7 @@ var NiumaDaemonRuntime = class {
|
|
|
82854
83116
|
}
|
|
82855
83117
|
desktopTrackers = new RuntimeDesktopIngressTrackers();
|
|
82856
83118
|
desktopIngress = new RuntimeDesktopIngress({
|
|
83119
|
+
discoverThread: (id5) => this.ipcThreadDiscovery.discover(id5),
|
|
82857
83120
|
nativeAdmission: () => this.nativeAdmission,
|
|
82858
83121
|
ensureNativeAdmission: (id5) => this.ensureNativeAdmission(id5),
|
|
82859
83122
|
requestReadFileRefresh: () => this.followerCoordination.desktopReadStateFileValue?.requestRefresh(),
|
|
@@ -83389,6 +83652,33 @@ var NiumaDaemonRuntime = class {
|
|
|
83389
83652
|
}
|
|
83390
83653
|
}
|
|
83391
83654
|
});
|
|
83655
|
+
ipcThreadDiscovery = new RuntimeIpcThreadDiscovery({
|
|
83656
|
+
eligible: (id5) => !this.lifecycle.stoppingValue && this.desktopSession.desktopIpcStateValue === "ready" && this.executionHost.appServerStateValue === "ready" && !this.archiveState.isConfirmed(id5) && !this.catalog.hasActiveTombstone(id5) && this.nativeAdmission.isVisible(id5) && !this.catalog.storeValue.getPublicThreadSummary(id5),
|
|
83657
|
+
capture: () => {
|
|
83658
|
+
const runtime = this.lifecycle.runtimeGenerationValue, ipc = this.desktopSession.ipcConnectionGenerationValue;
|
|
83659
|
+
const client = this.executionHost.appServerValue, generation = this.appServerLoads.connectionGeneration;
|
|
83660
|
+
return () => !this.lifecycle.stoppingValue && runtime === this.lifecycle.runtimeGenerationValue && ipc === this.desktopSession.ipcConnectionGenerationValue && client === this.executionHost.appServerValue && generation === this.appServerLoads.connectionGeneration;
|
|
83661
|
+
},
|
|
83662
|
+
read: (id5) => this.nativeAdmission.ensureSummary(id5, this.appServerLoads.connectionGeneration),
|
|
83663
|
+
current: (token3) => this.nativeAdmission.isCurrent(token3),
|
|
83664
|
+
enqueue: (run) => this.eventSequencer.enqueue(async () => {
|
|
83665
|
+
run();
|
|
83666
|
+
}),
|
|
83667
|
+
commit: (thread4) => {
|
|
83668
|
+
this.directoryAuthority.begin(false);
|
|
83669
|
+
this.catalog.upsertAuthoritativeThreadSummary(thread4);
|
|
83670
|
+
this.emitEvent(this.publication.threadUpdatedEvent(thread4.id, "app_server", nowSeconds()));
|
|
83671
|
+
this.activityPublication.publishGlobalStatusIfChanged();
|
|
83672
|
+
},
|
|
83673
|
+
diagnostic: (threadId2, phase, elapsedMs) => this.diagnostics.writeDebug({
|
|
83674
|
+
component: "daemon",
|
|
83675
|
+
channel: "ipc",
|
|
83676
|
+
event: "ipc_thread_discovery",
|
|
83677
|
+
threadId: threadId2,
|
|
83678
|
+
phase,
|
|
83679
|
+
attributes: { durationMs: elapsedMs }
|
|
83680
|
+
})
|
|
83681
|
+
});
|
|
83392
83682
|
async ensureNativeAdmission(id5) {
|
|
83393
83683
|
return !this.lifecycle.stoppingValue && !this.archiveState.isConfirmed(id5) && await this.nativeAdmission.ensure(id5, this.appServerLoads.connectionGeneration) === "ordinary";
|
|
83394
83684
|
}
|
|
@@ -84075,7 +84365,7 @@ var NiumaDaemonRuntime = class {
|
|
|
84075
84365
|
isBlocked: isStartBlockedByLifecycle
|
|
84076
84366
|
});
|
|
84077
84367
|
// 所有 runtime 与 coordinator 共用同一审计实例,确保 thread-scope 事件可关联当前 trace。
|
|
84078
|
-
threadLoadReports = new ThreadLoadReports();
|
|
84368
|
+
threadLoadReports = new ThreadLoadReports(Date.now, () => this.followerOpenTraceAudit);
|
|
84079
84369
|
followerOpenTraceAudit;
|
|
84080
84370
|
// 异步选择只等待目录;端口在实际调用时读取,不能提前冻结Owner或缓存。
|
|
84081
84371
|
settingsSelection = new RuntimeSettingsSelection({
|
|
@@ -84413,6 +84703,34 @@ var NiumaDaemonRuntime = class {
|
|
|
84413
84703
|
});
|
|
84414
84704
|
};
|
|
84415
84705
|
|
|
84706
|
+
// apps/desktop/src/daemon/thread-load-record.ts
|
|
84707
|
+
import { z as z17 } from "zod";
|
|
84708
|
+
var LoadRecordSchema = z17.object({
|
|
84709
|
+
schema_version: z17.literal(3),
|
|
84710
|
+
record_type: z17.enum(["load_start", "load_sample", "load_terminal", "load_close"]),
|
|
84711
|
+
load_id: z17.string().uuid(),
|
|
84712
|
+
thread_id: z17.string().min(1).max(256),
|
|
84713
|
+
sequence: z17.number().int().nonnegative(),
|
|
84714
|
+
occurred_at_ms: z17.number().int().nonnegative().max(864e13),
|
|
84715
|
+
clock: z17.enum(["client", "daemon"]),
|
|
84716
|
+
phase: z17.enum([...CLIENT_LOAD_PHASES, "open_received", "identity_ready", "lease_acquired", "shell_sent", "history_sent", "stream_closed", "failed", "cancelled", "superseded", "closed", "expired"]),
|
|
84717
|
+
elapsed_ms: z17.number().int().min(0).max(9e5),
|
|
84718
|
+
event_at_ms: z17.number().int().min(1).max(864e13).optional(),
|
|
84719
|
+
source_transport: z17.enum(["local", "direct", "relay"]).optional(),
|
|
84720
|
+
client_class: z17.enum(["web", "ios", "other"]).optional(),
|
|
84721
|
+
title: z17.string().max(256).optional(),
|
|
84722
|
+
lease_id: z17.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u).optional(),
|
|
84723
|
+
trace_id: z17.string().regex(/^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u).optional(),
|
|
84724
|
+
terminal_phase: z17.enum(["request_started", "snapshot_received", "history_ready", "open_received", "identity_ready", "lease_acquired", "shell_sent", "history_sent"]).optional(),
|
|
84725
|
+
reason: z17.enum(["open_rejected", "history_failed", "left_view", "user_cancelled", "stream_replaced"]).optional()
|
|
84726
|
+
}).strict().superRefine((v, ctx) => {
|
|
84727
|
+
const fail18 = () => ctx.addIssue({ code: "custom", message: "invalid_load_record" });
|
|
84728
|
+
if (v.record_type === "load_start" && (v.phase !== "open_received" || v.clock !== "daemon" || !v.source_transport)) fail18();
|
|
84729
|
+
if (v.record_type === "load_terminal" && !["failed", "cancelled", "superseded", "expired"].includes(v.phase)) fail18();
|
|
84730
|
+
if (v.record_type === "load_close" && (v.phase !== "closed" || v.clock !== "daemon")) fail18();
|
|
84731
|
+
if (v.record_type === "load_sample" && (v.clock === "client" ? !CLIENT_LOAD_PHASES.includes(v.phase) : !["open_received", "identity_ready", "lease_acquired", "shell_sent", "history_sent", "stream_closed"].includes(v.phase))) fail18();
|
|
84732
|
+
});
|
|
84733
|
+
|
|
84416
84734
|
// apps/desktop/src/daemon/follower-open-trace.ts
|
|
84417
84735
|
import { randomUUID as randomUUID52 } from "node:crypto";
|
|
84418
84736
|
import path51 from "node:path";
|
|
@@ -84421,6 +84739,7 @@ var MAX_FILE_BYTES2 = 5 * 1024 * 1024;
|
|
|
84421
84739
|
var MAX_TOTAL_BYTES2 = 20 * 1024 * 1024;
|
|
84422
84740
|
var MAX_LINE_BYTES2 = 64 * 1024;
|
|
84423
84741
|
var MAX_DIRECTORY_ENTRIES3 = 256;
|
|
84742
|
+
var MAX_PROCESSED_LINES2 = 1e4;
|
|
84424
84743
|
var SUBSCRIPTION_TRACE_SAFE_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,255}$/u;
|
|
84425
84744
|
var FOLLOWER_OPEN_TRACE_TITLE_MAX_LENGTH = 256;
|
|
84426
84745
|
var TRANSPORTS = /* @__PURE__ */ new Set(["local", "direct", "relay"]);
|
|
@@ -84582,6 +84901,9 @@ function isOptionalTraceTitle(value) {
|
|
|
84582
84901
|
function hasOnlyKeys2(value, allowed) {
|
|
84583
84902
|
return value !== null && typeof value === "object" && !Array.isArray(value) && Object.keys(value).every((key) => allowed.includes(key));
|
|
84584
84903
|
}
|
|
84904
|
+
function isRecent(value, nowMs) {
|
|
84905
|
+
return value <= nowMs && nowMs - value <= DAEMON_LOG_RETENTION_MS;
|
|
84906
|
+
}
|
|
84585
84907
|
function dateFileName2(timestampMs) {
|
|
84586
84908
|
return `${new Date(timestampMs).toISOString().slice(0, 10)}.ndjson`;
|
|
84587
84909
|
}
|
|
@@ -84688,6 +85010,10 @@ function parseRecord2(line) {
|
|
|
84688
85010
|
}
|
|
84689
85011
|
if (value === null || typeof value !== "object" || Array.isArray(value)) return null;
|
|
84690
85012
|
const record25 = value;
|
|
85013
|
+
if (record25.schema_version === 3) {
|
|
85014
|
+
const parsed = LoadRecordSchema.safeParse(record25);
|
|
85015
|
+
return parsed.success ? parsed.data : null;
|
|
85016
|
+
}
|
|
84691
85017
|
if (record25.schema_version === 1) return parseV1Record(record25);
|
|
84692
85018
|
if (record25.schema_version === 2) return parseV2Record(record25);
|
|
84693
85019
|
return null;
|
|
@@ -84723,6 +85049,46 @@ function readPrivateTraceFile(file, remainingBytes, storage) {
|
|
|
84723
85049
|
return { bytesRead: error2 instanceof PrivateLogFileError ? error2.bytesRead : 0, incomplete: true };
|
|
84724
85050
|
}
|
|
84725
85051
|
}
|
|
85052
|
+
function readRecords(runtimeDir, nowMs, storage) {
|
|
85053
|
+
if (!Number.isFinite(nowMs)) return { records: [], incomplete: true };
|
|
85054
|
+
const candidates = listPrivateTraceFiles(runtimeDir, storage);
|
|
85055
|
+
const records = [];
|
|
85056
|
+
let incomplete = candidates.incomplete;
|
|
85057
|
+
let totalBytes = 0;
|
|
85058
|
+
let processedLines = 0;
|
|
85059
|
+
for (const filePath of candidates.files) {
|
|
85060
|
+
if (totalBytes >= MAX_TOTAL_BYTES2) {
|
|
85061
|
+
incomplete = true;
|
|
85062
|
+
break;
|
|
85063
|
+
}
|
|
85064
|
+
const file = readPrivateTraceFile(filePath, MAX_TOTAL_BYTES2 - totalBytes, storage);
|
|
85065
|
+
totalBytes += file.bytesRead;
|
|
85066
|
+
if (file.incomplete) incomplete = true;
|
|
85067
|
+
if (file.content === void 0) continue;
|
|
85068
|
+
let end = file.content.endsWith("\n") ? file.content.length - 1 : file.content.length;
|
|
85069
|
+
while (end > 0 && processedLines < MAX_PROCESSED_LINES2) {
|
|
85070
|
+
const newline = file.content.lastIndexOf("\n", end - 1);
|
|
85071
|
+
const start = newline + 1;
|
|
85072
|
+
const length = end - start;
|
|
85073
|
+
processedLines += 1;
|
|
85074
|
+
if (length > 0 && length <= MAX_LINE_BYTES2) {
|
|
85075
|
+
const line = file.content.slice(start, end);
|
|
85076
|
+
if (Buffer.byteLength(line, "utf8") <= MAX_LINE_BYTES2) {
|
|
85077
|
+
const record25 = parseRecord2(line);
|
|
85078
|
+
if (record25 && timestampOf(record25) <= nowMs) records.push(record25);
|
|
85079
|
+
else incomplete = true;
|
|
85080
|
+
} else incomplete = true;
|
|
85081
|
+
} else if (length > 0) incomplete = true;
|
|
85082
|
+
end = Math.max(0, newline);
|
|
85083
|
+
}
|
|
85084
|
+
if (totalBytes >= MAX_TOTAL_BYTES2 || processedLines >= MAX_PROCESSED_LINES2) {
|
|
85085
|
+
if (end > 0 || filePath !== candidates.files.at(-1)) incomplete = true;
|
|
85086
|
+
break;
|
|
85087
|
+
}
|
|
85088
|
+
}
|
|
85089
|
+
records.reverse();
|
|
85090
|
+
return { records, incomplete: incomplete || hasIncompleteSubscriptionHistory(records, nowMs) };
|
|
85091
|
+
}
|
|
84726
85092
|
function readPersistedSequenceFloor(runtimeDir, storage) {
|
|
84727
85093
|
let maximum = 0;
|
|
84728
85094
|
let totalBytes = 0;
|
|
@@ -84741,6 +85107,56 @@ function readPersistedSequenceFloor(runtimeDir, storage) {
|
|
|
84741
85107
|
}
|
|
84742
85108
|
return maximum;
|
|
84743
85109
|
}
|
|
85110
|
+
function subscriptionIdentity(record25) {
|
|
85111
|
+
return `${record25.trace_id}\0${record25.thread_id}\0${record25.lease_epoch}`;
|
|
85112
|
+
}
|
|
85113
|
+
function occursAfterStart(record25, trace) {
|
|
85114
|
+
return record25.occurred_at_ms > trace.opened_at_ms || record25.occurred_at_ms === trace.opened_at_ms && record25.sequence > trace.sequence;
|
|
85115
|
+
}
|
|
85116
|
+
function occursBeforeClose(record25, close) {
|
|
85117
|
+
return record25.occurred_at_ms < close.occurred_at_ms || record25.occurred_at_ms === close.occurred_at_ms && record25.sequence < close.sequence;
|
|
85118
|
+
}
|
|
85119
|
+
function hasIncompleteSubscriptionHistory(records, nowMs) {
|
|
85120
|
+
const starts = /* @__PURE__ */ new Map();
|
|
85121
|
+
const eventsByIdentity = /* @__PURE__ */ new Map();
|
|
85122
|
+
const closesByIdentity = /* @__PURE__ */ new Map();
|
|
85123
|
+
for (const record25 of records) {
|
|
85124
|
+
if (record25.record_type === "subscription_start") {
|
|
85125
|
+
const identity6 = subscriptionIdentity(record25);
|
|
85126
|
+
if (starts.has(identity6)) return true;
|
|
85127
|
+
starts.set(identity6, record25);
|
|
85128
|
+
continue;
|
|
85129
|
+
}
|
|
85130
|
+
if (record25.record_type === "lease_event" || record25.record_type === "subscription_event") {
|
|
85131
|
+
const identity6 = subscriptionIdentity(record25);
|
|
85132
|
+
const events = eventsByIdentity.get(identity6) ?? [];
|
|
85133
|
+
events.push(record25);
|
|
85134
|
+
eventsByIdentity.set(identity6, events);
|
|
85135
|
+
continue;
|
|
85136
|
+
}
|
|
85137
|
+
if (record25.record_type === "subscription_close") {
|
|
85138
|
+
const identity6 = subscriptionIdentity(record25);
|
|
85139
|
+
const closes = closesByIdentity.get(identity6) ?? [];
|
|
85140
|
+
closes.push(record25);
|
|
85141
|
+
closesByIdentity.set(identity6, closes);
|
|
85142
|
+
}
|
|
85143
|
+
}
|
|
85144
|
+
for (const [identity6, events] of eventsByIdentity) {
|
|
85145
|
+
const start = starts.get(identity6);
|
|
85146
|
+
if (!start || events.some((event) => !occursAfterStart(event, start))) return true;
|
|
85147
|
+
}
|
|
85148
|
+
for (const start of starts.values()) {
|
|
85149
|
+
const identity6 = subscriptionIdentity(start);
|
|
85150
|
+
const closes = closesByIdentity.get(identity6) ?? [];
|
|
85151
|
+
if (closes.some((close2) => !occursAfterStart(close2, start))) return true;
|
|
85152
|
+
if (closes.length > 1) return true;
|
|
85153
|
+
const close = closes[0];
|
|
85154
|
+
if (close && (eventsByIdentity.get(identity6) ?? []).some((event) => !occursBeforeClose(event, close))) return true;
|
|
85155
|
+
if (!close && !isRecent(start.opened_at_ms, nowMs)) return true;
|
|
85156
|
+
}
|
|
85157
|
+
if ([...closesByIdentity.keys()].some((identity6) => !starts.has(identity6))) return true;
|
|
85158
|
+
return false;
|
|
85159
|
+
}
|
|
84744
85160
|
var FollowerOpenTraceAuditWriter = class {
|
|
84745
85161
|
constructor(runtimeDir, nowMs, files) {
|
|
84746
85162
|
this.runtimeDir = runtimeDir;
|
|
@@ -84754,6 +85170,30 @@ var FollowerOpenTraceAuditWriter = class {
|
|
|
84754
85170
|
nowMs;
|
|
84755
85171
|
files;
|
|
84756
85172
|
sequence;
|
|
85173
|
+
loadEpoch = 0;
|
|
85174
|
+
loadIds;
|
|
85175
|
+
reserveLoadId(id5) {
|
|
85176
|
+
if (!this.loadIds) {
|
|
85177
|
+
try {
|
|
85178
|
+
this.ensureTraceDirectory(path51.join(this.runtimeDir, TRACE_DIRECTORY_NAME));
|
|
85179
|
+
} catch {
|
|
85180
|
+
return false;
|
|
85181
|
+
}
|
|
85182
|
+
const read = readRecords(this.runtimeDir, this.nowMs(), this.files);
|
|
85183
|
+
if (read.incomplete) return false;
|
|
85184
|
+
this.loadIds = new Set(read.records.filter((r) => r.schema_version === 3).map((r) => r.load_id));
|
|
85185
|
+
}
|
|
85186
|
+
if (this.loadIds.size >= 1e4 || this.loadIds.has(id5)) return false;
|
|
85187
|
+
this.loadIds.add(id5);
|
|
85188
|
+
return true;
|
|
85189
|
+
}
|
|
85190
|
+
loadGeneration() {
|
|
85191
|
+
return this.loadEpoch;
|
|
85192
|
+
}
|
|
85193
|
+
recordLoad(input) {
|
|
85194
|
+
const parsed = LoadRecordSchema.safeParse({ ...input, schema_version: 3, sequence: this.nextSequence() });
|
|
85195
|
+
if (parsed.success) this.write(parsed.data);
|
|
85196
|
+
}
|
|
84757
85197
|
traceDirectoryInitialized = false;
|
|
84758
85198
|
/** 只缓存当前追加文件;日期切换或清空后重新发现已有分片。 */
|
|
84759
85199
|
appendFilePath;
|
|
@@ -84887,6 +85327,7 @@ var FollowerOpenTraceAuditWriter = class {
|
|
|
84887
85327
|
for (const entry of matching) this.files.remove(entry.file);
|
|
84888
85328
|
}
|
|
84889
85329
|
this.appendFilePath = void 0;
|
|
85330
|
+
this.loadEpoch += 1;
|
|
84890
85331
|
this.activeTraces.clear();
|
|
84891
85332
|
this.activeSubscriptionTraces.clear();
|
|
84892
85333
|
this.activeSubscriptionTraceHandles.clear();
|
|
@@ -85126,16 +85567,16 @@ import { dirname as dirname5, join as join3 } from "node:path";
|
|
|
85126
85567
|
|
|
85127
85568
|
// apps/desktop/src/daemon/async-input-notification-store.ts
|
|
85128
85569
|
import { createHash as createHash41 } from "node:crypto";
|
|
85129
|
-
import { z as
|
|
85570
|
+
import { z as z18 } from "zod";
|
|
85130
85571
|
var ASYNC_INPUT_NOTIFICATION_MAX_BYTES = 2 * 1024 * 1024;
|
|
85131
|
-
var identityText =
|
|
85132
|
-
var entrySchema2 =
|
|
85133
|
-
key:
|
|
85572
|
+
var identityText = z18.string().min(1).max(8e3);
|
|
85573
|
+
var entrySchema2 = z18.object({
|
|
85574
|
+
key: z18.string().regex(/^[a-f0-9]{64}$/),
|
|
85134
85575
|
threadId: identityText,
|
|
85135
85576
|
turnId: identityText,
|
|
85136
|
-
stage:
|
|
85577
|
+
stage: z18.enum(["admitted", "sent"])
|
|
85137
85578
|
}).strict();
|
|
85138
|
-
var documentSchema2 =
|
|
85579
|
+
var documentSchema2 = z18.object({ version: z18.literal(1), entries: z18.array(entrySchema2).max(4096) }).strict();
|
|
85139
85580
|
var AsyncInputNotificationStore = class _AsyncInputNotificationStore {
|
|
85140
85581
|
constructor(journal, document) {
|
|
85141
85582
|
this.journal = journal;
|