oasis_test_v2 2.2.82 → 2.2.84
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1196 -458
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1347,6 +1347,21 @@ function actualModelId(model) {
|
|
|
1347
1347
|
if (!t) return void 0;
|
|
1348
1348
|
return isPseudoModelId(t) ? void 0 : t;
|
|
1349
1349
|
}
|
|
1350
|
+
function modelSourceRank(model, source) {
|
|
1351
|
+
if (!actualModelId(model)) return -1;
|
|
1352
|
+
return source ? MODEL_SOURCE_RANK[source] ?? 1 : 1;
|
|
1353
|
+
}
|
|
1354
|
+
function preferRunModel(existing, incoming, tie = "keep") {
|
|
1355
|
+
const incomingModel = actualModelId(incoming.effectiveModel);
|
|
1356
|
+
if (!incomingModel) return null;
|
|
1357
|
+
const existingRank = modelSourceRank(existing.effectiveModel, existing.modelSource);
|
|
1358
|
+
const incomingRank = modelSourceRank(incomingModel, incoming.modelSource);
|
|
1359
|
+
if (incomingRank > existingRank) return { effectiveModel: incomingModel, modelSource: incoming.modelSource ?? null };
|
|
1360
|
+
if (incomingRank === existingRank && tie === "replace") {
|
|
1361
|
+
return { effectiveModel: incomingModel, modelSource: incoming.modelSource ?? null };
|
|
1362
|
+
}
|
|
1363
|
+
return null;
|
|
1364
|
+
}
|
|
1350
1365
|
function legacyScopeIsEmpty(scope2) {
|
|
1351
1366
|
return scope2.artifactIds.length === 0 && scope2.chatSessionIds.length === 0 && (scope2.runtimeInstanceIds?.length ?? 0) === 0;
|
|
1352
1367
|
}
|
|
@@ -1356,11 +1371,20 @@ function legacyScopeMatcher(scope2) {
|
|
|
1356
1371
|
const runtimes = new Set(scope2.runtimeInstanceIds ?? []);
|
|
1357
1372
|
return (run) => run.artifactId != null && artifacts.has(run.artifactId) || run.chatSessionId != null && sessions.has(run.chatSessionId) || run.runtimeInstanceId != null && runtimes.has(run.runtimeInstanceId);
|
|
1358
1373
|
}
|
|
1359
|
-
var PSEUDO_MODEL_IDS, DISPLAY_CNY_PER_USD, USAGE_POINT_FINAL_SEQ;
|
|
1374
|
+
var PSEUDO_MODEL_IDS, MODEL_SOURCE_RANK, DISPLAY_CNY_PER_USD, USAGE_POINT_FINAL_SEQ;
|
|
1360
1375
|
var init_trace = __esm({
|
|
1361
1376
|
"../contract/src/trace.ts"() {
|
|
1362
1377
|
"use strict";
|
|
1363
1378
|
PSEUDO_MODEL_IDS = ["default", "default[]", "auto"];
|
|
1379
|
+
MODEL_SOURCE_RANK = {
|
|
1380
|
+
runtime: 2,
|
|
1381
|
+
runtime_rollout: 2,
|
|
1382
|
+
requested: 1,
|
|
1383
|
+
session_override: 1,
|
|
1384
|
+
actor_config: 1,
|
|
1385
|
+
runtime_default: 1,
|
|
1386
|
+
unknown: 0
|
|
1387
|
+
};
|
|
1364
1388
|
DISPLAY_CNY_PER_USD = 7.2;
|
|
1365
1389
|
USAGE_POINT_FINAL_SEQ = 2147483647;
|
|
1366
1390
|
}
|
|
@@ -8506,14 +8530,46 @@ async function runACPSession(job, cfg) {
|
|
|
8506
8530
|
let runtimeReportedModel;
|
|
8507
8531
|
let requestedModelAccepted;
|
|
8508
8532
|
const reportedModel = () => pickReportedModel({ runtime: [routedModel, runtimeReportedModel], requested: requestedModelAccepted });
|
|
8533
|
+
let turnIndex = 0;
|
|
8534
|
+
let turnStartedMs = Date.now();
|
|
8535
|
+
let freshSession = true;
|
|
8536
|
+
let routedPollInflight = false;
|
|
8509
8537
|
const pollRoutedModel = async () => {
|
|
8510
|
-
if (
|
|
8511
|
-
if (actualModelId(runtimeReportedModel)) return;
|
|
8538
|
+
if (!cfg.readRoutedModel || !capturedSessionId || exited) return false;
|
|
8539
|
+
if (actualModelId(runtimeReportedModel)) return true;
|
|
8540
|
+
if (routedPollInflight) return false;
|
|
8541
|
+
routedPollInflight = true;
|
|
8542
|
+
const turn = turnIndex;
|
|
8512
8543
|
try {
|
|
8513
|
-
|
|
8544
|
+
const found2 = actualModelId(await cfg.readRoutedModel(capturedSessionId, {
|
|
8545
|
+
turnStartedMs,
|
|
8546
|
+
freshSession
|
|
8547
|
+
}));
|
|
8548
|
+
if (!found2 || turn !== turnIndex) return false;
|
|
8549
|
+
if (found2 !== routedModel) {
|
|
8550
|
+
routedModel = found2;
|
|
8551
|
+
emitUsageCheckpoint();
|
|
8552
|
+
}
|
|
8553
|
+
return true;
|
|
8514
8554
|
} catch {
|
|
8555
|
+
return false;
|
|
8556
|
+
} finally {
|
|
8557
|
+
routedPollInflight = false;
|
|
8515
8558
|
}
|
|
8516
|
-
|
|
8559
|
+
};
|
|
8560
|
+
const ROUTED_MODEL_POLL_DELAYS_MS = [0, 150, 400, 900, 2e3];
|
|
8561
|
+
let routedSamplingTurn = -1;
|
|
8562
|
+
const startRoutedModelSampling = () => {
|
|
8563
|
+
if (!cfg.readRoutedModel || routedSamplingTurn === turnIndex) return;
|
|
8564
|
+
routedSamplingTurn = turnIndex;
|
|
8565
|
+
const turn = turnIndex;
|
|
8566
|
+
void (async () => {
|
|
8567
|
+
for (const delay of ROUTED_MODEL_POLL_DELAYS_MS) {
|
|
8568
|
+
if (delay > 0) await new Promise((r) => setTimeout(r, delay));
|
|
8569
|
+
if (exited || turn !== turnIndex) return;
|
|
8570
|
+
if (await pollRoutedModel()) return;
|
|
8571
|
+
}
|
|
8572
|
+
})();
|
|
8517
8573
|
};
|
|
8518
8574
|
const modelForUsage = () => reportedModel()?.model;
|
|
8519
8575
|
const usageCheckpointCbs = [];
|
|
@@ -8639,11 +8695,15 @@ ${note}` : note };
|
|
|
8639
8695
|
},
|
|
8640
8696
|
(text7) => {
|
|
8641
8697
|
confirmAppendBatch();
|
|
8698
|
+
startRoutedModelSampling();
|
|
8642
8699
|
if (cfg.classifyPromptFailure && turnMessage.length < PROMPT_TURN_MESSAGE_MAX) turnMessage += text7;
|
|
8643
8700
|
for (const cb of outputCbs) cb(text7);
|
|
8644
8701
|
},
|
|
8645
8702
|
(e) => {
|
|
8646
|
-
if (["message", "thought", "tool_use", "tool_result"].includes(e.kind))
|
|
8703
|
+
if (["message", "thought", "tool_use", "tool_result"].includes(e.kind)) {
|
|
8704
|
+
confirmAppendBatch();
|
|
8705
|
+
startRoutedModelSampling();
|
|
8706
|
+
}
|
|
8647
8707
|
for (const cb of telemetryCbs) cb(e);
|
|
8648
8708
|
},
|
|
8649
8709
|
// runtime 自己用 stopReason=cancelled 收尾时也保留取消语义;此前误记成 error,
|
|
@@ -8712,6 +8772,7 @@ ${note}` : note };
|
|
|
8712
8772
|
sessionId = job.runtimeSessionId;
|
|
8713
8773
|
ambiguousResume = true;
|
|
8714
8774
|
}
|
|
8775
|
+
if (sessionId) freshSession = false;
|
|
8715
8776
|
} catch {
|
|
8716
8777
|
sessionId = "";
|
|
8717
8778
|
}
|
|
@@ -8725,6 +8786,7 @@ ${note}` : note };
|
|
|
8725
8786
|
sessionId = extractSessionID(sessionRes);
|
|
8726
8787
|
runtimeReportedModel = extractCurrentModelID(sessionRes) ?? runtimeReportedModel;
|
|
8727
8788
|
if (!sessionId) throw new Error("session/new returned no sessionId");
|
|
8789
|
+
freshSession = true;
|
|
8728
8790
|
}
|
|
8729
8791
|
capturedSessionId = sessionId;
|
|
8730
8792
|
if (resolvedModel2) {
|
|
@@ -8761,6 +8823,8 @@ ${task}` : task;
|
|
|
8761
8823
|
const sendPrompt = async (text7) => {
|
|
8762
8824
|
turnMessage = "";
|
|
8763
8825
|
turnStderr = [];
|
|
8826
|
+
turnIndex += 1;
|
|
8827
|
+
turnStartedMs = Date.now();
|
|
8764
8828
|
const p2 = client.request("session/prompt", { sessionId, prompt: [{ type: "text", text: text7 }] });
|
|
8765
8829
|
inflightStopReason = p2.then((r) => extractStopReason(r), () => "");
|
|
8766
8830
|
try {
|
|
@@ -8780,6 +8844,7 @@ ${task}` : task;
|
|
|
8780
8844
|
sessionId = extractSessionID(sessionRes);
|
|
8781
8845
|
runtimeReportedModel = extractCurrentModelID(sessionRes) ?? runtimeReportedModel;
|
|
8782
8846
|
if (!sessionId) throw new Error("session/new returned no sessionId");
|
|
8847
|
+
freshSession = true;
|
|
8783
8848
|
capturedSessionId = sessionId;
|
|
8784
8849
|
emitUsageCheckpoint();
|
|
8785
8850
|
promptResult = await sendPrompt(userText);
|
|
@@ -9548,14 +9613,59 @@ function pickCursorModelName(value2) {
|
|
|
9548
9613
|
};
|
|
9549
9614
|
return visit(value2, 0) ?? fallback;
|
|
9550
9615
|
}
|
|
9551
|
-
function
|
|
9552
|
-
if (typeof cell !== "string"
|
|
9616
|
+
function parseCell(cell) {
|
|
9617
|
+
if (typeof cell !== "string") return void 0;
|
|
9553
9618
|
try {
|
|
9554
|
-
return
|
|
9619
|
+
return JSON.parse(cell);
|
|
9555
9620
|
} catch {
|
|
9556
9621
|
return void 0;
|
|
9557
9622
|
}
|
|
9558
9623
|
}
|
|
9624
|
+
function looksLikeTimeKey(key2) {
|
|
9625
|
+
const tokens2 = key2.replace(/([a-z0-9])([A-Z])/g, "$1 $2").toLowerCase().split(/[^a-z0-9]+/).filter(Boolean);
|
|
9626
|
+
const last = tokens2[tokens2.length - 1];
|
|
9627
|
+
if (!last || !TIME_KEY_TAILS.includes(last)) return false;
|
|
9628
|
+
return last !== "at" || tokens2.length > 1;
|
|
9629
|
+
}
|
|
9630
|
+
function cursorTimeValueMs(value2) {
|
|
9631
|
+
if (typeof value2 === "bigint") return cursorTimeValueMs(Number(value2));
|
|
9632
|
+
if (typeof value2 === "number") {
|
|
9633
|
+
if (!Number.isFinite(value2)) return void 0;
|
|
9634
|
+
if (value2 > 1e15) return Math.floor(value2 / 1e3);
|
|
9635
|
+
if (value2 > 1e12) return value2;
|
|
9636
|
+
if (value2 > 1e9) return value2 * 1e3;
|
|
9637
|
+
return void 0;
|
|
9638
|
+
}
|
|
9639
|
+
if (typeof value2 === "string") {
|
|
9640
|
+
const t = value2.trim();
|
|
9641
|
+
if (!t) return void 0;
|
|
9642
|
+
if (/^\d+$/.test(t)) return cursorTimeValueMs(Number(t));
|
|
9643
|
+
const ms = Date.parse(t);
|
|
9644
|
+
return Number.isFinite(ms) ? ms : void 0;
|
|
9645
|
+
}
|
|
9646
|
+
return void 0;
|
|
9647
|
+
}
|
|
9648
|
+
function cursorRowTimeMs(row, parsedCells) {
|
|
9649
|
+
let best;
|
|
9650
|
+
const take = (v2) => {
|
|
9651
|
+
const ms = cursorTimeValueMs(v2);
|
|
9652
|
+
if (ms !== void 0 && (best === void 0 || ms > best)) best = ms;
|
|
9653
|
+
};
|
|
9654
|
+
for (const [key2, value2] of Object.entries(row)) if (looksLikeTimeKey(key2)) take(value2);
|
|
9655
|
+
const visit = (node2, depth) => {
|
|
9656
|
+
if (depth > 8 || node2 === null || typeof node2 !== "object") return;
|
|
9657
|
+
if (Array.isArray(node2)) {
|
|
9658
|
+
for (const item of node2) visit(item, depth + 1);
|
|
9659
|
+
return;
|
|
9660
|
+
}
|
|
9661
|
+
for (const [key2, value2] of Object.entries(node2)) {
|
|
9662
|
+
if (looksLikeTimeKey(key2)) take(value2);
|
|
9663
|
+
visit(value2, depth + 1);
|
|
9664
|
+
}
|
|
9665
|
+
};
|
|
9666
|
+
for (const parsed of parsedCells) visit(parsed, 0);
|
|
9667
|
+
return best;
|
|
9668
|
+
}
|
|
9559
9669
|
async function openReadOnly(file) {
|
|
9560
9670
|
try {
|
|
9561
9671
|
const sqlite = await import("node:sqlite");
|
|
@@ -9564,7 +9674,9 @@ async function openReadOnly(file) {
|
|
|
9564
9674
|
return null;
|
|
9565
9675
|
}
|
|
9566
9676
|
}
|
|
9567
|
-
async function readCursorRoutedModel(sessionId,
|
|
9677
|
+
async function readCursorRoutedModel(sessionId, window3) {
|
|
9678
|
+
const env = window3.env ?? process.env;
|
|
9679
|
+
const earliest = window3.turnStartedMs - TURN_CLOCK_TOLERANCE_MS;
|
|
9568
9680
|
const file = cursorAcpSessionStorePath(sessionId, env);
|
|
9569
9681
|
if (!file) return void 0;
|
|
9570
9682
|
const db = await openReadOnly(file);
|
|
@@ -9580,10 +9692,17 @@ async function readCursorRoutedModel(sessionId, env = process.env) {
|
|
|
9580
9692
|
continue;
|
|
9581
9693
|
}
|
|
9582
9694
|
for (const row of rows) {
|
|
9583
|
-
|
|
9584
|
-
|
|
9585
|
-
|
|
9695
|
+
const cells = Object.values(row);
|
|
9696
|
+
if (!cells.some((cell) => typeof cell === "string" && cell.includes("modelName"))) continue;
|
|
9697
|
+
const parsed = cells.map(parseCell);
|
|
9698
|
+
const model = parsed.map((value2) => value2 === void 0 ? void 0 : pickCursorModelName(value2)).find((name) => !!name);
|
|
9699
|
+
if (!model) continue;
|
|
9700
|
+
const rowMs = cursorRowTimeMs(row, parsed);
|
|
9701
|
+
if (rowMs !== void 0) {
|
|
9702
|
+
if (rowMs >= earliest) return model;
|
|
9703
|
+
continue;
|
|
9586
9704
|
}
|
|
9705
|
+
if (window3.freshSession) return model;
|
|
9587
9706
|
}
|
|
9588
9707
|
}
|
|
9589
9708
|
return void 0;
|
|
@@ -9596,7 +9715,7 @@ async function readCursorRoutedModel(sessionId, env = process.env) {
|
|
|
9596
9715
|
}
|
|
9597
9716
|
}
|
|
9598
9717
|
}
|
|
9599
|
-
var fs10, os6, path12, MAX_TABLES, MAX_ROWS_PER_TABLE;
|
|
9718
|
+
var fs10, os6, path12, MAX_TABLES, MAX_ROWS_PER_TABLE, TURN_CLOCK_TOLERANCE_MS, TIME_KEY_TAILS;
|
|
9600
9719
|
var init_local_store = __esm({
|
|
9601
9720
|
"../adapters/src/cursor/local-store.ts"() {
|
|
9602
9721
|
"use strict";
|
|
@@ -9605,6 +9724,8 @@ var init_local_store = __esm({
|
|
|
9605
9724
|
path12 = __toESM(require("node:path"), 1);
|
|
9606
9725
|
MAX_TABLES = 24;
|
|
9607
9726
|
MAX_ROWS_PER_TABLE = 200;
|
|
9727
|
+
TURN_CLOCK_TOLERANCE_MS = 1e3;
|
|
9728
|
+
TIME_KEY_TAILS = ["at", "ts", "time", "timestamp", "date", "millis", "epoch"];
|
|
9608
9729
|
}
|
|
9609
9730
|
});
|
|
9610
9731
|
|
|
@@ -9652,7 +9773,7 @@ var init_cursor = __esm({
|
|
|
9652
9773
|
// 采集点 4:「自动」档下 cursor 对外只报 `default[]`(不是型号、查不到价,v2 上 385 条记的就是它),
|
|
9653
9774
|
// 而它自己的 `~/.cursor/acp-sessions/<会话号>/store.db` 里逐条回复都带实际路由到的模型。
|
|
9654
9775
|
// 这是 cursor 的内部格式:读不到就退回会话级自报值,绝不报错(见 local-store.ts)。
|
|
9655
|
-
readRoutedModel: (sessionId) => readCursorRoutedModel(sessionId),
|
|
9776
|
+
readRoutedModel: (sessionId, window3) => readCursorRoutedModel(sessionId, window3),
|
|
9656
9777
|
...this.opts.syncSkills ? { syncSkills: this.opts.syncSkills } : {}
|
|
9657
9778
|
});
|
|
9658
9779
|
}
|
|
@@ -35188,7 +35309,7 @@ var require_websocket = __commonJS({
|
|
|
35188
35309
|
var http2 = require("http");
|
|
35189
35310
|
var net = require("net");
|
|
35190
35311
|
var tls = require("tls");
|
|
35191
|
-
var { randomBytes:
|
|
35312
|
+
var { randomBytes: randomBytes15, createHash: createHash45 } = require("crypto");
|
|
35192
35313
|
var { Duplex, Readable } = require("stream");
|
|
35193
35314
|
var { URL: URL2 } = require("url");
|
|
35194
35315
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -35726,7 +35847,7 @@ var require_websocket = __commonJS({
|
|
|
35726
35847
|
}
|
|
35727
35848
|
}
|
|
35728
35849
|
const defaultPort = isSecure ? 443 : 80;
|
|
35729
|
-
const key2 =
|
|
35850
|
+
const key2 = randomBytes15(16).toString("base64");
|
|
35730
35851
|
const request2 = isSecure ? https.request : http2.request;
|
|
35731
35852
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
35732
35853
|
let perMessageDeflate;
|
|
@@ -130137,7 +130258,7 @@ var require_utils3 = __commonJS({
|
|
|
130137
130258
|
var nodeCrypto = require("crypto");
|
|
130138
130259
|
module2.exports = {
|
|
130139
130260
|
postgresMd5PasswordHash,
|
|
130140
|
-
randomBytes:
|
|
130261
|
+
randomBytes: randomBytes15,
|
|
130141
130262
|
deriveKey,
|
|
130142
130263
|
sha256: sha2563,
|
|
130143
130264
|
hashByName,
|
|
@@ -130147,7 +130268,7 @@ var require_utils3 = __commonJS({
|
|
|
130147
130268
|
var webCrypto = nodeCrypto.webcrypto || globalThis.crypto;
|
|
130148
130269
|
var subtleCrypto = webCrypto.subtle;
|
|
130149
130270
|
var textEncoder = new TextEncoder();
|
|
130150
|
-
function
|
|
130271
|
+
function randomBytes15(length) {
|
|
130151
130272
|
return webCrypto.getRandomValues(Buffer.alloc(length));
|
|
130152
130273
|
}
|
|
130153
130274
|
async function md5(string7) {
|
|
@@ -140939,16 +141060,32 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
140939
141060
|
//
|
|
140940
141061
|
// 这些字段不能成为「没做完也能交」的出口:真正未满足交付标准时继续完成,外部阻塞走 oasis gap。
|
|
140941
141062
|
// 四项本身只传递一份已达标成果的非阻塞残余信息,不参与 conclude 判据。
|
|
140942
|
-
|
|
141063
|
+
//
|
|
141064
|
+
// ★ 2026-09-23(语菲,验收用例 H-01):此前只列参数名、没说挂在哪条命令上,agent 常把它们写到
|
|
141065
|
+
// `oasis conclude` 上——conclude 只收 `--note`,其余参数被静默丢掉(v2 上 143 次执行里写过这四项
|
|
141066
|
+
// 16 次,6 次写在 conclude 上、全丢)。所以点名「是 propose 的参数」并给一条**追加式**示例:
|
|
141067
|
+
// 只示范「在那条命令末尾加上什么」,不给整条 propose——design(交稿目录不是 deliverable/)、
|
|
141068
|
+
// 分批续跑(要带 --checkpoint --continue)各有自己的提交命令,照抄一整条会交错目录或漏参数。
|
|
141069
|
+
// 「没有就连参数名也不写」:只写参数名不跟值会被 parseArgs 拒(CLI 侧已对这四项放宽为空值,
|
|
141070
|
+
// 但未升级的节点包仍会拒),提示词也把这条路堵上。
|
|
141071
|
+
//
|
|
141072
|
+
// 集成会话(integrating || queueTaskDue)不出这段:那一档「怎么提交」明令「绝不要用 oasis propose」,
|
|
141073
|
+
// 而 `oasis integrate` 也不收这四项——再教「这是 propose 的参数」只会把它引去 propose,
|
|
141074
|
+
// 队列从 N 变 N+1、随后 conclude 撞 queue not quiescent(本文件「怎么提交」那段注释记的卡死形状)。
|
|
141075
|
+
...args.action === "review" || integrating || queueTaskDue ? [] : [
|
|
140943
141076
|
``,
|
|
140944
141077
|
`### \u4EA4\u4ED8\u65F6\u7684\u975E\u963B\u585E\u4FE1\u606F`,
|
|
140945
|
-
|
|
140946
|
-
|
|
141078
|
+
`\u4E0B\u9762\u51E0\u9879\u662F\u4EA4\u4ED8\u547D\u4EE4\uFF08\`oasis propose\`\uFF09\u7684\u53C2\u6570\uFF0C\u76F4\u63A5\u52A0\u5728\u90A3\u6761\u547D\u4EE4\u540E\u9762\uFF0C\u548C \`--reason\` \u5199\u5728\u4E00\u8D77\uFF1B\`oasis conclude\` \u53EA\u6536 \`--note\`\uFF0C\u5199\u5728 conclude \u4E0A\u7684\u5176\u5B83\u53C2\u6570\u4E0D\u4F1A\u88AB\u8BB0\u5F55\u3002`,
|
|
141079
|
+
`\`--reason\` \u5199\u660E\u76F8\u5BF9\u4E0A\u4E00\u7248\u6539\u4E86\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48\u3001\u53EF\u80FD\u5F71\u54CD\u4EC0\u4E48\uFF1B\u9996\u6B21\u7248\u672C\u8BF4\u660E\u672C\u7248\u5B8C\u6210\u601D\u8DEF\u548C\u5185\u5BB9\u3002`,
|
|
141080
|
+
`\u53EA\u6709\u5F53\u524D\u7248\u672C\u5DF2\u7ECF\u8FBE\u5230\u4EA4\u4ED8\u6807\u51C6\u65F6\uFF0C\u624D\u53EF\u4EE5\u8BB0\u5F55\uFF08\u6BCF\u9879\u53EF\u4EE5\u5199\u591A\u6761\uFF0C\u7528\u82F1\u6587\u5206\u53F7 \`;\` \u9694\u5F00\uFF1B\u4EE5\u4E0B\u67D0\u4E00\u9879\u5982\u679C\u6CA1\u6709\u5C31\u4E0D\u5199\uFF0C\u540C\u65F6\u8BE5\u53C2\u6570\u4E5F\u4E0D\u5199\uFF09\uFF1A`,
|
|
140947
141081
|
`- \`--unresolved\`\uFF1A\u4EFB\u52A1\u8303\u56F4\u4E4B\u5916\u7684\u5DF2\u77E5\u95EE\u9898\uFF1B`,
|
|
140948
141082
|
`- \`--risks\`\uFF1A\u6210\u679C\u53EF\u4EA4\u4ED8\uFF0C\u4F46\u4F7F\u7528\u65F6\u9700\u6CE8\u610F\u7684\u6B8B\u4F59\u98CE\u9669\uFF1B`,
|
|
140949
141083
|
`- \`--gaps\`\uFF1A\u4E0D\u5C5E\u4E8E\u672C\u6B21\u5F3A\u5236\u9A8C\u6536\u6761\u4EF6\u7684\u9A8C\u8BC1\u8303\u56F4\u9650\u5236\uFF1B`,
|
|
140950
141084
|
`- \`--next\`\uFF1A\u4E0B\u6E38\u5982\u4F55\u4F7F\u7528\u6210\u679C\uFF0C\u4E0D\u662F\u4F60\u5269\u4F59\u6CA1\u505A\u7684\u5DE5\u4F5C\u3002`,
|
|
140951
|
-
`\
|
|
141085
|
+
`\u4F8B\u5982\u5728\u90A3\u6761\u547D\u4EE4\u672B\u5C3E\u52A0\u4E0A\uFF1A\`--risks "<\u98CE\u9669\u4E00>; <\u98CE\u9669\u4E8C>" --next "<\u4E0B\u6E38\u600E\u4E48\u7528>"\``,
|
|
141086
|
+
`\u672A\u8FBE\u5230\u4EA4\u4ED8\u6807\u51C6\u7684\u4E8B\u9879\u4E0D\u80FD\u653E\u5728\u8FD9\u91CC\uFF0C\u5E94\u7EE7\u7EED\u5B8C\u6210\u6216\u8FD0\u884C \`oasis gap\`\u3002`
|
|
141087
|
+
],
|
|
141088
|
+
...args.action === "review" ? [] : [
|
|
140952
141089
|
``,
|
|
140953
141090
|
`### \u4F1A\u8BDD\u53EF\u80FD\u88AB\u780D\uFF1A\u4E2D\u9014\u7559\u4E2A\u65AD\u70B9`,
|
|
140954
141091
|
// ★ 2026-08-18:`continuity-checkpoint` 此前在任务书里出现 **0 次**——说明书只在
|
|
@@ -208705,11 +208842,17 @@ var init_app_adopt = __esm({
|
|
|
208705
208842
|
});
|
|
208706
208843
|
|
|
208707
208844
|
// ../connectors/src/github/app-manifest.ts
|
|
208845
|
+
function randomAppNameSuffix() {
|
|
208846
|
+
const alphabet = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
208847
|
+
return Array.from((0, import_node_crypto42.randomBytes)(4), (b2) => alphabet[b2 % alphabet.length]).join("");
|
|
208848
|
+
}
|
|
208708
208849
|
function buildAppManifest(args) {
|
|
208709
208850
|
const base = args.baseUrl.replace(/\/+$/, "");
|
|
208851
|
+
const suffix = args.nameSuffix ?? randomAppNameSuffix();
|
|
208852
|
+
const room = GITHUB_APP_NAME_MAX - args.namePrefix.length - suffix.length - 2;
|
|
208853
|
+
const middle = args.employeeSlug.slice(0, Math.max(0, room)).replace(/-+$/, "");
|
|
208710
208854
|
return {
|
|
208711
|
-
name:
|
|
208712
|
-
// GitHub App 名上限 34 字符
|
|
208855
|
+
name: [args.namePrefix, middle, suffix].filter(Boolean).join("-"),
|
|
208713
208856
|
url: base,
|
|
208714
208857
|
redirect_url: `${base}${args.redirectPath}`,
|
|
208715
208858
|
public: false,
|
|
@@ -208787,10 +208930,11 @@ function checkAppOwnership(conv, want) {
|
|
|
208787
208930
|
}
|
|
208788
208931
|
return null;
|
|
208789
208932
|
}
|
|
208790
|
-
var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, REQUIRED_WRITE_PERMISSIONS, PERMISSION_RANK, FORBIDDEN_IMPORT_PERMISSION_KEYS;
|
|
208933
|
+
var import_node_crypto42, GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, GITHUB_APP_NAME_MAX, PENDING_TTL_MS, REQUIRED_WRITE_PERMISSIONS, PERMISSION_RANK, FORBIDDEN_IMPORT_PERMISSION_KEYS;
|
|
208791
208934
|
var init_app_manifest = __esm({
|
|
208792
208935
|
"../connectors/src/github/app-manifest.ts"() {
|
|
208793
208936
|
"use strict";
|
|
208937
|
+
import_node_crypto42 = require("node:crypto");
|
|
208794
208938
|
GITHUB_APP_DEFAULT_PERMISSIONS = {
|
|
208795
208939
|
contents: "write",
|
|
208796
208940
|
// clone / push
|
|
@@ -208819,6 +208963,7 @@ var init_app_manifest = __esm({
|
|
|
208819
208963
|
{ key: "workflows", label: "\u5DE5\u4F5C\u6D41\u6587\u4EF6\uFF08\u8BFB\u5199\uFF09", desc: "\u4FEE\u6539 .github/workflows \u4E0B\u7684 CI \u914D\u7F6E" },
|
|
208820
208964
|
{ key: "issues", label: "Issue\uFF08\u8BFB\u5199\uFF09", desc: "\u521B\u5EFA\u4E0E\u8BC4\u8BBA Issue" }
|
|
208821
208965
|
];
|
|
208966
|
+
GITHUB_APP_NAME_MAX = 34;
|
|
208822
208967
|
PENDING_TTL_MS = 15 * 60 * 1e3;
|
|
208823
208968
|
REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
|
|
208824
208969
|
PERMISSION_RANK = { read: 1, write: 2, admin: 3 };
|
|
@@ -208835,6 +208980,195 @@ var init_app_manifest = __esm({
|
|
|
208835
208980
|
}
|
|
208836
208981
|
});
|
|
208837
208982
|
|
|
208983
|
+
// ../connectors/src/github/app-inventory.ts
|
|
208984
|
+
function permissionVerdict(perms) {
|
|
208985
|
+
const missingRequired = REQUIRED_WRITE.filter((k2) => perms[k2] !== "write" && perms[k2] !== "admin");
|
|
208986
|
+
const excess = excessAppPermissions(perms);
|
|
208987
|
+
return {
|
|
208988
|
+
missingRequired: [...missingRequired],
|
|
208989
|
+
missing: missingAppPermissions(perms),
|
|
208990
|
+
excess,
|
|
208991
|
+
usable: missingRequired.length === 0 && excess.length === 0
|
|
208992
|
+
};
|
|
208993
|
+
}
|
|
208994
|
+
async function listOrgInstalledApps(args, deps = {}) {
|
|
208995
|
+
const d = { ...defaultDeps3, ...deps };
|
|
208996
|
+
let resp;
|
|
208997
|
+
try {
|
|
208998
|
+
resp = await d.fetch(`${GITHUB_API2}/orgs/${encodeURIComponent(args.org)}/installations?per_page=100`, {
|
|
208999
|
+
headers: {
|
|
209000
|
+
authorization: `Bearer ${args.token}`,
|
|
209001
|
+
accept: "application/vnd.github+json",
|
|
209002
|
+
"x-github-api-version": "2022-11-28"
|
|
209003
|
+
}
|
|
209004
|
+
});
|
|
209005
|
+
} catch (e) {
|
|
209006
|
+
return { status: "error", message: String(e) };
|
|
209007
|
+
}
|
|
209008
|
+
if (resp.status === 401 || resp.status === 403) return { status: "needsAuth", httpStatus: resp.status };
|
|
209009
|
+
const body2 = await resp.json().catch(() => ({}));
|
|
209010
|
+
if (!resp.ok) return { status: "error", message: `GitHub \u8FD4\u56DE HTTP ${resp.status} ${String(body2["message"] ?? "")}`.trim() };
|
|
209011
|
+
const list2 = Array.isArray(body2["installations"]) ? body2["installations"] : [];
|
|
209012
|
+
const all2 = list2.flatMap((raw) => {
|
|
209013
|
+
const item = raw;
|
|
209014
|
+
const appId = item["app_id"] === void 0 ? "" : String(item["app_id"]);
|
|
209015
|
+
const installationId = item["id"] === void 0 ? "" : String(item["id"]);
|
|
209016
|
+
if (!appId || !installationId) return [];
|
|
209017
|
+
const rawPerms = item["permissions"];
|
|
209018
|
+
const permissions = {};
|
|
209019
|
+
for (const [k2, v2] of Object.entries(rawPerms ?? {})) if (typeof v2 === "string") permissions[k2] = v2;
|
|
209020
|
+
return [{ appId, slug: String(item["app_slug"] ?? ""), installationId, org: args.org, permissions }];
|
|
209021
|
+
});
|
|
209022
|
+
const owned = await Promise.all(all2.map(async (app) => {
|
|
209023
|
+
if (!app.slug) return app;
|
|
209024
|
+
try {
|
|
209025
|
+
const r = await d.fetch(`${GITHUB_API2}/apps/${encodeURIComponent(app.slug)}`, {
|
|
209026
|
+
headers: {
|
|
209027
|
+
authorization: `Bearer ${args.token}`,
|
|
209028
|
+
accept: "application/vnd.github+json",
|
|
209029
|
+
"x-github-api-version": "2022-11-28"
|
|
209030
|
+
}
|
|
209031
|
+
});
|
|
209032
|
+
if (!r.ok) return app;
|
|
209033
|
+
const meta = await r.json().catch(() => ({}));
|
|
209034
|
+
const login = meta.owner?.login;
|
|
209035
|
+
return login && login.toLowerCase() !== args.org.toLowerCase() ? null : app;
|
|
209036
|
+
} catch {
|
|
209037
|
+
return app;
|
|
209038
|
+
}
|
|
209039
|
+
}));
|
|
209040
|
+
return { status: "ok", apps: owned.filter((a) => a !== null) };
|
|
209041
|
+
}
|
|
209042
|
+
async function uninstallAppInstallation(args, deps = {}) {
|
|
209043
|
+
const d = { ...defaultDeps3, ...deps };
|
|
209044
|
+
const jwt = createAppJwt(args.appId, args.privateKeyPem, d.nowMs());
|
|
209045
|
+
const resp = await d.fetch(`${GITHUB_API2}/app/installations/${encodeURIComponent(args.installationId)}`, {
|
|
209046
|
+
method: "DELETE",
|
|
209047
|
+
headers: {
|
|
209048
|
+
authorization: `Bearer ${jwt}`,
|
|
209049
|
+
accept: "application/vnd.github+json",
|
|
209050
|
+
"x-github-api-version": "2022-11-28"
|
|
209051
|
+
}
|
|
209052
|
+
});
|
|
209053
|
+
if (resp.status === 204 || resp.status === 404) return;
|
|
209054
|
+
const body2 = await resp.json().catch(() => ({}));
|
|
209055
|
+
throw new Error(`github app: uninstall failed HTTP ${resp.status} ${String(body2["message"] ?? "")}`.trim());
|
|
209056
|
+
}
|
|
209057
|
+
function appSettingsUrl(owner, slug6) {
|
|
209058
|
+
const s2 = encodeURIComponent(slug6);
|
|
209059
|
+
return owner.kind === "org" ? `https://github.com/organizations/${encodeURIComponent(owner.login)}/settings/apps/${s2}` : `https://github.com/settings/apps/${s2}`;
|
|
209060
|
+
}
|
|
209061
|
+
function appInstallPageUrl(slug6) {
|
|
209062
|
+
return `https://github.com/apps/${encodeURIComponent(slug6)}/installations/new`;
|
|
209063
|
+
}
|
|
209064
|
+
function appDeleteUrl(owner, slug6) {
|
|
209065
|
+
return `${appSettingsUrl(owner, slug6)}/advanced`;
|
|
209066
|
+
}
|
|
209067
|
+
function ownerMatches(app, owner) {
|
|
209068
|
+
if (owner.kind === "org") {
|
|
209069
|
+
return app.ownerType === "Organization" && app.ownerLogin.toLowerCase() === owner.login.toLowerCase();
|
|
209070
|
+
}
|
|
209071
|
+
if (app.ownerType !== "User") return false;
|
|
209072
|
+
return !owner.login || app.ownerLogin.toLowerCase() === owner.login.toLowerCase();
|
|
209073
|
+
}
|
|
209074
|
+
function buildReuseCandidates(args) {
|
|
209075
|
+
const { owner } = args;
|
|
209076
|
+
const known = new Set(args.oasisApps.map((a2) => a2.appId));
|
|
209077
|
+
const a = args.oasisApps.filter((app) => ownerMatches(app, owner)).map((app) => {
|
|
209078
|
+
const verdict = app.permissions ? permissionVerdict(app.permissions) : null;
|
|
209079
|
+
const selectable = verdict ? verdict.usable : true;
|
|
209080
|
+
const action = !selectable ? "blocked" : app.installationIds.length === 0 ? "install" : "bind";
|
|
209081
|
+
return {
|
|
209082
|
+
kind: "oasis",
|
|
209083
|
+
action,
|
|
209084
|
+
appId: app.appId,
|
|
209085
|
+
slug: app.slug,
|
|
209086
|
+
...app.installationIds[0] ? { installationId: app.installationIds[0] } : {},
|
|
209087
|
+
usedBy: app.usedBy,
|
|
209088
|
+
isOrgDefault: app.isOrgDefault,
|
|
209089
|
+
permissionsUnknown: !verdict,
|
|
209090
|
+
verdict,
|
|
209091
|
+
selectable,
|
|
209092
|
+
settingsUrl: appSettingsUrl(owner, app.slug),
|
|
209093
|
+
permissionsUrl: `${appSettingsUrl(owner, app.slug)}/permissions`,
|
|
209094
|
+
installUrl: appInstallPageUrl(app.slug)
|
|
209095
|
+
};
|
|
209096
|
+
});
|
|
209097
|
+
const b2 = owner.kind === "org" ? args.installed.filter((i) => !known.has(i.appId) && i.org.toLowerCase() === owner.login.toLowerCase()).map((i) => {
|
|
209098
|
+
const verdict = permissionVerdict(i.permissions);
|
|
209099
|
+
return {
|
|
209100
|
+
kind: "installed",
|
|
209101
|
+
action: verdict.usable ? "import" : "blocked",
|
|
209102
|
+
appId: i.appId,
|
|
209103
|
+
slug: i.slug,
|
|
209104
|
+
installationId: i.installationId,
|
|
209105
|
+
usedBy: [],
|
|
209106
|
+
isOrgDefault: false,
|
|
209107
|
+
permissionsUnknown: false,
|
|
209108
|
+
verdict,
|
|
209109
|
+
selectable: verdict.usable,
|
|
209110
|
+
settingsUrl: appSettingsUrl(owner, i.slug),
|
|
209111
|
+
permissionsUrl: `${appSettingsUrl(owner, i.slug)}/permissions`,
|
|
209112
|
+
installUrl: appInstallPageUrl(i.slug)
|
|
209113
|
+
};
|
|
209114
|
+
}) : [];
|
|
209115
|
+
return [...a, ...b2].sort((x2, y) => Number(y.selectable) - Number(x2.selectable));
|
|
209116
|
+
}
|
|
209117
|
+
function buildAppInventory(args) {
|
|
209118
|
+
const rows = /* @__PURE__ */ new Map();
|
|
209119
|
+
const ownerOf = (login, type) => !login ? null : type === "Organization" ? { kind: "org", login } : { kind: "user", login };
|
|
209120
|
+
for (const app of args.oasisApps) {
|
|
209121
|
+
const inUse = app.isOrgDefault || app.usedBy.length > 0;
|
|
209122
|
+
const owner = ownerOf(app.ownerLogin, app.ownerType);
|
|
209123
|
+
rows.set(app.appId, {
|
|
209124
|
+
appId: app.appId,
|
|
209125
|
+
slug: app.slug,
|
|
209126
|
+
ownerLogin: app.ownerLogin,
|
|
209127
|
+
hasKey: true,
|
|
209128
|
+
usedBy: app.usedBy,
|
|
209129
|
+
isOrgDefault: app.isOrgDefault,
|
|
209130
|
+
inUse,
|
|
209131
|
+
installationIds: [...app.installationIds],
|
|
209132
|
+
canUninstall: !inUse && app.installationIds.length > 0,
|
|
209133
|
+
deleteUrl: owner && app.slug ? appDeleteUrl(owner, app.slug) : ""
|
|
209134
|
+
});
|
|
209135
|
+
}
|
|
209136
|
+
for (const i of args.installed) {
|
|
209137
|
+
const prev = rows.get(i.appId);
|
|
209138
|
+
if (prev) {
|
|
209139
|
+
if (!prev.installationIds.includes(i.installationId)) prev.installationIds.push(i.installationId);
|
|
209140
|
+
prev.canUninstall = !prev.inUse && prev.installationIds.length > 0;
|
|
209141
|
+
if (!prev.ownerLogin) prev.ownerLogin = i.org;
|
|
209142
|
+
if (!prev.deleteUrl && prev.slug) prev.deleteUrl = appDeleteUrl({ kind: "org", login: i.org }, prev.slug);
|
|
209143
|
+
continue;
|
|
209144
|
+
}
|
|
209145
|
+
rows.set(i.appId, {
|
|
209146
|
+
appId: i.appId,
|
|
209147
|
+
slug: i.slug,
|
|
209148
|
+
ownerLogin: i.org,
|
|
209149
|
+
hasKey: false,
|
|
209150
|
+
usedBy: [],
|
|
209151
|
+
isOrgDefault: false,
|
|
209152
|
+
inUse: false,
|
|
209153
|
+
installationIds: [i.installationId],
|
|
209154
|
+
canUninstall: false,
|
|
209155
|
+
deleteUrl: i.slug ? appDeleteUrl({ kind: "org", login: i.org }, i.slug) : ""
|
|
209156
|
+
});
|
|
209157
|
+
}
|
|
209158
|
+
return [...rows.values()].sort((x2, y) => Number(x2.inUse) - Number(y.inUse) || x2.slug.localeCompare(y.slug));
|
|
209159
|
+
}
|
|
209160
|
+
var GITHUB_API2, defaultDeps3, REQUIRED_WRITE;
|
|
209161
|
+
var init_app_inventory = __esm({
|
|
209162
|
+
"../connectors/src/github/app-inventory.ts"() {
|
|
209163
|
+
"use strict";
|
|
209164
|
+
init_app_auth();
|
|
209165
|
+
init_app_manifest();
|
|
209166
|
+
GITHUB_API2 = "https://api.github.com";
|
|
209167
|
+
defaultDeps3 = { fetch: (...a) => globalThis.fetch(...a), nowMs: () => Date.now() };
|
|
209168
|
+
REQUIRED_WRITE = ["contents", "pull_requests"];
|
|
209169
|
+
}
|
|
209170
|
+
});
|
|
209171
|
+
|
|
208838
209172
|
// ../connectors/src/registry.ts
|
|
208839
209173
|
function createConnectorBySlug(slug6) {
|
|
208840
209174
|
switch (slug6) {
|
|
@@ -209291,6 +209625,7 @@ var init_src8 = __esm({
|
|
|
209291
209625
|
init_app_auth();
|
|
209292
209626
|
init_app_adopt();
|
|
209293
209627
|
init_app_manifest();
|
|
209628
|
+
init_app_inventory();
|
|
209294
209629
|
init_registry2();
|
|
209295
209630
|
init_provision();
|
|
209296
209631
|
init_prepare_job();
|
|
@@ -209299,6 +209634,118 @@ var init_src8 = __esm({
|
|
|
209299
209634
|
}
|
|
209300
209635
|
});
|
|
209301
209636
|
|
|
209637
|
+
// ../server/src/github-app-inventory.ts
|
|
209638
|
+
async function collectOasisGithubApps(svc) {
|
|
209639
|
+
const rows = (await svc.listVariables()).filter((r) => r.scope === "global" || r.scope === "personal");
|
|
209640
|
+
const agents = await svc.listActors({ kind: "agent", status: "active" });
|
|
209641
|
+
const nameOf2 = new Map(agents.map((a) => [a.id, a.name || a.id]));
|
|
209642
|
+
const plain = (key2, actorId) => rows.find((r) => r.key === key2 && r.actorId === actorId && !r.encrypted)?.maskedValue ?? "";
|
|
209643
|
+
const byAppId = /* @__PURE__ */ new Map();
|
|
209644
|
+
for (const r of rows) {
|
|
209645
|
+
if (r.key !== "GITHUB_APP_ID" || r.encrypted || !r.maskedValue) continue;
|
|
209646
|
+
const e = byAppId.get(r.maskedValue) ?? {
|
|
209647
|
+
slug: "",
|
|
209648
|
+
installationId: "",
|
|
209649
|
+
keyActorId: void 0,
|
|
209650
|
+
usedBy: [],
|
|
209651
|
+
isOrgDefault: false,
|
|
209652
|
+
sources: []
|
|
209653
|
+
};
|
|
209654
|
+
e.sources.push(r.actorId);
|
|
209655
|
+
if (!r.actorId) e.isOrgDefault = true;
|
|
209656
|
+
else if (nameOf2.has(r.actorId) && !e.usedBy.includes(r.actorId)) e.usedBy.push(r.actorId);
|
|
209657
|
+
byAppId.set(r.maskedValue, e);
|
|
209658
|
+
}
|
|
209659
|
+
const out = await Promise.all([...byAppId.entries()].map(async ([appId, e]) => {
|
|
209660
|
+
let pem = null;
|
|
209661
|
+
let keyActorId;
|
|
209662
|
+
for (const src of [...e.sources].sort((a, b2) => Number(Boolean(a)) - Number(Boolean(b2)))) {
|
|
209663
|
+
pem = await svc.revealVariable("GITHUB_APP_PRIVATE_KEY", src).catch(() => null);
|
|
209664
|
+
if (pem) {
|
|
209665
|
+
keyActorId = src;
|
|
209666
|
+
break;
|
|
209667
|
+
}
|
|
209668
|
+
}
|
|
209669
|
+
if (!pem) return null;
|
|
209670
|
+
const slug6 = plain("GITHUB_APP_SLUG", keyActorId);
|
|
209671
|
+
const storedInstallationId = plain("GITHUB_APP_INSTALLATION_ID", keyActorId);
|
|
209672
|
+
const [meta, installs] = await Promise.all([
|
|
209673
|
+
fetchAppSelfMetadata({ appId, privateKeyPem: pem }).catch(() => null),
|
|
209674
|
+
listAppInstallations({ appId, privateKeyPem: pem }).catch(() => null)
|
|
209675
|
+
]);
|
|
209676
|
+
const stored = installs?.find((i) => i.installationId === storedInstallationId) ?? installs?.[0];
|
|
209677
|
+
const permissions = stored && Object.keys(stored.permissions).length > 0 ? stored.permissions : meta?.permissions ?? null;
|
|
209678
|
+
const app = {
|
|
209679
|
+
appId,
|
|
209680
|
+
slug: meta?.slug || slug6,
|
|
209681
|
+
ownerLogin: meta?.ownerLogin ?? "",
|
|
209682
|
+
ownerType: meta?.ownerType ?? "",
|
|
209683
|
+
usedBy: e.usedBy,
|
|
209684
|
+
usedByNames: e.usedBy.map((id) => nameOf2.get(id) ?? id),
|
|
209685
|
+
isOrgDefault: e.isOrgDefault,
|
|
209686
|
+
// 列不出来(私钥失效等)时退回库里记的那一处,卸载时 404 也当成功。
|
|
209687
|
+
installationIds: installs ? installs.map((i) => i.installationId) : storedInstallationId ? [storedInstallationId] : [],
|
|
209688
|
+
permissions,
|
|
209689
|
+
keyActorId
|
|
209690
|
+
};
|
|
209691
|
+
return app;
|
|
209692
|
+
}));
|
|
209693
|
+
return out.filter((a) => a !== null);
|
|
209694
|
+
}
|
|
209695
|
+
async function ghUser(token, path47) {
|
|
209696
|
+
const r = await fetch(`https://api.github.com${path47}`, {
|
|
209697
|
+
headers: {
|
|
209698
|
+
authorization: `Bearer ${token}`,
|
|
209699
|
+
accept: "application/vnd.github+json",
|
|
209700
|
+
"x-github-api-version": "2022-11-28"
|
|
209701
|
+
}
|
|
209702
|
+
});
|
|
209703
|
+
return { status: r.status, body: r.ok ? await r.json().catch(() => null) : null };
|
|
209704
|
+
}
|
|
209705
|
+
async function githubLoginOf(token) {
|
|
209706
|
+
const r = await ghUser(token, "/user").catch(() => null);
|
|
209707
|
+
return r?.body?.login ?? "";
|
|
209708
|
+
}
|
|
209709
|
+
async function listMemberships(token) {
|
|
209710
|
+
const r = await ghUser(
|
|
209711
|
+
token,
|
|
209712
|
+
"/user/memberships/orgs?state=active&per_page=100"
|
|
209713
|
+
);
|
|
209714
|
+
if (!r.body) return null;
|
|
209715
|
+
return r.body.flatMap((m2) => m2.organization?.login ? [{ login: m2.organization.login, role: m2.role ?? "member" }] : []);
|
|
209716
|
+
}
|
|
209717
|
+
async function orgInstalledAppsFor(token, org) {
|
|
209718
|
+
if (!token) return { state: { status: "needsAuth" }, apps: [] };
|
|
209719
|
+
const m2 = await ghUser(token, `/user/memberships/orgs/${encodeURIComponent(org)}`);
|
|
209720
|
+
if (m2.status === 401) return { state: { status: "needsAuth" }, apps: [] };
|
|
209721
|
+
if (m2.body && m2.body.role !== "admin") return { state: { status: "notAdmin" }, apps: [] };
|
|
209722
|
+
if (!m2.body && m2.status === 404) return { state: { status: "notAdmin" }, apps: [] };
|
|
209723
|
+
if (!m2.body) return { state: { status: "needsAuth" }, apps: [] };
|
|
209724
|
+
const r = await listOrgInstalledApps({ token, org });
|
|
209725
|
+
if (r.status === "ok") return { state: { status: "ok" }, apps: r.apps };
|
|
209726
|
+
if (r.status === "needsAuth") return { state: { status: "needsAuth" }, apps: [] };
|
|
209727
|
+
return { state: { status: "error", message: r.message }, apps: [] };
|
|
209728
|
+
}
|
|
209729
|
+
async function pickUserToken(svc) {
|
|
209730
|
+
const rows = await svc.listVariables();
|
|
209731
|
+
const sources = [void 0, ...rows.filter((r) => r.key === "GITHUB_TOKEN" && r.scope === "personal" && r.actorId).map((r) => r.actorId)];
|
|
209732
|
+
const tried = /* @__PURE__ */ new Set();
|
|
209733
|
+
for (const src of sources) {
|
|
209734
|
+
const token = await svc.revealVariable("GITHUB_TOKEN", src).catch(() => null);
|
|
209735
|
+
if (!token || tried.has(token)) continue;
|
|
209736
|
+
tried.add(token);
|
|
209737
|
+
const memberships = await listMemberships(token).catch(() => null);
|
|
209738
|
+
if (memberships) return { token, memberships };
|
|
209739
|
+
}
|
|
209740
|
+
return null;
|
|
209741
|
+
}
|
|
209742
|
+
var init_github_app_inventory = __esm({
|
|
209743
|
+
"../server/src/github-app-inventory.ts"() {
|
|
209744
|
+
"use strict";
|
|
209745
|
+
init_src8();
|
|
209746
|
+
}
|
|
209747
|
+
});
|
|
209748
|
+
|
|
209302
209749
|
// ../server/src/server.ts
|
|
209303
209750
|
function isBundleFrozen(err) {
|
|
209304
209751
|
return typeof err === "object" && err !== null && err.code === "TENANT_BUNDLE_FROZEN";
|
|
@@ -212740,7 +213187,7 @@ async function startOasisServer(opts) {
|
|
|
212740
213187
|
entry = {
|
|
212741
213188
|
// 旧 CLI 未带 waiterId 时给它塞一个服务端本地生成的——它绝不可能出现在 leave 上,
|
|
212742
213189
|
// 也就绝不会误命中 leftWaiterIds、绝不会被别人的 leave 摘掉。行为与旧 CLI 相同。
|
|
212743
|
-
waiterId: clientWaiterId ?? `server:${(0,
|
|
213190
|
+
waiterId: clientWaiterId ?? `server:${(0, import_node_crypto43.randomUUID)()}`,
|
|
212744
213191
|
onResolve,
|
|
212745
213192
|
expiresAt: expiresAt2,
|
|
212746
213193
|
cleanup: () => clearTimeout(expiryTimer),
|
|
@@ -214878,57 +215325,71 @@ ${composed}`;
|
|
|
214878
215325
|
}
|
|
214879
215326
|
if (url.pathname === "/api/connectors/github/app/available" && req.method === "POST") {
|
|
214880
215327
|
try {
|
|
215328
|
+
const { actorId, owner } = JSON.parse(rawBody || "{}");
|
|
214881
215329
|
const svc = await connectorActorsService();
|
|
214882
215330
|
if (!svc) throw new Error("actors service unavailable");
|
|
214883
|
-
const
|
|
214884
|
-
const
|
|
214885
|
-
const
|
|
214886
|
-
|
|
214887
|
-
|
|
214888
|
-
|
|
214889
|
-
|
|
214890
|
-
|
|
214891
|
-
|
|
214892
|
-
|
|
214893
|
-
|
|
214894
|
-
|
|
214895
|
-
|
|
214896
|
-
|
|
214897
|
-
|
|
214898
|
-
|
|
214899
|
-
|
|
214900
|
-
|
|
214901
|
-
|
|
214902
|
-
|
|
214903
|
-
|
|
214904
|
-
|
|
214905
|
-
|
|
214906
|
-
|
|
214907
|
-
})
|
|
215331
|
+
const token = await svc.revealResolvedVariable("GITHUB_TOKEN", actorId);
|
|
215332
|
+
const appOwner = owner?.kind === "org" && owner.login ? { kind: "org", login: owner.login } : { kind: "user", ...token ? { login: await githubLoginOf(token) } : {} };
|
|
215333
|
+
const [oasisApps, installed] = await Promise.all([
|
|
215334
|
+
collectOasisGithubApps(svc),
|
|
215335
|
+
appOwner.kind === "org" ? orgInstalledAppsFor(token, appOwner.login) : Promise.resolve({ state: { status: "ok" }, apps: [] })
|
|
215336
|
+
]);
|
|
215337
|
+
const names = new Map(oasisApps.map((a) => [a.appId, a.usedByNames]));
|
|
215338
|
+
const candidates = buildReuseCandidates({ owner: appOwner, oasisApps, installed: installed.apps }).map((c) => ({ ...c, usedBy: names.get(c.appId) ?? [] }));
|
|
215339
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ candidates, installed: installed.state }));
|
|
215340
|
+
} catch (e) {
|
|
215341
|
+
res.writeHead(500, { "content-type": "application/json" }).end(JSON.stringify({ error: String(e) }));
|
|
215342
|
+
}
|
|
215343
|
+
return;
|
|
215344
|
+
}
|
|
215345
|
+
if (url.pathname === "/api/connectors/github/app/inventory" && req.method === "POST") {
|
|
215346
|
+
try {
|
|
215347
|
+
const svc = await connectorActorsService();
|
|
215348
|
+
if (!svc) throw new Error("actors service unavailable");
|
|
215349
|
+
const [oasisApps, picked] = await Promise.all([collectOasisGithubApps(svc), pickUserToken(svc)]);
|
|
215350
|
+
const adminOrgs = picked ? picked.memberships.filter((m2) => m2.role === "admin").map((m2) => m2.login) : [];
|
|
215351
|
+
const perOrg = picked ? await Promise.all(adminOrgs.map((org) => orgInstalledAppsFor(picked.token, org))) : [];
|
|
215352
|
+
const rows = buildAppInventory({ oasisApps, installed: perOrg.flatMap((r) => r.apps) });
|
|
215353
|
+
const names = new Map(oasisApps.map((a) => [a.appId, a.usedByNames]));
|
|
215354
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
215355
|
+
rows: rows.map((r) => ({ ...r, usedBy: names.get(r.appId) ?? [] })),
|
|
215356
|
+
/** 组织里装着的那部分列没列出来:needsAuth = 没有可用的 GitHub 登录;notAdmin = 不是任何组织的管理员。 */
|
|
215357
|
+
installed: !picked ? { status: "needsAuth" } : adminOrgs.length === 0 ? { status: "notAdmin" } : perOrg.find((r) => r.state.status !== "ok")?.state ?? { status: "ok" },
|
|
215358
|
+
orgs: adminOrgs
|
|
215359
|
+
}));
|
|
215360
|
+
} catch (e) {
|
|
215361
|
+
res.writeHead(500, { "content-type": "application/json" }).end(JSON.stringify({ error: String(e) }));
|
|
215362
|
+
}
|
|
215363
|
+
return;
|
|
215364
|
+
}
|
|
215365
|
+
if (url.pathname === "/api/connectors/github/app/uninstall" && req.method === "POST") {
|
|
215366
|
+
try {
|
|
215367
|
+
const { appIds } = JSON.parse(rawBody || "{}");
|
|
215368
|
+
if (!Array.isArray(appIds) || appIds.length === 0 || !appIds.every((x2) => typeof x2 === "string")) {
|
|
215369
|
+
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: "\u8BF7\u5148\u52FE\u9009\u8981\u5378\u8F7D\u7684 App" }));
|
|
215370
|
+
return;
|
|
214908
215371
|
}
|
|
214909
|
-
const
|
|
214910
|
-
|
|
214911
|
-
|
|
214912
|
-
|
|
214913
|
-
|
|
214914
|
-
|
|
214915
|
-
|
|
214916
|
-
|
|
214917
|
-
}
|
|
215372
|
+
const svc = await connectorActorsService();
|
|
215373
|
+
if (!svc) throw new Error("actors service unavailable");
|
|
215374
|
+
const apps = new Map((await collectOasisGithubApps(svc)).map((a) => [a.appId, a]));
|
|
215375
|
+
const results = await Promise.all(appIds.map(async (appId) => {
|
|
215376
|
+
const app = apps.get(appId);
|
|
215377
|
+
if (!app) return { appId, ok: false, error: "Oasis \u6CA1\u6709\u8FD9\u4E2A App \u7684\u79C1\u94A5\uFF0C\u5378\u8F7D\u4E0D\u4E86\uFF0C\u8BF7\u53BB GitHub \u9875\u9762\u5904\u7406" };
|
|
215378
|
+
if (app.isOrgDefault || app.usedBy.length > 0) {
|
|
215379
|
+
return { appId, slug: app.slug, ok: false, error: `\u8FD8\u6709 agent \u5728\u7528\uFF08${app.isOrgDefault ? "\u7EC4\u7EC7\u9ED8\u8BA4" : app.usedByNames.join("\u3001")}\uFF09\uFF0C\u4E0D\u80FD\u5378\u8F7D` };
|
|
215380
|
+
}
|
|
215381
|
+
const pem = await svc.revealVariable("GITHUB_APP_PRIVATE_KEY", app.keyActorId);
|
|
215382
|
+
if (!pem) return { appId, slug: app.slug, ok: false, error: "\u79C1\u94A5\u8BFB\u4E0D\u51FA\u6765\uFF0C\u5378\u8F7D\u4E0D\u4E86" };
|
|
214918
215383
|
try {
|
|
214919
|
-
const
|
|
214920
|
-
|
|
214921
|
-
|
|
214922
|
-
|
|
214923
|
-
|
|
214924
|
-
|
|
214925
|
-
});
|
|
214926
|
-
return { ...base, missing: missingAppPermissions(perms) };
|
|
214927
|
-
} catch {
|
|
214928
|
-
return { ...base, permissionsUnknown: true };
|
|
215384
|
+
for (const installationId of app.installationIds) {
|
|
215385
|
+
await uninstallAppInstallation({ appId, privateKeyPem: pem, installationId });
|
|
215386
|
+
}
|
|
215387
|
+
return { appId, slug: app.slug, ok: true };
|
|
215388
|
+
} catch (e) {
|
|
215389
|
+
return { appId, slug: app.slug, ok: false, error: `GitHub \u62D2\u7EDD\u4E86\u5378\u8F7D\uFF1A${String(e).replace(/^Error:\s*/, "")}` };
|
|
214929
215390
|
}
|
|
214930
215391
|
}));
|
|
214931
|
-
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
215392
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ results }));
|
|
214932
215393
|
} catch (e) {
|
|
214933
215394
|
res.writeHead(500, { "content-type": "application/json" }).end(JSON.stringify({ error: String(e) }));
|
|
214934
215395
|
}
|
|
@@ -214957,9 +215418,11 @@ ${composed}`;
|
|
|
214957
215418
|
return;
|
|
214958
215419
|
}
|
|
214959
215420
|
const pick3 = (key2) => rows.find((r) => r.key === key2 && r.actorId === srcActor && !r.encrypted)?.maskedValue ?? "";
|
|
214960
|
-
const
|
|
215421
|
+
const storedInstallationId = pick3("GITHUB_APP_INSTALLATION_ID");
|
|
215422
|
+
const live = await listAppInstallations({ appId, privateKeyPem: pem }).catch(() => null);
|
|
215423
|
+
const installationId = live ? (live.find((i) => i.installationId === storedInstallationId) ?? live[0])?.installationId ?? "" : storedInstallationId;
|
|
214961
215424
|
if (!installationId) {
|
|
214962
|
-
res.writeHead(409, { "content-type": "application/json" }).end(JSON.stringify({ error: "\u8FD9\u4E2A App \u8FD8\u6CA1\
|
|
215425
|
+
res.writeHead(409, { "content-type": "application/json" }).end(JSON.stringify({ error: "\u8FD9\u4E2A App \u8FD8\u6CA1\u88C5\u5230\u4EFB\u4F55\u8D26\u53F7\u2014\u2014\u5148\u5728 GitHub \u4E0A\u5B89\u88C5\u5B83\uFF0C\u88C5\u597D\u540E\u518D\u70B9\u8FDE\u63A5" }));
|
|
214963
215426
|
return;
|
|
214964
215427
|
}
|
|
214965
215428
|
const slug6 = pick3("GITHUB_APP_SLUG");
|
|
@@ -214997,7 +215460,7 @@ ${composed}`;
|
|
|
214997
215460
|
const msg = String(e);
|
|
214998
215461
|
bad(
|
|
214999
215462
|
400,
|
|
215000
|
-
/HTTP 401/.test(msg) ? "
|
|
215463
|
+
/HTTP 401/.test(msg) ? "\u8FD9\u4E2A\u79C1\u94A5\u548C\u6240\u9009\u7684 App \u5BF9\u4E0D\u4E0A\u2014\u2014\u8BF7\u786E\u8BA4\u5B83\u662F\u5728\u8FD9\u4E2A App \u7684\u8BBE\u7F6E\u9875\u70B9 Generate a private key \u4E0B\u8F7D\u7684\u90A3\u4E00\u4EFD\uFF08\u624B\u586B App ID \u65F6\u4E5F\u6838\u5BF9\u4E00\u4E0B\u6709\u6CA1\u6709\u6284\u9519\uFF09" : /私钥解析失败/.test(msg) ? msg.replace(/^Error:\s*/, "").replace(/^github app:\s*/, "") : `GitHub \u62D2\u7EDD\u4E86\u8FD9\u5BF9\u51ED\u636E\uFF1A${msg}`
|
|
215001
215464
|
);
|
|
215002
215465
|
return;
|
|
215003
215466
|
}
|
|
@@ -215667,14 +216130,14 @@ async function markDeliveredWithRetry(store, messageId, attempts = 3) {
|
|
|
215667
216130
|
}
|
|
215668
216131
|
return false;
|
|
215669
216132
|
}
|
|
215670
|
-
var http,
|
|
216133
|
+
var http, import_node_crypto43, 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;
|
|
215671
216134
|
var init_server3 = __esm({
|
|
215672
216135
|
"../server/src/server.ts"() {
|
|
215673
216136
|
"use strict";
|
|
215674
216137
|
init_src();
|
|
215675
216138
|
init_file_limits2();
|
|
215676
216139
|
http = __toESM(require("node:http"), 1);
|
|
215677
|
-
|
|
216140
|
+
import_node_crypto43 = require("node:crypto");
|
|
215678
216141
|
init_chat_session();
|
|
215679
216142
|
init_chat_system_message();
|
|
215680
216143
|
init_sealed_node_receipt();
|
|
@@ -215740,6 +216203,7 @@ var init_server3 = __esm({
|
|
|
215740
216203
|
init_child_live_turn();
|
|
215741
216204
|
init_registry_audit_sink();
|
|
215742
216205
|
init_src8();
|
|
216206
|
+
init_github_app_inventory();
|
|
215743
216207
|
init_continuation3();
|
|
215744
216208
|
CONNECTOR_AUTH_SNAPSHOT_TTL_MS = 30 * 60 * 1e3;
|
|
215745
216209
|
defaultResolveActor = (token) => token.startsWith("token:") ? token.slice("token:".length) : null;
|
|
@@ -215854,7 +216318,7 @@ function createNodeTokenStore(file) {
|
|
|
215854
216318
|
return {
|
|
215855
216319
|
issue(nodeId) {
|
|
215856
216320
|
const table = read3();
|
|
215857
|
-
const token = `ont_${(0,
|
|
216321
|
+
const token = `ont_${(0, import_node_crypto44.randomBytes)(24).toString("base64url")}`;
|
|
215858
216322
|
table[token] = nodeId;
|
|
215859
216323
|
write(table);
|
|
215860
216324
|
return token;
|
|
@@ -215914,7 +216378,7 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
215914
216378
|
return {
|
|
215915
216379
|
issue(name, ttlMs = defaultTtlMs, companyId) {
|
|
215916
216380
|
const m2 = prune();
|
|
215917
|
-
const token = `ent_${(0,
|
|
216381
|
+
const token = `ent_${(0, import_node_crypto44.randomBytes)(24).toString("base64url")}`;
|
|
215918
216382
|
const expiresAt2 = Date.now() + ttlMs;
|
|
215919
216383
|
m2.set(token, { name, expiresAt: expiresAt2, ...companyId !== void 0 ? { companyId } : {} });
|
|
215920
216384
|
write(m2);
|
|
@@ -215963,33 +216427,33 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
215963
216427
|
}
|
|
215964
216428
|
};
|
|
215965
216429
|
}
|
|
215966
|
-
var
|
|
216430
|
+
var import_node_crypto44, fs22, path21, SESSION_TOKEN_PREFIX, b64url2, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
|
|
215967
216431
|
var init_tokens = __esm({
|
|
215968
216432
|
"../server/src/tokens.ts"() {
|
|
215969
216433
|
"use strict";
|
|
215970
|
-
|
|
216434
|
+
import_node_crypto44 = require("node:crypto");
|
|
215971
216435
|
fs22 = __toESM(require("node:fs"), 1);
|
|
215972
216436
|
path21 = __toESM(require("node:path"), 1);
|
|
215973
216437
|
SESSION_TOKEN_PREFIX = "oat_v2_";
|
|
215974
216438
|
b64url2 = (value2) => Buffer.from(value2).toString("base64url");
|
|
215975
216439
|
fromB64url = (value2) => Buffer.from(value2, "base64url").toString("utf8");
|
|
215976
216440
|
readOrCreateSecret = (file) => {
|
|
215977
|
-
if (!file) return (0,
|
|
216441
|
+
if (!file) return (0, import_node_crypto44.randomBytes)(32);
|
|
215978
216442
|
try {
|
|
215979
216443
|
const raw = fs22.readFileSync(file, "utf8").trim();
|
|
215980
216444
|
if (raw) return Buffer.from(raw, "base64url");
|
|
215981
216445
|
} catch {
|
|
215982
216446
|
}
|
|
215983
|
-
const secret = (0,
|
|
216447
|
+
const secret = (0, import_node_crypto44.randomBytes)(32);
|
|
215984
216448
|
fs22.mkdirSync(path21.dirname(file), { recursive: true });
|
|
215985
216449
|
fs22.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
215986
216450
|
return secret;
|
|
215987
216451
|
};
|
|
215988
|
-
sign = (secret, payload2) => (0,
|
|
216452
|
+
sign = (secret, payload2) => (0, import_node_crypto44.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
215989
216453
|
signatureMatches = (actual, expected) => {
|
|
215990
216454
|
const a = Buffer.from(actual);
|
|
215991
216455
|
const b2 = Buffer.from(expected);
|
|
215992
|
-
return a.length === b2.length && (0,
|
|
216456
|
+
return a.length === b2.length && (0, import_node_crypto44.timingSafeEqual)(a, b2);
|
|
215993
216457
|
};
|
|
215994
216458
|
isTokenClaims = (value2) => {
|
|
215995
216459
|
if (value2 === null || typeof value2 !== "object") return false;
|
|
@@ -216051,31 +216515,31 @@ function createDataplaneTokenIssuer(opts = {}) {
|
|
|
216051
216515
|
}
|
|
216052
216516
|
};
|
|
216053
216517
|
}
|
|
216054
|
-
var
|
|
216518
|
+
var import_node_crypto45, fs23, path22, PREFIX2, b64url3, fromB64url2, sign2, sigMatches, readOrCreateSecret2, isClaims, isDataplaneToken;
|
|
216055
216519
|
var init_session_dataplane_token = __esm({
|
|
216056
216520
|
"../server/src/session-dataplane-token.ts"() {
|
|
216057
216521
|
"use strict";
|
|
216058
|
-
|
|
216522
|
+
import_node_crypto45 = require("node:crypto");
|
|
216059
216523
|
fs23 = __toESM(require("node:fs"), 1);
|
|
216060
216524
|
path22 = __toESM(require("node:path"), 1);
|
|
216061
216525
|
init_src();
|
|
216062
216526
|
PREFIX2 = "osd_";
|
|
216063
216527
|
b64url3 = (v2) => Buffer.from(v2, "utf8").toString("base64url");
|
|
216064
216528
|
fromB64url2 = (v2) => Buffer.from(v2, "base64url").toString("utf8");
|
|
216065
|
-
sign2 = (secret, payload2) => (0,
|
|
216529
|
+
sign2 = (secret, payload2) => (0, import_node_crypto45.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
216066
216530
|
sigMatches = (actual, expected) => {
|
|
216067
216531
|
const a = Buffer.from(actual);
|
|
216068
216532
|
const b2 = Buffer.from(expected);
|
|
216069
|
-
return a.length === b2.length && (0,
|
|
216533
|
+
return a.length === b2.length && (0, import_node_crypto45.timingSafeEqual)(a, b2);
|
|
216070
216534
|
};
|
|
216071
216535
|
readOrCreateSecret2 = (file) => {
|
|
216072
|
-
if (!file) return (0,
|
|
216536
|
+
if (!file) return (0, import_node_crypto45.randomBytes)(32);
|
|
216073
216537
|
try {
|
|
216074
216538
|
const raw = fs23.readFileSync(file, "utf8").trim();
|
|
216075
216539
|
if (raw) return Buffer.from(raw, "base64url");
|
|
216076
216540
|
} catch {
|
|
216077
216541
|
}
|
|
216078
|
-
const secret = (0,
|
|
216542
|
+
const secret = (0, import_node_crypto45.randomBytes)(32);
|
|
216079
216543
|
fs23.mkdirSync(path22.dirname(file), { recursive: true });
|
|
216080
216544
|
fs23.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
216081
216545
|
return secret;
|
|
@@ -218877,11 +219341,11 @@ function onlyHits(pool, q2) {
|
|
|
218877
219341
|
if (!q2.requireMatch || q2.keywords.length === 0) return [...pool];
|
|
218878
219342
|
return pool.filter((r) => memoryMatchScore(r, q2.keywords) > 0);
|
|
218879
219343
|
}
|
|
218880
|
-
var
|
|
219344
|
+
var import_node_crypto46, MemoryActorMemoryStore, toIndexEntry;
|
|
218881
219345
|
var init_memory_actor_memory_store = __esm({
|
|
218882
219346
|
"../testkit/src/memory-actor-memory-store.ts"() {
|
|
218883
219347
|
"use strict";
|
|
218884
|
-
|
|
219348
|
+
import_node_crypto46 = require("node:crypto");
|
|
218885
219349
|
init_src();
|
|
218886
219350
|
MemoryActorMemoryStore = class {
|
|
218887
219351
|
rows = /* @__PURE__ */ new Map();
|
|
@@ -218935,7 +219399,7 @@ var init_memory_actor_memory_store = __esm({
|
|
|
218935
219399
|
async write(input, now) {
|
|
218936
219400
|
if (input.memId === void 0) {
|
|
218937
219401
|
const rec2 = {
|
|
218938
|
-
memId: `mem:${(0,
|
|
219402
|
+
memId: `mem:${(0, import_node_crypto46.randomUUID)()}`,
|
|
218939
219403
|
actorId: input.actorId,
|
|
218940
219404
|
projectId: input.projectId,
|
|
218941
219405
|
keywords: [...input.keywords],
|
|
@@ -220634,13 +221098,13 @@ var init_stats = __esm({
|
|
|
220634
221098
|
|
|
220635
221099
|
// ../server/src/domains/projects/project-id.ts
|
|
220636
221100
|
function randomProjectId() {
|
|
220637
|
-
return projectIdFromUuid((0,
|
|
221101
|
+
return projectIdFromUuid((0, import_node_crypto47.randomUUID)());
|
|
220638
221102
|
}
|
|
220639
|
-
var
|
|
221103
|
+
var import_node_crypto47;
|
|
220640
221104
|
var init_project_id = __esm({
|
|
220641
221105
|
"../server/src/domains/projects/project-id.ts"() {
|
|
220642
221106
|
"use strict";
|
|
220643
|
-
|
|
221107
|
+
import_node_crypto47 = require("node:crypto");
|
|
220644
221108
|
init_src();
|
|
220645
221109
|
}
|
|
220646
221110
|
});
|
|
@@ -222715,12 +223179,12 @@ function applyTurnPatch(t, patch) {
|
|
|
222715
223179
|
...patch.lastError !== void 0 ? { lastError: patch.lastError } : {}
|
|
222716
223180
|
};
|
|
222717
223181
|
}
|
|
222718
|
-
var
|
|
223182
|
+
var import_node_crypto48, fs24, path23, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
|
|
222719
223183
|
var init_dev_store = __esm({
|
|
222720
223184
|
"../server/src/dev-store.ts"() {
|
|
222721
223185
|
"use strict";
|
|
222722
223186
|
init_src();
|
|
222723
|
-
|
|
223187
|
+
import_node_crypto48 = require("node:crypto");
|
|
222724
223188
|
fs24 = __toESM(require("node:fs"), 1);
|
|
222725
223189
|
path23 = __toESM(require("node:path"), 1);
|
|
222726
223190
|
init_src();
|
|
@@ -222774,7 +223238,7 @@ var init_dev_store = __esm({
|
|
|
222774
223238
|
return path23.join(this.dir, hash3);
|
|
222775
223239
|
}
|
|
222776
223240
|
async put(bytes2) {
|
|
222777
|
-
const hash3 = (0,
|
|
223241
|
+
const hash3 = (0, import_node_crypto48.createHash)("sha256").update(bytes2).digest("hex");
|
|
222778
223242
|
const file = this.fileOf(hash3);
|
|
222779
223243
|
if (!fs24.existsSync(file)) fs24.writeFileSync(file, bytes2);
|
|
222780
223244
|
return hash3;
|
|
@@ -224069,7 +224533,7 @@ var init_company_engine_router = __esm({
|
|
|
224069
224533
|
|
|
224070
224534
|
// ../server/src/skill-market-client.ts
|
|
224071
224535
|
function digestOf2(bytes2) {
|
|
224072
|
-
return `sha256:${(0,
|
|
224536
|
+
return `sha256:${(0, import_node_crypto49.createHash)("sha256").update(bytes2).digest("hex")}`;
|
|
224073
224537
|
}
|
|
224074
224538
|
function createSkillMarketClientFromEnv(env = process.env) {
|
|
224075
224539
|
const base = env["SKILL_MARKET_BASE_URL"];
|
|
@@ -224080,11 +224544,11 @@ function createSkillMarketClientFromEnv(env = process.env) {
|
|
|
224080
224544
|
function sleep4(ms) {
|
|
224081
224545
|
return new Promise((r) => setTimeout(r, ms));
|
|
224082
224546
|
}
|
|
224083
|
-
var
|
|
224547
|
+
var import_node_crypto49, DisabledSkillMarketClient, FakeSkillMarketClient, HttpSkillMarketClient;
|
|
224084
224548
|
var init_skill_market_client = __esm({
|
|
224085
224549
|
"../server/src/skill-market-client.ts"() {
|
|
224086
224550
|
"use strict";
|
|
224087
|
-
|
|
224551
|
+
import_node_crypto49 = require("node:crypto");
|
|
224088
224552
|
init_src();
|
|
224089
224553
|
DisabledSkillMarketClient = class {
|
|
224090
224554
|
async listSkills(_input) {
|
|
@@ -224935,7 +225399,7 @@ async function copySessionOutputs(deps) {
|
|
|
224935
225399
|
continue;
|
|
224936
225400
|
}
|
|
224937
225401
|
const saved = existing?.[file.path];
|
|
224938
|
-
if (saved && savedContentHash(saved) === (0,
|
|
225402
|
+
if (saved && savedContentHash(saved) === (0, import_node_crypto50.createHash)("sha256").update(bytes2).digest("hex")) {
|
|
224939
225403
|
const aligned = { ...saved, size: bytes2.length, mtime: file.mtime };
|
|
224940
225404
|
delete aligned.editedAt;
|
|
224941
225405
|
realigned.push(aligned);
|
|
@@ -225032,11 +225496,11 @@ function createOutputCopyScheduler(deps) {
|
|
|
225032
225496
|
}
|
|
225033
225497
|
};
|
|
225034
225498
|
}
|
|
225035
|
-
var
|
|
225499
|
+
var import_node_crypto50, OUTPUT_COPY_LIMITS;
|
|
225036
225500
|
var init_outputs_copy = __esm({
|
|
225037
225501
|
"../server/src/domains/chat-sessions/outputs-copy.ts"() {
|
|
225038
225502
|
"use strict";
|
|
225039
|
-
|
|
225503
|
+
import_node_crypto50 = require("node:crypto");
|
|
225040
225504
|
init_src();
|
|
225041
225505
|
OUTPUT_COPY_LIMITS = {
|
|
225042
225506
|
maxFileBytes: FILE_CONTENT_MAX_BYTES,
|
|
@@ -225421,11 +225885,11 @@ function typeDefError(def, mode) {
|
|
|
225421
225885
|
}
|
|
225422
225886
|
return null;
|
|
225423
225887
|
}
|
|
225424
|
-
var
|
|
225888
|
+
var import_node_crypto51, RESERVED_FIELD_NAMES, ARTIFACT_TYPE_ACCENTS, TYPE_DEF_SCHEMA, TypesAdminService;
|
|
225425
225889
|
var init_types_admin = __esm({
|
|
225426
225890
|
"../server/src/types-admin.ts"() {
|
|
225427
225891
|
"use strict";
|
|
225428
|
-
|
|
225892
|
+
import_node_crypto51 = require("node:crypto");
|
|
225429
225893
|
init_zod();
|
|
225430
225894
|
init_src7();
|
|
225431
225895
|
init_config_audit();
|
|
@@ -225552,7 +226016,7 @@ var init_types_admin = __esm({
|
|
|
225552
226016
|
async trace(change, target, by, detail) {
|
|
225553
226017
|
try {
|
|
225554
226018
|
await this.audit?.({
|
|
225555
|
-
id: `reg_${(0,
|
|
226019
|
+
id: `reg_${(0, import_node_crypto51.randomUUID)()}`,
|
|
225556
226020
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
225557
226021
|
kind: "registry_change",
|
|
225558
226022
|
target,
|
|
@@ -225700,11 +226164,11 @@ function roleDefError(def, mode) {
|
|
|
225700
226164
|
}
|
|
225701
226165
|
return null;
|
|
225702
226166
|
}
|
|
225703
|
-
var
|
|
226167
|
+
var import_node_crypto52, ACCENTS, ROLE_DEF_SCHEMA, RolesAdminService;
|
|
225704
226168
|
var init_roles_admin = __esm({
|
|
225705
226169
|
"../server/src/roles-admin.ts"() {
|
|
225706
226170
|
"use strict";
|
|
225707
|
-
|
|
226171
|
+
import_node_crypto52 = require("node:crypto");
|
|
225708
226172
|
init_zod();
|
|
225709
226173
|
init_src7();
|
|
225710
226174
|
init_config_audit();
|
|
@@ -225729,7 +226193,7 @@ var init_roles_admin = __esm({
|
|
|
225729
226193
|
async trace(change, target, by, detail) {
|
|
225730
226194
|
try {
|
|
225731
226195
|
await this.deps.audit?.({
|
|
225732
|
-
id: `reg_${(0,
|
|
226196
|
+
id: `reg_${(0, import_node_crypto52.randomUUID)()}`,
|
|
225733
226197
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
225734
226198
|
kind: "registry_change",
|
|
225735
226199
|
target,
|
|
@@ -226920,14 +227384,13 @@ function frameTokenTotal(usage) {
|
|
|
226920
227384
|
return (usage.inputTokens ?? 0) + (usage.outputTokens ?? 0) + (usage.cacheReadTokens ?? 0) + (usage.cacheCreationTokens ?? 0);
|
|
226921
227385
|
}
|
|
226922
227386
|
async function backfillRunModel(target, run, model, modelSource, warn) {
|
|
226923
|
-
const
|
|
226924
|
-
|
|
226925
|
-
|
|
227387
|
+
const patch = preferRunModel(
|
|
227388
|
+
{ effectiveModel: run.effectiveModel, modelSource: run.modelSource },
|
|
227389
|
+
{ effectiveModel: model, modelSource: modelSource === "requested" ? "requested" : "runtime" }
|
|
227390
|
+
);
|
|
227391
|
+
if (!patch) return;
|
|
226926
227392
|
try {
|
|
226927
|
-
await target.store.updateRun(target.runId,
|
|
226928
|
-
effectiveModel,
|
|
226929
|
-
modelSource: modelSource === "requested" ? "requested" : "runtime"
|
|
226930
|
-
});
|
|
227393
|
+
await target.store.updateRun(target.runId, patch);
|
|
226931
227394
|
} catch (err) {
|
|
226932
227395
|
warn(`[usage-ledger] run ${target.runId} \u7684\u6A21\u578B\u540D\u8865\u5199\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u4F1A\u8BDD\uFF09\uFF1A${String(err)}`);
|
|
226933
227396
|
}
|
|
@@ -227693,8 +228156,10 @@ var init_sink = __esm({
|
|
|
227693
228156
|
const isErr = status === "failed" || status === "timeout";
|
|
227694
228157
|
const errorFields = isErr ? { errorCode: update.exit.reason ?? "error", errorMessage: formatExitError(update.exit) } : {};
|
|
227695
228158
|
const exitModel = actualModelId(update.exit.model);
|
|
227696
|
-
const
|
|
227697
|
-
const
|
|
228159
|
+
const observedModel = actualModelId(st.observedModel);
|
|
228160
|
+
const exitIsRequestedOnly = update.exit.modelSource === "requested";
|
|
228161
|
+
const model = (exitIsRequestedOnly ? observedModel ?? exitModel : exitModel ?? observedModel) ?? null;
|
|
228162
|
+
const modelSource = model && model === exitModel && exitIsRequestedOnly && !observedModel ? "requested" : "runtime";
|
|
227698
228163
|
const exitRtId = typeof update.exit.runtimeSessionId === "string" && update.exit.runtimeSessionId.trim() ? update.exit.runtimeSessionId.trim() : void 0;
|
|
227699
228164
|
if (exitRtId) st.baseMetadata = { ...st.baseMetadata, runtimeSessionId: exitRtId };
|
|
227700
228165
|
const exitWorkdir = typeof update.exit.workdirRef === "string" && update.exit.workdirRef.trim() ? update.exit.workdirRef.trim() : void 0;
|
|
@@ -227725,6 +228190,12 @@ var init_sink = __esm({
|
|
|
227725
228190
|
createdAt: update.exit.at
|
|
227726
228191
|
});
|
|
227727
228192
|
}
|
|
228193
|
+
const currentRun = model ? await this.store.getRun(st.runId).catch(() => null) : null;
|
|
228194
|
+
const modelPatch = model ? preferRunModel(
|
|
228195
|
+
{ effectiveModel: currentRun?.effectiveModel, modelSource: currentRun?.modelSource },
|
|
228196
|
+
{ effectiveModel: model, modelSource },
|
|
228197
|
+
"replace"
|
|
228198
|
+
) : null;
|
|
227728
228199
|
const finished = await this.store.updateRun(st.runId, {
|
|
227729
228200
|
status,
|
|
227730
228201
|
endedAt: update.exit.at,
|
|
@@ -227740,7 +228211,7 @@ var init_sink = __esm({
|
|
|
227740
228211
|
// token/成本来自 adapter 解析 stream-json(含 cache);不带则不写、保持 null。
|
|
227741
228212
|
...update.exit.usage ? { usage: update.exit.usage } : {},
|
|
227742
228213
|
// effectiveModel/modelSource 喂用量聚合(聚合键含 model);与 chat/finishRun 路径一致。
|
|
227743
|
-
...
|
|
228214
|
+
...modelPatch ?? {},
|
|
227744
228215
|
// metadata 整列替换:必须带上 baseMetadata(bundleManifest/runtimeSessionId)一起写回。
|
|
227745
228216
|
// model 有则并入(前端 findModelInValue 直接读 metadata.model)。**不能只在有 model 时才写**
|
|
227746
228217
|
// ——否则无 model 的 run(如回捕型 runtime 没报模型)会把 exit 校正过的会话号丢掉。
|
|
@@ -228095,10 +228566,8 @@ function wireRecoveredChatTurn(deps) {
|
|
|
228095
228566
|
live.emit({ type: "done", ...plan.runtimeSessionId ? { sessionId: plan.runtimeSessionId } : {} });
|
|
228096
228567
|
live.finish(failed ? "error" : "done");
|
|
228097
228568
|
deps.unregister();
|
|
228098
|
-
const
|
|
228099
|
-
|
|
228100
|
-
info.runtimeSessionId
|
|
228101
|
-
) : void 0;
|
|
228569
|
+
const currentRun = await trace.getRun(plan.runId).catch(() => null);
|
|
228570
|
+
const nativeSessionMetadata = info.runtimeSessionId && info.runtimeSessionId !== plan.runtimeSessionId ? nativeRuntimeSessionMetadata(currentRun?.metadata, info.runtimeSessionId) : void 0;
|
|
228102
228571
|
enqueueTrace(async () => {
|
|
228103
228572
|
await appender.append([{
|
|
228104
228573
|
eventType: "run.finished",
|
|
@@ -228107,7 +228576,7 @@ function wireRecoveredChatTurn(deps) {
|
|
|
228107
228576
|
startedAt: finishedAt
|
|
228108
228577
|
}]);
|
|
228109
228578
|
await appender.update({
|
|
228110
|
-
...runTerminalPatch(info, plan.startedAt, finishedAt),
|
|
228579
|
+
...runTerminalPatch(info, plan.startedAt, finishedAt, currentRun),
|
|
228111
228580
|
// 运行时自己退干净了,但平台没把输出接全——运行记录不许写「成功」(Bug 0123)。
|
|
228112
228581
|
// 退出帧本身已经是失败时保持它的归因,只补一句缺口说明。
|
|
228113
228582
|
...outputGapRunPatch(droppedFrames, exitIsFailure, info),
|
|
@@ -228331,7 +228800,7 @@ async function reconcileChatExitFrame(deps) {
|
|
|
228331
228800
|
];
|
|
228332
228801
|
await deps.trace.appendEvents(row.runId, seqless.map((e, i) => ({ ...e, seq: baseSeq + i + 1 })));
|
|
228333
228802
|
await deps.trace.updateRun(row.runId, {
|
|
228334
|
-
...runTerminalPatch(info, run.startedAt, finishedAt),
|
|
228803
|
+
...runTerminalPatch(info, run.startedAt, finishedAt, run),
|
|
228335
228804
|
...outputGapRunPatch(droppedFrames, exitIsFailure, info),
|
|
228336
228805
|
// 首轮占位会话号 → runtime 报回的原生号(Bug 0171,判据见本函数上方那一段)。
|
|
228337
228806
|
...nativeSessionMetadata ? { metadata: nativeSessionMetadata } : {}
|
|
@@ -228560,6 +229029,7 @@ var init_chat_recovery = __esm({
|
|
|
228560
229029
|
"use strict";
|
|
228561
229030
|
init_file_restore();
|
|
228562
229031
|
init_continuation3();
|
|
229032
|
+
init_src();
|
|
228563
229033
|
init_chat_parts();
|
|
228564
229034
|
init_sink();
|
|
228565
229035
|
init_usage_ledger();
|
|
@@ -228587,7 +229057,7 @@ var init_chat_recovery = __esm({
|
|
|
228587
229057
|
const existing = formatExitError(info);
|
|
228588
229058
|
return { errorMessage: existing ? `${existing}\uFF1B${gap}` : gap };
|
|
228589
229059
|
};
|
|
228590
|
-
runTerminalPatch = (info, startedAt, endedAt) => ({
|
|
229060
|
+
runTerminalPatch = (info, startedAt, endedAt, current) => ({
|
|
228591
229061
|
status: classifySessionExitStatus(info),
|
|
228592
229062
|
endedAt,
|
|
228593
229063
|
durationMs: Date.parse(endedAt) - Date.parse(startedAt),
|
|
@@ -228600,15 +229070,19 @@ var init_chat_recovery = __esm({
|
|
|
228600
229070
|
// 不能用 null 覆盖,否则恢复轮的 token 会掉进「未知模型」桶。
|
|
228601
229071
|
// 伪型号(`default[]` / `auto`)不是模型名,不写;请求值(`requested`)与实际值分开记来源
|
|
228602
229072
|
// ——重挂路与 chat 主路、派发路三处必须同一判据,否则同一条 run 换条路收尾归属就变了。
|
|
228603
|
-
...
|
|
229073
|
+
...preferRunModel(
|
|
229074
|
+
{ effectiveModel: current?.effectiveModel, modelSource: current?.modelSource },
|
|
229075
|
+
chatExitModelFields(info.model, null, null, info.modelSource),
|
|
229076
|
+
"replace"
|
|
229077
|
+
) ?? {}
|
|
228604
229078
|
});
|
|
228605
229079
|
}
|
|
228606
229080
|
});
|
|
228607
229081
|
|
|
228608
229082
|
// ../server/src/auth/crypto.ts
|
|
228609
229083
|
function hashPassword(password) {
|
|
228610
|
-
const salt = (0,
|
|
228611
|
-
const dk = (0,
|
|
229084
|
+
const salt = (0, import_node_crypto53.randomBytes)(16);
|
|
229085
|
+
const dk = (0, import_node_crypto53.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
|
|
228612
229086
|
return `scrypt$${SCRYPT_N}$${salt.toString("base64url")}$${dk.toString("base64url")}`;
|
|
228613
229087
|
}
|
|
228614
229088
|
function verifyPassword(password, stored) {
|
|
@@ -228625,8 +229099,8 @@ function verifyPassword(password, stored) {
|
|
|
228625
229099
|
return false;
|
|
228626
229100
|
}
|
|
228627
229101
|
if (expected.length === 0) return false;
|
|
228628
|
-
const dk = (0,
|
|
228629
|
-
return dk.length === expected.length && (0,
|
|
229102
|
+
const dk = (0, import_node_crypto53.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
|
|
229103
|
+
return dk.length === expected.length && (0, import_node_crypto53.timingSafeEqual)(dk, expected);
|
|
228630
229104
|
}
|
|
228631
229105
|
function b64urlJson(value2) {
|
|
228632
229106
|
return Buffer.from(JSON.stringify(value2)).toString("base64url");
|
|
@@ -228634,17 +229108,17 @@ function b64urlJson(value2) {
|
|
|
228634
229108
|
function signSession(claims, secret) {
|
|
228635
229109
|
const head = b64urlJson({ alg: "HS256", typ: "JWT" });
|
|
228636
229110
|
const body2 = b64urlJson(claims);
|
|
228637
|
-
const sig = (0,
|
|
229111
|
+
const sig = (0, import_node_crypto53.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
228638
229112
|
return `${head}.${body2}.${sig}`;
|
|
228639
229113
|
}
|
|
228640
229114
|
function verifySession(token, secret, nowMs) {
|
|
228641
229115
|
const parts = token.split(".");
|
|
228642
229116
|
if (parts.length !== 3) return null;
|
|
228643
229117
|
const [head, body2, sig] = parts;
|
|
228644
|
-
const expected = (0,
|
|
229118
|
+
const expected = (0, import_node_crypto53.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
228645
229119
|
const got = Buffer.from(sig);
|
|
228646
229120
|
const exp = Buffer.from(expected);
|
|
228647
|
-
if (got.length !== exp.length || !(0,
|
|
229121
|
+
if (got.length !== exp.length || !(0, import_node_crypto53.timingSafeEqual)(got, exp)) return null;
|
|
228648
229122
|
let claims;
|
|
228649
229123
|
try {
|
|
228650
229124
|
claims = JSON.parse(Buffer.from(body2, "base64url").toString("utf8"));
|
|
@@ -228656,21 +229130,21 @@ function verifySession(token, secret, nowMs) {
|
|
|
228656
229130
|
return claims;
|
|
228657
229131
|
}
|
|
228658
229132
|
function generateCode() {
|
|
228659
|
-
return String((0,
|
|
229133
|
+
return String((0, import_node_crypto53.randomInt)(0, 1e6)).padStart(6, "0");
|
|
228660
229134
|
}
|
|
228661
229135
|
function hashCode(code2, secret) {
|
|
228662
|
-
return (0,
|
|
229136
|
+
return (0, import_node_crypto53.createHmac)("sha256", secret).update(`code:${code2}`).digest("base64url");
|
|
228663
229137
|
}
|
|
228664
229138
|
function safeEqualHash(a, b2) {
|
|
228665
229139
|
const ba = Buffer.from(a);
|
|
228666
229140
|
const bb = Buffer.from(b2);
|
|
228667
|
-
return ba.length === bb.length && (0,
|
|
229141
|
+
return ba.length === bb.length && (0, import_node_crypto53.timingSafeEqual)(ba, bb);
|
|
228668
229142
|
}
|
|
228669
|
-
var
|
|
229143
|
+
var import_node_crypto53, SCRYPT_N, SCRYPT_KEYLEN;
|
|
228670
229144
|
var init_crypto2 = __esm({
|
|
228671
229145
|
"../server/src/auth/crypto.ts"() {
|
|
228672
229146
|
"use strict";
|
|
228673
|
-
|
|
229147
|
+
import_node_crypto53 = require("node:crypto");
|
|
228674
229148
|
SCRYPT_N = 16384;
|
|
228675
229149
|
SCRYPT_KEYLEN = 32;
|
|
228676
229150
|
}
|
|
@@ -230054,18 +230528,18 @@ function variableKeyFromEnv(env = process.env) {
|
|
|
230054
230528
|
return buf;
|
|
230055
230529
|
}
|
|
230056
230530
|
if (env.NODE_ENV === "production") throw new Error("OASIS_VAR_KEY is required in production");
|
|
230057
|
-
return (0,
|
|
230531
|
+
return (0, import_node_crypto54.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
|
|
230058
230532
|
}
|
|
230059
230533
|
function dedupe2(ids2) {
|
|
230060
230534
|
return [...new Set(ids2.filter((x2) => typeof x2 === "string" && x2.length > 0))];
|
|
230061
230535
|
}
|
|
230062
|
-
var
|
|
230536
|
+
var import_node_crypto54, REDACTED_MARKER, ActorsService, MASK_TAIL_MIN_LENGTH, mask, changedKeys;
|
|
230063
230537
|
var init_service5 = __esm({
|
|
230064
230538
|
"../server/src/domains/actors/service.ts"() {
|
|
230065
230539
|
"use strict";
|
|
230066
230540
|
init_file_limits2();
|
|
230067
230541
|
init_keyed_mutex();
|
|
230068
|
-
|
|
230542
|
+
import_node_crypto54 = require("node:crypto");
|
|
230069
230543
|
init_skill_fetcher();
|
|
230070
230544
|
init_identity();
|
|
230071
230545
|
init_migrate();
|
|
@@ -230689,7 +231163,7 @@ ${input.description}
|
|
|
230689
231163
|
*/
|
|
230690
231164
|
buildSkillFile(skillId, path47, content3, now) {
|
|
230691
231165
|
const bytes2 = new TextEncoder().encode(content3);
|
|
230692
|
-
const blobHash = (0,
|
|
231166
|
+
const blobHash = (0, import_node_crypto54.createHash)("sha256").update(bytes2).digest("hex");
|
|
230693
231167
|
return { skillId, path: path47, content: content3, blobHash, size: bytes2.length, updatedAt: now };
|
|
230694
231168
|
}
|
|
230695
231169
|
/**
|
|
@@ -231812,15 +232286,15 @@ ${input.description}
|
|
|
231812
232286
|
return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
|
|
231813
232287
|
}
|
|
231814
232288
|
encrypt(plain) {
|
|
231815
|
-
const iv = (0,
|
|
231816
|
-
const cipher = (0,
|
|
232289
|
+
const iv = (0, import_node_crypto54.randomBytes)(12);
|
|
232290
|
+
const cipher = (0, import_node_crypto54.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
231817
232291
|
const enc3 = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
|
|
231818
232292
|
return [iv.toString("base64"), cipher.getAuthTag().toString("base64"), enc3.toString("base64")].join(".");
|
|
231819
232293
|
}
|
|
231820
232294
|
decrypt(packed) {
|
|
231821
232295
|
const [iv, tag, data] = packed.split(".");
|
|
231822
232296
|
if (!iv || !tag || typeof data !== "string") throw new Error("malformed ciphertext");
|
|
231823
|
-
const decipher = (0,
|
|
232297
|
+
const decipher = (0, import_node_crypto54.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
|
|
231824
232298
|
decipher.setAuthTag(Buffer.from(tag, "base64"));
|
|
231825
232299
|
return Buffer.concat([decipher.update(Buffer.from(data, "base64")), decipher.final()]).toString("utf8");
|
|
231826
232300
|
}
|
|
@@ -232434,7 +232908,7 @@ async function listSkillMetadataForActor(args) {
|
|
|
232434
232908
|
usedDirs.add(dir);
|
|
232435
232909
|
const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
232436
232910
|
let latest = "1970-01-01T00:00:00.000Z";
|
|
232437
|
-
const hasher = (0,
|
|
232911
|
+
const hasher = (0, import_node_crypto55.createHash)("sha256");
|
|
232438
232912
|
for (const m2 of sorted) {
|
|
232439
232913
|
if (m2.updatedAt > latest) latest = m2.updatedAt;
|
|
232440
232914
|
hasher.update(m2.path);
|
|
@@ -232459,11 +232933,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
232459
232933
|
const dir = sanitizeSkillDir(c.name, c.slug);
|
|
232460
232934
|
if (usedDirs.has(dir)) continue;
|
|
232461
232935
|
usedDirs.add(dir);
|
|
232462
|
-
const hasher = (0,
|
|
232936
|
+
const hasher = (0, import_node_crypto55.createHash)("sha256");
|
|
232463
232937
|
for (const p2 of paths) {
|
|
232464
232938
|
hasher.update(p2);
|
|
232465
232939
|
hasher.update("\0");
|
|
232466
|
-
hasher.update((0,
|
|
232940
|
+
hasher.update((0, import_node_crypto55.createHash)("sha256").update(c.files[p2]).digest("hex"));
|
|
232467
232941
|
hasher.update("\0");
|
|
232468
232942
|
}
|
|
232469
232943
|
out.push({
|
|
@@ -232484,11 +232958,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
232484
232958
|
const dir = sanitizeSkillDir(b2.name, b2.id);
|
|
232485
232959
|
if (usedDirs.has(dir)) continue;
|
|
232486
232960
|
usedDirs.add(dir);
|
|
232487
|
-
const hasher = (0,
|
|
232961
|
+
const hasher = (0, import_node_crypto55.createHash)("sha256");
|
|
232488
232962
|
for (const p2 of paths) {
|
|
232489
232963
|
hasher.update(p2);
|
|
232490
232964
|
hasher.update("\0");
|
|
232491
|
-
hasher.update((0,
|
|
232965
|
+
hasher.update((0, import_node_crypto55.createHash)("sha256").update(b2.files[p2]).digest("hex"));
|
|
232492
232966
|
hasher.update("\0");
|
|
232493
232967
|
}
|
|
232494
232968
|
out.push({
|
|
@@ -232508,7 +232982,7 @@ function builtinSkillToFiles(b2) {
|
|
|
232508
232982
|
skillId: `builtin:${b2.id}`,
|
|
232509
232983
|
path: path47,
|
|
232510
232984
|
content: content3,
|
|
232511
|
-
blobHash: (0,
|
|
232985
|
+
blobHash: (0, import_node_crypto55.createHash)("sha256").update(content3).digest("hex"),
|
|
232512
232986
|
size: Buffer.byteLength(content3, "utf8"),
|
|
232513
232987
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
232514
232988
|
}));
|
|
@@ -232532,7 +233006,7 @@ function sanitizeSkillDir(name, fallbackId) {
|
|
|
232532
233006
|
if (byName) return byName;
|
|
232533
233007
|
const byId = fallbackId ? fold2(fallbackId) : "";
|
|
232534
233008
|
if (byId) return byId;
|
|
232535
|
-
return `skill-${(0,
|
|
233009
|
+
return `skill-${(0, import_node_crypto55.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`;
|
|
232536
233010
|
}
|
|
232537
233011
|
async function materializeSkillFiles(args) {
|
|
232538
233012
|
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
@@ -232565,7 +233039,7 @@ function connectorSkillToFiles(c) {
|
|
|
232565
233039
|
skillId: c.id,
|
|
232566
233040
|
path: path47,
|
|
232567
233041
|
content: content3,
|
|
232568
|
-
blobHash: (0,
|
|
233042
|
+
blobHash: (0, import_node_crypto55.createHash)("sha256").update(content3).digest("hex"),
|
|
232569
233043
|
size: Buffer.byteLength(content3, "utf8"),
|
|
232570
233044
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
232571
233045
|
}));
|
|
@@ -232582,11 +233056,11 @@ function connectorSkillDisplayRows(connectorSkills, enabledConnectors) {
|
|
|
232582
233056
|
...s2.version !== void 0 ? { version: s2.version } : {}
|
|
232583
233057
|
}));
|
|
232584
233058
|
}
|
|
232585
|
-
var
|
|
233059
|
+
var import_node_crypto55;
|
|
232586
233060
|
var init_skill_materializer = __esm({
|
|
232587
233061
|
"../server/src/domains/actors/skill-materializer.ts"() {
|
|
232588
233062
|
"use strict";
|
|
232589
|
-
|
|
233063
|
+
import_node_crypto55 = require("node:crypto");
|
|
232590
233064
|
}
|
|
232591
233065
|
});
|
|
232592
233066
|
|
|
@@ -234693,7 +235167,7 @@ function createActorsDomain(opts) {
|
|
|
234693
235167
|
...kernel !== void 0 ? { onRolesChanged: (a, r) => kernel.setActorRoles(a, r) } : {},
|
|
234694
235168
|
audit: async (entry) => {
|
|
234695
235169
|
await opts.audit?.({
|
|
234696
|
-
id: `reg_${(0,
|
|
235170
|
+
id: `reg_${(0, import_node_crypto56.randomUUID)()}`,
|
|
234697
235171
|
actor: entry.by,
|
|
234698
235172
|
kind: "registry_change",
|
|
234699
235173
|
target: entry.actorId,
|
|
@@ -234733,11 +235207,11 @@ function createActorsDomain(opts) {
|
|
|
234733
235207
|
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 } : {}, ...opts.agentManageGuard ? { agentManageGuard: opts.agentManageGuard } : {} })
|
|
234734
235208
|
};
|
|
234735
235209
|
}
|
|
234736
|
-
var
|
|
235210
|
+
var import_node_crypto56;
|
|
234737
235211
|
var init_actors = __esm({
|
|
234738
235212
|
"../server/src/domains/actors/index.ts"() {
|
|
234739
235213
|
"use strict";
|
|
234740
|
-
|
|
235214
|
+
import_node_crypto56 = require("node:crypto");
|
|
234741
235215
|
init_service5();
|
|
234742
235216
|
init_routes3();
|
|
234743
235217
|
init_service5();
|
|
@@ -236426,6 +236900,13 @@ function isPendingActor(id) {
|
|
|
236426
236900
|
function isAgentActor(id) {
|
|
236427
236901
|
return typeof id === "string" && id.startsWith("actor:agent:");
|
|
236428
236902
|
}
|
|
236903
|
+
function isBlockingBackpressure(i) {
|
|
236904
|
+
if (i.kind === "gap" || i.kind === "escalation") return false;
|
|
236905
|
+
if (i.intent === "advisory") return false;
|
|
236906
|
+
const from = i.raisedByNodeId;
|
|
236907
|
+
const about = i.aboutNodeId;
|
|
236908
|
+
return !!from && !!about && from !== about;
|
|
236909
|
+
}
|
|
236429
236910
|
function isDispatchLayerFailure(detail) {
|
|
236430
236911
|
const reason = detail?.reason;
|
|
236431
236912
|
return typeof reason === "string" && reason.startsWith("dispatch ");
|
|
@@ -236650,12 +237131,8 @@ function buildWorkorderActivity(input) {
|
|
|
236650
237131
|
} else if (r.decision === "approved" || r.decision === "completed") h.to = h.to ?? r.decidedAt ?? r.at;
|
|
236651
237132
|
}
|
|
236652
237133
|
for (const i of snap.issues) {
|
|
236653
|
-
if (i
|
|
236654
|
-
|
|
236655
|
-
const from = i.raisedByNodeId;
|
|
236656
|
-
const about = i.aboutNodeId;
|
|
236657
|
-
if (!from || !about || from === about) continue;
|
|
236658
|
-
addHold(from, { kind: "backpressure", from: i.createdAt, to: i.resolvedAt ?? null, upstream: about });
|
|
237134
|
+
if (!isBlockingBackpressure(i)) continue;
|
|
237135
|
+
addHold(i.raisedByNodeId, { kind: "backpressure", from: i.createdAt, to: i.resolvedAt ?? null, upstream: i.aboutNodeId });
|
|
236659
237136
|
}
|
|
236660
237137
|
const HOLD_RANK = { paused: 0, continuationDenied: 1, continuation: 2, backpressure: 3 };
|
|
236661
237138
|
const holdOf2 = (w2) => {
|
|
@@ -236675,11 +237152,50 @@ function buildWorkorderActivity(input) {
|
|
|
236675
237152
|
};
|
|
236676
237153
|
const lastStampOf = (w2) => [w2.createdAt, w2.startedAt, w2.endedAt, w2.deadAt, w2.cancelledAt].filter((t) => !!t).sort().at(-1);
|
|
236677
237154
|
const concludedRootBriefNodeIds = /* @__PURE__ */ new Set();
|
|
237155
|
+
const blockingBackpressure = snap.issues.filter((i) => isBlockingBackpressure(i));
|
|
237156
|
+
const blockingBackpressureIds = new Set(blockingBackpressure.map((i) => i.id));
|
|
237157
|
+
const backpressureRaisedBy = /* @__PURE__ */ new Map();
|
|
237158
|
+
for (const i of [...blockingBackpressure].sort((a, b2) => a.createdAt.localeCompare(b2.createdAt) || a.id.localeCompare(b2.id))) {
|
|
237159
|
+
const from = i.raisedByNodeId;
|
|
237160
|
+
backpressureRaisedBy.set(from, [...backpressureRaisedBy.get(from) ?? [], i]);
|
|
237161
|
+
}
|
|
237162
|
+
const backpressureOnRaiserCard = /* @__PURE__ */ new Set();
|
|
237163
|
+
const backpressureDriving = /* @__PURE__ */ new Map();
|
|
237164
|
+
{
|
|
237165
|
+
const add = (workId, issueId) => {
|
|
237166
|
+
if (!issueId || !blockingBackpressureIds.has(issueId)) return;
|
|
237167
|
+
const list2 = backpressureDriving.get(workId) ?? [];
|
|
237168
|
+
if (!list2.includes(issueId)) list2.push(issueId);
|
|
237169
|
+
backpressureDriving.set(workId, list2);
|
|
237170
|
+
};
|
|
237171
|
+
for (const rec2 of events) {
|
|
237172
|
+
const ev = rec2.event;
|
|
237173
|
+
if (ev.kind !== "work.create" || !ev.workId) continue;
|
|
237174
|
+
for (const r of ev.reasons ?? []) if (r.kind === "issue") add(ev.workId, r.issueId);
|
|
237175
|
+
}
|
|
237176
|
+
for (const w2 of snap.works) for (const id of w2.frozenIssueIds ?? []) add(w2.id, id);
|
|
237177
|
+
}
|
|
237178
|
+
const backpressureTargetName = (nodeId) => nodeId && rootBriefNodeIds.has(nodeId) ? "\u4EFB\u52A1\u8BF4\u660E" : nodeName(nodeId);
|
|
237179
|
+
const backpressureOwnerOf = (nodeId) => {
|
|
237180
|
+
const assignee = nodeId ? nodeById.get(nodeId)?.assigneeActorId : void 0;
|
|
237181
|
+
return assignee && !isPendingActor(assignee) ? assignee : ownerId;
|
|
237182
|
+
};
|
|
237183
|
+
const backpressureRaisersOf = (workId) => {
|
|
237184
|
+
const ids2 = backpressureDriving.get(workId);
|
|
237185
|
+
if (!ids2?.length) return void 0;
|
|
237186
|
+
const authors = [...new Set(ids2.map((id) => issueById.get(id)?.authorActorId).filter((a) => !!a))];
|
|
237187
|
+
return authors.length ? authors.map(nameOf2).join("\u3001") : void 0;
|
|
237188
|
+
};
|
|
236678
237189
|
for (const [nodeId, works] of worksOfNode) {
|
|
236679
237190
|
const interrupts = [...interruptsOfNode.get(nodeId) ?? []].sort((a, b2) => a.at.localeCompare(b2.at) || a.issueId.localeCompare(b2.issueId));
|
|
236680
237191
|
const trips = stopLossOfNode.get(nodeId) ?? [];
|
|
236681
237192
|
const interventions = [...interventionsOfNode.get(nodeId) ?? []].sort();
|
|
236682
237193
|
const humanBetween = (prev, w2) => !!prev && interventions.some((t) => t >= lastStampOf(prev) && t <= w2.createdAt);
|
|
237194
|
+
const upstreamRoundBetween = (prev, w2) => {
|
|
237195
|
+
if (!prev) return false;
|
|
237196
|
+
const ancestors = ancestorsOf(nodeId);
|
|
237197
|
+
return snap.works.some((u) => u.lane !== "reply" && ancestors.has(u.nodeId) && u.createdAt > prev.createdAt && u.createdAt <= w2.createdAt);
|
|
237198
|
+
};
|
|
236683
237199
|
const node2 = nodeById.get(nodeId);
|
|
236684
237200
|
const nodeCancelledAt = node2?.cancelledAt ?? null;
|
|
236685
237201
|
const name = nodeName(nodeId);
|
|
@@ -236691,17 +237207,20 @@ function buildWorkorderActivity(input) {
|
|
|
236691
237207
|
const st = statusOf2(w2);
|
|
236692
237208
|
const nextStart = nextStartOf.get(w2.id) ?? null;
|
|
236693
237209
|
const interrupt = interrupts.find((t) => t.at >= w2.createdAt && (!nextStart || t.at < nextStart));
|
|
237210
|
+
const roundEndedAt = w2.endedAt ?? w2.deadAt ?? w2.cancelledAt;
|
|
237211
|
+
const raisedHere = !w2.conclusion && !interrupt ? (backpressureRaisedBy.get(nodeId) ?? []).filter((i) => i.createdAt >= w2.createdAt && (!nextStart || i.createdAt < nextStart) && (!roundEndedAt || i.createdAt <= roundEndedAt)) : [];
|
|
237212
|
+
const halted = !!interrupt || raisedHere.length > 0;
|
|
236694
237213
|
const tripsHere = trips.filter((t) => t.at >= w2.createdAt && (!nextStart || t.at < nextStart));
|
|
236695
237214
|
const removedHere = !!nodeCancelledAt && nodeCancelledAt >= w2.createdAt && (!next || nodeCancelledAt < next.createdAt);
|
|
236696
237215
|
const reassigned = !!next && next.assigneeActorId !== w2.assigneeActorId;
|
|
236697
237216
|
const killedByPlan = !!(w2.deadAt || w2.cancelledAt) && !!next && (reassigned || (next.nodeVersion ?? 0) > (w2.nodeVersion ?? 0));
|
|
236698
237217
|
const killedAtOfRound = w2.deadAt ?? w2.cancelledAt;
|
|
236699
|
-
const supersededBy = !w2.conclusion && !
|
|
236700
|
-
const failedRound = !w2.conclusion && !
|
|
237218
|
+
const supersededBy = !w2.conclusion && !halted && !removedHere && !killedByPlan && killedAtOfRound && next && !killedByWorkorderPause(w2, killedAtOfRound) ? supersedingUpstreamVersion(nodeId, w2, killedAtOfRound, next) : void 0;
|
|
237219
|
+
const failedRound = !w2.conclusion && !halted && !removedHere && !killedByPlan && !supersededBy && (!!w2.deadAt || !!w2.cancelledAt || st === "failed" || st === "retry" || noOutputRound(w2));
|
|
236701
237220
|
const foldableFailure = failedRound && !(killedAtOfRound && killedByWorkorderPause(w2, killedAtOfRound));
|
|
236702
|
-
const ackedRound = st === "success" && !!w2.upstreamAck && !w2.conclusion && artifacts.length === 0 && !
|
|
236703
|
-
const held = !w2.conclusion && !
|
|
236704
|
-
const handedOverRound = !w2.conclusion && !
|
|
237221
|
+
const ackedRound = st === "success" && !!w2.upstreamAck && !w2.conclusion && artifacts.length === 0 && !halted && !removedHere && !killedByPlan && !supersededBy && !failedRound;
|
|
237222
|
+
const held = !w2.conclusion && !halted && !removedHere && !killedByPlan && !supersededBy && !failedRound && !ackedRound ? holdOf2(w2) : void 0;
|
|
237223
|
+
const handedOverRound = !w2.conclusion && !halted && !removedHere && !killedByPlan && !supersededBy && !failedRound && !held && !ackedRound && st === "success" && !!w2.endedAt && !!next;
|
|
236705
237224
|
const refiredByFuse = tripsHere.some((t) => t.kind === "output_stall");
|
|
236706
237225
|
const brokenByHuman = humanBetween(works[idx - 1], w2) && !refiredByFuse;
|
|
236707
237226
|
if (foldableFailure && fold2 && !brokenByHuman) {
|
|
@@ -236714,7 +237233,7 @@ function buildWorkorderActivity(input) {
|
|
|
236714
237233
|
if (tripsHere.length) fold2.stopLossTrips = [...fold2.stopLossTrips ?? [], ...tripsHere];
|
|
236715
237234
|
continue;
|
|
236716
237235
|
}
|
|
236717
|
-
const absorb2 = fold2 && !brokenByHuman && !!w2.conclusion && fold2.executorId === w2.assigneeActorId ? fold2 : null;
|
|
237236
|
+
const absorb2 = fold2 && !brokenByHuman && !!w2.conclusion && fold2.executorId === w2.assigneeActorId && !upstreamRoundBetween(works[idx - 1], w2) ? fold2 : null;
|
|
236718
237237
|
fold2 = null;
|
|
236719
237238
|
if (handedOverRound && handoverFold && handoverFold.executorId === w2.assigneeActorId) {
|
|
236720
237239
|
handoverFold.traceWorkIds.push(w2.id);
|
|
@@ -236749,6 +237268,7 @@ function buildWorkorderActivity(input) {
|
|
|
236749
237268
|
}
|
|
236750
237269
|
executionCards.push(card2);
|
|
236751
237270
|
cardOfWork.set(w2.id, card2);
|
|
237271
|
+
if (isHumanActorId(card2.executorId) && backpressureDriving.has(w2.id)) card2.humanTrace = true;
|
|
236752
237272
|
if (w2.conclusion) {
|
|
236753
237273
|
card2.phase = "done";
|
|
236754
237274
|
if (rootBriefNodeIds.has(nodeId)) {
|
|
@@ -236764,6 +237284,10 @@ function buildWorkorderActivity(input) {
|
|
|
236764
237284
|
card2.status = awaits ? ACTIVITY_COPY.doneAwaitingReview(name) : ACTIVITY_COPY.done(name);
|
|
236765
237285
|
}
|
|
236766
237286
|
}
|
|
237287
|
+
const bpRaisers = backpressureRaisersOf(w2.id);
|
|
237288
|
+
if (bpRaisers && (card2.status === ACTIVITY_COPY.done(name) || card2.status === ACTIVITY_COPY.goalConfirmed || card2.status === ACTIVITY_COPY.goalRevised)) {
|
|
237289
|
+
card2.status = ACTIVITY_COPY.backpressureAddressed(bpRaisers, backpressureTargetName(nodeId));
|
|
237290
|
+
}
|
|
236767
237291
|
} else if (interrupt) {
|
|
236768
237292
|
card2.phase = "stuck";
|
|
236769
237293
|
card2.segmentOpen = false;
|
|
@@ -236772,6 +237296,18 @@ function buildWorkorderActivity(input) {
|
|
|
236772
237296
|
card2.actions = [{ kind: "open_thread", label: BUTTON.view, target: gapThreadSessionId(interrupt.authorId), variant: "quiet" }];
|
|
236773
237297
|
}
|
|
236774
237298
|
if (interrupt.at > card2.updatedAt) card2.updatedAt = interrupt.at;
|
|
237299
|
+
} else if (raisedHere.length) {
|
|
237300
|
+
card2.phase = "stuck";
|
|
237301
|
+
card2.segmentOpen = false;
|
|
237302
|
+
card2.awaitingHuman = false;
|
|
237303
|
+
const upstreams = [...new Set(raisedHere.map((i) => i.aboutNodeId))];
|
|
237304
|
+
const targets = upstreams.map(backpressureTargetName);
|
|
237305
|
+
const owners = [...new Set(upstreams.map((u) => nameOf2(backpressureOwnerOf(u))))];
|
|
237306
|
+
card2.status = artifacts.length ? ACTIVITY_COPY.backpressureAfterStage(name, targets, owners) : ACTIVITY_COPY.backpressure(nameOf2(card2.executorId), targets, owners);
|
|
237307
|
+
for (const i of raisedHere) {
|
|
237308
|
+
backpressureOnRaiserCard.add(i.id);
|
|
237309
|
+
if (i.createdAt > card2.updatedAt) card2.updatedAt = i.createdAt;
|
|
237310
|
+
}
|
|
236775
237311
|
} else if (supersededBy) {
|
|
236776
237312
|
card2.phase = "stuck";
|
|
236777
237313
|
card2.segmentOpen = false;
|
|
@@ -236934,7 +237470,7 @@ function buildWorkorderActivity(input) {
|
|
|
236934
237470
|
const forcedBy = str5(reasons.find((r) => r.kind === "forced")?.actorId);
|
|
236935
237471
|
const parentWorkId = str5(workById.get(workId)?.parentWorkId);
|
|
236936
237472
|
const reworkOfRejected = !!parentWorkId && workById.get(parentWorkId)?.acceptanceState === "rejected";
|
|
236937
|
-
const status = reasonKinds.has("rework") || reworkOfRejected ? ACTIVITY_COPY.reworking(nodeName(nodeId)) : reasonKinds.has("resumed") ? ACTIVITY_COPY.resumed(nameOf2(d.executorId), nodeName(nodeId)) : reasonKinds.has("spec_changed") ? ACTIVITY_COPY.specChanged(nodeName(nodeId)) : reasonKinds.has("issue") ? ACTIVITY_COPY.issueDriven(nodeName(nodeId)) : forcedBy ? ACTIVITY_COPY.forcedRerun(nameOf2(forcedBy), nodeName(nodeId)) : ACTIVITY_COPY.working(nodeName(nodeId));
|
|
237473
|
+
const status = reasonKinds.has("rework") || reworkOfRejected ? ACTIVITY_COPY.reworking(nodeName(nodeId)) : reasonKinds.has("resumed") ? ACTIVITY_COPY.resumed(nameOf2(d.executorId), nodeName(nodeId)) : reasonKinds.has("spec_changed") ? ACTIVITY_COPY.specChanged(nodeName(nodeId)) : reasonKinds.has("issue") ? backpressureRaisersOf(workId) ? ACTIVITY_COPY.backpressureInProgress(backpressureRaisersOf(workId), backpressureTargetName(nodeId)) : ACTIVITY_COPY.issueDriven(nodeName(nodeId)) : forcedBy ? ACTIVITY_COPY.forcedRerun(nameOf2(forcedBy), nodeName(nodeId)) : ACTIVITY_COPY.working(nodeName(nodeId));
|
|
236938
237474
|
for (const r of reasons) {
|
|
236939
237475
|
if (r.kind !== "issue") continue;
|
|
236940
237476
|
const issueId = str5(r.issueId);
|
|
@@ -237052,6 +237588,7 @@ function buildWorkorderActivity(input) {
|
|
|
237052
237588
|
const raisedFrom = str5(ev.raisedByNodeId);
|
|
237053
237589
|
const isBackpressure = !isEscalation && !isGap && !!raisedFrom && raisedFrom !== nodeId;
|
|
237054
237590
|
if (isBackpressure) backpressureIssueIds.add(issueId);
|
|
237591
|
+
if (isBackpressure && backpressureOnRaiserCard.has(issueId)) break;
|
|
237055
237592
|
const body2 = str5(ev.body) ?? "";
|
|
237056
237593
|
if (isEscalation) {
|
|
237057
237594
|
const linkedGapId = str5(ev.gapId);
|
|
@@ -237106,8 +237643,8 @@ function buildWorkorderActivity(input) {
|
|
|
237106
237643
|
...isBackpressure ? { segmentOpen: false, awaitingHuman: false } : {},
|
|
237107
237644
|
status: isBackpressure ? ACTIVITY_COPY.backpressure(
|
|
237108
237645
|
nameOf2(authorId),
|
|
237109
|
-
|
|
237110
|
-
nameOf2((nodeId ? nodeById.get(nodeId)?.assigneeActorId : void 0) ?? ownerId)
|
|
237646
|
+
[backpressureTargetName(nodeId)],
|
|
237647
|
+
[nameOf2((nodeId ? nodeById.get(nodeId)?.assigneeActorId : void 0) ?? ownerId)]
|
|
237111
237648
|
) : ACTIVITY_COPY.commentRaised(nameOf2(authorId), nameOf2(commentTargetId ?? ownerId), nodeName(nodeId)),
|
|
237112
237649
|
/* **正文一律不上卡**:缺口去缺口线、回压去产物批注、留言去留言线。
|
|
237113
237650
|
此前只有缺口/回压被排除,留言仍是「正文当小状态 + 展开区再印一遍」,
|
|
@@ -237441,7 +237978,7 @@ function buildWorkorderActivity(input) {
|
|
|
237441
237978
|
card2.phaseLabel = PHASE_LABEL.escalationPending;
|
|
237442
237979
|
card2.segmentOpen = true;
|
|
237443
237980
|
card2.awaitingHuman = true;
|
|
237444
|
-
card2.status = ACTIVITY_COPY.backpressureAwaitingOwner(nameOf2(card2.executorId),
|
|
237981
|
+
card2.status = ACTIVITY_COPY.backpressureAwaitingOwner(nameOf2(card2.executorId), backpressureTargetName(card2.nodeId));
|
|
237445
237982
|
card2.actions = [{ kind: "open_issue", label: BUTTON.handle, target: issueId, variant: "primary" }];
|
|
237446
237983
|
}
|
|
237447
237984
|
for (const card2 of executionCards) {
|
|
@@ -237644,7 +238181,7 @@ function buildWorkorderActivity(input) {
|
|
|
237644
238181
|
artifacts: d.artifacts,
|
|
237645
238182
|
actions: d.actions,
|
|
237646
238183
|
...traced && d.traceAvailable ? { traceAvailable: true } : {},
|
|
237647
|
-
...d.traceWorkIds?.length ? { traceWorkIds: d.traceWorkIds, ...traced ? { traceAvailable: true } : {} } : {},
|
|
238184
|
+
...d.traceWorkIds?.length ? { traceWorkIds: d.traceWorkIds, ...traced || d.humanTrace ? { traceAvailable: true } : {} } : {},
|
|
237648
238185
|
.../* @__PURE__ */ ((r) => r ? { runId: r, traceAvailable: true } : {})(traced ? runIdOfCard(d) : void 0)
|
|
237649
238186
|
};
|
|
237650
238187
|
});
|
|
@@ -237901,6 +238438,7 @@ var init_activity2 = __esm({
|
|
|
237901
238438
|
heldByContinuation: (node2) => `\u300A${node2}\u300B\u5DF2\u4EA4\u4ED8\u9636\u6BB5\u6210\u679C\uFF0C\u672C\u6279\u7EED\u8DD1\u989D\u5EA6\u5DF2\u7528\u5B8C\uFF0C\u7B49\u5F85\u6279\u51C6\u7EE7\u7EED\u3002`,
|
|
237902
238439
|
heldByContinuationDenied: (node2) => `\u300A${node2}\u300B\u5DF2\u4EA4\u4ED8\u9636\u6BB5\u6210\u679C\uFF0C\u7EED\u8DD1\u7533\u8BF7\u672A\u83B7\u6279\u51C6\uFF0C\u8282\u70B9\u5DF2\u6682\u505C\uFF0C\u7B49\u5F85\u653E\u884C\u3002`,
|
|
237903
238440
|
heldByWorkorderPause: (node2) => `\u300A${node2}\u300B\u5DF2\u4EA4\u4ED8\u9636\u6BB5\u6210\u679C\uFF0C\u4EFB\u52A1\u5DF2\u6682\u505C\uFF0C\u7B49\u5F85\u6062\u590D\u3002`,
|
|
238441
|
+
/** 只剩「交完稿、这一轮结束之后才补提」的那一档;同一轮里提的见 {@link ACTIVITY_COPY.backpressureAfterStage}(ADR 0623 补章)。 */
|
|
237904
238442
|
heldByBackpressure: (node2, upstreams) => `\u300A${node2}\u300B\u5DF2\u4EA4\u4ED8\uFF0C\u7B49\u5F85${upstreams.map((u) => `\u300A${u}\u300B`).join("\u3001")}\u5904\u7406\u4FEE\u6539\u8981\u6C42\u540E\u518D\u6536\u53E3\u3002`,
|
|
237905
238443
|
/** `works.status=retry`:这一轮没跑成,等引擎重派。谁按的重试由 `plan.node_retry` 补进这句。 */
|
|
237906
238444
|
awaitingRedispatch: (executor, node2) => `${executor} \u8FD9\u4E00\u8F6E\u6CA1\u8DD1\u6210\u300A${node2}\u300B\uFF0C\u7B49\u5F85\u91CD\u6D3E\u3002`,
|
|
@@ -237953,8 +238491,27 @@ var init_activity2 = __esm({
|
|
|
237953
238491
|
(「{X} 遇到处理不了的问题,需要 @{Y} 的协助」)——**别在别处复用**:系统代开的两种止损
|
|
237954
238492
|
上报根本没有人「开口」,套这句话是假话(生产上它已经把 `actor:system` 渲染成了句子的主语)。
|
|
237955
238493
|
①「缺口卡」也删掉(F4):它和执行卡挂的是同一段运行、同一份轨迹,点哪张打开的都一样。 */
|
|
237956
|
-
/**
|
|
237957
|
-
|
|
238494
|
+
/**
|
|
238495
|
+
* 回压(下游对上游提修改要求)——发起人 2026-09-08 认可的措辞。
|
|
238496
|
+
*
|
|
238497
|
+
* 2026-09-23 起它是**提出方那一轮执行卡的结局句**(奕璇定,与缺口 F4 同一做法):提要求这件事就发生在
|
|
238498
|
+
* 那一轮里,不再单独出一张 `issue:` 卡。同一轮对几个上游提了要求时并成一句(《A》、《B》 / @X、@Y)。
|
|
238499
|
+
* 🚨 **之后一个字不改**:要求关掉了也不翻署名、不改写成「已基于…更新了一版」——那是被要求方那张卡的事。
|
|
238500
|
+
*/
|
|
238501
|
+
backpressure: (raiser, upstreams, owners) => `${raiser} \u5BF9${upstreams.map((u) => `\u300A${u}\u300B`).join("\u3001")}\u63D0\u51FA\u4FEE\u6539\u8981\u6C42\uFF0C\u9700\u8981 ${owners.map((o) => `@${o}`).join("\u3001")} \u5904\u7406\u3002`,
|
|
238502
|
+
/**
|
|
238503
|
+
* 同上,但提出方**这一轮先交了阶段成果**(propose 了、没 conclude)、同一轮又提了修改要求(奕璇 2026-09-23 定,
|
|
238504
|
+
* ADR 0623 补章):此前这一档出两张卡——自己那轮「已交付,等待《X》处理修改要求后再收口」+ 一张 `issue:` 回压卡。
|
|
238505
|
+
* 合成这一句:「交了什么」由卡上 / 轨迹里的交付物说,句子说「停在哪、等谁」。之后同样一个字不改。
|
|
238506
|
+
*/
|
|
238507
|
+
backpressureAfterStage: (node2, upstreams, owners) => `\u300A${node2}\u300B\u5DF2\u63D0\u4EA4\u9636\u6BB5\u6210\u679C\uFF0C\u5BF9${upstreams.map((u) => `\u300A${u}\u300B`).join("\u3001")}\u63D0\u51FA\u4FEE\u6539\u8981\u6C42\uFF0C\u9700\u8981 ${owners.map((o) => `@${o}`).join("\u3001")} \u5904\u7406\u3002`,
|
|
238508
|
+
/** 被要求方是 agent、正在按修改要求改的那一轮(取代通用的「正在根据反馈调整」:说清是谁提的)。 */
|
|
238509
|
+
backpressureInProgress: (raisers, node2) => `\u6B63\u5728\u6839\u636E ${raisers} \u7684\u4FEE\u6539\u8981\u6C42\u8C03\u6574\u300A${node2}\u300B\u3002`,
|
|
238510
|
+
/**
|
|
238511
|
+
* 被要求方按修改要求交出了新一版(agent / 真人同一句)。取代「《X》已完成」「已修订目标」——
|
|
238512
|
+
* 此前同一件事还另有一张回压卡收口成「{X} 已基于 {Z} 的留言更新了一版」,一件事三张卡。
|
|
238513
|
+
*/
|
|
238514
|
+
backpressureAddressed: (raisers, node2) => `\u5DF2\u6309 ${raisers} \u7684\u4FEE\u6539\u8981\u6C42\u66F4\u65B0\u300A${node2}\u300B\u3002`,
|
|
237958
238515
|
/**
|
|
237959
238516
|
* 被回压节点的负责人是**真人**时,系统为他开的那一轮(奕璇 2026-09-22 定):这一轮不会自己跑,
|
|
237960
238517
|
* 是在等他动手——不能再说「正在根据反馈调整」(`issueDriven`),那句会让一张没人在动的卡挂成「进行中」。
|
|
@@ -238113,6 +238670,26 @@ function buildWorkorderActivityTrace(input) {
|
|
|
238113
238670
|
if (!briefing) continue;
|
|
238114
238671
|
firstBriefing ??= briefing;
|
|
238115
238672
|
const sources = sourcesOfWork(work, input, briefing);
|
|
238673
|
+
const humanBackpressureRound = isHumanActorId(work.assigneeActorId) && sources.some((src) => {
|
|
238674
|
+
const issue2 = src.kind === "comment" ? snap.issues.find((i) => i.id === src.issueId) : void 0;
|
|
238675
|
+
return !!issue2 && isBlockingBackpressure(issue2);
|
|
238676
|
+
});
|
|
238677
|
+
if (humanBackpressureRound) {
|
|
238678
|
+
const before = previousVersionOf(work, snap);
|
|
238679
|
+
works.push({
|
|
238680
|
+
workId,
|
|
238681
|
+
at: work.createdAt,
|
|
238682
|
+
nodeTitle: briefing.nodeTitle,
|
|
238683
|
+
...briefing.spec ? { spec: briefing.spec } : {},
|
|
238684
|
+
sources,
|
|
238685
|
+
attempts: [],
|
|
238686
|
+
artifacts: [
|
|
238687
|
+
...before ? artifactsOfWork(before, input).map((a) => ({ ...a, name: `${a.name}\uFF08\u6539\u524D\uFF09` })) : [],
|
|
238688
|
+
...artifactsOfWork(work, input).map((a) => ({ ...a, name: `${a.name}\uFF08\u6539\u540E\uFF09` }))
|
|
238689
|
+
]
|
|
238690
|
+
});
|
|
238691
|
+
continue;
|
|
238692
|
+
}
|
|
238116
238693
|
const artifacts = single.attempts.at(-1)?.artifacts ?? artifactsOfWork(work, input);
|
|
238117
238694
|
works.push({
|
|
238118
238695
|
workId,
|
|
@@ -238186,6 +238763,13 @@ function sourcesOfWork(work, input, briefing) {
|
|
|
238186
238763
|
...briefing.spec ? { content: briefing.spec } : {}
|
|
238187
238764
|
}];
|
|
238188
238765
|
}
|
|
238766
|
+
function previousVersionOf(work, snap) {
|
|
238767
|
+
const delivered = new Set(snap.artifacts.map((a) => a.workId));
|
|
238768
|
+
const parentId = work.parentWorkId;
|
|
238769
|
+
const parent = parentId ? snap.works.find((w2) => w2.id === parentId && delivered.has(w2.id)) : void 0;
|
|
238770
|
+
if (parent) return parent;
|
|
238771
|
+
return snap.works.filter((w2) => w2.nodeId === work.nodeId && w2.id !== work.id && w2.createdAt < work.createdAt && delivered.has(w2.id)).sort((a, b2) => a.createdAt.localeCompare(b2.createdAt) || a.id.localeCompare(b2.id)).at(-1);
|
|
238772
|
+
}
|
|
238189
238773
|
function artifactsOfWork(work, input) {
|
|
238190
238774
|
const snap = input.snap;
|
|
238191
238775
|
const workId = work.id;
|
|
@@ -238344,6 +238928,7 @@ var init_activity_trace = __esm({
|
|
|
238344
238928
|
"use strict";
|
|
238345
238929
|
init_src6();
|
|
238346
238930
|
init_review_activity();
|
|
238931
|
+
init_src();
|
|
238347
238932
|
init_activity2();
|
|
238348
238933
|
init_workorder_manager();
|
|
238349
238934
|
init_src7();
|
|
@@ -239255,11 +239840,11 @@ function fromRow(row) {
|
|
|
239255
239840
|
for (const [k2, v2] of opt) if (v2 !== void 0 && v2 !== null) r[k2] = v2;
|
|
239256
239841
|
return r;
|
|
239257
239842
|
}
|
|
239258
|
-
var
|
|
239843
|
+
var import_node_crypto57, import_node_fs16, DEFAULT_PAGE, MAX_PAGE, pageSize, MemoryNotificationStore, ident3, iso2, str2, PostgresNotificationStore;
|
|
239259
239844
|
var init_notification_store = __esm({
|
|
239260
239845
|
"../server/src/domains/collab/notification-store.ts"() {
|
|
239261
239846
|
"use strict";
|
|
239262
|
-
|
|
239847
|
+
import_node_crypto57 = require("node:crypto");
|
|
239263
239848
|
import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
239264
239849
|
DEFAULT_PAGE = 50;
|
|
239265
239850
|
MAX_PAGE = 200;
|
|
@@ -239292,7 +239877,7 @@ var init_notification_store = __esm({
|
|
|
239292
239877
|
async insert(n) {
|
|
239293
239878
|
const existing = this.findLive(n.recipient, n.sourceKey, n.category);
|
|
239294
239879
|
if (existing) return existing;
|
|
239295
|
-
const row = { ...n, id: `ntf:${(0,
|
|
239880
|
+
const row = { ...n, id: `ntf:${(0, import_node_crypto57.randomUUID)()}`, updatedAt: n.enteredAt };
|
|
239296
239881
|
this.rows.set(row.id, row);
|
|
239297
239882
|
this.save();
|
|
239298
239883
|
return row;
|
|
@@ -239425,7 +240010,7 @@ var init_notification_store = __esm({
|
|
|
239425
240010
|
return new _PostgresNotificationStore(sql, schema);
|
|
239426
240011
|
}
|
|
239427
240012
|
async insert(n) {
|
|
239428
|
-
const id = `ntf:${(0,
|
|
240013
|
+
const id = `ntf:${(0, import_node_crypto57.randomUUID)()}`;
|
|
239429
240014
|
const r = await this.sql.query(
|
|
239430
240015
|
`INSERT INTO ${this.t} (id, recipient, category, source_key, kind, workorder_id, node_id, card_id, actor_id,
|
|
239431
240016
|
title, workspace_title, entered_at, updated_at, status, read_at, item)
|
|
@@ -240554,13 +241139,13 @@ function nameKey(name) {
|
|
|
240554
241139
|
function cleanName(name) {
|
|
240555
241140
|
return name.trim().replace(/\s+/g, " ");
|
|
240556
241141
|
}
|
|
240557
|
-
var import_node_fs17, import_node_path21,
|
|
241142
|
+
var import_node_fs17, import_node_path21, import_node_crypto58, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
240558
241143
|
var init_tags = __esm({
|
|
240559
241144
|
"../server/src/domains/collab/tags.ts"() {
|
|
240560
241145
|
"use strict";
|
|
240561
241146
|
import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
240562
241147
|
import_node_path21 = __toESM(require("node:path"), 1);
|
|
240563
|
-
|
|
241148
|
+
import_node_crypto58 = __toESM(require("node:crypto"), 1);
|
|
240564
241149
|
SEP = "::";
|
|
240565
241150
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
240566
241151
|
prefixOf = (companyId) => `${companyId}${SEP}`;
|
|
@@ -240578,7 +241163,7 @@ var init_tags = __esm({
|
|
|
240578
241163
|
if (!name) return null;
|
|
240579
241164
|
if (this.entries(companyId).some((t) => nameKey(t.name) === nameKey(name))) return null;
|
|
240580
241165
|
const tag = {
|
|
240581
|
-
id: `tag-${
|
|
241166
|
+
id: `tag-${import_node_crypto58.default.randomBytes(6).toString("hex")}`,
|
|
240582
241167
|
name,
|
|
240583
241168
|
...input.color?.trim() ? { color: input.color.trim() } : {},
|
|
240584
241169
|
...input.description?.trim() ? { description: input.description.trim() } : {}
|
|
@@ -241967,11 +242552,11 @@ async function isEmployedElsewhere(store, companyId, accountId) {
|
|
|
241967
242552
|
const memberships = await store.listMembershipsForAccount(accountId);
|
|
241968
242553
|
return memberships.some((m2) => m2.companyId !== companyId);
|
|
241969
242554
|
}
|
|
241970
|
-
var
|
|
242555
|
+
var import_node_crypto59, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, INVITE_LINK_TTL_MS, INVITE_LINK_TOKEN_BYTES, INVITE_LINK_ROLE, SLUG_RE, CompanyError, CompaniesService;
|
|
241971
242556
|
var init_service6 = __esm({
|
|
241972
242557
|
"../server/src/domains/companies/service.ts"() {
|
|
241973
242558
|
"use strict";
|
|
241974
|
-
|
|
242559
|
+
import_node_crypto59 = require("node:crypto");
|
|
241975
242560
|
init_console_url();
|
|
241976
242561
|
ROLES = ["owner", "admin", "member"];
|
|
241977
242562
|
INVITABLE_ROLES = ["admin", "member"];
|
|
@@ -242070,9 +242655,13 @@ var init_service6 = __esm({
|
|
|
242070
242655
|
await this.store.updateCompany(id, { name });
|
|
242071
242656
|
return { ...company, name };
|
|
242072
242657
|
}
|
|
242073
|
-
/**
|
|
242658
|
+
/**
|
|
242659
|
+
* 设置/清除公司头像引用("blob:<哈希>";null = 回到默认首字母标识)。
|
|
242660
|
+
* 权限(本组织 owner/admin)由路由层 `requireOwnerOrAdmin` 强制;这里只守「组织还可用」
|
|
242661
|
+
* ——与本域其余写面同一条判据(D8.2:闸不只长在路由上),解散之后 404 COMPANY_NOT_FOUND。
|
|
242662
|
+
*/
|
|
242074
242663
|
async setAvatar(id, ref2) {
|
|
242075
|
-
const company = await this.
|
|
242664
|
+
const company = await this.requireActiveCompany(id);
|
|
242076
242665
|
await this.store.updateCompany(id, { avatar: ref2 });
|
|
242077
242666
|
const next = ref2 === null ? (({ avatar: _drop, ...rest }) => rest)(company) : { ...company, avatar: ref2 };
|
|
242078
242667
|
return next;
|
|
@@ -242086,7 +242675,7 @@ var init_service6 = __esm({
|
|
|
242086
242675
|
const existing = await this.store.getAccountByEmail(normalized4);
|
|
242087
242676
|
if (existing) return existing;
|
|
242088
242677
|
const account = {
|
|
242089
|
-
id: `actor:human:${(0,
|
|
242678
|
+
id: `actor:human:${(0, import_node_crypto59.randomUUID)()}`,
|
|
242090
242679
|
email: normalized4,
|
|
242091
242680
|
name: name ?? normalized4,
|
|
242092
242681
|
status: "active"
|
|
@@ -242484,7 +243073,7 @@ var init_service6 = __esm({
|
|
|
242484
243073
|
}
|
|
242485
243074
|
const nowMs = Date.parse(this.now());
|
|
242486
243075
|
const invitation = {
|
|
242487
|
-
id: `invitation:${(0,
|
|
243076
|
+
id: `invitation:${(0, import_node_crypto59.randomUUID)()}`,
|
|
242488
243077
|
companyId,
|
|
242489
243078
|
email: mail,
|
|
242490
243079
|
role,
|
|
@@ -242615,7 +243204,7 @@ var init_service6 = __esm({
|
|
|
242615
243204
|
const nowMs = Date.parse(this.now());
|
|
242616
243205
|
const link = {
|
|
242617
243206
|
companyId,
|
|
242618
|
-
token: (0,
|
|
243207
|
+
token: (0, import_node_crypto59.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
|
|
242619
243208
|
role: INVITE_LINK_ROLE,
|
|
242620
243209
|
createdAt: new Date(nowMs).toISOString(),
|
|
242621
243210
|
expiresAt: new Date(nowMs + INVITE_LINK_TTL_MS).toISOString(),
|
|
@@ -242672,7 +243261,7 @@ var init_service6 = __esm({
|
|
|
242672
243261
|
const reusable = existing.find((inv) => !this.isExpired(inv));
|
|
242673
243262
|
if (reusable) return reusable;
|
|
242674
243263
|
const invitation = {
|
|
242675
|
-
id: `invitation:${(0,
|
|
243264
|
+
id: `invitation:${(0, import_node_crypto59.randomUUID)()}`,
|
|
242676
243265
|
companyId: link.companyId,
|
|
242677
243266
|
email: mail,
|
|
242678
243267
|
role: link.role,
|
|
@@ -242718,9 +243307,9 @@ var init_service6 = __esm({
|
|
|
242718
243307
|
* 登录身份查自己那条 membership;不是成员 → 404。
|
|
242719
243308
|
*/
|
|
242720
243309
|
async completeMemberOnboarding(companyId, accountId) {
|
|
242721
|
-
await this.requireCompany(companyId);
|
|
242722
243310
|
const member = await this.store.getMember(companyId, accountId);
|
|
242723
243311
|
if (!member) throw new CompanyError(404, "NOT_FOUND", `\u4E0D\u662F\u8BE5\u516C\u53F8\u6210\u5458\uFF1A${accountId}`);
|
|
243312
|
+
await this.requireActiveCompany(companyId);
|
|
242724
243313
|
if (member.onboardingCompletedAt) return member;
|
|
242725
243314
|
const next = { ...member, onboardingCompletedAt: this.now() };
|
|
242726
243315
|
await this.store.upsertMember(next);
|
|
@@ -242744,9 +243333,9 @@ var init_service6 = __esm({
|
|
|
242744
243333
|
async setMemberOnboardingStep(companyId, accountId, step) {
|
|
242745
243334
|
const trimmed = step?.trim();
|
|
242746
243335
|
if (!trimmed) throw new CompanyError(400, "BAD_REQUEST", "step \u4E0D\u80FD\u4E3A\u7A7A");
|
|
242747
|
-
await this.requireCompany(companyId);
|
|
242748
243336
|
const member = await this.store.getMember(companyId, accountId);
|
|
242749
243337
|
if (!member) throw new CompanyError(404, "NOT_FOUND", `\u4E0D\u662F\u8BE5\u516C\u53F8\u6210\u5458\uFF1A${accountId}`);
|
|
243338
|
+
await this.requireActiveCompany(companyId);
|
|
242750
243339
|
const next = { ...member, onboardingStep: trimmed };
|
|
242751
243340
|
await this.store.upsertMember(next);
|
|
242752
243341
|
return next;
|
|
@@ -242906,11 +243495,11 @@ var init_service6 = __esm({
|
|
|
242906
243495
|
});
|
|
242907
243496
|
|
|
242908
243497
|
// ../server/src/domains/companies/offboarding.ts
|
|
242909
|
-
var
|
|
243498
|
+
var import_node_crypto60, OWNER_PROTECTED_MESSAGE, MemberOffboardingService;
|
|
242910
243499
|
var init_offboarding = __esm({
|
|
242911
243500
|
"../server/src/domains/companies/offboarding.ts"() {
|
|
242912
243501
|
"use strict";
|
|
242913
|
-
|
|
243502
|
+
import_node_crypto60 = require("node:crypto");
|
|
242914
243503
|
init_service6();
|
|
242915
243504
|
OWNER_PROTECTED_MESSAGE = "\u7EC4\u7EC7\u7BA1\u7406\u5458\u4E0D\u53EF\u88AB\u79FB\u9664\uFF0C\u53EA\u80FD\u7531\u672C\u4EBA\u8F6C\u4EA4\u6216\u89E3\u6563\u7EC4\u7EC7";
|
|
242916
243505
|
MemberOffboardingService = class {
|
|
@@ -242987,7 +243576,7 @@ var init_offboarding = __esm({
|
|
|
242987
243576
|
const { ownedAgents, inFlight } = await this.snapshot(companyId, accountId);
|
|
242988
243577
|
const at2 = this.now();
|
|
242989
243578
|
const started = await this.store.startMemberOffboarding({
|
|
242990
|
-
operationId: `off:${(0,
|
|
243579
|
+
operationId: `off:${(0, import_node_crypto60.randomUUID)()}`,
|
|
242991
243580
|
companyId,
|
|
242992
243581
|
accountId,
|
|
242993
243582
|
initiatedBy,
|
|
@@ -243219,6 +243808,13 @@ function companiesDomain(opts) {
|
|
|
243219
243808
|
await requireActiveCompany(companyId);
|
|
243220
243809
|
return me;
|
|
243221
243810
|
};
|
|
243811
|
+
const requireActiveSelfMember = async (req, companyId) => {
|
|
243812
|
+
const me = await whoami(req);
|
|
243813
|
+
const member = await service.getMember(companyId, me.accountId);
|
|
243814
|
+
if (!member) throw new ApiError(404, "NOT_FOUND", `\u4E0D\u662F\u8BE5\u516C\u53F8\u6210\u5458\uFF1A${me.accountId}`);
|
|
243815
|
+
await requireActiveCompany(companyId);
|
|
243816
|
+
return { me, member };
|
|
243817
|
+
};
|
|
243222
243818
|
return (router) => {
|
|
243223
243819
|
router.get("/api/companies", async (req) => {
|
|
243224
243820
|
const me = await whoami(req);
|
|
@@ -243268,13 +243864,17 @@ function companiesDomain(opts) {
|
|
|
243268
243864
|
return { status: 201, body: company };
|
|
243269
243865
|
});
|
|
243270
243866
|
router.post("/api/companies/:id/avatar", async (req) => {
|
|
243867
|
+
const cid = req.params.id;
|
|
243868
|
+
await requireOwnerOrAdmin(req, cid);
|
|
243271
243869
|
if (!blobs) throw new ApiError(501, "NOT_IMPLEMENTED", "blob \u5B58\u50A8\u672A\u63A5\u5165");
|
|
243272
243870
|
const ref2 = await storeImageBlob(blobs, req.body?.data);
|
|
243273
|
-
const company = await service.setAvatar(
|
|
243871
|
+
const company = await service.setAvatar(cid, ref2).catch(mapErr);
|
|
243274
243872
|
return { status: 201, body: { avatar: company.avatar } };
|
|
243275
243873
|
});
|
|
243276
243874
|
router.delete("/api/companies/:id/avatar", async (req) => {
|
|
243277
|
-
|
|
243875
|
+
const cid = req.params.id;
|
|
243876
|
+
await requireOwnerOrAdmin(req, cid);
|
|
243877
|
+
await service.setAvatar(cid, null).catch(mapErr);
|
|
243278
243878
|
return { status: 200, body: { ok: true } };
|
|
243279
243879
|
});
|
|
243280
243880
|
router.get("/api/companies/:id/members", async (req) => {
|
|
@@ -243284,23 +243884,23 @@ function companiesDomain(opts) {
|
|
|
243284
243884
|
return { status: 200, body: { items } };
|
|
243285
243885
|
});
|
|
243286
243886
|
router.get("/api/companies/:id/members/me", async (req) => {
|
|
243287
|
-
const
|
|
243288
|
-
const member = await service.getMember(req.params.id, me.accountId);
|
|
243289
|
-
if (!member) throw new ApiError(404, "NOT_FOUND", `\u4E0D\u662F\u8BE5\u516C\u53F8\u6210\u5458\uFF1A${me.accountId}`);
|
|
243887
|
+
const { member } = await requireActiveSelfMember(req, req.params.id);
|
|
243290
243888
|
return { status: 200, body: member };
|
|
243291
243889
|
});
|
|
243292
243890
|
router.post("/api/companies/:id/members/me/onboarding-complete", async (req) => {
|
|
243293
|
-
const
|
|
243294
|
-
const
|
|
243891
|
+
const cid = req.params.id;
|
|
243892
|
+
const { me } = await requireActiveSelfMember(req, cid);
|
|
243893
|
+
const member = await service.completeMemberOnboarding(cid, me.accountId).catch(mapErr);
|
|
243295
243894
|
return { status: 200, body: member };
|
|
243296
243895
|
});
|
|
243297
243896
|
router.post("/api/companies/:id/members/me/onboarding-step", async (req) => {
|
|
243298
|
-
const
|
|
243897
|
+
const cid = req.params.id;
|
|
243898
|
+
const { me } = await requireActiveSelfMember(req, cid);
|
|
243299
243899
|
const body2 = req.body ?? {};
|
|
243300
243900
|
if (typeof body2.step !== "string") {
|
|
243301
243901
|
throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 step: string");
|
|
243302
243902
|
}
|
|
243303
|
-
const member = await service.setMemberOnboardingStep(
|
|
243903
|
+
const member = await service.setMemberOnboardingStep(cid, me.accountId, body2.step).catch(mapErr);
|
|
243304
243904
|
return { status: 200, body: member };
|
|
243305
243905
|
});
|
|
243306
243906
|
router.patch("/api/companies/:id/members/:accountId", async (req) => {
|
|
@@ -243598,18 +244198,18 @@ var init_routes6 = __esm({
|
|
|
243598
244198
|
|
|
243599
244199
|
// ../server/src/domains/companies/agent-credentials.ts
|
|
243600
244200
|
function hashAgentToken(token, secret) {
|
|
243601
|
-
return HASH_PREFIX + (0,
|
|
244201
|
+
return HASH_PREFIX + (0, import_node_crypto61.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
|
|
243602
244202
|
}
|
|
243603
244203
|
function safeEqual(a, b2) {
|
|
243604
244204
|
const ba = Buffer.from(a);
|
|
243605
244205
|
const bb = Buffer.from(b2);
|
|
243606
|
-
return ba.length === bb.length && (0,
|
|
244206
|
+
return ba.length === bb.length && (0, import_node_crypto61.timingSafeEqual)(ba, bb);
|
|
243607
244207
|
}
|
|
243608
|
-
var
|
|
244208
|
+
var import_node_crypto61, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
|
|
243609
244209
|
var init_agent_credentials = __esm({
|
|
243610
244210
|
"../server/src/domains/companies/agent-credentials.ts"() {
|
|
243611
244211
|
"use strict";
|
|
243612
|
-
|
|
244212
|
+
import_node_crypto61 = require("node:crypto");
|
|
243613
244213
|
init_service6();
|
|
243614
244214
|
HASH_PREFIX = "ac1$";
|
|
243615
244215
|
TOKEN_PREFIX = "oak_";
|
|
@@ -243634,7 +244234,7 @@ var init_agent_credentials = __esm({
|
|
|
243634
244234
|
if (employee.status !== "active") {
|
|
243635
244235
|
throw new CompanyError(409, "AGENT_LEFT", `\u6570\u5B57\u5458\u5DE5\u5DF2\u79BB\u5F00\uFF0C\u4E0D\u80FD\u7B7E\u53D1\u51ED\u8BC1\uFF1A${agentId}`);
|
|
243636
244236
|
}
|
|
243637
|
-
const token = `${TOKEN_PREFIX}${(0,
|
|
244237
|
+
const token = `${TOKEN_PREFIX}${(0, import_node_crypto61.randomBytes)(32).toString("base64url")}`;
|
|
243638
244238
|
const credential = {
|
|
243639
244239
|
tokenHash: hashAgentToken(token, this.secret),
|
|
243640
244240
|
companyId,
|
|
@@ -244146,7 +244746,7 @@ function gatewayInstanceSlug(gatewayUrl) {
|
|
|
244146
244746
|
}
|
|
244147
244747
|
function connectInstanceName(gatewayUrl, token, companyId) {
|
|
244148
244748
|
const scope2 = companyId?.trim();
|
|
244149
|
-
const suffix = scope2 ? `c${(0,
|
|
244749
|
+
const suffix = scope2 ? `c${(0, import_node_crypto62.createHash)("sha256").update(`${gatewayUrl}\0${scope2}`).digest("hex").slice(0, 10)}` : token.replace(/[^a-z0-9]/gi, "").slice(-8).toLowerCase() || "enroll";
|
|
244150
244750
|
const base = gatewayInstanceSlug(gatewayUrl);
|
|
244151
244751
|
return base.slice(0, Math.max(1, 64 - suffix.length - 1)) + "-" + suffix;
|
|
244152
244752
|
}
|
|
@@ -244475,12 +245075,12 @@ function buildNpxCmd(p2) {
|
|
|
244475
245075
|
const prefix = daemonNpmPrefix();
|
|
244476
245076
|
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)}`;
|
|
244477
245077
|
}
|
|
244478
|
-
var
|
|
245078
|
+
var import_node_crypto62;
|
|
244479
245079
|
var init_connect_script = __esm({
|
|
244480
245080
|
"../server/src/domains/nodes/connect-script.ts"() {
|
|
244481
245081
|
"use strict";
|
|
244482
245082
|
init_src();
|
|
244483
|
-
|
|
245083
|
+
import_node_crypto62 = require("node:crypto");
|
|
244484
245084
|
}
|
|
244485
245085
|
});
|
|
244486
245086
|
|
|
@@ -244940,7 +245540,7 @@ function nodesDomain(deps) {
|
|
|
244940
245540
|
if (!daemon.meta.adapters.some((kind) => QUOTA_CAPABLE_KINDS.has(kind))) {
|
|
244941
245541
|
return { ok: false, code: "no-quota-runtime", reason: "\u8FD9\u53F0\u673A\u5668\u4E0A\u6CA1\u6709\u4F1A\u4E0A\u62A5\u989D\u5EA6\u7684\u8FD0\u884C\u65F6\uFF08\u53EA\u6709 Claude Code \u548C Codex \u80FD\u67E5\u5230\u8BA2\u9605\u989D\u5EA6\uFF09" };
|
|
244942
245542
|
}
|
|
244943
|
-
const requestId = (0,
|
|
245543
|
+
const requestId = (0, import_node_crypto63.randomUUID)();
|
|
244944
245544
|
const task = new Promise((resolve12) => {
|
|
244945
245545
|
const timer = setTimeout(() => {
|
|
244946
245546
|
quotaRefreshWaiters.delete(requestId);
|
|
@@ -245316,7 +245916,7 @@ function nodesDomain(deps) {
|
|
|
245316
245916
|
}
|
|
245317
245917
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
245318
245918
|
} else {
|
|
245319
|
-
nodeId = `node-${(0,
|
|
245919
|
+
nodeId = `node-${(0, import_node_crypto63.randomUUID)().slice(0, 8)}`;
|
|
245320
245920
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
245321
245921
|
}
|
|
245322
245922
|
const existingNode = await deps.nodeStore.getNode(nodeId);
|
|
@@ -245582,16 +246182,16 @@ function normalizeGatewayUrl(raw) {
|
|
|
245582
246182
|
}
|
|
245583
246183
|
}
|
|
245584
246184
|
function newNodeId() {
|
|
245585
|
-
return "node-" + (0,
|
|
246185
|
+
return "node-" + (0, import_node_crypto63.randomUUID)().replace(/-/g, "").slice(0, 12);
|
|
245586
246186
|
}
|
|
245587
|
-
var
|
|
246187
|
+
var import_node_crypto63, import_node_fs18, import_node_url6, import_node_path22, NODE_NAME_MAX_LENGTH;
|
|
245588
246188
|
var init_routes7 = __esm({
|
|
245589
246189
|
"../server/src/domains/nodes/routes.ts"() {
|
|
245590
246190
|
"use strict";
|
|
245591
246191
|
init_src();
|
|
245592
246192
|
init_faults();
|
|
245593
246193
|
init_runtime_status();
|
|
245594
|
-
|
|
246194
|
+
import_node_crypto63 = require("node:crypto");
|
|
245595
246195
|
import_node_fs18 = require("node:fs");
|
|
245596
246196
|
import_node_url6 = require("node:url");
|
|
245597
246197
|
import_node_path22 = require("node:path");
|
|
@@ -247258,7 +247858,7 @@ function createBundle(root, target, input) {
|
|
|
247258
247858
|
}
|
|
247259
247859
|
}
|
|
247260
247860
|
const bytes2 = fs29.statSync(absBundle).size;
|
|
247261
|
-
const digest = (0,
|
|
247861
|
+
const digest = (0, import_node_crypto64.createHash)("sha256").update(fs29.readFileSync(absBundle)).digest("hex");
|
|
247262
247862
|
const relBase = `inputs/git-bundles/${safeRepo}-${commit.slice(0, 12)}`;
|
|
247263
247863
|
return {
|
|
247264
247864
|
absoluteBundlePath: absBundle,
|
|
@@ -247354,12 +247954,12 @@ function classifyGitError(fallback, err, where) {
|
|
|
247354
247954
|
function oneLine2(msg) {
|
|
247355
247955
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
247356
247956
|
}
|
|
247357
|
-
var import_node_child_process17,
|
|
247957
|
+
var import_node_child_process17, import_node_crypto64, fs29, os8, path26, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
247358
247958
|
var init_readonly_bundle = __esm({
|
|
247359
247959
|
"../server/src/git/readonly-bundle.ts"() {
|
|
247360
247960
|
"use strict";
|
|
247361
247961
|
import_node_child_process17 = require("node:child_process");
|
|
247362
|
-
|
|
247962
|
+
import_node_crypto64 = require("node:crypto");
|
|
247363
247963
|
fs29 = __toESM(require("node:fs"), 1);
|
|
247364
247964
|
os8 = __toESM(require("node:os"), 1);
|
|
247365
247965
|
path26 = __toESM(require("node:path"), 1);
|
|
@@ -247380,7 +247980,7 @@ var init_readonly_bundle = __esm({
|
|
|
247380
247980
|
// ../server/src/domains/collab/create-seeded-workorder.ts
|
|
247381
247981
|
function makeSeededWorkorderCreator(deps) {
|
|
247382
247982
|
const locks = createKeyedMutex();
|
|
247383
|
-
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0,
|
|
247983
|
+
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto65.randomUUID)().slice(0, 8)}`);
|
|
247384
247984
|
const create = async (input) => {
|
|
247385
247985
|
const company = input.companyId && deps.resolveCompany ? await deps.resolveCompany(input.companyId) : void 0;
|
|
247386
247986
|
const kernel = company?.kernel ?? deps.kernel;
|
|
@@ -247467,7 +248067,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
247467
248067
|
return await finishCreation({ workspace, rootArtifactId: planned.rootArtifactId, spawned: planned.spawned });
|
|
247468
248068
|
};
|
|
247469
248069
|
return async (input) => {
|
|
247470
|
-
const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0,
|
|
248070
|
+
const release = await locks.acquire(`${input.companyId ?? ""}\0${input.idempotencyKey ?? (0, import_node_crypto65.randomUUID)()}`);
|
|
247471
248071
|
try {
|
|
247472
248072
|
return await create(input);
|
|
247473
248073
|
} finally {
|
|
@@ -247476,7 +248076,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
247476
248076
|
};
|
|
247477
248077
|
}
|
|
247478
248078
|
function workspaceForKey(key2) {
|
|
247479
|
-
return `ws:wo-${(0,
|
|
248079
|
+
return `ws:wo-${(0, import_node_crypto65.createHash)("sha256").update(key2).digest("hex").slice(0, 8)}`;
|
|
247480
248080
|
}
|
|
247481
248081
|
function existingWorkorder(snapshot, workspace, actor) {
|
|
247482
248082
|
if (!snapshot?.nodes.length) return null;
|
|
@@ -247488,11 +248088,11 @@ function existingWorkorder(snapshot, workspace, actor) {
|
|
|
247488
248088
|
spawned: snapshot.nodes.map((node2) => ({ id: node2.id, type: node2.type, owner: node2.assigneeActorId ?? actor }))
|
|
247489
248089
|
};
|
|
247490
248090
|
}
|
|
247491
|
-
var
|
|
248091
|
+
var import_node_crypto65;
|
|
247492
248092
|
var init_create_seeded_workorder = __esm({
|
|
247493
248093
|
"../server/src/domains/collab/create-seeded-workorder.ts"() {
|
|
247494
248094
|
"use strict";
|
|
247495
|
-
|
|
248095
|
+
import_node_crypto65 = require("node:crypto");
|
|
247496
248096
|
init_uncategorized_project();
|
|
247497
248097
|
init_src();
|
|
247498
248098
|
init_planner();
|
|
@@ -247718,8 +248318,16 @@ var init_service8 = __esm({
|
|
|
247718
248318
|
errorCode: input.errorCode ?? null,
|
|
247719
248319
|
errorMessage: input.errorMessage ?? null,
|
|
247720
248320
|
usage: input.usage ?? null,
|
|
247721
|
-
|
|
247722
|
-
|
|
248321
|
+
// 模型那两格按取值优先级挑(上游诊断 ④),不是无条件「收尾值优先」:`input` 里可能只剩
|
|
248322
|
+
// 请求值(claude 一条 init 都没吐就退出、ACP `set_model` 被接受但运行时从没回报),
|
|
248323
|
+
// 而 run 行上可能已经由运行中检查点补上了运行时回报的**实际值**——请求值顶掉实际值,
|
|
248324
|
+
// 这一轮就永远记在一个没跑过的型号头上(PR #2213 评审阻断项 1)。同档以收尾值为准
|
|
248325
|
+
// (`replace`):收尾只写一次,且它是这一轮解析链的最终结论。
|
|
248326
|
+
...preferRunModel(
|
|
248327
|
+
{ effectiveModel: run.effectiveModel, modelSource: run.modelSource },
|
|
248328
|
+
{ effectiveModel: input.effectiveModel, modelSource: input.modelSource },
|
|
248329
|
+
"replace"
|
|
248330
|
+
) ?? { effectiveModel: run.effectiveModel ?? null, modelSource: run.modelSource ?? null },
|
|
247723
248331
|
transcriptRef: input.transcriptRef ?? null
|
|
247724
248332
|
};
|
|
247725
248333
|
const updated = await this.store.updateRun(id, patch);
|
|
@@ -248995,12 +249603,12 @@ function stateFromAttempt(attempt, handoff, checkpoint, now, stalledAfterMs, ope
|
|
|
248995
249603
|
if (attempt.status === "no-output") return handoff?.unresolvedIssues.length ? "blocked" : "no_change";
|
|
248996
249604
|
return "failed";
|
|
248997
249605
|
}
|
|
248998
|
-
var
|
|
249606
|
+
var import_node_crypto66, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
|
|
248999
249607
|
var init_service9 = __esm({
|
|
249000
249608
|
"../server/src/domains/execution-continuity/service.ts"() {
|
|
249001
249609
|
"use strict";
|
|
249002
249610
|
init_src();
|
|
249003
|
-
|
|
249611
|
+
import_node_crypto66 = require("node:crypto");
|
|
249004
249612
|
init_src7();
|
|
249005
249613
|
BLOCKING_STATES = /* @__PURE__ */ new Set(["stalled", "failed", "blocked"]);
|
|
249006
249614
|
HANDOFF_OUTCOMES2 = /* @__PURE__ */ new Set(["succeeded", "no-output", "failed", "cancelled", "timeout", "orphaned"]);
|
|
@@ -249231,7 +249839,7 @@ var init_service9 = __esm({
|
|
|
249231
249839
|
if (typeof expectedHash !== "string" || !this.readBundleFile) return null;
|
|
249232
249840
|
const injectedResume = this.readBundleFile(attempt.id, "execution/RESUME.md");
|
|
249233
249841
|
if (!injectedResume) return null;
|
|
249234
|
-
const actualHash = (0,
|
|
249842
|
+
const actualHash = (0, import_node_crypto66.createHash)("sha256").update(injectedResume).digest("hex");
|
|
249235
249843
|
if (actualHash !== expectedHash) return null;
|
|
249236
249844
|
const recoverySnapshot = parseResumePackSnapshot(injectedResume);
|
|
249237
249845
|
if (!recoverySnapshot || recoverySnapshot.scenario !== "redispatch" || !recoverySnapshot.previousAttempt || recoverySnapshot.node.nodeId !== attempt.nodeId || recoverySnapshot.jobKey !== attempt.jobKey || recoverySnapshot.part !== attempt.part) return null;
|
|
@@ -250413,7 +251021,7 @@ function createChatSessionsDomain(opts) {
|
|
|
250413
251021
|
if (!text7.trim()) throw new ApiError(400, "BAD_REQUEST", "text required");
|
|
250414
251022
|
const now = Date.now();
|
|
250415
251023
|
sweepDrafts(now);
|
|
250416
|
-
const id = `cd_${(0,
|
|
251024
|
+
const id = `cd_${(0, import_node_crypto67.randomUUID)()}`;
|
|
250417
251025
|
drafts.set(id, { text: text7, actor: req.auth.actor, expiresAt: now + DRAFT_TTL_MS });
|
|
250418
251026
|
return { status: 201, body: { id, expiresInMs: DRAFT_TTL_MS } };
|
|
250419
251027
|
});
|
|
@@ -250490,7 +251098,7 @@ function createChatSessionsDomain(opts) {
|
|
|
250490
251098
|
const runtimeId = agentDefault.binding?.nodeId ?? "unknown";
|
|
250491
251099
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
250492
251100
|
const session = {
|
|
250493
|
-
id: (0,
|
|
251101
|
+
id: (0, import_node_crypto67.randomUUID)(),
|
|
250494
251102
|
humanActorId: req.auth.actor,
|
|
250495
251103
|
// 注:这里**刻意不写 companyId**。新会话要不要带公司归属,按 ws:wo-6d588f8e 的 ADR
|
|
250496
251104
|
// (每公司 schema、最终移除表内 company 列)统一定,不在本节点自行发明。
|
|
@@ -250625,7 +251233,7 @@ function createChatSessionsDomain(opts) {
|
|
|
250625
251233
|
if (body2.role !== "user" && body2.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
|
|
250626
251234
|
const role = body2.role;
|
|
250627
251235
|
const msg = await store2.appendMessage({
|
|
250628
|
-
id: (0,
|
|
251236
|
+
id: (0, import_node_crypto67.randomUUID)(),
|
|
250629
251237
|
sessionId: req.params.id,
|
|
250630
251238
|
role,
|
|
250631
251239
|
content: role === "user" ? stripInjectedChatContext(body2.content) : body2.content,
|
|
@@ -250667,7 +251275,7 @@ function createChatSessionsDomain(opts) {
|
|
|
250667
251275
|
const known = key2 ? cur.find((x2) => x2.clientKey === key2) : void 0;
|
|
250668
251276
|
if (!known && cur.length >= QUEUE_MAX) throw new ApiError(409, "QUEUE_FULL", `\u961F\u5217\u5DF2\u6EE1\uFF08\u4E0A\u9650 ${QUEUE_MAX} \u6761\uFF09`);
|
|
250669
251277
|
const item = await store2.enqueuePendingMessage({
|
|
250670
|
-
id: (0,
|
|
251278
|
+
id: (0, import_node_crypto67.randomUUID)(),
|
|
250671
251279
|
chatSessionId: sid,
|
|
250672
251280
|
text: text7,
|
|
250673
251281
|
...attachments.length ? { attachments } : {},
|
|
@@ -251520,12 +252128,12 @@ async function legacySendFailureCards(entries, deps) {
|
|
|
251520
252128
|
}
|
|
251521
252129
|
return out;
|
|
251522
252130
|
}
|
|
251523
|
-
var
|
|
252131
|
+
var import_node_crypto67, DEFAULT_SNAPSHOT_ITEMS, INFLIGHT_INSERT_SETTLE_WAIT_MS, MAX_SNAPSHOT_ITEMS, PROJECTED_CARD_LIMIT, SUBMISSION_NOT_DELIVERED_NOTE, SUBMISSION_UNCONFIRMED_NOTE, LEGACY_CARD_LIMIT;
|
|
251524
252132
|
var init_chat_sessions2 = __esm({
|
|
251525
252133
|
"../server/src/domains/chat-sessions/index.ts"() {
|
|
251526
252134
|
"use strict";
|
|
251527
252135
|
init_file_limits2();
|
|
251528
|
-
|
|
252136
|
+
import_node_crypto67 = require("node:crypto");
|
|
251529
252137
|
init_src();
|
|
251530
252138
|
init_chat_session();
|
|
251531
252139
|
init_persistent_files();
|
|
@@ -252985,7 +253593,7 @@ function busyError(chatSessionId, blockedBy) {
|
|
|
252985
253593
|
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`;
|
|
252986
253594
|
}
|
|
252987
253595
|
function genWebhookToken() {
|
|
252988
|
-
return `owt_${(0,
|
|
253596
|
+
return `owt_${(0, import_node_crypto68.randomBytes)(32).toString("base64url")}`;
|
|
252989
253597
|
}
|
|
252990
253598
|
function validateTitleTemplate(tpl) {
|
|
252991
253599
|
const residue = tpl.replace(DATE_TOKEN, "");
|
|
@@ -253041,11 +253649,11 @@ function appendSourceNote(brief, automation, source, atIso) {
|
|
|
253041
253649
|
---
|
|
253042
253650
|
\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`;
|
|
253043
253651
|
}
|
|
253044
|
-
var
|
|
253652
|
+
var import_node_crypto68, DATE_TOKEN, AutomationsService, EVENT_RETRY_BASE_MS, EVENT_RETRY_MAX_MS, EVENT_RETRY_MAX_ATTEMPTS, eventAttempts, eventLastAttemptAt, eventLastError, CHAT_REPLY_MAX;
|
|
253045
253653
|
var init_service10 = __esm({
|
|
253046
253654
|
"../server/src/domains/automations/service.ts"() {
|
|
253047
253655
|
"use strict";
|
|
253048
|
-
|
|
253656
|
+
import_node_crypto68 = require("node:crypto");
|
|
253049
253657
|
init_src();
|
|
253050
253658
|
init_registry3();
|
|
253051
253659
|
init_attribution();
|
|
@@ -253859,11 +254467,11 @@ function verifySignature(rawBody, headers, secret) {
|
|
|
253859
254467
|
if (!secret) return "not_required";
|
|
253860
254468
|
const given = header1(headers, "x-hub-signature-256");
|
|
253861
254469
|
if (!given) return "missing";
|
|
253862
|
-
const expected = `sha256=${(0,
|
|
254470
|
+
const expected = `sha256=${(0, import_node_crypto69.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
|
|
253863
254471
|
const a = Buffer.from(given);
|
|
253864
254472
|
const b2 = Buffer.from(expected);
|
|
253865
254473
|
if (a.length !== b2.length) return "invalid";
|
|
253866
|
-
return (0,
|
|
254474
|
+
return (0, import_node_crypto69.timingSafeEqual)(a, b2) ? "valid" : "invalid";
|
|
253867
254475
|
}
|
|
253868
254476
|
function eventAllowed(filters, envelope) {
|
|
253869
254477
|
if (!filters || filters.length === 0) return true;
|
|
@@ -253893,11 +254501,11 @@ function splitEvent(envelope) {
|
|
|
253893
254501
|
}
|
|
253894
254502
|
return { eventName, actionCandidates: candidates };
|
|
253895
254503
|
}
|
|
253896
|
-
var
|
|
254504
|
+
var import_node_crypto69, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
|
|
253897
254505
|
var init_webhook = __esm({
|
|
253898
254506
|
"../server/src/domains/automations/webhook.ts"() {
|
|
253899
254507
|
"use strict";
|
|
253900
|
-
|
|
254508
|
+
import_node_crypto69 = require("node:crypto");
|
|
253901
254509
|
MAX_BODY_BYTES = 256 * 1024;
|
|
253902
254510
|
AutomationWebhookService = class {
|
|
253903
254511
|
store;
|
|
@@ -255049,7 +255657,7 @@ function playbooksDomain(opts) {
|
|
|
255049
255657
|
opts.overrides.set(companyOf(req), ref2, nodeKey, nextOverride);
|
|
255050
255658
|
try {
|
|
255051
255659
|
await opts.audit?.({
|
|
255052
|
-
id: `reg_${(0,
|
|
255660
|
+
id: `reg_${(0, import_node_crypto70.randomUUID)()}`,
|
|
255053
255661
|
actor: req.auth.actor,
|
|
255054
255662
|
kind: "registry_change",
|
|
255055
255663
|
target: `playbook:${ref2}#${nodeKey}`,
|
|
@@ -255066,11 +255674,11 @@ function playbooksDomain(opts) {
|
|
|
255066
255674
|
});
|
|
255067
255675
|
};
|
|
255068
255676
|
}
|
|
255069
|
-
var
|
|
255677
|
+
var import_node_crypto70;
|
|
255070
255678
|
var init_routes12 = __esm({
|
|
255071
255679
|
"../server/src/domains/playbooks/routes.ts"() {
|
|
255072
255680
|
"use strict";
|
|
255073
|
-
|
|
255681
|
+
import_node_crypto70 = require("node:crypto");
|
|
255074
255682
|
init_router();
|
|
255075
255683
|
init_registry3();
|
|
255076
255684
|
init_planner();
|
|
@@ -255199,17 +255807,17 @@ function completionFingerprint(workspace, members) {
|
|
|
255199
255807
|
workspace,
|
|
255200
255808
|
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 }))
|
|
255201
255809
|
});
|
|
255202
|
-
return (0,
|
|
255810
|
+
return (0, import_node_crypto71.createHash)("sha256").update(canonical2).digest("hex");
|
|
255203
255811
|
}
|
|
255204
255812
|
function eventConsumptionKey(args) {
|
|
255205
255813
|
const raw = `project-event:${EVENT_KEY_VERSION}:${args.triggerId}:${args.event}:${args.workspace}:${args.fingerprint}`;
|
|
255206
|
-
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0,
|
|
255814
|
+
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0, import_node_crypto71.createHash)("sha256").update(raw).digest("hex")}`;
|
|
255207
255815
|
}
|
|
255208
|
-
var
|
|
255816
|
+
var import_node_crypto71, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
|
|
255209
255817
|
var init_project_event_poller = __esm({
|
|
255210
255818
|
"../server/src/automations/project-event-poller.ts"() {
|
|
255211
255819
|
"use strict";
|
|
255212
|
-
|
|
255820
|
+
import_node_crypto71 = require("node:crypto");
|
|
255213
255821
|
EVENT_KEY_VERSION = "v1";
|
|
255214
255822
|
EMPTY_METRICS = () => ({
|
|
255215
255823
|
scanDurationMs: 0,
|
|
@@ -255419,7 +256027,7 @@ function queryInputReceipt(hub, nodeId, dispatchId, clientMessageKey, pending, t
|
|
|
255419
256027
|
const viaSession = hub.hasSession?.(dispatchId) === true;
|
|
255420
256028
|
const supported = viaSession ? hub.supportsInputReceiptQuery?.(dispatchId) === true : daemonMetaOf(hub, nodeId)?.supportsInputReceiptQuery === true;
|
|
255421
256029
|
if (!supported) return Promise.resolve({ status: "unknown", reason: "unsupported" });
|
|
255422
|
-
const requestId = (0,
|
|
256030
|
+
const requestId = (0, import_node_crypto72.randomUUID)();
|
|
255423
256031
|
return new Promise((resolve12) => {
|
|
255424
256032
|
const timer = setTimeout(() => {
|
|
255425
256033
|
pending.delete(requestId);
|
|
@@ -255481,7 +256089,7 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
|
|
|
255481
256089
|
if (input.requireConsumptionReceipt && !hub.supportsInputConsumptionReceipts?.(dispatchId)) {
|
|
255482
256090
|
return Promise.resolve({ accepted: false, reason: "consumption-unsupported" });
|
|
255483
256091
|
}
|
|
255484
|
-
const requestId = (0,
|
|
256092
|
+
const requestId = (0, import_node_crypto72.randomUUID)();
|
|
255485
256093
|
const sent = routeToSession(hub, nodeId, dispatchId, { type: "append_input", dispatchId, input, requestId });
|
|
255486
256094
|
if (!sent) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
|
|
255487
256095
|
return new Promise((resolve12) => {
|
|
@@ -255494,11 +256102,11 @@ function sendAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs, sessi
|
|
|
255494
256102
|
entry.appendWaiters.push({ requestId, requireConsumptionReceipt: input.requireConsumptionReceipt, resolve: resolve12, timer });
|
|
255495
256103
|
});
|
|
255496
256104
|
}
|
|
255497
|
-
var
|
|
256105
|
+
var import_node_crypto72, 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;
|
|
255498
256106
|
var init_daemon_adapter = __esm({
|
|
255499
256107
|
"../server/src/daemon-adapter.ts"() {
|
|
255500
256108
|
"use strict";
|
|
255501
|
-
|
|
256109
|
+
import_node_crypto72 = require("node:crypto");
|
|
255502
256110
|
init_src();
|
|
255503
256111
|
STASH_TTL_MS = 5 * 6e4;
|
|
255504
256112
|
STASH_MAX_FRAMES_PER_ID = 1e4;
|
|
@@ -255938,7 +256546,7 @@ var init_daemon_adapter = __esm({
|
|
|
255938
256546
|
async spawn(job) {
|
|
255939
256547
|
const nodeId = job.binding?.nodeId;
|
|
255940
256548
|
if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
|
|
255941
|
-
const dispatchId = job.dispatchId ?? `dispatch:${(0,
|
|
256549
|
+
const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto72.randomUUID)()}`;
|
|
255942
256550
|
if (job.dispatchId && this.pending.has(dispatchId)) {
|
|
255943
256551
|
return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
255944
256552
|
}
|
|
@@ -256194,7 +256802,7 @@ var init_daemon_adapter = __esm({
|
|
|
256194
256802
|
return daemon?.meta.supportsWorkdirWalk === true;
|
|
256195
256803
|
}
|
|
256196
256804
|
request(nodeId, buildFrame) {
|
|
256197
|
-
const requestId = (0,
|
|
256805
|
+
const requestId = (0, import_node_crypto72.randomUUID)();
|
|
256198
256806
|
const sent = this.hub.dispatch(nodeId, buildFrame(requestId));
|
|
256199
256807
|
if (!sent) return Promise.resolve({ ok: false, code: "NODE_OFFLINE" });
|
|
256200
256808
|
return new Promise((resolve12) => {
|
|
@@ -256302,13 +256910,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
256302
256910
|
if (sha(body2) === lastPushedHash) return { kind: "echo" };
|
|
256303
256911
|
return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
|
|
256304
256912
|
}
|
|
256305
|
-
var
|
|
256913
|
+
var import_node_crypto73, sha, enc2, dec, MirrorEngine, MemoryMirrorStateStore, MapMirrorIdentities;
|
|
256306
256914
|
var init_engine = __esm({
|
|
256307
256915
|
"../server/src/mirror/engine.ts"() {
|
|
256308
256916
|
"use strict";
|
|
256309
|
-
|
|
256917
|
+
import_node_crypto73 = require("node:crypto");
|
|
256310
256918
|
init_src();
|
|
256311
|
-
sha = (s2) => (0,
|
|
256919
|
+
sha = (s2) => (0, import_node_crypto73.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
256312
256920
|
enc2 = (s2) => new TextEncoder().encode(s2);
|
|
256313
256921
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
256314
256922
|
MirrorEngine = class {
|
|
@@ -256589,11 +257197,11 @@ function humanExitCause(exit3) {
|
|
|
256589
257197
|
const base = (exit3.reason ? label2[exit3.reason] : void 0) ?? `\u4F1A\u8BDD\u5F02\u5E38\u7ED3\u675F\uFF08${exit3.reason ?? "\u65E0\u9000\u51FA\u4FE1\u606F"}\uFF09`;
|
|
256590
257198
|
return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
|
|
256591
257199
|
}
|
|
256592
|
-
var
|
|
257200
|
+
var import_node_crypto74, 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;
|
|
256593
257201
|
var init_worker = __esm({
|
|
256594
257202
|
"../server/src/coordinator/worker.ts"() {
|
|
256595
257203
|
"use strict";
|
|
256596
|
-
|
|
257204
|
+
import_node_crypto74 = require("node:crypto");
|
|
256597
257205
|
init_src7();
|
|
256598
257206
|
init_identity();
|
|
256599
257207
|
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
|
|
@@ -256863,7 +257471,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
256863
257471
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
256864
257472
|
}
|
|
256865
257473
|
evaluationKey(kind, artifactId, evidence) {
|
|
256866
|
-
const fingerprint2 = (0,
|
|
257474
|
+
const fingerprint2 = (0, import_node_crypto74.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
256867
257475
|
return `${kind}:${artifactId}:${fingerprint2}`;
|
|
256868
257476
|
}
|
|
256869
257477
|
artifactEvidence(id) {
|
|
@@ -257252,8 +257860,8 @@ ${ctx.nodeFault}
|
|
|
257252
257860
|
const taskWithRejections = rejectedSection ? `${task}
|
|
257253
257861
|
|
|
257254
257862
|
${rejectedSection}` : task;
|
|
257255
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
257256
|
-
const coordinatorRunId = `coordinate:${(0,
|
|
257863
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto74.randomUUID)();
|
|
257864
|
+
const coordinatorRunId = `coordinate:${(0, import_node_crypto74.randomUUID)()}`;
|
|
257257
257865
|
const taskWithContext = coordinatorContext ? [
|
|
257258
257866
|
taskWithRejections,
|
|
257259
257867
|
``,
|
|
@@ -257297,7 +257905,7 @@ ${rejectedSection}` : task;
|
|
|
257297
257905
|
const startedAtMs = Date.now();
|
|
257298
257906
|
let trajectoryStarted = false;
|
|
257299
257907
|
if (this.deps.trajectory) {
|
|
257300
|
-
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0,
|
|
257908
|
+
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto74.createHash)("sha256").update(content3).digest("hex")]));
|
|
257301
257909
|
const session = {
|
|
257302
257910
|
runId: coordinatorRunId,
|
|
257303
257911
|
runtimeSessionId,
|
|
@@ -257508,11 +258116,11 @@ var init_pg_ident = __esm({
|
|
|
257508
258116
|
});
|
|
257509
258117
|
|
|
257510
258118
|
// ../storage/src/postgres.ts
|
|
257511
|
-
var
|
|
258119
|
+
var import_node_crypto75, ident4, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
|
|
257512
258120
|
var init_postgres = __esm({
|
|
257513
258121
|
"../storage/src/postgres.ts"() {
|
|
257514
258122
|
"use strict";
|
|
257515
|
-
|
|
258123
|
+
import_node_crypto75 = require("node:crypto");
|
|
257516
258124
|
init_pg_ident();
|
|
257517
258125
|
init_esm();
|
|
257518
258126
|
init_src();
|
|
@@ -257692,7 +258300,7 @@ var init_postgres = __esm({
|
|
|
257692
258300
|
return new _PostgresBlobStore(pool, schema);
|
|
257693
258301
|
}
|
|
257694
258302
|
async put(bytes2) {
|
|
257695
|
-
const hash3 = (0,
|
|
258303
|
+
const hash3 = (0, import_node_crypto75.createHash)("sha256").update(bytes2).digest("hex");
|
|
257696
258304
|
await this.pool.query(
|
|
257697
258305
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
257698
258306
|
[hash3, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
|
|
@@ -257740,7 +258348,7 @@ function stageAtLeast(stage, min2) {
|
|
|
257740
258348
|
return STAGES.indexOf(stage) >= STAGES.indexOf(min2);
|
|
257741
258349
|
}
|
|
257742
258350
|
function newVariableId() {
|
|
257743
|
-
return `var_${(0,
|
|
258351
|
+
return `var_${(0, import_node_crypto76.randomUUID)()}`;
|
|
257744
258352
|
}
|
|
257745
258353
|
async function declareRecordsAware(db) {
|
|
257746
258354
|
await db.query(`SELECT set_config('${RECORDS_AWARE_SETTING}', 'on', true)`);
|
|
@@ -258096,11 +258704,11 @@ async function listBindingTargetIds(db, s2, kind) {
|
|
|
258096
258704
|
[kind]
|
|
258097
258705
|
)).rows.map((x2) => x2.target_id);
|
|
258098
258706
|
}
|
|
258099
|
-
var
|
|
258707
|
+
var import_node_crypto76, STAGES, RECORDS_AWARE_SETTING, markLockName;
|
|
258100
258708
|
var init_variable_bindings = __esm({
|
|
258101
258709
|
"../storage/src/variable-bindings.ts"() {
|
|
258102
258710
|
"use strict";
|
|
258103
|
-
|
|
258711
|
+
import_node_crypto76 = require("node:crypto");
|
|
258104
258712
|
init_src();
|
|
258105
258713
|
STAGES = ["off", "dual", "read", "records"];
|
|
258106
258714
|
RECORDS_AWARE_SETTING = "oasis.variable_records_aware";
|
|
@@ -268162,11 +268770,11 @@ var init_postgres_delegations = __esm({
|
|
|
268162
268770
|
});
|
|
268163
268771
|
|
|
268164
268772
|
// ../storage/src/postgres-nodes.ts
|
|
268165
|
-
var
|
|
268773
|
+
var import_node_crypto77, ident13, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToFault, rowToQuota, rowToRuntime;
|
|
268166
268774
|
var init_postgres_nodes = __esm({
|
|
268167
268775
|
"../storage/src/postgres-nodes.ts"() {
|
|
268168
268776
|
"use strict";
|
|
268169
|
-
|
|
268777
|
+
import_node_crypto77 = require("node:crypto");
|
|
268170
268778
|
init_pg_ident();
|
|
268171
268779
|
init_esm();
|
|
268172
268780
|
ident13 = (s2) => {
|
|
@@ -268516,7 +269124,7 @@ var init_postgres_nodes = __esm({
|
|
|
268516
269124
|
return store;
|
|
268517
269125
|
}
|
|
268518
269126
|
issue(nodeId) {
|
|
268519
|
-
const token = `ont_${(0,
|
|
269127
|
+
const token = `ont_${(0, import_node_crypto77.randomBytes)(24).toString("base64url")}`;
|
|
268520
269128
|
this.cache.set(token, nodeId);
|
|
268521
269129
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
268522
269130
|
return token;
|
|
@@ -268818,11 +269426,11 @@ var init_postgres_type_registry = __esm({
|
|
|
268818
269426
|
});
|
|
268819
269427
|
|
|
268820
269428
|
// ../storage/src/postgres-actor-memory.ts
|
|
268821
|
-
var
|
|
269429
|
+
var import_node_crypto78, matchClause, ident15, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
|
|
268822
269430
|
var init_postgres_actor_memory = __esm({
|
|
268823
269431
|
"../storage/src/postgres-actor-memory.ts"() {
|
|
268824
269432
|
"use strict";
|
|
268825
|
-
|
|
269433
|
+
import_node_crypto78 = require("node:crypto");
|
|
268826
269434
|
init_pg_ident();
|
|
268827
269435
|
init_src();
|
|
268828
269436
|
matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
|
|
@@ -269032,7 +269640,7 @@ var init_postgres_actor_memory = __esm({
|
|
|
269032
269640
|
}
|
|
269033
269641
|
async write(input, now) {
|
|
269034
269642
|
if (input.memId === void 0) {
|
|
269035
|
-
const memId = `mem:${(0,
|
|
269643
|
+
const memId = `mem:${(0, import_node_crypto78.randomUUID)()}`;
|
|
269036
269644
|
const r2 = await this.pool.query(
|
|
269037
269645
|
`INSERT INTO ${this.s}.actor_memories
|
|
269038
269646
|
(mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
|
|
@@ -270603,14 +271211,14 @@ function companySchemaName(companyId) {
|
|
|
270603
271211
|
if (typeof companyId !== "string" || !companyId.trim()) {
|
|
270604
271212
|
throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
|
|
270605
271213
|
}
|
|
270606
|
-
const hex = (0,
|
|
271214
|
+
const hex = (0, import_node_crypto79.createHash)("sha256").update(companyId, "utf8").digest("hex");
|
|
270607
271215
|
return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
|
|
270608
271216
|
}
|
|
270609
|
-
var
|
|
271217
|
+
var import_node_crypto79, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
|
|
270610
271218
|
var init_tenant_schema_mapping = __esm({
|
|
270611
271219
|
"../storage/src/tenant-schema-mapping.ts"() {
|
|
270612
271220
|
"use strict";
|
|
270613
|
-
|
|
271221
|
+
import_node_crypto79 = require("node:crypto");
|
|
270614
271222
|
init_esm();
|
|
270615
271223
|
init_pg_ident();
|
|
270616
271224
|
COMPANY_SCHEMA_PREFIX = "c_";
|
|
@@ -270684,7 +271292,7 @@ var init_tenant_schema_mapping = __esm({
|
|
|
270684
271292
|
|
|
270685
271293
|
// ../storage/src/company-data-plane-schema.ts
|
|
270686
271294
|
function canonicalTypeDefHash(def) {
|
|
270687
|
-
return `sha256:${(0,
|
|
271295
|
+
return `sha256:${(0, import_node_crypto80.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
|
|
270688
271296
|
}
|
|
270689
271297
|
function defaultArtifactTypeTemplate() {
|
|
270690
271298
|
return [
|
|
@@ -270866,11 +271474,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
|
|
|
270866
271474
|
}
|
|
270867
271475
|
return { inserted };
|
|
270868
271476
|
}
|
|
270869
|
-
var
|
|
271477
|
+
var import_node_crypto80, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
|
|
270870
271478
|
var init_company_data_plane_schema = __esm({
|
|
270871
271479
|
"../storage/src/company-data-plane-schema.ts"() {
|
|
270872
271480
|
"use strict";
|
|
270873
|
-
|
|
271481
|
+
import_node_crypto80 = require("node:crypto");
|
|
270874
271482
|
init_esm();
|
|
270875
271483
|
init_pg_ident();
|
|
270876
271484
|
DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
|
|
@@ -270949,11 +271557,11 @@ function rowToFile2(row) {
|
|
|
270949
271557
|
updatedAt: new Date(row.updated_at).toISOString()
|
|
270950
271558
|
};
|
|
270951
271559
|
}
|
|
270952
|
-
var
|
|
271560
|
+
var import_node_crypto81, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
|
|
270953
271561
|
var init_company_owned_registry_store = __esm({
|
|
270954
271562
|
"../storage/src/company-owned-registry-store.ts"() {
|
|
270955
271563
|
"use strict";
|
|
270956
|
-
|
|
271564
|
+
import_node_crypto81 = require("node:crypto");
|
|
270957
271565
|
init_esm();
|
|
270958
271566
|
init_src();
|
|
270959
271567
|
init_pg_ident();
|
|
@@ -271338,7 +271946,7 @@ var init_company_owned_registry_store = __esm({
|
|
|
271338
271946
|
enabled: skill.enabled,
|
|
271339
271947
|
files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
|
|
271340
271948
|
});
|
|
271341
|
-
return (0,
|
|
271949
|
+
return (0, import_node_crypto81.createHash)("sha256").update(body2).digest("hex");
|
|
271342
271950
|
}
|
|
271343
271951
|
};
|
|
271344
271952
|
}
|
|
@@ -274148,7 +274756,7 @@ function sourceSetConservation(input) {
|
|
|
274148
274756
|
return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
|
|
274149
274757
|
}
|
|
274150
274758
|
function payloadChecksum(value2) {
|
|
274151
|
-
return (0,
|
|
274759
|
+
return (0, import_node_crypto82.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
274152
274760
|
}
|
|
274153
274761
|
async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
|
|
274154
274762
|
const cs = quoteIdent2(companySchema);
|
|
@@ -274540,11 +275148,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
|
|
|
274540
275148
|
sequences
|
|
274541
275149
|
};
|
|
274542
275150
|
}
|
|
274543
|
-
var
|
|
275151
|
+
var import_node_crypto82, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
|
|
274544
275152
|
var init_tenant_migration_operator = __esm({
|
|
274545
275153
|
"../storage/src/tenant-migration-operator.ts"() {
|
|
274546
275154
|
"use strict";
|
|
274547
|
-
|
|
275155
|
+
import_node_crypto82 = require("node:crypto");
|
|
274548
275156
|
init_esm();
|
|
274549
275157
|
init_pg_ident();
|
|
274550
275158
|
init_tenancy_attribution();
|
|
@@ -274780,8 +275388,8 @@ var init_tenant_new_company_provision = __esm({
|
|
|
274780
275388
|
// ../storage/src/knowledge-snapshot-crypto.ts
|
|
274781
275389
|
function sealSnapshot(snapshot, key2) {
|
|
274782
275390
|
if (snapshot.content.startsWith(PREFIX3)) return structuredClone(snapshot);
|
|
274783
|
-
const iv = (0,
|
|
274784
|
-
const cipher = (0,
|
|
275391
|
+
const iv = (0, import_node_crypto83.randomBytes)(12);
|
|
275392
|
+
const cipher = (0, import_node_crypto83.createCipheriv)("aes-256-gcm", bytes(key2), iv);
|
|
274785
275393
|
cipher.setAAD(aad2(snapshot));
|
|
274786
275394
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
274787
275395
|
return { ...structuredClone(snapshot), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
|
|
@@ -274791,7 +275399,7 @@ function openSnapshot(snapshot, key2) {
|
|
|
274791
275399
|
const packed = snapshot.content.slice(PREFIX3.length).split(".");
|
|
274792
275400
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
274793
275401
|
const [iv, tag, data] = packed;
|
|
274794
|
-
const decipher = (0,
|
|
275402
|
+
const decipher = (0, import_node_crypto83.createDecipheriv)("aes-256-gcm", bytes(key2), Buffer.from(iv, "base64url"));
|
|
274795
275403
|
decipher.setAAD(aad2(snapshot));
|
|
274796
275404
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
274797
275405
|
return {
|
|
@@ -274799,11 +275407,11 @@ function openSnapshot(snapshot, key2) {
|
|
|
274799
275407
|
content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
|
|
274800
275408
|
};
|
|
274801
275409
|
}
|
|
274802
|
-
var
|
|
275410
|
+
var import_node_crypto83, PREFIX3, bytes, aad2;
|
|
274803
275411
|
var init_knowledge_snapshot_crypto = __esm({
|
|
274804
275412
|
"../storage/src/knowledge-snapshot-crypto.ts"() {
|
|
274805
275413
|
"use strict";
|
|
274806
|
-
|
|
275414
|
+
import_node_crypto83 = require("node:crypto");
|
|
274807
275415
|
PREFIX3 = "oasis-knowledge:v1:";
|
|
274808
275416
|
bytes = (key2) => {
|
|
274809
275417
|
const value2 = Buffer.from(key2);
|
|
@@ -275695,7 +276303,7 @@ function reportedCost(v2) {
|
|
|
275695
276303
|
}
|
|
275696
276304
|
function newUsageBackfillManifestId(now = /* @__PURE__ */ new Date()) {
|
|
275697
276305
|
const stamp = now.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
|
|
275698
|
-
return `ulb-${stamp}-${(0,
|
|
276306
|
+
return `ulb-${stamp}-${(0, import_node_crypto84.randomBytes)(3).toString("hex")}`;
|
|
275699
276307
|
}
|
|
275700
276308
|
async function backfillUsageLedger(ledger, opts) {
|
|
275701
276309
|
if (!opts.dryRun && !opts.manifestId) throw new Error("execute \u9700\u8981 manifestId");
|
|
@@ -276244,11 +276852,11 @@ async function audit(c, s2, manifestId, runId, field, before, after, createdAt)
|
|
|
276244
276852
|
[manifestId, runId, field, before == null ? null : JSON.stringify(before), after == null ? null : JSON.stringify(after), createdAt]
|
|
276245
276853
|
);
|
|
276246
276854
|
}
|
|
276247
|
-
var
|
|
276855
|
+
var import_node_crypto84, BUCKETS, ENDED_SQL, START_EVIDENCE_SQL, CHAT_RUN_SQL, ALLOWED_MODEL_EVIDENCE_TIERS, emptyStep, MODEL_BACKFILL_SOURCE, fourOf, sameUsage, ChatRunLookup;
|
|
276248
276856
|
var init_usage_ledger_backfill = __esm({
|
|
276249
276857
|
"../storage/src/usage-ledger-backfill.ts"() {
|
|
276250
276858
|
"use strict";
|
|
276251
|
-
|
|
276859
|
+
import_node_crypto84 = require("node:crypto");
|
|
276252
276860
|
init_src();
|
|
276253
276861
|
init_pg_ident();
|
|
276254
276862
|
init_postgres_trace();
|
|
@@ -276827,31 +277435,64 @@ var init_connector_tool_versions = __esm({
|
|
|
276827
277435
|
});
|
|
276828
277436
|
|
|
276829
277437
|
// ../server/src/design/board-watch.ts
|
|
276830
|
-
function
|
|
276831
|
-
if (
|
|
276832
|
-
if (
|
|
276833
|
-
|
|
276834
|
-
if (
|
|
276835
|
-
|
|
276836
|
-
|
|
276837
|
-
|
|
276838
|
-
|
|
277438
|
+
function parseOdTime(v2) {
|
|
277439
|
+
if (typeof v2 === "number") return Number.isFinite(v2) ? v2 : null;
|
|
277440
|
+
if (typeof v2 !== "string" || v2.trim().length === 0) return null;
|
|
277441
|
+
const s2 = v2.trim();
|
|
277442
|
+
if (/^\d+(\.\d+)?$/.test(s2)) return Number(s2);
|
|
277443
|
+
const t = Date.parse(s2);
|
|
277444
|
+
return Number.isFinite(t) ? t : null;
|
|
277445
|
+
}
|
|
277446
|
+
function nonEmpty2(v2) {
|
|
277447
|
+
return typeof v2 === "string" && v2.trim().length > 0 ? v2 : null;
|
|
276839
277448
|
}
|
|
276840
|
-
|
|
277449
|
+
function roundOfMessage(m2, conversationId = null) {
|
|
277450
|
+
if (m2["role"] !== "assistant") return null;
|
|
277451
|
+
const status = nonEmpty2(m2["runStatus"]);
|
|
277452
|
+
if (status === null || !TERMINAL_RUN_STATUS.has(status)) return null;
|
|
277453
|
+
const endedAt = parseOdTime(m2["endedAt"]);
|
|
277454
|
+
if (endedAt === null) return null;
|
|
277455
|
+
const runId = nonEmpty2(m2["runId"]);
|
|
277456
|
+
const messageId = nonEmpty2(m2["id"]);
|
|
277457
|
+
if (runId === null && messageId === null) return null;
|
|
277458
|
+
const files = Array.isArray(m2["producedFiles"]) ? m2["producedFiles"] : [];
|
|
277459
|
+
const producedFiles = files.map((f2) => typeof f2 === "string" ? f2 : f2 && typeof f2 === "object" ? nonEmpty2(f2["path"]) ?? nonEmpty2(f2["name"]) : null).filter((s2) => s2 !== null);
|
|
277460
|
+
const { error: error2, errorCode } = messageError(m2, status);
|
|
277461
|
+
return {
|
|
277462
|
+
key: runId ?? `msg:${messageId}`,
|
|
277463
|
+
conversationId,
|
|
277464
|
+
runId,
|
|
277465
|
+
status,
|
|
277466
|
+
agentId: nonEmpty2(m2["agentId"]),
|
|
277467
|
+
endedAt,
|
|
277468
|
+
producedFiles,
|
|
277469
|
+
error: error2,
|
|
277470
|
+
errorCode
|
|
277471
|
+
};
|
|
277472
|
+
}
|
|
277473
|
+
function messageError(m2, status) {
|
|
277474
|
+
const events = Array.isArray(m2["events"]) ? m2["events"] : [];
|
|
277475
|
+
for (let i = events.length - 1; i >= 0; i--) {
|
|
277476
|
+
const e = events[i];
|
|
277477
|
+
if (!e || typeof e !== "object") continue;
|
|
277478
|
+
const ev = e;
|
|
277479
|
+
if (ev["kind"] !== "status" || ev["label"] !== "error") continue;
|
|
277480
|
+
const detail = nonEmpty2(ev["detail"]);
|
|
277481
|
+
if (detail !== null) return { error: detail, errorCode: nonEmpty2(ev["code"]) };
|
|
277482
|
+
}
|
|
277483
|
+
if (status !== "succeeded") {
|
|
277484
|
+
const content3 = nonEmpty2(m2["content"]);
|
|
277485
|
+
if (content3 !== null) return { error: content3, errorCode: null };
|
|
277486
|
+
}
|
|
277487
|
+
return { error: null, errorCode: null };
|
|
277488
|
+
}
|
|
277489
|
+
var RUN_MARKER_PREFIX, boardWatchRunMarker, parseRunMarker, SINCE_MARKER_PREFIX, boardWatchSinceMarker, parseSinceMarker, TERMINAL_RUN_STATUS, MAX_REASON_CHARS, MAX_LISTED_FILES, BoardWatcher;
|
|
276841
277490
|
var init_board_watch = __esm({
|
|
276842
277491
|
"../server/src/design/board-watch.ts"() {
|
|
276843
277492
|
"use strict";
|
|
276844
277493
|
init_src7();
|
|
276845
|
-
MARKER_PREFIX = "[od-board-watch mtime:";
|
|
276846
|
-
boardWatchMarker = (mtimeMs) => `${MARKER_PREFIX}${mtimeMs}]`;
|
|
276847
|
-
parseMarker = (body2) => {
|
|
276848
|
-
const i = body2.indexOf(MARKER_PREFIX);
|
|
276849
|
-
if (i < 0) return null;
|
|
276850
|
-
const n = Number.parseInt(body2.slice(i + MARKER_PREFIX.length), 10);
|
|
276851
|
-
return Number.isFinite(n) ? n : null;
|
|
276852
|
-
};
|
|
276853
277494
|
RUN_MARKER_PREFIX = "[od-board-watch run:";
|
|
276854
|
-
boardWatchRunMarker = (
|
|
277495
|
+
boardWatchRunMarker = (roundKey) => `${RUN_MARKER_PREFIX}${roundKey}]`;
|
|
276855
277496
|
parseRunMarker = (body2) => {
|
|
276856
277497
|
const i = body2.indexOf(RUN_MARKER_PREFIX);
|
|
276857
277498
|
if (i < 0) return null;
|
|
@@ -276860,113 +277501,183 @@ var init_board_watch = __esm({
|
|
|
276860
277501
|
const id = body2.slice(i + RUN_MARKER_PREFIX.length, j);
|
|
276861
277502
|
return id.length > 0 ? id : null;
|
|
276862
277503
|
};
|
|
277504
|
+
SINCE_MARKER_PREFIX = "[od-board-watch since:";
|
|
277505
|
+
boardWatchSinceMarker = (sinceMs) => `${SINCE_MARKER_PREFIX}${sinceMs}]`;
|
|
277506
|
+
parseSinceMarker = (body2) => {
|
|
277507
|
+
const i = body2.indexOf(SINCE_MARKER_PREFIX);
|
|
277508
|
+
if (i < 0) return null;
|
|
277509
|
+
const n = Number.parseInt(body2.slice(i + SINCE_MARKER_PREFIX.length), 10);
|
|
277510
|
+
return Number.isFinite(n) ? n : null;
|
|
277511
|
+
};
|
|
276863
277512
|
TERMINAL_RUN_STATUS = /* @__PURE__ */ new Set(["succeeded", "failed", "canceled", "cancelled"]);
|
|
277513
|
+
MAX_REASON_CHARS = 500;
|
|
277514
|
+
MAX_LISTED_FILES = 10;
|
|
276864
277515
|
BoardWatcher = class {
|
|
276865
277516
|
constructor(deps) {
|
|
276866
277517
|
this.deps = deps;
|
|
276867
|
-
|
|
276868
|
-
|
|
277518
|
+
if (!deps.kernel && !(deps.listCompanies && deps.kernelFor)) throw new Error("BoardWatcher \u9700\u8981 kernel\uFF0C\u6216 listCompanies + kernelFor");
|
|
277519
|
+
}
|
|
277520
|
+
/** `<公司>\0<artifactId>` → 本进程第一次读成功时钉住的起算点(还没写过带 since 的信时用),免得在第一封信之前随时间往后漂。 */
|
|
277521
|
+
pinnedSince = /* @__PURE__ */ new Map();
|
|
277522
|
+
/** `<公司>\0<boardKey>\0<conversationId>` → 本进程上次把这个对话的轮次处理完时它的 updatedAt。 */
|
|
277523
|
+
seenConvAt = /* @__PURE__ */ new Map();
|
|
277524
|
+
/** 公司 → 上次记下的失败原文(同样的错只记一次;成功一轮就清掉)。 */
|
|
277525
|
+
companyLastError = /* @__PURE__ */ new Map();
|
|
277526
|
+
async odGet(path47) {
|
|
276869
277527
|
const fetchImpl = this.deps.fetchImpl ?? fetch;
|
|
276870
|
-
return fetchImpl(`${this.deps.odBase}${path47}`, this.deps.odToken ? { headers: { authorization: `Bearer ${this.deps.odToken}` } } : void 0);
|
|
276871
|
-
}
|
|
276872
|
-
/** 查一块板的交付物(排 task-context/、只算带 artifactManifest 的)。404/网络错 → null(板不存在)。 */
|
|
276873
|
-
async boardFiles(boardKey) {
|
|
276874
277528
|
try {
|
|
276875
|
-
const res = await this.
|
|
276876
|
-
if (
|
|
276877
|
-
|
|
276878
|
-
|
|
276879
|
-
|
|
276880
|
-
|
|
277529
|
+
const res = await fetchImpl(`${this.deps.odBase}${path47}`, this.deps.odToken ? { headers: { authorization: `Bearer ${this.deps.odToken}` } } : void 0);
|
|
277530
|
+
if (res.status === 401 || res.status === 403) return { kind: "denied", status: res.status };
|
|
277531
|
+
if (res.status === 404) return { kind: "missing" };
|
|
277532
|
+
if (!res.ok) return { kind: "error", detail: `HTTP ${res.status}` };
|
|
277533
|
+
return { kind: "ok", value: await res.json() };
|
|
277534
|
+
} catch (err) {
|
|
277535
|
+
return { kind: "error", detail: String(err) };
|
|
276881
277536
|
}
|
|
276882
277537
|
}
|
|
276883
277538
|
/**
|
|
276884
|
-
*
|
|
276885
|
-
*
|
|
276886
|
-
*
|
|
277539
|
+
* 列出一块板上结束时间可能晚于 since 的轮次(跨对话;顺序不重要,调用方按 endedAt 排)。
|
|
277540
|
+
*
|
|
277541
|
+
* 省流:od 的 assistant 消息带整段 events 与 content,每分钟把每个对话的 /messages 全拉一遍,轮次多的板
|
|
277542
|
+
* 一分钟就是几 MB。所以先用 /conversations 列表里的 updatedAt / latestRun.endedAt(取较大)筛:
|
|
277543
|
+
* - 不晚于 since → 这个对话里不可能有要写信的轮次,跳过;
|
|
277544
|
+
* - 和本进程上次看完时一样 → 没变,跳过(seenConvAt,serve 重启即清空,退回只按 since 筛,run marker 去重兜着)。
|
|
277545
|
+
* 两个时间都没有的对话照拉,不猜。返回每个拉过的对话的 updatedAt,由 tick 在它的轮次都写完信后记进 seenConvAt。
|
|
276887
277546
|
*/
|
|
276888
|
-
async
|
|
276889
|
-
|
|
276890
|
-
|
|
276891
|
-
|
|
276892
|
-
|
|
276893
|
-
|
|
276894
|
-
|
|
276895
|
-
|
|
276896
|
-
|
|
277547
|
+
async boardRounds(company, boardKey, since) {
|
|
277548
|
+
const base = `/api/projects/${encodeURIComponent(boardKey)}/conversations`;
|
|
277549
|
+
const convs = await this.odGet(base);
|
|
277550
|
+
if (convs.kind !== "ok") return convs;
|
|
277551
|
+
const rounds = [];
|
|
277552
|
+
const fetched = /* @__PURE__ */ new Map();
|
|
277553
|
+
for (const c of convs.value.conversations ?? []) {
|
|
277554
|
+
const cid = nonEmpty2(c["id"]);
|
|
277555
|
+
if (cid === null) continue;
|
|
277556
|
+
const latestRun = c["latestRun"] && typeof c["latestRun"] === "object" ? c["latestRun"] : {};
|
|
277557
|
+
const times = [parseOdTime(c["updatedAt"]), parseOdTime(latestRun["endedAt"])].filter((t) => t !== null);
|
|
277558
|
+
const convAt = times.length > 0 ? Math.max(...times) : null;
|
|
277559
|
+
if (convAt !== null && (convAt <= since || this.seenConvAt.get(`${company}\0${boardKey}\0${cid}`) === convAt)) continue;
|
|
277560
|
+
const msgs = await this.odGet(`${base}/${encodeURIComponent(cid)}/messages`);
|
|
277561
|
+
if (msgs.kind === "missing") continue;
|
|
277562
|
+
if (msgs.kind !== "ok") return msgs;
|
|
277563
|
+
fetched.set(cid, convAt);
|
|
277564
|
+
for (const m2 of msgs.value.messages ?? []) {
|
|
277565
|
+
if (!m2 || typeof m2 !== "object") continue;
|
|
277566
|
+
const r = roundOfMessage(m2, cid);
|
|
277567
|
+
if (r !== null) rounds.push(r);
|
|
277568
|
+
}
|
|
277569
|
+
}
|
|
277570
|
+
return { kind: "ok", value: { rounds, fetched } };
|
|
277571
|
+
}
|
|
277572
|
+
/** 失败轮消息上没有错误原文时,去 `/api/runs` 按 runId 找 od 记的 error;找不到(含 od 重启过)→ null。 */
|
|
277573
|
+
async runErrorFromRegistry(boardKey, runId) {
|
|
277574
|
+
const res = await this.odGet(`/api/runs?projectId=${encodeURIComponent(boardKey)}`);
|
|
277575
|
+
if (res.kind !== "ok") return null;
|
|
277576
|
+
const hit = (res.value.runs ?? []).find((r) => String(r["runId"] ?? r["id"] ?? "") === runId);
|
|
277577
|
+
return hit ? nonEmpty2(hit["error"]) : null;
|
|
276897
277578
|
}
|
|
276898
277579
|
async tick(now = Date.now()) {
|
|
276899
|
-
const {
|
|
276900
|
-
const
|
|
277580
|
+
const { log: log3 } = this.deps;
|
|
277581
|
+
const denied = [];
|
|
277582
|
+
const { listCompanies, kernelFor } = this.deps;
|
|
277583
|
+
if (listCompanies && kernelFor) {
|
|
277584
|
+
for (const companyId of await listCompanies()) {
|
|
277585
|
+
try {
|
|
277586
|
+
await this.tickCompany(companyId, await kernelFor(companyId), now, denied);
|
|
277587
|
+
this.companyLastError.delete(companyId);
|
|
277588
|
+
} catch (err) {
|
|
277589
|
+
const msg = String(err);
|
|
277590
|
+
if (this.companyLastError.get(companyId) === msg) continue;
|
|
277591
|
+
this.companyLastError.set(companyId, msg);
|
|
277592
|
+
log3?.(`[board-watch] [${companyId}] \u8FD9\u4E00\u8F6E\u6CA1\u5DE1\u6210\uFF08\u5176\u4F59\u516C\u53F8\u7EE7\u7EED\uFF09\uFF1A${msg}`);
|
|
277593
|
+
}
|
|
277594
|
+
}
|
|
277595
|
+
} else {
|
|
277596
|
+
await this.tickCompany("", this.deps.kernel, now, denied);
|
|
277597
|
+
}
|
|
277598
|
+
if (denied.length > 0) {
|
|
277599
|
+
const codes = [...new Set(denied.map((d) => d.status))].join("/");
|
|
277600
|
+
const eg = denied[0];
|
|
277601
|
+
log3?.(
|
|
277602
|
+
`[board-watch] od \u62D2\u7EDD\u4E86\u5DE1\u68C0\u8BF7\u6C42\uFF08HTTP ${codes}\uFF0C${denied.length} \u5757\u677F\uFF0C\u5982 ${eg.company ? `[${eg.company}] ` : ""}${eg.boardKey}\uFF09\uFF1A${this.deps.odToken ? "\u5E26\u4E86 OASIS_OPEN_DESIGN_TOKEN \u4F46 od \u4E0D\u8BA4\uFF0C\u6838\u5BF9\u5B83\u4E0E od \u7684 OD_API_TOKEN \u662F\u5426\u4E00\u81F4" : "\u6CA1\u914D OASIS_OPEN_DESIGN_TOKEN\uFF0Cod \u8981\u4EE4\u724C"}\u3002\u8FD9\u4E9B\u677F\u672C\u8F6E\u6CA1\u770B\u6210`
|
|
277603
|
+
);
|
|
277604
|
+
}
|
|
277605
|
+
}
|
|
277606
|
+
/** 巡一家公司(company 为空串 = 单 kernel 模式);被拒的板记进 denied,由 tick 统一汇总成一行。 */
|
|
277607
|
+
async tickCompany(company, kernel, now, denied) {
|
|
277608
|
+
const { boardKeyOf, log: log3 } = this.deps;
|
|
277609
|
+
const graceMs = this.deps.firstLookGraceMs ?? 10 * 6e4;
|
|
276901
277610
|
const maxPerTick = this.deps.maxLettersPerTick ?? 2;
|
|
276902
277611
|
const actor = this.deps.actor ?? "actor:system";
|
|
277612
|
+
const tag = company ? `[${company}] ` : "";
|
|
276903
277613
|
const model = kernel.model;
|
|
276904
277614
|
let written = 0;
|
|
276905
|
-
for (const a of model.artifacts.values()) {
|
|
276906
|
-
if (a.type !== "design") continue;
|
|
276907
|
-
if (lifecycleOf(model, a.id) !== "active") continue;
|
|
277615
|
+
for (const a of [...model.artifacts.values()]) {
|
|
276908
277616
|
if (written >= maxPerTick) {
|
|
276909
|
-
log3?.(`[board-watch] \u672C\u8F6E\u5199\u4FE1\u5DF2\u8FBE\u4E0A\u9650 ${maxPerTick}\uFF0C\u5176\u4F59\u677F\u4E0B\u8F6E\u518D\u770B`);
|
|
277617
|
+
log3?.(`[board-watch] ${tag}\u672C\u8F6E\u5199\u4FE1\u5DF2\u8FBE\u4E0A\u9650 ${maxPerTick}\uFF0C\u5176\u4F59\u677F\u4E0B\u8F6E\u518D\u770B`);
|
|
276910
277618
|
break;
|
|
276911
277619
|
}
|
|
277620
|
+
if (a.type !== "design") continue;
|
|
277621
|
+
if (lifecycleOf(model, a.id) !== "active") continue;
|
|
276912
277622
|
const boardKey = boardKeyOf(a.id);
|
|
276913
|
-
const
|
|
276914
|
-
|
|
276915
|
-
const
|
|
276916
|
-
|
|
276917
|
-
|
|
276918
|
-
|
|
276919
|
-
|
|
276920
|
-
);
|
|
276921
|
-
const
|
|
276922
|
-
|
|
276923
|
-
)
|
|
276924
|
-
|
|
276925
|
-
|
|
276926
|
-
const candidate = {
|
|
276927
|
-
boardMtime,
|
|
276928
|
-
hasRevision: revisionsOf(model, a.id).length > 0,
|
|
276929
|
-
lastOpAtMs: lastOpAt ? Date.parse(lastOpAt) : null,
|
|
276930
|
-
hasOpenWatchLetter: watchLetters.some((x2) => x2.state === "open"),
|
|
276931
|
-
lastWatchMtime: watchLetters.reduce((mx, x2) => {
|
|
276932
|
-
const m2 = parseMarker(x2.body);
|
|
276933
|
-
return m2 !== null && (mx === null || m2 > mx) ? m2 : mx;
|
|
276934
|
-
}, null),
|
|
276935
|
-
freshTerminalRunId: newestTerminalRun !== null && !letteredRuns.has(newestTerminalRun.runId) ? newestTerminalRun.runId : null
|
|
276936
|
-
};
|
|
276937
|
-
if (!decideBoardLetter(candidate, now, quietMs)) continue;
|
|
276938
|
-
const fmt = (fs52) => fs52.slice(0, 5).map((f2) => `- ${f2.path}\uFF08${f2.kind ?? "?"}\uFF09\xB7 ${f2.mtime ? new Date(f2.mtime).toISOString() : "?"}`).join("\n");
|
|
276939
|
-
let body2;
|
|
276940
|
-
let logLine;
|
|
276941
|
-
if (candidate.freshTerminalRunId !== null) {
|
|
276942
|
-
const status = newestTerminalRun.status;
|
|
276943
|
-
const ok3 = status === "succeeded";
|
|
276944
|
-
const listed = files.length > 0 ? fmt([...files].sort((x2, y) => (y.mtime ?? 0) - (x2.mtime ?? 0))) : "\uFF08\u677F\u4E0A\u6682\u65E0\u4EA4\u4ED8\u7269\uFF09";
|
|
276945
|
-
body2 = [
|
|
276946
|
-
// 两个 marker 都带:run marker 管快路径去重,mtime marker 顺手把慢路径也盖住——
|
|
276947
|
-
// 否则这封信被 resolve 后,慢路径会就**同一批板内容**再写一封(两路去重各管各的)。
|
|
276948
|
-
boardMtime !== null ? `${boardWatchRunMarker(candidate.freshTerminalRunId)} ${boardWatchMarker(boardMtime)}` : boardWatchRunMarker(candidate.freshTerminalRunId),
|
|
276949
|
-
ok3 ? `\u753B\u677F ${boardKey} \u7684\u5F15\u64CE\u8DD1\u5B8C\u4E86\uFF08run ${candidate.freshTerminalRunId.slice(0, 8)} \u7EC8\u6001=${status}\uFF09\uFF0C\u8D27\u5728\u677F\u4E0A\u7B49\u4F60\u6536\uFF1A` : `\u753B\u677F ${boardKey} \u7684\u5F15\u64CE\u8FD9\u4E00\u8F6E**\u6CA1\u8DD1\u6210**\uFF08run ${candidate.freshTerminalRunId.slice(0, 8)} \u7EC8\u6001=${status}\uFF09\u3002\u677F\u4E0A\u5F53\u524D\u5185\u5BB9\uFF1A`,
|
|
276950
|
-
listed,
|
|
276951
|
-
``,
|
|
276952
|
-
ok3 ? `\u53D6\u8D27\u6838\u5BF9\uFF1A\`oasis design status ${a.id} --pull\` \u2192 \u5BF9\u7740 DESIGN_BRIEF.md \u4E0E inputs/ \u9010\u5B57\u6BB5\u6838\uFF08\u6570\u636E\u5BF9\u4E0D\u5BF9\u3001\u72B6\u6001\u5168\u4E0D\u5168\u3001\u6709\u6CA1\u6709\u7F16\u9020\uFF09\u3002\u591F\u597D\u5C31 \`oasis propose ${a.id} --from-dir <\u76EE\u5F55> --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"\`\uFF1B\u8981\u6539\u5C31\u56DE\u677F\u4E0A\u518D\u6765\u4E00\u8F6E \`oasis design chat ${a.id} --turn continue --message "<\u8981\u6539\u4EC0\u4E48>" --async\`\uFF08\u26D4 \u522B\u628A --pull \u4E0B\u6765\u7684\u6587\u4EF6\u5728\u672C\u5730\u624B\u6539\u540E propose\uFF09\u3002` : `\u5148 \`oasis design status ${a.id}\` \u770B\u677F\u4E0A\u6709\u6CA1\u6709\u53EF\u7528\u7684\u4E0A\u4E00\u7248\uFF1A\u6709\u5C31\u7167\u5E38\u53D6\u8D27\u6838\u5BF9\uFF1B\u6CA1\u6709\u5C31\u628A\u9700\u6C42\u4E0E\u771F\u5B9E\u6570\u636E\u9489\u5F97\u66F4\u6B7B\u540E\u91CD\u8D77\u4E00\u8F6E \`oasis design chat ${a.id} --message "<\u2026>" --async\`\uFF0C\u4ECD\u4E0D\u884C\u7528 \`oasis gap ${a.id} --desc "<\u5361\u5728\u54EA>"\` \u5192\u6CE1\u7ED9\u4EBA\u3002`
|
|
276953
|
-
].join("\n");
|
|
276954
|
-
logLine = `[board-watch] ${a.id} \u2190 \u677F ${boardKey} \u5F15\u64CE\u6536\u5C3E\uFF08run ${candidate.freshTerminalRunId.slice(0, 8)} ${status}\uFF09\u2192 \u5DF2\u5199\u4FE1\u5524 owner`;
|
|
276955
|
-
} else {
|
|
276956
|
-
const newest = files.filter((f2) => f2.mtime !== null && candidate.lastOpAtMs !== null && f2.mtime > candidate.lastOpAtMs).sort((x2, y) => (y.mtime ?? 0) - (x2.mtime ?? 0));
|
|
276957
|
-
body2 = [
|
|
276958
|
-
boardWatchMarker(boardMtime),
|
|
276959
|
-
`\u753B\u677F ${boardKey} \u4E0A\u6709 Oasis \u4E4B\u5916\u7684\u65B0\u52A8\u9759\uFF08\u4EBA\u5728\u677F\u4E0A\u5BF9\u8BDD/\u6539\u7A3F\uFF0C\u6216\u5F15\u64CE\u4EA7\u4E86\u6CA1\u4EBA\u6536\u7684\u65B0\u7248\uFF09\uFF0C\u6BD4\u672C\u4EA7\u7269\u6700\u8FD1\u4E00\u6B21\u64CD\u4F5C\uFF08${lastOpAt ?? "?"}\uFF09\u65B0\u3001\u4E14\u5DF2\u9759\u9ED8 ${Math.round(quietMs / 6e4)} \u5206\u949F\uFF1A`,
|
|
276960
|
-
fmt(newest.length > 0 ? newest : files),
|
|
276961
|
-
``,
|
|
276962
|
-
`\u8BF7\u53D6\u8D27\u6838\u5BF9\uFF1A\`oasis design status ${a.id} --pull\` \u2192 \u5185\u5BB9\u5408\u610F\u5C31 \`oasis propose ${a.id} --from-dir <\u76EE\u5F55> --reason "<\u6536\u5F55\u677F\u4E0A\u4EBA\u5DE5\u8FED\u4EE3>"\` \u6536\u5F55\u4E3A\u65B0\u7248\u672C\uFF1B\u4E0D\u5408\u610F/\u4E0D\u5FC5\u6536\u5F55\uFF0C\u56DE\u5E16\u8BF4\u660E\u540E\u6309 wontfix \u5904\u7406\u5373\u53EF\uFF08\u540C\u4E00\u7248\u4E0D\u4F1A\u518D\u6765\u4FE1\uFF09\u3002`
|
|
276963
|
-
].join("\n");
|
|
276964
|
-
logLine = `[board-watch] ${a.id} \u2190 \u677F ${boardKey} \u6709\u65B0\u5185\u5BB9\uFF08mtime=${new Date(boardMtime).toISOString()}\uFF09\u2192 \u5DF2\u5199\u4FE1\u5524 owner`;
|
|
277623
|
+
const pinKey = `${company}\0${a.id}`;
|
|
277624
|
+
const watchLetters = annotationsOf(model, a.id).filter((x2) => x2.author === actor && x2.body.includes("[od-board-watch "));
|
|
277625
|
+
const lettered = new Set(watchLetters.map((x2) => parseRunMarker(x2.body)).filter((s2) => s2 !== null));
|
|
277626
|
+
const recordedSince = watchLetters.reduce((mn, x2) => {
|
|
277627
|
+
const s2 = parseSinceMarker(x2.body);
|
|
277628
|
+
return s2 !== null && (mn === null || s2 < mn) ? s2 : mn;
|
|
277629
|
+
}, null);
|
|
277630
|
+
const since = recordedSince ?? this.pinnedSince.get(pinKey) ?? now - graceMs;
|
|
277631
|
+
const read3 = await this.boardRounds(company, boardKey, since);
|
|
277632
|
+
if (read3.kind === "missing") continue;
|
|
277633
|
+
if (read3.kind === "denied") {
|
|
277634
|
+
denied.push({ company, boardKey, status: read3.status });
|
|
277635
|
+
continue;
|
|
276965
277636
|
}
|
|
276966
|
-
|
|
276967
|
-
|
|
276968
|
-
|
|
277637
|
+
if (read3.kind === "error") {
|
|
277638
|
+
log3?.(`[board-watch] ${tag}\u8BFB\u753B\u677F ${boardKey} \u5931\u8D25\uFF08${read3.detail}\uFF09\uFF0C\u672C\u8F6E\u8DF3\u8FC7`);
|
|
277639
|
+
continue;
|
|
277640
|
+
}
|
|
277641
|
+
if (recordedSince === null && !this.pinnedSince.has(pinKey)) this.pinnedSince.set(pinKey, since);
|
|
277642
|
+
const fresh = read3.value.rounds.filter((r) => r.endedAt > since && !lettered.has(r.key)).sort((x2, y) => x2.endedAt - y.endedAt);
|
|
277643
|
+
const seen = /* @__PURE__ */ new Set();
|
|
277644
|
+
for (const r of fresh) {
|
|
277645
|
+
if (written >= maxPerTick) break;
|
|
277646
|
+
if (seen.has(r.key)) continue;
|
|
277647
|
+
seen.add(r.key);
|
|
277648
|
+
const ok3 = r.status === "succeeded";
|
|
277649
|
+
const reason = ok3 ? null : r.error ?? (r.runId !== null ? await this.runErrorFromRegistry(boardKey, r.runId) : null);
|
|
277650
|
+
await kernel.annotate({ artifactId: a.id, actor, body: this.letterBody(a.id, boardKey, r, since, reason), kind: "comment" });
|
|
277651
|
+
written++;
|
|
277652
|
+
log3?.(`[board-watch] ${tag}${a.id} \u2190 \u677F ${boardKey} \u4E00\u8F6E\u5BF9\u8BDD\u7ED3\u675F\uFF08${r.key.slice(0, 12)} ${r.status}${r.agentId ? ` ${r.agentId}` : ""}\uFF09\u2192 \u5DF2\u5199\u4FE1\u5524 owner`);
|
|
277653
|
+
}
|
|
277654
|
+
const pending = new Set(fresh.filter((r) => !seen.has(r.key)).map((r) => r.conversationId));
|
|
277655
|
+
for (const [cid, convAt] of read3.value.fetched) {
|
|
277656
|
+
if (convAt !== null && !pending.has(cid)) this.seenConvAt.set(`${company}\0${boardKey}\0${cid}`, convAt);
|
|
277657
|
+
}
|
|
277658
|
+
}
|
|
277659
|
+
}
|
|
277660
|
+
letterBody(artifactId, boardKey, r, since, reason) {
|
|
277661
|
+
const marker = `${boardWatchRunMarker(r.key)} ${boardWatchSinceMarker(since)}`;
|
|
277662
|
+
const round = `${r.runId !== null ? `run ${r.runId.slice(0, 8)}` : `\u6D88\u606F ${r.key.slice(4, 12)}`}\uFF0C\u5F15\u64CE=${r.agentId ?? "?"}\uFF0C\u7ED3\u675F\u4E8E ${new Date(r.endedAt).toISOString()}`;
|
|
277663
|
+
if (r.status === "succeeded") {
|
|
277664
|
+
const files = r.producedFiles.length > 0 ? [...r.producedFiles.slice(0, MAX_LISTED_FILES).map((f2) => `- ${f2}`), ...r.producedFiles.length > MAX_LISTED_FILES ? [`- \u2026\u53E6 ${r.producedFiles.length - MAX_LISTED_FILES} \u4E2A`] : []].join("\n") : "\uFF08\u8FD9\u4E00\u8F6E\u6CA1\u6709\u767B\u8BB0\u4EA7\u51FA\u6587\u4EF6\uFF09";
|
|
277665
|
+
return [
|
|
277666
|
+
marker,
|
|
277667
|
+
`\u753B\u677F ${boardKey} \u4E0A\u6709\u4E00\u8F6E\u5BF9\u8BDD\u8DD1\u5B8C\u4E86\uFF08${round}\uFF09\uFF0C\u8FD9\u4E00\u8F6E\u4EA7\u51FA\uFF1A`,
|
|
277668
|
+
files,
|
|
277669
|
+
``,
|
|
277670
|
+
`\u53D6\u8D27\u6838\u5BF9\uFF1A\`oasis design status ${artifactId} --pull\` \u2192 \u5BF9\u7740 DESIGN_BRIEF.md \u4E0E inputs/ \u9010\u5B57\u6BB5\u6838\uFF08\u6570\u636E\u5BF9\u4E0D\u5BF9\u3001\u72B6\u6001\u5168\u4E0D\u5168\u3001\u6709\u6CA1\u6709\u7F16\u9020\uFF09\u3002\u591F\u597D\u5C31 \`oasis propose ${artifactId} --from-dir <\u76EE\u5F55> --reason "<\u8FD9\u7248\u505A\u4E86\u4EC0\u4E48>"\`\uFF1B\u8981\u6539\u5C31\u56DE\u677F\u4E0A\u518D\u6765\u4E00\u8F6E \`oasis design chat ${artifactId} --turn continue --message "<\u8981\u6539\u4EC0\u4E48>" --async\`\uFF08\u26D4 \u522B\u628A --pull \u4E0B\u6765\u7684\u6587\u4EF6\u5728\u672C\u5730\u624B\u6539\u540E propose\uFF09\u3002\u8FD9\u4E00\u8F6E\u82E5\u662F\u4EBA\u76F4\u63A5\u5728\u677F\u4E0A\u804A\u51FA\u6765\u7684\u3001\u5185\u5BB9\u4E0D\u5FC5\u6536\u5F55\uFF0C\u56DE\u5E16\u8BF4\u660E\u540E\u6309 wontfix \u5904\u7406\u5373\u53EF\uFF08\u540C\u4E00\u8F6E\u4E0D\u4F1A\u518D\u6765\u4FE1\uFF09\u3002`
|
|
277671
|
+
].join("\n");
|
|
276969
277672
|
}
|
|
277673
|
+
const quoted = reason === null ? null : reason.length > MAX_REASON_CHARS ? `${reason.slice(0, MAX_REASON_CHARS)}\u2026` : reason;
|
|
277674
|
+
return [
|
|
277675
|
+
marker,
|
|
277676
|
+
`\u753B\u677F ${boardKey} \u4E0A\u6709\u4E00\u8F6E\u5BF9\u8BDD**\u6CA1\u8DD1\u6210**\uFF08\u7EC8\u6001=${r.status}\uFF0C${round}\uFF09\u3002`,
|
|
277677
|
+
quoted !== null ? `od \u8BB0\u7684\u539F\u56E0\uFF08\u539F\u6587\uFF09\uFF1A${quoted}${r.errorCode !== null ? `\uFF08\u9519\u8BEF\u7801 ${r.errorCode}\uFF09` : ""}` : `od \u6CA1\u6709\u8BB0\u5F55\u8FD9\u4E00\u8F6E\u7684\u5931\u8D25\u539F\u56E0\u3002`,
|
|
277678
|
+
``,
|
|
277679
|
+
`\u5148 \`oasis design status ${artifactId}\` \u770B\u677F\u4E0A\u6709\u6CA1\u6709\u53EF\u7528\u7684\u4E0A\u4E00\u7248\uFF1A\u6709\u5C31\u7167\u5E38\u53D6\u8D27\u6838\u5BF9\u3002\u8981\u91CD\u8DD1\u5C31\u81EA\u5DF1\u5224\u65AD\uFF1A\u50CF\u662F\u989D\u5EA6/\u9650\u6D41\u5C31\u7B49\u6062\u590D\u540E\u518D\u6765\uFF0C\u6216\u6362\u4E2A\u5F15\u64CE \`oasis design chat ${artifactId} --agent <\u5F15\u64CE> --message "<\u2026>" --async\`\uFF1B\u50CF\u662F\u9700\u6C42/\u6570\u636E\u95EE\u9898\u5C31\u628A\u5B83\u4EEC\u9489\u5F97\u66F4\u6B7B\u540E\u91CD\u8D77\u4E00\u8F6E\uFF1B\u4ECD\u4E0D\u884C\u7528 \`oasis gap ${artifactId} --desc "<\u5361\u5728\u54EA>"\` \u5192\u6CE1\u7ED9\u4EBA\u3002`
|
|
277680
|
+
].join("\n");
|
|
276970
277681
|
}
|
|
276971
277682
|
};
|
|
276972
277683
|
}
|
|
@@ -277848,8 +278559,8 @@ __export(src_exports2, {
|
|
|
277848
278559
|
bindWorkorderProject: () => bindWorkorderProject,
|
|
277849
278560
|
bindingResolverFromRegistry: () => bindingResolverFromRegistry,
|
|
277850
278561
|
bindingRuntimeState: () => bindingRuntimeState,
|
|
277851
|
-
boardWatchMarker: () => boardWatchMarker,
|
|
277852
278562
|
boardWatchRunMarker: () => boardWatchRunMarker,
|
|
278563
|
+
boardWatchSinceMarker: () => boardWatchSinceMarker,
|
|
277853
278564
|
broadcastMessageId: () => broadcastMessageId,
|
|
277854
278565
|
broadcastMessageText: () => broadcastMessageText,
|
|
277855
278566
|
bucketRuntimeRuns: () => bucketRuntimeRuns,
|
|
@@ -277953,7 +278664,6 @@ __export(src_exports2, {
|
|
|
277953
278664
|
cronNext: () => cronNext,
|
|
277954
278665
|
cronNextN: () => cronNextN,
|
|
277955
278666
|
deadlineClockTick: () => deadlineClockTick,
|
|
277956
|
-
decideBoardLetter: () => decideBoardLetter,
|
|
277957
278667
|
defaultAvatarRefOf: () => defaultAvatarRefOf,
|
|
277958
278668
|
delegationArtifactsView: () => delegationArtifactsView,
|
|
277959
278669
|
delegationBundleAdditions: () => delegationBundleAdditions,
|
|
@@ -278104,6 +278814,7 @@ __export(src_exports2, {
|
|
|
278104
278814
|
parseConnectorSkillId: () => parseConnectorSkillId,
|
|
278105
278815
|
parseKnowledgeAnswerOutput: () => parseKnowledgeAnswerOutput,
|
|
278106
278816
|
parseKnowledgePlan: () => parseKnowledgePlan,
|
|
278817
|
+
parseOdTime: () => parseOdTime,
|
|
278107
278818
|
parseReadScope: () => parseReadScope,
|
|
278108
278819
|
parseSkillFrontmatter: () => parseSkillFrontmatter,
|
|
278109
278820
|
parseSymrefHead: () => parseSymrefHead,
|
|
@@ -278193,6 +278904,7 @@ __export(src_exports2, {
|
|
|
278193
278904
|
retireCdGateInTypeStore: () => retireCdGateInTypeStore,
|
|
278194
278905
|
rolesDomain: () => rolesDomain,
|
|
278195
278906
|
rollbackOrgIdentity: () => rollbackOrgIdentity,
|
|
278907
|
+
roundOfMessage: () => roundOfMessage,
|
|
278196
278908
|
routeFusedSignal: () => routeFusedSignal,
|
|
278197
278909
|
runtimeConnectionStatus: () => runtimeConnectionStatus,
|
|
278198
278910
|
runtimeDriftBlock: () => runtimeDriftBlock,
|
|
@@ -278758,14 +279470,14 @@ init_src();
|
|
|
278758
279470
|
var os16 = __toESM(require("node:os"));
|
|
278759
279471
|
var path46 = __toESM(require("node:path"));
|
|
278760
279472
|
var import_node_child_process26 = require("node:child_process");
|
|
278761
|
-
var
|
|
279473
|
+
var import_node_crypto95 = require("node:crypto");
|
|
278762
279474
|
|
|
278763
279475
|
// ../cli/src/cli.ts
|
|
278764
279476
|
init_src();
|
|
278765
279477
|
var fs44 = __toESM(require("node:fs"), 1);
|
|
278766
279478
|
var os13 = __toESM(require("node:os"), 1);
|
|
278767
279479
|
var path39 = __toESM(require("node:path"), 1);
|
|
278768
|
-
var
|
|
279480
|
+
var import_node_crypto93 = require("node:crypto");
|
|
278769
279481
|
|
|
278770
279482
|
// ../cli/src/serve.ts
|
|
278771
279483
|
init_src11();
|
|
@@ -278777,11 +279489,11 @@ var fs36 = __toESM(require("node:fs"), 1);
|
|
|
278777
279489
|
var os9 = __toESM(require("node:os"), 1);
|
|
278778
279490
|
var path30 = __toESM(require("node:path"), 1);
|
|
278779
279491
|
var import_node_child_process18 = require("node:child_process");
|
|
278780
|
-
var
|
|
279492
|
+
var import_node_crypto89 = require("node:crypto");
|
|
278781
279493
|
var import_node_url7 = require("node:url");
|
|
278782
279494
|
|
|
278783
279495
|
// ../cli/src/artifact-discovery-source.ts
|
|
278784
|
-
var
|
|
279496
|
+
var import_node_crypto85 = require("node:crypto");
|
|
278785
279497
|
init_src7();
|
|
278786
279498
|
var ArtifactDiscoverySourceUnreadableError = class extends Error {
|
|
278787
279499
|
constructor(message) {
|
|
@@ -278811,7 +279523,7 @@ async function resolveArtifactDiscoverySourceContent(blobs, input) {
|
|
|
278811
279523
|
throw new ArtifactDiscoverySourceUnreadableError(`Artifact Revision ${input.revisionId} \u7684 contentKind \u4E0D\u53D7\u652F\u6301\uFF1A${String(input.contentKind)}`);
|
|
278812
279524
|
}
|
|
278813
279525
|
const rootBytes = await blobs.get(input.contentRef);
|
|
278814
|
-
const sourceFingerprint = (0,
|
|
279526
|
+
const sourceFingerprint = (0, import_node_crypto85.createHash)("sha256").update(rootBytes).digest("hex");
|
|
278815
279527
|
if (input.contentKind === "inline-blob") {
|
|
278816
279528
|
const sourceContent = decodeText3(rootBytes);
|
|
278817
279529
|
if (sourceContent === null) {
|
|
@@ -278835,7 +279547,7 @@ ${entry.text}`).join("\n\n"),
|
|
|
278835
279547
|
}
|
|
278836
279548
|
|
|
278837
279549
|
// ../server/src/domains/discussions/service.ts
|
|
278838
|
-
var
|
|
279550
|
+
var import_node_crypto86 = require("node:crypto");
|
|
278839
279551
|
init_zod();
|
|
278840
279552
|
init_discussions();
|
|
278841
279553
|
init_router();
|
|
@@ -278897,7 +279609,7 @@ function remapTopics(topics, removed) {
|
|
|
278897
279609
|
return [...out].map(([topic_id, summary]) => ({ topic_id, summary }));
|
|
278898
279610
|
}
|
|
278899
279611
|
var entryId = (projectId2, id) => JSON.stringify([projectId2, id]);
|
|
278900
|
-
var hash2 = (s2) => (0,
|
|
279612
|
+
var hash2 = (s2) => (0, import_node_crypto86.createHash)("sha256").update(s2).digest("hex").slice(0, 24);
|
|
278901
279613
|
var canonical = (s2) => s2.normalize("NFKC").trim().toLocaleLowerCase();
|
|
278902
279614
|
function decisionFingerprint(d) {
|
|
278903
279615
|
return hash2(JSON.stringify([d.statement, d.rationale, d.alternatives]));
|
|
@@ -279117,7 +279829,7 @@ var DiscussionService = class {
|
|
|
279117
279829
|
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");
|
|
279118
279830
|
}
|
|
279119
279831
|
}
|
|
279120
|
-
const operation = (value2) => tx.put("operation", (0,
|
|
279832
|
+
const operation = (value2) => tx.put("operation", (0, import_node_crypto86.randomUUID)(), {
|
|
279121
279833
|
...value2,
|
|
279122
279834
|
projectId: projectId2,
|
|
279123
279835
|
actorId: ctx.actorId,
|
|
@@ -279134,7 +279846,7 @@ var DiscussionService = class {
|
|
|
279134
279846
|
if (id.startsWith("new:")) {
|
|
279135
279847
|
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`);
|
|
279136
279848
|
const existing = [...topicMap.values()].find((x2) => canonical(x2.title) === canonical(t.title));
|
|
279137
|
-
id = existing?.topicId ?? `topic_${(0,
|
|
279849
|
+
id = existing?.topicId ?? `topic_${(0, import_node_crypto86.randomUUID)()}`;
|
|
279138
279850
|
if (!existing) createdTopics.add(id);
|
|
279139
279851
|
} else if (!topicMap.has(id)) invalid("topics.topic_id", `\u8BAE\u9898 ${id} \u4E0D\u5B58\u5728\uFF1B\u65B0\u8BAE\u9898\u4F7F\u7528 new: \u524D\u7F00`);
|
|
279140
279852
|
topicAliases.set(t.topic_id, id);
|
|
@@ -279186,7 +279898,7 @@ var DiscussionService = class {
|
|
|
279186
279898
|
if (id.startsWith("new:")) {
|
|
279187
279899
|
const candidateKey = JSON.stringify([topicId, canonical(d.record.statement)]);
|
|
279188
279900
|
const existing = [...decisionMap.values()].find((x2) => x2.topicId === topicId && canonical(x2.record.statement) === canonical(d.record.statement));
|
|
279189
|
-
id = existing?.decisionId ?? candidateIds.get(candidateKey) ?? `decision_${(0,
|
|
279901
|
+
id = existing?.decisionId ?? candidateIds.get(candidateKey) ?? `decision_${(0, import_node_crypto86.randomUUID)()}`;
|
|
279190
279902
|
candidateIds.set(candidateKey, id);
|
|
279191
279903
|
} else if (!decisionMap.has(id)) invalid("decision_id", `\u51B3\u7B56 ${id} \u4E0D\u5B58\u5728\uFF1B\u65B0\u51B3\u7B56\u4F7F\u7528 new: \u524D\u7F00`);
|
|
279192
279904
|
decisionAliases.set(d.decision_id, id);
|
|
@@ -279448,7 +280160,7 @@ var DiscussionService = class {
|
|
|
279448
280160
|
...row.value.confirmation ? { confirmation: { ...row.value.confirmation, fingerprint: decisionFingerprint(record9) } } : {}
|
|
279449
280161
|
};
|
|
279450
280162
|
await tx.put("decision", row.id, value2);
|
|
279451
|
-
await tx.put("operation", (0,
|
|
280163
|
+
await tx.put("operation", (0, import_node_crypto86.randomUUID)(), {
|
|
279452
280164
|
action: "edit",
|
|
279453
280165
|
kind: "decision",
|
|
279454
280166
|
projectId: projectId2,
|
|
@@ -279512,7 +280224,7 @@ var DiscussionService = class {
|
|
|
279512
280224
|
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`);
|
|
279513
280225
|
const summary = given.get(row.id);
|
|
279514
280226
|
await tx.put("discussion", row.id, { ...current.value, record: { ...current.value.record, summary } });
|
|
279515
|
-
await tx.put("operation", (0,
|
|
280227
|
+
await tx.put("operation", (0, import_node_crypto86.randomUUID)(), {
|
|
279516
280228
|
action: "edit",
|
|
279517
280229
|
kind: "discussion",
|
|
279518
280230
|
projectId: current.value.record.project_id,
|
|
@@ -279528,7 +280240,7 @@ var DiscussionService = class {
|
|
|
279528
280240
|
});
|
|
279529
280241
|
}
|
|
279530
280242
|
async operation(tx, actorId, kind, id, from, to) {
|
|
279531
|
-
await tx.put("operation", (0,
|
|
280243
|
+
await tx.put("operation", (0, import_node_crypto86.randomUUID)(), { actorId, kind, id, from, to, at: new Date(this.now()).toISOString() });
|
|
279532
280244
|
}
|
|
279533
280245
|
};
|
|
279534
280246
|
function pickDiscussionContent(d) {
|
|
@@ -279828,7 +280540,7 @@ var DiscussionContext = class {
|
|
|
279828
280540
|
};
|
|
279829
280541
|
|
|
279830
280542
|
// ../server/src/domains/discussions/worker.ts
|
|
279831
|
-
var
|
|
280543
|
+
var import_node_crypto87 = require("node:crypto");
|
|
279832
280544
|
var DISCUSSION_IDLE_MS = 15 * 6e4;
|
|
279833
280545
|
var DISCUSSION_MAX_CORRECTIONS = 3;
|
|
279834
280546
|
var DISCUSSION_LEASE_MS = 2 * 6e4;
|
|
@@ -279854,7 +280566,7 @@ var DiscussionWorker = class {
|
|
|
279854
280566
|
if (await this.isReplying(sessionId)) return false;
|
|
279855
280567
|
const cutoff = eligibleCutoff(await this.service.chat.listMessages(sessionId), this.service.now());
|
|
279856
280568
|
if (!cutoff) return false;
|
|
279857
|
-
const owner = (0,
|
|
280569
|
+
const owner = (0, import_node_crypto87.randomUUID)();
|
|
279858
280570
|
const claimed = await this.service.store.transaction(async (tx) => {
|
|
279859
280571
|
const old = (await tx.get("job", sessionId))?.value;
|
|
279860
280572
|
if (old?.status === "running" && (old.leaseUntil ?? 0) > this.service.now()) return null;
|
|
@@ -280576,7 +281288,7 @@ function createDiscussionRuntime(options) {
|
|
|
280576
281288
|
}
|
|
280577
281289
|
|
|
280578
281290
|
// ../server/src/domains/discussions/store.ts
|
|
280579
|
-
var
|
|
281291
|
+
var import_node_crypto88 = require("node:crypto");
|
|
280580
281292
|
var import_promises17 = require("node:fs/promises");
|
|
280581
281293
|
var import_node_path27 = require("node:path");
|
|
280582
281294
|
var key = (kind, id) => JSON.stringify([kind, id]);
|
|
@@ -280621,7 +281333,7 @@ var MemoryDiscussionStore = class _MemoryDiscussionStore {
|
|
|
280621
281333
|
if (changed) {
|
|
280622
281334
|
if (this.filename) {
|
|
280623
281335
|
await (0, import_promises17.mkdir)((0, import_node_path27.dirname)(this.filename), { recursive: true });
|
|
280624
|
-
const temp = `${this.filename}.${(0,
|
|
281336
|
+
const temp = `${this.filename}.${(0, import_node_crypto88.randomUUID)()}.tmp`;
|
|
280625
281337
|
await (0, import_promises17.writeFile)(temp, JSON.stringify(next), "utf8");
|
|
280626
281338
|
await (0, import_promises17.rename)(temp, this.filename);
|
|
280627
281339
|
}
|
|
@@ -281570,7 +282282,7 @@ function oasisWrapperScript() {
|
|
|
281570
282282
|
const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
281571
282283
|
const tsx = path30.join(repoRoot, "node_modules/.bin/tsx");
|
|
281572
282284
|
const main = path30.join(repoRoot, "packages/cli/src/main.ts");
|
|
281573
|
-
const key2 = (0,
|
|
282285
|
+
const key2 = (0, import_node_crypto89.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
281574
282286
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
281575
282287
|
const stable = path30.join(os9.tmpdir(), `oasis-cli-wrapper-${uid}-${key2}`);
|
|
281576
282288
|
let dir;
|
|
@@ -281963,7 +282675,7 @@ async function startServe(opts) {
|
|
|
281963
282675
|
if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
|
|
281964
282676
|
const online = hub.connectedDaemons().some((d) => d.daemonId === nodeId);
|
|
281965
282677
|
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" });
|
|
281966
|
-
const requestId = (0,
|
|
282678
|
+
const requestId = (0, import_node_crypto89.randomUUID)();
|
|
281967
282679
|
const task = new Promise((resolve12) => {
|
|
281968
282680
|
const timer = setTimeout(() => {
|
|
281969
282681
|
modelRefreshWaiters.delete(requestId);
|
|
@@ -282792,7 +283504,7 @@ async function startServe(opts) {
|
|
|
282792
283504
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
282793
283505
|
if (buf || session.runId) {
|
|
282794
283506
|
await turnStore.appendMessage({
|
|
282795
|
-
id: (0,
|
|
283507
|
+
id: (0, import_node_crypto89.randomUUID)(),
|
|
282796
283508
|
sessionId: chatSessionId,
|
|
282797
283509
|
role: "assistant",
|
|
282798
283510
|
content: buf,
|
|
@@ -282838,7 +283550,7 @@ async function startServe(opts) {
|
|
|
282838
283550
|
chatTargets: {
|
|
282839
283551
|
inspect: inspectChatTarget,
|
|
282840
283552
|
createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
|
|
282841
|
-
const sessionId = (0,
|
|
283553
|
+
const sessionId = (0, import_node_crypto89.randomUUID)();
|
|
282842
283554
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
282843
283555
|
const binding = await registryStore.getBinding(agentId).catch(() => null);
|
|
282844
283556
|
await (await chatStoreFor(companyId)).createSession({
|
|
@@ -284240,7 +284952,7 @@ async function startServe(opts) {
|
|
|
284240
284952
|
}));
|
|
284241
284953
|
}
|
|
284242
284954
|
const limits = { wallClockMs: wallClockForKind("planner") };
|
|
284243
|
-
const artifactId = `artifact:planner:${(0,
|
|
284955
|
+
const artifactId = `artifact:planner:${(0, import_node_crypto89.randomUUID)()}`;
|
|
284244
284956
|
const handle = await chatRemoteAdapter.spawn({
|
|
284245
284957
|
actor: planner.id,
|
|
284246
284958
|
// companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
|
|
@@ -285161,10 +285873,10 @@ async function startServe(opts) {
|
|
|
285161
285873
|
if (isDeletedActor(dispatchTarget)) {
|
|
285162
285874
|
throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
|
|
285163
285875
|
}
|
|
285164
|
-
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0,
|
|
285876
|
+
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto89.randomUUID)());
|
|
285165
285877
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
285166
|
-
const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0,
|
|
285167
|
-
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0,
|
|
285878
|
+
const traceRunId = requestDispatchId ? stableChatTraceRunId(requestDispatchId) : `chat-run:${(0, import_node_crypto89.randomUUID)()}`;
|
|
285879
|
+
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto89.randomUUID)()}`;
|
|
285168
285880
|
let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
|
|
285169
285881
|
if (stableDispatch && !stableDispatch.shouldDispatch) {
|
|
285170
285882
|
if (isHumanSubmitDispatchId(requestDispatchId)) {
|
|
@@ -285638,7 +286350,13 @@ async function startServe(opts) {
|
|
|
285638
286350
|
metadata: { ...base, dispatchId: handle.id },
|
|
285639
286351
|
// 恢复路径拿不到 dispatchChat 闭包里的 fallback 解析结果,开跑时先写进账本;退出帧若上报
|
|
285640
286352
|
// 更精确 model 仍会覆盖为 runtime 来源。
|
|
285641
|
-
|
|
286353
|
+
// 这是**请求值**(会话选择 / 员工配置 / runtime 默认),按 ④ 排在实际值之下:采集点 1 的
|
|
286354
|
+
// 首帧检查点可能已经先一步把运行时回报的实际值写进这一行(两条路都是异步入队,谁先到不定),
|
|
286355
|
+
// 预写不能把它顶掉。
|
|
286356
|
+
...preferRunModel(
|
|
286357
|
+
{ effectiveModel: run.effectiveModel, modelSource: run.modelSource },
|
|
286358
|
+
{ effectiveModel: chatModel, modelSource: chatModelSource }
|
|
286359
|
+
) ?? {}
|
|
285642
286360
|
});
|
|
285643
286361
|
});
|
|
285644
286362
|
const buffered = [];
|
|
@@ -285710,11 +286428,17 @@ async function startServe(opts) {
|
|
|
285710
286428
|
}]);
|
|
285711
286429
|
const usage = info.usage ?? null;
|
|
285712
286430
|
const modelFields = chatExitModelFields(info.model, chatModel, chatModelSource, info.modelSource);
|
|
286431
|
+
const needsNativeSessionMetadata = !!info.runtimeSessionId && info.runtimeSessionId !== runtimeSessionId;
|
|
286432
|
+
const currentRun = needsNativeSessionMetadata || "effectiveModel" in modelFields ? await (await traceStoreFor(runCompanyId)).getRun(traceRunId).catch(() => null) : null;
|
|
285713
286433
|
let nativeSessionMetadata;
|
|
285714
|
-
if (
|
|
285715
|
-
|
|
285716
|
-
nativeSessionMetadata = nativeRuntimeSessionMetadata(run?.metadata, info.runtimeSessionId);
|
|
286434
|
+
if (needsNativeSessionMetadata) {
|
|
286435
|
+
nativeSessionMetadata = nativeRuntimeSessionMetadata(currentRun?.metadata, info.runtimeSessionId);
|
|
285717
286436
|
}
|
|
286437
|
+
const modelPatch = preferRunModel(
|
|
286438
|
+
{ effectiveModel: currentRun?.effectiveModel, modelSource: currentRun?.modelSource },
|
|
286439
|
+
{ effectiveModel: modelFields.effectiveModel, modelSource: modelFields.modelSource },
|
|
286440
|
+
"replace"
|
|
286441
|
+
) ?? {};
|
|
285718
286442
|
await traceAppender.update({
|
|
285719
286443
|
status: classifySessionExitStatus(info),
|
|
285720
286444
|
endedAt,
|
|
@@ -285724,7 +286448,7 @@ async function startServe(opts) {
|
|
|
285724
286448
|
...!isHealthySessionExit(info) && info.reason !== "cancelled" ? { errorCode: info.reason ?? "error", errorMessage: formatExitError(info) } : {},
|
|
285725
286449
|
transcriptRef: info.transcriptRef ?? null,
|
|
285726
286450
|
usage,
|
|
285727
|
-
...
|
|
286451
|
+
...modelPatch,
|
|
285728
286452
|
...nativeSessionMetadata ? { metadata: nativeSessionMetadata } : {}
|
|
285729
286453
|
});
|
|
285730
286454
|
if (usage) await settleRunUsage(await traceStoreFor(runCompanyId), traceRunId);
|
|
@@ -286622,7 +287346,7 @@ async function startServe(opts) {
|
|
|
286622
287346
|
console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
|
|
286623
287347
|
return;
|
|
286624
287348
|
}
|
|
286625
|
-
const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0,
|
|
287349
|
+
const ledgerId = opts2?.protocolRecovery?.dispatchId ?? `dispatch:${(0, import_node_crypto89.randomUUID)()}`;
|
|
286626
287350
|
try {
|
|
286627
287351
|
const inserted = await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
286628
287352
|
id: ledgerId,
|
|
@@ -286722,7 +287446,7 @@ async function startServe(opts) {
|
|
|
286722
287446
|
const kernelModel = newKernel.model;
|
|
286723
287447
|
const art = kernelModel.artifacts.get(nodeId);
|
|
286724
287448
|
const revWid = art?.workspace ?? "";
|
|
286725
|
-
const ledgerId = `dispatch:${(0,
|
|
287449
|
+
const ledgerId = `dispatch:${(0, import_node_crypto89.randomUUID)()}`;
|
|
286726
287450
|
try {
|
|
286727
287451
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
286728
287452
|
id: ledgerId,
|
|
@@ -287116,7 +287840,7 @@ async function startServe(opts) {
|
|
|
287116
287840
|
resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
|
|
287117
287841
|
try {
|
|
287118
287842
|
const governance = server.knowledgeGovernance;
|
|
287119
|
-
const taskFingerprint = (0,
|
|
287843
|
+
const taskFingerprint = (0, import_node_crypto89.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
|
|
287120
287844
|
const requestContext = {
|
|
287121
287845
|
organizationId: companyId,
|
|
287122
287846
|
actorId,
|
|
@@ -288579,7 +289303,12 @@ ${nodeFault}` : "");
|
|
|
288579
289303
|
const odBase = (process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
288580
289304
|
const odToken = process.env["OASIS_OPEN_DESIGN_TOKEN"]?.trim() || void 0;
|
|
288581
289305
|
const boardWatcher = new BoardWatcher({
|
|
288582
|
-
|
|
289306
|
+
listCompanies: async () => {
|
|
289307
|
+
if (!chatStoreRouter) return [defaultCompanyId];
|
|
289308
|
+
const active = (await controlPlaneStore.listCompanies()).filter((c) => c.status === "active").map((c) => c.id);
|
|
289309
|
+
return [defaultCompanyId, ...active.filter((id) => id !== defaultCompanyId)];
|
|
289310
|
+
},
|
|
289311
|
+
kernelFor: async (companyId) => (await getEngine(companyId)).kernel,
|
|
288583
289312
|
odBase,
|
|
288584
289313
|
...odToken ? { odToken } : {},
|
|
288585
289314
|
boardKeyOf: deriveBoardKey,
|
|
@@ -288588,7 +289317,7 @@ ${nodeFault}` : "");
|
|
|
288588
289317
|
boardWatchTimer = setInterval(() => {
|
|
288589
289318
|
void boardWatcher.tick().catch((err) => console.error(`[board-watch] tick \u5931\u8D25: ${String(err)}`));
|
|
288590
289319
|
}, 6e4);
|
|
288591
|
-
console.log(`[serve] \u753B\u677F\u76D1\u89C6\u5668\u5DF2\u542F\u7528\uFF08od=${odBase}${odToken ? "\uFF0C\u5E26\u4EE4\u724C" : ""}\uFF0C\
|
|
289320
|
+
console.log(`[serve] \u753B\u677F\u76D1\u89C6\u5668\u5DF2\u542F\u7528\uFF08od=${odBase}${odToken ? "\uFF0C\u5E26\u4EE4\u724C" : ""}\uFF0C\u5DE1\u6240\u6709\u516C\u53F8\uFF0C\u6BCF\u7ED3\u675F\u4E00\u8F6E\u5BF9\u8BDD\u5199\u4E00\u5C01\u4FE1\uFF0C\u6BCF\u8F6E\u6BCF\u5BB6\u516C\u53F8\u4E0A\u9650 2 \u5C01\uFF1BOASIS_BOARD_WATCH=0 \u53EF\u5173\uFF09`);
|
|
288592
289321
|
} else {
|
|
288593
289322
|
console.log(`[serve] \u753B\u677F\u76D1\u89C6\u5668\u5DF2\u88AB OASIS_BOARD_WATCH=${boardWatchFlag} \u663E\u5F0F\u5173\u95ED`);
|
|
288594
289323
|
}
|
|
@@ -289835,7 +290564,7 @@ var RuntimeQuotaMonitor = class {
|
|
|
289835
290564
|
init_wrapper();
|
|
289836
290565
|
init_src();
|
|
289837
290566
|
var import_node_os11 = require("node:os");
|
|
289838
|
-
var
|
|
290567
|
+
var import_node_crypto90 = require("node:crypto");
|
|
289839
290568
|
init_src8();
|
|
289840
290569
|
init_src2();
|
|
289841
290570
|
|
|
@@ -290739,7 +291468,7 @@ var DaemonWsClient = class {
|
|
|
290739
291468
|
*/
|
|
290740
291469
|
async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
|
|
290741
291470
|
if (artifactIds.length === 0) return {};
|
|
290742
|
-
const requestId = (0,
|
|
291471
|
+
const requestId = (0, import_node_crypto90.randomUUID)();
|
|
290743
291472
|
return new Promise((resolve12, reject) => {
|
|
290744
291473
|
const timer = setTimeout(() => {
|
|
290745
291474
|
this.gcPending.delete(requestId);
|
|
@@ -291153,7 +291882,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
291153
291882
|
// ../cli/src/daemon/machine-id.ts
|
|
291154
291883
|
var import_node_child_process23 = require("node:child_process");
|
|
291155
291884
|
var import_node_fs24 = require("node:fs");
|
|
291156
|
-
var
|
|
291885
|
+
var import_node_crypto91 = require("node:crypto");
|
|
291157
291886
|
var import_node_os14 = require("node:os");
|
|
291158
291887
|
function linuxMachineId() {
|
|
291159
291888
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
@@ -291219,7 +291948,7 @@ var defaultSources = {
|
|
|
291219
291948
|
function resolveNodeId(sources = {}) {
|
|
291220
291949
|
const s2 = { ...defaultSources, ...sources };
|
|
291221
291950
|
const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
|
|
291222
|
-
const digest = (0,
|
|
291951
|
+
const digest = (0, import_node_crypto91.createHash)("sha256").update(material).digest("hex").slice(0, 12);
|
|
291223
291952
|
return `node-${digest}`;
|
|
291224
291953
|
}
|
|
291225
291954
|
|
|
@@ -293091,13 +293820,13 @@ function ownFlagsFromDecl(command2) {
|
|
|
293091
293820
|
}
|
|
293092
293821
|
|
|
293093
293822
|
// ../cli/src/connector-effect-runner.ts
|
|
293094
|
-
var
|
|
293823
|
+
var import_node_crypto92 = require("node:crypto");
|
|
293095
293824
|
var import_node_child_process24 = require("node:child_process");
|
|
293096
293825
|
init_src8();
|
|
293097
293826
|
function stableKey(effect) {
|
|
293098
293827
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
293099
293828
|
const canonical2 = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
|
|
293100
|
-
return `sha256:${(0,
|
|
293829
|
+
return `sha256:${(0, import_node_crypto92.createHash)("sha256").update(canonical2).digest("hex")}`;
|
|
293101
293830
|
}
|
|
293102
293831
|
async function runConnectorEffect(connector, toolArgs, deps) {
|
|
293103
293832
|
const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
|
|
@@ -293473,6 +294202,7 @@ ${buildCommandIndex()}
|
|
|
293473
294202
|
${USAGE_FOOTER}`;
|
|
293474
294203
|
var COMMAND_HELP = buildCommandHelp();
|
|
293475
294204
|
var HISTORICAL_REVIEW_GUIDANCE = "\u672C\u7968\u4E0D\u53C2\u4E0E\u672C\u8F6E quorum\uFF1B\u4F46\u5B83\u6307\u51FA\u7684\u95EE\u9898\u53EF\u80FD\u4ECD\u7136\u5B58\u5728\uFF0C\u9700\u9010\u6761\u5BF9\u7167 diff \u786E\u8BA4";
|
|
294205
|
+
var EMPTY_OK_NOTE_FLAGS = /* @__PURE__ */ new Set(["unresolved", "risks", "gaps", "next"]);
|
|
293476
294206
|
function parseArgs(argv) {
|
|
293477
294207
|
const positional = [];
|
|
293478
294208
|
const flags = /* @__PURE__ */ new Map();
|
|
@@ -293499,6 +294229,10 @@ function parseArgs(argv) {
|
|
|
293499
294229
|
const value2 = argv[i + 1];
|
|
293500
294230
|
const key2 = a.slice(2);
|
|
293501
294231
|
if (value2 === void 0 || value2.startsWith("--")) {
|
|
294232
|
+
if (EMPTY_OK_NOTE_FLAGS.has(key2)) {
|
|
294233
|
+
flags.set(key2, "");
|
|
294234
|
+
continue;
|
|
294235
|
+
}
|
|
293502
294236
|
if (!booleanFlags.has(key2)) throw new Error(`flag ${a} \u9700\u8981\u4E00\u4E2A\u503C`);
|
|
293503
294237
|
flags.set(key2, "true");
|
|
293504
294238
|
} else {
|
|
@@ -293652,7 +294386,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
293652
294386
|
const timeoutMs = resolveAuthWaitMs();
|
|
293653
294387
|
const controller = new AbortController();
|
|
293654
294388
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
293655
|
-
const waiterId = (0,
|
|
294389
|
+
const waiterId = (0, import_node_crypto93.randomUUID)();
|
|
293656
294390
|
process.stderr.write(
|
|
293657
294391
|
`\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
|
|
293658
294392
|
`
|
|
@@ -293736,7 +294470,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
293736
294470
|
}
|
|
293737
294471
|
}
|
|
293738
294472
|
}
|
|
293739
|
-
var CLI_VERSION = "2.2.
|
|
294473
|
+
var CLI_VERSION = "2.2.84" ? "2.2.84" : "dev";
|
|
293740
294474
|
function apiHeaders(token, company) {
|
|
293741
294475
|
const headers = {
|
|
293742
294476
|
authorization: `Bearer ${token}`,
|
|
@@ -294102,7 +294836,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
294102
294836
|
const store = createNodeTokenStore(path39.join(dir, "node-tokens.json"));
|
|
294103
294837
|
const sub = positional[0];
|
|
294104
294838
|
if (sub === "issue") {
|
|
294105
|
-
const id = flags.get("id") ?? `node-${(0,
|
|
294839
|
+
const id = flags.get("id") ?? `node-${(0, import_node_crypto93.randomUUID)()}`;
|
|
294106
294840
|
const token2 = store.issue(id);
|
|
294107
294841
|
println(token2);
|
|
294108
294842
|
process.stderr.write(
|
|
@@ -295252,7 +295986,7 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
295252
295986
|
if (!name) throw new Error("\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
295253
295987
|
const goal = flags.get("goal")?.trim();
|
|
295254
295988
|
const slug6 = flags.get("slug");
|
|
295255
|
-
const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0,
|
|
295989
|
+
const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0, import_node_crypto93.randomUUID)());
|
|
295256
295990
|
const result = await api.request("POST", "/api/projects", {
|
|
295257
295991
|
...id ? { id } : {},
|
|
295258
295992
|
name,
|
|
@@ -295603,6 +296337,10 @@ ${res.warning}`);
|
|
|
295603
296337
|
note: flags.get("note")
|
|
295604
296338
|
});
|
|
295605
296339
|
println(message);
|
|
296340
|
+
const ignoredNotes = [...EMPTY_OK_NOTE_FLAGS].filter((k2) => flags.has(k2)).map((k2) => `--${k2}`);
|
|
296341
|
+
if (ignoredNotes.length > 0) {
|
|
296342
|
+
println(`\u26A0 ${ignoredNotes.join("\u3001")} \u6CA1\u6709\u88AB\u8BB0\u5F55\uFF1Aoasis conclude \u53EA\u6536 --note\u3002\u8FD9\u51E0\u9879\u8981\u5199\u5728 oasis propose \u4E0A\uFF0C\u4E0B\u6B21\u4EA4\u4ED8\u65F6\u4E00\u8D77\u5E26\u4E0A\u3002`);
|
|
296343
|
+
}
|
|
295606
296344
|
break;
|
|
295607
296345
|
}
|
|
295608
296346
|
case "review": {
|
|
@@ -297523,13 +298261,13 @@ function runtimeAssetSourceRoots(input) {
|
|
|
297523
298261
|
}
|
|
297524
298262
|
|
|
297525
298263
|
// src/install.ts
|
|
297526
|
-
var
|
|
298264
|
+
var import_node_crypto94 = require("node:crypto");
|
|
297527
298265
|
var fs50 = __toESM(require("node:fs"));
|
|
297528
298266
|
var path45 = __toESM(require("node:path"));
|
|
297529
298267
|
function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
|
|
297530
298268
|
const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
|
|
297531
298269
|
if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
|
|
297532
|
-
const digest = (0,
|
|
298270
|
+
const digest = (0, import_node_crypto94.createHash)("sha256").update(fs50.readFileSync(sourceFile)).digest("hex").slice(0, 8);
|
|
297533
298271
|
return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
|
|
297534
298272
|
}
|
|
297535
298273
|
function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
@@ -297652,7 +298390,7 @@ function shimScript() {
|
|
|
297652
298390
|
}
|
|
297653
298391
|
|
|
297654
298392
|
// src/index.ts
|
|
297655
|
-
var PKG_VERSION = true ? "2.2.
|
|
298393
|
+
var PKG_VERSION = true ? "2.2.84" : "dev";
|
|
297656
298394
|
var LOCAL_BIN = localBin();
|
|
297657
298395
|
var NPM_PREFIX = npmPrefix();
|
|
297658
298396
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -297960,7 +298698,7 @@ function newInstanceName() {
|
|
|
297960
298698
|
const existing = new Set(listInstances());
|
|
297961
298699
|
if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
|
|
297962
298700
|
for (; ; ) {
|
|
297963
|
-
const n = `inst-${(0,
|
|
298701
|
+
const n = `inst-${(0, import_node_crypto95.randomBytes)(3).toString("hex")}`;
|
|
297964
298702
|
if (!existing.has(n)) return n;
|
|
297965
298703
|
}
|
|
297966
298704
|
}
|