oasis_test 0.1.87 → 0.1.89
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 +927 -250
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2488,6 +2488,24 @@ var init_registry = __esm({
|
|
|
2488
2488
|
}
|
|
2489
2489
|
});
|
|
2490
2490
|
|
|
2491
|
+
// ../contract/src/credential-ref.ts
|
|
2492
|
+
function makeVarRef(key) {
|
|
2493
|
+
return `${VAR_REF_PREFIX}${key}`;
|
|
2494
|
+
}
|
|
2495
|
+
function parseVarRef(s2) {
|
|
2496
|
+
if (!s2.startsWith(VAR_REF_PREFIX)) return null;
|
|
2497
|
+
const key = s2.slice(VAR_REF_PREFIX.length);
|
|
2498
|
+
if (key.length === 0 || /[\s/]/.test(key)) return null;
|
|
2499
|
+
return key;
|
|
2500
|
+
}
|
|
2501
|
+
var VAR_REF_PREFIX;
|
|
2502
|
+
var init_credential_ref = __esm({
|
|
2503
|
+
"../contract/src/credential-ref.ts"() {
|
|
2504
|
+
"use strict";
|
|
2505
|
+
VAR_REF_PREFIX = "oasis://var/";
|
|
2506
|
+
}
|
|
2507
|
+
});
|
|
2508
|
+
|
|
2491
2509
|
// ../contract/src/views.ts
|
|
2492
2510
|
var init_views = __esm({
|
|
2493
2511
|
"../contract/src/views.ts"() {
|
|
@@ -2565,6 +2583,7 @@ var init_src = __esm({
|
|
|
2565
2583
|
init_runtime();
|
|
2566
2584
|
init_daemon_protocol();
|
|
2567
2585
|
init_registry();
|
|
2586
|
+
init_credential_ref();
|
|
2568
2587
|
init_views();
|
|
2569
2588
|
init_telemetry();
|
|
2570
2589
|
init_trace();
|
|
@@ -6887,7 +6906,7 @@ var init_dispatcher = __esm({
|
|
|
6887
6906
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
6888
6907
|
const tokenFor = this.opts.tokenFor ?? ((a, _ctx) => `token:${a}`);
|
|
6889
6908
|
const actorToken = tokenFor(dispatchSpec.actor, credentialCtx);
|
|
6890
|
-
const provisioned = this.opts.provision ? await this.opts.provision(dispatchSpec.actor) : void 0;
|
|
6909
|
+
const provisioned = this.opts.provision ? await this.opts.provision(dispatchSpec.actor, spec.artifactId) : void 0;
|
|
6891
6910
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
6892
6911
|
const jobEnv = {
|
|
6893
6912
|
...provisioned?.env ?? {},
|
|
@@ -23533,8 +23552,8 @@ var require_axios = __commonJS({
|
|
|
23533
23552
|
axios.toFormData = toFormData;
|
|
23534
23553
|
axios.AxiosError = AxiosError$1;
|
|
23535
23554
|
axios.Cancel = axios.CanceledError;
|
|
23536
|
-
axios.all = function all(
|
|
23537
|
-
return Promise.all(
|
|
23555
|
+
axios.all = function all(promises2) {
|
|
23556
|
+
return Promise.all(promises2);
|
|
23538
23557
|
};
|
|
23539
23558
|
axios.spread = spread;
|
|
23540
23559
|
axios.isAxiosError = isAxiosError;
|
|
@@ -124780,8 +124799,8 @@ function getElementAtPath(obj, path30) {
|
|
|
124780
124799
|
}
|
|
124781
124800
|
function promiseAllObject(promisesObj) {
|
|
124782
124801
|
const keys = Object.keys(promisesObj);
|
|
124783
|
-
const
|
|
124784
|
-
return Promise.all(
|
|
124802
|
+
const promises2 = keys.map((key) => promisesObj[key]);
|
|
124803
|
+
return Promise.all(promises2).then((results) => {
|
|
124785
124804
|
const resolvedObj = {};
|
|
124786
124805
|
for (let i = 0; i < keys.length; i++) {
|
|
124787
124806
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -140760,8 +140779,8 @@ var init_install = __esm({
|
|
|
140760
140779
|
function shSingleQuote(v2) {
|
|
140761
140780
|
return `'${v2.replace(/'/g, `'\\''`)}'`;
|
|
140762
140781
|
}
|
|
140763
|
-
async function writeSessionCredsFile(slug6, exports2) {
|
|
140764
|
-
const dir = await (0, import_promises.mkdtemp)((0, import_node_path5.join)((0, import_node_os3.tmpdir)(), `oasis-${slug6}-`));
|
|
140782
|
+
async function writeSessionCredsFile(slug6, exports2, reuseDir) {
|
|
140783
|
+
const dir = reuseDir ?? await (0, import_promises.mkdtemp)((0, import_node_path5.join)((0, import_node_os3.tmpdir)(), `oasis-${slug6}-`));
|
|
140765
140784
|
const file = (0, import_node_path5.join)(dir, "creds.env");
|
|
140766
140785
|
const body = Object.entries(exports2).map(([k2, v2]) => `export ${k2}=${shSingleQuote(v2)}`).join("\n");
|
|
140767
140786
|
await (0, import_promises.writeFile)(file, body + "\n", { mode: 384 });
|
|
@@ -140787,7 +140806,7 @@ async function refreshCredentialsIfNeeded(connector, credentials, opts = {}) {
|
|
|
140787
140806
|
return { status: "unsupported", detail: `${connector.config.slug}: \u51ED\u636E\u4E0D\u8FC7\u671F\uFF0C\u65E0\u9700\u7EED\u671F` };
|
|
140788
140807
|
}
|
|
140789
140808
|
const nowMs = opts.nowMs ?? Date.now();
|
|
140790
|
-
const skewMs = opts.skewMs ?? CREDENTIAL_REFRESH_SKEW_MS;
|
|
140809
|
+
const skewMs = opts.skewMs ?? connector.minRemainingLifetimeMs ?? CREDENTIAL_REFRESH_SKEW_MS;
|
|
140791
140810
|
const expiresAt = readEpochMs(credentials, connector.expiresAtCredentialKey);
|
|
140792
140811
|
if (!isExpiringSoon(expiresAt, nowMs, skewMs)) {
|
|
140793
140812
|
return { status: "fresh" };
|
|
@@ -141072,6 +141091,8 @@ var init_feishu = __esm({
|
|
|
141072
141091
|
"FEISHU_REFRESH_TOKEN_EXPIRES_AT",
|
|
141073
141092
|
"FEISHU_USER_OPEN_ID"
|
|
141074
141093
|
];
|
|
141094
|
+
/** 宿主机登录态隔离,理由同 github(见接口注释):由通用装配层无条件设。 */
|
|
141095
|
+
hostCredentialIsolationEnvKeys = ["LARKSUITE_CLI_CONFIG_DIR"];
|
|
141075
141096
|
/** inject() 写进 sessionEnv 的全部键——通用 cleanup() 按它逐个删。 */
|
|
141076
141097
|
injectedEnvKeys = [
|
|
141077
141098
|
"LARK_BIN",
|
|
@@ -141140,7 +141161,7 @@ var init_feishu = __esm({
|
|
|
141140
141161
|
LARKSUITE_CLI_APP_ID: appId,
|
|
141141
141162
|
LARKSUITE_CLI_APP_SECRET: appSecret,
|
|
141142
141163
|
...userAccessToken ? { LARKSUITE_CLI_USER_ACCESS_TOKEN: userAccessToken } : {}
|
|
141143
|
-
});
|
|
141164
|
+
}, sessionEnv.get("FEISHU_RUN_TMPDIR"));
|
|
141144
141165
|
const configDir = (0, import_node_path6.join)(creds.dir, "lark-config");
|
|
141145
141166
|
await (0, import_promises3.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
141146
141167
|
sessionEnv.set("LARK_BIN", await this.resolveAbsoluteLarkBin());
|
|
@@ -141633,10 +141654,17 @@ async function exchangeManifestCode(code, deps = {}) {
|
|
|
141633
141654
|
const appId = body["id"] === void 0 ? "" : String(body["id"]);
|
|
141634
141655
|
const privateKeyPem = typeof body["pem"] === "string" ? body["pem"] : "";
|
|
141635
141656
|
if (!appId || !privateKeyPem) throw new Error("github app: id/pem missing in conversion response");
|
|
141657
|
+
const owner = body["owner"];
|
|
141658
|
+
const rawPerms = body["permissions"];
|
|
141659
|
+
const permissions = {};
|
|
141660
|
+
for (const [k2, v2] of Object.entries(rawPerms ?? {})) if (typeof v2 === "string") permissions[k2] = v2;
|
|
141636
141661
|
return {
|
|
141637
141662
|
appId,
|
|
141638
141663
|
privateKeyPem,
|
|
141639
141664
|
slug: typeof body["slug"] === "string" ? body["slug"] : "",
|
|
141665
|
+
ownerLogin: typeof owner?.["login"] === "string" ? owner["login"] : "",
|
|
141666
|
+
ownerType: typeof owner?.["type"] === "string" ? owner["type"] : "",
|
|
141667
|
+
permissions,
|
|
141640
141668
|
...typeof body["webhook_secret"] === "string" ? { webhookSecret: body["webhook_secret"] } : {}
|
|
141641
141669
|
};
|
|
141642
141670
|
}
|
|
@@ -141720,6 +141748,18 @@ var init_github = __esm({
|
|
|
141720
141748
|
{ key: "access_token", from: "GITHUB_APP_TOKEN", required: false },
|
|
141721
141749
|
{ key: "app_token_expires_at", from: "GITHUB_APP_TOKEN_EXPIRES_AT", required: false }
|
|
141722
141750
|
];
|
|
141751
|
+
/**
|
|
141752
|
+
* installation token 满寿命就是 1 小时;声明成全寿命 ⇒ **每次注入都铸新的**。
|
|
141753
|
+
*
|
|
141754
|
+
* 代价可接受:铸 token 是纯换取(私钥 + installation_id 推出来的),
|
|
141755
|
+
* **旧 token 不会被新的作废**(GitHub 要显式 `DELETE /installation/token` 才失效),
|
|
141756
|
+
* 所以多铸一次既不打断在跑的会话、也不消耗任何一次性材料。
|
|
141757
|
+
*
|
|
141758
|
+
* 换来的是:一场会话开头拿到的 token 一定是满 60 分钟,而不是「上一场剩下的 6 分钟」。
|
|
141759
|
+
* ⚠ 仍挡不住跑超过 60 分钟的会话——会话硬顶是 120 分钟(`SESSION_WALL_CLOCK_MS`),
|
|
141760
|
+
* 那半截要靠会话内续期,本字段管不到。
|
|
141761
|
+
*/
|
|
141762
|
+
minRemainingLifetimeMs = 60 * 6e4;
|
|
141723
141763
|
/** 过期判定只认这个键——必须与注入时消费的 token 同源(契约测试盯着)。 */
|
|
141724
141764
|
expiresAtCredentialKey = "app_token_expires_at";
|
|
141725
141765
|
// 私钥不会过期,故不声明 refreshMaterialExpiresAtCredentialKey,也无需 clearOnExpired。
|
|
@@ -141729,6 +141769,12 @@ var init_github = __esm({
|
|
|
141729
141769
|
"GITHUB_APP_TOKEN",
|
|
141730
141770
|
"GITHUB_APP_PRIVATE_KEY"
|
|
141731
141771
|
];
|
|
141772
|
+
/**
|
|
141773
|
+
* 宿主机登录态隔离:`gh` 只认 env 里的 GH_TOKEN 或 `~/.config/gh/hosts.yml`。
|
|
141774
|
+
* 这个键**由通用装配层无条件设**(哪怕本连接器没接通),否则关掉连接器时
|
|
141775
|
+
* agent 会静默用成宿主机那个真人账号——见接口里的详细说明。
|
|
141776
|
+
*/
|
|
141777
|
+
hostCredentialIsolationEnvKeys = ["GH_CONFIG_DIR"];
|
|
141732
141778
|
/** inject() 写进 sessionEnv 的全部键——通用 cleanup() 按它逐个删。 */
|
|
141733
141779
|
injectedEnvKeys = [
|
|
141734
141780
|
"GH_BIN",
|
|
@@ -141819,7 +141865,7 @@ var init_github = __esm({
|
|
|
141819
141865
|
const creds = await writeSessionCredsFile(this.config.slug, {
|
|
141820
141866
|
GH_TOKEN: token,
|
|
141821
141867
|
GITHUB_TOKEN: token
|
|
141822
|
-
});
|
|
141868
|
+
}, sessionEnv.get("GH_RUN_TMPDIR"));
|
|
141823
141869
|
const configDir = (0, import_node_path7.join)(creds.dir, "gh-config");
|
|
141824
141870
|
await (0, import_promises4.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
141825
141871
|
sessionEnv.set("GH_BIN", await this.resolveRealBin("gh"));
|
|
@@ -141872,7 +141918,27 @@ function callbackHtml(ok, message) {
|
|
|
141872
141918
|
setTimeout(function(){window.close()},${ok ? 800 : 4e3})</script>
|
|
141873
141919
|
</body>`;
|
|
141874
141920
|
}
|
|
141875
|
-
|
|
141921
|
+
function checkAppOwnership(conv, want) {
|
|
141922
|
+
if (want.ownerKind === "org" && want.ownerLogin) {
|
|
141923
|
+
const got = conv.ownerLogin;
|
|
141924
|
+
if (!got) {
|
|
141925
|
+
return { message: "GitHub \u6CA1\u8FD4\u56DE App \u7684\u5F52\u5C5E\u8D26\u53F7\uFF0C\u65E0\u6CD5\u786E\u8BA4\u5EFA\u5BF9\u4E86\u5730\u65B9\u2014\u2014\u8BF7\u5220\u6389\u8FD9\u4E2A App \u91CD\u8BD5\u3002" };
|
|
141926
|
+
}
|
|
141927
|
+
if (got.toLowerCase() !== want.ownerLogin.toLowerCase()) {
|
|
141928
|
+
return {
|
|
141929
|
+
message: `\u4F60\u9009\u7684\u662F\u7EC4\u7EC7 ${want.ownerLogin}\uFF0C\u4F46\u8FD9\u4E2A App \u5EFA\u5728\u4E86 ${got}\uFF08${conv.ownerType || "\u672A\u77E5\u7C7B\u578B"}\uFF09\u540D\u4E0B\u3002\u79C1\u6709 App \u53EA\u80FD\u88C5\u5728\u62E5\u6709\u5B83\u7684\u8D26\u53F7\u4E0A\uFF0C\u6240\u4EE5\u5B83\u6C38\u8FDC\u8BBF\u95EE\u4E0D\u5230 ${want.ownerLogin} \u7684\u4ED3\u5E93\u2014\u2014\u8865\u88C5\u4E5F\u6CA1\u7528\u3002\u8BF7\u53BB GitHub \u5220\u6389 ${got} \u540D\u4E0B\u8FD9\u4E2A App\uFF0C\u7136\u540E\u91CD\u65B0\u8FDE\u63A5\uFF0C\u5728\u521B\u5EFA\u9875\u786E\u8BA4\u5730\u5740\u662F github.com/organizations/${want.ownerLogin}/settings/apps/new\u3002`
|
|
141930
|
+
};
|
|
141931
|
+
}
|
|
141932
|
+
}
|
|
141933
|
+
const missing = REQUIRED_WRITE_PERMISSIONS.filter((k2) => conv.permissions[k2] !== "write");
|
|
141934
|
+
if (missing.length > 0) {
|
|
141935
|
+
return {
|
|
141936
|
+
message: `\u8FD9\u4E2A App \u7F3A\u5C11\u5FC5\u8981\u7684\u5199\u6743\u9650\uFF1A${missing.join(" / ")}\uFF08\u9700\u8981 write\uFF09\u3002agent \u5C06\u65E0\u6CD5\u63A8\u9001\u5206\u652F\u6216\u5F00 PR\u3002\u8BF7\u5728 App \u8BBE\u7F6E\u9875\u8865\u4E0A\u6743\u9650\u540E\u91CD\u65B0\u8FDE\u63A5\u3002`
|
|
141937
|
+
};
|
|
141938
|
+
}
|
|
141939
|
+
return null;
|
|
141940
|
+
}
|
|
141941
|
+
var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, PendingAppCreations, REQUIRED_WRITE_PERMISSIONS;
|
|
141876
141942
|
var init_app_manifest = __esm({
|
|
141877
141943
|
"../connectors/src/github/app-manifest.ts"() {
|
|
141878
141944
|
"use strict";
|
|
@@ -141915,6 +141981,7 @@ var init_app_manifest = __esm({
|
|
|
141915
141981
|
return this.map.size;
|
|
141916
141982
|
}
|
|
141917
141983
|
};
|
|
141984
|
+
REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
|
|
141918
141985
|
}
|
|
141919
141986
|
});
|
|
141920
141987
|
|
|
@@ -141971,19 +142038,27 @@ function collectCredentials(connector, ctx) {
|
|
|
141971
142038
|
}
|
|
141972
142039
|
return creds;
|
|
141973
142040
|
}
|
|
142041
|
+
function collectAllConnectorCredentials(ctx) {
|
|
142042
|
+
return createAllConnectors().flatMap((connector) => {
|
|
142043
|
+
const credentials = collectCredentials(connector, ctx);
|
|
142044
|
+
return credentials ? [{ slug: connector.config.slug, credentials }] : [];
|
|
142045
|
+
});
|
|
142046
|
+
}
|
|
141974
142047
|
async function buildConnectorProvision(ctx) {
|
|
141975
142048
|
const envOverrides = {};
|
|
141976
142049
|
const wrapperPaths = [];
|
|
141977
142050
|
const requiredTools = /* @__PURE__ */ new Set();
|
|
141978
|
-
const connectorCreds = [];
|
|
141979
142051
|
const cleanups = [];
|
|
141980
142052
|
const sensitiveVars = /* @__PURE__ */ new Set();
|
|
142053
|
+
const isolationKeys = /* @__PURE__ */ new Set();
|
|
142054
|
+
const connectorCreds = collectAllConnectorCredentials(ctx);
|
|
142055
|
+
const credentialsBySlug = new Map(connectorCreds.map((c) => [c.slug, c.credentials]));
|
|
141981
142056
|
for (const connector of createAllConnectors()) {
|
|
141982
142057
|
for (const v2 of connector.sensitiveVars) sensitiveVars.add(v2);
|
|
141983
|
-
const
|
|
141984
|
-
|
|
142058
|
+
for (const k2 of connector.hostCredentialIsolationEnvKeys ?? []) isolationKeys.add(k2);
|
|
142059
|
+
const credentials = credentialsBySlug.get(connector.config.slug);
|
|
142060
|
+
if (credentials === void 0) continue;
|
|
141985
142061
|
try {
|
|
141986
|
-
connectorCreds.push({ slug: connector.config.slug, credentials });
|
|
141987
142062
|
const sessionEnv = /* @__PURE__ */ new Map();
|
|
141988
142063
|
await connector.inject(credentials, sessionEnv);
|
|
141989
142064
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
@@ -141999,6 +142074,19 @@ async function buildConnectorProvision(ctx) {
|
|
|
141999
142074
|
log("[provision]", `${connector.config.slug}: \u88C5\u914D\u5931\u8D25\uFF08\u8BE5\u8FDE\u63A5\u5668\u672C\u8F6E\u4E0D\u53EF\u7528\uFF09: ${String(err)}`);
|
|
142000
142075
|
}
|
|
142001
142076
|
}
|
|
142077
|
+
const isolationRoot = await (0, import_promises5.mkdtemp)((0, import_node_path8.join)((0, import_node_os4.tmpdir)(), "oasis-isolate-"));
|
|
142078
|
+
let isolationUsed = false;
|
|
142079
|
+
for (const key of isolationKeys) {
|
|
142080
|
+
if (envOverrides[key]) continue;
|
|
142081
|
+
const dir = (0, import_node_path8.join)(isolationRoot, key.toLowerCase());
|
|
142082
|
+
await (0, import_promises5.mkdir)(dir, { recursive: true, mode: 448 });
|
|
142083
|
+
envOverrides[key] = dir;
|
|
142084
|
+
isolationUsed = true;
|
|
142085
|
+
}
|
|
142086
|
+
if (!isolationUsed) await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
|
|
142087
|
+
else cleanups.push(async () => {
|
|
142088
|
+
await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
|
|
142089
|
+
});
|
|
142002
142090
|
const cleanup = async () => {
|
|
142003
142091
|
for (const fn of cleanups) await fn().catch(() => {
|
|
142004
142092
|
});
|
|
@@ -142012,23 +142100,28 @@ async function buildConnectorProvision(ctx) {
|
|
|
142012
142100
|
cleanup
|
|
142013
142101
|
};
|
|
142014
142102
|
}
|
|
142103
|
+
var import_promises5, import_node_os4, import_node_path8;
|
|
142015
142104
|
var init_provision = __esm({
|
|
142016
142105
|
"../connectors/src/provision.ts"() {
|
|
142017
142106
|
"use strict";
|
|
142018
142107
|
init_base();
|
|
142019
142108
|
init_registry2();
|
|
142020
142109
|
init_logger();
|
|
142110
|
+
import_promises5 = require("node:fs/promises");
|
|
142111
|
+
import_node_os4 = require("node:os");
|
|
142112
|
+
import_node_path8 = require("node:path");
|
|
142021
142113
|
}
|
|
142022
142114
|
});
|
|
142023
142115
|
|
|
142024
142116
|
// ../connectors/src/prepare-job.ts
|
|
142025
|
-
async function prepareConnectorsForJob(job) {
|
|
142117
|
+
async function prepareConnectorsForJob(job, deps) {
|
|
142026
142118
|
const creds = job.connectorCreds ?? [];
|
|
142027
142119
|
const remoteWrappers = job.wrapperPaths ?? [];
|
|
142028
142120
|
const localWrappers = [];
|
|
142029
142121
|
const cleanups = [];
|
|
142030
142122
|
const envOverrides = {};
|
|
142031
142123
|
const statuses = [];
|
|
142124
|
+
const injected = /* @__PURE__ */ new Map();
|
|
142032
142125
|
for (const { slug: slug6, credentials } of creds) {
|
|
142033
142126
|
const connector = createConnectorBySlug(slug6);
|
|
142034
142127
|
if (!connector) {
|
|
@@ -142043,6 +142136,7 @@ async function prepareConnectorsForJob(job) {
|
|
|
142043
142136
|
await connector.inject(credentials, sessionEnv);
|
|
142044
142137
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
142045
142138
|
cleanups.push(() => connector.cleanup(sessionEnv));
|
|
142139
|
+
injected.set(slug6, { connector, sessionEnv });
|
|
142046
142140
|
status.credsReady = true;
|
|
142047
142141
|
} catch (err) {
|
|
142048
142142
|
status.error = String(err);
|
|
@@ -142076,13 +142170,62 @@ async function prepareConnectorsForJob(job) {
|
|
|
142076
142170
|
env: { ...job.env ?? {}, ...envOverrides, PATH: pathWithTools },
|
|
142077
142171
|
wrapperPaths: [...keptLocal, ...keptRemote]
|
|
142078
142172
|
};
|
|
142173
|
+
if (injected.size > 0 && (job.limits?.wallClockMs ?? 0) > SESSION_CREDENTIAL_RENEW_INTERVAL_MS) {
|
|
142174
|
+
const fetchCredentials = deps?.fetchCredentials ?? fetchCredentialsFromServer(job);
|
|
142175
|
+
const setTimer = deps?.setTimer ?? defaultSetTimer;
|
|
142176
|
+
const timer = setTimer(() => {
|
|
142177
|
+
void renewInjectedCredentials(injected, fetchCredentials);
|
|
142178
|
+
}, SESSION_CREDENTIAL_RENEW_INTERVAL_MS);
|
|
142179
|
+
cleanups.push(async () => {
|
|
142180
|
+
timer.stop();
|
|
142181
|
+
});
|
|
142182
|
+
log("[node-connectors]", `\u4F1A\u8BDD\u4E2D\u9014\u7EED\u671F\u5DF2\u542F\u52A8\uFF08\u6BCF ${SESSION_CREDENTIAL_RENEW_INTERVAL_MS / 6e4} \u5206\u949F\uFF0C${injected.size} \u4E2A\u8FDE\u63A5\u5668\uFF09`);
|
|
142183
|
+
}
|
|
142079
142184
|
const cleanup = async () => {
|
|
142080
142185
|
for (const fn of cleanups) await fn().catch(() => {
|
|
142081
142186
|
});
|
|
142082
142187
|
};
|
|
142083
142188
|
return { job: preparedJob, cleanup, statuses };
|
|
142084
142189
|
}
|
|
142085
|
-
|
|
142190
|
+
async function renewInjectedCredentials(injected, fetchCredentials) {
|
|
142191
|
+
const outcome = { renewed: [], failed: [] };
|
|
142192
|
+
let fresh;
|
|
142193
|
+
try {
|
|
142194
|
+
fresh = await fetchCredentials();
|
|
142195
|
+
} catch (err) {
|
|
142196
|
+
for (const slug6 of injected.keys()) outcome.failed.push({ slug: slug6, error: String(err) });
|
|
142197
|
+
log("[node-connectors]", `\u7EED\u671F\uFF1A\u5411 server \u53D6\u51ED\u636E\u5931\u8D25\uFF0C\u672C\u8F6E\u6CBF\u7528\u65E7\u51ED\u636E: ${String(err)}`);
|
|
142198
|
+
return outcome;
|
|
142199
|
+
}
|
|
142200
|
+
for (const { slug: slug6, credentials } of fresh) {
|
|
142201
|
+
const target = injected.get(slug6);
|
|
142202
|
+
if (!target) continue;
|
|
142203
|
+
try {
|
|
142204
|
+
await target.connector.inject(credentials, target.sessionEnv);
|
|
142205
|
+
outcome.renewed.push(slug6);
|
|
142206
|
+
} catch (err) {
|
|
142207
|
+
outcome.failed.push({ slug: slug6, error: String(err) });
|
|
142208
|
+
log("[node-connectors]", `\u26A0 \u7EED\u671F\uFF1A${slug6} \u5C31\u5730\u91CD\u6CE8\u5931\u8D25\uFF0C\u6CBF\u7528\u65E7\u51ED\u636E: ${String(err)}`);
|
|
142209
|
+
}
|
|
142210
|
+
}
|
|
142211
|
+
if (outcome.renewed.length > 0) log("[node-connectors]", `\u7EED\u671F\uFF1A\u5DF2\u5C31\u5730\u6362\u65B0 ${outcome.renewed.join(", ")}`);
|
|
142212
|
+
return outcome;
|
|
142213
|
+
}
|
|
142214
|
+
function defaultSetTimer(fn, ms) {
|
|
142215
|
+
const timer = setInterval(fn, ms);
|
|
142216
|
+
timer.unref?.();
|
|
142217
|
+
return { stop: () => clearInterval(timer) };
|
|
142218
|
+
}
|
|
142219
|
+
function fetchCredentialsFromServer(job) {
|
|
142220
|
+
return async () => {
|
|
142221
|
+
const url = new URL("/api/connector-credentials", job.server?.url ?? "").toString();
|
|
142222
|
+
const res = await fetch(url, { headers: { authorization: `Bearer ${job.actorToken}` } });
|
|
142223
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
142224
|
+
const body = await res.json();
|
|
142225
|
+
return body.connectorCreds ?? [];
|
|
142226
|
+
};
|
|
142227
|
+
}
|
|
142228
|
+
var import_node_fs5, SESSION_CREDENTIAL_RENEW_INTERVAL_MS;
|
|
142086
142229
|
var init_prepare_job = __esm({
|
|
142087
142230
|
"../connectors/src/prepare-job.ts"() {
|
|
142088
142231
|
"use strict";
|
|
@@ -142090,6 +142233,7 @@ var init_prepare_job = __esm({
|
|
|
142090
142233
|
init_base();
|
|
142091
142234
|
init_registry2();
|
|
142092
142235
|
init_logger();
|
|
142236
|
+
SESSION_CREDENTIAL_RENEW_INTERVAL_MS = 30 * 6e4;
|
|
142093
142237
|
}
|
|
142094
142238
|
});
|
|
142095
142239
|
|
|
@@ -142428,8 +142572,8 @@ function materializeFiles(dir, files) {
|
|
|
142428
142572
|
if (!files) return;
|
|
142429
142573
|
for (const [rel, content] of Object.entries(files)) {
|
|
142430
142574
|
try {
|
|
142431
|
-
const file =
|
|
142432
|
-
import_node_fs6.default.mkdirSync(
|
|
142575
|
+
const file = import_node_path9.default.join(dir, rel);
|
|
142576
|
+
import_node_fs6.default.mkdirSync(import_node_path9.default.dirname(file), { recursive: true });
|
|
142433
142577
|
import_node_fs6.default.writeFileSync(file, content);
|
|
142434
142578
|
} catch {
|
|
142435
142579
|
}
|
|
@@ -142445,7 +142589,7 @@ function resolveLegacyWorkRoot(workRoot) {
|
|
|
142445
142589
|
if (workRoot) return workRoot;
|
|
142446
142590
|
const env = process.env["OASIS_WORK_ROOT"];
|
|
142447
142591
|
if (env) return env;
|
|
142448
|
-
return
|
|
142592
|
+
return import_node_os5.default.tmpdir();
|
|
142449
142593
|
}
|
|
142450
142594
|
function resolveWorkRoots(workRoot) {
|
|
142451
142595
|
return { workRoot: resolveWorkRoot(workRoot), legacyRoot: resolveLegacyWorkRoot(workRoot) };
|
|
@@ -142456,7 +142600,7 @@ function slug5(workdirKey) {
|
|
|
142456
142600
|
return `${safe}-${h}`;
|
|
142457
142601
|
}
|
|
142458
142602
|
function sessionDirFor(workRoot, runtimeKind, workdirKey) {
|
|
142459
|
-
return
|
|
142603
|
+
return import_node_path9.default.join(resolveWorkRoot(workRoot), "sessions", runtimeKind, slug5(workdirKey));
|
|
142460
142604
|
}
|
|
142461
142605
|
function sessionDirKind(runtimeKind) {
|
|
142462
142606
|
return runtimeKind === "claude-code" ? "claude" : runtimeKind;
|
|
@@ -142469,20 +142613,20 @@ function resolveSessionDirWithLegacy(args) {
|
|
|
142469
142613
|
return import_node_fs6.default.existsSync(legacy) ? legacy : fresh;
|
|
142470
142614
|
}
|
|
142471
142615
|
function oneShotDirFor(workRoot, runtimeKind) {
|
|
142472
|
-
const base =
|
|
142616
|
+
const base = import_node_path9.default.join(resolveWorkRoot(workRoot), "tmp");
|
|
142473
142617
|
import_node_fs6.default.mkdirSync(base, { recursive: true });
|
|
142474
|
-
return import_node_fs6.default.mkdtempSync(
|
|
142618
|
+
return import_node_fs6.default.mkdtempSync(import_node_path9.default.join(base, `${runtimeKind}-`));
|
|
142475
142619
|
}
|
|
142476
142620
|
function writeMeta(dir, meta) {
|
|
142477
142621
|
try {
|
|
142478
|
-
import_node_fs6.default.writeFileSync(
|
|
142622
|
+
import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, META_FILE), `${JSON.stringify(meta, null, 2)}
|
|
142479
142623
|
`);
|
|
142480
142624
|
} catch {
|
|
142481
142625
|
}
|
|
142482
142626
|
}
|
|
142483
142627
|
function readMeta(dir) {
|
|
142484
142628
|
try {
|
|
142485
|
-
const raw = JSON.parse(import_node_fs6.default.readFileSync(
|
|
142629
|
+
const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, META_FILE), "utf8"));
|
|
142486
142630
|
if (!raw || typeof raw !== "object") return null;
|
|
142487
142631
|
const m2 = raw;
|
|
142488
142632
|
return typeof m2.kind === "string" && typeof m2.createdAt === "string" ? m2 : null;
|
|
@@ -142511,14 +142655,14 @@ function lockWorkdir(dir, pid, holder, workdirKey) {
|
|
|
142511
142655
|
...workdirKey !== void 0 ? { workdirKey } : {}
|
|
142512
142656
|
};
|
|
142513
142657
|
try {
|
|
142514
|
-
import_node_fs6.default.writeFileSync(
|
|
142658
|
+
import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, LOCK_FILE), `${JSON.stringify(lock)}
|
|
142515
142659
|
`);
|
|
142516
142660
|
} catch {
|
|
142517
142661
|
}
|
|
142518
142662
|
}
|
|
142519
142663
|
function readLock(dir) {
|
|
142520
142664
|
try {
|
|
142521
|
-
const raw = JSON.parse(import_node_fs6.default.readFileSync(
|
|
142665
|
+
const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, LOCK_FILE), "utf8"));
|
|
142522
142666
|
if (!raw || typeof raw !== "object") return null;
|
|
142523
142667
|
const l = raw;
|
|
142524
142668
|
return Number.isInteger(l.pid) && l.pid > 0 ? l : null;
|
|
@@ -142528,14 +142672,14 @@ function readLock(dir) {
|
|
|
142528
142672
|
}
|
|
142529
142673
|
function unlockWorkdir(dir) {
|
|
142530
142674
|
try {
|
|
142531
|
-
import_node_fs6.default.unlinkSync(
|
|
142675
|
+
import_node_fs6.default.unlinkSync(import_node_path9.default.join(dir, LOCK_FILE));
|
|
142532
142676
|
} catch {
|
|
142533
142677
|
}
|
|
142534
142678
|
}
|
|
142535
142679
|
function isWorkdirLive(dir) {
|
|
142536
142680
|
let raw;
|
|
142537
142681
|
try {
|
|
142538
|
-
raw = import_node_fs6.default.readFileSync(
|
|
142682
|
+
raw = import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, LOCK_FILE), "utf8");
|
|
142539
142683
|
} catch {
|
|
142540
142684
|
return false;
|
|
142541
142685
|
}
|
|
@@ -142552,7 +142696,7 @@ function clearWorkdir(dir) {
|
|
|
142552
142696
|
);
|
|
142553
142697
|
}
|
|
142554
142698
|
for (const entry of import_node_fs6.default.readdirSync(dir)) {
|
|
142555
|
-
import_node_fs6.default.rmSync(
|
|
142699
|
+
import_node_fs6.default.rmSync(import_node_path9.default.join(dir, entry), { recursive: true, force: true });
|
|
142556
142700
|
}
|
|
142557
142701
|
}
|
|
142558
142702
|
function prepareWorkdir(args) {
|
|
@@ -142582,19 +142726,19 @@ function prepareWorkdir(args) {
|
|
|
142582
142726
|
return dir;
|
|
142583
142727
|
}
|
|
142584
142728
|
function legacyChatSessionDir(workRoot, rtId) {
|
|
142585
|
-
return
|
|
142729
|
+
return import_node_path9.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
|
|
142586
142730
|
}
|
|
142587
|
-
var import_node_crypto9, import_node_fs6,
|
|
142731
|
+
var import_node_crypto9, import_node_fs6, import_node_os5, import_node_path9, META_FILE, LOCK_FILE, NEW_WORK_ROOT, LEGACY_ROOTS, LEGACY_ONESHOT_PREFIX;
|
|
142588
142732
|
var init_session_paths = __esm({
|
|
142589
142733
|
"../adapters/src/_core/session-paths.ts"() {
|
|
142590
142734
|
"use strict";
|
|
142591
142735
|
import_node_crypto9 = require("node:crypto");
|
|
142592
142736
|
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
142593
|
-
|
|
142594
|
-
|
|
142737
|
+
import_node_os5 = __toESM(require("node:os"), 1);
|
|
142738
|
+
import_node_path9 = __toESM(require("node:path"), 1);
|
|
142595
142739
|
META_FILE = ".oasis-meta.json";
|
|
142596
142740
|
LOCK_FILE = ".oasis-lock";
|
|
142597
|
-
NEW_WORK_ROOT = () =>
|
|
142741
|
+
NEW_WORK_ROOT = () => import_node_path9.default.join(import_node_os5.default.homedir(), ".oasis", "work");
|
|
142598
142742
|
LEGACY_ROOTS = ["oasis-chat-sessions", "oasis-transcripts"];
|
|
142599
142743
|
LEGACY_ONESHOT_PREFIX = "oasis-session-";
|
|
142600
142744
|
}
|
|
@@ -143816,7 +143960,7 @@ async function discoverACPModels(bin, provider, args = ["acp"]) {
|
|
|
143816
143960
|
clientCapabilities: {}
|
|
143817
143961
|
});
|
|
143818
143962
|
try {
|
|
143819
|
-
tmpDir = (0, import_node_fs7.mkdtempSync)((0,
|
|
143963
|
+
tmpDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path10.join)((0, import_node_os6.tmpdir)(), `oasis-acp-${provider}-`));
|
|
143820
143964
|
} catch {
|
|
143821
143965
|
return fail();
|
|
143822
143966
|
}
|
|
@@ -143872,14 +144016,14 @@ function parseACPSessionNewModels(result) {
|
|
|
143872
144016
|
async function discoverOpenclawModels(bin) {
|
|
143873
144017
|
throw new Error("discoverOpenclawModels: TODO");
|
|
143874
144018
|
}
|
|
143875
|
-
var import_node_child_process9, import_node_fs7,
|
|
144019
|
+
var import_node_child_process9, import_node_fs7, import_node_os6, import_node_path10, modelCache, CACHE_TTL_MS;
|
|
143876
144020
|
var init_models = __esm({
|
|
143877
144021
|
"../adapters/src/_core/models.ts"() {
|
|
143878
144022
|
"use strict";
|
|
143879
144023
|
import_node_child_process9 = require("node:child_process");
|
|
143880
144024
|
import_node_fs7 = require("node:fs");
|
|
143881
|
-
|
|
143882
|
-
|
|
144025
|
+
import_node_os6 = require("node:os");
|
|
144026
|
+
import_node_path10 = require("node:path");
|
|
143883
144027
|
modelCache = /* @__PURE__ */ new Map();
|
|
143884
144028
|
CACHE_TTL_MS = 6e4;
|
|
143885
144029
|
}
|
|
@@ -146446,7 +146590,7 @@ function dirSizeBytes(dir) {
|
|
|
146446
146590
|
return;
|
|
146447
146591
|
}
|
|
146448
146592
|
for (const e of entries) {
|
|
146449
|
-
const p2 =
|
|
146593
|
+
const p2 = import_node_path11.default.join(d, e.name);
|
|
146450
146594
|
if (e.isSymbolicLink()) continue;
|
|
146451
146595
|
if (e.isDirectory()) {
|
|
146452
146596
|
walk(p2);
|
|
@@ -146463,40 +146607,40 @@ function dirSizeBytes(dir) {
|
|
|
146463
146607
|
}
|
|
146464
146608
|
function listWorkdirs(workRoot, legacyRoot) {
|
|
146465
146609
|
const out = [];
|
|
146466
|
-
const sessions =
|
|
146610
|
+
const sessions = import_node_path11.default.join(workRoot, "sessions");
|
|
146467
146611
|
try {
|
|
146468
146612
|
for (const kind of import_node_fs8.default.readdirSync(sessions)) {
|
|
146469
|
-
const kindDir =
|
|
146613
|
+
const kindDir = import_node_path11.default.join(sessions, kind);
|
|
146470
146614
|
try {
|
|
146471
|
-
for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(
|
|
146615
|
+
for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(import_node_path11.default.join(kindDir, slug6));
|
|
146472
146616
|
} catch {
|
|
146473
146617
|
}
|
|
146474
146618
|
}
|
|
146475
146619
|
} catch {
|
|
146476
146620
|
}
|
|
146477
|
-
const tmp =
|
|
146621
|
+
const tmp = import_node_path11.default.join(workRoot, "tmp");
|
|
146478
146622
|
try {
|
|
146479
|
-
for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(
|
|
146623
|
+
for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(import_node_path11.default.join(tmp, d));
|
|
146480
146624
|
} catch {
|
|
146481
146625
|
}
|
|
146482
146626
|
for (const legacy of LEGACY_ROOTS) {
|
|
146483
|
-
const root =
|
|
146627
|
+
const root = import_node_path11.default.join(legacyRoot, legacy);
|
|
146484
146628
|
try {
|
|
146485
|
-
for (const d of import_node_fs8.default.readdirSync(root)) out.push(
|
|
146629
|
+
for (const d of import_node_fs8.default.readdirSync(root)) out.push(import_node_path11.default.join(root, d));
|
|
146486
146630
|
} catch {
|
|
146487
146631
|
}
|
|
146488
146632
|
}
|
|
146489
146633
|
try {
|
|
146490
146634
|
for (const d of import_node_fs8.default.readdirSync(legacyRoot)) {
|
|
146491
|
-
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(
|
|
146635
|
+
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(import_node_path11.default.join(legacyRoot, d));
|
|
146492
146636
|
}
|
|
146493
146637
|
} catch {
|
|
146494
146638
|
}
|
|
146495
146639
|
return [...new Set(out)];
|
|
146496
146640
|
}
|
|
146497
146641
|
function kindFromPath(workRoot, dir) {
|
|
146498
|
-
const rel =
|
|
146499
|
-
const parts = rel.split(
|
|
146642
|
+
const rel = import_node_path11.default.relative(workRoot, dir);
|
|
146643
|
+
const parts = rel.split(import_node_path11.default.sep);
|
|
146500
146644
|
if (parts[0] === "sessions" && parts[1]) return parts[1];
|
|
146501
146645
|
if (parts[0] === "tmp" && parts[1]) return parts[1].replace(/-[^-]*$/, "");
|
|
146502
146646
|
return void 0;
|
|
@@ -146538,7 +146682,7 @@ async function runGcSweep(deps) {
|
|
|
146538
146682
|
let deleted = 0;
|
|
146539
146683
|
for (const d of decisions) {
|
|
146540
146684
|
if (d.action !== "delete") continue;
|
|
146541
|
-
if (import_node_fs8.default.existsSync(
|
|
146685
|
+
if (import_node_fs8.default.existsSync(import_node_path11.default.join(d.dir, LOCK_FILE)) && isWorkdirLive(d.dir)) {
|
|
146542
146686
|
log3(`[gc] \u8DF3\u8FC7 ${d.dir}\uFF1A\u6267\u884C\u524D\u590D\u67E5\u53D1\u73B0\u5DF2\u88AB\u5360\u7528`);
|
|
146543
146687
|
continue;
|
|
146544
146688
|
}
|
|
@@ -146589,12 +146733,12 @@ function startGcLoop(deps) {
|
|
|
146589
146733
|
clearInterval(timer);
|
|
146590
146734
|
};
|
|
146591
146735
|
}
|
|
146592
|
-
var import_node_fs8,
|
|
146736
|
+
var import_node_fs8, import_node_path11;
|
|
146593
146737
|
var init_gc_loop = __esm({
|
|
146594
146738
|
"../adapters/src/_core/gc-loop.ts"() {
|
|
146595
146739
|
"use strict";
|
|
146596
146740
|
import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
146597
|
-
|
|
146741
|
+
import_node_path11 = __toESM(require("node:path"), 1);
|
|
146598
146742
|
init_session_paths();
|
|
146599
146743
|
init_workdir_gc();
|
|
146600
146744
|
}
|
|
@@ -146630,14 +146774,14 @@ var init_src4 = __esm({
|
|
|
146630
146774
|
});
|
|
146631
146775
|
|
|
146632
146776
|
// ../connectors/src/connector-adapter.ts
|
|
146633
|
-
var
|
|
146777
|
+
var import_promises6, import_node_fs9, import_node_os7, import_node_path12, ConnectorAwareAdapter;
|
|
146634
146778
|
var init_connector_adapter = __esm({
|
|
146635
146779
|
"../connectors/src/connector-adapter.ts"() {
|
|
146636
146780
|
"use strict";
|
|
146637
|
-
|
|
146781
|
+
import_promises6 = require("node:fs/promises");
|
|
146638
146782
|
import_node_fs9 = require("node:fs");
|
|
146639
|
-
|
|
146640
|
-
|
|
146783
|
+
import_node_os7 = require("node:os");
|
|
146784
|
+
import_node_path12 = require("node:path");
|
|
146641
146785
|
init_src4();
|
|
146642
146786
|
init_base();
|
|
146643
146787
|
init_prepare_job();
|
|
@@ -146660,11 +146804,11 @@ var init_connector_adapter = __esm({
|
|
|
146660
146804
|
const wrapperPaths = [...prepared.job.wrapperPaths ?? [], ...sentinelWrappers];
|
|
146661
146805
|
let extraEnv = { ...strippedEnv };
|
|
146662
146806
|
if (wrapperPaths.length > 0) {
|
|
146663
|
-
const wrapperBinDir = await (0,
|
|
146664
|
-
await (0,
|
|
146807
|
+
const wrapperBinDir = await (0, import_promises6.mkdtemp)((0, import_node_path12.join)((0, import_node_os7.tmpdir)(), "oasis-wrappers-"));
|
|
146808
|
+
await (0, import_promises6.mkdir)(wrapperBinDir, { recursive: true });
|
|
146665
146809
|
for (const wp of wrapperPaths) {
|
|
146666
|
-
const linkName = (0,
|
|
146667
|
-
await (0,
|
|
146810
|
+
const linkName = (0, import_node_path12.basename)(wp).replace(/\.sh$/, "");
|
|
146811
|
+
await (0, import_promises6.symlink)(wp, (0, import_node_path12.join)(wrapperBinDir, linkName));
|
|
146668
146812
|
}
|
|
146669
146813
|
extraEnv = { ...extraEnv, PATH: [wrapperBinDir, extraEnv["PATH"] ?? ""].filter(Boolean).join(":") };
|
|
146670
146814
|
log("[adapter]", ` connectors injected +${Date.now() - t0}ms wrappers=${wrapperPaths.length}`);
|
|
@@ -149451,12 +149595,12 @@ async function startOasisServer(opts) {
|
|
|
149451
149595
|
const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
|
|
149452
149596
|
if (actorCtx) {
|
|
149453
149597
|
const { mkdtempSync: mkdtempSync5, mkdirSync: mkdirSync21, writeFileSync: writeFileSync13 } = await import("node:fs");
|
|
149454
|
-
const { join:
|
|
149455
|
-
const { tmpdir:
|
|
149456
|
-
const dir = mkdtempSync5(
|
|
149598
|
+
const { join: join31, dirname: dirname24 } = await import("node:path");
|
|
149599
|
+
const { tmpdir: tmpdir9 } = await import("node:os");
|
|
149600
|
+
const dir = mkdtempSync5(join31(tmpdir9(), "oasis-chat-"));
|
|
149457
149601
|
if (actorCtx.config?.prompt) {
|
|
149458
149602
|
for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
149459
|
-
const file =
|
|
149603
|
+
const file = join31(dir, rel);
|
|
149460
149604
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149461
149605
|
writeFileSync13(file, content);
|
|
149462
149606
|
}
|
|
@@ -149468,12 +149612,12 @@ async function startOasisServer(opts) {
|
|
|
149468
149612
|
const s2 = byId.get(id);
|
|
149469
149613
|
return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
|
|
149470
149614
|
});
|
|
149471
|
-
writeFileSync13(
|
|
149615
|
+
writeFileSync13(join31(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
|
|
149472
149616
|
}
|
|
149473
149617
|
if (opts.materializeSkills) {
|
|
149474
149618
|
const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
|
|
149475
149619
|
for (const [rel, content] of Object.entries(skillFiles)) {
|
|
149476
|
-
const file =
|
|
149620
|
+
const file = join31(dir, rel);
|
|
149477
149621
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149478
149622
|
writeFileSync13(file, content);
|
|
149479
149623
|
}
|
|
@@ -149487,7 +149631,7 @@ async function startOasisServer(opts) {
|
|
|
149487
149631
|
const modeNote = c.mode === "oauth" ? "OAuth \xB7 \u51ED\u8BC1\u7531\u5E73\u53F0\u7BA1\u7406\uFF0C\u901A\u8FC7\u5BF9\u5E94 CLI wrapper \u8C03\u7528" : "\u76F4\u63A5\u5199\u5165 \xB7 \u51ED\u8BC1\u5DF2\u6CE8\u5165\u73AF\u5883\u53D8\u91CF";
|
|
149488
149632
|
return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
|
|
149489
149633
|
});
|
|
149490
|
-
writeFileSync13(
|
|
149634
|
+
writeFileSync13(join31(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
|
|
149491
149635
|
}
|
|
149492
149636
|
spawnCwd = dir;
|
|
149493
149637
|
}
|
|
@@ -149728,7 +149872,14 @@ async function startOasisServer(opts) {
|
|
|
149728
149872
|
baseUrl: base,
|
|
149729
149873
|
redirectPath: "/api/connectors/github/app/manifest-callback"
|
|
149730
149874
|
});
|
|
149731
|
-
githubAppPending.put(state, {
|
|
149875
|
+
githubAppPending.put(state, {
|
|
149876
|
+
...actorId ? { actorId } : {},
|
|
149877
|
+
employeeSlug: nameSlug,
|
|
149878
|
+
createdAtMs: Date.now(),
|
|
149879
|
+
// 存下这次选的归属——回调时要拿它跟 GitHub 返回的 owner 比对。
|
|
149880
|
+
wantOwnerKind: kind,
|
|
149881
|
+
...kind === "org" && owner?.login ? { wantOwnerLogin: owner.login } : {}
|
|
149882
|
+
});
|
|
149732
149883
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
149733
149884
|
state,
|
|
149734
149885
|
formAction: manifestFormAction(kind === "org" ? { kind: "org", login: owner.login } : { kind: "user" }, state),
|
|
@@ -149791,6 +149942,14 @@ async function startOasisServer(opts) {
|
|
|
149791
149942
|
}
|
|
149792
149943
|
try {
|
|
149793
149944
|
const conv = await exchangeManifestCode(code);
|
|
149945
|
+
const problem = checkAppOwnership(conv, {
|
|
149946
|
+
...pending.wantOwnerLogin ? { ownerLogin: pending.wantOwnerLogin } : {},
|
|
149947
|
+
...pending.wantOwnerKind ? { ownerKind: pending.wantOwnerKind } : {}
|
|
149948
|
+
});
|
|
149949
|
+
if (problem) {
|
|
149950
|
+
fail(problem.message);
|
|
149951
|
+
return;
|
|
149952
|
+
}
|
|
149794
149953
|
const svc = opts.actors?.service;
|
|
149795
149954
|
if (!svc) throw new Error("actors service unavailable");
|
|
149796
149955
|
const scope = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
@@ -150446,9 +150605,11 @@ var init_memory_registry_store = __esm({
|
|
|
150446
150605
|
// key: ${runtimeId}::${modelId}
|
|
150447
150606
|
connectors = /* @__PURE__ */ new Map();
|
|
150448
150607
|
variables = /* @__PURE__ */ new Map();
|
|
150449
|
-
// key = key::actorId
|
|
150450
|
-
|
|
150451
|
-
|
|
150608
|
+
// key = key::actorId::projectId
|
|
150609
|
+
// 唯一键覆盖三种作用域(ADR 0125:无 environment 维):personal=(key,actorId)、project=(key,projectId)、global=(key)。
|
|
150610
|
+
// 三段拼接后天然互不碰撞(personal 有 actorId 无 projectId,project 反之,global 全空)。
|
|
150611
|
+
_varKey(key, actorId, projectId) {
|
|
150612
|
+
return `${key}::${actorId ?? ""}::${projectId ?? ""}`;
|
|
150452
150613
|
}
|
|
150453
150614
|
skillCatalog = /* @__PURE__ */ new Map();
|
|
150454
150615
|
installedSkills = /* @__PURE__ */ new Map();
|
|
@@ -150581,7 +150742,7 @@ var init_memory_registry_store = __esm({
|
|
|
150581
150742
|
this.skillFiles.delete(skillId);
|
|
150582
150743
|
}
|
|
150583
150744
|
async putVariable(v2) {
|
|
150584
|
-
this.variables.set(this._varKey(v2.key, v2.actorId), { ...v2 });
|
|
150745
|
+
this.variables.set(this._varKey(v2.key, v2.actorId, v2.projectId), { ...v2 });
|
|
150585
150746
|
}
|
|
150586
150747
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
150587
150748
|
const mk = this._varKey(key, actorId);
|
|
@@ -150596,8 +150757,11 @@ var init_memory_registry_store = __esm({
|
|
|
150596
150757
|
if (actorId !== void 0) return all.filter((v2) => v2.scope === "global" || v2.actorId === actorId).map((v2) => ({ ...v2 }));
|
|
150597
150758
|
return all.map((v2) => ({ ...v2 }));
|
|
150598
150759
|
}
|
|
150599
|
-
async
|
|
150600
|
-
this.variables.
|
|
150760
|
+
async resolveProjectVariables(projectId) {
|
|
150761
|
+
return [...this.variables.values()].filter((v2) => v2.scope === "project" && v2.projectId === projectId).map((v2) => ({ ...v2 }));
|
|
150762
|
+
}
|
|
150763
|
+
async deleteVariable(key, actorId, scoping) {
|
|
150764
|
+
this.variables.delete(this._varKey(key, actorId, scoping?.projectId));
|
|
150601
150765
|
}
|
|
150602
150766
|
};
|
|
150603
150767
|
}
|
|
@@ -154721,6 +154885,10 @@ async function sweepSilentSessions(deps) {
|
|
|
154721
154885
|
continue;
|
|
154722
154886
|
}
|
|
154723
154887
|
if (!live.lastEventAt) continue;
|
|
154888
|
+
if (deps.isTraceHealthy && !deps.isTraceHealthy(s2.sessionId)) {
|
|
154889
|
+
deps.log?.(`[liveness] \u8DF3\u8FC7 ${s2.artifactId}\uFF1Atrace \u5199\u5165\u4E0D\u5065\u5EB7\uFF08\u89C2\u6D4B\u964D\u7EA7\uFF09\uFF0C\u4FE1\u606F\u4E0D\u8DB3\u4E0D\u5224\u9759\u9ED8 \u2192 \u4EA4 wallClock \u515C\u5E95`);
|
|
154890
|
+
continue;
|
|
154891
|
+
}
|
|
154724
154892
|
const runtime = { hasInFlight: true, lastSessionEventAt: live.lastEventAt, openToolCall: live.openToolCall };
|
|
154725
154893
|
if (!isRuntimeSilent(runtime, deps.now, deps.silentThresholdMs)) continue;
|
|
154726
154894
|
const ok = await deps.kill(s2.jobKey).catch(() => false);
|
|
@@ -155420,6 +155588,73 @@ var init_recovery_plan = __esm({
|
|
|
155420
155588
|
}
|
|
155421
155589
|
});
|
|
155422
155590
|
|
|
155591
|
+
// ../server/src/domains/trace/resilient-appender.ts
|
|
155592
|
+
var ResilientTraceAppender;
|
|
155593
|
+
var init_resilient_appender = __esm({
|
|
155594
|
+
"../server/src/domains/trace/resilient-appender.ts"() {
|
|
155595
|
+
"use strict";
|
|
155596
|
+
ResilientTraceAppender = class {
|
|
155597
|
+
constructor(opts) {
|
|
155598
|
+
this.opts = opts;
|
|
155599
|
+
this.seq = opts.startSeq ?? 0;
|
|
155600
|
+
}
|
|
155601
|
+
seq;
|
|
155602
|
+
failing = false;
|
|
155603
|
+
/** 当前已成功落库的最大 seq。 */
|
|
155604
|
+
get currentSeq() {
|
|
155605
|
+
return this.seq;
|
|
155606
|
+
}
|
|
155607
|
+
/** 恢复路径:把 seq 对齐到库里已有的最大值(不改健康态)。 */
|
|
155608
|
+
resetSeq(seq) {
|
|
155609
|
+
this.seq = seq;
|
|
155610
|
+
}
|
|
155611
|
+
onSuccess() {
|
|
155612
|
+
this.opts.health?.markHealthy(this.opts.runId);
|
|
155613
|
+
if (this.failing) {
|
|
155614
|
+
this.failing = false;
|
|
155615
|
+
this.opts.onRecover?.();
|
|
155616
|
+
}
|
|
155617
|
+
}
|
|
155618
|
+
onFailure(err) {
|
|
155619
|
+
this.opts.health?.markUnhealthy(this.opts.runId);
|
|
155620
|
+
if (!this.failing) {
|
|
155621
|
+
this.failing = true;
|
|
155622
|
+
this.opts.onError?.(err);
|
|
155623
|
+
}
|
|
155624
|
+
}
|
|
155625
|
+
/**
|
|
155626
|
+
* 追加一批事件(seq 自动连续分配);**成功才推进 seq**。返回是否落库。
|
|
155627
|
+
* 幂等吸收(storage 层)保证:若失败其实是"提交成功但连接抖断",下次同 seq 重投会被吸收、不重复。
|
|
155628
|
+
*/
|
|
155629
|
+
async append(events) {
|
|
155630
|
+
if (events.length === 0) return true;
|
|
155631
|
+
const base = this.seq;
|
|
155632
|
+
const withSeq = events.map((e, i) => ({ ...e, seq: base + i + 1 }));
|
|
155633
|
+
try {
|
|
155634
|
+
await this.opts.store.appendEvents(this.opts.runId, withSeq);
|
|
155635
|
+
this.seq = base + events.length;
|
|
155636
|
+
this.onSuccess();
|
|
155637
|
+
return true;
|
|
155638
|
+
} catch (err) {
|
|
155639
|
+
this.onFailure(err);
|
|
155640
|
+
return false;
|
|
155641
|
+
}
|
|
155642
|
+
}
|
|
155643
|
+
/** 更新 run(心跳 lastProgressAt / 终态 / metadata 等);失败不熄灭事件通道。 */
|
|
155644
|
+
async update(patch) {
|
|
155645
|
+
try {
|
|
155646
|
+
await this.opts.store.updateRun(this.opts.runId, patch);
|
|
155647
|
+
this.onSuccess();
|
|
155648
|
+
return true;
|
|
155649
|
+
} catch (err) {
|
|
155650
|
+
this.onFailure(err);
|
|
155651
|
+
return false;
|
|
155652
|
+
}
|
|
155653
|
+
}
|
|
155654
|
+
};
|
|
155655
|
+
}
|
|
155656
|
+
});
|
|
155657
|
+
|
|
155423
155658
|
// ../server/src/domains/trace/sink.ts
|
|
155424
155659
|
function deriveMessage(payload) {
|
|
155425
155660
|
if (payload && typeof payload === "object") {
|
|
@@ -155429,11 +155664,10 @@ function deriveMessage(payload) {
|
|
|
155429
155664
|
}
|
|
155430
155665
|
return void 0;
|
|
155431
155666
|
}
|
|
155432
|
-
function trajectoryEventToRunEvent(e
|
|
155667
|
+
function trajectoryEventToRunEvent(e) {
|
|
155433
155668
|
const map = KIND_MAP[e.kind] ?? { eventType: "progress", stream: "runtime" };
|
|
155434
155669
|
const message = deriveMessage(e.payload);
|
|
155435
155670
|
return {
|
|
155436
|
-
seq,
|
|
155437
155671
|
eventType: map.eventType,
|
|
155438
155672
|
stream: map.stream,
|
|
155439
155673
|
...message !== void 0 ? { message } : {},
|
|
@@ -155512,6 +155746,7 @@ var KIND_MAP, MODEL_TEXT_LIMIT, TOOL_PREVIEW_LIMIT, PROGRESS_TOUCH_THROTTLE_MS,
|
|
|
155512
155746
|
var init_sink = __esm({
|
|
155513
155747
|
"../server/src/domains/trace/sink.ts"() {
|
|
155514
155748
|
"use strict";
|
|
155749
|
+
init_resilient_appender();
|
|
155515
155750
|
KIND_MAP = {
|
|
155516
155751
|
message: { eventType: "model.output.completed", stream: "model" },
|
|
155517
155752
|
thought: { eventType: "model.output.delta", stream: "model" },
|
|
@@ -155527,12 +155762,23 @@ var init_sink = __esm({
|
|
|
155527
155762
|
store;
|
|
155528
155763
|
runtimeKind;
|
|
155529
155764
|
onError;
|
|
155765
|
+
health;
|
|
155530
155766
|
sessions = /* @__PURE__ */ new Map();
|
|
155531
155767
|
constructor(opts) {
|
|
155532
155768
|
this.store = opts.store;
|
|
155533
155769
|
this.runtimeKind = opts.runtimeKind ?? "custom";
|
|
155534
155770
|
this.onError = opts.onError ?? (() => {
|
|
155535
155771
|
});
|
|
155772
|
+
this.health = opts.health;
|
|
155773
|
+
}
|
|
155774
|
+
/** 为一个 run 造事件通道 appender(seq 两道防线 + 健康度上报都收在这里)。 */
|
|
155775
|
+
makeAppender(runId) {
|
|
155776
|
+
return new ResilientTraceAppender({
|
|
155777
|
+
runId,
|
|
155778
|
+
store: this.store,
|
|
155779
|
+
...this.health ? { health: this.health } : {},
|
|
155780
|
+
onError: (err) => this.onError(err)
|
|
155781
|
+
});
|
|
155536
155782
|
}
|
|
155537
155783
|
runtimeKindFor(session) {
|
|
155538
155784
|
if (this.runtimeKind !== "auto") return this.runtimeKind;
|
|
@@ -155554,7 +155800,7 @@ var init_sink = __esm({
|
|
|
155554
155800
|
begin(session, _bundleFiles) {
|
|
155555
155801
|
const st = {
|
|
155556
155802
|
runId: session.runId,
|
|
155557
|
-
|
|
155803
|
+
appender: this.makeAppender(session.runId),
|
|
155558
155804
|
chain: Promise.resolve(),
|
|
155559
155805
|
openTools: /* @__PURE__ */ new Map(),
|
|
155560
155806
|
// runtimeSessionId:运行时自己的会话号(= 会话工作目录名,也是 --resume 的键)。落账后
|
|
@@ -155588,8 +155834,7 @@ var init_sink = __esm({
|
|
|
155588
155834
|
relation: "triggered_by",
|
|
155589
155835
|
createdAt: session.startedAt
|
|
155590
155836
|
});
|
|
155591
|
-
await
|
|
155592
|
-
seq: ++st.seq,
|
|
155837
|
+
await st.appender.append([{
|
|
155593
155838
|
eventType: "run.started",
|
|
155594
155839
|
stream: "runtime",
|
|
155595
155840
|
message: `${session.action} ${session.artifactId}`
|
|
@@ -155599,7 +155844,7 @@ var init_sink = __esm({
|
|
|
155599
155844
|
recover(session) {
|
|
155600
155845
|
const st = {
|
|
155601
155846
|
runId: session.runId,
|
|
155602
|
-
|
|
155847
|
+
appender: this.makeAppender(session.runId),
|
|
155603
155848
|
chain: Promise.resolve(),
|
|
155604
155849
|
openTools: /* @__PURE__ */ new Map(),
|
|
155605
155850
|
baseMetadata: { bundleManifest: session.bundleManifest, recovered: true },
|
|
@@ -155626,11 +155871,10 @@ var init_sink = __esm({
|
|
|
155626
155871
|
st.baseMetadata = { ...asMetadata(existing.metadata) ?? st.baseMetadata, recovered: true };
|
|
155627
155872
|
}
|
|
155628
155873
|
const events = await this.store.listEvents(session.runId, {});
|
|
155629
|
-
st.
|
|
155874
|
+
st.appender.resetSeq(events.reduce((max, event) => Math.max(max, event.seq), 0));
|
|
155630
155875
|
const recoveredAt = session.recoveredAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
155631
155876
|
const interruptedAt = session.interruptedAt ?? recoveredAt;
|
|
155632
|
-
await
|
|
155633
|
-
seq: ++st.seq,
|
|
155877
|
+
await st.appender.append([{
|
|
155634
155878
|
eventType: "progress",
|
|
155635
155879
|
stream: "system",
|
|
155636
155880
|
level: "warn",
|
|
@@ -155655,11 +155899,11 @@ var init_sink = __esm({
|
|
|
155655
155899
|
const ms = Date.parse(event.ts);
|
|
155656
155900
|
if (!Number.isNaN(ms) && ms - (st.lastProgressTouchMs ?? 0) >= PROGRESS_TOUCH_THROTTLE_MS) {
|
|
155657
155901
|
st.lastProgressTouchMs = ms;
|
|
155658
|
-
await
|
|
155902
|
+
await st.appender.update({ lastProgressAt: event.ts });
|
|
155659
155903
|
}
|
|
155660
155904
|
return;
|
|
155661
155905
|
}
|
|
155662
|
-
await
|
|
155906
|
+
await st.appender.append([trajectoryEventToRunEvent(event)]);
|
|
155663
155907
|
await this.materializeToolCall(st, event);
|
|
155664
155908
|
});
|
|
155665
155909
|
}
|
|
@@ -155710,8 +155954,7 @@ var init_sink = __esm({
|
|
|
155710
155954
|
const captured = this.sessions.get(sessionId);
|
|
155711
155955
|
this.enqueue(sessionId, async (st) => {
|
|
155712
155956
|
for (const ref2 of update.opRefs) {
|
|
155713
|
-
await
|
|
155714
|
-
seq: ++st.seq,
|
|
155957
|
+
await st.appender.append([{
|
|
155715
155958
|
eventType: "oplog.appended",
|
|
155716
155959
|
stream: "oasis",
|
|
155717
155960
|
message: ref2.kind,
|
|
@@ -155725,8 +155968,7 @@ var init_sink = __esm({
|
|
|
155725
155968
|
createdAt: update.exit.at
|
|
155726
155969
|
});
|
|
155727
155970
|
}
|
|
155728
|
-
await
|
|
155729
|
-
seq: ++st.seq,
|
|
155971
|
+
await st.appender.append([{
|
|
155730
155972
|
eventType: "run.finished",
|
|
155731
155973
|
stream: "runtime",
|
|
155732
155974
|
message: `exit code=${update.exit.code ?? "killed"} ops=${update.opRefs.length}`
|
|
@@ -155760,6 +156002,7 @@ var init_sink = __esm({
|
|
|
155760
156002
|
});
|
|
155761
156003
|
if (captured) captured.chain = captured.chain.finally(() => {
|
|
155762
156004
|
this.sessions.delete(sessionId);
|
|
156005
|
+
this.health?.forget(captured.runId);
|
|
155763
156006
|
});
|
|
155764
156007
|
}
|
|
155765
156008
|
};
|
|
@@ -155821,27 +156064,26 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155821
156064
|
live.emit(rest);
|
|
155822
156065
|
}
|
|
155823
156066
|
deps.register();
|
|
155824
|
-
|
|
155825
|
-
|
|
156067
|
+
const appender = new ResilientTraceAppender({
|
|
156068
|
+
runId: plan.runId,
|
|
156069
|
+
store: trace,
|
|
156070
|
+
...deps.traceHealth ? { health: deps.traceHealth } : {},
|
|
156071
|
+
onError: (err) => log3(`[chat-recovery] run ${plan.runId} trace \u5199\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u7184\u706D\uFF09: ${String(err)}`)
|
|
156072
|
+
});
|
|
155826
156073
|
let traceChain = trace.listEvents(plan.runId, {}).then((events) => {
|
|
155827
|
-
|
|
156074
|
+
appender.resetSeq(events.reduce((n, e) => Math.max(n, e.seq), 0));
|
|
155828
156075
|
}).catch((err) => {
|
|
155829
|
-
|
|
155830
|
-
log3(`[chat-recovery] run ${plan.runId} \u8BFB\u4E8B\u4EF6\u5931\u8D25
|
|
156076
|
+
deps.traceHealth?.markUnhealthy(plan.runId);
|
|
156077
|
+
log3(`[chat-recovery] run ${plan.runId} \u8BFB\u4E8B\u4EF6\u5931\u8D25: ${String(err)}`);
|
|
155831
156078
|
});
|
|
155832
156079
|
const enqueueTrace = (step) => {
|
|
155833
|
-
|
|
155834
|
-
|
|
155835
|
-
if (traceEnabled) await step();
|
|
155836
|
-
}).catch((err) => {
|
|
155837
|
-
traceEnabled = false;
|
|
155838
|
-
log3(`[chat-recovery] run ${plan.runId} trace \u7EED\u8D26\u5931\u8D25: ${String(err)}`);
|
|
156080
|
+
traceChain = traceChain.then(step).catch((err) => {
|
|
156081
|
+
log3(`[chat-recovery] run ${plan.runId} trace \u7EED\u8D26\u5F02\u5E38: ${String(err)}`);
|
|
155839
156082
|
});
|
|
155840
156083
|
};
|
|
155841
156084
|
const recoveredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
155842
156085
|
enqueueTrace(async () => {
|
|
155843
|
-
await
|
|
155844
|
-
seq: ++traceSeq,
|
|
156086
|
+
await appender.append([{
|
|
155845
156087
|
eventType: "progress",
|
|
155846
156088
|
stream: "system",
|
|
155847
156089
|
level: "warn",
|
|
@@ -155865,11 +156107,11 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155865
156107
|
const ms = Date.parse(event.ts);
|
|
155866
156108
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
155867
156109
|
lastProgressTouchMs = ms;
|
|
155868
|
-
enqueueTrace(() =>
|
|
156110
|
+
enqueueTrace(() => appender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
155869
156111
|
}
|
|
155870
156112
|
return;
|
|
155871
156113
|
}
|
|
155872
|
-
enqueueTrace(() =>
|
|
156114
|
+
enqueueTrace(() => appender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
155873
156115
|
if (event.kind === "message" && sawTextOutput) return;
|
|
155874
156116
|
const part = chatPartFromTrajectoryEvent(event);
|
|
155875
156117
|
if (part) {
|
|
@@ -155950,14 +156192,13 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155950
156192
|
live.finish(failed ? "error" : "done");
|
|
155951
156193
|
deps.unregister();
|
|
155952
156194
|
enqueueTrace(async () => {
|
|
155953
|
-
await
|
|
155954
|
-
seq: ++traceSeq,
|
|
156195
|
+
await appender.append([{
|
|
155955
156196
|
eventType: "run.finished",
|
|
155956
156197
|
stream: "runtime",
|
|
155957
156198
|
message: `exit code=${info.code ?? "killed"}`,
|
|
155958
156199
|
startedAt: finishedAt
|
|
155959
156200
|
}]);
|
|
155960
|
-
await
|
|
156201
|
+
await appender.update(runTerminalPatch(info, plan.startedAt, finishedAt));
|
|
155961
156202
|
if (info.usage && trace.updateUsageAggregates) {
|
|
155962
156203
|
const run = await trace.getRun(plan.runId);
|
|
155963
156204
|
if (run) void trace.updateUsageAggregates(run).catch(() => void 0);
|
|
@@ -156054,17 +156295,17 @@ async function reconcileChatExitFrame(deps) {
|
|
|
156054
156295
|
}).catch(() => void 0);
|
|
156055
156296
|
try {
|
|
156056
156297
|
const events = await deps.trace.listEvents(row.runId, {});
|
|
156057
|
-
|
|
156058
|
-
|
|
156059
|
-
...stash.frames.filter((frame) => frame.type === "event").map((frame) => frame.event).filter((event) => event.kind !== "system").map((event) => trajectoryEventToRunEvent(event
|
|
156298
|
+
const baseSeq = events.reduce((n, e) => Math.max(n, e.seq), 0);
|
|
156299
|
+
const seqless = [
|
|
156300
|
+
...stash.frames.filter((frame) => frame.type === "event").map((frame) => frame.event).filter((event) => event.kind !== "system").map((event) => trajectoryEventToRunEvent(event)),
|
|
156060
156301
|
{
|
|
156061
|
-
seq: ++traceSeq,
|
|
156062
156302
|
eventType: "run.finished",
|
|
156063
156303
|
stream: "runtime",
|
|
156064
156304
|
message: `exit code=${info.code ?? "killed"}\uFF08serve \u505C\u673A\u7A97\u53E3\u5185\u7ED3\u675F\uFF0C\u8282\u70B9 outbox \u91CD\u53D1\u5BF9\u8D26\uFF09`,
|
|
156065
156305
|
startedAt: finishedAt
|
|
156066
156306
|
}
|
|
156067
|
-
]
|
|
156307
|
+
];
|
|
156308
|
+
await deps.trace.appendEvents(row.runId, seqless.map((e, i) => ({ ...e, seq: baseSeq + i + 1 })));
|
|
156068
156309
|
await deps.trace.updateRun(row.runId, runTerminalPatch(info, run.startedAt, finishedAt));
|
|
156069
156310
|
if (info.usage && deps.trace.updateUsageAggregates) {
|
|
156070
156311
|
const fresh = await deps.trace.getRun(row.runId);
|
|
@@ -156085,6 +156326,7 @@ var init_chat_recovery = __esm({
|
|
|
156085
156326
|
import_node_crypto20 = require("node:crypto");
|
|
156086
156327
|
init_chat_parts();
|
|
156087
156328
|
init_sink();
|
|
156329
|
+
init_resilient_appender();
|
|
156088
156330
|
asObj3 = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
156089
156331
|
partsOf = (parts) => Array.isArray(parts) ? parts.filter((p2) => p2 && typeof p2 === "object" && typeof p2.type === "string") : [];
|
|
156090
156332
|
maxPartSeq = (parts) => parts.reduce((n, p2) => Math.max(n, typeof p2.seq === "number" ? p2.seq : 0), 0);
|
|
@@ -156678,6 +156920,24 @@ var init_skill_fetcher = __esm({
|
|
|
156678
156920
|
});
|
|
156679
156921
|
|
|
156680
156922
|
// ../server/src/domains/actors/service.ts
|
|
156923
|
+
function applyRefDelivery(env, entries, warn = (m2) => console.warn(m2)) {
|
|
156924
|
+
for (const e of entries) {
|
|
156925
|
+
if (!(e.key in env)) continue;
|
|
156926
|
+
const mode = e.deliveryMode;
|
|
156927
|
+
switch (mode) {
|
|
156928
|
+
case "env":
|
|
156929
|
+
break;
|
|
156930
|
+
// 非敏感:明文保持不动
|
|
156931
|
+
case "ref":
|
|
156932
|
+
env[e.key] = makeVarRef(e.key);
|
|
156933
|
+
break;
|
|
156934
|
+
default:
|
|
156935
|
+
delete env[e.key];
|
|
156936
|
+
warn(`[credential] \u672A\u77E5 deliveryMode "${mode}"\uFF08key=${e.key}\uFF09\u2014\u2014\u5DF2\u4ECE env \u5254\u9664\uFF0C\u4FDD\u5B88\u5904\u7406\u4E0D\u6CE8\u5165\u660E\u6587`);
|
|
156937
|
+
break;
|
|
156938
|
+
}
|
|
156939
|
+
}
|
|
156940
|
+
}
|
|
156681
156941
|
function computeEffectiveEntries(config2, connections, connectors) {
|
|
156682
156942
|
const globalConnected = new Set(connectors.filter((c) => c.status === "connected").map((c) => c.id));
|
|
156683
156943
|
const record6 = new Map(connections.map((c) => [c.connectorId, c.enabled]));
|
|
@@ -156709,6 +156969,7 @@ var init_service3 = __esm({
|
|
|
156709
156969
|
init_skill_fetcher();
|
|
156710
156970
|
init_identity();
|
|
156711
156971
|
init_src5();
|
|
156972
|
+
init_src();
|
|
156712
156973
|
REDACTED_MARKER = "[REDACTED]";
|
|
156713
156974
|
ActorsService = class {
|
|
156714
156975
|
constructor(opts) {
|
|
@@ -157362,8 +157623,11 @@ ${input.description}
|
|
|
157362
157623
|
key: v2.key,
|
|
157363
157624
|
scope: v2.scope,
|
|
157364
157625
|
...v2.actorId !== void 0 ? { actorId: v2.actorId } : {},
|
|
157626
|
+
...v2.projectId !== void 0 ? { projectId: v2.projectId } : {},
|
|
157365
157627
|
...v2.connectorId !== void 0 ? { connectorId: v2.connectorId } : {},
|
|
157366
157628
|
...v2.overrides !== void 0 ? { overrides: v2.overrides } : {},
|
|
157629
|
+
// 缺省 "env"(存量行为不变,敏感项需显式选 "ref",ADR §4.4 / 待确认 3)
|
|
157630
|
+
deliveryMode: v2.deliveryMode ?? "env",
|
|
157367
157631
|
valueEncrypted: v2.encrypted === false ? `plain:${v2.value}` : this.encrypt(v2.value),
|
|
157368
157632
|
updatedAt: this.now()
|
|
157369
157633
|
});
|
|
@@ -157399,8 +157663,11 @@ ${input.description}
|
|
|
157399
157663
|
key: r.key,
|
|
157400
157664
|
scope: r.scope,
|
|
157401
157665
|
...r.actorId !== void 0 ? { actorId: r.actorId } : {},
|
|
157666
|
+
...r.projectId !== void 0 ? { projectId: r.projectId } : {},
|
|
157402
157667
|
...r.connectorId !== void 0 ? { connectorId: r.connectorId } : {},
|
|
157403
157668
|
...r.overrides !== void 0 ? { overrides: r.overrides } : {},
|
|
157669
|
+
deliveryMode: r.deliveryMode ?? "env",
|
|
157670
|
+
// 缺省视为 env(ADR §4.4;存量行读侧统一回填)
|
|
157404
157671
|
encrypted: !isPlain,
|
|
157405
157672
|
maskedValue: isPlain ? r.valueEncrypted.slice(6) : mask(this.decrypt(r.valueEncrypted)),
|
|
157406
157673
|
updatedAt: r.updatedAt
|
|
@@ -157424,8 +157691,13 @@ ${input.description}
|
|
|
157424
157691
|
}
|
|
157425
157692
|
return this.revealVariable(key, void 0);
|
|
157426
157693
|
}
|
|
157427
|
-
deleteVariable(key, actorId) {
|
|
157428
|
-
return this.opts.store.deleteVariable(key, actorId);
|
|
157694
|
+
deleteVariable(key, actorId, scoping) {
|
|
157695
|
+
return this.opts.store.deleteVariable(key, actorId, scoping);
|
|
157696
|
+
}
|
|
157697
|
+
/** 该 key 是否在**任一**作用域存在(reveal 判权失败时区分 not_found / no_permission,仅 server 侧审计用;§4.5.2)。 */
|
|
157698
|
+
async hasVariableKey(key) {
|
|
157699
|
+
const rows = await this.opts.store.listVariables();
|
|
157700
|
+
return rows.some((r) => r.key === key);
|
|
157429
157701
|
}
|
|
157430
157702
|
async resolveActorEnv(actorId) {
|
|
157431
157703
|
const cfg = await this.opts.store.latestConfig(actorId);
|
|
@@ -157455,6 +157727,64 @@ ${input.description}
|
|
|
157455
157727
|
}
|
|
157456
157728
|
return env;
|
|
157457
157729
|
}
|
|
157730
|
+
/** 密文 → 明文(与 resolveActorEnv 内联的 decode 同规则:plain: 前缀直读,否则 AES 解密)。 */
|
|
157731
|
+
decodeCiphertext(ct) {
|
|
157732
|
+
return ct.startsWith("plain:") ? ct.slice(6) : this.decrypt(ct);
|
|
157733
|
+
}
|
|
157734
|
+
/**
|
|
157735
|
+
* ADR 凭据保险库 §4.3 / ADR 0125:按「项目」解析 project 变量为明文条目(含 deliveryMode)。
|
|
157736
|
+
* store 未实现 resolveProjectVariables(旧实现)时返回空——调用方跳过 project 层。
|
|
157737
|
+
*/
|
|
157738
|
+
async resolveProjectVariables(projectId) {
|
|
157739
|
+
if (!this.opts.store.resolveProjectVariables) return [];
|
|
157740
|
+
const rows = await this.opts.store.resolveProjectVariables(projectId);
|
|
157741
|
+
return rows.map((r) => ({ key: r.key, value: this.decodeCiphertext(r.valueEncrypted), deliveryMode: r.deliveryMode ?? "env" }));
|
|
157742
|
+
}
|
|
157743
|
+
/**
|
|
157744
|
+
* ADR 凭据保险库 §4.3 / ADR 0125:派单/reveal 用的**合并后**变量条目(明文 + deliveryMode)。
|
|
157745
|
+
* 优先级低→高:global < project < personal(同 key 时高层覆盖低层,personal 最优先)。
|
|
157746
|
+
* 连接器门禁与 resolveActorEnv 同源(未启用的连接器变量不注入)。
|
|
157747
|
+
* - `opts.projectId` 给出时才叠加 project 层;缺省 = 只有 personal+global(存量行为)。
|
|
157748
|
+
*/
|
|
157749
|
+
async resolveActorProvisionEntries(actorId, opts) {
|
|
157750
|
+
const cfg = await this.opts.store.latestConfig(actorId);
|
|
157751
|
+
const enabledConnectors = await this.effectiveEnabledConnectors(actorId, cfg);
|
|
157752
|
+
if (opts?.refreshConnectors !== false) {
|
|
157753
|
+
await refreshEnabledConnectorCredentials(
|
|
157754
|
+
this,
|
|
157755
|
+
createAllConnectors(),
|
|
157756
|
+
actorId,
|
|
157757
|
+
(slug6) => enabledConnectors.has(slug6)
|
|
157758
|
+
);
|
|
157759
|
+
}
|
|
157760
|
+
const rows = await this.opts.store.listVariables(actorId);
|
|
157761
|
+
const projectRows = opts?.projectId && this.opts.store.resolveProjectVariables ? await this.opts.store.resolveProjectVariables(opts.projectId) : [];
|
|
157762
|
+
const merged = /* @__PURE__ */ new Map();
|
|
157763
|
+
const gated = (row) => !row.connectorId || enabledConnectors.has(row.connectorId);
|
|
157764
|
+
const put = (row) => {
|
|
157765
|
+
if (!gated(row)) return;
|
|
157766
|
+
merged.set(row.key, { key: row.key, value: this.decodeCiphertext(row.valueEncrypted), deliveryMode: row.deliveryMode ?? "env" });
|
|
157767
|
+
};
|
|
157768
|
+
for (const row of rows) {
|
|
157769
|
+
if (row.scope === "global" && !row.actorId) put(row);
|
|
157770
|
+
}
|
|
157771
|
+
for (const row of projectRows) {
|
|
157772
|
+
if (row.scope === "project") put(row);
|
|
157773
|
+
}
|
|
157774
|
+
for (const row of rows) {
|
|
157775
|
+
if (row.scope === "personal" && (!row.actorId || row.actorId === actorId)) put(row);
|
|
157776
|
+
}
|
|
157777
|
+
return [...merged.values()];
|
|
157778
|
+
}
|
|
157779
|
+
/**
|
|
157780
|
+
* ADR 凭据保险库 §4.5.1:reveal 的判权即「能否被解析」——该 key 通过 §4.3 合并顺序对本 caller
|
|
157781
|
+
* 能得出值即可读,返回明文;否则返回 null(缺 key / 无权,统一由路由映射成 403,不区分)。
|
|
157782
|
+
*/
|
|
157783
|
+
async resolveRevealValue(actorId, key, opts) {
|
|
157784
|
+
const entries = await this.resolveActorProvisionEntries(actorId, { ...opts, refreshConnectors: false });
|
|
157785
|
+
const hit = entries.find((e) => e.key === key);
|
|
157786
|
+
return hit ? { value: hit.value } : null;
|
|
157787
|
+
}
|
|
157458
157788
|
encrypt(plain) {
|
|
157459
157789
|
const iv = (0, import_node_crypto22.randomBytes)(12);
|
|
157460
157790
|
const cipher = (0, import_node_crypto22.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
@@ -158463,7 +158793,7 @@ var init_skill_materializer = __esm({
|
|
|
158463
158793
|
|
|
158464
158794
|
// ../server/src/governance/connector-skills.ts
|
|
158465
158795
|
function connectorSkillsDir(dataDir, connectorId) {
|
|
158466
|
-
return (0,
|
|
158796
|
+
return (0, import_node_path13.join)(dataDir, "connector-skills", connectorId);
|
|
158467
158797
|
}
|
|
158468
158798
|
function parseConnectorSkillId(id) {
|
|
158469
158799
|
if (!id.startsWith("connector:")) return null;
|
|
@@ -158473,17 +158803,17 @@ function parseConnectorSkillId(id) {
|
|
|
158473
158803
|
return { connectorId: rest.slice(0, i), slug: rest.slice(i + 1) };
|
|
158474
158804
|
}
|
|
158475
158805
|
async function collect(root, dir, out) {
|
|
158476
|
-
for (const e of await (0,
|
|
158477
|
-
const abs = (0,
|
|
158806
|
+
for (const e of await (0, import_promises7.readdir)(dir, { withFileTypes: true })) {
|
|
158807
|
+
const abs = (0, import_node_path13.join)(dir, e.name);
|
|
158478
158808
|
if (e.isDirectory()) await collect(root, abs, out);
|
|
158479
|
-
else if (e.isFile()) out[(0,
|
|
158809
|
+
else if (e.isFile()) out[(0, import_node_path13.relative)(root, abs).split(/[\\/]/).join("/")] = await (0, import_promises7.readFile)(abs, "utf8");
|
|
158480
158810
|
}
|
|
158481
158811
|
}
|
|
158482
158812
|
async function readLocalPack(dataDir, connectorId) {
|
|
158483
158813
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158484
158814
|
let slugs;
|
|
158485
158815
|
try {
|
|
158486
|
-
slugs = (await (0,
|
|
158816
|
+
slugs = (await (0, import_promises7.readdir)(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
158487
158817
|
} catch {
|
|
158488
158818
|
return [];
|
|
158489
158819
|
}
|
|
@@ -158491,7 +158821,7 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158491
158821
|
for (const slug6 of slugs) {
|
|
158492
158822
|
const files = {};
|
|
158493
158823
|
try {
|
|
158494
|
-
await collect((0,
|
|
158824
|
+
await collect((0, import_node_path13.join)(root, slug6), (0, import_node_path13.join)(root, slug6), files);
|
|
158495
158825
|
} catch {
|
|
158496
158826
|
continue;
|
|
158497
158827
|
}
|
|
@@ -158507,17 +158837,17 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158507
158837
|
async function writePack(dataDir, connectorId, pack) {
|
|
158508
158838
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158509
158839
|
const tmp = `${root}.tmp`;
|
|
158510
|
-
await (0,
|
|
158840
|
+
await (0, import_promises7.rm)(tmp, { recursive: true, force: true });
|
|
158511
158841
|
for (const s2 of pack) {
|
|
158512
158842
|
for (const [rel, content] of Object.entries(s2.files)) {
|
|
158513
|
-
const abs = (0,
|
|
158514
|
-
await (0,
|
|
158515
|
-
await (0,
|
|
158843
|
+
const abs = (0, import_node_path13.join)(tmp, s2.slug, rel);
|
|
158844
|
+
await (0, import_promises7.mkdir)((0, import_node_path13.dirname)(abs), { recursive: true });
|
|
158845
|
+
await (0, import_promises7.writeFile)(abs, content, "utf8");
|
|
158516
158846
|
}
|
|
158517
158847
|
}
|
|
158518
|
-
await (0,
|
|
158519
|
-
await (0,
|
|
158520
|
-
await (0,
|
|
158848
|
+
await (0, import_promises7.rm)(root, { recursive: true, force: true });
|
|
158849
|
+
await (0, import_promises7.mkdir)((0, import_node_path13.dirname)(root), { recursive: true });
|
|
158850
|
+
await (0, import_promises7.rename)(tmp, root);
|
|
158521
158851
|
}
|
|
158522
158852
|
function packMatches(local, remote) {
|
|
158523
158853
|
if (local.length !== remote.length) return false;
|
|
@@ -158544,18 +158874,21 @@ async function syncConnectorSkills(args) {
|
|
|
158544
158874
|
log3(`[connector-skills] ${args.connectorId}\uFF1A\u5DF2\u4ECE\u5382\u5546\u540C\u6B65 ${fresh.length} \u4E2A\u6280\u80FD`);
|
|
158545
158875
|
return { skills: fresh, outcome: "fetched" };
|
|
158546
158876
|
}
|
|
158547
|
-
var
|
|
158877
|
+
var import_promises7, import_node_path13, toId;
|
|
158548
158878
|
var init_connector_skills = __esm({
|
|
158549
158879
|
"../server/src/governance/connector-skills.ts"() {
|
|
158550
158880
|
"use strict";
|
|
158551
|
-
|
|
158552
|
-
|
|
158881
|
+
import_promises7 = require("node:fs/promises");
|
|
158882
|
+
import_node_path13 = require("node:path");
|
|
158553
158883
|
init_src5();
|
|
158554
158884
|
toId = (connectorId, slug6) => `connector:${connectorId}/${slug6}`;
|
|
158555
158885
|
}
|
|
158556
158886
|
});
|
|
158557
158887
|
|
|
158558
158888
|
// ../server/src/domains/actors/routes.ts
|
|
158889
|
+
function isKnownRevealSource(source) {
|
|
158890
|
+
return CREDENTIAL_REVEAL_SOURCES.has(source) || source.startsWith("agent-skill:");
|
|
158891
|
+
}
|
|
158559
158892
|
function positionsFromPayload(body) {
|
|
158560
158893
|
if (!body) return void 0;
|
|
158561
158894
|
if (Object.prototype.hasOwnProperty.call(body, "roles")) {
|
|
@@ -158588,6 +158921,8 @@ function actorApiRecord(actor) {
|
|
|
158588
158921
|
}
|
|
158589
158922
|
function actorsDomain(opts) {
|
|
158590
158923
|
const { resolveCtx } = opts;
|
|
158924
|
+
const revealLimits = opts.credentialRevealLimits ?? { perSession: 200, perSessionPerKey: 20 };
|
|
158925
|
+
const revealLimiter = new RevealRateLimiter(revealLimits.perSession, revealLimits.perSessionPerKey);
|
|
158591
158926
|
return (router) => {
|
|
158592
158927
|
router.get("/api/actors", async (req) => {
|
|
158593
158928
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
@@ -158827,11 +159162,23 @@ function actorsDomain(opts) {
|
|
|
158827
159162
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158828
159163
|
const b2 = req.body;
|
|
158829
159164
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159165
|
+
const scope = b2.scope ?? "global";
|
|
159166
|
+
if (scope === "project" && !b2.projectId) {
|
|
159167
|
+
throw new ApiError(400, "BAD_REQUEST", "scope=project \u5FC5\u987B\u63D0\u4F9B projectId");
|
|
159168
|
+
}
|
|
159169
|
+
if (scope === "project" && opts.projectExists && !await opts.projectExists(b2.projectId)) {
|
|
159170
|
+
throw new ApiError(400, "BAD_REQUEST", `\u9879\u76EE\u4E0D\u5B58\u5728\uFF1A${b2.projectId}\uFF08scope=project \u53D8\u91CF\u7684 projectId \u5FC5\u987B\u662F\u771F\u5B9E\u9879\u76EE\uFF09`);
|
|
159171
|
+
}
|
|
159172
|
+
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
|
|
159173
|
+
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
|
|
159174
|
+
}
|
|
158830
159175
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158831
159176
|
await service.putVariable({
|
|
158832
159177
|
key: b2.key,
|
|
158833
159178
|
value: b2.value,
|
|
158834
|
-
scope
|
|
159179
|
+
scope,
|
|
159180
|
+
...scope === "project" ? { projectId: b2.projectId } : {},
|
|
159181
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158835
159182
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158836
159183
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158837
159184
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158840,7 +159187,12 @@ function actorsDomain(opts) {
|
|
|
158840
159187
|
});
|
|
158841
159188
|
router.delete("/api/variables/:key", async (req) => {
|
|
158842
159189
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158843
|
-
|
|
159190
|
+
const projectId = req.query.get("projectId") ?? void 0;
|
|
159191
|
+
await service.deleteVariable(
|
|
159192
|
+
req.params.key,
|
|
159193
|
+
void 0,
|
|
159194
|
+
projectId ? { projectId } : void 0
|
|
159195
|
+
);
|
|
158844
159196
|
return { status: 200, body: { ok: true } };
|
|
158845
159197
|
});
|
|
158846
159198
|
router.get("/api/actors/:id/variables", async (req) => {
|
|
@@ -158852,6 +159204,9 @@ function actorsDomain(opts) {
|
|
|
158852
159204
|
const actorId = req.params.id;
|
|
158853
159205
|
const b2 = req.body;
|
|
158854
159206
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159207
|
+
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
|
|
159208
|
+
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
|
|
159209
|
+
}
|
|
158855
159210
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158856
159211
|
if (b2.connectorId === void 0) {
|
|
158857
159212
|
const existing = await service.listVariables(actorId);
|
|
@@ -158869,6 +159224,7 @@ function actorsDomain(opts) {
|
|
|
158869
159224
|
value: b2.value,
|
|
158870
159225
|
actorId,
|
|
158871
159226
|
scope: "personal",
|
|
159227
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158872
159228
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158873
159229
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158874
159230
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158880,6 +159236,51 @@ function actorsDomain(opts) {
|
|
|
158880
159236
|
await service.deleteVariable(req.params.key, req.params.id);
|
|
158881
159237
|
return { status: 200, body: { ok: true } };
|
|
158882
159238
|
});
|
|
159239
|
+
router.post("/api/variables/reveal", async (req) => {
|
|
159240
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
159241
|
+
const b2 = req.body;
|
|
159242
|
+
const rawKey = typeof b2?.key === "string" ? b2.key.trim() : "";
|
|
159243
|
+
if (!rawKey) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159244
|
+
const key = parseVarRef(rawKey) ?? rawKey;
|
|
159245
|
+
const source = typeof b2?.source === "string" && b2.source.trim() || "agent-cli";
|
|
159246
|
+
if (!isKnownRevealSource(source)) throw new ApiError(400, "BAD_REQUEST", `\u672A\u8BC6\u522B\u7684 source\u300C${source}\u300D\uFF08\xA74.5.4\uFF1A\u53EA\u63A5\u53D7\u8BC6\u522B\u503C\uFF09`);
|
|
159247
|
+
const actor = req.auth.actor;
|
|
159248
|
+
const artifactId = req.auth.dispatch?.artifactId;
|
|
159249
|
+
const sessionId = req.auth.dispatch?.sessionId;
|
|
159250
|
+
const now = Date.now();
|
|
159251
|
+
const timestamp = new Date(now).toISOString();
|
|
159252
|
+
const sessionKey = sessionId ?? `${actor}::${artifactId ?? "no-artifact"}`;
|
|
159253
|
+
const dispatchFields = { ...sessionId ? { sessionId } : {}, ...artifactId ? { artifactId } : {} };
|
|
159254
|
+
const throttled = revealLimiter.check(sessionKey, key, now);
|
|
159255
|
+
if (throttled) {
|
|
159256
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_throttled", actor, variableKey: key, source, timestamp, scope: throttled, ...dispatchFields });
|
|
159257
|
+
return { status: 429, body: { code: "throttled", key, scope: throttled } };
|
|
159258
|
+
}
|
|
159259
|
+
const scope = artifactId && opts.resolveDispatchScope ? await opts.resolveDispatchScope(artifactId) : {};
|
|
159260
|
+
const resolved = await service.resolveRevealValue(actor, key, scope);
|
|
159261
|
+
if (!resolved) {
|
|
159262
|
+
const reason = await service.hasVariableKey(key) ? "no_permission" : "not_found";
|
|
159263
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_denied", actor, variableKey: key, source, timestamp, reason, ...dispatchFields });
|
|
159264
|
+
return { status: 403, body: { code: "denied", key } };
|
|
159265
|
+
}
|
|
159266
|
+
await opts.credentialAudit?.({ kind: "credential_reveal", actor, variableKey: key, source, timestamp, ...dispatchFields });
|
|
159267
|
+
return { status: 200, body: { value: resolved.value } };
|
|
159268
|
+
});
|
|
159269
|
+
router.get("/api/variables/reveal-audit", async (req) => {
|
|
159270
|
+
if (!opts.readCredentialAudit) return { status: 501, body: { error: "credential audit reader \u672A\u914D\u7F6E" } };
|
|
159271
|
+
const actor = req.query.get("actor") ?? void 0;
|
|
159272
|
+
const key = req.query.get("key") ?? void 0;
|
|
159273
|
+
const kind = req.query.get("kind") ?? void 0;
|
|
159274
|
+
const limitRaw = req.query.get("limit");
|
|
159275
|
+
const limit = limitRaw ? Math.min(Math.max(parseInt(limitRaw, 10) || 50, 1), 500) : 50;
|
|
159276
|
+
const items = await opts.readCredentialAudit({
|
|
159277
|
+
...actor ? { actor } : {},
|
|
159278
|
+
...key ? { key } : {},
|
|
159279
|
+
...kind ? { kind } : {},
|
|
159280
|
+
limit
|
|
159281
|
+
});
|
|
159282
|
+
return { status: 200, body: { items } };
|
|
159283
|
+
});
|
|
158883
159284
|
router.get("/api/skills/market", async (req) => {
|
|
158884
159285
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158885
159286
|
const [catalog, installed] = await Promise.all([
|
|
@@ -159038,6 +159439,18 @@ function actorsDomain(opts) {
|
|
|
159038
159439
|
const results = await opts.refreshConnectorSkills();
|
|
159039
159440
|
return { status: 200, body: { results } };
|
|
159040
159441
|
});
|
|
159442
|
+
router.get("/api/connector-credentials", async (req) => {
|
|
159443
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
159444
|
+
const actorId = req.auth.actor;
|
|
159445
|
+
const entries = await service.resolveActorProvisionEntries(actorId);
|
|
159446
|
+
const vars = {};
|
|
159447
|
+
for (const e of entries) vars[e.key] = e.value;
|
|
159448
|
+
const connectorCreds = collectAllConnectorCredentials({
|
|
159449
|
+
vars,
|
|
159450
|
+
actorName: vars["GIT_AUTHOR_NAME"] ?? actorId.split(":").pop() ?? "oasis-agent"
|
|
159451
|
+
});
|
|
159452
|
+
return { status: 200, body: { connectorCreds } };
|
|
159453
|
+
});
|
|
159041
159454
|
router.get("/api/skill-cache/manifest", async (req) => {
|
|
159042
159455
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
159043
159456
|
const builtins = opts.getBuiltinSkills?.() ?? [];
|
|
@@ -159316,12 +159729,15 @@ function actorsDomain(opts) {
|
|
|
159316
159729
|
});
|
|
159317
159730
|
};
|
|
159318
159731
|
}
|
|
159732
|
+
var CREDENTIAL_REVEAL_SOURCES, RevealRateLimiter;
|
|
159319
159733
|
var init_routes = __esm({
|
|
159320
159734
|
"../server/src/domains/actors/routes.ts"() {
|
|
159321
159735
|
"use strict";
|
|
159322
159736
|
init_src();
|
|
159323
159737
|
init_src2();
|
|
159324
159738
|
init_router();
|
|
159739
|
+
init_src();
|
|
159740
|
+
init_src5();
|
|
159325
159741
|
init_memory();
|
|
159326
159742
|
init_skill_fetcher();
|
|
159327
159743
|
init_stats();
|
|
@@ -159330,6 +159746,44 @@ var init_routes = __esm({
|
|
|
159330
159746
|
init_image_upload();
|
|
159331
159747
|
init_skill_materializer();
|
|
159332
159748
|
init_connector_skills();
|
|
159749
|
+
CREDENTIAL_REVEAL_SOURCES = /* @__PURE__ */ new Set(["agent-cli", "smoke-test", "oasis-internal"]);
|
|
159750
|
+
RevealRateLimiter = class {
|
|
159751
|
+
constructor(perSession, perSessionPerKey, ttlMs = 2 * 60 * 6e4) {
|
|
159752
|
+
this.perSession = perSession;
|
|
159753
|
+
this.perSessionPerKey = perSessionPerKey;
|
|
159754
|
+
this.ttlMs = ttlMs;
|
|
159755
|
+
}
|
|
159756
|
+
sessionCounts = /* @__PURE__ */ new Map();
|
|
159757
|
+
sessionKeyCounts = /* @__PURE__ */ new Map();
|
|
159758
|
+
/** 记一次尝试;返回命中的限流档(若超限)或 null(放行)。 */
|
|
159759
|
+
check(sessionKey, varKey, now) {
|
|
159760
|
+
this.prune(now);
|
|
159761
|
+
const sk = `${sessionKey}::${varKey}`;
|
|
159762
|
+
const s2 = this.sessionCounts.get(sessionKey) ?? { count: 0, last: now };
|
|
159763
|
+
const k2 = this.sessionKeyCounts.get(sk) ?? { count: 0, last: now };
|
|
159764
|
+
if (k2.count >= this.perSessionPerKey) {
|
|
159765
|
+
k2.last = now;
|
|
159766
|
+
this.sessionKeyCounts.set(sk, k2);
|
|
159767
|
+
return "session_key";
|
|
159768
|
+
}
|
|
159769
|
+
if (s2.count >= this.perSession) {
|
|
159770
|
+
s2.last = now;
|
|
159771
|
+
this.sessionCounts.set(sessionKey, s2);
|
|
159772
|
+
return "session";
|
|
159773
|
+
}
|
|
159774
|
+
s2.count += 1;
|
|
159775
|
+
s2.last = now;
|
|
159776
|
+
this.sessionCounts.set(sessionKey, s2);
|
|
159777
|
+
k2.count += 1;
|
|
159778
|
+
k2.last = now;
|
|
159779
|
+
this.sessionKeyCounts.set(sk, k2);
|
|
159780
|
+
return null;
|
|
159781
|
+
}
|
|
159782
|
+
prune(now) {
|
|
159783
|
+
for (const [key, v2] of this.sessionCounts) if (now - v2.last > this.ttlMs) this.sessionCounts.delete(key);
|
|
159784
|
+
for (const [key, v2] of this.sessionKeyCounts) if (now - v2.last > this.ttlMs) this.sessionKeyCounts.delete(key);
|
|
159785
|
+
}
|
|
159786
|
+
};
|
|
159333
159787
|
}
|
|
159334
159788
|
});
|
|
159335
159789
|
|
|
@@ -159428,7 +159882,7 @@ function createActorsDomain(opts) {
|
|
|
159428
159882
|
return {
|
|
159429
159883
|
service: defaultCtx.service,
|
|
159430
159884
|
resolveCtx,
|
|
159431
|
-
register: actorsDomain({ resolveCtx, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {} })
|
|
159885
|
+
register: actorsDomain({ resolveCtx, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {}, ...opts.resolveDispatchScope ? { resolveDispatchScope: opts.resolveDispatchScope } : {}, ...opts.projectExists ? { projectExists: opts.projectExists } : {}, ...opts.credentialAudit ? { credentialAudit: opts.credentialAudit } : {}, ...opts.readCredentialAudit ? { readCredentialAudit: opts.readCredentialAudit } : {}, ...opts.credentialRevealLimits ? { credentialRevealLimits: opts.credentialRevealLimits } : {} })
|
|
159432
159886
|
};
|
|
159433
159887
|
}
|
|
159434
159888
|
var import_node_crypto24;
|
|
@@ -161857,10 +162311,10 @@ function nodesDomain(deps) {
|
|
|
161857
162311
|
}
|
|
161858
162312
|
}
|
|
161859
162313
|
try {
|
|
161860
|
-
const here = (0,
|
|
162314
|
+
const here = (0, import_node_path14.dirname)((0, import_node_url4.fileURLToPath)(__esm_import_meta_url));
|
|
161861
162315
|
for (const rel of ["../../../../node-daemon/package.json", "../../../../../node-daemon/package.json"]) {
|
|
161862
162316
|
try {
|
|
161863
|
-
const raw = (0, import_node_fs11.readFileSync)((0,
|
|
162317
|
+
const raw = (0, import_node_fs11.readFileSync)((0, import_node_path14.resolve)(here, rel), "utf8");
|
|
161864
162318
|
const pkg = JSON.parse(raw);
|
|
161865
162319
|
if (pkg.version) return { version: pkg.version, source: "monorepo" };
|
|
161866
162320
|
} catch {
|
|
@@ -162172,14 +162626,14 @@ function nodesDomain(deps) {
|
|
|
162172
162626
|
});
|
|
162173
162627
|
};
|
|
162174
162628
|
}
|
|
162175
|
-
var import_node_crypto26, import_node_fs11, import_node_url4,
|
|
162629
|
+
var import_node_crypto26, import_node_fs11, import_node_url4, import_node_path14;
|
|
162176
162630
|
var init_routes5 = __esm({
|
|
162177
162631
|
"../server/src/domains/nodes/routes.ts"() {
|
|
162178
162632
|
"use strict";
|
|
162179
162633
|
import_node_crypto26 = require("node:crypto");
|
|
162180
162634
|
import_node_fs11 = require("node:fs");
|
|
162181
162635
|
import_node_url4 = require("node:url");
|
|
162182
|
-
|
|
162636
|
+
import_node_path14 = require("node:path");
|
|
162183
162637
|
init_src4();
|
|
162184
162638
|
init_connect_script();
|
|
162185
162639
|
init_node_health();
|
|
@@ -163336,6 +163790,7 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163336
163790
|
const runtimeEmployees = /* @__PURE__ */ new Map();
|
|
163337
163791
|
const runtimeInstanceKind = /* @__PURE__ */ new Map();
|
|
163338
163792
|
const runtimeHostnames = input.runtimeHostnames ?? /* @__PURE__ */ new Map();
|
|
163793
|
+
const runtimeNodeNames = input.runtimeNodeNames ?? /* @__PURE__ */ new Map();
|
|
163339
163794
|
for (const run of input.runs) {
|
|
163340
163795
|
const usage = usageOf(run);
|
|
163341
163796
|
if (!usage) {
|
|
@@ -163466,11 +163921,27 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163466
163921
|
(e) => e.share,
|
|
163467
163922
|
(e, s2) => ({ ...e, share: s2 })
|
|
163468
163923
|
);
|
|
163924
|
+
function parseNodeId(rtKey) {
|
|
163925
|
+
const parts = rtKey.split(":");
|
|
163926
|
+
if (parts.length >= 3 && parts[0] === "runtime") return parts[1];
|
|
163927
|
+
return "";
|
|
163928
|
+
}
|
|
163929
|
+
function resolveDisplayName(rtKey, kind) {
|
|
163930
|
+
const nodeId = parseNodeId(rtKey);
|
|
163931
|
+
if (nodeId) {
|
|
163932
|
+
const name = runtimeNodeNames.get(nodeId);
|
|
163933
|
+
if (name) return name;
|
|
163934
|
+
}
|
|
163935
|
+
const h = runtimeHostnames.get(rtKey);
|
|
163936
|
+
if (h) return h;
|
|
163937
|
+
if (nodeId) return nodeId;
|
|
163938
|
+
return kind;
|
|
163939
|
+
}
|
|
163469
163940
|
function resolveHostname(rtKey, kind) {
|
|
163470
163941
|
const h = runtimeHostnames.get(rtKey);
|
|
163471
163942
|
if (h) return h;
|
|
163472
|
-
const
|
|
163473
|
-
if (
|
|
163943
|
+
const nodeId = parseNodeId(rtKey);
|
|
163944
|
+
if (nodeId) return nodeId;
|
|
163474
163945
|
return kind;
|
|
163475
163946
|
}
|
|
163476
163947
|
const runtimeRows = normalizeShares(
|
|
@@ -163498,6 +163969,8 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163498
163969
|
);
|
|
163499
163970
|
return {
|
|
163500
163971
|
runtimeInstanceId: rtKey,
|
|
163972
|
+
nodeId: parseNodeId(rtKey),
|
|
163973
|
+
displayName: resolveDisplayName(rtKey, kind),
|
|
163501
163974
|
hostname: resolveHostname(rtKey, kind),
|
|
163502
163975
|
runtimeKind: kind,
|
|
163503
163976
|
usage,
|
|
@@ -163535,12 +164008,12 @@ function nameKey(name) {
|
|
|
163535
164008
|
function cleanName(name) {
|
|
163536
164009
|
return name.trim().replace(/\s+/g, " ");
|
|
163537
164010
|
}
|
|
163538
|
-
var import_node_fs12,
|
|
164011
|
+
var import_node_fs12, import_node_path15, import_node_crypto27, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
163539
164012
|
var init_tags = __esm({
|
|
163540
164013
|
"../server/src/domains/collab/tags.ts"() {
|
|
163541
164014
|
"use strict";
|
|
163542
164015
|
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
163543
|
-
|
|
164016
|
+
import_node_path15 = __toESM(require("node:path"), 1);
|
|
163544
164017
|
import_node_crypto27 = __toESM(require("node:crypto"), 1);
|
|
163545
164018
|
SEP = "::";
|
|
163546
164019
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
@@ -163626,7 +164099,7 @@ var init_tags = __esm({
|
|
|
163626
164099
|
}
|
|
163627
164100
|
persist() {
|
|
163628
164101
|
try {
|
|
163629
|
-
import_node_fs12.default.mkdirSync(
|
|
164102
|
+
import_node_fs12.default.mkdirSync(import_node_path15.default.dirname(this.file), { recursive: true });
|
|
163630
164103
|
const tmp = `${this.file}.tmp`;
|
|
163631
164104
|
import_node_fs12.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
163632
164105
|
import_node_fs12.default.renameSync(tmp, this.file);
|
|
@@ -163767,17 +164240,22 @@ function collabDomain(opts) {
|
|
|
163767
164240
|
return { status: 400, body: { error: { code: "bad_request", message: "timeZone \u65E0\u6548" } } };
|
|
163768
164241
|
}
|
|
163769
164242
|
const { kernel } = await resolveCtx(req.auth.companyId);
|
|
163770
|
-
const [runs, runtimeRecords] = await Promise.all([
|
|
164243
|
+
const [runs, runtimeRecords, nodeRecords] = await Promise.all([
|
|
163771
164244
|
opts.trace.listUsageRuns({ from, to }),
|
|
163772
|
-
opts.listRuntimes ? opts.listRuntimes().catch(() => []) : Promise.resolve([])
|
|
164245
|
+
opts.listRuntimes ? opts.listRuntimes().catch(() => []) : Promise.resolve([]),
|
|
164246
|
+
opts.listNodes ? opts.listNodes().catch(() => []) : Promise.resolve([])
|
|
163773
164247
|
]);
|
|
163774
164248
|
const runtimeHostnames = /* @__PURE__ */ new Map();
|
|
163775
164249
|
for (const rt of runtimeRecords) {
|
|
163776
164250
|
if (rt.id && rt.hostname) runtimeHostnames.set(rt.id, rt.hostname);
|
|
163777
164251
|
}
|
|
164252
|
+
const runtimeNodeNames = /* @__PURE__ */ new Map();
|
|
164253
|
+
for (const n of nodeRecords) {
|
|
164254
|
+
if (n.id && n.name) runtimeNodeNames.set(n.id, n.name);
|
|
164255
|
+
}
|
|
163778
164256
|
return {
|
|
163779
164257
|
status: 200,
|
|
163780
|
-
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames })
|
|
164258
|
+
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames, runtimeNodeNames })
|
|
163781
164259
|
};
|
|
163782
164260
|
});
|
|
163783
164261
|
router.get("/api/workorders", async (req) => {
|
|
@@ -164577,10 +165055,10 @@ function tokenType(p2) {
|
|
|
164577
165055
|
function parseOtlpMetricsUsage(body) {
|
|
164578
165056
|
const req = body;
|
|
164579
165057
|
const out = [];
|
|
164580
|
-
for (const
|
|
164581
|
-
const runId = attrString(
|
|
165058
|
+
for (const rm5 of req.resourceMetrics ?? []) {
|
|
165059
|
+
const runId = attrString(rm5.resource?.attributes, "oasis.run_id");
|
|
164582
165060
|
if (!runId) continue;
|
|
164583
|
-
const actorId = attrString(
|
|
165061
|
+
const actorId = attrString(rm5.resource?.attributes, "oasis.actor_id");
|
|
164584
165062
|
let input = 0;
|
|
164585
165063
|
let output = 0;
|
|
164586
165064
|
let cacheRead = 0;
|
|
@@ -164588,7 +165066,7 @@ function parseOtlpMetricsUsage(body) {
|
|
|
164588
165066
|
let costUsd = 0;
|
|
164589
165067
|
let sawToken = false;
|
|
164590
165068
|
let sawCost = false;
|
|
164591
|
-
for (const sm of
|
|
165069
|
+
for (const sm of rm5.scopeMetrics ?? []) {
|
|
164592
165070
|
for (const m2 of sm.metrics ?? []) {
|
|
164593
165071
|
const name = (m2.name ?? "").toLowerCase();
|
|
164594
165072
|
const points = m2.sum?.dataPoints ?? m2.gauge?.dataPoints ?? [];
|
|
@@ -164964,6 +165442,30 @@ var init_routes6 = __esm({
|
|
|
164964
165442
|
}
|
|
164965
165443
|
});
|
|
164966
165444
|
|
|
165445
|
+
// ../server/src/domains/trace/trace-health.ts
|
|
165446
|
+
function createTraceHealth() {
|
|
165447
|
+
const unhealthy = /* @__PURE__ */ new Set();
|
|
165448
|
+
return {
|
|
165449
|
+
markUnhealthy(runId) {
|
|
165450
|
+
unhealthy.add(runId);
|
|
165451
|
+
},
|
|
165452
|
+
markHealthy(runId) {
|
|
165453
|
+
unhealthy.delete(runId);
|
|
165454
|
+
},
|
|
165455
|
+
isHealthy(runId) {
|
|
165456
|
+
return !unhealthy.has(runId);
|
|
165457
|
+
},
|
|
165458
|
+
forget(runId) {
|
|
165459
|
+
unhealthy.delete(runId);
|
|
165460
|
+
}
|
|
165461
|
+
};
|
|
165462
|
+
}
|
|
165463
|
+
var init_trace_health = __esm({
|
|
165464
|
+
"../server/src/domains/trace/trace-health.ts"() {
|
|
165465
|
+
"use strict";
|
|
165466
|
+
}
|
|
165467
|
+
});
|
|
165468
|
+
|
|
164967
165469
|
// ../server/src/domains/trace/index.ts
|
|
164968
165470
|
function createTraceDomain(opts) {
|
|
164969
165471
|
const service = new TraceService({ store: opts.store });
|
|
@@ -164978,6 +165480,8 @@ var init_trace2 = __esm({
|
|
|
164978
165480
|
init_routes6();
|
|
164979
165481
|
init_sink();
|
|
164980
165482
|
init_chat_parts();
|
|
165483
|
+
init_trace_health();
|
|
165484
|
+
init_resilient_appender();
|
|
164981
165485
|
}
|
|
164982
165486
|
});
|
|
164983
165487
|
|
|
@@ -167049,12 +167553,12 @@ function normalize(patch) {
|
|
|
167049
167553
|
...reviewRoles !== void 0 ? { reviewRoles: [...new Set(reviewRoles.map((r) => r.trim()).filter(Boolean))] } : {}
|
|
167050
167554
|
};
|
|
167051
167555
|
}
|
|
167052
|
-
var import_node_fs13,
|
|
167556
|
+
var import_node_fs13, import_node_path16, SEP2, keyOf2, prefixOf2, MemoryPlaybookOverrideStore, FilePlaybookOverrideStore;
|
|
167053
167557
|
var init_overrides = __esm({
|
|
167054
167558
|
"../server/src/domains/playbooks/overrides.ts"() {
|
|
167055
167559
|
"use strict";
|
|
167056
167560
|
import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
167057
|
-
|
|
167561
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
167058
167562
|
SEP2 = "::";
|
|
167059
167563
|
keyOf2 = (companyId, ref2, nodeKey) => `${companyId}${SEP2}${ref2}${SEP2}${nodeKey}`;
|
|
167060
167564
|
prefixOf2 = (companyId, ref2) => `${companyId}${SEP2}${ref2}${SEP2}`;
|
|
@@ -167093,7 +167597,7 @@ var init_overrides = __esm({
|
|
|
167093
167597
|
}
|
|
167094
167598
|
persist() {
|
|
167095
167599
|
try {
|
|
167096
|
-
import_node_fs13.default.mkdirSync(
|
|
167600
|
+
import_node_fs13.default.mkdirSync(import_node_path16.default.dirname(this.file), { recursive: true });
|
|
167097
167601
|
const tmp = `${this.file}.tmp`;
|
|
167098
167602
|
import_node_fs13.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167099
167603
|
import_node_fs13.default.renameSync(tmp, this.file);
|
|
@@ -167532,12 +168036,12 @@ var init_daemon_adapter = __esm({
|
|
|
167532
168036
|
});
|
|
167533
168037
|
|
|
167534
168038
|
// ../server/src/side-map.ts
|
|
167535
|
-
var import_node_fs14,
|
|
168039
|
+
var import_node_fs14, import_node_path17, FileSideMap;
|
|
167536
168040
|
var init_side_map = __esm({
|
|
167537
168041
|
"../server/src/side-map.ts"() {
|
|
167538
168042
|
"use strict";
|
|
167539
168043
|
import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
167540
|
-
|
|
168044
|
+
import_node_path17 = __toESM(require("node:path"), 1);
|
|
167541
168045
|
FileSideMap = class {
|
|
167542
168046
|
constructor(file) {
|
|
167543
168047
|
this.file = file;
|
|
@@ -167564,7 +168068,7 @@ var init_side_map = __esm({
|
|
|
167564
168068
|
}
|
|
167565
168069
|
persist() {
|
|
167566
168070
|
try {
|
|
167567
|
-
import_node_fs14.default.mkdirSync(
|
|
168071
|
+
import_node_fs14.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
|
|
167568
168072
|
const tmp = `${this.file}.tmp`;
|
|
167569
168073
|
import_node_fs14.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167570
168074
|
import_node_fs14.default.renameSync(tmp, this.file);
|
|
@@ -169020,26 +169524,26 @@ ${ctx.nodeFault}
|
|
|
169020
169524
|
|
|
169021
169525
|
// ../server/src/governance/builtin-skills.ts
|
|
169022
169526
|
async function collectDir(root, dir, out) {
|
|
169023
|
-
const entries = await (0,
|
|
169527
|
+
const entries = await (0, import_promises8.readdir)(dir, { withFileTypes: true });
|
|
169024
169528
|
for (const e of entries) {
|
|
169025
|
-
const abs = (0,
|
|
169529
|
+
const abs = (0, import_node_path18.join)(dir, e.name);
|
|
169026
169530
|
if (e.isDirectory()) {
|
|
169027
169531
|
await collectDir(root, abs, out);
|
|
169028
169532
|
} else if (e.isFile()) {
|
|
169029
|
-
const info = await (0,
|
|
169533
|
+
const info = await (0, import_promises8.stat)(abs);
|
|
169030
169534
|
if (info.size > MAX_FILE_BYTES3) {
|
|
169031
169535
|
console.warn(`[builtin-skills] skip oversized file (${info.size}B): ${abs}`);
|
|
169032
169536
|
continue;
|
|
169033
169537
|
}
|
|
169034
|
-
const rel = (0,
|
|
169035
|
-
out[rel] = await (0,
|
|
169538
|
+
const rel = (0, import_node_path18.relative)(root, abs).split(/[\\/]/).join("/");
|
|
169539
|
+
out[rel] = await (0, import_promises8.readFile)(abs, "utf8");
|
|
169036
169540
|
}
|
|
169037
169541
|
}
|
|
169038
169542
|
}
|
|
169039
169543
|
async function loadBuiltinSkills(skillsDir) {
|
|
169040
169544
|
let dirents;
|
|
169041
169545
|
try {
|
|
169042
|
-
dirents = await (0,
|
|
169546
|
+
dirents = await (0, import_promises8.readdir)(skillsDir, { withFileTypes: true });
|
|
169043
169547
|
} catch {
|
|
169044
169548
|
return [];
|
|
169045
169549
|
}
|
|
@@ -169047,7 +169551,7 @@ async function loadBuiltinSkills(skillsDir) {
|
|
|
169047
169551
|
for (const d of dirents) {
|
|
169048
169552
|
if (!d.isDirectory()) continue;
|
|
169049
169553
|
const slug6 = d.name;
|
|
169050
|
-
const skillDir = (0,
|
|
169554
|
+
const skillDir = (0, import_node_path18.join)(skillsDir, slug6);
|
|
169051
169555
|
const files = {};
|
|
169052
169556
|
try {
|
|
169053
169557
|
await collectDir(skillDir, skillDir, files);
|
|
@@ -169075,12 +169579,12 @@ function materializeBuiltinSkills(builtins, skillsDirPrefix) {
|
|
|
169075
169579
|
}
|
|
169076
169580
|
return out;
|
|
169077
169581
|
}
|
|
169078
|
-
var
|
|
169582
|
+
var import_promises8, import_node_path18, MAX_FILE_BYTES3;
|
|
169079
169583
|
var init_builtin_skills = __esm({
|
|
169080
169584
|
"../server/src/governance/builtin-skills.ts"() {
|
|
169081
169585
|
"use strict";
|
|
169082
|
-
|
|
169083
|
-
|
|
169586
|
+
import_promises8 = require("node:fs/promises");
|
|
169587
|
+
import_node_path18 = require("node:path");
|
|
169084
169588
|
init_skill_fetcher();
|
|
169085
169589
|
init_skill_materializer();
|
|
169086
169590
|
MAX_FILE_BYTES3 = 1 << 20;
|
|
@@ -174572,6 +175076,21 @@ var init_postgres = __esm({
|
|
|
174572
175076
|
});
|
|
174573
175077
|
|
|
174574
175078
|
// ../storage/src/postgres-registry.ts
|
|
175079
|
+
function rowToVariable(row) {
|
|
175080
|
+
return {
|
|
175081
|
+
key: row.key,
|
|
175082
|
+
scope: row.scope === "connector" ? "global" : row.scope,
|
|
175083
|
+
...row.actor_id !== null && row.actor_id !== void 0 ? { actorId: row.actor_id } : {},
|
|
175084
|
+
...row.project_id !== null && row.project_id !== void 0 ? { projectId: row.project_id } : {},
|
|
175085
|
+
...row.connector_id !== null && row.connector_id !== void 0 ? { connectorId: row.connector_id } : {},
|
|
175086
|
+
...row.overrides !== null && row.overrides !== void 0 ? { overrides: row.overrides } : {},
|
|
175087
|
+
// 保留库里存的原始 delivery_mode(含未来 broker/wrapper 档,annotation d7456d5e Req3)——
|
|
175088
|
+
// **不塌成 env**,否则未知档位读回来变明文;仅 null/空回填 "env"(存量行)。派单侧按未知档保守处理。
|
|
175089
|
+
deliveryMode: typeof row.delivery_mode === "string" && row.delivery_mode ? row.delivery_mode : "env",
|
|
175090
|
+
valueEncrypted: row.value_encrypted,
|
|
175091
|
+
updatedAt: new Date(row.updated_at).toISOString()
|
|
175092
|
+
};
|
|
175093
|
+
}
|
|
174575
175094
|
var ident4, PostgresRegistryStore, rowToActor, rowToConfig;
|
|
174576
175095
|
var init_postgres_registry = __esm({
|
|
174577
175096
|
"../storage/src/postgres-registry.ts"() {
|
|
@@ -174703,9 +175222,21 @@ var init_postgres_registry = __esm({
|
|
|
174703
175222
|
value_encrypted text NOT NULL,
|
|
174704
175223
|
updated_at timestamptz NOT NULL
|
|
174705
175224
|
)`);
|
|
174706
|
-
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS "${s2}_variables_key_actor_uq" ON "${s2}".variables (key, COALESCE(actor_id, ''))`);
|
|
174707
175225
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS overrides text`);
|
|
174708
175226
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS actor_id text`);
|
|
175227
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS project_id text`);
|
|
175228
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS environment text`);
|
|
175229
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS delivery_mode text`);
|
|
175230
|
+
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_key_actor_uq"`);
|
|
175231
|
+
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_scope_uq"`);
|
|
175232
|
+
await pool.query(`
|
|
175233
|
+
DELETE FROM "${s2}".variables v
|
|
175234
|
+
WHERE v.ctid NOT IN (
|
|
175235
|
+
SELECT DISTINCT ON (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) ctid
|
|
175236
|
+
FROM "${s2}".variables
|
|
175237
|
+
ORDER BY key, COALESCE(actor_id, ''), COALESCE(project_id, ''), updated_at DESC, ctid DESC
|
|
175238
|
+
)`);
|
|
175239
|
+
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS "${s2}_variables_scope_uq_v2" ON "${s2}".variables (key, COALESCE(actor_id, ''), COALESCE(project_id, ''))`);
|
|
174709
175240
|
await pool.query(`
|
|
174710
175241
|
CREATE TABLE IF NOT EXISTS "${s2}".runtime_configs (
|
|
174711
175242
|
runtime_id text PRIMARY KEY,
|
|
@@ -175149,27 +175680,36 @@ var init_postgres_registry = __esm({
|
|
|
175149
175680
|
}
|
|
175150
175681
|
/* ---------- 变量 ---------- */
|
|
175151
175682
|
async putVariable(v2) {
|
|
175152
|
-
const aid = v2.actorId ?? null;
|
|
175153
175683
|
await this.pool.query(
|
|
175154
|
-
`INSERT INTO ${this.s}.variables (key, scope, actor_id, connector_id, overrides, value_encrypted, updated_at)
|
|
175155
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7)
|
|
175156
|
-
ON CONFLICT (key, COALESCE(actor_id, '')) DO UPDATE
|
|
175157
|
-
SET scope=$2, actor_id=$3,
|
|
175158
|
-
[
|
|
175684
|
+
`INSERT INTO ${this.s}.variables (key, scope, actor_id, project_id, connector_id, overrides, delivery_mode, value_encrypted, updated_at)
|
|
175685
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
175686
|
+
ON CONFLICT (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) DO UPDATE
|
|
175687
|
+
SET scope=$2, actor_id=$3, project_id=$4, connector_id=$5, overrides=$6, delivery_mode=$7, value_encrypted=$8, updated_at=$9`,
|
|
175688
|
+
[
|
|
175689
|
+
v2.key,
|
|
175690
|
+
v2.scope,
|
|
175691
|
+
v2.actorId ?? null,
|
|
175692
|
+
v2.projectId ?? null,
|
|
175693
|
+
v2.connectorId ?? null,
|
|
175694
|
+
v2.overrides ?? null,
|
|
175695
|
+
v2.deliveryMode ?? null,
|
|
175696
|
+
v2.valueEncrypted,
|
|
175697
|
+
v2.updatedAt
|
|
175698
|
+
]
|
|
175159
175699
|
);
|
|
175160
175700
|
}
|
|
175161
175701
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
175162
175702
|
const aid = actorId ?? null;
|
|
175163
175703
|
await this.pool.query(
|
|
175164
175704
|
`UPDATE ${this.s}.variables SET value_encrypted=$3, updated_at=$4
|
|
175165
|
-
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')`,
|
|
175705
|
+
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'') AND COALESCE(project_id,'')=''`,
|
|
175166
175706
|
[key, aid, valueEncrypted, updatedAt]
|
|
175167
175707
|
);
|
|
175168
175708
|
}
|
|
175169
175709
|
async getVariableCiphertext(key, actorId) {
|
|
175170
175710
|
const aid = actorId ?? null;
|
|
175171
175711
|
const r = await this.pool.query(
|
|
175172
|
-
`SELECT value_encrypted FROM ${this.s}.variables WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')`,
|
|
175712
|
+
`SELECT value_encrypted FROM ${this.s}.variables WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'') AND COALESCE(project_id,'')=''`,
|
|
175173
175713
|
[key, aid]
|
|
175174
175714
|
);
|
|
175175
175715
|
return r.rows[0]?.value_encrypted ?? null;
|
|
@@ -175184,21 +175724,21 @@ var init_postgres_registry = __esm({
|
|
|
175184
175724
|
} else {
|
|
175185
175725
|
r = await this.pool.query(`SELECT * FROM ${this.s}.variables ORDER BY key`);
|
|
175186
175726
|
}
|
|
175187
|
-
return r.rows.map((row) => (
|
|
175188
|
-
key: row.key,
|
|
175189
|
-
scope: row.scope === "connector" ? "global" : row.scope,
|
|
175190
|
-
...row.actor_id !== null && row.actor_id !== void 0 ? { actorId: row.actor_id } : {},
|
|
175191
|
-
...row.connector_id !== null ? { connectorId: row.connector_id } : {},
|
|
175192
|
-
...row.overrides !== null ? { overrides: row.overrides } : {},
|
|
175193
|
-
valueEncrypted: row.value_encrypted,
|
|
175194
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
175195
|
-
}));
|
|
175727
|
+
return r.rows.map((row) => rowToVariable(row));
|
|
175196
175728
|
}
|
|
175197
|
-
async
|
|
175198
|
-
const
|
|
175729
|
+
async resolveProjectVariables(projectId) {
|
|
175730
|
+
const r = await this.pool.query(
|
|
175731
|
+
`SELECT * FROM ${this.s}.variables WHERE scope='project' AND project_id=$1 ORDER BY key`,
|
|
175732
|
+
[projectId]
|
|
175733
|
+
);
|
|
175734
|
+
return r.rows.map((row) => rowToVariable(row));
|
|
175735
|
+
}
|
|
175736
|
+
async deleteVariable(key, actorId, scoping) {
|
|
175199
175737
|
await this.pool.query(
|
|
175200
|
-
`DELETE FROM ${this.s}.variables
|
|
175201
|
-
|
|
175738
|
+
`DELETE FROM ${this.s}.variables
|
|
175739
|
+
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')
|
|
175740
|
+
AND COALESCE(project_id,'')=COALESCE($3::text,'')`,
|
|
175741
|
+
[key, actorId ?? null, scoping?.projectId ?? null]
|
|
175202
175742
|
);
|
|
175203
175743
|
}
|
|
175204
175744
|
};
|
|
@@ -176017,6 +176557,7 @@ var init_postgres_projects = __esm({
|
|
|
176017
176557
|
work_order_id text PRIMARY KEY,
|
|
176018
176558
|
project_id text NOT NULL
|
|
176019
176559
|
)`);
|
|
176560
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".workspace_bindings ADD COLUMN IF NOT EXISTS environment text`);
|
|
176020
176561
|
await pool.query(`
|
|
176021
176562
|
CREATE TABLE IF NOT EXISTS "${s2}".workspace_dispatch_hold (
|
|
176022
176563
|
work_order_id text PRIMARY KEY
|
|
@@ -176886,6 +177427,38 @@ var init_postgres_control_plane = __esm({
|
|
|
176886
177427
|
}
|
|
176887
177428
|
});
|
|
176888
177429
|
|
|
177430
|
+
// ../storage/src/pg-sanitize.ts
|
|
177431
|
+
function hasPgUnstorable(s2) {
|
|
177432
|
+
return new RegExp(PG_UNSTORABLE_SOURCE).test(s2);
|
|
177433
|
+
}
|
|
177434
|
+
function scrubPgString(v2) {
|
|
177435
|
+
return typeof v2 === "string" ? v2.replace(new RegExp(PG_UNSTORABLE_SOURCE, "g"), REPLACEMENT) : v2;
|
|
177436
|
+
}
|
|
177437
|
+
function scrubPgJson(v2) {
|
|
177438
|
+
const re = new RegExp(PG_UNSTORABLE_SOURCE, "g");
|
|
177439
|
+
const walk = (x2) => {
|
|
177440
|
+
if (typeof x2 === "string") return x2.replace(re, REPLACEMENT);
|
|
177441
|
+
if (Array.isArray(x2)) return x2.map(walk);
|
|
177442
|
+
if (x2 && typeof x2 === "object") {
|
|
177443
|
+
const out = {};
|
|
177444
|
+
for (const [k2, val] of Object.entries(x2)) {
|
|
177445
|
+
out[k2.replace(re, REPLACEMENT)] = walk(val);
|
|
177446
|
+
}
|
|
177447
|
+
return out;
|
|
177448
|
+
}
|
|
177449
|
+
return x2;
|
|
177450
|
+
};
|
|
177451
|
+
return walk(v2);
|
|
177452
|
+
}
|
|
177453
|
+
var REPLACEMENT, PG_UNSTORABLE_SOURCE;
|
|
177454
|
+
var init_pg_sanitize = __esm({
|
|
177455
|
+
"../storage/src/pg-sanitize.ts"() {
|
|
177456
|
+
"use strict";
|
|
177457
|
+
REPLACEMENT = "\uFFFD";
|
|
177458
|
+
PG_UNSTORABLE_SOURCE = "\\u0000|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]";
|
|
177459
|
+
}
|
|
177460
|
+
});
|
|
177461
|
+
|
|
176889
177462
|
// ../storage/src/postgres-trace.ts
|
|
176890
177463
|
var ident9, PostgresTraceStore, rowToRun, rowToEvent2, rowToToolCall, rowToArtifact2;
|
|
176891
177464
|
var init_postgres_trace = __esm({
|
|
@@ -176893,6 +177466,7 @@ var init_postgres_trace = __esm({
|
|
|
176893
177466
|
"use strict";
|
|
176894
177467
|
init_esm2();
|
|
176895
177468
|
init_src();
|
|
177469
|
+
init_pg_sanitize();
|
|
176896
177470
|
ident9 = (s2) => {
|
|
176897
177471
|
if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
|
|
176898
177472
|
return s2;
|
|
@@ -177153,12 +177727,12 @@ var init_postgres_trace = __esm({
|
|
|
177153
177727
|
run.exitCode,
|
|
177154
177728
|
run.exitReason,
|
|
177155
177729
|
run.errorCode,
|
|
177156
|
-
run.errorMessage,
|
|
177730
|
+
scrubPgString(run.errorMessage),
|
|
177157
177731
|
run.usage === null ? null : JSON.stringify(run.usage),
|
|
177158
177732
|
run.effectiveModel,
|
|
177159
177733
|
run.modelSource,
|
|
177160
177734
|
run.transcriptRef,
|
|
177161
|
-
JSON.stringify(run.metadata),
|
|
177735
|
+
JSON.stringify(scrubPgJson(run.metadata)),
|
|
177162
177736
|
run.createdAt,
|
|
177163
177737
|
run.updatedAt
|
|
177164
177738
|
]
|
|
@@ -177201,7 +177775,7 @@ var init_postgres_trace = __esm({
|
|
|
177201
177775
|
for (const [key, spec] of Object.entries(_PostgresTraceStore.RUN_COLS)) {
|
|
177202
177776
|
if (!(key in patch)) continue;
|
|
177203
177777
|
const v2 = patch[key];
|
|
177204
|
-
args.push(spec.json ? v2 == null ? null : JSON.stringify(v2) : v2 ?? null);
|
|
177778
|
+
args.push(spec.json ? v2 == null ? null : JSON.stringify(scrubPgJson(v2)) : scrubPgString(v2 ?? null));
|
|
177205
177779
|
sets.push(spec.json ? `${spec.col}=$${args.length}::jsonb` : `${spec.col}=$${args.length}`);
|
|
177206
177780
|
}
|
|
177207
177781
|
args.push(this.now());
|
|
@@ -177340,8 +177914,8 @@ var init_postgres_trace = __esm({
|
|
|
177340
177914
|
stream,
|
|
177341
177915
|
level,
|
|
177342
177916
|
inp.color ?? null,
|
|
177343
|
-
inp.message ?? null,
|
|
177344
|
-
JSON.stringify(payload),
|
|
177917
|
+
scrubPgString(inp.message ?? null),
|
|
177918
|
+
JSON.stringify(scrubPgJson(payload)),
|
|
177345
177919
|
inp.blobRef ?? null,
|
|
177346
177920
|
inp.spanId ?? null,
|
|
177347
177921
|
inp.parentSpanId ?? null,
|
|
@@ -177416,11 +177990,11 @@ var init_postgres_trace = __esm({
|
|
|
177416
177990
|
c.durationMs ?? null,
|
|
177417
177991
|
c.inputRef ?? null,
|
|
177418
177992
|
c.outputRef ?? null,
|
|
177419
|
-
c.inputPreview ?? null,
|
|
177420
|
-
c.outputPreview ?? null,
|
|
177993
|
+
scrubPgString(c.inputPreview ?? null),
|
|
177994
|
+
scrubPgString(c.outputPreview ?? null),
|
|
177421
177995
|
c.errorCode ?? null,
|
|
177422
|
-
c.errorMessage ?? null,
|
|
177423
|
-
JSON.stringify(c.metadata ?? {})
|
|
177996
|
+
scrubPgString(c.errorMessage ?? null),
|
|
177997
|
+
JSON.stringify(scrubPgJson(c.metadata ?? {}))
|
|
177424
177998
|
]
|
|
177425
177999
|
);
|
|
177426
178000
|
}
|
|
@@ -177465,12 +178039,12 @@ var init_postgres_trace = __esm({
|
|
|
177465
178039
|
a.id,
|
|
177466
178040
|
a.runId,
|
|
177467
178041
|
a.kind,
|
|
177468
|
-
a.name,
|
|
178042
|
+
scrubPgString(a.name),
|
|
177469
178043
|
a.contentType ?? null,
|
|
177470
178044
|
a.size ?? null,
|
|
177471
178045
|
a.blobRef,
|
|
177472
178046
|
a.createdAt,
|
|
177473
|
-
JSON.stringify(a.metadata ?? {})
|
|
178047
|
+
JSON.stringify(scrubPgJson(a.metadata ?? {}))
|
|
177474
178048
|
]
|
|
177475
178049
|
);
|
|
177476
178050
|
}
|
|
@@ -179182,7 +179756,10 @@ __export(src_exports, {
|
|
|
179182
179756
|
PostgresTraceStore: () => PostgresTraceStore,
|
|
179183
179757
|
PostgresTypeRegistryStore: () => PostgresTypeRegistryStore,
|
|
179184
179758
|
backfillTypeRegistryFromFile: () => backfillTypeRegistryFromFile,
|
|
179185
|
-
createPgPool: () => createPgPool
|
|
179759
|
+
createPgPool: () => createPgPool,
|
|
179760
|
+
hasPgUnstorable: () => hasPgUnstorable,
|
|
179761
|
+
scrubPgJson: () => scrubPgJson,
|
|
179762
|
+
scrubPgString: () => scrubPgString
|
|
179186
179763
|
});
|
|
179187
179764
|
var init_src8 = __esm({
|
|
179188
179765
|
"../storage/src/index.ts"() {
|
|
@@ -179195,6 +179772,7 @@ var init_src8 = __esm({
|
|
|
179195
179772
|
init_pool();
|
|
179196
179773
|
init_postgres_control_plane();
|
|
179197
179774
|
init_postgres_trace();
|
|
179775
|
+
init_pg_sanitize();
|
|
179198
179776
|
init_postgres_automations();
|
|
179199
179777
|
init_postgres_chat_sessions();
|
|
179200
179778
|
init_postgres_nodes();
|
|
@@ -179594,15 +180172,18 @@ function splitIdentityFiles3(prompt) {
|
|
|
179594
180172
|
}
|
|
179595
180173
|
return out;
|
|
179596
180174
|
}
|
|
179597
|
-
async function buildActorProvision(service, actorId) {
|
|
179598
|
-
const
|
|
179599
|
-
const
|
|
180175
|
+
async function buildActorProvision(service, actorId, scope) {
|
|
180176
|
+
const entries = await service.resolveActorProvisionEntries(actorId, scope);
|
|
180177
|
+
const raw = {};
|
|
180178
|
+
for (const e of entries) raw[e.key] = e.value;
|
|
179600
180179
|
const provision = await buildConnectorProvision({
|
|
179601
180180
|
vars: raw,
|
|
179602
180181
|
actorName: raw["GIT_AUTHOR_NAME"] ?? actorId.split(":").pop() ?? "oasis-agent"
|
|
179603
180182
|
});
|
|
180183
|
+
const env = { ...raw };
|
|
179604
180184
|
for (const k2 of provision.sensitiveVars) delete env[k2];
|
|
179605
180185
|
for (const [k2, v2] of Object.entries(provision.envOverrides)) env[k2] = v2;
|
|
180186
|
+
applyRefDelivery(env, entries);
|
|
179606
180187
|
return {
|
|
179607
180188
|
env,
|
|
179608
180189
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
@@ -179828,6 +180409,45 @@ async function startServe(opts) {
|
|
|
179828
180409
|
});
|
|
179829
180410
|
for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.target, timestamp: record6.timestamp });
|
|
179830
180411
|
};
|
|
180412
|
+
const credentialAudit = (record6) => {
|
|
180413
|
+
fs29.appendFile(registryAuditFile, JSON.stringify(record6) + "\n", () => {
|
|
180414
|
+
});
|
|
180415
|
+
for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.variableKey, timestamp: record6.timestamp });
|
|
180416
|
+
};
|
|
180417
|
+
const readCredentialAudit = async (filter) => {
|
|
180418
|
+
let raw;
|
|
180419
|
+
try {
|
|
180420
|
+
raw = await fs29.promises.readFile(registryAuditFile, "utf8");
|
|
180421
|
+
} catch {
|
|
180422
|
+
return [];
|
|
180423
|
+
}
|
|
180424
|
+
const out = [];
|
|
180425
|
+
for (const line of raw.split("\n")) {
|
|
180426
|
+
if (!line.trim()) continue;
|
|
180427
|
+
let rec;
|
|
180428
|
+
try {
|
|
180429
|
+
rec = JSON.parse(line);
|
|
180430
|
+
} catch {
|
|
180431
|
+
continue;
|
|
180432
|
+
}
|
|
180433
|
+
if (typeof rec.kind !== "string" || !rec.kind.startsWith("credential_reveal")) continue;
|
|
180434
|
+
if (filter.actor && rec.actor !== filter.actor) continue;
|
|
180435
|
+
if (filter.key && rec.variableKey !== filter.key) continue;
|
|
180436
|
+
if (filter.kind && rec.kind !== filter.kind) continue;
|
|
180437
|
+
out.push(rec);
|
|
180438
|
+
}
|
|
180439
|
+
out.reverse();
|
|
180440
|
+
return typeof filter.limit === "number" ? out.slice(0, filter.limit) : out;
|
|
180441
|
+
};
|
|
180442
|
+
const resolveDispatchScope = async (artifactId) => {
|
|
180443
|
+
const ws = kernel.model.artifacts.get(artifactId)?.workspace;
|
|
180444
|
+
if (!ws) return {};
|
|
180445
|
+
const binding = await artifactStateStore.getWorkspaceBinding(ws);
|
|
180446
|
+
if (!binding) return {};
|
|
180447
|
+
return {
|
|
180448
|
+
...binding.projectId ? { projectId: binding.projectId } : {}
|
|
180449
|
+
};
|
|
180450
|
+
};
|
|
179831
180451
|
await syncRegistryRolesToKernel(registryStore, kernel);
|
|
179832
180452
|
let builtinSkills = [];
|
|
179833
180453
|
let connectorSkills = [];
|
|
@@ -179844,6 +180464,13 @@ async function startServe(opts) {
|
|
|
179844
180464
|
blobs: assets,
|
|
179845
180465
|
trace: () => traceStoreForActors,
|
|
179846
180466
|
audit: registryAudit,
|
|
180467
|
+
// ADR 凭据保险库 §4.5/§4.7 / ADR 0125:reveal 判权的项目解析 + 凭据读取审计读写。
|
|
180468
|
+
resolveDispatchScope,
|
|
180469
|
+
credentialAudit,
|
|
180470
|
+
readCredentialAudit,
|
|
180471
|
+
// ADR 0125:写 scope=project 变量时校验 projectId 真实存在(getProject 直查,含临时项目)。
|
|
180472
|
+
// projectStateStore 在下方 ~行 1023 才赋值——本箭头只在请求时跑,那时已就绪(同 resolveDispatchScope 惰性模式)。
|
|
180473
|
+
projectExists: async (id) => await projectStateStore.getProject(id) !== null,
|
|
179847
180474
|
// CO-302 数据面隔离(actors 域试点):按当前公司取其引擎,用各自 registry 服务该域请求。
|
|
179848
180475
|
// engineRouter 在下方(行 ~411)以 const 声明;此箭头只在请求时调用,那时已初始化,闭包引用合法
|
|
179849
180476
|
// (TDZ 只在构造时访问才报错,这里不访问)。默认公司命中现有单实例(registry===registryStore),
|
|
@@ -179974,7 +180601,13 @@ async function startServe(opts) {
|
|
|
179974
180601
|
traceStoreForActors = traceStore;
|
|
179975
180602
|
const trajReader = new FsTrajectorySink(opts.dir);
|
|
179976
180603
|
const trace = createTraceDomain({ store: traceStore, readBundleFile: (id, rel) => trajReader.readBundleFile(id, rel) });
|
|
179977
|
-
const
|
|
180604
|
+
const traceHealth = createTraceHealth();
|
|
180605
|
+
const traceStoreSink = new TraceStoreSink({
|
|
180606
|
+
store: traceStore,
|
|
180607
|
+
runtimeKind: "auto",
|
|
180608
|
+
health: traceHealth,
|
|
180609
|
+
onError: (err) => console.warn(`[trace-sink] \u5199\u89C2\u6D4B\u6D41\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u5F71\u54CD\u6D3E\u53D1\uFF09: ${String(err)}`)
|
|
180610
|
+
});
|
|
179978
180611
|
const automationStore = pgPool ? await PostgresAutomationStore.open(pgPool, pgSchema) : new MemoryAutomationStore();
|
|
179979
180612
|
console.log(`[serve] \u81EA\u52A8\u5316\u4F53\u7CFB\uFF1A${pgPool ? `Postgres schema=${pgSchema}` : "\u5185\u5B58 dev store"}`);
|
|
179980
180613
|
const automations = createAutomationsDomain({ store: automationStore, kernel });
|
|
@@ -180438,6 +181071,8 @@ async function startServe(opts) {
|
|
|
180438
181071
|
// 组织汇总用——从 node_runtimes 取 hostname,解析运行时实例标签(kind @ hostname)
|
|
180439
181072
|
listRuntimes: (nodeId) => nodeStore.listRuntimes(nodeId),
|
|
180440
181073
|
dispatchJournal: () => journalRing.slice(-200),
|
|
181074
|
+
// 组织汇总用——从 nodes 取 name(用户友好名),优先于 hostname 作为展示标签
|
|
181075
|
+
listNodes: () => nodeStore.listNodes(),
|
|
180441
181076
|
// 诊断 92ac8f18-83e5fde6 §④ D-2:按**请求公司**取其 dispatcher 的 queued/backoff 信号。
|
|
180442
181077
|
// CO-302 每家公司各有一套 dispatcher(dispatchers 以 companyId 为键)——固定读默认公司会让
|
|
180443
181078
|
// 非默认公司请求拿到错的/空的信号(code-review 打回)。该公司未起 dispatcher(老部署无 --dispatch、
|
|
@@ -180577,10 +181212,14 @@ async function startServe(opts) {
|
|
|
180577
181212
|
const traceRunId = `chat-run:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180578
181213
|
const artifactId = `artifact:chat:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180579
181214
|
const traceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180580
|
-
let traceSeq = 0;
|
|
180581
181215
|
let lastProgressTouchMs = 0;
|
|
180582
181216
|
const PROGRESS_TOUCH_THROTTLE_MS2 = 2e4;
|
|
180583
|
-
|
|
181217
|
+
const traceAppender = new ResilientTraceAppender({
|
|
181218
|
+
runId: traceRunId,
|
|
181219
|
+
store: traceStore,
|
|
181220
|
+
health: traceHealth,
|
|
181221
|
+
onError: (err) => console.warn(`[trace] chat run ${traceRunId} \u5199\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u7184\u706D\uFF09: ${String(err)}`)
|
|
181222
|
+
});
|
|
180584
181223
|
const analyzedRunId = chatSessionId ? (await chatSessionStore.getSession(chatSessionId).catch(() => null))?.analyzedRunId ?? void 0 : void 0;
|
|
180585
181224
|
let traceChain = traceStore.createRun({
|
|
180586
181225
|
id: traceRunId,
|
|
@@ -180601,16 +181240,14 @@ async function startServe(opts) {
|
|
|
180601
181240
|
...analyzedRunId ? { analyzedRunId } : {}
|
|
180602
181241
|
}
|
|
180603
181242
|
}).then(async () => {
|
|
180604
|
-
await
|
|
181243
|
+
await traceAppender.append([
|
|
180605
181244
|
{
|
|
180606
|
-
seq: ++traceSeq,
|
|
180607
181245
|
eventType: "run.started",
|
|
180608
181246
|
stream: "runtime",
|
|
180609
181247
|
message: `chat ${actorId}`,
|
|
180610
181248
|
startedAt: traceStartedAt
|
|
180611
181249
|
},
|
|
180612
181250
|
{
|
|
180613
|
-
seq: ++traceSeq,
|
|
180614
181251
|
eventType: "input.message",
|
|
180615
181252
|
stream: "model",
|
|
180616
181253
|
actorId,
|
|
@@ -180620,16 +181257,12 @@ async function startServe(opts) {
|
|
|
180620
181257
|
}
|
|
180621
181258
|
]);
|
|
180622
181259
|
}).catch((err) => {
|
|
180623
|
-
|
|
180624
|
-
console.warn(`[trace] chat run create failed: ${String(err)}`);
|
|
181260
|
+
traceHealth.markUnhealthy(traceRunId);
|
|
181261
|
+
console.warn(`[trace] chat run create failed (continuing): ${String(err)}`);
|
|
180625
181262
|
});
|
|
180626
181263
|
const enqueueTrace = (step) => {
|
|
180627
|
-
|
|
180628
|
-
|
|
180629
|
-
if (traceEnabled) await step();
|
|
180630
|
-
}).catch((err) => {
|
|
180631
|
-
traceEnabled = false;
|
|
180632
|
-
console.warn(`[trace] chat run ${traceRunId} failed: ${String(err)}`);
|
|
181264
|
+
traceChain = traceChain.then(step).catch((err) => {
|
|
181265
|
+
console.warn(`[trace] chat run ${traceRunId} \u7EED\u8D26\u5F02\u5E38: ${String(err)}`);
|
|
180633
181266
|
});
|
|
180634
181267
|
};
|
|
180635
181268
|
const provision = await buildActorProvision(actorService, actorId);
|
|
@@ -180776,7 +181409,7 @@ async function startServe(opts) {
|
|
|
180776
181409
|
const run = await traceStore.getRun(traceRunId);
|
|
180777
181410
|
if (!run) return;
|
|
180778
181411
|
const base = run.metadata && typeof run.metadata === "object" && !Array.isArray(run.metadata) ? run.metadata : {};
|
|
180779
|
-
await
|
|
181412
|
+
await traceAppender.update({
|
|
180780
181413
|
metadata: { ...base, dispatchId: handle.id },
|
|
180781
181414
|
// 恢复路径拿不到 dispatchChat 闭包里的 fallback 解析结果,开跑时先写进账本;退出帧若上报
|
|
180782
181415
|
// 更精确 model 仍会覆盖为 runtime 来源。
|
|
@@ -180798,23 +181431,23 @@ async function startServe(opts) {
|
|
|
180798
181431
|
const ms = Date.parse(event.ts);
|
|
180799
181432
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
180800
181433
|
lastProgressTouchMs = ms;
|
|
180801
|
-
enqueueTrace(() =>
|
|
181434
|
+
enqueueTrace(() => traceAppender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
180802
181435
|
}
|
|
180803
181436
|
return;
|
|
180804
181437
|
}
|
|
180805
|
-
enqueueTrace(() =>
|
|
181438
|
+
enqueueTrace(() => traceAppender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
180806
181439
|
});
|
|
180807
181440
|
let capturedNativeSessionId;
|
|
180808
181441
|
const done = new Promise((resolve8, reject) => {
|
|
180809
181442
|
handle.onExit((info) => {
|
|
180810
181443
|
chatLiveSessions.delete(chatJobKey);
|
|
181444
|
+
traceHealth.forget(traceRunId);
|
|
180811
181445
|
void provision.cleanup();
|
|
180812
181446
|
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180813
181447
|
const durationMs = Date.parse(endedAt) - Date.parse(traceStartedAt);
|
|
180814
181448
|
if (info.runtimeSessionId) capturedNativeSessionId = info.runtimeSessionId;
|
|
180815
181449
|
enqueueTrace(async () => {
|
|
180816
|
-
await
|
|
180817
|
-
seq: ++traceSeq,
|
|
181450
|
+
await traceAppender.append([{
|
|
180818
181451
|
eventType: "run.finished",
|
|
180819
181452
|
stream: "runtime",
|
|
180820
181453
|
message: `exit code=${info.code ?? "killed"}`,
|
|
@@ -180823,7 +181456,7 @@ async function startServe(opts) {
|
|
|
180823
181456
|
const usage = info.usage ?? null;
|
|
180824
181457
|
const effectiveModel = info.model ?? chatModel ?? null;
|
|
180825
181458
|
const modelSource = info.model ? "runtime" : chatModelSource;
|
|
180826
|
-
await
|
|
181459
|
+
await traceAppender.update({
|
|
180827
181460
|
status: info.reason === "timeout" ? "timeout" : info.reason === "cancelled" ? "cancelled" : info.code === 0 ? "succeeded" : "failed",
|
|
180828
181461
|
endedAt,
|
|
180829
181462
|
durationMs,
|
|
@@ -180928,6 +181561,7 @@ async function startServe(opts) {
|
|
|
180928
181561
|
unregister: () => {
|
|
180929
181562
|
chatLiveSessions.delete(jobKey);
|
|
180930
181563
|
},
|
|
181564
|
+
traceHealth,
|
|
180931
181565
|
log: (m2) => console.log(m2)
|
|
180932
181566
|
});
|
|
180933
181567
|
console.log(`[chat-recovery] \u91CD\u6302 chat \u8F6E\uFF1Asession=${plan.chatSessionId} run=${plan.runId} node=${daemonId}`);
|
|
@@ -181148,7 +181782,7 @@ async function startServe(opts) {
|
|
|
181148
181782
|
console.warn(`[dispatch] artifact ${artifactId} owner ${actor} \u5DF2\u505C\u7528\uFF0C\u6309 ownerRole=${ownerRole} \u6539\u6D3E\u7ED9 ${replacement.id}${rejected.length ? `\uFF08\u8DF3\u8FC7\u4E0D\u5065\u5EB7\u7684\uFF1A${rejected.join("\u3001")}\uFF09` : ""}`);
|
|
181149
181783
|
return { actor: replacement.id, originalActor: actor, routeReason: "disabled-owner-fallback" };
|
|
181150
181784
|
},
|
|
181151
|
-
provision: async (actorId) => buildActorProvision((await runActors()).service, actorId),
|
|
181785
|
+
provision: async (actorId, artifactId) => buildActorProvision((await runActors()).service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181152
181786
|
resolveActorContext: async (actorId) => buildActorContext((await runActors()).service, actorId),
|
|
181153
181787
|
// 收尾评审的角色分工段(reviewer 此前彼此不知道对方存在 → 越界 / 重复劳动)。
|
|
181154
181788
|
// 职责取自**岗位目录**(配置面),不在代码里硬编码任何岗位——加角色自动就在。
|
|
@@ -181771,7 +182405,7 @@ ${nodeFault}` : "");
|
|
|
181771
182405
|
resolveManager: (id) => resolveManagerBinding(registryStore, id),
|
|
181772
182406
|
schemaTypes: schema.map((d) => d.name),
|
|
181773
182407
|
schemaTypeDescriptions: Object.fromEntries(schema.filter((d) => d.description).map((d) => [d.name, d.description])),
|
|
181774
|
-
provision: (actorId) => buildActorProvision(actors.service, actorId),
|
|
182408
|
+
provision: async (actorId, artifactId) => buildActorProvision(actors.service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181775
182409
|
// 阻塞诊断(proposal D1/D3):派发器运行时信号(queued/fused/backoff/hasInFlight)注入诊断,
|
|
181776
182410
|
// 让协调者把"资源 / 运行时"病因和"图病"分开——资源排队的节点不会被误唤去砍流程。
|
|
181777
182411
|
runtimeSignals: (id) => {
|
|
@@ -181811,6 +182445,9 @@ ${nodeFault}` : "");
|
|
|
181811
182445
|
if (c) return Promise.resolve(c.kill()).then(() => true).catch(() => false);
|
|
181812
182446
|
return dispatcherByJob.get(jobKey)?.killSession(jobKey) ?? Promise.resolve(false);
|
|
181813
182447
|
},
|
|
182448
|
+
// trace 写不进去的 run:冻结的事件钟是"观测降级"不是"真静默",按"信息不足→不判"跳过、交 wallClock
|
|
182449
|
+
// 兜底(brief §限制1 / 诊断 §6)。真卡死的 run trace 健康、isTraceHealthy=true,照常被杀。
|
|
182450
|
+
isTraceHealthy: (sessionId) => traceHealth.isHealthy(sessionId),
|
|
181814
182451
|
now: Date.now(),
|
|
181815
182452
|
silentThresholdMs,
|
|
181816
182453
|
log: (m2) => console.log(m2)
|
|
@@ -181973,7 +182610,7 @@ var SessionManager = class {
|
|
|
181973
182610
|
|
|
181974
182611
|
// ../cli/src/daemon/ws-client.ts
|
|
181975
182612
|
init_wrapper();
|
|
181976
|
-
var
|
|
182613
|
+
var import_node_os8 = require("node:os");
|
|
181977
182614
|
var import_node_crypto38 = require("node:crypto");
|
|
181978
182615
|
init_src5();
|
|
181979
182616
|
|
|
@@ -182029,7 +182666,7 @@ function detectRuntimes() {
|
|
|
182029
182666
|
|
|
182030
182667
|
// ../cli/src/daemon/workdir-handler.ts
|
|
182031
182668
|
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
182032
|
-
var
|
|
182669
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
182033
182670
|
init_src4();
|
|
182034
182671
|
init_src();
|
|
182035
182672
|
var WORKDIR_READ_MAX_BYTES2 = 2 * 1024 * 1024;
|
|
@@ -182048,10 +182685,10 @@ function isSensitiveSegment(segment) {
|
|
|
182048
182685
|
}
|
|
182049
182686
|
function relPathIsSensitive(rel) {
|
|
182050
182687
|
if (!rel) return false;
|
|
182051
|
-
return rel.split(
|
|
182688
|
+
return rel.split(import_node_path19.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
|
|
182052
182689
|
}
|
|
182053
182690
|
function withinBase(p2, base) {
|
|
182054
|
-
return p2 === base || p2.startsWith(base +
|
|
182691
|
+
return p2 === base || p2.startsWith(base + import_node_path19.default.sep);
|
|
182055
182692
|
}
|
|
182056
182693
|
function normalizeRel(raw) {
|
|
182057
182694
|
const trimmed = (raw ?? "").trim();
|
|
@@ -182068,7 +182705,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
|
|
|
182068
182705
|
} catch {
|
|
182069
182706
|
return null;
|
|
182070
182707
|
}
|
|
182071
|
-
return isLegacy ?
|
|
182708
|
+
return isLegacy ? import_node_path19.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path19.default.join(trustedRootReal, "sessions", dirKind);
|
|
182072
182709
|
}
|
|
182073
182710
|
async function resolveWithinWorkdir(req) {
|
|
182074
182711
|
const dirKind = sessionDirKind(req.runtimeKind);
|
|
@@ -182086,11 +182723,11 @@ async function resolveWithinWorkdir(req) {
|
|
|
182086
182723
|
} catch {
|
|
182087
182724
|
return { ok: false, code: "NOT_FOUND" };
|
|
182088
182725
|
}
|
|
182089
|
-
if (
|
|
182726
|
+
if (import_node_path19.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
|
|
182090
182727
|
const rel = normalizeRel(req.path);
|
|
182091
|
-
const requested =
|
|
182728
|
+
const requested = import_node_path19.default.resolve(base, rel);
|
|
182092
182729
|
if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182093
|
-
const cleanRel = base === requested ? "" :
|
|
182730
|
+
const cleanRel = base === requested ? "" : import_node_path19.default.relative(base, requested);
|
|
182094
182731
|
if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
|
|
182095
182732
|
let real;
|
|
182096
182733
|
try {
|
|
@@ -182100,7 +182737,7 @@ async function resolveWithinWorkdir(req) {
|
|
|
182100
182737
|
return { ok: false, code: "PATH_ESCAPE" };
|
|
182101
182738
|
}
|
|
182102
182739
|
if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182103
|
-
const realRel = base === real ? "" :
|
|
182740
|
+
const realRel = base === real ? "" : import_node_path19.default.relative(base, real);
|
|
182104
182741
|
if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
|
|
182105
182742
|
return { ok: true, base, real };
|
|
182106
182743
|
}
|
|
@@ -182136,7 +182773,7 @@ async function handleWorkdirList(req) {
|
|
|
182136
182773
|
const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
|
|
182137
182774
|
const entries = [];
|
|
182138
182775
|
for (const d of slice) {
|
|
182139
|
-
const abs =
|
|
182776
|
+
const abs = import_node_path19.default.join(anchor, d.name);
|
|
182140
182777
|
try {
|
|
182141
182778
|
const st = await import_node_fs16.default.promises.lstat(abs);
|
|
182142
182779
|
if (st.isSymbolicLink()) continue;
|
|
@@ -182168,7 +182805,7 @@ async function verifyOpenedFd(fh, base, fallback) {
|
|
|
182168
182805
|
const fdReal = await fdCanonicalPath(fh);
|
|
182169
182806
|
if (fdReal === null) return { anchor: fallback };
|
|
182170
182807
|
if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
|
|
182171
|
-
const fdRel = base === fdReal ? "" :
|
|
182808
|
+
const fdRel = base === fdReal ? "" : import_node_path19.default.relative(base, fdReal);
|
|
182172
182809
|
if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
|
|
182173
182810
|
return { anchor: `/proc/self/fd/${fh.fd}` };
|
|
182174
182811
|
}
|
|
@@ -182257,7 +182894,7 @@ function looksBinary(bytes) {
|
|
|
182257
182894
|
function contentTypeFor(absPath, bytes) {
|
|
182258
182895
|
const sniffed = sniffContentType(bytes);
|
|
182259
182896
|
if (sniffed) return sniffed;
|
|
182260
|
-
const ext =
|
|
182897
|
+
const ext = import_node_path19.default.extname(absPath).toLowerCase();
|
|
182261
182898
|
if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
|
|
182262
182899
|
return looksBinary(bytes) ? "application/octet-stream" : "text/plain; charset=utf-8";
|
|
182263
182900
|
}
|
|
@@ -182600,7 +183237,7 @@ var DaemonWsClient = class {
|
|
|
182600
183237
|
buildMeta() {
|
|
182601
183238
|
const activeSessions = this.sessions.activeSessions();
|
|
182602
183239
|
return {
|
|
182603
|
-
hostname: (0,
|
|
183240
|
+
hostname: (0, import_node_os8.hostname)(),
|
|
182604
183241
|
adapters: this.adapters,
|
|
182605
183242
|
...this.reportRuntimes ? { runtimes: this.runtimes } : {},
|
|
182606
183243
|
nodeVersion: process.version,
|
|
@@ -182630,18 +183267,18 @@ var RuntimeRouterAdapter = class {
|
|
|
182630
183267
|
|
|
182631
183268
|
// ../cli/src/daemon/reap-claude-projects.ts
|
|
182632
183269
|
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
182633
|
-
var
|
|
182634
|
-
var
|
|
183270
|
+
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
183271
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
182635
183272
|
function claudeProjectSlug(cwd) {
|
|
182636
183273
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
182637
183274
|
}
|
|
182638
183275
|
function claudeProjectsRoot() {
|
|
182639
|
-
const configDir = process.env["CLAUDE_CONFIG_DIR"] ||
|
|
182640
|
-
return
|
|
183276
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path20.default.join(import_node_os9.default.homedir(), ".claude");
|
|
183277
|
+
return import_node_path20.default.join(configDir, "projects");
|
|
182641
183278
|
}
|
|
182642
183279
|
function reapClaudeProjects(workdir, runtimeKind) {
|
|
182643
183280
|
if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
|
|
182644
|
-
const dir =
|
|
183281
|
+
const dir = import_node_path20.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
|
|
182645
183282
|
if (!import_node_fs17.default.existsSync(dir)) return;
|
|
182646
183283
|
try {
|
|
182647
183284
|
import_node_fs17.default.rmSync(dir, { recursive: true, force: true });
|
|
@@ -182651,7 +183288,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
|
|
|
182651
183288
|
|
|
182652
183289
|
// ../cli/src/node.ts
|
|
182653
183290
|
init_src4();
|
|
182654
|
-
var
|
|
183291
|
+
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
182655
183292
|
var RESILIENCE = {
|
|
182656
183293
|
codex: { idleTimeoutMs: 6e5 }
|
|
182657
183294
|
};
|
|
@@ -182715,7 +183352,7 @@ async function startNode(opts) {
|
|
|
182715
183352
|
console.log(`[oasis node] ${opts.nodeId} \u2192 ${opts.serverUrl}`);
|
|
182716
183353
|
client.start();
|
|
182717
183354
|
const { workRoot, legacyRoot } = resolveWorkRoots(opts.workRoot);
|
|
182718
|
-
const workRootIsEphemeral = workRoot.startsWith(
|
|
183355
|
+
const workRootIsEphemeral = workRoot.startsWith(import_node_os10.default.tmpdir());
|
|
182719
183356
|
if (opts.gcEnabled === false && !workRootIsEphemeral) {
|
|
182720
183357
|
console.warn(`[oasis node] \u26A0 \u56DE\u6536\u5668\u5DF2\u5173\u95ED\uFF0C\u800C\u5DE5\u4F5C\u533A\u5728\u6301\u4E45\u76D8\uFF08${workRoot}\uFF09\u2014\u2014\u6CA1\u6709\u4EFB\u4F55\u5783\u573E\u56DE\u6536\uFF0C\u5B9E\u6D4B\u4E24\u5468\u4F1A\u6DA8 12.4GB\u3002\u4EC5\u4F9B\u6392\u969C\uFF0C\u522B\u957F\u671F\u8FD9\u4E48\u8DD1\u3002`);
|
|
182721
183358
|
}
|
|
@@ -182750,7 +183387,7 @@ async function startNode(opts) {
|
|
|
182750
183387
|
var import_node_child_process16 = require("node:child_process");
|
|
182751
183388
|
var import_node_fs18 = require("node:fs");
|
|
182752
183389
|
var import_node_crypto39 = require("node:crypto");
|
|
182753
|
-
var
|
|
183390
|
+
var import_node_os11 = require("node:os");
|
|
182754
183391
|
function linuxMachineId() {
|
|
182755
183392
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
182756
183393
|
try {
|
|
@@ -182790,13 +183427,13 @@ function windowsMachineId() {
|
|
|
182790
183427
|
}
|
|
182791
183428
|
function fallbackFingerprint() {
|
|
182792
183429
|
const macs = [];
|
|
182793
|
-
const ifaces = (0,
|
|
183430
|
+
const ifaces = (0, import_node_os11.networkInterfaces)();
|
|
182794
183431
|
for (const name of Object.keys(ifaces).sort()) {
|
|
182795
183432
|
for (const ni of ifaces[name] ?? []) {
|
|
182796
183433
|
if (!ni.internal && ni.mac && ni.mac !== "00:00:00:00:00:00") macs.push(ni.mac);
|
|
182797
183434
|
}
|
|
182798
183435
|
}
|
|
182799
|
-
return `fallback:${(0,
|
|
183436
|
+
return `fallback:${(0, import_node_os11.hostname)()}:${macs.sort()[0] ?? "no-mac"}`;
|
|
182800
183437
|
}
|
|
182801
183438
|
function machineFingerprint() {
|
|
182802
183439
|
const byOs = process.platform === "darwin" ? macMachineId() : process.platform === "win32" ? windowsMachineId() : linuxMachineId();
|
|
@@ -182806,7 +183443,7 @@ var defaultSources = {
|
|
|
182806
183443
|
machineFingerprint,
|
|
182807
183444
|
osUser: () => {
|
|
182808
183445
|
try {
|
|
182809
|
-
return (0,
|
|
183446
|
+
return (0, import_node_os11.userInfo)().username;
|
|
182810
183447
|
} catch {
|
|
182811
183448
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
182812
183449
|
}
|
|
@@ -183810,6 +184447,19 @@ var COMMAND_DECLS = {
|
|
|
183810
184447
|
description: "\u4EA4\u4ED8\u7269\u6587\u6863\u4F53\u7CFB\u64CD\u4F5C\uFF08artifact revision \u5B50\u547D\u4EE4\u96C6\uFF09\u3002",
|
|
183811
184448
|
subCommands: ["artifact revision register", "artifact revision approve", "artifact revision reject"],
|
|
183812
184449
|
examples: ['oasis artifact revision register --project oasis --artifact-id artifact:dev:abc --type dev --title "v1.0" --version 1 --content-ref ref-001']
|
|
184450
|
+
},
|
|
184451
|
+
var: {
|
|
184452
|
+
usage: "oasis var <reveal> ...",
|
|
184453
|
+
description: "\u51ED\u636E\u4FDD\u9669\u5E93\uFF1A\u8BFB\u53D6\u654F\u611F\u53D8\u91CF\u660E\u6587\uFF08ADR \u51ED\u636E\u4FDD\u9669\u5E93 \xA74.5\uFF09\u3002",
|
|
184454
|
+
subCommands: ["var reveal"],
|
|
184455
|
+
examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD"]
|
|
184456
|
+
},
|
|
184457
|
+
"var reveal": {
|
|
184458
|
+
usage: "oasis var reveal <key> [--source <tag>]",
|
|
184459
|
+
description: "\u8BFB\u53D6\u654F\u611F\u53D8\u91CF\u7684\u660E\u6587\u3002env \u91CC\u82E5\u89C1 oasis://var/X\uFF08\u5F15\u7528\u975E\u660E\u6587\uFF09\u2192 \u7528\u672C\u547D\u4EE4\u53D6\u660E\u6587\u3002\u7F3A key/\u65E0\u6743\u8FD4\u56DE denied\uFF1B\u77ED\u65F6\u8BFB\u53D6\u8FC7\u591A\u4F1A\u9650\u6D41\u3002\u660E\u6587\u53EA\u8F93\u51FA\u5230 stdout\u3002",
|
|
184460
|
+
positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key\uFF08\u53EF\u4F20\u88F8 key \u6216 oasis://var/<key> \u5F15\u7528\uFF0C\u4E8C\u8005\u7B49\u4EF7\uFF09" }],
|
|
184461
|
+
flags: [{ name: "source", desc: "\u8C03\u7528\u6765\u6E90\u6807\u8BB0\uFF08\u5BA1\u8BA1\u7528\uFF0C\u5982 smoke-test\uFF1B\u7F3A\u7701 agent-cli\uFF09", own: true }],
|
|
184462
|
+
examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var reveal oasis://var/GLM_API_KEY --source smoke-test"]
|
|
183813
184463
|
}
|
|
183814
184464
|
};
|
|
183815
184465
|
function formatCommandHelp(decl) {
|
|
@@ -185475,6 +186125,33 @@ ${res.warning}`);
|
|
|
185475
186125
|
println(`\u5DF2\u5220\u9664 ${memId}`);
|
|
185476
186126
|
break;
|
|
185477
186127
|
}
|
|
186128
|
+
case "var": {
|
|
186129
|
+
const sub = positional[0];
|
|
186130
|
+
if (sub === "reveal") {
|
|
186131
|
+
const rawKey = needPos(positional, 1, "oasis var reveal <key> [--source <tag>]");
|
|
186132
|
+
const key = parseVarRef(rawKey) ?? rawKey;
|
|
186133
|
+
const source = flags.get("source");
|
|
186134
|
+
try {
|
|
186135
|
+
const out = await api.request("POST", "/api/variables/reveal", {
|
|
186136
|
+
key,
|
|
186137
|
+
...source ? { source } : {}
|
|
186138
|
+
});
|
|
186139
|
+
println(out.value);
|
|
186140
|
+
} catch (e) {
|
|
186141
|
+
if (e instanceof ApiRequestError && e.status === 403) {
|
|
186142
|
+
throw new Error(`\u51ED\u636E\u4E0D\u53EF\u8BFB\uFF1A${key}\uFF08403 denied\uFF09\u2014\u2014\u8BE5 key \u4E0D\u5B58\u5728\uFF0C\u6216\u672C\u4F1A\u8BDD\u65E0\u6743\u8BFB\u53D6\uFF08ADR \xA74.5\uFF09\u3002\u522B\u5FAA\u73AF\u91CD\u8BD5\uFF1B\u7F3A\u51ED\u636E\u8BF7\u4E0A\u62A5\u8FD0\u7EF4\u3002`);
|
|
186143
|
+
}
|
|
186144
|
+
if (e instanceof ApiRequestError && e.status === 429) {
|
|
186145
|
+
const scope = e.body?.scope ?? "session";
|
|
186146
|
+
throw new Error(`reveal \u89E6\u53D1\u9650\u6D41\uFF1A${key}\uFF08429 throttled\uFF0C\u6863=${scope}\uFF09\u2014\u2014\u77ED\u65F6\u5185\u8BFB\u53D6\u8FC7\u591A\u3002\u522B\u518D\u5FAA\u73AF reveal \u540C\u4E00 key\u3002`);
|
|
186147
|
+
}
|
|
186148
|
+
throw e;
|
|
186149
|
+
}
|
|
186150
|
+
break;
|
|
186151
|
+
}
|
|
186152
|
+
throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4\uFF1Aoasis var ${sub ?? ""}
|
|
186153
|
+
\u53EF\u7528\uFF1Aoasis var reveal <key> [--source <tag>]`);
|
|
186154
|
+
}
|
|
185478
186155
|
case "pin": {
|
|
185479
186156
|
const { message } = await api.cmd("pin", {
|
|
185480
186157
|
artifactId: needPos(positional, 0, "oasis pin <artifactId> --to u --rev r"),
|
|
@@ -186174,7 +186851,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
186174
186851
|
}
|
|
186175
186852
|
|
|
186176
186853
|
// src/index.ts
|
|
186177
|
-
var PKG_VERSION = true ? "0.1.
|
|
186854
|
+
var PKG_VERSION = true ? "0.1.89" : "dev";
|
|
186178
186855
|
var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
|
|
186179
186856
|
var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
|
|
186180
186857
|
var PID_FILE = path29.join(OASIS_DIR, "node.pid");
|