oasis_test_v2 2.2.77 → 2.2.79
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 +1126 -717
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -455,6 +455,13 @@ var init_inbox_read = __esm({
|
|
|
455
455
|
}
|
|
456
456
|
});
|
|
457
457
|
|
|
458
|
+
// ../contract/src/connector-auth-pending.ts
|
|
459
|
+
var init_connector_auth_pending = __esm({
|
|
460
|
+
"../contract/src/connector-auth-pending.ts"() {
|
|
461
|
+
"use strict";
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
|
|
458
465
|
// ../contract/src/notifications.ts
|
|
459
466
|
var LEDGER_INBOX_KINDS;
|
|
460
467
|
var init_notifications = __esm({
|
|
@@ -1047,12 +1054,13 @@ function sanitizeRuntimeQuotas(value2, now = Date.now()) {
|
|
|
1047
1054
|
}
|
|
1048
1055
|
return result;
|
|
1049
1056
|
}
|
|
1050
|
-
var RUNTIME_QUOTA_POLL_MS, RUNTIME_QUOTA_STALE_MS, statuses;
|
|
1057
|
+
var RUNTIME_QUOTA_POLL_MS, RUNTIME_QUOTA_STALE_MS, RUNTIME_QUOTA_REFRESH_MIN_GAP_MS, statuses;
|
|
1051
1058
|
var init_runtime_quota = __esm({
|
|
1052
1059
|
"../contract/src/runtime-quota.ts"() {
|
|
1053
1060
|
"use strict";
|
|
1054
1061
|
RUNTIME_QUOTA_POLL_MS = 5 * 6e4;
|
|
1055
1062
|
RUNTIME_QUOTA_STALE_MS = 2 * RUNTIME_QUOTA_POLL_MS;
|
|
1063
|
+
RUNTIME_QUOTA_REFRESH_MIN_GAP_MS = 3e4;
|
|
1056
1064
|
statuses = /* @__PURE__ */ new Set(["ok", "unavailable", "unauthenticated", "unsupported", "error", "rate_limited"]);
|
|
1057
1065
|
}
|
|
1058
1066
|
});
|
|
@@ -2277,6 +2285,7 @@ var init_src = __esm({
|
|
|
2277
2285
|
init_annotation();
|
|
2278
2286
|
init_collab_view();
|
|
2279
2287
|
init_inbox_read();
|
|
2288
|
+
init_connector_auth_pending();
|
|
2280
2289
|
init_notifications();
|
|
2281
2290
|
init_workorder_quality();
|
|
2282
2291
|
init_workorder_attachments();
|
|
@@ -2562,7 +2571,7 @@ var init_session_runtime_target = __esm({
|
|
|
2562
2571
|
this.name = "SessionRuntimeOverrideError";
|
|
2563
2572
|
}
|
|
2564
2573
|
};
|
|
2565
|
-
CLEAR_SESSION_RUNTIME_HINT = "\u5728\u8FD0\u884C\u65F6\u9009\u62E9\u91CC\
|
|
2574
|
+
CLEAR_SESSION_RUNTIME_HINT = "\u5728\u8F93\u5165\u6846\u5E95\u90E8\u7684\u8FD0\u884C\u65F6\u9009\u62E9\u91CC\u6362\u4E00\u53F0\u53EF\u7528\u7684\u670D\u52A1\u5668\u6216\u8FD0\u884C\u65F6\u5373\u53EF\u7EE7\u7EED\uFF08\u5458\u5DE5\u81EA\u5DF1\u7684\u90A3\u4E00\u5957\u6807\u7740\u300C\u5F53\u524D\u5458\u5DE5\u6240\u5728\u670D\u52A1\u5668\u300D\u300C\u5F53\u524D\u5458\u5DE5\u8FD0\u884C\u65F6\u300D\uFF09\u3002";
|
|
2566
2575
|
}
|
|
2567
2576
|
});
|
|
2568
2577
|
|
|
@@ -164597,7 +164606,7 @@ var init_initialize_workorder = __esm({
|
|
|
164597
164606
|
function hasRejectionEvidence(reason) {
|
|
164598
164607
|
return DEFINITELY_NOT_DELIVERED.has(reason ?? "");
|
|
164599
164608
|
}
|
|
164600
|
-
var DEFINITELY_NOT_DELIVERED, INSERT_UNCERTAIN_NOTE;
|
|
164609
|
+
var DEFINITELY_NOT_DELIVERED, INSERT_UNCERTAIN_NOTE, INSERT_RETURNED_NOTE;
|
|
164601
164610
|
var init_chat_insert_evidence = __esm({
|
|
164602
164611
|
"../server/src/chat-insert-evidence.ts"() {
|
|
164603
164612
|
"use strict";
|
|
@@ -164611,6 +164620,7 @@ var init_chat_insert_evidence = __esm({
|
|
|
164611
164620
|
"not-consumed"
|
|
164612
164621
|
]);
|
|
164613
164622
|
INSERT_UNCERTAIN_NOTE = "\u8FD9\u6B21\u63D2\u5165\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF1A\u65E0\u6CD5\u786E\u8BA4 agent \u662F\u5426\u5DF2\u8BFB\u5230\u3002";
|
|
164623
|
+
INSERT_RETURNED_NOTE = "\u8FD9\u53E5\u8BDD\u6CA1\u6709\u4EA4\u5230 agent \u624B\u4E0A\uFF1A\u63D2\u8BDD\u65F6\u9875\u9762\u5DF2\u5237\u65B0\u6216\u5173\u95ED\uFF0C\u6CA1\u80FD\u5728\u672C\u8F6E\u7ED3\u675F\u540E\u81EA\u52A8\u53D1\u51FA\u3002";
|
|
164614
164624
|
}
|
|
164615
164625
|
});
|
|
164616
164626
|
|
|
@@ -165880,14 +165890,15 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
|
|
|
165880
165890
|
if (!batch.length) {
|
|
165881
165891
|
const state = submitted.state ?? "queued";
|
|
165882
165892
|
const returned = state === "cancelled" && submitted.stateReason?.startsWith("client-retained:");
|
|
165893
|
+
const landed = state === "cancelled" && submitted.stateReason?.startsWith("client-gone:");
|
|
165883
165894
|
const reason = state === "delivering" ? "in-flight" : returned ? submitted.stateReason.slice("client-retained:".length) : "unconfirmed";
|
|
165884
165895
|
return {
|
|
165885
165896
|
accepted: state === "delivered",
|
|
165886
165897
|
...state !== "delivered" ? { reason } : {},
|
|
165887
|
-
queued: !returned,
|
|
165898
|
+
queued: !returned && !landed,
|
|
165888
165899
|
delivered: "",
|
|
165889
165900
|
batch: [submitted],
|
|
165890
|
-
insertStatus: insertStatusOfRow(submitted)
|
|
165901
|
+
insertStatus: landed ? "uncertain" : insertStatusOfRow(submitted)
|
|
165891
165902
|
};
|
|
165892
165903
|
}
|
|
165893
165904
|
const prepared = await buildChatAttachmentFiles(
|
|
@@ -165909,8 +165920,13 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
|
|
|
165909
165920
|
const recordOutcome = async (res) => {
|
|
165910
165921
|
const nextState = res.accepted ? "delivered" : hasRejectionEvidence(res.reason) ? "queued" : "unconfirmed";
|
|
165911
165922
|
const stateReason = res.detail ? `${res.reason ?? (res.accepted ? "delivered" : "")}:${res.detail}` : res.reason;
|
|
165912
|
-
const
|
|
165913
|
-
|
|
165923
|
+
const wantsReturn = retainLocallyOnFailure && !!clientKey && nextState === "queued";
|
|
165924
|
+
const orphanedReturn = wantsReturn && deps.clientAttached?.() === false;
|
|
165925
|
+
const returnToClient = wantsReturn && !orphanedReturn;
|
|
165926
|
+
if (orphanedReturn && deps.store.markPendingMessages) {
|
|
165927
|
+
await deps.store.markPendingMessages(chatSessionId, [submitted.id], "cancelled", `client-gone:${res.reason}`);
|
|
165928
|
+
await deps.store.markPendingMessages(chatSessionId, ids2.filter((id) => id !== submitted.id), nextState, stateReason);
|
|
165929
|
+
} else if (returnToClient && deps.store.markPendingMessages) {
|
|
165914
165930
|
await deps.store.markPendingMessages(chatSessionId, [submitted.id], "cancelled", `client-retained:${res.reason}`);
|
|
165915
165931
|
await deps.store.markPendingMessages(chatSessionId, ids2.filter((id) => id !== submitted.id), nextState, stateReason);
|
|
165916
165932
|
} else {
|
|
@@ -165920,7 +165936,15 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
|
|
|
165920
165936
|
if (returnToClient) await deps.store.removePendingMessage(chatSessionId, submitted.id);
|
|
165921
165937
|
}
|
|
165922
165938
|
const insertStatus = nextState === "delivered" ? "inserted" : nextState === "unconfirmed" ? "uncertain" : "not-inserted";
|
|
165923
|
-
return {
|
|
165939
|
+
return {
|
|
165940
|
+
...res,
|
|
165941
|
+
queued: !returnToClient && !orphanedReturn,
|
|
165942
|
+
delivered: merged,
|
|
165943
|
+
batch,
|
|
165944
|
+
insertStatus,
|
|
165945
|
+
...orphanedReturn ? { orphanedReturn: true } : {},
|
|
165946
|
+
...prepared.paths.length ? { attachmentPaths: prepared.paths } : {}
|
|
165947
|
+
};
|
|
165924
165948
|
};
|
|
165925
165949
|
let settle;
|
|
165926
165950
|
const settled = new Promise((resolve12) => {
|
|
@@ -165954,82 +165978,6 @@ var init_append_now = __esm({
|
|
|
165954
165978
|
}
|
|
165955
165979
|
});
|
|
165956
165980
|
|
|
165957
|
-
// ../server/src/domains/chat-sessions/insert-status.ts
|
|
165958
|
-
async function resolveInsertStatus(deps, chatSessionId, clientKey) {
|
|
165959
|
-
const id = insertRequestId(chatSessionId, clientKey);
|
|
165960
|
-
if (!deps.store.getPendingMessage) return { status: "uncertain" };
|
|
165961
|
-
let row = await deps.store.getPendingMessage(chatSessionId, id);
|
|
165962
|
-
if (row?.state !== "delivering") return { status: insertStatusOfRow(row) };
|
|
165963
|
-
if (deps.isTurnRunning(chatSessionId)) return { status: "in-flight" };
|
|
165964
|
-
if (isInsertInflight(id)) {
|
|
165965
|
-
await waitForInflightInsert(id, deps.settleWaitMs ?? 1e4);
|
|
165966
|
-
row = await deps.store.getPendingMessage(chatSessionId, id);
|
|
165967
|
-
return { status: insertStatusOfRow(row) };
|
|
165968
|
-
}
|
|
165969
|
-
const running = settlingOrphans.get(id);
|
|
165970
|
-
if (running) return running;
|
|
165971
|
-
const settling = settleOrphan(deps, chatSessionId, row).finally(() => {
|
|
165972
|
-
settlingOrphans.delete(id);
|
|
165973
|
-
});
|
|
165974
|
-
settlingOrphans.set(id, settling);
|
|
165975
|
-
return settling;
|
|
165976
|
-
}
|
|
165977
|
-
async function settleOrphan(deps, chatSessionId, row) {
|
|
165978
|
-
const ref2 = row.deliveryRef;
|
|
165979
|
-
const answer = ref2?.nodeId && ref2.dispatchId && deps.confirm ? await deps.confirm({ nodeId: ref2.nodeId, dispatchId: ref2.dispatchId, runtimeKey: ref2.runtimeKey }).catch(() => ({ status: "unknown", reason: "query-failed" })) : { status: "unknown", reason: ref2 ? "no-node" : "no-delivery-ref" };
|
|
165980
|
-
const trace = ref2 && deps.store.listPendingTrace ? await deps.store.listPendingTrace(chatSessionId).catch(() => []) : [];
|
|
165981
|
-
const batch = trace.filter((r) => r.state === "delivering" && r.deliveryRef?.runtimeKey === ref2?.runtimeKey);
|
|
165982
|
-
if (!batch.some((r) => r.id === row.id)) batch.push(row);
|
|
165983
|
-
const ids2 = batch.map((r) => r.id);
|
|
165984
|
-
deps.log?.(`[chat-insert] \u5B64\u513F\u63D2\u5165\u7ED3\u7B97 sid=${chatSessionId} row=${row.id} \u2192 ${answer.status}${answer.reason ? `(${answer.reason})` : ""}`);
|
|
165985
|
-
if (answer.status === "consumed") {
|
|
165986
|
-
await backfill(deps, chatSessionId, batch, row).catch((err) => {
|
|
165987
|
-
deps.log?.(`[chat-insert] \u8865\u884C\u5931\u8D25\uFF08\u4ECD\u6309\u5DF2\u63D2\u5165\u5904\u7406\uFF0Cruntime \u786E\u5B9E\u8BFB\u5230\u4E86\uFF09sid=${chatSessionId}: ${String(err)}`);
|
|
165988
|
-
});
|
|
165989
|
-
await deps.store.markPendingMessages?.(chatSessionId, ids2, "delivered", "delivered:node-confirmed-orphan");
|
|
165990
|
-
return { status: "inserted" };
|
|
165991
|
-
}
|
|
165992
|
-
if (answer.status === "not-consumed") {
|
|
165993
|
-
await deps.store.markPendingMessages?.(chatSessionId, [row.id], "cancelled", "client-retained:not-consumed");
|
|
165994
|
-
const rest = ids2.filter((x2) => x2 !== row.id);
|
|
165995
|
-
if (rest.length) await deps.store.markPendingMessages?.(chatSessionId, rest, "queued", `not-consumed:${answer.reason ?? ""}`);
|
|
165996
|
-
return { status: "not-inserted" };
|
|
165997
|
-
}
|
|
165998
|
-
await deps.store.markPendingMessages?.(chatSessionId, ids2, "unconfirmed", `unconfirmed:${answer.reason ?? "unknown"}`);
|
|
165999
|
-
return { status: "uncertain" };
|
|
166000
|
-
}
|
|
166001
|
-
async function backfill(deps, chatSessionId, batch, row) {
|
|
166002
|
-
if (!deps.items) return;
|
|
166003
|
-
const ref2 = row.deliveryRef;
|
|
166004
|
-
const sorted = [...batch].sort((a, b2) => a.seq - b2.seq);
|
|
166005
|
-
const ledger = new ChatItemLedger({
|
|
166006
|
-
items: deps.items,
|
|
166007
|
-
versionSeed: await deps.items.sessionVersionCursor(chatSessionId).catch(() => 0),
|
|
166008
|
-
sessionId: chatSessionId,
|
|
166009
|
-
turnId: ref2?.turnId ?? `insert-backfill:${row.id}`,
|
|
166010
|
-
...deps.log ? { log: deps.log } : {}
|
|
166011
|
-
});
|
|
166012
|
-
const text7 = sorted.map((m2) => m2.text).filter(Boolean).join("\n\n");
|
|
166013
|
-
const attachments = sorted.flatMap((m2) => (m2.attachments ?? []).map((a) => ({
|
|
166014
|
-
name: a.name,
|
|
166015
|
-
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
166016
|
-
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
166017
|
-
})));
|
|
166018
|
-
const clientKeys = sorted.map((m2) => m2.clientKey).filter((k2) => !!k2);
|
|
166019
|
-
ledger.recordUserInput(text7, attachments, clientKeys, ref2?.ord !== void 0 ? { ord: ref2.ord } : void 0);
|
|
166020
|
-
await ledger.drain();
|
|
166021
|
-
if (ledger.failures > 0) throw new Error("chat_items \u5199\u5165\u5931\u8D25");
|
|
166022
|
-
}
|
|
166023
|
-
var settlingOrphans;
|
|
166024
|
-
var init_insert_status = __esm({
|
|
166025
|
-
"../server/src/domains/chat-sessions/insert-status.ts"() {
|
|
166026
|
-
"use strict";
|
|
166027
|
-
init_chat_item_ledger();
|
|
166028
|
-
init_append_now();
|
|
166029
|
-
settlingOrphans = /* @__PURE__ */ new Map();
|
|
166030
|
-
}
|
|
166031
|
-
});
|
|
166032
|
-
|
|
166033
165981
|
// ../server/src/domains/chat-sessions/append-progress.ts
|
|
166034
165982
|
function wantsAppendProgress(req) {
|
|
166035
165983
|
const accept = req.headers.accept;
|
|
@@ -169950,6 +169898,15 @@ async function probeChatSubmission(args) {
|
|
|
169950
169898
|
}
|
|
169951
169899
|
}
|
|
169952
169900
|
const base = { persisted: message !== null, attempts: attempt };
|
|
169901
|
+
if (!lastTurn && chatStore?.getPendingMessage) {
|
|
169902
|
+
const insert = await read("message", () => chatStore.getPendingMessage(sid, insertRequestId(sid, csid)));
|
|
169903
|
+
if (insert?.clientKey === csid) {
|
|
169904
|
+
const landed = insert.state === "unconfirmed" || insert.state === "cancelled" && (insert.stateReason ?? "").startsWith("client-gone:");
|
|
169905
|
+
if (insert.state === "delivered") return { status: { state: "delivered", persisted: true, attempts: attempt, retryable: false }, nextAttempt: attempt, message, lastTurn };
|
|
169906
|
+
if (insert.state === "delivering") return { status: { state: "pending", ...base, retryable: false }, nextAttempt: attempt, message, lastTurn };
|
|
169907
|
+
if (landed) return { status: { state: "not_delivered", ...base, retryable: true }, nextAttempt: attempt, message, lastTurn };
|
|
169908
|
+
}
|
|
169909
|
+
}
|
|
169953
169910
|
let status;
|
|
169954
169911
|
if (!turns) {
|
|
169955
169912
|
if (message && messageDelivered(message)) status = { state: "delivered", ...base, retryable: false };
|
|
@@ -170067,6 +170024,7 @@ var init_chat_submission = __esm({
|
|
|
170067
170024
|
init_src();
|
|
170068
170025
|
init_chat_turn_gate();
|
|
170069
170026
|
init_stable_chat_dispatch_ids();
|
|
170027
|
+
init_append_now();
|
|
170070
170028
|
MAX_SUBMIT_ATTEMPTS = 20;
|
|
170071
170029
|
LEGACY_LOOKBACK_MESSAGES = 200;
|
|
170072
170030
|
LEGACY_LATER_TURNS_LIMIT = 50;
|
|
@@ -170088,6 +170046,56 @@ var init_chat_submission = __esm({
|
|
|
170088
170046
|
}
|
|
170089
170047
|
});
|
|
170090
170048
|
|
|
170049
|
+
// ../server/src/domains/chat-sessions/insert-undelivered.ts
|
|
170050
|
+
async function landUndeliveredInsert(input) {
|
|
170051
|
+
const { store, itemStore, chatSessionId: sid, clientKey, text: text7, note } = input;
|
|
170052
|
+
const log3 = input.log ?? ((m2) => console.warn(m2));
|
|
170053
|
+
try {
|
|
170054
|
+
if (!itemStore || !chatItemsDoubleWriteEnabled()) return;
|
|
170055
|
+
const ledger = new ChatItemLedger({
|
|
170056
|
+
items: itemStore,
|
|
170057
|
+
versionSeed: await itemStore.sessionVersionCursor(sid).catch(() => 0),
|
|
170058
|
+
sessionId: sid,
|
|
170059
|
+
turnId: fallbackTurnId(),
|
|
170060
|
+
log: log3
|
|
170061
|
+
});
|
|
170062
|
+
const refs = input.attachments.map((a) => ({
|
|
170063
|
+
name: a.name,
|
|
170064
|
+
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
170065
|
+
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
170066
|
+
}));
|
|
170067
|
+
ledger.recordRejectedSubmission({
|
|
170068
|
+
user: { text: text7, clientSubmitId: clientKey, ...refs.length ? { attachments: refs } : {} },
|
|
170069
|
+
failure: { reason: note, retryable: true }
|
|
170070
|
+
});
|
|
170071
|
+
await ledger.drain();
|
|
170072
|
+
if (ledger.failures > 0) return;
|
|
170073
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
170074
|
+
await store.appendMessage({
|
|
170075
|
+
id: (0, import_node_crypto26.randomUUID)(),
|
|
170076
|
+
sessionId: sid,
|
|
170077
|
+
role: "user",
|
|
170078
|
+
content: text7,
|
|
170079
|
+
createdAt: now,
|
|
170080
|
+
messageKey: chatSubmitMessageKey(sid, clientKey),
|
|
170081
|
+
...refs.length ? { attachments: refs } : {},
|
|
170082
|
+
needsAgentDelivery: true
|
|
170083
|
+
});
|
|
170084
|
+
await store.updateSession(sid, { touchedAt: now }).catch(() => void 0);
|
|
170085
|
+
} catch (err) {
|
|
170086
|
+
log3(`[chat] \u63D2\u8BDD\u6CA1\u4EA4\u5230 agent \u624B\u4E0A\u3001\u843D\u672A\u9001\u8FBE user \u884C\u5931\u8D25\uFF08session=${sid} key=${clientKey}\uFF09: ${String(err)}`);
|
|
170087
|
+
}
|
|
170088
|
+
}
|
|
170089
|
+
var import_node_crypto26;
|
|
170090
|
+
var init_insert_undelivered = __esm({
|
|
170091
|
+
"../server/src/domains/chat-sessions/insert-undelivered.ts"() {
|
|
170092
|
+
"use strict";
|
|
170093
|
+
import_node_crypto26 = require("node:crypto");
|
|
170094
|
+
init_src();
|
|
170095
|
+
init_chat_item_ledger();
|
|
170096
|
+
}
|
|
170097
|
+
});
|
|
170098
|
+
|
|
170091
170099
|
// ../server/src/chat-workorder-files.ts
|
|
170092
170100
|
function workOrderFileEditTarget(workOrderId, file) {
|
|
170093
170101
|
if (!isEditableFileName(file.name)) return null;
|
|
@@ -170097,7 +170105,7 @@ function workOrderFileEditTarget(workOrderId, file) {
|
|
|
170097
170105
|
return { kind: "work-order-file", workOrderId, fileId: file.fileId, name: file.name };
|
|
170098
170106
|
}
|
|
170099
170107
|
function workOrderFileId(workOrderId, blobId, name) {
|
|
170100
|
-
return `wof:${(0,
|
|
170108
|
+
return `wof:${(0, import_node_crypto27.createHash)("sha256").update(`${workOrderId}|${blobId}|${name}`).digest("hex").slice(0, 32)}`;
|
|
170101
170109
|
}
|
|
170102
170110
|
async function linkChatAttachmentsToWorkOrder(input) {
|
|
170103
170111
|
const warnings = [];
|
|
@@ -170148,11 +170156,11 @@ async function linkChatAttachmentsToWorkOrder(input) {
|
|
|
170148
170156
|
}
|
|
170149
170157
|
return { linked, warnings };
|
|
170150
170158
|
}
|
|
170151
|
-
var
|
|
170159
|
+
var import_node_crypto27;
|
|
170152
170160
|
var init_chat_workorder_files = __esm({
|
|
170153
170161
|
"../server/src/chat-workorder-files.ts"() {
|
|
170154
170162
|
"use strict";
|
|
170155
|
-
|
|
170163
|
+
import_node_crypto27 = require("node:crypto");
|
|
170156
170164
|
init_src();
|
|
170157
170165
|
}
|
|
170158
170166
|
});
|
|
@@ -170943,11 +170951,11 @@ var init_config_store = __esm({
|
|
|
170943
170951
|
function clone2(value2) {
|
|
170944
170952
|
return structuredClone(value2);
|
|
170945
170953
|
}
|
|
170946
|
-
var
|
|
170954
|
+
var import_node_crypto28, import_promises3, import_node_path6, MemoryKnowledgeRunStore, FileKnowledgeRunStore;
|
|
170947
170955
|
var init_run_store = __esm({
|
|
170948
170956
|
"../server/src/domains/knowledge/run-store.ts"() {
|
|
170949
170957
|
"use strict";
|
|
170950
|
-
|
|
170958
|
+
import_node_crypto28 = require("node:crypto");
|
|
170951
170959
|
import_promises3 = require("node:fs/promises");
|
|
170952
170960
|
import_node_path6 = require("node:path");
|
|
170953
170961
|
MemoryKnowledgeRunStore = class {
|
|
@@ -171064,7 +171072,7 @@ var init_run_store = __esm({
|
|
|
171064
171072
|
}
|
|
171065
171073
|
async persist(runs) {
|
|
171066
171074
|
const shape = { version: 1, runs };
|
|
171067
|
-
const temp = `${this.file}.${process.pid}.${(0,
|
|
171075
|
+
const temp = `${this.file}.${process.pid}.${(0, import_node_crypto28.randomUUID)()}.tmp`;
|
|
171068
171076
|
try {
|
|
171069
171077
|
await (0, import_promises3.writeFile)(temp, `${JSON.stringify(shape, null, 2)}
|
|
171070
171078
|
`, { mode: 384 });
|
|
@@ -171713,12 +171721,12 @@ function retryableKnowledgeRun(record9) {
|
|
|
171713
171721
|
const latestAnswerAttempt = [...record9.attempts ?? []].reverse().find((attempt) => attempt.kind !== "fast");
|
|
171714
171722
|
return record9.status === "succeeded" && record9.request.action === "ask" && record9.executionHealth === "degraded" && latestAnswerAttempt?.status === "failed";
|
|
171715
171723
|
}
|
|
171716
|
-
var
|
|
171724
|
+
var import_node_crypto29, ACTION_LABEL, STATUS_MARKER, FINAL_ANSWER_MARKER, ACTIVE_STATUSES, RETRYABLE_STATUSES, HEARTBEAT_INTERVAL_MS, LEASE_MS, MAX_CONCURRENT_READS, ACTION_FLOW, KnowledgeService;
|
|
171717
171725
|
var init_service2 = __esm({
|
|
171718
171726
|
"../server/src/domains/knowledge/service.ts"() {
|
|
171719
171727
|
"use strict";
|
|
171720
171728
|
init_file_limits2();
|
|
171721
|
-
|
|
171729
|
+
import_node_crypto29 = require("node:crypto");
|
|
171722
171730
|
init_src7();
|
|
171723
171731
|
init_config_store();
|
|
171724
171732
|
init_run_store();
|
|
@@ -171761,7 +171769,7 @@ var init_service2 = __esm({
|
|
|
171761
171769
|
constructor(options) {
|
|
171762
171770
|
this.options = options;
|
|
171763
171771
|
this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
171764
|
-
this.id = options.id ??
|
|
171772
|
+
this.id = options.id ?? import_node_crypto29.randomUUID;
|
|
171765
171773
|
this.runStore = options.runStore ?? new MemoryKnowledgeRunStore();
|
|
171766
171774
|
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? HEARTBEAT_INTERVAL_MS;
|
|
171767
171775
|
this.leaseMs = options.leaseMs ?? LEASE_MS;
|
|
@@ -182712,7 +182720,7 @@ function stableJson2(value2) {
|
|
|
182712
182720
|
return JSON.stringify(stableValue(value2));
|
|
182713
182721
|
}
|
|
182714
182722
|
function sha256(value2) {
|
|
182715
|
-
return (0,
|
|
182723
|
+
return (0, import_node_crypto30.createHash)("sha256").update(value2).digest("hex");
|
|
182716
182724
|
}
|
|
182717
182725
|
function normalizeKnowledgeContent(title, content3) {
|
|
182718
182726
|
const body2 = content3.normalize("NFC").replace(/\r\n?/gu, "\n").replace(PUBLISH_MARKER, "\n").split("\n").map((line2) => line2.replace(/[\t ]+$/gu, "")).join("\n").replace(/\n{3,}/gu, "\n\n").trim();
|
|
@@ -182954,11 +182962,11 @@ function renderUntrustedKnowledgeFragment(input) {
|
|
|
182954
182962
|
"</knowledge>"
|
|
182955
182963
|
].join("\n");
|
|
182956
182964
|
}
|
|
182957
|
-
var
|
|
182965
|
+
var import_node_crypto30, KNOWLEDGE_NORMALIZER_VERSION, KNOWLEDGE_PACK_TEMPLATE_VERSION, PUBLISH_MARKER, STOPWORDS, LEXICAL_STOPWORDS, lexicalSegmenters, KNOWLEDGE_LEXICAL_INDEX_VERSION, KNOWLEDGE_MAINTENANCE_RELEVANCE_THRESHOLD, KNOWLEDGE_LAYOUT_TERMS;
|
|
182958
182966
|
var init_governance_content = __esm({
|
|
182959
182967
|
"../server/src/domains/knowledge/governance-content.ts"() {
|
|
182960
182968
|
"use strict";
|
|
182961
|
-
|
|
182969
|
+
import_node_crypto30 = require("node:crypto");
|
|
182962
182970
|
init_mdast_util_from_markdown();
|
|
182963
182971
|
init_mdast_util_gfm();
|
|
182964
182972
|
init_micromark_extension_gfm();
|
|
@@ -193125,11 +193133,11 @@ function approvedSnapshotBody(title, content3) {
|
|
|
193125
193133
|
function uniqueStrings(values) {
|
|
193126
193134
|
return [...new Set(values)].sort();
|
|
193127
193135
|
}
|
|
193128
|
-
var
|
|
193136
|
+
var import_node_crypto31, KnowledgeGovernanceError, put2, REMEDIATION_ACTION_BY_TASK, KnowledgeGovernanceService;
|
|
193129
193137
|
var init_governance_service = __esm({
|
|
193130
193138
|
"../server/src/domains/knowledge/governance-service.ts"() {
|
|
193131
193139
|
"use strict";
|
|
193132
|
-
|
|
193140
|
+
import_node_crypto31 = require("node:crypto");
|
|
193133
193141
|
init_governance_content();
|
|
193134
193142
|
init_knowledge_policy();
|
|
193135
193143
|
init_network_maintenance();
|
|
@@ -193151,7 +193159,7 @@ var init_governance_service = __esm({
|
|
|
193151
193159
|
constructor(options) {
|
|
193152
193160
|
this.options = options;
|
|
193153
193161
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
193154
|
-
this.id = options.id ?? ((prefix) => `${prefix}_${(0,
|
|
193162
|
+
this.id = options.id ?? ((prefix) => `${prefix}_${(0, import_node_crypto31.randomUUID)()}`);
|
|
193155
193163
|
this.versionViewBaseUrl = (options.versionViewBaseUrl ?? "/api/knowledge/items").replace(/\/$/u, "");
|
|
193156
193164
|
this.projectProvisionRetryDelayMs = Math.max(0, options.projectProvisionRetryDelayMs ?? 6e4);
|
|
193157
193165
|
this.projectProvisionMaxRetryDelayMs = Math.max(this.projectProvisionRetryDelayMs, options.projectProvisionMaxRetryDelayMs ?? 36e5);
|
|
@@ -198842,7 +198850,7 @@ function trustedKnowledgeInvocationId(body2, turn) {
|
|
|
198842
198850
|
if (body2.action !== "ask") return void 0;
|
|
198843
198851
|
const scope2 = turn?.artifactId ?? turn?.dispatchId;
|
|
198844
198852
|
if (!scope2) return void 0;
|
|
198845
|
-
const fingerprint2 = (0,
|
|
198853
|
+
const fingerprint2 = (0, import_node_crypto32.createHash)("sha256").update(JSON.stringify({
|
|
198846
198854
|
action: body2.action,
|
|
198847
198855
|
message: body2.message?.trim() ?? "",
|
|
198848
198856
|
queryMode: body2.queryMode === "deep" ? "deep" : "fast",
|
|
@@ -198997,11 +199005,11 @@ function knowledgeRoutes(service, options = {}) {
|
|
|
198997
199005
|
});
|
|
198998
199006
|
};
|
|
198999
199007
|
}
|
|
199000
|
-
var
|
|
199008
|
+
var import_node_crypto32, KNOWLEDGE_WORKORDER_ACTIONS;
|
|
199001
199009
|
var init_routes = __esm({
|
|
199002
199010
|
"../server/src/domains/knowledge/routes.ts"() {
|
|
199003
199011
|
"use strict";
|
|
199004
|
-
|
|
199012
|
+
import_node_crypto32 = require("node:crypto");
|
|
199005
199013
|
init_src7();
|
|
199006
199014
|
init_router();
|
|
199007
199015
|
init_governance_service();
|
|
@@ -200629,7 +200637,7 @@ async function resolveChatAttachmentDiscoverySource(input) {
|
|
|
200629
200637
|
sourceType: input.sourceType,
|
|
200630
200638
|
sourceId: session.id,
|
|
200631
200639
|
sourceVersionId: attachment.blobRef,
|
|
200632
|
-
sourceFingerprint: (0,
|
|
200640
|
+
sourceFingerprint: (0, import_node_crypto33.createHash)("sha256").update(bytes2).digest("hex"),
|
|
200633
200641
|
sourceContent: new TextDecoder().decode(bytes2),
|
|
200634
200642
|
sourceDisplayName: attachment.name,
|
|
200635
200643
|
...session.projectId ? { projectId: session.projectId } : {},
|
|
@@ -200640,11 +200648,11 @@ async function resolveChatAttachmentDiscoverySource(input) {
|
|
|
200640
200648
|
}
|
|
200641
200649
|
};
|
|
200642
200650
|
}
|
|
200643
|
-
var
|
|
200651
|
+
var import_node_crypto33, TEXT_CONTENT_TYPES;
|
|
200644
200652
|
var init_chat_attachment_discovery = __esm({
|
|
200645
200653
|
"../server/src/domains/knowledge/chat-attachment-discovery.ts"() {
|
|
200646
200654
|
"use strict";
|
|
200647
|
-
|
|
200655
|
+
import_node_crypto33 = require("node:crypto");
|
|
200648
200656
|
TEXT_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
200649
200657
|
"application/json",
|
|
200650
200658
|
"application/xml",
|
|
@@ -200820,8 +200828,8 @@ function aad(snapshot) {
|
|
|
200820
200828
|
}
|
|
200821
200829
|
function sealKnowledgeSnapshot(snapshot, key2) {
|
|
200822
200830
|
if (snapshot.content.startsWith(PREFIX)) return structuredClone(snapshot);
|
|
200823
|
-
const iv = (0,
|
|
200824
|
-
const cipher = (0,
|
|
200831
|
+
const iv = (0, import_node_crypto34.randomBytes)(12);
|
|
200832
|
+
const cipher = (0, import_node_crypto34.createCipheriv)("aes-256-gcm", keyBytes(key2), iv);
|
|
200825
200833
|
cipher.setAAD(aad(snapshot));
|
|
200826
200834
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
200827
200835
|
return {
|
|
@@ -200834,7 +200842,7 @@ function openKnowledgeSnapshot(snapshot, key2) {
|
|
|
200834
200842
|
const packed = snapshot.content.slice(PREFIX.length).split(".");
|
|
200835
200843
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
200836
200844
|
const [iv, tag, data] = packed;
|
|
200837
|
-
const decipher = (0,
|
|
200845
|
+
const decipher = (0, import_node_crypto34.createDecipheriv)("aes-256-gcm", keyBytes(key2), Buffer.from(iv, "base64url"));
|
|
200838
200846
|
decipher.setAAD(aad(snapshot));
|
|
200839
200847
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
200840
200848
|
const content3 = Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8");
|
|
@@ -200843,11 +200851,11 @@ function openKnowledgeSnapshot(snapshot, key2) {
|
|
|
200843
200851
|
function isSealedKnowledgeSnapshotContent(content3) {
|
|
200844
200852
|
return content3.startsWith(PREFIX);
|
|
200845
200853
|
}
|
|
200846
|
-
var
|
|
200854
|
+
var import_node_crypto34, PREFIX;
|
|
200847
200855
|
var init_snapshot_crypto = __esm({
|
|
200848
200856
|
"../server/src/domains/knowledge/snapshot-crypto.ts"() {
|
|
200849
200857
|
"use strict";
|
|
200850
|
-
|
|
200858
|
+
import_node_crypto34 = require("node:crypto");
|
|
200851
200859
|
PREFIX = "oasis-knowledge:v1:";
|
|
200852
200860
|
}
|
|
200853
200861
|
});
|
|
@@ -200930,11 +200938,11 @@ function uniquenessKeys(kind, record9) {
|
|
|
200930
200938
|
return [];
|
|
200931
200939
|
}
|
|
200932
200940
|
}
|
|
200933
|
-
var
|
|
200941
|
+
var import_node_crypto35, import_promises4, import_node_path7, RECORD_KINDS, MemoryKnowledgeGovernanceStore, FileKnowledgeGovernanceStore;
|
|
200934
200942
|
var init_governance_store = __esm({
|
|
200935
200943
|
"../server/src/domains/knowledge/governance-store.ts"() {
|
|
200936
200944
|
"use strict";
|
|
200937
|
-
|
|
200945
|
+
import_node_crypto35 = require("node:crypto");
|
|
200938
200946
|
import_promises4 = require("node:fs/promises");
|
|
200939
200947
|
import_node_path7 = require("node:path");
|
|
200940
200948
|
init_snapshot_crypto();
|
|
@@ -201152,7 +201160,7 @@ var init_governance_store = __esm({
|
|
|
201152
201160
|
return result;
|
|
201153
201161
|
}
|
|
201154
201162
|
async persist(shape) {
|
|
201155
|
-
const temp = `${this.file}.${process.pid}.${(0,
|
|
201163
|
+
const temp = `${this.file}.${process.pid}.${(0, import_node_crypto35.randomUUID)()}.tmp`;
|
|
201156
201164
|
try {
|
|
201157
201165
|
await (0, import_promises4.writeFile)(temp, `${JSON.stringify(this.sealSnapshots(shape), null, 2)}
|
|
201158
201166
|
`, { mode: 384 });
|
|
@@ -201188,7 +201196,7 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
|
|
|
201188
201196
|
if (error2.code !== "ENOENT") throw error2;
|
|
201189
201197
|
}
|
|
201190
201198
|
await (0, import_promises5.mkdir)((0, import_node_path8.dirname)(file), { recursive: true });
|
|
201191
|
-
const generated = `oasis-${(0,
|
|
201199
|
+
const generated = `oasis-${(0, import_node_crypto36.randomUUID)()}`;
|
|
201192
201200
|
try {
|
|
201193
201201
|
await (0, import_promises5.writeFile)(file, `${generated}
|
|
201194
201202
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
@@ -201198,11 +201206,11 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
|
|
|
201198
201206
|
return readDeploymentId(file);
|
|
201199
201207
|
}
|
|
201200
201208
|
}
|
|
201201
|
-
var
|
|
201209
|
+
var import_node_crypto36, import_promises5, import_node_path8, VALID_DEPLOYMENT_ID;
|
|
201202
201210
|
var init_deployment_id = __esm({
|
|
201203
201211
|
"../server/src/domains/knowledge/deployment-id.ts"() {
|
|
201204
201212
|
"use strict";
|
|
201205
|
-
|
|
201213
|
+
import_node_crypto36 = require("node:crypto");
|
|
201206
201214
|
import_promises5 = require("node:fs/promises");
|
|
201207
201215
|
import_node_path8 = require("node:path");
|
|
201208
201216
|
VALID_DEPLOYMENT_ID = /^oasis-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
@@ -202083,7 +202091,7 @@ function roundFailureText(kind, error2) {
|
|
|
202083
202091
|
return kind === "timeout" ? `\u8FD9\u4E00\u6B21\u6267\u884C\u8DD1\u6EE1\u4E86\u5355\u6B21\u8FD0\u884C\u7684\u65F6\u95F4\u4E0A\u9650\uFF08${wallClockText()}\uFF09\uFF0C\u88AB\u7CFB\u7EDF\u505C\u4E0B\u4E86\uFF08${error2}\uFF09` : `\u8FD9\u4E00\u8F6E\u6CA1\u8DD1\u5B8C\uFF1A${error2}`;
|
|
202084
202092
|
}
|
|
202085
202093
|
function deterministicUuid2(seed) {
|
|
202086
|
-
const h = (0,
|
|
202094
|
+
const h = (0, import_node_crypto37.createHash)("sha256").update(seed).digest();
|
|
202087
202095
|
const b2 = Buffer.from(h.subarray(0, 16));
|
|
202088
202096
|
b2[6] = b2[6] & 15 | 80;
|
|
202089
202097
|
b2[8] = b2[8] & 63 | 128;
|
|
@@ -202138,11 +202146,11 @@ async function seedChildRoundRows(chatStore, childSessionId, round, prompt2, now
|
|
|
202138
202146
|
createdAt: now
|
|
202139
202147
|
});
|
|
202140
202148
|
}
|
|
202141
|
-
var
|
|
202149
|
+
var import_node_crypto37, DelegationError, DIGEST_CHARS, PENDING_QUEUE_OWNER, DISPATCH_LEASE_MS, CONSECUTIVE_FAIL_LIMIT, roundTurnKey, roundTurnId, DelegationService;
|
|
202142
202150
|
var init_service3 = __esm({
|
|
202143
202151
|
"../server/src/domains/delegations/service.ts"() {
|
|
202144
202152
|
"use strict";
|
|
202145
|
-
|
|
202153
|
+
import_node_crypto37 = require("node:crypto");
|
|
202146
202154
|
init_src();
|
|
202147
202155
|
init_chat_exit();
|
|
202148
202156
|
init_parent_conversation();
|
|
@@ -203450,7 +203458,7 @@ var init_continue_outcome = __esm({
|
|
|
203450
203458
|
function trustedDelegationInvocationId(body2, turn) {
|
|
203451
203459
|
const scope2 = turn?.artifactId ?? turn?.dispatchId;
|
|
203452
203460
|
if (!scope2) return void 0;
|
|
203453
|
-
const fingerprint2 = (0,
|
|
203461
|
+
const fingerprint2 = (0, import_node_crypto38.createHash)("sha256").update(JSON.stringify({ to: body2.to?.trim() ?? "", task: body2.task ?? "", as: body2.as?.trim() ?? "", files: body2.files ?? [] })).digest("hex").slice(0, 20);
|
|
203454
203462
|
return `dispatch:${scope2}:delegation:${fingerprint2}`;
|
|
203455
203463
|
}
|
|
203456
203464
|
function callerOf(req, invocationId) {
|
|
@@ -203545,11 +203553,11 @@ function delegationRoutes(service) {
|
|
|
203545
203553
|
});
|
|
203546
203554
|
};
|
|
203547
203555
|
}
|
|
203548
|
-
var
|
|
203556
|
+
var import_node_crypto38;
|
|
203549
203557
|
var init_routes2 = __esm({
|
|
203550
203558
|
"../server/src/domains/delegations/routes.ts"() {
|
|
203551
203559
|
"use strict";
|
|
203552
|
-
|
|
203560
|
+
import_node_crypto38 = require("node:crypto");
|
|
203553
203561
|
init_router();
|
|
203554
203562
|
init_continue_outcome();
|
|
203555
203563
|
init_service3();
|
|
@@ -204460,6 +204468,60 @@ var init_child_live_turn = __esm({
|
|
|
204460
204468
|
}
|
|
204461
204469
|
});
|
|
204462
204470
|
|
|
204471
|
+
// ../server/src/domains/actors/registry-audit-sink.ts
|
|
204472
|
+
function createRegistryAuditSink(file) {
|
|
204473
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
204474
|
+
const notify = (msg) => {
|
|
204475
|
+
for (const listener of listeners) listener(msg);
|
|
204476
|
+
};
|
|
204477
|
+
return {
|
|
204478
|
+
/** 登记审计:落盘 + 推 registry 通知(前端据此重拉登记类投影)。 */
|
|
204479
|
+
registryAudit: (record9) => {
|
|
204480
|
+
fs20.appendFile(file, JSON.stringify(record9) + "\n", () => {
|
|
204481
|
+
});
|
|
204482
|
+
notify({ kind: record9.kind, actor: record9.actor, target: record9.target, timestamp: record9.timestamp });
|
|
204483
|
+
},
|
|
204484
|
+
/**
|
|
204485
|
+
* 凭据审计(ADR 凭据保险库 §4.7):与登记审计同落一份旁账,按 kind 前缀 `credential_` 区分。
|
|
204486
|
+
*
|
|
204487
|
+
* **只落盘、不推 registry 通知**(D-10 推送面)。registry 通知是实例级的,`/api/events` 原样转发给
|
|
204488
|
+
* 任何已认证的连接、不分组织;凭据事件推进去 = 别家组织开一条 SSE 就能实时看到「谁在读/改哪个变量」。
|
|
204489
|
+
* 仓内没有任何消费方订它(2.0 前端只订无内容的 runtime-status,而后者本来就不被凭据事件唤醒)。
|
|
204490
|
+
* 要看凭据审计走 `GET /api/variables/reveal-audit`(按请求方组织过滤)。将来若需要实时推送,
|
|
204491
|
+
* 得先让通知带组织、`/api/events` 按组织过滤(recvvzbhOGiS7l 的完整修复),再放回来。
|
|
204492
|
+
*/
|
|
204493
|
+
credentialAudit: (record9) => {
|
|
204494
|
+
fs20.appendFile(file, JSON.stringify(record9) + "\n", () => {
|
|
204495
|
+
});
|
|
204496
|
+
},
|
|
204497
|
+
/** runtime 状态变了:只发无内容的失效提示(ADR 0576)。 */
|
|
204498
|
+
notifyRuntimeStatus: () => {
|
|
204499
|
+
notify({ kind: "runtime_status_changed", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
204500
|
+
},
|
|
204501
|
+
/** 这些人的铃铛有新通知了:各发一条无内容的失效提示,前端据此重拉台账、弹页内提示。 */
|
|
204502
|
+
notifyNotificationsChanged: (recipients) => {
|
|
204503
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
204504
|
+
for (const target of new Set(recipients)) notify({ kind: NOTIFICATIONS_CHANGED, target, timestamp });
|
|
204505
|
+
},
|
|
204506
|
+
notifications: {
|
|
204507
|
+
subscribe(listener) {
|
|
204508
|
+
listeners.add(listener);
|
|
204509
|
+
return () => {
|
|
204510
|
+
listeners.delete(listener);
|
|
204511
|
+
};
|
|
204512
|
+
}
|
|
204513
|
+
}
|
|
204514
|
+
};
|
|
204515
|
+
}
|
|
204516
|
+
var fs20, NOTIFICATIONS_CHANGED;
|
|
204517
|
+
var init_registry_audit_sink = __esm({
|
|
204518
|
+
"../server/src/domains/actors/registry-audit-sink.ts"() {
|
|
204519
|
+
"use strict";
|
|
204520
|
+
fs20 = __toESM(require("node:fs"), 1);
|
|
204521
|
+
NOTIFICATIONS_CHANGED = "notifications_changed";
|
|
204522
|
+
}
|
|
204523
|
+
});
|
|
204524
|
+
|
|
204463
204525
|
// ../connectors/src/_base/wrapper-assets.ts
|
|
204464
204526
|
function isUsableWrapper(scriptPath) {
|
|
204465
204527
|
if (!(0, import_node_fs7.existsSync)(scriptPath)) return false;
|
|
@@ -205588,7 +205650,7 @@ function createAppJwt(appId, privateKeyPem, nowMs) {
|
|
|
205588
205650
|
exp: nowSec + JWT_TTL_SEC,
|
|
205589
205651
|
iss: appId
|
|
205590
205652
|
}));
|
|
205591
|
-
const signer = (0,
|
|
205653
|
+
const signer = (0, import_node_crypto39.createSign)("RSA-SHA256");
|
|
205592
205654
|
signer.update(`${header}.${payload2}`);
|
|
205593
205655
|
signer.end();
|
|
205594
205656
|
try {
|
|
@@ -205751,11 +205813,11 @@ async function exchangeManifestCode(code2, deps = {}) {
|
|
|
205751
205813
|
...typeof body2["client_secret"] === "string" ? { clientSecret: body2["client_secret"] } : {}
|
|
205752
205814
|
};
|
|
205753
205815
|
}
|
|
205754
|
-
var
|
|
205816
|
+
var import_node_crypto39, GITHUB_API, JWT_TTL_SEC, JWT_IAT_SKEW_SEC, defaultDeps2;
|
|
205755
205817
|
var init_app_auth = __esm({
|
|
205756
205818
|
"../connectors/src/github/app-auth.ts"() {
|
|
205757
205819
|
"use strict";
|
|
205758
|
-
|
|
205820
|
+
import_node_crypto39 = require("node:crypto");
|
|
205759
205821
|
GITHUB_API = "https://api.github.com";
|
|
205760
205822
|
JWT_TTL_SEC = 9 * 60;
|
|
205761
205823
|
JWT_IAT_SKEW_SEC = 60;
|
|
@@ -206680,11 +206742,11 @@ function extractOutlineKnowledgeCandidateDrafts(events) {
|
|
|
206680
206742
|
}
|
|
206681
206743
|
return [...drafts.values()];
|
|
206682
206744
|
}
|
|
206683
|
-
var
|
|
206745
|
+
var import_node_crypto40, REQUEST_TIMEOUT_MS, WRITE_ENDPOINTS, DEFAULT_WRITE_INTERVAL_MS, DEFAULT_RATE_LIMIT_RETRIES, DEFAULT_MAX_RATE_LIMIT_DELAY_MS, OutlineKnowledgeApiError, writeCoordinators, OutlineKnowledgeApi, INIT_DEFINITIONS, REPAIRABLE_LINT_CODES;
|
|
206684
206746
|
var init_knowledge_api = __esm({
|
|
206685
206747
|
"../connectors/src/outline/knowledge-api.ts"() {
|
|
206686
206748
|
"use strict";
|
|
206687
|
-
|
|
206749
|
+
import_node_crypto40 = require("node:crypto");
|
|
206688
206750
|
REQUEST_TIMEOUT_MS = 2e4;
|
|
206689
206751
|
WRITE_ENDPOINTS = /* @__PURE__ */ new Set(["collections.create", "documents.create", "documents.update", "documents.publish"]);
|
|
206690
206752
|
DEFAULT_WRITE_INTERVAL_MS = process.env["NODE_ENV"] === "test" ? 0 : 250;
|
|
@@ -206711,7 +206773,7 @@ var init_knowledge_api = __esm({
|
|
|
206711
206773
|
this.baseUrl = canonicalUrl(baseUrl);
|
|
206712
206774
|
this.lastResponseBaseUrl = this.baseUrl;
|
|
206713
206775
|
this.token = token;
|
|
206714
|
-
this.coordinatorKey = `${this.baseUrl}:${(0,
|
|
206776
|
+
this.coordinatorKey = `${this.baseUrl}:${(0, import_node_crypto40.createHash)("sha256").update(token).digest("hex")}`;
|
|
206715
206777
|
this.writeIntervalMs = Math.max(0, options.writeIntervalMs ?? DEFAULT_WRITE_INTERVAL_MS);
|
|
206716
206778
|
this.maxRateLimitRetries = Math.max(0, options.maxRateLimitRetries ?? DEFAULT_RATE_LIMIT_RETRIES);
|
|
206717
206779
|
this.maxRateLimitDelayMs = Math.max(0, options.maxRateLimitDelayMs ?? DEFAULT_MAX_RATE_LIMIT_DELAY_MS);
|
|
@@ -208119,15 +208181,15 @@ function classifyOutlineGovernedMigrationDocument(document4) {
|
|
|
208119
208181
|
if (path46.startsWith("wiki/sources/")) return { mapping: "formal", metadata: legacyMetadata(document4, "source_note"), reason: "legacy_source_note" };
|
|
208120
208182
|
return { mapping: "excluded", reason: "legacy_unmapped_path" };
|
|
208121
208183
|
}
|
|
208122
|
-
var
|
|
208184
|
+
var import_node_crypto41, value, text4, hash, REVISION_VISIBILITY_RETRY_DELAYS_MS, governedProvisionRuns, PUBLISH_MARKER2, PUBLISH_MARKER_PRESENT;
|
|
208123
208185
|
var init_governed_knowledge = __esm({
|
|
208124
208186
|
"../connectors/src/outline/governed-knowledge.ts"() {
|
|
208125
208187
|
"use strict";
|
|
208126
|
-
|
|
208188
|
+
import_node_crypto41 = require("node:crypto");
|
|
208127
208189
|
init_knowledge_api();
|
|
208128
208190
|
value = (input) => input && typeof input === "object" && !Array.isArray(input) ? input : null;
|
|
208129
208191
|
text4 = (input) => typeof input === "string" && input.trim() ? input.trim() : null;
|
|
208130
|
-
hash = (input) => (0,
|
|
208192
|
+
hash = (input) => (0, import_node_crypto41.createHash)("sha256").update(input.normalize("NFC").replace(/\r\n?/gu, "\n")).digest("hex");
|
|
208131
208193
|
REVISION_VISIBILITY_RETRY_DELAYS_MS = [0, 100, 250, 500, 1e3, 2e3];
|
|
208132
208194
|
governedProvisionRuns = /* @__PURE__ */ new Map();
|
|
208133
208195
|
PUBLISH_MARKER2 = /\n?<!--\s*oasis-publish:[\s\S]*?-->\n?/giu;
|
|
@@ -208385,7 +208447,9 @@ function buildAppManifest(args) {
|
|
|
208385
208447
|
default_permissions: { ...GITHUB_APP_DEFAULT_PERMISSIONS },
|
|
208386
208448
|
// 暂不订阅 webhook:本方案只需要主动调 API,开着反而多一份要维护的密钥与端点。
|
|
208387
208449
|
hook_attributes: { url: `${base}/api/connectors/github/app/webhook`, active: false },
|
|
208388
|
-
callback_urls: [`${base}/api/connectors/github/app/oauth-callback`]
|
|
208450
|
+
callback_urls: [`${base}/api/connectors/github/app/oauth-callback`],
|
|
208451
|
+
setup_url: `${base}${args.setupPath}`,
|
|
208452
|
+
setup_on_update: true
|
|
208389
208453
|
};
|
|
208390
208454
|
}
|
|
208391
208455
|
function manifestFormAction(owner, state) {
|
|
@@ -208454,7 +208518,7 @@ function checkAppOwnership(conv, want) {
|
|
|
208454
208518
|
}
|
|
208455
208519
|
return null;
|
|
208456
208520
|
}
|
|
208457
|
-
var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS,
|
|
208521
|
+
var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, REQUIRED_WRITE_PERMISSIONS, PERMISSION_RANK, FORBIDDEN_IMPORT_PERMISSION_KEYS;
|
|
208458
208522
|
var init_app_manifest = __esm({
|
|
208459
208523
|
"../connectors/src/github/app-manifest.ts"() {
|
|
208460
208524
|
"use strict";
|
|
@@ -208487,31 +208551,6 @@ var init_app_manifest = __esm({
|
|
|
208487
208551
|
{ key: "issues", label: "Issue\uFF08\u8BFB\u5199\uFF09", desc: "\u521B\u5EFA\u4E0E\u8BC4\u8BBA Issue" }
|
|
208488
208552
|
];
|
|
208489
208553
|
PENDING_TTL_MS = 15 * 60 * 1e3;
|
|
208490
|
-
PendingAppCreations = class {
|
|
208491
|
-
map = /* @__PURE__ */ new Map();
|
|
208492
|
-
put(state, v2) {
|
|
208493
|
-
this.sweep(v2.createdAtMs);
|
|
208494
|
-
this.map.set(state, v2);
|
|
208495
|
-
}
|
|
208496
|
-
get(state, nowMs) {
|
|
208497
|
-
const v2 = this.map.get(state);
|
|
208498
|
-
if (!v2) return void 0;
|
|
208499
|
-
if (nowMs - v2.createdAtMs > PENDING_TTL_MS) {
|
|
208500
|
-
this.map.delete(state);
|
|
208501
|
-
return void 0;
|
|
208502
|
-
}
|
|
208503
|
-
return v2;
|
|
208504
|
-
}
|
|
208505
|
-
/** 过期条目清理——每次写入顺带做,不另起定时器。 */
|
|
208506
|
-
sweep(nowMs) {
|
|
208507
|
-
for (const [k2, v2] of this.map) {
|
|
208508
|
-
if (nowMs - v2.createdAtMs > PENDING_TTL_MS) this.map.delete(k2);
|
|
208509
|
-
}
|
|
208510
|
-
}
|
|
208511
|
-
get size() {
|
|
208512
|
-
return this.map.size;
|
|
208513
|
-
}
|
|
208514
|
-
};
|
|
208515
208554
|
REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
|
|
208516
208555
|
PERMISSION_RANK = { read: 1, write: 2, admin: 3 };
|
|
208517
208556
|
FORBIDDEN_IMPORT_PERMISSION_KEYS = [
|
|
@@ -208995,6 +209034,16 @@ var init_src8 = __esm({
|
|
|
208995
209034
|
function isBundleFrozen(err) {
|
|
208996
209035
|
return typeof err === "object" && err !== null && err.code === "TENANT_BUNDLE_FROZEN";
|
|
208997
209036
|
}
|
|
209037
|
+
async function lookupGithubAppPending(store, state) {
|
|
209038
|
+
const missing = "\u627E\u4E0D\u5230\u8FD9\u6B21\u8FDE\u63A5\u7684\u8BB0\u5F55\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u70B9\u4E00\u6B21\u300C\u8FDE\u63A5\u300D";
|
|
209039
|
+
if (!store || !state) return { message: missing };
|
|
209040
|
+
const hit = await store.get(state, Date.now());
|
|
209041
|
+
if (hit.status === "expired") {
|
|
209042
|
+
return { message: "\u8FD9\u6B21\u8FDE\u63A5\u4ECE\u5F00\u59CB\u5230\u73B0\u5728\u5DF2\u8D85\u8FC7 15 \u5206\u949F\uFF0C\u5DF2\u7ECF\u5931\u6548\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u70B9\u4E00\u6B21\u300C\u8FDE\u63A5\u300D" };
|
|
209043
|
+
}
|
|
209044
|
+
if (hit.status === "missing") return { message: missing };
|
|
209045
|
+
return { pending: hit.value.value, message: "" };
|
|
209046
|
+
}
|
|
208998
209047
|
function resolveCallbackBase(supplied, requestHost) {
|
|
208999
209048
|
if (!supplied || !supplied.trim()) {
|
|
209000
209049
|
throw new Error("\u7F3A\u5C11 callbackBase\uFF1A\u524D\u7AEF\u9700\u62A5\u4E0A window.location.origin + API_BASE");
|
|
@@ -210769,7 +210818,7 @@ async function startOasisServer(opts) {
|
|
|
210769
210818
|
}
|
|
210770
210819
|
return void 0;
|
|
210771
210820
|
}
|
|
210772
|
-
const appendNowThroughQueue2 = async (sid, text7, clientKey, attachments, perCompanyStore, retainLocallyOnFailure = false, onAwaitingConsumption, resend = false, itemStore) => {
|
|
210821
|
+
const appendNowThroughQueue2 = async (sid, text7, clientKey, attachments, perCompanyStore, retainLocallyOnFailure = false, onAwaitingConsumption, resend = false, itemStore, clientAttached) => {
|
|
210773
210822
|
if (perCompanyStore === null) {
|
|
210774
210823
|
throw new Error(
|
|
210775
210824
|
`appendNowThroughQueue: per-company chat store unresolved (sid=${sid})`
|
|
@@ -210802,52 +210851,22 @@ async function startOasisServer(opts) {
|
|
|
210802
210851
|
}
|
|
210803
210852
|
}
|
|
210804
210853
|
throw new Error(`blob ${blobRef} \u4E24\u4E2A\u67DC\u91CC\u90FD\u6CA1\u6709`);
|
|
210805
|
-
}
|
|
210854
|
+
},
|
|
210855
|
+
...clientAttached ? { clientAttached } : {}
|
|
210806
210856
|
}, clientKey, attachments, retainLocallyOnFailure, resend ? { resend: true } : void 0);
|
|
210807
|
-
if (r.insertStatus === "uncertain" && clientKey) {
|
|
210857
|
+
if ((r.insertStatus === "uncertain" || r.orphanedReturn) && clientKey) {
|
|
210808
210858
|
const shown = r.batch.map((m2) => m2.text).filter(Boolean).join("\n\n") || text7;
|
|
210809
|
-
await landUndeliveredInsert(
|
|
210810
|
-
|
|
210811
|
-
|
|
210812
|
-
|
|
210813
|
-
|
|
210814
|
-
|
|
210815
|
-
|
|
210816
|
-
|
|
210817
|
-
items: itemStore,
|
|
210818
|
-
versionSeed: await itemStore.sessionVersionCursor(sid).catch(() => 0),
|
|
210819
|
-
sessionId: sid,
|
|
210820
|
-
turnId: fallbackTurnId(),
|
|
210821
|
-
log: (m2) => console.warn(m2)
|
|
210822
|
-
});
|
|
210823
|
-
const refs = attachments.map((a) => ({
|
|
210824
|
-
name: a.name,
|
|
210825
|
-
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
210826
|
-
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
210827
|
-
}));
|
|
210828
|
-
ledger.recordRejectedSubmission({
|
|
210829
|
-
user: { text: text7, clientSubmitId: clientKey, ...refs.length ? { attachments: refs } : {} },
|
|
210830
|
-
// 文案取自 turn-copy 那一句的前半(ADR 0615 决策 10):行为上「不确定」与「没送到」完全一样
|
|
210831
|
-
// (都不自动发、都等人点),所以只差这一句话。
|
|
210832
|
-
failure: { reason: INSERT_UNCERTAIN_NOTE, retryable: true }
|
|
210833
|
-
});
|
|
210834
|
-
await ledger.drain();
|
|
210835
|
-
if (ledger.failures > 0) return;
|
|
210836
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
210837
|
-
await store.appendMessage({
|
|
210838
|
-
id: (0, import_node_crypto41.randomUUID)(),
|
|
210839
|
-
sessionId: sid,
|
|
210840
|
-
role: "user",
|
|
210841
|
-
content: text7,
|
|
210842
|
-
createdAt: now,
|
|
210843
|
-
messageKey: chatSubmitMessageKey(sid, clientKey),
|
|
210844
|
-
...refs.length ? { attachments: refs } : {},
|
|
210845
|
-
needsAgentDelivery: true
|
|
210859
|
+
await landUndeliveredInsert({
|
|
210860
|
+
store,
|
|
210861
|
+
itemStore,
|
|
210862
|
+
chatSessionId: sid,
|
|
210863
|
+
clientKey,
|
|
210864
|
+
text: shown,
|
|
210865
|
+
attachments: attachments ?? [],
|
|
210866
|
+
note: r.orphanedReturn ? INSERT_RETURNED_NOTE : INSERT_UNCERTAIN_NOTE
|
|
210846
210867
|
});
|
|
210847
|
-
await store.updateSession(sid, { touchedAt: now }).catch(() => void 0);
|
|
210848
|
-
} catch (err) {
|
|
210849
|
-
console.warn(`[chat] \u63D2\u8BDD\u7ED3\u679C\u4E0D\u786E\u5B9A\u3001\u843D\u672A\u9001\u8FBE user \u884C\u5931\u8D25\uFF08session=${sid} key=${clientKey}\uFF09: ${String(err)}`);
|
|
210850
210868
|
}
|
|
210869
|
+
return { accepted: r.accepted, ...r.reason ? { reason: r.reason } : {}, queued: r.queued, insertStatus: r.insertStatus };
|
|
210851
210870
|
};
|
|
210852
210871
|
const GRAPH_EDIT_SUMMARY_MAX = 60;
|
|
210853
210872
|
const truncateSummary = (s2) => {
|
|
@@ -211109,10 +211128,10 @@ async function startOasisServer(opts) {
|
|
|
211109
211128
|
...fp(p2)
|
|
211110
211129
|
}))
|
|
211111
211130
|
] : [];
|
|
211112
|
-
const { randomUUID:
|
|
211131
|
+
const { randomUUID: randomUUID48 } = await import("node:crypto");
|
|
211113
211132
|
try {
|
|
211114
211133
|
await store.enqueuePendingMessage({
|
|
211115
|
-
id:
|
|
211134
|
+
id: randomUUID48(),
|
|
211116
211135
|
chatSessionId: input.chatSessionId,
|
|
211117
211136
|
text: input.text,
|
|
211118
211137
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -211145,11 +211164,11 @@ async function startOasisServer(opts) {
|
|
|
211145
211164
|
...f2?.mtime ? { srcMtime: f2.mtime } : {}
|
|
211146
211165
|
};
|
|
211147
211166
|
});
|
|
211148
|
-
const { randomUUID:
|
|
211167
|
+
const { randomUUID: randomUUID48 } = await import("node:crypto");
|
|
211149
211168
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
211150
211169
|
try {
|
|
211151
211170
|
await store.enqueuePendingMessage({
|
|
211152
|
-
id:
|
|
211171
|
+
id: randomUUID48(),
|
|
211153
211172
|
chatSessionId: input.chatSessionId,
|
|
211154
211173
|
text: "",
|
|
211155
211174
|
createdAt: nowIso,
|
|
@@ -211559,7 +211578,7 @@ async function startOasisServer(opts) {
|
|
|
211559
211578
|
return;
|
|
211560
211579
|
}
|
|
211561
211580
|
if (url.pathname.startsWith("/api/files/")) {
|
|
211562
|
-
const company = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
211581
|
+
const company = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname, req.method) : void 0;
|
|
211563
211582
|
if (company?.kind === "ambiguous") {
|
|
211564
211583
|
writeApiError(res, companyAmbiguousError(actor, company.companies));
|
|
211565
211584
|
return;
|
|
@@ -211596,7 +211615,7 @@ async function startOasisServer(opts) {
|
|
|
211596
211615
|
return;
|
|
211597
211616
|
}
|
|
211598
211617
|
const sessionKey = (req.headers.authorization ?? "").startsWith("Bearer ") ? req.headers.authorization.slice("Bearer ".length) : actor;
|
|
211599
|
-
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
|
|
211618
|
+
const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname, req.method) : void 0;
|
|
211600
211619
|
const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
|
|
211601
211620
|
const fileLimits = await opts.fileLimits?.get(currentCompanyId) ?? { ...DEFAULT_FILE_LIMITS };
|
|
211602
211621
|
const requestMaxBytes = fileUploadRequestMaxBytes(fileLimits);
|
|
@@ -212451,7 +212470,7 @@ async function startOasisServer(opts) {
|
|
|
212451
212470
|
entry = {
|
|
212452
212471
|
// 旧 CLI 未带 waiterId 时给它塞一个服务端本地生成的——它绝不可能出现在 leave 上,
|
|
212453
212472
|
// 也就绝不会误命中 leftWaiterIds、绝不会被别人的 leave 摘掉。行为与旧 CLI 相同。
|
|
212454
|
-
waiterId: clientWaiterId ?? `server:${(0,
|
|
212473
|
+
waiterId: clientWaiterId ?? `server:${(0, import_node_crypto42.randomUUID)()}`,
|
|
212455
212474
|
onResolve,
|
|
212456
212475
|
expiresAt: expiresAt2,
|
|
212457
212476
|
cleanup: () => clearTimeout(expiryTimer),
|
|
@@ -212532,7 +212551,7 @@ async function startOasisServer(opts) {
|
|
|
212532
212551
|
const openRoom = async () => {
|
|
212533
212552
|
let chatSessionId2;
|
|
212534
212553
|
if (chatStore) {
|
|
212535
|
-
const { randomUUID:
|
|
212554
|
+
const { randomUUID: randomUUID48 } = await import("node:crypto");
|
|
212536
212555
|
const known = discussSessions.get(itemKey);
|
|
212537
212556
|
const knownSession = known ? await chatStore.getSession(known) : null;
|
|
212538
212557
|
if (knownSession && knownSession.workspace === ctx.workspace && knownSession.humanActorId === ctx.ownerId && (!body2.escalationId || knownSession.escalationId === body2.escalationId)) chatSessionId2 = known;
|
|
@@ -212541,7 +212560,7 @@ async function startOasisServer(opts) {
|
|
|
212541
212560
|
chatSessionId2 = existing[0]?.id;
|
|
212542
212561
|
}
|
|
212543
212562
|
if (!chatSessionId2) {
|
|
212544
|
-
chatSessionId2 =
|
|
212563
|
+
chatSessionId2 = randomUUID48();
|
|
212545
212564
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
212546
212565
|
const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
|
|
212547
212566
|
const reg0 = (await resolveEngine(currentCompanyId).catch(() => null))?.registry ?? opts.registry;
|
|
@@ -212796,6 +212815,19 @@ async function startOasisServer(opts) {
|
|
|
212796
212815
|
changed();
|
|
212797
212816
|
return;
|
|
212798
212817
|
}
|
|
212818
|
+
if (topics?.size === 1 && topics.has("notifications")) {
|
|
212819
|
+
const changed = () => res.write('data: {"channel":"notifications"}\n\n');
|
|
212820
|
+
const unsubscribe = opts.notifications?.subscribe((n) => {
|
|
212821
|
+
if (n.kind === NOTIFICATIONS_CHANGED && n.target === actor) changed();
|
|
212822
|
+
});
|
|
212823
|
+
const heartbeat = setInterval(() => res.write(":heartbeat\n\n"), 15e3);
|
|
212824
|
+
req.on("close", () => {
|
|
212825
|
+
clearInterval(heartbeat);
|
|
212826
|
+
unsubscribe?.();
|
|
212827
|
+
});
|
|
212828
|
+
changed();
|
|
212829
|
+
return;
|
|
212830
|
+
}
|
|
212799
212831
|
const wantRegistry = topics === null || topics.has("registry");
|
|
212800
212832
|
const wsAllowed = (ws) => topics === null || ws !== void 0 && topics.has(ws);
|
|
212801
212833
|
let closed = false;
|
|
@@ -212804,9 +212836,10 @@ async function startOasisServer(opts) {
|
|
|
212804
212836
|
|
|
212805
212837
|
`);
|
|
212806
212838
|
};
|
|
212807
|
-
const unsubNotify = wantRegistry ? opts.notifications?.subscribe(
|
|
212808
|
-
|
|
212809
|
-
|
|
212839
|
+
const unsubNotify = wantRegistry ? opts.notifications?.subscribe((n) => {
|
|
212840
|
+
if (n.kind === NOTIFICATIONS_CHANGED) return;
|
|
212841
|
+
send({ channel: "registry", kind: n.kind, actor: n.actor, target: n.target, timestamp: n.timestamp });
|
|
212842
|
+
}) : void 0;
|
|
212810
212843
|
if (engineEvents) {
|
|
212811
212844
|
let lastSeq = 0;
|
|
212812
212845
|
const unsub = engineEvents((records) => {
|
|
@@ -213245,31 +213278,11 @@ async function startOasisServer(opts) {
|
|
|
213245
213278
|
timeoutMs: APPEND_TURN_START_WAIT_MS
|
|
213246
213279
|
});
|
|
213247
213280
|
const appendItemStore = opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems;
|
|
213248
|
-
|
|
213249
|
-
|
|
213250
|
-
|
|
213251
|
-
|
|
213252
|
-
|
|
213253
|
-
const perCompanyStore = await chatStoreNowOrNull();
|
|
213254
|
-
const cs = await perCompanyStore?.getSession(sid).catch(() => null) ?? null;
|
|
213255
|
-
if (!perCompanyStore || !cs || cs.humanActorId !== actor) {
|
|
213256
|
-
res.writeHead(404, { "content-type": "application/json" }).end(JSON.stringify({ error: "CHAT_SESSION_NOT_FOUND" }));
|
|
213257
|
-
return;
|
|
213258
|
-
}
|
|
213259
|
-
const clientKey = url.searchParams.get("clientKey") ?? "";
|
|
213260
|
-
if (!clientKey) {
|
|
213261
|
-
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: "CLIENT_KEY_REQUIRED" }));
|
|
213262
|
-
return;
|
|
213263
|
-
}
|
|
213264
|
-
const items = opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems;
|
|
213265
|
-
const result = await resolveInsertStatus({
|
|
213266
|
-
store: perCompanyStore,
|
|
213267
|
-
isTurnRunning: (id) => liveChat.isRunning(id),
|
|
213268
|
-
...opts.confirmInputReceipt ? { confirm: opts.confirmInputReceipt } : {},
|
|
213269
|
-
...items ? { items } : {},
|
|
213270
|
-
log: (m2) => console.warn(m2)
|
|
213271
|
-
}, sid, clientKey);
|
|
213272
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ clientKey, ...result }));
|
|
213281
|
+
let clientGone = false;
|
|
213282
|
+
res.once("close", () => {
|
|
213283
|
+
if (!res.writableEnded) clientGone = true;
|
|
213284
|
+
});
|
|
213285
|
+
await respondAppend(res, wantsAppendProgress(req), (onAwaitingConsumption) => appendNowThroughQueue2(sid, text7, clientKey, insertAttachments, perCompanyStore, retainLocallyOnFailure, onAwaitingConsumption, resend, appendItemStore, () => !clientGone));
|
|
213273
213286
|
return;
|
|
213274
213287
|
}
|
|
213275
213288
|
if (url.pathname === "/api/chat" && req.method === "POST") {
|
|
@@ -213653,7 +213666,7 @@ ${composed}`;
|
|
|
213653
213666
|
if (rejectedLedger.failures === 0 && retriedRow) {
|
|
213654
213667
|
turnPersisted = true;
|
|
213655
213668
|
} else if (rejectedLedger.failures === 0) {
|
|
213656
|
-
const { randomUUID:
|
|
213669
|
+
const { randomUUID: randomUUID49 } = await import("node:crypto");
|
|
213657
213670
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
213658
213671
|
const rejectedAttachments = effectiveAttachments.map((a) => ({
|
|
213659
213672
|
name: a.name,
|
|
@@ -213661,7 +213674,7 @@ ${composed}`;
|
|
|
213661
213674
|
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
213662
213675
|
}));
|
|
213663
213676
|
await chatStore.appendMessage({
|
|
213664
|
-
id:
|
|
213677
|
+
id: randomUUID49(),
|
|
213665
213678
|
sessionId: persistTarget.id,
|
|
213666
213679
|
role: "user",
|
|
213667
213680
|
content: persistedUserMessage,
|
|
@@ -213746,14 +213759,14 @@ ${composed}`;
|
|
|
213746
213759
|
runtimeSessionId: session.nativeSessionId ?? session.id
|
|
213747
213760
|
}).catch(() => void 0);
|
|
213748
213761
|
}
|
|
213749
|
-
const { randomUUID:
|
|
213762
|
+
const { randomUUID: randomUUID49 } = await import("node:crypto");
|
|
213750
213763
|
const persistAttachments = effectiveAttachments.map((a) => ({
|
|
213751
213764
|
name: a.name,
|
|
213752
213765
|
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
213753
213766
|
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
213754
213767
|
}));
|
|
213755
213768
|
if (!retriedRow) await chatStore.appendMessage({
|
|
213756
|
-
id:
|
|
213769
|
+
id: randomUUID49(),
|
|
213757
213770
|
sessionId: persistTarget.id,
|
|
213758
213771
|
role: "user",
|
|
213759
213772
|
content: persistedUserMessage,
|
|
@@ -214202,8 +214215,8 @@ ${composed}`;
|
|
|
214202
214215
|
}
|
|
214203
214216
|
}
|
|
214204
214217
|
const { spawn: spawn11 } = await import("node:child_process");
|
|
214205
|
-
const { randomUUID:
|
|
214206
|
-
const sessionId = body2.sessionId ??
|
|
214218
|
+
const { randomUUID: randomUUID48 } = await import("node:crypto");
|
|
214219
|
+
const sessionId = body2.sessionId ?? randomUUID48();
|
|
214207
214220
|
const args = [
|
|
214208
214221
|
"-p",
|
|
214209
214222
|
body2.message,
|
|
@@ -214292,33 +214305,32 @@ ${composed}`;
|
|
|
214292
214305
|
}
|
|
214293
214306
|
const svc = await connectorActorsService();
|
|
214294
214307
|
if (!svc) throw new Error("actors service unavailable");
|
|
214295
|
-
const
|
|
214308
|
+
const snapshots2 = opts.connectorAuthPending?.snapshots;
|
|
214309
|
+
if (!snapshots2) throw new Error("connector auth snapshot store unavailable");
|
|
214310
|
+
const snapKey = { companyId: currentCompanyId ?? "", actorId, connectorId };
|
|
214296
214311
|
const now = Date.now();
|
|
214297
|
-
for (const [k2, v2] of connectorAuthSnapshots) {
|
|
214298
|
-
if (now - v2.at > CONNECTOR_AUTH_SNAPSHOT_TTL_MS) connectorAuthSnapshots.delete(k2);
|
|
214299
|
-
}
|
|
214300
214312
|
if (op === "begin") {
|
|
214301
214313
|
const rows = await svc.snapshotActorConnectorVars(actorId, connectorId);
|
|
214302
|
-
|
|
214314
|
+
await snapshots2.put(snapKey, rows, now, now + CONNECTOR_AUTH_SNAPSHOT_TTL_MS);
|
|
214303
214315
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true, snapshot: rows.length }));
|
|
214304
214316
|
return;
|
|
214305
214317
|
}
|
|
214306
214318
|
if (op === "commit") {
|
|
214307
|
-
|
|
214319
|
+
await snapshots2.delete(snapKey);
|
|
214308
214320
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true }));
|
|
214309
214321
|
return;
|
|
214310
214322
|
}
|
|
214311
|
-
const
|
|
214312
|
-
if (!
|
|
214323
|
+
const snapRows = await snapshots2.get(snapKey, now);
|
|
214324
|
+
if (!snapRows) {
|
|
214313
214325
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: false, reason: "no_snapshot" }));
|
|
214314
214326
|
return;
|
|
214315
214327
|
}
|
|
214316
214328
|
const out = await svc.restoreActorConnectorVars(
|
|
214317
214329
|
actorId,
|
|
214318
214330
|
connectorId,
|
|
214319
|
-
|
|
214331
|
+
snapRows
|
|
214320
214332
|
);
|
|
214321
|
-
|
|
214333
|
+
await snapshots2.delete(snapKey);
|
|
214322
214334
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true, ...out }));
|
|
214323
214335
|
} catch (e) {
|
|
214324
214336
|
res.writeHead(500).end(JSON.stringify({ error: String(e) }));
|
|
@@ -214499,24 +214511,35 @@ ${composed}`;
|
|
|
214499
214511
|
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: `\u56DE\u8C03\u5730\u5740\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4E2D\u6B62\uFF08\u907F\u514D\u5728 GitHub \u4E0A\u7559\u4E0B\u5B64\u513F App\uFF09\uFF1A${e.message}` }));
|
|
214500
214512
|
return;
|
|
214501
214513
|
}
|
|
214502
|
-
const { randomUUID:
|
|
214503
|
-
const state =
|
|
214514
|
+
const { randomUUID: randomUUID48 } = await import("node:crypto");
|
|
214515
|
+
const state = randomUUID48();
|
|
214504
214516
|
const nameSlug = (actorName || actorId?.split(":").pop() || owner?.login || "bot").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "bot";
|
|
214505
214517
|
const manifest = buildAppManifest({
|
|
214506
214518
|
employeeSlug: nameSlug,
|
|
214507
214519
|
namePrefix: "oasis",
|
|
214508
214520
|
baseUrl: base,
|
|
214509
|
-
redirectPath: "/api/connectors/github/app/manifest-callback"
|
|
214521
|
+
redirectPath: "/api/connectors/github/app/manifest-callback",
|
|
214522
|
+
setupPath: "/api/connectors/github/app/setup-callback"
|
|
214510
214523
|
});
|
|
214511
|
-
|
|
214524
|
+
const pendingStore = opts.connectorAuthPending?.githubApp;
|
|
214525
|
+
if (!pendingStore) throw new Error("github app pending store unavailable");
|
|
214526
|
+
const createdAtMs = Date.now();
|
|
214527
|
+
const entry = {
|
|
214512
214528
|
...actorId ? { actorId } : {},
|
|
214513
214529
|
// 回调那一步没有鉴权头,解析不出公司——只能在这里记下来带过去。
|
|
214514
214530
|
...currentCompanyId ? { companyId: currentCompanyId } : {},
|
|
214515
214531
|
employeeSlug: nameSlug,
|
|
214516
|
-
createdAtMs
|
|
214532
|
+
createdAtMs,
|
|
214517
214533
|
// 存下这次选的归属——回调时要拿它跟 GitHub 返回的 owner 比对。
|
|
214518
214534
|
wantOwnerKind: kind,
|
|
214519
214535
|
...kind === "org" && owner?.login ? { wantOwnerLogin: owner.login } : {}
|
|
214536
|
+
};
|
|
214537
|
+
await pendingStore.put({
|
|
214538
|
+
state,
|
|
214539
|
+
...currentCompanyId ? { companyId: currentCompanyId } : {},
|
|
214540
|
+
value: { ...entry },
|
|
214541
|
+
createdAtMs,
|
|
214542
|
+
expiresAtMs: createdAtMs + PENDING_TTL_MS
|
|
214520
214543
|
});
|
|
214521
214544
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
214522
214545
|
state,
|
|
@@ -214831,16 +214854,22 @@ ${composed}`;
|
|
|
214831
214854
|
if (url.pathname === "/api/connectors/github/app/manifest-callback" && req.method === "GET") {
|
|
214832
214855
|
const code2 = url.searchParams.get("code") ?? "";
|
|
214833
214856
|
const state = url.searchParams.get("state") ?? "";
|
|
214834
|
-
const
|
|
214835
|
-
const
|
|
214836
|
-
|
|
214837
|
-
|
|
214838
|
-
|
|
214857
|
+
const pendingStore = opts.connectorAuthPending?.githubApp;
|
|
214858
|
+
const found2 = await lookupGithubAppPending(pendingStore, state);
|
|
214859
|
+
const pending = found2.pending;
|
|
214860
|
+
const fail = async (msg) => {
|
|
214861
|
+
if (pending && pendingStore) {
|
|
214862
|
+
await pendingStore.patch(state, { done: true, error: msg }).catch(() => {
|
|
214863
|
+
});
|
|
214839
214864
|
}
|
|
214840
214865
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(callbackHtml(false, msg));
|
|
214841
214866
|
};
|
|
214842
|
-
if (!
|
|
214843
|
-
fail(
|
|
214867
|
+
if (!pending) {
|
|
214868
|
+
await fail(found2.message);
|
|
214869
|
+
return;
|
|
214870
|
+
}
|
|
214871
|
+
if (!code2) {
|
|
214872
|
+
await fail("GitHub \u6CA1\u6709\u5E26\u56DE\u5EFA\u597D\u7684 App \u4FE1\u606F\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u70B9\u4E00\u6B21\u300C\u8FDE\u63A5\u300D");
|
|
214844
214873
|
return;
|
|
214845
214874
|
}
|
|
214846
214875
|
try {
|
|
@@ -214850,7 +214879,7 @@ ${composed}`;
|
|
|
214850
214879
|
...pending.wantOwnerKind ? { ownerKind: pending.wantOwnerKind } : {}
|
|
214851
214880
|
});
|
|
214852
214881
|
if (problem) {
|
|
214853
|
-
fail(problem.message);
|
|
214882
|
+
await fail(problem.message);
|
|
214854
214883
|
return;
|
|
214855
214884
|
}
|
|
214856
214885
|
const svc = await connectorActorsService(pending.companyId);
|
|
@@ -214862,29 +214891,77 @@ ${composed}`;
|
|
|
214862
214891
|
if (conv.slug) await put3("GITHUB_APP_SLUG", conv.slug, false);
|
|
214863
214892
|
if (conv.clientId) await put3("GITHUB_APP_CLIENT_ID", conv.clientId, false);
|
|
214864
214893
|
if (conv.clientSecret) await put3("GITHUB_APP_CLIENT_SECRET", conv.clientSecret, true);
|
|
214865
|
-
|
|
214866
|
-
|
|
214867
|
-
|
|
214868
|
-
|
|
214869
|
-
|
|
214870
|
-
|
|
214871
|
-
|
|
214894
|
+
const progress = {
|
|
214895
|
+
appId: conv.appId,
|
|
214896
|
+
...conv.slug ? { slug: conv.slug } : {},
|
|
214897
|
+
// 收尾那一屏要用:这个 bot 到手的是哪些权限、归属是谁(拼权限设置页地址要 ownerType)。
|
|
214898
|
+
ownerLogin: conv.ownerLogin,
|
|
214899
|
+
ownerType: conv.ownerType,
|
|
214900
|
+
permissions: conv.permissions,
|
|
214901
|
+
account: conv.slug ? `${conv.slug}[bot]` : conv.appId
|
|
214902
|
+
};
|
|
214903
|
+
await pendingStore.patch(state, progress);
|
|
214872
214904
|
if (!conv.slug) {
|
|
214873
214905
|
res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(callbackHtml(false, "App \u5DF2\u521B\u5EFA\uFF0C\u4F46\u672A\u62FF\u5230 slug\u2014\u2014\u8BF7\u624B\u52A8\u5728 GitHub \u4E0A\u5B89\u88C5\u5B83"));
|
|
214874
214906
|
return;
|
|
214875
214907
|
}
|
|
214876
214908
|
res.writeHead(302, { location: appInstallUrl(conv.slug, state) }).end();
|
|
214877
214909
|
} catch (e) {
|
|
214878
|
-
fail(String(e));
|
|
214910
|
+
await fail(String(e));
|
|
214879
214911
|
}
|
|
214880
214912
|
return;
|
|
214881
214913
|
}
|
|
214914
|
+
const finishGithubAppInstall = async (state, pending, pendingStore) => {
|
|
214915
|
+
if (pending.done && pending.error) return { ok: false, error: pending.error };
|
|
214916
|
+
if (pending.done) return { ok: true, ...pending.account ? { account: pending.account } : {} };
|
|
214917
|
+
if (!pending.appId) return { ok: false, error: "pending" };
|
|
214918
|
+
try {
|
|
214919
|
+
const keySvc = await connectorActorsService(pending.companyId);
|
|
214920
|
+
if (!keySvc) throw new Error("actors service unavailable");
|
|
214921
|
+
const privateKeyPem = await keySvc.revealVariable("GITHUB_APP_PRIVATE_KEY", pending.actorId);
|
|
214922
|
+
if (!privateKeyPem) throw new Error("GitHub App \u7684\u79C1\u94A5\u4E0D\u5728\u53D8\u91CF\u91CC\u4E86\uFF08\u53EF\u80FD\u88AB\u5220\u9664\uFF09\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u8FDE\u63A5");
|
|
214923
|
+
const installs = await listAppInstallations({
|
|
214924
|
+
appId: pending.appId,
|
|
214925
|
+
privateKeyPem
|
|
214926
|
+
});
|
|
214927
|
+
const first = installs[0];
|
|
214928
|
+
if (!first) return { ok: false, error: "pending" };
|
|
214929
|
+
const svc = await connectorActorsService(pending.companyId);
|
|
214930
|
+
if (!svc) throw new Error("actors service unavailable");
|
|
214931
|
+
const scope2 = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
214932
|
+
const put3 = (key2, value2, encrypted) => svc.putVariable({ key: key2, value: value2, ...scope2, connectorId: "github", encrypted });
|
|
214933
|
+
await put3("GITHUB_APP_INSTALLATION_ID", first.installationId, false);
|
|
214934
|
+
const minted = await mintInstallationToken({
|
|
214935
|
+
appId: pending.appId,
|
|
214936
|
+
privateKeyPem,
|
|
214937
|
+
installationId: first.installationId
|
|
214938
|
+
});
|
|
214939
|
+
if (pending.actorId) {
|
|
214940
|
+
await put3("GITHUB_APP_TOKEN", minted.token, true);
|
|
214941
|
+
await put3("GITHUB_APP_TOKEN_EXPIRES_AT", String(minted.expiresAtMs), false);
|
|
214942
|
+
}
|
|
214943
|
+
if (pending.slug) {
|
|
214944
|
+
const bot = await fetchAppBotIdentity(pending.slug, { token: minted.token });
|
|
214945
|
+
await put3("GITHUB_APP_BOT_EMAIL", bot?.email ?? "", false);
|
|
214946
|
+
await put3("GITHUB_APP_BOT_NAME", bot?.login ?? `${pending.slug}[bot]`, false);
|
|
214947
|
+
}
|
|
214948
|
+
await pendingStore.patch(state, { done: true });
|
|
214949
|
+
return { ok: true, account: pending.account ?? first.account };
|
|
214950
|
+
} catch (e) {
|
|
214951
|
+
const error2 = String(e);
|
|
214952
|
+
await pendingStore.patch(state, { error: error2 }).catch(() => {
|
|
214953
|
+
});
|
|
214954
|
+
return { ok: false, error: error2 };
|
|
214955
|
+
}
|
|
214956
|
+
};
|
|
214882
214957
|
if (url.pathname === "/api/connectors/github/app/status" && req.method === "POST") {
|
|
214883
|
-
const { state } = JSON.parse(rawBody || "{}");
|
|
214884
|
-
const
|
|
214958
|
+
const { state = "" } = JSON.parse(rawBody || "{}");
|
|
214959
|
+
const pendingStore = opts.connectorAuthPending?.githubApp;
|
|
214960
|
+
const found2 = await lookupGithubAppPending(pendingStore, state);
|
|
214961
|
+
const pending = found2.pending;
|
|
214885
214962
|
const reply = (body2) => res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify(body2));
|
|
214886
|
-
if (!pending) {
|
|
214887
|
-
reply({ ok: false, error:
|
|
214963
|
+
if (!pending || !pendingStore) {
|
|
214964
|
+
reply({ ok: false, error: found2.message });
|
|
214888
214965
|
return;
|
|
214889
214966
|
}
|
|
214890
214967
|
if (pending.error) {
|
|
@@ -214909,46 +214986,28 @@ ${composed}`;
|
|
|
214909
214986
|
reply({ ok: true, account: pending.account, ...permissionView() });
|
|
214910
214987
|
return;
|
|
214911
214988
|
}
|
|
214912
|
-
|
|
214913
|
-
|
|
214989
|
+
const result = await finishGithubAppInstall(state, pending, pendingStore);
|
|
214990
|
+
if (result.ok) reply({ ok: true, account: result.account ?? pending.account, ...permissionView() });
|
|
214991
|
+
else reply({ ok: false, error: result.error });
|
|
214992
|
+
return;
|
|
214993
|
+
}
|
|
214994
|
+
if (url.pathname === "/api/connectors/github/app/setup-callback" && req.method === "GET") {
|
|
214995
|
+
const state = url.searchParams.get("state") ?? "";
|
|
214996
|
+
const html = (ok3, msg) => res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(callbackHtml(ok3, msg));
|
|
214997
|
+
const pendingStore = opts.connectorAuthPending?.githubApp;
|
|
214998
|
+
const found2 = await lookupGithubAppPending(pendingStore, state);
|
|
214999
|
+
if (!found2.pending || !pendingStore) {
|
|
215000
|
+
html(false, state ? found2.message : "GitHub \u4E0A\u7684\u5B89\u88C5\u5DF2\u751F\u6548\uFF1B\u5982\u679C\u63A7\u5236\u53F0\u91CC\u8FD8\u6CA1\u663E\u793A\u5DF2\u8FDE\u63A5\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u70B9\u4E00\u6B21\u300C\u8FDE\u63A5\u300D");
|
|
214914
215001
|
return;
|
|
214915
215002
|
}
|
|
214916
|
-
|
|
214917
|
-
|
|
214918
|
-
|
|
214919
|
-
privateKeyPem: pending.privateKeyPem
|
|
214920
|
-
});
|
|
214921
|
-
const first = installs[0];
|
|
214922
|
-
if (!first) {
|
|
214923
|
-
reply({ ok: false, error: "pending" });
|
|
214924
|
-
return;
|
|
214925
|
-
}
|
|
214926
|
-
const svc = await connectorActorsService();
|
|
214927
|
-
if (!svc) throw new Error("actors service unavailable");
|
|
214928
|
-
const scope2 = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
214929
|
-
const put3 = (key2, value2, encrypted) => svc.putVariable({ key: key2, value: value2, ...scope2, connectorId: "github", encrypted });
|
|
214930
|
-
await put3("GITHUB_APP_INSTALLATION_ID", first.installationId, false);
|
|
214931
|
-
const minted = await mintInstallationToken({
|
|
214932
|
-
appId: pending.appId,
|
|
214933
|
-
privateKeyPem: pending.privateKeyPem,
|
|
214934
|
-
installationId: first.installationId
|
|
214935
|
-
});
|
|
214936
|
-
if (pending.actorId) {
|
|
214937
|
-
await put3("GITHUB_APP_TOKEN", minted.token, true);
|
|
214938
|
-
await put3("GITHUB_APP_TOKEN_EXPIRES_AT", String(minted.expiresAtMs), false);
|
|
214939
|
-
}
|
|
214940
|
-
if (pending.slug) {
|
|
214941
|
-
const bot = await fetchAppBotIdentity(pending.slug, { token: minted.token });
|
|
214942
|
-
await put3("GITHUB_APP_BOT_EMAIL", bot?.email ?? "", false);
|
|
214943
|
-
await put3("GITHUB_APP_BOT_NAME", bot?.login ?? `${pending.slug}[bot]`, false);
|
|
214944
|
-
}
|
|
214945
|
-
pending.done = true;
|
|
214946
|
-
delete pending.privateKeyPem;
|
|
214947
|
-
reply({ ok: true, account: pending.account ?? first.account, ...permissionView() });
|
|
214948
|
-
} catch (e) {
|
|
214949
|
-
pending.error = String(e);
|
|
214950
|
-
reply({ ok: false, error: pending.error });
|
|
215003
|
+
if (url.searchParams.get("setup_action") === "request") {
|
|
215004
|
+
html(false, "\u5DF2\u5411\u7EC4\u7EC7\u7BA1\u7406\u5458\u63D0\u4EA4\u5B89\u88C5\u7533\u8BF7\uFF0C\u6279\u51C6\u540E\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u65B0\u70B9\u4E00\u6B21\u300C\u8FDE\u63A5\u300D");
|
|
215005
|
+
return;
|
|
214951
215006
|
}
|
|
215007
|
+
const result = await finishGithubAppInstall(state, found2.pending, pendingStore);
|
|
215008
|
+
if (result.ok) html(true, `\u5DF2\u8FDE\u63A5\u4E3A ${result.account ?? found2.pending.account ?? "GitHub App"}`);
|
|
215009
|
+
else if (result.error === "pending") html(false, "GitHub \u8FD8\u6CA1\u67E5\u5230\u8FD9\u6B21\u5B89\u88C5\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u7A0D\u540E\u91CD\u8BD5");
|
|
215010
|
+
else html(false, result.error);
|
|
214952
215011
|
return;
|
|
214953
215012
|
}
|
|
214954
215013
|
if (url.pathname === "/api/connectors/feishu/login/start" && req.method === "POST") {
|
|
@@ -215325,14 +215384,14 @@ async function markDeliveredWithRetry(store, messageId, attempts = 3) {
|
|
|
215325
215384
|
}
|
|
215326
215385
|
return false;
|
|
215327
215386
|
}
|
|
215328
|
-
var http,
|
|
215387
|
+
var http, import_node_crypto42, CONNECTOR_AUTH_SNAPSHOT_TTL_MS, defaultResolveActor, enc, CHAT_OUTPUT_LIMIT, APPEND_TURN_START_WAIT_MS, STREAMING_PATHS, PLANNER_BLOCKING_CODES, WILL_VERBS, GOVERNANCE_COMMANDS, READ_ONLY_COMMANDS, isAgent, isHuman;
|
|
215329
215388
|
var init_server3 = __esm({
|
|
215330
215389
|
"../server/src/server.ts"() {
|
|
215331
215390
|
"use strict";
|
|
215332
215391
|
init_src();
|
|
215333
215392
|
init_file_limits2();
|
|
215334
215393
|
http = __toESM(require("node:http"), 1);
|
|
215335
|
-
|
|
215394
|
+
import_node_crypto42 = require("node:crypto");
|
|
215336
215395
|
init_chat_session();
|
|
215337
215396
|
init_chat_system_message();
|
|
215338
215397
|
init_sealed_node_receipt();
|
|
@@ -215364,7 +215423,6 @@ var init_server3 = __esm({
|
|
|
215364
215423
|
init_live_chat();
|
|
215365
215424
|
init_chat_turn_wait();
|
|
215366
215425
|
init_append_now();
|
|
215367
|
-
init_insert_status();
|
|
215368
215426
|
init_append_progress();
|
|
215369
215427
|
init_workorder_drafts();
|
|
215370
215428
|
init_draft_edit();
|
|
@@ -215385,6 +215443,7 @@ var init_server3 = __esm({
|
|
|
215385
215443
|
init_chat_turn_gate();
|
|
215386
215444
|
init_chat_submission();
|
|
215387
215445
|
init_chat_insert_evidence();
|
|
215446
|
+
init_insert_undelivered();
|
|
215388
215447
|
init_chat_workorder_files();
|
|
215389
215448
|
init_chat_item_ledger();
|
|
215390
215449
|
init_chat_cancel_attribution();
|
|
@@ -215396,10 +215455,9 @@ var init_server3 = __esm({
|
|
|
215396
215455
|
init_knowledge2();
|
|
215397
215456
|
init_assembly();
|
|
215398
215457
|
init_child_live_turn();
|
|
215458
|
+
init_registry_audit_sink();
|
|
215399
215459
|
init_src8();
|
|
215400
215460
|
init_continuation3();
|
|
215401
|
-
githubAppPending = new PendingAppCreations();
|
|
215402
|
-
connectorAuthSnapshots = /* @__PURE__ */ new Map();
|
|
215403
215461
|
CONNECTOR_AUTH_SNAPSHOT_TTL_MS = 30 * 60 * 1e3;
|
|
215404
215462
|
defaultResolveActor = (token) => token.startsWith("token:") ? token.slice("token:".length) : null;
|
|
215405
215463
|
enc = (s2) => new TextEncoder().encode(s2);
|
|
@@ -215495,25 +215553,25 @@ function createTokenIssuer(opts = {}) {
|
|
|
215495
215553
|
function createNodeTokenStore(file) {
|
|
215496
215554
|
const read3 = () => {
|
|
215497
215555
|
try {
|
|
215498
|
-
return JSON.parse(
|
|
215556
|
+
return JSON.parse(fs21.readFileSync(file, "utf8"));
|
|
215499
215557
|
} catch {
|
|
215500
215558
|
return {};
|
|
215501
215559
|
}
|
|
215502
215560
|
};
|
|
215503
|
-
const write = (table) =>
|
|
215561
|
+
const write = (table) => fs21.writeFileSync(file, JSON.stringify(table, null, 2), { mode: 384 });
|
|
215504
215562
|
const revokedFile = file.replace(/(\.json)?$/, "-revoked.json");
|
|
215505
215563
|
const readRevoked = () => {
|
|
215506
215564
|
try {
|
|
215507
|
-
return JSON.parse(
|
|
215565
|
+
return JSON.parse(fs21.readFileSync(revokedFile, "utf8"));
|
|
215508
215566
|
} catch {
|
|
215509
215567
|
return {};
|
|
215510
215568
|
}
|
|
215511
215569
|
};
|
|
215512
|
-
const writeRevoked = (table) =>
|
|
215570
|
+
const writeRevoked = (table) => fs21.writeFileSync(revokedFile, JSON.stringify(table, null, 2), { mode: 384 });
|
|
215513
215571
|
return {
|
|
215514
215572
|
issue(nodeId) {
|
|
215515
215573
|
const table = read3();
|
|
215516
|
-
const token = `ont_${(0,
|
|
215574
|
+
const token = `ont_${(0, import_node_crypto43.randomBytes)(24).toString("base64url")}`;
|
|
215517
215575
|
table[token] = nodeId;
|
|
215518
215576
|
write(table);
|
|
215519
215577
|
return token;
|
|
@@ -215553,14 +215611,14 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
215553
215611
|
const read3 = () => {
|
|
215554
215612
|
if (!file) return table;
|
|
215555
215613
|
try {
|
|
215556
|
-
return new Map(Object.entries(JSON.parse(
|
|
215614
|
+
return new Map(Object.entries(JSON.parse(fs21.readFileSync(file, "utf8"))));
|
|
215557
215615
|
} catch {
|
|
215558
215616
|
return /* @__PURE__ */ new Map();
|
|
215559
215617
|
}
|
|
215560
215618
|
};
|
|
215561
215619
|
const write = (m2) => {
|
|
215562
215620
|
if (!file) return;
|
|
215563
|
-
|
|
215621
|
+
fs21.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
|
|
215564
215622
|
};
|
|
215565
215623
|
const table = /* @__PURE__ */ new Map();
|
|
215566
215624
|
const prune = () => {
|
|
@@ -215573,7 +215631,7 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
215573
215631
|
return {
|
|
215574
215632
|
issue(name, ttlMs = defaultTtlMs, companyId) {
|
|
215575
215633
|
const m2 = prune();
|
|
215576
|
-
const token = `ent_${(0,
|
|
215634
|
+
const token = `ent_${(0, import_node_crypto43.randomBytes)(24).toString("base64url")}`;
|
|
215577
215635
|
const expiresAt2 = Date.now() + ttlMs;
|
|
215578
215636
|
m2.set(token, { name, expiresAt: expiresAt2, ...companyId !== void 0 ? { companyId } : {} });
|
|
215579
215637
|
write(m2);
|
|
@@ -215622,33 +215680,33 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
215622
215680
|
}
|
|
215623
215681
|
};
|
|
215624
215682
|
}
|
|
215625
|
-
var
|
|
215683
|
+
var import_node_crypto43, fs21, path20, SESSION_TOKEN_PREFIX, b64url2, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
|
|
215626
215684
|
var init_tokens = __esm({
|
|
215627
215685
|
"../server/src/tokens.ts"() {
|
|
215628
215686
|
"use strict";
|
|
215629
|
-
|
|
215630
|
-
|
|
215687
|
+
import_node_crypto43 = require("node:crypto");
|
|
215688
|
+
fs21 = __toESM(require("node:fs"), 1);
|
|
215631
215689
|
path20 = __toESM(require("node:path"), 1);
|
|
215632
215690
|
SESSION_TOKEN_PREFIX = "oat_v2_";
|
|
215633
215691
|
b64url2 = (value2) => Buffer.from(value2).toString("base64url");
|
|
215634
215692
|
fromB64url = (value2) => Buffer.from(value2, "base64url").toString("utf8");
|
|
215635
215693
|
readOrCreateSecret = (file) => {
|
|
215636
|
-
if (!file) return (0,
|
|
215694
|
+
if (!file) return (0, import_node_crypto43.randomBytes)(32);
|
|
215637
215695
|
try {
|
|
215638
|
-
const raw =
|
|
215696
|
+
const raw = fs21.readFileSync(file, "utf8").trim();
|
|
215639
215697
|
if (raw) return Buffer.from(raw, "base64url");
|
|
215640
215698
|
} catch {
|
|
215641
215699
|
}
|
|
215642
|
-
const secret = (0,
|
|
215643
|
-
|
|
215644
|
-
|
|
215700
|
+
const secret = (0, import_node_crypto43.randomBytes)(32);
|
|
215701
|
+
fs21.mkdirSync(path20.dirname(file), { recursive: true });
|
|
215702
|
+
fs21.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
215645
215703
|
return secret;
|
|
215646
215704
|
};
|
|
215647
|
-
sign = (secret, payload2) => (0,
|
|
215705
|
+
sign = (secret, payload2) => (0, import_node_crypto43.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
215648
215706
|
signatureMatches = (actual, expected) => {
|
|
215649
215707
|
const a = Buffer.from(actual);
|
|
215650
215708
|
const b2 = Buffer.from(expected);
|
|
215651
|
-
return a.length === b2.length && (0,
|
|
215709
|
+
return a.length === b2.length && (0, import_node_crypto43.timingSafeEqual)(a, b2);
|
|
215652
215710
|
};
|
|
215653
215711
|
isTokenClaims = (value2) => {
|
|
215654
215712
|
if (value2 === null || typeof value2 !== "object") return false;
|
|
@@ -215670,6 +215728,9 @@ var init_tokens = __esm({
|
|
|
215670
215728
|
function isOperatorRequest(auth) {
|
|
215671
215729
|
return auth.scopes?.includes(OPERATOR_SCOPE) === true;
|
|
215672
215730
|
}
|
|
215731
|
+
function operatorCrossCompanyRead(auth, method) {
|
|
215732
|
+
return method === "GET" && isOperatorRequest(auth);
|
|
215733
|
+
}
|
|
215673
215734
|
var OPERATOR_SCOPE;
|
|
215674
215735
|
var init_operator = __esm({
|
|
215675
215736
|
"../server/src/auth/operator.ts"() {
|
|
@@ -215707,33 +215768,33 @@ function createDataplaneTokenIssuer(opts = {}) {
|
|
|
215707
215768
|
}
|
|
215708
215769
|
};
|
|
215709
215770
|
}
|
|
215710
|
-
var
|
|
215771
|
+
var import_node_crypto44, fs22, path21, PREFIX2, b64url3, fromB64url2, sign2, sigMatches, readOrCreateSecret2, isClaims, isDataplaneToken;
|
|
215711
215772
|
var init_session_dataplane_token = __esm({
|
|
215712
215773
|
"../server/src/session-dataplane-token.ts"() {
|
|
215713
215774
|
"use strict";
|
|
215714
|
-
|
|
215715
|
-
|
|
215775
|
+
import_node_crypto44 = require("node:crypto");
|
|
215776
|
+
fs22 = __toESM(require("node:fs"), 1);
|
|
215716
215777
|
path21 = __toESM(require("node:path"), 1);
|
|
215717
215778
|
init_src();
|
|
215718
215779
|
PREFIX2 = "osd_";
|
|
215719
215780
|
b64url3 = (v2) => Buffer.from(v2, "utf8").toString("base64url");
|
|
215720
215781
|
fromB64url2 = (v2) => Buffer.from(v2, "base64url").toString("utf8");
|
|
215721
|
-
sign2 = (secret, payload2) => (0,
|
|
215782
|
+
sign2 = (secret, payload2) => (0, import_node_crypto44.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
215722
215783
|
sigMatches = (actual, expected) => {
|
|
215723
215784
|
const a = Buffer.from(actual);
|
|
215724
215785
|
const b2 = Buffer.from(expected);
|
|
215725
|
-
return a.length === b2.length && (0,
|
|
215786
|
+
return a.length === b2.length && (0, import_node_crypto44.timingSafeEqual)(a, b2);
|
|
215726
215787
|
};
|
|
215727
215788
|
readOrCreateSecret2 = (file) => {
|
|
215728
|
-
if (!file) return (0,
|
|
215789
|
+
if (!file) return (0, import_node_crypto44.randomBytes)(32);
|
|
215729
215790
|
try {
|
|
215730
|
-
const raw =
|
|
215791
|
+
const raw = fs22.readFileSync(file, "utf8").trim();
|
|
215731
215792
|
if (raw) return Buffer.from(raw, "base64url");
|
|
215732
215793
|
} catch {
|
|
215733
215794
|
}
|
|
215734
|
-
const secret = (0,
|
|
215735
|
-
|
|
215736
|
-
|
|
215795
|
+
const secret = (0, import_node_crypto44.randomBytes)(32);
|
|
215796
|
+
fs22.mkdirSync(path21.dirname(file), { recursive: true });
|
|
215797
|
+
fs22.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
215737
215798
|
return secret;
|
|
215738
215799
|
};
|
|
215739
215800
|
isClaims = (v2) => {
|
|
@@ -218406,11 +218467,11 @@ function onlyHits(pool, q2) {
|
|
|
218406
218467
|
if (!q2.requireMatch || q2.keywords.length === 0) return [...pool];
|
|
218407
218468
|
return pool.filter((r) => memoryMatchScore(r, q2.keywords) > 0);
|
|
218408
218469
|
}
|
|
218409
|
-
var
|
|
218470
|
+
var import_node_crypto45, MemoryActorMemoryStore, toIndexEntry;
|
|
218410
218471
|
var init_memory_actor_memory_store = __esm({
|
|
218411
218472
|
"../testkit/src/memory-actor-memory-store.ts"() {
|
|
218412
218473
|
"use strict";
|
|
218413
|
-
|
|
218474
|
+
import_node_crypto45 = require("node:crypto");
|
|
218414
218475
|
init_src();
|
|
218415
218476
|
MemoryActorMemoryStore = class {
|
|
218416
218477
|
rows = /* @__PURE__ */ new Map();
|
|
@@ -218464,7 +218525,7 @@ var init_memory_actor_memory_store = __esm({
|
|
|
218464
218525
|
async write(input, now) {
|
|
218465
218526
|
if (input.memId === void 0) {
|
|
218466
218527
|
const rec2 = {
|
|
218467
|
-
memId: `mem:${(0,
|
|
218528
|
+
memId: `mem:${(0, import_node_crypto45.randomUUID)()}`,
|
|
218468
218529
|
actorId: input.actorId,
|
|
218469
218530
|
projectId: input.projectId,
|
|
218470
218531
|
keywords: [...input.keywords],
|
|
@@ -219275,13 +219336,13 @@ var init_stats = __esm({
|
|
|
219275
219336
|
|
|
219276
219337
|
// ../server/src/domains/projects/project-id.ts
|
|
219277
219338
|
function randomProjectId() {
|
|
219278
|
-
return projectIdFromUuid((0,
|
|
219339
|
+
return projectIdFromUuid((0, import_node_crypto46.randomUUID)());
|
|
219279
219340
|
}
|
|
219280
|
-
var
|
|
219341
|
+
var import_node_crypto46;
|
|
219281
219342
|
var init_project_id = __esm({
|
|
219282
219343
|
"../server/src/domains/projects/project-id.ts"() {
|
|
219283
219344
|
"use strict";
|
|
219284
|
-
|
|
219345
|
+
import_node_crypto46 = require("node:crypto");
|
|
219285
219346
|
init_src();
|
|
219286
219347
|
}
|
|
219287
219348
|
});
|
|
@@ -221356,13 +221417,13 @@ function applyTurnPatch(t, patch) {
|
|
|
221356
221417
|
...patch.lastError !== void 0 ? { lastError: patch.lastError } : {}
|
|
221357
221418
|
};
|
|
221358
221419
|
}
|
|
221359
|
-
var
|
|
221420
|
+
var import_node_crypto47, fs23, path22, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
|
|
221360
221421
|
var init_dev_store = __esm({
|
|
221361
221422
|
"../server/src/dev-store.ts"() {
|
|
221362
221423
|
"use strict";
|
|
221363
221424
|
init_src();
|
|
221364
|
-
|
|
221365
|
-
|
|
221425
|
+
import_node_crypto47 = require("node:crypto");
|
|
221426
|
+
fs23 = __toESM(require("node:fs"), 1);
|
|
221366
221427
|
path22 = __toESM(require("node:path"), 1);
|
|
221367
221428
|
init_src();
|
|
221368
221429
|
init_src9();
|
|
@@ -221376,8 +221437,8 @@ var init_dev_store = __esm({
|
|
|
221376
221437
|
}
|
|
221377
221438
|
static async open(file) {
|
|
221378
221439
|
const memory = new MemoryOplogStore();
|
|
221379
|
-
if (
|
|
221380
|
-
for (const line2 of
|
|
221440
|
+
if (fs23.existsSync(file)) {
|
|
221441
|
+
for (const line2 of fs23.readFileSync(file, "utf8").split("\n")) {
|
|
221381
221442
|
if (!line2.trim()) continue;
|
|
221382
221443
|
const stored = JSON.parse(line2);
|
|
221383
221444
|
const { artifactId, seq, ...op } = stored;
|
|
@@ -221385,15 +221446,15 @@ var init_dev_store = __esm({
|
|
|
221385
221446
|
if (assigned !== seq) throw new Error(`corrupt ndjson log: seq mismatch at ${line2}`);
|
|
221386
221447
|
}
|
|
221387
221448
|
} else {
|
|
221388
|
-
|
|
221389
|
-
|
|
221449
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
221450
|
+
fs23.writeFileSync(file, "");
|
|
221390
221451
|
}
|
|
221391
221452
|
return new _NdjsonOplogStore(file, memory);
|
|
221392
221453
|
}
|
|
221393
221454
|
async append(artifactId, op, expectedSeq) {
|
|
221394
221455
|
const seq = await this.memory.append(artifactId, op, expectedSeq);
|
|
221395
221456
|
const stored = { ...op, artifactId, seq };
|
|
221396
|
-
|
|
221457
|
+
fs23.appendFileSync(this.file, JSON.stringify(stored) + "\n");
|
|
221397
221458
|
return seq;
|
|
221398
221459
|
}
|
|
221399
221460
|
read(artifactId, fromSeq) {
|
|
@@ -221409,39 +221470,39 @@ var init_dev_store = __esm({
|
|
|
221409
221470
|
DirBlobStore = class {
|
|
221410
221471
|
constructor(dir) {
|
|
221411
221472
|
this.dir = dir;
|
|
221412
|
-
|
|
221473
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
221413
221474
|
}
|
|
221414
221475
|
fileOf(hash3) {
|
|
221415
221476
|
return path22.join(this.dir, hash3);
|
|
221416
221477
|
}
|
|
221417
221478
|
async put(bytes2) {
|
|
221418
|
-
const hash3 = (0,
|
|
221479
|
+
const hash3 = (0, import_node_crypto47.createHash)("sha256").update(bytes2).digest("hex");
|
|
221419
221480
|
const file = this.fileOf(hash3);
|
|
221420
|
-
if (!
|
|
221481
|
+
if (!fs23.existsSync(file)) fs23.writeFileSync(file, bytes2);
|
|
221421
221482
|
return hash3;
|
|
221422
221483
|
}
|
|
221423
221484
|
async meta(hash3) {
|
|
221424
221485
|
const file = this.fileOf(hash3);
|
|
221425
|
-
if (!
|
|
221426
|
-
const size =
|
|
221427
|
-
const fd =
|
|
221486
|
+
if (!fs23.existsSync(file)) return null;
|
|
221487
|
+
const size = fs23.statSync(file).size;
|
|
221488
|
+
const fd = fs23.openSync(file, "r");
|
|
221428
221489
|
const head = Buffer.alloc(16);
|
|
221429
|
-
|
|
221430
|
-
|
|
221490
|
+
fs23.readSync(fd, head, 0, 16, 0);
|
|
221491
|
+
fs23.closeSync(fd);
|
|
221431
221492
|
const contentType = sniffContentType(new Uint8Array(head));
|
|
221432
221493
|
return { size, ...contentType ? { contentType } : {} };
|
|
221433
221494
|
}
|
|
221434
221495
|
async get(hash3) {
|
|
221435
221496
|
const file = this.fileOf(hash3);
|
|
221436
|
-
if (!
|
|
221437
|
-
return new Uint8Array(
|
|
221497
|
+
if (!fs23.existsSync(file)) throw new BlobNotFoundError(hash3);
|
|
221498
|
+
return new Uint8Array(fs23.readFileSync(file));
|
|
221438
221499
|
}
|
|
221439
221500
|
async has(hash3) {
|
|
221440
|
-
return
|
|
221501
|
+
return fs23.existsSync(this.fileOf(hash3));
|
|
221441
221502
|
}
|
|
221442
221503
|
async sweep(reachable) {
|
|
221443
|
-
for (const name of
|
|
221444
|
-
if (!reachable.has(name))
|
|
221504
|
+
for (const name of fs23.readdirSync(this.dir)) {
|
|
221505
|
+
if (!reachable.has(name)) fs23.unlinkSync(this.fileOf(name));
|
|
221445
221506
|
}
|
|
221446
221507
|
}
|
|
221447
221508
|
};
|
|
@@ -221470,7 +221531,7 @@ var init_dev_store = __esm({
|
|
|
221470
221531
|
this.file = file;
|
|
221471
221532
|
}
|
|
221472
221533
|
static async open(file) {
|
|
221473
|
-
const seed =
|
|
221534
|
+
const seed = fs23.existsSync(file) ? JSON.parse(fs23.readFileSync(file, "utf8")) : [];
|
|
221474
221535
|
return new _FileTypeRegistryStore(file, seed);
|
|
221475
221536
|
}
|
|
221476
221537
|
async put(def) {
|
|
@@ -221483,8 +221544,8 @@ var init_dev_store = __esm({
|
|
|
221483
221544
|
}
|
|
221484
221545
|
async save() {
|
|
221485
221546
|
const tmp = `${this.file}.tmp`;
|
|
221486
|
-
|
|
221487
|
-
|
|
221547
|
+
fs23.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
|
|
221548
|
+
fs23.renameSync(tmp, this.file);
|
|
221488
221549
|
}
|
|
221489
221550
|
};
|
|
221490
221551
|
FileRoleRegistryStore = class _FileRoleRegistryStore extends MemoryRoleRegistryStore {
|
|
@@ -221493,7 +221554,7 @@ var init_dev_store = __esm({
|
|
|
221493
221554
|
this.file = file;
|
|
221494
221555
|
}
|
|
221495
221556
|
static async open(file) {
|
|
221496
|
-
const seed =
|
|
221557
|
+
const seed = fs23.existsSync(file) ? JSON.parse(fs23.readFileSync(file, "utf8")) : [];
|
|
221497
221558
|
return new _FileRoleRegistryStore(file, seed);
|
|
221498
221559
|
}
|
|
221499
221560
|
async put(def) {
|
|
@@ -221506,8 +221567,8 @@ var init_dev_store = __esm({
|
|
|
221506
221567
|
}
|
|
221507
221568
|
async save() {
|
|
221508
221569
|
const tmp = `${this.file}.tmp`;
|
|
221509
|
-
|
|
221510
|
-
|
|
221570
|
+
fs23.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
|
|
221571
|
+
fs23.renameSync(tmp, this.file);
|
|
221511
221572
|
}
|
|
221512
221573
|
};
|
|
221513
221574
|
FileRegistryStore = class _FileRegistryStore extends MemoryRegistryStore {
|
|
@@ -221525,8 +221586,8 @@ var init_dev_store = __esm({
|
|
|
221525
221586
|
}
|
|
221526
221587
|
static async open(file) {
|
|
221527
221588
|
const store = new _FileRegistryStore(file);
|
|
221528
|
-
if (
|
|
221529
|
-
const snap = JSON.parse(
|
|
221589
|
+
if (fs23.existsSync(file)) {
|
|
221590
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
221530
221591
|
for (const a of snap.actors) await MemoryRegistryStore.prototype.upsertActor.call(store, a);
|
|
221531
221592
|
for (const c of snap.configs) await MemoryRegistryStore.prototype.appendConfig.call(store, c);
|
|
221532
221593
|
for (const t of snap.teams) await MemoryRegistryStore.prototype.upsertTeam.call(store, t);
|
|
@@ -221567,7 +221628,7 @@ var init_dev_store = __esm({
|
|
|
221567
221628
|
skillFiles: skillFilesEntries,
|
|
221568
221629
|
connections
|
|
221569
221630
|
};
|
|
221570
|
-
|
|
221631
|
+
fs23.writeFileSync(this.file, JSON.stringify(snap, null, 2));
|
|
221571
221632
|
}
|
|
221572
221633
|
};
|
|
221573
221634
|
FileAssistantBindStore = class _FileAssistantBindStore extends MemoryAssistantBindStore {
|
|
@@ -221585,11 +221646,11 @@ var init_dev_store = __esm({
|
|
|
221585
221646
|
}
|
|
221586
221647
|
static async open(file) {
|
|
221587
221648
|
const store = new _FileAssistantBindStore(file);
|
|
221588
|
-
if (
|
|
221649
|
+
if (fs23.existsSync(file)) store._load(JSON.parse(fs23.readFileSync(file, "utf8")));
|
|
221589
221650
|
return store;
|
|
221590
221651
|
}
|
|
221591
221652
|
async save() {
|
|
221592
|
-
|
|
221653
|
+
fs23.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
|
|
221593
221654
|
}
|
|
221594
221655
|
};
|
|
221595
221656
|
FileHumanPrefsStore = class _FileHumanPrefsStore extends MemoryHumanPrefsStore {
|
|
@@ -221607,11 +221668,11 @@ var init_dev_store = __esm({
|
|
|
221607
221668
|
}
|
|
221608
221669
|
static async open(file) {
|
|
221609
221670
|
const store = new _FileHumanPrefsStore(file);
|
|
221610
|
-
if (
|
|
221671
|
+
if (fs23.existsSync(file)) store._load(JSON.parse(fs23.readFileSync(file, "utf8")));
|
|
221611
221672
|
return store;
|
|
221612
221673
|
}
|
|
221613
221674
|
async save() {
|
|
221614
|
-
|
|
221675
|
+
fs23.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
|
|
221615
221676
|
}
|
|
221616
221677
|
};
|
|
221617
221678
|
FileProjectStateStore = class _FileProjectStateStore extends MemoryProjectStateStore {
|
|
@@ -221621,8 +221682,8 @@ var init_dev_store = __esm({
|
|
|
221621
221682
|
}
|
|
221622
221683
|
static async open(file) {
|
|
221623
221684
|
const store = new _FileProjectStateStore(file);
|
|
221624
|
-
if (
|
|
221625
|
-
const snap = JSON.parse(
|
|
221685
|
+
if (fs23.existsSync(file)) {
|
|
221686
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
221626
221687
|
for (const project of snap.projects ?? []) await MemoryProjectStateStore.prototype.upsertProject.call(store, project);
|
|
221627
221688
|
const membersByProject = /* @__PURE__ */ new Map();
|
|
221628
221689
|
for (const member of snap.members ?? []) {
|
|
@@ -221634,8 +221695,8 @@ var init_dev_store = __esm({
|
|
|
221634
221695
|
await MemoryProjectStateStore.prototype.replaceProjectMembers.call(store, projectId2, members);
|
|
221635
221696
|
}
|
|
221636
221697
|
} else {
|
|
221637
|
-
|
|
221638
|
-
|
|
221698
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
221699
|
+
fs23.writeFileSync(file, JSON.stringify({ projects: [], members: [] }, null, 2));
|
|
221639
221700
|
}
|
|
221640
221701
|
return store;
|
|
221641
221702
|
}
|
|
@@ -221654,7 +221715,7 @@ var init_dev_store = __esm({
|
|
|
221654
221715
|
async save() {
|
|
221655
221716
|
const projects = await this.listProjects();
|
|
221656
221717
|
const members = (await Promise.all(projects.map((project) => this.listProjectMembers(project.id)))).flat();
|
|
221657
|
-
|
|
221718
|
+
fs23.writeFileSync(this.file, JSON.stringify({ projects, members }, null, 2));
|
|
221658
221719
|
}
|
|
221659
221720
|
};
|
|
221660
221721
|
FileArtifactStateStore = class _FileArtifactStateStore extends MemoryArtifactStateStore {
|
|
@@ -221664,8 +221725,8 @@ var init_dev_store = __esm({
|
|
|
221664
221725
|
}
|
|
221665
221726
|
static async open(file) {
|
|
221666
221727
|
const store = new _FileArtifactStateStore(file);
|
|
221667
|
-
if (
|
|
221668
|
-
const snap = JSON.parse(
|
|
221728
|
+
if (fs23.existsSync(file)) {
|
|
221729
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
221669
221730
|
for (const artifact of snap.artifacts ?? []) await MemoryArtifactStateStore.prototype.upsertArtifact.call(store, artifact);
|
|
221670
221731
|
for (const revision of snap.revisions ?? []) await MemoryArtifactStateStore.prototype.upsertRevision.call(store, revision);
|
|
221671
221732
|
for (const event of snap.events ?? []) await MemoryArtifactStateStore.prototype.appendEvent.call(store, event);
|
|
@@ -221675,8 +221736,8 @@ var init_dev_store = __esm({
|
|
|
221675
221736
|
for (const ws of snap.workspaceDispatchHeld ?? []) await MemoryArtifactStateStore.prototype.setWorkspaceDispatchHold.call(store, ws, true);
|
|
221676
221737
|
for (const f2 of snap.workOrderFiles ?? []) await MemoryArtifactStateStore.prototype.addWorkOrderFile.call(store, f2);
|
|
221677
221738
|
} else {
|
|
221678
|
-
|
|
221679
|
-
|
|
221739
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
221740
|
+
fs23.writeFileSync(file, JSON.stringify({ artifacts: [], revisions: [], events: [], annotations: [], nodeOutputs: [], workspaceBindings: [], workspaceDispatchHeld: [], workOrderFiles: [] }, null, 2));
|
|
221680
221741
|
}
|
|
221681
221742
|
return store;
|
|
221682
221743
|
}
|
|
@@ -221713,7 +221774,7 @@ var init_dev_store = __esm({
|
|
|
221713
221774
|
await this.save();
|
|
221714
221775
|
}
|
|
221715
221776
|
async save() {
|
|
221716
|
-
|
|
221777
|
+
fs23.writeFileSync(this.file, JSON.stringify(await this.listAll(), null, 2));
|
|
221717
221778
|
}
|
|
221718
221779
|
};
|
|
221719
221780
|
FileTraceStore = class _FileTraceStore extends MemoryTraceStore {
|
|
@@ -221740,25 +221801,25 @@ var init_dev_store = __esm({
|
|
|
221740
221801
|
return path22.join(this.eventsDir, `${encodeURIComponent(runId)}.ndjson`);
|
|
221741
221802
|
}
|
|
221742
221803
|
appendLine(file, obj2) {
|
|
221743
|
-
|
|
221804
|
+
fs23.appendFileSync(file, JSON.stringify(obj2) + "\n");
|
|
221744
221805
|
}
|
|
221745
221806
|
static replay(file, fn) {
|
|
221746
|
-
if (!
|
|
221747
|
-
for (const line2 of
|
|
221807
|
+
if (!fs23.existsSync(file)) return;
|
|
221808
|
+
for (const line2 of fs23.readFileSync(file, "utf8").split("\n")) {
|
|
221748
221809
|
if (!line2.trim()) continue;
|
|
221749
221810
|
fn(JSON.parse(line2));
|
|
221750
221811
|
}
|
|
221751
221812
|
}
|
|
221752
221813
|
static async open(dir) {
|
|
221753
221814
|
const store = new _FileTraceStore(dir);
|
|
221754
|
-
|
|
221815
|
+
fs23.mkdirSync(store.eventsDir, { recursive: true });
|
|
221755
221816
|
_FileTraceStore.replay(store.runsFile, (r) => store.restoreRun(r));
|
|
221756
|
-
for (const name of
|
|
221817
|
+
for (const name of fs23.readdirSync(store.eventsDir)) {
|
|
221757
221818
|
_FileTraceStore.replay(path22.join(store.eventsDir, name), (e) => store.restoreEvent(e));
|
|
221758
221819
|
}
|
|
221759
221820
|
_FileTraceStore.replay(store.toolCallsFile, (c) => store.restoreToolCall(c));
|
|
221760
221821
|
_FileTraceStore.replay(store.linksFile, (l) => store.restoreLink(l));
|
|
221761
|
-
store.restoreContinuity(
|
|
221822
|
+
store.restoreContinuity(fs23.existsSync(store.continuityFile) ? JSON.parse(fs23.readFileSync(store.continuityFile, "utf8")) : {});
|
|
221762
221823
|
return store;
|
|
221763
221824
|
}
|
|
221764
221825
|
async createRun(input) {
|
|
@@ -221810,8 +221871,8 @@ var init_dev_store = __esm({
|
|
|
221810
221871
|
}
|
|
221811
221872
|
saveContinuity() {
|
|
221812
221873
|
const tmp = `${this.continuityFile}.tmp`;
|
|
221813
|
-
|
|
221814
|
-
|
|
221874
|
+
fs23.writeFileSync(tmp, JSON.stringify(this.continuitySnapshot(), null, 2));
|
|
221875
|
+
fs23.renameSync(tmp, this.continuityFile);
|
|
221815
221876
|
}
|
|
221816
221877
|
async appendEvents(runId, inputs) {
|
|
221817
221878
|
const existing = await super.listEvents(runId, {});
|
|
@@ -222276,8 +222337,8 @@ var init_dev_store = __esm({
|
|
|
222276
222337
|
}
|
|
222277
222338
|
static async open(file) {
|
|
222278
222339
|
const store = new _FileChatSessionStore(file);
|
|
222279
|
-
if (
|
|
222280
|
-
const snap = JSON.parse(
|
|
222340
|
+
if (fs23.existsSync(file)) {
|
|
222341
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
222281
222342
|
for (const [sid, copies] of Object.entries(snap.outputCopies ?? {})) store.outputCopies.set(sid, copies);
|
|
222282
222343
|
for (const [sid, fps] of Object.entries(snap.outputFingerprints ?? {})) store.outputFingerprints.set(sid, fps);
|
|
222283
222344
|
for (const [sid, issues] of Object.entries(snap.fileIssues ?? {})) store.fileIssues.set(sid, issues);
|
|
@@ -222287,8 +222348,8 @@ var init_dev_store = __esm({
|
|
|
222287
222348
|
for (const [sid, kinds] of Object.entries(snap.sessionWorkOrderKinds ?? {})) store.sessionWorkOrderKinds.set(sid, new Map(Object.entries(kinds)));
|
|
222288
222349
|
for (const [sid, list2] of Object.entries(snap.pending ?? {})) store.pending.set(sid, list2);
|
|
222289
222350
|
} else {
|
|
222290
|
-
|
|
222291
|
-
|
|
222351
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
222352
|
+
fs23.writeFileSync(file, JSON.stringify({ sessions: [], messages: {}, sessionWorkOrders: {} }, null, 2));
|
|
222292
222353
|
}
|
|
222293
222354
|
return store;
|
|
222294
222355
|
}
|
|
@@ -222382,7 +222443,7 @@ var init_dev_store = __esm({
|
|
|
222382
222443
|
sessionWorkOrderKinds: Object.fromEntries([...this.sessionWorkOrderKinds].map(([k2, v2]) => [k2, Object.fromEntries(v2)])),
|
|
222383
222444
|
pending: Object.fromEntries(this.pending)
|
|
222384
222445
|
};
|
|
222385
|
-
|
|
222446
|
+
fs23.writeFileSync(this.file, JSON.stringify(snap, null, 2));
|
|
222386
222447
|
}
|
|
222387
222448
|
};
|
|
222388
222449
|
MemoryChatTurnStore = class {
|
|
@@ -222465,17 +222526,17 @@ var init_dev_store = __esm({
|
|
|
222465
222526
|
}
|
|
222466
222527
|
static async open(file) {
|
|
222467
222528
|
const store = new _FileChatTurnStore(file);
|
|
222468
|
-
if (
|
|
222469
|
-
const snap = JSON.parse(
|
|
222529
|
+
if (fs23.existsSync(file)) {
|
|
222530
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
222470
222531
|
for (const t of snap.turns ?? []) store.turns.set(t.id, t);
|
|
222471
222532
|
} else {
|
|
222472
|
-
|
|
222473
|
-
|
|
222533
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
222534
|
+
fs23.writeFileSync(file, JSON.stringify({ turns: [] }, null, 2));
|
|
222474
222535
|
}
|
|
222475
222536
|
return store;
|
|
222476
222537
|
}
|
|
222477
222538
|
persist() {
|
|
222478
|
-
|
|
222539
|
+
fs23.writeFileSync(this.file, JSON.stringify({ turns: [...this.turns.values()] }, null, 2));
|
|
222479
222540
|
}
|
|
222480
222541
|
};
|
|
222481
222542
|
MemoryReadMarkerStore = class _MemoryReadMarkerStore {
|
|
@@ -222501,12 +222562,12 @@ var init_dev_store = __esm({
|
|
|
222501
222562
|
}
|
|
222502
222563
|
static async open(file) {
|
|
222503
222564
|
const store = new _FileReadMarkerStore(file);
|
|
222504
|
-
if (
|
|
222505
|
-
const snap = JSON.parse(
|
|
222565
|
+
if (fs23.existsSync(file)) {
|
|
222566
|
+
const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
|
|
222506
222567
|
for (const m2 of snap.markers ?? []) store.markers.set(`${m2.actorId}\0${m2.scope}`, m2);
|
|
222507
222568
|
} else {
|
|
222508
|
-
|
|
222509
|
-
|
|
222569
|
+
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
222570
|
+
fs23.writeFileSync(file, JSON.stringify({ markers: [] }, null, 2));
|
|
222510
222571
|
}
|
|
222511
222572
|
return store;
|
|
222512
222573
|
}
|
|
@@ -222515,18 +222576,18 @@ var init_dev_store = __esm({
|
|
|
222515
222576
|
this.save();
|
|
222516
222577
|
}
|
|
222517
222578
|
save() {
|
|
222518
|
-
|
|
222579
|
+
fs23.writeFileSync(this.file, JSON.stringify({ markers: [...this.markers.values()] }, null, 2));
|
|
222519
222580
|
}
|
|
222520
222581
|
};
|
|
222521
222582
|
}
|
|
222522
222583
|
});
|
|
222523
222584
|
|
|
222524
222585
|
// ../server/src/control-plane-file-store.ts
|
|
222525
|
-
var
|
|
222586
|
+
var fs24, path23, MUTATORS2, SNAPSHOT_VERSION, FileControlPlaneStore;
|
|
222526
222587
|
var init_control_plane_file_store = __esm({
|
|
222527
222588
|
"../server/src/control-plane-file-store.ts"() {
|
|
222528
222589
|
"use strict";
|
|
222529
|
-
|
|
222590
|
+
fs24 = __toESM(require("node:fs"), 1);
|
|
222530
222591
|
path23 = __toESM(require("node:path"), 1);
|
|
222531
222592
|
init_src9();
|
|
222532
222593
|
MUTATORS2 = [
|
|
@@ -222569,8 +222630,8 @@ var init_control_plane_file_store = __esm({
|
|
|
222569
222630
|
}
|
|
222570
222631
|
static async open(file) {
|
|
222571
222632
|
const store = new _FileControlPlaneStore(file);
|
|
222572
|
-
if (
|
|
222573
|
-
const snap = JSON.parse(
|
|
222633
|
+
if (fs24.existsSync(file)) {
|
|
222634
|
+
const snap = JSON.parse(fs24.readFileSync(file, "utf8"));
|
|
222574
222635
|
const needsOnboardingBackfill = (snap.version ?? 1) < 2;
|
|
222575
222636
|
const backfillAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
222576
222637
|
for (const c of snap.companies ?? []) await MemoryControlPlaneStore.prototype.createCompany.call(store, c);
|
|
@@ -222588,7 +222649,7 @@ var init_control_plane_file_store = __esm({
|
|
|
222588
222649
|
for (const op of snap.offboardings ?? []) store.offboardings.set(`${op.companyId}\0${op.operationId}`, op);
|
|
222589
222650
|
if (needsOnboardingBackfill) await store.save();
|
|
222590
222651
|
} else {
|
|
222591
|
-
|
|
222652
|
+
fs24.mkdirSync(path23.dirname(file), { recursive: true });
|
|
222592
222653
|
}
|
|
222593
222654
|
return store;
|
|
222594
222655
|
}
|
|
@@ -222625,7 +222686,7 @@ var init_control_plane_file_store = __esm({
|
|
|
222625
222686
|
// 交接操作无按公司列举的读面(按 operationId / accountId 定位),直接读 protected map。
|
|
222626
222687
|
offboardings: [...this.offboardings.values()]
|
|
222627
222688
|
};
|
|
222628
|
-
|
|
222689
|
+
fs24.writeFileSync(this.file, JSON.stringify(snap, null, 2));
|
|
222629
222690
|
}
|
|
222630
222691
|
};
|
|
222631
222692
|
}
|
|
@@ -222701,7 +222762,7 @@ var init_company_engine_router = __esm({
|
|
|
222701
222762
|
|
|
222702
222763
|
// ../server/src/skill-market-client.ts
|
|
222703
222764
|
function digestOf2(bytes2) {
|
|
222704
|
-
return `sha256:${(0,
|
|
222765
|
+
return `sha256:${(0, import_node_crypto48.createHash)("sha256").update(bytes2).digest("hex")}`;
|
|
222705
222766
|
}
|
|
222706
222767
|
function createSkillMarketClientFromEnv(env = process.env) {
|
|
222707
222768
|
const base = env["SKILL_MARKET_BASE_URL"];
|
|
@@ -222712,11 +222773,11 @@ function createSkillMarketClientFromEnv(env = process.env) {
|
|
|
222712
222773
|
function sleep4(ms) {
|
|
222713
222774
|
return new Promise((r) => setTimeout(r, ms));
|
|
222714
222775
|
}
|
|
222715
|
-
var
|
|
222776
|
+
var import_node_crypto48, DisabledSkillMarketClient, FakeSkillMarketClient, HttpSkillMarketClient;
|
|
222716
222777
|
var init_skill_market_client = __esm({
|
|
222717
222778
|
"../server/src/skill-market-client.ts"() {
|
|
222718
222779
|
"use strict";
|
|
222719
|
-
|
|
222780
|
+
import_node_crypto48 = require("node:crypto");
|
|
222720
222781
|
init_src();
|
|
222721
222782
|
DisabledSkillMarketClient = class {
|
|
222722
222783
|
async listSkills(_input) {
|
|
@@ -223567,7 +223628,7 @@ async function copySessionOutputs(deps) {
|
|
|
223567
223628
|
continue;
|
|
223568
223629
|
}
|
|
223569
223630
|
const saved = existing?.[file.path];
|
|
223570
|
-
if (saved && savedContentHash(saved) === (0,
|
|
223631
|
+
if (saved && savedContentHash(saved) === (0, import_node_crypto49.createHash)("sha256").update(bytes2).digest("hex")) {
|
|
223571
223632
|
const aligned = { ...saved, size: bytes2.length, mtime: file.mtime };
|
|
223572
223633
|
delete aligned.editedAt;
|
|
223573
223634
|
realigned.push(aligned);
|
|
@@ -223664,11 +223725,11 @@ function createOutputCopyScheduler(deps) {
|
|
|
223664
223725
|
}
|
|
223665
223726
|
};
|
|
223666
223727
|
}
|
|
223667
|
-
var
|
|
223728
|
+
var import_node_crypto49, OUTPUT_COPY_LIMITS;
|
|
223668
223729
|
var init_outputs_copy = __esm({
|
|
223669
223730
|
"../server/src/domains/chat-sessions/outputs-copy.ts"() {
|
|
223670
223731
|
"use strict";
|
|
223671
|
-
|
|
223732
|
+
import_node_crypto49 = require("node:crypto");
|
|
223672
223733
|
init_src();
|
|
223673
223734
|
OUTPUT_COPY_LIMITS = {
|
|
223674
223735
|
maxFileBytes: FILE_CONTENT_MAX_BYTES,
|
|
@@ -223883,11 +223944,11 @@ function typeDefError(def, mode) {
|
|
|
223883
223944
|
}
|
|
223884
223945
|
return null;
|
|
223885
223946
|
}
|
|
223886
|
-
var
|
|
223947
|
+
var import_node_crypto50, RESERVED_FIELD_NAMES, ARTIFACT_TYPE_ACCENTS, TYPE_DEF_SCHEMA, TypesAdminService;
|
|
223887
223948
|
var init_types_admin = __esm({
|
|
223888
223949
|
"../server/src/types-admin.ts"() {
|
|
223889
223950
|
"use strict";
|
|
223890
|
-
|
|
223951
|
+
import_node_crypto50 = require("node:crypto");
|
|
223891
223952
|
init_zod();
|
|
223892
223953
|
init_src7();
|
|
223893
223954
|
init_config_audit();
|
|
@@ -224014,7 +224075,7 @@ var init_types_admin = __esm({
|
|
|
224014
224075
|
async trace(change, target, by, detail) {
|
|
224015
224076
|
try {
|
|
224016
224077
|
await this.audit?.({
|
|
224017
|
-
id: `reg_${(0,
|
|
224078
|
+
id: `reg_${(0, import_node_crypto50.randomUUID)()}`,
|
|
224018
224079
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
224019
224080
|
kind: "registry_change",
|
|
224020
224081
|
target,
|
|
@@ -224162,11 +224223,11 @@ function roleDefError(def, mode) {
|
|
|
224162
224223
|
}
|
|
224163
224224
|
return null;
|
|
224164
224225
|
}
|
|
224165
|
-
var
|
|
224226
|
+
var import_node_crypto51, ACCENTS, ROLE_DEF_SCHEMA, RolesAdminService;
|
|
224166
224227
|
var init_roles_admin = __esm({
|
|
224167
224228
|
"../server/src/roles-admin.ts"() {
|
|
224168
224229
|
"use strict";
|
|
224169
|
-
|
|
224230
|
+
import_node_crypto51 = require("node:crypto");
|
|
224170
224231
|
init_zod();
|
|
224171
224232
|
init_src7();
|
|
224172
224233
|
init_config_audit();
|
|
@@ -224191,7 +224252,7 @@ var init_roles_admin = __esm({
|
|
|
224191
224252
|
async trace(change, target, by, detail) {
|
|
224192
224253
|
try {
|
|
224193
224254
|
await this.deps.audit?.({
|
|
224194
|
-
id: `reg_${(0,
|
|
224255
|
+
id: `reg_${(0, import_node_crypto51.randomUUID)()}`,
|
|
224195
224256
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
224196
224257
|
kind: "registry_change",
|
|
224197
224258
|
target,
|
|
@@ -224204,8 +224265,13 @@ var init_roles_admin = __esm({
|
|
|
224204
224265
|
list() {
|
|
224205
224266
|
return this.deps.store.list();
|
|
224206
224267
|
}
|
|
224207
|
-
|
|
224208
|
-
|
|
224268
|
+
/**
|
|
224269
|
+
* @param companyId 按哪家公司的员工数人头(Bug 0245)。岗位目录全公司共用一份,但「谁在岗」是各公司自己的——
|
|
224270
|
+
* GET /api/roles 必须传请求所属公司,否则落到默认公司那份早已不再更新的旧名单,所有公司都报同一组错数。
|
|
224271
|
+
* 缺省 = 默认公司(改名 / 弃用 / 删除这几条写路径暂维持原口径)。
|
|
224272
|
+
*/
|
|
224273
|
+
async usage(name, companyId) {
|
|
224274
|
+
return (await this.usageMany([name], companyId))[name];
|
|
224209
224275
|
}
|
|
224210
224276
|
/**
|
|
224211
224277
|
* ADR 0088 D4:多个岗位的用量**一次取数**。此前 `/api/roles` 对每个岗位各调一次 `usage()`,
|
|
@@ -224213,9 +224279,9 @@ var init_roles_admin = __esm({
|
|
|
224213
224279
|
* ——13 个岗位 = 13 份全表。员工页首屏门控在这条上(listRoles 与 listActors 并行等齐才渲染)。
|
|
224214
224280
|
* 三份数据只取一次,逐岗位在内存算。单岗位口径与旧 `usage()` 逐字段一致(后者现转调本方法)。
|
|
224215
224281
|
*/
|
|
224216
|
-
async usageMany(names) {
|
|
224282
|
+
async usageMany(names, companyId) {
|
|
224217
224283
|
const [actors, types2, owners] = await Promise.all([
|
|
224218
|
-
this.deps.actors(),
|
|
224284
|
+
this.deps.actors(companyId),
|
|
224219
224285
|
this.deps.types(),
|
|
224220
224286
|
this.deps.artifactOwners?.() ?? Promise.resolve([])
|
|
224221
224287
|
]);
|
|
@@ -227050,8 +227116,8 @@ var init_chat_recovery = __esm({
|
|
|
227050
227116
|
|
|
227051
227117
|
// ../server/src/auth/crypto.ts
|
|
227052
227118
|
function hashPassword(password) {
|
|
227053
|
-
const salt = (0,
|
|
227054
|
-
const dk = (0,
|
|
227119
|
+
const salt = (0, import_node_crypto52.randomBytes)(16);
|
|
227120
|
+
const dk = (0, import_node_crypto52.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
|
|
227055
227121
|
return `scrypt$${SCRYPT_N}$${salt.toString("base64url")}$${dk.toString("base64url")}`;
|
|
227056
227122
|
}
|
|
227057
227123
|
function verifyPassword(password, stored) {
|
|
@@ -227068,8 +227134,8 @@ function verifyPassword(password, stored) {
|
|
|
227068
227134
|
return false;
|
|
227069
227135
|
}
|
|
227070
227136
|
if (expected.length === 0) return false;
|
|
227071
|
-
const dk = (0,
|
|
227072
|
-
return dk.length === expected.length && (0,
|
|
227137
|
+
const dk = (0, import_node_crypto52.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
|
|
227138
|
+
return dk.length === expected.length && (0, import_node_crypto52.timingSafeEqual)(dk, expected);
|
|
227073
227139
|
}
|
|
227074
227140
|
function b64urlJson(value2) {
|
|
227075
227141
|
return Buffer.from(JSON.stringify(value2)).toString("base64url");
|
|
@@ -227077,17 +227143,17 @@ function b64urlJson(value2) {
|
|
|
227077
227143
|
function signSession(claims, secret) {
|
|
227078
227144
|
const head = b64urlJson({ alg: "HS256", typ: "JWT" });
|
|
227079
227145
|
const body2 = b64urlJson(claims);
|
|
227080
|
-
const sig = (0,
|
|
227146
|
+
const sig = (0, import_node_crypto52.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
227081
227147
|
return `${head}.${body2}.${sig}`;
|
|
227082
227148
|
}
|
|
227083
227149
|
function verifySession(token, secret, nowMs) {
|
|
227084
227150
|
const parts = token.split(".");
|
|
227085
227151
|
if (parts.length !== 3) return null;
|
|
227086
227152
|
const [head, body2, sig] = parts;
|
|
227087
|
-
const expected = (0,
|
|
227153
|
+
const expected = (0, import_node_crypto52.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
227088
227154
|
const got = Buffer.from(sig);
|
|
227089
227155
|
const exp = Buffer.from(expected);
|
|
227090
|
-
if (got.length !== exp.length || !(0,
|
|
227156
|
+
if (got.length !== exp.length || !(0, import_node_crypto52.timingSafeEqual)(got, exp)) return null;
|
|
227091
227157
|
let claims;
|
|
227092
227158
|
try {
|
|
227093
227159
|
claims = JSON.parse(Buffer.from(body2, "base64url").toString("utf8"));
|
|
@@ -227099,21 +227165,21 @@ function verifySession(token, secret, nowMs) {
|
|
|
227099
227165
|
return claims;
|
|
227100
227166
|
}
|
|
227101
227167
|
function generateCode() {
|
|
227102
|
-
return String((0,
|
|
227168
|
+
return String((0, import_node_crypto52.randomInt)(0, 1e6)).padStart(6, "0");
|
|
227103
227169
|
}
|
|
227104
227170
|
function hashCode(code2, secret) {
|
|
227105
|
-
return (0,
|
|
227171
|
+
return (0, import_node_crypto52.createHmac)("sha256", secret).update(`code:${code2}`).digest("base64url");
|
|
227106
227172
|
}
|
|
227107
227173
|
function safeEqualHash(a, b2) {
|
|
227108
227174
|
const ba = Buffer.from(a);
|
|
227109
227175
|
const bb = Buffer.from(b2);
|
|
227110
|
-
return ba.length === bb.length && (0,
|
|
227176
|
+
return ba.length === bb.length && (0, import_node_crypto52.timingSafeEqual)(ba, bb);
|
|
227111
227177
|
}
|
|
227112
|
-
var
|
|
227178
|
+
var import_node_crypto52, SCRYPT_N, SCRYPT_KEYLEN;
|
|
227113
227179
|
var init_crypto2 = __esm({
|
|
227114
227180
|
"../server/src/auth/crypto.ts"() {
|
|
227115
227181
|
"use strict";
|
|
227116
|
-
|
|
227182
|
+
import_node_crypto52 = require("node:crypto");
|
|
227117
227183
|
SCRYPT_N = 16384;
|
|
227118
227184
|
SCRYPT_KEYLEN = 32;
|
|
227119
227185
|
}
|
|
@@ -228497,18 +228563,18 @@ function variableKeyFromEnv(env = process.env) {
|
|
|
228497
228563
|
return buf;
|
|
228498
228564
|
}
|
|
228499
228565
|
if (env.NODE_ENV === "production") throw new Error("OASIS_VAR_KEY is required in production");
|
|
228500
|
-
return (0,
|
|
228566
|
+
return (0, import_node_crypto53.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
|
|
228501
228567
|
}
|
|
228502
228568
|
function dedupe2(ids2) {
|
|
228503
228569
|
return [...new Set(ids2.filter((x2) => typeof x2 === "string" && x2.length > 0))];
|
|
228504
228570
|
}
|
|
228505
|
-
var
|
|
228571
|
+
var import_node_crypto53, REDACTED_MARKER, ActorsService, MASK_TAIL_MIN_LENGTH, mask, changedKeys;
|
|
228506
228572
|
var init_service5 = __esm({
|
|
228507
228573
|
"../server/src/domains/actors/service.ts"() {
|
|
228508
228574
|
"use strict";
|
|
228509
228575
|
init_file_limits2();
|
|
228510
228576
|
init_keyed_mutex();
|
|
228511
|
-
|
|
228577
|
+
import_node_crypto53 = require("node:crypto");
|
|
228512
228578
|
init_skill_fetcher();
|
|
228513
228579
|
init_identity();
|
|
228514
228580
|
init_migrate();
|
|
@@ -229132,7 +229198,7 @@ ${input.description}
|
|
|
229132
229198
|
*/
|
|
229133
229199
|
buildSkillFile(skillId, path46, content3, now) {
|
|
229134
229200
|
const bytes2 = new TextEncoder().encode(content3);
|
|
229135
|
-
const blobHash = (0,
|
|
229201
|
+
const blobHash = (0, import_node_crypto53.createHash)("sha256").update(bytes2).digest("hex");
|
|
229136
229202
|
return { skillId, path: path46, content: content3, blobHash, size: bytes2.length, updatedAt: now };
|
|
229137
229203
|
}
|
|
229138
229204
|
/**
|
|
@@ -230255,15 +230321,15 @@ ${input.description}
|
|
|
230255
230321
|
return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
|
|
230256
230322
|
}
|
|
230257
230323
|
encrypt(plain) {
|
|
230258
|
-
const iv = (0,
|
|
230259
|
-
const cipher = (0,
|
|
230324
|
+
const iv = (0, import_node_crypto53.randomBytes)(12);
|
|
230325
|
+
const cipher = (0, import_node_crypto53.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
230260
230326
|
const enc3 = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
|
|
230261
230327
|
return [iv.toString("base64"), cipher.getAuthTag().toString("base64"), enc3.toString("base64")].join(".");
|
|
230262
230328
|
}
|
|
230263
230329
|
decrypt(packed) {
|
|
230264
230330
|
const [iv, tag, data] = packed.split(".");
|
|
230265
230331
|
if (!iv || !tag || typeof data !== "string") throw new Error("malformed ciphertext");
|
|
230266
|
-
const decipher = (0,
|
|
230332
|
+
const decipher = (0, import_node_crypto53.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
|
|
230267
230333
|
decipher.setAuthTag(Buffer.from(tag, "base64"));
|
|
230268
230334
|
return Buffer.concat([decipher.update(Buffer.from(data, "base64")), decipher.final()]).toString("utf8");
|
|
230269
230335
|
}
|
|
@@ -230876,7 +230942,7 @@ async function listSkillMetadataForActor(args) {
|
|
|
230876
230942
|
usedDirs.add(dir);
|
|
230877
230943
|
const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
230878
230944
|
let latest = "1970-01-01T00:00:00.000Z";
|
|
230879
|
-
const hasher = (0,
|
|
230945
|
+
const hasher = (0, import_node_crypto54.createHash)("sha256");
|
|
230880
230946
|
for (const m2 of sorted) {
|
|
230881
230947
|
if (m2.updatedAt > latest) latest = m2.updatedAt;
|
|
230882
230948
|
hasher.update(m2.path);
|
|
@@ -230901,11 +230967,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
230901
230967
|
const dir = sanitizeSkillDir(c.name, c.slug);
|
|
230902
230968
|
if (usedDirs.has(dir)) continue;
|
|
230903
230969
|
usedDirs.add(dir);
|
|
230904
|
-
const hasher = (0,
|
|
230970
|
+
const hasher = (0, import_node_crypto54.createHash)("sha256");
|
|
230905
230971
|
for (const p2 of paths) {
|
|
230906
230972
|
hasher.update(p2);
|
|
230907
230973
|
hasher.update("\0");
|
|
230908
|
-
hasher.update((0,
|
|
230974
|
+
hasher.update((0, import_node_crypto54.createHash)("sha256").update(c.files[p2]).digest("hex"));
|
|
230909
230975
|
hasher.update("\0");
|
|
230910
230976
|
}
|
|
230911
230977
|
out.push({
|
|
@@ -230926,11 +230992,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
230926
230992
|
const dir = sanitizeSkillDir(b2.name, b2.id);
|
|
230927
230993
|
if (usedDirs.has(dir)) continue;
|
|
230928
230994
|
usedDirs.add(dir);
|
|
230929
|
-
const hasher = (0,
|
|
230995
|
+
const hasher = (0, import_node_crypto54.createHash)("sha256");
|
|
230930
230996
|
for (const p2 of paths) {
|
|
230931
230997
|
hasher.update(p2);
|
|
230932
230998
|
hasher.update("\0");
|
|
230933
|
-
hasher.update((0,
|
|
230999
|
+
hasher.update((0, import_node_crypto54.createHash)("sha256").update(b2.files[p2]).digest("hex"));
|
|
230934
231000
|
hasher.update("\0");
|
|
230935
231001
|
}
|
|
230936
231002
|
out.push({
|
|
@@ -230950,7 +231016,7 @@ function builtinSkillToFiles(b2) {
|
|
|
230950
231016
|
skillId: `builtin:${b2.id}`,
|
|
230951
231017
|
path: path46,
|
|
230952
231018
|
content: content3,
|
|
230953
|
-
blobHash: (0,
|
|
231019
|
+
blobHash: (0, import_node_crypto54.createHash)("sha256").update(content3).digest("hex"),
|
|
230954
231020
|
size: Buffer.byteLength(content3, "utf8"),
|
|
230955
231021
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
230956
231022
|
}));
|
|
@@ -230974,7 +231040,7 @@ function sanitizeSkillDir(name, fallbackId) {
|
|
|
230974
231040
|
if (byName) return byName;
|
|
230975
231041
|
const byId = fallbackId ? fold2(fallbackId) : "";
|
|
230976
231042
|
if (byId) return byId;
|
|
230977
|
-
return `skill-${(0,
|
|
231043
|
+
return `skill-${(0, import_node_crypto54.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`;
|
|
230978
231044
|
}
|
|
230979
231045
|
async function materializeSkillFiles(args) {
|
|
230980
231046
|
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
@@ -231007,7 +231073,7 @@ function connectorSkillToFiles(c) {
|
|
|
231007
231073
|
skillId: c.id,
|
|
231008
231074
|
path: path46,
|
|
231009
231075
|
content: content3,
|
|
231010
|
-
blobHash: (0,
|
|
231076
|
+
blobHash: (0, import_node_crypto54.createHash)("sha256").update(content3).digest("hex"),
|
|
231011
231077
|
size: Buffer.byteLength(content3, "utf8"),
|
|
231012
231078
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
231013
231079
|
}));
|
|
@@ -231024,11 +231090,11 @@ function connectorSkillDisplayRows(connectorSkills, enabledConnectors) {
|
|
|
231024
231090
|
...s2.version !== void 0 ? { version: s2.version } : {}
|
|
231025
231091
|
}));
|
|
231026
231092
|
}
|
|
231027
|
-
var
|
|
231093
|
+
var import_node_crypto54;
|
|
231028
231094
|
var init_skill_materializer = __esm({
|
|
231029
231095
|
"../server/src/domains/actors/skill-materializer.ts"() {
|
|
231030
231096
|
"use strict";
|
|
231031
|
-
|
|
231097
|
+
import_node_crypto54 = require("node:crypto");
|
|
231032
231098
|
}
|
|
231033
231099
|
});
|
|
231034
231100
|
|
|
@@ -232800,54 +232866,6 @@ var init_credential_audit_log = __esm({
|
|
|
232800
232866
|
}
|
|
232801
232867
|
});
|
|
232802
232868
|
|
|
232803
|
-
// ../server/src/domains/actors/registry-audit-sink.ts
|
|
232804
|
-
function createRegistryAuditSink(file) {
|
|
232805
|
-
const listeners = /* @__PURE__ */ new Set();
|
|
232806
|
-
const notify = (msg) => {
|
|
232807
|
-
for (const listener of listeners) listener(msg);
|
|
232808
|
-
};
|
|
232809
|
-
return {
|
|
232810
|
-
/** 登记审计:落盘 + 推 registry 通知(前端据此重拉登记类投影)。 */
|
|
232811
|
-
registryAudit: (record9) => {
|
|
232812
|
-
fs24.appendFile(file, JSON.stringify(record9) + "\n", () => {
|
|
232813
|
-
});
|
|
232814
|
-
notify({ kind: record9.kind, actor: record9.actor, target: record9.target, timestamp: record9.timestamp });
|
|
232815
|
-
},
|
|
232816
|
-
/**
|
|
232817
|
-
* 凭据审计(ADR 凭据保险库 §4.7):与登记审计同落一份旁账,按 kind 前缀 `credential_` 区分。
|
|
232818
|
-
*
|
|
232819
|
-
* **只落盘、不推 registry 通知**(D-10 推送面)。registry 通知是实例级的,`/api/events` 原样转发给
|
|
232820
|
-
* 任何已认证的连接、不分组织;凭据事件推进去 = 别家组织开一条 SSE 就能实时看到「谁在读/改哪个变量」。
|
|
232821
|
-
* 仓内没有任何消费方订它(2.0 前端只订无内容的 runtime-status,而后者本来就不被凭据事件唤醒)。
|
|
232822
|
-
* 要看凭据审计走 `GET /api/variables/reveal-audit`(按请求方组织过滤)。将来若需要实时推送,
|
|
232823
|
-
* 得先让通知带组织、`/api/events` 按组织过滤(recvvzbhOGiS7l 的完整修复),再放回来。
|
|
232824
|
-
*/
|
|
232825
|
-
credentialAudit: (record9) => {
|
|
232826
|
-
fs24.appendFile(file, JSON.stringify(record9) + "\n", () => {
|
|
232827
|
-
});
|
|
232828
|
-
},
|
|
232829
|
-
/** runtime 状态变了:只发无内容的失效提示(ADR 0576)。 */
|
|
232830
|
-
notifyRuntimeStatus: () => {
|
|
232831
|
-
notify({ kind: "runtime_status_changed", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
|
|
232832
|
-
},
|
|
232833
|
-
notifications: {
|
|
232834
|
-
subscribe(listener) {
|
|
232835
|
-
listeners.add(listener);
|
|
232836
|
-
return () => {
|
|
232837
|
-
listeners.delete(listener);
|
|
232838
|
-
};
|
|
232839
|
-
}
|
|
232840
|
-
}
|
|
232841
|
-
};
|
|
232842
|
-
}
|
|
232843
|
-
var fs24;
|
|
232844
|
-
var init_registry_audit_sink = __esm({
|
|
232845
|
-
"../server/src/domains/actors/registry-audit-sink.ts"() {
|
|
232846
|
-
"use strict";
|
|
232847
|
-
fs24 = __toESM(require("node:fs"), 1);
|
|
232848
|
-
}
|
|
232849
|
-
});
|
|
232850
|
-
|
|
232851
232869
|
// ../server/src/domains/actors/stop-on-delete.ts
|
|
232852
232870
|
function planStopForDeletedActor(actorId, open3) {
|
|
232853
232871
|
const mine = open3.filter((row) => row.actorId === actorId);
|
|
@@ -233074,7 +233092,7 @@ function createActorsDomain(opts) {
|
|
|
233074
233092
|
...kernel !== void 0 ? { onRolesChanged: (a, r) => kernel.setActorRoles(a, r) } : {},
|
|
233075
233093
|
audit: async (entry) => {
|
|
233076
233094
|
await opts.audit?.({
|
|
233077
|
-
id: `reg_${(0,
|
|
233095
|
+
id: `reg_${(0, import_node_crypto55.randomUUID)()}`,
|
|
233078
233096
|
actor: entry.by,
|
|
233079
233097
|
kind: "registry_change",
|
|
233080
233098
|
target: entry.actorId,
|
|
@@ -233114,11 +233132,11 @@ function createActorsDomain(opts) {
|
|
|
233114
233132
|
register: actorsDomain({ resolveCtx, ...opts.resolveTrace ? { resolveTrace: opts.resolveTrace } : {}, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {}, ...opts.resolveDispatchScope ? { resolveDispatchScope: opts.resolveDispatchScope } : {}, ...opts.projectExists ? { projectExists: opts.projectExists } : {}, ...opts.companyMemberRole ? { companyMemberRole: opts.companyMemberRole } : {}, ...opts.credentialAudit ? { credentialAudit: opts.credentialAudit } : {}, ...opts.readCredentialAudit ? { readCredentialAudit: opts.readCredentialAudit } : {}, ...opts.credentialRevealLimits ? { credentialRevealLimits: opts.credentialRevealLimits } : {}, ...opts.skillMarket ? { skillMarket: opts.skillMarket } : {}, ...opts.resolveNodeTenancy ? { resolveNodeTenancy: opts.resolveNodeTenancy } : {} })
|
|
233115
233133
|
};
|
|
233116
233134
|
}
|
|
233117
|
-
var
|
|
233135
|
+
var import_node_crypto55;
|
|
233118
233136
|
var init_actors = __esm({
|
|
233119
233137
|
"../server/src/domains/actors/index.ts"() {
|
|
233120
233138
|
"use strict";
|
|
233121
|
-
|
|
233139
|
+
import_node_crypto55 = require("node:crypto");
|
|
233122
233140
|
init_service5();
|
|
233123
233141
|
init_routes3();
|
|
233124
233142
|
init_service5();
|
|
@@ -234811,6 +234829,9 @@ function isDispatchLayerFailure(detail) {
|
|
|
234811
234829
|
const reason = detail?.reason;
|
|
234812
234830
|
return typeof reason === "string" && reason.startsWith("dispatch ");
|
|
234813
234831
|
}
|
|
234832
|
+
function externalRefOf(a) {
|
|
234833
|
+
return a.contentKind === "external" && a.contentRef ? { externalRef: a.contentRef } : {};
|
|
234834
|
+
}
|
|
234814
234835
|
function buildWorkorderActivity(input) {
|
|
234815
234836
|
const { workorderId, snap, events } = input;
|
|
234816
234837
|
const ref2 = input.ref ?? ((id) => ({ id }));
|
|
@@ -234838,7 +234859,7 @@ function buildWorkorderActivity(input) {
|
|
|
234838
234859
|
} else if (isRootBrief) {
|
|
234839
234860
|
list2.push({ id: a.id, revisionId: a.workId, name: "\u4EFB\u52A1\u76EE\u6807", path: "\u4EFB\u52A1\u76EE\u6807.md", nodeId });
|
|
234840
234861
|
} else {
|
|
234841
|
-
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId });
|
|
234862
|
+
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId, ...externalRefOf(a) });
|
|
234842
234863
|
}
|
|
234843
234864
|
artifactsByWork.set(a.workId, list2);
|
|
234844
234865
|
}
|
|
@@ -235197,6 +235218,7 @@ function buildWorkorderActivity(input) {
|
|
|
235197
235218
|
const workOfIssue = /* @__PURE__ */ new Map();
|
|
235198
235219
|
const reasonWorksOfIssue = /* @__PURE__ */ new Map();
|
|
235199
235220
|
const recoveryLetterIssueIds = /* @__PURE__ */ new Set();
|
|
235221
|
+
const backpressureIssueIds = /* @__PURE__ */ new Set();
|
|
235200
235222
|
const plainComments = [];
|
|
235201
235223
|
const escalations = [];
|
|
235202
235224
|
const gapCreatedSeq = /* @__PURE__ */ new Map();
|
|
@@ -235428,6 +235450,7 @@ function buildWorkorderActivity(input) {
|
|
|
235428
235450
|
const isGap = issueKind === "gap";
|
|
235429
235451
|
const raisedFrom = str5(ev.raisedByNodeId);
|
|
235430
235452
|
const isBackpressure = !isEscalation && !isGap && !!raisedFrom && raisedFrom !== nodeId;
|
|
235453
|
+
if (isBackpressure) backpressureIssueIds.add(issueId);
|
|
235431
235454
|
const body2 = str5(ev.body) ?? "";
|
|
235432
235455
|
if (isEscalation) {
|
|
235433
235456
|
const linkedGapId = str5(ev.gapId);
|
|
@@ -235475,6 +235498,11 @@ function buildWorkorderActivity(input) {
|
|
|
235475
235498
|
/* 回压是**执行中断**(这一轮走不下去了,要外部介入);唤醒信那档不是中断,仍是进行中。
|
|
235476
235499
|
缺口走不到这里了(F4 在上面 break)。 */
|
|
235477
235500
|
phase: isBackpressure ? "stuck" : "running",
|
|
235501
|
+
/* 回压卡**不喊**:砖红只给「此刻等人动手」的那张(奕璇 2026-09-22)。轮到动手的是被回压节点的
|
|
235502
|
+
负责人——真人时由他那一轮喊(砖红 + 去处理),agent 时它自己在跑(暖橙)。提要求这一段在
|
|
235503
|
+
开口那一刻就结束了,与缺口中断的执行卡同一条先例(F1:上一段结束就转灰,该喊的是下游那张)。
|
|
235504
|
+
不写这两个字段时前端退回老规则(开着 + stuck ⇒ 砖红),同一件事页面上会有两张红卡。 */
|
|
235505
|
+
...isBackpressure ? { segmentOpen: false, awaitingHuman: false } : {},
|
|
235478
235506
|
status: isBackpressure ? ACTIVITY_COPY.backpressure(
|
|
235479
235507
|
nameOf2(authorId),
|
|
235480
235508
|
nodeName(nodeId),
|
|
@@ -235484,11 +235512,15 @@ function buildWorkorderActivity(input) {
|
|
|
235484
235512
|
此前只有缺口/回压被排除,留言仍是「正文当小状态 + 展开区再印一遍」,
|
|
235485
235513
|
全库实测最长 8096 字印两遍(`ws:wo-56bba3c1`),一张卡顶掉整屏。 */
|
|
235486
235514
|
artifacts: [],
|
|
235487
|
-
/*
|
|
235488
|
-
|
|
235489
|
-
|
|
235490
|
-
|
|
235491
|
-
|
|
235515
|
+
/* 按钮只长在「人能点、而且轮到人动手」的那张卡上(奕璇 2026-09-22):
|
|
235516
|
+
· 回压卡**一个按钮都没有**:它署名的是提要求的一方(多为 agent),轮到动手的是被回压节点的
|
|
235517
|
+
负责人。负责人是真人时「去处理」挂在系统给他开的那一轮上(见事件循环之后
|
|
235518
|
+
`backpressureAwaitingOwner` 那一段),落点、target 与原先这颗一样;负责人是 agent 时
|
|
235519
|
+
它自己会跑,没有人要动手。
|
|
235520
|
+
· 唤醒信给「查看沟通」直达留言线——线是投影出来的、恒存在,id 这里就能算。
|
|
235521
|
+
· 唤醒信算不出对面是谁(该产物没负责人 / 负责人就是作者)时退回「去处理」,但**只在署名的
|
|
235522
|
+
是真人时**给:agent / 系统署名的卡挂「去处理」,点的人进去没有一件是他该做的事。 */
|
|
235523
|
+
actions: isBackpressure ? [] : !commentTargetId ? isHumanActorId(authorId) ? [{ kind: "open_issue", label: BUTTON.handle, target: issueId }] : [] : [{ kind: "open_thread", label: BUTTON.view, target: commentThreadSessionId(authorId, commentTargetId), variant: "quiet" }]
|
|
235492
235524
|
});
|
|
235493
235525
|
break;
|
|
235494
235526
|
}
|
|
@@ -235799,6 +235831,18 @@ function buildWorkorderActivity(input) {
|
|
|
235799
235831
|
const message = (input.runFailures ?? []).filter((f2) => f2.nodeId === card2.nodeId && f2.startedAt >= card2.at && f2.startedAt <= trip.at && f2.message.trim()).sort((a, b2) => a.startedAt.localeCompare(b2.startedAt)).at(-1)?.message;
|
|
235800
235832
|
return message ? firstSentence(message) : void 0;
|
|
235801
235833
|
};
|
|
235834
|
+
for (const card2 of executionCards) {
|
|
235835
|
+
const workId = card2.openWorkId;
|
|
235836
|
+
if (!workId || !isHumanActorId(card2.executorId)) continue;
|
|
235837
|
+
const issueId = [...backpressureIssueIds].find((id) => reasonWorksOfIssue.get(id)?.includes(workId) && !issueById.get(id)?.resolvedAt && !plainResolveEvents.has(id));
|
|
235838
|
+
if (!issueId) continue;
|
|
235839
|
+
card2.phase = "not_started";
|
|
235840
|
+
card2.phaseLabel = PHASE_LABEL.escalationPending;
|
|
235841
|
+
card2.segmentOpen = true;
|
|
235842
|
+
card2.awaitingHuman = true;
|
|
235843
|
+
card2.status = ACTIVITY_COPY.backpressureAwaitingOwner(nameOf2(card2.executorId), nodeName(card2.nodeId));
|
|
235844
|
+
card2.actions = [{ kind: "open_issue", label: BUTTON.handle, target: issueId, variant: "primary" }];
|
|
235845
|
+
}
|
|
235802
235846
|
for (const card2 of executionCards) {
|
|
235803
235847
|
const trips = card2.stopLossTrips;
|
|
235804
235848
|
if (!trips?.length) continue;
|
|
@@ -236310,6 +236354,11 @@ var init_activity2 = __esm({
|
|
|
236310
236354
|
①「缺口卡」也删掉(F4):它和执行卡挂的是同一段运行、同一份轨迹,点哪张打开的都一样。 */
|
|
236311
236355
|
/** 回压(下游对上游提修改要求)——发起人 2026-09-08 认可的措辞。 */
|
|
236312
236356
|
backpressure: (raiser, upstream, owner) => `${raiser} \u5BF9\u300A${upstream}\u300B\u63D0\u51FA\u4FEE\u6539\u8981\u6C42\uFF0C\u9700\u8981 @${owner} \u5904\u7406\u3002`,
|
|
236357
|
+
/**
|
|
236358
|
+
* 被回压节点的负责人是**真人**时,系统为他开的那一轮(奕璇 2026-09-22 定):这一轮不会自己跑,
|
|
236359
|
+
* 是在等他动手——不能再说「正在根据反馈调整」(`issueDriven`),那句会让一张没人在动的卡挂成「进行中」。
|
|
236360
|
+
*/
|
|
236361
|
+
backpressureAwaitingOwner: (owner, node2) => `\u7B49 @${owner} \u6839\u636E\u4FEE\u6539\u8981\u6C42\u8C03\u6574\u300A${node2}\u300B\u3002`,
|
|
236313
236362
|
/**
|
|
236314
236363
|
* 留言 / 批注——**一句索引,正文不上卡**(发起人 2026-09-09 定)。
|
|
236315
236364
|
*
|
|
@@ -236393,7 +236442,10 @@ var init_activity2 = __esm({
|
|
|
236393
236442
|
* 所以仍然要 override,只是换成和 `stuck` 一族同一个词。
|
|
236394
236443
|
*/
|
|
236395
236444
|
failed: "\u6267\u884C\u4E2D\u65AD",
|
|
236396
|
-
/**
|
|
236445
|
+
/**
|
|
236446
|
+
* 升级卡没人处理那一档。**不写「待你处理」**:别人看到的字要和该处理的人看到的一样。
|
|
236447
|
+
* 被回压的真人负责人那一轮(等他按修改要求动手)也用这个词——同样是「这一段卡在人身上」。
|
|
236448
|
+
*/
|
|
236397
236449
|
escalationPending: "\u5F85\u5904\u7406"
|
|
236398
236450
|
};
|
|
236399
236451
|
COORDINATOR_CARD_PREFIX = "coordinator:";
|
|
@@ -236552,7 +236604,7 @@ function artifactsOfWork(work, input) {
|
|
|
236552
236604
|
} else if (isRootBrief) {
|
|
236553
236605
|
list2.push({ id: a.id, revisionId: a.workId, name: "\u4EFB\u52A1\u76EE\u6807", path: "\u4EFB\u52A1\u76EE\u6807.md", nodeId: artifactNodeId });
|
|
236554
236606
|
} else {
|
|
236555
|
-
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId: artifactNodeId });
|
|
236607
|
+
list2.push({ id: a.id, revisionId: a.workId, name: a.name, nodeId: artifactNodeId, ...externalRefOf(a) });
|
|
236556
236608
|
}
|
|
236557
236609
|
}
|
|
236558
236610
|
return list2;
|
|
@@ -237602,11 +237654,11 @@ function fromRow(row) {
|
|
|
237602
237654
|
for (const [k2, v2] of opt) if (v2 !== void 0 && v2 !== null) r[k2] = v2;
|
|
237603
237655
|
return r;
|
|
237604
237656
|
}
|
|
237605
|
-
var
|
|
237657
|
+
var import_node_crypto56, import_node_fs16, DEFAULT_PAGE, MAX_PAGE, pageSize, MemoryNotificationStore, ident3, iso2, str2, PostgresNotificationStore;
|
|
237606
237658
|
var init_notification_store = __esm({
|
|
237607
237659
|
"../server/src/domains/collab/notification-store.ts"() {
|
|
237608
237660
|
"use strict";
|
|
237609
|
-
|
|
237661
|
+
import_node_crypto56 = require("node:crypto");
|
|
237610
237662
|
import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
237611
237663
|
DEFAULT_PAGE = 50;
|
|
237612
237664
|
MAX_PAGE = 200;
|
|
@@ -237639,7 +237691,7 @@ var init_notification_store = __esm({
|
|
|
237639
237691
|
async insert(n) {
|
|
237640
237692
|
const existing = this.findLive(n.recipient, n.sourceKey, n.category);
|
|
237641
237693
|
if (existing) return existing;
|
|
237642
|
-
const row = { ...n, id: `ntf:${(0,
|
|
237694
|
+
const row = { ...n, id: `ntf:${(0, import_node_crypto56.randomUUID)()}`, updatedAt: n.enteredAt };
|
|
237643
237695
|
this.rows.set(row.id, row);
|
|
237644
237696
|
this.save();
|
|
237645
237697
|
return row;
|
|
@@ -237772,7 +237824,7 @@ var init_notification_store = __esm({
|
|
|
237772
237824
|
return new _PostgresNotificationStore(sql, schema);
|
|
237773
237825
|
}
|
|
237774
237826
|
async insert(n) {
|
|
237775
|
-
const id = `ntf:${(0,
|
|
237827
|
+
const id = `ntf:${(0, import_node_crypto56.randomUUID)()}`;
|
|
237776
237828
|
const r = await this.sql.query(
|
|
237777
237829
|
`INSERT INTO ${this.t} (id, recipient, category, source_key, kind, workorder_id, node_id, card_id, actor_id,
|
|
237778
237830
|
title, workspace_title, entered_at, updated_at, status, read_at, item)
|
|
@@ -239780,13 +239832,13 @@ function nameKey(name) {
|
|
|
239780
239832
|
function cleanName(name) {
|
|
239781
239833
|
return name.trim().replace(/\s+/g, " ");
|
|
239782
239834
|
}
|
|
239783
|
-
var import_node_fs17, import_node_path21,
|
|
239835
|
+
var import_node_fs17, import_node_path21, import_node_crypto57, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
239784
239836
|
var init_tags = __esm({
|
|
239785
239837
|
"../server/src/domains/collab/tags.ts"() {
|
|
239786
239838
|
"use strict";
|
|
239787
239839
|
import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
239788
239840
|
import_node_path21 = __toESM(require("node:path"), 1);
|
|
239789
|
-
|
|
239841
|
+
import_node_crypto57 = __toESM(require("node:crypto"), 1);
|
|
239790
239842
|
SEP = "::";
|
|
239791
239843
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
239792
239844
|
prefixOf = (companyId) => `${companyId}${SEP}`;
|
|
@@ -239804,7 +239856,7 @@ var init_tags = __esm({
|
|
|
239804
239856
|
if (!name) return null;
|
|
239805
239857
|
if (this.entries(companyId).some((t) => nameKey(t.name) === nameKey(name))) return null;
|
|
239806
239858
|
const tag = {
|
|
239807
|
-
id: `tag-${
|
|
239859
|
+
id: `tag-${import_node_crypto57.default.randomBytes(6).toString("hex")}`,
|
|
239808
239860
|
name,
|
|
239809
239861
|
...input.color?.trim() ? { color: input.color.trim() } : {},
|
|
239810
239862
|
...input.description?.trim() ? { description: input.description.trim() } : {}
|
|
@@ -241193,11 +241245,11 @@ async function isEmployedElsewhere(store, companyId, accountId) {
|
|
|
241193
241245
|
const memberships = await store.listMembershipsForAccount(accountId);
|
|
241194
241246
|
return memberships.some((m2) => m2.companyId !== companyId);
|
|
241195
241247
|
}
|
|
241196
|
-
var
|
|
241248
|
+
var import_node_crypto58, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, INVITE_LINK_TTL_MS, INVITE_LINK_TOKEN_BYTES, INVITE_LINK_ROLE, SLUG_RE, CompanyError, CompaniesService;
|
|
241197
241249
|
var init_service6 = __esm({
|
|
241198
241250
|
"../server/src/domains/companies/service.ts"() {
|
|
241199
241251
|
"use strict";
|
|
241200
|
-
|
|
241252
|
+
import_node_crypto58 = require("node:crypto");
|
|
241201
241253
|
init_console_url();
|
|
241202
241254
|
ROLES = ["owner", "admin", "member"];
|
|
241203
241255
|
INVITABLE_ROLES = ["admin", "member"];
|
|
@@ -241289,7 +241341,7 @@ var init_service6 = __esm({
|
|
|
241289
241341
|
const existing = await this.store.getAccountByEmail(normalized4);
|
|
241290
241342
|
if (existing) return existing;
|
|
241291
241343
|
const account = {
|
|
241292
|
-
id: `actor:human:${(0,
|
|
241344
|
+
id: `actor:human:${(0, import_node_crypto58.randomUUID)()}`,
|
|
241293
241345
|
email: normalized4,
|
|
241294
241346
|
name: name ?? normalized4,
|
|
241295
241347
|
status: "active"
|
|
@@ -241498,7 +241550,7 @@ var init_service6 = __esm({
|
|
|
241498
241550
|
}
|
|
241499
241551
|
const nowMs = Date.parse(this.now());
|
|
241500
241552
|
const invitation = {
|
|
241501
|
-
id: `invitation:${(0,
|
|
241553
|
+
id: `invitation:${(0, import_node_crypto58.randomUUID)()}`,
|
|
241502
241554
|
companyId,
|
|
241503
241555
|
email: mail,
|
|
241504
241556
|
role,
|
|
@@ -241629,7 +241681,7 @@ var init_service6 = __esm({
|
|
|
241629
241681
|
const nowMs = Date.parse(this.now());
|
|
241630
241682
|
const link = {
|
|
241631
241683
|
companyId,
|
|
241632
|
-
token: (0,
|
|
241684
|
+
token: (0, import_node_crypto58.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
|
|
241633
241685
|
role: INVITE_LINK_ROLE,
|
|
241634
241686
|
createdAt: new Date(nowMs).toISOString(),
|
|
241635
241687
|
expiresAt: new Date(nowMs + INVITE_LINK_TTL_MS).toISOString(),
|
|
@@ -241686,7 +241738,7 @@ var init_service6 = __esm({
|
|
|
241686
241738
|
const reusable = existing.find((inv) => !this.isExpired(inv));
|
|
241687
241739
|
if (reusable) return reusable;
|
|
241688
241740
|
const invitation = {
|
|
241689
|
-
id: `invitation:${(0,
|
|
241741
|
+
id: `invitation:${(0, import_node_crypto58.randomUUID)()}`,
|
|
241690
241742
|
companyId: link.companyId,
|
|
241691
241743
|
email: mail,
|
|
241692
241744
|
role: link.role,
|
|
@@ -241924,11 +241976,11 @@ var init_service6 = __esm({
|
|
|
241924
241976
|
});
|
|
241925
241977
|
|
|
241926
241978
|
// ../server/src/domains/companies/offboarding.ts
|
|
241927
|
-
var
|
|
241979
|
+
var import_node_crypto59, MemberOffboardingService;
|
|
241928
241980
|
var init_offboarding = __esm({
|
|
241929
241981
|
"../server/src/domains/companies/offboarding.ts"() {
|
|
241930
241982
|
"use strict";
|
|
241931
|
-
|
|
241983
|
+
import_node_crypto59 = require("node:crypto");
|
|
241932
241984
|
init_service6();
|
|
241933
241985
|
MemberOffboardingService = class {
|
|
241934
241986
|
store;
|
|
@@ -242000,7 +242052,7 @@ var init_offboarding = __esm({
|
|
|
242000
242052
|
const { ownedAgents, inFlight } = await this.snapshot(companyId, accountId);
|
|
242001
242053
|
const at2 = this.now();
|
|
242002
242054
|
const started = await this.store.startMemberOffboarding({
|
|
242003
|
-
operationId: `off:${(0,
|
|
242055
|
+
operationId: `off:${(0, import_node_crypto59.randomUUID)()}`,
|
|
242004
242056
|
companyId,
|
|
242005
242057
|
accountId,
|
|
242006
242058
|
initiatedBy,
|
|
@@ -242510,18 +242562,18 @@ var init_routes6 = __esm({
|
|
|
242510
242562
|
|
|
242511
242563
|
// ../server/src/domains/companies/agent-credentials.ts
|
|
242512
242564
|
function hashAgentToken(token, secret) {
|
|
242513
|
-
return HASH_PREFIX + (0,
|
|
242565
|
+
return HASH_PREFIX + (0, import_node_crypto60.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
|
|
242514
242566
|
}
|
|
242515
242567
|
function safeEqual(a, b2) {
|
|
242516
242568
|
const ba = Buffer.from(a);
|
|
242517
242569
|
const bb = Buffer.from(b2);
|
|
242518
|
-
return ba.length === bb.length && (0,
|
|
242570
|
+
return ba.length === bb.length && (0, import_node_crypto60.timingSafeEqual)(ba, bb);
|
|
242519
242571
|
}
|
|
242520
|
-
var
|
|
242572
|
+
var import_node_crypto60, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
|
|
242521
242573
|
var init_agent_credentials = __esm({
|
|
242522
242574
|
"../server/src/domains/companies/agent-credentials.ts"() {
|
|
242523
242575
|
"use strict";
|
|
242524
|
-
|
|
242576
|
+
import_node_crypto60 = require("node:crypto");
|
|
242525
242577
|
init_service6();
|
|
242526
242578
|
HASH_PREFIX = "ac1$";
|
|
242527
242579
|
TOKEN_PREFIX = "oak_";
|
|
@@ -242546,7 +242598,7 @@ var init_agent_credentials = __esm({
|
|
|
242546
242598
|
if (employee.status !== "active") {
|
|
242547
242599
|
throw new CompanyError(409, "AGENT_LEFT", `\u6570\u5B57\u5458\u5DE5\u5DF2\u79BB\u5F00\uFF0C\u4E0D\u80FD\u7B7E\u53D1\u51ED\u8BC1\uFF1A${agentId}`);
|
|
242548
242600
|
}
|
|
242549
|
-
const token = `${TOKEN_PREFIX}${(0,
|
|
242601
|
+
const token = `${TOKEN_PREFIX}${(0, import_node_crypto60.randomBytes)(32).toString("base64url")}`;
|
|
242550
242602
|
const credential = {
|
|
242551
242603
|
tokenHash: hashAgentToken(token, this.secret),
|
|
242552
242604
|
companyId,
|
|
@@ -243037,7 +243089,7 @@ function gatewayInstanceSlug(gatewayUrl) {
|
|
|
243037
243089
|
}
|
|
243038
243090
|
function connectInstanceName(gatewayUrl, token, companyId) {
|
|
243039
243091
|
const scope2 = companyId?.trim();
|
|
243040
|
-
const suffix = scope2 ? `c${(0,
|
|
243092
|
+
const suffix = scope2 ? `c${(0, import_node_crypto61.createHash)("sha256").update(`${gatewayUrl}\0${scope2}`).digest("hex").slice(0, 10)}` : token.replace(/[^a-z0-9]/gi, "").slice(-8).toLowerCase() || "enroll";
|
|
243041
243093
|
const base = gatewayInstanceSlug(gatewayUrl);
|
|
243042
243094
|
return base.slice(0, Math.max(1, 64 - suffix.length - 1)) + "-" + suffix;
|
|
243043
243095
|
}
|
|
@@ -243366,12 +243418,12 @@ function buildNpxCmd(p2) {
|
|
|
243366
243418
|
const prefix = daemonNpmPrefix();
|
|
243367
243419
|
return `npm install -g --prefer-online --prefix ${prefix} ${DAEMON_NPM_PACKAGE}@latest && ${prefix}/bin/oasis daemon start --instance ${shellQuote(instanceName)} --server-ws ${shellQuote(p2.gatewayUrl)}${companyPart}${namePart} --pkg ${shellQuote(DAEMON_NPM_PACKAGE)} --upgrade --enroll-token ${shellQuote(p2.token)}`;
|
|
243368
243420
|
}
|
|
243369
|
-
var
|
|
243421
|
+
var import_node_crypto61;
|
|
243370
243422
|
var init_connect_script = __esm({
|
|
243371
243423
|
"../server/src/domains/nodes/connect-script.ts"() {
|
|
243372
243424
|
"use strict";
|
|
243373
243425
|
init_src();
|
|
243374
|
-
|
|
243426
|
+
import_node_crypto61 = require("node:crypto");
|
|
243375
243427
|
}
|
|
243376
243428
|
});
|
|
243377
243429
|
|
|
@@ -243731,6 +243783,10 @@ function nodesDomain(deps) {
|
|
|
243731
243783
|
}
|
|
243732
243784
|
if (rows.length > 0) console.log(`[nodes] \u989D\u5EA6\u6C34\u5408\uFF1A\u4ECE\u5E93\u91CC\u8BFB\u56DE ${rows.length} \u6761\u8FD0\u884C\u65F6\u989D\u5EA6`);
|
|
243733
243785
|
}).catch((err) => console.warn(`[nodes] \u989D\u5EA6\u6C34\u5408\u5931\u8D25\uFF08\u7167\u65E7\u7B49\u4E0B\u4E00\u6B21\u91C7\u96C6\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`));
|
|
243786
|
+
const quotaRefreshWaiters = /* @__PURE__ */ new Map();
|
|
243787
|
+
const quotaRefreshInFlight = /* @__PURE__ */ new Map();
|
|
243788
|
+
const QUOTA_REFRESH_TIMEOUT_MS = 4e4;
|
|
243789
|
+
const QUOTA_CAPABLE_KINDS = /* @__PURE__ */ new Set(["codex", "claude-code"]);
|
|
243734
243790
|
const UPDATE_TIMEOUT_MS = 15e4;
|
|
243735
243791
|
const nodeUpdates = /* @__PURE__ */ new Map();
|
|
243736
243792
|
function runtimeInfoOf(r) {
|
|
@@ -243812,6 +243868,45 @@ function nodesDomain(deps) {
|
|
|
243812
243868
|
}
|
|
243813
243869
|
return { version: null, source: null };
|
|
243814
243870
|
}
|
|
243871
|
+
async function refreshNodeQuotas(nodeId) {
|
|
243872
|
+
const running = quotaRefreshInFlight.get(nodeId);
|
|
243873
|
+
if (running) return running;
|
|
243874
|
+
const hub = deps.getHub();
|
|
243875
|
+
if (!hub) return { ok: false, code: "no-gateway", reason: "\u672C\u90E8\u7F72\u6CA1\u6709\u8282\u70B9\u7F51\u5173\uFF0C\u591F\u4E0D\u5230\u90A3\u53F0\u673A\u5668" };
|
|
243876
|
+
const daemon = hub.connectedDaemons().find((d) => d.daemonId === nodeId);
|
|
243877
|
+
if (!daemon) {
|
|
243878
|
+
return { ok: false, code: "offline", reason: "\u8FD9\u53F0\u8282\u70B9\u5F53\u524D\u4E0D\u5728\u7EBF\uFF0C\u770B\u5230\u7684\u662F\u5B83\u6700\u540E\u4E00\u6B21\u4E0A\u62A5\u7684\u989D\u5EA6\uFF1B\u628A\u673A\u5668\u8FDE\u56DE\u6765\u4E4B\u540E\u624D\u80FD\u91CD\u91C7" };
|
|
243879
|
+
}
|
|
243880
|
+
if (!daemon.meta.supportsQuotaRefresh) {
|
|
243881
|
+
return { ok: false, code: "unsupported-version", reason: "\u8FD9\u53F0\u8282\u70B9\u7684\u7A0B\u5E8F\u7248\u672C\u8FD8\u4E0D\u652F\u6301\u989D\u5EA6\u91CD\u91C7\uFF0C\u66F4\u65B0\u8282\u70B9\u4E4B\u540E\u53EF\u7528" };
|
|
243882
|
+
}
|
|
243883
|
+
if (!daemon.meta.adapters.some((kind) => QUOTA_CAPABLE_KINDS.has(kind))) {
|
|
243884
|
+
return { ok: false, code: "no-quota-runtime", reason: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u4F1A\u4E0A\u62A5\u989D\u5EA6\u7684\u8FD0\u884C\u65F6\uFF08\u53EA\u6709 Claude Code \u548C Codex \u80FD\u67E5\u5230\u8BA2\u9605\u989D\u5EA6\uFF09" };
|
|
243885
|
+
}
|
|
243886
|
+
const requestId = (0, import_node_crypto62.randomUUID)();
|
|
243887
|
+
const task = new Promise((resolve12) => {
|
|
243888
|
+
const timer = setTimeout(() => {
|
|
243889
|
+
quotaRefreshWaiters.delete(requestId);
|
|
243890
|
+
resolve12({ ok: false, code: "timeout", reason: `\u8FD9\u53F0\u8282\u70B9\u6CA1\u5728 ${Math.round(QUOTA_REFRESH_TIMEOUT_MS / 1e3)} \u79D2\u5185\u56DE\u8BDD\uFF0C\u9875\u9762\u4E0A\u4ECD\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u989D\u5EA6` });
|
|
243891
|
+
}, QUOTA_REFRESH_TIMEOUT_MS);
|
|
243892
|
+
quotaRefreshWaiters.set(requestId, {
|
|
243893
|
+
// 节点自己说没采(连点被最小间隔挡下、这台机器上采集出错)→ 原样把它那句话带回前端。
|
|
243894
|
+
resolve: (r) => resolve12(r.ok ? { ok: true } : { ok: false, code: "node", ...r.reason ? { reason: r.reason } : {} }),
|
|
243895
|
+
timer
|
|
243896
|
+
});
|
|
243897
|
+
const sent = hub.dispatch(nodeId, { type: "refresh_quotas", requestId });
|
|
243898
|
+
if (sent) return;
|
|
243899
|
+
const waiter = quotaRefreshWaiters.get(requestId);
|
|
243900
|
+
if (!waiter) return;
|
|
243901
|
+
quotaRefreshWaiters.delete(requestId);
|
|
243902
|
+
clearTimeout(waiter.timer);
|
|
243903
|
+
resolve12({ ok: false, code: "offline", reason: "\u6307\u4EE4\u6CA1\u9001\u5230\u8FD9\u53F0\u8282\u70B9\uFF08\u8FDE\u63A5\u521A\u65AD\u5F00\uFF09\uFF0C\u9875\u9762\u4E0A\u4ECD\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u989D\u5EA6" });
|
|
243904
|
+
}).finally(() => {
|
|
243905
|
+
quotaRefreshInFlight.delete(nodeId);
|
|
243906
|
+
});
|
|
243907
|
+
quotaRefreshInFlight.set(nodeId, task);
|
|
243908
|
+
return task;
|
|
243909
|
+
}
|
|
243815
243910
|
let hubWired = false;
|
|
243816
243911
|
function wireHub(hub) {
|
|
243817
243912
|
if (hubWired) return;
|
|
@@ -243848,6 +243943,14 @@ function nodesDomain(deps) {
|
|
|
243848
243943
|
}
|
|
243849
243944
|
})().catch((err) => console.warn(`[nodes] \u6545\u969C\u81EA\u52A8\u89E3\u9664\u5931\u8D25(node=${daemonId})\uFF1A${err instanceof Error ? err.message : String(err)}`));
|
|
243850
243945
|
});
|
|
243946
|
+
hub.addMessageListener((_daemonId, msg) => {
|
|
243947
|
+
if (msg.type !== "quota_refresh_result") return;
|
|
243948
|
+
const waiter = quotaRefreshWaiters.get(msg.requestId);
|
|
243949
|
+
if (!waiter) return;
|
|
243950
|
+
quotaRefreshWaiters.delete(msg.requestId);
|
|
243951
|
+
clearTimeout(waiter.timer);
|
|
243952
|
+
waiter.resolve({ ok: msg.ok, ...msg.reason ? { reason: msg.reason } : {} });
|
|
243953
|
+
});
|
|
243851
243954
|
hub.addMessageListener(async (daemonId, msg) => {
|
|
243852
243955
|
if (msg.type !== "hello") return;
|
|
243853
243956
|
const d = hub.connectedDaemons().find((c) => c.daemonId === daemonId);
|
|
@@ -244156,7 +244259,7 @@ function nodesDomain(deps) {
|
|
|
244156
244259
|
}
|
|
244157
244260
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
244158
244261
|
} else {
|
|
244159
|
-
nodeId = `node-${(0,
|
|
244262
|
+
nodeId = `node-${(0, import_node_crypto62.randomUUID)().slice(0, 8)}`;
|
|
244160
244263
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
244161
244264
|
}
|
|
244162
244265
|
const existingNode = await deps.nodeStore.getNode(nodeId);
|
|
@@ -244269,6 +244372,22 @@ function nodesDomain(deps) {
|
|
|
244269
244372
|
nodeUpdates.set(nodeId, tracked);
|
|
244270
244373
|
return { status: 200, body: { ok: true, alreadyLatest: false, updateStatus: publicUpdateStatus(tracked, activeRunCount) } };
|
|
244271
244374
|
});
|
|
244375
|
+
router.post("/api/nodes/:nodeId/quotas/refresh", async (req) => {
|
|
244376
|
+
const nodeId = req.params["nodeId"];
|
|
244377
|
+
if (!nodeId) return { status: 400, body: { error: "missing nodeId" } };
|
|
244378
|
+
const scope2 = req.auth.companyId !== void 0 ? { companyId: req.auth.companyId } : void 0;
|
|
244379
|
+
const node2 = (await deps.nodeStore.listNodes(scope2)).find((n) => n.id === nodeId);
|
|
244380
|
+
if (!node2) return { status: 404, body: { error: "NODE_NOT_FOUND", message: "\u8282\u70B9\u4E0D\u5B58\u5728\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u7EC4\u7EC7" } };
|
|
244381
|
+
const outcome = await refreshNodeQuotas(nodeId);
|
|
244382
|
+
return {
|
|
244383
|
+
status: 200,
|
|
244384
|
+
body: {
|
|
244385
|
+
refreshed: outcome.ok,
|
|
244386
|
+
...outcome.code ? { code: outcome.code } : {},
|
|
244387
|
+
...outcome.reason ? { reason: outcome.reason } : {}
|
|
244388
|
+
}
|
|
244389
|
+
};
|
|
244390
|
+
});
|
|
244272
244391
|
router.delete("/api/runtimes/:runtimeId", async (req) => {
|
|
244273
244392
|
const runtimeId = req.params["runtimeId"];
|
|
244274
244393
|
if (!runtimeId) return { status: 400, body: { error: "missing runtimeId" } };
|
|
@@ -244406,16 +244525,16 @@ function normalizeGatewayUrl(raw) {
|
|
|
244406
244525
|
}
|
|
244407
244526
|
}
|
|
244408
244527
|
function newNodeId() {
|
|
244409
|
-
return "node-" + (0,
|
|
244528
|
+
return "node-" + (0, import_node_crypto62.randomUUID)().replace(/-/g, "").slice(0, 12);
|
|
244410
244529
|
}
|
|
244411
|
-
var
|
|
244530
|
+
var import_node_crypto62, import_node_fs18, import_node_url6, import_node_path22, NODE_NAME_MAX_LENGTH;
|
|
244412
244531
|
var init_routes7 = __esm({
|
|
244413
244532
|
"../server/src/domains/nodes/routes.ts"() {
|
|
244414
244533
|
"use strict";
|
|
244415
244534
|
init_src();
|
|
244416
244535
|
init_faults();
|
|
244417
244536
|
init_runtime_status();
|
|
244418
|
-
|
|
244537
|
+
import_node_crypto62 = require("node:crypto");
|
|
244419
244538
|
import_node_fs18 = require("node:fs");
|
|
244420
244539
|
import_node_url6 = require("node:url");
|
|
244421
244540
|
import_node_path22 = require("node:path");
|
|
@@ -244912,9 +245031,9 @@ var init_types4 = __esm({
|
|
|
244912
245031
|
// ../server/src/domains/roles/index.ts
|
|
244913
245032
|
function rolesDomain(deps) {
|
|
244914
245033
|
return (router) => {
|
|
244915
|
-
router.get("/api/roles", async () => {
|
|
245034
|
+
router.get("/api/roles", async (req) => {
|
|
244916
245035
|
const roles = await deps.admin.list();
|
|
244917
|
-
const usageByRole = await deps.admin.usageMany(roles.map((r) => r.name));
|
|
245036
|
+
const usageByRole = await deps.admin.usageMany(roles.map((r) => r.name), req.auth.companyId);
|
|
244918
245037
|
const items = roles.map((r) => {
|
|
244919
245038
|
const u = usageByRole[r.name];
|
|
244920
245039
|
return {
|
|
@@ -244933,7 +245052,7 @@ function rolesDomain(deps) {
|
|
|
244933
245052
|
if (!name) return { status: 400, body: { error: "missing name" } };
|
|
244934
245053
|
const roles = await deps.admin.list();
|
|
244935
245054
|
if (!roles.some((r) => r.name === name)) return { status: 404, body: { error: `\u5C97\u4F4D\u4E0D\u5B58\u5728: ${name}` } };
|
|
244936
|
-
return { status: 200, body: { usage: await deps.admin.usage(name) } };
|
|
245055
|
+
return { status: 200, body: { usage: await deps.admin.usage(name, req.auth.companyId) } };
|
|
244937
245056
|
});
|
|
244938
245057
|
router.post("/api/roles", async (req) => {
|
|
244939
245058
|
const r = await deps.admin.add(req.body ?? {}, req.auth.actor);
|
|
@@ -245689,6 +245808,12 @@ var init_notification_reconciler = __esm({
|
|
|
245689
245808
|
const ctx = await this.deps.load(companyId);
|
|
245690
245809
|
if (!ctx) return EMPTY;
|
|
245691
245810
|
const stats = await this.reconcileWith(companyId, st, ctx);
|
|
245811
|
+
if (stats.notified) {
|
|
245812
|
+
try {
|
|
245813
|
+
this.deps.onNotified?.(companyId, stats.notified);
|
|
245814
|
+
} catch {
|
|
245815
|
+
}
|
|
245816
|
+
}
|
|
245692
245817
|
const tookMs = this.now - startedAt;
|
|
245693
245818
|
if (tookMs > SLOW_RECONCILE_MS) {
|
|
245694
245819
|
this.deps.log(`[notification-ledger] ${companyId} \u5BF9\u8D26\u8017\u65F6 ${tookMs}ms\uFF08\u6210\u5458 ${ctx.humans.length}\uFF0C\u5F85\u5904\u7406 ${stats.pending}\uFF0C\u672C\u6B21\u65B0\u589E ${stats.inserted} / \u7ED3\u675F ${stats.closed}\uFF09`);
|
|
@@ -245712,6 +245837,7 @@ var init_notification_reconciler = __esm({
|
|
|
245712
245837
|
const nowMs = this.now;
|
|
245713
245838
|
const nowIso = new Date(nowMs).toISOString();
|
|
245714
245839
|
const stats = { inserted: 0, refreshed: 0, closed: 0, pending: 0 };
|
|
245840
|
+
const notified = /* @__PURE__ */ new Set();
|
|
245715
245841
|
const ttl = this.deps.snapshotTtlMs ?? 5 * 6e4;
|
|
245716
245842
|
const loadSnapshot2 = async (wid) => {
|
|
245717
245843
|
const hit = st.snaps.get(wid);
|
|
@@ -245789,6 +245915,7 @@ var init_notification_reconciler = __esm({
|
|
|
245789
245915
|
});
|
|
245790
245916
|
st.lastSeenAt.set(inserted.id, nowIso);
|
|
245791
245917
|
stats.inserted++;
|
|
245918
|
+
notified.add(c.recipient);
|
|
245792
245919
|
}
|
|
245793
245920
|
const eventsOf = /* @__PURE__ */ new Map();
|
|
245794
245921
|
const cancelledOf = /* @__PURE__ */ new Map();
|
|
@@ -245805,7 +245932,7 @@ var init_notification_reconciler = __esm({
|
|
|
245805
245932
|
st.lastSeenAt.delete(row.id);
|
|
245806
245933
|
}
|
|
245807
245934
|
stats.pending = current.size;
|
|
245808
|
-
stats.notices = await this.reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2);
|
|
245935
|
+
stats.notices = await this.reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2, notified);
|
|
245809
245936
|
if (nowMs - st.lastPurgeAt > (this.deps.purgeEveryMs ?? 6 * 36e5)) {
|
|
245810
245937
|
st.lastPurgeAt = nowMs;
|
|
245811
245938
|
const purged = await ctx.store.purgeBefore(new Date(nowMs - (this.deps.retentionMs ?? 90 * DAY2)).toISOString());
|
|
@@ -245814,6 +245941,7 @@ var init_notification_reconciler = __esm({
|
|
|
245814
245941
|
for (const [id, d] of st.drafts) if (nowMs - d.at > DRAFT_OUTCOME_TTL_MS) st.drafts.delete(id);
|
|
245815
245942
|
if (waitingForGrace) this.schedule(companyId, this.graceMs);
|
|
245816
245943
|
st.primed = true;
|
|
245944
|
+
if (notified.size > 0) stats.notified = [...notified];
|
|
245817
245945
|
return stats;
|
|
245818
245946
|
}
|
|
245819
245947
|
async judge(st, ctx, model, row, nowMs, nowIso, eventsOf, cancelledOf) {
|
|
@@ -245855,7 +245983,7 @@ var init_notification_reconciler = __esm({
|
|
|
245855
245983
|
* 早就结束的任务不能在上线那一刻集体「任务已完成」一遍。之后每拍新看到的变化都发。
|
|
245856
245984
|
* 来源键 = `<种类>:<工单>@<那件事的 seq>`:同一件事重启后再算一遍撞唯一约束即收手;任务重开后再完成是新的一件事。
|
|
245857
245985
|
*/
|
|
245858
|
-
async reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2) {
|
|
245986
|
+
async reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2, notified) {
|
|
245859
245987
|
const store = ctx.engineStore;
|
|
245860
245988
|
if (!store) return 0;
|
|
245861
245989
|
const members = new Set(ctx.humans);
|
|
@@ -245877,6 +246005,7 @@ var init_notification_reconciler = __esm({
|
|
|
245877
246005
|
...trigger ? { actorId: trigger } : {},
|
|
245878
246006
|
enteredAt: new Date(rec2.createdAt).toISOString()
|
|
245879
246007
|
});
|
|
246008
|
+
notified.add(recipient);
|
|
245880
246009
|
sent++;
|
|
245881
246010
|
}
|
|
245882
246011
|
};
|
|
@@ -246072,7 +246201,7 @@ function createBundle(root, target, input) {
|
|
|
246072
246201
|
}
|
|
246073
246202
|
}
|
|
246074
246203
|
const bytes2 = fs28.statSync(absBundle).size;
|
|
246075
|
-
const digest = (0,
|
|
246204
|
+
const digest = (0, import_node_crypto63.createHash)("sha256").update(fs28.readFileSync(absBundle)).digest("hex");
|
|
246076
246205
|
const relBase = `inputs/git-bundles/${safeRepo}-${commit.slice(0, 12)}`;
|
|
246077
246206
|
return {
|
|
246078
246207
|
absoluteBundlePath: absBundle,
|
|
@@ -246168,12 +246297,12 @@ function classifyGitError(fallback, err, where) {
|
|
|
246168
246297
|
function oneLine2(msg) {
|
|
246169
246298
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
246170
246299
|
}
|
|
246171
|
-
var import_node_child_process17,
|
|
246300
|
+
var import_node_child_process17, import_node_crypto63, fs28, os7, path25, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
246172
246301
|
var init_readonly_bundle = __esm({
|
|
246173
246302
|
"../server/src/git/readonly-bundle.ts"() {
|
|
246174
246303
|
"use strict";
|
|
246175
246304
|
import_node_child_process17 = require("node:child_process");
|
|
246176
|
-
|
|
246305
|
+
import_node_crypto63 = require("node:crypto");
|
|
246177
246306
|
fs28 = __toESM(require("node:fs"), 1);
|
|
246178
246307
|
os7 = __toESM(require("node:os"), 1);
|
|
246179
246308
|
path25 = __toESM(require("node:path"), 1);
|
|
@@ -246194,7 +246323,7 @@ var init_readonly_bundle = __esm({
|
|
|
246194
246323
|
// ../server/src/domains/collab/create-seeded-workorder.ts
|
|
246195
246324
|
function makeSeededWorkorderCreator(deps) {
|
|
246196
246325
|
const locks = createKeyedMutex();
|
|
246197
|
-
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0,
|
|
246326
|
+
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto64.randomUUID)().slice(0, 8)}`);
|
|
246198
246327
|
const create = async (input) => {
|
|
246199
246328
|
const company = input.companyId && deps.resolveCompany ? await deps.resolveCompany(input.companyId) : void 0;
|
|
246200
246329
|
const kernel = company?.kernel ?? deps.kernel;
|
|
@@ -246281,7 +246410,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
246281
246410
|
return await finishCreation({ workspace, rootArtifactId: planned.rootArtifactId, spawned: planned.spawned });
|
|
246282
246411
|
};
|
|
246283
246412
|
return async (input) => {
|
|
246284
|
-
const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0,
|
|
246413
|
+
const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0, import_node_crypto64.randomUUID)()}`);
|
|
246285
246414
|
try {
|
|
246286
246415
|
return await create(input);
|
|
246287
246416
|
} finally {
|
|
@@ -246290,7 +246419,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
246290
246419
|
};
|
|
246291
246420
|
}
|
|
246292
246421
|
function workspaceForKey(key2) {
|
|
246293
|
-
return `ws:wo-${(0,
|
|
246422
|
+
return `ws:wo-${(0, import_node_crypto64.createHash)("sha256").update(key2).digest("hex").slice(0, 8)}`;
|
|
246294
246423
|
}
|
|
246295
246424
|
function existingWorkorder(snapshot, workspace, actor) {
|
|
246296
246425
|
if (!snapshot?.nodes.length) return null;
|
|
@@ -246302,11 +246431,11 @@ function existingWorkorder(snapshot, workspace, actor) {
|
|
|
246302
246431
|
spawned: snapshot.nodes.map((node2) => ({ id: node2.id, type: node2.type, owner: node2.assigneeActorId ?? actor }))
|
|
246303
246432
|
};
|
|
246304
246433
|
}
|
|
246305
|
-
var
|
|
246434
|
+
var import_node_crypto64;
|
|
246306
246435
|
var init_create_seeded_workorder = __esm({
|
|
246307
246436
|
"../server/src/domains/collab/create-seeded-workorder.ts"() {
|
|
246308
246437
|
"use strict";
|
|
246309
|
-
|
|
246438
|
+
import_node_crypto64 = require("node:crypto");
|
|
246310
246439
|
init_uncategorized_project();
|
|
246311
246440
|
init_src();
|
|
246312
246441
|
init_planner();
|
|
@@ -247809,12 +247938,12 @@ function stateFromAttempt(attempt, handoff, checkpoint, now, stalledAfterMs, ope
|
|
|
247809
247938
|
if (attempt.status === "no-output") return handoff?.unresolvedIssues.length ? "blocked" : "no_change";
|
|
247810
247939
|
return "failed";
|
|
247811
247940
|
}
|
|
247812
|
-
var
|
|
247941
|
+
var import_node_crypto65, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
|
|
247813
247942
|
var init_service9 = __esm({
|
|
247814
247943
|
"../server/src/domains/execution-continuity/service.ts"() {
|
|
247815
247944
|
"use strict";
|
|
247816
247945
|
init_src();
|
|
247817
|
-
|
|
247946
|
+
import_node_crypto65 = require("node:crypto");
|
|
247818
247947
|
init_src7();
|
|
247819
247948
|
BLOCKING_STATES = /* @__PURE__ */ new Set(["stalled", "failed", "blocked"]);
|
|
247820
247949
|
HANDOFF_OUTCOMES2 = /* @__PURE__ */ new Set(["succeeded", "no-output", "failed", "cancelled", "timeout", "orphaned"]);
|
|
@@ -248045,7 +248174,7 @@ var init_service9 = __esm({
|
|
|
248045
248174
|
if (typeof expectedHash !== "string" || !this.readBundleFile) return null;
|
|
248046
248175
|
const injectedResume = this.readBundleFile(attempt.id, "execution/RESUME.md");
|
|
248047
248176
|
if (!injectedResume) return null;
|
|
248048
|
-
const actualHash = (0,
|
|
248177
|
+
const actualHash = (0, import_node_crypto65.createHash)("sha256").update(injectedResume).digest("hex");
|
|
248049
248178
|
if (actualHash !== expectedHash) return null;
|
|
248050
248179
|
const recoverySnapshot = parseResumePackSnapshot(injectedResume);
|
|
248051
248180
|
if (!recoverySnapshot || recoverySnapshot.scenario !== "redispatch" || !recoverySnapshot.previousAttempt || recoverySnapshot.node.nodeId !== attempt.nodeId || recoverySnapshot.jobKey !== attempt.jobKey || recoverySnapshot.part !== attempt.part) return null;
|
|
@@ -248789,6 +248918,87 @@ var init_reply_anchors = __esm({
|
|
|
248789
248918
|
}
|
|
248790
248919
|
});
|
|
248791
248920
|
|
|
248921
|
+
// ../server/src/domains/chat-sessions/insert-status.ts
|
|
248922
|
+
async function resolveInsertStatus(deps, chatSessionId, clientKey) {
|
|
248923
|
+
const id = insertRequestId(chatSessionId, clientKey);
|
|
248924
|
+
if (!deps.store.getPendingMessage) return { status: "uncertain" };
|
|
248925
|
+
let row = await deps.store.getPendingMessage(chatSessionId, id);
|
|
248926
|
+
if (row?.state !== "delivering") return { status: insertStatusOfRow(row) };
|
|
248927
|
+
if (deps.isTurnRunning(chatSessionId)) return { status: "in-flight" };
|
|
248928
|
+
if (isInsertInflight(id)) {
|
|
248929
|
+
await waitForInflightInsert(id, deps.settleWaitMs ?? 1e4);
|
|
248930
|
+
row = await deps.store.getPendingMessage(chatSessionId, id);
|
|
248931
|
+
return { status: insertStatusOfRow(row) };
|
|
248932
|
+
}
|
|
248933
|
+
const running = settlingOrphans.get(id);
|
|
248934
|
+
if (running) return running;
|
|
248935
|
+
const settling = settleOrphan(deps, chatSessionId, row).finally(() => {
|
|
248936
|
+
settlingOrphans.delete(id);
|
|
248937
|
+
});
|
|
248938
|
+
settlingOrphans.set(id, settling);
|
|
248939
|
+
return settling;
|
|
248940
|
+
}
|
|
248941
|
+
async function settleOrphan(deps, chatSessionId, row) {
|
|
248942
|
+
const ref2 = row.deliveryRef;
|
|
248943
|
+
const answer = ref2?.nodeId && ref2.dispatchId && deps.confirm ? await deps.confirm({ nodeId: ref2.nodeId, dispatchId: ref2.dispatchId, runtimeKey: ref2.runtimeKey }).catch(() => ({ status: "unknown", reason: "query-failed" })) : { status: "unknown", reason: ref2 ? "no-node" : "no-delivery-ref" };
|
|
248944
|
+
const trace = ref2 && deps.store.listPendingTrace ? await deps.store.listPendingTrace(chatSessionId).catch(() => []) : [];
|
|
248945
|
+
const batch = trace.filter((r) => r.state === "delivering" && r.deliveryRef?.runtimeKey === ref2?.runtimeKey);
|
|
248946
|
+
if (!batch.some((r) => r.id === row.id)) batch.push(row);
|
|
248947
|
+
const ids2 = batch.map((r) => r.id);
|
|
248948
|
+
deps.log?.(`[chat-insert] \u5B64\u513F\u63D2\u5165\u7ED3\u7B97 sid=${chatSessionId} row=${row.id} \u2192 ${answer.status}${answer.reason ? `(${answer.reason})` : ""}`);
|
|
248949
|
+
if (answer.status === "consumed") {
|
|
248950
|
+
await backfill(deps, chatSessionId, batch, row).catch((err) => {
|
|
248951
|
+
deps.log?.(`[chat-insert] \u8865\u884C\u5931\u8D25\uFF08\u4ECD\u6309\u5DF2\u63D2\u5165\u5904\u7406\uFF0Cruntime \u786E\u5B9E\u8BFB\u5230\u4E86\uFF09sid=${chatSessionId}: ${String(err)}`);
|
|
248952
|
+
});
|
|
248953
|
+
await deps.store.markPendingMessages?.(chatSessionId, ids2, "delivered", "delivered:node-confirmed-orphan");
|
|
248954
|
+
return { status: "inserted" };
|
|
248955
|
+
}
|
|
248956
|
+
if (answer.status === "not-consumed") {
|
|
248957
|
+
await deps.store.markPendingMessages?.(chatSessionId, [row.id], "cancelled", "client-gone:not-consumed");
|
|
248958
|
+
const rest = ids2.filter((x2) => x2 !== row.id);
|
|
248959
|
+
if (rest.length) await deps.store.markPendingMessages?.(chatSessionId, rest, "queued", `not-consumed:${answer.reason ?? ""}`);
|
|
248960
|
+
if (row.clientKey) await deps.landUndelivered?.({ clientKey: row.clientKey, rows: [row], note: INSERT_RETURNED_NOTE });
|
|
248961
|
+
return { status: "not-inserted" };
|
|
248962
|
+
}
|
|
248963
|
+
await deps.store.markPendingMessages?.(chatSessionId, ids2, "unconfirmed", `unconfirmed:${answer.reason ?? "unknown"}`);
|
|
248964
|
+
if (row.clientKey) {
|
|
248965
|
+
await deps.landUndelivered?.({ clientKey: row.clientKey, rows: [...batch].sort((a, b2) => a.seq - b2.seq), note: INSERT_UNCERTAIN_NOTE });
|
|
248966
|
+
}
|
|
248967
|
+
return { status: "uncertain" };
|
|
248968
|
+
}
|
|
248969
|
+
async function backfill(deps, chatSessionId, batch, row) {
|
|
248970
|
+
if (!deps.items) return;
|
|
248971
|
+
const ref2 = row.deliveryRef;
|
|
248972
|
+
const sorted = [...batch].sort((a, b2) => a.seq - b2.seq);
|
|
248973
|
+
const ledger = new ChatItemLedger({
|
|
248974
|
+
items: deps.items,
|
|
248975
|
+
versionSeed: await deps.items.sessionVersionCursor(chatSessionId).catch(() => 0),
|
|
248976
|
+
sessionId: chatSessionId,
|
|
248977
|
+
turnId: ref2?.turnId ?? `insert-backfill:${row.id}`,
|
|
248978
|
+
...deps.log ? { log: deps.log } : {}
|
|
248979
|
+
});
|
|
248980
|
+
const text7 = sorted.map((m2) => m2.text).filter(Boolean).join("\n\n");
|
|
248981
|
+
const attachments = sorted.flatMap((m2) => (m2.attachments ?? []).map((a) => ({
|
|
248982
|
+
name: a.name,
|
|
248983
|
+
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
248984
|
+
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
248985
|
+
})));
|
|
248986
|
+
const clientKeys = sorted.map((m2) => m2.clientKey).filter((k2) => !!k2);
|
|
248987
|
+
ledger.recordUserInput(text7, attachments, clientKeys, ref2?.ord !== void 0 ? { ord: ref2.ord } : void 0);
|
|
248988
|
+
await ledger.drain();
|
|
248989
|
+
if (ledger.failures > 0) throw new Error("chat_items \u5199\u5165\u5931\u8D25");
|
|
248990
|
+
}
|
|
248991
|
+
var settlingOrphans;
|
|
248992
|
+
var init_insert_status = __esm({
|
|
248993
|
+
"../server/src/domains/chat-sessions/insert-status.ts"() {
|
|
248994
|
+
"use strict";
|
|
248995
|
+
init_chat_item_ledger();
|
|
248996
|
+
init_chat_insert_evidence();
|
|
248997
|
+
init_append_now();
|
|
248998
|
+
settlingOrphans = /* @__PURE__ */ new Map();
|
|
248999
|
+
}
|
|
249000
|
+
});
|
|
249001
|
+
|
|
248792
249002
|
// ../server/src/domains/chat-sessions/agent-history.ts
|
|
248793
249003
|
async function resolveChatHistoryViewer(auth, getSession) {
|
|
248794
249004
|
if (isHumanActorId(auth.actor)) return { kind: "human", actor: auth.actor };
|
|
@@ -248991,6 +249201,29 @@ function throwWorkdirError(code2) {
|
|
|
248991
249201
|
}
|
|
248992
249202
|
}
|
|
248993
249203
|
function createChatSessionsDomain(opts) {
|
|
249204
|
+
const settleInFlightInserts = async ({ store: store2, items, chatSessionId }) => {
|
|
249205
|
+
const rows = await store2.listInFlightInserts(chatSessionId);
|
|
249206
|
+
for (const row of rows) {
|
|
249207
|
+
if (!row.clientKey) continue;
|
|
249208
|
+
await resolveInsertStatus({
|
|
249209
|
+
store: store2,
|
|
249210
|
+
isTurnRunning: (id) => opts.liveChat?.isRunning(id) ?? false,
|
|
249211
|
+
...opts.confirmInputReceipt ? { confirm: opts.confirmInputReceipt } : {},
|
|
249212
|
+
items,
|
|
249213
|
+
settleWaitMs: INFLIGHT_INSERT_SETTLE_WAIT_MS,
|
|
249214
|
+
landUndelivered: ({ clientKey, rows: batch, note }) => landUndeliveredInsert({
|
|
249215
|
+
store: store2,
|
|
249216
|
+
itemStore: items,
|
|
249217
|
+
chatSessionId,
|
|
249218
|
+
clientKey,
|
|
249219
|
+
text: batch.map((m2) => m2.text).filter(Boolean).join("\n\n"),
|
|
249220
|
+
attachments: batch.flatMap((m2) => m2.attachments ?? []),
|
|
249221
|
+
note
|
|
249222
|
+
}),
|
|
249223
|
+
log: (m2) => console.warn(m2)
|
|
249224
|
+
}, chatSessionId, row.clientKey);
|
|
249225
|
+
}
|
|
249226
|
+
};
|
|
248994
249227
|
const { store, registry: registry2 } = opts;
|
|
248995
249228
|
const bindingFor = opts.resolveBinding ?? bindingResolverFromRegistry(registry2);
|
|
248996
249229
|
async function storeFor(req) {
|
|
@@ -249123,7 +249356,7 @@ function createChatSessionsDomain(opts) {
|
|
|
249123
249356
|
if (!text7.trim()) throw new ApiError(400, "BAD_REQUEST", "text required");
|
|
249124
249357
|
const now = Date.now();
|
|
249125
249358
|
sweepDrafts(now);
|
|
249126
|
-
const id = `cd_${(0,
|
|
249359
|
+
const id = `cd_${(0, import_node_crypto66.randomUUID)()}`;
|
|
249127
249360
|
drafts.set(id, { text: text7, actor: req.auth.actor, expiresAt: now + DRAFT_TTL_MS });
|
|
249128
249361
|
return { status: 201, body: { id, expiresInMs: DRAFT_TTL_MS } };
|
|
249129
249362
|
});
|
|
@@ -249200,7 +249433,7 @@ function createChatSessionsDomain(opts) {
|
|
|
249200
249433
|
const runtimeId = agentDefault.binding?.nodeId ?? "unknown";
|
|
249201
249434
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
249202
249435
|
const session = {
|
|
249203
|
-
id: (0,
|
|
249436
|
+
id: (0, import_node_crypto66.randomUUID)(),
|
|
249204
249437
|
humanActorId: req.auth.actor,
|
|
249205
249438
|
// 注:这里**刻意不写 companyId**。新会话要不要带公司归属,按 ws:wo-6d588f8e 的 ADR
|
|
249206
249439
|
// (每公司 schema、最终移除表内 company 列)统一定,不在本节点自行发明。
|
|
@@ -249319,19 +249552,6 @@ function createChatSessionsDomain(opts) {
|
|
|
249319
249552
|
});
|
|
249320
249553
|
return { status: 200, body: await store2.getSession(req.params.id) };
|
|
249321
249554
|
});
|
|
249322
|
-
router.post("/api/chat-sessions/:id/runtime/reset-to-agent-default", async (req) => {
|
|
249323
|
-
const store2 = await storeFor(req);
|
|
249324
|
-
const session = await store2.getSession(req.params.id);
|
|
249325
|
-
if (!session || session.humanActorId !== req.auth.actor) throw new ApiError(404, "NOT_FOUND", "session not found");
|
|
249326
|
-
const agentDefault = await agentDefaultRuntime(req.auth.companyId, session.aiActorId);
|
|
249327
|
-
const initial = chatSessionInitialRuntime({ binding: agentDefault.binding, agentModel: agentDefault.model });
|
|
249328
|
-
await store2.updateSession(req.params.id, {
|
|
249329
|
-
overrideNodeId: initial.overrideNodeId,
|
|
249330
|
-
overrideRuntimeKind: initial.overrideRuntimeKind,
|
|
249331
|
-
model: initial.model
|
|
249332
|
-
});
|
|
249333
|
-
return { status: 200, body: await store2.getSession(req.params.id) };
|
|
249334
|
-
});
|
|
249335
249555
|
router.delete("/api/chat-sessions/:id", async (req) => {
|
|
249336
249556
|
const store2 = await storeFor(req);
|
|
249337
249557
|
const session = await store2.getSession(req.params.id);
|
|
@@ -249348,7 +249568,7 @@ function createChatSessionsDomain(opts) {
|
|
|
249348
249568
|
if (body2.role !== "user" && body2.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
|
|
249349
249569
|
const role = body2.role;
|
|
249350
249570
|
const msg = await store2.appendMessage({
|
|
249351
|
-
id: (0,
|
|
249571
|
+
id: (0, import_node_crypto66.randomUUID)(),
|
|
249352
249572
|
sessionId: req.params.id,
|
|
249353
249573
|
role,
|
|
249354
249574
|
content: role === "user" ? stripInjectedChatContext(body2.content) : body2.content,
|
|
@@ -249390,7 +249610,7 @@ function createChatSessionsDomain(opts) {
|
|
|
249390
249610
|
const known = key2 ? cur.find((x2) => x2.clientKey === key2) : void 0;
|
|
249391
249611
|
if (!known && cur.length >= QUEUE_MAX) throw new ApiError(409, "QUEUE_FULL", `\u961F\u5217\u5DF2\u6EE1\uFF08\u4E0A\u9650 ${QUEUE_MAX} \u6761\uFF09`);
|
|
249392
249612
|
const item = await store2.enqueuePendingMessage({
|
|
249393
|
-
id: (0,
|
|
249613
|
+
id: (0, import_node_crypto66.randomUUID)(),
|
|
249394
249614
|
chatSessionId: sid,
|
|
249395
249615
|
text: text7,
|
|
249396
249616
|
...attachments.length ? { attachments } : {},
|
|
@@ -249440,6 +249660,11 @@ function createChatSessionsDomain(opts) {
|
|
|
249440
249660
|
const stale = Number.isFinite(startedAt) && Date.now() - startedAt >= LINK_WINDOWS.chatTurnPhaseStaleAfterMs;
|
|
249441
249661
|
return { turnId: activeTurnRow.id, phase: stale ? "recovering" : "running" };
|
|
249442
249662
|
})();
|
|
249663
|
+
if (sinceVersion === 0 && beforeOrd === void 0 && session?.humanActorId === req.auth.actor && store2.listInFlightInserts) {
|
|
249664
|
+
await settleInFlightInserts({ store: store2, items, chatSessionId }).catch((e) => {
|
|
249665
|
+
console.warn(`[chat] \u5728\u98DE\u63D2\u8BDD\u7ED3\u7B97\u5931\u8D25\uFF08session=${chatSessionId}\uFF09\uFF0C\u8FD9\u6B21\u5FEB\u7167\u7167\u65E7\u6295\u5F71: ${String(e)}`);
|
|
249666
|
+
});
|
|
249667
|
+
}
|
|
249443
249668
|
const snapshotEntries = [];
|
|
249444
249669
|
let nextSinceVersion = sinceVersion;
|
|
249445
249670
|
let hasMoreBefore = false;
|
|
@@ -250238,12 +250463,12 @@ async function legacySendFailureCards(entries, deps) {
|
|
|
250238
250463
|
}
|
|
250239
250464
|
return out;
|
|
250240
250465
|
}
|
|
250241
|
-
var
|
|
250466
|
+
var import_node_crypto66, DEFAULT_SNAPSHOT_ITEMS, INFLIGHT_INSERT_SETTLE_WAIT_MS, MAX_SNAPSHOT_ITEMS, PROJECTED_CARD_LIMIT, SUBMISSION_NOT_DELIVERED_NOTE, SUBMISSION_UNCONFIRMED_NOTE, LEGACY_CARD_LIMIT;
|
|
250242
250467
|
var init_chat_sessions2 = __esm({
|
|
250243
250468
|
"../server/src/domains/chat-sessions/index.ts"() {
|
|
250244
250469
|
"use strict";
|
|
250245
250470
|
init_file_limits2();
|
|
250246
|
-
|
|
250471
|
+
import_node_crypto66 = require("node:crypto");
|
|
250247
250472
|
init_src();
|
|
250248
250473
|
init_chat_session();
|
|
250249
250474
|
init_persistent_files();
|
|
@@ -250259,6 +250484,8 @@ var init_chat_sessions2 = __esm({
|
|
|
250259
250484
|
init_service3();
|
|
250260
250485
|
init_reply_anchors();
|
|
250261
250486
|
init_injected_context();
|
|
250487
|
+
init_insert_status();
|
|
250488
|
+
init_insert_undelivered();
|
|
250262
250489
|
init_agent_history();
|
|
250263
250490
|
init_deletion();
|
|
250264
250491
|
init_chat_turn_gate();
|
|
@@ -250270,6 +250497,7 @@ var init_chat_sessions2 = __esm({
|
|
|
250270
250497
|
init_chat_submission();
|
|
250271
250498
|
init_project_bundle();
|
|
250272
250499
|
DEFAULT_SNAPSHOT_ITEMS = 400;
|
|
250500
|
+
INFLIGHT_INSERT_SETTLE_WAIT_MS = 6e3;
|
|
250273
250501
|
MAX_SNAPSHOT_ITEMS = 1e3;
|
|
250274
250502
|
PROJECTED_CARD_LIMIT = 10;
|
|
250275
250503
|
SUBMISSION_NOT_DELIVERED_NOTE = "\u8FD9\u6761\u6D88\u606F\u6CA1\u6709\u53D1\u51FA\uFF0C\u53EF\u4EE5\u91CD\u8BD5";
|
|
@@ -251700,7 +251928,7 @@ function busyError(chatSessionId, blockedBy) {
|
|
|
251700
251928
|
return `\u76EE\u6807\u4F1A\u8BDD ${chatSessionId} \u6B63\u6709\u4E00\u8F6E\u5728\u8DD1${blockedBy ? `\uFF08${blockedBy}\uFF09` : ""}\u2014\u2014\u672C\u6B21\u89E6\u53D1\u5DF2\u4E22\u5F03\uFF0C\u4E0D\u6392\u961F\u3001\u4E0D\u8865\u8DD1`;
|
|
251701
251929
|
}
|
|
251702
251930
|
function genWebhookToken() {
|
|
251703
|
-
return `owt_${(0,
|
|
251931
|
+
return `owt_${(0, import_node_crypto67.randomBytes)(32).toString("base64url")}`;
|
|
251704
251932
|
}
|
|
251705
251933
|
function validateTitleTemplate(tpl) {
|
|
251706
251934
|
const residue = tpl.replace(DATE_TOKEN, "");
|
|
@@ -251756,11 +251984,11 @@ function appendSourceNote(brief, automation, source, atIso) {
|
|
|
251756
251984
|
---
|
|
251757
251985
|
\u672C\u5DE5\u5355\u7531\u81EA\u52A8\u5316\u300C${automation.name}\u300D\u4E8E ${atIso} \u89E6\u53D1\uFF08\u6765\u6E90\uFF1A${source}\uFF09\u3002\u5F00\u5DE5\u540E\u8BF7\u628A\u5DE5\u5355\u6807\u9898\u6539\u6210\u51C6\u786E\u53CD\u6620\u5B9E\u9645\u5DE5\u4F5C\u7684\u63CF\u8FF0\u3002`;
|
|
251758
251986
|
}
|
|
251759
|
-
var
|
|
251987
|
+
var import_node_crypto67, DATE_TOKEN, AutomationsService, EVENT_RETRY_BASE_MS, EVENT_RETRY_MAX_MS, EVENT_RETRY_MAX_ATTEMPTS, eventAttempts, eventLastAttemptAt, eventLastError, CHAT_REPLY_MAX;
|
|
251760
251988
|
var init_service10 = __esm({
|
|
251761
251989
|
"../server/src/domains/automations/service.ts"() {
|
|
251762
251990
|
"use strict";
|
|
251763
|
-
|
|
251991
|
+
import_node_crypto67 = require("node:crypto");
|
|
251764
251992
|
init_src();
|
|
251765
251993
|
init_registry3();
|
|
251766
251994
|
init_attribution();
|
|
@@ -252574,11 +252802,11 @@ function verifySignature(rawBody, headers, secret) {
|
|
|
252574
252802
|
if (!secret) return "not_required";
|
|
252575
252803
|
const given = header1(headers, "x-hub-signature-256");
|
|
252576
252804
|
if (!given) return "missing";
|
|
252577
|
-
const expected = `sha256=${(0,
|
|
252805
|
+
const expected = `sha256=${(0, import_node_crypto68.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
|
|
252578
252806
|
const a = Buffer.from(given);
|
|
252579
252807
|
const b2 = Buffer.from(expected);
|
|
252580
252808
|
if (a.length !== b2.length) return "invalid";
|
|
252581
|
-
return (0,
|
|
252809
|
+
return (0, import_node_crypto68.timingSafeEqual)(a, b2) ? "valid" : "invalid";
|
|
252582
252810
|
}
|
|
252583
252811
|
function eventAllowed(filters, envelope) {
|
|
252584
252812
|
if (!filters || filters.length === 0) return true;
|
|
@@ -252608,11 +252836,11 @@ function splitEvent(envelope) {
|
|
|
252608
252836
|
}
|
|
252609
252837
|
return { eventName, actionCandidates: candidates };
|
|
252610
252838
|
}
|
|
252611
|
-
var
|
|
252839
|
+
var import_node_crypto68, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
|
|
252612
252840
|
var init_webhook = __esm({
|
|
252613
252841
|
"../server/src/domains/automations/webhook.ts"() {
|
|
252614
252842
|
"use strict";
|
|
252615
|
-
|
|
252843
|
+
import_node_crypto68 = require("node:crypto");
|
|
252616
252844
|
MAX_BODY_BYTES = 256 * 1024;
|
|
252617
252845
|
AutomationWebhookService = class {
|
|
252618
252846
|
store;
|
|
@@ -253764,7 +253992,7 @@ function playbooksDomain(opts) {
|
|
|
253764
253992
|
opts.overrides.set(companyOf(req), ref2, nodeKey, nextOverride);
|
|
253765
253993
|
try {
|
|
253766
253994
|
await opts.audit?.({
|
|
253767
|
-
id: `reg_${(0,
|
|
253995
|
+
id: `reg_${(0, import_node_crypto69.randomUUID)()}`,
|
|
253768
253996
|
actor: req.auth.actor,
|
|
253769
253997
|
kind: "registry_change",
|
|
253770
253998
|
target: `playbook:${ref2}#${nodeKey}`,
|
|
@@ -253781,11 +254009,11 @@ function playbooksDomain(opts) {
|
|
|
253781
254009
|
});
|
|
253782
254010
|
};
|
|
253783
254011
|
}
|
|
253784
|
-
var
|
|
254012
|
+
var import_node_crypto69;
|
|
253785
254013
|
var init_routes12 = __esm({
|
|
253786
254014
|
"../server/src/domains/playbooks/routes.ts"() {
|
|
253787
254015
|
"use strict";
|
|
253788
|
-
|
|
254016
|
+
import_node_crypto69 = require("node:crypto");
|
|
253789
254017
|
init_router();
|
|
253790
254018
|
init_registry3();
|
|
253791
254019
|
init_planner();
|
|
@@ -253914,17 +254142,17 @@ function completionFingerprint(workspace, members) {
|
|
|
253914
254142
|
workspace,
|
|
253915
254143
|
members: [...members].sort((a, b2) => a.artifactId < b2.artifactId ? -1 : a.artifactId > b2.artifactId ? 1 : 0).map((m2) => ({ artifactId: m2.artifactId, currentRevisionId: m2.currentRevisionId ?? null }))
|
|
253916
254144
|
});
|
|
253917
|
-
return (0,
|
|
254145
|
+
return (0, import_node_crypto70.createHash)("sha256").update(canonical2).digest("hex");
|
|
253918
254146
|
}
|
|
253919
254147
|
function eventConsumptionKey(args) {
|
|
253920
254148
|
const raw = `project-event:${EVENT_KEY_VERSION}:${args.triggerId}:${args.event}:${args.workspace}:${args.fingerprint}`;
|
|
253921
|
-
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0,
|
|
254149
|
+
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0, import_node_crypto70.createHash)("sha256").update(raw).digest("hex")}`;
|
|
253922
254150
|
}
|
|
253923
|
-
var
|
|
254151
|
+
var import_node_crypto70, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
|
|
253924
254152
|
var init_project_event_poller = __esm({
|
|
253925
254153
|
"../server/src/automations/project-event-poller.ts"() {
|
|
253926
254154
|
"use strict";
|
|
253927
|
-
|
|
254155
|
+
import_node_crypto70 = require("node:crypto");
|
|
253928
254156
|
EVENT_KEY_VERSION = "v1";
|
|
253929
254157
|
EMPTY_METRICS = () => ({
|
|
253930
254158
|
scanDurationMs: 0,
|
|
@@ -254134,7 +254362,7 @@ function queryInputReceipt(hub, nodeId, dispatchId, clientMessageKey, pending, t
|
|
|
254134
254362
|
const viaSession = hub.hasSession?.(dispatchId) === true;
|
|
254135
254363
|
const supported = viaSession ? hub.supportsInputReceiptQuery?.(dispatchId) === true : daemonMetaOf(hub, nodeId)?.supportsInputReceiptQuery === true;
|
|
254136
254364
|
if (!supported) return Promise.resolve({ status: "unknown", reason: "unsupported" });
|
|
254137
|
-
const requestId = (0,
|
|
254365
|
+
const requestId = (0, import_node_crypto71.randomUUID)();
|
|
254138
254366
|
return new Promise((resolve12) => {
|
|
254139
254367
|
const timer = setTimeout(() => {
|
|
254140
254368
|
pending.delete(requestId);
|
|
@@ -254196,7 +254424,7 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
|
|
|
254196
254424
|
if (input.requireConsumptionReceipt && !hub.supportsInputConsumptionReceipts?.(dispatchId)) {
|
|
254197
254425
|
return Promise.resolve({ accepted: false, reason: "consumption-unsupported" });
|
|
254198
254426
|
}
|
|
254199
|
-
const requestId = (0,
|
|
254427
|
+
const requestId = (0, import_node_crypto71.randomUUID)();
|
|
254200
254428
|
const sent = routeToSession(hub, nodeId, dispatchId, { type: "append_input", dispatchId, input, requestId });
|
|
254201
254429
|
if (!sent) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
|
|
254202
254430
|
return new Promise((resolve12) => {
|
|
@@ -254209,11 +254437,11 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
|
|
|
254209
254437
|
entry.appendWaiters.push({ requestId, requireConsumptionReceipt: input.requireConsumptionReceipt, resolve: resolve12, timer });
|
|
254210
254438
|
});
|
|
254211
254439
|
}
|
|
254212
|
-
var
|
|
254440
|
+
var import_node_crypto71, STASH_TTL_MS, STASH_MAX_FRAMES_PER_ID, STASH_MAX_TOTAL_FRAMES, STASH_MAX_IDS, STASH_LOSS_MAX_IDS, STASH_LOSS_TTL_MS, DaemonHubAdapter, BindingRouterAdapter, WorkdirBridge;
|
|
254213
254441
|
var init_daemon_adapter = __esm({
|
|
254214
254442
|
"../server/src/daemon-adapter.ts"() {
|
|
254215
254443
|
"use strict";
|
|
254216
|
-
|
|
254444
|
+
import_node_crypto71 = require("node:crypto");
|
|
254217
254445
|
init_src();
|
|
254218
254446
|
STASH_TTL_MS = 5 * 6e4;
|
|
254219
254447
|
STASH_MAX_FRAMES_PER_ID = 1e4;
|
|
@@ -254653,7 +254881,7 @@ var init_daemon_adapter = __esm({
|
|
|
254653
254881
|
async spawn(job) {
|
|
254654
254882
|
const nodeId = job.binding?.nodeId;
|
|
254655
254883
|
if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
|
|
254656
|
-
const dispatchId = job.dispatchId ?? `dispatch:${(0,
|
|
254884
|
+
const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto71.randomUUID)()}`;
|
|
254657
254885
|
if (job.dispatchId && this.pending.has(dispatchId)) {
|
|
254658
254886
|
return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
254659
254887
|
}
|
|
@@ -254909,7 +255137,7 @@ var init_daemon_adapter = __esm({
|
|
|
254909
255137
|
return daemon?.meta.supportsWorkdirWalk === true;
|
|
254910
255138
|
}
|
|
254911
255139
|
request(nodeId, buildFrame) {
|
|
254912
|
-
const requestId = (0,
|
|
255140
|
+
const requestId = (0, import_node_crypto71.randomUUID)();
|
|
254913
255141
|
const sent = this.hub.dispatch(nodeId, buildFrame(requestId));
|
|
254914
255142
|
if (!sent) return Promise.resolve({ ok: false, code: "NODE_OFFLINE" });
|
|
254915
255143
|
return new Promise((resolve12) => {
|
|
@@ -255017,13 +255245,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
255017
255245
|
if (sha(body2) === lastPushedHash) return { kind: "echo" };
|
|
255018
255246
|
return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
|
|
255019
255247
|
}
|
|
255020
|
-
var
|
|
255248
|
+
var import_node_crypto72, sha, enc2, dec, MirrorEngine, MemoryMirrorStateStore, MapMirrorIdentities;
|
|
255021
255249
|
var init_engine = __esm({
|
|
255022
255250
|
"../server/src/mirror/engine.ts"() {
|
|
255023
255251
|
"use strict";
|
|
255024
|
-
|
|
255252
|
+
import_node_crypto72 = require("node:crypto");
|
|
255025
255253
|
init_src();
|
|
255026
|
-
sha = (s2) => (0,
|
|
255254
|
+
sha = (s2) => (0, import_node_crypto72.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
255027
255255
|
enc2 = (s2) => new TextEncoder().encode(s2);
|
|
255028
255256
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
255029
255257
|
MirrorEngine = class {
|
|
@@ -255304,11 +255532,11 @@ function humanExitCause(exit3) {
|
|
|
255304
255532
|
const base = (exit3.reason ? label2[exit3.reason] : void 0) ?? `\u4F1A\u8BDD\u5F02\u5E38\u7ED3\u675F\uFF08${exit3.reason ?? "\u65E0\u9000\u51FA\u4FE1\u606F"}\uFF09`;
|
|
255305
255533
|
return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
|
|
255306
255534
|
}
|
|
255307
|
-
var
|
|
255535
|
+
var import_node_crypto73, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, AUTONOMOUS_RECOVERY_TOOLS, HIGH_RISK_COMMANDS, REJECTED_PROPOSALS_IN_TASK, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_RECOVERY_TOOLS, CONVERSATIONAL_ESCALATION_TOOLS, CONVERSATIONAL_MANAGER_BODY, MACHINE_EXIT_CODES, CoordinatorWorker;
|
|
255308
255536
|
var init_worker = __esm({
|
|
255309
255537
|
"../server/src/coordinator/worker.ts"() {
|
|
255310
255538
|
"use strict";
|
|
255311
|
-
|
|
255539
|
+
import_node_crypto73 = require("node:crypto");
|
|
255312
255540
|
init_src7();
|
|
255313
255541
|
init_identity();
|
|
255314
255542
|
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
|
|
@@ -255578,7 +255806,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
255578
255806
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
255579
255807
|
}
|
|
255580
255808
|
evaluationKey(kind, artifactId, evidence) {
|
|
255581
|
-
const fingerprint2 = (0,
|
|
255809
|
+
const fingerprint2 = (0, import_node_crypto73.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
255582
255810
|
return `${kind}:${artifactId}:${fingerprint2}`;
|
|
255583
255811
|
}
|
|
255584
255812
|
artifactEvidence(id) {
|
|
@@ -255967,8 +256195,8 @@ ${ctx.nodeFault}
|
|
|
255967
256195
|
const taskWithRejections = rejectedSection ? `${task}
|
|
255968
256196
|
|
|
255969
256197
|
${rejectedSection}` : task;
|
|
255970
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
255971
|
-
const coordinatorRunId = `coordinate:${(0,
|
|
256198
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto73.randomUUID)();
|
|
256199
|
+
const coordinatorRunId = `coordinate:${(0, import_node_crypto73.randomUUID)()}`;
|
|
255972
256200
|
const taskWithContext = coordinatorContext ? [
|
|
255973
256201
|
taskWithRejections,
|
|
255974
256202
|
``,
|
|
@@ -256012,7 +256240,7 @@ ${rejectedSection}` : task;
|
|
|
256012
256240
|
const startedAtMs = Date.now();
|
|
256013
256241
|
let trajectoryStarted = false;
|
|
256014
256242
|
if (this.deps.trajectory) {
|
|
256015
|
-
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0,
|
|
256243
|
+
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto73.createHash)("sha256").update(content3).digest("hex")]));
|
|
256016
256244
|
const session = {
|
|
256017
256245
|
runId: coordinatorRunId,
|
|
256018
256246
|
runtimeSessionId,
|
|
@@ -256223,11 +256451,11 @@ var init_pg_ident = __esm({
|
|
|
256223
256451
|
});
|
|
256224
256452
|
|
|
256225
256453
|
// ../storage/src/postgres.ts
|
|
256226
|
-
var
|
|
256454
|
+
var import_node_crypto74, ident4, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
|
|
256227
256455
|
var init_postgres = __esm({
|
|
256228
256456
|
"../storage/src/postgres.ts"() {
|
|
256229
256457
|
"use strict";
|
|
256230
|
-
|
|
256458
|
+
import_node_crypto74 = require("node:crypto");
|
|
256231
256459
|
init_pg_ident();
|
|
256232
256460
|
init_esm();
|
|
256233
256461
|
init_src();
|
|
@@ -256407,7 +256635,7 @@ var init_postgres = __esm({
|
|
|
256407
256635
|
return new _PostgresBlobStore(pool, schema);
|
|
256408
256636
|
}
|
|
256409
256637
|
async put(bytes2) {
|
|
256410
|
-
const hash3 = (0,
|
|
256638
|
+
const hash3 = (0, import_node_crypto74.createHash)("sha256").update(bytes2).digest("hex");
|
|
256411
256639
|
await this.pool.query(
|
|
256412
256640
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
256413
256641
|
[hash3, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
|
|
@@ -256455,7 +256683,7 @@ function stageAtLeast(stage, min2) {
|
|
|
256455
256683
|
return STAGES.indexOf(stage) >= STAGES.indexOf(min2);
|
|
256456
256684
|
}
|
|
256457
256685
|
function newVariableId() {
|
|
256458
|
-
return `var_${(0,
|
|
256686
|
+
return `var_${(0, import_node_crypto75.randomUUID)()}`;
|
|
256459
256687
|
}
|
|
256460
256688
|
async function declareRecordsAware(db) {
|
|
256461
256689
|
await db.query(`SELECT set_config('${RECORDS_AWARE_SETTING}', 'on', true)`);
|
|
@@ -256811,11 +257039,11 @@ async function listBindingTargetIds(db, s2, kind) {
|
|
|
256811
257039
|
[kind]
|
|
256812
257040
|
)).rows.map((x2) => x2.target_id);
|
|
256813
257041
|
}
|
|
256814
|
-
var
|
|
257042
|
+
var import_node_crypto75, STAGES, RECORDS_AWARE_SETTING, markLockName;
|
|
256815
257043
|
var init_variable_bindings = __esm({
|
|
256816
257044
|
"../storage/src/variable-bindings.ts"() {
|
|
256817
257045
|
"use strict";
|
|
256818
|
-
|
|
257046
|
+
import_node_crypto75 = require("node:crypto");
|
|
256819
257047
|
init_src();
|
|
256820
257048
|
STAGES = ["off", "dual", "read", "records"];
|
|
256821
257049
|
RECORDS_AWARE_SETTING = "oasis.variable_records_aware";
|
|
@@ -266543,11 +266771,11 @@ var init_postgres_delegations = __esm({
|
|
|
266543
266771
|
});
|
|
266544
266772
|
|
|
266545
266773
|
// ../storage/src/postgres-nodes.ts
|
|
266546
|
-
var
|
|
266774
|
+
var import_node_crypto76, ident13, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToFault, rowToQuota, rowToRuntime;
|
|
266547
266775
|
var init_postgres_nodes = __esm({
|
|
266548
266776
|
"../storage/src/postgres-nodes.ts"() {
|
|
266549
266777
|
"use strict";
|
|
266550
|
-
|
|
266778
|
+
import_node_crypto76 = require("node:crypto");
|
|
266551
266779
|
init_pg_ident();
|
|
266552
266780
|
init_esm();
|
|
266553
266781
|
ident13 = (s2) => {
|
|
@@ -266897,7 +267125,7 @@ var init_postgres_nodes = __esm({
|
|
|
266897
267125
|
return store;
|
|
266898
267126
|
}
|
|
266899
267127
|
issue(nodeId) {
|
|
266900
|
-
const token = `ont_${(0,
|
|
267128
|
+
const token = `ont_${(0, import_node_crypto76.randomBytes)(24).toString("base64url")}`;
|
|
266901
267129
|
this.cache.set(token, nodeId);
|
|
266902
267130
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
266903
267131
|
return token;
|
|
@@ -267199,11 +267427,11 @@ var init_postgres_type_registry = __esm({
|
|
|
267199
267427
|
});
|
|
267200
267428
|
|
|
267201
267429
|
// ../storage/src/postgres-actor-memory.ts
|
|
267202
|
-
var
|
|
267430
|
+
var import_node_crypto77, matchClause, ident15, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
|
|
267203
267431
|
var init_postgres_actor_memory = __esm({
|
|
267204
267432
|
"../storage/src/postgres-actor-memory.ts"() {
|
|
267205
267433
|
"use strict";
|
|
267206
|
-
|
|
267434
|
+
import_node_crypto77 = require("node:crypto");
|
|
267207
267435
|
init_pg_ident();
|
|
267208
267436
|
init_src();
|
|
267209
267437
|
matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
|
|
@@ -267413,7 +267641,7 @@ var init_postgres_actor_memory = __esm({
|
|
|
267413
267641
|
}
|
|
267414
267642
|
async write(input, now) {
|
|
267415
267643
|
if (input.memId === void 0) {
|
|
267416
|
-
const memId = `mem:${(0,
|
|
267644
|
+
const memId = `mem:${(0, import_node_crypto77.randomUUID)()}`;
|
|
267417
267645
|
const r2 = await this.pool.query(
|
|
267418
267646
|
`INSERT INTO ${this.s}.actor_memories
|
|
267419
267647
|
(mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
|
|
@@ -267651,6 +267879,124 @@ var init_postgres_inbox_read = __esm({
|
|
|
267651
267879
|
}
|
|
267652
267880
|
});
|
|
267653
267881
|
|
|
267882
|
+
// ../storage/src/postgres-connector-auth-pending.ts
|
|
267883
|
+
var ident17, PostgresGithubAppPendingStore, PostgresConnectorAuthSnapshotStore;
|
|
267884
|
+
var init_postgres_connector_auth_pending = __esm({
|
|
267885
|
+
"../storage/src/postgres-connector-auth-pending.ts"() {
|
|
267886
|
+
"use strict";
|
|
267887
|
+
init_esm();
|
|
267888
|
+
init_pg_ident();
|
|
267889
|
+
ident17 = (s2) => {
|
|
267890
|
+
quoteIdent2(s2);
|
|
267891
|
+
return s2;
|
|
267892
|
+
};
|
|
267893
|
+
PostgresGithubAppPendingStore = class _PostgresGithubAppPendingStore {
|
|
267894
|
+
constructor(pool, schema) {
|
|
267895
|
+
this.pool = pool;
|
|
267896
|
+
this.s = `"${ident17(schema)}"`;
|
|
267897
|
+
}
|
|
267898
|
+
s;
|
|
267899
|
+
static async open(pool, schema = "public") {
|
|
267900
|
+
const s2 = ident17(schema);
|
|
267901
|
+
await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
|
|
267902
|
+
await pool.query(`
|
|
267903
|
+
CREATE TABLE IF NOT EXISTS "${s2}".github_app_pending (
|
|
267904
|
+
state text PRIMARY KEY,
|
|
267905
|
+
company_id text,
|
|
267906
|
+
data jsonb NOT NULL,
|
|
267907
|
+
created_at timestamptz NOT NULL,
|
|
267908
|
+
expires_at timestamptz NOT NULL
|
|
267909
|
+
)`);
|
|
267910
|
+
return new _PostgresGithubAppPendingStore(pool, schema);
|
|
267911
|
+
}
|
|
267912
|
+
async put(entry) {
|
|
267913
|
+
await this.pool.query(
|
|
267914
|
+
`DELETE FROM ${this.s}.github_app_pending WHERE expires_at < $1`,
|
|
267915
|
+
[new Date(entry.createdAtMs)]
|
|
267916
|
+
);
|
|
267917
|
+
await this.pool.query(
|
|
267918
|
+
`INSERT INTO ${this.s}.github_app_pending (state, company_id, data, created_at, expires_at)
|
|
267919
|
+
VALUES ($1, $2, $3::jsonb, $4, $5)
|
|
267920
|
+
ON CONFLICT (state) DO UPDATE SET company_id = EXCLUDED.company_id, data = EXCLUDED.data,
|
|
267921
|
+
created_at = EXCLUDED.created_at, expires_at = EXCLUDED.expires_at`,
|
|
267922
|
+
[
|
|
267923
|
+
entry.state,
|
|
267924
|
+
entry.companyId ?? null,
|
|
267925
|
+
JSON.stringify(entry.value),
|
|
267926
|
+
new Date(entry.createdAtMs),
|
|
267927
|
+
new Date(entry.expiresAtMs)
|
|
267928
|
+
]
|
|
267929
|
+
);
|
|
267930
|
+
}
|
|
267931
|
+
async get(state, nowMs) {
|
|
267932
|
+
if (!state) return { status: "missing" };
|
|
267933
|
+
const r = await this.pool.query(
|
|
267934
|
+
`SELECT company_id, data, expires_at FROM ${this.s}.github_app_pending WHERE state = $1`,
|
|
267935
|
+
[state]
|
|
267936
|
+
);
|
|
267937
|
+
const row = r.rows[0];
|
|
267938
|
+
if (!row) return { status: "missing" };
|
|
267939
|
+
if (row.expires_at.getTime() < nowMs) return { status: "expired" };
|
|
267940
|
+
return { status: "found", value: { ...row.company_id ? { companyId: row.company_id } : {}, value: row.data } };
|
|
267941
|
+
}
|
|
267942
|
+
async patch(state, fields) {
|
|
267943
|
+
await this.pool.query(
|
|
267944
|
+
`UPDATE ${this.s}.github_app_pending SET data = data || $2::jsonb WHERE state = $1`,
|
|
267945
|
+
[state, JSON.stringify(fields)]
|
|
267946
|
+
);
|
|
267947
|
+
}
|
|
267948
|
+
};
|
|
267949
|
+
PostgresConnectorAuthSnapshotStore = class _PostgresConnectorAuthSnapshotStore {
|
|
267950
|
+
constructor(pool, schema) {
|
|
267951
|
+
this.pool = pool;
|
|
267952
|
+
this.s = `"${ident17(schema)}"`;
|
|
267953
|
+
}
|
|
267954
|
+
s;
|
|
267955
|
+
static async open(pool, schema = "public") {
|
|
267956
|
+
const s2 = ident17(schema);
|
|
267957
|
+
await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
|
|
267958
|
+
await pool.query(`
|
|
267959
|
+
CREATE TABLE IF NOT EXISTS "${s2}".connector_auth_snapshots (
|
|
267960
|
+
company_id text NOT NULL,
|
|
267961
|
+
actor_id text NOT NULL,
|
|
267962
|
+
connector_id text NOT NULL,
|
|
267963
|
+
rows jsonb NOT NULL,
|
|
267964
|
+
created_at timestamptz NOT NULL,
|
|
267965
|
+
expires_at timestamptz NOT NULL,
|
|
267966
|
+
PRIMARY KEY (company_id, actor_id, connector_id)
|
|
267967
|
+
)`);
|
|
267968
|
+
return new _PostgresConnectorAuthSnapshotStore(pool, schema);
|
|
267969
|
+
}
|
|
267970
|
+
async put(key2, rows, nowMs, expiresAtMs) {
|
|
267971
|
+
await this.pool.query(`DELETE FROM ${this.s}.connector_auth_snapshots WHERE expires_at < $1`, [new Date(nowMs)]);
|
|
267972
|
+
await this.pool.query(
|
|
267973
|
+
`INSERT INTO ${this.s}.connector_auth_snapshots (company_id, actor_id, connector_id, rows, created_at, expires_at)
|
|
267974
|
+
VALUES ($1, $2, $3, $4::jsonb, $5, $6)
|
|
267975
|
+
ON CONFLICT (company_id, actor_id, connector_id) DO UPDATE SET rows = EXCLUDED.rows,
|
|
267976
|
+
created_at = EXCLUDED.created_at, expires_at = EXCLUDED.expires_at`,
|
|
267977
|
+
[key2.companyId, key2.actorId, key2.connectorId, JSON.stringify(rows), new Date(nowMs), new Date(expiresAtMs)]
|
|
267978
|
+
);
|
|
267979
|
+
}
|
|
267980
|
+
async get(key2, nowMs) {
|
|
267981
|
+
const r = await this.pool.query(
|
|
267982
|
+
`SELECT rows, expires_at FROM ${this.s}.connector_auth_snapshots
|
|
267983
|
+
WHERE company_id = $1 AND actor_id = $2 AND connector_id = $3`,
|
|
267984
|
+
[key2.companyId, key2.actorId, key2.connectorId]
|
|
267985
|
+
);
|
|
267986
|
+
const row = r.rows[0];
|
|
267987
|
+
if (!row || row.expires_at.getTime() < nowMs) return void 0;
|
|
267988
|
+
return row.rows;
|
|
267989
|
+
}
|
|
267990
|
+
async delete(key2) {
|
|
267991
|
+
await this.pool.query(
|
|
267992
|
+
`DELETE FROM ${this.s}.connector_auth_snapshots WHERE company_id = $1 AND actor_id = $2 AND connector_id = $3`,
|
|
267993
|
+
[key2.companyId, key2.actorId, key2.connectorId]
|
|
267994
|
+
);
|
|
267995
|
+
}
|
|
267996
|
+
};
|
|
267997
|
+
}
|
|
267998
|
+
});
|
|
267999
|
+
|
|
267654
268000
|
// ../storage/src/postgres-dispatches.ts
|
|
267655
268001
|
function rowToRecord2(r) {
|
|
267656
268002
|
return {
|
|
@@ -267672,18 +268018,18 @@ function rowToRecord2(r) {
|
|
|
267672
268018
|
protocolRecoveryRound: r.protocol_recovery_round ?? null
|
|
267673
268019
|
};
|
|
267674
268020
|
}
|
|
267675
|
-
var
|
|
268021
|
+
var ident18, PostgresDispatchStore;
|
|
267676
268022
|
var init_postgres_dispatches = __esm({
|
|
267677
268023
|
"../storage/src/postgres-dispatches.ts"() {
|
|
267678
268024
|
"use strict";
|
|
267679
|
-
|
|
268025
|
+
ident18 = (schema) => schema.replace(/[^a-zA-Z0-9_]/g, "");
|
|
267680
268026
|
PostgresDispatchStore = class _PostgresDispatchStore {
|
|
267681
268027
|
constructor(pool, s2) {
|
|
267682
268028
|
this.pool = pool;
|
|
267683
268029
|
this.s = s2;
|
|
267684
268030
|
}
|
|
267685
268031
|
static async open(pool, schema = "public") {
|
|
267686
|
-
const s2 =
|
|
268032
|
+
const s2 = ident18(schema);
|
|
267687
268033
|
await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
|
|
267688
268034
|
await pool.query(`
|
|
267689
268035
|
CREATE TABLE IF NOT EXISTS "${s2}".dispatches (
|
|
@@ -268866,14 +269212,14 @@ function companySchemaName(companyId) {
|
|
|
268866
269212
|
if (typeof companyId !== "string" || !companyId.trim()) {
|
|
268867
269213
|
throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
|
|
268868
269214
|
}
|
|
268869
|
-
const hex = (0,
|
|
269215
|
+
const hex = (0, import_node_crypto78.createHash)("sha256").update(companyId, "utf8").digest("hex");
|
|
268870
269216
|
return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
|
|
268871
269217
|
}
|
|
268872
|
-
var
|
|
269218
|
+
var import_node_crypto78, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
|
|
268873
269219
|
var init_tenant_schema_mapping = __esm({
|
|
268874
269220
|
"../storage/src/tenant-schema-mapping.ts"() {
|
|
268875
269221
|
"use strict";
|
|
268876
|
-
|
|
269222
|
+
import_node_crypto78 = require("node:crypto");
|
|
268877
269223
|
init_esm();
|
|
268878
269224
|
init_pg_ident();
|
|
268879
269225
|
COMPANY_SCHEMA_PREFIX = "c_";
|
|
@@ -268947,7 +269293,7 @@ var init_tenant_schema_mapping = __esm({
|
|
|
268947
269293
|
|
|
268948
269294
|
// ../storage/src/company-data-plane-schema.ts
|
|
268949
269295
|
function canonicalTypeDefHash(def) {
|
|
268950
|
-
return `sha256:${(0,
|
|
269296
|
+
return `sha256:${(0, import_node_crypto79.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
|
|
268951
269297
|
}
|
|
268952
269298
|
function defaultArtifactTypeTemplate() {
|
|
268953
269299
|
return [
|
|
@@ -269129,11 +269475,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
|
|
|
269129
269475
|
}
|
|
269130
269476
|
return { inserted };
|
|
269131
269477
|
}
|
|
269132
|
-
var
|
|
269478
|
+
var import_node_crypto79, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
|
|
269133
269479
|
var init_company_data_plane_schema = __esm({
|
|
269134
269480
|
"../storage/src/company-data-plane-schema.ts"() {
|
|
269135
269481
|
"use strict";
|
|
269136
|
-
|
|
269482
|
+
import_node_crypto79 = require("node:crypto");
|
|
269137
269483
|
init_esm();
|
|
269138
269484
|
init_pg_ident();
|
|
269139
269485
|
DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
|
|
@@ -269212,11 +269558,11 @@ function rowToFile2(row) {
|
|
|
269212
269558
|
updatedAt: new Date(row.updated_at).toISOString()
|
|
269213
269559
|
};
|
|
269214
269560
|
}
|
|
269215
|
-
var
|
|
269561
|
+
var import_node_crypto80, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
|
|
269216
269562
|
var init_company_owned_registry_store = __esm({
|
|
269217
269563
|
"../storage/src/company-owned-registry-store.ts"() {
|
|
269218
269564
|
"use strict";
|
|
269219
|
-
|
|
269565
|
+
import_node_crypto80 = require("node:crypto");
|
|
269220
269566
|
init_esm();
|
|
269221
269567
|
init_src();
|
|
269222
269568
|
init_pg_ident();
|
|
@@ -269601,7 +269947,7 @@ var init_company_owned_registry_store = __esm({
|
|
|
269601
269947
|
enabled: skill.enabled,
|
|
269602
269948
|
files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
|
|
269603
269949
|
});
|
|
269604
|
-
return (0,
|
|
269950
|
+
return (0, import_node_crypto80.createHash)("sha256").update(body2).digest("hex");
|
|
269605
269951
|
}
|
|
269606
269952
|
};
|
|
269607
269953
|
}
|
|
@@ -272411,7 +272757,7 @@ function sourceSetConservation(input) {
|
|
|
272411
272757
|
return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
|
|
272412
272758
|
}
|
|
272413
272759
|
function payloadChecksum(value2) {
|
|
272414
|
-
return (0,
|
|
272760
|
+
return (0, import_node_crypto81.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
272415
272761
|
}
|
|
272416
272762
|
async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
|
|
272417
272763
|
const cs = quoteIdent2(companySchema);
|
|
@@ -272803,11 +273149,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
|
|
|
272803
273149
|
sequences
|
|
272804
273150
|
};
|
|
272805
273151
|
}
|
|
272806
|
-
var
|
|
273152
|
+
var import_node_crypto81, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
|
|
272807
273153
|
var init_tenant_migration_operator = __esm({
|
|
272808
273154
|
"../storage/src/tenant-migration-operator.ts"() {
|
|
272809
273155
|
"use strict";
|
|
272810
|
-
|
|
273156
|
+
import_node_crypto81 = require("node:crypto");
|
|
272811
273157
|
init_esm();
|
|
272812
273158
|
init_pg_ident();
|
|
272813
273159
|
init_tenancy_attribution();
|
|
@@ -273043,8 +273389,8 @@ var init_tenant_new_company_provision = __esm({
|
|
|
273043
273389
|
// ../storage/src/knowledge-snapshot-crypto.ts
|
|
273044
273390
|
function sealSnapshot(snapshot, key2) {
|
|
273045
273391
|
if (snapshot.content.startsWith(PREFIX3)) return structuredClone(snapshot);
|
|
273046
|
-
const iv = (0,
|
|
273047
|
-
const cipher = (0,
|
|
273392
|
+
const iv = (0, import_node_crypto82.randomBytes)(12);
|
|
273393
|
+
const cipher = (0, import_node_crypto82.createCipheriv)("aes-256-gcm", bytes(key2), iv);
|
|
273048
273394
|
cipher.setAAD(aad2(snapshot));
|
|
273049
273395
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
273050
273396
|
return { ...structuredClone(snapshot), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
|
|
@@ -273054,7 +273400,7 @@ function openSnapshot(snapshot, key2) {
|
|
|
273054
273400
|
const packed = snapshot.content.slice(PREFIX3.length).split(".");
|
|
273055
273401
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
273056
273402
|
const [iv, tag, data] = packed;
|
|
273057
|
-
const decipher = (0,
|
|
273403
|
+
const decipher = (0, import_node_crypto82.createDecipheriv)("aes-256-gcm", bytes(key2), Buffer.from(iv, "base64url"));
|
|
273058
273404
|
decipher.setAAD(aad2(snapshot));
|
|
273059
273405
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
273060
273406
|
return {
|
|
@@ -273062,11 +273408,11 @@ function openSnapshot(snapshot, key2) {
|
|
|
273062
273408
|
content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
|
|
273063
273409
|
};
|
|
273064
273410
|
}
|
|
273065
|
-
var
|
|
273411
|
+
var import_node_crypto82, PREFIX3, bytes, aad2;
|
|
273066
273412
|
var init_knowledge_snapshot_crypto = __esm({
|
|
273067
273413
|
"../storage/src/knowledge-snapshot-crypto.ts"() {
|
|
273068
273414
|
"use strict";
|
|
273069
|
-
|
|
273415
|
+
import_node_crypto82 = require("node:crypto");
|
|
273070
273416
|
PREFIX3 = "oasis-knowledge:v1:";
|
|
273071
273417
|
bytes = (key2) => {
|
|
273072
273418
|
const value2 = Buffer.from(key2);
|
|
@@ -273114,7 +273460,7 @@ function assertRecordScope(record9, scope2) {
|
|
|
273114
273460
|
function equal(left, right) {
|
|
273115
273461
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
273116
273462
|
}
|
|
273117
|
-
var
|
|
273463
|
+
var ident19, TABLES, TABLE_BY_KIND, PostgresKnowledgeGovernanceStore;
|
|
273118
273464
|
var init_postgres_knowledge = __esm({
|
|
273119
273465
|
"../storage/src/postgres-knowledge.ts"() {
|
|
273120
273466
|
"use strict";
|
|
@@ -273122,7 +273468,7 @@ var init_postgres_knowledge = __esm({
|
|
|
273122
273468
|
init_pg_ident();
|
|
273123
273469
|
init_pg_sanitize();
|
|
273124
273470
|
init_knowledge_snapshot_crypto();
|
|
273125
|
-
|
|
273471
|
+
ident19 = (value2) => {
|
|
273126
273472
|
quoteIdent2(value2);
|
|
273127
273473
|
return value2;
|
|
273128
273474
|
};
|
|
@@ -273280,11 +273626,11 @@ var init_postgres_knowledge = __esm({
|
|
|
273280
273626
|
constructor(pool, schema, snapshotKey2) {
|
|
273281
273627
|
this.pool = pool;
|
|
273282
273628
|
this.snapshotKey = snapshotKey2;
|
|
273283
|
-
this.s = `"${
|
|
273629
|
+
this.s = `"${ident19(schema)}"`;
|
|
273284
273630
|
}
|
|
273285
273631
|
s;
|
|
273286
273632
|
static async open(pool, schema = "public", snapshotKey2) {
|
|
273287
|
-
const safe =
|
|
273633
|
+
const safe = ident19(schema);
|
|
273288
273634
|
await pool.query(`CREATE SCHEMA IF NOT EXISTS "${safe}"`);
|
|
273289
273635
|
for (const spec of TABLES) {
|
|
273290
273636
|
await pool.query(`
|
|
@@ -273958,7 +274304,7 @@ function reportedCost(v2) {
|
|
|
273958
274304
|
}
|
|
273959
274305
|
function newUsageBackfillManifestId(now = /* @__PURE__ */ new Date()) {
|
|
273960
274306
|
const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
|
|
273961
|
-
return `ulb-${stamp}-${(0,
|
|
274307
|
+
return `ulb-${stamp}-${(0, import_node_crypto83.randomBytes)(3).toString("hex")}`;
|
|
273962
274308
|
}
|
|
273963
274309
|
async function backfillUsageLedger(ledger, opts) {
|
|
273964
274310
|
if (!opts.dryRun && !opts.manifestId) throw new Error("execute \u9700\u8981 manifestId");
|
|
@@ -274392,11 +274738,11 @@ async function audit(c, s2, manifestId, runId, field, before, after, createdAt)
|
|
|
274392
274738
|
[manifestId, runId, field, before == null ? null : JSON.stringify(before), after == null ? null : JSON.stringify(after), createdAt]
|
|
274393
274739
|
);
|
|
274394
274740
|
}
|
|
274395
|
-
var
|
|
274741
|
+
var import_node_crypto83, BUCKETS, ENDED_SQL, START_EVIDENCE_SQL, CHAT_RUN_SQL, emptyStep, fourOf, sameUsage, ChatRunLookup;
|
|
274396
274742
|
var init_usage_ledger_backfill = __esm({
|
|
274397
274743
|
"../storage/src/usage-ledger-backfill.ts"() {
|
|
274398
274744
|
"use strict";
|
|
274399
|
-
|
|
274745
|
+
import_node_crypto83 = require("node:crypto");
|
|
274400
274746
|
init_src();
|
|
274401
274747
|
init_pg_ident();
|
|
274402
274748
|
init_postgres_trace();
|
|
@@ -274528,9 +274874,11 @@ __export(src_exports, {
|
|
|
274528
274874
|
PostgresChatItemStore: () => PostgresChatItemStore,
|
|
274529
274875
|
PostgresChatSessionStore: () => PostgresChatSessionStore,
|
|
274530
274876
|
PostgresChatTurnStore: () => PostgresChatTurnStore,
|
|
274877
|
+
PostgresConnectorAuthSnapshotStore: () => PostgresConnectorAuthSnapshotStore,
|
|
274531
274878
|
PostgresControlPlaneStore: () => PostgresControlPlaneStore,
|
|
274532
274879
|
PostgresDelegationStore: () => PostgresDelegationStore,
|
|
274533
274880
|
PostgresDispatchStore: () => PostgresDispatchStore,
|
|
274881
|
+
PostgresGithubAppPendingStore: () => PostgresGithubAppPendingStore,
|
|
274534
274882
|
PostgresHumanPrefsStore: () => PostgresHumanPrefsStore,
|
|
274535
274883
|
PostgresKnowledgeGovernanceStore: () => PostgresKnowledgeGovernanceStore,
|
|
274536
274884
|
PostgresModelPriceStore: () => PostgresModelPriceStore,
|
|
@@ -274664,6 +275012,7 @@ var init_src10 = __esm({
|
|
|
274664
275012
|
init_postgres_type_registry();
|
|
274665
275013
|
init_postgres_actor_memory();
|
|
274666
275014
|
init_postgres_inbox_read();
|
|
275015
|
+
init_postgres_connector_auth_pending();
|
|
274667
275016
|
init_postgres_dispatches();
|
|
274668
275017
|
init_tenancy_inventory();
|
|
274669
275018
|
init_tenancy_move();
|
|
@@ -275893,6 +276242,7 @@ __export(src_exports2, {
|
|
|
275893
276242
|
MirrorEngine: () => MirrorEngine,
|
|
275894
276243
|
MissingCompanyContextError: () => MissingCompanyContextError,
|
|
275895
276244
|
NODE_HEARTBEAT_STALE_MS: () => NODE_HEARTBEAT_STALE_MS,
|
|
276245
|
+
NOTIFICATIONS_CHANGED: () => NOTIFICATIONS_CHANGED,
|
|
275896
276246
|
NPM_PROBE_TIMEOUT_MS: () => NPM_PROBE_TIMEOUT_MS,
|
|
275897
276247
|
NdjsonOplogStore: () => NdjsonOplogStore,
|
|
275898
276248
|
NodeHealthTracker: () => NodeHealthTracker,
|
|
@@ -276210,6 +276560,7 @@ __export(src_exports2, {
|
|
|
276210
276560
|
openChatTurn: () => openChatTurn,
|
|
276211
276561
|
openKnowledgeSnapshot: () => openKnowledgeSnapshot,
|
|
276212
276562
|
openNewEngine: () => openNewEngine,
|
|
276563
|
+
operatorCrossCompanyRead: () => operatorCrossCompanyRead,
|
|
276213
276564
|
outputsPartProvider: () => outputsPartProvider,
|
|
276214
276565
|
packMatches: () => packMatches,
|
|
276215
276566
|
parentConversationTaskLines: () => parentConversationTaskLines,
|
|
@@ -276811,14 +277162,14 @@ init_src();
|
|
|
276811
277162
|
var os15 = __toESM(require("node:os"));
|
|
276812
277163
|
var path45 = __toESM(require("node:path"));
|
|
276813
277164
|
var import_node_child_process26 = require("node:child_process");
|
|
276814
|
-
var
|
|
277165
|
+
var import_node_crypto94 = require("node:crypto");
|
|
276815
277166
|
|
|
276816
277167
|
// ../cli/src/cli.ts
|
|
276817
277168
|
init_src();
|
|
276818
277169
|
var fs43 = __toESM(require("node:fs"), 1);
|
|
276819
277170
|
var os12 = __toESM(require("node:os"), 1);
|
|
276820
277171
|
var path38 = __toESM(require("node:path"), 1);
|
|
276821
|
-
var
|
|
277172
|
+
var import_node_crypto92 = require("node:crypto");
|
|
276822
277173
|
|
|
276823
277174
|
// ../cli/src/serve.ts
|
|
276824
277175
|
init_src11();
|
|
@@ -276830,11 +277181,11 @@ var fs35 = __toESM(require("node:fs"), 1);
|
|
|
276830
277181
|
var os8 = __toESM(require("node:os"), 1);
|
|
276831
277182
|
var path29 = __toESM(require("node:path"), 1);
|
|
276832
277183
|
var import_node_child_process18 = require("node:child_process");
|
|
276833
|
-
var
|
|
277184
|
+
var import_node_crypto88 = require("node:crypto");
|
|
276834
277185
|
var import_node_url7 = require("node:url");
|
|
276835
277186
|
|
|
276836
277187
|
// ../cli/src/artifact-discovery-source.ts
|
|
276837
|
-
var
|
|
277188
|
+
var import_node_crypto84 = require("node:crypto");
|
|
276838
277189
|
init_src7();
|
|
276839
277190
|
var ArtifactDiscoverySourceUnreadableError = class extends Error {
|
|
276840
277191
|
constructor(message) {
|
|
@@ -276864,7 +277215,7 @@ async function resolveArtifactDiscoverySourceContent(blobs, input) {
|
|
|
276864
277215
|
throw new ArtifactDiscoverySourceUnreadableError(`Artifact Revision ${input.revisionId} \u7684 contentKind \u4E0D\u53D7\u652F\u6301\uFF1A${String(input.contentKind)}`);
|
|
276865
277216
|
}
|
|
276866
277217
|
const rootBytes = await blobs.get(input.contentRef);
|
|
276867
|
-
const sourceFingerprint = (0,
|
|
277218
|
+
const sourceFingerprint = (0, import_node_crypto84.createHash)("sha256").update(rootBytes).digest("hex");
|
|
276868
277219
|
if (input.contentKind === "inline-blob") {
|
|
276869
277220
|
const sourceContent = decodeText3(rootBytes);
|
|
276870
277221
|
if (sourceContent === null) {
|
|
@@ -276888,7 +277239,7 @@ ${entry.text}`).join("\n\n"),
|
|
|
276888
277239
|
}
|
|
276889
277240
|
|
|
276890
277241
|
// ../server/src/domains/discussions/service.ts
|
|
276891
|
-
var
|
|
277242
|
+
var import_node_crypto85 = require("node:crypto");
|
|
276892
277243
|
init_zod();
|
|
276893
277244
|
init_discussions();
|
|
276894
277245
|
init_router();
|
|
@@ -276950,7 +277301,7 @@ function remapTopics(topics, removed) {
|
|
|
276950
277301
|
return [...out].map(([topic_id, summary]) => ({ topic_id, summary }));
|
|
276951
277302
|
}
|
|
276952
277303
|
var entryId = (projectId2, id) => JSON.stringify([projectId2, id]);
|
|
276953
|
-
var hash2 = (s2) => (0,
|
|
277304
|
+
var hash2 = (s2) => (0, import_node_crypto85.createHash)("sha256").update(s2).digest("hex").slice(0, 24);
|
|
276954
277305
|
var canonical = (s2) => s2.normalize("NFKC").trim().toLocaleLowerCase();
|
|
276955
277306
|
function decisionFingerprint(d) {
|
|
276956
277307
|
return hash2(JSON.stringify([d.statement, d.rationale, d.alternatives]));
|
|
@@ -277170,7 +277521,7 @@ var DiscussionService = class {
|
|
|
277170
277521
|
throw new ApiError(409, "DISCUSSION_CONFLICT", "\u9879\u76EE\u8BAE\u9898\u6216\u51B3\u7B56\u5DF2\u53D8\u5316\uFF0C\u8BF7\u8BFB\u53D6\u6700\u65B0\u5185\u5BB9\u540E\u4FEE\u6B63");
|
|
277171
277522
|
}
|
|
277172
277523
|
}
|
|
277173
|
-
const operation = (value2) => tx.put("operation", (0,
|
|
277524
|
+
const operation = (value2) => tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
|
|
277174
277525
|
...value2,
|
|
277175
277526
|
projectId: projectId2,
|
|
277176
277527
|
actorId: ctx.actorId,
|
|
@@ -277187,7 +277538,7 @@ var DiscussionService = class {
|
|
|
277187
277538
|
if (id.startsWith("new:")) {
|
|
277188
277539
|
if (BUG_TOPIC.test(t.title.trim())) invalid("topics.title", `\u300C${t.title}\u300D\u662F\u5355\u4E2A Bug\uFF1A\u4FEE\u590D\u60C5\u51B5\u5199\u8FDB\u8BA8\u8BBA\u8BB0\u5F55\uFF0C\u5B9A\u51FA\u7684\u89C4\u5219\u6302\u5230\u5BF9\u5E94\u529F\u80FD\u8BAE\u9898\u4E0B\uFF0C\u4E0D\u6309 Bug \u53F7\u5EFA\u8BAE\u9898`);
|
|
277189
277540
|
const existing = [...topicMap.values()].find((x2) => canonical(x2.title) === canonical(t.title));
|
|
277190
|
-
id = existing?.topicId ?? `topic_${(0,
|
|
277541
|
+
id = existing?.topicId ?? `topic_${(0, import_node_crypto85.randomUUID)()}`;
|
|
277191
277542
|
if (!existing) createdTopics.add(id);
|
|
277192
277543
|
} else if (!topicMap.has(id)) invalid("topics.topic_id", `\u8BAE\u9898 ${id} \u4E0D\u5B58\u5728\uFF1B\u65B0\u8BAE\u9898\u4F7F\u7528 new: \u524D\u7F00`);
|
|
277193
277544
|
topicAliases.set(t.topic_id, id);
|
|
@@ -277239,7 +277590,7 @@ var DiscussionService = class {
|
|
|
277239
277590
|
if (id.startsWith("new:")) {
|
|
277240
277591
|
const candidateKey = JSON.stringify([topicId, canonical(d.record.statement)]);
|
|
277241
277592
|
const existing = [...decisionMap.values()].find((x2) => x2.topicId === topicId && canonical(x2.record.statement) === canonical(d.record.statement));
|
|
277242
|
-
id = existing?.decisionId ?? candidateIds.get(candidateKey) ?? `decision_${(0,
|
|
277593
|
+
id = existing?.decisionId ?? candidateIds.get(candidateKey) ?? `decision_${(0, import_node_crypto85.randomUUID)()}`;
|
|
277243
277594
|
candidateIds.set(candidateKey, id);
|
|
277244
277595
|
} else if (!decisionMap.has(id)) invalid("decision_id", `\u51B3\u7B56 ${id} \u4E0D\u5B58\u5728\uFF1B\u65B0\u51B3\u7B56\u4F7F\u7528 new: \u524D\u7F00`);
|
|
277245
277596
|
decisionAliases.set(d.decision_id, id);
|
|
@@ -277501,7 +277852,7 @@ var DiscussionService = class {
|
|
|
277501
277852
|
...row.value.confirmation ? { confirmation: { ...row.value.confirmation, fingerprint: decisionFingerprint(record9) } } : {}
|
|
277502
277853
|
};
|
|
277503
277854
|
await tx.put("decision", row.id, value2);
|
|
277504
|
-
await tx.put("operation", (0,
|
|
277855
|
+
await tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
|
|
277505
277856
|
action: "edit",
|
|
277506
277857
|
kind: "decision",
|
|
277507
277858
|
projectId: projectId2,
|
|
@@ -277565,7 +277916,7 @@ var DiscussionService = class {
|
|
|
277565
277916
|
if (!current || current.revision !== row.revision) throw new ApiError(409, "DISCUSSION_CONFLICT", `\u8BA8\u8BBA ${row.id} \u5DF2\u88AB\u4FEE\u6539\uFF0C\u8BF7\u8BFB\u53D6\u6700\u65B0\u5185\u5BB9\u540E\u91CD\u8BD5`);
|
|
277566
277917
|
const summary = given.get(row.id);
|
|
277567
277918
|
await tx.put("discussion", row.id, { ...current.value, record: { ...current.value.record, summary } });
|
|
277568
|
-
await tx.put("operation", (0,
|
|
277919
|
+
await tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
|
|
277569
277920
|
action: "edit",
|
|
277570
277921
|
kind: "discussion",
|
|
277571
277922
|
projectId: current.value.record.project_id,
|
|
@@ -277581,7 +277932,7 @@ var DiscussionService = class {
|
|
|
277581
277932
|
});
|
|
277582
277933
|
}
|
|
277583
277934
|
async operation(tx, actorId, kind, id, from, to) {
|
|
277584
|
-
await tx.put("operation", (0,
|
|
277935
|
+
await tx.put("operation", (0, import_node_crypto85.randomUUID)(), { actorId, kind, id, from, to, at: new Date(this.now()).toISOString() });
|
|
277585
277936
|
}
|
|
277586
277937
|
};
|
|
277587
277938
|
function pickDiscussionContent(d) {
|
|
@@ -277881,7 +278232,7 @@ var DiscussionContext = class {
|
|
|
277881
278232
|
};
|
|
277882
278233
|
|
|
277883
278234
|
// ../server/src/domains/discussions/worker.ts
|
|
277884
|
-
var
|
|
278235
|
+
var import_node_crypto86 = require("node:crypto");
|
|
277885
278236
|
var DISCUSSION_IDLE_MS = 15 * 6e4;
|
|
277886
278237
|
var DISCUSSION_MAX_CORRECTIONS = 3;
|
|
277887
278238
|
var DISCUSSION_LEASE_MS = 2 * 6e4;
|
|
@@ -277907,7 +278258,7 @@ var DiscussionWorker = class {
|
|
|
277907
278258
|
if (await this.isReplying(sessionId)) return false;
|
|
277908
278259
|
const cutoff = eligibleCutoff(await this.service.chat.listMessages(sessionId), this.service.now());
|
|
277909
278260
|
if (!cutoff) return false;
|
|
277910
|
-
const owner = (0,
|
|
278261
|
+
const owner = (0, import_node_crypto86.randomUUID)();
|
|
277911
278262
|
const claimed = await this.service.store.transaction(async (tx) => {
|
|
277912
278263
|
const old = (await tx.get("job", sessionId))?.value;
|
|
277913
278264
|
if (old?.status === "running" && (old.leaseUntil ?? 0) > this.service.now()) return null;
|
|
@@ -278629,7 +278980,7 @@ function createDiscussionRuntime(options) {
|
|
|
278629
278980
|
}
|
|
278630
278981
|
|
|
278631
278982
|
// ../server/src/domains/discussions/store.ts
|
|
278632
|
-
var
|
|
278983
|
+
var import_node_crypto87 = require("node:crypto");
|
|
278633
278984
|
var import_promises17 = require("node:fs/promises");
|
|
278634
278985
|
var import_node_path27 = require("node:path");
|
|
278635
278986
|
var key = (kind, id) => JSON.stringify([kind, id]);
|
|
@@ -278674,7 +279025,7 @@ var MemoryDiscussionStore = class _MemoryDiscussionStore {
|
|
|
278674
279025
|
if (changed) {
|
|
278675
279026
|
if (this.filename) {
|
|
278676
279027
|
await (0, import_promises17.mkdir)((0, import_node_path27.dirname)(this.filename), { recursive: true });
|
|
278677
|
-
const temp = `${this.filename}.${(0,
|
|
279028
|
+
const temp = `${this.filename}.${(0, import_node_crypto87.randomUUID)()}.tmp`;
|
|
278678
279029
|
await (0, import_promises17.writeFile)(temp, JSON.stringify(next), "utf8");
|
|
278679
279030
|
await (0, import_promises17.rename)(temp, this.filename);
|
|
278680
279031
|
}
|
|
@@ -279623,7 +279974,7 @@ function oasisWrapperScript() {
|
|
|
279623
279974
|
const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
279624
279975
|
const tsx = path29.join(repoRoot, "node_modules/.bin/tsx");
|
|
279625
279976
|
const main = path29.join(repoRoot, "packages/cli/src/main.ts");
|
|
279626
|
-
const key2 = (0,
|
|
279977
|
+
const key2 = (0, import_node_crypto88.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
279627
279978
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
279628
279979
|
const stable = path29.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key2}`);
|
|
279629
279980
|
let dir;
|
|
@@ -280016,7 +280367,7 @@ async function startServe(opts) {
|
|
|
280016
280367
|
if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
|
|
280017
280368
|
const online = hub.connectedDaemons().some((d) => d.daemonId === nodeId);
|
|
280018
280369
|
if (!online) return Promise.resolve({ ok: false, reason: "\u8282\u70B9\u5F53\u524D\u4E0D\u5728\u7EBF\uFF0C\u7528\u7684\u662F\u5B83\u4E0A\u6B21\u62A5\u7684\u6E05\u5355" });
|
|
280019
|
-
const requestId = (0,
|
|
280370
|
+
const requestId = (0, import_node_crypto88.randomUUID)();
|
|
280020
280371
|
const task = new Promise((resolve12) => {
|
|
280021
280372
|
const timer = setTimeout(() => {
|
|
280022
280373
|
modelRefreshWaiters.delete(requestId);
|
|
@@ -280817,7 +281168,7 @@ async function startServe(opts) {
|
|
|
280817
281168
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
280818
281169
|
if (buf || session.runId) {
|
|
280819
281170
|
await turnStore.appendMessage({
|
|
280820
|
-
id: (0,
|
|
281171
|
+
id: (0, import_node_crypto88.randomUUID)(),
|
|
280821
281172
|
sessionId: chatSessionId,
|
|
280822
281173
|
role: "assistant",
|
|
280823
281174
|
content: buf,
|
|
@@ -280863,7 +281214,7 @@ async function startServe(opts) {
|
|
|
280863
281214
|
chatTargets: {
|
|
280864
281215
|
inspect: inspectChatTarget,
|
|
280865
281216
|
createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
|
|
280866
|
-
const sessionId = (0,
|
|
281217
|
+
const sessionId = (0, import_node_crypto88.randomUUID)();
|
|
280867
281218
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
280868
281219
|
const binding = await registryStore.getBinding(agentId).catch(() => null);
|
|
280869
281220
|
await (await chatStoreFor(companyId)).createSession({
|
|
@@ -281056,7 +281407,8 @@ async function startServe(opts) {
|
|
|
281056
281407
|
})();
|
|
281057
281408
|
}
|
|
281058
281409
|
await syncRegistryRolesToKernel(registryStore, defaultCompanyKernel);
|
|
281059
|
-
const
|
|
281410
|
+
const operatorScopesOf = (authorization) => authorization.startsWith("Bearer ") ? issuer.resolveClaims(authorization.slice("Bearer ".length))?.scopes : void 0;
|
|
281411
|
+
const resolveCompanyContext = async (actor, headers, pathname, method) => {
|
|
281060
281412
|
if (isCompanyCrossTenantPath(pathname)) {
|
|
281061
281413
|
return { kind: "exempt" };
|
|
281062
281414
|
}
|
|
@@ -281079,7 +281431,11 @@ async function startServe(opts) {
|
|
|
281079
281431
|
}
|
|
281080
281432
|
const ctx = await companies.service.resolveCurrentCompany(me.accountId, selector);
|
|
281081
281433
|
if (!ctx) return { kind: "not-found", ...selector !== void 0 ? { selector } : {} };
|
|
281082
|
-
|
|
281434
|
+
if (ctx.isMember) return { kind: "ok", companyId: ctx.company.id };
|
|
281435
|
+
if (operatorCrossCompanyRead({ scopes: operatorScopesOf(authz) }, method)) {
|
|
281436
|
+
return { kind: "ok", companyId: ctx.company.id };
|
|
281437
|
+
}
|
|
281438
|
+
return { kind: "forbidden" };
|
|
281083
281439
|
};
|
|
281084
281440
|
const resolveActor = (token) => issuer.resolve(token) ?? (opts.allowSimpleTokens && token.startsWith("token:") ? token.slice("token:".length) : null);
|
|
281085
281441
|
const AGENT_PRINCIPAL_CACHE_MAX = 4096;
|
|
@@ -281625,9 +281981,9 @@ async function startServe(opts) {
|
|
|
281625
281981
|
return engine2;
|
|
281626
281982
|
};
|
|
281627
281983
|
const liveKernels = () => engineRouter.liveEngines().map((e) => e.kernel);
|
|
281628
|
-
const countRoleHolders = async (role) => (await roleHolders()).filter((a) => a.status !== "disabled" && a.roles?.includes(role)).length;
|
|
281629
|
-
const roleHolders = async () => {
|
|
281630
|
-
const employees = await
|
|
281984
|
+
const countRoleHolders = async (role, companyId) => (await roleHolders(companyId)).filter((a) => a.status !== "disabled" && a.roles?.includes(role)).length;
|
|
281985
|
+
const roleHolders = async (companyId) => {
|
|
281986
|
+
const employees = await (await actors.resolveCtx(companyId ?? defaultCompanyId)).service.listActors();
|
|
281631
281987
|
const ids2 = new Set(employees.map((a) => a.id));
|
|
281632
281988
|
const systemActors = kernelRegistry.filter((e) => !ids2.has(e.actor)).map((e) => ({ id: e.actor, roles: e.roles, status: "active" }));
|
|
281633
281989
|
return [...employees, ...systemActors];
|
|
@@ -282163,6 +282519,11 @@ async function startServe(opts) {
|
|
|
282163
282519
|
// CO-301 阶段1:请求热路径按当前公司经路由层取引擎(恒等到默认公司;per-company 懒建是后续阶段)。
|
|
282164
282520
|
resolveEngine: (companyId) => getEngine(companyId ?? defaultCompanyId),
|
|
282165
282521
|
actors,
|
|
282522
|
+
// Bug 0246:GitHub App 待回调登记与重连快照落共享 schema——服务器重启 / 换副本都读得到。
|
|
282523
|
+
connectorAuthPending: {
|
|
282524
|
+
githubApp: await PostgresGithubAppPendingStore.open(pgPool, sharedSchema),
|
|
282525
|
+
snapshots: await PostgresConnectorAuthSnapshotStore.open(pgPool, sharedSchema)
|
|
282526
|
+
},
|
|
282166
282527
|
port: opts.port ?? 7320,
|
|
282167
282528
|
projectState: projectStateStore,
|
|
282168
282529
|
artifactState: artifactStateStore,
|
|
@@ -282213,7 +282574,7 @@ async function startServe(opts) {
|
|
|
282213
282574
|
}));
|
|
282214
282575
|
}
|
|
282215
282576
|
const limits = { wallClockMs: wallClockForKind("planner") };
|
|
282216
|
-
const artifactId = `artifact:planner:${(0,
|
|
282577
|
+
const artifactId = `artifact:planner:${(0, import_node_crypto88.randomUUID)()}`;
|
|
282217
282578
|
const handle = await chatRemoteAdapter.spawn({
|
|
282218
282579
|
actor: planner.id,
|
|
282219
282580
|
// companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
|
|
@@ -282302,7 +282663,7 @@ async function startServe(opts) {
|
|
|
282302
282663
|
await rebuildLiveSchema();
|
|
282303
282664
|
for (const d of schema) engine2.kernel.setType(d);
|
|
282304
282665
|
},
|
|
282305
|
-
countRoleHolders,
|
|
282666
|
+
(role) => countRoleHolders(role, cid),
|
|
282306
282667
|
registryAudit
|
|
282307
282668
|
);
|
|
282308
282669
|
}
|
|
@@ -282441,9 +282802,9 @@ async function startServe(opts) {
|
|
|
282441
282802
|
// store(`public.actor_bindings`),org-registry cutover 之后它是冻结旧镜像——只留给
|
|
282442
282803
|
// 本域其它老读口,工作区定位一律不许再用它。
|
|
282443
282804
|
resolveBinding: resolveCompanyBinding,
|
|
282444
|
-
/* ADR 0613
|
|
282805
|
+
/* ADR 0613:建会话那一下要读员工详情页配的型号,按**当前公司**读
|
|
282445
282806
|
(与 `resolveBinding` 同一条理由:全局 `registry` 对已切 `actor-config` 的公司是冻结旧镜像)。
|
|
282446
|
-
⚠
|
|
282807
|
+
⚠ 只有这一下读它;解析每一轮的模型依旧不读员工配置(ADR 0610 D1)。 */
|
|
282447
282808
|
resolveActorModel: resolveAgentConfiguredModel,
|
|
282448
282809
|
// 按 runId 路由:切换后新会话的事件落在本公司库里,共享 store 会一条都补不出 parts。
|
|
282449
282810
|
// ⚠ `runRoutedTrace` 声明在本行**之后**:包成箭头函数避 TDZ(本域只需要 listEvents)。
|
|
@@ -282531,6 +282892,8 @@ async function startServe(opts) {
|
|
|
282531
282892
|
// live 注册表算 `frameCursor`。与 server.ts 的双写解析同一层,与 attach 路径共享 registry。
|
|
282532
282893
|
resolveChatItems: (companyId) => chatItemsFor(companyId),
|
|
282533
282894
|
liveChat,
|
|
282895
|
+
// ADR 0615 B3:快照读口给 serve 重启留下的孤儿插话落结论时问节点——与 `/append` 同一条网关。
|
|
282896
|
+
confirmInputReceipt: (ref2) => chatRemoteAdapter ? chatRemoteAdapter.confirmInputReceipt(ref2.nodeId, ref2.dispatchId, ref2.runtimeKey) : Promise.resolve({ status: "unknown", reason: "node-gateway-not-ready" }),
|
|
282534
282897
|
// ADR-0587:列表行派生 `unread`,与 collab 域收件箱读同一份按公司的水位(无 PG 时闭包自己回落单实例)。
|
|
282535
282898
|
resolveReadMarkers: readMarkerStoreFor,
|
|
282536
282899
|
// ADR 0610 D4:`GET /api/chat-sessions/:id/usage` 的取数口——**与 collab 域是同一个实例**,
|
|
@@ -283134,8 +283497,6 @@ async function startServe(opts) {
|
|
|
283134
283497
|
discussSessions: new FileSideMap(path29.join(opts.dir, "discuss-sessions.json")),
|
|
283135
283498
|
escalateDiscussRetain: new FileSideMap(path29.join(opts.dir, "escalate-discuss-retain.json")),
|
|
283136
283499
|
// 切片 2b:代署 escalate 发起会话保留(落盘)
|
|
283137
|
-
// Bug 0107:插入结果读口结算孤儿插入行(serve 在途中重启)时问节点——走 chat 那条网关。
|
|
283138
|
-
confirmInputReceipt: (ref2) => chatRemoteAdapter ? chatRemoteAdapter.confirmInputReceipt(ref2.nodeId, ref2.dispatchId, ref2.runtimeKey) : Promise.resolve({ status: "unknown", reason: "node-gateway-not-ready" }),
|
|
283139
283500
|
dispatchChat: automationDispatchChat = async (chatReq) => {
|
|
283140
283501
|
const dispatchChatImpl = async ({ actorId, message, dispatchId: requestDispatchId, admitDispatch, executionProfile, knowledgeAttemptKind, requiredConnectorSlugs, env: requestEnv, sessionId, chatSessionId, chatTurnId, attachments, workspace, companyId, model: sessionModelOverride, parentConversationSnapshot, extraSystemPrompt, delegatedChildTurn, workspaceBundle }) => {
|
|
283141
283502
|
const isolatedKnowledgeTurn = executionProfile === "knowledge-single-turn";
|
|
@@ -283158,10 +283519,10 @@ async function startServe(opts) {
|
|
|
283158
283519
|
if (isDeletedActor(dispatchTarget)) {
|
|
283159
283520
|
throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
|
|
283160
283521
|
}
|
|
283161
|
-
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0,
|
|
283522
|
+
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto88.randomUUID)());
|
|
283162
283523
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
283163
|
-
const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0,
|
|
283164
|
-
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0,
|
|
283524
|
+
const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto88.randomUUID)()}`;
|
|
283525
|
+
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto88.randomUUID)()}`;
|
|
283165
283526
|
let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
|
|
283166
283527
|
if (stableDispatch && !stableDispatch.shouldDispatch) {
|
|
283167
283528
|
if (isHumanSubmitDispatchId(requestDispatchId)) {
|
|
@@ -284611,7 +284972,7 @@ async function startServe(opts) {
|
|
|
284611
284972
|
console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
|
|
284612
284973
|
return;
|
|
284613
284974
|
}
|
|
284614
|
-
const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0,
|
|
284975
|
+
const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto88.randomUUID)()}`;
|
|
284615
284976
|
try {
|
|
284616
284977
|
const inserted = await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
284617
284978
|
id: ledgerId,
|
|
@@ -284711,7 +285072,7 @@ async function startServe(opts) {
|
|
|
284711
285072
|
const kernelModel = newKernel.model;
|
|
284712
285073
|
const art = kernelModel.artifacts.get(nodeId);
|
|
284713
285074
|
const revWid = art?.workspace ?? "";
|
|
284714
|
-
const ledgerId = `dispatch:${(0,
|
|
285075
|
+
const ledgerId = `dispatch:${(0, import_node_crypto88.randomUUID)()}`;
|
|
284715
285076
|
try {
|
|
284716
285077
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
284717
285078
|
id: ledgerId,
|
|
@@ -285105,7 +285466,7 @@ async function startServe(opts) {
|
|
|
285105
285466
|
resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
|
|
285106
285467
|
try {
|
|
285107
285468
|
const governance = server.knowledgeGovernance;
|
|
285108
|
-
const taskFingerprint = (0,
|
|
285469
|
+
const taskFingerprint = (0, import_node_crypto88.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
|
|
285109
285470
|
const requestContext = {
|
|
285110
285471
|
organizationId: companyId,
|
|
285111
285472
|
actorId,
|
|
@@ -285832,7 +286193,9 @@ async function startServe(opts) {
|
|
|
285832
286193
|
slaMs: humanMs
|
|
285833
286194
|
};
|
|
285834
286195
|
},
|
|
285835
|
-
log: (message) => console.warn(message)
|
|
286196
|
+
log: (message) => console.warn(message),
|
|
286197
|
+
// 新进了通知就推给收件人本人(/api/events?topics=notifications):铃铛角标与页内提示不等 30 秒轮询。
|
|
286198
|
+
onNotified: (_companyId, recipients) => auditSink.notifyNotificationsChanged(recipients)
|
|
285836
286199
|
});
|
|
285837
286200
|
notificationLedgerWorker = worker;
|
|
285838
286201
|
const ledgerSubscribed = /* @__PURE__ */ new Set();
|
|
@@ -287699,11 +288062,12 @@ async function readClaudeQuota(binary, signal, deps = {}) {
|
|
|
287699
288062
|
// ../cli/src/daemon/quota/monitor.ts
|
|
287700
288063
|
var read2 = (runtime, signal) => runtime.kind === "codex" ? readCodexQuota(runtime.binary ?? "codex", signal) : readClaudeQuota(runtime.binary ?? "claude", signal, { version: runtime.version });
|
|
287701
288064
|
var RuntimeQuotaMonitor = class {
|
|
287702
|
-
constructor(runtimes, send, reader = read2, intervalMs = RUNTIME_QUOTA_POLL_MS) {
|
|
288065
|
+
constructor(runtimes, send, reader = read2, intervalMs = RUNTIME_QUOTA_POLL_MS, minGapMs = RUNTIME_QUOTA_REFRESH_MIN_GAP_MS) {
|
|
287703
288066
|
this.runtimes = runtimes;
|
|
287704
288067
|
this.send = send;
|
|
287705
288068
|
this.reader = reader;
|
|
287706
288069
|
this.intervalMs = intervalMs;
|
|
288070
|
+
this.minGapMs = minGapMs;
|
|
287707
288071
|
}
|
|
287708
288072
|
cache = [];
|
|
287709
288073
|
collectedAt;
|
|
@@ -287733,6 +288097,41 @@ var RuntimeQuotaMonitor = class {
|
|
|
287733
288097
|
});
|
|
287734
288098
|
return this.pending;
|
|
287735
288099
|
}
|
|
288100
|
+
/**
|
|
288101
|
+
* 人点了页面上的「刷新」(服务端下发 `refresh_quotas`,ADR 0620):**现在就去问上游**。
|
|
288102
|
+
*
|
|
288103
|
+
* 与 {@link refresh} 的唯一区别就是**不看那 5 分钟**——那条节流是背景轮询的节奏,
|
|
288104
|
+
* 对一个正盯着页面等结果的人没有任何意义。换上的是一条窄得多的闸:
|
|
288105
|
+
* {@link RUNTIME_QUOTA_REFRESH_MIN_GAP_MS}(30 秒)。连点被它挡下,且挡下时**如实说**
|
|
288106
|
+
* 「刚在 N 秒前采过」,不假装采了一次(发起人方申的定则:会静默降级的动作必须回报走了哪条路)。
|
|
288107
|
+
*
|
|
288108
|
+
* provider 自己给的 `retryAt` 退避**不在**绕过范围内:那是上游明说的「别来了」,
|
|
288109
|
+
* 谁点按钮都不该越过它。被它挡住的那个 runtime 在 `collect` 里照旧沿用上一次的结果。
|
|
288110
|
+
*/
|
|
288111
|
+
forceRefresh() {
|
|
288112
|
+
if (this.stopped) return Promise.resolve({ ok: false, reason: "\u8FD9\u53F0\u8282\u70B9\u6B63\u5728\u505C\u673A\uFF0C\u6CA1\u6709\u91CD\u91C7\u989D\u5EA6" });
|
|
288113
|
+
if (this.collectableKinds().length === 0) {
|
|
288114
|
+
return Promise.resolve({ ok: false, reason: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u4F1A\u4E0A\u62A5\u989D\u5EA6\u7684\u8FD0\u884C\u65F6\uFF08\u53EA\u6709 Claude Code \u548C Codex \u80FD\u67E5\u5230\u8BA2\u9605\u989D\u5EA6\uFF09" });
|
|
288115
|
+
}
|
|
288116
|
+
if (this.pending) return this.pending.then(() => ({ ok: true }));
|
|
288117
|
+
const sinceMs = this.collectedAt === void 0 ? Number.POSITIVE_INFINITY : Date.now() - this.collectedAt;
|
|
288118
|
+
if (sinceMs < this.minGapMs) {
|
|
288119
|
+
return Promise.resolve({
|
|
288120
|
+
ok: false,
|
|
288121
|
+
reason: `\u989D\u5EA6\u521A\u5728 ${Math.max(1, Math.round(sinceMs / 1e3))} \u79D2\u524D\u91C7\u8FC7\uFF0C\u9875\u9762\u4E0A\u5C31\u662F\u6700\u65B0\u6570\u636E\uFF1B${Math.ceil((this.minGapMs - sinceMs) / 1e3)} \u79D2\u540E\u53EF\u4EE5\u518D\u91C7\u4E00\u6B21`
|
|
288122
|
+
});
|
|
288123
|
+
}
|
|
288124
|
+
this.pending = this.collect().finally(() => {
|
|
288125
|
+
this.pending = void 0;
|
|
288126
|
+
});
|
|
288127
|
+
return this.pending.then(() => ({ ok: true }));
|
|
288128
|
+
}
|
|
288129
|
+
/** 这台机器上真的会上报额度的 runtime(白名单硬编码在 collect 里,两处取同一份判据)。 */
|
|
288130
|
+
collectableKinds() {
|
|
288131
|
+
const kinds = [];
|
|
288132
|
+
for (const r of this.runtimes) if (r.kind === "codex" || r.kind === "claude-code") kinds.push(r.kind);
|
|
288133
|
+
return kinds;
|
|
288134
|
+
}
|
|
287736
288135
|
async collect() {
|
|
287737
288136
|
const result = [];
|
|
287738
288137
|
for (const runtime of this.runtimes) {
|
|
@@ -287763,7 +288162,7 @@ var RuntimeQuotaMonitor = class {
|
|
|
287763
288162
|
init_wrapper();
|
|
287764
288163
|
init_src();
|
|
287765
288164
|
var import_node_os11 = require("node:os");
|
|
287766
|
-
var
|
|
288165
|
+
var import_node_crypto89 = require("node:crypto");
|
|
287767
288166
|
init_src8();
|
|
287768
288167
|
init_src2();
|
|
287769
288168
|
|
|
@@ -288582,6 +288981,13 @@ var DaemonWsClient = class {
|
|
|
288582
288981
|
void this.reportRuntimeModels({ force: true, requestId: msg.requestId });
|
|
288583
288982
|
break;
|
|
288584
288983
|
}
|
|
288984
|
+
case "refresh_quotas": {
|
|
288985
|
+
const requestId = msg.requestId;
|
|
288986
|
+
void this.quotaMonitor.forceRefresh().catch((err) => ({ ok: false, reason: `\u91CD\u91C7\u989D\u5EA6\u65F6\u51FA\u9519\uFF1A${err instanceof Error ? err.message : String(err)}` })).then((r) => {
|
|
288987
|
+
this.send({ type: "quota_refresh_result", requestId, ok: r.ok, ...r.reason ? { reason: r.reason } : {} });
|
|
288988
|
+
});
|
|
288989
|
+
break;
|
|
288990
|
+
}
|
|
288585
288991
|
case "update": {
|
|
288586
288992
|
this.pendingUpdatePkg = msg.pkg;
|
|
288587
288993
|
if (!this.onUpdate) {
|
|
@@ -288660,7 +289066,7 @@ var DaemonWsClient = class {
|
|
|
288660
289066
|
*/
|
|
288661
289067
|
async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
|
|
288662
289068
|
if (artifactIds.length === 0) return {};
|
|
288663
|
-
const requestId = (0,
|
|
289069
|
+
const requestId = (0, import_node_crypto89.randomUUID)();
|
|
288664
289070
|
return new Promise((resolve12, reject) => {
|
|
288665
289071
|
const timer = setTimeout(() => {
|
|
288666
289072
|
this.gcPending.delete(requestId);
|
|
@@ -288808,6 +289214,9 @@ var DaemonWsClient = class {
|
|
|
288808
289214
|
supportsChunkedMessages: true,
|
|
288809
289215
|
// Bug 0107:本 daemon 认 `input_receipt_query`。恒 true——handler 随包发。
|
|
288810
289216
|
supportsInputReceiptQuery: true,
|
|
289217
|
+
// ADR 0620:本 daemon 认 `refresh_quotas`(人点刷新时现去问一遍上游额度)。恒 true——
|
|
289218
|
+
// 采集器随包发。服务端据此对老节点当场回「升级后可用」,不必发一帧出去等超时。
|
|
289219
|
+
supportsQuotaRefresh: true,
|
|
288811
289220
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
288812
289221
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
288813
289222
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -289071,7 +289480,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
289071
289480
|
// ../cli/src/daemon/machine-id.ts
|
|
289072
289481
|
var import_node_child_process23 = require("node:child_process");
|
|
289073
289482
|
var import_node_fs24 = require("node:fs");
|
|
289074
|
-
var
|
|
289483
|
+
var import_node_crypto90 = require("node:crypto");
|
|
289075
289484
|
var import_node_os14 = require("node:os");
|
|
289076
289485
|
function linuxMachineId() {
|
|
289077
289486
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
@@ -289137,7 +289546,7 @@ var defaultSources = {
|
|
|
289137
289546
|
function resolveNodeId(sources = {}) {
|
|
289138
289547
|
const s2 = { ...defaultSources, ...sources };
|
|
289139
289548
|
const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
|
|
289140
|
-
const digest = (0,
|
|
289549
|
+
const digest = (0, import_node_crypto90.createHash)("sha256").update(material).digest("hex").slice(0, 12);
|
|
289141
289550
|
return `node-${digest}`;
|
|
289142
289551
|
}
|
|
289143
289552
|
|
|
@@ -291009,13 +291418,13 @@ function ownFlagsFromDecl(command2) {
|
|
|
291009
291418
|
}
|
|
291010
291419
|
|
|
291011
291420
|
// ../cli/src/connector-effect-runner.ts
|
|
291012
|
-
var
|
|
291421
|
+
var import_node_crypto91 = require("node:crypto");
|
|
291013
291422
|
var import_node_child_process24 = require("node:child_process");
|
|
291014
291423
|
init_src8();
|
|
291015
291424
|
function stableKey(effect) {
|
|
291016
291425
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
291017
291426
|
const canonical2 = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
|
|
291018
|
-
return `sha256:${(0,
|
|
291427
|
+
return `sha256:${(0, import_node_crypto91.createHash)("sha256").update(canonical2).digest("hex")}`;
|
|
291019
291428
|
}
|
|
291020
291429
|
async function runConnectorEffect(connector, toolArgs, deps) {
|
|
291021
291430
|
const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
|
|
@@ -291570,7 +291979,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
291570
291979
|
const timeoutMs = resolveAuthWaitMs();
|
|
291571
291980
|
const controller = new AbortController();
|
|
291572
291981
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
291573
|
-
const waiterId = (0,
|
|
291982
|
+
const waiterId = (0, import_node_crypto92.randomUUID)();
|
|
291574
291983
|
process.stderr.write(
|
|
291575
291984
|
`\u7B49\u5F85\u4EBA\u5DE5\u6388\u6743\u4E2D\u2026\u2026\u6700\u591A ${Math.round(timeoutMs / 1e3)} \u79D2\uFF0C\u8D85\u65F6\u4F1A\u81EA\u52A8\u8F6C\u4E3A\u5F85\u5BA1\uFF1B\u8FD9\u4E0D\u662F\u9519\u8BEF\uFF0C\u8BF7\u52FF\u91CD\u8BD5\u540C\u4E00\u6761\u547D\u4EE4\u3002
|
|
291576
291985
|
`
|
|
@@ -291654,7 +292063,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
291654
292063
|
}
|
|
291655
292064
|
}
|
|
291656
292065
|
}
|
|
291657
|
-
var CLI_VERSION = "2.2.
|
|
292066
|
+
var CLI_VERSION = "2.2.79" ? "2.2.79" : "dev";
|
|
291658
292067
|
function apiHeaders(token, company) {
|
|
291659
292068
|
const headers = {
|
|
291660
292069
|
authorization: `Bearer ${token}`,
|
|
@@ -292020,7 +292429,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
292020
292429
|
const store = createNodeTokenStore(path38.join(dir, "node-tokens.json"));
|
|
292021
292430
|
const sub = positional[0];
|
|
292022
292431
|
if (sub === "issue") {
|
|
292023
|
-
const id = flags.get("id") ?? `node-${(0,
|
|
292432
|
+
const id = flags.get("id") ?? `node-${(0, import_node_crypto92.randomUUID)()}`;
|
|
292024
292433
|
const token2 = store.issue(id);
|
|
292025
292434
|
println(token2);
|
|
292026
292435
|
process.stderr.write(
|
|
@@ -293159,7 +293568,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
293159
293568
|
if (!name) throw new Error("\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
293160
293569
|
const goal = flags.get("goal")?.trim();
|
|
293161
293570
|
const slug6 = flags.get("slug");
|
|
293162
|
-
const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0,
|
|
293571
|
+
const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0, import_node_crypto92.randomUUID)());
|
|
293163
293572
|
const result = await api.request("POST", "/api/projects", {
|
|
293164
293573
|
...id ? { id } : {},
|
|
293165
293574
|
name,
|
|
@@ -295424,13 +295833,13 @@ function runtimeAssetSourceRoots(input) {
|
|
|
295424
295833
|
}
|
|
295425
295834
|
|
|
295426
295835
|
// src/install.ts
|
|
295427
|
-
var
|
|
295836
|
+
var import_node_crypto93 = require("node:crypto");
|
|
295428
295837
|
var fs49 = __toESM(require("node:fs"));
|
|
295429
295838
|
var path44 = __toESM(require("node:path"));
|
|
295430
295839
|
function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
|
|
295431
295840
|
const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
|
|
295432
295841
|
if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
|
|
295433
|
-
const digest = (0,
|
|
295842
|
+
const digest = (0, import_node_crypto93.createHash)("sha256").update(fs49.readFileSync(sourceFile)).digest("hex").slice(0, 8);
|
|
295434
295843
|
return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
|
|
295435
295844
|
}
|
|
295436
295845
|
function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
@@ -295553,7 +295962,7 @@ function shimScript() {
|
|
|
295553
295962
|
}
|
|
295554
295963
|
|
|
295555
295964
|
// src/index.ts
|
|
295556
|
-
var PKG_VERSION = true ? "2.2.
|
|
295965
|
+
var PKG_VERSION = true ? "2.2.79" : "dev";
|
|
295557
295966
|
var LOCAL_BIN = localBin();
|
|
295558
295967
|
var NPM_PREFIX = npmPrefix();
|
|
295559
295968
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -295861,7 +296270,7 @@ function newInstanceName() {
|
|
|
295861
296270
|
const existing = new Set(listInstances());
|
|
295862
296271
|
if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
|
|
295863
296272
|
for (; ; ) {
|
|
295864
|
-
const n = `inst-${(0,
|
|
296273
|
+
const n = `inst-${(0, import_node_crypto94.randomBytes)(3).toString("hex")}`;
|
|
295865
296274
|
if (!existing.has(n)) return n;
|
|
295866
296275
|
}
|
|
295867
296276
|
}
|