oasis_test 0.1.45 → 0.1.47
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 +920 -629
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1958,9 +1958,9 @@ var init_kernel = __esm({
|
|
|
1958
1958
|
throw new KernelError(`revision not in queue: ${args.revisionId}\uFF08state=${target?.state ?? "missing"}\uFF09`);
|
|
1959
1959
|
}
|
|
1960
1960
|
if (isStale(this.model, head)) {
|
|
1961
|
-
const
|
|
1961
|
+
const path20 = this.pathForStaleHead(artifact, queue);
|
|
1962
1962
|
throw new KernelError(
|
|
1963
|
-
`stale base: ${head.id} based on ${head.base ?? "\u2205"}, head is ${artifact.currentRev ?? "\u2205"} \u2014 ` + (
|
|
1963
|
+
`stale base: ${head.id} based on ${head.base ?? "\u2205"}, head is ${artifact.currentRev ?? "\u2205"} \u2014 ` + (path20 === "rebase" ? `\u9700\u8981 rebase\uFF1A\u4F5C\u8005\u5728\u65B0 head \u4E0A\u91CD\u5199\u540E propose --rebase-of ${head.id}\uFF08\xA75.5\uFF09` : `\u591A\u6761\u7ADE\u4E89\u4E14\u68C0\u67E5\u8D35 \u2192 group-commit\uFF1Aowner \u4E00\u6B21\u96C6\u6210\u6574\u6279\uFF08\xA75.5\uFF09`)
|
|
1964
1964
|
);
|
|
1965
1965
|
}
|
|
1966
1966
|
await this.landHead(args.artifactId, args.actor, head, args.hand);
|
|
@@ -1977,13 +1977,13 @@ var init_kernel = __esm({
|
|
|
1977
1977
|
const head = queue[0];
|
|
1978
1978
|
if (!head) return { landed };
|
|
1979
1979
|
if (isStale(this.model, head)) {
|
|
1980
|
-
const
|
|
1980
|
+
const path20 = this.pathForStaleHead(artifact, queue);
|
|
1981
1981
|
return {
|
|
1982
1982
|
landed,
|
|
1983
1983
|
blockedHead: {
|
|
1984
1984
|
revision: head,
|
|
1985
|
-
path:
|
|
1986
|
-
hint:
|
|
1985
|
+
path: path20,
|
|
1986
|
+
hint: path20 === "rebase" ? `\u4F5C\u8005\u91CD\u5199\u540E propose --rebase-of ${head.id}` : `owner \u96C6\u6210\u6574\u6279\uFF08integrate\uFF09\uFF0CR*.parents = [head, \u2026batch]`
|
|
1987
1987
|
}
|
|
1988
1988
|
};
|
|
1989
1989
|
}
|
|
@@ -3852,7 +3852,7 @@ function computeReviewJobs(model) {
|
|
|
3852
3852
|
}
|
|
3853
3853
|
return out;
|
|
3854
3854
|
}
|
|
3855
|
-
var import_node_crypto2, DEFAULT_PREDISPATCH_TIMEOUT_MS, SpawnAttemptStale, SEED_ROOT_SUCCESSFUL_PRODUCE_LIMIT, Dispatcher;
|
|
3855
|
+
var import_node_crypto2, DEFAULT_PREDISPATCH_TIMEOUT_MS, SpawnAttemptStale, SEED_ROOT_SUCCESSFUL_PRODUCE_LIMIT, CANVAS_RUNTIME_KIND, NON_PRODUCE_FALLBACK_RUNTIME_KIND, Dispatcher;
|
|
3856
3856
|
var init_dispatcher = __esm({
|
|
3857
3857
|
"../core/src/dispatcher.ts"() {
|
|
3858
3858
|
"use strict";
|
|
@@ -3869,6 +3869,8 @@ var init_dispatcher = __esm({
|
|
|
3869
3869
|
}
|
|
3870
3870
|
};
|
|
3871
3871
|
SEED_ROOT_SUCCESSFUL_PRODUCE_LIMIT = 5;
|
|
3872
|
+
CANVAS_RUNTIME_KIND = "open-design";
|
|
3873
|
+
NON_PRODUCE_FALLBACK_RUNTIME_KIND = "claude-code";
|
|
3872
3874
|
Dispatcher = class {
|
|
3873
3875
|
constructor(opts) {
|
|
3874
3876
|
this.opts = opts;
|
|
@@ -4177,6 +4179,28 @@ var init_dispatcher = __esm({
|
|
|
4177
4179
|
});
|
|
4178
4180
|
}
|
|
4179
4181
|
}
|
|
4182
|
+
/**
|
|
4183
|
+
* 员工 → 运行时绑定,按动作校正。
|
|
4184
|
+
*
|
|
4185
|
+
* 背景:design 产物走「画板化」(提案 design-node-canvas-driven)——designer 的 produce 会话跑在
|
|
4186
|
+
* open-design 画板引擎里,产出**真实可打开的界面稿**(HTML + acceptance.md)而非文档。为此
|
|
4187
|
+
* designer 被绑到 `runtimeKind: "open-design"`。但 open-design 是**只会 produce 的专用引擎**:
|
|
4188
|
+
* 它的适配器无视 action,永远驱动画板引擎产界面再 propose。designer 一旦以 reviewer / 被 @ 回复 /
|
|
4189
|
+
* 收口身份被派活(action ≠ produce),仍按绑定路由到 open-design 就必崩(harvest 无 HTML 入口稿、
|
|
4190
|
+
* 或 propose 非己产物 → 会话 code=1 reason=error),评审票永远投不出,评审门只能靠他人凑 quorum 或
|
|
4191
|
+
* 人工 force-conclude。
|
|
4192
|
+
*
|
|
4193
|
+
* 修正:非 produce 的动作忽略画板绑定,回退到节点上的通用编码运行时(claude-code)——保持同一 nodeId,
|
|
4194
|
+
* 只换 runtimeKind。与 assembler 的 `canvasMode`(同样 `action !== "review"` 才进画板模式)语义一致:
|
|
4195
|
+
* 画板只服务于「产界面」,评审/回复/收口回到能真正读写、能投票的通用运行时。
|
|
4196
|
+
*/
|
|
4197
|
+
async resolveBindingFor(spec) {
|
|
4198
|
+
const binding = await this.opts.resolveBinding?.(spec.actor) ?? void 0;
|
|
4199
|
+
if (binding && spec.action !== "produce" && binding.runtimeKind === CANVAS_RUNTIME_KIND) {
|
|
4200
|
+
return { ...binding, runtimeKind: NON_PRODUCE_FALLBACK_RUNTIME_KIND };
|
|
4201
|
+
}
|
|
4202
|
+
return binding;
|
|
4203
|
+
}
|
|
4180
4204
|
async spawnJobInner(jobKey, spec, attempt) {
|
|
4181
4205
|
if (this.inFlight.has(jobKey)) return 0;
|
|
4182
4206
|
const { kernel } = this.opts;
|
|
@@ -4217,7 +4241,7 @@ var init_dispatcher = __esm({
|
|
|
4217
4241
|
const ws = kernel.model.artifacts.get(spec.artifactId)?.workspace;
|
|
4218
4242
|
const codeRepo = ws ? await this.opts.resolveCodeRepo?.(ws) ?? null : null;
|
|
4219
4243
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
4220
|
-
const binding = await this.
|
|
4244
|
+
const binding = await this.resolveBindingFor(spec);
|
|
4221
4245
|
this.assertSpawnAttemptCurrent(jobKey, attempt);
|
|
4222
4246
|
const materializeSkills = this.opts.materializeSkills ? () => this.opts.materializeSkills(spec.actor, binding?.runtimeKind ?? "claude") : void 0;
|
|
4223
4247
|
const bundle = await assembleContext({
|
|
@@ -5181,8 +5205,8 @@ var init_parseUtil = __esm({
|
|
|
5181
5205
|
init_errors2();
|
|
5182
5206
|
init_en();
|
|
5183
5207
|
makeIssue = (params) => {
|
|
5184
|
-
const { data, path:
|
|
5185
|
-
const fullPath = [...
|
|
5208
|
+
const { data, path: path20, errorMaps, issueData } = params;
|
|
5209
|
+
const fullPath = [...path20, ...issueData.path || []];
|
|
5186
5210
|
const fullIssue = {
|
|
5187
5211
|
...issueData,
|
|
5188
5212
|
path: fullPath
|
|
@@ -5490,11 +5514,11 @@ var init_types = __esm({
|
|
|
5490
5514
|
init_parseUtil();
|
|
5491
5515
|
init_util();
|
|
5492
5516
|
ParseInputLazyPath = class {
|
|
5493
|
-
constructor(parent, value,
|
|
5517
|
+
constructor(parent, value, path20, key) {
|
|
5494
5518
|
this._cachedPath = [];
|
|
5495
5519
|
this.parent = parent;
|
|
5496
5520
|
this.data = value;
|
|
5497
|
-
this._path =
|
|
5521
|
+
this._path = path20;
|
|
5498
5522
|
this._key = key;
|
|
5499
5523
|
}
|
|
5500
5524
|
get path() {
|
|
@@ -9068,10 +9092,10 @@ function assignProp(target, prop, value) {
|
|
|
9068
9092
|
configurable: true
|
|
9069
9093
|
});
|
|
9070
9094
|
}
|
|
9071
|
-
function getElementAtPath(obj,
|
|
9072
|
-
if (!
|
|
9095
|
+
function getElementAtPath(obj, path20) {
|
|
9096
|
+
if (!path20)
|
|
9073
9097
|
return obj;
|
|
9074
|
-
return
|
|
9098
|
+
return path20.reduce((acc, key) => acc?.[key], obj);
|
|
9075
9099
|
}
|
|
9076
9100
|
function promiseAllObject(promisesObj) {
|
|
9077
9101
|
const keys = Object.keys(promisesObj);
|
|
@@ -9320,11 +9344,11 @@ function aborted(x2, startIndex = 0) {
|
|
|
9320
9344
|
}
|
|
9321
9345
|
return false;
|
|
9322
9346
|
}
|
|
9323
|
-
function prefixIssues(
|
|
9347
|
+
function prefixIssues(path20, issues) {
|
|
9324
9348
|
return issues.map((iss) => {
|
|
9325
9349
|
var _a;
|
|
9326
9350
|
(_a = iss).path ?? (_a.path = []);
|
|
9327
|
-
iss.path.unshift(
|
|
9351
|
+
iss.path.unshift(path20);
|
|
9328
9352
|
return iss;
|
|
9329
9353
|
});
|
|
9330
9354
|
}
|
|
@@ -17864,8 +17888,8 @@ var require_utils = __commonJS({
|
|
|
17864
17888
|
}
|
|
17865
17889
|
return ind;
|
|
17866
17890
|
}
|
|
17867
|
-
function removeDotSegments(
|
|
17868
|
-
let input =
|
|
17891
|
+
function removeDotSegments(path20) {
|
|
17892
|
+
let input = path20;
|
|
17869
17893
|
const output = [];
|
|
17870
17894
|
let nextSlash = -1;
|
|
17871
17895
|
let len = 0;
|
|
@@ -18117,8 +18141,8 @@ var require_schemes = __commonJS({
|
|
|
18117
18141
|
wsComponent.secure = void 0;
|
|
18118
18142
|
}
|
|
18119
18143
|
if (wsComponent.resourceName) {
|
|
18120
|
-
const [
|
|
18121
|
-
wsComponent.path =
|
|
18144
|
+
const [path20, query] = wsComponent.resourceName.split("?");
|
|
18145
|
+
wsComponent.path = path20 && path20 !== "/" ? path20 : void 0;
|
|
18122
18146
|
wsComponent.query = query;
|
|
18123
18147
|
wsComponent.resourceName = void 0;
|
|
18124
18148
|
}
|
|
@@ -21511,12 +21535,12 @@ var require_dist = __commonJS({
|
|
|
21511
21535
|
throw new Error(`Unknown format "${name}"`);
|
|
21512
21536
|
return f2;
|
|
21513
21537
|
};
|
|
21514
|
-
function addFormats(ajv, list,
|
|
21538
|
+
function addFormats(ajv, list, fs21, exportName) {
|
|
21515
21539
|
var _a;
|
|
21516
21540
|
var _b;
|
|
21517
21541
|
(_a = (_b = ajv.opts.code).formats) !== null && _a !== void 0 ? _a : _b.formats = (0, codegen_1._)`require("ajv-formats/dist/formats").${exportName}`;
|
|
21518
21542
|
for (const f2 of list)
|
|
21519
|
-
ajv.addFormat(f2,
|
|
21543
|
+
ajv.addFormat(f2, fs21[f2]);
|
|
21520
21544
|
}
|
|
21521
21545
|
module2.exports = exports2 = formatsPlugin;
|
|
21522
21546
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
@@ -21631,23 +21655,23 @@ var init_router = __esm({
|
|
|
21631
21655
|
};
|
|
21632
21656
|
Router = class {
|
|
21633
21657
|
routes = [];
|
|
21634
|
-
on(method,
|
|
21635
|
-
this.routes.push({ method, segments:
|
|
21658
|
+
on(method, path20, handler) {
|
|
21659
|
+
this.routes.push({ method, segments: path20.split("/").filter(Boolean), handler });
|
|
21636
21660
|
}
|
|
21637
|
-
get(
|
|
21638
|
-
this.on("GET",
|
|
21661
|
+
get(path20, h) {
|
|
21662
|
+
this.on("GET", path20, h);
|
|
21639
21663
|
}
|
|
21640
|
-
post(
|
|
21641
|
-
this.on("POST",
|
|
21664
|
+
post(path20, h) {
|
|
21665
|
+
this.on("POST", path20, h);
|
|
21642
21666
|
}
|
|
21643
|
-
patch(
|
|
21644
|
-
this.on("PATCH",
|
|
21667
|
+
patch(path20, h) {
|
|
21668
|
+
this.on("PATCH", path20, h);
|
|
21645
21669
|
}
|
|
21646
|
-
put(
|
|
21647
|
-
this.on("PUT",
|
|
21670
|
+
put(path20, h) {
|
|
21671
|
+
this.on("PUT", path20, h);
|
|
21648
21672
|
}
|
|
21649
|
-
delete(
|
|
21650
|
-
this.on("DELETE",
|
|
21673
|
+
delete(path20, h) {
|
|
21674
|
+
this.on("DELETE", path20, h);
|
|
21651
21675
|
}
|
|
21652
21676
|
match(method, pathname) {
|
|
21653
21677
|
const parts = pathname.split("/").filter(Boolean);
|
|
@@ -24384,7 +24408,7 @@ async function runView(kernel, oplog, blobs, name, artifactId, params) {
|
|
|
24384
24408
|
}
|
|
24385
24409
|
case "content": {
|
|
24386
24410
|
const id = need2();
|
|
24387
|
-
const
|
|
24411
|
+
const path20 = params?.get("path") ?? null;
|
|
24388
24412
|
const artifact = model.artifacts.get(id);
|
|
24389
24413
|
if (!artifact) throw new Error(`artifact \u4E0D\u5B58\u5728: ${id}`);
|
|
24390
24414
|
const head = artifact.currentRev;
|
|
@@ -24396,11 +24420,11 @@ async function runView(kernel, oplog, blobs, name, artifactId, params) {
|
|
|
24396
24420
|
const dec2 = new TextDecoder();
|
|
24397
24421
|
if (headRev.contentKind === "manifest") {
|
|
24398
24422
|
const entries = await readManifest(blobs, headRev.contentRef);
|
|
24399
|
-
if (
|
|
24400
|
-
const e = entries.find((x2) => x2.path ===
|
|
24401
|
-
if (!e) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${
|
|
24423
|
+
if (path20 !== null) {
|
|
24424
|
+
const e = entries.find((x2) => x2.path === path20);
|
|
24425
|
+
if (!e) throw new Error(`\u6587\u4EF6\u4E0D\u5B58\u5728: ${path20}\uFF08\u672C\u4EA7\u7269\u6709\uFF1A${entries.map((x2) => x2.path).join("\u3001")}\uFF09`);
|
|
24402
24426
|
const isText = !e.bytes.includes(0);
|
|
24403
|
-
return { kind: "file", path:
|
|
24427
|
+
return { kind: "file", path: path20, bytes: e.bytes.length, text: isText ? dec2.decode(e.bytes) : null };
|
|
24404
24428
|
}
|
|
24405
24429
|
return {
|
|
24406
24430
|
kind: "manifest",
|
|
@@ -24695,9 +24719,9 @@ async function startOasisServer(opts) {
|
|
|
24695
24719
|
}
|
|
24696
24720
|
}
|
|
24697
24721
|
if (!target) return;
|
|
24698
|
-
const { randomUUID:
|
|
24722
|
+
const { randomUUID: randomUUID19 } = await import("node:crypto");
|
|
24699
24723
|
if (chatStore) {
|
|
24700
|
-
await chatStore.appendMessage({ id:
|
|
24724
|
+
await chatStore.appendMessage({ id: randomUUID19(), sessionId: target, role: "user", content: message, createdAt: (/* @__PURE__ */ new Date()).toISOString() }).catch(() => void 0);
|
|
24701
24725
|
}
|
|
24702
24726
|
const rt = record5?.runtimeSessionId ?? opts.retainedSession?.({ draftId: review.draftId });
|
|
24703
24727
|
const session = await opts.dispatchChat({
|
|
@@ -24715,7 +24739,7 @@ async function startOasisServer(opts) {
|
|
|
24715
24739
|
});
|
|
24716
24740
|
void session.done.then(async () => {
|
|
24717
24741
|
if (reply || session.runId) {
|
|
24718
|
-
await chatStore.appendMessage({ id:
|
|
24742
|
+
await chatStore.appendMessage({ id: randomUUID19(), sessionId: sid, role: "assistant", content: reply, createdAt: (/* @__PURE__ */ new Date()).toISOString(), ...session.runId ? { runId: session.runId } : {} }).catch(() => void 0);
|
|
24719
24743
|
}
|
|
24720
24744
|
}).catch(() => void 0);
|
|
24721
24745
|
}
|
|
@@ -24785,11 +24809,11 @@ async function startOasisServer(opts) {
|
|
|
24785
24809
|
let chatSessionId;
|
|
24786
24810
|
let createdThisCall = false;
|
|
24787
24811
|
if (chatStore) {
|
|
24788
|
-
const { randomUUID:
|
|
24812
|
+
const { randomUUID: randomUUID19 } = await import("node:crypto");
|
|
24789
24813
|
const known = discussSessions.get(itemKey);
|
|
24790
24814
|
if (known && await chatStore.getSession(known).catch(() => null)) chatSessionId = known;
|
|
24791
24815
|
if (!chatSessionId) {
|
|
24792
|
-
chatSessionId =
|
|
24816
|
+
chatSessionId = randomUUID19();
|
|
24793
24817
|
createdThisCall = true;
|
|
24794
24818
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
24795
24819
|
const title = `\u89E3\u51B3\uFF1A${ctx.seed.slice(ctx.seed.indexOf("\uFF1A") + 1, ctx.seed.indexOf("\uFF1A") + 25) || "\u5DE5\u5355\u5361\u70B9"}`;
|
|
@@ -24797,7 +24821,7 @@ async function startOasisServer(opts) {
|
|
|
24797
24821
|
await chatStore.linkWorkOrder(chatSessionId, ctx.workspace).catch(() => void 0);
|
|
24798
24822
|
}
|
|
24799
24823
|
discussSessions.set(itemKey, chatSessionId);
|
|
24800
|
-
await chatStore.appendMessage({ id:
|
|
24824
|
+
await chatStore.appendMessage({ id: randomUUID19(), sessionId: chatSessionId, role: "user", content: ctx.seed, createdAt: (/* @__PURE__ */ new Date()).toISOString() }).catch(() => void 0);
|
|
24801
24825
|
}
|
|
24802
24826
|
let session;
|
|
24803
24827
|
try {
|
|
@@ -24816,9 +24840,9 @@ async function startOasisServer(opts) {
|
|
|
24816
24840
|
reply += chunk;
|
|
24817
24841
|
});
|
|
24818
24842
|
void session.done.then(async () => {
|
|
24819
|
-
const { randomUUID:
|
|
24843
|
+
const { randomUUID: randomUUID19 } = await import("node:crypto");
|
|
24820
24844
|
if (reply || session.runId) {
|
|
24821
|
-
await chatStore.appendMessage({ id:
|
|
24845
|
+
await chatStore.appendMessage({ id: randomUUID19(), sessionId: sid, role: "assistant", content: reply, createdAt: (/* @__PURE__ */ new Date()).toISOString(), ...session.runId ? { runId: session.runId } : {} }).catch(() => void 0);
|
|
24822
24846
|
}
|
|
24823
24847
|
}).catch(() => void 0);
|
|
24824
24848
|
}
|
|
@@ -25151,14 +25175,14 @@ async function startOasisServer(opts) {
|
|
|
25151
25175
|
const persistSession = chatStore && body.chatSessionId ? await chatStore.getSession(body.chatSessionId).catch(() => null) : null;
|
|
25152
25176
|
const persistTarget = persistSession && persistSession.humanActorId === actor ? persistSession : null;
|
|
25153
25177
|
if (chatStore && persistTarget) {
|
|
25154
|
-
const { randomUUID:
|
|
25178
|
+
const { randomUUID: randomUUID20 } = await import("node:crypto");
|
|
25155
25179
|
const persistAttachments = attachments.map((a) => ({
|
|
25156
25180
|
name: a.name,
|
|
25157
25181
|
...a.blobRef !== void 0 ? { blobRef: a.blobRef } : {},
|
|
25158
25182
|
...a.contentType !== void 0 ? { contentType: a.contentType } : {}
|
|
25159
25183
|
}));
|
|
25160
25184
|
await chatStore.appendMessage({
|
|
25161
|
-
id:
|
|
25185
|
+
id: randomUUID20(),
|
|
25162
25186
|
sessionId: persistTarget.id,
|
|
25163
25187
|
role: "user",
|
|
25164
25188
|
content: body.message,
|
|
@@ -25168,8 +25192,8 @@ async function startOasisServer(opts) {
|
|
|
25168
25192
|
}
|
|
25169
25193
|
let assistantMsgId;
|
|
25170
25194
|
if (chatStore && persistTarget) {
|
|
25171
|
-
const { randomUUID:
|
|
25172
|
-
const id =
|
|
25195
|
+
const { randomUUID: randomUUID20 } = await import("node:crypto");
|
|
25196
|
+
const id = randomUUID20();
|
|
25173
25197
|
await chatStore.appendMessage({
|
|
25174
25198
|
id,
|
|
25175
25199
|
sessionId: persistTarget.id,
|
|
@@ -25200,9 +25224,9 @@ async function startOasisServer(opts) {
|
|
|
25200
25224
|
}).catch(() => void 0);
|
|
25201
25225
|
} else {
|
|
25202
25226
|
if (!assistantText && !session.runId && parts.length === 0) return;
|
|
25203
|
-
const { randomUUID:
|
|
25227
|
+
const { randomUUID: randomUUID20 } = await import("node:crypto");
|
|
25204
25228
|
await chatStore.appendMessage({
|
|
25205
|
-
id:
|
|
25229
|
+
id: randomUUID20(),
|
|
25206
25230
|
sessionId: persistTarget.id,
|
|
25207
25231
|
role: "assistant",
|
|
25208
25232
|
content: assistantText,
|
|
@@ -25330,13 +25354,13 @@ async function startOasisServer(opts) {
|
|
|
25330
25354
|
const actorCtx = await opts.resolveActorContext(body.actorId).catch(() => null);
|
|
25331
25355
|
if (actorCtx) {
|
|
25332
25356
|
const { mkdtempSync: mkdtempSync9, mkdirSync: mkdirSync16, writeFileSync: writeFileSync15 } = await import("node:fs");
|
|
25333
|
-
const { join:
|
|
25334
|
-
const { tmpdir:
|
|
25335
|
-
const dir = mkdtempSync9(
|
|
25357
|
+
const { join: join24, dirname: dirname18 } = await import("node:path");
|
|
25358
|
+
const { tmpdir: tmpdir14 } = await import("node:os");
|
|
25359
|
+
const dir = mkdtempSync9(join24(tmpdir14(), "oasis-chat-"));
|
|
25336
25360
|
if (actorCtx.config?.prompt) {
|
|
25337
25361
|
for (const [rel, content] of Object.entries(splitIdentityFiles2(actorCtx.config.prompt))) {
|
|
25338
|
-
const file =
|
|
25339
|
-
mkdirSync16(
|
|
25362
|
+
const file = join24(dir, rel);
|
|
25363
|
+
mkdirSync16(dirname18(file), { recursive: true });
|
|
25340
25364
|
writeFileSync15(file, content);
|
|
25341
25365
|
}
|
|
25342
25366
|
}
|
|
@@ -25347,13 +25371,13 @@ async function startOasisServer(opts) {
|
|
|
25347
25371
|
const s2 = byId.get(id);
|
|
25348
25372
|
return s2 ? `- **${s2.name}** (\`${s2.id}\`): ${s2.description}` : `- \`${id}\`\uFF08\u672A\u5728\u6280\u80FD\u5E93\u4E2D\uFF0C\u53EF\u80FD\u5DF2\u5378\u8F7D\uFF09`;
|
|
25349
25373
|
});
|
|
25350
|
-
writeFileSync15(
|
|
25374
|
+
writeFileSync15(join24(dir, "SKILLS.md"), ["# \u53EF\u7528\u6280\u80FD", "", "\u4EE5\u4E0B\u6280\u80FD\u5DF2\u4E3A\u4F60\u542F\u7528\uFF0C\u53EF\u5728\u672C\u6B21\u4F1A\u8BDD\u4E2D\u76F4\u63A5\u4F7F\u7528\uFF1A", "", ...lines].join("\n"));
|
|
25351
25375
|
}
|
|
25352
25376
|
if (opts.materializeSkills) {
|
|
25353
25377
|
const skillFiles = await opts.materializeSkills(body.actorId, "claude").catch(() => ({}));
|
|
25354
25378
|
for (const [rel, content] of Object.entries(skillFiles)) {
|
|
25355
|
-
const file =
|
|
25356
|
-
mkdirSync16(
|
|
25379
|
+
const file = join24(dir, rel);
|
|
25380
|
+
mkdirSync16(dirname18(file), { recursive: true });
|
|
25357
25381
|
writeFileSync15(file, content);
|
|
25358
25382
|
}
|
|
25359
25383
|
}
|
|
@@ -25366,14 +25390,14 @@ async function startOasisServer(opts) {
|
|
|
25366
25390
|
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";
|
|
25367
25391
|
return `- **${c.name}** (\`${c.id}\`): ${statusNote} \xB7 ${modeNote}`;
|
|
25368
25392
|
});
|
|
25369
|
-
writeFileSync15(
|
|
25393
|
+
writeFileSync15(join24(dir, "CONNECTORS.md"), ["# \u53EF\u7528\u8FDE\u63A5\u5668", "", "\u4EE5\u4E0B\u8FDE\u63A5\u5668\u5DF2\u4E3A\u672C\u6B21\u4F1A\u8BDD\u914D\u7F6E\uFF0C\u51ED\u8BC1\u5DF2\u901A\u8FC7\u73AF\u5883\u53D8\u91CF\u6216 CLI wrapper \u6CE8\u5165\uFF0C\u65E0\u9700\u624B\u52A8\u914D\u7F6E\uFF1A", "", ...lines].join("\n"));
|
|
25370
25394
|
}
|
|
25371
25395
|
spawnCwd = dir;
|
|
25372
25396
|
}
|
|
25373
25397
|
}
|
|
25374
25398
|
const { spawn: spawn7 } = await import("node:child_process");
|
|
25375
|
-
const { randomUUID:
|
|
25376
|
-
const sessionId = body.sessionId ??
|
|
25399
|
+
const { randomUUID: randomUUID19 } = await import("node:crypto");
|
|
25400
|
+
const sessionId = body.sessionId ?? randomUUID19();
|
|
25377
25401
|
const args = [
|
|
25378
25402
|
"-p",
|
|
25379
25403
|
body.message,
|
|
@@ -27690,13 +27714,13 @@ var init_service = __esm({
|
|
|
27690
27714
|
async readDocument(contentRef) {
|
|
27691
27715
|
for (const [projectId, space] of this.spaces) {
|
|
27692
27716
|
if (!contentRef.startsWith(`${space.rootRef}/`)) continue;
|
|
27693
|
-
const
|
|
27694
|
-
const content = space.files.get(
|
|
27717
|
+
const path20 = contentRef.slice(space.rootRef.length + 1);
|
|
27718
|
+
const content = space.files.get(path20);
|
|
27695
27719
|
if (content === void 0) return null;
|
|
27696
27720
|
return {
|
|
27697
27721
|
contentRef,
|
|
27698
27722
|
content,
|
|
27699
|
-
url: `https://outline.local/${encodeURIComponent(projectId)}/${
|
|
27723
|
+
url: `https://outline.local/${encodeURIComponent(projectId)}/${path20.split("/").map(encodeURIComponent).join("/")}`
|
|
27700
27724
|
};
|
|
27701
27725
|
}
|
|
27702
27726
|
return null;
|
|
@@ -27780,8 +27804,8 @@ var init_service = __esm({
|
|
|
27780
27804
|
const space = this.requireSpace(state.projectId);
|
|
27781
27805
|
const stored = { ...state, payload: { ...state.payload }, updatedAt: state.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString() };
|
|
27782
27806
|
space.runStates.set(runStateKey(state.workOrderId, state.nodeId), stored);
|
|
27783
|
-
const
|
|
27784
|
-
space.files.set(
|
|
27807
|
+
const path20 = `run_state/${state.workOrderId ?? "project"}/${state.nodeId ?? "default"}.json`;
|
|
27808
|
+
space.files.set(path20, JSON.stringify(stored, null, 2));
|
|
27785
27809
|
return { ...stored, payload: { ...stored.payload } };
|
|
27786
27810
|
}
|
|
27787
27811
|
requireSpace(projectId) {
|
|
@@ -33266,12 +33290,12 @@ var init_daemon_hub = __esm({
|
|
|
33266
33290
|
this.disconnectListeners.add(cb);
|
|
33267
33291
|
return () => this.disconnectListeners.delete(cb);
|
|
33268
33292
|
}
|
|
33269
|
-
constructor(server,
|
|
33293
|
+
constructor(server, path20 = "/daemon/ws", resolveNode, opts = {}) {
|
|
33270
33294
|
this.pingIntervalMs = opts.pingIntervalMs ?? 2e4;
|
|
33271
33295
|
this.silenceTimeoutMs = opts.silenceTimeoutMs ?? 6e4;
|
|
33272
33296
|
this.wss = new import_websocket_server.default({
|
|
33273
33297
|
server,
|
|
33274
|
-
path:
|
|
33298
|
+
path: path20,
|
|
33275
33299
|
...resolveNode ? {
|
|
33276
33300
|
verifyClient: (info, cb) => {
|
|
33277
33301
|
const authHeader = info.req.headers.authorization ?? "";
|
|
@@ -33626,13 +33650,13 @@ var init_skill_fetcher = __esm({
|
|
|
33626
33650
|
files = {};
|
|
33627
33651
|
totalBytes = 0;
|
|
33628
33652
|
fileCount = 0;
|
|
33629
|
-
add(
|
|
33653
|
+
add(path20, content) {
|
|
33630
33654
|
const bytes = new TextEncoder().encode(content).length;
|
|
33631
33655
|
if (this.fileCount >= MAX_FILE_COUNT)
|
|
33632
33656
|
throw new Error(`Import bundle exceeds ${MAX_FILE_COUNT} file limit`);
|
|
33633
33657
|
if (this.totalBytes + bytes > MAX_TOTAL_BYTES)
|
|
33634
33658
|
throw new Error(`Import bundle exceeds ${MAX_TOTAL_BYTES} byte limit`);
|
|
33635
|
-
this.files[
|
|
33659
|
+
this.files[path20] = content;
|
|
33636
33660
|
this.totalBytes += bytes;
|
|
33637
33661
|
this.fileCount++;
|
|
33638
33662
|
}
|
|
@@ -33901,7 +33925,7 @@ ${input.description}
|
|
|
33901
33925
|
};
|
|
33902
33926
|
await this.opts.store.putInstalledSkill(installed);
|
|
33903
33927
|
const skillFiles = Object.entries(fetched.files).map(
|
|
33904
|
-
([
|
|
33928
|
+
([path20, content]) => this.buildSkillFile(id, path20, content, now)
|
|
33905
33929
|
);
|
|
33906
33930
|
await this.opts.store.putSkillFiles(id, skillFiles);
|
|
33907
33931
|
await this.audit({ kind: "skill_install", actorId: by, by, at: now, detail: { skillId: id, source: input.sourceKind, sourceUrl } });
|
|
@@ -33936,7 +33960,7 @@ ${input.description}
|
|
|
33936
33960
|
connectorId
|
|
33937
33961
|
});
|
|
33938
33962
|
const skillFiles = Object.entries(entry.files).map(
|
|
33939
|
-
([
|
|
33963
|
+
([path20, content]) => this.buildSkillFile(id, path20, content, now)
|
|
33940
33964
|
);
|
|
33941
33965
|
await this.opts.store.putSkillFiles(id, skillFiles);
|
|
33942
33966
|
}
|
|
@@ -33954,25 +33978,25 @@ ${input.description}
|
|
|
33954
33978
|
* 构造 SkillFile:正文内联进 content(决策 0036);blobHash/size 计算为 content 的 sha256
|
|
33955
33979
|
* 与字节数,仅作元数据/审计(不再有读取方,正文直接从 content 出)。
|
|
33956
33980
|
*/
|
|
33957
|
-
buildSkillFile(skillId,
|
|
33981
|
+
buildSkillFile(skillId, path20, content, now) {
|
|
33958
33982
|
const bytes = new TextEncoder().encode(content);
|
|
33959
33983
|
const blobHash = (0, import_node_crypto6.createHash)("sha256").update(bytes).digest("hex");
|
|
33960
|
-
return { skillId, path:
|
|
33984
|
+
return { skillId, path: path20, content, blobHash, size: bytes.length, updatedAt: now };
|
|
33961
33985
|
}
|
|
33962
33986
|
/**
|
|
33963
33987
|
* 更新或新建技能的单个文件。
|
|
33964
33988
|
* 正文内联进 skill_files(决策 0036),更新文件索引,但**不**改写技能的 name/description——
|
|
33965
33989
|
* 如果修改的是 SKILL.md,调用方应另外调用 updateInstalledSkill 同步 frontmatter。
|
|
33966
33990
|
*/
|
|
33967
|
-
async putSkillFile(skillId,
|
|
33991
|
+
async putSkillFile(skillId, path20, content) {
|
|
33968
33992
|
const cur = (await this.opts.store.listInstalledSkills()).find((x2) => x2.id === skillId);
|
|
33969
33993
|
if (!cur) throw new Error(`\u672A\u5B89\u88C5\u8BE5\u6280\u80FD\uFF1A${skillId}`);
|
|
33970
33994
|
const now = this.now();
|
|
33971
|
-
const file = this.buildSkillFile(skillId,
|
|
33995
|
+
const file = this.buildSkillFile(skillId, path20, content, now);
|
|
33972
33996
|
const existing = await this.opts.store.listSkillFiles(skillId);
|
|
33973
|
-
const next = [...existing.filter((f2) => f2.path !==
|
|
33997
|
+
const next = [...existing.filter((f2) => f2.path !== path20), file];
|
|
33974
33998
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
33975
|
-
if (
|
|
33999
|
+
if (path20 === "SKILL.md") {
|
|
33976
34000
|
const { name, description } = parseSkillFrontmatter(content);
|
|
33977
34001
|
if (name || description) {
|
|
33978
34002
|
await this.opts.store.putInstalledSkill({
|
|
@@ -33988,11 +34012,11 @@ ${input.description}
|
|
|
33988
34012
|
* 删除技能的单个支撑文件(SKILL.md 主文档受保护,调用方应先拦截)。
|
|
33989
34013
|
* 单文件删除=读现有清单→剔除该 path→整体回写(putSkillFiles 是 replace-all 语义);blob 残留由 GC 回收。
|
|
33990
34014
|
*/
|
|
33991
|
-
async deleteSkillFile(skillId,
|
|
34015
|
+
async deleteSkillFile(skillId, path20) {
|
|
33992
34016
|
const cur = (await this.opts.store.listInstalledSkills()).find((x2) => x2.id === skillId);
|
|
33993
34017
|
if (!cur) throw new Error(`\u672A\u5B89\u88C5\u8BE5\u6280\u80FD\uFF1A${skillId}`);
|
|
33994
34018
|
const existing = await this.opts.store.listSkillFiles(skillId);
|
|
33995
|
-
const next = existing.filter((f2) => f2.path !==
|
|
34019
|
+
const next = existing.filter((f2) => f2.path !== path20);
|
|
33996
34020
|
if (next.length === existing.length) return;
|
|
33997
34021
|
await this.opts.store.putSkillFiles(skillId, next);
|
|
33998
34022
|
}
|
|
@@ -34338,15 +34362,30 @@ function priceForModel(model) {
|
|
|
34338
34362
|
function estimateRowCost(row) {
|
|
34339
34363
|
return estimateUsageCost(row.effectiveModel, row);
|
|
34340
34364
|
}
|
|
34341
|
-
function
|
|
34365
|
+
function estimateUsageCostBreakdown(model, usage) {
|
|
34342
34366
|
const price = priceForModel(model);
|
|
34343
34367
|
if (!price) return null;
|
|
34344
34368
|
const inputTokens = Math.max(usage.inputTokens ?? 0, 0);
|
|
34345
34369
|
const outputTokens = Math.max(usage.outputTokens ?? 0, 0);
|
|
34346
34370
|
const cacheReadTokens = Math.max(usage.cacheReadTokens ?? 0, 0);
|
|
34347
34371
|
const cacheCreationTokens = Math.max(usage.cacheCreationTokens ?? 0, 0);
|
|
34348
|
-
const
|
|
34349
|
-
return {
|
|
34372
|
+
const cacheReadPrice = price.cachedInputPerMillion ?? price.inputPerMillion * 0.1;
|
|
34373
|
+
return {
|
|
34374
|
+
currency: price.currency,
|
|
34375
|
+
inputMicros: Math.round(inputTokens * price.inputPerMillion / 1e6 * 1e6),
|
|
34376
|
+
cacheMicros: Math.round(
|
|
34377
|
+
(cacheCreationTokens * price.inputPerMillion + cacheReadTokens * cacheReadPrice) / 1e6 * 1e6
|
|
34378
|
+
),
|
|
34379
|
+
outputMicros: Math.round(outputTokens * price.outputPerMillion / 1e6 * 1e6)
|
|
34380
|
+
};
|
|
34381
|
+
}
|
|
34382
|
+
function estimateUsageCost(model, usage) {
|
|
34383
|
+
const breakdown = estimateUsageCostBreakdown(model, usage);
|
|
34384
|
+
if (!breakdown) return null;
|
|
34385
|
+
return {
|
|
34386
|
+
currency: breakdown.currency,
|
|
34387
|
+
micros: breakdown.inputMicros + breakdown.cacheMicros + breakdown.outputMicros
|
|
34388
|
+
};
|
|
34350
34389
|
}
|
|
34351
34390
|
var FOREIGN_MODEL_MARKUP, usd, cny, MODEL_PRICES, PREFIX_PRICES;
|
|
34352
34391
|
var init_model_pricing = __esm({
|
|
@@ -34461,6 +34500,30 @@ var init_model_pricing = __esm({
|
|
|
34461
34500
|
});
|
|
34462
34501
|
|
|
34463
34502
|
// ../server/src/domains/actors/stats.ts
|
|
34503
|
+
function emptyCostBreakdown() {
|
|
34504
|
+
return {
|
|
34505
|
+
inputUsdMicros: 0,
|
|
34506
|
+
cacheUsdMicros: 0,
|
|
34507
|
+
outputUsdMicros: 0,
|
|
34508
|
+
inputCnyMicros: 0,
|
|
34509
|
+
cacheCnyMicros: 0,
|
|
34510
|
+
outputCnyMicros: 0
|
|
34511
|
+
};
|
|
34512
|
+
}
|
|
34513
|
+
function addEstimatedBreakdown(target, model, usage) {
|
|
34514
|
+
const estimated = estimateUsageCostBreakdown(model, usage);
|
|
34515
|
+
if (!estimated) return false;
|
|
34516
|
+
if (estimated.currency === "USD") {
|
|
34517
|
+
target.inputUsdMicros += estimated.inputMicros;
|
|
34518
|
+
target.cacheUsdMicros += estimated.cacheMicros;
|
|
34519
|
+
target.outputUsdMicros += estimated.outputMicros;
|
|
34520
|
+
} else {
|
|
34521
|
+
target.inputCnyMicros += estimated.inputMicros;
|
|
34522
|
+
target.cacheCnyMicros += estimated.cacheMicros;
|
|
34523
|
+
target.outputCnyMicros += estimated.outputMicros;
|
|
34524
|
+
}
|
|
34525
|
+
return true;
|
|
34526
|
+
}
|
|
34464
34527
|
async function actorStats(oplog, actorId, opts = {}) {
|
|
34465
34528
|
const myRevisions = /* @__PURE__ */ new Set();
|
|
34466
34529
|
const mergedTargets = /* @__PURE__ */ new Set();
|
|
@@ -34504,8 +34567,10 @@ async function actorStats(oplog, actorId, opts = {}) {
|
|
|
34504
34567
|
approveRateGiven: reviewsGiven === 0 ? null : approvalsGiven / reviewsGiven,
|
|
34505
34568
|
reworkReceived,
|
|
34506
34569
|
tokenWeek: weeklyUsage.tokenWeek,
|
|
34570
|
+
tokenWeekBreakdown: weeklyUsage.tokenWeekBreakdown,
|
|
34507
34571
|
costWeekUsdMicros: weeklyUsage.costWeekUsdMicros,
|
|
34508
34572
|
costWeekCnyMicros: weeklyUsage.costWeekCnyMicros,
|
|
34573
|
+
costWeekBreakdown: weeklyUsage.costWeekBreakdown,
|
|
34509
34574
|
usageWindow: { from, to },
|
|
34510
34575
|
unpricedModels: weeklyUsage.unpricedModels
|
|
34511
34576
|
};
|
|
@@ -34521,61 +34586,86 @@ async function listWeeklyRuns(trace, actorId, from, to) {
|
|
|
34521
34586
|
return out;
|
|
34522
34587
|
}
|
|
34523
34588
|
function summarizeWeeklyRuns(runs) {
|
|
34524
|
-
let
|
|
34589
|
+
let input = 0;
|
|
34590
|
+
let cache = 0;
|
|
34591
|
+
let output = 0;
|
|
34525
34592
|
let costWeekUsdMicros = 0;
|
|
34526
34593
|
let costWeekCnyMicros = 0;
|
|
34594
|
+
const costWeekBreakdown = emptyCostBreakdown();
|
|
34527
34595
|
const unpriced = /* @__PURE__ */ new Set();
|
|
34528
34596
|
for (const run of runs) {
|
|
34529
34597
|
const usage = run.usage;
|
|
34530
34598
|
if (!usage) continue;
|
|
34531
|
-
const
|
|
34532
|
-
const
|
|
34533
|
-
|
|
34599
|
+
const inputTokens = Math.max(usage.inputTokens ?? 0, 0);
|
|
34600
|
+
const outputTokens = Math.max(usage.outputTokens ?? 0, 0);
|
|
34601
|
+
const cacheCreation = Math.max(usage.cacheCreationTokens ?? 0, 0);
|
|
34602
|
+
const cacheRead = Math.max(usage.cacheReadTokens ?? 0, 0);
|
|
34603
|
+
input += inputTokens;
|
|
34604
|
+
cache += cacheCreation + cacheRead;
|
|
34605
|
+
output += outputTokens;
|
|
34606
|
+
const priced = addEstimatedBreakdown(costWeekBreakdown, run.effectiveModel ?? null, usage);
|
|
34607
|
+
const storedCost = Math.max(usage.costUsdMicros ?? 0, 0);
|
|
34608
|
+
if (storedCost > 0) {
|
|
34609
|
+
costWeekUsdMicros += storedCost;
|
|
34610
|
+
continue;
|
|
34611
|
+
}
|
|
34534
34612
|
const estimated = estimateUsageCost(run.effectiveModel, usage);
|
|
34535
34613
|
if (estimated) {
|
|
34536
34614
|
if (estimated.currency === "USD") costWeekUsdMicros += estimated.micros;
|
|
34537
34615
|
else costWeekCnyMicros += estimated.micros;
|
|
34538
34616
|
continue;
|
|
34539
34617
|
}
|
|
34540
|
-
|
|
34541
|
-
if (storedCost > 0) {
|
|
34542
|
-
costWeekUsdMicros += storedCost;
|
|
34543
|
-
} else if (input + output > 0) {
|
|
34618
|
+
if (!priced && inputTokens + outputTokens + cacheCreation + cacheRead > 0) {
|
|
34544
34619
|
unpriced.add(run.effectiveModel ?? "unknown");
|
|
34545
34620
|
}
|
|
34546
34621
|
}
|
|
34547
34622
|
return {
|
|
34548
|
-
tokenWeek,
|
|
34623
|
+
tokenWeek: input + cache + output,
|
|
34624
|
+
tokenWeekBreakdown: { input, cache, output },
|
|
34549
34625
|
costWeekUsdMicros,
|
|
34550
34626
|
costWeekCnyMicros,
|
|
34627
|
+
costWeekBreakdown,
|
|
34551
34628
|
unpricedModels: [...unpriced].sort()
|
|
34552
34629
|
};
|
|
34553
34630
|
}
|
|
34554
34631
|
function summarizeWeeklyUsage(rows) {
|
|
34555
|
-
let
|
|
34632
|
+
let input = 0;
|
|
34633
|
+
let cache = 0;
|
|
34634
|
+
let output = 0;
|
|
34556
34635
|
let costWeekUsdMicros = 0;
|
|
34557
34636
|
let costWeekCnyMicros = 0;
|
|
34637
|
+
const costWeekBreakdown = emptyCostBreakdown();
|
|
34558
34638
|
const unpriced = /* @__PURE__ */ new Set();
|
|
34559
34639
|
for (const row of rows) {
|
|
34560
|
-
const
|
|
34561
|
-
const
|
|
34562
|
-
|
|
34640
|
+
const inputTokens = Math.max(row.inputTokens, 0);
|
|
34641
|
+
const outputTokens = Math.max(row.outputTokens, 0);
|
|
34642
|
+
const cacheCreation = Math.max(row.cacheCreationTokens, 0);
|
|
34643
|
+
const cacheRead = Math.max(row.cacheReadTokens, 0);
|
|
34644
|
+
input += inputTokens;
|
|
34645
|
+
cache += cacheCreation + cacheRead;
|
|
34646
|
+
output += outputTokens;
|
|
34647
|
+
const priced = addEstimatedBreakdown(costWeekBreakdown, row.effectiveModel, row);
|
|
34648
|
+
const storedCost = Math.max(row.costUsdMicros, 0);
|
|
34649
|
+
if (storedCost > 0) {
|
|
34650
|
+
costWeekUsdMicros += storedCost;
|
|
34651
|
+
continue;
|
|
34652
|
+
}
|
|
34563
34653
|
const estimated = estimateRowCost(row);
|
|
34564
34654
|
if (estimated) {
|
|
34565
34655
|
if (estimated.currency === "USD") costWeekUsdMicros += estimated.micros;
|
|
34566
34656
|
else costWeekCnyMicros += estimated.micros;
|
|
34567
34657
|
continue;
|
|
34568
34658
|
}
|
|
34569
|
-
if (
|
|
34570
|
-
costWeekUsdMicros += row.costUsdMicros;
|
|
34571
|
-
} else if (input + output > 0) {
|
|
34659
|
+
if (!priced && inputTokens + outputTokens + cacheCreation + cacheRead > 0) {
|
|
34572
34660
|
unpriced.add(row.effectiveModel ?? "unknown");
|
|
34573
34661
|
}
|
|
34574
34662
|
}
|
|
34575
34663
|
return {
|
|
34576
|
-
tokenWeek,
|
|
34664
|
+
tokenWeek: input + cache + output,
|
|
34665
|
+
tokenWeekBreakdown: { input, cache, output },
|
|
34577
34666
|
costWeekUsdMicros,
|
|
34578
34667
|
costWeekCnyMicros,
|
|
34668
|
+
costWeekBreakdown,
|
|
34579
34669
|
unpricedModels: [...unpriced].sort()
|
|
34580
34670
|
};
|
|
34581
34671
|
}
|
|
@@ -36770,27 +36860,188 @@ var init_sender = __esm({
|
|
|
36770
36860
|
}
|
|
36771
36861
|
});
|
|
36772
36862
|
|
|
36773
|
-
// ../adapters/src/open-design/
|
|
36774
|
-
function numEnv(name, fallback) {
|
|
36775
|
-
const v2 = process.env[name];
|
|
36776
|
-
const n = Number(v2);
|
|
36777
|
-
return v2 !== void 0 && v2 !== "" && Number.isFinite(n) && n > 0 ? n : fallback;
|
|
36778
|
-
}
|
|
36863
|
+
// ../adapters/src/open-design/driver.ts
|
|
36779
36864
|
function deriveBoardKey(artifactId) {
|
|
36780
36865
|
const tail = artifactId.split(":").pop() ?? artifactId;
|
|
36781
36866
|
const ascii = tail.replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 24);
|
|
36782
36867
|
const sha8 = (0, import_node_crypto10.createHash)("sha256").update(artifactId).digest("hex").slice(0, 8);
|
|
36783
36868
|
return ascii ? `od-${ascii}-${sha8}` : `od-${sha8}`;
|
|
36784
36869
|
}
|
|
36785
|
-
|
|
36786
|
-
|
|
36787
|
-
|
|
36870
|
+
async function odApi(base, fetchImpl, method, p2, body) {
|
|
36871
|
+
const res = await fetchImpl(`${base}${p2}`, {
|
|
36872
|
+
method,
|
|
36873
|
+
...body !== void 0 ? { body: JSON.stringify(body), headers: { "content-type": "application/json" } } : {}
|
|
36874
|
+
});
|
|
36875
|
+
if (!res.ok) throw new Error(`od ${method} ${p2} \u2192 ${res.status}: ${(await res.text()).slice(0, 200)}`);
|
|
36876
|
+
return await res.json();
|
|
36877
|
+
}
|
|
36878
|
+
async function ensureProject(base, fetchImpl, boardKey, title) {
|
|
36879
|
+
let conversationId = null;
|
|
36880
|
+
try {
|
|
36881
|
+
const created = await odApi(base, fetchImpl, "POST", "/api/projects", { id: boardKey, name: title });
|
|
36882
|
+
conversationId = created.conversationId ?? null;
|
|
36883
|
+
} catch {
|
|
36884
|
+
}
|
|
36885
|
+
if (!conversationId) {
|
|
36886
|
+
const c = await odApi(base, fetchImpl, "GET", `/api/projects/${encodeURIComponent(boardKey)}/conversations`);
|
|
36887
|
+
conversationId = c.conversations?.[0]?.id ?? null;
|
|
36888
|
+
}
|
|
36889
|
+
if (!conversationId) throw new Error(`od \u9879\u76EE ${boardKey} \u65E0\u53EF\u7528\u4F1A\u8BDD`);
|
|
36890
|
+
let resolvedDir = null;
|
|
36891
|
+
try {
|
|
36892
|
+
const d = await odApi(base, fetchImpl, "GET", `/api/projects/${encodeURIComponent(boardKey)}`);
|
|
36893
|
+
resolvedDir = d.resolvedDir ?? null;
|
|
36894
|
+
} catch {
|
|
36895
|
+
}
|
|
36896
|
+
return { conversationId, resolvedDir };
|
|
36897
|
+
}
|
|
36898
|
+
function materializeContext(resolvedDir, files) {
|
|
36899
|
+
if (!resolvedDir) return;
|
|
36900
|
+
fs6.mkdirSync(resolvedDir, { recursive: true });
|
|
36901
|
+
const root = path5.join(resolvedDir, "task-context");
|
|
36902
|
+
fs6.rmSync(root, { recursive: true, force: true });
|
|
36903
|
+
for (const [rel, content] of Object.entries(files)) {
|
|
36904
|
+
const f2 = path5.join(root, rel);
|
|
36905
|
+
fs6.mkdirSync(path5.dirname(f2), { recursive: true });
|
|
36906
|
+
fs6.writeFileSync(f2, content);
|
|
36907
|
+
}
|
|
36908
|
+
}
|
|
36909
|
+
async function startDesignRun(base, fetchImpl, args) {
|
|
36910
|
+
const created = await odApi(base, fetchImpl, "POST", "/api/runs", {
|
|
36911
|
+
agentId: args.agentId,
|
|
36912
|
+
projectId: args.boardKey,
|
|
36913
|
+
conversationId: args.conversationId,
|
|
36914
|
+
assistantMessageId: (0, import_node_crypto10.randomUUID)(),
|
|
36915
|
+
clientRequestId: (0, import_node_crypto10.randomUUID)(),
|
|
36916
|
+
message: args.message,
|
|
36917
|
+
systemPrompt: args.systemPrompt
|
|
36918
|
+
});
|
|
36919
|
+
return created.runId;
|
|
36920
|
+
}
|
|
36921
|
+
async function pumpDesignEvents(base, fetchImpl, runId, onLine) {
|
|
36922
|
+
const res = await fetchImpl(`${base}/api/runs/${runId}/events`);
|
|
36923
|
+
if (!res.ok || !res.body) return;
|
|
36924
|
+
const reader = res.body.getReader();
|
|
36925
|
+
const dec2 = new TextDecoder();
|
|
36926
|
+
let buf = "";
|
|
36927
|
+
for (; ; ) {
|
|
36928
|
+
const { done, value } = await reader.read();
|
|
36929
|
+
if (done) break;
|
|
36930
|
+
buf += dec2.decode(value, { stream: true });
|
|
36931
|
+
let nl;
|
|
36932
|
+
while ((nl = buf.indexOf("\n")) >= 0) {
|
|
36933
|
+
const line = buf.slice(0, nl).trim();
|
|
36934
|
+
buf = buf.slice(nl + 1);
|
|
36935
|
+
if (line.startsWith("data:")) {
|
|
36936
|
+
const payload = line.slice(5).trim();
|
|
36937
|
+
if (payload) onLine(payload);
|
|
36938
|
+
}
|
|
36939
|
+
}
|
|
36940
|
+
}
|
|
36941
|
+
}
|
|
36942
|
+
async function pollDesignRun(base, fetchImpl, runId, opts = {}) {
|
|
36943
|
+
const interval = opts.intervalMs ?? 5e3;
|
|
36944
|
+
const maxMs = opts.maxMs ?? 30 * 6e4;
|
|
36945
|
+
const started = Date.now();
|
|
36946
|
+
for (; ; ) {
|
|
36947
|
+
await new Promise((r) => setTimeout(r, interval));
|
|
36948
|
+
const s2 = await odApi(base, fetchImpl, "GET", `/api/runs/${runId}`).catch(() => null);
|
|
36949
|
+
if (!s2) {
|
|
36950
|
+
if (Date.now() - started > maxMs) throw new Error(`od run ${runId} \u8F6E\u8BE2\u8D85\u65F6\uFF08${Math.round(maxMs / 6e4)}min \u65E0\u7EC8\u6001\uFF09`);
|
|
36951
|
+
continue;
|
|
36952
|
+
}
|
|
36953
|
+
opts.onPoll?.(s2.status);
|
|
36954
|
+
if (s2.status === "succeeded" || s2.status === "failed" || s2.status === "canceled") return s2.status;
|
|
36955
|
+
if (Date.now() - started > maxMs) throw new Error(`od run ${runId} \u8F6E\u8BE2\u8D85\u65F6\uFF08${Math.round(maxMs / 6e4)}min \u672A\u6536\u5C3E\uFF0C\u672B\u72B6\u6001 ${s2.status}\uFF09`);
|
|
36956
|
+
}
|
|
36957
|
+
}
|
|
36958
|
+
async function harvestBoard(base, fetchImpl, publicBase, workRoot, boardKey, runId) {
|
|
36959
|
+
const listing = await odApi(
|
|
36960
|
+
base,
|
|
36961
|
+
fetchImpl,
|
|
36962
|
+
"GET",
|
|
36963
|
+
`/api/projects/${encodeURIComponent(boardKey)}/files`
|
|
36964
|
+
);
|
|
36965
|
+
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));
|
|
36966
|
+
const entry = htmls[0]?.path;
|
|
36967
|
+
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");
|
|
36968
|
+
const dir = fs6.mkdtempSync(path5.join(workRoot, "od-deliverable-"));
|
|
36969
|
+
const fetchInline = async (rel) => {
|
|
36970
|
+
const res = await fetchImpl(`${base}/api/projects/${encodeURIComponent(boardKey)}/export/${encodeURIComponent(rel)}?inline=1`);
|
|
36971
|
+
if (!res.ok) throw new Error(`od export ${rel} \u2192 ${res.status}`);
|
|
36972
|
+
return await res.text();
|
|
36973
|
+
};
|
|
36974
|
+
fs6.writeFileSync(path5.join(dir, "index.html"), await fetchInline(entry));
|
|
36975
|
+
for (const f2 of listing.files ?? []) {
|
|
36976
|
+
if (f2.path.endsWith(".md") && !f2.path.includes("/")) {
|
|
36977
|
+
try {
|
|
36978
|
+
fs6.writeFileSync(path5.join(dir, f2.path), await fetchInline(f2.path));
|
|
36979
|
+
} catch {
|
|
36980
|
+
}
|
|
36981
|
+
}
|
|
36982
|
+
}
|
|
36983
|
+
fs6.writeFileSync(
|
|
36984
|
+
path5.join(dir, "board.link"),
|
|
36985
|
+
`${publicBase}/projects/${boardKey}
|
|
36986
|
+
\u5165\u53E3\u7A3F\uFF1A${entry}
|
|
36987
|
+
\u5FEB\u7167\u6765\u6E90 run\uFF1A${runId}
|
|
36988
|
+
\uFF08\u6D3B\u753B\u677F\u2014\u2014\u7EE7\u7EED\u8FED\u4EE3\u8BF7\u56DE\u5230\u8BE5\u9879\u76EE\uFF1B\u672C\u88C5\u7BB1\u5355\u4E3A\u8BE5\u6B21\u4EA4\u4ED8\u7684\u51BB\u7ED3\u5FEB\u7167\uFF09
|
|
36989
|
+
`
|
|
36990
|
+
);
|
|
36991
|
+
return { dir, entry };
|
|
36992
|
+
}
|
|
36993
|
+
async function runOpenDesignSession(opts) {
|
|
36994
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
36995
|
+
const workRoot = opts.workRoot ?? os.tmpdir();
|
|
36996
|
+
const boardKey = deriveBoardKey(opts.artifactId);
|
|
36997
|
+
const { conversationId, resolvedDir } = await ensureProject(opts.base, fetchImpl, boardKey, opts.title);
|
|
36998
|
+
if (opts.contextFiles) materializeContext(resolvedDir, opts.contextFiles);
|
|
36999
|
+
const runId = await startDesignRun(opts.base, fetchImpl, {
|
|
37000
|
+
agentId: opts.agentId,
|
|
37001
|
+
boardKey,
|
|
37002
|
+
conversationId,
|
|
37003
|
+
message: opts.message,
|
|
37004
|
+
systemPrompt: opts.systemPrompt
|
|
37005
|
+
});
|
|
37006
|
+
if (opts.onLine) void pumpDesignEvents(opts.base, fetchImpl, runId, opts.onLine).catch(() => {
|
|
37007
|
+
});
|
|
37008
|
+
const status = await pollDesignRun(opts.base, fetchImpl, runId, {
|
|
37009
|
+
...opts.pollIntervalMs !== void 0 ? { intervalMs: opts.pollIntervalMs } : {},
|
|
37010
|
+
...opts.pollMaxMs !== void 0 ? { maxMs: opts.pollMaxMs } : {}
|
|
37011
|
+
});
|
|
37012
|
+
if (status === "canceled") throw new Error(`od run ${runId} \u88AB\u53D6\u6D88`);
|
|
37013
|
+
if (status === "failed") throw new Error(`od run ${runId} \u5931\u8D25`);
|
|
37014
|
+
const { dir, entry } = await harvestBoard(opts.base, fetchImpl, opts.publicBase, workRoot, boardKey, runId);
|
|
37015
|
+
return { dir, entry, boardKey, runId };
|
|
37016
|
+
}
|
|
37017
|
+
var import_node_crypto10, fs6, os, path5;
|
|
37018
|
+
var init_driver = __esm({
|
|
37019
|
+
"../adapters/src/open-design/driver.ts"() {
|
|
36788
37020
|
"use strict";
|
|
36789
37021
|
import_node_crypto10 = require("node:crypto");
|
|
36790
|
-
import_node_child_process2 = require("node:child_process");
|
|
36791
37022
|
fs6 = __toESM(require("node:fs"), 1);
|
|
36792
37023
|
os = __toESM(require("node:os"), 1);
|
|
36793
37024
|
path5 = __toESM(require("node:path"), 1);
|
|
37025
|
+
}
|
|
37026
|
+
});
|
|
37027
|
+
|
|
37028
|
+
// ../adapters/src/open-design/index.ts
|
|
37029
|
+
function numEnv(name, fallback) {
|
|
37030
|
+
const v2 = process.env[name];
|
|
37031
|
+
const n = Number(v2);
|
|
37032
|
+
return v2 !== void 0 && v2 !== "" && Number.isFinite(n) && n > 0 ? n : fallback;
|
|
37033
|
+
}
|
|
37034
|
+
var import_node_crypto11, import_node_child_process2, fs7, os2, path6, TOOL_RESULT_SNIPPET, DELTA_FLUSH_MS, TELEMETRY_HEARTBEAT_MS, OdEventTranslator, OpenDesignAdapter;
|
|
37035
|
+
var init_open_design = __esm({
|
|
37036
|
+
"../adapters/src/open-design/index.ts"() {
|
|
37037
|
+
"use strict";
|
|
37038
|
+
import_node_crypto11 = require("node:crypto");
|
|
37039
|
+
import_node_child_process2 = require("node:child_process");
|
|
37040
|
+
fs7 = __toESM(require("node:fs"), 1);
|
|
37041
|
+
os2 = __toESM(require("node:os"), 1);
|
|
37042
|
+
path6 = __toESM(require("node:path"), 1);
|
|
37043
|
+
init_driver();
|
|
37044
|
+
init_driver();
|
|
36794
37045
|
TOOL_RESULT_SNIPPET = 2e3;
|
|
36795
37046
|
DELTA_FLUSH_MS = 2e4;
|
|
36796
37047
|
TELEMETRY_HEARTBEAT_MS = 12e4;
|
|
@@ -36876,7 +37127,7 @@ var init_open_design = __esm({
|
|
|
36876
37127
|
this.publicBase = (opts.publicBaseUrl ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
36877
37128
|
this.agentId = opts.agentId ?? "claude";
|
|
36878
37129
|
this.oasisBin = opts.oasisBin ?? "oasis";
|
|
36879
|
-
this.workRoot = opts.workRoot ??
|
|
37130
|
+
this.workRoot = opts.workRoot ?? os2.tmpdir();
|
|
36880
37131
|
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
36881
37132
|
this.maxConcurrent = opts.maxConcurrent ?? numEnv("OASIS_OPEN_DESIGN_MAX_CONCURRENT", 2);
|
|
36882
37133
|
this.runPropose = opts.runPropose ?? (async ({ artifactId, dir, reason, serverUrl, token }) => {
|
|
@@ -36909,91 +37160,16 @@ var init_open_design = __esm({
|
|
|
36909
37160
|
this.active--;
|
|
36910
37161
|
this.waiters.shift()?.();
|
|
36911
37162
|
}
|
|
36912
|
-
async api(method, p2, body) {
|
|
36913
|
-
const res = await this.fetchImpl(`${this.base}${p2}`, {
|
|
36914
|
-
method,
|
|
36915
|
-
...body !== void 0 ? { body: JSON.stringify(body), headers: { "content-type": "application/json" } } : {}
|
|
36916
|
-
});
|
|
36917
|
-
if (!res.ok) throw new Error(`od ${method} ${p2} \u2192 ${res.status}: ${(await res.text()).slice(0, 200)}`);
|
|
36918
|
-
return await res.json();
|
|
36919
|
-
}
|
|
36920
|
-
/** 项目就绪(幂等):不存在则建(显式 id=派生 key);已存在则取既有会话。返回 conversationId + 项目目录。 */
|
|
36921
|
-
async ensureProject(boardKey, title) {
|
|
36922
|
-
let conversationId = null;
|
|
36923
|
-
try {
|
|
36924
|
-
const created = await this.api("POST", "/api/projects", { id: boardKey, name: title });
|
|
36925
|
-
conversationId = created.conversationId ?? null;
|
|
36926
|
-
} catch {
|
|
36927
|
-
}
|
|
36928
|
-
if (!conversationId) {
|
|
36929
|
-
const c = await this.api("GET", `/api/projects/${encodeURIComponent(boardKey)}/conversations`);
|
|
36930
|
-
conversationId = c.conversations?.[0]?.id ?? null;
|
|
36931
|
-
}
|
|
36932
|
-
if (!conversationId) throw new Error(`od \u9879\u76EE ${boardKey} \u65E0\u53EF\u7528\u4F1A\u8BDD`);
|
|
36933
|
-
let resolvedDir = null;
|
|
36934
|
-
try {
|
|
36935
|
-
const d = await this.api("GET", `/api/projects/${encodeURIComponent(boardKey)}`);
|
|
36936
|
-
resolvedDir = d.resolvedDir ?? null;
|
|
36937
|
-
} catch {
|
|
36938
|
-
}
|
|
36939
|
-
return { conversationId, resolvedDir };
|
|
36940
|
-
}
|
|
36941
|
-
/** 把派发 bundle 铺进画板项目的 task-context/(同机直写;TASK.md 里引用的 inputs/ 等由此可读)。 */
|
|
36942
|
-
materializeContext(resolvedDir, files) {
|
|
36943
|
-
if (!resolvedDir) return;
|
|
36944
|
-
fs6.mkdirSync(resolvedDir, { recursive: true });
|
|
36945
|
-
const root = path5.join(resolvedDir, "task-context");
|
|
36946
|
-
fs6.rmSync(root, { recursive: true, force: true });
|
|
36947
|
-
for (const [rel, content] of Object.entries(files)) {
|
|
36948
|
-
const f2 = path5.join(root, rel);
|
|
36949
|
-
fs6.mkdirSync(path5.dirname(f2), { recursive: true });
|
|
36950
|
-
fs6.writeFileSync(f2, content);
|
|
36951
|
-
}
|
|
36952
|
-
}
|
|
36953
|
-
/** 收割:挑最新完成态的 HTML 为入口导出(引用树收拢),连同项目内 .md 文档组装装箱单目录。 */
|
|
36954
|
-
async harvest(boardKey, runId) {
|
|
36955
|
-
const listing = await this.api(
|
|
36956
|
-
"GET",
|
|
36957
|
-
`/api/projects/${encodeURIComponent(boardKey)}/files`
|
|
36958
|
-
);
|
|
36959
|
-
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));
|
|
36960
|
-
const entry = htmls[0]?.path;
|
|
36961
|
-
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");
|
|
36962
|
-
const dir = fs6.mkdtempSync(path5.join(this.workRoot, "od-deliverable-"));
|
|
36963
|
-
const fetchInline = async (rel) => {
|
|
36964
|
-
const res = await this.fetchImpl(`${this.base}/api/projects/${encodeURIComponent(boardKey)}/export/${encodeURIComponent(rel)}?inline=1`);
|
|
36965
|
-
if (!res.ok) throw new Error(`od export ${rel} \u2192 ${res.status}`);
|
|
36966
|
-
return await res.text();
|
|
36967
|
-
};
|
|
36968
|
-
fs6.writeFileSync(path5.join(dir, "index.html"), await fetchInline(entry));
|
|
36969
|
-
for (const f2 of listing.files ?? []) {
|
|
36970
|
-
if (f2.path.endsWith(".md") && !f2.path.includes("/")) {
|
|
36971
|
-
try {
|
|
36972
|
-
fs6.writeFileSync(path5.join(dir, f2.path), await fetchInline(f2.path));
|
|
36973
|
-
} catch {
|
|
36974
|
-
}
|
|
36975
|
-
}
|
|
36976
|
-
}
|
|
36977
|
-
fs6.writeFileSync(
|
|
36978
|
-
path5.join(dir, "board.link"),
|
|
36979
|
-
`${this.publicBase}/projects/${boardKey}
|
|
36980
|
-
\u5165\u53E3\u7A3F\uFF1A${entry}
|
|
36981
|
-
\u5FEB\u7167\u6765\u6E90 run\uFF1A${runId}
|
|
36982
|
-
\uFF08\u6D3B\u753B\u677F\u2014\u2014\u7EE7\u7EED\u8FED\u4EE3\u8BF7\u56DE\u5230\u8BE5\u9879\u76EE\uFF1B\u672C\u88C5\u7BB1\u5355\u4E3A\u8BE5\u6B21\u4EA4\u4ED8\u7684\u51BB\u7ED3\u5FEB\u7167\uFF09
|
|
36983
|
-
`
|
|
36984
|
-
);
|
|
36985
|
-
return { dir, entry };
|
|
36986
|
-
}
|
|
36987
37163
|
async spawn(job) {
|
|
36988
37164
|
const boardKey = deriveBoardKey(job.artifactId);
|
|
36989
|
-
const id = `od-${boardKey}-${(0,
|
|
37165
|
+
const id = `od-${boardKey}-${(0, import_node_crypto11.randomUUID)().slice(0, 8)}`;
|
|
36990
37166
|
const exitCbs = [];
|
|
36991
37167
|
const outputCbs = [];
|
|
36992
37168
|
const telemetryCbs = [];
|
|
36993
37169
|
let exited = null;
|
|
36994
37170
|
let killed = false;
|
|
36995
37171
|
let runId = null;
|
|
36996
|
-
const transcriptRef =
|
|
37172
|
+
const transcriptRef = path6.join(this.workRoot, `od-transcript-${id}.ndjson`);
|
|
36997
37173
|
const translator = new OdEventTranslator();
|
|
36998
37174
|
let eventSeq = 0;
|
|
36999
37175
|
let lastTelemetryAt = Date.now();
|
|
@@ -37018,15 +37194,15 @@ var init_open_design = __esm({
|
|
|
37018
37194
|
finish({ code: null, reason: "timeout" });
|
|
37019
37195
|
return;
|
|
37020
37196
|
}
|
|
37021
|
-
const { conversationId, resolvedDir } = await this.
|
|
37022
|
-
|
|
37197
|
+
const { conversationId, resolvedDir } = await ensureProject(this.base, this.fetchImpl, boardKey, job.artifactId);
|
|
37198
|
+
materializeContext(resolvedDir, job.bundle.files);
|
|
37023
37199
|
const task = job.bundle.files["TASK.md"] ?? "";
|
|
37024
|
-
const created = await this.
|
|
37200
|
+
const created = await odApi(this.base, this.fetchImpl, "POST", "/api/runs", {
|
|
37025
37201
|
agentId: this.agentId,
|
|
37026
37202
|
projectId: boardKey,
|
|
37027
37203
|
conversationId,
|
|
37028
|
-
assistantMessageId: (0,
|
|
37029
|
-
clientRequestId: (0,
|
|
37204
|
+
assistantMessageId: (0, import_node_crypto11.randomUUID)(),
|
|
37205
|
+
clientRequestId: (0, import_node_crypto11.randomUUID)(),
|
|
37030
37206
|
message: task,
|
|
37031
37207
|
systemPrompt: "\u4F60\u662F\u8BBE\u8BA1\u5F15\u64CE\u4E2D\u7684\u754C\u9762\u8BBE\u8BA1\u5E08\u3002\u4EFB\u52A1\u4E66\u89C1\u672C\u6761\u6D88\u606F\uFF1B\u4E0A\u6E38\u8F93\u5165\u7B49\u4E0A\u4E0B\u6587\u6587\u4EF6\u5728\u9879\u76EE task-context/ \u76EE\u5F55\u3002\u6309\u4EFB\u52A1\u4E66\u7684\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u534F\u8BAE\u5DE5\u4F5C\uFF1A\u4EA7\u51FA\u81EA\u5305\u542B HTML \u5165\u53E3\u7A3F\u4E0E acceptance.md\uFF0C\u5B8C\u6210\u5373\u7ED3\u675F\u56DE\u590D\uFF0C\u4EA4\u7A3F\u7531\u7CFB\u7EDF\u4EE3\u529E\u3002"
|
|
37032
37208
|
});
|
|
@@ -37039,7 +37215,7 @@ var init_open_design = __esm({
|
|
|
37039
37215
|
let status = "running";
|
|
37040
37216
|
for (; ; ) {
|
|
37041
37217
|
await new Promise((r) => setTimeout(r, 5e3));
|
|
37042
|
-
const s2 = await this.
|
|
37218
|
+
const s2 = await odApi(this.base, this.fetchImpl, "GET", `/api/runs/${runId}`).catch(() => null);
|
|
37043
37219
|
if (!s2) continue;
|
|
37044
37220
|
status = s2.status;
|
|
37045
37221
|
if (status === "succeeded" || status === "failed" || status === "canceled") break;
|
|
@@ -37055,7 +37231,7 @@ var init_open_design = __esm({
|
|
|
37055
37231
|
finish({ code: 1, reason: "error" });
|
|
37056
37232
|
return;
|
|
37057
37233
|
}
|
|
37058
|
-
const { dir, entry } = await this.
|
|
37234
|
+
const { dir, entry } = await harvestBoard(this.base, this.fetchImpl, this.publicBase, this.workRoot, boardKey, runId);
|
|
37059
37235
|
await this.runPropose({
|
|
37060
37236
|
artifactId: job.artifactId,
|
|
37061
37237
|
dir,
|
|
@@ -37066,7 +37242,7 @@ var init_open_design = __esm({
|
|
|
37066
37242
|
finish({ code: 0, reason: "clean" });
|
|
37067
37243
|
} catch (err) {
|
|
37068
37244
|
try {
|
|
37069
|
-
|
|
37245
|
+
fs7.appendFileSync(transcriptRef, JSON.stringify({ kind: "adapter-error", message: String(err) }) + "\n");
|
|
37070
37246
|
} catch {
|
|
37071
37247
|
}
|
|
37072
37248
|
finish({ code: 1, reason: "error" });
|
|
@@ -37076,7 +37252,7 @@ var init_open_design = __esm({
|
|
|
37076
37252
|
})();
|
|
37077
37253
|
const cancel = async () => {
|
|
37078
37254
|
killed = true;
|
|
37079
|
-
if (runId) await this.
|
|
37255
|
+
if (runId) await odApi(this.base, this.fetchImpl, "POST", `/api/runs/${runId}/cancel`).catch(() => {
|
|
37080
37256
|
});
|
|
37081
37257
|
};
|
|
37082
37258
|
return {
|
|
@@ -37112,7 +37288,7 @@ var init_open_design = __esm({
|
|
|
37112
37288
|
const payload = line.slice(5).trim();
|
|
37113
37289
|
if (payload) {
|
|
37114
37290
|
try {
|
|
37115
|
-
|
|
37291
|
+
fs7.appendFileSync(transcriptRef, payload + "\n");
|
|
37116
37292
|
} catch {
|
|
37117
37293
|
}
|
|
37118
37294
|
onLine(payload);
|
|
@@ -37216,26 +37392,26 @@ function classifyExit(result) {
|
|
|
37216
37392
|
return void 0;
|
|
37217
37393
|
}
|
|
37218
37394
|
function conversationExists(sessionId) {
|
|
37219
|
-
const configDir = process.env["CLAUDE_CONFIG_DIR"] ||
|
|
37220
|
-
const projectsDir =
|
|
37395
|
+
const configDir = process.env["CLAUDE_CONFIG_DIR"] || path7.join(os3.homedir(), ".claude");
|
|
37396
|
+
const projectsDir = path7.join(configDir, "projects");
|
|
37221
37397
|
const target = `${sessionId}.jsonl`;
|
|
37222
37398
|
try {
|
|
37223
|
-
for (const proj of
|
|
37224
|
-
if (
|
|
37399
|
+
for (const proj of fs8.readdirSync(projectsDir)) {
|
|
37400
|
+
if (fs8.existsSync(path7.join(projectsDir, proj, target))) return true;
|
|
37225
37401
|
}
|
|
37226
37402
|
} catch {
|
|
37227
37403
|
}
|
|
37228
37404
|
return false;
|
|
37229
37405
|
}
|
|
37230
|
-
var import_node_child_process3,
|
|
37406
|
+
var import_node_child_process3, import_node_crypto12, fs8, os3, path7, readline, ClaudeCodeAdapter;
|
|
37231
37407
|
var init_claude_code = __esm({
|
|
37232
37408
|
"../adapters/src/claude-code/index.ts"() {
|
|
37233
37409
|
"use strict";
|
|
37234
37410
|
import_node_child_process3 = require("node:child_process");
|
|
37235
|
-
|
|
37236
|
-
|
|
37237
|
-
|
|
37238
|
-
|
|
37411
|
+
import_node_crypto12 = require("node:crypto");
|
|
37412
|
+
fs8 = __toESM(require("node:fs"), 1);
|
|
37413
|
+
os3 = __toESM(require("node:os"), 1);
|
|
37414
|
+
path7 = __toESM(require("node:path"), 1);
|
|
37239
37415
|
readline = __toESM(require("node:readline"), 1);
|
|
37240
37416
|
ClaudeCodeAdapter = class {
|
|
37241
37417
|
constructor(opts = {}) {
|
|
@@ -37264,9 +37440,9 @@ var init_claude_code = __esm({
|
|
|
37264
37440
|
}
|
|
37265
37441
|
async spawn(job) {
|
|
37266
37442
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
37267
|
-
const id = `claude-${slug6}-${(0,
|
|
37268
|
-
const dir = job.runtimeSessionId ?
|
|
37269
|
-
|
|
37443
|
+
const id = `claude-${slug6}-${(0, import_node_crypto12.randomUUID)().slice(0, 8)}`;
|
|
37444
|
+
const dir = job.runtimeSessionId ? path7.join(this.opts.workRoot ?? os3.tmpdir(), "oasis-chat-sessions", job.runtimeSessionId.replace(/[^a-zA-Z0-9_-]+/g, "_")) : fs8.mkdtempSync(path7.join(this.opts.workRoot ?? os3.tmpdir(), "oasis-session-"));
|
|
37445
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
37270
37446
|
if (this.opts.syncSkills) {
|
|
37271
37447
|
try {
|
|
37272
37448
|
await this.opts.syncSkills({
|
|
@@ -37281,14 +37457,14 @@ var init_claude_code = __esm({
|
|
|
37281
37457
|
}
|
|
37282
37458
|
}
|
|
37283
37459
|
for (const [rel, content] of Object.entries(job.bundle.files)) {
|
|
37284
|
-
const file =
|
|
37285
|
-
|
|
37286
|
-
|
|
37460
|
+
const file = path7.join(dir, rel);
|
|
37461
|
+
fs8.mkdirSync(path7.dirname(file), { recursive: true });
|
|
37462
|
+
fs8.writeFileSync(file, content);
|
|
37287
37463
|
}
|
|
37288
37464
|
for (const [rel, b64] of Object.entries(job.bundle.binaryFiles ?? {})) {
|
|
37289
|
-
const file =
|
|
37290
|
-
|
|
37291
|
-
|
|
37465
|
+
const file = path7.join(dir, rel);
|
|
37466
|
+
fs8.mkdirSync(path7.dirname(file), { recursive: true });
|
|
37467
|
+
fs8.writeFileSync(file, Buffer.from(b64, "base64"));
|
|
37292
37468
|
}
|
|
37293
37469
|
const prompt = job.bundle.files["TASK.md"];
|
|
37294
37470
|
if (!prompt) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
@@ -37320,7 +37496,7 @@ var init_claude_code = __esm({
|
|
|
37320
37496
|
...job.env,
|
|
37321
37497
|
// BUG-4 缓冲:抬高单响应输出 token 上限(临时缓冲,根治靠分解)
|
|
37322
37498
|
...this.opts.maxOutputTokens ? { CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(this.opts.maxOutputTokens) } : {},
|
|
37323
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
37499
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path7.dirname(p2)).join(path7.delimiter)}${path7.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
37324
37500
|
OASIS_SERVER: job.server.url,
|
|
37325
37501
|
OASIS_TOKEN: job.actorToken,
|
|
37326
37502
|
// OTel 遥测(默认关;resolveOtelEnv 决定开不开,runId 进 resource 属性自然归位到本次 run)。
|
|
@@ -37332,8 +37508,8 @@ var init_claude_code = __esm({
|
|
|
37332
37508
|
});
|
|
37333
37509
|
if (promptViaStdin) child.stdin.write(prompt);
|
|
37334
37510
|
child.stdin.end();
|
|
37335
|
-
let transcriptRef =
|
|
37336
|
-
const out =
|
|
37511
|
+
let transcriptRef = path7.join(dir, "transcript.txt");
|
|
37512
|
+
const out = fs8.createWriteStream(transcriptRef);
|
|
37337
37513
|
const telemetryCbs = [];
|
|
37338
37514
|
let eventSeq = 0;
|
|
37339
37515
|
let lastResult;
|
|
@@ -37403,14 +37579,14 @@ var init_claude_code = __esm({
|
|
|
37403
37579
|
const reason = killedByUs ? "timeout" : classifyExit(lastResult);
|
|
37404
37580
|
if (this.opts.cleanupWorkdir && !job.runtimeSessionId) {
|
|
37405
37581
|
try {
|
|
37406
|
-
const keepDir =
|
|
37407
|
-
|
|
37408
|
-
const kept =
|
|
37582
|
+
const keepDir = path7.join(this.opts.workRoot ?? os3.tmpdir(), "oasis-transcripts");
|
|
37583
|
+
fs8.mkdirSync(keepDir, { recursive: true });
|
|
37584
|
+
const kept = path7.join(keepDir, `${id}.txt`);
|
|
37409
37585
|
const src = transcriptRef;
|
|
37410
37586
|
out.end(() => {
|
|
37411
37587
|
try {
|
|
37412
|
-
|
|
37413
|
-
|
|
37588
|
+
fs8.renameSync(src, kept);
|
|
37589
|
+
fs8.rmSync(dir, { recursive: true, force: true });
|
|
37414
37590
|
} catch {
|
|
37415
37591
|
}
|
|
37416
37592
|
});
|
|
@@ -37589,7 +37765,7 @@ var init_resilient = __esm({
|
|
|
37589
37765
|
|
|
37590
37766
|
// ../adapters/src/_core/skill-cache.ts
|
|
37591
37767
|
function defaultCacheRoot() {
|
|
37592
|
-
return
|
|
37768
|
+
return path8.join(os4.homedir(), ".oasis", "skill-cache");
|
|
37593
37769
|
}
|
|
37594
37770
|
function sessionSkillsSubdir(runtimeKind) {
|
|
37595
37771
|
return runtimeKind === "claude" || runtimeKind === "claude-code" ? ".claude/skills" : ".agent_context/skills";
|
|
@@ -37600,7 +37776,7 @@ async function syncActorSkills(opts) {
|
|
|
37600
37776
|
});
|
|
37601
37777
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
37602
37778
|
const actorDir = pathForActor(cacheRoot, opts.actorId);
|
|
37603
|
-
const manifestPath =
|
|
37779
|
+
const manifestPath = path8.join(actorDir, "manifest.json");
|
|
37604
37780
|
await fsp.mkdir(actorDir, { recursive: true, mode: 493 });
|
|
37605
37781
|
const release = await acquireLock(cacheRoot, opts.actorId, now, log3);
|
|
37606
37782
|
try {
|
|
@@ -37618,7 +37794,7 @@ async function syncActorSkills(opts) {
|
|
|
37618
37794
|
const cloudIds = new Set(cloudMetadata.map((s2) => s2.id));
|
|
37619
37795
|
for (const cloud of cloudMetadata) {
|
|
37620
37796
|
const cached2 = manifest.skills[cloud.id];
|
|
37621
|
-
const skillDir =
|
|
37797
|
+
const skillDir = path8.join(actorDir, cloud.dir);
|
|
37622
37798
|
const inSync = cached2 && cached2.dir === cloud.dir && cached2.contentHash === cloud.contentHash && cached2.cloudUpdatedAt === cloud.updatedAt && await dirLooksValid(skillDir, cached2.fileList);
|
|
37623
37799
|
if (inSync) {
|
|
37624
37800
|
skipped += 1;
|
|
@@ -37646,7 +37822,7 @@ async function syncActorSkills(opts) {
|
|
|
37646
37822
|
for (const [id, entry] of Object.entries(manifest.skills)) {
|
|
37647
37823
|
if (cloudIds.has(id)) continue;
|
|
37648
37824
|
try {
|
|
37649
|
-
await fsp.rm(
|
|
37825
|
+
await fsp.rm(path8.join(actorDir, entry.dir), { recursive: true, force: true });
|
|
37650
37826
|
} catch (err) {
|
|
37651
37827
|
log3("warn", `\u5220\u9664\u5B64\u513F\u6280\u80FD\u76EE\u5F55\u5931\u8D25 ${entry.dir}`, err);
|
|
37652
37828
|
}
|
|
@@ -37663,14 +37839,14 @@ async function syncActorSkills(opts) {
|
|
|
37663
37839
|
}
|
|
37664
37840
|
}
|
|
37665
37841
|
function pathForActor(cacheRoot, actorId) {
|
|
37666
|
-
return
|
|
37842
|
+
return path8.join(cacheRoot, "actors", encodeURIComponent(actorId));
|
|
37667
37843
|
}
|
|
37668
37844
|
function lockPathFor(cacheRoot, actorId) {
|
|
37669
|
-
return
|
|
37845
|
+
return path8.join(cacheRoot, "locks", `${encodeURIComponent(actorId)}.lock`);
|
|
37670
37846
|
}
|
|
37671
37847
|
async function acquireLock(cacheRoot, actorId, now, log3) {
|
|
37672
37848
|
const lockPath = lockPathFor(cacheRoot, actorId);
|
|
37673
|
-
await fsp.mkdir(
|
|
37849
|
+
await fsp.mkdir(path8.dirname(lockPath), { recursive: true, mode: 493 });
|
|
37674
37850
|
const started = now().getTime();
|
|
37675
37851
|
while (true) {
|
|
37676
37852
|
try {
|
|
@@ -37736,26 +37912,26 @@ async function readManifest2(manifestPath, actorId, log3) {
|
|
|
37736
37912
|
};
|
|
37737
37913
|
}
|
|
37738
37914
|
async function writeManifest(manifestPath, manifest) {
|
|
37739
|
-
const dir =
|
|
37915
|
+
const dir = path8.dirname(manifestPath);
|
|
37740
37916
|
await fsp.mkdir(dir, { recursive: true });
|
|
37741
37917
|
const tmp = `${manifestPath}.${process.pid}.${Date.now()}.tmp`;
|
|
37742
37918
|
await fsp.writeFile(tmp, JSON.stringify(manifest, null, 2), { mode: 420 });
|
|
37743
37919
|
await fsp.rename(tmp, manifestPath);
|
|
37744
37920
|
}
|
|
37745
37921
|
async function materializeSkillDir(actorDir, targetDir, files, previousDir) {
|
|
37746
|
-
const targetPath =
|
|
37747
|
-
const tmpPath =
|
|
37748
|
-
const oldBackup =
|
|
37922
|
+
const targetPath = path8.join(actorDir, targetDir);
|
|
37923
|
+
const tmpPath = path8.join(actorDir, `${targetDir}.new.${process.pid}.${Date.now()}`);
|
|
37924
|
+
const oldBackup = path8.join(actorDir, `${targetDir}.old.${process.pid}.${Date.now()}`);
|
|
37749
37925
|
await fsp.rm(tmpPath, { recursive: true, force: true });
|
|
37750
37926
|
await fsp.mkdir(tmpPath, { recursive: true, mode: 493 });
|
|
37751
37927
|
for (const f2 of files) {
|
|
37752
37928
|
if (!f2.content) continue;
|
|
37753
|
-
const dest =
|
|
37754
|
-
const rel =
|
|
37755
|
-
if (rel.startsWith("..") ||
|
|
37929
|
+
const dest = path8.join(tmpPath, f2.path);
|
|
37930
|
+
const rel = path8.relative(tmpPath, dest);
|
|
37931
|
+
if (rel.startsWith("..") || path8.isAbsolute(rel)) {
|
|
37756
37932
|
throw new Error(`SkillFile.path \u4E0D\u5408\u6CD5: ${f2.path}`);
|
|
37757
37933
|
}
|
|
37758
|
-
await fsp.mkdir(
|
|
37934
|
+
await fsp.mkdir(path8.dirname(dest), { recursive: true });
|
|
37759
37935
|
await fsp.writeFile(dest, f2.content, { mode: 420 });
|
|
37760
37936
|
}
|
|
37761
37937
|
let hadOld = false;
|
|
@@ -37769,14 +37945,14 @@ async function materializeSkillDir(actorDir, targetDir, files, previousDir) {
|
|
|
37769
37945
|
await fsp.rename(tmpPath, targetPath);
|
|
37770
37946
|
if (hadOld) await fsp.rm(oldBackup, { recursive: true, force: true });
|
|
37771
37947
|
if (previousDir && previousDir !== targetDir) {
|
|
37772
|
-
await fsp.rm(
|
|
37948
|
+
await fsp.rm(path8.join(actorDir, previousDir), { recursive: true, force: true });
|
|
37773
37949
|
}
|
|
37774
37950
|
}
|
|
37775
37951
|
async function dirLooksValid(dir, expectFileList) {
|
|
37776
37952
|
if (expectFileList.length === 0) return false;
|
|
37777
37953
|
try {
|
|
37778
37954
|
for (const rel of expectFileList) {
|
|
37779
|
-
await fsp.stat(
|
|
37955
|
+
await fsp.stat(path8.join(dir, rel));
|
|
37780
37956
|
}
|
|
37781
37957
|
return true;
|
|
37782
37958
|
} catch {
|
|
@@ -37785,18 +37961,18 @@ async function dirLooksValid(dir, expectFileList) {
|
|
|
37785
37961
|
}
|
|
37786
37962
|
async function syncSessionSymlinks(sessionDir, runtimeKind, actorDir, manifest, log3) {
|
|
37787
37963
|
const subdir = sessionSkillsSubdir(runtimeKind);
|
|
37788
|
-
const skillsDir =
|
|
37964
|
+
const skillsDir = path8.join(sessionDir, subdir);
|
|
37789
37965
|
await fsp.mkdir(skillsDir, { recursive: true, mode: 493 });
|
|
37790
37966
|
const desired = /* @__PURE__ */ new Map();
|
|
37791
37967
|
for (const entry of Object.values(manifest.skills)) {
|
|
37792
|
-
desired.set(entry.dir,
|
|
37968
|
+
desired.set(entry.dir, path8.join(actorDir, entry.dir));
|
|
37793
37969
|
}
|
|
37794
37970
|
for (const [name, target] of desired) {
|
|
37795
|
-
const link =
|
|
37971
|
+
const link = path8.join(skillsDir, name);
|
|
37796
37972
|
let ok = false;
|
|
37797
37973
|
try {
|
|
37798
37974
|
const current = await fsp.readlink(link);
|
|
37799
|
-
ok =
|
|
37975
|
+
ok = path8.resolve(skillsDir, current) === target;
|
|
37800
37976
|
} catch {
|
|
37801
37977
|
}
|
|
37802
37978
|
if (!ok) {
|
|
@@ -37816,19 +37992,19 @@ async function syncSessionSymlinks(sessionDir, runtimeKind, actorDir, manifest,
|
|
|
37816
37992
|
for (const name of entries) {
|
|
37817
37993
|
if (desired.has(name)) continue;
|
|
37818
37994
|
try {
|
|
37819
|
-
await fsp.rm(
|
|
37995
|
+
await fsp.rm(path8.join(skillsDir, name), { recursive: true, force: true });
|
|
37820
37996
|
} catch (err) {
|
|
37821
37997
|
log3("warn", `\u6E05\u5B64\u513F\u5931\u8D25 ${name}`, err);
|
|
37822
37998
|
}
|
|
37823
37999
|
}
|
|
37824
38000
|
}
|
|
37825
|
-
var fsp,
|
|
38001
|
+
var fsp, os4, path8, MANIFEST_SCHEMA_VERSION, STALE_LOCK_MS, LOCK_ACQUIRE_TIMEOUT_MS, LOCK_POLL_MS;
|
|
37826
38002
|
var init_skill_cache = __esm({
|
|
37827
38003
|
"../adapters/src/_core/skill-cache.ts"() {
|
|
37828
38004
|
"use strict";
|
|
37829
38005
|
fsp = __toESM(require("node:fs/promises"), 1);
|
|
37830
|
-
|
|
37831
|
-
|
|
38006
|
+
os4 = __toESM(require("node:os"), 1);
|
|
38007
|
+
path8 = __toESM(require("node:path"), 1);
|
|
37832
38008
|
MANIFEST_SCHEMA_VERSION = 1;
|
|
37833
38009
|
STALE_LOCK_MS = 6e4;
|
|
37834
38010
|
LOCK_ACQUIRE_TIMEOUT_MS = 3e4;
|
|
@@ -38197,12 +38373,12 @@ function parseCodexModel(lines) {
|
|
|
38197
38373
|
function codexSessionsRoot() {
|
|
38198
38374
|
const candidates = [];
|
|
38199
38375
|
const ch = process.env["CODEX_HOME"];
|
|
38200
|
-
if (ch) candidates.push(
|
|
38201
|
-
const home = process.env["HOME"] ||
|
|
38202
|
-
if (home) candidates.push(
|
|
38376
|
+
if (ch) candidates.push(path9.join(ch, "sessions"));
|
|
38377
|
+
const home = process.env["HOME"] || os5.homedir();
|
|
38378
|
+
if (home) candidates.push(path9.join(home, ".codex", "sessions"));
|
|
38203
38379
|
for (const c of candidates) {
|
|
38204
38380
|
try {
|
|
38205
|
-
if (
|
|
38381
|
+
if (fs9.statSync(c).isDirectory()) return c;
|
|
38206
38382
|
} catch {
|
|
38207
38383
|
}
|
|
38208
38384
|
}
|
|
@@ -38216,13 +38392,13 @@ function codexRolloutExists(sessionId, root = codexSessionsRoot()) {
|
|
|
38216
38392
|
if (hit) return;
|
|
38217
38393
|
let ents;
|
|
38218
38394
|
try {
|
|
38219
|
-
ents =
|
|
38395
|
+
ents = fs9.readdirSync(d, { withFileTypes: true });
|
|
38220
38396
|
} catch {
|
|
38221
38397
|
return;
|
|
38222
38398
|
}
|
|
38223
38399
|
for (const ent of ents) {
|
|
38224
38400
|
if (hit) return;
|
|
38225
|
-
const p2 =
|
|
38401
|
+
const p2 = path9.join(d, ent.name);
|
|
38226
38402
|
if (ent.isDirectory()) walk(p2);
|
|
38227
38403
|
else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(suffix)) {
|
|
38228
38404
|
hit = true;
|
|
@@ -38239,17 +38415,17 @@ function listRecentRollouts(root, sinceMs) {
|
|
|
38239
38415
|
const walk = (d) => {
|
|
38240
38416
|
let ents;
|
|
38241
38417
|
try {
|
|
38242
|
-
ents =
|
|
38418
|
+
ents = fs9.readdirSync(d, { withFileTypes: true });
|
|
38243
38419
|
} catch {
|
|
38244
38420
|
return;
|
|
38245
38421
|
}
|
|
38246
38422
|
for (const ent of ents) {
|
|
38247
|
-
const p2 =
|
|
38423
|
+
const p2 = path9.join(d, ent.name);
|
|
38248
38424
|
if (ent.isDirectory()) walk(p2);
|
|
38249
38425
|
else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(".jsonl")) {
|
|
38250
38426
|
let m2 = 0;
|
|
38251
38427
|
try {
|
|
38252
|
-
m2 =
|
|
38428
|
+
m2 = fs9.statSync(p2).mtimeMs;
|
|
38253
38429
|
} catch {
|
|
38254
38430
|
}
|
|
38255
38431
|
if (m2 >= margin) found.push({ f: p2, m: m2 });
|
|
@@ -38264,7 +38440,7 @@ function scanCodexTelemetry(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
|
|
|
38264
38440
|
for (const f2 of listRecentRollouts(sessionsRoot, sinceMs)) {
|
|
38265
38441
|
let lines;
|
|
38266
38442
|
try {
|
|
38267
|
-
lines =
|
|
38443
|
+
lines = fs9.readFileSync(f2, "utf8").split("\n");
|
|
38268
38444
|
} catch {
|
|
38269
38445
|
continue;
|
|
38270
38446
|
}
|
|
@@ -38455,15 +38631,15 @@ function normalizeCodexConsoleLine(line, state = createCodexNormalizeState()) {
|
|
|
38455
38631
|
tool.output.push(line);
|
|
38456
38632
|
return [];
|
|
38457
38633
|
}
|
|
38458
|
-
var import_node_child_process5,
|
|
38634
|
+
var import_node_child_process5, import_node_crypto13, fs9, os5, path9, readline2, CodexAdapter;
|
|
38459
38635
|
var init_codex = __esm({
|
|
38460
38636
|
"../adapters/src/codex/index.ts"() {
|
|
38461
38637
|
"use strict";
|
|
38462
38638
|
import_node_child_process5 = require("node:child_process");
|
|
38463
|
-
|
|
38464
|
-
|
|
38465
|
-
|
|
38466
|
-
|
|
38639
|
+
import_node_crypto13 = require("node:crypto");
|
|
38640
|
+
fs9 = __toESM(require("node:fs"), 1);
|
|
38641
|
+
os5 = __toESM(require("node:os"), 1);
|
|
38642
|
+
path9 = __toESM(require("node:path"), 1);
|
|
38467
38643
|
readline2 = __toESM(require("node:readline"), 1);
|
|
38468
38644
|
init_claude_code();
|
|
38469
38645
|
CodexAdapter = class {
|
|
@@ -38472,13 +38648,13 @@ var init_codex = __esm({
|
|
|
38472
38648
|
}
|
|
38473
38649
|
async spawn(job) {
|
|
38474
38650
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
38475
|
-
const id = `codex-${slug6}-${(0,
|
|
38651
|
+
const id = `codex-${slug6}-${(0, import_node_crypto13.randomUUID)().slice(0, 8)}`;
|
|
38476
38652
|
const startedAtMs = Date.now();
|
|
38477
|
-
const dir =
|
|
38653
|
+
const dir = fs9.mkdtempSync(path9.join(this.opts.workRoot ?? os5.tmpdir(), "oasis-session-"));
|
|
38478
38654
|
for (const [rel, content] of Object.entries(job.bundle.files)) {
|
|
38479
|
-
const file =
|
|
38480
|
-
|
|
38481
|
-
|
|
38655
|
+
const file = path9.join(dir, rel);
|
|
38656
|
+
fs9.mkdirSync(path9.dirname(file), { recursive: true });
|
|
38657
|
+
fs9.writeFileSync(file, content);
|
|
38482
38658
|
}
|
|
38483
38659
|
const task = job.bundle.files["TASK.md"];
|
|
38484
38660
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
@@ -38507,14 +38683,14 @@ var init_codex = __esm({
|
|
|
38507
38683
|
...scrubLeakyEnv(process.env),
|
|
38508
38684
|
...this.opts.env,
|
|
38509
38685
|
...job.env,
|
|
38510
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
38686
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path9.dirname(p2)).join(path9.delimiter)}${path9.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
38511
38687
|
OASIS_SERVER: job.server.url,
|
|
38512
38688
|
OASIS_TOKEN: job.actorToken
|
|
38513
38689
|
},
|
|
38514
38690
|
stdio: ["ignore", "pipe", "pipe"]
|
|
38515
38691
|
});
|
|
38516
|
-
let transcriptRef =
|
|
38517
|
-
const out =
|
|
38692
|
+
let transcriptRef = path9.join(dir, "transcript.txt");
|
|
38693
|
+
const out = fs9.createWriteStream(transcriptRef);
|
|
38518
38694
|
const outputCbs = [];
|
|
38519
38695
|
const telemetryCbs = [];
|
|
38520
38696
|
const normalizeState = createCodexNormalizeState();
|
|
@@ -38527,14 +38703,34 @@ var init_codex = __esm({
|
|
|
38527
38703
|
for (const cb of telemetryCbs) cb(full);
|
|
38528
38704
|
}
|
|
38529
38705
|
};
|
|
38706
|
+
const stderrTail = [];
|
|
38707
|
+
const STDERR_MAX_LINES = 40;
|
|
38708
|
+
const STDERR_MAX_BYTES = 4e3;
|
|
38709
|
+
const pushStderrTail = (line) => {
|
|
38710
|
+
stderrTail.push(line);
|
|
38711
|
+
while (stderrTail.length > STDERR_MAX_LINES) stderrTail.shift();
|
|
38712
|
+
let total = stderrTail.reduce((n, l) => n + l.length + 1, 0);
|
|
38713
|
+
while (total > STDERR_MAX_BYTES && stderrTail.length > 1) {
|
|
38714
|
+
total -= stderrTail.shift().length + 1;
|
|
38715
|
+
}
|
|
38716
|
+
};
|
|
38717
|
+
const stdoutErrorLines = [];
|
|
38718
|
+
const pushStdoutErrorLine = (line) => {
|
|
38719
|
+
if (/^\s*(Error|error):/i.test(line) || /"error"\s*:/.test(line)) {
|
|
38720
|
+
stdoutErrorLines.push(line);
|
|
38721
|
+
if (stdoutErrorLines.length > 10) stdoutErrorLines.shift();
|
|
38722
|
+
}
|
|
38723
|
+
};
|
|
38530
38724
|
const rl = readline2.createInterface({ input: child.stdout });
|
|
38531
38725
|
rl.on("line", (line) => {
|
|
38532
38726
|
out.write(line + "\n");
|
|
38727
|
+
pushStdoutErrorLine(line);
|
|
38533
38728
|
emitNormalized(normalizeCodexStreamLine(line, normalizeState));
|
|
38534
38729
|
});
|
|
38535
38730
|
const errRl = readline2.createInterface({ input: child.stderr });
|
|
38536
38731
|
errRl.on("line", (line) => {
|
|
38537
38732
|
out.write(line + "\n");
|
|
38733
|
+
pushStderrTail(line);
|
|
38538
38734
|
emitNormalized(normalizeCodexConsoleLine(line, consoleNormalizeState));
|
|
38539
38735
|
});
|
|
38540
38736
|
const callbacks = [];
|
|
@@ -38544,14 +38740,14 @@ var init_codex = __esm({
|
|
|
38544
38740
|
if (exited) return;
|
|
38545
38741
|
if (this.opts.cleanupWorkdir) {
|
|
38546
38742
|
try {
|
|
38547
|
-
const keepDir =
|
|
38548
|
-
|
|
38549
|
-
const kept =
|
|
38743
|
+
const keepDir = path9.join(this.opts.workRoot ?? os5.tmpdir(), "oasis-transcripts");
|
|
38744
|
+
fs9.mkdirSync(keepDir, { recursive: true });
|
|
38745
|
+
const kept = path9.join(keepDir, `${id}.txt`);
|
|
38550
38746
|
const src = transcriptRef;
|
|
38551
38747
|
out.end(() => {
|
|
38552
38748
|
try {
|
|
38553
|
-
|
|
38554
|
-
|
|
38749
|
+
fs9.renameSync(src, kept);
|
|
38750
|
+
fs9.rmSync(dir, { recursive: true, force: true });
|
|
38555
38751
|
} catch {
|
|
38556
38752
|
}
|
|
38557
38753
|
});
|
|
@@ -38576,13 +38772,16 @@ var init_codex = __esm({
|
|
|
38576
38772
|
const telemetry = scanCodexTelemetry(dir, startedAtMs);
|
|
38577
38773
|
const model = telemetry.model ?? job.model ?? this.opts.model;
|
|
38578
38774
|
const runtimeSessionId = telemetry.sessionId ?? (job.resumeRuntimeSession ? job.runtimeSessionId : void 0);
|
|
38775
|
+
const isError = !killedByUs && typeof code === "number" && code !== 0;
|
|
38776
|
+
const errorMessage = isError ? [...stdoutErrorLines, ...stderrTail].join("\n").trim().slice(-4e3) || void 0 : void 0;
|
|
38579
38777
|
finish({
|
|
38580
38778
|
code: killedByUs ? null : code,
|
|
38581
38779
|
reason: killedByUs ? "timeout" : code === 0 ? "clean" : "error",
|
|
38582
38780
|
transcriptRef,
|
|
38583
38781
|
...telemetry.usage ? { usage: telemetry.usage } : {},
|
|
38584
38782
|
...model ? { model } : {},
|
|
38585
|
-
...runtimeSessionId ? { runtimeSessionId } : {}
|
|
38783
|
+
...runtimeSessionId ? { runtimeSessionId } : {},
|
|
38784
|
+
...errorMessage ? { errorMessage } : {}
|
|
38586
38785
|
});
|
|
38587
38786
|
});
|
|
38588
38787
|
return {
|
|
@@ -39096,6 +39295,13 @@ function parseArgsJSON(argsText) {
|
|
|
39096
39295
|
return { text: t };
|
|
39097
39296
|
}
|
|
39098
39297
|
}
|
|
39298
|
+
function composeAcpErrorMessage(rpcError, stderrTail) {
|
|
39299
|
+
const parts = [];
|
|
39300
|
+
if (rpcError && rpcError.trim()) parts.push(rpcError.trim());
|
|
39301
|
+
if (stderrTail.length) parts.push(stderrTail.join("\n").trim());
|
|
39302
|
+
const combined = parts.filter(Boolean).join("\n---\n").slice(-4e3).trim();
|
|
39303
|
+
return combined || void 0;
|
|
39304
|
+
}
|
|
39099
39305
|
function extractSessionID(result) {
|
|
39100
39306
|
return result?.sessionId ?? "";
|
|
39101
39307
|
}
|
|
@@ -39117,13 +39323,13 @@ function extractStopReason(result) {
|
|
|
39117
39323
|
}
|
|
39118
39324
|
async function runACPSession(job, cfg) {
|
|
39119
39325
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
39120
|
-
const binTag =
|
|
39121
|
-
const id = `${binTag}-${slug6}-${(0,
|
|
39122
|
-
const dir =
|
|
39326
|
+
const binTag = path10.basename(cfg.bin).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12) || "acp";
|
|
39327
|
+
const id = `${binTag}-${slug6}-${(0, import_node_crypto14.randomUUID)().slice(0, 8)}`;
|
|
39328
|
+
const dir = fs10.mkdtempSync(path10.join(cfg.workRoot ?? os6.tmpdir(), "oasis-session-"));
|
|
39123
39329
|
for (const [rel, content] of Object.entries(job.bundle.files)) {
|
|
39124
|
-
const file =
|
|
39125
|
-
|
|
39126
|
-
|
|
39330
|
+
const file = path10.join(dir, rel);
|
|
39331
|
+
fs10.mkdirSync(path10.dirname(file), { recursive: true });
|
|
39332
|
+
fs10.writeFileSync(file, content);
|
|
39127
39333
|
}
|
|
39128
39334
|
const task = job.bundle.files["TASK.md"];
|
|
39129
39335
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
@@ -39134,14 +39340,14 @@ async function runACPSession(job, cfg) {
|
|
|
39134
39340
|
...cfg.env,
|
|
39135
39341
|
...job.env,
|
|
39136
39342
|
...cfg.yoloEnv ?? {},
|
|
39137
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
39343
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path10.dirname(p2)).join(path10.delimiter)}${path10.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
39138
39344
|
OASIS_SERVER: job.server.url,
|
|
39139
39345
|
OASIS_TOKEN: job.actorToken
|
|
39140
39346
|
},
|
|
39141
39347
|
stdio: ["pipe", "pipe", "pipe"]
|
|
39142
39348
|
});
|
|
39143
|
-
let transcriptRef =
|
|
39144
|
-
const transcriptOut =
|
|
39349
|
+
let transcriptRef = path10.join(dir, "transcript.txt");
|
|
39350
|
+
const transcriptOut = fs10.createWriteStream(transcriptRef);
|
|
39145
39351
|
const outputCbs = [];
|
|
39146
39352
|
const telemetryCbs = [];
|
|
39147
39353
|
const exitCbs = [];
|
|
@@ -39158,14 +39364,14 @@ async function runACPSession(job, cfg) {
|
|
|
39158
39364
|
if (capturedSessionId && !info.runtimeSessionId) info = { ...info, runtimeSessionId: capturedSessionId };
|
|
39159
39365
|
if (cfg.cleanupWorkdir) {
|
|
39160
39366
|
try {
|
|
39161
|
-
const keepDir =
|
|
39162
|
-
|
|
39163
|
-
const kept =
|
|
39367
|
+
const keepDir = path10.join(cfg.workRoot ?? os6.tmpdir(), "oasis-transcripts");
|
|
39368
|
+
fs10.mkdirSync(keepDir, { recursive: true });
|
|
39369
|
+
const kept = path10.join(keepDir, `${id}.txt`);
|
|
39164
39370
|
const src = transcriptRef;
|
|
39165
39371
|
transcriptOut.end(() => {
|
|
39166
39372
|
try {
|
|
39167
|
-
|
|
39168
|
-
|
|
39373
|
+
fs10.renameSync(src, kept);
|
|
39374
|
+
fs10.rmSync(dir, { recursive: true, force: true });
|
|
39169
39375
|
} catch {
|
|
39170
39376
|
}
|
|
39171
39377
|
});
|
|
@@ -39181,7 +39387,23 @@ async function runACPSession(job, cfg) {
|
|
|
39181
39387
|
killedByUs = true;
|
|
39182
39388
|
child.kill("SIGKILL");
|
|
39183
39389
|
}, job.limits.wallClockMs);
|
|
39184
|
-
|
|
39390
|
+
const stderrTail = [];
|
|
39391
|
+
const STDERR_MAX_LINES = 40;
|
|
39392
|
+
const STDERR_MAX_BYTES = 4e3;
|
|
39393
|
+
const stderrRl = readline3.createInterface({ input: child.stderr });
|
|
39394
|
+
stderrRl.on("line", (line) => {
|
|
39395
|
+
try {
|
|
39396
|
+
transcriptOut.write(line + "\n");
|
|
39397
|
+
} catch {
|
|
39398
|
+
}
|
|
39399
|
+
stderrTail.push(line);
|
|
39400
|
+
while (stderrTail.length > STDERR_MAX_LINES) stderrTail.shift();
|
|
39401
|
+
let total = stderrTail.reduce((n, l) => n + l.length + 1, 0);
|
|
39402
|
+
while (total > STDERR_MAX_BYTES && stderrTail.length > 1) {
|
|
39403
|
+
total -= stderrTail.shift().length + 1;
|
|
39404
|
+
}
|
|
39405
|
+
});
|
|
39406
|
+
let lastRpcError;
|
|
39185
39407
|
let streamingCurrentTurn = false;
|
|
39186
39408
|
const client = new ACPClient(
|
|
39187
39409
|
(line) => {
|
|
@@ -39213,14 +39435,20 @@ async function runACPSession(job, cfg) {
|
|
|
39213
39435
|
resolve4();
|
|
39214
39436
|
});
|
|
39215
39437
|
});
|
|
39216
|
-
child.on("error", () => {
|
|
39438
|
+
child.on("error", (err) => {
|
|
39217
39439
|
clearTimeout(timer);
|
|
39218
|
-
finish({ code: null, reason: "error", transcriptRef });
|
|
39440
|
+
finish({ code: null, reason: "error", transcriptRef, errorMessage: composeAcpErrorMessage(err instanceof Error ? err.message : String(err), stderrTail) });
|
|
39219
39441
|
});
|
|
39220
39442
|
child.on("exit", (code) => {
|
|
39221
39443
|
clearTimeout(timer);
|
|
39222
39444
|
void readerDone.then(() => {
|
|
39223
|
-
|
|
39445
|
+
const isError = !killedByUs && typeof code === "number" && code !== 0;
|
|
39446
|
+
finish({
|
|
39447
|
+
code: killedByUs ? null : code,
|
|
39448
|
+
reason: killedByUs ? "timeout" : code === 0 ? "clean" : "error",
|
|
39449
|
+
transcriptRef,
|
|
39450
|
+
...isError ? { errorMessage: composeAcpErrorMessage(lastRpcError, stderrTail) } : {}
|
|
39451
|
+
});
|
|
39224
39452
|
});
|
|
39225
39453
|
});
|
|
39226
39454
|
void (async () => {
|
|
@@ -39311,10 +39539,11 @@ ${task}` : task;
|
|
|
39311
39539
|
if (!exited) finish({ code: 0, reason: "clean", transcriptRef, usage, model: actualModel });
|
|
39312
39540
|
child.kill("SIGTERM");
|
|
39313
39541
|
} catch (err) {
|
|
39542
|
+
lastRpcError = err instanceof Error ? err.message : String(err);
|
|
39314
39543
|
if (!exited) {
|
|
39315
39544
|
const reason = killedByUs ? "timeout" : "error";
|
|
39316
39545
|
const usage = buildUsage(client.usage, estimateCost(client.usage, actualModel));
|
|
39317
|
-
finish({ code: null, reason, transcriptRef, usage, model: actualModel });
|
|
39546
|
+
finish({ code: null, reason, transcriptRef, usage, model: actualModel, errorMessage: composeAcpErrorMessage(lastRpcError, stderrTail) });
|
|
39318
39547
|
}
|
|
39319
39548
|
} finally {
|
|
39320
39549
|
await readerDone;
|
|
@@ -39342,15 +39571,15 @@ ${task}` : task;
|
|
|
39342
39571
|
}
|
|
39343
39572
|
};
|
|
39344
39573
|
}
|
|
39345
|
-
var import_node_child_process6,
|
|
39574
|
+
var import_node_child_process6, import_node_crypto14, fs10, os6, path10, readline3, ACPClient;
|
|
39346
39575
|
var init_acp = __esm({
|
|
39347
39576
|
"../adapters/src/_core/acp.ts"() {
|
|
39348
39577
|
"use strict";
|
|
39349
39578
|
import_node_child_process6 = require("node:child_process");
|
|
39350
|
-
|
|
39351
|
-
|
|
39352
|
-
|
|
39353
|
-
|
|
39579
|
+
import_node_crypto14 = require("node:crypto");
|
|
39580
|
+
fs10 = __toESM(require("node:fs"), 1);
|
|
39581
|
+
os6 = __toESM(require("node:os"), 1);
|
|
39582
|
+
path10 = __toESM(require("node:path"), 1);
|
|
39354
39583
|
readline3 = __toESM(require("node:readline"), 1);
|
|
39355
39584
|
init_claude_code();
|
|
39356
39585
|
init_usage();
|
|
@@ -39668,12 +39897,12 @@ var init_kiro = __esm({
|
|
|
39668
39897
|
// ../adapters/src/_core/subprocess.ts
|
|
39669
39898
|
function materialize(job, workRoot) {
|
|
39670
39899
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
39671
|
-
const id = `${slug6}-${(0,
|
|
39672
|
-
const dir =
|
|
39900
|
+
const id = `${slug6}-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
|
|
39901
|
+
const dir = fs11.mkdtempSync(path11.join(workRoot ?? os7.tmpdir(), "oasis-session-"));
|
|
39673
39902
|
for (const [rel, content] of Object.entries(job.bundle.files)) {
|
|
39674
|
-
const file =
|
|
39675
|
-
|
|
39676
|
-
|
|
39903
|
+
const file = path11.join(dir, rel);
|
|
39904
|
+
fs11.mkdirSync(path11.dirname(file), { recursive: true });
|
|
39905
|
+
fs11.writeFileSync(file, content);
|
|
39677
39906
|
}
|
|
39678
39907
|
const task = job.bundle.files["TASK.md"];
|
|
39679
39908
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
@@ -39684,7 +39913,7 @@ function buildEnv(job, extra) {
|
|
|
39684
39913
|
...scrubLeakyEnv(process.env),
|
|
39685
39914
|
...extra,
|
|
39686
39915
|
...job.env,
|
|
39687
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
39916
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path11.dirname(p2)).join(path11.delimiter)}${path11.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
39688
39917
|
OASIS_SERVER: job.server.url,
|
|
39689
39918
|
OASIS_TOKEN: job.actorToken
|
|
39690
39919
|
};
|
|
@@ -39696,14 +39925,14 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, exitCbs) {
|
|
|
39696
39925
|
if (cfg.model && !info.model) info = { ...info, model: cfg.model };
|
|
39697
39926
|
if (cfg.cleanupWorkdir) {
|
|
39698
39927
|
try {
|
|
39699
|
-
const keepDir =
|
|
39700
|
-
|
|
39701
|
-
const kept =
|
|
39928
|
+
const keepDir = path11.join(cfg.workRoot ?? os7.tmpdir(), "oasis-transcripts");
|
|
39929
|
+
fs11.mkdirSync(keepDir, { recursive: true });
|
|
39930
|
+
const kept = path11.join(keepDir, `${id}.txt`);
|
|
39702
39931
|
const src = transcriptRefPtr.value;
|
|
39703
39932
|
transcriptOut.end(() => {
|
|
39704
39933
|
try {
|
|
39705
|
-
|
|
39706
|
-
|
|
39934
|
+
fs11.renameSync(src, kept);
|
|
39935
|
+
fs11.rmSync(dir, { recursive: true, force: true });
|
|
39707
39936
|
} catch {
|
|
39708
39937
|
}
|
|
39709
39938
|
});
|
|
@@ -39725,8 +39954,8 @@ function runStreamJson(job, cfg) {
|
|
|
39725
39954
|
env: buildEnv(job, cfg.env),
|
|
39726
39955
|
stdio: ["ignore", "pipe", "pipe"]
|
|
39727
39956
|
});
|
|
39728
|
-
const transcriptRefPtr = { value:
|
|
39729
|
-
const transcriptOut =
|
|
39957
|
+
const transcriptRefPtr = { value: path11.join(dir, "transcript.txt") };
|
|
39958
|
+
const transcriptOut = fs11.createWriteStream(transcriptRefPtr.value);
|
|
39730
39959
|
const outputCbs = [];
|
|
39731
39960
|
const telemetryCbs = [];
|
|
39732
39961
|
const exitCbs = [];
|
|
@@ -39783,8 +40012,8 @@ function runOneShotText(job, cfg) {
|
|
|
39783
40012
|
env: buildEnv(job, cfg.env),
|
|
39784
40013
|
stdio: ["ignore", "pipe", "pipe"]
|
|
39785
40014
|
});
|
|
39786
|
-
const transcriptRefPtr = { value:
|
|
39787
|
-
const transcriptOut =
|
|
40015
|
+
const transcriptRefPtr = { value: path11.join(dir, "transcript.txt") };
|
|
40016
|
+
const transcriptOut = fs11.createWriteStream(transcriptRefPtr.value);
|
|
39788
40017
|
const outputCbs = [];
|
|
39789
40018
|
const exitCbs = [];
|
|
39790
40019
|
const { finish, exited } = makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, exitCbs);
|
|
@@ -39823,15 +40052,15 @@ function runOneShotText(job, cfg) {
|
|
|
39823
40052
|
}
|
|
39824
40053
|
});
|
|
39825
40054
|
}
|
|
39826
|
-
var import_node_child_process7,
|
|
40055
|
+
var import_node_child_process7, import_node_crypto15, fs11, os7, path11, readline4;
|
|
39827
40056
|
var init_subprocess = __esm({
|
|
39828
40057
|
"../adapters/src/_core/subprocess.ts"() {
|
|
39829
40058
|
"use strict";
|
|
39830
40059
|
import_node_child_process7 = require("node:child_process");
|
|
39831
|
-
|
|
39832
|
-
|
|
39833
|
-
|
|
39834
|
-
|
|
40060
|
+
import_node_crypto15 = require("node:crypto");
|
|
40061
|
+
fs11 = __toESM(require("node:fs"), 1);
|
|
40062
|
+
os7 = __toESM(require("node:os"), 1);
|
|
40063
|
+
path11 = __toESM(require("node:path"), 1);
|
|
39835
40064
|
readline4 = __toESM(require("node:readline"), 1);
|
|
39836
40065
|
init_claude_code();
|
|
39837
40066
|
}
|
|
@@ -40235,11 +40464,11 @@ function normalizeOpenClaw(line) {
|
|
|
40235
40464
|
}
|
|
40236
40465
|
return [];
|
|
40237
40466
|
}
|
|
40238
|
-
var
|
|
40467
|
+
var import_node_crypto16, OpenClawAdapter;
|
|
40239
40468
|
var init_openclaw = __esm({
|
|
40240
40469
|
"../adapters/src/openclaw/index.ts"() {
|
|
40241
40470
|
"use strict";
|
|
40242
|
-
|
|
40471
|
+
import_node_crypto16 = require("node:crypto");
|
|
40243
40472
|
init_subprocess();
|
|
40244
40473
|
OpenClawAdapter = class {
|
|
40245
40474
|
constructor(opts = {}) {
|
|
@@ -40257,7 +40486,7 @@ var init_openclaw = __esm({
|
|
|
40257
40486
|
---
|
|
40258
40487
|
|
|
40259
40488
|
${task}` : task;
|
|
40260
|
-
const sessionId = job2.runtimeSessionId ?? `oasis-${(0,
|
|
40489
|
+
const sessionId = job2.runtimeSessionId ?? `oasis-${(0, import_node_crypto16.randomUUID)().slice(0, 8)}`;
|
|
40261
40490
|
return [
|
|
40262
40491
|
"agent",
|
|
40263
40492
|
...opts.mode !== "gateway" ? ["--local"] : [],
|
|
@@ -40561,7 +40790,7 @@ Write-Host " Remove : Unregister-ScheduledTask -TaskName 'OasisNode' -Confirm:$
|
|
|
40561
40790
|
}
|
|
40562
40791
|
function buildNpxCmd(p2) {
|
|
40563
40792
|
const namePart = p2.nodeName ? ` --name ${p2.nodeName}` : "";
|
|
40564
|
-
return `
|
|
40793
|
+
return `npm install -g --prefer-online --prefix ~/.oasis/npm-global oasis_test@latest && ~/.oasis/npm-global/bin/oasis start --server-ws ${p2.gatewayUrl}${namePart} --enroll-token ${p2.token}`;
|
|
40565
40794
|
}
|
|
40566
40795
|
var init_connect_script = __esm({
|
|
40567
40796
|
"../server/src/domains/nodes/connect-script.ts"() {
|
|
@@ -40728,7 +40957,7 @@ function nodesDomain(deps) {
|
|
|
40728
40957
|
nodeId = incomingNodeId;
|
|
40729
40958
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
40730
40959
|
} else {
|
|
40731
|
-
nodeId = `node-${(0,
|
|
40960
|
+
nodeId = `node-${(0, import_node_crypto17.randomUUID)().slice(0, 8)}`;
|
|
40732
40961
|
deps.enrollTokens.setIssuedNodeId(enrollToken, nodeId);
|
|
40733
40962
|
}
|
|
40734
40963
|
const existingNode = await deps.nodeStore.getNode(nodeId);
|
|
@@ -40768,6 +40997,23 @@ function nodesDomain(deps) {
|
|
|
40768
40997
|
await deps.nodeStore.deleteNode(nodeId);
|
|
40769
40998
|
return { status: 200, body: { ok: true } };
|
|
40770
40999
|
});
|
|
41000
|
+
router.get("/api/nodes/expected-daemon-version", async () => {
|
|
41001
|
+
const envVer = (process.env["OASIS_LATEST_NODE_DAEMON_VERSION"] ?? "").trim();
|
|
41002
|
+
if (envVer) return { status: 200, body: { version: envVer, source: "env" } };
|
|
41003
|
+
try {
|
|
41004
|
+
const here = (0, import_node_path2.dirname)((0, import_node_url.fileURLToPath)(__esm_import_meta_url));
|
|
41005
|
+
for (const rel of ["../../../../node-daemon/package.json", "../../../../../node-daemon/package.json"]) {
|
|
41006
|
+
try {
|
|
41007
|
+
const raw = (0, import_node_fs3.readFileSync)((0, import_node_path2.resolve)(here, rel), "utf8");
|
|
41008
|
+
const pkg = JSON.parse(raw);
|
|
41009
|
+
if (pkg.version) return { status: 200, body: { version: pkg.version, source: "monorepo" } };
|
|
41010
|
+
} catch {
|
|
41011
|
+
}
|
|
41012
|
+
}
|
|
41013
|
+
} catch {
|
|
41014
|
+
}
|
|
41015
|
+
return { status: 200, body: { version: null, source: null } };
|
|
41016
|
+
});
|
|
40771
41017
|
router.post("/api/nodes/:nodeId/update", async (req) => {
|
|
40772
41018
|
const nodeId = req.params["nodeId"];
|
|
40773
41019
|
if (!nodeId) return { status: 400, body: { error: "missing nodeId" } };
|
|
@@ -40851,11 +41097,14 @@ function nodesDomain(deps) {
|
|
|
40851
41097
|
});
|
|
40852
41098
|
};
|
|
40853
41099
|
}
|
|
40854
|
-
var
|
|
41100
|
+
var import_node_crypto17, import_node_fs3, import_node_url, import_node_path2;
|
|
40855
41101
|
var init_routes4 = __esm({
|
|
40856
41102
|
"../server/src/domains/nodes/routes.ts"() {
|
|
40857
41103
|
"use strict";
|
|
40858
|
-
|
|
41104
|
+
import_node_crypto17 = require("node:crypto");
|
|
41105
|
+
import_node_fs3 = require("node:fs");
|
|
41106
|
+
import_node_url = require("node:url");
|
|
41107
|
+
import_node_path2 = require("node:path");
|
|
40859
41108
|
init_src4();
|
|
40860
41109
|
init_connect_script();
|
|
40861
41110
|
}
|
|
@@ -40914,11 +41163,11 @@ var init_types3 = __esm({
|
|
|
40914
41163
|
});
|
|
40915
41164
|
|
|
40916
41165
|
// ../server/src/node-store.ts
|
|
40917
|
-
var
|
|
41166
|
+
var fs12, MemoryNodeStore, FileNodeStore;
|
|
40918
41167
|
var init_node_store = __esm({
|
|
40919
41168
|
"../server/src/node-store.ts"() {
|
|
40920
41169
|
"use strict";
|
|
40921
|
-
|
|
41170
|
+
fs12 = __toESM(require("node:fs"), 1);
|
|
40922
41171
|
MemoryNodeStore = class {
|
|
40923
41172
|
nodes = /* @__PURE__ */ new Map();
|
|
40924
41173
|
runtimes = /* @__PURE__ */ new Map();
|
|
@@ -41003,16 +41252,16 @@ var init_node_store = __esm({
|
|
|
41003
41252
|
static async open(file) {
|
|
41004
41253
|
const s2 = new _FileNodeStore(file);
|
|
41005
41254
|
try {
|
|
41006
|
-
const snap = JSON.parse(
|
|
41255
|
+
const snap = JSON.parse(fs12.readFileSync(file, "utf8"));
|
|
41007
41256
|
for (const n of snap.nodes ?? []) s2.nodes.set(n.id, n);
|
|
41008
41257
|
for (const r of snap.runtimes ?? []) s2.runtimes.set(r.id, r);
|
|
41009
41258
|
} catch {
|
|
41010
|
-
|
|
41259
|
+
fs12.writeFileSync(file, JSON.stringify({ nodes: [], runtimes: [] }, null, 2));
|
|
41011
41260
|
}
|
|
41012
41261
|
return s2;
|
|
41013
41262
|
}
|
|
41014
41263
|
flush() {
|
|
41015
|
-
|
|
41264
|
+
fs12.writeFileSync(this.file, JSON.stringify({
|
|
41016
41265
|
nodes: [...this.nodes.values()],
|
|
41017
41266
|
runtimes: [...this.runtimes.values()]
|
|
41018
41267
|
}, null, 2));
|
|
@@ -41556,7 +41805,7 @@ var init_collab = __esm({
|
|
|
41556
41805
|
|
|
41557
41806
|
// ../server/src/domains/collab/create-seeded-workorder.ts
|
|
41558
41807
|
function makeSeededWorkorderCreator(deps) {
|
|
41559
|
-
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0,
|
|
41808
|
+
const genWorkspace = deps.genWorkspace ?? (() => `ws:wo-${(0, import_node_crypto18.randomUUID)().slice(0, 8)}`);
|
|
41560
41809
|
return async (input) => {
|
|
41561
41810
|
const workspace = genWorkspace();
|
|
41562
41811
|
if (input.projectId && deps.artifactState) {
|
|
@@ -41593,11 +41842,11 @@ function makeSeededWorkorderCreator(deps) {
|
|
|
41593
41842
|
return { workspace, rootArtifactId: briefId, spawned: planned.spawned };
|
|
41594
41843
|
};
|
|
41595
41844
|
}
|
|
41596
|
-
var
|
|
41845
|
+
var import_node_crypto18, enc2;
|
|
41597
41846
|
var init_create_seeded_workorder = __esm({
|
|
41598
41847
|
"../server/src/domains/collab/create-seeded-workorder.ts"() {
|
|
41599
41848
|
"use strict";
|
|
41600
|
-
|
|
41849
|
+
import_node_crypto18 = require("node:crypto");
|
|
41601
41850
|
init_planner();
|
|
41602
41851
|
enc2 = (s2) => new TextEncoder().encode(s2);
|
|
41603
41852
|
}
|
|
@@ -42623,7 +42872,7 @@ function createChatSessionsDomain(opts) {
|
|
|
42623
42872
|
const runtimeId = await currentRuntimeId(body.aiActorId) ?? "unknown";
|
|
42624
42873
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
42625
42874
|
const session = {
|
|
42626
|
-
id: (0,
|
|
42875
|
+
id: (0, import_node_crypto19.randomUUID)(),
|
|
42627
42876
|
humanActorId: req.auth.actor,
|
|
42628
42877
|
aiActorId: body.aiActorId,
|
|
42629
42878
|
runtimeId,
|
|
@@ -42674,7 +42923,7 @@ function createChatSessionsDomain(opts) {
|
|
|
42674
42923
|
if (!body?.role || !body?.content) throw new ApiError(400, "BAD_REQUEST", "role and content required");
|
|
42675
42924
|
if (body.role !== "user" && body.role !== "assistant") throw new ApiError(400, "BAD_REQUEST", "role must be user or assistant");
|
|
42676
42925
|
const msg = await store.appendMessage({
|
|
42677
|
-
id: (0,
|
|
42926
|
+
id: (0, import_node_crypto19.randomUUID)(),
|
|
42678
42927
|
sessionId: req.params.id,
|
|
42679
42928
|
role: body.role,
|
|
42680
42929
|
content: body.content,
|
|
@@ -42711,11 +42960,11 @@ function createChatSessionsDomain(opts) {
|
|
|
42711
42960
|
});
|
|
42712
42961
|
};
|
|
42713
42962
|
}
|
|
42714
|
-
var
|
|
42963
|
+
var import_node_crypto19;
|
|
42715
42964
|
var init_chat_sessions = __esm({
|
|
42716
42965
|
"../server/src/domains/chat-sessions/index.ts"() {
|
|
42717
42966
|
"use strict";
|
|
42718
|
-
|
|
42967
|
+
import_node_crypto19 = require("node:crypto");
|
|
42719
42968
|
init_router();
|
|
42720
42969
|
init_workorders();
|
|
42721
42970
|
init_chat_parts();
|
|
@@ -44081,11 +44330,11 @@ function ackMsFromEnv(fallback) {
|
|
|
44081
44330
|
const n = Number(v2);
|
|
44082
44331
|
return Number.isFinite(n) && n >= 0 ? n : fallback;
|
|
44083
44332
|
}
|
|
44084
|
-
var
|
|
44333
|
+
var import_node_crypto20, DaemonHubAdapter, BindingRouterAdapter;
|
|
44085
44334
|
var init_daemon_adapter = __esm({
|
|
44086
44335
|
"../server/src/daemon-adapter.ts"() {
|
|
44087
44336
|
"use strict";
|
|
44088
|
-
|
|
44337
|
+
import_node_crypto20 = require("node:crypto");
|
|
44089
44338
|
DaemonHubAdapter = class {
|
|
44090
44339
|
constructor(hub, opts = {}) {
|
|
44091
44340
|
this.hub = hub;
|
|
@@ -44172,7 +44421,7 @@ var init_daemon_adapter = __esm({
|
|
|
44172
44421
|
async spawn(job) {
|
|
44173
44422
|
const nodeId = job.binding?.nodeId;
|
|
44174
44423
|
if (!nodeId) throw new Error("DaemonHubAdapter \u9700\u8981 job.binding.nodeId\uFF08\u8DEF\u7531\u9519\u8BEF\uFF09");
|
|
44175
|
-
const dispatchId = `dispatch:${(0,
|
|
44424
|
+
const dispatchId = `dispatch:${(0, import_node_crypto20.randomUUID)()}`;
|
|
44176
44425
|
const entry = {
|
|
44177
44426
|
nodeId,
|
|
44178
44427
|
exitCbs: [],
|
|
@@ -44270,17 +44519,17 @@ var init_daemon_adapter = __esm({
|
|
|
44270
44519
|
});
|
|
44271
44520
|
|
|
44272
44521
|
// ../server/src/side-map.ts
|
|
44273
|
-
var
|
|
44522
|
+
var import_node_fs4, import_node_path3, FileSideMap;
|
|
44274
44523
|
var init_side_map = __esm({
|
|
44275
44524
|
"../server/src/side-map.ts"() {
|
|
44276
44525
|
"use strict";
|
|
44277
|
-
|
|
44278
|
-
|
|
44526
|
+
import_node_fs4 = __toESM(require("node:fs"), 1);
|
|
44527
|
+
import_node_path3 = __toESM(require("node:path"), 1);
|
|
44279
44528
|
FileSideMap = class {
|
|
44280
44529
|
constructor(file) {
|
|
44281
44530
|
this.file = file;
|
|
44282
44531
|
try {
|
|
44283
|
-
const raw = JSON.parse(
|
|
44532
|
+
const raw = JSON.parse(import_node_fs4.default.readFileSync(file, "utf8"));
|
|
44284
44533
|
for (const [k2, v2] of Object.entries(raw)) if (typeof v2 === "string") this.map.set(k2, v2);
|
|
44285
44534
|
} catch {
|
|
44286
44535
|
}
|
|
@@ -44298,10 +44547,10 @@ var init_side_map = __esm({
|
|
|
44298
44547
|
}
|
|
44299
44548
|
persist() {
|
|
44300
44549
|
try {
|
|
44301
|
-
|
|
44550
|
+
import_node_fs4.default.mkdirSync(import_node_path3.default.dirname(this.file), { recursive: true });
|
|
44302
44551
|
const tmp = `${this.file}.tmp`;
|
|
44303
|
-
|
|
44304
|
-
|
|
44552
|
+
import_node_fs4.default.writeFileSync(tmp, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
44553
|
+
import_node_fs4.default.renameSync(tmp, this.file);
|
|
44305
44554
|
} catch {
|
|
44306
44555
|
}
|
|
44307
44556
|
}
|
|
@@ -44316,13 +44565,13 @@ function classifyPage(page, lastPushedHash, serviceAccount) {
|
|
|
44316
44565
|
if (sha(body) === lastPushedHash) return { kind: "echo" };
|
|
44317
44566
|
return { kind: "human-edit", content: body, updatedBy: page.updatedBy };
|
|
44318
44567
|
}
|
|
44319
|
-
var
|
|
44568
|
+
var import_node_crypto21, sha, enc3, dec, MirrorEngine, MapMirrorIdentities;
|
|
44320
44569
|
var init_engine = __esm({
|
|
44321
44570
|
"../server/src/mirror/engine.ts"() {
|
|
44322
44571
|
"use strict";
|
|
44323
|
-
|
|
44572
|
+
import_node_crypto21 = require("node:crypto");
|
|
44324
44573
|
init_src();
|
|
44325
|
-
sha = (s2) => (0,
|
|
44574
|
+
sha = (s2) => (0, import_node_crypto21.createHash)("sha256").update(s2, "utf8").digest("hex");
|
|
44326
44575
|
enc3 = (s2) => new TextEncoder().encode(s2);
|
|
44327
44576
|
dec = (b2) => new TextDecoder().decode(b2);
|
|
44328
44577
|
MirrorEngine = class {
|
|
@@ -44435,22 +44684,22 @@ var init_engine = __esm({
|
|
|
44435
44684
|
});
|
|
44436
44685
|
|
|
44437
44686
|
// ../server/src/mirror/fs-state.ts
|
|
44438
|
-
var
|
|
44687
|
+
var fs14, FsMirrorStateStore;
|
|
44439
44688
|
var init_fs_state = __esm({
|
|
44440
44689
|
"../server/src/mirror/fs-state.ts"() {
|
|
44441
44690
|
"use strict";
|
|
44442
|
-
|
|
44691
|
+
fs14 = __toESM(require("node:fs"), 1);
|
|
44443
44692
|
FsMirrorStateStore = class {
|
|
44444
44693
|
constructor(file) {
|
|
44445
44694
|
this.file = file;
|
|
44446
|
-
if (
|
|
44447
|
-
const obj = JSON.parse(
|
|
44695
|
+
if (fs14.existsSync(file)) {
|
|
44696
|
+
const obj = JSON.parse(fs14.readFileSync(file, "utf8"));
|
|
44448
44697
|
for (const [k2, v2] of Object.entries(obj)) this.map.set(k2, v2);
|
|
44449
44698
|
}
|
|
44450
44699
|
}
|
|
44451
44700
|
map = /* @__PURE__ */ new Map();
|
|
44452
44701
|
flush() {
|
|
44453
|
-
|
|
44702
|
+
fs14.writeFileSync(this.file, JSON.stringify(Object.fromEntries(this.map), null, 2));
|
|
44454
44703
|
}
|
|
44455
44704
|
async get(artifactId) {
|
|
44456
44705
|
return this.map.get(artifactId) ?? null;
|
|
@@ -44467,13 +44716,13 @@ var init_fs_state = __esm({
|
|
|
44467
44716
|
});
|
|
44468
44717
|
|
|
44469
44718
|
// ../server/src/git/integrate.ts
|
|
44470
|
-
var import_node_child_process8,
|
|
44719
|
+
var import_node_child_process8, fs15, path13, GitRemoteIntegrator;
|
|
44471
44720
|
var init_integrate = __esm({
|
|
44472
44721
|
"../server/src/git/integrate.ts"() {
|
|
44473
44722
|
"use strict";
|
|
44474
44723
|
import_node_child_process8 = require("node:child_process");
|
|
44475
|
-
|
|
44476
|
-
|
|
44724
|
+
fs15 = __toESM(require("node:fs"), 1);
|
|
44725
|
+
path13 = __toESM(require("node:path"), 1);
|
|
44477
44726
|
GitRemoteIntegrator = class {
|
|
44478
44727
|
constructor(remote, cloneDir, develop = "develop") {
|
|
44479
44728
|
this.remote = remote;
|
|
@@ -44490,8 +44739,8 @@ var init_integrate = __esm({
|
|
|
44490
44739
|
}
|
|
44491
44740
|
/** 确保本地工作克隆存在并拉到最新远程态。幂等。 */
|
|
44492
44741
|
sync() {
|
|
44493
|
-
if (!
|
|
44494
|
-
|
|
44742
|
+
if (!fs15.existsSync(path13.join(this.cloneDir, ".git"))) {
|
|
44743
|
+
fs15.mkdirSync(path13.dirname(this.cloneDir), { recursive: true });
|
|
44495
44744
|
(0, import_node_child_process8.execFileSync)("git", ["clone", "--quiet", this.remote, this.cloneDir], { env: this.env, maxBuffer: 256 * 1024 * 1024 });
|
|
44496
44745
|
this.git(["config", "user.email", "oasis@local"]);
|
|
44497
44746
|
this.git(["config", "user.name", "oasis"]);
|
|
@@ -44542,12 +44791,12 @@ var init_integrate = __esm({
|
|
|
44542
44791
|
});
|
|
44543
44792
|
|
|
44544
44793
|
// ../server/src/git/sync.ts
|
|
44545
|
-
var
|
|
44794
|
+
var os8, path14, slug3, GitSyncWorker;
|
|
44546
44795
|
var init_sync = __esm({
|
|
44547
44796
|
"../server/src/git/sync.ts"() {
|
|
44548
44797
|
"use strict";
|
|
44549
|
-
|
|
44550
|
-
|
|
44798
|
+
os8 = __toESM(require("node:os"), 1);
|
|
44799
|
+
path14 = __toESM(require("node:path"), 1);
|
|
44551
44800
|
init_src2();
|
|
44552
44801
|
init_integrate();
|
|
44553
44802
|
init_collect();
|
|
@@ -44563,8 +44812,8 @@ var init_sync = __esm({
|
|
|
44563
44812
|
const key = repo.remote;
|
|
44564
44813
|
let g2 = this.integrators.get(key);
|
|
44565
44814
|
if (!g2) {
|
|
44566
|
-
const root = this.deps.mirrorRoot ??
|
|
44567
|
-
const cloneDir = repo.repoDir ??
|
|
44815
|
+
const root = this.deps.mirrorRoot ?? path14.join(os8.tmpdir(), "oasis-git-mirrors");
|
|
44816
|
+
const cloneDir = repo.repoDir ?? path14.join(root, slug3(repo.id));
|
|
44568
44817
|
g2 = new GitRemoteIntegrator(repo.remote, cloneDir, repo.develop);
|
|
44569
44818
|
this.integrators.set(key, g2);
|
|
44570
44819
|
}
|
|
@@ -44605,13 +44854,13 @@ var init_sync = __esm({
|
|
|
44605
44854
|
});
|
|
44606
44855
|
|
|
44607
44856
|
// ../server/src/git/ci-provider.ts
|
|
44608
|
-
var import_node_child_process9,
|
|
44857
|
+
var import_node_child_process9, fs16, path15, import_node_util, execFile, slug4, GhCiProvider;
|
|
44609
44858
|
var init_ci_provider = __esm({
|
|
44610
44859
|
"../server/src/git/ci-provider.ts"() {
|
|
44611
44860
|
"use strict";
|
|
44612
44861
|
import_node_child_process9 = require("node:child_process");
|
|
44613
|
-
|
|
44614
|
-
|
|
44862
|
+
fs16 = __toESM(require("node:fs"), 1);
|
|
44863
|
+
path15 = __toESM(require("node:path"), 1);
|
|
44615
44864
|
import_node_util = require("node:util");
|
|
44616
44865
|
execFile = (0, import_node_util.promisify)(import_node_child_process9.execFile);
|
|
44617
44866
|
slug4 = (id) => id.replace(/[^a-zA-Z0-9_-]+/g, "_");
|
|
@@ -44625,9 +44874,9 @@ var init_ci_provider = __esm({
|
|
|
44625
44874
|
/** 缺则 clone(首次使用/进程重启后本地镜像不存在)——否则 git fetch 会"not a git repo"报错。同 GitRemoteIntegrator。 */
|
|
44626
44875
|
ensureClone(repo) {
|
|
44627
44876
|
const dir = this.repoDir(repo);
|
|
44628
|
-
if (
|
|
44877
|
+
if (fs16.existsSync(path15.join(dir, ".git"))) return;
|
|
44629
44878
|
if (!repo.remote) throw new Error(`repo ${repo.id} \u65E0 remote\uFF0C\u65E0\u6CD5 clone`);
|
|
44630
|
-
|
|
44879
|
+
fs16.mkdirSync(path15.dirname(dir), { recursive: true });
|
|
44631
44880
|
(0, import_node_child_process9.execFileSync)("git", ["clone", "--quiet", repo.remote, dir], { env: process.env });
|
|
44632
44881
|
this.opts.log?.(`[ci] cloned ${repo.id} \u2192 ${dir}`);
|
|
44633
44882
|
}
|
|
@@ -44890,11 +45139,11 @@ var init_resolve = __esm({
|
|
|
44890
45139
|
});
|
|
44891
45140
|
|
|
44892
45141
|
// ../server/src/coordinator/worker.ts
|
|
44893
|
-
var
|
|
45142
|
+
var import_node_crypto22, AUTONOMOUS_ETHOS, CONVERSATIONAL_ETHOS, SHARED_GRAPH_BODY, COORDINATOR_SYSTEM_PROMPT, CONVERSATIONAL_MANAGER_BODY, CoordinatorWorker;
|
|
44894
45143
|
var init_worker = __esm({
|
|
44895
45144
|
"../server/src/coordinator/worker.ts"() {
|
|
44896
45145
|
"use strict";
|
|
44897
|
-
|
|
45146
|
+
import_node_crypto22 = require("node:crypto");
|
|
44898
45147
|
init_src2();
|
|
44899
45148
|
init_identity();
|
|
44900
45149
|
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
|
|
@@ -45070,7 +45319,7 @@ ${SHARED_GRAPH_BODY}`;
|
|
|
45070
45319
|
return this.deps.kernel.model.lastSeq.get(artifactId) ?? 0;
|
|
45071
45320
|
}
|
|
45072
45321
|
evaluationKey(kind, artifactId, evidence) {
|
|
45073
|
-
const fingerprint = (0,
|
|
45322
|
+
const fingerprint = (0, import_node_crypto22.createHash)("sha256").update(JSON.stringify(evidence)).digest("hex");
|
|
45074
45323
|
return `${kind}:${artifactId}:${fingerprint}`;
|
|
45075
45324
|
}
|
|
45076
45325
|
artifactEvidence(id) {
|
|
@@ -45310,7 +45559,7 @@ ${SHARED_GRAPH_BODY}`;
|
|
|
45310
45559
|
const token = this.deps.tokenFor(actorId, ctx);
|
|
45311
45560
|
const serverUrl = this.deps.serverUrlFor ? await this.deps.serverUrlFor(ctx) : this.deps.serverUrl;
|
|
45312
45561
|
const workspace = this.deps.kernel.model.artifacts.get(artifactId)?.workspace;
|
|
45313
|
-
const runtimeSessionId = opts?.resumeSessionId ?? (0,
|
|
45562
|
+
const runtimeSessionId = opts?.resumeSessionId ?? (0, import_node_crypto22.randomUUID)();
|
|
45314
45563
|
const job = {
|
|
45315
45564
|
actor: actorId,
|
|
45316
45565
|
actorToken: token,
|
|
@@ -45382,7 +45631,7 @@ ${SHARED_GRAPH_BODY}`;
|
|
|
45382
45631
|
async function collectDir(root, dir, out) {
|
|
45383
45632
|
const entries = await (0, import_promises.readdir)(dir, { withFileTypes: true });
|
|
45384
45633
|
for (const e of entries) {
|
|
45385
|
-
const abs = (0,
|
|
45634
|
+
const abs = (0, import_node_path4.join)(dir, e.name);
|
|
45386
45635
|
if (e.isDirectory()) {
|
|
45387
45636
|
await collectDir(root, abs, out);
|
|
45388
45637
|
} else if (e.isFile()) {
|
|
@@ -45391,7 +45640,7 @@ async function collectDir(root, dir, out) {
|
|
|
45391
45640
|
console.warn(`[builtin-skills] skip oversized file (${info.size}B): ${abs}`);
|
|
45392
45641
|
continue;
|
|
45393
45642
|
}
|
|
45394
|
-
const rel = (0,
|
|
45643
|
+
const rel = (0, import_node_path4.relative)(root, abs).split(/[\\/]/).join("/");
|
|
45395
45644
|
out[rel] = await (0, import_promises.readFile)(abs, "utf8");
|
|
45396
45645
|
}
|
|
45397
45646
|
}
|
|
@@ -45407,7 +45656,7 @@ async function loadBuiltinSkills(skillsDir) {
|
|
|
45407
45656
|
for (const d of dirents) {
|
|
45408
45657
|
if (!d.isDirectory()) continue;
|
|
45409
45658
|
const slug6 = d.name;
|
|
45410
|
-
const skillDir = (0,
|
|
45659
|
+
const skillDir = (0, import_node_path4.join)(skillsDir, slug6);
|
|
45411
45660
|
const files = {};
|
|
45412
45661
|
try {
|
|
45413
45662
|
await collectDir(skillDir, skillDir, files);
|
|
@@ -45439,12 +45688,12 @@ function sanitize(name) {
|
|
|
45439
45688
|
const s2 = name.toLowerCase().trim().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
|
|
45440
45689
|
return s2 || "skill";
|
|
45441
45690
|
}
|
|
45442
|
-
var import_promises,
|
|
45691
|
+
var import_promises, import_node_path4, MAX_FILE_BYTES2;
|
|
45443
45692
|
var init_builtin_skills = __esm({
|
|
45444
45693
|
"../server/src/governance/builtin-skills.ts"() {
|
|
45445
45694
|
"use strict";
|
|
45446
45695
|
import_promises = require("node:fs/promises");
|
|
45447
|
-
|
|
45696
|
+
import_node_path4 = require("node:path");
|
|
45448
45697
|
init_skill_fetcher();
|
|
45449
45698
|
MAX_FILE_BYTES2 = 1 << 20;
|
|
45450
45699
|
}
|
|
@@ -47099,15 +47348,15 @@ var require_pg_connection_string = __commonJS({
|
|
|
47099
47348
|
if (config2.sslcert || config2.sslkey || config2.sslrootcert || config2.sslmode) {
|
|
47100
47349
|
config2.ssl = {};
|
|
47101
47350
|
}
|
|
47102
|
-
const
|
|
47351
|
+
const fs21 = config2.sslcert || config2.sslkey || config2.sslrootcert ? require("fs") : null;
|
|
47103
47352
|
if (config2.sslcert) {
|
|
47104
|
-
config2.ssl.cert =
|
|
47353
|
+
config2.ssl.cert = fs21.readFileSync(config2.sslcert).toString();
|
|
47105
47354
|
}
|
|
47106
47355
|
if (config2.sslkey) {
|
|
47107
|
-
config2.ssl.key =
|
|
47356
|
+
config2.ssl.key = fs21.readFileSync(config2.sslkey).toString();
|
|
47108
47357
|
}
|
|
47109
47358
|
if (config2.sslrootcert) {
|
|
47110
|
-
config2.ssl.ca =
|
|
47359
|
+
config2.ssl.ca = fs21.readFileSync(config2.sslrootcert).toString();
|
|
47111
47360
|
}
|
|
47112
47361
|
if (options.useLibpqCompat && config2.uselibpqcompat) {
|
|
47113
47362
|
throw new Error("Both useLibpqCompat and uselibpqcompat are set. Please use only one of them.");
|
|
@@ -48872,7 +49121,7 @@ var require_split2 = __commonJS({
|
|
|
48872
49121
|
var require_helper = __commonJS({
|
|
48873
49122
|
"../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/helper.js"(exports2, module2) {
|
|
48874
49123
|
"use strict";
|
|
48875
|
-
var
|
|
49124
|
+
var path20 = require("path");
|
|
48876
49125
|
var Stream = require("stream").Stream;
|
|
48877
49126
|
var split = require_split2();
|
|
48878
49127
|
var util2 = require("util");
|
|
@@ -48911,7 +49160,7 @@ var require_helper = __commonJS({
|
|
|
48911
49160
|
};
|
|
48912
49161
|
module2.exports.getFileName = function(rawEnv) {
|
|
48913
49162
|
var env = rawEnv || process.env;
|
|
48914
|
-
var file = env.PGPASSFILE || (isWin ?
|
|
49163
|
+
var file = env.PGPASSFILE || (isWin ? path20.join(env.APPDATA || "./", "postgresql", "pgpass.conf") : path20.join(env.HOME || "./", ".pgpass"));
|
|
48915
49164
|
return file;
|
|
48916
49165
|
};
|
|
48917
49166
|
module2.exports.usePgPass = function(stats, fname) {
|
|
@@ -49043,16 +49292,16 @@ var require_helper = __commonJS({
|
|
|
49043
49292
|
var require_lib = __commonJS({
|
|
49044
49293
|
"../../node_modules/.pnpm/pgpass@1.0.5/node_modules/pgpass/lib/index.js"(exports2, module2) {
|
|
49045
49294
|
"use strict";
|
|
49046
|
-
var
|
|
49047
|
-
var
|
|
49295
|
+
var path20 = require("path");
|
|
49296
|
+
var fs21 = require("fs");
|
|
49048
49297
|
var helper = require_helper();
|
|
49049
49298
|
module2.exports = function(connInfo, cb) {
|
|
49050
49299
|
var file = helper.getFileName();
|
|
49051
|
-
|
|
49300
|
+
fs21.stat(file, function(err, stat3) {
|
|
49052
49301
|
if (err || !helper.usePgPass(stat3, file)) {
|
|
49053
49302
|
return cb(void 0);
|
|
49054
49303
|
}
|
|
49055
|
-
var st =
|
|
49304
|
+
var st = fs21.createReadStream(file);
|
|
49056
49305
|
helper.getPassword(connInfo, st, cb);
|
|
49057
49306
|
});
|
|
49058
49307
|
};
|
|
@@ -50605,38 +50854,38 @@ __export(trajectory_exports, {
|
|
|
50605
50854
|
exportTrajectories: () => exportTrajectories
|
|
50606
50855
|
});
|
|
50607
50856
|
async function exportTrajectories(dataDir) {
|
|
50608
|
-
const root =
|
|
50609
|
-
if (!
|
|
50857
|
+
const root = path16.join(dataDir, "trajectories");
|
|
50858
|
+
if (!fs17.existsSync(root)) return [];
|
|
50610
50859
|
const model = emptyReadModel();
|
|
50611
|
-
const oplogFile =
|
|
50612
|
-
if (
|
|
50860
|
+
const oplogFile = path16.join(dataDir, "oplog.ndjson");
|
|
50861
|
+
if (fs17.existsSync(oplogFile)) {
|
|
50613
50862
|
const oplog = await NdjsonOplogStore.open(oplogFile);
|
|
50614
50863
|
for await (const entry of oplog.readAll()) fold(model, entry.op);
|
|
50615
50864
|
}
|
|
50616
50865
|
const samples = [];
|
|
50617
|
-
for (const sessionId of
|
|
50618
|
-
const dir =
|
|
50619
|
-
const sessionFile =
|
|
50620
|
-
if (!
|
|
50621
|
-
const session = JSON.parse(
|
|
50866
|
+
for (const sessionId of fs17.readdirSync(root).sort()) {
|
|
50867
|
+
const dir = path16.join(root, sessionId);
|
|
50868
|
+
const sessionFile = path16.join(dir, "session.json");
|
|
50869
|
+
if (!fs17.existsSync(sessionFile)) continue;
|
|
50870
|
+
const session = JSON.parse(fs17.readFileSync(sessionFile, "utf8"));
|
|
50622
50871
|
const events = [];
|
|
50623
|
-
const eventsFile =
|
|
50624
|
-
if (
|
|
50625
|
-
for (const line of
|
|
50872
|
+
const eventsFile = path16.join(dir, "events.ndjson");
|
|
50873
|
+
if (fs17.existsSync(eventsFile)) {
|
|
50874
|
+
for (const line of fs17.readFileSync(eventsFile, "utf8").split("\n")) {
|
|
50626
50875
|
if (line.trim()) events.push(JSON.parse(line));
|
|
50627
50876
|
}
|
|
50628
50877
|
}
|
|
50629
50878
|
const bundle = {};
|
|
50630
|
-
const bundleDir =
|
|
50879
|
+
const bundleDir = path16.join(dir, "bundle");
|
|
50631
50880
|
const walk = (sub) => {
|
|
50632
|
-
for (const name of
|
|
50881
|
+
for (const name of fs17.readdirSync(path16.join(bundleDir, sub))) {
|
|
50633
50882
|
const rel = sub ? `${sub}/${name}` : name;
|
|
50634
|
-
const full =
|
|
50635
|
-
if (
|
|
50636
|
-
else bundle[rel] =
|
|
50883
|
+
const full = path16.join(bundleDir, rel);
|
|
50884
|
+
if (fs17.statSync(full).isDirectory()) walk(rel);
|
|
50885
|
+
else bundle[rel] = fs17.readFileSync(full, "utf8");
|
|
50637
50886
|
}
|
|
50638
50887
|
};
|
|
50639
|
-
if (
|
|
50888
|
+
if (fs17.existsSync(bundleDir)) walk("");
|
|
50640
50889
|
const proposed = (session.opRefs ?? []).filter((r) => r.kind === "propose_revision").map((r) => r.target);
|
|
50641
50890
|
const verdicts = proposed.flatMap(
|
|
50642
50891
|
(rev) => (model.reviews.get(rev) ?? []).map((v2) => ({ author: v2.author, verdict: v2.verdict, ...v2.note !== void 0 ? { note: v2.note } : {} }))
|
|
@@ -50648,51 +50897,51 @@ async function exportTrajectories(dataDir) {
|
|
|
50648
50897
|
}
|
|
50649
50898
|
return samples;
|
|
50650
50899
|
}
|
|
50651
|
-
var
|
|
50900
|
+
var fs17, path16, FsTrajectorySink;
|
|
50652
50901
|
var init_trajectory = __esm({
|
|
50653
50902
|
"../cli/src/trajectory.ts"() {
|
|
50654
50903
|
"use strict";
|
|
50655
|
-
|
|
50656
|
-
|
|
50904
|
+
fs17 = __toESM(require("node:fs"), 1);
|
|
50905
|
+
path16 = __toESM(require("node:path"), 1);
|
|
50657
50906
|
init_src2();
|
|
50658
50907
|
init_src5();
|
|
50659
50908
|
FsTrajectorySink = class {
|
|
50660
50909
|
constructor(dataDir, broadcast) {
|
|
50661
50910
|
this.broadcast = broadcast;
|
|
50662
|
-
this.root =
|
|
50911
|
+
this.root = path16.join(dataDir, "trajectories");
|
|
50663
50912
|
}
|
|
50664
50913
|
root;
|
|
50665
50914
|
dir(sessionId) {
|
|
50666
|
-
return
|
|
50915
|
+
return path16.join(this.root, sessionId);
|
|
50667
50916
|
}
|
|
50668
50917
|
begin(session, bundleFiles) {
|
|
50669
50918
|
const dir = this.dir(session.sessionId);
|
|
50670
|
-
|
|
50671
|
-
|
|
50919
|
+
fs17.mkdirSync(path16.join(dir, "bundle"), { recursive: true });
|
|
50920
|
+
fs17.writeFileSync(path16.join(dir, "session.json"), JSON.stringify(session, null, 2));
|
|
50672
50921
|
for (const [rel, content] of Object.entries(bundleFiles)) {
|
|
50673
|
-
const file =
|
|
50674
|
-
|
|
50675
|
-
|
|
50922
|
+
const file = path16.join(dir, "bundle", rel);
|
|
50923
|
+
fs17.mkdirSync(path16.dirname(file), { recursive: true });
|
|
50924
|
+
fs17.writeFileSync(file, content);
|
|
50676
50925
|
}
|
|
50677
50926
|
this.broadcast?.({ type: "begin", sessionId: session.sessionId, data: session });
|
|
50678
50927
|
}
|
|
50679
50928
|
recover(session) {
|
|
50680
|
-
|
|
50681
|
-
const file =
|
|
50682
|
-
if (!
|
|
50929
|
+
fs17.mkdirSync(this.dir(session.sessionId), { recursive: true });
|
|
50930
|
+
const file = path16.join(this.dir(session.sessionId), "session.json");
|
|
50931
|
+
if (!fs17.existsSync(file)) fs17.writeFileSync(file, JSON.stringify(session, null, 2));
|
|
50683
50932
|
this.broadcast?.({ type: "begin", sessionId: session.sessionId, data: { ...session, recovered: true } });
|
|
50684
50933
|
}
|
|
50685
50934
|
event(sessionId, event) {
|
|
50686
|
-
|
|
50687
|
-
|
|
50935
|
+
fs17.mkdirSync(this.dir(sessionId), { recursive: true });
|
|
50936
|
+
fs17.appendFileSync(path16.join(this.dir(sessionId), "events.ndjson"), JSON.stringify(event) + "\n");
|
|
50688
50937
|
this.broadcast?.({ type: "event", sessionId, data: event });
|
|
50689
50938
|
}
|
|
50690
50939
|
end(sessionId, update) {
|
|
50691
|
-
const file =
|
|
50692
|
-
const session = JSON.parse(
|
|
50940
|
+
const file = path16.join(this.dir(sessionId), "session.json");
|
|
50941
|
+
const session = JSON.parse(fs17.readFileSync(file, "utf8"));
|
|
50693
50942
|
session.exit = update.exit;
|
|
50694
50943
|
session.opRefs = update.opRefs;
|
|
50695
|
-
|
|
50944
|
+
fs17.writeFileSync(file, JSON.stringify(session, null, 2));
|
|
50696
50945
|
this.broadcast?.({ type: "end", sessionId, data: session });
|
|
50697
50946
|
}
|
|
50698
50947
|
};
|
|
@@ -50700,30 +50949,30 @@ var init_trajectory = __esm({
|
|
|
50700
50949
|
});
|
|
50701
50950
|
|
|
50702
50951
|
// src/index.ts
|
|
50703
|
-
var
|
|
50704
|
-
var
|
|
50705
|
-
var
|
|
50952
|
+
var fs20 = __toESM(require("node:fs"));
|
|
50953
|
+
var os11 = __toESM(require("node:os"));
|
|
50954
|
+
var path19 = __toESM(require("node:path"));
|
|
50706
50955
|
var import_node_child_process15 = require("node:child_process");
|
|
50707
50956
|
|
|
50708
50957
|
// ../cli/src/cli.ts
|
|
50958
|
+
var fs19 = __toESM(require("node:fs"), 1);
|
|
50959
|
+
var os10 = __toESM(require("node:os"), 1);
|
|
50960
|
+
var path18 = __toESM(require("node:path"), 1);
|
|
50961
|
+
var import_node_crypto27 = require("node:crypto");
|
|
50962
|
+
|
|
50963
|
+
// ../cli/src/serve.ts
|
|
50709
50964
|
var fs18 = __toESM(require("node:fs"), 1);
|
|
50710
50965
|
var os9 = __toESM(require("node:os"), 1);
|
|
50711
50966
|
var path17 = __toESM(require("node:path"), 1);
|
|
50712
|
-
var
|
|
50713
|
-
|
|
50714
|
-
// ../cli/src/serve.ts
|
|
50715
|
-
var fs17 = __toESM(require("node:fs"), 1);
|
|
50716
|
-
var os8 = __toESM(require("node:os"), 1);
|
|
50717
|
-
var path16 = __toESM(require("node:path"), 1);
|
|
50718
|
-
var import_node_crypto24 = require("node:crypto");
|
|
50719
|
-
var import_node_url3 = require("node:url");
|
|
50967
|
+
var import_node_crypto25 = require("node:crypto");
|
|
50968
|
+
var import_node_url4 = require("node:url");
|
|
50720
50969
|
init_src2();
|
|
50721
50970
|
init_src5();
|
|
50722
50971
|
|
|
50723
50972
|
// ../connectors/src/_base/stage.ts
|
|
50724
|
-
var
|
|
50973
|
+
var import_node_fs5 = require("node:fs");
|
|
50725
50974
|
var import_node_os2 = require("node:os");
|
|
50726
|
-
var
|
|
50975
|
+
var import_node_path5 = require("node:path");
|
|
50727
50976
|
var stagedBinDirs = /* @__PURE__ */ new Map();
|
|
50728
50977
|
function stageConnectorWrapper(connector) {
|
|
50729
50978
|
const scriptPath = connector.wrapperScriptPath();
|
|
@@ -50734,10 +50983,10 @@ function stageConnectorWrapper(connector) {
|
|
|
50734
50983
|
}
|
|
50735
50984
|
const cacheKey = `${commandName}\0${scriptPath}`;
|
|
50736
50985
|
const cached2 = stagedBinDirs.get(cacheKey);
|
|
50737
|
-
if (cached2 && (0,
|
|
50738
|
-
const binDir = (0,
|
|
50739
|
-
const link = (0,
|
|
50740
|
-
(0,
|
|
50986
|
+
if (cached2 && (0, import_node_fs5.existsSync)((0, import_node_path5.join)(cached2, commandName))) return (0, import_node_path5.join)(cached2, commandName);
|
|
50987
|
+
const binDir = (0, import_node_fs5.mkdtempSync)((0, import_node_path5.join)((0, import_node_os2.tmpdir)(), `oasis-conn-${connector.config.slug}-`));
|
|
50988
|
+
const link = (0, import_node_path5.join)(binDir, commandName);
|
|
50989
|
+
(0, import_node_fs5.symlinkSync)(scriptPath, link);
|
|
50741
50990
|
stagedBinDirs.set(cacheKey, binDir);
|
|
50742
50991
|
return link;
|
|
50743
50992
|
}
|
|
@@ -50831,7 +51080,7 @@ async function ensureConnectorTools(tools, deps = {}) {
|
|
|
50831
51080
|
// ../connectors/src/_base/cli-connector.ts
|
|
50832
51081
|
var import_node_child_process11 = require("node:child_process");
|
|
50833
51082
|
var import_node_util3 = require("node:util");
|
|
50834
|
-
var
|
|
51083
|
+
var import_node_path6 = require("node:path");
|
|
50835
51084
|
var execFile3 = (0, import_node_util3.promisify)(import_node_child_process11.execFile);
|
|
50836
51085
|
var CliConnector = class {
|
|
50837
51086
|
constructor(wrapperDir) {
|
|
@@ -50843,7 +51092,7 @@ var CliConnector = class {
|
|
|
50843
51092
|
* The wrapper is a bash script that shadows the real CLI on PATH.
|
|
50844
51093
|
*/
|
|
50845
51094
|
wrapperScriptPath() {
|
|
50846
|
-
return (0,
|
|
51095
|
+
return (0, import_node_path6.join)(this.wrapperDir, "wrapper.sh");
|
|
50847
51096
|
}
|
|
50848
51097
|
/**
|
|
50849
51098
|
* Resolve the absolute path to a CLI binary using `which`.
|
|
@@ -50878,15 +51127,15 @@ var CliConnector = class {
|
|
|
50878
51127
|
// ../connectors/src/feishu/index.ts
|
|
50879
51128
|
var import_node_child_process12 = require("node:child_process");
|
|
50880
51129
|
var import_node_util4 = require("node:util");
|
|
50881
|
-
var
|
|
50882
|
-
var
|
|
51130
|
+
var import_node_path7 = require("node:path");
|
|
51131
|
+
var import_node_url2 = require("node:url");
|
|
50883
51132
|
var import_promises2 = require("node:fs/promises");
|
|
50884
51133
|
var import_node_os3 = require("node:os");
|
|
50885
51134
|
function shSingleQuote(v2) {
|
|
50886
51135
|
return `'${v2.replace(/'/g, `'\\''`)}'`;
|
|
50887
51136
|
}
|
|
50888
51137
|
var execFileAsync2 = (0, import_node_util4.promisify)(import_node_child_process12.execFile);
|
|
50889
|
-
var __dirname = (0,
|
|
51138
|
+
var __dirname = (0, import_node_path7.dirname)((0, import_node_url2.fileURLToPath)(__esm_import_meta_url));
|
|
50890
51139
|
var FeishuConnector = class extends CliConnector {
|
|
50891
51140
|
config = {
|
|
50892
51141
|
slug: "feishu",
|
|
@@ -50926,8 +51175,8 @@ var FeishuConnector = class extends CliConnector {
|
|
|
50926
51175
|
if (!appId) throw new Error("feishu inject: missing app_id");
|
|
50927
51176
|
if (!appSecret) throw new Error("feishu inject: missing app_secret");
|
|
50928
51177
|
const userAccessToken = credentials["user_access_token"] ?? credentials["FEISHU_USER_ACCESS_TOKEN"];
|
|
50929
|
-
const dir = await (0, import_promises2.mkdtemp)((0,
|
|
50930
|
-
const credsFile = (0,
|
|
51178
|
+
const dir = await (0, import_promises2.mkdtemp)((0, import_node_path7.join)((0, import_node_os3.tmpdir)(), "oasis-feishu-"));
|
|
51179
|
+
const credsFile = (0, import_node_path7.join)(dir, "creds.env");
|
|
50931
51180
|
const lines = [
|
|
50932
51181
|
`export LARKSUITE_CLI_APP_ID=${shSingleQuote(appId)}`,
|
|
50933
51182
|
`export LARKSUITE_CLI_APP_SECRET=${shSingleQuote(appSecret)}`
|
|
@@ -50982,11 +51231,11 @@ var FeishuConnector = class extends CliConnector {
|
|
|
50982
51231
|
};
|
|
50983
51232
|
|
|
50984
51233
|
// ../connectors/src/github/index.ts
|
|
50985
|
-
var
|
|
50986
|
-
var
|
|
51234
|
+
var import_node_path8 = require("node:path");
|
|
51235
|
+
var import_node_url3 = require("node:url");
|
|
50987
51236
|
var import_promises3 = require("node:fs/promises");
|
|
50988
51237
|
var import_node_os4 = require("node:os");
|
|
50989
|
-
var __dirname2 = (0,
|
|
51238
|
+
var __dirname2 = (0, import_node_path8.dirname)((0, import_node_url3.fileURLToPath)(__esm_import_meta_url));
|
|
50990
51239
|
function shSingleQuote2(v2) {
|
|
50991
51240
|
return `'${v2.replace(/'/g, `'\\''`)}'`;
|
|
50992
51241
|
}
|
|
@@ -51024,8 +51273,8 @@ var GithubConnector = class extends CliConnector {
|
|
|
51024
51273
|
const token = credentials["access_token"];
|
|
51025
51274
|
if (!token) throw new Error("github inject: missing access_token");
|
|
51026
51275
|
const name = credentials["actor_name"] ?? "oasis-agent";
|
|
51027
|
-
const dir = await (0, import_promises3.mkdtemp)((0,
|
|
51028
|
-
const credsFile = (0,
|
|
51276
|
+
const dir = await (0, import_promises3.mkdtemp)((0, import_node_path8.join)((0, import_node_os4.tmpdir)(), "oasis-github-"));
|
|
51277
|
+
const credsFile = (0, import_node_path8.join)(dir, "creds.env");
|
|
51029
51278
|
await (0, import_promises3.writeFile)(
|
|
51030
51279
|
credsFile,
|
|
51031
51280
|
`export GH_TOKEN=${shSingleQuote2(token)}
|
|
@@ -51065,7 +51314,7 @@ export GITHUB_TOKEN=${shSingleQuote2(token)}
|
|
|
51065
51314
|
// ../connectors/src/connector-adapter.ts
|
|
51066
51315
|
var import_promises4 = require("node:fs/promises");
|
|
51067
51316
|
var import_node_os5 = require("node:os");
|
|
51068
|
-
var
|
|
51317
|
+
var import_node_path9 = require("node:path");
|
|
51069
51318
|
init_src4();
|
|
51070
51319
|
|
|
51071
51320
|
// ../connectors/src/logger.ts
|
|
@@ -51095,11 +51344,11 @@ var ConnectorAwareAdapter = class {
|
|
|
51095
51344
|
);
|
|
51096
51345
|
let extraEnv = { ...strippedEnv };
|
|
51097
51346
|
if (wrapperPaths.length > 0) {
|
|
51098
|
-
const wrapperBinDir = await (0, import_promises4.mkdtemp)((0,
|
|
51347
|
+
const wrapperBinDir = await (0, import_promises4.mkdtemp)((0, import_node_path9.join)((0, import_node_os5.tmpdir)(), "oasis-wrappers-"));
|
|
51099
51348
|
await (0, import_promises4.mkdir)(wrapperBinDir, { recursive: true });
|
|
51100
51349
|
for (const wp of wrapperPaths) {
|
|
51101
|
-
const linkName = (0,
|
|
51102
|
-
await (0, import_promises4.symlink)(wp, (0,
|
|
51350
|
+
const linkName = (0, import_node_path9.basename)(wp).replace(/\.sh$/, "");
|
|
51351
|
+
await (0, import_promises4.symlink)(wp, (0, import_node_path9.join)(wrapperBinDir, linkName));
|
|
51103
51352
|
}
|
|
51104
51353
|
extraEnv = { ...extraEnv, PATH: `${wrapperBinDir}:${process.env["PATH"] ?? ""}` };
|
|
51105
51354
|
log("[adapter]", ` connectors injected +${Date.now() - t0}ms wrappers=${wrapperPaths.length} env_keys=${Object.keys(job.env ?? {}).join(",")}`);
|
|
@@ -51632,7 +51881,7 @@ function defaultDocumentPath2(input) {
|
|
|
51632
51881
|
init_src4();
|
|
51633
51882
|
|
|
51634
51883
|
// ../storage/src/postgres.ts
|
|
51635
|
-
var
|
|
51884
|
+
var import_node_crypto23 = require("node:crypto");
|
|
51636
51885
|
|
|
51637
51886
|
// ../../node_modules/.pnpm/pg@8.21.0/node_modules/pg/esm/index.mjs
|
|
51638
51887
|
var import_lib = __toESM(require_lib2(), 1);
|
|
@@ -51767,7 +52016,7 @@ var PostgresBlobStore = class _PostgresBlobStore {
|
|
|
51767
52016
|
return new _PostgresBlobStore(pool, schema);
|
|
51768
52017
|
}
|
|
51769
52018
|
async put(bytes) {
|
|
51770
|
-
const hash = (0,
|
|
52019
|
+
const hash = (0, import_node_crypto23.createHash)("sha256").update(bytes).digest("hex");
|
|
51771
52020
|
await this.pool.query(
|
|
51772
52021
|
`INSERT INTO ${this.t} (hash, bytes, size, content_type) VALUES ($1, $2, $3, $4) ON CONFLICT (hash) DO NOTHING`,
|
|
51773
52022
|
[hash, Buffer.from(bytes), bytes.byteLength, sniffContentType(bytes) ?? null]
|
|
@@ -54760,7 +55009,7 @@ var rowToMessage = (row) => ({
|
|
|
54760
55009
|
});
|
|
54761
55010
|
|
|
54762
55011
|
// ../storage/src/postgres-nodes.ts
|
|
54763
|
-
var
|
|
55012
|
+
var import_node_crypto24 = require("node:crypto");
|
|
54764
55013
|
var ident8 = (s2) => {
|
|
54765
55014
|
if (!/^[a-z_][a-z0-9_]*$/.test(s2)) throw new Error(`invalid schema name: ${s2}`);
|
|
54766
55015
|
return s2;
|
|
@@ -54898,7 +55147,7 @@ var PostgresNodeTokenStore = class _PostgresNodeTokenStore {
|
|
|
54898
55147
|
return store;
|
|
54899
55148
|
}
|
|
54900
55149
|
issue(nodeId) {
|
|
54901
|
-
const token = `ont_${(0,
|
|
55150
|
+
const token = `ont_${(0, import_node_crypto24.randomBytes)(24).toString("base64url")}`;
|
|
54902
55151
|
this.cache.set(token, nodeId);
|
|
54903
55152
|
void this.pool.query(`INSERT INTO ${this.s}.node_tokens (token,node_id) VALUES ($1,$2)`, [token, nodeId]);
|
|
54904
55153
|
return token;
|
|
@@ -54940,8 +55189,8 @@ init_trajectory();
|
|
|
54940
55189
|
function builtinSkillsDir() {
|
|
54941
55190
|
const override = process.env["OASIS_BUILTIN_SKILLS_DIR"]?.trim();
|
|
54942
55191
|
if (override) return override;
|
|
54943
|
-
const repoRoot = (0,
|
|
54944
|
-
return
|
|
55192
|
+
const repoRoot = (0, import_node_url4.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
55193
|
+
return path17.join(repoRoot, "skills");
|
|
54945
55194
|
}
|
|
54946
55195
|
function materializeBuiltins(builtins, runtimeKind) {
|
|
54947
55196
|
if (builtins.length === 0) return {};
|
|
@@ -54973,16 +55222,16 @@ function apiUrlFromGatewayUrl(raw) {
|
|
|
54973
55222
|
}
|
|
54974
55223
|
var oasisWrapperCache;
|
|
54975
55224
|
function oasisWrapperScript() {
|
|
54976
|
-
if (oasisWrapperCache &&
|
|
54977
|
-
const repoRoot = (0,
|
|
54978
|
-
const tsx =
|
|
54979
|
-
const main =
|
|
54980
|
-
const dir =
|
|
54981
|
-
const wrapper =
|
|
54982
|
-
|
|
55225
|
+
if (oasisWrapperCache && fs18.existsSync(oasisWrapperCache)) return oasisWrapperCache;
|
|
55226
|
+
const repoRoot = (0, import_node_url4.fileURLToPath)(new URL("../../../", __esm_import_meta_url));
|
|
55227
|
+
const tsx = path17.join(repoRoot, "node_modules/.bin/tsx");
|
|
55228
|
+
const main = path17.join(repoRoot, "packages/cli/src/main.ts");
|
|
55229
|
+
const dir = fs18.mkdtempSync(path17.join(os9.tmpdir(), "oasis-cli-"));
|
|
55230
|
+
const wrapper = path17.join(dir, "oasis");
|
|
55231
|
+
fs18.writeFileSync(wrapper, `#!/usr/bin/env bash
|
|
54983
55232
|
exec ${JSON.stringify(tsx)} ${JSON.stringify(main)} "$@"
|
|
54984
55233
|
`);
|
|
54985
|
-
|
|
55234
|
+
fs18.chmodSync(wrapper, 493);
|
|
54986
55235
|
oasisWrapperCache = wrapper;
|
|
54987
55236
|
return wrapper;
|
|
54988
55237
|
}
|
|
@@ -55069,26 +55318,26 @@ function traceRuntimeKind(runtimeKind) {
|
|
|
55069
55318
|
}
|
|
55070
55319
|
async function startServe(opts) {
|
|
55071
55320
|
const serverStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
55072
|
-
|
|
55073
|
-
const serverHeartbeatFile =
|
|
55321
|
+
fs18.mkdirSync(opts.dir, { recursive: true });
|
|
55322
|
+
const serverHeartbeatFile = path17.join(opts.dir, "serve-heartbeat.json");
|
|
55074
55323
|
let previousServerHeartbeatAt;
|
|
55075
|
-
if (
|
|
55324
|
+
if (fs18.existsSync(serverHeartbeatFile)) {
|
|
55076
55325
|
try {
|
|
55077
|
-
const raw = JSON.parse(
|
|
55326
|
+
const raw = JSON.parse(fs18.readFileSync(serverHeartbeatFile, "utf8"));
|
|
55078
55327
|
if (raw.at && Number.isFinite(Date.parse(raw.at))) previousServerHeartbeatAt = raw.at;
|
|
55079
55328
|
} catch {
|
|
55080
55329
|
}
|
|
55081
55330
|
}
|
|
55082
55331
|
const writeServerHeartbeat = () => {
|
|
55083
|
-
|
|
55332
|
+
fs18.writeFile(serverHeartbeatFile, JSON.stringify({ at: (/* @__PURE__ */ new Date()).toISOString(), pid: process.pid }) + "\n", () => {
|
|
55084
55333
|
});
|
|
55085
55334
|
};
|
|
55086
55335
|
writeServerHeartbeat();
|
|
55087
55336
|
const serverHeartbeatTimer = setInterval(writeServerHeartbeat, 5e3);
|
|
55088
55337
|
serverHeartbeatTimer.unref?.();
|
|
55089
|
-
const lock =
|
|
55090
|
-
if (
|
|
55091
|
-
const pid = Number(
|
|
55338
|
+
const lock = path17.join(opts.dir, "serve.lock");
|
|
55339
|
+
if (fs18.existsSync(lock)) {
|
|
55340
|
+
const pid = Number(fs18.readFileSync(lock, "utf8"));
|
|
55092
55341
|
let alive = false;
|
|
55093
55342
|
try {
|
|
55094
55343
|
process.kill(pid, 0);
|
|
@@ -55096,19 +55345,19 @@ async function startServe(opts) {
|
|
|
55096
55345
|
} catch {
|
|
55097
55346
|
}
|
|
55098
55347
|
if (alive) throw new Error(`\u8BE5\u6570\u636E\u76EE\u5F55\u5DF2\u6709 serve \u5728\u8DD1\uFF08pid=${pid}\uFF09\u2014\u2014\u5355\u5199\u8005\u8FDB\u7A0B\uFF0C\u4E0D\u80FD\u53CC\u5F00`);
|
|
55099
|
-
|
|
55348
|
+
fs18.unlinkSync(lock);
|
|
55100
55349
|
}
|
|
55101
|
-
|
|
55350
|
+
fs18.writeFileSync(lock, String(process.pid));
|
|
55102
55351
|
const loadJson = (name) => {
|
|
55103
|
-
const file =
|
|
55104
|
-
return
|
|
55352
|
+
const file = path17.join(opts.dir, name);
|
|
55353
|
+
return fs18.existsSync(file) ? JSON.parse(fs18.readFileSync(file, "utf8")) : void 0;
|
|
55105
55354
|
};
|
|
55106
55355
|
const pgDsn = process.env["OASIS_PG_DSN"] ?? process.env["DATABASE_URL"];
|
|
55107
55356
|
const pgSchema = process.env["OASIS_PG_SCHEMA"] ?? "public";
|
|
55108
55357
|
const pgPool = pgDsn ? createPgPool(pgDsn) : void 0;
|
|
55109
|
-
const oplog = pgDsn && pgPool ? await PostgresOplogStore.open(pgPool, pgSchema) : await NdjsonOplogStore.open(
|
|
55110
|
-
const blobs = pgDsn && pgPool ? await PostgresBlobStore.open(pgPool, pgSchema) : new DirBlobStore(
|
|
55111
|
-
const assets = new DirBlobStore(
|
|
55358
|
+
const oplog = pgDsn && pgPool ? await PostgresOplogStore.open(pgPool, pgSchema) : await NdjsonOplogStore.open(path17.join(opts.dir, "oplog.ndjson"));
|
|
55359
|
+
const blobs = pgDsn && pgPool ? await PostgresBlobStore.open(pgPool, pgSchema) : new DirBlobStore(path17.join(opts.dir, "blobs"));
|
|
55360
|
+
const assets = new DirBlobStore(path17.join(opts.dir, "assets"));
|
|
55112
55361
|
const defaultRootSchema = [
|
|
55113
55362
|
{ 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" },
|
|
55114
55363
|
{
|
|
@@ -55126,7 +55375,7 @@ async function startServe(opts) {
|
|
|
55126
55375
|
if (!schema.some((d) => d.name === "document")) {
|
|
55127
55376
|
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" });
|
|
55128
55377
|
}
|
|
55129
|
-
const typeStore = await FileTypeRegistryStore.open(
|
|
55378
|
+
const typeStore = await FileTypeRegistryStore.open(path17.join(opts.dir, "type-registry.json"));
|
|
55130
55379
|
if ((await typeStore.list()).length === 0) for (const d of schema) await typeStore.put(d);
|
|
55131
55380
|
{
|
|
55132
55381
|
const live = await typeStore.list();
|
|
@@ -55134,7 +55383,7 @@ async function startServe(opts) {
|
|
|
55134
55383
|
schema.length = 0;
|
|
55135
55384
|
schema.push(...live);
|
|
55136
55385
|
}
|
|
55137
|
-
const registryStore = pgDsn && pgPool ? await PostgresRegistryStore.open(pgPool, pgSchema) : await FileRegistryStore.open(
|
|
55386
|
+
const registryStore = pgDsn && pgPool ? await PostgresRegistryStore.open(pgPool, pgSchema) : await FileRegistryStore.open(path17.join(opts.dir, "registry-store.json"));
|
|
55138
55387
|
try {
|
|
55139
55388
|
await backfillSkillContentFromAssets(registryStore, assets);
|
|
55140
55389
|
} catch (err) {
|
|
@@ -55158,17 +55407,17 @@ async function startServe(opts) {
|
|
|
55158
55407
|
// per-contentType merge facet(§5.6):text=expensive→group-commit、code/structured=cheap→顺序 rebase
|
|
55159
55408
|
handlers: defaultHandlersByContentType()
|
|
55160
55409
|
});
|
|
55161
|
-
const issuer = createTokenIssuer({ secretFile:
|
|
55162
|
-
const operatorActor = `actor:human:${
|
|
55410
|
+
const issuer = createTokenIssuer({ secretFile: path17.join(opts.dir, "session-token-secret") });
|
|
55411
|
+
const operatorActor = `actor:human:${os9.userInfo().username}`;
|
|
55163
55412
|
const operatorToken = issuer.issue(operatorActor);
|
|
55164
|
-
|
|
55165
|
-
let nodeTokens = createNodeTokenStore(
|
|
55166
|
-
const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3,
|
|
55167
|
-
let nodeStore = await FileNodeStore.open(
|
|
55168
|
-
const registryAuditFile =
|
|
55413
|
+
fs18.writeFileSync(path17.join(opts.dir, "operator-token"), operatorToken, { mode: 384 });
|
|
55414
|
+
let nodeTokens = createNodeTokenStore(path17.join(opts.dir, "node-tokens.json"));
|
|
55415
|
+
const enrollTokens = createEnrollTokenStore(30 * 60 * 1e3, path17.join(opts.dir, "enroll-tokens.json"));
|
|
55416
|
+
let nodeStore = await FileNodeStore.open(path17.join(opts.dir, "nodes.json"));
|
|
55417
|
+
const registryAuditFile = path17.join(opts.dir, "registry-audit.ndjson");
|
|
55169
55418
|
const registryListeners = /* @__PURE__ */ new Set();
|
|
55170
55419
|
const registryAudit = (record5) => {
|
|
55171
|
-
|
|
55420
|
+
fs18.appendFile(registryAuditFile, JSON.stringify(record5) + "\n", () => {
|
|
55172
55421
|
});
|
|
55173
55422
|
for (const l of registryListeners) l({ kind: record5.kind, actor: record5.actor, target: record5.target, timestamp: record5.timestamp });
|
|
55174
55423
|
};
|
|
@@ -55205,9 +55454,9 @@ async function startServe(opts) {
|
|
|
55205
55454
|
nodeTokens = await PostgresNodeTokenStore.open(pgPool, pgSchema);
|
|
55206
55455
|
console.log(`[serve] \u4E8B\u5B9E/\u72B6\u6001\u4F53\u7CFB\uFF1APostgres schema=${pgSchema}\uFF08oplog / registry / blobs / artifacts / chat\uFF09`);
|
|
55207
55456
|
} else {
|
|
55208
|
-
projectStateStore = await FileProjectStateStore.open(
|
|
55209
|
-
artifactStateStore = await FileArtifactStateStore.open(
|
|
55210
|
-
chatSessionStore = await FileChatSessionStore.open(
|
|
55457
|
+
projectStateStore = await FileProjectStateStore.open(path17.join(opts.dir, "artifact-document-projects.json"));
|
|
55458
|
+
artifactStateStore = await FileArtifactStateStore.open(path17.join(opts.dir, "artifact-document-state.json"));
|
|
55459
|
+
chatSessionStore = await FileChatSessionStore.open(path17.join(opts.dir, "chat-sessions.json"));
|
|
55211
55460
|
console.log("[serve] \u4EA4\u4ED8\u7269\u72B6\u6001\u4F53\u7CFB\uFF1A\u672C\u5730 JSON dev store");
|
|
55212
55461
|
console.log("[serve] \u8282\u70B9/\u8FD0\u884C\u65F6\u4F53\u7CFB\uFF1A\u672C\u5730 JSON dev store");
|
|
55213
55462
|
}
|
|
@@ -55226,7 +55475,7 @@ async function startServe(opts) {
|
|
|
55226
55475
|
});
|
|
55227
55476
|
console.log(`[serve] \u9879\u76EE\u6587\u6863\u4F53\u7CFB\uFF1AOutline ${outlineUrl}\uFF08\u6302\u5728 Team Workspace\u300C\u9879\u76EE\u300D\u4E0B\uFF09`);
|
|
55228
55477
|
} else {
|
|
55229
|
-
projectDocumentStore = await FileProjectDocumentStore.open(
|
|
55478
|
+
projectDocumentStore = await FileProjectDocumentStore.open(path17.join(opts.dir, "project-document-spaces.json"));
|
|
55230
55479
|
console.log("[serve] \u9879\u76EE\u6587\u6863\u4F53\u7CFB\uFF1A\u672C\u5730\u5185\u5B58/\u6587\u4EF6 dev store");
|
|
55231
55480
|
}
|
|
55232
55481
|
const registryActorNames = /* @__PURE__ */ new Map();
|
|
@@ -55260,7 +55509,7 @@ async function startServe(opts) {
|
|
|
55260
55509
|
traceStore = await PostgresTraceStore.open(tracePool, pgSchema);
|
|
55261
55510
|
console.log(`[serve] \u8FD0\u884C\u8F68\u8FF9\u4F53\u7CFB\uFF1APostgres schema=${pgSchema}${traceDsn === pgDsn ? "" : "\uFF08\u72EC\u7ACB trace \u5E93\uFF09"}`);
|
|
55262
55511
|
} else {
|
|
55263
|
-
traceStore = await FileTraceStore.open(
|
|
55512
|
+
traceStore = await FileTraceStore.open(path17.join(opts.dir, "trace"));
|
|
55264
55513
|
console.log("[serve] \u8FD0\u884C\u8F68\u8FF9\u4F53\u7CFB\uFF1A\u672C\u5730 ndjson dev store");
|
|
55265
55514
|
}
|
|
55266
55515
|
traceStoreForActors = traceStore;
|
|
@@ -55280,7 +55529,7 @@ async function startServe(opts) {
|
|
|
55280
55529
|
create: createSeededWorkorder,
|
|
55281
55530
|
projectExists: async (id) => Boolean(await projectStateStore.getProject(id))
|
|
55282
55531
|
});
|
|
55283
|
-
const controlPlaneStore = pgDsn && pgPool ? await PostgresControlPlaneStore.open(pgPool, pgSchema) : await FileControlPlaneStore.open(
|
|
55532
|
+
const controlPlaneStore = pgDsn && pgPool ? await PostgresControlPlaneStore.open(pgPool, pgSchema) : await FileControlPlaneStore.open(path17.join(opts.dir, "control-plane.json"));
|
|
55284
55533
|
const resendKey = process.env["RESEND_API_KEY"];
|
|
55285
55534
|
const mailFrom = process.env["RESEND_FROM_EMAIL"] ?? process.env["OASIS_MAIL_FROM"] ?? "noreply@open-friday.com";
|
|
55286
55535
|
if (!resendKey) console.warn("[serve] RESEND_API_KEY \u672A\u8BBE\u2014\u2014\u9A8C\u8BC1\u7801/\u9080\u8BF7\u6253\u5370\u5230\u65E5\u5FD7\uFF08dev\uFF09\uFF1B\u751F\u4EA7\u8BF7\u914D RESEND_API_KEY + RESEND_FROM_EMAIL\uFF08Resend \u5DF2\u9A8C\u8BC1\u57DF\u540D\uFF09");
|
|
@@ -55350,12 +55599,12 @@ async function startServe(opts) {
|
|
|
55350
55599
|
}
|
|
55351
55600
|
return auth.sessionAccountId(headers);
|
|
55352
55601
|
};
|
|
55353
|
-
const workorderDrafts = new WorkorderDraftStore(
|
|
55354
|
-
const journalFile =
|
|
55602
|
+
const workorderDrafts = new WorkorderDraftStore(path17.join(opts.dir, "workorder-drafts.json"));
|
|
55603
|
+
const journalFile = path17.join(opts.dir, "dispatch-journal.ndjson");
|
|
55355
55604
|
const journalRing = [];
|
|
55356
|
-
if (
|
|
55605
|
+
if (fs18.existsSync(journalFile)) {
|
|
55357
55606
|
try {
|
|
55358
|
-
const lines =
|
|
55607
|
+
const lines = fs18.readFileSync(journalFile, "utf8").split(/\r?\n/).filter(Boolean);
|
|
55359
55608
|
for (const line of lines.slice(-500)) {
|
|
55360
55609
|
try {
|
|
55361
55610
|
journalRing.push(JSON.parse(line));
|
|
@@ -55368,7 +55617,7 @@ async function startServe(opts) {
|
|
|
55368
55617
|
const journal = (entry) => {
|
|
55369
55618
|
journalRing.push(entry);
|
|
55370
55619
|
if (journalRing.length > 500) journalRing.shift();
|
|
55371
|
-
|
|
55620
|
+
fs18.appendFile(journalFile, JSON.stringify(entry) + "\n", () => {
|
|
55372
55621
|
});
|
|
55373
55622
|
};
|
|
55374
55623
|
const closeOrphanedDispatches = () => {
|
|
@@ -55395,7 +55644,7 @@ async function startServe(opts) {
|
|
|
55395
55644
|
defaultEngine: { kernel, oplog, blobs, registry: registryStore, assets },
|
|
55396
55645
|
defaultCompanyId,
|
|
55397
55646
|
buildEngine: async (companyId) => {
|
|
55398
|
-
const engine2 = await openFileEngine(
|
|
55647
|
+
const engine2 = await openFileEngine(path17.join(opts.dir, "companies", companyEngineDirName(companyId)), { schema });
|
|
55399
55648
|
await ensureCompanyActors(controlPlaneStore, companyId, engine2.registry);
|
|
55400
55649
|
await syncRegistryRolesToKernel(engine2.registry, engine2.kernel);
|
|
55401
55650
|
return engine2;
|
|
@@ -55512,7 +55761,7 @@ async function startServe(opts) {
|
|
|
55512
55761
|
return {};
|
|
55513
55762
|
}));
|
|
55514
55763
|
const limits = { wallClockMs: SESSION_WALL_CLOCK_MS.planner };
|
|
55515
|
-
const artifactId = `artifact:planner:${(0,
|
|
55764
|
+
const artifactId = `artifact:planner:${(0, import_node_crypto25.randomUUID)()}`;
|
|
55516
55765
|
const handle = await chatRemoteAdapter.spawn({
|
|
55517
55766
|
actor: planner.id,
|
|
55518
55767
|
actorToken: issueSessionToken(planner.id, { artifactId, action: "plan-workorder", limits, binding }),
|
|
@@ -55620,7 +55869,7 @@ async function startServe(opts) {
|
|
|
55620
55869
|
},
|
|
55621
55870
|
retainedSession: (key) => key.annotationId && key.artifactId ? allDispatchers().map((d) => d.retainedProduceSessionFor(key.artifactId)).find(Boolean) : coordinatorRef?.retainedSessionFor(key),
|
|
55622
55871
|
// 0030 D3/D7 落盘:discuss 按项表写文件,serve 重启后同一卡点续同一段、不再新开。
|
|
55623
|
-
discussSessions: new FileSideMap(
|
|
55872
|
+
discussSessions: new FileSideMap(path17.join(opts.dir, "discuss-sessions.json")),
|
|
55624
55873
|
dispatchChat: async ({ actorId, message, sessionId, chatSessionId, attachments, workspace, companyId }) => {
|
|
55625
55874
|
const runCompanyId = companyId ?? defaultCompanyId;
|
|
55626
55875
|
const actorCtxForCompany = await actors.resolveCtx(runCompanyId);
|
|
@@ -55642,10 +55891,10 @@ async function startServe(opts) {
|
|
|
55642
55891
|
if (!localUrl) {
|
|
55643
55892
|
throw new ApiError(503, "SERVER_URL_NOT_READY", "server URL \u5C1A\u672A\u5C31\u7EEA");
|
|
55644
55893
|
}
|
|
55645
|
-
const runtimeSessionId = sessionId ?? (0,
|
|
55894
|
+
const runtimeSessionId = sessionId ?? (0, import_node_crypto25.randomUUID)();
|
|
55646
55895
|
const resumeRuntimeSession = Boolean(sessionId);
|
|
55647
|
-
const traceRunId = `chat-run:${(0,
|
|
55648
|
-
const artifactId = `artifact:chat:${(0,
|
|
55896
|
+
const traceRunId = `chat-run:${(0, import_node_crypto25.randomUUID)()}`;
|
|
55897
|
+
const artifactId = `artifact:chat:${(0, import_node_crypto25.randomUUID)()}`;
|
|
55649
55898
|
const traceStartedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
55650
55899
|
let traceSeq = 0;
|
|
55651
55900
|
let traceEnabled = true;
|
|
@@ -55846,7 +56095,13 @@ async function startServe(opts) {
|
|
|
55846
56095
|
}
|
|
55847
56096
|
});
|
|
55848
56097
|
if (info.code === 0) resolve4();
|
|
55849
|
-
else
|
|
56098
|
+
else {
|
|
56099
|
+
const detail = info.errorMessage?.trim();
|
|
56100
|
+
const generic = `runtime exited with code ${info.code ?? "null"}${info.reason ? ` (${info.reason})` : ""}`;
|
|
56101
|
+
reject(new Error(detail ? `${generic}
|
|
56102
|
+
|
|
56103
|
+
${detail}` : generic));
|
|
56104
|
+
}
|
|
55850
56105
|
});
|
|
55851
56106
|
});
|
|
55852
56107
|
return {
|
|
@@ -55890,7 +56145,7 @@ async function startServe(opts) {
|
|
|
55890
56145
|
console.log(`[serve] \u8FDC\u7A0B agent API URL\uFF1A${remoteApiUrl ?? "\u672A\u914D\u7F6E\uFF08\u4EC5\u652F\u6301\u672C\u673A runtime\uFF09"}`);
|
|
55891
56146
|
const projectsCfg = loadJson("projects.json");
|
|
55892
56147
|
const seedProjects = (projectsCfg?.projects ?? []).map(
|
|
55893
|
-
(p2) => p2.repos?.length ? { ...p2, repos: p2.repos.map((r) => r.repoDir ? { ...r, repoDir:
|
|
56148
|
+
(p2) => p2.repos?.length ? { ...p2, repos: p2.repos.map((r) => r.repoDir ? { ...r, repoDir: path17.resolve(opts.dir, r.repoDir) } : r) } : p2
|
|
55894
56149
|
);
|
|
55895
56150
|
for (const sp of seedProjects) {
|
|
55896
56151
|
const existing = await projectStateStore.getProject(sp.id);
|
|
@@ -56021,8 +56276,8 @@ async function startServe(opts) {
|
|
|
56021
56276
|
// 每 agent 并发产出上限默认 5(工单数 / 全局总量默认不限);--max-produce-per-agent N 覆盖。
|
|
56022
56277
|
maxConcurrentProducePerActor: opts.maxConcurrentProducePerActor ?? 5,
|
|
56023
56278
|
// 提案 uniform-annotation-resolve ③/④ 落盘:容错计数 + produce 会话号(重启不丢;丢了也只是降级/多容错一轮)
|
|
56024
|
-
annotationRescue: new FileSideMap(
|
|
56025
|
-
produceSessions: new FileSideMap(
|
|
56279
|
+
annotationRescue: new FileSideMap(path17.join(opts.dir, `annotation-rescue.${companyId}.json`)),
|
|
56280
|
+
produceSessions: new FileSideMap(path17.join(opts.dir, `produce-sessions.${companyId}.json`))
|
|
56026
56281
|
});
|
|
56027
56282
|
const slot = { dispatcher: d, logged: 0, ticking: false };
|
|
56028
56283
|
dispatchers.set(companyId, slot);
|
|
@@ -56208,7 +56463,7 @@ async function startServe(opts) {
|
|
|
56208
56463
|
schema: schemaMap,
|
|
56209
56464
|
mirrors: new Map(opts.mirror.connectors.map((c) => [c.platform, c])),
|
|
56210
56465
|
identities: opts.mirror.identities ?? new MapMirrorIdentities(),
|
|
56211
|
-
state: new FsMirrorStateStore(
|
|
56466
|
+
state: new FsMirrorStateStore(path17.join(opts.dir, "mirror-state.json")),
|
|
56212
56467
|
...opts.mirror.debounceMs !== void 0 ? { debounceMs: opts.mirror.debounceMs } : {},
|
|
56213
56468
|
log: (m2) => console.log(m2)
|
|
56214
56469
|
});
|
|
@@ -56220,7 +56475,7 @@ async function startServe(opts) {
|
|
|
56220
56475
|
if (opts.dispatch) {
|
|
56221
56476
|
if (ciGateEnabled) {
|
|
56222
56477
|
const ci = new GhCiProvider({
|
|
56223
|
-
mirrorRoot:
|
|
56478
|
+
mirrorRoot: path17.join(opts.dir, "git-mirrors"),
|
|
56224
56479
|
failClosedWhenNoChecks: process.env["OASIS_CI_FAIL_CLOSED"] === "1",
|
|
56225
56480
|
log: (m2) => console.log(m2)
|
|
56226
56481
|
});
|
|
@@ -56232,7 +56487,7 @@ async function startServe(opts) {
|
|
|
56232
56487
|
const gitSync = new GitSyncWorker({
|
|
56233
56488
|
kernel,
|
|
56234
56489
|
resolveProject,
|
|
56235
|
-
mirrorRoot:
|
|
56490
|
+
mirrorRoot: path17.join(opts.dir, "git-mirrors"),
|
|
56236
56491
|
log: (m2) => console.log(m2)
|
|
56237
56492
|
});
|
|
56238
56493
|
gitTimer = setInterval(() => {
|
|
@@ -56295,7 +56550,7 @@ async function startServe(opts) {
|
|
|
56295
56550
|
// 病历里展示节点的"在跑会话情况"(runId + 跑了多久):从派发器在途会话按 artifactId 过滤。
|
|
56296
56551
|
sessionsOf: (id) => allDispatchers().flatMap((d) => d.inFlightSessions()).filter((s2) => s2.artifactId === id).map((s2) => ({ runId: s2.sessionId, action: s2.action, startedAt: s2.startedAt })),
|
|
56297
56552
|
log: (m2) => console.log(m2),
|
|
56298
|
-
retention: new FileSideMap(
|
|
56553
|
+
retention: new FileSideMap(path17.join(opts.dir, "retained-sessions.json"))
|
|
56299
56554
|
// 0030 D7 落盘
|
|
56300
56555
|
});
|
|
56301
56556
|
coordinatorRef = coordinator;
|
|
@@ -56406,7 +56661,7 @@ async function startServe(opts) {
|
|
|
56406
56661
|
await server.close();
|
|
56407
56662
|
if (pgPool) await pgPool.end().catch(() => {
|
|
56408
56663
|
});
|
|
56409
|
-
|
|
56664
|
+
fs18.rmSync(lock, { force: true });
|
|
56410
56665
|
}
|
|
56411
56666
|
};
|
|
56412
56667
|
}
|
|
@@ -56842,13 +57097,13 @@ async function startNode(opts) {
|
|
|
56842
57097
|
|
|
56843
57098
|
// ../cli/src/daemon/machine-id.ts
|
|
56844
57099
|
var import_node_child_process14 = require("node:child_process");
|
|
56845
|
-
var
|
|
56846
|
-
var
|
|
57100
|
+
var import_node_fs6 = require("node:fs");
|
|
57101
|
+
var import_node_crypto26 = require("node:crypto");
|
|
56847
57102
|
var import_node_os7 = require("node:os");
|
|
56848
57103
|
function linuxMachineId() {
|
|
56849
57104
|
for (const p2 of ["/etc/machine-id", "/var/lib/dbus/machine-id"]) {
|
|
56850
57105
|
try {
|
|
56851
|
-
const v2 = (0,
|
|
57106
|
+
const v2 = (0, import_node_fs6.readFileSync)(p2, "utf8").trim();
|
|
56852
57107
|
if (v2) return v2;
|
|
56853
57108
|
} catch {
|
|
56854
57109
|
}
|
|
@@ -56909,13 +57164,14 @@ var defaultSources = {
|
|
|
56909
57164
|
function resolveNodeId(sources = {}) {
|
|
56910
57165
|
const s2 = { ...defaultSources, ...sources };
|
|
56911
57166
|
const material = `${s2.machineFingerprint()}:${s2.osUser()}`;
|
|
56912
|
-
const digest = (0,
|
|
57167
|
+
const digest = (0, import_node_crypto26.createHash)("sha256").update(material).digest("hex").slice(0, 12);
|
|
56913
57168
|
return `node-${digest}`;
|
|
56914
57169
|
}
|
|
56915
57170
|
|
|
56916
57171
|
// ../cli/src/cli.ts
|
|
56917
57172
|
init_src5();
|
|
56918
57173
|
init_src();
|
|
57174
|
+
init_src4();
|
|
56919
57175
|
var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uFF08\u670D\u52A1\u7AEF\u7626\u5BA2\u6237\u7AEF\uFF09
|
|
56920
57176
|
|
|
56921
57177
|
oasis serve [--dir .oasis] [--port 7320] [--dispatch true [--model haiku] [--max-produce-per-agent 5] [--max-concurrent-produce N]] [--allow-simple-tokens true] [--public-url https://host/oasis-api] [--gateway-url wss://host/oasis-api/node-gateway]
|
|
@@ -56952,6 +57208,9 @@ var USAGE = `oasis \u2014\u2014 artifact-centric \u534F\u4F5C\u5185\u6838 CLI\uF
|
|
|
56952
57208
|
reject <artifactId> <revisionId> --reason <text>
|
|
56953
57209
|
conclude <artifactId> [--note <text>] # \u673A\u68B0 grounding \u786C\u62E6\uFF1B\u6709 gate \u5219\u8FDB\u5165\u5F85\u5BA1
|
|
56954
57210
|
review <artifactId> --verdict approve|request_changes [--note <t>]
|
|
57211
|
+
design run <artifactId> [--brief <t>] [--reason <t>] [--od-url <url>] [--title <t>] [--agent <id>]
|
|
57212
|
+
# design \u4EA7\u7269\uFF1A\u5728\u901A\u7528 runtime \u4E0A\u9A71\u52A8 open-design \u753B\u677F\u5F15\u64CE\u4EA7\u754C\u9762\u7A3F\u5E76\u4EA4\u7A3F\uFF08\u63D0\u6848 design-node-runtime-to-cli-tool\uFF09\u3002
|
|
57213
|
+
# --brief \u7F3A\u7701\u8BFB\u5F53\u524D\u76EE\u5F55 TASK.md\uFF1B\u4E0A\u4E0B\u6587\u53D6\u5F53\u524D\u76EE\u5F55 inputs/\uFF1Bod \u5730\u5740\u7F3A\u7701 $OASIS_OPEN_DESIGN_URL \u6216\u672C\u673A 7457\u3002
|
|
56955
57214
|
|
|
56956
57215
|
\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09
|
|
56957
57216
|
annotate <artifactId> --body <text> [--from <\u4E0B\u6E38> --blocks true]
|
|
@@ -57075,8 +57334,8 @@ function makeClient(base, token) {
|
|
|
57075
57334
|
if (!res.ok) await fail(res);
|
|
57076
57335
|
return (await res.json()).data;
|
|
57077
57336
|
},
|
|
57078
|
-
async request(method,
|
|
57079
|
-
const res = await fetch(`${base}${
|
|
57337
|
+
async request(method, path20, body) {
|
|
57338
|
+
const res = await fetch(`${base}${path20}`, {
|
|
57080
57339
|
method,
|
|
57081
57340
|
headers,
|
|
57082
57341
|
...body !== void 0 ? { body: JSON.stringify(body) } : {}
|
|
@@ -57084,8 +57343,8 @@ function makeClient(base, token) {
|
|
|
57084
57343
|
if (!res.ok) await fail(res);
|
|
57085
57344
|
return await res.json();
|
|
57086
57345
|
},
|
|
57087
|
-
async post(
|
|
57088
|
-
const res = await fetch(`${base}${
|
|
57346
|
+
async post(path20, body) {
|
|
57347
|
+
const res = await fetch(`${base}${path20}`, { method: "POST", headers, body: JSON.stringify(body) });
|
|
57089
57348
|
if (!res.ok) await fail(res);
|
|
57090
57349
|
return await res.json();
|
|
57091
57350
|
}
|
|
@@ -57098,62 +57357,62 @@ async function runCli(argv, println = console.log) {
|
|
|
57098
57357
|
return;
|
|
57099
57358
|
}
|
|
57100
57359
|
const { positional, flags } = parseArgs(rest);
|
|
57101
|
-
const dir = flags.get("dir") ?? process.env["OASIS_DIR"] ??
|
|
57360
|
+
const dir = flags.get("dir") ?? process.env["OASIS_DIR"] ?? path18.resolve(".oasis");
|
|
57102
57361
|
if (command === "node" && positional[0] !== "output") {
|
|
57103
57362
|
const serverUrl = flags.get("server-ws") ?? process.env["OASIS_SERVER_WS"] ?? "ws://127.0.0.1:7320/node-gateway";
|
|
57104
57363
|
const nodeName = flags.get("name") ?? process.env["OASIS_NODE_NAME"];
|
|
57105
|
-
const nodeIdFile =
|
|
57106
|
-
const nodeTokenFile =
|
|
57107
|
-
const enrollTokenFile =
|
|
57108
|
-
const reportMarkerFile =
|
|
57109
|
-
const persistedNodeId =
|
|
57364
|
+
const nodeIdFile = path18.join(dir, "node-id");
|
|
57365
|
+
const nodeTokenFile = path18.join(dir, "node-token");
|
|
57366
|
+
const enrollTokenFile = path18.join(dir, "enroll-token");
|
|
57367
|
+
const reportMarkerFile = path18.join(dir, "report-runtimes");
|
|
57368
|
+
const persistedNodeId = fs19.existsSync(nodeIdFile) ? fs19.readFileSync(nodeIdFile, "utf8").trim() : null;
|
|
57110
57369
|
let nodeId = persistedNodeId || resolveNodeId();
|
|
57111
|
-
let token2 = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? (
|
|
57112
|
-
const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (
|
|
57370
|
+
let token2 = flags.get("token") ?? process.env["OASIS_NODE_TOKEN"] ?? (fs19.existsSync(nodeTokenFile) ? fs19.readFileSync(nodeTokenFile, "utf8").trim() : void 0);
|
|
57371
|
+
const enrollToken = flags.get("enroll-token") ?? process.env["OASIS_ENROLL_TOKEN"] ?? (fs19.existsSync(enrollTokenFile) ? fs19.readFileSync(enrollTokenFile, "utf8").trim() : void 0);
|
|
57113
57372
|
let freshEnrollment = false;
|
|
57114
57373
|
if (!token2 && enrollToken) {
|
|
57115
57374
|
const httpBase2 = serverUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
|
|
57116
57375
|
const res = await fetch(`${httpBase2}/api/nodes/exchange`, {
|
|
57117
57376
|
method: "POST",
|
|
57118
57377
|
headers: { "content-type": "application/json" },
|
|
57119
|
-
body: JSON.stringify({ enrollToken, nodeId, hostname:
|
|
57378
|
+
body: JSON.stringify({ enrollToken, nodeId, hostname: os10.hostname() })
|
|
57120
57379
|
});
|
|
57121
57380
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
57122
57381
|
const body = await res.json();
|
|
57123
57382
|
nodeId = body.nodeId;
|
|
57124
57383
|
token2 = body.token;
|
|
57125
|
-
|
|
57126
|
-
|
|
57127
|
-
|
|
57384
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
57385
|
+
fs19.writeFileSync(nodeIdFile, nodeId);
|
|
57386
|
+
fs19.writeFileSync(nodeTokenFile, token2, { mode: 384 });
|
|
57128
57387
|
try {
|
|
57129
|
-
|
|
57388
|
+
fs19.unlinkSync(enrollTokenFile);
|
|
57130
57389
|
} catch {
|
|
57131
57390
|
}
|
|
57132
57391
|
freshEnrollment = true;
|
|
57133
57392
|
}
|
|
57134
57393
|
if (!nodeId) throw new Error("no nodeId \u2014 provide --enroll-token <ent_...> on first run");
|
|
57135
|
-
const scriptRun = freshEnrollment ||
|
|
57394
|
+
const scriptRun = freshEnrollment || fs19.existsSync(reportMarkerFile);
|
|
57136
57395
|
if (flags.has("service")) {
|
|
57137
57396
|
const { spawnSync, execSync: execSync2 } = await import("node:child_process");
|
|
57138
57397
|
if (token2) {
|
|
57139
|
-
|
|
57140
|
-
|
|
57398
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
57399
|
+
fs19.writeFileSync(nodeTokenFile, token2, { mode: 384 });
|
|
57141
57400
|
}
|
|
57142
57401
|
if (scriptRun) {
|
|
57143
|
-
|
|
57144
|
-
|
|
57402
|
+
fs19.mkdirSync(dir, { recursive: true });
|
|
57403
|
+
fs19.writeFileSync(reportMarkerFile, "");
|
|
57145
57404
|
}
|
|
57146
57405
|
println("\u2192 Installing oasis_test globally...");
|
|
57147
57406
|
spawnSync("npm", ["install", "-g", "oasis_test@latest"], { stdio: "inherit" });
|
|
57148
57407
|
const prefix = execSync2("npm prefix -g").toString().trim();
|
|
57149
|
-
const binPath =
|
|
57408
|
+
const binPath = path18.join(prefix, "bin", "oasis_test");
|
|
57150
57409
|
const svcArgs = `node --server-ws ${serverUrl} --dir ${dir}${nodeName ? ` --name ${nodeName}` : ""}`;
|
|
57151
57410
|
if (process.platform === "linux") {
|
|
57152
|
-
const svcFile =
|
|
57153
|
-
|
|
57411
|
+
const svcFile = path18.join(os10.homedir(), ".config/systemd/user/oasis-node.service");
|
|
57412
|
+
fs19.mkdirSync(path18.dirname(svcFile), { recursive: true });
|
|
57154
57413
|
if (spawnSync("systemctl", ["--user", "is-active", "--quiet", "oasis-node"], {}).status === 0)
|
|
57155
57414
|
spawnSync("systemctl", ["--user", "stop", "oasis-node"], { stdio: "inherit" });
|
|
57156
|
-
|
|
57415
|
+
fs19.writeFileSync(svcFile, [
|
|
57157
57416
|
"[Unit]",
|
|
57158
57417
|
"Description=Oasis Node Daemon",
|
|
57159
57418
|
"After=network.target",
|
|
@@ -57162,7 +57421,7 @@ async function runCli(argv, println = console.log) {
|
|
|
57162
57421
|
`ExecStart=${binPath} ${svcArgs}`,
|
|
57163
57422
|
// Carry the install-time PATH so the detached daemon detects CLIs in user dirs
|
|
57164
57423
|
// (~/.npm-global/bin, ~/.local/bin) — systemd --user otherwise gives a minimal PATH.
|
|
57165
|
-
`Environment=PATH=${process.env["PATH"] ?? ""}:${
|
|
57424
|
+
`Environment=PATH=${process.env["PATH"] ?? ""}:${path18.join(os10.homedir(), ".npm-global/bin")}:${path18.join(os10.homedir(), ".local/bin")}:/usr/local/bin`,
|
|
57166
57425
|
"Restart=on-failure",
|
|
57167
57426
|
"RestartSec=5",
|
|
57168
57427
|
"StandardOutput=journal",
|
|
@@ -57174,31 +57433,31 @@ async function runCli(argv, println = console.log) {
|
|
|
57174
57433
|
].join("\n"));
|
|
57175
57434
|
spawnSync("systemctl", ["--user", "daemon-reload"], { stdio: "inherit" });
|
|
57176
57435
|
spawnSync("systemctl", ["--user", "enable", "--now", "oasis-node"], { stdio: "inherit" });
|
|
57177
|
-
spawnSync("loginctl", ["enable-linger",
|
|
57436
|
+
spawnSync("loginctl", ["enable-linger", os10.userInfo().username], { stdio: "ignore" });
|
|
57178
57437
|
println("\u2713 Oasis node service started (systemd --user oasis-node)");
|
|
57179
57438
|
println(" Status : systemctl --user status oasis-node");
|
|
57180
57439
|
println(" Logs : journalctl --user -u oasis-node -f");
|
|
57181
57440
|
println(" Stop : systemctl --user stop oasis-node");
|
|
57182
57441
|
} else if (process.platform === "darwin") {
|
|
57183
|
-
const plist =
|
|
57184
|
-
|
|
57442
|
+
const plist = path18.join(os10.homedir(), "Library/LaunchAgents/com.oasis.node.plist");
|
|
57443
|
+
fs19.mkdirSync(path18.dirname(plist), { recursive: true });
|
|
57185
57444
|
spawnSync("launchctl", ["unload", plist], { stdio: "ignore" });
|
|
57186
57445
|
const argXml = [binPath, "node", "--server-ws", serverUrl, "--dir", dir, ...nodeName ? ["--name", nodeName] : []].map((a) => `<string>${a}</string>`).join("");
|
|
57187
|
-
|
|
57446
|
+
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>${os10.homedir()}/.oasis-node.log</string><key>StandardErrorPath</key><string>${os10.homedir()}/.oasis-node.err</string></dict></plist>`);
|
|
57188
57447
|
spawnSync("launchctl", ["load", plist], { stdio: "inherit" });
|
|
57189
57448
|
println("\u2713 Oasis node service started (macOS LaunchAgent com.oasis.node)");
|
|
57190
|
-
println(` Logs : tail -f ${
|
|
57449
|
+
println(` Logs : tail -f ${os10.homedir()}/.oasis-node.log`);
|
|
57191
57450
|
println(` Stop : launchctl unload ${plist}`);
|
|
57192
57451
|
} else {
|
|
57193
|
-
spawnSync("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${
|
|
57452
|
+
spawnSync("sh", ["-c", `nohup ${binPath} ${svcArgs} > ${path18.join(os10.homedir(), ".oasis-node.log")} 2>&1 &`], { stdio: "inherit" });
|
|
57194
57453
|
println(`\u2713 Oasis node started in background (nohup). Logs: ~/.oasis-node.log`);
|
|
57195
57454
|
println(" Note: no automatic restart on reboot in this environment.");
|
|
57196
57455
|
}
|
|
57197
57456
|
return;
|
|
57198
57457
|
}
|
|
57199
|
-
if (
|
|
57458
|
+
if (fs19.existsSync(reportMarkerFile)) {
|
|
57200
57459
|
try {
|
|
57201
|
-
|
|
57460
|
+
fs19.unlinkSync(reportMarkerFile);
|
|
57202
57461
|
} catch {
|
|
57203
57462
|
}
|
|
57204
57463
|
}
|
|
@@ -57206,14 +57465,14 @@ async function runCli(argv, println = console.log) {
|
|
|
57206
57465
|
return;
|
|
57207
57466
|
}
|
|
57208
57467
|
if (command === "node-token") {
|
|
57209
|
-
const store = createNodeTokenStore(
|
|
57468
|
+
const store = createNodeTokenStore(path18.join(dir, "node-tokens.json"));
|
|
57210
57469
|
const sub = positional[0];
|
|
57211
57470
|
if (sub === "issue") {
|
|
57212
|
-
const id = flags.get("id") ?? `node-${(0,
|
|
57471
|
+
const id = flags.get("id") ?? `node-${(0, import_node_crypto27.randomUUID)()}`;
|
|
57213
57472
|
const token2 = store.issue(id);
|
|
57214
57473
|
println(token2);
|
|
57215
57474
|
process.stderr.write(
|
|
57216
|
-
`\u5DF2\u4E3A ${id} \u7B7E\u53D1 node-token\uFF08\u5199\u5165 ${
|
|
57475
|
+
`\u5DF2\u4E3A ${id} \u7B7E\u53D1 node-token\uFF08\u5199\u5165 ${path18.join(dir, "node-tokens.json")}\uFF09\u3002
|
|
57217
57476
|
\u628A\u4E0A\u9762\u8FD9\u4E32\u653E\u5230\u8282\u70B9\u673A\uFF1A--token <t> / $OASIS_NODE_TOKEN / <\u8282\u70B9dir>/node-token
|
|
57218
57477
|
`
|
|
57219
57478
|
);
|
|
@@ -57234,7 +57493,7 @@ async function runCli(argv, println = console.log) {
|
|
|
57234
57493
|
}
|
|
57235
57494
|
if (command === "admin" && positional[0] === "grant-owner") {
|
|
57236
57495
|
const email2 = need(flags, "email");
|
|
57237
|
-
const store = await FileControlPlaneStore.open(
|
|
57496
|
+
const store = await FileControlPlaneStore.open(path18.join(dir, "control-plane.json"));
|
|
57238
57497
|
const activeCompanies = (await store.listCompanies()).filter((c) => c.status === "active");
|
|
57239
57498
|
const companyId = flags.get("company") ?? activeCompanies[0]?.id ?? resolveDefaultCompanyConfig().id;
|
|
57240
57499
|
const name = flags.get("name");
|
|
@@ -57247,11 +57506,11 @@ async function runCli(argv, println = console.log) {
|
|
|
57247
57506
|
}
|
|
57248
57507
|
if (command === "export-trajectories") {
|
|
57249
57508
|
const { exportTrajectories: exportTrajectories2 } = await Promise.resolve().then(() => (init_trajectory(), trajectory_exports));
|
|
57250
|
-
const samples = await exportTrajectories2(
|
|
57509
|
+
const samples = await exportTrajectories2(path18.resolve(dir));
|
|
57251
57510
|
const outFile = flags.get("out");
|
|
57252
57511
|
const lines = samples.map((sample) => JSON.stringify(sample)).join("\n");
|
|
57253
57512
|
if (outFile !== void 0) {
|
|
57254
|
-
|
|
57513
|
+
fs19.writeFileSync(outFile, lines + (lines ? "\n" : ""));
|
|
57255
57514
|
println(`\u5DF2\u5BFC\u51FA ${samples.length} \u6761\u8F68\u8FF9\u6837\u672C \u2192 ${outFile}\uFF08approved/rejected \u6210\u5BF9\u5373\u504F\u597D\u5BF9\uFF09`);
|
|
57256
57515
|
} else {
|
|
57257
57516
|
println(lines);
|
|
@@ -57259,10 +57518,10 @@ async function runCli(argv, println = console.log) {
|
|
|
57259
57518
|
return;
|
|
57260
57519
|
}
|
|
57261
57520
|
if (command === "serve" && positional[0] === "install") {
|
|
57262
|
-
const absDir =
|
|
57263
|
-
const name = `oasis-serve-${
|
|
57264
|
-
const unitDir = flags.get("unit-dir") ??
|
|
57265
|
-
const bin = flags.get("bin") ??
|
|
57521
|
+
const absDir = path18.resolve(dir);
|
|
57522
|
+
const name = `oasis-serve-${path18.basename(absDir)}`;
|
|
57523
|
+
const unitDir = flags.get("unit-dir") ?? path18.join(os10.homedir(), ".config", "systemd", "user");
|
|
57524
|
+
const bin = flags.get("bin") ?? path18.join(os10.homedir(), ".local", "bin", "oasis");
|
|
57266
57525
|
const port = flags.get("port") ?? "7320";
|
|
57267
57526
|
const extra = (flags.get("dispatch") === "true" ? ` --dispatch true` : "") + (flags.has("model") ? ` --model ${flags.get("model")}` : "");
|
|
57268
57527
|
const unit = [
|
|
@@ -57279,9 +57538,9 @@ async function runCli(argv, println = console.log) {
|
|
|
57279
57538
|
`WantedBy=default.target`,
|
|
57280
57539
|
``
|
|
57281
57540
|
].join("\n");
|
|
57282
|
-
|
|
57283
|
-
const unitPath =
|
|
57284
|
-
|
|
57541
|
+
fs19.mkdirSync(unitDir, { recursive: true });
|
|
57542
|
+
const unitPath = path18.join(unitDir, `${name}.service`);
|
|
57543
|
+
fs19.writeFileSync(unitPath, unit);
|
|
57285
57544
|
println(`\u5DF2\u5199\u5165 ${unitPath}`);
|
|
57286
57545
|
println(`\u542F\u7528\uFF1Asystemctl --user daemon-reload && systemctl --user enable --now ${name}`);
|
|
57287
57546
|
println(`\u5F00\u673A\u81EA\u542F\uFF08\u542B\u672A\u767B\u5F55\uFF09\uFF1Aloginctl enable-linger $USER`);
|
|
@@ -57303,20 +57562,20 @@ async function runCli(argv, println = console.log) {
|
|
|
57303
57562
|
});
|
|
57304
57563
|
const port2 = new URL(handle.baseUrl).port;
|
|
57305
57564
|
println(`oasis serve \u5C31\u7EEA\uFF1Ahttp://0.0.0.0:${port2}\uFF08\u672C\u673A\u8BBF\u95EE\u7528 http://127.0.0.1:${port2}\uFF09`);
|
|
57306
|
-
println(`operator token \u5DF2\u5199\u5165 ${
|
|
57565
|
+
println(`operator token \u5DF2\u5199\u5165 ${path18.join(dir, "operator-token")}\uFF08\u672C\u673A CLI \u81EA\u52A8\u8BFB\u53D6\uFF09`);
|
|
57307
57566
|
if (flags.get("dispatch") === "true") println(`\u8C03\u5EA6\u5FAA\u73AF\u5DF2\u542F\u52A8\uFF08claude-code adapter\uFF09`);
|
|
57308
57567
|
await new Promise(() => {
|
|
57309
57568
|
});
|
|
57310
57569
|
return;
|
|
57311
57570
|
}
|
|
57312
57571
|
const base = flags.get("server") ?? process.env["OASIS_SERVER"] ?? "http://127.0.0.1:7320";
|
|
57313
|
-
const tokenFile =
|
|
57314
|
-
const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (
|
|
57572
|
+
const tokenFile = path18.join(dir, "operator-token");
|
|
57573
|
+
const token = flags.get("token") ?? process.env["OASIS_TOKEN"] ?? (fs19.existsSync(tokenFile) ? fs19.readFileSync(tokenFile, "utf8").trim() : void 0);
|
|
57315
57574
|
if (!token) {
|
|
57316
57575
|
throw new Error(`\u65E0 token\uFF1A\u5148 oasis serve\uFF08\u4F1A\u751F\u6210 ${tokenFile}\uFF09\uFF0C\u6216\u663E\u5F0F --token / $OASIS_TOKEN`);
|
|
57317
57576
|
}
|
|
57318
57577
|
const api = makeClient(base, token);
|
|
57319
|
-
const readFileArg = (file) =>
|
|
57578
|
+
const readFileArg = (file) => fs19.readFileSync(file, "utf8");
|
|
57320
57579
|
const parseJsonFlag = (value, name) => {
|
|
57321
57580
|
const parsed = JSON.parse(value);
|
|
57322
57581
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
@@ -57334,11 +57593,11 @@ async function runCli(argv, println = console.log) {
|
|
|
57334
57593
|
const readDirFiles = (root) => {
|
|
57335
57594
|
const out = [];
|
|
57336
57595
|
const walk = (abs, rel) => {
|
|
57337
|
-
for (const name of
|
|
57338
|
-
const childAbs =
|
|
57596
|
+
for (const name of fs19.readdirSync(abs)) {
|
|
57597
|
+
const childAbs = path18.join(abs, name);
|
|
57339
57598
|
const childRel = rel ? `${rel}/${name}` : name;
|
|
57340
|
-
if (
|
|
57341
|
-
else out.push({ path: childRel, contentBase64:
|
|
57599
|
+
if (fs19.statSync(childAbs).isDirectory()) walk(childAbs, childRel);
|
|
57600
|
+
else out.push({ path: childRel, contentBase64: fs19.readFileSync(childAbs).toString("base64") });
|
|
57342
57601
|
}
|
|
57343
57602
|
};
|
|
57344
57603
|
walk(root, "");
|
|
@@ -57464,7 +57723,7 @@ async function runCli(argv, println = console.log) {
|
|
|
57464
57723
|
}
|
|
57465
57724
|
switch (command) {
|
|
57466
57725
|
case "create-workorder": {
|
|
57467
|
-
const planRaw = flags.get("plan-file") !== void 0 ?
|
|
57726
|
+
const planRaw = flags.get("plan-file") !== void 0 ? fs19.readFileSync(flags.get("plan-file"), "utf8") : flags.get("plan");
|
|
57468
57727
|
const acceptanceFlag = flags.get("acceptance");
|
|
57469
57728
|
const args = {
|
|
57470
57729
|
createdVia: "seed",
|
|
@@ -57685,9 +57944,9 @@ async function runCli(argv, println = console.log) {
|
|
|
57685
57944
|
if (verb === "add") {
|
|
57686
57945
|
const file = flags.get("file");
|
|
57687
57946
|
if (file !== void 0) {
|
|
57688
|
-
const bytes =
|
|
57947
|
+
const bytes = fs19.readFileSync(file);
|
|
57689
57948
|
const res = await api.request("POST", `/api/projects/${encodeURIComponent(projectId)}/files`, {
|
|
57690
|
-
name: flags.get("name") ??
|
|
57949
|
+
name: flags.get("name") ?? path18.basename(file),
|
|
57691
57950
|
...flags.has("path") ? { path: flags.get("path") } : {},
|
|
57692
57951
|
content_base64: bytes.toString("base64"),
|
|
57693
57952
|
...flags.has("content-type") ? { content_type: flags.get("content-type") } : {}
|
|
@@ -57844,6 +58103,38 @@ ${res.warning}`);
|
|
|
57844
58103
|
println(message);
|
|
57845
58104
|
break;
|
|
57846
58105
|
}
|
|
58106
|
+
case "design": {
|
|
58107
|
+
const sub = positional[0];
|
|
58108
|
+
if (sub !== "run") throw new Error("\u7528\u6CD5\uFF1Aoasis design run <artifactId> [--brief <t>] [--reason <t>] [--od-url <url>] [--title <t>] [--agent <id>]");
|
|
58109
|
+
const artifactId = needPos(positional, 1, "oasis design run <artifactId>");
|
|
58110
|
+
const odBase = (flags.get("od-url") ?? process.env["OASIS_OPEN_DESIGN_URL"] ?? "http://127.0.0.1:7457").replace(/\/$/, "");
|
|
58111
|
+
const odPublic = (flags.get("od-public-url") ?? process.env["OASIS_OPEN_DESIGN_PUBLIC_URL"] ?? "https://design.open-friday.com").replace(/\/$/, "");
|
|
58112
|
+
const brief = flags.get("brief") ?? (fs19.existsSync("TASK.md") ? fs19.readFileSync("TASK.md", "utf8") : "");
|
|
58113
|
+
if (!brief.trim()) throw new Error("\u65E0\u8BBE\u8BA1\u4EFB\u52A1\uFF1A\u7ED9 --brief <text> \u6216\u5728\u5F53\u524D\u76EE\u5F55\u653E TASK.md");
|
|
58114
|
+
const contextFiles = { "TASK.md": brief };
|
|
58115
|
+
if (fs19.existsSync("inputs") && fs19.statSync("inputs").isDirectory()) {
|
|
58116
|
+
for (const f2 of readDirFiles("inputs")) {
|
|
58117
|
+
contextFiles[`inputs/${f2.path}`] = Buffer.from(f2.contentBase64, "base64").toString("utf8");
|
|
58118
|
+
}
|
|
58119
|
+
}
|
|
58120
|
+
println(`[design] \u753B\u677F ${deriveBoardKey(artifactId)} \u2190 ${artifactId}\uFF1B\u9A71\u52A8 od \u5F15\u64CE ${odBase} \u2026`);
|
|
58121
|
+
const { dir: dir2, entry, boardKey, runId } = await runOpenDesignSession({
|
|
58122
|
+
base: odBase,
|
|
58123
|
+
publicBase: odPublic,
|
|
58124
|
+
agentId: flags.get("agent") ?? "claude",
|
|
58125
|
+
artifactId,
|
|
58126
|
+
title: flags.get("title") ?? artifactId,
|
|
58127
|
+
message: brief,
|
|
58128
|
+
systemPrompt: "\u4F60\u662F\u8BBE\u8BA1\u5F15\u64CE\u4E2D\u7684\u754C\u9762\u8BBE\u8BA1\u5E08\u3002\u4EFB\u52A1\u4E66\u89C1\u672C\u6761\u6D88\u606F\uFF1B\u4E0A\u6E38\u8F93\u5165\u7B49\u4E0A\u4E0B\u6587\u6587\u4EF6\u5728\u9879\u76EE task-context/ \u76EE\u5F55\u3002\u6309\u4EFB\u52A1\u4E66\u7684\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u534F\u8BAE\u5DE5\u4F5C\uFF1A\u4EA7\u51FA\u81EA\u5305\u542B HTML \u5165\u53E3\u7A3F\u4E0E acceptance.md\uFF0C\u5B8C\u6210\u5373\u7ED3\u675F\u56DE\u590D\uFF0C\u4EA4\u7A3F\u7531\u7CFB\u7EDF\u4EE3\u529E\u3002",
|
|
58129
|
+
contextFiles,
|
|
58130
|
+
onLine: (line) => println(`[od] ${line.length > 500 ? line.slice(0, 500) + "\u2026" : line}`)
|
|
58131
|
+
});
|
|
58132
|
+
println(`[design] \u753B\u677F\u4EA7\u51FA ${entry}\uFF08board ${boardKey}, run ${runId.slice(0, 8)}\uFF09\u2192 \u4EA4\u7A3F\u4E2D \u2026`);
|
|
58133
|
+
const reason = flags.get("reason") ?? `\u753B\u677F\u5FEB\u7167\u4EA4\u4ED8\uFF1A${entry}\uFF08board ${boardKey}, run ${runId.slice(0, 8)}\uFF09`;
|
|
58134
|
+
const { message } = await api.cmd("propose", { artifactId, files: readDirFiles(dir2), reason });
|
|
58135
|
+
println(message);
|
|
58136
|
+
break;
|
|
58137
|
+
}
|
|
57847
58138
|
case "merge": {
|
|
57848
58139
|
const artifactId = needPos(positional, 0, "oasis merge <artifactId> [revisionId]");
|
|
57849
58140
|
const { message } = await api.cmd("merge", { artifactId, revisionId: positional[1] });
|
|
@@ -58236,8 +58527,8 @@ ${res.warning}`);
|
|
|
58236
58527
|
}
|
|
58237
58528
|
case "content": {
|
|
58238
58529
|
const id = needPos(positional, 0, "oasis content <artifactId> [path]");
|
|
58239
|
-
const
|
|
58240
|
-
const c = await api.view("content", id,
|
|
58530
|
+
const path20 = positional[1];
|
|
58531
|
+
const c = await api.view("content", id, path20 ? { path: path20 } : void 0);
|
|
58241
58532
|
if (c.kind === "empty") println("\uFF08\u672C\u4EA7\u7269\u5C1A\u65E0\u5185\u5BB9\uFF09");
|
|
58242
58533
|
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`);
|
|
58243
58534
|
else if (c.kind === "text") println(c.text);
|
|
@@ -58410,14 +58701,14 @@ ${res.warning}`);
|
|
|
58410
58701
|
}
|
|
58411
58702
|
|
|
58412
58703
|
// src/index.ts
|
|
58413
|
-
var PKG_VERSION = true ? "0.1.
|
|
58414
|
-
var OASIS_DIR =
|
|
58415
|
-
var CONFIG_FILE =
|
|
58416
|
-
var PID_FILE =
|
|
58417
|
-
var BIN_FILE =
|
|
58418
|
-
var LOCAL_BIN =
|
|
58419
|
-
var LOG_FILE =
|
|
58420
|
-
var NPM_PREFIX =
|
|
58704
|
+
var PKG_VERSION = true ? "0.1.47" : "dev";
|
|
58705
|
+
var OASIS_DIR = path19.join(os11.homedir(), ".oasis");
|
|
58706
|
+
var CONFIG_FILE = path19.join(OASIS_DIR, "node-config.json");
|
|
58707
|
+
var PID_FILE = path19.join(OASIS_DIR, "node.pid");
|
|
58708
|
+
var BIN_FILE = path19.join(OASIS_DIR, "bin", "oasis.js");
|
|
58709
|
+
var LOCAL_BIN = path19.join(os11.homedir(), ".local", "bin", "oasis");
|
|
58710
|
+
var LOG_FILE = path19.join(OASIS_DIR, "node.log");
|
|
58711
|
+
var NPM_PREFIX = path19.join(OASIS_DIR, "npm-global");
|
|
58421
58712
|
var PKG_NAME = "oasis_test";
|
|
58422
58713
|
var parseFlags = (argv) => {
|
|
58423
58714
|
const flags = /* @__PURE__ */ new Map();
|
|
@@ -58429,18 +58720,18 @@ var parseFlags = (argv) => {
|
|
|
58429
58720
|
};
|
|
58430
58721
|
var readConfig = () => {
|
|
58431
58722
|
try {
|
|
58432
|
-
return JSON.parse(
|
|
58723
|
+
return JSON.parse(fs20.readFileSync(CONFIG_FILE, "utf8"));
|
|
58433
58724
|
} catch {
|
|
58434
58725
|
return null;
|
|
58435
58726
|
}
|
|
58436
58727
|
};
|
|
58437
58728
|
var saveConfig = (c) => {
|
|
58438
|
-
|
|
58439
|
-
|
|
58729
|
+
fs20.mkdirSync(OASIS_DIR, { recursive: true });
|
|
58730
|
+
fs20.writeFileSync(CONFIG_FILE, JSON.stringify(c), { mode: 384 });
|
|
58440
58731
|
};
|
|
58441
58732
|
var readPid = () => {
|
|
58442
58733
|
try {
|
|
58443
|
-
const p2 = parseInt(
|
|
58734
|
+
const p2 = parseInt(fs20.readFileSync(PID_FILE, "utf8").trim(), 10);
|
|
58444
58735
|
return isNaN(p2) ? null : p2;
|
|
58445
58736
|
} catch {
|
|
58446
58737
|
return null;
|
|
@@ -58456,26 +58747,26 @@ var isRunning = (pid) => {
|
|
|
58456
58747
|
};
|
|
58457
58748
|
var httpBase = (wsUrl) => wsUrl.replace(/^ws(s?):\/\//, "http$1://").replace(/\/node-gateway.*$/, "");
|
|
58458
58749
|
function installBinary() {
|
|
58459
|
-
|
|
58460
|
-
|
|
58461
|
-
|
|
58462
|
-
|
|
58750
|
+
fs20.mkdirSync(path19.dirname(BIN_FILE), { recursive: true });
|
|
58751
|
+
fs20.copyFileSync(process.argv[1], BIN_FILE);
|
|
58752
|
+
fs20.mkdirSync(path19.dirname(LOCAL_BIN), { recursive: true });
|
|
58753
|
+
fs20.writeFileSync(LOCAL_BIN, `#!/bin/sh
|
|
58463
58754
|
exec node "${BIN_FILE}" "$@"
|
|
58464
58755
|
`, { mode: 493 });
|
|
58465
58756
|
}
|
|
58466
58757
|
function setupAutostart() {
|
|
58467
58758
|
const cmd = `${process.execPath} "${BIN_FILE}" --_daemon`;
|
|
58468
|
-
const home =
|
|
58759
|
+
const home = os11.homedir();
|
|
58469
58760
|
const extraBins = [
|
|
58470
|
-
|
|
58471
|
-
|
|
58761
|
+
path19.join(home, ".npm-global", "bin"),
|
|
58762
|
+
path19.join(home, ".local", "bin"),
|
|
58472
58763
|
"/usr/local/bin"
|
|
58473
58764
|
];
|
|
58474
58765
|
const daemonPath = [process.env["PATH"] ?? "", ...extraBins].filter(Boolean).join(":");
|
|
58475
58766
|
if (process.platform === "linux") {
|
|
58476
|
-
const unitDir =
|
|
58477
|
-
|
|
58478
|
-
|
|
58767
|
+
const unitDir = path19.join(os11.homedir(), ".config", "systemd", "user");
|
|
58768
|
+
fs20.mkdirSync(unitDir, { recursive: true });
|
|
58769
|
+
fs20.writeFileSync(path19.join(unitDir, "oasis-node.service"), [
|
|
58479
58770
|
"[Unit]",
|
|
58480
58771
|
"Description=Oasis Node Daemon",
|
|
58481
58772
|
"After=network.target",
|
|
@@ -58497,9 +58788,9 @@ function setupAutostart() {
|
|
|
58497
58788
|
} catch {
|
|
58498
58789
|
}
|
|
58499
58790
|
} else if (process.platform === "darwin") {
|
|
58500
|
-
const plist =
|
|
58501
|
-
|
|
58502
|
-
|
|
58791
|
+
const plist = path19.join(os11.homedir(), "Library", "LaunchAgents", "com.oasis.node.plist");
|
|
58792
|
+
fs20.mkdirSync(path19.dirname(plist), { recursive: true });
|
|
58793
|
+
fs20.writeFileSync(plist, `<?xml version="1.0" encoding="UTF-8"?>
|
|
58503
58794
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
58504
58795
|
<plist version="1.0"><dict>
|
|
58505
58796
|
<key>Label</key><string>com.oasis.node</string>
|
|
@@ -58516,14 +58807,14 @@ function setupAutostart() {
|
|
|
58516
58807
|
}
|
|
58517
58808
|
}
|
|
58518
58809
|
function spawnDaemon() {
|
|
58519
|
-
const log3 =
|
|
58810
|
+
const log3 = fs20.openSync(LOG_FILE, "a");
|
|
58520
58811
|
const child = (0, import_node_child_process15.spawn)(process.execPath, [BIN_FILE, "--_daemon"], {
|
|
58521
58812
|
detached: true,
|
|
58522
58813
|
stdio: ["ignore", log3, log3]
|
|
58523
58814
|
});
|
|
58524
58815
|
child.unref();
|
|
58525
58816
|
const pid = child.pid ?? 0;
|
|
58526
|
-
|
|
58817
|
+
fs20.writeFileSync(PID_FILE, String(pid));
|
|
58527
58818
|
return pid;
|
|
58528
58819
|
}
|
|
58529
58820
|
function stopDaemon() {
|
|
@@ -58535,7 +58826,7 @@ function stopDaemon() {
|
|
|
58535
58826
|
}
|
|
58536
58827
|
}
|
|
58537
58828
|
try {
|
|
58538
|
-
|
|
58829
|
+
fs20.unlinkSync(PID_FILE);
|
|
58539
58830
|
} catch {
|
|
58540
58831
|
}
|
|
58541
58832
|
try {
|
|
@@ -58551,7 +58842,7 @@ function selfUpdate() {
|
|
|
58551
58842
|
const cfg = readConfig();
|
|
58552
58843
|
if (!cfg?.serverUrl) throw new Error("no config \u2014 run `oasis start` first");
|
|
58553
58844
|
const nameArg = cfg.name ? ` --name '${cfg.name.replace(/'/g, "'\\''")}'` : "";
|
|
58554
|
-
const oasisBin =
|
|
58845
|
+
const oasisBin = path19.join(NPM_PREFIX, "bin", "oasis");
|
|
58555
58846
|
const startCmd = `"${oasisBin}" start --server-ws '${cfg.serverUrl}'${nameArg}`;
|
|
58556
58847
|
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`;
|
|
58557
58848
|
const hasSystemd = process.platform === "linux" && (() => {
|
|
@@ -58562,7 +58853,7 @@ function selfUpdate() {
|
|
|
58562
58853
|
return false;
|
|
58563
58854
|
}
|
|
58564
58855
|
})();
|
|
58565
|
-
const log3 =
|
|
58856
|
+
const log3 = fs20.openSync(LOG_FILE, "a");
|
|
58566
58857
|
if (hasSystemd) {
|
|
58567
58858
|
const child = (0, import_node_child_process15.spawn)("systemd-run", ["--user", "--scope", "--quiet", "sh", "-c", inner], {
|
|
58568
58859
|
detached: true,
|
|
@@ -58588,10 +58879,10 @@ void (async () => {
|
|
|
58588
58879
|
console.error(`[oasis] daemon already running (PID ${alivePid}) \u2014 exiting duplicate`);
|
|
58589
58880
|
process.exit(0);
|
|
58590
58881
|
}
|
|
58591
|
-
|
|
58882
|
+
fs20.writeFileSync(PID_FILE, String(process.pid));
|
|
58592
58883
|
const cleanup = () => {
|
|
58593
58884
|
try {
|
|
58594
|
-
|
|
58885
|
+
fs20.unlinkSync(PID_FILE);
|
|
58595
58886
|
} catch {
|
|
58596
58887
|
}
|
|
58597
58888
|
};
|
|
@@ -58651,7 +58942,7 @@ void (async () => {
|
|
|
58651
58942
|
const res = await fetch(`${httpBase(serverUrl)}/api/nodes/exchange`, {
|
|
58652
58943
|
method: "POST",
|
|
58653
58944
|
headers: { "content-type": "application/json" },
|
|
58654
|
-
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname:
|
|
58945
|
+
body: JSON.stringify({ enrollToken, nodeId: derivedNodeId, hostname: os11.hostname() })
|
|
58655
58946
|
});
|
|
58656
58947
|
if (!res.ok) throw new Error(`enroll token exchange failed: HTTP ${res.status}`);
|
|
58657
58948
|
const body = await res.json();
|
|
@@ -58674,7 +58965,7 @@ void (async () => {
|
|
|
58674
58965
|
const pid = spawnDaemon();
|
|
58675
58966
|
console.log(`\u2713 daemon started (PID ${pid})${nameChanged ? ` [name updated: ${prev.name} \u2192 ${name}]` : ""}`);
|
|
58676
58967
|
console.log(` logs: tail -f ${LOG_FILE}`);
|
|
58677
|
-
if (!process.env["PATH"]?.includes(
|
|
58968
|
+
if (!process.env["PATH"]?.includes(path19.dirname(LOCAL_BIN)))
|
|
58678
58969
|
console.log(` add to PATH: echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc && source ~/.bashrc`);
|
|
58679
58970
|
return;
|
|
58680
58971
|
}
|