oasis_test 0.1.109 → 0.1.110
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 +184 -28
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4102,12 +4102,15 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
4102
4102
|
// 刻意不写「过去 24 小时发生 N 次」这类统计:任务书是长期提示词,写死的数字会过期变成假话。
|
|
4103
4103
|
`\u4F60\u8FD9\u4E00\u8F6E\u968F\u65F6\u53EF\u80FD\u88AB\u780D\u2014\u2014\u8D85\u65F6\u3001\u989D\u5EA6\u6253\u6EE1\u3001\u8282\u70B9\u6389\u7EBF\u90FD\u4F1A\uFF0C\u800C\u4E14**\u662F\u5E38\u4E8B**\u3002\u771F\u88AB\u780D\u65F6\uFF0C\u4E0B\u4E00\u8D9F\u63A5\u624B\u7684\u4EBA\u53EA\u770B\u5F97\u5230\u300C\u4F60\u4E3A\u4EC0\u4E48\u65AD\u300D\uFF0C\u770B\u4E0D\u5230\u300C\u4F60\u5E72\u5230\u54EA\u300D\u2014\u2014\u9664\u975E\u4F60\u7559\u4E86\u65AD\u70B9\u3002`,
|
|
4104
4104
|
`\u505A\u5B8C\u4E00\u4E2A\u9636\u6BB5\u3001\u6216\u8981\u5F00\u59CB\u4E00\u4EF6\u53EF\u80FD\u5F88\u4E45\u7684\u4E8B\u4E4B\u524D\uFF0C\u987A\u624B\u8BB0\u4E00\u6761\uFF08\u51E0\u79D2\u8FD4\u56DE\uFF0C\u4E0D\u6253\u65AD\u4F60\uFF09\uFF1A`,
|
|
4105
|
+
// ★ 参数必须是 **JSON string array**(CLI 侧 `JSON.parse` 后校验,见 cli.ts parseStringArrayFlag)。
|
|
4106
|
+
// 这里给的是能逐字复制的真例子——写成自然语言一句话会当场抛 `--pending 必须是 JSON string array`。
|
|
4105
4107
|
`\`\`\``,
|
|
4106
4108
|
`oasis continuity-checkpoint --trigger stage_completed \\`,
|
|
4107
|
-
` --completed "\
|
|
4108
|
-
` --pending "\
|
|
4109
|
-
` --recoverability
|
|
4109
|
+
` --completed '["\u8BFB\u9700\u6C42","\u6539 auth \u4E2D\u95F4\u4EF6","\u8DD1\u5355\u6D4B"]' \\`,
|
|
4110
|
+
` --pending '["\u8865\u96C6\u6210\u6D4B\u8BD5","\u5199\u7ED3\u6848\u62A5\u544A"]' \\`,
|
|
4111
|
+
` --recoverability partial`,
|
|
4110
4112
|
`\`\`\``,
|
|
4113
|
+
`\u4E24\u4E2A\u6570\u7EC4\u90FD\u662F JSON\uFF08\u5355\u5F15\u53F7\u5305\u4F4F\u3001\u91CC\u9762\u7528\u53CC\u5F15\u53F7\uFF09\u3002\u6B65\u9AA4\u540D\u7528\u7A33\u5B9A\u7684\u8BF4\u6CD5\u2014\u2014\u91CD\u8DD1\u65F6\u540C\u4E00\u6B65\u7528\u540C\u4E00\u4E2A\u540D\uFF0C\u4E0B\u4E00\u8D9F\u624D\u8BA4\u5F97\u51FA\u54EA\u4E9B\u5DF2\u7ECF\u505A\u5B8C\u3002\`--recoverability\` \u4E09\u9009\u4E00\uFF1A\`full\`=\u63A5\u624B\u7684\u4EBA\u7167\u7740\u5C31\u80FD\u7EED\u4E0A\u3001\`partial\`=\u80FD\u7EED\u4F46\u8981\u91CD\u505A\u4E00\u90E8\u5206\u3001\`none\`=\u7B49\u4E8E\u4ECE\u5934\u518D\u6765\u3002`,
|
|
4111
4114
|
`**\u53EA\u6709\u4F60\u77E5\u9053\u300C\u8FD8\u5269\u4EC0\u4E48\u300D**\u2014\u2014\u7CFB\u7EDF\u80FD\u81EA\u52A8\u8BB0\u4E0B\u4F60\u8DD1\u8FC7\u54EA\u4E9B\u547D\u4EE4\u3001\u4EA4\u5230\u4E86\u54EA\u4E00\u7248\uFF0C\u4F46\u63A8\u4E0D\u51FA\u4F60\u6253\u7B97\u5E72\u4EC0\u4E48\u3002\u522B\u5199\u7A7A\u8BDD\uFF1B\u6CA1\u4EC0\u4E48\u53EF\u5199\u5C31\u4E0D\u5199\uFF0C\u522B\u4E3A\u4E86\u586B\u800C\u586B\u3002`
|
|
4112
4115
|
],
|
|
4113
4116
|
// 兜底(§10):上次失败了 → 明确告诉它发生了什么 + 怎么破(首选 add-revision 拆出去)
|
|
@@ -158906,7 +158909,12 @@ async function cachedDiscovery(key, fn) {
|
|
|
158906
158909
|
if (entry && now < entry.expiresAt) {
|
|
158907
158910
|
return entry.models;
|
|
158908
158911
|
}
|
|
158909
|
-
|
|
158912
|
+
let models;
|
|
158913
|
+
try {
|
|
158914
|
+
models = await fn();
|
|
158915
|
+
} catch {
|
|
158916
|
+
return [];
|
|
158917
|
+
}
|
|
158910
158918
|
modelCache.set(key, { models, expiresAt: now + CACHE_TTL_MS });
|
|
158911
158919
|
return models;
|
|
158912
158920
|
}
|
|
@@ -158976,12 +158984,77 @@ async function discoverCursorModels(bin) {
|
|
|
158976
158984
|
async function discoverOpenCodeModels(bin) {
|
|
158977
158985
|
throw new Error("discoverOpenCodeModels: TODO");
|
|
158978
158986
|
}
|
|
158987
|
+
function isPiDiscoveryNoise(line) {
|
|
158988
|
+
const lower = line.toLowerCase();
|
|
158989
|
+
if (lower.includes("no models match pattern")) return true;
|
|
158990
|
+
if (lower.startsWith("warning:") || lower.startsWith("error:") || lower.startsWith("info:")) return true;
|
|
158991
|
+
return line.includes("`") || lower.includes("--help") || lower.includes("usage:") || lower.includes("unknown flag") || lower.includes("unknown command");
|
|
158992
|
+
}
|
|
158993
|
+
function parsePiModels(output) {
|
|
158994
|
+
const models = [];
|
|
158995
|
+
const seen = /* @__PURE__ */ new Set();
|
|
158996
|
+
for (const raw of output.split("\n")) {
|
|
158997
|
+
const line = raw.trim();
|
|
158998
|
+
if (!line || isPiDiscoveryNoise(line)) continue;
|
|
158999
|
+
const fields = line.split(/\s+/).filter(Boolean);
|
|
159000
|
+
if (fields.length === 0) continue;
|
|
159001
|
+
const first = fields[0];
|
|
159002
|
+
if (first.toLowerCase() === "provider") continue;
|
|
159003
|
+
let id;
|
|
159004
|
+
if (/[:/]/.test(first)) {
|
|
159005
|
+
id = first.replace(":", "/");
|
|
159006
|
+
} else if (fields.length >= 2) {
|
|
159007
|
+
id = `${first}/${fields[1]}`;
|
|
159008
|
+
} else {
|
|
159009
|
+
continue;
|
|
159010
|
+
}
|
|
159011
|
+
const slash = id.indexOf("/");
|
|
159012
|
+
if (slash <= 0 || slash === id.length - 1) continue;
|
|
159013
|
+
if (seen.has(id)) continue;
|
|
159014
|
+
seen.add(id);
|
|
159015
|
+
models.push({ id, label: id, provider: id.slice(0, slash) });
|
|
159016
|
+
}
|
|
159017
|
+
return models;
|
|
159018
|
+
}
|
|
158979
159019
|
async function discoverPiModels(bin) {
|
|
158980
|
-
|
|
159020
|
+
const out = await runCapture(bin ?? "pi", ["--list-models"]);
|
|
159021
|
+
return out === void 0 ? [] : parsePiModels(out);
|
|
158981
159022
|
}
|
|
158982
159023
|
async function discoverAntigravityModels(bin) {
|
|
158983
159024
|
throw new Error("discoverAntigravityModels: TODO");
|
|
158984
159025
|
}
|
|
159026
|
+
async function runCapture(bin, args, timeoutMs = 15e3) {
|
|
159027
|
+
return await new Promise((resolve10) => {
|
|
159028
|
+
let child;
|
|
159029
|
+
try {
|
|
159030
|
+
child = (0, import_node_child_process8.spawn)(bin, args, { stdio: ["ignore", "pipe", "ignore"], env: { ...process.env } });
|
|
159031
|
+
} catch {
|
|
159032
|
+
resolve10(void 0);
|
|
159033
|
+
return;
|
|
159034
|
+
}
|
|
159035
|
+
let out = "";
|
|
159036
|
+
let settled = false;
|
|
159037
|
+
const done = (v2) => {
|
|
159038
|
+
if (!settled) {
|
|
159039
|
+
settled = true;
|
|
159040
|
+
clearTimeout(timer);
|
|
159041
|
+
resolve10(v2);
|
|
159042
|
+
}
|
|
159043
|
+
};
|
|
159044
|
+
const timer = setTimeout(() => {
|
|
159045
|
+
try {
|
|
159046
|
+
child.kill("SIGKILL");
|
|
159047
|
+
} catch {
|
|
159048
|
+
}
|
|
159049
|
+
done(void 0);
|
|
159050
|
+
}, timeoutMs);
|
|
159051
|
+
child.stdout?.on("data", (d) => {
|
|
159052
|
+
out += d.toString();
|
|
159053
|
+
});
|
|
159054
|
+
child.on("error", () => done(void 0));
|
|
159055
|
+
child.on("close", (code) => done(code === 0 ? out : void 0));
|
|
159056
|
+
});
|
|
159057
|
+
}
|
|
158985
159058
|
async function discoverACPModels(bin, provider, args = ["acp"]) {
|
|
158986
159059
|
const child = (() => {
|
|
158987
159060
|
try {
|
|
@@ -166721,12 +166794,11 @@ function systemHandoffFor(run, checkpoint = null, effects = []) {
|
|
|
166721
166794
|
summary: `[system_reconstructed] attempt=${run.id} outcome=${outcome} reason=${terminalReason}; ${progress}`.slice(0, 400),
|
|
166722
166795
|
changedOutputs: structuredClone(run.outputRefs),
|
|
166723
166796
|
unresolvedIssues: [],
|
|
166724
|
-
risks
|
|
166725
|
-
|
|
166726
|
-
|
|
166727
|
-
],
|
|
166797
|
+
// 与 PG 触发器同口径(2026-08-18):risks / verificationGaps 只装业务语义的东西。会话怎么死的
|
|
166798
|
+
// 已在 summary 的 reason= 段里,不再冒充成「交付物的风险」;「没有断点」也不是「验证缺口」。
|
|
166799
|
+
risks: pendingEffects || failedEffects ? [`external effects: pending=${pendingEffects}, failed=${failedEffects}`] : [],
|
|
166728
166800
|
nextActions: structuredClone(checkpoint?.pendingSteps ?? []),
|
|
166729
|
-
verificationGaps:
|
|
166801
|
+
verificationGaps: [],
|
|
166730
166802
|
userHandoff: null,
|
|
166731
166803
|
createdAt: run.endedAt ?? run.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
166732
166804
|
};
|
|
@@ -167116,6 +167188,13 @@ var init_memory_trace_store = __esm({
|
|
|
167116
167188
|
const handoff = this.handoffs.get(attemptId);
|
|
167117
167189
|
return handoff ? structuredClone(handoff) : null;
|
|
167118
167190
|
}
|
|
167191
|
+
async getHandoffByOutputVersion(version2) {
|
|
167192
|
+
const hits = [...this.handoffs.values()].filter((h) => h.changedOutputs.some((ref2) => ref2.version === version2));
|
|
167193
|
+
if (hits.length === 0) return null;
|
|
167194
|
+
let best = hits[0];
|
|
167195
|
+
for (const h of hits.slice(1)) if (h.createdAt >= best.createdAt) best = h;
|
|
167196
|
+
return structuredClone(best);
|
|
167197
|
+
}
|
|
167119
167198
|
async listAttempts(workOrderId) {
|
|
167120
167199
|
return [...this.runs.values()].filter((run) => run.workOrderId === workOrderId && run.nodeId !== null).sort((a, b2) => (a.nodeId ?? "").localeCompare(b2.nodeId ?? "") || (a.attemptNo ?? 0) - (b2.attemptNo ?? 0)).map((run) => this.decorate(structuredClone(run)));
|
|
167121
167200
|
}
|
|
@@ -184040,7 +184119,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
184040
184119
|
version: input.pinnedWorkId,
|
|
184041
184120
|
...upstreamNode?.title ? { label: upstreamNode.title } : {}
|
|
184042
184121
|
}];
|
|
184043
|
-
const deliveredRow =
|
|
184122
|
+
const deliveredRow = await opts.getHandoffByOutputVersion(input.pinnedWorkId).catch(() => null);
|
|
184044
184123
|
const systemHandoff = () => renderDeliveredWorkHandoff({
|
|
184045
184124
|
upstreamNodeId: input.upstreamNodeId,
|
|
184046
184125
|
upstreamTitle: upstreamNode?.title,
|
|
@@ -187722,8 +187801,30 @@ ${ctx.nodeFault}
|
|
|
187722
187801
|
...prov?.connectorCreds && prov.connectorCreds.length > 0 ? { connectorCreds: prov.connectorCreds } : {}
|
|
187723
187802
|
};
|
|
187724
187803
|
this.deps.log?.(`[coordinator] ${logMsg}`);
|
|
187804
|
+
const coordinatorRunId = `coordinate:${runtimeSessionId}`;
|
|
187805
|
+
if (this.deps.recordCoordinatorRun) {
|
|
187806
|
+
await this.deps.recordCoordinatorRun({
|
|
187807
|
+
runId: coordinatorRunId,
|
|
187808
|
+
actorId,
|
|
187809
|
+
artifactId,
|
|
187810
|
+
workOrderId: workspace ?? null,
|
|
187811
|
+
runtimeSessionId,
|
|
187812
|
+
bundleFiles: Object.keys(job.bundle.files)
|
|
187813
|
+
}).catch((error2) => {
|
|
187814
|
+
this.deps.log?.(`[coordinator] \u8D26\u672C\u767B\u8BB0\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u4F1A\u8BDD\uFF09\uFF1A${String(error2)}`);
|
|
187815
|
+
});
|
|
187816
|
+
}
|
|
187725
187817
|
const handle = await this.deps.adapter.spawn(job);
|
|
187726
187818
|
const exit = await new Promise((resolve10) => handle.onExit(resolve10));
|
|
187819
|
+
if (this.deps.finishCoordinatorRun) {
|
|
187820
|
+
await this.deps.finishCoordinatorRun(coordinatorRunId, {
|
|
187821
|
+
status: exit.code === 0 ? "succeeded" : "failed",
|
|
187822
|
+
exitCode: exit.code,
|
|
187823
|
+
...exit.reason ? { exitReason: String(exit.reason) } : {}
|
|
187824
|
+
}).catch((error2) => {
|
|
187825
|
+
this.deps.log?.(`[coordinator] \u8D26\u672C\u6536\u5C3E\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u4F1A\u8BDD\uFF09\uFF1A${String(error2)}`);
|
|
187826
|
+
});
|
|
187827
|
+
}
|
|
187727
187828
|
await this.finalizeStage(token);
|
|
187728
187829
|
this.registerRetained(artifactId, actorId, runtimeSessionId);
|
|
187729
187830
|
return { sessionId: runtimeSessionId, managerActorId: actorId, exit };
|
|
@@ -190889,6 +190990,9 @@ var init_postgres_trace = __esm({
|
|
|
190889
190990
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs ADD COLUMN IF NOT EXISTS part text`);
|
|
190890
190991
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs ADD COLUMN IF NOT EXISTS user_handoff jsonb`);
|
|
190891
190992
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs DROP CONSTRAINT IF EXISTS node_handoffs_summary_check`);
|
|
190993
|
+
await pool.query(
|
|
190994
|
+
`CREATE INDEX IF NOT EXISTS node_handoffs_changed_outputs_idx ON "${s2}".node_handoffs USING GIN (changed_outputs)`
|
|
190995
|
+
);
|
|
190892
190996
|
await pool.query(`
|
|
190893
190997
|
UPDATE "${s2}".node_handoffs h
|
|
190894
190998
|
SET job_key=COALESCE(NULLIF(h.job_key, ''), r.job_key, 'attempt:' || h.attempt_id), part=r.part
|
|
@@ -190998,15 +191102,26 @@ var init_postgres_trace = __esm({
|
|
|
190998
191102
|
END,
|
|
190999
191103
|
400
|
|
191000
191104
|
);
|
|
191105
|
+
-- 2026-08-18\uFF1Arisks / verification_gaps \u53EA\u88C5 **\u4E1A\u52A1\u8BED\u4E49** \u7684\u4E1C\u897F\u3002
|
|
191106
|
+
--
|
|
191107
|
+
-- \u75C5\u6839\uFF1A\u8FD9\u91CC\u539F\u672C\u628A NEW.error_message \u585E\u8FDB risks\u3001\u628A\u300C\u6CA1\u6709\u53EF\u7528\u65AD\u70B9\u300D\u585E\u8FDB verification_gaps\u3002
|
|
191108
|
+
-- \u4E24\u8005\u90FD\u4E0D\u662F\u5B83\u4EEC\u5B57\u9762\u7684\u610F\u601D\u2014\u2014\u7EBF\u4E0A\u771F\u5B9E\u503C\u662F
|
|
191109
|
+
-- risks = ["[success] You've hit your session limit - resets 4:40pm (UTC)"]
|
|
191110
|
+
-- verification_gaps = ["No valid pre-terminal checkpoint was available."]
|
|
191111
|
+
-- \u524D\u8005\u662F\u300C\u8FD9\u6B21\u4F1A\u8BDD\u600E\u4E48\u6B7B\u7684\u300D\uFF0C\u540E\u8005\u662F\u300C\u7CFB\u7EDF\u81EA\u5DF1\u6CA1\u6599\u300D\uFF0C\u90FD\u4E0D\u662F\u300C\u4EA4\u4ED8\u7269\u6709\u4EC0\u4E48\u98CE\u9669 / \u54EA\u91CC\u6CA1\u6838\u9A8C\u300D\u3002
|
|
191112
|
+
-- \u5371\u5BB3\u6709\u4E8C\uFF1A(1) \u4EA4\u4ED8\u6210\u529F\u4E4B\u540E\u4F1A\u8BDD\u624D\u8D85\u65F6\u7684\u60C5\u5F62\uFF0C\u8FD9\u4E9B\u4F1A\u88AB\u586B\u8FDB\u7A7A\u5B57\u6BB5\u5E76 **\u771F\u7684\u88AB\u4E0B\u6E38\u8BFB\u5230**\uFF1B
|
|
191113
|
+
-- (2) \u7EDF\u8BA1\u586B\u5145\u7387\u65F6\u5168\u662F\u566A\u97F3\uFF0C\u770B\u8D77\u6765 80% \u6709\u503C\uFF0C\u5176\u5B9E\u6CA1\u4E00\u6761\u662F\u6267\u884C\u4EBA\u5199\u7684\u3002
|
|
191114
|
+
--
|
|
191115
|
+
-- \u4E24\u6761\u4FE1\u606F\u90FD\u4E0D\u4E22\uFF1A\u7EC8\u6001\u539F\u56E0\u5DF2\u5728 summary \u7684 reason= \u6BB5\u91CC\uFF08terminal_reason \u5C31\u53D6\u81EA
|
|
191116
|
+
-- error_message\uFF09\uFF0C\u300C\u6CA1\u6709\u65AD\u70B9\u300D\u4E5F\u5DF2\u5728 summary \u7684 no valid pre-terminal checkpoint \u91CC\u3002
|
|
191117
|
+
-- \u8FD9\u91CC\u53EA\u662F\u4E0D\u518D\u628A\u5B83\u4EEC\u5192\u5145\u6210\u4E1A\u52A1\u5B57\u6BB5\u3002
|
|
191118
|
+
--
|
|
191119
|
+
-- \u5916\u90E8\u6548\u5E94\u7559\u5728 risks\uFF1A\u534A\u6210\u54C1\u526F\u4F5C\u7528\uFF08\u5DF2\u53D1\u51FA\u7684\u8BF7\u6C42 / \u5EFA\u4E86\u4E00\u534A\u7684\u8D44\u6E90\uFF09\u786E\u5B9E\u662F\u4E0B\u6E38\u8BE5\u77E5\u9053\u7684\u98CE\u9669\u3002
|
|
191001
191120
|
reconstructed_risks :=
|
|
191002
|
-
CASE WHEN NEW.error_message IS NULL THEN '[]'::jsonb
|
|
191003
|
-
ELSE jsonb_build_array(left(NEW.error_message, 400)) END ||
|
|
191004
191121
|
CASE WHEN COALESCE(pending_effects, 0) = 0 AND COALESCE(failed_effects, 0) = 0 THEN '[]'::jsonb
|
|
191005
191122
|
ELSE jsonb_build_array('external effects: pending=' || COALESCE(pending_effects, 0) ||
|
|
191006
191123
|
', failed=' || COALESCE(failed_effects, 0)) END;
|
|
191007
|
-
reconstructed_gaps :=
|
|
191008
|
-
THEN jsonb_build_array('No valid pre-terminal checkpoint was available.')
|
|
191009
|
-
ELSE '[]'::jsonb END;
|
|
191124
|
+
reconstructed_gaps := '[]'::jsonb;
|
|
191010
191125
|
INSERT INTO "${s2}".node_handoffs AS current_handoff
|
|
191011
191126
|
(handoff_id, attempt_id, job_key, part, produced_by, outcome, summary, changed_outputs,
|
|
191012
191127
|
unresolved_issues, risks, next_actions, verification_gaps, user_handoff, created_at)
|
|
@@ -191954,6 +192069,15 @@ var init_postgres_trace = __esm({
|
|
|
191954
192069
|
const r = await this.pool.query(`SELECT * FROM ${this.s}.node_handoffs WHERE attempt_id=$1`, [attemptId]);
|
|
191955
192070
|
return r.rows[0] ? rowToHandoff(r.rows[0]) : null;
|
|
191956
192071
|
}
|
|
192072
|
+
async getHandoffByOutputVersion(version2) {
|
|
192073
|
+
const r = await this.pool.query(
|
|
192074
|
+
`SELECT * FROM ${this.s}.node_handoffs
|
|
192075
|
+
WHERE changed_outputs @> $1::jsonb
|
|
192076
|
+
ORDER BY created_at DESC LIMIT 1`,
|
|
192077
|
+
[JSON.stringify([{ version: version2 }])]
|
|
192078
|
+
);
|
|
192079
|
+
return r.rows[0] ? rowToHandoff(r.rows[0]) : null;
|
|
192080
|
+
}
|
|
191957
192081
|
async listAttempts(workOrderId) {
|
|
191958
192082
|
const r = await this.pool.query(
|
|
191959
192083
|
`SELECT r.*, (SELECT count(*) FROM ${this.s}.agent_tool_calls tc WHERE tc.run_id=r.id)::int AS tool_call_count
|
|
@@ -197142,7 +197266,8 @@ async function startServe(opts) {
|
|
|
197142
197266
|
if (!store) throw new Error(`engine store unavailable for ${companyId}`);
|
|
197143
197267
|
return store.transaction((tx) => tx.loadWorkorder(workOrderId));
|
|
197144
197268
|
},
|
|
197145
|
-
getHandoff: (attemptId) => traceStore.getHandoff(attemptId)
|
|
197269
|
+
getHandoff: (attemptId) => traceStore.getHandoff(attemptId),
|
|
197270
|
+
getHandoffByOutputVersion: (version2) => traceStore.getHandoffByOutputVersion(version2)
|
|
197146
197271
|
}),
|
|
197147
197272
|
executionContinuityInstructions: continuityMode === "off" ? renderBusinessHandoffProtocol() : renderContinuityProtocol(),
|
|
197148
197273
|
// ★ 恢复包注入(2026-08-17):从「只有 resume 实验组才给」改成「只要账本开着就给」——
|
|
@@ -197762,6 +197887,31 @@ ${st.detail}
|
|
|
197762
197887
|
const view = await executionContinuity.service.coordinatorView(workOrderId, defaultCompanyId);
|
|
197763
197888
|
return view ? renderCoordinatorView(view) : null;
|
|
197764
197889
|
},
|
|
197890
|
+
// D2(2026-08-18):协调者会话进执行账本。inputRefs 记下 bundle 里实际发出的文件——
|
|
197891
|
+
// 这是唯一能证明「COORDINATOR_VIEW.md 到底有没有随会话发出去」的痕迹。两处都 fail-open。
|
|
197892
|
+
recordCoordinatorRun: async (input) => {
|
|
197893
|
+
await traceStore.createRun({
|
|
197894
|
+
id: input.runId,
|
|
197895
|
+
actorId: input.actorId,
|
|
197896
|
+
runtimeKind: "claude-code",
|
|
197897
|
+
triggerKind: "intervention",
|
|
197898
|
+
artifactId: input.artifactId,
|
|
197899
|
+
nodeId: input.artifactId,
|
|
197900
|
+
workOrderId: input.workOrderId,
|
|
197901
|
+
runtimeSessionId: input.runtimeSessionId,
|
|
197902
|
+
jobKey: `coordinate::${input.artifactId}`,
|
|
197903
|
+
action: "coordinate",
|
|
197904
|
+
inputRefs: input.bundleFiles.map((name) => ({ kind: "bundle", id: name }))
|
|
197905
|
+
});
|
|
197906
|
+
},
|
|
197907
|
+
finishCoordinatorRun: async (runId, outcome) => {
|
|
197908
|
+
await traceStore.updateRun(runId, {
|
|
197909
|
+
status: outcome.status,
|
|
197910
|
+
exitCode: outcome.exitCode,
|
|
197911
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
197912
|
+
...outcome.exitReason ? { exitReason: outcome.exitReason } : {}
|
|
197913
|
+
});
|
|
197914
|
+
},
|
|
197765
197915
|
// 阻塞诊断(proposal D1/D3):派发器运行时信号(queued/fused/backoff/hasInFlight)注入诊断,
|
|
197766
197916
|
// 让协调者把"资源 / 运行时"病因和"图病"分开——资源排队的节点不会被误唤去砍流程。
|
|
197767
197917
|
runtimeSignals: (id) => {
|
|
@@ -199453,13 +199603,13 @@ var COMMAND_DECLS = {
|
|
|
199453
199603
|
},
|
|
199454
199604
|
"continuity-checkpoint": {
|
|
199455
199605
|
group: "\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09",
|
|
199456
|
-
usage: "oasis continuity-checkpoint --pending <
|
|
199606
|
+
usage: "oasis continuity-checkpoint --pending <list> --recoverability full|partial|none [--trigger plan_completed|stage_completed] [--refs <json-array>] [--completed <list>]",
|
|
199457
199607
|
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",
|
|
199458
199608
|
flags: [
|
|
199459
|
-
{ name: "pending", desc:
|
|
199609
|
+
{ name: "pending", desc: `\u5F85\u5B8C\u6210\u6B65\u9AA4\u3002JSON \u6570\u7EC4 '["a","b"]' \u6216\u5206\u53F7\u5206\u9694 "a; b" \u90FD\u6536`, required: true },
|
|
199460
199610
|
{ name: "recoverability", desc: "\u6062\u590D\u7A0B\u5EA6\uFF08full | partial | none\uFF09", required: true },
|
|
199461
199611
|
{ name: "refs", desc: "\u5DF2\u6301\u4E45\u5316\u4EA7\u51FA\u5F15\u7528 JSON array" },
|
|
199462
|
-
{ name: "completed", desc: "\u5DF2\u5B8C\u6210\u7A33\u5B9A\u6B65\u9AA4 id
|
|
199612
|
+
{ name: "completed", desc: "\u5DF2\u5B8C\u6210\u7684\u7A33\u5B9A\u6B65\u9AA4 id\u3002JSON \u6570\u7EC4\u6216\u5206\u53F7\u5206\u9694\u90FD\u6536" },
|
|
199463
199613
|
{ name: "trigger", desc: "\u7ED3\u6784\u5316\u8FB9\u754C\uFF08plan_completed | stage_completed\uFF1B\u7701\u7565\u4E3A\u666E\u901A agent checkpoint\uFF09" }
|
|
199464
199614
|
],
|
|
199465
199615
|
examples: [`oasis continuity-checkpoint --pending '["run tests"]' --recoverability full --refs '[{"kind":"file","id":"src/x.ts"}]'`]
|
|
@@ -200572,6 +200722,19 @@ function semicolonList(raw, field) {
|
|
|
200572
200722
|
const items = raw.split(";").map((x2) => x2.trim()).filter(Boolean);
|
|
200573
200723
|
return items.length > 0 ? { [field]: items } : {};
|
|
200574
200724
|
}
|
|
200725
|
+
function parseStringArrayFlag(value, name) {
|
|
200726
|
+
const trimmed = value.trim();
|
|
200727
|
+
if (trimmed.startsWith("[")) {
|
|
200728
|
+
const parsed = JSON.parse(trimmed);
|
|
200729
|
+
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
|
|
200730
|
+
throw new Error(`--${name} \u5FC5\u987B\u662F JSON string array`);
|
|
200731
|
+
}
|
|
200732
|
+
return parsed;
|
|
200733
|
+
}
|
|
200734
|
+
const items = trimmed.split(";").map((x2) => x2.trim()).filter(Boolean);
|
|
200735
|
+
if (items.length === 0) throw new Error(`--${name} \u4E0D\u80FD\u4E3A\u7A7A\uFF08JSON string array\uFF0C\u6216\u5206\u53F7\u5206\u9694\uFF09`);
|
|
200736
|
+
return items;
|
|
200737
|
+
}
|
|
200575
200738
|
async function readStdin() {
|
|
200576
200739
|
if (process.stdin.isTTY) return "";
|
|
200577
200740
|
const chunks = [];
|
|
@@ -201132,13 +201295,6 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
201132
201295
|
}
|
|
201133
201296
|
return parsed;
|
|
201134
201297
|
};
|
|
201135
|
-
const parseStringArrayFlag = (value, name) => {
|
|
201136
|
-
const parsed = JSON.parse(value);
|
|
201137
|
-
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
|
|
201138
|
-
throw new Error(`--${name} \u5FC5\u987B\u662F JSON string array`);
|
|
201139
|
-
}
|
|
201140
|
-
return parsed;
|
|
201141
|
-
};
|
|
201142
201298
|
const parseArrayFlag = (value, name) => {
|
|
201143
201299
|
const parsed = JSON.parse(value);
|
|
201144
201300
|
if (!Array.isArray(parsed)) throw new Error(`--${name} \u5FC5\u987B\u662F JSON array`);
|
|
@@ -203242,7 +203398,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
203242
203398
|
}
|
|
203243
203399
|
|
|
203244
203400
|
// src/index.ts
|
|
203245
|
-
var PKG_VERSION = true ? "0.1.
|
|
203401
|
+
var PKG_VERSION = true ? "0.1.110" : "dev";
|
|
203246
203402
|
var OASIS_DIR = path28.join(os11.homedir(), ".oasis");
|
|
203247
203403
|
var CONFIG_FILE = path28.join(OASIS_DIR, "node-config.json");
|
|
203248
203404
|
var PID_FILE = path28.join(OASIS_DIR, "node.pid");
|