oasis_test 0.1.95 → 0.1.96

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 +325 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -2516,6 +2516,100 @@ var init_runtime = __esm({
2516
2516
  }
2517
2517
  });
2518
2518
 
2519
+ // ../contract/src/parse-extra-args.ts
2520
+ function parseExtraArgs(input) {
2521
+ const out = [];
2522
+ const n = input.length;
2523
+ let buf = "";
2524
+ let hasToken = false;
2525
+ let i = 0;
2526
+ while (i < n) {
2527
+ const c = input[i];
2528
+ if (isSpace(c)) {
2529
+ if (hasToken) {
2530
+ out.push(buf);
2531
+ buf = "";
2532
+ hasToken = false;
2533
+ }
2534
+ i++;
2535
+ continue;
2536
+ }
2537
+ if (c === "'") {
2538
+ hasToken = true;
2539
+ const start = i;
2540
+ i++;
2541
+ while (i < n && input[i] !== "'") {
2542
+ buf += input[i];
2543
+ i++;
2544
+ }
2545
+ if (i >= n) throw new BadExtraArgsError(`\u672A\u95ED\u5408\u7684\u5355\u5F15\u53F7\uFF08\u8D77\u4E8E\u7B2C ${start + 1} \u5217\uFF09`, start + 1);
2546
+ i++;
2547
+ continue;
2548
+ }
2549
+ if (c === '"') {
2550
+ hasToken = true;
2551
+ const start = i;
2552
+ i++;
2553
+ while (i < n && input[i] !== '"') {
2554
+ if (input[i] === "\\") {
2555
+ const next = input[i + 1];
2556
+ if (next === void 0) throw new BadExtraArgsError(`\u53CC\u5F15\u53F7\u5185\u60AC\u7A7A\u53CD\u659C\u6760\uFF08\u7B2C ${i + 1} \u5217\uFF09`, i + 1);
2557
+ if (next === "\\" || next === '"' || next === "$" || next === "`") {
2558
+ buf += next;
2559
+ } else {
2560
+ buf += "\\" + next;
2561
+ }
2562
+ i += 2;
2563
+ } else {
2564
+ buf += input[i];
2565
+ i++;
2566
+ }
2567
+ }
2568
+ if (i >= n) throw new BadExtraArgsError(`\u672A\u95ED\u5408\u7684\u53CC\u5F15\u53F7\uFF08\u8D77\u4E8E\u7B2C ${start + 1} \u5217\uFF09`, start + 1);
2569
+ i++;
2570
+ continue;
2571
+ }
2572
+ if (c === "\\") {
2573
+ const next = input[i + 1];
2574
+ if (next === void 0) throw new BadExtraArgsError(`\u60AC\u7A7A\u53CD\u659C\u6760\uFF08\u7B2C ${i + 1} \u5217\uFF09`, i + 1);
2575
+ hasToken = true;
2576
+ buf += next;
2577
+ i += 2;
2578
+ continue;
2579
+ }
2580
+ hasToken = true;
2581
+ buf += c;
2582
+ i++;
2583
+ }
2584
+ if (hasToken) out.push(buf);
2585
+ return out;
2586
+ }
2587
+ function normalizeExtraArgs(input) {
2588
+ if (input === void 0) return void 0;
2589
+ if (typeof input === "string") return parseExtraArgs(input);
2590
+ if (!Array.isArray(input) || input.some((x2) => typeof x2 !== "string")) {
2591
+ throw new BadExtraArgsError("extraArgs \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4", 0);
2592
+ }
2593
+ return [...input];
2594
+ }
2595
+ var ERR_BAD_EXTRA_ARGS, BadExtraArgsError, isSpace;
2596
+ var init_parse_extra_args = __esm({
2597
+ "../contract/src/parse-extra-args.ts"() {
2598
+ "use strict";
2599
+ ERR_BAD_EXTRA_ARGS = "ERR_BAD_EXTRA_ARGS";
2600
+ BadExtraArgsError = class extends Error {
2601
+ /** @param column 1-based 列位(供 API 400 / CLI 报错定位) */
2602
+ constructor(message, column) {
2603
+ super(message);
2604
+ this.column = column;
2605
+ }
2606
+ name = "BadExtraArgsError";
2607
+ code = ERR_BAD_EXTRA_ARGS;
2608
+ };
2609
+ isSpace = (c) => c === " " || c === " " || c === "\n" || c === "\r" || c === "\v" || c === "\f";
2610
+ }
2611
+ });
2612
+
2519
2613
  // ../contract/src/daemon-protocol.ts
2520
2614
  var init_daemon_protocol = __esm({
2521
2615
  "../contract/src/daemon-protocol.ts"() {
@@ -2685,6 +2779,7 @@ var init_src = __esm({
2685
2779
  init_storage();
2686
2780
  init_avatar();
2687
2781
  init_runtime();
2782
+ init_parse_extra_args();
2688
2783
  init_daemon_protocol();
2689
2784
  init_registry();
2690
2785
  init_credential_ref();
@@ -7426,6 +7521,7 @@ var init_dispatcher = __esm({
7426
7521
  ...spec.part !== void 0 ? { OASIS_PART: spec.part } : {}
7427
7522
  };
7428
7523
  const resolvedModel3 = this.opts.resolveModel ? await this.opts.resolveModel(dispatchSpec.actor) : void 0;
7524
+ const resolvedExtraArgs = this.opts.resolveExtraArgs ? await this.opts.resolveExtraArgs(dispatchSpec.actor) : void 0;
7429
7525
  this.assertSpawnAttemptCurrent(jobKey, attempt);
7430
7526
  const freshWorkdir = workdirKey !== void 0 && !priorConsistent;
7431
7527
  const job = {
@@ -7438,6 +7534,7 @@ var init_dispatcher = __esm({
7438
7534
  server: { url: serverUrl },
7439
7535
  limits,
7440
7536
  ...resolvedModel3 ? { model: resolvedModel3 } : {},
7537
+ ...resolvedExtraArgs && resolvedExtraArgs.length > 0 ? { extraArgs: resolvedExtraArgs } : {},
7441
7538
  ...binding !== void 0 ? { binding } : {},
7442
7539
  ...runtimeSessionId !== void 0 ? { runtimeSessionId } : {},
7443
7540
  ...workdirKey !== void 0 ? { workdirKey } : {},
@@ -145408,6 +145505,52 @@ var init_transcript = __esm({
145408
145505
  }
145409
145506
  });
145410
145507
 
145508
+ // ../adapters/src/_core/filter-extra-args.ts
145509
+ function filterBlockedFlags(args, blocked, onFiltered) {
145510
+ if (!blocked || blocked.size === 0) return [...args];
145511
+ const out = [];
145512
+ for (let i = 0; i < args.length; i++) {
145513
+ const tok = args[i];
145514
+ const eq = tok.startsWith("-") ? tok.indexOf("=") : -1;
145515
+ const name = eq >= 0 ? tok.slice(0, eq) : tok;
145516
+ const kind = blocked.get(name);
145517
+ if (kind !== void 0) {
145518
+ onFiltered?.(name);
145519
+ if (kind === "value" && eq < 0) i++;
145520
+ continue;
145521
+ }
145522
+ out.push(tok);
145523
+ }
145524
+ return out;
145525
+ }
145526
+ function prepareExtraArgs(jobExtra, staticExtra, blocked, tel) {
145527
+ const merged = [...jobExtra ?? [], ...staticExtra ?? []];
145528
+ if (merged.length === 0) return [];
145529
+ const filtered = [];
145530
+ const kept = filterBlockedFlags(merged, blocked, (f2) => filtered.push(f2));
145531
+ if (filtered.length > 0) {
145532
+ console.warn(`[adapter:${tel.runtime}] ` + JSON.stringify({
145533
+ event: "extra_args_filtered",
145534
+ actor: tel.actor,
145535
+ runtime: tel.runtime,
145536
+ dispatchId: tel.dispatchId,
145537
+ filtered
145538
+ }));
145539
+ }
145540
+ console.debug(`[adapter:${tel.runtime}] ` + JSON.stringify({
145541
+ event: "spawn_argv_prepared",
145542
+ runtime: tel.runtime,
145543
+ argv_lengths: { extra: merged.length, filtered: kept.length },
145544
+ extra_flags_kept: kept.filter((t) => t.startsWith("-"))
145545
+ }));
145546
+ return kept;
145547
+ }
145548
+ var init_filter_extra_args = __esm({
145549
+ "../adapters/src/_core/filter-extra-args.ts"() {
145550
+ "use strict";
145551
+ }
145552
+ });
145553
+
145411
145554
  // ../adapters/src/claude-code/index.ts
145412
145555
  function normalizeClaudeStreamLine(line) {
145413
145556
  let parsed;
@@ -145584,7 +145727,7 @@ function classifyExit(result) {
145584
145727
  if (status === 429 || status === 529) return "rate-limit";
145585
145728
  return "error";
145586
145729
  }
145587
- var import_node_child_process8, import_node_crypto12, fs9, path7, readline, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
145730
+ var import_node_child_process8, import_node_crypto12, fs9, path7, readline, CLAUDE_BLOCKED_FLAGS, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
145588
145731
  var init_claude_code = __esm({
145589
145732
  "../adapters/src/claude-code/index.ts"() {
145590
145733
  "use strict";
@@ -145598,6 +145741,33 @@ var init_claude_code = __esm({
145598
145741
  init_resume_classify();
145599
145742
  init_session_paths();
145600
145743
  init_transcript();
145744
+ init_filter_extra_args();
145745
+ CLAUDE_BLOCKED_FLAGS = /* @__PURE__ */ new Map([
145746
+ ["-p", "value"],
145747
+ // 本 adapter 用 `-p <prompt>` 驱动 CLI;覆盖会替掉真正的 prompt
145748
+ ["--print", "value"],
145749
+ // 同 -p
145750
+ ["--output-format", "value"],
145751
+ // 遥测链依赖 stream-json;覆盖会让 dispatcher/telemetry 读不到事件
145752
+ ["--input-format", "value"],
145753
+ // 与 append-mode 强绑;覆盖会破坏 stream-json 输入
145754
+ ["--permission-mode", "value"],
145755
+ // adapter 强制 bypassPermissions(一次性会话协议前置)
145756
+ ["--mcp-config", "value"],
145757
+ // 会替换 adapter 注入的 MCP 配置目录,agent 认不到工具
145758
+ ["--append-system-prompt", "value"],
145759
+ // 已由 job.systemPrompt 走同一 flag 注入;重复不确定谁生效
145760
+ ["--model", "value"],
145761
+ // 已由 job.model 走同一 flag 注入;同上
145762
+ ["--session-id", "value"],
145763
+ // adapter 自己按 runtimeSessionId 决定续跑(ADR-0053/0060)
145764
+ ["--resume", "value"],
145765
+ // 同上
145766
+ ["--verbose", "boolean"],
145767
+ // 与 --output-format stream-json 配对;单独无意义、成对是重复
145768
+ ["--include-partial-messages", "boolean"]
145769
+ // 同上
145770
+ ]);
145601
145771
  ONE_SHOT_UNSAFE_TOOLS = ["ScheduleWakeup", "CronCreate", "CronDelete", "CronList"];
145602
145772
  ClaudeCodeAdapter = class {
145603
145773
  constructor(opts = {}) {
@@ -145682,7 +145852,14 @@ var init_claude_code = __esm({
145682
145852
  // ADR-0093:stream-json 输入模式——让 claude 逐条从 stdin 读 user 消息(支持多轮追加)。
145683
145853
  ...appendMode ? ["--input-format", "stream-json"] : [],
145684
145854
  ...job.model ?? this.opts.model ? ["--model", job.model ?? this.opts.model] : [],
145685
- ...this.opts.extraArgs ?? []
145855
+ // ADR「agent CLI 启动参数员工级可配置化」:员工配置 job.extraArgs(在前)+ opts.extraArgs(静态默认,在后),
145856
+ // 过 CLAUDE_BLOCKED_FLAGS 拦截打破协议契约的 flag(剔除 + warn),追加到 argv 末尾。
145857
+ ...prepareExtraArgs(
145858
+ job.extraArgs,
145859
+ this.opts.extraArgs,
145860
+ CLAUDE_BLOCKED_FLAGS,
145861
+ { runtime: "claude-code", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
145862
+ )
145686
145863
  ];
145687
145864
  const otelEnv = this.resolveOtelEnv(job, id);
145688
145865
  const child = (0, import_node_child_process8.spawn)(this.opts.claudeBin ?? "claude", args, {
@@ -146996,7 +147173,7 @@ function normalizeCodexConsoleLine(line, state = createCodexNormalizeState()) {
146996
147173
  tool.output.push(line);
146997
147174
  return [];
146998
147175
  }
146999
- var import_node_child_process10, import_node_crypto13, fs10, os4, path9, readline2, CODEX_ARGV_PROMPT_MAX_BYTES, CodexAdapter;
147176
+ var import_node_child_process10, import_node_crypto13, fs10, os4, path9, readline2, CODEX_BLOCKED_FLAGS, CODEX_ARGV_PROMPT_MAX_BYTES, CodexAdapter;
147000
147177
  var init_codex = __esm({
147001
147178
  "../adapters/src/codex/index.ts"() {
147002
147179
  "use strict";
@@ -147012,6 +147189,25 @@ var init_codex = __esm({
147012
147189
  init_session_paths();
147013
147190
  init_claude_code();
147014
147191
  init_transcript();
147192
+ init_filter_extra_args();
147193
+ CODEX_BLOCKED_FLAGS = /* @__PURE__ */ new Map([
147194
+ ["exec", "boolean"],
147195
+ // adapter argv 首 token 已是 exec;重复成非法子命令
147196
+ ["-C", "value"],
147197
+ // adapter 用 -C <dir> 指定 cwd;覆盖会把 cwd 换成任意路径
147198
+ ["--json", "boolean"],
147199
+ // 遥测链前置
147200
+ ["--dangerously-bypass-approvals-and-sandbox", "boolean"],
147201
+ // 权限模式前置(重复无害但语义混乱)
147202
+ ["--skip-git-repo-check", "boolean"],
147203
+ // 会话前置
147204
+ ["--model", "value"],
147205
+ // 由 job.model 走同一 flag 注入
147206
+ ["resume", "value"],
147207
+ // 位置参数,续会话通过 job.runtimeSessionId 走同 flag 注入
147208
+ ["--listen", "value"]
147209
+ // Multica 实证:codex --listen stdio:// 是 daemon↔CLI 传输协议;改会断链
147210
+ ]);
147015
147211
  CODEX_ARGV_PROMPT_MAX_BYTES = 1e5;
147016
147212
  CodexAdapter = class {
147017
147213
  constructor(opts = {}) {
@@ -147076,7 +147272,14 @@ var init_codex = __esm({
147076
147272
  // 打开 reasoning 摘要通道:默认 auto,让 codex 产出 reasoning item(→ thought → 前端思考块)。
147077
147273
  ...this.opts.reasoningSummary !== "none" ? ["-c", `model_reasoning_summary=${this.opts.reasoningSummary ?? "auto"}`] : [],
147078
147274
  ...this.opts.reasoningEffort ? ["-c", `model_reasoning_effort=${this.opts.reasoningEffort}`] : [],
147079
- ...this.opts.extraArgs ?? [],
147275
+ // ADR「agent CLI 启动参数员工级可配置化」:员工配置 job.extraArgs(在前)+ opts.extraArgs(静态默认,在后),
147276
+ // 过 CODEX_BLOCKED_FLAGS 拦截。追加在**位置 prompt 之前**(codex exec 的 [PROMPT] 必须是末位参数)。
147277
+ ...prepareExtraArgs(
147278
+ job.extraArgs,
147279
+ this.opts.extraArgs,
147280
+ CODEX_BLOCKED_FLAGS,
147281
+ { runtime: "codex", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
147282
+ ),
147080
147283
  promptViaStdin ? "-" : prompt
147081
147284
  ];
147082
147285
  const child = (0, import_node_child_process10.spawn)(this.opts.codexBin ?? "codex", args, {
@@ -147808,7 +148011,12 @@ async function runACPSession(job, cfg) {
147808
148011
  });
147809
148012
  }
147810
148013
  const task = materializeBundle(dir, job.bundle);
147811
- const child = (0, import_node_child_process11.spawn)(cfg.bin, [...cfg.args ?? [], ...cfg.extraArgs ?? []], {
148014
+ const child = (0, import_node_child_process11.spawn)(cfg.bin, [...cfg.args ?? [], ...prepareExtraArgs(
148015
+ job.extraArgs,
148016
+ cfg.extraArgs,
148017
+ cfg.blockedFlags,
148018
+ { runtime: cfg.runtimeKind ?? "acp", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
148019
+ )], {
147812
148020
  cwd: dir,
147813
148021
  env: {
147814
148022
  ...scrubLeakyEnv(process.env),
@@ -148096,6 +148304,7 @@ var init_acp = __esm({
148096
148304
  init_usage();
148097
148305
  init_pricing();
148098
148306
  init_transcript();
148307
+ init_filter_extra_args();
148099
148308
  ACPClient = class {
148100
148309
  constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false) {
148101
148310
  this.write = write;
@@ -148516,7 +148725,12 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, workdirKey, e
148516
148725
  }
148517
148726
  async function runStreamJson(job, cfg) {
148518
148727
  const { id, dir, task: _task } = await materialize(job, cfg);
148519
- const args = [...cfg.buildArgs(job, dir), ...cfg.extraArgs ?? []];
148728
+ const args = [...cfg.buildArgs(job, dir), ...prepareExtraArgs(
148729
+ job.extraArgs,
148730
+ cfg.extraArgs,
148731
+ cfg.blockedFlags,
148732
+ { runtime: cfg.runtimeKind ?? "subprocess", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
148733
+ )];
148520
148734
  const child = (0, import_node_child_process12.spawn)(cfg.bin, args, {
148521
148735
  cwd: dir,
148522
148736
  env: buildEnv(job, cfg.env),
@@ -148593,7 +148807,12 @@ async function runStreamJson(job, cfg) {
148593
148807
  }
148594
148808
  async function runOneShotText(job, cfg) {
148595
148809
  const { id, dir } = await materialize(job, cfg);
148596
- const args = [...cfg.buildArgs(job, dir), ...cfg.extraArgs ?? []];
148810
+ const args = [...cfg.buildArgs(job, dir), ...prepareExtraArgs(
148811
+ job.extraArgs,
148812
+ cfg.extraArgs,
148813
+ cfg.blockedFlags,
148814
+ { runtime: cfg.runtimeKind ?? "subprocess", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
148815
+ )];
148597
148816
  const child = (0, import_node_child_process12.spawn)(cfg.bin, args, {
148598
148817
  cwd: dir,
148599
148818
  env: buildEnv(job, cfg.env),
@@ -148672,6 +148891,7 @@ var init_subprocess = __esm({
148672
148891
  init_sync_skills();
148673
148892
  init_session_paths();
148674
148893
  init_transcript();
148894
+ init_filter_extra_args();
148675
148895
  }
148676
148896
  });
148677
148897
 
@@ -160651,6 +160871,7 @@ var init_service4 = __esm({
160651
160871
  connectorIds: patch.connectorIds ?? latest?.connectorIds ?? [],
160652
160872
  maxConcurrent: patch.maxConcurrent ?? latest?.maxConcurrent ?? 4,
160653
160873
  batchedContinuation: patch.batchedContinuation ?? latest?.batchedContinuation ?? false,
160874
+ extraArgs: patch.extraArgs ?? latest?.extraArgs ?? [],
160654
160875
  createdBy: by,
160655
160876
  createdAt: this.now(),
160656
160877
  source: "patch"
@@ -160677,6 +160898,7 @@ var init_service4 = __esm({
160677
160898
  connectorIds: [...target.connectorIds],
160678
160899
  maxConcurrent: target.maxConcurrent,
160679
160900
  batchedContinuation: target.batchedContinuation ?? false,
160901
+ extraArgs: [...target.extraArgs ?? []],
160680
160902
  createdBy: by,
160681
160903
  createdAt: this.now(),
160682
160904
  source: "rollback",
@@ -161325,7 +161547,7 @@ ${input.description}
161325
161547
  };
161326
161548
  mask = (plain) => plain.length <= 4 ? "\u2022\u2022\u2022\u2022" : `${"\u2022".repeat(4)}${plain.slice(-4)}`;
161327
161549
  changedKeys = (prev, next) => {
161328
- if (!prev) return ["prompt", "model", "skills", "connectorIds", "maxConcurrent", "batchedContinuation"];
161550
+ if (!prev) return ["prompt", "model", "skills", "connectorIds", "maxConcurrent", "batchedContinuation", "extraArgs"];
161329
161551
  const keys = [];
161330
161552
  if (prev.prompt !== next.prompt) keys.push("prompt");
161331
161553
  if (prev.model !== next.model) keys.push("model");
@@ -161333,6 +161555,7 @@ ${input.description}
161333
161555
  if (JSON.stringify(prev.connectorIds) !== JSON.stringify(next.connectorIds)) keys.push("connectorIds");
161334
161556
  if ((prev.batchedContinuation ?? false) !== (next.batchedContinuation ?? false)) keys.push("batchedContinuation");
161335
161557
  if (prev.maxConcurrent !== next.maxConcurrent) keys.push("maxConcurrent");
161558
+ if (JSON.stringify(prev.extraArgs ?? []) !== JSON.stringify(next.extraArgs ?? [])) keys.push("extraArgs");
161336
161559
  return keys;
161337
161560
  };
161338
161561
  }
@@ -162602,6 +162825,19 @@ function actorsDomain(opts) {
162602
162825
  checkStringArray("skills");
162603
162826
  checkStringArray("connectorIds");
162604
162827
  checkBoolean("batchedContinuation");
162828
+ const rawExtra = b2.extraArgs;
162829
+ if (rawExtra !== void 0 && typeof rawExtra !== "string" && !(Array.isArray(rawExtra) && rawExtra.every((x2) => typeof x2 === "string"))) {
162830
+ throw new ApiError(400, "BAD_REQUEST", "extraArgs \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");
162831
+ }
162832
+ let extraArgs;
162833
+ try {
162834
+ extraArgs = normalizeExtraArgs(rawExtra);
162835
+ } catch (e) {
162836
+ if (e instanceof BadExtraArgsError) {
162837
+ throw new ApiError(400, "ERR_BAD_EXTRA_ARGS", `extraArgs \u89E3\u6790\u5931\u8D25\uFF08\u7B2C ${e.column} \u5217\uFF09\uFF1A${e.message}`);
162838
+ }
162839
+ throw e;
162840
+ }
162605
162841
  const cfg = await service.patchConfig(
162606
162842
  req.params.id,
162607
162843
  {
@@ -162610,7 +162846,8 @@ function actorsDomain(opts) {
162610
162846
  ...b2.skills !== void 0 ? { skills: b2.skills } : {},
162611
162847
  ...b2.connectorIds !== void 0 ? { connectorIds: b2.connectorIds } : {},
162612
162848
  ...typeof b2.maxConcurrent === "number" ? { maxConcurrent: b2.maxConcurrent } : {},
162613
- ...b2.batchedContinuation !== void 0 ? { batchedContinuation: b2.batchedContinuation } : {}
162849
+ ...b2.batchedContinuation !== void 0 ? { batchedContinuation: b2.batchedContinuation } : {},
162850
+ ...extraArgs !== void 0 ? { extraArgs } : {}
162614
162851
  },
162615
162852
  req.auth.actor
162616
162853
  );
@@ -179454,6 +179691,8 @@ var init_postgres_registry = __esm({
179454
179691
  reviewer_ids jsonb NOT NULL DEFAULT '[]'::jsonb,
179455
179692
  max_concurrent integer NOT NULL DEFAULT 4,
179456
179693
  batched_continuation boolean NOT NULL DEFAULT false,
179694
+ -- ADR\u300Cagent CLI \u542F\u52A8\u53C2\u6570\u5458\u5DE5\u7EA7\u53EF\u914D\u7F6E\u5316\u300D\uFF1A\u6BCF\u6B21\u6D3E\u53D1\u8FFD\u52A0\u5230\u5E95\u5C42 CLI argv \u7684\u542F\u52A8\u53C2\u6570\uFF08\u5DF2\u5207\u597D\u7684 string[]\uFF09\u3002
179695
+ extra_args jsonb NOT NULL DEFAULT '[]'::jsonb,
179457
179696
  -- memory_enabled \u5217\u4FDD\u7559\uFF082026-08-10 \u65E9\u5148\u7248\u672C\u5199\u8FC7\uFF09\u4F46\u4E0D\u518D\u8BFB\u5199\uFF1A\u8BB0\u5FC6\u5F00\u5173\u5DF2\u632A\u5230
179458
179697
  -- agent_prefs\uFF08\u72EC\u7ACB\u8BBE\u7F6E\uFF0C\u4E0D\u8FDB\u7248\u672C\u94FE\uFF09\u3002\u4E0E reviewer_ids \u540C\u89C4\u683C\u7684\u6B7B\u5217\u3002
179459
179698
  memory_enabled boolean NOT NULL DEFAULT true,
@@ -179466,6 +179705,7 @@ var init_postgres_registry = __esm({
179466
179705
  await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS max_concurrent integer NOT NULL DEFAULT 4`);
179467
179706
  await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS reviewer_ids jsonb NOT NULL DEFAULT '[]'::jsonb`);
179468
179707
  await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS batched_continuation boolean NOT NULL DEFAULT false`);
179708
+ await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS extra_args jsonb NOT NULL DEFAULT '[]'::jsonb`);
179469
179709
  await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS memory_enabled boolean NOT NULL DEFAULT true`);
179470
179710
  await pool.query(`
179471
179711
  CREATE TABLE IF NOT EXISTS "${s2}".agent_prefs (
@@ -179706,8 +179946,8 @@ var init_postgres_registry = __esm({
179706
179946
  const r = await this.pool.query(
179707
179947
  // reviewer_ids 列保留(历史数据)但不再写入——决策 0029 删了 actor 级 reviewer override;列有 DEFAULT '[]' 自动填。
179708
179948
  `INSERT INTO ${this.s}.actor_configs
179709
- (actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, created_by, created_at, source, rolled_back_from)
179710
- SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9,$10,$11,$12
179949
+ (actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, extra_args, created_by, created_at, source, rolled_back_from)
179950
+ SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9::jsonb,$10,$11,$12,$13
179711
179951
  WHERE (SELECT COALESCE(MAX(version), 0) + 1 FROM ${this.s}.actor_configs WHERE actor_id = $1) = $2::int`,
179712
179952
  [
179713
179953
  c.actorId,
@@ -179718,6 +179958,7 @@ var init_postgres_registry = __esm({
179718
179958
  JSON.stringify(c.connectorIds),
179719
179959
  c.maxConcurrent,
179720
179960
  c.batchedContinuation ?? false,
179961
+ JSON.stringify(c.extraArgs ?? []),
179721
179962
  c.createdBy,
179722
179963
  c.createdAt,
179723
179964
  c.source,
@@ -180129,6 +180370,7 @@ var init_postgres_registry = __esm({
180129
180370
  connectorIds: row.connector_ids,
180130
180371
  maxConcurrent: row.max_concurrent ?? 4,
180131
180372
  batchedContinuation: row.batched_continuation ?? false,
180373
+ extraArgs: row.extra_args ?? [],
180132
180374
  // 注意:memory_enabled 是死列,不映射进 ActorConfig——记忆开关在 agent_prefs。
180133
180375
  createdBy: row.created_by,
180134
180376
  createdAt: new Date(row.created_at).toISOString(),
@@ -187248,6 +187490,13 @@ async function startServe(opts) {
187248
187490
  }
187249
187491
  return candidate;
187250
187492
  },
187493
+ // ADR「agent CLI 启动参数员工级可配置化」:每次派发解析员工 actor_configs.extraArgs 下发(形态同 resolveModel)。
187494
+ // 只读员工配置,不叠 runtime 默认、不做「没有员工就找 runtime」回退(ADR §3.3 / §4-A)。
187495
+ resolveExtraArgs: async (actorId) => {
187496
+ const actors2 = await runActors();
187497
+ const cfg = await actors2.service.latestConfig(actorId);
187498
+ return cfg?.extraArgs && cfg.extraArgs.length > 0 ? cfg.extraArgs : void 0;
187499
+ },
187251
187500
  ...opts.backoff !== void 0 ? { backoff: opts.backoff } : {},
187252
187501
  ...opts.maxConcurrentProduce !== void 0 ? { maxConcurrentProduce: opts.maxConcurrentProduce } : {},
187253
187502
  // 每 agent 并发产出上限默认 5(工单数 / 全局总量默认不限);--max-produce-per-agent N 覆盖。
@@ -189567,12 +189816,21 @@ var COMMAND_DECLS = {
189567
189816
  examples: ["oasis actors --role dev", "oasis actors --kind agent"]
189568
189817
  },
189569
189818
  actor: {
189570
- usage: "oasis actor <actorId>",
189571
- description: "\u8FD9\u4E2A id \u5230\u5E95\u662F\u8C01\u2014\u2014\u5355\u4EBA\u5B8C\u6574\u6863\u6848\uFF08\u59D3\u540D/\u5C97\u4F4D/\u56E2\u961F/\u6C47\u62A5/\u80FD\u529B\u4ECB\u7ECD/\u64C5\u957F/\u90AE\u7BB1/\u72B6\u6001\uFF09\u3002",
189819
+ usage: "oasis actor <actorId> | oasis actor config <actorId> [--show | --extra-args-json '[...]']\uFF08\u4E00\u884C\u6587\u672C\u4ECE stdin \u8BFB\uFF09",
189820
+ description: "\u8FD9\u4E2A id \u5230\u5E95\u662F\u8C01\u2014\u2014\u5355\u4EBA\u5B8C\u6574\u6863\u6848\uFF08\u59D3\u540D/\u5C97\u4F4D/\u56E2\u961F/\u6C47\u62A5/\u80FD\u529B\u4ECB\u7ECD/\u64C5\u957F/\u90AE\u7BB1/\u72B6\u6001\uFF09\u3002\u5B50\u547D\u4EE4 `config` \u8BFB/\u5199\u5458\u5DE5\u7684 extraArgs\uFF08\u5E95\u5C42 CLI \u542F\u52A8\u53C2\u6570\uFF0C\u6BCF\u6B21\u6D3E\u53D1\u8FFD\u52A0\u5230 argv\uFF1B\u4EC5\u4EBA\u7C7B operator token \u53EF\u5199\uFF09\u3002",
189572
189821
  positional: [
189573
- { name: "<actorId>", required: true, desc: "\u89D2\u8272 id" }
189822
+ { name: "<actorId>", required: true, desc: "\u89D2\u8272 id\uFF08\u5199 extraArgs \u65F6\u662F `config` \u540E\u7684\u90A3\u4E2A id\uFF09" }
189823
+ ],
189824
+ flags: [
189825
+ { name: "show", boolean: true, desc: "config \u5B50\u547D\u4EE4\uFF1A\u53EA\u663E\u793A\u5F53\u524D extraArgs\uFF0C\u4E0D\u5199\u5165" },
189826
+ { name: "extra-args-json", desc: "config \u5B50\u547D\u4EE4\uFF1AJSON \u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u76F4\u63A5\u843D\u5E93\uFF08\u5DF2\u81EA\u5207\uFF09\u3002\u4E0D\u7ED9\u5219\u4ECE stdin \u8BFB\u4E00\u884C\u6587\u672C\u3001\u670D\u52A1\u7AEF shell-words \u5207\u5206" }
189574
189827
  ],
189575
- examples: ["oasis actor agent-dev-001"]
189828
+ examples: [
189829
+ "oasis actor agent-dev-001",
189830
+ "oasis actor config agent-dev-001 --show",
189831
+ "printf %s '--disallowedTools WebSearch,AskUserQuestion --effort max' | oasis actor config agent-dev-001",
189832
+ `oasis actor config agent-dev-001 --extra-args-json '["--disallowedTools","WebSearch,AskUserQuestion"]'`
189833
+ ]
189576
189834
  },
189577
189835
  roles: {
189578
189836
  usage: "oasis roles",
@@ -192462,6 +192720,57 @@ ${res.warning}`);
192462
192720
  // 员工」而非 500。命令签名与 status <id> / content <id> 同形(位置参数,不用 --id);不加 --company(公司
192463
192721
  // 由 token 定死,加了服务端也会忽略 = 假承诺)。每字段一行、人话标签、id 完整不截断。
192464
192722
  case "actor": {
192723
+ if (positional[0] === "config") {
192724
+ const actorId = needPos(
192725
+ positional,
192726
+ 1,
192727
+ "oasis actor config <actorId> [--show | --extra-args-json '[...]']\uFF08\u4E00\u884C\u6587\u672C\u4ECE stdin \u8BFB\uFF09"
192728
+ );
192729
+ const cfgPath = `/api/actors/${encodeURIComponent(actorId)}/config`;
192730
+ const forbiddenWrite = (e) => e instanceof ApiRequestError && e.status === 403 ? new Error("\u5199\u5458\u5DE5\u914D\u7F6E\u4EC5\u9650\u4EBA\u7C7B\u63A7\u5236\u53F0\u7528\u6237\uFF08operator token\uFF09\u3002") : void 0;
192731
+ const jsonFlag = flags.get("extra-args-json");
192732
+ const stdinRaw = jsonFlag === void 0 ? await readStdin() : "";
192733
+ const wantWrite = jsonFlag !== void 0 || stdinRaw.length > 0;
192734
+ if (flags.get("show") === "true" || !wantWrite) {
192735
+ let cfg2 = null;
192736
+ try {
192737
+ cfg2 = await api.request("GET", cfgPath);
192738
+ } catch (e) {
192739
+ if (e instanceof ApiRequestError && e.status === 404) {
192740
+ println("\u8BE5\u5458\u5DE5\u8FD8\u6CA1\u6709\u914D\u7F6E\u7248\u672C");
192741
+ break;
192742
+ }
192743
+ throw e;
192744
+ }
192745
+ const ea2 = cfg2?.extraArgs ?? [];
192746
+ println(`extraArgs: ${ea2.length ? ea2.join(" ") : "(\u7A7A)"}`);
192747
+ break;
192748
+ }
192749
+ let body;
192750
+ if (jsonFlag !== void 0) {
192751
+ let parsed;
192752
+ try {
192753
+ parsed = JSON.parse(jsonFlag);
192754
+ } catch {
192755
+ throw new Error("--extra-args-json \u4E0D\u662F\u5408\u6CD5 JSON");
192756
+ }
192757
+ if (!Array.isArray(parsed) || parsed.some((x2) => typeof x2 !== "string")) {
192758
+ throw new Error(`--extra-args-json \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4\uFF0C\u5982 '["--disallowedTools","A,B"]'`);
192759
+ }
192760
+ body = { extraArgs: parsed };
192761
+ } else {
192762
+ body = { extraArgs: stdinRaw };
192763
+ }
192764
+ let cfg;
192765
+ try {
192766
+ cfg = await api.request("POST", cfgPath, body);
192767
+ } catch (e) {
192768
+ throw forbiddenWrite(e) ?? e;
192769
+ }
192770
+ const ea = cfg.extraArgs ?? [];
192771
+ println(`\u5DF2\u5199\u5165\u914D\u7F6E v${cfg.version}\uFF1AextraArgs = ${ea.length ? ea.join(" ") : "(\u7A7A)"}`);
192772
+ break;
192773
+ }
192465
192774
  const id = needPos(positional, 0, "oasis actor <actorId>");
192466
192775
  const a = await api.request("GET", `/api/actors/${encodeURIComponent(id)}`);
192467
192776
  println(`id\uFF1A${a.id}`);
@@ -192984,7 +193293,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
192984
193293
  }
192985
193294
 
192986
193295
  // src/index.ts
192987
- var PKG_VERSION = true ? "0.1.95" : "dev";
193296
+ var PKG_VERSION = true ? "0.1.96" : "dev";
192988
193297
  var OASIS_DIR = path29.join(os10.homedir(), ".oasis");
192989
193298
  var CONFIG_FILE = path29.join(OASIS_DIR, "node-config.json");
192990
193299
  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.95",
3
+ "version": "0.1.96",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"