oasis_test_v2 2.2.20 → 2.2.21
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 +467 -157
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -4082,7 +4082,8 @@ var init_model = __esm({
|
|
|
4082
4082
|
BUSINESS_HANDOFF_POLICY_FIELD = "businessHandoffPolicy";
|
|
4083
4083
|
BUSINESS_HANDOFF_POLICY_EXEMPT = "exempt";
|
|
4084
4084
|
DEFAULT_CONFIG = {
|
|
4085
|
-
maxRetries: 3
|
|
4085
|
+
maxRetries: 3,
|
|
4086
|
+
maxStagnantCheckpoints: 3
|
|
4086
4087
|
};
|
|
4087
4088
|
deriveWorkId = (nodeId, version2) => `wk:${nodeId}:${version2}`;
|
|
4088
4089
|
deriveReviewId = (workId, reviewer, group) => `rv:${workId}:${reviewer}:${group}`;
|
|
@@ -4090,6 +4091,101 @@ var init_model = __esm({
|
|
|
4090
4091
|
}
|
|
4091
4092
|
});
|
|
4092
4093
|
|
|
4094
|
+
// ../engine/src/closure-gate.ts
|
|
4095
|
+
function closureSlotOfFacts(facts) {
|
|
4096
|
+
const report = facts.liveClosureReport();
|
|
4097
|
+
if (report) return { kind: "closure-report", id: report.id };
|
|
4098
|
+
const business = facts.liveBusinessNodes();
|
|
4099
|
+
if (business.length === 1) return { kind: "sole-artifact", id: business[0].id };
|
|
4100
|
+
if (business.length === 0) return { kind: "empty" };
|
|
4101
|
+
return { kind: "missing", businessCount: business.length };
|
|
4102
|
+
}
|
|
4103
|
+
function humanGateActorsOfFacts(facts, artifactId) {
|
|
4104
|
+
const slot = closureSlotOfFacts(facts);
|
|
4105
|
+
if (slot.kind !== "closure-report" && slot.kind !== "sole-artifact") return [];
|
|
4106
|
+
if (slot.id !== artifactId) return [];
|
|
4107
|
+
const owner = facts.humanOwner();
|
|
4108
|
+
return owner === null ? [] : [owner];
|
|
4109
|
+
}
|
|
4110
|
+
function closureReviewGroup(actor) {
|
|
4111
|
+
return `closure:${actor}`;
|
|
4112
|
+
}
|
|
4113
|
+
function closureReviewerSpecs(closureActors) {
|
|
4114
|
+
return closureActors.map((actor) => ({
|
|
4115
|
+
reviewerActorId: actor,
|
|
4116
|
+
reviewGroup: closureReviewGroup(actor),
|
|
4117
|
+
source: "closure"
|
|
4118
|
+
}));
|
|
4119
|
+
}
|
|
4120
|
+
function engineClosureFacts(state) {
|
|
4121
|
+
return {
|
|
4122
|
+
liveBusinessNodes: () => state.liveNodes().filter((n) => n.type !== BRIEF_TYPE && n.type !== DELIVERY_SUMMARY_TYPE).map((n) => ({ id: n.id, type: n.type })),
|
|
4123
|
+
liveClosureReport: () => {
|
|
4124
|
+
const r = state.liveNodes().find((n) => n.type === DELIVERY_SUMMARY_TYPE);
|
|
4125
|
+
return r ? { id: r.id, type: r.type } : null;
|
|
4126
|
+
},
|
|
4127
|
+
humanOwner: () => {
|
|
4128
|
+
const brief = state.liveNodes().find((n) => n.type === BRIEF_TYPE);
|
|
4129
|
+
const owner = brief?.assigneeActorId;
|
|
4130
|
+
if (!owner || !owner.startsWith(HUMAN_ACTOR_PREFIX)) return null;
|
|
4131
|
+
return owner;
|
|
4132
|
+
}
|
|
4133
|
+
};
|
|
4134
|
+
}
|
|
4135
|
+
function engineWorkorderHumanOwner(state) {
|
|
4136
|
+
return engineClosureFacts(state).humanOwner();
|
|
4137
|
+
}
|
|
4138
|
+
function engineHumanGateActors(state, nodeId) {
|
|
4139
|
+
return humanGateActorsOfFacts(engineClosureFacts(state), nodeId);
|
|
4140
|
+
}
|
|
4141
|
+
var DELIVERY_SUMMARY_TYPE, BRIEF_TYPE, HUMAN_ACTOR_PREFIX;
|
|
4142
|
+
var init_closure_gate = __esm({
|
|
4143
|
+
"../engine/src/closure-gate.ts"() {
|
|
4144
|
+
"use strict";
|
|
4145
|
+
DELIVERY_SUMMARY_TYPE = "delivery-summary";
|
|
4146
|
+
BRIEF_TYPE = "brief";
|
|
4147
|
+
HUMAN_ACTOR_PREFIX = "actor:human:";
|
|
4148
|
+
}
|
|
4149
|
+
});
|
|
4150
|
+
|
|
4151
|
+
// ../engine/src/continuation.ts
|
|
4152
|
+
function continuationApprover(state) {
|
|
4153
|
+
const owner = engineWorkorderHumanOwner(state);
|
|
4154
|
+
if (owner || state.liveNodes().some((node2) => node2.type === "brief")) return owner;
|
|
4155
|
+
return state.workorder.ownerActorId.startsWith("actor:human:") ? state.workorder.ownerActorId : null;
|
|
4156
|
+
}
|
|
4157
|
+
function continuationUsedRounds(state, nodeId) {
|
|
4158
|
+
const withOutput = new Set(state.artifactsOfNode(nodeId).map((a) => a.workId));
|
|
4159
|
+
return state.mainWorksOf(nodeId).filter((w2) => w2.assigneeActorId.startsWith("actor:agent:") && (w2.startedAt || w2.sessionRef || w2.lastActivityAt || withOutput.has(w2.id))).length;
|
|
4160
|
+
}
|
|
4161
|
+
function continuationAwaitingStart(state, work) {
|
|
4162
|
+
return work.status === "running" && !work.endedAt && !work.deadAt && !work.cancelledAt && !work.startedAt && !work.sessionRef && !work.lastActivityAt && state.artifactsOf(work.id).length === 0;
|
|
4163
|
+
}
|
|
4164
|
+
function continuationExhausted(state, node2) {
|
|
4165
|
+
const budget = node2.continuationBudget;
|
|
4166
|
+
return !!budget && (budget.request?.decision === "denied" || budget.request?.decision === "pending" || continuationUsedRounds(state, node2.id) >= budget.authorizedRounds);
|
|
4167
|
+
}
|
|
4168
|
+
function continuationRequestId(node2) {
|
|
4169
|
+
return `continuation:${node2.id}:${node2.continuationBudget.requestGeneration + 1}`;
|
|
4170
|
+
}
|
|
4171
|
+
function continuationSummary(state, node2, rounds) {
|
|
4172
|
+
const used = continuationUsedRounds(state, node2.id);
|
|
4173
|
+
const latest = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
4174
|
+
const output = node2.latestProposedWorkId ? state.work(node2.latestProposedWorkId) : latest;
|
|
4175
|
+
const files = output ? state.artifactsOf(output.id) : [];
|
|
4176
|
+
return `\u300A${node2.title}\u300B\u5C1A\u672A\u5B8C\u6210\uFF0C\u5DF2\u8FBE\u5230\u81EA\u52A8\u6D3E\u53D1\u4E0A\u9650\u3002\u7D2F\u8BA1\u5DF2\u8FD0\u884C ${used} \u8F6E\uFF0C\u5DF2\u6388\u6743 ${node2.continuationBudget.authorizedRounds} \u8F6E\u3002
|
|
4177
|
+
\u9636\u6BB5\u6210\u679C\uFF1A${files.length ? files.map((a) => a.logicalPath).join("\u3001") : "\u6682\u65E0\u5DF2\u63D0\u4EA4\u7684\u4EA4\u4ED8\u5185\u5BB9"}\u3002
|
|
4178
|
+
\u6700\u8FD1 checkpoint \u8BF4\u660E\uFF08\u6267\u884C\u4EBA\u539F\u6587\uFF09\uFF1A${output?.proposalReason || "\u672A\u77E5\uFF0C\u672A\u63D0\u4F9B"}
|
|
4179
|
+
\u5269\u4F59\u4E8B\u9879\u53CA\u4E0B\u4E00\u6279\u8BA1\u5212\uFF1A\u4EE5\u4EE5\u4E0A\u8BF4\u660E\u4E3A\u4F9D\u636E\uFF1B\u672A\u660E\u786E\u63D0\u4F9B\u7684\u90E8\u5206\u672A\u77E5\uFF0C\u9700\u4EBA\u5DE5\u786E\u8BA4\u3002
|
|
4180
|
+
\u540C\u610F\u540E\u6700\u591A\u518D\u8FD0\u884C ${rounds} \u8F6E\uFF1B\u62D2\u7EDD\u6216\u4E0D\u56DE\u590D\u5C06\u4FDD\u6301\u6682\u505C\u5E76\u4FDD\u7559\u6210\u679C\uFF0C\u4E0D\u81EA\u52A8\u5BA3\u544A\u5B8C\u6210\u3002`;
|
|
4181
|
+
}
|
|
4182
|
+
var init_continuation = __esm({
|
|
4183
|
+
"../engine/src/continuation.ts"() {
|
|
4184
|
+
"use strict";
|
|
4185
|
+
init_closure_gate();
|
|
4186
|
+
}
|
|
4187
|
+
});
|
|
4188
|
+
|
|
4093
4189
|
// ../engine/src/events.ts
|
|
4094
4190
|
function eventAnchors(e) {
|
|
4095
4191
|
switch (e.kind) {
|
|
@@ -4334,6 +4430,10 @@ var init_state = __esm({
|
|
|
4334
4430
|
artifactsOf(workId) {
|
|
4335
4431
|
return this.artifactList.filter((a) => a.workId === workId);
|
|
4336
4432
|
}
|
|
4433
|
+
/** 多批次分析一次读取本节点全部快照,避免每个 work 再扫整单产物。 */
|
|
4434
|
+
artifactsOfNode(nodeId) {
|
|
4435
|
+
return this.artifactList.filter((a) => a.nodeId === nodeId);
|
|
4436
|
+
}
|
|
4337
4437
|
workInputsOf(workId) {
|
|
4338
4438
|
return this.workInputList.filter((i) => i.workId === workId);
|
|
4339
4439
|
}
|
|
@@ -4491,60 +4591,6 @@ var init_state = __esm({
|
|
|
4491
4591
|
}
|
|
4492
4592
|
});
|
|
4493
4593
|
|
|
4494
|
-
// ../engine/src/closure-gate.ts
|
|
4495
|
-
function closureSlotOfFacts(facts) {
|
|
4496
|
-
const report = facts.liveClosureReport();
|
|
4497
|
-
if (report) return { kind: "closure-report", id: report.id };
|
|
4498
|
-
const business = facts.liveBusinessNodes();
|
|
4499
|
-
if (business.length === 1) return { kind: "sole-artifact", id: business[0].id };
|
|
4500
|
-
if (business.length === 0) return { kind: "empty" };
|
|
4501
|
-
return { kind: "missing", businessCount: business.length };
|
|
4502
|
-
}
|
|
4503
|
-
function humanGateActorsOfFacts(facts, artifactId) {
|
|
4504
|
-
const slot = closureSlotOfFacts(facts);
|
|
4505
|
-
if (slot.kind !== "closure-report" && slot.kind !== "sole-artifact") return [];
|
|
4506
|
-
if (slot.id !== artifactId) return [];
|
|
4507
|
-
const owner = facts.humanOwner();
|
|
4508
|
-
return owner === null ? [] : [owner];
|
|
4509
|
-
}
|
|
4510
|
-
function closureReviewGroup(actor) {
|
|
4511
|
-
return `closure:${actor}`;
|
|
4512
|
-
}
|
|
4513
|
-
function closureReviewerSpecs(closureActors) {
|
|
4514
|
-
return closureActors.map((actor) => ({
|
|
4515
|
-
reviewerActorId: actor,
|
|
4516
|
-
reviewGroup: closureReviewGroup(actor),
|
|
4517
|
-
source: "closure"
|
|
4518
|
-
}));
|
|
4519
|
-
}
|
|
4520
|
-
function engineClosureFacts(state) {
|
|
4521
|
-
return {
|
|
4522
|
-
liveBusinessNodes: () => state.liveNodes().filter((n) => n.type !== BRIEF_TYPE && n.type !== DELIVERY_SUMMARY_TYPE).map((n) => ({ id: n.id, type: n.type })),
|
|
4523
|
-
liveClosureReport: () => {
|
|
4524
|
-
const r = state.liveNodes().find((n) => n.type === DELIVERY_SUMMARY_TYPE);
|
|
4525
|
-
return r ? { id: r.id, type: r.type } : null;
|
|
4526
|
-
},
|
|
4527
|
-
humanOwner: () => {
|
|
4528
|
-
const brief = state.liveNodes().find((n) => n.type === BRIEF_TYPE);
|
|
4529
|
-
const owner = brief?.assigneeActorId;
|
|
4530
|
-
if (!owner || !owner.startsWith(HUMAN_ACTOR_PREFIX)) return null;
|
|
4531
|
-
return owner;
|
|
4532
|
-
}
|
|
4533
|
-
};
|
|
4534
|
-
}
|
|
4535
|
-
function engineHumanGateActors(state, nodeId) {
|
|
4536
|
-
return humanGateActorsOfFacts(engineClosureFacts(state), nodeId);
|
|
4537
|
-
}
|
|
4538
|
-
var DELIVERY_SUMMARY_TYPE, BRIEF_TYPE, HUMAN_ACTOR_PREFIX;
|
|
4539
|
-
var init_closure_gate = __esm({
|
|
4540
|
-
"../engine/src/closure-gate.ts"() {
|
|
4541
|
-
"use strict";
|
|
4542
|
-
DELIVERY_SUMMARY_TYPE = "delivery-summary";
|
|
4543
|
-
BRIEF_TYPE = "brief";
|
|
4544
|
-
HUMAN_ACTOR_PREFIX = "actor:human:";
|
|
4545
|
-
}
|
|
4546
|
-
});
|
|
4547
|
-
|
|
4548
4594
|
// ../engine/src/letters.ts
|
|
4549
4595
|
function repliesSorted(state, issueId) {
|
|
4550
4596
|
return [...state.repliesOf(issueId)].sort((a, b2) => a.createdAt.localeCompare(b2.createdAt));
|
|
@@ -4701,6 +4747,26 @@ function scan(state, ctx) {
|
|
|
4701
4747
|
const events = [];
|
|
4702
4748
|
for (const node2 of state.liveNodes()) {
|
|
4703
4749
|
const lw = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
4750
|
+
const continuationPolicy = node2.assigneeActorId ? ctx.continuationPolicies?.get(node2.assigneeActorId) : null;
|
|
4751
|
+
if (!node2.continuationBudget && continuationPolicy) {
|
|
4752
|
+
events.push({ kind: "continuation.initialized", workorderId: state.workorder.id, nodeId: node2.id, rounds: continuationPolicy.maxRounds });
|
|
4753
|
+
continue;
|
|
4754
|
+
}
|
|
4755
|
+
const delivered = node2.latestProposedWorkId ? state.work(node2.latestProposedWorkId) : null;
|
|
4756
|
+
const hasCurrentDelivery = delivered?.status === "success" && !delivered.deadAt && (delivered.conclusion != null || node2.latestAcceptId === delivered.id) && delivered.nodeVersion === node2.version && inputsMatch(state, node2, delivered);
|
|
4757
|
+
if (node2.continuationBudget && continuationExhausted(state, node2) && !hasCurrentDelivery && (!lw || lw.endedAt || lw.deadAt || continuationAwaitingStart(state, lw))) {
|
|
4758
|
+
const requestId = continuationRequestId(node2);
|
|
4759
|
+
if (node2.continuationBudget.request?.decision !== "pending" && node2.continuationBudget.request?.decision !== "denied") {
|
|
4760
|
+
events.push({
|
|
4761
|
+
kind: "continuation.requested",
|
|
4762
|
+
workorderId: state.workorder.id,
|
|
4763
|
+
nodeId: node2.id,
|
|
4764
|
+
requestId,
|
|
4765
|
+
rounds: continuationPolicy?.maxRounds ?? node2.continuationBudget.roundsPerGrant
|
|
4766
|
+
});
|
|
4767
|
+
}
|
|
4768
|
+
continue;
|
|
4769
|
+
}
|
|
4704
4770
|
if (!lw) {
|
|
4705
4771
|
tryToRun(state, node2.id, ctx, events);
|
|
4706
4772
|
continue;
|
|
@@ -4994,6 +5060,20 @@ function scanBlockersForNode(state, node2, latest) {
|
|
|
4994
5060
|
function tryToRun(state, nodeId, ctx, events) {
|
|
4995
5061
|
const node2 = state.node(nodeId);
|
|
4996
5062
|
if (!node2) return;
|
|
5063
|
+
if (continuationExhausted(state, node2)) {
|
|
5064
|
+
const latest2 = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
5065
|
+
const request2 = node2.continuationBudget?.request;
|
|
5066
|
+
if ((!latest2 || latest2.endedAt || latest2.deadAt) && request2?.decision !== "pending" && request2?.decision !== "denied") {
|
|
5067
|
+
events.push({
|
|
5068
|
+
kind: "continuation.requested",
|
|
5069
|
+
workorderId: state.workorder.id,
|
|
5070
|
+
nodeId: node2.id,
|
|
5071
|
+
requestId: continuationRequestId(node2),
|
|
5072
|
+
rounds: (node2.assigneeActorId ? ctx.continuationPolicies?.get(node2.assigneeActorId)?.maxRounds : null) ?? node2.continuationBudget.roundsPerGrant
|
|
5073
|
+
});
|
|
5074
|
+
} else if (latest2 && !latest2.endedAt && !latest2.deadAt) checkRunningWorkTimeout(state, node2, latest2, ctx, events);
|
|
5075
|
+
return;
|
|
5076
|
+
}
|
|
4997
5077
|
if (!node2.assigneeActorId) return;
|
|
4998
5078
|
const latest = (node2.latestWorkId ? state.work(node2.latestWorkId) : null) ?? null;
|
|
4999
5079
|
if (unexemptedVetoBlockers(scanBlockersForNode(state, node2, latest), "dispatch").length > 0) {
|
|
@@ -5092,19 +5172,34 @@ function findHumanRecoveryPost(state, node2, deadAt) {
|
|
|
5092
5172
|
const first = candidates[0];
|
|
5093
5173
|
return first ? { actorId: first.actorId, at: first.at } : null;
|
|
5094
5174
|
}
|
|
5095
|
-
function
|
|
5096
|
-
const works = state.mainWorksOf(nodeId).sort((a, b2) =>
|
|
5175
|
+
function countStagnantCheckpoints(state, nodeId) {
|
|
5176
|
+
const works = state.mainWorksOf(nodeId).sort((a, b2) => a.createdAt.localeCompare(b2.createdAt) || a.id.localeCompare(b2.id, "en", { numeric: true }));
|
|
5177
|
+
const contents = /* @__PURE__ */ new Map();
|
|
5178
|
+
for (const a of state.artifactsOfNode(nodeId)) {
|
|
5179
|
+
const parts = contents.get(a.workId) ?? [];
|
|
5180
|
+
parts.push(JSON.stringify([a.logicalPath, a.contentKind, a.contentRef]));
|
|
5181
|
+
contents.set(a.workId, parts);
|
|
5182
|
+
}
|
|
5183
|
+
const seen = /* @__PURE__ */ new Set();
|
|
5097
5184
|
let count2 = 0;
|
|
5185
|
+
let version2;
|
|
5098
5186
|
for (const w2 of works) {
|
|
5099
|
-
if (w2.retryAt)
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5105
|
-
|
|
5106
|
-
|
|
5107
|
-
|
|
5187
|
+
if (w2.retryAt || w2.status === "success" && w2.conclusion != null) {
|
|
5188
|
+
seen.clear();
|
|
5189
|
+
count2 = 0;
|
|
5190
|
+
version2 = void 0;
|
|
5191
|
+
}
|
|
5192
|
+
if (w2.status !== "success") continue;
|
|
5193
|
+
const parts = contents.get(w2.id);
|
|
5194
|
+
if (!parts?.length) continue;
|
|
5195
|
+
if (version2 !== void 0 && version2 !== w2.nodeVersion) {
|
|
5196
|
+
seen.clear();
|
|
5197
|
+
count2 = 0;
|
|
5198
|
+
}
|
|
5199
|
+
version2 = w2.nodeVersion;
|
|
5200
|
+
const signature = JSON.stringify(parts.sort());
|
|
5201
|
+
count2 = !w2.retryAt && w2.conclusion == null && seen.has(signature) ? count2 + 1 : 0;
|
|
5202
|
+
seen.add(signature);
|
|
5108
5203
|
}
|
|
5109
5204
|
return count2;
|
|
5110
5205
|
}
|
|
@@ -5123,8 +5218,8 @@ function countConsecutiveRejections(state, nodeId) {
|
|
|
5123
5218
|
return count2;
|
|
5124
5219
|
}
|
|
5125
5220
|
function unconcludedCheckpointsExhausted(state, nodeId, ctx) {
|
|
5126
|
-
const limit = ctx.config?.
|
|
5127
|
-
const rounds =
|
|
5221
|
+
const limit = ctx.config?.maxStagnantCheckpoints ?? DEFAULT_CONFIG.maxStagnantCheckpoints;
|
|
5222
|
+
const rounds = countStagnantCheckpoints(state, nodeId);
|
|
5128
5223
|
return rounds > limit ? { rounds, limit } : null;
|
|
5129
5224
|
}
|
|
5130
5225
|
function gateRejectionsExhausted(state, nodeId, ctx) {
|
|
@@ -5478,6 +5573,7 @@ function assessConvergence(state, ctx) {
|
|
|
5478
5573
|
var init_activate = __esm({
|
|
5479
5574
|
"../engine/src/activate.ts"() {
|
|
5480
5575
|
"use strict";
|
|
5576
|
+
init_continuation();
|
|
5481
5577
|
init_src3();
|
|
5482
5578
|
init_src2();
|
|
5483
5579
|
init_model();
|
|
@@ -5532,6 +5628,7 @@ CREATE TABLE IF NOT EXISTS ${q2}.workflow_nodes (
|
|
|
5532
5628
|
latest_accept_id text,
|
|
5533
5629
|
is_final_output boolean NOT NULL DEFAULT false,
|
|
5534
5630
|
fields jsonb,
|
|
5631
|
+
continuation_budget jsonb,
|
|
5535
5632
|
cancelled_at timestamptz,
|
|
5536
5633
|
-- \u5C01\u5B58\u539F\u56E0\uFF08accepted/cancelled/frozen\uFF09\u3002NULL = \u5B58\u91CF\u884C\uFF0C\u8BFB\u6A21\u578B\u6309 cancelled \u515C\u5E95\u3002
|
|
5537
5634
|
seal_reason text,
|
|
@@ -5539,6 +5636,7 @@ CREATE TABLE IF NOT EXISTS ${q2}.workflow_nodes (
|
|
|
5539
5636
|
created_at timestamptz NOT NULL,
|
|
5540
5637
|
updated_at timestamptz NOT NULL
|
|
5541
5638
|
);
|
|
5639
|
+
ALTER TABLE ${q2}.workflow_nodes ADD COLUMN IF NOT EXISTS continuation_budget jsonb;
|
|
5542
5640
|
CREATE INDEX IF NOT EXISTS nodes_workorder_idx ON ${q2}.workflow_nodes (workorder_id);
|
|
5543
5641
|
|
|
5544
5642
|
CREATE TABLE IF NOT EXISTS ${q2}.workflow_edges (
|
|
@@ -11444,6 +11542,7 @@ var init_store_postgres = __esm({
|
|
|
11444
11542
|
// NULL = 存量行(ADR 0137 迁移批量置的 cancelled_at):按 cancelled 读,不追溯改写历史。
|
|
11445
11543
|
sealReason: n.seal_reason ?? null,
|
|
11446
11544
|
fields: n.fields ?? void 0,
|
|
11545
|
+
continuationBudget: n.continuation_budget ?? null,
|
|
11447
11546
|
rowVersion: n.row_version,
|
|
11448
11547
|
createdAt: iso(n.created_at),
|
|
11449
11548
|
updatedAt: iso(n.updated_at)
|
|
@@ -11625,8 +11724,8 @@ var init_store_postgres = __esm({
|
|
|
11625
11724
|
`INSERT INTO ${this.s}.workflow_nodes
|
|
11626
11725
|
(id,workorder_id,type,title,spec,version,assignee_actor_id,assignee_role,
|
|
11627
11726
|
latest_work_id,latest_proposed_work_id,latest_accept_id,is_final_output,
|
|
11628
|
-
fields,cancelled_at,seal_reason,row_version,created_at,updated_at)
|
|
11629
|
-
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)
|
|
11727
|
+
fields,cancelled_at,seal_reason,row_version,created_at,updated_at,continuation_budget)
|
|
11728
|
+
VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19)
|
|
11630
11729
|
ON CONFLICT (id) DO NOTHING`,
|
|
11631
11730
|
[
|
|
11632
11731
|
n.id,
|
|
@@ -11646,13 +11745,14 @@ var init_store_postgres = __esm({
|
|
|
11646
11745
|
n.sealReason ?? null,
|
|
11647
11746
|
n.rowVersion,
|
|
11648
11747
|
n.createdAt,
|
|
11649
|
-
n.updatedAt
|
|
11748
|
+
n.updatedAt,
|
|
11749
|
+
n.continuationBudget ? JSON.stringify(n.continuationBudget) : null
|
|
11650
11750
|
]
|
|
11651
11751
|
);
|
|
11652
11752
|
break;
|
|
11653
11753
|
}
|
|
11654
11754
|
case "node.update":
|
|
11655
|
-
await this.patch("workflow_nodes", "id", m2.id, m2.patch, { fields: true });
|
|
11755
|
+
await this.patch("workflow_nodes", "id", m2.id, m2.patch, { fields: true, continuationBudget: true });
|
|
11656
11756
|
break;
|
|
11657
11757
|
case "edge.insert": {
|
|
11658
11758
|
const e = m2.row;
|
|
@@ -12076,7 +12176,7 @@ function newNode(id, workorderId, at, version2) {
|
|
|
12076
12176
|
updatedAt: at
|
|
12077
12177
|
};
|
|
12078
12178
|
}
|
|
12079
|
-
function markNodeForRetry(state, nodeId, at, resetRejectedBudget = false) {
|
|
12179
|
+
function markNodeForRetry(state, nodeId, at, resetRejectedBudget = false, resetCheckpointBudget = false) {
|
|
12080
12180
|
const node2 = state.node(nodeId);
|
|
12081
12181
|
if (!node2) return;
|
|
12082
12182
|
const lw = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
@@ -12085,6 +12185,9 @@ function markNodeForRetry(state, nodeId, at, resetRejectedBudget = false) {
|
|
|
12085
12185
|
}
|
|
12086
12186
|
if (lw && !lw.deadAt && workState(lw, hasOutput(lw, state.artifactsOf(lw.id).length)) === "success") {
|
|
12087
12187
|
if (resetRejectedBudget && lw.acceptanceState === "rejected") state.updateWork(lw.id, { retryAt: at });
|
|
12188
|
+
if (resetCheckpointBudget && lw.conclusion == null && state.artifactsOf(lw.id).length > 0) {
|
|
12189
|
+
state.updateWork(lw.id, { retryAt: at });
|
|
12190
|
+
}
|
|
12088
12191
|
for (const req of state.requirementsOf(node2.id)) {
|
|
12089
12192
|
if (!req.latestReviewId) continue;
|
|
12090
12193
|
const r = state.review(req.latestReviewId);
|
|
@@ -12216,7 +12319,7 @@ var init_plan = __esm({
|
|
|
12216
12319
|
const changed = node2.assigneeActorId !== e.assigneeActorId;
|
|
12217
12320
|
const lw = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
12218
12321
|
const settled = lw !== null && lw !== void 0 && workState(lw, hasOutput(lw, state.artifactsOf(lw.id).length)) === "success";
|
|
12219
|
-
if (changed && e.resetRejectedBudget === true && lw &&
|
|
12322
|
+
if (changed && lw && !lw.deadAt && settled && (e.resetRejectedBudget === true && lw.acceptanceState === "rejected" || e.resetCheckpointBudget === true && lw.conclusion == null && state.artifactsOf(lw.id).length > 0)) {
|
|
12220
12323
|
state.updateWork(lw.id, { retryAt: ctx.at });
|
|
12221
12324
|
}
|
|
12222
12325
|
state.updateNode(e.nodeId, {
|
|
@@ -12291,7 +12394,7 @@ var init_plan = __esm({
|
|
|
12291
12394
|
name: "plan/node-retry",
|
|
12292
12395
|
kind: "plan.node_retry",
|
|
12293
12396
|
apply(e, state, ctx) {
|
|
12294
|
-
markNodeForRetry(state, e.nodeId, ctx.at, e.resetRejectedBudget === true);
|
|
12397
|
+
markNodeForRetry(state, e.nodeId, ctx.at, e.resetRejectedBudget === true, e.resetCheckpointBudget === true);
|
|
12295
12398
|
}
|
|
12296
12399
|
};
|
|
12297
12400
|
planUpdateFields = {
|
|
@@ -12429,7 +12532,8 @@ var init_workorder = __esm({
|
|
|
12429
12532
|
workorderId: e.workorderId,
|
|
12430
12533
|
nodeId: node2.id,
|
|
12431
12534
|
by: e.by,
|
|
12432
|
-
resetRejectedBudget: e.resetRejectedBudget
|
|
12535
|
+
resetRejectedBudget: e.resetRejectedBudget,
|
|
12536
|
+
resetCheckpointBudget: e.resetCheckpointBudget
|
|
12433
12537
|
}, state, ctx);
|
|
12434
12538
|
}
|
|
12435
12539
|
}
|
|
@@ -12452,6 +12556,7 @@ var workCreate, workRedispatch, workSnapshotRecorded, workKill, workResponse, wo
|
|
|
12452
12556
|
var init_work = __esm({
|
|
12453
12557
|
"../engine/src/handlers/work.ts"() {
|
|
12454
12558
|
"use strict";
|
|
12559
|
+
init_continuation();
|
|
12455
12560
|
init_views2();
|
|
12456
12561
|
init_kill();
|
|
12457
12562
|
init_letters();
|
|
@@ -12500,6 +12605,7 @@ var init_work = __esm({
|
|
|
12500
12605
|
});
|
|
12501
12606
|
return;
|
|
12502
12607
|
}
|
|
12608
|
+
if (e.continuationGateVersion === 1 && continuationExhausted(state, node2)) return;
|
|
12503
12609
|
supersedeLatestWork(state, e.nodeId, ctx.at);
|
|
12504
12610
|
killNodeReviews(state, e.nodeId, ctx.at);
|
|
12505
12611
|
for (const w2 of state.replyWorksOf(e.nodeId)) {
|
|
@@ -12980,7 +13086,7 @@ var init_issue = __esm({
|
|
|
12980
13086
|
}
|
|
12981
13087
|
if (issue2.kind === "gap" || issue2.kind === "escalation") {
|
|
12982
13088
|
const nodeId = issue2.raisedByNodeId ?? issue2.aboutNodeId;
|
|
12983
|
-
if (nodeId) markNodeForRetry(state, nodeId, ctx.at, e.resetRejectedBudget === true);
|
|
13089
|
+
if (nodeId) markNodeForRetry(state, nodeId, ctx.at, e.resetRejectedBudget === true, e.resetCheckpointBudget === true);
|
|
12984
13090
|
}
|
|
12985
13091
|
}
|
|
12986
13092
|
};
|
|
@@ -13181,6 +13287,10 @@ var init_review = __esm({
|
|
|
13181
13287
|
}
|
|
13182
13288
|
return;
|
|
13183
13289
|
}
|
|
13290
|
+
const budget = state.node(w2.nodeId)?.continuationBudget;
|
|
13291
|
+
if (budget?.request && (budget.request.decision === "pending" || budget.request.decision === "denied")) {
|
|
13292
|
+
state.updateNode(w2.nodeId, { continuationBudget: { ...budget, request: { ...budget.request, decision: "completed" } } });
|
|
13293
|
+
}
|
|
13184
13294
|
state.updateNode(w2.nodeId, { latestAcceptId: e.workId, updatedAt: ctx.at });
|
|
13185
13295
|
state.updateWork(e.workId, {
|
|
13186
13296
|
acceptanceState: "accepted",
|
|
@@ -13300,6 +13410,67 @@ var init_review = __esm({
|
|
|
13300
13410
|
}
|
|
13301
13411
|
});
|
|
13302
13412
|
|
|
13413
|
+
// ../engine/src/handlers/continuation.ts
|
|
13414
|
+
var validRounds, continuationInitialize, continuationRequest, continuationDecide;
|
|
13415
|
+
var init_continuation2 = __esm({
|
|
13416
|
+
"../engine/src/handlers/continuation.ts"() {
|
|
13417
|
+
"use strict";
|
|
13418
|
+
init_continuation();
|
|
13419
|
+
validRounds = (n) => Number.isSafeInteger(n) && n >= 1 && n <= 100;
|
|
13420
|
+
continuationInitialize = {
|
|
13421
|
+
name: "continuation/initialize",
|
|
13422
|
+
kind: "continuation.initialized",
|
|
13423
|
+
apply(e, state) {
|
|
13424
|
+
const node2 = state.node(e.nodeId);
|
|
13425
|
+
if (!node2 || node2.continuationBudget || !validRounds(e.rounds)) return;
|
|
13426
|
+
state.updateNode(node2.id, { continuationBudget: { authorizedRounds: e.rounds, requestGeneration: 0, roundsPerGrant: e.rounds, request: null } });
|
|
13427
|
+
}
|
|
13428
|
+
};
|
|
13429
|
+
continuationRequest = {
|
|
13430
|
+
name: "continuation/request",
|
|
13431
|
+
kind: "continuation.requested",
|
|
13432
|
+
apply(e, state, ctx) {
|
|
13433
|
+
const node2 = state.node(e.nodeId);
|
|
13434
|
+
if (!node2 || node2.cancelledAt || !node2.continuationBudget || !validRounds(e.rounds) || continuationRequestId(node2) !== e.requestId || !continuationExhausted(state, node2) || node2.continuationBudget.request?.decision === "pending" || node2.continuationBudget.request?.decision === "denied") return;
|
|
13435
|
+
const latest = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
13436
|
+
if (latest && !latest.endedAt && !latest.deadAt && !continuationAwaitingStart(state, latest)) return;
|
|
13437
|
+
state.updateNode(node2.id, { continuationBudget: {
|
|
13438
|
+
...node2.continuationBudget,
|
|
13439
|
+
requestGeneration: node2.continuationBudget.requestGeneration + 1,
|
|
13440
|
+
request: {
|
|
13441
|
+
id: e.requestId,
|
|
13442
|
+
at: ctx.at,
|
|
13443
|
+
rounds: e.rounds,
|
|
13444
|
+
usedRounds: continuationUsedRounds(state, node2.id),
|
|
13445
|
+
summary: continuationSummary(state, node2, e.rounds),
|
|
13446
|
+
decision: "pending"
|
|
13447
|
+
}
|
|
13448
|
+
} });
|
|
13449
|
+
}
|
|
13450
|
+
};
|
|
13451
|
+
continuationDecide = {
|
|
13452
|
+
name: "continuation/decide",
|
|
13453
|
+
kind: "continuation.decided",
|
|
13454
|
+
apply(e, state, ctx) {
|
|
13455
|
+
const node2 = state.node(e.nodeId);
|
|
13456
|
+
const budget = node2?.continuationBudget;
|
|
13457
|
+
const request2 = budget?.request;
|
|
13458
|
+
if (!node2 || node2.cancelledAt || !budget || !request2 || request2.id !== e.requestId || request2.decision !== "pending" || !ctx.actorId.startsWith("actor:human:") || ctx.actorId !== continuationApprover(state)) return;
|
|
13459
|
+
state.updateNode(node2.id, { continuationBudget: {
|
|
13460
|
+
...budget,
|
|
13461
|
+
authorizedRounds: e.approve ? Math.max(budget.authorizedRounds, continuationUsedRounds(state, node2.id)) + request2.rounds : budget.authorizedRounds,
|
|
13462
|
+
roundsPerGrant: request2.rounds,
|
|
13463
|
+
request: { ...request2, decision: e.approve ? "approved" : "denied", decidedBy: ctx.actorId, decidedAt: ctx.at, reason: e.reason }
|
|
13464
|
+
} });
|
|
13465
|
+
const latest = node2.latestWorkId ? state.work(node2.latestWorkId) : null;
|
|
13466
|
+
if (e.approve && latest && continuationAwaitingStart(state, latest)) {
|
|
13467
|
+
state.emit({ kind: "work.redispatch", workorderId: e.workorderId, workId: latest.id });
|
|
13468
|
+
}
|
|
13469
|
+
}
|
|
13470
|
+
};
|
|
13471
|
+
}
|
|
13472
|
+
});
|
|
13473
|
+
|
|
13303
13474
|
// ../engine/src/handlers/index.ts
|
|
13304
13475
|
var HANDLERS;
|
|
13305
13476
|
var init_handlers = __esm({
|
|
@@ -13311,6 +13482,7 @@ var init_handlers = __esm({
|
|
|
13311
13482
|
init_work();
|
|
13312
13483
|
init_review();
|
|
13313
13484
|
init_issue();
|
|
13485
|
+
init_continuation2();
|
|
13314
13486
|
init_types();
|
|
13315
13487
|
HANDLERS = [
|
|
13316
13488
|
/* ── 工作区级(5)── */
|
|
@@ -13331,6 +13503,9 @@ var init_handlers = __esm({
|
|
|
13331
13503
|
erase(planUpdateReviewRequirements),
|
|
13332
13504
|
erase(planNodeRetry),
|
|
13333
13505
|
erase(planUpdateFields),
|
|
13506
|
+
erase(continuationInitialize),
|
|
13507
|
+
erase(continuationRequest),
|
|
13508
|
+
erase(continuationDecide),
|
|
13334
13509
|
/* ── 节点级 work(7)── */
|
|
13335
13510
|
erase(workCreate),
|
|
13336
13511
|
erase(workRedispatch),
|
|
@@ -13365,7 +13540,7 @@ var init_handlers = __esm({
|
|
|
13365
13540
|
// ../engine/src/bus.ts
|
|
13366
13541
|
function versionCommandEvent(event) {
|
|
13367
13542
|
if (event.kind === "work.create" || event.kind === "review.create") {
|
|
13368
|
-
return { ...event, pauseGateVersion: 1 };
|
|
13543
|
+
return { ...event, pauseGateVersion: 1, ...event.kind === "work.create" ? { continuationGateVersion: 1 } : {} };
|
|
13369
13544
|
}
|
|
13370
13545
|
if (event.kind === "issue.reply") return { ...event, handlingVersion: 1 };
|
|
13371
13546
|
if (event.kind === "work.response" && event.semanticsVersion === 2) {
|
|
@@ -13379,11 +13554,11 @@ function versionCommandEvent(event) {
|
|
|
13379
13554
|
case "work.handoff_recorded":
|
|
13380
13555
|
return { ...event, semanticsVersion: 2 };
|
|
13381
13556
|
case "issue.resolve":
|
|
13382
|
-
return { ...event, semanticsVersion: 2, resetRejectedBudget: true };
|
|
13557
|
+
return { ...event, semanticsVersion: 2, resetRejectedBudget: true, resetCheckpointBudget: true };
|
|
13383
13558
|
case "plan.node_retry":
|
|
13384
13559
|
case "workorder.resumed":
|
|
13385
13560
|
case "plan.assign_actor":
|
|
13386
|
-
return { ...event, resetRejectedBudget: true };
|
|
13561
|
+
return { ...event, resetRejectedBudget: true, resetCheckpointBudget: true };
|
|
13387
13562
|
default:
|
|
13388
13563
|
return event;
|
|
13389
13564
|
}
|
|
@@ -13429,6 +13604,7 @@ var init_bus = __esm({
|
|
|
13429
13604
|
init_model();
|
|
13430
13605
|
init_handlers();
|
|
13431
13606
|
init_state();
|
|
13607
|
+
init_continuation();
|
|
13432
13608
|
SYSTEM_ACTOR = "actor:system:engine";
|
|
13433
13609
|
NOOP_IO = {
|
|
13434
13610
|
async dispatchWork() {
|
|
@@ -13915,6 +14091,21 @@ var init_bus = __esm({
|
|
|
13915
14091
|
const snap = await this.store.transaction((tx) => tx.loadWorkorder(workorderId));
|
|
13916
14092
|
if (!snap || snap.workorder.dispatchPaused) return false;
|
|
13917
14093
|
const work = snap.works.find((row) => row.id === workId);
|
|
14094
|
+
if (work && work.lane === "main" && !work.startedAt && !work.sessionRef && !work.lastActivityAt) {
|
|
14095
|
+
const node2 = snap.nodes.find((row) => row.id === work.nodeId);
|
|
14096
|
+
if (node2 && !node2.continuationBudget && this.io.continuationPolicy) {
|
|
14097
|
+
const policy = await this.io.continuationPolicy(work.assigneeActorId);
|
|
14098
|
+
if (policy) {
|
|
14099
|
+
if (!Number.isSafeInteger(policy.maxRounds) || policy.maxRounds < 1 || policy.maxRounds > 100) {
|
|
14100
|
+
throw new Error(`invalid continuation round limit for ${work.assigneeActorId}`);
|
|
14101
|
+
}
|
|
14102
|
+
buffered.push({ event: { kind: "continuation.initialized", workorderId, nodeId: node2.id, rounds: policy.maxRounds } });
|
|
14103
|
+
buffered.push({ event: { kind: "work.redispatch", workorderId, workId } });
|
|
14104
|
+
return false;
|
|
14105
|
+
}
|
|
14106
|
+
}
|
|
14107
|
+
if (node2 && continuationExhausted(new WorkorderState(snap), node2)) return false;
|
|
14108
|
+
}
|
|
13918
14109
|
if (opts?.neverStarted && work) {
|
|
13919
14110
|
const node2 = snap.nodes.find((row) => row.id === work.nodeId);
|
|
13920
14111
|
if (work.startedAt || work.sessionRef || !node2 || node2.cancelledAt || node2.latestWorkId !== workId) return false;
|
|
@@ -14024,7 +14215,21 @@ var init_bus = __esm({
|
|
|
14024
14215
|
if (!snapshot) return { emitted: 0, terminated: false };
|
|
14025
14216
|
if (snapshot.workorder.lifecycle !== "active") return { emitted: 0, terminated: false };
|
|
14026
14217
|
const state = new WorkorderState(snapshot);
|
|
14027
|
-
const
|
|
14218
|
+
const continuationPolicies = /* @__PURE__ */ new Map();
|
|
14219
|
+
if (this.io.continuationPolicy) {
|
|
14220
|
+
for (const node2 of state.liveNodes()) {
|
|
14221
|
+
const budget = node2.continuationBudget;
|
|
14222
|
+
if (budget && (!continuationExhausted(state, node2) || budget.request?.decision === "pending" || budget.request?.decision === "denied")) continue;
|
|
14223
|
+
if (node2.assigneeActorId && !continuationPolicies.has(node2.assigneeActorId)) {
|
|
14224
|
+
const policy = await this.io.continuationPolicy(node2.assigneeActorId);
|
|
14225
|
+
if (policy && (!Number.isSafeInteger(policy.maxRounds) || policy.maxRounds < 1 || policy.maxRounds > 100)) {
|
|
14226
|
+
throw new Error(`invalid continuation round limit for ${node2.assigneeActorId}`);
|
|
14227
|
+
}
|
|
14228
|
+
continuationPolicies.set(node2.assigneeActorId, policy);
|
|
14229
|
+
}
|
|
14230
|
+
}
|
|
14231
|
+
}
|
|
14232
|
+
const scanCtx = { continuationPolicies, at: this.clock.now(), actorId: SYSTEM_ACTOR, config: this.config, policy: this.policyOf() };
|
|
14028
14233
|
const { events, terminated } = scan(state, scanCtx);
|
|
14029
14234
|
await tx.applyMutations(workorderId, state.mutations);
|
|
14030
14235
|
const allEvents = [...state.emitted, ...events];
|
|
@@ -14159,6 +14364,7 @@ var init_src4 = __esm({
|
|
|
14159
14364
|
"../engine/src/index.ts"() {
|
|
14160
14365
|
"use strict";
|
|
14161
14366
|
init_model();
|
|
14367
|
+
init_continuation();
|
|
14162
14368
|
init_events();
|
|
14163
14369
|
init_views2();
|
|
14164
14370
|
init_state();
|
|
@@ -15296,6 +15502,7 @@ ${manifestDiff(baseC, newC)}
|
|
|
15296
15502
|
let skillsLines = [];
|
|
15297
15503
|
let identityNote = null;
|
|
15298
15504
|
let batchedContinuation = false;
|
|
15505
|
+
let continuationMaxRounds = 3;
|
|
15299
15506
|
let memoryEnabled = true;
|
|
15300
15507
|
let executorRole = null;
|
|
15301
15508
|
const executionActor = args.actorId ?? artifact.owner;
|
|
@@ -15303,6 +15510,7 @@ ${manifestDiff(baseC, newC)}
|
|
|
15303
15510
|
const actorCtx = await args.resolveActorContext(executionActor).catch(() => null);
|
|
15304
15511
|
if (actorCtx) {
|
|
15305
15512
|
batchedContinuation = actorCtx.config?.batchedContinuation === true;
|
|
15513
|
+
continuationMaxRounds = actorCtx.config?.continuationMaxRounds ?? 3;
|
|
15306
15514
|
memoryEnabled = actorCtx.memoryEnabled !== false;
|
|
15307
15515
|
executorRole = actorCtx.roles?.[0] ?? null;
|
|
15308
15516
|
if (actorCtx.config?.prompt) {
|
|
@@ -15674,7 +15882,7 @@ ${m2.spec.split("\n").map((l) => ` > ${l}`).join("\n")}`);
|
|
|
15674
15882
|
`- \u7F3A\u4E00\u4E2A**\u8FD8\u4E0D\u5B58\u5728\u7684\u524D\u7F6E** \u2192 \`oasis gap\` \u4EA4\u4E0A\u53BB\uFF0C**\u522B\u786C\u7F16**\uFF1B\u5DF2\u505A\u5B8C\u7684\u90E8\u5206\u7167\u5E38 \`propose\`\uFF0C\u4F46\u8FD9\u4E00\u8F6E \`conclude\` \u4F1A\u88AB\u62D2\uFF0C\u63D0\u4EA4\u5B8C\u5373\u6536\u5DE5\u2014\u2014\u524D\u7F6E\u5C31\u7EEA\u540E\u7CFB\u7EDF\u4F1A\u5E26\u7740\u89E3\u6CD5\u8BF4\u660E\u91CD\u65B0\u5524\u8D77\u4F60\u3002`,
|
|
15675
15883
|
`- \u5BF9**\u4E0A\u6E38**\u6709\u610F\u89C1\u2014\u2014\u6709\u7591\u95EE\u3001\u8981\u5B83\u6539\u3001\u5224\u5B83\u6CA1\u8FBE\u6807 \u2192 \`oasis annotate <\u4E0A\u6E38id> --body "<\u8BF4\u6E05\u695A>"\` \u540E**\u6536\u5DE5**\u3002\u5199\u7ED9\u4E0A\u6E38\u7684\u8BC4\u8BBA\u81EA\u52A8\u5E26\u963B\u585E\u529B\uFF1A**\u5B83\u7B54\u590D\u524D\u4E0D\u80FD\u6536\u5C3E**\uFF0C\u7B54\u590D\u540E\u7CFB\u7EDF\u91CD\u6D3E\u4F60\u3002`,
|
|
15676
15884
|
...args.part === void 0 ? [`- \u6D3B\u592A\u5927 / \u53EF\u5E76\u884C \u2192 \`oasis add-revision\` \u62C6\u6210\u5B50\u90E8\u4EF6\u6D3E\u51FA\u53BB\uFF0C\u522B\u4E00\u4EBA\u4E00\u4F1A\u8BDD\u786C\u625B\u3002`] : [],
|
|
15677
|
-
...batchedContinuation && args.part === void 0 ? [`- \u957F\u4EFB\u52A1\u5DF2\u5141\u8BB8\u5206\u6279\u7EED\u8DD1\uFF1A\u4E00\u6279\u6709\u8FDB\u5C55\u4F46\u6574\u4F53\u672A\u5B8C\u6210\u65F6\uFF0C\u6309\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u91CC\u7684 propose \u547D\u4EE4\u8FFD\u52A0 \`--checkpoint --continue\`\uFF0Creason \u5199\u6E05\u672C\u6279\u5B8C\u6210\u4E86\u4EC0\u4E48\u3001\u5269\u4EC0\u4E48\u3001\u4E0B\u6279\u4ECE\u54EA\u7EE7\u7EED\uFF0C\u7136\u540E\u6536\u5DE5\uFF1B\u7CFB\u7EDF\
|
|
15885
|
+
...batchedContinuation && args.part === void 0 ? [`- \u957F\u4EFB\u52A1\u5DF2\u5141\u8BB8\u5206\u6279\u7EED\u8DD1\uFF1A\u4E00\u6279\u6709\u8FDB\u5C55\u4F46\u6574\u4F53\u672A\u5B8C\u6210\u65F6\uFF0C\u6309\u300C\u600E\u4E48\u63D0\u4EA4\u300D\u91CC\u7684 propose \u547D\u4EE4\u8FFD\u52A0 \`--checkpoint --continue\`\uFF0Creason \u5199\u6E05\u672C\u6279\u5B8C\u6210\u4E86\u4EC0\u4E48\u3001\u5269\u4EC0\u4E48\u3001\u4E0B\u6279\u4ECE\u54EA\u7EE7\u7EED\uFF0C\u7136\u540E\u6536\u5DE5\uFF1B\u7CFB\u7EDF\u5728\u6BCF\u6B21\u6388\u6743\u7684 ${continuationMaxRounds} \u8F6E\u989D\u5EA6\u5185\u6D3E\u53D1\u4E0B\u4E00\u8F6E\u6B63\u5F0F session\uFF08\u9996\u6B21\u6267\u884C\u4E5F\u8BA1\u4E00\u8F6E\uFF09\uFF0C\u5230\u9650\u5C1A\u672A conclude \u65F6\u6682\u505C\u5E76\u7B49\u5F85\u4EBA\u5DE5\u5BA1\u6279\uFF0C\u540C\u610F\u540E\u8FFD\u52A0\u540C\u6837\u989D\u5EA6\u3002\u7A7A\u4EA7\u51FA\u6216\u8FDE\u7EED\u91CD\u590D\u5DF2\u6709\u5FEB\u7167\u4ECD\u4F1A\u63D0\u524D\u6682\u505C\uFF0C\u9047\u5230\u963B\u585E\u5E94\u5982\u5B9E\u4E0A\u62A5\u3002\u5168\u90E8\u5B8C\u6210\u65F6\u7167\u5E38 propose \u540E \`oasis conclude ${artifactId} --note "<\u4EA4\u4ED8\u7ED3\u8BBA>"\`\u3002`] : [],
|
|
15678
15886
|
`- \u5199\u5165\u53EA\u8D70 \`oasis propose\`\uFF0C\u771F\u6B63\u5B8C\u6574\u4E86\u624D \`oasis conclude\`\uFF1B\u5361\u6CA1\u5361\u4F4F\u3001\u8FDB\u5EA6\u90FD\u662F\u7CFB\u7EDF\u7B97\u7684\uFF0C\u522B\u81EA\u5DF1\u7EF4\u62A4\u3002`,
|
|
15679
15887
|
`- \u4F46**\u7B80\u5355\u3001\u81EA\u8DB3\u3001\u4E0D\u4F9D\u8D56\u672A\u5B9A\u51B3\u7B56\u7684\u4EFB\u52A1**\uFF08\u5982\u6539\u4E2A\u80CC\u666F\u8272\uFF09\u2192 \u76F4\u63A5\u505A\uFF0C\u5224\u65AD\u6743\u5728\u4F60\u3002`,
|
|
15680
15888
|
...typeDef?.recommendedInputs && typeDef.recommendedInputs.length > 0 ? [`- \u672C\u7C7B\u578B\u5E38\u89C1\u4E0A\u6E38\u4F9D\u8D56\uFF08\u63A8\u8350\uFF0C\u975E\u5F3A\u5236\uFF09\uFF1A${typeDef.recommendedInputs.join("\u3001")}\u2014\u2014\u4F9D\u8D56\u5176\u4E2D\u67D0\u4E2A\u800C\u5B83\u8FD8\u6CA1\u6709\uFF0C\u6309\u4E0A\u9762 gap \u89C4\u5219\u62A5\u7F3A\u53E3\u3002`] : []
|
|
@@ -18793,6 +19001,36 @@ function bridgeLoadReadModel(input) {
|
|
|
18793
19001
|
pinMeta.set(edge.toNodeId, record8);
|
|
18794
19002
|
}
|
|
18795
19003
|
const pendingReviews = /* @__PURE__ */ new Map();
|
|
19004
|
+
for (const snap of snapshots2) {
|
|
19005
|
+
let approver;
|
|
19006
|
+
for (const node2 of snap.nodes) {
|
|
19007
|
+
const request2 = node2.continuationBudget?.request;
|
|
19008
|
+
const latest = node2.latestWorkId ? workById.get(node2.latestWorkId) : void 0;
|
|
19009
|
+
if (!request2 || node2.cancelledAt || latest && !latest.endedAt && !latest.deadAt && (latest.startedAt || latest.sessionRef || latest.lastActivityAt || snap.artifacts.some((a) => a.workId === latest.id))) continue;
|
|
19010
|
+
if (request2.decision === "pending" || request2.decision === "denied") {
|
|
19011
|
+
const artifact = artifacts.get(node2.id);
|
|
19012
|
+
if (artifact) artifact.continuationPause = { decision: request2.decision, detail: request2.summary, at: request2.at };
|
|
19013
|
+
}
|
|
19014
|
+
if (request2.decision !== "pending") continue;
|
|
19015
|
+
if (approver === void 0) approver = continuationApprover(new WorkorderState(snap));
|
|
19016
|
+
pendingReviews.set(request2.id, {
|
|
19017
|
+
draftId: request2.id,
|
|
19018
|
+
continuation: { nodeId: node2.id, requestId: request2.id, approverActorId: approver },
|
|
19019
|
+
plan: { workspace: snap.workorder.id, reason: request2.summary, ops: [] },
|
|
19020
|
+
changeClass: "C",
|
|
19021
|
+
nonMonotonicOps: [],
|
|
19022
|
+
proposedBy: node2.assigneeActorId ?? snap.workorder.ownerActorId,
|
|
19023
|
+
origin: null,
|
|
19024
|
+
workspace: snap.workorder.id,
|
|
19025
|
+
advisory: [],
|
|
19026
|
+
downstreamClosure: [],
|
|
19027
|
+
at: request2.at,
|
|
19028
|
+
anchor: node2.id,
|
|
19029
|
+
kind: "command",
|
|
19030
|
+
command: { command: "continueBatch", args: { artifactId: node2.id, rounds: request2.rounds }, effectLabel: request2.summary }
|
|
19031
|
+
});
|
|
19032
|
+
}
|
|
19033
|
+
}
|
|
18796
19034
|
const pointedReviewIds = new Set(
|
|
18797
19035
|
allRequirements.map((r) => r.latestReviewId).filter((x2) => x2 != null)
|
|
18798
19036
|
);
|
|
@@ -19392,6 +19630,7 @@ var import_node_crypto3, PENDING_ROLE_PREFIX2, PENDING_UNASSIGNED2, EngineKernel
|
|
|
19392
19630
|
var init_kernel_bridge = __esm({
|
|
19393
19631
|
"../core/src/kernel-bridge.ts"() {
|
|
19394
19632
|
"use strict";
|
|
19633
|
+
init_src4();
|
|
19395
19634
|
import_node_crypto3 = require("node:crypto");
|
|
19396
19635
|
init_read_model();
|
|
19397
19636
|
init_closure_gate2();
|
|
@@ -21183,7 +21422,35 @@ var init_kernel_bridge = __esm({
|
|
|
21183
21422
|
await this.refreshModel();
|
|
21184
21423
|
return { draftId };
|
|
21185
21424
|
}
|
|
21425
|
+
async decideContinuation(draftId, actor, approve, reason) {
|
|
21426
|
+
const review = this.model.pendingReviews.get(draftId);
|
|
21427
|
+
if (!review?.continuation || !review.workspace) throw new Error("\u7EED\u8DD1\u5BA1\u6279\u4E0D\u5B58\u5728\u6216\u5DF2\u5904\u7406");
|
|
21428
|
+
const snapshot = await this.store.transaction((tx) => tx.loadWorkorder(review.workspace));
|
|
21429
|
+
const node2 = snapshot?.nodes.find((n) => n.id === review.continuation.nodeId);
|
|
21430
|
+
const request2 = node2?.continuationBudget?.request;
|
|
21431
|
+
if (!actor.startsWith("actor:human:") || !snapshot || continuationApprover(new WorkorderState(snapshot)) !== actor) throw new Error("\u4EC5\u5DE5\u5355\u4EBA\u7C7B\u8D1F\u8D23\u4EBA\u53EF\u4EE5\u5BA1\u6279\u7EED\u8DD1\u989D\u5EA6");
|
|
21432
|
+
if (!request2 || request2.id !== draftId || request2.decision !== "pending" || node2?.cancelledAt) throw new Error("\u7EED\u8DD1\u5BA1\u6279\u5DF2\u5904\u7406\u6216\u5931\u6548");
|
|
21433
|
+
const expectedAuthorized = Math.max(
|
|
21434
|
+
node2.continuationBudget.authorizedRounds,
|
|
21435
|
+
continuationUsedRounds(new WorkorderState(snapshot), node2.id)
|
|
21436
|
+
) + request2.rounds;
|
|
21437
|
+
await this.commit({
|
|
21438
|
+
companyId: snapshot.workorder.companyId,
|
|
21439
|
+
workorderId: snapshot.workorder.id,
|
|
21440
|
+
actorId: actor,
|
|
21441
|
+
event: { kind: "continuation.decided", workorderId: snapshot.workorder.id, nodeId: node2.id, requestId: draftId, approve, reason }
|
|
21442
|
+
});
|
|
21443
|
+
const after = await this.store.transaction((tx) => tx.loadWorkorder(snapshot.workorder.id));
|
|
21444
|
+
const afterBudget = after?.nodes.find((n) => n.id === node2.id)?.continuationBudget;
|
|
21445
|
+
const decided = afterBudget?.request;
|
|
21446
|
+
const applied = approve ? (afterBudget?.authorizedRounds ?? 0) >= expectedAuthorized : decided?.id === draftId && (decided.decision === "denied" || decided.decision === "completed");
|
|
21447
|
+
if (!applied) throw new Error("\u7EED\u8DD1\u5BA1\u6279\u53D1\u751F\u51B2\u7A81\uFF0C\u8BF7\u5237\u65B0\u540E\u67E5\u770B\u7ED3\u679C");
|
|
21448
|
+
return node2.id;
|
|
21449
|
+
}
|
|
21186
21450
|
async applyAuthorizedCommand(args) {
|
|
21451
|
+
if (this.model.pendingReviews.get(args.draftId)?.continuation) {
|
|
21452
|
+
return { command: "continueBatch", artifactId: await this.decideContinuation(args.draftId, args.actor, true) };
|
|
21453
|
+
}
|
|
21187
21454
|
const card2 = this.draftCards.get(args.draftId);
|
|
21188
21455
|
if (!card2 || card2.kind !== "command" || !card2.command) {
|
|
21189
21456
|
throw new Error(`\u4E0D\u662F\u547D\u4EE4\u6388\u6743\u8BF7\u6C42\u6216\u5DF2\u5904\u7406\uFF1A${args.draftId}`);
|
|
@@ -21213,6 +21480,10 @@ var init_kernel_bridge = __esm({
|
|
|
21213
21480
|
return { command: card2.command, artifactId };
|
|
21214
21481
|
}
|
|
21215
21482
|
async rejectIntervention(args) {
|
|
21483
|
+
if (this.model.pendingReviews.get(args.draftId)?.continuation) {
|
|
21484
|
+
await this.decideContinuation(args.draftId, args.actor, false, args.reason);
|
|
21485
|
+
return;
|
|
21486
|
+
}
|
|
21216
21487
|
this.draftCards.delete(args.draftId);
|
|
21217
21488
|
await this.forgetDraftCard(args.draftId);
|
|
21218
21489
|
await this.refreshModel();
|
|
@@ -142917,6 +143188,7 @@ function shortId2(id) {
|
|
|
142917
143188
|
function stallOf(model, id, runtime, dispatcherSignals) {
|
|
142918
143189
|
const a = model.artifacts.get(id);
|
|
142919
143190
|
if (!a) return null;
|
|
143191
|
+
if (a.continuationPause) return a.continuationPause.decision === "pending" ? { kind: "waiting_human", action: "discuss", ref: id, detail: a.continuationPause.detail, since: a.continuationPause.at } : { kind: "held", detail: "\u5DF2\u62D2\u7EDD\u8FFD\u52A0\u81EA\u52A8\u7EED\u8DD1\u989D\u5EA6\uFF0C\u8282\u70B9\u4FDD\u6301\u6682\u505C\uFF1B\u6210\u679C\u5DF2\u4FDD\u7559\u3002", since: a.continuationPause.at };
|
|
142920
143192
|
const ownerIsAgent = a.owner.startsWith("actor:agent:");
|
|
142921
143193
|
const escs = unresolvedEscalationsOf(model, id);
|
|
142922
143194
|
if (escs.length > 0) {
|
|
@@ -143072,7 +143344,7 @@ function nodeInfo(model, a) {
|
|
|
143072
143344
|
const hasUnproducedParts = (a.parts ?? []).some((p2) => !producedParts.has(p2.name));
|
|
143073
143345
|
const blockedByIssue = unresolvedGapsOf(model, a.id).length > 0 || unresolvedEscalationsOf(model, a.id).length > 0;
|
|
143074
143346
|
let mark;
|
|
143075
|
-
if (!sealed && blockedByIssue) {
|
|
143347
|
+
if (!sealed && (blockedByIssue || a.continuationPause)) {
|
|
143076
143348
|
mark = "blocked";
|
|
143077
143349
|
} else if (a.latestWorkState !== void 0) {
|
|
143078
143350
|
const st = a.latestWorkState;
|
|
@@ -143129,6 +143401,7 @@ function deriveStage(members, opts) {
|
|
|
143129
143401
|
}
|
|
143130
143402
|
function nodeRunState(model, artifact, info, runtime, opts) {
|
|
143131
143403
|
if (info.sealed) return void 0;
|
|
143404
|
+
if (artifact.continuationPause) return artifact.continuationPause.decision === "pending" ? "pending" : "blocked";
|
|
143132
143405
|
const id = artifact.id;
|
|
143133
143406
|
const now = opts?.now ?? Date.now();
|
|
143134
143407
|
const rt = runtime ?? {};
|
|
@@ -161536,6 +161809,17 @@ var init_workorder_drafts = __esm({
|
|
|
161536
161809
|
async forWorkspace(workspace) {
|
|
161537
161810
|
return [...this.drafts.values()].reverse().find((d) => d.workspace === workspace);
|
|
161538
161811
|
}
|
|
161812
|
+
/**
|
|
161813
|
+
* 按 workspace + **版本号**取某一版(2026-09-11:对话流里一版一张卡,右侧面板也按版本定位,
|
|
161814
|
+
* 于是「人在面板里改负责人/审核人再保存」这件事必须写回**他正在看的那一版**)。
|
|
161815
|
+
*
|
|
161816
|
+
* ⚠ 别用 `forWorkspace` 顶替它:那个取的是链上**最新**一版。看着 V1 改了一笔、却写进 V3,
|
|
161817
|
+
* 等于用旧图把新图整个盖掉——V2/V3 的内容会无声消失(2026-09-11 发起人报的「节点图要隔离」)。
|
|
161818
|
+
* 找不到那一版时回 undefined,由调用方判 404,不许静默回落到最新版。
|
|
161819
|
+
*/
|
|
161820
|
+
async forWorkspaceVersion(workspace, version2) {
|
|
161821
|
+
return [...this.drafts.values()].find((d) => d.workspace === workspace && d.version === version2);
|
|
161822
|
+
}
|
|
161539
161823
|
/** 按 chat 会话取最新一份:agent 不自带 ws(后端生成)时,friday 据本会话 id 取回它刚建的草案。 */
|
|
161540
161824
|
async forSession(chatSessionId) {
|
|
161541
161825
|
return [...this.drafts.values()].reverse().find((d) => d.chatSessionId === chatSessionId);
|
|
@@ -162582,8 +162866,8 @@ async function buildDynamicWorkorderPlan(input) {
|
|
|
162582
162866
|
const explicit = node2.owner ? await validateExplicitOwner(input.registry, node2.owner, node2.type) : null;
|
|
162583
162867
|
if (explicit?.issue) issues.push(explicit.issue);
|
|
162584
162868
|
const owner = explicit?.actor ? { role: def.ownerRole ?? "", actor: explicit.actor } : def.ownerRole ? await resolveRole(def.ownerRole, node2.type) : null;
|
|
162585
|
-
const
|
|
162586
|
-
if (enforceStaffing && def.ownerRole && !
|
|
162869
|
+
const staffable = staffableTypes.has(node2.type);
|
|
162870
|
+
if (enforceStaffing && def.ownerRole && !staffable && !input.retainUnstaffedNodes) continue;
|
|
162587
162871
|
const ownerActor = owner?.actor ?? (def.ownerRole ? `pending:role:${def.ownerRole}` : PENDING_UNASSIGNED);
|
|
162588
162872
|
availableNodes.push({
|
|
162589
162873
|
type: node2.type,
|
|
@@ -162782,7 +163066,18 @@ async function validateExplicitOwner(registry2, owner, artifactType) {
|
|
|
162782
163066
|
return { actor: owner };
|
|
162783
163067
|
}
|
|
162784
163068
|
function pickPreferred(actors) {
|
|
162785
|
-
return
|
|
163069
|
+
return actors.filter((a) => a.kind === "agent").sort((a, b2) => a.id.localeCompare(b2.id))[0];
|
|
163070
|
+
}
|
|
163071
|
+
async function autoAssignableRoles(registry2) {
|
|
163072
|
+
const out = /* @__PURE__ */ new Set();
|
|
163073
|
+
if (!registry2) return out;
|
|
163074
|
+
for (const actor of await registry2.listActors({ status: "active" })) {
|
|
163075
|
+
if (actor.kind !== "agent") continue;
|
|
163076
|
+
const binding = await registry2.getBinding(actor.id);
|
|
163077
|
+
if (!binding || binding.status !== "active") continue;
|
|
163078
|
+
for (const role of actor.roles) out.add(role);
|
|
163079
|
+
}
|
|
163080
|
+
return out;
|
|
162786
163081
|
}
|
|
162787
163082
|
async function resolveActiveRole(registry2, role, artifactType, roles) {
|
|
162788
163083
|
if (!registry2) {
|
|
@@ -162818,7 +163113,10 @@ async function resolveActiveRole(registry2, role, artifactType, roles) {
|
|
|
162818
163113
|
};
|
|
162819
163114
|
}
|
|
162820
163115
|
const preferred = pickPreferred(actors);
|
|
163116
|
+
const nodeWord = artifactType ? `${artifactType} \u8282\u70B9` : "\u5BF9\u5E94\u8282\u70B9";
|
|
162821
163117
|
if (!preferred) {
|
|
163118
|
+
const humans = actors.filter((a) => a.kind === "human");
|
|
163119
|
+
const message = humans.length > 0 ? `${role} \u5C97\u4F4D\u5F53\u524D\u53EA\u6709\u771F\u4EBA\uFF08${humans.map((h) => h.name).join("\u3001")}\uFF09\u3001\u6CA1\u6709\u53EF\u81EA\u52A8\u63A5\u5355\u7684 agent\u2014\u2014${nodeWord}\u843D\u5F85\u5C97\uFF0C\u8BF7\u5728\u56FE\u4E0A\u6307\u5B9A\u8D1F\u8D23\u4EBA\uFF0C\u6216\u7ED9\u8BE5\u5C97\u4F4D\u914D\u4E00\u4E2A agent\u3002` : `\u7F3A\u5C11 active \u7684 ${role} \u5458\u5DE5\uFF0C${nodeWord}\u4E0D\u4F1A\u81EA\u52A8\u6D3E\u53D1\u3002`;
|
|
162822
163120
|
return {
|
|
162823
163121
|
role,
|
|
162824
163122
|
actor: null,
|
|
@@ -162827,27 +163125,25 @@ async function resolveActiveRole(registry2, role, artifactType, roles) {
|
|
|
162827
163125
|
severity: "blocking",
|
|
162828
163126
|
role,
|
|
162829
163127
|
...artifactType ? { artifactType } : {},
|
|
162830
|
-
message
|
|
163128
|
+
message
|
|
162831
163129
|
}
|
|
162832
163130
|
};
|
|
162833
163131
|
}
|
|
162834
|
-
|
|
162835
|
-
|
|
162836
|
-
|
|
162837
|
-
|
|
163132
|
+
const binding = await registry2.getBinding(preferred.id);
|
|
163133
|
+
if (!binding || binding.status !== "active") {
|
|
163134
|
+
return {
|
|
163135
|
+
role,
|
|
163136
|
+
actor: null,
|
|
163137
|
+
issue: {
|
|
163138
|
+
code: "missing_binding",
|
|
163139
|
+
severity: "blocking",
|
|
162838
163140
|
role,
|
|
162839
|
-
|
|
162840
|
-
|
|
162841
|
-
|
|
162842
|
-
|
|
162843
|
-
|
|
162844
|
-
|
|
162845
|
-
// 措辞对两条路都成立:规则路会丢节点、agent/剧本路保留为待岗——**都是「暂不自动派发」**,
|
|
162846
|
-
// 而非「暂不创建」(后者在保留待岗后就是假话)。
|
|
162847
|
-
message: `${preferred.name}\uFF08${preferred.id}\uFF09\u7F3A\u5C11 active runtime \u7ED1\u5B9A\uFF0C${artifactType ? `${artifactType} \u8282\u70B9` : "\u5BF9\u5E94\u8282\u70B9"}\u6682\u4E0D\u81EA\u52A8\u6D3E\u53D1\uFF08\u5F85\u8865\u9F50\u540E\u81EA\u52A8\u63A5\u624B\uFF09\u3002`
|
|
162848
|
-
}
|
|
162849
|
-
};
|
|
162850
|
-
}
|
|
163141
|
+
...artifactType ? { artifactType } : {},
|
|
163142
|
+
// 措辞对两条路都成立:规则路会丢节点、agent/剧本路保留为待岗——**都是「暂不自动派发」**,
|
|
163143
|
+
// 而非「暂不创建」(后者在保留待岗后就是假话)。
|
|
163144
|
+
message: `${preferred.name}\uFF08${preferred.id}\uFF09\u7F3A\u5C11 active runtime \u7ED1\u5B9A\uFF0C${nodeWord}\u6682\u4E0D\u81EA\u52A8\u6D3E\u53D1\uFF08\u5F85\u8865\u9F50\u540E\u81EA\u52A8\u63A5\u624B\uFF09\u3002`
|
|
163145
|
+
}
|
|
163146
|
+
};
|
|
162851
163147
|
}
|
|
162852
163148
|
return { role, actor: preferred.id };
|
|
162853
163149
|
}
|
|
@@ -163274,7 +163570,12 @@ function planningStatusOf(_model, arts, resolveRoleExecutor) {
|
|
|
163274
163570
|
const role = a.owner.slice(PENDING_ROLE_PREFIX.length);
|
|
163275
163571
|
if (seenRoles.has(role)) continue;
|
|
163276
163572
|
seenRoles.add(role);
|
|
163277
|
-
issues.push({
|
|
163573
|
+
issues.push({
|
|
163574
|
+
code: "missing_role",
|
|
163575
|
+
severity: "warning",
|
|
163576
|
+
role,
|
|
163577
|
+
message: `${role} \u5C97\u4F4D\u6CA1\u6709\u53EF\u81EA\u52A8\u63A5\u5355\u7684 agent\uFF0C\u76F8\u5173\u8282\u70B9\u5F85\u6D3E\u2014\u2014\u8BF7 assign \u6307\u5B9A\u8D1F\u8D23\u4EBA\uFF0C\u6216\u7ED9\u8BE5\u5C97\u4F4D\u914D\u4E00\u4E2A agent\u3002`
|
|
163578
|
+
});
|
|
163278
163579
|
}
|
|
163279
163580
|
if (resolveRoleExecutor) {
|
|
163280
163581
|
for (const a of arts) {
|
|
@@ -163322,7 +163623,12 @@ function draftPlanningStatusOf(spawns, isRoleStaffed, extraBlockingIssues = [])
|
|
|
163322
163623
|
if (isRoleStaffed(role)) continue;
|
|
163323
163624
|
if (seenRoles.has(role)) continue;
|
|
163324
163625
|
seenRoles.add(role);
|
|
163325
|
-
issues.push({
|
|
163626
|
+
issues.push({
|
|
163627
|
+
code: "missing_role",
|
|
163628
|
+
severity: "warning",
|
|
163629
|
+
role,
|
|
163630
|
+
message: `${role} \u5C97\u4F4D\u6CA1\u6709\u53EF\u81EA\u52A8\u63A5\u5355\u7684 agent\uFF0C\u76F8\u5173\u8282\u70B9\u5F85\u6D3E\u2014\u2014\u8BF7\u5728\u56FE\u4E0A\u6307\u5B9A\u8D1F\u8D23\u4EBA\uFF0C\u6216\u7ED9\u8BE5\u5C97\u4F4D\u914D\u4E00\u4E2A agent\u3002`
|
|
163631
|
+
});
|
|
163326
163632
|
}
|
|
163327
163633
|
}
|
|
163328
163634
|
for (const extra of extraBlockingIssues) {
|
|
@@ -164394,7 +164700,7 @@ async function planChatContinuation(input) {
|
|
|
164394
164700
|
};
|
|
164395
164701
|
}
|
|
164396
164702
|
var UNFINISHED_OPEN, UNFINISHED_EMPTY;
|
|
164397
|
-
var
|
|
164703
|
+
var init_continuation3 = __esm({
|
|
164398
164704
|
"../server/src/domains/chat-sessions/continuation.ts"() {
|
|
164399
164705
|
"use strict";
|
|
164400
164706
|
init_injected_context();
|
|
@@ -194988,6 +195294,7 @@ var init_curator_skill = __esm({
|
|
|
194988
195294
|
skills,
|
|
194989
195295
|
connectorIds,
|
|
194990
195296
|
maxConcurrent: 4,
|
|
195297
|
+
...currentConfig?.continuationMaxRounds !== void 0 ? { continuationMaxRounds: currentConfig.continuationMaxRounds } : {},
|
|
194991
195298
|
...currentConfig?.batchedContinuation !== void 0 ? { batchedContinuation: currentConfig.batchedContinuation } : {}
|
|
194992
195299
|
}, by);
|
|
194993
195300
|
}
|
|
@@ -202780,33 +203087,13 @@ async function draftActorResolver(registry2) {
|
|
|
202780
203087
|
}
|
|
202781
203088
|
async function draftRoleStaffingResolver(registry2) {
|
|
202782
203089
|
if (!registry2) return () => true;
|
|
202783
|
-
const
|
|
202784
|
-
|
|
202785
|
-
for (const a of actors) if (a.status === "active") for (const r of a.roles) staffedRoles.add(r);
|
|
202786
|
-
return (role) => staffedRoles.has(role);
|
|
203090
|
+
const assignable = await autoAssignableRoles(registry2);
|
|
203091
|
+
return (role) => assignable.has(role);
|
|
202787
203092
|
}
|
|
202788
203093
|
async function draftRolePlannableResolver(registry2) {
|
|
202789
203094
|
if (!registry2) return async () => true;
|
|
202790
|
-
const
|
|
202791
|
-
|
|
202792
|
-
for (const a of actors) {
|
|
202793
|
-
if (a.status !== "active") continue;
|
|
202794
|
-
for (const r of a.roles) {
|
|
202795
|
-
const list2 = activeActorsByRole.get(r) ?? [];
|
|
202796
|
-
list2.push(a);
|
|
202797
|
-
activeActorsByRole.set(r, list2);
|
|
202798
|
-
}
|
|
202799
|
-
}
|
|
202800
|
-
return async (role) => {
|
|
202801
|
-
const list2 = activeActorsByRole.get(role);
|
|
202802
|
-
if (!list2 || list2.length === 0) return false;
|
|
202803
|
-
for (const a of list2) {
|
|
202804
|
-
if (a.kind !== "agent") return true;
|
|
202805
|
-
const binding = await registry2.getBinding(a.id);
|
|
202806
|
-
if (binding && binding.status === "active") return true;
|
|
202807
|
-
}
|
|
202808
|
-
return false;
|
|
202809
|
-
};
|
|
203095
|
+
const assignable = await autoAssignableRoles(registry2);
|
|
203096
|
+
return async (role) => assignable.has(role);
|
|
202810
203097
|
}
|
|
202811
203098
|
async function draftTypeReviewerResolver(schema, registry2) {
|
|
202812
203099
|
if (!schema || !registry2) return void 0;
|
|
@@ -203118,6 +203405,8 @@ async function resolveProposeContent(kernel, blobs, args, artifactId, ctx) {
|
|
|
203118
203405
|
}
|
|
203119
203406
|
function authorizedCommandReceipt(command, args, actor) {
|
|
203120
203407
|
switch (command) {
|
|
203408
|
+
case "continueBatch":
|
|
203409
|
+
return { message: `\u5DF2\u6388\u6743\u518D\u8FD0\u884C ${args.rounds} \u8F6E\uFF1B\u5176\u4ED6\u963B\u585E\u89E3\u9664\u540E\u7EE7\u7EED\u3002` };
|
|
203121
203410
|
case "forceConclude":
|
|
203122
203411
|
return { message: `force_conclude ${str(args, "artifactId")}\u2014\u2014\u91CC\u7A0B\u7891\u5E26 forced(by=${actor}) \u6807\u8BB0\uFF0C\u6D88\u8D39\u8005\u53EF\u89C1` };
|
|
203123
203412
|
case "promote":
|
|
@@ -205608,11 +205897,7 @@ async function startOasisServer(opts) {
|
|
|
205608
205897
|
return;
|
|
205609
205898
|
}
|
|
205610
205899
|
}
|
|
205611
|
-
const staffedRoles =
|
|
205612
|
-
if (principalRegistry) {
|
|
205613
|
-
const actorsForStaffing = await principalRegistry.listActors();
|
|
205614
|
-
for (const a of actorsForStaffing) if (a.status === "active") for (const r of a.roles) staffedRoles.add(r);
|
|
205615
|
-
}
|
|
205900
|
+
const staffedRoles = await autoAssignableRoles(principalRegistry);
|
|
205616
205901
|
const spawnedForPlanning = body2.plan.ops.filter((op) => op.action === "spawn").filter((op) => op.type !== DELIVERY_SUMMARY_ARTIFACT_TYPE).map((op) => {
|
|
205617
205902
|
const title = op.title ?? op.description;
|
|
205618
205903
|
return {
|
|
@@ -206021,7 +206306,7 @@ async function startOasisServer(opts) {
|
|
|
206021
206306
|
}
|
|
206022
206307
|
if (url.pathname === "/api/workorder/draft/plan" && req.method === "POST" && wodrafts) {
|
|
206023
206308
|
try {
|
|
206024
|
-
const { workspace, plan, holder } = JSON.parse(rawBody);
|
|
206309
|
+
const { workspace, plan, holder, version: version2 } = JSON.parse(rawBody);
|
|
206025
206310
|
if (!workspace || !plan || !Array.isArray(plan.ops)) throw new Error("\u9700\u8981 { workspace, plan:{ops:[]} }");
|
|
206026
206311
|
const planLockedBy = wodrafts.editLockHolder(workspace);
|
|
206027
206312
|
if (planLockedBy && planLockedBy !== holder) {
|
|
@@ -206030,9 +206315,10 @@ async function startOasisServer(opts) {
|
|
|
206030
206315
|
);
|
|
206031
206316
|
return;
|
|
206032
206317
|
}
|
|
206033
|
-
const draft = await wodrafts.forWorkspace(workspace);
|
|
206318
|
+
const draft = version2 === void 0 ? await wodrafts.forWorkspace(workspace) : await wodrafts.forWorkspaceVersion(workspace, version2);
|
|
206034
206319
|
if (!draft) {
|
|
206035
|
-
|
|
206320
|
+
const what = version2 === void 0 ? workspace : `${workspace} v${version2}`;
|
|
206321
|
+
res.writeHead(404, { "content-type": "application/json" }).end(JSON.stringify({ error: `no staged workorder draft for ${what}` }));
|
|
206036
206322
|
return;
|
|
206037
206323
|
}
|
|
206038
206324
|
const pv = await engine.kernel.previewIntervention({ ...plan, reason: plan.reason || "(draft edit)" });
|
|
@@ -206302,7 +206588,7 @@ async function startOasisServer(opts) {
|
|
|
206302
206588
|
if (viewName === "intervention-drafts") {
|
|
206303
206589
|
const origin = url.searchParams.get("origin");
|
|
206304
206590
|
const workspace = url.searchParams.get("workspace") ?? void 0;
|
|
206305
|
-
const reviews = listPendingReviews(engine.kernel.model, origin === null ? workspace : void 0).filter((r) => origin === null ? true : r.origin === origin);
|
|
206591
|
+
const reviews = listPendingReviews(engine.kernel.model, origin === null ? workspace : void 0).filter((r) => origin === null ? true : r.origin === origin).filter((r) => !r.continuation || r.continuation.approverActorId === actor);
|
|
206306
206592
|
const data2 = reviews.map((r) => ({
|
|
206307
206593
|
id: r.draftId,
|
|
206308
206594
|
plan: r.plan,
|
|
@@ -206320,7 +206606,8 @@ async function startOasisServer(opts) {
|
|
|
206320
206606
|
anchor: r.anchor,
|
|
206321
206607
|
// 提案 coordinator-command-authorization:命令授权卡的种类 + 命令本体(前端据此渲成命令卡)。
|
|
206322
206608
|
...r.kind !== void 0 ? { kind: r.kind } : {},
|
|
206323
|
-
...r.command !== void 0 ? { command: r.command } : {}
|
|
206609
|
+
...r.command !== void 0 ? { command: r.command } : {},
|
|
206610
|
+
...r.continuation ? { continuation: r.continuation } : {}
|
|
206324
206611
|
}));
|
|
206325
206612
|
res.writeHead(200, { "content-type": "application/json" }).end(JSON.stringify({ data: data2 }));
|
|
206326
206613
|
return;
|
|
@@ -208456,7 +208743,7 @@ var init_server3 = __esm({
|
|
|
208456
208743
|
init_planner();
|
|
208457
208744
|
init_chat_parts();
|
|
208458
208745
|
init_injected_context();
|
|
208459
|
-
|
|
208746
|
+
init_continuation3();
|
|
208460
208747
|
init_chat_turn_gate();
|
|
208461
208748
|
init_chat_workorder_files();
|
|
208462
208749
|
init_chat_item_ledger();
|
|
@@ -208469,7 +208756,7 @@ var init_server3 = __esm({
|
|
|
208469
208756
|
init_assembly();
|
|
208470
208757
|
init_child_live_turn();
|
|
208471
208758
|
init_src8();
|
|
208472
|
-
|
|
208759
|
+
init_continuation3();
|
|
208473
208760
|
githubAppPending = new PendingAppCreations();
|
|
208474
208761
|
connectorAuthSnapshots = /* @__PURE__ */ new Map();
|
|
208475
208762
|
CONNECTOR_AUTH_SNAPSHOT_TTL_MS = 30 * 60 * 1e3;
|
|
@@ -220006,6 +220293,7 @@ var init_service5 = __esm({
|
|
|
220006
220293
|
connectorIds: patch.connectorIds ?? latest?.connectorIds ?? [],
|
|
220007
220294
|
maxConcurrent: patch.maxConcurrent ?? latest?.maxConcurrent ?? 4,
|
|
220008
220295
|
batchedContinuation: patch.batchedContinuation ?? latest?.batchedContinuation ?? false,
|
|
220296
|
+
continuationMaxRounds: patch.continuationMaxRounds ?? latest?.continuationMaxRounds ?? 3,
|
|
220009
220297
|
extraArgs: patch.extraArgs ?? latest?.extraArgs ?? [],
|
|
220010
220298
|
createdBy: by,
|
|
220011
220299
|
createdAt: this.now(),
|
|
@@ -220033,6 +220321,7 @@ var init_service5 = __esm({
|
|
|
220033
220321
|
connectorIds: [...target.connectorIds],
|
|
220034
220322
|
maxConcurrent: target.maxConcurrent,
|
|
220035
220323
|
batchedContinuation: target.batchedContinuation ?? false,
|
|
220324
|
+
continuationMaxRounds: target.continuationMaxRounds ?? 3,
|
|
220036
220325
|
extraArgs: [...target.extraArgs ?? []],
|
|
220037
220326
|
createdBy: by,
|
|
220038
220327
|
createdAt: this.now(),
|
|
@@ -220921,12 +221210,13 @@ ${input.description}
|
|
|
220921
221210
|
};
|
|
220922
221211
|
mask = (plain) => plain.length <= 4 ? "\u2022\u2022\u2022\u2022" : `${"\u2022".repeat(4)}${plain.slice(-4)}`;
|
|
220923
221212
|
changedKeys = (prev, next) => {
|
|
220924
|
-
if (!prev) return ["prompt", "model", "skills", "connectorIds", "maxConcurrent", "batchedContinuation", "extraArgs"];
|
|
221213
|
+
if (!prev) return ["prompt", "model", "skills", "connectorIds", "maxConcurrent", "batchedContinuation", "continuationMaxRounds", "extraArgs"];
|
|
220925
221214
|
const keys = [];
|
|
220926
221215
|
if (prev.prompt !== next.prompt) keys.push("prompt");
|
|
220927
221216
|
if (prev.model !== next.model) keys.push("model");
|
|
220928
221217
|
if (JSON.stringify(prev.skills) !== JSON.stringify(next.skills)) keys.push("skills");
|
|
220929
221218
|
if (JSON.stringify(prev.connectorIds) !== JSON.stringify(next.connectorIds)) keys.push("connectorIds");
|
|
221219
|
+
if ((prev.continuationMaxRounds ?? 3) !== (next.continuationMaxRounds ?? 3)) keys.push("continuationMaxRounds");
|
|
220930
221220
|
if ((prev.batchedContinuation ?? false) !== (next.batchedContinuation ?? false)) keys.push("batchedContinuation");
|
|
220931
221221
|
if (prev.maxConcurrent !== next.maxConcurrent) keys.push("maxConcurrent");
|
|
220932
221222
|
if (JSON.stringify(prev.extraArgs ?? []) !== JSON.stringify(next.extraArgs ?? [])) keys.push("extraArgs");
|
|
@@ -222450,6 +222740,9 @@ function actorsDomain(opts) {
|
|
|
222450
222740
|
checkStringArray("skills");
|
|
222451
222741
|
checkStringArray("connectorIds");
|
|
222452
222742
|
checkBoolean("batchedContinuation");
|
|
222743
|
+
if (b2.continuationMaxRounds !== void 0 && (!Number.isSafeInteger(b2.continuationMaxRounds) || b2.continuationMaxRounds < 1 || b2.continuationMaxRounds > 100)) {
|
|
222744
|
+
throw new ApiError(400, "BAD_REQUEST", "continuationMaxRounds \u5FC5\u987B\u662F 1\u2013100 \u7684\u6574\u6570");
|
|
222745
|
+
}
|
|
222453
222746
|
const rawExtra = b2.extraArgs;
|
|
222454
222747
|
if (rawExtra !== void 0 && typeof rawExtra !== "string" && !(Array.isArray(rawExtra) && rawExtra.every((x2) => typeof x2 === "string"))) {
|
|
222455
222748
|
throw new ApiError(400, "BAD_REQUEST", "extraArgs \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6216\u5B57\u7B26\u4E32\u6570\u7EC4");
|
|
@@ -222471,6 +222764,7 @@ function actorsDomain(opts) {
|
|
|
222471
222764
|
...b2.skills !== void 0 ? { skills: b2.skills } : {},
|
|
222472
222765
|
...b2.connectorIds !== void 0 ? { connectorIds: b2.connectorIds } : {},
|
|
222473
222766
|
...typeof b2.maxConcurrent === "number" ? { maxConcurrent: b2.maxConcurrent } : {},
|
|
222767
|
+
...b2.continuationMaxRounds !== void 0 ? { continuationMaxRounds: b2.continuationMaxRounds } : {},
|
|
222474
222768
|
...b2.batchedContinuation !== void 0 ? { batchedContinuation: b2.batchedContinuation } : {},
|
|
222475
222769
|
...extraArgs !== void 0 ? { extraArgs } : {}
|
|
222476
222770
|
},
|
|
@@ -226034,6 +226328,7 @@ var init_activity_trace = __esm({
|
|
|
226034
226328
|
|
|
226035
226329
|
// ../server/src/domains/collab/inbox.ts
|
|
226036
226330
|
function changeConfirmSummary(r) {
|
|
226331
|
+
if (r.continuation) return `\u81EA\u52A8\u7EED\u8DD1\u5DF2\u5230\u9650\uFF0C\u7B49\u5F85\u4F60\u5BA1\u6838\uFF1A${r.plan.reason}`;
|
|
226037
226332
|
const why = r.plan.reason.slice(0, 100);
|
|
226038
226333
|
if (r.kind === "command" && r.command) {
|
|
226039
226334
|
return `\u7BA1\u7406\u8005\u8BF7\u6C42\u6267\u884C\u4E00\u4E2A\u9AD8\u5371\u64CD\u4F5C\uFF0C\u7B49\u4F60\u6388\u6743\uFF1A${r.command.effectLabel}`;
|
|
@@ -226194,7 +226489,7 @@ function buildInbox(model, me, leadOf, resolveActor, markers = [], slaMs, nowIso
|
|
|
226194
226489
|
const anchorOwner = model.artifacts.get(r.anchor)?.owner;
|
|
226195
226490
|
const isOwnerRecipient = creatorOf.get(r.workspace) === me;
|
|
226196
226491
|
const isLeadRecipient = !!anchorOwner && !!leadOf && leadOf(anchorOwner) === me;
|
|
226197
|
-
if (!isOwnerRecipient && !isLeadRecipient) continue;
|
|
226492
|
+
if (r.continuation ? r.continuation.approverActorId !== me : !isOwnerRecipient && !isLeadRecipient) continue;
|
|
226198
226493
|
const anchorArt = model.artifacts.get(r.anchor);
|
|
226199
226494
|
const opCount = r.plan.ops?.length ?? 0;
|
|
226200
226495
|
out.push({
|
|
@@ -241899,6 +242194,7 @@ var init_postgres_registry = __esm({
|
|
|
241899
242194
|
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS max_concurrent integer NOT NULL DEFAULT 4`);
|
|
241900
242195
|
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS reviewer_ids jsonb NOT NULL DEFAULT '[]'::jsonb`);
|
|
241901
242196
|
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS batched_continuation boolean NOT NULL DEFAULT false`);
|
|
242197
|
+
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS continuation_max_rounds integer NOT NULL DEFAULT 3 CHECK (continuation_max_rounds BETWEEN 1 AND 100)`);
|
|
241902
242198
|
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS extra_args jsonb NOT NULL DEFAULT '[]'::jsonb`);
|
|
241903
242199
|
await pool.query(`ALTER TABLE "${s2}".actor_configs ADD COLUMN IF NOT EXISTS memory_enabled boolean NOT NULL DEFAULT true`);
|
|
241904
242200
|
await pool.query(`
|
|
@@ -242150,8 +242446,8 @@ var init_postgres_registry = __esm({
|
|
|
242150
242446
|
const r = await this.pool.query(
|
|
242151
242447
|
// reviewer_ids 列保留(历史数据)但不再写入——决策 0029 删了 actor 级 reviewer override;列有 DEFAULT '[]' 自动填。
|
|
242152
242448
|
`INSERT INTO ${this.s}.actor_configs
|
|
242153
|
-
(actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, extra_args, created_by, created_at, source, rolled_back_from)
|
|
242154
|
-
SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9::jsonb,$10,$11,$12,$13
|
|
242449
|
+
(actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, extra_args, created_by, created_at, source, rolled_back_from, continuation_max_rounds)
|
|
242450
|
+
SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9::jsonb,$10,$11,$12,$13,$14::int
|
|
242155
242451
|
WHERE (SELECT COALESCE(MAX(version), 0) + 1 FROM ${this.s}.actor_configs WHERE actor_id = $1) = $2::int`,
|
|
242156
242452
|
[
|
|
242157
242453
|
c.actorId,
|
|
@@ -242166,7 +242462,8 @@ var init_postgres_registry = __esm({
|
|
|
242166
242462
|
c.createdBy,
|
|
242167
242463
|
c.createdAt,
|
|
242168
242464
|
c.source,
|
|
242169
|
-
c.rolledBackFrom ?? null
|
|
242465
|
+
c.rolledBackFrom ?? null,
|
|
242466
|
+
c.continuationMaxRounds ?? 3
|
|
242170
242467
|
]
|
|
242171
242468
|
);
|
|
242172
242469
|
if (r.rowCount !== 1) throw new Error(`config version conflict for ${c.actorId}: got ${c.version}`);
|
|
@@ -242618,6 +242915,7 @@ var init_postgres_registry = __esm({
|
|
|
242618
242915
|
connectorIds: row.connector_ids,
|
|
242619
242916
|
maxConcurrent: row.max_concurrent ?? 4,
|
|
242620
242917
|
batchedContinuation: row.batched_continuation ?? false,
|
|
242918
|
+
continuationMaxRounds: row.continuation_max_rounds ?? 3,
|
|
242621
242919
|
extraArgs: row.extra_args ?? [],
|
|
242622
242920
|
// 注意:memory_enabled 是死列,不映射进 ActorConfig——记忆开关在 agent_prefs。
|
|
242623
242921
|
createdBy: row.created_by,
|
|
@@ -252576,6 +252874,7 @@ async function provisionCompanyDataPlaneSchema(pool, schema) {
|
|
|
252576
252874
|
reviewer_ids jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
252577
252875
|
max_concurrent integer NOT NULL DEFAULT 4,
|
|
252578
252876
|
batched_continuation boolean NOT NULL DEFAULT false,
|
|
252877
|
+
continuation_max_rounds integer NOT NULL DEFAULT 3 CHECK (continuation_max_rounds BETWEEN 1 AND 100),
|
|
252579
252878
|
extra_args jsonb NOT NULL DEFAULT '[]'::jsonb,
|
|
252580
252879
|
memory_enabled boolean NOT NULL DEFAULT true,
|
|
252581
252880
|
created_by text NOT NULL REFERENCES ${s2}.actors(id) ON DELETE RESTRICT,
|
|
@@ -252584,6 +252883,7 @@ async function provisionCompanyDataPlaneSchema(pool, schema) {
|
|
|
252584
252883
|
rolled_back_from integer,
|
|
252585
252884
|
PRIMARY KEY (actor_id, version)
|
|
252586
252885
|
)`);
|
|
252886
|
+
await pool.query(`ALTER TABLE ${s2}.actor_configs ADD COLUMN IF NOT EXISTS continuation_max_rounds integer NOT NULL DEFAULT 3 CHECK (continuation_max_rounds BETWEEN 1 AND 100)`);
|
|
252587
252887
|
await pool.query(`
|
|
252588
252888
|
CREATE TABLE IF NOT EXISTS ${s2}.agent_prefs (
|
|
252589
252889
|
actor_id text PRIMARY KEY REFERENCES ${s2}.actors(id) ON DELETE CASCADE,
|
|
@@ -252707,6 +253007,7 @@ function rowToConfig2(row) {
|
|
|
252707
253007
|
connectorIds: row.connector_ids,
|
|
252708
253008
|
maxConcurrent: row.max_concurrent,
|
|
252709
253009
|
batchedContinuation: row.batched_continuation,
|
|
253010
|
+
continuationMaxRounds: row.continuation_max_rounds ?? 3,
|
|
252710
253011
|
extraArgs: row.extra_args ?? [],
|
|
252711
253012
|
createdBy: row.created_by,
|
|
252712
253013
|
createdAt: new Date(row.created_at).toISOString(),
|
|
@@ -252989,8 +253290,8 @@ var init_company_owned_registry_store = __esm({
|
|
|
252989
253290
|
async appendConfig(c) {
|
|
252990
253291
|
const r = await this.pool.query(
|
|
252991
253292
|
`INSERT INTO ${this.s}.actor_configs
|
|
252992
|
-
(actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, extra_args, created_by, created_at, source, rolled_back_from)
|
|
252993
|
-
SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9::jsonb,$10,$11,$12,$13
|
|
253293
|
+
(actor_id, version, prompt, model, skills, connector_ids, max_concurrent, batched_continuation, extra_args, created_by, created_at, source, rolled_back_from, continuation_max_rounds)
|
|
253294
|
+
SELECT $1,$2::int,$3,$4,$5::jsonb,$6::jsonb,$7::int,$8::boolean,$9::jsonb,$10,$11,$12,$13,$14::int
|
|
252994
253295
|
WHERE (SELECT COALESCE(MAX(version), 0) + 1 FROM ${this.s}.actor_configs WHERE actor_id = $1) = $2::int`,
|
|
252995
253296
|
[
|
|
252996
253297
|
c.actorId,
|
|
@@ -253005,7 +253306,8 @@ var init_company_owned_registry_store = __esm({
|
|
|
253005
253306
|
c.createdBy,
|
|
253006
253307
|
c.createdAt,
|
|
253007
253308
|
c.source,
|
|
253008
|
-
c.rolledBackFrom ?? null
|
|
253309
|
+
c.rolledBackFrom ?? null,
|
|
253310
|
+
c.continuationMaxRounds ?? 3
|
|
253009
253311
|
]
|
|
253010
253312
|
);
|
|
253011
253313
|
if (r.rowCount !== 1) throw new Error(`config version conflict for ${c.actorId}: got ${c.version}`);
|
|
@@ -255061,8 +255363,8 @@ async function runIdentityMigration(input) {
|
|
|
255061
255363
|
const ins = await client.query(
|
|
255062
255364
|
`INSERT INTO ${cs}.actor_configs
|
|
255063
255365
|
(actor_id,version,prompt,model,skills,connector_ids,reviewer_ids,max_concurrent,
|
|
255064
|
-
batched_continuation,extra_args,memory_enabled,created_by,created_at,source,rolled_back_from)
|
|
255065
|
-
VALUES ($1,$2,$3,$4,$5::jsonb,$6::jsonb,$7::jsonb,$8,$9,$10::jsonb,$11,$12,$13,$14,$15)
|
|
255366
|
+
batched_continuation,extra_args,memory_enabled,created_by,created_at,source,rolled_back_from,continuation_max_rounds)
|
|
255367
|
+
VALUES ($1,$2,$3,$4,$5::jsonb,$6::jsonb,$7::jsonb,$8,$9,$10::jsonb,$11,$12,$13,$14,$15,$16)
|
|
255066
255368
|
ON CONFLICT (actor_id, version) DO NOTHING`,
|
|
255067
255369
|
[
|
|
255068
255370
|
r.actor_id,
|
|
@@ -255079,7 +255381,8 @@ async function runIdentityMigration(input) {
|
|
|
255079
255381
|
r.created_by,
|
|
255080
255382
|
r.created_at,
|
|
255081
255383
|
r.source,
|
|
255082
|
-
r.rolled_back_from ?? null
|
|
255384
|
+
r.rolled_back_from ?? null,
|
|
255385
|
+
r.continuation_max_rounds ?? 3
|
|
255083
255386
|
]
|
|
255084
255387
|
);
|
|
255085
255388
|
plan.configRows += ins.rowCount ?? 0;
|
|
@@ -257419,6 +257722,9 @@ var init_cutover_aware_workorder_drafts = __esm({
|
|
|
257419
257722
|
async forWorkspace(w2) {
|
|
257420
257723
|
return (await this.pick()).forWorkspace(w2);
|
|
257421
257724
|
}
|
|
257725
|
+
async forWorkspaceVersion(w2, version2) {
|
|
257726
|
+
return (await this.pick()).forWorkspaceVersion(w2, version2);
|
|
257727
|
+
}
|
|
257422
257728
|
async forSession(s2) {
|
|
257423
257729
|
return (await this.pick()).forSession(s2);
|
|
257424
257730
|
}
|
|
@@ -258431,7 +258737,7 @@ var init_src11 = __esm({
|
|
|
258431
258737
|
init_execution_continuity2();
|
|
258432
258738
|
init_chat_sessions();
|
|
258433
258739
|
init_dev_store();
|
|
258434
|
-
|
|
258740
|
+
init_continuation3();
|
|
258435
258741
|
init_knowledge2();
|
|
258436
258742
|
init_delegations();
|
|
258437
258743
|
init_automations();
|
|
@@ -258968,9 +259274,9 @@ function render(reason, facts) {
|
|
|
258968
259274
|
switch (reason.kind) {
|
|
258969
259275
|
case "checkpoints-exhausted":
|
|
258970
259276
|
return {
|
|
258971
|
-
headline: `\u8FD9\u4E00\u6B65**\
|
|
259277
|
+
headline: `\u8FD9\u4E00\u6B65**\u8FDE\u7EED ${reason.rounds} \u8F6E\u6CA1\u6709\u65B0\u589E\u4EA4\u4ED8\u5185\u5BB9**\uFF0C\u91CD\u590D\u63D0\u4EA4\u5DF2\u6709\u5FEB\u7167\u4E14\u672A\u6536\u53E3\uFF08\u65E0\u8FDB\u5C55\u4E0A\u9650 ${reason.limit}\uFF09\u2014\u2014\u5F15\u64CE\u5DF2\u6682\u505C\u81EA\u52A8\u7EED\u8DD1\uFF0C\u7B49\u5F85\u4EBA\u5DE5\u5904\u7406\u3002`,
|
|
258972
259278
|
detail: facts,
|
|
258973
|
-
action: "\u9700\u8981\u4F60\u5904\u7406\uFF1A\
|
|
259279
|
+
action: "\u9700\u8981\u4F60\u5904\u7406\uFF1A\u68C0\u67E5\u6700\u8FD1\u5FEB\u7167\u548C\u5269\u4F59\u5DE5\u4F5C\uFF0C\u8865\u5145\u6267\u884C\u65B9\u5411\u540E\u91CD\u8DD1\u672C\u8282\u70B9\uFF08\u91CD\u7F6E\u65E0\u8FDB\u5C55\u8BA1\u6570\uFF09\uFF1B\u5982\u679C\u5DF2\u7ECF\u5B8C\u6210\uFF0C\u8BA9\u6267\u884C\u4EBA\u63D0\u4EA4\u5B8C\u6574\u5FEB\u7167\u5E76 conclude\u3002"
|
|
258974
259280
|
};
|
|
258975
259281
|
case "gate-rejections-exhausted":
|
|
258976
259282
|
return {
|
|
@@ -263671,6 +263977,10 @@ async function startServe(opts) {
|
|
|
263671
263977
|
return false;
|
|
263672
263978
|
});
|
|
263673
263979
|
const engineIO = {
|
|
263980
|
+
async continuationPolicy(actorId) {
|
|
263981
|
+
const config2 = await (await companyRegistryFor(companyId)).latestConfig(actorId);
|
|
263982
|
+
return config2?.batchedContinuation ? { maxRounds: config2.continuationMaxRounds ?? 3 } : null;
|
|
263983
|
+
},
|
|
263674
263984
|
async dispatchWork(workId, opts2) {
|
|
263675
263985
|
if (engineDispatchBridges.size === 0) {
|
|
263676
263986
|
console.warn(`[new-engine] dispatchWork ${workId} \u8DF3\u8FC7\uFF1A\u672C\u8FDB\u7A0B\u4E00\u5BB6\u516C\u53F8\u7684\u6D3E\u53D1\u6865\u90FD\u6CA1\u6709\uFF08--dispatch \u672A\u5F00\uFF1F\uFF09`);
|
|
@@ -272829,7 +273139,7 @@ function shimScript() {
|
|
|
272829
273139
|
}
|
|
272830
273140
|
|
|
272831
273141
|
// src/index.ts
|
|
272832
|
-
var PKG_VERSION = true ? "2.2.
|
|
273142
|
+
var PKG_VERSION = true ? "2.2.21" : "dev";
|
|
272833
273143
|
var LOCAL_BIN = localBin();
|
|
272834
273144
|
var NPM_PREFIX = npmPrefix();
|
|
272835
273145
|
var INSTANCE = DEFAULT_INSTANCE;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oasis_test_v2",
|
|
3
|
-
"version": "2.2.
|
|
3
|
+
"version": "2.2.21",
|
|
4
4
|
"description": "Oasis node daemon + CLI — background daemon, auto-start, full server CLI",
|
|
5
5
|
"bin": {
|
|
6
6
|
"oasis": "./dist/index.js"
|
|
@@ -26,6 +26,6 @@
|
|
|
26
26
|
"node": ">=20"
|
|
27
27
|
},
|
|
28
28
|
"oasisRelease": {
|
|
29
|
-
"sourceHead": "
|
|
29
|
+
"sourceHead": "9d8339aadeb1d13c73ce23e2f4d03d4616c54a90"
|
|
30
30
|
}
|
|
31
31
|
}
|