oasis_test 0.1.89 → 0.1.91

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.
Files changed (2) hide show
  1. package/dist/index.js +368 -130
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -6001,6 +6001,13 @@ var init_dispatcher = __esm({
6001
6001
  * 是否相对本会话推进过**(上游产新版才动 pin,天然排除驳回/人类改单)。运行时态、不进 oplog/重放,
6002
6002
  * 与 inFlight 同生同灭。 */
6003
6003
  inFlightPins = /* @__PURE__ */ new Map();
6004
+ /**
6005
+ * 本次会话的凭据清理器,与 inFlight 同生同灭。
6006
+ * **必须在「只有槽位主人才能解锁」那个守卫里调**(见 handleSessionExit)——
6007
+ * 无差别调用 = 拿僵尸会话的死讯删掉**活会话正在用的** creds 文件,
6008
+ * 那比不清理更糟:活着的 agent 下一次 `gh` 就炸,且现场看起来像凭据凭空消失。
6009
+ */
6010
+ inFlightCleanup = /* @__PURE__ */ new Map();
6004
6011
  /** ADR-0094:本会话已确认不支持原生 append(codex/subprocess 远端报 unsupported,或会话在收尾)——
6005
6012
  * 停投,回落"等会话退出 + fresh 重派"。与 inFlight 同生同灭。 */
6006
6013
  appendSkip = /* @__PURE__ */ new Set();
@@ -6934,6 +6941,8 @@ var init_dispatcher = __esm({
6934
6941
  ...Object.keys(jobEnv).length > 0 ? { env: jobEnv } : {},
6935
6942
  ...provisioned?.wrapperPaths && provisioned.wrapperPaths.length > 0 ? { wrapperPaths: provisioned.wrapperPaths } : {},
6936
6943
  ...provisioned?.requiredTools && provisioned.requiredTools.length > 0 ? { requiredTools: provisioned.requiredTools } : {},
6944
+ // 凭据本体随 job 下发,供**节点侧本机注入**(见上方 provision 注释)。
6945
+ ...provisioned?.connectorCreds && provisioned.connectorCreds.length > 0 ? { connectorCreds: provisioned.connectorCreds } : {},
6937
6946
  // ADR-0078 D1/D3:把本次派发的 id 交给 adapter 当 handle.id——于是
6938
6947
  // `handle.id` = `agent_runs.id` = token 的 dispatchId claim,三处同值。
6939
6948
  dispatchId: attempt
@@ -6965,6 +6974,7 @@ var init_dispatcher = __esm({
6965
6974
  }
6966
6975
  this.inFlight.set(jobKey, session);
6967
6976
  this.inFlightActor.set(jobKey, dispatchSpec.actor);
6977
+ if (provisioned?.cleanup) this.inFlightCleanup.set(jobKey, provisioned.cleanup);
6968
6978
  const dispatchedAtMs = Date.now();
6969
6979
  this.inFlightStartedAt.set(jobKey, dispatchedAtMs);
6970
6980
  const seqAtDispatch = seqNow;
@@ -7059,6 +7069,12 @@ var init_dispatcher = __esm({
7059
7069
  this.inFlightStartedAt.delete(jobKey);
7060
7070
  this.inFlightPins.delete(jobKey);
7061
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
+ }
7062
7078
  }
7063
7079
  const seqAtExit = kernel.model.lastSeq.get(spec.artifactId) ?? 0;
7064
7080
  const exitSessionKey = this.produceSessionKeyFor(spec);
@@ -142160,14 +142176,48 @@ async function prepareConnectorsForJob(job, deps) {
142160
142176
  }
142161
142177
  const keptLocal = localWrappers.filter((p2) => isStagedWrapperUsable(p2));
142162
142178
  const keptRemote = remoteWrappers.filter((p2) => (0, import_node_fs5.existsSync)(p2));
142163
- const dropped = remoteWrappers.length - keptRemote.length + (localWrappers.length - keptLocal.length);
142164
- if (dropped > 0) log("[node-connectors]", `\u4E22\u5F03 ${dropped} \u6761\u672C\u673A\u4E0D\u53EF\u7528\u7684 wrapper \u8DEF\u5F84`);
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
+ }
142165
142191
  const basePath = job.env?.["PATH"] ?? process.env["PATH"] ?? "";
142166
142192
  const toolsBin = connectorToolsBinDir();
142167
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
+ }
142168
142218
  const preparedJob = {
142169
142219
  ...job,
142170
- env: { ...job.env ?? {}, ...envOverrides, PATH: pathWithTools },
142220
+ env: jobEnv,
142171
142221
  wrapperPaths: [...keptLocal, ...keptRemote]
142172
142222
  };
142173
142223
  if (injected.size > 0 && (job.limits?.wallClockMs ?? 0) > SESSION_CREDENTIAL_RENEW_INTERVAL_MS) {
@@ -142225,11 +142275,14 @@ function fetchCredentialsFromServer(job) {
142225
142275
  return body.connectorCreds ?? [];
142226
142276
  };
142227
142277
  }
142228
- var import_node_fs5, SESSION_CREDENTIAL_RENEW_INTERVAL_MS;
142278
+ var import_node_fs5, import_promises6, import_node_os5, import_node_path9, SESSION_CREDENTIAL_RENEW_INTERVAL_MS;
142229
142279
  var init_prepare_job = __esm({
142230
142280
  "../connectors/src/prepare-job.ts"() {
142231
142281
  "use strict";
142232
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");
142233
142286
  init_base();
142234
142287
  init_registry2();
142235
142288
  init_logger();
@@ -142572,8 +142625,8 @@ function materializeFiles(dir, files) {
142572
142625
  if (!files) return;
142573
142626
  for (const [rel, content] of Object.entries(files)) {
142574
142627
  try {
142575
- const file = import_node_path9.default.join(dir, rel);
142576
- import_node_fs6.default.mkdirSync(import_node_path9.default.dirname(file), { recursive: true });
142628
+ const file = import_node_path10.default.join(dir, rel);
142629
+ import_node_fs6.default.mkdirSync(import_node_path10.default.dirname(file), { recursive: true });
142577
142630
  import_node_fs6.default.writeFileSync(file, content);
142578
142631
  } catch {
142579
142632
  }
@@ -142589,7 +142642,7 @@ function resolveLegacyWorkRoot(workRoot) {
142589
142642
  if (workRoot) return workRoot;
142590
142643
  const env = process.env["OASIS_WORK_ROOT"];
142591
142644
  if (env) return env;
142592
- return import_node_os5.default.tmpdir();
142645
+ return import_node_os6.default.tmpdir();
142593
142646
  }
142594
142647
  function resolveWorkRoots(workRoot) {
142595
142648
  return { workRoot: resolveWorkRoot(workRoot), legacyRoot: resolveLegacyWorkRoot(workRoot) };
@@ -142600,7 +142653,7 @@ function slug5(workdirKey) {
142600
142653
  return `${safe}-${h}`;
142601
142654
  }
142602
142655
  function sessionDirFor(workRoot, runtimeKind, workdirKey) {
142603
- return import_node_path9.default.join(resolveWorkRoot(workRoot), "sessions", runtimeKind, slug5(workdirKey));
142656
+ return import_node_path10.default.join(resolveWorkRoot(workRoot), "sessions", runtimeKind, slug5(workdirKey));
142604
142657
  }
142605
142658
  function sessionDirKind(runtimeKind) {
142606
142659
  return runtimeKind === "claude-code" ? "claude" : runtimeKind;
@@ -142613,20 +142666,20 @@ function resolveSessionDirWithLegacy(args) {
142613
142666
  return import_node_fs6.default.existsSync(legacy) ? legacy : fresh;
142614
142667
  }
142615
142668
  function oneShotDirFor(workRoot, runtimeKind) {
142616
- const base = import_node_path9.default.join(resolveWorkRoot(workRoot), "tmp");
142669
+ const base = import_node_path10.default.join(resolveWorkRoot(workRoot), "tmp");
142617
142670
  import_node_fs6.default.mkdirSync(base, { recursive: true });
142618
- return import_node_fs6.default.mkdtempSync(import_node_path9.default.join(base, `${runtimeKind}-`));
142671
+ return import_node_fs6.default.mkdtempSync(import_node_path10.default.join(base, `${runtimeKind}-`));
142619
142672
  }
142620
142673
  function writeMeta(dir, meta) {
142621
142674
  try {
142622
- import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, META_FILE), `${JSON.stringify(meta, null, 2)}
142675
+ import_node_fs6.default.writeFileSync(import_node_path10.default.join(dir, META_FILE), `${JSON.stringify(meta, null, 2)}
142623
142676
  `);
142624
142677
  } catch {
142625
142678
  }
142626
142679
  }
142627
142680
  function readMeta(dir) {
142628
142681
  try {
142629
- const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, META_FILE), "utf8"));
142682
+ const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, META_FILE), "utf8"));
142630
142683
  if (!raw || typeof raw !== "object") return null;
142631
142684
  const m2 = raw;
142632
142685
  return typeof m2.kind === "string" && typeof m2.createdAt === "string" ? m2 : null;
@@ -142655,14 +142708,14 @@ function lockWorkdir(dir, pid, holder, workdirKey) {
142655
142708
  ...workdirKey !== void 0 ? { workdirKey } : {}
142656
142709
  };
142657
142710
  try {
142658
- import_node_fs6.default.writeFileSync(import_node_path9.default.join(dir, LOCK_FILE), `${JSON.stringify(lock)}
142711
+ import_node_fs6.default.writeFileSync(import_node_path10.default.join(dir, LOCK_FILE), `${JSON.stringify(lock)}
142659
142712
  `);
142660
142713
  } catch {
142661
142714
  }
142662
142715
  }
142663
142716
  function readLock(dir) {
142664
142717
  try {
142665
- const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, LOCK_FILE), "utf8"));
142718
+ const raw = JSON.parse(import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, LOCK_FILE), "utf8"));
142666
142719
  if (!raw || typeof raw !== "object") return null;
142667
142720
  const l = raw;
142668
142721
  return Number.isInteger(l.pid) && l.pid > 0 ? l : null;
@@ -142672,14 +142725,14 @@ function readLock(dir) {
142672
142725
  }
142673
142726
  function unlockWorkdir(dir) {
142674
142727
  try {
142675
- import_node_fs6.default.unlinkSync(import_node_path9.default.join(dir, LOCK_FILE));
142728
+ import_node_fs6.default.unlinkSync(import_node_path10.default.join(dir, LOCK_FILE));
142676
142729
  } catch {
142677
142730
  }
142678
142731
  }
142679
142732
  function isWorkdirLive(dir) {
142680
142733
  let raw;
142681
142734
  try {
142682
- raw = import_node_fs6.default.readFileSync(import_node_path9.default.join(dir, LOCK_FILE), "utf8");
142735
+ raw = import_node_fs6.default.readFileSync(import_node_path10.default.join(dir, LOCK_FILE), "utf8");
142683
142736
  } catch {
142684
142737
  return false;
142685
142738
  }
@@ -142696,7 +142749,7 @@ function clearWorkdir(dir) {
142696
142749
  );
142697
142750
  }
142698
142751
  for (const entry of import_node_fs6.default.readdirSync(dir)) {
142699
- import_node_fs6.default.rmSync(import_node_path9.default.join(dir, entry), { recursive: true, force: true });
142752
+ import_node_fs6.default.rmSync(import_node_path10.default.join(dir, entry), { recursive: true, force: true });
142700
142753
  }
142701
142754
  }
142702
142755
  function prepareWorkdir(args) {
@@ -142726,19 +142779,19 @@ function prepareWorkdir(args) {
142726
142779
  return dir;
142727
142780
  }
142728
142781
  function legacyChatSessionDir(workRoot, rtId) {
142729
- return import_node_path9.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
142782
+ return import_node_path10.default.join(resolveLegacyWorkRoot(workRoot), "oasis-chat-sessions", rtId.replace(/[^a-zA-Z0-9_-]+/g, "_"));
142730
142783
  }
142731
- var import_node_crypto9, import_node_fs6, import_node_os5, import_node_path9, META_FILE, LOCK_FILE, NEW_WORK_ROOT, LEGACY_ROOTS, LEGACY_ONESHOT_PREFIX;
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;
142732
142785
  var init_session_paths = __esm({
142733
142786
  "../adapters/src/_core/session-paths.ts"() {
142734
142787
  "use strict";
142735
142788
  import_node_crypto9 = require("node:crypto");
142736
142789
  import_node_fs6 = __toESM(require("node:fs"), 1);
142737
- import_node_os5 = __toESM(require("node:os"), 1);
142738
- import_node_path9 = __toESM(require("node:path"), 1);
142790
+ import_node_os6 = __toESM(require("node:os"), 1);
142791
+ import_node_path10 = __toESM(require("node:path"), 1);
142739
142792
  META_FILE = ".oasis-meta.json";
142740
142793
  LOCK_FILE = ".oasis-lock";
142741
- NEW_WORK_ROOT = () => import_node_path9.default.join(import_node_os5.default.homedir(), ".oasis", "work");
142794
+ NEW_WORK_ROOT = () => import_node_path10.default.join(import_node_os6.default.homedir(), ".oasis", "work");
142742
142795
  LEGACY_ROOTS = ["oasis-chat-sessions", "oasis-transcripts"];
142743
142796
  LEGACY_ONESHOT_PREFIX = "oasis-session-";
142744
142797
  }
@@ -143960,7 +144013,7 @@ async function discoverACPModels(bin, provider, args = ["acp"]) {
143960
144013
  clientCapabilities: {}
143961
144014
  });
143962
144015
  try {
143963
- tmpDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path10.join)((0, import_node_os6.tmpdir)(), `oasis-acp-${provider}-`));
144016
+ tmpDir = (0, import_node_fs7.mkdtempSync)((0, import_node_path11.join)((0, import_node_os7.tmpdir)(), `oasis-acp-${provider}-`));
143964
144017
  } catch {
143965
144018
  return fail();
143966
144019
  }
@@ -144016,14 +144069,14 @@ function parseACPSessionNewModels(result) {
144016
144069
  async function discoverOpenclawModels(bin) {
144017
144070
  throw new Error("discoverOpenclawModels: TODO");
144018
144071
  }
144019
- var import_node_child_process9, import_node_fs7, import_node_os6, import_node_path10, modelCache, CACHE_TTL_MS;
144072
+ var import_node_child_process9, import_node_fs7, import_node_os7, import_node_path11, modelCache, CACHE_TTL_MS;
144020
144073
  var init_models = __esm({
144021
144074
  "../adapters/src/_core/models.ts"() {
144022
144075
  "use strict";
144023
144076
  import_node_child_process9 = require("node:child_process");
144024
144077
  import_node_fs7 = require("node:fs");
144025
- import_node_os6 = require("node:os");
144026
- import_node_path10 = require("node:path");
144078
+ import_node_os7 = require("node:os");
144079
+ import_node_path11 = require("node:path");
144027
144080
  modelCache = /* @__PURE__ */ new Map();
144028
144081
  CACHE_TTL_MS = 6e4;
144029
144082
  }
@@ -146590,7 +146643,7 @@ function dirSizeBytes(dir) {
146590
146643
  return;
146591
146644
  }
146592
146645
  for (const e of entries) {
146593
- const p2 = import_node_path11.default.join(d, e.name);
146646
+ const p2 = import_node_path12.default.join(d, e.name);
146594
146647
  if (e.isSymbolicLink()) continue;
146595
146648
  if (e.isDirectory()) {
146596
146649
  walk(p2);
@@ -146607,40 +146660,40 @@ function dirSizeBytes(dir) {
146607
146660
  }
146608
146661
  function listWorkdirs(workRoot, legacyRoot) {
146609
146662
  const out = [];
146610
- const sessions = import_node_path11.default.join(workRoot, "sessions");
146663
+ const sessions = import_node_path12.default.join(workRoot, "sessions");
146611
146664
  try {
146612
146665
  for (const kind of import_node_fs8.default.readdirSync(sessions)) {
146613
- const kindDir = import_node_path11.default.join(sessions, kind);
146666
+ const kindDir = import_node_path12.default.join(sessions, kind);
146614
146667
  try {
146615
- for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(import_node_path11.default.join(kindDir, slug6));
146668
+ for (const slug6 of import_node_fs8.default.readdirSync(kindDir)) out.push(import_node_path12.default.join(kindDir, slug6));
146616
146669
  } catch {
146617
146670
  }
146618
146671
  }
146619
146672
  } catch {
146620
146673
  }
146621
- const tmp = import_node_path11.default.join(workRoot, "tmp");
146674
+ const tmp = import_node_path12.default.join(workRoot, "tmp");
146622
146675
  try {
146623
- for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(import_node_path11.default.join(tmp, d));
146676
+ for (const d of import_node_fs8.default.readdirSync(tmp)) out.push(import_node_path12.default.join(tmp, d));
146624
146677
  } catch {
146625
146678
  }
146626
146679
  for (const legacy of LEGACY_ROOTS) {
146627
- const root = import_node_path11.default.join(legacyRoot, legacy);
146680
+ const root = import_node_path12.default.join(legacyRoot, legacy);
146628
146681
  try {
146629
- for (const d of import_node_fs8.default.readdirSync(root)) out.push(import_node_path11.default.join(root, d));
146682
+ for (const d of import_node_fs8.default.readdirSync(root)) out.push(import_node_path12.default.join(root, d));
146630
146683
  } catch {
146631
146684
  }
146632
146685
  }
146633
146686
  try {
146634
146687
  for (const d of import_node_fs8.default.readdirSync(legacyRoot)) {
146635
- if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(import_node_path11.default.join(legacyRoot, d));
146688
+ if (d.startsWith(LEGACY_ONESHOT_PREFIX)) out.push(import_node_path12.default.join(legacyRoot, d));
146636
146689
  }
146637
146690
  } catch {
146638
146691
  }
146639
146692
  return [...new Set(out)];
146640
146693
  }
146641
146694
  function kindFromPath(workRoot, dir) {
146642
- const rel = import_node_path11.default.relative(workRoot, dir);
146643
- const parts = rel.split(import_node_path11.default.sep);
146695
+ const rel = import_node_path12.default.relative(workRoot, dir);
146696
+ const parts = rel.split(import_node_path12.default.sep);
146644
146697
  if (parts[0] === "sessions" && parts[1]) return parts[1];
146645
146698
  if (parts[0] === "tmp" && parts[1]) return parts[1].replace(/-[^-]*$/, "");
146646
146699
  return void 0;
@@ -146682,7 +146735,7 @@ async function runGcSweep(deps) {
146682
146735
  let deleted = 0;
146683
146736
  for (const d of decisions) {
146684
146737
  if (d.action !== "delete") continue;
146685
- if (import_node_fs8.default.existsSync(import_node_path11.default.join(d.dir, LOCK_FILE)) && isWorkdirLive(d.dir)) {
146738
+ if (import_node_fs8.default.existsSync(import_node_path12.default.join(d.dir, LOCK_FILE)) && isWorkdirLive(d.dir)) {
146686
146739
  log3(`[gc] \u8DF3\u8FC7 ${d.dir}\uFF1A\u6267\u884C\u524D\u590D\u67E5\u53D1\u73B0\u5DF2\u88AB\u5360\u7528`);
146687
146740
  continue;
146688
146741
  }
@@ -146733,12 +146786,12 @@ function startGcLoop(deps) {
146733
146786
  clearInterval(timer);
146734
146787
  };
146735
146788
  }
146736
- var import_node_fs8, import_node_path11;
146789
+ var import_node_fs8, import_node_path12;
146737
146790
  var init_gc_loop = __esm({
146738
146791
  "../adapters/src/_core/gc-loop.ts"() {
146739
146792
  "use strict";
146740
146793
  import_node_fs8 = __toESM(require("node:fs"), 1);
146741
- import_node_path11 = __toESM(require("node:path"), 1);
146794
+ import_node_path12 = __toESM(require("node:path"), 1);
146742
146795
  init_session_paths();
146743
146796
  init_workdir_gc();
146744
146797
  }
@@ -146774,14 +146827,14 @@ var init_src4 = __esm({
146774
146827
  });
146775
146828
 
146776
146829
  // ../connectors/src/connector-adapter.ts
146777
- var import_promises6, import_node_fs9, import_node_os7, import_node_path12, ConnectorAwareAdapter;
146830
+ var import_promises7, import_node_fs9, import_node_os8, import_node_path13, ConnectorAwareAdapter;
146778
146831
  var init_connector_adapter = __esm({
146779
146832
  "../connectors/src/connector-adapter.ts"() {
146780
146833
  "use strict";
146781
- import_promises6 = require("node:fs/promises");
146834
+ import_promises7 = require("node:fs/promises");
146782
146835
  import_node_fs9 = require("node:fs");
146783
- import_node_os7 = require("node:os");
146784
- import_node_path12 = require("node:path");
146836
+ import_node_os8 = require("node:os");
146837
+ import_node_path13 = require("node:path");
146785
146838
  init_src4();
146786
146839
  init_base();
146787
146840
  init_prepare_job();
@@ -146804,11 +146857,11 @@ var init_connector_adapter = __esm({
146804
146857
  const wrapperPaths = [...prepared.job.wrapperPaths ?? [], ...sentinelWrappers];
146805
146858
  let extraEnv = { ...strippedEnv };
146806
146859
  if (wrapperPaths.length > 0) {
146807
- const wrapperBinDir = await (0, import_promises6.mkdtemp)((0, import_node_path12.join)((0, import_node_os7.tmpdir)(), "oasis-wrappers-"));
146808
- await (0, import_promises6.mkdir)(wrapperBinDir, { recursive: true });
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 });
146809
146862
  for (const wp of wrapperPaths) {
146810
- const linkName = (0, import_node_path12.basename)(wp).replace(/\.sh$/, "");
146811
- await (0, import_promises6.symlink)(wp, (0, import_node_path12.join)(wrapperBinDir, linkName));
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));
146812
146865
  }
146813
146866
  extraEnv = { ...extraEnv, PATH: [wrapperBinDir, extraEnv["PATH"] ?? ""].filter(Boolean).join(":") };
146814
146867
  log("[adapter]", ` connectors injected +${Date.now() - t0}ms wrappers=${wrapperPaths.length}`);
@@ -149595,12 +149648,12 @@ async function startOasisServer(opts) {
149595
149648
  const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
149596
149649
  if (actorCtx) {
149597
149650
  const { mkdtempSync: mkdtempSync5, mkdirSync: mkdirSync21, writeFileSync: writeFileSync13 } = await import("node:fs");
149598
- const { join: join31, dirname: dirname24 } = await import("node:path");
149599
- const { tmpdir: tmpdir9 } = await import("node:os");
149600
- const dir = mkdtempSync5(join31(tmpdir9(), "oasis-chat-"));
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-"));
149601
149654
  if (actorCtx.config?.prompt) {
149602
149655
  for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
149603
- const file = join31(dir, rel);
149656
+ const file = join32(dir, rel);
149604
149657
  mkdirSync21(dirname24(file), { recursive: true });
149605
149658
  writeFileSync13(file, content);
149606
149659
  }
@@ -149612,12 +149665,12 @@ async function startOasisServer(opts) {
149612
149665
  const s2 = byId.get(id);
149613
149666
  return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
149614
149667
  });
149615
- writeFileSync13(join31(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
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"));
149616
149669
  }
149617
149670
  if (opts.materializeSkills) {
149618
149671
  const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
149619
149672
  for (const [rel, content] of Object.entries(skillFiles)) {
149620
- const file = join31(dir, rel);
149673
+ const file = join32(dir, rel);
149621
149674
  mkdirSync21(dirname24(file), { recursive: true });
149622
149675
  writeFileSync13(file, content);
149623
149676
  }
@@ -149631,7 +149684,7 @@ async function startOasisServer(opts) {
149631
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";
149632
149685
  return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
149633
149686
  });
149634
- writeFileSync13(join31(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
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"));
149635
149688
  }
149636
149689
  spawnCwd = dir;
149637
149690
  }
@@ -158793,7 +158846,7 @@ var init_skill_materializer = __esm({
158793
158846
 
158794
158847
  // ../server/src/governance/connector-skills.ts
158795
158848
  function connectorSkillsDir(dataDir, connectorId) {
158796
- return (0, import_node_path13.join)(dataDir, "connector-skills", connectorId);
158849
+ return (0, import_node_path14.join)(dataDir, "connector-skills", connectorId);
158797
158850
  }
158798
158851
  function parseConnectorSkillId(id) {
158799
158852
  if (!id.startsWith("connector:")) return null;
@@ -158803,17 +158856,17 @@ function parseConnectorSkillId(id) {
158803
158856
  return { connectorId: rest.slice(0, i), slug: rest.slice(i + 1) };
158804
158857
  }
158805
158858
  async function collect(root, dir, out) {
158806
- for (const e of await (0, import_promises7.readdir)(dir, { withFileTypes: true })) {
158807
- const abs = (0, import_node_path13.join)(dir, e.name);
158859
+ for (const e of await (0, import_promises8.readdir)(dir, { withFileTypes: true })) {
158860
+ const abs = (0, import_node_path14.join)(dir, e.name);
158808
158861
  if (e.isDirectory()) await collect(root, abs, out);
158809
- else if (e.isFile()) out[(0, import_node_path13.relative)(root, abs).split(/[\\/]/).join("/")] = await (0, import_promises7.readFile)(abs, "utf8");
158862
+ else if (e.isFile()) out[(0, import_node_path14.relative)(root, abs).split(/[\\/]/).join("/")] = await (0, import_promises8.readFile)(abs, "utf8");
158810
158863
  }
158811
158864
  }
158812
158865
  async function readLocalPack(dataDir, connectorId) {
158813
158866
  const root = connectorSkillsDir(dataDir, connectorId);
158814
158867
  let slugs;
158815
158868
  try {
158816
- slugs = (await (0, import_promises7.readdir)(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
158869
+ slugs = (await (0, import_promises8.readdir)(root, { withFileTypes: true })).filter((d) => d.isDirectory()).map((d) => d.name);
158817
158870
  } catch {
158818
158871
  return [];
158819
158872
  }
@@ -158821,7 +158874,7 @@ async function readLocalPack(dataDir, connectorId) {
158821
158874
  for (const slug6 of slugs) {
158822
158875
  const files = {};
158823
158876
  try {
158824
- await collect((0, import_node_path13.join)(root, slug6), (0, import_node_path13.join)(root, slug6), files);
158877
+ await collect((0, import_node_path14.join)(root, slug6), (0, import_node_path14.join)(root, slug6), files);
158825
158878
  } catch {
158826
158879
  continue;
158827
158880
  }
@@ -158837,17 +158890,17 @@ async function readLocalPack(dataDir, connectorId) {
158837
158890
  async function writePack(dataDir, connectorId, pack) {
158838
158891
  const root = connectorSkillsDir(dataDir, connectorId);
158839
158892
  const tmp = `${root}.tmp`;
158840
- await (0, import_promises7.rm)(tmp, { recursive: true, force: true });
158893
+ await (0, import_promises8.rm)(tmp, { recursive: true, force: true });
158841
158894
  for (const s2 of pack) {
158842
158895
  for (const [rel, content] of Object.entries(s2.files)) {
158843
- const abs = (0, import_node_path13.join)(tmp, s2.slug, rel);
158844
- await (0, import_promises7.mkdir)((0, import_node_path13.dirname)(abs), { recursive: true });
158845
- await (0, import_promises7.writeFile)(abs, content, "utf8");
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");
158846
158899
  }
158847
158900
  }
158848
- await (0, import_promises7.rm)(root, { recursive: true, force: true });
158849
- await (0, import_promises7.mkdir)((0, import_node_path13.dirname)(root), { recursive: true });
158850
- await (0, import_promises7.rename)(tmp, root);
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);
158851
158904
  }
158852
158905
  function packMatches(local, remote) {
158853
158906
  if (local.length !== remote.length) return false;
@@ -158874,12 +158927,12 @@ async function syncConnectorSkills(args) {
158874
158927
  log3(`[connector-skills] ${args.connectorId}\uFF1A\u5DF2\u4ECE\u5382\u5546\u540C\u6B65 ${fresh.length} \u4E2A\u6280\u80FD`);
158875
158928
  return { skills: fresh, outcome: "fetched" };
158876
158929
  }
158877
- var import_promises7, import_node_path13, toId;
158930
+ var import_promises8, import_node_path14, toId;
158878
158931
  var init_connector_skills = __esm({
158879
158932
  "../server/src/governance/connector-skills.ts"() {
158880
158933
  "use strict";
158881
- import_promises7 = require("node:fs/promises");
158882
- import_node_path13 = require("node:path");
158934
+ import_promises8 = require("node:fs/promises");
158935
+ import_node_path14 = require("node:path");
158883
158936
  init_src5();
158884
158937
  toId = (connectorId, slug6) => `connector:${connectorId}/${slug6}`;
158885
158938
  }
@@ -159154,15 +159207,43 @@ function actorsDomain(opts) {
159154
159207
  const conn = await service.setActorConnectorEnabled(req.params.id, req.params.connectorId, b2.enabled);
159155
159208
  return { status: 200, body: conn };
159156
159209
  });
159210
+ const requireVariableManager = (req) => {
159211
+ if (!isHumanActor(req.auth.actor)) {
159212
+ throw new ApiError(
159213
+ 403,
159214
+ "VARIABLE_MANAGEMENT_FORBIDDEN",
159215
+ "\u53D8\u91CF\u7684\u5217\u51FA/\u5199\u5165/\u5220\u9664\u4EC5\u9650\u4EBA\u7C7B\u63A7\u5236\u53F0\u7528\u6237\uFF1Bagent \u8BFB\u53D6\u51ED\u636E\u8BF7\u7528 `oasis var reveal <key>`"
159216
+ );
159217
+ }
159218
+ };
159219
+ const auditVariableChange = async (req, kind, variableKey, targetScope) => {
159220
+ await opts.credentialAudit?.({
159221
+ kind,
159222
+ actor: req.auth.actor,
159223
+ variableKey,
159224
+ targetScope,
159225
+ source: "console",
159226
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
159227
+ });
159228
+ };
159157
159229
  router.get("/api/variables", async (req) => {
159230
+ requireVariableManager(req);
159158
159231
  const { service } = await resolveCtx(req.auth.companyId);
159159
159232
  return { status: 200, body: { items: await service.listVariables() } };
159160
159233
  });
159161
159234
  router.post("/api/variables", async (req) => {
159235
+ requireVariableManager(req);
159162
159236
  const { service } = await resolveCtx(req.auth.companyId);
159163
159237
  const b2 = req.body;
159164
159238
  if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
159165
- const scope = b2.scope ?? "global";
159239
+ if (b2.scope !== "global" && b2.scope !== "personal" && b2.scope !== "project") {
159240
+ throw new ApiError(
159241
+ 400,
159242
+ "BAD_REQUEST",
159243
+ "\u5FC5\u987B\u663E\u5F0F\u63D0\u4F9B scope\uFF08global | personal | project\uFF09\u2014\u2014\u4F5C\u7528\u57DF\u51B3\u5B9A\u8FD9\u6761\u51ED\u636E\u53D1\u7ED9\u8C01\uFF0C\u4E0D\u8BBE\u7F3A\u7701"
159244
+ );
159245
+ }
159246
+ const scope = b2.scope;
159166
159247
  if (scope === "project" && !b2.projectId) {
159167
159248
  throw new ApiError(400, "BAD_REQUEST", "scope=project \u5FC5\u987B\u63D0\u4F9B projectId");
159168
159249
  }
@@ -159172,6 +159253,13 @@ function actorsDomain(opts) {
159172
159253
  if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
159173
159254
  throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
159174
159255
  }
159256
+ if (scope === "personal") {
159257
+ throw new ApiError(
159258
+ 400,
159259
+ "BAD_REQUEST",
159260
+ "personal \u53D8\u91CF\u8BF7\u8D70 POST /api/actors/:id/variables\uFF08\u672C\u7AEF\u70B9\u65E0 actorId\uFF0C\u5199\u5165\u4F1A\u843D\u4E0B\u65E0\u5F52\u5C5E\u7684\u7578\u5F62\u884C\uFF09"
159261
+ );
159262
+ }
159175
159263
  if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
159176
159264
  await service.putVariable({
159177
159265
  key: b2.key,
@@ -159183,9 +159271,16 @@ function actorsDomain(opts) {
159183
159271
  ...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
159184
159272
  ...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
159185
159273
  });
159274
+ await auditVariableChange(
159275
+ req,
159276
+ "credential_write",
159277
+ b2.key,
159278
+ scope === "project" ? `project:${b2.projectId}` : "global"
159279
+ );
159186
159280
  return { status: 201, body: { ok: true } };
159187
159281
  });
159188
159282
  router.delete("/api/variables/:key", async (req) => {
159283
+ requireVariableManager(req);
159189
159284
  const { service } = await resolveCtx(req.auth.companyId);
159190
159285
  const projectId = req.query.get("projectId") ?? void 0;
159191
159286
  await service.deleteVariable(
@@ -159193,13 +159288,21 @@ function actorsDomain(opts) {
159193
159288
  void 0,
159194
159289
  projectId ? { projectId } : void 0
159195
159290
  );
159291
+ await auditVariableChange(
159292
+ req,
159293
+ "credential_delete",
159294
+ req.params.key,
159295
+ projectId ? `project:${projectId}` : "global"
159296
+ );
159196
159297
  return { status: 200, body: { ok: true } };
159197
159298
  });
159198
159299
  router.get("/api/actors/:id/variables", async (req) => {
159300
+ requireVariableManager(req);
159199
159301
  const { service } = await resolveCtx(req.auth.companyId);
159200
159302
  return { status: 200, body: { items: await service.listVariables(req.params.id) } };
159201
159303
  });
159202
159304
  router.post("/api/actors/:id/variables", async (req) => {
159305
+ requireVariableManager(req);
159203
159306
  const { service } = await resolveCtx(req.auth.companyId);
159204
159307
  const actorId = req.params.id;
159205
159308
  const b2 = req.body;
@@ -159229,11 +159332,14 @@ function actorsDomain(opts) {
159229
159332
  ...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
159230
159333
  ...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
159231
159334
  });
159335
+ await auditVariableChange(req, "credential_write", b2.key, `personal:${actorId}`);
159232
159336
  return { status: 201, body: { ok: true } };
159233
159337
  });
159234
159338
  router.delete("/api/actors/:id/variables/:key", async (req) => {
159339
+ requireVariableManager(req);
159235
159340
  const { service } = await resolveCtx(req.auth.companyId);
159236
159341
  await service.deleteVariable(req.params.key, req.params.id);
159342
+ await auditVariableChange(req, "credential_delete", req.params.key, `personal:${req.params.id}`);
159237
159343
  return { status: 200, body: { ok: true } };
159238
159344
  });
159239
159345
  router.post("/api/variables/reveal", async (req) => {
@@ -162311,10 +162417,10 @@ function nodesDomain(deps) {
162311
162417
  }
162312
162418
  }
162313
162419
  try {
162314
- const here = (0, import_node_path14.dirname)((0, import_node_url4.fileURLToPath)(__esm_import_meta_url));
162420
+ const here = (0, import_node_path15.dirname)((0, import_node_url4.fileURLToPath)(__esm_import_meta_url));
162315
162421
  for (const rel of ["../../../../node-daemon/package.json", "../../../../../node-daemon/package.json"]) {
162316
162422
  try {
162317
- const raw = (0, import_node_fs11.readFileSync)((0, import_node_path14.resolve)(here, rel), "utf8");
162423
+ const raw = (0, import_node_fs11.readFileSync)((0, import_node_path15.resolve)(here, rel), "utf8");
162318
162424
  const pkg = JSON.parse(raw);
162319
162425
  if (pkg.version) return { version: pkg.version, source: "monorepo" };
162320
162426
  } catch {
@@ -162626,14 +162732,14 @@ function nodesDomain(deps) {
162626
162732
  });
162627
162733
  };
162628
162734
  }
162629
- var import_node_crypto26, import_node_fs11, import_node_url4, import_node_path14;
162735
+ var import_node_crypto26, import_node_fs11, import_node_url4, import_node_path15;
162630
162736
  var init_routes5 = __esm({
162631
162737
  "../server/src/domains/nodes/routes.ts"() {
162632
162738
  "use strict";
162633
162739
  import_node_crypto26 = require("node:crypto");
162634
162740
  import_node_fs11 = require("node:fs");
162635
162741
  import_node_url4 = require("node:url");
162636
- import_node_path14 = require("node:path");
162742
+ import_node_path15 = require("node:path");
162637
162743
  init_src4();
162638
162744
  init_connect_script();
162639
162745
  init_node_health();
@@ -164008,12 +164114,12 @@ function nameKey(name) {
164008
164114
  function cleanName(name) {
164009
164115
  return name.trim().replace(/\s+/g, " ");
164010
164116
  }
164011
- var import_node_fs12, import_node_path15, import_node_crypto27, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
164117
+ var import_node_fs12, import_node_path16, import_node_crypto27, SEP, keyOf, prefixOf, MemoryWorkorderTagStore, FileWorkorderTagStore;
164012
164118
  var init_tags = __esm({
164013
164119
  "../server/src/domains/collab/tags.ts"() {
164014
164120
  "use strict";
164015
164121
  import_node_fs12 = __toESM(require("node:fs"), 1);
164016
- import_node_path15 = __toESM(require("node:path"), 1);
164122
+ import_node_path16 = __toESM(require("node:path"), 1);
164017
164123
  import_node_crypto27 = __toESM(require("node:crypto"), 1);
164018
164124
  SEP = "::";
164019
164125
  keyOf = (companyId, id) => `${companyId}${SEP}${id}`;
@@ -164099,7 +164205,7 @@ var init_tags = __esm({
164099
164205
  }
164100
164206
  persist() {
164101
164207
  try {
164102
- import_node_fs12.default.mkdirSync(import_node_path15.default.dirname(this.file), { recursive: true });
164208
+ import_node_fs12.default.mkdirSync(import_node_path16.default.dirname(this.file), { recursive: true });
164103
164209
  const tmp = `${this.file}.tmp`;
164104
164210
  import_node_fs12.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
164105
164211
  import_node_fs12.default.renameSync(tmp, this.file);
@@ -165055,10 +165161,10 @@ function tokenType(p2) {
165055
165161
  function parseOtlpMetricsUsage(body) {
165056
165162
  const req = body;
165057
165163
  const out = [];
165058
- for (const rm5 of req.resourceMetrics ?? []) {
165059
- const runId = attrString(rm5.resource?.attributes, "oasis.run_id");
165164
+ for (const rm6 of req.resourceMetrics ?? []) {
165165
+ const runId = attrString(rm6.resource?.attributes, "oasis.run_id");
165060
165166
  if (!runId) continue;
165061
- const actorId = attrString(rm5.resource?.attributes, "oasis.actor_id");
165167
+ const actorId = attrString(rm6.resource?.attributes, "oasis.actor_id");
165062
165168
  let input = 0;
165063
165169
  let output = 0;
165064
165170
  let cacheRead = 0;
@@ -165066,7 +165172,7 @@ function parseOtlpMetricsUsage(body) {
165066
165172
  let costUsd = 0;
165067
165173
  let sawToken = false;
165068
165174
  let sawCost = false;
165069
- for (const sm of rm5.scopeMetrics ?? []) {
165175
+ for (const sm of rm6.scopeMetrics ?? []) {
165070
165176
  for (const m2 of sm.metrics ?? []) {
165071
165177
  const name = (m2.name ?? "").toLowerCase();
165072
165178
  const points = m2.sum?.dataPoints ?? m2.gauge?.dataPoints ?? [];
@@ -167553,12 +167659,12 @@ function normalize(patch) {
167553
167659
  ...reviewRoles !== void 0 ? { reviewRoles: [...new Set(reviewRoles.map((r) => r.trim()).filter(Boolean))] } : {}
167554
167660
  };
167555
167661
  }
167556
- var import_node_fs13, import_node_path16, SEP2, keyOf2, prefixOf2, MemoryPlaybookOverrideStore, FilePlaybookOverrideStore;
167662
+ var import_node_fs13, import_node_path17, SEP2, keyOf2, prefixOf2, MemoryPlaybookOverrideStore, FilePlaybookOverrideStore;
167557
167663
  var init_overrides = __esm({
167558
167664
  "../server/src/domains/playbooks/overrides.ts"() {
167559
167665
  "use strict";
167560
167666
  import_node_fs13 = __toESM(require("node:fs"), 1);
167561
- import_node_path16 = __toESM(require("node:path"), 1);
167667
+ import_node_path17 = __toESM(require("node:path"), 1);
167562
167668
  SEP2 = "::";
167563
167669
  keyOf2 = (companyId, ref2, nodeKey) => `${companyId}${SEP2}${ref2}${SEP2}${nodeKey}`;
167564
167670
  prefixOf2 = (companyId, ref2) => `${companyId}${SEP2}${ref2}${SEP2}`;
@@ -167597,7 +167703,7 @@ var init_overrides = __esm({
167597
167703
  }
167598
167704
  persist() {
167599
167705
  try {
167600
- import_node_fs13.default.mkdirSync(import_node_path16.default.dirname(this.file), { recursive: true });
167706
+ import_node_fs13.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
167601
167707
  const tmp = `${this.file}.tmp`;
167602
167708
  import_node_fs13.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
167603
167709
  import_node_fs13.default.renameSync(tmp, this.file);
@@ -168036,12 +168142,12 @@ var init_daemon_adapter = __esm({
168036
168142
  });
168037
168143
 
168038
168144
  // ../server/src/side-map.ts
168039
- var import_node_fs14, import_node_path17, FileSideMap;
168145
+ var import_node_fs14, import_node_path18, FileSideMap;
168040
168146
  var init_side_map = __esm({
168041
168147
  "../server/src/side-map.ts"() {
168042
168148
  "use strict";
168043
168149
  import_node_fs14 = __toESM(require("node:fs"), 1);
168044
- import_node_path17 = __toESM(require("node:path"), 1);
168150
+ import_node_path18 = __toESM(require("node:path"), 1);
168045
168151
  FileSideMap = class {
168046
168152
  constructor(file) {
168047
168153
  this.file = file;
@@ -168068,7 +168174,7 @@ var init_side_map = __esm({
168068
168174
  }
168069
168175
  persist() {
168070
168176
  try {
168071
- import_node_fs14.default.mkdirSync(import_node_path17.default.dirname(this.file), { recursive: true });
168177
+ import_node_fs14.default.mkdirSync(import_node_path18.default.dirname(this.file), { recursive: true });
168072
168178
  const tmp = `${this.file}.tmp`;
168073
168179
  import_node_fs14.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
168074
168180
  import_node_fs14.default.renameSync(tmp, this.file);
@@ -169524,26 +169630,26 @@ ${ctx.nodeFault}
169524
169630
 
169525
169631
  // ../server/src/governance/builtin-skills.ts
169526
169632
  async function collectDir(root, dir, out) {
169527
- const entries = await (0, import_promises8.readdir)(dir, { withFileTypes: true });
169633
+ const entries = await (0, import_promises9.readdir)(dir, { withFileTypes: true });
169528
169634
  for (const e of entries) {
169529
- const abs = (0, import_node_path18.join)(dir, e.name);
169635
+ const abs = (0, import_node_path19.join)(dir, e.name);
169530
169636
  if (e.isDirectory()) {
169531
169637
  await collectDir(root, abs, out);
169532
169638
  } else if (e.isFile()) {
169533
- const info = await (0, import_promises8.stat)(abs);
169639
+ const info = await (0, import_promises9.stat)(abs);
169534
169640
  if (info.size > MAX_FILE_BYTES3) {
169535
169641
  console.warn(`[builtin-skills] skip oversized file (${info.size}B): ${abs}`);
169536
169642
  continue;
169537
169643
  }
169538
- const rel = (0, import_node_path18.relative)(root, abs).split(/[\\/]/).join("/");
169539
- out[rel] = await (0, import_promises8.readFile)(abs, "utf8");
169644
+ const rel = (0, import_node_path19.relative)(root, abs).split(/[\\/]/).join("/");
169645
+ out[rel] = await (0, import_promises9.readFile)(abs, "utf8");
169540
169646
  }
169541
169647
  }
169542
169648
  }
169543
169649
  async function loadBuiltinSkills(skillsDir) {
169544
169650
  let dirents;
169545
169651
  try {
169546
- dirents = await (0, import_promises8.readdir)(skillsDir, { withFileTypes: true });
169652
+ dirents = await (0, import_promises9.readdir)(skillsDir, { withFileTypes: true });
169547
169653
  } catch {
169548
169654
  return [];
169549
169655
  }
@@ -169551,7 +169657,7 @@ async function loadBuiltinSkills(skillsDir) {
169551
169657
  for (const d of dirents) {
169552
169658
  if (!d.isDirectory()) continue;
169553
169659
  const slug6 = d.name;
169554
- const skillDir = (0, import_node_path18.join)(skillsDir, slug6);
169660
+ const skillDir = (0, import_node_path19.join)(skillsDir, slug6);
169555
169661
  const files = {};
169556
169662
  try {
169557
169663
  await collectDir(skillDir, skillDir, files);
@@ -169579,12 +169685,12 @@ function materializeBuiltinSkills(builtins, skillsDirPrefix) {
169579
169685
  }
169580
169686
  return out;
169581
169687
  }
169582
- var import_promises8, import_node_path18, MAX_FILE_BYTES3;
169688
+ var import_promises9, import_node_path19, MAX_FILE_BYTES3;
169583
169689
  var init_builtin_skills = __esm({
169584
169690
  "../server/src/governance/builtin-skills.ts"() {
169585
169691
  "use strict";
169586
- import_promises8 = require("node:fs/promises");
169587
- import_node_path18 = require("node:path");
169692
+ import_promises9 = require("node:fs/promises");
169693
+ import_node_path19 = require("node:path");
169588
169694
  init_skill_fetcher();
169589
169695
  init_skill_materializer();
169590
169696
  MAX_FILE_BYTES3 = 1 << 20;
@@ -182610,7 +182716,7 @@ var SessionManager = class {
182610
182716
 
182611
182717
  // ../cli/src/daemon/ws-client.ts
182612
182718
  init_wrapper();
182613
- var import_node_os8 = require("node:os");
182719
+ var import_node_os9 = require("node:os");
182614
182720
  var import_node_crypto38 = require("node:crypto");
182615
182721
  init_src5();
182616
182722
 
@@ -182666,7 +182772,7 @@ function detectRuntimes() {
182666
182772
 
182667
182773
  // ../cli/src/daemon/workdir-handler.ts
182668
182774
  var import_node_fs16 = __toESM(require("node:fs"), 1);
182669
- var import_node_path19 = __toESM(require("node:path"), 1);
182775
+ var import_node_path20 = __toESM(require("node:path"), 1);
182670
182776
  init_src4();
182671
182777
  init_src();
182672
182778
  var WORKDIR_READ_MAX_BYTES2 = 2 * 1024 * 1024;
@@ -182685,10 +182791,10 @@ function isSensitiveSegment(segment) {
182685
182791
  }
182686
182792
  function relPathIsSensitive(rel) {
182687
182793
  if (!rel) return false;
182688
- return rel.split(import_node_path19.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
182794
+ return rel.split(import_node_path20.default.sep).some((seg) => seg.length > 0 && isSensitiveSegment(seg));
182689
182795
  }
182690
182796
  function withinBase(p2, base) {
182691
- return p2 === base || p2.startsWith(base + import_node_path19.default.sep);
182797
+ return p2 === base || p2.startsWith(base + import_node_path20.default.sep);
182692
182798
  }
182693
182799
  function normalizeRel(raw) {
182694
182800
  const trimmed = (raw ?? "").trim();
@@ -182705,7 +182811,7 @@ async function trustedCanonicalContainer(req, logicalBase, dirKind) {
182705
182811
  } catch {
182706
182812
  return null;
182707
182813
  }
182708
- return isLegacy ? import_node_path19.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path19.default.join(trustedRootReal, "sessions", dirKind);
182814
+ return isLegacy ? import_node_path20.default.join(trustedRootReal, "oasis-chat-sessions") : import_node_path20.default.join(trustedRootReal, "sessions", dirKind);
182709
182815
  }
182710
182816
  async function resolveWithinWorkdir(req) {
182711
182817
  const dirKind = sessionDirKind(req.runtimeKind);
@@ -182723,11 +182829,11 @@ async function resolveWithinWorkdir(req) {
182723
182829
  } catch {
182724
182830
  return { ok: false, code: "NOT_FOUND" };
182725
182831
  }
182726
- if (import_node_path19.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
182832
+ if (import_node_path20.default.dirname(base) !== canonicalContainer) return { ok: false, code: "PATH_ESCAPE" };
182727
182833
  const rel = normalizeRel(req.path);
182728
- const requested = import_node_path19.default.resolve(base, rel);
182834
+ const requested = import_node_path20.default.resolve(base, rel);
182729
182835
  if (!withinBase(requested, base)) return { ok: false, code: "PATH_ESCAPE" };
182730
- const cleanRel = base === requested ? "" : import_node_path19.default.relative(base, requested);
182836
+ const cleanRel = base === requested ? "" : import_node_path20.default.relative(base, requested);
182731
182837
  if (relPathIsSensitive(cleanRel)) return { ok: false, code: "SENSITIVE" };
182732
182838
  let real;
182733
182839
  try {
@@ -182737,7 +182843,7 @@ async function resolveWithinWorkdir(req) {
182737
182843
  return { ok: false, code: "PATH_ESCAPE" };
182738
182844
  }
182739
182845
  if (!withinBase(real, base)) return { ok: false, code: "PATH_ESCAPE" };
182740
- const realRel = base === real ? "" : import_node_path19.default.relative(base, real);
182846
+ const realRel = base === real ? "" : import_node_path20.default.relative(base, real);
182741
182847
  if (relPathIsSensitive(realRel)) return { ok: false, code: "SENSITIVE" };
182742
182848
  return { ok: true, base, real };
182743
182849
  }
@@ -182773,7 +182879,7 @@ async function handleWorkdirList(req) {
182773
182879
  const slice = truncated ? visible.slice(0, WORKDIR_LIST_MAX_ENTRIES) : visible;
182774
182880
  const entries = [];
182775
182881
  for (const d of slice) {
182776
- const abs = import_node_path19.default.join(anchor, d.name);
182882
+ const abs = import_node_path20.default.join(anchor, d.name);
182777
182883
  try {
182778
182884
  const st = await import_node_fs16.default.promises.lstat(abs);
182779
182885
  if (st.isSymbolicLink()) continue;
@@ -182805,7 +182911,7 @@ async function verifyOpenedFd(fh, base, fallback) {
182805
182911
  const fdReal = await fdCanonicalPath(fh);
182806
182912
  if (fdReal === null) return { anchor: fallback };
182807
182913
  if (!withinBase(fdReal, base)) return { error: { ok: false, code: "PATH_ESCAPE" } };
182808
- const fdRel = base === fdReal ? "" : import_node_path19.default.relative(base, fdReal);
182914
+ const fdRel = base === fdReal ? "" : import_node_path20.default.relative(base, fdReal);
182809
182915
  if (relPathIsSensitive(fdRel)) return { error: { ok: false, code: "SENSITIVE" } };
182810
182916
  return { anchor: `/proc/self/fd/${fh.fd}` };
182811
182917
  }
@@ -182894,7 +183000,7 @@ function looksBinary(bytes) {
182894
183000
  function contentTypeFor(absPath, bytes) {
182895
183001
  const sniffed = sniffContentType(bytes);
182896
183002
  if (sniffed) return sniffed;
182897
- const ext = import_node_path19.default.extname(absPath).toLowerCase();
183003
+ const ext = import_node_path20.default.extname(absPath).toLowerCase();
182898
183004
  if (EXT_CONTENT_TYPE[ext]) return EXT_CONTENT_TYPE[ext];
182899
183005
  return looksBinary(bytes) ? "application/octet-stream" : "text/plain; charset=utf-8";
182900
183006
  }
@@ -183237,7 +183343,7 @@ var DaemonWsClient = class {
183237
183343
  buildMeta() {
183238
183344
  const activeSessions = this.sessions.activeSessions();
183239
183345
  return {
183240
- hostname: (0, import_node_os8.hostname)(),
183346
+ hostname: (0, import_node_os9.hostname)(),
183241
183347
  adapters: this.adapters,
183242
183348
  ...this.reportRuntimes ? { runtimes: this.runtimes } : {},
183243
183349
  nodeVersion: process.version,
@@ -183267,18 +183373,18 @@ var RuntimeRouterAdapter = class {
183267
183373
 
183268
183374
  // ../cli/src/daemon/reap-claude-projects.ts
183269
183375
  var import_node_fs17 = __toESM(require("node:fs"), 1);
183270
- var import_node_os9 = __toESM(require("node:os"), 1);
183271
- var import_node_path20 = __toESM(require("node:path"), 1);
183376
+ var import_node_os10 = __toESM(require("node:os"), 1);
183377
+ var import_node_path21 = __toESM(require("node:path"), 1);
183272
183378
  function claudeProjectSlug(cwd) {
183273
183379
  return cwd.replace(/[^a-zA-Z0-9]/g, "-");
183274
183380
  }
183275
183381
  function claudeProjectsRoot() {
183276
- const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path20.default.join(import_node_os9.default.homedir(), ".claude");
183277
- return import_node_path20.default.join(configDir, "projects");
183382
+ const configDir = process.env["CLAUDE_CONFIG_DIR"] || import_node_path21.default.join(import_node_os10.default.homedir(), ".claude");
183383
+ return import_node_path21.default.join(configDir, "projects");
183278
183384
  }
183279
183385
  function reapClaudeProjects(workdir, runtimeKind) {
183280
183386
  if (runtimeKind !== "claude" && runtimeKind !== "claude-code") return;
183281
- const dir = import_node_path20.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
183387
+ const dir = import_node_path21.default.join(claudeProjectsRoot(), claudeProjectSlug(workdir));
183282
183388
  if (!import_node_fs17.default.existsSync(dir)) return;
183283
183389
  try {
183284
183390
  import_node_fs17.default.rmSync(dir, { recursive: true, force: true });
@@ -183288,7 +183394,7 @@ function reapClaudeProjects(workdir, runtimeKind) {
183288
183394
 
183289
183395
  // ../cli/src/node.ts
183290
183396
  init_src4();
183291
- var import_node_os10 = __toESM(require("node:os"), 1);
183397
+ var import_node_os11 = __toESM(require("node:os"), 1);
183292
183398
  var RESILIENCE = {
183293
183399
  codex: { idleTimeoutMs: 6e5 }
183294
183400
  };
@@ -183352,7 +183458,7 @@ async function startNode(opts) {
183352
183458
  console.log(`[oasis node] ${opts.nodeId} \u2192 ${opts.serverUrl}`);
183353
183459
  client.start();
183354
183460
  const { workRoot, legacyRoot } = resolveWorkRoots(opts.workRoot);
183355
- const workRootIsEphemeral = workRoot.startsWith(import_node_os10.default.tmpdir());
183461
+ const workRootIsEphemeral = workRoot.startsWith(import_node_os11.default.tmpdir());
183356
183462
  if (opts.gcEnabled === false && !workRootIsEphemeral) {
183357
183463
  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`);
183358
183464
  }
@@ -183387,7 +183493,7 @@ async function startNode(opts) {
183387
183493
  var import_node_child_process16 = require("node:child_process");
183388
183494
  var import_node_fs18 = require("node:fs");
183389
183495
  var import_node_crypto39 = require("node:crypto");
183390
- var import_node_os11 = require("node:os");
183496
+ var import_node_os12 = require("node:os");
183391
183497
  function linuxMachineId() {
183392
183498
  for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
183393
183499
  try {
@@ -183427,13 +183533,13 @@ function windowsMachineId() {
183427
183533
  }
183428
183534
  function fallbackFingerprint() {
183429
183535
  const macs = [];
183430
- const ifaces = (0, import_node_os11.networkInterfaces)();
183536
+ const ifaces = (0, import_node_os12.networkInterfaces)();
183431
183537
  for (const name of Object.keys(ifaces).sort()) {
183432
183538
  for (const ni of ifaces[name] ?? []) {
183433
183539
  if (!ni.internal && ni.mac && ni.mac !== "00:00:00:00:00:00") macs.push(ni.mac);
183434
183540
  }
183435
183541
  }
183436
- return `fallback:${(0, import_node_os11.hostname)()}:${macs.sort()[0] ?? "no-mac"}`;
183542
+ return `fallback:${(0, import_node_os12.hostname)()}:${macs.sort()[0] ?? "no-mac"}`;
183437
183543
  }
183438
183544
  function machineFingerprint() {
183439
183545
  const byOs = process.platform === "darwin" ? macMachineId() : process.platform === "win32" ? windowsMachineId() : linuxMachineId();
@@ -183443,7 +183549,7 @@ var defaultSources = {
183443
183549
  machineFingerprint,
183444
183550
  osUser: () => {
183445
183551
  try {
183446
- return (0, import_node_os11.userInfo)().username;
183552
+ return (0, import_node_os12.userInfo)().username;
183447
183553
  } catch {
183448
183554
  return process.env["USER"] ?? process.env["USERNAME"] ?? "unknown";
183449
183555
  }
@@ -184449,17 +184555,53 @@ var COMMAND_DECLS = {
184449
184555
  examples: ['oasis artifact revision register --project oasis --artifact-id artifact:dev:abc --type dev --title "v1.0" --version 1 --content-ref ref-001']
184450
184556
  },
184451
184557
  var: {
184452
- usage: "oasis var <reveal> ...",
184453
- description: "\u51ED\u636E\u4FDD\u9669\u5E93\uFF1A\u8BFB\u53D6\u654F\u611F\u53D8\u91CF\u660E\u6587\uFF08ADR \u51ED\u636E\u4FDD\u9669\u5E93 \xA74.5\uFF09\u3002",
184454
- subCommands: ["var reveal"],
184455
- examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD"]
184558
+ usage: "oasis var <reveal|list|set|rm> ...",
184559
+ description: "\u51ED\u636E\u4FDD\u9669\u5E93\uFF08ADR \u51ED\u636E\u4FDD\u9669\u5E93 / ADR 0125\uFF09\u3002reveal \u662F agent \u53D6\u660E\u6587\u7684\u5165\u53E3\uFF1Blist/set/rm \u662F\u7BA1\u7406\u9762\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\u3002",
184560
+ subCommands: ["var reveal", "var list", "var set", "var rm"],
184561
+ examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var list --scope project --project oasis"]
184456
184562
  },
184457
184563
  "var reveal": {
184458
184564
  usage: "oasis var reveal <key> [--source <tag>]",
184459
- description: "\u8BFB\u53D6\u654F\u611F\u53D8\u91CF\u7684\u660E\u6587\u3002env \u91CC\u82E5\u89C1 oasis://var/X\uFF08\u5F15\u7528\u975E\u660E\u6587\uFF09\u2192 \u7528\u672C\u547D\u4EE4\u53D6\u660E\u6587\u3002\u7F3A key/\u65E0\u6743\u8FD4\u56DE denied\uFF1B\u77ED\u65F6\u8BFB\u53D6\u8FC7\u591A\u4F1A\u9650\u6D41\u3002\u660E\u6587\u53EA\u8F93\u51FA\u5230 stdout\u3002",
184565
+ 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**\u8F93\u51FA\u4F1A\u8FDB\u5165\u4F1A\u8BDD\u8BB0\u5F55\u4E0E trace**\u2014\u2014\u80FD\u5305\u8FDB\u5B50\u8FDB\u7A0B\u5C31\u522B\u88F8\u8DD1\uFF0C\u7528 X=$(oasis var reveal K) \u63A5\u4F4F\u3002",
184460
184566
  positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key\uFF08\u53EF\u4F20\u88F8 key \u6216 oasis://var/<key> \u5F15\u7528\uFF0C\u4E8C\u8005\u7B49\u4EF7\uFF09" }],
184461
184567
  flags: [{ name: "source", desc: "\u8C03\u7528\u6765\u6E90\u6807\u8BB0\uFF08\u5BA1\u8BA1\u7528\uFF0C\u5982 smoke-test\uFF1B\u7F3A\u7701 agent-cli\uFF09", own: true }],
184462
184568
  examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var reveal oasis://var/GLM_API_KEY --source smoke-test"]
184569
+ },
184570
+ "var list": {
184571
+ usage: "oasis var list [--scope global|project|personal] [--project <id>] [--actor <actorId>]",
184572
+ description: "\u5217\u51FA\u53D8\u91CF\u5143\u6570\u636E\uFF08key / \u4F5C\u7528\u57DF / \u5F52\u5C5E / \u6295\u9012\u6A21\u5F0F\uFF09\u3002**\u503C\u4E0D\u51FA\u73B0**\u3002\u7BA1\u7406\u9762\u547D\u4EE4\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\uFF1Bagent \u8C03\u4F1A\u5F97\u5230 403\u3002",
184573
+ flags: [
184574
+ { name: "scope", desc: "\u53EA\u5217\u8FD9\u4E00\u6863\uFF1Aglobal | project | personal", own: true },
184575
+ { name: "project", desc: "\u53EA\u5217\u8BE5\u9879\u76EE\u7684 project \u53D8\u91CF", own: true },
184576
+ { name: "actor", desc: "\u5217\u8BE5\u5458\u5DE5\u53EF\u89C1\u7684\u53D8\u91CF\uFF08personal + global\uFF09", own: true }
184577
+ ],
184578
+ examples: ["oasis var list", "oasis var list --scope project --project oasis"]
184579
+ },
184580
+ "var set": {
184581
+ usage: "oasis var set <key> --scope global|project|personal [--project <id>] [--actor <actorId>] [--delivery env|ref]",
184582
+ description: "\u5199\u5165\u53D8\u91CF\u3002**\u503C\u53EA\u4ECE stdin \u8BFB**\u2014\u2014\u547D\u4EE4\u884C\u53C2\u6570\u4F1A\u8FDB shell history\u3001\u4E5F\u4F1A\u88AB\u540C\u673A\u4EFB\u4F55\u4EBA ps aux \u770B\u89C1\u3002--scope \u5FC5\u586B\u4E0D\u8BBE\u7F3A\u7701\uFF08\u4F5C\u7528\u57DF\u51B3\u5B9A\u8FD9\u6761\u51ED\u636E\u53D1\u7ED9\u8C01\uFF09\u3002\u7BA1\u7406\u9762\u547D\u4EE4\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\u3002",
184583
+ positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key" }],
184584
+ flags: [
184585
+ { name: "scope", desc: "global=\u5168\u7EC4\u7EC7 / project=\u6302\u9879\u76EE / personal=\u6302\u5458\u5DE5\uFF08\u5FC5\u586B\uFF09", own: true },
184586
+ { name: "project", desc: "\u9879\u76EE id\uFF08--scope project \u65F6\u5FC5\u586B\uFF09", own: true },
184587
+ { name: "actor", desc: "\u5458\u5DE5 actorId\uFF08--scope personal \u65F6\u5FC5\u586B\uFF09", own: true },
184588
+ { name: "delivery", desc: "\u6295\u9012\u6A21\u5F0F\uFF1Aenv=\u660E\u6587\u6CE8\u5165 / ref=\u5F15\u7528\u6CE8\u5165\uFF08\u654F\u611F\u9879\u7528\u8FD9\u4E2A\uFF09\uFF1B\u7F3A\u7701 env", own: true }
184589
+ ],
184590
+ examples: [
184591
+ 'printf %s "$SECRET" | oasis var set DEV_SPA_LOGIN_PASSWORD --scope project --project oasis --delivery ref',
184592
+ "oasis var set TAVILY_API_KEY --scope global < key.txt"
184593
+ ]
184594
+ },
184595
+ "var rm": {
184596
+ usage: "oasis var rm <key> --scope global|project|personal [--project <id>] [--actor <actorId>]",
184597
+ description: "\u5220\u9664\u4E00\u884C\u53D8\u91CF\u3002--scope \u5FC5\u586B\u2014\u2014\u540C\u4E00\u4E2A key \u53EF\u4EE5\u5728\u4E09\u6863\u5404\u6709\u4E00\u884C\uFF0C\u4E0D\u6307\u660E\u4F1A\u5220\u9519\u884C\u3002\u7BA1\u7406\u9762\u547D\u4EE4\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\u3002",
184598
+ positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key" }],
184599
+ flags: [
184600
+ { name: "scope", desc: "\u8981\u5220\u54EA\u4E00\u6863\uFF1Aglobal | project | personal\uFF08\u5FC5\u586B\uFF09", own: true },
184601
+ { name: "project", desc: "\u9879\u76EE id\uFF08--scope project \u65F6\u5FC5\u586B\uFF09", own: true },
184602
+ { name: "actor", desc: "\u5458\u5DE5 actorId\uFF08--scope personal \u65F6\u5FC5\u586B\uFF09", own: true }
184603
+ ],
184604
+ examples: ["oasis var rm STALE_KEY --scope project --project oasis"]
184463
184605
  }
184464
184606
  };
184465
184607
  function formatCommandHelp(decl) {
@@ -184678,6 +184820,12 @@ function needPos(positional, i, usage) {
184678
184820
  if (v2 === void 0) throw new Error(`\u7528\u6CD5: ${usage}`);
184679
184821
  return v2;
184680
184822
  }
184823
+ async function readStdin() {
184824
+ if (process.stdin.isTTY) return "";
184825
+ const chunks = [];
184826
+ for await (const c of process.stdin) chunks.push(Buffer.from(c));
184827
+ return Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
184828
+ }
184681
184829
  function slugId(value) {
184682
184830
  return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || `artifact-${Date.now()}`;
184683
184831
  }
@@ -186149,8 +186297,98 @@ ${res.warning}`);
186149
186297
  }
186150
186298
  break;
186151
186299
  }
186300
+ const forbidden = (e) => e instanceof ApiRequestError && e.status === 403 ? new Error("\u53D8\u91CF\u7684\u5217\u51FA/\u5199\u5165/\u5220\u9664\u4EC5\u9650\u4EBA\u7C7B\u63A7\u5236\u53F0\u7528\u6237\uFF08operator token\uFF09\u3002agent \u53D6\u51ED\u636E\u8BF7\u7528 `oasis var reveal <key>`\u3002") : void 0;
186301
+ const readScope = () => {
186302
+ const scope = flags.get("scope");
186303
+ if (scope !== "global" && scope !== "project" && scope !== "personal") {
186304
+ throw new Error("--scope \u5FC5\u586B\uFF0C\u53D6\u503C global | project | personal\n global \u5168\u7EC4\u7EC7\u901A\u7528\uFF0C\u6240\u6709 agent \u90FD\u62FF\u5F97\u5230\n project \u6302\u5728\u9879\u76EE\u4E0A\uFF08\u914D --project <id>\uFF09\uFF0C\u6D3E\u5230\u8BE5\u9879\u76EE\u7684 agent \u81EA\u52A8\u83B7\u5F97\n personal \u6302\u5728\u5458\u5DE5\u4E0A\uFF08\u914D --actor <actorId>\uFF09\uFF0C\u53EA\u6709\u90A3\u4E2A agent \u62FF\u5F97\u5230\n\uFF08\u4E0D\u8BBE\u7F3A\u7701\uFF1A\u4F5C\u7528\u57DF\u51B3\u5B9A\u8FD9\u6761\u51ED\u636E\u53D1\u7ED9\u8C01\uFF0C\u731C\u9519\u5C31\u662F\u628A\u5B83\u53D1\u7ED9\u5168\u7EC4\u7EC7\u3002\uFF09");
186305
+ }
186306
+ if (scope === "project" && !flags.get("project")) throw new Error("--scope project \u5FC5\u987B\u914D --project <projectId>");
186307
+ if (scope === "personal" && !flags.get("actor")) throw new Error("--scope personal \u5FC5\u987B\u914D --actor <actorId>");
186308
+ return {
186309
+ scope,
186310
+ ...flags.get("project") ? { projectId: flags.get("project") } : {},
186311
+ ...flags.get("actor") ? { actorId: flags.get("actor") } : {}
186312
+ };
186313
+ };
186314
+ if (sub === "list") {
186315
+ const want = flags.get("scope");
186316
+ const actorFilter = flags.get("actor");
186317
+ const path30 = actorFilter ? `/api/actors/${encodeURIComponent(actorFilter)}/variables` : "/api/variables";
186318
+ let items;
186319
+ try {
186320
+ ({ items } = await api.request("GET", path30));
186321
+ } catch (e) {
186322
+ throw forbidden(e) ?? e;
186323
+ }
186324
+ const rows = items.filter((v2) => !want || v2.scope === want).filter((v2) => !flags.get("project") || v2.projectId === flags.get("project"));
186325
+ if (rows.length === 0) {
186326
+ println("\u6CA1\u6709\u5339\u914D\u7684\u53D8\u91CF");
186327
+ break;
186328
+ }
186329
+ for (const v2 of rows) {
186330
+ const owner = v2.scope === "project" ? v2.projectId ?? "?" : v2.scope === "personal" ? v2.actorId ?? "?" : "-";
186331
+ println(`${v2.key} ${v2.scope} ${owner} ${v2.deliveryMode ?? "env"}${v2.connectorId ? ` [connector:${v2.connectorId}]` : ""}`);
186332
+ }
186333
+ break;
186334
+ }
186335
+ if (sub === "set") {
186336
+ const key = needPos(positional, 1, "oasis var set <key> --scope \u2026 \uFF08\u503C\u4ECE stdin \u8BFB\uFF09");
186337
+ const { scope, projectId, actorId } = readScope();
186338
+ const delivery = flags.get("delivery") ?? flags.get("delivery-mode");
186339
+ if (delivery !== void 0 && delivery !== "env" && delivery !== "ref") {
186340
+ throw new Error("--delivery \u53EA\u80FD\u662F env\uFF08\u660E\u6587\u6CE8\u5165\uFF09\u6216 ref\uFF08\u5F15\u7528\u6CE8\u5165\uFF0C\u654F\u611F\u9879\u7528\u8FD9\u4E2A\uFF09");
186341
+ }
186342
+ const value = await readStdin();
186343
+ if (!value) {
186344
+ throw new Error(`\u503C\u4ECE stdin \u8BFB\uFF0C\u547D\u4EE4\u884C\u4E0D\u63A5\u53D7 --value\uFF08\u4F1A\u8FDB shell history \u548C ps aux\uFF09\u3002\u7528\u6CD5\uFF1A
186345
+ printf %s "$SECRET" | oasis var set ${key} --scope ${scope}${projectId ? ` --project ${projectId}` : ""}
186346
+ oasis var set ${key} --scope ${scope} < secret.txt`);
186347
+ }
186348
+ const body = {
186349
+ key,
186350
+ value,
186351
+ scope,
186352
+ ...projectId ? { projectId } : {},
186353
+ ...delivery ? { deliveryMode: delivery } : {},
186354
+ encrypted: true
186355
+ };
186356
+ try {
186357
+ if (scope === "personal") {
186358
+ await api.request("POST", `/api/actors/${encodeURIComponent(actorId)}/variables`, { ...body, scope: "personal" });
186359
+ } else {
186360
+ await api.request("POST", "/api/variables", body);
186361
+ }
186362
+ } catch (e) {
186363
+ throw forbidden(e) ?? e;
186364
+ }
186365
+ const where = scope === "project" ? `\u9879\u76EE ${projectId}` : scope === "personal" ? `\u5458\u5DE5 ${actorId}` : "\u5168\u7EC4\u7EC7";
186366
+ println(`\u5DF2\u5199\u5165 ${key}\uFF08${where}\uFF0C\u6295\u9012=${delivery ?? "env"}\uFF09`);
186367
+ break;
186368
+ }
186369
+ if (sub === "rm") {
186370
+ const key = needPos(positional, 1, "oasis var rm <key> --scope \u2026");
186371
+ const { scope, projectId, actorId } = readScope();
186372
+ try {
186373
+ if (scope === "personal") {
186374
+ await api.request("DELETE", `/api/actors/${encodeURIComponent(actorId)}/variables/${encodeURIComponent(key)}`);
186375
+ } else {
186376
+ const q = scope === "project" ? `?projectId=${encodeURIComponent(projectId)}` : "";
186377
+ await api.request("DELETE", `/api/variables/${encodeURIComponent(key)}${q}`);
186378
+ }
186379
+ } catch (e) {
186380
+ throw forbidden(e) ?? e;
186381
+ }
186382
+ println(`\u5DF2\u5220\u9664 ${key}\uFF08${scope === "project" ? `\u9879\u76EE ${projectId}` : scope === "personal" ? `\u5458\u5DE5 ${actorId}` : "\u5168\u7EC4\u7EC7"}\uFF09`);
186383
+ break;
186384
+ }
186152
186385
  throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4\uFF1Aoasis var ${sub ?? ""}
186153
- \u53EF\u7528\uFF1Aoasis var reveal <key> [--source <tag>]`);
186386
+ \u53EF\u7528\uFF1A
186387
+ oasis var reveal <key> [--source <tag>] \u53D6\u660E\u6587\uFF08agent \u7528\uFF09
186388
+ oasis var list [--scope s] [--project p] [--actor a]
186389
+ oasis var set <key> --scope \u2026 [--delivery env|ref] \uFF08\u503C\u4ECE stdin\uFF09
186390
+ oasis var rm <key> --scope \u2026
186391
+ \u540E\u4E09\u4E2A\u662F\u7BA1\u7406\u9762\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\u3002`);
186154
186392
  }
186155
186393
  case "pin": {
186156
186394
  const { message } = await api.cmd("pin", {
@@ -186851,7 +187089,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
186851
187089
  }
186852
187090
 
186853
187091
  // src/index.ts
186854
- var PKG_VERSION = true ? "0.1.89" : "dev";
187092
+ var PKG_VERSION = true ? "0.1.91" : "dev";
186855
187093
  var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
186856
187094
  var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
186857
187095
  var PID_FILE = path29.join(OASIS_DIR, "node.pid");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test",
3
- "version": "0.1.89",
3
+ "version": "0.1.91",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"