oasis_test 0.1.52 → 0.1.53

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 +905 -834
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -339,7 +339,7 @@ function fold(model, op) {
339
339
  nonMonotonicOps: p2.nonMonotonicOps,
340
340
  proposedBy: p2.proposedBy,
341
341
  origin: p2.origin ?? null,
342
- workspace: p2.plan.workspace ?? null,
342
+ workspace: p2.plan.workspace ?? model.artifacts.get(op.artifactId)?.workspace ?? null,
343
343
  advisory: p2.advisory ?? [],
344
344
  downstreamClosure: p2.downstreamClosure ?? [],
345
345
  at: op.timestamp,
@@ -2004,9 +2004,9 @@ var init_kernel = __esm({
2004
2004
  throw new KernelError(`revision not in queue: ${args.revisionId}\uFF08state=${target?.state ?? "missing"}\uFF09`);
2005
2005
  }
2006
2006
  if (isStale(this.model, head)) {
2007
- const path20 = this.pathForStaleHead(artifact, queue);
2007
+ const path19 = this.pathForStaleHead(artifact, queue);
2008
2008
  throw new KernelError(
2009
- `stale base: ${head.id} based on ${head.base ?? "\u2205"}, head is ${artifact.currentRev ?? "\u2205"} \u2014 ` + (path20 === "rebase" ? `\u9700\u8981 rebase\uFF1A\u4F5C\u8005\u5728\u65B0 head \u4E0A\u91CD\u5199\u540E propose --rebase-of ${head.id}\uFF08\xA75.5\uFF09` : `\u591A\u6761\u7ADE\u4E89\u4E14\u68C0\u67E5\u8D35 \u2192 group-commit\uFF1Aowner \u4E00\u6B21\u96C6\u6210\u6574\u6279\uFF08\xA75.5\uFF09`)
2009
+ `stale base: ${head.id} based on ${head.base ?? "\u2205"}, head is ${artifact.currentRev ?? "\u2205"} \u2014 ` + (path19 === "rebase" ? `\u9700\u8981 rebase\uFF1A\u4F5C\u8005\u5728\u65B0 head \u4E0A\u91CD\u5199\u540E propose --rebase-of ${head.id}\uFF08\xA75.5\uFF09` : `\u591A\u6761\u7ADE\u4E89\u4E14\u68C0\u67E5\u8D35 \u2192 group-commit\uFF1Aowner \u4E00\u6B21\u96C6\u6210\u6574\u6279\uFF08\xA75.5\uFF09`)
2010
2010
  );
2011
2011
  }
2012
2012
  await this.landHead(args.artifactId, args.actor, head, args.hand);
@@ -2023,13 +2023,13 @@ var init_kernel = __esm({
2023
2023
  const head = queue[0];
2024
2024
  if (!head) return { landed };
2025
2025
  if (isStale(this.model, head)) {
2026
- const path20 = this.pathForStaleHead(artifact, queue);
2026
+ const path19 = this.pathForStaleHead(artifact, queue);
2027
2027
  return {
2028
2028
  landed,
2029
2029
  blockedHead: {
2030
2030
  revision: head,
2031
- path: path20,
2032
- hint: path20 === "rebase" ? `\u4F5C\u8005\u91CD\u5199\u540E propose --rebase-of ${head.id}` : `owner \u96C6\u6210\u6574\u6279\uFF08integrate\uFF09\uFF0CR*.parents = [head, \u2026batch]`
2031
+ path: path19,
2032
+ hint: path19 === "rebase" ? `\u4F5C\u8005\u91CD\u5199\u540E propose --rebase-of ${head.id}` : `owner \u96C6\u6210\u6574\u6279\uFF08integrate\uFF09\uFF0CR*.parents = [head, \u2026batch]`
2033
2033
  }
2034
2034
  };
2035
2035
  }
@@ -4808,6 +4808,172 @@ var init_src2 = __esm({
4808
4808
  }
4809
4809
  });
4810
4810
 
4811
+ // ../server/src/git/ci-provider.ts
4812
+ function normalizeRemote(remote) {
4813
+ let s2 = remote.trim();
4814
+ s2 = s2.replace(/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//, "");
4815
+ s2 = s2.replace(/^git@/, "").replace(/^([^/:]+):/, "$1/");
4816
+ s2 = s2.replace(/\/+$/, "").replace(/\.git$/i, "");
4817
+ const slash = s2.indexOf("/");
4818
+ if (slash > 0) s2 = s2.slice(0, slash).toLowerCase() + s2.slice(slash);
4819
+ return s2;
4820
+ }
4821
+ function isGitHubRemote(remote) {
4822
+ return !!remote && /(?:^|\/\/|@)github\.com[/:]/i.test(remote);
4823
+ }
4824
+ function ciBranchFor(artifactId, sha2) {
4825
+ const s2 = slug3(artifactId.replace(/^artifact:/, "")).slice(0, 48);
4826
+ return `oasis-ci/${s2}/${sha2.slice(0, 8)}`;
4827
+ }
4828
+ function mirrorDirFor(mirrorRoot, repo) {
4829
+ if (repo.repoDir) return repo.repoDir;
4830
+ const key = repo.remote ? `${slug3(repo.id)}-${crypto.createHash("sha1").update(normalizeRemote(repo.remote)).digest("hex").slice(0, 8)}` : slug3(repo.id);
4831
+ return `${mirrorRoot}/${key}`;
4832
+ }
4833
+ var import_node_child_process, crypto, fs, path, import_node_util, execFile, slug3, GhCiProvider;
4834
+ var init_ci_provider = __esm({
4835
+ "../server/src/git/ci-provider.ts"() {
4836
+ "use strict";
4837
+ import_node_child_process = require("node:child_process");
4838
+ crypto = __toESM(require("node:crypto"), 1);
4839
+ fs = __toESM(require("node:fs"), 1);
4840
+ path = __toESM(require("node:path"), 1);
4841
+ import_node_util = require("node:util");
4842
+ execFile = (0, import_node_util.promisify)(import_node_child_process.execFile);
4843
+ slug3 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
4844
+ GhCiProvider = class {
4845
+ constructor(opts) {
4846
+ this.opts = opts;
4847
+ }
4848
+ repoDir(repo) {
4849
+ return mirrorDirFor(this.opts.mirrorRoot, repo);
4850
+ }
4851
+ /** 缺则 clone(首次使用/进程重启后本地镜像不存在)——否则 git fetch 会"not a git repo"报错。同 GitRemoteIntegrator。 */
4852
+ ensureClone(repo) {
4853
+ const dir = this.repoDir(repo);
4854
+ if (fs.existsSync(path.join(dir, ".git"))) {
4855
+ if (repo.remote) {
4856
+ let origin = "";
4857
+ try {
4858
+ origin = (0, import_node_child_process.execFileSync)("git", ["remote", "get-url", "origin"], { cwd: dir, env: process.env }).toString().trim();
4859
+ } catch {
4860
+ }
4861
+ if (origin !== repo.remote) {
4862
+ (0, import_node_child_process.execFileSync)("git", ["remote", "set-url", "origin", repo.remote], { cwd: dir, env: process.env });
4863
+ this.opts.log?.(`[ci] ${repo.id} \u955C\u50CF origin \u7EA0\u504F\uFF1A${origin || "(\u65E0)"} \u2192 ${repo.remote}`);
4864
+ }
4865
+ }
4866
+ return;
4867
+ }
4868
+ if (!repo.remote) throw new Error(`repo ${repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5 clone`);
4869
+ fs.mkdirSync(path.dirname(dir), { recursive: true });
4870
+ (0, import_node_child_process.execFileSync)("git", ["clone", "--quiet", repo.remote, dir], { env: process.env });
4871
+ this.opts.log?.(`[ci] cloned ${repo.id} \u2192 ${dir}`);
4872
+ }
4873
+ async gh(repo, args) {
4874
+ this.ensureClone(repo);
4875
+ const { stdout } = await execFile("gh", args, { cwd: this.repoDir(repo), env: process.env });
4876
+ return stdout.trim();
4877
+ }
4878
+ async git(repo, args) {
4879
+ this.ensureClone(repo);
4880
+ const { stdout } = await execFile("git", args, { cwd: this.repoDir(repo), env: process.env });
4881
+ return stdout.trim();
4882
+ }
4883
+ async ensurePr(ref, meta) {
4884
+ if (!ref.repo.remote) throw new Error(`repo ${ref.repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5\u5F00 PR`);
4885
+ await this.git(ref.repo, ["fetch", "--quiet", "--prune", "origin"]);
4886
+ await this.git(ref.repo, ["push", "--quiet", "--force-with-lease", "origin", `${ref.sha}:refs/heads/${ref.branch}`]);
4887
+ const existing = await this.gh(ref.repo, ["pr", "list", "--head", ref.branch, "--base", ref.repo.develop, "--state", "open", "--json", "number,url"]);
4888
+ const list = JSON.parse(existing || "[]");
4889
+ if (list[0]) return list[0];
4890
+ const url = await this.gh(ref.repo, ["pr", "create", "--base", ref.repo.develop, "--head", ref.branch, "--title", meta.title, "--body", meta.body]);
4891
+ const created = JSON.parse(await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "number,url"]));
4892
+ this.opts.log?.(`[ci] opened PR ${created.url} (${ref.branch} \u2192 ${ref.repo.develop})`);
4893
+ return created.url ? created : { number: created.number, url };
4894
+ }
4895
+ async status(ref) {
4896
+ let raw;
4897
+ try {
4898
+ raw = await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "statusCheckRollup,createdAt"]);
4899
+ } catch (e) {
4900
+ return { state: "pending", summary: `\u8BFB PR \u72B6\u6001\u5931\u8D25\uFF08\u4E0B\u8F6E\u91CD\u8BD5\uFF09\uFF1A${String(e)}` };
4901
+ }
4902
+ const parsed = JSON.parse(raw || "{}");
4903
+ const rollup = parsed.statusCheckRollup ?? [];
4904
+ if (rollup.length === 0) {
4905
+ const grace = this.opts.noCheckGraceMs ?? 12e4;
4906
+ const ageMs = parsed.createdAt ? Date.now() - Date.parse(parsed.createdAt) : Infinity;
4907
+ if (ageMs < grace) return { state: "pending" };
4908
+ if (this.opts.failClosedWhenNoChecks) return { state: "failure", summary: "\u8BE5\u4ED3\u672A\u914D\u4EFB\u4F55 Actions check\uFF08fail-closed\uFF09\u2014\u2014\u8BF7\u8865 CI \u6216\u6539\u914D\u7F6E" };
4909
+ this.opts.log?.(`[ci] ${ref.repo.id} PR ${ref.branch} \u5F00\u4E86 ${Math.round(ageMs / 1e3)}s \u4ECD\u65E0 check\uFF0C\u5224\u65E0 CI\u3001\u95F8\u7A7A\u8FC7\uFF08\u544A\u8B66\uFF09`);
4910
+ return { state: "success", summary: "\u65E0 CI check\uFF0C\u95F8\u7A7A\u8FC7" };
4911
+ }
4912
+ const failed = [];
4913
+ let anyPending = false;
4914
+ for (const c of rollup) {
4915
+ const concl = (c.conclusion ?? "").toUpperCase();
4916
+ const st = (c.status ?? "").toUpperCase();
4917
+ if (st && st !== "COMPLETED") {
4918
+ anyPending = true;
4919
+ continue;
4920
+ }
4921
+ if (concl && !["SUCCESS", "NEUTRAL", "SKIPPED"].includes(concl)) failed.push(c);
4922
+ }
4923
+ if (failed.length > 0) {
4924
+ const blocks = [];
4925
+ for (const c of failed) {
4926
+ const name = c.name ?? c.context ?? "check";
4927
+ const concl = (c.conclusion ?? "").toUpperCase();
4928
+ const url = c.detailsUrl ?? c.targetUrl ?? "";
4929
+ let block = ` - ${name} \u2192 ${concl}${url ? `
4930
+ ${url}` : ""}`;
4931
+ const tail = await this.failedLogTail(ref.repo, url);
4932
+ if (tail) block += `
4933
+ \u5931\u8D25\u65E5\u5FD7\uFF08\u672B\u5C3E\uFF09\uFF1A
4934
+ ${tail.split("\n").map((l) => " " + l).join("\n")}`;
4935
+ blocks.push(block);
4936
+ }
4937
+ return { state: "failure", summary: `CI \u672A\u8FC7\uFF08${failed.length} \u4E2A check\uFF09\uFF1A
4938
+ ${blocks.join("\n")}` };
4939
+ }
4940
+ if (anyPending) return { state: "pending" };
4941
+ return { state: "success", summary: `CI \u901A\u8FC7\uFF08${rollup.length} \u4E2A check\uFF09` };
4942
+ }
4943
+ /** best-effort:从 check 的 detailsUrl 提 Actions run id,取失败步骤日志末尾(截断)。取不到返回空。 */
4944
+ async failedLogTail(repo, detailsUrl) {
4945
+ const m2 = /\/runs\/(\d+)/.exec(detailsUrl);
4946
+ if (!m2) return "";
4947
+ try {
4948
+ const log3 = await this.gh(repo, ["run", "view", m2[1], "--log-failed"]);
4949
+ return log3.split("\n").filter(Boolean).slice(-40).join("\n").slice(-2e3);
4950
+ } catch {
4951
+ return "";
4952
+ }
4953
+ }
4954
+ async merge(ref) {
4955
+ try {
4956
+ await this.gh(ref.repo, ["pr", "merge", ref.branch, "--merge", "--delete-branch"]);
4957
+ this.opts.log?.(`[ci] merged PR ${ref.branch} \u2192 ${ref.repo.develop}`);
4958
+ return { merged: true };
4959
+ } catch (e) {
4960
+ return { merged: false, reason: String(e) };
4961
+ }
4962
+ }
4963
+ async isMerged(ref) {
4964
+ if (!ref.repo.remote) return false;
4965
+ try {
4966
+ await this.git(ref.repo, ["fetch", "--quiet", "origin", ref.repo.develop]);
4967
+ await this.git(ref.repo, ["merge-base", "--is-ancestor", ref.sha, `origin/${ref.repo.develop}`]);
4968
+ return true;
4969
+ } catch {
4970
+ return false;
4971
+ }
4972
+ }
4973
+ };
4974
+ }
4975
+ });
4976
+
4811
4977
  // ../server/src/git/collect.ts
4812
4978
  function collectUmbrellaCommits(repos, featBranch, env) {
4813
4979
  const out = {};
@@ -4815,7 +4981,7 @@ function collectUmbrellaCommits(repos, featBranch, env) {
4815
4981
  if (!r.remote) continue;
4816
4982
  let ls;
4817
4983
  try {
4818
- ls = (0, import_node_child_process.execFileSync)("git", ["ls-remote", r.remote, `refs/heads/${featBranch}`, `refs/heads/${r.develop}`], {
4984
+ ls = (0, import_node_child_process2.execFileSync)("git", ["ls-remote", r.remote, `refs/heads/${featBranch}`, `refs/heads/${r.develop}`], {
4819
4985
  encoding: "utf8",
4820
4986
  ...env ? { env } : {}
4821
4987
  });
@@ -4830,12 +4996,16 @@ function collectUmbrellaCommits(repos, featBranch, env) {
4830
4996
  }
4831
4997
  const featSha = refs.get(`refs/heads/${featBranch}`);
4832
4998
  const devSha = refs.get(`refs/heads/${r.develop}`);
4833
- if (featSha && featSha !== devSha) out[r.id] = featSha;
4999
+ if (featSha && featSha !== devSha) out[r.remote ? normalizeRemote(r.remote) : r.id] = featSha;
4834
5000
  }
4835
5001
  return out;
4836
5002
  }
4837
5003
  function parseUmbrellaCommits(contentRef, repos) {
4838
- const byId = new Map(repos.map((r) => [r.id, r]));
5004
+ const byKey = /* @__PURE__ */ new Map();
5005
+ for (const r of repos) {
5006
+ byKey.set(r.id, r);
5007
+ if (r.remote) byKey.set(normalizeRemote(r.remote), r);
5008
+ }
4839
5009
  if (contentRef.trim().startsWith("{")) {
4840
5010
  let manifest = null;
4841
5011
  try {
@@ -4845,8 +5015,8 @@ function parseUmbrellaCommits(contentRef, repos) {
4845
5015
  }
4846
5016
  if (manifest) {
4847
5017
  const out = [];
4848
- for (const [id, sha2] of Object.entries(manifest)) {
4849
- const repo = byId.get(id);
5018
+ for (const [key, sha2] of Object.entries(manifest)) {
5019
+ const repo = byKey.get(key);
4850
5020
  if (repo && typeof sha2 === "string") out.push({ repo, sha: sha2 });
4851
5021
  }
4852
5022
  return out;
@@ -4854,11 +5024,12 @@ function parseUmbrellaCommits(contentRef, repos) {
4854
5024
  }
4855
5025
  return repos[0] ? [{ repo: repos[0], sha: contentRef }] : [];
4856
5026
  }
4857
- var import_node_child_process;
5027
+ var import_node_child_process2;
4858
5028
  var init_collect = __esm({
4859
5029
  "../server/src/git/collect.ts"() {
4860
5030
  "use strict";
4861
- import_node_child_process = require("node:child_process");
5031
+ import_node_child_process2 = require("node:child_process");
5032
+ init_ci_provider();
4862
5033
  }
4863
5034
  });
4864
5035
 
@@ -4869,17 +5040,16 @@ function autoMergeWorkIntoFeat(args) {
4869
5040
  for (const repo of args.repos) {
4870
5041
  if (!repo.remote) continue;
4871
5042
  const remote = repo.remote;
4872
- const key = `${repo.id.replace(/[^a-zA-Z0-9_-]+/g, "_")}-${(0, import_node_crypto3.createHash)("sha1").update(remote).digest("hex").slice(0, 12)}`;
4873
- const dir = path.join(args.mirrorRoot, key);
4874
- const git = (a) => (0, import_node_child_process2.execFileSync)("git", ["-C", dir, ...a], { encoding: "utf8", env, maxBuffer: 256 * 1024 * 1024 }).trim();
5043
+ const dir = mirrorDirFor(args.mirrorRoot, repo);
5044
+ const git = (a) => (0, import_node_child_process3.execFileSync)("git", ["-C", dir, ...a], { encoding: "utf8", env, maxBuffer: 256 * 1024 * 1024 }).trim();
4875
5045
  const clone2 = () => {
4876
- fs.rmSync(dir, { recursive: true, force: true });
4877
- fs.mkdirSync(path.dirname(dir), { recursive: true });
4878
- (0, import_node_child_process2.execFileSync)("git", ["clone", "--quiet", remote, dir], { env, maxBuffer: 256 * 1024 * 1024 });
5046
+ fs2.rmSync(dir, { recursive: true, force: true });
5047
+ fs2.mkdirSync(path2.dirname(dir), { recursive: true });
5048
+ (0, import_node_child_process3.execFileSync)("git", ["clone", "--quiet", remote, dir], { env, maxBuffer: 256 * 1024 * 1024 });
4879
5049
  git(["config", "user.email", "oasis@local"]);
4880
5050
  git(["config", "user.name", "oasis"]);
4881
5051
  };
4882
- if (!fs.existsSync(path.join(dir, ".git"))) {
5052
+ if (!fs2.existsSync(path2.join(dir, ".git"))) {
4883
5053
  clone2();
4884
5054
  } else {
4885
5055
  let originOk = false;
@@ -4934,18 +5104,18 @@ function autoMergeWorkIntoFeat(args) {
4934
5104
  staged.push(dir);
4935
5105
  }
4936
5106
  for (const dir of staged) {
4937
- (0, import_node_child_process2.execFileSync)("git", ["-C", dir, "push", "--quiet", "origin", args.featBranch], { env, maxBuffer: 256 * 1024 * 1024 });
5107
+ (0, import_node_child_process3.execFileSync)("git", ["-C", dir, "push", "--quiet", "origin", args.featBranch], { env, maxBuffer: 256 * 1024 * 1024 });
4938
5108
  }
4939
5109
  return { ok: true };
4940
5110
  }
4941
- var import_node_child_process2, import_node_crypto3, fs, path;
5111
+ var import_node_child_process3, fs2, path2;
4942
5112
  var init_auto_merge = __esm({
4943
5113
  "../server/src/git/auto-merge.ts"() {
4944
5114
  "use strict";
4945
- import_node_child_process2 = require("node:child_process");
4946
- import_node_crypto3 = require("node:crypto");
4947
- fs = __toESM(require("node:fs"), 1);
4948
- path = __toESM(require("node:path"), 1);
5115
+ import_node_child_process3 = require("node:child_process");
5116
+ fs2 = __toESM(require("node:fs"), 1);
5117
+ path2 = __toESM(require("node:path"), 1);
5118
+ init_ci_provider();
4949
5119
  }
4950
5120
  });
4951
5121
 
@@ -5361,8 +5531,8 @@ var init_parseUtil = __esm({
5361
5531
  init_errors2();
5362
5532
  init_en();
5363
5533
  makeIssue = (params) => {
5364
- const { data, path: path20, errorMaps, issueData } = params;
5365
- const fullPath = [...path20, ...issueData.path || []];
5534
+ const { data, path: path19, errorMaps, issueData } = params;
5535
+ const fullPath = [...path19, ...issueData.path || []];
5366
5536
  const fullIssue = {
5367
5537
  ...issueData,
5368
5538
  path: fullPath
@@ -5670,11 +5840,11 @@ var init_types = __esm({
5670
5840
  init_parseUtil();
5671
5841
  init_util();
5672
5842
  ParseInputLazyPath = class {
5673
- constructor(parent, value, path20, key) {
5843
+ constructor(parent, value, path19, key) {
5674
5844
  this._cachedPath = [];
5675
5845
  this.parent = parent;
5676
5846
  this.data = value;
5677
- this._path = path20;
5847
+ this._path = path19;
5678
5848
  this._key = key;
5679
5849
  }
5680
5850
  get path() {
@@ -9248,10 +9418,10 @@ function assignProp(target, prop, value) {
9248
9418
  configurable: true
9249
9419
  });
9250
9420
  }
9251
- function getElementAtPath(obj, path20) {
9252
- if (!path20)
9421
+ function getElementAtPath(obj, path19) {
9422
+ if (!path19)
9253
9423
  return obj;
9254
- return path20.reduce((acc, key) => acc?.[key], obj);
9424
+ return path19.reduce((acc, key) => acc?.[key], obj);
9255
9425
  }
9256
9426
  function promiseAllObject(promisesObj) {
9257
9427
  const keys = Object.keys(promisesObj);
@@ -9500,11 +9670,11 @@ function aborted(x2, startIndex = 0) {
9500
9670
  }
9501
9671
  return false;
9502
9672
  }
9503
- function prefixIssues(path20, issues) {
9673
+ function prefixIssues(path19, issues) {
9504
9674
  return issues.map((iss) => {
9505
9675
  var _a;
9506
9676
  (_a = iss).path ?? (_a.path = []);
9507
- iss.path.unshift(path20);
9677
+ iss.path.unshift(path19);
9508
9678
  return iss;
9509
9679
  });
9510
9680
  }
@@ -18044,8 +18214,8 @@ var require_utils = __commonJS({
18044
18214
  }
18045
18215
  return ind;
18046
18216
  }
18047
- function removeDotSegments(path20) {
18048
- let input = path20;
18217
+ function removeDotSegments(path19) {
18218
+ let input = path19;
18049
18219
  const output = [];
18050
18220
  let nextSlash = -1;
18051
18221
  let len = 0;
@@ -18297,8 +18467,8 @@ var require_schemes = __commonJS({
18297
18467
  wsComponent.secure = void 0;
18298
18468
  }
18299
18469
  if (wsComponent.resourceName) {
18300
- const [path20, query] = wsComponent.resourceName.split("?");
18301
- wsComponent.path = path20 && path20 !== "/" ? path20 : void 0;
18470
+ const [path19, query] = wsComponent.resourceName.split("?");
18471
+ wsComponent.path = path19 && path19 !== "/" ? path19 : void 0;
18302
18472
  wsComponent.query = query;
18303
18473
  wsComponent.resourceName = void 0;
18304
18474
  }
@@ -21811,23 +21981,23 @@ var init_router = __esm({
21811
21981
  };
21812
21982
  Router = class {
21813
21983
  routes = [];
21814
- on(method, path20, handler) {
21815
- this.routes.push({ method, segments: path20.split("/").filter(Boolean), handler });
21984
+ on(method, path19, handler) {
21985
+ this.routes.push({ method, segments: path19.split("/").filter(Boolean), handler });
21816
21986
  }
21817
- get(path20, h) {
21818
- this.on("GET", path20, h);
21987
+ get(path19, h) {
21988
+ this.on("GET", path19, h);
21819
21989
  }
21820
- post(path20, h) {
21821
- this.on("POST", path20, h);
21990
+ post(path19, h) {
21991
+ this.on("POST", path19, h);
21822
21992
  }
21823
- patch(path20, h) {
21824
- this.on("PATCH", path20, h);
21993
+ patch(path19, h) {
21994
+ this.on("PATCH", path19, h);
21825
21995
  }
21826
- put(path20, h) {
21827
- this.on("PUT", path20, h);
21996
+ put(path19, h) {
21997
+ this.on("PUT", path19, h);
21828
21998
  }
21829
- delete(path20, h) {
21830
- this.on("DELETE", path20, h);
21999
+ delete(path19, h) {
22000
+ this.on("DELETE", path19, h);
21831
22001
  }
21832
22002
  match(method, pathname) {
21833
22003
  const parts = pathname.split("/").filter(Boolean);
@@ -22296,10 +22466,10 @@ async function buildDynamicWorkorderPlan(input) {
22296
22466
  const schema = input.schema;
22297
22467
  const schemaByName = new Map(schema.map((def) => [def.name, def]));
22298
22468
  const displayTitle = input.title?.trim() || input.description;
22299
- const slug6 = artifactSlug(input.requestedArtifactId ?? input.workspace, displayTitle);
22300
- const briefId = `artifact:brief:${slug6}`;
22469
+ const slug4 = artifactSlug(input.requestedArtifactId ?? input.workspace, displayTitle);
22470
+ const briefId = `artifact:brief:${slug4}`;
22301
22471
  const primaryType = schemaByName.has(input.requestedType) && input.requestedType !== "brief" ? input.requestedType : "prd";
22302
- const primaryId = input.requestedArtifactId && input.requestedType === primaryType ? input.requestedArtifactId : `artifact:${primaryType}:${slug6}`;
22472
+ const primaryId = input.requestedArtifactId && input.requestedType === primaryType ? input.requestedArtifactId : `artifact:${primaryType}:${slug4}`;
22303
22473
  const issues = [...input.agentIssues ?? []];
22304
22474
  const enforceStaffing = Boolean(input.registry);
22305
22475
  const staffableTypes = new Set((await plannerArtifactTypes(schema, input.registry)).map((def) => def.name));
@@ -22378,7 +22548,7 @@ async function buildDynamicWorkorderPlan(input) {
22378
22548
  const owner = await resolveRole(def.ownerRole, type);
22379
22549
  const ownerActor = owner.actor ?? (type === primaryType ? input.actor : `pending:role:${def.ownerRole}`);
22380
22550
  if (enforceStaffing && !owner.actor && type !== primaryType) continue;
22381
- const id = type === primaryType ? primaryId : `artifact:${type}:${slug6}`;
22551
+ const id = type === primaryType ? primaryId : `artifact:${type}:${slug4}`;
22382
22552
  availableNodes.push({ type, id, role: def.ownerRole, owner: ownerActor });
22383
22553
  }
22384
22554
  }
@@ -23859,11 +24029,11 @@ async function resolveProposeContent(kernel, blobs, args, artifactId, ctx) {
23859
24029
  const ws = art?.workspace;
23860
24030
  const repos = ws ? (await ctx.resolveCodeRepo(ws))?.repos : void 0;
23861
24031
  if (repos?.length) {
23862
- const slug6 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
23863
- const feat = `feat/${slug6(artifactId)}`;
24032
+ const slug4 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
24033
+ const feat = `feat/${slug4(artifactId)}`;
23864
24034
  const proposingPart = optStr(args, "part");
23865
24035
  if (proposingPart !== void 0 && ctx.gitMirrorRoot) {
23866
- const work = `feat/${slug6(artifactId)}__${slug6(proposingPart)}`;
24036
+ const work = `feat/${slug4(artifactId)}__${slug4(proposingPart)}`;
23867
24037
  const r = autoMergeWorkIntoFeat({
23868
24038
  repos,
23869
24039
  workBranch: work,
@@ -24582,7 +24752,7 @@ async function runView(kernel, oplog, blobs, name, artifactId, params, ciGateSta
24582
24752
  }
24583
24753
  case "content": {
24584
24754
  const id = need2();
24585
- const path20 = params?.get("path") ?? null;
24755
+ const path19 = params?.get("path") ?? null;
24586
24756
  const artifact = model.artifacts.get(id);
24587
24757
  if (!artifact) throw new Error(`artifact \u4E0D\u5B58\u5728: ${id}`);
24588
24758
  const head = artifact.currentRev;
@@ -24594,11 +24764,11 @@ async function runView(kernel, oplog, blobs, name, artifactId, params, ciGateSta
24594
24764
  const dec2 = new TextDecoder();
24595
24765
  if (headRev.contentKind === "manifest") {
24596
24766
  const entries = await readManifest(blobs, headRev.contentRef);
24597
- if (path20 !== null) {
24598
- const e = entries.find((x2) => x2.path === path20);
24599
- if (!e) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${path20}\uFF08\u672C\u4EA7\u7269\u6709\uFF1A${entries.map((x2) => x2.path).join("\u3001")}\uFF09`);
24767
+ if (path19 !== null) {
24768
+ const e = entries.find((x2) => x2.path === path19);
24769
+ if (!e) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${path19}\uFF08\u672C\u4EA7\u7269\u6709\uFF1A${entries.map((x2) => x2.path).join("\u3001")}\uFF09`);
24600
24770
  const isText = !e.bytes.includes(0);
24601
- return { kind: "file", path: path20, bytes: e.bytes.length, text: isText ? dec2.decode(e.bytes) : null };
24771
+ return { kind: "file", path: path19, bytes: e.bytes.length, text: isText ? dec2.decode(e.bytes) : null };
24602
24772
  }
24603
24773
  return {
24604
24774
  kind: "manifest",
@@ -24870,7 +25040,9 @@ async function startOasisServer(opts) {
24870
25040
  if (url.pathname === "/api/intervention/draft" && req.method === "POST") {
24871
25041
  try {
24872
25042
  const plan = JSON.parse(rawBody);
24873
- const { draftId, changeClass, nonMonotonicOps } = await engine.kernel.proposeIntervention(plan, actor);
25043
+ const chatSessionId = req.headers["x-chat-session-id"];
25044
+ const origin = typeof chatSessionId === "string" && chatSessionId ? chatSessionId : void 0;
25045
+ const { draftId, changeClass, nonMonotonicOps } = await engine.kernel.proposeIntervention(plan, actor, origin ? { origin } : void 0);
24874
25046
  res.writeHead(200, { "content-type": "application/json" }).end(
24875
25047
  JSON.stringify({ draftId, changeClass, nonMonotonicOps })
24876
25048
  );
@@ -25236,7 +25408,10 @@ async function startOasisServer(opts) {
25236
25408
  try {
25237
25409
  const viewName = url.searchParams.get("name") ?? "";
25238
25410
  if (viewName === "intervention-drafts") {
25239
- const data2 = listPendingReviews(engine.kernel.model).map((r) => ({
25411
+ const origin = url.searchParams.get("origin");
25412
+ const workspace = url.searchParams.get("workspace") ?? void 0;
25413
+ const reviews = listPendingReviews(engine.kernel.model, origin === null ? workspace : void 0).filter((r) => origin === null ? true : r.origin === origin);
25414
+ const data2 = reviews.map((r) => ({
25240
25415
  id: r.draftId,
25241
25416
  plan: r.plan,
25242
25417
  draftedBy: r.proposedBy,
@@ -25247,6 +25422,7 @@ async function startOasisServer(opts) {
25247
25422
  downstreamClosure: r.downstreamClosure,
25248
25423
  at: r.at,
25249
25424
  origin: r.origin,
25425
+ workspace: r.workspace,
25250
25426
  anchor: r.anchor
25251
25427
  }));
25252
25428
  res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ data: data2 }));
@@ -25559,12 +25735,12 @@ async function startOasisServer(opts) {
25559
25735
  const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
25560
25736
  if (actorCtx) {
25561
25737
  const { mkdtempSync: mkdtempSync9, mkdirSync: mkdirSync17, writeFileSync: writeFileSync15 } = await import("node:fs");
25562
- const { join: join24, dirname: dirname19 } = await import("node:path");
25563
- const { tmpdir: tmpdir13 } = await import("node:os");
25564
- const dir = mkdtempSync9(join24(tmpdir13(), "oasis-chat-"));
25738
+ const { join: join23, dirname: dirname19 } = await import("node:path");
25739
+ const { tmpdir: tmpdir12 } = await import("node:os");
25740
+ const dir = mkdtempSync9(join23(tmpdir12(), "oasis-chat-"));
25565
25741
  if (actorCtx.config?.prompt) {
25566
25742
  for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
25567
- const file = join24(dir, rel);
25743
+ const file = join23(dir, rel);
25568
25744
  mkdirSync17(dirname19(file), { recursive: true });
25569
25745
  writeFileSync15(file, content);
25570
25746
  }
@@ -25576,12 +25752,12 @@ async function startOasisServer(opts) {
25576
25752
  const s2 = byId.get(id);
25577
25753
  return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
25578
25754
  });
25579
- writeFileSync15(join24(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
25755
+ writeFileSync15(join23(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
25580
25756
  }
25581
25757
  if (opts.materializeSkills) {
25582
25758
  const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
25583
25759
  for (const [rel, content] of Object.entries(skillFiles)) {
25584
- const file = join24(dir, rel);
25760
+ const file = join23(dir, rel);
25585
25761
  mkdirSync17(dirname19(file), { recursive: true });
25586
25762
  writeFileSync15(file, content);
25587
25763
  }
@@ -25595,7 +25771,7 @@ async function startOasisServer(opts) {
25595
25771
  const modeNote = c.mode === "oauth" ? "OAuth \xB7 \u51ED\u8BC1\u7531\u5E73\u53F0\u7BA1\u7406\uFF0C\u901A\u8FC7\u5BF9\u5E94 CLI wrapper \u8C03\u7528" : "\u76F4\u63A5\u5199\u5165 \xB7 \u51ED\u8BC1\u5DF2\u6CE8\u5165\u73AF\u5883\u53D8\u91CF";
25596
25772
  return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
25597
25773
  });
25598
- writeFileSync15(join24(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
25774
+ writeFileSync15(join23(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
25599
25775
  }
25600
25776
  spawnCwd = dir;
25601
25777
  }
@@ -26037,16 +26213,16 @@ function createTokenIssuer(opts = {}) {
26037
26213
  function createNodeTokenStore(file) {
26038
26214
  const read = () => {
26039
26215
  try {
26040
- return JSON.parse(fs3.readFileSync(file, "utf8"));
26216
+ return JSON.parse(fs4.readFileSync(file, "utf8"));
26041
26217
  } catch {
26042
26218
  return {};
26043
26219
  }
26044
26220
  };
26045
- const write = (table) => fs3.writeFileSync(file, JSON.stringify(table, null, 2), { mode: 384 });
26221
+ const write = (table) => fs4.writeFileSync(file, JSON.stringify(table, null, 2), { mode: 384 });
26046
26222
  return {
26047
26223
  issue(nodeId) {
26048
26224
  const table = read();
26049
- const token = `ont_${(0, import_node_crypto4.randomBytes)(24).toString("base64url")}`;
26225
+ const token = `ont_${(0, import_node_crypto3.randomBytes)(24).toString("base64url")}`;
26050
26226
  table[token] = nodeId;
26051
26227
  write(table);
26052
26228
  return token;
@@ -26068,14 +26244,14 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
26068
26244
  const read = () => {
26069
26245
  if (!file) return table;
26070
26246
  try {
26071
- return new Map(Object.entries(JSON.parse(fs3.readFileSync(file, "utf8"))));
26247
+ return new Map(Object.entries(JSON.parse(fs4.readFileSync(file, "utf8"))));
26072
26248
  } catch {
26073
26249
  return /* @__PURE__ */ new Map();
26074
26250
  }
26075
26251
  };
26076
26252
  const write = (m2) => {
26077
26253
  if (!file) return;
26078
- fs3.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
26254
+ fs4.writeFileSync(file, JSON.stringify(Object.fromEntries(m2), null, 2), { mode: 384 });
26079
26255
  };
26080
26256
  const table = /* @__PURE__ */ new Map();
26081
26257
  const prune = () => {
@@ -26088,7 +26264,7 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
26088
26264
  return {
26089
26265
  issue(name, ttlMs = defaultTtlMs) {
26090
26266
  const m2 = prune();
26091
- const token = `ent_${(0, import_node_crypto4.randomBytes)(24).toString("base64url")}`;
26267
+ const token = `ent_${(0, import_node_crypto3.randomBytes)(24).toString("base64url")}`;
26092
26268
  const expiresAt = Date.now() + ttlMs;
26093
26269
  m2.set(token, { name, expiresAt });
26094
26270
  write(m2);
@@ -26118,33 +26294,33 @@ function createEnrollTokenStore(defaultTtlMs = 30 * 60 * 1e3, file) {
26118
26294
  }
26119
26295
  };
26120
26296
  }
26121
- var import_node_crypto4, fs3, path2, SESSION_TOKEN_PREFIX, b64url, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
26297
+ var import_node_crypto3, fs4, path3, SESSION_TOKEN_PREFIX, b64url, fromB64url, readOrCreateSecret, sign, signatureMatches, isTokenClaims;
26122
26298
  var init_tokens = __esm({
26123
26299
  "../server/src/tokens.ts"() {
26124
26300
  "use strict";
26125
- import_node_crypto4 = require("node:crypto");
26126
- fs3 = __toESM(require("node:fs"), 1);
26127
- path2 = __toESM(require("node:path"), 1);
26301
+ import_node_crypto3 = require("node:crypto");
26302
+ fs4 = __toESM(require("node:fs"), 1);
26303
+ path3 = __toESM(require("node:path"), 1);
26128
26304
  SESSION_TOKEN_PREFIX = "oat_v2_";
26129
26305
  b64url = (value) => Buffer.from(value).toString("base64url");
26130
26306
  fromB64url = (value) => Buffer.from(value, "base64url").toString("utf8");
26131
26307
  readOrCreateSecret = (file) => {
26132
- if (!file) return (0, import_node_crypto4.randomBytes)(32);
26308
+ if (!file) return (0, import_node_crypto3.randomBytes)(32);
26133
26309
  try {
26134
- const raw = fs3.readFileSync(file, "utf8").trim();
26310
+ const raw = fs4.readFileSync(file, "utf8").trim();
26135
26311
  if (raw) return Buffer.from(raw, "base64url");
26136
26312
  } catch {
26137
26313
  }
26138
- const secret = (0, import_node_crypto4.randomBytes)(32);
26139
- fs3.mkdirSync(path2.dirname(file), { recursive: true });
26140
- fs3.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
26314
+ const secret = (0, import_node_crypto3.randomBytes)(32);
26315
+ fs4.mkdirSync(path3.dirname(file), { recursive: true });
26316
+ fs4.writeFileSync(file, secret.toString("base64url"), { mode: 384 });
26141
26317
  return secret;
26142
26318
  };
26143
- sign = (secret, payload) => (0, import_node_crypto4.createHmac)("sha256", secret).update(payload).digest("base64url");
26319
+ sign = (secret, payload) => (0, import_node_crypto3.createHmac)("sha256", secret).update(payload).digest("base64url");
26144
26320
  signatureMatches = (actual, expected) => {
26145
26321
  const a = Buffer.from(actual);
26146
26322
  const b2 = Buffer.from(expected);
26147
- return a.length === b2.length && (0, import_node_crypto4.timingSafeEqual)(a, b2);
26323
+ return a.length === b2.length && (0, import_node_crypto3.timingSafeEqual)(a, b2);
26148
26324
  };
26149
26325
  isTokenClaims = (value) => {
26150
26326
  if (value === null || typeof value !== "object") return false;
@@ -26992,9 +27168,9 @@ var init_memory_control_plane_store = __esm({
26992
27168
  const c = this.companies.get(id);
26993
27169
  return c ? { ...c } : null;
26994
27170
  }
26995
- async getCompanyBySlug(slug6) {
27171
+ async getCompanyBySlug(slug4) {
26996
27172
  for (const c of this.companies.values()) {
26997
- if (c.slug === slug6) return { ...c };
27173
+ if (c.slug === slug4) return { ...c };
26998
27174
  }
26999
27175
  return null;
27000
27176
  }
@@ -27489,8 +27665,8 @@ function namedError(name, message) {
27489
27665
  return err;
27490
27666
  }
27491
27667
  function slugProjectId(name) {
27492
- const slug6 = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
27493
- return `proj_${slug6 || Date.now()}`;
27668
+ const slug4 = name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
27669
+ return `proj_${slug4 || Date.now()}`;
27494
27670
  }
27495
27671
  function runStateKey(workOrderId, nodeId) {
27496
27672
  return `${workOrderId ?? ""}::${nodeId ?? ""}`;
@@ -27920,13 +28096,13 @@ var init_service = __esm({
27920
28096
  async readDocument(contentRef) {
27921
28097
  for (const [projectId, space] of this.spaces) {
27922
28098
  if (!contentRef.startsWith(`${space.rootRef}/`)) continue;
27923
- const path20 = contentRef.slice(space.rootRef.length + 1);
27924
- const content = space.files.get(path20);
28099
+ const path19 = contentRef.slice(space.rootRef.length + 1);
28100
+ const content = space.files.get(path19);
27925
28101
  if (content === void 0) return null;
27926
28102
  return {
27927
28103
  contentRef,
27928
28104
  content,
27929
- url: `https://outline.local/${encodeURIComponent(projectId)}/${path20.split("/").map(encodeURIComponent).join("/")}`
28105
+ url: `https://outline.local/${encodeURIComponent(projectId)}/${path19.split("/").map(encodeURIComponent).join("/")}`
27930
28106
  };
27931
28107
  }
27932
28108
  return null;
@@ -28010,8 +28186,8 @@ var init_service = __esm({
28010
28186
  const space = this.requireSpace(state.projectId);
28011
28187
  const stored = { ...state, payload: { ...state.payload }, updatedAt: state.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
28012
28188
  space.runStates.set(runStateKey(state.workOrderId, state.nodeId), stored);
28013
- const path20 = `run_state/${state.workOrderId ?? "project"}/${state.nodeId ?? "default"}.json`;
28014
- space.files.set(path20, JSON.stringify(stored, null, 2));
28189
+ const path19 = `run_state/${state.workOrderId ?? "project"}/${state.nodeId ?? "default"}.json`;
28190
+ space.files.set(path19, JSON.stringify(stored, null, 2));
28015
28191
  return { ...stored, payload: { ...stored.payload } };
28016
28192
  }
28017
28193
  requireSpace(projectId) {
@@ -28711,13 +28887,13 @@ var init_service = __esm({
28711
28887
  });
28712
28888
 
28713
28889
  // ../server/src/dev-store.ts
28714
- var import_node_crypto5, fs4, path3, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRegistryStore, FileProjectStateStore, FileProjectDocumentStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore;
28890
+ var import_node_crypto4, fs5, path4, NdjsonOplogStore, DirBlobStore, MUTATORS, FileTypeRegistryStore, FileRegistryStore, FileProjectStateStore, FileProjectDocumentStore, FileArtifactStateStore, FileTraceStore, MemoryChatSessionStore, FileChatSessionStore;
28715
28891
  var init_dev_store = __esm({
28716
28892
  "../server/src/dev-store.ts"() {
28717
28893
  "use strict";
28718
- import_node_crypto5 = require("node:crypto");
28719
- fs4 = __toESM(require("node:fs"), 1);
28720
- path3 = __toESM(require("node:path"), 1);
28894
+ import_node_crypto4 = require("node:crypto");
28895
+ fs5 = __toESM(require("node:fs"), 1);
28896
+ path4 = __toESM(require("node:path"), 1);
28721
28897
  init_src();
28722
28898
  init_src3();
28723
28899
  init_src3();
@@ -28729,8 +28905,8 @@ var init_dev_store = __esm({
28729
28905
  }
28730
28906
  static async open(file) {
28731
28907
  const memory = new MemoryOplogStore();
28732
- if (fs4.existsSync(file)) {
28733
- for (const line of fs4.readFileSync(file, "utf8").split("\n")) {
28908
+ if (fs5.existsSync(file)) {
28909
+ for (const line of fs5.readFileSync(file, "utf8").split("\n")) {
28734
28910
  if (!line.trim()) continue;
28735
28911
  const stored = JSON.parse(line);
28736
28912
  const { artifactId, seq, ...op } = stored;
@@ -28738,15 +28914,15 @@ var init_dev_store = __esm({
28738
28914
  if (assigned !== seq) throw new Error(`corrupt ndjson log: seq mismatch at ${line}`);
28739
28915
  }
28740
28916
  } else {
28741
- fs4.mkdirSync(path3.dirname(file), { recursive: true });
28742
- fs4.writeFileSync(file, "");
28917
+ fs5.mkdirSync(path4.dirname(file), { recursive: true });
28918
+ fs5.writeFileSync(file, "");
28743
28919
  }
28744
28920
  return new _NdjsonOplogStore(file, memory);
28745
28921
  }
28746
28922
  async append(artifactId, op, expectedSeq) {
28747
28923
  const seq = await this.memory.append(artifactId, op, expectedSeq);
28748
28924
  const stored = { ...op, artifactId, seq };
28749
- fs4.appendFileSync(this.file, JSON.stringify(stored) + "\n");
28925
+ fs5.appendFileSync(this.file, JSON.stringify(stored) + "\n");
28750
28926
  return seq;
28751
28927
  }
28752
28928
  read(artifactId, fromSeq) {
@@ -28762,39 +28938,39 @@ var init_dev_store = __esm({
28762
28938
  DirBlobStore = class {
28763
28939
  constructor(dir) {
28764
28940
  this.dir = dir;
28765
- fs4.mkdirSync(dir, { recursive: true });
28941
+ fs5.mkdirSync(dir, { recursive: true });
28766
28942
  }
28767
28943
  fileOf(hash) {
28768
- return path3.join(this.dir, hash);
28944
+ return path4.join(this.dir, hash);
28769
28945
  }
28770
28946
  async put(bytes) {
28771
- const hash = (0, import_node_crypto5.createHash)("sha256").update(bytes).digest("hex");
28947
+ const hash = (0, import_node_crypto4.createHash)("sha256").update(bytes).digest("hex");
28772
28948
  const file = this.fileOf(hash);
28773
- if (!fs4.existsSync(file)) fs4.writeFileSync(file, bytes);
28949
+ if (!fs5.existsSync(file)) fs5.writeFileSync(file, bytes);
28774
28950
  return hash;
28775
28951
  }
28776
28952
  async meta(hash) {
28777
28953
  const file = this.fileOf(hash);
28778
- if (!fs4.existsSync(file)) return null;
28779
- const size = fs4.statSync(file).size;
28780
- const fd = fs4.openSync(file, "r");
28954
+ if (!fs5.existsSync(file)) return null;
28955
+ const size = fs5.statSync(file).size;
28956
+ const fd = fs5.openSync(file, "r");
28781
28957
  const head = Buffer.alloc(16);
28782
- fs4.readSync(fd, head, 0, 16, 0);
28783
- fs4.closeSync(fd);
28958
+ fs5.readSync(fd, head, 0, 16, 0);
28959
+ fs5.closeSync(fd);
28784
28960
  const contentType = sniffContentType(new Uint8Array(head));
28785
28961
  return { size, ...contentType ? { contentType } : {} };
28786
28962
  }
28787
28963
  async get(hash) {
28788
28964
  const file = this.fileOf(hash);
28789
- if (!fs4.existsSync(file)) throw new BlobNotFoundError(hash);
28790
- return new Uint8Array(fs4.readFileSync(file));
28965
+ if (!fs5.existsSync(file)) throw new BlobNotFoundError(hash);
28966
+ return new Uint8Array(fs5.readFileSync(file));
28791
28967
  }
28792
28968
  async has(hash) {
28793
- return fs4.existsSync(this.fileOf(hash));
28969
+ return fs5.existsSync(this.fileOf(hash));
28794
28970
  }
28795
28971
  async sweep(reachable) {
28796
- for (const name of fs4.readdirSync(this.dir)) {
28797
- if (!reachable.has(name)) fs4.unlinkSync(this.fileOf(name));
28972
+ for (const name of fs5.readdirSync(this.dir)) {
28973
+ if (!reachable.has(name)) fs5.unlinkSync(this.fileOf(name));
28798
28974
  }
28799
28975
  }
28800
28976
  };
@@ -28822,7 +28998,7 @@ var init_dev_store = __esm({
28822
28998
  this.file = file;
28823
28999
  }
28824
29000
  static async open(file) {
28825
- const seed = fs4.existsSync(file) ? JSON.parse(fs4.readFileSync(file, "utf8")) : [];
29001
+ const seed = fs5.existsSync(file) ? JSON.parse(fs5.readFileSync(file, "utf8")) : [];
28826
29002
  return new _FileTypeRegistryStore(file, seed);
28827
29003
  }
28828
29004
  async put(def) {
@@ -28835,8 +29011,8 @@ var init_dev_store = __esm({
28835
29011
  }
28836
29012
  async save() {
28837
29013
  const tmp = `${this.file}.tmp`;
28838
- fs4.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
28839
- fs4.renameSync(tmp, this.file);
29014
+ fs5.writeFileSync(tmp, JSON.stringify(await this.list(), null, 2));
29015
+ fs5.renameSync(tmp, this.file);
28840
29016
  }
28841
29017
  };
28842
29018
  FileRegistryStore = class _FileRegistryStore extends MemoryRegistryStore {
@@ -28854,8 +29030,8 @@ var init_dev_store = __esm({
28854
29030
  }
28855
29031
  static async open(file) {
28856
29032
  const store = new _FileRegistryStore(file);
28857
- if (fs4.existsSync(file)) {
28858
- const snap = JSON.parse(fs4.readFileSync(file, "utf8"));
29033
+ if (fs5.existsSync(file)) {
29034
+ const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
28859
29035
  for (const a of snap.actors) await MemoryRegistryStore.prototype.upsertActor.call(store, a);
28860
29036
  for (const c of snap.configs) await MemoryRegistryStore.prototype.appendConfig.call(store, c);
28861
29037
  for (const t of snap.teams) await MemoryRegistryStore.prototype.upsertTeam.call(store, t);
@@ -28896,7 +29072,7 @@ var init_dev_store = __esm({
28896
29072
  skillFiles: skillFilesEntries,
28897
29073
  connections
28898
29074
  };
28899
- fs4.writeFileSync(this.file, JSON.stringify(snap, null, 2));
29075
+ fs5.writeFileSync(this.file, JSON.stringify(snap, null, 2));
28900
29076
  }
28901
29077
  };
28902
29078
  FileProjectStateStore = class _FileProjectStateStore extends MemoryProjectStateStore {
@@ -28906,8 +29082,8 @@ var init_dev_store = __esm({
28906
29082
  }
28907
29083
  static async open(file) {
28908
29084
  const store = new _FileProjectStateStore(file);
28909
- if (fs4.existsSync(file)) {
28910
- const snap = JSON.parse(fs4.readFileSync(file, "utf8"));
29085
+ if (fs5.existsSync(file)) {
29086
+ const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
28911
29087
  for (const project of snap.projects ?? []) await MemoryProjectStateStore.prototype.upsertProject.call(store, project);
28912
29088
  const membersByProject = /* @__PURE__ */ new Map();
28913
29089
  for (const member of snap.members ?? []) {
@@ -28919,8 +29095,8 @@ var init_dev_store = __esm({
28919
29095
  await MemoryProjectStateStore.prototype.replaceProjectMembers.call(store, projectId, members);
28920
29096
  }
28921
29097
  } else {
28922
- fs4.mkdirSync(path3.dirname(file), { recursive: true });
28923
- fs4.writeFileSync(file, JSON.stringify({ projects: [], members: [] }, null, 2));
29098
+ fs5.mkdirSync(path4.dirname(file), { recursive: true });
29099
+ fs5.writeFileSync(file, JSON.stringify({ projects: [], members: [] }, null, 2));
28924
29100
  }
28925
29101
  return store;
28926
29102
  }
@@ -28939,7 +29115,7 @@ var init_dev_store = __esm({
28939
29115
  async save() {
28940
29116
  const projects = await this.listProjects();
28941
29117
  const members = (await Promise.all(projects.map((project) => this.listProjectMembers(project.id)))).flat();
28942
- fs4.writeFileSync(this.file, JSON.stringify({ projects, members }, null, 2));
29118
+ fs5.writeFileSync(this.file, JSON.stringify({ projects, members }, null, 2));
28943
29119
  }
28944
29120
  };
28945
29121
  FileProjectDocumentStore = class _FileProjectDocumentStore extends MemoryProjectDocumentStore {
@@ -28949,8 +29125,8 @@ var init_dev_store = __esm({
28949
29125
  }
28950
29126
  static async open(file) {
28951
29127
  const store = new _FileProjectDocumentStore(file);
28952
- if (fs4.existsSync(file)) {
28953
- const snap = JSON.parse(fs4.readFileSync(file, "utf8"));
29128
+ if (fs5.existsSync(file)) {
29129
+ const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
28954
29130
  for (const [projectId, space] of Object.entries(snap.spaces ?? {})) {
28955
29131
  store.spaces.set(projectId, {
28956
29132
  rootRef: space.rootRef,
@@ -28964,8 +29140,8 @@ var init_dev_store = __esm({
28964
29140
  });
28965
29141
  }
28966
29142
  } else {
28967
- fs4.mkdirSync(path3.dirname(file), { recursive: true });
28968
- fs4.writeFileSync(file, JSON.stringify({ spaces: {} }, null, 2));
29143
+ fs5.mkdirSync(path4.dirname(file), { recursive: true });
29144
+ fs5.writeFileSync(file, JSON.stringify({ spaces: {} }, null, 2));
28969
29145
  }
28970
29146
  return store;
28971
29147
  }
@@ -28998,7 +29174,7 @@ var init_dev_store = __esm({
28998
29174
  runStates: [...space.runStates.values()]
28999
29175
  };
29000
29176
  }
29001
- fs4.writeFileSync(this.file, JSON.stringify({ spaces }, null, 2));
29177
+ fs5.writeFileSync(this.file, JSON.stringify({ spaces }, null, 2));
29002
29178
  }
29003
29179
  };
29004
29180
  FileArtifactStateStore = class _FileArtifactStateStore extends MemoryArtifactStateStore {
@@ -29008,8 +29184,8 @@ var init_dev_store = __esm({
29008
29184
  }
29009
29185
  static async open(file) {
29010
29186
  const store = new _FileArtifactStateStore(file);
29011
- if (fs4.existsSync(file)) {
29012
- const snap = JSON.parse(fs4.readFileSync(file, "utf8"));
29187
+ if (fs5.existsSync(file)) {
29188
+ const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
29013
29189
  for (const artifact of snap.artifacts ?? []) await MemoryArtifactStateStore.prototype.upsertArtifact.call(store, artifact);
29014
29190
  for (const revision of snap.revisions ?? []) await MemoryArtifactStateStore.prototype.upsertRevision.call(store, revision);
29015
29191
  for (const event of snap.events ?? []) await MemoryArtifactStateStore.prototype.appendEvent.call(store, event);
@@ -29018,8 +29194,8 @@ var init_dev_store = __esm({
29018
29194
  for (const binding of snap.workspaceBindings ?? []) await MemoryArtifactStateStore.prototype.upsertWorkspaceBinding.call(store, binding);
29019
29195
  for (const ws of snap.workspaceDispatchHeld ?? []) await MemoryArtifactStateStore.prototype.setWorkspaceDispatchHold.call(store, ws, true);
29020
29196
  } else {
29021
- fs4.mkdirSync(path3.dirname(file), { recursive: true });
29022
- fs4.writeFileSync(file, JSON.stringify({ artifacts: [], revisions: [], events: [], annotations: [], nodeOutputs: [], workspaceBindings: [], workspaceDispatchHeld: [] }, null, 2));
29197
+ fs5.mkdirSync(path4.dirname(file), { recursive: true });
29198
+ fs5.writeFileSync(file, JSON.stringify({ artifacts: [], revisions: [], events: [], annotations: [], nodeOutputs: [], workspaceBindings: [], workspaceDispatchHeld: [] }, null, 2));
29023
29199
  }
29024
29200
  return store;
29025
29201
  }
@@ -29052,7 +29228,7 @@ var init_dev_store = __esm({
29052
29228
  await this.save();
29053
29229
  }
29054
29230
  async save() {
29055
- fs4.writeFileSync(this.file, JSON.stringify(await this.listAll(), null, 2));
29231
+ fs5.writeFileSync(this.file, JSON.stringify(await this.listAll(), null, 2));
29056
29232
  }
29057
29233
  };
29058
29234
  FileTraceStore = class _FileTraceStore extends MemoryTraceStore {
@@ -29061,39 +29237,39 @@ var init_dev_store = __esm({
29061
29237
  this.dir = dir;
29062
29238
  }
29063
29239
  get runsFile() {
29064
- return path3.join(this.dir, "runs.ndjson");
29240
+ return path4.join(this.dir, "runs.ndjson");
29065
29241
  }
29066
29242
  get toolCallsFile() {
29067
- return path3.join(this.dir, "tool-calls.ndjson");
29243
+ return path4.join(this.dir, "tool-calls.ndjson");
29068
29244
  }
29069
29245
  get linksFile() {
29070
- return path3.join(this.dir, "links.ndjson");
29246
+ return path4.join(this.dir, "links.ndjson");
29071
29247
  }
29072
29248
  get artifactsFile() {
29073
- return path3.join(this.dir, "artifacts.ndjson");
29249
+ return path4.join(this.dir, "artifacts.ndjson");
29074
29250
  }
29075
29251
  get eventsDir() {
29076
- return path3.join(this.dir, "events");
29252
+ return path4.join(this.dir, "events");
29077
29253
  }
29078
29254
  eventsFile(runId) {
29079
- return path3.join(this.eventsDir, `${encodeURIComponent(runId)}.ndjson`);
29255
+ return path4.join(this.eventsDir, `${encodeURIComponent(runId)}.ndjson`);
29080
29256
  }
29081
29257
  appendLine(file, obj) {
29082
- fs4.appendFileSync(file, JSON.stringify(obj) + "\n");
29258
+ fs5.appendFileSync(file, JSON.stringify(obj) + "\n");
29083
29259
  }
29084
29260
  static replay(file, fn) {
29085
- if (!fs4.existsSync(file)) return;
29086
- for (const line of fs4.readFileSync(file, "utf8").split("\n")) {
29261
+ if (!fs5.existsSync(file)) return;
29262
+ for (const line of fs5.readFileSync(file, "utf8").split("\n")) {
29087
29263
  if (!line.trim()) continue;
29088
29264
  fn(JSON.parse(line));
29089
29265
  }
29090
29266
  }
29091
29267
  static async open(dir) {
29092
29268
  const store = new _FileTraceStore(dir);
29093
- fs4.mkdirSync(store.eventsDir, { recursive: true });
29269
+ fs5.mkdirSync(store.eventsDir, { recursive: true });
29094
29270
  _FileTraceStore.replay(store.runsFile, (r) => store.restoreRun(r));
29095
- for (const name of fs4.readdirSync(store.eventsDir)) {
29096
- _FileTraceStore.replay(path3.join(store.eventsDir, name), (e) => store.restoreEvent(e));
29271
+ for (const name of fs5.readdirSync(store.eventsDir)) {
29272
+ _FileTraceStore.replay(path4.join(store.eventsDir, name), (e) => store.restoreEvent(e));
29097
29273
  }
29098
29274
  _FileTraceStore.replay(store.toolCallsFile, (c) => store.restoreToolCall(c));
29099
29275
  _FileTraceStore.replay(store.linksFile, (l) => store.restoreLink(l));
@@ -29196,14 +29372,14 @@ var init_dev_store = __esm({
29196
29372
  }
29197
29373
  static async open(file) {
29198
29374
  const store = new _FileChatSessionStore(file);
29199
- if (fs4.existsSync(file)) {
29200
- const snap = JSON.parse(fs4.readFileSync(file, "utf8"));
29375
+ if (fs5.existsSync(file)) {
29376
+ const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
29201
29377
  for (const s2 of snap.sessions ?? []) store.sessions.set(s2.id, s2);
29202
29378
  for (const [sid, list] of Object.entries(snap.messages ?? {})) store.messages.set(sid, list);
29203
29379
  for (const [sid, ids] of Object.entries(snap.sessionWorkOrders ?? {})) store.sessionWorkOrders.set(sid, new Set(ids));
29204
29380
  } else {
29205
- fs4.mkdirSync(path3.dirname(file), { recursive: true });
29206
- fs4.writeFileSync(file, JSON.stringify({ sessions: [], messages: {}, sessionWorkOrders: {} }, null, 2));
29381
+ fs5.mkdirSync(path4.dirname(file), { recursive: true });
29382
+ fs5.writeFileSync(file, JSON.stringify({ sessions: [], messages: {}, sessionWorkOrders: {} }, null, 2));
29207
29383
  }
29208
29384
  return store;
29209
29385
  }
@@ -29238,19 +29414,19 @@ var init_dev_store = __esm({
29238
29414
  messages: Object.fromEntries(this.messages),
29239
29415
  sessionWorkOrders: Object.fromEntries([...this.sessionWorkOrders].map(([k2, v2]) => [k2, [...v2]]))
29240
29416
  };
29241
- fs4.writeFileSync(this.file, JSON.stringify(snap, null, 2));
29417
+ fs5.writeFileSync(this.file, JSON.stringify(snap, null, 2));
29242
29418
  }
29243
29419
  };
29244
29420
  }
29245
29421
  });
29246
29422
 
29247
29423
  // ../server/src/control-plane-file-store.ts
29248
- var fs5, path4, MUTATORS2, FileControlPlaneStore;
29424
+ var fs6, path5, MUTATORS2, FileControlPlaneStore;
29249
29425
  var init_control_plane_file_store = __esm({
29250
29426
  "../server/src/control-plane-file-store.ts"() {
29251
29427
  "use strict";
29252
- fs5 = __toESM(require("node:fs"), 1);
29253
- path4 = __toESM(require("node:path"), 1);
29428
+ fs6 = __toESM(require("node:fs"), 1);
29429
+ path5 = __toESM(require("node:path"), 1);
29254
29430
  init_src3();
29255
29431
  MUTATORS2 = [
29256
29432
  "createCompany",
@@ -29278,15 +29454,15 @@ var init_control_plane_file_store = __esm({
29278
29454
  }
29279
29455
  static async open(file) {
29280
29456
  const store = new _FileControlPlaneStore(file);
29281
- if (fs5.existsSync(file)) {
29282
- const snap = JSON.parse(fs5.readFileSync(file, "utf8"));
29457
+ if (fs6.existsSync(file)) {
29458
+ const snap = JSON.parse(fs6.readFileSync(file, "utf8"));
29283
29459
  for (const c of snap.companies ?? []) await MemoryControlPlaneStore.prototype.createCompany.call(store, c);
29284
29460
  for (const m2 of snap.members ?? []) await MemoryControlPlaneStore.prototype.upsertMember.call(store, m2);
29285
29461
  for (const inv of snap.invitations ?? []) await MemoryControlPlaneStore.prototype.createInvitation.call(store, inv);
29286
29462
  for (const a of snap.accounts ?? []) await MemoryControlPlaneStore.prototype.upsertAccount.call(store, a);
29287
29463
  for (const e of snap.accountSecrets ?? []) store.accountSecrets.set(e.accountId, { ...e.secret });
29288
29464
  } else {
29289
- fs5.mkdirSync(path4.dirname(file), { recursive: true });
29465
+ fs6.mkdirSync(path5.dirname(file), { recursive: true });
29290
29466
  }
29291
29467
  return store;
29292
29468
  }
@@ -29307,7 +29483,7 @@ var init_control_plane_file_store = __esm({
29307
29483
  accounts,
29308
29484
  accountSecrets
29309
29485
  };
29310
- fs5.writeFileSync(this.file, JSON.stringify(snap, null, 2));
29486
+ fs6.writeFileSync(this.file, JSON.stringify(snap, null, 2));
29311
29487
  }
29312
29488
  };
29313
29489
  }
@@ -29666,8 +29842,8 @@ var init_recovery_plan = __esm({
29666
29842
 
29667
29843
  // ../server/src/auth/crypto.ts
29668
29844
  function hashPassword(password) {
29669
- const salt = (0, import_node_crypto6.randomBytes)(16);
29670
- const dk = (0, import_node_crypto6.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
29845
+ const salt = (0, import_node_crypto5.randomBytes)(16);
29846
+ const dk = (0, import_node_crypto5.scryptSync)(password, salt, SCRYPT_KEYLEN, { N: SCRYPT_N, maxmem: 64 * 1024 * 1024 });
29671
29847
  return `scrypt$${SCRYPT_N}$${salt.toString("base64url")}$${dk.toString("base64url")}`;
29672
29848
  }
29673
29849
  function verifyPassword(password, stored) {
@@ -29684,8 +29860,8 @@ function verifyPassword(password, stored) {
29684
29860
  return false;
29685
29861
  }
29686
29862
  if (expected.length === 0) return false;
29687
- const dk = (0, import_node_crypto6.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
29688
- return dk.length === expected.length && (0, import_node_crypto6.timingSafeEqual)(dk, expected);
29863
+ const dk = (0, import_node_crypto5.scryptSync)(password, salt, expected.length, { N, maxmem: 64 * 1024 * 1024 });
29864
+ return dk.length === expected.length && (0, import_node_crypto5.timingSafeEqual)(dk, expected);
29689
29865
  }
29690
29866
  function b64urlJson(value) {
29691
29867
  return Buffer.from(JSON.stringify(value)).toString("base64url");
@@ -29693,17 +29869,17 @@ function b64urlJson(value) {
29693
29869
  function signSession(claims, secret) {
29694
29870
  const head = b64urlJson({ alg: "HS256", typ: "JWT" });
29695
29871
  const body = b64urlJson(claims);
29696
- const sig = (0, import_node_crypto6.createHmac)("sha256", secret).update(`${head}.${body}`).digest("base64url");
29872
+ const sig = (0, import_node_crypto5.createHmac)("sha256", secret).update(`${head}.${body}`).digest("base64url");
29697
29873
  return `${head}.${body}.${sig}`;
29698
29874
  }
29699
29875
  function verifySession(token, secret, nowMs) {
29700
29876
  const parts = token.split(".");
29701
29877
  if (parts.length !== 3) return null;
29702
29878
  const [head, body, sig] = parts;
29703
- const expected = (0, import_node_crypto6.createHmac)("sha256", secret).update(`${head}.${body}`).digest("base64url");
29879
+ const expected = (0, import_node_crypto5.createHmac)("sha256", secret).update(`${head}.${body}`).digest("base64url");
29704
29880
  const got = Buffer.from(sig);
29705
29881
  const exp = Buffer.from(expected);
29706
- if (got.length !== exp.length || !(0, import_node_crypto6.timingSafeEqual)(got, exp)) return null;
29882
+ if (got.length !== exp.length || !(0, import_node_crypto5.timingSafeEqual)(got, exp)) return null;
29707
29883
  let claims;
29708
29884
  try {
29709
29885
  claims = JSON.parse(Buffer.from(body, "base64url").toString("utf8"));
@@ -29715,21 +29891,21 @@ function verifySession(token, secret, nowMs) {
29715
29891
  return claims;
29716
29892
  }
29717
29893
  function generateCode() {
29718
- return String((0, import_node_crypto6.randomInt)(0, 1e6)).padStart(6, "0");
29894
+ return String((0, import_node_crypto5.randomInt)(0, 1e6)).padStart(6, "0");
29719
29895
  }
29720
29896
  function hashCode(code, secret) {
29721
- return (0, import_node_crypto6.createHmac)("sha256", secret).update(`code:${code}`).digest("base64url");
29897
+ return (0, import_node_crypto5.createHmac)("sha256", secret).update(`code:${code}`).digest("base64url");
29722
29898
  }
29723
29899
  function safeEqualHash(a, b2) {
29724
29900
  const ba = Buffer.from(a);
29725
29901
  const bb = Buffer.from(b2);
29726
- return ba.length === bb.length && (0, import_node_crypto6.timingSafeEqual)(ba, bb);
29902
+ return ba.length === bb.length && (0, import_node_crypto5.timingSafeEqual)(ba, bb);
29727
29903
  }
29728
- var import_node_crypto6, SCRYPT_N, SCRYPT_KEYLEN;
29904
+ var import_node_crypto5, SCRYPT_N, SCRYPT_KEYLEN;
29729
29905
  var init_crypto = __esm({
29730
29906
  "../server/src/auth/crypto.ts"() {
29731
29907
  "use strict";
29732
- import_node_crypto6 = require("node:crypto");
29908
+ import_node_crypto5 = require("node:crypto");
29733
29909
  SCRYPT_N = 16384;
29734
29910
  SCRYPT_KEYLEN = 32;
29735
29911
  }
@@ -29737,11 +29913,11 @@ var init_crypto = __esm({
29737
29913
 
29738
29914
  // ../server/src/file-engine.ts
29739
29915
  async function openFileEngine(dir, seed = {}) {
29740
- fs6.mkdirSync(dir, { recursive: true });
29741
- const oplog = await NdjsonOplogStore.open(path5.join(dir, "oplog.ndjson"));
29742
- const blobs = new DirBlobStore(path5.join(dir, "blobs"));
29743
- const assets = new DirBlobStore(path5.join(dir, "assets"));
29744
- const registry2 = await FileRegistryStore.open(path5.join(dir, "registry-store.json"));
29916
+ fs7.mkdirSync(dir, { recursive: true });
29917
+ const oplog = await NdjsonOplogStore.open(path6.join(dir, "oplog.ndjson"));
29918
+ const blobs = new DirBlobStore(path6.join(dir, "blobs"));
29919
+ const assets = new DirBlobStore(path6.join(dir, "assets"));
29920
+ const registry2 = await FileRegistryStore.open(path6.join(dir, "registry-store.json"));
29745
29921
  const kernel = await Kernel.open(oplog, {
29746
29922
  schema: seed.schema ?? [],
29747
29923
  registry: seed.registry ?? [],
@@ -29754,12 +29930,12 @@ async function openFileEngine(dir, seed = {}) {
29754
29930
  function companyEngineDirName(companyId) {
29755
29931
  return companyId.replace(/[^A-Za-z0-9._-]/g, "_");
29756
29932
  }
29757
- var fs6, path5;
29933
+ var fs7, path6;
29758
29934
  var init_file_engine = __esm({
29759
29935
  "../server/src/file-engine.ts"() {
29760
29936
  "use strict";
29761
- fs6 = __toESM(require("node:fs"), 1);
29762
- path5 = __toESM(require("node:path"), 1);
29937
+ fs7 = __toESM(require("node:fs"), 1);
29938
+ path6 = __toESM(require("node:path"), 1);
29763
29939
  init_src2();
29764
29940
  init_dev_store();
29765
29941
  }
@@ -32013,7 +32189,7 @@ var require_websocket = __commonJS({
32013
32189
  var http2 = require("http");
32014
32190
  var net = require("net");
32015
32191
  var tls = require("tls");
32016
- var { randomBytes: randomBytes5, createHash: createHash12 } = require("crypto");
32192
+ var { randomBytes: randomBytes5, createHash: createHash11 } = require("crypto");
32017
32193
  var { Duplex, Readable } = require("stream");
32018
32194
  var { URL: URL2 } = require("url");
32019
32195
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -32681,7 +32857,7 @@ var require_websocket = __commonJS({
32681
32857
  abortHandshake(websocket, socket, "Invalid Upgrade header");
32682
32858
  return;
32683
32859
  }
32684
- const digest = createHash12("sha1").update(key + GUID).digest("base64");
32860
+ const digest = createHash11("sha1").update(key + GUID).digest("base64");
32685
32861
  if (res.headers["sec-websocket-accept"] !== digest) {
32686
32862
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
32687
32863
  return;
@@ -33050,7 +33226,7 @@ var require_websocket_server = __commonJS({
33050
33226
  var EventEmitter = require("events");
33051
33227
  var http2 = require("http");
33052
33228
  var { Duplex } = require("stream");
33053
- var { createHash: createHash12 } = require("crypto");
33229
+ var { createHash: createHash11 } = require("crypto");
33054
33230
  var extension2 = require_extension();
33055
33231
  var PerMessageDeflate2 = require_permessage_deflate();
33056
33232
  var subprotocol2 = require_subprotocol();
@@ -33357,7 +33533,7 @@ var require_websocket_server = __commonJS({
33357
33533
  );
33358
33534
  }
33359
33535
  if (this._state > RUNNING) return abortHandshake(socket, 503);
33360
- const digest = createHash12("sha1").update(key + GUID).digest("base64");
33536
+ const digest = createHash11("sha1").update(key + GUID).digest("base64");
33361
33537
  const headers = [
33362
33538
  "HTTP/1.1 101 Switching Protocols",
33363
33539
  "Upgrade: websocket",
@@ -33501,12 +33677,12 @@ var init_daemon_hub = __esm({
33501
33677
  this.disconnectListeners.add(cb);
33502
33678
  return () => this.disconnectListeners.delete(cb);
33503
33679
  }
33504
- constructor(server, path20 = "/daemon/ws", resolveNode, opts = {}) {
33680
+ constructor(server, path19 = "/daemon/ws", resolveNode, opts = {}) {
33505
33681
  this.pingIntervalMs = opts.pingIntervalMs ?? 2e4;
33506
33682
  this.silenceTimeoutMs = opts.silenceTimeoutMs ?? 6e4;
33507
33683
  this.wss = new import_websocket_server.default({
33508
33684
  server,
33509
- path: path20,
33685
+ path: path19,
33510
33686
  ...resolveNode ? {
33511
33687
  verifyClient: (info, cb) => {
33512
33688
  const authHeader = info.req.headers.authorization ?? "";
@@ -33688,11 +33864,11 @@ async function fetchGitHubApi(url) {
33688
33864
  async function fetchFromClawHub(sourceUrl) {
33689
33865
  const parsed = new URL(sourceUrl);
33690
33866
  const parts = parsed.pathname.replace(/^\//, "").split("/").filter(Boolean);
33691
- const slug6 = parts[parts.length - 1];
33692
- if (!slug6) throw new Error(`Cannot extract ClawHub slug from URL: ${sourceUrl}`);
33867
+ const slug4 = parts[parts.length - 1];
33868
+ if (!slug4) throw new Error(`Cannot extract ClawHub slug from URL: ${sourceUrl}`);
33693
33869
  const apiBase = "https://clawhub.ai/api/v1";
33694
- const meta = await fetch(`${apiBase}/skills/${encodeURIComponent(slug6)}`).then((r) => {
33695
- if (r.status === 404) throw new Error(`Skill not found on ClawHub: ${slug6}`);
33870
+ const meta = await fetch(`${apiBase}/skills/${encodeURIComponent(slug4)}`).then((r) => {
33871
+ if (r.status === 404) throw new Error(`Skill not found on ClawHub: ${slug4}`);
33696
33872
  if (!r.ok) throw new Error(`ClawHub returned ${r.status}`);
33697
33873
  return r.json();
33698
33874
  });
@@ -33700,13 +33876,13 @@ async function fetchFromClawHub(sourceUrl) {
33700
33876
  let latestVersion = (chSkill.tags?.["latest"] ?? meta.latestVersion?.version) || "";
33701
33877
  let filePaths = [];
33702
33878
  if (latestVersion) {
33703
- const vUrl = `${apiBase}/skills/${encodeURIComponent(slug6)}/versions/${encodeURIComponent(latestVersion)}`;
33879
+ const vUrl = `${apiBase}/skills/${encodeURIComponent(slug4)}/versions/${encodeURIComponent(latestVersion)}`;
33704
33880
  const vMeta = await fetch(vUrl).then((r) => r.ok ? r.json() : null);
33705
33881
  if (vMeta) filePaths = vMeta.version.files.map((f2) => f2.path);
33706
33882
  }
33707
33883
  const bundle = new Bundle();
33708
33884
  for (const fp of filePaths) {
33709
- let fileUrl = `${apiBase}/skills/${encodeURIComponent(slug6)}/file?path=${encodeURIComponent(fp)}`;
33885
+ let fileUrl = `${apiBase}/skills/${encodeURIComponent(slug4)}/file?path=${encodeURIComponent(fp)}`;
33710
33886
  if (latestVersion) fileUrl += `&version=${encodeURIComponent(latestVersion)}`;
33711
33887
  try {
33712
33888
  const content = await fetchText(fileUrl);
@@ -33717,11 +33893,11 @@ async function fetchFromClawHub(sourceUrl) {
33717
33893
  console.warn(`[skill-fetcher] ClawHub: skipping ${fp}: ${err}`);
33718
33894
  }
33719
33895
  }
33720
- if (!bundle.files["SKILL.md"]) throw new Error(`ClawHub: SKILL.md missing for ${slug6}`);
33896
+ if (!bundle.files["SKILL.md"]) throw new Error(`ClawHub: SKILL.md missing for ${slug4}`);
33721
33897
  const { name, description } = parseSkillFrontmatter(bundle.files["SKILL.md"]);
33722
33898
  return {
33723
- id: `claw-${slug6.replace(/[^a-z0-9-]/g, "-")}`,
33724
- name: name || chSkill.displayName || slug6,
33899
+ id: `claw-${slug4.replace(/[^a-z0-9-]/g, "-")}`,
33900
+ name: name || chSkill.displayName || slug4,
33725
33901
  description: description || chSkill.summary || "",
33726
33902
  files: bundle.files
33727
33903
  };
@@ -33861,13 +34037,13 @@ var init_skill_fetcher = __esm({
33861
34037
  files = {};
33862
34038
  totalBytes = 0;
33863
34039
  fileCount = 0;
33864
- add(path20, content) {
34040
+ add(path19, content) {
33865
34041
  const bytes = new TextEncoder().encode(content).length;
33866
34042
  if (this.fileCount >= MAX_FILE_COUNT)
33867
34043
  throw new Error(`Import bundle exceeds ${MAX_FILE_COUNT} file limit`);
33868
34044
  if (this.totalBytes + bytes > MAX_TOTAL_BYTES)
33869
34045
  throw new Error(`Import bundle exceeds ${MAX_TOTAL_BYTES} byte limit`);
33870
- this.files[path20] = content;
34046
+ this.files[path19] = content;
33871
34047
  this.totalBytes += bytes;
33872
34048
  this.fileCount++;
33873
34049
  }
@@ -33884,13 +34060,13 @@ function variableKeyFromEnv(env = process.env) {
33884
34060
  return buf;
33885
34061
  }
33886
34062
  if (env.NODE_ENV === "production") throw new Error("OASIS_VAR_KEY is required in production");
33887
- return (0, import_node_crypto7.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
34063
+ return (0, import_node_crypto6.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
33888
34064
  }
33889
- var import_node_crypto7, REDACTED_MARKER, ActorsService, mask, changedKeys;
34065
+ var import_node_crypto6, REDACTED_MARKER, ActorsService, mask, changedKeys;
33890
34066
  var init_service2 = __esm({
33891
34067
  "../server/src/domains/actors/service.ts"() {
33892
34068
  "use strict";
33893
- import_node_crypto7 = require("node:crypto");
34069
+ import_node_crypto6 = require("node:crypto");
33894
34070
  init_skill_fetcher();
33895
34071
  init_identity();
33896
34072
  init_feishu_oauth();
@@ -34136,7 +34312,7 @@ ${input.description}
34136
34312
  };
34137
34313
  await this.opts.store.putInstalledSkill(installed);
34138
34314
  const skillFiles = Object.entries(fetched.files).map(
34139
- ([path20, content]) => this.buildSkillFile(id, path20, content, now)
34315
+ ([path19, content]) => this.buildSkillFile(id, path19, content, now)
34140
34316
  );
34141
34317
  await this.opts.store.putSkillFiles(id, skillFiles);
34142
34318
  await this.audit({ kind: "skill_install", actorId: by, by, at: now, detail: { skillId: id, source: input.sourceKind, sourceUrl } });
@@ -34171,7 +34347,7 @@ ${input.description}
34171
34347
  connectorId
34172
34348
  });
34173
34349
  const skillFiles = Object.entries(entry.files).map(
34174
- ([path20, content]) => this.buildSkillFile(id, path20, content, now)
34350
+ ([path19, content]) => this.buildSkillFile(id, path19, content, now)
34175
34351
  );
34176
34352
  await this.opts.store.putSkillFiles(id, skillFiles);
34177
34353
  }
@@ -34189,25 +34365,25 @@ ${input.description}
34189
34365
  * 构造 SkillFile:正文内联进 content(决策 0036);blobHash/size 计算为 content 的 sha256
34190
34366
  * 与字节数,仅作元数据/审计(不再有读取方,正文直接从 content 出)。
34191
34367
  */
34192
- buildSkillFile(skillId, path20, content, now) {
34368
+ buildSkillFile(skillId, path19, content, now) {
34193
34369
  const bytes = new TextEncoder().encode(content);
34194
- const blobHash = (0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex");
34195
- return { skillId, path: path20, content, blobHash, size: bytes.length, updatedAt: now };
34370
+ const blobHash = (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
34371
+ return { skillId, path: path19, content, blobHash, size: bytes.length, updatedAt: now };
34196
34372
  }
34197
34373
  /**
34198
34374
  * 更新或新建技能的单个文件。
34199
34375
  * 正文内联进 skill_files(决策 0036),更新文件索引,但**不**改写技能的 name/description——
34200
34376
  * 如果修改的是 SKILL.md,调用方应另外调用 updateInstalledSkill 同步 frontmatter。
34201
34377
  */
34202
- async putSkillFile(skillId, path20, content) {
34378
+ async putSkillFile(skillId, path19, content) {
34203
34379
  const cur = (await this.opts.store.listInstalledSkills()).find((x2) => x2.id === skillId);
34204
34380
  if (!cur) throw new Error(`\u672A\u5B89\u88C5\u8BE5\u6280\u80FD\uFF1A${skillId}`);
34205
34381
  const now = this.now();
34206
- const file = this.buildSkillFile(skillId, path20, content, now);
34382
+ const file = this.buildSkillFile(skillId, path19, content, now);
34207
34383
  const existing = await this.opts.store.listSkillFiles(skillId);
34208
- const next = [...existing.filter((f2) => f2.path !== path20), file];
34384
+ const next = [...existing.filter((f2) => f2.path !== path19), file];
34209
34385
  await this.opts.store.putSkillFiles(skillId, next);
34210
- if (path20 === "SKILL.md") {
34386
+ if (path19 === "SKILL.md") {
34211
34387
  const { name, description } = parseSkillFrontmatter(content);
34212
34388
  if (name || description) {
34213
34389
  await this.opts.store.putInstalledSkill({
@@ -34223,11 +34399,11 @@ ${input.description}
34223
34399
  * 删除技能的单个支撑文件(SKILL.md 主文档受保护,调用方应先拦截)。
34224
34400
  * 单文件删除=读现有清单→剔除该 path→整体回写(putSkillFiles 是 replace-all 语义);blob 残留由 GC 回收。
34225
34401
  */
34226
- async deleteSkillFile(skillId, path20) {
34402
+ async deleteSkillFile(skillId, path19) {
34227
34403
  const cur = (await this.opts.store.listInstalledSkills()).find((x2) => x2.id === skillId);
34228
34404
  if (!cur) throw new Error(`\u672A\u5B89\u88C5\u8BE5\u6280\u80FD\uFF1A${skillId}`);
34229
34405
  const existing = await this.opts.store.listSkillFiles(skillId);
34230
- const next = existing.filter((f2) => f2.path !== path20);
34406
+ const next = existing.filter((f2) => f2.path !== path19);
34231
34407
  if (next.length === existing.length) return;
34232
34408
  await this.opts.store.putSkillFiles(skillId, next);
34233
34409
  }
@@ -34525,15 +34701,15 @@ ${input.description}
34525
34701
  return env;
34526
34702
  }
34527
34703
  encrypt(plain) {
34528
- const iv = (0, import_node_crypto7.randomBytes)(12);
34529
- const cipher = (0, import_node_crypto7.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
34704
+ const iv = (0, import_node_crypto6.randomBytes)(12);
34705
+ const cipher = (0, import_node_crypto6.createCipheriv)("aes-256-gcm", this.opts.variableKey, iv);
34530
34706
  const enc4 = Buffer.concat([cipher.update(plain, "utf8"), cipher.final()]);
34531
34707
  return [iv.toString("base64"), cipher.getAuthTag().toString("base64"), enc4.toString("base64")].join(".");
34532
34708
  }
34533
34709
  decrypt(packed) {
34534
34710
  const [iv, tag, data] = packed.split(".");
34535
34711
  if (!iv || !tag || typeof data !== "string") throw new Error("malformed ciphertext");
34536
- const decipher = (0, import_node_crypto7.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
34712
+ const decipher = (0, import_node_crypto6.createDecipheriv)("aes-256-gcm", this.opts.variableKey, Buffer.from(iv, "base64"));
34537
34713
  decipher.setAuthTag(Buffer.from(tag, "base64"));
34538
34714
  return Buffer.concat([decipher.update(Buffer.from(data, "base64")), decipher.final()]).toString("utf8");
34539
34715
  }
@@ -35067,7 +35243,7 @@ async function listSkillMetadataForActor(args) {
35067
35243
  usedDirs.add(dir);
35068
35244
  const sorted = [...metas].sort((a, b2) => a.path.localeCompare(b2.path));
35069
35245
  let latest = "1970-01-01T00:00:00.000Z";
35070
- const hasher = (0, import_node_crypto8.createHash)("sha256");
35246
+ const hasher = (0, import_node_crypto7.createHash)("sha256");
35071
35247
  for (const m2 of sorted) {
35072
35248
  if (m2.updatedAt > latest) latest = m2.updatedAt;
35073
35249
  hasher.update(m2.path);
@@ -35090,11 +35266,11 @@ async function listSkillMetadataForActor(args) {
35090
35266
  const dir = sanitizeSkillDir(b2.name || b2.id);
35091
35267
  if (usedDirs.has(dir)) continue;
35092
35268
  usedDirs.add(dir);
35093
- const hasher = (0, import_node_crypto8.createHash)("sha256");
35269
+ const hasher = (0, import_node_crypto7.createHash)("sha256");
35094
35270
  for (const p2 of paths) {
35095
35271
  hasher.update(p2);
35096
35272
  hasher.update("\0");
35097
- hasher.update((0, import_node_crypto8.createHash)("sha256").update(b2.files[p2]).digest("hex"));
35273
+ hasher.update((0, import_node_crypto7.createHash)("sha256").update(b2.files[p2]).digest("hex"));
35098
35274
  hasher.update("\0");
35099
35275
  }
35100
35276
  out.push({
@@ -35110,11 +35286,11 @@ async function listSkillMetadataForActor(args) {
35110
35286
  return out;
35111
35287
  }
35112
35288
  function builtinSkillToFiles(b2) {
35113
- return Object.entries(b2.files ?? {}).map(([path20, content]) => ({
35289
+ return Object.entries(b2.files ?? {}).map(([path19, content]) => ({
35114
35290
  skillId: `builtin:${b2.id}`,
35115
- path: path20,
35291
+ path: path19,
35116
35292
  content,
35117
- blobHash: (0, import_node_crypto8.createHash)("sha256").update(content).digest("hex"),
35293
+ blobHash: (0, import_node_crypto7.createHash)("sha256").update(content).digest("hex"),
35118
35294
  size: Buffer.byteLength(content, "utf8"),
35119
35295
  updatedAt: "1970-01-01T00:00:00.000Z"
35120
35296
  }));
@@ -35124,6 +35300,10 @@ function skillsDirForRuntime(runtimeKind) {
35124
35300
  case "claude":
35125
35301
  case "claude-code":
35126
35302
  return ".claude/skills";
35303
+ case "codex":
35304
+ return ".codex/skills";
35305
+ case "cursor":
35306
+ return ".cursor/skills";
35127
35307
  default:
35128
35308
  return ".agent_context/skills";
35129
35309
  }
@@ -35158,11 +35338,11 @@ async function materializeSkillFiles(args) {
35158
35338
  }
35159
35339
  return out;
35160
35340
  }
35161
- var import_node_crypto8;
35341
+ var import_node_crypto7;
35162
35342
  var init_skill_materializer = __esm({
35163
35343
  "../server/src/domains/actors/skill-materializer.ts"() {
35164
35344
  "use strict";
35165
- import_node_crypto8 = require("node:crypto");
35345
+ import_node_crypto7 = require("node:crypto");
35166
35346
  }
35167
35347
  });
35168
35348
 
@@ -35652,7 +35832,7 @@ function createActorsDomain(opts) {
35652
35832
  ...kernel !== void 0 ? { onRolesChanged: (a, r) => kernel.setActorRoles(a, r) } : {},
35653
35833
  audit: async (entry) => {
35654
35834
  await opts.audit?.({
35655
- id: `reg_${(0, import_node_crypto9.randomUUID)()}`,
35835
+ id: `reg_${(0, import_node_crypto8.randomUUID)()}`,
35656
35836
  actor: entry.by,
35657
35837
  kind: "registry_change",
35658
35838
  target: entry.actorId,
@@ -35687,11 +35867,11 @@ function createActorsDomain(opts) {
35687
35867
  register: actorsDomain({ resolveCtx, ...opts.trace ? { trace: opts.trace } : {}, ...opts.listBuiltinSkills ? { listBuiltinSkills: opts.listBuiltinSkills } : {}, ...opts.getBuiltinSkills ? { getBuiltinSkills: opts.getBuiltinSkills } : {} })
35688
35868
  };
35689
35869
  }
35690
- var import_node_crypto9;
35870
+ var import_node_crypto8;
35691
35871
  var init_actors = __esm({
35692
35872
  "../server/src/domains/actors/index.ts"() {
35693
35873
  "use strict";
35694
- import_node_crypto9 = require("node:crypto");
35874
+ import_node_crypto8 = require("node:crypto");
35695
35875
  init_service2();
35696
35876
  init_routes();
35697
35877
  init_service2();
@@ -36524,11 +36704,11 @@ var init_projects = __esm({
36524
36704
  });
36525
36705
 
36526
36706
  // ../server/src/domains/companies/service.ts
36527
- var import_node_crypto10, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, SLUG_RE, CompanyError, CompaniesService;
36707
+ var import_node_crypto9, ROLES, INVITABLE_ROLES, INVITATION_TTL_MS, SLUG_RE, CompanyError, CompaniesService;
36528
36708
  var init_service3 = __esm({
36529
36709
  "../server/src/domains/companies/service.ts"() {
36530
36710
  "use strict";
36531
- import_node_crypto10 = require("node:crypto");
36711
+ import_node_crypto9 = require("node:crypto");
36532
36712
  ROLES = ["owner", "admin", "member"];
36533
36713
  INVITABLE_ROLES = ["admin", "member"];
36534
36714
  INVITATION_TTL_MS = 7 * 24 * 60 * 60 * 1e3;
@@ -36580,7 +36760,7 @@ var init_service3 = __esm({
36580
36760
  const existing = await this.store.getAccountByEmail(normalized);
36581
36761
  if (existing) return existing;
36582
36762
  const account = {
36583
- id: `actor:human:${(0, import_node_crypto10.randomUUID)()}`,
36763
+ id: `actor:human:${(0, import_node_crypto9.randomUUID)()}`,
36584
36764
  email: normalized,
36585
36765
  name: name ?? normalized,
36586
36766
  status: "active"
@@ -36625,14 +36805,14 @@ var init_service3 = __esm({
36625
36805
  }
36626
36806
  /** 新建公司:校验 slug、生成 id=company:<slug>、把创建者设为 owner。 */
36627
36807
  async create(input, creatorAccountId) {
36628
- const slug6 = input.slug?.trim() ?? "";
36629
- if (!SLUG_RE.test(slug6)) throw new CompanyError(400, "BAD_SLUG", "slug \u987B\u4E3A URL \u5B89\u5168\u7684\u5C0F\u5199\u4E32\uFF08^[a-z][a-z0-9-]*$\uFF09");
36808
+ const slug4 = input.slug?.trim() ?? "";
36809
+ if (!SLUG_RE.test(slug4)) throw new CompanyError(400, "BAD_SLUG", "slug \u987B\u4E3A URL \u5B89\u5168\u7684\u5C0F\u5199\u4E32\uFF08^[a-z][a-z0-9-]*$\uFF09");
36630
36810
  const name = input.name?.trim() ?? "";
36631
36811
  if (!name) throw new CompanyError(400, "BAD_REQUEST", "\u7F3A\u5C11 name");
36632
- if (await this.store.getCompanyBySlug(slug6)) throw new CompanyError(409, "SLUG_TAKEN", `slug \u5DF2\u88AB\u5360\u7528\uFF1A${slug6}`);
36812
+ if (await this.store.getCompanyBySlug(slug4)) throw new CompanyError(409, "SLUG_TAKEN", `slug \u5DF2\u88AB\u5360\u7528\uFF1A${slug4}`);
36633
36813
  const company = {
36634
- id: `company:${slug6}`,
36635
- slug: slug6,
36814
+ id: `company:${slug4}`,
36815
+ slug: slug4,
36636
36816
  name,
36637
36817
  status: "active",
36638
36818
  createdAt: this.now(),
@@ -36704,7 +36884,7 @@ var init_service3 = __esm({
36704
36884
  }
36705
36885
  const nowMs = Date.parse(this.now());
36706
36886
  const invitation = {
36707
- id: `invitation:${(0, import_node_crypto10.randomUUID)()}`,
36887
+ id: `invitation:${(0, import_node_crypto9.randomUUID)()}`,
36708
36888
  companyId,
36709
36889
  email: mail,
36710
36890
  role,
@@ -36862,9 +37042,9 @@ var init_routes3 = __esm({
36862
37042
 
36863
37043
  // ../server/src/domains/companies/migrate.ts
36864
37044
  function resolveDefaultCompanyConfig(env = process.env) {
36865
- const slug6 = env["OASIS_DEFAULT_COMPANY_SLUG"]?.trim() || "oasis";
37045
+ const slug4 = env["OASIS_DEFAULT_COMPANY_SLUG"]?.trim() || "oasis";
36866
37046
  const name = env["OASIS_DEFAULT_COMPANY_NAME"]?.trim() || "Oasis \u603B\u90E8";
36867
- return { id: `company:${slug6}`, slug: slug6, name };
37047
+ return { id: `company:${slug4}`, slug: slug4, name };
36868
37048
  }
36869
37049
  async function migrateDefaultCompany(store, actors, opts = {}) {
36870
37050
  const now = opts.now ?? (() => (/* @__PURE__ */ new Date()).toISOString());
@@ -37188,7 +37368,7 @@ var init_sender = __esm({
37188
37368
  function deriveBoardKey(artifactId) {
37189
37369
  const tail = artifactId.split(":").pop() ?? artifactId;
37190
37370
  const ascii = tail.replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 24);
37191
- const sha8 = (0, import_node_crypto11.createHash)("sha256").update(artifactId).digest("hex").slice(0, 8);
37371
+ const sha8 = (0, import_node_crypto10.createHash)("sha256").update(artifactId).digest("hex").slice(0, 8);
37192
37372
  return ascii ? `od-${ascii}-${sha8}` : `od-${sha8}`;
37193
37373
  }
37194
37374
  async function odApi(base, fetchImpl, method, p2, body) {
@@ -37221,13 +37401,13 @@ async function ensureProject(base, fetchImpl, boardKey, title) {
37221
37401
  }
37222
37402
  function materializeContext(resolvedDir, files) {
37223
37403
  if (!resolvedDir) return;
37224
- fs7.mkdirSync(resolvedDir, { recursive: true });
37225
- const root = path6.join(resolvedDir, "task-context");
37226
- fs7.rmSync(root, { recursive: true, force: true });
37404
+ fs8.mkdirSync(resolvedDir, { recursive: true });
37405
+ const root = path7.join(resolvedDir, "task-context");
37406
+ fs8.rmSync(root, { recursive: true, force: true });
37227
37407
  for (const [rel, content] of Object.entries(files)) {
37228
- const f2 = path6.join(root, rel);
37229
- fs7.mkdirSync(path6.dirname(f2), { recursive: true });
37230
- fs7.writeFileSync(f2, content);
37408
+ const f2 = path7.join(root, rel);
37409
+ fs8.mkdirSync(path7.dirname(f2), { recursive: true });
37410
+ fs8.writeFileSync(f2, content);
37231
37411
  }
37232
37412
  }
37233
37413
  async function startDesignRun(base, fetchImpl, args) {
@@ -37235,8 +37415,8 @@ async function startDesignRun(base, fetchImpl, args) {
37235
37415
  agentId: args.agentId,
37236
37416
  projectId: args.boardKey,
37237
37417
  conversationId: args.conversationId,
37238
- assistantMessageId: (0, import_node_crypto11.randomUUID)(),
37239
- clientRequestId: (0, import_node_crypto11.randomUUID)(),
37418
+ assistantMessageId: (0, import_node_crypto10.randomUUID)(),
37419
+ clientRequestId: (0, import_node_crypto10.randomUUID)(),
37240
37420
  message: args.message,
37241
37421
  systemPrompt: args.systemPrompt
37242
37422
  });
@@ -37289,23 +37469,23 @@ async function harvestBoard(base, fetchImpl, publicBase, workRoot, boardKey, run
37289
37469
  const htmls = (listing.files ?? []).filter((f2) => f2.kind === "html" && !f2.path.startsWith("task-context/")).filter((f2) => (f2.artifactManifest?.status ?? "complete") === "complete").sort((a, b2) => (b2.mtime ?? 0) - (a.mtime ?? 0));
37290
37470
  const entry = htmls[0]?.path;
37291
37471
  if (!entry) throw new Error("\u753B\u677F\u9879\u76EE\u65E0\u5DF2\u5B8C\u6210\u7684 HTML \u5165\u53E3\u7A3F\u2014\u2014\u8BBE\u8BA1\u4F1A\u8BDD\u672A\u4EA7\u51FA\u53EF\u4EA4\u4ED8\u754C\u9762");
37292
- const dir = fs7.mkdtempSync(path6.join(workRoot, "od-deliverable-"));
37472
+ const dir = fs8.mkdtempSync(path7.join(workRoot, "od-deliverable-"));
37293
37473
  const fetchInline = async (rel) => {
37294
37474
  const res = await fetchImpl(`${base}/api/projects/${encodeURIComponent(boardKey)}/export/${encodeURIComponent(rel)}?inline=1`);
37295
37475
  if (!res.ok) throw new Error(`od export ${rel} \u2192 ${res.status}`);
37296
37476
  return await res.text();
37297
37477
  };
37298
- fs7.writeFileSync(path6.join(dir, "index.html"), await fetchInline(entry));
37478
+ fs8.writeFileSync(path7.join(dir, "index.html"), await fetchInline(entry));
37299
37479
  for (const f2 of listing.files ?? []) {
37300
37480
  if (f2.path.endsWith(".md") && !f2.path.includes("/")) {
37301
37481
  try {
37302
- fs7.writeFileSync(path6.join(dir, f2.path), await fetchInline(f2.path));
37482
+ fs8.writeFileSync(path7.join(dir, f2.path), await fetchInline(f2.path));
37303
37483
  } catch {
37304
37484
  }
37305
37485
  }
37306
37486
  }
37307
- fs7.writeFileSync(
37308
- path6.join(dir, "board.link"),
37487
+ fs8.writeFileSync(
37488
+ path7.join(dir, "board.link"),
37309
37489
  `${publicBase}/projects/${boardKey}
37310
37490
  \u5165\u53E3\u7A3F\uFF1A${entry}
37311
37491
  \u5FEB\u7167\u6765\u6E90 run\uFF1A${runId}
@@ -37338,14 +37518,14 @@ async function runOpenDesignSession(opts) {
37338
37518
  const { dir, entry } = await harvestBoard(opts.base, fetchImpl, opts.publicBase, workRoot, boardKey, runId);
37339
37519
  return { dir, entry, boardKey, runId };
37340
37520
  }
37341
- var import_node_crypto11, fs7, os, path6;
37521
+ var import_node_crypto10, fs8, os, path7;
37342
37522
  var init_driver = __esm({
37343
37523
  "../adapters/src/open-design/driver.ts"() {
37344
37524
  "use strict";
37345
- import_node_crypto11 = require("node:crypto");
37346
- fs7 = __toESM(require("node:fs"), 1);
37525
+ import_node_crypto10 = require("node:crypto");
37526
+ fs8 = __toESM(require("node:fs"), 1);
37347
37527
  os = __toESM(require("node:os"), 1);
37348
- path6 = __toESM(require("node:path"), 1);
37528
+ path7 = __toESM(require("node:path"), 1);
37349
37529
  }
37350
37530
  });
37351
37531
 
@@ -37471,26 +37651,26 @@ function classifyExit(result) {
37471
37651
  return void 0;
37472
37652
  }
37473
37653
  function conversationExists(sessionId) {
37474
- const configDir = process.env["CLAUDE_CONFIG_DIR"] || path7.join(os2.homedir(), ".claude");
37475
- const projectsDir = path7.join(configDir, "projects");
37654
+ const configDir = process.env["CLAUDE_CONFIG_DIR"] || path8.join(os2.homedir(), ".claude");
37655
+ const projectsDir = path8.join(configDir, "projects");
37476
37656
  const target = `${sessionId}.jsonl`;
37477
37657
  try {
37478
- for (const proj of fs8.readdirSync(projectsDir)) {
37479
- if (fs8.existsSync(path7.join(projectsDir, proj, target))) return true;
37658
+ for (const proj of fs9.readdirSync(projectsDir)) {
37659
+ if (fs9.existsSync(path8.join(projectsDir, proj, target))) return true;
37480
37660
  }
37481
37661
  } catch {
37482
37662
  }
37483
37663
  return false;
37484
37664
  }
37485
- var import_node_child_process3, import_node_crypto12, fs8, os2, path7, readline, ClaudeCodeAdapter;
37665
+ var import_node_child_process4, import_node_crypto11, fs9, os2, path8, readline, ClaudeCodeAdapter;
37486
37666
  var init_claude_code = __esm({
37487
37667
  "../adapters/src/claude-code/index.ts"() {
37488
37668
  "use strict";
37489
- import_node_child_process3 = require("node:child_process");
37490
- import_node_crypto12 = require("node:crypto");
37491
- fs8 = __toESM(require("node:fs"), 1);
37669
+ import_node_child_process4 = require("node:child_process");
37670
+ import_node_crypto11 = require("node:crypto");
37671
+ fs9 = __toESM(require("node:fs"), 1);
37492
37672
  os2 = __toESM(require("node:os"), 1);
37493
- path7 = __toESM(require("node:path"), 1);
37673
+ path8 = __toESM(require("node:path"), 1);
37494
37674
  readline = __toESM(require("node:readline"), 1);
37495
37675
  init_sync_skills();
37496
37676
  ClaudeCodeAdapter = class {
@@ -37519,10 +37699,10 @@ var init_claude_code = __esm({
37519
37699
  };
37520
37700
  }
37521
37701
  async spawn(job) {
37522
- const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
37523
- const id = `claude-${slug6}-${(0, import_node_crypto12.randomUUID)().slice(0, 8)}`;
37524
- const dir = job.runtimeSessionId ? path7.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-chat-sessions", job.runtimeSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_")) : fs8.mkdtempSync(path7.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-session-"));
37525
- fs8.mkdirSync(dir, { recursive: true });
37702
+ const slug4 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
37703
+ const id = `claude-${slug4}-${(0, import_node_crypto11.randomUUID)().slice(0, 8)}`;
37704
+ const dir = job.runtimeSessionId ? path8.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-chat-sessions", job.runtimeSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_")) : fs9.mkdtempSync(path8.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-session-"));
37705
+ fs9.mkdirSync(dir, { recursive: true });
37526
37706
  await runSyncSkills(this.opts.syncSkills, {
37527
37707
  actorId: job.actor,
37528
37708
  actorToken: job.actorToken,
@@ -37531,14 +37711,14 @@ var init_claude_code = __esm({
37531
37711
  sessionDir: dir
37532
37712
  });
37533
37713
  for (const [rel, content] of Object.entries(job.bundle.files)) {
37534
- const file = path7.join(dir, rel);
37535
- fs8.mkdirSync(path7.dirname(file), { recursive: true });
37536
- fs8.writeFileSync(file, content);
37714
+ const file = path8.join(dir, rel);
37715
+ fs9.mkdirSync(path8.dirname(file), { recursive: true });
37716
+ fs9.writeFileSync(file, content);
37537
37717
  }
37538
37718
  for (const [rel, b64] of Object.entries(job.bundle.binaryFiles ?? {})) {
37539
- const file = path7.join(dir, rel);
37540
- fs8.mkdirSync(path7.dirname(file), { recursive: true });
37541
- fs8.writeFileSync(file, Buffer.from(b64, "base64"));
37719
+ const file = path8.join(dir, rel);
37720
+ fs9.mkdirSync(path8.dirname(file), { recursive: true });
37721
+ fs9.writeFileSync(file, Buffer.from(b64, "base64"));
37542
37722
  }
37543
37723
  const prompt = job.bundle.files["TASK.md"];
37544
37724
  if (!prompt) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
@@ -37559,7 +37739,7 @@ var init_claude_code = __esm({
37559
37739
  ...this.opts.extraArgs ?? []
37560
37740
  ];
37561
37741
  const otelEnv = this.resolveOtelEnv(job, id);
37562
- const child = (0, import_node_child_process3.spawn)(this.opts.claudeBin ?? "claude", args, {
37742
+ const child = (0, import_node_child_process4.spawn)(this.opts.claudeBin ?? "claude", args, {
37563
37743
  cwd: dir,
37564
37744
  env: {
37565
37745
  // 凭证泄漏防护:剔除 pnpm/npm 脚本注入的变量——npm_lifecycle_script 等会把 serve 的启动命令
@@ -37570,7 +37750,7 @@ var init_claude_code = __esm({
37570
37750
  ...job.env,
37571
37751
  // BUG-4 缓冲:抬高单响应输出 token 上限(临时缓冲,根治靠分解)
37572
37752
  ...this.opts.maxOutputTokens ? { CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(this.opts.maxOutputTokens) } : {},
37573
- ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path7.dirname(p2)).join(path7.delimiter)}${path7.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
37753
+ ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path8.dirname(p2)).join(path8.delimiter)}${path8.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
37574
37754
  OASIS_SERVER: job.server.url,
37575
37755
  OASIS_TOKEN: job.actorToken,
37576
37756
  // OTel 遥测(默认关;resolveOtelEnv 决定开不开,runId 进 resource 属性自然归位到本次 run)。
@@ -37582,8 +37762,8 @@ var init_claude_code = __esm({
37582
37762
  });
37583
37763
  if (promptViaStdin) child.stdin.write(prompt);
37584
37764
  child.stdin.end();
37585
- let transcriptRef = path7.join(dir, "transcript.txt");
37586
- const out = fs8.createWriteStream(transcriptRef);
37765
+ let transcriptRef = path8.join(dir, "transcript.txt");
37766
+ const out = fs9.createWriteStream(transcriptRef);
37587
37767
  const telemetryCbs = [];
37588
37768
  let eventSeq = 0;
37589
37769
  let lastResult;
@@ -37669,14 +37849,14 @@ var init_claude_code = __esm({
37669
37849
  const reason = killedByUs ? "timeout" : classifyExit(lastResult);
37670
37850
  if (this.opts.cleanupWorkdir && !job.runtimeSessionId) {
37671
37851
  try {
37672
- const keepDir = path7.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-transcripts");
37673
- fs8.mkdirSync(keepDir, { recursive: true });
37674
- const kept = path7.join(keepDir, `${id}.txt`);
37852
+ const keepDir = path8.join(this.opts.workRoot ?? os2.tmpdir(), "oasis-transcripts");
37853
+ fs9.mkdirSync(keepDir, { recursive: true });
37854
+ const kept = path8.join(keepDir, `${id}.txt`);
37675
37855
  const src = transcriptRef;
37676
37856
  out.end(() => {
37677
37857
  try {
37678
- fs8.renameSync(src, kept);
37679
- fs8.rmSync(dir, { recursive: true, force: true });
37858
+ fs9.renameSync(src, kept);
37859
+ fs9.rmSync(dir, { recursive: true, force: true });
37680
37860
  } catch {
37681
37861
  }
37682
37862
  });
@@ -37872,10 +38052,20 @@ var init_resilient = __esm({
37872
38052
 
37873
38053
  // ../adapters/src/_core/skill-cache.ts
37874
38054
  function defaultCacheRoot() {
37875
- return path8.join(os3.homedir(), ".oasis", "skill-cache");
38055
+ return path9.join(os3.homedir(), ".oasis", "skill-cache");
37876
38056
  }
37877
38057
  function sessionSkillsSubdir(runtimeKind) {
37878
- return runtimeKind === "claude" || runtimeKind === "claude-code" ? ".claude/skills" : ".agent_context/skills";
38058
+ switch (runtimeKind) {
38059
+ case "claude":
38060
+ case "claude-code":
38061
+ return ".claude/skills";
38062
+ case "codex":
38063
+ return ".codex/skills";
38064
+ case "cursor":
38065
+ return ".cursor/skills";
38066
+ default:
38067
+ return ".agent_context/skills";
38068
+ }
37879
38069
  }
37880
38070
  async function syncActorSkills(opts) {
37881
38071
  const cacheRoot = opts.cacheRoot ?? defaultCacheRoot();
@@ -37883,7 +38073,7 @@ async function syncActorSkills(opts) {
37883
38073
  });
37884
38074
  const now = opts.now ?? (() => /* @__PURE__ */ new Date());
37885
38075
  const actorDir = pathForActor(cacheRoot, opts.actorId);
37886
- const manifestPath = path8.join(actorDir, "manifest.json");
38076
+ const manifestPath = path9.join(actorDir, "manifest.json");
37887
38077
  await fsp.mkdir(actorDir, { recursive: true, mode: 493 });
37888
38078
  const release = await acquireLock(cacheRoot, opts.actorId, now, log3);
37889
38079
  try {
@@ -37901,7 +38091,7 @@ async function syncActorSkills(opts) {
37901
38091
  const cloudIds = new Set(cloudMetadata.map((s2) => s2.id));
37902
38092
  for (const cloud of cloudMetadata) {
37903
38093
  const cached2 = manifest.skills[cloud.id];
37904
- const skillDir = path8.join(actorDir, cloud.dir);
38094
+ const skillDir = path9.join(actorDir, cloud.dir);
37905
38095
  const inSync = cached2 && cached2.dir === cloud.dir && cached2.contentHash === cloud.contentHash && cached2.cloudUpdatedAt === cloud.updatedAt && await dirLooksValid(skillDir, cached2.fileList);
37906
38096
  if (inSync) {
37907
38097
  skipped += 1;
@@ -37929,7 +38119,7 @@ async function syncActorSkills(opts) {
37929
38119
  for (const [id, entry] of Object.entries(manifest.skills)) {
37930
38120
  if (cloudIds.has(id)) continue;
37931
38121
  try {
37932
- await fsp.rm(path8.join(actorDir, entry.dir), { recursive: true, force: true });
38122
+ await fsp.rm(path9.join(actorDir, entry.dir), { recursive: true, force: true });
37933
38123
  } catch (err) {
37934
38124
  log3("warn", `\u5220\u9664\u5B64\u513F\u6280\u80FD\u76EE\u5F55\u5931\u8D25 ${entry.dir}`, err);
37935
38125
  }
@@ -37946,14 +38136,14 @@ async function syncActorSkills(opts) {
37946
38136
  }
37947
38137
  }
37948
38138
  function pathForActor(cacheRoot, actorId) {
37949
- return path8.join(cacheRoot, "actors", encodeURIComponent(actorId));
38139
+ return path9.join(cacheRoot, "actors", encodeURIComponent(actorId));
37950
38140
  }
37951
38141
  function lockPathFor(cacheRoot, actorId) {
37952
- return path8.join(cacheRoot, "locks", `${encodeURIComponent(actorId)}.lock`);
38142
+ return path9.join(cacheRoot, "locks", `${encodeURIComponent(actorId)}.lock`);
37953
38143
  }
37954
38144
  async function acquireLock(cacheRoot, actorId, now, log3) {
37955
38145
  const lockPath = lockPathFor(cacheRoot, actorId);
37956
- await fsp.mkdir(path8.dirname(lockPath), { recursive: true, mode: 493 });
38146
+ await fsp.mkdir(path9.dirname(lockPath), { recursive: true, mode: 493 });
37957
38147
  const started = now().getTime();
37958
38148
  while (true) {
37959
38149
  try {
@@ -38019,26 +38209,26 @@ async function readManifest2(manifestPath, actorId, log3) {
38019
38209
  };
38020
38210
  }
38021
38211
  async function writeManifest(manifestPath, manifest) {
38022
- const dir = path8.dirname(manifestPath);
38212
+ const dir = path9.dirname(manifestPath);
38023
38213
  await fsp.mkdir(dir, { recursive: true });
38024
38214
  const tmp = `${manifestPath}.${process.pid}.${Date.now()}.tmp`;
38025
38215
  await fsp.writeFile(tmp, JSON.stringify(manifest, null, 2), { mode: 420 });
38026
38216
  await fsp.rename(tmp, manifestPath);
38027
38217
  }
38028
38218
  async function materializeSkillDir(actorDir, targetDir, files, previousDir) {
38029
- const targetPath = path8.join(actorDir, targetDir);
38030
- const tmpPath = path8.join(actorDir, `${targetDir}.new.${process.pid}.${Date.now()}`);
38031
- const oldBackup = path8.join(actorDir, `${targetDir}.old.${process.pid}.${Date.now()}`);
38219
+ const targetPath = path9.join(actorDir, targetDir);
38220
+ const tmpPath = path9.join(actorDir, `${targetDir}.new.${process.pid}.${Date.now()}`);
38221
+ const oldBackup = path9.join(actorDir, `${targetDir}.old.${process.pid}.${Date.now()}`);
38032
38222
  await fsp.rm(tmpPath, { recursive: true, force: true });
38033
38223
  await fsp.mkdir(tmpPath, { recursive: true, mode: 493 });
38034
38224
  for (const f2 of files) {
38035
38225
  if (!f2.content) continue;
38036
- const dest = path8.join(tmpPath, f2.path);
38037
- const rel = path8.relative(tmpPath, dest);
38038
- if (rel.startsWith("..") || path8.isAbsolute(rel)) {
38226
+ const dest = path9.join(tmpPath, f2.path);
38227
+ const rel = path9.relative(tmpPath, dest);
38228
+ if (rel.startsWith("..") || path9.isAbsolute(rel)) {
38039
38229
  throw new Error(`SkillFile.path \u4E0D\u5408\u6CD5: ${f2.path}`);
38040
38230
  }
38041
- await fsp.mkdir(path8.dirname(dest), { recursive: true });
38231
+ await fsp.mkdir(path9.dirname(dest), { recursive: true });
38042
38232
  await fsp.writeFile(dest, f2.content, { mode: 420 });
38043
38233
  }
38044
38234
  let hadOld = false;
@@ -38052,14 +38242,14 @@ async function materializeSkillDir(actorDir, targetDir, files, previousDir) {
38052
38242
  await fsp.rename(tmpPath, targetPath);
38053
38243
  if (hadOld) await fsp.rm(oldBackup, { recursive: true, force: true });
38054
38244
  if (previousDir && previousDir !== targetDir) {
38055
- await fsp.rm(path8.join(actorDir, previousDir), { recursive: true, force: true });
38245
+ await fsp.rm(path9.join(actorDir, previousDir), { recursive: true, force: true });
38056
38246
  }
38057
38247
  }
38058
38248
  async function dirLooksValid(dir, expectFileList) {
38059
38249
  if (expectFileList.length === 0) return false;
38060
38250
  try {
38061
38251
  for (const rel of expectFileList) {
38062
- await fsp.stat(path8.join(dir, rel));
38252
+ await fsp.stat(path9.join(dir, rel));
38063
38253
  }
38064
38254
  return true;
38065
38255
  } catch {
@@ -38068,18 +38258,18 @@ async function dirLooksValid(dir, expectFileList) {
38068
38258
  }
38069
38259
  async function syncSessionSymlinks(sessionDir, runtimeKind, actorDir, manifest, log3) {
38070
38260
  const subdir = sessionSkillsSubdir(runtimeKind);
38071
- const skillsDir = path8.join(sessionDir, subdir);
38261
+ const skillsDir = path9.join(sessionDir, subdir);
38072
38262
  await fsp.mkdir(skillsDir, { recursive: true, mode: 493 });
38073
38263
  const desired = /* @__PURE__ */ new Map();
38074
38264
  for (const entry of Object.values(manifest.skills)) {
38075
- desired.set(entry.dir, path8.join(actorDir, entry.dir));
38265
+ desired.set(entry.dir, path9.join(actorDir, entry.dir));
38076
38266
  }
38077
38267
  for (const [name, target] of desired) {
38078
- const link = path8.join(skillsDir, name);
38268
+ const link = path9.join(skillsDir, name);
38079
38269
  let ok = false;
38080
38270
  try {
38081
38271
  const current = await fsp.readlink(link);
38082
- ok = path8.resolve(skillsDir, current) === target;
38272
+ ok = path9.resolve(skillsDir, current) === target;
38083
38273
  } catch {
38084
38274
  }
38085
38275
  if (!ok) {
@@ -38099,19 +38289,19 @@ async function syncSessionSymlinks(sessionDir, runtimeKind, actorDir, manifest,
38099
38289
  for (const name of entries) {
38100
38290
  if (desired.has(name)) continue;
38101
38291
  try {
38102
- await fsp.rm(path8.join(skillsDir, name), { recursive: true, force: true });
38292
+ await fsp.rm(path9.join(skillsDir, name), { recursive: true, force: true });
38103
38293
  } catch (err) {
38104
38294
  log3("warn", `\u6E05\u5B64\u513F\u5931\u8D25 ${name}`, err);
38105
38295
  }
38106
38296
  }
38107
38297
  }
38108
- var fsp, os3, path8, MANIFEST_SCHEMA_VERSION, STALE_LOCK_MS, LOCK_ACQUIRE_TIMEOUT_MS, LOCK_POLL_MS;
38298
+ var fsp, os3, path9, MANIFEST_SCHEMA_VERSION, STALE_LOCK_MS, LOCK_ACQUIRE_TIMEOUT_MS, LOCK_POLL_MS;
38109
38299
  var init_skill_cache = __esm({
38110
38300
  "../adapters/src/_core/skill-cache.ts"() {
38111
38301
  "use strict";
38112
38302
  fsp = __toESM(require("node:fs/promises"), 1);
38113
38303
  os3 = __toESM(require("node:os"), 1);
38114
- path8 = __toESM(require("node:path"), 1);
38304
+ path9 = __toESM(require("node:path"), 1);
38115
38305
  MANIFEST_SCHEMA_VERSION = 1;
38116
38306
  STALE_LOCK_MS = 6e4;
38117
38307
  LOCK_ACQUIRE_TIMEOUT_MS = 3e4;
@@ -38295,7 +38485,7 @@ async function discoverAntigravityModels(bin) {
38295
38485
  async function discoverACPModels(bin, provider, args = ["acp"]) {
38296
38486
  const child = (() => {
38297
38487
  try {
38298
- return (0, import_node_child_process4.spawn)(bin, args, { stdio: ["pipe", "pipe", "ignore"], env: { ...process.env } });
38488
+ return (0, import_node_child_process5.spawn)(bin, args, { stdio: ["pipe", "pipe", "ignore"], env: { ...process.env } });
38299
38489
  } catch {
38300
38490
  return null;
38301
38491
  }
@@ -38401,11 +38591,11 @@ function parseACPSessionNewModels(result) {
38401
38591
  async function discoverOpenclawModels(bin) {
38402
38592
  throw new Error("discoverOpenclawModels: TODO");
38403
38593
  }
38404
- var import_node_child_process4, import_node_fs2, import_node_os, import_node_path, modelCache, CACHE_TTL_MS2;
38594
+ var import_node_child_process5, import_node_fs2, import_node_os, import_node_path, modelCache, CACHE_TTL_MS2;
38405
38595
  var init_models = __esm({
38406
38596
  "../adapters/src/_core/models.ts"() {
38407
38597
  "use strict";
38408
- import_node_child_process4 = require("node:child_process");
38598
+ import_node_child_process5 = require("node:child_process");
38409
38599
  import_node_fs2 = require("node:fs");
38410
38600
  import_node_os = require("node:os");
38411
38601
  import_node_path = require("node:path");
@@ -38480,12 +38670,12 @@ function parseCodexModel(lines) {
38480
38670
  function codexSessionsRoot() {
38481
38671
  const candidates = [];
38482
38672
  const ch = process.env["CODEX_HOME"];
38483
- if (ch) candidates.push(path9.join(ch, "sessions"));
38673
+ if (ch) candidates.push(path10.join(ch, "sessions"));
38484
38674
  const home = process.env["HOME"] || os4.homedir();
38485
- if (home) candidates.push(path9.join(home, ".codex", "sessions"));
38675
+ if (home) candidates.push(path10.join(home, ".codex", "sessions"));
38486
38676
  for (const c of candidates) {
38487
38677
  try {
38488
- if (fs9.statSync(c).isDirectory()) return c;
38678
+ if (fs10.statSync(c).isDirectory()) return c;
38489
38679
  } catch {
38490
38680
  }
38491
38681
  }
@@ -38499,13 +38689,13 @@ function codexRolloutExists(sessionId, root = codexSessionsRoot()) {
38499
38689
  if (hit) return;
38500
38690
  let ents;
38501
38691
  try {
38502
- ents = fs9.readdirSync(d, { withFileTypes: true });
38692
+ ents = fs10.readdirSync(d, { withFileTypes: true });
38503
38693
  } catch {
38504
38694
  return;
38505
38695
  }
38506
38696
  for (const ent of ents) {
38507
38697
  if (hit) return;
38508
- const p2 = path9.join(d, ent.name);
38698
+ const p2 = path10.join(d, ent.name);
38509
38699
  if (ent.isDirectory()) walk(p2);
38510
38700
  else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(suffix)) {
38511
38701
  hit = true;
@@ -38522,17 +38712,17 @@ function listRecentRollouts(root, sinceMs) {
38522
38712
  const walk = (d) => {
38523
38713
  let ents;
38524
38714
  try {
38525
- ents = fs9.readdirSync(d, { withFileTypes: true });
38715
+ ents = fs10.readdirSync(d, { withFileTypes: true });
38526
38716
  } catch {
38527
38717
  return;
38528
38718
  }
38529
38719
  for (const ent of ents) {
38530
- const p2 = path9.join(d, ent.name);
38720
+ const p2 = path10.join(d, ent.name);
38531
38721
  if (ent.isDirectory()) walk(p2);
38532
38722
  else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(".jsonl")) {
38533
38723
  let m2 = 0;
38534
38724
  try {
38535
- m2 = fs9.statSync(p2).mtimeMs;
38725
+ m2 = fs10.statSync(p2).mtimeMs;
38536
38726
  } catch {
38537
38727
  }
38538
38728
  if (m2 >= margin) found.push({ f: p2, m: m2 });
@@ -38557,7 +38747,7 @@ function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
38557
38747
  const files = listRecentRollouts(sessionsRoot, sinceMs);
38558
38748
  const readLines = (f2) => {
38559
38749
  try {
38560
- return fs9.readFileSync(f2, "utf8").split("\n");
38750
+ return fs10.readFileSync(f2, "utf8").split("\n");
38561
38751
  } catch {
38562
38752
  return null;
38563
38753
  }
@@ -38757,15 +38947,15 @@ function normalizeCodexConsoleLine(line, state = createCodexNormalizeState()) {
38757
38947
  tool.output.push(line);
38758
38948
  return [];
38759
38949
  }
38760
- var import_node_child_process5, import_node_crypto13, fs9, os4, path9, readline2, CodexAdapter;
38950
+ var import_node_child_process6, import_node_crypto12, fs10, os4, path10, readline2, CodexAdapter;
38761
38951
  var init_codex = __esm({
38762
38952
  "../adapters/src/codex/index.ts"() {
38763
38953
  "use strict";
38764
- import_node_child_process5 = require("node:child_process");
38765
- import_node_crypto13 = require("node:crypto");
38766
- fs9 = __toESM(require("node:fs"), 1);
38954
+ import_node_child_process6 = require("node:child_process");
38955
+ import_node_crypto12 = require("node:crypto");
38956
+ fs10 = __toESM(require("node:fs"), 1);
38767
38957
  os4 = __toESM(require("node:os"), 1);
38768
- path9 = __toESM(require("node:path"), 1);
38958
+ path10 = __toESM(require("node:path"), 1);
38769
38959
  readline2 = __toESM(require("node:readline"), 1);
38770
38960
  init_sync_skills();
38771
38961
  init_claude_code();
@@ -38774,10 +38964,10 @@ var init_codex = __esm({
38774
38964
  this.opts = opts;
38775
38965
  }
38776
38966
  async spawn(job) {
38777
- const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
38778
- const id = `codex-${slug6}-${(0, import_node_crypto13.randomUUID)().slice(0, 8)}`;
38967
+ const slug4 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
38968
+ const id = `codex-${slug4}-${(0, import_node_crypto12.randomUUID)().slice(0, 8)}`;
38779
38969
  const startedAtMs = Date.now();
38780
- const dir = fs9.mkdtempSync(path9.join(this.opts.workRoot ?? os4.tmpdir(), "oasis-session-"));
38970
+ const dir = fs10.mkdtempSync(path10.join(this.opts.workRoot ?? os4.tmpdir(), "oasis-session-"));
38781
38971
  await runSyncSkills(this.opts.syncSkills, {
38782
38972
  actorId: job.actor,
38783
38973
  actorToken: job.actorToken,
@@ -38786,9 +38976,9 @@ var init_codex = __esm({
38786
38976
  sessionDir: dir
38787
38977
  });
38788
38978
  for (const [rel, content] of Object.entries(job.bundle.files)) {
38789
- const file = path9.join(dir, rel);
38790
- fs9.mkdirSync(path9.dirname(file), { recursive: true });
38791
- fs9.writeFileSync(file, content);
38979
+ const file = path10.join(dir, rel);
38980
+ fs10.mkdirSync(path10.dirname(file), { recursive: true });
38981
+ fs10.writeFileSync(file, content);
38792
38982
  }
38793
38983
  const task = job.bundle.files["TASK.md"];
38794
38984
  if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
@@ -38811,20 +39001,20 @@ var init_codex = __esm({
38811
39001
  ...this.opts.extraArgs ?? [],
38812
39002
  prompt
38813
39003
  ];
38814
- const child = (0, import_node_child_process5.spawn)(this.opts.codexBin ?? "codex", args, {
39004
+ const child = (0, import_node_child_process6.spawn)(this.opts.codexBin ?? "codex", args, {
38815
39005
  cwd: dir,
38816
39006
  env: {
38817
39007
  ...scrubLeakyEnv(process.env),
38818
39008
  ...this.opts.env,
38819
39009
  ...job.env,
38820
- ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path9.dirname(p2)).join(path9.delimiter)}${path9.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
39010
+ ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path10.dirname(p2)).join(path10.delimiter)}${path10.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
38821
39011
  OASIS_SERVER: job.server.url,
38822
39012
  OASIS_TOKEN: job.actorToken
38823
39013
  },
38824
39014
  stdio: ["ignore", "pipe", "pipe"]
38825
39015
  });
38826
- let transcriptRef = path9.join(dir, "transcript.txt");
38827
- const out = fs9.createWriteStream(transcriptRef);
39016
+ let transcriptRef = path10.join(dir, "transcript.txt");
39017
+ const out = fs10.createWriteStream(transcriptRef);
38828
39018
  const outputCbs = [];
38829
39019
  const telemetryCbs = [];
38830
39020
  const normalizeState = createCodexNormalizeState();
@@ -38890,14 +39080,14 @@ var init_codex = __esm({
38890
39080
  if (exited) return;
38891
39081
  if (this.opts.cleanupWorkdir) {
38892
39082
  try {
38893
- const keepDir = path9.join(this.opts.workRoot ?? os4.tmpdir(), "oasis-transcripts");
38894
- fs9.mkdirSync(keepDir, { recursive: true });
38895
- const kept = path9.join(keepDir, `${id}.txt`);
39083
+ const keepDir = path10.join(this.opts.workRoot ?? os4.tmpdir(), "oasis-transcripts");
39084
+ fs10.mkdirSync(keepDir, { recursive: true });
39085
+ const kept = path10.join(keepDir, `${id}.txt`);
38896
39086
  const src = transcriptRef;
38897
39087
  out.end(() => {
38898
39088
  try {
38899
- fs9.renameSync(src, kept);
38900
- fs9.rmSync(dir, { recursive: true, force: true });
39089
+ fs10.renameSync(src, kept);
39090
+ fs10.rmSync(dir, { recursive: true, force: true });
38901
39091
  } catch {
38902
39092
  }
38903
39093
  });
@@ -39486,10 +39676,10 @@ function buildReportedUsage(acc, model, inputTokensIncludeCacheRead) {
39486
39676
  return buildUsage(normalized, cost);
39487
39677
  }
39488
39678
  async function runACPSession(job, cfg) {
39489
- const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
39490
- const binTag = path10.basename(cfg.bin).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12) || "acp";
39491
- const id = `${binTag}-${slug6}-${(0, import_node_crypto14.randomUUID)().slice(0, 8)}`;
39492
- const dir = fs10.mkdtempSync(path10.join(cfg.workRoot ?? os5.tmpdir(), "oasis-session-"));
39679
+ const slug4 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
39680
+ const binTag = path11.basename(cfg.bin).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12) || "acp";
39681
+ const id = `${binTag}-${slug4}-${(0, import_node_crypto13.randomUUID)().slice(0, 8)}`;
39682
+ const dir = fs11.mkdtempSync(path11.join(cfg.workRoot ?? os5.tmpdir(), "oasis-session-"));
39493
39683
  if (cfg.runtimeKind) {
39494
39684
  await runSyncSkills(cfg.syncSkills, {
39495
39685
  actorId: job.actor,
@@ -39500,27 +39690,27 @@ async function runACPSession(job, cfg) {
39500
39690
  });
39501
39691
  }
39502
39692
  for (const [rel, content] of Object.entries(job.bundle.files)) {
39503
- const file = path10.join(dir, rel);
39504
- fs10.mkdirSync(path10.dirname(file), { recursive: true });
39505
- fs10.writeFileSync(file, content);
39693
+ const file = path11.join(dir, rel);
39694
+ fs11.mkdirSync(path11.dirname(file), { recursive: true });
39695
+ fs11.writeFileSync(file, content);
39506
39696
  }
39507
39697
  const task = job.bundle.files["TASK.md"];
39508
39698
  if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
39509
- const child = (0, import_node_child_process6.spawn)(cfg.bin, [...cfg.args ?? [], ...cfg.extraArgs ?? []], {
39699
+ const child = (0, import_node_child_process7.spawn)(cfg.bin, [...cfg.args ?? [], ...cfg.extraArgs ?? []], {
39510
39700
  cwd: dir,
39511
39701
  env: {
39512
39702
  ...scrubLeakyEnv(process.env),
39513
39703
  ...cfg.env,
39514
39704
  ...job.env,
39515
39705
  ...cfg.yoloEnv ?? {},
39516
- ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path10.dirname(p2)).join(path10.delimiter)}${path10.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
39706
+ ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path11.dirname(p2)).join(path11.delimiter)}${path11.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
39517
39707
  OASIS_SERVER: job.server.url,
39518
39708
  OASIS_TOKEN: job.actorToken
39519
39709
  },
39520
39710
  stdio: ["pipe", "pipe", "pipe"]
39521
39711
  });
39522
- let transcriptRef = path10.join(dir, "transcript.txt");
39523
- const transcriptOut = fs10.createWriteStream(transcriptRef);
39712
+ let transcriptRef = path11.join(dir, "transcript.txt");
39713
+ const transcriptOut = fs11.createWriteStream(transcriptRef);
39524
39714
  const outputCbs = [];
39525
39715
  const telemetryCbs = [];
39526
39716
  const exitCbs = [];
@@ -39537,14 +39727,14 @@ async function runACPSession(job, cfg) {
39537
39727
  if (capturedSessionId && !info.runtimeSessionId) info = { ...info, runtimeSessionId: capturedSessionId };
39538
39728
  if (cfg.cleanupWorkdir) {
39539
39729
  try {
39540
- const keepDir = path10.join(cfg.workRoot ?? os5.tmpdir(), "oasis-transcripts");
39541
- fs10.mkdirSync(keepDir, { recursive: true });
39542
- const kept = path10.join(keepDir, `${id}.txt`);
39730
+ const keepDir = path11.join(cfg.workRoot ?? os5.tmpdir(), "oasis-transcripts");
39731
+ fs11.mkdirSync(keepDir, { recursive: true });
39732
+ const kept = path11.join(keepDir, `${id}.txt`);
39543
39733
  const src = transcriptRef;
39544
39734
  transcriptOut.end(() => {
39545
39735
  try {
39546
- fs10.renameSync(src, kept);
39547
- fs10.rmSync(dir, { recursive: true, force: true });
39736
+ fs11.renameSync(src, kept);
39737
+ fs11.rmSync(dir, { recursive: true, force: true });
39548
39738
  } catch {
39549
39739
  }
39550
39740
  });
@@ -39745,15 +39935,15 @@ ${task}` : task;
39745
39935
  }
39746
39936
  };
39747
39937
  }
39748
- var import_node_child_process6, import_node_crypto14, fs10, os5, path10, readline3, ACPClient;
39938
+ var import_node_child_process7, import_node_crypto13, fs11, os5, path11, readline3, ACPClient;
39749
39939
  var init_acp = __esm({
39750
39940
  "../adapters/src/_core/acp.ts"() {
39751
39941
  "use strict";
39752
- import_node_child_process6 = require("node:child_process");
39753
- import_node_crypto14 = require("node:crypto");
39754
- fs10 = __toESM(require("node:fs"), 1);
39942
+ import_node_child_process7 = require("node:child_process");
39943
+ import_node_crypto13 = require("node:crypto");
39944
+ fs11 = __toESM(require("node:fs"), 1);
39755
39945
  os5 = __toESM(require("node:os"), 1);
39756
- path10 = __toESM(require("node:path"), 1);
39946
+ path11 = __toESM(require("node:path"), 1);
39757
39947
  readline3 = __toESM(require("node:readline"), 1);
39758
39948
  init_sync_skills();
39759
39949
  init_claude_code();
@@ -40087,9 +40277,9 @@ var init_kiro = __esm({
40087
40277
 
40088
40278
  // ../adapters/src/_core/subprocess.ts
40089
40279
  async function materialize(job, cfg) {
40090
- const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
40091
- const id = `${slug6}-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
40092
- const dir = fs11.mkdtempSync(path11.join(cfg.workRoot ?? os6.tmpdir(), "oasis-session-"));
40280
+ const slug4 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
40281
+ const id = `${slug4}-${(0, import_node_crypto14.randomUUID)().slice(0, 8)}`;
40282
+ const dir = fs12.mkdtempSync(path12.join(cfg.workRoot ?? os6.tmpdir(), "oasis-session-"));
40093
40283
  if (cfg.runtimeKind) {
40094
40284
  await runSyncSkills(cfg.syncSkills, {
40095
40285
  actorId: job.actor,
@@ -40100,9 +40290,9 @@ async function materialize(job, cfg) {
40100
40290
  });
40101
40291
  }
40102
40292
  for (const [rel, content] of Object.entries(job.bundle.files)) {
40103
- const file = path11.join(dir, rel);
40104
- fs11.mkdirSync(path11.dirname(file), { recursive: true });
40105
- fs11.writeFileSync(file, content);
40293
+ const file = path12.join(dir, rel);
40294
+ fs12.mkdirSync(path12.dirname(file), { recursive: true });
40295
+ fs12.writeFileSync(file, content);
40106
40296
  }
40107
40297
  const task = job.bundle.files["TASK.md"];
40108
40298
  if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
@@ -40113,7 +40303,7 @@ function buildEnv(job, extra) {
40113
40303
  ...scrubLeakyEnv(process.env),
40114
40304
  ...extra,
40115
40305
  ...job.env,
40116
- ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path11.dirname(p2)).join(path11.delimiter)}${path11.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
40306
+ ...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path12.dirname(p2)).join(path12.delimiter)}${path12.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
40117
40307
  OASIS_SERVER: job.server.url,
40118
40308
  OASIS_TOKEN: job.actorToken
40119
40309
  };
@@ -40125,14 +40315,14 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, exitCbs) {
40125
40315
  if (cfg.model && !info.model) info = { ...info, model: cfg.model };
40126
40316
  if (cfg.cleanupWorkdir) {
40127
40317
  try {
40128
- const keepDir = path11.join(cfg.workRoot ?? os6.tmpdir(), "oasis-transcripts");
40129
- fs11.mkdirSync(keepDir, { recursive: true });
40130
- const kept = path11.join(keepDir, `${id}.txt`);
40318
+ const keepDir = path12.join(cfg.workRoot ?? os6.tmpdir(), "oasis-transcripts");
40319
+ fs12.mkdirSync(keepDir, { recursive: true });
40320
+ const kept = path12.join(keepDir, `${id}.txt`);
40131
40321
  const src = transcriptRefPtr.value;
40132
40322
  transcriptOut.end(() => {
40133
40323
  try {
40134
- fs11.renameSync(src, kept);
40135
- fs11.rmSync(dir, { recursive: true, force: true });
40324
+ fs12.renameSync(src, kept);
40325
+ fs12.rmSync(dir, { recursive: true, force: true });
40136
40326
  } catch {
40137
40327
  }
40138
40328
  });
@@ -40149,13 +40339,13 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, exitCbs) {
40149
40339
  async function runStreamJson(job, cfg) {
40150
40340
  const { id, dir, task: _task } = await materialize(job, cfg);
40151
40341
  const args = [...cfg.buildArgs(job, dir), ...cfg.extraArgs ?? []];
40152
- const child = (0, import_node_child_process7.spawn)(cfg.bin, args, {
40342
+ const child = (0, import_node_child_process8.spawn)(cfg.bin, args, {
40153
40343
  cwd: dir,
40154
40344
  env: buildEnv(job, cfg.env),
40155
40345
  stdio: ["ignore", "pipe", "pipe"]
40156
40346
  });
40157
- const transcriptRefPtr = { value: path11.join(dir, "transcript.txt") };
40158
- const transcriptOut = fs11.createWriteStream(transcriptRefPtr.value);
40347
+ const transcriptRefPtr = { value: path12.join(dir, "transcript.txt") };
40348
+ const transcriptOut = fs12.createWriteStream(transcriptRefPtr.value);
40159
40349
  const outputCbs = [];
40160
40350
  const telemetryCbs = [];
40161
40351
  const exitCbs = [];
@@ -40225,13 +40415,13 @@ async function runStreamJson(job, cfg) {
40225
40415
  async function runOneShotText(job, cfg) {
40226
40416
  const { id, dir } = await materialize(job, cfg);
40227
40417
  const args = [...cfg.buildArgs(job, dir), ...cfg.extraArgs ?? []];
40228
- const child = (0, import_node_child_process7.spawn)(cfg.bin, args, {
40418
+ const child = (0, import_node_child_process8.spawn)(cfg.bin, args, {
40229
40419
  cwd: dir,
40230
40420
  env: buildEnv(job, cfg.env),
40231
40421
  stdio: ["ignore", "pipe", "pipe"]
40232
40422
  });
40233
- const transcriptRefPtr = { value: path11.join(dir, "transcript.txt") };
40234
- const transcriptOut = fs11.createWriteStream(transcriptRefPtr.value);
40423
+ const transcriptRefPtr = { value: path12.join(dir, "transcript.txt") };
40424
+ const transcriptOut = fs12.createWriteStream(transcriptRefPtr.value);
40235
40425
  const outputCbs = [];
40236
40426
  const exitCbs = [];
40237
40427
  const { finish, exited } = makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, exitCbs);
@@ -40288,15 +40478,15 @@ async function runOneShotText(job, cfg) {
40288
40478
  }
40289
40479
  });
40290
40480
  }
40291
- var import_node_child_process7, import_node_crypto15, fs11, os6, path11, readline4;
40481
+ var import_node_child_process8, import_node_crypto14, fs12, os6, path12, readline4;
40292
40482
  var init_subprocess = __esm({
40293
40483
  "../adapters/src/_core/subprocess.ts"() {
40294
40484
  "use strict";
40295
- import_node_child_process7 = require("node:child_process");
40296
- import_node_crypto15 = require("node:crypto");
40297
- fs11 = __toESM(require("node:fs"), 1);
40485
+ import_node_child_process8 = require("node:child_process");
40486
+ import_node_crypto14 = require("node:crypto");
40487
+ fs12 = __toESM(require("node:fs"), 1);
40298
40488
  os6 = __toESM(require("node:os"), 1);
40299
- path11 = __toESM(require("node:path"), 1);
40489
+ path12 = __toESM(require("node:path"), 1);
40300
40490
  readline4 = __toESM(require("node:readline"), 1);
40301
40491
  init_claude_code();
40302
40492
  init_sync_skills();
@@ -40703,11 +40893,11 @@ function normalizeOpenClaw(line) {
40703
40893
  }
40704
40894
  return [];
40705
40895
  }
40706
- var import_node_crypto16, OpenClawAdapter;
40896
+ var import_node_crypto15, OpenClawAdapter;
40707
40897
  var init_openclaw = __esm({
40708
40898
  "../adapters/src/openclaw/index.ts"() {
40709
40899
  "use strict";
40710
- import_node_crypto16 = require("node:crypto");
40900
+ import_node_crypto15 = require("node:crypto");
40711
40901
  init_subprocess();
40712
40902
  OpenClawAdapter = class {
40713
40903
  constructor(opts = {}) {
@@ -40725,7 +40915,7 @@ var init_openclaw = __esm({
40725
40915
  ---
40726
40916
 
40727
40917
  ${task}` : task;
40728
- const sessionId = job2.runtimeSessionId ?? `oasis-${(0, import_node_crypto16.randomUUID)().slice(0, 8)}`;
40918
+ const sessionId = job2.runtimeSessionId ?? `oasis-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
40729
40919
  return [
40730
40920
  "agent",
40731
40921
  ...opts.mode !== "gateway" ? ["--local"] : [],
@@ -41197,7 +41387,7 @@ function nodesDomain(deps) {
41197
41387
  nodeId = incomingNodeId;
41198
41388
  deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
41199
41389
  } else {
41200
- nodeId = `node-${(0, import_node_crypto17.randomUUID)().slice(0, 8)}`;
41390
+ nodeId = `node-${(0, import_node_crypto16.randomUUID)().slice(0, 8)}`;
41201
41391
  deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
41202
41392
  }
41203
41393
  const existingNode = await deps.nodeStore.getNode(nodeId);
@@ -41337,11 +41527,11 @@ function nodesDomain(deps) {
41337
41527
  });
41338
41528
  };
41339
41529
  }
41340
- var import_node_crypto17, import_node_fs3, import_node_url, import_node_path2;
41530
+ var import_node_crypto16, import_node_fs3, import_node_url, import_node_path2;
41341
41531
  var init_routes4 = __esm({
41342
41532
  "../server/src/domains/nodes/routes.ts"() {
41343
41533
  "use strict";
41344
- import_node_crypto17 = require("node:crypto");
41534
+ import_node_crypto16 = require("node:crypto");
41345
41535
  import_node_fs3 = require("node:fs");
41346
41536
  import_node_url = require("node:url");
41347
41537
  import_node_path2 = require("node:path");
@@ -41403,11 +41593,11 @@ var init_types3 = __esm({
41403
41593
  });
41404
41594
 
41405
41595
  // ../server/src/node-store.ts
41406
- var fs12, MemoryNodeStore, FileNodeStore;
41596
+ var fs13, MemoryNodeStore, FileNodeStore;
41407
41597
  var init_node_store = __esm({
41408
41598
  "../server/src/node-store.ts"() {
41409
41599
  "use strict";
41410
- fs12 = __toESM(require("node:fs"), 1);
41600
+ fs13 = __toESM(require("node:fs"), 1);
41411
41601
  MemoryNodeStore = class {
41412
41602
  nodes = /* @__PURE__ */ new Map();
41413
41603
  runtimes = /* @__PURE__ */ new Map();
@@ -41492,16 +41682,16 @@ var init_node_store = __esm({
41492
41682
  static async open(file) {
41493
41683
  const s2 = new _FileNodeStore(file);
41494
41684
  try {
41495
- const snap = JSON.parse(fs12.readFileSync(file, "utf8"));
41685
+ const snap = JSON.parse(fs13.readFileSync(file, "utf8"));
41496
41686
  for (const n of snap.nodes ?? []) s2.nodes.set(n.id, n);
41497
41687
  for (const r of snap.runtimes ?? []) s2.runtimes.set(r.id, r);
41498
41688
  } catch {
41499
- fs12.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
41689
+ fs13.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
41500
41690
  }
41501
41691
  return s2;
41502
41692
  }
41503
41693
  flush() {
41504
- fs12.writeFileSync(this.file, JSON.stringify({
41694
+ fs13.writeFileSync(this.file, JSON.stringify({
41505
41695
  nodes: [...this.nodes.values()],
41506
41696
  runtimes: [...this.runtimes.values()]
41507
41697
  }, null, 2));
@@ -41616,7 +41806,11 @@ function buildInbox(model, me, leadOf) {
41616
41806
  }
41617
41807
  for (const r of listPendingReviews(model)) {
41618
41808
  if (r.origin) continue;
41619
- if (!r.workspace || creatorOf.get(r.workspace) !== me) continue;
41809
+ if (!r.workspace) continue;
41810
+ const anchorOwner = model.artifacts.get(r.anchor)?.owner;
41811
+ const isOwnerRecipient = creatorOf.get(r.workspace) === me;
41812
+ const isLeadRecipient = !!anchorOwner && !!leadOf && leadOf(anchorOwner) === me;
41813
+ if (!isOwnerRecipient && !isLeadRecipient) continue;
41620
41814
  out.push({
41621
41815
  kind: "change-confirm",
41622
41816
  artifactId: r.anchor,
@@ -42045,7 +42239,7 @@ var init_collab = __esm({
42045
42239
 
42046
42240
  // ../server/src/domains/collab/create-seeded-workorder.ts
42047
42241
  function makeSeededWorkorderCreator(deps) {
42048
- const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto18.randomUUID)().slice(0, 8)}`);
42242
+ const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto17.randomUUID)().slice(0, 8)}`);
42049
42243
  return async (input) => {
42050
42244
  const workspace = genWorkspace();
42051
42245
  if (input.projectId && deps.artifactState) {
@@ -42082,11 +42276,11 @@ function makeSeededWorkorderCreator(deps) {
42082
42276
  return { workspace, rootArtifactId: briefId, spawned: planned.spawned };
42083
42277
  };
42084
42278
  }
42085
- var import_node_crypto18, enc2;
42279
+ var import_node_crypto17, enc2;
42086
42280
  var init_create_seeded_workorder = __esm({
42087
42281
  "../server/src/domains/collab/create-seeded-workorder.ts"() {
42088
42282
  "use strict";
42089
- import_node_crypto18 = require("node:crypto");
42283
+ import_node_crypto17 = require("node:crypto");
42090
42284
  init_planner();
42091
42285
  enc2 = (s2) => new TextEncoder().encode(s2);
42092
42286
  }
@@ -43164,7 +43358,7 @@ function createChatSessionsDomain(opts) {
43164
43358
  const runtimeId = await currentRuntimeId(body.aiActorId) ?? "unknown";
43165
43359
  const now = (/* @__PURE__ */ new Date()).toISOString();
43166
43360
  const session = {
43167
- id: (0, import_node_crypto19.randomUUID)(),
43361
+ id: (0, import_node_crypto18.randomUUID)(),
43168
43362
  humanActorId: req.auth.actor,
43169
43363
  aiActorId: body.aiActorId,
43170
43364
  runtimeId,
@@ -43215,7 +43409,7 @@ function createChatSessionsDomain(opts) {
43215
43409
  if (!body?.role || !body?.content) throw new ApiError(400, "BAD_REQUEST", "role and content required");
43216
43410
  if (body.role !== "user" && body.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
43217
43411
  const msg = await store.appendMessage({
43218
- id: (0, import_node_crypto19.randomUUID)(),
43412
+ id: (0, import_node_crypto18.randomUUID)(),
43219
43413
  sessionId: req.params.id,
43220
43414
  role: body.role,
43221
43415
  content: body.content,
@@ -43252,11 +43446,11 @@ function createChatSessionsDomain(opts) {
43252
43446
  });
43253
43447
  };
43254
43448
  }
43255
- var import_node_crypto19;
43449
+ var import_node_crypto18;
43256
43450
  var init_chat_sessions = __esm({
43257
43451
  "../server/src/domains/chat-sessions/index.ts"() {
43258
43452
  "use strict";
43259
- import_node_crypto19 = require("node:crypto");
43453
+ import_node_crypto18 = require("node:crypto");
43260
43454
  init_router();
43261
43455
  init_workorders();
43262
43456
  init_chat_parts();
@@ -44622,11 +44816,11 @@ function ackMsFromEnv(fallback) {
44622
44816
  const n = Number(v2);
44623
44817
  return Number.isFinite(n) && n >= 0 ? n : fallback;
44624
44818
  }
44625
- var import_node_crypto20, DaemonHubAdapter, BindingRouterAdapter;
44819
+ var import_node_crypto19, DaemonHubAdapter, BindingRouterAdapter;
44626
44820
  var init_daemon_adapter = __esm({
44627
44821
  "../server/src/daemon-adapter.ts"() {
44628
44822
  "use strict";
44629
- import_node_crypto20 = require("node:crypto");
44823
+ import_node_crypto19 = require("node:crypto");
44630
44824
  DaemonHubAdapter = class {
44631
44825
  constructor(hub, opts = {}) {
44632
44826
  this.hub = hub;
@@ -44713,7 +44907,7 @@ var init_daemon_adapter = __esm({
44713
44907
  async spawn(job) {
44714
44908
  const nodeId = job.binding?.nodeId;
44715
44909
  if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
44716
- const dispatchId = `dispatch:${(0, import_node_crypto20.randomUUID)()}`;
44910
+ const dispatchId = `dispatch:${(0, import_node_crypto19.randomUUID)()}`;
44717
44911
  const entry = {
44718
44912
  nodeId,
44719
44913
  exitCbs: [],
@@ -44857,13 +45051,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
44857
45051
  if (sha(body) === lastPushedHash) return { kind: "echo" };
44858
45052
  return { kind: "human-edit", content: body, updatedBy: page.updatedBy };
44859
45053
  }
44860
- var import_node_crypto21, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
45054
+ var import_node_crypto20, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
44861
45055
  var init_engine = __esm({
44862
45056
  "../server/src/mirror/engine.ts"() {
44863
45057
  "use strict";
44864
- import_node_crypto21 = require("node:crypto");
45058
+ import_node_crypto20 = require("node:crypto");
44865
45059
  init_src();
44866
- sha = (s2) => (0, import_node_crypto21.createHash)("sha256").update(s2, "utf8").digest("hex");
45060
+ sha = (s2) => (0, import_node_crypto20.createHash)("sha256").update(s2, "utf8").digest("hex");
44867
45061
  enc3 = (s2) => new TextEncoder().encode(s2);
44868
45062
  dec = (b2) => new TextDecoder().decode(b2);
44869
45063
  MirrorEngine = class {
@@ -44976,22 +45170,22 @@ var init_engine = __esm({
44976
45170
  });
44977
45171
 
44978
45172
  // ../server/src/mirror/fs-state.ts
44979
- var fs14, FsMirrorStateStore;
45173
+ var fs15, FsMirrorStateStore;
44980
45174
  var init_fs_state = __esm({
44981
45175
  "../server/src/mirror/fs-state.ts"() {
44982
45176
  "use strict";
44983
- fs14 = __toESM(require("node:fs"), 1);
45177
+ fs15 = __toESM(require("node:fs"), 1);
44984
45178
  FsMirrorStateStore = class {
44985
45179
  constructor(file) {
44986
45180
  this.file = file;
44987
- if (fs14.existsSync(file)) {
44988
- const obj = JSON.parse(fs14.readFileSync(file, "utf8"));
45181
+ if (fs15.existsSync(file)) {
45182
+ const obj = JSON.parse(fs15.readFileSync(file, "utf8"));
44989
45183
  for (const [k2, v2] of Object.entries(obj)) this.map.set(k2, v2);
44990
45184
  }
44991
45185
  }
44992
45186
  map = /* @__PURE__ */ new Map();
44993
45187
  flush() {
44994
- fs14.writeFileSync(this.file, JSON.stringify(Object.fromEntries(this.map), null, 2));
45188
+ fs15.writeFileSync(this.file, JSON.stringify(Object.fromEntries(this.map), null, 2));
44995
45189
  }
44996
45190
  async get(artifactId) {
44997
45191
  return this.map.get(artifactId) ?? null;
@@ -45008,13 +45202,13 @@ var init_fs_state = __esm({
45008
45202
  });
45009
45203
 
45010
45204
  // ../server/src/git/integrate.ts
45011
- var import_node_child_process8, fs15, path13, GitRemoteIntegrator;
45205
+ var import_node_child_process9, fs16, path14, GitRemoteIntegrator;
45012
45206
  var init_integrate = __esm({
45013
45207
  "../server/src/git/integrate.ts"() {
45014
45208
  "use strict";
45015
- import_node_child_process8 = require("node:child_process");
45016
- fs15 = __toESM(require("node:fs"), 1);
45017
- path13 = __toESM(require("node:path"), 1);
45209
+ import_node_child_process9 = require("node:child_process");
45210
+ fs16 = __toESM(require("node:fs"), 1);
45211
+ path14 = __toESM(require("node:path"), 1);
45018
45212
  GitRemoteIntegrator = class {
45019
45213
  constructor(remote, cloneDir, develop = "develop") {
45020
45214
  this.remote = remote;
@@ -45023,7 +45217,7 @@ var init_integrate = __esm({
45023
45217
  }
45024
45218
  env = { ...process.env, LC_ALL: "C", LANG: "C", GIT_TERMINAL_PROMPT: "0" };
45025
45219
  git(args) {
45026
- return (0, import_node_child_process8.execFileSync)("git", ["-C", this.cloneDir, ...args], {
45220
+ return (0, import_node_child_process9.execFileSync)("git", ["-C", this.cloneDir, ...args], {
45027
45221
  encoding: "utf8",
45028
45222
  env: this.env,
45029
45223
  maxBuffer: 256 * 1024 * 1024
@@ -45031,9 +45225,9 @@ var init_integrate = __esm({
45031
45225
  }
45032
45226
  /** 确保本地工作克隆存在并拉到最新远程态。幂等。 */
45033
45227
  sync() {
45034
- if (!fs15.existsSync(path13.join(this.cloneDir, ".git"))) {
45035
- fs15.mkdirSync(path13.dirname(this.cloneDir), { recursive: true });
45036
- (0, import_node_child_process8.execFileSync)("git", ["clone", "--quiet", this.remote, this.cloneDir], { env: this.env, maxBuffer: 256 * 1024 * 1024 });
45228
+ if (!fs16.existsSync(path14.join(this.cloneDir, ".git"))) {
45229
+ fs16.mkdirSync(path14.dirname(this.cloneDir), { recursive: true });
45230
+ (0, import_node_child_process9.execFileSync)("git", ["clone", "--quiet", this.remote, this.cloneDir], { env: this.env, maxBuffer: 256 * 1024 * 1024 });
45037
45231
  this.git(["config", "user.email", "oasis@local"]);
45038
45232
  this.git(["config", "user.name", "oasis"]);
45039
45233
  } else {
@@ -45083,224 +45277,26 @@ var init_integrate = __esm({
45083
45277
  });
45084
45278
 
45085
45279
  // ../server/src/git/sync.ts
45086
- var os7, path14, slug3, GitSyncWorker;
45087
45280
  var init_sync = __esm({
45088
45281
  "../server/src/git/sync.ts"() {
45089
45282
  "use strict";
45090
- os7 = __toESM(require("node:os"), 1);
45091
- path14 = __toESM(require("node:path"), 1);
45092
- init_src2();
45093
- init_integrate();
45094
- init_collect();
45095
- slug3 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
45096
- GitSyncWorker = class {
45097
- // 仓库键(remote||id) → 集成器(缓存)
45098
- constructor(deps) {
45099
- this.deps = deps;
45100
- }
45101
- integrators = /* @__PURE__ */ new Map();
45102
- integratorFor(repo) {
45103
- if (!repo.remote) return null;
45104
- const key = repo.remote;
45105
- let g2 = this.integrators.get(key);
45106
- if (!g2) {
45107
- const root = this.deps.mirrorRoot ?? path14.join(os7.tmpdir(), "oasis-git-mirrors");
45108
- const cloneDir = repo.repoDir ?? path14.join(root, slug3(repo.id));
45109
- g2 = new GitRemoteIntegrator(repo.remote, cloneDir, repo.develop);
45110
- this.integrators.set(key, g2);
45111
- }
45112
- return g2;
45113
- }
45114
- /** 一轮:把每个已 conclude 的代码 artifact 的 commit **逐仓**集成进各自 develop。幂等(git ancestor 判断)。 */
45115
- async tick() {
45116
- const { kernel, log: log3 } = this.deps;
45117
- const synced = /* @__PURE__ */ new Set();
45118
- for (const artifact of kernel.model.artifacts.values()) {
45119
- const p2 = await this.deps.resolveProject(artifact.workspace);
45120
- if (!p2 || !p2.repos?.length) continue;
45121
- if (!isConcluded(kernel.model, artifact.id)) continue;
45122
- const head = artifact.currentRev;
45123
- if (!head) continue;
45124
- const rev = kernel.model.revisions.get(head);
45125
- if (!rev || rev.contentKind !== "external-pin") continue;
45126
- for (const { repo, sha: sha2 } of parseUmbrellaCommits(rev.contentRef, p2.repos)) {
45127
- const integ = this.integratorFor(repo);
45128
- if (!integ) continue;
45129
- const tag = `${artifact.id}/${repo.id}@${sha2.slice(0, 12)}`;
45130
- try {
45131
- if (!synced.has(repo.remote)) {
45132
- integ.sync();
45133
- synced.add(repo.remote);
45134
- }
45135
- const r = integ.integrate(sha2, `integrate ${tag} \u2192 ${repo.develop}`);
45136
- if (r.merged) log3?.(`[git] merged ${tag} \u2192 ${repo.develop}`);
45137
- else if (r.conflicts?.length) log3?.(`[git] ${tag} \u96C6\u6210\u51B2\u7A81: ${r.conflicts.join(", ")}\uFF08\u5F85\u56DE\u704C blocking annotation + rebase\uFF09`);
45138
- } catch (e) {
45139
- log3?.(`[git] ${tag} \u96C6\u6210\u5931\u8D25\uFF08\u4E0B\u4E00\u8F6E\u91CD\u8BD5\uFF09: ${String(e)}`);
45140
- }
45141
- }
45142
- }
45143
- }
45144
- };
45145
- }
45146
- });
45147
-
45148
- // ../server/src/git/ci-provider.ts
45149
- function mirrorDirFor(mirrorRoot, repo) {
45150
- if (repo.repoDir) return repo.repoDir;
45151
- const key = repo.remote ? `${slug4(repo.id)}-${crypto.createHash("sha1").update(repo.remote).digest("hex").slice(0, 8)}` : slug4(repo.id);
45152
- return `${mirrorRoot}/${key}`;
45153
- }
45154
- var import_node_child_process9, crypto, fs16, path15, import_node_util, execFile, slug4, GhCiProvider;
45155
- var init_ci_provider = __esm({
45156
- "../server/src/git/ci-provider.ts"() {
45157
- "use strict";
45158
- import_node_child_process9 = require("node:child_process");
45159
- crypto = __toESM(require("node:crypto"), 1);
45160
- fs16 = __toESM(require("node:fs"), 1);
45161
- path15 = __toESM(require("node:path"), 1);
45162
- import_node_util = require("node:util");
45163
- execFile = (0, import_node_util.promisify)(import_node_child_process9.execFile);
45164
- slug4 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
45165
- GhCiProvider = class {
45166
- constructor(opts) {
45167
- this.opts = opts;
45168
- }
45169
- repoDir(repo) {
45170
- return mirrorDirFor(this.opts.mirrorRoot, repo);
45171
- }
45172
- /** 缺则 clone(首次使用/进程重启后本地镜像不存在)——否则 git fetch 会"not a git repo"报错。同 GitRemoteIntegrator。 */
45173
- ensureClone(repo) {
45174
- const dir = this.repoDir(repo);
45175
- if (fs16.existsSync(path15.join(dir, ".git"))) {
45176
- if (repo.remote) {
45177
- let origin = "";
45178
- try {
45179
- origin = (0, import_node_child_process9.execFileSync)("git", ["remote", "get-url", "origin"], { cwd: dir, env: process.env }).toString().trim();
45180
- } catch {
45181
- }
45182
- if (origin !== repo.remote) {
45183
- (0, import_node_child_process9.execFileSync)("git", ["remote", "set-url", "origin", repo.remote], { cwd: dir, env: process.env });
45184
- this.opts.log?.(`[ci] ${repo.id} \u955C\u50CF origin \u7EA0\u504F\uFF1A${origin || "(\u65E0)"} \u2192 ${repo.remote}`);
45185
- }
45186
- }
45187
- return;
45188
- }
45189
- if (!repo.remote) throw new Error(`repo ${repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5 clone`);
45190
- fs16.mkdirSync(path15.dirname(dir), { recursive: true });
45191
- (0, import_node_child_process9.execFileSync)("git", ["clone", "--quiet", repo.remote, dir], { env: process.env });
45192
- this.opts.log?.(`[ci] cloned ${repo.id} \u2192 ${dir}`);
45193
- }
45194
- async gh(repo, args) {
45195
- this.ensureClone(repo);
45196
- const { stdout } = await execFile("gh", args, { cwd: this.repoDir(repo), env: process.env });
45197
- return stdout.trim();
45198
- }
45199
- async git(repo, args) {
45200
- this.ensureClone(repo);
45201
- const { stdout } = await execFile("git", args, { cwd: this.repoDir(repo), env: process.env });
45202
- return stdout.trim();
45203
- }
45204
- async ensurePr(ref, meta) {
45205
- if (!ref.repo.remote) throw new Error(`repo ${ref.repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5\u5F00 PR`);
45206
- await this.git(ref.repo, ["fetch", "--quiet", "--prune", "origin"]);
45207
- await this.git(ref.repo, ["push", "--quiet", "--force-with-lease", "origin", `${ref.sha}:refs/heads/${ref.branch}`]);
45208
- const existing = await this.gh(ref.repo, ["pr", "list", "--head", ref.branch, "--base", ref.repo.develop, "--state", "open", "--json", "number,url"]);
45209
- const list = JSON.parse(existing || "[]");
45210
- if (list[0]) return list[0];
45211
- const url = await this.gh(ref.repo, ["pr", "create", "--base", ref.repo.develop, "--head", ref.branch, "--title", meta.title, "--body", meta.body]);
45212
- const created = JSON.parse(await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "number,url"]));
45213
- this.opts.log?.(`[ci] opened PR ${created.url} (${ref.branch} \u2192 ${ref.repo.develop})`);
45214
- return created.url ? created : { number: created.number, url };
45215
- }
45216
- async status(ref) {
45217
- let raw;
45218
- try {
45219
- raw = await this.gh(ref.repo, ["pr", "view", ref.branch, "--json", "statusCheckRollup,createdAt"]);
45220
- } catch (e) {
45221
- return { state: "pending", summary: `\u8BFB PR \u72B6\u6001\u5931\u8D25\uFF08\u4E0B\u8F6E\u91CD\u8BD5\uFF09\uFF1A${String(e)}` };
45222
- }
45223
- const parsed = JSON.parse(raw || "{}");
45224
- const rollup = parsed.statusCheckRollup ?? [];
45225
- if (rollup.length === 0) {
45226
- const grace = this.opts.noCheckGraceMs ?? 12e4;
45227
- const ageMs = parsed.createdAt ? Date.now() - Date.parse(parsed.createdAt) : Infinity;
45228
- if (ageMs < grace) return { state: "pending" };
45229
- if (this.opts.failClosedWhenNoChecks) return { state: "failure", summary: "\u8BE5\u4ED3\u672A\u914D\u4EFB\u4F55 Actions check\uFF08fail-closed\uFF09\u2014\u2014\u8BF7\u8865 CI \u6216\u6539\u914D\u7F6E" };
45230
- this.opts.log?.(`[ci] ${ref.repo.id} PR ${ref.branch} \u5F00\u4E86 ${Math.round(ageMs / 1e3)}s \u4ECD\u65E0 check\uFF0C\u5224\u65E0 CI\u3001\u95F8\u7A7A\u8FC7\uFF08\u544A\u8B66\uFF09`);
45231
- return { state: "success", summary: "\u65E0 CI check\uFF0C\u95F8\u7A7A\u8FC7" };
45232
- }
45233
- const failed = [];
45234
- let anyPending = false;
45235
- for (const c of rollup) {
45236
- const concl = (c.conclusion ?? "").toUpperCase();
45237
- const st = (c.status ?? "").toUpperCase();
45238
- if (st && st !== "COMPLETED") {
45239
- anyPending = true;
45240
- continue;
45241
- }
45242
- if (concl && !["SUCCESS", "NEUTRAL", "SKIPPED"].includes(concl)) failed.push(c);
45243
- }
45244
- if (failed.length > 0) {
45245
- const blocks = [];
45246
- for (const c of failed) {
45247
- const name = c.name ?? c.context ?? "check";
45248
- const concl = (c.conclusion ?? "").toUpperCase();
45249
- const url = c.detailsUrl ?? c.targetUrl ?? "";
45250
- let block = ` - ${name} \u2192 ${concl}${url ? `
45251
- ${url}` : ""}`;
45252
- const tail = await this.failedLogTail(ref.repo, url);
45253
- if (tail) block += `
45254
- \u5931\u8D25\u65E5\u5FD7\uFF08\u672B\u5C3E\uFF09\uFF1A
45255
- ${tail.split("\n").map((l) => " " + l).join("\n")}`;
45256
- blocks.push(block);
45257
- }
45258
- return { state: "failure", summary: `CI \u672A\u8FC7\uFF08${failed.length} \u4E2A check\uFF09\uFF1A
45259
- ${blocks.join("\n")}` };
45260
- }
45261
- if (anyPending) return { state: "pending" };
45262
- return { state: "success", summary: `CI \u901A\u8FC7\uFF08${rollup.length} \u4E2A check\uFF09` };
45263
- }
45264
- /** best-effort:从 check 的 detailsUrl 提 Actions run id,取失败步骤日志末尾(截断)。取不到返回空。 */
45265
- async failedLogTail(repo, detailsUrl) {
45266
- const m2 = /\/runs\/(\d+)/.exec(detailsUrl);
45267
- if (!m2) return "";
45268
- try {
45269
- const log3 = await this.gh(repo, ["run", "view", m2[1], "--log-failed"]);
45270
- return log3.split("\n").filter(Boolean).slice(-40).join("\n").slice(-2e3);
45271
- } catch {
45272
- return "";
45273
- }
45274
- }
45275
- async merge(ref) {
45276
- try {
45277
- await this.gh(ref.repo, ["pr", "merge", ref.branch, "--merge", "--delete-branch"]);
45278
- this.opts.log?.(`[ci] merged PR ${ref.branch} \u2192 ${ref.repo.develop}`);
45279
- return { merged: true };
45280
- } catch (e) {
45281
- return { merged: false, reason: String(e) };
45282
- }
45283
- }
45284
- };
45285
45283
  }
45286
45284
  });
45287
45285
 
45288
45286
  // ../server/src/git/ci-gate.ts
45289
- var slug5, CiGateWorker;
45287
+ var CiGateWorker;
45290
45288
  var init_ci_gate = __esm({
45291
45289
  "../server/src/git/ci-gate.ts"() {
45292
45290
  "use strict";
45293
45291
  init_src2();
45294
45292
  init_collect();
45295
- slug5 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
45293
+ init_ci_provider();
45296
45294
  CiGateWorker = class {
45297
45295
  constructor(deps) {
45298
45296
  this.deps = deps;
45299
45297
  this.ciActor = deps.ciActor ?? "actor:ci";
45300
45298
  }
45301
45299
  ciActor;
45302
- /** 进程内"已尝试合并"去重(避免每轮重复 gh pr merge;重启后至多多试一次,gh 报已合并即无害)。 */
45303
- mergedOnce = /* @__PURE__ */ new Set();
45304
45300
  /** 逐产物失败退避:连续失败指数拉长重试间隔,超过阈值响亮升级一次(不再静默每轮刷日志)。 */
45305
45301
  failures = /* @__PURE__ */ new Map();
45306
45302
  inBackoff(artifactId) {
@@ -45336,9 +45332,8 @@ var init_ci_gate = __esm({
45336
45332
  if (!p2 || !p2.repos?.length) return null;
45337
45333
  const units = [];
45338
45334
  for (const { repo, sha: sha2 } of parseUmbrellaCommits(contentRef, p2.repos)) {
45339
- if (!repo.remote) continue;
45340
- const artifactSlug2 = slug5(artifactId.replace(/^artifact:/, "")).slice(0, 48);
45341
- units.push({ repo, sha: sha2, branch: `oasis-ci/${artifactSlug2}/${sha2.slice(0, 8)}` });
45335
+ if (!isGitHubRemote(repo.remote)) continue;
45336
+ units.push({ repo, sha: sha2, branch: ciBranchFor(artifactId, sha2) });
45342
45337
  }
45343
45338
  return units;
45344
45339
  }
@@ -45386,14 +45381,6 @@ var init_ci_gate = __esm({
45386
45381
  log3?.(`[ci] vote ${artifact.id} \u5931\u8D25\uFF08\u9000\u907F\u91CD\u8BD5\uFF09\uFF1A${String(e)}`);
45387
45382
  }
45388
45383
  );
45389
- } else if (isConcluded(kernel.model, artifact.id) && rev.contentKind === "external-pin") {
45390
- await this.mergeMilestone(artifact.id, artifact.workspace, rev.contentRef, head).then(
45391
- () => this.recordOk(artifact.id),
45392
- (e) => {
45393
- this.recordFail(artifact.id);
45394
- log3?.(`[ci] merge ${artifact.id} \u5931\u8D25\uFF08\u9000\u907F\u91CD\u8BD5\uFF09\uFF1A${String(e)}`);
45395
- }
45396
- );
45397
45384
  } else {
45398
45385
  this.clearStatus(artifact.id);
45399
45386
  }
@@ -45430,32 +45417,122 @@ var init_ci_gate = __esm({
45430
45417
  this.clearStatus(artifactId);
45431
45418
  log3?.(`[ci] ${artifactId} CI \u5168\u7EFF \u2192 approve`);
45432
45419
  }
45433
- async mergeMilestone(artifactId, workspace, contentRef, head) {
45434
- const { ci, log: log3 } = this.deps;
45435
- const units = await this.unitsFor(artifactId, workspace, contentRef);
45436
- if (!units) {
45437
- this.clearStatus(artifactId);
45438
- return;
45420
+ };
45421
+ }
45422
+ });
45423
+
45424
+ // ../server/src/git/merge-worker.ts
45425
+ var MergeWorker;
45426
+ var init_merge_worker = __esm({
45427
+ "../server/src/git/merge-worker.ts"() {
45428
+ "use strict";
45429
+ init_src2();
45430
+ init_collect();
45431
+ init_integrate();
45432
+ init_ci_provider();
45433
+ MergeWorker = class {
45434
+ constructor(deps) {
45435
+ this.deps = deps;
45436
+ }
45437
+ integrators = /* @__PURE__ */ new Map();
45438
+ mergedOnce = /* @__PURE__ */ new Set();
45439
+ failures = /* @__PURE__ */ new Map();
45440
+ inBackoff(id) {
45441
+ const f2 = this.failures.get(id);
45442
+ return !!f2 && Date.now() < f2.nextAt;
45443
+ }
45444
+ recordFail(id) {
45445
+ const base = this.deps.backoff?.baseMs ?? 3e4;
45446
+ const cap = this.deps.backoff?.capMs ?? 6e5;
45447
+ const escalateAfter = this.deps.backoff?.escalateAfter ?? 5;
45448
+ const f2 = this.failures.get(id) ?? { count: 0, nextAt: 0, escalated: false };
45449
+ f2.count += 1;
45450
+ f2.nextAt = Date.now() + Math.min(base * 2 ** (f2.count - 1), cap);
45451
+ if (f2.count >= escalateAfter && !f2.escalated) {
45452
+ f2.escalated = true;
45453
+ this.deps.log?.(`[merge] \u26A0\uFE0F ${id} \u8FDE\u7EED\u5931\u8D25 ${f2.count} \u6B21\uFF0C\u5DF2\u8FDB\u5165\u957F\u9000\u907F\uFF08\u4E0A\u9650 ${Math.round(cap / 1e3)}s\uFF09\u2014\u2014\u8BF7\u4EBA\u5DE5\u68C0\u67E5\u8FDC\u7AEF\u4ED3 / \u5206\u652F\u4FDD\u62A4\u72B6\u6001`);
45439
45454
  }
45440
- const pending = units.filter((u) => !this.mergedOnce.has(`${artifactId}::${head}::${u.repo.id}`));
45441
- if (pending.length === 0) {
45442
- this.clearStatus(artifactId);
45443
- return;
45455
+ this.failures.set(id, f2);
45456
+ }
45457
+ recordOk(id) {
45458
+ this.failures.delete(id);
45459
+ }
45460
+ setStatus(id, s2) {
45461
+ this.deps.statusSink?.set(id, { ...s2, updatedAt: (/* @__PURE__ */ new Date()).toISOString() });
45462
+ }
45463
+ clearStatus(id) {
45464
+ this.deps.statusSink?.delete(id);
45465
+ }
45466
+ /** 非 GitHub 仓的本地集成器(按归一化 remote 缓存;克隆目录与 CI 闸同套 mirrorDirFor,逻辑 id 重名不撞)。 */
45467
+ integratorFor(repo) {
45468
+ if (!repo.remote) return null;
45469
+ const key = normalizeRemote(repo.remote);
45470
+ let g2 = this.integrators.get(key);
45471
+ if (!g2) {
45472
+ g2 = new GitRemoteIntegrator(repo.remote, mirrorDirFor(this.deps.mirrorRoot, repo), repo.develop);
45473
+ this.integrators.set(key, g2);
45444
45474
  }
45445
- this.setStatus(artifactId, { phase: "merging", repos: pending.map((u) => ({ repoId: u.repo.id, sha: u.sha.slice(0, 8), state: "success" })) });
45446
- for (const unit of units) {
45447
- const key = `${artifactId}::${head}::${unit.repo.id}`;
45448
- if (this.mergedOnce.has(key)) continue;
45449
- const r = await ci.merge({ repo: unit.repo, branch: unit.branch });
45450
- if (r.merged) {
45451
- this.mergedOnce.add(key);
45452
- log3?.(`[ci] merged ${artifactId}/${unit.repo.id} \u2192 ${unit.repo.develop}`);
45453
- } else {
45454
- this.mergedOnce.add(key);
45455
- log3?.(`[ci] ${artifactId}/${unit.repo.id} \u672A\u5408\uFF08${r.reason ?? "not mergeable"}\uFF09\u2014\u2014\u82E5\u5DF2\u5408\u5E76\u53EF\u5FFD\u7565`);
45475
+ return g2;
45476
+ }
45477
+ async tick() {
45478
+ const { kernel, log: log3 } = this.deps;
45479
+ for (const artifact of kernel.model.artifacts.values()) {
45480
+ const head = artifact.currentRev;
45481
+ if (!head) continue;
45482
+ const rev = kernel.model.revisions.get(head);
45483
+ if (!rev || rev.contentKind !== "external-pin") continue;
45484
+ if (!isConcluded(kernel.model, artifact.id)) continue;
45485
+ if (this.inBackoff(artifact.id)) continue;
45486
+ const p2 = await this.deps.resolveProject(artifact.workspace);
45487
+ if (!p2 || !p2.repos?.length) {
45488
+ this.clearStatus(artifact.id);
45489
+ continue;
45490
+ }
45491
+ const units = parseUmbrellaCommits(rev.contentRef, p2.repos).filter((u) => u.repo.remote);
45492
+ const keyOf = (u) => `${artifact.id}::${head}::${normalizeRemote(u.repo.remote)}`;
45493
+ const pending = units.filter((u) => !this.mergedOnce.has(keyOf(u)));
45494
+ if (pending.length === 0) {
45495
+ this.clearStatus(artifact.id);
45496
+ continue;
45497
+ }
45498
+ this.setStatus(artifact.id, { phase: "merging", repos: pending.map((u) => ({ repoId: u.repo.id, sha: u.sha.slice(0, 8), state: "success" })) });
45499
+ try {
45500
+ for (const { repo, sha: sha2 } of pending) {
45501
+ if (isGitHubRemote(repo.remote)) {
45502
+ if (await this.deps.ci.isMerged({ repo, sha: sha2 })) {
45503
+ this.mergedOnce.add(keyOf({ repo }));
45504
+ continue;
45505
+ }
45506
+ const branch = ciBranchFor(artifact.id, sha2);
45507
+ await this.deps.ci.ensurePr(
45508
+ { repo, branch, sha: sha2 },
45509
+ { title: `[oasis-ci] ${artifact.id} \u2192 ${repo.develop}`, body: `merge artifact ${artifact.id} @ ${sha2}` }
45510
+ );
45511
+ const r = await this.deps.ci.merge({ repo, branch });
45512
+ this.mergedOnce.add(keyOf({ repo }));
45513
+ log3?.(r.merged ? `[merge] merged ${artifact.id}/${repo.id} \u2192 ${repo.develop}\uFF08PR\uFF09` : `[merge] ${artifact.id}/${repo.id} \u672A\u5408\uFF08${r.reason ?? "not mergeable"}\uFF09\u2014\u2014\u82E5\u5DF2\u5408\u53EF\u5FFD\u7565`);
45514
+ } else {
45515
+ const integ = this.integratorFor(repo);
45516
+ if (!integ) continue;
45517
+ integ.sync();
45518
+ const r = integ.integrate(sha2, `integrate ${artifact.id}/${repo.id}@${sha2.slice(0, 12)} \u2192 ${repo.develop}`);
45519
+ if (r.merged || r.already) {
45520
+ this.mergedOnce.add(keyOf({ repo }));
45521
+ if (r.merged) log3?.(`[merge] merged ${artifact.id}/${repo.id} \u2192 ${repo.develop}\uFF08\u672C\u5730\uFF09`);
45522
+ } else if (r.conflicts?.length) {
45523
+ log3?.(`[merge] ${artifact.id}/${repo.id} \u96C6\u6210\u51B2\u7A81: ${r.conflicts.join(", ")}\uFF08\u5F85\u56DE\u704C blocking annotation + rebase\uFF09`);
45524
+ }
45525
+ }
45526
+ }
45527
+ this.recordOk(artifact.id);
45528
+ this.clearStatus(artifact.id);
45529
+ } catch (e) {
45530
+ this.recordFail(artifact.id);
45531
+ const f2 = this.failures.get(artifact.id);
45532
+ this.setStatus(artifact.id, { phase: "stuck", repos: [], reason: String(e).slice(0, 500), ...f2 ? { retryAt: new Date(f2.nextAt).toISOString() } : {} });
45533
+ log3?.(`[merge] ${artifact.id} \u5408\u5E76\u5931\u8D25\uFF08\u9000\u907F\u91CD\u8BD5\uFF09\uFF1A${String(e)}`);
45456
45534
  }
45457
45535
  }
45458
- this.clearStatus(artifactId);
45459
45536
  }
45460
45537
  };
45461
45538
  }
@@ -45492,11 +45569,11 @@ var init_resolve = __esm({
45492
45569
  });
45493
45570
 
45494
45571
  // ../server/src/coordinator/worker.ts
45495
- var import_node_crypto22, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_MANAGER_BODY, CoordinatorWorker;
45572
+ var import_node_crypto21, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_MANAGER_BODY, CoordinatorWorker;
45496
45573
  var init_worker = __esm({
45497
45574
  "../server/src/coordinator/worker.ts"() {
45498
45575
  "use strict";
45499
- import_node_crypto22 = require("node:crypto");
45576
+ import_node_crypto21 = require("node:crypto");
45500
45577
  init_src2();
45501
45578
  init_identity();
45502
45579
  AUTONOMOUS_ETHOS = `\u4F60\u662F\u8FD9\u4E2A\u5DE5\u5355\u7684**\u7BA1\u7406\u8005**\u2014\u2014\u804C\u8D23\u662F\u8BA9\u5B83\u987A\u7545\u8DD1\u5B8C\u3002\u7CFB\u7EDF\u5728\u67D0\u4E2A\u8282\u70B9\u5361\u4F4F\u3001\u673A\u68B0\u5206\u8BCA\u786E\u8BA4"\u9700\u8981\u4F60"\u65F6\u5524\u8D77\u4F60\uFF08\u65E0\u4EBA\u5728\u573A\uFF0C\u4F60\u8FD9\u4E00\u8F6E\u628A\u80FD\u505A\u7684\u505A\u6389\uFF09\u3002\u4F60\u7684\u624B\u6BB5\u5F88\u5BBD\uFF1A
@@ -45672,7 +45749,7 @@ ${SHARED_GRAPH_BODY}`;
45672
45749
  return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
45673
45750
  }
45674
45751
  evaluationKey(kind, artifactId, evidence) {
45675
- const fingerprint = (0, import_node_crypto22.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
45752
+ const fingerprint = (0, import_node_crypto21.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
45676
45753
  return `${kind}:${artifactId}:${fingerprint}`;
45677
45754
  }
45678
45755
  artifactEvidence(id) {
@@ -45912,7 +45989,7 @@ ${SHARED_GRAPH_BODY}`;
45912
45989
  const token = this.deps.tokenFor(actorId, ctx);
45913
45990
  const serverUrl = this.deps.serverUrlFor ? await this.deps.serverUrlFor(ctx) : this.deps.serverUrl;
45914
45991
  const workspace = this.deps.kernel.model.artifacts.get(artifactId)?.workspace;
45915
- const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto22.randomUUID)();
45992
+ const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto21.randomUUID)();
45916
45993
  const job = {
45917
45994
  actor: actorId,
45918
45995
  actorToken: token,
@@ -46008,22 +46085,22 @@ async function loadBuiltinSkills(skillsDir) {
46008
46085
  const skills = [];
46009
46086
  for (const d of dirents) {
46010
46087
  if (!d.isDirectory()) continue;
46011
- const slug6 = d.name;
46012
- const skillDir = (0, import_node_path4.join)(skillsDir, slug6);
46088
+ const slug4 = d.name;
46089
+ const skillDir = (0, import_node_path4.join)(skillsDir, slug4);
46013
46090
  const files = {};
46014
46091
  try {
46015
46092
  await collectDir(skillDir, skillDir, files);
46016
46093
  } catch (err) {
46017
- console.warn(`[builtin-skills] failed reading ${slug6}: ${String(err)}`);
46094
+ console.warn(`[builtin-skills] failed reading ${slug4}: ${String(err)}`);
46018
46095
  continue;
46019
46096
  }
46020
46097
  const skillMd = files["SKILL.md"];
46021
46098
  if (!skillMd) {
46022
- console.warn(`[builtin-skills] ${slug6} has no SKILL.md, skipping`);
46099
+ console.warn(`[builtin-skills] ${slug4} has no SKILL.md, skipping`);
46023
46100
  continue;
46024
46101
  }
46025
46102
  const { name, description } = parseSkillFrontmatter(skillMd);
46026
- skills.push({ id: slug6, name: name || slug6, description, files });
46103
+ skills.push({ id: slug4, name: name || slug4, description, files });
46027
46104
  }
46028
46105
  return skills;
46029
46106
  }
@@ -46105,6 +46182,7 @@ var init_src5 = __esm({
46105
46182
  init_sync();
46106
46183
  init_ci_provider();
46107
46184
  init_ci_gate();
46185
+ init_merge_worker();
46108
46186
  init_resolve();
46109
46187
  init_identity();
46110
46188
  init_worker();
@@ -49475,7 +49553,7 @@ var require_split2 = __commonJS({
49475
49553
  var require_helper = __commonJS({
49476
49554
  "../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/helper.js"(exports2, module2) {
49477
49555
  "use strict";
49478
- var path20 = require("path");
49556
+ var path19 = require("path");
49479
49557
  var Stream = require("stream").Stream;
49480
49558
  var split = require_split2();
49481
49559
  var util2 = require("util");
@@ -49514,7 +49592,7 @@ var require_helper = __commonJS({
49514
49592
  };
49515
49593
  module2.exports.getFileName = function(rawEnv) {
49516
49594
  var env = rawEnv || process.env;
49517
- var file = env.PGPASSFILE || (isWin ? path20.join(env.APPDATA || "./", "postgresql", "pgpass.conf") : path20.join(env.HOME || "./", ".pgpass"));
49595
+ var file = env.PGPASSFILE || (isWin ? path19.join(env.APPDATA || "./", "postgresql", "pgpass.conf") : path19.join(env.HOME || "./", ".pgpass"));
49518
49596
  return file;
49519
49597
  };
49520
49598
  module2.exports.usePgPass = function(stats, fname) {
@@ -49646,7 +49724,7 @@ var require_helper = __commonJS({
49646
49724
  var require_lib = __commonJS({
49647
49725
  "../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js"(exports2, module2) {
49648
49726
  "use strict";
49649
- var path20 = require("path");
49727
+ var path19 = require("path");
49650
49728
  var fs21 = require("fs");
49651
49729
  var helper = require_helper();
49652
49730
  module2.exports = function(connInfo, cb) {
@@ -51208,33 +51286,33 @@ __export(trajectory_exports, {
51208
51286
  exportTrajectories: () => exportTrajectories
51209
51287
  });
51210
51288
  async function exportTrajectories(dataDir) {
51211
- const root = path16.join(dataDir, "trajectories");
51289
+ const root = path15.join(dataDir, "trajectories");
51212
51290
  if (!fs17.existsSync(root)) return [];
51213
51291
  const model = emptyReadModel();
51214
- const oplogFile = path16.join(dataDir, "oplog.ndjson");
51292
+ const oplogFile = path15.join(dataDir, "oplog.ndjson");
51215
51293
  if (fs17.existsSync(oplogFile)) {
51216
51294
  const oplog = await NdjsonOplogStore.open(oplogFile);
51217
51295
  for await (const entry of oplog.readAll()) fold(model, entry.op);
51218
51296
  }
51219
51297
  const samples = [];
51220
51298
  for (const sessionId of fs17.readdirSync(root).sort()) {
51221
- const dir = path16.join(root, sessionId);
51222
- const sessionFile = path16.join(dir, "session.json");
51299
+ const dir = path15.join(root, sessionId);
51300
+ const sessionFile = path15.join(dir, "session.json");
51223
51301
  if (!fs17.existsSync(sessionFile)) continue;
51224
51302
  const session = JSON.parse(fs17.readFileSync(sessionFile, "utf8"));
51225
51303
  const events = [];
51226
- const eventsFile = path16.join(dir, "events.ndjson");
51304
+ const eventsFile = path15.join(dir, "events.ndjson");
51227
51305
  if (fs17.existsSync(eventsFile)) {
51228
51306
  for (const line of fs17.readFileSync(eventsFile, "utf8").split("\n")) {
51229
51307
  if (line.trim()) events.push(JSON.parse(line));
51230
51308
  }
51231
51309
  }
51232
51310
  const bundle = {};
51233
- const bundleDir = path16.join(dir, "bundle");
51311
+ const bundleDir = path15.join(dir, "bundle");
51234
51312
  const walk = (sub) => {
51235
- for (const name of fs17.readdirSync(path16.join(bundleDir, sub))) {
51313
+ for (const name of fs17.readdirSync(path15.join(bundleDir, sub))) {
51236
51314
  const rel = sub ? `${sub}/${name}` : name;
51237
- const full = path16.join(bundleDir, rel);
51315
+ const full = path15.join(bundleDir, rel);
51238
51316
  if (fs17.statSync(full).isDirectory()) walk(rel);
51239
51317
  else bundle[rel] = fs17.readFileSync(full, "utf8");
51240
51318
  }
@@ -51251,47 +51329,47 @@ async function exportTrajectories(dataDir) {
51251
51329
  }
51252
51330
  return samples;
51253
51331
  }
51254
- var fs17, path16, FsTrajectorySink;
51332
+ var fs17, path15, FsTrajectorySink;
51255
51333
  var init_trajectory = __esm({
51256
51334
  "../cli/src/trajectory.ts"() {
51257
51335
  "use strict";
51258
51336
  fs17 = __toESM(require("node:fs"), 1);
51259
- path16 = __toESM(require("node:path"), 1);
51337
+ path15 = __toESM(require("node:path"), 1);
51260
51338
  init_src2();
51261
51339
  init_src5();
51262
51340
  FsTrajectorySink = class {
51263
51341
  constructor(dataDir, broadcast) {
51264
51342
  this.broadcast = broadcast;
51265
- this.root = path16.join(dataDir, "trajectories");
51343
+ this.root = path15.join(dataDir, "trajectories");
51266
51344
  }
51267
51345
  root;
51268
51346
  dir(sessionId) {
51269
- return path16.join(this.root, sessionId);
51347
+ return path15.join(this.root, sessionId);
51270
51348
  }
51271
51349
  begin(session, bundleFiles) {
51272
51350
  const dir = this.dir(session.sessionId);
51273
- fs17.mkdirSync(path16.join(dir, "bundle"), { recursive: true });
51274
- fs17.writeFileSync(path16.join(dir, "session.json"), JSON.stringify(session, null, 2));
51351
+ fs17.mkdirSync(path15.join(dir, "bundle"), { recursive: true });
51352
+ fs17.writeFileSync(path15.join(dir, "session.json"), JSON.stringify(session, null, 2));
51275
51353
  for (const [rel, content] of Object.entries(bundleFiles)) {
51276
- const file = path16.join(dir, "bundle", rel);
51277
- fs17.mkdirSync(path16.dirname(file), { recursive: true });
51354
+ const file = path15.join(dir, "bundle", rel);
51355
+ fs17.mkdirSync(path15.dirname(file), { recursive: true });
51278
51356
  fs17.writeFileSync(file, content);
51279
51357
  }
51280
51358
  this.broadcast?.({ type: "begin", sessionId: session.sessionId, data: session });
51281
51359
  }
51282
51360
  recover(session) {
51283
51361
  fs17.mkdirSync(this.dir(session.sessionId), { recursive: true });
51284
- const file = path16.join(this.dir(session.sessionId), "session.json");
51362
+ const file = path15.join(this.dir(session.sessionId), "session.json");
51285
51363
  if (!fs17.existsSync(file)) fs17.writeFileSync(file, JSON.stringify(session, null, 2));
51286
51364
  this.broadcast?.({ type: "begin", sessionId: session.sessionId, data: { ...session, recovered: true } });
51287
51365
  }
51288
51366
  event(sessionId, event) {
51289
51367
  fs17.mkdirSync(this.dir(sessionId), { recursive: true });
51290
- fs17.appendFileSync(path16.join(this.dir(sessionId), "events.ndjson"), JSON.stringify(event) + "\n");
51368
+ fs17.appendFileSync(path15.join(this.dir(sessionId), "events.ndjson"), JSON.stringify(event) + "\n");
51291
51369
  this.broadcast?.({ type: "event", sessionId, data: event });
51292
51370
  }
51293
51371
  end(sessionId, update) {
51294
- const file = path16.join(this.dir(sessionId), "session.json");
51372
+ const file = path15.join(this.dir(sessionId), "session.json");
51295
51373
  const session = JSON.parse(fs17.readFileSync(file, "utf8"));
51296
51374
  session.exit = update.exit;
51297
51375
  session.opRefs = update.opRefs;
@@ -51302,23 +51380,23 @@ var init_trajectory = __esm({
51302
51380
  * 路径逻辑复用写入侧 `this.dir()`(单一真相,随 --dir 迁移同步);带路径穿越防护。 */
51303
51381
  readBundleFile(sessionId, rel) {
51304
51382
  if (!sessionId || sessionId.includes("/") || sessionId.includes("..")) return null;
51305
- const bundleRoot = path16.join(this.dir(sessionId), "bundle");
51306
- const target = path16.resolve(bundleRoot, rel);
51307
- if (target !== bundleRoot && !target.startsWith(bundleRoot + path16.sep)) return null;
51383
+ const bundleRoot = path15.join(this.dir(sessionId), "bundle");
51384
+ const target = path15.resolve(bundleRoot, rel);
51385
+ if (target !== bundleRoot && !target.startsWith(bundleRoot + path15.sep)) return null;
51308
51386
  if (!fs17.existsSync(target) || !fs17.statSync(target).isFile()) return null;
51309
51387
  return fs17.readFileSync(target, "utf8");
51310
51388
  }
51311
51389
  /** 列出某会话 bundle 下所有文件的相对路径(供前端「本次输入」点开清单)。 */
51312
51390
  listBundle(sessionId) {
51313
51391
  if (!sessionId || sessionId.includes("/") || sessionId.includes("..")) return [];
51314
- const bundleRoot = path16.join(this.dir(sessionId), "bundle");
51392
+ const bundleRoot = path15.join(this.dir(sessionId), "bundle");
51315
51393
  if (!fs17.existsSync(bundleRoot)) return [];
51316
51394
  const out = [];
51317
51395
  const walk = (d) => {
51318
51396
  for (const e of fs17.readdirSync(d, { withFileTypes: true })) {
51319
- const full = path16.join(d, e.name);
51397
+ const full = path15.join(d, e.name);
51320
51398
  if (e.isDirectory()) walk(full);
51321
- else out.push(path16.relative(bundleRoot, full));
51399
+ else out.push(path15.relative(bundleRoot, full));
51322
51400
  }
51323
51401
  };
51324
51402
  walk(bundleRoot);
@@ -51330,21 +51408,21 @@ var init_trajectory = __esm({
51330
51408
 
51331
51409
  // src/index.ts
51332
51410
  var fs20 = __toESM(require("node:fs"));
51333
- var os10 = __toESM(require("node:os"));
51334
- var path19 = __toESM(require("node:path"));
51411
+ var os9 = __toESM(require("node:os"));
51412
+ var path18 = __toESM(require("node:path"));
51335
51413
  var import_node_child_process15 = require("node:child_process");
51336
51414
 
51337
51415
  // ../cli/src/cli.ts
51338
51416
  var fs19 = __toESM(require("node:fs"), 1);
51339
- var os9 = __toESM(require("node:os"), 1);
51340
- var path18 = __toESM(require("node:path"), 1);
51341
- var import_node_crypto27 = require("node:crypto");
51417
+ var os8 = __toESM(require("node:os"), 1);
51418
+ var path17 = __toESM(require("node:path"), 1);
51419
+ var import_node_crypto26 = require("node:crypto");
51342
51420
 
51343
51421
  // ../cli/src/serve.ts
51344
51422
  var fs18 = __toESM(require("node:fs"), 1);
51345
- var os8 = __toESM(require("node:os"), 1);
51346
- var path17 = __toESM(require("node:path"), 1);
51347
- var import_node_crypto25 = require("node:crypto");
51423
+ var os7 = __toESM(require("node:os"), 1);
51424
+ var path16 = __toESM(require("node:path"), 1);
51425
+ var import_node_crypto24 = require("node:crypto");
51348
51426
  var import_node_url4 = require("node:url");
51349
51427
  init_src2();
51350
51428
  init_src5();
@@ -52261,7 +52339,7 @@ function defaultDocumentPath2(input) {
52261
52339
  init_src4();
52262
52340
 
52263
52341
  // ../storage/src/postgres.ts
52264
- var import_node_crypto23 = require("node:crypto");
52342
+ var import_node_crypto22 = require("node:crypto");
52265
52343
 
52266
52344
  // ../../node_modules/.pnpm/pg@8.21.0/node_modules/pg/esm/index.mjs
52267
52345
  var import_lib = __toESM(require_lib2(), 1);
@@ -52396,7 +52474,7 @@ var PostgresBlobStore = class _PostgresBlobStore {
52396
52474
  return new _PostgresBlobStore(pool, schema);
52397
52475
  }
52398
52476
  async put(bytes) {
52399
- const hash = (0, import_node_crypto23.createHash)("sha256").update(bytes).digest("hex");
52477
+ const hash = (0, import_node_crypto22.createHash)("sha256").update(bytes).digest("hex");
52400
52478
  await this.pool.query(
52401
52479
  `INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
52402
52480
  [hash, Buffer.from(bytes), bytes.byteLength, sniffContentType(bytes) ?? null]
@@ -53861,8 +53939,8 @@ var PostgresControlPlaneStore = class _PostgresControlPlaneStore {
53861
53939
  const r = await this.pool.query(`SELECT * FROM ${this.s}.companies WHERE id = $1`, [id]);
53862
53940
  return r.rows[0] ? rowToCompany(r.rows[0]) : null;
53863
53941
  }
53864
- async getCompanyBySlug(slug6) {
53865
- const r = await this.pool.query(`SELECT * FROM ${this.s}.companies WHERE slug = $1`, [slug6]);
53942
+ async getCompanyBySlug(slug4) {
53943
+ const r = await this.pool.query(`SELECT * FROM ${this.s}.companies WHERE slug = $1`, [slug4]);
53866
53944
  return r.rows[0] ? rowToCompany(r.rows[0]) : null;
53867
53945
  }
53868
53946
  async listCompanies() {
@@ -54306,7 +54384,7 @@ var PostgresTraceStore = class _PostgresTraceStore {
54306
54384
  run.exitReason,
54307
54385
  run.errorCode,
54308
54386
  run.errorMessage,
54309
- JSON.stringify(run.usage),
54387
+ run.usage === null ? null : JSON.stringify(run.usage),
54310
54388
  run.effectiveModel,
54311
54389
  run.modelSource,
54312
54390
  run.transcriptRef,
@@ -54353,7 +54431,7 @@ var PostgresTraceStore = class _PostgresTraceStore {
54353
54431
  for (const [key, spec] of Object.entries(_PostgresTraceStore.RUN_COLS)) {
54354
54432
  if (!(key in patch)) continue;
54355
54433
  const v2 = patch[key];
54356
- args.push(spec.json ? JSON.stringify(v2 ?? null) : v2 ?? null);
54434
+ args.push(spec.json ? v2 == null ? null : JSON.stringify(v2) : v2 ?? null);
54357
54435
  sets.push(spec.json ? `${spec.col}=$${args.length}::jsonb` : `${spec.col}=$${args.length}`);
54358
54436
  }
54359
54437
  args.push(this.now());
@@ -54706,7 +54784,7 @@ var PostgresTraceStore = class _PostgresTraceStore {
54706
54784
  COALESCE(SUM(COALESCE((usage->>'cacheCreationTokens')::bigint, 0)), 0),
54707
54785
  COALESCE(SUM(COALESCE((usage->>'costUsdMicros')::bigint, 0)), 0)
54708
54786
  FROM ${this.s}.agent_runs
54709
- WHERE usage IS NOT NULL
54787
+ WHERE jsonb_typeof(usage) = 'object'
54710
54788
  AND started_at >= $2 AND started_at < $3
54711
54789
  GROUP BY actor_id, runtime_instance_id, runtime_kind, effective_model, hour`,
54712
54790
  [cid, from, to]
@@ -55412,7 +55490,7 @@ var rowToMessage = (row) => ({
55412
55490
  });
55413
55491
 
55414
55492
  // ../storage/src/postgres-nodes.ts
55415
- var import_node_crypto24 = require("node:crypto");
55493
+ var import_node_crypto23 = require("node:crypto");
55416
55494
  var ident8 = (s2) => {
55417
55495
  if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
55418
55496
  return s2;
@@ -55550,7 +55628,7 @@ var PostgresNodeTokenStore = class _PostgresNodeTokenStore {
55550
55628
  return store;
55551
55629
  }
55552
55630
  issue(nodeId) {
55553
- const token = `ont_${(0, import_node_crypto24.randomBytes)(24).toString("base64url")}`;
55631
+ const token = `ont_${(0, import_node_crypto23.randomBytes)(24).toString("base64url")}`;
55554
55632
  this.cache.set(token, nodeId);
55555
55633
  void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
55556
55634
  return token;
@@ -55697,7 +55775,7 @@ function builtinSkillsDir() {
55697
55775
  const override = process.env["OASIS_BUILTIN_SKILLS_DIR"]?.trim();
55698
55776
  if (override) return override;
55699
55777
  const repoRoot = (0, import_node_url4.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
55700
- return path17.join(repoRoot, "skills");
55778
+ return path16.join(repoRoot, "skills");
55701
55779
  }
55702
55780
  function materializeBuiltins(builtins, runtimeKind) {
55703
55781
  if (builtins.length === 0) return {};
@@ -55731,10 +55809,10 @@ var oasisWrapperCache;
55731
55809
  function oasisWrapperScript() {
55732
55810
  if (oasisWrapperCache && fs18.existsSync(oasisWrapperCache)) return oasisWrapperCache;
55733
55811
  const repoRoot = (0, import_node_url4.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
55734
- const tsx = path17.join(repoRoot, "node_modules/.bin/tsx");
55735
- const main = path17.join(repoRoot, "packages/cli/src/main.ts");
55736
- const dir = fs18.mkdtempSync(path17.join(os8.tmpdir(), "oasis-cli-"));
55737
- const wrapper = path17.join(dir, "oasis");
55812
+ const tsx = path16.join(repoRoot, "node_modules/.bin/tsx");
55813
+ const main = path16.join(repoRoot, "packages/cli/src/main.ts");
55814
+ const dir = fs18.mkdtempSync(path16.join(os7.tmpdir(), "oasis-cli-"));
55815
+ const wrapper = path16.join(dir, "oasis");
55738
55816
  fs18.writeFileSync(wrapper, `#!/usr/bin/env bash
55739
55817
  exec ${JSON.stringify(tsx)} ${JSON.stringify(main)} "$@"
55740
55818
  `);
@@ -55826,7 +55904,7 @@ function traceRuntimeKind(runtimeKind) {
55826
55904
  async function startServe(opts) {
55827
55905
  const serverStartedAt = (/* @__PURE__ */ new Date()).toISOString();
55828
55906
  fs18.mkdirSync(opts.dir, { recursive: true });
55829
- const serverHeartbeatFile = path17.join(opts.dir, "serve-heartbeat.json");
55907
+ const serverHeartbeatFile = path16.join(opts.dir, "serve-heartbeat.json");
55830
55908
  let previousServerHeartbeatAt;
55831
55909
  if (fs18.existsSync(serverHeartbeatFile)) {
55832
55910
  try {
@@ -55842,7 +55920,7 @@ async function startServe(opts) {
55842
55920
  writeServerHeartbeat();
55843
55921
  const serverHeartbeatTimer = setInterval(writeServerHeartbeat, 5e3);
55844
55922
  serverHeartbeatTimer.unref?.();
55845
- const lock = path17.join(opts.dir, "serve.lock");
55923
+ const lock = path16.join(opts.dir, "serve.lock");
55846
55924
  if (fs18.existsSync(lock)) {
55847
55925
  const pid = Number(fs18.readFileSync(lock, "utf8"));
55848
55926
  let alive = false;
@@ -55856,15 +55934,15 @@ async function startServe(opts) {
55856
55934
  }
55857
55935
  fs18.writeFileSync(lock, String(process.pid));
55858
55936
  const loadJson = (name) => {
55859
- const file = path17.join(opts.dir, name);
55937
+ const file = path16.join(opts.dir, name);
55860
55938
  return fs18.existsSync(file) ? JSON.parse(fs18.readFileSync(file, "utf8")) : void 0;
55861
55939
  };
55862
55940
  const pgDsn = process.env["OASIS_PG_DSN"] ?? process.env["DATABASE_URL"];
55863
55941
  const pgSchema = process.env["OASIS_PG_SCHEMA"] ?? "public";
55864
55942
  const pgPool = pgDsn ? createPgPool(pgDsn) : void 0;
55865
- const oplog = pgDsn && pgPool ? await PostgresOplogStore.open(pgPool, pgSchema) : await NdjsonOplogStore.open(path17.join(opts.dir, "oplog.ndjson"));
55866
- const blobs = pgDsn && pgPool ? await PostgresBlobStore.open(pgPool, pgSchema) : new DirBlobStore(path17.join(opts.dir, "blobs"));
55867
- const assets = new DirBlobStore(path17.join(opts.dir, "assets"));
55943
+ const oplog = pgDsn && pgPool ? await PostgresOplogStore.open(pgPool, pgSchema) : await NdjsonOplogStore.open(path16.join(opts.dir, "oplog.ndjson"));
55944
+ const blobs = pgDsn && pgPool ? await PostgresBlobStore.open(pgPool, pgSchema) : new DirBlobStore(path16.join(opts.dir, "blobs"));
55945
+ const assets = new DirBlobStore(path16.join(opts.dir, "assets"));
55868
55946
  const defaultRootSchema = [
55869
55947
  { name: "brief", description: "\u5DE5\u5355\u603B\u7EB2\uFF1A\u53D1\u8D77\u65B9\u5BF9\u9F50\u7684\u603B\u76EE\u6807\u4E0E\u8303\u56F4\uFF0C\u6574\u5F20\u534F\u4F5C\u56FE\u7684\u6839\u3002", contentType: "text", ownerRole: "founder" },
55870
55948
  {
@@ -55882,7 +55960,7 @@ async function startServe(opts) {
55882
55960
  if (!schema.some((d) => d.name === "document")) {
55883
55961
  schema.push({ name: "document", description: "\u901A\u7528\u6587\u6863\uFF1A\u672A\u7EC6\u5206\u7684\u6587\u5B57\u4EA7\u7269\uFF08\u5177\u4F53\u7C7B\u578B\u89C1 docType\uFF09\u3002", contentType: "text", ownerRole: "writer" });
55884
55962
  }
55885
- const typeStore = await FileTypeRegistryStore.open(path17.join(opts.dir, "type-registry.json"));
55963
+ const typeStore = await FileTypeRegistryStore.open(path16.join(opts.dir, "type-registry.json"));
55886
55964
  if ((await typeStore.list()).length === 0) for (const d of schema) await typeStore.put(d);
55887
55965
  {
55888
55966
  const live = await typeStore.list();
@@ -55890,7 +55968,7 @@ async function startServe(opts) {
55890
55968
  schema.length = 0;
55891
55969
  schema.push(...live);
55892
55970
  }
55893
- const registryStore = pgDsn && pgPool ? await PostgresRegistryStore.open(pgPool, pgSchema) : await FileRegistryStore.open(path17.join(opts.dir, "registry-store.json"));
55971
+ const registryStore = pgDsn && pgPool ? await PostgresRegistryStore.open(pgPool, pgSchema) : await FileRegistryStore.open(path16.join(opts.dir, "registry-store.json"));
55894
55972
  try {
55895
55973
  await backfillSkillContentFromAssets(registryStore, assets);
55896
55974
  } catch (err) {
@@ -55914,14 +55992,14 @@ async function startServe(opts) {
55914
55992
  // per-contentType merge facet(§5.6):text=expensive→group-commit、code/structured=cheap→顺序 rebase
55915
55993
  handlers: defaultHandlersByContentType()
55916
55994
  });
55917
- const issuer = createTokenIssuer({ secretFile: path17.join(opts.dir, "session-token-secret") });
55918
- const operatorActor = `actor:human:${os8.userInfo().username}`;
55995
+ const issuer = createTokenIssuer({ secretFile: path16.join(opts.dir, "session-token-secret") });
55996
+ const operatorActor = `actor:human:${os7.userInfo().username}`;
55919
55997
  const operatorToken = issuer.issue(operatorActor);
55920
- fs18.writeFileSync(path17.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
55921
- let nodeTokens = createNodeTokenStore(path17.join(opts.dir, "node-tokens.json"));
55922
- const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3, path17.join(opts.dir, "enroll-tokens.json"));
55923
- let nodeStore = await FileNodeStore.open(path17.join(opts.dir, "nodes.json"));
55924
- const registryAuditFile = path17.join(opts.dir, "registry-audit.ndjson");
55998
+ fs18.writeFileSync(path16.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
55999
+ let nodeTokens = createNodeTokenStore(path16.join(opts.dir, "node-tokens.json"));
56000
+ const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3, path16.join(opts.dir, "enroll-tokens.json"));
56001
+ let nodeStore = await FileNodeStore.open(path16.join(opts.dir, "nodes.json"));
56002
+ const registryAuditFile = path16.join(opts.dir, "registry-audit.ndjson");
55925
56003
  const registryListeners = /* @__PURE__ */ new Set();
55926
56004
  const registryAudit = (record5) => {
55927
56005
  fs18.appendFile(registryAuditFile, JSON.stringify(record5) + "\n", () => {
@@ -55963,9 +56041,9 @@ async function startServe(opts) {
55963
56041
  nodeTokens = await PostgresNodeTokenStore.open(pgPool, pgSchema);
55964
56042
  console.log(`[serve] \u4E8B\u5B9E/\u72B6\u6001\u4F53\u7CFB\uFF1APostgres schema=${pgSchema}\uFF08oplog / registry / blobs / artifacts / chat\uFF09`);
55965
56043
  } else {
55966
- projectStateStore = await FileProjectStateStore.open(path17.join(opts.dir, "artifact-document-projects.json"));
55967
- artifactStateStore = await FileArtifactStateStore.open(path17.join(opts.dir, "artifact-document-state.json"));
55968
- chatSessionStore = await FileChatSessionStore.open(path17.join(opts.dir, "chat-sessions.json"));
56044
+ projectStateStore = await FileProjectStateStore.open(path16.join(opts.dir, "artifact-document-projects.json"));
56045
+ artifactStateStore = await FileArtifactStateStore.open(path16.join(opts.dir, "artifact-document-state.json"));
56046
+ chatSessionStore = await FileChatSessionStore.open(path16.join(opts.dir, "chat-sessions.json"));
55969
56047
  console.log("[serve] \u4EA4\u4ED8\u7269\u72B6\u6001\u4F53\u7CFB\uFF1A\u672C\u5730 JSON dev store");
55970
56048
  console.log("[serve] \u8282\u70B9/\u8FD0\u884C\u65F6\u4F53\u7CFB\uFF1A\u672C\u5730 JSON dev store");
55971
56049
  }
@@ -55984,7 +56062,7 @@ async function startServe(opts) {
55984
56062
  });
55985
56063
  console.log(`[serve] \u9879\u76EE\u6587\u6863\u4F53\u7CFB\uFF1AOutline ${outlineUrl}\uFF08\u6302\u5728 Team Workspace\u300C\u9879\u76EE\u300D\u4E0B\uFF09`);
55986
56064
  } else {
55987
- projectDocumentStore = await FileProjectDocumentStore.open(path17.join(opts.dir, "project-document-spaces.json"));
56065
+ projectDocumentStore = await FileProjectDocumentStore.open(path16.join(opts.dir, "project-document-spaces.json"));
55988
56066
  console.log("[serve] \u9879\u76EE\u6587\u6863\u4F53\u7CFB\uFF1A\u672C\u5730\u5185\u5B58/\u6587\u4EF6 dev store");
55989
56067
  }
55990
56068
  const registryActorNames = /* @__PURE__ */ new Map();
@@ -56018,7 +56096,7 @@ async function startServe(opts) {
56018
56096
  traceStore = await PostgresTraceStore.open(tracePool, pgSchema);
56019
56097
  console.log(`[serve] \u8FD0\u884C\u8F68\u8FF9\u4F53\u7CFB\uFF1APostgres schema=${pgSchema}${traceDsn === pgDsn ? "" : "\uFF08\u72EC\u7ACB trace \u5E93\uFF09"}`);
56020
56098
  } else {
56021
- traceStore = await FileTraceStore.open(path17.join(opts.dir, "trace"));
56099
+ traceStore = await FileTraceStore.open(path16.join(opts.dir, "trace"));
56022
56100
  console.log("[serve] \u8FD0\u884C\u8F68\u8FF9\u4F53\u7CFB\uFF1A\u672C\u5730 ndjson dev store");
56023
56101
  }
56024
56102
  traceStoreForActors = traceStore;
@@ -56039,7 +56117,7 @@ async function startServe(opts) {
56039
56117
  create: createSeededWorkorder,
56040
56118
  projectExists: async (id) => Boolean(await projectStateStore.getProject(id))
56041
56119
  });
56042
- const controlPlaneStore = pgDsn && pgPool ? await PostgresControlPlaneStore.open(pgPool, pgSchema) : await FileControlPlaneStore.open(path17.join(opts.dir, "control-plane.json"));
56120
+ const controlPlaneStore = pgDsn && pgPool ? await PostgresControlPlaneStore.open(pgPool, pgSchema) : await FileControlPlaneStore.open(path16.join(opts.dir, "control-plane.json"));
56043
56121
  if (pgDsn && pgPool) {
56044
56122
  const priceStore = await PostgresModelPriceStore.open(pgPool, pgSchema);
56045
56123
  setModelPriceCacheLoader(async () => {
@@ -56128,8 +56206,8 @@ async function startServe(opts) {
56128
56206
  }
56129
56207
  return auth.sessionAccountId(headers);
56130
56208
  };
56131
- const workorderDrafts = new WorkorderDraftStore(path17.join(opts.dir, "workorder-drafts.json"));
56132
- const journalFile = path17.join(opts.dir, "dispatch-journal.ndjson");
56209
+ const workorderDrafts = new WorkorderDraftStore(path16.join(opts.dir, "workorder-drafts.json"));
56210
+ const journalFile = path16.join(opts.dir, "dispatch-journal.ndjson");
56133
56211
  const journalRing = [];
56134
56212
  if (fs18.existsSync(journalFile)) {
56135
56213
  try {
@@ -56173,7 +56251,7 @@ async function startServe(opts) {
56173
56251
  defaultEngine: { kernel, oplog, blobs, registry: registryStore, assets },
56174
56252
  defaultCompanyId,
56175
56253
  buildEngine: async (companyId) => {
56176
- const engine2 = await openFileEngine(path17.join(opts.dir, "companies", companyEngineDirName(companyId)), { schema });
56254
+ const engine2 = await openFileEngine(path16.join(opts.dir, "companies", companyEngineDirName(companyId)), { schema });
56177
56255
  await ensureCompanyActors(controlPlaneStore, companyId, engine2.registry);
56178
56256
  await syncRegistryRolesToKernel(engine2.registry, engine2.kernel);
56179
56257
  return engine2;
@@ -56290,7 +56368,7 @@ async function startServe(opts) {
56290
56368
  }));
56291
56369
  }
56292
56370
  const limits = { wallClockMs: SESSION_WALL_CLOCK_MS.planner };
56293
- const artifactId = `artifact:planner:${(0, import_node_crypto25.randomUUID)()}`;
56371
+ const artifactId = `artifact:planner:${(0, import_node_crypto24.randomUUID)()}`;
56294
56372
  const handle = await chatRemoteAdapter.spawn({
56295
56373
  actor: planner.id,
56296
56374
  actorToken: issueSessionToken(planner.id, { artifactId, action: "plan-workorder", limits, binding }),
@@ -56318,7 +56396,7 @@ async function startServe(opts) {
56318
56396
  resolveCodeRepo: (ws) => resolveCodeRepoRef?.(ws) ?? null,
56319
56397
  // B3 auto-merge(§9.7):part propose 时把工作分支合进伞分支的兜底 mirror 根——与 GitSyncWorker/CiGate
56320
56398
  // 的 git-mirrors **分开**(各自 checkout 不同分支,共享 clone 会竞态)。
56321
- gitMirrorRoot: path17.join(opts.dir, "propose-mirrors"),
56399
+ gitMirrorRoot: path16.join(opts.dir, "propose-mirrors"),
56322
56400
  domains: [
56323
56401
  actors.register,
56324
56402
  companies.register,
@@ -56401,8 +56479,8 @@ async function startServe(opts) {
56401
56479
  },
56402
56480
  retainedSession: (key) => key.annotationId && key.artifactId ? allDispatchers().map((d) => d.retainedProduceSessionFor(key.artifactId)).find(Boolean) : coordinatorRef?.retainedSessionFor(key),
56403
56481
  // 0030 D3/D7 落盘:discuss 按项表写文件,serve 重启后同一卡点续同一段、不再新开。
56404
- discussSessions: new FileSideMap(path17.join(opts.dir, "discuss-sessions.json")),
56405
- escalateDiscussRetain: new FileSideMap(path17.join(opts.dir, "escalate-discuss-retain.json")),
56482
+ discussSessions: new FileSideMap(path16.join(opts.dir, "discuss-sessions.json")),
56483
+ escalateDiscussRetain: new FileSideMap(path16.join(opts.dir, "escalate-discuss-retain.json")),
56406
56484
  // 切片 2b:代署 escalate 发起会话保留(落盘)
56407
56485
  dispatchChat: async ({ actorId, message, sessionId, chatSessionId, attachments, workspace, companyId }) => {
56408
56486
  const runCompanyId = companyId ?? defaultCompanyId;
@@ -56425,10 +56503,10 @@ async function startServe(opts) {
56425
56503
  if (!localUrl) {
56426
56504
  throw new ApiError(503, "SERVER_URL_NOT_READY", "server URL \u5C1A\u672A\u5C31\u7EEA");
56427
56505
  }
56428
- const runtimeSessionId = sessionId ?? (0, import_node_crypto25.randomUUID)();
56506
+ const runtimeSessionId = sessionId ?? (0, import_node_crypto24.randomUUID)();
56429
56507
  const resumeRuntimeSession = Boolean(sessionId);
56430
- const traceRunId = `chat-run:${(0, import_node_crypto25.randomUUID)()}`;
56431
- const artifactId = `artifact:chat:${(0, import_node_crypto25.randomUUID)()}`;
56508
+ const traceRunId = `chat-run:${(0, import_node_crypto24.randomUUID)()}`;
56509
+ const artifactId = `artifact:chat:${(0, import_node_crypto24.randomUUID)()}`;
56432
56510
  const traceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
56433
56511
  let traceSeq = 0;
56434
56512
  let lastProgressTouchMs = 0;
@@ -56707,7 +56785,7 @@ ${detail}` : genericLine));
56707
56785
  console.log(`[serve] \u8FDC\u7A0B agent API URL\uFF1A${remoteApiUrl ?? "\u672A\u914D\u7F6E\uFF08\u4EC5\u652F\u6301\u672C\u673A runtime\uFF09"}`);
56708
56786
  const projectsCfg = loadJson("projects.json");
56709
56787
  const seedProjects = (projectsCfg?.projects ?? []).map(
56710
- (p2) => p2.repos?.length ? { ...p2, repos: p2.repos.map((r) => r.repoDir ? { ...r, repoDir: path17.resolve(opts.dir, r.repoDir) } : r) } : p2
56788
+ (p2) => p2.repos?.length ? { ...p2, repos: p2.repos.map((r) => r.repoDir ? { ...r, repoDir: path16.resolve(opts.dir, r.repoDir) } : r) } : p2
56711
56789
  );
56712
56790
  for (const sp of seedProjects) {
56713
56791
  const existing = await projectStateStore.getProject(sp.id);
@@ -56837,8 +56915,8 @@ ${detail}` : genericLine));
56837
56915
  // 每 agent 并发产出上限默认 5(工单数 / 全局总量默认不限);--max-produce-per-agent N 覆盖。
56838
56916
  maxConcurrentProducePerActor: opts.maxConcurrentProducePerActor ?? 5,
56839
56917
  // 提案 uniform-annotation-resolve ③/④ 落盘:容错计数 + produce 会话号(重启不丢;丢了也只是降级/多容错一轮)
56840
- annotationRescue: new FileSideMap(path17.join(opts.dir, `annotation-rescue.${companyId}.json`)),
56841
- produceSessions: new FileSideMap(path17.join(opts.dir, `produce-sessions.${companyId}.json`))
56918
+ annotationRescue: new FileSideMap(path16.join(opts.dir, `annotation-rescue.${companyId}.json`)),
56919
+ produceSessions: new FileSideMap(path16.join(opts.dir, `produce-sessions.${companyId}.json`))
56842
56920
  });
56843
56921
  const slot = { dispatcher: d, logged: 0, ticking: false };
56844
56922
  dispatchers.set(companyId, slot);
@@ -57024,7 +57102,7 @@ ${detail}` : genericLine));
57024
57102
  schema: schemaMap,
57025
57103
  mirrors: new Map(opts.mirror.connectors.map((c) => [c.platform, c])),
57026
57104
  identities: opts.mirror.identities ?? new MapMirrorIdentities(),
57027
- state: new FsMirrorStateStore(path17.join(opts.dir, "mirror-state.json")),
57105
+ state: new FsMirrorStateStore(path16.join(opts.dir, "mirror-state.json")),
57028
57106
  ...opts.mirror.debounceMs !== void 0 ? { debounceMs: opts.mirror.debounceMs } : {},
57029
57107
  log: (m2) => console.log(m2)
57030
57108
  });
@@ -57034,27 +57112,20 @@ ${detail}` : genericLine));
57034
57112
  }
57035
57113
  let gitTimer;
57036
57114
  if (opts.dispatch) {
57037
- if (ciGateEnabled) {
57038
- const ci = new GhCiProvider({
57039
- mirrorRoot: path17.join(opts.dir, "git-mirrors"),
57040
- failClosedWhenNoChecks: process.env["OASIS_CI_FAIL_CLOSED"] === "1",
57041
- log: (m2) => console.log(m2)
57042
- });
57043
- const ciGate = new CiGateWorker({ kernel, resolveProject, ci, statusSink: ciGateStatus, log: (m2) => console.log(m2) });
57044
- gitTimer = setInterval(() => {
57045
- void ciGate.tick().catch((err) => console.error(`[ci] tick \u5931\u8D25: ${String(err)}`));
57046
- }, 3e4);
57047
- } else {
57048
- const gitSync = new GitSyncWorker({
57049
- kernel,
57050
- resolveProject,
57051
- mirrorRoot: path17.join(opts.dir, "git-mirrors"),
57052
- log: (m2) => console.log(m2)
57053
- });
57054
- gitTimer = setInterval(() => {
57055
- void gitSync.tick().catch((err) => console.error(`[git] \u540C\u6B65\u5931\u8D25: ${String(err)}`));
57056
- }, 3e4);
57057
- }
57115
+ const gitMirrorRoot = path16.join(opts.dir, "git-mirrors");
57116
+ const ci = new GhCiProvider({
57117
+ mirrorRoot: gitMirrorRoot,
57118
+ failClosedWhenNoChecks: process.env["OASIS_CI_FAIL_CLOSED"] === "1",
57119
+ log: (m2) => console.log(m2)
57120
+ });
57121
+ const mergeWorker = new MergeWorker({ kernel, resolveProject, ci, mirrorRoot: gitMirrorRoot, statusSink: ciGateStatus, log: (m2) => console.log(m2) });
57122
+ const ciGate = ciGateEnabled ? new CiGateWorker({ kernel, resolveProject, ci, statusSink: ciGateStatus, log: (m2) => console.log(m2) }) : void 0;
57123
+ gitTimer = setInterval(() => {
57124
+ void (async () => {
57125
+ if (ciGate) await ciGate.tick().catch((err) => console.error(`[ci] tick \u5931\u8D25: ${String(err)}`));
57126
+ await mergeWorker.tick().catch((err) => console.error(`[merge] tick \u5931\u8D25: ${String(err)}`));
57127
+ })();
57128
+ }, 3e4);
57058
57129
  }
57059
57130
  let coordTimer;
57060
57131
  let livenessTimer;
@@ -57109,7 +57180,7 @@ ${detail}` : genericLine));
57109
57180
  // 病历里展示节点的"在跑会话情况"(runId + 跑了多久):从派发器在途会话按 artifactId 过滤。
57110
57181
  sessionsOf: (id) => allDispatchers().flatMap((d) => d.inFlightSessions()).filter((s2) => s2.artifactId === id).map((s2) => ({ runId: s2.sessionId, action: s2.action, startedAt: s2.startedAt })),
57111
57182
  log: (m2) => console.log(m2),
57112
- retention: new FileSideMap(path17.join(opts.dir, "retained-sessions.json"))
57183
+ retention: new FileSideMap(path16.join(opts.dir, "retained-sessions.json"))
57113
57184
  // 0030 D7 落盘
57114
57185
  });
57115
57186
  coordinatorRef = coordinator;
@@ -57653,7 +57724,7 @@ async function startNode(opts) {
57653
57724
  // ../cli/src/daemon/machine-id.ts
57654
57725
  var import_node_child_process14 = require("node:child_process");
57655
57726
  var import_node_fs6 = require("node:fs");
57656
- var import_node_crypto26 = require("node:crypto");
57727
+ var import_node_crypto25 = require("node:crypto");
57657
57728
  var import_node_os7 = require("node:os");
57658
57729
  function linuxMachineId() {
57659
57730
  for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
@@ -57719,7 +57790,7 @@ var defaultSources = {
57719
57790
  function resolveNodeId(sources = {}) {
57720
57791
  const s2 = { ...defaultSources, ...sources };
57721
57792
  const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
57722
- const digest = (0, import_node_crypto26.createHash)("sha256").update(material).digest("hex").slice(0, 12);
57793
+ const digest = (0, import_node_crypto25.createHash)("sha256").update(material).digest("hex").slice(0, 12);
57723
57794
  return `node-${digest}`;
57724
57795
  }
57725
57796
 
@@ -57889,8 +57960,8 @@ function makeClient(base, token) {
57889
57960
  if (!res.ok) await fail(res);
57890
57961
  return (await res.json()).data;
57891
57962
  },
57892
- async request(method, path20, body) {
57893
- const res = await fetch(`${base}${path20}`, {
57963
+ async request(method, path19, body) {
57964
+ const res = await fetch(`${base}${path19}`, {
57894
57965
  method,
57895
57966
  headers,
57896
57967
  ...body !== void 0 ? { body: JSON.stringify(body) } : {}
@@ -57898,8 +57969,8 @@ function makeClient(base, token) {
57898
57969
  if (!res.ok) await fail(res);
57899
57970
  return await res.json();
57900
57971
  },
57901
- async post(path20, body) {
57902
- const res = await fetch(`${base}${path20}`, { method: "POST", headers, body: JSON.stringify(body) });
57972
+ async post(path19, body) {
57973
+ const res = await fetch(`${base}${path19}`, { method: "POST", headers, body: JSON.stringify(body) });
57903
57974
  if (!res.ok) await fail(res);
57904
57975
  return await res.json();
57905
57976
  }
@@ -57912,14 +57983,14 @@ async function runCli(argv, println = console.log) {
57912
57983
  return;
57913
57984
  }
57914
57985
  const { positional, flags } = parseArgs(rest);
57915
- const dir = flags.get("dir") ?? process.env["OASIS_DIR"] ?? path18.resolve(".oasis");
57986
+ const dir = flags.get("dir") ?? process.env["OASIS_DIR"] ?? path17.resolve(".oasis");
57916
57987
  if (command === "node" && positional[0] !== "output") {
57917
57988
  const serverUrl = flags.get("server-ws") ?? process.env["OASIS_SERVER_WS"] ?? "ws://127.0.0.1:7320/node-gateway";
57918
57989
  const nodeName = flags.get("name") ?? process.env["OASIS_NODE_NAME"];
57919
- const nodeIdFile = path18.join(dir, "node-id");
57920
- const nodeTokenFile = path18.join(dir, "node-token");
57921
- const enrollTokenFile = path18.join(dir, "enroll-token");
57922
- const reportMarkerFile = path18.join(dir, "report-runtimes");
57990
+ const nodeIdFile = path17.join(dir, "node-id");
57991
+ const nodeTokenFile = path17.join(dir, "node-token");
57992
+ const enrollTokenFile = path17.join(dir, "enroll-token");
57993
+ const reportMarkerFile = path17.join(dir, "report-runtimes");
57923
57994
  const persistedNodeId = fs19.existsSync(nodeIdFile) ? fs19.readFileSync(nodeIdFile, "utf8").trim() : null;
57924
57995
  let nodeId = persistedNodeId || resolveNodeId();
57925
57996
  let token2 = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? (fs19.existsSync(nodeTokenFile) ? fs19.readFileSync(nodeTokenFile, "utf8").trim() : void 0);
@@ -57930,7 +58001,7 @@ async function runCli(argv, println = console.log) {
57930
58001
  const res = await fetch(`${httpBase2}/api/nodes/exchange`, {
57931
58002
  method: "POST",
57932
58003
  headers: { "content-type": "application/json" },
57933
- body: JSON.stringify({ enrollToken, nodeId, hostname: os9.hostname() })
58004
+ body: JSON.stringify({ enrollToken, nodeId, hostname: os8.hostname() })
57934
58005
  });
57935
58006
  if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
57936
58007
  const body = await res.json();
@@ -57960,11 +58031,11 @@ async function runCli(argv, println = console.log) {
57960
58031
  println("\u2192 Installing oasis_test globally...");
57961
58032
  spawnSync("npm", ["install", "-g", "oasis_test@latest"], { stdio: "inherit" });
57962
58033
  const prefix = execSync2("npm prefix -g").toString().trim();
57963
- const binPath = path18.join(prefix, "bin", "oasis_test");
58034
+ const binPath = path17.join(prefix, "bin", "oasis_test");
57964
58035
  const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
57965
58036
  if (process.platform === "linux") {
57966
- const svcFile = path18.join(os9.homedir(), ".config/systemd/user/oasis-node.service");
57967
- fs19.mkdirSync(path18.dirname(svcFile), { recursive: true });
58037
+ const svcFile = path17.join(os8.homedir(), ".config/systemd/user/oasis-node.service");
58038
+ fs19.mkdirSync(path17.dirname(svcFile), { recursive: true });
57968
58039
  if (spawnSync("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
57969
58040
  spawnSync("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
57970
58041
  fs19.writeFileSync(svcFile, [
@@ -57976,7 +58047,7 @@ async function runCli(argv, println = console.log) {
57976
58047
  `ExecStart=${binPath} ${svcArgs}`,
57977
58048
  // Carry the install-time PATH so the detached daemon detects CLIs in user dirs
57978
58049
  // (~/.npm-global/bin, ~/.local/bin) — systemd --user otherwise gives a minimal PATH.
57979
- `Environment=PATH=${process.env["PATH"] ?? ""}:${path18.join(os9.homedir(), ".npm-global/bin")}:${path18.join(os9.homedir(), ".local/bin")}:/usr/local/bin`,
58050
+ `Environment=PATH=${process.env["PATH"] ?? ""}:${path17.join(os8.homedir(), ".npm-global/bin")}:${path17.join(os8.homedir(), ".local/bin")}:/usr/local/bin`,
57980
58051
  "Restart=on-failure",
57981
58052
  "RestartSec=5",
57982
58053
  "StandardOutput=journal",
@@ -57988,23 +58059,23 @@ async function runCli(argv, println = console.log) {
57988
58059
  ].join("\n"));
57989
58060
  spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
57990
58061
  spawnSync("systemctl", ["--user", "enable", "--now", "oasis-node"], { stdio: "inherit" });
57991
- spawnSync("loginctl", ["enable-linger", os9.userInfo().username], { stdio: "ignore" });
58062
+ spawnSync("loginctl", ["enable-linger", os8.userInfo().username], { stdio: "ignore" });
57992
58063
  println("\u2713 Oasis node service started (systemd --user oasis-node)");
57993
58064
  println(" Status : systemctl --user status oasis-node");
57994
58065
  println(" Logs : journalctl --user -u oasis-node -f");
57995
58066
  println(" Stop : systemctl --user stop oasis-node");
57996
58067
  } else if (process.platform === "darwin") {
57997
- const plist = path18.join(os9.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
57998
- fs19.mkdirSync(path18.dirname(plist), { recursive: true });
58068
+ const plist = path17.join(os8.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
58069
+ fs19.mkdirSync(path17.dirname(plist), { recursive: true });
57999
58070
  spawnSync("launchctl", ["unload", plist], { stdio: "ignore" });
58000
58071
  const argXml = [binPath, "node", "--server-ws", serverUrl, "--dir", dir, ...nodeName ? ["--name", nodeName] : []].map((a) => `<string>${a}</string>`).join("");
58001
- fs19.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>${os9.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os9.homedir()}/.oasis-node.err</string></dict></plist>`);
58072
+ fs19.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>`);
58002
58073
  spawnSync("launchctl", ["load", plist], { stdio: "inherit" });
58003
58074
  println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
58004
- println(` Logs : tail -f ${os9.homedir()}/.oasis-node.log`);
58075
+ println(` Logs : tail -f ${os8.homedir()}/.oasis-node.log`);
58005
58076
  println(` Stop : launchctl unload ${plist}`);
58006
58077
  } else {
58007
- spawnSync("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path18.join(os9.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
58078
+ spawnSync("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path17.join(os8.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
58008
58079
  println(`\u2713 Oasis node started in background (nohup). Logs: ~/.oasis-node.log`);
58009
58080
  println(" Note: no automatic restart on reboot in this environment.");
58010
58081
  }
@@ -58020,14 +58091,14 @@ async function runCli(argv, println = console.log) {
58020
58091
  return;
58021
58092
  }
58022
58093
  if (command === "node-token") {
58023
- const store = createNodeTokenStore(path18.join(dir, "node-tokens.json"));
58094
+ const store = createNodeTokenStore(path17.join(dir, "node-tokens.json"));
58024
58095
  const sub = positional[0];
58025
58096
  if (sub === "issue") {
58026
- const id = flags.get("id") ?? `node-${(0, import_node_crypto27.randomUUID)()}`;
58097
+ const id = flags.get("id") ?? `node-${(0, import_node_crypto26.randomUUID)()}`;
58027
58098
  const token2 = store.issue(id);
58028
58099
  println(token2);
58029
58100
  process.stderr.write(
58030
- `\u5DF2\u4E3A ${id} \u7B7E\u53D1 node-token\uFF08\u5199\u5165 ${path18.join(dir, "node-tokens.json")}\uFF09\u3002
58101
+ `\u5DF2\u4E3A ${id} \u7B7E\u53D1 node-token\uFF08\u5199\u5165 ${path17.join(dir, "node-tokens.json")}\uFF09\u3002
58031
58102
  \u628A\u4E0A\u9762\u8FD9\u4E32\u653E\u5230\u8282\u70B9\u673A\uFF1A--token <t> / $OASIS_NODE_TOKEN / <\u8282\u70B9dir>/node-token
58032
58103
  `
58033
58104
  );
@@ -58048,7 +58119,7 @@ async function runCli(argv, println = console.log) {
58048
58119
  }
58049
58120
  if (command === "admin" && positional[0] === "grant-owner") {
58050
58121
  const email2 = need(flags, "email");
58051
- const store = await FileControlPlaneStore.open(path18.join(dir, "control-plane.json"));
58122
+ const store = await FileControlPlaneStore.open(path17.join(dir, "control-plane.json"));
58052
58123
  const activeCompanies = (await store.listCompanies()).filter((c) => c.status === "active");
58053
58124
  const companyId = flags.get("company") ?? activeCompanies[0]?.id ?? resolveDefaultCompanyConfig().id;
58054
58125
  const name = flags.get("name");
@@ -58061,7 +58132,7 @@ async function runCli(argv, println = console.log) {
58061
58132
  }
58062
58133
  if (command === "export-trajectories") {
58063
58134
  const { exportTrajectories: exportTrajectories2 } = await Promise.resolve().then(() => (init_trajectory(), trajectory_exports));
58064
- const samples = await exportTrajectories2(path18.resolve(dir));
58135
+ const samples = await exportTrajectories2(path17.resolve(dir));
58065
58136
  const outFile = flags.get("out");
58066
58137
  const lines = samples.map((sample) => JSON.stringify(sample)).join("\n");
58067
58138
  if (outFile !== void 0) {
@@ -58073,10 +58144,10 @@ async function runCli(argv, println = console.log) {
58073
58144
  return;
58074
58145
  }
58075
58146
  if (command === "serve" && positional[0] === "install") {
58076
- const absDir = path18.resolve(dir);
58077
- const name = `oasis-serve-${path18.basename(absDir)}`;
58078
- const unitDir = flags.get("unit-dir") ?? path18.join(os9.homedir(), ".config", "systemd", "user");
58079
- const bin = flags.get("bin") ?? path18.join(os9.homedir(), ".local", "bin", "oasis");
58147
+ const absDir = path17.resolve(dir);
58148
+ const name = `oasis-serve-${path17.basename(absDir)}`;
58149
+ const unitDir = flags.get("unit-dir") ?? path17.join(os8.homedir(), ".config", "systemd", "user");
58150
+ const bin = flags.get("bin") ?? path17.join(os8.homedir(), ".local", "bin", "oasis");
58080
58151
  const port = flags.get("port") ?? "7320";
58081
58152
  const extra = (flags.get("dispatch") === "true" ? ` --dispatch true` : "") + (flags.has("model") ? ` --model ${flags.get("model")}` : "");
58082
58153
  const unit = [
@@ -58094,7 +58165,7 @@ async function runCli(argv, println = console.log) {
58094
58165
  ``
58095
58166
  ].join("\n");
58096
58167
  fs19.mkdirSync(unitDir, { recursive: true });
58097
- const unitPath = path18.join(unitDir, `${name}.service`);
58168
+ const unitPath = path17.join(unitDir, `${name}.service`);
58098
58169
  fs19.writeFileSync(unitPath, unit);
58099
58170
  println(`\u5DF2\u5199\u5165 ${unitPath}`);
58100
58171
  println(`\u542F\u7528\uFF1Asystemctl --user daemon-reload && systemctl --user enable --now ${name}`);
@@ -58117,14 +58188,14 @@ async function runCli(argv, println = console.log) {
58117
58188
  });
58118
58189
  const port2 = new URL(handle.baseUrl).port;
58119
58190
  println(`oasis serve \u5C31\u7EEA\uFF1Ahttp://0.0.0.0:${port2}\uFF08\u672C\u673A\u8BBF\u95EE\u7528 http://127.0.0.1:${port2}\uFF09`);
58120
- println(`operator token \u5DF2\u5199\u5165 ${path18.join(dir, "operator-token")}\uFF08\u672C\u673A CLI \u81EA\u52A8\u8BFB\u53D6\uFF09`);
58191
+ println(`operator token \u5DF2\u5199\u5165 ${path17.join(dir, "operator-token")}\uFF08\u672C\u673A CLI \u81EA\u52A8\u8BFB\u53D6\uFF09`);
58121
58192
  if (flags.get("dispatch") === "true") println(`\u8C03\u5EA6\u5FAA\u73AF\u5DF2\u542F\u52A8\uFF08claude-code adapter\uFF09`);
58122
58193
  await new Promise(() => {
58123
58194
  });
58124
58195
  return;
58125
58196
  }
58126
58197
  const base = flags.get("server") ?? process.env["OASIS_SERVER"] ?? "http://127.0.0.1:7320";
58127
- const tokenFile = path18.join(dir, "operator-token");
58198
+ const tokenFile = path17.join(dir, "operator-token");
58128
58199
  const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (fs19.existsSync(tokenFile) ? fs19.readFileSync(tokenFile, "utf8").trim() : void 0);
58129
58200
  if (!token) {
58130
58201
  throw new Error(`\u65E0 token\uFF1A\u5148 oasis serve\uFF08\u4F1A\u751F\u6210 ${tokenFile}\uFF09\uFF0C\u6216\u663E\u5F0F --token / $OASIS_TOKEN`);
@@ -58149,7 +58220,7 @@ async function runCli(argv, println = console.log) {
58149
58220
  const out = [];
58150
58221
  const walk = (abs, rel) => {
58151
58222
  for (const name of fs19.readdirSync(abs)) {
58152
- const childAbs = path18.join(abs, name);
58223
+ const childAbs = path17.join(abs, name);
58153
58224
  const childRel = rel ? `${rel}/${name}` : name;
58154
58225
  if (fs19.statSync(childAbs).isDirectory()) walk(childAbs, childRel);
58155
58226
  else out.push({ path: childRel, contentBase64: fs19.readFileSync(childAbs).toString("base64") });
@@ -58501,7 +58572,7 @@ async function runCli(argv, println = console.log) {
58501
58572
  if (file !== void 0) {
58502
58573
  const bytes = fs19.readFileSync(file);
58503
58574
  const res = await api.request("POST", `/api/projects/${encodeURIComponent(projectId)}/files`, {
58504
- name: flags.get("name") ?? path18.basename(file),
58575
+ name: flags.get("name") ?? path17.basename(file),
58505
58576
  ...flags.has("path") ? { path: flags.get("path") } : {},
58506
58577
  content_base64: bytes.toString("base64"),
58507
58578
  ...flags.has("content-type") ? { content_type: flags.get("content-type") } : {}
@@ -59083,8 +59154,8 @@ ${res.warning}`);
59083
59154
  }
59084
59155
  case "content": {
59085
59156
  const id = needPos(positional, 0, "oasis content <artifactId> [path]");
59086
- const path20 = positional[1];
59087
- const c = await api.view("content", id, path20 ? { path: path20 } : void 0);
59157
+ const path19 = positional[1];
59158
+ const c = await api.view("content", id, path19 ? { path: path19 } : void 0);
59088
59159
  if (c.kind === "empty") println("\uFF08\u672C\u4EA7\u7269\u5C1A\u65E0\u5185\u5BB9\uFF09");
59089
59160
  else if (c.kind === "external-pin") println(`\u4EE3\u7801/\u5916\u90E8\u4EA4\u4ED8\u7269\uFF1A\u5185\u5BB9\u5728 git/\u5916\u90E8 \u2192 ${c.ref}\uFF08\u6309\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u91CC\u7684\u4ED3\u5E93\u6E05\u5355 clone \u53D6\uFF09`);
59090
59161
  else if (c.kind === "text") println(c.text);
@@ -59257,14 +59328,14 @@ ${res.warning}`);
59257
59328
  }
59258
59329
 
59259
59330
  // src/index.ts
59260
- var PKG_VERSION = true ? "0.1.52" : "dev";
59261
- var OASIS_DIR = path19.join(os10.homedir(), ".oasis");
59262
- var CONFIG_FILE = path19.join(OASIS_DIR, "node-config.json");
59263
- var PID_FILE = path19.join(OASIS_DIR, "node.pid");
59264
- var BIN_FILE = path19.join(OASIS_DIR, "bin", "oasis.js");
59265
- var LOCAL_BIN = path19.join(os10.homedir(), ".local", "bin", "oasis");
59266
- var LOG_FILE = path19.join(OASIS_DIR, "node.log");
59267
- var NPM_PREFIX = path19.join(OASIS_DIR, "npm-global");
59331
+ var PKG_VERSION = true ? "0.1.53" : "dev";
59332
+ var OASIS_DIR = path18.join(os9.homedir(), ".oasis");
59333
+ var CONFIG_FILE = path18.join(OASIS_DIR, "node-config.json");
59334
+ var PID_FILE = path18.join(OASIS_DIR, "node.pid");
59335
+ var BIN_FILE = path18.join(OASIS_DIR, "bin", "oasis.js");
59336
+ var LOCAL_BIN = path18.join(os9.homedir(), ".local", "bin", "oasis");
59337
+ var LOG_FILE = path18.join(OASIS_DIR, "node.log");
59338
+ var NPM_PREFIX = path18.join(OASIS_DIR, "npm-global");
59268
59339
  var PKG_NAME = "oasis_test";
59269
59340
  var parseFlags = (argv) => {
59270
59341
  const flags = /* @__PURE__ */ new Map();
@@ -59303,26 +59374,26 @@ var isRunning = (pid) => {
59303
59374
  };
59304
59375
  var httpBase = (wsUrl) => wsUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
59305
59376
  function installBinary() {
59306
- fs20.mkdirSync(path19.dirname(BIN_FILE), { recursive: true });
59377
+ fs20.mkdirSync(path18.dirname(BIN_FILE), { recursive: true });
59307
59378
  fs20.copyFileSync(process.argv[1], BIN_FILE);
59308
- fs20.mkdirSync(path19.dirname(LOCAL_BIN), { recursive: true });
59379
+ fs20.mkdirSync(path18.dirname(LOCAL_BIN), { recursive: true });
59309
59380
  fs20.writeFileSync(LOCAL_BIN, `#!/bin/sh
59310
59381
  exec node "${BIN_FILE}" "$@"
59311
59382
  `, { mode: 493 });
59312
59383
  }
59313
59384
  function setupAutostart() {
59314
59385
  const cmd = `${process.execPath} "${BIN_FILE}" --_daemon`;
59315
- const home = os10.homedir();
59386
+ const home = os9.homedir();
59316
59387
  const extraBins = [
59317
- path19.join(home, ".npm-global", "bin"),
59318
- path19.join(home, ".local", "bin"),
59388
+ path18.join(home, ".npm-global", "bin"),
59389
+ path18.join(home, ".local", "bin"),
59319
59390
  "/usr/local/bin"
59320
59391
  ];
59321
59392
  const daemonPath = [process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":");
59322
59393
  if (process.platform === "linux") {
59323
- const unitDir = path19.join(os10.homedir(), ".config", "systemd", "user");
59394
+ const unitDir = path18.join(os9.homedir(), ".config", "systemd", "user");
59324
59395
  fs20.mkdirSync(unitDir, { recursive: true });
59325
- fs20.writeFileSync(path19.join(unitDir, "oasis-node.service"), [
59396
+ fs20.writeFileSync(path18.join(unitDir, "oasis-node.service"), [
59326
59397
  "[Unit]",
59327
59398
  "Description=Oasis Node Daemon",
59328
59399
  "After=network.target",
@@ -59344,8 +59415,8 @@ function setupAutostart() {
59344
59415
  } catch {
59345
59416
  }
59346
59417
  } else if (process.platform === "darwin") {
59347
- const plist = path19.join(os10.homedir(), "Library", "LaunchAgents", "com.oasis.node.plist");
59348
- fs20.mkdirSync(path19.dirname(plist), { recursive: true });
59418
+ const plist = path18.join(os9.homedir(), "Library", "LaunchAgents", "com.oasis.node.plist");
59419
+ fs20.mkdirSync(path18.dirname(plist), { recursive: true });
59349
59420
  fs20.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
59350
59421
  <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
59351
59422
  <plist version="1.0"><dict>
@@ -59398,7 +59469,7 @@ function selfUpdate() {
59398
59469
  const cfg = readConfig();
59399
59470
  if (!cfg?.serverUrl) throw new Error("no config \u2014 run `oasis start` first");
59400
59471
  const nameArg = cfg.name ? ` --name '${cfg.name.replace(/'/g, "'\\''")}'` : "";
59401
- const oasisBin = path19.join(NPM_PREFIX, "bin", "oasis");
59472
+ const oasisBin = path18.join(NPM_PREFIX, "bin", "oasis");
59402
59473
  const startCmd = `"${oasisBin}" start --server-ws '${cfg.serverUrl}'${nameArg}`;
59403
59474
  const inner = `{ echo "[oasis] self-update \u2192 npm install --prefix ${NPM_PREFIX} ${PKG_NAME}@latest"; sleep 2; npm install -g --prefer-online --prefix '${NPM_PREFIX}' '${PKG_NAME}@latest' && ${startCmd}; } >> '${LOG_FILE}' 2>&1`;
59404
59475
  const hasSystemd = process.platform === "linux" && (() => {
@@ -59498,7 +59569,7 @@ void (async () => {
59498
59569
  const res = await fetch(`${httpBase(serverUrl)}/api/nodes/exchange`, {
59499
59570
  method: "POST",
59500
59571
  headers: { "content-type": "application/json" },
59501
- body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os10.hostname() })
59572
+ body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os9.hostname() })
59502
59573
  });
59503
59574
  if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
59504
59575
  const body = await res.json();
@@ -59521,7 +59592,7 @@ void (async () => {
59521
59592
  const pid = spawnDaemon();
59522
59593
  console.log(`\u2713 daemon started (PID ${pid})${nameChanged ? ` [name updated: ${prev.name} \u2192 ${name}]` : ""}`);
59523
59594
  console.log(` logs: tail -f ${LOG_FILE}`);
59524
- if (!process.env["PATH"]?.includes(path19.dirname(LOCAL_BIN)))
59595
+ if (!process.env["PATH"]?.includes(path18.dirname(LOCAL_BIN)))
59525
59596
  console.log(` add to PATH: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc`);
59526
59597
  return;
59527
59598
  }