@useorgx/openclaw-plugin 0.7.8 → 0.7.15
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/README.md +94 -122
- package/dashboard/dist/assets/0RUEVzJa.js +1 -0
- package/dashboard/dist/assets/0RUEVzJa.js.br +0 -0
- package/dashboard/dist/assets/0RUEVzJa.js.gz +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js +1 -0
- package/dashboard/dist/assets/3TtV4moZ.js.br +0 -0
- package/dashboard/dist/assets/3TtV4moZ.js.gz +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js +1 -0
- package/dashboard/dist/assets/3VwNyxUf.js.br +0 -0
- package/dashboard/dist/assets/3VwNyxUf.js.gz +0 -0
- package/dashboard/dist/assets/{DpuQm1oF.js → 7DhYqBrM.js} +2 -2
- package/dashboard/dist/assets/7DhYqBrM.js.br +0 -0
- package/dashboard/dist/assets/7DhYqBrM.js.gz +0 -0
- package/dashboard/dist/assets/{tcEHYcbW.js → BCudUvwg.js} +1 -1
- package/dashboard/dist/assets/BCudUvwg.js.br +0 -0
- package/dashboard/dist/assets/BCudUvwg.js.gz +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js +53 -0
- package/dashboard/dist/assets/BV0BcV1u.js.br +0 -0
- package/dashboard/dist/assets/BV0BcV1u.js.gz +0 -0
- package/dashboard/dist/assets/BVvffj0x.js +1 -0
- package/dashboard/dist/assets/BVvffj0x.js.br +0 -0
- package/dashboard/dist/assets/BVvffj0x.js.gz +0 -0
- package/dashboard/dist/assets/BiOgVMED.js +1 -0
- package/dashboard/dist/assets/BiOgVMED.js.br +0 -0
- package/dashboard/dist/assets/BiOgVMED.js.gz +0 -0
- package/dashboard/dist/assets/BjK42gtU.js +1 -0
- package/dashboard/dist/assets/BjK42gtU.js.br +0 -0
- package/dashboard/dist/assets/BjK42gtU.js.gz +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js +1 -0
- package/dashboard/dist/assets/C-MOJWHs.js.br +0 -0
- package/dashboard/dist/assets/C-MOJWHs.js.gz +0 -0
- package/dashboard/dist/assets/C91KLKit.js +1 -0
- package/dashboard/dist/assets/C91KLKit.js.br +0 -0
- package/dashboard/dist/assets/C91KLKit.js.gz +0 -0
- package/dashboard/dist/assets/{CnitK1MX.js → C9fvfXmS.js} +1 -1
- package/dashboard/dist/assets/C9fvfXmS.js.br +0 -0
- package/dashboard/dist/assets/C9fvfXmS.js.gz +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js +1 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.br +0 -0
- package/dashboard/dist/assets/CFZ4Swr5.js.gz +0 -0
- package/dashboard/dist/assets/{77gGFBt6.js → CGj8kRhg.js} +1 -1
- package/dashboard/dist/assets/CGj8kRhg.js.br +0 -0
- package/dashboard/dist/assets/CGj8kRhg.js.gz +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js +1 -0
- package/dashboard/dist/assets/CJjEAGFN.js.br +0 -0
- package/dashboard/dist/assets/CJjEAGFN.js.gz +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js +1 -0
- package/dashboard/dist/assets/CKrH5fYO.js.br +0 -0
- package/dashboard/dist/assets/CKrH5fYO.js.gz +0 -0
- package/dashboard/dist/assets/CMTTPXch.js +1 -0
- package/dashboard/dist/assets/CMTTPXch.js.br +0 -0
- package/dashboard/dist/assets/CMTTPXch.js.gz +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js +1 -0
- package/dashboard/dist/assets/CSlBSRyv.js.br +0 -0
- package/dashboard/dist/assets/CSlBSRyv.js.gz +0 -0
- package/dashboard/dist/assets/CnPC783_.js +1 -0
- package/dashboard/dist/assets/CnPC783_.js.br +0 -0
- package/dashboard/dist/assets/CnPC783_.js.gz +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js +1 -0
- package/dashboard/dist/assets/Ctw95IkC.js.br +0 -0
- package/dashboard/dist/assets/Ctw95IkC.js.gz +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js +1 -0
- package/dashboard/dist/assets/DHz-aQPw.js.br +0 -0
- package/dashboard/dist/assets/DHz-aQPw.js.gz +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css +1 -0
- package/dashboard/dist/assets/DNX2foSJ.css.br +0 -0
- package/dashboard/dist/assets/DNX2foSJ.css.gz +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js +8 -0
- package/dashboard/dist/assets/Dj2k1r16.js.br +0 -0
- package/dashboard/dist/assets/Dj2k1r16.js.gz +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js +212 -0
- package/dashboard/dist/assets/DxUw4FMR.js.br +0 -0
- package/dashboard/dist/assets/DxUw4FMR.js.gz +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js +1 -0
- package/dashboard/dist/assets/T2NFtzAv.js.br +0 -0
- package/dashboard/dist/assets/T2NFtzAv.js.gz +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js +1 -0
- package/dashboard/dist/assets/cX2e-TLi.js.br +0 -0
- package/dashboard/dist/assets/cX2e-TLi.js.gz +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js +9 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.br +0 -0
- package/dashboard/dist/assets/eeHXe_OQ.js.gz +0 -0
- package/dashboard/dist/assets/{DxKG5zy8.js → gZr_xKlA.js} +2 -2
- package/dashboard/dist/assets/gZr_xKlA.js.br +0 -0
- package/dashboard/dist/assets/gZr_xKlA.js.gz +0 -0
- package/dashboard/dist/brand/control-tower.png +0 -0
- package/dashboard/dist/brand/design-codex.png +0 -0
- package/dashboard/dist/brand/engineering-autopilot.png +0 -0
- package/dashboard/dist/brand/launch-captain.png +0 -0
- package/dashboard/dist/brand/orgx-logo.png +0 -0
- package/dashboard/dist/brand/pipeline-intelligence.png +0 -0
- package/dashboard/dist/brand/product-orchestrator.png +0 -0
- package/dashboard/dist/brand/xandy-orchestrator.png +0 -0
- package/dashboard/dist/index.html +8 -6
- package/dashboard/dist/index.html.br +0 -0
- package/dashboard/dist/index.html.gz +0 -0
- package/dist/hash-utils.d.ts +1 -0
- package/dist/hash-utils.js +4 -0
- package/dist/http/helpers/auto-continue-engine.d.ts +36 -0
- package/dist/http/helpers/auto-continue-engine.js +198 -75
- package/dist/http/helpers/autopilot-runtime.d.ts +1 -0
- package/dist/http/helpers/autopilot-runtime.js +31 -3
- package/dist/http/helpers/autopilot-slice-utils.d.ts +10 -0
- package/dist/http/helpers/autopilot-slice-utils.js +158 -54
- package/dist/http/helpers/hash-utils.d.ts +1 -1
- package/dist/http/helpers/hash-utils.js +1 -1
- package/dist/http/helpers/humanize-slice-failure.d.ts +35 -0
- package/dist/http/helpers/humanize-slice-failure.js +137 -0
- package/dist/http/helpers/mission-control.d.ts +1 -0
- package/dist/http/helpers/mission-control.js +73 -7
- package/dist/http/helpers/queue-constants.d.ts +37 -0
- package/dist/http/helpers/queue-constants.js +34 -0
- package/dist/http/helpers/slice-experience-v2.js +2 -5
- package/dist/http/helpers/slice-run-projections.js +2 -5
- package/dist/http/helpers/workspace-scope.js +4 -3
- package/dist/http/index.js +166 -63
- package/dist/http/routes/chat.js +1 -21
- package/dist/http/routes/live-misc.js +9 -2
- package/dist/http/routes/live-snapshot.js +14 -27
- package/dist/http/routes/mission-control-actions.js +7 -18
- package/dist/http/routes/mission-control-read.d.ts +1 -0
- package/dist/http/routes/mission-control-read.js +14 -56
- package/dist/index.d.ts +8 -1
- package/dist/index.js +21 -1
- package/dist/lib/type-coercion.d.ts +10 -0
- package/dist/lib/type-coercion.js +82 -0
- package/dist/mcp-http-handler.js +14 -2
- package/dist/openclaw.plugin.json +1 -1
- package/dist/services/experiment-randomization.js +9 -2
- package/dist/tools/core-tools.d.ts +27 -0
- package/dist/tools/core-tools.js +89 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +3 -2
- package/dashboard/dist/assets/77gGFBt6.js.br +0 -0
- package/dashboard/dist/assets/77gGFBt6.js.gz +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js +0 -1
- package/dashboard/dist/assets/BBpTN_SR.js.br +0 -0
- package/dashboard/dist/assets/BBpTN_SR.js.gz +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js +0 -53
- package/dashboard/dist/assets/BJgZIVUQ.js.br +0 -0
- package/dashboard/dist/assets/BJgZIVUQ.js.gz +0 -0
- package/dashboard/dist/assets/BTAEErUY.js +0 -1
- package/dashboard/dist/assets/BTAEErUY.js.br +0 -0
- package/dashboard/dist/assets/BTAEErUY.js.gz +0 -0
- package/dashboard/dist/assets/BVShoyjA.js +0 -1
- package/dashboard/dist/assets/BVShoyjA.js.br +0 -0
- package/dashboard/dist/assets/BVShoyjA.js.gz +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js +0 -1
- package/dashboard/dist/assets/BgcAY5rE.js.br +0 -0
- package/dashboard/dist/assets/BgcAY5rE.js.gz +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js +0 -1
- package/dashboard/dist/assets/C-KIc3Wc.js.br +0 -0
- package/dashboard/dist/assets/C-KIc3Wc.js.gz +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js +0 -1
- package/dashboard/dist/assets/C-PAoJF-.js.br +0 -0
- package/dashboard/dist/assets/C-PAoJF-.js.gz +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js +0 -1
- package/dashboard/dist/assets/C0nA-iUG.js.br +0 -0
- package/dashboard/dist/assets/C0nA-iUG.js.gz +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js +0 -1
- package/dashboard/dist/assets/C6GO-FKy.js.br +0 -0
- package/dashboard/dist/assets/C6GO-FKy.js.gz +0 -0
- package/dashboard/dist/assets/CFwPph5U.js +0 -1
- package/dashboard/dist/assets/CFwPph5U.js.br +0 -0
- package/dashboard/dist/assets/CFwPph5U.js.gz +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js +0 -1
- package/dashboard/dist/assets/CL_wXqR7.js.br +0 -0
- package/dashboard/dist/assets/CL_wXqR7.js.gz +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js +0 -212
- package/dashboard/dist/assets/CPjsbbgZ.js.br +0 -0
- package/dashboard/dist/assets/CPjsbbgZ.js.gz +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js +0 -1
- package/dashboard/dist/assets/CSr2ZnTV.js.br +0 -0
- package/dashboard/dist/assets/CSr2ZnTV.js.gz +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js +0 -1
- package/dashboard/dist/assets/CgQDT6yL.js.br +0 -0
- package/dashboard/dist/assets/CgQDT6yL.js.gz +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.br +0 -0
- package/dashboard/dist/assets/CnitK1MX.js.gz +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js +0 -9
- package/dashboard/dist/assets/CxQ08qFN.js.br +0 -0
- package/dashboard/dist/assets/CxQ08qFN.js.gz +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js +0 -1
- package/dashboard/dist/assets/D7DHFX0D.js.br +0 -0
- package/dashboard/dist/assets/D7DHFX0D.js.gz +0 -0
- package/dashboard/dist/assets/DEip7uko.js +0 -1
- package/dashboard/dist/assets/DEip7uko.js.br +0 -0
- package/dashboard/dist/assets/DEip7uko.js.gz +0 -0
- package/dashboard/dist/assets/DHUSLc01.css +0 -1
- package/dashboard/dist/assets/DHUSLc01.css.br +0 -0
- package/dashboard/dist/assets/DHUSLc01.css.gz +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js +0 -1
- package/dashboard/dist/assets/DOFL9l8s.js.br +0 -0
- package/dashboard/dist/assets/DOFL9l8s.js.gz +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.br +0 -0
- package/dashboard/dist/assets/DpuQm1oF.js.gz +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.br +0 -0
- package/dashboard/dist/assets/DxKG5zy8.js.gz +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js +0 -8
- package/dashboard/dist/assets/cNrhgGc1.js.br +0 -0
- package/dashboard/dist/assets/cNrhgGc1.js.gz +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.br +0 -0
- package/dashboard/dist/assets/tcEHYcbW.js.gz +0 -0
|
@@ -9,11 +9,13 @@ import { appendTeamCompletion } from "../../team-context-store.js";
|
|
|
9
9
|
import { readOpenClawGatewayPort, readOpenClawSettingsSnapshot, } from "../../openclaw-settings.js";
|
|
10
10
|
import { resolveRuntimeHookToken, } from "../../runtime-instance-store.js";
|
|
11
11
|
import { detectMcpHandshakeFailure, shouldKillWorker } from "../../worker-supervisor.js";
|
|
12
|
+
import { humanizeSliceFailure, humanizeSliceFailureSummary } from "./humanize-slice-failure.js";
|
|
12
13
|
import { getOrgxPluginConfigDir } from "../../paths.js";
|
|
13
14
|
import { buildMissionControlGraph, DEFAULT_TOKEN_BUDGET_ASSUMPTIONS, dedupeStrings, detectBehaviorConfigDrift, deriveBehaviorAutomationLevel, deriveBehaviorConfigContext, deriveExecutionPolicy, evaluateScopeCompletion, isDispatchableWorkstreamStatus, isDoneStatus, isTodoStatus, readBudgetEnvNumber, selectSliceTasksByScope, SLICE_SCOPE_TIMEOUT_MULTIPLIER, spawnGuardIsRateLimited, summarizeSpawnGuardBlockReason, } from "./mission-control.js";
|
|
14
15
|
import { createAutopilotRuntime } from "./autopilot-runtime.js";
|
|
15
|
-
import { buildScopeDirective, buildSliceOutputInstructions, buildWorkstreamSlicePrompt, createCodexBinResolver, ensureAutopilotSliceSchemaPath, fileUpdatedAtEpochMs, parseSliceResult, readFileTailSafe, readSliceOutputFile, } from "./autopilot-slice-utils.js";
|
|
16
|
+
import { buildScopeDirective, buildSliceOutputInstructions, buildWorkstreamSlicePrompt, createCodexBinResolver, ensureAutopilotSliceSchemaPath, extractSessionIdFromLog, extractSessionIdFromOutput, fileUpdatedAtEpochMs, parseSliceResult, readFileTailSafe, readSliceOutputFile, } from "./autopilot-slice-utils.js";
|
|
16
17
|
import { pickString } from "./value-utils.js";
|
|
18
|
+
import { LaneState, RunStatus, } from "./queue-constants.js";
|
|
17
19
|
function resolveAutopilotDefaultCwd(filename) {
|
|
18
20
|
let cursor = dirname(filename);
|
|
19
21
|
for (let i = 0; i < 12; i += 1) {
|
|
@@ -63,6 +65,35 @@ export function createAutoContinueEngine(deps) {
|
|
|
63
65
|
? "reject"
|
|
64
66
|
: "approve";
|
|
65
67
|
const autoContinueSliceRuns = new Map();
|
|
68
|
+
const workstreamSessionStore = new Map();
|
|
69
|
+
function sessionResumeEnabled() {
|
|
70
|
+
const raw = (process.env.ORGX_AUTOPILOT_SESSION_RESUME ?? "").trim().toLowerCase();
|
|
71
|
+
if (!raw)
|
|
72
|
+
return false;
|
|
73
|
+
return !(raw === "0" || raw === "false" || raw === "no" || raw === "off");
|
|
74
|
+
}
|
|
75
|
+
function setWorkstreamSession(workstreamId, entry) {
|
|
76
|
+
workstreamSessionStore.set(workstreamId, entry);
|
|
77
|
+
}
|
|
78
|
+
function getWorkstreamSession(workstreamId) {
|
|
79
|
+
return workstreamSessionStore.get(workstreamId) ?? null;
|
|
80
|
+
}
|
|
81
|
+
function clearWorkstreamSession(initiativeId) {
|
|
82
|
+
for (const [key, entry] of workstreamSessionStore.entries()) {
|
|
83
|
+
if (entry.initiativeId === initiativeId) {
|
|
84
|
+
workstreamSessionStore.delete(key);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
function listWorkstreamSessions(initiativeId) {
|
|
89
|
+
const results = [];
|
|
90
|
+
for (const entry of workstreamSessionStore.values()) {
|
|
91
|
+
if (!initiativeId || entry.initiativeId === initiativeId) {
|
|
92
|
+
results.push(entry);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return results;
|
|
96
|
+
}
|
|
66
97
|
/** Spread into any metadata object to flag mock-worker activity. */
|
|
67
98
|
function mockMeta(slice) {
|
|
68
99
|
return slice.isMockWorker ? { mock: true } : {};
|
|
@@ -999,7 +1030,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
999
1030
|
}
|
|
1000
1031
|
const existing = run.laneByWorkstreamId[normalizedWorkstreamId] ?? {
|
|
1001
1032
|
workstreamId: normalizedWorkstreamId,
|
|
1002
|
-
state:
|
|
1033
|
+
state: LaneState.IDLE,
|
|
1003
1034
|
activeRunId: null,
|
|
1004
1035
|
activeTaskIds: [],
|
|
1005
1036
|
blockedReason: null,
|
|
@@ -1051,12 +1082,12 @@ export function createAutoContinueEngine(deps) {
|
|
|
1051
1082
|
if (lane && lane.activeRunId === sliceRunId) {
|
|
1052
1083
|
setLaneState(run, {
|
|
1053
1084
|
workstreamId: normalizedWorkstreamId,
|
|
1054
|
-
state: lane.state ===
|
|
1085
|
+
state: lane.state === LaneState.BLOCKED ? "blocked" : "idle",
|
|
1055
1086
|
activeRunId: null,
|
|
1056
1087
|
activeTaskIds: [],
|
|
1057
1088
|
retryAt: lane.retryAt ?? null,
|
|
1058
1089
|
waitingOnWorkstreamIds: lane.waitingOnWorkstreamIds ?? [],
|
|
1059
|
-
blockedReason: lane.state ===
|
|
1090
|
+
blockedReason: lane.state === LaneState.BLOCKED ? lane.blockedReason : null,
|
|
1060
1091
|
});
|
|
1061
1092
|
}
|
|
1062
1093
|
}
|
|
@@ -1359,7 +1390,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1359
1390
|
updated_at: lane.updatedAt,
|
|
1360
1391
|
}));
|
|
1361
1392
|
const patch = {
|
|
1362
|
-
auto_continue_enabled: input.run.status ===
|
|
1393
|
+
auto_continue_enabled: input.run.status === RunStatus.RUNNING || input.run.status === RunStatus.STOPPING,
|
|
1363
1394
|
auto_continue_status: input.run.status,
|
|
1364
1395
|
auto_continue_stop_reason: input.run.stopReason,
|
|
1365
1396
|
auto_continue_started_at: input.run.startedAt,
|
|
@@ -1398,7 +1429,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1398
1429
|
const now = new Date().toISOString();
|
|
1399
1430
|
ensureRunInternals(input.run);
|
|
1400
1431
|
const activeRunIds = listActiveSliceRunIds(input.run);
|
|
1401
|
-
input.run.status =
|
|
1432
|
+
input.run.status = RunStatus.STOPPED;
|
|
1402
1433
|
input.run.stopReason = input.reason;
|
|
1403
1434
|
input.run.stoppedAt = now;
|
|
1404
1435
|
input.run.updatedAt = now;
|
|
@@ -1412,7 +1443,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1412
1443
|
if (lane.activeRunId || lane.activeTaskIds.length > 0) {
|
|
1413
1444
|
setLaneState(input.run, {
|
|
1414
1445
|
workstreamId: lane.workstreamId,
|
|
1415
|
-
state: lane.state ===
|
|
1446
|
+
state: lane.state === LaneState.BLOCKED ? "blocked" : "idle",
|
|
1416
1447
|
activeRunId: null,
|
|
1417
1448
|
activeTaskIds: [],
|
|
1418
1449
|
});
|
|
@@ -1542,7 +1573,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1542
1573
|
event: "autopilot_transition",
|
|
1543
1574
|
actionType: "run_state_transition",
|
|
1544
1575
|
}),
|
|
1545
|
-
old_state:
|
|
1576
|
+
old_state: LaneState.RUNNING,
|
|
1546
1577
|
new_state: input.reason === "completed" || input.reason === "stopped" ? "idle" : input.reason === "blocked" ? "blocked" : input.reason === "error" ? "error" : "idle",
|
|
1547
1578
|
reason: input.reason,
|
|
1548
1579
|
workspace_id: input.run.allowedWorkstreamIds?.[0] ?? null,
|
|
@@ -1700,8 +1731,8 @@ export function createAutoContinueEngine(deps) {
|
|
|
1700
1731
|
const decisionResult = await requestDecisionQueued({
|
|
1701
1732
|
initiativeId: run.initiativeId,
|
|
1702
1733
|
correlationId: slice.runId,
|
|
1703
|
-
title: `
|
|
1704
|
-
summary: `MCP handshake failed${mcpHandshake.server ? ` for ${mcpHandshake.server}` : ""}
|
|
1734
|
+
title: `Agent couldn't connect to tools: ${slice.workstreamTitle ?? slice.workstreamId}`,
|
|
1735
|
+
summary: humanizeSliceFailureSummary(`MCP handshake failed${mcpHandshake.server ? ` for ${mcpHandshake.server}` : ""}.`),
|
|
1705
1736
|
urgency: "high",
|
|
1706
1737
|
options: [
|
|
1707
1738
|
"Retry this workstream slice",
|
|
@@ -1744,7 +1775,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1744
1775
|
});
|
|
1745
1776
|
setLaneState(run, {
|
|
1746
1777
|
workstreamId: slice.workstreamId,
|
|
1747
|
-
state:
|
|
1778
|
+
state: LaneState.BLOCKED,
|
|
1748
1779
|
activeRunId: null,
|
|
1749
1780
|
activeTaskIds: [],
|
|
1750
1781
|
blockedReason: slice.lastError,
|
|
@@ -1786,6 +1817,9 @@ export function createAutoContinueEngine(deps) {
|
|
|
1786
1817
|
clearAutoContinueSliceTransientState(slice.runId);
|
|
1787
1818
|
const event = killDecision.kind === "timeout" ? "autopilot_slice_timeout" : "autopilot_slice_log_stall";
|
|
1788
1819
|
const humanLabel = killDecision.kind === "timeout" ? "timed out" : "stalled";
|
|
1820
|
+
const stallDecisionTitle = killDecision.kind === "timeout"
|
|
1821
|
+
? `Autopilot slice timed out: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
1822
|
+
: `Autopilot slice stalled: ${slice.workstreamTitle ?? slice.workstreamId}`;
|
|
1789
1823
|
await emitActivitySafe({
|
|
1790
1824
|
initiativeId: run.initiativeId,
|
|
1791
1825
|
runId: slice.runId,
|
|
@@ -1819,8 +1853,8 @@ export function createAutoContinueEngine(deps) {
|
|
|
1819
1853
|
const decisionResult = await requestDecisionQueued({
|
|
1820
1854
|
initiativeId: run.initiativeId,
|
|
1821
1855
|
correlationId: slice.runId,
|
|
1822
|
-
title:
|
|
1823
|
-
summary:
|
|
1856
|
+
title: stallDecisionTitle,
|
|
1857
|
+
summary: humanizeSliceFailureSummary(slice.lastError ?? `Autopilot slice ${humanLabel}`),
|
|
1824
1858
|
urgency: "high",
|
|
1825
1859
|
options: [
|
|
1826
1860
|
"Retry this workstream slice",
|
|
@@ -1872,7 +1906,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
1872
1906
|
});
|
|
1873
1907
|
setLaneState(run, {
|
|
1874
1908
|
workstreamId: slice.workstreamId,
|
|
1875
|
-
state:
|
|
1909
|
+
state: LaneState.BLOCKED,
|
|
1876
1910
|
activeRunId: null,
|
|
1877
1911
|
activeTaskIds: [],
|
|
1878
1912
|
blockedReason: slice.lastError,
|
|
@@ -1904,6 +1938,25 @@ export function createAutoContinueEngine(deps) {
|
|
|
1904
1938
|
const raw = readSliceOutputFile(slice.outputPath);
|
|
1905
1939
|
const parsed = raw ? parseSliceResult(raw) : null;
|
|
1906
1940
|
const parsedStatus = parsed?.status ?? "error";
|
|
1941
|
+
// Session capture: extract CLI session ID from output or log for future resume.
|
|
1942
|
+
if (sessionResumeEnabled()) {
|
|
1943
|
+
const outputSessionId = raw ? extractSessionIdFromOutput(raw, slice.sourceClient) : null;
|
|
1944
|
+
const logSessionId = outputSessionId
|
|
1945
|
+
? null
|
|
1946
|
+
: extractSessionIdFromLog(readFileTailSafe(slice.logPath, 32_000), slice.sourceClient);
|
|
1947
|
+
const capturedSessionId = outputSessionId ?? logSessionId ?? null;
|
|
1948
|
+
if (capturedSessionId) {
|
|
1949
|
+
slice.cliSessionId = capturedSessionId;
|
|
1950
|
+
setWorkstreamSession(slice.workstreamId, {
|
|
1951
|
+
sessionId: capturedSessionId,
|
|
1952
|
+
workstreamId: slice.workstreamId,
|
|
1953
|
+
initiativeId: slice.initiativeId,
|
|
1954
|
+
sourceClient: slice.sourceClient,
|
|
1955
|
+
capturedAt: new Date().toISOString(),
|
|
1956
|
+
fromRunId: slice.runId,
|
|
1957
|
+
});
|
|
1958
|
+
}
|
|
1959
|
+
}
|
|
1907
1960
|
const defaultDecisionBlocking = parsedStatus === "completed" ? false : true;
|
|
1908
1961
|
const allDecisions = Array.isArray(parsed?.decisions_needed)
|
|
1909
1962
|
? (parsed?.decisions_needed ?? [])
|
|
@@ -1919,13 +1972,25 @@ export function createAutoContinueEngine(deps) {
|
|
|
1919
1972
|
const decisions = allDecisions.filter((item) => !isParserSyntheticFallbackDecision(item));
|
|
1920
1973
|
const normalizedBlockingDecisionCount = allDecisions.filter((item) => typeof item.blocking === "boolean" ? item.blocking : defaultDecisionBlocking).length;
|
|
1921
1974
|
const normalizedNonBlockingDecisionCount = Math.max(0, allDecisions.length - normalizedBlockingDecisionCount);
|
|
1922
|
-
const
|
|
1975
|
+
const operationalParsedStatus = parsedStatus === "completed" && normalizedBlockingDecisionCount > 0
|
|
1923
1976
|
? "needs_decision"
|
|
1924
1977
|
: parsedStatus;
|
|
1978
|
+
const parsedSummarySignal = String(parsed?.summary ?? "").toLowerCase();
|
|
1979
|
+
const parsedLooksLikeNoOutcomeCompletion = operationalParsedStatus === "error" &&
|
|
1980
|
+
(parsedSummarySignal.includes("without verifiable outcomes") ||
|
|
1981
|
+
parsedSummarySignal.includes("without output") ||
|
|
1982
|
+
parsedSummarySignal.includes("without artifacts") ||
|
|
1983
|
+
parsedSummarySignal.includes("did not report artifacts") ||
|
|
1984
|
+
(parsedSummarySignal.includes("did not report") &&
|
|
1985
|
+
parsedSummarySignal.includes("status updates")) ||
|
|
1986
|
+
parsedSummarySignal.includes("produced nothing"));
|
|
1987
|
+
const reportedParsedStatus = parsedLooksLikeNoOutcomeCompletion
|
|
1988
|
+
? "completed"
|
|
1989
|
+
: operationalParsedStatus;
|
|
1925
1990
|
slice.status =
|
|
1926
|
-
|
|
1991
|
+
operationalParsedStatus === "completed"
|
|
1927
1992
|
? "completed"
|
|
1928
|
-
:
|
|
1993
|
+
: operationalParsedStatus === "blocked" || operationalParsedStatus === "needs_decision"
|
|
1929
1994
|
? "blocked"
|
|
1930
1995
|
: "error";
|
|
1931
1996
|
slice.finishedAt = now;
|
|
@@ -2005,7 +2070,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2005
2070
|
: [];
|
|
2006
2071
|
const resultEnvelope = {
|
|
2007
2072
|
summary: userSummary,
|
|
2008
|
-
parsed_status:
|
|
2073
|
+
parsed_status: reportedParsedStatus,
|
|
2009
2074
|
task_updates: taskUpdates,
|
|
2010
2075
|
milestone_updates: milestoneUpdates,
|
|
2011
2076
|
next_actions: nextActions,
|
|
@@ -2196,7 +2261,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2196
2261
|
correlation_id: slice.runId,
|
|
2197
2262
|
requested_by_agent_id: run.agentId,
|
|
2198
2263
|
requested_by_agent_name: run.agentName,
|
|
2199
|
-
status:
|
|
2264
|
+
status: reportedParsedStatus,
|
|
2200
2265
|
artifacts: artifacts.length,
|
|
2201
2266
|
decisions: allDecisions.length,
|
|
2202
2267
|
blocking_decisions: normalizedBlockingDecisionCount,
|
|
@@ -2240,7 +2305,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2240
2305
|
userSummary,
|
|
2241
2306
|
event: "autopilot_slice_handoff",
|
|
2242
2307
|
extra: {
|
|
2243
|
-
parsed_status:
|
|
2308
|
+
parsed_status: reportedParsedStatus,
|
|
2244
2309
|
artifacts: artifacts.length,
|
|
2245
2310
|
decisions: decisions.length,
|
|
2246
2311
|
decision_ids: decisionIds,
|
|
@@ -2286,7 +2351,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2286
2351
|
behavior_config_hash: slice.behaviorConfigHash,
|
|
2287
2352
|
policy_source: slice.behaviorPolicySource,
|
|
2288
2353
|
behavior_automation_level: slice.behaviorAutomationLevel,
|
|
2289
|
-
parsed_status:
|
|
2354
|
+
parsed_status: reportedParsedStatus,
|
|
2290
2355
|
has_output: Boolean(parsed),
|
|
2291
2356
|
artifacts: artifacts.length,
|
|
2292
2357
|
decisions: allDecisions.length,
|
|
@@ -2295,7 +2360,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2295
2360
|
decision_ids: decisionIds,
|
|
2296
2361
|
blocking_decision_ids: Array.from(new Set(blockingDecisionIds)),
|
|
2297
2362
|
non_blocking_decision_ids: Array.from(new Set(nonBlockingDecisionIds)),
|
|
2298
|
-
decision_required: blockingDecisionQueued ||
|
|
2363
|
+
decision_required: blockingDecisionQueued || operationalParsedStatus === "needs_decision",
|
|
2299
2364
|
status_updates_applied: statusUpdateResult.applied,
|
|
2300
2365
|
status_updates_buffered: statusUpdateResult.buffered,
|
|
2301
2366
|
reported_skill_evidence_count: skillEvidence.length,
|
|
@@ -2333,19 +2398,63 @@ export function createAutoContinueEngine(deps) {
|
|
|
2333
2398
|
queued: false,
|
|
2334
2399
|
decisionIds: [],
|
|
2335
2400
|
};
|
|
2401
|
+
const fallbackRawError = parsed?.summary ??
|
|
2402
|
+
slice.lastError ??
|
|
2403
|
+
(slice.status === "blocked"
|
|
2404
|
+
? "Execution is blocked and needs intervention."
|
|
2405
|
+
: "Agent process exited without a valid output contract.");
|
|
2406
|
+
const fallbackHumanized = humanizeSliceFailure(fallbackRawError);
|
|
2407
|
+
const fallbackErrorSignal = [
|
|
2408
|
+
parsed?.summary ?? null,
|
|
2409
|
+
slice.lastError ?? null,
|
|
2410
|
+
fallbackRawError,
|
|
2411
|
+
]
|
|
2412
|
+
.filter((entry) => typeof entry === "string" && entry.trim().length > 0)
|
|
2413
|
+
.join(" ")
|
|
2414
|
+
.toLowerCase();
|
|
2415
|
+
const looksLikeNoOutcome = fallbackErrorSignal.includes("without verifiable outcomes") ||
|
|
2416
|
+
fallbackErrorSignal.includes("without output") ||
|
|
2417
|
+
fallbackErrorSignal.includes("without artifacts") ||
|
|
2418
|
+
fallbackErrorSignal.includes("did not report artifacts") ||
|
|
2419
|
+
(fallbackErrorSignal.includes("did not report") &&
|
|
2420
|
+
fallbackErrorSignal.includes("status updates")) ||
|
|
2421
|
+
fallbackErrorSignal.includes("produced nothing");
|
|
2422
|
+
const looksLikeStall = fallbackErrorSignal.includes("stall") ||
|
|
2423
|
+
fallbackErrorSignal.includes("stopped making progress");
|
|
2424
|
+
const looksLikeTimeout = fallbackErrorSignal.includes("timeout") ||
|
|
2425
|
+
fallbackErrorSignal.includes("timed out") ||
|
|
2426
|
+
fallbackErrorSignal.includes("ran out of time");
|
|
2427
|
+
const blockedLike = slice.status === "blocked" ||
|
|
2428
|
+
looksLikeNoOutcome ||
|
|
2429
|
+
looksLikeStall ||
|
|
2430
|
+
looksLikeTimeout;
|
|
2431
|
+
const decisionConflictSource = looksLikeNoOutcome
|
|
2432
|
+
? "slice_completed_without_outcome"
|
|
2433
|
+
: looksLikeTimeout
|
|
2434
|
+
? "slice_timeout"
|
|
2435
|
+
: looksLikeStall
|
|
2436
|
+
? "slice_stall_no_output"
|
|
2437
|
+
: blockedLike
|
|
2438
|
+
? "slice_missing_blocking_decision"
|
|
2439
|
+
: "slice_invalid_output";
|
|
2440
|
+
const fallbackDecisionTitle = looksLikeNoOutcome
|
|
2441
|
+
? `Autopilot slice needs verification: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
2442
|
+
: looksLikeStall
|
|
2443
|
+
? `Autopilot slice stalled: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
2444
|
+
: looksLikeTimeout
|
|
2445
|
+
? `Autopilot slice timed out: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
2446
|
+
: blockedLike
|
|
2447
|
+
? `Autopilot slice blocked: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
2448
|
+
: `Autopilot slice failed: ${slice.workstreamTitle ?? slice.workstreamId}`;
|
|
2449
|
+
const fallbackDecisionSummary = looksLikeNoOutcome
|
|
2450
|
+
? "The slice reported completion but did not produce artifacts or status updates. Decide whether to retry, request stronger output, or mark tasks manually."
|
|
2451
|
+
: fallbackHumanized.explanation;
|
|
2336
2452
|
if (!blockingDecisionQueued) {
|
|
2337
|
-
const blockedLike = slice.status === "blocked";
|
|
2338
2453
|
fallbackDecisionResult = await requestDecisionQueued({
|
|
2339
2454
|
initiativeId: run.initiativeId,
|
|
2340
2455
|
correlationId: slice.runId,
|
|
2341
|
-
title:
|
|
2342
|
-
|
|
2343
|
-
: `Autopilot slice failed: ${slice.workstreamTitle ?? slice.workstreamId}`,
|
|
2344
|
-
summary: parsed?.summary ??
|
|
2345
|
-
slice.lastError ??
|
|
2346
|
-
(blockedLike
|
|
2347
|
-
? "The slice reported a blocked/decision-required state without a blocking decision payload. Review logs/output and decide whether to retry, unblock, or skip."
|
|
2348
|
-
: "The slice failed without producing a valid output contract. Review logs/output and decide whether to retry or pause autopilot."),
|
|
2456
|
+
title: fallbackDecisionTitle,
|
|
2457
|
+
summary: fallbackDecisionSummary,
|
|
2349
2458
|
urgency: "high",
|
|
2350
2459
|
options: [
|
|
2351
2460
|
"Retry this workstream slice",
|
|
@@ -2353,18 +2462,20 @@ export function createAutoContinueEngine(deps) {
|
|
|
2353
2462
|
"Skip this workstream for now",
|
|
2354
2463
|
],
|
|
2355
2464
|
blocking: true,
|
|
2356
|
-
decisionType:
|
|
2465
|
+
decisionType: looksLikeNoOutcome
|
|
2466
|
+
? "autopilot_completed_without_outcome"
|
|
2467
|
+
: blockedLike
|
|
2468
|
+
? "autopilot_blocked_without_decision"
|
|
2469
|
+
: "autopilot_failure",
|
|
2357
2470
|
workstreamId: slice.workstreamId,
|
|
2358
2471
|
agentId: slice.agentId,
|
|
2359
2472
|
sourceSystem: "orgx-autopilot",
|
|
2360
|
-
conflictSource:
|
|
2361
|
-
? "slice_missing_blocking_decision"
|
|
2362
|
-
: "slice_invalid_output",
|
|
2473
|
+
conflictSource: decisionConflictSource,
|
|
2363
2474
|
dedupeKey: [
|
|
2364
2475
|
"autopilot",
|
|
2365
2476
|
run.initiativeId,
|
|
2366
2477
|
slice.workstreamId,
|
|
2367
|
-
|
|
2478
|
+
decisionConflictSource,
|
|
2368
2479
|
].join(":"),
|
|
2369
2480
|
recommendedAction: nextActions[0] ??
|
|
2370
2481
|
"Review the output contract and logs, then retry or pause autopilot until the blocker is resolved.",
|
|
@@ -2372,19 +2483,17 @@ export function createAutoContinueEngine(deps) {
|
|
|
2372
2483
|
sourceRef: {
|
|
2373
2484
|
run_id: slice.runId,
|
|
2374
2485
|
workstream_id: slice.workstreamId,
|
|
2375
|
-
parsed_status:
|
|
2486
|
+
parsed_status: reportedParsedStatus,
|
|
2376
2487
|
},
|
|
2377
2488
|
evidenceRefs: [
|
|
2378
2489
|
{
|
|
2379
2490
|
evidence_type: "slice_output_validation",
|
|
2380
2491
|
title: "Slice output requires fallback decision",
|
|
2381
|
-
summary:
|
|
2382
|
-
slice.lastError ??
|
|
2383
|
-
"Slice did not provide a blocking decision payload.",
|
|
2492
|
+
summary: fallbackDecisionSummary,
|
|
2384
2493
|
source_pointer: slice.outputPath,
|
|
2385
2494
|
payload: {
|
|
2386
2495
|
log_path: slice.logPath,
|
|
2387
|
-
parsed_status:
|
|
2496
|
+
parsed_status: reportedParsedStatus,
|
|
2388
2497
|
},
|
|
2389
2498
|
},
|
|
2390
2499
|
...artifactEvidenceRefs,
|
|
@@ -2393,12 +2502,12 @@ export function createAutoContinueEngine(deps) {
|
|
|
2393
2502
|
}
|
|
2394
2503
|
setLaneState(run, {
|
|
2395
2504
|
workstreamId: slice.workstreamId,
|
|
2396
|
-
state:
|
|
2505
|
+
state: LaneState.BLOCKED,
|
|
2397
2506
|
activeRunId: null,
|
|
2398
2507
|
activeTaskIds: [],
|
|
2399
2508
|
blockedReason: parsed?.summary ??
|
|
2400
2509
|
slice.lastError ??
|
|
2401
|
-
`Slice returned status: ${
|
|
2510
|
+
`Slice returned status: ${reportedParsedStatus}`,
|
|
2402
2511
|
waitingOnWorkstreamIds: [],
|
|
2403
2512
|
retryAt: null,
|
|
2404
2513
|
});
|
|
@@ -2407,10 +2516,8 @@ export function createAutoContinueEngine(deps) {
|
|
|
2407
2516
|
}
|
|
2408
2517
|
await stopAutoContinueRun({
|
|
2409
2518
|
run,
|
|
2410
|
-
reason:
|
|
2411
|
-
error:
|
|
2412
|
-
slice.lastError ??
|
|
2413
|
-
`Slice returned status: ${effectiveParsedStatus}`,
|
|
2519
|
+
reason: blockedLike ? "blocked" : "error",
|
|
2520
|
+
error: fallbackRawError,
|
|
2414
2521
|
decisionRequired: blockingDecisionQueued || fallbackDecisionResult.queued,
|
|
2415
2522
|
decisionIds: Array.from(new Set([...decisionIds, ...fallbackDecisionResult.decisionIds])),
|
|
2416
2523
|
});
|
|
@@ -2421,12 +2528,14 @@ export function createAutoContinueEngine(deps) {
|
|
|
2421
2528
|
decisions.length === 0 &&
|
|
2422
2529
|
statusUpdateResult.applied === 0;
|
|
2423
2530
|
if (!parsed || parsedStatus === "error" || completionHadNoOutcome) {
|
|
2531
|
+
const rawError = slice.lastError ?? (completionHadNoOutcome
|
|
2532
|
+
? "Completed without verifiable outcomes or artifacts."
|
|
2533
|
+
: "Agent process exited without a valid output contract.");
|
|
2534
|
+
const humanized = humanizeSliceFailure(rawError);
|
|
2424
2535
|
const attentionTitle = completionHadNoOutcome
|
|
2425
|
-
? `
|
|
2426
|
-
:
|
|
2427
|
-
const attentionSummary =
|
|
2428
|
-
? "The slice reported completion but did not produce artifacts or status updates. Decide whether to retry, request stronger output, or mark tasks manually."
|
|
2429
|
-
: "The slice exited without a valid output contract. Review logs/output and decide whether to retry or pause autopilot.";
|
|
2536
|
+
? `Agent finished but produced nothing: ${slice.workstreamTitle ?? slice.workstreamId}`
|
|
2537
|
+
: `${humanized.headline}: ${slice.workstreamTitle ?? slice.workstreamId}`;
|
|
2538
|
+
const attentionSummary = humanized.explanation;
|
|
2430
2539
|
const decisionResult = await requestDecisionQueued({
|
|
2431
2540
|
initiativeId: run.initiativeId,
|
|
2432
2541
|
correlationId: slice.runId,
|
|
@@ -2481,7 +2590,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2481
2590
|
});
|
|
2482
2591
|
setLaneState(run, {
|
|
2483
2592
|
workstreamId: slice.workstreamId,
|
|
2484
|
-
state:
|
|
2593
|
+
state: LaneState.BLOCKED,
|
|
2485
2594
|
activeRunId: null,
|
|
2486
2595
|
activeTaskIds: [],
|
|
2487
2596
|
blockedReason: slice.lastError ??
|
|
@@ -2515,7 +2624,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2515
2624
|
});
|
|
2516
2625
|
setLaneState(run, {
|
|
2517
2626
|
workstreamId: slice.workstreamId,
|
|
2518
|
-
state:
|
|
2627
|
+
state: LaneState.COMPLETED,
|
|
2519
2628
|
activeRunId: null,
|
|
2520
2629
|
activeTaskIds: [],
|
|
2521
2630
|
blockedReason: null,
|
|
@@ -2593,7 +2702,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2593
2702
|
}
|
|
2594
2703
|
syncLegacyRunPointers(run);
|
|
2595
2704
|
if (run.stopRequested) {
|
|
2596
|
-
run.status =
|
|
2705
|
+
run.status = RunStatus.STOPPING;
|
|
2597
2706
|
run.updatedAt = now;
|
|
2598
2707
|
await stopAutoContinueRun({ run, reason: "stopped" });
|
|
2599
2708
|
return;
|
|
@@ -2725,7 +2834,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2725
2834
|
for (const [workstreamId, waitingOnWorkstreamIds] of waitingByWorkstream.entries()) {
|
|
2726
2835
|
setLaneState(run, {
|
|
2727
2836
|
workstreamId,
|
|
2728
|
-
state:
|
|
2837
|
+
state: LaneState.WAITING_DEPENDENCY,
|
|
2729
2838
|
activeRunId: null,
|
|
2730
2839
|
activeTaskIds: [],
|
|
2731
2840
|
blockedReason: null,
|
|
@@ -2976,7 +3085,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
2976
3085
|
}
|
|
2977
3086
|
setLaneState(run, {
|
|
2978
3087
|
workstreamId: selectedWorkstreamId,
|
|
2979
|
-
state:
|
|
3088
|
+
state: LaneState.BLOCKED,
|
|
2980
3089
|
activeRunId: null,
|
|
2981
3090
|
activeTaskIds: [],
|
|
2982
3091
|
blockedReason,
|
|
@@ -3071,7 +3180,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3071
3180
|
}
|
|
3072
3181
|
setLaneState(run, {
|
|
3073
3182
|
workstreamId: selectedWorkstreamId,
|
|
3074
|
-
state:
|
|
3183
|
+
state: LaneState.BLOCKED,
|
|
3075
3184
|
activeRunId: null,
|
|
3076
3185
|
activeTaskIds: [],
|
|
3077
3186
|
blockedReason,
|
|
@@ -3136,7 +3245,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3136
3245
|
});
|
|
3137
3246
|
setLaneState(run, {
|
|
3138
3247
|
workstreamId: selectedWorkstreamId,
|
|
3139
|
-
state:
|
|
3248
|
+
state: LaneState.RATE_LIMITED,
|
|
3140
3249
|
activeRunId: null,
|
|
3141
3250
|
activeTaskIds: [],
|
|
3142
3251
|
blockedReason,
|
|
@@ -3219,7 +3328,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3219
3328
|
run.updatedAt = now;
|
|
3220
3329
|
setLaneState(run, {
|
|
3221
3330
|
workstreamId: selectedWorkstreamId,
|
|
3222
|
-
state:
|
|
3331
|
+
state: LaneState.IDLE,
|
|
3223
3332
|
activeRunId: null,
|
|
3224
3333
|
activeTaskIds: [],
|
|
3225
3334
|
blockedReason: null,
|
|
@@ -3327,7 +3436,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3327
3436
|
}
|
|
3328
3437
|
setLaneState(run, {
|
|
3329
3438
|
workstreamId: selectedWorkstreamId,
|
|
3330
|
-
state:
|
|
3439
|
+
state: LaneState.BLOCKED,
|
|
3331
3440
|
activeRunId: null,
|
|
3332
3441
|
activeTaskIds: [],
|
|
3333
3442
|
blockedReason,
|
|
@@ -3463,6 +3572,9 @@ export function createAutoContinueEngine(deps) {
|
|
|
3463
3572
|
catch {
|
|
3464
3573
|
// best effort
|
|
3465
3574
|
}
|
|
3575
|
+
// Session resume: check if a previous session exists for this workstream.
|
|
3576
|
+
const priorSession = sessionResumeEnabled() ? getWorkstreamSession(selectedWorkstreamId) : null;
|
|
3577
|
+
const resumedFromSessionId = priorSession?.sessionId ?? null;
|
|
3466
3578
|
const spawned = spawnCodexSliceWorker({
|
|
3467
3579
|
runId: sliceRunId,
|
|
3468
3580
|
prompt,
|
|
@@ -3470,6 +3582,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3470
3582
|
logPath,
|
|
3471
3583
|
outputPath,
|
|
3472
3584
|
outputSchemaPath: schemaPath,
|
|
3585
|
+
resumeSessionId: resumedFromSessionId,
|
|
3473
3586
|
env: {
|
|
3474
3587
|
ORGX_SOURCE_CLIENT: executorSourceClient,
|
|
3475
3588
|
ORGX_RUN_ID: sliceRunId,
|
|
@@ -3510,7 +3623,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3510
3623
|
behaviorAutomationLevel,
|
|
3511
3624
|
sourceClient: executorSourceClient,
|
|
3512
3625
|
pid: spawned.pid,
|
|
3513
|
-
status:
|
|
3626
|
+
status: RunStatus.RUNNING,
|
|
3514
3627
|
startedAt: now,
|
|
3515
3628
|
finishedAt: null,
|
|
3516
3629
|
updatedAt: now,
|
|
@@ -3523,6 +3636,8 @@ export function createAutoContinueEngine(deps) {
|
|
|
3523
3636
|
scopeMilestoneIds: scopeMilestoneIds,
|
|
3524
3637
|
lastError: null,
|
|
3525
3638
|
isMockWorker: workerKind === "mock",
|
|
3639
|
+
cliSessionId: null,
|
|
3640
|
+
resumedFromSessionId,
|
|
3526
3641
|
};
|
|
3527
3642
|
autoContinueSliceRuns.set(sliceRunId, slice);
|
|
3528
3643
|
try {
|
|
@@ -3626,7 +3741,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
3626
3741
|
run.activeTaskIds = dedupeStrings([...run.activeTaskIds, ...slice.taskIds]);
|
|
3627
3742
|
setLaneState(run, {
|
|
3628
3743
|
workstreamId: selectedWorkstreamId,
|
|
3629
|
-
state:
|
|
3744
|
+
state: LaneState.RUNNING,
|
|
3630
3745
|
activeRunId: sliceRunId,
|
|
3631
3746
|
activeTaskIds: slice.taskIds,
|
|
3632
3747
|
blockedReason: null,
|
|
@@ -3705,16 +3820,16 @@ export function createAutoContinueEngine(deps) {
|
|
|
3705
3820
|
}
|
|
3706
3821
|
const lane = run.laneByWorkstreamId[workstreamId] ?? null;
|
|
3707
3822
|
if (lane &&
|
|
3708
|
-
(lane.state ===
|
|
3709
|
-
lane.state ===
|
|
3710
|
-
lane.state ===
|
|
3711
|
-
lane.state ===
|
|
3823
|
+
(lane.state === LaneState.RUNNING ||
|
|
3824
|
+
lane.state === LaneState.BLOCKED ||
|
|
3825
|
+
lane.state === LaneState.WAITING_DEPENDENCY ||
|
|
3826
|
+
lane.state === LaneState.RATE_LIMITED)) {
|
|
3712
3827
|
return run;
|
|
3713
3828
|
}
|
|
3714
3829
|
if (Array.isArray(run.allowedWorkstreamIds) &&
|
|
3715
3830
|
run.allowedWorkstreamIds.length > 0 &&
|
|
3716
3831
|
run.allowedWorkstreamIds.includes(workstreamId) &&
|
|
3717
|
-
(run.status ===
|
|
3832
|
+
(run.status === RunStatus.RUNNING || run.status === RunStatus.STOPPING)) {
|
|
3718
3833
|
return run;
|
|
3719
3834
|
}
|
|
3720
3835
|
return null;
|
|
@@ -3798,13 +3913,13 @@ export function createAutoContinueEngine(deps) {
|
|
|
3798
3913
|
const existingRun = autoContinueRuns.get(initiativeId) ?? null;
|
|
3799
3914
|
if (existingRun &&
|
|
3800
3915
|
(existingRun.stopRequested ||
|
|
3801
|
-
existingRun.status ===
|
|
3916
|
+
existingRun.status === RunStatus.STOPPING ||
|
|
3802
3917
|
existingRun.stopReason === "stopped")) {
|
|
3803
3918
|
await emitSkip("paused_by_user");
|
|
3804
3919
|
return;
|
|
3805
3920
|
}
|
|
3806
3921
|
if (existingRun &&
|
|
3807
|
-
(existingRun.status ===
|
|
3922
|
+
(existingRun.status === RunStatus.RUNNING || existingRun.status === RunStatus.STOPPING) &&
|
|
3808
3923
|
listActiveSliceRunIds(existingRun).length > 0) {
|
|
3809
3924
|
const activeRunIds = listActiveSliceRunIds(existingRun);
|
|
3810
3925
|
await emitSkip("already_running", {
|
|
@@ -4017,7 +4132,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
4017
4132
|
async function startAutoContinueRun(input) {
|
|
4018
4133
|
const now = new Date().toISOString();
|
|
4019
4134
|
const existing = autoContinueRuns.get(input.initiativeId) ?? null;
|
|
4020
|
-
const existingIsLive = existing?.status ===
|
|
4135
|
+
const existingIsLive = existing?.status === RunStatus.RUNNING || existing?.status === RunStatus.STOPPING;
|
|
4021
4136
|
const run = existing ??
|
|
4022
4137
|
{
|
|
4023
4138
|
initiativeId: input.initiativeId,
|
|
@@ -4032,7 +4147,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
4032
4147
|
scope: "task",
|
|
4033
4148
|
tokenBudget: defaultAutoContinueTokenBudget(),
|
|
4034
4149
|
tokensUsed: 0,
|
|
4035
|
-
status:
|
|
4150
|
+
status: RunStatus.RUNNING,
|
|
4036
4151
|
stopReason: null,
|
|
4037
4152
|
stopRequested: false,
|
|
4038
4153
|
startedAt: now,
|
|
@@ -4075,7 +4190,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
4075
4190
|
? normalizeTokenBudget(run.tokenBudget, defaultAutoContinueTokenBudget())
|
|
4076
4191
|
: defaultAutoContinueTokenBudget();
|
|
4077
4192
|
}
|
|
4078
|
-
run.status =
|
|
4193
|
+
run.status = RunStatus.RUNNING;
|
|
4079
4194
|
run.stopReason = null;
|
|
4080
4195
|
run.stopRequested = false;
|
|
4081
4196
|
run.stoppedAt = null;
|
|
@@ -4094,6 +4209,7 @@ export function createAutoContinueEngine(deps) {
|
|
|
4094
4209
|
run.activeTaskId = null;
|
|
4095
4210
|
run.activeRunId = null;
|
|
4096
4211
|
run.activeTaskTokenEstimate = null;
|
|
4212
|
+
clearWorkstreamSession(input.initiativeId);
|
|
4097
4213
|
}
|
|
4098
4214
|
syncLegacyRunPointers(run);
|
|
4099
4215
|
autoContinueRuns.set(input.initiativeId, run);
|
|
@@ -4157,8 +4273,8 @@ export function createAutoContinueEngine(deps) {
|
|
|
4157
4273
|
event: "autopilot_transition",
|
|
4158
4274
|
actionType: "run_state_transition",
|
|
4159
4275
|
}),
|
|
4160
|
-
old_state:
|
|
4161
|
-
new_state:
|
|
4276
|
+
old_state: LaneState.IDLE,
|
|
4277
|
+
new_state: LaneState.RUNNING,
|
|
4162
4278
|
reason: "started",
|
|
4163
4279
|
workspace_id: run.allowedWorkstreamIds?.[0] ?? null,
|
|
4164
4280
|
},
|
|
@@ -4191,5 +4307,12 @@ export function createAutoContinueEngine(deps) {
|
|
|
4191
4307
|
getAutoContinueLaneForWorkstream,
|
|
4192
4308
|
scheduleAutoFixForWorkstream,
|
|
4193
4309
|
startAutoContinueRun,
|
|
4310
|
+
// Session store (for resume support)
|
|
4311
|
+
workstreamSessionStore,
|
|
4312
|
+
getWorkstreamSession,
|
|
4313
|
+
setWorkstreamSession,
|
|
4314
|
+
clearWorkstreamSession,
|
|
4315
|
+
listWorkstreamSessions,
|
|
4316
|
+
sessionResumeEnabled,
|
|
4194
4317
|
};
|
|
4195
4318
|
}
|