oasis_test 0.1.108 → 0.1.109
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 +291 -53
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4092,7 +4092,23 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
4092
4092
|
`- \`--unresolved\` **\u4F60\u77E5\u9053\u4F46\u6CA1\u89E3\u51B3\u7684** \u2014\u2014 \u514D\u5F97\u4E0B\u6E38\u91CD\u590D\u8E29\u4F60\u5DF2\u7ECF\u8E29\u8FC7\u7684\u5751\u3002\u4F8B\uFF1A\`--unresolved "\u7EBF\u4E0A\u914D\u989D\u6CA1\u786E\u8BA4"\``,
|
|
4093
4093
|
`- \`--risks\` **\u4EA4\u4ED8\u7269\u672C\u8EAB\u6CA1\u9519\u3001\u4F46\u7528\u7684\u65F6\u5019\u8981\u5F53\u5FC3\u7684** \u2014\u2014 \u4F8B\uFF1A\`--risks "\u5E76\u53D1\u8C03\u7528\u53EF\u80FD\u89E6\u53D1\u9650\u6D41"\``,
|
|
4094
4094
|
`- \`--next\` **\u5EFA\u8BAE\u4E0B\u6E38\u5148\u505A\u54EA\u4E00\u6B65**\uFF08\u53EF\u9009\uFF09\u2014\u2014 \u4F8B\uFF1A\`--next "\u5148\u8DD1\u4E00\u6B21\u5C0F\u6D41\u91CF\u7070\u5EA6"\``,
|
|
4095
|
-
`\u5199 \`none\` = \u300C\u6211\u786E\u8BA4\u6CA1\u6709\u300D\uFF1B\u4E0D\u5199 = \u300C\u6CA1\u4EBA\u5199\u8FC7\u300D\u3002**\u8FD9\u4E24\u4EF6\u4E8B\u5BF9\u4E0B\u6E38\u5B8C\u5168\u4E0D\u540C\uFF0C\u522B\u6DF7\u3002
|
|
4095
|
+
`\u5199 \`none\` = \u300C\u6211\u786E\u8BA4\u6CA1\u6709\u300D\uFF1B\u4E0D\u5199 = \u300C\u6CA1\u4EBA\u5199\u8FC7\u300D\u3002**\u8FD9\u4E24\u4EF6\u4E8B\u5BF9\u4E0B\u6E38\u5B8C\u5168\u4E0D\u540C\uFF0C\u522B\u6DF7\u3002**`,
|
|
4096
|
+
``,
|
|
4097
|
+
`### \u4F1A\u8BDD\u53EF\u80FD\u88AB\u780D\uFF1A\u4E2D\u9014\u7559\u4E2A\u65AD\u70B9`,
|
|
4098
|
+
// ★ 2026-08-18:`continuity-checkpoint` 此前在任务书里出现 **0 次**——说明书只在
|
|
4099
|
+
// `execution/CONTINUITY.md`(没人读)和 `oasis help` 里。线上 160 条 checkpoint 只有 6 条带
|
|
4100
|
+
// pendingSteps,且全部来自同一个自己跑 `oasis help continuity-checkpoint` 摸出来的 agent。
|
|
4101
|
+
// 「知道的会用、且用得很好」已被实证,缺的只是这段话。
|
|
4102
|
+
// 刻意不写「过去 24 小时发生 N 次」这类统计:任务书是长期提示词,写死的数字会过期变成假话。
|
|
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
|
+
`\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
|
+
`\`\`\``,
|
|
4106
|
+
`oasis continuity-checkpoint --trigger stage_completed \\`,
|
|
4107
|
+
` --completed "\u5DF2\u5B8C\u6210\u7684\u6B65\u9AA4,\u9017\u53F7\u5206\u9694\uFF08\u7528\u7A33\u5B9A\u7684\u540D\u5B57\uFF0C\u91CD\u8DD1\u65F6\u540C\u4E00\u6B65\u540C\u4E00\u4E2A\u540D\uFF09" \\`,
|
|
4108
|
+
` --pending "\u8FD8\u5269\u4EC0\u4E48\u6CA1\u505A" \\`,
|
|
4109
|
+
` --recoverability full|partial|none`,
|
|
4110
|
+
`\`\`\``,
|
|
4111
|
+
`**\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`
|
|
4096
4112
|
],
|
|
4097
4113
|
// 兜底(§10):上次失败了 → 明确告诉它发生了什么 + 怎么破(首选 add-revision 拆出去)
|
|
4098
4114
|
...args.lastFailure ? args.lastFailure.resumed ? [
|
|
@@ -158863,6 +158879,8 @@ async function listModels(runtime, executablePath) {
|
|
|
158863
158879
|
return cachedDiscovery(runtime, async () => await discoverACPModels(executablePath ?? "kimi", "kimi", ["acp"]) ?? []);
|
|
158864
158880
|
case "kiro":
|
|
158865
158881
|
return cachedDiscovery(runtime, async () => await discoverACPModels(executablePath ?? "kiro-cli", "kiro", ["acp"]) ?? []);
|
|
158882
|
+
case "reasonix":
|
|
158883
|
+
return cachedDiscovery(runtime, async () => await discoverACPModels(executablePath ?? "reasonix", "reasonix", ["acp"]) ?? []);
|
|
158866
158884
|
case "openclaw":
|
|
158867
158885
|
return cachedDiscovery(runtime, () => discoverOpenclawModels(executablePath));
|
|
158868
158886
|
default:
|
|
@@ -160122,6 +160140,20 @@ function joinOutputParts(parts) {
|
|
|
160122
160140
|
if (parts.every((p2) => typeof p2 === "string")) return parts.join("");
|
|
160123
160141
|
return parts;
|
|
160124
160142
|
}
|
|
160143
|
+
function pickApprovalOptionId(params) {
|
|
160144
|
+
const raw = params?.options;
|
|
160145
|
+
if (!Array.isArray(raw)) return LEGACY_APPROVE_OPTION_ID;
|
|
160146
|
+
const options = raw.filter(
|
|
160147
|
+
(o) => typeof o?.optionId === "string"
|
|
160148
|
+
);
|
|
160149
|
+
if (options.length === 0) return LEGACY_APPROVE_OPTION_ID;
|
|
160150
|
+
const byId = options.find((o) => o.optionId === LEGACY_APPROVE_OPTION_ID)?.optionId;
|
|
160151
|
+
const byKind = (kind) => options.find((o) => o.kind === kind)?.optionId;
|
|
160152
|
+
const nonReject = options.find(
|
|
160153
|
+
(o) => !String(o.kind ?? o.optionId).startsWith("reject")
|
|
160154
|
+
)?.optionId;
|
|
160155
|
+
return byId ?? byKind("allow_always") ?? byKind("allow_once") ?? nonReject ?? LEGACY_APPROVE_OPTION_ID;
|
|
160156
|
+
}
|
|
160125
160157
|
function normalizeACPUpdate(data) {
|
|
160126
160158
|
const d = data;
|
|
160127
160159
|
if (!d) return ["", data];
|
|
@@ -160370,7 +160402,8 @@ async function runACPSession(job, cfg) {
|
|
|
160370
160402
|
if (reason === "cancelled") finish({ code: null, reason: "cancelled", transcriptRef });
|
|
160371
160403
|
},
|
|
160372
160404
|
() => streamingCurrentTurn,
|
|
160373
|
-
cfg.finalUsageIsAuthoritative === true
|
|
160405
|
+
cfg.finalUsageIsAuthoritative === true,
|
|
160406
|
+
cfg.vendorUsageNotification
|
|
160374
160407
|
);
|
|
160375
160408
|
usageClient = client;
|
|
160376
160409
|
const rl = readline3.createInterface({ input: child.stdout });
|
|
@@ -160540,7 +160573,7 @@ ${task}` : task;
|
|
|
160540
160573
|
}
|
|
160541
160574
|
};
|
|
160542
160575
|
}
|
|
160543
|
-
var import_node_child_process10, import_node_crypto16, fs11, path11, readline3, ACPClient;
|
|
160576
|
+
var import_node_child_process10, import_node_crypto16, fs11, path11, readline3, ACPClient, LEGACY_APPROVE_OPTION_ID;
|
|
160544
160577
|
var init_acp = __esm({
|
|
160545
160578
|
"../adapters/src/_core/acp.ts"() {
|
|
160546
160579
|
"use strict";
|
|
@@ -160559,13 +160592,14 @@ var init_acp = __esm({
|
|
|
160559
160592
|
init_transcript();
|
|
160560
160593
|
init_filter_extra_args();
|
|
160561
160594
|
ACPClient = class {
|
|
160562
|
-
constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false) {
|
|
160595
|
+
constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false, vendorUsage) {
|
|
160563
160596
|
this.write = write;
|
|
160564
160597
|
this.onOutput = onOutput;
|
|
160565
160598
|
this.onTelemetry = onTelemetry;
|
|
160566
160599
|
this.onStop = onStop;
|
|
160567
160600
|
this.acceptNotification = acceptNotification;
|
|
160568
160601
|
this.finalUsageIsAuthoritative = finalUsageIsAuthoritative;
|
|
160602
|
+
this.vendorUsage = vendorUsage;
|
|
160569
160603
|
}
|
|
160570
160604
|
nextId = 0;
|
|
160571
160605
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -160579,7 +160613,37 @@ var init_acp = __esm({
|
|
|
160579
160613
|
* 是否还在流。每收到一条 session/update / session/notification 就 +1,主循环轮询该值。
|
|
160580
160614
|
*/
|
|
160581
160615
|
notificationCount = 0;
|
|
160616
|
+
/** 厂商私有用量:已完成轮次的累计 + 当前轮的最新快照,两者相加即 this.usage。 */
|
|
160617
|
+
vendorTurnBase = newUsageAcc();
|
|
160618
|
+
vendorTurnSnapshot = newUsageAcc();
|
|
160619
|
+
applyVendorUsage(params) {
|
|
160620
|
+
const picked = this.vendorUsage?.pick(params);
|
|
160621
|
+
if (!picked) return;
|
|
160622
|
+
this.vendorTurnSnapshot = {
|
|
160623
|
+
inputTokens: picked.inputTokens ?? 0,
|
|
160624
|
+
outputTokens: picked.outputTokens ?? 0,
|
|
160625
|
+
cacheReadTokens: picked.cacheReadTokens ?? 0,
|
|
160626
|
+
cacheCreationTokens: picked.cacheCreationTokens ?? 0
|
|
160627
|
+
};
|
|
160628
|
+
this.usage = {
|
|
160629
|
+
inputTokens: this.vendorTurnBase.inputTokens + this.vendorTurnSnapshot.inputTokens,
|
|
160630
|
+
outputTokens: this.vendorTurnBase.outputTokens + this.vendorTurnSnapshot.outputTokens,
|
|
160631
|
+
cacheReadTokens: this.vendorTurnBase.cacheReadTokens + this.vendorTurnSnapshot.cacheReadTokens,
|
|
160632
|
+
cacheCreationTokens: this.vendorTurnBase.cacheCreationTokens + this.vendorTurnSnapshot.cacheCreationTokens
|
|
160633
|
+
};
|
|
160634
|
+
}
|
|
160635
|
+
/** 新一轮 prompt 发出前,把上一轮的快照折进基数(快照是「当前轮」口径,会归零重来)。 */
|
|
160636
|
+
foldVendorTurn() {
|
|
160637
|
+
this.vendorTurnBase = {
|
|
160638
|
+
inputTokens: this.vendorTurnBase.inputTokens + this.vendorTurnSnapshot.inputTokens,
|
|
160639
|
+
outputTokens: this.vendorTurnBase.outputTokens + this.vendorTurnSnapshot.outputTokens,
|
|
160640
|
+
cacheReadTokens: this.vendorTurnBase.cacheReadTokens + this.vendorTurnSnapshot.cacheReadTokens,
|
|
160641
|
+
cacheCreationTokens: this.vendorTurnBase.cacheCreationTokens + this.vendorTurnSnapshot.cacheCreationTokens
|
|
160642
|
+
};
|
|
160643
|
+
this.vendorTurnSnapshot = newUsageAcc();
|
|
160644
|
+
}
|
|
160582
160645
|
request(method, params) {
|
|
160646
|
+
if (this.vendorUsage && method === "session/prompt") this.foldVendorTurn();
|
|
160583
160647
|
const id = this.nextId++;
|
|
160584
160648
|
return new Promise((resolve10, reject) => {
|
|
160585
160649
|
this.pending.set(id, { resolve: resolve10, reject, method });
|
|
@@ -160631,11 +160695,15 @@ var init_acp = __esm({
|
|
|
160631
160695
|
handleAgentRequest(raw) {
|
|
160632
160696
|
const method = raw["method"];
|
|
160633
160697
|
const id = raw["id"];
|
|
160634
|
-
const resp = method === "session/request_permission" ? { jsonrpc: "2.0", id, result: { outcome: { outcome: "selected", optionId: "
|
|
160698
|
+
const resp = method === "session/request_permission" ? { jsonrpc: "2.0", id, result: { outcome: { outcome: "selected", optionId: pickApprovalOptionId(raw["params"]) } } } : { jsonrpc: "2.0", id, error: { code: -32601, message: `method not found: ${method}` } };
|
|
160635
160699
|
this.write(JSON.stringify(resp) + "\n");
|
|
160636
160700
|
}
|
|
160637
160701
|
handleNotification(raw) {
|
|
160638
160702
|
const method = raw["method"];
|
|
160703
|
+
if (this.vendorUsage && method === this.vendorUsage.method) {
|
|
160704
|
+
this.applyVendorUsage(raw["params"]);
|
|
160705
|
+
return;
|
|
160706
|
+
}
|
|
160639
160707
|
if (method !== "session/update" && method !== "session/notification") return;
|
|
160640
160708
|
const params = raw["params"];
|
|
160641
160709
|
if (!params?.update) return;
|
|
@@ -160794,6 +160862,7 @@ var init_acp = __esm({
|
|
|
160794
160862
|
});
|
|
160795
160863
|
}
|
|
160796
160864
|
};
|
|
160865
|
+
LEGACY_APPROVE_OPTION_ID = "approve_for_session";
|
|
160797
160866
|
}
|
|
160798
160867
|
});
|
|
160799
160868
|
|
|
@@ -160895,6 +160964,72 @@ var init_kiro = __esm({
|
|
|
160895
160964
|
}
|
|
160896
160965
|
});
|
|
160897
160966
|
|
|
160967
|
+
// ../adapters/src/reasonix/index.ts
|
|
160968
|
+
var REASONIX_BLOCKED_FLAGS, REASONIX_USAGE_NOTIFICATION, ReasonixAdapter;
|
|
160969
|
+
var init_reasonix = __esm({
|
|
160970
|
+
"../adapters/src/reasonix/index.ts"() {
|
|
160971
|
+
"use strict";
|
|
160972
|
+
init_acp();
|
|
160973
|
+
REASONIX_BLOCKED_FLAGS = /* @__PURE__ */ new Map([
|
|
160974
|
+
["--model", "value"],
|
|
160975
|
+
["--planner", "value"],
|
|
160976
|
+
["--sandbox-network", "value"],
|
|
160977
|
+
["--sandbox-bash", "value"],
|
|
160978
|
+
["--workspace-only", "boolean"]
|
|
160979
|
+
]);
|
|
160980
|
+
REASONIX_USAGE_NOTIFICATION = {
|
|
160981
|
+
method: "_reasonix.io/session/status_update",
|
|
160982
|
+
pick(params) {
|
|
160983
|
+
const rec = (v2) => v2 && typeof v2 === "object" && !Array.isArray(v2) ? v2 : void 0;
|
|
160984
|
+
const num2 = (v2) => typeof v2 === "number" && Number.isFinite(v2) && v2 >= 0 ? v2 : void 0;
|
|
160985
|
+
const turn = rec(rec(rec(rec(params)?.["status"])?.["usage"])?.["turn"]);
|
|
160986
|
+
if (!turn) return void 0;
|
|
160987
|
+
const promptTokens = num2(turn["promptTokens"]);
|
|
160988
|
+
const cacheHit = num2(turn["cacheHitTokens"]);
|
|
160989
|
+
const cacheMiss = num2(turn["cacheMissTokens"]);
|
|
160990
|
+
const inputTokens = cacheMiss ?? (promptTokens === void 0 ? void 0 : Math.max(0, promptTokens - (cacheHit ?? 0)));
|
|
160991
|
+
const outputTokens = num2(turn["completionTokens"]);
|
|
160992
|
+
if (inputTokens === void 0 && outputTokens === void 0 && cacheHit === void 0) return void 0;
|
|
160993
|
+
return {
|
|
160994
|
+
...inputTokens !== void 0 ? { inputTokens } : {},
|
|
160995
|
+
...outputTokens !== void 0 ? { outputTokens } : {},
|
|
160996
|
+
...cacheHit !== void 0 ? { cacheReadTokens: cacheHit } : {}
|
|
160997
|
+
};
|
|
160998
|
+
}
|
|
160999
|
+
};
|
|
161000
|
+
ReasonixAdapter = class {
|
|
161001
|
+
constructor(opts = {}) {
|
|
161002
|
+
this.opts = opts;
|
|
161003
|
+
}
|
|
161004
|
+
/** ADR-0093:ACP 引擎原生支持对话追加(同 session 二次 session/prompt)。 */
|
|
161005
|
+
capabilities = { appendInput: true };
|
|
161006
|
+
spawn(job) {
|
|
161007
|
+
return runACPSession(job, {
|
|
161008
|
+
bin: this.opts.reasonixBin ?? "reasonix",
|
|
161009
|
+
args: [
|
|
161010
|
+
"acp",
|
|
161011
|
+
"--planner",
|
|
161012
|
+
"auto",
|
|
161013
|
+
"--sandbox-network",
|
|
161014
|
+
"auto",
|
|
161015
|
+
"--sandbox-bash",
|
|
161016
|
+
"auto",
|
|
161017
|
+
"--workspace-only"
|
|
161018
|
+
],
|
|
161019
|
+
model: this.opts.model,
|
|
161020
|
+
resumeMethod: "session/resume",
|
|
161021
|
+
vendorUsageNotification: REASONIX_USAGE_NOTIFICATION,
|
|
161022
|
+
blockedFlags: REASONIX_BLOCKED_FLAGS,
|
|
161023
|
+
workRoot: this.opts.workRoot,
|
|
161024
|
+
cleanupWorkdir: this.opts.cleanupWorkdir,
|
|
161025
|
+
env: this.opts.env,
|
|
161026
|
+
extraArgs: this.opts.extraArgs
|
|
161027
|
+
});
|
|
161028
|
+
}
|
|
161029
|
+
};
|
|
161030
|
+
}
|
|
161031
|
+
});
|
|
161032
|
+
|
|
160898
161033
|
// ../adapters/src/_core/subprocess.ts
|
|
160899
161034
|
async function materialize(job, cfg) {
|
|
160900
161035
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
@@ -161975,6 +162110,7 @@ var init_src6 = __esm({
|
|
|
161975
162110
|
init_hermes();
|
|
161976
162111
|
init_kimi();
|
|
161977
162112
|
init_kiro();
|
|
162113
|
+
init_reasonix();
|
|
161978
162114
|
init_cursor();
|
|
161979
162115
|
init_codebuddy();
|
|
161980
162116
|
init_gemini();
|
|
@@ -163962,6 +164098,7 @@ async function startOasisServer(opts) {
|
|
|
163962
164098
|
...tokenClaims.artifactId !== void 0 ? { artifactId: tokenClaims.artifactId } : {},
|
|
163963
164099
|
durableRefs: tokenClaims.artifactId !== void 0 ? [{ kind: "artifact", id: tokenClaims.artifactId, label: body.command }] : [],
|
|
163964
164100
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
164101
|
+
...listArg("pendingSteps") ? { pendingSteps: listArg("pendingSteps") } : {},
|
|
163965
164102
|
...delivered ? { delivered } : {}
|
|
163966
164103
|
});
|
|
163967
164104
|
} catch (error2) {
|
|
@@ -166323,7 +166460,14 @@ var init_memory_registry_store = __esm({
|
|
|
166323
166460
|
this.skillFiles.delete(skillId);
|
|
166324
166461
|
}
|
|
166325
166462
|
async putVariable(v2) {
|
|
166326
|
-
this.
|
|
166463
|
+
const mk = this._varKey(v2.key, v2.actorId, v2.projectId);
|
|
166464
|
+
const ex = this.variables.get(mk);
|
|
166465
|
+
this.variables.set(mk, { ...v2, ...ex?.lastUsedAt !== void 0 ? { lastUsedAt: ex.lastUsedAt } : {} });
|
|
166466
|
+
}
|
|
166467
|
+
async touchVariableUsage(key, actorId, projectId, when) {
|
|
166468
|
+
const mk = this._varKey(key, actorId, projectId);
|
|
166469
|
+
const ex = this.variables.get(mk);
|
|
166470
|
+
if (ex) this.variables.set(mk, { ...ex, lastUsedAt: when });
|
|
166327
166471
|
}
|
|
166328
166472
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
166329
166473
|
const mk = this._varKey(key, actorId);
|
|
@@ -174471,9 +174615,37 @@ ${input.description}
|
|
|
174471
174615
|
// 非连接器写入到此 deliveryMode 必非空(上面已拦);连接器写入沿用 env(其值经 sensitiveVars 剔除,不进 env)。
|
|
174472
174616
|
deliveryMode: v2.deliveryMode ?? "env",
|
|
174473
174617
|
valueEncrypted: v2.encrypted === false ? `plain:${v2.value}` : this.encrypt(v2.value),
|
|
174474
|
-
updatedAt: this.now()
|
|
174618
|
+
updatedAt: this.now(),
|
|
174619
|
+
// ADR 凭据保险库补章 §D2.2:expiresAt 写侧穿透——**显式带 key**(含 undefined),使清空(传空→undefined)
|
|
174620
|
+
// 也落到底(store 两实现都按此覆盖)。lastUsedAt 从不由写侧传,取用时另刷(§D2.3)。
|
|
174621
|
+
expiresAt: v2.expiresAt
|
|
174475
174622
|
});
|
|
174476
174623
|
}
|
|
174624
|
+
/** ADR 凭据保险库补章 §D2.3:某一行变量「明文真被取用」→ 刷 lastUsedAt。行按 (key, actorId?, projectId?)
|
|
174625
|
+
* 唯一键定位(与 put/delete 同址)。store 未实现该方法时静默跳过(不影响主功能)。 */
|
|
174626
|
+
async touchVariableUsage(key, origin, when) {
|
|
174627
|
+
await this.opts.store.touchVariableUsage?.(key, origin?.actorId, origin?.projectId, when ?? this.now());
|
|
174628
|
+
}
|
|
174629
|
+
/**
|
|
174630
|
+
* ADR 凭据保险库补章 §D1.2:**人类控制台** reveal 的取值——不走 agent 的 `resolveActorProvisionEntries`
|
|
174631
|
+
* 解析链(人类既无 personal 变量也无派单 artifactId,那条链恒空)。直接按存储唯一键取该行、解出明文。
|
|
174632
|
+
* - `selector` 由控制台列表行给出(personal 带 actorId、project 带 projectId、global 两者皆空)——
|
|
174633
|
+
* 与 `GET /api/variables`「对所有人类返回全量」的可见口径一致(补章 §D1.3),列得到即 reveal 得到。
|
|
174634
|
+
* - 命中返回明文 + 该行的 origin(供刷 lastUsedAt);未命中(无此行)返回 null(路由映射 403,与 agent 同壳)。
|
|
174635
|
+
*/
|
|
174636
|
+
async revealHumanValue(key, selector) {
|
|
174637
|
+
const wantActor = selector?.actorId;
|
|
174638
|
+
const wantProject = selector?.projectId;
|
|
174639
|
+
const rows = await this.opts.store.listVariables();
|
|
174640
|
+
const row = rows.find(
|
|
174641
|
+
(r) => r.key === key && (r.actorId ?? void 0) === (wantActor ?? void 0) && (r.projectId ?? void 0) === (wantProject ?? void 0)
|
|
174642
|
+
);
|
|
174643
|
+
if (!row) return null;
|
|
174644
|
+
return {
|
|
174645
|
+
value: this.decodeCiphertext(row.valueEncrypted),
|
|
174646
|
+
origin: { ...row.actorId !== void 0 ? { actorId: row.actorId } : {}, ...row.projectId !== void 0 ? { projectId: row.projectId } : {} }
|
|
174647
|
+
};
|
|
174648
|
+
}
|
|
174477
174649
|
/** 更新已有变量的 encrypted 属性(重新加密或解密),不改其他字段 */
|
|
174478
174650
|
async patchVariableEncryption(key, actorId, encrypted) {
|
|
174479
174651
|
const ct = await this.opts.store.getVariableCiphertext(key, actorId);
|
|
@@ -174512,7 +174684,10 @@ ${input.description}
|
|
|
174512
174684
|
// 缺省视为 env(ADR §4.4;存量行读侧统一回填)
|
|
174513
174685
|
encrypted: !isPlain,
|
|
174514
174686
|
maskedValue: isPlain ? r.valueEncrypted.slice(6) : mask(this.decrypt(r.valueEncrypted)),
|
|
174515
|
-
updatedAt: r.updatedAt
|
|
174687
|
+
updatedAt: r.updatedAt,
|
|
174688
|
+
// ADR 凭据保险库补章 §D2.1:到期/取用时间戳透传(展示层据此染色;补章 §D2.4)。
|
|
174689
|
+
...r.expiresAt !== void 0 ? { expiresAt: r.expiresAt } : {},
|
|
174690
|
+
...r.lastUsedAt !== void 0 ? { lastUsedAt: r.lastUsedAt } : {}
|
|
174516
174691
|
};
|
|
174517
174692
|
});
|
|
174518
174693
|
}
|
|
@@ -174605,7 +174780,12 @@ ${input.description}
|
|
|
174605
174780
|
const gated = (row) => !row.connectorId || enabledConnectors.has(row.connectorId);
|
|
174606
174781
|
const put = (row) => {
|
|
174607
174782
|
if (!gated(row)) return;
|
|
174608
|
-
merged.set(row.key, {
|
|
174783
|
+
merged.set(row.key, {
|
|
174784
|
+
key: row.key,
|
|
174785
|
+
value: this.decodeCiphertext(row.valueEncrypted),
|
|
174786
|
+
deliveryMode: row.deliveryMode ?? "env",
|
|
174787
|
+
origin: { ...row.actorId !== void 0 ? { actorId: row.actorId } : {}, ...row.projectId !== void 0 ? { projectId: row.projectId } : {} }
|
|
174788
|
+
});
|
|
174609
174789
|
};
|
|
174610
174790
|
for (const row of rows) {
|
|
174611
174791
|
if (row.scope === "global" && !row.actorId) put(row);
|
|
@@ -174625,7 +174805,7 @@ ${input.description}
|
|
|
174625
174805
|
async resolveRevealValue(actorId, key, opts) {
|
|
174626
174806
|
const entries = await this.resolveActorProvisionEntries(actorId, { ...opts, refreshConnectors: false });
|
|
174627
174807
|
const hit = entries.find((e) => e.key === key);
|
|
174628
|
-
return hit ? { value: hit.value } : null;
|
|
174808
|
+
return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
|
|
174629
174809
|
}
|
|
174630
174810
|
encrypt(plain) {
|
|
174631
174811
|
const iv = (0, import_node_crypto26.randomBytes)(12);
|
|
@@ -175854,6 +176034,21 @@ var init_connector_skills = __esm({
|
|
|
175854
176034
|
function isKnownRevealSource(source) {
|
|
175855
176035
|
return CREDENTIAL_REVEAL_SOURCES.has(source) || source.startsWith("agent-skill:");
|
|
175856
176036
|
}
|
|
176037
|
+
function clientMetaFromReq(req) {
|
|
176038
|
+
const fwd = req.raw?.headers?.["x-forwarded-for"];
|
|
176039
|
+
const fwdFirst = (Array.isArray(fwd) ? fwd[0] : fwd)?.split(",")[0]?.trim();
|
|
176040
|
+
const clientIp = fwdFirst || req.raw?.socket?.remoteAddress || void 0;
|
|
176041
|
+
const ua = req.raw?.headers?.["user-agent"];
|
|
176042
|
+
const userAgent = (Array.isArray(ua) ? ua[0] : ua) || void 0;
|
|
176043
|
+
return { ...clientIp ? { clientIp } : {}, ...userAgent ? { userAgent } : {} };
|
|
176044
|
+
}
|
|
176045
|
+
function normalizeExpiresAt(raw) {
|
|
176046
|
+
if (raw === void 0 || raw === null || raw === "") return void 0;
|
|
176047
|
+
if (typeof raw !== "string") throw new ApiError(400, "BAD_REQUEST", "expiresAt \u987B\u4E3A ISO-8601 \u5B57\u7B26\u4E32");
|
|
176048
|
+
const t = Date.parse(raw);
|
|
176049
|
+
if (Number.isNaN(t)) throw new ApiError(400, "BAD_REQUEST", `expiresAt \u4E0D\u662F\u5408\u6CD5\u65E5\u671F\uFF1A${raw}`);
|
|
176050
|
+
return new Date(t).toISOString();
|
|
176051
|
+
}
|
|
175857
176052
|
function positionsFromPayload(body) {
|
|
175858
176053
|
if (!body) return void 0;
|
|
175859
176054
|
if (Object.prototype.hasOwnProperty.call(body, "roles")) {
|
|
@@ -175888,6 +176083,8 @@ function actorsDomain(opts) {
|
|
|
175888
176083
|
const { resolveCtx } = opts;
|
|
175889
176084
|
const revealLimits = opts.credentialRevealLimits ?? { perSession: 200, perSessionPerKey: 20 };
|
|
175890
176085
|
const revealLimiter = new RevealRateLimiter(revealLimits.perSession, revealLimits.perSessionPerKey);
|
|
176086
|
+
const consoleRevealLimits = opts.credentialRevealLimits?.console ?? { perSession: 60, perSessionPerKey: 10 };
|
|
176087
|
+
const consoleRevealLimiter = new RevealRateLimiter(consoleRevealLimits.perSession, consoleRevealLimits.perSessionPerKey);
|
|
175891
176088
|
return (router) => {
|
|
175892
176089
|
router.get("/api/actors", async (req) => {
|
|
175893
176090
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
@@ -176174,11 +176371,6 @@ function actorsDomain(opts) {
|
|
|
176174
176371
|
}
|
|
176175
176372
|
};
|
|
176176
176373
|
const auditVariableChange = async (req, kind, variableKey, targetScope) => {
|
|
176177
|
-
const fwd = req.raw?.headers?.["x-forwarded-for"];
|
|
176178
|
-
const fwdFirst = (Array.isArray(fwd) ? fwd[0] : fwd)?.split(",")[0]?.trim();
|
|
176179
|
-
const clientIp = fwdFirst || req.raw?.socket?.remoteAddress || void 0;
|
|
176180
|
-
const ua = req.raw?.headers?.["user-agent"];
|
|
176181
|
-
const userAgent = (Array.isArray(ua) ? ua[0] : ua) || void 0;
|
|
176182
176374
|
await opts.credentialAudit?.({
|
|
176183
176375
|
kind,
|
|
176184
176376
|
actor: req.auth.actor,
|
|
@@ -176186,8 +176378,7 @@ function actorsDomain(opts) {
|
|
|
176186
176378
|
targetScope,
|
|
176187
176379
|
source: "console",
|
|
176188
176380
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
176189
|
-
...
|
|
176190
|
-
...userAgent ? { userAgent } : {}
|
|
176381
|
+
...clientMetaFromReq(req)
|
|
176191
176382
|
});
|
|
176192
176383
|
};
|
|
176193
176384
|
router.get("/api/variables", async (req) => {
|
|
@@ -176200,6 +176391,7 @@ function actorsDomain(opts) {
|
|
|
176200
176391
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
176201
176392
|
const b2 = req.body;
|
|
176202
176393
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
176394
|
+
const expiresAt2 = normalizeExpiresAt(b2.expiresAt);
|
|
176203
176395
|
if (b2.scope !== "global" && b2.scope !== "personal" && b2.scope !== "project") {
|
|
176204
176396
|
throw new ApiError(
|
|
176205
176397
|
400,
|
|
@@ -176240,7 +176432,8 @@ function actorsDomain(opts) {
|
|
|
176240
176432
|
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
176241
176433
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
176242
176434
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
176243
|
-
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
176435
|
+
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {},
|
|
176436
|
+
expiresAt: expiresAt2
|
|
176244
176437
|
});
|
|
176245
176438
|
await auditVariableChange(
|
|
176246
176439
|
req,
|
|
@@ -176278,6 +176471,7 @@ function actorsDomain(opts) {
|
|
|
176278
176471
|
const actorId = req.params.id;
|
|
176279
176472
|
const b2 = req.body;
|
|
176280
176473
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
176474
|
+
const expiresAt2 = normalizeExpiresAt(b2.expiresAt);
|
|
176281
176475
|
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref" && b2.deliveryMode !== "broker") {
|
|
176282
176476
|
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env\u3001ref \u6216 broker");
|
|
176283
176477
|
}
|
|
@@ -176308,7 +176502,8 @@ function actorsDomain(opts) {
|
|
|
176308
176502
|
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
176309
176503
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
176310
176504
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
176311
|
-
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
176505
|
+
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {},
|
|
176506
|
+
expiresAt: expiresAt2
|
|
176312
176507
|
});
|
|
176313
176508
|
await auditVariableChange(req, "credential_write", b2.key, `personal:${actorId}`);
|
|
176314
176509
|
return { status: 201, body: { ok: true } };
|
|
@@ -176329,25 +176524,33 @@ function actorsDomain(opts) {
|
|
|
176329
176524
|
const source = typeof b2?.source === "string" && b2.source.trim() || "agent-cli";
|
|
176330
176525
|
if (!isKnownRevealSource(source)) throw new ApiError(400, "BAD_REQUEST", `\u672A\u8BC6\u522B\u7684 source\u300C${source}\u300D\uFF08\xA74.5.4\uFF1A\u53EA\u63A5\u53D7\u8BC6\u522B\u503C\uFF09`);
|
|
176331
176526
|
const actor = req.auth.actor;
|
|
176527
|
+
const isHuman2 = isHumanActor(actor);
|
|
176528
|
+
const isConsole = source === "console";
|
|
176529
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
176332
176530
|
const artifactId = req.auth.dispatch?.artifactId;
|
|
176333
176531
|
const sessionId = req.auth.dispatch?.sessionId;
|
|
176334
|
-
const now = Date.now();
|
|
176335
|
-
const timestamp = new Date(now).toISOString();
|
|
176336
|
-
const sessionKey = sessionId ?? `${actor}::${artifactId ?? "no-artifact"}`;
|
|
176337
176532
|
const dispatchFields = { ...sessionId ? { sessionId } : {}, ...artifactId ? { artifactId } : {} };
|
|
176338
|
-
const
|
|
176533
|
+
const consoleMeta = isConsole ? clientMetaFromReq(req) : {};
|
|
176534
|
+
if (isConsole && !isHuman2) {
|
|
176535
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_denied", actor, variableKey: key, source, timestamp, reason: "no_permission", ...dispatchFields, ...consoleMeta });
|
|
176536
|
+
return { status: 403, body: { code: "denied", key } };
|
|
176537
|
+
}
|
|
176538
|
+
const now = Date.now();
|
|
176539
|
+
const sessionKey = isConsole ? actor : sessionId ?? `${actor}::${artifactId ?? "no-artifact"}`;
|
|
176540
|
+
const limiter = isConsole ? consoleRevealLimiter : revealLimiter;
|
|
176541
|
+
const throttled = limiter.check(sessionKey, key, now);
|
|
176339
176542
|
if (throttled) {
|
|
176340
|
-
await opts.credentialAudit?.({ kind: "credential_reveal_throttled", actor, variableKey: key, source, timestamp, scope: throttled, ...dispatchFields });
|
|
176543
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_throttled", actor, variableKey: key, source, timestamp, scope: throttled, ...dispatchFields, ...consoleMeta });
|
|
176341
176544
|
return { status: 429, body: { code: "throttled", key, scope: throttled } };
|
|
176342
176545
|
}
|
|
176343
|
-
const
|
|
176344
|
-
const resolved = await service.resolveRevealValue(actor, key, scope);
|
|
176546
|
+
const resolved = isHuman2 ? await service.revealHumanValue(key, { ...b2?.actorId ? { actorId: b2.actorId } : {}, ...b2?.projectId ? { projectId: b2.projectId } : {} }) : await service.resolveRevealValue(actor, key, artifactId && opts.resolveDispatchScope ? await opts.resolveDispatchScope(artifactId) : {});
|
|
176345
176547
|
if (!resolved) {
|
|
176346
176548
|
const reason = await service.hasVariableKey(key) ? "no_permission" : "not_found";
|
|
176347
|
-
await opts.credentialAudit?.({ kind: "credential_reveal_denied", actor, variableKey: key, source, timestamp, reason, ...dispatchFields });
|
|
176549
|
+
await opts.credentialAudit?.({ kind: "credential_reveal_denied", actor, variableKey: key, source, timestamp, reason, ...dispatchFields, ...consoleMeta });
|
|
176348
176550
|
return { status: 403, body: { code: "denied", key } };
|
|
176349
176551
|
}
|
|
176350
|
-
await opts.credentialAudit?.({ kind: "credential_reveal", actor, variableKey: key, source, timestamp, ...dispatchFields });
|
|
176552
|
+
await opts.credentialAudit?.({ kind: "credential_reveal", actor, variableKey: key, source, timestamp, ...dispatchFields, ...consoleMeta });
|
|
176553
|
+
await service.touchVariableUsage(key, resolved.origin, timestamp);
|
|
176351
176554
|
return { status: 200, body: { value: resolved.value } };
|
|
176352
176555
|
});
|
|
176353
176556
|
router.get("/api/variables/reveal-audit", async (req) => {
|
|
@@ -176850,7 +177053,7 @@ var init_routes2 = __esm({
|
|
|
176850
177053
|
init_image_upload();
|
|
176851
177054
|
init_skill_materializer();
|
|
176852
177055
|
init_connector_skills();
|
|
176853
|
-
CREDENTIAL_REVEAL_SOURCES = /* @__PURE__ */ new Set(["agent-cli", "agent-exec", "smoke-test", "oasis-internal"]);
|
|
177056
|
+
CREDENTIAL_REVEAL_SOURCES = /* @__PURE__ */ new Set(["agent-cli", "agent-exec", "smoke-test", "oasis-internal", "console"]);
|
|
176854
177057
|
RevealRateLimiter = class {
|
|
176855
177058
|
constructor(perSession, perSessionPerKey, ttlMs = 2 * 60 * 6e4) {
|
|
176856
177059
|
this.perSession = perSession;
|
|
@@ -183066,8 +183269,8 @@ function executionContinuityDomain(service) {
|
|
|
183066
183269
|
if (b2.changedOutputs !== void 0 && !isRefArray(b2.changedOutputs) || b2.unresolvedIssues !== void 0 && !isStringArray(b2.unresolvedIssues) || b2.risks !== void 0 && !isStringArray(b2.risks) || b2.nextActions !== void 0 && !isStringArray(b2.nextActions) || b2.verificationGaps !== void 0 && !isStringArray(b2.verificationGaps)) {
|
|
183067
183270
|
throw new ApiError(400, "BAD_REQUEST", "handoff arrays contain invalid values");
|
|
183068
183271
|
}
|
|
183069
|
-
if (!isUserHandoff(b2.userHandoff)) {
|
|
183070
|
-
throw new ApiError(400, "BAD_REQUEST", "\
|
|
183272
|
+
if (b2.userHandoff !== void 0 && b2.userHandoff !== null && !isUserHandoff(b2.userHandoff)) {
|
|
183273
|
+
throw new ApiError(400, "BAD_REQUEST", "userHandoff \u5F62\u72B6\u975E\u6CD5\uFF08\u53EF\u4EE5\u4E0D\u7ED9\uFF1B\u7ED9\u4E86\u5C31\u8981\u5408\u6CD5\uFF09");
|
|
183071
183274
|
}
|
|
183072
183275
|
const handoff = await service.handoff({
|
|
183073
183276
|
attemptId,
|
|
@@ -183118,10 +183321,20 @@ function renderResumePack(pack) {
|
|
|
183118
183321
|
if (!pack.previousAttempt) lines.push("- This is the first attempt.");
|
|
183119
183322
|
else {
|
|
183120
183323
|
lines.push(`- Attempt ${pack.previousAttempt.attemptNo ?? "?"}: ${pack.previousHandoff?.summary || pack.previousAttempt.status}`);
|
|
183121
|
-
|
|
183122
|
-
|
|
183123
|
-
|
|
183124
|
-
|
|
183324
|
+
const cp = pack.latestCheckpoint;
|
|
183325
|
+
const done = cp?.completedStepIds ?? [];
|
|
183326
|
+
const durable = (cp?.durableRefs.length ? cp.durableRefs : pack.previousHandoff?.changedOutputs) ?? [];
|
|
183327
|
+
if (cp) lines.push(`- Recoverability: ${cp.recoverability}`);
|
|
183328
|
+
if (done.length > 0) lines.push(`- \u4E0A\u4E00\u8D9F\u5DF2\u5B8C\u6210\u7684\u6B65\u9AA4\uFF1A${done.join("\u3001")}`);
|
|
183329
|
+
for (const ref2 of durable) {
|
|
183330
|
+
lines.push(` - durable: ${ref2.kind}:${ref2.id}${ref2.version ? `@${ref2.version}` : ""}${ref2.label ? ` \u2014 ${ref2.label}` : ""}`);
|
|
183331
|
+
}
|
|
183332
|
+
if (cp && cp.pendingSteps.length > 0) {
|
|
183333
|
+
for (const step of cp.pendingSteps) lines.push(` - pending: ${step}`);
|
|
183334
|
+
} else {
|
|
183335
|
+
lines.push(
|
|
183336
|
+
durable.length > 0 || done.length > 0 ? "- \u672A\u5B8C\u6210\u7684\u6B65\u9AA4\uFF1A**\u672A\u77E5**\uFF08\u4E0A\u4E00\u8D9F\u6CA1\u7559 checkpoint\uFF09\u2014\u2014\u4EE5\u4E0A\u9762\u8FD9\u4E9B\u5DF2\u843D\u5730\u7684\u4EA7\u51FA\u4E3A\u51C6\uFF0C\u81EA\u5DF1\u6838\u5BF9\u8FD8\u7F3A\u4EC0\u4E48\uFF0C\u522B\u4ECE\u5934\u91CD\u505A\u3002" : "- \u4E0A\u4E00\u8D9F\u6CA1\u7559\u4E0B\u4EFB\u4F55\u53EF\u6062\u590D\u7684\u75D5\u8FF9\uFF08\u6CA1\u8DD1\u5230\u4EFB\u4F55\u6301\u4E45\u5316\u547D\u4EE4\uFF09\u2014\u2014\u6309\u9996\u6B21\u6267\u884C\u5904\u7406\u3002"
|
|
183337
|
+
);
|
|
183125
183338
|
}
|
|
183126
183339
|
}
|
|
183127
183340
|
lines.push("", "## External effects");
|
|
@@ -183230,6 +183443,7 @@ function renderCoordinatorView(view) {
|
|
|
183230
183443
|
function shouldInjectResumePack(pack) {
|
|
183231
183444
|
const status = pack?.previousAttempt?.status;
|
|
183232
183445
|
if (!status) return false;
|
|
183446
|
+
if (status === "running" || status === "queued") return false;
|
|
183233
183447
|
return status !== "succeeded" && status !== "no-output";
|
|
183234
183448
|
}
|
|
183235
183449
|
function renderContinuityProtocol() {
|
|
@@ -183462,9 +183676,6 @@ var init_service7 = __esm({
|
|
|
183462
183676
|
async handoff(input) {
|
|
183463
183677
|
if (!HANDOFF_OUTCOMES2.has(input.outcome)) throw new Error(`invalid handoff outcome: ${input.outcome}`);
|
|
183464
183678
|
if (!input.summary.trim()) throw new Error("handoff summary is required");
|
|
183465
|
-
if (input.producedBy === "agent" && !input.userHandoff) {
|
|
183466
|
-
throw new Error("agent-authored handoff requires userHandoff");
|
|
183467
|
-
}
|
|
183468
183679
|
const userHandoff = input.userHandoff ? normalizeUserHandoff(input.outcome, input.changedOutputs ?? [], input.userHandoff) : void 0;
|
|
183469
183680
|
const attempt = await this.awaitAttempt(input.attemptId);
|
|
183470
183681
|
const handoff = await this.afterAttemptVisible(() => this.store.putHandoff({
|
|
@@ -183668,8 +183879,7 @@ var init_service7 = __esm({
|
|
|
183668
183879
|
"failed"
|
|
183669
183880
|
].map((state) => [state, nodes.filter((node) => node.nodeState === state).length]));
|
|
183670
183881
|
const collaborationStatus = nodes.length > 0 && nodes.every((node) => DONE_STATES.has(node.nodeState)) ? "completed" : nodes.some((node) => BLOCKING_STATES.has(node.nodeState)) ? "needs_coordination" : "in_progress";
|
|
183671
|
-
|
|
183672
|
-
return { workOrderId, mode: this.mode, collaborationStatus, handoffSummary, progress, nodes, dependencyBlocks, todo: todos };
|
|
183882
|
+
return { workOrderId, mode: this.mode, collaborationStatus, progress, nodes, dependencyBlocks, todo: todos };
|
|
183673
183883
|
}
|
|
183674
183884
|
};
|
|
183675
183885
|
}
|
|
@@ -183804,8 +184014,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
183804
184014
|
const edge = snapshot.edges.find(
|
|
183805
184015
|
(candidate) => candidate.fromNodeId === input.upstreamNodeId && candidate.toNodeId === input.downstreamNodeId
|
|
183806
184016
|
);
|
|
183807
|
-
const
|
|
183808
|
-
const businessEdge = edge?.kind === "data" && edge.required && downstream?.fields?.[BUSINESS_HANDOFF_POLICY_FIELD] !== BUSINESS_HANDOFF_POLICY_EXEMPT;
|
|
184017
|
+
const businessEdge = edge?.kind === "data" && edge.required;
|
|
183809
184018
|
if (!businessEdge) return null;
|
|
183810
184019
|
if (edge.pinnedWorkId !== input.pinnedWorkId) {
|
|
183811
184020
|
warn(
|
|
@@ -183871,7 +184080,6 @@ var INJECTED_TEXT_LIMIT, NONE_TOKENS;
|
|
|
183871
184080
|
var init_upstream_handoff_input = __esm({
|
|
183872
184081
|
"../server/src/domains/execution-continuity/upstream-handoff-input.ts"() {
|
|
183873
184082
|
"use strict";
|
|
183874
|
-
init_src3();
|
|
183875
184083
|
INJECTED_TEXT_LIMIT = 4e3;
|
|
183876
184084
|
NONE_TOKENS = /* @__PURE__ */ new Set(["none", "n/a", "na", "nil", "\u65E0", "\u6CA1\u6709", "\u6682\u65E0"]);
|
|
183877
184085
|
}
|
|
@@ -188084,7 +188292,10 @@ function rowToVariable(row) {
|
|
|
188084
188292
|
// **不塌成 env**,否则未知档位读回来变明文;仅 null/空回填 "env"(存量行)。派单侧按未知档保守处理。
|
|
188085
188293
|
deliveryMode: typeof row.delivery_mode === "string" && row.delivery_mode ? row.delivery_mode : "env",
|
|
188086
188294
|
valueEncrypted: row.value_encrypted,
|
|
188087
|
-
updatedAt: new Date(row.updated_at).toISOString()
|
|
188295
|
+
updatedAt: new Date(row.updated_at).toISOString(),
|
|
188296
|
+
// ADR 凭据保险库补章 §D2.1:到期/取用时间戳(text 列存 ISO 字符串,原样带出;null/空 = undefined)。
|
|
188297
|
+
...row.expires_at ? { expiresAt: row.expires_at } : {},
|
|
188298
|
+
...row.last_used_at ? { lastUsedAt: row.last_used_at } : {}
|
|
188088
188299
|
};
|
|
188089
188300
|
}
|
|
188090
188301
|
var ident4, PostgresRegistryStore, rowToActor, rowToConfig, rowToAgentPrefs;
|
|
@@ -188247,6 +188458,8 @@ var init_postgres_registry = __esm({
|
|
|
188247
188458
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS project_id text`);
|
|
188248
188459
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS environment text`);
|
|
188249
188460
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS delivery_mode text`);
|
|
188461
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS expires_at text`);
|
|
188462
|
+
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS last_used_at text`);
|
|
188250
188463
|
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_key_actor_uq"`);
|
|
188251
188464
|
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_scope_uq"`);
|
|
188252
188465
|
await pool.query(`
|
|
@@ -188723,10 +188936,10 @@ var init_postgres_registry = __esm({
|
|
|
188723
188936
|
/* ---------- 变量 ---------- */
|
|
188724
188937
|
async putVariable(v2) {
|
|
188725
188938
|
await this.pool.query(
|
|
188726
|
-
`INSERT INTO ${this.s}.variables (key, scope, actor_id, project_id, connector_id, overrides, delivery_mode, value_encrypted, updated_at)
|
|
188727
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9)
|
|
188939
|
+
`INSERT INTO ${this.s}.variables (key, scope, actor_id, project_id, connector_id, overrides, delivery_mode, value_encrypted, updated_at, expires_at)
|
|
188940
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10)
|
|
188728
188941
|
ON CONFLICT (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) DO UPDATE
|
|
188729
|
-
SET scope=$2, actor_id=$3, project_id=$4, connector_id=$5, overrides=$6, delivery_mode=$7, value_encrypted=$8, updated_at=$9`,
|
|
188942
|
+
SET scope=$2, actor_id=$3, project_id=$4, connector_id=$5, overrides=$6, delivery_mode=$7, value_encrypted=$8, updated_at=$9, expires_at=$10`,
|
|
188730
188943
|
[
|
|
188731
188944
|
v2.key,
|
|
188732
188945
|
v2.scope,
|
|
@@ -188736,10 +188949,18 @@ var init_postgres_registry = __esm({
|
|
|
188736
188949
|
v2.overrides ?? null,
|
|
188737
188950
|
v2.deliveryMode ?? null,
|
|
188738
188951
|
v2.valueEncrypted,
|
|
188739
|
-
v2.updatedAt
|
|
188952
|
+
v2.updatedAt,
|
|
188953
|
+
v2.expiresAt ?? null
|
|
188740
188954
|
]
|
|
188741
188955
|
);
|
|
188742
188956
|
}
|
|
188957
|
+
async touchVariableUsage(key, actorId, projectId, when) {
|
|
188958
|
+
await this.pool.query(
|
|
188959
|
+
`UPDATE ${this.s}.variables SET last_used_at=$4
|
|
188960
|
+
WHERE key=$1 AND COALESCE(actor_id,'')=COALESCE($2::text,'') AND COALESCE(project_id,'')=COALESCE($3::text,'')`,
|
|
188961
|
+
[key, actorId ?? null, projectId ?? null, when]
|
|
188962
|
+
);
|
|
188963
|
+
}
|
|
188743
188964
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
188744
188965
|
const aid = actorId ?? null;
|
|
188745
188966
|
await this.pool.query(
|
|
@@ -194470,6 +194691,15 @@ async function buildActorProvision(service, actorId, scope, onBrokerRefused) {
|
|
|
194470
194691
|
const brokerRefused = [];
|
|
194471
194692
|
applyRefDelivery(env, entries, void 0, (k2) => brokerRefused.push(k2));
|
|
194472
194693
|
if (onBrokerRefused) for (const k2 of brokerRefused) await onBrokerRefused(k2);
|
|
194694
|
+
const brokerSet = new Set(brokerRefused);
|
|
194695
|
+
for (const e of entries) {
|
|
194696
|
+
if (brokerSet.has(e.key)) continue;
|
|
194697
|
+
try {
|
|
194698
|
+
await service.touchVariableUsage(e.key, e.origin);
|
|
194699
|
+
} catch (err) {
|
|
194700
|
+
console.warn(`[credential] touchVariableUsage(${e.key}) \u5931\u8D25\uFF08\u4E0D\u963B\u65AD\u6D3E\u5355\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`);
|
|
194701
|
+
}
|
|
194702
|
+
}
|
|
194473
194703
|
return {
|
|
194474
194704
|
env,
|
|
194475
194705
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
@@ -195781,7 +196011,10 @@ async function startServe(opts) {
|
|
|
195781
196011
|
...await materializeSkillFiles({ service: actors.service, actorId, runtimeKind })
|
|
195782
196012
|
}),
|
|
195783
196013
|
uploadChatAttachment: async ({ contentBase64 }) => ({ blobRef: await assets.put(new Uint8Array(Buffer.from(contentBase64, "base64"))) }),
|
|
195784
|
-
onDispatchCommandCompleted: async ({ dispatchId, command, durableRefs, at, delivered }) => {
|
|
196014
|
+
onDispatchCommandCompleted: async ({ dispatchId, command, durableRefs, at, delivered, pendingSteps }) => {
|
|
196015
|
+
if (pendingSteps && pendingSteps.length > 0) {
|
|
196016
|
+
traceStoreSink.checkpointState(dispatchId, { pendingSteps: [...pendingSteps] });
|
|
196017
|
+
}
|
|
195785
196018
|
traceStoreSink.checkpoint(dispatchId, {
|
|
195786
196019
|
trigger: "important_output",
|
|
195787
196020
|
// 交作业的那条命令带着版本号(`wk:<节点>:<n>`),比笼统的「动过这个产物」有用得多——
|
|
@@ -197751,12 +197984,13 @@ var KNOWN2 = [
|
|
|
197751
197984
|
{ adapter: "copilot", binary: "copilot" },
|
|
197752
197985
|
{ adapter: "kimi", binary: "kimi" },
|
|
197753
197986
|
{ adapter: "kiro", binary: "kiro-cli" },
|
|
197987
|
+
{ adapter: "reasonix", binary: "reasonix" },
|
|
197754
197988
|
{ adapter: "pi", binary: "pi" },
|
|
197755
197989
|
{ adapter: "openclaw", binary: "openclaw" },
|
|
197756
197990
|
{ adapter: "codebuddy", binary: "codebuddy" },
|
|
197757
197991
|
{ adapter: "antigravity", binary: "agy" }
|
|
197758
197992
|
];
|
|
197759
|
-
var NATIVE_APPEND_RUNTIMES = /* @__PURE__ */ new Set(["hermes", "gemini", "kimi", "kiro"]);
|
|
197993
|
+
var NATIVE_APPEND_RUNTIMES = /* @__PURE__ */ new Set(["hermes", "gemini", "kimi", "kiro", "reasonix"]);
|
|
197760
197994
|
function onPath(binary) {
|
|
197761
197995
|
try {
|
|
197762
197996
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -198560,6 +198794,7 @@ async function startNode(opts) {
|
|
|
198560
198794
|
copilot: new CopilotAdapter(),
|
|
198561
198795
|
kimi: new KimiAdapter(),
|
|
198562
198796
|
kiro: new KiroAdapter(),
|
|
198797
|
+
reasonix: new ReasonixAdapter(),
|
|
198563
198798
|
pi: new PiAdapter(),
|
|
198564
198799
|
openclaw: new OpenClawAdapter(),
|
|
198565
198800
|
codebuddy: new CodebuddyAdapter(),
|
|
@@ -199044,7 +199279,8 @@ var COMMAND_DECLS = {
|
|
|
199044
199279
|
{ name: "unresolved", desc: "\u7559\u7ED9\u4E0B\u6E38\u7684\u672A\u51B3\u4E8B\u9879\uFF08\u5206\u53F7\u5206\u9694\uFF09\u3002\u5199\u8FDB\u672C\u8282\u70B9\u7684\u6280\u672F\u4EA4\u63A5\uFF0C\u4E0B\u6E38\u5F00\u5DE5\u524D\u4F1A\u8BFB\u5230" },
|
|
199045
199280
|
{ name: "risks", desc: "\u4E0B\u6E38\u8BE5\u77E5\u9053\u7684\u98CE\u9669\uFF08\u5206\u53F7\u5206\u9694\uFF09" },
|
|
199046
199281
|
{ name: "next", desc: "\u5EFA\u8BAE\u4E0B\u6E38\u63A5\u7740\u505A\u4EC0\u4E48\uFF08\u5206\u53F7\u5206\u9694\uFF09" },
|
|
199047
|
-
{ name: "gaps", desc: "\u4F60\u6CA1\u80FD\u6838\u9A8C\u7684\u90E8\u5206\uFF08\u5206\u53F7\u5206\u9694\uFF09\u2014\u2014\u522B\u8BA9\u4E0B\u6E38\u4EE5\u4E3A\u5DF2\u9A8C\u8FC7" }
|
|
199282
|
+
{ name: "gaps", desc: "\u4F60\u6CA1\u80FD\u6838\u9A8C\u7684\u90E8\u5206\uFF08\u5206\u53F7\u5206\u9694\uFF09\u2014\u2014\u522B\u8BA9\u4E0B\u6E38\u4EE5\u4E3A\u5DF2\u9A8C\u8FC7" },
|
|
199283
|
+
{ name: "pending", desc: "\u8FD8\u5269\u4EC0\u4E48\u6CA1\u505A\uFF08\u5206\u53F7\u5206\u9694\uFF09\u3002\u5B58\u8FDB\u672C\u8F6E checkpoint\uFF1A\u8FD9\u4E00\u8D9F\u82E5\u88AB\u780D\uFF08\u8D85\u65F6/\u989D\u5EA6/\u6389\u7EBF\uFF09\uFF0C\u4E0B\u4E00\u8D9F\u63A5\u624B\u7684\u4EBA\u636E\u5B83\u63A5\u7740\u505A" }
|
|
199048
199284
|
],
|
|
199049
199285
|
examples: [
|
|
199050
199286
|
'oasis propose artifact:dev:abc-123 --from-dir deliverable/ --reason "\u4FEE\u590D\u767B\u5F55\u9875\u767D\u5C4F"',
|
|
@@ -201730,7 +201966,9 @@ ${res.warning}`);
|
|
|
201730
201966
|
...semicolonList(flags.get("unresolved"), "unresolvedIssues"),
|
|
201731
201967
|
...semicolonList(flags.get("risks"), "risks"),
|
|
201732
201968
|
...semicolonList(flags.get("next"), "nextActions"),
|
|
201733
|
-
...semicolonList(flags.get("gaps"), "verificationGaps")
|
|
201969
|
+
...semicolonList(flags.get("gaps"), "verificationGaps"),
|
|
201970
|
+
// 「还剩什么没做」:唯一系统推不出来的字段,挂在本来就要跑的命令上(见 server 的 pendingSteps 注释)
|
|
201971
|
+
...semicolonList(flags.get("pending"), "pendingSteps")
|
|
201734
201972
|
});
|
|
201735
201973
|
println(message);
|
|
201736
201974
|
break;
|
|
@@ -203004,7 +203242,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
203004
203242
|
}
|
|
203005
203243
|
|
|
203006
203244
|
// src/index.ts
|
|
203007
|
-
var PKG_VERSION = true ? "0.1.
|
|
203245
|
+
var PKG_VERSION = true ? "0.1.109" : "dev";
|
|
203008
203246
|
var OASIS_DIR = path28.join(os11.homedir(), ".oasis");
|
|
203009
203247
|
var CONFIG_FILE = path28.join(OASIS_DIR, "node-config.json");
|
|
203010
203248
|
var PID_FILE = path28.join(OASIS_DIR, "node.pid");
|