oasis_test_v2 2.2.34 → 2.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1148 -728
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -149,6 +149,9 @@ function normalizeGitRemote(remote) {
|
|
|
149
149
|
function projectActorKind(actorId) {
|
|
150
150
|
return actorId.startsWith("actor:human:") ? "human" : "agent";
|
|
151
151
|
}
|
|
152
|
+
function projectIdFromUuid(uuid2) {
|
|
153
|
+
return `proj_${uuid2.replace(/-/g, "").slice(0, 8)}`;
|
|
154
|
+
}
|
|
152
155
|
var init_project = __esm({
|
|
153
156
|
"../contract/src/project.ts"() {
|
|
154
157
|
"use strict";
|
|
@@ -22500,6 +22503,43 @@ var init_sync_skills = __esm({
|
|
|
22500
22503
|
|
|
22501
22504
|
// ../adapters/src/_core/materialize-bundle.ts
|
|
22502
22505
|
function materializeBundle(dir, bundle) {
|
|
22506
|
+
for (const [rel, entry] of Object.entries(bundle.restoreFiles ?? {})) {
|
|
22507
|
+
try {
|
|
22508
|
+
const parts = rel.split("/");
|
|
22509
|
+
if (!rel || path3.isAbsolute(rel) || rel.includes("\\") || parts.some((p2) => !p2 || p2 === "." || p2 === "..")) {
|
|
22510
|
+
throw new Error("\u975E\u6CD5\u76F8\u5BF9\u8DEF\u5F84");
|
|
22511
|
+
}
|
|
22512
|
+
let parent = fs3.realpathSync(dir);
|
|
22513
|
+
for (const component of parts.slice(0, -1)) {
|
|
22514
|
+
parent = path3.join(parent, component);
|
|
22515
|
+
if (!fs3.existsSync(parent)) fs3.mkdirSync(parent);
|
|
22516
|
+
const st = fs3.lstatSync(parent);
|
|
22517
|
+
if (st.isSymbolicLink() || !st.isDirectory()) throw new Error("\u6062\u590D\u8DEF\u5F84\u5305\u542B\u975E\u76EE\u5F55\u6216\u8F6F\u94FE\u63A5");
|
|
22518
|
+
}
|
|
22519
|
+
const file = path3.join(parent, parts.at(-1));
|
|
22520
|
+
let exists = false;
|
|
22521
|
+
try {
|
|
22522
|
+
const st = fs3.lstatSync(file);
|
|
22523
|
+
if (!st.isFile() || st.isSymbolicLink()) throw new Error("\u6062\u590D\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
|
|
22524
|
+
exists = true;
|
|
22525
|
+
} catch (error2) {
|
|
22526
|
+
if (error2.code !== "ENOENT") throw error2;
|
|
22527
|
+
}
|
|
22528
|
+
if (entry.requireExisting && !exists) throw new Error("\u4E0A\u6B21\u672A\u4FDD\u5B58\u7684\u6587\u4EF6\u5DF2\u4E0D\u5728\u672C\u8282\u70B9\uFF0C\u65E0\u6CD5\u6062\u590D\u6700\u65B0\u7248");
|
|
22529
|
+
if (exists && !entry.overwrite) continue;
|
|
22530
|
+
const bytes2 = Buffer.from(entry.contentBase64, "base64");
|
|
22531
|
+
if ((0, import_node_crypto6.createHash)("sha256").update(bytes2).digest("hex") !== entry.sha256) throw new Error("\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
22532
|
+
const temp = path3.join(parent, `.oasis-restore-${(0, import_node_crypto6.randomUUID)()}`);
|
|
22533
|
+
try {
|
|
22534
|
+
fs3.writeFileSync(temp, bytes2, { flag: "wx", mode: 384 });
|
|
22535
|
+
fs3.renameSync(temp, file);
|
|
22536
|
+
} finally {
|
|
22537
|
+
fs3.rmSync(temp, { force: true });
|
|
22538
|
+
}
|
|
22539
|
+
} catch (error2) {
|
|
22540
|
+
throw new BundleRestoreError(rel, error2 instanceof Error ? error2.message : String(error2));
|
|
22541
|
+
}
|
|
22542
|
+
}
|
|
22503
22543
|
for (const [rel, content3] of Object.entries(bundle.files)) {
|
|
22504
22544
|
const file = path3.join(dir, rel);
|
|
22505
22545
|
fs3.mkdirSync(path3.dirname(file), { recursive: true });
|
|
@@ -22514,12 +22554,20 @@ function materializeBundle(dir, bundle) {
|
|
|
22514
22554
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
22515
22555
|
return task;
|
|
22516
22556
|
}
|
|
22517
|
-
var fs3, path3;
|
|
22557
|
+
var fs3, path3, import_node_crypto6, BundleRestoreError;
|
|
22518
22558
|
var init_materialize_bundle = __esm({
|
|
22519
22559
|
"../adapters/src/_core/materialize-bundle.ts"() {
|
|
22520
22560
|
"use strict";
|
|
22521
22561
|
fs3 = __toESM(require("node:fs"), 1);
|
|
22522
22562
|
path3 = __toESM(require("node:path"), 1);
|
|
22563
|
+
import_node_crypto6 = require("node:crypto");
|
|
22564
|
+
BundleRestoreError = class extends Error {
|
|
22565
|
+
constructor(filePath, detail) {
|
|
22566
|
+
super(`\u6587\u4EF6\u6062\u590D\u5931\u8D25 ${filePath}\uFF1A${detail}`);
|
|
22567
|
+
this.filePath = filePath;
|
|
22568
|
+
this.name = "BundleRestoreError";
|
|
22569
|
+
}
|
|
22570
|
+
};
|
|
22523
22571
|
}
|
|
22524
22572
|
});
|
|
22525
22573
|
|
|
@@ -22573,7 +22621,7 @@ function resolveWorkRoots(workRoot) {
|
|
|
22573
22621
|
}
|
|
22574
22622
|
function workdirSlug(workdirKey) {
|
|
22575
22623
|
const safe = workdirKey.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 48);
|
|
22576
|
-
const h = (0,
|
|
22624
|
+
const h = (0, import_node_crypto7.createHash)("sha256").update(workdirKey).digest("hex").slice(0, 8);
|
|
22577
22625
|
return `${safe}-${h}`;
|
|
22578
22626
|
}
|
|
22579
22627
|
function sessionDirFor(workRoot, runtimeKind, workdirKey) {
|
|
@@ -22705,11 +22753,11 @@ function prepareWorkdir(args) {
|
|
|
22705
22753
|
function legacyChatSessionDir(workRoot, rtId) {
|
|
22706
22754
|
return import_node_path.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
|
|
22707
22755
|
}
|
|
22708
|
-
var
|
|
22756
|
+
var import_node_crypto7, import_node_fs2, import_node_os, import_node_path, META_FILE, LOCK_FILE, NEW_WORK_ROOT, slug3, LEGACY_ROOTS, LEGACY_ONESHOT_PREFIX;
|
|
22709
22757
|
var init_session_paths = __esm({
|
|
22710
22758
|
"../adapters/src/_core/session-paths.ts"() {
|
|
22711
22759
|
"use strict";
|
|
22712
|
-
|
|
22760
|
+
import_node_crypto7 = require("node:crypto");
|
|
22713
22761
|
import_node_fs2 = __toESM(require("node:fs"), 1);
|
|
22714
22762
|
import_node_os = __toESM(require("node:os"), 1);
|
|
22715
22763
|
import_node_path = __toESM(require("node:path"), 1);
|
|
@@ -22737,7 +22785,7 @@ function executionEnvHash(p2) {
|
|
|
22737
22785
|
binPkg: p2.binPackageDir ?? null,
|
|
22738
22786
|
extraRo: [...p2.extraRoBindDirs ?? []].sort()
|
|
22739
22787
|
});
|
|
22740
|
-
return (0,
|
|
22788
|
+
return (0, import_node_crypto8.createHash)("sha256").update(material).digest("hex").slice(0, 16);
|
|
22741
22789
|
}
|
|
22742
22790
|
function persistContainerName(workdirKey) {
|
|
22743
22791
|
return `oasis-wd-${workdirSlug(workdirKey)}`;
|
|
@@ -22857,11 +22905,11 @@ function wrapForContainer(p2) {
|
|
|
22857
22905
|
function killContainerArgs(containerName) {
|
|
22858
22906
|
return ["kill", containerName];
|
|
22859
22907
|
}
|
|
22860
|
-
var
|
|
22908
|
+
var import_node_crypto8, path5, CONTAINER_DEFAULT_PATH, CONTAINER_HOME, EE_HASH_LABEL;
|
|
22861
22909
|
var init_container_wrap = __esm({
|
|
22862
22910
|
"../adapters/src/_core/container-wrap.ts"() {
|
|
22863
22911
|
"use strict";
|
|
22864
|
-
|
|
22912
|
+
import_node_crypto8 = require("node:crypto");
|
|
22865
22913
|
path5 = __toESM(require("node:path"), 1);
|
|
22866
22914
|
init_session_paths();
|
|
22867
22915
|
CONTAINER_DEFAULT_PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
@@ -23589,12 +23637,12 @@ function classifyExit(result) {
|
|
|
23589
23637
|
if (status === 429 || status === 529) return "rate-limit";
|
|
23590
23638
|
return "error";
|
|
23591
23639
|
}
|
|
23592
|
-
var import_node_child_process3,
|
|
23640
|
+
var import_node_child_process3, import_node_crypto9, fs7, path7, readline, CLAUDE_BLOCKED_FLAGS, SUBAGENT_TRANSCRIPT_MAX_BYTES, SUBAGENT_TERMINAL, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
|
|
23593
23641
|
var init_claude_code = __esm({
|
|
23594
23642
|
"../adapters/src/claude-code/index.ts"() {
|
|
23595
23643
|
"use strict";
|
|
23596
23644
|
import_node_child_process3 = require("node:child_process");
|
|
23597
|
-
|
|
23645
|
+
import_node_crypto9 = require("node:crypto");
|
|
23598
23646
|
fs7 = __toESM(require("node:fs"), 1);
|
|
23599
23647
|
path7 = __toESM(require("node:path"), 1);
|
|
23600
23648
|
readline = __toESM(require("node:readline"), 1);
|
|
@@ -23674,7 +23722,7 @@ var init_claude_code = __esm({
|
|
|
23674
23722
|
}
|
|
23675
23723
|
async spawn(job) {
|
|
23676
23724
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
23677
|
-
const id = `claude-${slug6}-${(0,
|
|
23725
|
+
const id = `claude-${slug6}-${(0, import_node_crypto9.randomUUID)().slice(0, 8)}`;
|
|
23678
23726
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
23679
23727
|
workRoot: this.opts.workRoot,
|
|
23680
23728
|
runtimeKind: "claude",
|
|
@@ -24087,7 +24135,7 @@ var init_claude_code = __esm({
|
|
|
24087
24135
|
const outgoing = report.failed.length ? appendMaterializeWarning(input.text, report) : input.text;
|
|
24088
24136
|
if (input.interrupt) writeInterrupt();
|
|
24089
24137
|
diag("append_accepted", { writes, results, interrupt: !!input.interrupt, chars: input.text.length });
|
|
24090
|
-
const receiptId = input.requireConsumptionReceipt ? (0,
|
|
24138
|
+
const receiptId = input.requireConsumptionReceipt ? (0, import_node_crypto9.randomUUID)() : void 0;
|
|
24091
24139
|
if (receiptId) pendingInputReceipts.set(receiptId, input.clientMessageKey);
|
|
24092
24140
|
const ok3 = writeUserMessage(outgoing, receiptId);
|
|
24093
24141
|
if (!ok3 && receiptId) pendingInputReceipts.delete(receiptId);
|
|
@@ -24227,7 +24275,12 @@ function withResilience(inner, cfg = {}) {
|
|
|
24227
24275
|
try {
|
|
24228
24276
|
handle = await inner.spawn(job);
|
|
24229
24277
|
} catch (err) {
|
|
24230
|
-
finish({
|
|
24278
|
+
finish({
|
|
24279
|
+
code: null,
|
|
24280
|
+
reason: "error",
|
|
24281
|
+
errorMessage: errText(err),
|
|
24282
|
+
...err instanceof BundleRestoreError ? { fileRestoreError: { path: err.filePath, message: err.message } } : {}
|
|
24283
|
+
});
|
|
24231
24284
|
return;
|
|
24232
24285
|
}
|
|
24233
24286
|
const { info, produced } = await runOnce(handle);
|
|
@@ -24301,6 +24354,7 @@ var RETRYABLE, sleep2;
|
|
|
24301
24354
|
var init_resilient = __esm({
|
|
24302
24355
|
"../adapters/src/_core/resilient.ts"() {
|
|
24303
24356
|
"use strict";
|
|
24357
|
+
init_materialize_bundle();
|
|
24304
24358
|
init_src();
|
|
24305
24359
|
RETRYABLE = /* @__PURE__ */ new Set(["rate-limit", "timeout", "server-unreachable"]);
|
|
24306
24360
|
sleep2 = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
@@ -24484,9 +24538,9 @@ function lockPathFor(cacheRoot, actorId) {
|
|
|
24484
24538
|
}
|
|
24485
24539
|
function aggregateSkillContentHash(files) {
|
|
24486
24540
|
const sorted = [...files].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
24487
|
-
const hasher = (0,
|
|
24541
|
+
const hasher = (0, import_node_crypto10.createHash)("sha256");
|
|
24488
24542
|
for (const f2 of sorted) {
|
|
24489
|
-
const blob = (0,
|
|
24543
|
+
const blob = (0, import_node_crypto10.createHash)("sha256").update(f2.content).digest("hex");
|
|
24490
24544
|
hasher.update(f2.path);
|
|
24491
24545
|
hasher.update("\0");
|
|
24492
24546
|
hasher.update(blob);
|
|
@@ -24714,11 +24768,11 @@ async function verifyPendingLink(skillsDir, name, pend, log3) {
|
|
|
24714
24768
|
}
|
|
24715
24769
|
return true;
|
|
24716
24770
|
}
|
|
24717
|
-
var
|
|
24771
|
+
var import_node_crypto10, fsp, os4, path8, MANIFEST_SCHEMA_VERSION, STALE_LOCK_MS, LOCK_ACQUIRE_TIMEOUT_MS, LOCK_POLL_MS;
|
|
24718
24772
|
var init_skill_cache = __esm({
|
|
24719
24773
|
"../adapters/src/_core/skill-cache.ts"() {
|
|
24720
24774
|
"use strict";
|
|
24721
|
-
|
|
24775
|
+
import_node_crypto10 = require("node:crypto");
|
|
24722
24776
|
fsp = __toESM(require("node:fs/promises"), 1);
|
|
24723
24777
|
os4 = __toESM(require("node:os"), 1);
|
|
24724
24778
|
path8 = __toESM(require("node:path"), 1);
|
|
@@ -25367,7 +25421,7 @@ function isResponse(message) {
|
|
|
25367
25421
|
}
|
|
25368
25422
|
async function runProtocolSession(job, cfg) {
|
|
25369
25423
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
25370
|
-
const id = `${cfg.runtimeKind}-${slug6}-${(0,
|
|
25424
|
+
const id = `${cfg.runtimeKind}-${slug6}-${(0, import_node_crypto11.randomUUID)().slice(0, 8)}`;
|
|
25371
25425
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
25372
25426
|
workRoot: cfg.workRoot,
|
|
25373
25427
|
runtimeKind: cfg.runtimeKind,
|
|
@@ -25610,12 +25664,12 @@ async function runProtocolSession(job, cfg) {
|
|
|
25610
25664
|
}
|
|
25611
25665
|
};
|
|
25612
25666
|
}
|
|
25613
|
-
var import_node_child_process6,
|
|
25667
|
+
var import_node_child_process6, import_node_crypto11, path9, ProtocolCommandRejected, ProtocolSessionClosing;
|
|
25614
25668
|
var init_protocol_session = __esm({
|
|
25615
25669
|
"../adapters/src/_core/protocol-session.ts"() {
|
|
25616
25670
|
"use strict";
|
|
25617
25671
|
import_node_child_process6 = require("node:child_process");
|
|
25618
|
-
|
|
25672
|
+
import_node_crypto11 = require("node:crypto");
|
|
25619
25673
|
path9 = __toESM(require("node:path"), 1);
|
|
25620
25674
|
init_claude_code();
|
|
25621
25675
|
init_container_runtime();
|
|
@@ -26074,13 +26128,13 @@ function codexTurnErrorMessage(value2) {
|
|
|
26074
26128
|
const detail = typeof error2?.additionalDetails === "string" ? error2.additionalDetails.trim() : "";
|
|
26075
26129
|
return [summary, detail].filter(Boolean).join("\n").slice(0, 4e3);
|
|
26076
26130
|
}
|
|
26077
|
-
var import_node_child_process7,
|
|
26131
|
+
var import_node_child_process7, import_node_crypto12, fs8, os5, path10, readline2, CODEX_BLOCKED_FLAGS, CODEX_ARGV_PROMPT_MAX_BYTES, CODEX_APP_SERVER_BLOCKED_FLAGS, CodexAdapter;
|
|
26078
26132
|
var init_codex = __esm({
|
|
26079
26133
|
"../adapters/src/codex/index.ts"() {
|
|
26080
26134
|
"use strict";
|
|
26081
26135
|
import_node_child_process7 = require("node:child_process");
|
|
26082
26136
|
init_container_runtime();
|
|
26083
|
-
|
|
26137
|
+
import_node_crypto12 = require("node:crypto");
|
|
26084
26138
|
fs8 = __toESM(require("node:fs"), 1);
|
|
26085
26139
|
os5 = __toESM(require("node:os"), 1);
|
|
26086
26140
|
path10 = __toESM(require("node:path"), 1);
|
|
@@ -26368,7 +26422,7 @@ ${task}` : task;
|
|
|
26368
26422
|
}
|
|
26369
26423
|
async spawnExec(job) {
|
|
26370
26424
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
26371
|
-
const id = `codex-${slug6}-${(0,
|
|
26425
|
+
const id = `codex-${slug6}-${(0, import_node_crypto12.randomUUID)().slice(0, 8)}`;
|
|
26372
26426
|
const startedAtMs = Date.now();
|
|
26373
26427
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
26374
26428
|
workRoot: this.opts.workRoot,
|
|
@@ -27179,7 +27233,7 @@ async function runACPSession(job, cfg) {
|
|
|
27179
27233
|
}
|
|
27180
27234
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
27181
27235
|
const binTag = path11.basename(cfg.bin).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12) || "acp";
|
|
27182
|
-
const id = `${binTag}-${slug6}-${(0,
|
|
27236
|
+
const id = `${binTag}-${slug6}-${(0, import_node_crypto13.randomUUID)().slice(0, 8)}`;
|
|
27183
27237
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
27184
27238
|
workRoot: cfg.workRoot,
|
|
27185
27239
|
runtimeKind: cfg.runtimeKind ?? "subprocess",
|
|
@@ -27592,12 +27646,12 @@ ${task}` : task;
|
|
|
27592
27646
|
return run;
|
|
27593
27647
|
}
|
|
27594
27648
|
}
|
|
27595
|
-
var import_node_child_process8,
|
|
27649
|
+
var import_node_child_process8, import_node_crypto13, fs9, path11, readline3, ACPClient, LEGACY_APPROVE_OPTION_ID;
|
|
27596
27650
|
var init_acp = __esm({
|
|
27597
27651
|
"../adapters/src/_core/acp.ts"() {
|
|
27598
27652
|
"use strict";
|
|
27599
27653
|
import_node_child_process8 = require("node:child_process");
|
|
27600
|
-
|
|
27654
|
+
import_node_crypto13 = require("node:crypto");
|
|
27601
27655
|
fs9 = __toESM(require("node:fs"), 1);
|
|
27602
27656
|
path11 = __toESM(require("node:path"), 1);
|
|
27603
27657
|
readline3 = __toESM(require("node:readline"), 1);
|
|
@@ -28430,7 +28484,7 @@ var init_pdeathsig = __esm({
|
|
|
28430
28484
|
// ../adapters/src/_core/subprocess.ts
|
|
28431
28485
|
async function materialize(job, cfg) {
|
|
28432
28486
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
28433
|
-
const id = `${slug6}-${(0,
|
|
28487
|
+
const id = `${slug6}-${(0, import_node_crypto14.randomUUID)().slice(0, 8)}`;
|
|
28434
28488
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
28435
28489
|
workRoot: cfg.workRoot,
|
|
28436
28490
|
runtimeKind: cfg.runtimeKind ?? "subprocess",
|
|
@@ -28723,12 +28777,12 @@ async function runOneShotText(job, cfg) {
|
|
|
28723
28777
|
}
|
|
28724
28778
|
});
|
|
28725
28779
|
}
|
|
28726
|
-
var import_node_child_process10,
|
|
28780
|
+
var import_node_child_process10, import_node_crypto14, fs11, path13, readline4;
|
|
28727
28781
|
var init_subprocess = __esm({
|
|
28728
28782
|
"../adapters/src/_core/subprocess.ts"() {
|
|
28729
28783
|
"use strict";
|
|
28730
28784
|
import_node_child_process10 = require("node:child_process");
|
|
28731
|
-
|
|
28785
|
+
import_node_crypto14 = require("node:crypto");
|
|
28732
28786
|
fs11 = __toESM(require("node:fs"), 1);
|
|
28733
28787
|
path13 = __toESM(require("node:path"), 1);
|
|
28734
28788
|
readline4 = __toESM(require("node:readline"), 1);
|
|
@@ -28785,11 +28839,11 @@ function normalizeOpenClaw(line, state) {
|
|
|
28785
28839
|
const text5 = (r.payloads ?? []).map((pl) => pl?.text ?? "").filter(Boolean).join("\n");
|
|
28786
28840
|
return text5 ? [{ kind: "message", payload: { text: text5 }, outputText: text5 }] : [];
|
|
28787
28841
|
}
|
|
28788
|
-
var
|
|
28842
|
+
var import_node_crypto15, isTopLevelClose, OpenClawAdapter;
|
|
28789
28843
|
var init_openclaw = __esm({
|
|
28790
28844
|
"../adapters/src/openclaw/index.ts"() {
|
|
28791
28845
|
"use strict";
|
|
28792
|
-
|
|
28846
|
+
import_node_crypto15 = require("node:crypto");
|
|
28793
28847
|
init_subprocess();
|
|
28794
28848
|
isTopLevelClose = (line) => line === "}" || line === "}\r";
|
|
28795
28849
|
OpenClawAdapter = class {
|
|
@@ -28798,7 +28852,7 @@ var init_openclaw = __esm({
|
|
|
28798
28852
|
}
|
|
28799
28853
|
spawn(job) {
|
|
28800
28854
|
const opts = this.opts;
|
|
28801
|
-
const sessionId = job.runtimeSessionId ?? `oasis-${(0,
|
|
28855
|
+
const sessionId = job.runtimeSessionId ?? `oasis-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
|
|
28802
28856
|
return runStreamJson(job, {
|
|
28803
28857
|
model: job.model ?? opts.model,
|
|
28804
28858
|
bin: opts.openClawBin ?? "openclaw",
|
|
@@ -29599,6 +29653,7 @@ var init_src6 = __esm({
|
|
|
29599
29653
|
init_workdir_gc();
|
|
29600
29654
|
init_gc_loop();
|
|
29601
29655
|
init_normalizer2();
|
|
29656
|
+
init_materialize_bundle();
|
|
29602
29657
|
}
|
|
29603
29658
|
});
|
|
29604
29659
|
|
|
@@ -29954,7 +30009,7 @@ function chatItemsDoubleWriteEnabled(env = process.env) {
|
|
|
29954
30009
|
return raw !== "" && raw !== "0" && raw !== "false" && raw !== "off" && raw !== "no";
|
|
29955
30010
|
}
|
|
29956
30011
|
function fallbackTurnId(runId) {
|
|
29957
|
-
return runId ? `chat-run-turn:${runId}` : `local-turn:${(0,
|
|
30012
|
+
return runId ? `chat-run-turn:${runId}` : `local-turn:${(0, import_node_crypto16.randomUUID)()}`;
|
|
29958
30013
|
}
|
|
29959
30014
|
async function resolveChatItemsTurnId(items, messageId, fallback) {
|
|
29960
30015
|
const existing = await items.listItemsByMessage(messageId).catch(() => []);
|
|
@@ -29973,20 +30028,20 @@ function projectsIntoContent(kind, role, origin, telemetryTextInContent, attrs =
|
|
|
29973
30028
|
return true;
|
|
29974
30029
|
}
|
|
29975
30030
|
}
|
|
29976
|
-
var
|
|
30031
|
+
var import_node_crypto16, CHAT_ITEMS_DOUBLE_WRITE_ENV, SEGMENT_END_NOTE, ChatItemLedger;
|
|
29977
30032
|
var init_chat_item_ledger = __esm({
|
|
29978
30033
|
"../server/src/chat-item-ledger.ts"() {
|
|
29979
30034
|
"use strict";
|
|
29980
30035
|
init_src();
|
|
29981
30036
|
init_subagent_cost();
|
|
29982
30037
|
init_chat_item();
|
|
29983
|
-
|
|
30038
|
+
import_node_crypto16 = require("node:crypto");
|
|
29984
30039
|
CHAT_ITEMS_DOUBLE_WRITE_ENV = "OASIS_CHAT_ITEMS_DOUBLE_WRITE";
|
|
29985
30040
|
SEGMENT_END_NOTE = "\u672C\u6BB5\u65E0\u8F93\u51FA\uFF08\u4EBA\u5728\u9996\u4E2A\u6B63\u6587\u4E4B\u524D\u63D2\u4E86\u8BDD\uFF09";
|
|
29986
30041
|
ChatItemLedger = class {
|
|
29987
30042
|
constructor(deps) {
|
|
29988
30043
|
this.deps = deps;
|
|
29989
|
-
this.newId = deps.newId ??
|
|
30044
|
+
this.newId = deps.newId ?? import_node_crypto16.randomUUID;
|
|
29990
30045
|
this.now = deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
29991
30046
|
this.log = deps.log ?? ((m2) => console.warn(m2));
|
|
29992
30047
|
this.messageId = deps.messageId ?? null;
|
|
@@ -30606,7 +30661,7 @@ var init_chat_parts = __esm({
|
|
|
30606
30661
|
async function openAssistantRunningRow(deps) {
|
|
30607
30662
|
const now = deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
30608
30663
|
if (typeof deps.chatStore.appendMessage !== "function") return void 0;
|
|
30609
|
-
const id = (0,
|
|
30664
|
+
const id = (0, import_node_crypto17.randomUUID)();
|
|
30610
30665
|
const at = now();
|
|
30611
30666
|
try {
|
|
30612
30667
|
await deps.chatStore.appendMessage({
|
|
@@ -30650,7 +30705,7 @@ async function finalizeAssistantRow(deps) {
|
|
|
30650
30705
|
if (typeof deps.chatStore.appendMessage !== "function") return;
|
|
30651
30706
|
try {
|
|
30652
30707
|
await deps.chatStore.appendMessage({
|
|
30653
|
-
id: (0,
|
|
30708
|
+
id: (0, import_node_crypto17.randomUUID)(),
|
|
30654
30709
|
sessionId: deps.chatSessionId,
|
|
30655
30710
|
role: "assistant",
|
|
30656
30711
|
content: deps.content,
|
|
@@ -30664,6 +30719,13 @@ async function finalizeAssistantRow(deps) {
|
|
|
30664
30719
|
} catch {
|
|
30665
30720
|
}
|
|
30666
30721
|
}
|
|
30722
|
+
function outputsPartProvider(scan2, chatSessionId, companyId) {
|
|
30723
|
+
if (!scan2) return void 0;
|
|
30724
|
+
return async () => {
|
|
30725
|
+
const files = await scan2({ chatSessionId, ...companyId !== void 0 ? { companyId } : {} });
|
|
30726
|
+
return files && files.length > 0 ? { type: "outputs", seq: 0, outputs: files } : null;
|
|
30727
|
+
};
|
|
30728
|
+
}
|
|
30667
30729
|
async function appendOutputsPart(parts, provider) {
|
|
30668
30730
|
if (!provider) return parts;
|
|
30669
30731
|
const part = await provider().catch(() => null);
|
|
@@ -30907,11 +30969,11 @@ function runBackgroundAssistantChatTurn(deps) {
|
|
|
30907
30969
|
});
|
|
30908
30970
|
})().catch(() => void 0);
|
|
30909
30971
|
}
|
|
30910
|
-
var
|
|
30972
|
+
var import_node_crypto17;
|
|
30911
30973
|
var init_chat_assistant_turn = __esm({
|
|
30912
30974
|
"../server/src/chat-assistant-turn.ts"() {
|
|
30913
30975
|
"use strict";
|
|
30914
|
-
|
|
30976
|
+
import_node_crypto17 = require("node:crypto");
|
|
30915
30977
|
init_src6();
|
|
30916
30978
|
init_chat_item_ledger();
|
|
30917
30979
|
init_chat_parts();
|
|
@@ -30929,7 +30991,7 @@ async function openChatTurn(args) {
|
|
|
30929
30991
|
const turns = args.turns;
|
|
30930
30992
|
if (!turns) return { ok: true, turn: null };
|
|
30931
30993
|
const nowIso = args.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
30932
|
-
const turnId = (args.newId ??
|
|
30994
|
+
const turnId = (args.newId ?? import_node_crypto18.randomUUID)();
|
|
30933
30995
|
const messageKey = localTurnMessageKey(args.source, turnId);
|
|
30934
30996
|
const claim = await turns.claimTurn({
|
|
30935
30997
|
turnId,
|
|
@@ -30963,7 +31025,7 @@ async function openChatTurn(args) {
|
|
|
30963
31025
|
}
|
|
30964
31026
|
};
|
|
30965
31027
|
}
|
|
30966
|
-
function assistantRowRecovery(chatStore) {
|
|
31028
|
+
function assistantRowRecovery(chatStore, opts = {}) {
|
|
30967
31029
|
const rowOf = async (turn) => {
|
|
30968
31030
|
const runId = turn.assistantRunId;
|
|
30969
31031
|
if (!runId) return null;
|
|
@@ -30979,20 +31041,27 @@ function assistantRowRecovery(chatStore) {
|
|
|
30979
31041
|
|
|
30980
31042
|
` : "";
|
|
30981
31043
|
const content3 = patch.status === "error" ? `${partial2}${ORPHANED_TURN_ASSISTANT_NOTICE}` : row.content ?? "";
|
|
31044
|
+
const outputsPart = opts.outputsPartFor?.(turn.chatSessionId);
|
|
30982
31045
|
await finalizeAssistantRow({
|
|
30983
31046
|
chatStore,
|
|
30984
31047
|
chatSessionId: turn.chatSessionId,
|
|
30985
31048
|
assistantMsgId: row.id,
|
|
30986
31049
|
content: content3,
|
|
30987
|
-
parts
|
|
31050
|
+
// 不扫产出时照旧传空:finalize 对空 parts 不写这一列,行上原有的 parts 不动。
|
|
31051
|
+
// 要扫就必须带上原有 parts——否则扫到产出时写回去的只剩一张卡,这一轮的过程记录被冲掉。
|
|
31052
|
+
parts: outputsPart ? existingParts(row.parts) : [],
|
|
30988
31053
|
status: patch.status,
|
|
30989
31054
|
...turn.assistantRunId ? { runId: turn.assistantRunId } : {},
|
|
30990
31055
|
turnId: turn.id,
|
|
30991
|
-
now: () => patch.completedAt
|
|
31056
|
+
now: () => patch.completedAt,
|
|
31057
|
+
...outputsPart ? { outputsPart } : {}
|
|
30992
31058
|
});
|
|
30993
31059
|
}
|
|
30994
31060
|
};
|
|
30995
31061
|
}
|
|
31062
|
+
function existingParts(parts) {
|
|
31063
|
+
return Array.isArray(parts) ? parts.filter((p2) => p2 && typeof p2 === "object" && typeof p2.type === "string") : [];
|
|
31064
|
+
}
|
|
30996
31065
|
async function reconcileChatTurn(turn, deps) {
|
|
30997
31066
|
if (deps.isOwned?.(turn)) return { settled: false, turnId: turn.id, reason: "owned" };
|
|
30998
31067
|
const rowStatus = deps.assistantRowStatus ? await deps.assistantRowStatus(turn).catch(() => null) : null;
|
|
@@ -31097,11 +31166,11 @@ async function sweepStaleChatTurnsAcrossCompanies(deps) {
|
|
|
31097
31166
|
}
|
|
31098
31167
|
return settled;
|
|
31099
31168
|
}
|
|
31100
|
-
var
|
|
31169
|
+
var import_node_crypto18, ORPHANED_TURN_ASSISTANT_NOTICE;
|
|
31101
31170
|
var init_chat_turn_gate = __esm({
|
|
31102
31171
|
"../server/src/chat-turn-gate.ts"() {
|
|
31103
31172
|
"use strict";
|
|
31104
|
-
|
|
31173
|
+
import_node_crypto18 = require("node:crypto");
|
|
31105
31174
|
init_chat_assistant_turn();
|
|
31106
31175
|
ORPHANED_TURN_ASSISTANT_NOTICE = "\u8FD9\u4E00\u8F6E\u6CA1\u6709\u6B63\u5E38\u7ED3\u675F\uFF08\u670D\u52A1\u7AEF\u8FDB\u7A0B\u4E2D\u65AD\uFF09\uFF0C\u6CA1\u6709\u4EA7\u751F\u56DE\u590D\u3002\u4F60\u53EF\u4EE5\u518D\u95EE\u4E00\u6B21\u3002";
|
|
31107
31176
|
}
|
|
@@ -31313,11 +31382,11 @@ var init_parse = __esm({
|
|
|
31313
31382
|
|
|
31314
31383
|
// ../channels/src/feishu/crypto.ts
|
|
31315
31384
|
function decryptFeishu(encrypt, encryptKey) {
|
|
31316
|
-
const key = (0,
|
|
31385
|
+
const key = (0, import_node_crypto19.createHash)("sha256").update(encryptKey).digest();
|
|
31317
31386
|
const data = Buffer.from(encrypt, "base64");
|
|
31318
31387
|
const iv = data.subarray(0, 16);
|
|
31319
31388
|
const ciphertext = data.subarray(16);
|
|
31320
|
-
const decipher = (0,
|
|
31389
|
+
const decipher = (0, import_node_crypto19.createDecipheriv)("aes-256-cbc", key, iv);
|
|
31321
31390
|
decipher.setAutoPadding(true);
|
|
31322
31391
|
return Buffer.concat([decipher.update(ciphertext), decipher.final()]).toString("utf8");
|
|
31323
31392
|
}
|
|
@@ -31351,11 +31420,11 @@ function verifyToken(decoded, expected) {
|
|
|
31351
31420
|
const token = headerToken ?? decoded["token"];
|
|
31352
31421
|
return token === expected;
|
|
31353
31422
|
}
|
|
31354
|
-
var
|
|
31423
|
+
var import_node_crypto19;
|
|
31355
31424
|
var init_crypto = __esm({
|
|
31356
31425
|
"../channels/src/feishu/crypto.ts"() {
|
|
31357
31426
|
"use strict";
|
|
31358
|
-
|
|
31427
|
+
import_node_crypto19 = require("node:crypto");
|
|
31359
31428
|
}
|
|
31360
31429
|
});
|
|
31361
31430
|
|
|
@@ -31491,11 +31560,11 @@ var init_src7 = __esm({
|
|
|
31491
31560
|
function errMsg(e) {
|
|
31492
31561
|
return e instanceof Error ? e.message : String(e);
|
|
31493
31562
|
}
|
|
31494
|
-
var
|
|
31563
|
+
var import_node_crypto20, FEISHU, ChannelService, CardStreamer;
|
|
31495
31564
|
var init_service = __esm({
|
|
31496
31565
|
"../server/src/channels/service.ts"() {
|
|
31497
31566
|
"use strict";
|
|
31498
|
-
|
|
31567
|
+
import_node_crypto20 = require("node:crypto");
|
|
31499
31568
|
init_chat_turn_gate();
|
|
31500
31569
|
init_deletion();
|
|
31501
31570
|
init_src7();
|
|
@@ -31577,7 +31646,7 @@ var init_service = __esm({
|
|
|
31577
31646
|
return existing.chatSessionId;
|
|
31578
31647
|
}
|
|
31579
31648
|
}
|
|
31580
|
-
const id = (0,
|
|
31649
|
+
const id = (0, import_node_crypto20.randomUUID)();
|
|
31581
31650
|
const now = this.now();
|
|
31582
31651
|
if (cs) {
|
|
31583
31652
|
const rt = await this.deps.resolveRuntime?.(a.aiActorId).catch(() => null);
|
|
@@ -31613,7 +31682,7 @@ var init_service = __esm({
|
|
|
31613
31682
|
if (cs) {
|
|
31614
31683
|
const sess = await cs.getSession(intent.chatSessionId).catch(() => null);
|
|
31615
31684
|
resumeRt = sess?.runtimeSessionId ?? void 0;
|
|
31616
|
-
await cs.appendMessage({ id: (0,
|
|
31685
|
+
await cs.appendMessage({ id: (0, import_node_crypto20.randomUUID)(), sessionId: intent.chatSessionId, role: "user", content: intent.message, createdAt: this.now() }, { source: "channels" }).catch(() => void 0);
|
|
31617
31686
|
}
|
|
31618
31687
|
const opened = await openChatTurn({
|
|
31619
31688
|
turns: this.deps.chatTurns,
|
|
@@ -31651,7 +31720,7 @@ var init_service = __esm({
|
|
|
31651
31720
|
const reply = streamer.text();
|
|
31652
31721
|
if (reply || session.runId) {
|
|
31653
31722
|
await cs.appendMessage({
|
|
31654
|
-
id: (0,
|
|
31723
|
+
id: (0, import_node_crypto20.randomUUID)(),
|
|
31655
31724
|
sessionId: intent.chatSessionId,
|
|
31656
31725
|
role: "assistant",
|
|
31657
31726
|
content: reply,
|
|
@@ -52730,7 +52799,7 @@ var require_websocket = __commonJS({
|
|
|
52730
52799
|
var http2 = require("http");
|
|
52731
52800
|
var net = require("net");
|
|
52732
52801
|
var tls = require("tls");
|
|
52733
|
-
var { randomBytes: randomBytes13, createHash:
|
|
52802
|
+
var { randomBytes: randomBytes13, createHash: createHash41 } = require("crypto");
|
|
52734
52803
|
var { Duplex, Readable } = require("stream");
|
|
52735
52804
|
var { URL: URL2 } = require("url");
|
|
52736
52805
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -53398,7 +53467,7 @@ var require_websocket = __commonJS({
|
|
|
53398
53467
|
abortHandshake(websocket, socket, "Invalid Upgrade header");
|
|
53399
53468
|
return;
|
|
53400
53469
|
}
|
|
53401
|
-
const digest =
|
|
53470
|
+
const digest = createHash41("sha1").update(key + GUID).digest("base64");
|
|
53402
53471
|
if (res.headers["sec-websocket-accept"] !== digest) {
|
|
53403
53472
|
abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
|
|
53404
53473
|
return;
|
|
@@ -53767,7 +53836,7 @@ var require_websocket_server = __commonJS({
|
|
|
53767
53836
|
var EventEmitter = require("events");
|
|
53768
53837
|
var http2 = require("http");
|
|
53769
53838
|
var { Duplex } = require("stream");
|
|
53770
|
-
var { createHash:
|
|
53839
|
+
var { createHash: createHash41 } = require("crypto");
|
|
53771
53840
|
var extension3 = require_extension();
|
|
53772
53841
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
53773
53842
|
var subprotocol2 = require_subprotocol();
|
|
@@ -54074,7 +54143,7 @@ var require_websocket_server = __commonJS({
|
|
|
54074
54143
|
);
|
|
54075
54144
|
}
|
|
54076
54145
|
if (this._state > RUNNING) return abortHandshake(socket, 503);
|
|
54077
|
-
const digest =
|
|
54146
|
+
const digest = createHash41("sha1").update(key + GUID).digest("base64");
|
|
54078
54147
|
const headers = [
|
|
54079
54148
|
"HTTP/1.1 101 Switching Protocols",
|
|
54080
54149
|
"Upgrade: websocket",
|
|
@@ -162288,13 +162357,13 @@ var init_chat_attachment_files = __esm({
|
|
|
162288
162357
|
|
|
162289
162358
|
// ../server/src/domains/chat-sessions/append-now.ts
|
|
162290
162359
|
async function appendNowThroughQueue(chatSessionId, text5, deps, clientKey, attachments, retainLocallyOnFailure = false) {
|
|
162291
|
-
const newId = deps.newId ??
|
|
162360
|
+
const newId = deps.newId ?? import_node_crypto21.randomUUID;
|
|
162292
162361
|
const now = deps.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
162293
162362
|
if (!deps.store.claimPendingInsert) {
|
|
162294
162363
|
return { accepted: false, reason: "queue-unavailable", queued: false, delivered: "", batch: [] };
|
|
162295
162364
|
}
|
|
162296
162365
|
const { submitted, batch } = await deps.store.claimPendingInsert({
|
|
162297
|
-
id: clientKey ? `append-request:${(0,
|
|
162366
|
+
id: clientKey ? `append-request:${(0, import_node_crypto21.createHash)("sha256").update(JSON.stringify([chatSessionId, clientKey])).digest("hex")}` : newId(),
|
|
162298
162367
|
chatSessionId,
|
|
162299
162368
|
text: text5,
|
|
162300
162369
|
...attachments?.length ? { attachments } : {},
|
|
@@ -162350,11 +162419,11 @@ async function appendNowThroughQueue(chatSessionId, text5, deps, clientKey, atta
|
|
|
162350
162419
|
}
|
|
162351
162420
|
return { ...res, queued: !returnToClient, delivered: merged, batch, ...prepared.paths.length ? { attachmentPaths: prepared.paths } : {} };
|
|
162352
162421
|
}
|
|
162353
|
-
var
|
|
162422
|
+
var import_node_crypto21;
|
|
162354
162423
|
var init_append_now = __esm({
|
|
162355
162424
|
"../server/src/domains/chat-sessions/append-now.ts"() {
|
|
162356
162425
|
"use strict";
|
|
162357
|
-
|
|
162426
|
+
import_node_crypto21 = require("node:crypto");
|
|
162358
162427
|
init_chat_attachment_files();
|
|
162359
162428
|
}
|
|
162360
162429
|
});
|
|
@@ -163027,7 +163096,7 @@ function slug5(name) {
|
|
|
163027
163096
|
return s2 || "user";
|
|
163028
163097
|
}
|
|
163029
163098
|
function short6() {
|
|
163030
|
-
return (0,
|
|
163099
|
+
return (0, import_node_crypto22.randomBytes)(4).toString("hex").slice(0, 6);
|
|
163031
163100
|
}
|
|
163032
163101
|
async function assertBindingWritePermission(caller, targetHumanId, deps) {
|
|
163033
163102
|
if (caller === targetHumanId) return true;
|
|
@@ -163092,11 +163161,11 @@ async function resolveWorkorderPrincipals(caller, cliOverrides, deps) {
|
|
|
163092
163161
|
}
|
|
163093
163162
|
return { error: "UNBOUND_AGENT_NO_OWNER", message: `owner \u65E0\u6CD5\u89E3\u6790\uFF1A\u8C03\u7528\u65B9 ${caller} \u65E2\u975E\u5728\u5C97\u771F\u4EBA\u4E5F\u975E\u5DF2\u7ED1\u52A9\u7406` };
|
|
163094
163163
|
}
|
|
163095
|
-
var
|
|
163164
|
+
var import_node_crypto22, DEFAULT_ASSISTANT_PROMPT, DEFAULT_ASSISTANT_SKILLS, DEFAULT_ASSISTANT_RUNTIME_KIND, ASSISTANT_ARCHIVED_CODE, AssistantLazyCreateError, AssistantsService;
|
|
163096
163165
|
var init_assistants = __esm({
|
|
163097
163166
|
"../server/src/domains/actors/assistants.ts"() {
|
|
163098
163167
|
"use strict";
|
|
163099
|
-
|
|
163168
|
+
import_node_crypto22 = require("node:crypto");
|
|
163100
163169
|
init_src();
|
|
163101
163170
|
DEFAULT_ASSISTANT_PROMPT = "\u4F60\u662F\u8FD9\u540D\u771F\u4EBA\u5458\u5DE5\u7684\u4E13\u5C5E\u4E2A\u4EBA\u52A9\u7406\u3002\u4F60\u4EE5\u5176\u300C\u5DE5\u5355\u7BA1\u7406\u8005\u300D\u8EAB\u4EFD\u4EE3\u8DD1\uFF0C\u9075\u5FAA\u4E09\u6863\u6743\u9650\u6A21\u578B\uFF1A\u6863 A\uFF08\u52A0\u8FB9\u3001\u65B0\u5EFA\u8282\u70B9\u3001\u6539\u6807\u9898\u4E0E brief\u3001\u5E38\u89C4\u8BC4\u8BBA\u7B54\u7591\u3001\u63A8\u8FDB\u81EA\u5DF1\u63A5\u7684\u6D3B\uFF09\u53EF\u9006\u6539\u52A8\u76F4\u63A5\u751F\u6548\uFF1B\u6863 B\uFF08\u65AD\u8FB9\u3001\u5E9F\u8282\u70B9\u3001\u6539\u6D3E\u3001\u64A4\u90E8\u4EF6\uFF09\u9500\u6BC1\u6027\u6539\u52A8\u81EA\u52A8\u6253\u5305\u6210\u5F85\u786E\u8BA4\u63D0\u6848\uFF0C\u4EA4\u7531\u672C\u4EBA\u786E\u8BA4\u540E\u751F\u6548\uFF1B\u6863 C\uFF08force-conclude\u3001promote \u7B49\u6CBB\u7406\u547D\u4EE4\uFF09\u8D70\u4EBA\u5DE5\u6388\u6743\u5361\u3002\u4F60\u4E0D\u627F\u62C5\u4E1A\u52A1\u4E13\u4E1A\u5C97\u4F4D\u804C\u8D23\uFF0C\u53EA\u5728\u5176\u6388\u6743\u8303\u56F4\u5185\u534F\u52A9\u5EFA\u5355\u3001\u8DDF\u8FDB\u4E0E\u6C9F\u901A\u3002";
|
|
163102
163171
|
DEFAULT_ASSISTANT_SKILLS = [];
|
|
@@ -165506,7 +165575,7 @@ var init_continuation3 = __esm({
|
|
|
165506
165575
|
|
|
165507
165576
|
// ../server/src/chat-workorder-files.ts
|
|
165508
165577
|
function workOrderFileId(workOrderId, blobId, name) {
|
|
165509
|
-
return `wof:${(0,
|
|
165578
|
+
return `wof:${(0, import_node_crypto23.createHash)("sha256").update(`${workOrderId}|${blobId}|${name}`).digest("hex").slice(0, 32)}`;
|
|
165510
165579
|
}
|
|
165511
165580
|
async function linkChatAttachmentsToWorkOrder(input) {
|
|
165512
165581
|
const warnings = [];
|
|
@@ -165557,11 +165626,11 @@ async function linkChatAttachmentsToWorkOrder(input) {
|
|
|
165557
165626
|
}
|
|
165558
165627
|
return { linked, warnings };
|
|
165559
165628
|
}
|
|
165560
|
-
var
|
|
165629
|
+
var import_node_crypto23;
|
|
165561
165630
|
var init_chat_workorder_files = __esm({
|
|
165562
165631
|
"../server/src/chat-workorder-files.ts"() {
|
|
165563
165632
|
"use strict";
|
|
165564
|
-
|
|
165633
|
+
import_node_crypto23 = require("node:crypto");
|
|
165565
165634
|
}
|
|
165566
165635
|
});
|
|
165567
165636
|
|
|
@@ -166329,11 +166398,11 @@ var init_config_store = __esm({
|
|
|
166329
166398
|
function clone2(value2) {
|
|
166330
166399
|
return structuredClone(value2);
|
|
166331
166400
|
}
|
|
166332
|
-
var
|
|
166401
|
+
var import_node_crypto24, import_promises2, import_node_path5, MemoryKnowledgeRunStore, FileKnowledgeRunStore;
|
|
166333
166402
|
var init_run_store = __esm({
|
|
166334
166403
|
"../server/src/domains/knowledge/run-store.ts"() {
|
|
166335
166404
|
"use strict";
|
|
166336
|
-
|
|
166405
|
+
import_node_crypto24 = require("node:crypto");
|
|
166337
166406
|
import_promises2 = require("node:fs/promises");
|
|
166338
166407
|
import_node_path5 = require("node:path");
|
|
166339
166408
|
MemoryKnowledgeRunStore = class {
|
|
@@ -166450,7 +166519,7 @@ var init_run_store = __esm({
|
|
|
166450
166519
|
}
|
|
166451
166520
|
async persist(runs) {
|
|
166452
166521
|
const shape = { version: 1, runs };
|
|
166453
|
-
const temp = `${this.file}.${process.pid}.${(0,
|
|
166522
|
+
const temp = `${this.file}.${process.pid}.${(0, import_node_crypto24.randomUUID)()}.tmp`;
|
|
166454
166523
|
try {
|
|
166455
166524
|
await (0, import_promises2.writeFile)(temp, `${JSON.stringify(shape, null, 2)}
|
|
166456
166525
|
`, { mode: 384 });
|
|
@@ -167023,11 +167092,11 @@ function retryableKnowledgeRun(record8) {
|
|
|
167023
167092
|
const latestAnswerAttempt = [...record8.attempts ?? []].reverse().find((attempt) => attempt.kind !== "fast");
|
|
167024
167093
|
return record8.status === "succeeded" && record8.request.action === "ask" && record8.executionHealth === "degraded" && latestAnswerAttempt?.status === "failed";
|
|
167025
167094
|
}
|
|
167026
|
-
var
|
|
167095
|
+
var import_node_crypto25, ACTION_LABEL, STATUS_MARKER, FINAL_ANSWER_MARKER, ACTIVE_STATUSES, RETRYABLE_STATUSES, HEARTBEAT_INTERVAL_MS, LEASE_MS, MAX_CONCURRENT_READS, ACTION_FLOW, KnowledgeService;
|
|
167027
167096
|
var init_service2 = __esm({
|
|
167028
167097
|
"../server/src/domains/knowledge/service.ts"() {
|
|
167029
167098
|
"use strict";
|
|
167030
|
-
|
|
167099
|
+
import_node_crypto25 = require("node:crypto");
|
|
167031
167100
|
init_src5();
|
|
167032
167101
|
init_config_store();
|
|
167033
167102
|
init_run_store();
|
|
@@ -167070,7 +167139,7 @@ var init_service2 = __esm({
|
|
|
167070
167139
|
constructor(options) {
|
|
167071
167140
|
this.options = options;
|
|
167072
167141
|
this.now = options.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
|
|
167073
|
-
this.id = options.id ??
|
|
167142
|
+
this.id = options.id ?? import_node_crypto25.randomUUID;
|
|
167074
167143
|
this.runStore = options.runStore ?? new MemoryKnowledgeRunStore();
|
|
167075
167144
|
this.heartbeatIntervalMs = options.heartbeatIntervalMs ?? HEARTBEAT_INTERVAL_MS;
|
|
167076
167145
|
this.leaseMs = options.leaseMs ?? LEASE_MS;
|
|
@@ -178017,7 +178086,7 @@ function stableJson(value2) {
|
|
|
178017
178086
|
return JSON.stringify(stableValue(value2));
|
|
178018
178087
|
}
|
|
178019
178088
|
function sha256(value2) {
|
|
178020
|
-
return (0,
|
|
178089
|
+
return (0, import_node_crypto26.createHash)("sha256").update(value2).digest("hex");
|
|
178021
178090
|
}
|
|
178022
178091
|
function normalizeKnowledgeContent(title, content3) {
|
|
178023
178092
|
const body2 = content3.normalize("NFC").replace(/\r\n?/gu, "\n").replace(PUBLISH_MARKER, "\n").split("\n").map((line) => line.replace(/[\t ]+$/gu, "")).join("\n").replace(/\n{3,}/gu, "\n\n").trim();
|
|
@@ -178256,11 +178325,11 @@ function renderUntrustedKnowledgeFragment(input) {
|
|
|
178256
178325
|
"</knowledge>"
|
|
178257
178326
|
].join("\n");
|
|
178258
178327
|
}
|
|
178259
|
-
var
|
|
178328
|
+
var import_node_crypto26, KNOWLEDGE_NORMALIZER_VERSION, KNOWLEDGE_PACK_TEMPLATE_VERSION, PUBLISH_MARKER, STOPWORDS, LEXICAL_STOPWORDS, lexicalSegmenters, KNOWLEDGE_LEXICAL_INDEX_VERSION, KNOWLEDGE_MAINTENANCE_RELEVANCE_THRESHOLD, KNOWLEDGE_LAYOUT_TERMS;
|
|
178260
178329
|
var init_governance_content = __esm({
|
|
178261
178330
|
"../server/src/domains/knowledge/governance-content.ts"() {
|
|
178262
178331
|
"use strict";
|
|
178263
|
-
|
|
178332
|
+
import_node_crypto26 = require("node:crypto");
|
|
178264
178333
|
init_mdast_util_from_markdown();
|
|
178265
178334
|
init_mdast_util_gfm();
|
|
178266
178335
|
init_micromark_extension_gfm();
|
|
@@ -188427,11 +188496,11 @@ function approvedSnapshotBody(title, content3) {
|
|
|
188427
188496
|
function uniqueStrings(values) {
|
|
188428
188497
|
return [...new Set(values)].sort();
|
|
188429
188498
|
}
|
|
188430
|
-
var
|
|
188499
|
+
var import_node_crypto27, KnowledgeGovernanceError, put2, REMEDIATION_ACTION_BY_TASK, KnowledgeGovernanceService;
|
|
188431
188500
|
var init_governance_service = __esm({
|
|
188432
188501
|
"../server/src/domains/knowledge/governance-service.ts"() {
|
|
188433
188502
|
"use strict";
|
|
188434
|
-
|
|
188503
|
+
import_node_crypto27 = require("node:crypto");
|
|
188435
188504
|
init_governance_content();
|
|
188436
188505
|
init_knowledge_policy();
|
|
188437
188506
|
init_network_maintenance();
|
|
@@ -188453,7 +188522,7 @@ var init_governance_service = __esm({
|
|
|
188453
188522
|
constructor(options) {
|
|
188454
188523
|
this.options = options;
|
|
188455
188524
|
this.now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
188456
|
-
this.id = options.id ?? ((prefix) => `${prefix}_${(0,
|
|
188525
|
+
this.id = options.id ?? ((prefix) => `${prefix}_${(0, import_node_crypto27.randomUUID)()}`);
|
|
188457
188526
|
this.versionViewBaseUrl = (options.versionViewBaseUrl ?? "/api/knowledge/items").replace(/\/$/u, "");
|
|
188458
188527
|
this.projectProvisionRetryDelayMs = Math.max(0, options.projectProvisionRetryDelayMs ?? 6e4);
|
|
188459
188528
|
this.projectProvisionMaxRetryDelayMs = Math.max(this.projectProvisionRetryDelayMs, options.projectProvisionMaxRetryDelayMs ?? 36e5);
|
|
@@ -194144,7 +194213,7 @@ function trustedKnowledgeInvocationId(body2, turn) {
|
|
|
194144
194213
|
if (body2.action !== "ask") return void 0;
|
|
194145
194214
|
const scope = turn?.artifactId ?? turn?.dispatchId;
|
|
194146
194215
|
if (!scope) return void 0;
|
|
194147
|
-
const fingerprint2 = (0,
|
|
194216
|
+
const fingerprint2 = (0, import_node_crypto28.createHash)("sha256").update(JSON.stringify({
|
|
194148
194217
|
action: body2.action,
|
|
194149
194218
|
message: body2.message?.trim() ?? "",
|
|
194150
194219
|
queryMode: body2.queryMode === "deep" ? "deep" : "fast",
|
|
@@ -194299,11 +194368,11 @@ function knowledgeRoutes(service, options = {}) {
|
|
|
194299
194368
|
});
|
|
194300
194369
|
};
|
|
194301
194370
|
}
|
|
194302
|
-
var
|
|
194371
|
+
var import_node_crypto28, KNOWLEDGE_WORKORDER_ACTIONS;
|
|
194303
194372
|
var init_routes = __esm({
|
|
194304
194373
|
"../server/src/domains/knowledge/routes.ts"() {
|
|
194305
194374
|
"use strict";
|
|
194306
|
-
|
|
194375
|
+
import_node_crypto28 = require("node:crypto");
|
|
194307
194376
|
init_src5();
|
|
194308
194377
|
init_router();
|
|
194309
194378
|
init_governance_service();
|
|
@@ -195930,7 +195999,7 @@ async function resolveChatAttachmentDiscoverySource(input) {
|
|
|
195930
195999
|
sourceType: input.sourceType,
|
|
195931
196000
|
sourceId: session.id,
|
|
195932
196001
|
sourceVersionId: attachment.blobRef,
|
|
195933
|
-
sourceFingerprint: (0,
|
|
196002
|
+
sourceFingerprint: (0, import_node_crypto29.createHash)("sha256").update(bytes2).digest("hex"),
|
|
195934
196003
|
sourceContent: new TextDecoder().decode(bytes2),
|
|
195935
196004
|
sourceDisplayName: attachment.name,
|
|
195936
196005
|
...session.projectId ? { projectId: session.projectId } : {},
|
|
@@ -195941,11 +196010,11 @@ async function resolveChatAttachmentDiscoverySource(input) {
|
|
|
195941
196010
|
}
|
|
195942
196011
|
};
|
|
195943
196012
|
}
|
|
195944
|
-
var
|
|
196013
|
+
var import_node_crypto29, TEXT_CONTENT_TYPES;
|
|
195945
196014
|
var init_chat_attachment_discovery = __esm({
|
|
195946
196015
|
"../server/src/domains/knowledge/chat-attachment-discovery.ts"() {
|
|
195947
196016
|
"use strict";
|
|
195948
|
-
|
|
196017
|
+
import_node_crypto29 = require("node:crypto");
|
|
195949
196018
|
TEXT_CONTENT_TYPES = /* @__PURE__ */ new Set([
|
|
195950
196019
|
"application/json",
|
|
195951
196020
|
"application/xml",
|
|
@@ -196122,8 +196191,8 @@ function aad(snapshot) {
|
|
|
196122
196191
|
}
|
|
196123
196192
|
function sealKnowledgeSnapshot(snapshot, key) {
|
|
196124
196193
|
if (snapshot.content.startsWith(PREFIX)) return structuredClone(snapshot);
|
|
196125
|
-
const iv = (0,
|
|
196126
|
-
const cipher = (0,
|
|
196194
|
+
const iv = (0, import_node_crypto30.randomBytes)(12);
|
|
196195
|
+
const cipher = (0, import_node_crypto30.createCipheriv)("aes-256-gcm", keyBytes(key), iv);
|
|
196127
196196
|
cipher.setAAD(aad(snapshot));
|
|
196128
196197
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
196129
196198
|
return {
|
|
@@ -196136,17 +196205,17 @@ function openKnowledgeSnapshot(snapshot, key) {
|
|
|
196136
196205
|
const packed = snapshot.content.slice(PREFIX.length).split(".");
|
|
196137
196206
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
196138
196207
|
const [iv, tag, data] = packed;
|
|
196139
|
-
const decipher = (0,
|
|
196208
|
+
const decipher = (0, import_node_crypto30.createDecipheriv)("aes-256-gcm", keyBytes(key), Buffer.from(iv, "base64url"));
|
|
196140
196209
|
decipher.setAAD(aad(snapshot));
|
|
196141
196210
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
196142
196211
|
const content3 = Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8");
|
|
196143
196212
|
return { ...structuredClone(snapshot), content: content3 };
|
|
196144
196213
|
}
|
|
196145
|
-
var
|
|
196214
|
+
var import_node_crypto30, PREFIX;
|
|
196146
196215
|
var init_snapshot_crypto = __esm({
|
|
196147
196216
|
"../server/src/domains/knowledge/snapshot-crypto.ts"() {
|
|
196148
196217
|
"use strict";
|
|
196149
|
-
|
|
196218
|
+
import_node_crypto30 = require("node:crypto");
|
|
196150
196219
|
PREFIX = "oasis-knowledge:v1:";
|
|
196151
196220
|
}
|
|
196152
196221
|
});
|
|
@@ -196229,11 +196298,11 @@ function uniquenessKeys(kind, record8) {
|
|
|
196229
196298
|
return [];
|
|
196230
196299
|
}
|
|
196231
196300
|
}
|
|
196232
|
-
var
|
|
196301
|
+
var import_node_crypto31, import_promises3, import_node_path6, RECORD_KINDS, MemoryKnowledgeGovernanceStore, FileKnowledgeGovernanceStore;
|
|
196233
196302
|
var init_governance_store = __esm({
|
|
196234
196303
|
"../server/src/domains/knowledge/governance-store.ts"() {
|
|
196235
196304
|
"use strict";
|
|
196236
|
-
|
|
196305
|
+
import_node_crypto31 = require("node:crypto");
|
|
196237
196306
|
import_promises3 = require("node:fs/promises");
|
|
196238
196307
|
import_node_path6 = require("node:path");
|
|
196239
196308
|
init_snapshot_crypto();
|
|
@@ -196451,7 +196520,7 @@ var init_governance_store = __esm({
|
|
|
196451
196520
|
return result;
|
|
196452
196521
|
}
|
|
196453
196522
|
async persist(shape) {
|
|
196454
|
-
const temp = `${this.file}.${process.pid}.${(0,
|
|
196523
|
+
const temp = `${this.file}.${process.pid}.${(0, import_node_crypto31.randomUUID)()}.tmp`;
|
|
196455
196524
|
try {
|
|
196456
196525
|
await (0, import_promises3.writeFile)(temp, `${JSON.stringify(this.sealSnapshots(shape), null, 2)}
|
|
196457
196526
|
`, { mode: 384 });
|
|
@@ -196487,7 +196556,7 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
|
|
|
196487
196556
|
if (error2.code !== "ENOENT") throw error2;
|
|
196488
196557
|
}
|
|
196489
196558
|
await (0, import_promises4.mkdir)((0, import_node_path7.dirname)(file), { recursive: true });
|
|
196490
|
-
const generated = `oasis-${(0,
|
|
196559
|
+
const generated = `oasis-${(0, import_node_crypto32.randomUUID)()}`;
|
|
196491
196560
|
try {
|
|
196492
196561
|
await (0, import_promises4.writeFile)(file, `${generated}
|
|
196493
196562
|
`, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
@@ -196497,11 +196566,11 @@ async function loadOrCreateKnowledgeDeploymentId(file) {
|
|
|
196497
196566
|
return readDeploymentId(file);
|
|
196498
196567
|
}
|
|
196499
196568
|
}
|
|
196500
|
-
var
|
|
196569
|
+
var import_node_crypto32, import_promises4, import_node_path7, VALID_DEPLOYMENT_ID;
|
|
196501
196570
|
var init_deployment_id = __esm({
|
|
196502
196571
|
"../server/src/domains/knowledge/deployment-id.ts"() {
|
|
196503
196572
|
"use strict";
|
|
196504
|
-
|
|
196573
|
+
import_node_crypto32 = require("node:crypto");
|
|
196505
196574
|
import_promises4 = require("node:fs/promises");
|
|
196506
196575
|
import_node_path7 = require("node:path");
|
|
196507
196576
|
VALID_DEPLOYMENT_ID = /^oasis-[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
|
|
@@ -197198,7 +197267,7 @@ var init_files = __esm({
|
|
|
197198
197267
|
|
|
197199
197268
|
// ../server/src/domains/delegations/service.ts
|
|
197200
197269
|
function deterministicUuid(seed) {
|
|
197201
|
-
const h = (0,
|
|
197270
|
+
const h = (0, import_node_crypto33.createHash)("sha256").update(seed).digest();
|
|
197202
197271
|
const b2 = Buffer.from(h.subarray(0, 16));
|
|
197203
197272
|
b2[6] = b2[6] & 15 | 80;
|
|
197204
197273
|
b2[8] = b2[8] & 63 | 128;
|
|
@@ -197255,11 +197324,11 @@ async function seedChildRoundRows(chatStore, childSessionId, round, prompt2, now
|
|
|
197255
197324
|
createdAt: now
|
|
197256
197325
|
});
|
|
197257
197326
|
}
|
|
197258
|
-
var
|
|
197327
|
+
var import_node_crypto33, DelegationError, TITLE_TASK_CHARS, DIGEST_CHARS, PENDING_QUEUE_OWNER, DISPATCH_LEASE_MS, CONSECUTIVE_FAIL_LIMIT, DelegationService;
|
|
197259
197328
|
var init_service3 = __esm({
|
|
197260
197329
|
"../server/src/domains/delegations/service.ts"() {
|
|
197261
197330
|
"use strict";
|
|
197262
|
-
|
|
197331
|
+
import_node_crypto33 = require("node:crypto");
|
|
197263
197332
|
init_src();
|
|
197264
197333
|
init_parent_conversation();
|
|
197265
197334
|
init_deletion();
|
|
@@ -198461,7 +198530,7 @@ var init_continue_outcome = __esm({
|
|
|
198461
198530
|
function trustedDelegationInvocationId(body2, turn) {
|
|
198462
198531
|
const scope = turn?.artifactId ?? turn?.dispatchId;
|
|
198463
198532
|
if (!scope) return void 0;
|
|
198464
|
-
const fingerprint2 = (0,
|
|
198533
|
+
const fingerprint2 = (0, import_node_crypto34.createHash)("sha256").update(JSON.stringify({ to: body2.to?.trim() ?? "", task: body2.task ?? "", as: body2.as?.trim() ?? "", files: body2.files ?? [] })).digest("hex").slice(0, 20);
|
|
198465
198534
|
return `dispatch:${scope}:delegation:${fingerprint2}`;
|
|
198466
198535
|
}
|
|
198467
198536
|
function callerOf(req, invocationId) {
|
|
@@ -198556,11 +198625,11 @@ function delegationRoutes(service) {
|
|
|
198556
198625
|
});
|
|
198557
198626
|
};
|
|
198558
198627
|
}
|
|
198559
|
-
var
|
|
198628
|
+
var import_node_crypto34;
|
|
198560
198629
|
var init_routes2 = __esm({
|
|
198561
198630
|
"../server/src/domains/delegations/routes.ts"() {
|
|
198562
198631
|
"use strict";
|
|
198563
|
-
|
|
198632
|
+
import_node_crypto34 = require("node:crypto");
|
|
198564
198633
|
init_router();
|
|
198565
198634
|
init_continue_outcome();
|
|
198566
198635
|
init_service3();
|
|
@@ -200514,7 +200583,7 @@ function createAppJwt(appId, privateKeyPem, nowMs) {
|
|
|
200514
200583
|
exp: nowSec + JWT_TTL_SEC,
|
|
200515
200584
|
iss: appId
|
|
200516
200585
|
}));
|
|
200517
|
-
const signer = (0,
|
|
200586
|
+
const signer = (0, import_node_crypto35.createSign)("RSA-SHA256");
|
|
200518
200587
|
signer.update(`${header}.${payload2}`);
|
|
200519
200588
|
signer.end();
|
|
200520
200589
|
try {
|
|
@@ -200677,11 +200746,11 @@ async function exchangeManifestCode(code2, deps = {}) {
|
|
|
200677
200746
|
...typeof body2["client_secret"] === "string" ? { clientSecret: body2["client_secret"] } : {}
|
|
200678
200747
|
};
|
|
200679
200748
|
}
|
|
200680
|
-
var
|
|
200749
|
+
var import_node_crypto35, GITHUB_API, JWT_TTL_SEC, JWT_IAT_SKEW_SEC, defaultDeps2;
|
|
200681
200750
|
var init_app_auth = __esm({
|
|
200682
200751
|
"../connectors/src/github/app-auth.ts"() {
|
|
200683
200752
|
"use strict";
|
|
200684
|
-
|
|
200753
|
+
import_node_crypto35 = require("node:crypto");
|
|
200685
200754
|
GITHUB_API = "https://api.github.com";
|
|
200686
200755
|
JWT_TTL_SEC = 9 * 60;
|
|
200687
200756
|
JWT_IAT_SKEW_SEC = 60;
|
|
@@ -201606,11 +201675,11 @@ function extractOutlineKnowledgeCandidateDrafts(events) {
|
|
|
201606
201675
|
}
|
|
201607
201676
|
return [...drafts.values()];
|
|
201608
201677
|
}
|
|
201609
|
-
var
|
|
201678
|
+
var import_node_crypto36, REQUEST_TIMEOUT_MS, WRITE_ENDPOINTS, DEFAULT_WRITE_INTERVAL_MS, DEFAULT_RATE_LIMIT_RETRIES, DEFAULT_MAX_RATE_LIMIT_DELAY_MS, OutlineKnowledgeApiError, writeCoordinators, OutlineKnowledgeApi, INIT_DEFINITIONS, REPAIRABLE_LINT_CODES;
|
|
201610
201679
|
var init_knowledge_api = __esm({
|
|
201611
201680
|
"../connectors/src/outline/knowledge-api.ts"() {
|
|
201612
201681
|
"use strict";
|
|
201613
|
-
|
|
201682
|
+
import_node_crypto36 = require("node:crypto");
|
|
201614
201683
|
REQUEST_TIMEOUT_MS = 2e4;
|
|
201615
201684
|
WRITE_ENDPOINTS = /* @__PURE__ */ new Set(["collections.create", "documents.create", "documents.update", "documents.publish"]);
|
|
201616
201685
|
DEFAULT_WRITE_INTERVAL_MS = process.env["NODE_ENV"] === "test" ? 0 : 250;
|
|
@@ -201637,7 +201706,7 @@ var init_knowledge_api = __esm({
|
|
|
201637
201706
|
this.baseUrl = canonicalUrl(baseUrl);
|
|
201638
201707
|
this.lastResponseBaseUrl = this.baseUrl;
|
|
201639
201708
|
this.token = token;
|
|
201640
|
-
this.coordinatorKey = `${this.baseUrl}:${(0,
|
|
201709
|
+
this.coordinatorKey = `${this.baseUrl}:${(0, import_node_crypto36.createHash)("sha256").update(token).digest("hex")}`;
|
|
201641
201710
|
this.writeIntervalMs = Math.max(0, options.writeIntervalMs ?? DEFAULT_WRITE_INTERVAL_MS);
|
|
201642
201711
|
this.maxRateLimitRetries = Math.max(0, options.maxRateLimitRetries ?? DEFAULT_RATE_LIMIT_RETRIES);
|
|
201643
201712
|
this.maxRateLimitDelayMs = Math.max(0, options.maxRateLimitDelayMs ?? DEFAULT_MAX_RATE_LIMIT_DELAY_MS);
|
|
@@ -203045,15 +203114,15 @@ function classifyOutlineGovernedMigrationDocument(document4) {
|
|
|
203045
203114
|
if (path41.startsWith("wiki/sources/")) return { mapping: "formal", metadata: legacyMetadata(document4, "source_note"), reason: "legacy_source_note" };
|
|
203046
203115
|
return { mapping: "excluded", reason: "legacy_unmapped_path" };
|
|
203047
203116
|
}
|
|
203048
|
-
var
|
|
203117
|
+
var import_node_crypto37, value, text4, hash, REVISION_VISIBILITY_RETRY_DELAYS_MS, governedProvisionRuns, PUBLISH_MARKER2, PUBLISH_MARKER_PRESENT;
|
|
203049
203118
|
var init_governed_knowledge = __esm({
|
|
203050
203119
|
"../connectors/src/outline/governed-knowledge.ts"() {
|
|
203051
203120
|
"use strict";
|
|
203052
|
-
|
|
203121
|
+
import_node_crypto37 = require("node:crypto");
|
|
203053
203122
|
init_knowledge_api();
|
|
203054
203123
|
value = (input) => input && typeof input === "object" && !Array.isArray(input) ? input : null;
|
|
203055
203124
|
text4 = (input) => typeof input === "string" && input.trim() ? input.trim() : null;
|
|
203056
|
-
hash = (input) => (0,
|
|
203125
|
+
hash = (input) => (0, import_node_crypto37.createHash)("sha256").update(input.normalize("NFC").replace(/\r\n?/gu, "\n")).digest("hex");
|
|
203057
203126
|
REVISION_VISIBILITY_RETRY_DELAYS_MS = [0, 100, 250, 500, 1e3, 2e3];
|
|
203058
203127
|
governedProvisionRuns = /* @__PURE__ */ new Map();
|
|
203059
203128
|
PUBLISH_MARKER2 = /\n?<!--\s*oasis-publish:[\s\S]*?-->\n?/giu;
|
|
@@ -205488,14 +205557,7 @@ async function startOasisServer(opts) {
|
|
|
205488
205557
|
}
|
|
205489
205558
|
return null;
|
|
205490
205559
|
};
|
|
205491
|
-
const outputsPartFor = (chatSessionId, companyId) =>
|
|
205492
|
-
const scan2 = opts.sessionOutputsScan;
|
|
205493
|
-
if (!scan2) return void 0;
|
|
205494
|
-
return async () => {
|
|
205495
|
-
const files = await scan2({ chatSessionId, ...companyId !== void 0 ? { companyId } : {} });
|
|
205496
|
-
return files && files.length > 0 ? { type: "outputs", seq: 0, outputs: files } : null;
|
|
205497
|
-
};
|
|
205498
|
-
};
|
|
205560
|
+
const outputsPartFor = (chatSessionId, companyId) => outputsPartProvider(opts.sessionOutputsScan, chatSessionId, companyId);
|
|
205499
205561
|
async function anchorMessageIdFor(origin, storeFor) {
|
|
205500
205562
|
if (!origin) return void 0;
|
|
205501
205563
|
const live = liveChat.messageFor(origin);
|
|
@@ -205734,10 +205796,10 @@ async function startOasisServer(opts) {
|
|
|
205734
205796
|
...fp(p2)
|
|
205735
205797
|
}))
|
|
205736
205798
|
] : [];
|
|
205737
|
-
const { randomUUID:
|
|
205799
|
+
const { randomUUID: randomUUID43 } = await import("node:crypto");
|
|
205738
205800
|
try {
|
|
205739
205801
|
await store.enqueuePendingMessage({
|
|
205740
|
-
id:
|
|
205802
|
+
id: randomUUID43(),
|
|
205741
205803
|
chatSessionId: input.chatSessionId,
|
|
205742
205804
|
text: input.text,
|
|
205743
205805
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -205770,11 +205832,11 @@ async function startOasisServer(opts) {
|
|
|
205770
205832
|
...f2?.mtime ? { srcMtime: f2.mtime } : {}
|
|
205771
205833
|
};
|
|
205772
205834
|
});
|
|
205773
|
-
const { randomUUID:
|
|
205835
|
+
const { randomUUID: randomUUID43 } = await import("node:crypto");
|
|
205774
205836
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
205775
205837
|
try {
|
|
205776
205838
|
await store.enqueuePendingMessage({
|
|
205777
|
-
id:
|
|
205839
|
+
id: randomUUID43(),
|
|
205778
205840
|
chatSessionId: input.chatSessionId,
|
|
205779
205841
|
text: "",
|
|
205780
205842
|
createdAt: nowIso,
|
|
@@ -207021,7 +207083,7 @@ async function startOasisServer(opts) {
|
|
|
207021
207083
|
entry = {
|
|
207022
207084
|
// 旧 CLI 未带 waiterId 时给它塞一个服务端本地生成的——它绝不可能出现在 leave 上,
|
|
207023
207085
|
// 也就绝不会误命中 leftWaiterIds、绝不会被别人的 leave 摘掉。行为与旧 CLI 相同。
|
|
207024
|
-
waiterId: clientWaiterId ?? `server:${(0,
|
|
207086
|
+
waiterId: clientWaiterId ?? `server:${(0, import_node_crypto38.randomUUID)()}`,
|
|
207025
207087
|
onResolve,
|
|
207026
207088
|
expiresAt: expiresAt2,
|
|
207027
207089
|
cleanup: () => clearTimeout(expiryTimer),
|
|
@@ -207102,7 +207164,7 @@ async function startOasisServer(opts) {
|
|
|
207102
207164
|
const openRoom = async () => {
|
|
207103
207165
|
let chatSessionId2;
|
|
207104
207166
|
if (chatStore) {
|
|
207105
|
-
const { randomUUID:
|
|
207167
|
+
const { randomUUID: randomUUID43 } = await import("node:crypto");
|
|
207106
207168
|
const known = discussSessions.get(itemKey);
|
|
207107
207169
|
const knownSession = known ? await chatStore.getSession(known) : null;
|
|
207108
207170
|
if (knownSession && knownSession.workspace === ctx.workspace && knownSession.humanActorId === ctx.ownerId && (!body2.escalationId || knownSession.escalationId === body2.escalationId)) chatSessionId2 = known;
|
|
@@ -207111,7 +207173,7 @@ async function startOasisServer(opts) {
|
|
|
207111
207173
|
chatSessionId2 = existing[0]?.id;
|
|
207112
207174
|
}
|
|
207113
207175
|
if (!chatSessionId2) {
|
|
207114
|
-
chatSessionId2 =
|
|
207176
|
+
chatSessionId2 = randomUUID43();
|
|
207115
207177
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
207116
207178
|
const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
|
|
207117
207179
|
const reg0 = (await resolveEngine(currentCompanyId).catch(() => null))?.registry ?? opts.registry;
|
|
@@ -207980,14 +208042,14 @@ ${composed}`;
|
|
|
207980
208042
|
runtimeSessionId: session.nativeSessionId ?? session.id
|
|
207981
208043
|
}).catch(() => void 0);
|
|
207982
208044
|
}
|
|
207983
|
-
const { randomUUID:
|
|
208045
|
+
const { randomUUID: randomUUID44 } = await import("node:crypto");
|
|
207984
208046
|
const persistAttachments = effectiveAttachments.map((a) => ({
|
|
207985
208047
|
name: a.name,
|
|
207986
208048
|
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
207987
208049
|
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
207988
208050
|
}));
|
|
207989
208051
|
await chatStore.appendMessage({
|
|
207990
|
-
id:
|
|
208052
|
+
id: randomUUID44(),
|
|
207991
208053
|
sessionId: persistTarget.id,
|
|
207992
208054
|
role: "user",
|
|
207993
208055
|
content: persistedUserMessage,
|
|
@@ -208462,8 +208524,8 @@ ${composed}`;
|
|
|
208462
208524
|
}
|
|
208463
208525
|
}
|
|
208464
208526
|
const { spawn: spawn10 } = await import("node:child_process");
|
|
208465
|
-
const { randomUUID:
|
|
208466
|
-
const sessionId = body2.sessionId ??
|
|
208527
|
+
const { randomUUID: randomUUID43 } = await import("node:crypto");
|
|
208528
|
+
const sessionId = body2.sessionId ?? randomUUID43();
|
|
208467
208529
|
const args = [
|
|
208468
208530
|
"-p",
|
|
208469
208531
|
body2.message,
|
|
@@ -208759,8 +208821,8 @@ ${composed}`;
|
|
|
208759
208821
|
res.writeHead(400, { "content-type": "application/json" }).end(JSON.stringify({ error: `\u56DE\u8C03\u5730\u5740\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4E2D\u6B62\uFF08\u907F\u514D\u5728 GitHub \u4E0A\u7559\u4E0B\u5B64\u513F App\uFF09\uFF1A${e.message}` }));
|
|
208760
208822
|
return;
|
|
208761
208823
|
}
|
|
208762
|
-
const { randomUUID:
|
|
208763
|
-
const state =
|
|
208824
|
+
const { randomUUID: randomUUID43 } = await import("node:crypto");
|
|
208825
|
+
const state = randomUUID43();
|
|
208764
208826
|
const nameSlug = (actorName || actorId?.split(":").pop() || owner?.login || "bot").toLowerCase().replace(/[^a-z0-9-]+/g, "-").replace(/^-|-$/g, "").slice(0, 24) || "bot";
|
|
208765
208827
|
const manifest = buildAppManifest({
|
|
208766
208828
|
employeeSlug: nameSlug,
|
|
@@ -209536,12 +209598,12 @@ ${composed}`;
|
|
|
209536
209598
|
}
|
|
209537
209599
|
};
|
|
209538
209600
|
}
|
|
209539
|
-
var http,
|
|
209601
|
+
var http, import_node_crypto38, githubAppPending, connectorAuthSnapshots, CONNECTOR_AUTH_SNAPSHOT_TTL_MS, defaultResolveActor, enc, CHAT_OUTPUT_LIMIT, STREAMING_PATHS, PLANNER_BLOCKING_CODES, WILL_VERBS, GOVERNANCE_COMMANDS, READ_ONLY_COMMANDS, isAgent, isHuman;
|
|
209540
209602
|
var init_server3 = __esm({
|
|
209541
209603
|
"../server/src/server.ts"() {
|
|
209542
209604
|
"use strict";
|
|
209543
209605
|
http = __toESM(require("node:http"), 1);
|
|
209544
|
-
|
|
209606
|
+
import_node_crypto38 = require("node:crypto");
|
|
209545
209607
|
init_chat_session();
|
|
209546
209608
|
init_chat_system_message();
|
|
209547
209609
|
init_src();
|
|
@@ -209700,7 +209762,7 @@ function createNodeTokenStore(file) {
|
|
|
209700
209762
|
return {
|
|
209701
209763
|
issue(nodeId) {
|
|
209702
209764
|
const table = read();
|
|
209703
|
-
const token = `ont_${(0,
|
|
209765
|
+
const token = `ont_${(0, import_node_crypto39.randomBytes)(24).toString("base64url")}`;
|
|
209704
209766
|
table[token] = nodeId;
|
|
209705
209767
|
write(table);
|
|
209706
209768
|
return token;
|
|
@@ -209742,7 +209804,7 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
209742
209804
|
return {
|
|
209743
209805
|
issue(name, ttlMs = defaultTtlMs, companyId) {
|
|
209744
209806
|
const m2 = prune();
|
|
209745
|
-
const token = `ent_${(0,
|
|
209807
|
+
const token = `ent_${(0, import_node_crypto39.randomBytes)(24).toString("base64url")}`;
|
|
209746
209808
|
const expiresAt2 = Date.now() + ttlMs;
|
|
209747
209809
|
m2.set(token, { name, expiresAt: expiresAt2, ...companyId !== void 0 ? { companyId } : {} });
|
|
209748
209810
|
write(m2);
|
|
@@ -209791,33 +209853,33 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
|
|
|
209791
209853
|
}
|
|
209792
209854
|
};
|
|
209793
209855
|
}
|
|
209794
|
-
var
|
|
209856
|
+
var import_node_crypto39, fs18, path19, SESSION_TOKEN_PREFIX, b64url2, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
|
|
209795
209857
|
var init_tokens = __esm({
|
|
209796
209858
|
"../server/src/tokens.ts"() {
|
|
209797
209859
|
"use strict";
|
|
209798
|
-
|
|
209860
|
+
import_node_crypto39 = require("node:crypto");
|
|
209799
209861
|
fs18 = __toESM(require("node:fs"), 1);
|
|
209800
209862
|
path19 = __toESM(require("node:path"), 1);
|
|
209801
209863
|
SESSION_TOKEN_PREFIX = "oat_v2_";
|
|
209802
209864
|
b64url2 = (value2) => Buffer.from(value2).toString("base64url");
|
|
209803
209865
|
fromB64url = (value2) => Buffer.from(value2, "base64url").toString("utf8");
|
|
209804
209866
|
readOrCreateSecret = (file) => {
|
|
209805
|
-
if (!file) return (0,
|
|
209867
|
+
if (!file) return (0, import_node_crypto39.randomBytes)(32);
|
|
209806
209868
|
try {
|
|
209807
209869
|
const raw = fs18.readFileSync(file, "utf8").trim();
|
|
209808
209870
|
if (raw) return Buffer.from(raw, "base64url");
|
|
209809
209871
|
} catch {
|
|
209810
209872
|
}
|
|
209811
|
-
const secret = (0,
|
|
209873
|
+
const secret = (0, import_node_crypto39.randomBytes)(32);
|
|
209812
209874
|
fs18.mkdirSync(path19.dirname(file), { recursive: true });
|
|
209813
209875
|
fs18.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
209814
209876
|
return secret;
|
|
209815
209877
|
};
|
|
209816
|
-
sign = (secret, payload2) => (0,
|
|
209878
|
+
sign = (secret, payload2) => (0, import_node_crypto39.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
209817
209879
|
signatureMatches = (actual, expected) => {
|
|
209818
209880
|
const a = Buffer.from(actual);
|
|
209819
209881
|
const b2 = Buffer.from(expected);
|
|
209820
|
-
return a.length === b2.length && (0,
|
|
209882
|
+
return a.length === b2.length && (0, import_node_crypto39.timingSafeEqual)(a, b2);
|
|
209821
209883
|
};
|
|
209822
209884
|
isTokenClaims = (value2) => {
|
|
209823
209885
|
if (value2 === null || typeof value2 !== "object") return false;
|
|
@@ -209864,31 +209926,31 @@ function createDataplaneTokenIssuer(opts = {}) {
|
|
|
209864
209926
|
}
|
|
209865
209927
|
};
|
|
209866
209928
|
}
|
|
209867
|
-
var
|
|
209929
|
+
var import_node_crypto40, fs19, path20, PREFIX2, b64url3, fromB64url2, sign2, sigMatches, readOrCreateSecret2, isClaims;
|
|
209868
209930
|
var init_session_dataplane_token = __esm({
|
|
209869
209931
|
"../server/src/session-dataplane-token.ts"() {
|
|
209870
209932
|
"use strict";
|
|
209871
|
-
|
|
209933
|
+
import_node_crypto40 = require("node:crypto");
|
|
209872
209934
|
fs19 = __toESM(require("node:fs"), 1);
|
|
209873
209935
|
path20 = __toESM(require("node:path"), 1);
|
|
209874
209936
|
init_src();
|
|
209875
209937
|
PREFIX2 = "osd_";
|
|
209876
209938
|
b64url3 = (v2) => Buffer.from(v2, "utf8").toString("base64url");
|
|
209877
209939
|
fromB64url2 = (v2) => Buffer.from(v2, "base64url").toString("utf8");
|
|
209878
|
-
sign2 = (secret, payload2) => (0,
|
|
209940
|
+
sign2 = (secret, payload2) => (0, import_node_crypto40.createHmac)("sha256", secret).update(payload2).digest("base64url");
|
|
209879
209941
|
sigMatches = (actual, expected) => {
|
|
209880
209942
|
const a = Buffer.from(actual);
|
|
209881
209943
|
const b2 = Buffer.from(expected);
|
|
209882
|
-
return a.length === b2.length && (0,
|
|
209944
|
+
return a.length === b2.length && (0, import_node_crypto40.timingSafeEqual)(a, b2);
|
|
209883
209945
|
};
|
|
209884
209946
|
readOrCreateSecret2 = (file) => {
|
|
209885
|
-
if (!file) return (0,
|
|
209947
|
+
if (!file) return (0, import_node_crypto40.randomBytes)(32);
|
|
209886
209948
|
try {
|
|
209887
209949
|
const raw = fs19.readFileSync(file, "utf8").trim();
|
|
209888
209950
|
if (raw) return Buffer.from(raw, "base64url");
|
|
209889
209951
|
} catch {
|
|
209890
209952
|
}
|
|
209891
|
-
const secret = (0,
|
|
209953
|
+
const secret = (0, import_node_crypto40.randomBytes)(32);
|
|
209892
209954
|
fs19.mkdirSync(path20.dirname(file), { recursive: true });
|
|
209893
209955
|
fs19.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
|
|
209894
209956
|
return secret;
|
|
@@ -212034,11 +212096,11 @@ function onlyHits(pool, q2) {
|
|
|
212034
212096
|
if (!q2.requireMatch || q2.keywords.length === 0) return [...pool];
|
|
212035
212097
|
return pool.filter((r) => memoryMatchScore(r, q2.keywords) > 0);
|
|
212036
212098
|
}
|
|
212037
|
-
var
|
|
212099
|
+
var import_node_crypto41, MemoryActorMemoryStore, toIndexEntry;
|
|
212038
212100
|
var init_memory_actor_memory_store = __esm({
|
|
212039
212101
|
"../testkit/src/memory-actor-memory-store.ts"() {
|
|
212040
212102
|
"use strict";
|
|
212041
|
-
|
|
212103
|
+
import_node_crypto41 = require("node:crypto");
|
|
212042
212104
|
init_src();
|
|
212043
212105
|
MemoryActorMemoryStore = class {
|
|
212044
212106
|
rows = /* @__PURE__ */ new Map();
|
|
@@ -212092,7 +212154,7 @@ var init_memory_actor_memory_store = __esm({
|
|
|
212092
212154
|
async write(input, now) {
|
|
212093
212155
|
if (input.memId === void 0) {
|
|
212094
212156
|
const rec = {
|
|
212095
|
-
memId: `mem:${(0,
|
|
212157
|
+
memId: `mem:${(0, import_node_crypto41.randomUUID)()}`,
|
|
212096
212158
|
actorId: input.actorId,
|
|
212097
212159
|
projectId: input.projectId,
|
|
212098
212160
|
keywords: [...input.keywords],
|
|
@@ -212824,6 +212886,19 @@ var init_stats = __esm({
|
|
|
212824
212886
|
}
|
|
212825
212887
|
});
|
|
212826
212888
|
|
|
212889
|
+
// ../server/src/domains/projects/project-id.ts
|
|
212890
|
+
function randomProjectId() {
|
|
212891
|
+
return projectIdFromUuid((0, import_node_crypto42.randomUUID)());
|
|
212892
|
+
}
|
|
212893
|
+
var import_node_crypto42;
|
|
212894
|
+
var init_project_id = __esm({
|
|
212895
|
+
"../server/src/domains/projects/project-id.ts"() {
|
|
212896
|
+
"use strict";
|
|
212897
|
+
import_node_crypto42 = require("node:crypto");
|
|
212898
|
+
init_src();
|
|
212899
|
+
}
|
|
212900
|
+
});
|
|
212901
|
+
|
|
212827
212902
|
// ../server/src/domains/projects/service.ts
|
|
212828
212903
|
function sanitizeCreatorActorId(raw) {
|
|
212829
212904
|
const id = raw?.trim();
|
|
@@ -212884,7 +212959,7 @@ function creatorKindOf(actorId) {
|
|
|
212884
212959
|
if (!actorId) return null;
|
|
212885
212960
|
return actorId.startsWith("actor:human:") ? "human" : "agent";
|
|
212886
212961
|
}
|
|
212887
|
-
function emitChatFolders(items, chatFiles, resolveName) {
|
|
212962
|
+
function emitChatFolders(items, chatFiles, resolveName, taskTitles = /* @__PURE__ */ new Map()) {
|
|
212888
212963
|
const groups = /* @__PURE__ */ new Map();
|
|
212889
212964
|
for (const file of chatFiles) {
|
|
212890
212965
|
const list2 = groups.get(file.chatSessionId) ?? [];
|
|
@@ -212904,14 +212979,15 @@ function emitChatFolders(items, chatFiles, resolveName) {
|
|
|
212904
212979
|
depth: 0,
|
|
212905
212980
|
type: "folder",
|
|
212906
212981
|
size: null,
|
|
212907
|
-
taskId: null,
|
|
212908
|
-
taskTitle: CHAT_FOLDER_TASK_LABEL,
|
|
212982
|
+
taskId: head.taskId ?? null,
|
|
212983
|
+
taskTitle: head.taskId ? taskTitles.get(head.taskId) ?? head.taskId : CHAT_FOLDER_TASK_LABEL,
|
|
212909
212984
|
creatorKind: creatorKindOf(head.chatOwnerId),
|
|
212910
212985
|
creatorId: head.chatOwnerId,
|
|
212911
212986
|
creatorName: resolveName(head.chatOwnerId),
|
|
212912
212987
|
updatedAt: latest,
|
|
212913
212988
|
folderKind: "chat",
|
|
212914
|
-
chatSessionId: sessionId
|
|
212989
|
+
chatSessionId: sessionId,
|
|
212990
|
+
...head.fileIssues?.length ? { fileIssues: head.fileIssues } : {}
|
|
212915
212991
|
});
|
|
212916
212992
|
for (const file of group) {
|
|
212917
212993
|
items.push({
|
|
@@ -212925,13 +213001,14 @@ function emitChatFolders(items, chatFiles, resolveName) {
|
|
|
212925
213001
|
blobRef: file.blobId,
|
|
212926
213002
|
contentType: file.contentType ?? null,
|
|
212927
213003
|
size: file.size,
|
|
212928
|
-
taskId: null,
|
|
212929
|
-
taskTitle: CHAT_FOLDER_TASK_LABEL,
|
|
213004
|
+
taskId: head.taskId ?? null,
|
|
213005
|
+
taskTitle: head.taskId ? taskTitles.get(head.taskId) ?? head.taskId : CHAT_FOLDER_TASK_LABEL,
|
|
212930
213006
|
creatorKind: creatorKindOf(file.uploadedBy),
|
|
212931
213007
|
creatorId: file.uploadedBy ?? null,
|
|
212932
213008
|
creatorName: file.uploadedBy ? resolveName(file.uploadedBy) : null,
|
|
212933
213009
|
updatedAt: file.uploadedAt,
|
|
212934
|
-
chatSessionId: sessionId
|
|
213010
|
+
chatSessionId: sessionId,
|
|
213011
|
+
...head.fileIssues?.length ? { fileIssues: head.fileIssues } : {}
|
|
212935
213012
|
});
|
|
212936
213013
|
}
|
|
212937
213014
|
}
|
|
@@ -212965,10 +213042,6 @@ function namedError(name, message) {
|
|
|
212965
213042
|
err.name = name;
|
|
212966
213043
|
return err;
|
|
212967
213044
|
}
|
|
212968
|
-
function slugProjectId(name) {
|
|
212969
|
-
const slug6 = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
212970
|
-
return `proj_${slug6 || Date.now()}`;
|
|
212971
|
-
}
|
|
212972
213045
|
function dirname24(path41) {
|
|
212973
213046
|
const norm = path41.replace(/^\/+|\/+$/g, "");
|
|
212974
213047
|
const idx = norm.lastIndexOf("/");
|
|
@@ -213165,6 +213238,7 @@ var init_service4 = __esm({
|
|
|
213165
213238
|
init_uncategorized_project();
|
|
213166
213239
|
init_workorders();
|
|
213167
213240
|
init_stats();
|
|
213241
|
+
init_project_id();
|
|
213168
213242
|
init_node_state();
|
|
213169
213243
|
DEFAULT_AGENT_ACTOR = "actor:agent:system";
|
|
213170
213244
|
CHAT_FOLDER_TASK_LABEL = "\u5BF9\u8BDD";
|
|
@@ -213454,9 +213528,14 @@ var init_service4 = __esm({
|
|
|
213454
213528
|
async createProject(input) {
|
|
213455
213529
|
if (!input.name.trim()) throw new Error("project name is required");
|
|
213456
213530
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
213457
|
-
|
|
213458
|
-
|
|
213459
|
-
|
|
213531
|
+
let id;
|
|
213532
|
+
if (input.id !== void 0 && input.id.trim() !== "") {
|
|
213533
|
+
id = input.id;
|
|
213534
|
+
const existing = await this.projects.getProject(id);
|
|
213535
|
+
if (existing) return this.withProjectDerivedState(existing);
|
|
213536
|
+
} else {
|
|
213537
|
+
id = await this.allocateProjectId();
|
|
213538
|
+
}
|
|
213460
213539
|
const createdById = sanitizeCreatorActorId(input.createdBy);
|
|
213461
213540
|
const project = {
|
|
213462
213541
|
id,
|
|
@@ -213492,6 +213571,14 @@ var init_service4 = __esm({
|
|
|
213492
213571
|
}
|
|
213493
213572
|
return await this.getProject(id) ?? project;
|
|
213494
213573
|
}
|
|
213574
|
+
/** 给「没带 id 的新建」挑一个本公司还没用过的随机 id(`randomProjectId`);连撞几次说明生成器坏了,直接报错。 */
|
|
213575
|
+
async allocateProjectId() {
|
|
213576
|
+
for (let attempt = 0; attempt < 5; attempt++) {
|
|
213577
|
+
const id = randomProjectId();
|
|
213578
|
+
if (!await this.projects.getProject(id)) return id;
|
|
213579
|
+
}
|
|
213580
|
+
throw new Error("project id allocation failed: random ids kept colliding");
|
|
213581
|
+
}
|
|
213495
213582
|
async getProject(id) {
|
|
213496
213583
|
if (isUncategorizedProjectId(id)) return this.buildUncategorizedProject();
|
|
213497
213584
|
const project = await this.projects.getProject(id);
|
|
@@ -213983,7 +214070,7 @@ var init_service4 = __esm({
|
|
|
213983
214070
|
updatedAt: file.uploadedAt
|
|
213984
214071
|
});
|
|
213985
214072
|
}
|
|
213986
|
-
emitChatFolders(items, chatFiles, (actorId) => this.resolveActorName(actorId));
|
|
214073
|
+
emitChatFolders(items, chatFiles, (actorId) => this.resolveActorName(actorId), workorderTitleById);
|
|
213987
214074
|
fillFolderSizes(items);
|
|
213988
214075
|
const chatFolderTime = new Map(items.filter((item) => item.folderKind === "chat" && item.chatSessionId).map((item) => [item.chatSessionId, item.updatedAt]));
|
|
213989
214076
|
items.sort((a, b2) => {
|
|
@@ -214834,12 +214921,12 @@ var init_service4 = __esm({
|
|
|
214834
214921
|
});
|
|
214835
214922
|
|
|
214836
214923
|
// ../server/src/dev-store.ts
|
|
214837
|
-
var
|
|
214924
|
+
var import_node_crypto43, fs20, path21, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRoleRegistryStore, FileRegistryStore, FileAssistantBindStore, FileHumanPrefsStore, FileProjectStateStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore, MemoryChatTurnStore, FileChatTurnStore, MemoryReadMarkerStore, FileReadMarkerStore;
|
|
214838
214925
|
var init_dev_store = __esm({
|
|
214839
214926
|
"../server/src/dev-store.ts"() {
|
|
214840
214927
|
"use strict";
|
|
214841
214928
|
init_src();
|
|
214842
|
-
|
|
214929
|
+
import_node_crypto43 = require("node:crypto");
|
|
214843
214930
|
fs20 = __toESM(require("node:fs"), 1);
|
|
214844
214931
|
path21 = __toESM(require("node:path"), 1);
|
|
214845
214932
|
init_src();
|
|
@@ -214893,7 +214980,7 @@ var init_dev_store = __esm({
|
|
|
214893
214980
|
return path21.join(this.dir, hash2);
|
|
214894
214981
|
}
|
|
214895
214982
|
async put(bytes2) {
|
|
214896
|
-
const hash2 = (0,
|
|
214983
|
+
const hash2 = (0, import_node_crypto43.createHash)("sha256").update(bytes2).digest("hex");
|
|
214897
214984
|
const file = this.fileOf(hash2);
|
|
214898
214985
|
if (!fs20.existsSync(file)) fs20.writeFileSync(file, bytes2);
|
|
214899
214986
|
return hash2;
|
|
@@ -215321,6 +215408,8 @@ var init_dev_store = __esm({
|
|
|
215321
215408
|
pending = /* @__PURE__ */ new Map();
|
|
215322
215409
|
/** `outputs/` 产出文件的服务端副本表(2026-09-14):sessionId → 路径 → 副本。 */
|
|
215323
215410
|
outputCopies = /* @__PURE__ */ new Map();
|
|
215411
|
+
outputFingerprints = /* @__PURE__ */ new Map();
|
|
215412
|
+
fileIssues = /* @__PURE__ */ new Map();
|
|
215324
215413
|
pendingSeq = 0;
|
|
215325
215414
|
async claimPendingInsert(m2) {
|
|
215326
215415
|
const list2 = this.pending.get(m2.chatSessionId) ?? [];
|
|
@@ -215509,6 +215598,8 @@ var init_dev_store = __esm({
|
|
|
215509
215598
|
this.sessionWorkOrders.delete(id);
|
|
215510
215599
|
this.sessionWorkOrderKinds.delete(id);
|
|
215511
215600
|
this.outputCopies.delete(id);
|
|
215601
|
+
this.outputFingerprints.delete(id);
|
|
215602
|
+
this.fileIssues.delete(id);
|
|
215512
215603
|
}
|
|
215513
215604
|
async appendMessage(m2) {
|
|
215514
215605
|
return (await this.appendMessageOnce(m2)).message;
|
|
@@ -215637,6 +215728,22 @@ var init_dev_store = __esm({
|
|
|
215637
215728
|
}
|
|
215638
215729
|
return rows.sort((left, right) => left.createdAt.localeCompare(right.createdAt) || left.messageId.localeCompare(right.messageId));
|
|
215639
215730
|
}
|
|
215731
|
+
async readOutputFingerprints(sessionId) {
|
|
215732
|
+
return this.outputFingerprints.get(sessionId) ?? null;
|
|
215733
|
+
}
|
|
215734
|
+
async writeOutputFingerprints(sessionId, fingerprints) {
|
|
215735
|
+
if (this.sessions.has(sessionId)) this.outputFingerprints.set(sessionId, { ...fingerprints });
|
|
215736
|
+
}
|
|
215737
|
+
async readFileIssues(sessionId) {
|
|
215738
|
+
return (this.fileIssues.get(sessionId) ?? []).map((issue2) => ({ ...issue2 }));
|
|
215739
|
+
}
|
|
215740
|
+
async writeFileIssues(sessionId, phase, issues) {
|
|
215741
|
+
if (!this.sessions.has(sessionId)) return;
|
|
215742
|
+
this.fileIssues.set(sessionId, [...(this.fileIssues.get(sessionId) ?? []).filter((i) => i.phase !== phase), ...issues]);
|
|
215743
|
+
}
|
|
215744
|
+
async listFileSessionsByWorkspaces(workspaces) {
|
|
215745
|
+
return [...this.sessions.values()].filter((s2) => !!s2.workspace && workspaces.includes(s2.workspace) && s2.visibility !== "internal" && !s2.analyzedRunId).map((s2) => ({ ...s2 }));
|
|
215746
|
+
}
|
|
215640
215747
|
async readOutputCopies(sessionId) {
|
|
215641
215748
|
const hit = this.outputCopies.get(sessionId);
|
|
215642
215749
|
return hit ? { ...hit } : null;
|
|
@@ -215697,6 +215804,9 @@ var init_dev_store = __esm({
|
|
|
215697
215804
|
const store = new _FileChatSessionStore(file);
|
|
215698
215805
|
if (fs20.existsSync(file)) {
|
|
215699
215806
|
const snap = JSON.parse(fs20.readFileSync(file, "utf8"));
|
|
215807
|
+
for (const [sid, copies] of Object.entries(snap.outputCopies ?? {})) store.outputCopies.set(sid, copies);
|
|
215808
|
+
for (const [sid, fps] of Object.entries(snap.outputFingerprints ?? {})) store.outputFingerprints.set(sid, fps);
|
|
215809
|
+
for (const [sid, issues] of Object.entries(snap.fileIssues ?? {})) store.fileIssues.set(sid, issues);
|
|
215700
215810
|
for (const s2 of snap.sessions ?? []) store.sessions.set(s2.id, s2);
|
|
215701
215811
|
for (const [sid, list2] of Object.entries(snap.messages ?? {})) store.messages.set(sid, list2);
|
|
215702
215812
|
for (const [sid, ids2] of Object.entries(snap.sessionWorkOrders ?? {})) store.sessionWorkOrders.set(sid, new Set(ids2));
|
|
@@ -215708,6 +215818,18 @@ var init_dev_store = __esm({
|
|
|
215708
215818
|
}
|
|
215709
215819
|
return store;
|
|
215710
215820
|
}
|
|
215821
|
+
async mergeOutputCopies(id, copies) {
|
|
215822
|
+
await super.mergeOutputCopies(id, copies);
|
|
215823
|
+
this.save();
|
|
215824
|
+
}
|
|
215825
|
+
async writeOutputFingerprints(id, fps) {
|
|
215826
|
+
await super.writeOutputFingerprints(id, fps);
|
|
215827
|
+
this.save();
|
|
215828
|
+
}
|
|
215829
|
+
async writeFileIssues(id, phase, issues) {
|
|
215830
|
+
await super.writeFileIssues(id, phase, issues);
|
|
215831
|
+
this.save();
|
|
215832
|
+
}
|
|
215711
215833
|
async createSession(s2) {
|
|
215712
215834
|
await super.createSession(s2);
|
|
215713
215835
|
this.save();
|
|
@@ -215773,6 +215895,9 @@ var init_dev_store = __esm({
|
|
|
215773
215895
|
}
|
|
215774
215896
|
save() {
|
|
215775
215897
|
const snap = {
|
|
215898
|
+
outputCopies: Object.fromEntries(this.outputCopies),
|
|
215899
|
+
outputFingerprints: Object.fromEntries(this.outputFingerprints),
|
|
215900
|
+
fileIssues: Object.fromEntries(this.fileIssues),
|
|
215776
215901
|
sessions: [...this.sessions.values()],
|
|
215777
215902
|
messages: Object.fromEntries(this.messages),
|
|
215778
215903
|
sessionWorkOrders: Object.fromEntries([...this.sessionWorkOrders].map(([k2, v2]) => [k2, [...v2]])),
|
|
@@ -216093,7 +216218,7 @@ var init_company_engine_router = __esm({
|
|
|
216093
216218
|
|
|
216094
216219
|
// ../server/src/skill-market-client.ts
|
|
216095
216220
|
function digestOf2(bytes2) {
|
|
216096
|
-
return `sha256:${(0,
|
|
216221
|
+
return `sha256:${(0, import_node_crypto44.createHash)("sha256").update(bytes2).digest("hex")}`;
|
|
216097
216222
|
}
|
|
216098
216223
|
function createSkillMarketClientFromEnv(env = process.env) {
|
|
216099
216224
|
const base = env["SKILL_MARKET_BASE_URL"];
|
|
@@ -216104,11 +216229,11 @@ function createSkillMarketClientFromEnv(env = process.env) {
|
|
|
216104
216229
|
function sleep4(ms) {
|
|
216105
216230
|
return new Promise((r) => setTimeout(r, ms));
|
|
216106
216231
|
}
|
|
216107
|
-
var
|
|
216232
|
+
var import_node_crypto44, DisabledSkillMarketClient, HttpSkillMarketClient;
|
|
216108
216233
|
var init_skill_market_client = __esm({
|
|
216109
216234
|
"../server/src/skill-market-client.ts"() {
|
|
216110
216235
|
"use strict";
|
|
216111
|
-
|
|
216236
|
+
import_node_crypto44 = require("node:crypto");
|
|
216112
216237
|
init_src();
|
|
216113
216238
|
DisabledSkillMarketClient = class {
|
|
216114
216239
|
async listSkills(_input) {
|
|
@@ -216592,18 +216717,23 @@ async function scanSessionOutputs(bridge, loc, now = Date.now) {
|
|
|
216592
216717
|
if (!walked) return null;
|
|
216593
216718
|
if (walked.ok) {
|
|
216594
216719
|
const files2 = walked.entries.filter((entry) => entry.type === "file").map((entry) => ({ path: entry.path, size: entry.size, mtime: entry.mtime }));
|
|
216595
|
-
return { files: files2, via: "walk", tree: walked.entries };
|
|
216720
|
+
return { files: files2, via: "walk", tree: walked.entries, ...walked.truncated ? { incomplete: true } : {} };
|
|
216596
216721
|
}
|
|
216597
216722
|
if (walked.code === "NOT_FOUND") return { files: [], via: "walk", tree: [] };
|
|
216598
216723
|
if (walked.code !== "UNSUPPORTED") return null;
|
|
216599
216724
|
}
|
|
216725
|
+
let incomplete = false;
|
|
216600
216726
|
const files = await scanLayered(
|
|
216601
216727
|
(path41) => bridge.list(loc.nodeId, { ...locator, path: path41 }),
|
|
216602
|
-
now
|
|
216728
|
+
now,
|
|
216729
|
+
() => {
|
|
216730
|
+
incomplete = true;
|
|
216731
|
+
}
|
|
216603
216732
|
);
|
|
216604
|
-
return files === null ? null : { files, via: "layered" };
|
|
216733
|
+
return files === null ? null : { files, via: "layered", ...incomplete ? { incomplete: true } : {} };
|
|
216605
216734
|
}
|
|
216606
|
-
async function scanLayered(list2, now) {
|
|
216735
|
+
async function scanLayered(list2, now, markIncomplete = () => {
|
|
216736
|
+
}) {
|
|
216607
216737
|
const deadline = now() + BUDGET_MS;
|
|
216608
216738
|
const out = [];
|
|
216609
216739
|
let listCalls = 0;
|
|
@@ -216620,23 +216750,41 @@ async function scanLayered(list2, now) {
|
|
|
216620
216750
|
for (let depth = 0; depth <= MAX_DEPTH; depth += 1) {
|
|
216621
216751
|
const nextDirs = [];
|
|
216622
216752
|
for (const { path: dir, outcome } of level) {
|
|
216623
|
-
if (!outcome.ok)
|
|
216753
|
+
if (!outcome.ok) {
|
|
216754
|
+
markIncomplete();
|
|
216755
|
+
continue;
|
|
216756
|
+
}
|
|
216757
|
+
if (outcome.truncated) markIncomplete();
|
|
216624
216758
|
for (const entry of outcome.entries) {
|
|
216625
216759
|
if (entry.type === "dir") {
|
|
216626
216760
|
nextDirs.push(joinRel(dir, entry.name));
|
|
216627
216761
|
continue;
|
|
216628
216762
|
}
|
|
216629
|
-
if (out.length >= MAX_ENTRIES)
|
|
216763
|
+
if (out.length >= MAX_ENTRIES) {
|
|
216764
|
+
markIncomplete();
|
|
216765
|
+
continue;
|
|
216766
|
+
}
|
|
216630
216767
|
out.push({ path: joinRel(dir, entry.name), size: entry.size, mtime: entry.mtime });
|
|
216631
216768
|
}
|
|
216632
216769
|
}
|
|
216633
|
-
if (nextDirs.length === 0
|
|
216634
|
-
if (
|
|
216770
|
+
if (nextDirs.length === 0) break;
|
|
216771
|
+
if (depth === MAX_DEPTH) {
|
|
216772
|
+
markIncomplete();
|
|
216773
|
+
break;
|
|
216774
|
+
}
|
|
216775
|
+
if (out.length >= MAX_ENTRIES || listCalls >= MAX_LIST_CALLS || now() >= deadline) {
|
|
216776
|
+
markIncomplete();
|
|
216777
|
+
break;
|
|
216778
|
+
}
|
|
216635
216779
|
const batch = [];
|
|
216636
216780
|
for (const dir of nextDirs) {
|
|
216637
|
-
if (listCalls >= MAX_LIST_CALLS || now() >= deadline)
|
|
216781
|
+
if (listCalls >= MAX_LIST_CALLS || now() >= deadline) {
|
|
216782
|
+
markIncomplete();
|
|
216783
|
+
break;
|
|
216784
|
+
}
|
|
216638
216785
|
const outcome = await listDir(dir).catch(() => null);
|
|
216639
216786
|
if (outcome) batch.push({ path: dir, outcome });
|
|
216787
|
+
else markIncomplete();
|
|
216640
216788
|
}
|
|
216641
216789
|
level = batch;
|
|
216642
216790
|
}
|
|
@@ -216667,7 +216815,7 @@ async function settleSessionOutputs(deps) {
|
|
|
216667
216815
|
diff.fingerprints[WALK_TABLE_MARK] = { size: 0, mtime: "" };
|
|
216668
216816
|
}
|
|
216669
216817
|
await deps.writeFingerprints(deps.sessionId, diff.fingerprints).catch(() => void 0);
|
|
216670
|
-
return diff;
|
|
216818
|
+
return { ...diff, ...scan2.incomplete || scan2.files.some((f2) => f2.size == null || !f2.mtime) ? { scanIncomplete: true } : {} };
|
|
216671
216819
|
}
|
|
216672
216820
|
var WALK_MAX_ENTRIES, MAX_DEPTH, MAX_ENTRIES, MAX_LIST_CALLS, BUDGET_MS, WALK_TABLE_MARK;
|
|
216673
216821
|
var init_outputs_scan = __esm({
|
|
@@ -216722,11 +216870,17 @@ async function copySessionOutputs(deps) {
|
|
|
216722
216870
|
try {
|
|
216723
216871
|
existing = await deps.readCopies(deps.sessionId);
|
|
216724
216872
|
} catch {
|
|
216873
|
+
result.skipped = Object.keys(deps.fingerprints).filter(isOutputPath).map((path41) => ({ path: path41, code: "STORE_FAILED" }));
|
|
216725
216874
|
return result;
|
|
216726
216875
|
}
|
|
216876
|
+
const deadline = Date.now() + 2e4;
|
|
216727
216877
|
const plan = planOutputCopies(deps.fingerprints, existing, limits);
|
|
216728
216878
|
result.skipped.push(...plan.skipped);
|
|
216729
216879
|
for (const file of plan.toCopy) {
|
|
216880
|
+
if (Date.now() >= deadline) {
|
|
216881
|
+
result.skipped.push({ path: file.path, code: "BUDGET" });
|
|
216882
|
+
continue;
|
|
216883
|
+
}
|
|
216730
216884
|
let read;
|
|
216731
216885
|
try {
|
|
216732
216886
|
read = await deps.bridge.read(
|
|
@@ -216743,6 +216897,14 @@ async function copySessionOutputs(deps) {
|
|
|
216743
216897
|
continue;
|
|
216744
216898
|
}
|
|
216745
216899
|
const bytes2 = Buffer.from(read.contentBase64, "base64");
|
|
216900
|
+
if (bytes2.length > limits.maxFileBytes) {
|
|
216901
|
+
result.skipped.push({ path: file.path, code: "TOO_LARGE" });
|
|
216902
|
+
continue;
|
|
216903
|
+
}
|
|
216904
|
+
if (bytes2.length !== file.size || read.mtime && read.mtime !== file.mtime) {
|
|
216905
|
+
result.skipped.push({ path: file.path, code: "FILE_CHANGED" });
|
|
216906
|
+
continue;
|
|
216907
|
+
}
|
|
216746
216908
|
let blobRef;
|
|
216747
216909
|
try {
|
|
216748
216910
|
blobRef = await deps.putBlob(new Uint8Array(bytes2));
|
|
@@ -216772,7 +216934,7 @@ async function copySessionOutputs(deps) {
|
|
|
216772
216934
|
return result;
|
|
216773
216935
|
}
|
|
216774
216936
|
function createOutputCopyScheduler(deps) {
|
|
216775
|
-
const inFlight = /* @__PURE__ */ new
|
|
216937
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
216776
216938
|
return {
|
|
216777
216939
|
schedule(args) {
|
|
216778
216940
|
const { store, chatSessionId, companyId } = args;
|
|
@@ -216780,9 +216942,10 @@ function createOutputCopyScheduler(deps) {
|
|
|
216780
216942
|
const mergeCopies = store.mergeOutputCopies?.bind(store);
|
|
216781
216943
|
if (!readCopies || !mergeCopies) return Promise.resolve(null);
|
|
216782
216944
|
const key = `${companyId ?? ""}|${chatSessionId}`;
|
|
216783
|
-
|
|
216784
|
-
|
|
216785
|
-
|
|
216945
|
+
const prior = inFlight.get(key);
|
|
216946
|
+
let pending;
|
|
216947
|
+
pending = (async () => {
|
|
216948
|
+
await prior;
|
|
216786
216949
|
try {
|
|
216787
216950
|
const session = await store.getSession(chatSessionId);
|
|
216788
216951
|
if (!session || session.visibility === "internal" || session.analyzedRunId) return null;
|
|
@@ -216797,6 +216960,21 @@ function createOutputCopyScheduler(deps) {
|
|
|
216797
216960
|
putBlob: deps.putBlob,
|
|
216798
216961
|
...deps.limits ? { limits: deps.limits } : {}
|
|
216799
216962
|
});
|
|
216963
|
+
const messages = {
|
|
216964
|
+
TOO_LARGE: "\u8D85\u8FC7\u5355\u6587\u4EF6\u4FDD\u5B58\u4E0A\u9650 50 MiB",
|
|
216965
|
+
BUDGET: "\u672C\u8F6E\u4FDD\u5B58\u989D\u5EA6\u5DF2\u7528\u5B8C\uFF0C\u4E0B\u4E00\u8F6E\u91CD\u8BD5",
|
|
216966
|
+
READ_FAILED: "\u539F\u8282\u70B9\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25",
|
|
216967
|
+
STORE_FAILED: "\u670D\u52A1\u7AEF\u6587\u4EF6\u4FDD\u5B58\u5931\u8D25",
|
|
216968
|
+
FILE_CHANGED: "\u8BFB\u53D6\u671F\u95F4\u6587\u4EF6\u53D1\u751F\u53D8\u5316\uFF0C\u8BF7\u91CD\u8BD5"
|
|
216969
|
+
};
|
|
216970
|
+
const previousIssues = await store.readFileIssues?.(chatSessionId) ?? [];
|
|
216971
|
+
const settled = new Set(Object.keys(args.fingerprints));
|
|
216972
|
+
const issues = [
|
|
216973
|
+
...previousIssues.filter((i) => i.phase === "save" && i.path !== "outputs/" && !settled.has(i.path)),
|
|
216974
|
+
...result.skipped.map((s2) => ({ phase: "save", path: s2.path, code: s2.code, message: messages[s2.code] }))
|
|
216975
|
+
];
|
|
216976
|
+
if (args.scanIncomplete) issues.push({ phase: "save", path: "outputs/", code: "SCAN_INCOMPLETE", message: "\u4EA7\u51FA\u76EE\u5F55\u672A\u80FD\u5B8C\u6574\u626B\u63CF\uFF0C\u90E8\u5206\u6587\u4EF6\u53EF\u80FD\u5C1A\u672A\u4FDD\u5B58" });
|
|
216977
|
+
await store.writeFileIssues?.(chatSessionId, "save", issues);
|
|
216800
216978
|
if (result.skipped.length > 0) {
|
|
216801
216979
|
const head = result.skipped.slice(0, 5).map((s2) => `${s2.path}:${s2.code}`).join(", ");
|
|
216802
216980
|
deps.log?.(`[outputs-copy] ${chatSessionId}: \u590D\u5236 ${result.copied.length} \u4E2A\uFF0C\u8DF3\u8FC7 ${result.skipped.length} \u4E2A\uFF08${head}${result.skipped.length > 5 ? " \u2026" : ""}\uFF09`);
|
|
@@ -216804,11 +216982,14 @@ function createOutputCopyScheduler(deps) {
|
|
|
216804
216982
|
return result;
|
|
216805
216983
|
} catch (err) {
|
|
216806
216984
|
deps.log?.(`[outputs-copy] ${chatSessionId}: ${err instanceof Error ? err.message : String(err)}`);
|
|
216985
|
+
await store.writeFileIssues?.(chatSessionId, "save", [{ phase: "save", path: "outputs/", code: "STORE_FAILED", message: "\u4EA7\u51FA\u4FDD\u5B58\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5" }]).catch(() => void 0);
|
|
216807
216986
|
return null;
|
|
216808
216987
|
} finally {
|
|
216809
|
-
inFlight.delete(key);
|
|
216988
|
+
if (inFlight.get(key) === pending) inFlight.delete(key);
|
|
216810
216989
|
}
|
|
216811
216990
|
})();
|
|
216991
|
+
inFlight.set(key, pending);
|
|
216992
|
+
return pending;
|
|
216812
216993
|
}
|
|
216813
216994
|
};
|
|
216814
216995
|
}
|
|
@@ -216818,9 +216999,9 @@ var init_outputs_copy = __esm({
|
|
|
216818
216999
|
"use strict";
|
|
216819
217000
|
init_src();
|
|
216820
217001
|
OUTPUT_COPY_LIMITS = {
|
|
216821
|
-
maxFileBytes:
|
|
217002
|
+
maxFileBytes: 50 * 1024 * 1024,
|
|
216822
217003
|
maxFiles: 50,
|
|
216823
|
-
maxTotalBytes:
|
|
217004
|
+
maxTotalBytes: 100 * 1024 * 1024
|
|
216824
217005
|
};
|
|
216825
217006
|
}
|
|
216826
217007
|
});
|
|
@@ -217030,11 +217211,11 @@ function typeDefError(def, mode) {
|
|
|
217030
217211
|
}
|
|
217031
217212
|
return null;
|
|
217032
217213
|
}
|
|
217033
|
-
var
|
|
217214
|
+
var import_node_crypto45, RESERVED_FIELD_NAMES, ARTIFACT_TYPE_ACCENTS, TYPE_DEF_SCHEMA, TypesAdminService;
|
|
217034
217215
|
var init_types_admin = __esm({
|
|
217035
217216
|
"../server/src/types-admin.ts"() {
|
|
217036
217217
|
"use strict";
|
|
217037
|
-
|
|
217218
|
+
import_node_crypto45 = require("node:crypto");
|
|
217038
217219
|
init_zod();
|
|
217039
217220
|
init_src5();
|
|
217040
217221
|
init_config_audit();
|
|
@@ -217161,7 +217342,7 @@ var init_types_admin = __esm({
|
|
|
217161
217342
|
async trace(change, target, by, detail) {
|
|
217162
217343
|
try {
|
|
217163
217344
|
await this.audit?.({
|
|
217164
|
-
id: `reg_${(0,
|
|
217345
|
+
id: `reg_${(0, import_node_crypto45.randomUUID)()}`,
|
|
217165
217346
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
217166
217347
|
kind: "registry_change",
|
|
217167
217348
|
target,
|
|
@@ -217309,11 +217490,11 @@ function roleDefError(def, mode) {
|
|
|
217309
217490
|
}
|
|
217310
217491
|
return null;
|
|
217311
217492
|
}
|
|
217312
|
-
var
|
|
217493
|
+
var import_node_crypto46, ACCENTS, ROLE_DEF_SCHEMA, RolesAdminService;
|
|
217313
217494
|
var init_roles_admin = __esm({
|
|
217314
217495
|
"../server/src/roles-admin.ts"() {
|
|
217315
217496
|
"use strict";
|
|
217316
|
-
|
|
217497
|
+
import_node_crypto46 = require("node:crypto");
|
|
217317
217498
|
init_zod();
|
|
217318
217499
|
init_src5();
|
|
217319
217500
|
init_config_audit();
|
|
@@ -217338,7 +217519,7 @@ var init_roles_admin = __esm({
|
|
|
217338
217519
|
async trace(change, target, by, detail) {
|
|
217339
217520
|
try {
|
|
217340
217521
|
await this.deps.audit?.({
|
|
217341
|
-
id: `reg_${(0,
|
|
217522
|
+
id: `reg_${(0, import_node_crypto46.randomUUID)()}`,
|
|
217342
217523
|
actor: by ?? SYSTEM_CONFIG_ACTOR,
|
|
217343
217524
|
kind: "registry_change",
|
|
217344
217525
|
target,
|
|
@@ -218667,6 +218848,373 @@ var init_recovery_plan = __esm({
|
|
|
218667
218848
|
}
|
|
218668
218849
|
});
|
|
218669
218850
|
|
|
218851
|
+
// ../server/src/domains/chat-sessions/files-view.ts
|
|
218852
|
+
function reasonFromWorkdirCode(code2) {
|
|
218853
|
+
switch (code2) {
|
|
218854
|
+
case "NODE_OFFLINE":
|
|
218855
|
+
return "NODE_OFFLINE";
|
|
218856
|
+
case "TIMEOUT":
|
|
218857
|
+
return "TIMEOUT";
|
|
218858
|
+
default:
|
|
218859
|
+
return "ERROR";
|
|
218860
|
+
}
|
|
218861
|
+
}
|
|
218862
|
+
function joinRel2(dir, name) {
|
|
218863
|
+
return dir ? `${dir}/${name}` : name;
|
|
218864
|
+
}
|
|
218865
|
+
function workdirFileItem(rel, name, size, mtime) {
|
|
218866
|
+
return {
|
|
218867
|
+
id: `workdir:${rel}`,
|
|
218868
|
+
name,
|
|
218869
|
+
kind: "file",
|
|
218870
|
+
// 节点侧列目录只报 name/type/size/mtime,没有 MIME——诚实留 null,
|
|
218871
|
+
// 不拿后缀猜(红线:取不到就是取不到,别拿别的字段顶)。
|
|
218872
|
+
content_type: null,
|
|
218873
|
+
size,
|
|
218874
|
+
updated_at: mtime,
|
|
218875
|
+
source: "workdir",
|
|
218876
|
+
blob_ref: null,
|
|
218877
|
+
path: rel,
|
|
218878
|
+
message_id: null,
|
|
218879
|
+
// 工作区文件本期不开写回(brief §4①:要动 node↔server 协议帧,超预算)。
|
|
218880
|
+
// 这里是**按能力不渲染**的判据,不是置灰假钮。
|
|
218881
|
+
editable: false
|
|
218882
|
+
};
|
|
218883
|
+
}
|
|
218884
|
+
async function collectWorkdirFiles(bridge, loc, now = Date.now) {
|
|
218885
|
+
const items = [];
|
|
218886
|
+
if (typeof bridge.walk === "function") {
|
|
218887
|
+
const walked = await bridge.walk(
|
|
218888
|
+
loc.nodeId,
|
|
218889
|
+
{ workdirKey: loc.workdirKey, runtimeKind: loc.runtimeKind, rtId: loc.rtId, path: "" },
|
|
218890
|
+
WORKDIR_TREE_MAX_ENTRIES
|
|
218891
|
+
);
|
|
218892
|
+
if (walked.ok) {
|
|
218893
|
+
let truncated2 = walked.truncated === true;
|
|
218894
|
+
for (const entry of walked.entries) {
|
|
218895
|
+
if (entry.type !== "file") continue;
|
|
218896
|
+
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
218897
|
+
truncated2 = true;
|
|
218898
|
+
break;
|
|
218899
|
+
}
|
|
218900
|
+
const slash = entry.path.lastIndexOf("/");
|
|
218901
|
+
items.push(workdirFileItem(entry.path, entry.path.slice(slash + 1), entry.size, entry.mtime));
|
|
218902
|
+
}
|
|
218903
|
+
return { ok: true, items, truncated: truncated2 };
|
|
218904
|
+
}
|
|
218905
|
+
if (walked.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
218906
|
+
if (walked.code !== "UNSUPPORTED") return { ok: false, reason: reasonFromWorkdirCode(walked.code) };
|
|
218907
|
+
}
|
|
218908
|
+
const deadline = now() + WORKDIR_WALK_BUDGET_MS;
|
|
218909
|
+
let listCalls = 0;
|
|
218910
|
+
let truncated = false;
|
|
218911
|
+
const listDir = (path41) => {
|
|
218912
|
+
listCalls += 1;
|
|
218913
|
+
return bridge.list(loc.nodeId, {
|
|
218914
|
+
workdirKey: loc.workdirKey,
|
|
218915
|
+
runtimeKind: loc.runtimeKind,
|
|
218916
|
+
rtId: loc.rtId,
|
|
218917
|
+
path: path41
|
|
218918
|
+
});
|
|
218919
|
+
};
|
|
218920
|
+
const root = await listDir("");
|
|
218921
|
+
if (!root.ok) {
|
|
218922
|
+
if (root.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
218923
|
+
return { ok: false, reason: reasonFromWorkdirCode(root.code) };
|
|
218924
|
+
}
|
|
218925
|
+
let level = [{ path: "", outcome: root }];
|
|
218926
|
+
for (let depth = 0; depth <= WORKDIR_WALK_MAX_DEPTH; depth += 1) {
|
|
218927
|
+
const nextDirs = [];
|
|
218928
|
+
for (const { path: dir, outcome } of level) {
|
|
218929
|
+
if (!outcome.ok) {
|
|
218930
|
+
truncated = true;
|
|
218931
|
+
continue;
|
|
218932
|
+
}
|
|
218933
|
+
if (outcome.truncated) truncated = true;
|
|
218934
|
+
for (const entry of outcome.entries) {
|
|
218935
|
+
if (entry.type === "dir") {
|
|
218936
|
+
nextDirs.push(joinRel2(dir, entry.name));
|
|
218937
|
+
continue;
|
|
218938
|
+
}
|
|
218939
|
+
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
218940
|
+
truncated = true;
|
|
218941
|
+
continue;
|
|
218942
|
+
}
|
|
218943
|
+
items.push(workdirFileItem(joinRel2(dir, entry.name), entry.name, entry.size, entry.mtime));
|
|
218944
|
+
}
|
|
218945
|
+
}
|
|
218946
|
+
if (depth === WORKDIR_WALK_MAX_DEPTH || nextDirs.length === 0) {
|
|
218947
|
+
if (nextDirs.length > 0) truncated = true;
|
|
218948
|
+
break;
|
|
218949
|
+
}
|
|
218950
|
+
const budget = WORKDIR_WALK_MAX_LIST_CALLS - listCalls;
|
|
218951
|
+
if (budget <= 0 || now() >= deadline) {
|
|
218952
|
+
truncated = true;
|
|
218953
|
+
break;
|
|
218954
|
+
}
|
|
218955
|
+
const take = nextDirs.slice(0, budget);
|
|
218956
|
+
if (take.length < nextDirs.length) truncated = true;
|
|
218957
|
+
const outcomes = await Promise.all(take.map((p2) => listDir(p2)));
|
|
218958
|
+
level = take.map((p2, i) => ({ path: p2, outcome: outcomes[i] }));
|
|
218959
|
+
}
|
|
218960
|
+
return { ok: true, items, truncated };
|
|
218961
|
+
}
|
|
218962
|
+
async function collectMessageFiles(messages, blobs) {
|
|
218963
|
+
const rows = [];
|
|
218964
|
+
for (const message of messages) {
|
|
218965
|
+
if (!Array.isArray(message.attachments)) continue;
|
|
218966
|
+
message.attachments.forEach((attachment, index2) => {
|
|
218967
|
+
if (!attachment || typeof attachment.name !== "string" || !attachment.name) return;
|
|
218968
|
+
const blobRef = typeof attachment.blobRef === "string" && attachment.blobRef ? attachment.blobRef : null;
|
|
218969
|
+
rows.push({
|
|
218970
|
+
item: {
|
|
218971
|
+
id: `msg:${message.id}:${index2}`,
|
|
218972
|
+
name: attachment.name,
|
|
218973
|
+
kind: "file",
|
|
218974
|
+
updated_at: attachment.updatedAt ?? message.createdAt,
|
|
218975
|
+
source: "message",
|
|
218976
|
+
blob_ref: blobRef,
|
|
218977
|
+
path: null,
|
|
218978
|
+
message_id: message.id,
|
|
218979
|
+
// 没有 blobRef 的是**历史纯文本附件**(契约注释:legacy text attachments may only
|
|
218980
|
+
// contain `name`)——没有可写回的载体,一律不给编辑入口。
|
|
218981
|
+
editable: blobRef !== null && isEditableFileName(attachment.name)
|
|
218982
|
+
},
|
|
218983
|
+
blobRef,
|
|
218984
|
+
declaredType: typeof attachment.contentType === "string" && attachment.contentType ? attachment.contentType : null
|
|
218985
|
+
});
|
|
218986
|
+
});
|
|
218987
|
+
}
|
|
218988
|
+
const metaCache = /* @__PURE__ */ new Map();
|
|
218989
|
+
const metaOf = (ref2) => {
|
|
218990
|
+
if (!blobs) return Promise.resolve(null);
|
|
218991
|
+
let hit = metaCache.get(ref2);
|
|
218992
|
+
if (!hit) {
|
|
218993
|
+
hit = blobs.meta(ref2).catch(() => null);
|
|
218994
|
+
metaCache.set(ref2, hit);
|
|
218995
|
+
}
|
|
218996
|
+
return hit;
|
|
218997
|
+
};
|
|
218998
|
+
return Promise.all(rows.map(async ({ item, blobRef, declaredType }) => {
|
|
218999
|
+
const meta = blobRef ? await metaOf(blobRef) : null;
|
|
219000
|
+
return {
|
|
219001
|
+
...item,
|
|
219002
|
+
content_type: declaredType ?? meta?.contentType ?? null,
|
|
219003
|
+
size: meta?.size ?? null
|
|
219004
|
+
};
|
|
219005
|
+
}));
|
|
219006
|
+
}
|
|
219007
|
+
function mergeChatSessionFiles(messageItems, workdirItems, materializedCopies = /* @__PURE__ */ new Set()) {
|
|
219008
|
+
const out = [];
|
|
219009
|
+
const seenMessageKeys = /* @__PURE__ */ new Set();
|
|
219010
|
+
for (const item of [...messageItems].sort((a, b2) => b2.updated_at.localeCompare(a.updated_at))) {
|
|
219011
|
+
const key = `${item.name}\0${item.blob_ref ?? ""}`;
|
|
219012
|
+
if (seenMessageKeys.has(key)) continue;
|
|
219013
|
+
seenMessageKeys.add(key);
|
|
219014
|
+
out.push(item);
|
|
219015
|
+
}
|
|
219016
|
+
const seenWorkdirPaths = /* @__PURE__ */ new Set();
|
|
219017
|
+
for (const item of workdirItems) {
|
|
219018
|
+
if (item.path && materializedCopies.has(item.path)) continue;
|
|
219019
|
+
if (seenWorkdirPaths.has(item.id)) continue;
|
|
219020
|
+
seenWorkdirPaths.add(item.id);
|
|
219021
|
+
out.push(item);
|
|
219022
|
+
}
|
|
219023
|
+
out.sort((a, b2) => b2.updated_at.localeCompare(a.updated_at) || a.name.localeCompare(b2.name));
|
|
219024
|
+
return out;
|
|
219025
|
+
}
|
|
219026
|
+
async function findMaterializedAttachmentCopies(messageItems, workdirItems, read) {
|
|
219027
|
+
const copies = /* @__PURE__ */ new Set();
|
|
219028
|
+
const attachments = messageItems.filter((item) => item.blob_ref && /^[a-f0-9]{64}$/.test(item.blob_ref));
|
|
219029
|
+
let budget = CHAT_ATTACHMENT_MAX_BYTES;
|
|
219030
|
+
const deadline = Date.now() + WORKDIR_WALK_BUDGET_MS;
|
|
219031
|
+
let reads = 0;
|
|
219032
|
+
for (const file of workdirItems) {
|
|
219033
|
+
const rootFile = file.path === file.name;
|
|
219034
|
+
const inputFile = file.path?.startsWith("inputs/attachments/") && !file.path.slice("inputs/attachments/".length).includes("/");
|
|
219035
|
+
if (!file.path || !rootFile && !inputFile) continue;
|
|
219036
|
+
const candidates = attachments.filter((attachment) => {
|
|
219037
|
+
const safe = safeAttachmentName(attachment.name);
|
|
219038
|
+
const numbered = file.name.endsWith(`-${safe}`) && /^\d+$/.test(file.name.slice(0, -(safe.length + 1)));
|
|
219039
|
+
return (rootFile ? file.name === attachment.name : file.name === safe || numbered) && attachment.size !== null && attachment.size === file.size;
|
|
219040
|
+
});
|
|
219041
|
+
if (Date.now() >= deadline) break;
|
|
219042
|
+
if (!candidates.length || file.size === null || file.size > budget || reads >= 10) continue;
|
|
219043
|
+
reads += 1;
|
|
219044
|
+
budget -= file.size;
|
|
219045
|
+
let timer;
|
|
219046
|
+
try {
|
|
219047
|
+
const result = await Promise.race([
|
|
219048
|
+
read(file.path, file.size),
|
|
219049
|
+
new Promise((resolve10) => {
|
|
219050
|
+
timer = setTimeout(() => resolve10(null), Math.max(0, deadline - Date.now()));
|
|
219051
|
+
})
|
|
219052
|
+
]);
|
|
219053
|
+
if (!result?.ok) continue;
|
|
219054
|
+
const bytes2 = Buffer.from(result.contentBase64, "base64");
|
|
219055
|
+
if (bytes2.length !== file.size) continue;
|
|
219056
|
+
const hash2 = (0, import_node_crypto47.createHash)("sha256").update(bytes2).digest("hex");
|
|
219057
|
+
if (candidates.some((attachment) => attachment.blob_ref === hash2)) copies.add(file.path);
|
|
219058
|
+
} catch {
|
|
219059
|
+
} finally {
|
|
219060
|
+
if (timer) clearTimeout(timer);
|
|
219061
|
+
}
|
|
219062
|
+
}
|
|
219063
|
+
return copies;
|
|
219064
|
+
}
|
|
219065
|
+
var import_node_crypto47, WORKDIR_WALK_MAX_DEPTH, WORKDIR_WALK_MAX_ENTRIES, WORKDIR_WALK_MAX_LIST_CALLS, WORKDIR_WALK_BUDGET_MS, WORKDIR_TREE_MAX_ENTRIES;
|
|
219066
|
+
var init_files_view = __esm({
|
|
219067
|
+
"../server/src/domains/chat-sessions/files-view.ts"() {
|
|
219068
|
+
"use strict";
|
|
219069
|
+
import_node_crypto47 = require("node:crypto");
|
|
219070
|
+
init_chat_attachment_files();
|
|
219071
|
+
init_src();
|
|
219072
|
+
WORKDIR_WALK_MAX_DEPTH = 3;
|
|
219073
|
+
WORKDIR_WALK_MAX_ENTRIES = 200;
|
|
219074
|
+
WORKDIR_WALK_MAX_LIST_CALLS = 20;
|
|
219075
|
+
WORKDIR_WALK_BUDGET_MS = 1e4;
|
|
219076
|
+
WORKDIR_TREE_MAX_ENTRIES = 2e3;
|
|
219077
|
+
}
|
|
219078
|
+
});
|
|
219079
|
+
|
|
219080
|
+
// ../server/src/domains/chat-sessions/persistent-files.ts
|
|
219081
|
+
function outputDisplayName(path41) {
|
|
219082
|
+
return path41.startsWith("outputs/") ? path41.slice("outputs/".length) : path41;
|
|
219083
|
+
}
|
|
219084
|
+
async function collectPersistentSessionFiles(messages, copies, blobs, includeOutputAliases = false) {
|
|
219085
|
+
const attachments = mergeChatSessionFiles(await collectMessageFiles(messages, blobs), []);
|
|
219086
|
+
const outputs = Object.values(copies ?? {}).filter((copy) => Boolean(copy.blobRef)).filter((copy) => includeOutputAliases || !attachments.some((a) => a.name === outputDisplayName(copy.path) && a.blob_ref === copy.blobRef)).map((copy) => ({
|
|
219087
|
+
// 保留历史产出卡的 id;引用和读取来源升级为服务端副本。
|
|
219088
|
+
id: `workdir:${copy.path}`,
|
|
219089
|
+
name: outputDisplayName(copy.path),
|
|
219090
|
+
kind: "file",
|
|
219091
|
+
content_type: copy.contentType,
|
|
219092
|
+
size: copy.size,
|
|
219093
|
+
updated_at: Number.isNaN(Date.parse(copy.mtime)) ? copy.copiedAt : new Date(copy.mtime).toISOString(),
|
|
219094
|
+
source: "output",
|
|
219095
|
+
blob_ref: copy.blobRef,
|
|
219096
|
+
path: copy.path,
|
|
219097
|
+
message_id: null,
|
|
219098
|
+
editable: false
|
|
219099
|
+
}));
|
|
219100
|
+
return [...attachments, ...outputs].sort((a, b2) => b2.updated_at.localeCompare(a.updated_at) || a.id.localeCompare(b2.id));
|
|
219101
|
+
}
|
|
219102
|
+
async function readPersistentSessionFiles(store, sessionId, blobs, includeOutputAliases = false) {
|
|
219103
|
+
const [messages, copies] = await Promise.all([
|
|
219104
|
+
store.listSessionAttachmentMessages ? store.listSessionAttachmentMessages(sessionId) : store.listMessages(sessionId),
|
|
219105
|
+
store.readOutputCopies?.(sessionId) ?? Promise.resolve(null)
|
|
219106
|
+
]);
|
|
219107
|
+
return collectPersistentSessionFiles(messages, copies, blobs, includeOutputAliases);
|
|
219108
|
+
}
|
|
219109
|
+
var init_persistent_files = __esm({
|
|
219110
|
+
"../server/src/domains/chat-sessions/persistent-files.ts"() {
|
|
219111
|
+
"use strict";
|
|
219112
|
+
init_files_view();
|
|
219113
|
+
}
|
|
219114
|
+
});
|
|
219115
|
+
|
|
219116
|
+
// ../server/src/domains/chat-sessions/file-restore.ts
|
|
219117
|
+
async function recordSessionFileRestoreExit(store, sessionId, info) {
|
|
219118
|
+
if (info.fileRestoreError) await store.writeFileIssues?.(sessionId, "restore", [{
|
|
219119
|
+
phase: "restore",
|
|
219120
|
+
path: info.fileRestoreError.path,
|
|
219121
|
+
code: "MATERIALIZE_FAILED",
|
|
219122
|
+
message: info.fileRestoreError.message
|
|
219123
|
+
}]);
|
|
219124
|
+
}
|
|
219125
|
+
function attachmentRestorePath(name, ref2) {
|
|
219126
|
+
const key = (0, import_node_crypto48.createHash)("sha256").update(`${name}\0${ref2}`).digest("hex").slice(0, 12);
|
|
219127
|
+
return `inputs/history/${key}/${safeAttachmentName(name)}`;
|
|
219128
|
+
}
|
|
219129
|
+
async function prepareSessionFileRestore(input) {
|
|
219130
|
+
const issues = [];
|
|
219131
|
+
const restoreFiles = {};
|
|
219132
|
+
let items;
|
|
219133
|
+
try {
|
|
219134
|
+
items = await readPersistentSessionFiles(input.store, input.sessionId, void 0, true);
|
|
219135
|
+
} catch {
|
|
219136
|
+
const issue2 = { phase: "restore", path: "", code: "INDEX_UNAVAILABLE", message: "\u6587\u4EF6\u6E05\u5355\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5" };
|
|
219137
|
+
await input.store.writeFileIssues?.(input.sessionId, "restore", [issue2]);
|
|
219138
|
+
throw new ApiError(503, "CHAT_FILE_RESTORE_FAILED", issue2.message);
|
|
219139
|
+
}
|
|
219140
|
+
const saveIssues = (await input.store.readFileIssues?.(input.sessionId) ?? []).filter((i) => i.phase === "save");
|
|
219141
|
+
const fingerprints = await input.store.readOutputFingerprints?.(input.sessionId) ?? {};
|
|
219142
|
+
const copies = await input.store.readOutputCopies?.(input.sessionId) ?? {};
|
|
219143
|
+
const outputPaths = new Set(Object.keys(fingerprints).filter((p2) => p2.startsWith("outputs/")));
|
|
219144
|
+
for (const message of await input.store.listMessages(input.sessionId)) {
|
|
219145
|
+
if (!Array.isArray(message.parts)) continue;
|
|
219146
|
+
for (const part of message.parts) {
|
|
219147
|
+
if (!part || typeof part !== "object" || Array.isArray(part) || part.type !== "outputs" || !Array.isArray(part.outputs)) continue;
|
|
219148
|
+
for (const file of part.outputs) if (file && typeof file === "object" && !Array.isArray(file) && typeof file.path === "string" && file.path.startsWith("outputs/")) outputPaths.add(file.path);
|
|
219149
|
+
}
|
|
219150
|
+
}
|
|
219151
|
+
for (const path41 of outputPaths) {
|
|
219152
|
+
const copy = copies[path41], fp = fingerprints[path41];
|
|
219153
|
+
if ((!copy || fp && (copy.size !== fp.size || copy.mtime !== fp.mtime)) && !saveIssues.some((i) => i.path === path41)) {
|
|
219154
|
+
saveIssues.push({ phase: "save", path: path41, code: "UNSAVED_OUTPUT", message: "\u5386\u53F2\u4EA7\u51FA\u5C1A\u65E0\u6700\u65B0\u6301\u4E45\u526F\u672C\uFF0C\u8BF7\u5728\u539F\u8282\u70B9\u5B8C\u6210\u4FDD\u5B58\u540E\u518D\u5207\u6362" });
|
|
219155
|
+
}
|
|
219156
|
+
}
|
|
219157
|
+
if (input.fresh) issues.push(...saveIssues.map((i) => ({ ...i, phase: "restore", message: `\u539F\u6587\u4EF6\u5C1A\u672A\u4FDD\u5B58\uFF1A${i.message}` })));
|
|
219158
|
+
const lines = ["# \u4F1A\u8BDD\u6587\u4EF6", "", "\u4EE5\u4E0B\u6587\u4EF6\u6765\u81EA\u672C\u4F1A\u8BDD\u7684\u6301\u4E45\u8BB0\u5F55\u3002\u5386\u53F2\u8F93\u5165\u6309\u7248\u672C\u4FDD\u7559\uFF1Boutputs \u662F\u6700\u8FD1\u4FDD\u5B58\u7684\u4EA7\u51FA\u3002", ""];
|
|
219159
|
+
let total = 0;
|
|
219160
|
+
const seen = /* @__PURE__ */ new Set();
|
|
219161
|
+
const add = async (name, ref2, path41, replace2) => {
|
|
219162
|
+
if (seen.has(path41)) return;
|
|
219163
|
+
seen.add(path41);
|
|
219164
|
+
if (!ref2) {
|
|
219165
|
+
issues.push({ phase: "restore", path: path41, code: "MISSING_REFERENCE", message: `${name} \u6CA1\u6709\u53EF\u6062\u590D\u7684\u539F\u4EF6\uFF0C\u8BF7\u91CD\u65B0\u4E0A\u4F20` });
|
|
219166
|
+
return;
|
|
219167
|
+
}
|
|
219168
|
+
try {
|
|
219169
|
+
if (Object.keys(restoreFiles).length >= RESTORE_MAX_FILES) throw new Error("\u8D85\u8FC7\u5355\u8F6E\u6062\u590D\u6587\u4EF6\u6570\u91CF\u4E0A\u9650");
|
|
219170
|
+
const bytes2 = await input.readBlob(ref2);
|
|
219171
|
+
if (total + bytes2.byteLength > RESTORE_MAX_BYTES) throw new Error("\u8D85\u8FC7\u5355\u8F6E\u6062\u590D\u603B\u91CF 100 MiB");
|
|
219172
|
+
const hash2 = (0, import_node_crypto48.createHash)("sha256").update(bytes2).digest("hex");
|
|
219173
|
+
if (hash2 !== ref2.replace(/^blob:/, "")) throw new Error("\u539F\u4EF6\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
219174
|
+
total += bytes2.byteLength;
|
|
219175
|
+
restoreFiles[path41] = { contentBase64: Buffer.from(bytes2).toString("base64"), sha256: hash2, overwrite: replace2 };
|
|
219176
|
+
lines.push(`- ${JSON.stringify(name)} \u2192 ${JSON.stringify(path41)}`);
|
|
219177
|
+
} catch (error2) {
|
|
219178
|
+
issues.push({ phase: "restore", path: path41, code: "FILE_UNAVAILABLE", message: `${name}\uFF1A${error2 instanceof Error ? error2.message : "\u8BFB\u53D6\u5931\u8D25"}` });
|
|
219179
|
+
}
|
|
219180
|
+
};
|
|
219181
|
+
for (const item of items) {
|
|
219182
|
+
const path41 = item.source === "output" ? item.path : attachmentRestorePath(item.name, item.blob_ref ?? item.id);
|
|
219183
|
+
await add(item.name, item.blob_ref, path41, item.source === "message" || input.fresh);
|
|
219184
|
+
if (item.source === "message") {
|
|
219185
|
+
await add(item.name, item.blob_ref, `inputs/attachments/${safeAttachmentName(item.name)}`, true);
|
|
219186
|
+
}
|
|
219187
|
+
}
|
|
219188
|
+
if (!input.fresh) for (const issue2 of saveIssues) {
|
|
219189
|
+
if (!issue2.path.startsWith("outputs/")) continue;
|
|
219190
|
+
restoreFiles[issue2.path] = { contentBase64: "", sha256: (0, import_node_crypto48.createHash)("sha256").update("").digest("hex"), overwrite: false, requireExisting: true };
|
|
219191
|
+
lines.push(`- ${JSON.stringify(issue2.path)} \u5C1A\u672A\u4FDD\u5B58\uFF0C\u5FC5\u987B\u4FDD\u7559\u672C\u673A\u539F\u6587\u4EF6\uFF1A${issue2.message}`);
|
|
219192
|
+
}
|
|
219193
|
+
for (const attachment of input.attachments ?? []) {
|
|
219194
|
+
if (attachment.blobRef && !attachment.path) {
|
|
219195
|
+
await add(attachment.name, attachment.blobRef, attachmentRestorePath(attachment.name, attachment.blobRef), false);
|
|
219196
|
+
}
|
|
219197
|
+
}
|
|
219198
|
+
if (input.supportsFileRestore === false && Object.keys(restoreFiles).length) {
|
|
219199
|
+
issues.push({ phase: "restore", path: "", code: "NODE_UPGRADE_REQUIRED", message: "\u5F53\u524D\u8282\u70B9\u5C1A\u4E0D\u652F\u6301\u6587\u4EF6\u6062\u590D\uFF0C\u8BF7\u5347\u7EA7\u8282\u70B9\u540E\u91CD\u8BD5" });
|
|
219200
|
+
}
|
|
219201
|
+
await input.store.writeFileIssues?.(input.sessionId, "restore", issues);
|
|
219202
|
+
if (issues.length) throw new ApiError(409, "CHAT_FILE_RESTORE_FAILED", `\u6587\u4EF6\u6062\u590D\u672A\u5B8C\u6210\uFF1A${issues.map((i) => i.message).join("\uFF1B")}`);
|
|
219203
|
+
return { restoreFiles, index: lines.join("\n") };
|
|
219204
|
+
}
|
|
219205
|
+
var import_node_crypto48, RESTORE_MAX_BYTES, RESTORE_MAX_FILES;
|
|
219206
|
+
var init_file_restore = __esm({
|
|
219207
|
+
"../server/src/domains/chat-sessions/file-restore.ts"() {
|
|
219208
|
+
"use strict";
|
|
219209
|
+
import_node_crypto48 = require("node:crypto");
|
|
219210
|
+
init_chat_attachment_files();
|
|
219211
|
+
init_router();
|
|
219212
|
+
init_persistent_files();
|
|
219213
|
+
RESTORE_MAX_BYTES = 100 * 1024 * 1024;
|
|
219214
|
+
RESTORE_MAX_FILES = 500;
|
|
219215
|
+
}
|
|
219216
|
+
});
|
|
219217
|
+
|
|
218670
219218
|
// ../server/src/domains/trace/resilient-appender.ts
|
|
218671
219219
|
var ResilientTraceAppender;
|
|
218672
219220
|
var init_resilient_appender = __esm({
|
|
@@ -219589,7 +220137,7 @@ function wireRecoveredChatTurn(deps) {
|
|
|
219589
220137
|
const segText = itemLedger.projectContent();
|
|
219590
220138
|
const segParts = collectedParts();
|
|
219591
220139
|
const closingId = currentMsgId;
|
|
219592
|
-
const nextId = (0,
|
|
220140
|
+
const nextId = (0, import_node_crypto49.randomUUID)();
|
|
219593
220141
|
currentMsgId = nextId;
|
|
219594
220142
|
itemLedger.beginSegment();
|
|
219595
220143
|
live.setAssistantMessageId(nextId);
|
|
@@ -219603,7 +220151,7 @@ function wireRecoveredChatTurn(deps) {
|
|
|
219603
220151
|
...segParts.length ? { parts: segParts } : {}
|
|
219604
220152
|
}).catch(() => void 0);
|
|
219605
220153
|
await store.appendMessage({
|
|
219606
|
-
id: (0,
|
|
220154
|
+
id: (0, import_node_crypto49.randomUUID)(),
|
|
219607
220155
|
sessionId: plan.chatSessionId,
|
|
219608
220156
|
role: "user",
|
|
219609
220157
|
content: text5,
|
|
@@ -219635,6 +220183,7 @@ function wireRecoveredChatTurn(deps) {
|
|
|
219635
220183
|
const done = (async () => {
|
|
219636
220184
|
const info = await new Promise((resolve10) => handle.onExit(resolve10));
|
|
219637
220185
|
clearInterval(ckptTimer);
|
|
220186
|
+
await recordSessionFileRestoreExit(chatStore, plan.chatSessionId, info);
|
|
219638
220187
|
const failed = exitFailed(info);
|
|
219639
220188
|
if (failed) {
|
|
219640
220189
|
const errText2 = exitErrorText(info);
|
|
@@ -219664,11 +220213,12 @@ function wireRecoveredChatTurn(deps) {
|
|
|
219664
220213
|
log3
|
|
219665
220214
|
);
|
|
219666
220215
|
for (const item of closedItems) liveChat.publishItemStatus(plan.chatSessionId, item);
|
|
220216
|
+
const finalParts = await appendOutputsPart(parts, info.fileRestoreError ? void 0 : deps.outputsPart);
|
|
219667
220217
|
await chatStore.updateMessage(currentMsgId, {
|
|
219668
220218
|
content: itemLedger.projectContent(),
|
|
219669
220219
|
status: failed ? "error" : "done",
|
|
219670
220220
|
completedAt: finishedAt,
|
|
219671
|
-
...
|
|
220221
|
+
...finalParts.length ? { parts: finalParts } : {}
|
|
219672
220222
|
}).catch(() => void 0);
|
|
219673
220223
|
const nextRuntimeSessionId = info.runtimeSessionId ?? plan.runtimeSessionId;
|
|
219674
220224
|
await chatStore.updateSession(plan.chatSessionId, {
|
|
@@ -219742,10 +220292,11 @@ async function sweepDanglingChatTurns(deps) {
|
|
|
219742
220292
|
text: "\u8FD9\u4E00\u8F6E\u5728\u6267\u884C\u4E2D\u88AB\u6253\u65AD\uFF08serve \u91CD\u542F\u6216\u8282\u70B9\u9000\u51FA\uFF09\uFF0C\u672A\u80FD\u5B8C\u6210\u2014\u2014\u4EE5\u4E0A\u4E3A\u4E2D\u65AD\u524D\u5DF2\u751F\u6210\u7684\u5185\u5BB9\u3002"
|
|
219743
220293
|
});
|
|
219744
220294
|
}
|
|
220295
|
+
const finalParts = await appendOutputsPart(parts, deps.outputsPartFor?.(row.sessionId));
|
|
219745
220296
|
await deps.updateMessage(row.id, {
|
|
219746
220297
|
status,
|
|
219747
220298
|
completedAt,
|
|
219748
|
-
...
|
|
220299
|
+
...finalParts.length ? { parts: finalParts } : {}
|
|
219749
220300
|
});
|
|
219750
220301
|
closed.push(row.id);
|
|
219751
220302
|
deps.log?.(`[chat-sweep] \u884C ${row.id}\uFF08\u4F1A\u8BDD ${row.sessionId}\uFF09\u6536\u655B\u4E3A ${status}\uFF08${reason}\uFF09`);
|
|
@@ -219767,6 +220318,7 @@ async function reconcileChatExitFrame(deps) {
|
|
|
219767
220318
|
if (meta?.dispatchId !== deps.dispatchId) continue;
|
|
219768
220319
|
if (deps.ownedRunId?.(row.sessionId) === row.runId) return false;
|
|
219769
220320
|
const turn = await deps.getTurnForRun?.(row.sessionId, run.id);
|
|
220321
|
+
const outputsPart = deps.info.fileRestoreError ? void 0 : deps.outputsPartFor?.(row.sessionId);
|
|
219770
220322
|
if (turn && turn.status !== "reserved" && turn.status !== "running") {
|
|
219771
220323
|
await reconcileSettledChatTurn({
|
|
219772
220324
|
plan: {
|
|
@@ -219785,11 +220337,13 @@ async function reconcileChatExitFrame(deps) {
|
|
|
219785
220337
|
chatStore: deps.chatStore,
|
|
219786
220338
|
trace: deps.trace,
|
|
219787
220339
|
...deps.items ? { items: deps.items } : {},
|
|
220340
|
+
...outputsPart ? { outputsPart } : {},
|
|
219788
220341
|
...deps.log ? { log: deps.log } : {}
|
|
219789
220342
|
});
|
|
219790
220343
|
return true;
|
|
219791
220344
|
}
|
|
219792
220345
|
const { info } = deps;
|
|
220346
|
+
await recordSessionFileRestoreExit(deps.chatStore, row.sessionId, info);
|
|
219793
220347
|
const failed = exitFailed(info);
|
|
219794
220348
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
219795
220349
|
const stash = deps.drainStash(deps.dispatchId);
|
|
@@ -219837,11 +220391,12 @@ async function reconcileChatExitFrame(deps) {
|
|
|
219837
220391
|
failed ? "failed" : "completed",
|
|
219838
220392
|
deps.log ?? (() => void 0)
|
|
219839
220393
|
);
|
|
220394
|
+
const finalParts = await appendOutputsPart(parts, outputsPart);
|
|
219840
220395
|
await deps.chatStore.updateMessage(row.id, {
|
|
219841
220396
|
content: itemLedger.projectContent(),
|
|
219842
220397
|
status: failed ? "error" : "done",
|
|
219843
220398
|
completedAt: finishedAt,
|
|
219844
|
-
...
|
|
220399
|
+
...finalParts.length ? { parts: finalParts } : {}
|
|
219845
220400
|
});
|
|
219846
220401
|
const metaRsid = typeof meta?.runtimeSessionId === "string" ? meta.runtimeSessionId : void 0;
|
|
219847
220402
|
const nextRuntimeSessionId = info.runtimeSessionId ?? metaRsid;
|
|
@@ -219904,7 +220459,7 @@ async function planChatTurnRecoveryAcrossCompanies(deps) {
|
|
|
219904
220459
|
return { groups, settled, scanned, skipped };
|
|
219905
220460
|
}
|
|
219906
220461
|
async function sweepDanglingChatTurnsAcrossCompanies(deps) {
|
|
219907
|
-
const { listCompanies, storesFor, onCompanyError, onSessionClosed, log: log3, ...rest } = deps;
|
|
220462
|
+
const { listCompanies, storesFor, onCompanyError, onSessionClosed, sessionOutputsScan, log: log3, ...rest } = deps;
|
|
219908
220463
|
const closed = [];
|
|
219909
220464
|
for (const companyId of await listCompanies()) {
|
|
219910
220465
|
try {
|
|
@@ -219915,7 +220470,8 @@ async function sweepDanglingChatTurnsAcrossCompanies(deps) {
|
|
|
219915
220470
|
listMessages: (sid) => stores.chatStore.listMessages(sid),
|
|
219916
220471
|
updateMessage: (id, patch) => stores.chatStore.updateMessage(id, patch),
|
|
219917
220472
|
...log3 ? { log: (m2) => log3(companyId ? `${m2}\uFF3B${companyId}\uFF3D` : m2) } : {},
|
|
219918
|
-
...onSessionClosed ? { onSessionClosed: (sid, reason, messageId) => onSessionClosed(sid, reason, messageId, companyId) } : {}
|
|
220473
|
+
...onSessionClosed ? { onSessionClosed: (sid, reason, messageId) => onSessionClosed(sid, reason, messageId, companyId) } : {},
|
|
220474
|
+
...sessionOutputsScan ? { outputsPartFor: (sid) => outputsPartProvider(sessionOutputsScan, sid, companyId) } : {}
|
|
219919
220475
|
});
|
|
219920
220476
|
closed.push(...ids2);
|
|
219921
220477
|
} catch (err) {
|
|
@@ -219925,7 +220481,7 @@ async function sweepDanglingChatTurnsAcrossCompanies(deps) {
|
|
|
219925
220481
|
return closed;
|
|
219926
220482
|
}
|
|
219927
220483
|
async function reconcileChatExitFrameAcrossCompanies(deps) {
|
|
219928
|
-
const { listCompanies, storesFor, onCompanyError, log: log3, ...rest } = deps;
|
|
220484
|
+
const { listCompanies, storesFor, onCompanyError, sessionOutputsScan, log: log3, ...rest } = deps;
|
|
219929
220485
|
for (const companyId of await listCompanies()) {
|
|
219930
220486
|
try {
|
|
219931
220487
|
const stores = await storesFor(companyId);
|
|
@@ -219935,7 +220491,8 @@ async function reconcileChatExitFrameAcrossCompanies(deps) {
|
|
|
219935
220491
|
chatStore: stores.chatStore,
|
|
219936
220492
|
...stores.getTurnForRun ? { getTurnForRun: stores.getTurnForRun } : {},
|
|
219937
220493
|
...stores.items ? { items: stores.items } : {},
|
|
219938
|
-
...log3 ? { log: (m2) => log3(companyId ? `${m2}\uFF3B${companyId}\uFF3D` : m2) } : {}
|
|
220494
|
+
...log3 ? { log: (m2) => log3(companyId ? `${m2}\uFF3B${companyId}\uFF3D` : m2) } : {},
|
|
220495
|
+
...sessionOutputsScan ? { outputsPartFor: (sid) => outputsPartProvider(sessionOutputsScan, sid, companyId) } : {}
|
|
219939
220496
|
});
|
|
219940
220497
|
if (handled3) return true;
|
|
219941
220498
|
} catch (err) {
|
|
@@ -219957,9 +220514,11 @@ async function reconcileSettledChatTurn(deps) {
|
|
|
219957
220514
|
succeeded ? "completed" : "failed",
|
|
219958
220515
|
deps.log ?? (() => void 0)
|
|
219959
220516
|
);
|
|
220517
|
+
const withOutputs = await appendOutputsPart(plan.seedParts, deps.outputsPart);
|
|
219960
220518
|
await deps.chatStore.updateMessage(plan.assistantMsgId, {
|
|
219961
220519
|
status: succeeded ? "done" : "error",
|
|
219962
|
-
completedAt
|
|
220520
|
+
completedAt,
|
|
220521
|
+
...withOutputs !== plan.seedParts ? { parts: withOutputs } : {}
|
|
219963
220522
|
});
|
|
219964
220523
|
const run = await deps.trace.getRun(plan.runId);
|
|
219965
220524
|
if (run?.status === "running") {
|
|
@@ -219977,6 +220536,7 @@ async function recoverChatTurnsAcrossCompanies(deps) {
|
|
|
219977
220536
|
const { plan, turn, companyId, stores } = hit;
|
|
219978
220537
|
log3(`[chat-claim] company=${companyId ?? "<default>"} session=${plan.chatSessionId} run=${plan.runId} dispatch=${plan.dispatchId} \u7ED3\u8BBA=settled\uFF08\u4F9D\u636E\uFF1A\u540C\u516C\u53F8\u8F6E\u6B21 ${turn.id} \u5DF2 ${turn.status}\uFF0CcompletedAt=${turn.completedAt ?? "-"}\uFF09`);
|
|
219979
220538
|
deps.evict(plan.dispatchId);
|
|
220539
|
+
const outputsPart = outputsPartProvider(deps.sessionOutputsScan, plan.chatSessionId, companyId);
|
|
219980
220540
|
try {
|
|
219981
220541
|
await reconcileSettledChatTurn({
|
|
219982
220542
|
plan,
|
|
@@ -219984,6 +220544,7 @@ async function recoverChatTurnsAcrossCompanies(deps) {
|
|
|
219984
220544
|
chatStore: stores.chatStore,
|
|
219985
220545
|
trace: deps.trace,
|
|
219986
220546
|
...stores.items ? { items: stores.items } : {},
|
|
220547
|
+
...outputsPart ? { outputsPart } : {},
|
|
219987
220548
|
log: log3
|
|
219988
220549
|
});
|
|
219989
220550
|
} catch (err) {
|
|
@@ -220019,6 +220580,7 @@ async function recoverChatTurnsAcrossCompanies(deps) {
|
|
|
220019
220580
|
...companyId ? { companyId } : {}
|
|
220020
220581
|
});
|
|
220021
220582
|
} : void 0;
|
|
220583
|
+
const outputsPart = outputsPartProvider(deps.sessionOutputsScan, plan.chatSessionId, companyId);
|
|
220022
220584
|
const { done } = wireRecoveredChatTurn({
|
|
220023
220585
|
plan,
|
|
220024
220586
|
handle,
|
|
@@ -220029,6 +220591,7 @@ async function recoverChatTurnsAcrossCompanies(deps) {
|
|
|
220029
220591
|
unregister: () => deps.unregister(plan),
|
|
220030
220592
|
...deps.traceHealth ? { traceHealth: deps.traceHealth } : {},
|
|
220031
220593
|
...onTurnSettled ? { onTurnSettled } : {},
|
|
220594
|
+
...outputsPart ? { outputsPart } : {},
|
|
220032
220595
|
...stores.items ? { items: stores.items, itemsTurnId } : {},
|
|
220033
220596
|
log: log3
|
|
220034
220597
|
});
|
|
@@ -220042,15 +220605,17 @@ async function recoverChatTurnsAcrossCompanies(deps) {
|
|
|
220042
220605
|
}
|
|
220043
220606
|
return { ...result, recovered };
|
|
220044
220607
|
}
|
|
220045
|
-
var
|
|
220608
|
+
var import_node_crypto49, asObj3, partsOf, maxPartSeq, exitFailed, exitErrorText, runTerminalPatch;
|
|
220046
220609
|
var init_chat_recovery = __esm({
|
|
220047
220610
|
"../server/src/chat-recovery.ts"() {
|
|
220048
220611
|
"use strict";
|
|
220049
|
-
|
|
220612
|
+
init_file_restore();
|
|
220613
|
+
import_node_crypto49 = require("node:crypto");
|
|
220050
220614
|
init_chat_parts();
|
|
220051
220615
|
init_sink();
|
|
220052
220616
|
init_resilient_appender();
|
|
220053
220617
|
init_chat_item_ledger();
|
|
220618
|
+
init_chat_assistant_turn();
|
|
220054
220619
|
init_src6();
|
|
220055
220620
|
init_session_exit_outcome();
|
|
220056
220621
|
asObj3 = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
@@ -220076,8 +220641,8 @@ var init_chat_recovery = __esm({
|
|
|
220076
220641
|
|
|
220077
220642
|
// ../server/src/auth/crypto.ts
|
|
220078
220643
|
function hashPassword(password) {
|
|
220079
|
-
const salt = (0,
|
|
220080
|
-
const dk = (0,
|
|
220644
|
+
const salt = (0, import_node_crypto50.randomBytes)(16);
|
|
220645
|
+
const dk = (0, import_node_crypto50.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
|
|
220081
220646
|
return `scrypt$${SCRYPT_N}$${salt.toString("base64url")}$${dk.toString("base64url")}`;
|
|
220082
220647
|
}
|
|
220083
220648
|
function verifyPassword(password, stored) {
|
|
@@ -220094,8 +220659,8 @@ function verifyPassword(password, stored) {
|
|
|
220094
220659
|
return false;
|
|
220095
220660
|
}
|
|
220096
220661
|
if (expected.length === 0) return false;
|
|
220097
|
-
const dk = (0,
|
|
220098
|
-
return dk.length === expected.length && (0,
|
|
220662
|
+
const dk = (0, import_node_crypto50.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
|
|
220663
|
+
return dk.length === expected.length && (0, import_node_crypto50.timingSafeEqual)(dk, expected);
|
|
220099
220664
|
}
|
|
220100
220665
|
function b64urlJson(value2) {
|
|
220101
220666
|
return Buffer.from(JSON.stringify(value2)).toString("base64url");
|
|
@@ -220103,17 +220668,17 @@ function b64urlJson(value2) {
|
|
|
220103
220668
|
function signSession(claims, secret) {
|
|
220104
220669
|
const head = b64urlJson({ alg: "HS256", typ: "JWT" });
|
|
220105
220670
|
const body2 = b64urlJson(claims);
|
|
220106
|
-
const sig = (0,
|
|
220671
|
+
const sig = (0, import_node_crypto50.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
220107
220672
|
return `${head}.${body2}.${sig}`;
|
|
220108
220673
|
}
|
|
220109
220674
|
function verifySession(token, secret, nowMs) {
|
|
220110
220675
|
const parts = token.split(".");
|
|
220111
220676
|
if (parts.length !== 3) return null;
|
|
220112
220677
|
const [head, body2, sig] = parts;
|
|
220113
|
-
const expected = (0,
|
|
220678
|
+
const expected = (0, import_node_crypto50.createHmac)("sha256", secret).update(`${head}.${body2}`).digest("base64url");
|
|
220114
220679
|
const got = Buffer.from(sig);
|
|
220115
220680
|
const exp = Buffer.from(expected);
|
|
220116
|
-
if (got.length !== exp.length || !(0,
|
|
220681
|
+
if (got.length !== exp.length || !(0, import_node_crypto50.timingSafeEqual)(got, exp)) return null;
|
|
220117
220682
|
let claims;
|
|
220118
220683
|
try {
|
|
220119
220684
|
claims = JSON.parse(Buffer.from(body2, "base64url").toString("utf8"));
|
|
@@ -220125,21 +220690,21 @@ function verifySession(token, secret, nowMs) {
|
|
|
220125
220690
|
return claims;
|
|
220126
220691
|
}
|
|
220127
220692
|
function generateCode() {
|
|
220128
|
-
return String((0,
|
|
220693
|
+
return String((0, import_node_crypto50.randomInt)(0, 1e6)).padStart(6, "0");
|
|
220129
220694
|
}
|
|
220130
220695
|
function hashCode(code2, secret) {
|
|
220131
|
-
return (0,
|
|
220696
|
+
return (0, import_node_crypto50.createHmac)("sha256", secret).update(`code:${code2}`).digest("base64url");
|
|
220132
220697
|
}
|
|
220133
220698
|
function safeEqualHash(a, b2) {
|
|
220134
220699
|
const ba = Buffer.from(a);
|
|
220135
220700
|
const bb = Buffer.from(b2);
|
|
220136
|
-
return ba.length === bb.length && (0,
|
|
220701
|
+
return ba.length === bb.length && (0, import_node_crypto50.timingSafeEqual)(ba, bb);
|
|
220137
220702
|
}
|
|
220138
|
-
var
|
|
220703
|
+
var import_node_crypto50, SCRYPT_N, SCRYPT_KEYLEN;
|
|
220139
220704
|
var init_crypto2 = __esm({
|
|
220140
220705
|
"../server/src/auth/crypto.ts"() {
|
|
220141
220706
|
"use strict";
|
|
220142
|
-
|
|
220707
|
+
import_node_crypto50 = require("node:crypto");
|
|
220143
220708
|
SCRYPT_N = 16384;
|
|
220144
220709
|
SCRYPT_KEYLEN = 32;
|
|
220145
220710
|
}
|
|
@@ -221289,16 +221854,16 @@ function variableKeyFromEnv(env = process.env) {
|
|
|
221289
221854
|
return buf;
|
|
221290
221855
|
}
|
|
221291
221856
|
if (env.NODE_ENV === "production") throw new Error("OASIS_VAR_KEY is required in production");
|
|
221292
|
-
return (0,
|
|
221857
|
+
return (0, import_node_crypto51.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
|
|
221293
221858
|
}
|
|
221294
221859
|
function dedupe(ids2) {
|
|
221295
221860
|
return [...new Set(ids2.filter((x2) => typeof x2 === "string" && x2.length > 0))];
|
|
221296
221861
|
}
|
|
221297
|
-
var
|
|
221862
|
+
var import_node_crypto51, REDACTED_MARKER, ActorsService, mask, changedKeys;
|
|
221298
221863
|
var init_service5 = __esm({
|
|
221299
221864
|
"../server/src/domains/actors/service.ts"() {
|
|
221300
221865
|
"use strict";
|
|
221301
|
-
|
|
221866
|
+
import_node_crypto51 = require("node:crypto");
|
|
221302
221867
|
init_skill_fetcher();
|
|
221303
221868
|
init_identity();
|
|
221304
221869
|
init_migrate();
|
|
@@ -221862,7 +222427,7 @@ ${input.description}
|
|
|
221862
222427
|
*/
|
|
221863
222428
|
buildSkillFile(skillId, path41, content3, now) {
|
|
221864
222429
|
const bytes2 = new TextEncoder().encode(content3);
|
|
221865
|
-
const blobHash = (0,
|
|
222430
|
+
const blobHash = (0, import_node_crypto51.createHash)("sha256").update(bytes2).digest("hex");
|
|
221866
222431
|
return { skillId, path: path41, content: content3, blobHash, size: bytes2.length, updatedAt: now };
|
|
221867
222432
|
}
|
|
221868
222433
|
/**
|
|
@@ -222514,15 +223079,15 @@ ${input.description}
|
|
|
222514
223079
|
return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
|
|
222515
223080
|
}
|
|
222516
223081
|
encrypt(plain) {
|
|
222517
|
-
const iv = (0,
|
|
222518
|
-
const cipher = (0,
|
|
223082
|
+
const iv = (0, import_node_crypto51.randomBytes)(12);
|
|
223083
|
+
const cipher = (0, import_node_crypto51.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
222519
223084
|
const enc4 = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
|
|
222520
223085
|
return [iv.toString("base64"), cipher.getAuthTag().toString("base64"), enc4.toString("base64")].join(".");
|
|
222521
223086
|
}
|
|
222522
223087
|
decrypt(packed) {
|
|
222523
223088
|
const [iv, tag, data] = packed.split(".");
|
|
222524
223089
|
if (!iv || !tag || typeof data !== "string") throw new Error("malformed ciphertext");
|
|
222525
|
-
const decipher = (0,
|
|
223090
|
+
const decipher = (0, import_node_crypto51.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
|
|
222526
223091
|
decipher.setAuthTag(Buffer.from(tag, "base64"));
|
|
222527
223092
|
return Buffer.concat([decipher.update(Buffer.from(data, "base64")), decipher.final()]).toString("utf8");
|
|
222528
223093
|
}
|
|
@@ -223140,7 +223705,7 @@ async function listSkillMetadataForActor(args) {
|
|
|
223140
223705
|
usedDirs.add(dir);
|
|
223141
223706
|
const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
223142
223707
|
let latest = "1970-01-01T00:00:00.000Z";
|
|
223143
|
-
const hasher = (0,
|
|
223708
|
+
const hasher = (0, import_node_crypto52.createHash)("sha256");
|
|
223144
223709
|
for (const m2 of sorted) {
|
|
223145
223710
|
if (m2.updatedAt > latest) latest = m2.updatedAt;
|
|
223146
223711
|
hasher.update(m2.path);
|
|
@@ -223165,11 +223730,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
223165
223730
|
const dir = sanitizeSkillDir(c.name, c.slug);
|
|
223166
223731
|
if (usedDirs.has(dir)) continue;
|
|
223167
223732
|
usedDirs.add(dir);
|
|
223168
|
-
const hasher = (0,
|
|
223733
|
+
const hasher = (0, import_node_crypto52.createHash)("sha256");
|
|
223169
223734
|
for (const p2 of paths) {
|
|
223170
223735
|
hasher.update(p2);
|
|
223171
223736
|
hasher.update("\0");
|
|
223172
|
-
hasher.update((0,
|
|
223737
|
+
hasher.update((0, import_node_crypto52.createHash)("sha256").update(c.files[p2]).digest("hex"));
|
|
223173
223738
|
hasher.update("\0");
|
|
223174
223739
|
}
|
|
223175
223740
|
out.push({
|
|
@@ -223190,11 +223755,11 @@ async function listSkillMetadataForActor(args) {
|
|
|
223190
223755
|
const dir = sanitizeSkillDir(b2.name, b2.id);
|
|
223191
223756
|
if (usedDirs.has(dir)) continue;
|
|
223192
223757
|
usedDirs.add(dir);
|
|
223193
|
-
const hasher = (0,
|
|
223758
|
+
const hasher = (0, import_node_crypto52.createHash)("sha256");
|
|
223194
223759
|
for (const p2 of paths) {
|
|
223195
223760
|
hasher.update(p2);
|
|
223196
223761
|
hasher.update("\0");
|
|
223197
|
-
hasher.update((0,
|
|
223762
|
+
hasher.update((0, import_node_crypto52.createHash)("sha256").update(b2.files[p2]).digest("hex"));
|
|
223198
223763
|
hasher.update("\0");
|
|
223199
223764
|
}
|
|
223200
223765
|
out.push({
|
|
@@ -223214,7 +223779,7 @@ function builtinSkillToFiles(b2) {
|
|
|
223214
223779
|
skillId: `builtin:${b2.id}`,
|
|
223215
223780
|
path: path41,
|
|
223216
223781
|
content: content3,
|
|
223217
|
-
blobHash: (0,
|
|
223782
|
+
blobHash: (0, import_node_crypto52.createHash)("sha256").update(content3).digest("hex"),
|
|
223218
223783
|
size: Buffer.byteLength(content3, "utf8"),
|
|
223219
223784
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
223220
223785
|
}));
|
|
@@ -223238,7 +223803,7 @@ function sanitizeSkillDir(name, fallbackId) {
|
|
|
223238
223803
|
if (byName) return byName;
|
|
223239
223804
|
const byId = fallbackId ? fold2(fallbackId) : "";
|
|
223240
223805
|
if (byId) return byId;
|
|
223241
|
-
return `skill-${(0,
|
|
223806
|
+
return `skill-${(0, import_node_crypto52.createHash)("sha256").update(name).digest("hex").slice(0, 8)}`;
|
|
223242
223807
|
}
|
|
223243
223808
|
async function materializeSkillFiles(args) {
|
|
223244
223809
|
const skills = await args.service.listInstalledSkillsForActor(args.actorId);
|
|
@@ -223271,7 +223836,7 @@ function connectorSkillToFiles(c) {
|
|
|
223271
223836
|
skillId: c.id,
|
|
223272
223837
|
path: path41,
|
|
223273
223838
|
content: content3,
|
|
223274
|
-
blobHash: (0,
|
|
223839
|
+
blobHash: (0, import_node_crypto52.createHash)("sha256").update(content3).digest("hex"),
|
|
223275
223840
|
size: Buffer.byteLength(content3, "utf8"),
|
|
223276
223841
|
updatedAt: "1970-01-01T00:00:00.000Z"
|
|
223277
223842
|
}));
|
|
@@ -223288,11 +223853,11 @@ function connectorSkillDisplayRows(connectorSkills, enabledConnectors) {
|
|
|
223288
223853
|
...s2.version !== void 0 ? { version: s2.version } : {}
|
|
223289
223854
|
}));
|
|
223290
223855
|
}
|
|
223291
|
-
var
|
|
223856
|
+
var import_node_crypto52;
|
|
223292
223857
|
var init_skill_materializer = __esm({
|
|
223293
223858
|
"../server/src/domains/actors/skill-materializer.ts"() {
|
|
223294
223859
|
"use strict";
|
|
223295
|
-
|
|
223860
|
+
import_node_crypto52 = require("node:crypto");
|
|
223296
223861
|
}
|
|
223297
223862
|
});
|
|
223298
223863
|
|
|
@@ -224803,7 +225368,7 @@ function createActorsDomain(opts) {
|
|
|
224803
225368
|
...kernel !== void 0 ? { onRolesChanged: (a, r) => kernel.setActorRoles(a, r) } : {},
|
|
224804
225369
|
audit: async (entry) => {
|
|
224805
225370
|
await opts.audit?.({
|
|
224806
|
-
id: `reg_${(0,
|
|
225371
|
+
id: `reg_${(0, import_node_crypto53.randomUUID)()}`,
|
|
224807
225372
|
actor: entry.by,
|
|
224808
225373
|
kind: "registry_change",
|
|
224809
225374
|
target: entry.actorId,
|
|
@@ -224843,11 +225408,11 @@ function createActorsDomain(opts) {
|
|
|
224843
225408
|
register: actorsDomain({ resolveCtx, ...opts.resolveTrace ? { resolveTrace: opts.resolveTrace } : {}, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {}, ...opts.resolveDispatchScope ? { resolveDispatchScope: opts.resolveDispatchScope } : {}, ...opts.projectExists ? { projectExists: opts.projectExists } : {}, ...opts.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 } : {} })
|
|
224844
225409
|
};
|
|
224845
225410
|
}
|
|
224846
|
-
var
|
|
225411
|
+
var import_node_crypto53;
|
|
224847
225412
|
var init_actors = __esm({
|
|
224848
225413
|
"../server/src/domains/actors/index.ts"() {
|
|
224849
225414
|
"use strict";
|
|
224850
|
-
|
|
225415
|
+
import_node_crypto53 = require("node:crypto");
|
|
224851
225416
|
init_service5();
|
|
224852
225417
|
init_routes3();
|
|
224853
225418
|
init_service5();
|
|
@@ -225017,235 +225582,6 @@ var init_assistant_tier_dispatch = __esm({
|
|
|
225017
225582
|
}
|
|
225018
225583
|
});
|
|
225019
225584
|
|
|
225020
|
-
// ../server/src/domains/chat-sessions/files-view.ts
|
|
225021
|
-
function reasonFromWorkdirCode(code2) {
|
|
225022
|
-
switch (code2) {
|
|
225023
|
-
case "NODE_OFFLINE":
|
|
225024
|
-
return "NODE_OFFLINE";
|
|
225025
|
-
case "TIMEOUT":
|
|
225026
|
-
return "TIMEOUT";
|
|
225027
|
-
default:
|
|
225028
|
-
return "ERROR";
|
|
225029
|
-
}
|
|
225030
|
-
}
|
|
225031
|
-
function joinRel2(dir, name) {
|
|
225032
|
-
return dir ? `${dir}/${name}` : name;
|
|
225033
|
-
}
|
|
225034
|
-
function workdirFileItem(rel, name, size, mtime) {
|
|
225035
|
-
return {
|
|
225036
|
-
id: `workdir:${rel}`,
|
|
225037
|
-
name,
|
|
225038
|
-
kind: "file",
|
|
225039
|
-
// 节点侧列目录只报 name/type/size/mtime,没有 MIME——诚实留 null,
|
|
225040
|
-
// 不拿后缀猜(红线:取不到就是取不到,别拿别的字段顶)。
|
|
225041
|
-
content_type: null,
|
|
225042
|
-
size,
|
|
225043
|
-
updated_at: mtime,
|
|
225044
|
-
source: "workdir",
|
|
225045
|
-
blob_ref: null,
|
|
225046
|
-
path: rel,
|
|
225047
|
-
message_id: null,
|
|
225048
|
-
// 工作区文件本期不开写回(brief §4①:要动 node↔server 协议帧,超预算)。
|
|
225049
|
-
// 这里是**按能力不渲染**的判据,不是置灰假钮。
|
|
225050
|
-
editable: false
|
|
225051
|
-
};
|
|
225052
|
-
}
|
|
225053
|
-
async function collectWorkdirFiles(bridge, loc, now = Date.now) {
|
|
225054
|
-
const items = [];
|
|
225055
|
-
if (typeof bridge.walk === "function") {
|
|
225056
|
-
const walked = await bridge.walk(
|
|
225057
|
-
loc.nodeId,
|
|
225058
|
-
{ workdirKey: loc.workdirKey, runtimeKind: loc.runtimeKind, rtId: loc.rtId, path: "" },
|
|
225059
|
-
WORKDIR_TREE_MAX_ENTRIES
|
|
225060
|
-
);
|
|
225061
|
-
if (walked.ok) {
|
|
225062
|
-
let truncated2 = walked.truncated === true;
|
|
225063
|
-
for (const entry of walked.entries) {
|
|
225064
|
-
if (entry.type !== "file") continue;
|
|
225065
|
-
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
225066
|
-
truncated2 = true;
|
|
225067
|
-
break;
|
|
225068
|
-
}
|
|
225069
|
-
const slash = entry.path.lastIndexOf("/");
|
|
225070
|
-
items.push(workdirFileItem(entry.path, entry.path.slice(slash + 1), entry.size, entry.mtime));
|
|
225071
|
-
}
|
|
225072
|
-
return { ok: true, items, truncated: truncated2 };
|
|
225073
|
-
}
|
|
225074
|
-
if (walked.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
225075
|
-
if (walked.code !== "UNSUPPORTED") return { ok: false, reason: reasonFromWorkdirCode(walked.code) };
|
|
225076
|
-
}
|
|
225077
|
-
const deadline = now() + WORKDIR_WALK_BUDGET_MS;
|
|
225078
|
-
let listCalls = 0;
|
|
225079
|
-
let truncated = false;
|
|
225080
|
-
const listDir = (path41) => {
|
|
225081
|
-
listCalls += 1;
|
|
225082
|
-
return bridge.list(loc.nodeId, {
|
|
225083
|
-
workdirKey: loc.workdirKey,
|
|
225084
|
-
runtimeKind: loc.runtimeKind,
|
|
225085
|
-
rtId: loc.rtId,
|
|
225086
|
-
path: path41
|
|
225087
|
-
});
|
|
225088
|
-
};
|
|
225089
|
-
const root = await listDir("");
|
|
225090
|
-
if (!root.ok) {
|
|
225091
|
-
if (root.code === "NOT_FOUND") return { ok: true, items: [], truncated: false };
|
|
225092
|
-
return { ok: false, reason: reasonFromWorkdirCode(root.code) };
|
|
225093
|
-
}
|
|
225094
|
-
let level = [{ path: "", outcome: root }];
|
|
225095
|
-
for (let depth = 0; depth <= WORKDIR_WALK_MAX_DEPTH; depth += 1) {
|
|
225096
|
-
const nextDirs = [];
|
|
225097
|
-
for (const { path: dir, outcome } of level) {
|
|
225098
|
-
if (!outcome.ok) {
|
|
225099
|
-
truncated = true;
|
|
225100
|
-
continue;
|
|
225101
|
-
}
|
|
225102
|
-
if (outcome.truncated) truncated = true;
|
|
225103
|
-
for (const entry of outcome.entries) {
|
|
225104
|
-
if (entry.type === "dir") {
|
|
225105
|
-
nextDirs.push(joinRel2(dir, entry.name));
|
|
225106
|
-
continue;
|
|
225107
|
-
}
|
|
225108
|
-
if (items.length >= WORKDIR_WALK_MAX_ENTRIES) {
|
|
225109
|
-
truncated = true;
|
|
225110
|
-
continue;
|
|
225111
|
-
}
|
|
225112
|
-
items.push(workdirFileItem(joinRel2(dir, entry.name), entry.name, entry.size, entry.mtime));
|
|
225113
|
-
}
|
|
225114
|
-
}
|
|
225115
|
-
if (depth === WORKDIR_WALK_MAX_DEPTH || nextDirs.length === 0) {
|
|
225116
|
-
if (nextDirs.length > 0) truncated = true;
|
|
225117
|
-
break;
|
|
225118
|
-
}
|
|
225119
|
-
const budget = WORKDIR_WALK_MAX_LIST_CALLS - listCalls;
|
|
225120
|
-
if (budget <= 0 || now() >= deadline) {
|
|
225121
|
-
truncated = true;
|
|
225122
|
-
break;
|
|
225123
|
-
}
|
|
225124
|
-
const take = nextDirs.slice(0, budget);
|
|
225125
|
-
if (take.length < nextDirs.length) truncated = true;
|
|
225126
|
-
const outcomes = await Promise.all(take.map((p2) => listDir(p2)));
|
|
225127
|
-
level = take.map((p2, i) => ({ path: p2, outcome: outcomes[i] }));
|
|
225128
|
-
}
|
|
225129
|
-
return { ok: true, items, truncated };
|
|
225130
|
-
}
|
|
225131
|
-
async function collectMessageFiles(messages, blobs) {
|
|
225132
|
-
const rows = [];
|
|
225133
|
-
for (const message of messages) {
|
|
225134
|
-
if (!Array.isArray(message.attachments)) continue;
|
|
225135
|
-
message.attachments.forEach((attachment, index2) => {
|
|
225136
|
-
if (!attachment || typeof attachment.name !== "string" || !attachment.name) return;
|
|
225137
|
-
const blobRef = typeof attachment.blobRef === "string" && attachment.blobRef ? attachment.blobRef : null;
|
|
225138
|
-
rows.push({
|
|
225139
|
-
item: {
|
|
225140
|
-
id: `msg:${message.id}:${index2}`,
|
|
225141
|
-
name: attachment.name,
|
|
225142
|
-
kind: "file",
|
|
225143
|
-
updated_at: attachment.updatedAt ?? message.createdAt,
|
|
225144
|
-
source: "message",
|
|
225145
|
-
blob_ref: blobRef,
|
|
225146
|
-
path: null,
|
|
225147
|
-
message_id: message.id,
|
|
225148
|
-
// 没有 blobRef 的是**历史纯文本附件**(契约注释:legacy text attachments may only
|
|
225149
|
-
// contain `name`)——没有可写回的载体,一律不给编辑入口。
|
|
225150
|
-
editable: blobRef !== null && isEditableFileName(attachment.name)
|
|
225151
|
-
},
|
|
225152
|
-
blobRef,
|
|
225153
|
-
declaredType: typeof attachment.contentType === "string" && attachment.contentType ? attachment.contentType : null
|
|
225154
|
-
});
|
|
225155
|
-
});
|
|
225156
|
-
}
|
|
225157
|
-
const metaCache = /* @__PURE__ */ new Map();
|
|
225158
|
-
const metaOf = (ref2) => {
|
|
225159
|
-
if (!blobs) return Promise.resolve(null);
|
|
225160
|
-
let hit = metaCache.get(ref2);
|
|
225161
|
-
if (!hit) {
|
|
225162
|
-
hit = blobs.meta(ref2).catch(() => null);
|
|
225163
|
-
metaCache.set(ref2, hit);
|
|
225164
|
-
}
|
|
225165
|
-
return hit;
|
|
225166
|
-
};
|
|
225167
|
-
return Promise.all(rows.map(async ({ item, blobRef, declaredType }) => {
|
|
225168
|
-
const meta = blobRef ? await metaOf(blobRef) : null;
|
|
225169
|
-
return {
|
|
225170
|
-
...item,
|
|
225171
|
-
content_type: declaredType ?? meta?.contentType ?? null,
|
|
225172
|
-
size: meta?.size ?? null
|
|
225173
|
-
};
|
|
225174
|
-
}));
|
|
225175
|
-
}
|
|
225176
|
-
function mergeChatSessionFiles(messageItems, workdirItems, materializedCopies = /* @__PURE__ */ new Set()) {
|
|
225177
|
-
const out = [];
|
|
225178
|
-
const seenMessageKeys = /* @__PURE__ */ new Set();
|
|
225179
|
-
for (const item of [...messageItems].sort((a, b2) => b2.updated_at.localeCompare(a.updated_at))) {
|
|
225180
|
-
const key = `${item.name}\0${item.blob_ref ?? ""}`;
|
|
225181
|
-
if (seenMessageKeys.has(key)) continue;
|
|
225182
|
-
seenMessageKeys.add(key);
|
|
225183
|
-
out.push(item);
|
|
225184
|
-
}
|
|
225185
|
-
const seenWorkdirPaths = /* @__PURE__ */ new Set();
|
|
225186
|
-
for (const item of workdirItems) {
|
|
225187
|
-
if (item.path && materializedCopies.has(item.path)) continue;
|
|
225188
|
-
if (seenWorkdirPaths.has(item.id)) continue;
|
|
225189
|
-
seenWorkdirPaths.add(item.id);
|
|
225190
|
-
out.push(item);
|
|
225191
|
-
}
|
|
225192
|
-
out.sort((a, b2) => b2.updated_at.localeCompare(a.updated_at) || a.name.localeCompare(b2.name));
|
|
225193
|
-
return out;
|
|
225194
|
-
}
|
|
225195
|
-
async function findMaterializedAttachmentCopies(messageItems, workdirItems, read) {
|
|
225196
|
-
const copies = /* @__PURE__ */ new Set();
|
|
225197
|
-
const attachments = messageItems.filter((item) => item.blob_ref && /^[a-f0-9]{64}$/.test(item.blob_ref));
|
|
225198
|
-
let budget = CHAT_ATTACHMENT_MAX_BYTES;
|
|
225199
|
-
const deadline = Date.now() + WORKDIR_WALK_BUDGET_MS;
|
|
225200
|
-
let reads = 0;
|
|
225201
|
-
for (const file of workdirItems) {
|
|
225202
|
-
const rootFile = file.path === file.name;
|
|
225203
|
-
const inputFile = file.path?.startsWith("inputs/attachments/") && !file.path.slice("inputs/attachments/".length).includes("/");
|
|
225204
|
-
if (!file.path || !rootFile && !inputFile) continue;
|
|
225205
|
-
const candidates = attachments.filter((attachment) => {
|
|
225206
|
-
const safe = safeAttachmentName(attachment.name);
|
|
225207
|
-
const numbered = file.name.endsWith(`-${safe}`) && /^\d+$/.test(file.name.slice(0, -(safe.length + 1)));
|
|
225208
|
-
return (rootFile ? file.name === attachment.name : file.name === safe || numbered) && attachment.size !== null && attachment.size === file.size;
|
|
225209
|
-
});
|
|
225210
|
-
if (Date.now() >= deadline) break;
|
|
225211
|
-
if (!candidates.length || file.size === null || file.size > budget || reads >= 10) continue;
|
|
225212
|
-
reads += 1;
|
|
225213
|
-
budget -= file.size;
|
|
225214
|
-
let timer;
|
|
225215
|
-
try {
|
|
225216
|
-
const result = await Promise.race([
|
|
225217
|
-
read(file.path, file.size),
|
|
225218
|
-
new Promise((resolve10) => {
|
|
225219
|
-
timer = setTimeout(() => resolve10(null), Math.max(0, deadline - Date.now()));
|
|
225220
|
-
})
|
|
225221
|
-
]);
|
|
225222
|
-
if (!result?.ok) continue;
|
|
225223
|
-
const bytes2 = Buffer.from(result.contentBase64, "base64");
|
|
225224
|
-
if (bytes2.length !== file.size) continue;
|
|
225225
|
-
const hash2 = (0, import_node_crypto50.createHash)("sha256").update(bytes2).digest("hex");
|
|
225226
|
-
if (candidates.some((attachment) => attachment.blob_ref === hash2)) copies.add(file.path);
|
|
225227
|
-
} catch {
|
|
225228
|
-
} finally {
|
|
225229
|
-
if (timer) clearTimeout(timer);
|
|
225230
|
-
}
|
|
225231
|
-
}
|
|
225232
|
-
return copies;
|
|
225233
|
-
}
|
|
225234
|
-
var import_node_crypto50, WORKDIR_WALK_MAX_DEPTH, WORKDIR_WALK_MAX_ENTRIES, WORKDIR_WALK_MAX_LIST_CALLS, WORKDIR_WALK_BUDGET_MS, WORKDIR_TREE_MAX_ENTRIES;
|
|
225235
|
-
var init_files_view = __esm({
|
|
225236
|
-
"../server/src/domains/chat-sessions/files-view.ts"() {
|
|
225237
|
-
"use strict";
|
|
225238
|
-
import_node_crypto50 = require("node:crypto");
|
|
225239
|
-
init_chat_attachment_files();
|
|
225240
|
-
init_src();
|
|
225241
|
-
WORKDIR_WALK_MAX_DEPTH = 3;
|
|
225242
|
-
WORKDIR_WALK_MAX_ENTRIES = 200;
|
|
225243
|
-
WORKDIR_WALK_MAX_LIST_CALLS = 20;
|
|
225244
|
-
WORKDIR_WALK_BUDGET_MS = 1e4;
|
|
225245
|
-
WORKDIR_TREE_MAX_ENTRIES = 2e3;
|
|
225246
|
-
}
|
|
225247
|
-
});
|
|
225248
|
-
|
|
225249
225585
|
// ../server/src/domains/projects/chat-files.ts
|
|
225250
225586
|
function isProjectChatSession(session) {
|
|
225251
225587
|
if (session.visibility === "internal") return false;
|
|
@@ -225257,79 +225593,45 @@ function chatFolderTitle(session) {
|
|
|
225257
225593
|
const title = session.title?.trim();
|
|
225258
225594
|
return title ? title : "\u672A\u547D\u540D\u5BF9\u8BDD";
|
|
225259
225595
|
}
|
|
225260
|
-
function outputDisplayName(path41) {
|
|
225261
|
-
return path41.startsWith("outputs/") ? path41.slice("outputs/".length) : path41;
|
|
225262
|
-
}
|
|
225263
225596
|
async function collectProjectChatFiles(chat, projectId2, meta, options = {}) {
|
|
225264
225597
|
const scope = isUncategorizedProjectId(projectId2) ? null : projectId2;
|
|
225265
|
-
const [attachmentMessages, outputSessions] = await Promise.all([
|
|
225266
|
-
chat.listAttachmentMessages
|
|
225267
|
-
chat.listOutputCopies
|
|
225598
|
+
const [attachmentMessages, outputSessions, taskSessions] = await Promise.all([
|
|
225599
|
+
chat.listAttachmentMessages?.(scope) ?? [],
|
|
225600
|
+
chat.listOutputCopies?.(scope) ?? [],
|
|
225601
|
+
chat.listFileSessionsByWorkspaces?.(options.workOrderIds ?? []) ?? []
|
|
225268
225602
|
]);
|
|
225269
|
-
const
|
|
225603
|
+
const ids2 = [.../* @__PURE__ */ new Set([
|
|
225270
225604
|
...attachmentMessages.map((m2) => m2.sessionId),
|
|
225271
|
-
...outputSessions.map((s2) => s2.sessionId)
|
|
225605
|
+
...outputSessions.map((s2) => s2.sessionId),
|
|
225606
|
+
...taskSessions.map((s2) => s2.id)
|
|
225272
225607
|
])];
|
|
225273
|
-
const sessions = /* @__PURE__ */ new Map();
|
|
225274
|
-
await Promise.all(sessionIds.map(async (id) => {
|
|
225275
|
-
const session = await chat.getSession(id);
|
|
225276
|
-
if (!session) return;
|
|
225277
|
-
if ((session.projectId ?? null) !== scope) return;
|
|
225278
|
-
if (!isProjectChatSession(session)) return;
|
|
225279
|
-
if (options.isDelegationChild && await options.isDelegationChild(id).catch(() => false)) return;
|
|
225280
|
-
sessions.set(id, session);
|
|
225281
|
-
}));
|
|
225282
225608
|
const out = [];
|
|
225283
|
-
const
|
|
225284
|
-
|
|
225285
|
-
|
|
225286
|
-
|
|
225287
|
-
|
|
225288
|
-
|
|
225289
|
-
|
|
225290
|
-
|
|
225291
|
-
|
|
225292
|
-
const
|
|
225293
|
-
|
|
225294
|
-
bySession.set(message.sessionId, list2);
|
|
225295
|
-
}
|
|
225296
|
-
for (const [sessionId, messages] of bySession) {
|
|
225297
|
-
const session = sessions.get(sessionId);
|
|
225298
|
-
const rows = await collectMessageFiles(messages.map((m2) => ({ ...m2, id: m2.messageId })), { meta });
|
|
225299
|
-
for (const row of mergeChatSessionFiles(rows, [])) {
|
|
225300
|
-
if (row.blob_ref === null) continue;
|
|
225301
|
-
out.push({
|
|
225302
|
-
...base(session),
|
|
225303
|
-
fileId: `chat:${sessionId}:${row.id}`,
|
|
225304
|
-
name: row.name,
|
|
225305
|
-
blobId: row.blob_ref,
|
|
225306
|
-
...row.content_type ? { contentType: row.content_type } : {},
|
|
225307
|
-
size: row.size,
|
|
225308
|
-
uploadedBy: session.humanActorId,
|
|
225309
|
-
uploadedAt: row.updated_at,
|
|
225310
|
-
chatSource: "attachment"
|
|
225311
|
-
});
|
|
225312
|
-
}
|
|
225313
|
-
}
|
|
225314
|
-
for (const record8 of outputSessions) {
|
|
225315
|
-
const session = sessions.get(record8.sessionId);
|
|
225316
|
-
if (!session) continue;
|
|
225317
|
-
const seen = new Set(out.filter((file) => file.chatSessionId === session.id).map((file) => `${file.name}\0${file.blobId}`));
|
|
225318
|
-
const copies = record8.copies ?? {};
|
|
225319
|
-
for (const path41 of Object.keys(copies).sort((a, b2) => a.localeCompare(b2))) {
|
|
225320
|
-
const copy = copies[path41];
|
|
225321
|
-
if (!copy?.blobRef) continue;
|
|
225322
|
-
if (seen.has(`${copy.name}\0${copy.blobRef}`)) continue;
|
|
225609
|
+
for (const id of ids2) {
|
|
225610
|
+
const session = await chat.getSession(id);
|
|
225611
|
+
if (!session || session.visibility === "internal" || session.analyzedRunId) continue;
|
|
225612
|
+
if (session.workspace) {
|
|
225613
|
+
if (!options.workOrderIds?.includes(session.workspace)) continue;
|
|
225614
|
+
} else if ((session.projectId ?? null) !== scope || !isProjectChatSession(session)) continue;
|
|
225615
|
+
if (options.isDelegationChild && await options.isDelegationChild(id)) continue;
|
|
225616
|
+
const items = await readPersistentSessionFiles(chat, id, { meta });
|
|
225617
|
+
const fileIssues = await chat.readFileIssues?.(id) ?? [];
|
|
225618
|
+
for (const item of items) {
|
|
225619
|
+
if (!item.blob_ref) continue;
|
|
225323
225620
|
out.push({
|
|
225324
|
-
|
|
225325
|
-
|
|
225326
|
-
|
|
225327
|
-
|
|
225328
|
-
|
|
225329
|
-
|
|
225330
|
-
|
|
225331
|
-
|
|
225332
|
-
|
|
225621
|
+
projectId: projectId2,
|
|
225622
|
+
...fileIssues.length ? { fileIssues } : {},
|
|
225623
|
+
chatSessionId: id,
|
|
225624
|
+
chatTitle: chatFolderTitle(session),
|
|
225625
|
+
chatOwnerId: session.humanActorId,
|
|
225626
|
+
fileId: `chat:${id}:${item.id}`,
|
|
225627
|
+
name: item.name,
|
|
225628
|
+
blobId: item.blob_ref,
|
|
225629
|
+
...item.content_type ? { contentType: item.content_type } : {},
|
|
225630
|
+
size: item.size,
|
|
225631
|
+
uploadedBy: item.source === "output" ? session.aiActorId : session.humanActorId,
|
|
225632
|
+
uploadedAt: item.updated_at,
|
|
225633
|
+
chatSource: item.source === "output" ? "output" : "attachment",
|
|
225634
|
+
...session.workspace ? { taskId: session.workspace } : {}
|
|
225333
225635
|
});
|
|
225334
225636
|
}
|
|
225335
225637
|
}
|
|
@@ -225338,7 +225640,8 @@ async function collectProjectChatFiles(chat, projectId2, meta, options = {}) {
|
|
|
225338
225640
|
var init_chat_files2 = __esm({
|
|
225339
225641
|
"../server/src/domains/projects/chat-files.ts"() {
|
|
225340
225642
|
"use strict";
|
|
225341
|
-
|
|
225643
|
+
init_persistent_files();
|
|
225644
|
+
init_persistent_files();
|
|
225342
225645
|
init_uncategorized_project();
|
|
225343
225646
|
}
|
|
225344
225647
|
});
|
|
@@ -226302,7 +226605,8 @@ function toApiProjectFilesView(view) {
|
|
|
226302
226605
|
// 对话文件夹(`"chat"`):前端据此换带对话气泡的文件夹图标。其余文件夹与文件行为 null。
|
|
226303
226606
|
folder_kind: item.folderKind ?? null,
|
|
226304
226607
|
// 对话文件夹及其子文件所属的对话;前端「所属任务」列的「对话」筛选档靠它。其余行为 null。
|
|
226305
|
-
chat_session_id: item.chatSessionId ?? null
|
|
226608
|
+
chat_session_id: item.chatSessionId ?? null,
|
|
226609
|
+
...item.fileIssues?.length ? { file_issues: item.fileIssues } : {}
|
|
226306
226610
|
}))
|
|
226307
226611
|
};
|
|
226308
226612
|
}
|
|
@@ -228626,11 +228930,11 @@ function fromRow(row) {
|
|
|
228626
228930
|
for (const [k2, v2] of opt) if (v2 !== void 0 && v2 !== null) r[k2] = v2;
|
|
228627
228931
|
return r;
|
|
228628
228932
|
}
|
|
228629
|
-
var
|
|
228933
|
+
var import_node_crypto54, import_node_fs14, DEFAULT_PAGE, MAX_PAGE, pageSize, MemoryNotificationStore, ident3, iso2, str2, PostgresNotificationStore;
|
|
228630
228934
|
var init_notification_store = __esm({
|
|
228631
228935
|
"../server/src/domains/collab/notification-store.ts"() {
|
|
228632
228936
|
"use strict";
|
|
228633
|
-
|
|
228937
|
+
import_node_crypto54 = require("node:crypto");
|
|
228634
228938
|
import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
228635
228939
|
DEFAULT_PAGE = 50;
|
|
228636
228940
|
MAX_PAGE = 200;
|
|
@@ -228663,7 +228967,7 @@ var init_notification_store = __esm({
|
|
|
228663
228967
|
async insert(n) {
|
|
228664
228968
|
const existing = this.findLive(n.recipient, n.sourceKey, n.category);
|
|
228665
228969
|
if (existing) return existing;
|
|
228666
|
-
const row = { ...n, id: `ntf:${(0,
|
|
228970
|
+
const row = { ...n, id: `ntf:${(0, import_node_crypto54.randomUUID)()}`, updatedAt: n.enteredAt };
|
|
228667
228971
|
this.rows.set(row.id, row);
|
|
228668
228972
|
this.save();
|
|
228669
228973
|
return row;
|
|
@@ -228786,7 +229090,7 @@ var init_notification_store = __esm({
|
|
|
228786
229090
|
return new _PostgresNotificationStore(sql, schema);
|
|
228787
229091
|
}
|
|
228788
229092
|
async insert(n) {
|
|
228789
|
-
const id = `ntf:${(0,
|
|
229093
|
+
const id = `ntf:${(0, import_node_crypto54.randomUUID)()}`;
|
|
228790
229094
|
const r = await this.sql.query(
|
|
228791
229095
|
`INSERT INTO ${this.t} (id, recipient, category, source_key, kind, workorder_id, node_id, card_id, actor_id,
|
|
228792
229096
|
title, workspace_title, entered_at, updated_at, status, read_at, item)
|
|
@@ -229737,13 +230041,13 @@ function nameKey(name) {
|
|
|
229737
230041
|
function cleanName(name) {
|
|
229738
230042
|
return name.trim().replace(/\s+/g, " ");
|
|
229739
230043
|
}
|
|
229740
|
-
var import_node_fs15, import_node_path20,
|
|
230044
|
+
var import_node_fs15, import_node_path20, import_node_crypto55, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
229741
230045
|
var init_tags = __esm({
|
|
229742
230046
|
"../server/src/domains/collab/tags.ts"() {
|
|
229743
230047
|
"use strict";
|
|
229744
230048
|
import_node_fs15 = __toESM(require("node:fs"), 1);
|
|
229745
230049
|
import_node_path20 = __toESM(require("node:path"), 1);
|
|
229746
|
-
|
|
230050
|
+
import_node_crypto55 = __toESM(require("node:crypto"), 1);
|
|
229747
230051
|
SEP = "::";
|
|
229748
230052
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
229749
230053
|
prefixOf = (companyId) => `${companyId}${SEP}`;
|
|
@@ -229761,7 +230065,7 @@ var init_tags = __esm({
|
|
|
229761
230065
|
if (!name) return null;
|
|
229762
230066
|
if (this.entries(companyId).some((t) => nameKey(t.name) === nameKey(name))) return null;
|
|
229763
230067
|
const tag = {
|
|
229764
|
-
id: `tag-${
|
|
230068
|
+
id: `tag-${import_node_crypto55.default.randomBytes(6).toString("hex")}`,
|
|
229765
230069
|
name,
|
|
229766
230070
|
...input.color?.trim() ? { color: input.color.trim() } : {},
|
|
229767
230071
|
...input.description?.trim() ? { description: input.description.trim() } : {}
|
|
@@ -231007,11 +231311,11 @@ async function isEmployedElsewhere(store, companyId, accountId) {
|
|
|
231007
231311
|
const memberships = await store.listMembershipsForAccount(accountId);
|
|
231008
231312
|
return memberships.some((m2) => m2.companyId !== companyId);
|
|
231009
231313
|
}
|
|
231010
|
-
var
|
|
231314
|
+
var import_node_crypto56, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, INVITE_LINK_TTL_MS, INVITE_LINK_TOKEN_BYTES, INVITE_LINK_ROLE, SLUG_RE, CompanyError, CompaniesService;
|
|
231011
231315
|
var init_service6 = __esm({
|
|
231012
231316
|
"../server/src/domains/companies/service.ts"() {
|
|
231013
231317
|
"use strict";
|
|
231014
|
-
|
|
231318
|
+
import_node_crypto56 = require("node:crypto");
|
|
231015
231319
|
init_console_url();
|
|
231016
231320
|
ROLES = ["owner", "admin", "member"];
|
|
231017
231321
|
INVITABLE_ROLES = ["admin", "member"];
|
|
@@ -231103,7 +231407,7 @@ var init_service6 = __esm({
|
|
|
231103
231407
|
const existing = await this.store.getAccountByEmail(normalized4);
|
|
231104
231408
|
if (existing) return existing;
|
|
231105
231409
|
const account = {
|
|
231106
|
-
id: `actor:human:${(0,
|
|
231410
|
+
id: `actor:human:${(0, import_node_crypto56.randomUUID)()}`,
|
|
231107
231411
|
email: normalized4,
|
|
231108
231412
|
name: name ?? normalized4,
|
|
231109
231413
|
status: "active"
|
|
@@ -231312,7 +231616,7 @@ var init_service6 = __esm({
|
|
|
231312
231616
|
}
|
|
231313
231617
|
const nowMs = Date.parse(this.now());
|
|
231314
231618
|
const invitation = {
|
|
231315
|
-
id: `invitation:${(0,
|
|
231619
|
+
id: `invitation:${(0, import_node_crypto56.randomUUID)()}`,
|
|
231316
231620
|
companyId,
|
|
231317
231621
|
email: mail,
|
|
231318
231622
|
role,
|
|
@@ -231443,7 +231747,7 @@ var init_service6 = __esm({
|
|
|
231443
231747
|
const nowMs = Date.parse(this.now());
|
|
231444
231748
|
const link = {
|
|
231445
231749
|
companyId,
|
|
231446
|
-
token: (0,
|
|
231750
|
+
token: (0, import_node_crypto56.randomBytes)(INVITE_LINK_TOKEN_BYTES).toString("base64url"),
|
|
231447
231751
|
role: INVITE_LINK_ROLE,
|
|
231448
231752
|
createdAt: new Date(nowMs).toISOString(),
|
|
231449
231753
|
expiresAt: new Date(nowMs + INVITE_LINK_TTL_MS).toISOString(),
|
|
@@ -231500,7 +231804,7 @@ var init_service6 = __esm({
|
|
|
231500
231804
|
const reusable = existing.find((inv) => !this.isExpired(inv));
|
|
231501
231805
|
if (reusable) return reusable;
|
|
231502
231806
|
const invitation = {
|
|
231503
|
-
id: `invitation:${(0,
|
|
231807
|
+
id: `invitation:${(0, import_node_crypto56.randomUUID)()}`,
|
|
231504
231808
|
companyId: link.companyId,
|
|
231505
231809
|
email: mail,
|
|
231506
231810
|
role: link.role,
|
|
@@ -231738,11 +232042,11 @@ var init_service6 = __esm({
|
|
|
231738
232042
|
});
|
|
231739
232043
|
|
|
231740
232044
|
// ../server/src/domains/companies/offboarding.ts
|
|
231741
|
-
var
|
|
232045
|
+
var import_node_crypto57, MemberOffboardingService;
|
|
231742
232046
|
var init_offboarding = __esm({
|
|
231743
232047
|
"../server/src/domains/companies/offboarding.ts"() {
|
|
231744
232048
|
"use strict";
|
|
231745
|
-
|
|
232049
|
+
import_node_crypto57 = require("node:crypto");
|
|
231746
232050
|
init_service6();
|
|
231747
232051
|
MemberOffboardingService = class {
|
|
231748
232052
|
store;
|
|
@@ -231814,7 +232118,7 @@ var init_offboarding = __esm({
|
|
|
231814
232118
|
const { ownedAgents, inFlight } = await this.snapshot(companyId, accountId);
|
|
231815
232119
|
const at = this.now();
|
|
231816
232120
|
const started = await this.store.startMemberOffboarding({
|
|
231817
|
-
operationId: `off:${(0,
|
|
232121
|
+
operationId: `off:${(0, import_node_crypto57.randomUUID)()}`,
|
|
231818
232122
|
companyId,
|
|
231819
232123
|
accountId,
|
|
231820
232124
|
initiatedBy,
|
|
@@ -232324,18 +232628,18 @@ var init_routes6 = __esm({
|
|
|
232324
232628
|
|
|
232325
232629
|
// ../server/src/domains/companies/agent-credentials.ts
|
|
232326
232630
|
function hashAgentToken(token, secret) {
|
|
232327
|
-
return HASH_PREFIX + (0,
|
|
232631
|
+
return HASH_PREFIX + (0, import_node_crypto58.createHmac)("sha256", secret).update(`agent-token:${token}`).digest("base64url");
|
|
232328
232632
|
}
|
|
232329
232633
|
function safeEqual(a, b2) {
|
|
232330
232634
|
const ba = Buffer.from(a);
|
|
232331
232635
|
const bb = Buffer.from(b2);
|
|
232332
|
-
return ba.length === bb.length && (0,
|
|
232636
|
+
return ba.length === bb.length && (0, import_node_crypto58.timingSafeEqual)(ba, bb);
|
|
232333
232637
|
}
|
|
232334
|
-
var
|
|
232638
|
+
var import_node_crypto58, HASH_PREFIX, TOKEN_PREFIX, AgentCredentialService;
|
|
232335
232639
|
var init_agent_credentials = __esm({
|
|
232336
232640
|
"../server/src/domains/companies/agent-credentials.ts"() {
|
|
232337
232641
|
"use strict";
|
|
232338
|
-
|
|
232642
|
+
import_node_crypto58 = require("node:crypto");
|
|
232339
232643
|
init_service6();
|
|
232340
232644
|
HASH_PREFIX = "ac1$";
|
|
232341
232645
|
TOKEN_PREFIX = "oak_";
|
|
@@ -232360,7 +232664,7 @@ var init_agent_credentials = __esm({
|
|
|
232360
232664
|
if (employee.status !== "active") {
|
|
232361
232665
|
throw new CompanyError(409, "AGENT_LEFT", `\u6570\u5B57\u5458\u5DE5\u5DF2\u79BB\u5F00\uFF0C\u4E0D\u80FD\u7B7E\u53D1\u51ED\u8BC1\uFF1A${agentId}`);
|
|
232362
232666
|
}
|
|
232363
|
-
const token = `${TOKEN_PREFIX}${(0,
|
|
232667
|
+
const token = `${TOKEN_PREFIX}${(0, import_node_crypto58.randomBytes)(32).toString("base64url")}`;
|
|
232364
232668
|
const credential = {
|
|
232365
232669
|
tokenHash: hashAgentToken(token, this.secret),
|
|
232366
232670
|
companyId,
|
|
@@ -232780,7 +233084,7 @@ function gatewayInstanceSlug(gatewayUrl) {
|
|
|
232780
233084
|
}
|
|
232781
233085
|
function connectInstanceName(gatewayUrl, token, companyId) {
|
|
232782
233086
|
const scope = companyId?.trim();
|
|
232783
|
-
const suffix = scope ? `c${(0,
|
|
233087
|
+
const suffix = scope ? `c${(0, import_node_crypto59.createHash)("sha256").update(`${gatewayUrl}\0${scope}`).digest("hex").slice(0, 10)}` : token.replace(/[^a-z0-9]/gi, "").slice(-8).toLowerCase() || "enroll";
|
|
232784
233088
|
const base = gatewayInstanceSlug(gatewayUrl);
|
|
232785
233089
|
return base.slice(0, Math.max(1, 64 - suffix.length - 1)) + "-" + suffix;
|
|
232786
233090
|
}
|
|
@@ -233109,12 +233413,12 @@ function buildNpxCmd(p2) {
|
|
|
233109
233413
|
const prefix = daemonNpmPrefix();
|
|
233110
233414
|
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)}`;
|
|
233111
233415
|
}
|
|
233112
|
-
var
|
|
233416
|
+
var import_node_crypto59;
|
|
233113
233417
|
var init_connect_script = __esm({
|
|
233114
233418
|
"../server/src/domains/nodes/connect-script.ts"() {
|
|
233115
233419
|
"use strict";
|
|
233116
233420
|
init_src();
|
|
233117
|
-
|
|
233421
|
+
import_node_crypto59 = require("node:crypto");
|
|
233118
233422
|
}
|
|
233119
233423
|
});
|
|
233120
233424
|
|
|
@@ -233675,7 +233979,7 @@ function nodesDomain(deps) {
|
|
|
233675
233979
|
}
|
|
233676
233980
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
233677
233981
|
} else {
|
|
233678
|
-
nodeId = `node-${(0,
|
|
233982
|
+
nodeId = `node-${(0, import_node_crypto60.randomUUID)().slice(0, 8)}`;
|
|
233679
233983
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
233680
233984
|
}
|
|
233681
233985
|
const existingNode = await deps.nodeStore.getNode(nodeId);
|
|
@@ -233858,13 +234162,13 @@ function normalizeGatewayUrl(raw) {
|
|
|
233858
234162
|
}
|
|
233859
234163
|
}
|
|
233860
234164
|
function newNodeId() {
|
|
233861
|
-
return "node-" + (0,
|
|
234165
|
+
return "node-" + (0, import_node_crypto60.randomUUID)().replace(/-/g, "").slice(0, 12);
|
|
233862
234166
|
}
|
|
233863
|
-
var
|
|
234167
|
+
var import_node_crypto60, import_node_fs16, import_node_url6, import_node_path21;
|
|
233864
234168
|
var init_routes7 = __esm({
|
|
233865
234169
|
"../server/src/domains/nodes/routes.ts"() {
|
|
233866
234170
|
"use strict";
|
|
233867
|
-
|
|
234171
|
+
import_node_crypto60 = require("node:crypto");
|
|
233868
234172
|
import_node_fs16 = require("node:fs");
|
|
233869
234173
|
import_node_url6 = require("node:url");
|
|
233870
234174
|
import_node_path21 = require("node:path");
|
|
@@ -235055,7 +235359,7 @@ function createBundle(root, target, input) {
|
|
|
235055
235359
|
}
|
|
235056
235360
|
}
|
|
235057
235361
|
const bytes2 = fs26.statSync(absBundle).size;
|
|
235058
|
-
const digest = (0,
|
|
235362
|
+
const digest = (0, import_node_crypto61.createHash)("sha256").update(fs26.readFileSync(absBundle)).digest("hex");
|
|
235059
235363
|
const relBase = `inputs/git-bundles/${safeRepo}-${commit.slice(0, 12)}`;
|
|
235060
235364
|
return {
|
|
235061
235365
|
absoluteBundlePath: absBundle,
|
|
@@ -235151,12 +235455,12 @@ function classifyGitError(fallback, err, where) {
|
|
|
235151
235455
|
function oneLine(msg) {
|
|
235152
235456
|
return msg.split("\n").map((s2) => s2.trim()).filter(Boolean).slice(0, 3).join(" ");
|
|
235153
235457
|
}
|
|
235154
|
-
var import_node_child_process17,
|
|
235458
|
+
var import_node_child_process17, import_node_crypto61, fs26, os7, path25, GitReadonlyBundleError, HEX40, FETCH_TIMEOUT_MS2;
|
|
235155
235459
|
var init_readonly_bundle = __esm({
|
|
235156
235460
|
"../server/src/git/readonly-bundle.ts"() {
|
|
235157
235461
|
"use strict";
|
|
235158
235462
|
import_node_child_process17 = require("node:child_process");
|
|
235159
|
-
|
|
235463
|
+
import_node_crypto61 = require("node:crypto");
|
|
235160
235464
|
fs26 = __toESM(require("node:fs"), 1);
|
|
235161
235465
|
os7 = __toESM(require("node:os"), 1);
|
|
235162
235466
|
path25 = __toESM(require("node:path"), 1);
|
|
@@ -235176,7 +235480,7 @@ var init_readonly_bundle = __esm({
|
|
|
235176
235480
|
|
|
235177
235481
|
// ../server/src/domains/collab/create-seeded-workorder.ts
|
|
235178
235482
|
function makeSeededWorkorderCreator(deps) {
|
|
235179
|
-
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0,
|
|
235483
|
+
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto62.randomUUID)().slice(0, 8)}`);
|
|
235180
235484
|
return async (input) => {
|
|
235181
235485
|
const company = input.companyId && deps.resolveCompany ? await deps.resolveCompany(input.companyId) : void 0;
|
|
235182
235486
|
const kernel = company?.kernel ?? deps.kernel;
|
|
@@ -235269,7 +235573,7 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
235269
235573
|
};
|
|
235270
235574
|
}
|
|
235271
235575
|
function workspaceForKey(key) {
|
|
235272
|
-
return `ws:wo-${(0,
|
|
235576
|
+
return `ws:wo-${(0, import_node_crypto62.createHash)("sha256").update(key).digest("hex").slice(0, 8)}`;
|
|
235273
235577
|
}
|
|
235274
235578
|
function existingWorkorder(kernel, workspace) {
|
|
235275
235579
|
const arts = [...kernel.model.artifacts.values()].filter((a) => a.workspace === workspace);
|
|
@@ -235282,11 +235586,11 @@ function existingWorkorder(kernel, workspace) {
|
|
|
235282
235586
|
spawned: arts.map((a) => ({ id: a.id, type: a.type, owner: a.owner }))
|
|
235283
235587
|
};
|
|
235284
235588
|
}
|
|
235285
|
-
var
|
|
235589
|
+
var import_node_crypto62, enc2;
|
|
235286
235590
|
var init_create_seeded_workorder = __esm({
|
|
235287
235591
|
"../server/src/domains/collab/create-seeded-workorder.ts"() {
|
|
235288
235592
|
"use strict";
|
|
235289
|
-
|
|
235593
|
+
import_node_crypto62 = require("node:crypto");
|
|
235290
235594
|
init_uncategorized_project();
|
|
235291
235595
|
init_src();
|
|
235292
235596
|
init_planner();
|
|
@@ -236716,12 +237020,12 @@ function stateFromAttempt(attempt, handoff, checkpoint, now, stalledAfterMs, ope
|
|
|
236716
237020
|
if (attempt.status === "no-output") return handoff?.unresolvedIssues.length ? "blocked" : "no_change";
|
|
236717
237021
|
return "failed";
|
|
236718
237022
|
}
|
|
236719
|
-
var
|
|
237023
|
+
var import_node_crypto63, BLOCKING_STATES, HANDOFF_OUTCOMES2, RESUME_EXTERNAL_EFFECT_LIMIT, RESUME_SNAPSHOT_PREFIX, RESUME_SNAPSHOT_SUFFIX, ExecutionContinuityService;
|
|
236720
237024
|
var init_service8 = __esm({
|
|
236721
237025
|
"../server/src/domains/execution-continuity/service.ts"() {
|
|
236722
237026
|
"use strict";
|
|
236723
237027
|
init_src();
|
|
236724
|
-
|
|
237028
|
+
import_node_crypto63 = require("node:crypto");
|
|
236725
237029
|
init_src5();
|
|
236726
237030
|
BLOCKING_STATES = /* @__PURE__ */ new Set(["stalled", "failed", "blocked"]);
|
|
236727
237031
|
HANDOFF_OUTCOMES2 = /* @__PURE__ */ new Set(["succeeded", "no-output", "failed", "cancelled", "timeout", "orphaned"]);
|
|
@@ -236952,7 +237256,7 @@ var init_service8 = __esm({
|
|
|
236952
237256
|
if (typeof expectedHash !== "string" || !this.readBundleFile) return null;
|
|
236953
237257
|
const injectedResume = this.readBundleFile(attempt.id, "execution/RESUME.md");
|
|
236954
237258
|
if (!injectedResume) return null;
|
|
236955
|
-
const actualHash = (0,
|
|
237259
|
+
const actualHash = (0, import_node_crypto63.createHash)("sha256").update(injectedResume).digest("hex");
|
|
236956
237260
|
if (actualHash !== expectedHash) return null;
|
|
236957
237261
|
const recoverySnapshot = parseResumePackSnapshot(injectedResume);
|
|
236958
237262
|
if (!recoverySnapshot || recoverySnapshot.scenario !== "redispatch" || !recoverySnapshot.previousAttempt || recoverySnapshot.node.nodeId !== attempt.nodeId || recoverySnapshot.jobKey !== attempt.jobKey || recoverySnapshot.part !== attempt.part) return null;
|
|
@@ -237879,6 +238183,10 @@ var init_project_bundle = __esm({
|
|
|
237879
238183
|
});
|
|
237880
238184
|
|
|
237881
238185
|
// ../server/src/domains/chat-sessions/index.ts
|
|
238186
|
+
function sessionProjectIdToStore(projectId2) {
|
|
238187
|
+
if (typeof projectId2 !== "string" || projectId2.trim() === "") return null;
|
|
238188
|
+
return isUncategorizedProjectId(projectId2) ? null : projectId2;
|
|
238189
|
+
}
|
|
237882
238190
|
function parseDurationMs(raw) {
|
|
237883
238191
|
if (!raw) return null;
|
|
237884
238192
|
const m2 = /^(\d+)\s*(ms|s|m|h|d)?$/i.exec(raw.trim());
|
|
@@ -238052,7 +238360,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238052
238360
|
if (!text5.trim()) throw new ApiError(400, "BAD_REQUEST", "text required");
|
|
238053
238361
|
const now = Date.now();
|
|
238054
238362
|
sweepDrafts(now);
|
|
238055
|
-
const id = `cd_${(0,
|
|
238363
|
+
const id = `cd_${(0, import_node_crypto64.randomUUID)()}`;
|
|
238056
238364
|
drafts.set(id, { text: text5, actor: req.auth.actor, expiresAt: now + DRAFT_TTL_MS });
|
|
238057
238365
|
return { status: 201, body: { id, expiresInMs: DRAFT_TTL_MS } };
|
|
238058
238366
|
});
|
|
@@ -238104,7 +238412,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238104
238412
|
const runtimeId = await currentRuntimeId(body2.aiActorId) ?? "unknown";
|
|
238105
238413
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
238106
238414
|
const session = {
|
|
238107
|
-
id: (0,
|
|
238415
|
+
id: (0, import_node_crypto64.randomUUID)(),
|
|
238108
238416
|
humanActorId: req.auth.actor,
|
|
238109
238417
|
// 注:这里**刻意不写 companyId**。新会话要不要带公司归属,按 ws:wo-6d588f8e 的 ADR
|
|
238110
238418
|
// (每公司 schema、最终移除表内 company 列)统一定,不在本节点自行发明。
|
|
@@ -238117,7 +238425,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238117
238425
|
// 决策 0030 缝合:绑定是会话的语义属性(工单频道/问题会话给、脑暴省略)——发消息端据它带 workspace,
|
|
238118
238426
|
// 两个入口页面行为一致。区别于 linkWorkOrder(出处关联,建单脑暴也有、不构成绑定)。
|
|
238119
238427
|
workspace: body2.workspace ?? null,
|
|
238120
|
-
projectId: body2.projectId
|
|
238428
|
+
projectId: sessionProjectIdToStore(body2.projectId),
|
|
238121
238429
|
// 会话级模型覆盖(口径 A):建会话时就带上选择;空串/空白归 null = 沿用旧解析,不写员工全局配置。
|
|
238122
238430
|
model: normalizeModel(body2.model),
|
|
238123
238431
|
// ADR-0058:分析会话指向被分析 run;非空即"这是分析会话"(不进主聊天列表、进 trace 分析视图)。
|
|
@@ -238186,7 +238494,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238186
238494
|
...body2.runtimeId !== void 0 ? { runtimeId: body2.runtimeId } : {},
|
|
238187
238495
|
...Object.prototype.hasOwnProperty.call(body2, "runtimeSessionId") ? { runtimeSessionId: body2.runtimeSessionId } : {},
|
|
238188
238496
|
...body2.title !== void 0 ? { title: body2.title } : {},
|
|
238189
|
-
...Object.prototype.hasOwnProperty.call(body2, "projectId") ? { projectId: body2.projectId } : {},
|
|
238497
|
+
...Object.prototype.hasOwnProperty.call(body2, "projectId") ? { projectId: sessionProjectIdToStore(body2.projectId) } : {},
|
|
238190
238498
|
// 会话级模型覆盖:显式传 null / 空串 = 清除覆盖(回到旧解析);不传这一项 = 不动它。
|
|
238191
238499
|
...Object.prototype.hasOwnProperty.call(body2, "model") ? { model: normalizeModel(body2.model) } : {},
|
|
238192
238500
|
// 只有显式传了才写——改标题 / 换项目 / 换模型都不是「有新动静」,不该顶掉列表顺序与已读水位。
|
|
@@ -238210,7 +238518,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238210
238518
|
if (body2.role !== "user" && body2.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
|
|
238211
238519
|
const role = body2.role;
|
|
238212
238520
|
const msg = await store2.appendMessage({
|
|
238213
|
-
id: (0,
|
|
238521
|
+
id: (0, import_node_crypto64.randomUUID)(),
|
|
238214
238522
|
sessionId: req.params.id,
|
|
238215
238523
|
role,
|
|
238216
238524
|
content: role === "user" ? stripInjectedChatContext(body2.content) : body2.content,
|
|
@@ -238251,7 +238559,7 @@ function createChatSessionsDomain(opts) {
|
|
|
238251
238559
|
const known = key ? cur.find((x2) => x2.clientKey === key) : void 0;
|
|
238252
238560
|
if (!known && cur.length >= QUEUE_MAX) throw new ApiError(409, "QUEUE_FULL", `\u961F\u5217\u5DF2\u6EE1\uFF08\u4E0A\u9650 ${QUEUE_MAX} \u6761\uFF09`);
|
|
238253
238561
|
const item = await store.enqueuePendingMessage({
|
|
238254
|
-
id: (0,
|
|
238562
|
+
id: (0, import_node_crypto64.randomUUID)(),
|
|
238255
238563
|
chatSessionId: sid,
|
|
238256
238564
|
text: text5,
|
|
238257
238565
|
...attachments.length ? { attachments } : {},
|
|
@@ -238568,6 +238876,20 @@ function createChatSessionsDomain(opts) {
|
|
|
238568
238876
|
return { status: 200, body: body2 };
|
|
238569
238877
|
});
|
|
238570
238878
|
router.get("/api/chat-sessions/:id/workdir/file", async (req) => {
|
|
238879
|
+
const store2 = await storeFor(req);
|
|
238880
|
+
const session = await store2.getSession(req.params.id);
|
|
238881
|
+
if (!session || session.humanActorId !== req.auth.actor) throw new ApiError(404, "NOT_FOUND", "session not found");
|
|
238882
|
+
const copy = (await store2.readOutputCopies?.(session.id))?.[req.query?.get("path") ?? ""];
|
|
238883
|
+
if (copy) {
|
|
238884
|
+
const blobs = opts.resolveBlobs ? await opts.resolveBlobs(req.auth.companyId) : opts.blobs;
|
|
238885
|
+
if (!blobs?.get) throw new ApiError(503, "BLOB_STORE_UNAVAILABLE", "\u6587\u4EF6\u5B58\u50A8\u6682\u4E0D\u53EF\u7528");
|
|
238886
|
+
const bytes2 = Buffer.from(await blobs.get(copy.blobRef));
|
|
238887
|
+
return { status: 200, body: bytes2, headers: {
|
|
238888
|
+
"content-type": copy.contentType ?? "application/octet-stream",
|
|
238889
|
+
"content-length": String(bytes2.length),
|
|
238890
|
+
"cache-control": "no-store"
|
|
238891
|
+
} };
|
|
238892
|
+
}
|
|
238571
238893
|
const bridge = opts.workdir?.();
|
|
238572
238894
|
if (!bridge) throw new ApiError(404, "NOT_FOUND", "\u5DE5\u4F5C\u533A\u6587\u4EF6\u6D4F\u89C8\u672A\u542F\u7528");
|
|
238573
238895
|
const loc = await locateWorkdir(await storeFor(req), req.auth.companyId, req.params.id, req.auth.actor);
|
|
@@ -238604,9 +238926,12 @@ function createChatSessionsDomain(opts) {
|
|
|
238604
238926
|
const store2 = await storeFor(req);
|
|
238605
238927
|
const session = await store2.getSession(req.params.id);
|
|
238606
238928
|
if (!session || session.humanActorId !== req.auth.actor) throw new ApiError(404, "NOT_FOUND", "session not found");
|
|
238607
|
-
const attachmentRows = store2.listSessionAttachmentMessages ? await store2.listSessionAttachmentMessages(session.id) : await store2.listMessages(session.id);
|
|
238608
238929
|
const blobAccess = opts.resolveBlobs ? await opts.resolveBlobs(req.auth?.companyId) : opts.blobs;
|
|
238609
|
-
const
|
|
238930
|
+
const persistentItems = await readPersistentSessionFiles(store2, session.id, blobAccess, true);
|
|
238931
|
+
const messageItems = persistentItems.filter((item) => item.source === "message");
|
|
238932
|
+
const allOutputs = persistentItems.filter((item) => item.source === "output");
|
|
238933
|
+
const savedOutputs = allOutputs.filter((output) => !messageItems.some((m2) => m2.name === output.name && m2.blob_ref === output.blob_ref));
|
|
238934
|
+
const fileIssues = await store2.readFileIssues?.(session.id) ?? [];
|
|
238610
238935
|
let workdirItems = [];
|
|
238611
238936
|
let materializedCopies = /* @__PURE__ */ new Set();
|
|
238612
238937
|
let workdirAvailable = false;
|
|
@@ -238633,8 +238958,13 @@ function createChatSessionsDomain(opts) {
|
|
|
238633
238958
|
}
|
|
238634
238959
|
}
|
|
238635
238960
|
}
|
|
238636
|
-
const
|
|
238961
|
+
const archivedPaths = new Set(allOutputs.map((item) => item.path));
|
|
238962
|
+
const items = mergeChatSessionFiles(messageItems, [
|
|
238963
|
+
...savedOutputs,
|
|
238964
|
+
...workdirItems.filter((item) => !archivedPaths.has(item.path) && !item.path?.startsWith("inputs/history/"))
|
|
238965
|
+
], materializedCopies);
|
|
238637
238966
|
const body2 = {
|
|
238967
|
+
...fileIssues.length ? { fileIssues } : {},
|
|
238638
238968
|
total: items.length,
|
|
238639
238969
|
items,
|
|
238640
238970
|
workdirAvailable,
|
|
@@ -238702,13 +239032,14 @@ function createChatSessionsDomain(opts) {
|
|
|
238702
239032
|
});
|
|
238703
239033
|
};
|
|
238704
239034
|
}
|
|
238705
|
-
var
|
|
239035
|
+
var import_node_crypto64, DEFAULT_SNAPSHOT_ITEMS, MAX_SNAPSHOT_ITEMS;
|
|
238706
239036
|
var init_chat_sessions2 = __esm({
|
|
238707
239037
|
"../server/src/domains/chat-sessions/index.ts"() {
|
|
238708
239038
|
"use strict";
|
|
238709
|
-
|
|
239039
|
+
import_node_crypto64 = require("node:crypto");
|
|
238710
239040
|
init_src();
|
|
238711
239041
|
init_chat_session();
|
|
239042
|
+
init_persistent_files();
|
|
238712
239043
|
init_files_view();
|
|
238713
239044
|
init_router();
|
|
238714
239045
|
init_collab();
|
|
@@ -238723,6 +239054,7 @@ var init_chat_sessions2 = __esm({
|
|
|
238723
239054
|
init_company_data_store_router();
|
|
238724
239055
|
init_workorder_terminal();
|
|
238725
239056
|
init_session_workdir();
|
|
239057
|
+
init_uncategorized_project();
|
|
238726
239058
|
init_project_bundle();
|
|
238727
239059
|
DEFAULT_SNAPSHOT_ITEMS = 400;
|
|
238728
239060
|
MAX_SNAPSHOT_ITEMS = 1e3;
|
|
@@ -240110,7 +240442,7 @@ function busyError(chatSessionId, blockedBy) {
|
|
|
240110
240442
|
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`;
|
|
240111
240443
|
}
|
|
240112
240444
|
function genWebhookToken() {
|
|
240113
|
-
return `owt_${(0,
|
|
240445
|
+
return `owt_${(0, import_node_crypto65.randomBytes)(32).toString("base64url")}`;
|
|
240114
240446
|
}
|
|
240115
240447
|
function validateTitleTemplate(tpl) {
|
|
240116
240448
|
const residue = tpl.replace(DATE_TOKEN, "");
|
|
@@ -240166,11 +240498,11 @@ function appendSourceNote(brief, automation, source, atIso) {
|
|
|
240166
240498
|
---
|
|
240167
240499
|
\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`;
|
|
240168
240500
|
}
|
|
240169
|
-
var
|
|
240501
|
+
var import_node_crypto65, DATE_TOKEN, AutomationsService, EVENT_RETRY_BASE_MS, EVENT_RETRY_MAX_MS, EVENT_RETRY_MAX_ATTEMPTS, eventAttempts, eventLastAttemptAt, eventLastError, CHAT_REPLY_MAX;
|
|
240170
240502
|
var init_service9 = __esm({
|
|
240171
240503
|
"../server/src/domains/automations/service.ts"() {
|
|
240172
240504
|
"use strict";
|
|
240173
|
-
|
|
240505
|
+
import_node_crypto65 = require("node:crypto");
|
|
240174
240506
|
init_src();
|
|
240175
240507
|
init_registry3();
|
|
240176
240508
|
init_attribution();
|
|
@@ -240984,11 +241316,11 @@ function verifySignature(rawBody, headers, secret) {
|
|
|
240984
241316
|
if (!secret) return "not_required";
|
|
240985
241317
|
const given = header1(headers, "x-hub-signature-256");
|
|
240986
241318
|
if (!given) return "missing";
|
|
240987
|
-
const expected = `sha256=${(0,
|
|
241319
|
+
const expected = `sha256=${(0, import_node_crypto66.createHmac)("sha256", secret).update(rawBody).digest("hex")}`;
|
|
240988
241320
|
const a = Buffer.from(given);
|
|
240989
241321
|
const b2 = Buffer.from(expected);
|
|
240990
241322
|
if (a.length !== b2.length) return "invalid";
|
|
240991
|
-
return (0,
|
|
241323
|
+
return (0, import_node_crypto66.timingSafeEqual)(a, b2) ? "valid" : "invalid";
|
|
240992
241324
|
}
|
|
240993
241325
|
function eventAllowed(filters, envelope) {
|
|
240994
241326
|
if (!filters || filters.length === 0) return true;
|
|
@@ -241018,11 +241350,11 @@ function splitEvent(envelope) {
|
|
|
241018
241350
|
}
|
|
241019
241351
|
return { eventName, actionCandidates: candidates };
|
|
241020
241352
|
}
|
|
241021
|
-
var
|
|
241353
|
+
var import_node_crypto66, MAX_BODY_BYTES, AutomationWebhookService, header1, PROVIDER_PREFIXES;
|
|
241022
241354
|
var init_webhook = __esm({
|
|
241023
241355
|
"../server/src/domains/automations/webhook.ts"() {
|
|
241024
241356
|
"use strict";
|
|
241025
|
-
|
|
241357
|
+
import_node_crypto66 = require("node:crypto");
|
|
241026
241358
|
MAX_BODY_BYTES = 256 * 1024;
|
|
241027
241359
|
AutomationWebhookService = class {
|
|
241028
241360
|
store;
|
|
@@ -242178,7 +242510,7 @@ function playbooksDomain(opts) {
|
|
|
242178
242510
|
opts.overrides.set(companyOf(req), ref2, nodeKey, nextOverride);
|
|
242179
242511
|
try {
|
|
242180
242512
|
await opts.audit?.({
|
|
242181
|
-
id: `reg_${(0,
|
|
242513
|
+
id: `reg_${(0, import_node_crypto67.randomUUID)()}`,
|
|
242182
242514
|
actor: req.auth.actor,
|
|
242183
242515
|
kind: "registry_change",
|
|
242184
242516
|
target: `playbook:${ref2}#${nodeKey}`,
|
|
@@ -242195,11 +242527,11 @@ function playbooksDomain(opts) {
|
|
|
242195
242527
|
});
|
|
242196
242528
|
};
|
|
242197
242529
|
}
|
|
242198
|
-
var
|
|
242530
|
+
var import_node_crypto67;
|
|
242199
242531
|
var init_routes12 = __esm({
|
|
242200
242532
|
"../server/src/domains/playbooks/routes.ts"() {
|
|
242201
242533
|
"use strict";
|
|
242202
|
-
|
|
242534
|
+
import_node_crypto67 = require("node:crypto");
|
|
242203
242535
|
init_router();
|
|
242204
242536
|
init_registry3();
|
|
242205
242537
|
init_planner();
|
|
@@ -242313,17 +242645,17 @@ function completionFingerprint(workspace, members) {
|
|
|
242313
242645
|
workspace,
|
|
242314
242646
|
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 }))
|
|
242315
242647
|
});
|
|
242316
|
-
return (0,
|
|
242648
|
+
return (0, import_node_crypto68.createHash)("sha256").update(canonical).digest("hex");
|
|
242317
242649
|
}
|
|
242318
242650
|
function eventConsumptionKey(args) {
|
|
242319
242651
|
const raw = `project-event:${EVENT_KEY_VERSION}:${args.triggerId}:${args.event}:${args.workspace}:${args.fingerprint}`;
|
|
242320
|
-
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0,
|
|
242652
|
+
return raw.length <= 200 ? raw : `project-event:${EVENT_KEY_VERSION}:sha256:${(0, import_node_crypto68.createHash)("sha256").update(raw).digest("hex")}`;
|
|
242321
242653
|
}
|
|
242322
|
-
var
|
|
242654
|
+
var import_node_crypto68, EVENT_KEY_VERSION, EMPTY_METRICS, AUTOMATION_EVENT_HANDLERS, ProjectEventPoller;
|
|
242323
242655
|
var init_project_event_poller = __esm({
|
|
242324
242656
|
"../server/src/automations/project-event-poller.ts"() {
|
|
242325
242657
|
"use strict";
|
|
242326
|
-
|
|
242658
|
+
import_node_crypto68 = require("node:crypto");
|
|
242327
242659
|
EVENT_KEY_VERSION = "v1";
|
|
242328
242660
|
EMPTY_METRICS = () => ({
|
|
242329
242661
|
scanDurationMs: 0,
|
|
@@ -242534,7 +242866,7 @@ function remoteAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs) {
|
|
|
242534
242866
|
if (input.requireConsumptionReceipt && !hub.supportsInputConsumptionReceipts?.(dispatchId)) {
|
|
242535
242867
|
return Promise.resolve({ accepted: false, reason: "consumption-unsupported" });
|
|
242536
242868
|
}
|
|
242537
|
-
const requestId = (0,
|
|
242869
|
+
const requestId = (0, import_node_crypto69.randomUUID)();
|
|
242538
242870
|
const sent = routeToSession(hub, nodeId, dispatchId, { type: "append_input", dispatchId, input, requestId });
|
|
242539
242871
|
if (!sent) return Promise.resolve({ accepted: false, reason: "session-closing", ...unknownIfInterrupting });
|
|
242540
242872
|
return new Promise((resolve10) => {
|
|
@@ -242547,11 +242879,11 @@ function remoteAppendInput(hub, nodeId, dispatchId, entry, input, timeoutMs) {
|
|
|
242547
242879
|
entry.appendWaiters.push({ requestId, requireConsumptionReceipt: input.requireConsumptionReceipt, resolve: resolve10, timer });
|
|
242548
242880
|
});
|
|
242549
242881
|
}
|
|
242550
|
-
var
|
|
242882
|
+
var import_node_crypto69, STASH_TTL_MS, STASH_MAX_FRAMES_PER_ID, STASH_MAX_IDS, DaemonHubAdapter, BindingRouterAdapter, WorkdirBridge;
|
|
242551
242883
|
var init_daemon_adapter = __esm({
|
|
242552
242884
|
"../server/src/daemon-adapter.ts"() {
|
|
242553
242885
|
"use strict";
|
|
242554
|
-
|
|
242886
|
+
import_node_crypto69 = require("node:crypto");
|
|
242555
242887
|
init_src();
|
|
242556
242888
|
STASH_TTL_MS = 5 * 6e4;
|
|
242557
242889
|
STASH_MAX_FRAMES_PER_ID = 500;
|
|
@@ -242901,7 +243233,7 @@ var init_daemon_adapter = __esm({
|
|
|
242901
243233
|
async spawn(job) {
|
|
242902
243234
|
const nodeId = job.binding?.nodeId;
|
|
242903
243235
|
if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
|
|
242904
|
-
const dispatchId = job.dispatchId ?? `dispatch:${(0,
|
|
243236
|
+
const dispatchId = job.dispatchId ?? `dispatch:${(0, import_node_crypto69.randomUUID)()}`;
|
|
242905
243237
|
if (job.dispatchId && this.pending.has(dispatchId)) {
|
|
242906
243238
|
return this.recover(dispatchId, nodeId, job.binding?.runtimeKind, job.actor);
|
|
242907
243239
|
}
|
|
@@ -243138,7 +243470,7 @@ var init_daemon_adapter = __esm({
|
|
|
243138
243470
|
return daemon?.meta.supportsWorkdirWalk === true;
|
|
243139
243471
|
}
|
|
243140
243472
|
request(nodeId, buildFrame) {
|
|
243141
|
-
const requestId = (0,
|
|
243473
|
+
const requestId = (0, import_node_crypto69.randomUUID)();
|
|
243142
243474
|
const sent = this.hub.dispatch(nodeId, buildFrame(requestId));
|
|
243143
243475
|
if (!sent) return Promise.resolve({ ok: false, code: "NODE_OFFLINE" });
|
|
243144
243476
|
return new Promise((resolve10) => {
|
|
@@ -243246,13 +243578,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
243246
243578
|
if (sha(body2) === lastPushedHash) return { kind: "echo" };
|
|
243247
243579
|
return { kind: "human-edit", content: body2, updatedBy: page.updatedBy };
|
|
243248
243580
|
}
|
|
243249
|
-
var
|
|
243581
|
+
var import_node_crypto70, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
|
|
243250
243582
|
var init_engine = __esm({
|
|
243251
243583
|
"../server/src/mirror/engine.ts"() {
|
|
243252
243584
|
"use strict";
|
|
243253
|
-
|
|
243585
|
+
import_node_crypto70 = require("node:crypto");
|
|
243254
243586
|
init_src();
|
|
243255
|
-
sha = (s2) => (0,
|
|
243587
|
+
sha = (s2) => (0, import_node_crypto70.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
243256
243588
|
enc3 = (s2) => new TextEncoder().encode(s2);
|
|
243257
243589
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
243258
243590
|
MirrorEngine = class {
|
|
@@ -243499,11 +243831,11 @@ function humanExitCause(exit3) {
|
|
|
243499
243831
|
const base = (exit3.reason ? label[exit3.reason] : void 0) ?? `\u4F1A\u8BDD\u5F02\u5E38\u7ED3\u675F\uFF08${exit3.reason ?? "\u65E0\u9000\u51FA\u4FE1\u606F"}\uFF09`;
|
|
243500
243832
|
return exit3.errorMessage ? `${base}\uFF1A${exit3.errorMessage.slice(0, 200)}` : base;
|
|
243501
243833
|
}
|
|
243502
|
-
var
|
|
243834
|
+
var import_node_crypto71, 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;
|
|
243503
243835
|
var init_worker = __esm({
|
|
243504
243836
|
"../server/src/coordinator/worker.ts"() {
|
|
243505
243837
|
"use strict";
|
|
243506
|
-
|
|
243838
|
+
import_node_crypto71 = require("node:crypto");
|
|
243507
243839
|
init_src5();
|
|
243508
243840
|
init_identity();
|
|
243509
243841
|
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
|
|
@@ -243772,7 +244104,7 @@ ${HIGH_RISK_COMMANDS}`;
|
|
|
243772
244104
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
243773
244105
|
}
|
|
243774
244106
|
evaluationKey(kind, artifactId, evidence) {
|
|
243775
|
-
const fingerprint2 = (0,
|
|
244107
|
+
const fingerprint2 = (0, import_node_crypto71.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
243776
244108
|
return `${kind}:${artifactId}:${fingerprint2}`;
|
|
243777
244109
|
}
|
|
243778
244110
|
artifactEvidence(id) {
|
|
@@ -244151,8 +244483,8 @@ ${ctx.nodeFault}
|
|
|
244151
244483
|
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)}`);
|
|
244152
244484
|
}
|
|
244153
244485
|
}
|
|
244154
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
244155
|
-
const coordinatorRunId = `coordinate:${(0,
|
|
244486
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto71.randomUUID)();
|
|
244487
|
+
const coordinatorRunId = `coordinate:${(0, import_node_crypto71.randomUUID)()}`;
|
|
244156
244488
|
const taskWithContext = coordinatorContext ? [
|
|
244157
244489
|
task,
|
|
244158
244490
|
``,
|
|
@@ -244196,7 +244528,7 @@ ${ctx.nodeFault}
|
|
|
244196
244528
|
const startedAtMs = Date.now();
|
|
244197
244529
|
let trajectoryStarted = false;
|
|
244198
244530
|
if (this.deps.trajectory) {
|
|
244199
|
-
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0,
|
|
244531
|
+
const bundleManifest = Object.fromEntries(Object.entries(job.bundle.files).map(([name, content3]) => [name, (0, import_node_crypto71.createHash)("sha256").update(content3).digest("hex")]));
|
|
244200
244532
|
const session = {
|
|
244201
244533
|
runId: coordinatorRunId,
|
|
244202
244534
|
runtimeSessionId,
|
|
@@ -244401,11 +244733,11 @@ var init_pg_ident = __esm({
|
|
|
244401
244733
|
});
|
|
244402
244734
|
|
|
244403
244735
|
// ../storage/src/postgres.ts
|
|
244404
|
-
var
|
|
244736
|
+
var import_node_crypto72, ident4, isUniqueViolation, PostgresOplogStore, PostgresBlobStore;
|
|
244405
244737
|
var init_postgres = __esm({
|
|
244406
244738
|
"../storage/src/postgres.ts"() {
|
|
244407
244739
|
"use strict";
|
|
244408
|
-
|
|
244740
|
+
import_node_crypto72 = require("node:crypto");
|
|
244409
244741
|
init_pg_ident();
|
|
244410
244742
|
init_esm();
|
|
244411
244743
|
init_src();
|
|
@@ -244585,7 +244917,7 @@ var init_postgres = __esm({
|
|
|
244585
244917
|
return new _PostgresBlobStore(pool, schema);
|
|
244586
244918
|
}
|
|
244587
244919
|
async put(bytes2) {
|
|
244588
|
-
const hash2 = (0,
|
|
244920
|
+
const hash2 = (0, import_node_crypto72.createHash)("sha256").update(bytes2).digest("hex");
|
|
244589
244921
|
await this.pool.query(
|
|
244590
244922
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
244591
244923
|
[hash2, Buffer.from(bytes2), bytes2.byteLength, sniffContentType(bytes2) ?? null]
|
|
@@ -250858,6 +251190,7 @@ var init_postgres_chat_sessions = __esm({
|
|
|
250858
251190
|
await pool.query(`ALTER TABLE ${q2}.chat_sessions ADD COLUMN IF NOT EXISTS visibility text`);
|
|
250859
251191
|
await pool.query(`ALTER TABLE ${q2}.chat_sessions ADD COLUMN IF NOT EXISTS outputs_fingerprints jsonb`);
|
|
250860
251192
|
await pool.query(`ALTER TABLE ${q2}.chat_sessions ADD COLUMN IF NOT EXISTS outputs_copies jsonb`);
|
|
251193
|
+
await pool.query(`ALTER TABLE ${q2}.chat_sessions ADD COLUMN IF NOT EXISTS file_sync_issues jsonb`);
|
|
250861
251194
|
await pool.query(`
|
|
250862
251195
|
WITH ranked AS (
|
|
250863
251196
|
SELECT id, row_number() OVER (PARTITION BY session_id ORDER BY seq, created_at, id) AS rn
|
|
@@ -251129,6 +251462,29 @@ var init_postgres_chat_sessions = __esm({
|
|
|
251129
251462
|
);
|
|
251130
251463
|
return r.rows[0]?.outputs_copies ?? null;
|
|
251131
251464
|
}
|
|
251465
|
+
async readFileIssues(sessionId) {
|
|
251466
|
+
const r = await this.pool.query(
|
|
251467
|
+
`SELECT file_sync_issues FROM ${this.s}.chat_sessions WHERE id = $1 AND company_id = $2`,
|
|
251468
|
+
[sessionId, this.companyId]
|
|
251469
|
+
);
|
|
251470
|
+
return Object.values(r.rows[0]?.file_sync_issues ?? {}).flat();
|
|
251471
|
+
}
|
|
251472
|
+
async writeFileIssues(sessionId, phase, issues) {
|
|
251473
|
+
await this.pool.query(
|
|
251474
|
+
`UPDATE ${this.s}.chat_sessions SET file_sync_issues = COALESCE(file_sync_issues, '{}'::jsonb) || $1::jsonb
|
|
251475
|
+
WHERE id = $2 AND company_id = $3`,
|
|
251476
|
+
[JSON.stringify({ [phase]: issues }), sessionId, this.companyId]
|
|
251477
|
+
);
|
|
251478
|
+
}
|
|
251479
|
+
async listFileSessionsByWorkspaces(workspaces) {
|
|
251480
|
+
if (!workspaces.length) return [];
|
|
251481
|
+
const r = await this.pool.query(
|
|
251482
|
+
`SELECT * FROM ${this.s}.chat_sessions WHERE company_id = $1 AND workspace = ANY($2::text[])
|
|
251483
|
+
AND visibility IS DISTINCT FROM 'internal' AND analyzed_run_id IS NULL ORDER BY id`,
|
|
251484
|
+
[this.companyId, workspaces]
|
|
251485
|
+
);
|
|
251486
|
+
return r.rows.map(rowToSession);
|
|
251487
|
+
}
|
|
251132
251488
|
/**
|
|
251133
251489
|
* 按路径**合并**写入:同一路径新副本覆盖旧副本,其余路径保留。合并在一条 UPDATE 里用 jsonb `||` 完成,
|
|
251134
251490
|
* 不是读出来改完再整份写回——两次收尾的复制前后脚落库时,后写的不会把先写的吞掉。
|
|
@@ -253212,11 +253568,11 @@ var init_postgres_delegations = __esm({
|
|
|
253212
253568
|
});
|
|
253213
253569
|
|
|
253214
253570
|
// ../storage/src/postgres-nodes.ts
|
|
253215
|
-
var
|
|
253571
|
+
var import_node_crypto73, ident13, PostgresNodeStore, PostgresNodeTokenStore, rowToNode, rowToRuntime;
|
|
253216
253572
|
var init_postgres_nodes = __esm({
|
|
253217
253573
|
"../storage/src/postgres-nodes.ts"() {
|
|
253218
253574
|
"use strict";
|
|
253219
|
-
|
|
253575
|
+
import_node_crypto73 = require("node:crypto");
|
|
253220
253576
|
init_pg_ident();
|
|
253221
253577
|
init_esm();
|
|
253222
253578
|
ident13 = (s2) => {
|
|
@@ -253433,7 +253789,7 @@ var init_postgres_nodes = __esm({
|
|
|
253433
253789
|
return store;
|
|
253434
253790
|
}
|
|
253435
253791
|
issue(nodeId) {
|
|
253436
|
-
const token = `ont_${(0,
|
|
253792
|
+
const token = `ont_${(0, import_node_crypto73.randomBytes)(24).toString("base64url")}`;
|
|
253437
253793
|
this.cache.set(token, nodeId);
|
|
253438
253794
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
253439
253795
|
return token;
|
|
@@ -253699,11 +254055,11 @@ var init_postgres_type_registry = __esm({
|
|
|
253699
254055
|
});
|
|
253700
254056
|
|
|
253701
254057
|
// ../storage/src/postgres-actor-memory.ts
|
|
253702
|
-
var
|
|
254058
|
+
var import_node_crypto74, matchClause, ident15, PostgresActorMemoryStore, rowToIndexEntry, rowToRecord;
|
|
253703
254059
|
var init_postgres_actor_memory = __esm({
|
|
253704
254060
|
"../storage/src/postgres-actor-memory.ts"() {
|
|
253705
254061
|
"use strict";
|
|
253706
|
-
|
|
254062
|
+
import_node_crypto74 = require("node:crypto");
|
|
253707
254063
|
init_pg_ident();
|
|
253708
254064
|
init_src();
|
|
253709
254065
|
matchClause = (q2) => q2.requireMatch && q2.keywords.length > 0 ? " WHERE m > 0" : "";
|
|
@@ -253913,7 +254269,7 @@ var init_postgres_actor_memory = __esm({
|
|
|
253913
254269
|
}
|
|
253914
254270
|
async write(input, now) {
|
|
253915
254271
|
if (input.memId === void 0) {
|
|
253916
|
-
const memId = `mem:${(0,
|
|
254272
|
+
const memId = `mem:${(0, import_node_crypto74.randomUUID)()}`;
|
|
253917
254273
|
const r2 = await this.pool.query(
|
|
253918
254274
|
`INSERT INTO ${this.s}.actor_memories
|
|
253919
254275
|
(mem_id, actor_id, project_id, keywords, content, version, created_at, updated_at, accessed_at, source_artifact_id, source_session_id)
|
|
@@ -255360,14 +255716,14 @@ function companySchemaName(companyId) {
|
|
|
255360
255716
|
if (typeof companyId !== "string" || !companyId.trim()) {
|
|
255361
255717
|
throw new Error("company schema mapping \u9700\u8981\u975E\u7A7A companyId\uFF08fail-closed\uFF1A\u4E0D\u56DE\u9000\u9ED8\u8BA4\u516C\u53F8\uFF09");
|
|
255362
255718
|
}
|
|
255363
|
-
const hex = (0,
|
|
255719
|
+
const hex = (0, import_node_crypto75.createHash)("sha256").update(companyId, "utf8").digest("hex");
|
|
255364
255720
|
return `${COMPANY_SCHEMA_PREFIX}${hex.slice(0, DIGEST_HEX_LEN)}`;
|
|
255365
255721
|
}
|
|
255366
|
-
var
|
|
255722
|
+
var import_node_crypto75, COMPANY_SCHEMA_PREFIX, DIGEST_HEX_LEN, SchemaMappingConflictError, TenantStorageLocationStore;
|
|
255367
255723
|
var init_tenant_schema_mapping = __esm({
|
|
255368
255724
|
"../storage/src/tenant-schema-mapping.ts"() {
|
|
255369
255725
|
"use strict";
|
|
255370
|
-
|
|
255726
|
+
import_node_crypto75 = require("node:crypto");
|
|
255371
255727
|
init_esm();
|
|
255372
255728
|
init_pg_ident();
|
|
255373
255729
|
COMPANY_SCHEMA_PREFIX = "c_";
|
|
@@ -255441,7 +255797,7 @@ var init_tenant_schema_mapping = __esm({
|
|
|
255441
255797
|
|
|
255442
255798
|
// ../storage/src/company-data-plane-schema.ts
|
|
255443
255799
|
function canonicalTypeDefHash(def) {
|
|
255444
|
-
return `sha256:${(0,
|
|
255800
|
+
return `sha256:${(0, import_node_crypto76.createHash)("sha256").update(JSON.stringify(def), "utf8").digest("hex")}`;
|
|
255445
255801
|
}
|
|
255446
255802
|
function defaultArtifactTypeTemplate() {
|
|
255447
255803
|
return [
|
|
@@ -255623,11 +255979,11 @@ async function seedDefaultArtifactTypes(pool, schema, templates = defaultArtifac
|
|
|
255623
255979
|
}
|
|
255624
255980
|
return { inserted };
|
|
255625
255981
|
}
|
|
255626
|
-
var
|
|
255982
|
+
var import_node_crypto76, DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION;
|
|
255627
255983
|
var init_company_data_plane_schema = __esm({
|
|
255628
255984
|
"../storage/src/company-data-plane-schema.ts"() {
|
|
255629
255985
|
"use strict";
|
|
255630
|
-
|
|
255986
|
+
import_node_crypto76 = require("node:crypto");
|
|
255631
255987
|
init_esm();
|
|
255632
255988
|
init_pg_ident();
|
|
255633
255989
|
DEFAULT_ARTIFACT_TYPE_TEMPLATE_VERSION = "4c368e5c-types-v1";
|
|
@@ -255707,11 +256063,11 @@ function rowToFile2(row) {
|
|
|
255707
256063
|
updatedAt: new Date(row.updated_at).toISOString()
|
|
255708
256064
|
};
|
|
255709
256065
|
}
|
|
255710
|
-
var
|
|
256066
|
+
var import_node_crypto77, COMPANY_CONFLICT_MSG, CompanyIdentifierConflictError, CompanyOwnedRegistryStore;
|
|
255711
256067
|
var init_company_owned_registry_store = __esm({
|
|
255712
256068
|
"../storage/src/company-owned-registry-store.ts"() {
|
|
255713
256069
|
"use strict";
|
|
255714
|
-
|
|
256070
|
+
import_node_crypto77 = require("node:crypto");
|
|
255715
256071
|
init_esm();
|
|
255716
256072
|
init_src();
|
|
255717
256073
|
init_pg_ident();
|
|
@@ -256097,7 +256453,7 @@ var init_company_owned_registry_store = __esm({
|
|
|
256097
256453
|
enabled: skill.enabled,
|
|
256098
256454
|
files: files.map((f2) => ({ path: f2.path, blobHash: f2.blobHash }))
|
|
256099
256455
|
});
|
|
256100
|
-
return (0,
|
|
256456
|
+
return (0, import_node_crypto77.createHash)("sha256").update(body2).digest("hex");
|
|
256101
256457
|
}
|
|
256102
256458
|
};
|
|
256103
256459
|
}
|
|
@@ -258694,7 +259050,7 @@ function sourceSetConservation(input) {
|
|
|
258694
259050
|
return input.sourceFinal === input.copied + input.approvedRuntimeConversion + input.approvedArchive + input.approvedDiscard;
|
|
258695
259051
|
}
|
|
258696
259052
|
function payloadChecksum(value2) {
|
|
258697
|
-
return (0,
|
|
259053
|
+
return (0, import_node_crypto78.createHash)("sha256").update(JSON.stringify(value2)).digest("hex");
|
|
258698
259054
|
}
|
|
258699
259055
|
async function copyWorkorderDraftsIdempotent(pool, companyId, companySchema, manifestId, opts) {
|
|
258700
259056
|
const cs = quoteIdent2(companySchema);
|
|
@@ -259082,11 +259438,11 @@ async function copyTraceFamilyIdempotent(pool, companyId, companySchema, manifes
|
|
|
259082
259438
|
sequences
|
|
259083
259439
|
};
|
|
259084
259440
|
}
|
|
259085
|
-
var
|
|
259441
|
+
var import_node_crypto78, MissingInstallerActorsError, TypeCatalogNotCoveredError, ORG_REGISTRY_TABLES, TRACE_FAMILY;
|
|
259086
259442
|
var init_tenant_migration_operator = __esm({
|
|
259087
259443
|
"../storage/src/tenant-migration-operator.ts"() {
|
|
259088
259444
|
"use strict";
|
|
259089
|
-
|
|
259445
|
+
import_node_crypto78 = require("node:crypto");
|
|
259090
259446
|
init_esm();
|
|
259091
259447
|
init_pg_ident();
|
|
259092
259448
|
init_tenancy_attribution();
|
|
@@ -259318,8 +259674,8 @@ var init_tenant_new_company_provision = __esm({
|
|
|
259318
259674
|
// ../storage/src/knowledge-snapshot-crypto.ts
|
|
259319
259675
|
function sealSnapshot(snapshot, key) {
|
|
259320
259676
|
if (snapshot.content.startsWith(PREFIX3)) return structuredClone(snapshot);
|
|
259321
|
-
const iv = (0,
|
|
259322
|
-
const cipher = (0,
|
|
259677
|
+
const iv = (0, import_node_crypto79.randomBytes)(12);
|
|
259678
|
+
const cipher = (0, import_node_crypto79.createCipheriv)("aes-256-gcm", bytes(key), iv);
|
|
259323
259679
|
cipher.setAAD(aad2(snapshot));
|
|
259324
259680
|
const encrypted = Buffer.concat([cipher.update(snapshot.content, "utf8"), cipher.final()]);
|
|
259325
259681
|
return { ...structuredClone(snapshot), content: `${PREFIX3}${iv.toString("base64url")}.${cipher.getAuthTag().toString("base64url")}.${encrypted.toString("base64url")}` };
|
|
@@ -259329,7 +259685,7 @@ function openSnapshot(snapshot, key) {
|
|
|
259329
259685
|
const packed = snapshot.content.slice(PREFIX3.length).split(".");
|
|
259330
259686
|
if (packed.length !== 3 || packed.some((part) => !part)) throw new Error(`knowledge snapshot ${snapshot.ref} ciphertext is malformed`);
|
|
259331
259687
|
const [iv, tag, data] = packed;
|
|
259332
|
-
const decipher = (0,
|
|
259688
|
+
const decipher = (0, import_node_crypto79.createDecipheriv)("aes-256-gcm", bytes(key), Buffer.from(iv, "base64url"));
|
|
259333
259689
|
decipher.setAAD(aad2(snapshot));
|
|
259334
259690
|
decipher.setAuthTag(Buffer.from(tag, "base64url"));
|
|
259335
259691
|
return {
|
|
@@ -259337,11 +259693,11 @@ function openSnapshot(snapshot, key) {
|
|
|
259337
259693
|
content: Buffer.concat([decipher.update(Buffer.from(data, "base64url")), decipher.final()]).toString("utf8")
|
|
259338
259694
|
};
|
|
259339
259695
|
}
|
|
259340
|
-
var
|
|
259696
|
+
var import_node_crypto79, PREFIX3, bytes, aad2;
|
|
259341
259697
|
var init_knowledge_snapshot_crypto = __esm({
|
|
259342
259698
|
"../storage/src/knowledge-snapshot-crypto.ts"() {
|
|
259343
259699
|
"use strict";
|
|
259344
|
-
|
|
259700
|
+
import_node_crypto79 = require("node:crypto");
|
|
259345
259701
|
PREFIX3 = "oasis-knowledge:v1:";
|
|
259346
259702
|
bytes = (key) => {
|
|
259347
259703
|
const value2 = Buffer.from(key);
|
|
@@ -261371,6 +261727,7 @@ var init_src11 = __esm({
|
|
|
261371
261727
|
init_chat_recovery();
|
|
261372
261728
|
init_chat_system_message();
|
|
261373
261729
|
init_chat_turn_gate();
|
|
261730
|
+
init_chat_assistant_turn();
|
|
261374
261731
|
init_chat_workorder_files();
|
|
261375
261732
|
init_chat_broadcast();
|
|
261376
261733
|
init_workorder_terminal();
|
|
@@ -261453,6 +261810,7 @@ var init_src11 = __esm({
|
|
|
261453
261810
|
init_run_settlement_wiring();
|
|
261454
261811
|
init_deadline_clock();
|
|
261455
261812
|
init_read_model_clock();
|
|
261813
|
+
init_file_restore();
|
|
261456
261814
|
}
|
|
261457
261815
|
});
|
|
261458
261816
|
|
|
@@ -261588,20 +261946,20 @@ var fs45 = __toESM(require("node:fs"));
|
|
|
261588
261946
|
var os14 = __toESM(require("node:os"));
|
|
261589
261947
|
var path40 = __toESM(require("node:path"));
|
|
261590
261948
|
var import_node_child_process23 = require("node:child_process");
|
|
261591
|
-
var
|
|
261949
|
+
var import_node_crypto86 = require("node:crypto");
|
|
261592
261950
|
|
|
261593
261951
|
// ../cli/src/cli.ts
|
|
261594
261952
|
var fs40 = __toESM(require("node:fs"), 1);
|
|
261595
261953
|
var os12 = __toESM(require("node:os"), 1);
|
|
261596
261954
|
var path35 = __toESM(require("node:path"), 1);
|
|
261597
|
-
var
|
|
261955
|
+
var import_node_crypto84 = require("node:crypto");
|
|
261598
261956
|
|
|
261599
261957
|
// ../cli/src/serve.ts
|
|
261600
261958
|
var fs34 = __toESM(require("node:fs"), 1);
|
|
261601
261959
|
var os8 = __toESM(require("node:os"), 1);
|
|
261602
261960
|
var path29 = __toESM(require("node:path"), 1);
|
|
261603
261961
|
var import_node_child_process18 = require("node:child_process");
|
|
261604
|
-
var
|
|
261962
|
+
var import_node_crypto80 = require("node:crypto");
|
|
261605
261963
|
var import_node_url7 = require("node:url");
|
|
261606
261964
|
|
|
261607
261965
|
// ../cli/src/artifact-discovery-source.ts
|
|
@@ -262347,7 +262705,7 @@ init_src9();
|
|
|
262347
262705
|
init_src();
|
|
262348
262706
|
init_trajectory();
|
|
262349
262707
|
function deterministicUuid2(seed) {
|
|
262350
|
-
const h = (0,
|
|
262708
|
+
const h = (0, import_node_crypto80.createHash)("sha256").update(seed).digest();
|
|
262351
262709
|
const b2 = Buffer.from(h.subarray(0, 16));
|
|
262352
262710
|
b2[6] = b2[6] & 15 | 80;
|
|
262353
262711
|
b2[8] = b2[8] & 63 | 128;
|
|
@@ -262547,7 +262905,7 @@ function oasisWrapperScript() {
|
|
|
262547
262905
|
const repoRoot = (0, import_node_url7.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
262548
262906
|
const tsx = path29.join(repoRoot, "node_modules/.bin/tsx");
|
|
262549
262907
|
const main = path29.join(repoRoot, "packages/cli/src/main.ts");
|
|
262550
|
-
const key = (0,
|
|
262908
|
+
const key = (0, import_node_crypto80.createHash)("sha256").update(repoRoot).digest("hex").slice(0, 12);
|
|
262551
262909
|
const uid = typeof process.getuid === "function" ? process.getuid() : "na";
|
|
262552
262910
|
const stable = path29.join(os8.tmpdir(), `oasis-cli-wrapper-${uid}-${key}`);
|
|
262553
262911
|
let dir;
|
|
@@ -262928,7 +263286,7 @@ async function startServe(opts) {
|
|
|
262928
263286
|
if (!hub) return Promise.resolve({ ok: false, reason: "\u672C\u8FDB\u7A0B\u6CA1\u6709\u8282\u70B9\u7F51\u5173" });
|
|
262929
263287
|
const online = hub.connectedDaemons().some((d) => d.daemonId === nodeId);
|
|
262930
263288
|
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" });
|
|
262931
|
-
const requestId = (0,
|
|
263289
|
+
const requestId = (0, import_node_crypto80.randomUUID)();
|
|
262932
263290
|
const task = new Promise((resolve10) => {
|
|
262933
263291
|
const timer = setTimeout(() => {
|
|
262934
263292
|
modelRefreshWaiters.delete(requestId);
|
|
@@ -263199,6 +263557,8 @@ async function startServe(opts) {
|
|
|
263199
263557
|
listChatFiles: async (companyId, projectId2) => {
|
|
263200
263558
|
const chat = await chatStoreFor(companyId);
|
|
263201
263559
|
const facts = await blobStoreFor(companyId);
|
|
263560
|
+
const taskBindings = await (await artifactStateFor(companyId)).listWorkspaceBindings();
|
|
263561
|
+
const workOrderIds = taskBindings.filter((b2) => b2.projectId === projectId2 || isUncategorizedProjectId(projectId2) && !b2.projectId).map((b2) => b2.workOrderId);
|
|
263202
263562
|
return collectProjectChatFiles(chat, projectId2, async (ref2) => {
|
|
263203
263563
|
for (const cabinet of [assets, facts]) {
|
|
263204
263564
|
try {
|
|
@@ -263209,6 +263569,7 @@ async function startServe(opts) {
|
|
|
263209
263569
|
}
|
|
263210
263570
|
return null;
|
|
263211
263571
|
}, {
|
|
263572
|
+
workOrderIds,
|
|
263212
263573
|
// 委派子会话不进项目(ADR 0555:它的 outputs/ 是交给协调者的)。闭包在请求时才读
|
|
263213
263574
|
// `delegationStoreFor`,避开它在下方声明的 TDZ。
|
|
263214
263575
|
isDelegationChild: async (sessionId) => {
|
|
@@ -263680,7 +264041,7 @@ async function startServe(opts) {
|
|
|
263680
264041
|
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
263681
264042
|
if (buf || session.runId) {
|
|
263682
264043
|
await turnStore.appendMessage({
|
|
263683
|
-
id: (0,
|
|
264044
|
+
id: (0, import_node_crypto80.randomUUID)(),
|
|
263684
264045
|
sessionId: chatSessionId,
|
|
263685
264046
|
role: "assistant",
|
|
263686
264047
|
content: buf,
|
|
@@ -263726,7 +264087,7 @@ async function startServe(opts) {
|
|
|
263726
264087
|
chatTargets: {
|
|
263727
264088
|
inspect: inspectChatTarget,
|
|
263728
264089
|
createTargetSession: async ({ companyId, agentId, ownerHumanActorId, title }) => {
|
|
263729
|
-
const sessionId = (0,
|
|
264090
|
+
const sessionId = (0, import_node_crypto80.randomUUID)();
|
|
263730
264091
|
const nowIso = (/* @__PURE__ */ new Date()).toISOString();
|
|
263731
264092
|
const binding = await registryStore.getBinding(agentId).catch(() => null);
|
|
263732
264093
|
await (await chatStoreFor(companyId)).createSession({
|
|
@@ -264393,6 +264754,16 @@ async function startServe(opts) {
|
|
|
264393
264754
|
delegationStores.set(id, store);
|
|
264394
264755
|
return store;
|
|
264395
264756
|
};
|
|
264757
|
+
const readChatFileBlob = async (companyId, ref2) => {
|
|
264758
|
+
const facts = await blobStoreFor(companyId);
|
|
264759
|
+
for (const cabinet of [assets, facts]) {
|
|
264760
|
+
try {
|
|
264761
|
+
return await cabinet.get(ref2);
|
|
264762
|
+
} catch {
|
|
264763
|
+
}
|
|
264764
|
+
}
|
|
264765
|
+
throw new Error("\u6587\u4EF6\u539F\u4EF6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u91CD\u8BD5\u6216\u91CD\u65B0\u4E0A\u4F20");
|
|
264766
|
+
};
|
|
264396
264767
|
const outputCopyScheduler = createOutputCopyScheduler({
|
|
264397
264768
|
putBlob: (bytes2) => assets.put(bytes2),
|
|
264398
264769
|
isDelegationChild: async (companyId, sessionId) => {
|
|
@@ -264666,6 +265037,41 @@ async function startServe(opts) {
|
|
|
264666
265037
|
const listCompanyMembers = (companyId) => controlPlaneStore.listMembers(companyId ?? defaultCompanyId);
|
|
264667
265038
|
let notificationLedgerWorker;
|
|
264668
265039
|
let notificationLedgerTimer;
|
|
265040
|
+
const sessionOutputsScan = async ({ chatSessionId, companyId }) => {
|
|
265041
|
+
const bridge = workdirBridge;
|
|
265042
|
+
if (!bridge) return null;
|
|
265043
|
+
const store = chatStoreRouter ? await chatStoreFor(companyId).catch(() => null) : chatSessionStore;
|
|
265044
|
+
const read = store?.readOutputFingerprints?.bind(store);
|
|
265045
|
+
const write = store?.writeOutputFingerprints?.bind(store);
|
|
265046
|
+
if (!read || !write) return null;
|
|
265047
|
+
const recorded = await store?.getSession(chatSessionId);
|
|
265048
|
+
const located = recorded?.runtimeId && recorded.runtimeKind ? { ok: true, loc: {
|
|
265049
|
+
nodeId: recorded.runtimeId,
|
|
265050
|
+
runtimeKind: recorded.runtimeKind,
|
|
265051
|
+
rtId: recorded.runtimeSessionId,
|
|
265052
|
+
workdirKey: `chat:${chatSessionId}`
|
|
265053
|
+
} } : await locateSessionWorkdir(delegationWorkdirLocator, { chatSessionId, ...companyId !== void 0 ? { companyId } : {} });
|
|
265054
|
+
if (located.ok && foreignNodeBlock(await nodeStore.getNode(located.loc.nodeId), companyId ?? defaultCompanyId)) return null;
|
|
265055
|
+
if (!located.ok) return null;
|
|
265056
|
+
const diff = await settleSessionOutputs({
|
|
265057
|
+
bridge,
|
|
265058
|
+
loc: located.loc,
|
|
265059
|
+
sessionId: chatSessionId,
|
|
265060
|
+
readFingerprints: read,
|
|
265061
|
+
writeFingerprints: write
|
|
265062
|
+
}).catch(() => null);
|
|
265063
|
+
if (diff && store) await outputCopyScheduler.schedule({
|
|
265064
|
+
store,
|
|
265065
|
+
bridge,
|
|
265066
|
+
loc: located.loc,
|
|
265067
|
+
chatSessionId,
|
|
265068
|
+
companyId,
|
|
265069
|
+
fingerprints: diff.fingerprints,
|
|
265070
|
+
scanIncomplete: diff.scanIncomplete
|
|
265071
|
+
});
|
|
265072
|
+
else await store?.writeFileIssues?.(chatSessionId, "save", [{ phase: "save", path: "outputs/", code: "SCAN_UNAVAILABLE", message: "\u539F\u8282\u70B9\u4EA7\u51FA\u76EE\u5F55\u8BFB\u53D6\u5931\u8D25\uFF0C\u672A\u80FD\u786E\u8BA4\u672C\u8F6E\u6587\u4EF6\u5DF2\u4FDD\u5B58" }]);
|
|
265073
|
+
return diff?.changed ?? null;
|
|
265074
|
+
};
|
|
264669
265075
|
const server = await startOasisServer({
|
|
264670
265076
|
deployTargets,
|
|
264671
265077
|
onInterventionDraftResolved: (e) => notificationLedgerWorker?.draftResolved(e.companyId ?? defaultCompanyId, e.draftId, { by: e.by, approved: e.approved }),
|
|
@@ -264771,7 +265177,7 @@ async function startServe(opts) {
|
|
|
264771
265177
|
}));
|
|
264772
265178
|
}
|
|
264773
265179
|
const limits = { wallClockMs: wallClockForKind("planner") };
|
|
264774
|
-
const artifactId = `artifact:planner:${(0,
|
|
265180
|
+
const artifactId = `artifact:planner:${(0, import_node_crypto80.randomUUID)()}`;
|
|
264775
265181
|
const handle = await chatRemoteAdapter.spawn({
|
|
264776
265182
|
actor: planner.id,
|
|
264777
265183
|
// companyId 同协调者:planner 用的就是默认公司的 actors 服务,漏签会让它一调公司域端点就 404。
|
|
@@ -265003,6 +265409,7 @@ async function startServe(opts) {
|
|
|
265003
265409
|
// (于是每一行的「大小」都空掉)。顺序与 `/api/blobs/:hash` 那条读路同源。
|
|
265004
265410
|
// 写回也落资产柜,与附件上传同一个柜,否则新旧两版会分居两处。
|
|
265005
265411
|
blobs: {
|
|
265412
|
+
get: (ref2) => readChatFileBlob(void 0, ref2),
|
|
265006
265413
|
meta: async (blobRef) => {
|
|
265007
265414
|
for (const cabinet of [assets, blobs]) {
|
|
265008
265415
|
try {
|
|
@@ -265021,6 +265428,7 @@ async function startServe(opts) {
|
|
|
265021
265428
|
resolveBlobs: async (cid) => {
|
|
265022
265429
|
const factCabinet = await blobStoreFor(cid);
|
|
265023
265430
|
return {
|
|
265431
|
+
get: (ref2) => readChatFileBlob(cid, ref2),
|
|
265024
265432
|
meta: async (blobRef) => {
|
|
265025
265433
|
for (const cabinet of [assets, factCabinet]) {
|
|
265026
265434
|
try {
|
|
@@ -265108,40 +265516,8 @@ async function startServe(opts) {
|
|
|
265108
265516
|
// 三个方法的组合规则住在 `createDelegationWorkdirPort`(`@oasis/server`)——评审
|
|
265109
265517
|
// wo:acfee725 blocker ② 回归防线:**serve.ts 与单测走同一处**,那样「装配层退回全局 binding」
|
|
265110
265518
|
// 这类事故在单测里就能被复现。绝不许在这里再写一份。
|
|
265111
|
-
|
|
265112
|
-
|
|
265113
|
-
*
|
|
265114
|
-
* 复用 `delegationWorkdirLocator`(与派发、回流、chat 域**同一个 binding resolver 实例**)——
|
|
265115
|
-
* 委派回程读的就是子会话的 `outputs/`,主会话这条只是把同一套读口用到了自己身上。
|
|
265116
|
-
*
|
|
265117
|
-
* 三处 fail-closed,都返回 `null`(= 这一轮没有产出卡),一处都不猜:
|
|
265118
|
-
* · 桥还没建好 / 会话没绑定 / 节点离线 → 拿不到工作区;
|
|
265119
|
-
* · store 没有指纹方法(老 store / 文件态装配)→ 没地方记「上一轮长什么样」,
|
|
265120
|
-
* 硬扫会把整个 `outputs/` 每轮都当成新增,一口气刷几十张卡;
|
|
265121
|
-
* · 解析不出公司 → **绝不回落默认公司**(否则会去别家公司的库里读写指纹)。
|
|
265122
|
-
*/
|
|
265123
|
-
sessionOutputsScan: async ({ chatSessionId, companyId }) => {
|
|
265124
|
-
const bridge = workdirBridge;
|
|
265125
|
-
if (!bridge) return null;
|
|
265126
|
-
const store = chatStoreRouter ? await chatStoreFor(companyId).catch(() => null) : chatSessionStore;
|
|
265127
|
-
const read = store?.readOutputFingerprints?.bind(store);
|
|
265128
|
-
const write = store?.writeOutputFingerprints?.bind(store);
|
|
265129
|
-
if (!read || !write) return null;
|
|
265130
|
-
const located = await locateSessionWorkdir(delegationWorkdirLocator, {
|
|
265131
|
-
chatSessionId,
|
|
265132
|
-
...companyId !== void 0 ? { companyId } : {}
|
|
265133
|
-
});
|
|
265134
|
-
if (!located.ok) return null;
|
|
265135
|
-
const diff = await settleSessionOutputs({
|
|
265136
|
-
bridge,
|
|
265137
|
-
loc: located.loc,
|
|
265138
|
-
sessionId: chatSessionId,
|
|
265139
|
-
readFingerprints: read,
|
|
265140
|
-
writeFingerprints: write
|
|
265141
|
-
}).catch(() => null);
|
|
265142
|
-
if (diff && store) void outputCopyScheduler.schedule({ store, bridge, loc: located.loc, chatSessionId, companyId, fingerprints: diff.fingerprints });
|
|
265143
|
-
return diff?.changed ?? null;
|
|
265144
|
-
},
|
|
265519
|
+
// 会话产出扫描:实现见上方 `sessionOutputsScan`。serve 重启前后的恢复收尾用的是同一个函数。
|
|
265520
|
+
sessionOutputsScan,
|
|
265145
265521
|
delegationWorkdir: createDelegationWorkdirPort({
|
|
265146
265522
|
locator: delegationWorkdirLocator,
|
|
265147
265523
|
// 桥在 hub 建好后(本函数尾部)才赋值 → getter 每次调用时读最新值;早于此处的构造时 `workdirBridge`
|
|
@@ -265673,10 +266049,10 @@ async function startServe(opts) {
|
|
|
265673
266049
|
if (isDeletedActor(dispatchTarget)) {
|
|
265674
266050
|
throw new ApiError(409, ACTOR_DELETED_ERROR_CODE, ACTOR_DELETED_CHAT_MESSAGE);
|
|
265675
266051
|
}
|
|
265676
|
-
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid2(`chat-runtime:${requestDispatchId}`) : (0,
|
|
266052
|
+
const runtimeSessionId = sessionId ?? (requestDispatchId ? deterministicUuid2(`chat-runtime:${requestDispatchId}`) : (0, import_node_crypto80.randomUUID)());
|
|
265677
266053
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
265678
|
-
const traceRunId = requestDispatchId ? `chat-run:${deterministicUuid2(`chat-trace:${requestDispatchId}`)}` : `chat-run:${(0,
|
|
265679
|
-
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid2(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0,
|
|
266054
|
+
const traceRunId = requestDispatchId ? `chat-run:${deterministicUuid2(`chat-trace:${requestDispatchId}`)}` : `chat-run:${(0, import_node_crypto80.randomUUID)()}`;
|
|
266055
|
+
const artifactId = requestDispatchId ? `artifact:chat:${deterministicUuid2(`chat-artifact:${requestDispatchId}`)}` : `artifact:chat:${(0, import_node_crypto80.randomUUID)()}`;
|
|
265680
266056
|
let stableDispatch = requestDispatchId ? await resolveStableChatDispatch({ store: await traceStoreFor(runCompanyId), runId: traceRunId }) : null;
|
|
265681
266057
|
if (stableDispatch && !stableDispatch.shouldDispatch) {
|
|
265682
266058
|
return {
|
|
@@ -265740,10 +266116,7 @@ async function startServe(opts) {
|
|
|
265740
266116
|
}
|
|
265741
266117
|
}
|
|
265742
266118
|
}
|
|
265743
|
-
const turnChatStore = chatSessionId ? await chatStoreFor(runCompanyId)
|
|
265744
|
-
console.warn(`[chat] \u53D6\u516C\u53F8 ${runCompanyId} \u7684\u4F1A\u8BDD\u5B58\u50A8\u5931\u8D25\uFF08\u672C\u8F6E\u6309\u65E0\u4F1A\u8BDD\u8BB0\u5F55\u5904\u7406\uFF09: ${String(err)}`);
|
|
265745
|
-
return null;
|
|
265746
|
-
}) : null;
|
|
266119
|
+
const turnChatStore = chatSessionId ? await chatStoreFor(runCompanyId) : null;
|
|
265747
266120
|
const analyzedRunId = chatSessionId ? (await turnChatStore?.getSession(chatSessionId).catch(() => null))?.analyzedRunId ?? void 0 : void 0;
|
|
265748
266121
|
const actorConfigVersion = await actorService.latestConfig(actorId).then((c) => c?.version ?? null).catch(() => null);
|
|
265749
266122
|
const candidateTraceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -265774,6 +266147,22 @@ async function startServe(opts) {
|
|
|
265774
266147
|
...analyzedRunId ? { analyzedRunId } : {}
|
|
265775
266148
|
}
|
|
265776
266149
|
});
|
|
266150
|
+
const priorChatSession = chatSessionId ? await turnChatStore?.getSession(chatSessionId) : null;
|
|
266151
|
+
let freshChatWorkdir = chatSessionId ? chatNodeChanged(
|
|
266152
|
+
{ nodeId: priorChatSession?.runtimeId, runtimeKind: priorChatSession?.runtimeKind },
|
|
266153
|
+
{ nodeId: binding.nodeId, runtimeKind: binding.runtimeKind }
|
|
266154
|
+
) : false;
|
|
266155
|
+
let restore = !isolatedKnowledgeTurn && chatSessionId && turnChatStore ? await prepareSessionFileRestore({
|
|
266156
|
+
store: turnChatStore,
|
|
266157
|
+
sessionId: chatSessionId,
|
|
266158
|
+
readBlob: (ref2) => readChatFileBlob(runCompanyId, ref2),
|
|
266159
|
+
attachments,
|
|
266160
|
+
fresh: freshChatWorkdir,
|
|
266161
|
+
supportsFileRestore: node2.meta.supportsFileRestore === true
|
|
266162
|
+
}) : void 0;
|
|
266163
|
+
const usedRel = /* @__PURE__ */ new Set();
|
|
266164
|
+
const preparedAttachments = await buildChatAttachmentFiles(attachments, (ref2) => readChatFileBlob(runCompanyId, ref2), usedRel);
|
|
266165
|
+
if (preparedAttachments.missing.length) throw new ApiError(409, "CHAT_FILE_RESTORE_FAILED", preparedAttachments.missing.map((m2) => `${m2.name}\uFF1A${m2.error}`).join("\uFF1B"));
|
|
265777
266166
|
const stableTraceWasPresent = Boolean(stableDispatch);
|
|
265778
266167
|
if (requestDispatchId && !stableDispatch) {
|
|
265779
266168
|
stableDispatch = await resolveStableChatDispatch({
|
|
@@ -265796,13 +266185,20 @@ async function startServe(opts) {
|
|
|
265796
266185
|
binding = { actorId, ...stableDispatch.target, status: "active" };
|
|
265797
266186
|
node2 = await requireDispatchNode(binding);
|
|
265798
266187
|
requireNodeConnectors();
|
|
266188
|
+
freshChatWorkdir = chatNodeChanged(
|
|
266189
|
+
{ nodeId: priorChatSession?.runtimeId, runtimeKind: priorChatSession?.runtimeKind },
|
|
266190
|
+
{ nodeId: binding.nodeId, runtimeKind: binding.runtimeKind }
|
|
266191
|
+
);
|
|
266192
|
+
restore = !isolatedKnowledgeTurn && chatSessionId && turnChatStore ? await prepareSessionFileRestore({
|
|
266193
|
+
store: turnChatStore,
|
|
266194
|
+
sessionId: chatSessionId,
|
|
266195
|
+
readBlob: (ref2) => readChatFileBlob(runCompanyId, ref2),
|
|
266196
|
+
attachments,
|
|
266197
|
+
fresh: freshChatWorkdir,
|
|
266198
|
+
supportsFileRestore: node2.meta.supportsFileRestore === true
|
|
266199
|
+
}) : void 0;
|
|
265799
266200
|
}
|
|
265800
266201
|
}
|
|
265801
|
-
const priorChatSession = chatSessionId ? await turnChatStore?.getSession(chatSessionId).catch(() => null) : null;
|
|
265802
|
-
const freshChatWorkdir = chatSessionId ? chatNodeChanged(
|
|
265803
|
-
{ nodeId: priorChatSession?.runtimeId, runtimeKind: priorChatSession?.runtimeKind },
|
|
265804
|
-
{ nodeId: binding.nodeId, runtimeKind: binding.runtimeKind }
|
|
265805
|
-
) : false;
|
|
265806
266202
|
const existingTrace = stableDispatch?.run ?? null;
|
|
265807
266203
|
const existingEvents = existingTrace ? await (await traceStoreFor(runCompanyId)).listEvents(traceRunId, {}).catch(() => []) : [];
|
|
265808
266204
|
const traceStartedAt = existingTrace?.startedAt ?? candidateTraceStartedAt;
|
|
@@ -265848,18 +266244,13 @@ async function startServe(opts) {
|
|
|
265848
266244
|
const chatResolvedModel = sessionModelOverride ?? actorCtx?.config?.model ?? void 0;
|
|
265849
266245
|
const chatModel = chatResolvedModel ?? await registryStore.getRuntimeConfig(`runtime:${binding.nodeId}:${binding.runtimeKind}`).then((c) => c?.model).catch(() => void 0) ?? void 0;
|
|
265850
266246
|
const chatModelSource = sessionModelOverride ? "session_override" : chatResolvedModel ? "actor_config" : chatModel ? "runtime_default" : null;
|
|
265851
|
-
const
|
|
265852
|
-
const preparedAttachments = await buildChatAttachmentFiles(attachments, (ref2) => assets.get(ref2), usedRel);
|
|
265853
|
-
for (const miss of preparedAttachments.missing) {
|
|
265854
|
-
console.warn(`[chat] \u9644\u4EF6 blob ${miss.blobRef} \u8BFB\u53D6\u5931\u8D25: ${miss.error}`);
|
|
265855
|
-
}
|
|
265856
|
-
const attachmentFiles = { ...preparedAttachments.files };
|
|
266247
|
+
const attachmentFiles = { ...preparedAttachments.files, ...restore ? { "SESSION_FILES.md": restore.index } : {} };
|
|
265857
266248
|
const attachmentBinary = { ...preparedAttachments.binaryFiles };
|
|
265858
266249
|
const attachmentPaths = [...preparedAttachments.paths];
|
|
265859
266250
|
let turnProject = priorChatSession ? { state: "none" } : { state: "unknown" };
|
|
265860
266251
|
if (priorChatSession?.projectId) {
|
|
265861
266252
|
const projectId2 = priorChatSession.projectId;
|
|
265862
|
-
const projectBundle = await projectStateFor(runCompanyId).then((projects) => buildChatProjectBundle(projectId2, projects, (blobId) =>
|
|
266253
|
+
const projectBundle = await projectStateFor(runCompanyId).then((projects) => buildChatProjectBundle(projectId2, projects, (blobId) => readChatFileBlob(runCompanyId, blobId))).catch((err) => {
|
|
265863
266254
|
console.warn(`[chat] \u8BFB\u9879\u76EE ${projectId2} \u5931\u8D25\uFF08\u672C\u8F6E\u4E0D\u5199\u9879\u76EE\u6BB5\uFF09: ${String(err)}`);
|
|
265864
266255
|
return void 0;
|
|
265865
266256
|
});
|
|
@@ -265885,7 +266276,7 @@ async function startServe(opts) {
|
|
|
265885
266276
|
...actorCtx?.config?.prompt ? { personaPrompt: actorCtx.config.prompt } : {},
|
|
265886
266277
|
...extraSystemPrompt ? { expertSystemPrompt: extraSystemPrompt } : {}
|
|
265887
266278
|
});
|
|
265888
|
-
const taskHeader = chatPrompts.taskHeaderLines;
|
|
266279
|
+
const taskHeader = [...chatPrompts.taskHeaderLines, ...restore ? ["\u672C\u4F1A\u8BDD\u7684\u5386\u53F2\u6587\u4EF6\u4E0E\u5DF2\u4FDD\u5B58\u4EA7\u51FA\u89C1 SESSION_FILES.md\uFF0C\u53EF\u6309\u5217\u51FA\u7684\u76F8\u5BF9\u8DEF\u5F84\u8BFB\u53D6\u3002"] : []];
|
|
265889
266280
|
const chatMemoryEnabled = !isolatedKnowledgeTurn && actorCtx?.memoryEnabled !== false;
|
|
265890
266281
|
const chatMemorySvc = chatMemoryEnabled ? await actorMemoryFor(runCompanyId).catch(() => void 0) : void 0;
|
|
265891
266282
|
const chatMemoryLines = chatMemorySvc ? await chatMemorySvc.list({ actorId }, { scope: "all", keywords: ngramQueryTerms([message]), limit: MEMORY_INJECT_MAX, offset: 0 }).then((out) => [...memoryIndexLines(out.items), ...memoryHowToLines()]).catch(() => []) : [];
|
|
@@ -265930,7 +266321,7 @@ async function startServe(opts) {
|
|
|
265930
266321
|
actor: actorId,
|
|
265931
266322
|
actorToken: issueSessionToken(actorId, { artifactId, action: "chat", limits, binding, sessionId: runtimeSessionId, companyId: runCompanyId, ...requestDispatchId ? { dispatchId: requestDispatchId } : {}, ...chatSessionId !== void 0 ? { chatSessionId } : {} }),
|
|
265932
266323
|
artifactId,
|
|
265933
|
-
bundle: { files, ...Object.keys(attachmentBinary).length ? { binaryFiles: attachmentBinary } : {} },
|
|
266324
|
+
bundle: { files, ...Object.keys(attachmentBinary).length ? { binaryFiles: attachmentBinary } : {}, ...restore ? { restoreFiles: restore.restoreFiles } : {} },
|
|
265934
266325
|
// 人设在最前,固定规则接在它后面:助理那侧是分流正文(§6.5.3,只有普通脑暴那一支有),
|
|
265935
266326
|
// 专家那侧是 `EXPERT_DELEGATION_SYSTEM_PROMPT`(§6.5.7)。**三者都走 systemPrompt**——
|
|
265936
266327
|
// 放进 TASK.md 会随 `--resume` 每轮重复、O(N) 累积(§6.1.5)。
|
|
@@ -266063,10 +266454,11 @@ async function startServe(opts) {
|
|
|
266063
266454
|
}
|
|
266064
266455
|
});
|
|
266065
266456
|
const failed = !isHealthySessionExit(info);
|
|
266066
|
-
|
|
266067
|
-
|
|
266068
|
-
|
|
266069
|
-
|
|
266457
|
+
const recordRestore = turnChatStore && chatSessionId ? recordSessionFileRestoreExit(turnChatStore, chatSessionId, info) : Promise.resolve();
|
|
266458
|
+
void recordRestore.then(() => {
|
|
266459
|
+
if (!failed) resolve10();
|
|
266460
|
+
else reject(buildChatExitError(info));
|
|
266461
|
+
}, (error2) => reject(error2));
|
|
266070
266462
|
});
|
|
266071
266463
|
});
|
|
266072
266464
|
return {
|
|
@@ -266255,6 +266647,8 @@ async function startServe(opts) {
|
|
|
266255
266647
|
onCompanyError: chatRecoveryCompanyWarn(opts2.label),
|
|
266256
266648
|
// 重挂的那一轮收口时当场外报,与清扫拍同一个接收方(见 `notifyChatTurnSettled`)。
|
|
266257
266649
|
onTurnSettled: (info) => notifyChatTurnSettled(info),
|
|
266650
|
+
// 重挂 / 已收口两条路收尾时出产出卡(公司由扇出层按行绑)。
|
|
266651
|
+
sessionOutputsScan,
|
|
266258
266652
|
liveChat,
|
|
266259
266653
|
trace: runRoutedTrace,
|
|
266260
266654
|
traceHealth,
|
|
@@ -266410,6 +266804,7 @@ async function startServe(opts) {
|
|
|
266410
266804
|
listCompanies: chatRecoveryCompanies,
|
|
266411
266805
|
storesFor: chatRecoveryFor,
|
|
266412
266806
|
onCompanyError: chatRecoveryCompanyWarn("exit \u5BF9\u8D26"),
|
|
266807
|
+
sessionOutputsScan,
|
|
266413
266808
|
drainStash: (id) => chatRemoteAdapter?.drainStash(id) ?? { frames: [] },
|
|
266414
266809
|
log: (m2) => console.log(m2)
|
|
266415
266810
|
});
|
|
@@ -266478,6 +266873,7 @@ async function startServe(opts) {
|
|
|
266478
266873
|
listCompanies: chatRecoveryCompanies,
|
|
266479
266874
|
storesFor: chatRecoveryFor,
|
|
266480
266875
|
onCompanyError: chatRecoveryCompanyWarn("chat-sweep"),
|
|
266876
|
+
sessionOutputsScan,
|
|
266481
266877
|
getRun: (id) => fanOutTrace.getRun(id),
|
|
266482
266878
|
ownedRunId: (sid) => liveChat.runFor(sid),
|
|
266483
266879
|
now: Date.now(),
|
|
@@ -266510,7 +266906,12 @@ async function startServe(opts) {
|
|
|
266510
266906
|
storesFor: async (companyId) => {
|
|
266511
266907
|
const turns = await chatTurnsFor(companyId);
|
|
266512
266908
|
const messages = await chatStoreFor(companyId);
|
|
266513
|
-
return {
|
|
266909
|
+
return {
|
|
266910
|
+
turns,
|
|
266911
|
+
...assistantRowRecovery(messages, {
|
|
266912
|
+
outputsPartFor: (sid) => outputsPartProvider(sessionOutputsScan, sid, companyId)
|
|
266913
|
+
})
|
|
266914
|
+
};
|
|
266514
266915
|
},
|
|
266515
266916
|
getRun: (id) => fanOutTrace.getRun(id),
|
|
266516
266917
|
// 本进程在飞的轮不动——它自己的收尾路径会写终态(liveChat 只认人工/渠道那条,自动化轮
|
|
@@ -266803,7 +267204,7 @@ async function startServe(opts) {
|
|
|
266803
267204
|
console.log(`[new-engine] dispatchWork ${workId} \u662F human work\u2014\u2014\u4E0D\u6D3E runtime\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406`);
|
|
266804
267205
|
return;
|
|
266805
267206
|
}
|
|
266806
|
-
const ledgerId = `dispatch:${(0,
|
|
267207
|
+
const ledgerId = `dispatch:${(0, import_node_crypto80.randomUUID)()}`;
|
|
266807
267208
|
try {
|
|
266808
267209
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
266809
267210
|
id: ledgerId,
|
|
@@ -266888,7 +267289,7 @@ async function startServe(opts) {
|
|
|
266888
267289
|
const kernelModel = newKernel.model;
|
|
266889
267290
|
const art = kernelModel.artifacts.get(nodeId);
|
|
266890
267291
|
const revWid = art?.workspace ?? "";
|
|
266891
|
-
const ledgerId = `dispatch:${(0,
|
|
267292
|
+
const ledgerId = `dispatch:${(0, import_node_crypto80.randomUUID)()}`;
|
|
266892
267293
|
try {
|
|
266893
267294
|
await (await dispatchLedgerFor(companyId)).insertOpen({
|
|
266894
267295
|
id: ledgerId,
|
|
@@ -267266,7 +267667,7 @@ async function startServe(opts) {
|
|
|
267266
267667
|
resolveSupplementalContext: server.knowledgeGovernance ? async ({ actorId, artifactId, workOrderId, action, part, runtimeKind, taskMarkdown }) => {
|
|
267267
267668
|
try {
|
|
267268
267669
|
const governance = server.knowledgeGovernance;
|
|
267269
|
-
const taskFingerprint = (0,
|
|
267670
|
+
const taskFingerprint = (0, import_node_crypto80.createHash)("sha256").update(JSON.stringify({ artifactId, workOrderId, action, part: part ?? null, taskMarkdown })).digest("hex");
|
|
267270
267671
|
const requestContext = {
|
|
267271
267672
|
organizationId: companyId,
|
|
267272
267673
|
actorId,
|
|
@@ -268904,7 +269305,9 @@ async function runSession(dispatchId, job, deps) {
|
|
|
268904
269305
|
deps.sink.stream({ type: "session_live_event", dispatchId, event });
|
|
268905
269306
|
normalizer.onLiveEvent(event);
|
|
268906
269307
|
});
|
|
269308
|
+
let restoreFailedBeforeStart = false;
|
|
268907
269309
|
handle.onExit((info) => {
|
|
269310
|
+
if (info.fileRestoreError) restoreFailedBeforeStart = true;
|
|
268908
269311
|
normalizer.turnFinished(isHealthySessionExit(info) ? "completed" : "failed");
|
|
268909
269312
|
log2("[node-cli]", ` \u25A0 session_exited id=${handle.id} code=${info.code ?? "killed"} total=${Date.now() - t0}ms`);
|
|
268910
269313
|
if (info.transcriptRef) log2("[node-cli]", ` transcript: ${info.transcriptRef}`);
|
|
@@ -268914,7 +269317,7 @@ async function runSession(dispatchId, job, deps) {
|
|
|
268914
269317
|
if (cancelledBeforeStart) {
|
|
268915
269318
|
log2("[node-cli]", ` dispatch ${dispatchId} \u5728 setup \u671F\u95F4\u5DF2\u88AB fencing\uFF0Cspawn \u540E\u7ACB\u5373 kill`);
|
|
268916
269319
|
await handle.kill();
|
|
268917
|
-
} else {
|
|
269320
|
+
} else if (!restoreFailedBeforeStart) {
|
|
268918
269321
|
log2("[node-cli]", ` \u2192 session_started id=${handle.id} setup=${Date.now() - t0}ms`);
|
|
268919
269322
|
deps.sink.keyFrame({ type: "session_started", dispatchId, sessionId: handle.id, jobArtifactId: job.artifactId });
|
|
268920
269323
|
}
|
|
@@ -268922,7 +269325,12 @@ async function runSession(dispatchId, job, deps) {
|
|
|
268922
269325
|
deps.onFailure?.();
|
|
268923
269326
|
log2("[node-cli]", ` spawn failed: ${err}`);
|
|
268924
269327
|
const errorMessage = String(err?.stack ?? err).slice(0, 8e3);
|
|
268925
|
-
deps.sink.keyFrame({ type: "session_exited", dispatchId, sessionId: "spawn-failed", info: {
|
|
269328
|
+
deps.sink.keyFrame({ type: "session_exited", dispatchId, sessionId: "spawn-failed", info: {
|
|
269329
|
+
code: null,
|
|
269330
|
+
reason: "error",
|
|
269331
|
+
errorMessage,
|
|
269332
|
+
...err instanceof BundleRestoreError ? { fileRestoreError: { path: err.filePath, message: err.message } } : {}
|
|
269333
|
+
} });
|
|
268926
269334
|
}
|
|
268927
269335
|
}
|
|
268928
269336
|
|
|
@@ -269213,8 +269621,9 @@ var SessionProcessState = class {
|
|
|
269213
269621
|
|
|
269214
269622
|
// ../cli/src/daemon/ws-client.ts
|
|
269215
269623
|
init_wrapper();
|
|
269624
|
+
init_src();
|
|
269216
269625
|
var import_node_os9 = require("node:os");
|
|
269217
|
-
var
|
|
269626
|
+
var import_node_crypto81 = require("node:crypto");
|
|
269218
269627
|
init_src8();
|
|
269219
269628
|
init_src6();
|
|
269220
269629
|
|
|
@@ -269495,10 +269904,15 @@ async function handleWorkdirRead(req) {
|
|
|
269495
269904
|
const fresh = await fh.stat().catch(() => null);
|
|
269496
269905
|
return { ok: false, code: "TOO_LARGE", size: Math.max(fresh?.size ?? 0, bytesRead), absPath: real };
|
|
269497
269906
|
}
|
|
269907
|
+
const afterRead = await fh.stat();
|
|
269908
|
+
if (afterRead.size !== st.size || afterRead.mtimeMs !== st.mtimeMs) {
|
|
269909
|
+
return { ok: false, code: "INTERNAL", message: "\u6587\u4EF6\u5728\u8BFB\u53D6\u671F\u95F4\u53D1\u751F\u53D8\u5316" };
|
|
269910
|
+
}
|
|
269498
269911
|
const bytes2 = buf.subarray(0, bytesRead);
|
|
269499
269912
|
return {
|
|
269500
269913
|
ok: true,
|
|
269501
269914
|
contentBase64: bytes2.toString("base64"),
|
|
269915
|
+
mtime: st.mtime.toISOString(),
|
|
269502
269916
|
contentType: contentTypeFor(real, bytes2),
|
|
269503
269917
|
size: bytes2.length
|
|
269504
269918
|
// 以实际读到的字节数为准,不用任何可能已过时的 stat size
|
|
@@ -269751,6 +270165,7 @@ var DaemonWsClient = class {
|
|
|
269751
270165
|
connect() {
|
|
269752
270166
|
if (this.stopped) return;
|
|
269753
270167
|
const ws = new import_websocket.default(this.serverUrl, {
|
|
270168
|
+
maxPayload: 4 * Math.ceil(FILE_CONTENT_MAX_BYTES / 3) + 64 * 1024,
|
|
269754
270169
|
headers: {
|
|
269755
270170
|
"x-daemon-id": this.daemonId,
|
|
269756
270171
|
// 经公网网关时鉴权靠它(对齐 multica:Authorization 头反代天然透传);内网直连可空
|
|
@@ -269986,7 +270401,7 @@ var DaemonWsClient = class {
|
|
|
269986
270401
|
*/
|
|
269987
270402
|
async queryArtifactStates(artifactIds, timeoutMs = 15e3) {
|
|
269988
270403
|
if (artifactIds.length === 0) return {};
|
|
269989
|
-
const requestId = (0,
|
|
270404
|
+
const requestId = (0, import_node_crypto81.randomUUID)();
|
|
269990
270405
|
return new Promise((resolve10, reject) => {
|
|
269991
270406
|
const timer = setTimeout(() => {
|
|
269992
270407
|
this.gcPending.delete(requestId);
|
|
@@ -270128,6 +270543,7 @@ var DaemonWsClient = class {
|
|
|
270128
270543
|
supportsNormalizedEvents: true,
|
|
270129
270544
|
// ADR 0554:本 daemon 认 `workdir_walk`。恒 true——handler 随包发,装了这版就一定有。
|
|
270130
270545
|
supportsWorkdirWalk: true,
|
|
270546
|
+
supportsFileRestore: true,
|
|
270131
270547
|
...activeSessions.length > 0 ? { activeSessions } : {},
|
|
270132
270548
|
// 始终带字段(空数组也带)作为新协议能力标志;服务端仅对支持该字段的节点做缺席确认。
|
|
270133
270549
|
pendingDispatchIds: [...this.pendingDispatchIds]
|
|
@@ -270388,7 +270804,7 @@ function forwardSignal(child, sig, killGroup = (pgid, signal) => {
|
|
|
270388
270804
|
// ../cli/src/daemon/machine-id.ts
|
|
270389
270805
|
var import_node_child_process21 = require("node:child_process");
|
|
270390
270806
|
var import_node_fs22 = require("node:fs");
|
|
270391
|
-
var
|
|
270807
|
+
var import_node_crypto82 = require("node:crypto");
|
|
270392
270808
|
var import_node_os12 = require("node:os");
|
|
270393
270809
|
function linuxMachineId() {
|
|
270394
270810
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
@@ -270454,7 +270870,7 @@ var defaultSources = {
|
|
|
270454
270870
|
function resolveNodeId(sources = {}) {
|
|
270455
270871
|
const s2 = { ...defaultSources, ...sources };
|
|
270456
270872
|
const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
|
|
270457
|
-
const digest = (0,
|
|
270873
|
+
const digest = (0, import_node_crypto82.createHash)("sha256").update(material).digest("hex").slice(0, 12);
|
|
270458
270874
|
return `node-${digest}`;
|
|
270459
270875
|
}
|
|
270460
270876
|
|
|
@@ -271465,7 +271881,7 @@ var COMMAND_DECLS = {
|
|
|
271465
271881
|
flags: [
|
|
271466
271882
|
{ name: "name", desc: "\u9879\u76EE\u540D", required: true },
|
|
271467
271883
|
{ name: "goal", desc: "\u9879\u76EE\u76EE\u6807" },
|
|
271468
|
-
{ name: "slug", desc: "
|
|
271884
|
+
{ name: "slug", desc: "\u81EA\u5B9A\u4E49\u9879\u76EE id\uFF08\u53EF\u9009\uFF09\u3002\u4E0D\u7ED9\u5219\u968F\u673A\u751F\u6210 proj_xxxxxxxx\uFF1B\u7ED9\u4E86\u4E14\u8BE5 id \u5DF2\u5B58\u5728\uFF0C\u8FD4\u56DE\u7684\u662F\u5DF2\u6709\u9879\u76EE\uFF08\u4F1A\u63D0\u793A\uFF09" },
|
|
271469
271885
|
{ name: "members", desc: "\u6210\u5458 JSON \u6570\u7EC4" }
|
|
271470
271886
|
],
|
|
271471
271887
|
examples: ['oasis project create --name "My Project" --goal "\u6784\u5EFA\u534F\u4F5C\u5E73\u53F0"']
|
|
@@ -272225,13 +272641,13 @@ function ownFlagsFromDecl(command) {
|
|
|
272225
272641
|
}
|
|
272226
272642
|
|
|
272227
272643
|
// ../cli/src/connector-effect-runner.ts
|
|
272228
|
-
var
|
|
272644
|
+
var import_node_crypto83 = require("node:crypto");
|
|
272229
272645
|
var import_node_child_process22 = require("node:child_process");
|
|
272230
272646
|
init_src8();
|
|
272231
272647
|
function stableKey(effect) {
|
|
272232
272648
|
const keyFields = Object.fromEntries(Object.entries(effect.keyFields).sort(([a], [b2]) => a.localeCompare(b2)));
|
|
272233
272649
|
const canonical = JSON.stringify({ kind: effect.kind, target: effect.target, keyFields });
|
|
272234
|
-
return `sha256:${(0,
|
|
272650
|
+
return `sha256:${(0, import_node_crypto83.createHash)("sha256").update(canonical).digest("hex")}`;
|
|
272235
272651
|
}
|
|
272236
272652
|
async function runConnectorEffect(connector, toolArgs, deps) {
|
|
272237
272653
|
const effect = connector.describeExternalEffect?.(toolArgs) ?? null;
|
|
@@ -272467,7 +272883,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
272467
272883
|
const timeoutMs = resolveAuthWaitMs();
|
|
272468
272884
|
const controller = new AbortController();
|
|
272469
272885
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
272470
|
-
const waiterId = (0,
|
|
272886
|
+
const waiterId = (0, import_node_crypto84.randomUUID)();
|
|
272471
272887
|
process.stderr.write(
|
|
272472
272888
|
`\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
|
|
272473
272889
|
`
|
|
@@ -272890,7 +273306,7 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
272890
273306
|
const store = createNodeTokenStore(path35.join(dir, "node-tokens.json"));
|
|
272891
273307
|
const sub = positional[0];
|
|
272892
273308
|
if (sub === "issue") {
|
|
272893
|
-
const id = flags.get("id") ?? `node-${(0,
|
|
273309
|
+
const id = flags.get("id") ?? `node-${(0, import_node_crypto84.randomUUID)()}`;
|
|
272894
273310
|
const token2 = store.issue(id);
|
|
272895
273311
|
println(token2);
|
|
272896
273312
|
process.stderr.write(
|
|
@@ -273914,7 +274330,8 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
273914
274330
|
const name = need(flags, "name").trim();
|
|
273915
274331
|
if (!name) throw new Error("\u9879\u76EE\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A");
|
|
273916
274332
|
const goal = flags.get("goal")?.trim();
|
|
273917
|
-
const
|
|
274333
|
+
const slug6 = flags.get("slug");
|
|
274334
|
+
const id = slug6 !== void 0 ? projectSlug(slug6) : projectIdFromUuid((0, import_node_crypto84.randomUUID)());
|
|
273918
274335
|
const result = await api.request("POST", "/api/projects", {
|
|
273919
274336
|
...id ? { id } : {},
|
|
273920
274337
|
name,
|
|
@@ -273922,6 +274339,9 @@ ${t.ref} ${t.name} [\u5267\u672C=${t.playbookRef}]`);
|
|
|
273922
274339
|
...flags.has("members") ? { member_ids: parseStringArrayFlag(flags.get("members"), "members") } : {}
|
|
273923
274340
|
});
|
|
273924
274341
|
println(JSON.stringify(result, null, 2));
|
|
274342
|
+
if (typeof result?.name === "string" && result.name !== name) {
|
|
274343
|
+
println(`\u26A0\uFE0F \u9879\u76EE id\u300C${result.project_id ?? id}\u300D\u5DF2\u88AB\u300C${result.name}\u300D\u5360\u7528\uFF0C\u4E0A\u9762\u8FD4\u56DE\u7684\u662F\u90A3\u4E2A\u5DF2\u6709\u9879\u76EE\uFF0C\u6CA1\u6709\u65B0\u5EFA\u3002\u6362\u4E00\u4E2A --slug \u6216\u53BB\u6389 --slug \u91CD\u8BD5\u3002`);
|
|
274344
|
+
}
|
|
273925
274345
|
break;
|
|
273926
274346
|
}
|
|
273927
274347
|
if (positional[0] === "member") {
|
|
@@ -275903,13 +276323,13 @@ var LEGACY_SYSTEMD_UNIT = "oasis-node.service";
|
|
|
275903
276323
|
var LEGACY_LAUNCHD_LABEL = "com.oasis.node";
|
|
275904
276324
|
|
|
275905
276325
|
// src/install.ts
|
|
275906
|
-
var
|
|
276326
|
+
var import_node_crypto85 = require("node:crypto");
|
|
275907
276327
|
var fs44 = __toESM(require("node:fs"));
|
|
275908
276328
|
var path39 = __toESM(require("node:path"));
|
|
275909
276329
|
function versionLabel(sourceFile, pkgVersion, npmPrefixDir, pkgName = LEGACY_PKG_NAME) {
|
|
275910
276330
|
const tag = pkgName === LEGACY_PKG_NAME ? "" : `+pkg.${pkgName.replace(/[^A-Za-z0-9-]/g, "-")}`;
|
|
275911
276331
|
if (isFromNpmPrefix(sourceFile, npmPrefixDir)) return `${pkgVersion}${tag}`;
|
|
275912
|
-
const digest = (0,
|
|
276332
|
+
const digest = (0, import_node_crypto85.createHash)("sha256").update(fs44.readFileSync(sourceFile)).digest("hex").slice(0, 8);
|
|
275913
276333
|
return tag ? `${pkgVersion}${tag}.local.${digest}` : `${pkgVersion}+local.${digest}`;
|
|
275914
276334
|
}
|
|
275915
276335
|
function isFromNpmPrefix(sourceFile, npmPrefixDir) {
|
|
@@ -276032,7 +276452,7 @@ function shimScript() {
|
|
|
276032
276452
|
}
|
|
276033
276453
|
|
|
276034
276454
|
// src/index.ts
|
|
276035
|
-
var PKG_VERSION = true ? "2.2.
|
|
276455
|
+
var PKG_VERSION = true ? "2.2.36" : "dev";
|
|
276036
276456
|
var LOCAL_BIN = localBin();
|
|
276037
276457
|
var NPM_PREFIX = npmPrefix();
|
|
276038
276458
|
var INSTANCE = DEFAULT_INSTANCE;
|
|
@@ -276317,7 +276737,7 @@ function newInstanceName() {
|
|
|
276317
276737
|
const existing = new Set(listInstances());
|
|
276318
276738
|
if (!existing.has(DEFAULT_INSTANCE)) return DEFAULT_INSTANCE;
|
|
276319
276739
|
for (; ; ) {
|
|
276320
|
-
const n = `inst-${(0,
|
|
276740
|
+
const n = `inst-${(0, import_node_crypto86.randomBytes)(3).toString("hex")}`;
|
|
276321
276741
|
if (!existing.has(n)) return n;
|
|
276322
276742
|
}
|
|
276323
276743
|
}
|