oasis_test 0.1.87 → 0.1.90
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 +983 -253
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2488,6 +2488,24 @@ var init_registry = __esm({
|
|
|
2488
2488
|
}
|
|
2489
2489
|
});
|
|
2490
2490
|
|
|
2491
|
+
// ../contract/src/credential-ref.ts
|
|
2492
|
+
function makeVarRef(key) {
|
|
2493
|
+
return `${VAR_REF_PREFIX}${key}`;
|
|
2494
|
+
}
|
|
2495
|
+
function parseVarRef(s2) {
|
|
2496
|
+
if (!s2.startsWith(VAR_REF_PREFIX)) return null;
|
|
2497
|
+
const key = s2.slice(VAR_REF_PREFIX.length);
|
|
2498
|
+
if (key.length === 0 || /[\s/]/.test(key)) return null;
|
|
2499
|
+
return key;
|
|
2500
|
+
}
|
|
2501
|
+
var VAR_REF_PREFIX;
|
|
2502
|
+
var init_credential_ref = __esm({
|
|
2503
|
+
"../contract/src/credential-ref.ts"() {
|
|
2504
|
+
"use strict";
|
|
2505
|
+
VAR_REF_PREFIX = "oasis://var/";
|
|
2506
|
+
}
|
|
2507
|
+
});
|
|
2508
|
+
|
|
2491
2509
|
// ../contract/src/views.ts
|
|
2492
2510
|
var init_views = __esm({
|
|
2493
2511
|
"../contract/src/views.ts"() {
|
|
@@ -2565,6 +2583,7 @@ var init_src = __esm({
|
|
|
2565
2583
|
init_runtime();
|
|
2566
2584
|
init_daemon_protocol();
|
|
2567
2585
|
init_registry();
|
|
2586
|
+
init_credential_ref();
|
|
2568
2587
|
init_views();
|
|
2569
2588
|
init_telemetry();
|
|
2570
2589
|
init_trace();
|
|
@@ -5982,6 +6001,13 @@ var init_dispatcher = __esm({
|
|
|
5982
6001
|
* 是否相对本会话推进过**(上游产新版才动 pin,天然排除驳回/人类改单)。运行时态、不进 oplog/重放,
|
|
5983
6002
|
* 与 inFlight 同生同灭。 */
|
|
5984
6003
|
inFlightPins = /* @__PURE__ */ new Map();
|
|
6004
|
+
/**
|
|
6005
|
+
* 本次会话的凭据清理器,与 inFlight 同生同灭。
|
|
6006
|
+
* **必须在「只有槽位主人才能解锁」那个守卫里调**(见 handleSessionExit)——
|
|
6007
|
+
* 无差别调用 = 拿僵尸会话的死讯删掉**活会话正在用的** creds 文件,
|
|
6008
|
+
* 那比不清理更糟:活着的 agent 下一次 `gh` 就炸,且现场看起来像凭据凭空消失。
|
|
6009
|
+
*/
|
|
6010
|
+
inFlightCleanup = /* @__PURE__ */ new Map();
|
|
5985
6011
|
/** ADR-0094:本会话已确认不支持原生 append(codex/subprocess 远端报 unsupported,或会话在收尾)——
|
|
5986
6012
|
* 停投,回落"等会话退出 + fresh 重派"。与 inFlight 同生同灭。 */
|
|
5987
6013
|
appendSkip = /* @__PURE__ */ new Set();
|
|
@@ -6887,7 +6913,7 @@ var init_dispatcher = __esm({
|
|
|
6887
6913
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
6888
6914
|
const tokenFor = this.opts.tokenFor ?? ((a, _ctx) => `token:${a}`);
|
|
6889
6915
|
const actorToken = tokenFor(dispatchSpec.actor, credentialCtx);
|
|
6890
|
-
const provisioned = this.opts.provision ? await this.opts.provision(dispatchSpec.actor) : void 0;
|
|
6916
|
+
const provisioned = this.opts.provision ? await this.opts.provision(dispatchSpec.actor, spec.artifactId) : void 0;
|
|
6891
6917
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
6892
6918
|
const jobEnv = {
|
|
6893
6919
|
...provisioned?.env ?? {},
|
|
@@ -6915,6 +6941,8 @@ var init_dispatcher = __esm({
|
|
|
6915
6941
|
...Object.keys(jobEnv).length > 0 ? { env: jobEnv } : {},
|
|
6916
6942
|
...provisioned?.wrapperPaths && provisioned.wrapperPaths.length > 0 ? { wrapperPaths: provisioned.wrapperPaths } : {},
|
|
6917
6943
|
...provisioned?.requiredTools && provisioned.requiredTools.length > 0 ? { requiredTools: provisioned.requiredTools } : {},
|
|
6944
|
+
// 凭据本体随 job 下发,供**节点侧本机注入**(见上方 provision 注释)。
|
|
6945
|
+
...provisioned?.connectorCreds && provisioned.connectorCreds.length > 0 ? { connectorCreds: provisioned.connectorCreds } : {},
|
|
6918
6946
|
// ADR-0078 D1/D3:把本次派发的 id 交给 adapter 当 handle.id——于是
|
|
6919
6947
|
// `handle.id` = `agent_runs.id` = token 的 dispatchId claim,三处同值。
|
|
6920
6948
|
dispatchId: attempt
|
|
@@ -6946,6 +6974,7 @@ var init_dispatcher = __esm({
|
|
|
6946
6974
|
}
|
|
6947
6975
|
this.inFlight.set(jobKey, session);
|
|
6948
6976
|
this.inFlightActor.set(jobKey, dispatchSpec.actor);
|
|
6977
|
+
if (provisioned?.cleanup) this.inFlightCleanup.set(jobKey, provisioned.cleanup);
|
|
6949
6978
|
const dispatchedAtMs = Date.now();
|
|
6950
6979
|
this.inFlightStartedAt.set(jobKey, dispatchedAtMs);
|
|
6951
6980
|
const seqAtDispatch = seqNow;
|
|
@@ -7040,6 +7069,12 @@ var init_dispatcher = __esm({
|
|
|
7040
7069
|
this.inFlightStartedAt.delete(jobKey);
|
|
7041
7070
|
this.inFlightPins.delete(jobKey);
|
|
7042
7071
|
this.appendSkip.delete(jobKey);
|
|
7072
|
+
const cleanup = this.inFlightCleanup.get(jobKey);
|
|
7073
|
+
if (cleanup) {
|
|
7074
|
+
this.inFlightCleanup.delete(jobKey);
|
|
7075
|
+
void cleanup().catch(() => {
|
|
7076
|
+
});
|
|
7077
|
+
}
|
|
7043
7078
|
}
|
|
7044
7079
|
const seqAtExit = kernel.model.lastSeq.get(spec.artifactId) ?? 0;
|
|
7045
7080
|
const exitSessionKey = this.produceSessionKeyFor(spec);
|
|
@@ -23533,8 +23568,8 @@ var require_axios = __commonJS({
|
|
|
23533
23568
|
axios.toFormData = toFormData;
|
|
23534
23569
|
axios.AxiosError = AxiosError$1;
|
|
23535
23570
|
axios.Cancel = axios.CanceledError;
|
|
23536
|
-
axios.all = function all(
|
|
23537
|
-
return Promise.all(
|
|
23571
|
+
axios.all = function all(promises2) {
|
|
23572
|
+
return Promise.all(promises2);
|
|
23538
23573
|
};
|
|
23539
23574
|
axios.spread = spread;
|
|
23540
23575
|
axios.isAxiosError = isAxiosError;
|
|
@@ -124780,8 +124815,8 @@ function getElementAtPath(obj, path30) {
|
|
|
124780
124815
|
}
|
|
124781
124816
|
function promiseAllObject(promisesObj) {
|
|
124782
124817
|
const keys = Object.keys(promisesObj);
|
|
124783
|
-
const
|
|
124784
|
-
return Promise.all(
|
|
124818
|
+
const promises2 = keys.map((key) => promisesObj[key]);
|
|
124819
|
+
return Promise.all(promises2).then((results) => {
|
|
124785
124820
|
const resolvedObj = {};
|
|
124786
124821
|
for (let i = 0; i < keys.length; i++) {
|
|
124787
124822
|
resolvedObj[keys[i]] = results[i];
|
|
@@ -140760,8 +140795,8 @@ var init_install = __esm({
|
|
|
140760
140795
|
function shSingleQuote(v2) {
|
|
140761
140796
|
return `'${v2.replace(/'/g, `'\\''`)}'`;
|
|
140762
140797
|
}
|
|
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}-`));
|
|
140798
|
+
async function writeSessionCredsFile(slug6, exports2, reuseDir) {
|
|
140799
|
+
const dir = reuseDir ?? await (0, import_promises.mkdtemp)((0, import_node_path5.join)((0, import_node_os3.tmpdir)(), `oasis-${slug6}-`));
|
|
140765
140800
|
const file = (0, import_node_path5.join)(dir, "creds.env");
|
|
140766
140801
|
const body = Object.entries(exports2).map(([k2, v2]) => `export ${k2}=${shSingleQuote(v2)}`).join("\n");
|
|
140767
140802
|
await (0, import_promises.writeFile)(file, body + "\n", { mode: 384 });
|
|
@@ -140787,7 +140822,7 @@ async function refreshCredentialsIfNeeded(connector, credentials, opts = {}) {
|
|
|
140787
140822
|
return { status: "unsupported", detail: `${connector.config.slug}: \u51ED\u636E\u4E0D\u8FC7\u671F\uFF0C\u65E0\u9700\u7EED\u671F` };
|
|
140788
140823
|
}
|
|
140789
140824
|
const nowMs = opts.nowMs ?? Date.now();
|
|
140790
|
-
const skewMs = opts.skewMs ?? CREDENTIAL_REFRESH_SKEW_MS;
|
|
140825
|
+
const skewMs = opts.skewMs ?? connector.minRemainingLifetimeMs ?? CREDENTIAL_REFRESH_SKEW_MS;
|
|
140791
140826
|
const expiresAt = readEpochMs(credentials, connector.expiresAtCredentialKey);
|
|
140792
140827
|
if (!isExpiringSoon(expiresAt, nowMs, skewMs)) {
|
|
140793
140828
|
return { status: "fresh" };
|
|
@@ -141072,6 +141107,8 @@ var init_feishu = __esm({
|
|
|
141072
141107
|
"FEISHU_REFRESH_TOKEN_EXPIRES_AT",
|
|
141073
141108
|
"FEISHU_USER_OPEN_ID"
|
|
141074
141109
|
];
|
|
141110
|
+
/** 宿主机登录态隔离,理由同 github(见接口注释):由通用装配层无条件设。 */
|
|
141111
|
+
hostCredentialIsolationEnvKeys = ["LARKSUITE_CLI_CONFIG_DIR"];
|
|
141075
141112
|
/** inject() 写进 sessionEnv 的全部键——通用 cleanup() 按它逐个删。 */
|
|
141076
141113
|
injectedEnvKeys = [
|
|
141077
141114
|
"LARK_BIN",
|
|
@@ -141140,7 +141177,7 @@ var init_feishu = __esm({
|
|
|
141140
141177
|
LARKSUITE_CLI_APP_ID: appId,
|
|
141141
141178
|
LARKSUITE_CLI_APP_SECRET: appSecret,
|
|
141142
141179
|
...userAccessToken ? { LARKSUITE_CLI_USER_ACCESS_TOKEN: userAccessToken } : {}
|
|
141143
|
-
});
|
|
141180
|
+
}, sessionEnv.get("FEISHU_RUN_TMPDIR"));
|
|
141144
141181
|
const configDir = (0, import_node_path6.join)(creds.dir, "lark-config");
|
|
141145
141182
|
await (0, import_promises3.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
141146
141183
|
sessionEnv.set("LARK_BIN", await this.resolveAbsoluteLarkBin());
|
|
@@ -141633,10 +141670,17 @@ async function exchangeManifestCode(code, deps = {}) {
|
|
|
141633
141670
|
const appId = body["id"] === void 0 ? "" : String(body["id"]);
|
|
141634
141671
|
const privateKeyPem = typeof body["pem"] === "string" ? body["pem"] : "";
|
|
141635
141672
|
if (!appId || !privateKeyPem) throw new Error("github app: id/pem missing in conversion response");
|
|
141673
|
+
const owner = body["owner"];
|
|
141674
|
+
const rawPerms = body["permissions"];
|
|
141675
|
+
const permissions = {};
|
|
141676
|
+
for (const [k2, v2] of Object.entries(rawPerms ?? {})) if (typeof v2 === "string") permissions[k2] = v2;
|
|
141636
141677
|
return {
|
|
141637
141678
|
appId,
|
|
141638
141679
|
privateKeyPem,
|
|
141639
141680
|
slug: typeof body["slug"] === "string" ? body["slug"] : "",
|
|
141681
|
+
ownerLogin: typeof owner?.["login"] === "string" ? owner["login"] : "",
|
|
141682
|
+
ownerType: typeof owner?.["type"] === "string" ? owner["type"] : "",
|
|
141683
|
+
permissions,
|
|
141640
141684
|
...typeof body["webhook_secret"] === "string" ? { webhookSecret: body["webhook_secret"] } : {}
|
|
141641
141685
|
};
|
|
141642
141686
|
}
|
|
@@ -141720,6 +141764,18 @@ var init_github = __esm({
|
|
|
141720
141764
|
{ key: "access_token", from: "GITHUB_APP_TOKEN", required: false },
|
|
141721
141765
|
{ key: "app_token_expires_at", from: "GITHUB_APP_TOKEN_EXPIRES_AT", required: false }
|
|
141722
141766
|
];
|
|
141767
|
+
/**
|
|
141768
|
+
* installation token 满寿命就是 1 小时;声明成全寿命 ⇒ **每次注入都铸新的**。
|
|
141769
|
+
*
|
|
141770
|
+
* 代价可接受:铸 token 是纯换取(私钥 + installation_id 推出来的),
|
|
141771
|
+
* **旧 token 不会被新的作废**(GitHub 要显式 `DELETE /installation/token` 才失效),
|
|
141772
|
+
* 所以多铸一次既不打断在跑的会话、也不消耗任何一次性材料。
|
|
141773
|
+
*
|
|
141774
|
+
* 换来的是:一场会话开头拿到的 token 一定是满 60 分钟,而不是「上一场剩下的 6 分钟」。
|
|
141775
|
+
* ⚠ 仍挡不住跑超过 60 分钟的会话——会话硬顶是 120 分钟(`SESSION_WALL_CLOCK_MS`),
|
|
141776
|
+
* 那半截要靠会话内续期,本字段管不到。
|
|
141777
|
+
*/
|
|
141778
|
+
minRemainingLifetimeMs = 60 * 6e4;
|
|
141723
141779
|
/** 过期判定只认这个键——必须与注入时消费的 token 同源(契约测试盯着)。 */
|
|
141724
141780
|
expiresAtCredentialKey = "app_token_expires_at";
|
|
141725
141781
|
// 私钥不会过期,故不声明 refreshMaterialExpiresAtCredentialKey,也无需 clearOnExpired。
|
|
@@ -141729,6 +141785,12 @@ var init_github = __esm({
|
|
|
141729
141785
|
"GITHUB_APP_TOKEN",
|
|
141730
141786
|
"GITHUB_APP_PRIVATE_KEY"
|
|
141731
141787
|
];
|
|
141788
|
+
/**
|
|
141789
|
+
* 宿主机登录态隔离:`gh` 只认 env 里的 GH_TOKEN 或 `~/.config/gh/hosts.yml`。
|
|
141790
|
+
* 这个键**由通用装配层无条件设**(哪怕本连接器没接通),否则关掉连接器时
|
|
141791
|
+
* agent 会静默用成宿主机那个真人账号——见接口里的详细说明。
|
|
141792
|
+
*/
|
|
141793
|
+
hostCredentialIsolationEnvKeys = ["GH_CONFIG_DIR"];
|
|
141732
141794
|
/** inject() 写进 sessionEnv 的全部键——通用 cleanup() 按它逐个删。 */
|
|
141733
141795
|
injectedEnvKeys = [
|
|
141734
141796
|
"GH_BIN",
|
|
@@ -141819,7 +141881,7 @@ var init_github = __esm({
|
|
|
141819
141881
|
const creds = await writeSessionCredsFile(this.config.slug, {
|
|
141820
141882
|
GH_TOKEN: token,
|
|
141821
141883
|
GITHUB_TOKEN: token
|
|
141822
|
-
});
|
|
141884
|
+
}, sessionEnv.get("GH_RUN_TMPDIR"));
|
|
141823
141885
|
const configDir = (0, import_node_path7.join)(creds.dir, "gh-config");
|
|
141824
141886
|
await (0, import_promises4.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
141825
141887
|
sessionEnv.set("GH_BIN", await this.resolveRealBin("gh"));
|
|
@@ -141872,7 +141934,27 @@ function callbackHtml(ok, message) {
|
|
|
141872
141934
|
setTimeout(function(){window.close()},${ok ? 800 : 4e3})</script>
|
|
141873
141935
|
</body>`;
|
|
141874
141936
|
}
|
|
141875
|
-
|
|
141937
|
+
function checkAppOwnership(conv, want) {
|
|
141938
|
+
if (want.ownerKind === "org" && want.ownerLogin) {
|
|
141939
|
+
const got = conv.ownerLogin;
|
|
141940
|
+
if (!got) {
|
|
141941
|
+
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" };
|
|
141942
|
+
}
|
|
141943
|
+
if (got.toLowerCase() !== want.ownerLogin.toLowerCase()) {
|
|
141944
|
+
return {
|
|
141945
|
+
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`
|
|
141946
|
+
};
|
|
141947
|
+
}
|
|
141948
|
+
}
|
|
141949
|
+
const missing = REQUIRED_WRITE_PERMISSIONS.filter((k2) => conv.permissions[k2] !== "write");
|
|
141950
|
+
if (missing.length > 0) {
|
|
141951
|
+
return {
|
|
141952
|
+
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`
|
|
141953
|
+
};
|
|
141954
|
+
}
|
|
141955
|
+
return null;
|
|
141956
|
+
}
|
|
141957
|
+
var GITHUB_APP_DEFAULT_PERMISSIONS, GITHUB_APP_PERMISSION_LABELS, PENDING_TTL_MS, PendingAppCreations, REQUIRED_WRITE_PERMISSIONS;
|
|
141876
141958
|
var init_app_manifest = __esm({
|
|
141877
141959
|
"../connectors/src/github/app-manifest.ts"() {
|
|
141878
141960
|
"use strict";
|
|
@@ -141915,6 +141997,7 @@ var init_app_manifest = __esm({
|
|
|
141915
141997
|
return this.map.size;
|
|
141916
141998
|
}
|
|
141917
141999
|
};
|
|
142000
|
+
REQUIRED_WRITE_PERMISSIONS = ["contents", "pull_requests"];
|
|
141918
142001
|
}
|
|
141919
142002
|
});
|
|
141920
142003
|
|
|
@@ -141971,19 +142054,27 @@ function collectCredentials(connector, ctx) {
|
|
|
141971
142054
|
}
|
|
141972
142055
|
return creds;
|
|
141973
142056
|
}
|
|
142057
|
+
function collectAllConnectorCredentials(ctx) {
|
|
142058
|
+
return createAllConnectors().flatMap((connector) => {
|
|
142059
|
+
const credentials = collectCredentials(connector, ctx);
|
|
142060
|
+
return credentials ? [{ slug: connector.config.slug, credentials }] : [];
|
|
142061
|
+
});
|
|
142062
|
+
}
|
|
141974
142063
|
async function buildConnectorProvision(ctx) {
|
|
141975
142064
|
const envOverrides = {};
|
|
141976
142065
|
const wrapperPaths = [];
|
|
141977
142066
|
const requiredTools = /* @__PURE__ */ new Set();
|
|
141978
|
-
const connectorCreds = [];
|
|
141979
142067
|
const cleanups = [];
|
|
141980
142068
|
const sensitiveVars = /* @__PURE__ */ new Set();
|
|
142069
|
+
const isolationKeys = /* @__PURE__ */ new Set();
|
|
142070
|
+
const connectorCreds = collectAllConnectorCredentials(ctx);
|
|
142071
|
+
const credentialsBySlug = new Map(connectorCreds.map((c) => [c.slug, c.credentials]));
|
|
141981
142072
|
for (const connector of createAllConnectors()) {
|
|
141982
142073
|
for (const v2 of connector.sensitiveVars) sensitiveVars.add(v2);
|
|
141983
|
-
const
|
|
141984
|
-
|
|
142074
|
+
for (const k2 of connector.hostCredentialIsolationEnvKeys ?? []) isolationKeys.add(k2);
|
|
142075
|
+
const credentials = credentialsBySlug.get(connector.config.slug);
|
|
142076
|
+
if (credentials === void 0) continue;
|
|
141985
142077
|
try {
|
|
141986
|
-
connectorCreds.push({ slug: connector.config.slug, credentials });
|
|
141987
142078
|
const sessionEnv = /* @__PURE__ */ new Map();
|
|
141988
142079
|
await connector.inject(credentials, sessionEnv);
|
|
141989
142080
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
@@ -141999,6 +142090,19 @@ async function buildConnectorProvision(ctx) {
|
|
|
141999
142090
|
log("[provision]", `${connector.config.slug}: \u88C5\u914D\u5931\u8D25\uFF08\u8BE5\u8FDE\u63A5\u5668\u672C\u8F6E\u4E0D\u53EF\u7528\uFF09: ${String(err)}`);
|
|
142000
142091
|
}
|
|
142001
142092
|
}
|
|
142093
|
+
const isolationRoot = await (0, import_promises5.mkdtemp)((0, import_node_path8.join)((0, import_node_os4.tmpdir)(), "oasis-isolate-"));
|
|
142094
|
+
let isolationUsed = false;
|
|
142095
|
+
for (const key of isolationKeys) {
|
|
142096
|
+
if (envOverrides[key]) continue;
|
|
142097
|
+
const dir = (0, import_node_path8.join)(isolationRoot, key.toLowerCase());
|
|
142098
|
+
await (0, import_promises5.mkdir)(dir, { recursive: true, mode: 448 });
|
|
142099
|
+
envOverrides[key] = dir;
|
|
142100
|
+
isolationUsed = true;
|
|
142101
|
+
}
|
|
142102
|
+
if (!isolationUsed) await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
|
|
142103
|
+
else cleanups.push(async () => {
|
|
142104
|
+
await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
|
|
142105
|
+
});
|
|
142002
142106
|
const cleanup = async () => {
|
|
142003
142107
|
for (const fn of cleanups) await fn().catch(() => {
|
|
142004
142108
|
});
|
|
@@ -142012,23 +142116,28 @@ async function buildConnectorProvision(ctx) {
|
|
|
142012
142116
|
cleanup
|
|
142013
142117
|
};
|
|
142014
142118
|
}
|
|
142119
|
+
var import_promises5, import_node_os4, import_node_path8;
|
|
142015
142120
|
var init_provision = __esm({
|
|
142016
142121
|
"../connectors/src/provision.ts"() {
|
|
142017
142122
|
"use strict";
|
|
142018
142123
|
init_base();
|
|
142019
142124
|
init_registry2();
|
|
142020
142125
|
init_logger();
|
|
142126
|
+
import_promises5 = require("node:fs/promises");
|
|
142127
|
+
import_node_os4 = require("node:os");
|
|
142128
|
+
import_node_path8 = require("node:path");
|
|
142021
142129
|
}
|
|
142022
142130
|
});
|
|
142023
142131
|
|
|
142024
142132
|
// ../connectors/src/prepare-job.ts
|
|
142025
|
-
async function prepareConnectorsForJob(job) {
|
|
142133
|
+
async function prepareConnectorsForJob(job, deps) {
|
|
142026
142134
|
const creds = job.connectorCreds ?? [];
|
|
142027
142135
|
const remoteWrappers = job.wrapperPaths ?? [];
|
|
142028
142136
|
const localWrappers = [];
|
|
142029
142137
|
const cleanups = [];
|
|
142030
142138
|
const envOverrides = {};
|
|
142031
142139
|
const statuses = [];
|
|
142140
|
+
const injected = /* @__PURE__ */ new Map();
|
|
142032
142141
|
for (const { slug: slug6, credentials } of creds) {
|
|
142033
142142
|
const connector = createConnectorBySlug(slug6);
|
|
142034
142143
|
if (!connector) {
|
|
@@ -142043,6 +142152,7 @@ async function prepareConnectorsForJob(job) {
|
|
|
142043
142152
|
await connector.inject(credentials, sessionEnv);
|
|
142044
142153
|
for (const [k2, v2] of sessionEnv) envOverrides[k2] = v2;
|
|
142045
142154
|
cleanups.push(() => connector.cleanup(sessionEnv));
|
|
142155
|
+
injected.set(slug6, { connector, sessionEnv });
|
|
142046
142156
|
status.credsReady = true;
|
|
142047
142157
|
} catch (err) {
|
|
142048
142158
|
status.error = String(err);
|
|
@@ -142066,30 +142176,117 @@ async function prepareConnectorsForJob(job) {
|
|
|
142066
142176
|
}
|
|
142067
142177
|
const keptLocal = localWrappers.filter((p2) => isStagedWrapperUsable(p2));
|
|
142068
142178
|
const keptRemote = remoteWrappers.filter((p2) => (0, import_node_fs5.existsSync)(p2));
|
|
142069
|
-
const
|
|
142070
|
-
if (
|
|
142179
|
+
const droppedWrappers = remoteWrappers.length - keptRemote.length + (localWrappers.length - keptLocal.length);
|
|
142180
|
+
if (droppedWrappers > 0) log("[node-connectors]", `\u4E22\u5F03 ${droppedWrappers} \u6761\u672C\u673A\u4E0D\u53EF\u7528\u7684 wrapper \u8DEF\u5F84`);
|
|
142181
|
+
const staleKeys = /* @__PURE__ */ new Set();
|
|
142182
|
+
const isolationKeys = /* @__PURE__ */ new Set();
|
|
142183
|
+
for (const connector of createAllConnectors()) {
|
|
142184
|
+
if (injected.has(connector.config.slug)) continue;
|
|
142185
|
+
const isolation = new Set(connector.hostCredentialIsolationEnvKeys ?? []);
|
|
142186
|
+
for (const key of connector.injectedEnvKeys) {
|
|
142187
|
+
if (isolation.has(key)) isolationKeys.add(key);
|
|
142188
|
+
else staleKeys.add(key);
|
|
142189
|
+
}
|
|
142190
|
+
}
|
|
142071
142191
|
const basePath = job.env?.["PATH"] ?? process.env["PATH"] ?? "";
|
|
142072
142192
|
const toolsBin = connectorToolsBinDir();
|
|
142073
142193
|
const pathWithTools = basePath.split(":").includes(toolsBin) ? basePath : [toolsBin, basePath].filter(Boolean).join(":");
|
|
142194
|
+
const jobEnv = { ...job.env ?? {}, ...envOverrides, PATH: pathWithTools };
|
|
142195
|
+
let dropped = 0;
|
|
142196
|
+
for (const key of staleKeys) {
|
|
142197
|
+
if (jobEnv[key] === void 0) continue;
|
|
142198
|
+
delete jobEnv[key];
|
|
142199
|
+
dropped++;
|
|
142200
|
+
}
|
|
142201
|
+
if (isolationKeys.size > 0) {
|
|
142202
|
+
const isolationRoot = await (0, import_promises6.mkdtemp)((0, import_node_path9.join)((0, import_node_os5.tmpdir)(), "oasis-node-isolate-"));
|
|
142203
|
+
for (const key of isolationKeys) {
|
|
142204
|
+
const dir = (0, import_node_path9.join)(isolationRoot, key.toLowerCase());
|
|
142205
|
+
await (0, import_promises6.mkdir)(dir, { recursive: true, mode: 448 });
|
|
142206
|
+
jobEnv[key] = dir;
|
|
142207
|
+
}
|
|
142208
|
+
cleanups.push(async () => {
|
|
142209
|
+
await (0, import_promises6.rm)(isolationRoot, { recursive: true, force: true });
|
|
142210
|
+
});
|
|
142211
|
+
}
|
|
142212
|
+
if (dropped > 0) {
|
|
142213
|
+
log(
|
|
142214
|
+
"[node-connectors]",
|
|
142215
|
+
`\u26A0 \u6E05\u6389 ${dropped} \u4E2A\u6307\u5411\u522B\u7684\u673A\u5668\u7684\u8FDE\u63A5\u5668 env \u952E\uFF08server \u53D1\u4E86\u6307\u9488\u4F46\u6CA1\u53D1\u51ED\u636E\uFF09\u2014\u2014\u672C\u8F6E\u8FD9\u4E9B\u8FDE\u63A5\u5668**\u4E0D\u53EF\u7528**\uFF0Cagent \u5E94\u636E\u6B64\u5224\u5B9A\u300C\u6CA1\u6709\u8BE5\u80FD\u529B\u300D\uFF0C\u800C\u4E0D\u662F\u4EE5\u4E3A\u914D\u597D\u4E86\u3002`
|
|
142216
|
+
);
|
|
142217
|
+
}
|
|
142074
142218
|
const preparedJob = {
|
|
142075
142219
|
...job,
|
|
142076
|
-
env:
|
|
142220
|
+
env: jobEnv,
|
|
142077
142221
|
wrapperPaths: [...keptLocal, ...keptRemote]
|
|
142078
142222
|
};
|
|
142223
|
+
if (injected.size > 0 && (job.limits?.wallClockMs ?? 0) > SESSION_CREDENTIAL_RENEW_INTERVAL_MS) {
|
|
142224
|
+
const fetchCredentials = deps?.fetchCredentials ?? fetchCredentialsFromServer(job);
|
|
142225
|
+
const setTimer = deps?.setTimer ?? defaultSetTimer;
|
|
142226
|
+
const timer = setTimer(() => {
|
|
142227
|
+
void renewInjectedCredentials(injected, fetchCredentials);
|
|
142228
|
+
}, SESSION_CREDENTIAL_RENEW_INTERVAL_MS);
|
|
142229
|
+
cleanups.push(async () => {
|
|
142230
|
+
timer.stop();
|
|
142231
|
+
});
|
|
142232
|
+
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`);
|
|
142233
|
+
}
|
|
142079
142234
|
const cleanup = async () => {
|
|
142080
142235
|
for (const fn of cleanups) await fn().catch(() => {
|
|
142081
142236
|
});
|
|
142082
142237
|
};
|
|
142083
142238
|
return { job: preparedJob, cleanup, statuses };
|
|
142084
142239
|
}
|
|
142085
|
-
|
|
142240
|
+
async function renewInjectedCredentials(injected, fetchCredentials) {
|
|
142241
|
+
const outcome = { renewed: [], failed: [] };
|
|
142242
|
+
let fresh;
|
|
142243
|
+
try {
|
|
142244
|
+
fresh = await fetchCredentials();
|
|
142245
|
+
} catch (err) {
|
|
142246
|
+
for (const slug6 of injected.keys()) outcome.failed.push({ slug: slug6, error: String(err) });
|
|
142247
|
+
log("[node-connectors]", `\u7EED\u671F\uFF1A\u5411 server \u53D6\u51ED\u636E\u5931\u8D25\uFF0C\u672C\u8F6E\u6CBF\u7528\u65E7\u51ED\u636E: ${String(err)}`);
|
|
142248
|
+
return outcome;
|
|
142249
|
+
}
|
|
142250
|
+
for (const { slug: slug6, credentials } of fresh) {
|
|
142251
|
+
const target = injected.get(slug6);
|
|
142252
|
+
if (!target) continue;
|
|
142253
|
+
try {
|
|
142254
|
+
await target.connector.inject(credentials, target.sessionEnv);
|
|
142255
|
+
outcome.renewed.push(slug6);
|
|
142256
|
+
} catch (err) {
|
|
142257
|
+
outcome.failed.push({ slug: slug6, error: String(err) });
|
|
142258
|
+
log("[node-connectors]", `\u26A0 \u7EED\u671F\uFF1A${slug6} \u5C31\u5730\u91CD\u6CE8\u5931\u8D25\uFF0C\u6CBF\u7528\u65E7\u51ED\u636E: ${String(err)}`);
|
|
142259
|
+
}
|
|
142260
|
+
}
|
|
142261
|
+
if (outcome.renewed.length > 0) log("[node-connectors]", `\u7EED\u671F\uFF1A\u5DF2\u5C31\u5730\u6362\u65B0 ${outcome.renewed.join(", ")}`);
|
|
142262
|
+
return outcome;
|
|
142263
|
+
}
|
|
142264
|
+
function defaultSetTimer(fn, ms) {
|
|
142265
|
+
const timer = setInterval(fn, ms);
|
|
142266
|
+
timer.unref?.();
|
|
142267
|
+
return { stop: () => clearInterval(timer) };
|
|
142268
|
+
}
|
|
142269
|
+
function fetchCredentialsFromServer(job) {
|
|
142270
|
+
return async () => {
|
|
142271
|
+
const url = new URL("/api/connector-credentials", job.server?.url ?? "").toString();
|
|
142272
|
+
const res = await fetch(url, { headers: { authorization: `Bearer ${job.actorToken}` } });
|
|
142273
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
142274
|
+
const body = await res.json();
|
|
142275
|
+
return body.connectorCreds ?? [];
|
|
142276
|
+
};
|
|
142277
|
+
}
|
|
142278
|
+
var import_node_fs5, import_promises6, import_node_os5, import_node_path9, SESSION_CREDENTIAL_RENEW_INTERVAL_MS;
|
|
142086
142279
|
var init_prepare_job = __esm({
|
|
142087
142280
|
"../connectors/src/prepare-job.ts"() {
|
|
142088
142281
|
"use strict";
|
|
142089
142282
|
import_node_fs5 = require("node:fs");
|
|
142283
|
+
import_promises6 = require("node:fs/promises");
|
|
142284
|
+
import_node_os5 = require("node:os");
|
|
142285
|
+
import_node_path9 = require("node:path");
|
|
142090
142286
|
init_base();
|
|
142091
142287
|
init_registry2();
|
|
142092
142288
|
init_logger();
|
|
142289
|
+
SESSION_CREDENTIAL_RENEW_INTERVAL_MS = 30 * 6e4;
|
|
142093
142290
|
}
|
|
142094
142291
|
});
|
|
142095
142292
|
|
|
@@ -142428,8 +142625,8 @@ function materializeFiles(dir, files) {
|
|
|
142428
142625
|
if (!files) return;
|
|
142429
142626
|
for (const [rel, content] of Object.entries(files)) {
|
|
142430
142627
|
try {
|
|
142431
|
-
const file =
|
|
142432
|
-
import_node_fs6.default.mkdirSync(
|
|
142628
|
+
const file = import_node_path10.default.join(dir, rel);
|
|
142629
|
+
import_node_fs6.default.mkdirSync(import_node_path10.default.dirname(file), { recursive: true });
|
|
142433
142630
|
import_node_fs6.default.writeFileSync(file, content);
|
|
142434
142631
|
} catch {
|
|
142435
142632
|
}
|
|
@@ -142445,7 +142642,7 @@ function resolveLegacyWorkRoot(workRoot) {
|
|
|
142445
142642
|
if (workRoot) return workRoot;
|
|
142446
142643
|
const env = process.env["OASIS_WORK_ROOT"];
|
|
142447
142644
|
if (env) return env;
|
|
142448
|
-
return
|
|
142645
|
+
return import_node_os6.default.tmpdir();
|
|
142449
142646
|
}
|
|
142450
142647
|
function resolveWorkRoots(workRoot) {
|
|
142451
142648
|
return { workRoot: resolveWorkRoot(workRoot), legacyRoot: resolveLegacyWorkRoot(workRoot) };
|
|
@@ -142456,7 +142653,7 @@ function slug5(workdirKey) {
|
|
|
142456
142653
|
return `${safe}-${h}`;
|
|
142457
142654
|
}
|
|
142458
142655
|
function sessionDirFor(workRoot, runtimeKind, workdirKey) {
|
|
142459
|
-
return
|
|
142656
|
+
return import_node_path10.default.join(resolveWorkRoot(workRoot), "sessions", runtimeKind, slug5(workdirKey));
|
|
142460
142657
|
}
|
|
142461
142658
|
function sessionDirKind(runtimeKind) {
|
|
142462
142659
|
return runtimeKind === "claude-code" ? "claude" : runtimeKind;
|
|
@@ -142469,20 +142666,20 @@ function resolveSessionDirWithLegacy(args) {
|
|
|
142469
142666
|
return import_node_fs6.default.existsSync(legacy) ? legacy : fresh;
|
|
142470
142667
|
}
|
|
142471
142668
|
function oneShotDirFor(workRoot, runtimeKind) {
|
|
142472
|
-
const base =
|
|
142669
|
+
const base = import_node_path10.default.join(resolveWorkRoot(workRoot), "tmp");
|
|
142473
142670
|
import_node_fs6.default.mkdirSync(base, { recursive: true });
|
|
142474
|
-
return import_node_fs6.default.mkdtempSync(
|
|
142671
|
+
return import_node_fs6.default.mkdtempSync(import_node_path10.default.join(base, `${runtimeKind}-`));
|
|
142475
142672
|
}
|
|
142476
142673
|
function writeMeta(dir, meta) {
|
|
142477
142674
|
try {
|
|
142478
|
-
import_node_fs6.default.writeFileSync(
|
|
142675
|
+
import_node_fs6.default.writeFileSync(import_node_path10.default.join(dir, META_FILE), `${JSON.stringify(meta, null, 2)}
|
|
142479
142676
|
`);
|
|
142480
142677
|
} catch {
|
|
142481
142678
|
}
|
|
142482
142679
|
}
|
|
142483
142680
|
function readMeta(dir) {
|
|
142484
142681
|
try {
|
|
142485
|
-
const raw = JSON.parse(import_node_fs6.default.readFileSync(
|
|
142682
|
+
const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, META_FILE), "utf8"));
|
|
142486
142683
|
if (!raw || typeof raw !== "object") return null;
|
|
142487
142684
|
const m2 = raw;
|
|
142488
142685
|
return typeof m2.kind === "string" && typeof m2.createdAt === "string" ? m2 : null;
|
|
@@ -142511,14 +142708,14 @@ function lockWorkdir(dir, pid, holder, workdirKey) {
|
|
|
142511
142708
|
...workdirKey !== void 0 ? { workdirKey } : {}
|
|
142512
142709
|
};
|
|
142513
142710
|
try {
|
|
142514
|
-
import_node_fs6.default.writeFileSync(
|
|
142711
|
+
import_node_fs6.default.writeFileSync(import_node_path10.default.join(dir, LOCK_FILE), `${JSON.stringify(lock)}
|
|
142515
142712
|
`);
|
|
142516
142713
|
} catch {
|
|
142517
142714
|
}
|
|
142518
142715
|
}
|
|
142519
142716
|
function readLock(dir) {
|
|
142520
142717
|
try {
|
|
142521
|
-
const raw = JSON.parse(import_node_fs6.default.readFileSync(
|
|
142718
|
+
const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, LOCK_FILE), "utf8"));
|
|
142522
142719
|
if (!raw || typeof raw !== "object") return null;
|
|
142523
142720
|
const l = raw;
|
|
142524
142721
|
return Number.isInteger(l.pid) && l.pid > 0 ? l : null;
|
|
@@ -142528,14 +142725,14 @@ function readLock(dir) {
|
|
|
142528
142725
|
}
|
|
142529
142726
|
function unlockWorkdir(dir) {
|
|
142530
142727
|
try {
|
|
142531
|
-
import_node_fs6.default.unlinkSync(
|
|
142728
|
+
import_node_fs6.default.unlinkSync(import_node_path10.default.join(dir, LOCK_FILE));
|
|
142532
142729
|
} catch {
|
|
142533
142730
|
}
|
|
142534
142731
|
}
|
|
142535
142732
|
function isWorkdirLive(dir) {
|
|
142536
142733
|
let raw;
|
|
142537
142734
|
try {
|
|
142538
|
-
raw = import_node_fs6.default.readFileSync(
|
|
142735
|
+
raw = import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, LOCK_FILE), "utf8");
|
|
142539
142736
|
} catch {
|
|
142540
142737
|
return false;
|
|
142541
142738
|
}
|
|
@@ -142552,7 +142749,7 @@ function clearWorkdir(dir) {
|
|
|
142552
142749
|
);
|
|
142553
142750
|
}
|
|
142554
142751
|
for (const entry of import_node_fs6.default.readdirSync(dir)) {
|
|
142555
|
-
import_node_fs6.default.rmSync(
|
|
142752
|
+
import_node_fs6.default.rmSync(import_node_path10.default.join(dir, entry), { recursive: true, force: true });
|
|
142556
142753
|
}
|
|
142557
142754
|
}
|
|
142558
142755
|
function prepareWorkdir(args) {
|
|
@@ -142582,19 +142779,19 @@ function prepareWorkdir(args) {
|
|
|
142582
142779
|
return dir;
|
|
142583
142780
|
}
|
|
142584
142781
|
function legacyChatSessionDir(workRoot, rtId) {
|
|
142585
|
-
return
|
|
142782
|
+
return import_node_path10.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
|
|
142586
142783
|
}
|
|
142587
|
-
var import_node_crypto9, import_node_fs6,
|
|
142784
|
+
var import_node_crypto9, import_node_fs6, import_node_os6, import_node_path10, META_FILE, LOCK_FILE, NEW_WORK_ROOT, LEGACY_ROOTS, LEGACY_ONESHOT_PREFIX;
|
|
142588
142785
|
var init_session_paths = __esm({
|
|
142589
142786
|
"../adapters/src/_core/session-paths.ts"() {
|
|
142590
142787
|
"use strict";
|
|
142591
142788
|
import_node_crypto9 = require("node:crypto");
|
|
142592
142789
|
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
142593
|
-
|
|
142594
|
-
|
|
142790
|
+
import_node_os6 = __toESM(require("node:os"), 1);
|
|
142791
|
+
import_node_path10 = __toESM(require("node:path"), 1);
|
|
142595
142792
|
META_FILE = ".oasis-meta.json";
|
|
142596
142793
|
LOCK_FILE = ".oasis-lock";
|
|
142597
|
-
NEW_WORK_ROOT = () =>
|
|
142794
|
+
NEW_WORK_ROOT = () => import_node_path10.default.join(import_node_os6.default.homedir(), ".oasis", "work");
|
|
142598
142795
|
LEGACY_ROOTS = ["oasis-chat-sessions", "oasis-transcripts"];
|
|
142599
142796
|
LEGACY_ONESHOT_PREFIX = "oasis-session-";
|
|
142600
142797
|
}
|
|
@@ -143816,7 +144013,7 @@ async function discoverACPModels(bin, provider, args = ["acp"]) {
|
|
|
143816
144013
|
clientCapabilities: {}
|
|
143817
144014
|
});
|
|
143818
144015
|
try {
|
|
143819
|
-
tmpDir = (0, import_node_fs7.mkdtempSync)((0,
|
|
144016
|
+
tmpDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path11.join)((0, import_node_os7.tmpdir)(), `oasis-acp-${provider}-`));
|
|
143820
144017
|
} catch {
|
|
143821
144018
|
return fail();
|
|
143822
144019
|
}
|
|
@@ -143872,14 +144069,14 @@ function parseACPSessionNewModels(result) {
|
|
|
143872
144069
|
async function discoverOpenclawModels(bin) {
|
|
143873
144070
|
throw new Error("discoverOpenclawModels: TODO");
|
|
143874
144071
|
}
|
|
143875
|
-
var import_node_child_process9, import_node_fs7,
|
|
144072
|
+
var import_node_child_process9, import_node_fs7, import_node_os7, import_node_path11, modelCache, CACHE_TTL_MS;
|
|
143876
144073
|
var init_models = __esm({
|
|
143877
144074
|
"../adapters/src/_core/models.ts"() {
|
|
143878
144075
|
"use strict";
|
|
143879
144076
|
import_node_child_process9 = require("node:child_process");
|
|
143880
144077
|
import_node_fs7 = require("node:fs");
|
|
143881
|
-
|
|
143882
|
-
|
|
144078
|
+
import_node_os7 = require("node:os");
|
|
144079
|
+
import_node_path11 = require("node:path");
|
|
143883
144080
|
modelCache = /* @__PURE__ */ new Map();
|
|
143884
144081
|
CACHE_TTL_MS = 6e4;
|
|
143885
144082
|
}
|
|
@@ -146446,7 +146643,7 @@ function dirSizeBytes(dir) {
|
|
|
146446
146643
|
return;
|
|
146447
146644
|
}
|
|
146448
146645
|
for (const e of entries) {
|
|
146449
|
-
const p2 =
|
|
146646
|
+
const p2 = import_node_path12.default.join(d, e.name);
|
|
146450
146647
|
if (e.isSymbolicLink()) continue;
|
|
146451
146648
|
if (e.isDirectory()) {
|
|
146452
146649
|
walk(p2);
|
|
@@ -146463,40 +146660,40 @@ function dirSizeBytes(dir) {
|
|
|
146463
146660
|
}
|
|
146464
146661
|
function listWorkdirs(workRoot, legacyRoot) {
|
|
146465
146662
|
const out = [];
|
|
146466
|
-
const sessions =
|
|
146663
|
+
const sessions = import_node_path12.default.join(workRoot, "sessions");
|
|
146467
146664
|
try {
|
|
146468
146665
|
for (const kind of import_node_fs8.default.readdirSync(sessions)) {
|
|
146469
|
-
const kindDir =
|
|
146666
|
+
const kindDir = import_node_path12.default.join(sessions, kind);
|
|
146470
146667
|
try {
|
|
146471
|
-
for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(
|
|
146668
|
+
for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(import_node_path12.default.join(kindDir, slug6));
|
|
146472
146669
|
} catch {
|
|
146473
146670
|
}
|
|
146474
146671
|
}
|
|
146475
146672
|
} catch {
|
|
146476
146673
|
}
|
|
146477
|
-
const tmp =
|
|
146674
|
+
const tmp = import_node_path12.default.join(workRoot, "tmp");
|
|
146478
146675
|
try {
|
|
146479
|
-
for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(
|
|
146676
|
+
for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(import_node_path12.default.join(tmp, d));
|
|
146480
146677
|
} catch {
|
|
146481
146678
|
}
|
|
146482
146679
|
for (const legacy of LEGACY_ROOTS) {
|
|
146483
|
-
const root =
|
|
146680
|
+
const root = import_node_path12.default.join(legacyRoot, legacy);
|
|
146484
146681
|
try {
|
|
146485
|
-
for (const d of import_node_fs8.default.readdirSync(root)) out.push(
|
|
146682
|
+
for (const d of import_node_fs8.default.readdirSync(root)) out.push(import_node_path12.default.join(root, d));
|
|
146486
146683
|
} catch {
|
|
146487
146684
|
}
|
|
146488
146685
|
}
|
|
146489
146686
|
try {
|
|
146490
146687
|
for (const d of import_node_fs8.default.readdirSync(legacyRoot)) {
|
|
146491
|
-
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(
|
|
146688
|
+
if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(import_node_path12.default.join(legacyRoot, d));
|
|
146492
146689
|
}
|
|
146493
146690
|
} catch {
|
|
146494
146691
|
}
|
|
146495
146692
|
return [...new Set(out)];
|
|
146496
146693
|
}
|
|
146497
146694
|
function kindFromPath(workRoot, dir) {
|
|
146498
|
-
const rel =
|
|
146499
|
-
const parts = rel.split(
|
|
146695
|
+
const rel = import_node_path12.default.relative(workRoot, dir);
|
|
146696
|
+
const parts = rel.split(import_node_path12.default.sep);
|
|
146500
146697
|
if (parts[0] === "sessions" && parts[1]) return parts[1];
|
|
146501
146698
|
if (parts[0] === "tmp" && parts[1]) return parts[1].replace(/-[^-]*$/, "");
|
|
146502
146699
|
return void 0;
|
|
@@ -146538,7 +146735,7 @@ async function runGcSweep(deps) {
|
|
|
146538
146735
|
let deleted = 0;
|
|
146539
146736
|
for (const d of decisions) {
|
|
146540
146737
|
if (d.action !== "delete") continue;
|
|
146541
|
-
if (import_node_fs8.default.existsSync(
|
|
146738
|
+
if (import_node_fs8.default.existsSync(import_node_path12.default.join(d.dir, LOCK_FILE)) && isWorkdirLive(d.dir)) {
|
|
146542
146739
|
log3(`[gc] \u8DF3\u8FC7 ${d.dir}\uFF1A\u6267\u884C\u524D\u590D\u67E5\u53D1\u73B0\u5DF2\u88AB\u5360\u7528`);
|
|
146543
146740
|
continue;
|
|
146544
146741
|
}
|
|
@@ -146589,12 +146786,12 @@ function startGcLoop(deps) {
|
|
|
146589
146786
|
clearInterval(timer);
|
|
146590
146787
|
};
|
|
146591
146788
|
}
|
|
146592
|
-
var import_node_fs8,
|
|
146789
|
+
var import_node_fs8, import_node_path12;
|
|
146593
146790
|
var init_gc_loop = __esm({
|
|
146594
146791
|
"../adapters/src/_core/gc-loop.ts"() {
|
|
146595
146792
|
"use strict";
|
|
146596
146793
|
import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
146597
|
-
|
|
146794
|
+
import_node_path12 = __toESM(require("node:path"), 1);
|
|
146598
146795
|
init_session_paths();
|
|
146599
146796
|
init_workdir_gc();
|
|
146600
146797
|
}
|
|
@@ -146630,14 +146827,14 @@ var init_src4 = __esm({
|
|
|
146630
146827
|
});
|
|
146631
146828
|
|
|
146632
146829
|
// ../connectors/src/connector-adapter.ts
|
|
146633
|
-
var
|
|
146830
|
+
var import_promises7, import_node_fs9, import_node_os8, import_node_path13, ConnectorAwareAdapter;
|
|
146634
146831
|
var init_connector_adapter = __esm({
|
|
146635
146832
|
"../connectors/src/connector-adapter.ts"() {
|
|
146636
146833
|
"use strict";
|
|
146637
|
-
|
|
146834
|
+
import_promises7 = require("node:fs/promises");
|
|
146638
146835
|
import_node_fs9 = require("node:fs");
|
|
146639
|
-
|
|
146640
|
-
|
|
146836
|
+
import_node_os8 = require("node:os");
|
|
146837
|
+
import_node_path13 = require("node:path");
|
|
146641
146838
|
init_src4();
|
|
146642
146839
|
init_base();
|
|
146643
146840
|
init_prepare_job();
|
|
@@ -146660,11 +146857,11 @@ var init_connector_adapter = __esm({
|
|
|
146660
146857
|
const wrapperPaths = [...prepared.job.wrapperPaths ?? [], ...sentinelWrappers];
|
|
146661
146858
|
let extraEnv = { ...strippedEnv };
|
|
146662
146859
|
if (wrapperPaths.length > 0) {
|
|
146663
|
-
const wrapperBinDir = await (0,
|
|
146664
|
-
await (0,
|
|
146860
|
+
const wrapperBinDir = await (0, import_promises7.mkdtemp)((0, import_node_path13.join)((0, import_node_os8.tmpdir)(), "oasis-wrappers-"));
|
|
146861
|
+
await (0, import_promises7.mkdir)(wrapperBinDir, { recursive: true });
|
|
146665
146862
|
for (const wp of wrapperPaths) {
|
|
146666
|
-
const linkName = (0,
|
|
146667
|
-
await (0,
|
|
146863
|
+
const linkName = (0, import_node_path13.basename)(wp).replace(/\.sh$/, "");
|
|
146864
|
+
await (0, import_promises7.symlink)(wp, (0, import_node_path13.join)(wrapperBinDir, linkName));
|
|
146668
146865
|
}
|
|
146669
146866
|
extraEnv = { ...extraEnv, PATH: [wrapperBinDir, extraEnv["PATH"] ?? ""].filter(Boolean).join(":") };
|
|
146670
146867
|
log("[adapter]", ` connectors injected +${Date.now() - t0}ms wrappers=${wrapperPaths.length}`);
|
|
@@ -149451,12 +149648,12 @@ async function startOasisServer(opts) {
|
|
|
149451
149648
|
const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
|
|
149452
149649
|
if (actorCtx) {
|
|
149453
149650
|
const { mkdtempSync: mkdtempSync5, mkdirSync: mkdirSync21, writeFileSync: writeFileSync13 } = await import("node:fs");
|
|
149454
|
-
const { join:
|
|
149455
|
-
const { tmpdir:
|
|
149456
|
-
const dir = mkdtempSync5(
|
|
149651
|
+
const { join: join32, dirname: dirname24 } = await import("node:path");
|
|
149652
|
+
const { tmpdir: tmpdir10 } = await import("node:os");
|
|
149653
|
+
const dir = mkdtempSync5(join32(tmpdir10(), "oasis-chat-"));
|
|
149457
149654
|
if (actorCtx.config?.prompt) {
|
|
149458
149655
|
for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
149459
|
-
const file =
|
|
149656
|
+
const file = join32(dir, rel);
|
|
149460
149657
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149461
149658
|
writeFileSync13(file, content);
|
|
149462
149659
|
}
|
|
@@ -149468,12 +149665,12 @@ async function startOasisServer(opts) {
|
|
|
149468
149665
|
const s2 = byId.get(id);
|
|
149469
149666
|
return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
|
|
149470
149667
|
});
|
|
149471
|
-
writeFileSync13(
|
|
149668
|
+
writeFileSync13(join32(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
|
|
149472
149669
|
}
|
|
149473
149670
|
if (opts.materializeSkills) {
|
|
149474
149671
|
const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
|
|
149475
149672
|
for (const [rel, content] of Object.entries(skillFiles)) {
|
|
149476
|
-
const file =
|
|
149673
|
+
const file = join32(dir, rel);
|
|
149477
149674
|
mkdirSync21(dirname24(file), { recursive: true });
|
|
149478
149675
|
writeFileSync13(file, content);
|
|
149479
149676
|
}
|
|
@@ -149487,7 +149684,7 @@ async function startOasisServer(opts) {
|
|
|
149487
149684
|
const modeNote = c.mode === "oauth" ? "OAuth \xB7 \u51ED\u8BC1\u7531\u5E73\u53F0\u7BA1\u7406\uFF0C\u901A\u8FC7\u5BF9\u5E94 CLI wrapper \u8C03\u7528" : "\u76F4\u63A5\u5199\u5165 \xB7 \u51ED\u8BC1\u5DF2\u6CE8\u5165\u73AF\u5883\u53D8\u91CF";
|
|
149488
149685
|
return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
|
|
149489
149686
|
});
|
|
149490
|
-
writeFileSync13(
|
|
149687
|
+
writeFileSync13(join32(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
|
|
149491
149688
|
}
|
|
149492
149689
|
spawnCwd = dir;
|
|
149493
149690
|
}
|
|
@@ -149728,7 +149925,14 @@ async function startOasisServer(opts) {
|
|
|
149728
149925
|
baseUrl: base,
|
|
149729
149926
|
redirectPath: "/api/connectors/github/app/manifest-callback"
|
|
149730
149927
|
});
|
|
149731
|
-
githubAppPending.put(state, {
|
|
149928
|
+
githubAppPending.put(state, {
|
|
149929
|
+
...actorId ? { actorId } : {},
|
|
149930
|
+
employeeSlug: nameSlug,
|
|
149931
|
+
createdAtMs: Date.now(),
|
|
149932
|
+
// 存下这次选的归属——回调时要拿它跟 GitHub 返回的 owner 比对。
|
|
149933
|
+
wantOwnerKind: kind,
|
|
149934
|
+
...kind === "org" && owner?.login ? { wantOwnerLogin: owner.login } : {}
|
|
149935
|
+
});
|
|
149732
149936
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({
|
|
149733
149937
|
state,
|
|
149734
149938
|
formAction: manifestFormAction(kind === "org" ? { kind: "org", login: owner.login } : { kind: "user" }, state),
|
|
@@ -149791,6 +149995,14 @@ async function startOasisServer(opts) {
|
|
|
149791
149995
|
}
|
|
149792
149996
|
try {
|
|
149793
149997
|
const conv = await exchangeManifestCode(code);
|
|
149998
|
+
const problem = checkAppOwnership(conv, {
|
|
149999
|
+
...pending.wantOwnerLogin ? { ownerLogin: pending.wantOwnerLogin } : {},
|
|
150000
|
+
...pending.wantOwnerKind ? { ownerKind: pending.wantOwnerKind } : {}
|
|
150001
|
+
});
|
|
150002
|
+
if (problem) {
|
|
150003
|
+
fail(problem.message);
|
|
150004
|
+
return;
|
|
150005
|
+
}
|
|
149794
150006
|
const svc = opts.actors?.service;
|
|
149795
150007
|
if (!svc) throw new Error("actors service unavailable");
|
|
149796
150008
|
const scope = pending.actorId ? { scope: "personal", actorId: pending.actorId } : { scope: "global" };
|
|
@@ -150446,9 +150658,11 @@ var init_memory_registry_store = __esm({
|
|
|
150446
150658
|
// key: ${runtimeId}::${modelId}
|
|
150447
150659
|
connectors = /* @__PURE__ */ new Map();
|
|
150448
150660
|
variables = /* @__PURE__ */ new Map();
|
|
150449
|
-
// key = key::actorId
|
|
150450
|
-
|
|
150451
|
-
|
|
150661
|
+
// key = key::actorId::projectId
|
|
150662
|
+
// 唯一键覆盖三种作用域(ADR 0125:无 environment 维):personal=(key,actorId)、project=(key,projectId)、global=(key)。
|
|
150663
|
+
// 三段拼接后天然互不碰撞(personal 有 actorId 无 projectId,project 反之,global 全空)。
|
|
150664
|
+
_varKey(key, actorId, projectId) {
|
|
150665
|
+
return `${key}::${actorId ?? ""}::${projectId ?? ""}`;
|
|
150452
150666
|
}
|
|
150453
150667
|
skillCatalog = /* @__PURE__ */ new Map();
|
|
150454
150668
|
installedSkills = /* @__PURE__ */ new Map();
|
|
@@ -150581,7 +150795,7 @@ var init_memory_registry_store = __esm({
|
|
|
150581
150795
|
this.skillFiles.delete(skillId);
|
|
150582
150796
|
}
|
|
150583
150797
|
async putVariable(v2) {
|
|
150584
|
-
this.variables.set(this._varKey(v2.key, v2.actorId), { ...v2 });
|
|
150798
|
+
this.variables.set(this._varKey(v2.key, v2.actorId, v2.projectId), { ...v2 });
|
|
150585
150799
|
}
|
|
150586
150800
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
150587
150801
|
const mk = this._varKey(key, actorId);
|
|
@@ -150596,8 +150810,11 @@ var init_memory_registry_store = __esm({
|
|
|
150596
150810
|
if (actorId !== void 0) return all.filter((v2) => v2.scope === "global" || v2.actorId === actorId).map((v2) => ({ ...v2 }));
|
|
150597
150811
|
return all.map((v2) => ({ ...v2 }));
|
|
150598
150812
|
}
|
|
150599
|
-
async
|
|
150600
|
-
this.variables.
|
|
150813
|
+
async resolveProjectVariables(projectId) {
|
|
150814
|
+
return [...this.variables.values()].filter((v2) => v2.scope === "project" && v2.projectId === projectId).map((v2) => ({ ...v2 }));
|
|
150815
|
+
}
|
|
150816
|
+
async deleteVariable(key, actorId, scoping) {
|
|
150817
|
+
this.variables.delete(this._varKey(key, actorId, scoping?.projectId));
|
|
150601
150818
|
}
|
|
150602
150819
|
};
|
|
150603
150820
|
}
|
|
@@ -154721,6 +154938,10 @@ async function sweepSilentSessions(deps) {
|
|
|
154721
154938
|
continue;
|
|
154722
154939
|
}
|
|
154723
154940
|
if (!live.lastEventAt) continue;
|
|
154941
|
+
if (deps.isTraceHealthy && !deps.isTraceHealthy(s2.sessionId)) {
|
|
154942
|
+
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`);
|
|
154943
|
+
continue;
|
|
154944
|
+
}
|
|
154724
154945
|
const runtime = { hasInFlight: true, lastSessionEventAt: live.lastEventAt, openToolCall: live.openToolCall };
|
|
154725
154946
|
if (!isRuntimeSilent(runtime, deps.now, deps.silentThresholdMs)) continue;
|
|
154726
154947
|
const ok = await deps.kill(s2.jobKey).catch(() => false);
|
|
@@ -155420,6 +155641,73 @@ var init_recovery_plan = __esm({
|
|
|
155420
155641
|
}
|
|
155421
155642
|
});
|
|
155422
155643
|
|
|
155644
|
+
// ../server/src/domains/trace/resilient-appender.ts
|
|
155645
|
+
var ResilientTraceAppender;
|
|
155646
|
+
var init_resilient_appender = __esm({
|
|
155647
|
+
"../server/src/domains/trace/resilient-appender.ts"() {
|
|
155648
|
+
"use strict";
|
|
155649
|
+
ResilientTraceAppender = class {
|
|
155650
|
+
constructor(opts) {
|
|
155651
|
+
this.opts = opts;
|
|
155652
|
+
this.seq = opts.startSeq ?? 0;
|
|
155653
|
+
}
|
|
155654
|
+
seq;
|
|
155655
|
+
failing = false;
|
|
155656
|
+
/** 当前已成功落库的最大 seq。 */
|
|
155657
|
+
get currentSeq() {
|
|
155658
|
+
return this.seq;
|
|
155659
|
+
}
|
|
155660
|
+
/** 恢复路径:把 seq 对齐到库里已有的最大值(不改健康态)。 */
|
|
155661
|
+
resetSeq(seq) {
|
|
155662
|
+
this.seq = seq;
|
|
155663
|
+
}
|
|
155664
|
+
onSuccess() {
|
|
155665
|
+
this.opts.health?.markHealthy(this.opts.runId);
|
|
155666
|
+
if (this.failing) {
|
|
155667
|
+
this.failing = false;
|
|
155668
|
+
this.opts.onRecover?.();
|
|
155669
|
+
}
|
|
155670
|
+
}
|
|
155671
|
+
onFailure(err) {
|
|
155672
|
+
this.opts.health?.markUnhealthy(this.opts.runId);
|
|
155673
|
+
if (!this.failing) {
|
|
155674
|
+
this.failing = true;
|
|
155675
|
+
this.opts.onError?.(err);
|
|
155676
|
+
}
|
|
155677
|
+
}
|
|
155678
|
+
/**
|
|
155679
|
+
* 追加一批事件(seq 自动连续分配);**成功才推进 seq**。返回是否落库。
|
|
155680
|
+
* 幂等吸收(storage 层)保证:若失败其实是"提交成功但连接抖断",下次同 seq 重投会被吸收、不重复。
|
|
155681
|
+
*/
|
|
155682
|
+
async append(events) {
|
|
155683
|
+
if (events.length === 0) return true;
|
|
155684
|
+
const base = this.seq;
|
|
155685
|
+
const withSeq = events.map((e, i) => ({ ...e, seq: base + i + 1 }));
|
|
155686
|
+
try {
|
|
155687
|
+
await this.opts.store.appendEvents(this.opts.runId, withSeq);
|
|
155688
|
+
this.seq = base + events.length;
|
|
155689
|
+
this.onSuccess();
|
|
155690
|
+
return true;
|
|
155691
|
+
} catch (err) {
|
|
155692
|
+
this.onFailure(err);
|
|
155693
|
+
return false;
|
|
155694
|
+
}
|
|
155695
|
+
}
|
|
155696
|
+
/** 更新 run(心跳 lastProgressAt / 终态 / metadata 等);失败不熄灭事件通道。 */
|
|
155697
|
+
async update(patch) {
|
|
155698
|
+
try {
|
|
155699
|
+
await this.opts.store.updateRun(this.opts.runId, patch);
|
|
155700
|
+
this.onSuccess();
|
|
155701
|
+
return true;
|
|
155702
|
+
} catch (err) {
|
|
155703
|
+
this.onFailure(err);
|
|
155704
|
+
return false;
|
|
155705
|
+
}
|
|
155706
|
+
}
|
|
155707
|
+
};
|
|
155708
|
+
}
|
|
155709
|
+
});
|
|
155710
|
+
|
|
155423
155711
|
// ../server/src/domains/trace/sink.ts
|
|
155424
155712
|
function deriveMessage(payload) {
|
|
155425
155713
|
if (payload && typeof payload === "object") {
|
|
@@ -155429,11 +155717,10 @@ function deriveMessage(payload) {
|
|
|
155429
155717
|
}
|
|
155430
155718
|
return void 0;
|
|
155431
155719
|
}
|
|
155432
|
-
function trajectoryEventToRunEvent(e
|
|
155720
|
+
function trajectoryEventToRunEvent(e) {
|
|
155433
155721
|
const map = KIND_MAP[e.kind] ?? { eventType: "progress", stream: "runtime" };
|
|
155434
155722
|
const message = deriveMessage(e.payload);
|
|
155435
155723
|
return {
|
|
155436
|
-
seq,
|
|
155437
155724
|
eventType: map.eventType,
|
|
155438
155725
|
stream: map.stream,
|
|
155439
155726
|
...message !== void 0 ? { message } : {},
|
|
@@ -155512,6 +155799,7 @@ var KIND_MAP, MODEL_TEXT_LIMIT, TOOL_PREVIEW_LIMIT, PROGRESS_TOUCH_THROTTLE_MS,
|
|
|
155512
155799
|
var init_sink = __esm({
|
|
155513
155800
|
"../server/src/domains/trace/sink.ts"() {
|
|
155514
155801
|
"use strict";
|
|
155802
|
+
init_resilient_appender();
|
|
155515
155803
|
KIND_MAP = {
|
|
155516
155804
|
message: { eventType: "model.output.completed", stream: "model" },
|
|
155517
155805
|
thought: { eventType: "model.output.delta", stream: "model" },
|
|
@@ -155527,12 +155815,23 @@ var init_sink = __esm({
|
|
|
155527
155815
|
store;
|
|
155528
155816
|
runtimeKind;
|
|
155529
155817
|
onError;
|
|
155818
|
+
health;
|
|
155530
155819
|
sessions = /* @__PURE__ */ new Map();
|
|
155531
155820
|
constructor(opts) {
|
|
155532
155821
|
this.store = opts.store;
|
|
155533
155822
|
this.runtimeKind = opts.runtimeKind ?? "custom";
|
|
155534
155823
|
this.onError = opts.onError ?? (() => {
|
|
155535
155824
|
});
|
|
155825
|
+
this.health = opts.health;
|
|
155826
|
+
}
|
|
155827
|
+
/** 为一个 run 造事件通道 appender(seq 两道防线 + 健康度上报都收在这里)。 */
|
|
155828
|
+
makeAppender(runId) {
|
|
155829
|
+
return new ResilientTraceAppender({
|
|
155830
|
+
runId,
|
|
155831
|
+
store: this.store,
|
|
155832
|
+
...this.health ? { health: this.health } : {},
|
|
155833
|
+
onError: (err) => this.onError(err)
|
|
155834
|
+
});
|
|
155536
155835
|
}
|
|
155537
155836
|
runtimeKindFor(session) {
|
|
155538
155837
|
if (this.runtimeKind !== "auto") return this.runtimeKind;
|
|
@@ -155554,7 +155853,7 @@ var init_sink = __esm({
|
|
|
155554
155853
|
begin(session, _bundleFiles) {
|
|
155555
155854
|
const st = {
|
|
155556
155855
|
runId: session.runId,
|
|
155557
|
-
|
|
155856
|
+
appender: this.makeAppender(session.runId),
|
|
155558
155857
|
chain: Promise.resolve(),
|
|
155559
155858
|
openTools: /* @__PURE__ */ new Map(),
|
|
155560
155859
|
// runtimeSessionId:运行时自己的会话号(= 会话工作目录名,也是 --resume 的键)。落账后
|
|
@@ -155588,8 +155887,7 @@ var init_sink = __esm({
|
|
|
155588
155887
|
relation: "triggered_by",
|
|
155589
155888
|
createdAt: session.startedAt
|
|
155590
155889
|
});
|
|
155591
|
-
await
|
|
155592
|
-
seq: ++st.seq,
|
|
155890
|
+
await st.appender.append([{
|
|
155593
155891
|
eventType: "run.started",
|
|
155594
155892
|
stream: "runtime",
|
|
155595
155893
|
message: `${session.action} ${session.artifactId}`
|
|
@@ -155599,7 +155897,7 @@ var init_sink = __esm({
|
|
|
155599
155897
|
recover(session) {
|
|
155600
155898
|
const st = {
|
|
155601
155899
|
runId: session.runId,
|
|
155602
|
-
|
|
155900
|
+
appender: this.makeAppender(session.runId),
|
|
155603
155901
|
chain: Promise.resolve(),
|
|
155604
155902
|
openTools: /* @__PURE__ */ new Map(),
|
|
155605
155903
|
baseMetadata: { bundleManifest: session.bundleManifest, recovered: true },
|
|
@@ -155626,11 +155924,10 @@ var init_sink = __esm({
|
|
|
155626
155924
|
st.baseMetadata = { ...asMetadata(existing.metadata) ?? st.baseMetadata, recovered: true };
|
|
155627
155925
|
}
|
|
155628
155926
|
const events = await this.store.listEvents(session.runId, {});
|
|
155629
|
-
st.
|
|
155927
|
+
st.appender.resetSeq(events.reduce((max, event) => Math.max(max, event.seq), 0));
|
|
155630
155928
|
const recoveredAt = session.recoveredAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
155631
155929
|
const interruptedAt = session.interruptedAt ?? recoveredAt;
|
|
155632
|
-
await
|
|
155633
|
-
seq: ++st.seq,
|
|
155930
|
+
await st.appender.append([{
|
|
155634
155931
|
eventType: "progress",
|
|
155635
155932
|
stream: "system",
|
|
155636
155933
|
level: "warn",
|
|
@@ -155655,11 +155952,11 @@ var init_sink = __esm({
|
|
|
155655
155952
|
const ms = Date.parse(event.ts);
|
|
155656
155953
|
if (!Number.isNaN(ms) && ms - (st.lastProgressTouchMs ?? 0) >= PROGRESS_TOUCH_THROTTLE_MS) {
|
|
155657
155954
|
st.lastProgressTouchMs = ms;
|
|
155658
|
-
await
|
|
155955
|
+
await st.appender.update({ lastProgressAt: event.ts });
|
|
155659
155956
|
}
|
|
155660
155957
|
return;
|
|
155661
155958
|
}
|
|
155662
|
-
await
|
|
155959
|
+
await st.appender.append([trajectoryEventToRunEvent(event)]);
|
|
155663
155960
|
await this.materializeToolCall(st, event);
|
|
155664
155961
|
});
|
|
155665
155962
|
}
|
|
@@ -155710,8 +156007,7 @@ var init_sink = __esm({
|
|
|
155710
156007
|
const captured = this.sessions.get(sessionId);
|
|
155711
156008
|
this.enqueue(sessionId, async (st) => {
|
|
155712
156009
|
for (const ref2 of update.opRefs) {
|
|
155713
|
-
await
|
|
155714
|
-
seq: ++st.seq,
|
|
156010
|
+
await st.appender.append([{
|
|
155715
156011
|
eventType: "oplog.appended",
|
|
155716
156012
|
stream: "oasis",
|
|
155717
156013
|
message: ref2.kind,
|
|
@@ -155725,8 +156021,7 @@ var init_sink = __esm({
|
|
|
155725
156021
|
createdAt: update.exit.at
|
|
155726
156022
|
});
|
|
155727
156023
|
}
|
|
155728
|
-
await
|
|
155729
|
-
seq: ++st.seq,
|
|
156024
|
+
await st.appender.append([{
|
|
155730
156025
|
eventType: "run.finished",
|
|
155731
156026
|
stream: "runtime",
|
|
155732
156027
|
message: `exit code=${update.exit.code ?? "killed"} ops=${update.opRefs.length}`
|
|
@@ -155760,6 +156055,7 @@ var init_sink = __esm({
|
|
|
155760
156055
|
});
|
|
155761
156056
|
if (captured) captured.chain = captured.chain.finally(() => {
|
|
155762
156057
|
this.sessions.delete(sessionId);
|
|
156058
|
+
this.health?.forget(captured.runId);
|
|
155763
156059
|
});
|
|
155764
156060
|
}
|
|
155765
156061
|
};
|
|
@@ -155821,27 +156117,26 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155821
156117
|
live.emit(rest);
|
|
155822
156118
|
}
|
|
155823
156119
|
deps.register();
|
|
155824
|
-
|
|
155825
|
-
|
|
156120
|
+
const appender = new ResilientTraceAppender({
|
|
156121
|
+
runId: plan.runId,
|
|
156122
|
+
store: trace,
|
|
156123
|
+
...deps.traceHealth ? { health: deps.traceHealth } : {},
|
|
156124
|
+
onError: (err) => log3(`[chat-recovery] run ${plan.runId} trace \u5199\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u7184\u706D\uFF09: ${String(err)}`)
|
|
156125
|
+
});
|
|
155826
156126
|
let traceChain = trace.listEvents(plan.runId, {}).then((events) => {
|
|
155827
|
-
|
|
156127
|
+
appender.resetSeq(events.reduce((n, e) => Math.max(n, e.seq), 0));
|
|
155828
156128
|
}).catch((err) => {
|
|
155829
|
-
|
|
155830
|
-
log3(`[chat-recovery] run ${plan.runId} \u8BFB\u4E8B\u4EF6\u5931\u8D25
|
|
156129
|
+
deps.traceHealth?.markUnhealthy(plan.runId);
|
|
156130
|
+
log3(`[chat-recovery] run ${plan.runId} \u8BFB\u4E8B\u4EF6\u5931\u8D25: ${String(err)}`);
|
|
155831
156131
|
});
|
|
155832
156132
|
const enqueueTrace = (step) => {
|
|
155833
|
-
|
|
155834
|
-
|
|
155835
|
-
if (traceEnabled) await step();
|
|
155836
|
-
}).catch((err) => {
|
|
155837
|
-
traceEnabled = false;
|
|
155838
|
-
log3(`[chat-recovery] run ${plan.runId} trace \u7EED\u8D26\u5931\u8D25: ${String(err)}`);
|
|
156133
|
+
traceChain = traceChain.then(step).catch((err) => {
|
|
156134
|
+
log3(`[chat-recovery] run ${plan.runId} trace \u7EED\u8D26\u5F02\u5E38: ${String(err)}`);
|
|
155839
156135
|
});
|
|
155840
156136
|
};
|
|
155841
156137
|
const recoveredAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
155842
156138
|
enqueueTrace(async () => {
|
|
155843
|
-
await
|
|
155844
|
-
seq: ++traceSeq,
|
|
156139
|
+
await appender.append([{
|
|
155845
156140
|
eventType: "progress",
|
|
155846
156141
|
stream: "system",
|
|
155847
156142
|
level: "warn",
|
|
@@ -155865,11 +156160,11 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155865
156160
|
const ms = Date.parse(event.ts);
|
|
155866
156161
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
155867
156162
|
lastProgressTouchMs = ms;
|
|
155868
|
-
enqueueTrace(() =>
|
|
156163
|
+
enqueueTrace(() => appender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
155869
156164
|
}
|
|
155870
156165
|
return;
|
|
155871
156166
|
}
|
|
155872
|
-
enqueueTrace(() =>
|
|
156167
|
+
enqueueTrace(() => appender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
155873
156168
|
if (event.kind === "message" && sawTextOutput) return;
|
|
155874
156169
|
const part = chatPartFromTrajectoryEvent(event);
|
|
155875
156170
|
if (part) {
|
|
@@ -155950,14 +156245,13 @@ function wireRecoveredChatTurn(deps) {
|
|
|
155950
156245
|
live.finish(failed ? "error" : "done");
|
|
155951
156246
|
deps.unregister();
|
|
155952
156247
|
enqueueTrace(async () => {
|
|
155953
|
-
await
|
|
155954
|
-
seq: ++traceSeq,
|
|
156248
|
+
await appender.append([{
|
|
155955
156249
|
eventType: "run.finished",
|
|
155956
156250
|
stream: "runtime",
|
|
155957
156251
|
message: `exit code=${info.code ?? "killed"}`,
|
|
155958
156252
|
startedAt: finishedAt
|
|
155959
156253
|
}]);
|
|
155960
|
-
await
|
|
156254
|
+
await appender.update(runTerminalPatch(info, plan.startedAt, finishedAt));
|
|
155961
156255
|
if (info.usage && trace.updateUsageAggregates) {
|
|
155962
156256
|
const run = await trace.getRun(plan.runId);
|
|
155963
156257
|
if (run) void trace.updateUsageAggregates(run).catch(() => void 0);
|
|
@@ -156054,17 +156348,17 @@ async function reconcileChatExitFrame(deps) {
|
|
|
156054
156348
|
}).catch(() => void 0);
|
|
156055
156349
|
try {
|
|
156056
156350
|
const events = await deps.trace.listEvents(row.runId, {});
|
|
156057
|
-
|
|
156058
|
-
|
|
156059
|
-
...stash.frames.filter((frame) => frame.type === "event").map((frame) => frame.event).filter((event) => event.kind !== "system").map((event) => trajectoryEventToRunEvent(event
|
|
156351
|
+
const baseSeq = events.reduce((n, e) => Math.max(n, e.seq), 0);
|
|
156352
|
+
const seqless = [
|
|
156353
|
+
...stash.frames.filter((frame) => frame.type === "event").map((frame) => frame.event).filter((event) => event.kind !== "system").map((event) => trajectoryEventToRunEvent(event)),
|
|
156060
156354
|
{
|
|
156061
|
-
seq: ++traceSeq,
|
|
156062
156355
|
eventType: "run.finished",
|
|
156063
156356
|
stream: "runtime",
|
|
156064
156357
|
message: `exit code=${info.code ?? "killed"}\uFF08serve \u505C\u673A\u7A97\u53E3\u5185\u7ED3\u675F\uFF0C\u8282\u70B9 outbox \u91CD\u53D1\u5BF9\u8D26\uFF09`,
|
|
156065
156358
|
startedAt: finishedAt
|
|
156066
156359
|
}
|
|
156067
|
-
]
|
|
156360
|
+
];
|
|
156361
|
+
await deps.trace.appendEvents(row.runId, seqless.map((e, i) => ({ ...e, seq: baseSeq + i + 1 })));
|
|
156068
156362
|
await deps.trace.updateRun(row.runId, runTerminalPatch(info, run.startedAt, finishedAt));
|
|
156069
156363
|
if (info.usage && deps.trace.updateUsageAggregates) {
|
|
156070
156364
|
const fresh = await deps.trace.getRun(row.runId);
|
|
@@ -156085,6 +156379,7 @@ var init_chat_recovery = __esm({
|
|
|
156085
156379
|
import_node_crypto20 = require("node:crypto");
|
|
156086
156380
|
init_chat_parts();
|
|
156087
156381
|
init_sink();
|
|
156382
|
+
init_resilient_appender();
|
|
156088
156383
|
asObj3 = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
156089
156384
|
partsOf = (parts) => Array.isArray(parts) ? parts.filter((p2) => p2 && typeof p2 === "object" && typeof p2.type === "string") : [];
|
|
156090
156385
|
maxPartSeq = (parts) => parts.reduce((n, p2) => Math.max(n, typeof p2.seq === "number" ? p2.seq : 0), 0);
|
|
@@ -156678,6 +156973,24 @@ var init_skill_fetcher = __esm({
|
|
|
156678
156973
|
});
|
|
156679
156974
|
|
|
156680
156975
|
// ../server/src/domains/actors/service.ts
|
|
156976
|
+
function applyRefDelivery(env, entries, warn = (m2) => console.warn(m2)) {
|
|
156977
|
+
for (const e of entries) {
|
|
156978
|
+
if (!(e.key in env)) continue;
|
|
156979
|
+
const mode = e.deliveryMode;
|
|
156980
|
+
switch (mode) {
|
|
156981
|
+
case "env":
|
|
156982
|
+
break;
|
|
156983
|
+
// 非敏感:明文保持不动
|
|
156984
|
+
case "ref":
|
|
156985
|
+
env[e.key] = makeVarRef(e.key);
|
|
156986
|
+
break;
|
|
156987
|
+
default:
|
|
156988
|
+
delete env[e.key];
|
|
156989
|
+
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`);
|
|
156990
|
+
break;
|
|
156991
|
+
}
|
|
156992
|
+
}
|
|
156993
|
+
}
|
|
156681
156994
|
function computeEffectiveEntries(config2, connections, connectors) {
|
|
156682
156995
|
const globalConnected = new Set(connectors.filter((c) => c.status === "connected").map((c) => c.id));
|
|
156683
156996
|
const record6 = new Map(connections.map((c) => [c.connectorId, c.enabled]));
|
|
@@ -156709,6 +157022,7 @@ var init_service3 = __esm({
|
|
|
156709
157022
|
init_skill_fetcher();
|
|
156710
157023
|
init_identity();
|
|
156711
157024
|
init_src5();
|
|
157025
|
+
init_src();
|
|
156712
157026
|
REDACTED_MARKER = "[REDACTED]";
|
|
156713
157027
|
ActorsService = class {
|
|
156714
157028
|
constructor(opts) {
|
|
@@ -157362,8 +157676,11 @@ ${input.description}
|
|
|
157362
157676
|
key: v2.key,
|
|
157363
157677
|
scope: v2.scope,
|
|
157364
157678
|
...v2.actorId !== void 0 ? { actorId: v2.actorId } : {},
|
|
157679
|
+
...v2.projectId !== void 0 ? { projectId: v2.projectId } : {},
|
|
157365
157680
|
...v2.connectorId !== void 0 ? { connectorId: v2.connectorId } : {},
|
|
157366
157681
|
...v2.overrides !== void 0 ? { overrides: v2.overrides } : {},
|
|
157682
|
+
// 缺省 "env"(存量行为不变,敏感项需显式选 "ref",ADR §4.4 / 待确认 3)
|
|
157683
|
+
deliveryMode: v2.deliveryMode ?? "env",
|
|
157367
157684
|
valueEncrypted: v2.encrypted === false ? `plain:${v2.value}` : this.encrypt(v2.value),
|
|
157368
157685
|
updatedAt: this.now()
|
|
157369
157686
|
});
|
|
@@ -157399,8 +157716,11 @@ ${input.description}
|
|
|
157399
157716
|
key: r.key,
|
|
157400
157717
|
scope: r.scope,
|
|
157401
157718
|
...r.actorId !== void 0 ? { actorId: r.actorId } : {},
|
|
157719
|
+
...r.projectId !== void 0 ? { projectId: r.projectId } : {},
|
|
157402
157720
|
...r.connectorId !== void 0 ? { connectorId: r.connectorId } : {},
|
|
157403
157721
|
...r.overrides !== void 0 ? { overrides: r.overrides } : {},
|
|
157722
|
+
deliveryMode: r.deliveryMode ?? "env",
|
|
157723
|
+
// 缺省视为 env(ADR §4.4;存量行读侧统一回填)
|
|
157404
157724
|
encrypted: !isPlain,
|
|
157405
157725
|
maskedValue: isPlain ? r.valueEncrypted.slice(6) : mask(this.decrypt(r.valueEncrypted)),
|
|
157406
157726
|
updatedAt: r.updatedAt
|
|
@@ -157424,8 +157744,13 @@ ${input.description}
|
|
|
157424
157744
|
}
|
|
157425
157745
|
return this.revealVariable(key, void 0);
|
|
157426
157746
|
}
|
|
157427
|
-
deleteVariable(key, actorId) {
|
|
157428
|
-
return this.opts.store.deleteVariable(key, actorId);
|
|
157747
|
+
deleteVariable(key, actorId, scoping) {
|
|
157748
|
+
return this.opts.store.deleteVariable(key, actorId, scoping);
|
|
157749
|
+
}
|
|
157750
|
+
/** 该 key 是否在**任一**作用域存在(reveal 判权失败时区分 not_found / no_permission,仅 server 侧审计用;§4.5.2)。 */
|
|
157751
|
+
async hasVariableKey(key) {
|
|
157752
|
+
const rows = await this.opts.store.listVariables();
|
|
157753
|
+
return rows.some((r) => r.key === key);
|
|
157429
157754
|
}
|
|
157430
157755
|
async resolveActorEnv(actorId) {
|
|
157431
157756
|
const cfg = await this.opts.store.latestConfig(actorId);
|
|
@@ -157455,6 +157780,64 @@ ${input.description}
|
|
|
157455
157780
|
}
|
|
157456
157781
|
return env;
|
|
157457
157782
|
}
|
|
157783
|
+
/** 密文 → 明文(与 resolveActorEnv 内联的 decode 同规则:plain: 前缀直读,否则 AES 解密)。 */
|
|
157784
|
+
decodeCiphertext(ct) {
|
|
157785
|
+
return ct.startsWith("plain:") ? ct.slice(6) : this.decrypt(ct);
|
|
157786
|
+
}
|
|
157787
|
+
/**
|
|
157788
|
+
* ADR 凭据保险库 §4.3 / ADR 0125:按「项目」解析 project 变量为明文条目(含 deliveryMode)。
|
|
157789
|
+
* store 未实现 resolveProjectVariables(旧实现)时返回空——调用方跳过 project 层。
|
|
157790
|
+
*/
|
|
157791
|
+
async resolveProjectVariables(projectId) {
|
|
157792
|
+
if (!this.opts.store.resolveProjectVariables) return [];
|
|
157793
|
+
const rows = await this.opts.store.resolveProjectVariables(projectId);
|
|
157794
|
+
return rows.map((r) => ({ key: r.key, value: this.decodeCiphertext(r.valueEncrypted), deliveryMode: r.deliveryMode ?? "env" }));
|
|
157795
|
+
}
|
|
157796
|
+
/**
|
|
157797
|
+
* ADR 凭据保险库 §4.3 / ADR 0125:派单/reveal 用的**合并后**变量条目(明文 + deliveryMode)。
|
|
157798
|
+
* 优先级低→高:global < project < personal(同 key 时高层覆盖低层,personal 最优先)。
|
|
157799
|
+
* 连接器门禁与 resolveActorEnv 同源(未启用的连接器变量不注入)。
|
|
157800
|
+
* - `opts.projectId` 给出时才叠加 project 层;缺省 = 只有 personal+global(存量行为)。
|
|
157801
|
+
*/
|
|
157802
|
+
async resolveActorProvisionEntries(actorId, opts) {
|
|
157803
|
+
const cfg = await this.opts.store.latestConfig(actorId);
|
|
157804
|
+
const enabledConnectors = await this.effectiveEnabledConnectors(actorId, cfg);
|
|
157805
|
+
if (opts?.refreshConnectors !== false) {
|
|
157806
|
+
await refreshEnabledConnectorCredentials(
|
|
157807
|
+
this,
|
|
157808
|
+
createAllConnectors(),
|
|
157809
|
+
actorId,
|
|
157810
|
+
(slug6) => enabledConnectors.has(slug6)
|
|
157811
|
+
);
|
|
157812
|
+
}
|
|
157813
|
+
const rows = await this.opts.store.listVariables(actorId);
|
|
157814
|
+
const projectRows = opts?.projectId && this.opts.store.resolveProjectVariables ? await this.opts.store.resolveProjectVariables(opts.projectId) : [];
|
|
157815
|
+
const merged = /* @__PURE__ */ new Map();
|
|
157816
|
+
const gated = (row) => !row.connectorId || enabledConnectors.has(row.connectorId);
|
|
157817
|
+
const put = (row) => {
|
|
157818
|
+
if (!gated(row)) return;
|
|
157819
|
+
merged.set(row.key, { key: row.key, value: this.decodeCiphertext(row.valueEncrypted), deliveryMode: row.deliveryMode ?? "env" });
|
|
157820
|
+
};
|
|
157821
|
+
for (const row of rows) {
|
|
157822
|
+
if (row.scope === "global" && !row.actorId) put(row);
|
|
157823
|
+
}
|
|
157824
|
+
for (const row of projectRows) {
|
|
157825
|
+
if (row.scope === "project") put(row);
|
|
157826
|
+
}
|
|
157827
|
+
for (const row of rows) {
|
|
157828
|
+
if (row.scope === "personal" && (!row.actorId || row.actorId === actorId)) put(row);
|
|
157829
|
+
}
|
|
157830
|
+
return [...merged.values()];
|
|
157831
|
+
}
|
|
157832
|
+
/**
|
|
157833
|
+
* ADR 凭据保险库 §4.5.1:reveal 的判权即「能否被解析」——该 key 通过 §4.3 合并顺序对本 caller
|
|
157834
|
+
* 能得出值即可读,返回明文;否则返回 null(缺 key / 无权,统一由路由映射成 403,不区分)。
|
|
157835
|
+
*/
|
|
157836
|
+
async resolveRevealValue(actorId, key, opts) {
|
|
157837
|
+
const entries = await this.resolveActorProvisionEntries(actorId, { ...opts, refreshConnectors: false });
|
|
157838
|
+
const hit = entries.find((e) => e.key === key);
|
|
157839
|
+
return hit ? { value: hit.value } : null;
|
|
157840
|
+
}
|
|
157458
157841
|
encrypt(plain) {
|
|
157459
157842
|
const iv = (0, import_node_crypto22.randomBytes)(12);
|
|
157460
157843
|
const cipher = (0, import_node_crypto22.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
|
|
@@ -158463,7 +158846,7 @@ var init_skill_materializer = __esm({
|
|
|
158463
158846
|
|
|
158464
158847
|
// ../server/src/governance/connector-skills.ts
|
|
158465
158848
|
function connectorSkillsDir(dataDir, connectorId) {
|
|
158466
|
-
return (0,
|
|
158849
|
+
return (0, import_node_path14.join)(dataDir, "connector-skills", connectorId);
|
|
158467
158850
|
}
|
|
158468
158851
|
function parseConnectorSkillId(id) {
|
|
158469
158852
|
if (!id.startsWith("connector:")) return null;
|
|
@@ -158473,17 +158856,17 @@ function parseConnectorSkillId(id) {
|
|
|
158473
158856
|
return { connectorId: rest.slice(0, i), slug: rest.slice(i + 1) };
|
|
158474
158857
|
}
|
|
158475
158858
|
async function collect(root, dir, out) {
|
|
158476
|
-
for (const e of await (0,
|
|
158477
|
-
const abs = (0,
|
|
158859
|
+
for (const e of await (0, import_promises8.readdir)(dir, { withFileTypes: true })) {
|
|
158860
|
+
const abs = (0, import_node_path14.join)(dir, e.name);
|
|
158478
158861
|
if (e.isDirectory()) await collect(root, abs, out);
|
|
158479
|
-
else if (e.isFile()) out[(0,
|
|
158862
|
+
else if (e.isFile()) out[(0, import_node_path14.relative)(root, abs).split(/[\\/]/).join("/")] = await (0, import_promises8.readFile)(abs, "utf8");
|
|
158480
158863
|
}
|
|
158481
158864
|
}
|
|
158482
158865
|
async function readLocalPack(dataDir, connectorId) {
|
|
158483
158866
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158484
158867
|
let slugs;
|
|
158485
158868
|
try {
|
|
158486
|
-
slugs = (await (0,
|
|
158869
|
+
slugs = (await (0, import_promises8.readdir)(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
158487
158870
|
} catch {
|
|
158488
158871
|
return [];
|
|
158489
158872
|
}
|
|
@@ -158491,7 +158874,7 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158491
158874
|
for (const slug6 of slugs) {
|
|
158492
158875
|
const files = {};
|
|
158493
158876
|
try {
|
|
158494
|
-
await collect((0,
|
|
158877
|
+
await collect((0, import_node_path14.join)(root, slug6), (0, import_node_path14.join)(root, slug6), files);
|
|
158495
158878
|
} catch {
|
|
158496
158879
|
continue;
|
|
158497
158880
|
}
|
|
@@ -158507,17 +158890,17 @@ async function readLocalPack(dataDir, connectorId) {
|
|
|
158507
158890
|
async function writePack(dataDir, connectorId, pack) {
|
|
158508
158891
|
const root = connectorSkillsDir(dataDir, connectorId);
|
|
158509
158892
|
const tmp = `${root}.tmp`;
|
|
158510
|
-
await (0,
|
|
158893
|
+
await (0, import_promises8.rm)(tmp, { recursive: true, force: true });
|
|
158511
158894
|
for (const s2 of pack) {
|
|
158512
158895
|
for (const [rel, content] of Object.entries(s2.files)) {
|
|
158513
|
-
const abs = (0,
|
|
158514
|
-
await (0,
|
|
158515
|
-
await (0,
|
|
158896
|
+
const abs = (0, import_node_path14.join)(tmp, s2.slug, rel);
|
|
158897
|
+
await (0, import_promises8.mkdir)((0, import_node_path14.dirname)(abs), { recursive: true });
|
|
158898
|
+
await (0, import_promises8.writeFile)(abs, content, "utf8");
|
|
158516
158899
|
}
|
|
158517
158900
|
}
|
|
158518
|
-
await (0,
|
|
158519
|
-
await (0,
|
|
158520
|
-
await (0,
|
|
158901
|
+
await (0, import_promises8.rm)(root, { recursive: true, force: true });
|
|
158902
|
+
await (0, import_promises8.mkdir)((0, import_node_path14.dirname)(root), { recursive: true });
|
|
158903
|
+
await (0, import_promises8.rename)(tmp, root);
|
|
158521
158904
|
}
|
|
158522
158905
|
function packMatches(local, remote) {
|
|
158523
158906
|
if (local.length !== remote.length) return false;
|
|
@@ -158544,18 +158927,21 @@ async function syncConnectorSkills(args) {
|
|
|
158544
158927
|
log3(`[connector-skills] ${args.connectorId}\uFF1A\u5DF2\u4ECE\u5382\u5546\u540C\u6B65 ${fresh.length} \u4E2A\u6280\u80FD`);
|
|
158545
158928
|
return { skills: fresh, outcome: "fetched" };
|
|
158546
158929
|
}
|
|
158547
|
-
var
|
|
158930
|
+
var import_promises8, import_node_path14, toId;
|
|
158548
158931
|
var init_connector_skills = __esm({
|
|
158549
158932
|
"../server/src/governance/connector-skills.ts"() {
|
|
158550
158933
|
"use strict";
|
|
158551
|
-
|
|
158552
|
-
|
|
158934
|
+
import_promises8 = require("node:fs/promises");
|
|
158935
|
+
import_node_path14 = require("node:path");
|
|
158553
158936
|
init_src5();
|
|
158554
158937
|
toId = (connectorId, slug6) => `connector:${connectorId}/${slug6}`;
|
|
158555
158938
|
}
|
|
158556
158939
|
});
|
|
158557
158940
|
|
|
158558
158941
|
// ../server/src/domains/actors/routes.ts
|
|
158942
|
+
function isKnownRevealSource(source) {
|
|
158943
|
+
return CREDENTIAL_REVEAL_SOURCES.has(source) || source.startsWith("agent-skill:");
|
|
158944
|
+
}
|
|
158559
158945
|
function positionsFromPayload(body) {
|
|
158560
158946
|
if (!body) return void 0;
|
|
158561
158947
|
if (Object.prototype.hasOwnProperty.call(body, "roles")) {
|
|
@@ -158588,6 +158974,8 @@ function actorApiRecord(actor) {
|
|
|
158588
158974
|
}
|
|
158589
158975
|
function actorsDomain(opts) {
|
|
158590
158976
|
const { resolveCtx } = opts;
|
|
158977
|
+
const revealLimits = opts.credentialRevealLimits ?? { perSession: 200, perSessionPerKey: 20 };
|
|
158978
|
+
const revealLimiter = new RevealRateLimiter(revealLimits.perSession, revealLimits.perSessionPerKey);
|
|
158591
158979
|
return (router) => {
|
|
158592
158980
|
router.get("/api/actors", async (req) => {
|
|
158593
158981
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
@@ -158827,11 +159215,23 @@ function actorsDomain(opts) {
|
|
|
158827
159215
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158828
159216
|
const b2 = req.body;
|
|
158829
159217
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159218
|
+
const scope = b2.scope ?? "global";
|
|
159219
|
+
if (scope === "project" && !b2.projectId) {
|
|
159220
|
+
throw new ApiError(400, "BAD_REQUEST", "scope=project \u5FC5\u987B\u63D0\u4F9B projectId");
|
|
159221
|
+
}
|
|
159222
|
+
if (scope === "project" && opts.projectExists && !await opts.projectExists(b2.projectId)) {
|
|
159223
|
+
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`);
|
|
159224
|
+
}
|
|
159225
|
+
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
|
|
159226
|
+
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
|
|
159227
|
+
}
|
|
158830
159228
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158831
159229
|
await service.putVariable({
|
|
158832
159230
|
key: b2.key,
|
|
158833
159231
|
value: b2.value,
|
|
158834
|
-
scope
|
|
159232
|
+
scope,
|
|
159233
|
+
...scope === "project" ? { projectId: b2.projectId } : {},
|
|
159234
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158835
159235
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158836
159236
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158837
159237
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158840,7 +159240,12 @@ function actorsDomain(opts) {
|
|
|
158840
159240
|
});
|
|
158841
159241
|
router.delete("/api/variables/:key", async (req) => {
|
|
158842
159242
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158843
|
-
|
|
159243
|
+
const projectId = req.query.get("projectId") ?? void 0;
|
|
159244
|
+
await service.deleteVariable(
|
|
159245
|
+
req.params.key,
|
|
159246
|
+
void 0,
|
|
159247
|
+
projectId ? { projectId } : void 0
|
|
159248
|
+
);
|
|
158844
159249
|
return { status: 200, body: { ok: true } };
|
|
158845
159250
|
});
|
|
158846
159251
|
router.get("/api/actors/:id/variables", async (req) => {
|
|
@@ -158852,6 +159257,9 @@ function actorsDomain(opts) {
|
|
|
158852
159257
|
const actorId = req.params.id;
|
|
158853
159258
|
const b2 = req.body;
|
|
158854
159259
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159260
|
+
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
|
|
159261
|
+
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
|
|
159262
|
+
}
|
|
158855
159263
|
if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
|
|
158856
159264
|
if (b2.connectorId === void 0) {
|
|
158857
159265
|
const existing = await service.listVariables(actorId);
|
|
@@ -158869,6 +159277,7 @@ function actorsDomain(opts) {
|
|
|
158869
159277
|
value: b2.value,
|
|
158870
159278
|
actorId,
|
|
158871
159279
|
scope: "personal",
|
|
159280
|
+
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
158872
159281
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
158873
159282
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
158874
159283
|
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
@@ -158880,6 +159289,51 @@ function actorsDomain(opts) {
|
|
|
158880
159289
|
await service.deleteVariable(req.params.key, req.params.id);
|
|
158881
159290
|
return { status: 200, body: { ok: true } };
|
|
158882
159291
|
});
|
|
159292
|
+
router.post("/api/variables/reveal", async (req) => {
|
|
159293
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
159294
|
+
const b2 = req.body;
|
|
159295
|
+
const rawKey = typeof b2?.key === "string" ? b2.key.trim() : "";
|
|
159296
|
+
if (!rawKey) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
159297
|
+
const key = parseVarRef(rawKey) ?? rawKey;
|
|
159298
|
+
const source = typeof b2?.source === "string" && b2.source.trim() || "agent-cli";
|
|
159299
|
+
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`);
|
|
159300
|
+
const actor = req.auth.actor;
|
|
159301
|
+
const artifactId = req.auth.dispatch?.artifactId;
|
|
159302
|
+
const sessionId = req.auth.dispatch?.sessionId;
|
|
159303
|
+
const now = Date.now();
|
|
159304
|
+
const timestamp = new Date(now).toISOString();
|
|
159305
|
+
const sessionKey = sessionId ?? `${actor}::${artifactId ?? "no-artifact"}`;
|
|
159306
|
+
const dispatchFields = { ...sessionId ? { sessionId } : {}, ...artifactId ? { artifactId } : {} };
|
|
159307
|
+
const throttled = revealLimiter.check(sessionKey, key, now);
|
|
159308
|
+
if (throttled) {
|
|
159309
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_throttled", actor, variableKey: key, source, timestamp, scope: throttled, ...dispatchFields });
|
|
159310
|
+
return { status: 429, body: { code: "throttled", key, scope: throttled } };
|
|
159311
|
+
}
|
|
159312
|
+
const scope = artifactId && opts.resolveDispatchScope ? await opts.resolveDispatchScope(artifactId) : {};
|
|
159313
|
+
const resolved = await service.resolveRevealValue(actor, key, scope);
|
|
159314
|
+
if (!resolved) {
|
|
159315
|
+
const reason = await service.hasVariableKey(key) ? "no_permission" : "not_found";
|
|
159316
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_denied", actor, variableKey: key, source, timestamp, reason, ...dispatchFields });
|
|
159317
|
+
return { status: 403, body: { code: "denied", key } };
|
|
159318
|
+
}
|
|
159319
|
+
await opts.credentialAudit?.({ kind: "credential_reveal", actor, variableKey: key, source, timestamp, ...dispatchFields });
|
|
159320
|
+
return { status: 200, body: { value: resolved.value } };
|
|
159321
|
+
});
|
|
159322
|
+
router.get("/api/variables/reveal-audit", async (req) => {
|
|
159323
|
+
if (!opts.readCredentialAudit) return { status: 501, body: { error: "credential audit reader \u672A\u914D\u7F6E" } };
|
|
159324
|
+
const actor = req.query.get("actor") ?? void 0;
|
|
159325
|
+
const key = req.query.get("key") ?? void 0;
|
|
159326
|
+
const kind = req.query.get("kind") ?? void 0;
|
|
159327
|
+
const limitRaw = req.query.get("limit");
|
|
159328
|
+
const limit = limitRaw ? Math.min(Math.max(parseInt(limitRaw, 10) || 50, 1), 500) : 50;
|
|
159329
|
+
const items = await opts.readCredentialAudit({
|
|
159330
|
+
...actor ? { actor } : {},
|
|
159331
|
+
...key ? { key } : {},
|
|
159332
|
+
...kind ? { kind } : {},
|
|
159333
|
+
limit
|
|
159334
|
+
});
|
|
159335
|
+
return { status: 200, body: { items } };
|
|
159336
|
+
});
|
|
158883
159337
|
router.get("/api/skills/market", async (req) => {
|
|
158884
159338
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
158885
159339
|
const [catalog, installed] = await Promise.all([
|
|
@@ -159038,6 +159492,18 @@ function actorsDomain(opts) {
|
|
|
159038
159492
|
const results = await opts.refreshConnectorSkills();
|
|
159039
159493
|
return { status: 200, body: { results } };
|
|
159040
159494
|
});
|
|
159495
|
+
router.get("/api/connector-credentials", async (req) => {
|
|
159496
|
+
const { service } = await resolveCtx(req.auth.companyId);
|
|
159497
|
+
const actorId = req.auth.actor;
|
|
159498
|
+
const entries = await service.resolveActorProvisionEntries(actorId);
|
|
159499
|
+
const vars = {};
|
|
159500
|
+
for (const e of entries) vars[e.key] = e.value;
|
|
159501
|
+
const connectorCreds = collectAllConnectorCredentials({
|
|
159502
|
+
vars,
|
|
159503
|
+
actorName: vars["GIT_AUTHOR_NAME"] ?? actorId.split(":").pop() ?? "oasis-agent"
|
|
159504
|
+
});
|
|
159505
|
+
return { status: 200, body: { connectorCreds } };
|
|
159506
|
+
});
|
|
159041
159507
|
router.get("/api/skill-cache/manifest", async (req) => {
|
|
159042
159508
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
159043
159509
|
const builtins = opts.getBuiltinSkills?.() ?? [];
|
|
@@ -159316,12 +159782,15 @@ function actorsDomain(opts) {
|
|
|
159316
159782
|
});
|
|
159317
159783
|
};
|
|
159318
159784
|
}
|
|
159785
|
+
var CREDENTIAL_REVEAL_SOURCES, RevealRateLimiter;
|
|
159319
159786
|
var init_routes = __esm({
|
|
159320
159787
|
"../server/src/domains/actors/routes.ts"() {
|
|
159321
159788
|
"use strict";
|
|
159322
159789
|
init_src();
|
|
159323
159790
|
init_src2();
|
|
159324
159791
|
init_router();
|
|
159792
|
+
init_src();
|
|
159793
|
+
init_src5();
|
|
159325
159794
|
init_memory();
|
|
159326
159795
|
init_skill_fetcher();
|
|
159327
159796
|
init_stats();
|
|
@@ -159330,6 +159799,44 @@ var init_routes = __esm({
|
|
|
159330
159799
|
init_image_upload();
|
|
159331
159800
|
init_skill_materializer();
|
|
159332
159801
|
init_connector_skills();
|
|
159802
|
+
CREDENTIAL_REVEAL_SOURCES = /* @__PURE__ */ new Set(["agent-cli", "smoke-test", "oasis-internal"]);
|
|
159803
|
+
RevealRateLimiter = class {
|
|
159804
|
+
constructor(perSession, perSessionPerKey, ttlMs = 2 * 60 * 6e4) {
|
|
159805
|
+
this.perSession = perSession;
|
|
159806
|
+
this.perSessionPerKey = perSessionPerKey;
|
|
159807
|
+
this.ttlMs = ttlMs;
|
|
159808
|
+
}
|
|
159809
|
+
sessionCounts = /* @__PURE__ */ new Map();
|
|
159810
|
+
sessionKeyCounts = /* @__PURE__ */ new Map();
|
|
159811
|
+
/** 记一次尝试;返回命中的限流档(若超限)或 null(放行)。 */
|
|
159812
|
+
check(sessionKey, varKey, now) {
|
|
159813
|
+
this.prune(now);
|
|
159814
|
+
const sk = `${sessionKey}::${varKey}`;
|
|
159815
|
+
const s2 = this.sessionCounts.get(sessionKey) ?? { count: 0, last: now };
|
|
159816
|
+
const k2 = this.sessionKeyCounts.get(sk) ?? { count: 0, last: now };
|
|
159817
|
+
if (k2.count >= this.perSessionPerKey) {
|
|
159818
|
+
k2.last = now;
|
|
159819
|
+
this.sessionKeyCounts.set(sk, k2);
|
|
159820
|
+
return "session_key";
|
|
159821
|
+
}
|
|
159822
|
+
if (s2.count >= this.perSession) {
|
|
159823
|
+
s2.last = now;
|
|
159824
|
+
this.sessionCounts.set(sessionKey, s2);
|
|
159825
|
+
return "session";
|
|
159826
|
+
}
|
|
159827
|
+
s2.count += 1;
|
|
159828
|
+
s2.last = now;
|
|
159829
|
+
this.sessionCounts.set(sessionKey, s2);
|
|
159830
|
+
k2.count += 1;
|
|
159831
|
+
k2.last = now;
|
|
159832
|
+
this.sessionKeyCounts.set(sk, k2);
|
|
159833
|
+
return null;
|
|
159834
|
+
}
|
|
159835
|
+
prune(now) {
|
|
159836
|
+
for (const [key, v2] of this.sessionCounts) if (now - v2.last > this.ttlMs) this.sessionCounts.delete(key);
|
|
159837
|
+
for (const [key, v2] of this.sessionKeyCounts) if (now - v2.last > this.ttlMs) this.sessionKeyCounts.delete(key);
|
|
159838
|
+
}
|
|
159839
|
+
};
|
|
159333
159840
|
}
|
|
159334
159841
|
});
|
|
159335
159842
|
|
|
@@ -159428,7 +159935,7 @@ function createActorsDomain(opts) {
|
|
|
159428
159935
|
return {
|
|
159429
159936
|
service: defaultCtx.service,
|
|
159430
159937
|
resolveCtx,
|
|
159431
|
-
register: actorsDomain({ resolveCtx, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {} })
|
|
159938
|
+
register: actorsDomain({ resolveCtx, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {}, ...opts.getConnectorSkills ? { getConnectorSkills: opts.getConnectorSkills } : {}, ...opts.refreshConnectorSkills ? { refreshConnectorSkills: opts.refreshConnectorSkills } : {}, ...opts.memory ? { memory: opts.memory } : {}, ...opts.resolveDispatchScope ? { resolveDispatchScope: opts.resolveDispatchScope } : {}, ...opts.projectExists ? { projectExists: opts.projectExists } : {}, ...opts.credentialAudit ? { credentialAudit: opts.credentialAudit } : {}, ...opts.readCredentialAudit ? { readCredentialAudit: opts.readCredentialAudit } : {}, ...opts.credentialRevealLimits ? { credentialRevealLimits: opts.credentialRevealLimits } : {} })
|
|
159432
159939
|
};
|
|
159433
159940
|
}
|
|
159434
159941
|
var import_node_crypto24;
|
|
@@ -161857,10 +162364,10 @@ function nodesDomain(deps) {
|
|
|
161857
162364
|
}
|
|
161858
162365
|
}
|
|
161859
162366
|
try {
|
|
161860
|
-
const here = (0,
|
|
162367
|
+
const here = (0, import_node_path15.dirname)((0, import_node_url4.fileURLToPath)(__esm_import_meta_url));
|
|
161861
162368
|
for (const rel of ["../../../../node-daemon/package.json", "../../../../../node-daemon/package.json"]) {
|
|
161862
162369
|
try {
|
|
161863
|
-
const raw = (0, import_node_fs11.readFileSync)((0,
|
|
162370
|
+
const raw = (0, import_node_fs11.readFileSync)((0, import_node_path15.resolve)(here, rel), "utf8");
|
|
161864
162371
|
const pkg = JSON.parse(raw);
|
|
161865
162372
|
if (pkg.version) return { version: pkg.version, source: "monorepo" };
|
|
161866
162373
|
} catch {
|
|
@@ -162172,14 +162679,14 @@ function nodesDomain(deps) {
|
|
|
162172
162679
|
});
|
|
162173
162680
|
};
|
|
162174
162681
|
}
|
|
162175
|
-
var import_node_crypto26, import_node_fs11, import_node_url4,
|
|
162682
|
+
var import_node_crypto26, import_node_fs11, import_node_url4, import_node_path15;
|
|
162176
162683
|
var init_routes5 = __esm({
|
|
162177
162684
|
"../server/src/domains/nodes/routes.ts"() {
|
|
162178
162685
|
"use strict";
|
|
162179
162686
|
import_node_crypto26 = require("node:crypto");
|
|
162180
162687
|
import_node_fs11 = require("node:fs");
|
|
162181
162688
|
import_node_url4 = require("node:url");
|
|
162182
|
-
|
|
162689
|
+
import_node_path15 = require("node:path");
|
|
162183
162690
|
init_src4();
|
|
162184
162691
|
init_connect_script();
|
|
162185
162692
|
init_node_health();
|
|
@@ -163336,6 +163843,7 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163336
163843
|
const runtimeEmployees = /* @__PURE__ */ new Map();
|
|
163337
163844
|
const runtimeInstanceKind = /* @__PURE__ */ new Map();
|
|
163338
163845
|
const runtimeHostnames = input.runtimeHostnames ?? /* @__PURE__ */ new Map();
|
|
163846
|
+
const runtimeNodeNames = input.runtimeNodeNames ?? /* @__PURE__ */ new Map();
|
|
163339
163847
|
for (const run of input.runs) {
|
|
163340
163848
|
const usage = usageOf(run);
|
|
163341
163849
|
if (!usage) {
|
|
@@ -163466,11 +163974,27 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163466
163974
|
(e) => e.share,
|
|
163467
163975
|
(e, s2) => ({ ...e, share: s2 })
|
|
163468
163976
|
);
|
|
163977
|
+
function parseNodeId(rtKey) {
|
|
163978
|
+
const parts = rtKey.split(":");
|
|
163979
|
+
if (parts.length >= 3 && parts[0] === "runtime") return parts[1];
|
|
163980
|
+
return "";
|
|
163981
|
+
}
|
|
163982
|
+
function resolveDisplayName(rtKey, kind) {
|
|
163983
|
+
const nodeId = parseNodeId(rtKey);
|
|
163984
|
+
if (nodeId) {
|
|
163985
|
+
const name = runtimeNodeNames.get(nodeId);
|
|
163986
|
+
if (name) return name;
|
|
163987
|
+
}
|
|
163988
|
+
const h = runtimeHostnames.get(rtKey);
|
|
163989
|
+
if (h) return h;
|
|
163990
|
+
if (nodeId) return nodeId;
|
|
163991
|
+
return kind;
|
|
163992
|
+
}
|
|
163469
163993
|
function resolveHostname(rtKey, kind) {
|
|
163470
163994
|
const h = runtimeHostnames.get(rtKey);
|
|
163471
163995
|
if (h) return h;
|
|
163472
|
-
const
|
|
163473
|
-
if (
|
|
163996
|
+
const nodeId = parseNodeId(rtKey);
|
|
163997
|
+
if (nodeId) return nodeId;
|
|
163474
163998
|
return kind;
|
|
163475
163999
|
}
|
|
163476
164000
|
const runtimeRows = normalizeShares(
|
|
@@ -163498,6 +164022,8 @@ function buildOrganizationUsageSummary(input) {
|
|
|
163498
164022
|
);
|
|
163499
164023
|
return {
|
|
163500
164024
|
runtimeInstanceId: rtKey,
|
|
164025
|
+
nodeId: parseNodeId(rtKey),
|
|
164026
|
+
displayName: resolveDisplayName(rtKey, kind),
|
|
163501
164027
|
hostname: resolveHostname(rtKey, kind),
|
|
163502
164028
|
runtimeKind: kind,
|
|
163503
164029
|
usage,
|
|
@@ -163535,12 +164061,12 @@ function nameKey(name) {
|
|
|
163535
164061
|
function cleanName(name) {
|
|
163536
164062
|
return name.trim().replace(/\s+/g, " ");
|
|
163537
164063
|
}
|
|
163538
|
-
var import_node_fs12,
|
|
164064
|
+
var import_node_fs12, import_node_path16, import_node_crypto27, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
|
|
163539
164065
|
var init_tags = __esm({
|
|
163540
164066
|
"../server/src/domains/collab/tags.ts"() {
|
|
163541
164067
|
"use strict";
|
|
163542
164068
|
import_node_fs12 = __toESM(require("node:fs"), 1);
|
|
163543
|
-
|
|
164069
|
+
import_node_path16 = __toESM(require("node:path"), 1);
|
|
163544
164070
|
import_node_crypto27 = __toESM(require("node:crypto"), 1);
|
|
163545
164071
|
SEP = "::";
|
|
163546
164072
|
keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
|
|
@@ -163626,7 +164152,7 @@ var init_tags = __esm({
|
|
|
163626
164152
|
}
|
|
163627
164153
|
persist() {
|
|
163628
164154
|
try {
|
|
163629
|
-
import_node_fs12.default.mkdirSync(
|
|
164155
|
+
import_node_fs12.default.mkdirSync(import_node_path16.default.dirname(this.file), { recursive: true });
|
|
163630
164156
|
const tmp = `${this.file}.tmp`;
|
|
163631
164157
|
import_node_fs12.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
163632
164158
|
import_node_fs12.default.renameSync(tmp, this.file);
|
|
@@ -163767,17 +164293,22 @@ function collabDomain(opts) {
|
|
|
163767
164293
|
return { status: 400, body: { error: { code: "bad_request", message: "timeZone \u65E0\u6548" } } };
|
|
163768
164294
|
}
|
|
163769
164295
|
const { kernel } = await resolveCtx(req.auth.companyId);
|
|
163770
|
-
const [runs, runtimeRecords] = await Promise.all([
|
|
164296
|
+
const [runs, runtimeRecords, nodeRecords] = await Promise.all([
|
|
163771
164297
|
opts.trace.listUsageRuns({ from, to }),
|
|
163772
|
-
opts.listRuntimes ? opts.listRuntimes().catch(() => []) : Promise.resolve([])
|
|
164298
|
+
opts.listRuntimes ? opts.listRuntimes().catch(() => []) : Promise.resolve([]),
|
|
164299
|
+
opts.listNodes ? opts.listNodes().catch(() => []) : Promise.resolve([])
|
|
163773
164300
|
]);
|
|
163774
164301
|
const runtimeHostnames = /* @__PURE__ */ new Map();
|
|
163775
164302
|
for (const rt of runtimeRecords) {
|
|
163776
164303
|
if (rt.id && rt.hostname) runtimeHostnames.set(rt.id, rt.hostname);
|
|
163777
164304
|
}
|
|
164305
|
+
const runtimeNodeNames = /* @__PURE__ */ new Map();
|
|
164306
|
+
for (const n of nodeRecords) {
|
|
164307
|
+
if (n.id && n.name) runtimeNodeNames.set(n.id, n.name);
|
|
164308
|
+
}
|
|
163778
164309
|
return {
|
|
163779
164310
|
status: 200,
|
|
163780
|
-
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames })
|
|
164311
|
+
body: buildOrganizationUsageSummary({ model: kernel.model, runs, bucketKind: bucket, timeZone, runtimeHostnames, runtimeNodeNames })
|
|
163781
164312
|
};
|
|
163782
164313
|
});
|
|
163783
164314
|
router.get("/api/workorders", async (req) => {
|
|
@@ -164577,10 +165108,10 @@ function tokenType(p2) {
|
|
|
164577
165108
|
function parseOtlpMetricsUsage(body) {
|
|
164578
165109
|
const req = body;
|
|
164579
165110
|
const out = [];
|
|
164580
|
-
for (const
|
|
164581
|
-
const runId = attrString(
|
|
165111
|
+
for (const rm6 of req.resourceMetrics ?? []) {
|
|
165112
|
+
const runId = attrString(rm6.resource?.attributes, "oasis.run_id");
|
|
164582
165113
|
if (!runId) continue;
|
|
164583
|
-
const actorId = attrString(
|
|
165114
|
+
const actorId = attrString(rm6.resource?.attributes, "oasis.actor_id");
|
|
164584
165115
|
let input = 0;
|
|
164585
165116
|
let output = 0;
|
|
164586
165117
|
let cacheRead = 0;
|
|
@@ -164588,7 +165119,7 @@ function parseOtlpMetricsUsage(body) {
|
|
|
164588
165119
|
let costUsd = 0;
|
|
164589
165120
|
let sawToken = false;
|
|
164590
165121
|
let sawCost = false;
|
|
164591
|
-
for (const sm of
|
|
165122
|
+
for (const sm of rm6.scopeMetrics ?? []) {
|
|
164592
165123
|
for (const m2 of sm.metrics ?? []) {
|
|
164593
165124
|
const name = (m2.name ?? "").toLowerCase();
|
|
164594
165125
|
const points = m2.sum?.dataPoints ?? m2.gauge?.dataPoints ?? [];
|
|
@@ -164964,6 +165495,30 @@ var init_routes6 = __esm({
|
|
|
164964
165495
|
}
|
|
164965
165496
|
});
|
|
164966
165497
|
|
|
165498
|
+
// ../server/src/domains/trace/trace-health.ts
|
|
165499
|
+
function createTraceHealth() {
|
|
165500
|
+
const unhealthy = /* @__PURE__ */ new Set();
|
|
165501
|
+
return {
|
|
165502
|
+
markUnhealthy(runId) {
|
|
165503
|
+
unhealthy.add(runId);
|
|
165504
|
+
},
|
|
165505
|
+
markHealthy(runId) {
|
|
165506
|
+
unhealthy.delete(runId);
|
|
165507
|
+
},
|
|
165508
|
+
isHealthy(runId) {
|
|
165509
|
+
return !unhealthy.has(runId);
|
|
165510
|
+
},
|
|
165511
|
+
forget(runId) {
|
|
165512
|
+
unhealthy.delete(runId);
|
|
165513
|
+
}
|
|
165514
|
+
};
|
|
165515
|
+
}
|
|
165516
|
+
var init_trace_health = __esm({
|
|
165517
|
+
"../server/src/domains/trace/trace-health.ts"() {
|
|
165518
|
+
"use strict";
|
|
165519
|
+
}
|
|
165520
|
+
});
|
|
165521
|
+
|
|
164967
165522
|
// ../server/src/domains/trace/index.ts
|
|
164968
165523
|
function createTraceDomain(opts) {
|
|
164969
165524
|
const service = new TraceService({ store: opts.store });
|
|
@@ -164978,6 +165533,8 @@ var init_trace2 = __esm({
|
|
|
164978
165533
|
init_routes6();
|
|
164979
165534
|
init_sink();
|
|
164980
165535
|
init_chat_parts();
|
|
165536
|
+
init_trace_health();
|
|
165537
|
+
init_resilient_appender();
|
|
164981
165538
|
}
|
|
164982
165539
|
});
|
|
164983
165540
|
|
|
@@ -167049,12 +167606,12 @@ function normalize(patch) {
|
|
|
167049
167606
|
...reviewRoles !== void 0 ? { reviewRoles: [...new Set(reviewRoles.map((r) => r.trim()).filter(Boolean))] } : {}
|
|
167050
167607
|
};
|
|
167051
167608
|
}
|
|
167052
|
-
var import_node_fs13,
|
|
167609
|
+
var import_node_fs13, import_node_path17, SEP2, keyOf2, prefixOf2, MemoryPlaybookOverrideStore, FilePlaybookOverrideStore;
|
|
167053
167610
|
var init_overrides = __esm({
|
|
167054
167611
|
"../server/src/domains/playbooks/overrides.ts"() {
|
|
167055
167612
|
"use strict";
|
|
167056
167613
|
import_node_fs13 = __toESM(require("node:fs"), 1);
|
|
167057
|
-
|
|
167614
|
+
import_node_path17 = __toESM(require("node:path"), 1);
|
|
167058
167615
|
SEP2 = "::";
|
|
167059
167616
|
keyOf2 = (companyId, ref2, nodeKey) => `${companyId}${SEP2}${ref2}${SEP2}${nodeKey}`;
|
|
167060
167617
|
prefixOf2 = (companyId, ref2) => `${companyId}${SEP2}${ref2}${SEP2}`;
|
|
@@ -167093,7 +167650,7 @@ var init_overrides = __esm({
|
|
|
167093
167650
|
}
|
|
167094
167651
|
persist() {
|
|
167095
167652
|
try {
|
|
167096
|
-
import_node_fs13.default.mkdirSync(
|
|
167653
|
+
import_node_fs13.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
|
|
167097
167654
|
const tmp = `${this.file}.tmp`;
|
|
167098
167655
|
import_node_fs13.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167099
167656
|
import_node_fs13.default.renameSync(tmp, this.file);
|
|
@@ -167532,12 +168089,12 @@ var init_daemon_adapter = __esm({
|
|
|
167532
168089
|
});
|
|
167533
168090
|
|
|
167534
168091
|
// ../server/src/side-map.ts
|
|
167535
|
-
var import_node_fs14,
|
|
168092
|
+
var import_node_fs14, import_node_path18, FileSideMap;
|
|
167536
168093
|
var init_side_map = __esm({
|
|
167537
168094
|
"../server/src/side-map.ts"() {
|
|
167538
168095
|
"use strict";
|
|
167539
168096
|
import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
167540
|
-
|
|
168097
|
+
import_node_path18 = __toESM(require("node:path"), 1);
|
|
167541
168098
|
FileSideMap = class {
|
|
167542
168099
|
constructor(file) {
|
|
167543
168100
|
this.file = file;
|
|
@@ -167564,7 +168121,7 @@ var init_side_map = __esm({
|
|
|
167564
168121
|
}
|
|
167565
168122
|
persist() {
|
|
167566
168123
|
try {
|
|
167567
|
-
import_node_fs14.default.mkdirSync(
|
|
168124
|
+
import_node_fs14.default.mkdirSync(import_node_path18.default.dirname(this.file), { recursive: true });
|
|
167568
168125
|
const tmp = `${this.file}.tmp`;
|
|
167569
168126
|
import_node_fs14.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
167570
168127
|
import_node_fs14.default.renameSync(tmp, this.file);
|
|
@@ -169020,26 +169577,26 @@ ${ctx.nodeFault}
|
|
|
169020
169577
|
|
|
169021
169578
|
// ../server/src/governance/builtin-skills.ts
|
|
169022
169579
|
async function collectDir(root, dir, out) {
|
|
169023
|
-
const entries = await (0,
|
|
169580
|
+
const entries = await (0, import_promises9.readdir)(dir, { withFileTypes: true });
|
|
169024
169581
|
for (const e of entries) {
|
|
169025
|
-
const abs = (0,
|
|
169582
|
+
const abs = (0, import_node_path19.join)(dir, e.name);
|
|
169026
169583
|
if (e.isDirectory()) {
|
|
169027
169584
|
await collectDir(root, abs, out);
|
|
169028
169585
|
} else if (e.isFile()) {
|
|
169029
|
-
const info = await (0,
|
|
169586
|
+
const info = await (0, import_promises9.stat)(abs);
|
|
169030
169587
|
if (info.size > MAX_FILE_BYTES3) {
|
|
169031
169588
|
console.warn(`[builtin-skills] skip oversized file (${info.size}B): ${abs}`);
|
|
169032
169589
|
continue;
|
|
169033
169590
|
}
|
|
169034
|
-
const rel = (0,
|
|
169035
|
-
out[rel] = await (0,
|
|
169591
|
+
const rel = (0, import_node_path19.relative)(root, abs).split(/[\\/]/).join("/");
|
|
169592
|
+
out[rel] = await (0, import_promises9.readFile)(abs, "utf8");
|
|
169036
169593
|
}
|
|
169037
169594
|
}
|
|
169038
169595
|
}
|
|
169039
169596
|
async function loadBuiltinSkills(skillsDir) {
|
|
169040
169597
|
let dirents;
|
|
169041
169598
|
try {
|
|
169042
|
-
dirents = await (0,
|
|
169599
|
+
dirents = await (0, import_promises9.readdir)(skillsDir, { withFileTypes: true });
|
|
169043
169600
|
} catch {
|
|
169044
169601
|
return [];
|
|
169045
169602
|
}
|
|
@@ -169047,7 +169604,7 @@ async function loadBuiltinSkills(skillsDir) {
|
|
|
169047
169604
|
for (const d of dirents) {
|
|
169048
169605
|
if (!d.isDirectory()) continue;
|
|
169049
169606
|
const slug6 = d.name;
|
|
169050
|
-
const skillDir = (0,
|
|
169607
|
+
const skillDir = (0, import_node_path19.join)(skillsDir, slug6);
|
|
169051
169608
|
const files = {};
|
|
169052
169609
|
try {
|
|
169053
169610
|
await collectDir(skillDir, skillDir, files);
|
|
@@ -169075,12 +169632,12 @@ function materializeBuiltinSkills(builtins, skillsDirPrefix) {
|
|
|
169075
169632
|
}
|
|
169076
169633
|
return out;
|
|
169077
169634
|
}
|
|
169078
|
-
var
|
|
169635
|
+
var import_promises9, import_node_path19, MAX_FILE_BYTES3;
|
|
169079
169636
|
var init_builtin_skills = __esm({
|
|
169080
169637
|
"../server/src/governance/builtin-skills.ts"() {
|
|
169081
169638
|
"use strict";
|
|
169082
|
-
|
|
169083
|
-
|
|
169639
|
+
import_promises9 = require("node:fs/promises");
|
|
169640
|
+
import_node_path19 = require("node:path");
|
|
169084
169641
|
init_skill_fetcher();
|
|
169085
169642
|
init_skill_materializer();
|
|
169086
169643
|
MAX_FILE_BYTES3 = 1 << 20;
|
|
@@ -174572,6 +175129,21 @@ var init_postgres = __esm({
|
|
|
174572
175129
|
});
|
|
174573
175130
|
|
|
174574
175131
|
// ../storage/src/postgres-registry.ts
|
|
175132
|
+
function rowToVariable(row) {
|
|
175133
|
+
return {
|
|
175134
|
+
key: row.key,
|
|
175135
|
+
scope: row.scope === "connector" ? "global" : row.scope,
|
|
175136
|
+
...row.actor_id !== null && row.actor_id !== void 0 ? { actorId: row.actor_id } : {},
|
|
175137
|
+
...row.project_id !== null && row.project_id !== void 0 ? { projectId: row.project_id } : {},
|
|
175138
|
+
...row.connector_id !== null && row.connector_id !== void 0 ? { connectorId: row.connector_id } : {},
|
|
175139
|
+
...row.overrides !== null && row.overrides !== void 0 ? { overrides: row.overrides } : {},
|
|
175140
|
+
// 保留库里存的原始 delivery_mode(含未来 broker/wrapper 档,annotation d7456d5e Req3)——
|
|
175141
|
+
// **不塌成 env**,否则未知档位读回来变明文;仅 null/空回填 "env"(存量行)。派单侧按未知档保守处理。
|
|
175142
|
+
deliveryMode: typeof row.delivery_mode === "string" && row.delivery_mode ? row.delivery_mode : "env",
|
|
175143
|
+
valueEncrypted: row.value_encrypted,
|
|
175144
|
+
updatedAt: new Date(row.updated_at).toISOString()
|
|
175145
|
+
};
|
|
175146
|
+
}
|
|
174575
175147
|
var ident4, PostgresRegistryStore, rowToActor, rowToConfig;
|
|
174576
175148
|
var init_postgres_registry = __esm({
|
|
174577
175149
|
"../storage/src/postgres-registry.ts"() {
|
|
@@ -174703,9 +175275,21 @@ var init_postgres_registry = __esm({
|
|
|
174703
175275
|
value_encrypted text NOT NULL,
|
|
174704
175276
|
updated_at timestamptz NOT NULL
|
|
174705
175277
|
)`);
|
|
174706
|
-
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS "${s2}_variables_key_actor_uq" ON "${s2}".variables (key, COALESCE(actor_id, ''))`);
|
|
174707
175278
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS overrides text`);
|
|
174708
175279
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS actor_id text`);
|
|
175280
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS project_id text`);
|
|
175281
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS environment text`);
|
|
175282
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS delivery_mode text`);
|
|
175283
|
+
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_key_actor_uq"`);
|
|
175284
|
+
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_scope_uq"`);
|
|
175285
|
+
await pool.query(`
|
|
175286
|
+
DELETE FROM "${s2}".variables v
|
|
175287
|
+
WHERE v.ctid NOT IN (
|
|
175288
|
+
SELECT DISTINCT ON (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) ctid
|
|
175289
|
+
FROM "${s2}".variables
|
|
175290
|
+
ORDER BY key, COALESCE(actor_id, ''), COALESCE(project_id, ''), updated_at DESC, ctid DESC
|
|
175291
|
+
)`);
|
|
175292
|
+
await pool.query(`CREATE UNIQUE INDEX IF NOT EXISTS "${s2}_variables_scope_uq_v2" ON "${s2}".variables (key, COALESCE(actor_id, ''), COALESCE(project_id, ''))`);
|
|
174709
175293
|
await pool.query(`
|
|
174710
175294
|
CREATE TABLE IF NOT EXISTS "${s2}".runtime_configs (
|
|
174711
175295
|
runtime_id text PRIMARY KEY,
|
|
@@ -175149,27 +175733,36 @@ var init_postgres_registry = __esm({
|
|
|
175149
175733
|
}
|
|
175150
175734
|
/* ---------- 变量 ---------- */
|
|
175151
175735
|
async putVariable(v2) {
|
|
175152
|
-
const aid = v2.actorId ?? null;
|
|
175153
175736
|
await this.pool.query(
|
|
175154
|
-
`INSERT INTO ${this.s}.variables (key, scope, actor_id, connector_id, overrides, value_encrypted, updated_at)
|
|
175155
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7)
|
|
175156
|
-
ON CONFLICT (key, COALESCE(actor_id, '')) DO UPDATE
|
|
175157
|
-
SET scope=$2, actor_id=$3,
|
|
175158
|
-
[
|
|
175737
|
+
`INSERT INTO ${this.s}.variables (key, scope, actor_id, project_id, connector_id, overrides, delivery_mode, value_encrypted, updated_at)
|
|
175738
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
175739
|
+
ON CONFLICT (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) DO UPDATE
|
|
175740
|
+
SET scope=$2, actor_id=$3, project_id=$4, connector_id=$5, overrides=$6, delivery_mode=$7, value_encrypted=$8, updated_at=$9`,
|
|
175741
|
+
[
|
|
175742
|
+
v2.key,
|
|
175743
|
+
v2.scope,
|
|
175744
|
+
v2.actorId ?? null,
|
|
175745
|
+
v2.projectId ?? null,
|
|
175746
|
+
v2.connectorId ?? null,
|
|
175747
|
+
v2.overrides ?? null,
|
|
175748
|
+
v2.deliveryMode ?? null,
|
|
175749
|
+
v2.valueEncrypted,
|
|
175750
|
+
v2.updatedAt
|
|
175751
|
+
]
|
|
175159
175752
|
);
|
|
175160
175753
|
}
|
|
175161
175754
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
175162
175755
|
const aid = actorId ?? null;
|
|
175163
175756
|
await this.pool.query(
|
|
175164
175757
|
`UPDATE ${this.s}.variables SET value_encrypted=$3, updated_at=$4
|
|
175165
|
-
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')`,
|
|
175758
|
+
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'') AND COALESCE(project_id,'')=''`,
|
|
175166
175759
|
[key, aid, valueEncrypted, updatedAt]
|
|
175167
175760
|
);
|
|
175168
175761
|
}
|
|
175169
175762
|
async getVariableCiphertext(key, actorId) {
|
|
175170
175763
|
const aid = actorId ?? null;
|
|
175171
175764
|
const r = await this.pool.query(
|
|
175172
|
-
`SELECT value_encrypted FROM ${this.s}.variables WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')`,
|
|
175765
|
+
`SELECT value_encrypted FROM ${this.s}.variables WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'') AND COALESCE(project_id,'')=''`,
|
|
175173
175766
|
[key, aid]
|
|
175174
175767
|
);
|
|
175175
175768
|
return r.rows[0]?.value_encrypted ?? null;
|
|
@@ -175184,21 +175777,21 @@ var init_postgres_registry = __esm({
|
|
|
175184
175777
|
} else {
|
|
175185
175778
|
r = await this.pool.query(`SELECT * FROM ${this.s}.variables ORDER BY key`);
|
|
175186
175779
|
}
|
|
175187
|
-
return r.rows.map((row) => (
|
|
175188
|
-
key: row.key,
|
|
175189
|
-
scope: row.scope === "connector" ? "global" : row.scope,
|
|
175190
|
-
...row.actor_id !== null && row.actor_id !== void 0 ? { actorId: row.actor_id } : {},
|
|
175191
|
-
...row.connector_id !== null ? { connectorId: row.connector_id } : {},
|
|
175192
|
-
...row.overrides !== null ? { overrides: row.overrides } : {},
|
|
175193
|
-
valueEncrypted: row.value_encrypted,
|
|
175194
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
175195
|
-
}));
|
|
175780
|
+
return r.rows.map((row) => rowToVariable(row));
|
|
175196
175781
|
}
|
|
175197
|
-
async
|
|
175198
|
-
const
|
|
175782
|
+
async resolveProjectVariables(projectId) {
|
|
175783
|
+
const r = await this.pool.query(
|
|
175784
|
+
`SELECT * FROM ${this.s}.variables WHERE scope='project' AND project_id=$1 ORDER BY key`,
|
|
175785
|
+
[projectId]
|
|
175786
|
+
);
|
|
175787
|
+
return r.rows.map((row) => rowToVariable(row));
|
|
175788
|
+
}
|
|
175789
|
+
async deleteVariable(key, actorId, scoping) {
|
|
175199
175790
|
await this.pool.query(
|
|
175200
|
-
`DELETE FROM ${this.s}.variables
|
|
175201
|
-
|
|
175791
|
+
`DELETE FROM ${this.s}.variables
|
|
175792
|
+
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'')
|
|
175793
|
+
AND COALESCE(project_id,'')=COALESCE($3::text,'')`,
|
|
175794
|
+
[key, actorId ?? null, scoping?.projectId ?? null]
|
|
175202
175795
|
);
|
|
175203
175796
|
}
|
|
175204
175797
|
};
|
|
@@ -176017,6 +176610,7 @@ var init_postgres_projects = __esm({
|
|
|
176017
176610
|
work_order_id text PRIMARY KEY,
|
|
176018
176611
|
project_id text NOT NULL
|
|
176019
176612
|
)`);
|
|
176613
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".workspace_bindings ADD COLUMN IF NOT EXISTS environment text`);
|
|
176020
176614
|
await pool.query(`
|
|
176021
176615
|
CREATE TABLE IF NOT EXISTS "${s2}".workspace_dispatch_hold (
|
|
176022
176616
|
work_order_id text PRIMARY KEY
|
|
@@ -176886,6 +177480,38 @@ var init_postgres_control_plane = __esm({
|
|
|
176886
177480
|
}
|
|
176887
177481
|
});
|
|
176888
177482
|
|
|
177483
|
+
// ../storage/src/pg-sanitize.ts
|
|
177484
|
+
function hasPgUnstorable(s2) {
|
|
177485
|
+
return new RegExp(PG_UNSTORABLE_SOURCE).test(s2);
|
|
177486
|
+
}
|
|
177487
|
+
function scrubPgString(v2) {
|
|
177488
|
+
return typeof v2 === "string" ? v2.replace(new RegExp(PG_UNSTORABLE_SOURCE, "g"), REPLACEMENT) : v2;
|
|
177489
|
+
}
|
|
177490
|
+
function scrubPgJson(v2) {
|
|
177491
|
+
const re = new RegExp(PG_UNSTORABLE_SOURCE, "g");
|
|
177492
|
+
const walk = (x2) => {
|
|
177493
|
+
if (typeof x2 === "string") return x2.replace(re, REPLACEMENT);
|
|
177494
|
+
if (Array.isArray(x2)) return x2.map(walk);
|
|
177495
|
+
if (x2 && typeof x2 === "object") {
|
|
177496
|
+
const out = {};
|
|
177497
|
+
for (const [k2, val] of Object.entries(x2)) {
|
|
177498
|
+
out[k2.replace(re, REPLACEMENT)] = walk(val);
|
|
177499
|
+
}
|
|
177500
|
+
return out;
|
|
177501
|
+
}
|
|
177502
|
+
return x2;
|
|
177503
|
+
};
|
|
177504
|
+
return walk(v2);
|
|
177505
|
+
}
|
|
177506
|
+
var REPLACEMENT, PG_UNSTORABLE_SOURCE;
|
|
177507
|
+
var init_pg_sanitize = __esm({
|
|
177508
|
+
"../storage/src/pg-sanitize.ts"() {
|
|
177509
|
+
"use strict";
|
|
177510
|
+
REPLACEMENT = "\uFFFD";
|
|
177511
|
+
PG_UNSTORABLE_SOURCE = "\\u0000|[\\uD800-\\uDBFF](?![\\uDC00-\\uDFFF])|(?<![\\uD800-\\uDBFF])[\\uDC00-\\uDFFF]";
|
|
177512
|
+
}
|
|
177513
|
+
});
|
|
177514
|
+
|
|
176889
177515
|
// ../storage/src/postgres-trace.ts
|
|
176890
177516
|
var ident9, PostgresTraceStore, rowToRun, rowToEvent2, rowToToolCall, rowToArtifact2;
|
|
176891
177517
|
var init_postgres_trace = __esm({
|
|
@@ -176893,6 +177519,7 @@ var init_postgres_trace = __esm({
|
|
|
176893
177519
|
"use strict";
|
|
176894
177520
|
init_esm2();
|
|
176895
177521
|
init_src();
|
|
177522
|
+
init_pg_sanitize();
|
|
176896
177523
|
ident9 = (s2) => {
|
|
176897
177524
|
if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
|
|
176898
177525
|
return s2;
|
|
@@ -177153,12 +177780,12 @@ var init_postgres_trace = __esm({
|
|
|
177153
177780
|
run.exitCode,
|
|
177154
177781
|
run.exitReason,
|
|
177155
177782
|
run.errorCode,
|
|
177156
|
-
run.errorMessage,
|
|
177783
|
+
scrubPgString(run.errorMessage),
|
|
177157
177784
|
run.usage === null ? null : JSON.stringify(run.usage),
|
|
177158
177785
|
run.effectiveModel,
|
|
177159
177786
|
run.modelSource,
|
|
177160
177787
|
run.transcriptRef,
|
|
177161
|
-
JSON.stringify(run.metadata),
|
|
177788
|
+
JSON.stringify(scrubPgJson(run.metadata)),
|
|
177162
177789
|
run.createdAt,
|
|
177163
177790
|
run.updatedAt
|
|
177164
177791
|
]
|
|
@@ -177201,7 +177828,7 @@ var init_postgres_trace = __esm({
|
|
|
177201
177828
|
for (const [key, spec] of Object.entries(_PostgresTraceStore.RUN_COLS)) {
|
|
177202
177829
|
if (!(key in patch)) continue;
|
|
177203
177830
|
const v2 = patch[key];
|
|
177204
|
-
args.push(spec.json ? v2 == null ? null : JSON.stringify(v2) : v2 ?? null);
|
|
177831
|
+
args.push(spec.json ? v2 == null ? null : JSON.stringify(scrubPgJson(v2)) : scrubPgString(v2 ?? null));
|
|
177205
177832
|
sets.push(spec.json ? `${spec.col}=$${args.length}::jsonb` : `${spec.col}=$${args.length}`);
|
|
177206
177833
|
}
|
|
177207
177834
|
args.push(this.now());
|
|
@@ -177340,8 +177967,8 @@ var init_postgres_trace = __esm({
|
|
|
177340
177967
|
stream,
|
|
177341
177968
|
level,
|
|
177342
177969
|
inp.color ?? null,
|
|
177343
|
-
inp.message ?? null,
|
|
177344
|
-
JSON.stringify(payload),
|
|
177970
|
+
scrubPgString(inp.message ?? null),
|
|
177971
|
+
JSON.stringify(scrubPgJson(payload)),
|
|
177345
177972
|
inp.blobRef ?? null,
|
|
177346
177973
|
inp.spanId ?? null,
|
|
177347
177974
|
inp.parentSpanId ?? null,
|
|
@@ -177416,11 +178043,11 @@ var init_postgres_trace = __esm({
|
|
|
177416
178043
|
c.durationMs ?? null,
|
|
177417
178044
|
c.inputRef ?? null,
|
|
177418
178045
|
c.outputRef ?? null,
|
|
177419
|
-
c.inputPreview ?? null,
|
|
177420
|
-
c.outputPreview ?? null,
|
|
178046
|
+
scrubPgString(c.inputPreview ?? null),
|
|
178047
|
+
scrubPgString(c.outputPreview ?? null),
|
|
177421
178048
|
c.errorCode ?? null,
|
|
177422
|
-
c.errorMessage ?? null,
|
|
177423
|
-
JSON.stringify(c.metadata ?? {})
|
|
178049
|
+
scrubPgString(c.errorMessage ?? null),
|
|
178050
|
+
JSON.stringify(scrubPgJson(c.metadata ?? {}))
|
|
177424
178051
|
]
|
|
177425
178052
|
);
|
|
177426
178053
|
}
|
|
@@ -177465,12 +178092,12 @@ var init_postgres_trace = __esm({
|
|
|
177465
178092
|
a.id,
|
|
177466
178093
|
a.runId,
|
|
177467
178094
|
a.kind,
|
|
177468
|
-
a.name,
|
|
178095
|
+
scrubPgString(a.name),
|
|
177469
178096
|
a.contentType ?? null,
|
|
177470
178097
|
a.size ?? null,
|
|
177471
178098
|
a.blobRef,
|
|
177472
178099
|
a.createdAt,
|
|
177473
|
-
JSON.stringify(a.metadata ?? {})
|
|
178100
|
+
JSON.stringify(scrubPgJson(a.metadata ?? {}))
|
|
177474
178101
|
]
|
|
177475
178102
|
);
|
|
177476
178103
|
}
|
|
@@ -179182,7 +179809,10 @@ __export(src_exports, {
|
|
|
179182
179809
|
PostgresTraceStore: () => PostgresTraceStore,
|
|
179183
179810
|
PostgresTypeRegistryStore: () => PostgresTypeRegistryStore,
|
|
179184
179811
|
backfillTypeRegistryFromFile: () => backfillTypeRegistryFromFile,
|
|
179185
|
-
createPgPool: () => createPgPool
|
|
179812
|
+
createPgPool: () => createPgPool,
|
|
179813
|
+
hasPgUnstorable: () => hasPgUnstorable,
|
|
179814
|
+
scrubPgJson: () => scrubPgJson,
|
|
179815
|
+
scrubPgString: () => scrubPgString
|
|
179186
179816
|
});
|
|
179187
179817
|
var init_src8 = __esm({
|
|
179188
179818
|
"../storage/src/index.ts"() {
|
|
@@ -179195,6 +179825,7 @@ var init_src8 = __esm({
|
|
|
179195
179825
|
init_pool();
|
|
179196
179826
|
init_postgres_control_plane();
|
|
179197
179827
|
init_postgres_trace();
|
|
179828
|
+
init_pg_sanitize();
|
|
179198
179829
|
init_postgres_automations();
|
|
179199
179830
|
init_postgres_chat_sessions();
|
|
179200
179831
|
init_postgres_nodes();
|
|
@@ -179594,15 +180225,18 @@ function splitIdentityFiles3(prompt) {
|
|
|
179594
180225
|
}
|
|
179595
180226
|
return out;
|
|
179596
180227
|
}
|
|
179597
|
-
async function buildActorProvision(service, actorId) {
|
|
179598
|
-
const
|
|
179599
|
-
const
|
|
180228
|
+
async function buildActorProvision(service, actorId, scope) {
|
|
180229
|
+
const entries = await service.resolveActorProvisionEntries(actorId, scope);
|
|
180230
|
+
const raw = {};
|
|
180231
|
+
for (const e of entries) raw[e.key] = e.value;
|
|
179600
180232
|
const provision = await buildConnectorProvision({
|
|
179601
180233
|
vars: raw,
|
|
179602
180234
|
actorName: raw["GIT_AUTHOR_NAME"] ?? actorId.split(":").pop() ?? "oasis-agent"
|
|
179603
180235
|
});
|
|
180236
|
+
const env = { ...raw };
|
|
179604
180237
|
for (const k2 of provision.sensitiveVars) delete env[k2];
|
|
179605
180238
|
for (const [k2, v2] of Object.entries(provision.envOverrides)) env[k2] = v2;
|
|
180239
|
+
applyRefDelivery(env, entries);
|
|
179606
180240
|
return {
|
|
179607
180241
|
env,
|
|
179608
180242
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
@@ -179828,6 +180462,45 @@ async function startServe(opts) {
|
|
|
179828
180462
|
});
|
|
179829
180463
|
for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.target, timestamp: record6.timestamp });
|
|
179830
180464
|
};
|
|
180465
|
+
const credentialAudit = (record6) => {
|
|
180466
|
+
fs29.appendFile(registryAuditFile, JSON.stringify(record6) + "\n", () => {
|
|
180467
|
+
});
|
|
180468
|
+
for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.variableKey, timestamp: record6.timestamp });
|
|
180469
|
+
};
|
|
180470
|
+
const readCredentialAudit = async (filter) => {
|
|
180471
|
+
let raw;
|
|
180472
|
+
try {
|
|
180473
|
+
raw = await fs29.promises.readFile(registryAuditFile, "utf8");
|
|
180474
|
+
} catch {
|
|
180475
|
+
return [];
|
|
180476
|
+
}
|
|
180477
|
+
const out = [];
|
|
180478
|
+
for (const line of raw.split("\n")) {
|
|
180479
|
+
if (!line.trim()) continue;
|
|
180480
|
+
let rec;
|
|
180481
|
+
try {
|
|
180482
|
+
rec = JSON.parse(line);
|
|
180483
|
+
} catch {
|
|
180484
|
+
continue;
|
|
180485
|
+
}
|
|
180486
|
+
if (typeof rec.kind !== "string" || !rec.kind.startsWith("credential_reveal")) continue;
|
|
180487
|
+
if (filter.actor && rec.actor !== filter.actor) continue;
|
|
180488
|
+
if (filter.key && rec.variableKey !== filter.key) continue;
|
|
180489
|
+
if (filter.kind && rec.kind !== filter.kind) continue;
|
|
180490
|
+
out.push(rec);
|
|
180491
|
+
}
|
|
180492
|
+
out.reverse();
|
|
180493
|
+
return typeof filter.limit === "number" ? out.slice(0, filter.limit) : out;
|
|
180494
|
+
};
|
|
180495
|
+
const resolveDispatchScope = async (artifactId) => {
|
|
180496
|
+
const ws = kernel.model.artifacts.get(artifactId)?.workspace;
|
|
180497
|
+
if (!ws) return {};
|
|
180498
|
+
const binding = await artifactStateStore.getWorkspaceBinding(ws);
|
|
180499
|
+
if (!binding) return {};
|
|
180500
|
+
return {
|
|
180501
|
+
...binding.projectId ? { projectId: binding.projectId } : {}
|
|
180502
|
+
};
|
|
180503
|
+
};
|
|
179831
180504
|
await syncRegistryRolesToKernel(registryStore, kernel);
|
|
179832
180505
|
let builtinSkills = [];
|
|
179833
180506
|
let connectorSkills = [];
|
|
@@ -179844,6 +180517,13 @@ async function startServe(opts) {
|
|
|
179844
180517
|
blobs: assets,
|
|
179845
180518
|
trace: () => traceStoreForActors,
|
|
179846
180519
|
audit: registryAudit,
|
|
180520
|
+
// ADR 凭据保险库 §4.5/§4.7 / ADR 0125:reveal 判权的项目解析 + 凭据读取审计读写。
|
|
180521
|
+
resolveDispatchScope,
|
|
180522
|
+
credentialAudit,
|
|
180523
|
+
readCredentialAudit,
|
|
180524
|
+
// ADR 0125:写 scope=project 变量时校验 projectId 真实存在(getProject 直查,含临时项目)。
|
|
180525
|
+
// projectStateStore 在下方 ~行 1023 才赋值——本箭头只在请求时跑,那时已就绪(同 resolveDispatchScope 惰性模式)。
|
|
180526
|
+
projectExists: async (id) => await projectStateStore.getProject(id) !== null,
|
|
179847
180527
|
// CO-302 数据面隔离(actors 域试点):按当前公司取其引擎,用各自 registry 服务该域请求。
|
|
179848
180528
|
// engineRouter 在下方(行 ~411)以 const 声明;此箭头只在请求时调用,那时已初始化,闭包引用合法
|
|
179849
180529
|
// (TDZ 只在构造时访问才报错,这里不访问)。默认公司命中现有单实例(registry===registryStore),
|
|
@@ -179974,7 +180654,13 @@ async function startServe(opts) {
|
|
|
179974
180654
|
traceStoreForActors = traceStore;
|
|
179975
180655
|
const trajReader = new FsTrajectorySink(opts.dir);
|
|
179976
180656
|
const trace = createTraceDomain({ store: traceStore, readBundleFile: (id, rel) => trajReader.readBundleFile(id, rel) });
|
|
179977
|
-
const
|
|
180657
|
+
const traceHealth = createTraceHealth();
|
|
180658
|
+
const traceStoreSink = new TraceStoreSink({
|
|
180659
|
+
store: traceStore,
|
|
180660
|
+
runtimeKind: "auto",
|
|
180661
|
+
health: traceHealth,
|
|
180662
|
+
onError: (err) => console.warn(`[trace-sink] \u5199\u89C2\u6D4B\u6D41\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u5F71\u54CD\u6D3E\u53D1\uFF09: ${String(err)}`)
|
|
180663
|
+
});
|
|
179978
180664
|
const automationStore = pgPool ? await PostgresAutomationStore.open(pgPool, pgSchema) : new MemoryAutomationStore();
|
|
179979
180665
|
console.log(`[serve] \u81EA\u52A8\u5316\u4F53\u7CFB\uFF1A${pgPool ? `Postgres schema=${pgSchema}` : "\u5185\u5B58 dev store"}`);
|
|
179980
180666
|
const automations = createAutomationsDomain({ store: automationStore, kernel });
|
|
@@ -180438,6 +181124,8 @@ async function startServe(opts) {
|
|
|
180438
181124
|
// 组织汇总用——从 node_runtimes 取 hostname,解析运行时实例标签(kind @ hostname)
|
|
180439
181125
|
listRuntimes: (nodeId) => nodeStore.listRuntimes(nodeId),
|
|
180440
181126
|
dispatchJournal: () => journalRing.slice(-200),
|
|
181127
|
+
// 组织汇总用——从 nodes 取 name(用户友好名),优先于 hostname 作为展示标签
|
|
181128
|
+
listNodes: () => nodeStore.listNodes(),
|
|
180441
181129
|
// 诊断 92ac8f18-83e5fde6 §④ D-2:按**请求公司**取其 dispatcher 的 queued/backoff 信号。
|
|
180442
181130
|
// CO-302 每家公司各有一套 dispatcher(dispatchers 以 companyId 为键)——固定读默认公司会让
|
|
180443
181131
|
// 非默认公司请求拿到错的/空的信号(code-review 打回)。该公司未起 dispatcher(老部署无 --dispatch、
|
|
@@ -180577,10 +181265,14 @@ async function startServe(opts) {
|
|
|
180577
181265
|
const traceRunId = `chat-run:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180578
181266
|
const artifactId = `artifact:chat:${(0, import_node_crypto37.randomUUID)()}`;
|
|
180579
181267
|
const traceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180580
|
-
let traceSeq = 0;
|
|
180581
181268
|
let lastProgressTouchMs = 0;
|
|
180582
181269
|
const PROGRESS_TOUCH_THROTTLE_MS2 = 2e4;
|
|
180583
|
-
|
|
181270
|
+
const traceAppender = new ResilientTraceAppender({
|
|
181271
|
+
runId: traceRunId,
|
|
181272
|
+
store: traceStore,
|
|
181273
|
+
health: traceHealth,
|
|
181274
|
+
onError: (err) => console.warn(`[trace] chat run ${traceRunId} \u5199\u5931\u8D25\uFF08\u7EE7\u7EED\u3001\u4E0D\u7184\u706D\uFF09: ${String(err)}`)
|
|
181275
|
+
});
|
|
180584
181276
|
const analyzedRunId = chatSessionId ? (await chatSessionStore.getSession(chatSessionId).catch(() => null))?.analyzedRunId ?? void 0 : void 0;
|
|
180585
181277
|
let traceChain = traceStore.createRun({
|
|
180586
181278
|
id: traceRunId,
|
|
@@ -180601,16 +181293,14 @@ async function startServe(opts) {
|
|
|
180601
181293
|
...analyzedRunId ? { analyzedRunId } : {}
|
|
180602
181294
|
}
|
|
180603
181295
|
}).then(async () => {
|
|
180604
|
-
await
|
|
181296
|
+
await traceAppender.append([
|
|
180605
181297
|
{
|
|
180606
|
-
seq: ++traceSeq,
|
|
180607
181298
|
eventType: "run.started",
|
|
180608
181299
|
stream: "runtime",
|
|
180609
181300
|
message: `chat ${actorId}`,
|
|
180610
181301
|
startedAt: traceStartedAt
|
|
180611
181302
|
},
|
|
180612
181303
|
{
|
|
180613
|
-
seq: ++traceSeq,
|
|
180614
181304
|
eventType: "input.message",
|
|
180615
181305
|
stream: "model",
|
|
180616
181306
|
actorId,
|
|
@@ -180620,16 +181310,12 @@ async function startServe(opts) {
|
|
|
180620
181310
|
}
|
|
180621
181311
|
]);
|
|
180622
181312
|
}).catch((err) => {
|
|
180623
|
-
|
|
180624
|
-
console.warn(`[trace] chat run create failed: ${String(err)}`);
|
|
181313
|
+
traceHealth.markUnhealthy(traceRunId);
|
|
181314
|
+
console.warn(`[trace] chat run create failed (continuing): ${String(err)}`);
|
|
180625
181315
|
});
|
|
180626
181316
|
const enqueueTrace = (step) => {
|
|
180627
|
-
|
|
180628
|
-
|
|
180629
|
-
if (traceEnabled) await step();
|
|
180630
|
-
}).catch((err) => {
|
|
180631
|
-
traceEnabled = false;
|
|
180632
|
-
console.warn(`[trace] chat run ${traceRunId} failed: ${String(err)}`);
|
|
181317
|
+
traceChain = traceChain.then(step).catch((err) => {
|
|
181318
|
+
console.warn(`[trace] chat run ${traceRunId} \u7EED\u8D26\u5F02\u5E38: ${String(err)}`);
|
|
180633
181319
|
});
|
|
180634
181320
|
};
|
|
180635
181321
|
const provision = await buildActorProvision(actorService, actorId);
|
|
@@ -180776,7 +181462,7 @@ async function startServe(opts) {
|
|
|
180776
181462
|
const run = await traceStore.getRun(traceRunId);
|
|
180777
181463
|
if (!run) return;
|
|
180778
181464
|
const base = run.metadata && typeof run.metadata === "object" && !Array.isArray(run.metadata) ? run.metadata : {};
|
|
180779
|
-
await
|
|
181465
|
+
await traceAppender.update({
|
|
180780
181466
|
metadata: { ...base, dispatchId: handle.id },
|
|
180781
181467
|
// 恢复路径拿不到 dispatchChat 闭包里的 fallback 解析结果,开跑时先写进账本;退出帧若上报
|
|
180782
181468
|
// 更精确 model 仍会覆盖为 runtime 来源。
|
|
@@ -180798,23 +181484,23 @@ async function startServe(opts) {
|
|
|
180798
181484
|
const ms = Date.parse(event.ts);
|
|
180799
181485
|
if (!Number.isNaN(ms) && ms - lastProgressTouchMs >= PROGRESS_TOUCH_THROTTLE_MS2) {
|
|
180800
181486
|
lastProgressTouchMs = ms;
|
|
180801
|
-
enqueueTrace(() =>
|
|
181487
|
+
enqueueTrace(() => traceAppender.update({ lastProgressAt: event.ts }).then(() => void 0));
|
|
180802
181488
|
}
|
|
180803
181489
|
return;
|
|
180804
181490
|
}
|
|
180805
|
-
enqueueTrace(() =>
|
|
181491
|
+
enqueueTrace(() => traceAppender.append([trajectoryEventToRunEvent(event)]).then(() => void 0));
|
|
180806
181492
|
});
|
|
180807
181493
|
let capturedNativeSessionId;
|
|
180808
181494
|
const done = new Promise((resolve8, reject) => {
|
|
180809
181495
|
handle.onExit((info) => {
|
|
180810
181496
|
chatLiveSessions.delete(chatJobKey);
|
|
181497
|
+
traceHealth.forget(traceRunId);
|
|
180811
181498
|
void provision.cleanup();
|
|
180812
181499
|
const endedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
180813
181500
|
const durationMs = Date.parse(endedAt) - Date.parse(traceStartedAt);
|
|
180814
181501
|
if (info.runtimeSessionId) capturedNativeSessionId = info.runtimeSessionId;
|
|
180815
181502
|
enqueueTrace(async () => {
|
|
180816
|
-
await
|
|
180817
|
-
seq: ++traceSeq,
|
|
181503
|
+
await traceAppender.append([{
|
|
180818
181504
|
eventType: "run.finished",
|
|
180819
181505
|
stream: "runtime",
|
|
180820
181506
|
message: `exit code=${info.code ?? "killed"}`,
|
|
@@ -180823,7 +181509,7 @@ async function startServe(opts) {
|
|
|
180823
181509
|
const usage = info.usage ?? null;
|
|
180824
181510
|
const effectiveModel = info.model ?? chatModel ?? null;
|
|
180825
181511
|
const modelSource = info.model ? "runtime" : chatModelSource;
|
|
180826
|
-
await
|
|
181512
|
+
await traceAppender.update({
|
|
180827
181513
|
status: info.reason === "timeout" ? "timeout" : info.reason === "cancelled" ? "cancelled" : info.code === 0 ? "succeeded" : "failed",
|
|
180828
181514
|
endedAt,
|
|
180829
181515
|
durationMs,
|
|
@@ -180928,6 +181614,7 @@ async function startServe(opts) {
|
|
|
180928
181614
|
unregister: () => {
|
|
180929
181615
|
chatLiveSessions.delete(jobKey);
|
|
180930
181616
|
},
|
|
181617
|
+
traceHealth,
|
|
180931
181618
|
log: (m2) => console.log(m2)
|
|
180932
181619
|
});
|
|
180933
181620
|
console.log(`[chat-recovery] \u91CD\u6302 chat \u8F6E\uFF1Asession=${plan.chatSessionId} run=${plan.runId} node=${daemonId}`);
|
|
@@ -181148,7 +181835,7 @@ async function startServe(opts) {
|
|
|
181148
181835
|
console.warn(`[dispatch] artifact ${artifactId} owner ${actor} \u5DF2\u505C\u7528\uFF0C\u6309 ownerRole=${ownerRole} \u6539\u6D3E\u7ED9 ${replacement.id}${rejected.length ? `\uFF08\u8DF3\u8FC7\u4E0D\u5065\u5EB7\u7684\uFF1A${rejected.join("\u3001")}\uFF09` : ""}`);
|
|
181149
181836
|
return { actor: replacement.id, originalActor: actor, routeReason: "disabled-owner-fallback" };
|
|
181150
181837
|
},
|
|
181151
|
-
provision: async (actorId) => buildActorProvision((await runActors()).service, actorId),
|
|
181838
|
+
provision: async (actorId, artifactId) => buildActorProvision((await runActors()).service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181152
181839
|
resolveActorContext: async (actorId) => buildActorContext((await runActors()).service, actorId),
|
|
181153
181840
|
// 收尾评审的角色分工段(reviewer 此前彼此不知道对方存在 → 越界 / 重复劳动)。
|
|
181154
181841
|
// 职责取自**岗位目录**(配置面),不在代码里硬编码任何岗位——加角色自动就在。
|
|
@@ -181771,7 +182458,7 @@ ${nodeFault}` : "");
|
|
|
181771
182458
|
resolveManager: (id) => resolveManagerBinding(registryStore, id),
|
|
181772
182459
|
schemaTypes: schema.map((d) => d.name),
|
|
181773
182460
|
schemaTypeDescriptions: Object.fromEntries(schema.filter((d) => d.description).map((d) => [d.name, d.description])),
|
|
181774
|
-
provision: (actorId) => buildActorProvision(actors.service, actorId),
|
|
182461
|
+
provision: async (actorId, artifactId) => buildActorProvision(actors.service, actorId, artifactId ? await resolveDispatchScope(artifactId) : void 0),
|
|
181775
182462
|
// 阻塞诊断(proposal D1/D3):派发器运行时信号(queued/fused/backoff/hasInFlight)注入诊断,
|
|
181776
182463
|
// 让协调者把"资源 / 运行时"病因和"图病"分开——资源排队的节点不会被误唤去砍流程。
|
|
181777
182464
|
runtimeSignals: (id) => {
|
|
@@ -181811,6 +182498,9 @@ ${nodeFault}` : "");
|
|
|
181811
182498
|
if (c) return Promise.resolve(c.kill()).then(() => true).catch(() => false);
|
|
181812
182499
|
return dispatcherByJob.get(jobKey)?.killSession(jobKey) ?? Promise.resolve(false);
|
|
181813
182500
|
},
|
|
182501
|
+
// trace 写不进去的 run:冻结的事件钟是"观测降级"不是"真静默",按"信息不足→不判"跳过、交 wallClock
|
|
182502
|
+
// 兜底(brief §限制1 / 诊断 §6)。真卡死的 run trace 健康、isTraceHealthy=true,照常被杀。
|
|
182503
|
+
isTraceHealthy: (sessionId) => traceHealth.isHealthy(sessionId),
|
|
181814
182504
|
now: Date.now(),
|
|
181815
182505
|
silentThresholdMs,
|
|
181816
182506
|
log: (m2) => console.log(m2)
|
|
@@ -181973,7 +182663,7 @@ var SessionManager = class {
|
|
|
181973
182663
|
|
|
181974
182664
|
// ../cli/src/daemon/ws-client.ts
|
|
181975
182665
|
init_wrapper();
|
|
181976
|
-
var
|
|
182666
|
+
var import_node_os9 = require("node:os");
|
|
181977
182667
|
var import_node_crypto38 = require("node:crypto");
|
|
181978
182668
|
init_src5();
|
|
181979
182669
|
|
|
@@ -182029,7 +182719,7 @@ function detectRuntimes() {
|
|
|
182029
182719
|
|
|
182030
182720
|
// ../cli/src/daemon/workdir-handler.ts
|
|
182031
182721
|
var import_node_fs16 = __toESM(require("node:fs"), 1);
|
|
182032
|
-
var
|
|
182722
|
+
var import_node_path20 = __toESM(require("node:path"), 1);
|
|
182033
182723
|
init_src4();
|
|
182034
182724
|
init_src();
|
|
182035
182725
|
var WORKDIR_READ_MAX_BYTES2 = 2 * 1024 * 1024;
|
|
@@ -182048,10 +182738,10 @@ function isSensitiveSegment(segment) {
|
|
|
182048
182738
|
}
|
|
182049
182739
|
function relPathIsSensitive(rel) {
|
|
182050
182740
|
if (!rel) return false;
|
|
182051
|
-
return rel.split(
|
|
182741
|
+
return rel.split(import_node_path20.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
|
|
182052
182742
|
}
|
|
182053
182743
|
function withinBase(p2, base) {
|
|
182054
|
-
return p2 === base || p2.startsWith(base +
|
|
182744
|
+
return p2 === base || p2.startsWith(base + import_node_path20.default.sep);
|
|
182055
182745
|
}
|
|
182056
182746
|
function normalizeRel(raw) {
|
|
182057
182747
|
const trimmed = (raw ?? "").trim();
|
|
@@ -182068,7 +182758,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
|
|
|
182068
182758
|
} catch {
|
|
182069
182759
|
return null;
|
|
182070
182760
|
}
|
|
182071
|
-
return isLegacy ?
|
|
182761
|
+
return isLegacy ? import_node_path20.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path20.default.join(trustedRootReal, "sessions", dirKind);
|
|
182072
182762
|
}
|
|
182073
182763
|
async function resolveWithinWorkdir(req) {
|
|
182074
182764
|
const dirKind = sessionDirKind(req.runtimeKind);
|
|
@@ -182086,11 +182776,11 @@ async function resolveWithinWorkdir(req) {
|
|
|
182086
182776
|
} catch {
|
|
182087
182777
|
return { ok: false, code: "NOT_FOUND" };
|
|
182088
182778
|
}
|
|
182089
|
-
if (
|
|
182779
|
+
if (import_node_path20.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
|
|
182090
182780
|
const rel = normalizeRel(req.path);
|
|
182091
|
-
const requested =
|
|
182781
|
+
const requested = import_node_path20.default.resolve(base, rel);
|
|
182092
182782
|
if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182093
|
-
const cleanRel = base === requested ? "" :
|
|
182783
|
+
const cleanRel = base === requested ? "" : import_node_path20.default.relative(base, requested);
|
|
182094
182784
|
if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
|
|
182095
182785
|
let real;
|
|
182096
182786
|
try {
|
|
@@ -182100,7 +182790,7 @@ async function resolveWithinWorkdir(req) {
|
|
|
182100
182790
|
return { ok: false, code: "PATH_ESCAPE" };
|
|
182101
182791
|
}
|
|
182102
182792
|
if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
|
|
182103
|
-
const realRel = base === real ? "" :
|
|
182793
|
+
const realRel = base === real ? "" : import_node_path20.default.relative(base, real);
|
|
182104
182794
|
if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
|
|
182105
182795
|
return { ok: true, base, real };
|
|
182106
182796
|
}
|
|
@@ -182136,7 +182826,7 @@ async function handleWorkdirList(req) {
|
|
|
182136
182826
|
const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
|
|
182137
182827
|
const entries = [];
|
|
182138
182828
|
for (const d of slice) {
|
|
182139
|
-
const abs =
|
|
182829
|
+
const abs = import_node_path20.default.join(anchor, d.name);
|
|
182140
182830
|
try {
|
|
182141
182831
|
const st = await import_node_fs16.default.promises.lstat(abs);
|
|
182142
182832
|
if (st.isSymbolicLink()) continue;
|
|
@@ -182168,7 +182858,7 @@ async function verifyOpenedFd(fh, base, fallback) {
|
|
|
182168
182858
|
const fdReal = await fdCanonicalPath(fh);
|
|
182169
182859
|
if (fdReal === null) return { anchor: fallback };
|
|
182170
182860
|
if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
|
|
182171
|
-
const fdRel = base === fdReal ? "" :
|
|
182861
|
+
const fdRel = base === fdReal ? "" : import_node_path20.default.relative(base, fdReal);
|
|
182172
182862
|
if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
|
|
182173
182863
|
return { anchor: `/proc/self/fd/${fh.fd}` };
|
|
182174
182864
|
}
|
|
@@ -182257,7 +182947,7 @@ function looksBinary(bytes) {
|
|
|
182257
182947
|
function contentTypeFor(absPath, bytes) {
|
|
182258
182948
|
const sniffed = sniffContentType(bytes);
|
|
182259
182949
|
if (sniffed) return sniffed;
|
|
182260
|
-
const ext =
|
|
182950
|
+
const ext = import_node_path20.default.extname(absPath).toLowerCase();
|
|
182261
182951
|
if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
|
|
182262
182952
|
return looksBinary(bytes) ? "application/octet-stream" : "text/plain; charset=utf-8";
|
|
182263
182953
|
}
|
|
@@ -182600,7 +183290,7 @@ var DaemonWsClient = class {
|
|
|
182600
183290
|
buildMeta() {
|
|
182601
183291
|
const activeSessions = this.sessions.activeSessions();
|
|
182602
183292
|
return {
|
|
182603
|
-
hostname: (0,
|
|
183293
|
+
hostname: (0, import_node_os9.hostname)(),
|
|
182604
183294
|
adapters: this.adapters,
|
|
182605
183295
|
...this.reportRuntimes ? { runtimes: this.runtimes } : {},
|
|
182606
183296
|
nodeVersion: process.version,
|
|
@@ -182630,18 +183320,18 @@ var RuntimeRouterAdapter = class {
|
|
|
182630
183320
|
|
|
182631
183321
|
// ../cli/src/daemon/reap-claude-projects.ts
|
|
182632
183322
|
var import_node_fs17 = __toESM(require("node:fs"), 1);
|
|
182633
|
-
var
|
|
182634
|
-
var
|
|
183323
|
+
var import_node_os10 = __toESM(require("node:os"), 1);
|
|
183324
|
+
var import_node_path21 = __toESM(require("node:path"), 1);
|
|
182635
183325
|
function claudeProjectSlug(cwd) {
|
|
182636
183326
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
182637
183327
|
}
|
|
182638
183328
|
function claudeProjectsRoot() {
|
|
182639
|
-
const configDir = process.env["CLAUDE_CONFIG_DIR"] ||
|
|
182640
|
-
return
|
|
183329
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path21.default.join(import_node_os10.default.homedir(), ".claude");
|
|
183330
|
+
return import_node_path21.default.join(configDir, "projects");
|
|
182641
183331
|
}
|
|
182642
183332
|
function reapClaudeProjects(workdir, runtimeKind) {
|
|
182643
183333
|
if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
|
|
182644
|
-
const dir =
|
|
183334
|
+
const dir = import_node_path21.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
|
|
182645
183335
|
if (!import_node_fs17.default.existsSync(dir)) return;
|
|
182646
183336
|
try {
|
|
182647
183337
|
import_node_fs17.default.rmSync(dir, { recursive: true, force: true });
|
|
@@ -182651,7 +183341,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
|
|
|
182651
183341
|
|
|
182652
183342
|
// ../cli/src/node.ts
|
|
182653
183343
|
init_src4();
|
|
182654
|
-
var
|
|
183344
|
+
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
182655
183345
|
var RESILIENCE = {
|
|
182656
183346
|
codex: { idleTimeoutMs: 6e5 }
|
|
182657
183347
|
};
|
|
@@ -182715,7 +183405,7 @@ async function startNode(opts) {
|
|
|
182715
183405
|
console.log(`[oasis node] ${opts.nodeId} \u2192 ${opts.serverUrl}`);
|
|
182716
183406
|
client.start();
|
|
182717
183407
|
const { workRoot, legacyRoot } = resolveWorkRoots(opts.workRoot);
|
|
182718
|
-
const workRootIsEphemeral = workRoot.startsWith(
|
|
183408
|
+
const workRootIsEphemeral = workRoot.startsWith(import_node_os11.default.tmpdir());
|
|
182719
183409
|
if (opts.gcEnabled === false && !workRootIsEphemeral) {
|
|
182720
183410
|
console.warn(`[oasis node] \u26A0 \u56DE\u6536\u5668\u5DF2\u5173\u95ED\uFF0C\u800C\u5DE5\u4F5C\u533A\u5728\u6301\u4E45\u76D8\uFF08${workRoot}\uFF09\u2014\u2014\u6CA1\u6709\u4EFB\u4F55\u5783\u573E\u56DE\u6536\uFF0C\u5B9E\u6D4B\u4E24\u5468\u4F1A\u6DA8 12.4GB\u3002\u4EC5\u4F9B\u6392\u969C\uFF0C\u522B\u957F\u671F\u8FD9\u4E48\u8DD1\u3002`);
|
|
182721
183411
|
}
|
|
@@ -182750,7 +183440,7 @@ async function startNode(opts) {
|
|
|
182750
183440
|
var import_node_child_process16 = require("node:child_process");
|
|
182751
183441
|
var import_node_fs18 = require("node:fs");
|
|
182752
183442
|
var import_node_crypto39 = require("node:crypto");
|
|
182753
|
-
var
|
|
183443
|
+
var import_node_os12 = require("node:os");
|
|
182754
183444
|
function linuxMachineId() {
|
|
182755
183445
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
182756
183446
|
try {
|
|
@@ -182790,13 +183480,13 @@ function windowsMachineId() {
|
|
|
182790
183480
|
}
|
|
182791
183481
|
function fallbackFingerprint() {
|
|
182792
183482
|
const macs = [];
|
|
182793
|
-
const ifaces = (0,
|
|
183483
|
+
const ifaces = (0, import_node_os12.networkInterfaces)();
|
|
182794
183484
|
for (const name of Object.keys(ifaces).sort()) {
|
|
182795
183485
|
for (const ni of ifaces[name] ?? []) {
|
|
182796
183486
|
if (!ni.internal && ni.mac && ni.mac !== "00:00:00:00:00:00") macs.push(ni.mac);
|
|
182797
183487
|
}
|
|
182798
183488
|
}
|
|
182799
|
-
return `fallback:${(0,
|
|
183489
|
+
return `fallback:${(0, import_node_os12.hostname)()}:${macs.sort()[0] ?? "no-mac"}`;
|
|
182800
183490
|
}
|
|
182801
183491
|
function machineFingerprint() {
|
|
182802
183492
|
const byOs = process.platform === "darwin" ? macMachineId() : process.platform === "win32" ? windowsMachineId() : linuxMachineId();
|
|
@@ -182806,7 +183496,7 @@ var defaultSources = {
|
|
|
182806
183496
|
machineFingerprint,
|
|
182807
183497
|
osUser: () => {
|
|
182808
183498
|
try {
|
|
182809
|
-
return (0,
|
|
183499
|
+
return (0, import_node_os12.userInfo)().username;
|
|
182810
183500
|
} catch {
|
|
182811
183501
|
return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
|
|
182812
183502
|
}
|
|
@@ -183810,6 +184500,19 @@ var COMMAND_DECLS = {
|
|
|
183810
184500
|
description: "\u4EA4\u4ED8\u7269\u6587\u6863\u4F53\u7CFB\u64CD\u4F5C\uFF08artifact revision \u5B50\u547D\u4EE4\u96C6\uFF09\u3002",
|
|
183811
184501
|
subCommands: ["artifact revision register", "artifact revision approve", "artifact revision reject"],
|
|
183812
184502
|
examples: ['oasis artifact revision register --project oasis --artifact-id artifact:dev:abc --type dev --title "v1.0" --version 1 --content-ref ref-001']
|
|
184503
|
+
},
|
|
184504
|
+
var: {
|
|
184505
|
+
usage: "oasis var <reveal> ...",
|
|
184506
|
+
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",
|
|
184507
|
+
subCommands: ["var reveal"],
|
|
184508
|
+
examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD"]
|
|
184509
|
+
},
|
|
184510
|
+
"var reveal": {
|
|
184511
|
+
usage: "oasis var reveal <key> [--source <tag>]",
|
|
184512
|
+
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",
|
|
184513
|
+
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" }],
|
|
184514
|
+
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 }],
|
|
184515
|
+
examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var reveal oasis://var/GLM_API_KEY --source smoke-test"]
|
|
183813
184516
|
}
|
|
183814
184517
|
};
|
|
183815
184518
|
function formatCommandHelp(decl) {
|
|
@@ -185475,6 +186178,33 @@ ${res.warning}`);
|
|
|
185475
186178
|
println(`\u5DF2\u5220\u9664 ${memId}`);
|
|
185476
186179
|
break;
|
|
185477
186180
|
}
|
|
186181
|
+
case "var": {
|
|
186182
|
+
const sub = positional[0];
|
|
186183
|
+
if (sub === "reveal") {
|
|
186184
|
+
const rawKey = needPos(positional, 1, "oasis var reveal <key> [--source <tag>]");
|
|
186185
|
+
const key = parseVarRef(rawKey) ?? rawKey;
|
|
186186
|
+
const source = flags.get("source");
|
|
186187
|
+
try {
|
|
186188
|
+
const out = await api.request("POST", "/api/variables/reveal", {
|
|
186189
|
+
key,
|
|
186190
|
+
...source ? { source } : {}
|
|
186191
|
+
});
|
|
186192
|
+
println(out.value);
|
|
186193
|
+
} catch (e) {
|
|
186194
|
+
if (e instanceof ApiRequestError && e.status === 403) {
|
|
186195
|
+
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`);
|
|
186196
|
+
}
|
|
186197
|
+
if (e instanceof ApiRequestError && e.status === 429) {
|
|
186198
|
+
const scope = e.body?.scope ?? "session";
|
|
186199
|
+
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`);
|
|
186200
|
+
}
|
|
186201
|
+
throw e;
|
|
186202
|
+
}
|
|
186203
|
+
break;
|
|
186204
|
+
}
|
|
186205
|
+
throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4\uFF1Aoasis var ${sub ?? ""}
|
|
186206
|
+
\u53EF\u7528\uFF1Aoasis var reveal <key> [--source <tag>]`);
|
|
186207
|
+
}
|
|
185478
186208
|
case "pin": {
|
|
185479
186209
|
const { message } = await api.cmd("pin", {
|
|
185480
186210
|
artifactId: needPos(positional, 0, "oasis pin <artifactId> --to u --rev r"),
|
|
@@ -186174,7 +186904,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
186174
186904
|
}
|
|
186175
186905
|
|
|
186176
186906
|
// src/index.ts
|
|
186177
|
-
var PKG_VERSION = true ? "0.1.
|
|
186907
|
+
var PKG_VERSION = true ? "0.1.90" : "dev";
|
|
186178
186908
|
var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
|
|
186179
186909
|
var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
|
|
186180
186910
|
var PID_FILE = path29.join(OASIS_DIR, "node.pid");
|