oasis_test 0.1.90 → 0.1.92

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 +256 -36
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -141010,6 +141010,41 @@ var init_base = __esm({
141010
141010
  }
141011
141011
  });
141012
141012
 
141013
+ // ../connectors/src/logger.ts
141014
+ function ts() {
141015
+ return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
141016
+ }
141017
+ function log(tag, msg, extra) {
141018
+ const suffix = extra ? " " + JSON.stringify(extra) : "";
141019
+ console.log(`[${ts()}] ${tag} ${msg}${suffix}`);
141020
+ }
141021
+ var init_logger = __esm({
141022
+ "../connectors/src/logger.ts"() {
141023
+ "use strict";
141024
+ }
141025
+ });
141026
+
141027
+ // ../connectors/src/_base/host-isolation.ts
141028
+ function hostIsolationEnabled(env = process.env) {
141029
+ const v2 = env[HOST_ISOLATION_ENV];
141030
+ return v2 === "1" || v2 === "true";
141031
+ }
141032
+ function logHostIdentityFallback(keys, where) {
141033
+ if (keys.length === 0) return;
141034
+ log(
141035
+ where,
141036
+ `\u26A0 \u5BBF\u4E3B\u673A\u8EAB\u4EFD\u9694\u79BB\u5DF2\u5173\u95ED\uFF08${HOST_ISOLATION_ENV} \u672A\u5F00\uFF09\uFF1A\u672A\u63A5\u901A\u7684\u8FDE\u63A5\u5668\u4E0D\u518D\u5C4F\u853D\u5BBF\u4E3B\u673A\u767B\u5F55\u6001\uFF0C\u672C\u8F6E ${keys.join(", ")} \u4FDD\u6301\u5BBF\u4E3B\u673A\u9ED8\u8BA4\u503C \u2014\u2014 agent \u8C03 gh/git \u65F6\u7528\u7684\u662F**\u8FD9\u53F0\u673A\u5668\u4E0A\u90A3\u4E2A\u8D26\u53F7**\uFF08\u6743\u9650\u901A\u5E38\u6BD4\u8FDE\u63A5\u5668\u8EAB\u4EFD\u66F4\u5927\uFF09\uFF0Ccommit \u7F72\u540D\u8D70 git config --global\u3002`
141037
+ );
141038
+ }
141039
+ var HOST_ISOLATION_ENV;
141040
+ var init_host_isolation = __esm({
141041
+ "../connectors/src/_base/host-isolation.ts"() {
141042
+ "use strict";
141043
+ init_logger();
141044
+ HOST_ISOLATION_ENV = "OASIS_CONNECTOR_HOST_ISOLATION";
141045
+ }
141046
+ });
141047
+
141013
141048
  // ../connectors/src/feishu/index.ts
141014
141049
  function parseFeishuTokenResponse(data, nowMs) {
141015
141050
  const accessToken = String(data["access_token"] ?? "");
@@ -142025,20 +142060,6 @@ var init_registry2 = __esm({
142025
142060
  }
142026
142061
  });
142027
142062
 
142028
- // ../connectors/src/logger.ts
142029
- function ts() {
142030
- return (/* @__PURE__ */ new Date()).toISOString().slice(11, 23);
142031
- }
142032
- function log(tag, msg, extra) {
142033
- const suffix = extra ? " " + JSON.stringify(extra) : "";
142034
- console.log(`[${ts()}] ${tag} ${msg}${suffix}`);
142035
- }
142036
- var init_logger = __esm({
142037
- "../connectors/src/logger.ts"() {
142038
- "use strict";
142039
- }
142040
- });
142041
-
142042
142063
  // ../connectors/src/provision.ts
142043
142064
  function collectCredentials(connector, ctx) {
142044
142065
  const creds = {};
@@ -142090,19 +142111,24 @@ async function buildConnectorProvision(ctx) {
142090
142111
  log("[provision]", `${connector.config.slug}: \u88C5\u914D\u5931\u8D25\uFF08\u8BE5\u8FDE\u63A5\u5668\u672C\u8F6E\u4E0D\u53EF\u7528\uFF09: ${String(err)}`);
142091
142112
  }
142092
142113
  }
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;
142114
+ const pendingIsolation = [...isolationKeys].filter((k2) => !envOverrides[k2]);
142115
+ if (!hostIsolationEnabled()) {
142116
+ logHostIdentityFallback(pendingIsolation, "[provision]");
142117
+ } else {
142118
+ const isolationRoot = await (0, import_promises5.mkdtemp)((0, import_node_path8.join)((0, import_node_os4.tmpdir)(), "oasis-isolate-"));
142119
+ let isolationUsed = false;
142120
+ for (const key of isolationKeys) {
142121
+ if (envOverrides[key]) continue;
142122
+ const dir = (0, import_node_path8.join)(isolationRoot, key.toLowerCase());
142123
+ await (0, import_promises5.mkdir)(dir, { recursive: true, mode: 448 });
142124
+ envOverrides[key] = dir;
142125
+ isolationUsed = true;
142126
+ }
142127
+ if (!isolationUsed) await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
142128
+ else cleanups.push(async () => {
142129
+ await (0, import_promises5.rm)(isolationRoot, { recursive: true, force: true });
142130
+ });
142101
142131
  }
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
- });
142106
142132
  const cleanup = async () => {
142107
142133
  for (const fn of cleanups) await fn().catch(() => {
142108
142134
  });
@@ -142122,6 +142148,7 @@ var init_provision = __esm({
142122
142148
  "use strict";
142123
142149
  init_base();
142124
142150
  init_registry2();
142151
+ init_host_isolation();
142125
142152
  init_logger();
142126
142153
  import_promises5 = require("node:fs/promises");
142127
142154
  import_node_os4 = require("node:os");
@@ -142180,11 +142207,12 @@ async function prepareConnectorsForJob(job, deps) {
142180
142207
  if (droppedWrappers > 0) log("[node-connectors]", `\u4E22\u5F03 ${droppedWrappers} \u6761\u672C\u673A\u4E0D\u53EF\u7528\u7684 wrapper \u8DEF\u5F84`);
142181
142208
  const staleKeys = /* @__PURE__ */ new Set();
142182
142209
  const isolationKeys = /* @__PURE__ */ new Set();
142210
+ const isolate = hostIsolationEnabled();
142183
142211
  for (const connector of createAllConnectors()) {
142184
142212
  if (injected.has(connector.config.slug)) continue;
142185
142213
  const isolation = new Set(connector.hostCredentialIsolationEnvKeys ?? []);
142186
142214
  for (const key of connector.injectedEnvKeys) {
142187
- if (isolation.has(key)) isolationKeys.add(key);
142215
+ if (isolate && isolation.has(key)) isolationKeys.add(key);
142188
142216
  else staleKeys.add(key);
142189
142217
  }
142190
142218
  }
@@ -142198,7 +142226,12 @@ async function prepareConnectorsForJob(job, deps) {
142198
142226
  delete jobEnv[key];
142199
142227
  dropped++;
142200
142228
  }
142201
- if (isolationKeys.size > 0) {
142229
+ if (!isolate) {
142230
+ logHostIdentityFallback(
142231
+ createAllConnectors().filter((c) => !injected.has(c.config.slug)).flatMap((c) => [...c.hostCredentialIsolationEnvKeys ?? []]),
142232
+ "[node-connectors]"
142233
+ );
142234
+ } else if (isolationKeys.size > 0) {
142202
142235
  const isolationRoot = await (0, import_promises6.mkdtemp)((0, import_node_path9.join)((0, import_node_os5.tmpdir)(), "oasis-node-isolate-"));
142203
142236
  for (const key of isolationKeys) {
142204
142237
  const dir = (0, import_node_path9.join)(isolationRoot, key.toLowerCase());
@@ -142285,6 +142318,7 @@ var init_prepare_job = __esm({
142285
142318
  import_node_path9 = require("node:path");
142286
142319
  init_base();
142287
142320
  init_registry2();
142321
+ init_host_isolation();
142288
142322
  init_logger();
142289
142323
  SESSION_CREDENTIAL_RENEW_INTERVAL_MS = 30 * 6e4;
142290
142324
  }
@@ -146890,6 +146924,7 @@ var init_src5 = __esm({
146890
146924
  init_base();
146891
146925
  init_base();
146892
146926
  init_base();
146927
+ init_host_isolation();
146893
146928
  init_feishu();
146894
146929
  init_scopes();
146895
146930
  init_oauth();
@@ -159207,15 +159242,43 @@ function actorsDomain(opts) {
159207
159242
  const conn = await service.setActorConnectorEnabled(req.params.id, req.params.connectorId, b2.enabled);
159208
159243
  return { status: 200, body: conn };
159209
159244
  });
159245
+ const requireVariableManager = (req) => {
159246
+ if (!isHumanActor(req.auth.actor)) {
159247
+ throw new ApiError(
159248
+ 403,
159249
+ "VARIABLE_MANAGEMENT_FORBIDDEN",
159250
+ "\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>`"
159251
+ );
159252
+ }
159253
+ };
159254
+ const auditVariableChange = async (req, kind, variableKey, targetScope) => {
159255
+ await opts.credentialAudit?.({
159256
+ kind,
159257
+ actor: req.auth.actor,
159258
+ variableKey,
159259
+ targetScope,
159260
+ source: "console",
159261
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
159262
+ });
159263
+ };
159210
159264
  router.get("/api/variables", async (req) => {
159265
+ requireVariableManager(req);
159211
159266
  const { service } = await resolveCtx(req.auth.companyId);
159212
159267
  return { status: 200, body: { items: await service.listVariables() } };
159213
159268
  });
159214
159269
  router.post("/api/variables", async (req) => {
159270
+ requireVariableManager(req);
159215
159271
  const { service } = await resolveCtx(req.auth.companyId);
159216
159272
  const b2 = req.body;
159217
159273
  if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
159218
- const scope = b2.scope ?? "global";
159274
+ if (b2.scope !== "global" && b2.scope !== "personal" && b2.scope !== "project") {
159275
+ throw new ApiError(
159276
+ 400,
159277
+ "BAD_REQUEST",
159278
+ "\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"
159279
+ );
159280
+ }
159281
+ const scope = b2.scope;
159219
159282
  if (scope === "project" && !b2.projectId) {
159220
159283
  throw new ApiError(400, "BAD_REQUEST", "scope=project \u5FC5\u987B\u63D0\u4F9B projectId");
159221
159284
  }
@@ -159225,6 +159288,13 @@ function actorsDomain(opts) {
159225
159288
  if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref") {
159226
159289
  throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env \u6216 ref");
159227
159290
  }
159291
+ if (scope === "personal") {
159292
+ throw new ApiError(
159293
+ 400,
159294
+ "BAD_REQUEST",
159295
+ "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"
159296
+ );
159297
+ }
159228
159298
  if (b2.value === void 0 || b2.value === "") return { status: 200, body: { ok: true } };
159229
159299
  await service.putVariable({
159230
159300
  key: b2.key,
@@ -159236,9 +159306,16 @@ function actorsDomain(opts) {
159236
159306
  ...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
159237
159307
  ...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
159238
159308
  });
159309
+ await auditVariableChange(
159310
+ req,
159311
+ "credential_write",
159312
+ b2.key,
159313
+ scope === "project" ? `project:${b2.projectId}` : "global"
159314
+ );
159239
159315
  return { status: 201, body: { ok: true } };
159240
159316
  });
159241
159317
  router.delete("/api/variables/:key", async (req) => {
159318
+ requireVariableManager(req);
159242
159319
  const { service } = await resolveCtx(req.auth.companyId);
159243
159320
  const projectId = req.query.get("projectId") ?? void 0;
159244
159321
  await service.deleteVariable(
@@ -159246,13 +159323,21 @@ function actorsDomain(opts) {
159246
159323
  void 0,
159247
159324
  projectId ? { projectId } : void 0
159248
159325
  );
159326
+ await auditVariableChange(
159327
+ req,
159328
+ "credential_delete",
159329
+ req.params.key,
159330
+ projectId ? `project:${projectId}` : "global"
159331
+ );
159249
159332
  return { status: 200, body: { ok: true } };
159250
159333
  });
159251
159334
  router.get("/api/actors/:id/variables", async (req) => {
159335
+ requireVariableManager(req);
159252
159336
  const { service } = await resolveCtx(req.auth.companyId);
159253
159337
  return { status: 200, body: { items: await service.listVariables(req.params.id) } };
159254
159338
  });
159255
159339
  router.post("/api/actors/:id/variables", async (req) => {
159340
+ requireVariableManager(req);
159256
159341
  const { service } = await resolveCtx(req.auth.companyId);
159257
159342
  const actorId = req.params.id;
159258
159343
  const b2 = req.body;
@@ -159282,11 +159367,14 @@ function actorsDomain(opts) {
159282
159367
  ...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
159283
159368
  ...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
159284
159369
  });
159370
+ await auditVariableChange(req, "credential_write", b2.key, `personal:${actorId}`);
159285
159371
  return { status: 201, body: { ok: true } };
159286
159372
  });
159287
159373
  router.delete("/api/actors/:id/variables/:key", async (req) => {
159374
+ requireVariableManager(req);
159288
159375
  const { service } = await resolveCtx(req.auth.companyId);
159289
159376
  await service.deleteVariable(req.params.key, req.params.id);
159377
+ await auditVariableChange(req, "credential_delete", req.params.key, `personal:${req.params.id}`);
159290
159378
  return { status: 200, body: { ok: true } };
159291
159379
  });
159292
159380
  router.post("/api/variables/reveal", async (req) => {
@@ -184502,17 +184590,53 @@ var COMMAND_DECLS = {
184502
184590
  examples: ['oasis artifact revision register --project oasis --artifact-id artifact:dev:abc --type dev --title "v1.0" --version 1 --content-ref ref-001']
184503
184591
  },
184504
184592
  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"]
184593
+ usage: "oasis var <reveal|list|set|rm> ...",
184594
+ 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",
184595
+ subCommands: ["var reveal", "var list", "var set", "var rm"],
184596
+ examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var list --scope project --project oasis"]
184509
184597
  },
184510
184598
  "var reveal": {
184511
184599
  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",
184600
+ 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",
184513
184601
  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
184602
  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
184603
  examples: ["oasis var reveal DEV_SPA_LOGIN_PASSWORD", "oasis var reveal oasis://var/GLM_API_KEY --source smoke-test"]
184604
+ },
184605
+ "var list": {
184606
+ usage: "oasis var list [--scope global|project|personal] [--project <id>] [--actor <actorId>]",
184607
+ 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",
184608
+ flags: [
184609
+ { name: "scope", desc: "\u53EA\u5217\u8FD9\u4E00\u6863\uFF1Aglobal | project | personal", own: true },
184610
+ { name: "project", desc: "\u53EA\u5217\u8BE5\u9879\u76EE\u7684 project \u53D8\u91CF", own: true },
184611
+ { name: "actor", desc: "\u5217\u8BE5\u5458\u5DE5\u53EF\u89C1\u7684\u53D8\u91CF\uFF08personal + global\uFF09", own: true }
184612
+ ],
184613
+ examples: ["oasis var list", "oasis var list --scope project --project oasis"]
184614
+ },
184615
+ "var set": {
184616
+ usage: "oasis var set <key> --scope global|project|personal [--project <id>] [--actor <actorId>] [--delivery env|ref]",
184617
+ 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",
184618
+ positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key" }],
184619
+ flags: [
184620
+ { name: "scope", desc: "global=\u5168\u7EC4\u7EC7 / project=\u6302\u9879\u76EE / personal=\u6302\u5458\u5DE5\uFF08\u5FC5\u586B\uFF09", own: true },
184621
+ { name: "project", desc: "\u9879\u76EE id\uFF08--scope project \u65F6\u5FC5\u586B\uFF09", own: true },
184622
+ { name: "actor", desc: "\u5458\u5DE5 actorId\uFF08--scope personal \u65F6\u5FC5\u586B\uFF09", own: true },
184623
+ { 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 }
184624
+ ],
184625
+ examples: [
184626
+ 'printf %s "$SECRET" | oasis var set DEV_SPA_LOGIN_PASSWORD --scope project --project oasis --delivery ref',
184627
+ "oasis var set TAVILY_API_KEY --scope global < key.txt"
184628
+ ]
184629
+ },
184630
+ "var rm": {
184631
+ usage: "oasis var rm <key> --scope global|project|personal [--project <id>] [--actor <actorId>]",
184632
+ 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",
184633
+ positional: [{ name: "key", required: true, desc: "\u53D8\u91CF key" }],
184634
+ flags: [
184635
+ { name: "scope", desc: "\u8981\u5220\u54EA\u4E00\u6863\uFF1Aglobal | project | personal\uFF08\u5FC5\u586B\uFF09", own: true },
184636
+ { name: "project", desc: "\u9879\u76EE id\uFF08--scope project \u65F6\u5FC5\u586B\uFF09", own: true },
184637
+ { name: "actor", desc: "\u5458\u5DE5 actorId\uFF08--scope personal \u65F6\u5FC5\u586B\uFF09", own: true }
184638
+ ],
184639
+ examples: ["oasis var rm STALE_KEY --scope project --project oasis"]
184516
184640
  }
184517
184641
  };
184518
184642
  function formatCommandHelp(decl) {
@@ -184731,6 +184855,12 @@ function needPos(positional, i, usage) {
184731
184855
  if (v2 === void 0) throw new Error(`\u7528\u6CD5: ${usage}`);
184732
184856
  return v2;
184733
184857
  }
184858
+ async function readStdin() {
184859
+ if (process.stdin.isTTY) return "";
184860
+ const chunks = [];
184861
+ for await (const c of process.stdin) chunks.push(Buffer.from(c));
184862
+ return Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/, "");
184863
+ }
184734
184864
  function slugId(value) {
184735
184865
  return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "") || `artifact-${Date.now()}`;
184736
184866
  }
@@ -186202,8 +186332,98 @@ ${res.warning}`);
186202
186332
  }
186203
186333
  break;
186204
186334
  }
186335
+ 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;
186336
+ const readScope = () => {
186337
+ const scope = flags.get("scope");
186338
+ if (scope !== "global" && scope !== "project" && scope !== "personal") {
186339
+ 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");
186340
+ }
186341
+ if (scope === "project" && !flags.get("project")) throw new Error("--scope project \u5FC5\u987B\u914D --project <projectId>");
186342
+ if (scope === "personal" && !flags.get("actor")) throw new Error("--scope personal \u5FC5\u987B\u914D --actor <actorId>");
186343
+ return {
186344
+ scope,
186345
+ ...flags.get("project") ? { projectId: flags.get("project") } : {},
186346
+ ...flags.get("actor") ? { actorId: flags.get("actor") } : {}
186347
+ };
186348
+ };
186349
+ if (sub === "list") {
186350
+ const want = flags.get("scope");
186351
+ const actorFilter = flags.get("actor");
186352
+ const path30 = actorFilter ? `/api/actors/${encodeURIComponent(actorFilter)}/variables` : "/api/variables";
186353
+ let items;
186354
+ try {
186355
+ ({ items } = await api.request("GET", path30));
186356
+ } catch (e) {
186357
+ throw forbidden(e) ?? e;
186358
+ }
186359
+ const rows = items.filter((v2) => !want || v2.scope === want).filter((v2) => !flags.get("project") || v2.projectId === flags.get("project"));
186360
+ if (rows.length === 0) {
186361
+ println("\u6CA1\u6709\u5339\u914D\u7684\u53D8\u91CF");
186362
+ break;
186363
+ }
186364
+ for (const v2 of rows) {
186365
+ const owner = v2.scope === "project" ? v2.projectId ?? "?" : v2.scope === "personal" ? v2.actorId ?? "?" : "-";
186366
+ println(`${v2.key} ${v2.scope} ${owner} ${v2.deliveryMode ?? "env"}${v2.connectorId ? ` [connector:${v2.connectorId}]` : ""}`);
186367
+ }
186368
+ break;
186369
+ }
186370
+ if (sub === "set") {
186371
+ const key = needPos(positional, 1, "oasis var set <key> --scope \u2026 \uFF08\u503C\u4ECE stdin \u8BFB\uFF09");
186372
+ const { scope, projectId, actorId } = readScope();
186373
+ const delivery = flags.get("delivery") ?? flags.get("delivery-mode");
186374
+ if (delivery !== void 0 && delivery !== "env" && delivery !== "ref") {
186375
+ 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");
186376
+ }
186377
+ const value = await readStdin();
186378
+ if (!value) {
186379
+ 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
186380
+ printf %s "$SECRET" | oasis var set ${key} --scope ${scope}${projectId ? ` --project ${projectId}` : ""}
186381
+ oasis var set ${key} --scope ${scope} < secret.txt`);
186382
+ }
186383
+ const body = {
186384
+ key,
186385
+ value,
186386
+ scope,
186387
+ ...projectId ? { projectId } : {},
186388
+ ...delivery ? { deliveryMode: delivery } : {},
186389
+ encrypted: true
186390
+ };
186391
+ try {
186392
+ if (scope === "personal") {
186393
+ await api.request("POST", `/api/actors/${encodeURIComponent(actorId)}/variables`, { ...body, scope: "personal" });
186394
+ } else {
186395
+ await api.request("POST", "/api/variables", body);
186396
+ }
186397
+ } catch (e) {
186398
+ throw forbidden(e) ?? e;
186399
+ }
186400
+ const where = scope === "project" ? `\u9879\u76EE ${projectId}` : scope === "personal" ? `\u5458\u5DE5 ${actorId}` : "\u5168\u7EC4\u7EC7";
186401
+ println(`\u5DF2\u5199\u5165 ${key}\uFF08${where}\uFF0C\u6295\u9012=${delivery ?? "env"}\uFF09`);
186402
+ break;
186403
+ }
186404
+ if (sub === "rm") {
186405
+ const key = needPos(positional, 1, "oasis var rm <key> --scope \u2026");
186406
+ const { scope, projectId, actorId } = readScope();
186407
+ try {
186408
+ if (scope === "personal") {
186409
+ await api.request("DELETE", `/api/actors/${encodeURIComponent(actorId)}/variables/${encodeURIComponent(key)}`);
186410
+ } else {
186411
+ const q = scope === "project" ? `?projectId=${encodeURIComponent(projectId)}` : "";
186412
+ await api.request("DELETE", `/api/variables/${encodeURIComponent(key)}${q}`);
186413
+ }
186414
+ } catch (e) {
186415
+ throw forbidden(e) ?? e;
186416
+ }
186417
+ println(`\u5DF2\u5220\u9664 ${key}\uFF08${scope === "project" ? `\u9879\u76EE ${projectId}` : scope === "personal" ? `\u5458\u5DE5 ${actorId}` : "\u5168\u7EC4\u7EC7"}\uFF09`);
186418
+ break;
186419
+ }
186205
186420
  throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4\uFF1Aoasis var ${sub ?? ""}
186206
- \u53EF\u7528\uFF1Aoasis var reveal <key> [--source <tag>]`);
186421
+ \u53EF\u7528\uFF1A
186422
+ oasis var reveal <key> [--source <tag>] \u53D6\u660E\u6587\uFF08agent \u7528\uFF09
186423
+ oasis var list [--scope s] [--project p] [--actor a]
186424
+ oasis var set <key> --scope \u2026 [--delivery env|ref] \uFF08\u503C\u4ECE stdin\uFF09
186425
+ oasis var rm <key> --scope \u2026
186426
+ \u540E\u4E09\u4E2A\u662F\u7BA1\u7406\u9762\uFF0C\u4EC5\u9650\u4EBA\u7C7B operator token\u3002`);
186207
186427
  }
186208
186428
  case "pin": {
186209
186429
  const { message } = await api.cmd("pin", {
@@ -186904,7 +187124,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
186904
187124
  }
186905
187125
 
186906
187126
  // src/index.ts
186907
- var PKG_VERSION = true ? "0.1.90" : "dev";
187127
+ var PKG_VERSION = true ? "0.1.92" : "dev";
186908
187128
  var OASIS_DIR = path29.join(os9.homedir(), ".oasis");
186909
187129
  var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
186910
187130
  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.90",
3
+ "version": "0.1.92",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"