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.
- package/dist/index.js +905 -834
- 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
|
|
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 ` + (
|
|
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
|
|
2026
|
+
const path19 = this.pathForStaleHead(artifact, queue);
|
|
2027
2027
|
return {
|
|
2028
2028
|
landed,
|
|
2029
2029
|
blockedHead: {
|
|
2030
2030
|
revision: head,
|
|
2031
|
-
path:
|
|
2032
|
-
hint:
|
|
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,
|
|
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
|
|
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 [
|
|
4849
|
-
const repo =
|
|
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
|
|
5027
|
+
var import_node_child_process2;
|
|
4858
5028
|
var init_collect = __esm({
|
|
4859
5029
|
"../server/src/git/collect.ts"() {
|
|
4860
5030
|
"use strict";
|
|
4861
|
-
|
|
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
|
|
4873
|
-
const
|
|
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
|
-
|
|
4877
|
-
|
|
4878
|
-
(0,
|
|
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 (!
|
|
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,
|
|
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
|
|
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
|
-
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
|
|
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:
|
|
5365
|
-
const fullPath = [...
|
|
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,
|
|
5843
|
+
constructor(parent, value, path19, key) {
|
|
5674
5844
|
this._cachedPath = [];
|
|
5675
5845
|
this.parent = parent;
|
|
5676
5846
|
this.data = value;
|
|
5677
|
-
this._path =
|
|
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,
|
|
9252
|
-
if (!
|
|
9421
|
+
function getElementAtPath(obj, path19) {
|
|
9422
|
+
if (!path19)
|
|
9253
9423
|
return obj;
|
|
9254
|
-
return
|
|
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(
|
|
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(
|
|
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(
|
|
18048
|
-
let input =
|
|
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 [
|
|
18301
|
-
wsComponent.path =
|
|
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,
|
|
21815
|
-
this.routes.push({ method, segments:
|
|
21984
|
+
on(method, path19, handler) {
|
|
21985
|
+
this.routes.push({ method, segments: path19.split("/").filter(Boolean), handler });
|
|
21816
21986
|
}
|
|
21817
|
-
get(
|
|
21818
|
-
this.on("GET",
|
|
21987
|
+
get(path19, h) {
|
|
21988
|
+
this.on("GET", path19, h);
|
|
21819
21989
|
}
|
|
21820
|
-
post(
|
|
21821
|
-
this.on("POST",
|
|
21990
|
+
post(path19, h) {
|
|
21991
|
+
this.on("POST", path19, h);
|
|
21822
21992
|
}
|
|
21823
|
-
patch(
|
|
21824
|
-
this.on("PATCH",
|
|
21993
|
+
patch(path19, h) {
|
|
21994
|
+
this.on("PATCH", path19, h);
|
|
21825
21995
|
}
|
|
21826
|
-
put(
|
|
21827
|
-
this.on("PUT",
|
|
21996
|
+
put(path19, h) {
|
|
21997
|
+
this.on("PUT", path19, h);
|
|
21828
21998
|
}
|
|
21829
|
-
delete(
|
|
21830
|
-
this.on("DELETE",
|
|
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
|
|
22300
|
-
const briefId = `artifact:brief:${
|
|
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}:${
|
|
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}:${
|
|
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
|
|
23863
|
-
const feat = `feat/${
|
|
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/${
|
|
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
|
|
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 (
|
|
24598
|
-
const e = entries.find((x2) => x2.path ===
|
|
24599
|
-
if (!e) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${
|
|
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:
|
|
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
|
|
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
|
|
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:
|
|
25563
|
-
const { tmpdir:
|
|
25564
|
-
const dir = mkdtempSync9(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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(
|
|
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(
|
|
26216
|
+
return JSON.parse(fs4.readFileSync(file, "utf8"));
|
|
26041
26217
|
} catch {
|
|
26042
26218
|
return {};
|
|
26043
26219
|
}
|
|
26044
26220
|
};
|
|
26045
|
-
const write = (table) =>
|
|
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,
|
|
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(
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
26126
|
-
|
|
26127
|
-
|
|
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,
|
|
26308
|
+
if (!file) return (0, import_node_crypto3.randomBytes)(32);
|
|
26133
26309
|
try {
|
|
26134
|
-
const raw =
|
|
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,
|
|
26139
|
-
|
|
26140
|
-
|
|
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,
|
|
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,
|
|
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(
|
|
27171
|
+
async getCompanyBySlug(slug4) {
|
|
26996
27172
|
for (const c of this.companies.values()) {
|
|
26997
|
-
if (c.slug ===
|
|
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
|
|
27493
|
-
return `proj_${
|
|
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
|
|
27924
|
-
const content = space.files.get(
|
|
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)}/${
|
|
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
|
|
28014
|
-
space.files.set(
|
|
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
|
|
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
|
-
|
|
28719
|
-
|
|
28720
|
-
|
|
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 (
|
|
28733
|
-
for (const line of
|
|
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
|
-
|
|
28742
|
-
|
|
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
|
-
|
|
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
|
-
|
|
28941
|
+
fs5.mkdirSync(dir, { recursive: true });
|
|
28766
28942
|
}
|
|
28767
28943
|
fileOf(hash) {
|
|
28768
|
-
return
|
|
28944
|
+
return path4.join(this.dir, hash);
|
|
28769
28945
|
}
|
|
28770
28946
|
async put(bytes) {
|
|
28771
|
-
const hash = (0,
|
|
28947
|
+
const hash = (0, import_node_crypto4.createHash)("sha256").update(bytes).digest("hex");
|
|
28772
28948
|
const file = this.fileOf(hash);
|
|
28773
|
-
if (!
|
|
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 (!
|
|
28779
|
-
const size =
|
|
28780
|
-
const fd =
|
|
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
|
-
|
|
28783
|
-
|
|
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 (!
|
|
28790
|
-
return new Uint8Array(
|
|
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
|
|
28969
|
+
return fs5.existsSync(this.fileOf(hash));
|
|
28794
28970
|
}
|
|
28795
28971
|
async sweep(reachable) {
|
|
28796
|
-
for (const name of
|
|
28797
|
-
if (!reachable.has(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 =
|
|
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
|
-
|
|
28839
|
-
|
|
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 (
|
|
28858
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
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 (
|
|
28910
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
28923
|
-
|
|
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
|
-
|
|
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 (
|
|
28953
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
28968
|
-
|
|
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
|
-
|
|
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 (
|
|
29012
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
29022
|
-
|
|
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
|
-
|
|
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
|
|
29240
|
+
return path4.join(this.dir, "runs.ndjson");
|
|
29065
29241
|
}
|
|
29066
29242
|
get toolCallsFile() {
|
|
29067
|
-
return
|
|
29243
|
+
return path4.join(this.dir, "tool-calls.ndjson");
|
|
29068
29244
|
}
|
|
29069
29245
|
get linksFile() {
|
|
29070
|
-
return
|
|
29246
|
+
return path4.join(this.dir, "links.ndjson");
|
|
29071
29247
|
}
|
|
29072
29248
|
get artifactsFile() {
|
|
29073
|
-
return
|
|
29249
|
+
return path4.join(this.dir, "artifacts.ndjson");
|
|
29074
29250
|
}
|
|
29075
29251
|
get eventsDir() {
|
|
29076
|
-
return
|
|
29252
|
+
return path4.join(this.dir, "events");
|
|
29077
29253
|
}
|
|
29078
29254
|
eventsFile(runId) {
|
|
29079
|
-
return
|
|
29255
|
+
return path4.join(this.eventsDir, `${encodeURIComponent(runId)}.ndjson`);
|
|
29080
29256
|
}
|
|
29081
29257
|
appendLine(file, obj) {
|
|
29082
|
-
|
|
29258
|
+
fs5.appendFileSync(file, JSON.stringify(obj) + "\n");
|
|
29083
29259
|
}
|
|
29084
29260
|
static replay(file, fn) {
|
|
29085
|
-
if (!
|
|
29086
|
-
for (const line of
|
|
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
|
-
|
|
29269
|
+
fs5.mkdirSync(store.eventsDir, { recursive: true });
|
|
29094
29270
|
_FileTraceStore.replay(store.runsFile, (r) => store.restoreRun(r));
|
|
29095
|
-
for (const name of
|
|
29096
|
-
_FileTraceStore.replay(
|
|
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 (
|
|
29200
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
29206
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
29253
|
-
|
|
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 (
|
|
29282
|
-
const snap = JSON.parse(
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
29670
|
-
const dk = (0,
|
|
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,
|
|
29688
|
-
return dk.length === expected.length && (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
29894
|
+
return String((0, import_node_crypto5.randomInt)(0, 1e6)).padStart(6, "0");
|
|
29719
29895
|
}
|
|
29720
29896
|
function hashCode(code, secret) {
|
|
29721
|
-
return (0,
|
|
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,
|
|
29902
|
+
return ba.length === bb.length && (0, import_node_crypto5.timingSafeEqual)(ba, bb);
|
|
29727
29903
|
}
|
|
29728
|
-
var
|
|
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
|
-
|
|
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
|
-
|
|
29741
|
-
const oplog = await NdjsonOplogStore.open(
|
|
29742
|
-
const blobs = new DirBlobStore(
|
|
29743
|
-
const assets = new DirBlobStore(
|
|
29744
|
-
const registry2 = await FileRegistryStore.open(
|
|
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
|
|
29933
|
+
var fs7, path6;
|
|
29758
29934
|
var init_file_engine = __esm({
|
|
29759
29935
|
"../server/src/file-engine.ts"() {
|
|
29760
29936
|
"use strict";
|
|
29761
|
-
|
|
29762
|
-
|
|
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:
|
|
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 =
|
|
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:
|
|
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 =
|
|
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,
|
|
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:
|
|
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
|
|
33692
|
-
if (!
|
|
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(
|
|
33695
|
-
if (r.status === 404) throw new Error(`Skill not found on ClawHub: ${
|
|
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(
|
|
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(
|
|
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 ${
|
|
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-${
|
|
33724
|
-
name: name || chSkill.displayName ||
|
|
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(
|
|
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[
|
|
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,
|
|
34063
|
+
return (0, import_node_crypto6.createHash)("sha256").update("oasis-dev-only-variable-key").digest();
|
|
33888
34064
|
}
|
|
33889
|
-
var
|
|
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
|
-
|
|
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
|
-
([
|
|
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
|
-
([
|
|
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,
|
|
34368
|
+
buildSkillFile(skillId, path19, content, now) {
|
|
34193
34369
|
const bytes = new TextEncoder().encode(content);
|
|
34194
|
-
const blobHash = (0,
|
|
34195
|
-
return { skillId, path:
|
|
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,
|
|
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,
|
|
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 !==
|
|
34384
|
+
const next = [...existing.filter((f2) => f2.path !== path19), file];
|
|
34209
34385
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
34210
|
-
if (
|
|
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,
|
|
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 !==
|
|
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,
|
|
34529
|
-
const cipher = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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(([
|
|
35289
|
+
return Object.entries(b2.files ?? {}).map(([path19, content]) => ({
|
|
35114
35290
|
skillId: `builtin:${b2.id}`,
|
|
35115
|
-
path:
|
|
35291
|
+
path: path19,
|
|
35116
35292
|
content,
|
|
35117
|
-
blobHash: (0,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
35870
|
+
var import_node_crypto8;
|
|
35691
35871
|
var init_actors = __esm({
|
|
35692
35872
|
"../server/src/domains/actors/index.ts"() {
|
|
35693
35873
|
"use strict";
|
|
35694
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
36629
|
-
if (!SLUG_RE.test(
|
|
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(
|
|
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:${
|
|
36635
|
-
slug:
|
|
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,
|
|
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
|
|
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:${
|
|
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,
|
|
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
|
-
|
|
37225
|
-
const root =
|
|
37226
|
-
|
|
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 =
|
|
37229
|
-
|
|
37230
|
-
|
|
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,
|
|
37239
|
-
clientRequestId: (0,
|
|
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 =
|
|
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
|
-
|
|
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
|
-
|
|
37482
|
+
fs8.writeFileSync(path7.join(dir, f2.path), await fetchInline(f2.path));
|
|
37303
37483
|
} catch {
|
|
37304
37484
|
}
|
|
37305
37485
|
}
|
|
37306
37486
|
}
|
|
37307
|
-
|
|
37308
|
-
|
|
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
|
|
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
|
-
|
|
37346
|
-
|
|
37525
|
+
import_node_crypto10 = require("node:crypto");
|
|
37526
|
+
fs8 = __toESM(require("node:fs"), 1);
|
|
37347
37527
|
os = __toESM(require("node:os"), 1);
|
|
37348
|
-
|
|
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"] ||
|
|
37475
|
-
const projectsDir =
|
|
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
|
|
37479
|
-
if (
|
|
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
|
|
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
|
-
|
|
37490
|
-
|
|
37491
|
-
|
|
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
|
-
|
|
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
|
|
37523
|
-
const id = `claude-${
|
|
37524
|
-
const dir = job.runtimeSessionId ?
|
|
37525
|
-
|
|
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 =
|
|
37535
|
-
|
|
37536
|
-
|
|
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 =
|
|
37540
|
-
|
|
37541
|
-
|
|
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,
|
|
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) =>
|
|
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 =
|
|
37586
|
-
const out =
|
|
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 =
|
|
37673
|
-
|
|
37674
|
-
const kept =
|
|
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
|
-
|
|
37679
|
-
|
|
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
|
|
38055
|
+
return path9.join(os3.homedir(), ".oasis", "skill-cache");
|
|
37876
38056
|
}
|
|
37877
38057
|
function sessionSkillsSubdir(runtimeKind) {
|
|
37878
|
-
|
|
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 =
|
|
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 =
|
|
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(
|
|
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
|
|
38139
|
+
return path9.join(cacheRoot, "actors", encodeURIComponent(actorId));
|
|
37950
38140
|
}
|
|
37951
38141
|
function lockPathFor(cacheRoot, actorId) {
|
|
37952
|
-
return
|
|
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(
|
|
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 =
|
|
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 =
|
|
38030
|
-
const tmpPath =
|
|
38031
|
-
const oldBackup =
|
|
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 =
|
|
38037
|
-
const rel =
|
|
38038
|
-
if (rel.startsWith("..") ||
|
|
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(
|
|
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(
|
|
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(
|
|
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 =
|
|
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,
|
|
38265
|
+
desired.set(entry.dir, path9.join(actorDir, entry.dir));
|
|
38076
38266
|
}
|
|
38077
38267
|
for (const [name, target] of desired) {
|
|
38078
|
-
const link =
|
|
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 =
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
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(
|
|
38673
|
+
if (ch) candidates.push(path10.join(ch, "sessions"));
|
|
38484
38674
|
const home = process.env["HOME"] || os4.homedir();
|
|
38485
|
-
if (home) candidates.push(
|
|
38675
|
+
if (home) candidates.push(path10.join(home, ".codex", "sessions"));
|
|
38486
38676
|
for (const c of candidates) {
|
|
38487
38677
|
try {
|
|
38488
|
-
if (
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
38765
|
-
|
|
38766
|
-
|
|
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
|
-
|
|
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
|
|
38778
|
-
const id = `codex-${
|
|
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 =
|
|
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 =
|
|
38790
|
-
|
|
38791
|
-
|
|
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,
|
|
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) =>
|
|
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 =
|
|
38827
|
-
const out =
|
|
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 =
|
|
38894
|
-
|
|
38895
|
-
const kept =
|
|
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
|
-
|
|
38900
|
-
|
|
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
|
|
39490
|
-
const binTag =
|
|
39491
|
-
const id = `${binTag}-${
|
|
39492
|
-
const dir =
|
|
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 =
|
|
39504
|
-
|
|
39505
|
-
|
|
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,
|
|
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) =>
|
|
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 =
|
|
39523
|
-
const transcriptOut =
|
|
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 =
|
|
39541
|
-
|
|
39542
|
-
const kept =
|
|
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
|
-
|
|
39547
|
-
|
|
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
|
|
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
|
-
|
|
39753
|
-
|
|
39754
|
-
|
|
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
|
-
|
|
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
|
|
40091
|
-
const id = `${
|
|
40092
|
-
const dir =
|
|
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 =
|
|
40104
|
-
|
|
40105
|
-
|
|
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) =>
|
|
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 =
|
|
40129
|
-
|
|
40130
|
-
const kept =
|
|
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
|
-
|
|
40135
|
-
|
|
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,
|
|
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:
|
|
40158
|
-
const transcriptOut =
|
|
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,
|
|
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:
|
|
40234
|
-
const transcriptOut =
|
|
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
|
|
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
|
-
|
|
40296
|
-
|
|
40297
|
-
|
|
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
|
-
|
|
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
|
|
40896
|
+
var import_node_crypto15, OpenClawAdapter;
|
|
40707
40897
|
var init_openclaw = __esm({
|
|
40708
40898
|
"../adapters/src/openclaw/index.ts"() {
|
|
40709
40899
|
"use strict";
|
|
40710
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
|
41596
|
+
var fs13, MemoryNodeStore, FileNodeStore;
|
|
41407
41597
|
var init_node_store = __esm({
|
|
41408
41598
|
"../server/src/node-store.ts"() {
|
|
41409
41599
|
"use strict";
|
|
41410
|
-
|
|
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(
|
|
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
|
-
|
|
41689
|
+
fs13.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
|
|
41500
41690
|
}
|
|
41501
41691
|
return s2;
|
|
41502
41692
|
}
|
|
41503
41693
|
flush() {
|
|
41504
|
-
|
|
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
|
|
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,
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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
|
|
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
|
-
|
|
45058
|
+
import_node_crypto20 = require("node:crypto");
|
|
44865
45059
|
init_src();
|
|
44866
|
-
sha = (s2) => (0,
|
|
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
|
|
45173
|
+
var fs15, FsMirrorStateStore;
|
|
44980
45174
|
var init_fs_state = __esm({
|
|
44981
45175
|
"../server/src/mirror/fs-state.ts"() {
|
|
44982
45176
|
"use strict";
|
|
44983
|
-
|
|
45177
|
+
fs15 = __toESM(require("node:fs"), 1);
|
|
44984
45178
|
FsMirrorStateStore = class {
|
|
44985
45179
|
constructor(file) {
|
|
44986
45180
|
this.file = file;
|
|
44987
|
-
if (
|
|
44988
|
-
const obj = JSON.parse(
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
45016
|
-
|
|
45017
|
-
|
|
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,
|
|
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 (!
|
|
45035
|
-
|
|
45036
|
-
(0,
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
45434
|
-
|
|
45435
|
-
|
|
45436
|
-
|
|
45437
|
-
|
|
45438
|
-
|
|
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
|
-
|
|
45441
|
-
|
|
45442
|
-
|
|
45443
|
-
|
|
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
|
-
|
|
45446
|
-
|
|
45447
|
-
|
|
45448
|
-
|
|
45449
|
-
|
|
45450
|
-
|
|
45451
|
-
|
|
45452
|
-
|
|
45453
|
-
|
|
45454
|
-
|
|
45455
|
-
|
|
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
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
46012
|
-
const skillDir = (0, import_node_path4.join)(skillsDir,
|
|
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 ${
|
|
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] ${
|
|
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:
|
|
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
|
|
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 ?
|
|
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
|
|
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 =
|
|
51289
|
+
const root = path15.join(dataDir, "trajectories");
|
|
51212
51290
|
if (!fs17.existsSync(root)) return [];
|
|
51213
51291
|
const model = emptyReadModel();
|
|
51214
|
-
const oplogFile =
|
|
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 =
|
|
51222
|
-
const sessionFile =
|
|
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 =
|
|
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 =
|
|
51311
|
+
const bundleDir = path15.join(dir, "bundle");
|
|
51234
51312
|
const walk = (sub) => {
|
|
51235
|
-
for (const name of fs17.readdirSync(
|
|
51313
|
+
for (const name of fs17.readdirSync(path15.join(bundleDir, sub))) {
|
|
51236
51314
|
const rel = sub ? `${sub}/${name}` : name;
|
|
51237
|
-
const full =
|
|
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,
|
|
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
|
-
|
|
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 =
|
|
51343
|
+
this.root = path15.join(dataDir, "trajectories");
|
|
51266
51344
|
}
|
|
51267
51345
|
root;
|
|
51268
51346
|
dir(sessionId) {
|
|
51269
|
-
return
|
|
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(
|
|
51274
|
-
fs17.writeFileSync(
|
|
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 =
|
|
51277
|
-
fs17.mkdirSync(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
51306
|
-
const target =
|
|
51307
|
-
if (target !== bundleRoot && !target.startsWith(bundleRoot +
|
|
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 =
|
|
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 =
|
|
51397
|
+
const full = path15.join(d, e.name);
|
|
51320
51398
|
if (e.isDirectory()) walk(full);
|
|
51321
|
-
else out.push(
|
|
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
|
|
51334
|
-
var
|
|
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
|
|
51340
|
-
var
|
|
51341
|
-
var
|
|
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
|
|
51346
|
-
var
|
|
51347
|
-
var
|
|
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
|
|
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,
|
|
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(
|
|
53865
|
-
const r = await this.pool.query(`SELECT * FROM ${this.s}.companies WHERE slug = $1`, [
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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
|
|
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 =
|
|
55735
|
-
const main =
|
|
55736
|
-
const dir = fs18.mkdtempSync(
|
|
55737
|
-
const wrapper =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
55866
|
-
const blobs = pgDsn && pgPool ? await PostgresBlobStore.open(pgPool, pgSchema) : new DirBlobStore(
|
|
55867
|
-
const assets = new DirBlobStore(
|
|
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(
|
|
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(
|
|
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:
|
|
55918
|
-
const operatorActor = `actor:human:${
|
|
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(
|
|
55921
|
-
let nodeTokens = createNodeTokenStore(
|
|
55922
|
-
const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3,
|
|
55923
|
-
let nodeStore = await FileNodeStore.open(
|
|
55924
|
-
const registryAuditFile =
|
|
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(
|
|
55967
|
-
artifactStateStore = await FileArtifactStateStore.open(
|
|
55968
|
-
chatSessionStore = await FileChatSessionStore.open(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
56132
|
-
const journalFile =
|
|
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(
|
|
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,
|
|
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:
|
|
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(
|
|
56405
|
-
escalateDiscussRetain: new FileSideMap(
|
|
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,
|
|
56506
|
+
const runtimeSessionId = sessionId ?? (0, import_node_crypto24.randomUUID)();
|
|
56429
56507
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
56430
|
-
const traceRunId = `chat-run:${(0,
|
|
56431
|
-
const artifactId = `artifact:chat:${(0,
|
|
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:
|
|
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(
|
|
56841
|
-
produceSessions: new FileSideMap(
|
|
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(
|
|
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
|
-
|
|
57038
|
-
|
|
57039
|
-
|
|
57040
|
-
|
|
57041
|
-
|
|
57042
|
-
|
|
57043
|
-
|
|
57044
|
-
|
|
57045
|
-
|
|
57046
|
-
|
|
57047
|
-
|
|
57048
|
-
|
|
57049
|
-
|
|
57050
|
-
|
|
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(
|
|
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
|
|
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,
|
|
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,
|
|
57893
|
-
const res = await fetch(`${base}${
|
|
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(
|
|
57902
|
-
const res = await fetch(`${base}${
|
|
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"] ??
|
|
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 =
|
|
57920
|
-
const nodeTokenFile =
|
|
57921
|
-
const enrollTokenFile =
|
|
57922
|
-
const reportMarkerFile =
|
|
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:
|
|
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 =
|
|
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 =
|
|
57967
|
-
fs19.mkdirSync(
|
|
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"] ?? ""}:${
|
|
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",
|
|
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 =
|
|
57998
|
-
fs19.mkdirSync(
|
|
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>${
|
|
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 ${
|
|
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} > ${
|
|
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(
|
|
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,
|
|
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 ${
|
|
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(
|
|
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(
|
|
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 =
|
|
58077
|
-
const name = `oasis-serve-${
|
|
58078
|
-
const unitDir = flags.get("unit-dir") ??
|
|
58079
|
-
const bin = flags.get("bin") ??
|
|
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 =
|
|
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 ${
|
|
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 =
|
|
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 =
|
|
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") ??
|
|
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
|
|
59087
|
-
const c = await api.view("content", id,
|
|
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.
|
|
59261
|
-
var OASIS_DIR =
|
|
59262
|
-
var CONFIG_FILE =
|
|
59263
|
-
var PID_FILE =
|
|
59264
|
-
var BIN_FILE =
|
|
59265
|
-
var LOCAL_BIN =
|
|
59266
|
-
var LOG_FILE =
|
|
59267
|
-
var NPM_PREFIX =
|
|
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(
|
|
59377
|
+
fs20.mkdirSync(path18.dirname(BIN_FILE), { recursive: true });
|
|
59307
59378
|
fs20.copyFileSync(process.argv[1], BIN_FILE);
|
|
59308
|
-
fs20.mkdirSync(
|
|
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 =
|
|
59386
|
+
const home = os9.homedir();
|
|
59316
59387
|
const extraBins = [
|
|
59317
|
-
|
|
59318
|
-
|
|
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 =
|
|
59394
|
+
const unitDir = path18.join(os9.homedir(), ".config", "systemd", "user");
|
|
59324
59395
|
fs20.mkdirSync(unitDir, { recursive: true });
|
|
59325
|
-
fs20.writeFileSync(
|
|
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 =
|
|
59348
|
-
fs20.mkdirSync(
|
|
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 =
|
|
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:
|
|
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(
|
|
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
|
}
|