oasis_test 0.1.86 → 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 +994 -276
- package/package.json +2 -2
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());
|
|
@@ -141611,7 +141632,8 @@ async function fetchAppBotIdentity(slug6, opts = {}, deps = {}) {
|
|
|
141611
141632
|
const body = await resp.json().catch(() => ({}));
|
|
141612
141633
|
const id = body["id"];
|
|
141613
141634
|
if (id === void 0 || id === null) return null;
|
|
141614
|
-
|
|
141635
|
+
const actualLogin = typeof body["login"] === "string" && body["login"] ? body["login"] : login;
|
|
141636
|
+
return { login: actualLogin, email: `${String(id)}+${actualLogin}@users.noreply.github.com` };
|
|
141615
141637
|
} catch {
|
|
141616
141638
|
return null;
|
|
141617
141639
|
}
|
|
@@ -141632,10 +141654,17 @@ async function exchangeManifestCode(code, deps = {}) {
|
|
|
141632
141654
|
const appId = body["id"] === void 0 ? "" : String(body["id"]);
|
|
141633
141655
|
const privateKeyPem = typeof body["pem"] === "string" ? body["pem"] : "";
|
|
141634
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;
|
|
141635
141661
|
return {
|
|
141636
141662
|
appId,
|
|
141637
141663
|
privateKeyPem,
|
|
141638
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,
|
|
141639
141668
|
...typeof body["webhook_secret"] === "string" ? { webhookSecret: body["webhook_secret"] } : {}
|
|
141640
141669
|
};
|
|
141641
141670
|
}
|
|
@@ -141681,7 +141710,8 @@ var init_github = __esm({
|
|
|
141681
141710
|
{ key: "app_installation_id", description: "App \u5728\u8BE5\u7EC4\u7EC7/\u8D26\u53F7\u4E0B\u7684\u5B89\u88C5 ID", secret: false, required: false },
|
|
141682
141711
|
{ key: "app_token_expires_at", description: "installation token \u7684\u7EDD\u5BF9\u8FC7\u671F\u65F6\u523B\uFF08epoch ms\uFF09", secret: false, required: false },
|
|
141683
141712
|
{ key: "app_slug", description: "App \u7684 slug\u2014\u2014bot \u8EAB\u4EFD\u663E\u793A\u4E3A <slug>[bot]", secret: false, required: false },
|
|
141684
|
-
{ key: "app_bot_email", description: "bot \u8D26\u53F7\u7684 noreply \u90AE\u7BB1\uFF08commit \u7F72\u540D\u9760\u5B83\u94FE\u63A5\u5230 bot\uFF09", secret: false, required: false }
|
|
141713
|
+
{ key: "app_bot_email", description: "bot \u8D26\u53F7\u7684 noreply \u90AE\u7BB1\uFF08commit \u7F72\u540D\u9760\u5B83\u94FE\u63A5\u5230 bot\uFF09", secret: false, required: false },
|
|
141714
|
+
{ key: "app_bot_name", description: "bot \u8D26\u53F7\u7684 login\uFF08commit \u7F72\u540D\u7528\u5B83\uFF0C\u4E0E PR \u4F5C\u8005\u9010\u5B57\u4E00\u81F4\uFF09", secret: false, required: false }
|
|
141685
141715
|
]
|
|
141686
141716
|
};
|
|
141687
141717
|
/** wrapper 在 agent PATH 上冒名的命令——必须与真实 CLI 同名,否则遮蔽不生效。 */
|
|
@@ -141700,7 +141730,9 @@ var init_github = __esm({
|
|
|
141700
141730
|
{ key: "app_slug", from: "GITHUB_APP_SLUG", required: false },
|
|
141701
141731
|
// bot 的 noreply 邮箱:commit 署名靠**邮箱**链接到账号(name 只是自由文本)。
|
|
141702
141732
|
// 公开信息,非密钥。
|
|
141703
|
-
{ key: "app_bot_email", from: "GITHUB_APP_BOT_EMAIL", required: false }
|
|
141733
|
+
{ key: "app_bot_email", from: "GITHUB_APP_BOT_EMAIL", required: false },
|
|
141734
|
+
// bot 的 login:commit 署名的 name 用它,才能和 PR 作者显示成同一个身份。
|
|
141735
|
+
{ key: "app_bot_name", from: "GITHUB_APP_BOT_NAME", required: false }
|
|
141704
141736
|
];
|
|
141705
141737
|
/**
|
|
141706
141738
|
* 续期材料——**只在 server 侧读**。私钥留在这边铸 token,节点只拿铸出来的那一小时。
|
|
@@ -141716,6 +141748,18 @@ var init_github = __esm({
|
|
|
141716
141748
|
{ key: "access_token", from: "GITHUB_APP_TOKEN", required: false },
|
|
141717
141749
|
{ key: "app_token_expires_at", from: "GITHUB_APP_TOKEN_EXPIRES_AT", required: false }
|
|
141718
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;
|
|
141719
141763
|
/** 过期判定只认这个键——必须与注入时消费的 token 同源(契约测试盯着)。 */
|
|
141720
141764
|
expiresAtCredentialKey = "app_token_expires_at";
|
|
141721
141765
|
// 私钥不会过期,故不声明 refreshMaterialExpiresAtCredentialKey,也无需 clearOnExpired。
|
|
@@ -141725,6 +141769,12 @@ var init_github = __esm({
|
|
|
141725
141769
|
"GITHUB_APP_TOKEN",
|
|
141726
141770
|
"GITHUB_APP_PRIVATE_KEY"
|
|
141727
141771
|
];
|
|
141772
|
+
/**
|
|
141773
|
+
* 宿主机登录态隔离:`gh` 只认 env 里的 GH_TOKEN 或 `~/.config/gh/hosts.yml`。
|
|
141774
|
+
* 这个键**由通用装配层无条件设**(哪怕本连接器没接通),否则关掉连接器时
|
|
141775
|
+
* agent 会静默用成宿主机那个真人账号——见接口里的详细说明。
|
|
141776
|
+
*/
|
|
141777
|
+
hostCredentialIsolationEnvKeys = ["GH_CONFIG_DIR"];
|
|
141728
141778
|
/** inject() 写进 sessionEnv 的全部键——通用 cleanup() 按它逐个删。 */
|
|
141729
141779
|
injectedEnvKeys = [
|
|
141730
141780
|
"GH_BIN",
|
|
@@ -141815,7 +141865,7 @@ var init_github = __esm({
|
|
|
141815
141865
|
const creds = await writeSessionCredsFile(this.config.slug, {
|
|
141816
141866
|
GH_TOKEN: token,
|
|
141817
141867
|
GITHUB_TOKEN: token
|
|
141818
|
-
});
|
|
141868
|
+
}, sessionEnv.get("GH_RUN_TMPDIR"));
|
|
141819
141869
|
const configDir = (0, import_node_path7.join)(creds.dir, "gh-config");
|
|
141820
141870
|
await (0, import_promises4.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
141821
141871
|
sessionEnv.set("GH_BIN", await this.resolveRealBin("gh"));
|
|
@@ -141825,9 +141875,11 @@ var init_github = __esm({
|
|
|
141825
141875
|
const appSlug = credentials["app_slug"];
|
|
141826
141876
|
if (appSlug) sessionEnv.set("GH_APP_SLUG", appSlug);
|
|
141827
141877
|
const botEmail = credentials["app_bot_email"] ?? "";
|
|
141828
|
-
|
|
141878
|
+
const botName = credentials["app_bot_name"] ?? "";
|
|
141879
|
+
const signName = botName || name;
|
|
141880
|
+
sessionEnv.set("GIT_AUTHOR_NAME", signName);
|
|
141829
141881
|
sessionEnv.set("GIT_AUTHOR_EMAIL", botEmail);
|
|
141830
|
-
sessionEnv.set("GIT_COMMITTER_NAME",
|
|
141882
|
+
sessionEnv.set("GIT_COMMITTER_NAME", signName);
|
|
141831
141883
|
sessionEnv.set("GIT_COMMITTER_EMAIL", botEmail);
|
|
141832
141884
|
sessionEnv.set("EMAIL", botEmail);
|
|
141833
141885
|
sessionEnv.set("GIT_CONFIG_COUNT", "1");
|
|
@@ -141866,7 +141918,27 @@ function callbackHtml(ok, message) {
|
|
|
141866
141918
|
setTimeout(function(){window.close()},${ok ? 800 : 4e3})</script>
|
|
141867
141919
|
</body>`;
|
|
141868
141920
|
}
|
|
141869
|
-
|
|
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;
|
|
141870
141942
|
var init_app_manifest = __esm({
|
|
141871
141943
|
"../connectors/src/github/app-manifest.ts"() {
|
|
141872
141944
|
"use strict";
|
|
@@ -141909,6 +141981,7 @@ var init_app_manifest = __esm({
|
|
|
141909
141981
|
return this.map.size;
|
|
141910
141982
|
}
|
|
141911
141983
|
};
|
|
141984
|
+
REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
|
|
141912
141985
|
}
|
|
141913
141986
|
});
|
|
141914
141987
|
|
|
@@ -141965,19 +142038,27 @@ function collectCredentials(connector, ctx) {
|
|
|
141965
142038
|
}
|
|
141966
142039
|
return creds;
|
|
141967
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
|
+
}
|
|
141968
142047
|
async function buildConnectorProvision(ctx) {
|
|
141969
142048
|
const envOverrides = {};
|
|
141970
142049
|
const wrapperPaths = [];
|
|
141971
142050
|
const requiredTools = /* @__PURE__ */ new Set();
|
|
141972
|
-
const connectorCreds = [];
|
|
141973
142051
|
const cleanups = [];
|
|
141974
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]));
|
|
141975
142056
|
for (const connector of createAllConnectors()) {
|
|
141976
142057
|
for (const v2 of connector.sensitiveVars) sensitiveVars.add(v2);
|
|
141977
|
-
const
|
|
141978
|
-
|
|
142058
|
+
for (const k2 of connector.hostCredentialIsolationEnvKeys ?? []) isolationKeys.add(k2);
|
|
142059
|
+
const credentials = credentialsBySlug.get(connector.config.slug);
|
|
142060
|
+
if (credentials === void 0) continue;
|
|
141979
142061
|
try {
|
|
141980
|
-
connectorCreds.push({ slug: connector.config.slug, credentials });
|
|
141981
142062
|
const sessionEnv = /* @__PURE__ */ new Map();
|
|
141982
142063
|
await connector.inject(credentials, sessionEnv);
|
|
141983
142064
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
@@ -141993,6 +142074,19 @@ async function buildConnectorProvision(ctx) {
|
|
|
141993
142074
|
log("[provision]", `${connector.config.slug}: \u88C5\u914D\u5931\u8D25\uFF08\u8BE5\u8FDE\u63A5\u5668\u672C\u8F6E\u4E0D\u53EF\u7528\uFF09: ${String(err)}`);
|
|
141994
142075
|
}
|
|
141995
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
|
+
});
|
|
141996
142090
|
const cleanup = async () => {
|
|
141997
142091
|
for (const fn of cleanups) await fn().catch(() => {
|
|
141998
142092
|
});
|
|
@@ -142006,23 +142100,28 @@ async function buildConnectorProvision(ctx) {
|
|
|
142006
142100
|
cleanup
|
|
142007
142101
|
};
|
|
142008
142102
|
}
|
|
142103
|
+
var import_promises5, import_node_os4, import_node_path8;
|
|
142009
142104
|
var init_provision = __esm({
|
|
142010
142105
|
"../connectors/src/provision.ts"() {
|
|
142011
142106
|
"use strict";
|
|
142012
142107
|
init_base();
|
|
142013
142108
|
init_registry2();
|
|
142014
142109
|
init_logger();
|
|
142110
|
+
import_promises5 = require("node:fs/promises");
|
|
142111
|
+
import_node_os4 = require("node:os");
|
|
142112
|
+
import_node_path8 = require("node:path");
|
|
142015
142113
|
}
|
|
142016
142114
|
});
|
|
142017
142115
|
|
|
142018
142116
|
// ../connectors/src/prepare-job.ts
|
|
142019
|
-
async function prepareConnectorsForJob(job) {
|
|
142117
|
+
async function prepareConnectorsForJob(job, deps) {
|
|
142020
142118
|
const creds = job.connectorCreds ?? [];
|
|
142021
142119
|
const remoteWrappers = job.wrapperPaths ?? [];
|
|
142022
142120
|
const localWrappers = [];
|
|
142023
142121
|
const cleanups = [];
|
|
142024
142122
|
const envOverrides = {};
|
|
142025
142123
|
const statuses = [];
|
|
142124
|
+
const injected = /* @__PURE__ */ new Map();
|
|
142026
142125
|
for (const { slug: slug6, credentials } of creds) {
|
|
142027
142126
|
const connector = createConnectorBySlug(slug6);
|
|
142028
142127
|
if (!connector) {
|
|
@@ -142037,6 +142136,7 @@ async function prepareConnectorsForJob(job) {
|
|
|
142037
142136
|
await connector.inject(credentials, sessionEnv);
|
|
142038
142137
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
142039
142138
|
cleanups.push(() => connector.cleanup(sessionEnv));
|
|
142139
|
+
injected.set(slug6, { connector, sessionEnv });
|
|
142040
142140
|
status.credsReady = true;
|
|
142041
142141
|
} catch (err) {
|
|
142042
142142
|
status.error = String(err);
|
|
@@ -142070,13 +142170,62 @@ async function prepareConnectorsForJob(job) {
|
|
|
142070
142170
|
env: { ...job.env ?? {}, ...envOverrides, PATH: pathWithTools },
|
|
142071
142171
|
wrapperPaths: [...keptLocal, ...keptRemote]
|
|
142072
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
|
+
}
|
|
142073
142184
|
const cleanup = async () => {
|
|
142074
142185
|
for (const fn of cleanups) await fn().catch(() => {
|
|
142075
142186
|
});
|
|
142076
142187
|
};
|
|
142077
142188
|
return { job: preparedJob, cleanup, statuses };
|
|
142078
142189
|
}
|
|
142079
|
-
|
|
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;
|
|
142080
142229
|
var init_prepare_job = __esm({
|
|
142081
142230
|
"../connectors/src/prepare-job.ts"() {
|
|
142082
142231
|
"use strict";
|
|
@@ -142084,6 +142233,7 @@ var init_prepare_job = __esm({
|
|
|
142084
142233
|
init_base();
|
|
142085
142234
|
init_registry2();
|
|
142086
142235
|
init_logger();
|
|
142236
|
+
SESSION_CREDENTIAL_RENEW_INTERVAL_MS = 30 * 6e4;
|
|
142087
142237
|
}
|
|
142088
142238
|
});
|
|
142089
142239
|
|
|
@@ -142422,8 +142572,8 @@ function materializeFiles(dir, files) {
|
|
|
142422
142572
|
if (!files) return;
|
|
142423
142573
|
for (const [rel, content] of Object.entries(files)) {
|
|
142424
142574
|
try {
|
|
142425
|
-
const file =
|
|
142426
|
-
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 });
|
|
142427
142577
|
import_node_fs6.default.writeFileSync(file, content);
|
|
142428
142578
|
} catch {
|
|
142429
142579
|
}
|
|
@@ -142439,7 +142589,7 @@ function resolveLegacyWorkRoot(workRoot) {
|
|
|
142439
142589
|
if (workRoot) return workRoot;
|
|
142440
142590
|
const env = process.env["OASIS_WORK_ROOT"];
|
|
142441
142591
|
if (env) return env;
|
|
142442
|
-
return
|
|
142592
|
+
return import_node_os5.default.tmpdir();
|
|
142443
142593
|
}
|
|
142444
142594
|
function resolveWorkRoots(workRoot) {
|
|
142445
142595
|
return { workRoot: resolveWorkRoot(workRoot), legacyRoot: resolveLegacyWorkRoot(workRoot) };
|
|
@@ -142450,7 +142600,7 @@ function slug5(workdirKey) {
|
|
|
142450
142600
|
return `${safe}-${h}`;
|
|
142451
142601
|
}
|
|
142452
142602
|
function sessionDirFor(workRoot, runtimeKind, workdirKey) {
|
|
142453
|
-
return
|
|
142603
|
+
return import_node_path9.default.join(resolveWorkRoot(workRoot), "sessions", runtimeKind, slug5(workdirKey));
|
|
142454
142604
|
}
|
|
142455
142605
|
function sessionDirKind(runtimeKind) {
|
|
142456
142606
|
return runtimeKind === "claude-code" ? "claude" : runtimeKind;
|
|
@@ -142463,20 +142613,20 @@ function resolveSessionDirWithLegacy(args) {
|
|
|
142463
142613
|
return import_node_fs6.default.existsSync(legacy) ? legacy : fresh;
|
|
142464
142614
|
}
|
|
142465
142615
|
function oneShotDirFor(workRoot, runtimeKind) {
|
|
142466
|
-
const base =
|
|
142616
|
+
const base = import_node_path9.default.join(resolveWorkRoot(workRoot), "tmp");
|
|
142467
142617
|
import_node_fs6.default.mkdirSync(base, { recursive: true });
|
|
142468
|
-
return import_node_fs6.default.mkdtempSync(
|
|
142618
|
+
return import_node_fs6.default.mkdtempSync(import_node_path9.default.join(base, `${runtimeKind}-`));
|
|
142469
142619
|
}
|
|
142470
142620
|
function writeMeta(dir, meta) {
|
|
142471
142621
|
try {
|
|
142472
|
-
import_node_fs6.default.writeFileSync(
|
|
142622
|
+
import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, META_FILE), `${JSON.stringify(meta, null, 2)}
|
|
142473
142623
|
`);
|
|
142474
142624
|
} catch {
|
|
142475
142625
|
}
|
|
142476
142626
|
}
|
|
142477
142627
|
function readMeta(dir) {
|
|
142478
142628
|
try {
|
|
142479
|
-
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"));
|
|
142480
142630
|
if (!raw || typeof raw !== "object") return null;
|
|
142481
142631
|
const m2 = raw;
|
|
142482
142632
|
return typeof m2.kind === "string" && typeof m2.createdAt === "string" ? m2 : null;
|
|
@@ -142505,14 +142655,14 @@ function lockWorkdir(dir, pid, holder, workdirKey) {
|
|
|
142505
142655
|
...workdirKey !== void 0 ? { workdirKey } : {}
|
|
142506
142656
|
};
|
|
142507
142657
|
try {
|
|
142508
|
-
import_node_fs6.default.writeFileSync(
|
|
142658
|
+
import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, LOCK_FILE), `${JSON.stringify(lock)}
|
|
142509
142659
|
`);
|
|
142510
142660
|
} catch {
|
|
142511
142661
|
}
|
|
142512
142662
|
}
|
|
142513
142663
|
function readLock(dir) {
|
|
142514
142664
|
try {
|
|
142515
|
-
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"));
|
|
142516
142666
|
if (!raw || typeof raw !== "object") return null;
|
|
142517
142667
|
const l = raw;
|
|
142518
142668
|
return Number.isInteger(l.pid) && l.pid > 0 ? l : null;
|
|
@@ -142522,14 +142672,14 @@ function readLock(dir) {
|
|
|
142522
142672
|
}
|
|
142523
142673
|
function unlockWorkdir(dir) {
|
|
142524
142674
|
try {
|
|
142525
|
-
import_node_fs6.default.unlinkSync(
|
|
142675
|
+
import_node_fs6.default.unlinkSync(import_node_path9.default.join(dir, LOCK_FILE));
|
|
142526
142676
|
} catch {
|
|
142527
142677
|
}
|
|
142528
142678
|
}
|
|
142529
142679
|
function isWorkdirLive(dir) {
|
|
142530
142680
|
let raw;
|
|
142531
142681
|
try {
|
|
142532
|
-
raw = import_node_fs6.default.readFileSync(
|
|
142682
|
+
raw = import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, LOCK_FILE), "utf8");
|
|
142533
142683
|
} catch {
|
|
142534
142684
|
return false;
|
|
142535
142685
|
}
|
|
@@ -142546,7 +142696,7 @@ function clearWorkdir(dir) {
|
|
|
142546
142696
|
);
|
|
142547
142697
|
}
|
|
142548
142698
|
for (const entry of import_node_fs6.default.readdirSync(dir)) {
|
|
142549
|
-
import_node_fs6.default.rmSync(
|
|
142699
|
+
import_node_fs6.default.rmSync(import_node_path9.default.join(dir, entry), { recursive: true, force: true });
|
|
142550
142700
|
}
|
|
142551
142701
|
}
|
|
142552
142702
|
function prepareWorkdir(args) {
|
|
@@ -142576,19 +142726,19 @@ function prepareWorkdir(args) {
|
|
|
142576
142726
|
return dir;
|
|
142577
142727
|
}
|
|
142578
142728
|
function legacyChatSessionDir(workRoot, rtId) {
|
|
142579
|
-
return
|
|
142729
|
+
return import_node_path9.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
|
|
142580
142730
|
}
|
|
142581
|
-
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;
|
|
142582
142732
|
var init_session_paths = __esm({
|
|
142583
142733
|
"../adapters/src/_core/session-paths.ts"() {
|
|
142584
142734
|
"use strict";
|
|
142585
142735
|
import_node_crypto9 = require("node:crypto");
|
|
142586
142736
|
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
142587
|
-
|
|
142588
|
-
|
|
142737
|
+
import_node_os5 = __toESM(require("node:os"), 1);
|
|
142738
|
+
import_node_path9 = __toESM(require("node:path"), 1);
|
|
142589
142739
|
META_FILE = ".oasis-meta.json";
|
|
142590
142740
|
LOCK_FILE = ".oasis-lock";
|
|
142591
|
-
NEW_WORK_ROOT = () =>
|
|
142741
|
+
NEW_WORK_ROOT = () => import_node_path9.default.join(import_node_os5.default.homedir(), ".oasis", "work");
|
|
142592
142742
|
LEGACY_ROOTS = ["oasis-chat-sessions", "oasis-transcripts"];
|
|
142593
142743
|
LEGACY_ONESHOT_PREFIX = "oasis-session-";
|
|
142594
142744
|
}
|
|
@@ -143810,7 +143960,7 @@ async function discoverACPModels(bin, provider, args = ["acp"]) {
|
|
|
143810
143960
|
clientCapabilities: {}
|
|
143811
143961
|
});
|
|
143812
143962
|
try {
|
|
143813
|
-
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}-`));
|
|
143814
143964
|
} catch {
|
|
143815
143965
|
return fail();
|
|
143816
143966
|
}
|
|
@@ -143866,14 +144016,14 @@ function parseACPSessionNewModels(result) {
|
|
|
143866
144016
|
async function discoverOpenclawModels(bin) {
|
|
143867
144017
|
throw new Error("discoverOpenclawModels: TODO");
|
|
143868
144018
|
}
|
|
143869
|
-
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;
|
|
143870
144020
|
var init_models = __esm({
|
|
143871
144021
|
"../adapters/src/_core/models.ts"() {
|
|
143872
144022
|
"use strict";
|
|
143873
144023
|
import_node_child_process9 = require("node:child_process");
|
|
143874
144024
|
import_node_fs7 = require("node:fs");
|
|
143875
|
-
|
|
143876
|
-
|
|
144025
|
+
import_node_os6 = require("node:os");
|
|
144026
|
+
import_node_path10 = require("node:path");
|
|
143877
144027
|
modelCache = /* @__PURE__ */ new Map();
|
|
143878
144028
|
CACHE_TTL_MS = 6e4;
|
|
143879
144029
|
}
|
|
@@ -146440,7 +146590,7 @@ function dirSizeBytes(dir) {
|
|
|
146440
146590
|
return;
|
|
146441
146591
|
}
|
|
146442
146592
|
for (const e of entries) {
|
|
146443
|
-
const p2 =
|
|
146593
|
+
const p2 = import_node_path11.default.join(d, e.name);
|
|
146444
146594
|
if (e.isSymbolicLink()) continue;
|
|
146445
146595
|
if (e.isDirectory()) {
|
|
146446
146596
|
walk(p2);
|
|
@@ -146457,40 +146607,40 @@ function dirSizeBytes(dir) {
|
|
|
146457
146607
|
}
|
|
146458
146608
|
function listWorkdirs(workRoot, legacyRoot) {
|
|
146459
146609
|
const out = [];
|
|
146460
|
-
const sessions =
|
|
146610
|
+
const sessions = import_node_path11.default.join(workRoot, "sessions");
|
|
146461
146611
|
try {
|
|
146462
146612
|
for (const kind of import_node_fs8.default.readdirSync(sessions)) {
|
|
146463
|
-
const kindDir =
|
|
146613
|
+
const kindDir = import_node_path11.default.join(sessions, kind);
|
|
146464
146614
|
try {
|
|
146465
|
-
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));
|
|
146466
146616
|
} catch {
|
|
146467
146617
|
}
|
|
146468
146618
|
}
|
|
146469
146619
|
} catch {
|
|
146470
146620
|
}
|
|
146471
|
-
const tmp =
|
|
146621
|
+
const tmp = import_node_path11.default.join(workRoot, "tmp");
|
|
146472
146622
|
try {
|
|
146473
|
-
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));
|
|
146474
146624
|
} catch {
|
|
146475
146625
|
}
|
|
146476
146626
|
for (const legacy of LEGACY_ROOTS) {
|
|
146477
|
-
const root =
|
|
146627
|
+
const root = import_node_path11.default.join(legacyRoot, legacy);
|
|
146478
146628
|
try {
|
|
146479
|
-
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));
|
|
146480
146630
|
} catch {
|
|
146481
146631
|
}
|
|
146482
146632
|
}
|
|
146483
146633
|
try {
|
|
146484
146634
|
for (const d of import_node_fs8.default.readdirSync(legacyRoot)) {
|
|
146485
|
-
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(
|
|
146635
|
+
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(import_node_path11.default.join(legacyRoot, d));
|
|
146486
146636
|
}
|
|
146487
146637
|
} catch {
|
|
146488
146638
|
}
|
|
146489
146639
|
return [...new Set(out)];
|
|
146490
146640
|
}
|
|
146491
146641
|
function kindFromPath(workRoot, dir) {
|
|
146492
|
-
const rel =
|
|
146493
|
-
const parts = rel.split(
|
|
146642
|
+
const rel = import_node_path11.default.relative(workRoot, dir);
|
|
146643
|
+
const parts = rel.split(import_node_path11.default.sep);
|
|
146494
146644
|
if (parts[0] === "sessions" && parts[1]) return parts[1];
|
|
146495
146645
|
if (parts[0] === "tmp" && parts[1]) return parts[1].replace(/-[^-]*$/, "");
|
|
146496
146646
|
return void 0;
|
|
@@ -146532,7 +146682,7 @@ async function runGcSweep(deps) {
|
|
|
146532
146682
|
let deleted = 0;
|
|
146533
146683
|
for (const d of decisions) {
|
|
146534
146684
|
if (d.action !== "delete") continue;
|
|
146535
|
-
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)) {
|
|
146536
146686
|
log3(`[gc] \u8DF3\u8FC7 ${d.dir}\uFF1A\u6267\u884C\u524D\u590D\u67E5\u53D1\u73B0\u5DF2\u88AB\u5360\u7528`);
|
|
146537
146687
|
continue;
|
|
146538
146688
|
}
|
|
@@ -146583,12 +146733,12 @@ function startGcLoop(deps) {
|
|
|
146583
146733
|
clearInterval(timer);
|
|
146584
146734
|
};
|
|
146585
146735
|
}
|
|
146586
|
-
var import_node_fs8,
|
|
146736
|
+
var import_node_fs8, import_node_path11;
|
|
146587
146737
|
var init_gc_loop = __esm({
|
|
146588
146738
|
"../adapters/src/_core/gc-loop.ts"() {
|
|
146589
146739
|
"use strict";
|
|
146590
146740
|
import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
146591
|
-
|
|
146741
|
+
import_node_path11 = __toESM(require("node:path"), 1);
|
|
146592
146742
|
init_session_paths();
|
|
146593
146743
|
init_workdir_gc();
|
|
146594
146744
|
}
|
|
@@ -146624,14 +146774,14 @@ var init_src4 = __esm({
|
|
|
146624
146774
|
});
|
|
146625
146775
|
|
|
146626
146776
|
// ../connectors/src/connector-adapter.ts
|
|
146627
|
-
var
|
|
146777
|
+
var import_promises6, import_node_fs9, import_node_os7, import_node_path12, ConnectorAwareAdapter;
|
|
146628
146778
|
var init_connector_adapter = __esm({
|
|
146629
146779
|
"../connectors/src/connector-adapter.ts"() {
|
|
146630
146780
|
"use strict";
|
|
146631
|
-
|
|
146781
|
+
import_promises6 = require("node:fs/promises");
|
|
146632
146782
|
import_node_fs9 = require("node:fs");
|
|
146633
|
-
|
|
146634
|
-
|
|
146783
|
+
import_node_os7 = require("node:os");
|
|
146784
|
+
import_node_path12 = require("node:path");
|
|
146635
146785
|
init_src4();
|
|
146636
146786
|
init_base();
|
|
146637
146787
|
init_prepare_job();
|
|
@@ -146654,11 +146804,11 @@ var init_connector_adapter = __esm({
|
|
|
146654
146804
|
const wrapperPaths = [...prepared.job.wrapperPaths ?? [], ...sentinelWrappers];
|
|
146655
146805
|
let extraEnv = { ...strippedEnv };
|
|
146656
146806
|
if (wrapperPaths.length > 0) {
|
|
146657
|
-
const wrapperBinDir = await (0,
|
|
146658
|
-
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 });
|
|
146659
146809
|
for (const wp of wrapperPaths) {
|
|
146660
|
-
const linkName = (0,
|
|
146661
|
-
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));
|
|
146662
146812
|
}
|
|
146663
146813
|
extraEnv = { ...extraEnv, PATH: [wrapperBinDir, extraEnv["PATH"] ?? ""].filter(Boolean).join(":") };
|
|
146664
146814
|
log("[adapter]", ` connectors injected +${Date.now() - t0}ms wrappers=${wrapperPaths.length}`);
|
|
@@ -149445,12 +149595,12 @@ async function startOasisServer(opts) {
|
|
|
149445
149595
|
const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
|
|
149446
149596
|
if (actorCtx) {
|
|
149447
149597
|
const { mkdtempSync: mkdtempSync5, mkdirSync: mkdirSync21, writeFileSync: writeFileSync13 } = await import("node:fs");
|
|
149448
|
-
const { join:
|
|
149449
|
-
const { tmpdir:
|
|
149450
|
-
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-"));
|
|
149451
149601
|
if (actorCtx.config?.prompt) {
|
|
149452
149602
|
for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
149453
|
-
const file =
|
|
149603
|
+
const file = join31(dir, rel);
|
|
149454
149604
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149455
149605
|
writeFileSync13(file, content);
|
|
149456
149606
|
}
|
|
@@ -149462,12 +149612,12 @@ async function startOasisServer(opts) {
|
|
|
149462
149612
|
const s2 = byId.get(id);
|
|
149463
149613
|
return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
|
|
149464
149614
|
});
|
|
149465
|
-
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"));
|
|
149466
149616
|
}
|
|
149467
149617
|
if (opts.materializeSkills) {
|
|
149468
149618
|
const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
|
|
149469
149619
|
for (const [rel, content] of Object.entries(skillFiles)) {
|
|
149470
|
-
const file =
|
|
149620
|
+
const file = join31(dir, rel);
|
|
149471
149621
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149472
149622
|
writeFileSync13(file, content);
|
|
149473
149623
|
}
|
|
@@ -149481,7 +149631,7 @@ async function startOasisServer(opts) {
|
|
|
149481
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";
|
|
149482
149632
|
return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
|
|
149483
149633
|
});
|
|
149484
|
-
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"));
|
|
149485
149635
|
}
|
|
149486
149636
|
spawnCwd = dir;
|
|
149487
149637
|
}
|
|
@@ -149722,7 +149872,14 @@ async function startOasisServer(opts) {
|
|
|
149722
149872
|
baseUrl: base,
|
|
149723
149873
|
redirectPath: "/api/connectors/github/app/manifest-callback"
|
|
149724
149874
|
});
|
|
149725
|
-
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
|
+
});
|
|
149726
149883
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
149727
149884
|
state,
|
|
149728
149885
|
formAction: manifestFormAction(kind === "org" ? { kind: "org", login: owner.login } : { kind: "user" }, state),
|
|
@@ -149785,6 +149942,14 @@ async function startOasisServer(opts) {
|
|
|
149785
149942
|
}
|
|
149786
149943
|
try {
|
|
149787
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
|
+
}
|
|
149788
149953
|
const svc = opts.actors?.service;
|
|
149789
149954
|
if (!svc) throw new Error("actors service unavailable");
|
|
149790
149955
|
const scope = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
@@ -149852,7 +150017,10 @@ async function startOasisServer(opts) {
|
|
|
149852
150017
|
}
|
|
149853
150018
|
if (pending.slug) {
|
|
149854
150019
|
const bot = await fetchAppBotIdentity(pending.slug, { token: minted.token });
|
|
149855
|
-
if (bot)
|
|
150020
|
+
if (bot) {
|
|
150021
|
+
await put("GITHUB_APP_BOT_EMAIL", bot.email, false);
|
|
150022
|
+
await put("GITHUB_APP_BOT_NAME", bot.login, false);
|
|
150023
|
+
}
|
|
149856
150024
|
}
|
|
149857
150025
|
pending.done = true;
|
|
149858
150026
|
delete pending.privateKeyPem;
|
|
@@ -150437,9 +150605,11 @@ var init_memory_registry_store = __esm({
|
|
|
150437
150605
|
// key: ${runtimeId}::${modelId}
|
|
150438
150606
|
connectors = /* @__PURE__ */ new Map();
|
|
150439
150607
|
variables = /* @__PURE__ */ new Map();
|
|
150440
|
-
// key = key::actorId
|
|
150441
|
-
|
|
150442
|
-
|
|
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 ?? ""}`;
|
|
150443
150613
|
}
|
|
150444
150614
|
skillCatalog = /* @__PURE__ */ new Map();
|
|
150445
150615
|
installedSkills = /* @__PURE__ */ new Map();
|
|
@@ -150572,7 +150742,7 @@ var init_memory_registry_store = __esm({
|
|
|
150572
150742
|
this.skillFiles.delete(skillId);
|
|
150573
150743
|
}
|
|
150574
150744
|
async putVariable(v2) {
|
|
150575
|
-
this.variables.set(this._varKey(v2.key, v2.actorId), { ...v2 });
|
|
150745
|
+
this.variables.set(this._varKey(v2.key, v2.actorId, v2.projectId), { ...v2 });
|
|
150576
150746
|
}
|
|
150577
150747
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
150578
150748
|
const mk = this._varKey(key, actorId);
|
|
@@ -150587,8 +150757,11 @@ var init_memory_registry_store = __esm({
|
|
|
150587
150757
|
if (actorId !== void 0) return all.filter((v2) => v2.scope === "global" || v2.actorId === actorId).map((v2) => ({ ...v2 }));
|
|
150588
150758
|
return all.map((v2) => ({ ...v2 }));
|
|
150589
150759
|
}
|
|
150590
|
-
async
|
|
150591
|
-
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));
|
|
150592
150765
|
}
|
|
150593
150766
|
};
|
|
150594
150767
|
}
|
|
@@ -150887,6 +151060,7 @@ var init_memory_trace_store = __esm({
|
|
|
150887
151060
|
startedAt: run.startedAt,
|
|
150888
151061
|
effectiveModel: run.effectiveModel,
|
|
150889
151062
|
runtimeKind: run.runtimeKind,
|
|
151063
|
+
runtimeInstanceId: run.runtimeInstanceId ?? null,
|
|
150890
151064
|
usage: structuredClone(run.usage)
|
|
150891
151065
|
}));
|
|
150892
151066
|
}
|
|
@@ -154711,6 +154885,10 @@ async function sweepSilentSessions(deps) {
|
|
|
154711
154885
|
continue;
|
|
154712
154886
|
}
|
|
154713
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
|
+
}
|
|
154714
154892
|
const runtime = { hasInFlight: true, lastSessionEventAt: live.lastEventAt, openToolCall: live.openToolCall };
|
|
154715
154893
|
if (!isRuntimeSilent(runtime, deps.now, deps.silentThresholdMs)) continue;
|
|
154716
154894
|
const ok = await deps.kill(s2.jobKey).catch(() => false);
|
|
@@ -155410,6 +155588,73 @@ var init_recovery_plan = __esm({
|
|
|
155410
155588
|
}
|
|
155411
155589
|
});
|
|
155412
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
|
+
|
|
155413
155658
|
// ../server/src/domains/trace/sink.ts
|
|
155414
155659
|
function deriveMessage(payload) {
|
|
155415
155660
|
if (payload && typeof payload === "object") {
|
|
@@ -155419,11 +155664,10 @@ function deriveMessage(payload) {
|
|
|
155419
155664
|
}
|
|
155420
155665
|
return void 0;
|
|
155421
155666
|
}
|
|
155422
|
-
function trajectoryEventToRunEvent(e
|
|
155667
|
+
function trajectoryEventToRunEvent(e) {
|
|
155423
155668
|
const map = KIND_MAP[e.kind] ?? { eventType: "progress", stream: "runtime" };
|
|
155424
155669
|
const message = deriveMessage(e.payload);
|
|
155425
155670
|
return {
|
|
155426
|
-
seq,
|
|
155427
155671
|
eventType: map.eventType,
|
|
155428
155672
|
stream: map.stream,
|
|
155429
155673
|
...message !== void 0 ? { message } : {},
|
|
@@ -155502,6 +155746,7 @@ var KIND_MAP, MODEL_TEXT_LIMIT, TOOL_PREVIEW_LIMIT, PROGRESS_TOUCH_THROTTLE_MS,
|
|
|
155502
155746
|
var init_sink = __esm({
|
|
155503
155747
|
"../server/src/domains/trace/sink.ts"() {
|
|
155504
155748
|
"use strict";
|
|
155749
|
+
init_resilient_appender();
|
|
155505
155750
|
KIND_MAP = {
|
|
155506
155751
|
message: { eventType: "model.output.completed", stream: "model" },
|
|
155507
155752
|
thought: { eventType: "model.output.delta", stream: "model" },
|
|
@@ -155517,12 +155762,23 @@ var init_sink = __esm({
|
|
|
155517
155762
|
store;
|
|
155518
155763
|
runtimeKind;
|
|
155519
155764
|
onError;
|
|
155765
|
+
health;
|
|
155520
155766
|
sessions = /* @__PURE__ */ new Map();
|
|
155521
155767
|
constructor(opts) {
|
|
155522
155768
|
this.store = opts.store;
|
|
155523
155769
|
this.runtimeKind = opts.runtimeKind ?? "custom";
|
|
155524
155770
|
this.onError = opts.onError ?? (() => {
|
|
155525
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
|
+
});
|
|
155526
155782
|
}
|
|
155527
155783
|
runtimeKindFor(session) {
|
|
155528
155784
|
if (this.runtimeKind !== "auto") return this.runtimeKind;
|
|
@@ -155544,7 +155800,7 @@ var init_sink = __esm({
|
|
|
155544
155800
|
begin(session, _bundleFiles) {
|
|
155545
155801
|
const st = {
|
|
155546
155802
|
runId: session.runId,
|
|
155547
|
-
|
|
155803
|
+
appender: this.makeAppender(session.runId),
|
|
155548
155804
|
chain: Promise.resolve(),
|
|
155549
155805
|
openTools: /* @__PURE__ */ new Map(),
|
|
155550
155806
|
// runtimeSessionId:运行时自己的会话号(= 会话工作目录名,也是 --resume 的键)。落账后
|
|
@@ -155578,8 +155834,7 @@ var init_sink = __esm({
|
|
|
155578
155834
|
relation: "triggered_by",
|
|
155579
155835
|
createdAt: session.startedAt
|
|
155580
155836
|
});
|
|
155581
|
-
await
|
|
155582
|
-
seq: ++st.seq,
|
|
155837
|
+
await st.appender.append([{
|
|
155583
155838
|
eventType: "run.started",
|
|
155584
155839
|
stream: "runtime",
|
|
155585
155840
|
message: `${session.action} ${session.artifactId}`
|
|
@@ -155589,7 +155844,7 @@ var init_sink = __esm({
|
|
|
155589
155844
|
recover(session) {
|
|
155590
155845
|
const st = {
|
|
155591
155846
|
runId: session.runId,
|
|
155592
|
-
|
|
155847
|
+
appender: this.makeAppender(session.runId),
|
|
155593
155848
|
chain: Promise.resolve(),
|
|
155594
155849
|
openTools: /* @__PURE__ */ new Map(),
|
|
155595
155850
|
baseMetadata: { bundleManifest: session.bundleManifest, recovered: true },
|
|
@@ -155616,11 +155871,10 @@ var init_sink = __esm({
|
|
|
155616
155871
|
st.baseMetadata = { ...asMetadata(existing.metadata) ?? st.baseMetadata, recovered: true };
|
|
155617
155872
|
}
|
|
155618
155873
|
const events = await this.store.listEvents(session.runId, {});
|
|
155619
|
-
st.
|
|
155874
|
+
st.appender.resetSeq(events.reduce((max, event) => Math.max(max, event.seq), 0));
|
|
155620
155875
|
const recoveredAt = session.recoveredAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
155621
155876
|
const interruptedAt = session.interruptedAt ?? recoveredAt;
|
|
155622
|
-
await
|
|
155623
|
-
seq: ++st.seq,
|
|
155877
|
+
await st.appender.append([{
|
|
155624
155878
|
eventType: "progress",
|
|
155625
155879
|
stream: "system",
|
|
155626
155880
|
level: "warn",
|
|
@@ -155645,11 +155899,11 @@ var init_sink = __esm({
|
|
|
155645
155899
|
const ms = Date.parse(event.ts);
|
|
155646
155900
|
if (!Number.isNaN(ms) && ms - (st.lastProgressTouchMs ?? 0) >= PROGRESS_TOUCH_THROTTLE_MS) {
|
|
155647
155901
|
st.lastProgressTouchMs = ms;
|
|
155648
|
-
await
|
|
155902
|
+
await st.appender.update({ lastProgressAt: event.ts });
|
|
155649
155903
|
}
|
|
155650
155904
|
return;
|
|
155651
155905
|
}
|
|
155652
|
-
await
|
|
155906
|
+
await st.appender.append([trajectoryEventToRunEvent(event)]);
|
|
155653
155907
|
await this.materializeToolCall(st, event);
|
|
155654
155908
|
});
|
|
155655
155909
|
}
|
|
@@ -155700,8 +155954,7 @@ var init_sink = __esm({
|
|
|
155700
155954
|
const captured = this.sessions.get(sessionId);
|
|
155701
155955
|
this.enqueue(sessionId, async (st) => {
|
|
155702
155956
|
for (const ref2 of update.opRefs) {
|
|
155703
|
-
await
|
|
155704
|
-
seq: ++st.seq,
|
|
155957
|
+
await st.appender.append([{
|
|
155705
155958
|
eventType: "oplog.appended",
|
|
155706
155959
|
stream: "oasis",
|
|
155707
155960
|
message: ref2.kind,
|
|
@@ -155715,8 +155968,7 @@ var init_sink = __esm({
|
|
|
155715
155968
|
createdAt: update.exit.at
|
|
155716
155969
|
});
|
|
155717
155970
|
}
|
|
155718
|
-
await
|
|
155719
|
-
seq: ++st.seq,
|
|
155971
|
+
await st.appender.append([{
|
|
155720
155972
|
eventType: "run.finished",
|
|
155721
155973
|
stream: "runtime",
|
|
155722
155974
|
message: `exit code=${update.exit.code ?? "killed"} ops=${update.opRefs.length}`
|
|
@@ -155750,6 +156002,7 @@ var init_sink = __esm({
|
|
|
155750
156002
|
});
|
|
155751
156003
|
if (captured) captured.chain = captured.chain.finally(() => {
|
|
155752
156004
|
this.sessions.delete(sessionId);
|
|
156005
|
+
this.health?.forget(captured.runId);
|
|
155753
156006
|
});
|
|
155754
156007
|
}
|
|
155755
156008
|
};
|
|
@@ -155811,27 +156064,26 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155811
156064
|
live.emit(rest);
|
|
155812
156065
|
}
|
|
155813
156066
|
deps.register();
|
|
155814
|
-
|
|
155815
|
-
|
|
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
|
+
});
|
|
155816
156073
|
let traceChain = trace.listEvents(plan.runId, {}).then((events) => {
|
|
155817
|
-
|
|
156074
|
+
appender.resetSeq(events.reduce((n, e) => Math.max(n, e.seq), 0));
|
|
155818
156075
|
}).catch((err) => {
|
|
155819
|
-
|
|
155820
|
-
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)}`);
|
|
155821
156078
|
});
|
|
155822
156079
|
const enqueueTrace = (step) => {
|
|
155823
|
-
|
|
155824
|
-
|
|
155825
|
-
if (traceEnabled) await step();
|
|
155826
|
-
}).catch((err) => {
|
|
155827
|
-
traceEnabled = false;
|
|
155828
|
-
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)}`);
|
|
155829
156082
|
});
|
|
155830
156083
|
};
|
|
155831
156084
|
const recoveredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
155832
156085
|
enqueueTrace(async () => {
|
|
155833
|
-
await
|
|
155834
|
-
seq: ++traceSeq,
|
|
156086
|
+
await appender.append([{
|
|
155835
156087
|
eventType: "progress",
|
|
155836
156088
|
stream: "system",
|
|
155837
156089
|
level: "warn",
|
|
@@ -155855,11 +156107,11 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155855
156107
|
const ms = Date.parse(event.ts);
|
|
155856
156108
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
155857
156109
|
lastProgressTouchMs = ms;
|
|
155858
|
-
enqueueTrace(() =>
|
|
156110
|
+
enqueueTrace(() => appender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
155859
156111
|
}
|
|
155860
156112
|
return;
|
|
155861
156113
|
}
|
|
155862
|
-
enqueueTrace(() =>
|
|
156114
|
+
enqueueTrace(() => appender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
155863
156115
|
if (event.kind === "message" && sawTextOutput) return;
|
|
155864
156116
|
const part = chatPartFromTrajectoryEvent(event);
|
|
155865
156117
|
if (part) {
|
|
@@ -155940,14 +156192,13 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155940
156192
|
live.finish(failed ? "error" : "done");
|
|
155941
156193
|
deps.unregister();
|
|
155942
156194
|
enqueueTrace(async () => {
|
|
155943
|
-
await
|
|
155944
|
-
seq: ++traceSeq,
|
|
156195
|
+
await appender.append([{
|
|
155945
156196
|
eventType: "run.finished",
|
|
155946
156197
|
stream: "runtime",
|
|
155947
156198
|
message: `exit code=${info.code ?? "killed"}`,
|
|
155948
156199
|
startedAt: finishedAt
|
|
155949
156200
|
}]);
|
|
155950
|
-
await
|
|
156201
|
+
await appender.update(runTerminalPatch(info, plan.startedAt, finishedAt));
|
|
155951
156202
|
if (info.usage && trace.updateUsageAggregates) {
|
|
155952
156203
|
const run = await trace.getRun(plan.runId);
|
|
155953
156204
|
if (run) void trace.updateUsageAggregates(run).catch(() => void 0);
|
|
@@ -156044,17 +156295,17 @@ async function reconcileChatExitFrame(deps) {
|
|
|
156044
156295
|
}).catch(() => void 0);
|
|
156045
156296
|
try {
|
|
156046
156297
|
const events = await deps.trace.listEvents(row.runId, {});
|
|
156047
|
-
|
|
156048
|
-
|
|
156049
|
-
...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)),
|
|
156050
156301
|
{
|
|
156051
|
-
seq: ++traceSeq,
|
|
156052
156302
|
eventType: "run.finished",
|
|
156053
156303
|
stream: "runtime",
|
|
156054
156304
|
message: `exit code=${info.code ?? "killed"}\uFF08serve \u505C\u673A\u7A97\u53E3\u5185\u7ED3\u675F\uFF0C\u8282\u70B9 outbox \u91CD\u53D1\u5BF9\u8D26\uFF09`,
|
|
156055
156305
|
startedAt: finishedAt
|
|
156056
156306
|
}
|
|
156057
|
-
]
|
|
156307
|
+
];
|
|
156308
|
+
await deps.trace.appendEvents(row.runId, seqless.map((e, i) => ({ ...e, seq: baseSeq + i + 1 })));
|
|
156058
156309
|
await deps.trace.updateRun(row.runId, runTerminalPatch(info, run.startedAt, finishedAt));
|
|
156059
156310
|
if (info.usage && deps.trace.updateUsageAggregates) {
|
|
156060
156311
|
const fresh = await deps.trace.getRun(row.runId);
|
|
@@ -156075,6 +156326,7 @@ var init_chat_recovery = __esm({
|
|
|
156075
156326
|
import_node_crypto20 = require("node:crypto");
|
|
156076
156327
|
init_chat_parts();
|
|
156077
156328
|
init_sink();
|
|
156329
|
+
init_resilient_appender();
|
|
156078
156330
|
asObj3 = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
156079
156331
|
partsOf = (parts) => Array.isArray(parts) ? parts.filter((p2) => p2 && typeof p2 === "object" && typeof p2.type === "string") : [];
|
|
156080
156332
|
maxPartSeq = (parts) => parts.reduce((n, p2) => Math.max(n, typeof p2.seq === "number" ? p2.seq : 0), 0);
|
|
@@ -156668,6 +156920,24 @@ var init_skill_fetcher = __esm({
|
|
|
156668
156920
|
});
|
|
156669
156921
|
|
|
156670
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
|
+
}
|
|
156671
156941
|
function computeEffectiveEntries(config2, connections, connectors) {
|
|
156672
156942
|
const globalConnected = new Set(connectors.filter((c) => c.status === "connected").map((c) => c.id));
|
|
156673
156943
|
const record6 = new Map(connections.map((c) => [c.connectorId, c.enabled]));
|
|
@@ -156699,6 +156969,7 @@ var init_service3 = __esm({
|
|
|
156699
156969
|
init_skill_fetcher();
|
|
156700
156970
|
init_identity();
|
|
156701
156971
|
init_src5();
|
|
156972
|
+
init_src();
|
|
156702
156973
|
REDACTED_MARKER = "[REDACTED]";
|
|
156703
156974
|
ActorsService = class {
|
|
156704
156975
|
constructor(opts) {
|
|
@@ -157352,8 +157623,11 @@ ${input.description}
|
|
|
157352
157623
|
key: v2.key,
|
|
157353
157624
|
scope: v2.scope,
|
|
157354
157625
|
...v2.actorId !== void 0 ? { actorId: v2.actorId } : {},
|
|
157626
|
+
...v2.projectId !== void 0 ? { projectId: v2.projectId } : {},
|
|
157355
157627
|
...v2.connectorId !== void 0 ? { connectorId: v2.connectorId } : {},
|
|
157356
157628
|
...v2.overrides !== void 0 ? { overrides: v2.overrides } : {},
|
|
157629
|
+
// 缺省 "env"(存量行为不变,敏感项需显式选 "ref",ADR §4.4 / 待确认 3)
|
|
157630
|
+
deliveryMode: v2.deliveryMode ?? "env",
|
|
157357
157631
|
valueEncrypted: v2.encrypted === false ? `plain:${v2.value}` : this.encrypt(v2.value),
|
|
157358
157632
|
updatedAt: this.now()
|
|
157359
157633
|
});
|
|
@@ -157389,8 +157663,11 @@ ${input.description}
|
|
|
157389
157663
|
key: r.key,
|
|
157390
157664
|
scope: r.scope,
|
|
157391
157665
|
...r.actorId !== void 0 ? { actorId: r.actorId } : {},
|
|
157666
|
+
...r.projectId !== void 0 ? { projectId: r.projectId } : {},
|
|
157392
157667
|
...r.connectorId !== void 0 ? { connectorId: r.connectorId } : {},
|
|
157393
157668
|
...r.overrides !== void 0 ? { overrides: r.overrides } : {},
|
|
157669
|
+
deliveryMode: r.deliveryMode ?? "env",
|
|
157670
|
+
// 缺省视为 env(ADR §4.4;存量行读侧统一回填)
|
|
157394
157671
|
encrypted: !isPlain,
|
|
157395
157672
|
maskedValue: isPlain ? r.valueEncrypted.slice(6) : mask(this.decrypt(r.valueEncrypted)),
|
|
157396
157673
|
updatedAt: r.updatedAt
|
|
@@ -157414,8 +157691,13 @@ ${input.description}
|
|
|
157414
157691
|
}
|
|
157415
157692
|
return this.revealVariable(key, void 0);
|
|
157416
157693
|
}
|
|
157417
|
-
deleteVariable(key, actorId) {
|
|
157418
|
-
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);
|
|
157419
157701
|
}
|
|
157420
157702
|
async resolveActorEnv(actorId) {
|
|
157421
157703
|
const cfg = await this.opts.store.latestConfig(actorId);
|
|
@@ -157445,6 +157727,64 @@ ${input.description}
|
|
|
157445
157727
|
}
|
|
157446
157728
|
return env;
|
|
157447
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
|
+
}
|
|
157448
157788
|
encrypt(plain) {
|
|
157449
157789
|
const iv = (0, import_node_crypto22.randomBytes)(12);
|
|
157450
157790
|
const cipher = (0, import_node_crypto22.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
@@ -158453,7 +158793,7 @@ var init_skill_materializer = __esm({
|
|
|
158453
158793
|
|
|
158454
158794
|
// ../server/src/governance/connector-skills.ts
|
|
158455
158795
|
function connectorSkillsDir(dataDir, connectorId) {
|
|
158456
|
-
return (0,
|
|
158796
|
+
return (0, import_node_path13.join)(dataDir, "connector-skills", connectorId);
|
|
158457
158797
|
}
|
|
158458
158798
|
function parseConnectorSkillId(id) {
|
|
158459
158799
|
if (!id.startsWith("connector:")) return null;
|
|
@@ -158463,17 +158803,17 @@ function parseConnectorSkillId(id) {
|
|
|
158463
158803
|
return { connectorId: rest.slice(0, i), slug: rest.slice(i + 1) };
|
|
158464
158804
|
}
|
|
158465
158805
|
async function collect(root, dir, out) {
|
|
158466
|
-
for (const e of await (0,
|
|
158467
|
-
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);
|
|
158468
158808
|
if (e.isDirectory()) await collect(root, abs, out);
|
|
158469
|
-
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");
|
|
158470
158810
|
}
|
|
158471
158811
|
}
|
|
158472
158812
|
async function readLocalPack(dataDir, connectorId) {
|
|
158473
158813
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158474
158814
|
let slugs;
|
|
158475
158815
|
try {
|
|
158476
|
-
slugs = (await (0,
|
|
158816
|
+
slugs = (await (0, import_promises7.readdir)(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
158477
158817
|
} catch {
|
|
158478
158818
|
return [];
|
|
158479
158819
|
}
|
|
@@ -158481,7 +158821,7 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158481
158821
|
for (const slug6 of slugs) {
|
|
158482
158822
|
const files = {};
|
|
158483
158823
|
try {
|
|
158484
|
-
await collect((0,
|
|
158824
|
+
await collect((0, import_node_path13.join)(root, slug6), (0, import_node_path13.join)(root, slug6), files);
|
|
158485
158825
|
} catch {
|
|
158486
158826
|
continue;
|
|
158487
158827
|
}
|
|
@@ -158497,17 +158837,17 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158497
158837
|
async function writePack(dataDir, connectorId, pack) {
|
|
158498
158838
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158499
158839
|
const tmp = `${root}.tmp`;
|
|
158500
|
-
await (0,
|
|
158840
|
+
await (0, import_promises7.rm)(tmp, { recursive: true, force: true });
|
|
158501
158841
|
for (const s2 of pack) {
|
|
158502
158842
|
for (const [rel, content] of Object.entries(s2.files)) {
|
|
158503
|
-
const abs = (0,
|
|
158504
|
-
await (0,
|
|
158505
|
-
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");
|
|
158506
158846
|
}
|
|
158507
158847
|
}
|
|
158508
|
-
await (0,
|
|
158509
|
-
await (0,
|
|
158510
|
-
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);
|
|
158511
158851
|
}
|
|
158512
158852
|
function packMatches(local, remote) {
|
|
158513
158853
|
if (local.length !== remote.length) return false;
|
|
@@ -158534,18 +158874,21 @@ async function syncConnectorSkills(args) {
|
|
|
158534
158874
|
log3(`[connector-skills] ${args.connectorId}\uFF1A\u5DF2\u4ECE\u5382\u5546\u540C\u6B65 ${fresh.length} \u4E2A\u6280\u80FD`);
|
|
158535
158875
|
return { skills: fresh, outcome: "fetched" };
|
|
158536
158876
|
}
|
|
158537
|
-
var
|
|
158877
|
+
var import_promises7, import_node_path13, toId;
|
|
158538
158878
|
var init_connector_skills = __esm({
|
|
158539
158879
|
"../server/src/governance/connector-skills.ts"() {
|
|
158540
158880
|
"use strict";
|
|
158541
|
-
|
|
158542
|
-
|
|
158881
|
+
import_promises7 = require("node:fs/promises");
|
|
158882
|
+
import_node_path13 = require("node:path");
|
|
158543
158883
|
init_src5();
|
|
158544
158884
|
toId = (connectorId, slug6) => `connector:${connectorId}/${slug6}`;
|
|
158545
158885
|
}
|
|
158546
158886
|
});
|
|
158547
158887
|
|
|
158548
158888
|
// ../server/src/domains/actors/routes.ts
|
|
158889
|
+
function isKnownRevealSource(source) {
|
|
158890
|
+
return CREDENTIAL_REVEAL_SOURCES.has(source) || source.startsWith("agent-skill:");
|
|
158891
|
+
}
|
|
158549
158892
|
function positionsFromPayload(body) {
|
|
158550
158893
|
if (!body) return void 0;
|
|
158551
158894
|
if (Object.prototype.hasOwnProperty.call(body, "roles")) {
|
|
@@ -158578,6 +158921,8 @@ function actorApiRecord(actor) {
|
|
|
158578
158921
|
}
|
|
158579
158922
|
function actorsDomain(opts) {
|
|
158580
158923
|
const { resolveCtx } = opts;
|
|
158924
|
+
const revealLimits = opts.credentialRevealLimits ?? { perSession: 200, perSessionPerKey: 20 };
|
|
158925
|
+
const revealLimiter = new RevealRateLimiter(revealLimits.perSession, revealLimits.perSessionPerKey);
|
|
158581
158926
|
return (router) => {
|
|
158582
158927
|
router.get("/api/actors", async (req) => {
|
|
158583
158928
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
@@ -158817,11 +159162,23 @@ function actorsDomain(opts) {
|
|
|
158817
159162
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158818
159163
|
const b2 = req.body;
|
|
158819
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
|
+
}
|
|
158820
159175
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158821
159176
|
await service.putVariable({
|
|
158822
159177
|
key: b2.key,
|
|
158823
159178
|
value: b2.value,
|
|
158824
|
-
scope
|
|
159179
|
+
scope,
|
|
159180
|
+
...scope === "project" ? { projectId: b2.projectId } : {},
|
|
159181
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158825
159182
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158826
159183
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158827
159184
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158830,7 +159187,12 @@ function actorsDomain(opts) {
|
|
|
158830
159187
|
});
|
|
158831
159188
|
router.delete("/api/variables/:key", async (req) => {
|
|
158832
159189
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158833
|
-
|
|
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
|
+
);
|
|
158834
159196
|
return { status: 200, body: { ok: true } };
|
|
158835
159197
|
});
|
|
158836
159198
|
router.get("/api/actors/:id/variables", async (req) => {
|
|
@@ -158842,6 +159204,9 @@ function actorsDomain(opts) {
|
|
|
158842
159204
|
const actorId = req.params.id;
|
|
158843
159205
|
const b2 = req.body;
|
|
158844
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
|
+
}
|
|
158845
159210
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158846
159211
|
if (b2.connectorId === void 0) {
|
|
158847
159212
|
const existing = await service.listVariables(actorId);
|
|
@@ -158859,6 +159224,7 @@ function actorsDomain(opts) {
|
|
|
158859
159224
|
value: b2.value,
|
|
158860
159225
|
actorId,
|
|
158861
159226
|
scope: "personal",
|
|
159227
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158862
159228
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158863
159229
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158864
159230
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158870,6 +159236,51 @@ function actorsDomain(opts) {
|
|
|
158870
159236
|
await service.deleteVariable(req.params.key, req.params.id);
|
|
158871
159237
|
return { status: 200, body: { ok: true } };
|
|
158872
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
|
+
});
|
|
158873
159284
|
router.get("/api/skills/market", async (req) => {
|
|
158874
159285
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158875
159286
|
const [catalog, installed] = await Promise.all([
|
|
@@ -159028,6 +159439,18 @@ function actorsDomain(opts) {
|
|
|
159028
159439
|
const results = await opts.refreshConnectorSkills();
|
|
159029
159440
|
return { status: 200, body: { results } };
|
|
159030
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
|
+
});
|
|
159031
159454
|
router.get("/api/skill-cache/manifest", async (req) => {
|
|
159032
159455
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
159033
159456
|
const builtins = opts.getBuiltinSkills?.() ?? [];
|
|
@@ -159306,12 +159729,15 @@ function actorsDomain(opts) {
|
|
|
159306
159729
|
});
|
|
159307
159730
|
};
|
|
159308
159731
|
}
|
|
159732
|
+
var CREDENTIAL_REVEAL_SOURCES, RevealRateLimiter;
|
|
159309
159733
|
var init_routes = __esm({
|
|
159310
159734
|
"../server/src/domains/actors/routes.ts"() {
|
|
159311
159735
|
"use strict";
|
|
159312
159736
|
init_src();
|
|
159313
159737
|
init_src2();
|
|
159314
159738
|
init_router();
|
|
159739
|
+
init_src();
|
|
159740
|
+
init_src5();
|
|
159315
159741
|
init_memory();
|
|
159316
159742
|
init_skill_fetcher();
|
|
159317
159743
|
init_stats();
|
|
@@ -159320,6 +159746,44 @@ var init_routes = __esm({
|
|
|
159320
159746
|
init_image_upload();
|
|
159321
159747
|
init_skill_materializer();
|
|
159322
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
|
+
};
|
|
159323
159787
|
}
|
|
159324
159788
|
});
|
|
159325
159789
|
|
|
@@ -159418,7 +159882,7 @@ function createActorsDomain(opts) {
|
|
|
159418
159882
|
return {
|
|
159419
159883
|
service: defaultCtx.service,
|
|
159420
159884
|
resolveCtx,
|
|
159421
|
-
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 } : {} })
|
|
159422
159886
|
};
|
|
159423
159887
|
}
|
|
159424
159888
|
var import_node_crypto24;
|
|
@@ -161847,10 +162311,10 @@ function nodesDomain(deps) {
|
|
|
161847
162311
|
}
|
|
161848
162312
|
}
|
|
161849
162313
|
try {
|
|
161850
|
-
const here = (0,
|
|
162314
|
+
const here = (0, import_node_path14.dirname)((0, import_node_url4.fileURLToPath)(__esm_import_meta_url));
|
|
161851
162315
|
for (const rel of ["../../../../node-daemon/package.json", "../../../../../node-daemon/package.json"]) {
|
|
161852
162316
|
try {
|
|
161853
|
-
const raw = (0, import_node_fs11.readFileSync)((0,
|
|
162317
|
+
const raw = (0, import_node_fs11.readFileSync)((0, import_node_path14.resolve)(here, rel), "utf8");
|
|
161854
162318
|
const pkg = JSON.parse(raw);
|
|
161855
162319
|
if (pkg.version) return { version: pkg.version, source: "monorepo" };
|
|
161856
162320
|
} catch {
|
|
@@ -162162,14 +162626,14 @@ function nodesDomain(deps) {
|
|
|
162162
162626
|
});
|
|
162163
162627
|
};
|
|
162164
162628
|
}
|
|
162165
|
-
var import_node_crypto26, import_node_fs11, import_node_url4,
|
|
162629
|
+
var import_node_crypto26, import_node_fs11, import_node_url4, import_node_path14;
|
|
162166
162630
|
var init_routes5 = __esm({
|
|
162167
162631
|
"../server/src/domains/nodes/routes.ts"() {
|
|
162168
162632
|
"use strict";
|
|
162169
162633
|
import_node_crypto26 = require("node:crypto");
|
|
162170
162634
|
import_node_fs11 = require("node:fs");
|
|
162171
162635
|
import_node_url4 = require("node:url");
|
|
162172
|
-
|
|
162636
|
+
import_node_path14 = require("node:path");
|
|
162173
162637
|
init_src4();
|
|
162174
162638
|
init_connect_script();
|
|
162175
162639
|
init_node_health();
|
|
@@ -163324,6 +163788,9 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163324
163788
|
const runtimeRunCounts = /* @__PURE__ */ new Map();
|
|
163325
163789
|
const runtimeModels = /* @__PURE__ */ new Map();
|
|
163326
163790
|
const runtimeEmployees = /* @__PURE__ */ new Map();
|
|
163791
|
+
const runtimeInstanceKind = /* @__PURE__ */ new Map();
|
|
163792
|
+
const runtimeHostnames = input.runtimeHostnames ?? /* @__PURE__ */ new Map();
|
|
163793
|
+
const runtimeNodeNames = input.runtimeNodeNames ?? /* @__PURE__ */ new Map();
|
|
163327
163794
|
for (const run of input.runs) {
|
|
163328
163795
|
const usage = usageOf(run);
|
|
163329
163796
|
if (!usage) {
|
|
@@ -163379,18 +163846,19 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163379
163846
|
empWoMap.set(rowId, empWoUsage);
|
|
163380
163847
|
}
|
|
163381
163848
|
addUsage(empWoUsage.usage, usage);
|
|
163382
|
-
const
|
|
163383
|
-
let rtUsage = runtimeTotals.get(
|
|
163849
|
+
const rtKey = run.runtimeInstanceId ?? `__unregistered__:${run.runtimeKind}`;
|
|
163850
|
+
let rtUsage = runtimeTotals.get(rtKey);
|
|
163384
163851
|
if (!rtUsage) {
|
|
163385
163852
|
rtUsage = emptyUsage();
|
|
163386
|
-
runtimeTotals.set(
|
|
163853
|
+
runtimeTotals.set(rtKey, rtUsage);
|
|
163854
|
+
runtimeInstanceKind.set(rtKey, run.runtimeKind);
|
|
163387
163855
|
}
|
|
163388
163856
|
addUsage(rtUsage, usage);
|
|
163389
|
-
runtimeRunCounts.set(
|
|
163390
|
-
let modelMap = runtimeModels.get(
|
|
163857
|
+
runtimeRunCounts.set(rtKey, (runtimeRunCounts.get(rtKey) ?? 0) + 1);
|
|
163858
|
+
let modelMap = runtimeModels.get(rtKey);
|
|
163391
163859
|
if (!modelMap) {
|
|
163392
163860
|
modelMap = /* @__PURE__ */ new Map();
|
|
163393
|
-
runtimeModels.set(
|
|
163861
|
+
runtimeModels.set(rtKey, modelMap);
|
|
163394
163862
|
}
|
|
163395
163863
|
let modelUsage = modelMap.get(run.effectiveModel);
|
|
163396
163864
|
if (!modelUsage) {
|
|
@@ -163398,10 +163866,10 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163398
163866
|
modelMap.set(run.effectiveModel, modelUsage);
|
|
163399
163867
|
}
|
|
163400
163868
|
addUsage(modelUsage, usage);
|
|
163401
|
-
let rtEmpMap = runtimeEmployees.get(
|
|
163869
|
+
let rtEmpMap = runtimeEmployees.get(rtKey);
|
|
163402
163870
|
if (!rtEmpMap) {
|
|
163403
163871
|
rtEmpMap = /* @__PURE__ */ new Map();
|
|
163404
|
-
runtimeEmployees.set(
|
|
163872
|
+
runtimeEmployees.set(rtKey, rtEmpMap);
|
|
163405
163873
|
}
|
|
163406
163874
|
let rtEmpUsage = rtEmpMap.get(run.actorId);
|
|
163407
163875
|
if (!rtEmpUsage) {
|
|
@@ -163453,9 +163921,33 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163453
163921
|
(e) => e.share,
|
|
163454
163922
|
(e, s2) => ({ ...e, share: s2 })
|
|
163455
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
|
+
}
|
|
163940
|
+
function resolveHostname(rtKey, kind) {
|
|
163941
|
+
const h = runtimeHostnames.get(rtKey);
|
|
163942
|
+
if (h) return h;
|
|
163943
|
+
const nodeId = parseNodeId(rtKey);
|
|
163944
|
+
if (nodeId) return nodeId;
|
|
163945
|
+
return kind;
|
|
163946
|
+
}
|
|
163456
163947
|
const runtimeRows = normalizeShares(
|
|
163457
|
-
[...runtimeTotals].map(([
|
|
163458
|
-
const
|
|
163948
|
+
[...runtimeTotals].map(([rtKey, usage]) => {
|
|
163949
|
+
const kind = runtimeInstanceKind.get(rtKey) ?? "unknown";
|
|
163950
|
+
const modelMap = runtimeModels.get(rtKey) ?? /* @__PURE__ */ new Map();
|
|
163459
163951
|
const models = normalizeShares(
|
|
163460
163952
|
[...modelMap].map(([model, modelUsage]) => ({
|
|
163461
163953
|
model,
|
|
@@ -163465,7 +163957,7 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163465
163957
|
(m2) => m2.share,
|
|
163466
163958
|
(m2, s2) => ({ ...m2, share: s2 })
|
|
163467
163959
|
);
|
|
163468
|
-
const empMap = runtimeEmployees.get(
|
|
163960
|
+
const empMap = runtimeEmployees.get(rtKey);
|
|
163469
163961
|
const employees = normalizeShares(
|
|
163470
163962
|
empMap ? [...empMap].map(([actorId, empUsage]) => ({
|
|
163471
163963
|
actorId,
|
|
@@ -163476,10 +163968,14 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163476
163968
|
(e, s2) => ({ ...e, share: s2 })
|
|
163477
163969
|
);
|
|
163478
163970
|
return {
|
|
163479
|
-
|
|
163971
|
+
runtimeInstanceId: rtKey,
|
|
163972
|
+
nodeId: parseNodeId(rtKey),
|
|
163973
|
+
displayName: resolveDisplayName(rtKey, kind),
|
|
163974
|
+
hostname: resolveHostname(rtKey, kind),
|
|
163975
|
+
runtimeKind: kind,
|
|
163480
163976
|
usage,
|
|
163481
163977
|
share: total.tokens > 0 ? usage.tokens / total.tokens : 0,
|
|
163482
|
-
runCount: runtimeRunCounts.get(
|
|
163978
|
+
runCount: runtimeRunCounts.get(rtKey) ?? 0,
|
|
163483
163979
|
models,
|
|
163484
163980
|
employees
|
|
163485
163981
|
};
|
|
@@ -163512,12 +164008,12 @@ function nameKey(name) {
|
|
|
163512
164008
|
function cleanName(name) {
|
|
163513
164009
|
return name.trim().replace(/\s+/g, " ");
|
|
163514
164010
|
}
|
|
163515
|
-
var import_node_fs12,
|
|
164011
|
+
var import_node_fs12, import_node_path15, import_node_crypto27, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
163516
164012
|
var init_tags = __esm({
|
|
163517
164013
|
"../server/src/domains/collab/tags.ts"() {
|
|
163518
164014
|
"use strict";
|
|
163519
164015
|
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
163520
|
-
|
|
164016
|
+
import_node_path15 = __toESM(require("node:path"), 1);
|
|
163521
164017
|
import_node_crypto27 = __toESM(require("node:crypto"), 1);
|
|
163522
164018
|
SEP = "::";
|
|
163523
164019
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
@@ -163603,7 +164099,7 @@ var init_tags = __esm({
|
|
|
163603
164099
|
}
|
|
163604
164100
|
persist() {
|
|
163605
164101
|
try {
|
|
163606
|
-
import_node_fs12.default.mkdirSync(
|
|
164102
|
+
import_node_fs12.default.mkdirSync(import_node_path15.default.dirname(this.file), { recursive: true });
|
|
163607
164103
|
const tmp = `${this.file}.tmp`;
|
|
163608
164104
|
import_node_fs12.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
163609
164105
|
import_node_fs12.default.renameSync(tmp, this.file);
|
|
@@ -163744,10 +164240,22 @@ function collabDomain(opts) {
|
|
|
163744
164240
|
return { status: 400, body: { error: { code: "bad_request", message: "timeZone \u65E0\u6548" } } };
|
|
163745
164241
|
}
|
|
163746
164242
|
const { kernel } = await resolveCtx(req.auth.companyId);
|
|
163747
|
-
const runs = await
|
|
164243
|
+
const [runs, runtimeRecords, nodeRecords] = await Promise.all([
|
|
164244
|
+
opts.trace.listUsageRuns({ from, to }),
|
|
164245
|
+
opts.listRuntimes ? opts.listRuntimes().catch(() => []) : Promise.resolve([]),
|
|
164246
|
+
opts.listNodes ? opts.listNodes().catch(() => []) : Promise.resolve([])
|
|
164247
|
+
]);
|
|
164248
|
+
const runtimeHostnames = /* @__PURE__ */ new Map();
|
|
164249
|
+
for (const rt of runtimeRecords) {
|
|
164250
|
+
if (rt.id && rt.hostname) runtimeHostnames.set(rt.id, rt.hostname);
|
|
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
|
+
}
|
|
163748
164256
|
return {
|
|
163749
164257
|
status: 200,
|
|
163750
|
-
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone })
|
|
164258
|
+
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames, runtimeNodeNames })
|
|
163751
164259
|
};
|
|
163752
164260
|
});
|
|
163753
164261
|
router.get("/api/workorders", async (req) => {
|
|
@@ -164547,10 +165055,10 @@ function tokenType(p2) {
|
|
|
164547
165055
|
function parseOtlpMetricsUsage(body) {
|
|
164548
165056
|
const req = body;
|
|
164549
165057
|
const out = [];
|
|
164550
|
-
for (const
|
|
164551
|
-
const runId = attrString(
|
|
165058
|
+
for (const rm5 of req.resourceMetrics ?? []) {
|
|
165059
|
+
const runId = attrString(rm5.resource?.attributes, "oasis.run_id");
|
|
164552
165060
|
if (!runId) continue;
|
|
164553
|
-
const actorId = attrString(
|
|
165061
|
+
const actorId = attrString(rm5.resource?.attributes, "oasis.actor_id");
|
|
164554
165062
|
let input = 0;
|
|
164555
165063
|
let output = 0;
|
|
164556
165064
|
let cacheRead = 0;
|
|
@@ -164558,7 +165066,7 @@ function parseOtlpMetricsUsage(body) {
|
|
|
164558
165066
|
let costUsd = 0;
|
|
164559
165067
|
let sawToken = false;
|
|
164560
165068
|
let sawCost = false;
|
|
164561
|
-
for (const sm of
|
|
165069
|
+
for (const sm of rm5.scopeMetrics ?? []) {
|
|
164562
165070
|
for (const m2 of sm.metrics ?? []) {
|
|
164563
165071
|
const name = (m2.name ?? "").toLowerCase();
|
|
164564
165072
|
const points = m2.sum?.dataPoints ?? m2.gauge?.dataPoints ?? [];
|
|
@@ -164934,6 +165442,30 @@ var init_routes6 = __esm({
|
|
|
164934
165442
|
}
|
|
164935
165443
|
});
|
|
164936
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
|
+
|
|
164937
165469
|
// ../server/src/domains/trace/index.ts
|
|
164938
165470
|
function createTraceDomain(opts) {
|
|
164939
165471
|
const service = new TraceService({ store: opts.store });
|
|
@@ -164948,6 +165480,8 @@ var init_trace2 = __esm({
|
|
|
164948
165480
|
init_routes6();
|
|
164949
165481
|
init_sink();
|
|
164950
165482
|
init_chat_parts();
|
|
165483
|
+
init_trace_health();
|
|
165484
|
+
init_resilient_appender();
|
|
164951
165485
|
}
|
|
164952
165486
|
});
|
|
164953
165487
|
|
|
@@ -167019,12 +167553,12 @@ function normalize(patch) {
|
|
|
167019
167553
|
...reviewRoles !== void 0 ? { reviewRoles: [...new Set(reviewRoles.map((r) => r.trim()).filter(Boolean))] } : {}
|
|
167020
167554
|
};
|
|
167021
167555
|
}
|
|
167022
|
-
var import_node_fs13,
|
|
167556
|
+
var import_node_fs13, import_node_path16, SEP2, keyOf2, prefixOf2, MemoryPlaybookOverrideStore, FilePlaybookOverrideStore;
|
|
167023
167557
|
var init_overrides = __esm({
|
|
167024
167558
|
"../server/src/domains/playbooks/overrides.ts"() {
|
|
167025
167559
|
"use strict";
|
|
167026
167560
|
import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
167027
|
-
|
|
167561
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
167028
167562
|
SEP2 = "::";
|
|
167029
167563
|
keyOf2 = (companyId, ref2, nodeKey) => `${companyId}${SEP2}${ref2}${SEP2}${nodeKey}`;
|
|
167030
167564
|
prefixOf2 = (companyId, ref2) => `${companyId}${SEP2}${ref2}${SEP2}`;
|
|
@@ -167063,7 +167597,7 @@ var init_overrides = __esm({
|
|
|
167063
167597
|
}
|
|
167064
167598
|
persist() {
|
|
167065
167599
|
try {
|
|
167066
|
-
import_node_fs13.default.mkdirSync(
|
|
167600
|
+
import_node_fs13.default.mkdirSync(import_node_path16.default.dirname(this.file), { recursive: true });
|
|
167067
167601
|
const tmp = `${this.file}.tmp`;
|
|
167068
167602
|
import_node_fs13.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167069
167603
|
import_node_fs13.default.renameSync(tmp, this.file);
|
|
@@ -167502,12 +168036,12 @@ var init_daemon_adapter = __esm({
|
|
|
167502
168036
|
});
|
|
167503
168037
|
|
|
167504
168038
|
// ../server/src/side-map.ts
|
|
167505
|
-
var import_node_fs14,
|
|
168039
|
+
var import_node_fs14, import_node_path17, FileSideMap;
|
|
167506
168040
|
var init_side_map = __esm({
|
|
167507
168041
|
"../server/src/side-map.ts"() {
|
|
167508
168042
|
"use strict";
|
|
167509
168043
|
import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
167510
|
-
|
|
168044
|
+
import_node_path17 = __toESM(require("node:path"), 1);
|
|
167511
168045
|
FileSideMap = class {
|
|
167512
168046
|
constructor(file) {
|
|
167513
168047
|
this.file = file;
|
|
@@ -167534,7 +168068,7 @@ var init_side_map = __esm({
|
|
|
167534
168068
|
}
|
|
167535
168069
|
persist() {
|
|
167536
168070
|
try {
|
|
167537
|
-
import_node_fs14.default.mkdirSync(
|
|
168071
|
+
import_node_fs14.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
|
|
167538
168072
|
const tmp = `${this.file}.tmp`;
|
|
167539
168073
|
import_node_fs14.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167540
168074
|
import_node_fs14.default.renameSync(tmp, this.file);
|
|
@@ -168990,26 +169524,26 @@ ${ctx.nodeFault}
|
|
|
168990
169524
|
|
|
168991
169525
|
// ../server/src/governance/builtin-skills.ts
|
|
168992
169526
|
async function collectDir(root, dir, out) {
|
|
168993
|
-
const entries = await (0,
|
|
169527
|
+
const entries = await (0, import_promises8.readdir)(dir, { withFileTypes: true });
|
|
168994
169528
|
for (const e of entries) {
|
|
168995
|
-
const abs = (0,
|
|
169529
|
+
const abs = (0, import_node_path18.join)(dir, e.name);
|
|
168996
169530
|
if (e.isDirectory()) {
|
|
168997
169531
|
await collectDir(root, abs, out);
|
|
168998
169532
|
} else if (e.isFile()) {
|
|
168999
|
-
const info = await (0,
|
|
169533
|
+
const info = await (0, import_promises8.stat)(abs);
|
|
169000
169534
|
if (info.size > MAX_FILE_BYTES3) {
|
|
169001
169535
|
console.warn(`[builtin-skills] skip oversized file (${info.size}B): ${abs}`);
|
|
169002
169536
|
continue;
|
|
169003
169537
|
}
|
|
169004
|
-
const rel = (0,
|
|
169005
|
-
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");
|
|
169006
169540
|
}
|
|
169007
169541
|
}
|
|
169008
169542
|
}
|
|
169009
169543
|
async function loadBuiltinSkills(skillsDir) {
|
|
169010
169544
|
let dirents;
|
|
169011
169545
|
try {
|
|
169012
|
-
dirents = await (0,
|
|
169546
|
+
dirents = await (0, import_promises8.readdir)(skillsDir, { withFileTypes: true });
|
|
169013
169547
|
} catch {
|
|
169014
169548
|
return [];
|
|
169015
169549
|
}
|
|
@@ -169017,7 +169551,7 @@ async function loadBuiltinSkills(skillsDir) {
|
|
|
169017
169551
|
for (const d of dirents) {
|
|
169018
169552
|
if (!d.isDirectory()) continue;
|
|
169019
169553
|
const slug6 = d.name;
|
|
169020
|
-
const skillDir = (0,
|
|
169554
|
+
const skillDir = (0, import_node_path18.join)(skillsDir, slug6);
|
|
169021
169555
|
const files = {};
|
|
169022
169556
|
try {
|
|
169023
169557
|
await collectDir(skillDir, skillDir, files);
|
|
@@ -169045,12 +169579,12 @@ function materializeBuiltinSkills(builtins, skillsDirPrefix) {
|
|
|
169045
169579
|
}
|
|
169046
169580
|
return out;
|
|
169047
169581
|
}
|
|
169048
|
-
var
|
|
169582
|
+
var import_promises8, import_node_path18, MAX_FILE_BYTES3;
|
|
169049
169583
|
var init_builtin_skills = __esm({
|
|
169050
169584
|
"../server/src/governance/builtin-skills.ts"() {
|
|
169051
169585
|
"use strict";
|
|
169052
|
-
|
|
169053
|
-
|
|
169586
|
+
import_promises8 = require("node:fs/promises");
|
|
169587
|
+
import_node_path18 = require("node:path");
|
|
169054
169588
|
init_skill_fetcher();
|
|
169055
169589
|
init_skill_materializer();
|
|
169056
169590
|
MAX_FILE_BYTES3 = 1 << 20;
|
|
@@ -174542,6 +175076,21 @@ var init_postgres = __esm({
|
|
|
174542
175076
|
});
|
|
174543
175077
|
|
|
174544
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
|
+
}
|
|
174545
175094
|
var ident4, PostgresRegistryStore, rowToActor, rowToConfig;
|
|
174546
175095
|
var init_postgres_registry = __esm({
|
|
174547
175096
|
"../storage/src/postgres-registry.ts"() {
|
|
@@ -174673,9 +175222,21 @@ var init_postgres_registry = __esm({
|
|
|
174673
175222
|
value_encrypted text NOT NULL,
|
|
174674
175223
|
updated_at timestamptz NOT NULL
|
|
174675
175224
|
)`);
|
|
174676
|
-
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS "${s2}_variables_key_actor_uq" ON "${s2}".variables (key, COALESCE(actor_id, ''))`);
|
|
174677
175225
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS overrides text`);
|
|
174678
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, ''))`);
|
|
174679
175240
|
await pool.query(`
|
|
174680
175241
|
CREATE TABLE IF NOT EXISTS "${s2}".runtime_configs (
|
|
174681
175242
|
runtime_id text PRIMARY KEY,
|
|
@@ -175119,27 +175680,36 @@ var init_postgres_registry = __esm({
|
|
|
175119
175680
|
}
|
|
175120
175681
|
/* ---------- 变量 ---------- */
|
|
175121
175682
|
async putVariable(v2) {
|
|
175122
|
-
const aid = v2.actorId ?? null;
|
|
175123
175683
|
await this.pool.query(
|
|
175124
|
-
`INSERT INTO ${this.s}.variables (key, scope, actor_id, connector_id, overrides, value_encrypted, updated_at)
|
|
175125
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7)
|
|
175126
|
-
ON CONFLICT (key, COALESCE(actor_id, '')) DO UPDATE
|
|
175127
|
-
SET scope=$2, actor_id=$3,
|
|
175128
|
-
[
|
|
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
|
+
]
|
|
175129
175699
|
);
|
|
175130
175700
|
}
|
|
175131
175701
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
175132
175702
|
const aid = actorId ?? null;
|
|
175133
175703
|
await this.pool.query(
|
|
175134
175704
|
`UPDATE ${this.s}.variables SET value_encrypted=$3, updated_at=$4
|
|
175135
|
-
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,'')=''`,
|
|
175136
175706
|
[key, aid, valueEncrypted, updatedAt]
|
|
175137
175707
|
);
|
|
175138
175708
|
}
|
|
175139
175709
|
async getVariableCiphertext(key, actorId) {
|
|
175140
175710
|
const aid = actorId ?? null;
|
|
175141
175711
|
const r = await this.pool.query(
|
|
175142
|
-
`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,'')=''`,
|
|
175143
175713
|
[key, aid]
|
|
175144
175714
|
);
|
|
175145
175715
|
return r.rows[0]?.value_encrypted ?? null;
|
|
@@ -175154,21 +175724,21 @@ var init_postgres_registry = __esm({
|
|
|
175154
175724
|
} else {
|
|
175155
175725
|
r = await this.pool.query(`SELECT * FROM ${this.s}.variables ORDER BY key`);
|
|
175156
175726
|
}
|
|
175157
|
-
return r.rows.map((row) => (
|
|
175158
|
-
key: row.key,
|
|
175159
|
-
scope: row.scope === "connector" ? "global" : row.scope,
|
|
175160
|
-
...row.actor_id !== null && row.actor_id !== void 0 ? { actorId: row.actor_id } : {},
|
|
175161
|
-
...row.connector_id !== null ? { connectorId: row.connector_id } : {},
|
|
175162
|
-
...row.overrides !== null ? { overrides: row.overrides } : {},
|
|
175163
|
-
valueEncrypted: row.value_encrypted,
|
|
175164
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
175165
|
-
}));
|
|
175727
|
+
return r.rows.map((row) => rowToVariable(row));
|
|
175166
175728
|
}
|
|
175167
|
-
async
|
|
175168
|
-
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) {
|
|
175169
175737
|
await this.pool.query(
|
|
175170
|
-
`DELETE FROM ${this.s}.variables
|
|
175171
|
-
|
|
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]
|
|
175172
175742
|
);
|
|
175173
175743
|
}
|
|
175174
175744
|
};
|
|
@@ -175987,6 +176557,7 @@ var init_postgres_projects = __esm({
|
|
|
175987
176557
|
work_order_id text PRIMARY KEY,
|
|
175988
176558
|
project_id text NOT NULL
|
|
175989
176559
|
)`);
|
|
176560
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".workspace_bindings ADD COLUMN IF NOT EXISTS environment text`);
|
|
175990
176561
|
await pool.query(`
|
|
175991
176562
|
CREATE TABLE IF NOT EXISTS "${s2}".workspace_dispatch_hold (
|
|
175992
176563
|
work_order_id text PRIMARY KEY
|
|
@@ -176856,6 +177427,38 @@ var init_postgres_control_plane = __esm({
|
|
|
176856
177427
|
}
|
|
176857
177428
|
});
|
|
176858
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
|
+
|
|
176859
177462
|
// ../storage/src/postgres-trace.ts
|
|
176860
177463
|
var ident9, PostgresTraceStore, rowToRun, rowToEvent2, rowToToolCall, rowToArtifact2;
|
|
176861
177464
|
var init_postgres_trace = __esm({
|
|
@@ -176863,6 +177466,7 @@ var init_postgres_trace = __esm({
|
|
|
176863
177466
|
"use strict";
|
|
176864
177467
|
init_esm2();
|
|
176865
177468
|
init_src();
|
|
177469
|
+
init_pg_sanitize();
|
|
176866
177470
|
ident9 = (s2) => {
|
|
176867
177471
|
if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
|
|
176868
177472
|
return s2;
|
|
@@ -177123,12 +177727,12 @@ var init_postgres_trace = __esm({
|
|
|
177123
177727
|
run.exitCode,
|
|
177124
177728
|
run.exitReason,
|
|
177125
177729
|
run.errorCode,
|
|
177126
|
-
run.errorMessage,
|
|
177730
|
+
scrubPgString(run.errorMessage),
|
|
177127
177731
|
run.usage === null ? null : JSON.stringify(run.usage),
|
|
177128
177732
|
run.effectiveModel,
|
|
177129
177733
|
run.modelSource,
|
|
177130
177734
|
run.transcriptRef,
|
|
177131
|
-
JSON.stringify(run.metadata),
|
|
177735
|
+
JSON.stringify(scrubPgJson(run.metadata)),
|
|
177132
177736
|
run.createdAt,
|
|
177133
177737
|
run.updatedAt
|
|
177134
177738
|
]
|
|
@@ -177171,7 +177775,7 @@ var init_postgres_trace = __esm({
|
|
|
177171
177775
|
for (const [key, spec] of Object.entries(_PostgresTraceStore.RUN_COLS)) {
|
|
177172
177776
|
if (!(key in patch)) continue;
|
|
177173
177777
|
const v2 = patch[key];
|
|
177174
|
-
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));
|
|
177175
177779
|
sets.push(spec.json ? `${spec.col}=$${args.length}::jsonb` : `${spec.col}=$${args.length}`);
|
|
177176
177780
|
}
|
|
177177
177781
|
args.push(this.now());
|
|
@@ -177239,7 +177843,7 @@ var init_postgres_trace = __esm({
|
|
|
177239
177843
|
}
|
|
177240
177844
|
async listUsageRuns(filter) {
|
|
177241
177845
|
const r = await this.pool.query(
|
|
177242
|
-
`SELECT actor_id, artifact_id, started_at, effective_model, runtime_kind, usage
|
|
177846
|
+
`SELECT actor_id, artifact_id, started_at, effective_model, runtime_kind, runtime_instance_id, usage
|
|
177243
177847
|
FROM ${this.s}.agent_runs
|
|
177244
177848
|
WHERE jsonb_typeof(usage) = 'object' AND started_at >= $1 AND started_at <= $2
|
|
177245
177849
|
ORDER BY started_at`,
|
|
@@ -177251,6 +177855,7 @@ var init_postgres_trace = __esm({
|
|
|
177251
177855
|
startedAt: row.started_at,
|
|
177252
177856
|
effectiveModel: row.effective_model ?? null,
|
|
177253
177857
|
runtimeKind: row.runtime_kind ?? "shell",
|
|
177858
|
+
runtimeInstanceId: row.runtime_instance_id ?? null,
|
|
177254
177859
|
usage: row.usage
|
|
177255
177860
|
}));
|
|
177256
177861
|
}
|
|
@@ -177309,8 +177914,8 @@ var init_postgres_trace = __esm({
|
|
|
177309
177914
|
stream,
|
|
177310
177915
|
level,
|
|
177311
177916
|
inp.color ?? null,
|
|
177312
|
-
inp.message ?? null,
|
|
177313
|
-
JSON.stringify(payload),
|
|
177917
|
+
scrubPgString(inp.message ?? null),
|
|
177918
|
+
JSON.stringify(scrubPgJson(payload)),
|
|
177314
177919
|
inp.blobRef ?? null,
|
|
177315
177920
|
inp.spanId ?? null,
|
|
177316
177921
|
inp.parentSpanId ?? null,
|
|
@@ -177385,11 +177990,11 @@ var init_postgres_trace = __esm({
|
|
|
177385
177990
|
c.durationMs ?? null,
|
|
177386
177991
|
c.inputRef ?? null,
|
|
177387
177992
|
c.outputRef ?? null,
|
|
177388
|
-
c.inputPreview ?? null,
|
|
177389
|
-
c.outputPreview ?? null,
|
|
177993
|
+
scrubPgString(c.inputPreview ?? null),
|
|
177994
|
+
scrubPgString(c.outputPreview ?? null),
|
|
177390
177995
|
c.errorCode ?? null,
|
|
177391
|
-
c.errorMessage ?? null,
|
|
177392
|
-
JSON.stringify(c.metadata ?? {})
|
|
177996
|
+
scrubPgString(c.errorMessage ?? null),
|
|
177997
|
+
JSON.stringify(scrubPgJson(c.metadata ?? {}))
|
|
177393
177998
|
]
|
|
177394
177999
|
);
|
|
177395
178000
|
}
|
|
@@ -177434,12 +178039,12 @@ var init_postgres_trace = __esm({
|
|
|
177434
178039
|
a.id,
|
|
177435
178040
|
a.runId,
|
|
177436
178041
|
a.kind,
|
|
177437
|
-
a.name,
|
|
178042
|
+
scrubPgString(a.name),
|
|
177438
178043
|
a.contentType ?? null,
|
|
177439
178044
|
a.size ?? null,
|
|
177440
178045
|
a.blobRef,
|
|
177441
178046
|
a.createdAt,
|
|
177442
|
-
JSON.stringify(a.metadata ?? {})
|
|
178047
|
+
JSON.stringify(scrubPgJson(a.metadata ?? {}))
|
|
177443
178048
|
]
|
|
177444
178049
|
);
|
|
177445
178050
|
}
|
|
@@ -179151,7 +179756,10 @@ __export(src_exports, {
|
|
|
179151
179756
|
PostgresTraceStore: () => PostgresTraceStore,
|
|
179152
179757
|
PostgresTypeRegistryStore: () => PostgresTypeRegistryStore,
|
|
179153
179758
|
backfillTypeRegistryFromFile: () => backfillTypeRegistryFromFile,
|
|
179154
|
-
createPgPool: () => createPgPool
|
|
179759
|
+
createPgPool: () => createPgPool,
|
|
179760
|
+
hasPgUnstorable: () => hasPgUnstorable,
|
|
179761
|
+
scrubPgJson: () => scrubPgJson,
|
|
179762
|
+
scrubPgString: () => scrubPgString
|
|
179155
179763
|
});
|
|
179156
179764
|
var init_src8 = __esm({
|
|
179157
179765
|
"../storage/src/index.ts"() {
|
|
@@ -179164,6 +179772,7 @@ var init_src8 = __esm({
|
|
|
179164
179772
|
init_pool();
|
|
179165
179773
|
init_postgres_control_plane();
|
|
179166
179774
|
init_postgres_trace();
|
|
179775
|
+
init_pg_sanitize();
|
|
179167
179776
|
init_postgres_automations();
|
|
179168
179777
|
init_postgres_chat_sessions();
|
|
179169
179778
|
init_postgres_nodes();
|
|
@@ -179563,15 +180172,18 @@ function splitIdentityFiles3(prompt) {
|
|
|
179563
180172
|
}
|
|
179564
180173
|
return out;
|
|
179565
180174
|
}
|
|
179566
|
-
async function buildActorProvision(service, actorId) {
|
|
179567
|
-
const
|
|
179568
|
-
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;
|
|
179569
180179
|
const provision = await buildConnectorProvision({
|
|
179570
180180
|
vars: raw,
|
|
179571
180181
|
actorName: raw["GIT_AUTHOR_NAME"] ?? actorId.split(":").pop() ?? "oasis-agent"
|
|
179572
180182
|
});
|
|
180183
|
+
const env = { ...raw };
|
|
179573
180184
|
for (const k2 of provision.sensitiveVars) delete env[k2];
|
|
179574
180185
|
for (const [k2, v2] of Object.entries(provision.envOverrides)) env[k2] = v2;
|
|
180186
|
+
applyRefDelivery(env, entries);
|
|
179575
180187
|
return {
|
|
179576
180188
|
env,
|
|
179577
180189
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
@@ -179797,6 +180409,45 @@ async function startServe(opts) {
|
|
|
179797
180409
|
});
|
|
179798
180410
|
for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.target, timestamp: record6.timestamp });
|
|
179799
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
|
+
};
|
|
179800
180451
|
await syncRegistryRolesToKernel(registryStore, kernel);
|
|
179801
180452
|
let builtinSkills = [];
|
|
179802
180453
|
let connectorSkills = [];
|
|
@@ -179813,6 +180464,13 @@ async function startServe(opts) {
|
|
|
179813
180464
|
blobs: assets,
|
|
179814
180465
|
trace: () => traceStoreForActors,
|
|
179815
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,
|
|
179816
180474
|
// CO-302 数据面隔离(actors 域试点):按当前公司取其引擎,用各自 registry 服务该域请求。
|
|
179817
180475
|
// engineRouter 在下方(行 ~411)以 const 声明;此箭头只在请求时调用,那时已初始化,闭包引用合法
|
|
179818
180476
|
// (TDZ 只在构造时访问才报错,这里不访问)。默认公司命中现有单实例(registry===registryStore),
|
|
@@ -179943,7 +180601,13 @@ async function startServe(opts) {
|
|
|
179943
180601
|
traceStoreForActors = traceStore;
|
|
179944
180602
|
const trajReader = new FsTrajectorySink(opts.dir);
|
|
179945
180603
|
const trace = createTraceDomain({ store: traceStore, readBundleFile: (id, rel) => trajReader.readBundleFile(id, rel) });
|
|
179946
|
-
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
|
+
});
|
|
179947
180611
|
const automationStore = pgPool ? await PostgresAutomationStore.open(pgPool, pgSchema) : new MemoryAutomationStore();
|
|
179948
180612
|
console.log(`[serve] \u81EA\u52A8\u5316\u4F53\u7CFB\uFF1A${pgPool ? `Postgres schema=${pgSchema}` : "\u5185\u5B58 dev store"}`);
|
|
179949
180613
|
const automations = createAutomationsDomain({ store: automationStore, kernel });
|
|
@@ -180404,7 +181068,11 @@ async function startServe(opts) {
|
|
|
180404
181068
|
trace: trace.service,
|
|
180405
181069
|
registry: registryStore,
|
|
180406
181070
|
artifacts: artifactStateStore,
|
|
181071
|
+
// 组织汇总用——从 node_runtimes 取 hostname,解析运行时实例标签(kind @ hostname)
|
|
181072
|
+
listRuntimes: (nodeId) => nodeStore.listRuntimes(nodeId),
|
|
180407
181073
|
dispatchJournal: () => journalRing.slice(-200),
|
|
181074
|
+
// 组织汇总用——从 nodes 取 name(用户友好名),优先于 hostname 作为展示标签
|
|
181075
|
+
listNodes: () => nodeStore.listNodes(),
|
|
180408
181076
|
// 诊断 92ac8f18-83e5fde6 §④ D-2:按**请求公司**取其 dispatcher 的 queued/backoff 信号。
|
|
180409
181077
|
// CO-302 每家公司各有一套 dispatcher(dispatchers 以 companyId 为键)——固定读默认公司会让
|
|
180410
181078
|
// 非默认公司请求拿到错的/空的信号(code-review 打回)。该公司未起 dispatcher(老部署无 --dispatch、
|
|
@@ -180544,10 +181212,14 @@ async function startServe(opts) {
|
|
|
180544
181212
|
const traceRunId = `chat-run:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180545
181213
|
const artifactId = `artifact:chat:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180546
181214
|
const traceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180547
|
-
let traceSeq = 0;
|
|
180548
181215
|
let lastProgressTouchMs = 0;
|
|
180549
181216
|
const PROGRESS_TOUCH_THROTTLE_MS2 = 2e4;
|
|
180550
|
-
|
|
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
|
+
});
|
|
180551
181223
|
const analyzedRunId = chatSessionId ? (await chatSessionStore.getSession(chatSessionId).catch(() => null))?.analyzedRunId ?? void 0 : void 0;
|
|
180552
181224
|
let traceChain = traceStore.createRun({
|
|
180553
181225
|
id: traceRunId,
|
|
@@ -180568,16 +181240,14 @@ async function startServe(opts) {
|
|
|
180568
181240
|
...analyzedRunId ? { analyzedRunId } : {}
|
|
180569
181241
|
}
|
|
180570
181242
|
}).then(async () => {
|
|
180571
|
-
await
|
|
181243
|
+
await traceAppender.append([
|
|
180572
181244
|
{
|
|
180573
|
-
seq: ++traceSeq,
|
|
180574
181245
|
eventType: "run.started",
|
|
180575
181246
|
stream: "runtime",
|
|
180576
181247
|
message: `chat ${actorId}`,
|
|
180577
181248
|
startedAt: traceStartedAt
|
|
180578
181249
|
},
|
|
180579
181250
|
{
|
|
180580
|
-
seq: ++traceSeq,
|
|
180581
181251
|
eventType: "input.message",
|
|
180582
181252
|
stream: "model",
|
|
180583
181253
|
actorId,
|
|
@@ -180587,16 +181257,12 @@ async function startServe(opts) {
|
|
|
180587
181257
|
}
|
|
180588
181258
|
]);
|
|
180589
181259
|
}).catch((err) => {
|
|
180590
|
-
|
|
180591
|
-
console.warn(`[trace] chat run create failed: ${String(err)}`);
|
|
181260
|
+
traceHealth.markUnhealthy(traceRunId);
|
|
181261
|
+
console.warn(`[trace] chat run create failed (continuing): ${String(err)}`);
|
|
180592
181262
|
});
|
|
180593
181263
|
const enqueueTrace = (step) => {
|
|
180594
|
-
|
|
180595
|
-
|
|
180596
|
-
if (traceEnabled) await step();
|
|
180597
|
-
}).catch((err) => {
|
|
180598
|
-
traceEnabled = false;
|
|
180599
|
-
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)}`);
|
|
180600
181266
|
});
|
|
180601
181267
|
};
|
|
180602
181268
|
const provision = await buildActorProvision(actorService, actorId);
|
|
@@ -180743,7 +181409,7 @@ async function startServe(opts) {
|
|
|
180743
181409
|
const run = await traceStore.getRun(traceRunId);
|
|
180744
181410
|
if (!run) return;
|
|
180745
181411
|
const base = run.metadata && typeof run.metadata === "object" && !Array.isArray(run.metadata) ? run.metadata : {};
|
|
180746
|
-
await
|
|
181412
|
+
await traceAppender.update({
|
|
180747
181413
|
metadata: { ...base, dispatchId: handle.id },
|
|
180748
181414
|
// 恢复路径拿不到 dispatchChat 闭包里的 fallback 解析结果,开跑时先写进账本;退出帧若上报
|
|
180749
181415
|
// 更精确 model 仍会覆盖为 runtime 来源。
|
|
@@ -180765,23 +181431,23 @@ async function startServe(opts) {
|
|
|
180765
181431
|
const ms = Date.parse(event.ts);
|
|
180766
181432
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
180767
181433
|
lastProgressTouchMs = ms;
|
|
180768
|
-
enqueueTrace(() =>
|
|
181434
|
+
enqueueTrace(() => traceAppender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
180769
181435
|
}
|
|
180770
181436
|
return;
|
|
180771
181437
|
}
|
|
180772
|
-
enqueueTrace(() =>
|
|
181438
|
+
enqueueTrace(() => traceAppender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
180773
181439
|
});
|
|
180774
181440
|
let capturedNativeSessionId;
|
|
180775
181441
|
const done = new Promise((resolve8, reject) => {
|
|
180776
181442
|
handle.onExit((info) => {
|
|
180777
181443
|
chatLiveSessions.delete(chatJobKey);
|
|
181444
|
+
traceHealth.forget(traceRunId);
|
|
180778
181445
|
void provision.cleanup();
|
|
180779
181446
|
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180780
181447
|
const durationMs = Date.parse(endedAt) - Date.parse(traceStartedAt);
|
|
180781
181448
|
if (info.runtimeSessionId) capturedNativeSessionId = info.runtimeSessionId;
|
|
180782
181449
|
enqueueTrace(async () => {
|
|
180783
|
-
await
|
|
180784
|
-
seq: ++traceSeq,
|
|
181450
|
+
await traceAppender.append([{
|
|
180785
181451
|
eventType: "run.finished",
|
|
180786
181452
|
stream: "runtime",
|
|
180787
181453
|
message: `exit code=${info.code ?? "killed"}`,
|
|
@@ -180790,7 +181456,7 @@ async function startServe(opts) {
|
|
|
180790
181456
|
const usage = info.usage ?? null;
|
|
180791
181457
|
const effectiveModel = info.model ?? chatModel ?? null;
|
|
180792
181458
|
const modelSource = info.model ? "runtime" : chatModelSource;
|
|
180793
|
-
await
|
|
181459
|
+
await traceAppender.update({
|
|
180794
181460
|
status: info.reason === "timeout" ? "timeout" : info.reason === "cancelled" ? "cancelled" : info.code === 0 ? "succeeded" : "failed",
|
|
180795
181461
|
endedAt,
|
|
180796
181462
|
durationMs,
|
|
@@ -180895,6 +181561,7 @@ async function startServe(opts) {
|
|
|
180895
181561
|
unregister: () => {
|
|
180896
181562
|
chatLiveSessions.delete(jobKey);
|
|
180897
181563
|
},
|
|
181564
|
+
traceHealth,
|
|
180898
181565
|
log: (m2) => console.log(m2)
|
|
180899
181566
|
});
|
|
180900
181567
|
console.log(`[chat-recovery] \u91CD\u6302 chat \u8F6E\uFF1Asession=${plan.chatSessionId} run=${plan.runId} node=${daemonId}`);
|
|
@@ -181115,7 +181782,7 @@ async function startServe(opts) {
|
|
|
181115
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` : ""}`);
|
|
181116
181783
|
return { actor: replacement.id, originalActor: actor, routeReason: "disabled-owner-fallback" };
|
|
181117
181784
|
},
|
|
181118
|
-
provision: async (actorId) => buildActorProvision((await runActors()).service, actorId),
|
|
181785
|
+
provision: async (actorId, artifactId) => buildActorProvision((await runActors()).service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181119
181786
|
resolveActorContext: async (actorId) => buildActorContext((await runActors()).service, actorId),
|
|
181120
181787
|
// 收尾评审的角色分工段(reviewer 此前彼此不知道对方存在 → 越界 / 重复劳动)。
|
|
181121
181788
|
// 职责取自**岗位目录**(配置面),不在代码里硬编码任何岗位——加角色自动就在。
|
|
@@ -181738,7 +182405,7 @@ ${nodeFault}` : "");
|
|
|
181738
182405
|
resolveManager: (id) => resolveManagerBinding(registryStore, id),
|
|
181739
182406
|
schemaTypes: schema.map((d) => d.name),
|
|
181740
182407
|
schemaTypeDescriptions: Object.fromEntries(schema.filter((d) => d.description).map((d) => [d.name, d.description])),
|
|
181741
|
-
provision: (actorId) => buildActorProvision(actors.service, actorId),
|
|
182408
|
+
provision: async (actorId, artifactId) => buildActorProvision(actors.service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181742
182409
|
// 阻塞诊断(proposal D1/D3):派发器运行时信号(queued/fused/backoff/hasInFlight)注入诊断,
|
|
181743
182410
|
// 让协调者把"资源 / 运行时"病因和"图病"分开——资源排队的节点不会被误唤去砍流程。
|
|
181744
182411
|
runtimeSignals: (id) => {
|
|
@@ -181778,6 +182445,9 @@ ${nodeFault}` : "");
|
|
|
181778
182445
|
if (c) return Promise.resolve(c.kill()).then(() => true).catch(() => false);
|
|
181779
182446
|
return dispatcherByJob.get(jobKey)?.killSession(jobKey) ?? Promise.resolve(false);
|
|
181780
182447
|
},
|
|
182448
|
+
// trace 写不进去的 run:冻结的事件钟是"观测降级"不是"真静默",按"信息不足→不判"跳过、交 wallClock
|
|
182449
|
+
// 兜底(brief §限制1 / 诊断 §6)。真卡死的 run trace 健康、isTraceHealthy=true,照常被杀。
|
|
182450
|
+
isTraceHealthy: (sessionId) => traceHealth.isHealthy(sessionId),
|
|
181781
182451
|
now: Date.now(),
|
|
181782
182452
|
silentThresholdMs,
|
|
181783
182453
|
log: (m2) => console.log(m2)
|
|
@@ -181940,7 +182610,7 @@ var SessionManager = class {
|
|
|
181940
182610
|
|
|
181941
182611
|
// ../cli/src/daemon/ws-client.ts
|
|
181942
182612
|
init_wrapper();
|
|
181943
|
-
var
|
|
182613
|
+
var import_node_os8 = require("node:os");
|
|
181944
182614
|
var import_node_crypto38 = require("node:crypto");
|
|
181945
182615
|
init_src5();
|
|
181946
182616
|
|
|
@@ -181996,7 +182666,7 @@ function detectRuntimes() {
|
|
|
181996
182666
|
|
|
181997
182667
|
// ../cli/src/daemon/workdir-handler.ts
|
|
181998
182668
|
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
181999
|
-
var
|
|
182669
|
+
var import_node_path19 = __toESM(require("node:path"), 1);
|
|
182000
182670
|
init_src4();
|
|
182001
182671
|
init_src();
|
|
182002
182672
|
var WORKDIR_READ_MAX_BYTES2 = 2 * 1024 * 1024;
|
|
@@ -182015,10 +182685,10 @@ function isSensitiveSegment(segment) {
|
|
|
182015
182685
|
}
|
|
182016
182686
|
function relPathIsSensitive(rel) {
|
|
182017
182687
|
if (!rel) return false;
|
|
182018
|
-
return rel.split(
|
|
182688
|
+
return rel.split(import_node_path19.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
|
|
182019
182689
|
}
|
|
182020
182690
|
function withinBase(p2, base) {
|
|
182021
|
-
return p2 === base || p2.startsWith(base +
|
|
182691
|
+
return p2 === base || p2.startsWith(base + import_node_path19.default.sep);
|
|
182022
182692
|
}
|
|
182023
182693
|
function normalizeRel(raw) {
|
|
182024
182694
|
const trimmed = (raw ?? "").trim();
|
|
@@ -182035,7 +182705,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
|
|
|
182035
182705
|
} catch {
|
|
182036
182706
|
return null;
|
|
182037
182707
|
}
|
|
182038
|
-
return isLegacy ?
|
|
182708
|
+
return isLegacy ? import_node_path19.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path19.default.join(trustedRootReal, "sessions", dirKind);
|
|
182039
182709
|
}
|
|
182040
182710
|
async function resolveWithinWorkdir(req) {
|
|
182041
182711
|
const dirKind = sessionDirKind(req.runtimeKind);
|
|
@@ -182053,11 +182723,11 @@ async function resolveWithinWorkdir(req) {
|
|
|
182053
182723
|
} catch {
|
|
182054
182724
|
return { ok: false, code: "NOT_FOUND" };
|
|
182055
182725
|
}
|
|
182056
|
-
if (
|
|
182726
|
+
if (import_node_path19.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
|
|
182057
182727
|
const rel = normalizeRel(req.path);
|
|
182058
|
-
const requested =
|
|
182728
|
+
const requested = import_node_path19.default.resolve(base, rel);
|
|
182059
182729
|
if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182060
|
-
const cleanRel = base === requested ? "" :
|
|
182730
|
+
const cleanRel = base === requested ? "" : import_node_path19.default.relative(base, requested);
|
|
182061
182731
|
if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
|
|
182062
182732
|
let real;
|
|
182063
182733
|
try {
|
|
@@ -182067,7 +182737,7 @@ async function resolveWithinWorkdir(req) {
|
|
|
182067
182737
|
return { ok: false, code: "PATH_ESCAPE" };
|
|
182068
182738
|
}
|
|
182069
182739
|
if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182070
|
-
const realRel = base === real ? "" :
|
|
182740
|
+
const realRel = base === real ? "" : import_node_path19.default.relative(base, real);
|
|
182071
182741
|
if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
|
|
182072
182742
|
return { ok: true, base, real };
|
|
182073
182743
|
}
|
|
@@ -182103,7 +182773,7 @@ async function handleWorkdirList(req) {
|
|
|
182103
182773
|
const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
|
|
182104
182774
|
const entries = [];
|
|
182105
182775
|
for (const d of slice) {
|
|
182106
|
-
const abs =
|
|
182776
|
+
const abs = import_node_path19.default.join(anchor, d.name);
|
|
182107
182777
|
try {
|
|
182108
182778
|
const st = await import_node_fs16.default.promises.lstat(abs);
|
|
182109
182779
|
if (st.isSymbolicLink()) continue;
|
|
@@ -182135,7 +182805,7 @@ async function verifyOpenedFd(fh, base, fallback) {
|
|
|
182135
182805
|
const fdReal = await fdCanonicalPath(fh);
|
|
182136
182806
|
if (fdReal === null) return { anchor: fallback };
|
|
182137
182807
|
if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
|
|
182138
|
-
const fdRel = base === fdReal ? "" :
|
|
182808
|
+
const fdRel = base === fdReal ? "" : import_node_path19.default.relative(base, fdReal);
|
|
182139
182809
|
if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
|
|
182140
182810
|
return { anchor: `/proc/self/fd/${fh.fd}` };
|
|
182141
182811
|
}
|
|
@@ -182224,7 +182894,7 @@ function looksBinary(bytes) {
|
|
|
182224
182894
|
function contentTypeFor(absPath, bytes) {
|
|
182225
182895
|
const sniffed = sniffContentType(bytes);
|
|
182226
182896
|
if (sniffed) return sniffed;
|
|
182227
|
-
const ext =
|
|
182897
|
+
const ext = import_node_path19.default.extname(absPath).toLowerCase();
|
|
182228
182898
|
if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
|
|
182229
182899
|
return looksBinary(bytes) ? "application/octet-stream" : "text/plain; charset=utf-8";
|
|
182230
182900
|
}
|
|
@@ -182567,7 +183237,7 @@ var DaemonWsClient = class {
|
|
|
182567
183237
|
buildMeta() {
|
|
182568
183238
|
const activeSessions = this.sessions.activeSessions();
|
|
182569
183239
|
return {
|
|
182570
|
-
hostname: (0,
|
|
183240
|
+
hostname: (0, import_node_os8.hostname)(),
|
|
182571
183241
|
adapters: this.adapters,
|
|
182572
183242
|
...this.reportRuntimes ? { runtimes: this.runtimes } : {},
|
|
182573
183243
|
nodeVersion: process.version,
|
|
@@ -182597,18 +183267,18 @@ var RuntimeRouterAdapter = class {
|
|
|
182597
183267
|
|
|
182598
183268
|
// ../cli/src/daemon/reap-claude-projects.ts
|
|
182599
183269
|
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
182600
|
-
var
|
|
182601
|
-
var
|
|
183270
|
+
var import_node_os9 = __toESM(require("node:os"), 1);
|
|
183271
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
182602
183272
|
function claudeProjectSlug(cwd) {
|
|
182603
183273
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
182604
183274
|
}
|
|
182605
183275
|
function claudeProjectsRoot() {
|
|
182606
|
-
const configDir = process.env["CLAUDE_CONFIG_DIR"] ||
|
|
182607
|
-
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");
|
|
182608
183278
|
}
|
|
182609
183279
|
function reapClaudeProjects(workdir, runtimeKind) {
|
|
182610
183280
|
if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
|
|
182611
|
-
const dir =
|
|
183281
|
+
const dir = import_node_path20.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
|
|
182612
183282
|
if (!import_node_fs17.default.existsSync(dir)) return;
|
|
182613
183283
|
try {
|
|
182614
183284
|
import_node_fs17.default.rmSync(dir, { recursive: true, force: true });
|
|
@@ -182618,7 +183288,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
|
|
|
182618
183288
|
|
|
182619
183289
|
// ../cli/src/node.ts
|
|
182620
183290
|
init_src4();
|
|
182621
|
-
var
|
|
183291
|
+
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
182622
183292
|
var RESILIENCE = {
|
|
182623
183293
|
codex: { idleTimeoutMs: 6e5 }
|
|
182624
183294
|
};
|
|
@@ -182682,7 +183352,7 @@ async function startNode(opts) {
|
|
|
182682
183352
|
console.log(`[oasis node] ${opts.nodeId} \u2192 ${opts.serverUrl}`);
|
|
182683
183353
|
client.start();
|
|
182684
183354
|
const { workRoot, legacyRoot } = resolveWorkRoots(opts.workRoot);
|
|
182685
|
-
const workRootIsEphemeral = workRoot.startsWith(
|
|
183355
|
+
const workRootIsEphemeral = workRoot.startsWith(import_node_os10.default.tmpdir());
|
|
182686
183356
|
if (opts.gcEnabled === false && !workRootIsEphemeral) {
|
|
182687
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`);
|
|
182688
183358
|
}
|
|
@@ -182717,7 +183387,7 @@ async function startNode(opts) {
|
|
|
182717
183387
|
var import_node_child_process16 = require("node:child_process");
|
|
182718
183388
|
var import_node_fs18 = require("node:fs");
|
|
182719
183389
|
var import_node_crypto39 = require("node:crypto");
|
|
182720
|
-
var
|
|
183390
|
+
var import_node_os11 = require("node:os");
|
|
182721
183391
|
function linuxMachineId() {
|
|
182722
183392
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
182723
183393
|
try {
|
|
@@ -182757,13 +183427,13 @@ function windowsMachineId() {
|
|
|
182757
183427
|
}
|
|
182758
183428
|
function fallbackFingerprint() {
|
|
182759
183429
|
const macs = [];
|
|
182760
|
-
const ifaces = (0,
|
|
183430
|
+
const ifaces = (0, import_node_os11.networkInterfaces)();
|
|
182761
183431
|
for (const name of Object.keys(ifaces).sort()) {
|
|
182762
183432
|
for (const ni of ifaces[name] ?? []) {
|
|
182763
183433
|
if (!ni.internal && ni.mac && ni.mac !== "00:00:00:00:00:00") macs.push(ni.mac);
|
|
182764
183434
|
}
|
|
182765
183435
|
}
|
|
182766
|
-
return `fallback:${(0,
|
|
183436
|
+
return `fallback:${(0, import_node_os11.hostname)()}:${macs.sort()[0] ?? "no-mac"}`;
|
|
182767
183437
|
}
|
|
182768
183438
|
function machineFingerprint() {
|
|
182769
183439
|
const byOs = process.platform === "darwin" ? macMachineId() : process.platform === "win32" ? windowsMachineId() : linuxMachineId();
|
|
@@ -182773,7 +183443,7 @@ var defaultSources = {
|
|
|
182773
183443
|
machineFingerprint,
|
|
182774
183444
|
osUser: () => {
|
|
182775
183445
|
try {
|
|
182776
|
-
return (0,
|
|
183446
|
+
return (0, import_node_os11.userInfo)().username;
|
|
182777
183447
|
} catch {
|
|
182778
183448
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
182779
183449
|
}
|
|
@@ -182957,7 +183627,7 @@ var COMMAND_DECLS = {
|
|
|
182957
183627
|
// —— 版本机(§5) ——
|
|
182958
183628
|
spawn: {
|
|
182959
183629
|
usage: "oasis spawn <artifactId> --type <t> [--title <\u77ED\u540D>] [--brief <\u89C4\u683C>] [--input <\u4E0A\u6E38id>[,<id>\u2026]] [--owner <actorId>] [--workspace ws] [--persistence temp|persistent] [--parts-file <json>] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>]",
|
|
182960
|
-
description: "\u521B\u5EFA\u65B0\u4EA7\u7269\u8282\u70B9\uFF08\xA75 \u7248\u672C\u673A\uFF09\u3002--<\u5B57\u6BB5> <\u503C> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u7528 oasis artifact-types show <type> \u67E5\u770B\uFF09\u3002",
|
|
183630
|
+
description: "\u521B\u5EFA\u65B0\u4EA7\u7269\u8282\u70B9\uFF08\xA75 \u7248\u672C\u673A\uFF09\u3002--<\u5B57\u6BB5> <\u503C> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u7528 oasis artifact-types show <type|\u8BE5\u4EA7\u7269 id> \u67E5\u770B\uFF09\u3002",
|
|
182961
183631
|
positional: [
|
|
182962
183632
|
{ name: "<artifactId>", required: true, desc: "\u4EA7\u7269 id" }
|
|
182963
183633
|
],
|
|
@@ -183510,9 +184180,9 @@ var COMMAND_DECLS = {
|
|
|
183510
184180
|
},
|
|
183511
184181
|
// —— 类型管理 ——
|
|
183512
184182
|
"artifact-types": {
|
|
183513
|
-
usage: "oasis artifact-types [list | search <q> | show <type> | add ... | edit ... | deprecate ... | delete ... | add-field ... | edit-field ... | drop-field ...]",
|
|
183514
|
-
description: "\u7BA1\u7406 artifact \u7C7B\u578B\u6CE8\u518C\u8868\u3002\u5B50\u547D\u4EE4\uFF1Alist\uFF08\u5217\u51FA\u5168\u90E8\uFF09\u3001search\uFF08\u641C\u7D22\uFF09\u3001show\uFF08\u770B\u8BE6\u60C5\u542B\u81EA\u5B9A\u4E49\u5B57\u6BB5\u8868\uFF09\u3001add/edit/deprecate/delete\uFF08\u7C7B\u578B CRUD\uFF09\u3001add-field/edit-field/drop-field\uFF08\u5B57\u6BB5\u7BA1\u7406\uFF09\u3002",
|
|
183515
|
-
examples: ["oasis artifact-types list", "oasis artifact-types show dev"]
|
|
184183
|
+
usage: "oasis artifact-types [list | search <q> | show <type|artifactId> | add ... | edit ... | deprecate ... | delete ... | add-field ... | edit-field ... | drop-field ...]",
|
|
184184
|
+
description: "\u7BA1\u7406 artifact \u7C7B\u578B\u6CE8\u518C\u8868\u3002\u5B50\u547D\u4EE4\uFF1Alist\uFF08\u5217\u51FA\u5168\u90E8\uFF09\u3001search\uFF08\u641C\u7D22\uFF09\u3001show\uFF08\u770B\u8BE6\u60C5\u542B\u81EA\u5B9A\u4E49\u5B57\u6BB5\u8868\uFF1B**\u76F4\u63A5\u5582\u4EA7\u7269 id \u4E5F\u884C**\uFF0C\u81EA\u52A8\u89E3\u6790\u6210\u5B83\u7684\u7C7B\u578B\uFF09\u3001add/edit/deprecate/delete\uFF08\u7C7B\u578B CRUD\uFF09\u3001add-field/edit-field/drop-field\uFF08\u5B57\u6BB5\u7BA1\u7406\uFF09\u3002",
|
|
184185
|
+
examples: ["oasis artifact-types list", "oasis artifact-types show dev", "oasis artifact-types show artifact:brief:abc-123"]
|
|
183516
184186
|
},
|
|
183517
184187
|
// —— 工单 ——
|
|
183518
184188
|
"create-workorder": {
|
|
@@ -183724,7 +184394,7 @@ var COMMAND_DECLS = {
|
|
|
183724
184394
|
},
|
|
183725
184395
|
edit: {
|
|
183726
184396
|
usage: "oasis edit <id> [--title \u2026] [--brief \u2026] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>] [--clear <\u5B57\u6BB5,\u2026>]",
|
|
183727
|
-
description: "\u4FEE\u6539\u4EA7\u7269\u5C5E\u6027\uFF08\xA75 \u6682\u5B58\u6001\u2014\u2014OASIS_STAGE=1 \u4E0B\u751F\u6548\uFF09\u3002--<\u5B57\u6BB5> <\u503C> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u7528 oasis
|
|
184397
|
+
description: "\u4FEE\u6539\u4EA7\u7269\u5C5E\u6027\uFF08\xA75 \u6682\u5B58\u6001\u2014\u2014OASIS_STAGE=1 \u4E0B\u751F\u6548\uFF09\u3002--<\u5B57\u6BB5> <\u503C> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u7528 oasis artifact-types show <\u8BE5\u4EA7\u7269 id> \u67E5\u770B\uFF09\u3002set-json / clear \u7684\u6392\u9664\u4E0E\u4E13\u9879\u5904\u7406\u89C1 fieldsFromFlags\u3002",
|
|
183728
184398
|
positional: [
|
|
183729
184399
|
{ name: "<id>", required: true, desc: "\u4EA7\u7269 id" }
|
|
183730
184400
|
],
|
|
@@ -183777,6 +184447,19 @@ var COMMAND_DECLS = {
|
|
|
183777
184447
|
description: "\u4EA4\u4ED8\u7269\u6587\u6863\u4F53\u7CFB\u64CD\u4F5C\uFF08artifact revision \u5B50\u547D\u4EE4\u96C6\uFF09\u3002",
|
|
183778
184448
|
subCommands: ["artifact revision register", "artifact revision approve", "artifact revision reject"],
|
|
183779
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"]
|
|
183780
184463
|
}
|
|
183781
184464
|
};
|
|
183782
184465
|
function formatCommandHelp(decl) {
|
|
@@ -183858,7 +184541,7 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
183858
184541
|
\u7248\u672C\u673A\uFF08\xA75\uFF09
|
|
183859
184542
|
spawn <artifactId> --type <t> [--title <\u77ED\u540D>] [--brief <\u89C4\u683C>] [--input <\u4E0A\u6E38id>[,<id>\u2026]] [--owner <actorId>] [--workspace ws] [--persistence temp|persistent] [--parts-file <json>] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>]
|
|
183860
184543
|
# --parts-file\uFF1Aconvergent \u5E76\u884C\u5206\u89E3\u7684\u90E8\u4EF6\u6E05\u5355 JSON [{name, spec?, deps?}]\uFF08Stage 3\uFF0C\u7CFB\u7EDF\u6309\u90E8\u4EF6\u6D3E N \u8DEF\uFF09
|
|
183861
|
-
# --<\u5B57\u6BB5> <\u503C>\uFF1A\u8BE5\u7C7B\u578B\u3010\u52A8\u6001\u58F0\u660E\u3011\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u4E0D\u662F\u56FA\u5B9A\u6E05\u5355\uFF09\u2014\u2014\u7528 "oasis artifact-types show <type>" \u770B\u53EF\u586B\u5B57\u6BB5\uFF1Bstring[]/\u6279\u91CF\u7528 --set-json\uFF1B\u7F3A\u5FC5\u586B\u4F1A\u62A5\u9519\u5217\u51FA
|
|
184544
|
+
# --<\u5B57\u6BB5> <\u503C>\uFF1A\u8BE5\u7C7B\u578B\u3010\u52A8\u6001\u58F0\u660E\u3011\u7684\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u4E0D\u662F\u56FA\u5B9A\u6E05\u5355\uFF09\u2014\u2014\u7528 "oasis artifact-types show <type|\u8BE5\u4EA7\u7269 id>" \u770B\u53EF\u586B\u5B57\u6BB5\uFF1Bstring[]/\u6279\u91CF\u7528 --set-json\uFF1B\u7F3A\u5FC5\u586B\u4F1A\u62A5\u9519\u5217\u51FA
|
|
183862
184545
|
propose <artifactId> [--file <path> | --from-dir <path> | --git-commit <sha>] --reason <text> [--base <revisionId|none>] [--part <name>] [--rebase-of <revisionId>] [--checkpoint --continue]
|
|
183863
184546
|
# --file \u5355\u6587\u4EF6\uFF1B--from-dir \u9012\u5F52\u6574\u76EE\u5F55\u4E3A\u591A\u6587\u4EF6 revision\uFF08\u88C5\u7BB1\u5355\uFF0C\u8DE8\u7248\u672C\u53BB\u91CD\uFF0CF1\uFF09\u3002
|
|
183864
184547
|
# \u4EE3\u7801\u8282\u70B9\u53EF\u3010\u7701\u7565\u5168\u90E8\u5185\u5BB9\u53C2\u6570\u3011\uFF0C\u4EC5 --reason\uFF1A\u5148\u628A\u6539\u52A8 push \u5230\u5DE5\u5355 feat \u5206\u652F\uFF0C\u7CFB\u7EDF\u81EA\u52A8\u4ECE git \u6536\u96C6\uFF08\u672C\u4F53\u5728 git\uFF09\u3002
|
|
@@ -183914,7 +184597,7 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
183914
184597
|
log <artifactId> # \u8BE5\u4EA7\u7269\u7684**\u64CD\u4F5C\u65E5\u5FD7**\uFF1A\u5DF2\u53D1\u751F\u7684\u5185\u6838\u4E8B\u5B9E\uFF08spawn/propose/merge/conclude\u2026\uFF09\uFF0C\u4ECE oplog \u8BFB
|
|
183915
184598
|
session-log <runId|artifactId> [--n 20] # \u67D0 agent **\u4F1A\u8BDD\u7684\u8FD0\u884C\u65F6\u8F93\u51FA**\uFF08\u65C1\u8D26\uFF0C\u975E\u5185\u6838\u4E8B\u5B9E\uFF09\uFF1A\u6700\u65B0 N \u6761\u4E8B\u4EF6 + "\u8DDD\u4E0A\u6B21\u4E8B\u4EF6 X \u5206\u949F"\uFF08>10min\u2248\u5361\uFF09+ \u5728\u98DE tool_use\u2014\u2014\u5224"\u60F3 vs \u5361"\u3002\u6CE8\u610F\u2260 log\uFF1Alog \u770B\u4EA7\u7269\u7ECF\u5386\u4E86\u4EC0\u4E48\uFF0Csession-log \u770B agent \u6B64\u523B\u5728\u8BF4/\u5E72\u4EC0\u4E48
|
|
183916
184599
|
artifact-types [list | search <q>] # \u770B/\u68C0\u7D22\u5DF2\u6CE8\u518C\u7C7B\u578B\uFF08\u7528\u9014/owner/\u72B6\u6001\uFF09\u2014\u2014\u7ED9\u4EBA\u548C agent \u9009 type
|
|
183917
|
-
artifact-types show <type>
|
|
184600
|
+
artifact-types show <type|artifactId> # \u770B\u5355\u7C7B\u578B\u8BE6\u60C5\uFF1A\u542B\u3010\u81EA\u5B9A\u4E49\u5B57\u6BB5\u8868\u3011(\u540D/\u7C7B\u578B/\u5FC5\u586B/\u8BF4\u660E)\u2014\u2014spawn/edit \u524D\u67E5\u80FD\u586B\u5565\u3002**\u76F4\u63A5\u5582\u4EA7\u7269 id \u4E5F\u884C**\uFF0C\u81EA\u52A8\u89E3\u6790\u6210\u5B83\u7684\u7C7B\u578B
|
|
183918
184601
|
artifact-types add <name> (--content-type <t> --owner-role <r> | --file <json>) [--description \u2026] # \u65B0\u589E\uFF08--file \u6536\u5B8C\u6574 ArtifactTypeDef\uFF1Atriggers/reviews/grounding/budget/acl/mirror\u2026\uFF09
|
|
183919
184602
|
artifact-types edit <name> [--file <json>] [--description \u2026] [--owner-role \u2026] [--content-type \u2026] # \u6539\u7C7B\u578B\u914D\u7F6E\uFF08name \u4E0D\u53EF\u6539\uFF1BcontentType \u6709\u5B58\u91CF\u5373\u62E6\uFF1B--file \u6536\u5B8C\u6574 patch\u3002\u6539\u5B57\u6BB5\u7528 *-field\uFF09
|
|
183920
184603
|
artifact-types add-field <type> <\u5B57\u6BB5> --type <string|string[]|number|boolean> [--required true] [--description \u2026] # \u7ED9\u7C7B\u578B\u3010\u58F0\u660E\u3011\u4E00\u4E2A\u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF08\u6539 schema\u3001\u5F71\u54CD\u8BE5 type \u6240\u6709\u8282\u70B9\u7684\u672A\u6765\u5199\u5165\uFF09
|
|
@@ -184571,7 +185254,7 @@ async function runCli(argv, println = console.log) {
|
|
|
184571
185254
|
const fields = fieldsFromFlags(ownFlagsFromDecl("edit"));
|
|
184572
185255
|
return {
|
|
184573
185256
|
action: "edit",
|
|
184574
|
-
artifactId: needPos(positional, 0, "oasis edit <id> [--title \u2026] [--brief \u2026] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>] [--clear <\u5B57\u6BB5,\u2026>]\uFF08--<\u5B57\u6BB5> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\uFF0C\u7528 oasis
|
|
185257
|
+
artifactId: needPos(positional, 0, "oasis edit <id> [--title \u2026] [--brief \u2026] [--<\u5B57\u6BB5> <\u503C>] [--set-json <json>] [--clear <\u5B57\u6BB5,\u2026>]\uFF08--<\u5B57\u6BB5> \u662F\u8BE5\u7C7B\u578B\u52A8\u6001\u58F0\u660E\u7684\uFF0C\u7528 oasis artifact-types show <\u8BE5\u4EA7\u7269 id> \u770B\u53EF\u586B\u5B57\u6BB5\uFF09"),
|
|
184575
185258
|
...flags.get("title") !== void 0 ? { title: flags.get("title") } : {},
|
|
184576
185259
|
...flags.get("brief") !== void 0 ? { description: flags.get("brief") } : {},
|
|
184577
185260
|
...fields !== void 0 ? { fields } : {}
|
|
@@ -185442,6 +186125,33 @@ ${res.warning}`);
|
|
|
185442
186125
|
println(`\u5DF2\u5220\u9664 ${memId}`);
|
|
185443
186126
|
break;
|
|
185444
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
|
+
}
|
|
185445
186155
|
case "pin": {
|
|
185446
186156
|
const { message } = await api.cmd("pin", {
|
|
185447
186157
|
artifactId: needPos(positional, 0, "oasis pin <artifactId> --to u --rev r"),
|
|
@@ -185989,13 +186699,21 @@ ${res.warning}`);
|
|
|
185989
186699
|
break;
|
|
185990
186700
|
}
|
|
185991
186701
|
if (sub === "show") {
|
|
185992
|
-
const
|
|
186702
|
+
const ref2 = needPos(positional, 1, "oasis artifact-types show <type|artifactId>");
|
|
186703
|
+
let name = ref2;
|
|
186704
|
+
let resolvedFrom;
|
|
186705
|
+
if (ref2.startsWith("artifact:")) {
|
|
186706
|
+
const v2 = await api.view("show", ref2);
|
|
186707
|
+
name = v2.artifact.type;
|
|
186708
|
+
resolvedFrom = ref2;
|
|
186709
|
+
}
|
|
185993
186710
|
const { items } = await api.request("GET", "/api/artifact-types");
|
|
185994
186711
|
const t = items.find((x2) => x2.name === name);
|
|
185995
186712
|
if (!t) {
|
|
185996
186713
|
println(`\uFF08\u65E0\u6B64\u7C7B\u578B: ${name}\uFF09`);
|
|
185997
186714
|
break;
|
|
185998
186715
|
}
|
|
186716
|
+
if (resolvedFrom) println(`${resolvedFrom} \u7684\u7C7B\u578B\u662F ${name}\uFF1A`);
|
|
185999
186717
|
println(`${t.name}${t.status === "deprecated" ? " [\u5DF2\u5F03\u7528]" : ""} (${t.contentType}, owner=${t.ownerRole})${t.description ? ` \u2014\u2014 ${t.description}` : ""}`);
|
|
186000
186718
|
const fds = t.fieldDefs ?? [];
|
|
186001
186719
|
println(fds.length === 0 ? " \u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF1A\u65E0" : " \u81EA\u5B9A\u4E49\u5B57\u6BB5\uFF1A");
|
|
@@ -186133,7 +186851,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
186133
186851
|
}
|
|
186134
186852
|
|
|
186135
186853
|
// src/index.ts
|
|
186136
|
-
var PKG_VERSION = true ? "0.1.
|
|
186854
|
+
var PKG_VERSION = true ? "0.1.89" : "dev";
|
|
186137
186855
|
var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
|
|
186138
186856
|
var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
|
|
186139
186857
|
var PID_FILE = path29.join(OASIS_DIR, "node.pid");
|