oasis_test 0.1.64 → 0.1.65

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 +239 -182
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1625,7 +1625,12 @@ var init_content_location_systems = __esm({
1625
1625
  { name: "id", required: true, description: "\u4ED3\u5E93\u903B\u8F91 id\u2014\u2014\u4F1E\u4ED3\u591A\u4ED3\u65F6\u533A\u5206\uFF0C\u65B9\u6848/\u4E0B\u6E38\u6309\u5B83\u5F15\u7528\uFF08\u4E0D\u5199\u5177\u4F53\u5730\u5740\uFF09" },
1626
1626
  { name: "remote", required: true, description: "\u8FDC\u7A0B URL\uFF08agent clone / \u7CFB\u7EDF\u96C6\u6210\u7528\uFF09" },
1627
1627
  { name: "develop", required: true, description: "\u96C6\u6210\u5206\u652F\u540D\uFF08\u5982 develop\uFF09" },
1628
- { name: "repoDir", required: false, description: "\u672C\u5730\u955C\u50CF\u76EE\u5F55\uFF08\u53EF\u9009\uFF0C\u7F3A\u7701\u81EA\u52A8\u6D3E\u751F\uFF09" }
1628
+ { name: "repoDir", required: false, description: "\u672C\u5730\u955C\u50CF\u76EE\u5F55\uFF08\u53EF\u9009\uFF0C\u7F3A\u7701\u81EA\u52A8\u6D3E\u751F\uFF09" },
1629
+ {
1630
+ name: "deployment",
1631
+ required: false,
1632
+ description: '\u81EA\u52A8\u90E8\u7F72\u58F0\u660E\uFF08\u53EF\u9009\uFF09\uFF1A\u586B\u4E86 = \u5408\u8FDB\u4E3B\u5E72\u540E\u7531 CD \u81EA\u52A8\u4E0A\u7EBF\uFF0C`cd`\uFF08\u4E0A\u7EBF\u6838\u9A8C\uFF09\u8282\u70B9\u636E\u6B64\u786E\u8BA4\u4EE3\u7801\u771F\u7684\u4E0A\u7EBF\u4E86\u624D\u653E\u884C\u4E0B\u6E38\u3002\u5F62\u5982 `{workflow:"deploy.yml", branch?:"develop", healthUrl?:"https://\u2026/healthz"}`\u2014\u2014workflow \u662F\u90E8\u7F72\u6D41\u6C34\u7EBF\u6587\u4EF6\u540D\uFF08\u5224\u636E\u2460\uFF1A\u8BE5 commit \u4E0A\u8FD9\u6761 run \u987B success\uFF09\uFF1BhealthUrl \u662F\u5065\u5EB7\u63A2\u9488\u5730\u5740\uFF0C\u5176 JSON \u54CD\u5E94\u91CC\u7684 gitSha \u7528\u6765\u786E\u8BA4\u7EBF\u4E0A\u8DD1\u7684\u786E\u5B9E\u5305\u542B\u672C\u6B21 commit\uFF08\u5224\u636E\u2461\uFF09\u3002**\u5F3A\u70C8\u5EFA\u8BAE\u586B healthUrl**\uFF1A\u53EA\u770B\u6D41\u6C34\u7EBF\u4F1A\u6F0F\u6389\u300C\u8DF3\u8FC7\u90E8\u7F72\u4E5F\u9000\u51FA 0\u300D\u90A3\u7C7B\u5047\u7EFF\u3002\u4E0D\u586B\u672C\u5B57\u6BB5 = \u8BE5\u4ED3\u6CA1\u6709\u81EA\u52A8\u90E8\u7F72\u6982\u5FF5\u3002'
1633
+ }
1629
1634
  ]
1630
1635
  }
1631
1636
  ];
@@ -2178,7 +2183,8 @@ var init_kernel = __esm({
2178
2183
  }
2179
2184
  }
2180
2185
  if (people.length > 0) {
2181
- requirements.push({ source: "manual", eligible: people, quorum: people.length });
2186
+ const q = Math.max(1, Math.min(gateSpec?.pinnedQuorum ?? people.length, people.length));
2187
+ requirements.push({ source: "manual", eligible: people, quorum: q });
2182
2188
  }
2183
2189
  const reviewers = [
2184
2190
  ...people.map((actor) => ({ actor, source: "manual" })),
@@ -2631,7 +2637,7 @@ var init_kernel = __esm({
2631
2637
  buildBucket("type", gateSpec.reviewers.flatMap((role) => this.roleIndex.get(role) ?? []), gateSpec.quorum, `\u7C7B\u578B\u89D2\u8272 roles=${gateSpec.reviewers.join(",")}`, gateSpec.reviewers);
2632
2638
  }
2633
2639
  if (manual.length > 0) {
2634
- buildBucket("manual", manual, manual.length, "\u6307\u5B9A\u4EBA\u4F4D");
2640
+ buildBucket("manual", manual, Math.max(1, Math.min(gateSpec?.pinnedQuorum ?? manual.length, manual.length)), "\u6307\u5B9A\u4EBA\u4F4D");
2635
2641
  }
2636
2642
  if (active.length > 0) {
2637
2643
  gate = { requirements: [...active, ...skipped] };
@@ -16560,7 +16566,7 @@ var require_form_data = __commonJS({
16560
16566
  var http2 = require("http");
16561
16567
  var https = require("https");
16562
16568
  var parseUrl = require("url").parse;
16563
- var fs29 = require("fs");
16569
+ var fs30 = require("fs");
16564
16570
  var Stream = require("stream").Stream;
16565
16571
  var crypto2 = require("crypto");
16566
16572
  var mime = require_mime_types();
@@ -16630,7 +16636,7 @@ var require_form_data = __commonJS({
16630
16636
  if (value.end != void 0 && value.end != Infinity && value.start != void 0) {
16631
16637
  callback(null, value.end + 1 - (value.start ? value.start : 0));
16632
16638
  } else {
16633
- fs29.stat(value.path, function(err, stat3) {
16639
+ fs30.stat(value.path, function(err, stat3) {
16634
16640
  if (err) {
16635
16641
  callback(err);
16636
16642
  return;
@@ -31205,7 +31211,7 @@ var require_lib2 = __commonJS({
31205
31211
  "use strict";
31206
31212
  Object.defineProperty(exports2, "__esModule", { value: true });
31207
31213
  var axios = require_axios();
31208
- var fs29 = require("fs");
31214
+ var fs30 = require("fs");
31209
31215
  var path24 = require("path");
31210
31216
  var crypto2 = require("crypto");
31211
31217
  var qs = require_lib();
@@ -31223,7 +31229,7 @@ var require_lib2 = __commonJS({
31223
31229
  return e && typeof e === "object" && "default" in e ? e : { "default": e };
31224
31230
  }
31225
31231
  var axios__default = /* @__PURE__ */ _interopDefaultLegacy(axios);
31226
- var fs__default = /* @__PURE__ */ _interopDefaultLegacy(fs29);
31232
+ var fs__default = /* @__PURE__ */ _interopDefaultLegacy(fs30);
31227
31233
  var path__default = /* @__PURE__ */ _interopDefaultLegacy(path24);
31228
31234
  var crypto__default = /* @__PURE__ */ _interopDefaultLegacy(crypto2);
31229
31235
  var identity__default = /* @__PURE__ */ _interopDefaultLegacy(identity);
@@ -135342,12 +135348,12 @@ var require_dist = __commonJS({
135342
135348
  throw new Error(`Unknown format "${name}"`);
135343
135349
  return f2;
135344
135350
  };
135345
- function addFormats(ajv, list, fs29, exportName) {
135351
+ function addFormats(ajv, list, fs30, exportName) {
135346
135352
  var _a;
135347
135353
  var _b;
135348
135354
  (_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
135349
135355
  for (const f2 of list)
135350
- ajv.addFormat(f2, fs29[f2]);
135356
+ ajv.addFormat(f2, fs30[f2]);
135351
135357
  }
135352
135358
  module2.exports = exports2 = formatsPlugin;
135353
135359
  Object.defineProperty(exports2, "__esModule", { value: true });
@@ -137176,7 +137182,7 @@ function buildTypeReviewerResolver(types2, actors) {
137176
137182
  if (gate.reviewers.length > 0) {
137177
137183
  requirements.push({ source: "type", eligible: reviewers, quorum: gate.quorum, roles: [...gate.reviewers] });
137178
137184
  }
137179
- if (pinned.length > 0) requirements.push({ source: "manual", eligible: pinned, quorum: pinned.length });
137185
+ if (pinned.length > 0) requirements.push({ source: "manual", eligible: pinned, quorum: Math.max(1, Math.min(gate.pinnedQuorum ?? pinned.length, pinned.length)) });
137180
137186
  return {
137181
137187
  reviewers: reviewers.map((actor) => ({ actor, source: "type" })),
137182
137188
  quorum: requirements.reduce((n, r) => n + r.quorum, 0),
@@ -144512,7 +144518,8 @@ var init_types_admin = __esm({
144512
144518
  (r) => r.startsWith("actor:"),
144513
144519
  "\u8FD9\u91CC\u586B\u7684\u662F**\u5177\u4F53\u67D0\u4E2A\u4EBA/agent**\uFF08\u5982 actor:human:zhangsan\uFF09\u3002\u8981\u6309\u5C97\u4F4D\u5B9A\u5BA1\u6838\uFF0C\u8BF7\u586B\u4E0A\u9762\u7684\u8BC4\u5BA1\u89D2\u8272"
144514
144520
  )
144515
- ).optional()
144521
+ ).optional(),
144522
+ pinnedQuorum: external_exports.number().int().positive().optional()
144516
144523
  }).strict()
144517
144524
  ).optional()
144518
144525
  }).strict(),
@@ -145239,6 +145246,13 @@ function githubSlugFromRemote(remote) {
145239
145246
  const m2 = /^github\.com\/([^/]+)\/([^/]+)/i.exec(n);
145240
145247
  return m2 ? `${m2[1]}/${m2[2]}` : null;
145241
145248
  }
145249
+ function deployedFromCompareStatus(status, observed) {
145250
+ if (status === "identical" || status === "ahead") {
145251
+ return { deployed: true, note: `\u7EBF\u4E0A ${observed.slice(0, 8)} \u5DF2\u5305\u542B\u672C\u6B21\u6539\u52A8` };
145252
+ }
145253
+ if (status === "behind") return { deployed: false, note: "\u7EBF\u4E0A\u662F\u66F4\u65E7\u7684\u7248\u672C" };
145254
+ return { deployed: false, note: `\u7EBF\u4E0A\u4E0E\u672C\u6B21\u5206\u53C9\uFF08${status || "\u672A\u77E5"}\uFF09` };
145255
+ }
145242
145256
  var import_node_child_process5, import_node_util2, execFile2, GhDeployProvider;
145243
145257
  var init_deploy_provider = __esm({
145244
145258
  "../server/src/git/deploy-provider.ts"() {
@@ -145288,21 +145302,49 @@ var init_deploy_provider = __esm({
145288
145302
  runUrl: run.url
145289
145303
  };
145290
145304
  }
145291
- if (probe.gitSha !== sha2) {
145305
+ const verdict = await this.compareDeployed(slug5, sha2, probe.gitSha);
145306
+ if (verdict.deployed) {
145292
145307
  return {
145293
- state: "failure",
145294
- kind: "sha-mismatch",
145295
- summary: `${repo.id}: \u90E8\u7F72\u6D41\u6C34\u7EBF\u62A5\u544A\u6210\u529F\uFF0C\u4F46\u7EBF\u4E0A\u8DD1\u7684\u662F ${probe.gitSha?.slice(0, 8) ?? "(\u672A\u77E5)"}\u3001\u672C\u6B21\u5E94\u4E3A ${sha2.slice(0, 8)} \u2014\u2014 \u90E8\u7F72\u88AB\u8DF3\u8FC7\u4E86\uFF0C\u5148\u68C0\u67E5\u90E8\u7F72\u6E90\u4ED3\u662F\u4E0D\u662F\u505C\u5728\u522B\u7684\u5206\u652F`,
145296
- ...probe.gitSha ? { observedSha: probe.gitSha } : {},
145308
+ state: "success",
145309
+ summary: `${repo.id}: \u5DF2\u4E0A\u7EBF ${sha2.slice(0, 8)}${verdict.note ? `\uFF08${verdict.note}\uFF09` : "\uFF08\u6D41\u6C34\u7EBF\u901A\u8FC7 + \u63A2\u9488\u6838\u5BF9\u4E00\u81F4\uFF09"}`,
145297
145310
  runUrl: run.url
145298
145311
  };
145299
145312
  }
145300
145313
  return {
145301
- state: "success",
145302
- summary: `${repo.id}: \u5DF2\u4E0A\u7EBF ${sha2.slice(0, 8)}\uFF08\u6D41\u6C34\u7EBF\u901A\u8FC7 + \u63A2\u9488\u6838\u5BF9\u4E00\u81F4\uFF09`,
145314
+ state: "failure",
145315
+ kind: "sha-mismatch",
145316
+ summary: `${repo.id}: \u90E8\u7F72\u6D41\u6C34\u7EBF\u62A5\u544A\u6210\u529F\uFF0C\u4F46\u7EBF\u4E0A\u8DD1\u7684\u662F ${probe.gitSha?.slice(0, 8) ?? "(\u672A\u77E5)"}\u3001\u672C\u6B21\u5E94\u4E3A ${sha2.slice(0, 8)}${verdict.note ? `\uFF08${verdict.note}\uFF09` : ""} \u2014\u2014 \u672C\u6B21\u6539\u52A8\u6CA1\u6709\u4E0A\u7EBF\uFF0C\u5148\u68C0\u67E5\u90E8\u7F72\u6E90\u4ED3\u662F\u4E0D\u662F\u505C\u5728\u522B\u7684\u5206\u652F`,
145317
+ ...probe.gitSha ? { observedSha: probe.gitSha } : {},
145303
145318
  runUrl: run.url
145304
145319
  };
145305
145320
  }
145321
+ /**
145322
+ * 判据②的实际判定:**线上跑的 commit 是否「包含」本次交付的 commit**——相等,或是它的后代。
145323
+ *
145324
+ * 为什么不能要求严格相等(2026-07-22 真实数据实测发现):主干是活的,从「本次合并进主干」到
145325
+ * 「本节点来核验」之间几乎总有别人的提交挤进来并触发新一轮部署,于是线上 sha **领先**于本次 sha。
145326
+ * 那时本次改动其实**早就上线了**(被包含在更新的 commit 里),严格相等却会判失败——闸会在真实
145327
+ * 环境里几乎总是误报,卡住下游、还误升级到收件箱。实测:线上 `2c3f3449` 是本次 `80d6a4ff` 的后代,
145328
+ * 严格相等判 sha-mismatch,而正确答案是「已上线」。
145329
+ *
145330
+ * 与 MergeWorker 的 `isMerged` 同一思路:**内容已被权威分支接纳**即算数,而不是逐字比对指针。
145331
+ * 落后(线上是旧版)与分叉(线上跑的是另一条线)都判未上线——那才是真正要拦的。
145332
+ */
145333
+ async compareDeployed(slug5, sha2, observed) {
145334
+ if (!observed) return { deployed: false, note: "\u63A2\u9488\u6CA1\u62A5\u51FA gitSha" };
145335
+ if (observed === sha2) return { deployed: true };
145336
+ try {
145337
+ const { stdout } = await execFile2(
145338
+ "gh",
145339
+ ["api", `repos/${slug5}/compare/${sha2}...${observed}`, "--jq", ".status"],
145340
+ { env: process.env, timeout: 3e4 }
145341
+ );
145342
+ return deployedFromCompareStatus(stdout.trim(), observed);
145343
+ } catch (e) {
145344
+ this.opts.log?.(`[cd] \u6BD4\u8F83 ${sha2.slice(0, 8)}\u2026${observed.slice(0, 8)} \u5931\u8D25\uFF0C\u9000\u5316\u4E3A\u4E25\u683C\u76F8\u7B49\uFF1A${String(e)}`);
145345
+ return { deployed: false, note: "\u65E0\u6CD5\u786E\u8BA4\u7EBF\u4E0A\u7248\u672C\u662F\u5426\u5305\u542B\u672C\u6B21\u6539\u52A8\uFF08\u6BD4\u8F83\u63A5\u53E3\u8C03\u7528\u5931\u8D25\uFF09" };
145346
+ }
145347
+ }
145306
145348
  /** 无流水线可读时的退化路径:只认探针。探针也没有 → pending(上层据此判「无判据」)。 */
145307
145349
  async probeOnly(deployment, sha2, prefix) {
145308
145350
  if (!deployment.healthUrl) return { state: "pending", summary: `${prefix}\uFF0C\u4E14\u672A\u914D\u5065\u5EB7\u63A2\u9488\u2014\u2014\u65E0\u5224\u636E\u53EF\u7528` };
@@ -145314,7 +145356,7 @@ var init_deploy_provider = __esm({
145314
145356
  return {
145315
145357
  state: "failure",
145316
145358
  kind: "sha-mismatch",
145317
- summary: `${prefix}\uFF1B\u7EBF\u4E0A\u8DD1\u7684\u662F ${probe.gitSha?.slice(0, 8) ?? "(\u672A\u77E5)"}\u3001\u672C\u6B21\u5E94\u4E3A ${sha2.slice(0, 8)}`,
145359
+ summary: `${prefix}\uFF1B\u7EBF\u4E0A\u8DD1\u7684\u662F ${probe.gitSha?.slice(0, 8) ?? "(\u672A\u77E5)"}\u3001\u672C\u6B21\u5E94\u4E3A ${sha2.slice(0, 8)}\uFF08\u975E GitHub \u4ED3\u65E0\u6CD5\u5224\u65AD\u7EBF\u4E0A\u662F\u5426\u5DF2\u5305\u542B\u672C\u6B21\u6539\u52A8\uFF0C\u53EA\u505A\u4E86\u4E25\u683C\u6BD4\u5BF9\uFF09`,
145318
145360
  ...probe.gitSha ? { observedSha: probe.gitSha } : {}
145319
145361
  };
145320
145362
  }
@@ -149062,6 +149104,21 @@ var init_session_paths = __esm({
149062
149104
  }
149063
149105
  });
149064
149106
 
149107
+ // ../adapters/src/_core/transcript.ts
149108
+ function openTranscript(file) {
149109
+ const out = fs12.createWriteStream(file);
149110
+ out.on("error", () => {
149111
+ });
149112
+ return out;
149113
+ }
149114
+ var fs12;
149115
+ var init_transcript = __esm({
149116
+ "../adapters/src/_core/transcript.ts"() {
149117
+ "use strict";
149118
+ fs12 = __toESM(require("node:fs"), 1);
149119
+ }
149120
+ });
149121
+
149065
149122
  // ../adapters/src/claude-code/index.ts
149066
149123
  function normalizeClaudeStreamLine(line) {
149067
149124
  let parsed;
@@ -149226,19 +149283,20 @@ function classifyExit(result) {
149226
149283
  if (status === 429 || status === 529) return "rate-limit";
149227
149284
  return "error";
149228
149285
  }
149229
- var import_node_child_process9, import_node_crypto14, fs12, path11, readline, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
149286
+ var import_node_child_process9, import_node_crypto14, fs13, path11, readline, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
149230
149287
  var init_claude_code = __esm({
149231
149288
  "../adapters/src/claude-code/index.ts"() {
149232
149289
  "use strict";
149233
149290
  import_node_child_process9 = require("node:child_process");
149234
149291
  import_node_crypto14 = require("node:crypto");
149235
- fs12 = __toESM(require("node:fs"), 1);
149292
+ fs13 = __toESM(require("node:fs"), 1);
149236
149293
  path11 = __toESM(require("node:path"), 1);
149237
149294
  readline = __toESM(require("node:readline"), 1);
149238
149295
  init_sync_skills();
149239
149296
  init_materialize_bundle();
149240
149297
  init_resume_classify();
149241
149298
  init_session_paths();
149299
+ init_transcript();
149242
149300
  ONE_SHOT_UNSAFE_TOOLS = ["ScheduleWakeup", "CronCreate", "CronDelete", "CronList"];
149243
149301
  ClaudeCodeAdapter = class {
149244
149302
  constructor(opts = {}) {
@@ -149290,7 +149348,7 @@ var init_claude_code = __esm({
149290
149348
  runtimeKind: "claude"
149291
149349
  }
149292
149350
  });
149293
- fs12.mkdirSync(dir, { recursive: true });
149351
+ fs13.mkdirSync(dir, { recursive: true });
149294
149352
  await runSyncSkills(this.opts.syncSkills, {
149295
149353
  actorId: job.actor,
149296
149354
  actorToken: job.actorToken,
@@ -149342,7 +149400,7 @@ var init_claude_code = __esm({
149342
149400
  if (promptViaStdin) child.stdin.write(prompt);
149343
149401
  child.stdin.end();
149344
149402
  let transcriptRef = path11.join(dir, "transcript.txt");
149345
- const out = fs12.createWriteStream(transcriptRef);
149403
+ const out = openTranscript(transcriptRef);
149346
149404
  const telemetryCbs = [];
149347
149405
  let eventSeq = 0;
149348
149406
  let lastResult;
@@ -149438,13 +149496,13 @@ var init_claude_code = __esm({
149438
149496
  if (this.opts.cleanupWorkdir && isOneShot) {
149439
149497
  try {
149440
149498
  const keepDir = path11.join(resolveWorkRoot(this.opts.workRoot), "oasis-transcripts");
149441
- fs12.mkdirSync(keepDir, { recursive: true });
149499
+ fs13.mkdirSync(keepDir, { recursive: true });
149442
149500
  const kept = path11.join(keepDir, `${id}.txt`);
149443
149501
  const src = transcriptRef;
149444
149502
  out.end(() => {
149445
149503
  try {
149446
- fs12.renameSync(src, kept);
149447
- fs12.rmSync(dir, { recursive: true, force: true });
149504
+ fs13.renameSync(src, kept);
149505
+ fs13.rmSync(dir, { recursive: true, force: true });
149448
149506
  } catch {
149449
149507
  }
149450
149508
  });
@@ -150264,7 +150322,7 @@ function codexSessionsRoot() {
150264
150322
  if (home) candidates.push(path13.join(home, ".codex", "sessions"));
150265
150323
  for (const c of candidates) {
150266
150324
  try {
150267
- if (fs13.statSync(c).isDirectory()) return c;
150325
+ if (fs14.statSync(c).isDirectory()) return c;
150268
150326
  } catch {
150269
150327
  }
150270
150328
  }
@@ -150276,7 +150334,7 @@ function listRecentRollouts(root, sinceMs) {
150276
150334
  const walk = (d) => {
150277
150335
  let ents;
150278
150336
  try {
150279
- ents = fs13.readdirSync(d, { withFileTypes: true });
150337
+ ents = fs14.readdirSync(d, { withFileTypes: true });
150280
150338
  } catch {
150281
150339
  return;
150282
150340
  }
@@ -150286,7 +150344,7 @@ function listRecentRollouts(root, sinceMs) {
150286
150344
  else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(".jsonl")) {
150287
150345
  let m2 = 0;
150288
150346
  try {
150289
- m2 = fs13.statSync(p2).mtimeMs;
150347
+ m2 = fs14.statSync(p2).mtimeMs;
150290
150348
  } catch {
150291
150349
  }
150292
150350
  if (m2 >= margin) found.push({ f: p2, m: m2 });
@@ -150311,7 +150369,7 @@ function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
150311
150369
  const files = listRecentRollouts(sessionsRoot, sinceMs);
150312
150370
  const readLines = (f2) => {
150313
150371
  try {
150314
- return fs13.readFileSync(f2, "utf8").split("\n");
150372
+ return fs14.readFileSync(f2, "utf8").split("\n");
150315
150373
  } catch {
150316
150374
  return null;
150317
150375
  }
@@ -150511,13 +150569,13 @@ function normalizeCodexConsoleLine(line, state = createCodexNormalizeState()) {
150511
150569
  tool.output.push(line);
150512
150570
  return [];
150513
150571
  }
150514
- var import_node_child_process11, import_node_crypto15, fs13, os4, path13, readline2, CodexAdapter;
150572
+ var import_node_child_process11, import_node_crypto15, fs14, os4, path13, readline2, CodexAdapter;
150515
150573
  var init_codex = __esm({
150516
150574
  "../adapters/src/codex/index.ts"() {
150517
150575
  "use strict";
150518
150576
  import_node_child_process11 = require("node:child_process");
150519
150577
  import_node_crypto15 = require("node:crypto");
150520
- fs13 = __toESM(require("node:fs"), 1);
150578
+ fs14 = __toESM(require("node:fs"), 1);
150521
150579
  os4 = __toESM(require("node:os"), 1);
150522
150580
  path13 = __toESM(require("node:path"), 1);
150523
150581
  readline2 = __toESM(require("node:readline"), 1);
@@ -150526,6 +150584,7 @@ var init_codex = __esm({
150526
150584
  init_resume_classify();
150527
150585
  init_session_paths();
150528
150586
  init_claude_code();
150587
+ init_transcript();
150529
150588
  CodexAdapter = class {
150530
150589
  constructor(opts = {}) {
150531
150590
  this.opts = opts;
@@ -150596,7 +150655,7 @@ var init_codex = __esm({
150596
150655
  });
150597
150656
  if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
150598
150657
  let transcriptRef = path13.join(dir, "transcript.txt");
150599
- const out = fs13.createWriteStream(transcriptRef);
150658
+ const out = openTranscript(transcriptRef);
150600
150659
  const outputCbs = [];
150601
150660
  const telemetryCbs = [];
150602
150661
  const normalizeState = createCodexNormalizeState();
@@ -150667,13 +150726,13 @@ var init_codex = __esm({
150667
150726
  if (this.opts.cleanupWorkdir && !job.workdirKey) {
150668
150727
  try {
150669
150728
  const keepDir = path13.join(resolveWorkRoot(this.opts.workRoot), "oasis-transcripts");
150670
- fs13.mkdirSync(keepDir, { recursive: true });
150729
+ fs14.mkdirSync(keepDir, { recursive: true });
150671
150730
  const kept = path13.join(keepDir, `${id}.txt`);
150672
150731
  const src = transcriptRef;
150673
150732
  out.end(() => {
150674
150733
  try {
150675
- fs13.renameSync(src, kept);
150676
- fs13.rmSync(dir, { recursive: true, force: true });
150734
+ fs14.renameSync(src, kept);
150735
+ fs14.rmSync(dir, { recursive: true, force: true });
150677
150736
  } catch {
150678
150737
  }
150679
150738
  });
@@ -151318,7 +151377,7 @@ async function runACPSession(job, cfg) {
151318
151377
  });
151319
151378
  if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
151320
151379
  let transcriptRef = path14.join(dir, "transcript.txt");
151321
- const transcriptOut = fs14.createWriteStream(transcriptRef);
151380
+ const transcriptOut = openTranscript(transcriptRef);
151322
151381
  const outputCbs = [];
151323
151382
  const telemetryCbs = [];
151324
151383
  const exitCbs = [];
@@ -151341,13 +151400,13 @@ async function runACPSession(job, cfg) {
151341
151400
  if (cfg.cleanupWorkdir && !job.workdirKey) {
151342
151401
  try {
151343
151402
  const keepDir = path14.join(resolveWorkRoot(cfg.workRoot), "oasis-transcripts");
151344
- fs14.mkdirSync(keepDir, { recursive: true });
151403
+ fs15.mkdirSync(keepDir, { recursive: true });
151345
151404
  const kept = path14.join(keepDir, `${id}.txt`);
151346
151405
  const src = transcriptRef;
151347
151406
  transcriptOut.end(() => {
151348
151407
  try {
151349
- fs14.renameSync(src, kept);
151350
- fs14.rmSync(dir, { recursive: true, force: true });
151408
+ fs15.renameSync(src, kept);
151409
+ fs15.rmSync(dir, { recursive: true, force: true });
151351
151410
  } catch {
151352
151411
  }
151353
151412
  });
@@ -151550,13 +151609,13 @@ ${task}` : task;
151550
151609
  }
151551
151610
  };
151552
151611
  }
151553
- var import_node_child_process12, import_node_crypto16, fs14, path14, readline3, ACPClient;
151612
+ var import_node_child_process12, import_node_crypto16, fs15, path14, readline3, ACPClient;
151554
151613
  var init_acp = __esm({
151555
151614
  "../adapters/src/_core/acp.ts"() {
151556
151615
  "use strict";
151557
151616
  import_node_child_process12 = require("node:child_process");
151558
151617
  import_node_crypto16 = require("node:crypto");
151559
- fs14 = __toESM(require("node:fs"), 1);
151618
+ fs15 = __toESM(require("node:fs"), 1);
151560
151619
  path14 = __toESM(require("node:path"), 1);
151561
151620
  readline3 = __toESM(require("node:readline"), 1);
151562
151621
  init_sync_skills();
@@ -151566,6 +151625,7 @@ var init_acp = __esm({
151566
151625
  init_materialize_bundle();
151567
151626
  init_usage();
151568
151627
  init_pricing();
151628
+ init_transcript();
151569
151629
  ACPClient = class {
151570
151630
  constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false) {
151571
151631
  this.write = write;
@@ -151958,13 +152018,13 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, workdirKey, e
151958
152018
  if (cfg.cleanupWorkdir && !workdirKey) {
151959
152019
  try {
151960
152020
  const keepDir = path15.join(resolveWorkRoot(cfg.workRoot), "oasis-transcripts");
151961
- fs15.mkdirSync(keepDir, { recursive: true });
152021
+ fs16.mkdirSync(keepDir, { recursive: true });
151962
152022
  const kept = path15.join(keepDir, `${id}.txt`);
151963
152023
  const src = transcriptRefPtr.value;
151964
152024
  transcriptOut.end(() => {
151965
152025
  try {
151966
- fs15.renameSync(src, kept);
151967
- fs15.rmSync(dir, { recursive: true, force: true });
152026
+ fs16.renameSync(src, kept);
152027
+ fs16.rmSync(dir, { recursive: true, force: true });
151968
152028
  } catch {
151969
152029
  }
151970
152030
  });
@@ -151988,9 +152048,7 @@ async function runStreamJson(job, cfg) {
151988
152048
  });
151989
152049
  if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
151990
152050
  const transcriptRefPtr = { value: path15.join(dir, "transcript.txt") };
151991
- const transcriptOut = fs15.createWriteStream(transcriptRefPtr.value);
151992
- transcriptOut.on("error", () => {
151993
- });
152051
+ const transcriptOut = openTranscript(transcriptRefPtr.value);
151994
152052
  const outputCbs = [];
151995
152053
  const telemetryCbs = [];
151996
152054
  const exitCbs = [];
@@ -152067,9 +152125,7 @@ async function runOneShotText(job, cfg) {
152067
152125
  });
152068
152126
  if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
152069
152127
  const transcriptRefPtr = { value: path15.join(dir, "transcript.txt") };
152070
- const transcriptOut = fs15.createWriteStream(transcriptRefPtr.value);
152071
- transcriptOut.on("error", () => {
152072
- });
152128
+ const transcriptOut = openTranscript(transcriptRefPtr.value);
152073
152129
  const outputCbs = [];
152074
152130
  const exitCbs = [];
152075
152131
  const { finish, exited } = makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, job.workdirKey, exitCbs);
@@ -152126,19 +152182,20 @@ async function runOneShotText(job, cfg) {
152126
152182
  }
152127
152183
  });
152128
152184
  }
152129
- var import_node_child_process13, import_node_crypto17, fs15, path15, readline4;
152185
+ var import_node_child_process13, import_node_crypto17, fs16, path15, readline4;
152130
152186
  var init_subprocess = __esm({
152131
152187
  "../adapters/src/_core/subprocess.ts"() {
152132
152188
  "use strict";
152133
152189
  import_node_child_process13 = require("node:child_process");
152134
152190
  import_node_crypto17 = require("node:crypto");
152135
- fs15 = __toESM(require("node:fs"), 1);
152191
+ fs16 = __toESM(require("node:fs"), 1);
152136
152192
  path15 = __toESM(require("node:path"), 1);
152137
152193
  readline4 = __toESM(require("node:readline"), 1);
152138
152194
  init_claude_code();
152139
152195
  init_materialize_bundle();
152140
152196
  init_sync_skills();
152141
152197
  init_session_paths();
152198
+ init_transcript();
152142
152199
  }
152143
152200
  });
152144
152201
 
@@ -156131,11 +156188,11 @@ var init_roles = __esm({
156131
156188
  });
156132
156189
 
156133
156190
  // ../server/src/node-store.ts
156134
- var fs18, MemoryNodeStore, FileNodeStore;
156191
+ var fs19, MemoryNodeStore, FileNodeStore;
156135
156192
  var init_node_store = __esm({
156136
156193
  "../server/src/node-store.ts"() {
156137
156194
  "use strict";
156138
- fs18 = __toESM(require("node:fs"), 1);
156195
+ fs19 = __toESM(require("node:fs"), 1);
156139
156196
  MemoryNodeStore = class {
156140
156197
  nodes = /* @__PURE__ */ new Map();
156141
156198
  runtimes = /* @__PURE__ */ new Map();
@@ -156220,16 +156277,16 @@ var init_node_store = __esm({
156220
156277
  static async open(file) {
156221
156278
  const s2 = new _FileNodeStore(file);
156222
156279
  try {
156223
- const snap = JSON.parse(fs18.readFileSync(file, "utf8"));
156280
+ const snap = JSON.parse(fs19.readFileSync(file, "utf8"));
156224
156281
  for (const n of snap.nodes ?? []) s2.nodes.set(n.id, n);
156225
156282
  for (const r of snap.runtimes ?? []) s2.runtimes.set(r.id, r);
156226
156283
  } catch {
156227
- fs18.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
156284
+ fs19.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
156228
156285
  }
156229
156286
  return s2;
156230
156287
  }
156231
156288
  flush() {
156232
- fs18.writeFileSync(this.file, JSON.stringify({
156289
+ fs19.writeFileSync(this.file, JSON.stringify({
156233
156290
  nodes: [...this.nodes.values()],
156234
156291
  runtimes: [...this.runtimes.values()]
156235
156292
  }, null, 2));
@@ -160161,22 +160218,22 @@ var init_engine = __esm({
160161
160218
  });
160162
160219
 
160163
160220
  // ../server/src/mirror/fs-state.ts
160164
- var fs20, FsMirrorStateStore;
160221
+ var fs21, FsMirrorStateStore;
160165
160222
  var init_fs_state = __esm({
160166
160223
  "../server/src/mirror/fs-state.ts"() {
160167
160224
  "use strict";
160168
- fs20 = __toESM(require("node:fs"), 1);
160225
+ fs21 = __toESM(require("node:fs"), 1);
160169
160226
  FsMirrorStateStore = class {
160170
160227
  constructor(file) {
160171
160228
  this.file = file;
160172
- if (fs20.existsSync(file)) {
160173
- const obj = JSON.parse(fs20.readFileSync(file, "utf8"));
160229
+ if (fs21.existsSync(file)) {
160230
+ const obj = JSON.parse(fs21.readFileSync(file, "utf8"));
160174
160231
  for (const [k2, v2] of Object.entries(obj)) this.map.set(k2, v2);
160175
160232
  }
160176
160233
  }
160177
160234
  map = /* @__PURE__ */ new Map();
160178
160235
  flush() {
160179
- fs20.writeFileSync(this.file, JSON.stringify(Object.fromEntries(this.map), null, 2));
160236
+ fs21.writeFileSync(this.file, JSON.stringify(Object.fromEntries(this.map), null, 2));
160180
160237
  }
160181
160238
  async get(artifactId) {
160182
160239
  return this.map.get(artifactId) ?? null;
@@ -160193,12 +160250,12 @@ var init_fs_state = __esm({
160193
160250
  });
160194
160251
 
160195
160252
  // ../server/src/git/integrate.ts
160196
- var import_node_child_process14, fs21, path18, GitRemoteIntegrator;
160253
+ var import_node_child_process14, fs22, path18, GitRemoteIntegrator;
160197
160254
  var init_integrate = __esm({
160198
160255
  "../server/src/git/integrate.ts"() {
160199
160256
  "use strict";
160200
160257
  import_node_child_process14 = require("node:child_process");
160201
- fs21 = __toESM(require("node:fs"), 1);
160258
+ fs22 = __toESM(require("node:fs"), 1);
160202
160259
  path18 = __toESM(require("node:path"), 1);
160203
160260
  GitRemoteIntegrator = class {
160204
160261
  constructor(remote, cloneDir, develop = "develop") {
@@ -160216,8 +160273,8 @@ var init_integrate = __esm({
160216
160273
  }
160217
160274
  /** 确保本地工作克隆存在并拉到最新远程态。幂等。 */
160218
160275
  sync() {
160219
- if (!fs21.existsSync(path18.join(this.cloneDir, ".git"))) {
160220
- fs21.mkdirSync(path18.dirname(this.cloneDir), { recursive: true });
160276
+ if (!fs22.existsSync(path18.join(this.cloneDir, ".git"))) {
160277
+ fs22.mkdirSync(path18.dirname(this.cloneDir), { recursive: true });
160221
160278
  (0, import_node_child_process14.execFileSync)("git", ["clone", "--quiet", this.remote, this.cloneDir], { env: this.env, maxBuffer: 256 * 1024 * 1024 });
160222
160279
  this.git(["config", "user.email", "oasis@local"]);
160223
160280
  this.git(["config", "user.name", "oasis"]);
@@ -163018,15 +163075,15 @@ var require_pg_connection_string = __commonJS({
163018
163075
  if (config2.sslcert || config2.sslkey || config2.sslrootcert || config2.sslmode) {
163019
163076
  config2.ssl = {};
163020
163077
  }
163021
- const fs29 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
163078
+ const fs30 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
163022
163079
  if (config2.sslcert) {
163023
- config2.ssl.cert = fs29.readFileSync(config2.sslcert).toString();
163080
+ config2.ssl.cert = fs30.readFileSync(config2.sslcert).toString();
163024
163081
  }
163025
163082
  if (config2.sslkey) {
163026
- config2.ssl.key = fs29.readFileSync(config2.sslkey).toString();
163083
+ config2.ssl.key = fs30.readFileSync(config2.sslkey).toString();
163027
163084
  }
163028
163085
  if (config2.sslrootcert) {
163029
- config2.ssl.ca = fs29.readFileSync(config2.sslrootcert).toString();
163086
+ config2.ssl.ca = fs30.readFileSync(config2.sslrootcert).toString();
163030
163087
  }
163031
163088
  if (options.useLibpqCompat && config2.uselibpqcompat) {
163032
163089
  throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
@@ -164963,15 +165020,15 @@ var require_lib3 = __commonJS({
164963
165020
  "../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js"(exports2, module2) {
164964
165021
  "use strict";
164965
165022
  var path24 = require("path");
164966
- var fs29 = require("fs");
165023
+ var fs30 = require("fs");
164967
165024
  var helper = require_helper();
164968
165025
  module2.exports = function(connInfo, cb) {
164969
165026
  var file = helper.getFileName();
164970
- fs29.stat(file, function(err, stat3) {
165027
+ fs30.stat(file, function(err, stat3) {
164971
165028
  if (err || !helper.usePgPass(stat3, file)) {
164972
165029
  return cb(void 0);
164973
165030
  }
164974
- var st = fs29.createReadStream(file);
165031
+ var st = fs30.createReadStream(file);
164975
165032
  helper.getPassword(connInfo, st, cb);
164976
165033
  });
164977
165034
  };
@@ -170835,37 +170892,37 @@ __export(trajectory_exports, {
170835
170892
  });
170836
170893
  async function exportTrajectories(dataDir) {
170837
170894
  const root = path19.join(dataDir, "trajectories");
170838
- if (!fs24.existsSync(root)) return [];
170895
+ if (!fs25.existsSync(root)) return [];
170839
170896
  const model = emptyReadModel();
170840
170897
  const oplogFile = path19.join(dataDir, "oplog.ndjson");
170841
- if (fs24.existsSync(oplogFile)) {
170898
+ if (fs25.existsSync(oplogFile)) {
170842
170899
  const oplog = await NdjsonOplogStore.open(oplogFile);
170843
170900
  for await (const entry of oplog.readAll()) fold(model, entry.op);
170844
170901
  }
170845
170902
  const samples = [];
170846
- for (const runId of fs24.readdirSync(root).sort()) {
170903
+ for (const runId of fs25.readdirSync(root).sort()) {
170847
170904
  const dir = path19.join(root, runId);
170848
170905
  const sessionFile = path19.join(dir, "session.json");
170849
- if (!fs24.existsSync(sessionFile)) continue;
170850
- const session = { ...JSON.parse(fs24.readFileSync(sessionFile, "utf8")), runId };
170906
+ if (!fs25.existsSync(sessionFile)) continue;
170907
+ const session = { ...JSON.parse(fs25.readFileSync(sessionFile, "utf8")), runId };
170851
170908
  const events = [];
170852
170909
  const eventsFile = path19.join(dir, "events.ndjson");
170853
- if (fs24.existsSync(eventsFile)) {
170854
- for (const line of fs24.readFileSync(eventsFile, "utf8").split("\n")) {
170910
+ if (fs25.existsSync(eventsFile)) {
170911
+ for (const line of fs25.readFileSync(eventsFile, "utf8").split("\n")) {
170855
170912
  if (line.trim()) events.push(JSON.parse(line));
170856
170913
  }
170857
170914
  }
170858
170915
  const bundle = {};
170859
170916
  const bundleDir = path19.join(dir, "bundle");
170860
170917
  const walk = (sub) => {
170861
- for (const name of fs24.readdirSync(path19.join(bundleDir, sub))) {
170918
+ for (const name of fs25.readdirSync(path19.join(bundleDir, sub))) {
170862
170919
  const rel = sub ? `${sub}/${name}` : name;
170863
170920
  const full = path19.join(bundleDir, rel);
170864
- if (fs24.statSync(full).isDirectory()) walk(rel);
170865
- else bundle[rel] = fs24.readFileSync(full, "utf8");
170921
+ if (fs25.statSync(full).isDirectory()) walk(rel);
170922
+ else bundle[rel] = fs25.readFileSync(full, "utf8");
170866
170923
  }
170867
170924
  };
170868
- if (fs24.existsSync(bundleDir)) walk("");
170925
+ if (fs25.existsSync(bundleDir)) walk("");
170869
170926
  const proposed = (session.opRefs ?? []).filter((r) => r.kind === "propose_revision").map((r) => r.target);
170870
170927
  const verdicts = proposed.flatMap(
170871
170928
  (rev) => (model.reviews.get(rev) ?? []).map((v2) => ({ author: v2.author, verdict: v2.verdict, ...v2.note !== void 0 ? { note: v2.note } : {} }))
@@ -170877,11 +170934,11 @@ async function exportTrajectories(dataDir) {
170877
170934
  }
170878
170935
  return samples;
170879
170936
  }
170880
- var fs24, path19, FsTrajectorySink;
170937
+ var fs25, path19, FsTrajectorySink;
170881
170938
  var init_trajectory = __esm({
170882
170939
  "../cli/src/trajectory.ts"() {
170883
170940
  "use strict";
170884
- fs24 = __toESM(require("node:fs"), 1);
170941
+ fs25 = __toESM(require("node:fs"), 1);
170885
170942
  path19 = __toESM(require("node:path"), 1);
170886
170943
  init_src2();
170887
170944
  init_src7();
@@ -170896,32 +170953,32 @@ var init_trajectory = __esm({
170896
170953
  }
170897
170954
  begin(session, bundleFiles) {
170898
170955
  const dir = this.dir(session.runId);
170899
- fs24.mkdirSync(path19.join(dir, "bundle"), { recursive: true });
170900
- fs24.writeFileSync(path19.join(dir, "session.json"), JSON.stringify(session, null, 2));
170956
+ fs25.mkdirSync(path19.join(dir, "bundle"), { recursive: true });
170957
+ fs25.writeFileSync(path19.join(dir, "session.json"), JSON.stringify(session, null, 2));
170901
170958
  for (const [rel, content] of Object.entries(bundleFiles)) {
170902
170959
  const file = path19.join(dir, "bundle", rel);
170903
- fs24.mkdirSync(path19.dirname(file), { recursive: true });
170904
- fs24.writeFileSync(file, content);
170960
+ fs25.mkdirSync(path19.dirname(file), { recursive: true });
170961
+ fs25.writeFileSync(file, content);
170905
170962
  }
170906
170963
  this.broadcast?.({ type: "begin", sessionId: session.runId, data: session });
170907
170964
  }
170908
170965
  recover(session) {
170909
- fs24.mkdirSync(this.dir(session.runId), { recursive: true });
170966
+ fs25.mkdirSync(this.dir(session.runId), { recursive: true });
170910
170967
  const file = path19.join(this.dir(session.runId), "session.json");
170911
- if (!fs24.existsSync(file)) fs24.writeFileSync(file, JSON.stringify(session, null, 2));
170968
+ if (!fs25.existsSync(file)) fs25.writeFileSync(file, JSON.stringify(session, null, 2));
170912
170969
  this.broadcast?.({ type: "begin", sessionId: session.runId, data: { ...session, recovered: true } });
170913
170970
  }
170914
170971
  event(sessionId, event) {
170915
- fs24.mkdirSync(this.dir(sessionId), { recursive: true });
170916
- fs24.appendFileSync(path19.join(this.dir(sessionId), "events.ndjson"), JSON.stringify(event) + "\n");
170972
+ fs25.mkdirSync(this.dir(sessionId), { recursive: true });
170973
+ fs25.appendFileSync(path19.join(this.dir(sessionId), "events.ndjson"), JSON.stringify(event) + "\n");
170917
170974
  this.broadcast?.({ type: "event", sessionId, data: event });
170918
170975
  }
170919
170976
  end(sessionId, update) {
170920
170977
  const file = path19.join(this.dir(sessionId), "session.json");
170921
- const session = JSON.parse(fs24.readFileSync(file, "utf8"));
170978
+ const session = JSON.parse(fs25.readFileSync(file, "utf8"));
170922
170979
  session.exit = update.exit;
170923
170980
  session.opRefs = update.opRefs;
170924
- fs24.writeFileSync(file, JSON.stringify(session, null, 2));
170981
+ fs25.writeFileSync(file, JSON.stringify(session, null, 2));
170925
170982
  this.broadcast?.({ type: "end", sessionId, data: session });
170926
170983
  }
170927
170984
  /** 只读取某会话 bundle 下的单个文件正文(供 trace 端点预览 TASK.md/上游正文等)。
@@ -170931,17 +170988,17 @@ var init_trajectory = __esm({
170931
170988
  const bundleRoot = path19.join(this.dir(sessionId), "bundle");
170932
170989
  const target = path19.resolve(bundleRoot, rel);
170933
170990
  if (target !== bundleRoot && !target.startsWith(bundleRoot + path19.sep)) return null;
170934
- if (!fs24.existsSync(target) || !fs24.statSync(target).isFile()) return null;
170935
- return fs24.readFileSync(target, "utf8");
170991
+ if (!fs25.existsSync(target) || !fs25.statSync(target).isFile()) return null;
170992
+ return fs25.readFileSync(target, "utf8");
170936
170993
  }
170937
170994
  /** 列出某会话 bundle 下所有文件的相对路径(供前端「本次输入」点开清单)。 */
170938
170995
  listBundle(sessionId) {
170939
170996
  if (!sessionId || sessionId.includes("/") || sessionId.includes("..")) return [];
170940
170997
  const bundleRoot = path19.join(this.dir(sessionId), "bundle");
170941
- if (!fs24.existsSync(bundleRoot)) return [];
170998
+ if (!fs25.existsSync(bundleRoot)) return [];
170942
170999
  const out = [];
170943
171000
  const walk = (d) => {
170944
- for (const e of fs24.readdirSync(d, { withFileTypes: true })) {
171001
+ for (const e of fs25.readdirSync(d, { withFileTypes: true })) {
170945
171002
  const full = path19.join(d, e.name);
170946
171003
  if (e.isDirectory()) walk(full);
170947
171004
  else out.push(path19.relative(bundleRoot, full));
@@ -170955,19 +171012,19 @@ var init_trajectory = __esm({
170955
171012
  });
170956
171013
 
170957
171014
  // src/index.ts
170958
- var fs28 = __toESM(require("node:fs"));
171015
+ var fs29 = __toESM(require("node:fs"));
170959
171016
  var os9 = __toESM(require("node:os"));
170960
171017
  var path23 = __toESM(require("node:path"));
170961
171018
  var import_node_child_process17 = require("node:child_process");
170962
171019
 
170963
171020
  // ../cli/src/cli.ts
170964
- var fs27 = __toESM(require("node:fs"), 1);
171021
+ var fs28 = __toESM(require("node:fs"), 1);
170965
171022
  var os8 = __toESM(require("node:os"), 1);
170966
171023
  var path22 = __toESM(require("node:path"), 1);
170967
171024
  var import_node_crypto33 = require("node:crypto");
170968
171025
 
170969
171026
  // ../cli/src/serve.ts
170970
- var fs25 = __toESM(require("node:fs"), 1);
171027
+ var fs26 = __toESM(require("node:fs"), 1);
170971
171028
  var os5 = __toESM(require("node:os"), 1);
170972
171029
  var path20 = __toESM(require("node:path"), 1);
170973
171030
  var import_node_crypto30 = require("node:crypto");
@@ -170976,7 +171033,7 @@ init_src2();
170976
171033
  init_src7();
170977
171034
 
170978
171035
  // ../cli/src/chat-exit.ts
170979
- var fs22 = __toESM(require("node:fs"), 1);
171036
+ var fs23 = __toESM(require("node:fs"), 1);
170980
171037
  var SUMMARY_BY_REASON = {
170981
171038
  cancelled: "\u5BF9\u8BDD\u5DF2\u4E2D\u65AD",
170982
171039
  timeout: "\u8FD0\u884C\u8D85\u65F6\uFF0C\u5DF2\u7EC8\u6B62",
@@ -170987,14 +171044,14 @@ var SUMMARY_BY_REASON = {
170987
171044
  };
170988
171045
  function transcriptTail(ref2) {
170989
171046
  try {
170990
- const stat3 = fs22.statSync(ref2);
171047
+ const stat3 = fs23.statSync(ref2);
170991
171048
  const size = Math.min(stat3.size, 4e3);
170992
171049
  const buf = Buffer.alloc(size);
170993
- const fd = fs22.openSync(ref2, "r");
171050
+ const fd = fs23.openSync(ref2, "r");
170994
171051
  try {
170995
- fs22.readSync(fd, buf, 0, size, Math.max(0, stat3.size - size));
171052
+ fs23.readSync(fd, buf, 0, size, Math.max(0, stat3.size - size));
170996
171053
  } finally {
170997
- fs22.closeSync(fd);
171054
+ fs23.closeSync(fd);
170998
171055
  }
170999
171056
  return buf.toString("utf8").trim();
171000
171057
  } catch {
@@ -171183,16 +171240,16 @@ async function fetchLatestNpmDaemonVersion() {
171183
171240
  }
171184
171241
  var oasisWrapperCache;
171185
171242
  function oasisWrapperScript() {
171186
- if (oasisWrapperCache && fs25.existsSync(oasisWrapperCache)) return oasisWrapperCache;
171243
+ if (oasisWrapperCache && fs26.existsSync(oasisWrapperCache)) return oasisWrapperCache;
171187
171244
  const repoRoot = (0, import_node_url5.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
171188
171245
  const tsx = path20.join(repoRoot, "node_modules/.bin/tsx");
171189
171246
  const main = path20.join(repoRoot, "packages/cli/src/main.ts");
171190
- const dir = fs25.mkdtempSync(path20.join(os5.tmpdir(), "oasis-cli-"));
171247
+ const dir = fs26.mkdtempSync(path20.join(os5.tmpdir(), "oasis-cli-"));
171191
171248
  const wrapper = path20.join(dir, "oasis");
171192
- fs25.writeFileSync(wrapper, `#!/usr/bin/env bash
171249
+ fs26.writeFileSync(wrapper, `#!/usr/bin/env bash
171193
171250
  exec ${JSON.stringify(tsx)} ${JSON.stringify(main)} "$@"
171194
171251
  `);
171195
- fs25.chmodSync(wrapper, 493);
171252
+ fs26.chmodSync(wrapper, 493);
171196
171253
  oasisWrapperCache = wrapper;
171197
171254
  return wrapper;
171198
171255
  }
@@ -171282,26 +171339,26 @@ function reworkWavefrontFromEnv(raw) {
171282
171339
  }
171283
171340
  async function startServe(opts) {
171284
171341
  const serverStartedAt = (/* @__PURE__ */ new Date()).toISOString();
171285
- fs25.mkdirSync(opts.dir, { recursive: true });
171342
+ fs26.mkdirSync(opts.dir, { recursive: true });
171286
171343
  const serverHeartbeatFile = path20.join(opts.dir, "serve-heartbeat.json");
171287
171344
  let previousServerHeartbeatAt;
171288
- if (fs25.existsSync(serverHeartbeatFile)) {
171345
+ if (fs26.existsSync(serverHeartbeatFile)) {
171289
171346
  try {
171290
- const raw = JSON.parse(fs25.readFileSync(serverHeartbeatFile, "utf8"));
171347
+ const raw = JSON.parse(fs26.readFileSync(serverHeartbeatFile, "utf8"));
171291
171348
  if (raw.at && Number.isFinite(Date.parse(raw.at))) previousServerHeartbeatAt = raw.at;
171292
171349
  } catch {
171293
171350
  }
171294
171351
  }
171295
171352
  const writeServerHeartbeat = () => {
171296
- fs25.writeFile(serverHeartbeatFile, JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), pid: process.pid }) + "\n", () => {
171353
+ fs26.writeFile(serverHeartbeatFile, JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), pid: process.pid }) + "\n", () => {
171297
171354
  });
171298
171355
  };
171299
171356
  writeServerHeartbeat();
171300
171357
  const serverHeartbeatTimer = setInterval(writeServerHeartbeat, 5e3);
171301
171358
  serverHeartbeatTimer.unref?.();
171302
171359
  const lock = path20.join(opts.dir, "serve.lock");
171303
- if (fs25.existsSync(lock)) {
171304
- const pid = Number(fs25.readFileSync(lock, "utf8"));
171360
+ if (fs26.existsSync(lock)) {
171361
+ const pid = Number(fs26.readFileSync(lock, "utf8"));
171305
171362
  let alive = false;
171306
171363
  try {
171307
171364
  process.kill(pid, 0);
@@ -171309,12 +171366,12 @@ async function startServe(opts) {
171309
171366
  } catch {
171310
171367
  }
171311
171368
  if (alive) throw new Error(`\u8BE5\u6570\u636E\u76EE\u5F55\u5DF2\u6709 serve \u5728\u8DD1\uFF08pid=${pid}\uFF09\u2014\u2014\u5355\u5199\u8005\u8FDB\u7A0B\uFF0C\u4E0D\u80FD\u53CC\u5F00`);
171312
- fs25.unlinkSync(lock);
171369
+ fs26.unlinkSync(lock);
171313
171370
  }
171314
- fs25.writeFileSync(lock, String(process.pid));
171371
+ fs26.writeFileSync(lock, String(process.pid));
171315
171372
  const loadJson = (name) => {
171316
171373
  const file = path20.join(opts.dir, name);
171317
- return fs25.existsSync(file) ? JSON.parse(fs25.readFileSync(file, "utf8")) : void 0;
171374
+ return fs26.existsSync(file) ? JSON.parse(fs26.readFileSync(file, "utf8")) : void 0;
171318
171375
  };
171319
171376
  const pgDsn = process.env["OASIS_PG_DSN"] ?? process.env["DATABASE_URL"];
171320
171377
  const pgSchema = process.env["OASIS_PG_SCHEMA"] ?? "public";
@@ -171408,14 +171465,14 @@ async function startServe(opts) {
171408
171465
  const apiActivity = createApiActivityLedger();
171409
171466
  const operatorActor = `actor:human:${os5.userInfo().username}`;
171410
171467
  const operatorToken = issuer.issue(operatorActor);
171411
- fs25.writeFileSync(path20.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
171468
+ fs26.writeFileSync(path20.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
171412
171469
  let nodeTokens = createNodeTokenStore(path20.join(opts.dir, "node-tokens.json"));
171413
171470
  const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3, path20.join(opts.dir, "enroll-tokens.json"));
171414
171471
  let nodeStore = await FileNodeStore.open(path20.join(opts.dir, "nodes.json"));
171415
171472
  const registryAuditFile = path20.join(opts.dir, "registry-audit.ndjson");
171416
171473
  const registryListeners = /* @__PURE__ */ new Set();
171417
171474
  const registryAudit = (record6) => {
171418
- fs25.appendFile(registryAuditFile, JSON.stringify(record6) + "\n", () => {
171475
+ fs26.appendFile(registryAuditFile, JSON.stringify(record6) + "\n", () => {
171419
171476
  });
171420
171477
  for (const l of registryListeners) l({ kind: record6.kind, actor: record6.actor, target: record6.target, timestamp: record6.timestamp });
171421
171478
  };
@@ -171658,9 +171715,9 @@ async function startServe(opts) {
171658
171715
  const workorderDrafts = pgDsn && pgPool ? await PostgresWorkorderDraftStore.open(pgPool, pgSchema, { backfillFromFile: workorderDraftFile }) : new WorkorderDraftStore(workorderDraftFile);
171659
171716
  const journalFile = path20.join(opts.dir, "dispatch-journal.ndjson");
171660
171717
  const journalRing = [];
171661
- if (fs25.existsSync(journalFile)) {
171718
+ if (fs26.existsSync(journalFile)) {
171662
171719
  try {
171663
- const lines = fs25.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean);
171720
+ const lines = fs26.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean);
171664
171721
  for (const line of lines.slice(-500)) {
171665
171722
  try {
171666
171723
  journalRing.push(JSON.parse(line));
@@ -171673,13 +171730,13 @@ async function startServe(opts) {
171673
171730
  const journal = (entry) => {
171674
171731
  journalRing.push(entry);
171675
171732
  if (journalRing.length > 500) journalRing.shift();
171676
- fs25.appendFile(journalFile, JSON.stringify(entry) + "\n", () => {
171733
+ fs26.appendFile(journalFile, JSON.stringify(entry) + "\n", () => {
171677
171734
  });
171678
171735
  };
171679
171736
  const readMetricJournal = () => {
171680
- if (!fs25.existsSync(journalFile)) return [...journalRing];
171737
+ if (!fs26.existsSync(journalFile)) return [...journalRing];
171681
171738
  try {
171682
- return fs25.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean).flatMap((line) => {
171739
+ return fs26.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean).flatMap((line) => {
171683
171740
  try {
171684
171741
  return [JSON.parse(line)];
171685
171742
  } catch {
@@ -173138,7 +173195,7 @@ async function startServe(opts) {
173138
173195
  await server.close();
173139
173196
  if (pgPool) await pgPool.end().catch(() => {
173140
173197
  });
173141
- fs25.rmSync(lock, { force: true });
173198
+ fs26.rmSync(lock, { force: true });
173142
173199
  }
173143
173200
  };
173144
173201
  }
@@ -173964,10 +174021,10 @@ async function runCli(argv, println = console.log) {
173964
174021
  const nodeTokenFile = path22.join(dir, "node-token");
173965
174022
  const enrollTokenFile = path22.join(dir, "enroll-token");
173966
174023
  const reportMarkerFile = path22.join(dir, "report-runtimes");
173967
- const persistedNodeId = fs27.existsSync(nodeIdFile) ? fs27.readFileSync(nodeIdFile, "utf8").trim() : null;
174024
+ const persistedNodeId = fs28.existsSync(nodeIdFile) ? fs28.readFileSync(nodeIdFile, "utf8").trim() : null;
173968
174025
  let nodeId = persistedNodeId || resolveNodeId();
173969
- let token2 = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? (fs27.existsSync(nodeTokenFile) ? fs27.readFileSync(nodeTokenFile, "utf8").trim() : void 0);
173970
- const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (fs27.existsSync(enrollTokenFile) ? fs27.readFileSync(enrollTokenFile, "utf8").trim() : void 0);
174026
+ let token2 = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? (fs28.existsSync(nodeTokenFile) ? fs28.readFileSync(nodeTokenFile, "utf8").trim() : void 0);
174027
+ const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (fs28.existsSync(enrollTokenFile) ? fs28.readFileSync(enrollTokenFile, "utf8").trim() : void 0);
173971
174028
  let freshEnrollment = false;
173972
174029
  if (!token2 && enrollToken) {
173973
174030
  const httpBase2 = serverUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
@@ -173980,26 +174037,26 @@ async function runCli(argv, println = console.log) {
173980
174037
  const body = await res.json();
173981
174038
  nodeId = body.nodeId;
173982
174039
  token2 = body.token;
173983
- fs27.mkdirSync(dir, { recursive: true });
173984
- fs27.writeFileSync(nodeIdFile, nodeId);
173985
- fs27.writeFileSync(nodeTokenFile, token2, { mode: 384 });
174040
+ fs28.mkdirSync(dir, { recursive: true });
174041
+ fs28.writeFileSync(nodeIdFile, nodeId);
174042
+ fs28.writeFileSync(nodeTokenFile, token2, { mode: 384 });
173986
174043
  try {
173987
- fs27.unlinkSync(enrollTokenFile);
174044
+ fs28.unlinkSync(enrollTokenFile);
173988
174045
  } catch {
173989
174046
  }
173990
174047
  freshEnrollment = true;
173991
174048
  }
173992
174049
  if (!nodeId) throw new Error("no nodeId \u2014 provide --enroll-token <ent_...> on first run");
173993
- const scriptRun = freshEnrollment || fs27.existsSync(reportMarkerFile);
174050
+ const scriptRun = freshEnrollment || fs28.existsSync(reportMarkerFile);
173994
174051
  if (flags.has("service")) {
173995
174052
  const { spawnSync, execSync: execSync2 } = await import("node:child_process");
173996
174053
  if (token2) {
173997
- fs27.mkdirSync(dir, { recursive: true });
173998
- fs27.writeFileSync(nodeTokenFile, token2, { mode: 384 });
174054
+ fs28.mkdirSync(dir, { recursive: true });
174055
+ fs28.writeFileSync(nodeTokenFile, token2, { mode: 384 });
173999
174056
  }
174000
174057
  if (scriptRun) {
174001
- fs27.mkdirSync(dir, { recursive: true });
174002
- fs27.writeFileSync(reportMarkerFile, "");
174058
+ fs28.mkdirSync(dir, { recursive: true });
174059
+ fs28.writeFileSync(reportMarkerFile, "");
174003
174060
  }
174004
174061
  println("\u2192 Installing oasis_test globally...");
174005
174062
  spawnSync("npm", ["install", "-g", "oasis_test@latest"], { stdio: "inherit" });
@@ -174008,10 +174065,10 @@ async function runCli(argv, println = console.log) {
174008
174065
  const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
174009
174066
  if (process.platform === "linux") {
174010
174067
  const svcFile = path22.join(os8.homedir(), ".config/systemd/user/oasis-node.service");
174011
- fs27.mkdirSync(path22.dirname(svcFile), { recursive: true });
174068
+ fs28.mkdirSync(path22.dirname(svcFile), { recursive: true });
174012
174069
  if (spawnSync("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
174013
174070
  spawnSync("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
174014
- fs27.writeFileSync(svcFile, [
174071
+ fs28.writeFileSync(svcFile, [
174015
174072
  "[Unit]",
174016
174073
  "Description=Oasis Node Daemon",
174017
174074
  "After=network.target",
@@ -174039,10 +174096,10 @@ async function runCli(argv, println = console.log) {
174039
174096
  println(" Stop : systemctl --user stop oasis-node");
174040
174097
  } else if (process.platform === "darwin") {
174041
174098
  const plist = path22.join(os8.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
174042
- fs27.mkdirSync(path22.dirname(plist), { recursive: true });
174099
+ fs28.mkdirSync(path22.dirname(plist), { recursive: true });
174043
174100
  spawnSync("launchctl", ["unload", plist], { stdio: "ignore" });
174044
174101
  const argXml = [binPath, "node", "--server-ws", serverUrl, "--dir", dir, ...nodeName ? ["--name", nodeName] : []].map((a) => `<string>${a}</string>`).join("");
174045
- fs27.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.oasis.node</string><key>ProgramArguments</key><array>${argXml}</array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${os8.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os8.homedir()}/.oasis-node.err</string></dict></plist>`);
174102
+ fs28.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>Label</key><string>com.oasis.node</string><key>ProgramArguments</key><array>${argXml}</array><key>RunAtLoad</key><true/><key>KeepAlive</key><true/><key>StandardOutPath</key><string>${os8.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os8.homedir()}/.oasis-node.err</string></dict></plist>`);
174046
174103
  spawnSync("launchctl", ["load", plist], { stdio: "inherit" });
174047
174104
  println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
174048
174105
  println(` Logs : tail -f ${os8.homedir()}/.oasis-node.log`);
@@ -174054,9 +174111,9 @@ async function runCli(argv, println = console.log) {
174054
174111
  }
174055
174112
  return;
174056
174113
  }
174057
- if (fs27.existsSync(reportMarkerFile)) {
174114
+ if (fs28.existsSync(reportMarkerFile)) {
174058
174115
  try {
174059
- fs27.unlinkSync(reportMarkerFile);
174116
+ fs28.unlinkSync(reportMarkerFile);
174060
174117
  } catch {
174061
174118
  }
174062
174119
  }
@@ -174137,7 +174194,7 @@ async function runCli(argv, println = console.log) {
174137
174194
  const outFile = flags.get("out");
174138
174195
  const lines = samples.map((sample) => JSON.stringify(sample)).join("\n");
174139
174196
  if (outFile !== void 0) {
174140
- fs27.writeFileSync(outFile, lines + (lines ? "\n" : ""));
174197
+ fs28.writeFileSync(outFile, lines + (lines ? "\n" : ""));
174141
174198
  println(`\u5DF2\u5BFC\u51FA ${samples.length} \u6761\u8F68\u8FF9\u6837\u672C \u2192 ${outFile}\uFF08approved/rejected \u6210\u5BF9\u5373\u504F\u597D\u5BF9\uFF09`);
174142
174199
  } else {
174143
174200
  println(lines);
@@ -174165,9 +174222,9 @@ async function runCli(argv, println = console.log) {
174165
174222
  `WantedBy=default.target`,
174166
174223
  ``
174167
174224
  ].join("\n");
174168
- fs27.mkdirSync(unitDir, { recursive: true });
174225
+ fs28.mkdirSync(unitDir, { recursive: true });
174169
174226
  const unitPath = path22.join(unitDir, `${name}.service`);
174170
- fs27.writeFileSync(unitPath, unit);
174227
+ fs28.writeFileSync(unitPath, unit);
174171
174228
  println(`\u5DF2\u5199\u5165 ${unitPath}`);
174172
174229
  println(`\u542F\u7528\uFF1Asystemctl --user daemon-reload && systemctl --user enable --now ${name}`);
174173
174230
  println(`\u5F00\u673A\u81EA\u542F\uFF08\u542B\u672A\u767B\u5F55\uFF09\uFF1Aloginctl enable-linger $USER`);
@@ -174197,12 +174254,12 @@ async function runCli(argv, println = console.log) {
174197
174254
  }
174198
174255
  const base = flags.get("server") ?? process.env["OASIS_SERVER"] ?? "http://127.0.0.1:7320";
174199
174256
  const tokenFile = path22.join(dir, "operator-token");
174200
- const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (fs27.existsSync(tokenFile) ? fs27.readFileSync(tokenFile, "utf8").trim() : void 0);
174257
+ const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (fs28.existsSync(tokenFile) ? fs28.readFileSync(tokenFile, "utf8").trim() : void 0);
174201
174258
  if (!token) {
174202
174259
  throw new Error(`\u65E0 token\uFF1A\u5148 oasis serve\uFF08\u4F1A\u751F\u6210 ${tokenFile}\uFF09\uFF0C\u6216\u663E\u5F0F --token / $OASIS_TOKEN`);
174203
174260
  }
174204
174261
  const api = makeClient(base, token);
174205
- const readFileArg = (file) => fs27.readFileSync(file, "utf8");
174262
+ const readFileArg = (file) => fs28.readFileSync(file, "utf8");
174206
174263
  const parseJsonFlag = (value, name) => {
174207
174264
  const parsed = JSON.parse(value);
174208
174265
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
@@ -174220,11 +174277,11 @@ async function runCli(argv, println = console.log) {
174220
174277
  const readDirFiles = (root) => {
174221
174278
  const out = [];
174222
174279
  const walk = (abs, rel) => {
174223
- for (const name of fs27.readdirSync(abs)) {
174280
+ for (const name of fs28.readdirSync(abs)) {
174224
174281
  const childAbs = path22.join(abs, name);
174225
174282
  const childRel = rel ? `${rel}/${name}` : name;
174226
- if (fs27.statSync(childAbs).isDirectory()) walk(childAbs, childRel);
174227
- else out.push({ path: childRel, contentBase64: fs27.readFileSync(childAbs).toString("base64") });
174283
+ if (fs28.statSync(childAbs).isDirectory()) walk(childAbs, childRel);
174284
+ else out.push({ path: childRel, contentBase64: fs28.readFileSync(childAbs).toString("base64") });
174228
174285
  }
174229
174286
  };
174230
174287
  walk(root, "");
@@ -174351,7 +174408,7 @@ async function runCli(argv, println = console.log) {
174351
174408
  }
174352
174409
  switch (command) {
174353
174410
  case "create-workorder": {
174354
- const planRaw = flags.get("plan-file") !== void 0 ? fs27.readFileSync(flags.get("plan-file"), "utf8") : flags.get("plan");
174411
+ const planRaw = flags.get("plan-file") !== void 0 ? fs28.readFileSync(flags.get("plan-file"), "utf8") : flags.get("plan");
174355
174412
  const acceptanceFlag = flags.get("acceptance");
174356
174413
  const args = {
174357
174414
  createdVia: "seed",
@@ -174572,7 +174629,7 @@ async function runCli(argv, println = console.log) {
174572
174629
  if (verb === "add") {
174573
174630
  const file = flags.get("file");
174574
174631
  if (file !== void 0) {
174575
- const bytes = fs27.readFileSync(file);
174632
+ const bytes = fs28.readFileSync(file);
174576
174633
  const res = await api.request("POST", `/api/projects/${encodeURIComponent(projectId)}/files`, {
174577
174634
  name: flags.get("name") ?? path22.basename(file),
174578
174635
  ...flags.has("path") ? { path: flags.get("path") } : {},
@@ -174736,14 +174793,14 @@ ${res.warning}`);
174736
174793
  const LEGACY_DESIGN_SYSTEM_PROMPT = "\u4F60\u662F\u8BBE\u8BA1\u5F15\u64CE\u4E2D\u7684\u754C\u9762\u8BBE\u8BA1\u5E08\u3002\u4EFB\u52A1\u4E66\u89C1\u672C\u6761\u6D88\u606F\uFF1B\u4E0A\u6E38\u8F93\u5165\u7B49\u4E0A\u4E0B\u6587\u6587\u4EF6\u5728\u9879\u76EE task-context/ \u76EE\u5F55\u3002\u6309\u4EFB\u52A1\u4E66\u7684\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u534F\u8BAE\u5DE5\u4F5C\uFF1A\u4EA7\u51FA\u81EA\u5305\u542B HTML \u5165\u53E3\u7A3F\u4E0E acceptance.md\uFF0C\u5B8C\u6210\u5373\u7ED3\u675F\u56DE\u590D\uFF0C\u4EA4\u7A3F\u7531\u7CFB\u7EDF\u4EE3\u529E\u3002";
174737
174794
  if (sub === "chat") {
174738
174795
  const artifactId2 = needPos(positional, 1, "oasis design chat <artifactId> --message <t>");
174739
- const message2 = flags.get("message") ?? (["DESIGN_BRIEF.md", "TASK.md"].map((f2) => fs27.existsSync(f2) ? fs27.readFileSync(f2, "utf8") : "").find((s2) => s2.trim()) ?? "");
174796
+ const message2 = flags.get("message") ?? (["DESIGN_BRIEF.md", "TASK.md"].map((f2) => fs28.existsSync(f2) ? fs28.readFileSync(f2, "utf8") : "").find((s2) => s2.trim()) ?? "");
174740
174797
  if (!message2.trim()) throw new Error("\u65E0\u5BF9\u8BDD\u5185\u5BB9\uFF1A\u7ED9 --message <text>\uFF0C\u6216\u5728\u5F53\u524D\u76EE\u5F55\u653E DESIGN_BRIEF.md / TASK.md");
174741
174798
  const odBase2 = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
174742
174799
  const isContinue = flags.get("turn") === "continue";
174743
174800
  const contextFiles2 = {};
174744
174801
  if (!isContinue) {
174745
174802
  contextFiles2["DESIGN_BRIEF.md"] = message2;
174746
- if (fs27.existsSync("inputs") && fs27.statSync("inputs").isDirectory()) {
174803
+ if (fs28.existsSync("inputs") && fs28.statSync("inputs").isDirectory()) {
174747
174804
  for (const f2 of readDirFiles("inputs")) {
174748
174805
  contextFiles2[`inputs/${f2.path}`] = Buffer.from(f2.contentBase64, "base64").toString("utf8");
174749
174806
  }
@@ -174811,11 +174868,11 @@ ${res.warning}`);
174811
174868
  const artifactId = needPos(positional, 1, "oasis design run <artifactId>");
174812
174869
  const odBase = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
174813
174870
  const odPublic = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
174814
- const briefFile = ["DESIGN_BRIEF.md", "TASK.md"].find((f2) => fs27.existsSync(f2));
174815
- const brief = flags.get("brief") ?? (briefFile ? fs27.readFileSync(briefFile, "utf8") : "");
174871
+ const briefFile = ["DESIGN_BRIEF.md", "TASK.md"].find((f2) => fs28.existsSync(f2));
174872
+ const brief = flags.get("brief") ?? (briefFile ? fs28.readFileSync(briefFile, "utf8") : "");
174816
174873
  if (!brief.trim()) throw new Error("\u65E0\u8BBE\u8BA1\u4EFB\u52A1\uFF1A\u7ED9 --brief <text>\uFF0C\u6216\u5728\u5F53\u524D\u76EE\u5F55\u653E DESIGN_BRIEF.md / TASK.md");
174817
174874
  const contextFiles = { "DESIGN_BRIEF.md": brief };
174818
- if (fs27.existsSync("inputs") && fs27.statSync("inputs").isDirectory()) {
174875
+ if (fs28.existsSync("inputs") && fs28.statSync("inputs").isDirectory()) {
174819
174876
  for (const f2 of readDirFiles("inputs")) {
174820
174877
  contextFiles[`inputs/${f2.path}`] = Buffer.from(f2.contentBase64, "base64").toString("utf8");
174821
174878
  }
@@ -175543,7 +175600,7 @@ ${res.warning}`);
175543
175600
  init_src6();
175544
175601
 
175545
175602
  // src/index.ts
175546
- var PKG_VERSION = true ? "0.1.64" : "dev";
175603
+ var PKG_VERSION = true ? "0.1.65" : "dev";
175547
175604
  var OASIS_DIR = path23.join(os9.homedir(), ".oasis");
175548
175605
  var CONFIG_FILE = path23.join(OASIS_DIR, "node-config.json");
175549
175606
  var PID_FILE = path23.join(OASIS_DIR, "node.pid");
@@ -175562,18 +175619,18 @@ var parseFlags = (argv) => {
175562
175619
  };
175563
175620
  var readConfig = () => {
175564
175621
  try {
175565
- return JSON.parse(fs28.readFileSync(CONFIG_FILE, "utf8"));
175622
+ return JSON.parse(fs29.readFileSync(CONFIG_FILE, "utf8"));
175566
175623
  } catch {
175567
175624
  return null;
175568
175625
  }
175569
175626
  };
175570
175627
  var saveConfig = (c) => {
175571
- fs28.mkdirSync(OASIS_DIR, { recursive: true });
175572
- fs28.writeFileSync(CONFIG_FILE, JSON.stringify(c), { mode: 384 });
175628
+ fs29.mkdirSync(OASIS_DIR, { recursive: true });
175629
+ fs29.writeFileSync(CONFIG_FILE, JSON.stringify(c), { mode: 384 });
175573
175630
  };
175574
175631
  var readPid = () => {
175575
175632
  try {
175576
- const p2 = parseInt(fs28.readFileSync(PID_FILE, "utf8").trim(), 10);
175633
+ const p2 = parseInt(fs29.readFileSync(PID_FILE, "utf8").trim(), 10);
175577
175634
  return isNaN(p2) ? null : p2;
175578
175635
  } catch {
175579
175636
  return null;
@@ -175589,10 +175646,10 @@ var isRunning2 = (pid) => {
175589
175646
  };
175590
175647
  var httpBase = (wsUrl) => wsUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
175591
175648
  function installBinary() {
175592
- fs28.mkdirSync(path23.dirname(BIN_FILE), { recursive: true });
175593
- fs28.copyFileSync(process.argv[1], BIN_FILE);
175594
- fs28.mkdirSync(path23.dirname(LOCAL_BIN), { recursive: true });
175595
- fs28.writeFileSync(LOCAL_BIN, `#!/bin/sh
175649
+ fs29.mkdirSync(path23.dirname(BIN_FILE), { recursive: true });
175650
+ fs29.copyFileSync(process.argv[1], BIN_FILE);
175651
+ fs29.mkdirSync(path23.dirname(LOCAL_BIN), { recursive: true });
175652
+ fs29.writeFileSync(LOCAL_BIN, `#!/bin/sh
175596
175653
  exec node "${BIN_FILE}" "$@"
175597
175654
  `, { mode: 493 });
175598
175655
  }
@@ -175607,8 +175664,8 @@ function setupAutostart() {
175607
175664
  const daemonPath = [process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":");
175608
175665
  if (process.platform === "linux") {
175609
175666
  const unitDir = path23.join(os9.homedir(), ".config", "systemd", "user");
175610
- fs28.mkdirSync(unitDir, { recursive: true });
175611
- fs28.writeFileSync(path23.join(unitDir, "oasis-node.service"), [
175667
+ fs29.mkdirSync(unitDir, { recursive: true });
175668
+ fs29.writeFileSync(path23.join(unitDir, "oasis-node.service"), [
175612
175669
  "[Unit]",
175613
175670
  "Description=Oasis Node Daemon",
175614
175671
  "After=network.target",
@@ -175631,8 +175688,8 @@ function setupAutostart() {
175631
175688
  }
175632
175689
  } else if (process.platform === "darwin") {
175633
175690
  const plist = path23.join(os9.homedir(), "Library", "LaunchAgents", "com.oasis.node.plist");
175634
- fs28.mkdirSync(path23.dirname(plist), { recursive: true });
175635
- fs28.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
175691
+ fs29.mkdirSync(path23.dirname(plist), { recursive: true });
175692
+ fs29.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
175636
175693
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
175637
175694
  <plist version="1.0"><dict>
175638
175695
  <key>Label</key><string>com.oasis.node</string>
@@ -175649,14 +175706,14 @@ function setupAutostart() {
175649
175706
  }
175650
175707
  }
175651
175708
  function spawnDaemon() {
175652
- const log3 = fs28.openSync(LOG_FILE, "a");
175709
+ const log3 = fs29.openSync(LOG_FILE, "a");
175653
175710
  const child = (0, import_node_child_process17.spawn)(process.execPath, [BIN_FILE, "--_daemon"], {
175654
175711
  detached: true,
175655
175712
  stdio: ["ignore", log3, log3]
175656
175713
  });
175657
175714
  child.unref();
175658
175715
  const pid = child.pid ?? 0;
175659
- fs28.writeFileSync(PID_FILE, String(pid));
175716
+ fs29.writeFileSync(PID_FILE, String(pid));
175660
175717
  return pid;
175661
175718
  }
175662
175719
  function stopDaemon() {
@@ -175668,7 +175725,7 @@ function stopDaemon() {
175668
175725
  }
175669
175726
  }
175670
175727
  try {
175671
- fs28.unlinkSync(PID_FILE);
175728
+ fs29.unlinkSync(PID_FILE);
175672
175729
  } catch {
175673
175730
  }
175674
175731
  try {
@@ -175695,7 +175752,7 @@ function selfUpdate() {
175695
175752
  return false;
175696
175753
  }
175697
175754
  })();
175698
- const log3 = fs28.openSync(LOG_FILE, "a");
175755
+ const log3 = fs29.openSync(LOG_FILE, "a");
175699
175756
  if (hasSystemd) {
175700
175757
  const child = (0, import_node_child_process17.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
175701
175758
  detached: true,
@@ -175730,10 +175787,10 @@ void (async () => {
175730
175787
  console.error(`[oasis] daemon already running (PID ${alivePid}) \u2014 exiting duplicate`);
175731
175788
  process.exit(0);
175732
175789
  }
175733
- fs28.writeFileSync(PID_FILE, String(process.pid));
175790
+ fs29.writeFileSync(PID_FILE, String(process.pid));
175734
175791
  const cleanup = () => {
175735
175792
  try {
175736
- fs28.unlinkSync(PID_FILE);
175793
+ fs29.unlinkSync(PID_FILE);
175737
175794
  } catch {
175738
175795
  }
175739
175796
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oasis_test",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
5
5
  "bin": {
6
6
  "oasis": "./dist/index.js"