oasis_test_v2 2.2.85 → 2.2.87
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 +740 -619
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -2524,368 +2524,26 @@ var init_sealed_node_receipt = __esm({
|
|
|
2524
2524
|
}
|
|
2525
2525
|
});
|
|
2526
2526
|
|
|
2527
|
-
// ../server/src/domains/chat-sessions/session-runtime-target.ts
|
|
2528
|
-
function sessionRuntimeOverride(session) {
|
|
2529
|
-
const nodeId = session?.overrideNodeId?.trim();
|
|
2530
|
-
const runtimeKind = session?.overrideRuntimeKind?.trim();
|
|
2531
|
-
if (!nodeId || !runtimeKind) return null;
|
|
2532
|
-
return { nodeId, runtimeKind };
|
|
2533
|
-
}
|
|
2534
|
-
function chatSessionInitialRuntime(input) {
|
|
2535
|
-
const trimmed = (v2) => typeof v2 === "string" && v2.trim() ? v2.trim() : null;
|
|
2536
|
-
const binding = input.binding?.nodeId && input.binding?.runtimeKind ? { nodeId: input.binding.nodeId, runtimeKind: input.binding.runtimeKind } : null;
|
|
2537
|
-
const requestedOverride = input.requested?.override;
|
|
2538
|
-
const picked = requestedOverride?.nodeId && requestedOverride?.runtimeKind ? { nodeId: requestedOverride.nodeId, runtimeKind: requestedOverride.runtimeKind } : null;
|
|
2539
|
-
const target = picked ?? binding;
|
|
2540
|
-
const followsAgentTarget = !picked || !!binding && picked.nodeId === binding.nodeId && picked.runtimeKind === binding.runtimeKind;
|
|
2541
|
-
const requestedModel = input.requested?.model;
|
|
2542
|
-
const model = requestedModel !== void 0 ? trimmed(requestedModel) : followsAgentTarget ? trimmed(input.agentModel) : null;
|
|
2543
|
-
return {
|
|
2544
|
-
overrideNodeId: target?.nodeId ?? null,
|
|
2545
|
-
overrideRuntimeKind: target?.runtimeKind ?? null,
|
|
2546
|
-
model
|
|
2547
|
-
};
|
|
2548
|
-
}
|
|
2549
|
-
function sessionRuntimeOverrideChangesTarget(session, binding) {
|
|
2550
|
-
const override = sessionRuntimeOverride(session);
|
|
2551
|
-
if (!override) return false;
|
|
2552
|
-
if (!binding) return true;
|
|
2553
|
-
return override.nodeId !== binding.nodeId || override.runtimeKind !== binding.runtimeKind;
|
|
2554
|
-
}
|
|
2555
|
-
async function resolveSessionRuntimeTarget(input) {
|
|
2556
|
-
const { probe } = input;
|
|
2557
|
-
const override = sessionRuntimeOverride(input.session);
|
|
2558
|
-
if (!override) {
|
|
2559
|
-
return probe.binding ? { binding: probe.binding, source: "actor_binding" } : null;
|
|
2560
|
-
}
|
|
2561
|
-
const kinds = await probe.availableRuntimeKinds(override.nodeId);
|
|
2562
|
-
const nodeName = (await probe.nodeDisplayName?.(override.nodeId))?.trim() || override.nodeId;
|
|
2563
|
-
if (kinds === null) {
|
|
2564
|
-
throw new SessionRuntimeOverrideError(
|
|
2565
|
-
"CHAT_SESSION_NODE_UNAVAILABLE",
|
|
2566
|
-
`\u8FD9\u6761\u4F1A\u8BDD\u9009\u5B9A\u7684\u8282\u70B9\u300C${nodeName}\u300D\u5F53\u524D\u4E0D\u53EF\u7528\uFF08\u53EF\u80FD\u5DF2\u79BB\u7EBF\u3001\u5DF2\u5220\u9664\uFF0C\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u516C\u53F8\uFF09\u3002\u8BF7\u786E\u8BA4\u90A3\u53F0\u673A\u5668\u5F00\u7740\u3001\u8282\u70B9\u7A0B\u5E8F\u5728\u8FD0\u884C\u540E\u518D\u53D1\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
2567
|
-
);
|
|
2568
|
-
}
|
|
2569
|
-
if (!kinds.includes(override.runtimeKind)) {
|
|
2570
|
-
throw new SessionRuntimeOverrideError(
|
|
2571
|
-
"CHAT_SESSION_RUNTIME_UNAVAILABLE",
|
|
2572
|
-
`\u8282\u70B9\u300C${nodeName}\u300D\u4E0A\u6CA1\u6709\u53EF\u7528\u7684\u8FD0\u884C\u65F6 ${override.runtimeKind}\uFF08\u53EF\u80FD\u5DF2\u5378\u8F7D\u3001\u8FD8\u6CA1\u88C5\u597D\uFF0C\u6216\u672A\u4E0A\u62A5\uFF09\u3002\u8BF7\u5728\u90A3\u53F0\u673A\u5668\u4E0A\u88C5\u597D\u540E\u518D\u53D1\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
2573
|
-
);
|
|
2574
|
-
}
|
|
2575
|
-
if (!probe.binding) {
|
|
2576
|
-
throw new SessionRuntimeOverrideError(
|
|
2577
|
-
"ACTOR_BINDING_MISSING",
|
|
2578
|
-
`\u8FD9\u4F4D Agent \u8FD8\u6CA1\u6709\u7ED1\u5B9A\u8FD0\u884C\u65F6\uFF0C\u9009\u5B9A\u8282\u70B9\u4E5F\u6D3E\u4E0D\u51FA\u53BB\u3002\u8BF7\u5148\u7ED9\u4ED6\u7ED1\u5B9A\u4E00\u4E2A\u53EF\u7528\u7684\u8FD0\u884C\u65F6\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
2579
|
-
);
|
|
2580
|
-
}
|
|
2581
|
-
return {
|
|
2582
|
-
binding: { actorId: probe.binding.actorId, nodeId: override.nodeId, runtimeKind: override.runtimeKind, status: probe.binding.status },
|
|
2583
|
-
source: "session_override"
|
|
2584
|
-
};
|
|
2585
|
-
}
|
|
2586
|
-
function canAnnounceRuntimeSwitch(prior) {
|
|
2587
|
-
const nodeId = prior?.runtimeId?.trim();
|
|
2588
|
-
const kind = prior?.runtimeKind?.trim();
|
|
2589
|
-
return Boolean(nodeId && kind && nodeId !== "unknown");
|
|
2590
|
-
}
|
|
2591
|
-
function runtimeSwitchedNotice(target) {
|
|
2592
|
-
const name = target.nodeName?.trim();
|
|
2593
|
-
const where = name ? `${name} \xB7 ${target.runtimeKind}` : target.runtimeKind;
|
|
2594
|
-
return `\u8FD0\u884C\u65F6\u5DF2\u5207\u5230 ${where}\uFF0C\u672C\u8F6E\u8D77\u5728\u65B0\u7684\u8FD0\u884C\u65F6\u4F1A\u8BDD\u4E2D\u7EE7\u7EED\uFF0C\u5DE5\u4F5C\u533A\u4E0E\u4E0A\u4E0B\u6587\u4E0D\u6CBF\u7528\u3002`;
|
|
2595
|
-
}
|
|
2596
|
-
var SessionRuntimeOverrideError, CLEAR_SESSION_RUNTIME_HINT;
|
|
2597
|
-
var init_session_runtime_target = __esm({
|
|
2598
|
-
"../server/src/domains/chat-sessions/session-runtime-target.ts"() {
|
|
2599
|
-
"use strict";
|
|
2600
|
-
SessionRuntimeOverrideError = class extends Error {
|
|
2601
|
-
constructor(code2, message, status = 409) {
|
|
2602
|
-
super(message);
|
|
2603
|
-
this.code = code2;
|
|
2604
|
-
this.status = status;
|
|
2605
|
-
this.name = "SessionRuntimeOverrideError";
|
|
2606
|
-
}
|
|
2607
|
-
};
|
|
2608
|
-
CLEAR_SESSION_RUNTIME_HINT = "\u5728\u8F93\u5165\u6846\u5E95\u90E8\u7684\u8FD0\u884C\u65F6\u9009\u62E9\u91CC\u6362\u4E00\u53F0\u53EF\u7528\u7684\u670D\u52A1\u5668\u6216\u8FD0\u884C\u65F6\u5373\u53EF\u7EE7\u7EED\uFF08\u5458\u5DE5\u81EA\u5DF1\u7684\u90A3\u4E00\u5957\u6807\u7740\u300C\u5F53\u524D\u5458\u5DE5\u6240\u5728\u670D\u52A1\u5668\u300D\u300C\u5F53\u524D\u5458\u5DE5\u8FD0\u884C\u65F6\u300D\uFF09\u3002";
|
|
2609
|
-
}
|
|
2610
|
-
});
|
|
2611
|
-
|
|
2612
|
-
// ../server/src/artifact-content.ts
|
|
2613
|
-
async function currentOutput(kernel, artifactId) {
|
|
2614
|
-
await kernel.refreshModel();
|
|
2615
|
-
const artifact = kernel.model.artifacts.get(artifactId);
|
|
2616
|
-
if (!artifact) throw new ApiError(404, "NOT_FOUND", "\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
2617
|
-
const snap = await kernel.getStore().transaction((tx) => tx.loadWorkorder(artifact.workspace));
|
|
2618
|
-
const node2 = snap?.nodes.find((n) => n.id === artifactId);
|
|
2619
|
-
const latest = snap?.works.find((w2) => w2.id === node2?.latestWorkId);
|
|
2620
|
-
const workId = latest && (latest.status === "failed" || latest.status === "dead") && node2?.latestProposedWorkId ? node2.latestProposedWorkId : node2?.latestWorkId;
|
|
2621
|
-
const output = snap?.artifacts.filter((a) => a.workId === workId).sort((a, b2) => a.ordinal - b2.ordinal)[0];
|
|
2622
|
-
if (!node2 || !output) throw new ApiError(404, "NOT_FOUND", "\u8FD9\u4E2A\u8282\u70B9\u5C1A\u672A\u4EA4\u4ED8\u6587\u4EF6");
|
|
2623
|
-
return { node: node2, output };
|
|
2624
|
-
}
|
|
2625
|
-
function looksLikeFileName(name) {
|
|
2626
|
-
return /^\.[a-z]{1,8}[0-9]?$/.test(fileExtensionOf(name));
|
|
2627
|
-
}
|
|
2628
|
-
function decodeText(bytes2) {
|
|
2629
|
-
if (bytes2.length > currentFileLimits().textEditBytes || bytes2.includes(0)) return null;
|
|
2630
|
-
try {
|
|
2631
|
-
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
2632
|
-
} catch {
|
|
2633
|
-
return null;
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2636
|
-
async function readEditable(kernel, blobs, artifactId, path47) {
|
|
2637
|
-
const { node: node2, output } = await currentOutput(kernel, artifactId);
|
|
2638
|
-
let text7 = null;
|
|
2639
|
-
if (output.contentKind === "manifest" && path47 !== null) {
|
|
2640
|
-
const manifest = parseManifest(await blobs.get(output.contentRef));
|
|
2641
|
-
const entry = manifest.entries.find((e) => e.path === path47);
|
|
2642
|
-
if (!entry) throw new ApiError(404, "NOT_FOUND", "\u5305\u5185\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
2643
|
-
if (isEditableFileName(entry.path)) text7 = decodeText(await blobs.get(entry.hash));
|
|
2644
|
-
} else if (output.contentKind === "inline") {
|
|
2645
|
-
const name = node2.title || output.name;
|
|
2646
|
-
if (!looksLikeFileName(name) || isEditableFileName(name)) text7 = decodeText(await blobs.get(output.contentRef));
|
|
2647
|
-
}
|
|
2648
|
-
const view = {
|
|
2649
|
-
artifactId,
|
|
2650
|
-
revisionId: output.workId,
|
|
2651
|
-
contentRef: output.contentRef,
|
|
2652
|
-
path: path47,
|
|
2653
|
-
editable: text7 !== null,
|
|
2654
|
-
text: text7
|
|
2655
|
-
};
|
|
2656
|
-
return { view, node: node2, output };
|
|
2657
|
-
}
|
|
2658
|
-
async function readArtifactEditableContent(kernel, blobs, artifactId, path47) {
|
|
2659
|
-
return (await readEditable(kernel, blobs, artifactId, path47)).view;
|
|
2660
|
-
}
|
|
2661
|
-
async function saveArtifactContent(kernel, blobs, actor, input) {
|
|
2662
|
-
if (!input || typeof input.artifactId !== "string" || typeof input.revisionId !== "string" || typeof input.contentRef !== "string" || typeof input.text !== "string" || input.path != null && typeof input.path !== "string") {
|
|
2663
|
-
throw new ApiError(400, "BAD_REQUEST", "\u4FDD\u5B58\u53C2\u6570\u4E0D\u5B8C\u6574");
|
|
2664
|
-
}
|
|
2665
|
-
const bytes2 = new TextEncoder().encode(input.text);
|
|
2666
|
-
if (bytes2.length > currentFileLimits().textEditBytes || bytes2.includes(0)) {
|
|
2667
|
-
throw new ApiError(400, "BAD_REQUEST", `\u4EC5\u652F\u6301\u4E0D\u8D85\u8FC7 ${currentFileLimits().textEditBytes / 1024 / 1024} MiB \u7684 UTF-8 \u6587\u672C`);
|
|
2668
|
-
}
|
|
2669
|
-
const path47 = input.path ?? null;
|
|
2670
|
-
const { view, node: node2, output } = await readEditable(kernel, blobs, input.artifactId, path47);
|
|
2671
|
-
if (view.revisionId !== input.revisionId || view.contentRef !== input.contentRef) {
|
|
2672
|
-
throw new ApiError(409, "CONTENT_CONFLICT", "\u5185\u5BB9\u5DF2\u88AB\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6587\u4EF6\u540E\u518D\u4FDD\u5B58");
|
|
2673
|
-
}
|
|
2674
|
-
if (!view.editable) throw new ApiError(400, "NOT_EDITABLE", "\u6B64\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91");
|
|
2675
|
-
let contentRef = await blobs.put(bytes2);
|
|
2676
|
-
if (output.contentKind === "manifest") {
|
|
2677
|
-
const manifest = parseManifest(await blobs.get(output.contentRef));
|
|
2678
|
-
contentRef = await blobs.put(serializeManifest(manifest.entries.map((e) => e.path === path47 ? { ...e, hash: contentRef, size: bytes2.length } : e)));
|
|
2679
|
-
}
|
|
2680
|
-
try {
|
|
2681
|
-
await kernel.editArtifactContent({
|
|
2682
|
-
artifactId: input.artifactId,
|
|
2683
|
-
actor,
|
|
2684
|
-
workId: output.workId,
|
|
2685
|
-
outputId: output.id,
|
|
2686
|
-
expectedLatestWorkId: node2.latestWorkId,
|
|
2687
|
-
previousRef: output.contentRef,
|
|
2688
|
-
contentRef,
|
|
2689
|
-
path: path47
|
|
2690
|
-
});
|
|
2691
|
-
} catch (error2) {
|
|
2692
|
-
if (error2.code === "content-conflict") {
|
|
2693
|
-
throw new ApiError(409, "CONTENT_CONFLICT", "\u5185\u5BB9\u5DF2\u88AB\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6587\u4EF6\u540E\u518D\u4FDD\u5B58");
|
|
2694
|
-
}
|
|
2695
|
-
throw error2;
|
|
2696
|
-
}
|
|
2697
|
-
return { ...view, contentRef, text: input.text };
|
|
2698
|
-
}
|
|
2699
|
-
async function readArtifactFile(kernel, blobs, artifactId, path47, expectedRef, revisionId = null) {
|
|
2700
|
-
await kernel.refreshModel();
|
|
2701
|
-
const artifact = kernel.model.artifacts.get(artifactId);
|
|
2702
|
-
const selectedRevision = revisionId ?? artifact?.currentRev;
|
|
2703
|
-
const output = selectedRevision ? kernel.model.revisions.get(selectedRevision) : void 0;
|
|
2704
|
-
if (!artifact || !output || output.artifactId !== artifactId) {
|
|
2705
|
-
throw new ApiError(404, "NOT_FOUND", revisionId !== null ? "\u8BE5\u4EA7\u7269\u7248\u672C\u4E0D\u5B58\u5728" : "\u6B64\u4EA7\u7269\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684\u539F\u6587\u4EF6");
|
|
2706
|
-
}
|
|
2707
|
-
if (expectedRef && output.contentRef !== expectedRef) throw new ApiError(409, "CONTENT_CONFLICT", "\u6587\u4EF6\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00");
|
|
2708
|
-
let hash3 = output.contentRef;
|
|
2709
|
-
let name = artifact.title || artifactId;
|
|
2710
|
-
if (output.contentKind === "manifest") {
|
|
2711
|
-
if (!path47) throw new ApiError(400, "PATH_REQUIRED", "\u8BF7\u9009\u62E9\u6587\u4EF6\u5939\u4E2D\u7684\u5177\u4F53\u6587\u4EF6");
|
|
2712
|
-
const entry = parseManifest(await blobs.get(output.contentRef)).entries.find((e) => e.path === path47);
|
|
2713
|
-
if (!entry) throw new ApiError(404, "NOT_FOUND", "\u5305\u5185\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
2714
|
-
hash3 = entry.hash;
|
|
2715
|
-
name = entry.path;
|
|
2716
|
-
if (entry.size !== void 0 && entry.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2717
|
-
} else if (output.contentKind !== "inline-blob") {
|
|
2718
|
-
throw new ApiError(404, "NOT_FOUND", "\u6B64\u4EA7\u7269\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684\u539F\u6587\u4EF6");
|
|
2719
|
-
}
|
|
2720
|
-
const meta = await blobs.meta?.(hash3);
|
|
2721
|
-
if (meta && meta.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2722
|
-
try {
|
|
2723
|
-
return { bytes: await blobs.get(hash3), name, contentType: meta?.contentType };
|
|
2724
|
-
} catch {
|
|
2725
|
-
throw new ApiError(404, "NOT_FOUND", "\u5F53\u524D\u516C\u53F8\u4E2D\u627E\u4E0D\u5230\u8BE5\u6587\u4EF6\u6B63\u6587");
|
|
2726
|
-
}
|
|
2727
|
-
}
|
|
2728
|
-
var init_artifact_content2 = __esm({
|
|
2729
|
-
"../server/src/artifact-content.ts"() {
|
|
2730
|
-
"use strict";
|
|
2731
|
-
init_file_limits2();
|
|
2732
|
-
init_src();
|
|
2733
|
-
init_router();
|
|
2734
|
-
}
|
|
2735
|
-
});
|
|
2736
|
-
|
|
2737
|
-
// ../server/src/file-http.ts
|
|
2738
|
-
async function serveFileRequest(req, res, url, engine) {
|
|
2739
|
-
try {
|
|
2740
|
-
if (req.method !== "GET" || url.pathname !== "/api/files/content") throw new ApiError(404, "NOT_FOUND", "\u6587\u4EF6\u63A5\u53E3\u4E0D\u5B58\u5728");
|
|
2741
|
-
const { bytes: bytes2, name, contentType } = await readArtifactFile(
|
|
2742
|
-
engine.kernel,
|
|
2743
|
-
engine.blobs,
|
|
2744
|
-
url.searchParams.get("artifact") ?? "",
|
|
2745
|
-
url.searchParams.get("path"),
|
|
2746
|
-
url.searchParams.get("ref"),
|
|
2747
|
-
url.searchParams.get("revisionId")
|
|
2748
|
-
);
|
|
2749
|
-
if (bytes2.length > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
2750
|
-
res.writeHead(200, {
|
|
2751
|
-
"content-type": contentType ?? sniffContentType(bytes2) ?? "application/octet-stream",
|
|
2752
|
-
"content-length": String(bytes2.length),
|
|
2753
|
-
"cache-control": "private, no-store",
|
|
2754
|
-
"x-content-type-options": "nosniff",
|
|
2755
|
-
"content-disposition": `attachment; filename*=UTF-8''${encodeURIComponent(name.split(/[\\/]/).pop() || "file").replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`)}`
|
|
2756
|
-
}).end(Buffer.from(bytes2));
|
|
2757
|
-
} catch (error2) {
|
|
2758
|
-
if (res.destroyed) return;
|
|
2759
|
-
const status = error2 instanceof ApiError ? error2.status : 500;
|
|
2760
|
-
if (!req.complete) {
|
|
2761
|
-
res.setHeader("connection", "close");
|
|
2762
|
-
req.resume();
|
|
2763
|
-
}
|
|
2764
|
-
res.writeHead(status, { "content-type": "application/json", "cache-control": "no-store" }).end(JSON.stringify({
|
|
2765
|
-
error: {
|
|
2766
|
-
code: error2 instanceof ApiError ? error2.code : "FILE_READ_FAILED",
|
|
2767
|
-
message: error2 instanceof ApiError ? error2.message : "\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
2768
|
-
}
|
|
2769
|
-
}));
|
|
2770
|
-
}
|
|
2771
|
-
}
|
|
2772
|
-
var init_file_http = __esm({
|
|
2773
|
-
"../server/src/file-http.ts"() {
|
|
2774
|
-
"use strict";
|
|
2775
|
-
init_src();
|
|
2776
|
-
init_artifact_content2();
|
|
2777
|
-
init_router();
|
|
2778
|
-
init_file_limits2();
|
|
2779
|
-
}
|
|
2780
|
-
});
|
|
2781
|
-
|
|
2782
|
-
// ../server/src/build-info.ts
|
|
2783
|
-
function findRepoRoot() {
|
|
2784
|
-
let dir;
|
|
2785
|
-
try {
|
|
2786
|
-
dir = path.dirname((0, import_node_url.fileURLToPath)(__esm_import_meta_url));
|
|
2787
|
-
} catch {
|
|
2788
|
-
return null;
|
|
2789
|
-
}
|
|
2790
|
-
for (let i = 0; i < 12; i++) {
|
|
2791
|
-
if (fs.existsSync(path.join(dir, ".git"))) return dir;
|
|
2792
|
-
const parent = path.dirname(dir);
|
|
2793
|
-
if (parent === dir) break;
|
|
2794
|
-
dir = parent;
|
|
2795
|
-
}
|
|
2796
|
-
return null;
|
|
2797
|
-
}
|
|
2798
|
-
function git(root, args) {
|
|
2799
|
-
try {
|
|
2800
|
-
const out = (0, import_node_child_process.execFileSync)("git", args, {
|
|
2801
|
-
cwd: root,
|
|
2802
|
-
encoding: "utf8",
|
|
2803
|
-
timeout: 3e3,
|
|
2804
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
2805
|
-
});
|
|
2806
|
-
const v2 = out.trim();
|
|
2807
|
-
return v2 || null;
|
|
2808
|
-
} catch {
|
|
2809
|
-
return null;
|
|
2810
|
-
}
|
|
2811
|
-
}
|
|
2812
|
-
function getBuildInfo() {
|
|
2813
|
-
if (cached) return cached;
|
|
2814
|
-
const envSha = process.env["OASIS_GIT_SHA"]?.trim();
|
|
2815
|
-
const envBranch = process.env["OASIS_GIT_BRANCH"]?.trim();
|
|
2816
|
-
let gitSha = envSha || null;
|
|
2817
|
-
let gitBranch = envBranch || null;
|
|
2818
|
-
if (!gitSha || !gitBranch) {
|
|
2819
|
-
const root = findRepoRoot();
|
|
2820
|
-
if (root) {
|
|
2821
|
-
if (!gitSha) gitSha = git(root, ["rev-parse", "HEAD"]);
|
|
2822
|
-
if (!gitBranch) {
|
|
2823
|
-
const b2 = git(root, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
2824
|
-
gitBranch = b2 === "HEAD" ? null : b2;
|
|
2825
|
-
}
|
|
2826
|
-
}
|
|
2827
|
-
}
|
|
2828
|
-
cached = { gitSha, gitBranch, startedAt: STARTED_AT };
|
|
2829
|
-
return cached;
|
|
2830
|
-
}
|
|
2831
|
-
function resetBuildInfoCacheForTest() {
|
|
2832
|
-
cached = void 0;
|
|
2833
|
-
}
|
|
2834
|
-
var import_node_child_process, fs, path, import_node_url, STARTED_AT, cached;
|
|
2835
|
-
var init_build_info = __esm({
|
|
2836
|
-
"../server/src/build-info.ts"() {
|
|
2837
|
-
"use strict";
|
|
2838
|
-
import_node_child_process = require("node:child_process");
|
|
2839
|
-
fs = __toESM(require("node:fs"), 1);
|
|
2840
|
-
path = __toESM(require("node:path"), 1);
|
|
2841
|
-
import_node_url = require("node:url");
|
|
2842
|
-
STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
2843
|
-
}
|
|
2844
|
-
});
|
|
2845
|
-
|
|
2846
|
-
// ../server/src/command-policy.ts
|
|
2847
|
-
function classifyCommand(command2) {
|
|
2848
|
-
return COMMAND_POLICY[command2] ?? { risk: "direct" };
|
|
2849
|
-
}
|
|
2850
|
-
var shortId, COMMAND_POLICY;
|
|
2851
|
-
var init_command_policy = __esm({
|
|
2852
|
-
"../server/src/command-policy.ts"() {
|
|
2853
|
-
"use strict";
|
|
2854
|
-
shortId = (v2) => typeof v2 === "string" ? v2.replace(/^artifact:[^:]+:/, "") : String(v2 ?? "?");
|
|
2855
|
-
COMMAND_POLICY = {
|
|
2856
|
-
forceConclude: {
|
|
2857
|
-
risk: "authorize",
|
|
2858
|
-
idempotent: false,
|
|
2859
|
-
effect: (a) => `\u5F3A\u5236\u6536\u53E3\u8282\u70B9 ${shortId(a.artifactId)}\uFF08\u7ED5\u8FC7\u8BC4\u5BA1\u95F8\u76F4\u63A5\u76D6\u91CC\u7A0B\u7891\uFF09`
|
|
2860
|
-
},
|
|
2861
|
-
promote: {
|
|
2862
|
-
risk: "authorize",
|
|
2863
|
-
idempotent: true,
|
|
2864
|
-
effect: (a) => `\u628A\u8282\u70B9 ${shortId(a.artifactId)} \u8F6C\u4E3A\u6301\u4E45\uFF08temp \u2192 persistent\uFF09`
|
|
2865
|
-
},
|
|
2866
|
-
resolveEscalation: {
|
|
2867
|
-
risk: "authorize",
|
|
2868
|
-
idempotent: true,
|
|
2869
|
-
// 重复关同一条是幂等的(kernel.resolveEscalation 内部按 escalationId 去重)
|
|
2870
|
-
// 「关错=静默停摆」的唯一防线是人在卡上一眼看出「关的是哪一条」——escalationId 与 reason 摘要必须上卡。
|
|
2871
|
-
// a 里 escalationId/artifactId 由 server.ts 起草时冻进 commandArgs(已四级解析),保证是真值、非 `?`。
|
|
2872
|
-
effect: (a) => typeof a.gapId === "string" ? `\u91C7\u7528\u65B9\u6848\uFF1A${String(a.reason ?? "")}\uFF1B\u89E3\u51B3\u7F3A\u53E3 ${a.gapId}\uFF1B\u5173\u95ED\u5173\u8054\u4E0A\u62A5 ${String(a.escalationId)}\uFF1B\u7EE7\u7EED\u6267\u884C\uFF1A\u662F\uFF08\u4ECD\u987B\u6EE1\u8DB3\u5176\u4ED6\u963B\u585E\u6761\u4EF6\uFF09` : `\u5173\u95ED\u4E0A\u62A5 ${shortId(a.escalationId)}\uFF08\u8282\u70B9 ${shortId(a.artifactId)}${typeof a.reason === "string" ? `\uFF0C\u7406\u7531\uFF1A${a.reason}` : ""}\uFF09`
|
|
2873
|
-
},
|
|
2874
|
-
gc: {
|
|
2875
|
-
risk: "forbidden",
|
|
2876
|
-
forbiddenReason: "gc \u662F\u56DE\u6536\u5B64\u513F blob \u7684\u57FA\u7840\u8BBE\u65BD\u7EF4\u62A4\uFF0C\u7531 serve \u8FDB\u7A0B/\u4EBA\u7C7B operator \u6267\u884C\uFF0C\u4E0D\u5C5E\u4E8E\u7BA1\u7406\u8005\u80FD\u529B\u8303\u56F4\u3002"
|
|
2877
|
-
}
|
|
2878
|
-
};
|
|
2879
|
-
}
|
|
2880
|
-
});
|
|
2881
|
-
|
|
2882
2527
|
// ../adapters/src/open-design/driver.ts
|
|
2883
|
-
function
|
|
2528
|
+
function boardKeyOf(artifactId, fingerprintInput) {
|
|
2884
2529
|
const tail = artifactId.split(":").pop() ?? artifactId;
|
|
2885
2530
|
const ascii = tail.replace(/[^a-zA-Z0-9-]+/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "").slice(0, 24);
|
|
2886
|
-
const sha8 = (0, import_node_crypto2.createHash)("sha256").update(
|
|
2531
|
+
const sha8 = (0, import_node_crypto2.createHash)("sha256").update(fingerprintInput).digest("hex").slice(0, 8);
|
|
2887
2532
|
return ascii ? `od-${ascii}-${sha8}` : `od-${sha8}`;
|
|
2888
2533
|
}
|
|
2534
|
+
function deriveBoardKey(companyId, artifactId) {
|
|
2535
|
+
const company = companyId.trim();
|
|
2536
|
+
if (company.length === 0) throw new Error(`\u6D3E\u751F\u753B\u677F\u540D\u9700\u8981\u516C\u53F8 id\uFF08${artifactId}\uFF09\u2014\u2014\u62FF\u4E0D\u5230\u516C\u53F8\u65F6\u4E0D\u80FD\u56DE\u843D\u5230\u4E0D\u5E26\u516C\u53F8\u7684\u65E7\u540D\u5B57`);
|
|
2537
|
+
return boardKeyOf(artifactId, `${company}\0${artifactId}`);
|
|
2538
|
+
}
|
|
2539
|
+
function parseBoardLinkBoardKey(text7) {
|
|
2540
|
+
for (const line2 of text7.split(/\r?\n/)) {
|
|
2541
|
+
const m2 = /\/projects\/([^/\s?#]+)\s*$/.exec(line2.trim());
|
|
2542
|
+
if (!m2) continue;
|
|
2543
|
+
return BOARD_KEY_RE.test(m2[1]) ? m2[1] : null;
|
|
2544
|
+
}
|
|
2545
|
+
return null;
|
|
2546
|
+
}
|
|
2889
2547
|
function withOdToken(fetchImpl, token) {
|
|
2890
2548
|
if (!token) return fetchImpl;
|
|
2891
2549
|
return (input, init) => {
|
|
@@ -3086,8 +2744,7 @@ async function fetchBoardTurns(base, fetchImpl, boardKey) {
|
|
|
3086
2744
|
turns.sort((a, b2) => (b2.startedAt ?? Number.NEGATIVE_INFINITY) - (a.startedAt ?? Number.NEGATIVE_INFINITY) || 0);
|
|
3087
2745
|
return turns;
|
|
3088
2746
|
}
|
|
3089
|
-
async function fetchBoardStatus(base, fetchImpl,
|
|
3090
|
-
const boardKey = deriveBoardKey(artifactId);
|
|
2747
|
+
async function fetchBoardStatus(base, fetchImpl, boardKey) {
|
|
3091
2748
|
let boardExists = true;
|
|
3092
2749
|
let artifacts = [];
|
|
3093
2750
|
try {
|
|
@@ -3131,7 +2788,7 @@ async function fetchBoardStatus(base, fetchImpl, artifactId) {
|
|
|
3131
2788
|
const turns = boardExists ? await fetchBoardTurns(base, fetchImpl, boardKey) : [];
|
|
3132
2789
|
return { boardKey, boardExists, runs, turns, artifacts };
|
|
3133
2790
|
}
|
|
3134
|
-
async function waitBoardSettled(base, fetchImpl,
|
|
2791
|
+
async function waitBoardSettled(base, fetchImpl, boardKey, opts = {}) {
|
|
3135
2792
|
const interval = opts.intervalMs ?? 2e4;
|
|
3136
2793
|
const timeout = opts.timeoutMs ?? 100 * 6e4;
|
|
3137
2794
|
const sleep6 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
@@ -3140,7 +2797,7 @@ async function waitBoardSettled(base, fetchImpl, artifactId, opts = {}) {
|
|
|
3140
2797
|
let lastKey = null;
|
|
3141
2798
|
let waited = false;
|
|
3142
2799
|
for (; ; ) {
|
|
3143
|
-
const st = await fetchBoardStatus(base, fetchImpl,
|
|
2800
|
+
const st = await fetchBoardStatus(base, fetchImpl, boardKey);
|
|
3144
2801
|
const elapsedMs = now() - started;
|
|
3145
2802
|
if (!st.boardExists) return { status: st, settled: true, waited, live: [], elapsedMs };
|
|
3146
2803
|
const live = liveBoardRuns(st);
|
|
@@ -3201,7 +2858,7 @@ async function harvestBoard(base, fetchImpl, publicBase, workRoot, boardKey, run
|
|
|
3201
2858
|
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));
|
|
3202
2859
|
const entry = htmls[0]?.path;
|
|
3203
2860
|
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");
|
|
3204
|
-
const dir =
|
|
2861
|
+
const dir = fs.mkdtempSync(path.join(workRoot, "od-deliverable-"));
|
|
3205
2862
|
const fetchInline = async (rel) => {
|
|
3206
2863
|
const res = await fetchImpl(`${base}/api/projects/${encodeURIComponent(boardKey)}/export/${encodeURIComponent(rel)}?inline=1`);
|
|
3207
2864
|
if (!res.ok) throw new Error(`od export ${rel} \u2192 ${res.status}`);
|
|
@@ -3212,16 +2869,16 @@ async function harvestBoard(base, fetchImpl, publicBase, workRoot, boardKey, run
|
|
|
3212
2869
|
if (!res.ok) throw new Error(`od raw ${rel} \u2192 ${res.status}`);
|
|
3213
2870
|
return await res.text();
|
|
3214
2871
|
};
|
|
3215
|
-
|
|
2872
|
+
fs.writeFileSync(path.join(dir, "index.html"), await fetchInline(entry));
|
|
3216
2873
|
for (const f2 of listing.files ?? []) {
|
|
3217
2874
|
if (f2.path.endsWith(".md") && !f2.path.includes("/")) {
|
|
3218
2875
|
try {
|
|
3219
|
-
|
|
2876
|
+
fs.writeFileSync(path.join(dir, f2.path), await fetchRaw(f2.path));
|
|
3220
2877
|
} catch {
|
|
3221
2878
|
}
|
|
3222
2879
|
}
|
|
3223
2880
|
}
|
|
3224
|
-
|
|
2881
|
+
fs.writeFileSync(path.join(dir, BOARD_LINK_FILE), formatBoardLink({ publicBase, boardKey, entry, runId }));
|
|
3225
2882
|
return { dir, entry };
|
|
3226
2883
|
}
|
|
3227
2884
|
function formatBoardLink(args) {
|
|
@@ -3242,7 +2899,7 @@ function parseBoardLinkSourceRun(text7) {
|
|
|
3242
2899
|
}
|
|
3243
2900
|
async function startDesignChatTurn(opts) {
|
|
3244
2901
|
const fetchImpl = withOdToken(opts.fetchImpl ?? fetch, opts.token);
|
|
3245
|
-
const boardKey =
|
|
2902
|
+
const boardKey = opts.boardKey;
|
|
3246
2903
|
const { conversationId } = await ensureProject(opts.base, fetchImpl, boardKey, opts.title);
|
|
3247
2904
|
if (opts.contextFiles) await materializeContext(opts.base, fetchImpl, boardKey, opts.contextFiles);
|
|
3248
2905
|
const userMessageId = await putVisibleUserTurn(opts.base, fetchImpl, { boardKey, conversationId, content: opts.message });
|
|
@@ -3269,13 +2926,14 @@ async function runDesignChatTurn(opts) {
|
|
|
3269
2926
|
const { artifacts, fileCount } = await fetchResultPackage(opts.base, fetchImpl, runId);
|
|
3270
2927
|
return { boardKey, conversationId, runId, userMessageId, artifacts, fileCount };
|
|
3271
2928
|
}
|
|
3272
|
-
var import_node_crypto2,
|
|
2929
|
+
var import_node_crypto2, fs, path, BOARD_KEY_RE, OdHttpError, TASK_CONTEXT_DIR, TERMINAL_TURN_STATUS, isTerminalRunStatus, BOARD_LINK_FILE, SOURCE_RUN_LABEL, UNKNOWN_SOURCE_RUN;
|
|
3273
2930
|
var init_driver = __esm({
|
|
3274
2931
|
"../adapters/src/open-design/driver.ts"() {
|
|
3275
2932
|
"use strict";
|
|
3276
2933
|
import_node_crypto2 = require("node:crypto");
|
|
3277
|
-
|
|
3278
|
-
|
|
2934
|
+
fs = __toESM(require("node:fs"), 1);
|
|
2935
|
+
path = __toESM(require("node:path"), 1);
|
|
2936
|
+
BOARD_KEY_RE = /^[A-Za-z0-9-]{1,64}$/;
|
|
3279
2937
|
OdHttpError = class extends Error {
|
|
3280
2938
|
constructor(message, status) {
|
|
3281
2939
|
super(message);
|
|
@@ -3328,20 +2986,20 @@ function materializeBundle(dir, bundle) {
|
|
|
3328
2986
|
for (const [rel, entry] of Object.entries(bundle.restoreFiles ?? {})) {
|
|
3329
2987
|
try {
|
|
3330
2988
|
const parts = rel.split("/");
|
|
3331
|
-
if (!rel ||
|
|
2989
|
+
if (!rel || path2.isAbsolute(rel) || rel.includes("\\") || parts.some((p2) => !p2 || p2 === "." || p2 === "..")) {
|
|
3332
2990
|
throw new Error("\u975E\u6CD5\u76F8\u5BF9\u8DEF\u5F84");
|
|
3333
2991
|
}
|
|
3334
|
-
let parent =
|
|
2992
|
+
let parent = fs2.realpathSync(dir);
|
|
3335
2993
|
for (const component of parts.slice(0, -1)) {
|
|
3336
|
-
parent =
|
|
3337
|
-
if (!
|
|
3338
|
-
const st =
|
|
2994
|
+
parent = path2.join(parent, component);
|
|
2995
|
+
if (!fs2.existsSync(parent)) fs2.mkdirSync(parent);
|
|
2996
|
+
const st = fs2.lstatSync(parent);
|
|
3339
2997
|
if (st.isSymbolicLink() || !st.isDirectory()) throw new Error("\u6062\u590D\u8DEF\u5F84\u5305\u542B\u975E\u76EE\u5F55\u6216\u8F6F\u94FE\u63A5");
|
|
3340
2998
|
}
|
|
3341
|
-
const file =
|
|
2999
|
+
const file = path2.join(parent, parts.at(-1));
|
|
3342
3000
|
let exists = false;
|
|
3343
3001
|
try {
|
|
3344
|
-
const st =
|
|
3002
|
+
const st = fs2.lstatSync(file);
|
|
3345
3003
|
if (!st.isFile() || st.isSymbolicLink()) throw new Error("\u6062\u590D\u76EE\u6807\u4E0D\u662F\u666E\u901A\u6587\u4EF6");
|
|
3346
3004
|
exists = true;
|
|
3347
3005
|
} catch (error2) {
|
|
@@ -3351,37 +3009,37 @@ function materializeBundle(dir, bundle) {
|
|
|
3351
3009
|
if (exists && !entry.overwrite) continue;
|
|
3352
3010
|
const bytes2 = Buffer.from(entry.contentBase64, "base64");
|
|
3353
3011
|
if ((0, import_node_crypto3.createHash)("sha256").update(bytes2).digest("hex") !== entry.sha256) throw new Error("\u5185\u5BB9\u6821\u9A8C\u5931\u8D25");
|
|
3354
|
-
const temp =
|
|
3012
|
+
const temp = path2.join(parent, `.oasis-restore-${(0, import_node_crypto3.randomUUID)()}`);
|
|
3355
3013
|
try {
|
|
3356
|
-
|
|
3357
|
-
|
|
3014
|
+
fs2.writeFileSync(temp, bytes2, { flag: "wx", mode: 384 });
|
|
3015
|
+
fs2.renameSync(temp, file);
|
|
3358
3016
|
} finally {
|
|
3359
|
-
|
|
3017
|
+
fs2.rmSync(temp, { force: true });
|
|
3360
3018
|
}
|
|
3361
3019
|
} catch (error2) {
|
|
3362
3020
|
throw new BundleRestoreError(rel, error2 instanceof Error ? error2.message : String(error2));
|
|
3363
3021
|
}
|
|
3364
3022
|
}
|
|
3365
3023
|
for (const [rel, content3] of Object.entries(bundle.files)) {
|
|
3366
|
-
const file =
|
|
3367
|
-
|
|
3368
|
-
|
|
3024
|
+
const file = path2.join(dir, rel);
|
|
3025
|
+
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
3026
|
+
fs2.writeFileSync(file, content3);
|
|
3369
3027
|
}
|
|
3370
3028
|
for (const [rel, b64] of Object.entries(bundle.binaryFiles ?? {})) {
|
|
3371
|
-
const file =
|
|
3372
|
-
|
|
3373
|
-
|
|
3029
|
+
const file = path2.join(dir, rel);
|
|
3030
|
+
fs2.mkdirSync(path2.dirname(file), { recursive: true });
|
|
3031
|
+
fs2.writeFileSync(file, Buffer.from(b64, "base64"));
|
|
3374
3032
|
}
|
|
3375
3033
|
const task = bundle.files["TASK.md"];
|
|
3376
3034
|
if (!task) throw new Error("bundle \u7F3A TASK.md\uFF08\u88C5\u914D\u5668\u5951\u7EA6\uFF09");
|
|
3377
3035
|
return task;
|
|
3378
3036
|
}
|
|
3379
|
-
var
|
|
3037
|
+
var fs2, path2, import_node_crypto3, BundleRestoreError;
|
|
3380
3038
|
var init_materialize_bundle = __esm({
|
|
3381
3039
|
"../adapters/src/_core/materialize-bundle.ts"() {
|
|
3382
3040
|
"use strict";
|
|
3383
|
-
|
|
3384
|
-
|
|
3041
|
+
fs2 = __toESM(require("node:fs"), 1);
|
|
3042
|
+
path2 = __toESM(require("node:path"), 1);
|
|
3385
3043
|
import_node_crypto3 = require("node:crypto");
|
|
3386
3044
|
BundleRestoreError = class extends Error {
|
|
3387
3045
|
constructor(filePath, detail) {
|
|
@@ -3625,7 +3283,7 @@ function containerEnv(job, extraEarly, extraLate) {
|
|
|
3625
3283
|
...extraLate
|
|
3626
3284
|
};
|
|
3627
3285
|
if (job.wrapperPaths?.length) {
|
|
3628
|
-
env["PATH"] = `${job.wrapperPaths.map((p2) =>
|
|
3286
|
+
env["PATH"] = `${job.wrapperPaths.map((p2) => path4.dirname(p2)).join(path4.delimiter)}${path4.delimiter}${CONTAINER_DEFAULT_PATH}`;
|
|
3629
3287
|
}
|
|
3630
3288
|
env["OASIS_SERVER"] = job.server.url;
|
|
3631
3289
|
env["OASIS_TOKEN"] = job.actorToken;
|
|
@@ -3634,7 +3292,7 @@ function containerEnv(job, extraEarly, extraLate) {
|
|
|
3634
3292
|
}
|
|
3635
3293
|
function commonArgs(p2, name) {
|
|
3636
3294
|
const ee = p2.executionEnv;
|
|
3637
|
-
const binMount = `/usr/local/bin/${p2.binName ??
|
|
3295
|
+
const binMount = `/usr/local/bin/${p2.binName ?? path4.basename(p2.binHostPath)}`;
|
|
3638
3296
|
const args = [
|
|
3639
3297
|
// 不用 --userns=keep-id:rootless 默认映射已是「容器内 root = 宿主调用用户」,bind 挂载上的
|
|
3640
3298
|
// 文件属主内外天然一致(agent 写的文件宿主侧可读可删);keep-id 反而在部分主机的 overlay
|
|
@@ -3653,7 +3311,7 @@ function commonArgs(p2, name) {
|
|
|
3653
3311
|
`${p2.homeHostDir}:${CONTAINER_HOME}`
|
|
3654
3312
|
];
|
|
3655
3313
|
for (const dir of /* @__PURE__ */ new Set([
|
|
3656
|
-
...(p2.job.wrapperPaths ?? []).map((w2) =>
|
|
3314
|
+
...(p2.job.wrapperPaths ?? []).map((w2) => path4.dirname(w2)),
|
|
3657
3315
|
...p2.extraRoBindDirs ?? []
|
|
3658
3316
|
])) {
|
|
3659
3317
|
args.push("-v", `${dir}:${dir}:ro`);
|
|
@@ -3677,7 +3335,7 @@ function droppedEnvNames(env) {
|
|
|
3677
3335
|
}
|
|
3678
3336
|
function wrapForContainer(p2) {
|
|
3679
3337
|
const ee = p2.executionEnv;
|
|
3680
|
-
const binInContainer = p2.binPackageDir ? p2.binHostPath : `/usr/local/bin/${p2.binName ??
|
|
3338
|
+
const binInContainer = p2.binPackageDir ? p2.binHostPath : `/usr/local/bin/${p2.binName ?? path4.basename(p2.binHostPath)}`;
|
|
3681
3339
|
const eeHash = executionEnvHash(p2);
|
|
3682
3340
|
if (ee.persist && p2.job.workdirKey) {
|
|
3683
3341
|
const name2 = persistContainerName(p2.job.workdirKey);
|
|
@@ -3704,8 +3362,8 @@ function wrapForContainer(p2) {
|
|
|
3704
3362
|
droppedEnvNames: droppedEnvNames(p2.env)
|
|
3705
3363
|
};
|
|
3706
3364
|
}
|
|
3707
|
-
const name = ephemeralContainerName(p2.job,
|
|
3708
|
-
const cidFile =
|
|
3365
|
+
const name = ephemeralContainerName(p2.job, path4.basename(p2.cwd));
|
|
3366
|
+
const cidFile = path4.join(p2.cwd, ".oasis-container-cid");
|
|
3709
3367
|
return {
|
|
3710
3368
|
bin: "podman",
|
|
3711
3369
|
args: [
|
|
@@ -3735,12 +3393,12 @@ function wrapForContainer(p2) {
|
|
|
3735
3393
|
function killContainerArgs(containerName) {
|
|
3736
3394
|
return ["kill", containerName];
|
|
3737
3395
|
}
|
|
3738
|
-
var import_node_crypto5,
|
|
3396
|
+
var import_node_crypto5, path4, CONTAINER_DEFAULT_PATH, CONTAINER_HOME, EE_HASH_LABEL;
|
|
3739
3397
|
var init_container_wrap = __esm({
|
|
3740
3398
|
"../adapters/src/_core/container-wrap.ts"() {
|
|
3741
3399
|
"use strict";
|
|
3742
3400
|
import_node_crypto5 = require("node:crypto");
|
|
3743
|
-
|
|
3401
|
+
path4 = __toESM(require("node:path"), 1);
|
|
3744
3402
|
init_session_paths();
|
|
3745
3403
|
CONTAINER_DEFAULT_PATH = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
|
|
3746
3404
|
CONTAINER_HOME = "/oasis-home";
|
|
@@ -3752,7 +3410,7 @@ var init_container_wrap = __esm({
|
|
|
3752
3410
|
function podmanAvailable() {
|
|
3753
3411
|
if (podmanProbe === void 0) {
|
|
3754
3412
|
try {
|
|
3755
|
-
podmanProbe = (0,
|
|
3413
|
+
podmanProbe = (0, import_node_child_process.spawnSync)(PODMAN, ["--version"], { timeout: 1e4 }).status === 0;
|
|
3756
3414
|
} catch {
|
|
3757
3415
|
podmanProbe = false;
|
|
3758
3416
|
}
|
|
@@ -3760,19 +3418,19 @@ function podmanAvailable() {
|
|
|
3760
3418
|
return podmanProbe;
|
|
3761
3419
|
}
|
|
3762
3420
|
function resolveBinHostPath(bin) {
|
|
3763
|
-
if (bin.includes(
|
|
3421
|
+
if (bin.includes(path5.sep)) {
|
|
3764
3422
|
try {
|
|
3765
|
-
return
|
|
3423
|
+
return fs4.realpathSync(path5.resolve(bin));
|
|
3766
3424
|
} catch {
|
|
3767
|
-
return
|
|
3425
|
+
return path5.resolve(bin);
|
|
3768
3426
|
}
|
|
3769
3427
|
}
|
|
3770
|
-
for (const dir of (process.env["PATH"] ?? "").split(
|
|
3428
|
+
for (const dir of (process.env["PATH"] ?? "").split(path5.delimiter)) {
|
|
3771
3429
|
if (!dir) continue;
|
|
3772
|
-
const candidate =
|
|
3430
|
+
const candidate = path5.join(dir, bin);
|
|
3773
3431
|
try {
|
|
3774
|
-
|
|
3775
|
-
return
|
|
3432
|
+
fs4.accessSync(candidate, fs4.constants.X_OK);
|
|
3433
|
+
return fs4.realpathSync(candidate);
|
|
3776
3434
|
} catch {
|
|
3777
3435
|
}
|
|
3778
3436
|
}
|
|
@@ -3780,25 +3438,25 @@ function resolveBinHostPath(bin) {
|
|
|
3780
3438
|
}
|
|
3781
3439
|
function resolveBinPackageDir(binHostPath) {
|
|
3782
3440
|
if (!/\.(js|mjs|cjs)$/i.test(binHostPath)) return null;
|
|
3783
|
-
let dir =
|
|
3441
|
+
let dir = path5.dirname(binHostPath);
|
|
3784
3442
|
for (let i = 0; i < 8; i++) {
|
|
3785
|
-
if (
|
|
3786
|
-
if (dir === "/" || dir === os2.tmpdir() || dir.split(
|
|
3443
|
+
if (fs4.existsSync(path5.join(dir, "package.json"))) {
|
|
3444
|
+
if (dir === "/" || dir === os2.tmpdir() || dir.split(path5.sep).length <= 2) return null;
|
|
3787
3445
|
return dir;
|
|
3788
3446
|
}
|
|
3789
|
-
const parent =
|
|
3447
|
+
const parent = path5.dirname(dir);
|
|
3790
3448
|
if (parent === dir) break;
|
|
3791
3449
|
dir = parent;
|
|
3792
3450
|
}
|
|
3793
3451
|
return null;
|
|
3794
3452
|
}
|
|
3795
3453
|
function containerHomeHostDir(workRoot) {
|
|
3796
|
-
const dir =
|
|
3797
|
-
|
|
3454
|
+
const dir = path5.join(resolveWorkRoot(workRoot), "container-home");
|
|
3455
|
+
fs4.mkdirSync(dir, { recursive: true });
|
|
3798
3456
|
return dir;
|
|
3799
3457
|
}
|
|
3800
3458
|
async function ensureImage(image) {
|
|
3801
|
-
const exists = (0,
|
|
3459
|
+
const exists = (0, import_node_child_process.spawnSync)(PODMAN, ["image", "exists", image], { timeout: 15e3 }).status === 0;
|
|
3802
3460
|
if (!exists) {
|
|
3803
3461
|
try {
|
|
3804
3462
|
await execFileP(PODMAN, ["pull", image], { timeout: 6e5 });
|
|
@@ -3816,7 +3474,7 @@ async function ensureImage(image) {
|
|
|
3816
3474
|
async function ensurePersistContainer(plan) {
|
|
3817
3475
|
if (plan.mode !== "exec" || !plan.ensureArgs) return;
|
|
3818
3476
|
const name = plan.containerName;
|
|
3819
|
-
const exists = (0,
|
|
3477
|
+
const exists = (0, import_node_child_process.spawnSync)(PODMAN, ["container", "exists", name], { timeout: 15e3 }).status === 0;
|
|
3820
3478
|
if (exists) {
|
|
3821
3479
|
const { stdout: label2 } = await execFileP(
|
|
3822
3480
|
PODMAN,
|
|
@@ -3835,7 +3493,7 @@ async function ensurePersistContainer(plan) {
|
|
|
3835
3493
|
}
|
|
3836
3494
|
function killContainerBestEffort(containerName, _mode) {
|
|
3837
3495
|
try {
|
|
3838
|
-
(0,
|
|
3496
|
+
(0, import_node_child_process.execFile)(PODMAN, killContainerArgs(containerName), { timeout: 3e4 }, () => {
|
|
3839
3497
|
});
|
|
3840
3498
|
} catch {
|
|
3841
3499
|
}
|
|
@@ -3856,8 +3514,8 @@ async function reapEphemeralContainers() {
|
|
|
3856
3514
|
}
|
|
3857
3515
|
function removePersistContainerForDir(workdir) {
|
|
3858
3516
|
if (!podmanAvailable()) return;
|
|
3859
|
-
const name = `oasis-wd-${
|
|
3860
|
-
(0,
|
|
3517
|
+
const name = `oasis-wd-${path5.basename(workdir)}`;
|
|
3518
|
+
(0, import_node_child_process.execFile)(PODMAN, ["rm", "-f", name], { timeout: 3e4 }, () => {
|
|
3861
3519
|
});
|
|
3862
3520
|
}
|
|
3863
3521
|
async function maybeContainerize(params) {
|
|
@@ -3870,12 +3528,12 @@ async function maybeContainerize(params) {
|
|
|
3870
3528
|
const env = containerEnv(params.job, params.extraEnvEarly, params.extraEnvLate);
|
|
3871
3529
|
const extraRoBindDirs = [...new Set((params.job.wrapperPaths ?? []).flatMap((w2) => {
|
|
3872
3530
|
try {
|
|
3873
|
-
const target =
|
|
3874
|
-
const targetDir =
|
|
3875
|
-
const baseSibling =
|
|
3531
|
+
const target = fs4.realpathSync(w2);
|
|
3532
|
+
const targetDir = path5.dirname(target);
|
|
3533
|
+
const baseSibling = path5.join(path5.dirname(targetDir), "_base");
|
|
3876
3534
|
const dirs = [targetDir];
|
|
3877
|
-
if (
|
|
3878
|
-
return dirs.filter((d) => d !== "/" && d !== os2.tmpdir() && d.split(
|
|
3535
|
+
if (fs4.existsSync(baseSibling)) dirs.push(baseSibling);
|
|
3536
|
+
return dirs.filter((d) => d !== "/" && d !== os2.tmpdir() && d.split(path5.sep).length > 2);
|
|
3879
3537
|
} catch {
|
|
3880
3538
|
return [];
|
|
3881
3539
|
}
|
|
@@ -3884,7 +3542,7 @@ async function maybeContainerize(params) {
|
|
|
3884
3542
|
const binPackageDir = resolveBinPackageDir(binHostPath);
|
|
3885
3543
|
const plan = wrapForContainer({
|
|
3886
3544
|
binHostPath,
|
|
3887
|
-
binName:
|
|
3545
|
+
binName: path5.basename(params.bin),
|
|
3888
3546
|
// realpath 前的名字("claude")——argv[0] 语义要保住
|
|
3889
3547
|
...binPackageDir ? { binPackageDir } : {},
|
|
3890
3548
|
args: params.args,
|
|
@@ -3899,22 +3557,22 @@ async function maybeContainerize(params) {
|
|
|
3899
3557
|
if (plan.droppedEnvNames.length > 0) {
|
|
3900
3558
|
console.warn(`[container] \u8FD9\u4E9B\u53D8\u91CF\u540D\u653E\u4E0D\u8FDB\u5BB9\u5668\uFF08\u5F00\u5934\u7A7A\u767D / \u542B = / \u7A7A\u5B57\u7B26\uFF09\uFF0C\u672C\u8F6E\u672A\u6CE8\u5165\uFF1A${plan.droppedEnvNames.map((k2) => JSON.stringify(k2)).join(", ")}`);
|
|
3901
3559
|
}
|
|
3902
|
-
if (plan.cidFile)
|
|
3560
|
+
if (plan.cidFile) fs4.rmSync(plan.cidFile, { force: true });
|
|
3903
3561
|
await ensurePersistContainer(plan);
|
|
3904
3562
|
return { bin: plan.bin, args: plan.args, env, containerName: plan.containerName, mode: plan.mode, imageDigest };
|
|
3905
3563
|
}
|
|
3906
|
-
var
|
|
3564
|
+
var import_node_child_process, fs4, os2, path5, import_node_util, execFileP, PODMAN, podmanProbe;
|
|
3907
3565
|
var init_container_runtime = __esm({
|
|
3908
3566
|
"../adapters/src/_core/container-runtime.ts"() {
|
|
3909
3567
|
"use strict";
|
|
3910
|
-
|
|
3911
|
-
|
|
3568
|
+
import_node_child_process = require("node:child_process");
|
|
3569
|
+
fs4 = __toESM(require("node:fs"), 1);
|
|
3912
3570
|
os2 = __toESM(require("node:os"), 1);
|
|
3913
|
-
|
|
3571
|
+
path5 = __toESM(require("node:path"), 1);
|
|
3914
3572
|
import_node_util = require("node:util");
|
|
3915
3573
|
init_container_wrap();
|
|
3916
3574
|
init_session_paths();
|
|
3917
|
-
execFileP = (0, import_node_util.promisify)(
|
|
3575
|
+
execFileP = (0, import_node_util.promisify)(import_node_child_process.execFile);
|
|
3918
3576
|
PODMAN = "podman";
|
|
3919
3577
|
}
|
|
3920
3578
|
});
|
|
@@ -4118,16 +3776,16 @@ var init_model_report = __esm({
|
|
|
4118
3776
|
|
|
4119
3777
|
// ../adapters/src/_core/transcript.ts
|
|
4120
3778
|
function openTranscript(file) {
|
|
4121
|
-
const out =
|
|
3779
|
+
const out = fs5.createWriteStream(file);
|
|
4122
3780
|
out.on("error", () => {
|
|
4123
3781
|
});
|
|
4124
3782
|
return out;
|
|
4125
3783
|
}
|
|
4126
|
-
var
|
|
3784
|
+
var fs5;
|
|
4127
3785
|
var init_transcript = __esm({
|
|
4128
3786
|
"../adapters/src/_core/transcript.ts"() {
|
|
4129
3787
|
"use strict";
|
|
4130
|
-
|
|
3788
|
+
fs5 = __toESM(require("node:fs"), 1);
|
|
4131
3789
|
}
|
|
4132
3790
|
});
|
|
4133
3791
|
|
|
@@ -4235,10 +3893,10 @@ function byModelOf(calls) {
|
|
|
4235
3893
|
}
|
|
4236
3894
|
function readSubagentTranscriptCalls(outputFile) {
|
|
4237
3895
|
try {
|
|
4238
|
-
const stat4 =
|
|
3896
|
+
const stat4 = fs6.statSync(outputFile);
|
|
4239
3897
|
if (!stat4.isFile() || stat4.size > SUBAGENT_TRANSCRIPT_MAX_BYTES) return void 0;
|
|
4240
3898
|
const calls = /* @__PURE__ */ new Map();
|
|
4241
|
-
for (const line2 of
|
|
3899
|
+
for (const line2 of fs6.readFileSync(outputFile, "utf8").split("\n")) {
|
|
4242
3900
|
if (!line2.includes('"assistant"') || !line2.includes('"usage"')) continue;
|
|
4243
3901
|
let parsed;
|
|
4244
3902
|
try {
|
|
@@ -4493,14 +4151,14 @@ function newClaudeUsageAcc() {
|
|
|
4493
4151
|
};
|
|
4494
4152
|
}
|
|
4495
4153
|
function findClaudeSessionFile(configDir, cwd, runtimeSessionId) {
|
|
4496
|
-
const root =
|
|
4154
|
+
const root = path6.join(configDir, "projects");
|
|
4497
4155
|
const name = `${runtimeSessionId}.jsonl`;
|
|
4498
|
-
const direct =
|
|
4499
|
-
if (
|
|
4156
|
+
const direct = path6.join(root, cwd.replace(/[^a-zA-Z0-9]/g, "-"), name);
|
|
4157
|
+
if (fs6.existsSync(direct)) return direct;
|
|
4500
4158
|
try {
|
|
4501
|
-
for (const slug6 of
|
|
4502
|
-
const candidate =
|
|
4503
|
-
if (
|
|
4159
|
+
for (const slug6 of fs6.readdirSync(root)) {
|
|
4160
|
+
const candidate = path6.join(root, slug6, name);
|
|
4161
|
+
if (fs6.existsSync(candidate)) return candidate;
|
|
4504
4162
|
}
|
|
4505
4163
|
} catch {
|
|
4506
4164
|
}
|
|
@@ -4508,15 +4166,15 @@ function findClaudeSessionFile(configDir, cwd, runtimeSessionId) {
|
|
|
4508
4166
|
}
|
|
4509
4167
|
function readClaudeRestoredCost(sessionFile) {
|
|
4510
4168
|
try {
|
|
4511
|
-
const stat4 =
|
|
4169
|
+
const stat4 = fs6.statSync(sessionFile);
|
|
4512
4170
|
if (!stat4.isFile() || stat4.size === 0) return null;
|
|
4513
4171
|
const length = Math.min(stat4.size, RESTORED_COST_TAIL_BYTES);
|
|
4514
4172
|
const buf = Buffer.alloc(length);
|
|
4515
|
-
const fd =
|
|
4173
|
+
const fd = fs6.openSync(sessionFile, "r");
|
|
4516
4174
|
try {
|
|
4517
|
-
|
|
4175
|
+
fs6.readSync(fd, buf, 0, length, stat4.size - length);
|
|
4518
4176
|
} finally {
|
|
4519
|
-
|
|
4177
|
+
fs6.closeSync(fd);
|
|
4520
4178
|
}
|
|
4521
4179
|
const lines = buf.toString("utf8").split("\n");
|
|
4522
4180
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
@@ -4740,15 +4398,15 @@ function classifyExit(result) {
|
|
|
4740
4398
|
if (status === 429 || status === 529) return "rate-limit";
|
|
4741
4399
|
return "error";
|
|
4742
4400
|
}
|
|
4743
|
-
var
|
|
4401
|
+
var import_node_child_process2, import_node_crypto6, fs6, os3, path6, readline, CLAUDE_BLOCKED_FLAGS, SUBAGENT_TRANSCRIPT_MAX_BYTES, SUBAGENT_TERMINAL, RESTORED_COST_TAIL_BYTES, ONE_SHOT_UNSAFE_TOOLS, ClaudeCodeAdapter;
|
|
4744
4402
|
var init_claude_code = __esm({
|
|
4745
4403
|
"../adapters/src/claude-code/index.ts"() {
|
|
4746
4404
|
"use strict";
|
|
4747
|
-
|
|
4405
|
+
import_node_child_process2 = require("node:child_process");
|
|
4748
4406
|
import_node_crypto6 = require("node:crypto");
|
|
4749
|
-
|
|
4407
|
+
fs6 = __toESM(require("node:fs"), 1);
|
|
4750
4408
|
os3 = __toESM(require("node:os"), 1);
|
|
4751
|
-
|
|
4409
|
+
path6 = __toESM(require("node:path"), 1);
|
|
4752
4410
|
readline = __toESM(require("node:readline"), 1);
|
|
4753
4411
|
init_sync_skills();
|
|
4754
4412
|
init_materialize_bundle();
|
|
@@ -4852,7 +4510,7 @@ var init_claude_code = __esm({
|
|
|
4852
4510
|
runtimeKind: "claude"
|
|
4853
4511
|
}
|
|
4854
4512
|
});
|
|
4855
|
-
|
|
4513
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
4856
4514
|
await runSyncSkills(this.opts.syncSkills, {
|
|
4857
4515
|
actorId: job.actor,
|
|
4858
4516
|
actorToken: job.actorToken,
|
|
@@ -4893,7 +4551,7 @@ var init_claude_code = __esm({
|
|
|
4893
4551
|
{ runtime: "claude-code", actor: job.actor, ...job.dispatchId ? { dispatchId: job.dispatchId } : {} }
|
|
4894
4552
|
)
|
|
4895
4553
|
];
|
|
4896
|
-
const claudeConfigDir = job.env?.["CLAUDE_CONFIG_DIR"] || this.opts.env?.["CLAUDE_CONFIG_DIR"] || process.env["CLAUDE_CONFIG_DIR"] ||
|
|
4554
|
+
const claudeConfigDir = job.env?.["CLAUDE_CONFIG_DIR"] || this.opts.env?.["CLAUDE_CONFIG_DIR"] || process.env["CLAUDE_CONFIG_DIR"] || path6.join(os3.homedir(), ".claude");
|
|
4897
4555
|
const resumedSessionFile = job.runtimeSessionId && job.resumeRuntimeSession ? findClaudeSessionFile(claudeConfigDir, dir, job.runtimeSessionId) : void 0;
|
|
4898
4556
|
const restoredCost = resumedSessionFile ? readClaudeRestoredCost(resumedSessionFile) : null;
|
|
4899
4557
|
const otelEnv = this.resolveOtelEnv(job, id);
|
|
@@ -4911,11 +4569,11 @@ var init_claude_code = __esm({
|
|
|
4911
4569
|
...otelEnv
|
|
4912
4570
|
}
|
|
4913
4571
|
});
|
|
4914
|
-
const child = containerized ? (0,
|
|
4572
|
+
const child = containerized ? (0, import_node_child_process2.spawn)(containerized.bin, containerized.args, {
|
|
4915
4573
|
cwd: dir,
|
|
4916
4574
|
env: scrubLeakyEnv(process.env),
|
|
4917
4575
|
stdio: ["pipe", "pipe", "pipe"]
|
|
4918
|
-
}) : (0,
|
|
4576
|
+
}) : (0, import_node_child_process2.spawn)(this.opts.claudeBin ?? "claude", args, {
|
|
4919
4577
|
cwd: dir,
|
|
4920
4578
|
env: {
|
|
4921
4579
|
// 凭证泄漏防护:剔除 pnpm/npm 脚本注入的变量——npm_lifecycle_script 等会把 serve 的启动命令
|
|
@@ -4926,7 +4584,7 @@ var init_claude_code = __esm({
|
|
|
4926
4584
|
...job.env,
|
|
4927
4585
|
// BUG-4 缓冲:抬高单响应输出 token 上限(临时缓冲,根治靠分解)
|
|
4928
4586
|
...this.opts.maxOutputTokens ? { CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(this.opts.maxOutputTokens) } : {},
|
|
4929
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
4587
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path6.dirname(p2)).join(path6.delimiter)}${path6.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
4930
4588
|
OASIS_SERVER: job.server.url,
|
|
4931
4589
|
OASIS_TOKEN: job.actorToken,
|
|
4932
4590
|
// OTel 遥测(默认关;resolveOtelEnv 决定开不开,runId 进 resource 属性自然归位到本次 run)。
|
|
@@ -5006,7 +4664,7 @@ var init_claude_code = __esm({
|
|
|
5006
4664
|
if (promptViaStdin) child.stdin.write(prompt2);
|
|
5007
4665
|
child.stdin.end();
|
|
5008
4666
|
}
|
|
5009
|
-
let transcriptRef =
|
|
4667
|
+
let transcriptRef = path6.join(dir, "transcript.txt");
|
|
5010
4668
|
const out = openTranscript(transcriptRef);
|
|
5011
4669
|
diag = (event, extra) => {
|
|
5012
4670
|
try {
|
|
@@ -5147,14 +4805,14 @@ var init_claude_code = __esm({
|
|
|
5147
4805
|
touchMetaExit(dir, { at: (/* @__PURE__ */ new Date()).toISOString(), ...reason ? { reason } : {}, runId: id });
|
|
5148
4806
|
if (this.opts.cleanupWorkdir && isOneShot) {
|
|
5149
4807
|
try {
|
|
5150
|
-
const keepDir =
|
|
5151
|
-
|
|
5152
|
-
const kept =
|
|
4808
|
+
const keepDir = path6.join(resolveWorkRoot(this.opts.workRoot), "oasis-transcripts");
|
|
4809
|
+
fs6.mkdirSync(keepDir, { recursive: true });
|
|
4810
|
+
const kept = path6.join(keepDir, `${id}.txt`);
|
|
5153
4811
|
const src = transcriptRef;
|
|
5154
4812
|
out.end(() => {
|
|
5155
4813
|
try {
|
|
5156
|
-
|
|
5157
|
-
|
|
4814
|
+
fs6.renameSync(src, kept);
|
|
4815
|
+
fs6.rmSync(dir, { recursive: true, force: true });
|
|
5158
4816
|
} catch {
|
|
5159
4817
|
}
|
|
5160
4818
|
});
|
|
@@ -5500,7 +5158,7 @@ var init_resilient = __esm({
|
|
|
5500
5158
|
|
|
5501
5159
|
// ../adapters/src/_core/skill-cache.ts
|
|
5502
5160
|
function defaultCacheRoot() {
|
|
5503
|
-
return
|
|
5161
|
+
return path7.join(os4.homedir(), ".oasis", "skill-cache");
|
|
5504
5162
|
}
|
|
5505
5163
|
function sessionSkillsSubdir(runtimeKind) {
|
|
5506
5164
|
switch (runtimeKind) {
|
|
@@ -5521,7 +5179,7 @@ async function syncActorSkills(opts) {
|
|
|
5521
5179
|
});
|
|
5522
5180
|
const now = opts.now ?? (() => /* @__PURE__ */ new Date());
|
|
5523
5181
|
const actorDir = pathForActor(cacheRoot, opts.actorId);
|
|
5524
|
-
const manifestPath =
|
|
5182
|
+
const manifestPath = path7.join(actorDir, "manifest.json");
|
|
5525
5183
|
await fsp.mkdir(actorDir, { recursive: true, mode: 493 });
|
|
5526
5184
|
const release = await acquireLock(cacheRoot, opts.actorId, now, log3);
|
|
5527
5185
|
try {
|
|
@@ -5542,7 +5200,7 @@ async function syncActorSkills(opts) {
|
|
|
5542
5200
|
for (const [id, entry] of Object.entries(manifest.skills)) {
|
|
5543
5201
|
if (cloudIds.has(id)) continue;
|
|
5544
5202
|
try {
|
|
5545
|
-
await fsp.rm(
|
|
5203
|
+
await fsp.rm(path7.join(actorDir, entry.dir), { recursive: true, force: true });
|
|
5546
5204
|
} catch (err) {
|
|
5547
5205
|
log3("warn", `\u5220\u9664\u5B64\u513F\u6280\u80FD\u76EE\u5F55\u5931\u8D25 ${entry.dir}`, err);
|
|
5548
5206
|
}
|
|
@@ -5554,7 +5212,7 @@ async function syncActorSkills(opts) {
|
|
|
5554
5212
|
const forceClearForSession = /* @__PURE__ */ new Set();
|
|
5555
5213
|
for (const cloud of cloudMetadata) {
|
|
5556
5214
|
const variantSlug = variantSlugFor(cloud.contentHash);
|
|
5557
|
-
const variantDir =
|
|
5215
|
+
const variantDir = path7.join(actorDir, cloud.dir, variantSlug);
|
|
5558
5216
|
const cached3 = manifest.skills[cloud.id];
|
|
5559
5217
|
const alreadyMaterialized = await dirLooksValid(variantDir, cloud.fileList);
|
|
5560
5218
|
let actualFiles = null;
|
|
@@ -5576,7 +5234,7 @@ async function syncActorSkills(opts) {
|
|
|
5576
5234
|
fileList: cloud.fileList
|
|
5577
5235
|
};
|
|
5578
5236
|
if (cached3 && cached3.dir !== cloud.dir) {
|
|
5579
|
-
await fsp.rm(
|
|
5237
|
+
await fsp.rm(path7.join(actorDir, cached3.dir), { recursive: true, force: true }).catch(() => {
|
|
5580
5238
|
});
|
|
5581
5239
|
}
|
|
5582
5240
|
desiredForSession.set(cloud.dir, { variantDir, variantSlug });
|
|
@@ -5638,7 +5296,7 @@ async function syncActorSkills(opts) {
|
|
|
5638
5296
|
fileList: cloud.fileList
|
|
5639
5297
|
};
|
|
5640
5298
|
if (cached3 && cached3.dir !== cloud.dir) {
|
|
5641
|
-
await fsp.rm(
|
|
5299
|
+
await fsp.rm(path7.join(actorDir, cached3.dir), { recursive: true, force: true }).catch(() => {
|
|
5642
5300
|
});
|
|
5643
5301
|
}
|
|
5644
5302
|
desiredForSession.set(cloud.dir, { variantDir, variantSlug });
|
|
@@ -5668,10 +5326,10 @@ async function syncActorSkills(opts) {
|
|
|
5668
5326
|
}
|
|
5669
5327
|
}
|
|
5670
5328
|
function pathForActor(cacheRoot, actorId) {
|
|
5671
|
-
return
|
|
5329
|
+
return path7.join(cacheRoot, "actors", encodeURIComponent(actorId));
|
|
5672
5330
|
}
|
|
5673
5331
|
function lockPathFor(cacheRoot, actorId) {
|
|
5674
|
-
return
|
|
5332
|
+
return path7.join(cacheRoot, "locks", `${encodeURIComponent(actorId)}.lock`);
|
|
5675
5333
|
}
|
|
5676
5334
|
function aggregateSkillContentHash(files) {
|
|
5677
5335
|
const sorted = [...files].sort((a, b2) => a.path.localeCompare(b2.path));
|
|
@@ -5693,7 +5351,7 @@ function variantSlugFor(contentHash) {
|
|
|
5693
5351
|
}
|
|
5694
5352
|
async function acquireLock(cacheRoot, actorId, now, log3) {
|
|
5695
5353
|
const lockPath = lockPathFor(cacheRoot, actorId);
|
|
5696
|
-
await fsp.mkdir(
|
|
5354
|
+
await fsp.mkdir(path7.dirname(lockPath), { recursive: true, mode: 493 });
|
|
5697
5355
|
const started = now().getTime();
|
|
5698
5356
|
while (true) {
|
|
5699
5357
|
try {
|
|
@@ -5759,28 +5417,28 @@ async function readManifest(manifestPath, actorId, log3) {
|
|
|
5759
5417
|
};
|
|
5760
5418
|
}
|
|
5761
5419
|
async function writeManifest(manifestPath, manifest) {
|
|
5762
|
-
const dir =
|
|
5420
|
+
const dir = path7.dirname(manifestPath);
|
|
5763
5421
|
await fsp.mkdir(dir, { recursive: true });
|
|
5764
5422
|
const tmp = `${manifestPath}.${process.pid}.${Date.now()}.tmp`;
|
|
5765
5423
|
await fsp.writeFile(tmp, JSON.stringify(manifest, null, 2), { mode: 420 });
|
|
5766
5424
|
await fsp.rename(tmp, manifestPath);
|
|
5767
5425
|
}
|
|
5768
5426
|
async function materializeVariantDir(actorDir, targetDir, variantSlug, files) {
|
|
5769
|
-
const parentPath =
|
|
5427
|
+
const parentPath = path7.join(actorDir, targetDir);
|
|
5770
5428
|
await fsp.mkdir(parentPath, { recursive: true, mode: 493 });
|
|
5771
|
-
const targetPath =
|
|
5772
|
-
const tmpPath =
|
|
5773
|
-
const oldBackup =
|
|
5429
|
+
const targetPath = path7.join(parentPath, variantSlug);
|
|
5430
|
+
const tmpPath = path7.join(parentPath, `${variantSlug}.new.${process.pid}.${Date.now()}`);
|
|
5431
|
+
const oldBackup = path7.join(parentPath, `${variantSlug}.old.${process.pid}.${Date.now()}`);
|
|
5774
5432
|
await fsp.rm(tmpPath, { recursive: true, force: true });
|
|
5775
5433
|
await fsp.mkdir(tmpPath, { recursive: true, mode: 493 });
|
|
5776
5434
|
for (const f2 of files) {
|
|
5777
5435
|
if (!f2.content) continue;
|
|
5778
|
-
const dest =
|
|
5779
|
-
const rel =
|
|
5780
|
-
if (rel.startsWith("..") ||
|
|
5436
|
+
const dest = path7.join(tmpPath, f2.path);
|
|
5437
|
+
const rel = path7.relative(tmpPath, dest);
|
|
5438
|
+
if (rel.startsWith("..") || path7.isAbsolute(rel)) {
|
|
5781
5439
|
throw new Error(`SkillFile.path \u4E0D\u5408\u6CD5: ${f2.path}`);
|
|
5782
5440
|
}
|
|
5783
|
-
await fsp.mkdir(
|
|
5441
|
+
await fsp.mkdir(path7.dirname(dest), { recursive: true });
|
|
5784
5442
|
await fsp.writeFile(dest, f2.content, { mode: 420 });
|
|
5785
5443
|
}
|
|
5786
5444
|
let hadOld = false;
|
|
@@ -5798,7 +5456,7 @@ async function dirLooksValid(dir, expectFileList) {
|
|
|
5798
5456
|
if (expectFileList.length === 0) return false;
|
|
5799
5457
|
try {
|
|
5800
5458
|
for (const rel of expectFileList) {
|
|
5801
|
-
await fsp.stat(
|
|
5459
|
+
await fsp.stat(path7.join(dir, rel));
|
|
5802
5460
|
}
|
|
5803
5461
|
return true;
|
|
5804
5462
|
} catch {
|
|
@@ -5810,7 +5468,7 @@ async function hashMaterializedDir(dir, fileList) {
|
|
|
5810
5468
|
try {
|
|
5811
5469
|
const files = [];
|
|
5812
5470
|
for (const rel of fileList) {
|
|
5813
|
-
const content3 = await fsp.readFile(
|
|
5471
|
+
const content3 = await fsp.readFile(path7.join(dir, rel), "utf8");
|
|
5814
5472
|
files.push({ path: rel, content: content3 });
|
|
5815
5473
|
}
|
|
5816
5474
|
return aggregateSkillContentHash(files);
|
|
@@ -5822,10 +5480,10 @@ async function listMaterializedFiles(dir) {
|
|
|
5822
5480
|
try {
|
|
5823
5481
|
const out = [];
|
|
5824
5482
|
const walk = async (sub) => {
|
|
5825
|
-
const abs = sub ?
|
|
5483
|
+
const abs = sub ? path7.join(dir, sub) : dir;
|
|
5826
5484
|
const entries = await fsp.readdir(abs, { withFileTypes: true });
|
|
5827
5485
|
for (const e of entries) {
|
|
5828
|
-
const rel = sub ?
|
|
5486
|
+
const rel = sub ? path7.join(sub, e.name) : e.name;
|
|
5829
5487
|
if (e.isDirectory()) {
|
|
5830
5488
|
await walk(rel);
|
|
5831
5489
|
} else {
|
|
@@ -5841,14 +5499,14 @@ async function listMaterializedFiles(dir) {
|
|
|
5841
5499
|
}
|
|
5842
5500
|
async function syncSessionSymlinks(sessionDir, runtimeKind, desired, pending, forceClear, log3) {
|
|
5843
5501
|
const subdir = sessionSkillsSubdir(runtimeKind);
|
|
5844
|
-
const skillsDir =
|
|
5502
|
+
const skillsDir = path7.join(sessionDir, subdir);
|
|
5845
5503
|
await fsp.mkdir(skillsDir, { recursive: true, mode: 493 });
|
|
5846
5504
|
for (const [name, { variantDir }] of desired) {
|
|
5847
|
-
const link =
|
|
5505
|
+
const link = path7.join(skillsDir, name);
|
|
5848
5506
|
let ok3 = false;
|
|
5849
5507
|
try {
|
|
5850
5508
|
const current = await fsp.readlink(link);
|
|
5851
|
-
ok3 =
|
|
5509
|
+
ok3 = path7.resolve(skillsDir, current) === variantDir;
|
|
5852
5510
|
} catch {
|
|
5853
5511
|
}
|
|
5854
5512
|
if (!ok3) {
|
|
@@ -5875,22 +5533,22 @@ async function syncSessionSymlinks(sessionDir, runtimeKind, desired, pending, fo
|
|
|
5875
5533
|
}
|
|
5876
5534
|
}
|
|
5877
5535
|
try {
|
|
5878
|
-
await fsp.rm(
|
|
5536
|
+
await fsp.rm(path7.join(skillsDir, name), { recursive: true, force: true });
|
|
5879
5537
|
} catch (err) {
|
|
5880
5538
|
log3("warn", `\u6E05\u5B64\u513F\u5931\u8D25 ${name}`, err);
|
|
5881
5539
|
}
|
|
5882
5540
|
}
|
|
5883
5541
|
}
|
|
5884
5542
|
async function verifyPendingLink(skillsDir, name, pend, log3) {
|
|
5885
|
-
const link =
|
|
5543
|
+
const link = path7.join(skillsDir, name);
|
|
5886
5544
|
let resolved;
|
|
5887
5545
|
try {
|
|
5888
5546
|
const current = await fsp.readlink(link);
|
|
5889
|
-
resolved =
|
|
5547
|
+
resolved = path7.resolve(skillsDir, current);
|
|
5890
5548
|
} catch {
|
|
5891
5549
|
return false;
|
|
5892
5550
|
}
|
|
5893
|
-
if (
|
|
5551
|
+
if (path7.basename(resolved) !== pend.wantedVariantSlug) return false;
|
|
5894
5552
|
const actual = await listMaterializedFiles(resolved);
|
|
5895
5553
|
const expected = [...pend.fileList].sort();
|
|
5896
5554
|
const setsMatch = actual !== null && actual.length === expected.length && actual.every((p2, i) => p2 === expected[i]);
|
|
@@ -5905,14 +5563,14 @@ async function verifyPendingLink(skillsDir, name, pend, log3) {
|
|
|
5905
5563
|
}
|
|
5906
5564
|
return true;
|
|
5907
5565
|
}
|
|
5908
|
-
var import_node_crypto7, fsp, os4,
|
|
5566
|
+
var import_node_crypto7, fsp, os4, path7, MANIFEST_SCHEMA_VERSION, STALE_LOCK_MS, LOCK_ACQUIRE_TIMEOUT_MS, LOCK_POLL_MS;
|
|
5909
5567
|
var init_skill_cache = __esm({
|
|
5910
5568
|
"../adapters/src/_core/skill-cache.ts"() {
|
|
5911
5569
|
"use strict";
|
|
5912
5570
|
import_node_crypto7 = require("node:crypto");
|
|
5913
5571
|
fsp = __toESM(require("node:fs/promises"), 1);
|
|
5914
5572
|
os4 = __toESM(require("node:os"), 1);
|
|
5915
|
-
|
|
5573
|
+
path7 = __toESM(require("node:path"), 1);
|
|
5916
5574
|
MANIFEST_SCHEMA_VERSION = 2;
|
|
5917
5575
|
STALE_LOCK_MS = 6e4;
|
|
5918
5576
|
LOCK_ACQUIRE_TIMEOUT_MS = 3e4;
|
|
@@ -5967,7 +5625,7 @@ var init_skill_cache_http = __esm({
|
|
|
5967
5625
|
function resolveOnPath(binary) {
|
|
5968
5626
|
try {
|
|
5969
5627
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
5970
|
-
const out = (0,
|
|
5628
|
+
const out = (0, import_node_child_process3.execFileSync)(cmd, [binary], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
5971
5629
|
const first = out.split("\n")[0]?.trim();
|
|
5972
5630
|
return first || void 0;
|
|
5973
5631
|
} catch {
|
|
@@ -5976,7 +5634,7 @@ function resolveOnPath(binary) {
|
|
|
5976
5634
|
}
|
|
5977
5635
|
function verifyCursorAcpIdentity(binary) {
|
|
5978
5636
|
try {
|
|
5979
|
-
(0,
|
|
5637
|
+
(0, import_node_child_process3.execFileSync)(binary, ["acp", "--help"], {
|
|
5980
5638
|
stdio: ["ignore", "ignore", "ignore"],
|
|
5981
5639
|
timeout: ACP_HELP_TIMEOUT_MS
|
|
5982
5640
|
});
|
|
@@ -5992,11 +5650,11 @@ function resolveCursorBinary() {
|
|
|
5992
5650
|
if (agent && verifyCursorAcpIdentity(agent)) return agent;
|
|
5993
5651
|
return void 0;
|
|
5994
5652
|
}
|
|
5995
|
-
var
|
|
5653
|
+
var import_node_child_process3, DEFAULT_CURSOR_BIN, ACP_HELP_TIMEOUT_MS;
|
|
5996
5654
|
var init_binary = __esm({
|
|
5997
5655
|
"../adapters/src/cursor/binary.ts"() {
|
|
5998
5656
|
"use strict";
|
|
5999
|
-
|
|
5657
|
+
import_node_child_process3 = require("node:child_process");
|
|
6000
5658
|
DEFAULT_CURSOR_BIN = "cursor-agent";
|
|
6001
5659
|
ACP_HELP_TIMEOUT_MS = 1500;
|
|
6002
5660
|
}
|
|
@@ -6204,7 +5862,7 @@ async function probeCodexAppServer(bin, timeoutMs = 15e3) {
|
|
|
6204
5862
|
}
|
|
6205
5863
|
let child;
|
|
6206
5864
|
try {
|
|
6207
|
-
child = (0,
|
|
5865
|
+
child = (0, import_node_child_process4.spawn)(bin, ["app-server", "--stdio", "-c", "allow_login_shell=false"], {
|
|
6208
5866
|
cwd: dir,
|
|
6209
5867
|
stdio: ["pipe", "pipe", "ignore"],
|
|
6210
5868
|
env: { ...process.env }
|
|
@@ -6384,7 +6042,7 @@ async function discoverPiModels(bin) {
|
|
|
6384
6042
|
async function discoverPiModelsRPC(bin) {
|
|
6385
6043
|
const child = (() => {
|
|
6386
6044
|
try {
|
|
6387
|
-
return (0,
|
|
6045
|
+
return (0, import_node_child_process4.spawn)(bin, ["--mode", "rpc", "--no-session", "--no-skills", "--no-prompt-templates", "--no-context-files"], {
|
|
6388
6046
|
stdio: ["pipe", "pipe", "ignore"],
|
|
6389
6047
|
env: { ...process.env }
|
|
6390
6048
|
});
|
|
@@ -6461,7 +6119,7 @@ async function runCapture(bin, args, timeoutMs = 15e3) {
|
|
|
6461
6119
|
return await new Promise((resolve12) => {
|
|
6462
6120
|
let child;
|
|
6463
6121
|
try {
|
|
6464
|
-
child = (0,
|
|
6122
|
+
child = (0, import_node_child_process4.spawn)(bin, args, { stdio: ["ignore", "pipe", "ignore"], env: { ...process.env } });
|
|
6465
6123
|
} catch {
|
|
6466
6124
|
resolve12(void 0);
|
|
6467
6125
|
return;
|
|
@@ -6492,7 +6150,7 @@ async function runCapture(bin, args, timeoutMs = 15e3) {
|
|
|
6492
6150
|
async function discoverACPModels(bin, provider, args = ["acp"], timeoutMs = 12e3) {
|
|
6493
6151
|
const child = (() => {
|
|
6494
6152
|
try {
|
|
6495
|
-
return (0,
|
|
6153
|
+
return (0, import_node_child_process4.spawn)(bin, args, {
|
|
6496
6154
|
stdio: ["pipe", "pipe", "ignore"],
|
|
6497
6155
|
env: { ...process.env, ...provider === "hermes" ? { HERMES_YOLO_MODE: "1" } : {} }
|
|
6498
6156
|
});
|
|
@@ -6663,11 +6321,11 @@ function parseOpenclawAgentsText(output) {
|
|
|
6663
6321
|
function isSafeIdentifier(value2) {
|
|
6664
6322
|
return /^[A-Za-z][A-Za-z0-9._/-]*$/.test(value2);
|
|
6665
6323
|
}
|
|
6666
|
-
var
|
|
6324
|
+
var import_node_child_process4, import_node_fs2, import_node_os2, import_node_path3, modelCache, CACHE_TTL_MS;
|
|
6667
6325
|
var init_models = __esm({
|
|
6668
6326
|
"../adapters/src/_core/models.ts"() {
|
|
6669
6327
|
"use strict";
|
|
6670
|
-
|
|
6328
|
+
import_node_child_process4 = require("node:child_process");
|
|
6671
6329
|
import_node_fs2 = require("node:fs");
|
|
6672
6330
|
import_node_os2 = require("node:os");
|
|
6673
6331
|
import_node_path3 = require("node:path");
|
|
@@ -6725,16 +6383,16 @@ async function runProtocolSession(job, cfg) {
|
|
|
6725
6383
|
...cfg.env,
|
|
6726
6384
|
...job.env,
|
|
6727
6385
|
...cfg.yoloEnv ?? {},
|
|
6728
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
6386
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path8.dirname(p2)).join(path8.delimiter)}${path8.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
6729
6387
|
OASIS_SERVER: job.server.url,
|
|
6730
6388
|
OASIS_TOKEN: job.actorToken,
|
|
6731
6389
|
...cfg.rootBypassRuntime ? rootBypassEnv(cfg.rootBypassRuntime) : {}
|
|
6732
6390
|
};
|
|
6733
|
-
const child = containerized ? (0,
|
|
6391
|
+
const child = containerized ? (0, import_node_child_process5.spawn)(containerized.bin, containerized.args, { cwd: dir, env: scrubLeakyEnv(process.env), stdio: ["pipe", "pipe", "pipe"] }) : (0, import_node_child_process5.spawn)(cfg.bin, args, { cwd: dir, env, stdio: ["pipe", "pipe", "pipe"] });
|
|
6734
6392
|
child.stdin.on("error", () => {
|
|
6735
6393
|
});
|
|
6736
6394
|
if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
|
|
6737
|
-
const transcriptRef =
|
|
6395
|
+
const transcriptRef = path8.join(dir, "transcript.txt");
|
|
6738
6396
|
const transcript = openTranscript(transcriptRef);
|
|
6739
6397
|
const outputCbs = [];
|
|
6740
6398
|
const telemetryCbs = [];
|
|
@@ -6956,13 +6614,13 @@ async function runProtocolSession(job, cfg) {
|
|
|
6956
6614
|
}
|
|
6957
6615
|
};
|
|
6958
6616
|
}
|
|
6959
|
-
var
|
|
6617
|
+
var import_node_child_process5, import_node_crypto8, path8, ProtocolCommandRejected, ProtocolSessionClosing;
|
|
6960
6618
|
var init_protocol_session = __esm({
|
|
6961
6619
|
"../adapters/src/_core/protocol-session.ts"() {
|
|
6962
6620
|
"use strict";
|
|
6963
|
-
|
|
6621
|
+
import_node_child_process5 = require("node:child_process");
|
|
6964
6622
|
import_node_crypto8 = require("node:crypto");
|
|
6965
|
-
|
|
6623
|
+
path8 = __toESM(require("node:path"), 1);
|
|
6966
6624
|
init_claude_code();
|
|
6967
6625
|
init_usage();
|
|
6968
6626
|
init_container_runtime();
|
|
@@ -7119,12 +6777,12 @@ function pickCodexReportedModel(sources) {
|
|
|
7119
6777
|
function codexSessionsRoot() {
|
|
7120
6778
|
const candidates = [];
|
|
7121
6779
|
const ch = process.env["CODEX_HOME"];
|
|
7122
|
-
if (ch) candidates.push(
|
|
6780
|
+
if (ch) candidates.push(path9.join(ch, "sessions"));
|
|
7123
6781
|
const home2 = process.env["HOME"] || os5.homedir();
|
|
7124
|
-
if (home2) candidates.push(
|
|
6782
|
+
if (home2) candidates.push(path9.join(home2, ".codex", "sessions"));
|
|
7125
6783
|
for (const c of candidates) {
|
|
7126
6784
|
try {
|
|
7127
|
-
if (
|
|
6785
|
+
if (fs7.statSync(c).isDirectory()) return c;
|
|
7128
6786
|
} catch {
|
|
7129
6787
|
}
|
|
7130
6788
|
}
|
|
@@ -7136,17 +6794,17 @@ function listRecentRollouts(root, sinceMs) {
|
|
|
7136
6794
|
const walk = (d) => {
|
|
7137
6795
|
let ents;
|
|
7138
6796
|
try {
|
|
7139
|
-
ents =
|
|
6797
|
+
ents = fs7.readdirSync(d, { withFileTypes: true });
|
|
7140
6798
|
} catch {
|
|
7141
6799
|
return;
|
|
7142
6800
|
}
|
|
7143
6801
|
for (const ent of ents) {
|
|
7144
|
-
const p2 =
|
|
6802
|
+
const p2 = path9.join(d, ent.name);
|
|
7145
6803
|
if (ent.isDirectory()) walk(p2);
|
|
7146
6804
|
else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(".jsonl")) {
|
|
7147
6805
|
let m2 = 0;
|
|
7148
6806
|
try {
|
|
7149
|
-
m2 =
|
|
6807
|
+
m2 = fs7.statSync(p2).mtimeMs;
|
|
7150
6808
|
} catch {
|
|
7151
6809
|
}
|
|
7152
6810
|
if (m2 >= margin) found2.push({ f: p2, m: m2 });
|
|
@@ -7162,12 +6820,12 @@ function findRolloutsBySessionId(root, sessionId) {
|
|
|
7162
6820
|
const walk = (d) => {
|
|
7163
6821
|
let ents;
|
|
7164
6822
|
try {
|
|
7165
|
-
ents =
|
|
6823
|
+
ents = fs7.readdirSync(d, { withFileTypes: true });
|
|
7166
6824
|
} catch {
|
|
7167
6825
|
return;
|
|
7168
6826
|
}
|
|
7169
6827
|
for (const ent of ents) {
|
|
7170
|
-
const p2 =
|
|
6828
|
+
const p2 = path9.join(d, ent.name);
|
|
7171
6829
|
if (ent.isDirectory()) walk(p2);
|
|
7172
6830
|
else if (ent.isFile() && ent.name.startsWith("rollout-") && ent.name.endsWith(suffix)) found2.push(p2);
|
|
7173
6831
|
}
|
|
@@ -7197,7 +6855,7 @@ function locateCodexRollout(workdir, sinceMs, sessionsRoot = codexSessionsRoot()
|
|
|
7197
6855
|
const files = listRecentRollouts(sessionsRoot, sinceMs);
|
|
7198
6856
|
const readLines = (f2) => {
|
|
7199
6857
|
try {
|
|
7200
|
-
return
|
|
6858
|
+
return fs7.readFileSync(f2, "utf8").split("\n");
|
|
7201
6859
|
} catch {
|
|
7202
6860
|
return null;
|
|
7203
6861
|
}
|
|
@@ -7443,16 +7101,16 @@ function codexTurnErrorMessage(value2) {
|
|
|
7443
7101
|
const detail = typeof error2?.additionalDetails === "string" ? error2.additionalDetails.trim() : "";
|
|
7444
7102
|
return [summary, detail].filter(Boolean).join("\n").slice(0, 4e3);
|
|
7445
7103
|
}
|
|
7446
|
-
var
|
|
7104
|
+
var import_node_child_process6, import_node_crypto9, fs7, os5, path9, readline2, CODEX_BLOCKED_FLAGS, CODEX_ARGV_PROMPT_MAX_BYTES, CodexRolloutLineTail, CodexRolloutUsageTail, CodexRolloutModelTail, CODEX_APP_SERVER_BLOCKED_FLAGS, CodexAdapter;
|
|
7447
7105
|
var init_codex = __esm({
|
|
7448
7106
|
"../adapters/src/codex/index.ts"() {
|
|
7449
7107
|
"use strict";
|
|
7450
|
-
|
|
7108
|
+
import_node_child_process6 = require("node:child_process");
|
|
7451
7109
|
init_container_runtime();
|
|
7452
7110
|
import_node_crypto9 = require("node:crypto");
|
|
7453
|
-
|
|
7111
|
+
fs7 = __toESM(require("node:fs"), 1);
|
|
7454
7112
|
os5 = __toESM(require("node:os"), 1);
|
|
7455
|
-
|
|
7113
|
+
path9 = __toESM(require("node:path"), 1);
|
|
7456
7114
|
readline2 = __toESM(require("node:readline"), 1);
|
|
7457
7115
|
init_sync_skills();
|
|
7458
7116
|
init_materialize_bundle();
|
|
@@ -7490,9 +7148,9 @@ var init_codex = __esm({
|
|
|
7490
7148
|
rest = "";
|
|
7491
7149
|
/** 读新追加的整行逐行回调;文件被截短时先回调 onReset 再从头读。读失败抛给调用方(调用方吞)。 */
|
|
7492
7150
|
read(onLine, onReset) {
|
|
7493
|
-
const fd =
|
|
7151
|
+
const fd = fs7.openSync(this.file, "r");
|
|
7494
7152
|
try {
|
|
7495
|
-
const size =
|
|
7153
|
+
const size = fs7.fstatSync(fd).size;
|
|
7496
7154
|
if (size < this.offset) {
|
|
7497
7155
|
this.offset = 0;
|
|
7498
7156
|
this.rest = "";
|
|
@@ -7500,7 +7158,7 @@ var init_codex = __esm({
|
|
|
7500
7158
|
}
|
|
7501
7159
|
if (size > this.offset) {
|
|
7502
7160
|
const buf = Buffer.alloc(size - this.offset);
|
|
7503
|
-
const n =
|
|
7161
|
+
const n = fs7.readSync(fd, buf, 0, buf.length, this.offset);
|
|
7504
7162
|
this.offset += n;
|
|
7505
7163
|
const text7 = this.rest + buf.subarray(0, n).toString("utf8");
|
|
7506
7164
|
const lines = text7.split("\n");
|
|
@@ -7508,7 +7166,7 @@ var init_codex = __esm({
|
|
|
7508
7166
|
for (const line2 of lines) onLine(line2);
|
|
7509
7167
|
}
|
|
7510
7168
|
} finally {
|
|
7511
|
-
|
|
7169
|
+
fs7.closeSync(fd);
|
|
7512
7170
|
}
|
|
7513
7171
|
}
|
|
7514
7172
|
};
|
|
@@ -7771,7 +7429,7 @@ ${task}` : task;
|
|
|
7771
7429
|
let fromRollout;
|
|
7772
7430
|
if (state.rolloutPath) {
|
|
7773
7431
|
try {
|
|
7774
|
-
fromRollout = parseCodexModel(
|
|
7432
|
+
fromRollout = parseCodexModel(fs7.readFileSync(state.rolloutPath, "utf8").split("\n"));
|
|
7775
7433
|
} catch {
|
|
7776
7434
|
}
|
|
7777
7435
|
}
|
|
@@ -7923,19 +7581,19 @@ ${task}` : task;
|
|
|
7923
7581
|
...this.opts.workRoot !== void 0 ? { workRoot: this.opts.workRoot } : {},
|
|
7924
7582
|
...this.opts.env !== void 0 ? { extraEnvEarly: this.opts.env } : {}
|
|
7925
7583
|
});
|
|
7926
|
-
const child = containerized ? (0,
|
|
7584
|
+
const child = containerized ? (0, import_node_child_process6.spawn)(containerized.bin, containerized.args, {
|
|
7927
7585
|
cwd: dir,
|
|
7928
7586
|
env: scrubLeakyEnv(process.env),
|
|
7929
7587
|
// stdin 的开合口径与宿主分支一致:codex 只在走 stdin 时才该收到管道(见下方长注释)。
|
|
7930
7588
|
// 容器包装本身带 `-i`,podman 会把这条管道透传给容器内进程。
|
|
7931
7589
|
stdio: [promptViaStdin ? "pipe" : "ignore", "pipe", "pipe"]
|
|
7932
|
-
}) : (0,
|
|
7590
|
+
}) : (0, import_node_child_process6.spawn)(this.opts.codexBin ?? "codex", args, {
|
|
7933
7591
|
cwd: dir,
|
|
7934
7592
|
env: {
|
|
7935
7593
|
...scrubLeakyEnv(process.env),
|
|
7936
7594
|
...this.opts.env,
|
|
7937
7595
|
...job.env,
|
|
7938
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
7596
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path9.dirname(p2)).join(path9.delimiter)}${path9.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
7939
7597
|
OASIS_SERVER: job.server.url,
|
|
7940
7598
|
OASIS_TOKEN: job.actorToken
|
|
7941
7599
|
},
|
|
@@ -7952,7 +7610,7 @@ ${task}` : task;
|
|
|
7952
7610
|
child.stdin.end(prompt2);
|
|
7953
7611
|
}
|
|
7954
7612
|
if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
|
|
7955
|
-
let transcriptRef =
|
|
7613
|
+
let transcriptRef = path9.join(dir, "transcript.txt");
|
|
7956
7614
|
const out = openTranscript(transcriptRef);
|
|
7957
7615
|
const outputCbs = [];
|
|
7958
7616
|
const telemetryCbs = [];
|
|
@@ -8054,14 +7712,14 @@ ${task}` : task;
|
|
|
8054
7712
|
}
|
|
8055
7713
|
if (this.opts.cleanupWorkdir && !job.workdirKey) {
|
|
8056
7714
|
try {
|
|
8057
|
-
const keepDir =
|
|
8058
|
-
|
|
8059
|
-
const kept =
|
|
7715
|
+
const keepDir = path9.join(resolveWorkRoot(this.opts.workRoot), "oasis-transcripts");
|
|
7716
|
+
fs7.mkdirSync(keepDir, { recursive: true });
|
|
7717
|
+
const kept = path9.join(keepDir, `${id}.txt`);
|
|
8060
7718
|
const src = transcriptRef;
|
|
8061
7719
|
out.end(() => {
|
|
8062
7720
|
try {
|
|
8063
|
-
|
|
8064
|
-
|
|
7721
|
+
fs7.renameSync(src, kept);
|
|
7722
|
+
fs7.rmSync(dir, { recursive: true, force: true });
|
|
8065
7723
|
} catch {
|
|
8066
7724
|
}
|
|
8067
7725
|
});
|
|
@@ -8579,10 +8237,10 @@ function buildReportedUsage(acc, model, inputTokensIncludeCacheRead) {
|
|
|
8579
8237
|
}
|
|
8580
8238
|
async function runACPSession(job, cfg) {
|
|
8581
8239
|
if (job.executionEnv) {
|
|
8582
|
-
throw new Error(`executionEnv\uFF1A${
|
|
8240
|
+
throw new Error(`executionEnv\uFF1A${path10.basename(cfg.bin)}\uFF08ACP runtime\uFF09\u5C1A\u672A\u652F\u6301\u5BB9\u5668\u5316\u6267\u884C\uFF08ADR-0147\uFF09\uFF0C\u8BF7\u6539\u6D3E claude-code \u5458\u5DE5\u6216\u53BB\u6389\u8BE5\u8282\u70B9\u7684 executionEnv \u58F0\u660E`);
|
|
8583
8241
|
}
|
|
8584
8242
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
8585
|
-
const binTag =
|
|
8243
|
+
const binTag = path10.basename(cfg.bin).replace(/[^a-zA-Z0-9]/g, "").slice(0, 12) || "acp";
|
|
8586
8244
|
const id = `${binTag}-${slug6}-${(0, import_node_crypto10.randomUUID)().slice(0, 8)}`;
|
|
8587
8245
|
const dir = job.workdirKey ? prepareWorkdir({
|
|
8588
8246
|
workRoot: cfg.workRoot,
|
|
@@ -8616,7 +8274,7 @@ async function runACPSession(job, cfg) {
|
|
|
8616
8274
|
});
|
|
8617
8275
|
}
|
|
8618
8276
|
const task = materializeBundle(dir, job.bundle);
|
|
8619
|
-
const child = (0,
|
|
8277
|
+
const child = (0, import_node_child_process7.spawn)(cfg.bin, [...cfg.args ?? [], ...prepareExtraArgs(
|
|
8620
8278
|
job.extraArgs,
|
|
8621
8279
|
cfg.extraArgs,
|
|
8622
8280
|
cfg.blockedFlags,
|
|
@@ -8628,9 +8286,9 @@ async function runACPSession(job, cfg) {
|
|
|
8628
8286
|
...cfg.env,
|
|
8629
8287
|
...job.env,
|
|
8630
8288
|
...cfg.yoloEnv ?? {},
|
|
8631
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
8289
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path10.dirname(p2)).join(path10.delimiter)}${path10.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
8632
8290
|
// 每会话技能目录绝对路径 → env(供不扫 cwd 的 runtime 经 config external_dirs 发现,见 injectSkillsDirEnv)。
|
|
8633
|
-
...cfg.injectSkillsDirEnv ? { [cfg.injectSkillsDirEnv]:
|
|
8291
|
+
...cfg.injectSkillsDirEnv ? { [cfg.injectSkillsDirEnv]: path10.join(dir, sessionSkillsSubdir(cfg.runtimeKind ?? "")) } : {},
|
|
8634
8292
|
OASIS_SERVER: job.server.url,
|
|
8635
8293
|
OASIS_TOKEN: job.actorToken,
|
|
8636
8294
|
...cfg.rootBypassRuntime ? rootBypassEnv(cfg.rootBypassRuntime) : {}
|
|
@@ -8640,7 +8298,7 @@ async function runACPSession(job, cfg) {
|
|
|
8640
8298
|
child.stdin.on("error", () => {
|
|
8641
8299
|
});
|
|
8642
8300
|
if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
|
|
8643
|
-
let transcriptRef =
|
|
8301
|
+
let transcriptRef = path10.join(dir, "transcript.txt");
|
|
8644
8302
|
const transcriptOut = openTranscript(transcriptRef);
|
|
8645
8303
|
const outputCbs = [];
|
|
8646
8304
|
const telemetryCbs = [];
|
|
@@ -8742,14 +8400,14 @@ ${note}` : note };
|
|
|
8742
8400
|
}
|
|
8743
8401
|
if (cfg.cleanupWorkdir && !job.workdirKey) {
|
|
8744
8402
|
try {
|
|
8745
|
-
const keepDir =
|
|
8746
|
-
|
|
8747
|
-
const kept =
|
|
8403
|
+
const keepDir = path10.join(resolveWorkRoot(cfg.workRoot), "oasis-transcripts");
|
|
8404
|
+
fs8.mkdirSync(keepDir, { recursive: true });
|
|
8405
|
+
const kept = path10.join(keepDir, `${id}.txt`);
|
|
8748
8406
|
const src = transcriptRef;
|
|
8749
8407
|
transcriptOut.end(() => {
|
|
8750
8408
|
try {
|
|
8751
|
-
|
|
8752
|
-
|
|
8409
|
+
fs8.renameSync(src, kept);
|
|
8410
|
+
fs8.rmSync(dir, { recursive: true, force: true });
|
|
8753
8411
|
} catch {
|
|
8754
8412
|
}
|
|
8755
8413
|
});
|
|
@@ -9099,14 +8757,14 @@ ${task}` : task;
|
|
|
9099
8757
|
return run;
|
|
9100
8758
|
}
|
|
9101
8759
|
}
|
|
9102
|
-
var
|
|
8760
|
+
var import_node_child_process7, import_node_crypto10, fs8, path10, readline3, PROMPT_TURN_MESSAGE_MAX, PROMPT_TURN_STDERR_MAX_LINES, PROMPT_FAILURE_STDERR_SETTLE_MS, ACPClient, LEGACY_APPROVE_OPTION_ID;
|
|
9103
8761
|
var init_acp = __esm({
|
|
9104
8762
|
"../adapters/src/_core/acp.ts"() {
|
|
9105
8763
|
"use strict";
|
|
9106
|
-
|
|
8764
|
+
import_node_child_process7 = require("node:child_process");
|
|
9107
8765
|
import_node_crypto10 = require("node:crypto");
|
|
9108
|
-
|
|
9109
|
-
|
|
8766
|
+
fs8 = __toESM(require("node:fs"), 1);
|
|
8767
|
+
path10 = __toESM(require("node:path"), 1);
|
|
9110
8768
|
readline3 = __toESM(require("node:readline"), 1);
|
|
9111
8769
|
init_sync_skills();
|
|
9112
8770
|
init_session_paths();
|
|
@@ -9708,10 +9366,10 @@ function cursorAcpSessionStorePath(sessionId, env = process.env) {
|
|
|
9708
9366
|
if (!sessionId) return void 0;
|
|
9709
9367
|
const home2 = env["CURSOR_HOME"] || env["HOME"] || os6.homedir();
|
|
9710
9368
|
if (!home2) return void 0;
|
|
9711
|
-
const base = env["CURSOR_HOME"] ? home2 :
|
|
9712
|
-
const file =
|
|
9369
|
+
const base = env["CURSOR_HOME"] ? home2 : path11.join(home2, ".cursor");
|
|
9370
|
+
const file = path11.join(base, "acp-sessions", sessionId, "store.db");
|
|
9713
9371
|
try {
|
|
9714
|
-
return
|
|
9372
|
+
return fs9.existsSync(file) ? file : void 0;
|
|
9715
9373
|
} catch {
|
|
9716
9374
|
return void 0;
|
|
9717
9375
|
}
|
|
@@ -9846,13 +9504,13 @@ async function readCursorRoutedModel(sessionId, window3) {
|
|
|
9846
9504
|
}
|
|
9847
9505
|
}
|
|
9848
9506
|
}
|
|
9849
|
-
var
|
|
9507
|
+
var fs9, os6, path11, MAX_TABLES, MAX_ROWS_PER_TABLE, TURN_CLOCK_TOLERANCE_MS, TIME_KEY_TAILS;
|
|
9850
9508
|
var init_local_store = __esm({
|
|
9851
9509
|
"../adapters/src/cursor/local-store.ts"() {
|
|
9852
9510
|
"use strict";
|
|
9853
|
-
|
|
9511
|
+
fs9 = __toESM(require("node:fs"), 1);
|
|
9854
9512
|
os6 = __toESM(require("node:os"), 1);
|
|
9855
|
-
|
|
9513
|
+
path11 = __toESM(require("node:path"), 1);
|
|
9856
9514
|
MAX_TABLES = 24;
|
|
9857
9515
|
MAX_ROWS_PER_TABLE = 200;
|
|
9858
9516
|
TURN_CLOCK_TOLERANCE_MS = 1e3;
|
|
@@ -10127,12 +9785,12 @@ function normalizePi(line2) {
|
|
|
10127
9785
|
function piReportedModel(state, requested) {
|
|
10128
9786
|
return pickReportedModel({ runtime: [state.model, state.startupModel], requested });
|
|
10129
9787
|
}
|
|
10130
|
-
var
|
|
9788
|
+
var fs10, path12, PI_SESSION_FILE, PI_BLOCKED_FLAGS, PiAdapter;
|
|
10131
9789
|
var init_pi = __esm({
|
|
10132
9790
|
"../adapters/src/pi/index.ts"() {
|
|
10133
9791
|
"use strict";
|
|
10134
|
-
|
|
10135
|
-
|
|
9792
|
+
fs10 = __toESM(require("node:fs"), 1);
|
|
9793
|
+
path12 = __toESM(require("node:path"), 1);
|
|
10136
9794
|
init_protocol_session();
|
|
10137
9795
|
init_usage();
|
|
10138
9796
|
init_model_report();
|
|
@@ -10159,9 +9817,9 @@ var init_pi = __esm({
|
|
|
10159
9817
|
buildArgs(job2, dir) {
|
|
10160
9818
|
const model = job2.model ?? opts.model;
|
|
10161
9819
|
if (!job2.workdirKey) return ["--mode", "rpc", "--no-session", ...model ? ["--model", model] : []];
|
|
10162
|
-
const sessionFile =
|
|
9820
|
+
const sessionFile = path12.join(dir, PI_SESSION_FILE);
|
|
10163
9821
|
try {
|
|
10164
|
-
if (!
|
|
9822
|
+
if (!fs10.existsSync(sessionFile)) fs10.writeFileSync(sessionFile, "");
|
|
10165
9823
|
} catch {
|
|
10166
9824
|
return ["--mode", "rpc", "--no-session"];
|
|
10167
9825
|
}
|
|
@@ -10268,7 +9926,7 @@ function pdeathsigAvailable(probe = defaultProbe) {
|
|
|
10268
9926
|
function defaultProbe() {
|
|
10269
9927
|
if (os7.platform() !== "linux") return false;
|
|
10270
9928
|
try {
|
|
10271
|
-
const help = (0,
|
|
9929
|
+
const help = (0, import_node_child_process8.execFileSync)("setpriv", ["--help"], { stdio: ["ignore", "pipe", "ignore"], timeout: 2e3 }).toString();
|
|
10272
9930
|
return help.includes("--pdeathsig");
|
|
10273
9931
|
} catch {
|
|
10274
9932
|
return false;
|
|
@@ -10280,11 +9938,11 @@ function pdeathsigWrap(bin, args) {
|
|
|
10280
9938
|
function shouldBindRuntimePdeathsig() {
|
|
10281
9939
|
return process.env["OASIS_BIND_RUNTIME_PDEATHSIG"] === "1" && pdeathsigAvailable();
|
|
10282
9940
|
}
|
|
10283
|
-
var
|
|
9941
|
+
var import_node_child_process8, os7, cachedAvailable;
|
|
10284
9942
|
var init_pdeathsig = __esm({
|
|
10285
9943
|
"../adapters/src/_core/pdeathsig.ts"() {
|
|
10286
9944
|
"use strict";
|
|
10287
|
-
|
|
9945
|
+
import_node_child_process8 = require("node:child_process");
|
|
10288
9946
|
os7 = __toESM(require("node:os"), 1);
|
|
10289
9947
|
}
|
|
10290
9948
|
});
|
|
@@ -10332,7 +9990,7 @@ function buildEnv(job, cfg) {
|
|
|
10332
9990
|
...scrubLeakyEnv(process.env),
|
|
10333
9991
|
...cfg.env,
|
|
10334
9992
|
...job.env,
|
|
10335
|
-
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) =>
|
|
9993
|
+
...job.wrapperPaths?.length ? { PATH: `${job.wrapperPaths.map((p2) => path13.dirname(p2)).join(path13.delimiter)}${path13.delimiter}${job.env?.["PATH"] ?? process.env["PATH"] ?? ""}` } : {},
|
|
10336
9994
|
OASIS_SERVER: job.server.url,
|
|
10337
9995
|
OASIS_TOKEN: job.actorToken,
|
|
10338
9996
|
// root 下放行 bypassPermissions(仅 claude 家族 runtime 声明;见 _core/root-bypass.ts)。
|
|
@@ -10357,14 +10015,14 @@ function makeFinish(id, cfg, transcriptRefPtr, transcriptOut, dir, workdirKey, r
|
|
|
10357
10015
|
}
|
|
10358
10016
|
if (cfg.cleanupWorkdir && !workdirKey) {
|
|
10359
10017
|
try {
|
|
10360
|
-
const keepDir =
|
|
10361
|
-
|
|
10362
|
-
const kept =
|
|
10018
|
+
const keepDir = path13.join(resolveWorkRoot(cfg.workRoot), "oasis-transcripts");
|
|
10019
|
+
fs11.mkdirSync(keepDir, { recursive: true });
|
|
10020
|
+
const kept = path13.join(keepDir, `${id}.txt`);
|
|
10363
10021
|
const src = transcriptRefPtr.value;
|
|
10364
10022
|
transcriptOut.end(() => {
|
|
10365
10023
|
try {
|
|
10366
|
-
|
|
10367
|
-
|
|
10024
|
+
fs11.renameSync(src, kept);
|
|
10025
|
+
fs11.rmSync(dir, { recursive: true, force: true });
|
|
10368
10026
|
} catch {
|
|
10369
10027
|
}
|
|
10370
10028
|
});
|
|
@@ -10395,17 +10053,17 @@ async function runStreamJson(job, cfg) {
|
|
|
10395
10053
|
...cfg.env !== void 0 ? { extraEnvEarly: cfg.env } : {}
|
|
10396
10054
|
});
|
|
10397
10055
|
const direct = shouldBindRuntimePdeathsig() ? pdeathsigWrap(cfg.bin, args) : { bin: cfg.bin, args };
|
|
10398
|
-
const child = containerized ? (0,
|
|
10056
|
+
const child = containerized ? (0, import_node_child_process9.spawn)(containerized.bin, containerized.args, {
|
|
10399
10057
|
cwd: dir,
|
|
10400
10058
|
env: scrubLeakyEnv(process.env),
|
|
10401
10059
|
stdio: ["ignore", "pipe", "pipe"]
|
|
10402
|
-
}) : (0,
|
|
10060
|
+
}) : (0, import_node_child_process9.spawn)(direct.bin, direct.args, {
|
|
10403
10061
|
cwd: dir,
|
|
10404
10062
|
env: buildEnv(job, cfg),
|
|
10405
10063
|
stdio: ["ignore", "pipe", "pipe"]
|
|
10406
10064
|
});
|
|
10407
10065
|
if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
|
|
10408
|
-
const transcriptRefPtr = { value:
|
|
10066
|
+
const transcriptRefPtr = { value: path13.join(dir, "transcript.txt") };
|
|
10409
10067
|
const transcriptOut = openTranscript(transcriptRefPtr.value);
|
|
10410
10068
|
const outputCbs = [];
|
|
10411
10069
|
const telemetryCbs = [];
|
|
@@ -10505,17 +10163,17 @@ async function runOneShotText(job, cfg) {
|
|
|
10505
10163
|
...cfg.env !== void 0 ? { extraEnvEarly: cfg.env } : {}
|
|
10506
10164
|
});
|
|
10507
10165
|
const direct = shouldBindRuntimePdeathsig() ? pdeathsigWrap(cfg.bin, args) : { bin: cfg.bin, args };
|
|
10508
|
-
const child = containerized ? (0,
|
|
10166
|
+
const child = containerized ? (0, import_node_child_process9.spawn)(containerized.bin, containerized.args, {
|
|
10509
10167
|
cwd: dir,
|
|
10510
10168
|
env: scrubLeakyEnv(process.env),
|
|
10511
10169
|
stdio: ["ignore", "pipe", "pipe"]
|
|
10512
|
-
}) : (0,
|
|
10170
|
+
}) : (0, import_node_child_process9.spawn)(direct.bin, direct.args, {
|
|
10513
10171
|
cwd: dir,
|
|
10514
10172
|
env: buildEnv(job, cfg),
|
|
10515
10173
|
stdio: ["ignore", "pipe", "pipe"]
|
|
10516
10174
|
});
|
|
10517
10175
|
if (child.pid !== void 0 && job.workdirKey) lockWorkdir(dir, child.pid, "session", job.workdirKey);
|
|
10518
|
-
const transcriptRefPtr = { value:
|
|
10176
|
+
const transcriptRefPtr = { value: path13.join(dir, "transcript.txt") };
|
|
10519
10177
|
const transcriptOut = openTranscript(transcriptRefPtr.value);
|
|
10520
10178
|
const outputCbs = [];
|
|
10521
10179
|
const exitCbs = [];
|
|
@@ -10588,14 +10246,14 @@ async function runOneShotText(job, cfg) {
|
|
|
10588
10246
|
}
|
|
10589
10247
|
});
|
|
10590
10248
|
}
|
|
10591
|
-
var
|
|
10249
|
+
var import_node_child_process9, import_node_crypto11, fs11, path13, readline4;
|
|
10592
10250
|
var init_subprocess = __esm({
|
|
10593
10251
|
"../adapters/src/_core/subprocess.ts"() {
|
|
10594
10252
|
"use strict";
|
|
10595
|
-
|
|
10253
|
+
import_node_child_process9 = require("node:child_process");
|
|
10596
10254
|
import_node_crypto11 = require("node:crypto");
|
|
10597
|
-
|
|
10598
|
-
|
|
10255
|
+
fs11 = __toESM(require("node:fs"), 1);
|
|
10256
|
+
path13 = __toESM(require("node:path"), 1);
|
|
10599
10257
|
readline4 = __toESM(require("node:readline"), 1);
|
|
10600
10258
|
init_claude_code();
|
|
10601
10259
|
init_container_runtime();
|
|
@@ -11469,6 +11127,398 @@ var init_src2 = __esm({
|
|
|
11469
11127
|
}
|
|
11470
11128
|
});
|
|
11471
11129
|
|
|
11130
|
+
// ../server/src/design/board-key.ts
|
|
11131
|
+
async function boardLinkOf(blobs, rev, cache) {
|
|
11132
|
+
if (rev.contentKind !== "manifest" || rev.contentRef.length === 0) return null;
|
|
11133
|
+
const hit = cache?.get(rev.id);
|
|
11134
|
+
if (hit !== void 0) return hit;
|
|
11135
|
+
const manifest = parseManifest(await blobs.get(rev.contentRef));
|
|
11136
|
+
const entry = manifest.entries.find((e) => e.path === BOARD_LINK_FILE);
|
|
11137
|
+
const text7 = entry ? new TextDecoder().decode(await blobs.get(entry.hash)) : null;
|
|
11138
|
+
cache?.set(rev.id, text7);
|
|
11139
|
+
return text7;
|
|
11140
|
+
}
|
|
11141
|
+
async function latestBoardLink(model, blobs, a, cache) {
|
|
11142
|
+
const head = a.currentRev ? model.revisions.get(a.currentRev) : void 0;
|
|
11143
|
+
const rest = [...model.revisions.values()].filter((r) => r.artifactId === a.id && r.id !== head?.id && r.contentKind === "manifest").sort((x2, y) => y.createdAt.localeCompare(x2.createdAt));
|
|
11144
|
+
for (const rev of head ? [head, ...rest] : rest) {
|
|
11145
|
+
const text7 = await boardLinkOf(blobs, rev, cache);
|
|
11146
|
+
if (text7 !== null) return text7;
|
|
11147
|
+
}
|
|
11148
|
+
return null;
|
|
11149
|
+
}
|
|
11150
|
+
async function resolveDesignBoard(args, deps = {}) {
|
|
11151
|
+
if (args.companyId.trim().length === 0) {
|
|
11152
|
+
throw new Error(`\u62FF\u4E0D\u5230 ${args.artifact.id} \u6240\u5728\u7684\u516C\u53F8\uFF0C\u4E0D\u80FD\u786E\u5B9A\u753B\u677F\u2014\u2014\u4E0D\u56DE\u843D\u5230\u4E0D\u5E26\u516C\u53F8\u7684\u65E7\u753B\u677F\u540D`);
|
|
11153
|
+
}
|
|
11154
|
+
const boardLink = args.blobs ? await latestBoardLink(args.model, args.blobs, args.artifact, deps.cache) : null;
|
|
11155
|
+
const fromLink = boardLink !== null ? parseBoardLinkBoardKey(boardLink) : null;
|
|
11156
|
+
if (fromLink !== null) return { boardKey: fromLink, source: "board-link" };
|
|
11157
|
+
return { boardKey: (deps.deriveKey ?? deriveBoardKey)(args.companyId, args.artifact.id), source: "derived" };
|
|
11158
|
+
}
|
|
11159
|
+
var init_board_key = __esm({
|
|
11160
|
+
"../server/src/design/board-key.ts"() {
|
|
11161
|
+
"use strict";
|
|
11162
|
+
init_src();
|
|
11163
|
+
init_src2();
|
|
11164
|
+
}
|
|
11165
|
+
});
|
|
11166
|
+
|
|
11167
|
+
// ../server/src/domains/chat-sessions/session-runtime-target.ts
|
|
11168
|
+
function sessionRuntimeOverride(session) {
|
|
11169
|
+
const nodeId = session?.overrideNodeId?.trim();
|
|
11170
|
+
const runtimeKind = session?.overrideRuntimeKind?.trim();
|
|
11171
|
+
if (!nodeId || !runtimeKind) return null;
|
|
11172
|
+
return { nodeId, runtimeKind };
|
|
11173
|
+
}
|
|
11174
|
+
function chatSessionInitialRuntime(input) {
|
|
11175
|
+
const trimmed = (v2) => typeof v2 === "string" && v2.trim() ? v2.trim() : null;
|
|
11176
|
+
const binding = input.binding?.nodeId && input.binding?.runtimeKind ? { nodeId: input.binding.nodeId, runtimeKind: input.binding.runtimeKind } : null;
|
|
11177
|
+
const requestedOverride = input.requested?.override;
|
|
11178
|
+
const picked = requestedOverride?.nodeId && requestedOverride?.runtimeKind ? { nodeId: requestedOverride.nodeId, runtimeKind: requestedOverride.runtimeKind } : null;
|
|
11179
|
+
const target = picked ?? binding;
|
|
11180
|
+
const followsAgentTarget = !picked || !!binding && picked.nodeId === binding.nodeId && picked.runtimeKind === binding.runtimeKind;
|
|
11181
|
+
const requestedModel = input.requested?.model;
|
|
11182
|
+
const model = requestedModel !== void 0 ? trimmed(requestedModel) : followsAgentTarget ? trimmed(input.agentModel) : null;
|
|
11183
|
+
return {
|
|
11184
|
+
overrideNodeId: target?.nodeId ?? null,
|
|
11185
|
+
overrideRuntimeKind: target?.runtimeKind ?? null,
|
|
11186
|
+
model
|
|
11187
|
+
};
|
|
11188
|
+
}
|
|
11189
|
+
function sessionRuntimeOverrideChangesTarget(session, binding) {
|
|
11190
|
+
const override = sessionRuntimeOverride(session);
|
|
11191
|
+
if (!override) return false;
|
|
11192
|
+
if (!binding) return true;
|
|
11193
|
+
return override.nodeId !== binding.nodeId || override.runtimeKind !== binding.runtimeKind;
|
|
11194
|
+
}
|
|
11195
|
+
async function resolveSessionRuntimeTarget(input) {
|
|
11196
|
+
const { probe } = input;
|
|
11197
|
+
const override = sessionRuntimeOverride(input.session);
|
|
11198
|
+
if (!override) {
|
|
11199
|
+
return probe.binding ? { binding: probe.binding, source: "actor_binding" } : null;
|
|
11200
|
+
}
|
|
11201
|
+
const kinds = await probe.availableRuntimeKinds(override.nodeId);
|
|
11202
|
+
const nodeName = (await probe.nodeDisplayName?.(override.nodeId))?.trim() || override.nodeId;
|
|
11203
|
+
if (kinds === null) {
|
|
11204
|
+
throw new SessionRuntimeOverrideError(
|
|
11205
|
+
"CHAT_SESSION_NODE_UNAVAILABLE",
|
|
11206
|
+
`\u8FD9\u6761\u4F1A\u8BDD\u9009\u5B9A\u7684\u8282\u70B9\u300C${nodeName}\u300D\u5F53\u524D\u4E0D\u53EF\u7528\uFF08\u53EF\u80FD\u5DF2\u79BB\u7EBF\u3001\u5DF2\u5220\u9664\uFF0C\u6216\u4E0D\u5C5E\u4E8E\u5F53\u524D\u516C\u53F8\uFF09\u3002\u8BF7\u786E\u8BA4\u90A3\u53F0\u673A\u5668\u5F00\u7740\u3001\u8282\u70B9\u7A0B\u5E8F\u5728\u8FD0\u884C\u540E\u518D\u53D1\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
11207
|
+
);
|
|
11208
|
+
}
|
|
11209
|
+
if (!kinds.includes(override.runtimeKind)) {
|
|
11210
|
+
throw new SessionRuntimeOverrideError(
|
|
11211
|
+
"CHAT_SESSION_RUNTIME_UNAVAILABLE",
|
|
11212
|
+
`\u8282\u70B9\u300C${nodeName}\u300D\u4E0A\u6CA1\u6709\u53EF\u7528\u7684\u8FD0\u884C\u65F6 ${override.runtimeKind}\uFF08\u53EF\u80FD\u5DF2\u5378\u8F7D\u3001\u8FD8\u6CA1\u88C5\u597D\uFF0C\u6216\u672A\u4E0A\u62A5\uFF09\u3002\u8BF7\u5728\u90A3\u53F0\u673A\u5668\u4E0A\u88C5\u597D\u540E\u518D\u53D1\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
11213
|
+
);
|
|
11214
|
+
}
|
|
11215
|
+
if (!probe.binding) {
|
|
11216
|
+
throw new SessionRuntimeOverrideError(
|
|
11217
|
+
"ACTOR_BINDING_MISSING",
|
|
11218
|
+
`\u8FD9\u4F4D Agent \u8FD8\u6CA1\u6709\u7ED1\u5B9A\u8FD0\u884C\u65F6\uFF0C\u9009\u5B9A\u8282\u70B9\u4E5F\u6D3E\u4E0D\u51FA\u53BB\u3002\u8BF7\u5148\u7ED9\u4ED6\u7ED1\u5B9A\u4E00\u4E2A\u53EF\u7528\u7684\u8FD0\u884C\u65F6\uFF1B\u6216${CLEAR_SESSION_RUNTIME_HINT}`
|
|
11219
|
+
);
|
|
11220
|
+
}
|
|
11221
|
+
return {
|
|
11222
|
+
binding: { actorId: probe.binding.actorId, nodeId: override.nodeId, runtimeKind: override.runtimeKind, status: probe.binding.status },
|
|
11223
|
+
source: "session_override"
|
|
11224
|
+
};
|
|
11225
|
+
}
|
|
11226
|
+
function canAnnounceRuntimeSwitch(prior) {
|
|
11227
|
+
const nodeId = prior?.runtimeId?.trim();
|
|
11228
|
+
const kind = prior?.runtimeKind?.trim();
|
|
11229
|
+
return Boolean(nodeId && kind && nodeId !== "unknown");
|
|
11230
|
+
}
|
|
11231
|
+
function runtimeSwitchedNotice(target) {
|
|
11232
|
+
const name = target.nodeName?.trim();
|
|
11233
|
+
const where = name ? `${name} \xB7 ${target.runtimeKind}` : target.runtimeKind;
|
|
11234
|
+
return `\u8FD0\u884C\u65F6\u5DF2\u5207\u5230 ${where}\uFF0C\u672C\u8F6E\u8D77\u5728\u65B0\u7684\u8FD0\u884C\u65F6\u4F1A\u8BDD\u4E2D\u7EE7\u7EED\uFF0C\u5DE5\u4F5C\u533A\u4E0E\u4E0A\u4E0B\u6587\u4E0D\u6CBF\u7528\u3002`;
|
|
11235
|
+
}
|
|
11236
|
+
var SessionRuntimeOverrideError, CLEAR_SESSION_RUNTIME_HINT;
|
|
11237
|
+
var init_session_runtime_target = __esm({
|
|
11238
|
+
"../server/src/domains/chat-sessions/session-runtime-target.ts"() {
|
|
11239
|
+
"use strict";
|
|
11240
|
+
SessionRuntimeOverrideError = class extends Error {
|
|
11241
|
+
constructor(code2, message, status = 409) {
|
|
11242
|
+
super(message);
|
|
11243
|
+
this.code = code2;
|
|
11244
|
+
this.status = status;
|
|
11245
|
+
this.name = "SessionRuntimeOverrideError";
|
|
11246
|
+
}
|
|
11247
|
+
};
|
|
11248
|
+
CLEAR_SESSION_RUNTIME_HINT = "\u5728\u8F93\u5165\u6846\u5E95\u90E8\u7684\u8FD0\u884C\u65F6\u9009\u62E9\u91CC\u6362\u4E00\u53F0\u53EF\u7528\u7684\u670D\u52A1\u5668\u6216\u8FD0\u884C\u65F6\u5373\u53EF\u7EE7\u7EED\uFF08\u5458\u5DE5\u81EA\u5DF1\u7684\u90A3\u4E00\u5957\u6807\u7740\u300C\u5F53\u524D\u5458\u5DE5\u6240\u5728\u670D\u52A1\u5668\u300D\u300C\u5F53\u524D\u5458\u5DE5\u8FD0\u884C\u65F6\u300D\uFF09\u3002";
|
|
11249
|
+
}
|
|
11250
|
+
});
|
|
11251
|
+
|
|
11252
|
+
// ../server/src/artifact-content.ts
|
|
11253
|
+
async function currentOutput(kernel, artifactId) {
|
|
11254
|
+
await kernel.refreshModel();
|
|
11255
|
+
const artifact = kernel.model.artifacts.get(artifactId);
|
|
11256
|
+
if (!artifact) throw new ApiError(404, "NOT_FOUND", "\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
11257
|
+
const snap = await kernel.getStore().transaction((tx) => tx.loadWorkorder(artifact.workspace));
|
|
11258
|
+
const node2 = snap?.nodes.find((n) => n.id === artifactId);
|
|
11259
|
+
const latest = snap?.works.find((w2) => w2.id === node2?.latestWorkId);
|
|
11260
|
+
const workId = latest && (latest.status === "failed" || latest.status === "dead") && node2?.latestProposedWorkId ? node2.latestProposedWorkId : node2?.latestWorkId;
|
|
11261
|
+
const output = snap?.artifacts.filter((a) => a.workId === workId).sort((a, b2) => a.ordinal - b2.ordinal)[0];
|
|
11262
|
+
if (!node2 || !output) throw new ApiError(404, "NOT_FOUND", "\u8FD9\u4E2A\u8282\u70B9\u5C1A\u672A\u4EA4\u4ED8\u6587\u4EF6");
|
|
11263
|
+
return { node: node2, output };
|
|
11264
|
+
}
|
|
11265
|
+
function looksLikeFileName(name) {
|
|
11266
|
+
return /^\.[a-z]{1,8}[0-9]?$/.test(fileExtensionOf(name));
|
|
11267
|
+
}
|
|
11268
|
+
function decodeText(bytes2) {
|
|
11269
|
+
if (bytes2.length > currentFileLimits().textEditBytes || bytes2.includes(0)) return null;
|
|
11270
|
+
try {
|
|
11271
|
+
return new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
|
|
11272
|
+
} catch {
|
|
11273
|
+
return null;
|
|
11274
|
+
}
|
|
11275
|
+
}
|
|
11276
|
+
async function readEditable(kernel, blobs, artifactId, path47) {
|
|
11277
|
+
const { node: node2, output } = await currentOutput(kernel, artifactId);
|
|
11278
|
+
let text7 = null;
|
|
11279
|
+
if (output.contentKind === "manifest" && path47 !== null) {
|
|
11280
|
+
const manifest = parseManifest(await blobs.get(output.contentRef));
|
|
11281
|
+
const entry = manifest.entries.find((e) => e.path === path47);
|
|
11282
|
+
if (!entry) throw new ApiError(404, "NOT_FOUND", "\u5305\u5185\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
11283
|
+
if (isEditableFileName(entry.path)) text7 = decodeText(await blobs.get(entry.hash));
|
|
11284
|
+
} else if (output.contentKind === "inline") {
|
|
11285
|
+
const name = node2.title || output.name;
|
|
11286
|
+
if (!looksLikeFileName(name) || isEditableFileName(name)) text7 = decodeText(await blobs.get(output.contentRef));
|
|
11287
|
+
}
|
|
11288
|
+
const view = {
|
|
11289
|
+
artifactId,
|
|
11290
|
+
revisionId: output.workId,
|
|
11291
|
+
contentRef: output.contentRef,
|
|
11292
|
+
path: path47,
|
|
11293
|
+
editable: text7 !== null,
|
|
11294
|
+
text: text7
|
|
11295
|
+
};
|
|
11296
|
+
return { view, node: node2, output };
|
|
11297
|
+
}
|
|
11298
|
+
async function readArtifactEditableContent(kernel, blobs, artifactId, path47) {
|
|
11299
|
+
return (await readEditable(kernel, blobs, artifactId, path47)).view;
|
|
11300
|
+
}
|
|
11301
|
+
async function saveArtifactContent(kernel, blobs, actor, input) {
|
|
11302
|
+
if (!input || typeof input.artifactId !== "string" || typeof input.revisionId !== "string" || typeof input.contentRef !== "string" || typeof input.text !== "string" || input.path != null && typeof input.path !== "string") {
|
|
11303
|
+
throw new ApiError(400, "BAD_REQUEST", "\u4FDD\u5B58\u53C2\u6570\u4E0D\u5B8C\u6574");
|
|
11304
|
+
}
|
|
11305
|
+
const bytes2 = new TextEncoder().encode(input.text);
|
|
11306
|
+
if (bytes2.length > currentFileLimits().textEditBytes || bytes2.includes(0)) {
|
|
11307
|
+
throw new ApiError(400, "BAD_REQUEST", `\u4EC5\u652F\u6301\u4E0D\u8D85\u8FC7 ${currentFileLimits().textEditBytes / 1024 / 1024} MiB \u7684 UTF-8 \u6587\u672C`);
|
|
11308
|
+
}
|
|
11309
|
+
const path47 = input.path ?? null;
|
|
11310
|
+
const { view, node: node2, output } = await readEditable(kernel, blobs, input.artifactId, path47);
|
|
11311
|
+
if (view.revisionId !== input.revisionId || view.contentRef !== input.contentRef) {
|
|
11312
|
+
throw new ApiError(409, "CONTENT_CONFLICT", "\u5185\u5BB9\u5DF2\u88AB\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6587\u4EF6\u540E\u518D\u4FDD\u5B58");
|
|
11313
|
+
}
|
|
11314
|
+
if (!view.editable) throw new ApiError(400, "NOT_EDITABLE", "\u6B64\u6587\u4EF6\u4E0D\u652F\u6301\u5728\u7EBF\u7F16\u8F91");
|
|
11315
|
+
let contentRef = await blobs.put(bytes2);
|
|
11316
|
+
if (output.contentKind === "manifest") {
|
|
11317
|
+
const manifest = parseManifest(await blobs.get(output.contentRef));
|
|
11318
|
+
contentRef = await blobs.put(serializeManifest(manifest.entries.map((e) => e.path === path47 ? { ...e, hash: contentRef, size: bytes2.length } : e)));
|
|
11319
|
+
}
|
|
11320
|
+
try {
|
|
11321
|
+
await kernel.editArtifactContent({
|
|
11322
|
+
artifactId: input.artifactId,
|
|
11323
|
+
actor,
|
|
11324
|
+
workId: output.workId,
|
|
11325
|
+
outputId: output.id,
|
|
11326
|
+
expectedLatestWorkId: node2.latestWorkId,
|
|
11327
|
+
previousRef: output.contentRef,
|
|
11328
|
+
contentRef,
|
|
11329
|
+
path: path47
|
|
11330
|
+
});
|
|
11331
|
+
} catch (error2) {
|
|
11332
|
+
if (error2.code === "content-conflict") {
|
|
11333
|
+
throw new ApiError(409, "CONTENT_CONFLICT", "\u5185\u5BB9\u5DF2\u88AB\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6587\u4EF6\u540E\u518D\u4FDD\u5B58");
|
|
11334
|
+
}
|
|
11335
|
+
throw error2;
|
|
11336
|
+
}
|
|
11337
|
+
return { ...view, contentRef, text: input.text };
|
|
11338
|
+
}
|
|
11339
|
+
async function readArtifactFile(kernel, blobs, artifactId, path47, expectedRef, revisionId = null) {
|
|
11340
|
+
await kernel.refreshModel();
|
|
11341
|
+
const artifact = kernel.model.artifacts.get(artifactId);
|
|
11342
|
+
const selectedRevision = revisionId ?? artifact?.currentRev;
|
|
11343
|
+
const output = selectedRevision ? kernel.model.revisions.get(selectedRevision) : void 0;
|
|
11344
|
+
if (!artifact || !output || output.artifactId !== artifactId) {
|
|
11345
|
+
throw new ApiError(404, "NOT_FOUND", revisionId !== null ? "\u8BE5\u4EA7\u7269\u7248\u672C\u4E0D\u5B58\u5728" : "\u6B64\u4EA7\u7269\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684\u539F\u6587\u4EF6");
|
|
11346
|
+
}
|
|
11347
|
+
if (expectedRef && output.contentRef !== expectedRef) throw new ApiError(409, "CONTENT_CONFLICT", "\u6587\u4EF6\u5DF2\u66F4\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00");
|
|
11348
|
+
let hash3 = output.contentRef;
|
|
11349
|
+
let name = artifact.title || artifactId;
|
|
11350
|
+
if (output.contentKind === "manifest") {
|
|
11351
|
+
if (!path47) throw new ApiError(400, "PATH_REQUIRED", "\u8BF7\u9009\u62E9\u6587\u4EF6\u5939\u4E2D\u7684\u5177\u4F53\u6587\u4EF6");
|
|
11352
|
+
const entry = parseManifest(await blobs.get(output.contentRef)).entries.find((e) => e.path === path47);
|
|
11353
|
+
if (!entry) throw new ApiError(404, "NOT_FOUND", "\u5305\u5185\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
11354
|
+
hash3 = entry.hash;
|
|
11355
|
+
name = entry.path;
|
|
11356
|
+
if (entry.size !== void 0 && entry.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
11357
|
+
} else if (output.contentKind !== "inline-blob") {
|
|
11358
|
+
throw new ApiError(404, "NOT_FOUND", "\u6B64\u4EA7\u7269\u6CA1\u6709\u53EF\u4E0B\u8F7D\u7684\u539F\u6587\u4EF6");
|
|
11359
|
+
}
|
|
11360
|
+
const meta = await blobs.meta?.(hash3);
|
|
11361
|
+
if (meta && meta.size > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
11362
|
+
try {
|
|
11363
|
+
return { bytes: await blobs.get(hash3), name, contentType: meta?.contentType };
|
|
11364
|
+
} catch {
|
|
11365
|
+
throw new ApiError(404, "NOT_FOUND", "\u5F53\u524D\u516C\u53F8\u4E2D\u627E\u4E0D\u5230\u8BE5\u6587\u4EF6\u6B63\u6587");
|
|
11366
|
+
}
|
|
11367
|
+
}
|
|
11368
|
+
var init_artifact_content2 = __esm({
|
|
11369
|
+
"../server/src/artifact-content.ts"() {
|
|
11370
|
+
"use strict";
|
|
11371
|
+
init_file_limits2();
|
|
11372
|
+
init_src();
|
|
11373
|
+
init_router();
|
|
11374
|
+
}
|
|
11375
|
+
});
|
|
11376
|
+
|
|
11377
|
+
// ../server/src/file-http.ts
|
|
11378
|
+
async function serveFileRequest(req, res, url, engine) {
|
|
11379
|
+
try {
|
|
11380
|
+
if (req.method !== "GET" || url.pathname !== "/api/files/content") throw new ApiError(404, "NOT_FOUND", "\u6587\u4EF6\u63A5\u53E3\u4E0D\u5B58\u5728");
|
|
11381
|
+
const { bytes: bytes2, name, contentType } = await readArtifactFile(
|
|
11382
|
+
engine.kernel,
|
|
11383
|
+
engine.blobs,
|
|
11384
|
+
url.searchParams.get("artifact") ?? "",
|
|
11385
|
+
url.searchParams.get("path"),
|
|
11386
|
+
url.searchParams.get("ref"),
|
|
11387
|
+
url.searchParams.get("revisionId")
|
|
11388
|
+
);
|
|
11389
|
+
if (bytes2.length > currentFileReadMaxBytes()) throw new ApiError(413, "FILE_TOO_LARGE", `\u6587\u4EF6\u8D85\u8FC7 ${currentFileReadMaxBytes() / 1024 / 1024} MiB \u8BFB\u53D6\u9650\u5236`);
|
|
11390
|
+
res.writeHead(200, {
|
|
11391
|
+
"content-type": contentType ?? sniffContentType(bytes2) ?? "application/octet-stream",
|
|
11392
|
+
"content-length": String(bytes2.length),
|
|
11393
|
+
"cache-control": "private, no-store",
|
|
11394
|
+
"x-content-type-options": "nosniff",
|
|
11395
|
+
"content-disposition": `attachment; filename*=UTF-8''${encodeURIComponent(name.split(/[\\/]/).pop() || "file").replace(/['()*]/g, (c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`)}`
|
|
11396
|
+
}).end(Buffer.from(bytes2));
|
|
11397
|
+
} catch (error2) {
|
|
11398
|
+
if (res.destroyed) return;
|
|
11399
|
+
const status = error2 instanceof ApiError ? error2.status : 500;
|
|
11400
|
+
if (!req.complete) {
|
|
11401
|
+
res.setHeader("connection", "close");
|
|
11402
|
+
req.resume();
|
|
11403
|
+
}
|
|
11404
|
+
res.writeHead(status, { "content-type": "application/json", "cache-control": "no-store" }).end(JSON.stringify({
|
|
11405
|
+
error: {
|
|
11406
|
+
code: error2 instanceof ApiError ? error2.code : "FILE_READ_FAILED",
|
|
11407
|
+
message: error2 instanceof ApiError ? error2.message : "\u6587\u4EF6\u8BFB\u53D6\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5"
|
|
11408
|
+
}
|
|
11409
|
+
}));
|
|
11410
|
+
}
|
|
11411
|
+
}
|
|
11412
|
+
var init_file_http = __esm({
|
|
11413
|
+
"../server/src/file-http.ts"() {
|
|
11414
|
+
"use strict";
|
|
11415
|
+
init_src();
|
|
11416
|
+
init_artifact_content2();
|
|
11417
|
+
init_router();
|
|
11418
|
+
init_file_limits2();
|
|
11419
|
+
}
|
|
11420
|
+
});
|
|
11421
|
+
|
|
11422
|
+
// ../server/src/build-info.ts
|
|
11423
|
+
function findRepoRoot() {
|
|
11424
|
+
let dir;
|
|
11425
|
+
try {
|
|
11426
|
+
dir = path15.dirname((0, import_node_url.fileURLToPath)(__esm_import_meta_url));
|
|
11427
|
+
} catch {
|
|
11428
|
+
return null;
|
|
11429
|
+
}
|
|
11430
|
+
for (let i = 0; i < 12; i++) {
|
|
11431
|
+
if (fs13.existsSync(path15.join(dir, ".git"))) return dir;
|
|
11432
|
+
const parent = path15.dirname(dir);
|
|
11433
|
+
if (parent === dir) break;
|
|
11434
|
+
dir = parent;
|
|
11435
|
+
}
|
|
11436
|
+
return null;
|
|
11437
|
+
}
|
|
11438
|
+
function git(root, args) {
|
|
11439
|
+
try {
|
|
11440
|
+
const out = (0, import_node_child_process10.execFileSync)("git", args, {
|
|
11441
|
+
cwd: root,
|
|
11442
|
+
encoding: "utf8",
|
|
11443
|
+
timeout: 3e3,
|
|
11444
|
+
stdio: ["ignore", "pipe", "ignore"]
|
|
11445
|
+
});
|
|
11446
|
+
const v2 = out.trim();
|
|
11447
|
+
return v2 || null;
|
|
11448
|
+
} catch {
|
|
11449
|
+
return null;
|
|
11450
|
+
}
|
|
11451
|
+
}
|
|
11452
|
+
function getBuildInfo() {
|
|
11453
|
+
if (cached) return cached;
|
|
11454
|
+
const envSha = process.env["OASIS_GIT_SHA"]?.trim();
|
|
11455
|
+
const envBranch = process.env["OASIS_GIT_BRANCH"]?.trim();
|
|
11456
|
+
let gitSha = envSha || null;
|
|
11457
|
+
let gitBranch = envBranch || null;
|
|
11458
|
+
if (!gitSha || !gitBranch) {
|
|
11459
|
+
const root = findRepoRoot();
|
|
11460
|
+
if (root) {
|
|
11461
|
+
if (!gitSha) gitSha = git(root, ["rev-parse", "HEAD"]);
|
|
11462
|
+
if (!gitBranch) {
|
|
11463
|
+
const b2 = git(root, ["rev-parse", "--abbrev-ref", "HEAD"]);
|
|
11464
|
+
gitBranch = b2 === "HEAD" ? null : b2;
|
|
11465
|
+
}
|
|
11466
|
+
}
|
|
11467
|
+
}
|
|
11468
|
+
cached = { gitSha, gitBranch, startedAt: STARTED_AT };
|
|
11469
|
+
return cached;
|
|
11470
|
+
}
|
|
11471
|
+
function resetBuildInfoCacheForTest() {
|
|
11472
|
+
cached = void 0;
|
|
11473
|
+
}
|
|
11474
|
+
var import_node_child_process10, fs13, path15, import_node_url, STARTED_AT, cached;
|
|
11475
|
+
var init_build_info = __esm({
|
|
11476
|
+
"../server/src/build-info.ts"() {
|
|
11477
|
+
"use strict";
|
|
11478
|
+
import_node_child_process10 = require("node:child_process");
|
|
11479
|
+
fs13 = __toESM(require("node:fs"), 1);
|
|
11480
|
+
path15 = __toESM(require("node:path"), 1);
|
|
11481
|
+
import_node_url = require("node:url");
|
|
11482
|
+
STARTED_AT = (/* @__PURE__ */ new Date()).toISOString();
|
|
11483
|
+
}
|
|
11484
|
+
});
|
|
11485
|
+
|
|
11486
|
+
// ../server/src/command-policy.ts
|
|
11487
|
+
function classifyCommand(command2) {
|
|
11488
|
+
return COMMAND_POLICY[command2] ?? { risk: "direct" };
|
|
11489
|
+
}
|
|
11490
|
+
var shortId, COMMAND_POLICY;
|
|
11491
|
+
var init_command_policy = __esm({
|
|
11492
|
+
"../server/src/command-policy.ts"() {
|
|
11493
|
+
"use strict";
|
|
11494
|
+
shortId = (v2) => typeof v2 === "string" ? v2.replace(/^artifact:[^:]+:/, "") : String(v2 ?? "?");
|
|
11495
|
+
COMMAND_POLICY = {
|
|
11496
|
+
forceConclude: {
|
|
11497
|
+
risk: "authorize",
|
|
11498
|
+
idempotent: false,
|
|
11499
|
+
effect: (a) => `\u5F3A\u5236\u6536\u53E3\u8282\u70B9 ${shortId(a.artifactId)}\uFF08\u7ED5\u8FC7\u8BC4\u5BA1\u95F8\u76F4\u63A5\u76D6\u91CC\u7A0B\u7891\uFF09`
|
|
11500
|
+
},
|
|
11501
|
+
promote: {
|
|
11502
|
+
risk: "authorize",
|
|
11503
|
+
idempotent: true,
|
|
11504
|
+
effect: (a) => `\u628A\u8282\u70B9 ${shortId(a.artifactId)} \u8F6C\u4E3A\u6301\u4E45\uFF08temp \u2192 persistent\uFF09`
|
|
11505
|
+
},
|
|
11506
|
+
resolveEscalation: {
|
|
11507
|
+
risk: "authorize",
|
|
11508
|
+
idempotent: true,
|
|
11509
|
+
// 重复关同一条是幂等的(kernel.resolveEscalation 内部按 escalationId 去重)
|
|
11510
|
+
// 「关错=静默停摆」的唯一防线是人在卡上一眼看出「关的是哪一条」——escalationId 与 reason 摘要必须上卡。
|
|
11511
|
+
// a 里 escalationId/artifactId 由 server.ts 起草时冻进 commandArgs(已四级解析),保证是真值、非 `?`。
|
|
11512
|
+
effect: (a) => typeof a.gapId === "string" ? `\u91C7\u7528\u65B9\u6848\uFF1A${String(a.reason ?? "")}\uFF1B\u89E3\u51B3\u7F3A\u53E3 ${a.gapId}\uFF1B\u5173\u95ED\u5173\u8054\u4E0A\u62A5 ${String(a.escalationId)}\uFF1B\u7EE7\u7EED\u6267\u884C\uFF1A\u662F\uFF08\u4ECD\u987B\u6EE1\u8DB3\u5176\u4ED6\u963B\u585E\u6761\u4EF6\uFF09` : `\u5173\u95ED\u4E0A\u62A5 ${shortId(a.escalationId)}\uFF08\u8282\u70B9 ${shortId(a.artifactId)}${typeof a.reason === "string" ? `\uFF0C\u7406\u7531\uFF1A${a.reason}` : ""}\uFF09`
|
|
11513
|
+
},
|
|
11514
|
+
gc: {
|
|
11515
|
+
risk: "forbidden",
|
|
11516
|
+
forbiddenReason: "gc \u662F\u56DE\u6536\u5B64\u513F blob \u7684\u57FA\u7840\u8BBE\u65BD\u7EF4\u62A4\uFF0C\u7531 serve \u8FDB\u7A0B/\u4EBA\u7C7B operator \u6267\u884C\uFF0C\u4E0D\u5C5E\u4E8E\u7BA1\u7406\u8005\u80FD\u529B\u8303\u56F4\u3002"
|
|
11517
|
+
}
|
|
11518
|
+
};
|
|
11519
|
+
}
|
|
11520
|
+
});
|
|
11521
|
+
|
|
11472
11522
|
// ../server/src/domains/actors/model-pricing.ts
|
|
11473
11523
|
function lookupInMap(map, prefixKeys, candidates) {
|
|
11474
11524
|
for (const candidate of candidates) {
|
|
@@ -141210,7 +141260,7 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
141210
141260
|
// 队列从 N 变 N+1、随后 conclude 撞 queue not quiescent(本文件「怎么提交」那段注释记的卡死形状)。
|
|
141211
141261
|
...args.action === "review" || integrating || queueTaskDue ? [] : [
|
|
141212
141262
|
``,
|
|
141213
|
-
`### \u4EA4\u4ED8\u65F6\u7684\
|
|
141263
|
+
`### \u4EA4\u4ED8\u65F6\u5199\u7ED9\u4E0B\u6E38\u7684\u6CE8\u610F\u4E8B\u9879`,
|
|
141214
141264
|
`\u4E0B\u9762\u51E0\u9879\u662F\u4EA4\u4ED8\u547D\u4EE4\uFF08\`oasis propose\`\uFF09\u7684\u53C2\u6570\uFF0C\u76F4\u63A5\u52A0\u5728\u90A3\u6761\u547D\u4EE4\u540E\u9762\uFF0C\u548C \`--reason\` \u5199\u5728\u4E00\u8D77\uFF1B\`oasis conclude\` \u53EA\u6536 \`--note\`\uFF0C\u5199\u5728 conclude \u4E0A\u7684\u5176\u5B83\u53C2\u6570\u4E0D\u4F1A\u88AB\u8BB0\u5F55\u3002`,
|
|
141215
141265
|
`\`--reason\` \u5199\u660E\u76F8\u5BF9\u4E0A\u4E00\u7248\u6539\u4E86\u4EC0\u4E48\u3001\u4E3A\u4EC0\u4E48\u3001\u53EF\u80FD\u5F71\u54CD\u4EC0\u4E48\uFF1B\u9996\u6B21\u7248\u672C\u8BF4\u660E\u672C\u7248\u5B8C\u6210\u601D\u8DEF\u548C\u5185\u5BB9\u3002`,
|
|
141216
141266
|
`\u53EA\u6709\u5F53\u524D\u7248\u672C\u5DF2\u7ECF\u8FBE\u5230\u4EA4\u4ED8\u6807\u51C6\u65F6\uFF0C\u624D\u53EF\u4EE5\u8BB0\u5F55\uFF08\u6BCF\u9879\u53EF\u4EE5\u5199\u591A\u6761\uFF0C\u7528\u82F1\u6587\u5206\u53F7 \`;\` \u9694\u5F00\uFF1B\u4EE5\u4E0B\u67D0\u4E00\u9879\u5982\u679C\u6CA1\u6709\u5C31\u4E0D\u5199\uFF0C\u540C\u65F6\u8BE5\u53C2\u6570\u4E5F\u4E0D\u5199\uFF09\uFF1A`,
|
|
@@ -143252,9 +143302,12 @@ ${supplemental.taskAppend.trim()}
|
|
|
143252
143302
|
bundle.files["TASK.md"] += [
|
|
143253
143303
|
"",
|
|
143254
143304
|
"## \u6267\u884C\u6062\u590D\uFF08\u4EC5\u5F53\u524D\u8282\u70B9\uFF09",
|
|
143255
|
-
|
|
143256
|
-
|
|
143257
|
-
"\
|
|
143305
|
+
// 2026-09-24(语菲定稿):进度记录可能比实际慢一步(K-04),换了执行机器时工作目录是新的、
|
|
143306
|
+
// 上一趟写的文件都不在(K-05 第三趟)——两种情况都以工作目录里实际有的文件为准。
|
|
143307
|
+
"\u672C\u8F6E\u662F\u540C\u4E00\u8282\u70B9\u4E0A\u4E00\u6B21\u6267\u884C\u4E2D\u65AD\u540E\u7684\u7EE7\u7EED\u3002\u5F00\u5DE5\u524D\u5148\u8BFB `execution/RESUME.md`\uFF0C\u91CC\u9762\u662F\u4E0A\u4E00\u6B21\u6700\u540E\u8BB0\u4E0B\u7684\u8FDB\u5EA6\uFF1B",
|
|
143308
|
+
"\u518D\u67E5\u770B\u5DE5\u4F5C\u76EE\u5F55\u91CC\u5B9E\u9645\u5DF2\u6709\u7684\u6587\u4EF6\uFF0C\u4EE5\u5B9E\u9645\u60C5\u51B5\u4E3A\u51C6\uFF1A",
|
|
143309
|
+
"- \u8FDB\u5EA6\u91CC\u8BF4\u5DF2\u7ECF\u5199\u597D\u7684\u6587\u4EF6\uFF0C\u5DE5\u4F5C\u76EE\u5F55\u91CC\u8FD8\u5728\u7684\uFF0C\u76F4\u63A5\u63A5\u7740\u7528\uFF1B",
|
|
143310
|
+
"- \u5DE5\u4F5C\u76EE\u5F55\u91CC\u6CA1\u6709\u7684\uFF08\u6BD4\u5982\u8FD9\u6B21\u6362\u4E86\u6267\u884C\u673A\u5668\uFF0C\u5DE5\u4F5C\u76EE\u5F55\u662F\u65B0\u7684\uFF09\uFF0C\u8981\u91CD\u65B0\u5199\u3002",
|
|
143258
143311
|
"\u8FD9\u4EFD\u6062\u590D\u6750\u6599\u4E0D\u662F\u4E0A\u6E38\u8282\u70B9\u7684\u4E1A\u52A1\u4EA4\u63A5\uFF1B\u4E0A\u6E38\u4EA4\u63A5\u4ECD\u4EE5 `inputs/*/_HANDOFF.md` \u4E3A\u51C6\u3002",
|
|
143259
143312
|
""
|
|
143260
143313
|
].join("\n");
|
|
@@ -213845,6 +213898,16 @@ async function startOasisServer(opts) {
|
|
|
213845
213898
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ data: data2 }));
|
|
213846
213899
|
return;
|
|
213847
213900
|
}
|
|
213901
|
+
if (viewName === "design-board") {
|
|
213902
|
+
const artifactId = url.searchParams.get("artifact");
|
|
213903
|
+
if (!artifactId) throw new Error("\u8BE5\u89C6\u56FE\u9700\u8981 artifact \u53C2\u6570");
|
|
213904
|
+
if (!currentCompanyId) throw new Error("\u62FF\u4E0D\u5230\u5F53\u524D\u516C\u53F8\uFF08\u4F1A\u8BDD token \u6CA1\u7B7E\u516C\u53F8\u3001\u8BF7\u6C42\u4E5F\u6CA1\u6307\u5B9A\u516C\u53F8\uFF09\uFF0C\u4E0D\u80FD\u786E\u5B9A\u753B\u677F\u2014\u2014\u4E0D\u56DE\u843D\u5230\u4E0D\u5E26\u516C\u53F8\u7684\u65E7\u753B\u677F\u540D");
|
|
213905
|
+
const artifact = engine.kernel.model.artifacts.get(artifactId);
|
|
213906
|
+
if (!artifact) throw new Error(`artifact \u4E0D\u5B58\u5728: ${artifactId}`);
|
|
213907
|
+
const board = await resolveDesignBoard({ companyId: currentCompanyId, model: engine.kernel.model, blobs: engine.blobs, artifact });
|
|
213908
|
+
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ data: { companyId: currentCompanyId, ...board } }));
|
|
213909
|
+
return;
|
|
213910
|
+
}
|
|
213848
213911
|
const customView = opts.views?.[viewName];
|
|
213849
213912
|
if (customView) {
|
|
213850
213913
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ data: await customView() }));
|
|
@@ -216277,6 +216340,7 @@ var init_server3 = __esm({
|
|
|
216277
216340
|
init_chat_session();
|
|
216278
216341
|
init_chat_system_message();
|
|
216279
216342
|
init_sealed_node_receipt();
|
|
216343
|
+
init_board_key();
|
|
216280
216344
|
init_session_runtime_target();
|
|
216281
216345
|
init_src();
|
|
216282
216346
|
init_src();
|
|
@@ -249291,8 +249355,10 @@ function executionContinuityDomain(service) {
|
|
|
249291
249355
|
router.post("/api/execution-continuity/attempts/:id/checkpoints", async (req) => {
|
|
249292
249356
|
const attemptId = resolveAttemptWriter(req, req.params.id);
|
|
249293
249357
|
const b2 = req.body ?? {};
|
|
249358
|
+
if (b2.pendingSteps === void 0) b2.pendingSteps = [];
|
|
249359
|
+
if (b2.recoverability === void 0) b2.recoverability = "partial";
|
|
249294
249360
|
if (!isStringArray(b2.pendingSteps) || !b2.recoverability || !["full", "partial", "none"].includes(b2.recoverability) || b2.durableRefs !== void 0 && !isRefArray(b2.durableRefs) || b2.completedStepIds !== void 0 && !isStringArray(b2.completedStepIds) || b2.trigger !== void 0 && !AGENT_CHECKPOINT_TRIGGERS.includes(b2.trigger)) {
|
|
249295
|
-
throw new ApiError(400, "BAD_REQUEST", "\
|
|
249361
|
+
throw new ApiError(400, "BAD_REQUEST", "pendingSteps \u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4\uFF1Brecoverability \u53EA\u80FD\u662F full|partial|none");
|
|
249296
249362
|
}
|
|
249297
249363
|
const checkpoint = await service.checkpoint({
|
|
249298
249364
|
attemptId,
|
|
@@ -249412,6 +249478,9 @@ function mergeContinuityRefs2(primary, extra) {
|
|
|
249412
249478
|
}
|
|
249413
249479
|
return out;
|
|
249414
249480
|
}
|
|
249481
|
+
function stripRecoverability(text7) {
|
|
249482
|
+
return text7.replace(/\s*recoverability=\w+/g, "");
|
|
249483
|
+
}
|
|
249415
249484
|
function renderResumePack(pack) {
|
|
249416
249485
|
const lines = [
|
|
249417
249486
|
"# ResumePack",
|
|
@@ -249425,7 +249494,7 @@ function renderResumePack(pack) {
|
|
|
249425
249494
|
lines.push("", "## Previous attempt");
|
|
249426
249495
|
if (!pack.previousAttempt) lines.push("- This is the first attempt.");
|
|
249427
249496
|
else {
|
|
249428
|
-
lines.push(`- Attempt ${pack.previousAttempt.attemptNo ?? "?"}: ${pack.previousHandoff?.summary || pack.previousAttempt.status}`);
|
|
249497
|
+
lines.push(`- Attempt ${pack.previousAttempt.attemptNo ?? "?"}: ${stripRecoverability(pack.previousHandoff?.summary || pack.previousAttempt.status)}`);
|
|
249429
249498
|
const cp = pack.latestCheckpoint;
|
|
249430
249499
|
const recoverySource = pack.recoverySourceAttempt ?? (cp ? pack.previousAttempt : null);
|
|
249431
249500
|
if (cp && recoverySource && recoverySource.id !== pack.previousAttempt.id) {
|
|
@@ -249433,7 +249502,6 @@ function renderResumePack(pack) {
|
|
|
249433
249502
|
}
|
|
249434
249503
|
const done = cp?.completedStepIds ?? [];
|
|
249435
249504
|
const durable = (cp?.durableRefs.length ? cp.durableRefs : pack.previousHandoff?.changedOutputs) ?? [];
|
|
249436
|
-
if (cp) lines.push(`- Recoverability: ${cp.recoverability}`);
|
|
249437
249505
|
if (done.length > 0) lines.push(`- \u4E0A\u4E00\u8D9F\u5DF2\u5B8C\u6210\u7684\u6B65\u9AA4\uFF1A${done.join("\u3001")}`);
|
|
249438
249506
|
for (const ref2 of durable) {
|
|
249439
249507
|
lines.push(` - durable: ${renderRefId(ref2)}${ref2.version ? `@${ref2.version}` : ""}${ref2.label ? ` \u2014 ${ref2.label}` : ""}`);
|
|
@@ -249446,20 +249514,6 @@ function renderResumePack(pack) {
|
|
|
249446
249514
|
);
|
|
249447
249515
|
}
|
|
249448
249516
|
}
|
|
249449
|
-
lines.push("", "## External effects");
|
|
249450
|
-
const effectSummary = pack.externalEffectSummary;
|
|
249451
|
-
if (effectSummary.total === 0) lines.push("- None recorded");
|
|
249452
|
-
else {
|
|
249453
|
-
const totals = effectSummary.totalByStatus;
|
|
249454
|
-
const included = effectSummary.includedByStatus;
|
|
249455
|
-
lines.push(
|
|
249456
|
-
`- ${effectSummary.total} total; showing all ${included.pending} pending, latest ${included.succeeded} of ${totals.succeeded} succeeded, and latest ${included.failed} of ${totals.failed} retryable failed. Older records remain available through the history query.`
|
|
249457
|
-
);
|
|
249458
|
-
}
|
|
249459
|
-
for (const effect of pack.externalEffects) {
|
|
249460
|
-
const action = effect.status === "succeeded" ? "do not repeat" : effect.status === "pending" ? "execution uncertain; reconcile before retry" : "failed; retry allowed";
|
|
249461
|
-
lines.push(`- [${effect.status}/${effect.source}] ${effect.kind} \u2192 ${effect.target} (${action}; key ${effect.idempotencyKey})`);
|
|
249462
|
-
}
|
|
249463
249517
|
const snapshot = Buffer.from(JSON.stringify(pack), "utf8").toString("base64url");
|
|
249464
249518
|
lines.push("", `${RESUME_SNAPSHOT_PREFIX}${snapshot}${RESUME_SNAPSHOT_SUFFIX}`);
|
|
249465
249519
|
return `${lines.join("\n")}
|
|
@@ -249593,7 +249647,7 @@ function renderCoordinatorView(view, taskBackground) {
|
|
|
249593
249647
|
);
|
|
249594
249648
|
if (source.recoveryCheckpoint) {
|
|
249595
249649
|
lines.push(
|
|
249596
|
-
` - Recovery checkpoint: #${source.recoveryCheckpoint.seq}
|
|
249650
|
+
` - Recovery checkpoint: #${source.recoveryCheckpoint.seq} from Attempt ${source.recoveredFromAttempt.attemptNo ?? "?"}`
|
|
249597
249651
|
);
|
|
249598
249652
|
for (const step of source.recoveryCheckpoint.pendingSteps) lines.push(` - Recovery pending: ${step}`);
|
|
249599
249653
|
}
|
|
@@ -249603,14 +249657,14 @@ function renderCoordinatorView(view, taskBackground) {
|
|
|
249603
249657
|
lines.push(` - Recovery Agent handoff (${handoffFrom}): ${source.recoveryHandoff.summary}`);
|
|
249604
249658
|
} else if (source.recoveryHandoff.producedBy === "system_reconstructed") {
|
|
249605
249659
|
lines.push(
|
|
249606
|
-
` - Recovery system reconstruction (${handoffFrom}, not an Agent conclusion): ${source.recoveryHandoff.summary}`
|
|
249660
|
+
` - Recovery system reconstruction (${handoffFrom}, not an Agent conclusion): ${stripRecoverability(source.recoveryHandoff.summary)}`
|
|
249607
249661
|
);
|
|
249608
249662
|
}
|
|
249609
249663
|
}
|
|
249610
249664
|
for (const risk of source.recoveryHandoff?.risks ?? []) lines.push(` - Recovery risk: ${risk}`);
|
|
249611
249665
|
}
|
|
249612
249666
|
if (node2.progress) {
|
|
249613
|
-
lines.push(`- Latest checkpoint
|
|
249667
|
+
lines.push(`- Latest checkpoint at ${node2.progress.lastCheckpointAt}`);
|
|
249614
249668
|
for (const step of node2.progress.pendingSteps) lines.push(` - Pending: ${step}`);
|
|
249615
249669
|
}
|
|
249616
249670
|
if (node2.handoffProducer === "agent" && node2.summary.trim() && !sameCoordinatorText(node2.summary, node2.conclusion)) {
|
|
@@ -277634,6 +277688,7 @@ var init_board_watch = __esm({
|
|
|
277634
277688
|
init_src();
|
|
277635
277689
|
init_src7();
|
|
277636
277690
|
init_src2();
|
|
277691
|
+
init_board_key();
|
|
277637
277692
|
RUN_MARKER_PREFIX = "[od-board-watch run:";
|
|
277638
277693
|
boardWatchRunMarker = (roundKey) => `${RUN_MARKER_PREFIX}${roundKey}]`;
|
|
277639
277694
|
parseRunMarker = (body2) => {
|
|
@@ -277674,6 +277729,12 @@ var init_board_watch = __esm({
|
|
|
277674
277729
|
revisionSourceRun = /* @__PURE__ */ new Map();
|
|
277675
277730
|
/** 因 owner 在做而压着没写的 `<公司>\0<artifactId>`(只为日志只打一次)。 */
|
|
277676
277731
|
deferredLogged = /* @__PURE__ */ new Set();
|
|
277732
|
+
/** 公司 → (revisionId → board.link 正文):解析画板用。revision id 跨公司可能同名,所以按公司分开。 */
|
|
277733
|
+
boardLinks = /* @__PURE__ */ new Map();
|
|
277734
|
+
/** `<公司>\0<artifactId>` → 上次解析画板失败的原文(同样的错只记一次)。 */
|
|
277735
|
+
boardResolveError = /* @__PURE__ */ new Map();
|
|
277736
|
+
/** 已经报过的串板(`<boardKey>\0<公司,…>`),同一组只报一次。 */
|
|
277737
|
+
sharedBoardLogged = /* @__PURE__ */ new Set();
|
|
277677
277738
|
async odGet(path47) {
|
|
277678
277739
|
const fetchImpl = this.deps.fetchImpl ?? fetch;
|
|
277679
277740
|
try {
|
|
@@ -277730,12 +277791,13 @@ var init_board_watch = __esm({
|
|
|
277730
277791
|
async tick(now = Date.now()) {
|
|
277731
277792
|
const { log: log3 } = this.deps;
|
|
277732
277793
|
const denied = [];
|
|
277794
|
+
const boardUsers = /* @__PURE__ */ new Map();
|
|
277733
277795
|
const { listCompanies, kernelFor } = this.deps;
|
|
277734
277796
|
if (listCompanies && kernelFor) {
|
|
277735
277797
|
for (const companyId of await listCompanies()) {
|
|
277736
277798
|
try {
|
|
277737
277799
|
const blobs = this.deps.blobsFor ? await this.deps.blobsFor(companyId) : void 0;
|
|
277738
|
-
await this.tickCompany(companyId, await kernelFor(companyId), now, denied, blobs);
|
|
277800
|
+
await this.tickCompany(companyId, await kernelFor(companyId), now, denied, blobs, boardUsers);
|
|
277739
277801
|
this.companyLastError.delete(companyId);
|
|
277740
277802
|
} catch (err) {
|
|
277741
277803
|
const msg = String(err);
|
|
@@ -277745,8 +277807,9 @@ var init_board_watch = __esm({
|
|
|
277745
277807
|
}
|
|
277746
277808
|
}
|
|
277747
277809
|
} else {
|
|
277748
|
-
await this.tickCompany("", this.deps.kernel, now, denied, this.deps.blobs);
|
|
277810
|
+
await this.tickCompany("", this.deps.kernel, now, denied, this.deps.blobs, boardUsers);
|
|
277749
277811
|
}
|
|
277812
|
+
this.logSharedBoards(boardUsers);
|
|
277750
277813
|
if (denied.length > 0) {
|
|
277751
277814
|
const codes = [...new Set(denied.map((d) => d.status))].join("/");
|
|
277752
277815
|
const eg = denied[0];
|
|
@@ -277756,8 +277819,8 @@ var init_board_watch = __esm({
|
|
|
277756
277819
|
}
|
|
277757
277820
|
}
|
|
277758
277821
|
/** 巡一家公司(company 为空串 = 单 kernel 模式);被拒的板记进 denied,由 tick 统一汇总成一行。 */
|
|
277759
|
-
async tickCompany(company, kernel, now, denied, blobs) {
|
|
277760
|
-
const {
|
|
277822
|
+
async tickCompany(company, kernel, now, denied, blobs, boardUsers) {
|
|
277823
|
+
const { log: log3 } = this.deps;
|
|
277761
277824
|
const graceMs = this.deps.firstLookGraceMs ?? 10 * 6e4;
|
|
277762
277825
|
const maxPerTick = this.deps.maxLettersPerTick ?? 2;
|
|
277763
277826
|
const actor = this.deps.actor ?? "actor:system";
|
|
@@ -277771,8 +277834,12 @@ var init_board_watch = __esm({
|
|
|
277771
277834
|
}
|
|
277772
277835
|
if (a.type !== "design") continue;
|
|
277773
277836
|
if (lifecycleOf(model, a.id) !== "active") continue;
|
|
277774
|
-
const boardKey = boardKeyOf(a.id);
|
|
277775
277837
|
const pinKey = `${company}\0${a.id}`;
|
|
277838
|
+
const boardKey = await this.boardOf(company, model, blobs, a, tag);
|
|
277839
|
+
if (boardKey === null) continue;
|
|
277840
|
+
const users = boardUsers.get(boardKey) ?? [];
|
|
277841
|
+
users.push({ company, artifactId: a.id });
|
|
277842
|
+
boardUsers.set(boardKey, users);
|
|
277776
277843
|
const watchLetters = annotationsOf(model, a.id).filter((x2) => x2.author === actor && x2.body.includes("[od-board-watch "));
|
|
277777
277844
|
const lettered = new Set(watchLetters.map((x2) => parseRunMarker(x2.body)).filter((s2) => s2 !== null));
|
|
277778
277845
|
const recordedSince = watchLetters.reduce((mn, x2) => {
|
|
@@ -277837,6 +277904,43 @@ var init_board_watch = __esm({
|
|
|
277837
277904
|
}
|
|
277838
277905
|
}
|
|
277839
277906
|
}
|
|
277907
|
+
/** 这个产物实际用的画板(与 CLI 同一个解析函数);解析不了(没有公司、装箱单读不到)→ 记一行日志、本轮跳过它。 */
|
|
277908
|
+
async boardOf(company, model, blobs, a, tag) {
|
|
277909
|
+
const errKey = `${company}\0${a.id}`;
|
|
277910
|
+
let cache = this.boardLinks.get(company);
|
|
277911
|
+
if (!cache) this.boardLinks.set(company, cache = /* @__PURE__ */ new Map());
|
|
277912
|
+
try {
|
|
277913
|
+
const { boardKey } = await resolveDesignBoard(
|
|
277914
|
+
{ companyId: company || (this.deps.companyId ?? ""), model, blobs, artifact: a },
|
|
277915
|
+
{ deriveKey: this.deps.boardKeyOf, cache }
|
|
277916
|
+
);
|
|
277917
|
+
this.boardResolveError.delete(errKey);
|
|
277918
|
+
return boardKey;
|
|
277919
|
+
} catch (err) {
|
|
277920
|
+
const msg = String(err);
|
|
277921
|
+
if (this.boardResolveError.get(errKey) !== msg) {
|
|
277922
|
+
this.boardResolveError.set(errKey, msg);
|
|
277923
|
+
this.deps.log?.(`[board-watch] ${tag}${a.id} \u89E3\u6790\u4E0D\u51FA\u753B\u677F\uFF0C\u672C\u8F6E\u8DF3\u8FC7\uFF1A${msg}`);
|
|
277924
|
+
}
|
|
277925
|
+
return null;
|
|
277926
|
+
}
|
|
277927
|
+
}
|
|
277928
|
+
/**
|
|
277929
|
+
* 同一块板这一轮同时是不止一家公司的 design 画板 → 记一行(同一组只记一次)。只会出现在旧规则遗留的存量板上:
|
|
277930
|
+
* 两家同名产物都已经交过稿、board.link 都指向同一块只由 artifactId 起名的旧板。不自动处理,交给人看。
|
|
277931
|
+
*/
|
|
277932
|
+
logSharedBoards(boardUsers) {
|
|
277933
|
+
for (const [boardKey, users] of boardUsers) {
|
|
277934
|
+
const companies = [...new Set(users.map((u) => u.company))].sort();
|
|
277935
|
+
if (companies.length < 2) continue;
|
|
277936
|
+
const key2 = `${boardKey}\0${companies.join(",")}`;
|
|
277937
|
+
if (this.sharedBoardLogged.has(key2)) continue;
|
|
277938
|
+
this.sharedBoardLogged.add(key2);
|
|
277939
|
+
this.deps.log?.(
|
|
277940
|
+
`[board-watch] \u4E32\u677F\uFF1A\u753B\u677F ${boardKey} \u540C\u65F6\u662F ${users.map((u) => `[${u.company}] ${u.artifactId}`).join("\u3001")} \u7684\u753B\u677F\uFF08\u65E7\u547D\u540D\u89C4\u5219\u53EA\u6309\u4EA7\u7269 id \u8D77\u540D\u3001\u4E24\u5BB6\u90FD\u5DF2\u5728\u8FD9\u5757\u677F\u4E0A\u4EA4\u8FC7\u7A3F\uFF09\u3002\u4E24\u5BB6\u4E92\u76F8\u770B\u5F97\u5230\u5BF9\u65B9\u7684\u6750\u6599\u548C\u7A3F\u5B50\uFF0C\u9700\u8981\u4EBA\u5904\u7406\uFF1B\u5DE1\u68C0\u4E0D\u81EA\u52A8\u6539`
|
|
277941
|
+
);
|
|
277942
|
+
}
|
|
277943
|
+
}
|
|
277840
277944
|
/**
|
|
277841
277945
|
* 当前 head 与最近一版装箱单(两者可能不同:head 在跑空壳/被打回时回落)各自 board.link 里的快照来源 runId。
|
|
277842
277946
|
* 读不到(非装箱单、没有 board.link、blob 缺失、占位 status-pull)的不算。
|
|
@@ -278974,6 +279078,7 @@ __export(src_exports2, {
|
|
|
278974
279078
|
knowledgeSearchTokenStream: () => knowledgeSearchTokenStream,
|
|
278975
279079
|
knowledgeSynthesisPrompt: () => knowledgeSynthesisPrompt,
|
|
278976
279080
|
knowledgeTerms: () => knowledgeTerms,
|
|
279081
|
+
latestBoardLink: () => latestBoardLink,
|
|
278977
279082
|
letterBackfillDoneScope: () => letterBackfillDoneScope,
|
|
278978
279083
|
linkChatAttachmentsToWorkOrder: () => linkChatAttachmentsToWorkOrder,
|
|
278979
279084
|
listActiveCoordinatorAgents: () => listActiveCoordinatorAgents,
|
|
@@ -279105,6 +279210,7 @@ __export(src_exports2, {
|
|
|
279105
279210
|
resolveChatItemsTurnId: () => resolveChatItemsTurnId,
|
|
279106
279211
|
resolveCoordinatorProvisionScope: () => resolveCoordinatorProvisionScope,
|
|
279107
279212
|
resolveDefaultCompanyConfig: () => resolveDefaultCompanyConfig,
|
|
279213
|
+
resolveDesignBoard: () => resolveDesignBoard,
|
|
279108
279214
|
resolveDispatchScope: () => resolveDispatchScope,
|
|
279109
279215
|
resolveListenTarget: () => resolveListenTarget,
|
|
279110
279216
|
resolveManagerBinding: () => resolveManagerBinding,
|
|
@@ -279322,6 +279428,7 @@ var init_src11 = __esm({
|
|
|
279322
279428
|
init_connector_tool_versions();
|
|
279323
279429
|
init_agent_manage_guard();
|
|
279324
279430
|
init_board_watch();
|
|
279431
|
+
init_board_key();
|
|
279325
279432
|
init_uncategorized_project();
|
|
279326
279433
|
init_run_settlement();
|
|
279327
279434
|
init_reconcile_terminal_runs();
|
|
@@ -292843,16 +292950,16 @@ var COMMAND_DECLS = {
|
|
|
292843
292950
|
},
|
|
292844
292951
|
"continuity-checkpoint": {
|
|
292845
292952
|
group: "\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09",
|
|
292846
|
-
usage: "oasis continuity-checkpoint --pending <list> --recoverability full|partial|none [--trigger plan_completed|stage_completed] [--refs <json-array>]
|
|
292953
|
+
usage: "oasis continuity-checkpoint [--completed <list>] [--pending <list>] [--recoverability full|partial|none] [--trigger plan_completed|stage_completed] [--refs <json-array>]",
|
|
292847
292954
|
description: "\u4E3A\u5F53\u524D\u6D3E\u53D1 attempt \u8FFD\u52A0\u53EF\u6062\u590D\u68C0\u67E5\u70B9\uFF08\u81EA\u52A8\u4FDD\u7559\u6700\u65B0\u4E94\u4E2A\uFF09\u3002",
|
|
292848
292955
|
flags: [
|
|
292849
|
-
{ name: "pending", desc:
|
|
292850
|
-
{ name: "recoverability", desc: "\u6062\u590D\u7A0B\u5EA6\uFF08full | partial | none\uFF09
|
|
292956
|
+
{ name: "pending", desc: '\u8FD8\u6CA1\u505A\u7684\u6B65\u9AA4\u3002\u5206\u53F7\u5206\u9694 "a; b" \u6216 JSON \u6570\u7EC4\u90FD\u6536\uFF1B\u4E0D\u5199\u6216\u5199\u7A7A = \u6CA1\u6709\u5269\u4F59' },
|
|
292957
|
+
{ name: "recoverability", desc: "\u6062\u590D\u7A0B\u5EA6\uFF08full | partial | none\uFF09\uFF0C\u53EF\u9009\uFF1B\u4E0D\u5199\u6309 partial \u8BB0" },
|
|
292851
292958
|
{ name: "refs", desc: "\u5DF2\u6301\u4E45\u5316\u4EA7\u51FA\u5F15\u7528 JSON array" },
|
|
292852
|
-
{ name: "completed", desc: "\
|
|
292959
|
+
{ name: "completed", desc: "\u5230\u73B0\u5728\u4E3A\u6B62\u786E\u5B9E\u505A\u5B8C\u7684\u6B65\u9AA4\u3002\u5206\u53F7\u5206\u9694\u6216 JSON \u6570\u7EC4\u90FD\u6536" },
|
|
292853
292960
|
{ name: "trigger", desc: "\u7ED3\u6784\u5316\u8FB9\u754C\uFF08plan_completed | stage_completed\uFF1B\u7701\u7565\u4E3A\u666E\u901A agent checkpoint\uFF09" }
|
|
292854
292961
|
],
|
|
292855
|
-
examples: [
|
|
292962
|
+
examples: ['oasis continuity-checkpoint --completed "\u67E5\u5B8C\u5317\u4EAC\u3001\u4E0A\u6D77\u653F\u7B56\uFF0C\u7ED3\u8BBA\u8BB0\u5728 notes.md; \u5199\u597D deliverable/beijing.md" --pending "\u5199 deliverable/shanghai.md; \u5199\u603B\u7ED3.md"']
|
|
292856
292963
|
},
|
|
292857
292964
|
"continuity-effect": {
|
|
292858
292965
|
group: "\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09",
|
|
@@ -294696,7 +294803,7 @@ async function waitForCommandAuthorization(base, headers, draftId, fallback) {
|
|
|
294696
294803
|
}
|
|
294697
294804
|
}
|
|
294698
294805
|
}
|
|
294699
|
-
var CLI_VERSION = "2.2.
|
|
294806
|
+
var CLI_VERSION = "2.2.87" ? "2.2.87" : "dev";
|
|
294700
294807
|
function apiHeaders(token, company) {
|
|
294701
294808
|
const headers = {
|
|
294702
294809
|
authorization: `Bearer ${token}`,
|
|
@@ -295641,9 +295748,10 @@ Trace: ${run.traceRunId}`);
|
|
|
295641
295748
|
break;
|
|
295642
295749
|
}
|
|
295643
295750
|
case "continuity-checkpoint": {
|
|
295751
|
+
const pendingRaw = flags.get("pending");
|
|
295644
295752
|
const result = await api.post("/api/execution-continuity/attempts/current/checkpoints", {
|
|
295645
|
-
pendingSteps:
|
|
295646
|
-
recoverability:
|
|
295753
|
+
pendingSteps: pendingRaw === void 0 || pendingRaw.trim() === "" ? [] : parseStringArrayFlag(pendingRaw, "pending"),
|
|
295754
|
+
...flags.has("recoverability") ? { recoverability: flags.get("recoverability") } : {},
|
|
295647
295755
|
durableRefs: flags.has("refs") ? parseArrayFlag(flags.get("refs"), "refs") : [],
|
|
295648
295756
|
completedStepIds: flags.has("completed") ? parseStringArrayFlag(flags.get("completed"), "completed") : [],
|
|
295649
295757
|
...flags.has("trigger") ? { trigger: flags.get("trigger") } : {}
|
|
@@ -296435,6 +296543,16 @@ ${res.warning}`);
|
|
|
296435
296543
|
}
|
|
296436
296544
|
case "design": {
|
|
296437
296545
|
const sub = positional[0];
|
|
296546
|
+
const resolveBoard = async (artifactId) => {
|
|
296547
|
+
let b2;
|
|
296548
|
+
try {
|
|
296549
|
+
b2 = await api.view("design-board", artifactId);
|
|
296550
|
+
} catch (err) {
|
|
296551
|
+
throw new Error(`\u62FF\u4E0D\u5230 ${artifactId} \u7684\u753B\u677F\uFF08\u753B\u677F\u540D\u8981\u5E26\u5F53\u524D\u516C\u53F8\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}\u3002\u4E0D\u56DE\u843D\u5230\u4E0D\u5E26\u516C\u53F8\u7684\u65E7\u753B\u677F\u540D`);
|
|
296552
|
+
}
|
|
296553
|
+
if (!b2?.companyId || !b2.boardKey) throw new Error(`\u62FF\u4E0D\u5230 ${artifactId} \u7684\u753B\u677F\uFF1A\u670D\u52A1\u7AEF\u6CA1\u7ED9\u51FA\u516C\u53F8\u6216\u753B\u677F\u540D\u3002\u4E0D\u56DE\u843D\u5230\u4E0D\u5E26\u516C\u53F8\u7684\u65E7\u753B\u677F\u540D`);
|
|
296554
|
+
return { boardKey: b2.boardKey, note: b2.source === "board-link" ? "\uFF08\u6CBF\u7528\u5DF2\u4EA4\u7A3F\u8BB0\u5F55\u91CC\u7684\u753B\u677F\uFF09" : "" };
|
|
296555
|
+
};
|
|
296438
296556
|
if (sub === "chat") {
|
|
296439
296557
|
const artifactId = needPos(positional, 1, "oasis design chat <artifactId> --message <t>");
|
|
296440
296558
|
const message = flags.get("message") ?? (["DESIGN_BRIEF.md", "TASK.md"].map((f2) => fs44.existsSync(f2) ? fs44.readFileSync(f2, "utf8") : "").find((s2) => s2.trim()) ?? "");
|
|
@@ -296452,24 +296570,26 @@ ${res.warning}`);
|
|
|
296452
296570
|
}
|
|
296453
296571
|
}
|
|
296454
296572
|
}
|
|
296573
|
+
const board = await resolveBoard(artifactId);
|
|
296455
296574
|
const baseTurnOpts = {
|
|
296456
296575
|
base: odBase,
|
|
296457
296576
|
...od.token ? { token: od.token } : {},
|
|
296458
296577
|
agentId: flags.get("agent") ?? "claude",
|
|
296459
296578
|
artifactId,
|
|
296579
|
+
boardKey: board.boardKey,
|
|
296460
296580
|
title: flags.get("title") ?? artifactId,
|
|
296461
296581
|
message,
|
|
296462
296582
|
...flags.get("system") !== void 0 ? { systemPrompt: flags.get("system") } : {},
|
|
296463
296583
|
...isContinue ? {} : { contextFiles }
|
|
296464
296584
|
};
|
|
296465
296585
|
if (flags.get("async") === "true") {
|
|
296466
|
-
println(`[design] \u753B\u677F ${
|
|
296586
|
+
println(`[design] \u753B\u677F ${board.boardKey}${board.note} \u2190 ${artifactId}\uFF1B${isContinue ? "\u7EED\u8F6E" : "\u9996\u8F6E"}\uFF08--async\uFF09\u2192 od \u5F15\u64CE ${odLabel} \u2026`);
|
|
296467
296587
|
const started = await startDesignChatTurn(baseTurnOpts);
|
|
296468
296588
|
println(`[design] \u5DF2\u4E0B\u5355\uFF1Arun ${started.runId.slice(0, 8)}\uFF08board ${started.boardKey}, \u53EF\u89C1 user \u56DE\u5408 ${started.userMessageId.slice(0, 8)}\uFF09\u3002\u5F15\u64CE\u901A\u5E38\u8981 13\u201344 \u5206\u949F\u3002`);
|
|
296469
296589
|
println(`[design] \u4E0B\u4E00\u6B65\u7ACB\u523B\u6267\u884C\uFF1Aoasis design status ${artifactId} --wait --pull\uFF08\u963B\u585E\u7B49\u8FD9\u4E00\u8F6E\u8DD1\u5B8C\u5E76\u62C9\u8D27\uFF0C\u6700\u957F\u7B49 100 \u5206\u949F\uFF09\u3002\u522B\u4E0B\u5355\u540E\u76F4\u63A5\u7ED3\u675F\u4F1A\u8BDD\uFF0C\u4E5F\u522B\u81EA\u5DF1\u9694\u51E0\u5206\u949F\u624B\u52A8 status\u3002`);
|
|
296470
296590
|
break;
|
|
296471
296591
|
}
|
|
296472
|
-
println(`[design] \u753B\u677F ${
|
|
296592
|
+
println(`[design] \u753B\u677F ${board.boardKey}${board.note} \u2190 ${artifactId}\uFF1B${isContinue ? "\u7EED\u8F6E" : "\u9996\u8F6E"}\u5BF9\u8BDD\u9A71\u52A8 od \u5F15\u64CE ${odLabel} \u2026`);
|
|
296473
296593
|
const turn = await runDesignChatTurn({
|
|
296474
296594
|
...baseTurnOpts,
|
|
296475
296595
|
onLine: (line2) => println(`[od] ${line2.length > 500 ? line2.slice(0, 500) + "\u2026" : line2}`)
|
|
@@ -296484,13 +296604,14 @@ ${res.warning}`);
|
|
|
296484
296604
|
const od = resolveOpenDesignEndpoint(flags.get("od-url"));
|
|
296485
296605
|
const odBase = od.base;
|
|
296486
296606
|
const odFetch = withOdToken(fetch, od.token);
|
|
296607
|
+
const { boardKey } = await resolveBoard(artifactId);
|
|
296487
296608
|
let st;
|
|
296488
296609
|
let waitedForRun = false;
|
|
296489
296610
|
if (flags.get("wait") === "true") {
|
|
296490
296611
|
const timeoutMin = positiveNumberFlag(flags, "wait-timeout", 100);
|
|
296491
296612
|
const intervalSec = positiveNumberFlag(flags, "wait-interval", 20);
|
|
296492
296613
|
const fmt = (ms) => `${Math.floor(ms / 6e4)} \u5206 ${Math.floor(ms % 6e4 / 1e3)} \u79D2`;
|
|
296493
|
-
const waited = await waitBoardSettled(odBase, odFetch,
|
|
296614
|
+
const waited = await waitBoardSettled(odBase, odFetch, boardKey, {
|
|
296494
296615
|
timeoutMs: timeoutMin * 6e4,
|
|
296495
296616
|
intervalMs: intervalSec * 1e3,
|
|
296496
296617
|
// 每次轮询打一行撑 liveness;状态没变只打短的一行,别刷屏
|
|
@@ -296511,7 +296632,7 @@ ${res.warning}`);
|
|
|
296511
296632
|
}
|
|
296512
296633
|
if (waitedForRun) println(`[design] \u753B\u677F\u4E0A\u7684\u8F6E\u6B21\u90FD\u5DF2\u7ED3\u675F\uFF08\u7B49\u4E86 ${fmt(waited.elapsedMs)}\uFF09\u3002`);
|
|
296513
296634
|
} else {
|
|
296514
|
-
st = await fetchBoardStatus(odBase, odFetch,
|
|
296635
|
+
st = await fetchBoardStatus(odBase, odFetch, boardKey);
|
|
296515
296636
|
}
|
|
296516
296637
|
if (!st.boardExists) {
|
|
296517
296638
|
println(`[design] \u753B\u677F ${st.boardKey} \u5C1A\u4E0D\u5B58\u5728\u2014\u2014\u8FD8\u6CA1\u8D77\u8FC7\u4EFB\u4F55\u4E00\u8F6E\u3002\u5F00\u5DE5\uFF1Aoasis design chat ${artifactId} --message "<\u8BBE\u8BA1\u9700\u6C42+\u771F\u5B9E\u6570\u636E>" --async\uFF0C\u968F\u540E oasis design status ${artifactId} --wait --pull`);
|
|
@@ -298652,7 +298773,7 @@ function shimScript() {
|
|
|
298652
298773
|
}
|
|
298653
298774
|
|
|
298654
298775
|
// src/index.ts
|
|
298655
|
-
var PKG_VERSION = true ? "2.2.
|
|
298776
|
+
var PKG_VERSION = true ? "2.2.87" : "dev";
|
|
298656
298777
|
var LOCAL_BIN = localBin();
|
|
298657
298778
|
var NPM_PREFIX = npmPrefix();
|
|
298658
298779
|
var INSTANCE = DEFAULT_INSTANCE;
|