oasis_test_v2 2.2.23 → 2.2.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/index.js +1138 -909
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4370,19 +4370,19 @@ var init_state = __esm({
|
|
|
4370
4370
|
reviewMap = /* @__PURE__ */ new Map();
|
|
4371
4371
|
mutationList = [];
|
|
4372
4372
|
emittedList = [];
|
|
4373
|
-
constructor(
|
|
4374
|
-
this.workorder = { ...
|
|
4375
|
-
for (const n of
|
|
4376
|
-
this.edgeList =
|
|
4377
|
-
this.requirementList =
|
|
4378
|
-
for (const w2 of
|
|
4379
|
-
this.artifactList =
|
|
4380
|
-
this.workInputList =
|
|
4381
|
-
for (const i of
|
|
4382
|
-
this.recipientList =
|
|
4383
|
-
this.replyList =
|
|
4384
|
-
this.attachmentList =
|
|
4385
|
-
for (const r of
|
|
4373
|
+
constructor(snapshot2) {
|
|
4374
|
+
this.workorder = { ...snapshot2.workorder };
|
|
4375
|
+
for (const n of snapshot2.nodes) this.nodeMap.set(n.id, { ...n });
|
|
4376
|
+
this.edgeList = snapshot2.edges.map((e) => ({ ...e }));
|
|
4377
|
+
this.requirementList = snapshot2.requirements.map((r) => ({ ...r }));
|
|
4378
|
+
for (const w2 of snapshot2.works) this.workMap.set(w2.id, { ...w2 });
|
|
4379
|
+
this.artifactList = snapshot2.artifacts.map((a) => ({ ...a }));
|
|
4380
|
+
this.workInputList = snapshot2.workInputs.map((i) => ({ ...i }));
|
|
4381
|
+
for (const i of snapshot2.issues) this.issueMap.set(i.id, { ...i });
|
|
4382
|
+
this.recipientList = snapshot2.issueRecipients.map((r) => ({ ...r }));
|
|
4383
|
+
this.replyList = snapshot2.issueReplies.map((r) => ({ ...r }));
|
|
4384
|
+
this.attachmentList = snapshot2.issueAttachments.map((a) => ({ ...a }));
|
|
4385
|
+
for (const r of snapshot2.reviews) this.reviewMap.set(r.id, { ...r });
|
|
4386
4386
|
}
|
|
4387
4387
|
/* ── 读 ── */
|
|
4388
4388
|
node(id) {
|
|
@@ -7761,15 +7761,15 @@ var require_pg_connection_string = __commonJS({
|
|
|
7761
7761
|
if (config2.sslcert || config2.sslkey || config2.sslrootcert || config2.sslmode) {
|
|
7762
7762
|
config2.ssl = {};
|
|
7763
7763
|
}
|
|
7764
|
-
const
|
|
7764
|
+
const fs48 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
|
|
7765
7765
|
if (config2.sslcert) {
|
|
7766
|
-
config2.ssl.cert =
|
|
7766
|
+
config2.ssl.cert = fs48.readFileSync(config2.sslcert).toString();
|
|
7767
7767
|
}
|
|
7768
7768
|
if (config2.sslkey) {
|
|
7769
|
-
config2.ssl.key =
|
|
7769
|
+
config2.ssl.key = fs48.readFileSync(config2.sslkey).toString();
|
|
7770
7770
|
}
|
|
7771
7771
|
if (config2.sslrootcert) {
|
|
7772
|
-
config2.ssl.ca =
|
|
7772
|
+
config2.ssl.ca = fs48.readFileSync(config2.sslrootcert).toString();
|
|
7773
7773
|
}
|
|
7774
7774
|
if (options.useLibpqCompat && config2.uselibpqcompat) {
|
|
7775
7775
|
throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
|
|
@@ -9706,15 +9706,15 @@ var require_lib = __commonJS({
|
|
|
9706
9706
|
"../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js"(exports2, module2) {
|
|
9707
9707
|
"use strict";
|
|
9708
9708
|
var path43 = require("path");
|
|
9709
|
-
var
|
|
9709
|
+
var fs48 = require("fs");
|
|
9710
9710
|
var helper = require_helper();
|
|
9711
9711
|
module2.exports = function(connInfo, cb) {
|
|
9712
9712
|
var file = helper.getFileName();
|
|
9713
|
-
|
|
9713
|
+
fs48.stat(file, function(err, stat3) {
|
|
9714
9714
|
if (err || !helper.usePgPass(stat3, file)) {
|
|
9715
9715
|
return cb(void 0);
|
|
9716
9716
|
}
|
|
9717
|
-
var st =
|
|
9717
|
+
var st = fs48.createReadStream(file);
|
|
9718
9718
|
helper.getPassword(connInfo, st, cb);
|
|
9719
9719
|
});
|
|
9720
9720
|
};
|
|
@@ -14048,8 +14048,8 @@ var init_bus = __esm({
|
|
|
14048
14048
|
*/
|
|
14049
14049
|
async applyRecord(record8) {
|
|
14050
14050
|
await this.store.transaction(async (tx) => {
|
|
14051
|
-
const
|
|
14052
|
-
const state = new WorkorderState(
|
|
14051
|
+
const snapshot2 = await tx.loadWorkorder(record8.workorderId);
|
|
14052
|
+
const state = new WorkorderState(snapshot2 ?? emptySnapshotPlaceholder(record8));
|
|
14053
14053
|
const ctx = {
|
|
14054
14054
|
seq: record8.seq,
|
|
14055
14055
|
at: record8.createdAt,
|
|
@@ -14223,10 +14223,10 @@ var init_bus = __esm({
|
|
|
14223
14223
|
await tx.lockWorkorder(workorderId);
|
|
14224
14224
|
if (await tx.hasPendingEvents(workorderId)) return { emitted: 0, terminated: false };
|
|
14225
14225
|
settledAt = this.processedSeq.get(workorderId) ?? 0;
|
|
14226
|
-
const
|
|
14227
|
-
if (!
|
|
14228
|
-
if (
|
|
14229
|
-
const state = new WorkorderState(
|
|
14226
|
+
const snapshot2 = await tx.loadWorkorder(workorderId);
|
|
14227
|
+
if (!snapshot2) return { emitted: 0, terminated: false };
|
|
14228
|
+
if (snapshot2.workorder.lifecycle !== "active") return { emitted: 0, terminated: false };
|
|
14229
|
+
const state = new WorkorderState(snapshot2);
|
|
14230
14230
|
const continuationPolicies = /* @__PURE__ */ new Map();
|
|
14231
14231
|
if (this.io.continuationPolicy) {
|
|
14232
14232
|
for (const node2 of state.liveNodes()) {
|
|
@@ -14277,14 +14277,14 @@ var init_bus = __esm({
|
|
|
14277
14277
|
return this.store.transaction(async (tx) => {
|
|
14278
14278
|
const record8 = await tx.claimNextEvent(this.clock.now(), this.recoverAppliedBefore());
|
|
14279
14279
|
if (!record8) return null;
|
|
14280
|
-
const
|
|
14281
|
-
if (
|
|
14280
|
+
const snapshot2 = await tx.loadWorkorder(record8.workorderId);
|
|
14281
|
+
if (snapshot2?.workorder.doneAt && record8.event.kind !== "work.content_edited") {
|
|
14282
14282
|
await tx.applyMutations(record8.workorderId, [{
|
|
14283
14283
|
t: "workorder.update",
|
|
14284
14284
|
patch: { doneAt: null }
|
|
14285
14285
|
}]);
|
|
14286
14286
|
}
|
|
14287
|
-
const state = new WorkorderState(
|
|
14287
|
+
const state = new WorkorderState(snapshot2 ?? emptySnapshotPlaceholder(record8));
|
|
14288
14288
|
const ctx = {
|
|
14289
14289
|
seq: record8.seq,
|
|
14290
14290
|
at: record8.createdAt,
|
|
@@ -14332,9 +14332,9 @@ var init_bus = __esm({
|
|
|
14332
14332
|
/* ═══════════════════════ 收敛断言(测试用) ═══════════════════════ */
|
|
14333
14333
|
async assertConvergence(workorderId) {
|
|
14334
14334
|
return this.store.transaction(async (tx) => {
|
|
14335
|
-
const
|
|
14336
|
-
if (!
|
|
14337
|
-
return assessConvergence(new WorkorderState(
|
|
14335
|
+
const snapshot2 = await tx.loadWorkorder(workorderId);
|
|
14336
|
+
if (!snapshot2) return { stuck: false, codes: [] };
|
|
14337
|
+
return assessConvergence(new WorkorderState(snapshot2), {
|
|
14338
14338
|
seq: 0,
|
|
14339
14339
|
at: this.clock.now(),
|
|
14340
14340
|
actorId: SYSTEM_ACTOR,
|
|
@@ -16198,6 +16198,7 @@ function makeProduceResumeFallback(first, spawnFallback) {
|
|
|
16198
16198
|
let active = first;
|
|
16199
16199
|
let fellBack = false;
|
|
16200
16200
|
let terminal;
|
|
16201
|
+
let cancelled = false;
|
|
16201
16202
|
const fanOut = (chunk) => {
|
|
16202
16203
|
if (outCbs.length) for (const cb of outCbs) cb(chunk);
|
|
16203
16204
|
else outBuf.push(chunk);
|
|
@@ -16242,7 +16243,7 @@ function makeProduceResumeFallback(first, spawnFallback) {
|
|
|
16242
16243
|
};
|
|
16243
16244
|
wire(first);
|
|
16244
16245
|
first.onExit((info) => {
|
|
16245
|
-
if (fellBack || sawOutput || !isSessionNotFound(info)) {
|
|
16246
|
+
if (cancelled || fellBack || sawOutput || !isSessionNotFound(info)) {
|
|
16246
16247
|
fireTerminal(info);
|
|
16247
16248
|
return;
|
|
16248
16249
|
}
|
|
@@ -16252,6 +16253,8 @@ function makeProduceResumeFallback(first, spawnFallback) {
|
|
|
16252
16253
|
active = second;
|
|
16253
16254
|
wire(second);
|
|
16254
16255
|
second.onExit((info2) => fireTerminal(info2));
|
|
16256
|
+
if (cancelled) void second.kill().catch(() => {
|
|
16257
|
+
});
|
|
16255
16258
|
},
|
|
16256
16259
|
// 回落连 spawn 都起不来(节点掉线等)→ 把原始 session-not-found 如实上报,交常规重试兜底。
|
|
16257
16260
|
() => fireTerminal(info)
|
|
@@ -16264,7 +16267,10 @@ function makeProduceResumeFallback(first, spawnFallback) {
|
|
|
16264
16267
|
// 稳定关联 id:回落后底层会话换了,trace 仍以同一个 id 归一。
|
|
16265
16268
|
id: stableId2,
|
|
16266
16269
|
// 绑到**当下**的 active(回落后会换人),不能在构造时快照。
|
|
16267
|
-
kill: () =>
|
|
16270
|
+
kill: () => {
|
|
16271
|
+
cancelled = true;
|
|
16272
|
+
return active.kill();
|
|
16273
|
+
},
|
|
16268
16274
|
// 四条流 + 退出走本代理的缓冲扇出:订阅者可能晚到、底层还会换人,都不能直接透传。
|
|
16269
16275
|
onExit: (cb) => {
|
|
16270
16276
|
if (terminal) {
|
|
@@ -17824,7 +17830,7 @@ ${supplemental.taskAppend.trim()}
|
|
|
17824
17830
|
dispatchId: attempt
|
|
17825
17831
|
};
|
|
17826
17832
|
const first = await this.opts.adapter.spawn(job);
|
|
17827
|
-
const session = resumeSession ? makeProduceResumeFallback(first, () => this.opts.adapter.spawn({ ...job, resumeRuntimeSession: false })) : first;
|
|
17833
|
+
const session = resumeSession && !job.execution ? makeProduceResumeFallback(first, () => this.opts.adapter.spawn({ ...job, resumeRuntimeSession: false })) : first;
|
|
17828
17834
|
if (!this.isSpawnAttemptCurrent(jobKey, attempt)) {
|
|
17829
17835
|
try {
|
|
17830
17836
|
await session.kill();
|
|
@@ -17948,7 +17954,8 @@ ${supplemental.taskAppend.trim()}
|
|
|
17948
17954
|
const reason = classifyExitReason(args.info);
|
|
17949
17955
|
return reason === args.info.reason ? args.info : { ...args.info, reason };
|
|
17950
17956
|
})();
|
|
17951
|
-
|
|
17957
|
+
const ownsSlot = this.inFlight.get(jobKey) === session;
|
|
17958
|
+
if (ownsSlot) {
|
|
17952
17959
|
this.inFlight.delete(jobKey);
|
|
17953
17960
|
this.inFlightActor.delete(jobKey);
|
|
17954
17961
|
this.inFlightStartedAt.delete(jobKey);
|
|
@@ -17963,7 +17970,7 @@ ${supplemental.taskAppend.trim()}
|
|
|
17963
17970
|
}
|
|
17964
17971
|
const seqAtExit = kernel.model.lastSeq.get(spec.artifactId) ?? 0;
|
|
17965
17972
|
const exitSessionKey = this.produceSessionKeyFor(spec);
|
|
17966
|
-
if (exitSessionKey) {
|
|
17973
|
+
if (exitSessionKey && ownsSlot) {
|
|
17967
17974
|
const prev = decodeProduceSession(this.produceSessions.get(exitSessionKey));
|
|
17968
17975
|
if (prev) {
|
|
17969
17976
|
const isWholeProduce = spec.action === "produce" && spec.part === void 0;
|
|
@@ -20943,9 +20950,9 @@ var init_kernel_bridge = __esm({
|
|
|
20943
20950
|
if (!args.actor.startsWith("actor:human:")) throw new Error("\u6062\u590D\u51B3\u5B9A\u9700\u8981\u4EBA\u660E\u786E\u786E\u8BA4");
|
|
20944
20951
|
if (!args.reason.trim()) throw new Error("\u6062\u590D\u51B3\u5B9A\u5FC5\u987B\u8BF4\u660E\u91C7\u7528\u7684\u65B9\u6848");
|
|
20945
20952
|
const wid = this.wo(args.artifactId);
|
|
20946
|
-
const
|
|
20947
|
-
const gap =
|
|
20948
|
-
const escalation =
|
|
20953
|
+
const snapshot2 = await this.store.transaction((tx) => tx.loadWorkorder(wid));
|
|
20954
|
+
const gap = snapshot2?.issues.find((i) => i.id === args.gapId && i.kind === "gap" && i.aboutNodeId === args.artifactId);
|
|
20955
|
+
const escalation = snapshot2?.issues.find((i) => i.id === args.escalationId && i.kind === "escalation" && i.aboutNodeId === args.artifactId);
|
|
20949
20956
|
if (!gap || !escalation || escalation.gapId !== gap.id) throw new Error("\u6062\u590D\u5361\u7684\u7F3A\u53E3\u4E0E\u4E0A\u62A5\u5173\u8054\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u786E\u8BA4");
|
|
20950
20957
|
const events = [];
|
|
20951
20958
|
for (const issue2 of [gap, escalation]) if (!issue2.resolvedAt) events.push({
|
|
@@ -21437,22 +21444,22 @@ var init_kernel_bridge = __esm({
|
|
|
21437
21444
|
async decideContinuation(draftId, actor, approve, reason) {
|
|
21438
21445
|
const review = this.model.pendingReviews.get(draftId);
|
|
21439
21446
|
if (!review?.continuation || !review.workspace) throw new Error("\u7EED\u8DD1\u5BA1\u6279\u4E0D\u5B58\u5728\u6216\u5DF2\u5904\u7406");
|
|
21440
|
-
const
|
|
21441
|
-
const node2 =
|
|
21447
|
+
const snapshot2 = await this.store.transaction((tx) => tx.loadWorkorder(review.workspace));
|
|
21448
|
+
const node2 = snapshot2?.nodes.find((n) => n.id === review.continuation.nodeId);
|
|
21442
21449
|
const request2 = node2?.continuationBudget?.request;
|
|
21443
|
-
if (!actor.startsWith("actor:human:") || !
|
|
21450
|
+
if (!actor.startsWith("actor:human:") || !snapshot2 || continuationApprover(new WorkorderState(snapshot2)) !== actor) throw new Error("\u4EC5\u5DE5\u5355\u4EBA\u7C7B\u8D1F\u8D23\u4EBA\u53EF\u4EE5\u5BA1\u6279\u7EED\u8DD1\u989D\u5EA6");
|
|
21444
21451
|
if (!request2 || request2.id !== draftId || request2.decision !== "pending" || node2?.cancelledAt) throw new Error("\u7EED\u8DD1\u5BA1\u6279\u5DF2\u5904\u7406\u6216\u5931\u6548");
|
|
21445
21452
|
const expectedAuthorized = Math.max(
|
|
21446
21453
|
node2.continuationBudget.authorizedRounds,
|
|
21447
|
-
continuationUsedRounds(new WorkorderState(
|
|
21454
|
+
continuationUsedRounds(new WorkorderState(snapshot2), node2.id)
|
|
21448
21455
|
) + request2.rounds;
|
|
21449
21456
|
await this.commit({
|
|
21450
|
-
companyId:
|
|
21451
|
-
workorderId:
|
|
21457
|
+
companyId: snapshot2.workorder.companyId,
|
|
21458
|
+
workorderId: snapshot2.workorder.id,
|
|
21452
21459
|
actorId: actor,
|
|
21453
|
-
event: { kind: "continuation.decided", workorderId:
|
|
21460
|
+
event: { kind: "continuation.decided", workorderId: snapshot2.workorder.id, nodeId: node2.id, requestId: draftId, approve, reason }
|
|
21454
21461
|
});
|
|
21455
|
-
const after = await this.store.transaction((tx) => tx.loadWorkorder(
|
|
21462
|
+
const after = await this.store.transaction((tx) => tx.loadWorkorder(snapshot2.workorder.id));
|
|
21456
21463
|
const afterBudget = after?.nodes.find((n) => n.id === node2.id)?.continuationBudget;
|
|
21457
21464
|
const decided = afterBudget?.request;
|
|
21458
21465
|
const applied = approve ? (afterBudget?.authorizedRounds ?? 0) >= expectedAuthorized : decided?.id === draftId && (decided.decision === "denied" || decided.decision === "completed");
|
|
@@ -23427,17 +23434,17 @@ function parseResultUsage(value2) {
|
|
|
23427
23434
|
const oneHour = usageNum(cache["ephemeral_1h_input_tokens"]);
|
|
23428
23435
|
return fiveMinute == null && oneHour == null ? void 0 : (fiveMinute ?? 0) + (oneHour ?? 0);
|
|
23429
23436
|
})();
|
|
23430
|
-
const
|
|
23437
|
+
const snapshot2 = {
|
|
23431
23438
|
input: usageNum(usage["input_tokens"]),
|
|
23432
23439
|
output: usageNum(usage["output_tokens"]),
|
|
23433
23440
|
cacheRead: usageNum(usage["cache_read_input_tokens"]),
|
|
23434
23441
|
cacheCreation
|
|
23435
23442
|
};
|
|
23436
|
-
return Object.values(
|
|
23443
|
+
return Object.values(snapshot2).some((v2) => v2 != null) ? snapshot2 : null;
|
|
23437
23444
|
}
|
|
23438
23445
|
function parseModelUsage(value2) {
|
|
23439
23446
|
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return null;
|
|
23440
|
-
const
|
|
23447
|
+
const snapshot2 = {};
|
|
23441
23448
|
const fields = [
|
|
23442
23449
|
["input", "inputTokens"],
|
|
23443
23450
|
["output", "outputTokens"],
|
|
@@ -23449,10 +23456,10 @@ function parseModelUsage(value2) {
|
|
|
23449
23456
|
const usage = model;
|
|
23450
23457
|
for (const [target, source] of fields) {
|
|
23451
23458
|
const amount = usageNum(usage[source]);
|
|
23452
|
-
if (amount != null)
|
|
23459
|
+
if (amount != null) snapshot2[target] = (snapshot2[target] ?? 0) + amount;
|
|
23453
23460
|
}
|
|
23454
23461
|
}
|
|
23455
|
-
return Object.values(
|
|
23462
|
+
return Object.values(snapshot2).some((v2) => v2 != null) ? snapshot2 : null;
|
|
23456
23463
|
}
|
|
23457
23464
|
function mergeFinalUsage(primary, fallback) {
|
|
23458
23465
|
if (!primary) return fallback;
|
|
@@ -25836,9 +25843,9 @@ function toolUseOnce(state, id, name, input) {
|
|
|
25836
25843
|
state.toolUseIds.add(id);
|
|
25837
25844
|
return [{ kind: "tool_use", payload: { id, name, input } }];
|
|
25838
25845
|
}
|
|
25839
|
-
function remainderAfterStream(streamed,
|
|
25840
|
-
if (!streamed) return
|
|
25841
|
-
return
|
|
25846
|
+
function remainderAfterStream(streamed, snapshot2) {
|
|
25847
|
+
if (!streamed) return snapshot2;
|
|
25848
|
+
return snapshot2.startsWith(streamed) ? snapshot2.slice(streamed.length) : "";
|
|
25842
25849
|
}
|
|
25843
25850
|
function noteCodexAgentDelta(state, delta) {
|
|
25844
25851
|
if (!delta) return [];
|
|
@@ -31378,9 +31385,9 @@ var init_service = __esm({
|
|
|
31378
31385
|
if (this.sending || this.finalized || !this.dirty) return;
|
|
31379
31386
|
this.sending = true;
|
|
31380
31387
|
this.dirty = false;
|
|
31381
|
-
const
|
|
31388
|
+
const snapshot2 = this.buf;
|
|
31382
31389
|
try {
|
|
31383
|
-
const card2 = buildTextCard(
|
|
31390
|
+
const card2 = buildTextCard(snapshot2, { footer: "\u25CF \u751F\u6210\u4E2D\u2026" });
|
|
31384
31391
|
if (!this.messageId) {
|
|
31385
31392
|
this.messageId = (await this.client.sendCard(this.chatId, card2)).messageId;
|
|
31386
31393
|
} else {
|
|
@@ -41387,7 +41394,7 @@ var require_form_data = __commonJS({
|
|
|
41387
41394
|
var http2 = require("http");
|
|
41388
41395
|
var https = require("https");
|
|
41389
41396
|
var parseUrl = require("url").parse;
|
|
41390
|
-
var
|
|
41397
|
+
var fs48 = require("fs");
|
|
41391
41398
|
var Stream = require("stream").Stream;
|
|
41392
41399
|
var crypto4 = require("crypto");
|
|
41393
41400
|
var mime = require_mime_types();
|
|
@@ -41457,7 +41464,7 @@ var require_form_data = __commonJS({
|
|
|
41457
41464
|
if (value2.end != void 0 && value2.end != Infinity && value2.start != void 0) {
|
|
41458
41465
|
callback(null, value2.end + 1 - (value2.start ? value2.start : 0));
|
|
41459
41466
|
} else {
|
|
41460
|
-
|
|
41467
|
+
fs48.stat(value2.path, function(err, stat3) {
|
|
41461
41468
|
if (err) {
|
|
41462
41469
|
callback(err);
|
|
41463
41470
|
return;
|
|
@@ -52184,7 +52191,7 @@ var require_websocket = __commonJS({
|
|
|
52184
52191
|
var http2 = require("http");
|
|
52185
52192
|
var net = require("net");
|
|
52186
52193
|
var tls = require("tls");
|
|
52187
|
-
var { randomBytes: randomBytes13, createHash:
|
|
52194
|
+
var { randomBytes: randomBytes13, createHash: createHash42 } = require("crypto");
|
|
52188
52195
|
var { Duplex, Readable } = require("stream");
|
|
52189
52196
|
var { URL: URL2 } = require("url");
|
|
52190
52197
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -52852,7 +52859,7 @@ var require_websocket = __commonJS({
|
|
|
52852
52859
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
52853
52860
|
return;
|
|
52854
52861
|
}
|
|
52855
|
-
const digest =
|
|
52862
|
+
const digest = createHash42("sha1").update(key + GUID).digest("base64");
|
|
52856
52863
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
52857
52864
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
52858
52865
|
return;
|
|
@@ -53221,7 +53228,7 @@ var require_websocket_server = __commonJS({
|
|
|
53221
53228
|
var EventEmitter = require("events");
|
|
53222
53229
|
var http2 = require("http");
|
|
53223
53230
|
var { Duplex } = require("stream");
|
|
53224
|
-
var { createHash:
|
|
53231
|
+
var { createHash: createHash42 } = require("crypto");
|
|
53225
53232
|
var extension3 = require_extension();
|
|
53226
53233
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
53227
53234
|
var subprotocol2 = require_subprotocol();
|
|
@@ -53528,7 +53535,7 @@ var require_websocket_server = __commonJS({
|
|
|
53528
53535
|
);
|
|
53529
53536
|
}
|
|
53530
53537
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
53531
|
-
const digest =
|
|
53538
|
+
const digest = createHash42("sha1").update(key + GUID).digest("base64");
|
|
53532
53539
|
const headers = [
|
|
53533
53540
|
"HTTP/1.1 101 Switching Protocols",
|
|
53534
53541
|
"Upgrade: websocket",
|
|
@@ -56032,7 +56039,7 @@ var require_lib4 = __commonJS({
|
|
|
56032
56039
|
"use strict";
|
|
56033
56040
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
56034
56041
|
var axios = require_axios();
|
|
56035
|
-
var
|
|
56042
|
+
var fs48 = require("fs");
|
|
56036
56043
|
var path43 = require("path");
|
|
56037
56044
|
var crypto4 = require("crypto");
|
|
56038
56045
|
var qs = require_lib3();
|
|
@@ -56050,7 +56057,7 @@ var require_lib4 = __commonJS({
|
|
|
56050
56057
|
return e && typeof e === "object" && "default" in e ? e : { "default": e };
|
|
56051
56058
|
}
|
|
56052
56059
|
var axios__default = /* @__PURE__ */ _interopDefaultLegacy(axios);
|
|
56053
|
-
var fs__default = /* @__PURE__ */ _interopDefaultLegacy(
|
|
56060
|
+
var fs__default = /* @__PURE__ */ _interopDefaultLegacy(fs48);
|
|
56054
56061
|
var path__default = /* @__PURE__ */ _interopDefaultLegacy(path43);
|
|
56055
56062
|
var crypto__default = /* @__PURE__ */ _interopDefaultLegacy(crypto4);
|
|
56056
56063
|
var identity__default = /* @__PURE__ */ _interopDefaultLegacy(identity);
|
|
@@ -140031,8 +140038,8 @@ var require_lib4 = __commonJS({
|
|
|
140031
140038
|
while (this.content.length > this.maxChars) {
|
|
140032
140039
|
yield this.rollover();
|
|
140033
140040
|
}
|
|
140034
|
-
const
|
|
140035
|
-
yield this.sender.updateCardElementContent(this.cardId, ELEMENT_ID,
|
|
140041
|
+
const snapshot2 = this.content || "...";
|
|
140042
|
+
yield this.sender.updateCardElementContent(this.cardId, ELEMENT_ID, snapshot2, ++this.sequence);
|
|
140036
140043
|
});
|
|
140037
140044
|
}
|
|
140038
140045
|
/**
|
|
@@ -140175,9 +140182,9 @@ var require_lib4 = __commonJS({
|
|
|
140175
140182
|
return __awaiter(this, void 0, void 0, function* () {
|
|
140176
140183
|
if (!this._messageId)
|
|
140177
140184
|
return;
|
|
140178
|
-
const
|
|
140185
|
+
const snapshot2 = this._current;
|
|
140179
140186
|
yield this.queue.enqueue(() => __awaiter(this, void 0, void 0, function* () {
|
|
140180
|
-
yield this.sender.patchCard(this._messageId,
|
|
140187
|
+
yield this.sender.patchCard(this._messageId, snapshot2);
|
|
140181
140188
|
}));
|
|
140182
140189
|
});
|
|
140183
140190
|
}
|
|
@@ -160426,12 +160433,12 @@ var require_dist2 = __commonJS({
|
|
|
160426
160433
|
throw new Error(`Unknown format "${name}"`);
|
|
160427
160434
|
return f2;
|
|
160428
160435
|
};
|
|
160429
|
-
function addFormats(ajv, list2,
|
|
160436
|
+
function addFormats(ajv, list2, fs48, exportName) {
|
|
160430
160437
|
var _a;
|
|
160431
160438
|
var _b;
|
|
160432
160439
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
160433
160440
|
for (const f2 of list2)
|
|
160434
|
-
ajv.addFormat(f2,
|
|
160441
|
+
ajv.addFormat(f2, fs48[f2]);
|
|
160435
160442
|
}
|
|
160436
160443
|
module2.exports = exports2 = formatsPlugin;
|
|
160437
160444
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -167590,8 +167597,8 @@ var init_service2 = __esm({
|
|
|
167590
167597
|
output += chunk;
|
|
167591
167598
|
if (answerAttempt && (output.length - checkpointedChars >= 1024 || FINAL_ANSWER_MARKER.test(output))) {
|
|
167592
167599
|
checkpointedChars = output.length;
|
|
167593
|
-
const
|
|
167594
|
-
checkpointChain = checkpointChain.then(() => this.checkpointAnswerDraft(record8, answerAttempt.id,
|
|
167600
|
+
const snapshot2 = output;
|
|
167601
|
+
checkpointChain = checkpointChain.then(() => this.checkpointAnswerDraft(record8, answerAttempt.id, snapshot2));
|
|
167595
167602
|
}
|
|
167596
167603
|
});
|
|
167597
167604
|
dispatched.onTelemetry?.((event) => {
|
|
@@ -184561,14 +184568,14 @@ var require_parser2 = __commonJS({
|
|
|
184561
184568
|
case "scalar":
|
|
184562
184569
|
case "single-quoted-scalar":
|
|
184563
184570
|
case "double-quoted-scalar": {
|
|
184564
|
-
const
|
|
184571
|
+
const fs48 = this.flowScalar(this.type);
|
|
184565
184572
|
if (atNextItem || it.value) {
|
|
184566
|
-
map.items.push({ start, key:
|
|
184573
|
+
map.items.push({ start, key: fs48, sep: [] });
|
|
184567
184574
|
this.onKeyLine = true;
|
|
184568
184575
|
} else if (it.sep) {
|
|
184569
|
-
this.stack.push(
|
|
184576
|
+
this.stack.push(fs48);
|
|
184570
184577
|
} else {
|
|
184571
|
-
Object.assign(it, { key:
|
|
184578
|
+
Object.assign(it, { key: fs48, sep: [] });
|
|
184572
184579
|
this.onKeyLine = true;
|
|
184573
184580
|
}
|
|
184574
184581
|
return;
|
|
@@ -184696,13 +184703,13 @@ var require_parser2 = __commonJS({
|
|
|
184696
184703
|
case "scalar":
|
|
184697
184704
|
case "single-quoted-scalar":
|
|
184698
184705
|
case "double-quoted-scalar": {
|
|
184699
|
-
const
|
|
184706
|
+
const fs48 = this.flowScalar(this.type);
|
|
184700
184707
|
if (!it || it.value)
|
|
184701
|
-
fc.items.push({ start: [], key:
|
|
184708
|
+
fc.items.push({ start: [], key: fs48, sep: [] });
|
|
184702
184709
|
else if (it.sep)
|
|
184703
|
-
this.stack.push(
|
|
184710
|
+
this.stack.push(fs48);
|
|
184704
184711
|
else
|
|
184705
|
-
Object.assign(it, { key:
|
|
184712
|
+
Object.assign(it, { key: fs48, sep: [] });
|
|
184706
184713
|
return;
|
|
184707
184714
|
}
|
|
184708
184715
|
case "flow-map-end":
|
|
@@ -185291,10 +185298,10 @@ function durationMs2(startedAt, completedAt) {
|
|
|
185291
185298
|
if (!startedAt || !completedAt) return void 0;
|
|
185292
185299
|
return Math.max(0, Date.parse(completedAt) - Date.parse(startedAt));
|
|
185293
185300
|
}
|
|
185294
|
-
function snapshotJson(
|
|
185295
|
-
if (!
|
|
185301
|
+
function snapshotJson(snapshot2, expectedHash) {
|
|
185302
|
+
if (!snapshot2 || !expectedHash || snapshot2.contentHash !== expectedHash || snapshot2.contentHash !== sha256(snapshot2.content)) return void 0;
|
|
185296
185303
|
try {
|
|
185297
|
-
return JSON.parse(
|
|
185304
|
+
return JSON.parse(snapshot2.content);
|
|
185298
185305
|
} catch {
|
|
185299
185306
|
return void 0;
|
|
185300
185307
|
}
|
|
@@ -185603,7 +185610,7 @@ var init_network_maintenance = __esm({
|
|
|
185603
185610
|
store.list(scope, "snapshot")
|
|
185604
185611
|
]);
|
|
185605
185612
|
const runTasks = tasks.filter((entry) => entry.maintenanceRunId === run.id).sort((left, right) => left.ordinal - right.ordinal);
|
|
185606
|
-
const snapshotByRef = new Map(snapshots2.map((
|
|
185613
|
+
const snapshotByRef = new Map(snapshots2.map((snapshot2) => [snapshot2.ref, snapshot2]));
|
|
185607
185614
|
return {
|
|
185608
185615
|
run,
|
|
185609
185616
|
tasks: runTasks,
|
|
@@ -185649,7 +185656,7 @@ var init_network_maintenance = __esm({
|
|
|
185649
185656
|
const itemById = new Map(allItems.map((item) => [item.id, item]));
|
|
185650
185657
|
const items = allItems.filter((item) => item.status === "active" && item.currentApprovedVersionId);
|
|
185651
185658
|
const versions = new Map((await store.list(scope, "item_version")).map((version2) => [version2.id, version2]));
|
|
185652
|
-
const snapshots2 = new Map((await store.list(scope, "snapshot")).map((
|
|
185659
|
+
const snapshots2 = new Map((await store.list(scope, "snapshot")).map((snapshot2) => [snapshot2.ref, snapshot2]));
|
|
185653
185660
|
const relations = await store.list(scope, "version_relation");
|
|
185654
185661
|
const currentVersions = new Map(items.map((item) => [item.currentApprovedVersionId, { item, version: versions.get(item.currentApprovedVersionId) }]));
|
|
185655
185662
|
const aiVisibleVersions = [...currentVersions.values()].filter((entry) => Boolean(entry.version) && entry.version.accessMode === "agent_and_human");
|
|
@@ -185679,11 +185686,11 @@ var init_network_maintenance = __esm({
|
|
|
185679
185686
|
if (mode === "full") for (const entry of currentDerived) affectedVersionIds.add(entry.version.id);
|
|
185680
185687
|
const settings = await store.get(scope, "maintenance_settings", `knmaintsettings_${sha256(`${ctx.organizationId}:${projectId2 ?? "org"}:${spaceId}`).slice(0, 24)}`) ?? this.defaultSettings(ctx, projectId2, spaceId);
|
|
185681
185688
|
const approvedContent = (entry) => {
|
|
185682
|
-
const
|
|
185683
|
-
if (!
|
|
185689
|
+
const snapshot2 = snapshots2.get(entry.version.contentSnapshotRef);
|
|
185690
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) {
|
|
185684
185691
|
return this.options.fail(409, "KNOWLEDGE_MAINTENANCE_SNAPSHOT_UNREADABLE", `\u6279\u51C6\u7248\u672C ${entry.version.id} \u7684\u4E0D\u53EF\u53D8\u5FEB\u7167\u4E0D\u53EF\u8BFB`);
|
|
185685
185692
|
}
|
|
185686
|
-
return
|
|
185693
|
+
return snapshot2.content;
|
|
185687
185694
|
};
|
|
185688
185695
|
const relevanceEntry = (entry) => ({
|
|
185689
185696
|
itemId: entry.item.id,
|
|
@@ -185898,7 +185905,7 @@ var init_network_maintenance = __esm({
|
|
|
185898
185905
|
const maintenanceInput = maintenanceInputFromSnapshot(inputSnapshot.content, run.mode, projectId2 ? "project" : "organization");
|
|
185899
185906
|
let existingTasks = (await store.list(scope, "maintenance_task")).filter((task) => task.maintenanceRunId === run.id);
|
|
185900
185907
|
const requestActor = await this.options.actor(ctx.actorId);
|
|
185901
|
-
const taskSnapshots = new Map((await store.list(scope, "snapshot")).map((
|
|
185908
|
+
const taskSnapshots = new Map((await store.list(scope, "snapshot")).map((snapshot2) => [snapshot2.ref, snapshot2]));
|
|
185902
185909
|
const completedTasks = [];
|
|
185903
185910
|
for (const task of existingTasks.filter((entry) => entry.status === "succeeded")) {
|
|
185904
185911
|
const resultSnapshot = task.resultSnapshotRef ? taskSnapshots.get(task.resultSnapshotRef) : void 0;
|
|
@@ -186036,9 +186043,9 @@ var init_network_maintenance = __esm({
|
|
|
186036
186043
|
}
|
|
186037
186044
|
if (puts.length > 0) await store.transact(scope, { puts });
|
|
186038
186045
|
},
|
|
186039
|
-
onTaskStarted: async (
|
|
186040
|
-
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey ===
|
|
186041
|
-
if (!current) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186046
|
+
onTaskStarted: async (taskKey2, sessionId) => {
|
|
186047
|
+
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey === taskKey2);
|
|
186048
|
+
if (!current) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u5C1A\u672A\u6301\u4E45\u5316`, false);
|
|
186042
186049
|
if (current.status === "succeeded") return;
|
|
186043
186050
|
const now = this.iso();
|
|
186044
186051
|
const running = {
|
|
@@ -186064,21 +186071,21 @@ var init_network_maintenance = __esm({
|
|
|
186064
186071
|
],
|
|
186065
186072
|
puts: [put("maintenance_task", running)]
|
|
186066
186073
|
});
|
|
186067
|
-
if (!result2.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186074
|
+
if (!result2.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u5DF2\u88AB\u5176\u4ED6 Worker \u9886\u53D6`, true);
|
|
186068
186075
|
},
|
|
186069
|
-
onTaskSucceeded: async (
|
|
186070
|
-
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey ===
|
|
186071
|
-
if (!current || current.status !== "running") throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186072
|
-
const currentInputSnapshot = (await store.list(scope, "snapshot")).find((
|
|
186076
|
+
onTaskSucceeded: async (taskKey2, rawOutput, result2) => {
|
|
186077
|
+
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey === taskKey2);
|
|
186078
|
+
if (!current || current.status !== "running") throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u4E0D\u5728\u8FD0\u884C\u6001`, false);
|
|
186079
|
+
const currentInputSnapshot = (await store.list(scope, "snapshot")).find((snapshot2) => snapshot2.ref === current.inputSnapshotRef);
|
|
186073
186080
|
if (!currentInputSnapshot || currentInputSnapshot.contentHash !== current.inputHash || currentInputSnapshot.contentHash !== sha256(currentInputSnapshot.content)) {
|
|
186074
|
-
throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186081
|
+
throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u7684\u8F93\u5165\u5FEB\u7167\u4E0D\u53EF\u8BFB`, false);
|
|
186075
186082
|
}
|
|
186076
186083
|
const taskInput = JSON.parse(currentInputSnapshot.content);
|
|
186077
186084
|
try {
|
|
186078
186085
|
validateMaintenanceTaskOperations(result2.operations, taskInput);
|
|
186079
186086
|
} catch (error2) {
|
|
186080
186087
|
const validationError = error2 instanceof Error ? error2.message : String(error2);
|
|
186081
|
-
const output2 = this.snapshot(ctx, "maintenance_task_output", stableJson(rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${
|
|
186088
|
+
const output2 = this.snapshot(ctx, "maintenance_task_output", stableJson(rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${taskKey2}:${current.retryCount}`);
|
|
186082
186089
|
const now2 = this.iso();
|
|
186083
186090
|
const failed = {
|
|
186084
186091
|
...current,
|
|
@@ -186101,11 +186108,11 @@ var init_network_maintenance = __esm({
|
|
|
186101
186108
|
],
|
|
186102
186109
|
puts: [put("snapshot", output2, "error"), put("maintenance_task", failed)]
|
|
186103
186110
|
});
|
|
186104
|
-
if (!rejected.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186111
|
+
if (!rejected.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u65E0\u6548\u7ED3\u679C\u72B6\u6001\u63D0\u4EA4\u51B2\u7A81`, true);
|
|
186105
186112
|
throw new KnowledgeMaintenanceProcessingError(validationError, false);
|
|
186106
186113
|
}
|
|
186107
|
-
const output = this.snapshot(ctx, "maintenance_task_output", stableJson(rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${
|
|
186108
|
-
const normalized4 = this.snapshot(ctx, "maintenance_task_result", stableJson(result2), projectId2, run.spaceId, `snapshot:maintenance-task-result:${run.id}:${
|
|
186114
|
+
const output = this.snapshot(ctx, "maintenance_task_output", stableJson(rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${taskKey2}:${current.retryCount}`);
|
|
186115
|
+
const normalized4 = this.snapshot(ctx, "maintenance_task_result", stableJson(result2), projectId2, run.spaceId, `snapshot:maintenance-task-result:${run.id}:${taskKey2}:${current.retryCount}`);
|
|
186109
186116
|
const now = this.iso();
|
|
186110
186117
|
const succeeded = {
|
|
186111
186118
|
...current,
|
|
@@ -186128,14 +186135,14 @@ var init_network_maintenance = __esm({
|
|
|
186128
186135
|
],
|
|
186129
186136
|
puts: [put("snapshot", output, "error"), put("snapshot", normalized4, "error"), put("maintenance_task", succeeded)]
|
|
186130
186137
|
});
|
|
186131
|
-
if (!saved.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186138
|
+
if (!saved.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u7ED3\u679C\u68C0\u67E5\u70B9\u63D0\u4EA4\u51B2\u7A81`, true);
|
|
186132
186139
|
},
|
|
186133
|
-
onTaskFailed: async (
|
|
186134
|
-
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey ===
|
|
186140
|
+
onTaskFailed: async (taskKey2, failure) => {
|
|
186141
|
+
const current = (await store.list(scope, "maintenance_task")).find((task) => task.maintenanceRunId === run.id && task.taskKey === taskKey2);
|
|
186135
186142
|
if (!current || current.status === "succeeded") return;
|
|
186136
186143
|
const retryable = failure.kind === "runtime" && isRetryableKnowledgeMaintenanceError(failure.cause ?? new Error(failure.message));
|
|
186137
186144
|
const now = this.iso();
|
|
186138
|
-
const output = failure.rawOutput ? this.snapshot(ctx, "maintenance_task_output", stableJson(failure.rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${
|
|
186145
|
+
const output = failure.rawOutput ? this.snapshot(ctx, "maintenance_task_output", stableJson(failure.rawOutput), projectId2, run.spaceId, `snapshot:maintenance-task-output:${run.id}:${taskKey2}:${current.retryCount}`) : void 0;
|
|
186139
186146
|
const failed = {
|
|
186140
186147
|
...current,
|
|
186141
186148
|
...failure.sessionId ? { sessionId: failure.sessionId } : {},
|
|
@@ -186152,7 +186159,7 @@ var init_network_maintenance = __esm({
|
|
|
186152
186159
|
checks: [{ kind: "maintenance_task", id: current.id, field: "status", equals: current.status }],
|
|
186153
186160
|
puts: [...output ? [put("snapshot", output, "error")] : [], put("maintenance_task", failed)]
|
|
186154
186161
|
});
|
|
186155
|
-
if (!saved.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${
|
|
186162
|
+
if (!saved.committed) throw new KnowledgeMaintenanceProcessingError(`\u77E5\u8BC6\u7F51\u7EDC\u4EFB\u52A1 ${taskKey2} \u5931\u8D25\u72B6\u6001\u63D0\u4EA4\u51B2\u7A81`, true);
|
|
186156
186163
|
}
|
|
186157
186164
|
});
|
|
186158
186165
|
const analyzer = await this.options.actor(analysis.analyzerActorId);
|
|
@@ -186252,7 +186259,7 @@ var init_network_maintenance = __esm({
|
|
|
186252
186259
|
targetItems: previewTargets,
|
|
186253
186260
|
sensitivityFindings: [...candidate.sensitivityFindings]
|
|
186254
186261
|
};
|
|
186255
|
-
const
|
|
186262
|
+
const snapshot2 = this.snapshot(
|
|
186256
186263
|
ctx,
|
|
186257
186264
|
"approved_preview",
|
|
186258
186265
|
stableJson(preview2),
|
|
@@ -186260,15 +186267,15 @@ var init_network_maintenance = __esm({
|
|
|
186260
186267
|
run.spaceId,
|
|
186261
186268
|
`snapshot:maintenance-preview:${candidate.id}:${candidate.candidateRevision}`
|
|
186262
186269
|
);
|
|
186263
|
-
approvedPreviewSnapshots.push(
|
|
186270
|
+
approvedPreviewSnapshots.push(snapshot2);
|
|
186264
186271
|
approvedCandidates.push({
|
|
186265
186272
|
...candidate,
|
|
186266
186273
|
decisionStatus: "approved",
|
|
186267
186274
|
decisionAction: candidate.recommendedAction,
|
|
186268
186275
|
decidedBy: ctx.actorId,
|
|
186269
186276
|
decisionReason: "\u7CFB\u7EDF\u6700\u5C0F\u5B89\u5168\u6821\u9A8C\u901A\u8FC7\uFF0C\u81EA\u52A8\u8FDB\u5165\u53D1\u5E03",
|
|
186270
|
-
approvedPreviewSnapshotRef:
|
|
186271
|
-
approvedPreviewHash:
|
|
186277
|
+
approvedPreviewSnapshotRef: snapshot2.ref,
|
|
186278
|
+
approvedPreviewHash: snapshot2.contentHash,
|
|
186272
186279
|
decidedAt: approvedAt,
|
|
186273
186280
|
updatedAt: approvedAt
|
|
186274
186281
|
});
|
|
@@ -186314,7 +186321,7 @@ var init_network_maintenance = __esm({
|
|
|
186314
186321
|
{ kind: "maintenance_run", id: run.id, field: "analysisAttemptId", equals: validating.analysisAttemptId }
|
|
186315
186322
|
],
|
|
186316
186323
|
puts: [
|
|
186317
|
-
...approvedPreviewSnapshots.map((
|
|
186324
|
+
...approvedPreviewSnapshots.map((snapshot2) => put("snapshot", snapshot2, "error")),
|
|
186318
186325
|
...approvedCandidates.map((candidate) => put("candidate", candidate, "error")),
|
|
186319
186326
|
...created.targets.map((target) => put("candidate_target", target, "error")),
|
|
186320
186327
|
...approvedOperations.map((operation) => put("maintenance_operation", operation, "error")),
|
|
@@ -186671,11 +186678,11 @@ var init_network_maintenance = __esm({
|
|
|
186671
186678
|
if (relevantTasks.length !== taskKeys.length || relevantTasks.some((task) => task.status !== "failed_deterministic" || task.retryCount < 1)) {
|
|
186672
186679
|
return this.options.fail(409, "KNOWLEDGE_MAINTENANCE_GAP_RETRY_REQUIRED", "\u81F3\u5C11\u8BA9\u77E5\u8BC6\u7BA1\u7406\u5458\u6309\u6821\u9A8C\u610F\u89C1\u8FD4\u4FEE\u4E00\u6B21\uFF1B\u8FDE\u7EED\u5931\u8D25\u540E\u624D\u80FD\u8DF3\u8FC7\u76F8\u5173\u4E3B\u9898");
|
|
186673
186680
|
}
|
|
186674
|
-
const inputSnapshot = snapshots2.find((
|
|
186681
|
+
const inputSnapshot = snapshots2.find((snapshot2) => snapshot2.ref === run.inputSnapshotRef);
|
|
186675
186682
|
if (!inputSnapshot || inputSnapshot.contentHash !== run.inputHash || inputSnapshot.contentHash !== sha256(inputSnapshot.content)) {
|
|
186676
186683
|
return this.options.fail(409, "KNOWLEDGE_MAINTENANCE_INPUT_CORRUPT", "\u7EF4\u62A4\u8F93\u5165\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
186677
186684
|
}
|
|
186678
|
-
const outputSnapshot = run.outputSnapshotRef ? snapshots2.find((
|
|
186685
|
+
const outputSnapshot = run.outputSnapshotRef ? snapshots2.find((snapshot2) => snapshot2.ref === run.outputSnapshotRef) : void 0;
|
|
186679
186686
|
if (!outputSnapshot || outputSnapshot.contentHash !== sha256(outputSnapshot.content)) {
|
|
186680
186687
|
return this.options.fail(409, "KNOWLEDGE_MAINTENANCE_OUTPUT_CORRUPT", "\u7EF4\u62A4\u8F93\u51FA\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
186681
186688
|
}
|
|
@@ -186826,16 +186833,16 @@ var init_network_maintenance = __esm({
|
|
|
186826
186833
|
targetItems: previewTargets,
|
|
186827
186834
|
sensitivityFindings: [...candidate.sensitivityFindings]
|
|
186828
186835
|
};
|
|
186829
|
-
const
|
|
186830
|
-
snapshots2.push(
|
|
186836
|
+
const snapshot2 = this.snapshot(ctx, "approved_preview", stableJson(preview2), projectId2, run.spaceId, `snapshot:maintenance-preview:${candidate.id}:${candidate.candidateRevision}`);
|
|
186837
|
+
snapshots2.push(snapshot2);
|
|
186831
186838
|
decidedCandidates.push({
|
|
186832
186839
|
...candidate,
|
|
186833
186840
|
decisionStatus: "approved",
|
|
186834
186841
|
decisionAction: candidate.recommendedAction,
|
|
186835
186842
|
decidedBy: ctx.actorId,
|
|
186836
186843
|
decisionReason: request2.reason.trim(),
|
|
186837
|
-
approvedPreviewSnapshotRef:
|
|
186838
|
-
approvedPreviewHash:
|
|
186844
|
+
approvedPreviewSnapshotRef: snapshot2.ref,
|
|
186845
|
+
approvedPreviewHash: snapshot2.contentHash,
|
|
186839
186846
|
decidedAt: now,
|
|
186840
186847
|
updatedAt: now
|
|
186841
186848
|
});
|
|
@@ -186889,7 +186896,7 @@ var init_network_maintenance = __esm({
|
|
|
186889
186896
|
const result = await store.transact(scope, {
|
|
186890
186897
|
checks: [{ kind: "maintenance_run", id: run.id, field: "status", equals: "awaiting_review" }],
|
|
186891
186898
|
puts: [
|
|
186892
|
-
...snapshots2.map((
|
|
186899
|
+
...snapshots2.map((snapshot2) => put("snapshot", snapshot2, "error")),
|
|
186893
186900
|
...decidedCandidates.map((candidate) => put("candidate", candidate)),
|
|
186894
186901
|
...nextOperations.map((operation) => put("maintenance_operation", operation)),
|
|
186895
186902
|
put("maintenance_run", reviewed),
|
|
@@ -187279,7 +187286,7 @@ var init_network_maintenance = __esm({
|
|
|
187279
187286
|
createdAt: now,
|
|
187280
187287
|
updatedAt: now
|
|
187281
187288
|
};
|
|
187282
|
-
const
|
|
187289
|
+
const snapshot2 = this.snapshot(ctx, "approved_content", normalizeKnowledgeContent(preview2.title, revision.content), run.projectId, run.spaceId, `snapshot:approved:${versionId}`);
|
|
187283
187290
|
const metadata = preview2.metadata;
|
|
187284
187291
|
const version2 = {
|
|
187285
187292
|
id: versionId,
|
|
@@ -187311,7 +187318,7 @@ var init_network_maintenance = __esm({
|
|
|
187311
187318
|
semanticContentHash: semanticKnowledgeHash(preview2.title, revision.content),
|
|
187312
187319
|
providerContentHash: revision.providerContentHash || providerKnowledgeHash(revision.content),
|
|
187313
187320
|
contentNormalizerVersion: KNOWLEDGE_NORMALIZER_VERSION,
|
|
187314
|
-
contentSnapshotRef:
|
|
187321
|
+
contentSnapshotRef: snapshot2.ref,
|
|
187315
187322
|
changeType: operation.action === "add" ? "initial" : operation.action,
|
|
187316
187323
|
changeSummary: candidate.recommendedReason,
|
|
187317
187324
|
approvedBy: candidate.decidedBy,
|
|
@@ -187320,7 +187327,7 @@ var init_network_maintenance = __esm({
|
|
|
187320
187327
|
};
|
|
187321
187328
|
finalItems.set(item.id, item);
|
|
187322
187329
|
puts.push(
|
|
187323
|
-
put("snapshot",
|
|
187330
|
+
put("snapshot", snapshot2, "error"),
|
|
187324
187331
|
put("item", item, updatesExisting ? "replace" : "error"),
|
|
187325
187332
|
put("item_version", version2, "error"),
|
|
187326
187333
|
put("provider_mapping", this.providerMapping(ctx, version2, connection, space, revision), "error"),
|
|
@@ -187401,7 +187408,7 @@ var init_network_maintenance = __esm({
|
|
|
187401
187408
|
title: version2.title,
|
|
187402
187409
|
abstract: version2.abstract,
|
|
187403
187410
|
logicalPath: item.logicalPath,
|
|
187404
|
-
content:
|
|
187411
|
+
content: snapshot2.content
|
|
187405
187412
|
}).map((entry) => ({
|
|
187406
187413
|
id: `${version2.id}:${entry.chunkId}:routing`,
|
|
187407
187414
|
organizationId: ctx.organizationId,
|
|
@@ -187506,9 +187513,9 @@ var init_network_maintenance = __esm({
|
|
|
187506
187513
|
const scope = recordScope(ctx.organizationId, projectId2, current.spaceId);
|
|
187507
187514
|
const previous3 = await store.get(scope, "generation", current.previousGenerationId);
|
|
187508
187515
|
if (!previous3?.manifestSnapshotRef || previous3.status !== "superseded") return this.options.fail(409, "KNOWLEDGE_GENERATION_PREVIOUS_UNAVAILABLE", "\u4E0A\u4E00 Generation \u4E0D\u53EF\u6062\u590D");
|
|
187509
|
-
const
|
|
187510
|
-
if (!
|
|
187511
|
-
const manifest = JSON.parse(
|
|
187516
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === previous3.manifestSnapshotRef);
|
|
187517
|
+
if (!snapshot2 || snapshot2.contentHash !== previous3.manifestHash || snapshot2.contentHash !== sha256(snapshot2.content)) return this.options.fail(409, "KNOWLEDGE_GENERATION_MANIFEST_CORRUPT", "\u4E0A\u4E00 Generation Manifest \u4E0D\u53EF\u8BFB");
|
|
187518
|
+
const manifest = JSON.parse(snapshot2.content);
|
|
187512
187519
|
const items = await store.list(scope, "item");
|
|
187513
187520
|
const versions = new Map((await store.list(scope, "item_version")).map((entry) => [entry.id, entry]));
|
|
187514
187521
|
const itemById = new Map(items.map((entry) => [entry.id, entry]));
|
|
@@ -188390,8 +188397,8 @@ var init_governance_service = __esm({
|
|
|
188390
188397
|
for (const item of (await store.list(itemScope, "item")).filter((entry) => entry.currentApprovedVersionId)) {
|
|
188391
188398
|
const version2 = versions.find((entry) => entry.id === item.currentApprovedVersionId);
|
|
188392
188399
|
if (!version2) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_CONFIGURATION_VERSION_MISSING", `\u6B63\u5F0F\u77E5\u8BC6\u5F53\u524D\u7248\u672C\u4E0D\u5B58\u5728\uFF1A${item.id}`);
|
|
188393
|
-
const
|
|
188394
|
-
if (!
|
|
188400
|
+
const snapshot2 = snapshots2.find((entry) => entry.ref === version2.contentSnapshotRef);
|
|
188401
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) {
|
|
188395
188402
|
throw new KnowledgeGovernanceError(409, "KNOWLEDGE_CONFIGURATION_SNAPSHOT_INVALID", `\u6B63\u5F0F\u77E5\u8BC6\u7F3A\u5C11\u53EF\u9A8C\u8BC1\u5FEB\u7167\uFF0C\u4E0D\u80FD\u5B89\u5168\u5207\u6362\u4F4D\u7F6E\uFF1A${item.id}`);
|
|
188396
188403
|
}
|
|
188397
188404
|
const targetSpace = {
|
|
@@ -188416,7 +188423,7 @@ var init_governance_service = __esm({
|
|
|
188416
188423
|
libraryRef: binding.libraryRef,
|
|
188417
188424
|
rootRef: binding.rootRef
|
|
188418
188425
|
});
|
|
188419
|
-
const approvedBody = approvedSnapshotBody(version2.title,
|
|
188426
|
+
const approvedBody = approvedSnapshotBody(version2.title, snapshot2.content);
|
|
188420
188427
|
const written = await this.options.provider.writeApprovedDocument(connection, {
|
|
188421
188428
|
jobId: `knowledge-cutover:${relocationKey}`,
|
|
188422
188429
|
itemId: item.id,
|
|
@@ -189209,9 +189216,9 @@ var init_governance_service = __esm({
|
|
|
189209
189216
|
const run = await store.get(scope, "discovery_run", runId);
|
|
189210
189217
|
if (!run) continue;
|
|
189211
189218
|
if (run.status !== "failed") throw new KnowledgeGovernanceError(409, "KNOWLEDGE_DISCOVERY_NOT_RETRYABLE", "\u53EA\u6709 failed Discovery Run \u53EF\u91CD\u8BD5");
|
|
189212
|
-
const
|
|
189213
|
-
if (!
|
|
189214
|
-
const input = JSON.parse(
|
|
189219
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === run.analysisInputSnapshotRef);
|
|
189220
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_DISCOVERY_INPUT_UNREADABLE", "Discovery \u8F93\u5165\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
189221
|
+
const input = JSON.parse(snapshot2.content);
|
|
189215
189222
|
const currentRuntime = await this.options.discoveryRuntime?.();
|
|
189216
189223
|
if (!currentRuntime) throw new KnowledgeGovernanceError(503, "KNOWLEDGE_DISCOVERY_RUNTIME_UNAVAILABLE", "\u77E5\u8BC6\u53D1\u73B0\u6A21\u578B\u914D\u7F6E\u4E0D\u53EF\u7528");
|
|
189217
189224
|
return this.enqueueDiscoveryEvent(ctx, {
|
|
@@ -189747,8 +189754,8 @@ var init_governance_service = __esm({
|
|
|
189747
189754
|
const limit = sampleSize === void 0 ? snapshots2.length : Math.max(1, Math.min(Math.floor(sampleSize), snapshots2.length));
|
|
189748
189755
|
const offset = snapshots2.length > 0 ? Math.floor(this.now().getTime() / 864e5) % snapshots2.length : 0;
|
|
189749
189756
|
const selected = [...snapshots2.slice(offset), ...snapshots2.slice(0, offset)].slice(0, limit);
|
|
189750
|
-
const corruptRefs = selected.filter((
|
|
189751
|
-
const existingRefs = new Set(snapshots2.map((
|
|
189757
|
+
const corruptRefs = selected.filter((snapshot2) => snapshot2.contentHash !== sha256(snapshot2.content)).map((snapshot2) => snapshot2.ref);
|
|
189758
|
+
const existingRefs = new Set(snapshots2.map((snapshot2) => snapshot2.ref));
|
|
189752
189759
|
const referencedRefs = await this.snapshotReferences(store, scope);
|
|
189753
189760
|
const missingRefs = [...referencedRefs].filter((ref2) => !existingRefs.has(ref2)).sort();
|
|
189754
189761
|
const report = {
|
|
@@ -189780,19 +189787,19 @@ var init_governance_service = __esm({
|
|
|
189780
189787
|
const snapshots2 = await store.list(scope, "snapshot");
|
|
189781
189788
|
const referencedRefs = await this.snapshotReferences(store, scope);
|
|
189782
189789
|
const now = this.now().getTime();
|
|
189783
|
-
const expired = snapshots2.filter((
|
|
189790
|
+
const expired = snapshots2.filter((snapshot2) => snapshot2.retentionUntil && Date.parse(snapshot2.retentionUntil) <= now && !referencedRefs.has(snapshot2.ref)).sort((left, right) => left.retentionUntil.localeCompare(right.retentionUntil) || left.ref.localeCompare(right.ref));
|
|
189784
189791
|
if (expired.length > 0) {
|
|
189785
189792
|
const result = await store.transact(scope, {
|
|
189786
|
-
checks: expired.map((
|
|
189787
|
-
deletes: expired.map((
|
|
189793
|
+
checks: expired.map((snapshot2) => ({ kind: "snapshot", id: snapshot2.id, field: "retentionUntil", equals: snapshot2.retentionUntil })),
|
|
189794
|
+
deletes: expired.map((snapshot2) => ({ kind: "snapshot", id: snapshot2.id })),
|
|
189788
189795
|
puts: [put2("audit_event", this.audit(ctx, "snapshot.retention_deleted", "snapshot", "expired", void 0, {
|
|
189789
|
-
deletedRefs: expired.map((
|
|
189790
|
-
deletedContentHashes: expired.map((
|
|
189796
|
+
deletedRefs: expired.map((snapshot2) => snapshot2.ref),
|
|
189797
|
+
deletedContentHashes: expired.map((snapshot2) => snapshot2.contentHash)
|
|
189791
189798
|
}, projectId2), "error")]
|
|
189792
189799
|
});
|
|
189793
189800
|
if (!result.committed) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_SNAPSHOT_RETENTION_CONFLICT", "Snapshot \u4FDD\u7559\u6E05\u7406\u9047\u5230\u5E76\u53D1\u53D8\u66F4");
|
|
189794
189801
|
}
|
|
189795
|
-
return { inspected: snapshots2.length, deletedRefs: expired.map((
|
|
189802
|
+
return { inspected: snapshots2.length, deletedRefs: expired.map((snapshot2) => snapshot2.ref) };
|
|
189796
189803
|
}
|
|
189797
189804
|
async cancelPublishJob(ctx, jobId, projectId2) {
|
|
189798
189805
|
if (projectId2) await this.authorizeProjectResource(ctx, projectId2, "review");
|
|
@@ -189845,7 +189852,7 @@ var init_governance_service = __esm({
|
|
|
189845
189852
|
if (!candidate || candidate.decisionStatus !== "approved" || candidate.candidateRevision !== job.candidateRevision) {
|
|
189846
189853
|
return this.failPublish(store, scope, job, "APPROVED_CANDIDATE_MISSING", true);
|
|
189847
189854
|
}
|
|
189848
|
-
const previewSnapshot = candidate.approvedPreviewSnapshotRef ? (await store.list(scope, "snapshot")).find((
|
|
189855
|
+
const previewSnapshot = candidate.approvedPreviewSnapshotRef ? (await store.list(scope, "snapshot")).find((snapshot2) => snapshot2.ref === candidate.approvedPreviewSnapshotRef) : void 0;
|
|
189849
189856
|
if (!previewSnapshot || previewSnapshot.contentHash !== job.previewHash || candidate.approvedPreviewHash !== job.previewHash) {
|
|
189850
189857
|
return this.failPublish(store, scope, job, "APPROVED_PREVIEW_MISSING", true);
|
|
189851
189858
|
}
|
|
@@ -189934,8 +189941,8 @@ var init_governance_service = __esm({
|
|
|
189934
189941
|
if (!version2) throw new KnowledgeGovernanceError(404, "KNOWLEDGE_VERSION_NOT_FOUND", "\u77E5\u8BC6\u7248\u672C\u4E0D\u5B58\u5728");
|
|
189935
189942
|
const item = await store.get(scope, "item", version2.knowledgeItemId);
|
|
189936
189943
|
if (!item || item.currentApprovedVersionId !== version2.id) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_VERSION_NOT_CURRENT", "\u77E5\u8BC6\u7248\u672C\u4E0D\u662F\u5F53\u524D\u6279\u51C6\u7248\u672C");
|
|
189937
|
-
const
|
|
189938
|
-
if (!
|
|
189944
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === version2.contentSnapshotRef);
|
|
189945
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) {
|
|
189939
189946
|
await this.setRuntimeState(store, scope, version2, "snapshot", "corrupt", "SNAPSHOT_HASH_MISMATCH");
|
|
189940
189947
|
throw new KnowledgeGovernanceError(409, "KNOWLEDGE_SNAPSHOT_CORRUPT", "\u77E5\u8BC6\u5FEB\u7167\u635F\u574F");
|
|
189941
189948
|
}
|
|
@@ -189946,7 +189953,7 @@ var init_governance_service = __esm({
|
|
|
189946
189953
|
title: version2.title,
|
|
189947
189954
|
abstract: version2.abstract,
|
|
189948
189955
|
logicalPath: item.logicalPath,
|
|
189949
|
-
content:
|
|
189956
|
+
content: snapshot2.content
|
|
189950
189957
|
}).map((entry) => ({
|
|
189951
189958
|
id: `${version2.id}:${entry.chunkId}:${indexKind}`,
|
|
189952
189959
|
organizationId: ctx.organizationId,
|
|
@@ -190050,7 +190057,7 @@ var init_governance_service = __esm({
|
|
|
190050
190057
|
const activeGeneration = (await store.list(entry.scope, "generation")).find((generation) => generation.status === "active");
|
|
190051
190058
|
const activeDerivedVersionIds = /* @__PURE__ */ new Set();
|
|
190052
190059
|
if (activeGeneration?.manifestSnapshotRef) {
|
|
190053
|
-
const manifest = (await store.list(entry.scope, "snapshot")).find((
|
|
190060
|
+
const manifest = (await store.list(entry.scope, "snapshot")).find((snapshot2) => snapshot2.ref === activeGeneration.manifestSnapshotRef);
|
|
190054
190061
|
if (!manifest || manifest.contentHash !== activeGeneration.manifestHash || manifest.contentHash !== sha256(manifest.content)) {
|
|
190055
190062
|
warnings.push(`${entry.space.id}: active Generation Manifest \u4E0D\u53EF\u8BFB`);
|
|
190056
190063
|
} else {
|
|
@@ -191279,7 +191286,7 @@ var init_governance_service = __esm({
|
|
|
191279
191286
|
});
|
|
191280
191287
|
const result = await store.transact(scope, {
|
|
191281
191288
|
puts: [
|
|
191282
|
-
...snapshots2.map((
|
|
191289
|
+
...snapshots2.map((snapshot2) => put2("snapshot", snapshot2, "error")),
|
|
191283
191290
|
put2("context_pack", pack, "error"),
|
|
191284
191291
|
...entries.map((entry) => put2("context_pack_entry", entry, "error")),
|
|
191285
191292
|
...usageEvents.map((event) => put2("usage_event", event, "error")),
|
|
@@ -191304,7 +191311,7 @@ var init_governance_service = __esm({
|
|
|
191304
191311
|
throw new KnowledgeGovernanceError(403, "KNOWLEDGE_PACK_FORBIDDEN", "\u65E0\u6743\u67E5\u770B\u8BE5 Context Pack");
|
|
191305
191312
|
}
|
|
191306
191313
|
const entries = (await store.list(scope, "context_pack_entry")).filter((entry) => entry.contextPackId === pack.id).sort((left, right) => left.ordinal - right.ordinal);
|
|
191307
|
-
const rendered = pack.renderedSnapshotRef ? (await store.list(scope, "snapshot")).find((
|
|
191314
|
+
const rendered = pack.renderedSnapshotRef ? (await store.list(scope, "snapshot")).find((snapshot2) => snapshot2.ref === pack.renderedSnapshotRef) : void 0;
|
|
191308
191315
|
if (rendered && rendered.contentHash !== sha256(rendered.content)) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_PACK_CORRUPT", "Context Pack \u6E32\u67D3\u5FEB\u7167 Hash \u4E0D\u4E00\u81F4");
|
|
191309
191316
|
return { pack, entries, ...rendered ? { renderedContent: rendered.content } : {} };
|
|
191310
191317
|
}
|
|
@@ -191537,9 +191544,9 @@ var init_governance_service = __esm({
|
|
|
191537
191544
|
const current = await store.get(scope, "discovery_run", runId);
|
|
191538
191545
|
if (!current) continue;
|
|
191539
191546
|
if (current.status === "ready") return current;
|
|
191540
|
-
const
|
|
191541
|
-
if (!
|
|
191542
|
-
const input = JSON.parse(
|
|
191547
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === current.analysisInputSnapshotRef);
|
|
191548
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) throw new Error("Discovery \u8F93\u5165\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
191549
|
+
const input = JSON.parse(snapshot2.content);
|
|
191543
191550
|
const rule = input.rule;
|
|
191544
191551
|
if (!rule || rule.id !== current.ruleId || rule.ruleVersion !== current.ruleVersion) throw new Error("Discovery \u6765\u6E90\u89C4\u5219\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
191545
191552
|
if (space.status !== "active") throw new Error("Discovery Knowledge Space \u4E0D\u53EF\u7528");
|
|
@@ -192353,7 +192360,7 @@ var init_governance_service = __esm({
|
|
|
192353
192360
|
const existing = await store.get(scope, "migration_batch", batchId);
|
|
192354
192361
|
if (existing) {
|
|
192355
192362
|
const entries2 = (await store.list(scope, "migration_entry")).filter((entry) => entry.batchId === existing.id);
|
|
192356
|
-
const reportSnapshot2 = (await store.list(scope, "snapshot")).find((
|
|
192363
|
+
const reportSnapshot2 = (await store.list(scope, "snapshot")).find((snapshot2) => snapshot2.ref === existing.reportSnapshotRef);
|
|
192357
192364
|
return { batch: existing, entries: entries2, report: reportSnapshot2 ? JSON.parse(reportSnapshot2.content) : { manifestHash } };
|
|
192358
192365
|
}
|
|
192359
192366
|
const report = {
|
|
@@ -192471,7 +192478,7 @@ var init_governance_service = __esm({
|
|
|
192471
192478
|
const result = await store.transact(scope, {
|
|
192472
192479
|
puts: [
|
|
192473
192480
|
put2("migration_batch", batch, "error"),
|
|
192474
|
-
...snapshots2.map((
|
|
192481
|
+
...snapshots2.map((snapshot2) => put2("snapshot", snapshot2, "error")),
|
|
192475
192482
|
...candidates.map((candidate) => put2("candidate", candidate, "error")),
|
|
192476
192483
|
...entries.map((entry) => put2("migration_entry", entry, "error")),
|
|
192477
192484
|
put2("audit_event", this.audit(ctx, "migration.dry_run", "migration_batch", batch.id, void 0, { ...batch, manifestHash }, input.projectId), "error")
|
|
@@ -192539,7 +192546,7 @@ var init_governance_service = __esm({
|
|
|
192539
192546
|
const connection = space ? await store.get(this.orgScope(ctx), "connector_connection", space.connectorConnectionId) : null;
|
|
192540
192547
|
if (!space || !connection) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MIGRATION_BINDING_MISSING", "\u8FC1\u79FB Space \u6216 Connection \u4E0D\u5B58\u5728");
|
|
192541
192548
|
if (!batch.signatureSnapshotRef) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MIGRATION_SIGNATURE_REQUIRED", "\u6CA1\u6709\u53EF\u5BA1\u8BA1\u7684 Hash \u6E05\u5355\u7B7E\u7F72");
|
|
192542
|
-
const signature = (await store.list(scope, "snapshot")).find((
|
|
192549
|
+
const signature = (await store.list(scope, "snapshot")).find((snapshot2) => snapshot2.ref === batch.signatureSnapshotRef);
|
|
192543
192550
|
if (!signature || signature.contentHash !== sha256(signature.content)) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MIGRATION_SIGNATURE_CORRUPT", "\u8FC1\u79FB\u7B7E\u7F72\u5FEB\u7167\u4E0D\u53EF\u8BFB");
|
|
192544
192551
|
const signedManifest = JSON.parse(signature.content);
|
|
192545
192552
|
if (signedManifest.batchId !== batch.id) throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MIGRATION_SIGNATURE_MISMATCH", "\u8FC1\u79FB\u7B7E\u7F72\u6279\u6B21\u4E0D\u5339\u914D");
|
|
@@ -192826,11 +192833,11 @@ var init_governance_service = __esm({
|
|
|
192826
192833
|
if (!run || run.inputHash !== candidate.maintenanceInputHash) {
|
|
192827
192834
|
throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MAINTENANCE_INPUT_STALE", "\u7EF4\u62A4 Candidate \u5DF2\u8131\u79BB\u51BB\u7ED3\u8F93\u5165");
|
|
192828
192835
|
}
|
|
192829
|
-
const
|
|
192830
|
-
if (!
|
|
192836
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === run.inputSnapshotRef);
|
|
192837
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content) || snapshot2.contentHash !== run.inputHash) {
|
|
192831
192838
|
throw new KnowledgeGovernanceError(409, "KNOWLEDGE_MAINTENANCE_INPUT_UNREADABLE", "\u7EF4\u62A4 Candidate \u7684\u51BB\u7ED3\u8F93\u5165\u4E0D\u53EF\u8BFB");
|
|
192832
192839
|
}
|
|
192833
|
-
const input = JSON.parse(
|
|
192840
|
+
const input = JSON.parse(snapshot2.content);
|
|
192834
192841
|
const sourceById = new Map(input.currentApprovedSources.filter((source) => source.knowledgeRole === "source").map((source) => [source.versionId, source]));
|
|
192835
192842
|
const derivedFromVersionIds = this.canonicalTargetIds(candidate.derivedFromVersionIds ?? []);
|
|
192836
192843
|
const sources = derivedFromVersionIds.map((versionId) => sourceById.get(versionId));
|
|
@@ -193137,7 +193144,7 @@ var init_governance_service = __esm({
|
|
|
193137
193144
|
const now = this.iso();
|
|
193138
193145
|
const projectId2 = candidate.projectId;
|
|
193139
193146
|
const normalizedContent = normalizeKnowledgeContent(preview2.title, approvedRevision.content);
|
|
193140
|
-
const
|
|
193147
|
+
const snapshot2 = this.snapshot(ctx, "approved_content", normalizedContent, projectId2, candidate.spaceId, `snapshot:approved:${job.allocatedVersionId}`);
|
|
193141
193148
|
const primary = targets[0];
|
|
193142
193149
|
const updatesExistingItem = Boolean(primary && job.action === "revise");
|
|
193143
193150
|
const priorVersions = updatesExistingItem && primary ? (await store.list(scope, "item_version")).filter((version3) => version3.knowledgeItemId === primary.id) : [];
|
|
@@ -193195,7 +193202,7 @@ var init_governance_service = __esm({
|
|
|
193195
193202
|
semanticContentHash: semanticKnowledgeHash(preview2.title, approvedRevision.content),
|
|
193196
193203
|
providerContentHash: approvedRevision.providerContentHash || providerKnowledgeHash(approvedRevision.content),
|
|
193197
193204
|
contentNormalizerVersion: KNOWLEDGE_NORMALIZER_VERSION,
|
|
193198
|
-
contentSnapshotRef:
|
|
193205
|
+
contentSnapshotRef: snapshot2.ref,
|
|
193199
193206
|
changeType: job.action === "add" ? "initial" : job.action,
|
|
193200
193207
|
changeSummary: candidate.recommendedReason,
|
|
193201
193208
|
approvedBy: candidate.decidedBy,
|
|
@@ -193299,7 +193306,7 @@ var init_governance_service = __esm({
|
|
|
193299
193306
|
const result = await store.transact(scope, {
|
|
193300
193307
|
checks,
|
|
193301
193308
|
puts: [
|
|
193302
|
-
put2("snapshot",
|
|
193309
|
+
put2("snapshot", snapshot2, "error"),
|
|
193303
193310
|
put2("item", item, updatesExistingItem ? "replace" : "error"),
|
|
193304
193311
|
...superseded.map((target) => put2("item", target)),
|
|
193305
193312
|
put2("item_version", version2, "error"),
|
|
@@ -193397,12 +193404,12 @@ var init_governance_service = __esm({
|
|
|
193397
193404
|
await this.setRuntimeState(store, scope, version2, "provider", "missing", "APPROVED_REVISION_UNREADABLE");
|
|
193398
193405
|
}
|
|
193399
193406
|
}
|
|
193400
|
-
const
|
|
193401
|
-
if (!
|
|
193402
|
-
await this.setRuntimeState(store, scope, version2, "snapshot",
|
|
193407
|
+
const snapshot2 = (await store.list(scope, "snapshot")).find((entry) => entry.ref === version2.contentSnapshotRef);
|
|
193408
|
+
if (!snapshot2 || snapshot2.contentHash !== sha256(snapshot2.content)) {
|
|
193409
|
+
await this.setRuntimeState(store, scope, version2, "snapshot", snapshot2 ? "corrupt" : "missing", snapshot2 ? "SNAPSHOT_HASH_MISMATCH" : "SNAPSHOT_MISSING");
|
|
193403
193410
|
throw new KnowledgeGovernanceError(409, "KNOWLEDGE_APPROVED_CONTENT_UNREADABLE", "\u6279\u51C6 Revision \u4E0E Snapshot \u5747\u4E0D\u53EF\u8BFB");
|
|
193404
193411
|
}
|
|
193405
|
-
return { content:
|
|
193412
|
+
return { content: snapshot2.content, source: "snapshot" };
|
|
193406
193413
|
}
|
|
193407
193414
|
async findItemAndVersion(ctx, store, projectId2, itemId) {
|
|
193408
193415
|
const scopes = [this.orgScope(ctx), ...projectId2 ? [this.projectScope(ctx, projectId2)] : []];
|
|
@@ -195489,36 +195496,36 @@ function keyBytes(key) {
|
|
|
195489
195496
|
if (value2.length !== 32) throw new Error("knowledge snapshot key must be 32 bytes");
|
|
195490
195497
|
return value2;
|
|
195491
195498
|
}
|
|
195492
|
-
function aad(
|
|
195499
|
+
function aad(snapshot2) {
|
|
195493
195500
|
return Buffer.from([
|
|
195494
|
-
|
|
195495
|
-
|
|
195496
|
-
|
|
195497
|
-
|
|
195498
|
-
|
|
195501
|
+
snapshot2.organizationId,
|
|
195502
|
+
snapshot2.projectId ?? "organization",
|
|
195503
|
+
snapshot2.spaceId ?? "none",
|
|
195504
|
+
snapshot2.ref,
|
|
195505
|
+
snapshot2.contentHash
|
|
195499
195506
|
].join("\0"), "utf8");
|
|
195500
195507
|
}
|
|
195501
|
-
function sealKnowledgeSnapshot(
|
|
195502
|
-
if (
|
|
195508
|
+
function sealKnowledgeSnapshot(snapshot2, key) {
|
|
195509
|
+
if (snapshot2.content.startsWith(PREFIX)) return structuredClone(snapshot2);
|
|
195503
195510
|
const iv = (0, import_node_crypto29.randomBytes)(12);
|
|
195504
195511
|
const cipher = (0, import_node_crypto29.createCipheriv)("aes-256-gcm", keyBytes(key), iv);
|
|
195505
|
-
cipher.setAAD(aad(
|
|
195506
|
-
const encrypted = Buffer.concat([cipher.update(
|
|
195512
|
+
cipher.setAAD(aad(snapshot2));
|
|
195513
|
+
const encrypted = Buffer.concat([cipher.update(snapshot2.content, "utf8"), cipher.final()]);
|
|
195507
195514
|
return {
|
|
195508
|
-
...structuredClone(
|
|
195515
|
+
...structuredClone(snapshot2),
|
|
195509
195516
|
content: `${PREFIX}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}`
|
|
195510
195517
|
};
|
|
195511
195518
|
}
|
|
195512
|
-
function openKnowledgeSnapshot(
|
|
195513
|
-
if (!
|
|
195514
|
-
const packed =
|
|
195515
|
-
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${
|
|
195519
|
+
function openKnowledgeSnapshot(snapshot2, key) {
|
|
195520
|
+
if (!snapshot2.content.startsWith(PREFIX)) return structuredClone(snapshot2);
|
|
195521
|
+
const packed = snapshot2.content.slice(PREFIX.length).split(".");
|
|
195522
|
+
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot2.ref} ciphertext is malformed`);
|
|
195516
195523
|
const [iv, tag, data] = packed;
|
|
195517
195524
|
const decipher = (0, import_node_crypto29.createDecipheriv)("aes-256-gcm", keyBytes(key), Buffer.from(iv, "base64url"));
|
|
195518
|
-
decipher.setAAD(aad(
|
|
195525
|
+
decipher.setAAD(aad(snapshot2));
|
|
195519
195526
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
195520
195527
|
const content3 = Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8");
|
|
195521
|
-
return { ...structuredClone(
|
|
195528
|
+
return { ...structuredClone(snapshot2), content: content3 };
|
|
195522
195529
|
}
|
|
195523
195530
|
var import_node_crypto29, PREFIX;
|
|
195524
195531
|
var init_snapshot_crypto = __esm({
|
|
@@ -196265,9 +196272,9 @@ function parentConversationTaskLines() {
|
|
|
196265
196272
|
`- ${PARENT_CONVERSATION_PATH}`
|
|
196266
196273
|
];
|
|
196267
196274
|
}
|
|
196268
|
-
function delegationBundleAdditions(
|
|
196269
|
-
if (!
|
|
196270
|
-
return { files: { [PARENT_CONVERSATION_PATH]:
|
|
196275
|
+
function delegationBundleAdditions(snapshot2) {
|
|
196276
|
+
if (!snapshot2) return { files: {}, taskLines: [] };
|
|
196277
|
+
return { files: { [PARENT_CONVERSATION_PATH]: snapshot2 }, taskLines: parentConversationTaskLines() };
|
|
196271
196278
|
}
|
|
196272
196279
|
var PARENT_CONVERSATION_RECENT_TURNS, FIRST_LINE_MAX, ROLE_LABEL;
|
|
196273
196280
|
var init_parent_conversation = __esm({
|
|
@@ -196985,13 +196992,13 @@ var init_service3 = __esm({
|
|
|
196985
196992
|
consumedAt: now,
|
|
196986
196993
|
at: now
|
|
196987
196994
|
});
|
|
196988
|
-
const
|
|
196995
|
+
const snapshot2 = buildParentConversationSnapshot(
|
|
196989
196996
|
parentMessages,
|
|
196990
196997
|
this.options.recentTurns === void 0 ? void 0 : { recentTurns: this.options.recentTurns }
|
|
196991
196998
|
);
|
|
196992
196999
|
const turns = await this.resolveTurns(companyId);
|
|
196993
197000
|
const claimed = await this.claim(store, record8.id, now, Boolean(turns));
|
|
196994
|
-
if (claimed) this.track(this.dispatchExpert(claimed, input.task, companyId,
|
|
197001
|
+
if (claimed) this.track(this.dispatchExpert(claimed, input.task, companyId, snapshot2, turns, { inbound }));
|
|
196995
197002
|
if (inserted) this.options.metrics?.recordCreated();
|
|
196996
197003
|
return { record: record8, created: inserted };
|
|
196997
197004
|
}
|
|
@@ -197025,10 +197032,10 @@ var init_service3 = __esm({
|
|
|
197025
197032
|
const expert = { actorId: record8.expertActorId, name: named?.name ?? actorSlug(record8.expertActorId) };
|
|
197026
197033
|
const now = this.now();
|
|
197027
197034
|
await this.materializeChild({ record: record8, chatStore, parent, expert, task: input.task, companyId, now });
|
|
197028
|
-
const
|
|
197035
|
+
const snapshot2 = await this.parentSnapshot(chatStore, parent.id);
|
|
197029
197036
|
const turns = await this.resolveTurns(companyId);
|
|
197030
197037
|
const claimed = await this.claim(store, record8.id, now, Boolean(turns));
|
|
197031
|
-
if (claimed) this.track(this.dispatchExpert(claimed, input.task, companyId,
|
|
197038
|
+
if (claimed) this.track(this.dispatchExpert(claimed, input.task, companyId, snapshot2, turns, { inbound }));
|
|
197032
197039
|
return { record: record8, created: false };
|
|
197033
197040
|
}
|
|
197034
197041
|
async materializeChild(args) {
|
|
@@ -197103,7 +197110,7 @@ var init_service3 = __esm({
|
|
|
197103
197110
|
* 覆盖事实——而且是**不可逆的**:`failed` 之后租约回收再也不成立,那条既有 run 接不回来。
|
|
197104
197111
|
* 那一类只释放派发所有权、其余原样留着,等账本恢复后由同一把稳定 dispatchId 接回去。
|
|
197105
197112
|
*/
|
|
197106
|
-
async dispatchExpert(record8, task, companyId,
|
|
197113
|
+
async dispatchExpert(record8, task, companyId, snapshot2, turns, opts) {
|
|
197107
197114
|
const inbound = opts?.inbound;
|
|
197108
197115
|
let outcomeSettled = false;
|
|
197109
197116
|
const notDispatched = async (reason) => {
|
|
@@ -197160,7 +197167,7 @@ var init_service3 = __esm({
|
|
|
197160
197167
|
chatSessionId: record8.childSessionId,
|
|
197161
197168
|
dispatchId,
|
|
197162
197169
|
...companyId ? { companyId } : {},
|
|
197163
|
-
...
|
|
197170
|
+
...snapshot2 ? { parentConversationSnapshot: snapshot2 } : {},
|
|
197164
197171
|
extraSystemPrompt: EXPERT_DELEGATION_SYSTEM_PROMPT,
|
|
197165
197172
|
..._DelegationService.inboundBundle(inbound) ? { workspaceBundle: _DelegationService.inboundBundle(inbound) } : {},
|
|
197166
197173
|
/* 派发这一侧要拿它们建 `chat_items` 账本(见本文件 `DelegationDispatchRequest` 的注释)。
|
|
@@ -197445,7 +197452,7 @@ var init_service3 = __esm({
|
|
|
197445
197452
|
},
|
|
197446
197453
|
wantedFiles
|
|
197447
197454
|
) : void 0;
|
|
197448
|
-
const
|
|
197455
|
+
const snapshot2 = await this.parentSnapshot(chatStore, record8.parentSessionId).catch(() => null);
|
|
197449
197456
|
const released = await store.patch(record8.id, {
|
|
197450
197457
|
state: "running",
|
|
197451
197458
|
failureKind: null,
|
|
@@ -197478,7 +197485,7 @@ var init_service3 = __esm({
|
|
|
197478
197485
|
await restore();
|
|
197479
197486
|
return false;
|
|
197480
197487
|
}
|
|
197481
|
-
this.track(this.dispatchExpert(claimed, body2, companyId,
|
|
197488
|
+
this.track(this.dispatchExpert(claimed, body2, companyId, snapshot2, turns, {
|
|
197482
197489
|
...inbound ? { inbound } : {},
|
|
197483
197490
|
/**
|
|
197484
197491
|
* **送到专家手上那一刻才算消费**(见 `dispatchExpert` 的 `onDispatched`)。
|
|
@@ -197586,7 +197593,7 @@ var init_service3 = __esm({
|
|
|
197586
197593
|
const now = this.now();
|
|
197587
197594
|
const messages = await this.parentMessages(chatStore, parent.id);
|
|
197588
197595
|
const messageId = this.touchAnchor(_DelegationService.birthMessageId(messages) || record8.id);
|
|
197589
|
-
const
|
|
197596
|
+
const snapshot2 = buildParentConversationSnapshot(
|
|
197590
197597
|
messages,
|
|
197591
197598
|
this.options.recentTurns === void 0 ? void 0 : { recentTurns: this.options.recentTurns }
|
|
197592
197599
|
);
|
|
@@ -197606,7 +197613,7 @@ var init_service3 = __esm({
|
|
|
197606
197613
|
\u3010\u968F\u8FD9\u6761\u8F6C\u8FBE\u9644\u5E26\u7684\u6587\u4EF6\u3011\u5DF2\u653E\u8FDB\u4F60\u7684\u5DE5\u4F5C\u76EE\u5F55\uFF0C\u53EF\u76F4\u63A5\u8BFB\u53D6\uFF1A
|
|
197607
197614
|
${inboundBundle.paths.map((path43) => `- ${path43}`).join("\n")}` : text5,
|
|
197608
197615
|
files: {
|
|
197609
|
-
...
|
|
197616
|
+
...snapshot2 ? { [PARENT_CONVERSATION_PATH]: snapshot2 } : {},
|
|
197610
197617
|
...inboundBundle.files
|
|
197611
197618
|
},
|
|
197612
197619
|
...Object.keys(inboundBundle.binaryFiles).length ? { binaryFiles: inboundBundle.binaryFiles } : {}
|
|
@@ -197691,9 +197698,9 @@ ${inboundBundle.paths.map((path43) => `- ${path43}`).join("\n")}` : text5,
|
|
|
197691
197698
|
const record8 = await store.get(delegationId);
|
|
197692
197699
|
if (!record8) return null;
|
|
197693
197700
|
const chatStore = await this.options.resolveChatSessions(companyId);
|
|
197694
|
-
const
|
|
197701
|
+
const snapshot2 = await this.parentSnapshot(chatStore, record8.parentSessionId);
|
|
197695
197702
|
return {
|
|
197696
|
-
...
|
|
197703
|
+
...snapshot2 ? { parentConversationSnapshot: snapshot2 } : {},
|
|
197697
197704
|
extraSystemPrompt: EXPERT_DELEGATION_SYSTEM_PROMPT
|
|
197698
197705
|
};
|
|
197699
197706
|
}
|
|
@@ -198080,11 +198087,11 @@ var init_store2 = __esm({
|
|
|
198080
198087
|
return store;
|
|
198081
198088
|
}
|
|
198082
198089
|
save() {
|
|
198083
|
-
const
|
|
198090
|
+
const snapshot2 = {
|
|
198084
198091
|
delegations: [...this.rows.values()],
|
|
198085
198092
|
touches: [...this.touches.values()]
|
|
198086
198093
|
};
|
|
198087
|
-
fs17.writeFileSync(this.file, JSON.stringify(
|
|
198094
|
+
fs17.writeFileSync(this.file, JSON.stringify(snapshot2, null, 2));
|
|
198088
198095
|
}
|
|
198089
198096
|
async create(record8) {
|
|
198090
198097
|
const r = await super.create(record8);
|
|
@@ -201415,8 +201422,8 @@ async function loadSnapshot(api, credentials, scope, force = false) {
|
|
|
201415
201422
|
const now = Date.now();
|
|
201416
201423
|
const entry = snapshots.get(key);
|
|
201417
201424
|
if (force) {
|
|
201418
|
-
const
|
|
201419
|
-
return { snapshot:
|
|
201425
|
+
const snapshot3 = await startSnapshotRefresh(api, credentials, scope);
|
|
201426
|
+
return { snapshot: snapshot3, status: "refreshed", ageMs: Math.max(0, Date.now() - snapshot3.loadedAt) };
|
|
201420
201427
|
}
|
|
201421
201428
|
if (entry?.value && entry.freshUntil > now) {
|
|
201422
201429
|
return { snapshot: entry.value, status: "fresh", ageMs: Math.max(0, now - entry.value.loadedAt) };
|
|
@@ -201425,8 +201432,8 @@ async function loadSnapshot(api, credentials, scope, force = false) {
|
|
|
201425
201432
|
void startSnapshotRefresh(api, credentials, scope).catch(() => void 0);
|
|
201426
201433
|
return { snapshot: entry.value, status: "stale", ageMs: Math.max(0, now - entry.value.loadedAt) };
|
|
201427
201434
|
}
|
|
201428
|
-
const
|
|
201429
|
-
return { snapshot, status: "miss", ageMs: Math.max(0, Date.now() -
|
|
201435
|
+
const snapshot2 = await startSnapshotRefresh(api, credentials, scope);
|
|
201436
|
+
return { snapshot: snapshot2, status: "miss", ageMs: Math.max(0, Date.now() - snapshot2.loadedAt) };
|
|
201430
201437
|
}
|
|
201431
201438
|
function invalidateOutlineKnowledgeCache(credentials, scope) {
|
|
201432
201439
|
snapshots.delete(snapshotKey(credentials, scope));
|
|
@@ -201439,9 +201446,9 @@ function evidenceLevel2(path43) {
|
|
|
201439
201446
|
if (["wiki/index", "wiki/overview", "wiki/sources"].includes(path43)) return "index";
|
|
201440
201447
|
return "other";
|
|
201441
201448
|
}
|
|
201442
|
-
function snapshotMatches(
|
|
201449
|
+
function snapshotMatches(snapshot2, plannedQueries) {
|
|
201443
201450
|
return plannedQueries.map((query) => {
|
|
201444
|
-
const nodes = [...
|
|
201451
|
+
const nodes = [...snapshot2.byId.values()].filter((node2) => node2.path && node2.path !== "raw" && !node2.path.startsWith("raw/"));
|
|
201445
201452
|
const queryTerms = lexicalTerms(query.text);
|
|
201446
201453
|
const titleScores = bm25Scores(queryTerms, nodes.map((node2) => node2.title));
|
|
201447
201454
|
const pathScores = bm25Scores(queryTerms, nodes.map((node2) => node2.path));
|
|
@@ -201484,16 +201491,16 @@ function mergeSearchCandidates(apiResults, localResults) {
|
|
|
201484
201491
|
return { status: "fulfilled", value: [...merged.values()] };
|
|
201485
201492
|
});
|
|
201486
201493
|
}
|
|
201487
|
-
function rankCandidates(results,
|
|
201494
|
+
function rankCandidates(results, snapshot2, plannedQueries) {
|
|
201488
201495
|
const merged = /* @__PURE__ */ new Map();
|
|
201489
201496
|
results.forEach((result, queryIndex) => {
|
|
201490
201497
|
if (result.status !== "fulfilled") return;
|
|
201491
201498
|
result.value.forEach((document4, sourceIndex) => {
|
|
201492
201499
|
const ref2 = string6(document4["id"]);
|
|
201493
|
-
const node2 = ref2 ?
|
|
201500
|
+
const node2 = ref2 ? snapshot2.byId.get(ref2) : void 0;
|
|
201494
201501
|
const title = string6(document4["title"]);
|
|
201495
201502
|
const url = string6(document4["url"]) ?? "";
|
|
201496
|
-
if (!ref2 || !node2 || !title || !
|
|
201503
|
+
if (!ref2 || !node2 || !title || !snapshot2.scopedIds.has(ref2) || node2.path === "raw" || node2.path.startsWith("raw/")) return;
|
|
201497
201504
|
const sourceRank = sourceIndex + 1;
|
|
201498
201505
|
const candidateSource = document4["candidateSource"] === "snapshot" ? "snapshot" : "api";
|
|
201499
201506
|
const sources = document4["candidateSource"] === "hybrid" ? /* @__PURE__ */ new Set(["api", "snapshot"]) : /* @__PURE__ */ new Set([candidateSource]);
|
|
@@ -201558,7 +201565,7 @@ async function mapConcurrent(values, limit, mapper) {
|
|
|
201558
201565
|
await Promise.all(workers);
|
|
201559
201566
|
return results;
|
|
201560
201567
|
}
|
|
201561
|
-
async function readCandidates(api, credentials, scope,
|
|
201568
|
+
async function readCandidates(api, credentials, scope, snapshot2, candidates, limit = MAX_READ_CANDIDATES) {
|
|
201562
201569
|
let refreshed;
|
|
201563
201570
|
const values = await mapConcurrent(candidates.slice(0, limit), READ_CONCURRENCY, async (candidate) => {
|
|
201564
201571
|
try {
|
|
@@ -201570,7 +201577,7 @@ async function readCandidates(api, credentials, scope, snapshot, candidates, lim
|
|
|
201570
201577
|
const parentDocumentId = string6(document4["parentDocumentId"]);
|
|
201571
201578
|
if (collectionId !== scope.libraryRef || !url || !text5 || !updatedAt) return null;
|
|
201572
201579
|
if (new URL(url).origin !== new URL(api.baseUrl).origin) return null;
|
|
201573
|
-
let activeSnapshot =
|
|
201580
|
+
let activeSnapshot = snapshot2;
|
|
201574
201581
|
const listed = activeSnapshot.byId.get(candidate.ref);
|
|
201575
201582
|
if (!listed || listed.updatedAt !== updatedAt || listed.parentId !== parentDocumentId) {
|
|
201576
201583
|
refreshed ??= loadSnapshot(api, credentials, scope, true).then((loaded) => loaded.snapshot);
|
|
@@ -201612,12 +201619,12 @@ function snapshotRankedCandidate(node2, queryIndexes, score) {
|
|
|
201612
201619
|
evidenceLevel: evidenceLevel2(node2.path)
|
|
201613
201620
|
};
|
|
201614
201621
|
}
|
|
201615
|
-
function routingPageCandidates(
|
|
201622
|
+
function routingPageCandidates(snapshot2, queryCount) {
|
|
201616
201623
|
const paths = /* @__PURE__ */ new Set(["wiki/overview", "wiki/index"]);
|
|
201617
|
-
return [...
|
|
201624
|
+
return [...snapshot2.byId.values()].filter((node2) => paths.has(node2.path.toLocaleLowerCase())).map((node2) => snapshotRankedCandidate(node2, new Set(Array.from({ length: queryCount }, (_2, index2) => index2)), 0.05));
|
|
201618
201625
|
}
|
|
201619
|
-
function linkedCandidates(documents,
|
|
201620
|
-
const byPath = new Map([...
|
|
201626
|
+
function linkedCandidates(documents, snapshot2, queries, excludedRefs) {
|
|
201627
|
+
const byPath = new Map([...snapshot2.byId.values()].map((node2) => [node2.path.toLocaleLowerCase(), node2]));
|
|
201621
201628
|
const ranked = /* @__PURE__ */ new Map();
|
|
201622
201629
|
for (const document4 of documents) {
|
|
201623
201630
|
for (const match of document4.text.matchAll(/\[([^\]]+)\]\(kb:\/\/([^\s)#]+)(?:#[^)]*)?\)/gu)) {
|
|
@@ -201834,35 +201841,35 @@ async function retrieveOutlineKnowledge(credentials, scope, request2) {
|
|
|
201834
201841
|
const snapshotStartedAt = performance.now();
|
|
201835
201842
|
let loadedSnapshot = await loadSnapshot(api, credentials, scope);
|
|
201836
201843
|
request2.signal?.throwIfAborted();
|
|
201837
|
-
let
|
|
201844
|
+
let snapshot2 = loadedSnapshot.snapshot;
|
|
201838
201845
|
let snapshotMs = performance.now() - snapshotStartedAt;
|
|
201839
201846
|
const searchStartedAt = performance.now();
|
|
201840
201847
|
const searchResults = await Promise.allSettled(effectiveQueries.map((query) => api.searchDocuments(scope.libraryRef, query.text)));
|
|
201841
201848
|
request2.signal?.throwIfAborted();
|
|
201842
201849
|
const apiCandidateRefs = new Set(searchResults.flatMap((result) => result.status === "fulfilled" ? result.value.map((document4) => string6(document4["id"])).filter((ref2) => Boolean(ref2)) : []));
|
|
201843
201850
|
const emptySearchCount = searchResults.filter((result) => result.status === "fulfilled" && result.value.length === 0).length;
|
|
201844
|
-
let localResults = snapshotMatches(
|
|
201851
|
+
let localResults = snapshotMatches(snapshot2, effectiveQueries);
|
|
201845
201852
|
let snapshotCandidateRefs = new Set(localResults.flatMap((documents2) => documents2.map((document4) => string6(document4["id"])).filter((ref2) => Boolean(ref2))));
|
|
201846
|
-
let ranked = rankCandidates(mergeSearchCandidates(searchResults, localResults),
|
|
201853
|
+
let ranked = rankCandidates(mergeSearchCandidates(searchResults, localResults), snapshot2, effectiveQueries);
|
|
201847
201854
|
let retrievalRounds = 1;
|
|
201848
201855
|
let recoveryReason;
|
|
201849
201856
|
if (ranked.length === 0) {
|
|
201850
201857
|
const refreshStartedAt = performance.now();
|
|
201851
201858
|
loadedSnapshot = await loadSnapshot(api, credentials, scope, true);
|
|
201852
|
-
|
|
201859
|
+
snapshot2 = loadedSnapshot.snapshot;
|
|
201853
201860
|
snapshotMs += performance.now() - refreshStartedAt;
|
|
201854
|
-
localResults = snapshotMatches(
|
|
201861
|
+
localResults = snapshotMatches(snapshot2, effectiveQueries);
|
|
201855
201862
|
snapshotCandidateRefs = new Set(localResults.flatMap((documents2) => documents2.map((document4) => string6(document4["id"])).filter((ref2) => Boolean(ref2))));
|
|
201856
|
-
ranked = rankCandidates(mergeSearchCandidates(searchResults, localResults),
|
|
201863
|
+
ranked = rankCandidates(mergeSearchCandidates(searchResults, localResults), snapshot2, effectiveQueries);
|
|
201857
201864
|
retrievalRounds = 2;
|
|
201858
201865
|
recoveryReason = "empty_candidates";
|
|
201859
201866
|
}
|
|
201860
201867
|
const searchMs = performance.now() - searchStartedAt;
|
|
201861
201868
|
const readStartedAt = performance.now();
|
|
201862
201869
|
request2.signal?.throwIfAborted();
|
|
201863
|
-
let documents = await readCandidates(api, credentials, scope,
|
|
201870
|
+
let documents = await readCandidates(api, credentials, scope, snapshot2, ranked, INITIAL_READ_CANDIDATES);
|
|
201864
201871
|
if (documents.length === 0) {
|
|
201865
|
-
const routingPages = await readCandidates(api, credentials, scope,
|
|
201872
|
+
const routingPages = await readCandidates(api, credentials, scope, snapshot2, routingPageCandidates(snapshot2, effectiveQueries.length), 2);
|
|
201866
201873
|
documents = routingPages;
|
|
201867
201874
|
retrievalRounds = 2;
|
|
201868
201875
|
recoveryReason ??= "insufficient_coverage";
|
|
@@ -201879,9 +201886,9 @@ async function retrieveOutlineKnowledge(credentials, scope, request2) {
|
|
|
201879
201886
|
const needsRouting = initialSelection.items.length === 0 || initialSelection.items.every((item) => item.evidenceLevel === "index") || initialMissing.length > 0;
|
|
201880
201887
|
if (needsRouting && documents.length < MAX_READ_CANDIDATES) {
|
|
201881
201888
|
const existingRefs = new Set(documents.map((document4) => document4.ref));
|
|
201882
|
-
const linked = linkedCandidates(documents,
|
|
201889
|
+
const linked = linkedCandidates(documents, snapshot2, effectiveQueries, existingRefs);
|
|
201883
201890
|
const remaining = MAX_READ_CANDIDATES - documents.length;
|
|
201884
|
-
const linkedDocuments = await readCandidates(api, credentials, scope,
|
|
201891
|
+
const linkedDocuments = await readCandidates(api, credentials, scope, snapshot2, linked, remaining);
|
|
201885
201892
|
if (linkedDocuments.length > 0) documents = [...documents, ...linkedDocuments];
|
|
201886
201893
|
retrievalRounds = 2;
|
|
201887
201894
|
recoveryReason ??= "insufficient_coverage";
|
|
@@ -201936,7 +201943,7 @@ async function retrieveOutlineKnowledge(credentials, scope, request2) {
|
|
|
201936
201943
|
async function validateOutlineKnowledgeCitationsFast(credentials, scope, candidates) {
|
|
201937
201944
|
if (candidates.length === 0) return [];
|
|
201938
201945
|
const api = new OutlineKnowledgeApi(credentials);
|
|
201939
|
-
let
|
|
201946
|
+
let snapshot2 = (await loadSnapshot(api, credentials, scope)).snapshot;
|
|
201940
201947
|
let refreshed;
|
|
201941
201948
|
const seen = /* @__PURE__ */ new Set();
|
|
201942
201949
|
const unique4 = candidates.filter((candidate) => {
|
|
@@ -201945,7 +201952,7 @@ async function validateOutlineKnowledgeCitationsFast(credentials, scope, candida
|
|
|
201945
201952
|
return true;
|
|
201946
201953
|
}).slice(0, 20);
|
|
201947
201954
|
const validated = await mapConcurrent(unique4, READ_CONCURRENCY, async (candidate) => {
|
|
201948
|
-
if (!
|
|
201955
|
+
if (!snapshot2.scopedIds.has(candidate.ref)) return null;
|
|
201949
201956
|
try {
|
|
201950
201957
|
const document4 = await api.documentInfo(candidate.ref);
|
|
201951
201958
|
const ref2 = string6(document4["id"]);
|
|
@@ -201956,12 +201963,12 @@ async function validateOutlineKnowledgeCitationsFast(credentials, scope, candida
|
|
|
201956
201963
|
const parentDocumentId = string6(document4["parentDocumentId"]);
|
|
201957
201964
|
if (!ref2 || !title || !url || collectionId !== scope.libraryRef) return null;
|
|
201958
201965
|
if (new URL(url).origin !== new URL(api.baseUrl).origin) return null;
|
|
201959
|
-
const listed =
|
|
201966
|
+
const listed = snapshot2.byId.get(ref2);
|
|
201960
201967
|
if (!listed || updatedAt && listed.updatedAt !== updatedAt || listed.parentId !== parentDocumentId) {
|
|
201961
201968
|
refreshed ??= loadSnapshot(api, credentials, scope, true).then((loaded) => loaded.snapshot);
|
|
201962
|
-
|
|
201969
|
+
snapshot2 = await refreshed;
|
|
201963
201970
|
}
|
|
201964
|
-
if (!
|
|
201971
|
+
if (!snapshot2.scopedIds.has(ref2)) return null;
|
|
201965
201972
|
return { ref: ref2, title, url, ...updatedAt ? { updatedAt } : {} };
|
|
201966
201973
|
} catch {
|
|
201967
201974
|
return null;
|
|
@@ -205576,6 +205583,26 @@ async function startOasisServer(opts) {
|
|
|
205576
205583
|
);
|
|
205577
205584
|
return;
|
|
205578
205585
|
}
|
|
205586
|
+
if (opts.isDispatchFenced && (req.method !== "GET" && req.method !== "HEAD" || url.pathname === "/api/whoami")) {
|
|
205587
|
+
const token = (req.headers.authorization ?? "").replace(/^Bearer /, "");
|
|
205588
|
+
const claims = opts.resolveTokenClaims?.(token);
|
|
205589
|
+
let fenced = false;
|
|
205590
|
+
if (claims?.dispatchId) {
|
|
205591
|
+
try {
|
|
205592
|
+
fenced = await opts.isDispatchFenced(claims.dispatchId);
|
|
205593
|
+
} catch {
|
|
205594
|
+
res.writeHead(503, { "content-type": "application/json" }).end(JSON.stringify({ error: {
|
|
205595
|
+
code: "EXECUTION_STATE_UNAVAILABLE",
|
|
205596
|
+
message: "\u6682\u65F6\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D\u6267\u884C\u8F6E\u6B21\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5\u3002"
|
|
205597
|
+
} }));
|
|
205598
|
+
return;
|
|
205599
|
+
}
|
|
205600
|
+
}
|
|
205601
|
+
if (fenced) {
|
|
205602
|
+
res.writeHead(409, { "content-type": "application/json" }).end(JSON.stringify({ error: { code: "DISPATCH_FENCED", message: "\u672C\u8F6E\u6267\u884C\u5DF2\u5931\u6548\uFF0C\u8BF7\u505C\u6B62\u8FD0\u884C\uFF1B\u540C\u4E00\u4EFB\u52A1\u53EA\u6709\u6700\u65B0\u4E00\u8F6E\u53EF\u4EE5\u542F\u52A8\u548C\u63D0\u4EA4\u7ED3\u679C\u3002" } }));
|
|
205603
|
+
return;
|
|
205604
|
+
}
|
|
205605
|
+
}
|
|
205579
205606
|
if (url.pathname === "/api/whoami" && req.method === "GET") {
|
|
205580
205607
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ actor }));
|
|
205581
205608
|
return;
|
|
@@ -205688,7 +205715,7 @@ async function startOasisServer(opts) {
|
|
|
205688
205715
|
const bearerToken = (req.headers.authorization ?? "").startsWith("Bearer ") ? req.headers.authorization.slice("Bearer ".length) : "";
|
|
205689
205716
|
const tokenClaims = bearerToken && opts.resolveTokenClaims ? opts.resolveTokenClaims(bearerToken) : null;
|
|
205690
205717
|
if (opts.isDispatchFenced && tokenClaims?.dispatchId) {
|
|
205691
|
-
const fenced = await opts.isDispatchFenced(tokenClaims.dispatchId)
|
|
205718
|
+
const fenced = await opts.isDispatchFenced(tokenClaims.dispatchId);
|
|
205692
205719
|
if (fenced) {
|
|
205693
205720
|
throw new ApiError(
|
|
205694
205721
|
409,
|
|
@@ -207756,13 +207783,13 @@ ${composed}`;
|
|
|
207756
207783
|
const actorCtx = await opts.resolveActorContext(body2.actorId).catch(() => null);
|
|
207757
207784
|
if (actorCtx) {
|
|
207758
207785
|
const { mkdtempSync: mkdtempSync6, mkdirSync: mkdirSync27, writeFileSync: writeFileSync20 } = await import("node:fs");
|
|
207759
|
-
const { join: join42, dirname:
|
|
207786
|
+
const { join: join42, dirname: dirname37 } = await import("node:path");
|
|
207760
207787
|
const { tmpdir: tmpdir13 } = await import("node:os");
|
|
207761
207788
|
const dir = mkdtempSync6(join42(tmpdir13(), "oasis-chat-"));
|
|
207762
207789
|
if (actorCtx.config?.prompt) {
|
|
207763
207790
|
for (const [rel, content3] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
207764
207791
|
const file = join42(dir, rel);
|
|
207765
|
-
mkdirSync27(
|
|
207792
|
+
mkdirSync27(dirname37(file), { recursive: true });
|
|
207766
207793
|
writeFileSync20(file, content3);
|
|
207767
207794
|
}
|
|
207768
207795
|
}
|
|
@@ -207779,7 +207806,7 @@ ${composed}`;
|
|
|
207779
207806
|
const skillFiles = await opts.materializeSkills(body2.actorId, "claude").catch(() => ({}));
|
|
207780
207807
|
for (const [rel, content3] of Object.entries(skillFiles)) {
|
|
207781
207808
|
const file = join42(dir, rel);
|
|
207782
|
-
mkdirSync27(
|
|
207809
|
+
mkdirSync27(dirname37(file), { recursive: true });
|
|
207783
207810
|
writeFileSync20(file, content3);
|
|
207784
207811
|
}
|
|
207785
207812
|
}
|
|
@@ -210215,8 +210242,8 @@ var init_memory_trace_store = __esm({
|
|
|
210215
210242
|
handoffs: [...this.handoffs.values()].map((x2) => structuredClone(x2))
|
|
210216
210243
|
};
|
|
210217
210244
|
}
|
|
210218
|
-
restoreContinuity(
|
|
210219
|
-
for (const checkpoint of
|
|
210245
|
+
restoreContinuity(snapshot2) {
|
|
210246
|
+
for (const checkpoint of snapshot2.checkpoints ?? []) {
|
|
210220
210247
|
const run = this.runs.get(checkpoint.attemptId);
|
|
210221
210248
|
const list2 = this.checkpoints.get(checkpoint.attemptId) ?? [];
|
|
210222
210249
|
list2.push(structuredClone({
|
|
@@ -210231,7 +210258,7 @@ var init_memory_trace_store = __esm({
|
|
|
210231
210258
|
const n = Number(checkpoint.checkpointId.replace(/^checkpoint_/, ""));
|
|
210232
210259
|
if (Number.isFinite(n)) this.checkpointIdCounter = Math.max(this.checkpointIdCounter, n);
|
|
210233
210260
|
}
|
|
210234
|
-
for (const effect of
|
|
210261
|
+
for (const effect of snapshot2.externalEffects ?? []) {
|
|
210235
210262
|
this.externalEffects.set(`${effect.nodeId}\0${effect.idempotencyKey}`, structuredClone({
|
|
210236
210263
|
...effect,
|
|
210237
210264
|
status: effect.status ?? "succeeded",
|
|
@@ -210239,7 +210266,7 @@ var init_memory_trace_store = __esm({
|
|
|
210239
210266
|
occurredAt: effect.occurredAt ?? null
|
|
210240
210267
|
}));
|
|
210241
210268
|
}
|
|
210242
|
-
for (const handoff of
|
|
210269
|
+
for (const handoff of snapshot2.handoffs ?? []) {
|
|
210243
210270
|
const run = this.runs.get(handoff.attemptId);
|
|
210244
210271
|
this.handoffs.set(handoff.attemptId, structuredClone({
|
|
210245
210272
|
...handoff,
|
|
@@ -219218,6 +219245,7 @@ var init_daemon_hub = __esm({
|
|
|
219218
219245
|
/** 外部可订阅的事件回调 */
|
|
219219
219246
|
onDaemonConnected;
|
|
219220
219247
|
onDaemonDisconnected;
|
|
219248
|
+
executionIsCurrent;
|
|
219221
219249
|
onMessage;
|
|
219222
219250
|
messageListeners = /* @__PURE__ */ new Set();
|
|
219223
219251
|
requireExecutionStopPersistence;
|
|
@@ -219247,6 +219275,13 @@ var init_daemon_hub = __esm({
|
|
|
219247
219275
|
});
|
|
219248
219276
|
});
|
|
219249
219277
|
}
|
|
219278
|
+
async acceptExecutionFrame(nodeId, msg) {
|
|
219279
|
+
if (msg.type !== "session_started" && msg.type !== "dispatch_received" || !this.executionIsCurrent) return true;
|
|
219280
|
+
if (await this.executionIsCurrent(msg.dispatchId)) return true;
|
|
219281
|
+
const kill = { type: "kill", dispatchId: msg.dispatchId };
|
|
219282
|
+
if (!this.sendToSession(msg.dispatchId, kill)) this.dispatch(nodeId, kill);
|
|
219283
|
+
return false;
|
|
219284
|
+
}
|
|
219250
219285
|
async persistExecutionStop(nodeId, msg) {
|
|
219251
219286
|
if (msg.type !== "session_exited" || msg.executionStopped !== true) return;
|
|
219252
219287
|
if (this.requireExecutionStopPersistence && this.executionStopListeners.size === 0) throw new Error("\u505C\u6B62\u8BC1\u660E\u5B58\u50A8\u5668\u5C1A\u672A\u5C31\u7EEA");
|
|
@@ -219431,6 +219466,9 @@ var init_daemon_hub = __esm({
|
|
|
219431
219466
|
ws.close(1008, "session identity mismatch");
|
|
219432
219467
|
return;
|
|
219433
219468
|
}
|
|
219469
|
+
if (this.executionIsCurrent && !await this.executionIsCurrent(dispatchId)) {
|
|
219470
|
+
ws.send(JSON.stringify({ type: "kill", dispatchId }));
|
|
219471
|
+
}
|
|
219434
219472
|
if (!registered) {
|
|
219435
219473
|
registered = true;
|
|
219436
219474
|
this.sessionSockets.set(dispatchId, ws);
|
|
@@ -219458,6 +219496,7 @@ var init_daemon_hub = __esm({
|
|
|
219458
219496
|
ws.close(1008, "session identity mismatch");
|
|
219459
219497
|
return;
|
|
219460
219498
|
}
|
|
219499
|
+
if (!await this.acceptExecutionFrame(nodeId, msg)) return;
|
|
219461
219500
|
await this.persistExecutionStop(nodeId, msg);
|
|
219462
219501
|
if (this.frameSeqSupported.has(dispatchId)) {
|
|
219463
219502
|
const seq = typeof msg.seq === "number" ? msg.seq : void 0;
|
|
@@ -219732,6 +219771,7 @@ var init_daemon_hub = __esm({
|
|
|
219732
219771
|
for (const listener of this.connectListeners) listener(daemon);
|
|
219733
219772
|
}
|
|
219734
219773
|
}
|
|
219774
|
+
if (!await this.acceptExecutionFrame(daemonId, msg)) return;
|
|
219735
219775
|
await this.persistExecutionStop(daemonId, msg);
|
|
219736
219776
|
this.onMessage?.(daemonId, msg);
|
|
219737
219777
|
for (const listener of this.messageListeners) listener(daemonId, msg);
|
|
@@ -221033,8 +221073,8 @@ ${input.description}
|
|
|
221033
221073
|
* 密文原样搬运,不经解密再加密——少一次明文落到内存里,也不受密钥轮换影响。
|
|
221034
221074
|
* 返回改了几行,调用方好把「回滚做了什么」如实说出来(回滚静默是上一版的毛病)。
|
|
221035
221075
|
*/
|
|
221036
|
-
async restoreActorConnectorVars(actorId, connectorId,
|
|
221037
|
-
const keep = new Map(
|
|
221076
|
+
async restoreActorConnectorVars(actorId, connectorId, snapshot2) {
|
|
221077
|
+
const keep = new Map(snapshot2.map((r) => [r.key, r]));
|
|
221038
221078
|
const now = await this.snapshotActorConnectorVars(actorId, connectorId);
|
|
221039
221079
|
let removed = 0;
|
|
221040
221080
|
for (const row of now) {
|
|
@@ -225117,53 +225157,6 @@ var init_routes5 = __esm({
|
|
|
225117
225157
|
}
|
|
225118
225158
|
});
|
|
225119
225159
|
|
|
225120
|
-
// ../server/src/domains/collab/execution-stop-routes.ts
|
|
225121
|
-
function registerExecutionStopRoutes(router, options, context2) {
|
|
225122
|
-
const fail = (status, message) => ({ status, body: { error: { code: "execution_stop_recovery", message } } });
|
|
225123
|
-
router.get("/api/workorders/:id/execution-stops", async (req) => {
|
|
225124
|
-
if (!(await context2(req)).exists) return fail(404, "\u5DE5\u5355\u4E0D\u5B58\u5728");
|
|
225125
|
-
if (!options) return fail(503, "\u505C\u6B62\u8865\u8BC1\u670D\u52A1\u672A\u5C31\u7EEA");
|
|
225126
|
-
const ledger = await options.ledgerFor(req.auth.companyId);
|
|
225127
|
-
const rows = await ledger.listByWorkorder(req.params.id);
|
|
225128
|
-
const body2 = { items: rows.filter((r) => r.cancelRequestedAt).map((r) => ({
|
|
225129
|
-
dispatchId: r.id,
|
|
225130
|
-
daemonId: r.daemonId,
|
|
225131
|
-
createdAt: r.createdAt,
|
|
225132
|
-
requestedAt: r.cancelRequestedAt,
|
|
225133
|
-
stoppedAt: r.executionStoppedAt ?? null,
|
|
225134
|
-
check: r.executionRecovery ?? null
|
|
225135
|
-
})) };
|
|
225136
|
-
return { status: 200, body: body2 };
|
|
225137
|
-
});
|
|
225138
|
-
router.post("/api/workorders/:id/execution-stops/:dispatchId/verify", async (req) => {
|
|
225139
|
-
if (!isHumanActor(req.auth.actor)) return fail(403, "\u505C\u6B62\u8865\u8BC1\u662F\u6CBB\u7406\u64CD\u4F5C\uFF0C\u4EC5\u4EBA\u7C7B\u53EF\u6267\u884C");
|
|
225140
|
-
const ctx = await context2(req);
|
|
225141
|
-
if (!ctx.exists) return fail(404, "\u5DE5\u5355\u4E0D\u5B58\u5728");
|
|
225142
|
-
if (!options) return fail(503, "\u505C\u6B62\u8865\u8BC1\u670D\u52A1\u672A\u5C31\u7EEA");
|
|
225143
|
-
const ledger = await options.ledgerFor(req.auth.companyId);
|
|
225144
|
-
const row = await ledger.getById(req.params.dispatchId);
|
|
225145
|
-
if (!row || row.workorderId !== req.params.id) return fail(404, "\u8BE5\u5DE5\u5355\u6CA1\u6709\u6B64\u6D3E\u53D1\u8BB0\u5F55");
|
|
225146
|
-
if (!row.cancelRequestedAt) return fail(409, "\u8BE5\u6267\u884C\u5C1A\u672A\u8BF7\u6C42\u53D6\u6D88\uFF0C\u8BF7\u5148\u6682\u505C\u5DE5\u5355");
|
|
225147
|
-
const body2 = req.body;
|
|
225148
|
-
let verification;
|
|
225149
|
-
if (body2?.evidence !== void 0 || body2?.confirmed !== void 0) {
|
|
225150
|
-
if (!ctx.paused) return fail(409, "\u4EBA\u5DE5\u8865\u8BC1\u524D\u8BF7\u5148\u6682\u505C\u5DE5\u5355\uFF1B\u6838\u9A8C\u5B8C\u6210\u540E\u624B\u52A8\u6062\u590D\u6D3E\u53D1");
|
|
225151
|
-
if (body2.confirmed !== true || typeof body2.evidence !== "string" || body2.evidence.trim().length < 20 || body2.evidence.length > 4e3) {
|
|
225152
|
-
return fail(400, "\u9700\u660E\u786E\u786E\u8BA4\u5DF2\u6838\u9A8C\u539F\u5B9E\u4F8B\u3001\u5B50\u8FDB\u7A0B\u3001\u5BB9\u5668\u548C\u5F85\u542F\u52A8\u5165\u53E3\uFF0C\u5E76\u586B\u5199 20\u20134000 \u5B57\u6838\u9A8C\u4F9D\u636E");
|
|
225153
|
-
}
|
|
225154
|
-
verification = { actor: req.auth.actor, evidence: body2.evidence.trim() };
|
|
225155
|
-
}
|
|
225156
|
-
const result = await options.verify(ledger, row.id, verification);
|
|
225157
|
-
return { status: 200, body: result };
|
|
225158
|
-
});
|
|
225159
|
-
}
|
|
225160
|
-
var init_execution_stop_routes = __esm({
|
|
225161
|
-
"../server/src/domains/collab/execution-stop-routes.ts"() {
|
|
225162
|
-
"use strict";
|
|
225163
|
-
init_src5();
|
|
225164
|
-
}
|
|
225165
|
-
});
|
|
225166
|
-
|
|
225167
225160
|
// ../server/src/domains/collab/activity-notice.ts
|
|
225168
225161
|
var NOTICE_TITLE;
|
|
225169
225162
|
var init_activity_notice = __esm({
|
|
@@ -226477,6 +226470,8 @@ function buildSingleTrace(input) {
|
|
|
226477
226470
|
const actorId = d.actorId ?? executorId;
|
|
226478
226471
|
return {
|
|
226479
226472
|
runId: d.id,
|
|
226473
|
+
...d.outcome === "failed" && d.reason ? { dispatchError: d.reason } : {},
|
|
226474
|
+
...(input.dispatches ?? []).some((newer) => newer.jobKey && newer.jobKey === d.jobKey && (newer.executionGeneration ?? 0) > (d.executionGeneration ?? 0)) ? { superseded: true } : {},
|
|
226480
226475
|
...d.cancelRequestedAt ? { cancelRequestedAt: d.cancelRequestedAt } : {},
|
|
226481
226476
|
...d.executionStoppedAt ? { executionStoppedAt: d.executionStoppedAt } : {},
|
|
226482
226477
|
at: d.createdAt,
|
|
@@ -228556,13 +228551,6 @@ function collabDomain(opts) {
|
|
|
228556
228551
|
}
|
|
228557
228552
|
const resolverFor = async (companyId, registry2) => buildResolver(registry2, await memberNameResolver(opts.listMembers, companyId));
|
|
228558
228553
|
return (router) => {
|
|
228559
|
-
registerExecutionStopRoutes(router, opts.executionStopRecovery, async (req) => {
|
|
228560
|
-
const { kernel } = await resolveCtx(req.auth.companyId);
|
|
228561
|
-
return {
|
|
228562
|
-
exists: [...kernel.model.artifacts.values()].some((a) => a.workspace === req.params.id),
|
|
228563
|
-
paused: kernel.model.pausedWorkorders.has(req.params.id)
|
|
228564
|
-
};
|
|
228565
|
-
});
|
|
228566
228554
|
router.get("/api/organization/usage-summary", async (req) => {
|
|
228567
228555
|
if (!opts.trace) {
|
|
228568
228556
|
return { status: 503, body: { error: { code: "no_trace_store", message: "\u8FD0\u884C\u7528\u91CF\u6570\u636E\u6E90\u672A\u63A5\u5165" } } };
|
|
@@ -229326,7 +229314,6 @@ var init_collab = __esm({
|
|
|
229326
229314
|
init_workorders();
|
|
229327
229315
|
init_workorder_detail();
|
|
229328
229316
|
init_workorders();
|
|
229329
|
-
init_execution_stop_routes();
|
|
229330
229317
|
init_activity2();
|
|
229331
229318
|
init_review_activity();
|
|
229332
229319
|
init_activity_trace();
|
|
@@ -234244,8 +234231,8 @@ function renderResumePack(pack) {
|
|
|
234244
234231
|
const action = effect.status === "succeeded" ? "do not repeat" : effect.status === "pending" ? "execution uncertain; reconcile before retry" : "failed; retry allowed";
|
|
234245
234232
|
lines.push(`- [${effect.status}/${effect.source}] ${effect.kind} \u2192 ${effect.target} (${action}; key ${effect.idempotencyKey})`);
|
|
234246
234233
|
}
|
|
234247
|
-
const
|
|
234248
|
-
lines.push("", `${RESUME_SNAPSHOT_PREFIX}${
|
|
234234
|
+
const snapshot2 = Buffer.from(JSON.stringify(pack), "utf8").toString("base64url");
|
|
234235
|
+
lines.push("", `${RESUME_SNAPSHOT_PREFIX}${snapshot2}${RESUME_SNAPSHOT_SUFFIX}`);
|
|
234249
234236
|
return `${lines.join("\n")}
|
|
234250
234237
|
`;
|
|
234251
234238
|
}
|
|
@@ -235034,12 +235021,12 @@ function createReworkHandoffInputResolver(opts) {
|
|
|
235034
235021
|
const warn = opts.warn ?? ((message) => console.warn(`[rework-handoff] ${message}`));
|
|
235035
235022
|
return async (input) => {
|
|
235036
235023
|
try {
|
|
235037
|
-
const
|
|
235038
|
-
if (!
|
|
235024
|
+
const snapshot2 = await opts.loadWorkorder(input.workOrderId);
|
|
235025
|
+
if (!snapshot2) {
|
|
235039
235026
|
warn(`\u5DE5\u5355\u5FEB\u7167\u8BFB\u4E0D\u5230\uFF0C\u8DF3\u8FC7\u8FD4\u5DE5\u4EA4\u63A5\u6CE8\u5165\uFF1A${input.workOrderId}`);
|
|
235040
235027
|
return null;
|
|
235041
235028
|
}
|
|
235042
|
-
const work =
|
|
235029
|
+
const work = snapshot2.works.find(
|
|
235043
235030
|
(candidate) => candidate.id === input.workId && candidate.nodeId === input.nodeId
|
|
235044
235031
|
);
|
|
235045
235032
|
if (!work) {
|
|
@@ -235051,7 +235038,7 @@ function createReworkHandoffInputResolver(opts) {
|
|
|
235051
235038
|
if (!handoff && work.agentHandoffAttemptId) {
|
|
235052
235039
|
handoff = await opts.getHandoff(work.agentHandoffAttemptId).catch(() => null);
|
|
235053
235040
|
}
|
|
235054
|
-
const node2 =
|
|
235041
|
+
const node2 = snapshot2.nodes.find((candidate) => candidate.id === input.nodeId);
|
|
235055
235042
|
return renderReworkNodeHandoff({
|
|
235056
235043
|
nodeId: input.nodeId,
|
|
235057
235044
|
nodeTitle: node2?.title,
|
|
@@ -235071,12 +235058,12 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
235071
235058
|
const warn = opts.warn ?? ((message) => console.warn(`[upstream-handoff] ${message}`));
|
|
235072
235059
|
return async (input) => {
|
|
235073
235060
|
try {
|
|
235074
|
-
const
|
|
235075
|
-
if (!
|
|
235061
|
+
const snapshot2 = await opts.loadWorkorder(input.workOrderId);
|
|
235062
|
+
if (!snapshot2) {
|
|
235076
235063
|
warn(`\u5DE5\u5355\u5FEB\u7167\u8BFB\u4E0D\u5230\uFF0C\u8DF3\u8FC7\u4E0A\u6E38\u4EA4\u63A5\u6CE8\u5165\uFF1A${input.workOrderId}`);
|
|
235077
235064
|
return null;
|
|
235078
235065
|
}
|
|
235079
|
-
const edge =
|
|
235066
|
+
const edge = snapshot2.edges.find(
|
|
235080
235067
|
(candidate) => candidate.fromNodeId === input.upstreamNodeId && candidate.toNodeId === input.downstreamNodeId
|
|
235081
235068
|
);
|
|
235082
235069
|
const businessEdge = edge?.kind === "data" && edge.required;
|
|
@@ -235087,7 +235074,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
235087
235074
|
);
|
|
235088
235075
|
return null;
|
|
235089
235076
|
}
|
|
235090
|
-
const work =
|
|
235077
|
+
const work = snapshot2.works.find(
|
|
235091
235078
|
(candidate) => candidate.id === input.pinnedWorkId && candidate.nodeId === input.upstreamNodeId
|
|
235092
235079
|
);
|
|
235093
235080
|
if (!work) {
|
|
@@ -235097,7 +235084,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
235097
235084
|
if (typeof work.assigneeActorId === "string" && work.assigneeActorId.startsWith("actor:human:")) {
|
|
235098
235085
|
return null;
|
|
235099
235086
|
}
|
|
235100
|
-
const upstreamNode =
|
|
235087
|
+
const upstreamNode = snapshot2.nodes.find((node2) => node2.id === input.upstreamNodeId);
|
|
235101
235088
|
const conclusion = typeof work.conclusion === "string" ? work.conclusion : null;
|
|
235102
235089
|
const changedOutputs = [{
|
|
235103
235090
|
kind: "artifact",
|
|
@@ -235151,14 +235138,14 @@ var init_upstream_handoff_input = __esm({
|
|
|
235151
235138
|
});
|
|
235152
235139
|
|
|
235153
235140
|
// ../server/src/domains/execution-continuity/node-conclusions.ts
|
|
235154
|
-
function nodeCoordinatorFactsFromSnapshot(
|
|
235155
|
-
const workById = new Map(
|
|
235141
|
+
function nodeCoordinatorFactsFromSnapshot(snapshot2) {
|
|
235142
|
+
const workById = new Map(snapshot2.works.map((work) => [work.id, work]));
|
|
235156
235143
|
const artifactCountByWork = /* @__PURE__ */ new Map();
|
|
235157
|
-
for (const artifact of
|
|
235144
|
+
for (const artifact of snapshot2.artifacts) {
|
|
235158
235145
|
artifactCountByWork.set(artifact.workId, (artifactCountByWork.get(artifact.workId) ?? 0) + 1);
|
|
235159
235146
|
}
|
|
235160
235147
|
const out = {};
|
|
235161
|
-
for (const node2 of
|
|
235148
|
+
for (const node2 of snapshot2.nodes) {
|
|
235162
235149
|
const currentWorkId = node2.latestWorkId ?? null;
|
|
235163
235150
|
const currentWork = currentWorkId ? workById.get(currentWorkId) : void 0;
|
|
235164
235151
|
const work = {
|
|
@@ -235167,7 +235154,7 @@ function nodeCoordinatorFactsFromSnapshot(snapshot) {
|
|
|
235167
235154
|
state: currentWorkId === null ? "not_started" : currentWork ? workState(currentWork, hasOutput(currentWork, artifactCountByWork.get(currentWork.id) ?? 0)) : "unavailable"
|
|
235168
235155
|
};
|
|
235169
235156
|
const accepted = node2.latestAcceptId ? workById.get(node2.latestAcceptId) : void 0;
|
|
235170
|
-
const conclusion = accepted?.conclusion?.trim() ||
|
|
235157
|
+
const conclusion = accepted?.conclusion?.trim() || snapshot2.works.filter((work2) => work2.nodeId === node2.id && work2.status === "success" && work2.conclusion?.trim()).sort((a, b2) => a.createdAt.localeCompare(b2.createdAt)).at(-1)?.conclusion?.trim();
|
|
235171
235158
|
const sealed = node2.cancelledAt ? { reason: node2.sealReason ?? "cancelled", at: node2.cancelledAt } : null;
|
|
235172
235159
|
out[node2.id] = {
|
|
235173
235160
|
work,
|
|
@@ -239719,8 +239706,8 @@ function makeAutomationWorkorderSnapshotResolver(kernel) {
|
|
|
239719
239706
|
};
|
|
239720
239707
|
}
|
|
239721
239708
|
function makeAutomationWorkorderStateResolver(kernel) {
|
|
239722
|
-
const
|
|
239723
|
-
return async (workspace) => (await
|
|
239709
|
+
const snapshot2 = makeAutomationWorkorderSnapshotResolver(kernel);
|
|
239710
|
+
return async (workspace) => (await snapshot2(workspace)).state;
|
|
239724
239711
|
}
|
|
239725
239712
|
function makeAutomationReplyResolver(kernel, blobs) {
|
|
239726
239713
|
return async (workspace) => {
|
|
@@ -240124,8 +240111,8 @@ var init_project_event_poller = __esm({
|
|
|
240124
240111
|
// 完成判据必须来自 D3 resolver(snapshot.state),不在这里复制 deriveStage。
|
|
240125
240112
|
// active / unknown 是「还没完成」,cancelled 永不产生 completed——四态里只有 done 触发。
|
|
240126
240113
|
"workorder.completed": {
|
|
240127
|
-
matches: (
|
|
240128
|
-
fingerprint: (workspace,
|
|
240114
|
+
matches: (snapshot2) => snapshot2.state === "done",
|
|
240115
|
+
fingerprint: (workspace, snapshot2) => completionFingerprint(workspace, snapshot2.members)
|
|
240129
240116
|
}
|
|
240130
240117
|
};
|
|
240131
240118
|
ProjectEventPoller = class {
|
|
@@ -240214,17 +240201,17 @@ var init_project_event_poller = __esm({
|
|
|
240214
240201
|
for (const event of config2.events) {
|
|
240215
240202
|
const handler = AUTOMATION_EVENT_HANDLERS[event];
|
|
240216
240203
|
if (!handler) continue;
|
|
240217
|
-
for (const { workspace, snapshot } of candidates) {
|
|
240218
|
-
if (!handler.matches(
|
|
240204
|
+
for (const { workspace, snapshot: snapshot2 } of candidates) {
|
|
240205
|
+
if (!handler.matches(snapshot2)) continue;
|
|
240219
240206
|
if (used >= budget) return used;
|
|
240220
|
-
const fingerprint2 = handler.fingerprint(workspace,
|
|
240207
|
+
const fingerprint2 = handler.fingerprint(workspace, snapshot2);
|
|
240221
240208
|
const key = eventConsumptionKey({ triggerId: trigger.id, event, workspace, fingerprint: fingerprint2 });
|
|
240222
240209
|
const envelope = {
|
|
240223
240210
|
event,
|
|
240224
240211
|
companyId: automation.companyId,
|
|
240225
240212
|
projectId: config2.projectId,
|
|
240226
240213
|
workspace,
|
|
240227
|
-
rootArtifactId:
|
|
240214
|
+
rootArtifactId: snapshot2.rootArtifactId,
|
|
240228
240215
|
completionFingerprint: fingerprint2,
|
|
240229
240216
|
observedAt: this.now().toISOString(),
|
|
240230
240217
|
...await this.originAutomationOf(workspace)
|
|
@@ -240694,7 +240681,7 @@ var init_daemon_adapter = __esm({
|
|
|
240694
240681
|
return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
240695
240682
|
}
|
|
240696
240683
|
if (this.beforeDispatch) {
|
|
240697
|
-
await this.beforeDispatch(dispatchId, nodeId);
|
|
240684
|
+
await this.beforeDispatch(dispatchId, nodeId, job);
|
|
240698
240685
|
if (job.dispatchId && this.pending.has(dispatchId)) return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
240699
240686
|
}
|
|
240700
240687
|
const supportsLiveProtocol = this.daemonSupportsLiveProtocol(nodeId, job.binding?.runtimeKind);
|
|
@@ -240945,18 +240932,6 @@ function isExplicitlyDispatchFenced(run) {
|
|
|
240945
240932
|
const fence = metadataObject(run.metadata).dispatchFence;
|
|
240946
240933
|
return fence !== null && typeof fence === "object" && !Array.isArray(fence);
|
|
240947
240934
|
}
|
|
240948
|
-
async function fenceDispatch(trace, dispatchId, reason, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
240949
|
-
const run = await trace.getRun(dispatchId);
|
|
240950
|
-
if (!run) return false;
|
|
240951
|
-
if (isExplicitlyDispatchFenced(run)) return true;
|
|
240952
|
-
await trace.updateRun(dispatchId, {
|
|
240953
|
-
metadata: {
|
|
240954
|
-
...metadataObject(run.metadata),
|
|
240955
|
-
dispatchFence: { at, reason }
|
|
240956
|
-
}
|
|
240957
|
-
});
|
|
240958
|
-
return true;
|
|
240959
|
-
}
|
|
240960
240935
|
var metadataObject;
|
|
240961
240936
|
var init_dispatch_fence = __esm({
|
|
240962
240937
|
"../server/src/dispatch-fence.ts"() {
|
|
@@ -240966,14 +240941,14 @@ var init_dispatch_fence = __esm({
|
|
|
240966
240941
|
});
|
|
240967
240942
|
|
|
240968
240943
|
// ../server/src/execution-stop.ts
|
|
240969
|
-
function
|
|
240970
|
-
|
|
240944
|
+
async function acceptsExecutionOutcome(ledger, id) {
|
|
240945
|
+
const row = await ledger.getById(id);
|
|
240946
|
+
return !row || !row.cancelRequestedAt && await ledger.isExecutionLatest(id);
|
|
240971
240947
|
}
|
|
240972
|
-
var
|
|
240948
|
+
var ExecutionStopBarrier;
|
|
240973
240949
|
var init_execution_stop = __esm({
|
|
240974
240950
|
"../server/src/execution-stop.ts"() {
|
|
240975
240951
|
"use strict";
|
|
240976
|
-
STOP_CONFIRMATION_WAIT_MS = 15e3;
|
|
240977
240952
|
ExecutionStopBarrier = class {
|
|
240978
240953
|
constructor(o) {
|
|
240979
240954
|
this.o = o;
|
|
@@ -240981,15 +240956,9 @@ var init_execution_stop = __esm({
|
|
|
240981
240956
|
o.hub.addExecutionStopListener((nodeId, dispatchId) => this.confirm(dispatchId, nodeId)),
|
|
240982
240957
|
o.hub.addSessionConnectListener(({ dispatchId }) => {
|
|
240983
240958
|
void this.replay(dispatchId).catch((e) => o.log?.(`\u6062\u590D\u53D6\u6D88\u5931\u8D25 ${dispatchId}: ${String(e)}`));
|
|
240984
|
-
}),
|
|
240985
|
-
o.hub.addConnectListener(({ daemonId }) => {
|
|
240986
|
-
for (const dispatchId of this.waiting.keys()) {
|
|
240987
|
-
void this.replay(dispatchId, daemonId).catch((e) => o.log?.(`\u91CD\u9001\u53D6\u6D88\u5931\u8D25 ${dispatchId}: ${String(e)}`));
|
|
240988
|
-
}
|
|
240989
240959
|
})
|
|
240990
240960
|
];
|
|
240991
240961
|
}
|
|
240992
|
-
waiting = /* @__PURE__ */ new Map();
|
|
240993
240962
|
unsubscribe;
|
|
240994
240963
|
async confirm(dispatchId, nodeId) {
|
|
240995
240964
|
const ledger = await this.o.ledgerFor(dispatchId);
|
|
@@ -240997,7 +240966,6 @@ var init_execution_stop = __esm({
|
|
|
240997
240966
|
if (!row) return;
|
|
240998
240967
|
if (row.daemonId && row.daemonId !== nodeId) throw new Error("\u505C\u6B62\u8BC1\u660E\u7684\u8282\u70B9\u8EAB\u4EFD\u4E0D\u5339\u914D");
|
|
240999
240968
|
if (!await ledger.recordExecutionStop(dispatchId, "confirmed")) throw new Error("dispatch \u4E0D\u5B58\u5728");
|
|
241000
|
-
this.waiting.get(dispatchId)?.resolve();
|
|
241001
240969
|
}
|
|
241002
240970
|
send(dispatchId, nodeId) {
|
|
241003
240971
|
const msg = { type: "kill", dispatchId };
|
|
@@ -241014,113 +240982,10 @@ var init_execution_stop = __esm({
|
|
|
241014
240982
|
throw new Error(`\u627E\u4E0D\u5230\u6D3E\u53D1\u884C ${dispatchId}\uFF0C\u505C\u6B62\u672A\u786E\u8BA4\uFF0C\u7981\u6B62\u66FF\u4EE3\u6267\u884C`);
|
|
241015
240983
|
}
|
|
241016
240984
|
const row = await ledger.getById(dispatchId);
|
|
241017
|
-
if (row?.executionStoppedAt)
|
|
241018
|
-
const existing = this.waiting.get(dispatchId);
|
|
241019
|
-
if (existing) return existing.promise;
|
|
241020
|
-
if (row?.executionRecovery?.retryAt && Date.parse(row.executionRecovery.retryAt) > Date.now()) {
|
|
241021
|
-
throw new Error(`\u6267\u884C ${dispatchId} \u505C\u6B62\u672A\u786E\u8BA4\uFF1A${row.executionRecovery.detail}\uFF1B\u8BF7\u5728\u6267\u884C\u8F68\u8FF9\u5904\u7406\uFF0C\u81EA\u52A8\u6838\u9A8C\u65F6\u95F4 ${row.executionRecovery.retryAt}`);
|
|
241022
|
-
}
|
|
241023
|
-
let resolve10, reject;
|
|
241024
|
-
const promise = new Promise((yes, no) => {
|
|
241025
|
-
resolve10 = yes;
|
|
241026
|
-
reject = no;
|
|
241027
|
-
});
|
|
241028
|
-
const timer = setTimeout(
|
|
241029
|
-
() => reject(new Error(`\u6267\u884C ${dispatchId} \u505C\u6B62\u672A\u786E\u8BA4\uFF0C\u7981\u6B62\u66FF\u4EE3\u6267\u884C\uFF1B\u7B49\u5F85\u8282\u70B9\u91CD\u8FDE\u6216\u6838\u9A8C\u8FD0\u884C\u65F6\u9000\u51FA`)),
|
|
241030
|
-
this.o.timeoutMs ?? STOP_CONFIRMATION_WAIT_MS
|
|
241031
|
-
);
|
|
241032
|
-
const entry = { promise, resolve: resolve10, reject };
|
|
241033
|
-
this.waiting.set(dispatchId, entry);
|
|
241034
|
-
try {
|
|
241035
|
-
void promise.catch(() => {
|
|
241036
|
-
});
|
|
241037
|
-
if ((await ledger.getById(dispatchId))?.executionStoppedAt) resolve10();
|
|
241038
|
-
else {
|
|
241039
|
-
this.send(dispatchId, nodeId ?? row?.daemonId);
|
|
241040
|
-
if (this.o.recover) {
|
|
241041
|
-
const result = await this.o.recover(dispatchId);
|
|
241042
|
-
if (result.state === "stopped" || (await ledger.getById(dispatchId))?.executionStoppedAt) resolve10();
|
|
241043
|
-
else if (result.state === "needs_verification") throw new Error(`\u6267\u884C ${dispatchId} \u505C\u6B62\u672A\u786E\u8BA4\uFF1A${result.detail}\uFF1B\u8BF7\u5728\u6267\u884C\u8F68\u8FF9\u5904\u7406`);
|
|
241044
|
-
}
|
|
241045
|
-
}
|
|
241046
|
-
await promise;
|
|
241047
|
-
} finally {
|
|
241048
|
-
clearTimeout(timer);
|
|
241049
|
-
if (this.waiting.get(dispatchId) === entry) this.waiting.delete(dispatchId);
|
|
241050
|
-
}
|
|
241051
|
-
}
|
|
241052
|
-
async releaseIfStopped(dispatchId) {
|
|
241053
|
-
if ((await (await this.o.ledgerFor(dispatchId)).getById(dispatchId))?.executionStoppedAt) this.waiting.get(dispatchId)?.resolve();
|
|
240985
|
+
if (!row?.executionStoppedAt) this.send(dispatchId, nodeId ?? row?.daemonId);
|
|
241054
240986
|
}
|
|
241055
240987
|
close() {
|
|
241056
240988
|
for (const off of this.unsubscribe) off();
|
|
241057
|
-
for (const entry of this.waiting.values()) entry.reject(new Error("\u670D\u52A1\u7AEF\u5173\u95ED\uFF0C\u505C\u6B62\u786E\u8BA4\u5C1A\u672A\u5B8C\u6210"));
|
|
241058
|
-
this.waiting.clear();
|
|
241059
|
-
}
|
|
241060
|
-
};
|
|
241061
|
-
}
|
|
241062
|
-
});
|
|
241063
|
-
|
|
241064
|
-
// ../server/src/execution-stop-recovery.ts
|
|
241065
|
-
var import_node_crypto66, VERIFY_WAIT_MS, VERIFY_RETRY_MS, ExecutionStopRecovery;
|
|
241066
|
-
var init_execution_stop_recovery = __esm({
|
|
241067
|
-
"../server/src/execution-stop-recovery.ts"() {
|
|
241068
|
-
"use strict";
|
|
241069
|
-
import_node_crypto66 = require("node:crypto");
|
|
241070
|
-
VERIFY_WAIT_MS = 5e3;
|
|
241071
|
-
VERIFY_RETRY_MS = 5 * 6e4;
|
|
241072
|
-
ExecutionStopRecovery = class {
|
|
241073
|
-
constructor(hub, timeoutMs = VERIFY_WAIT_MS) {
|
|
241074
|
-
this.hub = hub;
|
|
241075
|
-
this.timeoutMs = timeoutMs;
|
|
241076
|
-
}
|
|
241077
|
-
async verify(ledger, id, verification) {
|
|
241078
|
-
const row = await ledger.getById(id);
|
|
241079
|
-
if (!row) throw new Error("\u6D3E\u53D1\u884C\u4E0D\u5B58\u5728");
|
|
241080
|
-
if (row.executionStoppedAt) return { state: "stopped", at: row.executionStoppedAt, detail: "\u6267\u884C\u505C\u6B62\u5DF2\u786E\u8BA4" };
|
|
241081
|
-
if (!await ledger.recordExecutionStop(id, "requested")) throw new Error("\u53D6\u6D88\u610F\u56FE\u672A\u4FDD\u5B58");
|
|
241082
|
-
const confirmed2 = await ledger.getById(id);
|
|
241083
|
-
if (confirmed2?.executionStoppedAt) return { state: "stopped", at: confirmed2.executionStoppedAt, detail: "\u5DF2\u786E\u8BA4\u6267\u884C\u4ECE\u672A\u53D6\u5F97\u542F\u52A8\u8BB8\u53EF" };
|
|
241084
|
-
const now = () => (/* @__PURE__ */ new Date()).toISOString();
|
|
241085
|
-
const daemon = this.hub.connectedDaemons().find((d) => d.daemonId === row.daemonId);
|
|
241086
|
-
let result;
|
|
241087
|
-
if (!daemon?.meta.supportsExecutionStopRecovery) {
|
|
241088
|
-
result = { state: "unavailable", at: now(), detail: daemon ? "\u8282\u70B9\u4E0D\u652F\u6301\u505C\u6B62\u8865\u8BC1\uFF0C\u8BF7\u5347\u7EA7\u8282\u70B9\u5305" : "\u539F\u8282\u70B9\u672A\u8FDE\u63A5\uFF1B\u8BF7\u6062\u590D\u539F\u8282\u70B9\u8FDE\u63A5\u540E\u6838\u9A8C" };
|
|
241089
|
-
} else if (verification && this.hub.hasSession(id)) {
|
|
241090
|
-
result = { state: "running", at: now(), detail: "\u539F\u4F1A\u8BDD\u4ECD\u4FDD\u6301\u8FDE\u63A5\uFF0C\u62D2\u7EDD\u4EBA\u5DE5\u786E\u8BA4\uFF1B\u8BF7\u5148\u505C\u6B62\u539F\u4F1A\u8BDD" };
|
|
241091
|
-
} else {
|
|
241092
|
-
const requestId = (0, import_node_crypto66.randomUUID)();
|
|
241093
|
-
result = await new Promise((resolve10) => {
|
|
241094
|
-
const finish = (check2) => {
|
|
241095
|
-
clearTimeout(timer);
|
|
241096
|
-
off();
|
|
241097
|
-
resolve10(check2);
|
|
241098
|
-
};
|
|
241099
|
-
const off = this.hub.addMessageListener((node2, msg) => {
|
|
241100
|
-
if (node2 !== row.daemonId || msg.type !== "execution_stop_result" || msg.requestId !== requestId || msg.dispatchId !== id) return;
|
|
241101
|
-
const check2 = msg.result;
|
|
241102
|
-
const proof = check2?.proof;
|
|
241103
|
-
if (!check2 || !["stopped", "running", "needs_verification", "unavailable"].includes(check2.state) || typeof check2.detail !== "string" || check2.state === "stopped" && (!proof || !Number.isFinite(Date.parse(proof.at)) || proof.kind !== "runtime_exit" && proof.kind !== "operator_verified" || proof.kind === "operator_verified" && (!proof.actor?.startsWith("actor:human:") || !proof.evidence?.trim()))) {
|
|
241104
|
-
finish({ state: "unavailable", at: now(), detail: "\u8282\u70B9\u8865\u8BC1\u683C\u5F0F\u65E0\u6548\uFF0C\u4FDD\u6301\u505C\u6B62\u672A\u786E\u8BA4" });
|
|
241105
|
-
} else finish(check2);
|
|
241106
|
-
});
|
|
241107
|
-
const timer = setTimeout(() => finish({ state: "unavailable", at: now(), detail: "\u8282\u70B9\u6838\u9A8C\u8D85\u65F6\uFF1B\u53EF\u5728\u6267\u884C\u8F68\u8FF9\u4E2D\u91CD\u65B0\u6838\u9A8C" }), this.timeoutMs);
|
|
241108
|
-
if (!this.hub.dispatch(daemon.daemonId, { type: "verify_execution_stop", requestId, dispatchId: id, ...verification ? { verification } : {} })) {
|
|
241109
|
-
finish({ state: "unavailable", at: now(), detail: "\u6838\u9A8C\u671F\u95F4\u8282\u70B9\u65AD\u5F00\uFF0C\u8BF7\u6062\u590D\u8FDE\u63A5\u540E\u91CD\u65B0\u6838\u9A8C" });
|
|
241110
|
-
}
|
|
241111
|
-
});
|
|
241112
|
-
}
|
|
241113
|
-
if (!verification && result.state === "needs_verification" && this.hub.hasSession(id)) {
|
|
241114
|
-
result = { state: "running", at: now(), detail: "\u539F\u4F1A\u8BDD\u4ECD\u8FDE\u63A5\uFF0C\u7B49\u5F85\u5176\u771F\u5B9E\u505C\u6B62\u56DE\u62A5" };
|
|
241115
|
-
}
|
|
241116
|
-
result = {
|
|
241117
|
-
...result,
|
|
241118
|
-
at: now(),
|
|
241119
|
-
...row.daemonId ? { nodeId: row.daemonId } : {},
|
|
241120
|
-
...result.state !== "stopped" ? { retryAt: new Date(Date.now() + VERIFY_RETRY_MS).toISOString() } : {}
|
|
241121
|
-
};
|
|
241122
|
-
if (!await ledger.recordExecutionRecovery(id, row.daemonId, result)) throw new Error("\u505C\u6B62\u8865\u8BC1\u672A\u843D\u5E93\uFF0C\u4FDD\u6301\u963B\u585E");
|
|
241123
|
-
return result;
|
|
241124
240989
|
}
|
|
241125
240990
|
};
|
|
241126
240991
|
}
|
|
@@ -241177,13 +241042,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
241177
241042
|
if (sha(body2) === lastPushedHash) return { kind: "echo" };
|
|
241178
241043
|
return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
|
|
241179
241044
|
}
|
|
241180
|
-
var
|
|
241045
|
+
var import_node_crypto66, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
|
|
241181
241046
|
var init_engine = __esm({
|
|
241182
241047
|
"../server/src/mirror/engine.ts"() {
|
|
241183
241048
|
"use strict";
|
|
241184
|
-
|
|
241049
|
+
import_node_crypto66 = require("node:crypto");
|
|
241185
241050
|
init_src();
|
|
241186
|
-
sha = (s2) => (0,
|
|
241051
|
+
sha = (s2) => (0, import_node_crypto66.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
241187
241052
|
enc3 = (s2) => new TextEncoder().encode(s2);
|
|
241188
241053
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
241189
241054
|
MirrorEngine = class {
|
|
@@ -241430,11 +241295,11 @@ function humanExitCause(exit3) {
|
|
|
241430
241295
|
const base = (exit3.reason ? label[exit3.reason] : void 0) ?? `\u4F1A\u8BDD\u5F02\u5E38\u7ED3\u675F\uFF08${exit3.reason ?? "\u65E0\u9000\u51FA\u4FE1\u606F"}\uFF09`;
|
|
241431
241296
|
return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
|
|
241432
241297
|
}
|
|
241433
|
-
var
|
|
241298
|
+
var import_node_crypto67, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, AUTONOMOUS_RECOVERY_TOOLS, HIGH_RISK_COMMANDS, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_RECOVERY_TOOLS, CONVERSATIONAL_ESCALATION_TOOLS, CONVERSATIONAL_MANAGER_BODY, MACHINE_EXIT_CODES, CoordinatorWorker;
|
|
241434
241299
|
var init_worker = __esm({
|
|
241435
241300
|
"../server/src/coordinator/worker.ts"() {
|
|
241436
241301
|
"use strict";
|
|
241437
|
-
|
|
241302
|
+
import_node_crypto67 = require("node:crypto");
|
|
241438
241303
|
init_src5();
|
|
241439
241304
|
init_identity();
|
|
241440
241305
|
AUTONOMOUS_ETHOS = `\u4F60\u662F\u8FD9\u4E2A\u5DE5\u5355\u7684**\u7BA1\u7406\u8005**\u2014\u2014\u804C\u8D23\u662F\u8BA9\u5B83\u987A\u7545\u8DD1\u5B8C\u3002\u7CFB\u7EDF\u5728\u67D0\u4E2A\u8282\u70B9\u5361\u4F4F\u3001\u673A\u68B0\u5206\u8BCA\u786E\u8BA4"\u9700\u8981\u4F60"\u65F6\u5524\u8D77\u4F60\uFF08\u65E0\u4EBA\u5728\u573A\uFF0C\u4F60\u8FD9\u4E00\u8F6E\u628A\u80FD\u505A\u7684\u505A\u6389\uFF09\u3002\u4F60\u7684\u624B\u6BB5\u5F88\u5BBD\uFF1A
|
|
@@ -241703,7 +241568,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
241703
241568
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
241704
241569
|
}
|
|
241705
241570
|
evaluationKey(kind, artifactId, evidence) {
|
|
241706
|
-
const fingerprint2 = (0,
|
|
241571
|
+
const fingerprint2 = (0, import_node_crypto67.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
241707
241572
|
return `${kind}:${artifactId}:${fingerprint2}`;
|
|
241708
241573
|
}
|
|
241709
241574
|
artifactEvidence(id) {
|
|
@@ -242082,8 +241947,8 @@ ${ctx.nodeFault}
|
|
|
242082
241947
|
this.deps.log?.(`[coordinator] ${workspace} \u5168\u5C40\u4E0A\u4E0B\u6587\u8BFB\u53D6\u5931\u8D25\uFF0C\u7EE7\u7EED\u6CBF\u7528\u539F\u534F\u8C03\u8005\u4EFB\u52A1\uFF1A${String(error2)}`);
|
|
242083
241948
|
}
|
|
242084
241949
|
}
|
|
242085
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
242086
|
-
const coordinatorRunId = `coordinate:${(0,
|
|
241950
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto67.randomUUID)();
|
|
241951
|
+
const coordinatorRunId = `coordinate:${(0, import_node_crypto67.randomUUID)()}`;
|
|
242087
241952
|
const taskWithContext = coordinatorContext ? [
|
|
242088
241953
|
task,
|
|
242089
241954
|
``,
|
|
@@ -242127,7 +241992,7 @@ ${ctx.nodeFault}
|
|
|
242127
241992
|
const startedAtMs = Date.now();
|
|
242128
241993
|
let trajectoryStarted = false;
|
|
242129
241994
|
if (this.deps.trajectory) {
|
|
242130
|
-
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0,
|
|
241995
|
+
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto67.createHash)("sha256").update(content3).digest("hex")]));
|
|
242131
241996
|
const session = {
|
|
242132
241997
|
runId: coordinatorRunId,
|
|
242133
241998
|
runtimeSessionId,
|
|
@@ -242332,11 +242197,11 @@ var init_pg_ident = __esm({
|
|
|
242332
242197
|
});
|
|
242333
242198
|
|
|
242334
242199
|
// ../storage/src/postgres.ts
|
|
242335
|
-
var
|
|
242200
|
+
var import_node_crypto68, ident3, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
|
|
242336
242201
|
var init_postgres = __esm({
|
|
242337
242202
|
"../storage/src/postgres.ts"() {
|
|
242338
242203
|
"use strict";
|
|
242339
|
-
|
|
242204
|
+
import_node_crypto68 = require("node:crypto");
|
|
242340
242205
|
init_pg_ident();
|
|
242341
242206
|
init_esm();
|
|
242342
242207
|
init_src();
|
|
@@ -242516,7 +242381,7 @@ var init_postgres = __esm({
|
|
|
242516
242381
|
return new _PostgresBlobStore(pool, schema);
|
|
242517
242382
|
}
|
|
242518
242383
|
async put(bytes2) {
|
|
242519
|
-
const hash2 = (0,
|
|
242384
|
+
const hash2 = (0, import_node_crypto68.createHash)("sha256").update(bytes2).digest("hex");
|
|
242520
242385
|
await this.pool.query(
|
|
242521
242386
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
242522
242387
|
[hash2, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
|
|
@@ -250996,11 +250861,11 @@ var init_postgres_delegations = __esm({
|
|
|
250996
250861
|
});
|
|
250997
250862
|
|
|
250998
250863
|
// ../storage/src/postgres-nodes.ts
|
|
250999
|
-
var
|
|
250864
|
+
var import_node_crypto69, ident12, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToRuntime;
|
|
251000
250865
|
var init_postgres_nodes = __esm({
|
|
251001
250866
|
"../storage/src/postgres-nodes.ts"() {
|
|
251002
250867
|
"use strict";
|
|
251003
|
-
|
|
250868
|
+
import_node_crypto69 = require("node:crypto");
|
|
251004
250869
|
init_pg_ident();
|
|
251005
250870
|
init_esm();
|
|
251006
250871
|
ident12 = (s2) => {
|
|
@@ -251210,7 +251075,7 @@ var init_postgres_nodes = __esm({
|
|
|
251210
251075
|
return store;
|
|
251211
251076
|
}
|
|
251212
251077
|
issue(nodeId) {
|
|
251213
|
-
const token = `ont_${(0,
|
|
251078
|
+
const token = `ont_${(0, import_node_crypto69.randomBytes)(24).toString("base64url")}`;
|
|
251214
251079
|
this.cache.set(token, nodeId);
|
|
251215
251080
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
251216
251081
|
return token;
|
|
@@ -251476,11 +251341,11 @@ var init_postgres_type_registry = __esm({
|
|
|
251476
251341
|
});
|
|
251477
251342
|
|
|
251478
251343
|
// ../storage/src/postgres-actor-memory.ts
|
|
251479
|
-
var
|
|
251344
|
+
var import_node_crypto70, matchClause, ident14, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
|
|
251480
251345
|
var init_postgres_actor_memory = __esm({
|
|
251481
251346
|
"../storage/src/postgres-actor-memory.ts"() {
|
|
251482
251347
|
"use strict";
|
|
251483
|
-
|
|
251348
|
+
import_node_crypto70 = require("node:crypto");
|
|
251484
251349
|
init_pg_ident();
|
|
251485
251350
|
init_src();
|
|
251486
251351
|
matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
|
|
@@ -251690,7 +251555,7 @@ var init_postgres_actor_memory = __esm({
|
|
|
251690
251555
|
}
|
|
251691
251556
|
async write(input, now) {
|
|
251692
251557
|
if (input.memId === void 0) {
|
|
251693
|
-
const memId = `mem:${(0,
|
|
251558
|
+
const memId = `mem:${(0, import_node_crypto70.randomUUID)()}`;
|
|
251694
251559
|
const r2 = await this.pool.query(
|
|
251695
251560
|
`INSERT INTO ${this.s}.actor_memories
|
|
251696
251561
|
(mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
|
|
@@ -251946,7 +251811,8 @@ function rowToRecord2(r) {
|
|
|
251946
251811
|
outcome: r.outcome,
|
|
251947
251812
|
exitCode: r.exit_code,
|
|
251948
251813
|
reason: r.reason,
|
|
251949
|
-
|
|
251814
|
+
executionGeneration: r.execution_generation == null ? null : Number(r.execution_generation),
|
|
251815
|
+
executionPreparation: r.execution_preparation ?? null,
|
|
251950
251816
|
executionReservedAt: r.execution_reserved_at ? new Date(r.execution_reserved_at).toISOString() : null,
|
|
251951
251817
|
cancelRequestedAt: r.cancel_requested_at ? new Date(r.cancel_requested_at).toISOString() : null,
|
|
251952
251818
|
executionStoppedAt: r.execution_stopped_at ? new Date(r.execution_stopped_at).toISOString() : null
|
|
@@ -251994,7 +251860,9 @@ var init_postgres_dispatches = __esm({
|
|
|
251994
251860
|
)`);
|
|
251995
251861
|
await pool.query(`CREATE INDEX IF NOT EXISTS dispatches_target_idx ON "${s2}".dispatches (target_kind, target_id, created_at DESC)`);
|
|
251996
251862
|
await pool.query(`CREATE INDEX IF NOT EXISTS dispatches_workorder_idx ON "${s2}".dispatches (workorder_id, created_at DESC)`);
|
|
251997
|
-
await pool.query(`ALTER TABLE "${s2}".dispatches ADD COLUMN IF NOT EXISTS execution_reserved_at timestamptz, ADD COLUMN IF NOT EXISTS cancel_requested_at timestamptz, ADD COLUMN IF NOT EXISTS execution_stopped_at timestamptz
|
|
251863
|
+
await pool.query(`ALTER TABLE "${s2}".dispatches ADD COLUMN IF NOT EXISTS execution_reserved_at timestamptz, ADD COLUMN IF NOT EXISTS cancel_requested_at timestamptz, ADD COLUMN IF NOT EXISTS execution_stopped_at timestamptz`);
|
|
251864
|
+
await pool.query(`ALTER TABLE "${s2}".dispatches ADD COLUMN IF NOT EXISTS execution_generation bigint, ADD COLUMN IF NOT EXISTS execution_preparation jsonb`);
|
|
251865
|
+
await pool.query(`CREATE INDEX IF NOT EXISTS dispatches_execution_task_idx ON "${s2}".dispatches (workorder_id, job_key, execution_generation DESC) WHERE execution_generation IS NOT NULL`);
|
|
251998
251866
|
return new _PostgresDispatchStore(pool, s2);
|
|
251999
251867
|
}
|
|
252000
251868
|
/** write-ahead:派发意图产生的那一刻落 open 行(提案 I-D1)。同 id 重放安全(ON CONFLICT DO NOTHING)。 */
|
|
@@ -252014,21 +251882,46 @@ var init_postgres_dispatches = __esm({
|
|
|
252014
251882
|
]
|
|
252015
251883
|
);
|
|
252016
251884
|
}
|
|
252017
|
-
/**
|
|
251885
|
+
/** 每个任务只有最新一轮有效。首次升级汇总历史身份一次,后续只继承任务清场状态。 */
|
|
252018
251886
|
async reserveExecution(rec) {
|
|
252019
251887
|
if (!rec.jobKey || !rec.workorderId) throw new Error("\u6267\u884C\u5360\u4F4D\u7F3A\u5C11\u7A33\u5B9A\u4EFB\u52A1\u8EAB\u4EFD");
|
|
252020
251888
|
const client = await this.pool.connect();
|
|
252021
251889
|
try {
|
|
252022
251890
|
await client.query("BEGIN");
|
|
252023
251891
|
await client.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [JSON.stringify([this.s, rec.workorderId, rec.jobKey])]);
|
|
252024
|
-
const
|
|
252025
|
-
|
|
252026
|
-
|
|
251892
|
+
const latest = await client.query(`SELECT * FROM "${this.s}".dispatches WHERE workorder_id=$1 AND job_key=$2
|
|
251893
|
+
AND execution_generation IS NOT NULL ORDER BY execution_generation DESC LIMIT 1 FOR UPDATE`, [rec.workorderId, rec.jobKey]);
|
|
251894
|
+
const prior = latest.rows[0];
|
|
251895
|
+
const generation = Number(prior?.execution_generation ?? 0) + 1;
|
|
251896
|
+
let nodes, legacyDispatchIds, unassignedDispatchIds;
|
|
251897
|
+
if (prior) {
|
|
251898
|
+
nodes = prior.daemon_id && prior.execution_stopped_at ? [] : [.../* @__PURE__ */ new Set([...prior.execution_preparation?.nodes ?? [], ...prior.daemon_id ? [prior.daemon_id] : [], ...prior.execution_preparation?.targetNode ? [prior.execution_preparation.targetNode] : []])];
|
|
251899
|
+
legacyDispatchIds = prior.execution_preparation?.legacyDispatchIds ?? [];
|
|
251900
|
+
unassignedDispatchIds = prior.execution_preparation?.unassignedDispatchIds ?? [];
|
|
251901
|
+
} else {
|
|
251902
|
+
const legacy = await client.query(`SELECT id, daemon_id, execution_stopped_at, execution_reserved_at FROM "${this.s}".dispatches WHERE workorder_id=$1 AND job_key=$2`, [rec.workorderId, rec.jobKey]);
|
|
251903
|
+
nodes = [...new Set(legacy.rows.flatMap((r) => r.daemon_id && !r.execution_stopped_at ? [r.daemon_id] : []))];
|
|
251904
|
+
legacyDispatchIds = legacy.rows.map((r) => r.id);
|
|
251905
|
+
unassignedDispatchIds = legacy.rows.filter((r) => !r.daemon_id && !r.execution_stopped_at && !r.execution_reserved_at).map((r) => r.id);
|
|
251906
|
+
}
|
|
251907
|
+
await client.query(`UPDATE "${this.s}".dispatches SET cancel_requested_at=COALESCE(cancel_requested_at,now()),
|
|
251908
|
+
ended_at=now(), outcome='superseded', reason='newer-execution' WHERE workorder_id=$1 AND job_key=$2 AND ended_at IS NULL`, [rec.workorderId, rec.jobKey]);
|
|
252027
251909
|
await client.query(
|
|
252028
251910
|
`INSERT INTO "${this.s}".dispatches
|
|
252029
|
-
(id,
|
|
252030
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,now())`,
|
|
252031
|
-
[
|
|
251911
|
+
(id,target_kind,target_id,workorder_id,node_id,actor_id,job_key,created_at,execution_reserved_at,execution_generation,execution_preparation)
|
|
251912
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,now(),$9,$10::jsonb)`,
|
|
251913
|
+
[
|
|
251914
|
+
rec.id,
|
|
251915
|
+
rec.targetKind,
|
|
251916
|
+
rec.targetId,
|
|
251917
|
+
rec.workorderId,
|
|
251918
|
+
rec.nodeId ?? null,
|
|
251919
|
+
rec.actorId,
|
|
251920
|
+
rec.jobKey,
|
|
251921
|
+
rec.at ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
251922
|
+
generation,
|
|
251923
|
+
JSON.stringify({ generation, nodes, legacyDispatchIds, unassignedDispatchIds })
|
|
251924
|
+
]
|
|
252032
251925
|
);
|
|
252033
251926
|
await client.query("COMMIT");
|
|
252034
251927
|
} catch (error2) {
|
|
@@ -252038,12 +251931,74 @@ var init_postgres_dispatches = __esm({
|
|
|
252038
251931
|
client.release();
|
|
252039
251932
|
}
|
|
252040
251933
|
}
|
|
252041
|
-
|
|
251934
|
+
async withCurrentExecution(id, fn) {
|
|
251935
|
+
const client = await this.pool.connect();
|
|
251936
|
+
try {
|
|
251937
|
+
await client.query("BEGIN");
|
|
251938
|
+
const found = await client.query(`SELECT workorder_id,job_key FROM "${this.s}".dispatches WHERE id=$1`, [id]);
|
|
251939
|
+
const identity = found.rows[0];
|
|
251940
|
+
if (!identity) throw new Error(`\u6267\u884C ${id} \u6CA1\u6709\u542F\u52A8\u8BB8\u53EF`);
|
|
251941
|
+
await client.query("SELECT pg_advisory_xact_lock(hashtextextended($1, 0))", [JSON.stringify([this.s, identity.workorder_id, identity.job_key])]);
|
|
251942
|
+
const latest = await client.query(`SELECT * FROM "${this.s}".dispatches WHERE workorder_id=$1 AND job_key=$2
|
|
251943
|
+
AND execution_generation IS NOT NULL ORDER BY execution_generation DESC LIMIT 1 FOR UPDATE`, [identity.workorder_id, identity.job_key]);
|
|
251944
|
+
const row = latest.rows[0];
|
|
251945
|
+
if (row?.id !== id || row.ended_at || row.cancel_requested_at || row.execution_stopped_at) throw new Error(`\u6267\u884C ${id} \u6CA1\u6709\u542F\u52A8\u8BB8\u53EF\uFF1A\u5DF2\u88AB\u65B0\u8F6E\u66FF\u4EE3\u3001\u53D6\u6D88\u6216\u7ED3\u675F`);
|
|
251946
|
+
const result = await fn(client, row);
|
|
251947
|
+
await client.query("COMMIT");
|
|
251948
|
+
return result;
|
|
251949
|
+
} catch (error2) {
|
|
251950
|
+
await client.query("ROLLBACK");
|
|
251951
|
+
throw error2;
|
|
251952
|
+
} finally {
|
|
251953
|
+
client.release();
|
|
251954
|
+
}
|
|
251955
|
+
}
|
|
251956
|
+
/** 先将目标机器纳入清场集合,再允许异步 RPC;并发换轮也不会漏掉正在准备的旧目标。 */
|
|
251957
|
+
async prepareExecution(id, daemonId, locatedNodes) {
|
|
251958
|
+
return this.withCurrentExecution(id, async (client, row) => {
|
|
251959
|
+
if (row.daemon_id) throw new Error(`\u6267\u884C ${id} \u5DF2\u9886\u53D6\u542F\u52A8\u8BB8\u53EF`);
|
|
251960
|
+
const plan = row.execution_preparation;
|
|
251961
|
+
plan.nodes = [.../* @__PURE__ */ new Set([...plan.nodes, daemonId, ...locatedNodes ?? []])];
|
|
251962
|
+
if (locatedNodes) plan.unassignedDispatchIds = [];
|
|
251963
|
+
plan.targetNode = daemonId;
|
|
251964
|
+
await client.query(`UPDATE "${this.s}".dispatches SET execution_preparation=$2::jsonb WHERE id=$1`, [id, JSON.stringify(plan)]);
|
|
251965
|
+
return plan;
|
|
251966
|
+
});
|
|
251967
|
+
}
|
|
251968
|
+
async confirmExecutionPrepared(id, daemonId, generation) {
|
|
251969
|
+
await this.withCurrentExecution(id, async (client, row) => {
|
|
251970
|
+
const plan = row.execution_preparation;
|
|
251971
|
+
if (plan.generation !== generation) throw new Error("\u4EFB\u52A1\u6E05\u573A\u786E\u8BA4\u7684\u8F6E\u6B21\u4E0D\u5339\u914D");
|
|
251972
|
+
plan.nodes = plan.nodes.filter((n) => n !== daemonId);
|
|
251973
|
+
await client.query(`UPDATE "${this.s}".dispatches SET execution_preparation=$2::jsonb WHERE id=$1`, [id, JSON.stringify(plan)]);
|
|
251974
|
+
});
|
|
251975
|
+
}
|
|
251976
|
+
/** 清场完成后原子领取许可;先来的清场回执不能放行已过期轮次。 */
|
|
252042
251977
|
async claimExecution(id, daemonId) {
|
|
252043
|
-
|
|
252044
|
-
|
|
252045
|
-
|
|
252046
|
-
|
|
251978
|
+
await this.withCurrentExecution(id, async (client, row) => {
|
|
251979
|
+
const plan = row.execution_preparation;
|
|
251980
|
+
if (row.daemon_id || plan.nodes.length || plan.unassignedDispatchIds?.length || plan.targetNode !== daemonId) throw new Error(`\u6267\u884C ${id} \u6CA1\u6709\u542F\u52A8\u8BB8\u53EF\uFF1A\u4EFB\u52A1\u6E05\u573A\u5C1A\u672A\u5B8C\u6210\u6216\u5DF2\u6D3E\u53D1`);
|
|
251981
|
+
await client.query(
|
|
251982
|
+
`UPDATE "${this.s}".dispatches SET daemon_id=$2,execution_preparation=$3::jsonb WHERE id=$1`,
|
|
251983
|
+
[id, daemonId, JSON.stringify({ generation: plan.generation, nodes: [daemonId], legacyDispatchIds: [] })]
|
|
251984
|
+
);
|
|
251985
|
+
});
|
|
251986
|
+
}
|
|
251987
|
+
/** 退出帧仍需归属当前轮次,但不能因为刚记录实际退出就拒绝其正常收尾。 */
|
|
251988
|
+
async isExecutionLatest(id) {
|
|
251989
|
+
return this.executionMatches(id, false);
|
|
251990
|
+
}
|
|
251991
|
+
/** 平台启动和写入只查询最新轮次;不依赖 trace 是否存在或旧 outcome 是否可信。 */
|
|
251992
|
+
async isExecutionCurrent(id) {
|
|
251993
|
+
return this.executionMatches(id, true);
|
|
251994
|
+
}
|
|
251995
|
+
async executionMatches(id, requireActive) {
|
|
251996
|
+
const result = await this.pool.query(`SELECT d.* FROM "${this.s}".dispatches d WHERE id=$1
|
|
251997
|
+
AND (NOT $2::boolean OR (ended_at IS NULL AND cancel_requested_at IS NULL AND execution_stopped_at IS NULL))
|
|
251998
|
+
AND NOT EXISTS (SELECT 1 FROM "${this.s}".dispatches n WHERE n.workorder_id=d.workorder_id AND n.job_key=d.job_key
|
|
251999
|
+
AND ((n.execution_generation IS NOT NULL AND (d.execution_generation IS NULL OR n.execution_generation>d.execution_generation))
|
|
252000
|
+
OR (n.execution_generation IS NULL AND d.execution_generation IS NULL AND (n.created_at,n.id)>(d.created_at,d.id))))`, [id, requireActive]);
|
|
252001
|
+
return result.rows.length > 0;
|
|
252047
252002
|
}
|
|
252048
252003
|
/** 取消意图与停止证据独立、幂等持久化;返回 false 表示根本没有该派发行。 */
|
|
252049
252004
|
async recordExecutionStop(id, phase, at = (/* @__PURE__ */ new Date()).toISOString()) {
|
|
@@ -252055,18 +252010,6 @@ var init_postgres_dispatches = __esm({
|
|
|
252055
252010
|
);
|
|
252056
252011
|
return (result.rowCount ?? 0) > 0;
|
|
252057
252012
|
}
|
|
252058
|
-
/** 核验状态与补证审计同一次写;取消意图和节点归属必须仍匹配。 */
|
|
252059
|
-
async recordExecutionRecovery(id, nodeId, check2) {
|
|
252060
|
-
if (check2.state === "stopped" && !check2.proof) throw new Error("\u8865\u8BC1\u7F3A\u5C11\u6765\u6E90");
|
|
252061
|
-
const result = await this.pool.query(
|
|
252062
|
-
`UPDATE "${this.s}".dispatches
|
|
252063
|
-
SET execution_recovery = CASE WHEN execution_stopped_at IS NULL THEN $3::jsonb ELSE execution_recovery END,
|
|
252064
|
-
execution_stopped_at = COALESCE(execution_stopped_at, CASE WHEN $4 THEN now() ELSE NULL END)
|
|
252065
|
-
WHERE id = $1 AND daemon_id IS NOT DISTINCT FROM $2 AND cancel_requested_at IS NOT NULL`,
|
|
252066
|
-
[id, nodeId, JSON.stringify(check2), check2.state === "stopped"]
|
|
252067
|
-
);
|
|
252068
|
-
return (result.rowCount ?? 0) > 0;
|
|
252069
|
-
}
|
|
252070
252013
|
/** session_started 帧:回填 started_at / session_ref / daemon_id(幂等:只填第一次)。 */
|
|
252071
252014
|
async markStarted(id, opts) {
|
|
252072
252015
|
await this.pool.query(
|
|
@@ -253197,14 +253140,14 @@ function companySchemaName(companyId) {
|
|
|
253197
253140
|
if (typeof companyId !== "string" || !companyId.trim()) {
|
|
253198
253141
|
throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
|
|
253199
253142
|
}
|
|
253200
|
-
const hex = (0,
|
|
253143
|
+
const hex = (0, import_node_crypto71.createHash)("sha256").update(companyId, "utf8").digest("hex");
|
|
253201
253144
|
return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
|
|
253202
253145
|
}
|
|
253203
|
-
var
|
|
253146
|
+
var import_node_crypto71, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
|
|
253204
253147
|
var init_tenant_schema_mapping = __esm({
|
|
253205
253148
|
"../storage/src/tenant-schema-mapping.ts"() {
|
|
253206
253149
|
"use strict";
|
|
253207
|
-
|
|
253150
|
+
import_node_crypto71 = require("node:crypto");
|
|
253208
253151
|
init_esm();
|
|
253209
253152
|
init_pg_ident();
|
|
253210
253153
|
COMPANY_SCHEMA_PREFIX = "c_";
|
|
@@ -253278,7 +253221,7 @@ var init_tenant_schema_mapping = __esm({
|
|
|
253278
253221
|
|
|
253279
253222
|
// ../storage/src/company-data-plane-schema.ts
|
|
253280
253223
|
function canonicalTypeDefHash(def) {
|
|
253281
|
-
return `sha256:${(0,
|
|
253224
|
+
return `sha256:${(0, import_node_crypto72.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
|
|
253282
253225
|
}
|
|
253283
253226
|
function defaultArtifactTypeTemplate() {
|
|
253284
253227
|
return [
|
|
@@ -253460,11 +253403,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
|
|
|
253460
253403
|
}
|
|
253461
253404
|
return { inserted };
|
|
253462
253405
|
}
|
|
253463
|
-
var
|
|
253406
|
+
var import_node_crypto72, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
|
|
253464
253407
|
var init_company_data_plane_schema = __esm({
|
|
253465
253408
|
"../storage/src/company-data-plane-schema.ts"() {
|
|
253466
253409
|
"use strict";
|
|
253467
|
-
|
|
253410
|
+
import_node_crypto72 = require("node:crypto");
|
|
253468
253411
|
init_esm();
|
|
253469
253412
|
init_pg_ident();
|
|
253470
253413
|
DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
|
|
@@ -253544,11 +253487,11 @@ function rowToFile2(row) {
|
|
|
253544
253487
|
updatedAt: new Date(row.updated_at).toISOString()
|
|
253545
253488
|
};
|
|
253546
253489
|
}
|
|
253547
|
-
var
|
|
253490
|
+
var import_node_crypto73, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
|
|
253548
253491
|
var init_company_owned_registry_store = __esm({
|
|
253549
253492
|
"../storage/src/company-owned-registry-store.ts"() {
|
|
253550
253493
|
"use strict";
|
|
253551
|
-
|
|
253494
|
+
import_node_crypto73 = require("node:crypto");
|
|
253552
253495
|
init_esm();
|
|
253553
253496
|
init_src();
|
|
253554
253497
|
init_pg_ident();
|
|
@@ -253934,7 +253877,7 @@ var init_company_owned_registry_store = __esm({
|
|
|
253934
253877
|
enabled: skill.enabled,
|
|
253935
253878
|
files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
|
|
253936
253879
|
});
|
|
253937
|
-
return (0,
|
|
253880
|
+
return (0, import_node_crypto73.createHash)("sha256").update(body2).digest("hex");
|
|
253938
253881
|
}
|
|
253939
253882
|
};
|
|
253940
253883
|
}
|
|
@@ -254674,15 +254617,24 @@ var init_cutover_aware_dispatches = __esm({
|
|
|
254674
254617
|
async reserveExecution(rec) {
|
|
254675
254618
|
return (await this.pickWritable()).reserveExecution(rec);
|
|
254676
254619
|
}
|
|
254620
|
+
async prepareExecution(id, nodeId, locatedNodes) {
|
|
254621
|
+
return (await this.pickWritable()).prepareExecution(id, nodeId, locatedNodes);
|
|
254622
|
+
}
|
|
254623
|
+
async confirmExecutionPrepared(id, nodeId, generation) {
|
|
254624
|
+
return (await this.pickWritable()).confirmExecutionPrepared(id, nodeId, generation);
|
|
254625
|
+
}
|
|
254626
|
+
async isExecutionCurrent(id) {
|
|
254627
|
+
return (await this.pick()).isExecutionCurrent(id);
|
|
254628
|
+
}
|
|
254629
|
+
async isExecutionLatest(id) {
|
|
254630
|
+
return (await this.pick()).isExecutionLatest(id);
|
|
254631
|
+
}
|
|
254677
254632
|
async claimExecution(id, daemonId) {
|
|
254678
254633
|
return (await this.pickWritable()).claimExecution(id, daemonId);
|
|
254679
254634
|
}
|
|
254680
254635
|
async recordExecutionStop(id, phase, at) {
|
|
254681
254636
|
return (await this.pickWritable()).recordExecutionStop(id, phase, at);
|
|
254682
254637
|
}
|
|
254683
|
-
async recordExecutionRecovery(...args) {
|
|
254684
|
-
return (await this.pickWritable()).recordExecutionRecovery(...args);
|
|
254685
|
-
}
|
|
254686
254638
|
async close(id, opts) {
|
|
254687
254639
|
return (await this.pickWritable()).close(id, opts);
|
|
254688
254640
|
}
|
|
@@ -254775,24 +254727,36 @@ var init_cutover_aware_dispatches = __esm({
|
|
|
254775
254727
|
async reserveExecution(_rec) {
|
|
254776
254728
|
throw new Error("\u6267\u884C\u5360\u4F4D\u5FC5\u987B\u6307\u5B9A\u516C\u53F8");
|
|
254777
254729
|
}
|
|
254778
|
-
async
|
|
254730
|
+
async ownerOf(id) {
|
|
254779
254731
|
for (const cid of await this.o.listCompanies()) {
|
|
254780
254732
|
const ledger = await this.o.ledgerFor(cid);
|
|
254781
|
-
if (await ledger.getById(id)) return ledger
|
|
254733
|
+
if (await ledger.getById(id)) return ledger;
|
|
254782
254734
|
}
|
|
254783
254735
|
throw new Error(`\u627E\u4E0D\u5230\u6267\u884C ${id}`);
|
|
254784
254736
|
}
|
|
254785
|
-
async
|
|
254737
|
+
async prepareExecution(id, nodeId, locatedNodes) {
|
|
254738
|
+
return (await this.ownerOf(id)).prepareExecution(id, nodeId, locatedNodes);
|
|
254739
|
+
}
|
|
254740
|
+
async confirmExecutionPrepared(id, nodeId, generation) {
|
|
254741
|
+
return (await this.ownerOf(id)).confirmExecutionPrepared(id, nodeId, generation);
|
|
254742
|
+
}
|
|
254743
|
+
async isExecutionCurrent(id) {
|
|
254744
|
+
return (await this.ownerOf(id)).isExecutionCurrent(id);
|
|
254745
|
+
}
|
|
254746
|
+
async isExecutionLatest(id) {
|
|
254747
|
+
return (await this.ownerOf(id)).isExecutionLatest(id);
|
|
254748
|
+
}
|
|
254749
|
+
async claimExecution(id, daemonId) {
|
|
254786
254750
|
for (const cid of await this.o.listCompanies()) {
|
|
254787
254751
|
const ledger = await this.o.ledgerFor(cid);
|
|
254788
|
-
if (await ledger.getById(id)) return ledger.
|
|
254752
|
+
if (await ledger.getById(id)) return ledger.claimExecution(id, daemonId);
|
|
254789
254753
|
}
|
|
254790
|
-
|
|
254754
|
+
throw new Error(`\u627E\u4E0D\u5230\u6267\u884C ${id}`);
|
|
254791
254755
|
}
|
|
254792
|
-
async
|
|
254756
|
+
async recordExecutionStop(id, phase, at) {
|
|
254793
254757
|
for (const cid of await this.o.listCompanies()) {
|
|
254794
254758
|
const ledger = await this.o.ledgerFor(cid);
|
|
254795
|
-
if (await ledger.getById(
|
|
254759
|
+
if (await ledger.getById(id)) return ledger.recordExecutionStop(id, phase, at);
|
|
254796
254760
|
}
|
|
254797
254761
|
return false;
|
|
254798
254762
|
}
|
|
@@ -256558,7 +256522,7 @@ function sourceSetConservation(input) {
|
|
|
256558
256522
|
return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
|
|
256559
256523
|
}
|
|
256560
256524
|
function payloadChecksum(value2) {
|
|
256561
|
-
return (0,
|
|
256525
|
+
return (0, import_node_crypto74.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
256562
256526
|
}
|
|
256563
256527
|
async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
|
|
256564
256528
|
const cs = quoteIdent2(companySchema);
|
|
@@ -256946,11 +256910,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
|
|
|
256946
256910
|
sequences
|
|
256947
256911
|
};
|
|
256948
256912
|
}
|
|
256949
|
-
var
|
|
256913
|
+
var import_node_crypto74, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
|
|
256950
256914
|
var init_tenant_migration_operator = __esm({
|
|
256951
256915
|
"../storage/src/tenant-migration-operator.ts"() {
|
|
256952
256916
|
"use strict";
|
|
256953
|
-
|
|
256917
|
+
import_node_crypto74 = require("node:crypto");
|
|
256954
256918
|
init_esm();
|
|
256955
256919
|
init_pg_ident();
|
|
256956
256920
|
init_tenancy_attribution();
|
|
@@ -257180,44 +257144,44 @@ var init_tenant_new_company_provision = __esm({
|
|
|
257180
257144
|
});
|
|
257181
257145
|
|
|
257182
257146
|
// ../storage/src/knowledge-snapshot-crypto.ts
|
|
257183
|
-
function sealSnapshot(
|
|
257184
|
-
if (
|
|
257185
|
-
const iv = (0,
|
|
257186
|
-
const cipher = (0,
|
|
257187
|
-
cipher.setAAD(aad2(
|
|
257188
|
-
const encrypted = Buffer.concat([cipher.update(
|
|
257189
|
-
return { ...structuredClone(
|
|
257190
|
-
}
|
|
257191
|
-
function openSnapshot(
|
|
257192
|
-
if (!
|
|
257193
|
-
const packed =
|
|
257194
|
-
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${
|
|
257147
|
+
function sealSnapshot(snapshot2, key) {
|
|
257148
|
+
if (snapshot2.content.startsWith(PREFIX3)) return structuredClone(snapshot2);
|
|
257149
|
+
const iv = (0, import_node_crypto75.randomBytes)(12);
|
|
257150
|
+
const cipher = (0, import_node_crypto75.createCipheriv)("aes-256-gcm", bytes(key), iv);
|
|
257151
|
+
cipher.setAAD(aad2(snapshot2));
|
|
257152
|
+
const encrypted = Buffer.concat([cipher.update(snapshot2.content, "utf8"), cipher.final()]);
|
|
257153
|
+
return { ...structuredClone(snapshot2), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
|
|
257154
|
+
}
|
|
257155
|
+
function openSnapshot(snapshot2, key) {
|
|
257156
|
+
if (!snapshot2.content.startsWith(PREFIX3)) return structuredClone(snapshot2);
|
|
257157
|
+
const packed = snapshot2.content.slice(PREFIX3.length).split(".");
|
|
257158
|
+
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot2.ref} ciphertext is malformed`);
|
|
257195
257159
|
const [iv, tag, data] = packed;
|
|
257196
|
-
const decipher = (0,
|
|
257197
|
-
decipher.setAAD(aad2(
|
|
257160
|
+
const decipher = (0, import_node_crypto75.createDecipheriv)("aes-256-gcm", bytes(key), Buffer.from(iv, "base64url"));
|
|
257161
|
+
decipher.setAAD(aad2(snapshot2));
|
|
257198
257162
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
257199
257163
|
return {
|
|
257200
|
-
...structuredClone(
|
|
257164
|
+
...structuredClone(snapshot2),
|
|
257201
257165
|
content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
|
|
257202
257166
|
};
|
|
257203
257167
|
}
|
|
257204
|
-
var
|
|
257168
|
+
var import_node_crypto75, PREFIX3, bytes, aad2;
|
|
257205
257169
|
var init_knowledge_snapshot_crypto = __esm({
|
|
257206
257170
|
"../storage/src/knowledge-snapshot-crypto.ts"() {
|
|
257207
257171
|
"use strict";
|
|
257208
|
-
|
|
257172
|
+
import_node_crypto75 = require("node:crypto");
|
|
257209
257173
|
PREFIX3 = "oasis-knowledge:v1:";
|
|
257210
257174
|
bytes = (key) => {
|
|
257211
257175
|
const value2 = Buffer.from(key);
|
|
257212
257176
|
if (value2.length !== 32) throw new Error("knowledge snapshot key must be 32 bytes");
|
|
257213
257177
|
return value2;
|
|
257214
257178
|
};
|
|
257215
|
-
aad2 = (
|
|
257216
|
-
|
|
257217
|
-
|
|
257218
|
-
|
|
257219
|
-
|
|
257220
|
-
|
|
257179
|
+
aad2 = (snapshot2) => Buffer.from([
|
|
257180
|
+
snapshot2.organizationId,
|
|
257181
|
+
snapshot2.projectId ?? "organization",
|
|
257182
|
+
snapshot2.spaceId ?? "none",
|
|
257183
|
+
snapshot2.ref,
|
|
257184
|
+
snapshot2.contentHash
|
|
257221
257185
|
].join("\0"), "utf8");
|
|
257222
257186
|
}
|
|
257223
257187
|
});
|
|
@@ -258611,7 +258575,7 @@ var init_board_watch = __esm({
|
|
|
258611
258575
|
freshTerminalRunId: newestTerminalRun !== null && !letteredRuns.has(newestTerminalRun.runId) ? newestTerminalRun.runId : null
|
|
258612
258576
|
};
|
|
258613
258577
|
if (!decideBoardLetter(candidate, now, quietMs)) continue;
|
|
258614
|
-
const fmt = (
|
|
258578
|
+
const fmt = (fs48) => fs48.slice(0, 5).map((f2) => `- ${f2.path}\uFF08${f2.kind ?? "?"}\uFF09\xB7 ${f2.mtime ? new Date(f2.mtime).toISOString() : "?"}`).join("\n");
|
|
258615
258579
|
let body2;
|
|
258616
258580
|
let logLine;
|
|
258617
258581
|
if (candidate.freshTerminalRunId !== null) {
|
|
@@ -259192,6 +259156,58 @@ var init_read_model_clock = __esm({
|
|
|
259192
259156
|
}
|
|
259193
259157
|
});
|
|
259194
259158
|
|
|
259159
|
+
// ../server/src/task-replacement.ts
|
|
259160
|
+
var import_node_crypto76, TaskReplacementBarrier;
|
|
259161
|
+
var init_task_replacement = __esm({
|
|
259162
|
+
"../server/src/task-replacement.ts"() {
|
|
259163
|
+
"use strict";
|
|
259164
|
+
import_node_crypto76 = require("node:crypto");
|
|
259165
|
+
TaskReplacementBarrier = class {
|
|
259166
|
+
constructor(hub, timeoutMs = 3e4, locateLegacy) {
|
|
259167
|
+
this.hub = hub;
|
|
259168
|
+
this.timeoutMs = timeoutMs;
|
|
259169
|
+
this.locateLegacy = locateLegacy;
|
|
259170
|
+
}
|
|
259171
|
+
async prepare(ledger, dispatchId, nodeId, job, companyId = "") {
|
|
259172
|
+
let plan = await ledger.prepareExecution(dispatchId, nodeId);
|
|
259173
|
+
if (plan.unassignedDispatchIds?.length) {
|
|
259174
|
+
if (!this.locateLegacy) throw new Error(`\u4EFB\u52A1 ${dispatchId} \u7684\u5386\u53F2\u6267\u884C\u7F3A\u5C11\u673A\u5668\u5F52\u5C5E\uFF0C\u4E0D\u80FD\u786E\u8BA4\u6E05\u573A`);
|
|
259175
|
+
const nodes = await this.locateLegacy(plan.unassignedDispatchIds);
|
|
259176
|
+
if (!nodes.length) throw new Error(`\u4EFB\u52A1 ${dispatchId} \u7684\u5386\u53F2\u6267\u884C\u673A\u5668\u672A\u5B9A\u4F4D\uFF0C\u4E0D\u80FD\u786E\u8BA4\u6E05\u573A`);
|
|
259177
|
+
plan = await ledger.prepareExecution(dispatchId, nodeId, nodes);
|
|
259178
|
+
}
|
|
259179
|
+
const key = (0, import_node_crypto76.createHash)("sha256").update(JSON.stringify([job.server.url.replace(/\/+$/, ""), companyId, job.jobKey])).digest("hex");
|
|
259180
|
+
job.execution = { key, generation: plan.generation };
|
|
259181
|
+
const results = await Promise.allSettled(plan.nodes.map(async (node2) => {
|
|
259182
|
+
await this.replace(node2, { requestId: (0, import_node_crypto76.randomUUID)(), dispatchId, key, generation: plan.generation, legacyDispatchIds: plan.legacyDispatchIds, usesContainers: Boolean(job.executionEnv), ...job.workdirKey ? { workdirKey: job.workdirKey } : {} });
|
|
259183
|
+
await ledger.confirmExecutionPrepared(dispatchId, node2, plan.generation);
|
|
259184
|
+
}));
|
|
259185
|
+
const failures = results.flatMap((r, i) => r.status === "rejected" ? [`${plan.nodes[i]}\uFF1A${String(r.reason)}`] : []);
|
|
259186
|
+
if (failures.length) throw new Error(`\u4EFB\u52A1\u5207\u6362\u5C1A\u672A\u5B8C\u6210\uFF08\u5F53\u524D\u6267\u884C ${dispatchId}\uFF09\uFF1A${failures.join("\uFF1B")}`);
|
|
259187
|
+
await ledger.claimExecution(dispatchId, nodeId);
|
|
259188
|
+
}
|
|
259189
|
+
async replace(nodeId, request2) {
|
|
259190
|
+
const node2 = this.hub.connectedDaemons().find((n) => n.daemonId === nodeId);
|
|
259191
|
+
if (!node2) throw new Error("\u6267\u884C\u673A\u5668\u79BB\u7EBF\uFF0C\u8FDE\u63A5\u6062\u590D\u540E\u53EF\u7EE7\u7EED\u4EFB\u52A1\u5207\u6362");
|
|
259192
|
+
if (!node2.meta.supportsTaskReplacement) throw new Error("\u6267\u884C\u673A\u5668\u9700\u5347\u7EA7\u5230\u652F\u6301\u4EFB\u52A1\u6362\u8F6E\u7684\u7248\u672C");
|
|
259193
|
+
await new Promise((resolve10, reject) => {
|
|
259194
|
+
const finish = (error2) => {
|
|
259195
|
+
clearTimeout(timer);
|
|
259196
|
+
off();
|
|
259197
|
+
error2 ? reject(error2) : resolve10();
|
|
259198
|
+
};
|
|
259199
|
+
const off = this.hub.addMessageListener((sender, msg) => {
|
|
259200
|
+
if (sender !== nodeId || msg.type !== "task_replaced" || msg.requestId !== request2.requestId || msg.dispatchId !== request2.dispatchId || msg.key !== request2.key || msg.generation !== request2.generation) return;
|
|
259201
|
+
finish(msg.stopped ? void 0 : new Error(msg.detail ?? "\u65E7\u8FDB\u7A0B\u6E05\u7406\u5931\u8D25"));
|
|
259202
|
+
});
|
|
259203
|
+
const timer = setTimeout(() => finish(new Error("\u8282\u70B9\u5C1A\u672A\u5B8C\u6210\u65E7\u8FDB\u7A0B\u6E05\u7406\uFF0C\u8BF7\u68C0\u67E5\u8BE5\u8282\u70B9\u8FDE\u63A5\u4E0E\u8FDB\u7A0B\u6743\u9650")), this.timeoutMs);
|
|
259204
|
+
if (!this.hub.dispatch(nodeId, { type: "replace_task", ...request2 })) finish(new Error("\u6E05\u573A\u547D\u4EE4\u672A\u9001\u8FBE\u8282\u70B9"));
|
|
259205
|
+
});
|
|
259206
|
+
}
|
|
259207
|
+
};
|
|
259208
|
+
}
|
|
259209
|
+
});
|
|
259210
|
+
|
|
259195
259211
|
// ../server/src/index.ts
|
|
259196
259212
|
var init_src11 = __esm({
|
|
259197
259213
|
"../server/src/index.ts"() {
|
|
@@ -259284,7 +259300,6 @@ var init_src11 = __esm({
|
|
|
259284
259300
|
init_daemon_adapter();
|
|
259285
259301
|
init_dispatch_fence();
|
|
259286
259302
|
init_execution_stop();
|
|
259287
|
-
init_execution_stop_recovery();
|
|
259288
259303
|
init_node_health();
|
|
259289
259304
|
init_side_map();
|
|
259290
259305
|
init_engine();
|
|
@@ -259312,6 +259327,7 @@ var init_src11 = __esm({
|
|
|
259312
259327
|
init_run_settlement_wiring();
|
|
259313
259328
|
init_deadline_clock();
|
|
259314
259329
|
init_read_model_clock();
|
|
259330
|
+
init_task_replacement();
|
|
259315
259331
|
}
|
|
259316
259332
|
});
|
|
259317
259333
|
|
|
@@ -259443,15 +259459,15 @@ var init_trajectory = __esm({
|
|
|
259443
259459
|
});
|
|
259444
259460
|
|
|
259445
259461
|
// src/index.ts
|
|
259446
|
-
var
|
|
259447
|
-
var
|
|
259462
|
+
var fs47 = __toESM(require("node:fs"));
|
|
259463
|
+
var os16 = __toESM(require("node:os"));
|
|
259448
259464
|
var path42 = __toESM(require("node:path"));
|
|
259449
259465
|
var import_node_child_process20 = require("node:child_process");
|
|
259450
259466
|
var import_node_crypto85 = require("node:crypto");
|
|
259451
259467
|
|
|
259452
259468
|
// ../cli/src/cli.ts
|
|
259453
|
-
var
|
|
259454
|
-
var
|
|
259469
|
+
var fs42 = __toESM(require("node:fs"), 1);
|
|
259470
|
+
var os14 = __toESM(require("node:os"), 1);
|
|
259455
259471
|
var path37 = __toESM(require("node:path"), 1);
|
|
259456
259472
|
var import_node_crypto83 = require("node:crypto");
|
|
259457
259473
|
|
|
@@ -262663,14 +262679,6 @@ async function startServe(opts) {
|
|
|
262663
262679
|
// 派发台账:动态卡的 runId 与「执行轨迹」抽屉靠它把 work/review 硬关联到 agent_runs.id。
|
|
262664
262680
|
// 与上面 createServer 的 `dispatchesOfWorkorder`(timeline 用)是同一个闭包,别分叉。
|
|
262665
262681
|
dispatchesOfWorkorder: (wid) => fanOutLedger.listByWorkorder(wid),
|
|
262666
|
-
executionStopRecovery: {
|
|
262667
|
-
ledgerFor: (cid) => dispatchLedgerFor(cid),
|
|
262668
|
-
verify: async (ledger, id, verification) => {
|
|
262669
|
-
const result = await executionStopRecovery.verify(ledger, id, verification);
|
|
262670
|
-
if (result.state === "stopped") await executionStops.releaseIfStopped(id);
|
|
262671
|
-
return result;
|
|
262672
|
-
}
|
|
262673
|
-
},
|
|
262674
262682
|
// 组织汇总用——从 nodes 取 name(用户友好名),优先于 hostname 作为展示标签
|
|
262675
262683
|
listNodes: () => nodeStore.listNodes(),
|
|
262676
262684
|
// 诊断 92ac8f18-83e5fde6 §④ D-2:按**请求公司**取其 dispatcher 的 queued/backoff 信号。
|
|
@@ -263190,23 +263198,23 @@ async function startServe(opts) {
|
|
|
263190
263198
|
}
|
|
263191
263199
|
} catch (error2) {
|
|
263192
263200
|
const rollbackErrors = [];
|
|
263193
|
-
for (const
|
|
263201
|
+
for (const snapshot2 of [...snapshots2].reverse()) {
|
|
263194
263202
|
try {
|
|
263195
|
-
if (!
|
|
263196
|
-
await actors.service.deleteVariable(
|
|
263203
|
+
if (!snapshot2.row || snapshot2.previousValue === null) {
|
|
263204
|
+
await actors.service.deleteVariable(snapshot2.write.key, request2.actorId);
|
|
263197
263205
|
} else {
|
|
263198
263206
|
await actors.service.putVariable({
|
|
263199
|
-
key:
|
|
263200
|
-
value:
|
|
263201
|
-
scope:
|
|
263202
|
-
...
|
|
263203
|
-
...
|
|
263204
|
-
...
|
|
263205
|
-
encrypted:
|
|
263207
|
+
key: snapshot2.row.key,
|
|
263208
|
+
value: snapshot2.previousValue,
|
|
263209
|
+
scope: snapshot2.row.scope,
|
|
263210
|
+
...snapshot2.row.actorId ? { actorId: snapshot2.row.actorId } : {},
|
|
263211
|
+
...snapshot2.row.connectorId ? { connectorId: snapshot2.row.connectorId } : {},
|
|
263212
|
+
...snapshot2.row.overrides ? { overrides: snapshot2.row.overrides } : {},
|
|
263213
|
+
encrypted: snapshot2.row.encrypted
|
|
263206
263214
|
});
|
|
263207
263215
|
}
|
|
263208
263216
|
} catch (rollbackError) {
|
|
263209
|
-
rollbackErrors.push(`${
|
|
263217
|
+
rollbackErrors.push(`${snapshot2.write.key}: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`);
|
|
263210
263218
|
}
|
|
263211
263219
|
}
|
|
263212
263220
|
const detail = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -263412,7 +263420,9 @@ async function startServe(opts) {
|
|
|
263412
263420
|
* 这正是 ADR 点名要求的「收割记录须持久化,否则重启后 fencing 静默失效」。
|
|
263413
263421
|
*/
|
|
263414
263422
|
isDispatchFenced: async (dispatchId) => {
|
|
263415
|
-
const
|
|
263423
|
+
const ledger = await ledgerForDispatch(dispatchId);
|
|
263424
|
+
if (await ledger.getById(dispatchId)) return !await ledger.isExecutionCurrent(dispatchId);
|
|
263425
|
+
const r = await fanOutTrace.getRun(dispatchId);
|
|
263416
263426
|
if (!r) return false;
|
|
263417
263427
|
if (isExplicitlyDispatchFenced(r)) return true;
|
|
263418
263428
|
if (r.status === "running") return false;
|
|
@@ -264174,9 +264184,10 @@ async function startServe(opts) {
|
|
|
264174
264184
|
log: (m2) => console.log(m2)
|
|
264175
264185
|
});
|
|
264176
264186
|
if (!chatHandled) {
|
|
264187
|
+
const acceptsOutcome = await acceptsExecutionOutcome(await ledgerForDispatch(msg.dispatchId), msg.dispatchId);
|
|
264177
264188
|
const mapping = dispatchToWork.get(msg.dispatchId);
|
|
264178
264189
|
const exitBus = mapping ? busForCompany(mapping.companyId) ?? busForWorkorder(mapping.workorderId) : null;
|
|
264179
|
-
if (mapping && exitBus) {
|
|
264190
|
+
if (acceptsOutcome && mapping && exitBus) {
|
|
264180
264191
|
exitBus.submit({
|
|
264181
264192
|
companyId: "",
|
|
264182
264193
|
workorderId: mapping.workorderId,
|
|
@@ -264190,13 +264201,13 @@ async function startServe(opts) {
|
|
|
264190
264201
|
}
|
|
264191
264202
|
}).catch((err) => console.error(`[new-engine] work.response submit \u5931\u8D25:`, err));
|
|
264192
264203
|
dispatchToWork.delete(msg.dispatchId);
|
|
264193
|
-
if (mapping) workToSession.delete(mapping.workId);
|
|
264194
|
-
} else if (!mapping) {
|
|
264204
|
+
if (workToSession.get(mapping.workId)?.dispatchId === msg.dispatchId) workToSession.delete(mapping.workId);
|
|
264205
|
+
} else if (acceptsOutcome && !mapping) {
|
|
264195
264206
|
await fallbackDispatchExitToWork(msg);
|
|
264196
264207
|
}
|
|
264197
264208
|
const revMapping = dispatchToReview.get(msg.dispatchId);
|
|
264198
264209
|
const revExitBus = revMapping ? busForCompany(revMapping.companyId) ?? busForWorkorder(revMapping.workorderId) : null;
|
|
264199
|
-
if (revMapping && revExitBus) {
|
|
264210
|
+
if (acceptsOutcome && revMapping && revExitBus) {
|
|
264200
264211
|
revExitBus.submit({
|
|
264201
264212
|
companyId: "",
|
|
264202
264213
|
workorderId: revMapping.workorderId,
|
|
@@ -264208,7 +264219,13 @@ async function startServe(opts) {
|
|
|
264208
264219
|
}
|
|
264209
264220
|
}).catch((err) => console.error(`[new-engine] review.expired submit \u5931\u8D25:`, err));
|
|
264210
264221
|
dispatchToReview.delete(msg.dispatchId);
|
|
264211
|
-
reviewToSession.delete(revMapping.reviewId);
|
|
264222
|
+
if (reviewToSession.get(revMapping.reviewId)?.dispatchId === msg.dispatchId) reviewToSession.delete(revMapping.reviewId);
|
|
264223
|
+
}
|
|
264224
|
+
if (!acceptsOutcome) {
|
|
264225
|
+
dispatchToWork.delete(msg.dispatchId);
|
|
264226
|
+
dispatchToReview.delete(msg.dispatchId);
|
|
264227
|
+
if (mapping && workToSession.get(mapping.workId)?.dispatchId === msg.dispatchId) workToSession.delete(mapping.workId);
|
|
264228
|
+
if (revMapping && reviewToSession.get(revMapping.reviewId)?.dispatchId === msg.dispatchId) reviewToSession.delete(revMapping.reviewId);
|
|
264212
264229
|
}
|
|
264213
264230
|
await reconcileDispatchExitFrame({
|
|
264214
264231
|
dispatchId: msg.dispatchId,
|
|
@@ -264312,11 +264329,27 @@ async function startServe(opts) {
|
|
|
264312
264329
|
gatewayUrl: opts.gatewayUrl ?? `ws://127.0.0.1:${opts.port ?? 7320}/node-gateway`
|
|
264313
264330
|
}
|
|
264314
264331
|
};
|
|
264332
|
+
const taskReplacements = new TaskReplacementBarrier(hub, void 0, async (ids2) => {
|
|
264333
|
+
const nodes = /* @__PURE__ */ new Set();
|
|
264334
|
+
for (const id of ids2) {
|
|
264335
|
+
const run = await fanOutTrace.getRun(id);
|
|
264336
|
+
const instance = run?.runtimeInstanceId;
|
|
264337
|
+
if (!instance?.startsWith("runtime:") || instance.lastIndexOf(":") <= 8) {
|
|
264338
|
+
throw new Error("\u5386\u53F2\u4EFB\u52A1\u7684\u6267\u884C\u673A\u5668\u5F52\u5C5E\u7F3A\u5931\uFF0C\u65E0\u6CD5\u81EA\u52A8\u6E05\u573A\uFF1B\u8BF7\u6062\u590D\u8BE5\u4EFB\u52A1\u7684\u8282\u70B9\u767B\u8BB0\u548C\u8FD0\u884C\u8F68\u8FF9\u540E\u91CD\u8BD5");
|
|
264339
|
+
}
|
|
264340
|
+
nodes.add(instance.slice(8, instance.lastIndexOf(":")));
|
|
264341
|
+
}
|
|
264342
|
+
return [...nodes];
|
|
264343
|
+
});
|
|
264344
|
+
hub.executionIsCurrent = async (id) => {
|
|
264345
|
+
const ledger = await ledgerForDispatch(id);
|
|
264346
|
+
return !await ledger.getById(id) || ledger.isExecutionCurrent(id);
|
|
264347
|
+
};
|
|
264315
264348
|
chatRemoteAdapter = new DaemonHubAdapter(hub, { ...hubAdapterOpts, stashUnknownFrames: true });
|
|
264316
264349
|
dispatchRemoteAdapter = new DaemonHubAdapter(hub, {
|
|
264317
|
-
beforeDispatch: async (id, nodeId) => {
|
|
264350
|
+
beforeDispatch: async (id, nodeId, job) => {
|
|
264318
264351
|
const ledger = await ledgerForDispatch(id);
|
|
264319
|
-
if (await ledger.getById(id)) await
|
|
264352
|
+
if (await ledger.getById(id)) await taskReplacements.prepare(ledger, id, nodeId, job, issuer.resolveClaims(job.actorToken)?.companyId);
|
|
264320
264353
|
},
|
|
264321
264354
|
onDispatchNotSent: async (id) => {
|
|
264322
264355
|
const ledger = await ledgerForDispatch(id);
|
|
@@ -264364,13 +264397,7 @@ async function startServe(opts) {
|
|
|
264364
264397
|
const cid = companyOfDispatch(dispatchId);
|
|
264365
264398
|
return cid ? await dispatchLedgerFor(cid) : fanOutLedger;
|
|
264366
264399
|
};
|
|
264367
|
-
const
|
|
264368
|
-
const executionStops = new ExecutionStopBarrier({
|
|
264369
|
-
hub,
|
|
264370
|
-
ledgerFor: ledgerForDispatch,
|
|
264371
|
-
log: console.warn,
|
|
264372
|
-
recover: async (id) => executionStopRecovery.verify(await ledgerForDispatch(id), id)
|
|
264373
|
-
});
|
|
264400
|
+
const executionStops = new ExecutionStopBarrier({ hub, ledgerFor: ledgerForDispatch, log: console.warn });
|
|
264374
264401
|
const traceStoreForDispatch = async (dispatchId) => {
|
|
264375
264402
|
const cid = companyOfDispatch(dispatchId) ?? await fanOutTrace.companyOfRun(dispatchId).catch(() => null);
|
|
264376
264403
|
return cid ? await traceStoreFor(cid) : void 0;
|
|
@@ -264580,12 +264607,7 @@ async function startServe(opts) {
|
|
|
264580
264607
|
}
|
|
264581
264608
|
const bridge = engineDispatchBridges.forArtifact(rev.artifactId, companyId);
|
|
264582
264609
|
if (!bridge) return;
|
|
264583
|
-
const jobKey = replyIssueId ? `reply::${replyIssueId}::${rev.author}` : `produce::${rev.artifactId}`;
|
|
264584
264610
|
const ledger = await dispatchLedgerFor(companyId);
|
|
264585
|
-
for (const old of predecessorExecutions(await ledger.listByWorkorder(wid), jobKey)) {
|
|
264586
|
-
await fenceDispatch(await traceStoreFor(companyId), old.id, "successor-stop-barrier");
|
|
264587
|
-
await executionStops.cancel(ledger, old.id, old.daemonId);
|
|
264588
|
-
}
|
|
264589
264611
|
const ledgerId = `dispatch:${(0, import_node_crypto77.randomUUID)()}`;
|
|
264590
264612
|
try {
|
|
264591
264613
|
await (await dispatchLedgerFor(companyId)).reserveExecution({
|
|
@@ -264606,6 +264628,7 @@ async function startServe(opts) {
|
|
|
264606
264628
|
result = replyIssueId ? await bridge.replyWork(rev.artifactId, rev.author, replyIssueId, ledgerId) : await bridge.produce(rev.artifactId, rev.author, workId, ledgerId, opts2?.resumeEligible);
|
|
264607
264629
|
} catch (err) {
|
|
264608
264630
|
void dispatchLedgerFor(companyId).then((l) => l.close(ledgerId, { outcome: "failed", reason: `dispatch error: ${err instanceof Error ? err.message : String(err)}` })).catch(ledgerWarn("close(error)"));
|
|
264631
|
+
if (!await ledger.isExecutionLatest(ledgerId)) return;
|
|
264609
264632
|
console.log(`[new-engine] dispatchWork ${workId} \u6D3E\u53D1\u5F02\u5E38\uFF1A${String(err)} \u2192 \u7F6E work failed`);
|
|
264610
264633
|
const failBus = busForCompany(companyId);
|
|
264611
264634
|
if (failBus) {
|
|
@@ -264624,6 +264647,7 @@ async function startServe(opts) {
|
|
|
264624
264647
|
}
|
|
264625
264648
|
return;
|
|
264626
264649
|
}
|
|
264650
|
+
if (!await ledger.isExecutionLatest(ledgerId)) return;
|
|
264627
264651
|
if (result?.dispatchId) {
|
|
264628
264652
|
const delivery = dispatchRemoteAdapter?.deliveryStatus(result.dispatchId);
|
|
264629
264653
|
dispatchToWork.set(result.dispatchId, {
|
|
@@ -264637,7 +264661,8 @@ async function startServe(opts) {
|
|
|
264637
264661
|
if (delivery) workToSession.set(workId, { dispatchId: result.dispatchId, daemonId: delivery.nodeId });
|
|
264638
264662
|
dispatchedWorks.add(workId);
|
|
264639
264663
|
} else if (result?.kind === "spawn-failed" || result?.kind === "predispatch-timeout") {
|
|
264640
|
-
|
|
264664
|
+
const failureReason = result.reason ?? `dispatch ${result.kind}`;
|
|
264665
|
+
void ledger.close(ledgerId, { outcome: "failed", reason: failureReason }).catch(ledgerWarn("close(spawn-failed)"));
|
|
264641
264666
|
console.log(`[new-engine] dispatchWork ${workId} \u6D3E\u53D1\u5931\u8D25\uFF08${result.kind}${result.reason ? `\uFF1A${result.reason}` : ""}\uFF09\u2192 \u7F6E work failed`);
|
|
264642
264667
|
const failBus = busForCompany(companyId);
|
|
264643
264668
|
if (failBus) {
|
|
@@ -264650,7 +264675,7 @@ async function startServe(opts) {
|
|
|
264650
264675
|
workorderId: wid,
|
|
264651
264676
|
workId,
|
|
264652
264677
|
outcome: "failed",
|
|
264653
|
-
detail: { reason:
|
|
264678
|
+
detail: { reason: failureReason }
|
|
264654
264679
|
}
|
|
264655
264680
|
});
|
|
264656
264681
|
}
|
|
@@ -264670,11 +264695,6 @@ async function startServe(opts) {
|
|
|
264670
264695
|
const art = kernelModel.artifacts.get(nodeId);
|
|
264671
264696
|
const revWid = art?.workspace ?? "";
|
|
264672
264697
|
const reviewLedger = await dispatchLedgerFor(companyId);
|
|
264673
|
-
const reviewJobKey = `review::${nodeId}::${reviewerActorId}`;
|
|
264674
|
-
for (const old of predecessorExecutions(await reviewLedger.listByWorkorder(revWid), reviewJobKey)) {
|
|
264675
|
-
await fenceDispatch(await traceStoreFor(companyId), old.id, "review-successor-stop-barrier");
|
|
264676
|
-
await executionStops.cancel(reviewLedger, old.id, old.daemonId);
|
|
264677
|
-
}
|
|
264678
264698
|
const ledgerId = `dispatch:${(0, import_node_crypto77.randomUUID)()}`;
|
|
264679
264699
|
try {
|
|
264680
264700
|
await (await dispatchLedgerFor(companyId)).reserveExecution({
|
|
@@ -264695,14 +264715,16 @@ async function startServe(opts) {
|
|
|
264695
264715
|
result = await bridge.review(nodeId, reviewerActorId, ledgerId, reviewId);
|
|
264696
264716
|
} catch (err) {
|
|
264697
264717
|
void dispatchLedgerFor(companyId).then((l) => l.close(ledgerId, { outcome: "failed", reason: `dispatch error: ${err instanceof Error ? err.message : String(err)}` })).catch(ledgerWarn("close(review-error)"));
|
|
264718
|
+
if (!await reviewLedger.isExecutionLatest(ledgerId)) return;
|
|
264698
264719
|
throw err;
|
|
264699
264720
|
}
|
|
264721
|
+
if (!await reviewLedger.isExecutionLatest(ledgerId)) return;
|
|
264700
264722
|
if (result?.dispatchId) {
|
|
264701
264723
|
dispatchedReviews.add(reviewId);
|
|
264702
264724
|
dispatchToReview.set(result.dispatchId, { reviewId, workorderId: revWid, nodeId, companyId });
|
|
264703
264725
|
if (revWid) workorderCompany.set(revWid, companyId);
|
|
264704
264726
|
} else if (result?.kind === "spawn-failed" || result?.kind === "predispatch-timeout") {
|
|
264705
|
-
void
|
|
264727
|
+
void reviewLedger.close(ledgerId, { outcome: "failed", reason: result.reason ?? `dispatch ${result.kind}` }).catch(ledgerWarn("close(review-spawn-failed)"));
|
|
264706
264728
|
} else if (result?.kind) {
|
|
264707
264729
|
void dispatchLedgerFor(companyId).then((l) => l.close(ledgerId, { outcome: "superseded", reason: result.kind })).catch(ledgerWarn("close(review-skipped)"));
|
|
264708
264730
|
}
|
|
@@ -264715,9 +264737,8 @@ async function startServe(opts) {
|
|
|
264715
264737
|
const ids2 = new Map(rows.map((r) => [r.id, r.daemonId]));
|
|
264716
264738
|
if (mapped) ids2.set(mapped.dispatchId, mapped.daemonId);
|
|
264717
264739
|
for (const [dispatchId, daemonId] of ids2) {
|
|
264718
|
-
await fenceDispatch(await traceStoreFor(companyId), dispatchId, "engine-cancel-before-successor");
|
|
264719
264740
|
await executionStops.cancel(ledger, dispatchId, daemonId);
|
|
264720
|
-
await ledger.close(dispatchId, { outcome: "cancelled", reason: "session-stop-
|
|
264741
|
+
await ledger.close(dispatchId, { outcome: "cancelled", reason: "session-stop-requested" });
|
|
264721
264742
|
}
|
|
264722
264743
|
workToSession.delete(ref2);
|
|
264723
264744
|
reviewToSession.delete(ref2);
|
|
@@ -266473,7 +266494,7 @@ var SessionManager = class {
|
|
|
266473
266494
|
};
|
|
266474
266495
|
|
|
266475
266496
|
// ../cli/src/daemon/session-process.ts
|
|
266476
|
-
var
|
|
266497
|
+
var fs38 = __toESM(require("node:fs"), 1);
|
|
266477
266498
|
var path33 = __toESM(require("node:path"), 1);
|
|
266478
266499
|
init_wrapper();
|
|
266479
266500
|
init_src();
|
|
@@ -266560,10 +266581,15 @@ function isSessionLocked(lockPath) {
|
|
|
266560
266581
|
}
|
|
266561
266582
|
}
|
|
266562
266583
|
|
|
266563
|
-
// ../cli/src/daemon/
|
|
266564
|
-
|
|
266584
|
+
// ../cli/src/daemon/session-runner.ts
|
|
266585
|
+
init_src();
|
|
266586
|
+
init_src6();
|
|
266587
|
+
init_src8();
|
|
266588
|
+
|
|
266589
|
+
// ../cli/src/daemon/task-execution.ts
|
|
266590
|
+
var fs37 = __toESM(require("node:fs"), 1);
|
|
266565
266591
|
var path32 = __toESM(require("node:path"), 1);
|
|
266566
|
-
var
|
|
266592
|
+
var os10 = __toESM(require("node:os"), 1);
|
|
266567
266593
|
var import_node_crypto79 = require("node:crypto");
|
|
266568
266594
|
|
|
266569
266595
|
// ../cli/src/daemon/execution-lock.ts
|
|
@@ -266577,38 +266603,6 @@ var ExecutionLockConflictError = class extends Error {
|
|
|
266577
266603
|
this.conflictingDispatchId = conflictingDispatchId;
|
|
266578
266604
|
}
|
|
266579
266605
|
};
|
|
266580
|
-
function mutateLock(file, fn) {
|
|
266581
|
-
const guard = `${file}.guard`;
|
|
266582
|
-
fs35.mkdirSync(guard, { mode: 448 });
|
|
266583
|
-
try {
|
|
266584
|
-
return fn();
|
|
266585
|
-
} finally {
|
|
266586
|
-
fs35.rmdirSync(guard);
|
|
266587
|
-
}
|
|
266588
|
-
}
|
|
266589
|
-
function releaseExecutionLocksForDispatch(dispatchId, root = path31.join(os9.tmpdir(), `oasis-execution-locks-${process.getuid?.() ?? "user"}`)) {
|
|
266590
|
-
let names;
|
|
266591
|
-
try {
|
|
266592
|
-
names = fs35.readdirSync(root);
|
|
266593
|
-
} catch (e) {
|
|
266594
|
-
if (e.code === "ENOENT") return;
|
|
266595
|
-
throw e;
|
|
266596
|
-
}
|
|
266597
|
-
for (const name of names) {
|
|
266598
|
-
if (!/^[a-f0-9]{64}$/.test(name)) continue;
|
|
266599
|
-
const file = path31.join(root, name);
|
|
266600
|
-
try {
|
|
266601
|
-
const before = JSON.parse(fs35.readFileSync(file, "utf8"));
|
|
266602
|
-
if (before.dispatchId !== dispatchId) continue;
|
|
266603
|
-
mutateLock(file, () => {
|
|
266604
|
-
const held = JSON.parse(fs35.readFileSync(file, "utf8"));
|
|
266605
|
-
if (held.dispatchId === dispatchId && held.owner) fs35.unlinkSync(file);
|
|
266606
|
-
});
|
|
266607
|
-
} catch (e) {
|
|
266608
|
-
if (e.code !== "ENOENT") throw e;
|
|
266609
|
-
}
|
|
266610
|
-
}
|
|
266611
|
-
}
|
|
266612
266606
|
function executionLockKey(job) {
|
|
266613
266607
|
const key = job.workdirKey ?? job.jobKey;
|
|
266614
266608
|
if (!key) return null;
|
|
@@ -266621,7 +266615,7 @@ function acquireExecutionLock(job, dispatchId, root = path31.join(os9.tmpdir(),
|
|
|
266621
266615
|
const file = path31.join(root, key);
|
|
266622
266616
|
const owner = (0, import_node_crypto78.randomUUID)();
|
|
266623
266617
|
try {
|
|
266624
|
-
|
|
266618
|
+
fs35.writeFileSync(file, JSON.stringify({ owner, pid: process.pid, dispatchId }), { flag: "wx", mode: 384 });
|
|
266625
266619
|
} catch (e) {
|
|
266626
266620
|
if (e.code === "EEXIST") {
|
|
266627
266621
|
let conflictingDispatchId = null;
|
|
@@ -266636,121 +266630,343 @@ function acquireExecutionLock(job, dispatchId, root = path31.join(os9.tmpdir(),
|
|
|
266636
266630
|
}
|
|
266637
266631
|
return { path: file, release() {
|
|
266638
266632
|
try {
|
|
266639
|
-
|
|
266640
|
-
if (JSON.parse(fs35.readFileSync(file, "utf8")).owner === owner) fs35.unlinkSync(file);
|
|
266641
|
-
});
|
|
266633
|
+
if (JSON.parse(fs35.readFileSync(file, "utf8")).owner === owner) fs35.unlinkSync(file);
|
|
266642
266634
|
} catch {
|
|
266643
266635
|
}
|
|
266644
266636
|
} };
|
|
266645
266637
|
}
|
|
266638
|
+
function clearStoppedExecutionLocks(dispatchIds, root = path31.join(os9.tmpdir(), `oasis-execution-locks-${process.getuid?.() ?? "user"}`)) {
|
|
266639
|
+
const stopped2 = new Set(dispatchIds);
|
|
266640
|
+
let files;
|
|
266641
|
+
try {
|
|
266642
|
+
files = fs35.readdirSync(root);
|
|
266643
|
+
} catch (e) {
|
|
266644
|
+
if (e.code === "ENOENT") return;
|
|
266645
|
+
throw e;
|
|
266646
|
+
}
|
|
266647
|
+
for (const file of files) {
|
|
266648
|
+
if (!/^[a-f0-9]{64}$/.test(file)) continue;
|
|
266649
|
+
const target = path31.join(root, file);
|
|
266650
|
+
let owner;
|
|
266651
|
+
try {
|
|
266652
|
+
owner = JSON.parse(fs35.readFileSync(target, "utf8"));
|
|
266653
|
+
} catch {
|
|
266654
|
+
continue;
|
|
266655
|
+
}
|
|
266656
|
+
if (!owner?.dispatchId || !stopped2.has(owner.dispatchId)) continue;
|
|
266657
|
+
try {
|
|
266658
|
+
fs35.unlinkSync(target);
|
|
266659
|
+
} catch (e) {
|
|
266660
|
+
if (e.code !== "ENOENT") throw new Error("\u65E0\u6CD5\u56DE\u6536\u65E7\u4EFB\u52A1\u76EE\u5F55\u9501");
|
|
266661
|
+
}
|
|
266662
|
+
}
|
|
266663
|
+
}
|
|
266646
266664
|
|
|
266647
|
-
// ../cli/src/daemon/execution
|
|
266665
|
+
// ../cli/src/daemon/task-execution.ts
|
|
266666
|
+
init_src6();
|
|
266667
|
+
|
|
266668
|
+
// ../cli/src/daemon/task-processes.ts
|
|
266669
|
+
var fs36 = __toESM(require("node:fs"), 1);
|
|
266670
|
+
var import_node_child_process16 = require("node:child_process");
|
|
266671
|
+
var psEnv = { ...process.env, LC_ALL: "C" };
|
|
266648
266672
|
function processBirth(pid) {
|
|
266649
|
-
const
|
|
266650
|
-
|
|
266673
|
+
const p2 = (0, import_node_child_process16.spawnSync)("ps", ["-p", String(pid), "-o", "lstart="], { encoding: "utf8", env: psEnv, timeout: 3e3 });
|
|
266674
|
+
if (p2.error) throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u8FDB\u7A0B\u8EAB\u4EFD");
|
|
266675
|
+
return p2.stdout.trim();
|
|
266676
|
+
}
|
|
266677
|
+
function snapshot() {
|
|
266678
|
+
const p2 = (0, import_node_child_process16.spawnSync)("ps", ["-A", "-o", "pid=,ppid=,pgid=,stat=,lstart=,command="], { encoding: "utf8", env: psEnv, timeout: 3e3, maxBuffer: 16 * 1024 * 1024 });
|
|
266679
|
+
if (p2.status !== 0) throw new Error("\u65E0\u6CD5\u6838\u9A8C\u8282\u70B9\u8FDB\u7A0B\u8868");
|
|
266680
|
+
return p2.stdout.split("\n").flatMap((line) => {
|
|
266681
|
+
const parts = line.trim().split(/\s+/);
|
|
266682
|
+
return parts.length < 9 ? [] : [{ pid: Number(parts[0]), ppid: Number(parts[1]), pgid: Number(parts[2]), state: parts[3], birth: parts.slice(4, 9).join(" "), command: parts.slice(9).join(" ") }];
|
|
266683
|
+
});
|
|
266651
266684
|
}
|
|
266652
|
-
function
|
|
266653
|
-
const
|
|
266654
|
-
|
|
266655
|
-
|
|
266656
|
-
|
|
266657
|
-
|
|
266658
|
-
|
|
266659
|
-
|
|
266660
|
-
|
|
266661
|
-
|
|
266662
|
-
|
|
266663
|
-
|
|
266664
|
-
fs36.fsyncSync(dir);
|
|
266665
|
-
} finally {
|
|
266666
|
-
fs36.closeSync(dir);
|
|
266685
|
+
function executionIdentity(environment) {
|
|
266686
|
+
const value2 = (name) => new RegExp(`(?:^|[\\s\\0])${name}=([^\\s\\0]+)`).exec(environment)?.[1];
|
|
266687
|
+
let dispatchId = value2("OASIS_EXECUTION_DISPATCH_ID");
|
|
266688
|
+
if (!dispatchId) {
|
|
266689
|
+
const token = value2("OASIS_TOKEN");
|
|
266690
|
+
if (token?.startsWith("ost_")) {
|
|
266691
|
+
try {
|
|
266692
|
+
const claims = JSON.parse(Buffer.from(token.slice(4).split(".")[0], "base64url").toString("utf8"));
|
|
266693
|
+
if (typeof claims.dispatchId === "string") dispatchId = claims.dispatchId;
|
|
266694
|
+
} catch {
|
|
266695
|
+
}
|
|
266696
|
+
}
|
|
266667
266697
|
}
|
|
266698
|
+
return { key: value2("OASIS_EXECUTION_KEY"), generation: Number(value2("OASIS_EXECUTION_GENERATION")), dispatchId };
|
|
266668
266699
|
}
|
|
266669
|
-
|
|
266670
|
-
|
|
266671
|
-
|
|
266672
|
-
|
|
266700
|
+
function environments(rows) {
|
|
266701
|
+
if (process.platform === "linux") {
|
|
266702
|
+
const out = /* @__PURE__ */ new Map();
|
|
266703
|
+
for (const row of rows) {
|
|
266704
|
+
try {
|
|
266705
|
+
if (fs36.statSync(`/proc/${row.pid}`).uid !== process.getuid?.()) continue;
|
|
266706
|
+
out.set(row.pid, fs36.readFileSync(`/proc/${row.pid}/environ`, "utf8"));
|
|
266707
|
+
} catch (e) {
|
|
266708
|
+
if (!["ENOENT", "ESRCH"].includes(e.code ?? "") && !row.state.startsWith("Z")) throw new Error(`\u65E0\u6CD5\u6838\u9A8C\u8FDB\u7A0B ${row.pid} \u7684\u4EFB\u52A1\u5F52\u5C5E`);
|
|
266709
|
+
}
|
|
266710
|
+
}
|
|
266711
|
+
return out;
|
|
266673
266712
|
}
|
|
266674
|
-
|
|
266675
|
-
const
|
|
266676
|
-
|
|
266677
|
-
|
|
266678
|
-
|
|
266679
|
-
|
|
266680
|
-
|
|
266681
|
-
|
|
266682
|
-
|
|
266683
|
-
|
|
266713
|
+
if (process.platform === "darwin") {
|
|
266714
|
+
const p2 = (0, import_node_child_process16.spawnSync)("ps", ["eww", "-U", String(process.getuid?.()), "-o", "pid=,command="], { encoding: "utf8", env: psEnv, timeout: 3e3, maxBuffer: 32 * 1024 * 1024 });
|
|
266715
|
+
if (p2.status !== 0) throw new Error("\u65E0\u6CD5\u6838\u9A8C\u8282\u70B9\u6267\u884C\u73AF\u5883");
|
|
266716
|
+
return new Map(p2.stdout.split("\n").flatMap((line) => {
|
|
266717
|
+
const m2 = /^\s*(\d+)\s+(.*)$/.exec(line);
|
|
266718
|
+
return m2 ? [[Number(m2[1]), m2[2]]] : [];
|
|
266719
|
+
}));
|
|
266720
|
+
}
|
|
266721
|
+
throw new Error("\u5F53\u524D\u8282\u70B9\u4E0D\u652F\u6301\u53EF\u9A8C\u8BC1\u7684\u4EFB\u52A1\u8FDB\u7A0B\u6811\u6E05\u573A");
|
|
266722
|
+
}
|
|
266723
|
+
async function stopTaskProcesses(scope) {
|
|
266724
|
+
const ids2 = new Set(scope.legacyDispatchIds), safeIds = scope.legacyDispatchIds.map((id) => id.replace(/[^A-Za-z0-9._-]/g, "_"));
|
|
266725
|
+
const captured = /* @__PURE__ */ new Map();
|
|
266726
|
+
const deadline = Date.now() + 2e4;
|
|
266727
|
+
const isOld = (identity) => identity.key === scope.key && identity.generation < scope.generation || Boolean(identity.dispatchId && ids2.has(identity.dispatchId));
|
|
266728
|
+
const signal = (row, sig) => {
|
|
266729
|
+
scope.assertCurrent();
|
|
266730
|
+
if (row.pid === process.pid || row.pid <= 1 || row.birth !== processBirth(row.pid).replace(/\s+/g, " ")) return;
|
|
266731
|
+
try {
|
|
266732
|
+
process.kill(row.pid, sig);
|
|
266733
|
+
} catch (e) {
|
|
266734
|
+
if (e.code !== "ESRCH") throw new Error(`\u65E0\u6CD5\u505C\u6B62\u4EFB\u52A1\u8FDB\u7A0B ${row.pid}`);
|
|
266735
|
+
}
|
|
266736
|
+
};
|
|
266737
|
+
const containers = new Set(scope.checkContainers === false ? [] : scope.containers);
|
|
266738
|
+
const containerAbsent = (name) => {
|
|
266739
|
+
const result = (0, import_node_child_process16.spawnSync)("podman", ["container", "exists", name], { timeout: 3e3 });
|
|
266740
|
+
if (result.status === 1) return true;
|
|
266741
|
+
if (result.status !== 0) throw new Error("\u5BB9\u5668\u505C\u6B62\u72B6\u6001\u65E0\u6CD5\u786E\u8BA4");
|
|
266742
|
+
return false;
|
|
266743
|
+
};
|
|
266744
|
+
const discoverContainers = () => {
|
|
266745
|
+
if (scope.checkContainers === false) return;
|
|
266746
|
+
const podman = (0, import_node_child_process16.spawnSync)("podman", ["ps", "-a", "--format", "{{.Names}}"], { encoding: "utf8", timeout: 3e3 });
|
|
266747
|
+
if (podman.error && podman.error.code !== "ENOENT") throw new Error("\u65E0\u6CD5\u6838\u9A8C\u4EFB\u52A1\u5BB9\u5668");
|
|
266748
|
+
if (!podman.error && podman.status !== 0) throw new Error("\u5BB9\u5668\u5F15\u64CE\u4E0D\u53EF\u7528\uFF0C\u4EFB\u52A1\u5207\u6362\u7B49\u5F85\u8282\u70B9\u4FEE\u590D");
|
|
266749
|
+
if (podman.error?.code === "ENOENT") containers.clear();
|
|
266750
|
+
for (const name of (podman.stdout ?? "").split("\n").filter((n) => /^oasis-(job|wd)-[A-Za-z0-9_-]+$/.test(n))) {
|
|
266751
|
+
const result = (0, import_node_child_process16.spawnSync)("podman", ["inspect", name], { encoding: "utf8", timeout: 3e3, maxBuffer: 8 * 1024 * 1024 });
|
|
266752
|
+
if (result.status !== 0) {
|
|
266753
|
+
if (containerAbsent(name)) {
|
|
266754
|
+
containers.delete(name);
|
|
266755
|
+
continue;
|
|
266684
266756
|
}
|
|
266685
|
-
|
|
266757
|
+
throw new Error("\u65E0\u6CD5\u6838\u9A8C\u4EFB\u52A1\u5BB9\u5668\u8EAB\u4EFD");
|
|
266758
|
+
}
|
|
266759
|
+
const config2 = JSON.parse(result.stdout)[0];
|
|
266760
|
+
if (isOld(executionIdentity((config2?.Config?.Env ?? []).join("\0")))) containers.add(name);
|
|
266761
|
+
}
|
|
266762
|
+
};
|
|
266763
|
+
do {
|
|
266764
|
+
scope.assertCurrent();
|
|
266765
|
+
discoverContainers();
|
|
266766
|
+
const rows = snapshot().filter((r) => !r.state.startsWith("Z")), env = environments(rows);
|
|
266767
|
+
const selected = new Set(rows.filter((r) => r.pid !== process.pid && (captured.get(r.pid) === r.birth || scope.owners.some((o) => o.pid === r.pid && o.birth.replace(/\s+/g, " ") === r.birth) || isOld(executionIdentity(env.get(r.pid) ?? r.command)) || r.command.includes("--_session ") && safeIds.some((id) => r.command.includes(`/sessions/${id}/spec.json`)))).map((r) => r.pid));
|
|
266768
|
+
let grew;
|
|
266769
|
+
do {
|
|
266770
|
+
grew = false;
|
|
266771
|
+
for (const row of rows) if (row.pid !== process.pid && selected.has(row.ppid) && !selected.has(row.pid)) {
|
|
266772
|
+
selected.add(row.pid);
|
|
266773
|
+
grew = true;
|
|
266774
|
+
}
|
|
266775
|
+
} while (grew);
|
|
266776
|
+
for (const row of rows.filter((r) => selected.has(r.pid))) {
|
|
266777
|
+
captured.set(row.pid, row.birth);
|
|
266778
|
+
signal(row, "SIGSTOP");
|
|
266779
|
+
}
|
|
266780
|
+
if (selected.size) {
|
|
266781
|
+
const frozen = snapshot().filter((r) => !r.state.startsWith("Z"));
|
|
266782
|
+
do {
|
|
266783
|
+
grew = false;
|
|
266784
|
+
for (const row of frozen) if (row.pid !== process.pid && selected.has(row.ppid) && !selected.has(row.pid)) {
|
|
266785
|
+
selected.add(row.pid);
|
|
266786
|
+
captured.set(row.pid, row.birth);
|
|
266787
|
+
signal(row, "SIGSTOP");
|
|
266788
|
+
grew = true;
|
|
266789
|
+
}
|
|
266790
|
+
} while (grew);
|
|
266791
|
+
for (const row of frozen.filter((r) => selected.has(r.pid))) signal(row, "SIGKILL");
|
|
266792
|
+
}
|
|
266793
|
+
for (const name of [...containers]) {
|
|
266794
|
+
if (containerAbsent(name)) {
|
|
266795
|
+
containers.delete(name);
|
|
266796
|
+
continue;
|
|
266797
|
+
}
|
|
266798
|
+
const state = (0, import_node_child_process16.spawnSync)("podman", ["inspect", "--format", "{{.State.Running}}", name], { encoding: "utf8", timeout: 3e3 });
|
|
266799
|
+
if (state.status !== 0) {
|
|
266800
|
+
if (containerAbsent(name)) {
|
|
266801
|
+
containers.delete(name);
|
|
266802
|
+
continue;
|
|
266803
|
+
}
|
|
266804
|
+
throw new Error("\u5BB9\u5668\u505C\u6B62\u72B6\u6001\u65E0\u6CD5\u786E\u8BA4");
|
|
266805
|
+
}
|
|
266806
|
+
if (state.status === 0 && state.stdout.trim() === "false") {
|
|
266807
|
+
containers.delete(name);
|
|
266808
|
+
continue;
|
|
266809
|
+
}
|
|
266810
|
+
scope.assertCurrent();
|
|
266811
|
+
const killed = (0, import_node_child_process16.spawnSync)("podman", ["kill", name], { timeout: 3e3 });
|
|
266812
|
+
if (killed.status !== 0) {
|
|
266813
|
+
if (containerAbsent(name)) {
|
|
266814
|
+
containers.delete(name);
|
|
266815
|
+
continue;
|
|
266816
|
+
}
|
|
266817
|
+
throw new Error("\u65E0\u6CD5\u7EC8\u6B62\u65E7\u4EFB\u52A1\u5BB9\u5668");
|
|
266818
|
+
}
|
|
266819
|
+
}
|
|
266820
|
+
if (!selected.size && !containers.size && !scope.busy()) return;
|
|
266821
|
+
await new Promise((resolve10) => setTimeout(resolve10, 50));
|
|
266822
|
+
} while (Date.now() < deadline);
|
|
266823
|
+
throw new Error("\u65E7\u4EFB\u52A1\u8FDB\u7A0B\u5C1A\u672A\u5168\u90E8\u505C\u6B62\uFF0C\u8BF7\u68C0\u67E5\u8282\u70B9\u8FDB\u7A0B\u6743\u9650\u6216\u4ECD\u5728\u8FDB\u884C\u7684\u542F\u52A8\u64CD\u4F5C");
|
|
266824
|
+
}
|
|
266825
|
+
|
|
266826
|
+
// ../cli/src/daemon/task-execution.ts
|
|
266827
|
+
function taskKey(job) {
|
|
266828
|
+
let companyId = "";
|
|
266829
|
+
if (job.actorToken.startsWith("ost_")) {
|
|
266830
|
+
try {
|
|
266831
|
+
companyId = JSON.parse(Buffer.from(job.actorToken.slice(4).split(".")[0], "base64url").toString("utf8")).companyId ?? "";
|
|
266832
|
+
} catch {
|
|
266833
|
+
}
|
|
266834
|
+
}
|
|
266835
|
+
return (0, import_node_crypto79.createHash)("sha256").update(JSON.stringify([job.server.url.replace(/\/+$/, ""), companyId, job.jobKey])).digest("hex");
|
|
266836
|
+
}
|
|
266837
|
+
var TaskExecutions = class {
|
|
266838
|
+
constructor(root = process.env["OASIS_TASK_EXECUTIONS_ROOT"] ?? path32.join(os10.homedir(), ".oasis", "task-executions")) {
|
|
266839
|
+
this.root = root;
|
|
266840
|
+
}
|
|
266841
|
+
dir(key) {
|
|
266842
|
+
if (!/^[a-f0-9]{64}$/.test(key)) throw new Error("\u4EFB\u52A1\u6267\u884C\u8EAB\u4EFD\u65E0\u6548");
|
|
266843
|
+
return path32.join(this.root, key);
|
|
266844
|
+
}
|
|
266845
|
+
write(file, data) {
|
|
266846
|
+
fs37.mkdirSync(path32.dirname(file), { recursive: true, mode: 448 });
|
|
266847
|
+
const temporary = `${file}.${(0, import_node_crypto79.randomUUID)()}.tmp`;
|
|
266848
|
+
const fd = fs37.openSync(temporary, "wx", 384);
|
|
266849
|
+
try {
|
|
266850
|
+
try {
|
|
266851
|
+
fs37.writeFileSync(fd, JSON.stringify(data));
|
|
266852
|
+
fs37.fsyncSync(fd);
|
|
266853
|
+
} finally {
|
|
266854
|
+
fs37.closeSync(fd);
|
|
266686
266855
|
}
|
|
266856
|
+
fs37.linkSync(temporary, file);
|
|
266857
|
+
} finally {
|
|
266858
|
+
fs37.unlinkSync(temporary);
|
|
266859
|
+
}
|
|
266860
|
+
const dir = fs37.openSync(path32.dirname(file), "r");
|
|
266861
|
+
try {
|
|
266862
|
+
fs37.fsyncSync(dir);
|
|
266863
|
+
} finally {
|
|
266864
|
+
fs37.closeSync(dir);
|
|
266687
266865
|
}
|
|
266688
|
-
return dir;
|
|
266689
266866
|
}
|
|
266690
|
-
|
|
266867
|
+
generations(key) {
|
|
266691
266868
|
try {
|
|
266692
|
-
return
|
|
266869
|
+
return fs37.readdirSync(this.dir(key)).filter((n) => /^\d+\.json$/.test(n)).map((n) => Number(n.slice(0, -5)));
|
|
266693
266870
|
} catch (e) {
|
|
266694
|
-
if (e.code === "ENOENT") return
|
|
266871
|
+
if (e.code === "ENOENT") return [];
|
|
266695
266872
|
throw e;
|
|
266696
266873
|
}
|
|
266697
266874
|
}
|
|
266698
|
-
|
|
266699
|
-
return
|
|
266875
|
+
current(key, generation) {
|
|
266876
|
+
return this.generations(key).reduce((max, value2) => Math.max(max, value2), 0) === generation;
|
|
266700
266877
|
}
|
|
266701
|
-
|
|
266702
|
-
|
|
266703
|
-
|
|
266704
|
-
|
|
266705
|
-
|
|
266706
|
-
|
|
266707
|
-
|
|
266878
|
+
assertAllowed(dispatchId, job) {
|
|
266879
|
+
if (!job.jobKey) return;
|
|
266880
|
+
const key = taskKey(job), execution = job.execution;
|
|
266881
|
+
if (!execution) {
|
|
266882
|
+
if (this.generations(key).length) throw new Error("\u65E7\u8F6E\u6B21\u5DF2\u5931\u6548\uFF0C\u62D2\u7EDD\u65E0\u8F6E\u6B21\u8BB8\u53EF\u7684\u6267\u884C");
|
|
266883
|
+
return;
|
|
266884
|
+
}
|
|
266885
|
+
if (execution.key !== key || !this.current(key, execution.generation)) throw new Error("\u65E7\u8F6E\u6B21\u5DF2\u5931\u6548\uFF0C\u62D2\u7EDD\u91CD\u65B0\u542F\u52A8");
|
|
266886
|
+
const state = JSON.parse(fs37.readFileSync(path32.join(this.dir(key), `${execution.generation}.json`), "utf8"));
|
|
266887
|
+
if (state.dispatchId !== dispatchId || !fs37.existsSync(path32.join(this.dir(key), `${execution.generation}.ready`))) throw new Error("\u4EFB\u52A1\u5C1A\u672A\u5B8C\u6210\u65E7\u8FDB\u7A0B\u6E05\u573A");
|
|
266708
266888
|
}
|
|
266709
|
-
|
|
266710
|
-
this.
|
|
266711
|
-
if (!
|
|
266889
|
+
begin(dispatchId, job, isolated = false) {
|
|
266890
|
+
this.assertAllowed(dispatchId, job);
|
|
266891
|
+
if (!job.execution) return;
|
|
266892
|
+
this.write(
|
|
266893
|
+
path32.join(this.dir(job.execution.key), `${job.execution.generation}.started`),
|
|
266894
|
+
{ dispatchId, pid: process.pid, birth: processBirth(process.pid), isolated }
|
|
266895
|
+
);
|
|
266896
|
+
try {
|
|
266897
|
+
this.assertAllowed(dispatchId, job);
|
|
266898
|
+
} catch (error2) {
|
|
266899
|
+
this.finish(job);
|
|
266900
|
+
throw error2;
|
|
266901
|
+
}
|
|
266712
266902
|
}
|
|
266713
|
-
|
|
266714
|
-
|
|
266715
|
-
|
|
266716
|
-
|
|
266717
|
-
|
|
266718
|
-
if (
|
|
266719
|
-
throw new Error("\u505C\u6B62\u6536\u636E\u635F\u574F\uFF0C\u4FDD\u6301\u4EFB\u52A1\u9501\uFF1B\u8BF7\u4FDD\u7559\u73B0\u573A\u5E76\u6838\u9A8C\u8BE5\u8BB0\u5F55");
|
|
266720
|
-
}
|
|
266721
|
-
releaseExecutionLocksForDispatch(id, this.lockRoot);
|
|
266722
|
-
return result("stopped", "\u8282\u70B9\u5DF2\u6062\u590D\u6301\u4E45\u505C\u6B62\u6536\u636E", proof);
|
|
266903
|
+
finish(job) {
|
|
266904
|
+
if (!job.execution) return;
|
|
266905
|
+
try {
|
|
266906
|
+
this.write(path32.join(this.dir(job.execution.key), `${job.execution.generation}.finished`), {});
|
|
266907
|
+
} catch (e) {
|
|
266908
|
+
if (e.code !== "EEXIST") throw e;
|
|
266723
266909
|
}
|
|
266724
|
-
|
|
266725
|
-
|
|
266726
|
-
if (
|
|
266910
|
+
}
|
|
266911
|
+
async replace(request2, local) {
|
|
266912
|
+
if (!Number.isSafeInteger(request2.generation) || request2.generation < 1) throw new Error("\u4EFB\u52A1\u8F6E\u6B21\u65E0\u6548");
|
|
266913
|
+
const dir = this.dir(request2.key), file = path32.join(dir, `${request2.generation}.json`);
|
|
266914
|
+
try {
|
|
266915
|
+
this.write(file, request2);
|
|
266916
|
+
} catch (e) {
|
|
266917
|
+
if (e.code !== "EEXIST") throw e;
|
|
266918
|
+
const existing = JSON.parse(fs37.readFileSync(file, "utf8"));
|
|
266919
|
+
if (existing.dispatchId !== request2.dispatchId) throw new Error("\u540C\u4E00\u4EFB\u52A1\u8F6E\u6B21\u8EAB\u4EFD\u51B2\u7A81");
|
|
266920
|
+
}
|
|
266921
|
+
const assertCurrent = () => {
|
|
266922
|
+
if (!this.current(request2.key, request2.generation)) throw new Error("\u6E05\u573A\u8BF7\u6C42\u5DF2\u88AB\u66F4\u65B0\u8F6E\u6B21\u66FF\u4EE3");
|
|
266923
|
+
};
|
|
266924
|
+
assertCurrent();
|
|
266925
|
+
if (fs37.existsSync(path32.join(dir, `${request2.generation}.started`))) throw new Error("\u672C\u8F6E\u5DF2\u7ECF\u542F\u52A8\uFF0C\u62D2\u7EDD\u91CD\u590D\u6E05\u573A\u6216\u542F\u52A8");
|
|
266926
|
+
const ids2 = new Set(request2.legacyDispatchIds);
|
|
266927
|
+
let checkContainers = ids2.size > 0;
|
|
266928
|
+
const owners = [];
|
|
266929
|
+
const pendingOwners = [];
|
|
266930
|
+
for (const generation of this.generations(request2.key).filter((g2) => g2 < request2.generation).sort((a, b2) => b2 - a)) {
|
|
266931
|
+
const older = JSON.parse(fs37.readFileSync(path32.join(dir, `${generation}.json`), "utf8"));
|
|
266932
|
+
const prepared = fs37.existsSync(path32.join(dir, `${generation}.ready`));
|
|
266933
|
+
checkContainers ||= older.usesContainers !== false || !prepared && older.legacyDispatchIds.length > 0;
|
|
266934
|
+
ids2.add(older.dispatchId);
|
|
266935
|
+
if (!prepared) for (const id of older.legacyDispatchIds) ids2.add(id);
|
|
266727
266936
|
try {
|
|
266728
|
-
|
|
266729
|
-
|
|
266730
|
-
|
|
266731
|
-
if (!owner.birth || !birth || birth === owner.birth) return result("running", "\u4F1A\u8BDD\u5BBF\u4E3B\u8FDB\u7A0B\u4ECD\u5B58\u5728\u6216\u8EAB\u4EFD\u65E0\u6CD5\u6392\u9664\uFF0C\u4E0D\u80FD\u4EBA\u5DE5\u786E\u8BA4\u505C\u6B62");
|
|
266937
|
+
const owner = JSON.parse(fs37.readFileSync(path32.join(dir, `${generation}.started`), "utf8"));
|
|
266938
|
+
if (owner.isolated) owners.push(owner);
|
|
266939
|
+
else pendingOwners.push({ ...owner, generation });
|
|
266732
266940
|
} catch (e) {
|
|
266733
|
-
if (e.code !== "
|
|
266941
|
+
if (e.code !== "ENOENT") throw e;
|
|
266734
266942
|
}
|
|
266943
|
+
if (prepared) break;
|
|
266735
266944
|
}
|
|
266736
|
-
const
|
|
266737
|
-
|
|
266738
|
-
|
|
266739
|
-
|
|
266740
|
-
|
|
266945
|
+
const containers = request2.workdirKey ? [`oasis-wd-${workdirSlug(request2.workdirKey)}`] : [];
|
|
266946
|
+
void local.cancel().catch(() => {
|
|
266947
|
+
});
|
|
266948
|
+
await stopTaskProcesses({
|
|
266949
|
+
key: request2.key,
|
|
266950
|
+
generation: request2.generation,
|
|
266951
|
+
legacyDispatchIds: [...ids2],
|
|
266952
|
+
owners,
|
|
266953
|
+
containers,
|
|
266954
|
+
checkContainers,
|
|
266955
|
+
busy: () => local.busy() || pendingOwners.some((o) => !fs37.existsSync(path32.join(dir, `${o.generation}.finished`)) && processBirth(o.pid) === o.birth),
|
|
266956
|
+
assertCurrent
|
|
266957
|
+
});
|
|
266958
|
+
assertCurrent();
|
|
266959
|
+
clearStoppedExecutionLocks([...ids2]);
|
|
266960
|
+
try {
|
|
266961
|
+
this.write(path32.join(dir, `${request2.generation}.ready`), { at: (/* @__PURE__ */ new Date()).toISOString() });
|
|
266962
|
+
} catch (e) {
|
|
266963
|
+
if (e.code !== "EEXIST") throw e;
|
|
266741
266964
|
}
|
|
266742
|
-
if (!verification) return result("needs_verification", "\u7F3A\u5C11\u505C\u6B62\u6536\u636E\uFF1B\u9700\u9010\u6761\u6838\u9A8C\u65E7\u5B9E\u4F8B\u3001\u5B50\u8FDB\u7A0B\u3001\u5BB9\u5668\u548C\u5F85\u542F\u52A8\u5165\u53E3\uFF0C\u63D0\u4EA4\u4EBA\u5DE5\u6838\u9A8C\u4F9D\u636E");
|
|
266743
|
-
const manual = { kind: "operator_verified", at: (/* @__PURE__ */ new Date()).toISOString(), ...verification };
|
|
266744
|
-
this.stopped(id, manual);
|
|
266745
|
-
releaseExecutionLocksForDispatch(id, this.lockRoot);
|
|
266746
|
-
return result("stopped", "\u4EBA\u5DE5\u6838\u9A8C\u5DF2\u8BB0\u5F55\uFF0C\u8282\u70B9\u5DF2\u6301\u4E45\u5C01\u7981\u65E7\u6D3E\u53D1", manual);
|
|
266747
266965
|
}
|
|
266748
266966
|
};
|
|
266749
266967
|
|
|
266750
266968
|
// ../cli/src/daemon/session-runner.ts
|
|
266751
|
-
|
|
266752
|
-
init_src6();
|
|
266753
|
-
init_src8();
|
|
266969
|
+
init_src5();
|
|
266754
266970
|
async function preflightOasisAccess(job) {
|
|
266755
266971
|
const base = job.server.url.replace(/\/+$/, "");
|
|
266756
266972
|
try {
|
|
@@ -266758,6 +266974,7 @@ async function preflightOasisAccess(job) {
|
|
|
266758
266974
|
headers: { authorization: `Bearer ${job.actorToken}` },
|
|
266759
266975
|
signal: AbortSignal.timeout(5e3)
|
|
266760
266976
|
});
|
|
266977
|
+
if (res.status === 409) return { code: null, reason: "cancelled" };
|
|
266761
266978
|
if (res.status === 401 || res.status === 403) return { code: null, reason: "auth-error" };
|
|
266762
266979
|
if (!res.ok) return { code: null, reason: "server-unreachable" };
|
|
266763
266980
|
return null;
|
|
@@ -266767,49 +266984,50 @@ async function preflightOasisAccess(job) {
|
|
|
266767
266984
|
}
|
|
266768
266985
|
async function runSession(dispatchId, job, deps) {
|
|
266769
266986
|
const t0 = Date.now();
|
|
266770
|
-
const
|
|
266771
|
-
|
|
266772
|
-
|
|
266773
|
-
|
|
266774
|
-
|
|
266775
|
-
|
|
266776
|
-
|
|
266777
|
-
|
|
266778
|
-
|
|
266779
|
-
|
|
266780
|
-
recovery.stopped(dispatchId);
|
|
266781
|
-
} catch (error2) {
|
|
266782
|
-
log2("[node-cli]", `\u505C\u6B62\u6536\u636E\u5199\u76D8\u5931\u8D25 ${dispatchId}\uFF0C\u4FDD\u6301\u672A\u786E\u8BA4\uFF1A${String(error2)}`);
|
|
266783
|
-
setTimeout(persist, 1e3);
|
|
266784
|
-
return;
|
|
266785
|
-
}
|
|
266786
|
-
originalSink.keyFrame(msg);
|
|
266787
|
-
};
|
|
266788
|
-
persist();
|
|
266789
|
-
} } };
|
|
266790
|
-
}
|
|
266987
|
+
const executions = new TaskExecutions();
|
|
266988
|
+
const wasCancelled = () => {
|
|
266989
|
+
if (deps.wasCancelled?.()) return true;
|
|
266990
|
+
try {
|
|
266991
|
+
executions.assertAllowed(dispatchId, job);
|
|
266992
|
+
return false;
|
|
266993
|
+
} catch {
|
|
266994
|
+
return true;
|
|
266995
|
+
}
|
|
266996
|
+
};
|
|
266791
266997
|
let handle;
|
|
266792
266998
|
let lock = null;
|
|
266793
266999
|
let cleanup;
|
|
266794
267000
|
let exited = false;
|
|
266795
267001
|
let admitted = false;
|
|
267002
|
+
let began = false;
|
|
266796
267003
|
const cancelledWithoutRuntime = () => {
|
|
267004
|
+
executions.finish(job);
|
|
266797
267005
|
lock?.release();
|
|
266798
267006
|
deps.sink.keyFrame({ type: "session_exited", dispatchId, sessionId: "cancelled-before-spawn", executionStopped: true, info: { code: null, reason: "cancelled" } });
|
|
266799
267007
|
deps.onFailure?.();
|
|
266800
267008
|
};
|
|
266801
267009
|
try {
|
|
266802
|
-
|
|
267010
|
+
executions.begin(dispatchId, job, deps.isolatedProcess);
|
|
267011
|
+
began = true;
|
|
267012
|
+
if (job.execution) {
|
|
267013
|
+
job = { ...job, env: {
|
|
267014
|
+
...job.env,
|
|
267015
|
+
OASIS_EXECUTION_KEY: job.execution.key,
|
|
267016
|
+
OASIS_EXECUTION_GENERATION: String(job.execution.generation),
|
|
267017
|
+
OASIS_EXECUTION_DISPATCH_ID: dispatchId
|
|
267018
|
+
} };
|
|
267019
|
+
}
|
|
266803
267020
|
lock = acquireExecutionLock(job, dispatchId);
|
|
266804
267021
|
admitted = true;
|
|
266805
|
-
if (
|
|
267022
|
+
if (wasCancelled()) {
|
|
266806
267023
|
cancelledWithoutRuntime();
|
|
266807
267024
|
return;
|
|
266808
267025
|
}
|
|
266809
|
-
if (deps.preflight) {
|
|
267026
|
+
if (deps.preflight || job.execution) {
|
|
266810
267027
|
const preflightFailure = await preflightOasisAccess(job);
|
|
266811
267028
|
if (preflightFailure) {
|
|
266812
267029
|
log2("[node-cli]", ` preflight failed: ${preflightFailure.reason}`);
|
|
267030
|
+
executions.finish(job);
|
|
266813
267031
|
lock?.release();
|
|
266814
267032
|
deps.sink.keyFrame({ type: "session_exited", dispatchId, sessionId: "preflight-failed", executionStopped: true, info: preflightFailure });
|
|
266815
267033
|
deps.onFailure?.();
|
|
@@ -266822,19 +267040,25 @@ async function runSession(dispatchId, job, deps) {
|
|
|
266822
267040
|
}
|
|
266823
267041
|
const prepared = await prepareConnectorsForJob(job);
|
|
266824
267042
|
cleanup = prepared.cleanup;
|
|
266825
|
-
if (
|
|
267043
|
+
if (wasCancelled()) {
|
|
266826
267044
|
await cleanup();
|
|
266827
267045
|
cancelledWithoutRuntime();
|
|
266828
267046
|
return;
|
|
266829
267047
|
}
|
|
266830
267048
|
handle = await deps.adapter.spawn(prepared.job);
|
|
267049
|
+
if (job.execution && job.action === "produce" && job.resumeRuntimeSession) {
|
|
267050
|
+
handle = makeProduceResumeFallback(handle, async () => {
|
|
267051
|
+
if (wasCancelled()) throw new Error("\u65E7\u8F6E\u6B21\u5DF2\u5931\u6548\uFF0C\u62D2\u7EDD\u6062\u590D\u4F1A\u8BDD\u56DE\u843D");
|
|
267052
|
+
return deps.adapter.spawn({ ...prepared.job, resumeRuntimeSession: false });
|
|
267053
|
+
});
|
|
267054
|
+
}
|
|
266831
267055
|
const startedHandle = handle;
|
|
266832
267056
|
startedHandle.onExit(() => {
|
|
266833
267057
|
void prepared.cleanup().catch(() => {
|
|
266834
267058
|
});
|
|
266835
267059
|
});
|
|
266836
267060
|
deps.onHandle?.(handle);
|
|
266837
|
-
const cancelledBeforeStart =
|
|
267061
|
+
const cancelledBeforeStart = wasCancelled();
|
|
266838
267062
|
const normalizer = new ProviderStreamNormalizer({
|
|
266839
267063
|
providerName: job.binding?.runtimeKind ?? "runtime",
|
|
266840
267064
|
hasLiveProtocol: startedHandle.supportsLiveProtocol === true,
|
|
@@ -266856,6 +267080,7 @@ async function runSession(dispatchId, job, deps) {
|
|
|
266856
267080
|
startedHandle.onExit((info) => {
|
|
266857
267081
|
if (exited) return;
|
|
266858
267082
|
exited = true;
|
|
267083
|
+
executions.finish(job);
|
|
266859
267084
|
lock?.release();
|
|
266860
267085
|
normalizer.turnFinished(isHealthySessionExit(info) ? "completed" : "failed");
|
|
266861
267086
|
log2("[node-cli]", ` \u25A0 session_exited id=${startedHandle.id} code=${info.code ?? "killed"} total=${Date.now() - t0}ms`);
|
|
@@ -266873,6 +267098,7 @@ async function runSession(dispatchId, job, deps) {
|
|
|
266873
267098
|
}
|
|
266874
267099
|
} catch (err) {
|
|
266875
267100
|
if (!admitted && !(err instanceof ExecutionLockConflictError && err.conflictingDispatchId && err.conflictingDispatchId !== dispatchId)) {
|
|
267101
|
+
if (began) executions.finish(job);
|
|
266876
267102
|
log2("[node-cli]", `\u6267\u884C ${dispatchId} \u505C\u6B62\u672A\u786E\u8BA4\uFF1A${String(err)}`);
|
|
266877
267103
|
deps.onFailure?.(false);
|
|
266878
267104
|
return;
|
|
@@ -266881,6 +267107,7 @@ async function runSession(dispatchId, job, deps) {
|
|
|
266881
267107
|
log2("[node-cli]", `\u6267\u884C ${dispatchId} \u505C\u6B62\u672A\u786E\u8BA4\uFF1A${String(err)}`);
|
|
266882
267108
|
return;
|
|
266883
267109
|
}
|
|
267110
|
+
executions.finish(job);
|
|
266884
267111
|
lock?.release();
|
|
266885
267112
|
await cleanup?.().catch(() => {
|
|
266886
267113
|
});
|
|
@@ -266913,9 +267140,9 @@ async function runSessionProcess(specFile, adapter) {
|
|
|
266913
267140
|
await state.run();
|
|
266914
267141
|
}
|
|
266915
267142
|
function readSpec(specFile) {
|
|
266916
|
-
const spec = JSON.parse(
|
|
267143
|
+
const spec = JSON.parse(fs38.readFileSync(specFile, "utf8"));
|
|
266917
267144
|
try {
|
|
266918
|
-
|
|
267145
|
+
fs38.unlinkSync(specFile);
|
|
266919
267146
|
} catch {
|
|
266920
267147
|
}
|
|
266921
267148
|
return spec;
|
|
@@ -266967,8 +267194,8 @@ var SessionProcessState = class {
|
|
|
266967
267194
|
this.finish = resolve10;
|
|
266968
267195
|
});
|
|
266969
267196
|
await runSession(this.spec.dispatchId, this.spec.job, {
|
|
266970
|
-
recovery: new ExecutionRecovery(path33.dirname(this.spec.sessionDir)),
|
|
266971
267197
|
adapter: this.adapter,
|
|
267198
|
+
isolatedProcess: true,
|
|
266972
267199
|
preflight: this.spec.preflight,
|
|
266973
267200
|
sink: {
|
|
266974
267201
|
keyFrame: (m2) => this.sendKeyFrame(m2),
|
|
@@ -267521,7 +267748,6 @@ var DaemonWsClient = class {
|
|
|
267521
267748
|
this.preflight = preflight;
|
|
267522
267749
|
this.onUpdate = onUpdate;
|
|
267523
267750
|
this.daemonVersion = daemonVersion;
|
|
267524
|
-
this.recovery = opts.sessionsRoot ? new ExecutionRecovery(opts.sessionsRoot) : void 0;
|
|
267525
267751
|
this.daemonPkg = opts.daemonPkg;
|
|
267526
267752
|
this.spawnSessionProcess = opts.spawnSessionProcess;
|
|
267527
267753
|
this.countDetachedSessions = opts.countDetachedSessions;
|
|
@@ -267559,9 +267785,10 @@ var DaemonWsClient = class {
|
|
|
267559
267785
|
draining = false;
|
|
267560
267786
|
/** 已回 dispatch_received、尚未完成 runtime spawn 的派发;也随 hello 上报供重连对账。 */
|
|
267561
267787
|
pendingDispatchIds = /* @__PURE__ */ new Set();
|
|
267788
|
+
dispatchJobs = /* @__PURE__ */ new Map();
|
|
267789
|
+
taskExecutions = new TaskExecutions();
|
|
267562
267790
|
/** setup 期间收到 kill 的派发。spawn 返回后先杀句柄,不得再宣告 session_started。 */
|
|
267563
267791
|
cancelledPendingDispatchIds = /* @__PURE__ */ new Set();
|
|
267564
|
-
recovery;
|
|
267565
267792
|
spawnSessionProcess;
|
|
267566
267793
|
countDetachedSessions;
|
|
267567
267794
|
/**
|
|
@@ -267744,18 +267971,36 @@ var DaemonWsClient = class {
|
|
|
267744
267971
|
}
|
|
267745
267972
|
async handleMessage(msg) {
|
|
267746
267973
|
switch (msg.type) {
|
|
267974
|
+
case "replace_task": {
|
|
267975
|
+
const matches = () => [...this.dispatchJobs].filter(([id, job]) => id !== msg.dispatchId && (taskKey(job) === msg.key || msg.legacyDispatchIds.includes(id)));
|
|
267976
|
+
try {
|
|
267977
|
+
await this.taskExecutions.replace(msg, {
|
|
267978
|
+
cancel: async () => {
|
|
267979
|
+
for (const [id] of matches()) this.cancelledPendingDispatchIds.add(id);
|
|
267980
|
+
await Promise.all(matches().map(([id]) => this.sessions.kill(id)));
|
|
267981
|
+
},
|
|
267982
|
+
busy: () => matches().some(([id]) => this.pendingDispatchIds.has(id) || Boolean(this.sessions.get(id)))
|
|
267983
|
+
});
|
|
267984
|
+
for (const [id] of matches()) {
|
|
267985
|
+
this.dispatchJobs.delete(id);
|
|
267986
|
+
this.cancelledPendingDispatchIds.delete(id);
|
|
267987
|
+
}
|
|
267988
|
+
this.send({ type: "task_replaced", requestId: msg.requestId, dispatchId: msg.dispatchId, key: msg.key, generation: msg.generation, stopped: true });
|
|
267989
|
+
} catch (e) {
|
|
267990
|
+
this.send({ type: "task_replaced", requestId: msg.requestId, dispatchId: msg.dispatchId, key: msg.key, generation: msg.generation, stopped: false, detail: String(e) });
|
|
267991
|
+
}
|
|
267992
|
+
break;
|
|
267993
|
+
}
|
|
267747
267994
|
case "dispatch": {
|
|
267748
267995
|
const { dispatchId, job } = msg;
|
|
267996
|
+
const t0 = Date.now();
|
|
267749
267997
|
try {
|
|
267750
|
-
|
|
267751
|
-
|
|
267752
|
-
|
|
267753
|
-
}
|
|
267754
|
-
} catch (error2) {
|
|
267755
|
-
log2("[node-cli]", `\u65E0\u6CD5\u8BFB\u53D6\u6267\u884C\u5C01\u7981\uFF0C\u62D2\u7EDD\u542F\u52A8 ${dispatchId}\uFF1A${String(error2)}`);
|
|
267998
|
+
this.taskExecutions.assertAllowed(dispatchId, job);
|
|
267999
|
+
} catch {
|
|
268000
|
+
log2("[node-cli]", `\u62D2\u7EDD\u5931\u6548\u8F6E\u6B21 ${dispatchId}`);
|
|
267756
268001
|
break;
|
|
267757
268002
|
}
|
|
267758
|
-
|
|
268003
|
+
this.dispatchJobs.set(dispatchId, job);
|
|
267759
268004
|
log2("[node-cli]", `\u2190 dispatch ${dispatchId} artifact=${job.artifactId}`);
|
|
267760
268005
|
if (this.pendingDispatchIds.has(dispatchId) || this.sessions.get(dispatchId)) {
|
|
267761
268006
|
this.send({ type: "dispatch_received", dispatchId });
|
|
@@ -267764,7 +268009,6 @@ var DaemonWsClient = class {
|
|
|
267764
268009
|
if (this.draining) {
|
|
267765
268010
|
log2("[node-cli]", ` \u62D2\u6536\uFF1A\u8282\u70B9\u6B63\u5728\u505C\u673A\u6392\u7A7A \u2192 \u56DE\u9000\u51FA\u5E27\uFF0C\u670D\u52A1\u7AEF\u53EF\u7ACB\u5373\u6539\u6D3E`);
|
|
267766
268011
|
await runSession(dispatchId, job, {
|
|
267767
|
-
recovery: this.recovery,
|
|
267768
268012
|
adapter: this.sessions.getAdapter(),
|
|
267769
268013
|
preflight: false,
|
|
267770
268014
|
wasCancelled: () => true,
|
|
@@ -267785,7 +268029,6 @@ var DaemonWsClient = class {
|
|
|
267785
268029
|
log2("[node-cli]", ` \u72EC\u7ACB\u4F1A\u8BDD\u8FDB\u7A0B\u672A\u63A5\u7BA1\uFF0C\u56DE\u843D\u672C\u8FDB\u7A0B\u8DD1 dispatch=${dispatchId}`);
|
|
267786
268030
|
}
|
|
267787
268031
|
await runSession(dispatchId, job, {
|
|
267788
|
-
recovery: this.recovery,
|
|
267789
268032
|
adapter: this.sessions.getAdapter(),
|
|
267790
268033
|
preflight: this.preflight,
|
|
267791
268034
|
sink: {
|
|
@@ -267804,37 +268047,20 @@ var DaemonWsClient = class {
|
|
|
267804
268047
|
},
|
|
267805
268048
|
wasCancelled: () => this.cancelledPendingDispatchIds.has(dispatchId),
|
|
267806
268049
|
onExited: () => {
|
|
268050
|
+
this.dispatchJobs.delete(dispatchId);
|
|
267807
268051
|
this.cancelledPendingDispatchIds.delete(dispatchId);
|
|
267808
268052
|
this.maybeRunPendingUpdate();
|
|
267809
268053
|
},
|
|
267810
268054
|
onFailure: () => {
|
|
268055
|
+
this.dispatchJobs.delete(dispatchId);
|
|
267811
268056
|
this.pendingDispatchIds.delete(dispatchId);
|
|
267812
268057
|
this.cancelledPendingDispatchIds.delete(dispatchId);
|
|
267813
268058
|
}
|
|
267814
268059
|
});
|
|
267815
268060
|
break;
|
|
267816
268061
|
}
|
|
267817
|
-
case "verify_execution_stop": {
|
|
267818
|
-
let result;
|
|
267819
|
-
try {
|
|
267820
|
-
result = this.recovery ? this.recovery.verify(msg.dispatchId, this.pendingDispatchIds.has(msg.dispatchId) || !!this.sessions.get(msg.dispatchId), msg.verification) : { state: "unavailable", at: (/* @__PURE__ */ new Date()).toISOString(), detail: "\u8282\u70B9\u672A\u914D\u7F6E\u6301\u4E45\u4F1A\u8BDD\u76EE\u5F55\uFF0C\u8BF7\u5347\u7EA7\u8282\u70B9" };
|
|
267821
|
-
if (result.state === "running") {
|
|
267822
|
-
if (this.pendingDispatchIds.has(msg.dispatchId)) this.cancelledPendingDispatchIds.add(msg.dispatchId);
|
|
267823
|
-
await this.sessions.kill(msg.dispatchId);
|
|
267824
|
-
}
|
|
267825
|
-
} catch (e) {
|
|
267826
|
-
result = { state: "unavailable", at: (/* @__PURE__ */ new Date()).toISOString(), detail: `\u8282\u70B9\u6838\u9A8C\u5931\u8D25\uFF1A${String(e)}` };
|
|
267827
|
-
}
|
|
267828
|
-
this.send({ type: "execution_stop_result", requestId: msg.requestId, dispatchId: msg.dispatchId, result });
|
|
267829
|
-
break;
|
|
267830
|
-
}
|
|
267831
268062
|
case "kill": {
|
|
267832
268063
|
log2("[node-cli]", `\u2190 kill dispatch=${msg.dispatchId}`);
|
|
267833
|
-
try {
|
|
267834
|
-
this.recovery?.fence(msg.dispatchId);
|
|
267835
|
-
} catch (error2) {
|
|
267836
|
-
log2("[node-cli]", `\u5C01\u7981\u5199\u76D8\u5931\u8D25 ${msg.dispatchId}\uFF0C\u4ECD\u8BF7\u6C42\u505C\u6B62\uFF1A${String(error2)}`);
|
|
267837
|
-
}
|
|
267838
268064
|
const killed = await this.sessions.kill(msg.dispatchId);
|
|
267839
268065
|
if (!killed && this.pendingDispatchIds.has(msg.dispatchId)) {
|
|
267840
268066
|
this.cancelledPendingDispatchIds.add(msg.dispatchId);
|
|
@@ -268060,7 +268286,6 @@ var DaemonWsClient = class {
|
|
|
268060
268286
|
// probe honest. See DaemonMeta.runtimeCapabilities for the split rationale.
|
|
268061
268287
|
runtimeCapabilities: this.runtimes,
|
|
268062
268288
|
nodeVersion: process.version,
|
|
268063
|
-
...this.recovery ? { supportsExecutionStopRecovery: true } : {},
|
|
268064
268289
|
...this.daemonVersion ? { daemonVersion: this.daemonVersion } : {},
|
|
268065
268290
|
...this.daemonPkg ? { daemonPkg: this.daemonPkg } : {},
|
|
268066
268291
|
connectorReadiness: inspectConnectorRuntimeReadiness(),
|
|
@@ -268071,6 +268296,7 @@ var DaemonWsClient = class {
|
|
|
268071
268296
|
// **恒 true**——归一层在 `_core` 里、与具体 adapter 无关,装了这版 daemon 就一定发。
|
|
268072
268297
|
// 服务端据此决定是用节点归一还是自己就地归一;判据取能力位而不是「见过帧没有」,
|
|
268073
268298
|
// 否则首个 chunk 之前那段窗口两边都不归一,正文会静默丢一截。
|
|
268299
|
+
supportsTaskReplacement: true,
|
|
268074
268300
|
supportsNormalizedEvents: true,
|
|
268075
268301
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
268076
268302
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
@@ -268219,7 +268445,6 @@ async function startNode(opts) {
|
|
|
268219
268445
|
...opts.daemonPkg ? { daemonPkg: opts.daemonPkg } : {},
|
|
268220
268446
|
// chat 文件浏览 handler 用它定位会话目录;production 不传 = 与 adapter 同款默认根(~/.oasis/work)。
|
|
268221
268447
|
...opts.workRoot !== void 0 ? { workRoot: opts.workRoot } : {},
|
|
268222
|
-
...opts.sessionsRoot ? { sessionsRoot: opts.sessionsRoot } : {},
|
|
268223
268448
|
...opts.spawnSessionProcess ? { spawnSessionProcess: opts.spawnSessionProcess } : {},
|
|
268224
268449
|
...opts.countDetachedSessions ? { countDetachedSessions: opts.countDetachedSessions } : {}
|
|
268225
268450
|
});
|
|
@@ -268270,7 +268495,7 @@ async function startNode(opts) {
|
|
|
268270
268495
|
}
|
|
268271
268496
|
|
|
268272
268497
|
// ../cli/src/exec.ts
|
|
268273
|
-
var
|
|
268498
|
+
var os13 = __toESM(require("node:os"), 1);
|
|
268274
268499
|
var UnsafeExecArgvError = class extends Error {
|
|
268275
268500
|
code = "ERR_UNSAFE_EXEC_ARGV";
|
|
268276
268501
|
constructor(message) {
|
|
@@ -268307,7 +268532,7 @@ function planExec(opts) {
|
|
|
268307
268532
|
function computeExitCode(code2, signal) {
|
|
268308
268533
|
if (code2 !== null) return code2;
|
|
268309
268534
|
if (signal) {
|
|
268310
|
-
const num3 =
|
|
268535
|
+
const num3 = os13.constants.signals[signal];
|
|
268311
268536
|
return 128 + (typeof num3 === "number" ? num3 : 1);
|
|
268312
268537
|
}
|
|
268313
268538
|
return 1;
|
|
@@ -268410,7 +268635,7 @@ init_src5();
|
|
|
268410
268635
|
init_src6();
|
|
268411
268636
|
|
|
268412
268637
|
// ../cli/src/workorder-attachments.ts
|
|
268413
|
-
var
|
|
268638
|
+
var fs41 = __toESM(require("node:fs"), 1);
|
|
268414
268639
|
var path36 = __toESM(require("node:path"), 1);
|
|
268415
268640
|
init_src();
|
|
268416
268641
|
var MIME_BY_EXTENSION = {
|
|
@@ -268459,7 +268684,7 @@ function parseLocalWorkorderAttachments(argv) {
|
|
|
268459
268684
|
return out;
|
|
268460
268685
|
}
|
|
268461
268686
|
function readLocalWorkorderAttachment(input) {
|
|
268462
|
-
const stat3 =
|
|
268687
|
+
const stat3 = fs41.statSync(input.path);
|
|
268463
268688
|
if (!stat3.isFile()) throw new Error(`\u9644\u4EF6\u4E0D\u662F\u6587\u4EF6\uFF1A${input.path}`);
|
|
268464
268689
|
if (stat3.size > WORKORDER_ATTACHMENT_MAX_BYTES) {
|
|
268465
268690
|
throw new Error(`\u9644\u4EF6\u300C${path36.basename(input.path)}\u300D\u8D85\u8FC7 10MB`);
|
|
@@ -268467,7 +268692,7 @@ function readLocalWorkorderAttachment(input) {
|
|
|
268467
268692
|
return {
|
|
268468
268693
|
name: path36.basename(input.path),
|
|
268469
268694
|
contentType: input.contentType ?? inferAttachmentContentType(input.path),
|
|
268470
|
-
contentBase64:
|
|
268695
|
+
contentBase64: fs41.readFileSync(input.path).toString("base64")
|
|
268471
268696
|
};
|
|
268472
268697
|
}
|
|
268473
268698
|
|
|
@@ -270569,7 +270794,7 @@ function fieldsFromFlags(flags, ownFlags) {
|
|
|
270569
270794
|
}
|
|
270570
270795
|
return Object.keys(fields).length > 0 ? fields : void 0;
|
|
270571
270796
|
}
|
|
270572
|
-
function buildStageOp(cmd, flags, positional, readFile9 = (file) =>
|
|
270797
|
+
function buildStageOp(cmd, flags, positional, readFile9 = (file) => fs42.readFileSync(file, "utf8")) {
|
|
270573
270798
|
switch (cmd) {
|
|
270574
270799
|
case "link":
|
|
270575
270800
|
return {
|
|
@@ -270703,43 +270928,43 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270703
270928
|
const nodeTokenFile = path37.join(dir, "node-token");
|
|
270704
270929
|
const enrollTokenFile = path37.join(dir, "enroll-token");
|
|
270705
270930
|
const reportMarkerFile = path37.join(dir, "report-runtimes");
|
|
270706
|
-
const persistedNodeId =
|
|
270931
|
+
const persistedNodeId = fs42.existsSync(nodeIdFile) ? fs42.readFileSync(nodeIdFile, "utf8").trim() : null;
|
|
270707
270932
|
let nodeId = persistedNodeId || resolveNodeId();
|
|
270708
270933
|
const explicitToken = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"];
|
|
270709
|
-
let token2 = explicitToken ?? (
|
|
270710
|
-
const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (
|
|
270934
|
+
let token2 = explicitToken ?? (fs42.existsSync(nodeTokenFile) ? fs42.readFileSync(nodeTokenFile, "utf8").trim() : void 0);
|
|
270935
|
+
const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (fs42.existsSync(enrollTokenFile) ? fs42.readFileSync(enrollTokenFile, "utf8").trim() : void 0);
|
|
270711
270936
|
let freshEnrollment = false;
|
|
270712
270937
|
if (enrollToken && !explicitToken) {
|
|
270713
270938
|
const httpBase2 = serverUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
|
|
270714
270939
|
const res = await fetch(`${httpBase2}/api/nodes/exchange`, {
|
|
270715
270940
|
method: "POST",
|
|
270716
270941
|
headers: { "content-type": "application/json" },
|
|
270717
|
-
body: JSON.stringify({ enrollToken, nodeId, hostname:
|
|
270942
|
+
body: JSON.stringify({ enrollToken, nodeId, hostname: os14.hostname(), serverUrl, ...companyId ? { companyId } : {} })
|
|
270718
270943
|
});
|
|
270719
270944
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
270720
270945
|
const body2 = await res.json();
|
|
270721
270946
|
nodeId = body2.nodeId;
|
|
270722
270947
|
token2 = body2.token;
|
|
270723
|
-
|
|
270724
|
-
|
|
270725
|
-
|
|
270948
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
270949
|
+
fs42.writeFileSync(nodeIdFile, nodeId);
|
|
270950
|
+
fs42.writeFileSync(nodeTokenFile, token2, { mode: 384 });
|
|
270726
270951
|
try {
|
|
270727
|
-
|
|
270952
|
+
fs42.unlinkSync(enrollTokenFile);
|
|
270728
270953
|
} catch {
|
|
270729
270954
|
}
|
|
270730
270955
|
freshEnrollment = true;
|
|
270731
270956
|
}
|
|
270732
270957
|
if (!nodeId) throw new Error("no nodeId \u2014 provide --enroll-token <ent_...> on first run");
|
|
270733
|
-
const scriptRun = freshEnrollment ||
|
|
270958
|
+
const scriptRun = freshEnrollment || fs42.existsSync(reportMarkerFile);
|
|
270734
270959
|
if (flags.has("service")) {
|
|
270735
270960
|
const { spawnSync: spawnSync5, execSync: execSync2 } = await import("node:child_process");
|
|
270736
270961
|
if (token2) {
|
|
270737
|
-
|
|
270738
|
-
|
|
270962
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
270963
|
+
fs42.writeFileSync(nodeTokenFile, token2, { mode: 384 });
|
|
270739
270964
|
}
|
|
270740
270965
|
if (scriptRun) {
|
|
270741
|
-
|
|
270742
|
-
|
|
270966
|
+
fs42.mkdirSync(dir, { recursive: true });
|
|
270967
|
+
fs42.writeFileSync(reportMarkerFile, "");
|
|
270743
270968
|
}
|
|
270744
270969
|
println("\u2192 Installing oasis_test globally...");
|
|
270745
270970
|
spawnSync5("npm", ["install", "-g", "oasis_test@latest"], { stdio: "inherit" });
|
|
@@ -270747,11 +270972,11 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270747
270972
|
const binPath = path37.join(prefix, "bin", "oasis_test");
|
|
270748
270973
|
const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
|
|
270749
270974
|
if (process.platform === "linux") {
|
|
270750
|
-
const svcFile = path37.join(
|
|
270751
|
-
|
|
270975
|
+
const svcFile = path37.join(os14.homedir(), ".config/systemd/user/oasis-node.service");
|
|
270976
|
+
fs42.mkdirSync(path37.dirname(svcFile), { recursive: true });
|
|
270752
270977
|
if (spawnSync5("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
|
|
270753
270978
|
spawnSync5("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
|
|
270754
|
-
|
|
270979
|
+
fs42.writeFileSync(svcFile, [
|
|
270755
270980
|
"[Unit]",
|
|
270756
270981
|
"Description=Oasis Node Daemon",
|
|
270757
270982
|
"After=network.target",
|
|
@@ -270760,7 +270985,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270760
270985
|
`ExecStart=${binPath} ${svcArgs}`,
|
|
270761
270986
|
// Carry the install-time PATH so the detached daemon detects CLIs in user dirs
|
|
270762
270987
|
// (~/.npm-global/bin, ~/.local/bin) — systemd --user otherwise gives a minimal PATH.
|
|
270763
|
-
`Environment=PATH=${process.env["PATH"] ?? ""}:${path37.join(
|
|
270988
|
+
`Environment=PATH=${process.env["PATH"] ?? ""}:${path37.join(os14.homedir(), ".npm-global/bin")}:${path37.join(os14.homedir(), ".local/bin")}:/usr/local/bin`,
|
|
270764
270989
|
"Restart=on-failure",
|
|
270765
270990
|
"RestartSec=5",
|
|
270766
270991
|
"StandardOutput=journal",
|
|
@@ -270772,31 +270997,31 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270772
270997
|
].join("\n"));
|
|
270773
270998
|
spawnSync5("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
270774
270999
|
spawnSync5("systemctl", ["--user", "enable", "--now", "oasis-node"], { stdio: "inherit" });
|
|
270775
|
-
spawnSync5("loginctl", ["enable-linger",
|
|
271000
|
+
spawnSync5("loginctl", ["enable-linger", os14.userInfo().username], { stdio: "ignore" });
|
|
270776
271001
|
println("\u2713 Oasis node service started (systemd --user oasis-node)");
|
|
270777
271002
|
println(" Status : systemctl --user status oasis-node");
|
|
270778
271003
|
println(" Logs : journalctl --user -u oasis-node -f");
|
|
270779
271004
|
println(" Stop : systemctl --user stop oasis-node");
|
|
270780
271005
|
} else if (process.platform === "darwin") {
|
|
270781
|
-
const plist = path37.join(
|
|
270782
|
-
|
|
271006
|
+
const plist = path37.join(os14.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
|
|
271007
|
+
fs42.mkdirSync(path37.dirname(plist), { recursive: true });
|
|
270783
271008
|
spawnSync5("launchctl", ["unload", plist], { stdio: "ignore" });
|
|
270784
271009
|
const argXml = [binPath, "node", "--server-ws", serverUrl, "--dir", dir, ...nodeName ? ["--name", nodeName] : []].map((a) => `<string>${a}</string>`).join("");
|
|
270785
|
-
|
|
271010
|
+
fs42.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.oasis.node</string><key>ProgramArguments</key><array>${argXml}</array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${os14.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os14.homedir()}/.oasis-node.err</string></dict></plist>`);
|
|
270786
271011
|
spawnSync5("launchctl", ["load", plist], { stdio: "inherit" });
|
|
270787
271012
|
println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
|
|
270788
|
-
println(` Logs : tail -f ${
|
|
271013
|
+
println(` Logs : tail -f ${os14.homedir()}/.oasis-node.log`);
|
|
270789
271014
|
println(` Stop : launchctl unload ${plist}`);
|
|
270790
271015
|
} else {
|
|
270791
|
-
spawnSync5("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path37.join(
|
|
271016
|
+
spawnSync5("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path37.join(os14.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
|
|
270792
271017
|
println(`\u2713 Oasis node started in background (nohup). Logs: ~/.oasis-node.log`);
|
|
270793
271018
|
println(" Note: no automatic restart on reboot in this environment.");
|
|
270794
271019
|
}
|
|
270795
271020
|
return;
|
|
270796
271021
|
}
|
|
270797
|
-
if (
|
|
271022
|
+
if (fs42.existsSync(reportMarkerFile)) {
|
|
270798
271023
|
try {
|
|
270799
|
-
|
|
271024
|
+
fs42.unlinkSync(reportMarkerFile);
|
|
270800
271025
|
} catch {
|
|
270801
271026
|
}
|
|
270802
271027
|
}
|
|
@@ -270877,7 +271102,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270877
271102
|
const outFile = flags.get("out");
|
|
270878
271103
|
const lines = samples.map((sample) => JSON.stringify(sample)).join("\n");
|
|
270879
271104
|
if (outFile !== void 0) {
|
|
270880
|
-
|
|
271105
|
+
fs42.writeFileSync(outFile, lines + (lines ? "\n" : ""));
|
|
270881
271106
|
println(`\u5DF2\u5BFC\u51FA ${samples.length} \u6761\u8F68\u8FF9\u6837\u672C \u2192 ${outFile}\uFF08approved/rejected \u6210\u5BF9\u5373\u504F\u597D\u5BF9\uFF09`);
|
|
270882
271107
|
} else {
|
|
270883
271108
|
println(lines);
|
|
@@ -270887,8 +271112,8 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270887
271112
|
if (command === "serve" && positional[0] === "install") {
|
|
270888
271113
|
const absDir = path37.resolve(dir);
|
|
270889
271114
|
const name = `oasis-serve-${path37.basename(absDir)}`;
|
|
270890
|
-
const unitDir = flags.get("unit-dir") ?? path37.join(
|
|
270891
|
-
const bin = flags.get("bin") ?? path37.join(
|
|
271115
|
+
const unitDir = flags.get("unit-dir") ?? path37.join(os14.homedir(), ".config", "systemd", "user");
|
|
271116
|
+
const bin = flags.get("bin") ?? path37.join(os14.homedir(), ".local", "bin", "oasis");
|
|
270892
271117
|
const port = flags.get("port") ?? "7320";
|
|
270893
271118
|
const extra = (flags.get("dispatch") === "true" ? ` --dispatch true` : "") + (flags.has("model") ? ` --model ${flags.get("model")}` : "");
|
|
270894
271119
|
const unit = [
|
|
@@ -270905,9 +271130,9 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270905
271130
|
`WantedBy=default.target`,
|
|
270906
271131
|
``
|
|
270907
271132
|
].join("\n");
|
|
270908
|
-
|
|
271133
|
+
fs42.mkdirSync(unitDir, { recursive: true });
|
|
270909
271134
|
const unitPath = path37.join(unitDir, `${name}.service`);
|
|
270910
|
-
|
|
271135
|
+
fs42.writeFileSync(unitPath, unit);
|
|
270911
271136
|
println(`\u5DF2\u5199\u5165 ${unitPath}`);
|
|
270912
271137
|
println(`\u542F\u7528\uFF1Asystemctl --user daemon-reload && systemctl --user enable --now ${name}`);
|
|
270913
271138
|
println(`\u5F00\u673A\u81EA\u542F\uFF08\u542B\u672A\u767B\u5F55\uFF09\uFF1Aloginctl enable-linger $USER`);
|
|
@@ -270953,7 +271178,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270953
271178
|
}
|
|
270954
271179
|
const base = flags.get("server") ?? process.env["OASIS_SERVER"] ?? "http://127.0.0.1:7320";
|
|
270955
271180
|
const tokenFile = path37.join(dir, "operator-token");
|
|
270956
|
-
const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (
|
|
271181
|
+
const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (fs42.existsSync(tokenFile) ? fs42.readFileSync(tokenFile, "utf8").trim() : void 0);
|
|
270957
271182
|
if (!token) {
|
|
270958
271183
|
throw new Error(`\u65E0 token\uFF1A\u5148 oasis serve\uFF08\u4F1A\u751F\u6210 ${tokenFile}\uFF09\uFF0C\u6216\u663E\u5F0F --token / $OASIS_TOKEN`);
|
|
270959
271184
|
}
|
|
@@ -270964,7 +271189,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270964
271189
|
println(JSON.stringify({ mode: flags.get("execute") === "true" ? "execute" : "dry-run", count: rows.length, records: rows }, null, 2));
|
|
270965
271190
|
return;
|
|
270966
271191
|
}
|
|
270967
|
-
const readFileArg = (file) =>
|
|
271192
|
+
const readFileArg = (file) => fs42.readFileSync(file, "utf8");
|
|
270968
271193
|
const parseJsonFlag = (value2, name) => {
|
|
270969
271194
|
const parsed = JSON.parse(value2);
|
|
270970
271195
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -270980,11 +271205,11 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
270980
271205
|
const readDirFiles = (root) => {
|
|
270981
271206
|
const out = [];
|
|
270982
271207
|
const walk = (abs, rel) => {
|
|
270983
|
-
for (const name of
|
|
271208
|
+
for (const name of fs42.readdirSync(abs)) {
|
|
270984
271209
|
const childAbs = path37.join(abs, name);
|
|
270985
271210
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
270986
|
-
if (
|
|
270987
|
-
else out.push({ path: childRel, contentBase64:
|
|
271211
|
+
if (fs42.statSync(childAbs).isDirectory()) walk(childAbs, childRel);
|
|
271212
|
+
else out.push({ path: childRel, contentBase64: fs42.readFileSync(childAbs).toString("base64") });
|
|
270988
271213
|
}
|
|
270989
271214
|
};
|
|
270990
271215
|
walk(root, "");
|
|
@@ -271041,7 +271266,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
271041
271266
|
if (items.length > ATTACHMENT_MAX_COUNT) throw new Error(`\u9644\u4EF6\u6700\u591A ${ATTACHMENT_MAX_COUNT} \u4E2A`);
|
|
271042
271267
|
const uploaded = [];
|
|
271043
271268
|
for (const item of items) {
|
|
271044
|
-
const st =
|
|
271269
|
+
const st = fs42.statSync(item.file);
|
|
271045
271270
|
if (!st.isFile()) throw new Error(`\u9644\u4EF6\u4E0D\u662F\u6587\u4EF6\uFF1A${item.file}`);
|
|
271046
271271
|
if (st.size > ATTACHMENT_MAX_BYTES) throw new Error(`\u9644\u4EF6\u8D85\u8FC7 10MB\uFF1A${item.file}`);
|
|
271047
271272
|
const contentType = item.contentType ?? mimeOf(item.file);
|
|
@@ -271049,7 +271274,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
271049
271274
|
const res = await api.post("/api/chat/attachments", {
|
|
271050
271275
|
name,
|
|
271051
271276
|
contentType,
|
|
271052
|
-
contentBase64:
|
|
271277
|
+
contentBase64: fs42.readFileSync(item.file).toString("base64")
|
|
271053
271278
|
});
|
|
271054
271279
|
if (!res.blobRef) throw new Error(`\u9644\u4EF6\u4E0A\u4F20\u672A\u8FD4\u56DE blobRef\uFF1A${item.file}`);
|
|
271055
271280
|
uploaded.push({ name, contentType, url: blobUrlOf(res.blobRef) });
|
|
@@ -271300,16 +271525,16 @@ Trace: ${run.traceRunId}`);
|
|
|
271300
271525
|
const url = flags.get("url");
|
|
271301
271526
|
if (Boolean(file) === Boolean(url)) throw new Error("oasis kb ingest \u5FC5\u987B\u4E14\u53EA\u80FD\u4F20 --file \u6216 --url");
|
|
271302
271527
|
if (file) {
|
|
271303
|
-
if (!
|
|
271528
|
+
if (!fs42.existsSync(file) || !fs42.statSync(file).isFile()) throw new Error(`\u5165\u5E93\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${file}`);
|
|
271304
271529
|
const extension3 = path37.extname(file).toLowerCase();
|
|
271305
271530
|
if (![".md", ".txt", ".pdf"].includes(extension3)) throw new Error("V1 \u53EA\u652F\u6301 Markdown\u3001TXT \u548C PDF \u6587\u4EF6");
|
|
271306
|
-
if (
|
|
271531
|
+
if (fs42.statSync(file).size > ATTACHMENT_MAX_BYTES) throw new Error(`\u5165\u5E93\u6587\u4EF6\u8D85\u8FC7 10MB\uFF1A${file}`);
|
|
271307
271532
|
const name = path37.basename(file);
|
|
271308
271533
|
const contentType = mimeOf(file);
|
|
271309
271534
|
const uploaded = await api.post("/api/chat/attachments", {
|
|
271310
271535
|
name,
|
|
271311
271536
|
contentType,
|
|
271312
|
-
contentBase64:
|
|
271537
|
+
contentBase64: fs42.readFileSync(file).toString("base64")
|
|
271313
271538
|
});
|
|
271314
271539
|
if (!uploaded.blobRef) throw new Error("\u9644\u4EF6\u4E0A\u4F20\u672A\u8FD4\u56DE blobRef");
|
|
271315
271540
|
request2 = { action: "ingest", attachmentRef: uploaded.blobRef, attachmentName: name, attachmentContentType: contentType };
|
|
@@ -271363,7 +271588,7 @@ Trace: ${run.traceRunId}`);
|
|
|
271363
271588
|
const cleanup = async () => {
|
|
271364
271589
|
if (tmpDir) {
|
|
271365
271590
|
try {
|
|
271366
|
-
await
|
|
271591
|
+
await fs42.promises.rm(tmpDir, { recursive: true, force: true });
|
|
271367
271592
|
} catch {
|
|
271368
271593
|
}
|
|
271369
271594
|
}
|
|
@@ -271371,9 +271596,9 @@ Trace: ${run.traceRunId}`);
|
|
|
271371
271596
|
if (plan.inject.mode === "env") {
|
|
271372
271597
|
childEnv[plan.inject.envName] = value2;
|
|
271373
271598
|
} else {
|
|
271374
|
-
tmpDir = await
|
|
271599
|
+
tmpDir = await fs42.promises.mkdtemp(path37.join(os14.tmpdir(), "oasis-var-exec-"));
|
|
271375
271600
|
const keyfile = path37.join(tmpDir, "value");
|
|
271376
|
-
await
|
|
271601
|
+
await fs42.promises.writeFile(keyfile, value2, { mode: 384 });
|
|
271377
271602
|
childEnv[plan.inject.fileEnv] = keyfile;
|
|
271378
271603
|
}
|
|
271379
271604
|
const { spawn: spawn5 } = await import("node:child_process");
|
|
@@ -271689,7 +271914,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
271689
271914
|
break;
|
|
271690
271915
|
}
|
|
271691
271916
|
case "create-workorder": {
|
|
271692
|
-
const planRaw = flags.get("plan-file") !== void 0 ?
|
|
271917
|
+
const planRaw = flags.get("plan-file") !== void 0 ? fs42.readFileSync(flags.get("plan-file"), "utf8") : flags.get("plan");
|
|
271693
271918
|
const acceptanceFlag = flags.get("acceptance");
|
|
271694
271919
|
const type = need(flags, "type");
|
|
271695
271920
|
const title = need(flags, "title");
|
|
@@ -271908,7 +272133,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
271908
272133
|
if (verb === "add") {
|
|
271909
272134
|
const file = flags.get("file");
|
|
271910
272135
|
if (file !== void 0) {
|
|
271911
|
-
const bytes2 =
|
|
272136
|
+
const bytes2 = fs42.readFileSync(file);
|
|
271912
272137
|
const res = await api.request("POST", `/api/projects/${encodeURIComponent(projectId2)}/files`, {
|
|
271913
272138
|
name: flags.get("name") ?? path37.basename(file),
|
|
271914
272139
|
...flags.has("path") ? { path: flags.get("path") } : {},
|
|
@@ -272082,14 +272307,14 @@ ${res.warning}`);
|
|
|
272082
272307
|
const LEGACY_DESIGN_SYSTEM_PROMPT = "\u4F60\u662F\u8BBE\u8BA1\u5F15\u64CE\u4E2D\u7684\u754C\u9762\u8BBE\u8BA1\u5E08\u3002\u4EFB\u52A1\u4E66\u89C1\u672C\u6761\u6D88\u606F\uFF1B\u4E0A\u6E38\u8F93\u5165\u7B49\u4E0A\u4E0B\u6587\u6587\u4EF6\u5728\u9879\u76EE task-context/ \u76EE\u5F55\u3002\u6309\u4EFB\u52A1\u4E66\u7684\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u534F\u8BAE\u5DE5\u4F5C\uFF1A\u4EA7\u51FA\u81EA\u5305\u542B HTML \u5165\u53E3\u7A3F\u4E0E acceptance.md\uFF0C\u5B8C\u6210\u5373\u7ED3\u675F\u56DE\u590D\uFF0C\u4EA4\u7A3F\u7531\u7CFB\u7EDF\u4EE3\u529E\u3002";
|
|
272083
272308
|
if (sub === "chat") {
|
|
272084
272309
|
const artifactId2 = needPos(positional, 1, "oasis design chat <artifactId> --message <t>");
|
|
272085
|
-
const message2 = flags.get("message") ?? (["DESIGN_BRIEF.md", "TASK.md"].map((f2) =>
|
|
272310
|
+
const message2 = flags.get("message") ?? (["DESIGN_BRIEF.md", "TASK.md"].map((f2) => fs42.existsSync(f2) ? fs42.readFileSync(f2, "utf8") : "").find((s2) => s2.trim()) ?? "");
|
|
272086
272311
|
if (!message2.trim()) throw new Error("\u65E0\u5BF9\u8BDD\u5185\u5BB9\uFF1A\u7ED9 --message <text>\uFF0C\u6216\u5728\u5F53\u524D\u76EE\u5F55\u653E DESIGN_BRIEF.md / TASK.md");
|
|
272087
272312
|
const odBase2 = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
272088
272313
|
const isContinue = flags.get("turn") === "continue";
|
|
272089
272314
|
const contextFiles2 = {};
|
|
272090
272315
|
if (!isContinue) {
|
|
272091
272316
|
contextFiles2["DESIGN_BRIEF.md"] = message2;
|
|
272092
|
-
if (
|
|
272317
|
+
if (fs42.existsSync("inputs") && fs42.statSync("inputs").isDirectory()) {
|
|
272093
272318
|
for (const f2 of readDirFiles("inputs")) {
|
|
272094
272319
|
contextFiles2[`inputs/${f2.path}`] = Buffer.from(f2.contentBase64, "base64").toString("utf8");
|
|
272095
272320
|
}
|
|
@@ -272145,7 +272370,7 @@ ${res.warning}`);
|
|
|
272145
272370
|
for (const a of st.artifacts) println(` - ${a.path}\uFF08${a.kind ?? "?"}\uFF09status=${a.status ?? "?"}${a.mtime ? ` \xB7 ${new Date(a.mtime).toISOString()}` : ""}`);
|
|
272146
272371
|
if (flags.get("pull") === "true") {
|
|
272147
272372
|
const odPublic2 = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
272148
|
-
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2,
|
|
272373
|
+
const { dir: dir3, entry: entry2 } = await harvestBoard(odBase2, fetch, odPublic2, os14.tmpdir(), st.boardKey, st.runs[0]?.runId ?? "status-pull");
|
|
272149
272374
|
println(`[design] \u5DF2\u62C9\u5230\u672C\u5730\uFF1A${dir3}\uFF08\u5165\u53E3 ${entry2}\uFF09`);
|
|
272150
272375
|
println(`[design] \u8BFB\u5B8C\u6EE1\u610F\u5373\u4EA4\u7A3F\uFF1Aoasis propose ${artifactId2} --from-dir ${dir3} --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"`);
|
|
272151
272376
|
} else {
|
|
@@ -272157,11 +272382,11 @@ ${res.warning}`);
|
|
|
272157
272382
|
const artifactId = needPos(positional, 1, "oasis design run <artifactId>");
|
|
272158
272383
|
const odBase = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
272159
272384
|
const odPublic = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
272160
|
-
const briefFile = ["DESIGN_BRIEF.md", "TASK.md"].find((f2) =>
|
|
272161
|
-
const brief = flags.get("brief") ?? (briefFile ?
|
|
272385
|
+
const briefFile = ["DESIGN_BRIEF.md", "TASK.md"].find((f2) => fs42.existsSync(f2));
|
|
272386
|
+
const brief = flags.get("brief") ?? (briefFile ? fs42.readFileSync(briefFile, "utf8") : "");
|
|
272162
272387
|
if (!brief.trim()) throw new Error("\u65E0\u8BBE\u8BA1\u4EFB\u52A1\uFF1A\u7ED9 --brief <text>\uFF0C\u6216\u5728\u5F53\u524D\u76EE\u5F55\u653E DESIGN_BRIEF.md / TASK.md");
|
|
272163
272388
|
const contextFiles = { "DESIGN_BRIEF.md": brief };
|
|
272164
|
-
if (
|
|
272389
|
+
if (fs42.existsSync("inputs") && fs42.statSync("inputs").isDirectory()) {
|
|
272165
272390
|
for (const f2 of readDirFiles("inputs")) {
|
|
272166
272391
|
contextFiles[`inputs/${f2.path}`] = Buffer.from(f2.contentBase64, "base64").toString("utf8");
|
|
272167
272392
|
}
|
|
@@ -272675,22 +272900,22 @@ ${res.warning}`);
|
|
|
272675
272900
|
}
|
|
272676
272901
|
if (sub === "push") {
|
|
272677
272902
|
const dir2 = needPos(positional, 1, "oasis skill push <\u76EE\u5F55> [--scope self|all|actors]");
|
|
272678
|
-
if (!
|
|
272903
|
+
if (!fs42.existsSync(dir2) || !fs42.statSync(dir2).isDirectory()) throw new Error(`\u6280\u80FD\u76EE\u5F55\u4E0D\u5B58\u5728\uFF1A${dir2}`);
|
|
272679
272904
|
const SKIP2 = /* @__PURE__ */ new Set([".git", "node_modules", ".DS_Store"]);
|
|
272680
272905
|
const MAX_FILE_BYTES5 = 1 << 20;
|
|
272681
272906
|
const MAX_FILE_COUNT2 = 128;
|
|
272682
272907
|
const local = {};
|
|
272683
272908
|
const binary = [];
|
|
272684
272909
|
const walk = (abs, rel) => {
|
|
272685
|
-
for (const name2 of
|
|
272910
|
+
for (const name2 of fs42.readdirSync(abs).sort()) {
|
|
272686
272911
|
if (SKIP2.has(name2)) continue;
|
|
272687
272912
|
const childAbs = path37.join(abs, name2);
|
|
272688
272913
|
const childRel = rel ? `${rel}/${name2}` : name2;
|
|
272689
|
-
if (
|
|
272914
|
+
if (fs42.statSync(childAbs).isDirectory()) {
|
|
272690
272915
|
walk(childAbs, childRel);
|
|
272691
272916
|
continue;
|
|
272692
272917
|
}
|
|
272693
|
-
const buf =
|
|
272918
|
+
const buf = fs42.readFileSync(childAbs);
|
|
272694
272919
|
if (buf.length > MAX_FILE_BYTES5) throw new Error(`\u6280\u80FD\u6587\u4EF6\u8D85\u8FC7 1MiB\uFF1A${childRel}\uFF08${buf.length} \u5B57\u8282\uFF09`);
|
|
272695
272920
|
if (buf.includes(0)) {
|
|
272696
272921
|
binary.push(childRel);
|
|
@@ -273639,14 +273864,14 @@ ${res.warning}`);
|
|
|
273639
273864
|
init_src8();
|
|
273640
273865
|
|
|
273641
273866
|
// src/session-sweep.ts
|
|
273642
|
-
var
|
|
273867
|
+
var fs43 = __toESM(require("node:fs"));
|
|
273643
273868
|
var path38 = __toESM(require("node:path"));
|
|
273644
273869
|
function liveSessionPinnedLabels(sessionRoots2, deps) {
|
|
273645
273870
|
const labels = /* @__PURE__ */ new Set();
|
|
273646
273871
|
for (const root of sessionRoots2) {
|
|
273647
273872
|
let dirs;
|
|
273648
273873
|
try {
|
|
273649
|
-
dirs =
|
|
273874
|
+
dirs = fs43.readdirSync(root);
|
|
273650
273875
|
} catch {
|
|
273651
273876
|
continue;
|
|
273652
273877
|
}
|
|
@@ -273655,7 +273880,7 @@ function liveSessionPinnedLabels(sessionRoots2, deps) {
|
|
|
273655
273880
|
const live = deps.flockAvailable ? deps.isLocked(path38.join(sessionDir, "lock")) : true;
|
|
273656
273881
|
if (!live) continue;
|
|
273657
273882
|
try {
|
|
273658
|
-
const label =
|
|
273883
|
+
const label = fs43.readFileSync(path38.join(sessionDir, "pinned-version"), "utf8").trim();
|
|
273659
273884
|
if (label) labels.add(label);
|
|
273660
273885
|
} catch {
|
|
273661
273886
|
}
|
|
@@ -273671,7 +273896,7 @@ function sweepOrphanSessions(sessionRoots2, deps) {
|
|
|
273671
273896
|
for (const root of sessionRoots2) {
|
|
273672
273897
|
let dirs;
|
|
273673
273898
|
try {
|
|
273674
|
-
dirs =
|
|
273899
|
+
dirs = fs43.readdirSync(root);
|
|
273675
273900
|
} catch {
|
|
273676
273901
|
continue;
|
|
273677
273902
|
}
|
|
@@ -273679,12 +273904,12 @@ function sweepOrphanSessions(sessionRoots2, deps) {
|
|
|
273679
273904
|
const sessionDir = path38.join(root, d);
|
|
273680
273905
|
if (deps.isLocked(path38.join(sessionDir, "lock"))) continue;
|
|
273681
273906
|
try {
|
|
273682
|
-
if (now() -
|
|
273907
|
+
if (now() - fs43.statSync(sessionDir).mtimeMs < minAgeMs) continue;
|
|
273683
273908
|
} catch {
|
|
273684
273909
|
continue;
|
|
273685
273910
|
}
|
|
273686
273911
|
try {
|
|
273687
|
-
|
|
273912
|
+
fs43.rmSync(sessionDir, { recursive: true, force: true });
|
|
273688
273913
|
removed.push(sessionDir);
|
|
273689
273914
|
} catch {
|
|
273690
273915
|
}
|
|
@@ -273698,7 +273923,7 @@ function countLiveSessions(sessionRoots2, deps) {
|
|
|
273698
273923
|
for (const root of sessionRoots2) {
|
|
273699
273924
|
let dirs;
|
|
273700
273925
|
try {
|
|
273701
|
-
dirs =
|
|
273926
|
+
dirs = fs43.readdirSync(root);
|
|
273702
273927
|
} catch {
|
|
273703
273928
|
continue;
|
|
273704
273929
|
}
|
|
@@ -273711,7 +273936,7 @@ function countLiveSessions(sessionRoots2, deps) {
|
|
|
273711
273936
|
init_src8();
|
|
273712
273937
|
|
|
273713
273938
|
// src/runtime-assets.ts
|
|
273714
|
-
var
|
|
273939
|
+
var fs44 = __toESM(require("node:fs"));
|
|
273715
273940
|
var path39 = __toESM(require("node:path"));
|
|
273716
273941
|
var ASSET_EXTS = [".sh", ".mjs"];
|
|
273717
273942
|
var SESSION_SCOPED_PREFIXES = ["oasis-conn-", "oasis-wrappers-", "oasis-cli-"];
|
|
@@ -273727,7 +273952,7 @@ function installRuntimeAssets(srcRoot, binDir) {
|
|
|
273727
273952
|
let copied = 0;
|
|
273728
273953
|
let entries;
|
|
273729
273954
|
try {
|
|
273730
|
-
entries =
|
|
273955
|
+
entries = fs44.readdirSync(srcRoot, { withFileTypes: true });
|
|
273731
273956
|
} catch {
|
|
273732
273957
|
return 0;
|
|
273733
273958
|
}
|
|
@@ -273736,24 +273961,24 @@ function installRuntimeAssets(srcRoot, binDir) {
|
|
|
273736
273961
|
const srcDir = path39.join(srcRoot, entry.name);
|
|
273737
273962
|
let files;
|
|
273738
273963
|
try {
|
|
273739
|
-
files =
|
|
273964
|
+
files = fs44.readdirSync(srcDir).filter((f2) => ASSET_EXTS.some((ext) => f2.endsWith(ext)));
|
|
273740
273965
|
} catch {
|
|
273741
273966
|
continue;
|
|
273742
273967
|
}
|
|
273743
273968
|
if (files.length === 0) continue;
|
|
273744
273969
|
const destDir = path39.join(binDir, entry.name);
|
|
273745
|
-
|
|
273970
|
+
fs44.mkdirSync(destDir, { recursive: true });
|
|
273746
273971
|
for (const f2 of files) {
|
|
273747
273972
|
const dest = path39.join(destDir, f2);
|
|
273748
|
-
|
|
273749
|
-
|
|
273973
|
+
fs44.copyFileSync(path39.join(srcDir, f2), dest);
|
|
273974
|
+
fs44.chmodSync(dest, 493);
|
|
273750
273975
|
copied++;
|
|
273751
273976
|
}
|
|
273752
273977
|
}
|
|
273753
273978
|
return copied;
|
|
273754
273979
|
}
|
|
273755
273980
|
function syncRuntimeAssets(candidateRoots, binDir) {
|
|
273756
|
-
|
|
273981
|
+
fs44.mkdirSync(binDir, { recursive: true });
|
|
273757
273982
|
for (const root of candidateRoots) {
|
|
273758
273983
|
const copied = installRuntimeAssets(root, binDir);
|
|
273759
273984
|
if (copied > 0) return { from: root, copied };
|
|
@@ -273764,7 +273989,7 @@ function runtimeAssetSourceRoots(input) {
|
|
|
273764
273989
|
const roots = [];
|
|
273765
273990
|
if (input.executingBundle) roots.push(path39.dirname(input.executingBundle));
|
|
273766
273991
|
try {
|
|
273767
|
-
roots.push(
|
|
273992
|
+
roots.push(fs44.realpathSync(input.currentLink));
|
|
273768
273993
|
} catch {
|
|
273769
273994
|
}
|
|
273770
273995
|
roots.push(input.packageDist);
|
|
@@ -273772,11 +273997,11 @@ function runtimeAssetSourceRoots(input) {
|
|
|
273772
273997
|
}
|
|
273773
273998
|
|
|
273774
273999
|
// src/paths.ts
|
|
273775
|
-
var
|
|
273776
|
-
var
|
|
274000
|
+
var fs45 = __toESM(require("node:fs"));
|
|
274001
|
+
var os15 = __toESM(require("node:os"));
|
|
273777
274002
|
var path40 = __toESM(require("node:path"));
|
|
273778
274003
|
var DEFAULT_INSTANCE = "default";
|
|
273779
|
-
var home = () =>
|
|
274004
|
+
var home = () => os15.homedir();
|
|
273780
274005
|
var oasisDir = () => path40.join(home(), ".oasis");
|
|
273781
274006
|
var versionsDir = () => path40.join(oasisDir(), "versions");
|
|
273782
274007
|
var versionDir = (label) => path40.join(versionsDir(), label);
|
|
@@ -273806,17 +274031,17 @@ function instancePaths(name) {
|
|
|
273806
274031
|
}
|
|
273807
274032
|
function listInstances() {
|
|
273808
274033
|
const found = [];
|
|
273809
|
-
if (
|
|
274034
|
+
if (fs45.existsSync(instancePaths(DEFAULT_INSTANCE).configFile)) found.push(DEFAULT_INSTANCE);
|
|
273810
274035
|
let entries = [];
|
|
273811
274036
|
try {
|
|
273812
|
-
entries =
|
|
274037
|
+
entries = fs45.readdirSync(instancesRoot());
|
|
273813
274038
|
} catch {
|
|
273814
274039
|
return found;
|
|
273815
274040
|
}
|
|
273816
274041
|
for (const name of entries.sort()) {
|
|
273817
274042
|
if (name === DEFAULT_INSTANCE) continue;
|
|
273818
274043
|
if (!isValidInstanceName(name)) continue;
|
|
273819
|
-
if (
|
|
274044
|
+
if (fs45.existsSync(instancePaths(name).configFile)) found.push(name);
|
|
273820
274045
|
}
|
|
273821
274046
|
return found;
|
|
273822
274047
|
}
|
|
@@ -273824,7 +274049,7 @@ function referencedVersionLabels() {
|
|
|
273824
274049
|
const labels = /* @__PURE__ */ new Set();
|
|
273825
274050
|
for (const name of listInstances()) {
|
|
273826
274051
|
try {
|
|
273827
|
-
labels.add(path40.basename(
|
|
274052
|
+
labels.add(path40.basename(fs45.realpathSync(instancePaths(name).currentLink)));
|
|
273828
274053
|
} catch {
|
|
273829
274054
|
}
|
|
273830
274055
|
}
|
|
@@ -273849,12 +274074,12 @@ var LEGACY_LAUNCHD_LABEL = "com.oasis.node";
|
|
|
273849
274074
|
|
|
273850
274075
|
// src/install.ts
|
|
273851
274076
|
var import_node_crypto84 = require("node:crypto");
|
|
273852
|
-
var
|
|
274077
|
+
var fs46 = __toESM(require("node:fs"));
|
|
273853
274078
|
var path41 = __toESM(require("node:path"));
|
|
273854
274079
|
function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
|
|
273855
274080
|
const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
|
|
273856
274081
|
if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
|
|
273857
|
-
const digest = (0, import_node_crypto84.createHash)("sha256").update(
|
|
274082
|
+
const digest = (0, import_node_crypto84.createHash)("sha256").update(fs46.readFileSync(sourceFile)).digest("hex").slice(0, 8);
|
|
273858
274083
|
return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
|
|
273859
274084
|
}
|
|
273860
274085
|
function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
@@ -273865,14 +274090,14 @@ function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
|
273865
274090
|
var isLocalLabel = (label) => /(?:^|[+.])local\.[0-9a-f]{8}$/.test(label);
|
|
273866
274091
|
function installBinaryAtomic(sourceFile, targetPath) {
|
|
273867
274092
|
if (realpathOrSelf(sourceFile) === realpathOrSelf(targetPath)) return;
|
|
273868
|
-
|
|
274093
|
+
fs46.mkdirSync(path41.dirname(targetPath), { recursive: true });
|
|
273869
274094
|
const tmp = `${targetPath}.tmp.${process.pid}`;
|
|
273870
274095
|
try {
|
|
273871
|
-
|
|
273872
|
-
|
|
274096
|
+
fs46.copyFileSync(sourceFile, tmp);
|
|
274097
|
+
fs46.renameSync(tmp, targetPath);
|
|
273873
274098
|
} catch (e) {
|
|
273874
274099
|
try {
|
|
273875
|
-
|
|
274100
|
+
fs46.unlinkSync(tmp);
|
|
273876
274101
|
} catch {
|
|
273877
274102
|
}
|
|
273878
274103
|
throw e;
|
|
@@ -273880,24 +274105,24 @@ function installBinaryAtomic(sourceFile, targetPath) {
|
|
|
273880
274105
|
}
|
|
273881
274106
|
var realpathOrSelf = (p2) => {
|
|
273882
274107
|
try {
|
|
273883
|
-
return
|
|
274108
|
+
return fs46.realpathSync(p2);
|
|
273884
274109
|
} catch {
|
|
273885
274110
|
return path41.resolve(p2);
|
|
273886
274111
|
}
|
|
273887
274112
|
};
|
|
273888
274113
|
function pointCurrentAt(linkPath, targetDir) {
|
|
273889
|
-
|
|
274114
|
+
fs46.mkdirSync(path41.dirname(linkPath), { recursive: true });
|
|
273890
274115
|
const tmp = `${linkPath}.tmp.${process.pid}`;
|
|
273891
274116
|
try {
|
|
273892
|
-
|
|
274117
|
+
fs46.unlinkSync(tmp);
|
|
273893
274118
|
} catch {
|
|
273894
274119
|
}
|
|
273895
|
-
|
|
274120
|
+
fs46.symlinkSync(targetDir, tmp, "dir");
|
|
273896
274121
|
try {
|
|
273897
|
-
|
|
274122
|
+
fs46.renameSync(tmp, linkPath);
|
|
273898
274123
|
} catch (e) {
|
|
273899
274124
|
try {
|
|
273900
|
-
|
|
274125
|
+
fs46.unlinkSync(tmp);
|
|
273901
274126
|
} catch {
|
|
273902
274127
|
}
|
|
273903
274128
|
throw new Error(`\u65E0\u6CD5\u628A ${linkPath} \u6307\u5411 ${targetDir}\uFF1A${String(e)}\uFF08\u82E5\u5B83\u662F\u771F\u76EE\u5F55\uFF0C\u5220\u6389\u540E\u91CD\u8DD1\uFF09`);
|
|
@@ -273910,14 +274135,14 @@ function gcVersions(versionsDirPath, opts) {
|
|
|
273910
274135
|
const now = opts.now ?? Date.now();
|
|
273911
274136
|
let entries;
|
|
273912
274137
|
try {
|
|
273913
|
-
entries =
|
|
274138
|
+
entries = fs46.readdirSync(versionsDirPath);
|
|
273914
274139
|
} catch {
|
|
273915
274140
|
return [];
|
|
273916
274141
|
}
|
|
273917
274142
|
const candidates = entries.filter((name) => !keep.has(name) && !name.includes(".tmp.")).map((name) => {
|
|
273918
274143
|
const full = path41.join(versionsDirPath, name);
|
|
273919
274144
|
try {
|
|
273920
|
-
const st =
|
|
274145
|
+
const st = fs46.statSync(full);
|
|
273921
274146
|
return st.isDirectory() ? { name, full, mtime: st.mtimeMs } : null;
|
|
273922
274147
|
} catch {
|
|
273923
274148
|
return null;
|
|
@@ -273927,7 +274152,7 @@ function gcVersions(versionsDirPath, opts) {
|
|
|
273927
274152
|
for (const c of candidates.slice(keepSpare)) {
|
|
273928
274153
|
if (now - c.mtime < minAgeMs) continue;
|
|
273929
274154
|
try {
|
|
273930
|
-
|
|
274155
|
+
fs46.rmSync(c.full, { recursive: true, force: true });
|
|
273931
274156
|
deleted.push(c.name);
|
|
273932
274157
|
} catch {
|
|
273933
274158
|
}
|
|
@@ -273977,7 +274202,7 @@ function shimScript() {
|
|
|
273977
274202
|
}
|
|
273978
274203
|
|
|
273979
274204
|
// src/index.ts
|
|
273980
|
-
var PKG_VERSION = true ? "2.2.
|
|
274205
|
+
var PKG_VERSION = true ? "2.2.24" : "dev";
|
|
273981
274206
|
var LOCAL_BIN = localBin();
|
|
273982
274207
|
var NPM_PREFIX = npmPrefix();
|
|
273983
274208
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -274018,18 +274243,18 @@ var parseFlags = (argv) => {
|
|
|
274018
274243
|
};
|
|
274019
274244
|
var readConfig = () => {
|
|
274020
274245
|
try {
|
|
274021
|
-
return JSON.parse(
|
|
274246
|
+
return JSON.parse(fs47.readFileSync(CONFIG_FILE, "utf8"));
|
|
274022
274247
|
} catch {
|
|
274023
274248
|
return null;
|
|
274024
274249
|
}
|
|
274025
274250
|
};
|
|
274026
274251
|
var saveConfig = (c) => {
|
|
274027
|
-
|
|
274028
|
-
|
|
274252
|
+
fs47.mkdirSync(INST.dir, { recursive: true });
|
|
274253
|
+
fs47.writeFileSync(CONFIG_FILE, JSON.stringify(c), { mode: 384 });
|
|
274029
274254
|
};
|
|
274030
274255
|
var readPidAt = (file) => {
|
|
274031
274256
|
try {
|
|
274032
|
-
const p2 = parseInt(
|
|
274257
|
+
const p2 = parseInt(fs47.readFileSync(file, "utf8").trim(), 10);
|
|
274033
274258
|
return isNaN(p2) ? null : p2;
|
|
274034
274259
|
} catch {
|
|
274035
274260
|
return null;
|
|
@@ -274038,7 +274263,7 @@ var readPidAt = (file) => {
|
|
|
274038
274263
|
var readPid = () => readPidAt(PID_FILE);
|
|
274039
274264
|
var readConfigAt = (file) => {
|
|
274040
274265
|
try {
|
|
274041
|
-
return JSON.parse(
|
|
274266
|
+
return JSON.parse(fs47.readFileSync(file, "utf8"));
|
|
274042
274267
|
} catch {
|
|
274043
274268
|
return null;
|
|
274044
274269
|
}
|
|
@@ -274073,8 +274298,8 @@ function installSoftware(label) {
|
|
|
274073
274298
|
installBinaryAtomic(src, BIN_FILE);
|
|
274074
274299
|
ensureRuntimeAssets(BIN_DIR);
|
|
274075
274300
|
pointCurrentAt(INST.currentLink, vDir);
|
|
274076
|
-
|
|
274077
|
-
|
|
274301
|
+
fs47.mkdirSync(path42.dirname(LOCAL_BIN), { recursive: true });
|
|
274302
|
+
fs47.writeFileSync(LOCAL_BIN, shimScript(), { mode: 493 });
|
|
274078
274303
|
const keep = [.../* @__PURE__ */ new Set([label, ...referencedVersionLabels(), ...liveSessionPinnedLabels(sessionRoots(), { isLocked: isSessionLocked, flockAvailable: hasFlock() })])];
|
|
274079
274304
|
const removed = gcVersions(versionsDir(), { keep });
|
|
274080
274305
|
if (removed.length) console.error(`[oasis] \u7248\u672C GC\uFF1A\u5220\u9664 ${removed.join(", ")}\uFF08\u5728\u7528\uFF1A${keep.join(", ")}\uFF09`);
|
|
@@ -274083,7 +274308,7 @@ function installSoftware(label) {
|
|
|
274083
274308
|
function setupAutostart(name) {
|
|
274084
274309
|
const inst = instancePaths(name);
|
|
274085
274310
|
const cmd = `${process.execPath} "${inst.binFile}" --_daemon --instance ${name}`;
|
|
274086
|
-
const home2 =
|
|
274311
|
+
const home2 = os16.homedir();
|
|
274087
274312
|
const pnpmHome = process.env["PNPM_HOME"] || path42.join(home2, ".local", "share", "pnpm");
|
|
274088
274313
|
const extraBins = [
|
|
274089
274314
|
path42.join(home2, ".npm-global", "bin"),
|
|
@@ -274093,11 +274318,11 @@ function setupAutostart(name) {
|
|
|
274093
274318
|
];
|
|
274094
274319
|
const daemonPath = sanitizeDaemonPath([process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":"));
|
|
274095
274320
|
if (process.platform === "linux") {
|
|
274096
|
-
const unitDir = path42.join(
|
|
274097
|
-
|
|
274321
|
+
const unitDir = path42.join(os16.homedir(), ".config", "systemd", "user");
|
|
274322
|
+
fs47.mkdirSync(unitDir, { recursive: true });
|
|
274098
274323
|
const unit = systemdUnitName(name);
|
|
274099
|
-
|
|
274100
|
-
|
|
274324
|
+
fs47.mkdirSync(path42.dirname(inst.logFile), { recursive: true });
|
|
274325
|
+
fs47.writeFileSync(path42.join(unitDir, unit), systemdUnitText({
|
|
274101
274326
|
name,
|
|
274102
274327
|
cmd,
|
|
274103
274328
|
daemonPath,
|
|
@@ -274118,9 +274343,9 @@ function setupAutostart(name) {
|
|
|
274118
274343
|
return false;
|
|
274119
274344
|
} else if (process.platform === "darwin") {
|
|
274120
274345
|
const label = launchdLabel(name);
|
|
274121
|
-
const plist = path42.join(
|
|
274122
|
-
|
|
274123
|
-
|
|
274346
|
+
const plist = path42.join(os16.homedir(), "Library", "LaunchAgents", `${label}.plist`);
|
|
274347
|
+
fs47.mkdirSync(path42.dirname(plist), { recursive: true });
|
|
274348
|
+
fs47.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
|
|
274124
274349
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
274125
274350
|
<plist version="1.0"><dict>
|
|
274126
274351
|
<key>Label</key><string>${label}</string>
|
|
@@ -274140,8 +274365,8 @@ function setupAutostart(name) {
|
|
|
274140
274365
|
return false;
|
|
274141
274366
|
}
|
|
274142
274367
|
function spawnDaemon() {
|
|
274143
|
-
|
|
274144
|
-
const log3 =
|
|
274368
|
+
fs47.mkdirSync(path42.dirname(LOG_FILE), { recursive: true });
|
|
274369
|
+
const log3 = fs47.openSync(LOG_FILE, "a");
|
|
274145
274370
|
const child = (0, import_node_child_process20.spawn)(process.execPath, [INST.binFile, "--_daemon", "--instance", INSTANCE], {
|
|
274146
274371
|
detached: true,
|
|
274147
274372
|
stdio: ["ignore", log3, log3],
|
|
@@ -274162,7 +274387,7 @@ function stopDaemon(name) {
|
|
|
274162
274387
|
}
|
|
274163
274388
|
}
|
|
274164
274389
|
try {
|
|
274165
|
-
|
|
274390
|
+
fs47.unlinkSync(inst.pidFile);
|
|
274166
274391
|
} catch {
|
|
274167
274392
|
}
|
|
274168
274393
|
if (process.platform === "linux") {
|
|
@@ -274228,7 +274453,7 @@ function selfUpdate(targetPkg) {
|
|
|
274228
274453
|
return false;
|
|
274229
274454
|
}
|
|
274230
274455
|
})();
|
|
274231
|
-
const log3 =
|
|
274456
|
+
const log3 = fs47.openSync(LOG_FILE, "a");
|
|
274232
274457
|
if (hasSystemd) {
|
|
274233
274458
|
const child = (0, import_node_child_process20.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
|
|
274234
274459
|
detached: true,
|
|
@@ -274250,13 +274475,13 @@ function resolveInstance(explicit) {
|
|
|
274250
274475
|
}
|
|
274251
274476
|
function currentLabelOf(inst) {
|
|
274252
274477
|
try {
|
|
274253
|
-
return path42.basename(
|
|
274478
|
+
return path42.basename(fs47.realpathSync(inst.currentLink));
|
|
274254
274479
|
} catch {
|
|
274255
274480
|
return null;
|
|
274256
274481
|
}
|
|
274257
274482
|
}
|
|
274258
274483
|
function instanceHasSoftware(inst) {
|
|
274259
|
-
return
|
|
274484
|
+
return fs47.existsSync(inst.binFile) && currentLabelOf(inst) !== null;
|
|
274260
274485
|
}
|
|
274261
274486
|
function newInstanceName() {
|
|
274262
274487
|
const existing = new Set(listInstances());
|
|
@@ -274269,7 +274494,7 @@ function newInstanceName() {
|
|
|
274269
274494
|
function planStart(explicit, serverUrl, companyId) {
|
|
274270
274495
|
if (explicit) {
|
|
274271
274496
|
const name = resolveInstance(explicit);
|
|
274272
|
-
return { mode:
|
|
274497
|
+
return { mode: fs47.existsSync(instancePaths(name).configFile) ? "resume" : "new", names: [name] };
|
|
274273
274498
|
}
|
|
274274
274499
|
const all2 = listInstances();
|
|
274275
274500
|
if (all2.length === 0) return { mode: "new", names: [DEFAULT_INSTANCE] };
|
|
@@ -274300,7 +274525,7 @@ async function startOneInstance(o) {
|
|
|
274300
274525
|
const res = await fetch(`${httpBase(serverUrl)}/api/nodes/exchange`, {
|
|
274301
274526
|
method: "POST",
|
|
274302
274527
|
headers: { "content-type": "application/json" },
|
|
274303
|
-
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname:
|
|
274528
|
+
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os16.hostname(), serverUrl, ...companyId ? { companyId } : {} })
|
|
274304
274529
|
});
|
|
274305
274530
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
274306
274531
|
const body2 = await res.json();
|
|
@@ -274340,8 +274565,8 @@ async function startOneInstance(o) {
|
|
|
274340
274565
|
const cfgNow = readConfig();
|
|
274341
274566
|
if (cfgNow && !cfgNow.pkgName) saveConfig({ ...cfgNow, pkgName: BUILT_PKG_NAME });
|
|
274342
274567
|
} else {
|
|
274343
|
-
|
|
274344
|
-
|
|
274568
|
+
fs47.mkdirSync(path42.dirname(LOCAL_BIN), { recursive: true });
|
|
274569
|
+
fs47.writeFileSync(LOCAL_BIN, shimScript(), { mode: 493 });
|
|
274345
274570
|
}
|
|
274346
274571
|
const pidNow = readPid();
|
|
274347
274572
|
const alive2 = !!pidNow && isRunning2(pidNow);
|
|
@@ -274365,7 +274590,7 @@ function derivedNodeIdFor(name) {
|
|
|
274365
274590
|
if (name === DEFAULT_INSTANCE) return resolveNodeId();
|
|
274366
274591
|
const user = (() => {
|
|
274367
274592
|
try {
|
|
274368
|
-
return
|
|
274593
|
+
return os16.userInfo().username;
|
|
274369
274594
|
} catch {
|
|
274370
274595
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
274371
274596
|
}
|
|
@@ -274385,10 +274610,10 @@ function spawnSessionProcess(spec) {
|
|
|
274385
274610
|
try {
|
|
274386
274611
|
const safe = spec.dispatchId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
274387
274612
|
const dir = path42.join(INST.sessionsDir, safe);
|
|
274388
|
-
|
|
274613
|
+
fs47.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
274389
274614
|
const specFile = path42.join(dir, "spec.json");
|
|
274390
274615
|
const cfg = readConfig();
|
|
274391
|
-
|
|
274616
|
+
fs47.writeFileSync(specFile, JSON.stringify({
|
|
274392
274617
|
...spec,
|
|
274393
274618
|
sessionDir: dir,
|
|
274394
274619
|
nodeId: cfg?.nodeId ?? INSTANCE,
|
|
@@ -274397,19 +274622,24 @@ function spawnSessionProcess(spec) {
|
|
|
274397
274622
|
}), { mode: 384 });
|
|
274398
274623
|
let pinnedDir = INST.currentLink;
|
|
274399
274624
|
try {
|
|
274400
|
-
pinnedDir =
|
|
274625
|
+
pinnedDir = fs47.realpathSync(INST.currentLink);
|
|
274401
274626
|
} catch {
|
|
274402
274627
|
}
|
|
274403
274628
|
try {
|
|
274404
|
-
|
|
274629
|
+
fs47.writeFileSync(path42.join(dir, "pinned-version"), path42.basename(pinnedDir));
|
|
274405
274630
|
} catch {
|
|
274406
274631
|
}
|
|
274407
|
-
const logFd =
|
|
274632
|
+
const logFd = fs47.openSync(path42.join(dir, "session.log"), "a");
|
|
274408
274633
|
const argv = [INST.binFile, "--_session", specFile];
|
|
274409
|
-
const
|
|
274634
|
+
const executionEnv = spec.job.execution ? {
|
|
274635
|
+
OASIS_EXECUTION_KEY: spec.job.execution.key,
|
|
274636
|
+
OASIS_EXECUTION_GENERATION: String(spec.job.execution.generation),
|
|
274637
|
+
OASIS_EXECUTION_DISPATCH_ID: spec.dispatchId
|
|
274638
|
+
} : {};
|
|
274639
|
+
const env = { ...process.env, ...executionEnv, OASIS_CLI_HOME: pinnedDir };
|
|
274410
274640
|
const child = userScopeAvailable() ? (0, import_node_child_process20.spawn)(
|
|
274411
274641
|
"systemd-run",
|
|
274412
|
-
["--user", "--scope", "--quiet", `--setenv=OASIS_CLI_HOME=${pinnedDir}`, process.execPath, ...argv],
|
|
274642
|
+
["--user", "--scope", "--quiet", `--setenv=OASIS_CLI_HOME=${pinnedDir}`, ...Object.entries(executionEnv).map(([key, value2]) => `--setenv=${key}=${value2}`), process.execPath, ...argv],
|
|
274413
274643
|
{ detached: true, stdio: ["ignore", logFd, logFd], env }
|
|
274414
274644
|
) : (0, import_node_child_process20.spawn)(process.execPath, argv, { detached: true, stdio: ["ignore", logFd, logFd], env });
|
|
274415
274645
|
child.unref();
|
|
@@ -274452,9 +274682,9 @@ void (async () => {
|
|
|
274452
274682
|
process.exit(1);
|
|
274453
274683
|
}
|
|
274454
274684
|
try {
|
|
274455
|
-
const fd =
|
|
274456
|
-
|
|
274457
|
-
|
|
274685
|
+
const fd = fs47.openSync(PID_FILE, "wx");
|
|
274686
|
+
fs47.writeSync(fd, String(process.pid));
|
|
274687
|
+
fs47.closeSync(fd);
|
|
274458
274688
|
} catch {
|
|
274459
274689
|
const alivePid = readPid();
|
|
274460
274690
|
if (alivePid && alivePid !== process.pid && isRunning2(alivePid)) {
|
|
@@ -274462,13 +274692,13 @@ void (async () => {
|
|
|
274462
274692
|
process.exit(0);
|
|
274463
274693
|
}
|
|
274464
274694
|
try {
|
|
274465
|
-
|
|
274695
|
+
fs47.writeFileSync(PID_FILE, String(process.pid));
|
|
274466
274696
|
} catch {
|
|
274467
274697
|
}
|
|
274468
274698
|
}
|
|
274469
274699
|
const cleanup = () => {
|
|
274470
274700
|
try {
|
|
274471
|
-
if (
|
|
274701
|
+
if (fs47.readFileSync(PID_FILE, "utf8").trim() === String(process.pid)) fs47.unlinkSync(PID_FILE);
|
|
274472
274702
|
} catch {
|
|
274473
274703
|
}
|
|
274474
274704
|
};
|
|
@@ -274542,7 +274772,6 @@ void (async () => {
|
|
|
274542
274772
|
drainNode = ctl.drain;
|
|
274543
274773
|
},
|
|
274544
274774
|
// 服务端下发了数据面通行证时,把会话交给独立进程跑(daemon 重启不再连坐它)。
|
|
274545
|
-
sessionsRoot: INST.sessionsDir,
|
|
274546
274775
|
spawnSessionProcess,
|
|
274547
274776
|
countDetachedSessions: () => countLiveSessions(sessionRoots(), { isLocked: isSessionLocked, flockAvailable: hasFlock() })
|
|
274548
274777
|
});
|