oasis_test_v2 2.2.77 → 2.2.78

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.
Files changed (2) hide show
  1. package/dist/index.js +968 -707
  2. 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({
@@ -2277,6 +2284,7 @@ var init_src = __esm({
2277
2284
  init_annotation();
2278
2285
  init_collab_view();
2279
2286
  init_inbox_read();
2287
+ init_connector_auth_pending();
2280
2288
  init_notifications();
2281
2289
  init_workorder_quality();
2282
2290
  init_workorder_attachments();
@@ -2562,7 +2570,7 @@ var init_session_runtime_target = __esm({
2562
2570
  this.name = "SessionRuntimeOverrideError";
2563
2571
  }
2564
2572
  };
2565
- CLEAR_SESSION_RUNTIME_HINT = "\u5728\u8FD0\u884C\u65F6\u9009\u62E9\u91CC\u70B9\u300C\u6062\u590D\u4E3A\u5458\u5DE5\u9ED8\u8BA4\u8FD0\u884C\u914D\u7F6E\u300D\u5373\u53EF\u7EE7\u7EED\uFF08\u4F1A\u628A\u8FD9\u4F4D Agent \u6B64\u523B\u7684\u9ED8\u8BA4\u914D\u7F6E\u6284\u8FDB\u8FD9\u6761\u4F1A\u8BDD\uFF09\u3002";
2573
+ 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
2574
  }
2567
2575
  });
2568
2576
 
@@ -164597,7 +164605,7 @@ var init_initialize_workorder = __esm({
164597
164605
  function hasRejectionEvidence(reason) {
164598
164606
  return DEFINITELY_NOT_DELIVERED.has(reason ?? "");
164599
164607
  }
164600
- var DEFINITELY_NOT_DELIVERED, INSERT_UNCERTAIN_NOTE;
164608
+ var DEFINITELY_NOT_DELIVERED, INSERT_UNCERTAIN_NOTE, INSERT_RETURNED_NOTE;
164601
164609
  var init_chat_insert_evidence = __esm({
164602
164610
  "../server/src/chat-insert-evidence.ts"() {
164603
164611
  "use strict";
@@ -164611,6 +164619,7 @@ var init_chat_insert_evidence = __esm({
164611
164619
  "not-consumed"
164612
164620
  ]);
164613
164621
  INSERT_UNCERTAIN_NOTE = "\u8FD9\u6B21\u63D2\u5165\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF1A\u65E0\u6CD5\u786E\u8BA4 agent \u662F\u5426\u5DF2\u8BFB\u5230\u3002";
164622
+ 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
164623
  }
164615
164624
  });
164616
164625
 
@@ -165880,14 +165889,15 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
165880
165889
  if (!batch.length) {
165881
165890
  const state = submitted.state ?? "queued";
165882
165891
  const returned = state === "cancelled" && submitted.stateReason?.startsWith("client-retained:");
165892
+ const landed = state === "cancelled" && submitted.stateReason?.startsWith("client-gone:");
165883
165893
  const reason = state === "delivering" ? "in-flight" : returned ? submitted.stateReason.slice("client-retained:".length) : "unconfirmed";
165884
165894
  return {
165885
165895
  accepted: state === "delivered",
165886
165896
  ...state !== "delivered" ? { reason } : {},
165887
- queued: !returned,
165897
+ queued: !returned && !landed,
165888
165898
  delivered: "",
165889
165899
  batch: [submitted],
165890
- insertStatus: insertStatusOfRow(submitted)
165900
+ insertStatus: landed ? "uncertain" : insertStatusOfRow(submitted)
165891
165901
  };
165892
165902
  }
165893
165903
  const prepared = await buildChatAttachmentFiles(
@@ -165909,8 +165919,13 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
165909
165919
  const recordOutcome = async (res) => {
165910
165920
  const nextState = res.accepted ? "delivered" : hasRejectionEvidence(res.reason) ? "queued" : "unconfirmed";
165911
165921
  const stateReason = res.detail ? `${res.reason ?? (res.accepted ? "delivered" : "")}:${res.detail}` : res.reason;
165912
- const returnToClient = retainLocallyOnFailure && !!clientKey && nextState === "queued";
165913
- if (returnToClient && deps.store.markPendingMessages) {
165922
+ const wantsReturn = retainLocallyOnFailure && !!clientKey && nextState === "queued";
165923
+ const orphanedReturn = wantsReturn && deps.clientAttached?.() === false;
165924
+ const returnToClient = wantsReturn && !orphanedReturn;
165925
+ if (orphanedReturn && deps.store.markPendingMessages) {
165926
+ await deps.store.markPendingMessages(chatSessionId, [submitted.id], "cancelled", `client-gone:${res.reason}`);
165927
+ await deps.store.markPendingMessages(chatSessionId, ids2.filter((id) => id !== submitted.id), nextState, stateReason);
165928
+ } else if (returnToClient && deps.store.markPendingMessages) {
165914
165929
  await deps.store.markPendingMessages(chatSessionId, [submitted.id], "cancelled", `client-retained:${res.reason}`);
165915
165930
  await deps.store.markPendingMessages(chatSessionId, ids2.filter((id) => id !== submitted.id), nextState, stateReason);
165916
165931
  } else {
@@ -165920,7 +165935,15 @@ async function appendNowThroughQueue(chatSessionId, text7, deps, clientKey, atta
165920
165935
  if (returnToClient) await deps.store.removePendingMessage(chatSessionId, submitted.id);
165921
165936
  }
165922
165937
  const insertStatus = nextState === "delivered" ? "inserted" : nextState === "unconfirmed" ? "uncertain" : "not-inserted";
165923
- return { ...res, queued: !returnToClient, delivered: merged, batch, insertStatus, ...prepared.paths.length ? { attachmentPaths: prepared.paths } : {} };
165938
+ return {
165939
+ ...res,
165940
+ queued: !returnToClient && !orphanedReturn,
165941
+ delivered: merged,
165942
+ batch,
165943
+ insertStatus,
165944
+ ...orphanedReturn ? { orphanedReturn: true } : {},
165945
+ ...prepared.paths.length ? { attachmentPaths: prepared.paths } : {}
165946
+ };
165924
165947
  };
165925
165948
  let settle;
165926
165949
  const settled = new Promise((resolve12) => {
@@ -165954,82 +165977,6 @@ var init_append_now = __esm({
165954
165977
  }
165955
165978
  });
165956
165979
 
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
165980
  // ../server/src/domains/chat-sessions/append-progress.ts
166034
165981
  function wantsAppendProgress(req) {
166035
165982
  const accept = req.headers.accept;
@@ -169950,6 +169897,15 @@ async function probeChatSubmission(args) {
169950
169897
  }
169951
169898
  }
169952
169899
  const base = { persisted: message !== null, attempts: attempt };
169900
+ if (!lastTurn && chatStore?.getPendingMessage) {
169901
+ const insert = await read("message", () => chatStore.getPendingMessage(sid, insertRequestId(sid, csid)));
169902
+ if (insert?.clientKey === csid) {
169903
+ const landed = insert.state === "unconfirmed" || insert.state === "cancelled" && (insert.stateReason ?? "").startsWith("client-gone:");
169904
+ if (insert.state === "delivered") return { status: { state: "delivered", persisted: true, attempts: attempt, retryable: false }, nextAttempt: attempt, message, lastTurn };
169905
+ if (insert.state === "delivering") return { status: { state: "pending", ...base, retryable: false }, nextAttempt: attempt, message, lastTurn };
169906
+ if (landed) return { status: { state: "not_delivered", ...base, retryable: true }, nextAttempt: attempt, message, lastTurn };
169907
+ }
169908
+ }
169953
169909
  let status;
169954
169910
  if (!turns) {
169955
169911
  if (message && messageDelivered(message)) status = { state: "delivered", ...base, retryable: false };
@@ -170067,6 +170023,7 @@ var init_chat_submission = __esm({
170067
170023
  init_src();
170068
170024
  init_chat_turn_gate();
170069
170025
  init_stable_chat_dispatch_ids();
170026
+ init_append_now();
170070
170027
  MAX_SUBMIT_ATTEMPTS = 20;
170071
170028
  LEGACY_LOOKBACK_MESSAGES = 200;
170072
170029
  LEGACY_LATER_TURNS_LIMIT = 50;
@@ -170088,6 +170045,56 @@ var init_chat_submission = __esm({
170088
170045
  }
170089
170046
  });
170090
170047
 
170048
+ // ../server/src/domains/chat-sessions/insert-undelivered.ts
170049
+ async function landUndeliveredInsert(input) {
170050
+ const { store, itemStore, chatSessionId: sid, clientKey, text: text7, note } = input;
170051
+ const log3 = input.log ?? ((m2) => console.warn(m2));
170052
+ try {
170053
+ if (!itemStore || !chatItemsDoubleWriteEnabled()) return;
170054
+ const ledger = new ChatItemLedger({
170055
+ items: itemStore,
170056
+ versionSeed: await itemStore.sessionVersionCursor(sid).catch(() => 0),
170057
+ sessionId: sid,
170058
+ turnId: fallbackTurnId(),
170059
+ log: log3
170060
+ });
170061
+ const refs = input.attachments.map((a) => ({
170062
+ name: a.name,
170063
+ ...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
170064
+ ...a.contentType !== void 0 ? { contentType: a.contentType } : {}
170065
+ }));
170066
+ ledger.recordRejectedSubmission({
170067
+ user: { text: text7, clientSubmitId: clientKey, ...refs.length ? { attachments: refs } : {} },
170068
+ failure: { reason: note, retryable: true }
170069
+ });
170070
+ await ledger.drain();
170071
+ if (ledger.failures > 0) return;
170072
+ const now = (/* @__PURE__ */ new Date()).toISOString();
170073
+ await store.appendMessage({
170074
+ id: (0, import_node_crypto26.randomUUID)(),
170075
+ sessionId: sid,
170076
+ role: "user",
170077
+ content: text7,
170078
+ createdAt: now,
170079
+ messageKey: chatSubmitMessageKey(sid, clientKey),
170080
+ ...refs.length ? { attachments: refs } : {},
170081
+ needsAgentDelivery: true
170082
+ });
170083
+ await store.updateSession(sid, { touchedAt: now }).catch(() => void 0);
170084
+ } catch (err) {
170085
+ 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)}`);
170086
+ }
170087
+ }
170088
+ var import_node_crypto26;
170089
+ var init_insert_undelivered = __esm({
170090
+ "../server/src/domains/chat-sessions/insert-undelivered.ts"() {
170091
+ "use strict";
170092
+ import_node_crypto26 = require("node:crypto");
170093
+ init_src();
170094
+ init_chat_item_ledger();
170095
+ }
170096
+ });
170097
+
170091
170098
  // ../server/src/chat-workorder-files.ts
170092
170099
  function workOrderFileEditTarget(workOrderId, file) {
170093
170100
  if (!isEditableFileName(file.name)) return null;
@@ -170097,7 +170104,7 @@ function workOrderFileEditTarget(workOrderId, file) {
170097
170104
  return { kind: "work-order-file", workOrderId, fileId: file.fileId, name: file.name };
170098
170105
  }
170099
170106
  function workOrderFileId(workOrderId, blobId, name) {
170100
- return `wof:${(0, import_node_crypto26.createHash)("sha256").update(`${workOrderId}|${blobId}|${name}`).digest("hex").slice(0, 32)}`;
170107
+ return `wof:${(0, import_node_crypto27.createHash)("sha256").update(`${workOrderId}|${blobId}|${name}`).digest("hex").slice(0, 32)}`;
170101
170108
  }
170102
170109
  async function linkChatAttachmentsToWorkOrder(input) {
170103
170110
  const warnings = [];
@@ -170148,11 +170155,11 @@ async function linkChatAttachmentsToWorkOrder(input) {
170148
170155
  }
170149
170156
  return { linked, warnings };
170150
170157
  }
170151
- var import_node_crypto26;
170158
+ var import_node_crypto27;
170152
170159
  var init_chat_workorder_files = __esm({
170153
170160
  "../server/src/chat-workorder-files.ts"() {
170154
170161
  "use strict";
170155
- import_node_crypto26 = require("node:crypto");
170162
+ import_node_crypto27 = require("node:crypto");
170156
170163
  init_src();
170157
170164
  }
170158
170165
  });
@@ -170943,11 +170950,11 @@ var init_config_store = __esm({
170943
170950
  function clone2(value2) {
170944
170951
  return structuredClone(value2);
170945
170952
  }
170946
- var import_node_crypto27, import_promises3, import_node_path6, MemoryKnowledgeRunStore, FileKnowledgeRunStore;
170953
+ var import_node_crypto28, import_promises3, import_node_path6, MemoryKnowledgeRunStore, FileKnowledgeRunStore;
170947
170954
  var init_run_store = __esm({
170948
170955
  "../server/src/domains/knowledge/run-store.ts"() {
170949
170956
  "use strict";
170950
- import_node_crypto27 = require("node:crypto");
170957
+ import_node_crypto28 = require("node:crypto");
170951
170958
  import_promises3 = require("node:fs/promises");
170952
170959
  import_node_path6 = require("node:path");
170953
170960
  MemoryKnowledgeRunStore = class {
@@ -171064,7 +171071,7 @@ var init_run_store = __esm({
171064
171071
  }
171065
171072
  async persist(runs) {
171066
171073
  const shape = { version: 1, runs };
171067
- const temp = `${this.file}.${process.pid}.${(0, import_node_crypto27.randomUUID)()}.tmp`;
171074
+ const temp = `${this.file}.${process.pid}.${(0, import_node_crypto28.randomUUID)()}.tmp`;
171068
171075
  try {
171069
171076
  await (0, import_promises3.writeFile)(temp, `${JSON.stringify(shape, null, 2)}
171070
171077
  `, { mode: 384 });
@@ -171713,12 +171720,12 @@ function retryableKnowledgeRun(record9) {
171713
171720
  const latestAnswerAttempt = [...record9.attempts ?? []].reverse().find((attempt) => attempt.kind !== "fast");
171714
171721
  return record9.status === "succeeded" && record9.request.action === "ask" && record9.executionHealth === "degraded" && latestAnswerAttempt?.status === "failed";
171715
171722
  }
171716
- var import_node_crypto28, ACTION_LABEL, STATUS_MARKER, FINAL_ANSWER_MARKER, ACTIVE_STATUSES, RETRYABLE_STATUSES, HEARTBEAT_INTERVAL_MS, LEASE_MS, MAX_CONCURRENT_READS, ACTION_FLOW, KnowledgeService;
171723
+ 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
171724
  var init_service2 = __esm({
171718
171725
  "../server/src/domains/knowledge/service.ts"() {
171719
171726
  "use strict";
171720
171727
  init_file_limits2();
171721
- import_node_crypto28 = require("node:crypto");
171728
+ import_node_crypto29 = require("node:crypto");
171722
171729
  init_src7();
171723
171730
  init_config_store();
171724
171731
  init_run_store();
@@ -171761,7 +171768,7 @@ var init_service2 = __esm({
171761
171768
  constructor(options) {
171762
171769
  this.options = options;
171763
171770
  this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
171764
- this.id = options.id ?? import_node_crypto28.randomUUID;
171771
+ this.id = options.id ?? import_node_crypto29.randomUUID;
171765
171772
  this.runStore = options.runStore ?? new MemoryKnowledgeRunStore();
171766
171773
  this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? HEARTBEAT_INTERVAL_MS;
171767
171774
  this.leaseMs = options.leaseMs ?? LEASE_MS;
@@ -182712,7 +182719,7 @@ function stableJson2(value2) {
182712
182719
  return JSON.stringify(stableValue(value2));
182713
182720
  }
182714
182721
  function sha256(value2) {
182715
- return (0, import_node_crypto29.createHash)("sha256").update(value2).digest("hex");
182722
+ return (0, import_node_crypto30.createHash)("sha256").update(value2).digest("hex");
182716
182723
  }
182717
182724
  function normalizeKnowledgeContent(title, content3) {
182718
182725
  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 +182961,11 @@ function renderUntrustedKnowledgeFragment(input) {
182954
182961
  "</knowledge>"
182955
182962
  ].join("\n");
182956
182963
  }
182957
- var import_node_crypto29, KNOWLEDGE_NORMALIZER_VERSION, KNOWLEDGE_PACK_TEMPLATE_VERSION, PUBLISH_MARKER, STOPWORDS, LEXICAL_STOPWORDS, lexicalSegmenters, KNOWLEDGE_LEXICAL_INDEX_VERSION, KNOWLEDGE_MAINTENANCE_RELEVANCE_THRESHOLD, KNOWLEDGE_LAYOUT_TERMS;
182964
+ 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
182965
  var init_governance_content = __esm({
182959
182966
  "../server/src/domains/knowledge/governance-content.ts"() {
182960
182967
  "use strict";
182961
- import_node_crypto29 = require("node:crypto");
182968
+ import_node_crypto30 = require("node:crypto");
182962
182969
  init_mdast_util_from_markdown();
182963
182970
  init_mdast_util_gfm();
182964
182971
  init_micromark_extension_gfm();
@@ -193125,11 +193132,11 @@ function approvedSnapshotBody(title, content3) {
193125
193132
  function uniqueStrings(values) {
193126
193133
  return [...new Set(values)].sort();
193127
193134
  }
193128
- var import_node_crypto30, KnowledgeGovernanceError, put2, REMEDIATION_ACTION_BY_TASK, KnowledgeGovernanceService;
193135
+ var import_node_crypto31, KnowledgeGovernanceError, put2, REMEDIATION_ACTION_BY_TASK, KnowledgeGovernanceService;
193129
193136
  var init_governance_service = __esm({
193130
193137
  "../server/src/domains/knowledge/governance-service.ts"() {
193131
193138
  "use strict";
193132
- import_node_crypto30 = require("node:crypto");
193139
+ import_node_crypto31 = require("node:crypto");
193133
193140
  init_governance_content();
193134
193141
  init_knowledge_policy();
193135
193142
  init_network_maintenance();
@@ -193151,7 +193158,7 @@ var init_governance_service = __esm({
193151
193158
  constructor(options) {
193152
193159
  this.options = options;
193153
193160
  this.now = options.now ?? (() => /* @__PURE__ */ new Date());
193154
- this.id = options.id ?? ((prefix) => `${prefix}_${(0, import_node_crypto30.randomUUID)()}`);
193161
+ this.id = options.id ?? ((prefix) => `${prefix}_${(0, import_node_crypto31.randomUUID)()}`);
193155
193162
  this.versionViewBaseUrl = (options.versionViewBaseUrl ?? "/api/knowledge/items").replace(/\/$/u, "");
193156
193163
  this.projectProvisionRetryDelayMs = Math.max(0, options.projectProvisionRetryDelayMs ?? 6e4);
193157
193164
  this.projectProvisionMaxRetryDelayMs = Math.max(this.projectProvisionRetryDelayMs, options.projectProvisionMaxRetryDelayMs ?? 36e5);
@@ -198842,7 +198849,7 @@ function trustedKnowledgeInvocationId(body2, turn) {
198842
198849
  if (body2.action !== "ask") return void 0;
198843
198850
  const scope2 = turn?.artifactId ?? turn?.dispatchId;
198844
198851
  if (!scope2) return void 0;
198845
- const fingerprint2 = (0, import_node_crypto31.createHash)("sha256").update(JSON.stringify({
198852
+ const fingerprint2 = (0, import_node_crypto32.createHash)("sha256").update(JSON.stringify({
198846
198853
  action: body2.action,
198847
198854
  message: body2.message?.trim() ?? "",
198848
198855
  queryMode: body2.queryMode === "deep" ? "deep" : "fast",
@@ -198997,11 +199004,11 @@ function knowledgeRoutes(service, options = {}) {
198997
199004
  });
198998
199005
  };
198999
199006
  }
199000
- var import_node_crypto31, KNOWLEDGE_WORKORDER_ACTIONS;
199007
+ var import_node_crypto32, KNOWLEDGE_WORKORDER_ACTIONS;
199001
199008
  var init_routes = __esm({
199002
199009
  "../server/src/domains/knowledge/routes.ts"() {
199003
199010
  "use strict";
199004
- import_node_crypto31 = require("node:crypto");
199011
+ import_node_crypto32 = require("node:crypto");
199005
199012
  init_src7();
199006
199013
  init_router();
199007
199014
  init_governance_service();
@@ -200629,7 +200636,7 @@ async function resolveChatAttachmentDiscoverySource(input) {
200629
200636
  sourceType: input.sourceType,
200630
200637
  sourceId: session.id,
200631
200638
  sourceVersionId: attachment.blobRef,
200632
- sourceFingerprint: (0, import_node_crypto32.createHash)("sha256").update(bytes2).digest("hex"),
200639
+ sourceFingerprint: (0, import_node_crypto33.createHash)("sha256").update(bytes2).digest("hex"),
200633
200640
  sourceContent: new TextDecoder().decode(bytes2),
200634
200641
  sourceDisplayName: attachment.name,
200635
200642
  ...session.projectId ? { projectId: session.projectId } : {},
@@ -200640,11 +200647,11 @@ async function resolveChatAttachmentDiscoverySource(input) {
200640
200647
  }
200641
200648
  };
200642
200649
  }
200643
- var import_node_crypto32, TEXT_CONTENT_TYPES;
200650
+ var import_node_crypto33, TEXT_CONTENT_TYPES;
200644
200651
  var init_chat_attachment_discovery = __esm({
200645
200652
  "../server/src/domains/knowledge/chat-attachment-discovery.ts"() {
200646
200653
  "use strict";
200647
- import_node_crypto32 = require("node:crypto");
200654
+ import_node_crypto33 = require("node:crypto");
200648
200655
  TEXT_CONTENT_TYPES = /* @__PURE__ */ new Set([
200649
200656
  "application/json",
200650
200657
  "application/xml",
@@ -200820,8 +200827,8 @@ function aad(snapshot) {
200820
200827
  }
200821
200828
  function sealKnowledgeSnapshot(snapshot, key2) {
200822
200829
  if (snapshot.content.startsWith(PREFIX)) return structuredClone(snapshot);
200823
- const iv = (0, import_node_crypto33.randomBytes)(12);
200824
- const cipher = (0, import_node_crypto33.createCipheriv)("aes-256-gcm", keyBytes(key2), iv);
200830
+ const iv = (0, import_node_crypto34.randomBytes)(12);
200831
+ const cipher = (0, import_node_crypto34.createCipheriv)("aes-256-gcm", keyBytes(key2), iv);
200825
200832
  cipher.setAAD(aad(snapshot));
200826
200833
  const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
200827
200834
  return {
@@ -200834,7 +200841,7 @@ function openKnowledgeSnapshot(snapshot, key2) {
200834
200841
  const packed = snapshot.content.slice(PREFIX.length).split(".");
200835
200842
  if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
200836
200843
  const [iv, tag, data] = packed;
200837
- const decipher = (0, import_node_crypto33.createDecipheriv)("aes-256-gcm", keyBytes(key2), Buffer.from(iv, "base64url"));
200844
+ const decipher = (0, import_node_crypto34.createDecipheriv)("aes-256-gcm", keyBytes(key2), Buffer.from(iv, "base64url"));
200838
200845
  decipher.setAAD(aad(snapshot));
200839
200846
  decipher.setAuthTag(Buffer.from(tag, "base64url"));
200840
200847
  const content3 = Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8");
@@ -200843,11 +200850,11 @@ function openKnowledgeSnapshot(snapshot, key2) {
200843
200850
  function isSealedKnowledgeSnapshotContent(content3) {
200844
200851
  return content3.startsWith(PREFIX);
200845
200852
  }
200846
- var import_node_crypto33, PREFIX;
200853
+ var import_node_crypto34, PREFIX;
200847
200854
  var init_snapshot_crypto = __esm({
200848
200855
  "../server/src/domains/knowledge/snapshot-crypto.ts"() {
200849
200856
  "use strict";
200850
- import_node_crypto33 = require("node:crypto");
200857
+ import_node_crypto34 = require("node:crypto");
200851
200858
  PREFIX = "oasis-knowledge:v1:";
200852
200859
  }
200853
200860
  });
@@ -200930,11 +200937,11 @@ function uniquenessKeys(kind, record9) {
200930
200937
  return [];
200931
200938
  }
200932
200939
  }
200933
- var import_node_crypto34, import_promises4, import_node_path7, RECORD_KINDS, MemoryKnowledgeGovernanceStore, FileKnowledgeGovernanceStore;
200940
+ var import_node_crypto35, import_promises4, import_node_path7, RECORD_KINDS, MemoryKnowledgeGovernanceStore, FileKnowledgeGovernanceStore;
200934
200941
  var init_governance_store = __esm({
200935
200942
  "../server/src/domains/knowledge/governance-store.ts"() {
200936
200943
  "use strict";
200937
- import_node_crypto34 = require("node:crypto");
200944
+ import_node_crypto35 = require("node:crypto");
200938
200945
  import_promises4 = require("node:fs/promises");
200939
200946
  import_node_path7 = require("node:path");
200940
200947
  init_snapshot_crypto();
@@ -201152,7 +201159,7 @@ var init_governance_store = __esm({
201152
201159
  return result;
201153
201160
  }
201154
201161
  async persist(shape) {
201155
- const temp = `${this.file}.${process.pid}.${(0, import_node_crypto34.randomUUID)()}.tmp`;
201162
+ const temp = `${this.file}.${process.pid}.${(0, import_node_crypto35.randomUUID)()}.tmp`;
201156
201163
  try {
201157
201164
  await (0, import_promises4.writeFile)(temp, `${JSON.stringify(this.sealSnapshots(shape), null, 2)}
201158
201165
  `, { mode: 384 });
@@ -201188,7 +201195,7 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
201188
201195
  if (error2.code !== "ENOENT") throw error2;
201189
201196
  }
201190
201197
  await (0, import_promises5.mkdir)((0, import_node_path8.dirname)(file), { recursive: true });
201191
- const generated = `oasis-${(0, import_node_crypto35.randomUUID)()}`;
201198
+ const generated = `oasis-${(0, import_node_crypto36.randomUUID)()}`;
201192
201199
  try {
201193
201200
  await (0, import_promises5.writeFile)(file, `${generated}
201194
201201
  `, { encoding: "utf8", mode: 384, flag: "wx" });
@@ -201198,11 +201205,11 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
201198
201205
  return readDeploymentId(file);
201199
201206
  }
201200
201207
  }
201201
- var import_node_crypto35, import_promises5, import_node_path8, VALID_DEPLOYMENT_ID;
201208
+ var import_node_crypto36, import_promises5, import_node_path8, VALID_DEPLOYMENT_ID;
201202
201209
  var init_deployment_id = __esm({
201203
201210
  "../server/src/domains/knowledge/deployment-id.ts"() {
201204
201211
  "use strict";
201205
- import_node_crypto35 = require("node:crypto");
201212
+ import_node_crypto36 = require("node:crypto");
201206
201213
  import_promises5 = require("node:fs/promises");
201207
201214
  import_node_path8 = require("node:path");
201208
201215
  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 +202090,7 @@ function roundFailureText(kind, error2) {
202083
202090
  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
202091
  }
202085
202092
  function deterministicUuid2(seed) {
202086
- const h = (0, import_node_crypto36.createHash)("sha256").update(seed).digest();
202093
+ const h = (0, import_node_crypto37.createHash)("sha256").update(seed).digest();
202087
202094
  const b2 = Buffer.from(h.subarray(0, 16));
202088
202095
  b2[6] = b2[6] & 15 | 80;
202089
202096
  b2[8] = b2[8] & 63 | 128;
@@ -202138,11 +202145,11 @@ async function seedChildRoundRows(chatStore, childSessionId, round, prompt2, now
202138
202145
  createdAt: now
202139
202146
  });
202140
202147
  }
202141
- var import_node_crypto36, DelegationError, DIGEST_CHARS, PENDING_QUEUE_OWNER, DISPATCH_LEASE_MS, CONSECUTIVE_FAIL_LIMIT, roundTurnKey, roundTurnId, DelegationService;
202148
+ var import_node_crypto37, DelegationError, DIGEST_CHARS, PENDING_QUEUE_OWNER, DISPATCH_LEASE_MS, CONSECUTIVE_FAIL_LIMIT, roundTurnKey, roundTurnId, DelegationService;
202142
202149
  var init_service3 = __esm({
202143
202150
  "../server/src/domains/delegations/service.ts"() {
202144
202151
  "use strict";
202145
- import_node_crypto36 = require("node:crypto");
202152
+ import_node_crypto37 = require("node:crypto");
202146
202153
  init_src();
202147
202154
  init_chat_exit();
202148
202155
  init_parent_conversation();
@@ -203450,7 +203457,7 @@ var init_continue_outcome = __esm({
203450
203457
  function trustedDelegationInvocationId(body2, turn) {
203451
203458
  const scope2 = turn?.artifactId ?? turn?.dispatchId;
203452
203459
  if (!scope2) return void 0;
203453
- const fingerprint2 = (0, import_node_crypto37.createHash)("sha256").update(JSON.stringify({ to: body2.to?.trim() ?? "", task: body2.task ?? "", as: body2.as?.trim() ?? "", files: body2.files ?? [] })).digest("hex").slice(0, 20);
203460
+ 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
203461
  return `dispatch:${scope2}:delegation:${fingerprint2}`;
203455
203462
  }
203456
203463
  function callerOf(req, invocationId) {
@@ -203545,11 +203552,11 @@ function delegationRoutes(service) {
203545
203552
  });
203546
203553
  };
203547
203554
  }
203548
- var import_node_crypto37;
203555
+ var import_node_crypto38;
203549
203556
  var init_routes2 = __esm({
203550
203557
  "../server/src/domains/delegations/routes.ts"() {
203551
203558
  "use strict";
203552
- import_node_crypto37 = require("node:crypto");
203559
+ import_node_crypto38 = require("node:crypto");
203553
203560
  init_router();
203554
203561
  init_continue_outcome();
203555
203562
  init_service3();
@@ -204460,6 +204467,60 @@ var init_child_live_turn = __esm({
204460
204467
  }
204461
204468
  });
204462
204469
 
204470
+ // ../server/src/domains/actors/registry-audit-sink.ts
204471
+ function createRegistryAuditSink(file) {
204472
+ const listeners = /* @__PURE__ */ new Set();
204473
+ const notify = (msg) => {
204474
+ for (const listener of listeners) listener(msg);
204475
+ };
204476
+ return {
204477
+ /** 登记审计:落盘 + 推 registry 通知(前端据此重拉登记类投影)。 */
204478
+ registryAudit: (record9) => {
204479
+ fs20.appendFile(file, JSON.stringify(record9) + "\n", () => {
204480
+ });
204481
+ notify({ kind: record9.kind, actor: record9.actor, target: record9.target, timestamp: record9.timestamp });
204482
+ },
204483
+ /**
204484
+ * 凭据审计(ADR 凭据保险库 §4.7):与登记审计同落一份旁账,按 kind 前缀 `credential_` 区分。
204485
+ *
204486
+ * **只落盘、不推 registry 通知**(D-10 推送面)。registry 通知是实例级的,`/api/events` 原样转发给
204487
+ * 任何已认证的连接、不分组织;凭据事件推进去 = 别家组织开一条 SSE 就能实时看到「谁在读/改哪个变量」。
204488
+ * 仓内没有任何消费方订它(2.0 前端只订无内容的 runtime-status,而后者本来就不被凭据事件唤醒)。
204489
+ * 要看凭据审计走 `GET /api/variables/reveal-audit`(按请求方组织过滤)。将来若需要实时推送,
204490
+ * 得先让通知带组织、`/api/events` 按组织过滤(recvvzbhOGiS7l 的完整修复),再放回来。
204491
+ */
204492
+ credentialAudit: (record9) => {
204493
+ fs20.appendFile(file, JSON.stringify(record9) + "\n", () => {
204494
+ });
204495
+ },
204496
+ /** runtime 状态变了:只发无内容的失效提示(ADR 0576)。 */
204497
+ notifyRuntimeStatus: () => {
204498
+ notify({ kind: "runtime_status_changed", timestamp: (/* @__PURE__ */ new Date()).toISOString() });
204499
+ },
204500
+ /** 这些人的铃铛有新通知了:各发一条无内容的失效提示,前端据此重拉台账、弹页内提示。 */
204501
+ notifyNotificationsChanged: (recipients) => {
204502
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
204503
+ for (const target of new Set(recipients)) notify({ kind: NOTIFICATIONS_CHANGED, target, timestamp });
204504
+ },
204505
+ notifications: {
204506
+ subscribe(listener) {
204507
+ listeners.add(listener);
204508
+ return () => {
204509
+ listeners.delete(listener);
204510
+ };
204511
+ }
204512
+ }
204513
+ };
204514
+ }
204515
+ var fs20, NOTIFICATIONS_CHANGED;
204516
+ var init_registry_audit_sink = __esm({
204517
+ "../server/src/domains/actors/registry-audit-sink.ts"() {
204518
+ "use strict";
204519
+ fs20 = __toESM(require("node:fs"), 1);
204520
+ NOTIFICATIONS_CHANGED = "notifications_changed";
204521
+ }
204522
+ });
204523
+
204463
204524
  // ../connectors/src/_base/wrapper-assets.ts
204464
204525
  function isUsableWrapper(scriptPath) {
204465
204526
  if (!(0, import_node_fs7.existsSync)(scriptPath)) return false;
@@ -205588,7 +205649,7 @@ function createAppJwt(appId, privateKeyPem, nowMs) {
205588
205649
  exp: nowSec + JWT_TTL_SEC,
205589
205650
  iss: appId
205590
205651
  }));
205591
- const signer = (0, import_node_crypto38.createSign)("RSA-SHA256");
205652
+ const signer = (0, import_node_crypto39.createSign)("RSA-SHA256");
205592
205653
  signer.update(`${header}.${payload2}`);
205593
205654
  signer.end();
205594
205655
  try {
@@ -205751,11 +205812,11 @@ async function exchangeManifestCode(code2, deps = {}) {
205751
205812
  ...typeof body2["client_secret"] === "string" ? { clientSecret: body2["client_secret"] } : {}
205752
205813
  };
205753
205814
  }
205754
- var import_node_crypto38, GITHUB_API, JWT_TTL_SEC, JWT_IAT_SKEW_SEC, defaultDeps2;
205815
+ var import_node_crypto39, GITHUB_API, JWT_TTL_SEC, JWT_IAT_SKEW_SEC, defaultDeps2;
205755
205816
  var init_app_auth = __esm({
205756
205817
  "../connectors/src/github/app-auth.ts"() {
205757
205818
  "use strict";
205758
- import_node_crypto38 = require("node:crypto");
205819
+ import_node_crypto39 = require("node:crypto");
205759
205820
  GITHUB_API = "https://api.github.com";
205760
205821
  JWT_TTL_SEC = 9 * 60;
205761
205822
  JWT_IAT_SKEW_SEC = 60;
@@ -206680,11 +206741,11 @@ function extractOutlineKnowledgeCandidateDrafts(events) {
206680
206741
  }
206681
206742
  return [...drafts.values()];
206682
206743
  }
206683
- var import_node_crypto39, 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;
206744
+ 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
206745
  var init_knowledge_api = __esm({
206685
206746
  "../connectors/src/outline/knowledge-api.ts"() {
206686
206747
  "use strict";
206687
- import_node_crypto39 = require("node:crypto");
206748
+ import_node_crypto40 = require("node:crypto");
206688
206749
  REQUEST_TIMEOUT_MS = 2e4;
206689
206750
  WRITE_ENDPOINTS = /* @__PURE__ */ new Set(["collections.create", "documents.create", "documents.update", "documents.publish"]);
206690
206751
  DEFAULT_WRITE_INTERVAL_MS = process.env["NODE_ENV"] === "test" ? 0 : 250;
@@ -206711,7 +206772,7 @@ var init_knowledge_api = __esm({
206711
206772
  this.baseUrl = canonicalUrl(baseUrl);
206712
206773
  this.lastResponseBaseUrl = this.baseUrl;
206713
206774
  this.token = token;
206714
- this.coordinatorKey = `${this.baseUrl}:${(0, import_node_crypto39.createHash)("sha256").update(token).digest("hex")}`;
206775
+ this.coordinatorKey = `${this.baseUrl}:${(0, import_node_crypto40.createHash)("sha256").update(token).digest("hex")}`;
206715
206776
  this.writeIntervalMs = Math.max(0, options.writeIntervalMs ?? DEFAULT_WRITE_INTERVAL_MS);
206716
206777
  this.maxRateLimitRetries = Math.max(0, options.maxRateLimitRetries ?? DEFAULT_RATE_LIMIT_RETRIES);
206717
206778
  this.maxRateLimitDelayMs = Math.max(0, options.maxRateLimitDelayMs ?? DEFAULT_MAX_RATE_LIMIT_DELAY_MS);
@@ -208119,15 +208180,15 @@ function classifyOutlineGovernedMigrationDocument(document4) {
208119
208180
  if (path46.startsWith("wiki/sources/")) return { mapping: "formal", metadata: legacyMetadata(document4, "source_note"), reason: "legacy_source_note" };
208120
208181
  return { mapping: "excluded", reason: "legacy_unmapped_path" };
208121
208182
  }
208122
- var import_node_crypto40, value, text4, hash, REVISION_VISIBILITY_RETRY_DELAYS_MS, governedProvisionRuns, PUBLISH_MARKER2, PUBLISH_MARKER_PRESENT;
208183
+ var import_node_crypto41, value, text4, hash, REVISION_VISIBILITY_RETRY_DELAYS_MS, governedProvisionRuns, PUBLISH_MARKER2, PUBLISH_MARKER_PRESENT;
208123
208184
  var init_governed_knowledge = __esm({
208124
208185
  "../connectors/src/outline/governed-knowledge.ts"() {
208125
208186
  "use strict";
208126
- import_node_crypto40 = require("node:crypto");
208187
+ import_node_crypto41 = require("node:crypto");
208127
208188
  init_knowledge_api();
208128
208189
  value = (input) => input && typeof input === "object" && !Array.isArray(input) ? input : null;
208129
208190
  text4 = (input) => typeof input === "string" && input.trim() ? input.trim() : null;
208130
- hash = (input) => (0, import_node_crypto40.createHash)("sha256").update(input.normalize("NFC").replace(/\r\n?/gu, "\n")).digest("hex");
208191
+ hash = (input) => (0, import_node_crypto41.createHash)("sha256").update(input.normalize("NFC").replace(/\r\n?/gu, "\n")).digest("hex");
208131
208192
  REVISION_VISIBILITY_RETRY_DELAYS_MS = [0, 100, 250, 500, 1e3, 2e3];
208132
208193
  governedProvisionRuns = /* @__PURE__ */ new Map();
208133
208194
  PUBLISH_MARKER2 = /\n?<!--\s*oasis-publish:[\s\S]*?-->\n?/giu;
@@ -208385,7 +208446,9 @@ function buildAppManifest(args) {
208385
208446
  default_permissions: { ...GITHUB_APP_DEFAULT_PERMISSIONS },
208386
208447
  // 暂不订阅 webhook:本方案只需要主动调 API,开着反而多一份要维护的密钥与端点。
208387
208448
  hook_attributes: { url: `${base}/api/connectors/github/app/webhook`, active: false },
208388
- callback_urls: [`${base}/api/connectors/github/app/oauth-callback`]
208449
+ callback_urls: [`${base}/api/connectors/github/app/oauth-callback`],
208450
+ setup_url: `${base}${args.setupPath}`,
208451
+ setup_on_update: true
208389
208452
  };
208390
208453
  }
208391
208454
  function manifestFormAction(owner, state) {
@@ -208454,7 +208517,7 @@ function checkAppOwnership(conv, want) {
208454
208517
  }
208455
208518
  return null;
208456
208519
  }
208457
- var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, PendingAppCreations, REQUIRED_WRITE_PERMISSIONS, PERMISSION_RANK, FORBIDDEN_IMPORT_PERMISSION_KEYS;
208520
+ var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, REQUIRED_WRITE_PERMISSIONS, PERMISSION_RANK, FORBIDDEN_IMPORT_PERMISSION_KEYS;
208458
208521
  var init_app_manifest = __esm({
208459
208522
  "../connectors/src/github/app-manifest.ts"() {
208460
208523
  "use strict";
@@ -208487,31 +208550,6 @@ var init_app_manifest = __esm({
208487
208550
  { key: "issues", label: "Issue\uFF08\u8BFB\u5199\uFF09", desc: "\u521B\u5EFA\u4E0E\u8BC4\u8BBA Issue" }
208488
208551
  ];
208489
208552
  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
208553
  REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
208516
208554
  PERMISSION_RANK = { read: 1, write: 2, admin: 3 };
208517
208555
  FORBIDDEN_IMPORT_PERMISSION_KEYS = [
@@ -208995,6 +209033,16 @@ var init_src8 = __esm({
208995
209033
  function isBundleFrozen(err) {
208996
209034
  return typeof err === "object" && err !== null && err.code === "TENANT_BUNDLE_FROZEN";
208997
209035
  }
209036
+ async function lookupGithubAppPending(store, state) {
209037
+ 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";
209038
+ if (!store || !state) return { message: missing };
209039
+ const hit = await store.get(state, Date.now());
209040
+ if (hit.status === "expired") {
209041
+ 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" };
209042
+ }
209043
+ if (hit.status === "missing") return { message: missing };
209044
+ return { pending: hit.value.value, message: "" };
209045
+ }
208998
209046
  function resolveCallbackBase(supplied, requestHost) {
208999
209047
  if (!supplied || !supplied.trim()) {
209000
209048
  throw new Error("\u7F3A\u5C11 callbackBase\uFF1A\u524D\u7AEF\u9700\u62A5\u4E0A window.location.origin + API_BASE");
@@ -210769,7 +210817,7 @@ async function startOasisServer(opts) {
210769
210817
  }
210770
210818
  return void 0;
210771
210819
  }
210772
- const appendNowThroughQueue2 = async (sid, text7, clientKey, attachments, perCompanyStore, retainLocallyOnFailure = false, onAwaitingConsumption, resend = false, itemStore) => {
210820
+ const appendNowThroughQueue2 = async (sid, text7, clientKey, attachments, perCompanyStore, retainLocallyOnFailure = false, onAwaitingConsumption, resend = false, itemStore, clientAttached) => {
210773
210821
  if (perCompanyStore === null) {
210774
210822
  throw new Error(
210775
210823
  `appendNowThroughQueue: per-company chat store unresolved (sid=${sid})`
@@ -210802,52 +210850,22 @@ async function startOasisServer(opts) {
210802
210850
  }
210803
210851
  }
210804
210852
  throw new Error(`blob ${blobRef} \u4E24\u4E2A\u67DC\u91CC\u90FD\u6CA1\u6709`);
210805
- }
210853
+ },
210854
+ ...clientAttached ? { clientAttached } : {}
210806
210855
  }, clientKey, attachments, retainLocallyOnFailure, resend ? { resend: true } : void 0);
210807
- if (r.insertStatus === "uncertain" && clientKey) {
210856
+ if ((r.insertStatus === "uncertain" || r.orphanedReturn) && clientKey) {
210808
210857
  const shown = r.batch.map((m2) => m2.text).filter(Boolean).join("\n\n") || text7;
210809
- await landUndeliveredInsert(sid, clientKey, shown, attachments ?? [], store, itemStore);
210810
- }
210811
- return { accepted: r.accepted, ...r.reason ? { reason: r.reason } : {}, queued: r.queued, insertStatus: r.insertStatus };
210812
- };
210813
- const landUndeliveredInsert = async (sid, clientKey, text7, attachments, store, itemStore) => {
210814
- try {
210815
- if (!itemStore || !chatItemsDoubleWriteEnabled()) return;
210816
- const ledger = new ChatItemLedger({
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
210858
+ await landUndeliveredInsert({
210859
+ store,
210860
+ itemStore,
210861
+ chatSessionId: sid,
210862
+ clientKey,
210863
+ text: shown,
210864
+ attachments: attachments ?? [],
210865
+ note: r.orphanedReturn ? INSERT_RETURNED_NOTE : INSERT_UNCERTAIN_NOTE
210846
210866
  });
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
210867
  }
210868
+ return { accepted: r.accepted, ...r.reason ? { reason: r.reason } : {}, queued: r.queued, insertStatus: r.insertStatus };
210851
210869
  };
210852
210870
  const GRAPH_EDIT_SUMMARY_MAX = 60;
210853
210871
  const truncateSummary = (s2) => {
@@ -211109,10 +211127,10 @@ async function startOasisServer(opts) {
211109
211127
  ...fp(p2)
211110
211128
  }))
211111
211129
  ] : [];
211112
- const { randomUUID: randomUUID47 } = await import("node:crypto");
211130
+ const { randomUUID: randomUUID48 } = await import("node:crypto");
211113
211131
  try {
211114
211132
  await store.enqueuePendingMessage({
211115
- id: randomUUID47(),
211133
+ id: randomUUID48(),
211116
211134
  chatSessionId: input.chatSessionId,
211117
211135
  text: input.text,
211118
211136
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -211145,11 +211163,11 @@ async function startOasisServer(opts) {
211145
211163
  ...f2?.mtime ? { srcMtime: f2.mtime } : {}
211146
211164
  };
211147
211165
  });
211148
- const { randomUUID: randomUUID47 } = await import("node:crypto");
211166
+ const { randomUUID: randomUUID48 } = await import("node:crypto");
211149
211167
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
211150
211168
  try {
211151
211169
  await store.enqueuePendingMessage({
211152
- id: randomUUID47(),
211170
+ id: randomUUID48(),
211153
211171
  chatSessionId: input.chatSessionId,
211154
211172
  text: "",
211155
211173
  createdAt: nowIso,
@@ -211559,7 +211577,7 @@ async function startOasisServer(opts) {
211559
211577
  return;
211560
211578
  }
211561
211579
  if (url.pathname.startsWith("/api/files/")) {
211562
- const company = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname) : void 0;
211580
+ const company = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname, req.method) : void 0;
211563
211581
  if (company?.kind === "ambiguous") {
211564
211582
  writeApiError(res, companyAmbiguousError(actor, company.companies));
211565
211583
  return;
@@ -211596,7 +211614,7 @@ async function startOasisServer(opts) {
211596
211614
  return;
211597
211615
  }
211598
211616
  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;
211617
+ const companyCtx = opts.resolveCompanyContext ? await opts.resolveCompanyContext(actor, req.headers, url.pathname, req.method) : void 0;
211600
211618
  const currentCompanyId = companyCtx?.kind === "ok" ? companyCtx.companyId : void 0;
211601
211619
  const fileLimits = await opts.fileLimits?.get(currentCompanyId) ?? { ...DEFAULT_FILE_LIMITS };
211602
211620
  const requestMaxBytes = fileUploadRequestMaxBytes(fileLimits);
@@ -212451,7 +212469,7 @@ async function startOasisServer(opts) {
212451
212469
  entry = {
212452
212470
  // 旧 CLI 未带 waiterId 时给它塞一个服务端本地生成的——它绝不可能出现在 leave 上,
212453
212471
  // 也就绝不会误命中 leftWaiterIds、绝不会被别人的 leave 摘掉。行为与旧 CLI 相同。
212454
- waiterId: clientWaiterId ?? `server:${(0, import_node_crypto41.randomUUID)()}`,
212472
+ waiterId: clientWaiterId ?? `server:${(0, import_node_crypto42.randomUUID)()}`,
212455
212473
  onResolve,
212456
212474
  expiresAt: expiresAt2,
212457
212475
  cleanup: () => clearTimeout(expiryTimer),
@@ -212532,7 +212550,7 @@ async function startOasisServer(opts) {
212532
212550
  const openRoom = async () => {
212533
212551
  let chatSessionId2;
212534
212552
  if (chatStore) {
212535
- const { randomUUID: randomUUID47 } = await import("node:crypto");
212553
+ const { randomUUID: randomUUID48 } = await import("node:crypto");
212536
212554
  const known = discussSessions.get(itemKey);
212537
212555
  const knownSession = known ? await chatStore.getSession(known) : null;
212538
212556
  if (knownSession && knownSession.workspace === ctx.workspace && knownSession.humanActorId === ctx.ownerId && (!body2.escalationId || knownSession.escalationId === body2.escalationId)) chatSessionId2 = known;
@@ -212541,7 +212559,7 @@ async function startOasisServer(opts) {
212541
212559
  chatSessionId2 = existing[0]?.id;
212542
212560
  }
212543
212561
  if (!chatSessionId2) {
212544
- chatSessionId2 = randomUUID47();
212562
+ chatSessionId2 = randomUUID48();
212545
212563
  const now = (/* @__PURE__ */ new Date()).toISOString();
212546
212564
  const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
212547
212565
  const reg0 = (await resolveEngine(currentCompanyId).catch(() => null))?.registry ?? opts.registry;
@@ -212796,6 +212814,19 @@ async function startOasisServer(opts) {
212796
212814
  changed();
212797
212815
  return;
212798
212816
  }
212817
+ if (topics?.size === 1 && topics.has("notifications")) {
212818
+ const changed = () => res.write('data: {"channel":"notifications"}\n\n');
212819
+ const unsubscribe = opts.notifications?.subscribe((n) => {
212820
+ if (n.kind === NOTIFICATIONS_CHANGED && n.target === actor) changed();
212821
+ });
212822
+ const heartbeat = setInterval(() => res.write(":heartbeat\n\n"), 15e3);
212823
+ req.on("close", () => {
212824
+ clearInterval(heartbeat);
212825
+ unsubscribe?.();
212826
+ });
212827
+ changed();
212828
+ return;
212829
+ }
212799
212830
  const wantRegistry = topics === null || topics.has("registry");
212800
212831
  const wsAllowed = (ws) => topics === null || ws !== void 0 && topics.has(ws);
212801
212832
  let closed = false;
@@ -212804,9 +212835,10 @@ async function startOasisServer(opts) {
212804
212835
 
212805
212836
  `);
212806
212837
  };
212807
- const unsubNotify = wantRegistry ? opts.notifications?.subscribe(
212808
- (n) => send({ channel: "registry", kind: n.kind, actor: n.actor, target: n.target, timestamp: n.timestamp })
212809
- ) : void 0;
212838
+ const unsubNotify = wantRegistry ? opts.notifications?.subscribe((n) => {
212839
+ if (n.kind === NOTIFICATIONS_CHANGED) return;
212840
+ send({ channel: "registry", kind: n.kind, actor: n.actor, target: n.target, timestamp: n.timestamp });
212841
+ }) : void 0;
212810
212842
  if (engineEvents) {
212811
212843
  let lastSeq = 0;
212812
212844
  const unsub = engineEvents((records) => {
@@ -213245,31 +213277,11 @@ async function startOasisServer(opts) {
213245
213277
  timeoutMs: APPEND_TURN_START_WAIT_MS
213246
213278
  });
213247
213279
  const appendItemStore = opts.resolveChatItems ? await opts.resolveChatItems(currentCompanyId).catch(() => void 0) : opts.chatItems;
213248
- await respondAppend(res, wantsAppendProgress(req), (onAwaitingConsumption) => appendNowThroughQueue2(sid, text7, clientKey, insertAttachments, perCompanyStore, retainLocallyOnFailure, onAwaitingConsumption, resend, appendItemStore));
213249
- return;
213250
- }
213251
- if (req.method === "GET" && /^\/api\/chat-sessions\/[^/]+\/insert-status$/.test(url.pathname)) {
213252
- const sid = decodeURIComponent(url.pathname.split("/")[3] ?? "");
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 }));
213280
+ let clientGone = false;
213281
+ res.once("close", () => {
213282
+ if (!res.writableEnded) clientGone = true;
213283
+ });
213284
+ await respondAppend(res, wantsAppendProgress(req), (onAwaitingConsumption) => appendNowThroughQueue2(sid, text7, clientKey, insertAttachments, perCompanyStore, retainLocallyOnFailure, onAwaitingConsumption, resend, appendItemStore, () => !clientGone));
213273
213285
  return;
213274
213286
  }
213275
213287
  if (url.pathname === "/api/chat" && req.method === "POST") {
@@ -213653,7 +213665,7 @@ ${composed}`;
213653
213665
  if (rejectedLedger.failures === 0 && retriedRow) {
213654
213666
  turnPersisted = true;
213655
213667
  } else if (rejectedLedger.failures === 0) {
213656
- const { randomUUID: randomUUID48 } = await import("node:crypto");
213668
+ const { randomUUID: randomUUID49 } = await import("node:crypto");
213657
213669
  const now = (/* @__PURE__ */ new Date()).toISOString();
213658
213670
  const rejectedAttachments = effectiveAttachments.map((a) => ({
213659
213671
  name: a.name,
@@ -213661,7 +213673,7 @@ ${composed}`;
213661
213673
  ...a.contentType !== void 0 ? { contentType: a.contentType } : {}
213662
213674
  }));
213663
213675
  await chatStore.appendMessage({
213664
- id: randomUUID48(),
213676
+ id: randomUUID49(),
213665
213677
  sessionId: persistTarget.id,
213666
213678
  role: "user",
213667
213679
  content: persistedUserMessage,
@@ -213746,14 +213758,14 @@ ${composed}`;
213746
213758
  runtimeSessionId: session.nativeSessionId ?? session.id
213747
213759
  }).catch(() => void 0);
213748
213760
  }
213749
- const { randomUUID: randomUUID48 } = await import("node:crypto");
213761
+ const { randomUUID: randomUUID49 } = await import("node:crypto");
213750
213762
  const persistAttachments = effectiveAttachments.map((a) => ({
213751
213763
  name: a.name,
213752
213764
  ...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
213753
213765
  ...a.contentType !== void 0 ? { contentType: a.contentType } : {}
213754
213766
  }));
213755
213767
  if (!retriedRow) await chatStore.appendMessage({
213756
- id: randomUUID48(),
213768
+ id: randomUUID49(),
213757
213769
  sessionId: persistTarget.id,
213758
213770
  role: "user",
213759
213771
  content: persistedUserMessage,
@@ -214202,8 +214214,8 @@ ${composed}`;
214202
214214
  }
214203
214215
  }
214204
214216
  const { spawn: spawn11 } = await import("node:child_process");
214205
- const { randomUUID: randomUUID47 } = await import("node:crypto");
214206
- const sessionId = body2.sessionId ?? randomUUID47();
214217
+ const { randomUUID: randomUUID48 } = await import("node:crypto");
214218
+ const sessionId = body2.sessionId ?? randomUUID48();
214207
214219
  const args = [
214208
214220
  "-p",
214209
214221
  body2.message,
@@ -214292,33 +214304,32 @@ ${composed}`;
214292
214304
  }
214293
214305
  const svc = await connectorActorsService();
214294
214306
  if (!svc) throw new Error("actors service unavailable");
214295
- const cacheKey = `${currentCompanyId ?? ""}::${actorId}::${connectorId}`;
214307
+ const snapshots2 = opts.connectorAuthPending?.snapshots;
214308
+ if (!snapshots2) throw new Error("connector auth snapshot store unavailable");
214309
+ const snapKey = { companyId: currentCompanyId ?? "", actorId, connectorId };
214296
214310
  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
214311
  if (op === "begin") {
214301
214312
  const rows = await svc.snapshotActorConnectorVars(actorId, connectorId);
214302
- connectorAuthSnapshots.set(cacheKey, { rows, at: now });
214313
+ await snapshots2.put(snapKey, rows, now, now + CONNECTOR_AUTH_SNAPSHOT_TTL_MS);
214303
214314
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true, snapshot: rows.length }));
214304
214315
  return;
214305
214316
  }
214306
214317
  if (op === "commit") {
214307
- connectorAuthSnapshots.delete(cacheKey);
214318
+ await snapshots2.delete(snapKey);
214308
214319
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true }));
214309
214320
  return;
214310
214321
  }
214311
- const snap = connectorAuthSnapshots.get(cacheKey);
214312
- if (!snap) {
214322
+ const snapRows = await snapshots2.get(snapKey, now);
214323
+ if (!snapRows) {
214313
214324
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: false, reason: "no_snapshot" }));
214314
214325
  return;
214315
214326
  }
214316
214327
  const out = await svc.restoreActorConnectorVars(
214317
214328
  actorId,
214318
214329
  connectorId,
214319
- snap.rows
214330
+ snapRows
214320
214331
  );
214321
- connectorAuthSnapshots.delete(cacheKey);
214332
+ await snapshots2.delete(snapKey);
214322
214333
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ ok: true, ...out }));
214323
214334
  } catch (e) {
214324
214335
  res.writeHead(500).end(JSON.stringify({ error: String(e) }));
@@ -214499,24 +214510,35 @@ ${composed}`;
214499
214510
  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
214511
  return;
214501
214512
  }
214502
- const { randomUUID: randomUUID47 } = await import("node:crypto");
214503
- const state = randomUUID47();
214513
+ const { randomUUID: randomUUID48 } = await import("node:crypto");
214514
+ const state = randomUUID48();
214504
214515
  const nameSlug = (actorName || actorId?.split(":").pop() || owner?.login || "bot").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "bot";
214505
214516
  const manifest = buildAppManifest({
214506
214517
  employeeSlug: nameSlug,
214507
214518
  namePrefix: "oasis",
214508
214519
  baseUrl: base,
214509
- redirectPath: "/api/connectors/github/app/manifest-callback"
214520
+ redirectPath: "/api/connectors/github/app/manifest-callback",
214521
+ setupPath: "/api/connectors/github/app/setup-callback"
214510
214522
  });
214511
- githubAppPending.put(state, {
214523
+ const pendingStore = opts.connectorAuthPending?.githubApp;
214524
+ if (!pendingStore) throw new Error("github app pending store unavailable");
214525
+ const createdAtMs = Date.now();
214526
+ const entry = {
214512
214527
  ...actorId ? { actorId } : {},
214513
214528
  // 回调那一步没有鉴权头,解析不出公司——只能在这里记下来带过去。
214514
214529
  ...currentCompanyId ? { companyId: currentCompanyId } : {},
214515
214530
  employeeSlug: nameSlug,
214516
- createdAtMs: Date.now(),
214531
+ createdAtMs,
214517
214532
  // 存下这次选的归属——回调时要拿它跟 GitHub 返回的 owner 比对。
214518
214533
  wantOwnerKind: kind,
214519
214534
  ...kind === "org" && owner?.login ? { wantOwnerLogin: owner.login } : {}
214535
+ };
214536
+ await pendingStore.put({
214537
+ state,
214538
+ ...currentCompanyId ? { companyId: currentCompanyId } : {},
214539
+ value: { ...entry },
214540
+ createdAtMs,
214541
+ expiresAtMs: createdAtMs + PENDING_TTL_MS
214520
214542
  });
214521
214543
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
214522
214544
  state,
@@ -214831,16 +214853,22 @@ ${composed}`;
214831
214853
  if (url.pathname === "/api/connectors/github/app/manifest-callback" && req.method === "GET") {
214832
214854
  const code2 = url.searchParams.get("code") ?? "";
214833
214855
  const state = url.searchParams.get("state") ?? "";
214834
- const pending = githubAppPending.get(state, Date.now());
214835
- const fail = (msg) => {
214836
- if (pending) {
214837
- pending.done = true;
214838
- pending.error = msg;
214856
+ const pendingStore = opts.connectorAuthPending?.githubApp;
214857
+ const found2 = await lookupGithubAppPending(pendingStore, state);
214858
+ const pending = found2.pending;
214859
+ const fail = async (msg) => {
214860
+ if (pending && pendingStore) {
214861
+ await pendingStore.patch(state, { done: true, error: msg }).catch(() => {
214862
+ });
214839
214863
  }
214840
214864
  res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(callbackHtml(false, msg));
214841
214865
  };
214842
- if (!code2 || !pending) {
214843
- fail("state \u5DF2\u8FC7\u671F\u6216\u65E0\u6548\uFF0C\u8BF7\u56DE\u5230\u63A7\u5236\u53F0\u91CD\u8BD5");
214866
+ if (!pending) {
214867
+ await fail(found2.message);
214868
+ return;
214869
+ }
214870
+ if (!code2) {
214871
+ 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
214872
  return;
214845
214873
  }
214846
214874
  try {
@@ -214850,7 +214878,7 @@ ${composed}`;
214850
214878
  ...pending.wantOwnerKind ? { ownerKind: pending.wantOwnerKind } : {}
214851
214879
  });
214852
214880
  if (problem) {
214853
- fail(problem.message);
214881
+ await fail(problem.message);
214854
214882
  return;
214855
214883
  }
214856
214884
  const svc = await connectorActorsService(pending.companyId);
@@ -214862,29 +214890,77 @@ ${composed}`;
214862
214890
  if (conv.slug) await put3("GITHUB_APP_SLUG", conv.slug, false);
214863
214891
  if (conv.clientId) await put3("GITHUB_APP_CLIENT_ID", conv.clientId, false);
214864
214892
  if (conv.clientSecret) await put3("GITHUB_APP_CLIENT_SECRET", conv.clientSecret, true);
214865
- pending.appId = conv.appId;
214866
- pending.privateKeyPem = conv.privateKeyPem;
214867
- if (conv.slug) pending.slug = conv.slug;
214868
- pending.ownerLogin = conv.ownerLogin;
214869
- pending.ownerType = conv.ownerType;
214870
- pending.permissions = conv.permissions;
214871
- pending.account = conv.slug ? `${conv.slug}[bot]` : conv.appId;
214893
+ const progress = {
214894
+ appId: conv.appId,
214895
+ ...conv.slug ? { slug: conv.slug } : {},
214896
+ // 收尾那一屏要用:这个 bot 到手的是哪些权限、归属是谁(拼权限设置页地址要 ownerType)。
214897
+ ownerLogin: conv.ownerLogin,
214898
+ ownerType: conv.ownerType,
214899
+ permissions: conv.permissions,
214900
+ account: conv.slug ? `${conv.slug}[bot]` : conv.appId
214901
+ };
214902
+ await pendingStore.patch(state, progress);
214872
214903
  if (!conv.slug) {
214873
214904
  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
214905
  return;
214875
214906
  }
214876
214907
  res.writeHead(302, { location: appInstallUrl(conv.slug, state) }).end();
214877
214908
  } catch (e) {
214878
- fail(String(e));
214909
+ await fail(String(e));
214879
214910
  }
214880
214911
  return;
214881
214912
  }
214913
+ const finishGithubAppInstall = async (state, pending, pendingStore) => {
214914
+ if (pending.done && pending.error) return { ok: false, error: pending.error };
214915
+ if (pending.done) return { ok: true, ...pending.account ? { account: pending.account } : {} };
214916
+ if (!pending.appId) return { ok: false, error: "pending" };
214917
+ try {
214918
+ const keySvc = await connectorActorsService(pending.companyId);
214919
+ if (!keySvc) throw new Error("actors service unavailable");
214920
+ const privateKeyPem = await keySvc.revealVariable("GITHUB_APP_PRIVATE_KEY", pending.actorId);
214921
+ 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");
214922
+ const installs = await listAppInstallations({
214923
+ appId: pending.appId,
214924
+ privateKeyPem
214925
+ });
214926
+ const first = installs[0];
214927
+ if (!first) return { ok: false, error: "pending" };
214928
+ const svc = await connectorActorsService(pending.companyId);
214929
+ if (!svc) throw new Error("actors service unavailable");
214930
+ const scope2 = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
214931
+ const put3 = (key2, value2, encrypted) => svc.putVariable({ key: key2, value: value2, ...scope2, connectorId: "github", encrypted });
214932
+ await put3("GITHUB_APP_INSTALLATION_ID", first.installationId, false);
214933
+ const minted = await mintInstallationToken({
214934
+ appId: pending.appId,
214935
+ privateKeyPem,
214936
+ installationId: first.installationId
214937
+ });
214938
+ if (pending.actorId) {
214939
+ await put3("GITHUB_APP_TOKEN", minted.token, true);
214940
+ await put3("GITHUB_APP_TOKEN_EXPIRES_AT", String(minted.expiresAtMs), false);
214941
+ }
214942
+ if (pending.slug) {
214943
+ const bot = await fetchAppBotIdentity(pending.slug, { token: minted.token });
214944
+ await put3("GITHUB_APP_BOT_EMAIL", bot?.email ?? "", false);
214945
+ await put3("GITHUB_APP_BOT_NAME", bot?.login ?? `${pending.slug}[bot]`, false);
214946
+ }
214947
+ await pendingStore.patch(state, { done: true });
214948
+ return { ok: true, account: pending.account ?? first.account };
214949
+ } catch (e) {
214950
+ const error2 = String(e);
214951
+ await pendingStore.patch(state, { error: error2 }).catch(() => {
214952
+ });
214953
+ return { ok: false, error: error2 };
214954
+ }
214955
+ };
214882
214956
  if (url.pathname === "/api/connectors/github/app/status" && req.method === "POST") {
214883
- const { state } = JSON.parse(rawBody || "{}");
214884
- const pending = state ? githubAppPending.get(state, Date.now()) : void 0;
214957
+ const { state = "" } = JSON.parse(rawBody || "{}");
214958
+ const pendingStore = opts.connectorAuthPending?.githubApp;
214959
+ const found2 = await lookupGithubAppPending(pendingStore, state);
214960
+ const pending = found2.pending;
214885
214961
  const reply = (body2) => res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify(body2));
214886
- if (!pending) {
214887
- reply({ ok: false, error: "expired" });
214962
+ if (!pending || !pendingStore) {
214963
+ reply({ ok: false, error: found2.message });
214888
214964
  return;
214889
214965
  }
214890
214966
  if (pending.error) {
@@ -214909,46 +214985,28 @@ ${composed}`;
214909
214985
  reply({ ok: true, account: pending.account, ...permissionView() });
214910
214986
  return;
214911
214987
  }
214912
- if (!pending.appId || !pending.privateKeyPem) {
214913
- reply({ ok: false, error: "pending" });
214988
+ const result = await finishGithubAppInstall(state, pending, pendingStore);
214989
+ if (result.ok) reply({ ok: true, account: result.account ?? pending.account, ...permissionView() });
214990
+ else reply({ ok: false, error: result.error });
214991
+ return;
214992
+ }
214993
+ if (url.pathname === "/api/connectors/github/app/setup-callback" && req.method === "GET") {
214994
+ const state = url.searchParams.get("state") ?? "";
214995
+ const html = (ok3, msg) => res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(callbackHtml(ok3, msg));
214996
+ const pendingStore = opts.connectorAuthPending?.githubApp;
214997
+ const found2 = await lookupGithubAppPending(pendingStore, state);
214998
+ if (!found2.pending || !pendingStore) {
214999
+ 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
215000
  return;
214915
215001
  }
214916
- try {
214917
- const installs = await listAppInstallations({
214918
- appId: pending.appId,
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 });
215002
+ if (url.searchParams.get("setup_action") === "request") {
215003
+ 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");
215004
+ return;
214951
215005
  }
215006
+ const result = await finishGithubAppInstall(state, found2.pending, pendingStore);
215007
+ if (result.ok) html(true, `\u5DF2\u8FDE\u63A5\u4E3A ${result.account ?? found2.pending.account ?? "GitHub App"}`);
215008
+ 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");
215009
+ else html(false, result.error);
214952
215010
  return;
214953
215011
  }
214954
215012
  if (url.pathname === "/api/connectors/feishu/login/start" && req.method === "POST") {
@@ -215325,14 +215383,14 @@ async function markDeliveredWithRetry(store, messageId, attempts = 3) {
215325
215383
  }
215326
215384
  return false;
215327
215385
  }
215328
- var http, import_node_crypto41, githubAppPending, connectorAuthSnapshots, 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;
215386
+ 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
215387
  var init_server3 = __esm({
215330
215388
  "../server/src/server.ts"() {
215331
215389
  "use strict";
215332
215390
  init_src();
215333
215391
  init_file_limits2();
215334
215392
  http = __toESM(require("node:http"), 1);
215335
- import_node_crypto41 = require("node:crypto");
215393
+ import_node_crypto42 = require("node:crypto");
215336
215394
  init_chat_session();
215337
215395
  init_chat_system_message();
215338
215396
  init_sealed_node_receipt();
@@ -215364,7 +215422,6 @@ var init_server3 = __esm({
215364
215422
  init_live_chat();
215365
215423
  init_chat_turn_wait();
215366
215424
  init_append_now();
215367
- init_insert_status();
215368
215425
  init_append_progress();
215369
215426
  init_workorder_drafts();
215370
215427
  init_draft_edit();
@@ -215385,6 +215442,7 @@ var init_server3 = __esm({
215385
215442
  init_chat_turn_gate();
215386
215443
  init_chat_submission();
215387
215444
  init_chat_insert_evidence();
215445
+ init_insert_undelivered();
215388
215446
  init_chat_workorder_files();
215389
215447
  init_chat_item_ledger();
215390
215448
  init_chat_cancel_attribution();
@@ -215396,10 +215454,9 @@ var init_server3 = __esm({
215396
215454
  init_knowledge2();
215397
215455
  init_assembly();
215398
215456
  init_child_live_turn();
215457
+ init_registry_audit_sink();
215399
215458
  init_src8();
215400
215459
  init_continuation3();
215401
- githubAppPending = new PendingAppCreations();
215402
- connectorAuthSnapshots = /* @__PURE__ */ new Map();
215403
215460
  CONNECTOR_AUTH_SNAPSHOT_TTL_MS = 30 * 60 * 1e3;
215404
215461
  defaultResolveActor = (token) => token.startsWith("token:") ? token.slice("token:".length) : null;
215405
215462
  enc = (s2) => new TextEncoder().encode(s2);
@@ -215495,25 +215552,25 @@ function createTokenIssuer(opts = {}) {
215495
215552
  function createNodeTokenStore(file) {
215496
215553
  const read3 = () => {
215497
215554
  try {
215498
- return JSON.parse(fs20.readFileSync(file, "utf8"));
215555
+ return JSON.parse(fs21.readFileSync(file, "utf8"));
215499
215556
  } catch {
215500
215557
  return {};
215501
215558
  }
215502
215559
  };
215503
- const write = (table) => fs20.writeFileSync(file, JSON.stringify(table, null, 2), { mode: 384 });
215560
+ const write = (table) => fs21.writeFileSync(file, JSON.stringify(table, null, 2), { mode: 384 });
215504
215561
  const revokedFile = file.replace(/(\.json)?$/, "-revoked.json");
215505
215562
  const readRevoked = () => {
215506
215563
  try {
215507
- return JSON.parse(fs20.readFileSync(revokedFile, "utf8"));
215564
+ return JSON.parse(fs21.readFileSync(revokedFile, "utf8"));
215508
215565
  } catch {
215509
215566
  return {};
215510
215567
  }
215511
215568
  };
215512
- const writeRevoked = (table) => fs20.writeFileSync(revokedFile, JSON.stringify(table, null, 2), { mode: 384 });
215569
+ const writeRevoked = (table) => fs21.writeFileSync(revokedFile, JSON.stringify(table, null, 2), { mode: 384 });
215513
215570
  return {
215514
215571
  issue(nodeId) {
215515
215572
  const table = read3();
215516
- const token = `ont_${(0, import_node_crypto42.randomBytes)(24).toString("base64url")}`;
215573
+ const token = `ont_${(0, import_node_crypto43.randomBytes)(24).toString("base64url")}`;
215517
215574
  table[token] = nodeId;
215518
215575
  write(table);
215519
215576
  return token;
@@ -215553,14 +215610,14 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
215553
215610
  const read3 = () => {
215554
215611
  if (!file) return table;
215555
215612
  try {
215556
- return new Map(Object.entries(JSON.parse(fs20.readFileSync(file, "utf8"))));
215613
+ return new Map(Object.entries(JSON.parse(fs21.readFileSync(file, "utf8"))));
215557
215614
  } catch {
215558
215615
  return /* @__PURE__ */ new Map();
215559
215616
  }
215560
215617
  };
215561
215618
  const write = (m2) => {
215562
215619
  if (!file) return;
215563
- fs20.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
215620
+ fs21.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
215564
215621
  };
215565
215622
  const table = /* @__PURE__ */ new Map();
215566
215623
  const prune = () => {
@@ -215573,7 +215630,7 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
215573
215630
  return {
215574
215631
  issue(name, ttlMs = defaultTtlMs, companyId) {
215575
215632
  const m2 = prune();
215576
- const token = `ent_${(0, import_node_crypto42.randomBytes)(24).toString("base64url")}`;
215633
+ const token = `ent_${(0, import_node_crypto43.randomBytes)(24).toString("base64url")}`;
215577
215634
  const expiresAt2 = Date.now() + ttlMs;
215578
215635
  m2.set(token, { name, expiresAt: expiresAt2, ...companyId !== void 0 ? { companyId } : {} });
215579
215636
  write(m2);
@@ -215622,33 +215679,33 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
215622
215679
  }
215623
215680
  };
215624
215681
  }
215625
- var import_node_crypto42, fs20, path20, SESSION_TOKEN_PREFIX, b64url2, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
215682
+ var import_node_crypto43, fs21, path20, SESSION_TOKEN_PREFIX, b64url2, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
215626
215683
  var init_tokens = __esm({
215627
215684
  "../server/src/tokens.ts"() {
215628
215685
  "use strict";
215629
- import_node_crypto42 = require("node:crypto");
215630
- fs20 = __toESM(require("node:fs"), 1);
215686
+ import_node_crypto43 = require("node:crypto");
215687
+ fs21 = __toESM(require("node:fs"), 1);
215631
215688
  path20 = __toESM(require("node:path"), 1);
215632
215689
  SESSION_TOKEN_PREFIX = "oat_v2_";
215633
215690
  b64url2 = (value2) => Buffer.from(value2).toString("base64url");
215634
215691
  fromB64url = (value2) => Buffer.from(value2, "base64url").toString("utf8");
215635
215692
  readOrCreateSecret = (file) => {
215636
- if (!file) return (0, import_node_crypto42.randomBytes)(32);
215693
+ if (!file) return (0, import_node_crypto43.randomBytes)(32);
215637
215694
  try {
215638
- const raw = fs20.readFileSync(file, "utf8").trim();
215695
+ const raw = fs21.readFileSync(file, "utf8").trim();
215639
215696
  if (raw) return Buffer.from(raw, "base64url");
215640
215697
  } catch {
215641
215698
  }
215642
- const secret = (0, import_node_crypto42.randomBytes)(32);
215643
- fs20.mkdirSync(path20.dirname(file), { recursive: true });
215644
- fs20.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
215699
+ const secret = (0, import_node_crypto43.randomBytes)(32);
215700
+ fs21.mkdirSync(path20.dirname(file), { recursive: true });
215701
+ fs21.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
215645
215702
  return secret;
215646
215703
  };
215647
- sign = (secret, payload2) => (0, import_node_crypto42.createHmac)("sha256", secret).update(payload2).digest("base64url");
215704
+ sign = (secret, payload2) => (0, import_node_crypto43.createHmac)("sha256", secret).update(payload2).digest("base64url");
215648
215705
  signatureMatches = (actual, expected) => {
215649
215706
  const a = Buffer.from(actual);
215650
215707
  const b2 = Buffer.from(expected);
215651
- return a.length === b2.length && (0, import_node_crypto42.timingSafeEqual)(a, b2);
215708
+ return a.length === b2.length && (0, import_node_crypto43.timingSafeEqual)(a, b2);
215652
215709
  };
215653
215710
  isTokenClaims = (value2) => {
215654
215711
  if (value2 === null || typeof value2 !== "object") return false;
@@ -215670,6 +215727,9 @@ var init_tokens = __esm({
215670
215727
  function isOperatorRequest(auth) {
215671
215728
  return auth.scopes?.includes(OPERATOR_SCOPE) === true;
215672
215729
  }
215730
+ function operatorCrossCompanyRead(auth, method) {
215731
+ return method === "GET" && isOperatorRequest(auth);
215732
+ }
215673
215733
  var OPERATOR_SCOPE;
215674
215734
  var init_operator = __esm({
215675
215735
  "../server/src/auth/operator.ts"() {
@@ -215707,33 +215767,33 @@ function createDataplaneTokenIssuer(opts = {}) {
215707
215767
  }
215708
215768
  };
215709
215769
  }
215710
- var import_node_crypto43, fs21, path21, PREFIX2, b64url3, fromB64url2, sign2, sigMatches, readOrCreateSecret2, isClaims, isDataplaneToken;
215770
+ var import_node_crypto44, fs22, path21, PREFIX2, b64url3, fromB64url2, sign2, sigMatches, readOrCreateSecret2, isClaims, isDataplaneToken;
215711
215771
  var init_session_dataplane_token = __esm({
215712
215772
  "../server/src/session-dataplane-token.ts"() {
215713
215773
  "use strict";
215714
- import_node_crypto43 = require("node:crypto");
215715
- fs21 = __toESM(require("node:fs"), 1);
215774
+ import_node_crypto44 = require("node:crypto");
215775
+ fs22 = __toESM(require("node:fs"), 1);
215716
215776
  path21 = __toESM(require("node:path"), 1);
215717
215777
  init_src();
215718
215778
  PREFIX2 = "osd_";
215719
215779
  b64url3 = (v2) => Buffer.from(v2, "utf8").toString("base64url");
215720
215780
  fromB64url2 = (v2) => Buffer.from(v2, "base64url").toString("utf8");
215721
- sign2 = (secret, payload2) => (0, import_node_crypto43.createHmac)("sha256", secret).update(payload2).digest("base64url");
215781
+ sign2 = (secret, payload2) => (0, import_node_crypto44.createHmac)("sha256", secret).update(payload2).digest("base64url");
215722
215782
  sigMatches = (actual, expected) => {
215723
215783
  const a = Buffer.from(actual);
215724
215784
  const b2 = Buffer.from(expected);
215725
- return a.length === b2.length && (0, import_node_crypto43.timingSafeEqual)(a, b2);
215785
+ return a.length === b2.length && (0, import_node_crypto44.timingSafeEqual)(a, b2);
215726
215786
  };
215727
215787
  readOrCreateSecret2 = (file) => {
215728
- if (!file) return (0, import_node_crypto43.randomBytes)(32);
215788
+ if (!file) return (0, import_node_crypto44.randomBytes)(32);
215729
215789
  try {
215730
- const raw = fs21.readFileSync(file, "utf8").trim();
215790
+ const raw = fs22.readFileSync(file, "utf8").trim();
215731
215791
  if (raw) return Buffer.from(raw, "base64url");
215732
215792
  } catch {
215733
215793
  }
215734
- const secret = (0, import_node_crypto43.randomBytes)(32);
215735
- fs21.mkdirSync(path21.dirname(file), { recursive: true });
215736
- fs21.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
215794
+ const secret = (0, import_node_crypto44.randomBytes)(32);
215795
+ fs22.mkdirSync(path21.dirname(file), { recursive: true });
215796
+ fs22.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
215737
215797
  return secret;
215738
215798
  };
215739
215799
  isClaims = (v2) => {
@@ -218406,11 +218466,11 @@ function onlyHits(pool, q2) {
218406
218466
  if (!q2.requireMatch || q2.keywords.length === 0) return [...pool];
218407
218467
  return pool.filter((r) => memoryMatchScore(r, q2.keywords) > 0);
218408
218468
  }
218409
- var import_node_crypto44, MemoryActorMemoryStore, toIndexEntry;
218469
+ var import_node_crypto45, MemoryActorMemoryStore, toIndexEntry;
218410
218470
  var init_memory_actor_memory_store = __esm({
218411
218471
  "../testkit/src/memory-actor-memory-store.ts"() {
218412
218472
  "use strict";
218413
- import_node_crypto44 = require("node:crypto");
218473
+ import_node_crypto45 = require("node:crypto");
218414
218474
  init_src();
218415
218475
  MemoryActorMemoryStore = class {
218416
218476
  rows = /* @__PURE__ */ new Map();
@@ -218464,7 +218524,7 @@ var init_memory_actor_memory_store = __esm({
218464
218524
  async write(input, now) {
218465
218525
  if (input.memId === void 0) {
218466
218526
  const rec2 = {
218467
- memId: `mem:${(0, import_node_crypto44.randomUUID)()}`,
218527
+ memId: `mem:${(0, import_node_crypto45.randomUUID)()}`,
218468
218528
  actorId: input.actorId,
218469
218529
  projectId: input.projectId,
218470
218530
  keywords: [...input.keywords],
@@ -219275,13 +219335,13 @@ var init_stats = __esm({
219275
219335
 
219276
219336
  // ../server/src/domains/projects/project-id.ts
219277
219337
  function randomProjectId() {
219278
- return projectIdFromUuid((0, import_node_crypto45.randomUUID)());
219338
+ return projectIdFromUuid((0, import_node_crypto46.randomUUID)());
219279
219339
  }
219280
- var import_node_crypto45;
219340
+ var import_node_crypto46;
219281
219341
  var init_project_id = __esm({
219282
219342
  "../server/src/domains/projects/project-id.ts"() {
219283
219343
  "use strict";
219284
- import_node_crypto45 = require("node:crypto");
219344
+ import_node_crypto46 = require("node:crypto");
219285
219345
  init_src();
219286
219346
  }
219287
219347
  });
@@ -221356,13 +221416,13 @@ function applyTurnPatch(t, patch) {
221356
221416
  ...patch.lastError !== void 0 ? { lastError: patch.lastError } : {}
221357
221417
  };
221358
221418
  }
221359
- var import_node_crypto46, fs22, path22, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
221419
+ var import_node_crypto47, fs23, path22, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
221360
221420
  var init_dev_store = __esm({
221361
221421
  "../server/src/dev-store.ts"() {
221362
221422
  "use strict";
221363
221423
  init_src();
221364
- import_node_crypto46 = require("node:crypto");
221365
- fs22 = __toESM(require("node:fs"), 1);
221424
+ import_node_crypto47 = require("node:crypto");
221425
+ fs23 = __toESM(require("node:fs"), 1);
221366
221426
  path22 = __toESM(require("node:path"), 1);
221367
221427
  init_src();
221368
221428
  init_src9();
@@ -221376,8 +221436,8 @@ var init_dev_store = __esm({
221376
221436
  }
221377
221437
  static async open(file) {
221378
221438
  const memory = new MemoryOplogStore();
221379
- if (fs22.existsSync(file)) {
221380
- for (const line2 of fs22.readFileSync(file, "utf8").split("\n")) {
221439
+ if (fs23.existsSync(file)) {
221440
+ for (const line2 of fs23.readFileSync(file, "utf8").split("\n")) {
221381
221441
  if (!line2.trim()) continue;
221382
221442
  const stored = JSON.parse(line2);
221383
221443
  const { artifactId, seq, ...op } = stored;
@@ -221385,15 +221445,15 @@ var init_dev_store = __esm({
221385
221445
  if (assigned !== seq) throw new Error(`corrupt ndjson log: seq mismatch at ${line2}`);
221386
221446
  }
221387
221447
  } else {
221388
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
221389
- fs22.writeFileSync(file, "");
221448
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
221449
+ fs23.writeFileSync(file, "");
221390
221450
  }
221391
221451
  return new _NdjsonOplogStore(file, memory);
221392
221452
  }
221393
221453
  async append(artifactId, op, expectedSeq) {
221394
221454
  const seq = await this.memory.append(artifactId, op, expectedSeq);
221395
221455
  const stored = { ...op, artifactId, seq };
221396
- fs22.appendFileSync(this.file, JSON.stringify(stored) + "\n");
221456
+ fs23.appendFileSync(this.file, JSON.stringify(stored) + "\n");
221397
221457
  return seq;
221398
221458
  }
221399
221459
  read(artifactId, fromSeq) {
@@ -221409,39 +221469,39 @@ var init_dev_store = __esm({
221409
221469
  DirBlobStore = class {
221410
221470
  constructor(dir) {
221411
221471
  this.dir = dir;
221412
- fs22.mkdirSync(dir, { recursive: true });
221472
+ fs23.mkdirSync(dir, { recursive: true });
221413
221473
  }
221414
221474
  fileOf(hash3) {
221415
221475
  return path22.join(this.dir, hash3);
221416
221476
  }
221417
221477
  async put(bytes2) {
221418
- const hash3 = (0, import_node_crypto46.createHash)("sha256").update(bytes2).digest("hex");
221478
+ const hash3 = (0, import_node_crypto47.createHash)("sha256").update(bytes2).digest("hex");
221419
221479
  const file = this.fileOf(hash3);
221420
- if (!fs22.existsSync(file)) fs22.writeFileSync(file, bytes2);
221480
+ if (!fs23.existsSync(file)) fs23.writeFileSync(file, bytes2);
221421
221481
  return hash3;
221422
221482
  }
221423
221483
  async meta(hash3) {
221424
221484
  const file = this.fileOf(hash3);
221425
- if (!fs22.existsSync(file)) return null;
221426
- const size = fs22.statSync(file).size;
221427
- const fd = fs22.openSync(file, "r");
221485
+ if (!fs23.existsSync(file)) return null;
221486
+ const size = fs23.statSync(file).size;
221487
+ const fd = fs23.openSync(file, "r");
221428
221488
  const head = Buffer.alloc(16);
221429
- fs22.readSync(fd, head, 0, 16, 0);
221430
- fs22.closeSync(fd);
221489
+ fs23.readSync(fd, head, 0, 16, 0);
221490
+ fs23.closeSync(fd);
221431
221491
  const contentType = sniffContentType(new Uint8Array(head));
221432
221492
  return { size, ...contentType ? { contentType } : {} };
221433
221493
  }
221434
221494
  async get(hash3) {
221435
221495
  const file = this.fileOf(hash3);
221436
- if (!fs22.existsSync(file)) throw new BlobNotFoundError(hash3);
221437
- return new Uint8Array(fs22.readFileSync(file));
221496
+ if (!fs23.existsSync(file)) throw new BlobNotFoundError(hash3);
221497
+ return new Uint8Array(fs23.readFileSync(file));
221438
221498
  }
221439
221499
  async has(hash3) {
221440
- return fs22.existsSync(this.fileOf(hash3));
221500
+ return fs23.existsSync(this.fileOf(hash3));
221441
221501
  }
221442
221502
  async sweep(reachable) {
221443
- for (const name of fs22.readdirSync(this.dir)) {
221444
- if (!reachable.has(name)) fs22.unlinkSync(this.fileOf(name));
221503
+ for (const name of fs23.readdirSync(this.dir)) {
221504
+ if (!reachable.has(name)) fs23.unlinkSync(this.fileOf(name));
221445
221505
  }
221446
221506
  }
221447
221507
  };
@@ -221470,7 +221530,7 @@ var init_dev_store = __esm({
221470
221530
  this.file = file;
221471
221531
  }
221472
221532
  static async open(file) {
221473
- const seed = fs22.existsSync(file) ? JSON.parse(fs22.readFileSync(file, "utf8")) : [];
221533
+ const seed = fs23.existsSync(file) ? JSON.parse(fs23.readFileSync(file, "utf8")) : [];
221474
221534
  return new _FileTypeRegistryStore(file, seed);
221475
221535
  }
221476
221536
  async put(def) {
@@ -221483,8 +221543,8 @@ var init_dev_store = __esm({
221483
221543
  }
221484
221544
  async save() {
221485
221545
  const tmp = `${this.file}.tmp`;
221486
- fs22.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
221487
- fs22.renameSync(tmp, this.file);
221546
+ fs23.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
221547
+ fs23.renameSync(tmp, this.file);
221488
221548
  }
221489
221549
  };
221490
221550
  FileRoleRegistryStore = class _FileRoleRegistryStore extends MemoryRoleRegistryStore {
@@ -221493,7 +221553,7 @@ var init_dev_store = __esm({
221493
221553
  this.file = file;
221494
221554
  }
221495
221555
  static async open(file) {
221496
- const seed = fs22.existsSync(file) ? JSON.parse(fs22.readFileSync(file, "utf8")) : [];
221556
+ const seed = fs23.existsSync(file) ? JSON.parse(fs23.readFileSync(file, "utf8")) : [];
221497
221557
  return new _FileRoleRegistryStore(file, seed);
221498
221558
  }
221499
221559
  async put(def) {
@@ -221506,8 +221566,8 @@ var init_dev_store = __esm({
221506
221566
  }
221507
221567
  async save() {
221508
221568
  const tmp = `${this.file}.tmp`;
221509
- fs22.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
221510
- fs22.renameSync(tmp, this.file);
221569
+ fs23.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
221570
+ fs23.renameSync(tmp, this.file);
221511
221571
  }
221512
221572
  };
221513
221573
  FileRegistryStore = class _FileRegistryStore extends MemoryRegistryStore {
@@ -221525,8 +221585,8 @@ var init_dev_store = __esm({
221525
221585
  }
221526
221586
  static async open(file) {
221527
221587
  const store = new _FileRegistryStore(file);
221528
- if (fs22.existsSync(file)) {
221529
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
221588
+ if (fs23.existsSync(file)) {
221589
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
221530
221590
  for (const a of snap.actors) await MemoryRegistryStore.prototype.upsertActor.call(store, a);
221531
221591
  for (const c of snap.configs) await MemoryRegistryStore.prototype.appendConfig.call(store, c);
221532
221592
  for (const t of snap.teams) await MemoryRegistryStore.prototype.upsertTeam.call(store, t);
@@ -221567,7 +221627,7 @@ var init_dev_store = __esm({
221567
221627
  skillFiles: skillFilesEntries,
221568
221628
  connections
221569
221629
  };
221570
- fs22.writeFileSync(this.file, JSON.stringify(snap, null, 2));
221630
+ fs23.writeFileSync(this.file, JSON.stringify(snap, null, 2));
221571
221631
  }
221572
221632
  };
221573
221633
  FileAssistantBindStore = class _FileAssistantBindStore extends MemoryAssistantBindStore {
@@ -221585,11 +221645,11 @@ var init_dev_store = __esm({
221585
221645
  }
221586
221646
  static async open(file) {
221587
221647
  const store = new _FileAssistantBindStore(file);
221588
- if (fs22.existsSync(file)) store._load(JSON.parse(fs22.readFileSync(file, "utf8")));
221648
+ if (fs23.existsSync(file)) store._load(JSON.parse(fs23.readFileSync(file, "utf8")));
221589
221649
  return store;
221590
221650
  }
221591
221651
  async save() {
221592
- fs22.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
221652
+ fs23.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
221593
221653
  }
221594
221654
  };
221595
221655
  FileHumanPrefsStore = class _FileHumanPrefsStore extends MemoryHumanPrefsStore {
@@ -221607,11 +221667,11 @@ var init_dev_store = __esm({
221607
221667
  }
221608
221668
  static async open(file) {
221609
221669
  const store = new _FileHumanPrefsStore(file);
221610
- if (fs22.existsSync(file)) store._load(JSON.parse(fs22.readFileSync(file, "utf8")));
221670
+ if (fs23.existsSync(file)) store._load(JSON.parse(fs23.readFileSync(file, "utf8")));
221611
221671
  return store;
221612
221672
  }
221613
221673
  async save() {
221614
- fs22.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
221674
+ fs23.writeFileSync(this.file, JSON.stringify(this._dump(), null, 2));
221615
221675
  }
221616
221676
  };
221617
221677
  FileProjectStateStore = class _FileProjectStateStore extends MemoryProjectStateStore {
@@ -221621,8 +221681,8 @@ var init_dev_store = __esm({
221621
221681
  }
221622
221682
  static async open(file) {
221623
221683
  const store = new _FileProjectStateStore(file);
221624
- if (fs22.existsSync(file)) {
221625
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
221684
+ if (fs23.existsSync(file)) {
221685
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
221626
221686
  for (const project of snap.projects ?? []) await MemoryProjectStateStore.prototype.upsertProject.call(store, project);
221627
221687
  const membersByProject = /* @__PURE__ */ new Map();
221628
221688
  for (const member of snap.members ?? []) {
@@ -221634,8 +221694,8 @@ var init_dev_store = __esm({
221634
221694
  await MemoryProjectStateStore.prototype.replaceProjectMembers.call(store, projectId2, members);
221635
221695
  }
221636
221696
  } else {
221637
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
221638
- fs22.writeFileSync(file, JSON.stringify({ projects: [], members: [] }, null, 2));
221697
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
221698
+ fs23.writeFileSync(file, JSON.stringify({ projects: [], members: [] }, null, 2));
221639
221699
  }
221640
221700
  return store;
221641
221701
  }
@@ -221654,7 +221714,7 @@ var init_dev_store = __esm({
221654
221714
  async save() {
221655
221715
  const projects = await this.listProjects();
221656
221716
  const members = (await Promise.all(projects.map((project) => this.listProjectMembers(project.id)))).flat();
221657
- fs22.writeFileSync(this.file, JSON.stringify({ projects, members }, null, 2));
221717
+ fs23.writeFileSync(this.file, JSON.stringify({ projects, members }, null, 2));
221658
221718
  }
221659
221719
  };
221660
221720
  FileArtifactStateStore = class _FileArtifactStateStore extends MemoryArtifactStateStore {
@@ -221664,8 +221724,8 @@ var init_dev_store = __esm({
221664
221724
  }
221665
221725
  static async open(file) {
221666
221726
  const store = new _FileArtifactStateStore(file);
221667
- if (fs22.existsSync(file)) {
221668
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
221727
+ if (fs23.existsSync(file)) {
221728
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
221669
221729
  for (const artifact of snap.artifacts ?? []) await MemoryArtifactStateStore.prototype.upsertArtifact.call(store, artifact);
221670
221730
  for (const revision of snap.revisions ?? []) await MemoryArtifactStateStore.prototype.upsertRevision.call(store, revision);
221671
221731
  for (const event of snap.events ?? []) await MemoryArtifactStateStore.prototype.appendEvent.call(store, event);
@@ -221675,8 +221735,8 @@ var init_dev_store = __esm({
221675
221735
  for (const ws of snap.workspaceDispatchHeld ?? []) await MemoryArtifactStateStore.prototype.setWorkspaceDispatchHold.call(store, ws, true);
221676
221736
  for (const f2 of snap.workOrderFiles ?? []) await MemoryArtifactStateStore.prototype.addWorkOrderFile.call(store, f2);
221677
221737
  } else {
221678
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
221679
- fs22.writeFileSync(file, JSON.stringify({ artifacts: [], revisions: [], events: [], annotations: [], nodeOutputs: [], workspaceBindings: [], workspaceDispatchHeld: [], workOrderFiles: [] }, null, 2));
221738
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
221739
+ fs23.writeFileSync(file, JSON.stringify({ artifacts: [], revisions: [], events: [], annotations: [], nodeOutputs: [], workspaceBindings: [], workspaceDispatchHeld: [], workOrderFiles: [] }, null, 2));
221680
221740
  }
221681
221741
  return store;
221682
221742
  }
@@ -221713,7 +221773,7 @@ var init_dev_store = __esm({
221713
221773
  await this.save();
221714
221774
  }
221715
221775
  async save() {
221716
- fs22.writeFileSync(this.file, JSON.stringify(await this.listAll(), null, 2));
221776
+ fs23.writeFileSync(this.file, JSON.stringify(await this.listAll(), null, 2));
221717
221777
  }
221718
221778
  };
221719
221779
  FileTraceStore = class _FileTraceStore extends MemoryTraceStore {
@@ -221740,25 +221800,25 @@ var init_dev_store = __esm({
221740
221800
  return path22.join(this.eventsDir, `${encodeURIComponent(runId)}.ndjson`);
221741
221801
  }
221742
221802
  appendLine(file, obj2) {
221743
- fs22.appendFileSync(file, JSON.stringify(obj2) + "\n");
221803
+ fs23.appendFileSync(file, JSON.stringify(obj2) + "\n");
221744
221804
  }
221745
221805
  static replay(file, fn) {
221746
- if (!fs22.existsSync(file)) return;
221747
- for (const line2 of fs22.readFileSync(file, "utf8").split("\n")) {
221806
+ if (!fs23.existsSync(file)) return;
221807
+ for (const line2 of fs23.readFileSync(file, "utf8").split("\n")) {
221748
221808
  if (!line2.trim()) continue;
221749
221809
  fn(JSON.parse(line2));
221750
221810
  }
221751
221811
  }
221752
221812
  static async open(dir) {
221753
221813
  const store = new _FileTraceStore(dir);
221754
- fs22.mkdirSync(store.eventsDir, { recursive: true });
221814
+ fs23.mkdirSync(store.eventsDir, { recursive: true });
221755
221815
  _FileTraceStore.replay(store.runsFile, (r) => store.restoreRun(r));
221756
- for (const name of fs22.readdirSync(store.eventsDir)) {
221816
+ for (const name of fs23.readdirSync(store.eventsDir)) {
221757
221817
  _FileTraceStore.replay(path22.join(store.eventsDir, name), (e) => store.restoreEvent(e));
221758
221818
  }
221759
221819
  _FileTraceStore.replay(store.toolCallsFile, (c) => store.restoreToolCall(c));
221760
221820
  _FileTraceStore.replay(store.linksFile, (l) => store.restoreLink(l));
221761
- store.restoreContinuity(fs22.existsSync(store.continuityFile) ? JSON.parse(fs22.readFileSync(store.continuityFile, "utf8")) : {});
221821
+ store.restoreContinuity(fs23.existsSync(store.continuityFile) ? JSON.parse(fs23.readFileSync(store.continuityFile, "utf8")) : {});
221762
221822
  return store;
221763
221823
  }
221764
221824
  async createRun(input) {
@@ -221810,8 +221870,8 @@ var init_dev_store = __esm({
221810
221870
  }
221811
221871
  saveContinuity() {
221812
221872
  const tmp = `${this.continuityFile}.tmp`;
221813
- fs22.writeFileSync(tmp, JSON.stringify(this.continuitySnapshot(), null, 2));
221814
- fs22.renameSync(tmp, this.continuityFile);
221873
+ fs23.writeFileSync(tmp, JSON.stringify(this.continuitySnapshot(), null, 2));
221874
+ fs23.renameSync(tmp, this.continuityFile);
221815
221875
  }
221816
221876
  async appendEvents(runId, inputs) {
221817
221877
  const existing = await super.listEvents(runId, {});
@@ -222276,8 +222336,8 @@ var init_dev_store = __esm({
222276
222336
  }
222277
222337
  static async open(file) {
222278
222338
  const store = new _FileChatSessionStore(file);
222279
- if (fs22.existsSync(file)) {
222280
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
222339
+ if (fs23.existsSync(file)) {
222340
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
222281
222341
  for (const [sid, copies] of Object.entries(snap.outputCopies ?? {})) store.outputCopies.set(sid, copies);
222282
222342
  for (const [sid, fps] of Object.entries(snap.outputFingerprints ?? {})) store.outputFingerprints.set(sid, fps);
222283
222343
  for (const [sid, issues] of Object.entries(snap.fileIssues ?? {})) store.fileIssues.set(sid, issues);
@@ -222287,8 +222347,8 @@ var init_dev_store = __esm({
222287
222347
  for (const [sid, kinds] of Object.entries(snap.sessionWorkOrderKinds ?? {})) store.sessionWorkOrderKinds.set(sid, new Map(Object.entries(kinds)));
222288
222348
  for (const [sid, list2] of Object.entries(snap.pending ?? {})) store.pending.set(sid, list2);
222289
222349
  } else {
222290
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
222291
- fs22.writeFileSync(file, JSON.stringify({ sessions: [], messages: {}, sessionWorkOrders: {} }, null, 2));
222350
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
222351
+ fs23.writeFileSync(file, JSON.stringify({ sessions: [], messages: {}, sessionWorkOrders: {} }, null, 2));
222292
222352
  }
222293
222353
  return store;
222294
222354
  }
@@ -222382,7 +222442,7 @@ var init_dev_store = __esm({
222382
222442
  sessionWorkOrderKinds: Object.fromEntries([...this.sessionWorkOrderKinds].map(([k2, v2]) => [k2, Object.fromEntries(v2)])),
222383
222443
  pending: Object.fromEntries(this.pending)
222384
222444
  };
222385
- fs22.writeFileSync(this.file, JSON.stringify(snap, null, 2));
222445
+ fs23.writeFileSync(this.file, JSON.stringify(snap, null, 2));
222386
222446
  }
222387
222447
  };
222388
222448
  MemoryChatTurnStore = class {
@@ -222465,17 +222525,17 @@ var init_dev_store = __esm({
222465
222525
  }
222466
222526
  static async open(file) {
222467
222527
  const store = new _FileChatTurnStore(file);
222468
- if (fs22.existsSync(file)) {
222469
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
222528
+ if (fs23.existsSync(file)) {
222529
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
222470
222530
  for (const t of snap.turns ?? []) store.turns.set(t.id, t);
222471
222531
  } else {
222472
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
222473
- fs22.writeFileSync(file, JSON.stringify({ turns: [] }, null, 2));
222532
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
222533
+ fs23.writeFileSync(file, JSON.stringify({ turns: [] }, null, 2));
222474
222534
  }
222475
222535
  return store;
222476
222536
  }
222477
222537
  persist() {
222478
- fs22.writeFileSync(this.file, JSON.stringify({ turns: [...this.turns.values()] }, null, 2));
222538
+ fs23.writeFileSync(this.file, JSON.stringify({ turns: [...this.turns.values()] }, null, 2));
222479
222539
  }
222480
222540
  };
222481
222541
  MemoryReadMarkerStore = class _MemoryReadMarkerStore {
@@ -222501,12 +222561,12 @@ var init_dev_store = __esm({
222501
222561
  }
222502
222562
  static async open(file) {
222503
222563
  const store = new _FileReadMarkerStore(file);
222504
- if (fs22.existsSync(file)) {
222505
- const snap = JSON.parse(fs22.readFileSync(file, "utf8"));
222564
+ if (fs23.existsSync(file)) {
222565
+ const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
222506
222566
  for (const m2 of snap.markers ?? []) store.markers.set(`${m2.actorId}\0${m2.scope}`, m2);
222507
222567
  } else {
222508
- fs22.mkdirSync(path22.dirname(file), { recursive: true });
222509
- fs22.writeFileSync(file, JSON.stringify({ markers: [] }, null, 2));
222568
+ fs23.mkdirSync(path22.dirname(file), { recursive: true });
222569
+ fs23.writeFileSync(file, JSON.stringify({ markers: [] }, null, 2));
222510
222570
  }
222511
222571
  return store;
222512
222572
  }
@@ -222515,18 +222575,18 @@ var init_dev_store = __esm({
222515
222575
  this.save();
222516
222576
  }
222517
222577
  save() {
222518
- fs22.writeFileSync(this.file, JSON.stringify({ markers: [...this.markers.values()] }, null, 2));
222578
+ fs23.writeFileSync(this.file, JSON.stringify({ markers: [...this.markers.values()] }, null, 2));
222519
222579
  }
222520
222580
  };
222521
222581
  }
222522
222582
  });
222523
222583
 
222524
222584
  // ../server/src/control-plane-file-store.ts
222525
- var fs23, path23, MUTATORS2, SNAPSHOT_VERSION, FileControlPlaneStore;
222585
+ var fs24, path23, MUTATORS2, SNAPSHOT_VERSION, FileControlPlaneStore;
222526
222586
  var init_control_plane_file_store = __esm({
222527
222587
  "../server/src/control-plane-file-store.ts"() {
222528
222588
  "use strict";
222529
- fs23 = __toESM(require("node:fs"), 1);
222589
+ fs24 = __toESM(require("node:fs"), 1);
222530
222590
  path23 = __toESM(require("node:path"), 1);
222531
222591
  init_src9();
222532
222592
  MUTATORS2 = [
@@ -222569,8 +222629,8 @@ var init_control_plane_file_store = __esm({
222569
222629
  }
222570
222630
  static async open(file) {
222571
222631
  const store = new _FileControlPlaneStore(file);
222572
- if (fs23.existsSync(file)) {
222573
- const snap = JSON.parse(fs23.readFileSync(file, "utf8"));
222632
+ if (fs24.existsSync(file)) {
222633
+ const snap = JSON.parse(fs24.readFileSync(file, "utf8"));
222574
222634
  const needsOnboardingBackfill = (snap.version ?? 1) < 2;
222575
222635
  const backfillAt = (/* @__PURE__ */ new Date()).toISOString();
222576
222636
  for (const c of snap.companies ?? []) await MemoryControlPlaneStore.prototype.createCompany.call(store, c);
@@ -222588,7 +222648,7 @@ var init_control_plane_file_store = __esm({
222588
222648
  for (const op of snap.offboardings ?? []) store.offboardings.set(`${op.companyId}\0${op.operationId}`, op);
222589
222649
  if (needsOnboardingBackfill) await store.save();
222590
222650
  } else {
222591
- fs23.mkdirSync(path23.dirname(file), { recursive: true });
222651
+ fs24.mkdirSync(path23.dirname(file), { recursive: true });
222592
222652
  }
222593
222653
  return store;
222594
222654
  }
@@ -222625,7 +222685,7 @@ var init_control_plane_file_store = __esm({
222625
222685
  // 交接操作无按公司列举的读面(按 operationId / accountId 定位),直接读 protected map。
222626
222686
  offboardings: [...this.offboardings.values()]
222627
222687
  };
222628
- fs23.writeFileSync(this.file, JSON.stringify(snap, null, 2));
222688
+ fs24.writeFileSync(this.file, JSON.stringify(snap, null, 2));
222629
222689
  }
222630
222690
  };
222631
222691
  }
@@ -222701,7 +222761,7 @@ var init_company_engine_router = __esm({
222701
222761
 
222702
222762
  // ../server/src/skill-market-client.ts
222703
222763
  function digestOf2(bytes2) {
222704
- return `sha256:${(0, import_node_crypto47.createHash)("sha256").update(bytes2).digest("hex")}`;
222764
+ return `sha256:${(0, import_node_crypto48.createHash)("sha256").update(bytes2).digest("hex")}`;
222705
222765
  }
222706
222766
  function createSkillMarketClientFromEnv(env = process.env) {
222707
222767
  const base = env["SKILL_MARKET_BASE_URL"];
@@ -222712,11 +222772,11 @@ function createSkillMarketClientFromEnv(env = process.env) {
222712
222772
  function sleep4(ms) {
222713
222773
  return new Promise((r) => setTimeout(r, ms));
222714
222774
  }
222715
- var import_node_crypto47, DisabledSkillMarketClient, FakeSkillMarketClient, HttpSkillMarketClient;
222775
+ var import_node_crypto48, DisabledSkillMarketClient, FakeSkillMarketClient, HttpSkillMarketClient;
222716
222776
  var init_skill_market_client = __esm({
222717
222777
  "../server/src/skill-market-client.ts"() {
222718
222778
  "use strict";
222719
- import_node_crypto47 = require("node:crypto");
222779
+ import_node_crypto48 = require("node:crypto");
222720
222780
  init_src();
222721
222781
  DisabledSkillMarketClient = class {
222722
222782
  async listSkills(_input) {
@@ -223567,7 +223627,7 @@ async function copySessionOutputs(deps) {
223567
223627
  continue;
223568
223628
  }
223569
223629
  const saved = existing?.[file.path];
223570
- if (saved && savedContentHash(saved) === (0, import_node_crypto48.createHash)("sha256").update(bytes2).digest("hex")) {
223630
+ if (saved && savedContentHash(saved) === (0, import_node_crypto49.createHash)("sha256").update(bytes2).digest("hex")) {
223571
223631
  const aligned = { ...saved, size: bytes2.length, mtime: file.mtime };
223572
223632
  delete aligned.editedAt;
223573
223633
  realigned.push(aligned);
@@ -223664,11 +223724,11 @@ function createOutputCopyScheduler(deps) {
223664
223724
  }
223665
223725
  };
223666
223726
  }
223667
- var import_node_crypto48, OUTPUT_COPY_LIMITS;
223727
+ var import_node_crypto49, OUTPUT_COPY_LIMITS;
223668
223728
  var init_outputs_copy = __esm({
223669
223729
  "../server/src/domains/chat-sessions/outputs-copy.ts"() {
223670
223730
  "use strict";
223671
- import_node_crypto48 = require("node:crypto");
223731
+ import_node_crypto49 = require("node:crypto");
223672
223732
  init_src();
223673
223733
  OUTPUT_COPY_LIMITS = {
223674
223734
  maxFileBytes: FILE_CONTENT_MAX_BYTES,
@@ -223883,11 +223943,11 @@ function typeDefError(def, mode) {
223883
223943
  }
223884
223944
  return null;
223885
223945
  }
223886
- var import_node_crypto49, RESERVED_FIELD_NAMES, ARTIFACT_TYPE_ACCENTS, TYPE_DEF_SCHEMA, TypesAdminService;
223946
+ var import_node_crypto50, RESERVED_FIELD_NAMES, ARTIFACT_TYPE_ACCENTS, TYPE_DEF_SCHEMA, TypesAdminService;
223887
223947
  var init_types_admin = __esm({
223888
223948
  "../server/src/types-admin.ts"() {
223889
223949
  "use strict";
223890
- import_node_crypto49 = require("node:crypto");
223950
+ import_node_crypto50 = require("node:crypto");
223891
223951
  init_zod();
223892
223952
  init_src7();
223893
223953
  init_config_audit();
@@ -224014,7 +224074,7 @@ var init_types_admin = __esm({
224014
224074
  async trace(change, target, by, detail) {
224015
224075
  try {
224016
224076
  await this.audit?.({
224017
- id: `reg_${(0, import_node_crypto49.randomUUID)()}`,
224077
+ id: `reg_${(0, import_node_crypto50.randomUUID)()}`,
224018
224078
  actor: by ?? SYSTEM_CONFIG_ACTOR,
224019
224079
  kind: "registry_change",
224020
224080
  target,
@@ -224162,11 +224222,11 @@ function roleDefError(def, mode) {
224162
224222
  }
224163
224223
  return null;
224164
224224
  }
224165
- var import_node_crypto50, ACCENTS, ROLE_DEF_SCHEMA, RolesAdminService;
224225
+ var import_node_crypto51, ACCENTS, ROLE_DEF_SCHEMA, RolesAdminService;
224166
224226
  var init_roles_admin = __esm({
224167
224227
  "../server/src/roles-admin.ts"() {
224168
224228
  "use strict";
224169
- import_node_crypto50 = require("node:crypto");
224229
+ import_node_crypto51 = require("node:crypto");
224170
224230
  init_zod();
224171
224231
  init_src7();
224172
224232
  init_config_audit();
@@ -224191,7 +224251,7 @@ var init_roles_admin = __esm({
224191
224251
  async trace(change, target, by, detail) {
224192
224252
  try {
224193
224253
  await this.deps.audit?.({
224194
- id: `reg_${(0, import_node_crypto50.randomUUID)()}`,
224254
+ id: `reg_${(0, import_node_crypto51.randomUUID)()}`,
224195
224255
  actor: by ?? SYSTEM_CONFIG_ACTOR,
224196
224256
  kind: "registry_change",
224197
224257
  target,
@@ -224204,8 +224264,13 @@ var init_roles_admin = __esm({
224204
224264
  list() {
224205
224265
  return this.deps.store.list();
224206
224266
  }
224207
- async usage(name) {
224208
- return (await this.usageMany([name]))[name];
224267
+ /**
224268
+ * @param companyId 按哪家公司的员工数人头(Bug 0245)。岗位目录全公司共用一份,但「谁在岗」是各公司自己的——
224269
+ * GET /api/roles 必须传请求所属公司,否则落到默认公司那份早已不再更新的旧名单,所有公司都报同一组错数。
224270
+ * 缺省 = 默认公司(改名 / 弃用 / 删除这几条写路径暂维持原口径)。
224271
+ */
224272
+ async usage(name, companyId) {
224273
+ return (await this.usageMany([name], companyId))[name];
224209
224274
  }
224210
224275
  /**
224211
224276
  * ADR 0088 D4:多个岗位的用量**一次取数**。此前 `/api/roles` 对每个岗位各调一次 `usage()`,
@@ -224213,9 +224278,9 @@ var init_roles_admin = __esm({
224213
224278
  * ——13 个岗位 = 13 份全表。员工页首屏门控在这条上(listRoles 与 listActors 并行等齐才渲染)。
224214
224279
  * 三份数据只取一次,逐岗位在内存算。单岗位口径与旧 `usage()` 逐字段一致(后者现转调本方法)。
224215
224280
  */
224216
- async usageMany(names) {
224281
+ async usageMany(names, companyId) {
224217
224282
  const [actors, types2, owners] = await Promise.all([
224218
- this.deps.actors(),
224283
+ this.deps.actors(companyId),
224219
224284
  this.deps.types(),
224220
224285
  this.deps.artifactOwners?.() ?? Promise.resolve([])
224221
224286
  ]);
@@ -227050,8 +227115,8 @@ var init_chat_recovery = __esm({
227050
227115
 
227051
227116
  // ../server/src/auth/crypto.ts
227052
227117
  function hashPassword(password) {
227053
- const salt = (0, import_node_crypto51.randomBytes)(16);
227054
- const dk = (0, import_node_crypto51.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
227118
+ const salt = (0, import_node_crypto52.randomBytes)(16);
227119
+ const dk = (0, import_node_crypto52.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
227055
227120
  return `scrypt$${SCRYPT_N}$${salt.toString("base64url")}$${dk.toString("base64url")}`;
227056
227121
  }
227057
227122
  function verifyPassword(password, stored) {
@@ -227068,8 +227133,8 @@ function verifyPassword(password, stored) {
227068
227133
  return false;
227069
227134
  }
227070
227135
  if (expected.length === 0) return false;
227071
- const dk = (0, import_node_crypto51.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
227072
- return dk.length === expected.length && (0, import_node_crypto51.timingSafeEqual)(dk, expected);
227136
+ const dk = (0, import_node_crypto52.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
227137
+ return dk.length === expected.length && (0, import_node_crypto52.timingSafeEqual)(dk, expected);
227073
227138
  }
227074
227139
  function b64urlJson(value2) {
227075
227140
  return Buffer.from(JSON.stringify(value2)).toString("base64url");
@@ -227077,17 +227142,17 @@ function b64urlJson(value2) {
227077
227142
  function signSession(claims, secret) {
227078
227143
  const head = b64urlJson({ alg: "HS256", typ: "JWT" });
227079
227144
  const body2 = b64urlJson(claims);
227080
- const sig = (0, import_node_crypto51.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
227145
+ const sig = (0, import_node_crypto52.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
227081
227146
  return `${head}.${body2}.${sig}`;
227082
227147
  }
227083
227148
  function verifySession(token, secret, nowMs) {
227084
227149
  const parts = token.split(".");
227085
227150
  if (parts.length !== 3) return null;
227086
227151
  const [head, body2, sig] = parts;
227087
- const expected = (0, import_node_crypto51.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
227152
+ const expected = (0, import_node_crypto52.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
227088
227153
  const got = Buffer.from(sig);
227089
227154
  const exp = Buffer.from(expected);
227090
- if (got.length !== exp.length || !(0, import_node_crypto51.timingSafeEqual)(got, exp)) return null;
227155
+ if (got.length !== exp.length || !(0, import_node_crypto52.timingSafeEqual)(got, exp)) return null;
227091
227156
  let claims;
227092
227157
  try {
227093
227158
  claims = JSON.parse(Buffer.from(body2, "base64url").toString("utf8"));
@@ -227099,21 +227164,21 @@ function verifySession(token, secret, nowMs) {
227099
227164
  return claims;
227100
227165
  }
227101
227166
  function generateCode() {
227102
- return String((0, import_node_crypto51.randomInt)(0, 1e6)).padStart(6, "0");
227167
+ return String((0, import_node_crypto52.randomInt)(0, 1e6)).padStart(6, "0");
227103
227168
  }
227104
227169
  function hashCode(code2, secret) {
227105
- return (0, import_node_crypto51.createHmac)("sha256", secret).update(`code:${code2}`).digest("base64url");
227170
+ return (0, import_node_crypto52.createHmac)("sha256", secret).update(`code:${code2}`).digest("base64url");
227106
227171
  }
227107
227172
  function safeEqualHash(a, b2) {
227108
227173
  const ba = Buffer.from(a);
227109
227174
  const bb = Buffer.from(b2);
227110
- return ba.length === bb.length && (0, import_node_crypto51.timingSafeEqual)(ba, bb);
227175
+ return ba.length === bb.length && (0, import_node_crypto52.timingSafeEqual)(ba, bb);
227111
227176
  }
227112
- var import_node_crypto51, SCRYPT_N, SCRYPT_KEYLEN;
227177
+ var import_node_crypto52, SCRYPT_N, SCRYPT_KEYLEN;
227113
227178
  var init_crypto2 = __esm({
227114
227179
  "../server/src/auth/crypto.ts"() {
227115
227180
  "use strict";
227116
- import_node_crypto51 = require("node:crypto");
227181
+ import_node_crypto52 = require("node:crypto");
227117
227182
  SCRYPT_N = 16384;
227118
227183
  SCRYPT_KEYLEN = 32;
227119
227184
  }
@@ -228497,18 +228562,18 @@ function variableKeyFromEnv(env = process.env) {
228497
228562
  return buf;
228498
228563
  }
228499
228564
  if (env.NODE_ENV === "production") throw new Error("OASIS_VAR_KEY is required in production");
228500
- return (0, import_node_crypto52.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
228565
+ return (0, import_node_crypto53.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
228501
228566
  }
228502
228567
  function dedupe2(ids2) {
228503
228568
  return [...new Set(ids2.filter((x2) => typeof x2 === "string" && x2.length > 0))];
228504
228569
  }
228505
- var import_node_crypto52, REDACTED_MARKER, ActorsService, MASK_TAIL_MIN_LENGTH, mask, changedKeys;
228570
+ var import_node_crypto53, REDACTED_MARKER, ActorsService, MASK_TAIL_MIN_LENGTH, mask, changedKeys;
228506
228571
  var init_service5 = __esm({
228507
228572
  "../server/src/domains/actors/service.ts"() {
228508
228573
  "use strict";
228509
228574
  init_file_limits2();
228510
228575
  init_keyed_mutex();
228511
- import_node_crypto52 = require("node:crypto");
228576
+ import_node_crypto53 = require("node:crypto");
228512
228577
  init_skill_fetcher();
228513
228578
  init_identity();
228514
228579
  init_migrate();
@@ -229132,7 +229197,7 @@ ${input.description}
229132
229197
  */
229133
229198
  buildSkillFile(skillId, path46, content3, now) {
229134
229199
  const bytes2 = new TextEncoder().encode(content3);
229135
- const blobHash = (0, import_node_crypto52.createHash)("sha256").update(bytes2).digest("hex");
229200
+ const blobHash = (0, import_node_crypto53.createHash)("sha256").update(bytes2).digest("hex");
229136
229201
  return { skillId, path: path46, content: content3, blobHash, size: bytes2.length, updatedAt: now };
229137
229202
  }
229138
229203
  /**
@@ -230255,15 +230320,15 @@ ${input.description}
230255
230320
  return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
230256
230321
  }
230257
230322
  encrypt(plain) {
230258
- const iv = (0, import_node_crypto52.randomBytes)(12);
230259
- const cipher = (0, import_node_crypto52.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
230323
+ const iv = (0, import_node_crypto53.randomBytes)(12);
230324
+ const cipher = (0, import_node_crypto53.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
230260
230325
  const enc3 = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
230261
230326
  return [iv.toString("base64"), cipher.getAuthTag().toString("base64"), enc3.toString("base64")].join(".");
230262
230327
  }
230263
230328
  decrypt(packed) {
230264
230329
  const [iv, tag, data] = packed.split(".");
230265
230330
  if (!iv || !tag || typeof data !== "string") throw new Error("malformed ciphertext");
230266
- const decipher = (0, import_node_crypto52.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
230331
+ const decipher = (0, import_node_crypto53.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
230267
230332
  decipher.setAuthTag(Buffer.from(tag, "base64"));
230268
230333
  return Buffer.concat([decipher.update(Buffer.from(data, "base64")), decipher.final()]).toString("utf8");
230269
230334
  }
@@ -230876,7 +230941,7 @@ async function listSkillMetadataForActor(args) {
230876
230941
  usedDirs.add(dir);
230877
230942
  const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
230878
230943
  let latest = "1970-01-01T00:00:00.000Z";
230879
- const hasher = (0, import_node_crypto53.createHash)("sha256");
230944
+ const hasher = (0, import_node_crypto54.createHash)("sha256");
230880
230945
  for (const m2 of sorted) {
230881
230946
  if (m2.updatedAt > latest) latest = m2.updatedAt;
230882
230947
  hasher.update(m2.path);
@@ -230901,11 +230966,11 @@ async function listSkillMetadataForActor(args) {
230901
230966
  const dir = sanitizeSkillDir(c.name, c.slug);
230902
230967
  if (usedDirs.has(dir)) continue;
230903
230968
  usedDirs.add(dir);
230904
- const hasher = (0, import_node_crypto53.createHash)("sha256");
230969
+ const hasher = (0, import_node_crypto54.createHash)("sha256");
230905
230970
  for (const p2 of paths) {
230906
230971
  hasher.update(p2);
230907
230972
  hasher.update("\0");
230908
- hasher.update((0, import_node_crypto53.createHash)("sha256").update(c.files[p2]).digest("hex"));
230973
+ hasher.update((0, import_node_crypto54.createHash)("sha256").update(c.files[p2]).digest("hex"));
230909
230974
  hasher.update("\0");
230910
230975
  }
230911
230976
  out.push({
@@ -230926,11 +230991,11 @@ async function listSkillMetadataForActor(args) {
230926
230991
  const dir = sanitizeSkillDir(b2.name, b2.id);
230927
230992
  if (usedDirs.has(dir)) continue;
230928
230993
  usedDirs.add(dir);
230929
- const hasher = (0, import_node_crypto53.createHash)("sha256");
230994
+ const hasher = (0, import_node_crypto54.createHash)("sha256");
230930
230995
  for (const p2 of paths) {
230931
230996
  hasher.update(p2);
230932
230997
  hasher.update("\0");
230933
- hasher.update((0, import_node_crypto53.createHash)("sha256").update(b2.files[p2]).digest("hex"));
230998
+ hasher.update((0, import_node_crypto54.createHash)("sha256").update(b2.files[p2]).digest("hex"));
230934
230999
  hasher.update("\0");
230935
231000
  }
230936
231001
  out.push({
@@ -230950,7 +231015,7 @@ function builtinSkillToFiles(b2) {
230950
231015
  skillId: `builtin:${b2.id}`,
230951
231016
  path: path46,
230952
231017
  content: content3,
230953
- blobHash: (0, import_node_crypto53.createHash)("sha256").update(content3).digest("hex"),
231018
+ blobHash: (0, import_node_crypto54.createHash)("sha256").update(content3).digest("hex"),
230954
231019
  size: Buffer.byteLength(content3, "utf8"),
230955
231020
  updatedAt: "1970-01-01T00:00:00.000Z"
230956
231021
  }));
@@ -230974,7 +231039,7 @@ function sanitizeSkillDir(name, fallbackId) {
230974
231039
  if (byName) return byName;
230975
231040
  const byId = fallbackId ? fold2(fallbackId) : "";
230976
231041
  if (byId) return byId;
230977
- return `skill-${(0, import_node_crypto53.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`;
231042
+ return `skill-${(0, import_node_crypto54.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`;
230978
231043
  }
230979
231044
  async function materializeSkillFiles(args) {
230980
231045
  const skills = await args.service.listInstalledSkillsForActor(args.actorId);
@@ -231007,7 +231072,7 @@ function connectorSkillToFiles(c) {
231007
231072
  skillId: c.id,
231008
231073
  path: path46,
231009
231074
  content: content3,
231010
- blobHash: (0, import_node_crypto53.createHash)("sha256").update(content3).digest("hex"),
231075
+ blobHash: (0, import_node_crypto54.createHash)("sha256").update(content3).digest("hex"),
231011
231076
  size: Buffer.byteLength(content3, "utf8"),
231012
231077
  updatedAt: "1970-01-01T00:00:00.000Z"
231013
231078
  }));
@@ -231024,11 +231089,11 @@ function connectorSkillDisplayRows(connectorSkills, enabledConnectors) {
231024
231089
  ...s2.version !== void 0 ? { version: s2.version } : {}
231025
231090
  }));
231026
231091
  }
231027
- var import_node_crypto53;
231092
+ var import_node_crypto54;
231028
231093
  var init_skill_materializer = __esm({
231029
231094
  "../server/src/domains/actors/skill-materializer.ts"() {
231030
231095
  "use strict";
231031
- import_node_crypto53 = require("node:crypto");
231096
+ import_node_crypto54 = require("node:crypto");
231032
231097
  }
231033
231098
  });
231034
231099
 
@@ -232800,54 +232865,6 @@ var init_credential_audit_log = __esm({
232800
232865
  }
232801
232866
  });
232802
232867
 
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
232868
  // ../server/src/domains/actors/stop-on-delete.ts
232852
232869
  function planStopForDeletedActor(actorId, open3) {
232853
232870
  const mine = open3.filter((row) => row.actorId === actorId);
@@ -233074,7 +233091,7 @@ function createActorsDomain(opts) {
233074
233091
  ...kernel !== void 0 ? { onRolesChanged: (a, r) => kernel.setActorRoles(a, r) } : {},
233075
233092
  audit: async (entry) => {
233076
233093
  await opts.audit?.({
233077
- id: `reg_${(0, import_node_crypto54.randomUUID)()}`,
233094
+ id: `reg_${(0, import_node_crypto55.randomUUID)()}`,
233078
233095
  actor: entry.by,
233079
233096
  kind: "registry_change",
233080
233097
  target: entry.actorId,
@@ -233114,11 +233131,11 @@ function createActorsDomain(opts) {
233114
233131
  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
233132
  };
233116
233133
  }
233117
- var import_node_crypto54;
233134
+ var import_node_crypto55;
233118
233135
  var init_actors = __esm({
233119
233136
  "../server/src/domains/actors/index.ts"() {
233120
233137
  "use strict";
233121
- import_node_crypto54 = require("node:crypto");
233138
+ import_node_crypto55 = require("node:crypto");
233122
233139
  init_service5();
233123
233140
  init_routes3();
233124
233141
  init_service5();
@@ -237602,11 +237619,11 @@ function fromRow(row) {
237602
237619
  for (const [k2, v2] of opt) if (v2 !== void 0 && v2 !== null) r[k2] = v2;
237603
237620
  return r;
237604
237621
  }
237605
- var import_node_crypto55, import_node_fs16, DEFAULT_PAGE, MAX_PAGE, pageSize, MemoryNotificationStore, ident3, iso2, str2, PostgresNotificationStore;
237622
+ var import_node_crypto56, import_node_fs16, DEFAULT_PAGE, MAX_PAGE, pageSize, MemoryNotificationStore, ident3, iso2, str2, PostgresNotificationStore;
237606
237623
  var init_notification_store = __esm({
237607
237624
  "../server/src/domains/collab/notification-store.ts"() {
237608
237625
  "use strict";
237609
- import_node_crypto55 = require("node:crypto");
237626
+ import_node_crypto56 = require("node:crypto");
237610
237627
  import_node_fs16 = __toESM(require("node:fs"), 1);
237611
237628
  DEFAULT_PAGE = 50;
237612
237629
  MAX_PAGE = 200;
@@ -237639,7 +237656,7 @@ var init_notification_store = __esm({
237639
237656
  async insert(n) {
237640
237657
  const existing = this.findLive(n.recipient, n.sourceKey, n.category);
237641
237658
  if (existing) return existing;
237642
- const row = { ...n, id: `ntf:${(0, import_node_crypto55.randomUUID)()}`, updatedAt: n.enteredAt };
237659
+ const row = { ...n, id: `ntf:${(0, import_node_crypto56.randomUUID)()}`, updatedAt: n.enteredAt };
237643
237660
  this.rows.set(row.id, row);
237644
237661
  this.save();
237645
237662
  return row;
@@ -237772,7 +237789,7 @@ var init_notification_store = __esm({
237772
237789
  return new _PostgresNotificationStore(sql, schema);
237773
237790
  }
237774
237791
  async insert(n) {
237775
- const id = `ntf:${(0, import_node_crypto55.randomUUID)()}`;
237792
+ const id = `ntf:${(0, import_node_crypto56.randomUUID)()}`;
237776
237793
  const r = await this.sql.query(
237777
237794
  `INSERT INTO ${this.t} (id, recipient, category, source_key, kind, workorder_id, node_id, card_id, actor_id,
237778
237795
  title, workspace_title, entered_at, updated_at, status, read_at, item)
@@ -239780,13 +239797,13 @@ function nameKey(name) {
239780
239797
  function cleanName(name) {
239781
239798
  return name.trim().replace(/\s+/g, " ");
239782
239799
  }
239783
- var import_node_fs17, import_node_path21, import_node_crypto56, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
239800
+ var import_node_fs17, import_node_path21, import_node_crypto57, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
239784
239801
  var init_tags = __esm({
239785
239802
  "../server/src/domains/collab/tags.ts"() {
239786
239803
  "use strict";
239787
239804
  import_node_fs17 = __toESM(require("node:fs"), 1);
239788
239805
  import_node_path21 = __toESM(require("node:path"), 1);
239789
- import_node_crypto56 = __toESM(require("node:crypto"), 1);
239806
+ import_node_crypto57 = __toESM(require("node:crypto"), 1);
239790
239807
  SEP = "::";
239791
239808
  keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
239792
239809
  prefixOf = (companyId) => `${companyId}${SEP}`;
@@ -239804,7 +239821,7 @@ var init_tags = __esm({
239804
239821
  if (!name) return null;
239805
239822
  if (this.entries(companyId).some((t) => nameKey(t.name) === nameKey(name))) return null;
239806
239823
  const tag = {
239807
- id: `tag-${import_node_crypto56.default.randomBytes(6).toString("hex")}`,
239824
+ id: `tag-${import_node_crypto57.default.randomBytes(6).toString("hex")}`,
239808
239825
  name,
239809
239826
  ...input.color?.trim() ? { color: input.color.trim() } : {},
239810
239827
  ...input.description?.trim() ? { description: input.description.trim() } : {}
@@ -241193,11 +241210,11 @@ async function isEmployedElsewhere(store, companyId, accountId) {
241193
241210
  const memberships = await store.listMembershipsForAccount(accountId);
241194
241211
  return memberships.some((m2) => m2.companyId !== companyId);
241195
241212
  }
241196
- var import_node_crypto57, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, INVITE_LINK_TTL_MS, INVITE_LINK_TOKEN_BYTES, INVITE_LINK_ROLE, SLUG_RE, CompanyError, CompaniesService;
241213
+ 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
241214
  var init_service6 = __esm({
241198
241215
  "../server/src/domains/companies/service.ts"() {
241199
241216
  "use strict";
241200
- import_node_crypto57 = require("node:crypto");
241217
+ import_node_crypto58 = require("node:crypto");
241201
241218
  init_console_url();
241202
241219
  ROLES = ["owner", "admin", "member"];
241203
241220
  INVITABLE_ROLES = ["admin", "member"];
@@ -241289,7 +241306,7 @@ var init_service6 = __esm({
241289
241306
  const existing = await this.store.getAccountByEmail(normalized4);
241290
241307
  if (existing) return existing;
241291
241308
  const account = {
241292
- id: `actor:human:${(0, import_node_crypto57.randomUUID)()}`,
241309
+ id: `actor:human:${(0, import_node_crypto58.randomUUID)()}`,
241293
241310
  email: normalized4,
241294
241311
  name: name ?? normalized4,
241295
241312
  status: "active"
@@ -241498,7 +241515,7 @@ var init_service6 = __esm({
241498
241515
  }
241499
241516
  const nowMs = Date.parse(this.now());
241500
241517
  const invitation = {
241501
- id: `invitation:${(0, import_node_crypto57.randomUUID)()}`,
241518
+ id: `invitation:${(0, import_node_crypto58.randomUUID)()}`,
241502
241519
  companyId,
241503
241520
  email: mail,
241504
241521
  role,
@@ -241629,7 +241646,7 @@ var init_service6 = __esm({
241629
241646
  const nowMs = Date.parse(this.now());
241630
241647
  const link = {
241631
241648
  companyId,
241632
- token: (0, import_node_crypto57.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
241649
+ token: (0, import_node_crypto58.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
241633
241650
  role: INVITE_LINK_ROLE,
241634
241651
  createdAt: new Date(nowMs).toISOString(),
241635
241652
  expiresAt: new Date(nowMs + INVITE_LINK_TTL_MS).toISOString(),
@@ -241686,7 +241703,7 @@ var init_service6 = __esm({
241686
241703
  const reusable = existing.find((inv) => !this.isExpired(inv));
241687
241704
  if (reusable) return reusable;
241688
241705
  const invitation = {
241689
- id: `invitation:${(0, import_node_crypto57.randomUUID)()}`,
241706
+ id: `invitation:${(0, import_node_crypto58.randomUUID)()}`,
241690
241707
  companyId: link.companyId,
241691
241708
  email: mail,
241692
241709
  role: link.role,
@@ -241924,11 +241941,11 @@ var init_service6 = __esm({
241924
241941
  });
241925
241942
 
241926
241943
  // ../server/src/domains/companies/offboarding.ts
241927
- var import_node_crypto58, MemberOffboardingService;
241944
+ var import_node_crypto59, MemberOffboardingService;
241928
241945
  var init_offboarding = __esm({
241929
241946
  "../server/src/domains/companies/offboarding.ts"() {
241930
241947
  "use strict";
241931
- import_node_crypto58 = require("node:crypto");
241948
+ import_node_crypto59 = require("node:crypto");
241932
241949
  init_service6();
241933
241950
  MemberOffboardingService = class {
241934
241951
  store;
@@ -242000,7 +242017,7 @@ var init_offboarding = __esm({
242000
242017
  const { ownedAgents, inFlight } = await this.snapshot(companyId, accountId);
242001
242018
  const at2 = this.now();
242002
242019
  const started = await this.store.startMemberOffboarding({
242003
- operationId: `off:${(0, import_node_crypto58.randomUUID)()}`,
242020
+ operationId: `off:${(0, import_node_crypto59.randomUUID)()}`,
242004
242021
  companyId,
242005
242022
  accountId,
242006
242023
  initiatedBy,
@@ -242510,18 +242527,18 @@ var init_routes6 = __esm({
242510
242527
 
242511
242528
  // ../server/src/domains/companies/agent-credentials.ts
242512
242529
  function hashAgentToken(token, secret) {
242513
- return HASH_PREFIX + (0, import_node_crypto59.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
242530
+ return HASH_PREFIX + (0, import_node_crypto60.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
242514
242531
  }
242515
242532
  function safeEqual(a, b2) {
242516
242533
  const ba = Buffer.from(a);
242517
242534
  const bb = Buffer.from(b2);
242518
- return ba.length === bb.length && (0, import_node_crypto59.timingSafeEqual)(ba, bb);
242535
+ return ba.length === bb.length && (0, import_node_crypto60.timingSafeEqual)(ba, bb);
242519
242536
  }
242520
- var import_node_crypto59, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
242537
+ var import_node_crypto60, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
242521
242538
  var init_agent_credentials = __esm({
242522
242539
  "../server/src/domains/companies/agent-credentials.ts"() {
242523
242540
  "use strict";
242524
- import_node_crypto59 = require("node:crypto");
242541
+ import_node_crypto60 = require("node:crypto");
242525
242542
  init_service6();
242526
242543
  HASH_PREFIX = "ac1$";
242527
242544
  TOKEN_PREFIX = "oak_";
@@ -242546,7 +242563,7 @@ var init_agent_credentials = __esm({
242546
242563
  if (employee.status !== "active") {
242547
242564
  throw new CompanyError(409, "AGENT_LEFT", `\u6570\u5B57\u5458\u5DE5\u5DF2\u79BB\u5F00\uFF0C\u4E0D\u80FD\u7B7E\u53D1\u51ED\u8BC1\uFF1A${agentId}`);
242548
242565
  }
242549
- const token = `${TOKEN_PREFIX}${(0, import_node_crypto59.randomBytes)(32).toString("base64url")}`;
242566
+ const token = `${TOKEN_PREFIX}${(0, import_node_crypto60.randomBytes)(32).toString("base64url")}`;
242550
242567
  const credential = {
242551
242568
  tokenHash: hashAgentToken(token, this.secret),
242552
242569
  companyId,
@@ -243037,7 +243054,7 @@ function gatewayInstanceSlug(gatewayUrl) {
243037
243054
  }
243038
243055
  function connectInstanceName(gatewayUrl, token, companyId) {
243039
243056
  const scope2 = companyId?.trim();
243040
- const suffix = scope2 ? `c${(0, import_node_crypto60.createHash)("sha256").update(`${gatewayUrl}\0${scope2}`).digest("hex").slice(0, 10)}` : token.replace(/[^a-z0-9]/gi, "").slice(-8).toLowerCase() || "enroll";
243057
+ 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
243058
  const base = gatewayInstanceSlug(gatewayUrl);
243042
243059
  return base.slice(0, Math.max(1, 64 - suffix.length - 1)) + "-" + suffix;
243043
243060
  }
@@ -243366,12 +243383,12 @@ function buildNpxCmd(p2) {
243366
243383
  const prefix = daemonNpmPrefix();
243367
243384
  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
243385
  }
243369
- var import_node_crypto60;
243386
+ var import_node_crypto61;
243370
243387
  var init_connect_script = __esm({
243371
243388
  "../server/src/domains/nodes/connect-script.ts"() {
243372
243389
  "use strict";
243373
243390
  init_src();
243374
- import_node_crypto60 = require("node:crypto");
243391
+ import_node_crypto61 = require("node:crypto");
243375
243392
  }
243376
243393
  });
243377
243394
 
@@ -244156,7 +244173,7 @@ function nodesDomain(deps) {
244156
244173
  }
244157
244174
  deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
244158
244175
  } else {
244159
- nodeId = `node-${(0, import_node_crypto61.randomUUID)().slice(0, 8)}`;
244176
+ nodeId = `node-${(0, import_node_crypto62.randomUUID)().slice(0, 8)}`;
244160
244177
  deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
244161
244178
  }
244162
244179
  const existingNode = await deps.nodeStore.getNode(nodeId);
@@ -244406,16 +244423,16 @@ function normalizeGatewayUrl(raw) {
244406
244423
  }
244407
244424
  }
244408
244425
  function newNodeId() {
244409
- return "node-" + (0, import_node_crypto61.randomUUID)().replace(/-/g, "").slice(0, 12);
244426
+ return "node-" + (0, import_node_crypto62.randomUUID)().replace(/-/g, "").slice(0, 12);
244410
244427
  }
244411
- var import_node_crypto61, import_node_fs18, import_node_url6, import_node_path22, NODE_NAME_MAX_LENGTH;
244428
+ var import_node_crypto62, import_node_fs18, import_node_url6, import_node_path22, NODE_NAME_MAX_LENGTH;
244412
244429
  var init_routes7 = __esm({
244413
244430
  "../server/src/domains/nodes/routes.ts"() {
244414
244431
  "use strict";
244415
244432
  init_src();
244416
244433
  init_faults();
244417
244434
  init_runtime_status();
244418
- import_node_crypto61 = require("node:crypto");
244435
+ import_node_crypto62 = require("node:crypto");
244419
244436
  import_node_fs18 = require("node:fs");
244420
244437
  import_node_url6 = require("node:url");
244421
244438
  import_node_path22 = require("node:path");
@@ -244912,9 +244929,9 @@ var init_types4 = __esm({
244912
244929
  // ../server/src/domains/roles/index.ts
244913
244930
  function rolesDomain(deps) {
244914
244931
  return (router) => {
244915
- router.get("/api/roles", async () => {
244932
+ router.get("/api/roles", async (req) => {
244916
244933
  const roles = await deps.admin.list();
244917
- const usageByRole = await deps.admin.usageMany(roles.map((r) => r.name));
244934
+ const usageByRole = await deps.admin.usageMany(roles.map((r) => r.name), req.auth.companyId);
244918
244935
  const items = roles.map((r) => {
244919
244936
  const u = usageByRole[r.name];
244920
244937
  return {
@@ -244933,7 +244950,7 @@ function rolesDomain(deps) {
244933
244950
  if (!name) return { status: 400, body: { error: "missing name" } };
244934
244951
  const roles = await deps.admin.list();
244935
244952
  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) } };
244953
+ return { status: 200, body: { usage: await deps.admin.usage(name, req.auth.companyId) } };
244937
244954
  });
244938
244955
  router.post("/api/roles", async (req) => {
244939
244956
  const r = await deps.admin.add(req.body ?? {}, req.auth.actor);
@@ -245689,6 +245706,12 @@ var init_notification_reconciler = __esm({
245689
245706
  const ctx = await this.deps.load(companyId);
245690
245707
  if (!ctx) return EMPTY;
245691
245708
  const stats = await this.reconcileWith(companyId, st, ctx);
245709
+ if (stats.notified) {
245710
+ try {
245711
+ this.deps.onNotified?.(companyId, stats.notified);
245712
+ } catch {
245713
+ }
245714
+ }
245692
245715
  const tookMs = this.now - startedAt;
245693
245716
  if (tookMs > SLOW_RECONCILE_MS) {
245694
245717
  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 +245735,7 @@ var init_notification_reconciler = __esm({
245712
245735
  const nowMs = this.now;
245713
245736
  const nowIso = new Date(nowMs).toISOString();
245714
245737
  const stats = { inserted: 0, refreshed: 0, closed: 0, pending: 0 };
245738
+ const notified = /* @__PURE__ */ new Set();
245715
245739
  const ttl = this.deps.snapshotTtlMs ?? 5 * 6e4;
245716
245740
  const loadSnapshot2 = async (wid) => {
245717
245741
  const hit = st.snaps.get(wid);
@@ -245789,6 +245813,7 @@ var init_notification_reconciler = __esm({
245789
245813
  });
245790
245814
  st.lastSeenAt.set(inserted.id, nowIso);
245791
245815
  stats.inserted++;
245816
+ notified.add(c.recipient);
245792
245817
  }
245793
245818
  const eventsOf = /* @__PURE__ */ new Map();
245794
245819
  const cancelledOf = /* @__PURE__ */ new Map();
@@ -245805,7 +245830,7 @@ var init_notification_reconciler = __esm({
245805
245830
  st.lastSeenAt.delete(row.id);
245806
245831
  }
245807
245832
  stats.pending = current.size;
245808
- stats.notices = await this.reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2);
245833
+ stats.notices = await this.reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2, notified);
245809
245834
  if (nowMs - st.lastPurgeAt > (this.deps.purgeEveryMs ?? 6 * 36e5)) {
245810
245835
  st.lastPurgeAt = nowMs;
245811
245836
  const purged = await ctx.store.purgeBefore(new Date(nowMs - (this.deps.retentionMs ?? 90 * DAY2)).toISOString());
@@ -245814,6 +245839,7 @@ var init_notification_reconciler = __esm({
245814
245839
  for (const [id, d] of st.drafts) if (nowMs - d.at > DRAFT_OUTCOME_TTL_MS) st.drafts.delete(id);
245815
245840
  if (waitingForGrace) this.schedule(companyId, this.graceMs);
245816
245841
  st.primed = true;
245842
+ if (notified.size > 0) stats.notified = [...notified];
245817
245843
  return stats;
245818
245844
  }
245819
245845
  async judge(st, ctx, model, row, nowMs, nowIso, eventsOf, cancelledOf) {
@@ -245855,7 +245881,7 @@ var init_notification_reconciler = __esm({
245855
245881
  * 早就结束的任务不能在上线那一刻集体「任务已完成」一遍。之后每拍新看到的变化都发。
245856
245882
  * 来源键 = `<种类>:<工单>@<那件事的 seq>`:同一件事重启后再算一遍撞唯一约束即收手;任务重开后再完成是新的一件事。
245857
245883
  */
245858
- async reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2) {
245884
+ async reconcileTaskNotices(st, ctx, model, nowMs, loadSnapshot2, notified) {
245859
245885
  const store = ctx.engineStore;
245860
245886
  if (!store) return 0;
245861
245887
  const members = new Set(ctx.humans);
@@ -245877,6 +245903,7 @@ var init_notification_reconciler = __esm({
245877
245903
  ...trigger ? { actorId: trigger } : {},
245878
245904
  enteredAt: new Date(rec2.createdAt).toISOString()
245879
245905
  });
245906
+ notified.add(recipient);
245880
245907
  sent++;
245881
245908
  }
245882
245909
  };
@@ -246072,7 +246099,7 @@ function createBundle(root, target, input) {
246072
246099
  }
246073
246100
  }
246074
246101
  const bytes2 = fs28.statSync(absBundle).size;
246075
- const digest = (0, import_node_crypto62.createHash)("sha256").update(fs28.readFileSync(absBundle)).digest("hex");
246102
+ const digest = (0, import_node_crypto63.createHash)("sha256").update(fs28.readFileSync(absBundle)).digest("hex");
246076
246103
  const relBase = `inputs/git-bundles/${safeRepo}-${commit.slice(0, 12)}`;
246077
246104
  return {
246078
246105
  absoluteBundlePath: absBundle,
@@ -246168,12 +246195,12 @@ function classifyGitError(fallback, err, where) {
246168
246195
  function oneLine2(msg) {
246169
246196
  return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
246170
246197
  }
246171
- var import_node_child_process17, import_node_crypto62, fs28, os7, path25, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
246198
+ var import_node_child_process17, import_node_crypto63, fs28, os7, path25, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
246172
246199
  var init_readonly_bundle = __esm({
246173
246200
  "../server/src/git/readonly-bundle.ts"() {
246174
246201
  "use strict";
246175
246202
  import_node_child_process17 = require("node:child_process");
246176
- import_node_crypto62 = require("node:crypto");
246203
+ import_node_crypto63 = require("node:crypto");
246177
246204
  fs28 = __toESM(require("node:fs"), 1);
246178
246205
  os7 = __toESM(require("node:os"), 1);
246179
246206
  path25 = __toESM(require("node:path"), 1);
@@ -246194,7 +246221,7 @@ var init_readonly_bundle = __esm({
246194
246221
  // ../server/src/domains/collab/create-seeded-workorder.ts
246195
246222
  function makeSeededWorkorderCreator(deps) {
246196
246223
  const locks = createKeyedMutex();
246197
- const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto63.randomUUID)().slice(0, 8)}`);
246224
+ const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto64.randomUUID)().slice(0, 8)}`);
246198
246225
  const create = async (input) => {
246199
246226
  const company = input.companyId && deps.resolveCompany ? await deps.resolveCompany(input.companyId) : void 0;
246200
246227
  const kernel = company?.kernel ?? deps.kernel;
@@ -246281,7 +246308,7 @@ function makeSeededWorkorderCreator(deps) {
246281
246308
  return await finishCreation({ workspace, rootArtifactId: planned.rootArtifactId, spawned: planned.spawned });
246282
246309
  };
246283
246310
  return async (input) => {
246284
- const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0, import_node_crypto63.randomUUID)()}`);
246311
+ const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0, import_node_crypto64.randomUUID)()}`);
246285
246312
  try {
246286
246313
  return await create(input);
246287
246314
  } finally {
@@ -246290,7 +246317,7 @@ function makeSeededWorkorderCreator(deps) {
246290
246317
  };
246291
246318
  }
246292
246319
  function workspaceForKey(key2) {
246293
- return `ws:wo-${(0, import_node_crypto63.createHash)("sha256").update(key2).digest("hex").slice(0, 8)}`;
246320
+ return `ws:wo-${(0, import_node_crypto64.createHash)("sha256").update(key2).digest("hex").slice(0, 8)}`;
246294
246321
  }
246295
246322
  function existingWorkorder(snapshot, workspace, actor) {
246296
246323
  if (!snapshot?.nodes.length) return null;
@@ -246302,11 +246329,11 @@ function existingWorkorder(snapshot, workspace, actor) {
246302
246329
  spawned: snapshot.nodes.map((node2) => ({ id: node2.id, type: node2.type, owner: node2.assigneeActorId ?? actor }))
246303
246330
  };
246304
246331
  }
246305
- var import_node_crypto63;
246332
+ var import_node_crypto64;
246306
246333
  var init_create_seeded_workorder = __esm({
246307
246334
  "../server/src/domains/collab/create-seeded-workorder.ts"() {
246308
246335
  "use strict";
246309
- import_node_crypto63 = require("node:crypto");
246336
+ import_node_crypto64 = require("node:crypto");
246310
246337
  init_uncategorized_project();
246311
246338
  init_src();
246312
246339
  init_planner();
@@ -247809,12 +247836,12 @@ function stateFromAttempt(attempt, handoff, checkpoint, now, stalledAfterMs, ope
247809
247836
  if (attempt.status === "no-output") return handoff?.unresolvedIssues.length ? "blocked" : "no_change";
247810
247837
  return "failed";
247811
247838
  }
247812
- var import_node_crypto64, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
247839
+ var import_node_crypto65, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
247813
247840
  var init_service9 = __esm({
247814
247841
  "../server/src/domains/execution-continuity/service.ts"() {
247815
247842
  "use strict";
247816
247843
  init_src();
247817
- import_node_crypto64 = require("node:crypto");
247844
+ import_node_crypto65 = require("node:crypto");
247818
247845
  init_src7();
247819
247846
  BLOCKING_STATES = /* @__PURE__ */ new Set(["stalled", "failed", "blocked"]);
247820
247847
  HANDOFF_OUTCOMES2 = /* @__PURE__ */ new Set(["succeeded", "no-output", "failed", "cancelled", "timeout", "orphaned"]);
@@ -248045,7 +248072,7 @@ var init_service9 = __esm({
248045
248072
  if (typeof expectedHash !== "string" || !this.readBundleFile) return null;
248046
248073
  const injectedResume = this.readBundleFile(attempt.id, "execution/RESUME.md");
248047
248074
  if (!injectedResume) return null;
248048
- const actualHash = (0, import_node_crypto64.createHash)("sha256").update(injectedResume).digest("hex");
248075
+ const actualHash = (0, import_node_crypto65.createHash)("sha256").update(injectedResume).digest("hex");
248049
248076
  if (actualHash !== expectedHash) return null;
248050
248077
  const recoverySnapshot = parseResumePackSnapshot(injectedResume);
248051
248078
  if (!recoverySnapshot || recoverySnapshot.scenario !== "redispatch" || !recoverySnapshot.previousAttempt || recoverySnapshot.node.nodeId !== attempt.nodeId || recoverySnapshot.jobKey !== attempt.jobKey || recoverySnapshot.part !== attempt.part) return null;
@@ -248789,6 +248816,87 @@ var init_reply_anchors = __esm({
248789
248816
  }
248790
248817
  });
248791
248818
 
248819
+ // ../server/src/domains/chat-sessions/insert-status.ts
248820
+ async function resolveInsertStatus(deps, chatSessionId, clientKey) {
248821
+ const id = insertRequestId(chatSessionId, clientKey);
248822
+ if (!deps.store.getPendingMessage) return { status: "uncertain" };
248823
+ let row = await deps.store.getPendingMessage(chatSessionId, id);
248824
+ if (row?.state !== "delivering") return { status: insertStatusOfRow(row) };
248825
+ if (deps.isTurnRunning(chatSessionId)) return { status: "in-flight" };
248826
+ if (isInsertInflight(id)) {
248827
+ await waitForInflightInsert(id, deps.settleWaitMs ?? 1e4);
248828
+ row = await deps.store.getPendingMessage(chatSessionId, id);
248829
+ return { status: insertStatusOfRow(row) };
248830
+ }
248831
+ const running = settlingOrphans.get(id);
248832
+ if (running) return running;
248833
+ const settling = settleOrphan(deps, chatSessionId, row).finally(() => {
248834
+ settlingOrphans.delete(id);
248835
+ });
248836
+ settlingOrphans.set(id, settling);
248837
+ return settling;
248838
+ }
248839
+ async function settleOrphan(deps, chatSessionId, row) {
248840
+ const ref2 = row.deliveryRef;
248841
+ 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" };
248842
+ const trace = ref2 && deps.store.listPendingTrace ? await deps.store.listPendingTrace(chatSessionId).catch(() => []) : [];
248843
+ const batch = trace.filter((r) => r.state === "delivering" && r.deliveryRef?.runtimeKey === ref2?.runtimeKey);
248844
+ if (!batch.some((r) => r.id === row.id)) batch.push(row);
248845
+ const ids2 = batch.map((r) => r.id);
248846
+ deps.log?.(`[chat-insert] \u5B64\u513F\u63D2\u5165\u7ED3\u7B97 sid=${chatSessionId} row=${row.id} \u2192 ${answer.status}${answer.reason ? `(${answer.reason})` : ""}`);
248847
+ if (answer.status === "consumed") {
248848
+ await backfill(deps, chatSessionId, batch, row).catch((err) => {
248849
+ 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)}`);
248850
+ });
248851
+ await deps.store.markPendingMessages?.(chatSessionId, ids2, "delivered", "delivered:node-confirmed-orphan");
248852
+ return { status: "inserted" };
248853
+ }
248854
+ if (answer.status === "not-consumed") {
248855
+ await deps.store.markPendingMessages?.(chatSessionId, [row.id], "cancelled", "client-gone:not-consumed");
248856
+ const rest = ids2.filter((x2) => x2 !== row.id);
248857
+ if (rest.length) await deps.store.markPendingMessages?.(chatSessionId, rest, "queued", `not-consumed:${answer.reason ?? ""}`);
248858
+ if (row.clientKey) await deps.landUndelivered?.({ clientKey: row.clientKey, rows: [row], note: INSERT_RETURNED_NOTE });
248859
+ return { status: "not-inserted" };
248860
+ }
248861
+ await deps.store.markPendingMessages?.(chatSessionId, ids2, "unconfirmed", `unconfirmed:${answer.reason ?? "unknown"}`);
248862
+ if (row.clientKey) {
248863
+ await deps.landUndelivered?.({ clientKey: row.clientKey, rows: [...batch].sort((a, b2) => a.seq - b2.seq), note: INSERT_UNCERTAIN_NOTE });
248864
+ }
248865
+ return { status: "uncertain" };
248866
+ }
248867
+ async function backfill(deps, chatSessionId, batch, row) {
248868
+ if (!deps.items) return;
248869
+ const ref2 = row.deliveryRef;
248870
+ const sorted = [...batch].sort((a, b2) => a.seq - b2.seq);
248871
+ const ledger = new ChatItemLedger({
248872
+ items: deps.items,
248873
+ versionSeed: await deps.items.sessionVersionCursor(chatSessionId).catch(() => 0),
248874
+ sessionId: chatSessionId,
248875
+ turnId: ref2?.turnId ?? `insert-backfill:${row.id}`,
248876
+ ...deps.log ? { log: deps.log } : {}
248877
+ });
248878
+ const text7 = sorted.map((m2) => m2.text).filter(Boolean).join("\n\n");
248879
+ const attachments = sorted.flatMap((m2) => (m2.attachments ?? []).map((a) => ({
248880
+ name: a.name,
248881
+ ...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
248882
+ ...a.contentType !== void 0 ? { contentType: a.contentType } : {}
248883
+ })));
248884
+ const clientKeys = sorted.map((m2) => m2.clientKey).filter((k2) => !!k2);
248885
+ ledger.recordUserInput(text7, attachments, clientKeys, ref2?.ord !== void 0 ? { ord: ref2.ord } : void 0);
248886
+ await ledger.drain();
248887
+ if (ledger.failures > 0) throw new Error("chat_items \u5199\u5165\u5931\u8D25");
248888
+ }
248889
+ var settlingOrphans;
248890
+ var init_insert_status = __esm({
248891
+ "../server/src/domains/chat-sessions/insert-status.ts"() {
248892
+ "use strict";
248893
+ init_chat_item_ledger();
248894
+ init_chat_insert_evidence();
248895
+ init_append_now();
248896
+ settlingOrphans = /* @__PURE__ */ new Map();
248897
+ }
248898
+ });
248899
+
248792
248900
  // ../server/src/domains/chat-sessions/agent-history.ts
248793
248901
  async function resolveChatHistoryViewer(auth, getSession) {
248794
248902
  if (isHumanActorId(auth.actor)) return { kind: "human", actor: auth.actor };
@@ -248991,6 +249099,29 @@ function throwWorkdirError(code2) {
248991
249099
  }
248992
249100
  }
248993
249101
  function createChatSessionsDomain(opts) {
249102
+ const settleInFlightInserts = async ({ store: store2, items, chatSessionId }) => {
249103
+ const rows = await store2.listInFlightInserts(chatSessionId);
249104
+ for (const row of rows) {
249105
+ if (!row.clientKey) continue;
249106
+ await resolveInsertStatus({
249107
+ store: store2,
249108
+ isTurnRunning: (id) => opts.liveChat?.isRunning(id) ?? false,
249109
+ ...opts.confirmInputReceipt ? { confirm: opts.confirmInputReceipt } : {},
249110
+ items,
249111
+ settleWaitMs: INFLIGHT_INSERT_SETTLE_WAIT_MS,
249112
+ landUndelivered: ({ clientKey, rows: batch, note }) => landUndeliveredInsert({
249113
+ store: store2,
249114
+ itemStore: items,
249115
+ chatSessionId,
249116
+ clientKey,
249117
+ text: batch.map((m2) => m2.text).filter(Boolean).join("\n\n"),
249118
+ attachments: batch.flatMap((m2) => m2.attachments ?? []),
249119
+ note
249120
+ }),
249121
+ log: (m2) => console.warn(m2)
249122
+ }, chatSessionId, row.clientKey);
249123
+ }
249124
+ };
248994
249125
  const { store, registry: registry2 } = opts;
248995
249126
  const bindingFor = opts.resolveBinding ?? bindingResolverFromRegistry(registry2);
248996
249127
  async function storeFor(req) {
@@ -249123,7 +249254,7 @@ function createChatSessionsDomain(opts) {
249123
249254
  if (!text7.trim()) throw new ApiError(400, "BAD_REQUEST", "text required");
249124
249255
  const now = Date.now();
249125
249256
  sweepDrafts(now);
249126
- const id = `cd_${(0, import_node_crypto65.randomUUID)()}`;
249257
+ const id = `cd_${(0, import_node_crypto66.randomUUID)()}`;
249127
249258
  drafts.set(id, { text: text7, actor: req.auth.actor, expiresAt: now + DRAFT_TTL_MS });
249128
249259
  return { status: 201, body: { id, expiresInMs: DRAFT_TTL_MS } };
249129
249260
  });
@@ -249200,7 +249331,7 @@ function createChatSessionsDomain(opts) {
249200
249331
  const runtimeId = agentDefault.binding?.nodeId ?? "unknown";
249201
249332
  const now = (/* @__PURE__ */ new Date()).toISOString();
249202
249333
  const session = {
249203
- id: (0, import_node_crypto65.randomUUID)(),
249334
+ id: (0, import_node_crypto66.randomUUID)(),
249204
249335
  humanActorId: req.auth.actor,
249205
249336
  // 注:这里**刻意不写 companyId**。新会话要不要带公司归属,按 ws:wo-6d588f8e 的 ADR
249206
249337
  // (每公司 schema、最终移除表内 company 列)统一定,不在本节点自行发明。
@@ -249319,19 +249450,6 @@ function createChatSessionsDomain(opts) {
249319
249450
  });
249320
249451
  return { status: 200, body: await store2.getSession(req.params.id) };
249321
249452
  });
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
249453
  router.delete("/api/chat-sessions/:id", async (req) => {
249336
249454
  const store2 = await storeFor(req);
249337
249455
  const session = await store2.getSession(req.params.id);
@@ -249348,7 +249466,7 @@ function createChatSessionsDomain(opts) {
249348
249466
  if (body2.role !== "user" && body2.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
249349
249467
  const role = body2.role;
249350
249468
  const msg = await store2.appendMessage({
249351
- id: (0, import_node_crypto65.randomUUID)(),
249469
+ id: (0, import_node_crypto66.randomUUID)(),
249352
249470
  sessionId: req.params.id,
249353
249471
  role,
249354
249472
  content: role === "user" ? stripInjectedChatContext(body2.content) : body2.content,
@@ -249390,7 +249508,7 @@ function createChatSessionsDomain(opts) {
249390
249508
  const known = key2 ? cur.find((x2) => x2.clientKey === key2) : void 0;
249391
249509
  if (!known && cur.length >= QUEUE_MAX) throw new ApiError(409, "QUEUE_FULL", `\u961F\u5217\u5DF2\u6EE1\uFF08\u4E0A\u9650 ${QUEUE_MAX} \u6761\uFF09`);
249392
249510
  const item = await store2.enqueuePendingMessage({
249393
- id: (0, import_node_crypto65.randomUUID)(),
249511
+ id: (0, import_node_crypto66.randomUUID)(),
249394
249512
  chatSessionId: sid,
249395
249513
  text: text7,
249396
249514
  ...attachments.length ? { attachments } : {},
@@ -249440,6 +249558,11 @@ function createChatSessionsDomain(opts) {
249440
249558
  const stale = Number.isFinite(startedAt) && Date.now() - startedAt >= LINK_WINDOWS.chatTurnPhaseStaleAfterMs;
249441
249559
  return { turnId: activeTurnRow.id, phase: stale ? "recovering" : "running" };
249442
249560
  })();
249561
+ if (sinceVersion === 0 && beforeOrd === void 0 && session?.humanActorId === req.auth.actor && store2.listInFlightInserts) {
249562
+ await settleInFlightInserts({ store: store2, items, chatSessionId }).catch((e) => {
249563
+ 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)}`);
249564
+ });
249565
+ }
249443
249566
  const snapshotEntries = [];
249444
249567
  let nextSinceVersion = sinceVersion;
249445
249568
  let hasMoreBefore = false;
@@ -250238,12 +250361,12 @@ async function legacySendFailureCards(entries, deps) {
250238
250361
  }
250239
250362
  return out;
250240
250363
  }
250241
- var import_node_crypto65, DEFAULT_SNAPSHOT_ITEMS, MAX_SNAPSHOT_ITEMS, PROJECTED_CARD_LIMIT, SUBMISSION_NOT_DELIVERED_NOTE, SUBMISSION_UNCONFIRMED_NOTE, LEGACY_CARD_LIMIT;
250364
+ 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
250365
  var init_chat_sessions2 = __esm({
250243
250366
  "../server/src/domains/chat-sessions/index.ts"() {
250244
250367
  "use strict";
250245
250368
  init_file_limits2();
250246
- import_node_crypto65 = require("node:crypto");
250369
+ import_node_crypto66 = require("node:crypto");
250247
250370
  init_src();
250248
250371
  init_chat_session();
250249
250372
  init_persistent_files();
@@ -250259,6 +250382,8 @@ var init_chat_sessions2 = __esm({
250259
250382
  init_service3();
250260
250383
  init_reply_anchors();
250261
250384
  init_injected_context();
250385
+ init_insert_status();
250386
+ init_insert_undelivered();
250262
250387
  init_agent_history();
250263
250388
  init_deletion();
250264
250389
  init_chat_turn_gate();
@@ -250270,6 +250395,7 @@ var init_chat_sessions2 = __esm({
250270
250395
  init_chat_submission();
250271
250396
  init_project_bundle();
250272
250397
  DEFAULT_SNAPSHOT_ITEMS = 400;
250398
+ INFLIGHT_INSERT_SETTLE_WAIT_MS = 6e3;
250273
250399
  MAX_SNAPSHOT_ITEMS = 1e3;
250274
250400
  PROJECTED_CARD_LIMIT = 10;
250275
250401
  SUBMISSION_NOT_DELIVERED_NOTE = "\u8FD9\u6761\u6D88\u606F\u6CA1\u6709\u53D1\u51FA\uFF0C\u53EF\u4EE5\u91CD\u8BD5";
@@ -251700,7 +251826,7 @@ function busyError(chatSessionId, blockedBy) {
251700
251826
  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
251827
  }
251702
251828
  function genWebhookToken() {
251703
- return `owt_${(0, import_node_crypto66.randomBytes)(32).toString("base64url")}`;
251829
+ return `owt_${(0, import_node_crypto67.randomBytes)(32).toString("base64url")}`;
251704
251830
  }
251705
251831
  function validateTitleTemplate(tpl) {
251706
251832
  const residue = tpl.replace(DATE_TOKEN, "");
@@ -251756,11 +251882,11 @@ function appendSourceNote(brief, automation, source, atIso) {
251756
251882
  ---
251757
251883
  \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
251884
  }
251759
- var import_node_crypto66, DATE_TOKEN, AutomationsService, EVENT_RETRY_BASE_MS, EVENT_RETRY_MAX_MS, EVENT_RETRY_MAX_ATTEMPTS, eventAttempts, eventLastAttemptAt, eventLastError, CHAT_REPLY_MAX;
251885
+ 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
251886
  var init_service10 = __esm({
251761
251887
  "../server/src/domains/automations/service.ts"() {
251762
251888
  "use strict";
251763
- import_node_crypto66 = require("node:crypto");
251889
+ import_node_crypto67 = require("node:crypto");
251764
251890
  init_src();
251765
251891
  init_registry3();
251766
251892
  init_attribution();
@@ -252574,11 +252700,11 @@ function verifySignature(rawBody, headers, secret) {
252574
252700
  if (!secret) return "not_required";
252575
252701
  const given = header1(headers, "x-hub-signature-256");
252576
252702
  if (!given) return "missing";
252577
- const expected = `sha256=${(0, import_node_crypto67.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
252703
+ const expected = `sha256=${(0, import_node_crypto68.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
252578
252704
  const a = Buffer.from(given);
252579
252705
  const b2 = Buffer.from(expected);
252580
252706
  if (a.length !== b2.length) return "invalid";
252581
- return (0, import_node_crypto67.timingSafeEqual)(a, b2) ? "valid" : "invalid";
252707
+ return (0, import_node_crypto68.timingSafeEqual)(a, b2) ? "valid" : "invalid";
252582
252708
  }
252583
252709
  function eventAllowed(filters, envelope) {
252584
252710
  if (!filters || filters.length === 0) return true;
@@ -252608,11 +252734,11 @@ function splitEvent(envelope) {
252608
252734
  }
252609
252735
  return { eventName, actionCandidates: candidates };
252610
252736
  }
252611
- var import_node_crypto67, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
252737
+ var import_node_crypto68, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
252612
252738
  var init_webhook = __esm({
252613
252739
  "../server/src/domains/automations/webhook.ts"() {
252614
252740
  "use strict";
252615
- import_node_crypto67 = require("node:crypto");
252741
+ import_node_crypto68 = require("node:crypto");
252616
252742
  MAX_BODY_BYTES = 256 * 1024;
252617
252743
  AutomationWebhookService = class {
252618
252744
  store;
@@ -253764,7 +253890,7 @@ function playbooksDomain(opts) {
253764
253890
  opts.overrides.set(companyOf(req), ref2, nodeKey, nextOverride);
253765
253891
  try {
253766
253892
  await opts.audit?.({
253767
- id: `reg_${(0, import_node_crypto68.randomUUID)()}`,
253893
+ id: `reg_${(0, import_node_crypto69.randomUUID)()}`,
253768
253894
  actor: req.auth.actor,
253769
253895
  kind: "registry_change",
253770
253896
  target: `playbook:${ref2}#${nodeKey}`,
@@ -253781,11 +253907,11 @@ function playbooksDomain(opts) {
253781
253907
  });
253782
253908
  };
253783
253909
  }
253784
- var import_node_crypto68;
253910
+ var import_node_crypto69;
253785
253911
  var init_routes12 = __esm({
253786
253912
  "../server/src/domains/playbooks/routes.ts"() {
253787
253913
  "use strict";
253788
- import_node_crypto68 = require("node:crypto");
253914
+ import_node_crypto69 = require("node:crypto");
253789
253915
  init_router();
253790
253916
  init_registry3();
253791
253917
  init_planner();
@@ -253914,17 +254040,17 @@ function completionFingerprint(workspace, members) {
253914
254040
  workspace,
253915
254041
  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
254042
  });
253917
- return (0, import_node_crypto69.createHash)("sha256").update(canonical2).digest("hex");
254043
+ return (0, import_node_crypto70.createHash)("sha256").update(canonical2).digest("hex");
253918
254044
  }
253919
254045
  function eventConsumptionKey(args) {
253920
254046
  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, import_node_crypto69.createHash)("sha256").update(raw).digest("hex")}`;
254047
+ return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0, import_node_crypto70.createHash)("sha256").update(raw).digest("hex")}`;
253922
254048
  }
253923
- var import_node_crypto69, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
254049
+ var import_node_crypto70, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
253924
254050
  var init_project_event_poller = __esm({
253925
254051
  "../server/src/automations/project-event-poller.ts"() {
253926
254052
  "use strict";
253927
- import_node_crypto69 = require("node:crypto");
254053
+ import_node_crypto70 = require("node:crypto");
253928
254054
  EVENT_KEY_VERSION = "v1";
253929
254055
  EMPTY_METRICS = () => ({
253930
254056
  scanDurationMs: 0,
@@ -254134,7 +254260,7 @@ function queryInputReceipt(hub, nodeId, dispatchId, clientMessageKey, pending, t
254134
254260
  const viaSession = hub.hasSession?.(dispatchId) === true;
254135
254261
  const supported = viaSession ? hub.supportsInputReceiptQuery?.(dispatchId) === true : daemonMetaOf(hub, nodeId)?.supportsInputReceiptQuery === true;
254136
254262
  if (!supported) return Promise.resolve({ status: "unknown", reason: "unsupported" });
254137
- const requestId = (0, import_node_crypto70.randomUUID)();
254263
+ const requestId = (0, import_node_crypto71.randomUUID)();
254138
254264
  return new Promise((resolve12) => {
254139
254265
  const timer = setTimeout(() => {
254140
254266
  pending.delete(requestId);
@@ -254196,7 +254322,7 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
254196
254322
  if (input.requireConsumptionReceipt && !hub.supportsInputConsumptionReceipts?.(dispatchId)) {
254197
254323
  return Promise.resolve({ accepted: false, reason: "consumption-unsupported" });
254198
254324
  }
254199
- const requestId = (0, import_node_crypto70.randomUUID)();
254325
+ const requestId = (0, import_node_crypto71.randomUUID)();
254200
254326
  const sent = routeToSession(hub, nodeId, dispatchId, { type: "append_input", dispatchId, input, requestId });
254201
254327
  if (!sent) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
254202
254328
  return new Promise((resolve12) => {
@@ -254209,11 +254335,11 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
254209
254335
  entry.appendWaiters.push({ requestId, requireConsumptionReceipt: input.requireConsumptionReceipt, resolve: resolve12, timer });
254210
254336
  });
254211
254337
  }
254212
- var import_node_crypto70, 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;
254338
+ 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
254339
  var init_daemon_adapter = __esm({
254214
254340
  "../server/src/daemon-adapter.ts"() {
254215
254341
  "use strict";
254216
- import_node_crypto70 = require("node:crypto");
254342
+ import_node_crypto71 = require("node:crypto");
254217
254343
  init_src();
254218
254344
  STASH_TTL_MS = 5 * 6e4;
254219
254345
  STASH_MAX_FRAMES_PER_ID = 1e4;
@@ -254653,7 +254779,7 @@ var init_daemon_adapter = __esm({
254653
254779
  async spawn(job) {
254654
254780
  const nodeId = job.binding?.nodeId;
254655
254781
  if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
254656
- const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto70.randomUUID)()}`;
254782
+ const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto71.randomUUID)()}`;
254657
254783
  if (job.dispatchId && this.pending.has(dispatchId)) {
254658
254784
  return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
254659
254785
  }
@@ -254909,7 +255035,7 @@ var init_daemon_adapter = __esm({
254909
255035
  return daemon?.meta.supportsWorkdirWalk === true;
254910
255036
  }
254911
255037
  request(nodeId, buildFrame) {
254912
- const requestId = (0, import_node_crypto70.randomUUID)();
255038
+ const requestId = (0, import_node_crypto71.randomUUID)();
254913
255039
  const sent = this.hub.dispatch(nodeId, buildFrame(requestId));
254914
255040
  if (!sent) return Promise.resolve({ ok: false, code: "NODE_OFFLINE" });
254915
255041
  return new Promise((resolve12) => {
@@ -255017,13 +255143,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
255017
255143
  if (sha(body2) === lastPushedHash) return { kind: "echo" };
255018
255144
  return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
255019
255145
  }
255020
- var import_node_crypto71, sha, enc2, dec, MirrorEngine, MemoryMirrorStateStore, MapMirrorIdentities;
255146
+ var import_node_crypto72, sha, enc2, dec, MirrorEngine, MemoryMirrorStateStore, MapMirrorIdentities;
255021
255147
  var init_engine = __esm({
255022
255148
  "../server/src/mirror/engine.ts"() {
255023
255149
  "use strict";
255024
- import_node_crypto71 = require("node:crypto");
255150
+ import_node_crypto72 = require("node:crypto");
255025
255151
  init_src();
255026
- sha = (s2) => (0, import_node_crypto71.createHash)("sha256").update(s2, "utf8").digest("hex");
255152
+ sha = (s2) => (0, import_node_crypto72.createHash)("sha256").update(s2, "utf8").digest("hex");
255027
255153
  enc2 = (s2) => new TextEncoder().encode(s2);
255028
255154
  dec = (b2) => new TextDecoder().decode(b2);
255029
255155
  MirrorEngine = class {
@@ -255304,11 +255430,11 @@ function humanExitCause(exit3) {
255304
255430
  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
255431
  return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
255306
255432
  }
255307
- var import_node_crypto72, 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;
255433
+ 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
255434
  var init_worker = __esm({
255309
255435
  "../server/src/coordinator/worker.ts"() {
255310
255436
  "use strict";
255311
- import_node_crypto72 = require("node:crypto");
255437
+ import_node_crypto73 = require("node:crypto");
255312
255438
  init_src7();
255313
255439
  init_identity();
255314
255440
  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 +255704,7 @@ ${HIGH_RISK_COMMANDS}`;
255578
255704
  return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
255579
255705
  }
255580
255706
  evaluationKey(kind, artifactId, evidence) {
255581
- const fingerprint2 = (0, import_node_crypto72.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
255707
+ const fingerprint2 = (0, import_node_crypto73.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
255582
255708
  return `${kind}:${artifactId}:${fingerprint2}`;
255583
255709
  }
255584
255710
  artifactEvidence(id) {
@@ -255967,8 +256093,8 @@ ${ctx.nodeFault}
255967
256093
  const taskWithRejections = rejectedSection ? `${task}
255968
256094
 
255969
256095
  ${rejectedSection}` : task;
255970
- const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto72.randomUUID)();
255971
- const coordinatorRunId = `coordinate:${(0, import_node_crypto72.randomUUID)()}`;
256096
+ const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto73.randomUUID)();
256097
+ const coordinatorRunId = `coordinate:${(0, import_node_crypto73.randomUUID)()}`;
255972
256098
  const taskWithContext = coordinatorContext ? [
255973
256099
  taskWithRejections,
255974
256100
  ``,
@@ -256012,7 +256138,7 @@ ${rejectedSection}` : task;
256012
256138
  const startedAtMs = Date.now();
256013
256139
  let trajectoryStarted = false;
256014
256140
  if (this.deps.trajectory) {
256015
- const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto72.createHash)("sha256").update(content3).digest("hex")]));
256141
+ const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto73.createHash)("sha256").update(content3).digest("hex")]));
256016
256142
  const session = {
256017
256143
  runId: coordinatorRunId,
256018
256144
  runtimeSessionId,
@@ -256223,11 +256349,11 @@ var init_pg_ident = __esm({
256223
256349
  });
256224
256350
 
256225
256351
  // ../storage/src/postgres.ts
256226
- var import_node_crypto73, ident4, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
256352
+ var import_node_crypto74, ident4, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
256227
256353
  var init_postgres = __esm({
256228
256354
  "../storage/src/postgres.ts"() {
256229
256355
  "use strict";
256230
- import_node_crypto73 = require("node:crypto");
256356
+ import_node_crypto74 = require("node:crypto");
256231
256357
  init_pg_ident();
256232
256358
  init_esm();
256233
256359
  init_src();
@@ -256407,7 +256533,7 @@ var init_postgres = __esm({
256407
256533
  return new _PostgresBlobStore(pool, schema);
256408
256534
  }
256409
256535
  async put(bytes2) {
256410
- const hash3 = (0, import_node_crypto73.createHash)("sha256").update(bytes2).digest("hex");
256536
+ const hash3 = (0, import_node_crypto74.createHash)("sha256").update(bytes2).digest("hex");
256411
256537
  await this.pool.query(
256412
256538
  `INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
256413
256539
  [hash3, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
@@ -256455,7 +256581,7 @@ function stageAtLeast(stage, min2) {
256455
256581
  return STAGES.indexOf(stage) >= STAGES.indexOf(min2);
256456
256582
  }
256457
256583
  function newVariableId() {
256458
- return `var_${(0, import_node_crypto74.randomUUID)()}`;
256584
+ return `var_${(0, import_node_crypto75.randomUUID)()}`;
256459
256585
  }
256460
256586
  async function declareRecordsAware(db) {
256461
256587
  await db.query(`SELECT set_config('${RECORDS_AWARE_SETTING}', 'on', true)`);
@@ -256811,11 +256937,11 @@ async function listBindingTargetIds(db, s2, kind) {
256811
256937
  [kind]
256812
256938
  )).rows.map((x2) => x2.target_id);
256813
256939
  }
256814
- var import_node_crypto74, STAGES, RECORDS_AWARE_SETTING, markLockName;
256940
+ var import_node_crypto75, STAGES, RECORDS_AWARE_SETTING, markLockName;
256815
256941
  var init_variable_bindings = __esm({
256816
256942
  "../storage/src/variable-bindings.ts"() {
256817
256943
  "use strict";
256818
- import_node_crypto74 = require("node:crypto");
256944
+ import_node_crypto75 = require("node:crypto");
256819
256945
  init_src();
256820
256946
  STAGES = ["off", "dual", "read", "records"];
256821
256947
  RECORDS_AWARE_SETTING = "oasis.variable_records_aware";
@@ -266543,11 +266669,11 @@ var init_postgres_delegations = __esm({
266543
266669
  });
266544
266670
 
266545
266671
  // ../storage/src/postgres-nodes.ts
266546
- var import_node_crypto75, ident13, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToFault, rowToQuota, rowToRuntime;
266672
+ var import_node_crypto76, ident13, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToFault, rowToQuota, rowToRuntime;
266547
266673
  var init_postgres_nodes = __esm({
266548
266674
  "../storage/src/postgres-nodes.ts"() {
266549
266675
  "use strict";
266550
- import_node_crypto75 = require("node:crypto");
266676
+ import_node_crypto76 = require("node:crypto");
266551
266677
  init_pg_ident();
266552
266678
  init_esm();
266553
266679
  ident13 = (s2) => {
@@ -266897,7 +267023,7 @@ var init_postgres_nodes = __esm({
266897
267023
  return store;
266898
267024
  }
266899
267025
  issue(nodeId) {
266900
- const token = `ont_${(0, import_node_crypto75.randomBytes)(24).toString("base64url")}`;
267026
+ const token = `ont_${(0, import_node_crypto76.randomBytes)(24).toString("base64url")}`;
266901
267027
  this.cache.set(token, nodeId);
266902
267028
  void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
266903
267029
  return token;
@@ -267199,11 +267325,11 @@ var init_postgres_type_registry = __esm({
267199
267325
  });
267200
267326
 
267201
267327
  // ../storage/src/postgres-actor-memory.ts
267202
- var import_node_crypto76, matchClause, ident15, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
267328
+ var import_node_crypto77, matchClause, ident15, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
267203
267329
  var init_postgres_actor_memory = __esm({
267204
267330
  "../storage/src/postgres-actor-memory.ts"() {
267205
267331
  "use strict";
267206
- import_node_crypto76 = require("node:crypto");
267332
+ import_node_crypto77 = require("node:crypto");
267207
267333
  init_pg_ident();
267208
267334
  init_src();
267209
267335
  matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
@@ -267413,7 +267539,7 @@ var init_postgres_actor_memory = __esm({
267413
267539
  }
267414
267540
  async write(input, now) {
267415
267541
  if (input.memId === void 0) {
267416
- const memId = `mem:${(0, import_node_crypto76.randomUUID)()}`;
267542
+ const memId = `mem:${(0, import_node_crypto77.randomUUID)()}`;
267417
267543
  const r2 = await this.pool.query(
267418
267544
  `INSERT INTO ${this.s}.actor_memories
267419
267545
  (mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
@@ -267651,6 +267777,124 @@ var init_postgres_inbox_read = __esm({
267651
267777
  }
267652
267778
  });
267653
267779
 
267780
+ // ../storage/src/postgres-connector-auth-pending.ts
267781
+ var ident17, PostgresGithubAppPendingStore, PostgresConnectorAuthSnapshotStore;
267782
+ var init_postgres_connector_auth_pending = __esm({
267783
+ "../storage/src/postgres-connector-auth-pending.ts"() {
267784
+ "use strict";
267785
+ init_esm();
267786
+ init_pg_ident();
267787
+ ident17 = (s2) => {
267788
+ quoteIdent2(s2);
267789
+ return s2;
267790
+ };
267791
+ PostgresGithubAppPendingStore = class _PostgresGithubAppPendingStore {
267792
+ constructor(pool, schema) {
267793
+ this.pool = pool;
267794
+ this.s = `"${ident17(schema)}"`;
267795
+ }
267796
+ s;
267797
+ static async open(pool, schema = "public") {
267798
+ const s2 = ident17(schema);
267799
+ await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
267800
+ await pool.query(`
267801
+ CREATE TABLE IF NOT EXISTS "${s2}".github_app_pending (
267802
+ state text PRIMARY KEY,
267803
+ company_id text,
267804
+ data jsonb NOT NULL,
267805
+ created_at timestamptz NOT NULL,
267806
+ expires_at timestamptz NOT NULL
267807
+ )`);
267808
+ return new _PostgresGithubAppPendingStore(pool, schema);
267809
+ }
267810
+ async put(entry) {
267811
+ await this.pool.query(
267812
+ `DELETE FROM ${this.s}.github_app_pending WHERE expires_at < $1`,
267813
+ [new Date(entry.createdAtMs)]
267814
+ );
267815
+ await this.pool.query(
267816
+ `INSERT INTO ${this.s}.github_app_pending (state, company_id, data, created_at, expires_at)
267817
+ VALUES ($1, $2, $3::jsonb, $4, $5)
267818
+ ON CONFLICT (state) DO UPDATE SET company_id = EXCLUDED.company_id, data = EXCLUDED.data,
267819
+ created_at = EXCLUDED.created_at, expires_at = EXCLUDED.expires_at`,
267820
+ [
267821
+ entry.state,
267822
+ entry.companyId ?? null,
267823
+ JSON.stringify(entry.value),
267824
+ new Date(entry.createdAtMs),
267825
+ new Date(entry.expiresAtMs)
267826
+ ]
267827
+ );
267828
+ }
267829
+ async get(state, nowMs) {
267830
+ if (!state) return { status: "missing" };
267831
+ const r = await this.pool.query(
267832
+ `SELECT company_id, data, expires_at FROM ${this.s}.github_app_pending WHERE state = $1`,
267833
+ [state]
267834
+ );
267835
+ const row = r.rows[0];
267836
+ if (!row) return { status: "missing" };
267837
+ if (row.expires_at.getTime() < nowMs) return { status: "expired" };
267838
+ return { status: "found", value: { ...row.company_id ? { companyId: row.company_id } : {}, value: row.data } };
267839
+ }
267840
+ async patch(state, fields) {
267841
+ await this.pool.query(
267842
+ `UPDATE ${this.s}.github_app_pending SET data = data || $2::jsonb WHERE state = $1`,
267843
+ [state, JSON.stringify(fields)]
267844
+ );
267845
+ }
267846
+ };
267847
+ PostgresConnectorAuthSnapshotStore = class _PostgresConnectorAuthSnapshotStore {
267848
+ constructor(pool, schema) {
267849
+ this.pool = pool;
267850
+ this.s = `"${ident17(schema)}"`;
267851
+ }
267852
+ s;
267853
+ static async open(pool, schema = "public") {
267854
+ const s2 = ident17(schema);
267855
+ await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
267856
+ await pool.query(`
267857
+ CREATE TABLE IF NOT EXISTS "${s2}".connector_auth_snapshots (
267858
+ company_id text NOT NULL,
267859
+ actor_id text NOT NULL,
267860
+ connector_id text NOT NULL,
267861
+ rows jsonb NOT NULL,
267862
+ created_at timestamptz NOT NULL,
267863
+ expires_at timestamptz NOT NULL,
267864
+ PRIMARY KEY (company_id, actor_id, connector_id)
267865
+ )`);
267866
+ return new _PostgresConnectorAuthSnapshotStore(pool, schema);
267867
+ }
267868
+ async put(key2, rows, nowMs, expiresAtMs) {
267869
+ await this.pool.query(`DELETE FROM ${this.s}.connector_auth_snapshots WHERE expires_at < $1`, [new Date(nowMs)]);
267870
+ await this.pool.query(
267871
+ `INSERT INTO ${this.s}.connector_auth_snapshots (company_id, actor_id, connector_id, rows, created_at, expires_at)
267872
+ VALUES ($1, $2, $3, $4::jsonb, $5, $6)
267873
+ ON CONFLICT (company_id, actor_id, connector_id) DO UPDATE SET rows = EXCLUDED.rows,
267874
+ created_at = EXCLUDED.created_at, expires_at = EXCLUDED.expires_at`,
267875
+ [key2.companyId, key2.actorId, key2.connectorId, JSON.stringify(rows), new Date(nowMs), new Date(expiresAtMs)]
267876
+ );
267877
+ }
267878
+ async get(key2, nowMs) {
267879
+ const r = await this.pool.query(
267880
+ `SELECT rows, expires_at FROM ${this.s}.connector_auth_snapshots
267881
+ WHERE company_id = $1 AND actor_id = $2 AND connector_id = $3`,
267882
+ [key2.companyId, key2.actorId, key2.connectorId]
267883
+ );
267884
+ const row = r.rows[0];
267885
+ if (!row || row.expires_at.getTime() < nowMs) return void 0;
267886
+ return row.rows;
267887
+ }
267888
+ async delete(key2) {
267889
+ await this.pool.query(
267890
+ `DELETE FROM ${this.s}.connector_auth_snapshots WHERE company_id = $1 AND actor_id = $2 AND connector_id = $3`,
267891
+ [key2.companyId, key2.actorId, key2.connectorId]
267892
+ );
267893
+ }
267894
+ };
267895
+ }
267896
+ });
267897
+
267654
267898
  // ../storage/src/postgres-dispatches.ts
267655
267899
  function rowToRecord2(r) {
267656
267900
  return {
@@ -267672,18 +267916,18 @@ function rowToRecord2(r) {
267672
267916
  protocolRecoveryRound: r.protocol_recovery_round ?? null
267673
267917
  };
267674
267918
  }
267675
- var ident17, PostgresDispatchStore;
267919
+ var ident18, PostgresDispatchStore;
267676
267920
  var init_postgres_dispatches = __esm({
267677
267921
  "../storage/src/postgres-dispatches.ts"() {
267678
267922
  "use strict";
267679
- ident17 = (schema) => schema.replace(/[^a-zA-Z0-9_]/g, "");
267923
+ ident18 = (schema) => schema.replace(/[^a-zA-Z0-9_]/g, "");
267680
267924
  PostgresDispatchStore = class _PostgresDispatchStore {
267681
267925
  constructor(pool, s2) {
267682
267926
  this.pool = pool;
267683
267927
  this.s = s2;
267684
267928
  }
267685
267929
  static async open(pool, schema = "public") {
267686
- const s2 = ident17(schema);
267930
+ const s2 = ident18(schema);
267687
267931
  await pool.query(`CREATE SCHEMA IF NOT EXISTS "${s2}"`);
267688
267932
  await pool.query(`
267689
267933
  CREATE TABLE IF NOT EXISTS "${s2}".dispatches (
@@ -268866,14 +269110,14 @@ function companySchemaName(companyId) {
268866
269110
  if (typeof companyId !== "string" || !companyId.trim()) {
268867
269111
  throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
268868
269112
  }
268869
- const hex = (0, import_node_crypto77.createHash)("sha256").update(companyId, "utf8").digest("hex");
269113
+ const hex = (0, import_node_crypto78.createHash)("sha256").update(companyId, "utf8").digest("hex");
268870
269114
  return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
268871
269115
  }
268872
- var import_node_crypto77, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
269116
+ var import_node_crypto78, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
268873
269117
  var init_tenant_schema_mapping = __esm({
268874
269118
  "../storage/src/tenant-schema-mapping.ts"() {
268875
269119
  "use strict";
268876
- import_node_crypto77 = require("node:crypto");
269120
+ import_node_crypto78 = require("node:crypto");
268877
269121
  init_esm();
268878
269122
  init_pg_ident();
268879
269123
  COMPANY_SCHEMA_PREFIX = "c_";
@@ -268947,7 +269191,7 @@ var init_tenant_schema_mapping = __esm({
268947
269191
 
268948
269192
  // ../storage/src/company-data-plane-schema.ts
268949
269193
  function canonicalTypeDefHash(def) {
268950
- return `sha256:${(0, import_node_crypto78.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
269194
+ return `sha256:${(0, import_node_crypto79.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
268951
269195
  }
268952
269196
  function defaultArtifactTypeTemplate() {
268953
269197
  return [
@@ -269129,11 +269373,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
269129
269373
  }
269130
269374
  return { inserted };
269131
269375
  }
269132
- var import_node_crypto78, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
269376
+ var import_node_crypto79, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
269133
269377
  var init_company_data_plane_schema = __esm({
269134
269378
  "../storage/src/company-data-plane-schema.ts"() {
269135
269379
  "use strict";
269136
- import_node_crypto78 = require("node:crypto");
269380
+ import_node_crypto79 = require("node:crypto");
269137
269381
  init_esm();
269138
269382
  init_pg_ident();
269139
269383
  DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
@@ -269212,11 +269456,11 @@ function rowToFile2(row) {
269212
269456
  updatedAt: new Date(row.updated_at).toISOString()
269213
269457
  };
269214
269458
  }
269215
- var import_node_crypto79, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
269459
+ var import_node_crypto80, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
269216
269460
  var init_company_owned_registry_store = __esm({
269217
269461
  "../storage/src/company-owned-registry-store.ts"() {
269218
269462
  "use strict";
269219
- import_node_crypto79 = require("node:crypto");
269463
+ import_node_crypto80 = require("node:crypto");
269220
269464
  init_esm();
269221
269465
  init_src();
269222
269466
  init_pg_ident();
@@ -269601,7 +269845,7 @@ var init_company_owned_registry_store = __esm({
269601
269845
  enabled: skill.enabled,
269602
269846
  files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
269603
269847
  });
269604
- return (0, import_node_crypto79.createHash)("sha256").update(body2).digest("hex");
269848
+ return (0, import_node_crypto80.createHash)("sha256").update(body2).digest("hex");
269605
269849
  }
269606
269850
  };
269607
269851
  }
@@ -272411,7 +272655,7 @@ function sourceSetConservation(input) {
272411
272655
  return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
272412
272656
  }
272413
272657
  function payloadChecksum(value2) {
272414
- return (0, import_node_crypto80.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
272658
+ return (0, import_node_crypto81.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
272415
272659
  }
272416
272660
  async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
272417
272661
  const cs = quoteIdent2(companySchema);
@@ -272803,11 +273047,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
272803
273047
  sequences
272804
273048
  };
272805
273049
  }
272806
- var import_node_crypto80, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
273050
+ var import_node_crypto81, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
272807
273051
  var init_tenant_migration_operator = __esm({
272808
273052
  "../storage/src/tenant-migration-operator.ts"() {
272809
273053
  "use strict";
272810
- import_node_crypto80 = require("node:crypto");
273054
+ import_node_crypto81 = require("node:crypto");
272811
273055
  init_esm();
272812
273056
  init_pg_ident();
272813
273057
  init_tenancy_attribution();
@@ -273043,8 +273287,8 @@ var init_tenant_new_company_provision = __esm({
273043
273287
  // ../storage/src/knowledge-snapshot-crypto.ts
273044
273288
  function sealSnapshot(snapshot, key2) {
273045
273289
  if (snapshot.content.startsWith(PREFIX3)) return structuredClone(snapshot);
273046
- const iv = (0, import_node_crypto81.randomBytes)(12);
273047
- const cipher = (0, import_node_crypto81.createCipheriv)("aes-256-gcm", bytes(key2), iv);
273290
+ const iv = (0, import_node_crypto82.randomBytes)(12);
273291
+ const cipher = (0, import_node_crypto82.createCipheriv)("aes-256-gcm", bytes(key2), iv);
273048
273292
  cipher.setAAD(aad2(snapshot));
273049
273293
  const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
273050
273294
  return { ...structuredClone(snapshot), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
@@ -273054,7 +273298,7 @@ function openSnapshot(snapshot, key2) {
273054
273298
  const packed = snapshot.content.slice(PREFIX3.length).split(".");
273055
273299
  if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
273056
273300
  const [iv, tag, data] = packed;
273057
- const decipher = (0, import_node_crypto81.createDecipheriv)("aes-256-gcm", bytes(key2), Buffer.from(iv, "base64url"));
273301
+ const decipher = (0, import_node_crypto82.createDecipheriv)("aes-256-gcm", bytes(key2), Buffer.from(iv, "base64url"));
273058
273302
  decipher.setAAD(aad2(snapshot));
273059
273303
  decipher.setAuthTag(Buffer.from(tag, "base64url"));
273060
273304
  return {
@@ -273062,11 +273306,11 @@ function openSnapshot(snapshot, key2) {
273062
273306
  content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
273063
273307
  };
273064
273308
  }
273065
- var import_node_crypto81, PREFIX3, bytes, aad2;
273309
+ var import_node_crypto82, PREFIX3, bytes, aad2;
273066
273310
  var init_knowledge_snapshot_crypto = __esm({
273067
273311
  "../storage/src/knowledge-snapshot-crypto.ts"() {
273068
273312
  "use strict";
273069
- import_node_crypto81 = require("node:crypto");
273313
+ import_node_crypto82 = require("node:crypto");
273070
273314
  PREFIX3 = "oasis-knowledge:v1:";
273071
273315
  bytes = (key2) => {
273072
273316
  const value2 = Buffer.from(key2);
@@ -273114,7 +273358,7 @@ function assertRecordScope(record9, scope2) {
273114
273358
  function equal(left, right) {
273115
273359
  return JSON.stringify(left) === JSON.stringify(right);
273116
273360
  }
273117
- var ident18, TABLES, TABLE_BY_KIND, PostgresKnowledgeGovernanceStore;
273361
+ var ident19, TABLES, TABLE_BY_KIND, PostgresKnowledgeGovernanceStore;
273118
273362
  var init_postgres_knowledge = __esm({
273119
273363
  "../storage/src/postgres-knowledge.ts"() {
273120
273364
  "use strict";
@@ -273122,7 +273366,7 @@ var init_postgres_knowledge = __esm({
273122
273366
  init_pg_ident();
273123
273367
  init_pg_sanitize();
273124
273368
  init_knowledge_snapshot_crypto();
273125
- ident18 = (value2) => {
273369
+ ident19 = (value2) => {
273126
273370
  quoteIdent2(value2);
273127
273371
  return value2;
273128
273372
  };
@@ -273280,11 +273524,11 @@ var init_postgres_knowledge = __esm({
273280
273524
  constructor(pool, schema, snapshotKey2) {
273281
273525
  this.pool = pool;
273282
273526
  this.snapshotKey = snapshotKey2;
273283
- this.s = `"${ident18(schema)}"`;
273527
+ this.s = `"${ident19(schema)}"`;
273284
273528
  }
273285
273529
  s;
273286
273530
  static async open(pool, schema = "public", snapshotKey2) {
273287
- const safe = ident18(schema);
273531
+ const safe = ident19(schema);
273288
273532
  await pool.query(`CREATE SCHEMA IF NOT EXISTS "${safe}"`);
273289
273533
  for (const spec of TABLES) {
273290
273534
  await pool.query(`
@@ -273958,7 +274202,7 @@ function reportedCost(v2) {
273958
274202
  }
273959
274203
  function newUsageBackfillManifestId(now = /* @__PURE__ */ new Date()) {
273960
274204
  const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
273961
- return `ulb-${stamp}-${(0, import_node_crypto82.randomBytes)(3).toString("hex")}`;
274205
+ return `ulb-${stamp}-${(0, import_node_crypto83.randomBytes)(3).toString("hex")}`;
273962
274206
  }
273963
274207
  async function backfillUsageLedger(ledger, opts) {
273964
274208
  if (!opts.dryRun && !opts.manifestId) throw new Error("execute \u9700\u8981 manifestId");
@@ -274392,11 +274636,11 @@ async function audit(c, s2, manifestId, runId, field, before, after, createdAt)
274392
274636
  [manifestId, runId, field, before == null ? null : JSON.stringify(before), after == null ? null : JSON.stringify(after), createdAt]
274393
274637
  );
274394
274638
  }
274395
- var import_node_crypto82, BUCKETS, ENDED_SQL, START_EVIDENCE_SQL, CHAT_RUN_SQL, emptyStep, fourOf, sameUsage, ChatRunLookup;
274639
+ var import_node_crypto83, BUCKETS, ENDED_SQL, START_EVIDENCE_SQL, CHAT_RUN_SQL, emptyStep, fourOf, sameUsage, ChatRunLookup;
274396
274640
  var init_usage_ledger_backfill = __esm({
274397
274641
  "../storage/src/usage-ledger-backfill.ts"() {
274398
274642
  "use strict";
274399
- import_node_crypto82 = require("node:crypto");
274643
+ import_node_crypto83 = require("node:crypto");
274400
274644
  init_src();
274401
274645
  init_pg_ident();
274402
274646
  init_postgres_trace();
@@ -274528,9 +274772,11 @@ __export(src_exports, {
274528
274772
  PostgresChatItemStore: () => PostgresChatItemStore,
274529
274773
  PostgresChatSessionStore: () => PostgresChatSessionStore,
274530
274774
  PostgresChatTurnStore: () => PostgresChatTurnStore,
274775
+ PostgresConnectorAuthSnapshotStore: () => PostgresConnectorAuthSnapshotStore,
274531
274776
  PostgresControlPlaneStore: () => PostgresControlPlaneStore,
274532
274777
  PostgresDelegationStore: () => PostgresDelegationStore,
274533
274778
  PostgresDispatchStore: () => PostgresDispatchStore,
274779
+ PostgresGithubAppPendingStore: () => PostgresGithubAppPendingStore,
274534
274780
  PostgresHumanPrefsStore: () => PostgresHumanPrefsStore,
274535
274781
  PostgresKnowledgeGovernanceStore: () => PostgresKnowledgeGovernanceStore,
274536
274782
  PostgresModelPriceStore: () => PostgresModelPriceStore,
@@ -274664,6 +274910,7 @@ var init_src10 = __esm({
274664
274910
  init_postgres_type_registry();
274665
274911
  init_postgres_actor_memory();
274666
274912
  init_postgres_inbox_read();
274913
+ init_postgres_connector_auth_pending();
274667
274914
  init_postgres_dispatches();
274668
274915
  init_tenancy_inventory();
274669
274916
  init_tenancy_move();
@@ -275893,6 +276140,7 @@ __export(src_exports2, {
275893
276140
  MirrorEngine: () => MirrorEngine,
275894
276141
  MissingCompanyContextError: () => MissingCompanyContextError,
275895
276142
  NODE_HEARTBEAT_STALE_MS: () => NODE_HEARTBEAT_STALE_MS,
276143
+ NOTIFICATIONS_CHANGED: () => NOTIFICATIONS_CHANGED,
275896
276144
  NPM_PROBE_TIMEOUT_MS: () => NPM_PROBE_TIMEOUT_MS,
275897
276145
  NdjsonOplogStore: () => NdjsonOplogStore,
275898
276146
  NodeHealthTracker: () => NodeHealthTracker,
@@ -276210,6 +276458,7 @@ __export(src_exports2, {
276210
276458
  openChatTurn: () => openChatTurn,
276211
276459
  openKnowledgeSnapshot: () => openKnowledgeSnapshot,
276212
276460
  openNewEngine: () => openNewEngine,
276461
+ operatorCrossCompanyRead: () => operatorCrossCompanyRead,
276213
276462
  outputsPartProvider: () => outputsPartProvider,
276214
276463
  packMatches: () => packMatches,
276215
276464
  parentConversationTaskLines: () => parentConversationTaskLines,
@@ -276811,14 +277060,14 @@ init_src();
276811
277060
  var os15 = __toESM(require("node:os"));
276812
277061
  var path45 = __toESM(require("node:path"));
276813
277062
  var import_node_child_process26 = require("node:child_process");
276814
- var import_node_crypto93 = require("node:crypto");
277063
+ var import_node_crypto94 = require("node:crypto");
276815
277064
 
276816
277065
  // ../cli/src/cli.ts
276817
277066
  init_src();
276818
277067
  var fs43 = __toESM(require("node:fs"), 1);
276819
277068
  var os12 = __toESM(require("node:os"), 1);
276820
277069
  var path38 = __toESM(require("node:path"), 1);
276821
- var import_node_crypto91 = require("node:crypto");
277070
+ var import_node_crypto92 = require("node:crypto");
276822
277071
 
276823
277072
  // ../cli/src/serve.ts
276824
277073
  init_src11();
@@ -276830,11 +277079,11 @@ var fs35 = __toESM(require("node:fs"), 1);
276830
277079
  var os8 = __toESM(require("node:os"), 1);
276831
277080
  var path29 = __toESM(require("node:path"), 1);
276832
277081
  var import_node_child_process18 = require("node:child_process");
276833
- var import_node_crypto87 = require("node:crypto");
277082
+ var import_node_crypto88 = require("node:crypto");
276834
277083
  var import_node_url7 = require("node:url");
276835
277084
 
276836
277085
  // ../cli/src/artifact-discovery-source.ts
276837
- var import_node_crypto83 = require("node:crypto");
277086
+ var import_node_crypto84 = require("node:crypto");
276838
277087
  init_src7();
276839
277088
  var ArtifactDiscoverySourceUnreadableError = class extends Error {
276840
277089
  constructor(message) {
@@ -276864,7 +277113,7 @@ async function resolveArtifactDiscoverySourceContent(blobs, input) {
276864
277113
  throw new ArtifactDiscoverySourceUnreadableError(`Artifact Revision ${input.revisionId} \u7684 contentKind \u4E0D\u53D7\u652F\u6301\uFF1A${String(input.contentKind)}`);
276865
277114
  }
276866
277115
  const rootBytes = await blobs.get(input.contentRef);
276867
- const sourceFingerprint = (0, import_node_crypto83.createHash)("sha256").update(rootBytes).digest("hex");
277116
+ const sourceFingerprint = (0, import_node_crypto84.createHash)("sha256").update(rootBytes).digest("hex");
276868
277117
  if (input.contentKind === "inline-blob") {
276869
277118
  const sourceContent = decodeText3(rootBytes);
276870
277119
  if (sourceContent === null) {
@@ -276888,7 +277137,7 @@ ${entry.text}`).join("\n\n"),
276888
277137
  }
276889
277138
 
276890
277139
  // ../server/src/domains/discussions/service.ts
276891
- var import_node_crypto84 = require("node:crypto");
277140
+ var import_node_crypto85 = require("node:crypto");
276892
277141
  init_zod();
276893
277142
  init_discussions();
276894
277143
  init_router();
@@ -276950,7 +277199,7 @@ function remapTopics(topics, removed) {
276950
277199
  return [...out].map(([topic_id, summary]) => ({ topic_id, summary }));
276951
277200
  }
276952
277201
  var entryId = (projectId2, id) => JSON.stringify([projectId2, id]);
276953
- var hash2 = (s2) => (0, import_node_crypto84.createHash)("sha256").update(s2).digest("hex").slice(0, 24);
277202
+ var hash2 = (s2) => (0, import_node_crypto85.createHash)("sha256").update(s2).digest("hex").slice(0, 24);
276954
277203
  var canonical = (s2) => s2.normalize("NFKC").trim().toLocaleLowerCase();
276955
277204
  function decisionFingerprint(d) {
276956
277205
  return hash2(JSON.stringify([d.statement, d.rationale, d.alternatives]));
@@ -277170,7 +277419,7 @@ var DiscussionService = class {
277170
277419
  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
277420
  }
277172
277421
  }
277173
- const operation = (value2) => tx.put("operation", (0, import_node_crypto84.randomUUID)(), {
277422
+ const operation = (value2) => tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
277174
277423
  ...value2,
277175
277424
  projectId: projectId2,
277176
277425
  actorId: ctx.actorId,
@@ -277187,7 +277436,7 @@ var DiscussionService = class {
277187
277436
  if (id.startsWith("new:")) {
277188
277437
  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
277438
  const existing = [...topicMap.values()].find((x2) => canonical(x2.title) === canonical(t.title));
277190
- id = existing?.topicId ?? `topic_${(0, import_node_crypto84.randomUUID)()}`;
277439
+ id = existing?.topicId ?? `topic_${(0, import_node_crypto85.randomUUID)()}`;
277191
277440
  if (!existing) createdTopics.add(id);
277192
277441
  } 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
277442
  topicAliases.set(t.topic_id, id);
@@ -277239,7 +277488,7 @@ var DiscussionService = class {
277239
277488
  if (id.startsWith("new:")) {
277240
277489
  const candidateKey = JSON.stringify([topicId, canonical(d.record.statement)]);
277241
277490
  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, import_node_crypto84.randomUUID)()}`;
277491
+ id = existing?.decisionId ?? candidateIds.get(candidateKey) ?? `decision_${(0, import_node_crypto85.randomUUID)()}`;
277243
277492
  candidateIds.set(candidateKey, id);
277244
277493
  } else if (!decisionMap.has(id)) invalid("decision_id", `\u51B3\u7B56 ${id} \u4E0D\u5B58\u5728\uFF1B\u65B0\u51B3\u7B56\u4F7F\u7528 new: \u524D\u7F00`);
277245
277494
  decisionAliases.set(d.decision_id, id);
@@ -277501,7 +277750,7 @@ var DiscussionService = class {
277501
277750
  ...row.value.confirmation ? { confirmation: { ...row.value.confirmation, fingerprint: decisionFingerprint(record9) } } : {}
277502
277751
  };
277503
277752
  await tx.put("decision", row.id, value2);
277504
- await tx.put("operation", (0, import_node_crypto84.randomUUID)(), {
277753
+ await tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
277505
277754
  action: "edit",
277506
277755
  kind: "decision",
277507
277756
  projectId: projectId2,
@@ -277565,7 +277814,7 @@ var DiscussionService = class {
277565
277814
  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
277815
  const summary = given.get(row.id);
277567
277816
  await tx.put("discussion", row.id, { ...current.value, record: { ...current.value.record, summary } });
277568
- await tx.put("operation", (0, import_node_crypto84.randomUUID)(), {
277817
+ await tx.put("operation", (0, import_node_crypto85.randomUUID)(), {
277569
277818
  action: "edit",
277570
277819
  kind: "discussion",
277571
277820
  projectId: current.value.record.project_id,
@@ -277581,7 +277830,7 @@ var DiscussionService = class {
277581
277830
  });
277582
277831
  }
277583
277832
  async operation(tx, actorId, kind, id, from, to) {
277584
- await tx.put("operation", (0, import_node_crypto84.randomUUID)(), { actorId, kind, id, from, to, at: new Date(this.now()).toISOString() });
277833
+ await tx.put("operation", (0, import_node_crypto85.randomUUID)(), { actorId, kind, id, from, to, at: new Date(this.now()).toISOString() });
277585
277834
  }
277586
277835
  };
277587
277836
  function pickDiscussionContent(d) {
@@ -277881,7 +278130,7 @@ var DiscussionContext = class {
277881
278130
  };
277882
278131
 
277883
278132
  // ../server/src/domains/discussions/worker.ts
277884
- var import_node_crypto85 = require("node:crypto");
278133
+ var import_node_crypto86 = require("node:crypto");
277885
278134
  var DISCUSSION_IDLE_MS = 15 * 6e4;
277886
278135
  var DISCUSSION_MAX_CORRECTIONS = 3;
277887
278136
  var DISCUSSION_LEASE_MS = 2 * 6e4;
@@ -277907,7 +278156,7 @@ var DiscussionWorker = class {
277907
278156
  if (await this.isReplying(sessionId)) return false;
277908
278157
  const cutoff = eligibleCutoff(await this.service.chat.listMessages(sessionId), this.service.now());
277909
278158
  if (!cutoff) return false;
277910
- const owner = (0, import_node_crypto85.randomUUID)();
278159
+ const owner = (0, import_node_crypto86.randomUUID)();
277911
278160
  const claimed = await this.service.store.transaction(async (tx) => {
277912
278161
  const old = (await tx.get("job", sessionId))?.value;
277913
278162
  if (old?.status === "running" && (old.leaseUntil ?? 0) > this.service.now()) return null;
@@ -278629,7 +278878,7 @@ function createDiscussionRuntime(options) {
278629
278878
  }
278630
278879
 
278631
278880
  // ../server/src/domains/discussions/store.ts
278632
- var import_node_crypto86 = require("node:crypto");
278881
+ var import_node_crypto87 = require("node:crypto");
278633
278882
  var import_promises17 = require("node:fs/promises");
278634
278883
  var import_node_path27 = require("node:path");
278635
278884
  var key = (kind, id) => JSON.stringify([kind, id]);
@@ -278674,7 +278923,7 @@ var MemoryDiscussionStore = class _MemoryDiscussionStore {
278674
278923
  if (changed) {
278675
278924
  if (this.filename) {
278676
278925
  await (0, import_promises17.mkdir)((0, import_node_path27.dirname)(this.filename), { recursive: true });
278677
- const temp = `${this.filename}.${(0, import_node_crypto86.randomUUID)()}.tmp`;
278926
+ const temp = `${this.filename}.${(0, import_node_crypto87.randomUUID)()}.tmp`;
278678
278927
  await (0, import_promises17.writeFile)(temp, JSON.stringify(next), "utf8");
278679
278928
  await (0, import_promises17.rename)(temp, this.filename);
278680
278929
  }
@@ -279623,7 +279872,7 @@ function oasisWrapperScript() {
279623
279872
  const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
279624
279873
  const tsx = path29.join(repoRoot, "node_modules/.bin/tsx");
279625
279874
  const main = path29.join(repoRoot, "packages/cli/src/main.ts");
279626
- const key2 = (0, import_node_crypto87.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
279875
+ const key2 = (0, import_node_crypto88.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
279627
279876
  const uid = typeof process.getuid === "function" ? process.getuid() : "na";
279628
279877
  const stable = path29.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key2}`);
279629
279878
  let dir;
@@ -280016,7 +280265,7 @@ async function startServe(opts) {
280016
280265
  if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
280017
280266
  const online = hub.connectedDaemons().some((d) => d.daemonId === nodeId);
280018
280267
  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, import_node_crypto87.randomUUID)();
280268
+ const requestId = (0, import_node_crypto88.randomUUID)();
280020
280269
  const task = new Promise((resolve12) => {
280021
280270
  const timer = setTimeout(() => {
280022
280271
  modelRefreshWaiters.delete(requestId);
@@ -280817,7 +281066,7 @@ async function startServe(opts) {
280817
281066
  const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
280818
281067
  if (buf || session.runId) {
280819
281068
  await turnStore.appendMessage({
280820
- id: (0, import_node_crypto87.randomUUID)(),
281069
+ id: (0, import_node_crypto88.randomUUID)(),
280821
281070
  sessionId: chatSessionId,
280822
281071
  role: "assistant",
280823
281072
  content: buf,
@@ -280863,7 +281112,7 @@ async function startServe(opts) {
280863
281112
  chatTargets: {
280864
281113
  inspect: inspectChatTarget,
280865
281114
  createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
280866
- const sessionId = (0, import_node_crypto87.randomUUID)();
281115
+ const sessionId = (0, import_node_crypto88.randomUUID)();
280867
281116
  const nowIso = (/* @__PURE__ */ new Date()).toISOString();
280868
281117
  const binding = await registryStore.getBinding(agentId).catch(() => null);
280869
281118
  await (await chatStoreFor(companyId)).createSession({
@@ -281056,7 +281305,8 @@ async function startServe(opts) {
281056
281305
  })();
281057
281306
  }
281058
281307
  await syncRegistryRolesToKernel(registryStore, defaultCompanyKernel);
281059
- const resolveCompanyContext = async (actor, headers, pathname) => {
281308
+ const operatorScopesOf = (authorization) => authorization.startsWith("Bearer ") ? issuer.resolveClaims(authorization.slice("Bearer ".length))?.scopes : void 0;
281309
+ const resolveCompanyContext = async (actor, headers, pathname, method) => {
281060
281310
  if (isCompanyCrossTenantPath(pathname)) {
281061
281311
  return { kind: "exempt" };
281062
281312
  }
@@ -281079,7 +281329,11 @@ async function startServe(opts) {
281079
281329
  }
281080
281330
  const ctx = await companies.service.resolveCurrentCompany(me.accountId, selector);
281081
281331
  if (!ctx) return { kind: "not-found", ...selector !== void 0 ? { selector } : {} };
281082
- return ctx.isMember ? { kind: "ok", companyId: ctx.company.id } : { kind: "forbidden" };
281332
+ if (ctx.isMember) return { kind: "ok", companyId: ctx.company.id };
281333
+ if (operatorCrossCompanyRead({ scopes: operatorScopesOf(authz) }, method)) {
281334
+ return { kind: "ok", companyId: ctx.company.id };
281335
+ }
281336
+ return { kind: "forbidden" };
281083
281337
  };
281084
281338
  const resolveActor = (token) => issuer.resolve(token) ?? (opts.allowSimpleTokens && token.startsWith("token:") ? token.slice("token:".length) : null);
281085
281339
  const AGENT_PRINCIPAL_CACHE_MAX = 4096;
@@ -281625,9 +281879,9 @@ async function startServe(opts) {
281625
281879
  return engine2;
281626
281880
  };
281627
281881
  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 registryStore.listActors();
281882
+ const countRoleHolders = async (role, companyId) => (await roleHolders(companyId)).filter((a) => a.status !== "disabled" && a.roles?.includes(role)).length;
281883
+ const roleHolders = async (companyId) => {
281884
+ const employees = await (await actors.resolveCtx(companyId ?? defaultCompanyId)).service.listActors();
281631
281885
  const ids2 = new Set(employees.map((a) => a.id));
281632
281886
  const systemActors = kernelRegistry.filter((e) => !ids2.has(e.actor)).map((e) => ({ id: e.actor, roles: e.roles, status: "active" }));
281633
281887
  return [...employees, ...systemActors];
@@ -282163,6 +282417,11 @@ async function startServe(opts) {
282163
282417
  // CO-301 阶段1:请求热路径按当前公司经路由层取引擎(恒等到默认公司;per-company 懒建是后续阶段)。
282164
282418
  resolveEngine: (companyId) => getEngine(companyId ?? defaultCompanyId),
282165
282419
  actors,
282420
+ // Bug 0246:GitHub App 待回调登记与重连快照落共享 schema——服务器重启 / 换副本都读得到。
282421
+ connectorAuthPending: {
282422
+ githubApp: await PostgresGithubAppPendingStore.open(pgPool, sharedSchema),
282423
+ snapshots: await PostgresConnectorAuthSnapshotStore.open(pgPool, sharedSchema)
282424
+ },
282166
282425
  port: opts.port ?? 7320,
282167
282426
  projectState: projectStateStore,
282168
282427
  artifactState: artifactStateStore,
@@ -282213,7 +282472,7 @@ async function startServe(opts) {
282213
282472
  }));
282214
282473
  }
282215
282474
  const limits = { wallClockMs: wallClockForKind("planner") };
282216
- const artifactId = `artifact:planner:${(0, import_node_crypto87.randomUUID)()}`;
282475
+ const artifactId = `artifact:planner:${(0, import_node_crypto88.randomUUID)()}`;
282217
282476
  const handle = await chatRemoteAdapter.spawn({
282218
282477
  actor: planner.id,
282219
282478
  // companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
@@ -282302,7 +282561,7 @@ async function startServe(opts) {
282302
282561
  await rebuildLiveSchema();
282303
282562
  for (const d of schema) engine2.kernel.setType(d);
282304
282563
  },
282305
- countRoleHolders,
282564
+ (role) => countRoleHolders(role, cid),
282306
282565
  registryAudit
282307
282566
  );
282308
282567
  }
@@ -282441,9 +282700,9 @@ async function startServe(opts) {
282441
282700
  // store(`public.actor_bindings`),org-registry cutover 之后它是冻结旧镜像——只留给
282442
282701
  // 本域其它老读口,工作区定位一律不许再用它。
282443
282702
  resolveBinding: resolveCompanyBinding,
282444
- /* ADR 0613:建会话 / 「恢复为员工默认运行配置」这两下要读员工详情页配的型号,按**当前公司**读
282703
+ /* ADR 0613:建会话那一下要读员工详情页配的型号,按**当前公司**读
282445
282704
  (与 `resolveBinding` 同一条理由:全局 `registry` 对已切 `actor-config` 的公司是冻结旧镜像)。
282446
- ⚠ 只有这两下读它;解析每一轮的模型依旧不读员工配置(ADR 0610 D1)。 */
282705
+ ⚠ 只有这一下读它;解析每一轮的模型依旧不读员工配置(ADR 0610 D1)。 */
282447
282706
  resolveActorModel: resolveAgentConfiguredModel,
282448
282707
  // 按 runId 路由:切换后新会话的事件落在本公司库里,共享 store 会一条都补不出 parts。
282449
282708
  // ⚠ `runRoutedTrace` 声明在本行**之后**:包成箭头函数避 TDZ(本域只需要 listEvents)。
@@ -282531,6 +282790,8 @@ async function startServe(opts) {
282531
282790
  // live 注册表算 `frameCursor`。与 server.ts 的双写解析同一层,与 attach 路径共享 registry。
282532
282791
  resolveChatItems: (companyId) => chatItemsFor(companyId),
282533
282792
  liveChat,
282793
+ // ADR 0615 B3:快照读口给 serve 重启留下的孤儿插话落结论时问节点——与 `/append` 同一条网关。
282794
+ confirmInputReceipt: (ref2) => chatRemoteAdapter ? chatRemoteAdapter.confirmInputReceipt(ref2.nodeId, ref2.dispatchId, ref2.runtimeKey) : Promise.resolve({ status: "unknown", reason: "node-gateway-not-ready" }),
282534
282795
  // ADR-0587:列表行派生 `unread`,与 collab 域收件箱读同一份按公司的水位(无 PG 时闭包自己回落单实例)。
282535
282796
  resolveReadMarkers: readMarkerStoreFor,
282536
282797
  // ADR 0610 D4:`GET /api/chat-sessions/:id/usage` 的取数口——**与 collab 域是同一个实例**,
@@ -283134,8 +283395,6 @@ async function startServe(opts) {
283134
283395
  discussSessions: new FileSideMap(path29.join(opts.dir, "discuss-sessions.json")),
283135
283396
  escalateDiscussRetain: new FileSideMap(path29.join(opts.dir, "escalate-discuss-retain.json")),
283136
283397
  // 切片 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
283398
  dispatchChat: automationDispatchChat = async (chatReq) => {
283140
283399
  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
283400
  const isolatedKnowledgeTurn = executionProfile === "knowledge-single-turn";
@@ -283158,10 +283417,10 @@ async function startServe(opts) {
283158
283417
  if (isDeletedActor(dispatchTarget)) {
283159
283418
  throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
283160
283419
  }
283161
- const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto87.randomUUID)());
283420
+ const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto88.randomUUID)());
283162
283421
  const resumeRuntimeSession = Boolean(sessionId);
283163
- const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto87.randomUUID)()}`;
283164
- const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto87.randomUUID)()}`;
283422
+ const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto88.randomUUID)()}`;
283423
+ const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto88.randomUUID)()}`;
283165
283424
  let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
283166
283425
  if (stableDispatch && !stableDispatch.shouldDispatch) {
283167
283426
  if (isHumanSubmitDispatchId(requestDispatchId)) {
@@ -284611,7 +284870,7 @@ async function startServe(opts) {
284611
284870
  console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
284612
284871
  return;
284613
284872
  }
284614
- const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto87.randomUUID)()}`;
284873
+ const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto88.randomUUID)()}`;
284615
284874
  try {
284616
284875
  const inserted = await (await dispatchLedgerFor(companyId)).insertOpen({
284617
284876
  id: ledgerId,
@@ -284711,7 +284970,7 @@ async function startServe(opts) {
284711
284970
  const kernelModel = newKernel.model;
284712
284971
  const art = kernelModel.artifacts.get(nodeId);
284713
284972
  const revWid = art?.workspace ?? "";
284714
- const ledgerId = `dispatch:${(0, import_node_crypto87.randomUUID)()}`;
284973
+ const ledgerId = `dispatch:${(0, import_node_crypto88.randomUUID)()}`;
284715
284974
  try {
284716
284975
  await (await dispatchLedgerFor(companyId)).insertOpen({
284717
284976
  id: ledgerId,
@@ -285105,7 +285364,7 @@ async function startServe(opts) {
285105
285364
  resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
285106
285365
  try {
285107
285366
  const governance = server.knowledgeGovernance;
285108
- const taskFingerprint = (0, import_node_crypto87.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
285367
+ const taskFingerprint = (0, import_node_crypto88.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
285109
285368
  const requestContext = {
285110
285369
  organizationId: companyId,
285111
285370
  actorId,
@@ -285832,7 +286091,9 @@ async function startServe(opts) {
285832
286091
  slaMs: humanMs
285833
286092
  };
285834
286093
  },
285835
- log: (message) => console.warn(message)
286094
+ log: (message) => console.warn(message),
286095
+ // 新进了通知就推给收件人本人(/api/events?topics=notifications):铃铛角标与页内提示不等 30 秒轮询。
286096
+ onNotified: (_companyId, recipients) => auditSink.notifyNotificationsChanged(recipients)
285836
286097
  });
285837
286098
  notificationLedgerWorker = worker;
285838
286099
  const ledgerSubscribed = /* @__PURE__ */ new Set();
@@ -287763,7 +288024,7 @@ var RuntimeQuotaMonitor = class {
287763
288024
  init_wrapper();
287764
288025
  init_src();
287765
288026
  var import_node_os11 = require("node:os");
287766
- var import_node_crypto88 = require("node:crypto");
288027
+ var import_node_crypto89 = require("node:crypto");
287767
288028
  init_src8();
287768
288029
  init_src2();
287769
288030
 
@@ -288660,7 +288921,7 @@ var DaemonWsClient = class {
288660
288921
  */
288661
288922
  async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
288662
288923
  if (artifactIds.length === 0) return {};
288663
- const requestId = (0, import_node_crypto88.randomUUID)();
288924
+ const requestId = (0, import_node_crypto89.randomUUID)();
288664
288925
  return new Promise((resolve12, reject) => {
288665
288926
  const timer = setTimeout(() => {
288666
288927
  this.gcPending.delete(requestId);
@@ -289071,7 +289332,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
289071
289332
  // ../cli/src/daemon/machine-id.ts
289072
289333
  var import_node_child_process23 = require("node:child_process");
289073
289334
  var import_node_fs24 = require("node:fs");
289074
- var import_node_crypto89 = require("node:crypto");
289335
+ var import_node_crypto90 = require("node:crypto");
289075
289336
  var import_node_os14 = require("node:os");
289076
289337
  function linuxMachineId() {
289077
289338
  for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
@@ -289137,7 +289398,7 @@ var defaultSources = {
289137
289398
  function resolveNodeId(sources = {}) {
289138
289399
  const s2 = { ...defaultSources, ...sources };
289139
289400
  const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
289140
- const digest = (0, import_node_crypto89.createHash)("sha256").update(material).digest("hex").slice(0, 12);
289401
+ const digest = (0, import_node_crypto90.createHash)("sha256").update(material).digest("hex").slice(0, 12);
289141
289402
  return `node-${digest}`;
289142
289403
  }
289143
289404
 
@@ -291009,13 +291270,13 @@ function ownFlagsFromDecl(command2) {
291009
291270
  }
291010
291271
 
291011
291272
  // ../cli/src/connector-effect-runner.ts
291012
- var import_node_crypto90 = require("node:crypto");
291273
+ var import_node_crypto91 = require("node:crypto");
291013
291274
  var import_node_child_process24 = require("node:child_process");
291014
291275
  init_src8();
291015
291276
  function stableKey(effect) {
291016
291277
  const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
291017
291278
  const canonical2 = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
291018
- return `sha256:${(0, import_node_crypto90.createHash)("sha256").update(canonical2).digest("hex")}`;
291279
+ return `sha256:${(0, import_node_crypto91.createHash)("sha256").update(canonical2).digest("hex")}`;
291019
291280
  }
291020
291281
  async function runConnectorEffect(connector, toolArgs, deps) {
291021
291282
  const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
@@ -291570,7 +291831,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
291570
291831
  const timeoutMs = resolveAuthWaitMs();
291571
291832
  const controller = new AbortController();
291572
291833
  const timer = setTimeout(() => controller.abort(), timeoutMs);
291573
- const waiterId = (0, import_node_crypto91.randomUUID)();
291834
+ const waiterId = (0, import_node_crypto92.randomUUID)();
291574
291835
  process.stderr.write(
291575
291836
  `\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
291837
  `
@@ -291654,7 +291915,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
291654
291915
  }
291655
291916
  }
291656
291917
  }
291657
- var CLI_VERSION = "2.2.77" ? "2.2.77" : "dev";
291918
+ var CLI_VERSION = "2.2.78" ? "2.2.78" : "dev";
291658
291919
  function apiHeaders(token, company) {
291659
291920
  const headers = {
291660
291921
  authorization: `Bearer ${token}`,
@@ -292020,7 +292281,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
292020
292281
  const store = createNodeTokenStore(path38.join(dir, "node-tokens.json"));
292021
292282
  const sub = positional[0];
292022
292283
  if (sub === "issue") {
292023
- const id = flags.get("id") ?? `node-${(0, import_node_crypto91.randomUUID)()}`;
292284
+ const id = flags.get("id") ?? `node-${(0, import_node_crypto92.randomUUID)()}`;
292024
292285
  const token2 = store.issue(id);
292025
292286
  println(token2);
292026
292287
  process.stderr.write(
@@ -293159,7 +293420,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
293159
293420
  if (!name) throw new Error("\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
293160
293421
  const goal = flags.get("goal")?.trim();
293161
293422
  const slug6 = flags.get("slug");
293162
- const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0, import_node_crypto91.randomUUID)());
293423
+ const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0, import_node_crypto92.randomUUID)());
293163
293424
  const result = await api.request("POST", "/api/projects", {
293164
293425
  ...id ? { id } : {},
293165
293426
  name,
@@ -295424,13 +295685,13 @@ function runtimeAssetSourceRoots(input) {
295424
295685
  }
295425
295686
 
295426
295687
  // src/install.ts
295427
- var import_node_crypto92 = require("node:crypto");
295688
+ var import_node_crypto93 = require("node:crypto");
295428
295689
  var fs49 = __toESM(require("node:fs"));
295429
295690
  var path44 = __toESM(require("node:path"));
295430
295691
  function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
295431
295692
  const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
295432
295693
  if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
295433
- const digest = (0, import_node_crypto92.createHash)("sha256").update(fs49.readFileSync(sourceFile)).digest("hex").slice(0, 8);
295694
+ const digest = (0, import_node_crypto93.createHash)("sha256").update(fs49.readFileSync(sourceFile)).digest("hex").slice(0, 8);
295434
295695
  return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
295435
295696
  }
295436
295697
  function isFromNpmPrefix(sourceFile, npmPrefixDir) {
@@ -295553,7 +295814,7 @@ function shimScript() {
295553
295814
  }
295554
295815
 
295555
295816
  // src/index.ts
295556
- var PKG_VERSION = true ? "2.2.77" : "dev";
295817
+ var PKG_VERSION = true ? "2.2.78" : "dev";
295557
295818
  var LOCAL_BIN = localBin();
295558
295819
  var NPM_PREFIX = npmPrefix();
295559
295820
  var INSTANCE = DEFAULT_INSTANCE;
@@ -295861,7 +296122,7 @@ function newInstanceName() {
295861
296122
  const existing = new Set(listInstances());
295862
296123
  if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
295863
296124
  for (; ; ) {
295864
- const n = `inst-${(0, import_node_crypto93.randomBytes)(3).toString("hex")}`;
296125
+ const n = `inst-${(0, import_node_crypto94.randomBytes)(3).toString("hex")}`;
295865
296126
  if (!existing.has(n)) return n;
295866
296127
  }
295867
296128
  }