oasis_test_v2 2.2.15 → 2.2.17
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/_base/wrapper-base.sh +37 -13
- package/dist/index.js +702 -460
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -25452,7 +25452,9 @@ var init_codex = __esm({
|
|
|
25452
25452
|
const reasoningEffort = this.opts.reasoningEffort;
|
|
25453
25453
|
return runProtocolSession(job, {
|
|
25454
25454
|
bin: this.opts.codexBin ?? "codex",
|
|
25455
|
-
|
|
25455
|
+
// 同 exec 那条路:关掉登录 shell,否则 `~/.profile` 会把 `$HOME/.local/bin` 前置到
|
|
25456
|
+
// PATH 最前,压过注入的连接器 wrapper(理由与实证见 exec 分支里那段长注释)。
|
|
25457
|
+
args: ["app-server", "--stdio", "-c", "allow_login_shell=false"],
|
|
25456
25458
|
extraArgs: this.opts.extraArgs,
|
|
25457
25459
|
blockedFlags: CODEX_APP_SERVER_BLOCKED_FLAGS,
|
|
25458
25460
|
workRoot: this.opts.workRoot,
|
|
@@ -25633,6 +25635,24 @@ ${task}` : task;
|
|
|
25633
25635
|
// 打开 reasoning 摘要通道:默认 auto,让 codex 产出 reasoning item(→ thought → 前端思考块)。
|
|
25634
25636
|
...this.opts.reasoningSummary !== "none" ? ["-c", `model_reasoning_summary=${this.opts.reasoningSummary ?? "auto"}`] : [],
|
|
25635
25637
|
...this.opts.reasoningEffort ? ["-c", `model_reasoning_effort=${this.opts.reasoningEffort}`] : [],
|
|
25638
|
+
/* ★ 关掉登录 shell(2026-09-11)。
|
|
25639
|
+
codex 的 shell 工具默认把每条命令丢进 `/bin/bash -lc`——本机 codex 自己的
|
|
25640
|
+
thread_history 里逐字记着 `"command":"/bin/bash -lc \"pwd && rg …"`。
|
|
25641
|
+
登录 shell 会重跑 `~/.profile`,而 Ubuntu 的 profile 里是
|
|
25642
|
+
`PATH="$HOME/.local/bin:$PATH"`(**前置**);于是任何装在 `~/.local/bin` 的同名 CLI
|
|
25643
|
+
都会抢到注入的连接器 wrapper 前面。实测后果:飞书连接器凭据、连接记录全对,
|
|
25644
|
+
dev-agent(codex)跑 `lark-cli whoami` 却回 `not_configured`——wrapper 被绕过、
|
|
25645
|
+
而隔离键 `LARKSUITE_CLI_CONFIG_DIR` 照旧生效指着空目录,两头落空。
|
|
25646
|
+
同机同用户的 claude-code agent 一切正常,差别只有这一个 `-l`。
|
|
25647
|
+
|
|
25648
|
+
`allow_login_shell` 是 codex 的正式配置键(本机实测:给它传整数会报
|
|
25649
|
+
`invalid type: integer, expected a boolean in \`allow_login_shell\``,
|
|
25650
|
+
而不存在的键是被静默忽略的),exec 与 app-server 两条路都吃 `-c` 覆盖。
|
|
25651
|
+
|
|
25652
|
+
⚠ 未验证的一格:这个键**是否真的**就是那个 `-l` 的开关,只能等下一次
|
|
25653
|
+
codex 派单后在节点上 `ps` 看是 `bash -lc` 还是 `bash -c`。设错了是 no-op,不会更坏。 */
|
|
25654
|
+
"-c",
|
|
25655
|
+
"allow_login_shell=false",
|
|
25636
25656
|
// ADR「agent CLI 启动参数员工级可配置化」:员工配置 job.extraArgs(在前)+ opts.extraArgs(静态默认,在后),
|
|
25637
25657
|
// 过 CODEX_BLOCKED_FLAGS 拦截。追加在**位置 prompt 之前**(codex exec 的 [PROMPT] 必须是末位参数)。
|
|
25638
25658
|
...prepareExtraArgs(
|
|
@@ -28663,7 +28683,7 @@ function projectsIntoContent(kind, role, origin, telemetryTextInContent) {
|
|
|
28663
28683
|
return true;
|
|
28664
28684
|
}
|
|
28665
28685
|
}
|
|
28666
|
-
var import_node_crypto15, CHAT_ITEMS_DOUBLE_WRITE_ENV, ChatItemLedger;
|
|
28686
|
+
var import_node_crypto15, CHAT_ITEMS_DOUBLE_WRITE_ENV, SEGMENT_END_NOTE, ChatItemLedger;
|
|
28667
28687
|
var init_chat_item_ledger = __esm({
|
|
28668
28688
|
"../server/src/chat-item-ledger.ts"() {
|
|
28669
28689
|
"use strict";
|
|
@@ -28671,6 +28691,7 @@ var init_chat_item_ledger = __esm({
|
|
|
28671
28691
|
init_chat_item();
|
|
28672
28692
|
import_node_crypto15 = require("node:crypto");
|
|
28673
28693
|
CHAT_ITEMS_DOUBLE_WRITE_ENV = "OASIS_CHAT_ITEMS_DOUBLE_WRITE";
|
|
28694
|
+
SEGMENT_END_NOTE = "\u672C\u6BB5\u65E0\u8F93\u51FA\uFF08\u4EBA\u5728\u9996\u4E2A\u6B63\u6587\u4E4B\u524D\u63D2\u4E86\u8BDD\uFF09";
|
|
28674
28695
|
ChatItemLedger = class {
|
|
28675
28696
|
constructor(deps) {
|
|
28676
28697
|
this.deps = deps;
|
|
@@ -28699,6 +28720,8 @@ var init_chat_item_ledger = __esm({
|
|
|
28699
28720
|
log;
|
|
28700
28721
|
persistEnabled;
|
|
28701
28722
|
telemetryTextInContent;
|
|
28723
|
+
/** 本段的「无输出」注解已经提前落过(`closeSegmentBeforeUserInput`),`beginSegment` 别再落一条。 */
|
|
28724
|
+
segmentEndEmitted = false;
|
|
28702
28725
|
/** **不变量 1**:`providerItemKey → itemId`,本账本唯一持有。切段/收尾清空。 */
|
|
28703
28726
|
itemKeyMap = /* @__PURE__ */ new Map();
|
|
28704
28727
|
/** 内存账本:itemId → 行。插入顺序即 seq 顺序。 */
|
|
@@ -28916,19 +28939,11 @@ var init_chat_item_ledger = __esm({
|
|
|
28916
28939
|
* 映射一并清空——新段是新行,复用旧 itemId 会把新文本写进上一条消息。
|
|
28917
28940
|
*/
|
|
28918
28941
|
beginSegment() {
|
|
28919
|
-
this.
|
|
28920
|
-
|
|
28921
|
-
|
|
28922
|
-
|
|
28923
|
-
|
|
28924
|
-
status: "completed",
|
|
28925
|
-
origin: "server",
|
|
28926
|
-
text: "",
|
|
28927
|
-
attrs: {},
|
|
28928
|
-
inContent: false,
|
|
28929
|
-
persist: true,
|
|
28930
|
-
payload: { code: "segment_end", note: "\u672C\u6BB5\u65E0\u8F93\u51FA\uFF08\u4EBA\u5728\u9996\u4E2A\u6B63\u6587\u4E4B\u524D\u63D2\u4E86\u8BDD\uFF09" }
|
|
28931
|
-
});
|
|
28942
|
+
if (this.segmentEndEmitted) {
|
|
28943
|
+
this.segmentEndEmitted = false;
|
|
28944
|
+
} else {
|
|
28945
|
+
this.closeStreamingRows("completed");
|
|
28946
|
+
if (this.segmentItemCount === 0 && this.messageId) this.insertSegmentEnd();
|
|
28932
28947
|
}
|
|
28933
28948
|
this.itemKeyMap.clear();
|
|
28934
28949
|
this.lastTurnId = null;
|
|
@@ -28936,6 +28951,41 @@ var init_chat_item_ledger = __esm({
|
|
|
28936
28951
|
this.segment += 1;
|
|
28937
28952
|
this.segmentItemCount = 0;
|
|
28938
28953
|
}
|
|
28954
|
+
/**
|
|
28955
|
+
* 人插话时,先把「这一段到此为止」落定;**必须在那条 user 行之前调用**。
|
|
28956
|
+
*
|
|
28957
|
+
* 展示序(`ord`)由落库那一刻的表级序列派,所以**谁先落库谁在上面**。此前这条注解跟在
|
|
28958
|
+
* `beginSegment()` 里、而 `beginSegment` 由 `onUserInput` 回调在 user 行之后触发,于是
|
|
28959
|
+
* 「本段无输出」排到了人说的那句话**下面**——发起人 2026-09-11 的现场(会话 `eca44da4`:
|
|
28960
|
+
* user 行 ord 8503、注解 ord 8504)。他要的顺序是:开启这一轮的那条消息 → agent 头像块
|
|
28961
|
+
* (里面就是这条注解)→ 人插的那句话 → agent 接着说。
|
|
28962
|
+
*
|
|
28963
|
+
* 返回落下的那一行(`null` = 本段有输出、或还没有 assistant 行可归属,不需要注解),
|
|
28964
|
+
* 调用方据它把这条推上 v3 流——不推的话它只在下一次快照才出现。
|
|
28965
|
+
*/
|
|
28966
|
+
closeSegmentBeforeUserInput() {
|
|
28967
|
+
this.closeStreamingRows("completed");
|
|
28968
|
+
if (this.segmentEndEmitted) return null;
|
|
28969
|
+
if (this.segmentItemCount !== 0 || !this.messageId) return null;
|
|
28970
|
+
const id = this.insertSegmentEnd();
|
|
28971
|
+
this.segmentEndEmitted = true;
|
|
28972
|
+
const row = this.rows.get(id);
|
|
28973
|
+
return { itemId: id, version: row.wireVersion, startedVersion: row.startedVersion, ord: row.ord };
|
|
28974
|
+
}
|
|
28975
|
+
/** 零输出段兜底(S1 评审 B1):那条 assistant 行库里已经在了,一条 item 都没有会被对账抓成假红。 */
|
|
28976
|
+
insertSegmentEnd() {
|
|
28977
|
+
return this.insert({
|
|
28978
|
+
kind: "control",
|
|
28979
|
+
role: "assistant",
|
|
28980
|
+
status: "completed",
|
|
28981
|
+
origin: "server",
|
|
28982
|
+
text: "",
|
|
28983
|
+
attrs: {},
|
|
28984
|
+
inContent: false,
|
|
28985
|
+
persist: true,
|
|
28986
|
+
payload: { code: "segment_end", note: SEGMENT_END_NOTE }
|
|
28987
|
+
});
|
|
28988
|
+
}
|
|
28939
28989
|
/** 行落库了,把本段还挂着 NULL 的 assistant item 认领回去,并让后续 item 直接带上它。 */
|
|
28940
28990
|
bindMessage(messageId) {
|
|
28941
28991
|
this.messageId = messageId;
|
|
@@ -51348,7 +51398,7 @@ var require_websocket = __commonJS({
|
|
|
51348
51398
|
var http2 = require("http");
|
|
51349
51399
|
var net = require("net");
|
|
51350
51400
|
var tls = require("tls");
|
|
51351
|
-
var { randomBytes: randomBytes13, createHash:
|
|
51401
|
+
var { randomBytes: randomBytes13, createHash: createHash38 } = require("crypto");
|
|
51352
51402
|
var { Duplex, Readable } = require("stream");
|
|
51353
51403
|
var { URL: URL2 } = require("url");
|
|
51354
51404
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -52016,7 +52066,7 @@ var require_websocket = __commonJS({
|
|
|
52016
52066
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
52017
52067
|
return;
|
|
52018
52068
|
}
|
|
52019
|
-
const digest =
|
|
52069
|
+
const digest = createHash38("sha1").update(key + GUID).digest("base64");
|
|
52020
52070
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
52021
52071
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
52022
52072
|
return;
|
|
@@ -52385,7 +52435,7 @@ var require_websocket_server = __commonJS({
|
|
|
52385
52435
|
var EventEmitter = require("events");
|
|
52386
52436
|
var http2 = require("http");
|
|
52387
52437
|
var { Duplex } = require("stream");
|
|
52388
|
-
var { createHash:
|
|
52438
|
+
var { createHash: createHash38 } = require("crypto");
|
|
52389
52439
|
var extension3 = require_extension();
|
|
52390
52440
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
52391
52441
|
var subprotocol2 = require_subprotocol();
|
|
@@ -52692,7 +52742,7 @@ var require_websocket_server = __commonJS({
|
|
|
52692
52742
|
);
|
|
52693
52743
|
}
|
|
52694
52744
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
52695
|
-
const digest =
|
|
52745
|
+
const digest = createHash38("sha1").update(key + GUID).digest("base64");
|
|
52696
52746
|
const headers = [
|
|
52697
52747
|
"HTTP/1.1 101 Switching Protocols",
|
|
52698
52748
|
"Upgrade: websocket",
|
|
@@ -159847,6 +159897,7 @@ var DEFAULT_BUFFER_MAX, DEFAULT_GRACE_MS, DEFAULT_LIVE_COALESCE_MS, DEFAULT_LIVE
|
|
|
159847
159897
|
var init_live_chat = __esm({
|
|
159848
159898
|
"../server/src/live-chat.ts"() {
|
|
159849
159899
|
"use strict";
|
|
159900
|
+
init_chat_item_ledger();
|
|
159850
159901
|
DEFAULT_BUFFER_MAX = 4e3;
|
|
159851
159902
|
DEFAULT_GRACE_MS = 6e4;
|
|
159852
159903
|
DEFAULT_LIVE_COALESCE_MS = 24;
|
|
@@ -160593,6 +160644,24 @@ var init_live_chat = __esm({
|
|
|
160593
160644
|
text: shown,
|
|
160594
160645
|
...opts?.attachments?.length ? { attachments: opts.attachments } : {}
|
|
160595
160646
|
};
|
|
160647
|
+
const segmentEnd = (() => {
|
|
160648
|
+
try {
|
|
160649
|
+
return turn.items?.closeSegmentBeforeUserInput() ?? null;
|
|
160650
|
+
} catch {
|
|
160651
|
+
return null;
|
|
160652
|
+
}
|
|
160653
|
+
})();
|
|
160654
|
+
if (segmentEnd) {
|
|
160655
|
+
this.publishServerItem(turn, {
|
|
160656
|
+
itemId: segmentEnd.itemId,
|
|
160657
|
+
itemType: "control",
|
|
160658
|
+
startedVersion: segmentEnd.startedVersion,
|
|
160659
|
+
version: segmentEnd.version,
|
|
160660
|
+
ord: segmentEnd.ord,
|
|
160661
|
+
status: "completed",
|
|
160662
|
+
payload: { code: "segment_end", note: SEGMENT_END_NOTE }
|
|
160663
|
+
});
|
|
160664
|
+
}
|
|
160596
160665
|
try {
|
|
160597
160666
|
turn.items?.recordUserInput(shown, opts?.attachments, opts?.clientKeys);
|
|
160598
160667
|
} catch {
|
|
@@ -197867,41 +197936,6 @@ function stageConnectorWrapper(connector) {
|
|
|
197867
197936
|
stagedBinDirs.set(cacheKey, binDir);
|
|
197868
197937
|
return link;
|
|
197869
197938
|
}
|
|
197870
|
-
function clearLoginShellShadow(connector) {
|
|
197871
|
-
const commandName = connector.commandName;
|
|
197872
|
-
if (!commandName) return [];
|
|
197873
|
-
const home2 = process.env["HOME"] ?? (0, import_node_os3.homedir)();
|
|
197874
|
-
if (!home2) return [];
|
|
197875
|
-
const moved = [];
|
|
197876
|
-
for (const parts of LOGIN_SHELL_FRONT_DIRS) {
|
|
197877
|
-
const dir = (0, import_node_path9.join)(home2, ...parts);
|
|
197878
|
-
if (!(0, import_node_fs8.existsSync)(dir)) continue;
|
|
197879
|
-
const target = (0, import_node_path9.join)(dir, commandName);
|
|
197880
|
-
try {
|
|
197881
|
-
(0, import_node_fs8.lstatSync)(target);
|
|
197882
|
-
} catch {
|
|
197883
|
-
continue;
|
|
197884
|
-
}
|
|
197885
|
-
if (isOasisWrapperPath(target)) continue;
|
|
197886
|
-
const backup = (0, import_node_path9.join)(dir, `${commandName}${DISPLACED_SUFFIX}`);
|
|
197887
|
-
const dest = (0, import_node_fs8.existsSync)(backup) || safeLstat(backup) ? `${backup}.${Date.now()}` : backup;
|
|
197888
|
-
try {
|
|
197889
|
-
(0, import_node_fs8.renameSync)(target, dest);
|
|
197890
|
-
moved.push({ from: target, to: dest });
|
|
197891
|
-
} catch {
|
|
197892
|
-
continue;
|
|
197893
|
-
}
|
|
197894
|
-
}
|
|
197895
|
-
return moved;
|
|
197896
|
-
}
|
|
197897
|
-
function safeLstat(p2) {
|
|
197898
|
-
try {
|
|
197899
|
-
(0, import_node_fs8.lstatSync)(p2);
|
|
197900
|
-
return true;
|
|
197901
|
-
} catch {
|
|
197902
|
-
return false;
|
|
197903
|
-
}
|
|
197904
|
-
}
|
|
197905
197939
|
function isStagedWrapperUsable(link) {
|
|
197906
197940
|
try {
|
|
197907
197941
|
(0, import_node_fs8.lstatSync)(link);
|
|
@@ -197910,7 +197944,7 @@ function isStagedWrapperUsable(link) {
|
|
|
197910
197944
|
}
|
|
197911
197945
|
return (0, import_node_fs8.existsSync)(link);
|
|
197912
197946
|
}
|
|
197913
|
-
var import_node_fs8, import_node_os3, import_node_path9, stagedBinDirs
|
|
197947
|
+
var import_node_fs8, import_node_os3, import_node_path9, stagedBinDirs;
|
|
197914
197948
|
var init_stage = __esm({
|
|
197915
197949
|
"../connectors/src/_base/stage.ts"() {
|
|
197916
197950
|
"use strict";
|
|
@@ -197919,8 +197953,6 @@ var init_stage = __esm({
|
|
|
197919
197953
|
import_node_path9 = require("node:path");
|
|
197920
197954
|
init_wrapper_assets();
|
|
197921
197955
|
stagedBinDirs = /* @__PURE__ */ new Map();
|
|
197922
|
-
LOGIN_SHELL_FRONT_DIRS = [[".local", "bin"], ["bin"]];
|
|
197923
|
-
DISPLACED_SUFFIX = ".oasis-displaced";
|
|
197924
197956
|
}
|
|
197925
197957
|
});
|
|
197926
197958
|
|
|
@@ -201952,19 +201984,12 @@ async function prepareConnectorsForJob(job, deps) {
|
|
|
201952
201984
|
localWrappers.push(staged);
|
|
201953
201985
|
status.wrapperReady = true;
|
|
201954
201986
|
}
|
|
201955
|
-
const moved = clearLoginShellShadow(connector);
|
|
201956
|
-
for (const m2 of moved) {
|
|
201957
|
-
log(
|
|
201958
|
-
"[node-connectors]",
|
|
201959
|
-
`${slug6}: \u632A\u5F00\u767B\u5F55 shell \u906E\u6321 ${m2.from} \u2192 ${m2.to}\uFF08$HOME/.local/bin \u4F1A\u88AB ~/.profile \u63D2\u5230 PATH \u6700\u524D\uFF0C\u538B\u8FC7\u6CE8\u5165\u7684 wrapper\uFF1B\u6539\u540D\u4E0D\u5220\u9664\uFF0Cwrapper \u89E3\u6790\u94FE\u6700\u540E\u4E00\u6863\u4ECD\u80FD\u6361\u56DE\u5B83\uFF09`
|
|
201960
|
-
);
|
|
201961
|
-
}
|
|
201962
201987
|
const shadow = loginShellShadow(connector.commandName);
|
|
201963
201988
|
if (shadow) {
|
|
201964
201989
|
status.shadowedBy = shadow;
|
|
201965
201990
|
log(
|
|
201966
201991
|
"[node-connectors]",
|
|
201967
|
-
`\u26A0 ${slug6}: creds + wrapper \u5DF2\u843D\u5728\u672C\u673A\uFF0C\u4F46 **${shadow} \
|
|
201992
|
+
`\u26A0 ${slug6}: creds + wrapper \u5DF2\u843D\u5728\u672C\u673A\uFF0C\u4F46 **${shadow} \u4F1A\u5728\u767B\u5F55 shell \u91CC\u6321\u4F4F wrapper**\u2014\u2014Ubuntu \u7684 ~/.profile \u628A $HOME/.local/bin \u524D\u7F6E\u5230 PATH \u6700\u524D\u3002agent \u4E00\u65E6\u7528 \`bash -lc\` \u8C03 ${connector.commandName}\uFF0C\u8D70\u5230\u7684\u662F\u90A3\u4E2A\u5BBF\u4E3B\u526F\u672C\u3001\u914D\u7F6E\u76EE\u5F55\u53C8\u88AB\u9694\u79BB\u6210\u7A7A\u7684\uFF0C\u7ED3\u679C\u5C31\u662F\u300C\u672A\u914D\u7F6E\u300D\u3002`
|
|
201968
201993
|
);
|
|
201969
201994
|
} else {
|
|
201970
201995
|
log("[node-connectors]", `${slug6}: creds + wrapper \u5DF2\u843D\u5728\u672C\u673A`);
|
|
@@ -205876,13 +205901,22 @@ async function startOasisServer(opts) {
|
|
|
205876
205901
|
if (url.pathname === "/api/chat/attachments" && req.method === "POST" && opts.uploadChatAttachment) {
|
|
205877
205902
|
try {
|
|
205878
205903
|
const body2 = JSON.parse(rawBody);
|
|
205879
|
-
if (typeof body2.contentBase64 !== "string"
|
|
205880
|
-
const MAX_BASE64_LEN = Math.ceil(CHAT_ATTACHMENT_MAX_BYTES
|
|
205904
|
+
if (typeof body2.contentBase64 !== "string") throw new Error("\u7F3A\u5C11 contentBase64");
|
|
205905
|
+
const MAX_BASE64_LEN = 4 * Math.ceil(CHAT_ATTACHMENT_MAX_BYTES / 3);
|
|
205881
205906
|
if (body2.contentBase64.length > MAX_BASE64_LEN) {
|
|
205882
205907
|
res.writeHead(413, { "content-type": "application/json" });
|
|
205883
205908
|
res.end(JSON.stringify({ error: { code: "ATTACHMENT_TOO_LARGE", message: `\u9644\u4EF6\u8D85\u8FC7 ${CHAT_ATTACHMENT_MAX_BYTES / 1024 / 1024}MB \u4E0A\u9650` } }));
|
|
205884
205909
|
return;
|
|
205885
205910
|
}
|
|
205911
|
+
if (body2.contentBase64.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/.test(body2.contentBase64)) {
|
|
205912
|
+
throw new Error("\u9644\u4EF6\u7F16\u7801\u65E0\u6548\uFF0C\u8BF7\u91CD\u65B0\u9009\u62E9\u6587\u4EF6");
|
|
205913
|
+
}
|
|
205914
|
+
if (Buffer.from(body2.contentBase64, "base64").byteLength > CHAT_ATTACHMENT_MAX_BYTES) {
|
|
205915
|
+
res.writeHead(413, { "content-type": "application/json" }).end(JSON.stringify({
|
|
205916
|
+
error: { code: "ATTACHMENT_TOO_LARGE", message: `\u9644\u4EF6\u8D85\u8FC7 ${CHAT_ATTACHMENT_MAX_BYTES / 1024 / 1024}MB \u4E0A\u9650` }
|
|
205917
|
+
}));
|
|
205918
|
+
return;
|
|
205919
|
+
}
|
|
205886
205920
|
const out = await opts.uploadChatAttachment({
|
|
205887
205921
|
contentBase64: body2.contentBase64,
|
|
205888
205922
|
...typeof body2.contentType === "string" ? { contentType: body2.contentType } : {},
|
|
@@ -211505,7 +211539,7 @@ var init_service4 = __esm({
|
|
|
211505
211539
|
}
|
|
211506
211540
|
};
|
|
211507
211541
|
ProjectsService = class {
|
|
211508
|
-
constructor(projects, artifacts, kernel, oplog, actorNames, blobs, actorDirectory, resolveActorContext, loadActorResolver) {
|
|
211542
|
+
constructor(projects, artifacts, kernel, oplog, actorNames, blobs, actorDirectory, resolveActorContext, loadActorResolver, listChatFiles) {
|
|
211509
211543
|
this.projects = projects;
|
|
211510
211544
|
this.artifacts = artifacts;
|
|
211511
211545
|
this.kernel = kernel;
|
|
@@ -211515,6 +211549,7 @@ var init_service4 = __esm({
|
|
|
211515
211549
|
this.actorDirectory = actorDirectory;
|
|
211516
211550
|
this.resolveActorContext = resolveActorContext;
|
|
211517
211551
|
this.loadActorResolver = loadActorResolver;
|
|
211552
|
+
this.listChatFiles = listChatFiles;
|
|
211518
211553
|
}
|
|
211519
211554
|
projectCreatedHandler;
|
|
211520
211555
|
onProjectNameChanged;
|
|
@@ -212102,6 +212137,18 @@ var init_service4 = __esm({
|
|
|
212102
212137
|
});
|
|
212103
212138
|
}
|
|
212104
212139
|
const files = await this.collectProjectFiles(projectId2);
|
|
212140
|
+
const existingFiles = /* @__PURE__ */ new Set([
|
|
212141
|
+
...items.filter((item) => item.blobRef).map((item) => `${item.name}\0${item.blobRef}`),
|
|
212142
|
+
...files.map((file) => `${file.name}\0${file.blobId}`)
|
|
212143
|
+
]);
|
|
212144
|
+
if (this.listChatFiles && !isUncategorizedProjectId(projectId2)) {
|
|
212145
|
+
for (const file of await this.listChatFiles(projectId2)) {
|
|
212146
|
+
const key = `${file.name}\0${file.blobId}`;
|
|
212147
|
+
if (existingFiles.has(key)) continue;
|
|
212148
|
+
existingFiles.add(key);
|
|
212149
|
+
files.push(file);
|
|
212150
|
+
}
|
|
212151
|
+
}
|
|
212105
212152
|
for (const file of files) {
|
|
212106
212153
|
const path41 = typeof file.path === "string" && file.path.trim() ? file.path : void 0;
|
|
212107
212154
|
if (path41) emitFolder(dirname24(path41), file.uploadedAt);
|
|
@@ -212778,7 +212825,15 @@ var init_service4 = __esm({
|
|
|
212778
212825
|
* 亲手提交过至少一版」。这是仓库里唯一一条真实存在的「产物 ↔ 人」关系;
|
|
212779
212826
|
* 「谁 own 这个节点」不用(节点 owner 是**派给谁**,派了没干完的也会被算成产出,那是假数据)。
|
|
212780
212827
|
*
|
|
212781
|
-
*
|
|
212828
|
+
* **空轮不算产出**(ADR 0539 补记):内核把**每一轮执行**都投影成一版 revision,这一轮一个产出文件
|
|
212829
|
+
* 都没有时 bridge 如实给 `contentKind="empty"`(运行中占位 / 被限流打死的空跑 / 只留结论没产正文,
|
|
212830
|
+
* 见 `bridge-readmodel.workToRevision` 与 ADR-0134)。那种版本这里一律跳过——它不是「他交了什么」,
|
|
212831
|
+
* 展示层拿到只会得到一行没有大小、点开写着「还没有可预览的正文」的空行。
|
|
212832
|
+
* 项目页「相关文件」早就不列这类轮次(`collectEngineFilesForProject` 的
|
|
212833
|
+
* `latestAcceptId` / `cancelledAt` / `arts.length === 0` 三道闸),本栏此前漏了这条口径。
|
|
212834
|
+
*
|
|
212835
|
+
* 于是 `revisionCount` 记的是**他交付过几版**、`latestRevisionId`/`updatedAt` 取**他最近一次真的
|
|
212836
|
+
* 交了东西的那一版**;一版都没交过内容的产物整条不出现。
|
|
212782
212837
|
*
|
|
212783
212838
|
* 数据同 `artifactDetail`:从 `kernel.model` 现算投影(新引擎 oplog 已退役、派生 store 恒空),
|
|
212784
212839
|
* 不读 `artifact_revisions` 表——读那张表在新引擎上永远是空列表。
|
|
@@ -212796,6 +212851,7 @@ var init_service4 = __esm({
|
|
|
212796
212851
|
const byArtifact = /* @__PURE__ */ new Map();
|
|
212797
212852
|
for (const revision of projection.revisions) {
|
|
212798
212853
|
if (revision.actorId !== actorId) continue;
|
|
212854
|
+
if (isEmptyContent(this.kernel.model.revisions.get(revision.revisionId)?.contentKind)) continue;
|
|
212799
212855
|
const artifact = artifactById.get(revision.artifactId);
|
|
212800
212856
|
if (!artifact) continue;
|
|
212801
212857
|
const prev = byArtifact.get(revision.artifactId);
|
|
@@ -212838,8 +212894,10 @@ var init_service4 = __esm({
|
|
|
212838
212894
|
* 同一个 {@link contentByteSize}**,不另写一套判据):装箱单摊成每个物理文件一行,
|
|
212839
212895
|
* 其余(inline-blob / external-pin / 装箱单解析失败)整份产物一行。
|
|
212840
212896
|
*
|
|
212841
|
-
*
|
|
212842
|
-
*
|
|
212897
|
+
* 取哪一版:**他自己最近交付过内容的那一版**(`latestRevisionId`,空轮已在
|
|
212898
|
+
* {@link listActorArtifacts} 里滤掉),不是产物的 current head——这一栏回答的是「他交了什么」,
|
|
212899
|
+
* 拿别人后来覆盖的版本冒充他的产出就是假数据。该版本 id 随行发给前端(`revisionId`),
|
|
212900
|
+
* 预览栏据它定位同一版:行与预览必须指着同一个东西,否则会出现「行上有 20 KB、点开说没有正文」。
|
|
212843
212901
|
*/
|
|
212844
212902
|
async listActorFiles(actorId) {
|
|
212845
212903
|
const artifacts = await this.listActorArtifacts(actorId);
|
|
@@ -212851,6 +212909,7 @@ var init_service4 = __esm({
|
|
|
212851
212909
|
const base = {
|
|
212852
212910
|
artifactId: item.artifactId,
|
|
212853
212911
|
projectId: item.projectId,
|
|
212912
|
+
revisionId: item.latestRevisionId,
|
|
212854
212913
|
type: item.type,
|
|
212855
212914
|
updatedAt: item.updatedAt,
|
|
212856
212915
|
...contentKind ? { contentKind } : {},
|
|
@@ -220169,6 +220228,20 @@ ${input.description}
|
|
|
220169
220228
|
};
|
|
220170
220229
|
});
|
|
220171
220230
|
}
|
|
220231
|
+
/**
|
|
220232
|
+
* 这一行变量是谁建的(子 PRD《密钥管理》§1 的权限判据)。**只读元数据、不解密**——
|
|
220233
|
+
* `listVariables()` 会把每一行都解一遍出掩码,写路径上没必要付那个钱。
|
|
220234
|
+
*
|
|
220235
|
+
* 返回 undefined 有两种含义,调用方按「放行」处理:行不存在(新建),
|
|
220236
|
+
* 或行是 2026-09-10 之前落的(那时还没有 created_by 这一格)。
|
|
220237
|
+
*/
|
|
220238
|
+
async variableCreatedBy(key, selector = {}) {
|
|
220239
|
+
const rows = await this.opts.store.listVariables();
|
|
220240
|
+
const hit = rows.find(
|
|
220241
|
+
(r) => r.key === key && (r.actorId ?? "") === (selector.actorId ?? "") && (r.projectId ?? "") === (selector.projectId ?? "")
|
|
220242
|
+
);
|
|
220243
|
+
return hit?.createdBy;
|
|
220244
|
+
}
|
|
220172
220245
|
async revealVariable(key, actorId) {
|
|
220173
220246
|
const ct = await this.opts.store.getVariableCiphertext(key, actorId);
|
|
220174
220247
|
if (ct === null) return null;
|
|
@@ -221954,6 +222027,17 @@ function actorsDomain(opts) {
|
|
|
221954
222027
|
);
|
|
221955
222028
|
}
|
|
221956
222029
|
};
|
|
222030
|
+
const requireSecretOwner = async (req, service, key, selector = {}) => {
|
|
222031
|
+
const owner = await service.variableCreatedBy(key, selector);
|
|
222032
|
+
if (!owner || owner === req.auth.actor) return;
|
|
222033
|
+
const manager = opts.isCompanyManager ? await opts.isCompanyManager(req.auth.companyId ?? "", req.auth.actor).catch(() => false) : false;
|
|
222034
|
+
if (manager) return;
|
|
222035
|
+
throw new ApiError(
|
|
222036
|
+
403,
|
|
222037
|
+
"SECRET_NOT_OWNED",
|
|
222038
|
+
"\u8FD9\u4EFD\u5BC6\u94A5\u7531\u522B\u4EBA\u521B\u5EFA\uFF0C\u53EA\u6709\u521B\u5EFA\u8005\u672C\u4EBA\u6216\u7EC4\u7EC7\u7BA1\u7406\u8005\u53EF\u4EE5\u4FEE\u6539 / \u5220\u9664"
|
|
222039
|
+
);
|
|
222040
|
+
};
|
|
221957
222041
|
const auditVariableChange = async (req, kind, variableKey, targetScope) => {
|
|
221958
222042
|
await opts.credentialAudit?.({
|
|
221959
222043
|
kind,
|
|
@@ -222008,6 +222092,7 @@ function actorsDomain(opts) {
|
|
|
222008
222092
|
);
|
|
222009
222093
|
}
|
|
222010
222094
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
222095
|
+
await requireSecretOwner(req, service, b2.key, scope === "project" ? { projectId: b2.projectId } : {});
|
|
222011
222096
|
await service.putVariable({
|
|
222012
222097
|
key: b2.key,
|
|
222013
222098
|
value: b2.value,
|
|
@@ -222035,6 +222120,7 @@ function actorsDomain(opts) {
|
|
|
222035
222120
|
requireVariableManager(req);
|
|
222036
222121
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
222037
222122
|
const projectId2 = req.query.get("projectId") ?? void 0;
|
|
222123
|
+
await requireSecretOwner(req, service, req.params.key, projectId2 ? { projectId: projectId2 } : {});
|
|
222038
222124
|
await service.deleteVariable(
|
|
222039
222125
|
req.params.key,
|
|
222040
222126
|
void 0,
|
|
@@ -222082,6 +222168,7 @@ function actorsDomain(opts) {
|
|
|
222082
222168
|
);
|
|
222083
222169
|
}
|
|
222084
222170
|
}
|
|
222171
|
+
await requireSecretOwner(req, service, b2.key, { actorId });
|
|
222085
222172
|
await service.putVariable({
|
|
222086
222173
|
key: b2.key,
|
|
222087
222174
|
value: b2.value,
|
|
@@ -222102,6 +222189,7 @@ function actorsDomain(opts) {
|
|
|
222102
222189
|
router.delete("/api/actors/:id/variables/:key", async (req) => {
|
|
222103
222190
|
requireVariableManager(req);
|
|
222104
222191
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
222192
|
+
await requireSecretOwner(req, service, req.params.key, { actorId: req.params.id });
|
|
222105
222193
|
await service.deleteVariable(req.params.key, req.params.id);
|
|
222106
222194
|
await auditVariableChange(req, "credential_delete", req.params.key, `personal:${req.params.id}`);
|
|
222107
222195
|
return { status: 200, body: { ok: true } };
|
|
@@ -222910,7 +222998,7 @@ function createActorsDomain(opts) {
|
|
|
222910
222998
|
return {
|
|
222911
222999
|
service: defaultCtx.service,
|
|
222912
223000
|
resolveCtx,
|
|
222913
|
-
register: actorsDomain({ resolveCtx, ...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.credentialAudit ? { credentialAudit: opts.credentialAudit } : {}, ...opts.readCredentialAudit ? { readCredentialAudit: opts.readCredentialAudit } : {}, ...opts.credentialRevealLimits ? { credentialRevealLimits: opts.credentialRevealLimits } : {}, ...opts.skillMarket ? { skillMarket: opts.skillMarket } : {}, ...opts.resolveNodeTenancy ? { resolveNodeTenancy: opts.resolveNodeTenancy } : {} })
|
|
223001
|
+
register: actorsDomain({ resolveCtx, ...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.isCompanyManager ? { isCompanyManager: opts.isCompanyManager } : {}, ...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 } : {} })
|
|
222914
223002
|
};
|
|
222915
223003
|
}
|
|
222916
223004
|
var import_node_crypto49;
|
|
@@ -223267,6 +223355,7 @@ ${errs.join("\n")}`);
|
|
|
223267
223355
|
id: item.id,
|
|
223268
223356
|
artifact_id: item.artifactId,
|
|
223269
223357
|
project_id: item.projectId,
|
|
223358
|
+
revision_id: item.revisionId,
|
|
223270
223359
|
type: item.type,
|
|
223271
223360
|
name: item.name,
|
|
223272
223361
|
file_path: item.filePath,
|
|
@@ -223942,6 +224031,15 @@ var init_routes5 = __esm({
|
|
|
223942
224031
|
}
|
|
223943
224032
|
});
|
|
223944
224033
|
|
|
224034
|
+
// ../server/src/domains/collab/activity-notice.ts
|
|
224035
|
+
var NOTICE_TITLE;
|
|
224036
|
+
var init_activity_notice = __esm({
|
|
224037
|
+
"../server/src/domains/collab/activity-notice.ts"() {
|
|
224038
|
+
"use strict";
|
|
224039
|
+
NOTICE_TITLE = "\u53D8\u66F4\u901A\u77E5";
|
|
224040
|
+
}
|
|
224041
|
+
});
|
|
224042
|
+
|
|
223945
224043
|
// ../server/src/domains/collab/review-activity.ts
|
|
223946
224044
|
function reviewCardId(targetWorkId, reviewerActorId) {
|
|
223947
224045
|
return `${REVIEW_CARD_PREFIX}${encodeURIComponent(targetWorkId)}:${encodeURIComponent(reviewerActorId)}`;
|
|
@@ -224090,35 +224188,18 @@ var init_review_activity = __esm({
|
|
|
224090
224188
|
|
|
224091
224189
|
// ../server/src/domains/collab/review-requirement-activity.ts
|
|
224092
224190
|
function reviewRequirementActivity(snap, events, ref2) {
|
|
224093
|
-
const previous3 = /* @__PURE__ */ new Map();
|
|
224094
224191
|
const titles = new Map(snap.nodes.map((n) => [n.id, n.title]));
|
|
224095
224192
|
const cards = [];
|
|
224096
224193
|
const label = (r) => `${ref2(r.reviewerActorId).name || "\u672A\u547D\u540D\u5BA1\u6838\u4EBA"}${r.source === "closure" ? "\uFF08\u7ED3\u6848\u5BA1\u6838\uFF09" : ""}`;
|
|
224097
|
-
const names = (rows) => [...new Set(rows.map(label))].join("\u3001")
|
|
224194
|
+
const names = (rows) => [...new Set(rows.map(label))].join("\u3001");
|
|
224195
|
+
const submitter = (id) => ref2(id).name?.trim() || "\u672A\u547D\u540D\u6210\u5458";
|
|
224196
|
+
const sentence = (id, nodeTitle, rows) => rows.length ? `${submitter(id)} \u66F4\u6539\u300A${nodeTitle}\u300B\u8282\u70B9\u7684\u5BA1\u6838\u4EBA\u4E3A ${names(rows)}\u3002` : `${submitter(id)} \u6E05\u7A7A\u4E86\u300A${nodeTitle}\u300B\u8282\u70B9\u7684\u5BA1\u6838\u4EBA\u3002`;
|
|
224098
224197
|
for (const rec of [...events].sort((a, b2) => a.seq - b2.seq)) {
|
|
224099
224198
|
if (rec.status === "pending" || rec.status === "failed") continue;
|
|
224100
224199
|
const e = rec.event;
|
|
224101
|
-
if (e.kind === "plan.changed") {
|
|
224102
|
-
for (const node2 of e.addNodes ?? []) previous3.set(node2.id, node2.reviewers ?? []);
|
|
224103
|
-
for (const id of e.removeNodes ?? []) previous3.delete(id);
|
|
224104
|
-
continue;
|
|
224105
|
-
}
|
|
224106
|
-
if (e.kind === "plan.add_node") {
|
|
224107
|
-
previous3.set(e.nodeId, e.reviewers ?? []);
|
|
224108
|
-
continue;
|
|
224109
|
-
}
|
|
224110
224200
|
if (e.kind !== "plan.update_review_requirements") continue;
|
|
224111
|
-
|
|
224112
|
-
const after = e.reviewers;
|
|
224113
|
-
const beforeKeys = new Set(before?.map(requirementKey));
|
|
224114
|
-
const afterKeys = new Set(after.map(requirementKey));
|
|
224115
|
-
const added = before ? after.filter((r) => !beforeKeys.has(requirementKey(r))) : [];
|
|
224116
|
-
const removed = before?.filter((r) => !afterKeys.has(requirementKey(r))) ?? [];
|
|
224201
|
+
if (!isAuthoredChange(rec)) continue;
|
|
224117
224202
|
const nodeTitle = titles.get(e.nodeId) || "\u5DF2\u79FB\u9664\u7684\u8282\u70B9";
|
|
224118
|
-
if (!isAuthoredChange(rec)) {
|
|
224119
|
-
previous3.set(e.nodeId, after);
|
|
224120
|
-
continue;
|
|
224121
|
-
}
|
|
224122
224203
|
cards.push({
|
|
224123
224204
|
id: `wo:${rec.seq}`,
|
|
224124
224205
|
seq: rec.seq,
|
|
@@ -224129,24 +224210,19 @@ function reviewRequirementActivity(snap, events, ref2) {
|
|
|
224129
224210
|
executor: ref2(rec.actorId),
|
|
224130
224211
|
...rec.handActorId ? { handActor: ref2(rec.handActorId) } : {},
|
|
224131
224212
|
phase: "done",
|
|
224132
|
-
|
|
224133
|
-
|
|
224134
|
-
...added.length ? [`\u65B0\u589E\uFF1A${names(added)}`] : [],
|
|
224135
|
-
...removed.length ? [`\u79FB\u9664\uFF1A${names(removed)}`] : [],
|
|
224136
|
-
`\u66F4\u65B0\u540E\uFF1A${names(after)}`
|
|
224137
|
-
].join("\n"),
|
|
224213
|
+
noticeTitle: NOTICE_TITLE,
|
|
224214
|
+
status: sentence(rec.actorId, nodeTitle, e.reviewers),
|
|
224138
224215
|
artifacts: [],
|
|
224139
224216
|
actions: []
|
|
224140
224217
|
});
|
|
224141
|
-
previous3.set(e.nodeId, after);
|
|
224142
224218
|
}
|
|
224143
224219
|
return cards;
|
|
224144
224220
|
}
|
|
224145
|
-
var
|
|
224221
|
+
var isAuthoredChange;
|
|
224146
224222
|
var init_review_requirement_activity = __esm({
|
|
224147
224223
|
"../server/src/domains/collab/review-requirement-activity.ts"() {
|
|
224148
224224
|
"use strict";
|
|
224149
|
-
|
|
224225
|
+
init_activity_notice();
|
|
224150
224226
|
isAuthoredChange = (rec) => rec.origin !== "apply" && rec.origin !== "effect" && !rec.actorId.startsWith("actor:system:");
|
|
224151
224227
|
}
|
|
224152
224228
|
});
|
|
@@ -224242,7 +224318,6 @@ function buildWorkorderActivity(input) {
|
|
|
224242
224318
|
return tail || nodeId;
|
|
224243
224319
|
};
|
|
224244
224320
|
const cardOfWork = /* @__PURE__ */ new Map();
|
|
224245
|
-
const latestCardOfNode = /* @__PURE__ */ new Map();
|
|
224246
224321
|
const executionCards = [];
|
|
224247
224322
|
const offTimeline = (w2) => isDispatchLayerFailure(w2.outcomeDetail) || w2.outcome === "completed" && statusOf2(w2) !== "success" && !artifactsByWork.get(w2.id)?.length;
|
|
224248
224323
|
const statusOf2 = (w2) => w2.status ?? (w2.outcome === "failed" ? "failed" : w2.outcome === "completed" ? "success" : "running");
|
|
@@ -224271,35 +224346,45 @@ function buildWorkorderActivity(input) {
|
|
|
224271
224346
|
works.sort((a, b2) => a.createdAt.localeCompare(b2.createdAt) || a.id.localeCompare(b2.id));
|
|
224272
224347
|
const interrupts = [...interruptsOfNode.get(nodeId) ?? []].sort();
|
|
224273
224348
|
const node2 = nodeById.get(nodeId);
|
|
224349
|
+
const nodeCancelledAt = node2?.cancelledAt ?? null;
|
|
224274
224350
|
const name = nodeName(nodeId);
|
|
224275
|
-
let
|
|
224351
|
+
let fold2 = null;
|
|
224276
224352
|
for (const [idx, w2] of works.entries()) {
|
|
224277
|
-
|
|
224278
|
-
|
|
224279
|
-
|
|
224280
|
-
|
|
224281
|
-
|
|
224282
|
-
|
|
224283
|
-
|
|
224284
|
-
|
|
224285
|
-
|
|
224286
|
-
|
|
224287
|
-
|
|
224288
|
-
|
|
224289
|
-
|
|
224290
|
-
|
|
224291
|
-
|
|
224292
|
-
|
|
224293
|
-
executionCards.push(card2);
|
|
224294
|
-
latestCardOfNode.set(nodeId, card2);
|
|
224353
|
+
const next = works[idx + 1];
|
|
224354
|
+
const artifacts = artifactsByWork.get(w2.id) ?? [];
|
|
224355
|
+
const st = statusOf2(w2);
|
|
224356
|
+
const interrupt = interrupts.find((t) => t >= w2.createdAt && (!next || t < next.createdAt));
|
|
224357
|
+
const removedHere = !!nodeCancelledAt && nodeCancelledAt >= w2.createdAt && (!next || nodeCancelledAt < next.createdAt);
|
|
224358
|
+
const reassigned = !!next && next.assigneeActorId !== w2.assigneeActorId;
|
|
224359
|
+
const killedByPlan = !!(w2.deadAt || w2.cancelledAt) && !!next && (reassigned || (next.nodeVersion ?? 0) > (w2.nodeVersion ?? 0));
|
|
224360
|
+
const failedRound = !w2.conclusion && !interrupt && !removedHere && !killedByPlan && (!!w2.deadAt || !!w2.cancelledAt || st === "failed" || st === "retry");
|
|
224361
|
+
if (failedRound && fold2) {
|
|
224362
|
+
fold2.traceWorkIds.push(w2.id);
|
|
224363
|
+
cardOfWork.set(w2.id, fold2);
|
|
224364
|
+
fold2.updatedAt = lastStampOf(w2);
|
|
224365
|
+
fold2.stuckReason = w2.outcomeDetail?.reason === "timeout" ? "timeout" : "failed";
|
|
224366
|
+
fold2.foldedRounds = (fold2.foldedRounds ?? 1) + 1;
|
|
224367
|
+
fold2.status = ACTIVITY_COPY.foldedFailures(nameOf(fold2.executorId), name, fold2.foldedRounds);
|
|
224368
|
+
continue;
|
|
224295
224369
|
}
|
|
224296
|
-
|
|
224370
|
+
fold2 = null;
|
|
224371
|
+
const card2 = {
|
|
224372
|
+
/* 卡 id = 这一轮的 workId(连败折叠时取第一轮,React key 与滚动锚点因此稳定)。 */
|
|
224373
|
+
id: `work:${w2.id}`,
|
|
224374
|
+
traceWorkIds: [w2.id],
|
|
224375
|
+
seq: 0,
|
|
224376
|
+
// 事件循环里按这一轮 work.create 的 seq 填
|
|
224377
|
+
at: w2.createdAt,
|
|
224378
|
+
updatedAt: lastStampOf(w2),
|
|
224379
|
+
nodeId,
|
|
224380
|
+
executorId: w2.assigneeActorId,
|
|
224381
|
+
phase: "running",
|
|
224382
|
+
status: ACTIVITY_COPY.working(name),
|
|
224383
|
+
artifacts,
|
|
224384
|
+
actions: []
|
|
224385
|
+
};
|
|
224386
|
+
executionCards.push(card2);
|
|
224297
224387
|
cardOfWork.set(w2.id, card2);
|
|
224298
|
-
card2.executorId = w2.assigneeActorId;
|
|
224299
|
-
card2.updatedAt = lastStampOf(w2);
|
|
224300
|
-
card2.artifacts = artifactsByWork.get(w2.id) ?? card2.artifacts;
|
|
224301
|
-
delete card2.openWorkId;
|
|
224302
|
-
delete card2.stuckReason;
|
|
224303
224388
|
if (w2.conclusion) {
|
|
224304
224389
|
card2.phase = "done";
|
|
224305
224390
|
if (rootBriefNodeIds.has(nodeId)) {
|
|
@@ -224315,32 +224400,21 @@ function buildWorkorderActivity(input) {
|
|
|
224315
224400
|
card2.status = awaits ? ACTIVITY_COPY.doneAwaitingReview(name) : ACTIVITY_COPY.done(name);
|
|
224316
224401
|
}
|
|
224317
224402
|
}
|
|
224318
|
-
|
|
224319
|
-
continue;
|
|
224320
|
-
}
|
|
224321
|
-
const next = works[idx + 1];
|
|
224322
|
-
const interrupt = interrupts.find((t) => t >= w2.createdAt && (!next || t < next.createdAt));
|
|
224323
|
-
if (interrupt) {
|
|
224403
|
+
} else if (interrupt) {
|
|
224324
224404
|
card2.phase = "stuck";
|
|
224325
224405
|
card2.status = ACTIVITY_COPY.interruptedByIssue(name);
|
|
224326
224406
|
if (interrupt > card2.updatedAt) card2.updatedAt = interrupt;
|
|
224327
|
-
|
|
224328
|
-
continue;
|
|
224329
|
-
}
|
|
224330
|
-
const stuckKind = w2.outcomeDetail?.reason === "timeout" ? "timeout" : "failed";
|
|
224331
|
-
const st = statusOf2(w2);
|
|
224332
|
-
if (w2.deadAt || w2.cancelledAt) {
|
|
224407
|
+
} else if (removedHere || killedByPlan) {
|
|
224333
224408
|
card2.phase = "stuck";
|
|
224334
|
-
card2.
|
|
224335
|
-
card2.
|
|
224336
|
-
|
|
224409
|
+
card2.status = removedHere ? ACTIVITY_COPY.interruptedByNodeRemoved(name) : reassigned ? ACTIVITY_COPY.interruptedByReassign(name, nameOf(next.assigneeActorId)) : ACTIVITY_COPY.interruptedByPlanChange(name);
|
|
224410
|
+
if (!removedHere && !reassigned) card2.planChangeUnnamed = true;
|
|
224411
|
+
if (removedHere && nodeCancelledAt > card2.updatedAt) card2.updatedAt = nodeCancelledAt;
|
|
224412
|
+
} else if (failedRound) {
|
|
224413
|
+
const stuckKind = w2.outcomeDetail?.reason === "timeout" ? "timeout" : "failed";
|
|
224337
224414
|
card2.phase = "stuck";
|
|
224338
224415
|
card2.stuckReason = stuckKind;
|
|
224339
|
-
card2.status = stuckKind === "timeout" ? ACTIVITY_COPY.timedOut(nameOf(card2.executorId)) : ACTIVITY_COPY.failed(nameOf(card2.executorId));
|
|
224340
|
-
|
|
224341
|
-
card2.phase = "stuck";
|
|
224342
|
-
card2.stuckReason = stuckKind;
|
|
224343
|
-
card2.status = ACTIVITY_COPY.awaitingRedispatch(nameOf(card2.executorId), name);
|
|
224416
|
+
card2.status = w2.deadAt || w2.cancelledAt ? ACTIVITY_COPY.killed(name) : st === "retry" ? ACTIVITY_COPY.awaitingRedispatch(nameOf(card2.executorId), name) : stuckKind === "timeout" ? ACTIVITY_COPY.timedOut(nameOf(card2.executorId)) : ACTIVITY_COPY.failed(nameOf(card2.executorId));
|
|
224417
|
+
fold2 = card2;
|
|
224344
224418
|
} else if (w2.endedAt) {
|
|
224345
224419
|
card2.phase = "running";
|
|
224346
224420
|
card2.status = ACTIVITY_COPY.awaitingConclude(name);
|
|
@@ -224361,17 +224435,28 @@ function buildWorkorderActivity(input) {
|
|
|
224361
224435
|
if (rec.handActorId) d.handActorId = rec.handActorId;
|
|
224362
224436
|
return d;
|
|
224363
224437
|
};
|
|
224364
|
-
const
|
|
224438
|
+
const cardOpenAt = (nodeId, at) => {
|
|
224439
|
+
const list2 = worksOfNode.get(nodeId);
|
|
224440
|
+
if (!list2) return void 0;
|
|
224441
|
+
let hit;
|
|
224442
|
+
for (const w2 of list2) {
|
|
224443
|
+
if (w2.createdAt > at) break;
|
|
224444
|
+
hit = w2;
|
|
224445
|
+
}
|
|
224446
|
+
return hit ? cardOfWork.get(hit.id) : void 0;
|
|
224447
|
+
};
|
|
224448
|
+
const woCard = (rec, status, opts = {}) => {
|
|
224365
224449
|
standalone.push({
|
|
224366
224450
|
id: `wo:${rec.seq}`,
|
|
224367
224451
|
seq: rec.seq,
|
|
224368
224452
|
at: rec.createdAt,
|
|
224369
224453
|
updatedAt: rec.createdAt,
|
|
224370
|
-
executorId,
|
|
224454
|
+
executorId: rec.actorId,
|
|
224371
224455
|
...rec.handActorId ? { handActorId: rec.handActorId } : {},
|
|
224372
|
-
phase,
|
|
224456
|
+
phase: "done",
|
|
224457
|
+
...opts.notice ? { noticeTitle: NOTICE_TITLE } : {},
|
|
224373
224458
|
status,
|
|
224374
|
-
...detail ? { detail } : {},
|
|
224459
|
+
...opts.detail ? { detail: opts.detail } : {},
|
|
224375
224460
|
artifacts: [],
|
|
224376
224461
|
actions: []
|
|
224377
224462
|
});
|
|
@@ -224384,20 +224469,29 @@ function buildWorkorderActivity(input) {
|
|
|
224384
224469
|
case "plan.changed": {
|
|
224385
224470
|
break;
|
|
224386
224471
|
}
|
|
224472
|
+
/* 暂停 / 恢复是**人对这单做的事**,不是某一轮执行——走「变更通知」那套卡面(帧 `2874:1189`)。
|
|
224473
|
+
此前它们沿用执行卡的标题模板,卡面第一行被拼成「{谁} 已完成」(`ACTIVITY_PHASE_LABEL.done`),
|
|
224474
|
+
第二行才是「{谁}已暂停任务。」——标题和正文说的不是同一件事,而「已完成」在这一拍根本
|
|
224475
|
+
没有所指(暂停不是完成)。 */
|
|
224387
224476
|
case "workorder.paused":
|
|
224388
|
-
woCard(rec,
|
|
224477
|
+
woCard(rec, ACTIVITY_COPY.paused(nameOf(rec.actorId)), { notice: true, detail: str4(ev.reason) });
|
|
224389
224478
|
break;
|
|
224390
224479
|
case "workorder.resumed":
|
|
224391
|
-
woCard(rec,
|
|
224480
|
+
woCard(rec, ACTIVITY_COPY.resumedWorkorder(nameOf(rec.actorId)), { notice: true });
|
|
224392
224481
|
break;
|
|
224393
224482
|
case "workorder.meta_changed": {
|
|
224394
224483
|
const patch = ev.patch ?? {};
|
|
224395
224484
|
if (!("goal" in patch) && !("description" in patch)) break;
|
|
224396
|
-
woCard(rec,
|
|
224485
|
+
woCard(rec, ACTIVITY_COPY.goalChanged(nameOf(rec.actorId), managerName()));
|
|
224397
224486
|
break;
|
|
224398
224487
|
}
|
|
224399
224488
|
case "plan.update_spec": {
|
|
224400
|
-
|
|
224489
|
+
const nodeId = String(ev.nodeId ?? "");
|
|
224490
|
+
const d = cardOpenAt(nodeId, rec.createdAt);
|
|
224491
|
+
if (d?.planChangeUnnamed) {
|
|
224492
|
+
d.status = ACTIVITY_COPY.interruptedBySpecChange(nameOf(rec.actorId), nodeName(nodeId));
|
|
224493
|
+
delete d.planChangeUnnamed;
|
|
224494
|
+
}
|
|
224401
224495
|
break;
|
|
224402
224496
|
}
|
|
224403
224497
|
/* ── 执行(work)──────────────────────────────────────────────
|
|
@@ -224677,10 +224771,10 @@ function buildWorkorderActivity(input) {
|
|
|
224677
224771
|
case "plan.node_retry": {
|
|
224678
224772
|
const nodeId = String(ev.nodeId ?? "");
|
|
224679
224773
|
const by = str4(ev.by) ?? rec.actorId;
|
|
224680
|
-
const target =
|
|
224681
|
-
if (!target || target.phase !== "stuck") break;
|
|
224774
|
+
const target = cardOpenAt(nodeId, rec.createdAt);
|
|
224775
|
+
if (!target || target.phase !== "stuck" || !target.stuckReason) break;
|
|
224682
224776
|
touch(target, rec);
|
|
224683
|
-
target.status = target.stuckReason === "timeout" ? ACTIVITY_COPY.retriedAfterTimeout(nameOf(target.executorId), nameOf(by)) : ACTIVITY_COPY.retriedAfterFailure(nameOf(target.executorId), nameOf(by));
|
|
224777
|
+
target.status = target.foldedRounds && target.foldedRounds > 1 ? ACTIVITY_COPY.foldedFailuresRetried(nameOf(target.executorId), nodeName(nodeId), target.foldedRounds, nameOf(by)) : target.stuckReason === "timeout" ? ACTIVITY_COPY.retriedAfterTimeout(nameOf(target.executorId), nameOf(by)) : ACTIVITY_COPY.retriedAfterFailure(nameOf(target.executorId), nameOf(by));
|
|
224684
224778
|
break;
|
|
224685
224779
|
}
|
|
224686
224780
|
default:
|
|
@@ -224844,6 +224938,7 @@ function buildWorkorderActivity(input) {
|
|
|
224844
224938
|
...d.reviewWorkId ? { reviewWorkId: d.reviewWorkId, reviewers: d.reviewerIds?.map(ref2) } : {},
|
|
224845
224939
|
...d.handActorId ? { handActor: ref2(d.handActorId) } : {},
|
|
224846
224940
|
phase: d.phase,
|
|
224941
|
+
...d.noticeTitle ? { noticeTitle: d.noticeTitle } : {},
|
|
224847
224942
|
status: d.status,
|
|
224848
224943
|
...d.detail ? { detail: d.detail } : {},
|
|
224849
224944
|
...d.reviewNotes?.length ? { reviewNotes: d.reviewNotes } : {},
|
|
@@ -224865,13 +224960,13 @@ var init_activity2 = __esm({
|
|
|
224865
224960
|
"use strict";
|
|
224866
224961
|
init_src();
|
|
224867
224962
|
init_src4();
|
|
224963
|
+
init_activity_notice();
|
|
224868
224964
|
init_review_activity();
|
|
224869
224965
|
init_review_requirement_activity();
|
|
224870
224966
|
init_workorder_manager();
|
|
224871
224967
|
init_escalation_recipient();
|
|
224872
224968
|
ACTIVITY_EVENT_KINDS = [
|
|
224873
224969
|
"plan.changed",
|
|
224874
|
-
"plan.add_node",
|
|
224875
224970
|
"plan.update_review_requirements",
|
|
224876
224971
|
"plan.update_spec",
|
|
224877
224972
|
"plan.node_retry",
|
|
@@ -224945,7 +225040,39 @@ var init_activity2 = __esm({
|
|
|
224945
225040
|
*
|
|
224946
225041
|
* 不重复缺口卡那句「需要 @{协调者} 协助解决」:该找谁由缺口卡自己说,执行卡只说这一轮到此为止。
|
|
224947
225042
|
*/
|
|
225043
|
+
/**
|
|
225044
|
+
* **连败折叠**:同一节点上连续没跑成的 N 轮折成一张。不折叠的话 `ws:wo-6d588f8e` 的《隔离边界实现》
|
|
225045
|
+
* 会在时间线上连出 12 张,其中 9 张都是「执行失败。」——真正要给人看的是「这个节点一直没跑成」
|
|
225046
|
+
* 这一件事,逐轮的原因在轨迹抽屉里(`traceWorkIds` 收齐全部 N 轮,一轮不少)。
|
|
225047
|
+
*/
|
|
225048
|
+
foldedFailures: (executor, node2, n) => `${executor} \u8FDE\u7EED ${n} \u6B21\u6CA1\u8DD1\u6210\u300A${node2}\u300B\u3002`,
|
|
225049
|
+
/** 折叠卡上补「谁按的重试」——不把「连续 N 次」换成单轮那句。 */
|
|
225050
|
+
foldedFailuresRetried: (executor, node2, n, by) => `${executor} \u8FDE\u7EED ${n} \u6B21\u6CA1\u8DD1\u6210\u300A${node2}\u300B\uFF0C${by}\u5DF2\u4ECB\u5165\u91CD\u8BD5\u3002`,
|
|
224948
225051
|
interruptedByIssue: (node2) => `\u300A${node2}\u300B\u672C\u8F6E\u6267\u884C\u56E0\u5361\u70B9\u4E2D\u65AD\u3002`,
|
|
225052
|
+
/**
|
|
225053
|
+
* 这一轮**被计划变更打断**(P15)。与卡点中断同级:计划一动,这一轮就不再是「还在跑」,
|
|
225054
|
+
* 而是被引擎当场顶掉了——`plan.delete_node` 直接 `killLatestWork`;`plan.update_spec`(spec 真变)
|
|
225055
|
+
* 与 `plan.assign_actor`(换人)把 `node.version` 加一,scan 随即重派,`work.create` 自带
|
|
225056
|
+
* supersede 把在跑的这一轮翻成 dead。
|
|
225057
|
+
*
|
|
225058
|
+
* 此前这两条都不结束卡:删节点那档只落到 {@link killed}「本轮执行已终止」,不说是计划调整;
|
|
225059
|
+
* 改 spec / 改派那档**根本没有结局**——新一轮直接改写同一张卡,「中断」在页面上不存在,
|
|
225060
|
+
* 卡上署名还会换成新人(与 §2.1「一张卡只讲一个人的事」相抵)。
|
|
225061
|
+
*/
|
|
225062
|
+
interruptedByPlanChange: (node2) => `\u300A${node2}\u300B\u672C\u8F6E\u6267\u884C\u56E0\u8BA1\u5212\u8C03\u6574\u4E2D\u65AD\u3002`,
|
|
225063
|
+
/**
|
|
225064
|
+
* 计划变更里最常见的那一种:**有人改了任务说明**,在跑的这一轮因此被顶掉。
|
|
225065
|
+
*
|
|
225066
|
+
* 这句取代了原来那张独立的任务级卡「已确认任务说明更新,正在判断该修改的影响。」——两张卡讲的
|
|
225067
|
+
* 本来就是同一件事:计划动了、这一轮做不下去了。旧卡还有两个毛病:`phase` 写死 `running`,
|
|
225068
|
+
* 没有任何一拍能让它收口(`ws:wo-217a0909` 12:13 那两张就是这么永久停在「进行中」的);文案是
|
|
225069
|
+
* 一句没有主语也没有宾语的固定串,两次内容不同的修改渲染成两行一模一样的字。
|
|
225070
|
+
*/
|
|
225071
|
+
interruptedBySpecChange: (by, node2) => `${by} \u66F4\u65B0\u4E86\u4EFB\u52A1\u8BF4\u660E\uFF0C\u300A${node2}\u300B\u672C\u8F6E\u6267\u884C\u5230\u6B64\u4E2D\u65AD\u3002`,
|
|
225072
|
+
/** 换人那一档点破接手的人——卡到此为止,下一轮是新执行人的新卡。 */
|
|
225073
|
+
interruptedByReassign: (node2, next) => `\u300A${node2}\u300B\u672C\u8F6E\u6267\u884C\u56E0\u8BA1\u5212\u8C03\u6574\u4E2D\u65AD\uFF0C\u5DF2\u6539\u7531 ${next} \u63A5\u624B\u3002`,
|
|
225074
|
+
/** 节点被移出计划:这一轮再没有下文,也不会有新卡。 */
|
|
225075
|
+
interruptedByNodeRemoved: (node2) => `\u300A${node2}\u300B\u5DF2\u4ECE\u8BA1\u5212\u4E2D\u79FB\u9664\uFF0C\u672C\u8F6E\u6267\u884C\u4E2D\u65AD\u3002`,
|
|
224949
225076
|
/**
|
|
224950
225077
|
* 引擎判卷 success、`endedAt` 也写了,却始终没有 `work.conclude`:**交了稿没收口**。
|
|
224951
225078
|
* 如实说这一档,不冒充「正在处理」——后者把一轮早就结束的执行画成还在跑。
|
|
@@ -224982,7 +225109,6 @@ var init_activity2 = __esm({
|
|
|
224982
225109
|
paused: (actor) => `${actor}\u5DF2\u6682\u505C\u4EFB\u52A1\u3002`,
|
|
224983
225110
|
resumedWorkorder: (actor) => `${actor}\u5DF2\u6062\u590D\u4EFB\u52A1\u3002`,
|
|
224984
225111
|
goalChanged: (actor, manager) => `${actor}\u4FEE\u6539\u4E86\u4EFB\u52A1\u76EE\u6807\uFF0C\u9700\u8981 ${manager}\u91CD\u65B0\u8BC4\u4F30\u3002`,
|
|
224985
|
-
specConfirmed: "\u5DF2\u786E\u8BA4\u4EFB\u52A1\u8BF4\u660E\u66F4\u65B0\uFF0C\u6B63\u5728\u5224\u65AD\u8BE5\u4FEE\u6539\u7684\u5F71\u54CD\u3002",
|
|
224986
225112
|
handleEscalation: (target) => `${target} \u7684\u6267\u884C\u5F02\u5E38\u6301\u7EED\u672A\u89E3\u51B3\u3002`,
|
|
224987
225113
|
handledEscalation: (target) => `\u5DF2\u5904\u7406 ${target} \u7684\u6267\u884C\u5F02\u5E38\u3002`,
|
|
224988
225114
|
/**
|
|
@@ -225991,13 +226117,7 @@ function buildWaitingInbox(reviews, works, policy, nowIso, me, resolveActor) {
|
|
|
225991
226117
|
const isSelf = r.actorId === me;
|
|
225992
226118
|
const actorLabel = displayName(resolveActor, r.actorId);
|
|
225993
226119
|
if (r.status === "dead" || r.status === "exhausted") {
|
|
225994
|
-
out.push(isSelf ? card(kind, r, "urgent", start, `\u4F60\u7684${KIND_LABEL[kind]}\u5DF2\u4E2D\u6B62\uFF0C\u9700\u8981\u4F60\u4ECB\u5165\u91CD\u5F00`) : card(
|
|
225995
|
-
kind,
|
|
225996
|
-
r,
|
|
225997
|
-
"urgent",
|
|
225998
|
-
start,
|
|
225999
|
-
`\u8FD9\u4E00\u6B65\u7684${KIND_LABEL[kind]}\u5DF2\u4E2D\u6B62\uFF08${actorLabel} \u8FDE\u7EED\u5931\u8D25\u8D85\u9650\uFF09\u2014\u2014\u672C\u8F6E${KIND_LABEL[kind]}\u6536\u4E0D\u9F50\u3001\u8282\u70B9\u505C\u5728\u8FD9\u91CC\uFF0C\u9700\u8981\u4F60\u91CD\u5F00\u8FD9\u4E00\u8F6E`
|
|
226000
|
-
));
|
|
226120
|
+
out.push(isSelf ? card(kind, r, "urgent", start, `\u4F60\u7684${KIND_LABEL[kind]}\u5DF2\u4E2D\u6B62\uFF0C\u9700\u8981\u4F60\u4ECB\u5165\u91CD\u5F00`) : card(kind, r, "urgent", start, kind === "review-waiting" ? `\u8FD9\u4E00\u6B65\u7684\u8BC4\u5BA1\u5DF2\u4E2D\u6B62\uFF08${actorLabel} \u8FDE\u7EED\u5931\u8D25\u8D85\u9650\uFF09\u2014\u2014\u672C\u8F6E\u8BC4\u5BA1\u6536\u4E0D\u9F50\u3001\u8282\u70B9\u505C\u5728\u8FD9\u91CC\uFF0C\u9700\u8981\u4F60\u91CD\u5F00\u8FD9\u4E00\u8F6E` : `\u8FD9\u4E00\u6B65\u7684\u5904\u7406\u5DF2\u4E2D\u6B62\uFF08${actorLabel} \u8FDE\u7EED\u5931\u8D25\u8D85\u9650\uFF09\u2014\u2014\u8282\u70B9\u505C\u5728\u8FD9\u91CC\uFF0C\u9700\u8981\u6709\u4EBA\u91CD\u5F00`));
|
|
226001
226121
|
continue;
|
|
226002
226122
|
}
|
|
226003
226123
|
if (r.status !== "running") continue;
|
|
@@ -226049,14 +226169,20 @@ function collectWaitingRows(snapshots2, me, policy = CODE_DEFAULT_POLICY) {
|
|
|
226049
226169
|
const requirementHeads = new Map(snap.requirements.map((q2) => [reqKey(q2), q2.latestReviewId]));
|
|
226050
226170
|
const requirementHead = (r) => requirementHeads.get(reqKey(r));
|
|
226051
226171
|
const nodesWithRequirements = new Set(snap.requirements.map((q2) => q2.nodeId));
|
|
226052
|
-
const
|
|
226172
|
+
const briefNode = snap.nodes.find((n) => n.type === "brief");
|
|
226173
|
+
const managerOfWo = briefNode?.fields?.["manager"];
|
|
226053
226174
|
const isManager = typeof managerOfWo === "string" && managerOfWo === me;
|
|
226175
|
+
const launcher = briefNode?.assigneeActorId ?? null;
|
|
226176
|
+
const openIssueNodes = new Set(
|
|
226177
|
+
snap.issues.filter((i) => i.resolvedAt === null && i.aboutNodeId !== null).map((i) => i.aboutNodeId)
|
|
226178
|
+
);
|
|
226179
|
+
const nodeHasOpenIssue = (nodeId) => openIssueNodes.has(nodeId);
|
|
226054
226180
|
const latestReview = /* @__PURE__ */ new Map();
|
|
226055
226181
|
for (const r of snap.reviews) {
|
|
226056
226182
|
if (cancelled.has(r.nodeId)) continue;
|
|
226057
226183
|
if (acceptedWork.get(r.nodeId) === r.targetWorkId) continue;
|
|
226058
226184
|
const mine = r.reviewerActorId === me;
|
|
226059
|
-
const oversees = nodeOwner.get(r.nodeId) === me || isManager;
|
|
226185
|
+
const oversees = nodeOwner.get(r.nodeId) === me || isManager || launcher === me;
|
|
226060
226186
|
if (!mine && !oversees) continue;
|
|
226061
226187
|
latestBy(latestReview, r);
|
|
226062
226188
|
}
|
|
@@ -226075,10 +226201,12 @@ function collectWaitingRows(snapshots2, me, policy = CODE_DEFAULT_POLICY) {
|
|
|
226075
226201
|
const humanPending = !stopped && classify(r.reviewerActorId) === "human";
|
|
226076
226202
|
if (!mine && !stopped && !humanPending) continue;
|
|
226077
226203
|
const audience = [r.reviewerActorId];
|
|
226078
|
-
const
|
|
226079
|
-
if (
|
|
226080
|
-
|
|
226081
|
-
|
|
226204
|
+
const addBystanders = humanPending || stopped && !nodeHasOpenIssue(r.nodeId);
|
|
226205
|
+
if (addBystanders) {
|
|
226206
|
+
for (const candidate of [launcher, managerOfWo, nodeOwner.get(r.nodeId)]) {
|
|
226207
|
+
if (typeof candidate !== "string" || classify(candidate) !== "human") continue;
|
|
226208
|
+
if (!audience.includes(candidate)) audience.push(candidate);
|
|
226209
|
+
}
|
|
226082
226210
|
}
|
|
226083
226211
|
reviews.push({
|
|
226084
226212
|
id: r.id,
|
|
@@ -226095,17 +226223,25 @@ function collectWaitingRows(snapshots2, me, policy = CODE_DEFAULT_POLICY) {
|
|
|
226095
226223
|
const latestMain = /* @__PURE__ */ new Map();
|
|
226096
226224
|
const latestReply = /* @__PURE__ */ new Map();
|
|
226097
226225
|
for (const w2 of snap.works) {
|
|
226098
|
-
if (
|
|
226226
|
+
if (cancelled.has(w2.nodeId)) continue;
|
|
226099
226227
|
latestBy(isReplyWork(w2) ? latestReply : latestMain, w2);
|
|
226100
226228
|
}
|
|
226101
226229
|
for (const w2 of [...latestMain.values(), ...latestReply.values()]) {
|
|
226102
226230
|
const st = workState(w2, hasOutput(w2, outputCountOf(w2.id)));
|
|
226103
226231
|
if (st !== "running" && st !== "dead") continue;
|
|
226232
|
+
const audience = [w2.assigneeActorId];
|
|
226233
|
+
if (st === "dead" && !nodeHasOpenIssue(w2.nodeId)) {
|
|
226234
|
+
for (const candidate of [launcher, managerOfWo, nodeOwner.get(w2.nodeId)]) {
|
|
226235
|
+
if (typeof candidate !== "string" || classify(candidate) !== "human") continue;
|
|
226236
|
+
if (!audience.includes(candidate)) audience.push(candidate);
|
|
226237
|
+
}
|
|
226238
|
+
}
|
|
226104
226239
|
works.push({
|
|
226105
226240
|
id: w2.id,
|
|
226106
226241
|
workorderId: snap.workorder.id,
|
|
226107
226242
|
artifactId: w2.nodeId,
|
|
226108
226243
|
actorId: w2.assigneeActorId,
|
|
226244
|
+
notifyActorIds: audience,
|
|
226109
226245
|
...nodeTitle.get(w2.nodeId) ? { title: nodeTitle.get(w2.nodeId) } : {},
|
|
226110
226246
|
createdAt: w2.createdAt,
|
|
226111
226247
|
startedAt: w2.startedAt,
|
|
@@ -228074,6 +228210,245 @@ var init_collab = __esm({
|
|
|
228074
228210
|
}
|
|
228075
228211
|
});
|
|
228076
228212
|
|
|
228213
|
+
// ../server/src/domains/chat-sessions/files-view.ts
|
|
228214
|
+
function reasonFromWorkdirCode(code2) {
|
|
228215
|
+
switch (code2) {
|
|
228216
|
+
case "NODE_OFFLINE":
|
|
228217
|
+
return "NODE_OFFLINE";
|
|
228218
|
+
case "TIMEOUT":
|
|
228219
|
+
return "TIMEOUT";
|
|
228220
|
+
default:
|
|
228221
|
+
return "ERROR";
|
|
228222
|
+
}
|
|
228223
|
+
}
|
|
228224
|
+
function joinRel(dir, name) {
|
|
228225
|
+
return dir ? `${dir}/${name}` : name;
|
|
228226
|
+
}
|
|
228227
|
+
async function collectWorkdirFiles(bridge, loc, now = Date.now) {
|
|
228228
|
+
const deadline = now() + WORKDIR_WALK_BUDGET_MS;
|
|
228229
|
+
const items = [];
|
|
228230
|
+
let listCalls = 0;
|
|
228231
|
+
let truncated = false;
|
|
228232
|
+
const listDir = (path41) => {
|
|
228233
|
+
listCalls += 1;
|
|
228234
|
+
return bridge.list(loc.nodeId, {
|
|
228235
|
+
workdirKey: loc.workdirKey,
|
|
228236
|
+
runtimeKind: loc.runtimeKind,
|
|
228237
|
+
rtId: loc.rtId,
|
|
228238
|
+
path: path41
|
|
228239
|
+
});
|
|
228240
|
+
};
|
|
228241
|
+
const root = await listDir("");
|
|
228242
|
+
if (!root.ok) {
|
|
228243
|
+
if (root.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
228244
|
+
return { ok: false, reason: reasonFromWorkdirCode(root.code) };
|
|
228245
|
+
}
|
|
228246
|
+
let level = [{ path: "", outcome: root }];
|
|
228247
|
+
for (let depth = 0; depth <= WORKDIR_WALK_MAX_DEPTH; depth += 1) {
|
|
228248
|
+
const nextDirs = [];
|
|
228249
|
+
for (const { path: dir, outcome } of level) {
|
|
228250
|
+
if (!outcome.ok) {
|
|
228251
|
+
truncated = true;
|
|
228252
|
+
continue;
|
|
228253
|
+
}
|
|
228254
|
+
if (outcome.truncated) truncated = true;
|
|
228255
|
+
for (const entry of outcome.entries) {
|
|
228256
|
+
if (entry.type === "dir") {
|
|
228257
|
+
nextDirs.push(joinRel(dir, entry.name));
|
|
228258
|
+
continue;
|
|
228259
|
+
}
|
|
228260
|
+
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
228261
|
+
truncated = true;
|
|
228262
|
+
continue;
|
|
228263
|
+
}
|
|
228264
|
+
const rel = joinRel(dir, entry.name);
|
|
228265
|
+
items.push({
|
|
228266
|
+
id: `workdir:${rel}`,
|
|
228267
|
+
name: entry.name,
|
|
228268
|
+
kind: "file",
|
|
228269
|
+
// 节点侧列目录只报 name/type/size/mtime,没有 MIME——诚实留 null,
|
|
228270
|
+
// 不拿后缀猜(红线:取不到就是取不到,别拿别的字段顶)。
|
|
228271
|
+
content_type: null,
|
|
228272
|
+
size: entry.size,
|
|
228273
|
+
updated_at: entry.mtime,
|
|
228274
|
+
source: "workdir",
|
|
228275
|
+
blob_ref: null,
|
|
228276
|
+
path: rel,
|
|
228277
|
+
message_id: null,
|
|
228278
|
+
// 工作区文件本期不开写回(brief §4①:要动 node↔server 协议帧,超预算)。
|
|
228279
|
+
// 这里是**按能力不渲染**的判据,不是置灰假钮。
|
|
228280
|
+
editable: false
|
|
228281
|
+
});
|
|
228282
|
+
}
|
|
228283
|
+
}
|
|
228284
|
+
if (depth === WORKDIR_WALK_MAX_DEPTH || nextDirs.length === 0) {
|
|
228285
|
+
if (nextDirs.length > 0) truncated = true;
|
|
228286
|
+
break;
|
|
228287
|
+
}
|
|
228288
|
+
const budget = WORKDIR_WALK_MAX_LIST_CALLS - listCalls;
|
|
228289
|
+
if (budget <= 0 || now() >= deadline) {
|
|
228290
|
+
truncated = true;
|
|
228291
|
+
break;
|
|
228292
|
+
}
|
|
228293
|
+
const take = nextDirs.slice(0, budget);
|
|
228294
|
+
if (take.length < nextDirs.length) truncated = true;
|
|
228295
|
+
const outcomes = await Promise.all(take.map((p2) => listDir(p2)));
|
|
228296
|
+
level = take.map((p2, i) => ({ path: p2, outcome: outcomes[i] }));
|
|
228297
|
+
}
|
|
228298
|
+
return { ok: true, items, truncated };
|
|
228299
|
+
}
|
|
228300
|
+
async function collectMessageFiles(messages, blobs) {
|
|
228301
|
+
const rows = [];
|
|
228302
|
+
for (const message of messages) {
|
|
228303
|
+
if (!Array.isArray(message.attachments)) continue;
|
|
228304
|
+
message.attachments.forEach((attachment, index2) => {
|
|
228305
|
+
if (!attachment || typeof attachment.name !== "string" || !attachment.name) return;
|
|
228306
|
+
const blobRef = typeof attachment.blobRef === "string" && attachment.blobRef ? attachment.blobRef : null;
|
|
228307
|
+
rows.push({
|
|
228308
|
+
item: {
|
|
228309
|
+
id: `msg:${message.id}:${index2}`,
|
|
228310
|
+
name: attachment.name,
|
|
228311
|
+
kind: "file",
|
|
228312
|
+
updated_at: attachment.updatedAt ?? message.createdAt,
|
|
228313
|
+
source: "message",
|
|
228314
|
+
blob_ref: blobRef,
|
|
228315
|
+
path: null,
|
|
228316
|
+
message_id: message.id,
|
|
228317
|
+
// 没有 blobRef 的是**历史纯文本附件**(契约注释:legacy text attachments may only
|
|
228318
|
+
// contain `name`)——没有可写回的载体,一律不给编辑入口。
|
|
228319
|
+
editable: blobRef !== null && isEditableFileName(attachment.name)
|
|
228320
|
+
},
|
|
228321
|
+
blobRef,
|
|
228322
|
+
declaredType: typeof attachment.contentType === "string" && attachment.contentType ? attachment.contentType : null
|
|
228323
|
+
});
|
|
228324
|
+
});
|
|
228325
|
+
}
|
|
228326
|
+
const metaCache = /* @__PURE__ */ new Map();
|
|
228327
|
+
const metaOf = (ref2) => {
|
|
228328
|
+
if (!blobs) return Promise.resolve(null);
|
|
228329
|
+
let hit = metaCache.get(ref2);
|
|
228330
|
+
if (!hit) {
|
|
228331
|
+
hit = blobs.meta(ref2).catch(() => null);
|
|
228332
|
+
metaCache.set(ref2, hit);
|
|
228333
|
+
}
|
|
228334
|
+
return hit;
|
|
228335
|
+
};
|
|
228336
|
+
return Promise.all(rows.map(async ({ item, blobRef, declaredType }) => {
|
|
228337
|
+
const meta = blobRef ? await metaOf(blobRef) : null;
|
|
228338
|
+
return {
|
|
228339
|
+
...item,
|
|
228340
|
+
content_type: declaredType ?? meta?.contentType ?? null,
|
|
228341
|
+
size: meta?.size ?? null
|
|
228342
|
+
};
|
|
228343
|
+
}));
|
|
228344
|
+
}
|
|
228345
|
+
function mergeChatSessionFiles(messageItems, workdirItems, materializedCopies = /* @__PURE__ */ new Set()) {
|
|
228346
|
+
const out = [];
|
|
228347
|
+
const seenMessageKeys = /* @__PURE__ */ new Set();
|
|
228348
|
+
for (const item of [...messageItems].sort((a, b2) => b2.updated_at.localeCompare(a.updated_at))) {
|
|
228349
|
+
const key = `${item.name}\0${item.blob_ref ?? ""}`;
|
|
228350
|
+
if (seenMessageKeys.has(key)) continue;
|
|
228351
|
+
seenMessageKeys.add(key);
|
|
228352
|
+
out.push(item);
|
|
228353
|
+
}
|
|
228354
|
+
const seenWorkdirPaths = /* @__PURE__ */ new Set();
|
|
228355
|
+
for (const item of workdirItems) {
|
|
228356
|
+
if (item.path && materializedCopies.has(item.path)) continue;
|
|
228357
|
+
if (seenWorkdirPaths.has(item.id)) continue;
|
|
228358
|
+
seenWorkdirPaths.add(item.id);
|
|
228359
|
+
out.push(item);
|
|
228360
|
+
}
|
|
228361
|
+
out.sort((a, b2) => b2.updated_at.localeCompare(a.updated_at) || a.name.localeCompare(b2.name));
|
|
228362
|
+
return out;
|
|
228363
|
+
}
|
|
228364
|
+
async function findMaterializedAttachmentCopies(messageItems, workdirItems, read) {
|
|
228365
|
+
const copies = /* @__PURE__ */ new Set();
|
|
228366
|
+
const attachments = messageItems.filter((item) => item.blob_ref && /^[a-f0-9]{64}$/.test(item.blob_ref));
|
|
228367
|
+
let budget = CHAT_ATTACHMENT_MAX_BYTES;
|
|
228368
|
+
const deadline = Date.now() + WORKDIR_WALK_BUDGET_MS;
|
|
228369
|
+
let reads = 0;
|
|
228370
|
+
for (const file of workdirItems) {
|
|
228371
|
+
const rootFile = file.path === file.name;
|
|
228372
|
+
const inputFile = file.path?.startsWith("inputs/attachments/") && !file.path.slice("inputs/attachments/".length).includes("/");
|
|
228373
|
+
if (!file.path || !rootFile && !inputFile) continue;
|
|
228374
|
+
const candidates = attachments.filter((attachment) => {
|
|
228375
|
+
const safe = safeAttachmentName(attachment.name);
|
|
228376
|
+
const numbered = file.name.endsWith(`-${safe}`) && /^\d+$/.test(file.name.slice(0, -(safe.length + 1)));
|
|
228377
|
+
return (rootFile ? file.name === attachment.name : file.name === safe || numbered) && attachment.size !== null && attachment.size === file.size;
|
|
228378
|
+
});
|
|
228379
|
+
if (Date.now() >= deadline) break;
|
|
228380
|
+
if (!candidates.length || file.size === null || file.size > budget || reads >= 10) continue;
|
|
228381
|
+
reads += 1;
|
|
228382
|
+
budget -= file.size;
|
|
228383
|
+
let timer;
|
|
228384
|
+
try {
|
|
228385
|
+
const result = await Promise.race([
|
|
228386
|
+
read(file.path, file.size),
|
|
228387
|
+
new Promise((resolve10) => {
|
|
228388
|
+
timer = setTimeout(() => resolve10(null), Math.max(0, deadline - Date.now()));
|
|
228389
|
+
})
|
|
228390
|
+
]);
|
|
228391
|
+
if (!result?.ok) continue;
|
|
228392
|
+
const bytes2 = Buffer.from(result.contentBase64, "base64");
|
|
228393
|
+
if (bytes2.length !== file.size) continue;
|
|
228394
|
+
const hash2 = (0, import_node_crypto51.createHash)("sha256").update(bytes2).digest("hex");
|
|
228395
|
+
if (candidates.some((attachment) => attachment.blob_ref === hash2)) copies.add(file.path);
|
|
228396
|
+
} catch {
|
|
228397
|
+
} finally {
|
|
228398
|
+
if (timer) clearTimeout(timer);
|
|
228399
|
+
}
|
|
228400
|
+
}
|
|
228401
|
+
return copies;
|
|
228402
|
+
}
|
|
228403
|
+
var import_node_crypto51, WORKDIR_WALK_MAX_DEPTH, WORKDIR_WALK_MAX_ENTRIES, WORKDIR_WALK_MAX_LIST_CALLS, WORKDIR_WALK_BUDGET_MS;
|
|
228404
|
+
var init_files_view = __esm({
|
|
228405
|
+
"../server/src/domains/chat-sessions/files-view.ts"() {
|
|
228406
|
+
"use strict";
|
|
228407
|
+
import_node_crypto51 = require("node:crypto");
|
|
228408
|
+
init_chat_attachment_files();
|
|
228409
|
+
init_src();
|
|
228410
|
+
WORKDIR_WALK_MAX_DEPTH = 3;
|
|
228411
|
+
WORKDIR_WALK_MAX_ENTRIES = 200;
|
|
228412
|
+
WORKDIR_WALK_MAX_LIST_CALLS = 20;
|
|
228413
|
+
WORKDIR_WALK_BUDGET_MS = 1e4;
|
|
228414
|
+
}
|
|
228415
|
+
});
|
|
228416
|
+
|
|
228417
|
+
// ../server/src/domains/projects/chat-files.ts
|
|
228418
|
+
async function collectProjectChatFiles(chat, projectId2, meta) {
|
|
228419
|
+
if (!chat.listAttachmentMessages) return [];
|
|
228420
|
+
const messages = await chat.listAttachmentMessages(projectId2);
|
|
228421
|
+
const sessions = new Map(await Promise.all([...new Set(messages.map((m2) => m2.sessionId))].map(async (id) => [id, await chat.getSession(id)])));
|
|
228422
|
+
const visible = messages.filter((m2) => {
|
|
228423
|
+
const session = sessions.get(m2.sessionId);
|
|
228424
|
+
return session?.projectId === projectId2 && session.visibility !== "internal" && !session.analyzedRunId;
|
|
228425
|
+
});
|
|
228426
|
+
const byMessage = new Map(visible.map((m2) => [m2.messageId, m2]));
|
|
228427
|
+
const rows = await collectMessageFiles(visible.map((m2) => ({ ...m2, id: m2.messageId })), {
|
|
228428
|
+
meta
|
|
228429
|
+
});
|
|
228430
|
+
return mergeChatSessionFiles(rows, []).filter((row) => row.blob_ref !== null).map((row) => {
|
|
228431
|
+
const message = byMessage.get(row.message_id);
|
|
228432
|
+
const session = sessions.get(message.sessionId);
|
|
228433
|
+
return {
|
|
228434
|
+
projectId: projectId2,
|
|
228435
|
+
fileId: `chat:${message.sessionId}:${row.id}`,
|
|
228436
|
+
name: row.name,
|
|
228437
|
+
blobId: row.blob_ref,
|
|
228438
|
+
contentType: row.content_type ?? void 0,
|
|
228439
|
+
size: row.size,
|
|
228440
|
+
uploadedBy: session.humanActorId,
|
|
228441
|
+
uploadedAt: row.updated_at
|
|
228442
|
+
};
|
|
228443
|
+
});
|
|
228444
|
+
}
|
|
228445
|
+
var init_chat_files2 = __esm({
|
|
228446
|
+
"../server/src/domains/projects/chat-files.ts"() {
|
|
228447
|
+
"use strict";
|
|
228448
|
+
init_files_view();
|
|
228449
|
+
}
|
|
228450
|
+
});
|
|
228451
|
+
|
|
228077
228452
|
// ../server/src/domains/projects/index.ts
|
|
228078
228453
|
function createProjectsDomain(opts) {
|
|
228079
228454
|
const build = (companyId, deps) => {
|
|
@@ -228089,7 +228464,8 @@ function createProjectsDomain(opts) {
|
|
|
228089
228464
|
opts.listMembers ? async () => buildResolver(
|
|
228090
228465
|
deps?.actorDirectory ?? opts.actorDirectory,
|
|
228091
228466
|
await memberNameResolver(opts.listMembers, companyId)
|
|
228092
|
-
) : void 0
|
|
228467
|
+
) : void 0,
|
|
228468
|
+
opts.listChatFiles ? (projectId2) => opts.listChatFiles(companyId, projectId2) : void 0
|
|
228093
228469
|
);
|
|
228094
228470
|
if (opts.onProjectNameChangedFor) {
|
|
228095
228471
|
const handler = opts.onProjectNameChangedFor(companyId);
|
|
@@ -228141,6 +228517,7 @@ var init_projects = __esm({
|
|
|
228141
228517
|
init_routes5();
|
|
228142
228518
|
init_service4();
|
|
228143
228519
|
init_collab();
|
|
228520
|
+
init_chat_files2();
|
|
228144
228521
|
init_routes5();
|
|
228145
228522
|
init_service4();
|
|
228146
228523
|
init_projection();
|
|
@@ -228156,11 +228533,11 @@ async function isEmployedElsewhere(store, companyId, accountId) {
|
|
|
228156
228533
|
const memberships = await store.listMembershipsForAccount(accountId);
|
|
228157
228534
|
return memberships.some((m2) => m2.companyId !== companyId);
|
|
228158
228535
|
}
|
|
228159
|
-
var
|
|
228536
|
+
var import_node_crypto52, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, INVITE_LINK_TTL_MS, INVITE_LINK_TOKEN_BYTES, INVITE_LINK_ROLE, SLUG_RE, CompanyError, CompaniesService;
|
|
228160
228537
|
var init_service6 = __esm({
|
|
228161
228538
|
"../server/src/domains/companies/service.ts"() {
|
|
228162
228539
|
"use strict";
|
|
228163
|
-
|
|
228540
|
+
import_node_crypto52 = require("node:crypto");
|
|
228164
228541
|
init_console_url();
|
|
228165
228542
|
ROLES = ["owner", "admin", "member"];
|
|
228166
228543
|
INVITABLE_ROLES = ["admin", "member"];
|
|
@@ -228252,7 +228629,7 @@ var init_service6 = __esm({
|
|
|
228252
228629
|
const existing = await this.store.getAccountByEmail(normalized4);
|
|
228253
228630
|
if (existing) return existing;
|
|
228254
228631
|
const account = {
|
|
228255
|
-
id: `actor:human:${(0,
|
|
228632
|
+
id: `actor:human:${(0, import_node_crypto52.randomUUID)()}`,
|
|
228256
228633
|
email: normalized4,
|
|
228257
228634
|
name: name ?? normalized4,
|
|
228258
228635
|
status: "active"
|
|
@@ -228461,7 +228838,7 @@ var init_service6 = __esm({
|
|
|
228461
228838
|
}
|
|
228462
228839
|
const nowMs = Date.parse(this.now());
|
|
228463
228840
|
const invitation = {
|
|
228464
|
-
id: `invitation:${(0,
|
|
228841
|
+
id: `invitation:${(0, import_node_crypto52.randomUUID)()}`,
|
|
228465
228842
|
companyId,
|
|
228466
228843
|
email: mail,
|
|
228467
228844
|
role,
|
|
@@ -228592,7 +228969,7 @@ var init_service6 = __esm({
|
|
|
228592
228969
|
const nowMs = Date.parse(this.now());
|
|
228593
228970
|
const link = {
|
|
228594
228971
|
companyId,
|
|
228595
|
-
token: (0,
|
|
228972
|
+
token: (0, import_node_crypto52.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
|
|
228596
228973
|
role: INVITE_LINK_ROLE,
|
|
228597
228974
|
createdAt: new Date(nowMs).toISOString(),
|
|
228598
228975
|
expiresAt: new Date(nowMs + INVITE_LINK_TTL_MS).toISOString(),
|
|
@@ -228649,7 +229026,7 @@ var init_service6 = __esm({
|
|
|
228649
229026
|
const reusable = existing.find((inv) => !this.isExpired(inv));
|
|
228650
229027
|
if (reusable) return reusable;
|
|
228651
229028
|
const invitation = {
|
|
228652
|
-
id: `invitation:${(0,
|
|
229029
|
+
id: `invitation:${(0, import_node_crypto52.randomUUID)()}`,
|
|
228653
229030
|
companyId: link.companyId,
|
|
228654
229031
|
email: mail,
|
|
228655
229032
|
role: link.role,
|
|
@@ -228887,11 +229264,11 @@ var init_service6 = __esm({
|
|
|
228887
229264
|
});
|
|
228888
229265
|
|
|
228889
229266
|
// ../server/src/domains/companies/offboarding.ts
|
|
228890
|
-
var
|
|
229267
|
+
var import_node_crypto53, MemberOffboardingService;
|
|
228891
229268
|
var init_offboarding = __esm({
|
|
228892
229269
|
"../server/src/domains/companies/offboarding.ts"() {
|
|
228893
229270
|
"use strict";
|
|
228894
|
-
|
|
229271
|
+
import_node_crypto53 = require("node:crypto");
|
|
228895
229272
|
init_service6();
|
|
228896
229273
|
MemberOffboardingService = class {
|
|
228897
229274
|
store;
|
|
@@ -228963,7 +229340,7 @@ var init_offboarding = __esm({
|
|
|
228963
229340
|
const { ownedAgents, inFlight } = await this.snapshot(companyId, accountId);
|
|
228964
229341
|
const at = this.now();
|
|
228965
229342
|
const started = await this.store.startMemberOffboarding({
|
|
228966
|
-
operationId: `off:${(0,
|
|
229343
|
+
operationId: `off:${(0, import_node_crypto53.randomUUID)()}`,
|
|
228967
229344
|
companyId,
|
|
228968
229345
|
accountId,
|
|
228969
229346
|
initiatedBy,
|
|
@@ -229473,18 +229850,18 @@ var init_routes6 = __esm({
|
|
|
229473
229850
|
|
|
229474
229851
|
// ../server/src/domains/companies/agent-credentials.ts
|
|
229475
229852
|
function hashAgentToken(token, secret) {
|
|
229476
|
-
return HASH_PREFIX + (0,
|
|
229853
|
+
return HASH_PREFIX + (0, import_node_crypto54.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
|
|
229477
229854
|
}
|
|
229478
229855
|
function safeEqual(a, b2) {
|
|
229479
229856
|
const ba = Buffer.from(a);
|
|
229480
229857
|
const bb = Buffer.from(b2);
|
|
229481
|
-
return ba.length === bb.length && (0,
|
|
229858
|
+
return ba.length === bb.length && (0, import_node_crypto54.timingSafeEqual)(ba, bb);
|
|
229482
229859
|
}
|
|
229483
|
-
var
|
|
229860
|
+
var import_node_crypto54, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
|
|
229484
229861
|
var init_agent_credentials = __esm({
|
|
229485
229862
|
"../server/src/domains/companies/agent-credentials.ts"() {
|
|
229486
229863
|
"use strict";
|
|
229487
|
-
|
|
229864
|
+
import_node_crypto54 = require("node:crypto");
|
|
229488
229865
|
init_service6();
|
|
229489
229866
|
HASH_PREFIX = "ac1$";
|
|
229490
229867
|
TOKEN_PREFIX = "oak_";
|
|
@@ -229509,7 +229886,7 @@ var init_agent_credentials = __esm({
|
|
|
229509
229886
|
if (employee.status !== "active") {
|
|
229510
229887
|
throw new CompanyError(409, "AGENT_LEFT", `\u6570\u5B57\u5458\u5DE5\u5DF2\u79BB\u5F00\uFF0C\u4E0D\u80FD\u7B7E\u53D1\u51ED\u8BC1\uFF1A${agentId}`);
|
|
229511
229888
|
}
|
|
229512
|
-
const token = `${TOKEN_PREFIX}${(0,
|
|
229889
|
+
const token = `${TOKEN_PREFIX}${(0, import_node_crypto54.randomBytes)(32).toString("base64url")}`;
|
|
229513
229890
|
const credential = {
|
|
229514
229891
|
tokenHash: hashAgentToken(token, this.secret),
|
|
229515
229892
|
companyId,
|
|
@@ -229929,7 +230306,7 @@ function gatewayInstanceSlug(gatewayUrl) {
|
|
|
229929
230306
|
}
|
|
229930
230307
|
function connectInstanceName(gatewayUrl, token, companyId) {
|
|
229931
230308
|
const scope = companyId?.trim();
|
|
229932
|
-
const suffix = scope ? `c${(0,
|
|
230309
|
+
const suffix = scope ? `c${(0, import_node_crypto55.createHash)("sha256").update(`${gatewayUrl}\0${scope}`).digest("hex").slice(0, 10)}` : token.replace(/[^a-z0-9]/gi, "").slice(-8).toLowerCase() || "enroll";
|
|
229933
230310
|
const base = gatewayInstanceSlug(gatewayUrl);
|
|
229934
230311
|
return base.slice(0, Math.max(1, 64 - suffix.length - 1)) + "-" + suffix;
|
|
229935
230312
|
}
|
|
@@ -230258,12 +230635,12 @@ function buildNpxCmd(p2) {
|
|
|
230258
230635
|
const prefix = daemonNpmPrefix();
|
|
230259
230636
|
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)}`;
|
|
230260
230637
|
}
|
|
230261
|
-
var
|
|
230638
|
+
var import_node_crypto55;
|
|
230262
230639
|
var init_connect_script = __esm({
|
|
230263
230640
|
"../server/src/domains/nodes/connect-script.ts"() {
|
|
230264
230641
|
"use strict";
|
|
230265
230642
|
init_src();
|
|
230266
|
-
|
|
230643
|
+
import_node_crypto55 = require("node:crypto");
|
|
230267
230644
|
}
|
|
230268
230645
|
});
|
|
230269
230646
|
|
|
@@ -230697,7 +231074,7 @@ function nodesDomain(deps) {
|
|
|
230697
231074
|
}
|
|
230698
231075
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
230699
231076
|
} else {
|
|
230700
|
-
nodeId = `node-${(0,
|
|
231077
|
+
nodeId = `node-${(0, import_node_crypto56.randomUUID)().slice(0, 8)}`;
|
|
230701
231078
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
230702
231079
|
}
|
|
230703
231080
|
const existingNode = await deps.nodeStore.getNode(nodeId);
|
|
@@ -230859,13 +231236,13 @@ function normalizeGatewayUrl(raw) {
|
|
|
230859
231236
|
}
|
|
230860
231237
|
}
|
|
230861
231238
|
function newNodeId() {
|
|
230862
|
-
return "node-" + (0,
|
|
231239
|
+
return "node-" + (0, import_node_crypto56.randomUUID)().replace(/-/g, "").slice(0, 12);
|
|
230863
231240
|
}
|
|
230864
|
-
var
|
|
231241
|
+
var import_node_crypto56, import_node_fs15, import_node_url6, import_node_path21;
|
|
230865
231242
|
var init_routes7 = __esm({
|
|
230866
231243
|
"../server/src/domains/nodes/routes.ts"() {
|
|
230867
231244
|
"use strict";
|
|
230868
|
-
|
|
231245
|
+
import_node_crypto56 = require("node:crypto");
|
|
230869
231246
|
import_node_fs15 = require("node:fs");
|
|
230870
231247
|
import_node_url6 = require("node:url");
|
|
230871
231248
|
import_node_path21 = require("node:path");
|
|
@@ -231346,7 +231723,7 @@ function createBundle(root, target, input) {
|
|
|
231346
231723
|
}
|
|
231347
231724
|
}
|
|
231348
231725
|
const bytes2 = fs25.statSync(absBundle).size;
|
|
231349
|
-
const digest = (0,
|
|
231726
|
+
const digest = (0, import_node_crypto57.createHash)("sha256").update(fs25.readFileSync(absBundle)).digest("hex");
|
|
231350
231727
|
const relBase = `inputs/git-bundles/${safeRepo}-${commit.slice(0, 12)}`;
|
|
231351
231728
|
return {
|
|
231352
231729
|
absoluteBundlePath: absBundle,
|
|
@@ -231442,12 +231819,12 @@ function classifyGitError(fallback, err, where) {
|
|
|
231442
231819
|
function oneLine(msg) {
|
|
231443
231820
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
231444
231821
|
}
|
|
231445
|
-
var import_node_child_process17,
|
|
231822
|
+
var import_node_child_process17, import_node_crypto57, fs25, os7, path25, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
231446
231823
|
var init_readonly_bundle = __esm({
|
|
231447
231824
|
"../server/src/git/readonly-bundle.ts"() {
|
|
231448
231825
|
"use strict";
|
|
231449
231826
|
import_node_child_process17 = require("node:child_process");
|
|
231450
|
-
|
|
231827
|
+
import_node_crypto57 = require("node:crypto");
|
|
231451
231828
|
fs25 = __toESM(require("node:fs"), 1);
|
|
231452
231829
|
os7 = __toESM(require("node:os"), 1);
|
|
231453
231830
|
path25 = __toESM(require("node:path"), 1);
|
|
@@ -231467,7 +231844,7 @@ var init_readonly_bundle = __esm({
|
|
|
231467
231844
|
|
|
231468
231845
|
// ../server/src/domains/collab/create-seeded-workorder.ts
|
|
231469
231846
|
function makeSeededWorkorderCreator(deps) {
|
|
231470
|
-
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0,
|
|
231847
|
+
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto58.randomUUID)().slice(0, 8)}`);
|
|
231471
231848
|
return async (input) => {
|
|
231472
231849
|
const company = input.companyId && deps.resolveCompany ? await deps.resolveCompany(input.companyId) : void 0;
|
|
231473
231850
|
const kernel = company?.kernel ?? deps.kernel;
|
|
@@ -231560,7 +231937,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
231560
231937
|
};
|
|
231561
231938
|
}
|
|
231562
231939
|
function workspaceForKey(key) {
|
|
231563
|
-
return `ws:wo-${(0,
|
|
231940
|
+
return `ws:wo-${(0, import_node_crypto58.createHash)("sha256").update(key).digest("hex").slice(0, 8)}`;
|
|
231564
231941
|
}
|
|
231565
231942
|
function existingWorkorder(kernel, workspace) {
|
|
231566
231943
|
const arts = [...kernel.model.artifacts.values()].filter((a) => a.workspace === workspace);
|
|
@@ -231573,11 +231950,11 @@ function existingWorkorder(kernel, workspace) {
|
|
|
231573
231950
|
spawned: arts.map((a) => ({ id: a.id, type: a.type, owner: a.owner }))
|
|
231574
231951
|
};
|
|
231575
231952
|
}
|
|
231576
|
-
var
|
|
231953
|
+
var import_node_crypto58, enc2;
|
|
231577
231954
|
var init_create_seeded_workorder = __esm({
|
|
231578
231955
|
"../server/src/domains/collab/create-seeded-workorder.ts"() {
|
|
231579
231956
|
"use strict";
|
|
231580
|
-
|
|
231957
|
+
import_node_crypto58 = require("node:crypto");
|
|
231581
231958
|
init_uncategorized_project();
|
|
231582
231959
|
init_planner();
|
|
231583
231960
|
enc2 = (s2) => new TextEncoder().encode(s2);
|
|
@@ -232974,12 +233351,12 @@ function stateFromAttempt(attempt, handoff, checkpoint, now, stalledAfterMs, ope
|
|
|
232974
233351
|
if (attempt.status === "no-output") return handoff?.unresolvedIssues.length ? "blocked" : "no_change";
|
|
232975
233352
|
return "failed";
|
|
232976
233353
|
}
|
|
232977
|
-
var
|
|
233354
|
+
var import_node_crypto59, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
|
|
232978
233355
|
var init_service8 = __esm({
|
|
232979
233356
|
"../server/src/domains/execution-continuity/service.ts"() {
|
|
232980
233357
|
"use strict";
|
|
232981
233358
|
init_src();
|
|
232982
|
-
|
|
233359
|
+
import_node_crypto59 = require("node:crypto");
|
|
232983
233360
|
init_src5();
|
|
232984
233361
|
BLOCKING_STATES = /* @__PURE__ */ new Set(["stalled", "failed", "blocked"]);
|
|
232985
233362
|
HANDOFF_OUTCOMES2 = /* @__PURE__ */ new Set(["succeeded", "no-output", "failed", "cancelled", "timeout", "orphaned"]);
|
|
@@ -233210,7 +233587,7 @@ var init_service8 = __esm({
|
|
|
233210
233587
|
if (typeof expectedHash !== "string" || !this.readBundleFile) return null;
|
|
233211
233588
|
const injectedResume = this.readBundleFile(attempt.id, "execution/RESUME.md");
|
|
233212
233589
|
if (!injectedResume) return null;
|
|
233213
|
-
const actualHash = (0,
|
|
233590
|
+
const actualHash = (0, import_node_crypto59.createHash)("sha256").update(injectedResume).digest("hex");
|
|
233214
233591
|
if (actualHash !== expectedHash) return null;
|
|
233215
233592
|
const recoverySnapshot = parseResumePackSnapshot(injectedResume);
|
|
233216
233593
|
if (!recoverySnapshot || recoverySnapshot.scenario !== "redispatch" || !recoverySnapshot.previousAttempt || recoverySnapshot.node.nodeId !== attempt.nodeId || recoverySnapshot.jobKey !== attempt.jobKey || recoverySnapshot.part !== attempt.part) return null;
|
|
@@ -233801,171 +234178,6 @@ var init_execution_continuity2 = __esm({
|
|
|
233801
234178
|
}
|
|
233802
234179
|
});
|
|
233803
234180
|
|
|
233804
|
-
// ../server/src/domains/chat-sessions/files-view.ts
|
|
233805
|
-
function reasonFromWorkdirCode(code2) {
|
|
233806
|
-
switch (code2) {
|
|
233807
|
-
case "NODE_OFFLINE":
|
|
233808
|
-
return "NODE_OFFLINE";
|
|
233809
|
-
case "TIMEOUT":
|
|
233810
|
-
return "TIMEOUT";
|
|
233811
|
-
default:
|
|
233812
|
-
return "ERROR";
|
|
233813
|
-
}
|
|
233814
|
-
}
|
|
233815
|
-
function joinRel(dir, name) {
|
|
233816
|
-
return dir ? `${dir}/${name}` : name;
|
|
233817
|
-
}
|
|
233818
|
-
async function collectWorkdirFiles(bridge, loc, now = Date.now) {
|
|
233819
|
-
const deadline = now() + WORKDIR_WALK_BUDGET_MS;
|
|
233820
|
-
const items = [];
|
|
233821
|
-
let listCalls = 0;
|
|
233822
|
-
let truncated = false;
|
|
233823
|
-
const listDir = (path41) => {
|
|
233824
|
-
listCalls += 1;
|
|
233825
|
-
return bridge.list(loc.nodeId, {
|
|
233826
|
-
workdirKey: loc.workdirKey,
|
|
233827
|
-
runtimeKind: loc.runtimeKind,
|
|
233828
|
-
rtId: loc.rtId,
|
|
233829
|
-
path: path41
|
|
233830
|
-
});
|
|
233831
|
-
};
|
|
233832
|
-
const root = await listDir("");
|
|
233833
|
-
if (!root.ok) {
|
|
233834
|
-
if (root.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
233835
|
-
return { ok: false, reason: reasonFromWorkdirCode(root.code) };
|
|
233836
|
-
}
|
|
233837
|
-
let level = [{ path: "", outcome: root }];
|
|
233838
|
-
for (let depth = 0; depth <= WORKDIR_WALK_MAX_DEPTH; depth += 1) {
|
|
233839
|
-
const nextDirs = [];
|
|
233840
|
-
for (const { path: dir, outcome } of level) {
|
|
233841
|
-
if (!outcome.ok) {
|
|
233842
|
-
truncated = true;
|
|
233843
|
-
continue;
|
|
233844
|
-
}
|
|
233845
|
-
if (outcome.truncated) truncated = true;
|
|
233846
|
-
for (const entry of outcome.entries) {
|
|
233847
|
-
if (entry.type === "dir") {
|
|
233848
|
-
nextDirs.push(joinRel(dir, entry.name));
|
|
233849
|
-
continue;
|
|
233850
|
-
}
|
|
233851
|
-
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
233852
|
-
truncated = true;
|
|
233853
|
-
continue;
|
|
233854
|
-
}
|
|
233855
|
-
const rel = joinRel(dir, entry.name);
|
|
233856
|
-
items.push({
|
|
233857
|
-
id: `workdir:${rel}`,
|
|
233858
|
-
name: entry.name,
|
|
233859
|
-
kind: "file",
|
|
233860
|
-
// 节点侧列目录只报 name/type/size/mtime,没有 MIME——诚实留 null,
|
|
233861
|
-
// 不拿后缀猜(红线:取不到就是取不到,别拿别的字段顶)。
|
|
233862
|
-
content_type: null,
|
|
233863
|
-
size: entry.size,
|
|
233864
|
-
updated_at: entry.mtime,
|
|
233865
|
-
source: "workdir",
|
|
233866
|
-
blob_ref: null,
|
|
233867
|
-
path: rel,
|
|
233868
|
-
message_id: null,
|
|
233869
|
-
// 工作区文件本期不开写回(brief §4①:要动 node↔server 协议帧,超预算)。
|
|
233870
|
-
// 这里是**按能力不渲染**的判据,不是置灰假钮。
|
|
233871
|
-
editable: false
|
|
233872
|
-
});
|
|
233873
|
-
}
|
|
233874
|
-
}
|
|
233875
|
-
if (depth === WORKDIR_WALK_MAX_DEPTH || nextDirs.length === 0) {
|
|
233876
|
-
if (nextDirs.length > 0) truncated = true;
|
|
233877
|
-
break;
|
|
233878
|
-
}
|
|
233879
|
-
const budget = WORKDIR_WALK_MAX_LIST_CALLS - listCalls;
|
|
233880
|
-
if (budget <= 0 || now() >= deadline) {
|
|
233881
|
-
truncated = true;
|
|
233882
|
-
break;
|
|
233883
|
-
}
|
|
233884
|
-
const take = nextDirs.slice(0, budget);
|
|
233885
|
-
if (take.length < nextDirs.length) truncated = true;
|
|
233886
|
-
const outcomes = await Promise.all(take.map((p2) => listDir(p2)));
|
|
233887
|
-
level = take.map((p2, i) => ({ path: p2, outcome: outcomes[i] }));
|
|
233888
|
-
}
|
|
233889
|
-
return { ok: true, items, truncated };
|
|
233890
|
-
}
|
|
233891
|
-
async function collectMessageFiles(messages, blobs) {
|
|
233892
|
-
const rows = [];
|
|
233893
|
-
for (const message of messages) {
|
|
233894
|
-
if (!Array.isArray(message.attachments)) continue;
|
|
233895
|
-
message.attachments.forEach((attachment, index2) => {
|
|
233896
|
-
if (!attachment || typeof attachment.name !== "string" || !attachment.name) return;
|
|
233897
|
-
const blobRef = typeof attachment.blobRef === "string" && attachment.blobRef ? attachment.blobRef : null;
|
|
233898
|
-
rows.push({
|
|
233899
|
-
item: {
|
|
233900
|
-
id: `msg:${message.id}:${index2}`,
|
|
233901
|
-
name: attachment.name,
|
|
233902
|
-
kind: "file",
|
|
233903
|
-
updated_at: attachment.updatedAt ?? message.createdAt,
|
|
233904
|
-
source: "message",
|
|
233905
|
-
blob_ref: blobRef,
|
|
233906
|
-
path: null,
|
|
233907
|
-
message_id: message.id,
|
|
233908
|
-
// 没有 blobRef 的是**历史纯文本附件**(契约注释:legacy text attachments may only
|
|
233909
|
-
// contain `name`)——没有可写回的载体,一律不给编辑入口。
|
|
233910
|
-
editable: blobRef !== null && isEditableFileName(attachment.name)
|
|
233911
|
-
},
|
|
233912
|
-
blobRef,
|
|
233913
|
-
declaredType: typeof attachment.contentType === "string" && attachment.contentType ? attachment.contentType : null
|
|
233914
|
-
});
|
|
233915
|
-
});
|
|
233916
|
-
}
|
|
233917
|
-
const metaCache = /* @__PURE__ */ new Map();
|
|
233918
|
-
const metaOf = (ref2) => {
|
|
233919
|
-
if (!blobs) return Promise.resolve(null);
|
|
233920
|
-
let hit = metaCache.get(ref2);
|
|
233921
|
-
if (!hit) {
|
|
233922
|
-
hit = blobs.meta(ref2).catch(() => null);
|
|
233923
|
-
metaCache.set(ref2, hit);
|
|
233924
|
-
}
|
|
233925
|
-
return hit;
|
|
233926
|
-
};
|
|
233927
|
-
return Promise.all(rows.map(async ({ item, blobRef, declaredType }) => {
|
|
233928
|
-
const meta = blobRef ? await metaOf(blobRef) : null;
|
|
233929
|
-
return {
|
|
233930
|
-
...item,
|
|
233931
|
-
content_type: declaredType ?? meta?.contentType ?? null,
|
|
233932
|
-
size: meta?.size ?? null
|
|
233933
|
-
};
|
|
233934
|
-
}));
|
|
233935
|
-
}
|
|
233936
|
-
function mergeChatSessionFiles(messageItems, workdirItems) {
|
|
233937
|
-
const out = [];
|
|
233938
|
-
const seenMessageKeys = /* @__PURE__ */ new Set();
|
|
233939
|
-
const messageNames = /* @__PURE__ */ new Set();
|
|
233940
|
-
for (const item of messageItems) {
|
|
233941
|
-
const key = `${item.name}\0${item.blob_ref ?? ""}`;
|
|
233942
|
-
if (seenMessageKeys.has(key)) continue;
|
|
233943
|
-
seenMessageKeys.add(key);
|
|
233944
|
-
messageNames.add(item.name);
|
|
233945
|
-
out.push(item);
|
|
233946
|
-
}
|
|
233947
|
-
const seenWorkdirPaths = /* @__PURE__ */ new Set();
|
|
233948
|
-
for (const item of workdirItems) {
|
|
233949
|
-
if (item.path === item.name && messageNames.has(item.name)) continue;
|
|
233950
|
-
if (seenWorkdirPaths.has(item.id)) continue;
|
|
233951
|
-
seenWorkdirPaths.add(item.id);
|
|
233952
|
-
out.push(item);
|
|
233953
|
-
}
|
|
233954
|
-
out.sort((a, b2) => b2.updated_at.localeCompare(a.updated_at) || a.name.localeCompare(b2.name));
|
|
233955
|
-
return out;
|
|
233956
|
-
}
|
|
233957
|
-
var WORKDIR_WALK_MAX_DEPTH, WORKDIR_WALK_MAX_ENTRIES, WORKDIR_WALK_MAX_LIST_CALLS, WORKDIR_WALK_BUDGET_MS;
|
|
233958
|
-
var init_files_view = __esm({
|
|
233959
|
-
"../server/src/domains/chat-sessions/files-view.ts"() {
|
|
233960
|
-
"use strict";
|
|
233961
|
-
init_src();
|
|
233962
|
-
WORKDIR_WALK_MAX_DEPTH = 3;
|
|
233963
|
-
WORKDIR_WALK_MAX_ENTRIES = 200;
|
|
233964
|
-
WORKDIR_WALK_MAX_LIST_CALLS = 20;
|
|
233965
|
-
WORKDIR_WALK_BUDGET_MS = 1e4;
|
|
233966
|
-
}
|
|
233967
|
-
});
|
|
233968
|
-
|
|
233969
234181
|
// ../server/src/domains/collab/gap-thread.ts
|
|
233970
234182
|
function gapThreadSessionId(executorActorId) {
|
|
233971
234183
|
return `${GAP_THREAD_SESSION_PREFIX}${executorActorId}`;
|
|
@@ -234470,7 +234682,7 @@ function createChatSessionsDomain(opts) {
|
|
|
234470
234682
|
if (!text5.trim()) throw new ApiError(400, "BAD_REQUEST", "text required");
|
|
234471
234683
|
const now = Date.now();
|
|
234472
234684
|
sweepDrafts(now);
|
|
234473
|
-
const id = `cd_${(0,
|
|
234685
|
+
const id = `cd_${(0, import_node_crypto60.randomUUID)()}`;
|
|
234474
234686
|
drafts.set(id, { text: text5, actor: req.auth.actor, expiresAt: now + DRAFT_TTL_MS });
|
|
234475
234687
|
return { status: 201, body: { id, expiresInMs: DRAFT_TTL_MS } };
|
|
234476
234688
|
});
|
|
@@ -234522,7 +234734,7 @@ function createChatSessionsDomain(opts) {
|
|
|
234522
234734
|
const runtimeId = await currentRuntimeId(body2.aiActorId) ?? "unknown";
|
|
234523
234735
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
234524
234736
|
const session = {
|
|
234525
|
-
id: (0,
|
|
234737
|
+
id: (0, import_node_crypto60.randomUUID)(),
|
|
234526
234738
|
humanActorId: req.auth.actor,
|
|
234527
234739
|
// 注:这里**刻意不写 companyId**。新会话要不要带公司归属,按 ws:wo-6d588f8e 的 ADR
|
|
234528
234740
|
// (每公司 schema、最终移除表内 company 列)统一定,不在本节点自行发明。
|
|
@@ -234628,7 +234840,7 @@ function createChatSessionsDomain(opts) {
|
|
|
234628
234840
|
if (body2.role !== "user" && body2.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
|
|
234629
234841
|
const role = body2.role;
|
|
234630
234842
|
const msg = await store2.appendMessage({
|
|
234631
|
-
id: (0,
|
|
234843
|
+
id: (0, import_node_crypto60.randomUUID)(),
|
|
234632
234844
|
sessionId: req.params.id,
|
|
234633
234845
|
role,
|
|
234634
234846
|
content: role === "user" ? stripInjectedChatContext(body2.content) : body2.content,
|
|
@@ -234669,7 +234881,7 @@ function createChatSessionsDomain(opts) {
|
|
|
234669
234881
|
const known = key ? cur.find((x2) => x2.clientKey === key) : void 0;
|
|
234670
234882
|
if (!known && cur.length >= QUEUE_MAX) throw new ApiError(409, "QUEUE_FULL", `\u961F\u5217\u5DF2\u6EE1\uFF08\u4E0A\u9650 ${QUEUE_MAX} \u6761\uFF09`);
|
|
234671
234883
|
const item = await store.enqueuePendingMessage({
|
|
234672
|
-
id: (0,
|
|
234884
|
+
id: (0, import_node_crypto60.randomUUID)(),
|
|
234673
234885
|
chatSessionId: sid,
|
|
234674
234886
|
text: text5,
|
|
234675
234887
|
...attachments.length ? { attachments } : {},
|
|
@@ -235024,6 +235236,7 @@ function createChatSessionsDomain(opts) {
|
|
|
235024
235236
|
const blobAccess = opts.resolveBlobs ? await opts.resolveBlobs(req.auth?.companyId) : opts.blobs;
|
|
235025
235237
|
const messageItems = await collectMessageFiles(attachmentRows, blobAccess);
|
|
235026
235238
|
let workdirItems = [];
|
|
235239
|
+
let materializedCopies = /* @__PURE__ */ new Set();
|
|
235027
235240
|
let workdirAvailable = false;
|
|
235028
235241
|
let workdirTruncated = false;
|
|
235029
235242
|
let workdirReason = "NOT_ENABLED";
|
|
@@ -235037,13 +235250,18 @@ function createChatSessionsDomain(opts) {
|
|
|
235037
235250
|
if (outcome.ok) {
|
|
235038
235251
|
workdirAvailable = true;
|
|
235039
235252
|
workdirItems = outcome.items;
|
|
235253
|
+
materializedCopies = await findMaterializedAttachmentCopies(
|
|
235254
|
+
messageItems,
|
|
235255
|
+
workdirItems,
|
|
235256
|
+
(path41, maxBytes) => bridge.read(located.loc.nodeId, { ...located.loc, path: path41 }, maxBytes)
|
|
235257
|
+
);
|
|
235040
235258
|
workdirTruncated = outcome.truncated;
|
|
235041
235259
|
} else {
|
|
235042
235260
|
workdirReason = outcome.reason;
|
|
235043
235261
|
}
|
|
235044
235262
|
}
|
|
235045
235263
|
}
|
|
235046
|
-
const items = mergeChatSessionFiles(messageItems, workdirItems);
|
|
235264
|
+
const items = mergeChatSessionFiles(messageItems, workdirItems, materializedCopies);
|
|
235047
235265
|
const body2 = {
|
|
235048
235266
|
total: items.length,
|
|
235049
235267
|
items,
|
|
@@ -235112,11 +235330,11 @@ function createChatSessionsDomain(opts) {
|
|
|
235112
235330
|
});
|
|
235113
235331
|
};
|
|
235114
235332
|
}
|
|
235115
|
-
var
|
|
235333
|
+
var import_node_crypto60, DEFAULT_SNAPSHOT_ITEMS, MAX_SNAPSHOT_ITEMS, WORKDIR_READ_MAX_BYTES;
|
|
235116
235334
|
var init_chat_sessions = __esm({
|
|
235117
235335
|
"../server/src/domains/chat-sessions/index.ts"() {
|
|
235118
235336
|
"use strict";
|
|
235119
|
-
|
|
235337
|
+
import_node_crypto60 = require("node:crypto");
|
|
235120
235338
|
init_src();
|
|
235121
235339
|
init_chat_session();
|
|
235122
235340
|
init_files_view();
|
|
@@ -236520,7 +236738,7 @@ function busyError(chatSessionId, blockedBy) {
|
|
|
236520
236738
|
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`;
|
|
236521
236739
|
}
|
|
236522
236740
|
function genWebhookToken() {
|
|
236523
|
-
return `owt_${(0,
|
|
236741
|
+
return `owt_${(0, import_node_crypto61.randomBytes)(32).toString("base64url")}`;
|
|
236524
236742
|
}
|
|
236525
236743
|
function validateTitleTemplate(tpl) {
|
|
236526
236744
|
const residue = tpl.replace(DATE_TOKEN, "");
|
|
@@ -236576,11 +236794,11 @@ function appendSourceNote(brief, automation, source, atIso) {
|
|
|
236576
236794
|
---
|
|
236577
236795
|
\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`;
|
|
236578
236796
|
}
|
|
236579
|
-
var
|
|
236797
|
+
var import_node_crypto61, DATE_TOKEN, AutomationsService, EVENT_RETRY_BASE_MS, EVENT_RETRY_MAX_MS, EVENT_RETRY_MAX_ATTEMPTS, eventAttempts, eventLastAttemptAt, eventLastError, CHAT_REPLY_MAX;
|
|
236580
236798
|
var init_service9 = __esm({
|
|
236581
236799
|
"../server/src/domains/automations/service.ts"() {
|
|
236582
236800
|
"use strict";
|
|
236583
|
-
|
|
236801
|
+
import_node_crypto61 = require("node:crypto");
|
|
236584
236802
|
init_src();
|
|
236585
236803
|
init_registry3();
|
|
236586
236804
|
init_attribution();
|
|
@@ -237394,11 +237612,11 @@ function verifySignature(rawBody, headers, secret) {
|
|
|
237394
237612
|
if (!secret) return "not_required";
|
|
237395
237613
|
const given = header1(headers, "x-hub-signature-256");
|
|
237396
237614
|
if (!given) return "missing";
|
|
237397
|
-
const expected = `sha256=${(0,
|
|
237615
|
+
const expected = `sha256=${(0, import_node_crypto62.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
|
|
237398
237616
|
const a = Buffer.from(given);
|
|
237399
237617
|
const b2 = Buffer.from(expected);
|
|
237400
237618
|
if (a.length !== b2.length) return "invalid";
|
|
237401
|
-
return (0,
|
|
237619
|
+
return (0, import_node_crypto62.timingSafeEqual)(a, b2) ? "valid" : "invalid";
|
|
237402
237620
|
}
|
|
237403
237621
|
function eventAllowed(filters, envelope) {
|
|
237404
237622
|
if (!filters || filters.length === 0) return true;
|
|
@@ -237428,11 +237646,11 @@ function splitEvent(envelope) {
|
|
|
237428
237646
|
}
|
|
237429
237647
|
return { eventName, actionCandidates: candidates };
|
|
237430
237648
|
}
|
|
237431
|
-
var
|
|
237649
|
+
var import_node_crypto62, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
|
|
237432
237650
|
var init_webhook = __esm({
|
|
237433
237651
|
"../server/src/domains/automations/webhook.ts"() {
|
|
237434
237652
|
"use strict";
|
|
237435
|
-
|
|
237653
|
+
import_node_crypto62 = require("node:crypto");
|
|
237436
237654
|
MAX_BODY_BYTES = 256 * 1024;
|
|
237437
237655
|
AutomationWebhookService = class {
|
|
237438
237656
|
store;
|
|
@@ -238588,7 +238806,7 @@ function playbooksDomain(opts) {
|
|
|
238588
238806
|
opts.overrides.set(companyOf(req), ref2, nodeKey, nextOverride);
|
|
238589
238807
|
try {
|
|
238590
238808
|
await opts.audit?.({
|
|
238591
|
-
id: `reg_${(0,
|
|
238809
|
+
id: `reg_${(0, import_node_crypto63.randomUUID)()}`,
|
|
238592
238810
|
actor: req.auth.actor,
|
|
238593
238811
|
kind: "registry_change",
|
|
238594
238812
|
target: `playbook:${ref2}#${nodeKey}`,
|
|
@@ -238605,11 +238823,11 @@ function playbooksDomain(opts) {
|
|
|
238605
238823
|
});
|
|
238606
238824
|
};
|
|
238607
238825
|
}
|
|
238608
|
-
var
|
|
238826
|
+
var import_node_crypto63;
|
|
238609
238827
|
var init_routes12 = __esm({
|
|
238610
238828
|
"../server/src/domains/playbooks/routes.ts"() {
|
|
238611
238829
|
"use strict";
|
|
238612
|
-
|
|
238830
|
+
import_node_crypto63 = require("node:crypto");
|
|
238613
238831
|
init_router();
|
|
238614
238832
|
init_registry3();
|
|
238615
238833
|
init_planner();
|
|
@@ -238723,17 +238941,17 @@ function completionFingerprint(workspace, members) {
|
|
|
238723
238941
|
workspace,
|
|
238724
238942
|
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 }))
|
|
238725
238943
|
});
|
|
238726
|
-
return (0,
|
|
238944
|
+
return (0, import_node_crypto64.createHash)("sha256").update(canonical).digest("hex");
|
|
238727
238945
|
}
|
|
238728
238946
|
function eventConsumptionKey(args) {
|
|
238729
238947
|
const raw = `project-event:${EVENT_KEY_VERSION}:${args.triggerId}:${args.event}:${args.workspace}:${args.fingerprint}`;
|
|
238730
|
-
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0,
|
|
238948
|
+
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0, import_node_crypto64.createHash)("sha256").update(raw).digest("hex")}`;
|
|
238731
238949
|
}
|
|
238732
|
-
var
|
|
238950
|
+
var import_node_crypto64, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
|
|
238733
238951
|
var init_project_event_poller = __esm({
|
|
238734
238952
|
"../server/src/automations/project-event-poller.ts"() {
|
|
238735
238953
|
"use strict";
|
|
238736
|
-
|
|
238954
|
+
import_node_crypto64 = require("node:crypto");
|
|
238737
238955
|
EVENT_KEY_VERSION = "v1";
|
|
238738
238956
|
EMPTY_METRICS = () => ({
|
|
238739
238957
|
scanDurationMs: 0,
|
|
@@ -238941,7 +239159,7 @@ function routeToSession(hub, nodeId, dispatchId, msg) {
|
|
|
238941
239159
|
function remoteAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs) {
|
|
238942
239160
|
const unknownIfInterrupting = input.interrupt ? { interrupt: "unknown" } : {};
|
|
238943
239161
|
if (entry.exited) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
|
|
238944
|
-
const requestId = (0,
|
|
239162
|
+
const requestId = (0, import_node_crypto65.randomUUID)();
|
|
238945
239163
|
const sent = routeToSession(hub, nodeId, dispatchId, { type: "append_input", dispatchId, input, requestId });
|
|
238946
239164
|
if (!sent) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
|
|
238947
239165
|
return new Promise((resolve10) => {
|
|
@@ -238954,11 +239172,11 @@ function remoteAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs) {
|
|
|
238954
239172
|
entry.appendWaiters.push({ requestId, resolve: resolve10, timer });
|
|
238955
239173
|
});
|
|
238956
239174
|
}
|
|
238957
|
-
var
|
|
239175
|
+
var import_node_crypto65, STASH_TTL_MS, STASH_MAX_FRAMES_PER_ID, STASH_MAX_IDS, DaemonHubAdapter, BindingRouterAdapter, WorkdirBridge;
|
|
238958
239176
|
var init_daemon_adapter = __esm({
|
|
238959
239177
|
"../server/src/daemon-adapter.ts"() {
|
|
238960
239178
|
"use strict";
|
|
238961
|
-
|
|
239179
|
+
import_node_crypto65 = require("node:crypto");
|
|
238962
239180
|
init_src();
|
|
238963
239181
|
STASH_TTL_MS = 5 * 6e4;
|
|
238964
239182
|
STASH_MAX_FRAMES_PER_ID = 500;
|
|
@@ -239308,7 +239526,7 @@ var init_daemon_adapter = __esm({
|
|
|
239308
239526
|
async spawn(job) {
|
|
239309
239527
|
const nodeId = job.binding?.nodeId;
|
|
239310
239528
|
if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
|
|
239311
|
-
const dispatchId = job.dispatchId ?? `dispatch:${(0,
|
|
239529
|
+
const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto65.randomUUID)()}`;
|
|
239312
239530
|
if (job.dispatchId && this.pending.has(dispatchId)) {
|
|
239313
239531
|
return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
239314
239532
|
}
|
|
@@ -239522,7 +239740,7 @@ var init_daemon_adapter = __esm({
|
|
|
239522
239740
|
}));
|
|
239523
239741
|
}
|
|
239524
239742
|
request(nodeId, buildFrame) {
|
|
239525
|
-
const requestId = (0,
|
|
239743
|
+
const requestId = (0, import_node_crypto65.randomUUID)();
|
|
239526
239744
|
const sent = this.hub.dispatch(nodeId, buildFrame(requestId));
|
|
239527
239745
|
if (!sent) return Promise.resolve({ ok: false, code: "NODE_OFFLINE" });
|
|
239528
239746
|
return new Promise((resolve10) => {
|
|
@@ -239630,13 +239848,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
239630
239848
|
if (sha(body2) === lastPushedHash) return { kind: "echo" };
|
|
239631
239849
|
return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
|
|
239632
239850
|
}
|
|
239633
|
-
var
|
|
239851
|
+
var import_node_crypto66, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
|
|
239634
239852
|
var init_engine = __esm({
|
|
239635
239853
|
"../server/src/mirror/engine.ts"() {
|
|
239636
239854
|
"use strict";
|
|
239637
|
-
|
|
239855
|
+
import_node_crypto66 = require("node:crypto");
|
|
239638
239856
|
init_src();
|
|
239639
|
-
sha = (s2) => (0,
|
|
239857
|
+
sha = (s2) => (0, import_node_crypto66.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
239640
239858
|
enc3 = (s2) => new TextEncoder().encode(s2);
|
|
239641
239859
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
239642
239860
|
MirrorEngine = class {
|
|
@@ -239883,11 +240101,11 @@ function humanExitCause(exit3) {
|
|
|
239883
240101
|
const base = (exit3.reason ? label[exit3.reason] : void 0) ?? `\u4F1A\u8BDD\u5F02\u5E38\u7ED3\u675F\uFF08${exit3.reason ?? "\u65E0\u9000\u51FA\u4FE1\u606F"}\uFF09`;
|
|
239884
240102
|
return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
|
|
239885
240103
|
}
|
|
239886
|
-
var
|
|
240104
|
+
var import_node_crypto67, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, AUTONOMOUS_RECOVERY_TOOLS, HIGH_RISK_COMMANDS, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_RECOVERY_TOOLS, CONVERSATIONAL_ESCALATION_TOOLS, CONVERSATIONAL_MANAGER_BODY, MACHINE_EXIT_CODES, CoordinatorWorker;
|
|
239887
240105
|
var init_worker = __esm({
|
|
239888
240106
|
"../server/src/coordinator/worker.ts"() {
|
|
239889
240107
|
"use strict";
|
|
239890
|
-
|
|
240108
|
+
import_node_crypto67 = require("node:crypto");
|
|
239891
240109
|
init_src5();
|
|
239892
240110
|
init_identity();
|
|
239893
240111
|
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
|
|
@@ -240156,7 +240374,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
240156
240374
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
240157
240375
|
}
|
|
240158
240376
|
evaluationKey(kind, artifactId, evidence) {
|
|
240159
|
-
const fingerprint2 = (0,
|
|
240377
|
+
const fingerprint2 = (0, import_node_crypto67.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
240160
240378
|
return `${kind}:${artifactId}:${fingerprint2}`;
|
|
240161
240379
|
}
|
|
240162
240380
|
artifactEvidence(id) {
|
|
@@ -240535,8 +240753,8 @@ ${ctx.nodeFault}
|
|
|
240535
240753
|
this.deps.log?.(`[coordinator] ${workspace} \u5168\u5C40\u4E0A\u4E0B\u6587\u8BFB\u53D6\u5931\u8D25\uFF0C\u7EE7\u7EED\u6CBF\u7528\u539F\u534F\u8C03\u8005\u4EFB\u52A1\uFF1A${String(error2)}`);
|
|
240536
240754
|
}
|
|
240537
240755
|
}
|
|
240538
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
240539
|
-
const coordinatorRunId = `coordinate:${(0,
|
|
240756
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto67.randomUUID)();
|
|
240757
|
+
const coordinatorRunId = `coordinate:${(0, import_node_crypto67.randomUUID)()}`;
|
|
240540
240758
|
const taskWithContext = coordinatorContext ? [
|
|
240541
240759
|
task,
|
|
240542
240760
|
``,
|
|
@@ -240580,7 +240798,7 @@ ${ctx.nodeFault}
|
|
|
240580
240798
|
const startedAtMs = Date.now();
|
|
240581
240799
|
let trajectoryStarted = false;
|
|
240582
240800
|
if (this.deps.trajectory) {
|
|
240583
|
-
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0,
|
|
240801
|
+
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto67.createHash)("sha256").update(content3).digest("hex")]));
|
|
240584
240802
|
const session = {
|
|
240585
240803
|
runId: coordinatorRunId,
|
|
240586
240804
|
runtimeSessionId,
|
|
@@ -240785,11 +241003,11 @@ var init_pg_ident = __esm({
|
|
|
240785
241003
|
});
|
|
240786
241004
|
|
|
240787
241005
|
// ../storage/src/postgres.ts
|
|
240788
|
-
var
|
|
241006
|
+
var import_node_crypto68, ident3, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
|
|
240789
241007
|
var init_postgres = __esm({
|
|
240790
241008
|
"../storage/src/postgres.ts"() {
|
|
240791
241009
|
"use strict";
|
|
240792
|
-
|
|
241010
|
+
import_node_crypto68 = require("node:crypto");
|
|
240793
241011
|
init_pg_ident();
|
|
240794
241012
|
init_esm();
|
|
240795
241013
|
init_src();
|
|
@@ -240969,7 +241187,7 @@ var init_postgres = __esm({
|
|
|
240969
241187
|
return new _PostgresBlobStore(pool, schema);
|
|
240970
241188
|
}
|
|
240971
241189
|
async put(bytes2) {
|
|
240972
|
-
const hash2 = (0,
|
|
241190
|
+
const hash2 = (0, import_node_crypto68.createHash)("sha256").update(bytes2).digest("hex");
|
|
240973
241191
|
await this.pool.query(
|
|
240974
241192
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
240975
241193
|
[hash2, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
|
|
@@ -249392,11 +249610,11 @@ var init_postgres_delegations = __esm({
|
|
|
249392
249610
|
});
|
|
249393
249611
|
|
|
249394
249612
|
// ../storage/src/postgres-nodes.ts
|
|
249395
|
-
var
|
|
249613
|
+
var import_node_crypto69, ident12, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToRuntime;
|
|
249396
249614
|
var init_postgres_nodes = __esm({
|
|
249397
249615
|
"../storage/src/postgres-nodes.ts"() {
|
|
249398
249616
|
"use strict";
|
|
249399
|
-
|
|
249617
|
+
import_node_crypto69 = require("node:crypto");
|
|
249400
249618
|
init_pg_ident();
|
|
249401
249619
|
init_esm();
|
|
249402
249620
|
ident12 = (s2) => {
|
|
@@ -249606,7 +249824,7 @@ var init_postgres_nodes = __esm({
|
|
|
249606
249824
|
return store;
|
|
249607
249825
|
}
|
|
249608
249826
|
issue(nodeId) {
|
|
249609
|
-
const token = `ont_${(0,
|
|
249827
|
+
const token = `ont_${(0, import_node_crypto69.randomBytes)(24).toString("base64url")}`;
|
|
249610
249828
|
this.cache.set(token, nodeId);
|
|
249611
249829
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
249612
249830
|
return token;
|
|
@@ -249872,11 +250090,11 @@ var init_postgres_type_registry = __esm({
|
|
|
249872
250090
|
});
|
|
249873
250091
|
|
|
249874
250092
|
// ../storage/src/postgres-actor-memory.ts
|
|
249875
|
-
var
|
|
250093
|
+
var import_node_crypto70, matchClause, ident14, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
|
|
249876
250094
|
var init_postgres_actor_memory = __esm({
|
|
249877
250095
|
"../storage/src/postgres-actor-memory.ts"() {
|
|
249878
250096
|
"use strict";
|
|
249879
|
-
|
|
250097
|
+
import_node_crypto70 = require("node:crypto");
|
|
249880
250098
|
init_pg_ident();
|
|
249881
250099
|
init_src();
|
|
249882
250100
|
matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
|
|
@@ -250086,7 +250304,7 @@ var init_postgres_actor_memory = __esm({
|
|
|
250086
250304
|
}
|
|
250087
250305
|
async write(input, now) {
|
|
250088
250306
|
if (input.memId === void 0) {
|
|
250089
|
-
const memId = `mem:${(0,
|
|
250307
|
+
const memId = `mem:${(0, import_node_crypto70.randomUUID)()}`;
|
|
250090
250308
|
const r2 = await this.pool.query(
|
|
250091
250309
|
`INSERT INTO ${this.s}.actor_memories
|
|
250092
250310
|
(mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
|
|
@@ -251533,14 +251751,14 @@ function companySchemaName(companyId) {
|
|
|
251533
251751
|
if (typeof companyId !== "string" || !companyId.trim()) {
|
|
251534
251752
|
throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
|
|
251535
251753
|
}
|
|
251536
|
-
const hex = (0,
|
|
251754
|
+
const hex = (0, import_node_crypto71.createHash)("sha256").update(companyId, "utf8").digest("hex");
|
|
251537
251755
|
return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
|
|
251538
251756
|
}
|
|
251539
|
-
var
|
|
251757
|
+
var import_node_crypto71, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
|
|
251540
251758
|
var init_tenant_schema_mapping = __esm({
|
|
251541
251759
|
"../storage/src/tenant-schema-mapping.ts"() {
|
|
251542
251760
|
"use strict";
|
|
251543
|
-
|
|
251761
|
+
import_node_crypto71 = require("node:crypto");
|
|
251544
251762
|
init_esm();
|
|
251545
251763
|
init_pg_ident();
|
|
251546
251764
|
COMPANY_SCHEMA_PREFIX = "c_";
|
|
@@ -251614,7 +251832,7 @@ var init_tenant_schema_mapping = __esm({
|
|
|
251614
251832
|
|
|
251615
251833
|
// ../storage/src/company-data-plane-schema.ts
|
|
251616
251834
|
function canonicalTypeDefHash(def) {
|
|
251617
|
-
return `sha256:${(0,
|
|
251835
|
+
return `sha256:${(0, import_node_crypto72.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
|
|
251618
251836
|
}
|
|
251619
251837
|
function defaultArtifactTypeTemplate() {
|
|
251620
251838
|
return [
|
|
@@ -251794,11 +252012,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
|
|
|
251794
252012
|
}
|
|
251795
252013
|
return { inserted };
|
|
251796
252014
|
}
|
|
251797
|
-
var
|
|
252015
|
+
var import_node_crypto72, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
|
|
251798
252016
|
var init_company_data_plane_schema = __esm({
|
|
251799
252017
|
"../storage/src/company-data-plane-schema.ts"() {
|
|
251800
252018
|
"use strict";
|
|
251801
|
-
|
|
252019
|
+
import_node_crypto72 = require("node:crypto");
|
|
251802
252020
|
init_esm();
|
|
251803
252021
|
init_pg_ident();
|
|
251804
252022
|
DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
|
|
@@ -251877,11 +252095,11 @@ function rowToFile2(row) {
|
|
|
251877
252095
|
updatedAt: new Date(row.updated_at).toISOString()
|
|
251878
252096
|
};
|
|
251879
252097
|
}
|
|
251880
|
-
var
|
|
252098
|
+
var import_node_crypto73, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
|
|
251881
252099
|
var init_company_owned_registry_store = __esm({
|
|
251882
252100
|
"../storage/src/company-owned-registry-store.ts"() {
|
|
251883
252101
|
"use strict";
|
|
251884
|
-
|
|
252102
|
+
import_node_crypto73 = require("node:crypto");
|
|
251885
252103
|
init_esm();
|
|
251886
252104
|
init_src();
|
|
251887
252105
|
init_pg_ident();
|
|
@@ -252266,7 +252484,7 @@ var init_company_owned_registry_store = __esm({
|
|
|
252266
252484
|
enabled: skill.enabled,
|
|
252267
252485
|
files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
|
|
252268
252486
|
});
|
|
252269
|
-
return (0,
|
|
252487
|
+
return (0, import_node_crypto73.createHash)("sha256").update(body2).digest("hex");
|
|
252270
252488
|
}
|
|
252271
252489
|
};
|
|
252272
252490
|
}
|
|
@@ -254742,7 +254960,7 @@ function sourceSetConservation(input) {
|
|
|
254742
254960
|
return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
|
|
254743
254961
|
}
|
|
254744
254962
|
function payloadChecksum(value2) {
|
|
254745
|
-
return (0,
|
|
254963
|
+
return (0, import_node_crypto74.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
254746
254964
|
}
|
|
254747
254965
|
async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
|
|
254748
254966
|
const cs = quoteIdent2(companySchema);
|
|
@@ -255130,11 +255348,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
|
|
|
255130
255348
|
sequences
|
|
255131
255349
|
};
|
|
255132
255350
|
}
|
|
255133
|
-
var
|
|
255351
|
+
var import_node_crypto74, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
|
|
255134
255352
|
var init_tenant_migration_operator = __esm({
|
|
255135
255353
|
"../storage/src/tenant-migration-operator.ts"() {
|
|
255136
255354
|
"use strict";
|
|
255137
|
-
|
|
255355
|
+
import_node_crypto74 = require("node:crypto");
|
|
255138
255356
|
init_esm();
|
|
255139
255357
|
init_pg_ident();
|
|
255140
255358
|
init_tenancy_attribution();
|
|
@@ -255366,8 +255584,8 @@ var init_tenant_new_company_provision = __esm({
|
|
|
255366
255584
|
// ../storage/src/knowledge-snapshot-crypto.ts
|
|
255367
255585
|
function sealSnapshot(snapshot, key) {
|
|
255368
255586
|
if (snapshot.content.startsWith(PREFIX3)) return structuredClone(snapshot);
|
|
255369
|
-
const iv = (0,
|
|
255370
|
-
const cipher = (0,
|
|
255587
|
+
const iv = (0, import_node_crypto75.randomBytes)(12);
|
|
255588
|
+
const cipher = (0, import_node_crypto75.createCipheriv)("aes-256-gcm", bytes(key), iv);
|
|
255371
255589
|
cipher.setAAD(aad2(snapshot));
|
|
255372
255590
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
255373
255591
|
return { ...structuredClone(snapshot), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
|
|
@@ -255377,7 +255595,7 @@ function openSnapshot(snapshot, key) {
|
|
|
255377
255595
|
const packed = snapshot.content.slice(PREFIX3.length).split(".");
|
|
255378
255596
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
255379
255597
|
const [iv, tag, data] = packed;
|
|
255380
|
-
const decipher = (0,
|
|
255598
|
+
const decipher = (0, import_node_crypto75.createDecipheriv)("aes-256-gcm", bytes(key), Buffer.from(iv, "base64url"));
|
|
255381
255599
|
decipher.setAAD(aad2(snapshot));
|
|
255382
255600
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
255383
255601
|
return {
|
|
@@ -255385,11 +255603,11 @@ function openSnapshot(snapshot, key) {
|
|
|
255385
255603
|
content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
|
|
255386
255604
|
};
|
|
255387
255605
|
}
|
|
255388
|
-
var
|
|
255606
|
+
var import_node_crypto75, PREFIX3, bytes, aad2;
|
|
255389
255607
|
var init_knowledge_snapshot_crypto = __esm({
|
|
255390
255608
|
"../storage/src/knowledge-snapshot-crypto.ts"() {
|
|
255391
255609
|
"use strict";
|
|
255392
|
-
|
|
255610
|
+
import_node_crypto75 = require("node:crypto");
|
|
255393
255611
|
PREFIX3 = "oasis-knowledge:v1:";
|
|
255394
255612
|
bytes = (key) => {
|
|
255395
255613
|
const value2 = Buffer.from(key);
|
|
@@ -257620,20 +257838,20 @@ var fs44 = __toESM(require("node:fs"));
|
|
|
257620
257838
|
var os14 = __toESM(require("node:os"));
|
|
257621
257839
|
var path40 = __toESM(require("node:path"));
|
|
257622
257840
|
var import_node_child_process23 = require("node:child_process");
|
|
257623
|
-
var
|
|
257841
|
+
var import_node_crypto82 = require("node:crypto");
|
|
257624
257842
|
|
|
257625
257843
|
// ../cli/src/cli.ts
|
|
257626
257844
|
var fs39 = __toESM(require("node:fs"), 1);
|
|
257627
257845
|
var os12 = __toESM(require("node:os"), 1);
|
|
257628
257846
|
var path35 = __toESM(require("node:path"), 1);
|
|
257629
|
-
var
|
|
257847
|
+
var import_node_crypto80 = require("node:crypto");
|
|
257630
257848
|
|
|
257631
257849
|
// ../cli/src/serve.ts
|
|
257632
257850
|
var fs33 = __toESM(require("node:fs"), 1);
|
|
257633
257851
|
var os8 = __toESM(require("node:os"), 1);
|
|
257634
257852
|
var path29 = __toESM(require("node:path"), 1);
|
|
257635
257853
|
var import_node_child_process18 = require("node:child_process");
|
|
257636
|
-
var
|
|
257854
|
+
var import_node_crypto76 = require("node:crypto");
|
|
257637
257855
|
var import_node_url7 = require("node:url");
|
|
257638
257856
|
|
|
257639
257857
|
// ../cli/src/artifact-discovery-source.ts
|
|
@@ -258318,7 +258536,7 @@ init_src9();
|
|
|
258318
258536
|
init_src();
|
|
258319
258537
|
init_trajectory();
|
|
258320
258538
|
function deterministicUuid2(seed) {
|
|
258321
|
-
const h = (0,
|
|
258539
|
+
const h = (0, import_node_crypto76.createHash)("sha256").update(seed).digest();
|
|
258322
258540
|
const b2 = Buffer.from(h.subarray(0, 16));
|
|
258323
258541
|
b2[6] = b2[6] & 15 | 80;
|
|
258324
258542
|
b2[8] = b2[8] & 63 | 128;
|
|
@@ -258518,7 +258736,7 @@ function oasisWrapperScript() {
|
|
|
258518
258736
|
const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
258519
258737
|
const tsx = path29.join(repoRoot, "node_modules/.bin/tsx");
|
|
258520
258738
|
const main = path29.join(repoRoot, "packages/cli/src/main.ts");
|
|
258521
|
-
const key = (0,
|
|
258739
|
+
const key = (0, import_node_crypto76.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
258522
258740
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
258523
258741
|
const stable = path29.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key}`);
|
|
258524
258742
|
let dir;
|
|
@@ -258899,7 +259117,7 @@ async function startServe(opts) {
|
|
|
258899
259117
|
if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
|
|
258900
259118
|
const online = hub.connectedDaemons().some((d) => d.daemonId === nodeId);
|
|
258901
259119
|
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" });
|
|
258902
|
-
const requestId = (0,
|
|
259120
|
+
const requestId = (0, import_node_crypto76.randomUUID)();
|
|
258903
259121
|
const task = new Promise((resolve10) => {
|
|
258904
259122
|
const timer = setTimeout(() => {
|
|
258905
259123
|
modelRefreshWaiters.delete(requestId);
|
|
@@ -259007,6 +259225,16 @@ async function startServe(opts) {
|
|
|
259007
259225
|
// ADR 0125:写 scope=project 变量时校验 projectId 真实存在(getProject 直查,含临时项目)。
|
|
259008
259226
|
// projectStateStore 在下方 ~行 1023 才赋值——本箭头只在请求时跑,那时已就绪(同 resolveDispatchScope 惰性模式)。
|
|
259009
259227
|
projectExists: async (id) => await projectStateStore.getProject(id) !== null,
|
|
259228
|
+
/* 子 PRD《密钥管理》§1 的权限判据:密钥的写 / 删要认「创建者本人或组织管理者」。
|
|
259229
|
+
owner 与 admin 都算组织管理者(与组织页 `orgIdentityOf` 同一口径)。
|
|
259230
|
+
`controlPlaneStore` 在下方才赋值——本箭头只在请求时跑,那时已就绪(同 projectExists 的惰性模式)。
|
|
259231
|
+
成员表按 accountId 主键,但行上带 actorId,密钥那边手里只有 actorId,所以按 actorId 找。 */
|
|
259232
|
+
isCompanyManager: async (companyId, actorId) => {
|
|
259233
|
+
if (!companyId || !actorId) return false;
|
|
259234
|
+
const members = await controlPlaneStore.listMembers(companyId).catch(() => []);
|
|
259235
|
+
const me = members.find((m2) => m2.actorId === actorId);
|
|
259236
|
+
return me?.role === "owner" || me?.role === "admin";
|
|
259237
|
+
},
|
|
259010
259238
|
// CO-302 数据面隔离(actors 域试点):按当前公司取其引擎,用各自 registry 服务该域请求。
|
|
259011
259239
|
// engineRouter 在下方(行 ~411)以 const 声明;此箭头只在请求时调用,那时已初始化,闭包引用合法
|
|
259012
259240
|
// (TDZ 只在构造时访问才报错,这里不访问)。默认公司命中现有单实例(registry===registryStore),
|
|
@@ -259151,6 +259379,20 @@ async function startServe(opts) {
|
|
|
259151
259379
|
const defaultBranchResolver = makeDefaultBranchResolver({ log: (m2) => console.warn(m2) });
|
|
259152
259380
|
const perCompanyActorNames = /* @__PURE__ */ new Map();
|
|
259153
259381
|
const projectsDomain2 = createProjectsDomain({
|
|
259382
|
+
listChatFiles: async (companyId, projectId2) => {
|
|
259383
|
+
const chat = await chatStoreFor(companyId);
|
|
259384
|
+
const facts = await blobStoreFor(companyId);
|
|
259385
|
+
return collectProjectChatFiles(chat, projectId2, async (ref2) => {
|
|
259386
|
+
for (const cabinet of [assets, facts]) {
|
|
259387
|
+
try {
|
|
259388
|
+
const meta = await cabinet.meta?.(ref2);
|
|
259389
|
+
if (meta) return meta;
|
|
259390
|
+
} catch {
|
|
259391
|
+
}
|
|
259392
|
+
}
|
|
259393
|
+
return null;
|
|
259394
|
+
});
|
|
259395
|
+
},
|
|
259154
259396
|
projects: projectStateStore,
|
|
259155
259397
|
artifacts: artifactStateStore,
|
|
259156
259398
|
kernel: defaultCompanyKernel,
|
|
@@ -259597,7 +259839,7 @@ async function startServe(opts) {
|
|
|
259597
259839
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
259598
259840
|
if (buf || session.runId) {
|
|
259599
259841
|
await turnStore.appendMessage({
|
|
259600
|
-
id: (0,
|
|
259842
|
+
id: (0, import_node_crypto76.randomUUID)(),
|
|
259601
259843
|
sessionId: chatSessionId,
|
|
259602
259844
|
role: "assistant",
|
|
259603
259845
|
content: buf,
|
|
@@ -259643,7 +259885,7 @@ async function startServe(opts) {
|
|
|
259643
259885
|
chatTargets: {
|
|
259644
259886
|
inspect: inspectChatTarget,
|
|
259645
259887
|
createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
|
|
259646
|
-
const sessionId = (0,
|
|
259888
|
+
const sessionId = (0, import_node_crypto76.randomUUID)();
|
|
259647
259889
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
259648
259890
|
const binding = await registryStore.getBinding(agentId).catch(() => null);
|
|
259649
259891
|
await (await chatStoreFor(companyId)).createSession({
|
|
@@ -260646,7 +260888,7 @@ async function startServe(opts) {
|
|
|
260646
260888
|
}));
|
|
260647
260889
|
}
|
|
260648
260890
|
const limits = { wallClockMs: wallClockForKind("planner") };
|
|
260649
|
-
const artifactId = `artifact:planner:${(0,
|
|
260891
|
+
const artifactId = `artifact:planner:${(0, import_node_crypto76.randomUUID)()}`;
|
|
260650
260892
|
const handle = await chatRemoteAdapter.spawn({
|
|
260651
260893
|
actor: planner.id,
|
|
260652
260894
|
// companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
|
|
@@ -261498,10 +261740,10 @@ async function startServe(opts) {
|
|
|
261498
261740
|
if (isDeletedActor(dispatchTarget)) {
|
|
261499
261741
|
throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
|
|
261500
261742
|
}
|
|
261501
|
-
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid2(`chat-runtime:${requestDispatchId}`) : (0,
|
|
261743
|
+
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid2(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto76.randomUUID)());
|
|
261502
261744
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
261503
|
-
const traceRunId = requestDispatchId ? `chat-run:${deterministicUuid2(`chat-trace:${requestDispatchId}`)}` : `chat-run:${(0,
|
|
261504
|
-
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid2(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0,
|
|
261745
|
+
const traceRunId = requestDispatchId ? `chat-run:${deterministicUuid2(`chat-trace:${requestDispatchId}`)}` : `chat-run:${(0, import_node_crypto76.randomUUID)()}`;
|
|
261746
|
+
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid2(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto76.randomUUID)()}`;
|
|
261505
261747
|
let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
|
|
261506
261748
|
if (stableDispatch && !stableDispatch.shouldDispatch) {
|
|
261507
261749
|
return {
|
|
@@ -262623,7 +262865,7 @@ async function startServe(opts) {
|
|
|
262623
262865
|
console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
|
|
262624
262866
|
return;
|
|
262625
262867
|
}
|
|
262626
|
-
const ledgerId = `dispatch:${(0,
|
|
262868
|
+
const ledgerId = `dispatch:${(0, import_node_crypto76.randomUUID)()}`;
|
|
262627
262869
|
try {
|
|
262628
262870
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
262629
262871
|
id: ledgerId,
|
|
@@ -262708,7 +262950,7 @@ async function startServe(opts) {
|
|
|
262708
262950
|
const kernelModel = newKernel.model;
|
|
262709
262951
|
const art = kernelModel.artifacts.get(nodeId);
|
|
262710
262952
|
const revWid = art?.workspace ?? "";
|
|
262711
|
-
const ledgerId = `dispatch:${(0,
|
|
262953
|
+
const ledgerId = `dispatch:${(0, import_node_crypto76.randomUUID)()}`;
|
|
262712
262954
|
try {
|
|
262713
262955
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
262714
262956
|
id: ledgerId,
|
|
@@ -263086,7 +263328,7 @@ async function startServe(opts) {
|
|
|
263086
263328
|
resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
|
|
263087
263329
|
try {
|
|
263088
263330
|
const governance = server.knowledgeGovernance;
|
|
263089
|
-
const taskFingerprint = (0,
|
|
263331
|
+
const taskFingerprint = (0, import_node_crypto76.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
|
|
263090
263332
|
const requestContext = {
|
|
263091
263333
|
organizationId: companyId,
|
|
263092
263334
|
actorId,
|
|
@@ -264976,7 +265218,7 @@ var SessionProcessState = class {
|
|
|
264976
265218
|
// ../cli/src/daemon/ws-client.ts
|
|
264977
265219
|
init_wrapper();
|
|
264978
265220
|
var import_node_os9 = require("node:os");
|
|
264979
|
-
var
|
|
265221
|
+
var import_node_crypto77 = require("node:crypto");
|
|
264980
265222
|
init_src8();
|
|
264981
265223
|
init_src6();
|
|
264982
265224
|
|
|
@@ -265699,7 +265941,7 @@ var DaemonWsClient = class {
|
|
|
265699
265941
|
*/
|
|
265700
265942
|
async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
|
|
265701
265943
|
if (artifactIds.length === 0) return {};
|
|
265702
|
-
const requestId = (0,
|
|
265944
|
+
const requestId = (0, import_node_crypto77.randomUUID)();
|
|
265703
265945
|
return new Promise((resolve10, reject) => {
|
|
265704
265946
|
const timer = setTimeout(() => {
|
|
265705
265947
|
this.gcPending.delete(requestId);
|
|
@@ -266099,7 +266341,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
266099
266341
|
// ../cli/src/daemon/machine-id.ts
|
|
266100
266342
|
var import_node_child_process21 = require("node:child_process");
|
|
266101
266343
|
var import_node_fs21 = require("node:fs");
|
|
266102
|
-
var
|
|
266344
|
+
var import_node_crypto78 = require("node:crypto");
|
|
266103
266345
|
var import_node_os12 = require("node:os");
|
|
266104
266346
|
function linuxMachineId() {
|
|
266105
266347
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
@@ -266165,7 +266407,7 @@ var defaultSources = {
|
|
|
266165
266407
|
function resolveNodeId(sources = {}) {
|
|
266166
266408
|
const s2 = { ...defaultSources, ...sources };
|
|
266167
266409
|
const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
|
|
266168
|
-
const digest = (0,
|
|
266410
|
+
const digest = (0, import_node_crypto78.createHash)("sha256").update(material).digest("hex").slice(0, 12);
|
|
266169
266411
|
return `node-${digest}`;
|
|
266170
266412
|
}
|
|
266171
266413
|
|
|
@@ -267936,13 +268178,13 @@ function ownFlagsFromDecl(command) {
|
|
|
267936
268178
|
}
|
|
267937
268179
|
|
|
267938
268180
|
// ../cli/src/connector-effect-runner.ts
|
|
267939
|
-
var
|
|
268181
|
+
var import_node_crypto79 = require("node:crypto");
|
|
267940
268182
|
var import_node_child_process22 = require("node:child_process");
|
|
267941
268183
|
init_src8();
|
|
267942
268184
|
function stableKey(effect) {
|
|
267943
268185
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
267944
268186
|
const canonical = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
|
|
267945
|
-
return `sha256:${(0,
|
|
268187
|
+
return `sha256:${(0, import_node_crypto79.createHash)("sha256").update(canonical).digest("hex")}`;
|
|
267946
268188
|
}
|
|
267947
268189
|
async function runConnectorEffect(connector, toolArgs, deps) {
|
|
267948
268190
|
const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
|
|
@@ -268152,7 +268394,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
268152
268394
|
const timeoutMs = resolveAuthWaitMs();
|
|
268153
268395
|
const controller = new AbortController();
|
|
268154
268396
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
268155
|
-
const waiterId = (0,
|
|
268397
|
+
const waiterId = (0, import_node_crypto80.randomUUID)();
|
|
268156
268398
|
process.stderr.write(
|
|
268157
268399
|
`\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
|
|
268158
268400
|
`
|
|
@@ -268574,7 +268816,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
268574
268816
|
const store = createNodeTokenStore(path35.join(dir, "node-tokens.json"));
|
|
268575
268817
|
const sub = positional[0];
|
|
268576
268818
|
if (sub === "issue") {
|
|
268577
|
-
const id = flags.get("id") ?? `node-${(0,
|
|
268819
|
+
const id = flags.get("id") ?? `node-${(0, import_node_crypto80.randomUUID)()}`;
|
|
268578
268820
|
const token2 = store.issue(id);
|
|
268579
268821
|
println(token2);
|
|
268580
268822
|
process.stderr.write(
|
|
@@ -271587,13 +271829,13 @@ var LEGACY_SYSTEMD_UNIT = "oasis-node.service";
|
|
|
271587
271829
|
var LEGACY_LAUNCHD_LABEL = "com.oasis.node";
|
|
271588
271830
|
|
|
271589
271831
|
// src/install.ts
|
|
271590
|
-
var
|
|
271832
|
+
var import_node_crypto81 = require("node:crypto");
|
|
271591
271833
|
var fs43 = __toESM(require("node:fs"));
|
|
271592
271834
|
var path39 = __toESM(require("node:path"));
|
|
271593
271835
|
function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
|
|
271594
271836
|
const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
|
|
271595
271837
|
if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
|
|
271596
|
-
const digest = (0,
|
|
271838
|
+
const digest = (0, import_node_crypto81.createHash)("sha256").update(fs43.readFileSync(sourceFile)).digest("hex").slice(0, 8);
|
|
271597
271839
|
return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
|
|
271598
271840
|
}
|
|
271599
271841
|
function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
@@ -271716,7 +271958,7 @@ function shimScript() {
|
|
|
271716
271958
|
}
|
|
271717
271959
|
|
|
271718
271960
|
// src/index.ts
|
|
271719
|
-
var PKG_VERSION = true ? "2.2.
|
|
271961
|
+
var PKG_VERSION = true ? "2.2.17" : "dev";
|
|
271720
271962
|
var LOCAL_BIN = localBin();
|
|
271721
271963
|
var NPM_PREFIX = npmPrefix();
|
|
271722
271964
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -272001,7 +272243,7 @@ function newInstanceName() {
|
|
|
272001
272243
|
const existing = new Set(listInstances());
|
|
272002
272244
|
if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
|
|
272003
272245
|
for (; ; ) {
|
|
272004
|
-
const n = `inst-${(0,
|
|
272246
|
+
const n = `inst-${(0, import_node_crypto82.randomBytes)(3).toString("hex")}`;
|
|
272005
272247
|
if (!existing.has(n)) return n;
|
|
272006
272248
|
}
|
|
272007
272249
|
}
|