oasis_test 0.1.109 → 0.1.111
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 +342 -35
- 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
|
}
|
|
@@ -171253,6 +171332,79 @@ var init_orphan_sweep = __esm({
|
|
|
171253
171332
|
}
|
|
171254
171333
|
});
|
|
171255
171334
|
|
|
171335
|
+
// ../server/src/zero-output-breaker.ts
|
|
171336
|
+
async function scanZeroOutputBreaker(deps) {
|
|
171337
|
+
const tripped = [];
|
|
171338
|
+
const skipped = [];
|
|
171339
|
+
const countEnabled = deps.threshold > 0;
|
|
171340
|
+
const costEnabled = (deps.costThresholdMicros ?? 0) > 0;
|
|
171341
|
+
if (!countEnabled && !costEnabled) return { tripped, skipped };
|
|
171342
|
+
const sinceIso = new Date(deps.now - deps.windowMs).toISOString();
|
|
171343
|
+
const runs = await deps.listRecentZeroOutputRuns(sinceIso);
|
|
171344
|
+
const buckets = /* @__PURE__ */ new Map();
|
|
171345
|
+
for (const r of runs) {
|
|
171346
|
+
if (r.artifactId === null) continue;
|
|
171347
|
+
if (!deps.actions.has(r.action ?? "")) continue;
|
|
171348
|
+
const startedMs = Date.parse(r.startedAt);
|
|
171349
|
+
if (!Number.isFinite(startedMs)) continue;
|
|
171350
|
+
const b2 = buckets.get(r.artifactId);
|
|
171351
|
+
if (!b2) {
|
|
171352
|
+
buckets.set(r.artifactId, {
|
|
171353
|
+
count: 1,
|
|
171354
|
+
costUsdMicros: r.costUsdMicros ?? 0,
|
|
171355
|
+
latestRunId: r.id,
|
|
171356
|
+
latestStartedMs: startedMs
|
|
171357
|
+
});
|
|
171358
|
+
} else {
|
|
171359
|
+
b2.count += 1;
|
|
171360
|
+
b2.costUsdMicros += r.costUsdMicros ?? 0;
|
|
171361
|
+
if (startedMs >= b2.latestStartedMs) {
|
|
171362
|
+
b2.latestStartedMs = startedMs;
|
|
171363
|
+
b2.latestRunId = r.id;
|
|
171364
|
+
}
|
|
171365
|
+
}
|
|
171366
|
+
}
|
|
171367
|
+
for (const [artifactId, b2] of buckets) {
|
|
171368
|
+
const hitCount = countEnabled && b2.count >= deps.threshold;
|
|
171369
|
+
const hitCost = costEnabled && b2.costUsdMicros >= (deps.costThresholdMicros ?? 0);
|
|
171370
|
+
if (!hitCount && !hitCost) continue;
|
|
171371
|
+
if (deps.isHeld(artifactId) || deps.hasOpenEscalation?.(artifactId)) {
|
|
171372
|
+
skipped.push(artifactId);
|
|
171373
|
+
continue;
|
|
171374
|
+
}
|
|
171375
|
+
const closingRemark = await deps.closingRemarkOf(b2.latestRunId).catch(() => null);
|
|
171376
|
+
await deps.trip({
|
|
171377
|
+
artifactId,
|
|
171378
|
+
count: b2.count,
|
|
171379
|
+
costUsdMicros: b2.costUsdMicros,
|
|
171380
|
+
windowMs: deps.windowMs,
|
|
171381
|
+
latestRunId: b2.latestRunId,
|
|
171382
|
+
closingRemark
|
|
171383
|
+
});
|
|
171384
|
+
tripped.push(artifactId);
|
|
171385
|
+
deps.log?.(
|
|
171386
|
+
`[zero-output-breaker] ${artifactId}\uFF1A\u6700\u8FD1 ${Math.round(deps.windowMs / 6e4)} \u5206\u949F\u5185\u7D2F\u8BA1 ${b2.count} \u6B21\u96F6\u4EA7\u51FA\uFF08\u7EA6 $${(b2.costUsdMicros / 1e6).toFixed(1)}\uFF09\u2192 hold + \u6295\u9012\u6536\u4EF6\u7BB1`
|
|
171387
|
+
);
|
|
171388
|
+
}
|
|
171389
|
+
return { tripped, skipped };
|
|
171390
|
+
}
|
|
171391
|
+
function formatZeroOutputNotice(t) {
|
|
171392
|
+
const usd2 = (t.costUsdMicros / 1e6).toFixed(1);
|
|
171393
|
+
const mins = Math.round(t.windowMs / 6e4);
|
|
171394
|
+
const remark = t.closingRemark && t.closingRemark.trim() ? `
|
|
171395
|
+
|
|
171396
|
+
\u6700\u8FD1\u4E00\u6B21\u8FD0\u884C\u7684\u6536\u5C3E\u53D1\u8A00\uFF08\u5F80\u5F80\u76F4\u63A5\u5199\u7740\u5361\u5728\u54EA\uFF09\uFF1A
|
|
171397
|
+
${t.closingRemark.trim()}` : "";
|
|
171398
|
+
return `\u8FD9\u4E2A\u4EA7\u7269\u5728\u6700\u8FD1 ${mins} \u5206\u949F\u5185\u88AB\u53CD\u590D\u53EB\u9192\u3001\u7D2F\u8BA1\u6709 ${t.count} \u6B21\u8FD0\u884C**\u4EC0\u4E48\u90FD\u6CA1\u4EA4\u51FA\u6765**\uFF08\u8FD9\u4E9B\u7A7A\u8DD1\u7D2F\u8BA1\u82B1\u8D39\u7EA6 $${usd2}\uFF09\uFF0C\u5DF2\u81EA\u52A8\u6682\u505C\u6D3E\u53D1\u4EE5\u6B62\u635F\u3002
|
|
171399
|
+
|
|
171400
|
+
\u8FD9\u4E0D\u662F\u5728\u5224\u67D0\u4E00\u6B21\u8FD0\u884C\u5931\u8D25\u2014\u2014\u662F\u540C\u4E00\u4E2A\u4EA7\u7269\u5728\u8FD9\u6BB5\u65F6\u95F4\u91CC\u53CD\u590D\u96F6\u4EA7\u51FA\u3002\u65E0\u8BBA\u6BCF\u4E00\u6B21\u9000\u51FA\u591A\u4E48\u300C\u6B63\u5E38\u300D\uFF0C\u53CD\u590D\u5230\u8FD9\u4E2A\u6B21\u6570\u901A\u5E38\u610F\u5473\u7740\u5B83\u5361\u5728\u4E00\u4E2A\u53CD\u590D\u91CD\u8BD5\u4E5F\u8FC7\u4E0D\u53BB\u7684\u574E\u4E0A\uFF08\u7F3A\u51ED\u636E\u3001\u4E0A\u6E38\u670D\u52A1\u8FDE\u4E0D\u4E0A\u3001\u6216\u649E\u4E0A\u4E86\u522B\u7684\u6B7B\u5FAA\u73AF\uFF09\u3002\u8BF7\u770B\u4E00\u773C\u6839\u56E0\uFF1B\u5904\u7406\u5B8C\u7528 \`oasis release\` \u6062\u590D\u6D3E\u53D1\u3002` + remark;
|
|
171401
|
+
}
|
|
171402
|
+
var init_zero_output_breaker = __esm({
|
|
171403
|
+
"../server/src/zero-output-breaker.ts"() {
|
|
171404
|
+
"use strict";
|
|
171405
|
+
}
|
|
171406
|
+
});
|
|
171407
|
+
|
|
171256
171408
|
// ../server/src/session-exit-outcome.ts
|
|
171257
171409
|
function isHealthySessionExit(info) {
|
|
171258
171410
|
return info.code === 0 && (info.reason === void 0 || info.reason === "clean");
|
|
@@ -184040,7 +184192,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
184040
184192
|
version: input.pinnedWorkId,
|
|
184041
184193
|
...upstreamNode?.title ? { label: upstreamNode.title } : {}
|
|
184042
184194
|
}];
|
|
184043
|
-
const deliveredRow =
|
|
184195
|
+
const deliveredRow = await opts.getHandoffByOutputVersion(input.pinnedWorkId).catch(() => null);
|
|
184044
184196
|
const systemHandoff = () => renderDeliveredWorkHandoff({
|
|
184045
184197
|
upstreamNodeId: input.upstreamNodeId,
|
|
184046
184198
|
upstreamTitle: upstreamNode?.title,
|
|
@@ -187722,8 +187874,30 @@ ${ctx.nodeFault}
|
|
|
187722
187874
|
...prov?.connectorCreds && prov.connectorCreds.length > 0 ? { connectorCreds: prov.connectorCreds } : {}
|
|
187723
187875
|
};
|
|
187724
187876
|
this.deps.log?.(`[coordinator] ${logMsg}`);
|
|
187877
|
+
const coordinatorRunId = `coordinate:${runtimeSessionId}`;
|
|
187878
|
+
if (this.deps.recordCoordinatorRun) {
|
|
187879
|
+
await this.deps.recordCoordinatorRun({
|
|
187880
|
+
runId: coordinatorRunId,
|
|
187881
|
+
actorId,
|
|
187882
|
+
artifactId,
|
|
187883
|
+
workOrderId: workspace ?? null,
|
|
187884
|
+
runtimeSessionId,
|
|
187885
|
+
bundleFiles: Object.keys(job.bundle.files)
|
|
187886
|
+
}).catch((error2) => {
|
|
187887
|
+
this.deps.log?.(`[coordinator] \u8D26\u672C\u767B\u8BB0\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u4F1A\u8BDD\uFF09\uFF1A${String(error2)}`);
|
|
187888
|
+
});
|
|
187889
|
+
}
|
|
187725
187890
|
const handle = await this.deps.adapter.spawn(job);
|
|
187726
187891
|
const exit = await new Promise((resolve10) => handle.onExit(resolve10));
|
|
187892
|
+
if (this.deps.finishCoordinatorRun) {
|
|
187893
|
+
await this.deps.finishCoordinatorRun(coordinatorRunId, {
|
|
187894
|
+
status: exit.code === 0 ? "succeeded" : "failed",
|
|
187895
|
+
exitCode: exit.code,
|
|
187896
|
+
...exit.reason ? { exitReason: String(exit.reason) } : {}
|
|
187897
|
+
}).catch((error2) => {
|
|
187898
|
+
this.deps.log?.(`[coordinator] \u8D26\u672C\u6536\u5C3E\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u672C\u6B21\u4F1A\u8BDD\uFF09\uFF1A${String(error2)}`);
|
|
187899
|
+
});
|
|
187900
|
+
}
|
|
187727
187901
|
await this.finalizeStage(token);
|
|
187728
187902
|
this.registerRetained(artifactId, actorId, runtimeSessionId);
|
|
187729
187903
|
return { sessionId: runtimeSessionId, managerActorId: actorId, exit };
|
|
@@ -188000,6 +188174,7 @@ var init_src9 = __esm({
|
|
|
188000
188174
|
init_roles_seed();
|
|
188001
188175
|
init_liveness();
|
|
188002
188176
|
init_orphan_sweep();
|
|
188177
|
+
init_zero_output_breaker();
|
|
188003
188178
|
init_dispatch_exit_reconcile();
|
|
188004
188179
|
init_session_exit_outcome();
|
|
188005
188180
|
init_api_activity();
|
|
@@ -190889,6 +191064,9 @@ var init_postgres_trace = __esm({
|
|
|
190889
191064
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs ADD COLUMN IF NOT EXISTS part text`);
|
|
190890
191065
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs ADD COLUMN IF NOT EXISTS user_handoff jsonb`);
|
|
190891
191066
|
await pool.query(`ALTER TABLE "${s2}".node_handoffs DROP CONSTRAINT IF EXISTS node_handoffs_summary_check`);
|
|
191067
|
+
await pool.query(
|
|
191068
|
+
`CREATE INDEX IF NOT EXISTS node_handoffs_changed_outputs_idx ON "${s2}".node_handoffs USING GIN (changed_outputs)`
|
|
191069
|
+
);
|
|
190892
191070
|
await pool.query(`
|
|
190893
191071
|
UPDATE "${s2}".node_handoffs h
|
|
190894
191072
|
SET job_key=COALESCE(NULLIF(h.job_key, ''), r.job_key, 'attempt:' || h.attempt_id), part=r.part
|
|
@@ -190998,15 +191176,26 @@ var init_postgres_trace = __esm({
|
|
|
190998
191176
|
END,
|
|
190999
191177
|
400
|
|
191000
191178
|
);
|
|
191179
|
+
-- 2026-08-18\uFF1Arisks / verification_gaps \u53EA\u88C5 **\u4E1A\u52A1\u8BED\u4E49** \u7684\u4E1C\u897F\u3002
|
|
191180
|
+
--
|
|
191181
|
+
-- \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
|
|
191182
|
+
-- \u4E24\u8005\u90FD\u4E0D\u662F\u5B83\u4EEC\u5B57\u9762\u7684\u610F\u601D\u2014\u2014\u7EBF\u4E0A\u771F\u5B9E\u503C\u662F
|
|
191183
|
+
-- risks = ["[success] You've hit your session limit - resets 4:40pm (UTC)"]
|
|
191184
|
+
-- verification_gaps = ["No valid pre-terminal checkpoint was available."]
|
|
191185
|
+
-- \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
|
|
191186
|
+
-- \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
|
|
191187
|
+
-- (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
|
|
191188
|
+
--
|
|
191189
|
+
-- \u4E24\u6761\u4FE1\u606F\u90FD\u4E0D\u4E22\uFF1A\u7EC8\u6001\u539F\u56E0\u5DF2\u5728 summary \u7684 reason= \u6BB5\u91CC\uFF08terminal_reason \u5C31\u53D6\u81EA
|
|
191190
|
+
-- error_message\uFF09\uFF0C\u300C\u6CA1\u6709\u65AD\u70B9\u300D\u4E5F\u5DF2\u5728 summary \u7684 no valid pre-terminal checkpoint \u91CC\u3002
|
|
191191
|
+
-- \u8FD9\u91CC\u53EA\u662F\u4E0D\u518D\u628A\u5B83\u4EEC\u5192\u5145\u6210\u4E1A\u52A1\u5B57\u6BB5\u3002
|
|
191192
|
+
--
|
|
191193
|
+
-- \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
191194
|
reconstructed_risks :=
|
|
191002
|
-
CASE WHEN NEW.error_message IS NULL THEN '[]'::jsonb
|
|
191003
|
-
ELSE jsonb_build_array(left(NEW.error_message, 400)) END ||
|
|
191004
191195
|
CASE WHEN COALESCE(pending_effects, 0) = 0 AND COALESCE(failed_effects, 0) = 0 THEN '[]'::jsonb
|
|
191005
191196
|
ELSE jsonb_build_array('external effects: pending=' || COALESCE(pending_effects, 0) ||
|
|
191006
191197
|
', 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;
|
|
191198
|
+
reconstructed_gaps := '[]'::jsonb;
|
|
191010
191199
|
INSERT INTO "${s2}".node_handoffs AS current_handoff
|
|
191011
191200
|
(handoff_id, attempt_id, job_key, part, produced_by, outcome, summary, changed_outputs,
|
|
191012
191201
|
unresolved_issues, risks, next_actions, verification_gaps, user_handoff, created_at)
|
|
@@ -191954,6 +192143,15 @@ var init_postgres_trace = __esm({
|
|
|
191954
192143
|
const r = await this.pool.query(`SELECT * FROM ${this.s}.node_handoffs WHERE attempt_id=$1`, [attemptId]);
|
|
191955
192144
|
return r.rows[0] ? rowToHandoff(r.rows[0]) : null;
|
|
191956
192145
|
}
|
|
192146
|
+
async getHandoffByOutputVersion(version2) {
|
|
192147
|
+
const r = await this.pool.query(
|
|
192148
|
+
`SELECT * FROM ${this.s}.node_handoffs
|
|
192149
|
+
WHERE changed_outputs @> $1::jsonb
|
|
192150
|
+
ORDER BY created_at DESC LIMIT 1`,
|
|
192151
|
+
[JSON.stringify([{ version: version2 }])]
|
|
192152
|
+
);
|
|
192153
|
+
return r.rows[0] ? rowToHandoff(r.rows[0]) : null;
|
|
192154
|
+
}
|
|
191957
192155
|
async listAttempts(workOrderId) {
|
|
191958
192156
|
const r = await this.pool.query(
|
|
191959
192157
|
`SELECT r.*, (SELECT count(*) FROM ${this.s}.agent_tool_calls tc WHERE tc.run_id=r.id)::int AS tool_call_count
|
|
@@ -197142,7 +197340,8 @@ async function startServe(opts) {
|
|
|
197142
197340
|
if (!store) throw new Error(`engine store unavailable for ${companyId}`);
|
|
197143
197341
|
return store.transaction((tx) => tx.loadWorkorder(workOrderId));
|
|
197144
197342
|
},
|
|
197145
|
-
getHandoff: (attemptId) => traceStore.getHandoff(attemptId)
|
|
197343
|
+
getHandoff: (attemptId) => traceStore.getHandoff(attemptId),
|
|
197344
|
+
getHandoffByOutputVersion: (version2) => traceStore.getHandoffByOutputVersion(version2)
|
|
197146
197345
|
}),
|
|
197147
197346
|
executionContinuityInstructions: continuityMode === "off" ? renderBusinessHandoffProtocol() : renderContinuityProtocol(),
|
|
197148
197347
|
// ★ 恢复包注入(2026-08-17):从「只有 resume 实验组才给」改成「只要账本开着就给」——
|
|
@@ -197704,6 +197903,7 @@ ${st.detail}
|
|
|
197704
197903
|
let coordTimer;
|
|
197705
197904
|
let livenessTimer;
|
|
197706
197905
|
let orphanSweepTimer;
|
|
197906
|
+
let zeroOutputBreakerTimer;
|
|
197707
197907
|
if (opts.dispatch) {
|
|
197708
197908
|
const coordinator = new CoordinatorWorker({
|
|
197709
197909
|
kernel,
|
|
@@ -197762,6 +197962,31 @@ ${st.detail}
|
|
|
197762
197962
|
const view = await executionContinuity.service.coordinatorView(workOrderId, defaultCompanyId);
|
|
197763
197963
|
return view ? renderCoordinatorView(view) : null;
|
|
197764
197964
|
},
|
|
197965
|
+
// D2(2026-08-18):协调者会话进执行账本。inputRefs 记下 bundle 里实际发出的文件——
|
|
197966
|
+
// 这是唯一能证明「COORDINATOR_VIEW.md 到底有没有随会话发出去」的痕迹。两处都 fail-open。
|
|
197967
|
+
recordCoordinatorRun: async (input) => {
|
|
197968
|
+
await traceStore.createRun({
|
|
197969
|
+
id: input.runId,
|
|
197970
|
+
actorId: input.actorId,
|
|
197971
|
+
runtimeKind: "claude-code",
|
|
197972
|
+
triggerKind: "intervention",
|
|
197973
|
+
artifactId: input.artifactId,
|
|
197974
|
+
nodeId: input.artifactId,
|
|
197975
|
+
workOrderId: input.workOrderId,
|
|
197976
|
+
runtimeSessionId: input.runtimeSessionId,
|
|
197977
|
+
jobKey: `coordinate::${input.artifactId}`,
|
|
197978
|
+
action: "coordinate",
|
|
197979
|
+
inputRefs: input.bundleFiles.map((name) => ({ kind: "bundle", id: name }))
|
|
197980
|
+
});
|
|
197981
|
+
},
|
|
197982
|
+
finishCoordinatorRun: async (runId, outcome) => {
|
|
197983
|
+
await traceStore.updateRun(runId, {
|
|
197984
|
+
status: outcome.status,
|
|
197985
|
+
exitCode: outcome.exitCode,
|
|
197986
|
+
endedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
197987
|
+
...outcome.exitReason ? { exitReason: outcome.exitReason } : {}
|
|
197988
|
+
});
|
|
197989
|
+
},
|
|
197765
197990
|
// 阻塞诊断(proposal D1/D3):派发器运行时信号(queued/fused/backoff/hasInFlight)注入诊断,
|
|
197766
197991
|
// 让协调者把"资源 / 运行时"病因和"图病"分开——资源排队的节点不会被误唤去砍流程。
|
|
197767
197992
|
runtimeSignals: (id) => {
|
|
@@ -197868,6 +198093,80 @@ ${st.detail}
|
|
|
197868
198093
|
}).catch((err) => console.error(`[orphan-sweep] tick \u5931\u8D25: ${String(err)}`));
|
|
197869
198094
|
}, orphanIntervalMs);
|
|
197870
198095
|
}
|
|
198096
|
+
const zbFlag = (process.env["OASIS_ZERO_OUTPUT_BREAKER"] ?? "").trim().toLowerCase();
|
|
198097
|
+
const zbDisabledByEnv = ["0", "false", "off"].includes(zbFlag);
|
|
198098
|
+
const envInt = (name) => {
|
|
198099
|
+
const raw = process.env[name];
|
|
198100
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
198101
|
+
const n = Number(raw.trim());
|
|
198102
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
198103
|
+
};
|
|
198104
|
+
const zbEnabled = opts.zeroOutputBreaker?.enabled ?? !zbDisabledByEnv;
|
|
198105
|
+
const zbIntervalMs = opts.zeroOutputBreaker?.intervalMs ?? 3e4;
|
|
198106
|
+
const zbWindowMs = opts.zeroOutputBreaker?.windowMs ?? (envInt("OASIS_ZERO_OUTPUT_BREAKER_WINDOW_MIN") ?? 30) * 6e4;
|
|
198107
|
+
const zbThreshold = opts.zeroOutputBreaker?.threshold ?? envInt("OASIS_ZERO_OUTPUT_BREAKER_N") ?? 5;
|
|
198108
|
+
const zbCostThresholdMicros = opts.zeroOutputBreaker?.costThresholdMicros ?? (envInt("OASIS_ZERO_OUTPUT_BREAKER_COST_USD") ?? 0) * 1e6;
|
|
198109
|
+
if (zbEnabled && zbIntervalMs > 0 && (zbThreshold > 0 || zbCostThresholdMicros > 0)) {
|
|
198110
|
+
const zbActions = /* @__PURE__ */ new Set(["produce", "review"]);
|
|
198111
|
+
const listRecentZeroOutputRuns = async (sinceIso) => {
|
|
198112
|
+
const page = await traceStore.listRuns({ status: "no-output", from: sinceIso, limit: 1e3 });
|
|
198113
|
+
if (page.nextCursor) console.warn("[zero-output-breaker] no-output run \u8D85 1000 \u6761\u672A\u7FFB\u9875\uFF0C\u672C\u62CD\u53EA\u626B\u9996\u9875");
|
|
198114
|
+
return page.items.map((r) => ({
|
|
198115
|
+
id: r.id,
|
|
198116
|
+
artifactId: r.artifactId,
|
|
198117
|
+
action: r.action,
|
|
198118
|
+
startedAt: r.startedAt,
|
|
198119
|
+
costUsdMicros: r.usage?.costUsdMicros ?? null
|
|
198120
|
+
}));
|
|
198121
|
+
};
|
|
198122
|
+
const latestClosingRemark = async (runId) => {
|
|
198123
|
+
try {
|
|
198124
|
+
let afterSeq = 0;
|
|
198125
|
+
let last = null;
|
|
198126
|
+
let scanned = 0;
|
|
198127
|
+
for (; ; ) {
|
|
198128
|
+
const rows = await traceStore.listEvents(runId, { afterSeq, limit: 500 });
|
|
198129
|
+
if (rows.length === 0) break;
|
|
198130
|
+
for (const e of rows) {
|
|
198131
|
+
if (e.stream !== "model") continue;
|
|
198132
|
+
const payload = e.payload && typeof e.payload === "object" && !Array.isArray(e.payload) ? e.payload : {};
|
|
198133
|
+
const raw = payload["raw"] && typeof payload["raw"] === "object" && !Array.isArray(payload["raw"]) ? payload["raw"] : {};
|
|
198134
|
+
const kind = payload["kind"] ?? raw["kind"];
|
|
198135
|
+
if (kind === "thought") continue;
|
|
198136
|
+
const text = typeof raw["text"] === "string" ? raw["text"] : typeof e.message === "string" ? e.message : null;
|
|
198137
|
+
if (text && text.trim()) last = text;
|
|
198138
|
+
}
|
|
198139
|
+
afterSeq = rows[rows.length - 1].seq;
|
|
198140
|
+
scanned += rows.length;
|
|
198141
|
+
if (rows.length < 500 || scanned >= 5e3) break;
|
|
198142
|
+
}
|
|
198143
|
+
return last ? last.trim().slice(0, 500) : null;
|
|
198144
|
+
} catch {
|
|
198145
|
+
return null;
|
|
198146
|
+
}
|
|
198147
|
+
};
|
|
198148
|
+
zeroOutputBreakerTimer = setInterval(() => {
|
|
198149
|
+
void scanZeroOutputBreaker({
|
|
198150
|
+
now: Date.now(),
|
|
198151
|
+
windowMs: zbWindowMs,
|
|
198152
|
+
threshold: zbThreshold,
|
|
198153
|
+
costThresholdMicros: zbCostThresholdMicros,
|
|
198154
|
+
actions: zbActions,
|
|
198155
|
+
listRecentZeroOutputRuns,
|
|
198156
|
+
isHeld: (artifactId) => isHeld(kernel.model, artifactId),
|
|
198157
|
+
hasOpenEscalation: (artifactId) => unresolvedEscalationsOf(kernel.model, artifactId).length > 0,
|
|
198158
|
+
closingRemarkOf: latestClosingRemark,
|
|
198159
|
+
// 复用 SLA 同一止损出口:escalate(进收件箱)+ hold(source:"sla",挡派发不锁内容)+ 去重。
|
|
198160
|
+
trip: (t) => escalateHold(t.artifactId, formatZeroOutputNotice(t), "\u96F6\u4EA7\u51FA\u4FDD\u9669\u4E1D"),
|
|
198161
|
+
log: (m2) => console.log(m2)
|
|
198162
|
+
}).catch((err) => console.error(`[zero-output-breaker] tick \u5931\u8D25: ${String(err)}`));
|
|
198163
|
+
}, zbIntervalMs);
|
|
198164
|
+
console.log(
|
|
198165
|
+
`[serve] \u96F6\u4EA7\u51FA\u4FDD\u9669\u4E1D\uFF1A\u7A97\u53E3 ${Math.round(zbWindowMs / 6e4)}min\u3001N=${zbThreshold}${zbCostThresholdMicros > 0 ? `\u3001\u82B1\u8D39\u9608\u503C $${(zbCostThresholdMicros / 1e6).toFixed(0)}` : ""}\u3001\u5468\u671F ${Math.round(zbIntervalMs / 1e3)}s`
|
|
198166
|
+
);
|
|
198167
|
+
} else {
|
|
198168
|
+
console.log("[serve] \u96F6\u4EA7\u51FA\u4FDD\u9669\u4E1D\uFF1A\u5DF2\u5173\u95ED");
|
|
198169
|
+
}
|
|
197871
198170
|
}
|
|
197872
198171
|
const automationScheduler = new AutomationScheduler({
|
|
197873
198172
|
store: automationStore,
|
|
@@ -197900,6 +198199,7 @@ ${st.detail}
|
|
|
197900
198199
|
if (coordTimer) clearInterval(coordTimer);
|
|
197901
198200
|
if (livenessTimer) clearInterval(livenessTimer);
|
|
197902
198201
|
if (orphanSweepTimer) clearInterval(orphanSweepTimer);
|
|
198202
|
+
if (zeroOutputBreakerTimer) clearInterval(zeroOutputBreakerTimer);
|
|
197903
198203
|
clearInterval(automationTimer);
|
|
197904
198204
|
if (boardWatchTimer) clearInterval(boardWatchTimer);
|
|
197905
198205
|
clearInterval(serverHeartbeatTimer);
|
|
@@ -197991,13 +198291,14 @@ var KNOWN2 = [
|
|
|
197991
198291
|
{ adapter: "antigravity", binary: "agy" }
|
|
197992
198292
|
];
|
|
197993
198293
|
var NATIVE_APPEND_RUNTIMES = /* @__PURE__ */ new Set(["hermes", "gemini", "kimi", "kiro", "reasonix"]);
|
|
197994
|
-
function
|
|
198294
|
+
function resolveOnPath(binary) {
|
|
197995
198295
|
try {
|
|
197996
198296
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
197997
|
-
(0, import_node_child_process15.execFileSync)(cmd, [binary], { stdio: "ignore" });
|
|
197998
|
-
|
|
198297
|
+
const out = (0, import_node_child_process15.execFileSync)(cmd, [binary], { encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
|
|
198298
|
+
const first = out.split("\n")[0]?.trim();
|
|
198299
|
+
return first || binary;
|
|
197999
198300
|
} catch {
|
|
198000
|
-
return
|
|
198301
|
+
return void 0;
|
|
198001
198302
|
}
|
|
198002
198303
|
}
|
|
198003
198304
|
function versionOf(binary) {
|
|
@@ -198012,11 +198313,11 @@ function versionOf(binary) {
|
|
|
198012
198313
|
}
|
|
198013
198314
|
}
|
|
198014
198315
|
function detectRuntimes() {
|
|
198015
|
-
return KNOWN2.
|
|
198016
|
-
const version2 = versionOf(e.
|
|
198316
|
+
return KNOWN2.map((e) => ({ ...e, resolved: resolveOnPath(e.binary) })).filter((e) => e.resolved !== void 0).map((e) => {
|
|
198317
|
+
const version2 = versionOf(e.resolved);
|
|
198017
198318
|
return {
|
|
198018
198319
|
kind: e.adapter,
|
|
198019
|
-
binary: e.
|
|
198320
|
+
binary: e.resolved,
|
|
198020
198321
|
...version2 ? { version: version2 } : {},
|
|
198021
198322
|
...NATIVE_APPEND_RUNTIMES.has(e.adapter) ? { supportsAppendInput: true } : {}
|
|
198022
198323
|
};
|
|
@@ -199453,13 +199754,13 @@ var COMMAND_DECLS = {
|
|
|
199453
199754
|
},
|
|
199454
199755
|
"continuity-checkpoint": {
|
|
199455
199756
|
group: "\u56FE\u673A\u5236\uFF08\xA76/\xA77\uFF09",
|
|
199456
|
-
usage: "oasis continuity-checkpoint --pending <
|
|
199757
|
+
usage: "oasis continuity-checkpoint --pending <list> --recoverability full|partial|none [--trigger plan_completed|stage_completed] [--refs <json-array>] [--completed <list>]",
|
|
199457
199758
|
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
199759
|
flags: [
|
|
199459
|
-
{ name: "pending", desc:
|
|
199760
|
+
{ 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
199761
|
{ name: "recoverability", desc: "\u6062\u590D\u7A0B\u5EA6\uFF08full | partial | none\uFF09", required: true },
|
|
199461
199762
|
{ 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
|
|
199763
|
+
{ name: "completed", desc: "\u5DF2\u5B8C\u6210\u7684\u7A33\u5B9A\u6B65\u9AA4 id\u3002JSON \u6570\u7EC4\u6216\u5206\u53F7\u5206\u9694\u90FD\u6536" },
|
|
199463
199764
|
{ name: "trigger", desc: "\u7ED3\u6784\u5316\u8FB9\u754C\uFF08plan_completed | stage_completed\uFF1B\u7701\u7565\u4E3A\u666E\u901A agent checkpoint\uFF09" }
|
|
199464
199765
|
],
|
|
199465
199766
|
examples: [`oasis continuity-checkpoint --pending '["run tests"]' --recoverability full --refs '[{"kind":"file","id":"src/x.ts"}]'`]
|
|
@@ -200572,6 +200873,19 @@ function semicolonList(raw, field) {
|
|
|
200572
200873
|
const items = raw.split(";").map((x2) => x2.trim()).filter(Boolean);
|
|
200573
200874
|
return items.length > 0 ? { [field]: items } : {};
|
|
200574
200875
|
}
|
|
200876
|
+
function parseStringArrayFlag(value, name) {
|
|
200877
|
+
const trimmed = value.trim();
|
|
200878
|
+
if (trimmed.startsWith("[")) {
|
|
200879
|
+
const parsed = JSON.parse(trimmed);
|
|
200880
|
+
if (!Array.isArray(parsed) || parsed.some((item) => typeof item !== "string")) {
|
|
200881
|
+
throw new Error(`--${name} \u5FC5\u987B\u662F JSON string array`);
|
|
200882
|
+
}
|
|
200883
|
+
return parsed;
|
|
200884
|
+
}
|
|
200885
|
+
const items = trimmed.split(";").map((x2) => x2.trim()).filter(Boolean);
|
|
200886
|
+
if (items.length === 0) throw new Error(`--${name} \u4E0D\u80FD\u4E3A\u7A7A\uFF08JSON string array\uFF0C\u6216\u5206\u53F7\u5206\u9694\uFF09`);
|
|
200887
|
+
return items;
|
|
200888
|
+
}
|
|
200575
200889
|
async function readStdin() {
|
|
200576
200890
|
if (process.stdin.isTTY) return "";
|
|
200577
200891
|
const chunks = [];
|
|
@@ -201132,13 +201446,6 @@ async function runCli(argv, println = console.log, progressln = console.error) {
|
|
|
201132
201446
|
}
|
|
201133
201447
|
return parsed;
|
|
201134
201448
|
};
|
|
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
201449
|
const parseArrayFlag = (value, name) => {
|
|
201143
201450
|
const parsed = JSON.parse(value);
|
|
201144
201451
|
if (!Array.isArray(parsed)) throw new Error(`--${name} \u5FC5\u987B\u662F JSON array`);
|
|
@@ -203242,7 +203549,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
203242
203549
|
}
|
|
203243
203550
|
|
|
203244
203551
|
// src/index.ts
|
|
203245
|
-
var PKG_VERSION = true ? "0.1.
|
|
203552
|
+
var PKG_VERSION = true ? "0.1.111" : "dev";
|
|
203246
203553
|
var OASIS_DIR = path28.join(os11.homedir(), ".oasis");
|
|
203247
203554
|
var CONFIG_FILE = path28.join(OASIS_DIR, "node-config.json");
|
|
203248
203555
|
var PID_FILE = path28.join(OASIS_DIR, "node.pid");
|