oasis_test 0.1.107 → 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 +379 -86
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -993,20 +993,27 @@ function pinnedReviewerOf(model, artifactId, role) {
|
|
|
993
993
|
}
|
|
994
994
|
return best?.actor ?? null;
|
|
995
995
|
}
|
|
996
|
+
function latestAttempt(attempts) {
|
|
997
|
+
let best = null;
|
|
998
|
+
for (const a of attempts) {
|
|
999
|
+
if (best === null || a.at > best.at || a.at === best.at && a.seq >= best.seq) best = a;
|
|
1000
|
+
}
|
|
1001
|
+
return best;
|
|
1002
|
+
}
|
|
996
1003
|
function concludeMilestones(model, id) {
|
|
997
1004
|
return (model.concludeAttempts.get(id) ?? []).filter(
|
|
998
1005
|
(a) => attemptStatus(model, a) === "satisfied"
|
|
999
1006
|
);
|
|
1000
1007
|
}
|
|
1001
1008
|
function pendingConcludeAttempt(model, id) {
|
|
1002
|
-
const last = model.concludeAttempts.get(id)
|
|
1009
|
+
const last = latestAttempt(model.concludeAttempts.get(id) ?? []);
|
|
1003
1010
|
return last && attemptStatus(model, last) === "pending" ? last : null;
|
|
1004
1011
|
}
|
|
1005
1012
|
function isConcluded(model, id) {
|
|
1006
1013
|
return concludeMilestones(model, id).length > 0;
|
|
1007
1014
|
}
|
|
1008
1015
|
function concludedHead(model, id) {
|
|
1009
|
-
return concludeMilestones(model, id)
|
|
1016
|
+
return latestAttempt(concludeMilestones(model, id))?.head ?? null;
|
|
1010
1017
|
}
|
|
1011
1018
|
function revisionsOf(model, id) {
|
|
1012
1019
|
return [...model.revisions.values()].filter((r) => r.artifactId === id);
|
|
@@ -4068,6 +4075,41 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
4068
4075
|
});
|
|
4069
4076
|
})()
|
|
4070
4077
|
),
|
|
4078
|
+
// ★ 2026-08-18:交稿时把「系统看不出来的四件事」一并带上。
|
|
4079
|
+
//
|
|
4080
|
+
// 为什么必须写在**任务书**里:adapter 只把 TASK.md 当提示词喂给模型,其余 bundle 文件(包括
|
|
4081
|
+
// execution/CONTINUITY.md)只是躺在工作目录里、没人读。`--reason` 之所以交付过的节点 100% 都有,
|
|
4082
|
+
// 正因为它既进了任务书又是必填;这四项此前只活在 `oasis help propose` 里——next 上节点全部更新到
|
|
4083
|
+
// 认得它们之后的 10 小时里,两次真实交付**一次都没带**(实测 0/2)。
|
|
4084
|
+
//
|
|
4085
|
+
// 给 `none` 出口是刻意的:逼着写自由文本只会得到「暂无」这种假保证,而「确认没有」与「没人写」
|
|
4086
|
+
// 对下游是两条完全不同的信息(渲染侧据此分流,见 renderDeliveredWorkHandoff)。
|
|
4087
|
+
...args.action === "review" ? [] : [
|
|
4088
|
+
``,
|
|
4089
|
+
`### \u4EA4\u7A3F\u65F6\u4E00\u5E76\u5E26\u4E0A\uFF1A\u4E0B\u6E38\u8981\u7528\u7684\u56DB\u4EF6\u4E8B`,
|
|
4090
|
+
`\u8FD9\u56DB\u9879\u4F1A\u539F\u6837\u51FA\u73B0\u5728\u4E0B\u6E38\u8282\u70B9\u7684 \`inputs/<\u672C\u8282\u70B9>@<\u7248\u672C>/${UPSTREAM_HANDOFF_BASENAME}\` \u91CC\u3002\u5206\u53F7\u5206\u9694\uFF1B**\u786E\u5B9E\u6CA1\u6709\u5C31\u5199 \`none\`\uFF0C\u522B\u7F16\u300C\u6682\u65E0\u300D**\uFF1A`,
|
|
4091
|
+
`- \`--gaps\` **\u4F60\u6CA1\u80FD\u6838\u9A8C\u7684\u90E8\u5206** \u2014\u2014 \u6700\u8981\u7D27\u7684\u4E00\u9879\u3002\u4E0B\u6E38\u9ED8\u8BA4\u300C\u4E0A\u6E38\u4EA4\u4E86\u5C31\u662F\u9A8C\u8FC7\u4E86\u300D\uFF0C\u4F60\u4E0D\u5199\uFF0C\u6CA1\u9A8C\u7684\u90A3\u5757\u5C31\u76F4\u63A5\u8FDB\u4E0B\u4E00\u73AF\u3002\u4F8B\uFF1A\`--gaps "\u6CA1\u505A\u538B\u6D4B;\u53EA\u5728 dev \u9A8C\u8FC7"\``,
|
|
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
|
+
`- \`--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
|
+
`- \`--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**`,
|
|
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`
|
|
4112
|
+
],
|
|
4071
4113
|
// 兜底(§10):上次失败了 → 明确告诉它发生了什么 + 怎么破(首选 add-revision 拆出去)
|
|
4072
4114
|
...args.lastFailure ? args.lastFailure.resumed ? [
|
|
4073
4115
|
// 续跑分支:上文还在它眼前,别再说"没留下任何产出"(自相矛盾),改成"接着干 + 先核现场"。
|
|
@@ -7994,14 +8036,13 @@ FROM ${schema}.workflow_nodes n
|
|
|
7994
8036
|
LEFT JOIN ${schema}.works lw ON lw.id = n.latest_work_id
|
|
7995
8037
|
LEFT JOIN ${schema}.works ls ON ls.id = n.latest_success_work_id;
|
|
7996
8038
|
|
|
8039
|
+
-- workorder_view \u5DF2\u4E0B\u7EBF\uFF08\u5DE5\u5355 1aa1f35b\uFF09\uFF1A\u5B83\u53EA\u989D\u5916\u7ED9\u51FA total_count / done_count \u4E24\u4E2A\u8FDB\u5EA6\u6570\uFF0C\u5168\u4ED3\u96F6\u6D88\u8D39\u65B9\uFF0C
|
|
8040
|
+
-- \u4E14\u53E3\u5F84\u4E0E\u540E\u7AEF\u771F\u6E90\uFF08server summaryOfWorkspace \u7684 progressExcludingBrief\uFF09\u4E0D\u540C\u2014\u2014total \u53EA\u6392 cancelled\u3001done \u7528
|
|
8041
|
+
-- latest_accept_id IS NOT NULL\uFF08\u66FE\u88AB\u9A8C\u6536\u8FC7\u81F3\u5C11\u4E00\u6B21\uFF09\uFF0C\u800C\u771F\u6E90\u6392\u9664 brief + \u5DF2\u4F5C\u5E9F\u3001\u6309\u300C\u9A8C\u6536\u843D\u5728\u5F53\u524D\u7248\u300D\u7B97\u3002
|
|
8042
|
+
-- \u4FDD\u7559\u4E00\u4EFD\u89C6\u56FE\u65E2\u6CA1\u4EBA\u8BFB\u3001\u53E3\u5F84\u53C8\u5BF9\u4E0D\u4E0A\uFF0C\u53EA\u4F1A\u662F\u7B2C\u4E09\u5904\u5BF9\u4E0D\u4E0A\u7684\u8FDB\u5EA6\u6570\u3002\u8FD9\u91CC\u4E0D\u518D CREATE\uFF1B\u4E0B\u9762\u7684 DROP \u8BA9\u5B58\u91CF\u5E93
|
|
8043
|
+
-- \u5728\u4E0B\u6B21 migrate \u65F6\u628A\u65E7\u89C6\u56FE\u5220\u6389\uFF08ENGINE_DDL \u6BB5\u4EA6\u6709\u4E00\u5904 DROP\uFF0C\u4E8C\u8005\u90FD\u7559\u4EE5\u9632\u91CD\u6392\uFF09\u3002\u5DE5\u5355\u8FDB\u5EA6\u7EDF\u4E00\u8D70\u540E\u7AEF\u8BFB\u6A21\u578B\uFF0C
|
|
8044
|
+
-- \u9700\u8981 SQL \u4FA7\u7EDF\u8BA1\u65F6\u53E6\u7ACB\u4E0E\u771F\u6E90\u540C\u53E3\u5F84\u7684\u89C6\u56FE\u5E76\u6CE8\u660E\u670D\u52A1\u5BF9\u8C61\uFF0C\u522B\u590D\u6D3B\u8FD9\u4E24\u4E2A\u6570\u3002
|
|
7997
8045
|
DROP VIEW IF EXISTS ${schema}.workorder_view;
|
|
7998
|
-
CREATE VIEW ${schema}.workorder_view AS
|
|
7999
|
-
SELECT o.*,
|
|
8000
|
-
(SELECT count(*) FROM ${schema}.workflow_nodes n
|
|
8001
|
-
WHERE n.workorder_id = o.id AND n.cancelled_at IS NULL) AS total_count,
|
|
8002
|
-
(SELECT count(*) FROM ${schema}.workflow_nodes n
|
|
8003
|
-
WHERE n.workorder_id = o.id AND n.cancelled_at IS NULL AND n.latest_accept_id IS NOT NULL) AS done_count
|
|
8004
|
-
FROM ${schema}.workorders o;
|
|
8005
8046
|
`;
|
|
8006
8047
|
}
|
|
8007
8048
|
var init_schema2 = __esm({
|
|
@@ -13215,7 +13256,10 @@ var init_store_postgres = __esm({
|
|
|
13215
13256
|
JOIN ${this.s}.workflow_nodes n ON n.id = r.node_id WHERE n.workorder_id = $1`,
|
|
13216
13257
|
[id]
|
|
13217
13258
|
);
|
|
13218
|
-
const works = await this.c.query(
|
|
13259
|
+
const works = await this.c.query(
|
|
13260
|
+
`SELECT * FROM ${this.s}.works WHERE workorder_id = $1 ORDER BY created_at ASC, id ASC`,
|
|
13261
|
+
[id]
|
|
13262
|
+
);
|
|
13219
13263
|
const arts = await this.c.query(
|
|
13220
13264
|
`SELECT a.* FROM ${this.s}.work_artifacts a JOIN ${this.s}.works w ON w.id = a.work_id WHERE w.workorder_id = $1`,
|
|
13221
13265
|
[id]
|
|
@@ -14063,6 +14107,11 @@ var init_plan = __esm({
|
|
|
14063
14107
|
if (!node || node.cancelledAt) return;
|
|
14064
14108
|
killLatestWork(state, e.nodeId, ctx.at);
|
|
14065
14109
|
killNodeReviews(state, e.nodeId, ctx.at);
|
|
14110
|
+
for (const issue2 of state.allIssues()) {
|
|
14111
|
+
if (issue2.resolvedAt !== null) continue;
|
|
14112
|
+
if (issue2.aboutNodeId !== e.nodeId && issue2.raisedByNodeId !== e.nodeId) continue;
|
|
14113
|
+
state.updateIssue(issue2.id, { resolvedAt: ctx.at, resolution: "wontfix" });
|
|
14114
|
+
}
|
|
14066
14115
|
state.updateNode(e.nodeId, { cancelledAt: ctx.at, updatedAt: ctx.at });
|
|
14067
14116
|
for (const edge of state.edgesFrom(e.nodeId)) {
|
|
14068
14117
|
const dn = state.node(edge.toNodeId);
|
|
@@ -16007,6 +16056,7 @@ function bridgeLoadReadModel(input) {
|
|
|
16007
16056
|
const holds = /* @__PURE__ */ new Map();
|
|
16008
16057
|
for (const node of allNodes) {
|
|
16009
16058
|
if (!node.latestWorkId) continue;
|
|
16059
|
+
if (node.cancelledAt) continue;
|
|
16010
16060
|
const lw = allWorks.find((w2) => w2.id === node.latestWorkId);
|
|
16011
16061
|
if (!lw || !lw.deadAt) continue;
|
|
16012
16062
|
if (node.latestAcceptId === node.latestWorkId) continue;
|
|
@@ -149101,6 +149151,7 @@ function stallOf(model, id, runtime, dispatcherSignals) {
|
|
|
149101
149151
|
if (gaps.length > 0) {
|
|
149102
149152
|
return { kind: "waiting_human", action: "resolve_gap", detail: `\u5361\u5728\u7F3A\u53E3\u4E0A\u5F85\u4EBA\u8865\uFF1A${gaps[0].description}` };
|
|
149103
149153
|
}
|
|
149154
|
+
if (isDeliveredSettled(model, id)) return null;
|
|
149104
149155
|
if (isHeld(model, id)) {
|
|
149105
149156
|
const h = holdOf(model, id);
|
|
149106
149157
|
return { kind: "held", action: "resume", detail: `\u5DF2\u6682\u505C\u6D3E\u53D1${h?.reason ? `\uFF1A${h.reason}` : ""}\u2014\u2014\u5F85\u6062\u590D`, ...h?.at ? { since: h.at } : {} };
|
|
@@ -149146,7 +149197,7 @@ function stallOf(model, id, runtime, dispatcherSignals) {
|
|
|
149146
149197
|
if (dep) return { kind: "waiting_system", ref: dep.to, detail: `\u7B49\u4E0A\u6E38\u6536\u53E3\uFF1A${dep.to}` };
|
|
149147
149198
|
return { kind: "waiting_system", detail: `\u963B\u585E\u4E2D\uFF1A${b2.reasons[0] ?? "\u5F85\u524D\u7F6E\u5C31\u7EEA"}` };
|
|
149148
149199
|
}
|
|
149149
|
-
const queueCause =
|
|
149200
|
+
const queueCause = queueBlockCauseOf(model, id);
|
|
149150
149201
|
if (queueCause !== null) {
|
|
149151
149202
|
const pending = queueOf(model, id);
|
|
149152
149203
|
const since = pending[0]?.createdAt;
|
|
@@ -149973,9 +150024,10 @@ function summaryOfWorkspace(model, workspace, arts, ref2, resolveProject, dispat
|
|
|
149973
150024
|
owner: ref2(seed.owner),
|
|
149974
150025
|
participants: participantIds.map(ref2),
|
|
149975
150026
|
artifactCount: arts.length,
|
|
150027
|
+
// 原始计数(含 brief、含已作废)——仅作旧客户端回退;界面真源是下面的 progressExcludingBrief。
|
|
149976
150028
|
progress: { concluded, total: arts.length },
|
|
149977
|
-
// ADR 0088 D1
|
|
149978
|
-
progressExcludingBrief: progressExcludingBrief(arts, members
|
|
150029
|
+
// ADR 0088 D1:派生位内联,前端不再按行拉详情。这是进度的唯一真源(排除 brief + 已作废,见函数注释)。
|
|
150030
|
+
progressExcludingBrief: progressExcludingBrief(arts, members),
|
|
149979
150031
|
...runtimeAlertOf(arts, members, runtimeOf) ?? {},
|
|
149980
150032
|
updatedAt: lastOps[lastOps.length - 1] ?? "",
|
|
149981
150033
|
projectId: resolveProject?.(workspace) ?? null,
|
|
@@ -149990,20 +150042,17 @@ function tagsOf(seed) {
|
|
|
149990
150042
|
if (!Array.isArray(raw)) return [];
|
|
149991
150043
|
return [...new Set(raw.map((v2) => typeof v2 === "string" ? v2.trim() : "").filter(Boolean))];
|
|
149992
150044
|
}
|
|
149993
|
-
function progressExcludingBrief(arts, members
|
|
149994
|
-
let
|
|
149995
|
-
let
|
|
150045
|
+
function progressExcludingBrief(arts, members) {
|
|
150046
|
+
let total = 0;
|
|
150047
|
+
let concluded = 0;
|
|
149996
150048
|
for (let i = 0; i < arts.length; i++) {
|
|
149997
|
-
|
|
149998
|
-
|
|
149999
|
-
|
|
150000
|
-
|
|
150049
|
+
const info = members[i];
|
|
150050
|
+
if (arts[i].type === "brief") continue;
|
|
150051
|
+
if (info.sealed) continue;
|
|
150052
|
+
total++;
|
|
150053
|
+
if (info.concluded) concluded++;
|
|
150001
150054
|
}
|
|
150002
|
-
|
|
150003
|
-
return {
|
|
150004
|
-
concluded: Math.max(0, progress.concluded - briefConcluded),
|
|
150005
|
-
total: Math.max(0, progress.total - briefCount)
|
|
150006
|
-
};
|
|
150055
|
+
return { concluded, total };
|
|
150007
150056
|
}
|
|
150008
150057
|
function runtimeAlertOf(arts, members, runtimeOf) {
|
|
150009
150058
|
if (!runtimeOf) return void 0;
|
|
@@ -158830,6 +158879,8 @@ async function listModels(runtime, executablePath) {
|
|
|
158830
158879
|
return cachedDiscovery(runtime, async () => await discoverACPModels(executablePath ?? "kimi", "kimi", ["acp"]) ?? []);
|
|
158831
158880
|
case "kiro":
|
|
158832
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"]) ?? []);
|
|
158833
158884
|
case "openclaw":
|
|
158834
158885
|
return cachedDiscovery(runtime, () => discoverOpenclawModels(executablePath));
|
|
158835
158886
|
default:
|
|
@@ -159376,6 +159427,7 @@ var init_codex = __esm({
|
|
|
159376
159427
|
"../adapters/src/codex/index.ts"() {
|
|
159377
159428
|
"use strict";
|
|
159378
159429
|
import_node_child_process9 = require("node:child_process");
|
|
159430
|
+
init_container_runtime();
|
|
159379
159431
|
import_node_crypto15 = require("node:crypto");
|
|
159380
159432
|
fs10 = __toESM(require("node:fs"), 1);
|
|
159381
159433
|
os5 = __toESM(require("node:os"), 1);
|
|
@@ -159421,9 +159473,6 @@ var init_codex = __esm({
|
|
|
159421
159473
|
*/
|
|
159422
159474
|
capabilities = { appendInput: false };
|
|
159423
159475
|
async spawn(job) {
|
|
159424
|
-
if (job.executionEnv) {
|
|
159425
|
-
throw new Error("executionEnv\uFF1Acodex runtime \u5C1A\u672A\u652F\u6301\u5BB9\u5668\u5316\u6267\u884C\uFF08ADR-0147\uFF09\uFF0C\u8BF7\u6539\u6D3E claude-code \u5458\u5DE5\u6216\u53BB\u6389\u8BE5\u8282\u70B9\u7684 executionEnv \u58F0\u660E");
|
|
159426
|
-
}
|
|
159427
159476
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
159428
159477
|
const id = `codex-${slug6}-${(0, import_node_crypto15.randomUUID)().slice(0, 8)}`;
|
|
159429
159478
|
const startedAtMs = Date.now();
|
|
@@ -159483,7 +159532,21 @@ var init_codex = __esm({
|
|
|
159483
159532
|
),
|
|
159484
159533
|
promptViaStdin ? "-" : prompt
|
|
159485
159534
|
];
|
|
159486
|
-
const
|
|
159535
|
+
const containerized = await maybeContainerize({
|
|
159536
|
+
bin: this.opts.codexBin ?? "codex",
|
|
159537
|
+
args,
|
|
159538
|
+
cwd: dir,
|
|
159539
|
+
job,
|
|
159540
|
+
...this.opts.workRoot !== void 0 ? { workRoot: this.opts.workRoot } : {},
|
|
159541
|
+
...this.opts.env !== void 0 ? { extraEnvEarly: this.opts.env } : {}
|
|
159542
|
+
});
|
|
159543
|
+
const child = containerized ? (0, import_node_child_process9.spawn)(containerized.bin, containerized.args, {
|
|
159544
|
+
cwd: dir,
|
|
159545
|
+
env: scrubLeakyEnv(process.env),
|
|
159546
|
+
// stdin 的开合口径与宿主分支一致:codex 只在走 stdin 时才该收到管道(见下方长注释)。
|
|
159547
|
+
// 容器包装本身带 `-i`,podman 会把这条管道透传给容器内进程。
|
|
159548
|
+
stdio: [promptViaStdin ? "pipe" : "ignore", "pipe", "pipe"]
|
|
159549
|
+
}) : (0, import_node_child_process9.spawn)(this.opts.codexBin ?? "codex", args, {
|
|
159487
159550
|
cwd: dir,
|
|
159488
159551
|
env: {
|
|
159489
159552
|
...scrubLeakyEnv(process.env),
|
|
@@ -159598,6 +159661,7 @@ var init_codex = __esm({
|
|
|
159598
159661
|
};
|
|
159599
159662
|
const timer = setTimeout(() => {
|
|
159600
159663
|
killReason ??= "timeout";
|
|
159664
|
+
if (containerized) killContainerBestEffort(containerized.containerName, containerized.mode);
|
|
159601
159665
|
child.kill("SIGKILL");
|
|
159602
159666
|
}, job.limits.wallClockMs);
|
|
159603
159667
|
child.on("error", () => {
|
|
@@ -159625,13 +159689,16 @@ var init_codex = __esm({
|
|
|
159625
159689
|
...telemetry.usage ? { usage: telemetry.usage } : {},
|
|
159626
159690
|
...model ? { model } : {},
|
|
159627
159691
|
...runtimeSessionId ? { runtimeSessionId } : {},
|
|
159628
|
-
...errorMessage ? { errorMessage } : {}
|
|
159692
|
+
...errorMessage ? { errorMessage } : {},
|
|
159693
|
+
// 跑在哪个镜像上要落账:同一题换了镜像,分数就不可比(ADR-0147 M5)
|
|
159694
|
+
...containerized?.imageDigest ? { imageDigest: containerized.imageDigest } : {}
|
|
159629
159695
|
});
|
|
159630
159696
|
});
|
|
159631
159697
|
return {
|
|
159632
159698
|
id,
|
|
159633
159699
|
async kill() {
|
|
159634
159700
|
killReason ??= "cancelled";
|
|
159701
|
+
if (containerized) killContainerBestEffort(containerized.containerName, containerized.mode);
|
|
159635
159702
|
child.kill("SIGKILL");
|
|
159636
159703
|
},
|
|
159637
159704
|
onExit(cb) {
|
|
@@ -160073,6 +160140,20 @@ function joinOutputParts(parts) {
|
|
|
160073
160140
|
if (parts.every((p2) => typeof p2 === "string")) return parts.join("");
|
|
160074
160141
|
return parts;
|
|
160075
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
|
+
}
|
|
160076
160157
|
function normalizeACPUpdate(data) {
|
|
160077
160158
|
const d = data;
|
|
160078
160159
|
if (!d) return ["", data];
|
|
@@ -160321,7 +160402,8 @@ async function runACPSession(job, cfg) {
|
|
|
160321
160402
|
if (reason === "cancelled") finish({ code: null, reason: "cancelled", transcriptRef });
|
|
160322
160403
|
},
|
|
160323
160404
|
() => streamingCurrentTurn,
|
|
160324
|
-
cfg.finalUsageIsAuthoritative === true
|
|
160405
|
+
cfg.finalUsageIsAuthoritative === true,
|
|
160406
|
+
cfg.vendorUsageNotification
|
|
160325
160407
|
);
|
|
160326
160408
|
usageClient = client;
|
|
160327
160409
|
const rl = readline3.createInterface({ input: child.stdout });
|
|
@@ -160491,7 +160573,7 @@ ${task}` : task;
|
|
|
160491
160573
|
}
|
|
160492
160574
|
};
|
|
160493
160575
|
}
|
|
160494
|
-
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;
|
|
160495
160577
|
var init_acp = __esm({
|
|
160496
160578
|
"../adapters/src/_core/acp.ts"() {
|
|
160497
160579
|
"use strict";
|
|
@@ -160510,13 +160592,14 @@ var init_acp = __esm({
|
|
|
160510
160592
|
init_transcript();
|
|
160511
160593
|
init_filter_extra_args();
|
|
160512
160594
|
ACPClient = class {
|
|
160513
|
-
constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false) {
|
|
160595
|
+
constructor(write, onOutput, onTelemetry, onStop, acceptNotification = () => true, finalUsageIsAuthoritative = false, vendorUsage) {
|
|
160514
160596
|
this.write = write;
|
|
160515
160597
|
this.onOutput = onOutput;
|
|
160516
160598
|
this.onTelemetry = onTelemetry;
|
|
160517
160599
|
this.onStop = onStop;
|
|
160518
160600
|
this.acceptNotification = acceptNotification;
|
|
160519
160601
|
this.finalUsageIsAuthoritative = finalUsageIsAuthoritative;
|
|
160602
|
+
this.vendorUsage = vendorUsage;
|
|
160520
160603
|
}
|
|
160521
160604
|
nextId = 0;
|
|
160522
160605
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -160530,7 +160613,37 @@ var init_acp = __esm({
|
|
|
160530
160613
|
* 是否还在流。每收到一条 session/update / session/notification 就 +1,主循环轮询该值。
|
|
160531
160614
|
*/
|
|
160532
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
|
+
}
|
|
160533
160645
|
request(method, params) {
|
|
160646
|
+
if (this.vendorUsage && method === "session/prompt") this.foldVendorTurn();
|
|
160534
160647
|
const id = this.nextId++;
|
|
160535
160648
|
return new Promise((resolve10, reject) => {
|
|
160536
160649
|
this.pending.set(id, { resolve: resolve10, reject, method });
|
|
@@ -160582,11 +160695,15 @@ var init_acp = __esm({
|
|
|
160582
160695
|
handleAgentRequest(raw) {
|
|
160583
160696
|
const method = raw["method"];
|
|
160584
160697
|
const id = raw["id"];
|
|
160585
|
-
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}` } };
|
|
160586
160699
|
this.write(JSON.stringify(resp) + "\n");
|
|
160587
160700
|
}
|
|
160588
160701
|
handleNotification(raw) {
|
|
160589
160702
|
const method = raw["method"];
|
|
160703
|
+
if (this.vendorUsage && method === this.vendorUsage.method) {
|
|
160704
|
+
this.applyVendorUsage(raw["params"]);
|
|
160705
|
+
return;
|
|
160706
|
+
}
|
|
160590
160707
|
if (method !== "session/update" && method !== "session/notification") return;
|
|
160591
160708
|
const params = raw["params"];
|
|
160592
160709
|
if (!params?.update) return;
|
|
@@ -160745,6 +160862,7 @@ var init_acp = __esm({
|
|
|
160745
160862
|
});
|
|
160746
160863
|
}
|
|
160747
160864
|
};
|
|
160865
|
+
LEGACY_APPROVE_OPTION_ID = "approve_for_session";
|
|
160748
160866
|
}
|
|
160749
160867
|
});
|
|
160750
160868
|
|
|
@@ -160846,6 +160964,72 @@ var init_kiro = __esm({
|
|
|
160846
160964
|
}
|
|
160847
160965
|
});
|
|
160848
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
|
+
|
|
160849
161033
|
// ../adapters/src/_core/subprocess.ts
|
|
160850
161034
|
async function materialize(job, cfg) {
|
|
160851
161035
|
const slug6 = job.artifactId.replace(/[^a-zA-Z0-9_-]+/g, "_").slice(0, 32);
|
|
@@ -161926,6 +162110,7 @@ var init_src6 = __esm({
|
|
|
161926
162110
|
init_hermes();
|
|
161927
162111
|
init_kimi();
|
|
161928
162112
|
init_kiro();
|
|
162113
|
+
init_reasonix();
|
|
161929
162114
|
init_cursor();
|
|
161930
162115
|
init_codebuddy();
|
|
161931
162116
|
init_gemini();
|
|
@@ -163913,6 +164098,7 @@ async function startOasisServer(opts) {
|
|
|
163913
164098
|
...tokenClaims.artifactId !== void 0 ? { artifactId: tokenClaims.artifactId } : {},
|
|
163914
164099
|
durableRefs: tokenClaims.artifactId !== void 0 ? [{ kind: "artifact", id: tokenClaims.artifactId, label: body.command }] : [],
|
|
163915
164100
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
164101
|
+
...listArg("pendingSteps") ? { pendingSteps: listArg("pendingSteps") } : {},
|
|
163916
164102
|
...delivered ? { delivered } : {}
|
|
163917
164103
|
});
|
|
163918
164104
|
} catch (error2) {
|
|
@@ -166274,7 +166460,14 @@ var init_memory_registry_store = __esm({
|
|
|
166274
166460
|
this.skillFiles.delete(skillId);
|
|
166275
166461
|
}
|
|
166276
166462
|
async putVariable(v2) {
|
|
166277
|
-
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 });
|
|
166278
166471
|
}
|
|
166279
166472
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
166280
166473
|
const mk = this._varKey(key, actorId);
|
|
@@ -174422,9 +174615,37 @@ ${input.description}
|
|
|
174422
174615
|
// 非连接器写入到此 deliveryMode 必非空(上面已拦);连接器写入沿用 env(其值经 sensitiveVars 剔除,不进 env)。
|
|
174423
174616
|
deliveryMode: v2.deliveryMode ?? "env",
|
|
174424
174617
|
valueEncrypted: v2.encrypted === false ? `plain:${v2.value}` : this.encrypt(v2.value),
|
|
174425
|
-
updatedAt: this.now()
|
|
174618
|
+
updatedAt: this.now(),
|
|
174619
|
+
// ADR 凭据保险库补章 §D2.2:expiresAt 写侧穿透——**显式带 key**(含 undefined),使清空(传空→undefined)
|
|
174620
|
+
// 也落到底(store 两实现都按此覆盖)。lastUsedAt 从不由写侧传,取用时另刷(§D2.3)。
|
|
174621
|
+
expiresAt: v2.expiresAt
|
|
174426
174622
|
});
|
|
174427
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
|
+
}
|
|
174428
174649
|
/** 更新已有变量的 encrypted 属性(重新加密或解密),不改其他字段 */
|
|
174429
174650
|
async patchVariableEncryption(key, actorId, encrypted) {
|
|
174430
174651
|
const ct = await this.opts.store.getVariableCiphertext(key, actorId);
|
|
@@ -174463,7 +174684,10 @@ ${input.description}
|
|
|
174463
174684
|
// 缺省视为 env(ADR §4.4;存量行读侧统一回填)
|
|
174464
174685
|
encrypted: !isPlain,
|
|
174465
174686
|
maskedValue: isPlain ? r.valueEncrypted.slice(6) : mask(this.decrypt(r.valueEncrypted)),
|
|
174466
|
-
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 } : {}
|
|
174467
174691
|
};
|
|
174468
174692
|
});
|
|
174469
174693
|
}
|
|
@@ -174556,7 +174780,12 @@ ${input.description}
|
|
|
174556
174780
|
const gated = (row) => !row.connectorId || enabledConnectors.has(row.connectorId);
|
|
174557
174781
|
const put = (row) => {
|
|
174558
174782
|
if (!gated(row)) return;
|
|
174559
|
-
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
|
+
});
|
|
174560
174789
|
};
|
|
174561
174790
|
for (const row of rows) {
|
|
174562
174791
|
if (row.scope === "global" && !row.actorId) put(row);
|
|
@@ -174576,7 +174805,7 @@ ${input.description}
|
|
|
174576
174805
|
async resolveRevealValue(actorId, key, opts) {
|
|
174577
174806
|
const entries = await this.resolveActorProvisionEntries(actorId, { ...opts, refreshConnectors: false });
|
|
174578
174807
|
const hit = entries.find((e) => e.key === key);
|
|
174579
|
-
return hit ? { value: hit.value } : null;
|
|
174808
|
+
return hit ? { value: hit.value, ...hit.origin ? { origin: hit.origin } : {} } : null;
|
|
174580
174809
|
}
|
|
174581
174810
|
encrypt(plain) {
|
|
174582
174811
|
const iv = (0, import_node_crypto26.randomBytes)(12);
|
|
@@ -175805,6 +176034,21 @@ var init_connector_skills = __esm({
|
|
|
175805
176034
|
function isKnownRevealSource(source) {
|
|
175806
176035
|
return CREDENTIAL_REVEAL_SOURCES.has(source) || source.startsWith("agent-skill:");
|
|
175807
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
|
+
}
|
|
175808
176052
|
function positionsFromPayload(body) {
|
|
175809
176053
|
if (!body) return void 0;
|
|
175810
176054
|
if (Object.prototype.hasOwnProperty.call(body, "roles")) {
|
|
@@ -175839,6 +176083,8 @@ function actorsDomain(opts) {
|
|
|
175839
176083
|
const { resolveCtx } = opts;
|
|
175840
176084
|
const revealLimits = opts.credentialRevealLimits ?? { perSession: 200, perSessionPerKey: 20 };
|
|
175841
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);
|
|
175842
176088
|
return (router) => {
|
|
175843
176089
|
router.get("/api/actors", async (req) => {
|
|
175844
176090
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
@@ -176125,11 +176371,6 @@ function actorsDomain(opts) {
|
|
|
176125
176371
|
}
|
|
176126
176372
|
};
|
|
176127
176373
|
const auditVariableChange = async (req, kind, variableKey, targetScope) => {
|
|
176128
|
-
const fwd = req.raw?.headers?.["x-forwarded-for"];
|
|
176129
|
-
const fwdFirst = (Array.isArray(fwd) ? fwd[0] : fwd)?.split(",")[0]?.trim();
|
|
176130
|
-
const clientIp = fwdFirst || req.raw?.socket?.remoteAddress || void 0;
|
|
176131
|
-
const ua = req.raw?.headers?.["user-agent"];
|
|
176132
|
-
const userAgent = (Array.isArray(ua) ? ua[0] : ua) || void 0;
|
|
176133
176374
|
await opts.credentialAudit?.({
|
|
176134
176375
|
kind,
|
|
176135
176376
|
actor: req.auth.actor,
|
|
@@ -176137,8 +176378,7 @@ function actorsDomain(opts) {
|
|
|
176137
176378
|
targetScope,
|
|
176138
176379
|
source: "console",
|
|
176139
176380
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
176140
|
-
...
|
|
176141
|
-
...userAgent ? { userAgent } : {}
|
|
176381
|
+
...clientMetaFromReq(req)
|
|
176142
176382
|
});
|
|
176143
176383
|
};
|
|
176144
176384
|
router.get("/api/variables", async (req) => {
|
|
@@ -176151,6 +176391,7 @@ function actorsDomain(opts) {
|
|
|
176151
176391
|
const { service } = await resolveCtx(req.auth.companyId);
|
|
176152
176392
|
const b2 = req.body;
|
|
176153
176393
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
176394
|
+
const expiresAt2 = normalizeExpiresAt(b2.expiresAt);
|
|
176154
176395
|
if (b2.scope !== "global" && b2.scope !== "personal" && b2.scope !== "project") {
|
|
176155
176396
|
throw new ApiError(
|
|
176156
176397
|
400,
|
|
@@ -176191,7 +176432,8 @@ function actorsDomain(opts) {
|
|
|
176191
176432
|
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
176192
176433
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
176193
176434
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
176194
|
-
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
176435
|
+
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {},
|
|
176436
|
+
expiresAt: expiresAt2
|
|
176195
176437
|
});
|
|
176196
176438
|
await auditVariableChange(
|
|
176197
176439
|
req,
|
|
@@ -176229,6 +176471,7 @@ function actorsDomain(opts) {
|
|
|
176229
176471
|
const actorId = req.params.id;
|
|
176230
176472
|
const b2 = req.body;
|
|
176231
176473
|
if (!b2?.key) throw new ApiError(400, "BAD_REQUEST", "\u7F3A\u5C11 key");
|
|
176474
|
+
const expiresAt2 = normalizeExpiresAt(b2.expiresAt);
|
|
176232
176475
|
if (b2.deliveryMode !== void 0 && b2.deliveryMode !== "env" && b2.deliveryMode !== "ref" && b2.deliveryMode !== "broker") {
|
|
176233
176476
|
throw new ApiError(400, "BAD_REQUEST", "deliveryMode \u53EA\u80FD\u662F env\u3001ref \u6216 broker");
|
|
176234
176477
|
}
|
|
@@ -176259,7 +176502,8 @@ function actorsDomain(opts) {
|
|
|
176259
176502
|
...b2.deliveryMode !== void 0 ? { deliveryMode: b2.deliveryMode } : {},
|
|
176260
176503
|
...b2.connectorId !== void 0 ? { connectorId: b2.connectorId } : {},
|
|
176261
176504
|
...b2.overrides !== void 0 ? { overrides: b2.overrides } : {},
|
|
176262
|
-
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {}
|
|
176505
|
+
...b2.encrypted !== void 0 ? { encrypted: b2.encrypted } : {},
|
|
176506
|
+
expiresAt: expiresAt2
|
|
176263
176507
|
});
|
|
176264
176508
|
await auditVariableChange(req, "credential_write", b2.key, `personal:${actorId}`);
|
|
176265
176509
|
return { status: 201, body: { ok: true } };
|
|
@@ -176280,25 +176524,33 @@ function actorsDomain(opts) {
|
|
|
176280
176524
|
const source = typeof b2?.source === "string" && b2.source.trim() || "agent-cli";
|
|
176281
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`);
|
|
176282
176526
|
const actor = req.auth.actor;
|
|
176527
|
+
const isHuman2 = isHumanActor(actor);
|
|
176528
|
+
const isConsole = source === "console";
|
|
176529
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
176283
176530
|
const artifactId = req.auth.dispatch?.artifactId;
|
|
176284
176531
|
const sessionId = req.auth.dispatch?.sessionId;
|
|
176285
|
-
const now = Date.now();
|
|
176286
|
-
const timestamp = new Date(now).toISOString();
|
|
176287
|
-
const sessionKey = sessionId ?? `${actor}::${artifactId ?? "no-artifact"}`;
|
|
176288
176532
|
const dispatchFields = { ...sessionId ? { sessionId } : {}, ...artifactId ? { artifactId } : {} };
|
|
176289
|
-
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);
|
|
176290
176542
|
if (throttled) {
|
|
176291
|
-
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 });
|
|
176292
176544
|
return { status: 429, body: { code: "throttled", key, scope: throttled } };
|
|
176293
176545
|
}
|
|
176294
|
-
const
|
|
176295
|
-
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) : {});
|
|
176296
176547
|
if (!resolved) {
|
|
176297
176548
|
const reason = await service.hasVariableKey(key) ? "no_permission" : "not_found";
|
|
176298
|
-
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 });
|
|
176299
176550
|
return { status: 403, body: { code: "denied", key } };
|
|
176300
176551
|
}
|
|
176301
|
-
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);
|
|
176302
176554
|
return { status: 200, body: { value: resolved.value } };
|
|
176303
176555
|
});
|
|
176304
176556
|
router.get("/api/variables/reveal-audit", async (req) => {
|
|
@@ -176801,7 +177053,7 @@ var init_routes2 = __esm({
|
|
|
176801
177053
|
init_image_upload();
|
|
176802
177054
|
init_skill_materializer();
|
|
176803
177055
|
init_connector_skills();
|
|
176804
|
-
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"]);
|
|
176805
177057
|
RevealRateLimiter = class {
|
|
176806
177058
|
constructor(perSession, perSessionPerKey, ttlMs = 2 * 60 * 6e4) {
|
|
176807
177059
|
this.perSession = perSession;
|
|
@@ -183017,8 +183269,8 @@ function executionContinuityDomain(service) {
|
|
|
183017
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)) {
|
|
183018
183270
|
throw new ApiError(400, "BAD_REQUEST", "handoff arrays contain invalid values");
|
|
183019
183271
|
}
|
|
183020
|
-
if (!isUserHandoff(b2.userHandoff)) {
|
|
183021
|
-
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");
|
|
183022
183274
|
}
|
|
183023
183275
|
const handoff = await service.handoff({
|
|
183024
183276
|
attemptId,
|
|
@@ -183069,10 +183321,20 @@ function renderResumePack(pack) {
|
|
|
183069
183321
|
if (!pack.previousAttempt) lines.push("- This is the first attempt.");
|
|
183070
183322
|
else {
|
|
183071
183323
|
lines.push(`- Attempt ${pack.previousAttempt.attemptNo ?? "?"}: ${pack.previousHandoff?.summary || pack.previousAttempt.status}`);
|
|
183072
|
-
|
|
183073
|
-
|
|
183074
|
-
|
|
183075
|
-
|
|
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
|
+
);
|
|
183076
183338
|
}
|
|
183077
183339
|
}
|
|
183078
183340
|
lines.push("", "## External effects");
|
|
@@ -183181,6 +183443,7 @@ function renderCoordinatorView(view) {
|
|
|
183181
183443
|
function shouldInjectResumePack(pack) {
|
|
183182
183444
|
const status = pack?.previousAttempt?.status;
|
|
183183
183445
|
if (!status) return false;
|
|
183446
|
+
if (status === "running" || status === "queued") return false;
|
|
183184
183447
|
return status !== "succeeded" && status !== "no-output";
|
|
183185
183448
|
}
|
|
183186
183449
|
function renderContinuityProtocol() {
|
|
@@ -183413,9 +183676,6 @@ var init_service7 = __esm({
|
|
|
183413
183676
|
async handoff(input) {
|
|
183414
183677
|
if (!HANDOFF_OUTCOMES2.has(input.outcome)) throw new Error(`invalid handoff outcome: ${input.outcome}`);
|
|
183415
183678
|
if (!input.summary.trim()) throw new Error("handoff summary is required");
|
|
183416
|
-
if (input.producedBy === "agent" && !input.userHandoff) {
|
|
183417
|
-
throw new Error("agent-authored handoff requires userHandoff");
|
|
183418
|
-
}
|
|
183419
183679
|
const userHandoff = input.userHandoff ? normalizeUserHandoff(input.outcome, input.changedOutputs ?? [], input.userHandoff) : void 0;
|
|
183420
183680
|
const attempt = await this.awaitAttempt(input.attemptId);
|
|
183421
183681
|
const handoff = await this.afterAttemptVisible(() => this.store.putHandoff({
|
|
@@ -183619,8 +183879,7 @@ var init_service7 = __esm({
|
|
|
183619
183879
|
"failed"
|
|
183620
183880
|
].map((state) => [state, nodes.filter((node) => node.nodeState === state).length]));
|
|
183621
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";
|
|
183622
|
-
|
|
183623
|
-
return { workOrderId, mode: this.mode, collaborationStatus, handoffSummary, progress, nodes, dependencyBlocks, todo: todos };
|
|
183882
|
+
return { workOrderId, mode: this.mode, collaborationStatus, progress, nodes, dependencyBlocks, todo: todos };
|
|
183624
183883
|
}
|
|
183625
183884
|
};
|
|
183626
183885
|
}
|
|
@@ -183662,15 +183921,20 @@ var init_handoff_work_bridge = __esm({
|
|
|
183662
183921
|
|
|
183663
183922
|
// ../server/src/domains/execution-continuity/upstream-handoff-input.ts
|
|
183664
183923
|
function renderRefs(refs) {
|
|
183665
|
-
return refs.map(
|
|
183666
|
-
|
|
183667
|
-
|
|
183924
|
+
return refs.map((ref2) => {
|
|
183925
|
+
const label = ref2.id.startsWith(`${ref2.kind}:`) ? ref2.id : `${ref2.kind}:${ref2.id}`;
|
|
183926
|
+
return `- ${label}${ref2.version ? `@${ref2.version}` : ""}${ref2.label ? ` \u2014 ${ref2.label}` : ""}`;
|
|
183927
|
+
});
|
|
183668
183928
|
}
|
|
183669
183929
|
function bounded(text) {
|
|
183670
183930
|
const t = text.trim();
|
|
183671
183931
|
return [...t].length <= INJECTED_TEXT_LIMIT ? t : `${[...t].slice(0, INJECTED_TEXT_LIMIT).join("")}\u2026\uFF08\u539F\u6587\u8FC7\u957F\uFF0C\u6B64\u5904\u622A\u65AD\uFF1B\u5B8C\u6574\u5185\u5BB9\u89C1\u8BE5\u4E0A\u6E38\u8282\u70B9\u7684\u4EA4\u4ED8\u8BF4\u660E\uFF09`;
|
|
183672
183932
|
}
|
|
183933
|
+
function isExplicitNone(values) {
|
|
183934
|
+
return values.length === 1 && NONE_TOKENS.has((values[0] ?? "").trim().toLowerCase());
|
|
183935
|
+
}
|
|
183673
183936
|
function renderList(title, values) {
|
|
183937
|
+
if (isExplicitNone(values)) return [`## ${title}`, "- \u6267\u884C\u4EBA\u786E\u8BA4\uFF1A\u65E0", ""];
|
|
183674
183938
|
return [
|
|
183675
183939
|
`## ${title}`,
|
|
183676
183940
|
...values.length > 0 ? values.map((value) => `- ${value}`) : ["- None"],
|
|
@@ -183750,8 +184014,7 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
183750
184014
|
const edge = snapshot.edges.find(
|
|
183751
184015
|
(candidate) => candidate.fromNodeId === input.upstreamNodeId && candidate.toNodeId === input.downstreamNodeId
|
|
183752
184016
|
);
|
|
183753
|
-
const
|
|
183754
|
-
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;
|
|
183755
184018
|
if (!businessEdge) return null;
|
|
183756
184019
|
if (edge.pinnedWorkId !== input.pinnedWorkId) {
|
|
183757
184020
|
warn(
|
|
@@ -183813,12 +184076,12 @@ function createUpstreamHandoffInputResolver(opts) {
|
|
|
183813
184076
|
}
|
|
183814
184077
|
};
|
|
183815
184078
|
}
|
|
183816
|
-
var INJECTED_TEXT_LIMIT;
|
|
184079
|
+
var INJECTED_TEXT_LIMIT, NONE_TOKENS;
|
|
183817
184080
|
var init_upstream_handoff_input = __esm({
|
|
183818
184081
|
"../server/src/domains/execution-continuity/upstream-handoff-input.ts"() {
|
|
183819
184082
|
"use strict";
|
|
183820
|
-
init_src3();
|
|
183821
184083
|
INJECTED_TEXT_LIMIT = 4e3;
|
|
184084
|
+
NONE_TOKENS = /* @__PURE__ */ new Set(["none", "n/a", "na", "nil", "\u65E0", "\u6CA1\u6709", "\u6682\u65E0"]);
|
|
183822
184085
|
}
|
|
183823
184086
|
});
|
|
183824
184087
|
|
|
@@ -188029,7 +188292,10 @@ function rowToVariable(row) {
|
|
|
188029
188292
|
// **不塌成 env**,否则未知档位读回来变明文;仅 null/空回填 "env"(存量行)。派单侧按未知档保守处理。
|
|
188030
188293
|
deliveryMode: typeof row.delivery_mode === "string" && row.delivery_mode ? row.delivery_mode : "env",
|
|
188031
188294
|
valueEncrypted: row.value_encrypted,
|
|
188032
|
-
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 } : {}
|
|
188033
188299
|
};
|
|
188034
188300
|
}
|
|
188035
188301
|
var ident4, PostgresRegistryStore, rowToActor, rowToConfig, rowToAgentPrefs;
|
|
@@ -188192,6 +188458,8 @@ var init_postgres_registry = __esm({
|
|
|
188192
188458
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS project_id text`);
|
|
188193
188459
|
await pool.query(`ALTER TABLE IF EXISTS "${s2}".variables ADD COLUMN IF NOT EXISTS environment text`);
|
|
188194
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`);
|
|
188195
188463
|
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_key_actor_uq"`);
|
|
188196
188464
|
await pool.query(`DROP INDEX IF EXISTS "${s2}"."${s2}_variables_scope_uq"`);
|
|
188197
188465
|
await pool.query(`
|
|
@@ -188668,10 +188936,10 @@ var init_postgres_registry = __esm({
|
|
|
188668
188936
|
/* ---------- 变量 ---------- */
|
|
188669
188937
|
async putVariable(v2) {
|
|
188670
188938
|
await this.pool.query(
|
|
188671
|
-
`INSERT INTO ${this.s}.variables (key, scope, actor_id, project_id, connector_id, overrides, delivery_mode, value_encrypted, updated_at)
|
|
188672
|
-
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)
|
|
188673
188941
|
ON CONFLICT (key, COALESCE(actor_id, ''), COALESCE(project_id, '')) DO UPDATE
|
|
188674
|
-
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`,
|
|
188675
188943
|
[
|
|
188676
188944
|
v2.key,
|
|
188677
188945
|
v2.scope,
|
|
@@ -188681,10 +188949,18 @@ var init_postgres_registry = __esm({
|
|
|
188681
188949
|
v2.overrides ?? null,
|
|
188682
188950
|
v2.deliveryMode ?? null,
|
|
188683
188951
|
v2.valueEncrypted,
|
|
188684
|
-
v2.updatedAt
|
|
188952
|
+
v2.updatedAt,
|
|
188953
|
+
v2.expiresAt ?? null
|
|
188685
188954
|
]
|
|
188686
188955
|
);
|
|
188687
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
|
+
}
|
|
188688
188964
|
async patchVariableValue(key, actorId, valueEncrypted, updatedAt) {
|
|
188689
188965
|
const aid = actorId ?? null;
|
|
188690
188966
|
await this.pool.query(
|
|
@@ -194415,6 +194691,15 @@ async function buildActorProvision(service, actorId, scope, onBrokerRefused) {
|
|
|
194415
194691
|
const brokerRefused = [];
|
|
194416
194692
|
applyRefDelivery(env, entries, void 0, (k2) => brokerRefused.push(k2));
|
|
194417
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
|
+
}
|
|
194418
194703
|
return {
|
|
194419
194704
|
env,
|
|
194420
194705
|
wrapperPaths: [oasisWrapperScript(), ...provision.wrapperPaths],
|
|
@@ -195726,7 +196011,10 @@ async function startServe(opts) {
|
|
|
195726
196011
|
...await materializeSkillFiles({ service: actors.service, actorId, runtimeKind })
|
|
195727
196012
|
}),
|
|
195728
196013
|
uploadChatAttachment: async ({ contentBase64 }) => ({ blobRef: await assets.put(new Uint8Array(Buffer.from(contentBase64, "base64"))) }),
|
|
195729
|
-
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
|
+
}
|
|
195730
196018
|
traceStoreSink.checkpoint(dispatchId, {
|
|
195731
196019
|
trigger: "important_output",
|
|
195732
196020
|
// 交作业的那条命令带着版本号(`wk:<节点>:<n>`),比笼统的「动过这个产物」有用得多——
|
|
@@ -197696,12 +197984,13 @@ var KNOWN2 = [
|
|
|
197696
197984
|
{ adapter: "copilot", binary: "copilot" },
|
|
197697
197985
|
{ adapter: "kimi", binary: "kimi" },
|
|
197698
197986
|
{ adapter: "kiro", binary: "kiro-cli" },
|
|
197987
|
+
{ adapter: "reasonix", binary: "reasonix" },
|
|
197699
197988
|
{ adapter: "pi", binary: "pi" },
|
|
197700
197989
|
{ adapter: "openclaw", binary: "openclaw" },
|
|
197701
197990
|
{ adapter: "codebuddy", binary: "codebuddy" },
|
|
197702
197991
|
{ adapter: "antigravity", binary: "agy" }
|
|
197703
197992
|
];
|
|
197704
|
-
var NATIVE_APPEND_RUNTIMES = /* @__PURE__ */ new Set(["hermes", "gemini", "kimi", "kiro"]);
|
|
197993
|
+
var NATIVE_APPEND_RUNTIMES = /* @__PURE__ */ new Set(["hermes", "gemini", "kimi", "kiro", "reasonix"]);
|
|
197705
197994
|
function onPath(binary) {
|
|
197706
197995
|
try {
|
|
197707
197996
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -198505,6 +198794,7 @@ async function startNode(opts) {
|
|
|
198505
198794
|
copilot: new CopilotAdapter(),
|
|
198506
198795
|
kimi: new KimiAdapter(),
|
|
198507
198796
|
kiro: new KiroAdapter(),
|
|
198797
|
+
reasonix: new ReasonixAdapter(),
|
|
198508
198798
|
pi: new PiAdapter(),
|
|
198509
198799
|
openclaw: new OpenClawAdapter(),
|
|
198510
198800
|
codebuddy: new CodebuddyAdapter(),
|
|
@@ -198989,7 +199279,8 @@ var COMMAND_DECLS = {
|
|
|
198989
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" },
|
|
198990
199280
|
{ name: "risks", desc: "\u4E0B\u6E38\u8BE5\u77E5\u9053\u7684\u98CE\u9669\uFF08\u5206\u53F7\u5206\u9694\uFF09" },
|
|
198991
199281
|
{ name: "next", desc: "\u5EFA\u8BAE\u4E0B\u6E38\u63A5\u7740\u505A\u4EC0\u4E48\uFF08\u5206\u53F7\u5206\u9694\uFF09" },
|
|
198992
|
-
{ 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" }
|
|
198993
199284
|
],
|
|
198994
199285
|
examples: [
|
|
198995
199286
|
'oasis propose artifact:dev:abc-123 --from-dir deliverable/ --reason "\u4FEE\u590D\u767B\u5F55\u9875\u767D\u5C4F"',
|
|
@@ -201675,7 +201966,9 @@ ${res.warning}`);
|
|
|
201675
201966
|
...semicolonList(flags.get("unresolved"), "unresolvedIssues"),
|
|
201676
201967
|
...semicolonList(flags.get("risks"), "risks"),
|
|
201677
201968
|
...semicolonList(flags.get("next"), "nextActions"),
|
|
201678
|
-
...semicolonList(flags.get("gaps"), "verificationGaps")
|
|
201969
|
+
...semicolonList(flags.get("gaps"), "verificationGaps"),
|
|
201970
|
+
// 「还剩什么没做」:唯一系统推不出来的字段,挂在本来就要跑的命令上(见 server 的 pendingSteps 注释)
|
|
201971
|
+
...semicolonList(flags.get("pending"), "pendingSteps")
|
|
201679
201972
|
});
|
|
201680
201973
|
println(message);
|
|
201681
201974
|
break;
|
|
@@ -202949,7 +203242,7 @@ function syncRuntimeAssets(candidateRoots, binDir) {
|
|
|
202949
203242
|
}
|
|
202950
203243
|
|
|
202951
203244
|
// src/index.ts
|
|
202952
|
-
var PKG_VERSION = true ? "0.1.
|
|
203245
|
+
var PKG_VERSION = true ? "0.1.109" : "dev";
|
|
202953
203246
|
var OASIS_DIR = path28.join(os11.homedir(), ".oasis");
|
|
202954
203247
|
var CONFIG_FILE = path28.join(OASIS_DIR, "node-config.json");
|
|
202955
203248
|
var PID_FILE = path28.join(OASIS_DIR, "node.pid");
|