@ryan_nookpi/pi-extension-subagent 0.5.6 → 0.5.7
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 +3 -3
- package/cli.ts +9 -2
- package/package.json +1 -1
- package/run-utils.ts +3 -3
- package/tool-execute.ts +102 -44
- package/types.ts +4 -1
package/README.md
CHANGED
|
@@ -98,9 +98,9 @@ subagent run <agent> [--main|--isolated] -- <task>
|
|
|
98
98
|
subagent continue <runId> [--agent <agent>] [--main|--isolated] -- <task>
|
|
99
99
|
subagent batch [--main|--isolated] --agent <agent> --task <task> ...
|
|
100
100
|
subagent chain [--main|--isolated] --agent <agent> --task <task> ...
|
|
101
|
-
subagent status <runId>
|
|
102
|
-
subagent detail <runId>
|
|
103
|
-
subagent abort <runId|runId,runId|all>
|
|
101
|
+
subagent status <runId|groupId>
|
|
102
|
+
subagent detail <runId|groupId>
|
|
103
|
+
subagent abort <runId|groupId|runId,runId|all>
|
|
104
104
|
subagent remove <runId|runId,runId|all>
|
|
105
105
|
```
|
|
106
106
|
|
package/cli.ts
CHANGED
|
@@ -64,7 +64,7 @@ export const SUBAGENT_CLI_HELP_TEXT = [
|
|
|
64
64
|
" subagent chain [--main|--isolated] --agent <agent> --task <task> --agent <agent> --task <task> ...",
|
|
65
65
|
"",
|
|
66
66
|
" Cleanup:",
|
|
67
|
-
" subagent abort <runId|runId,runId|all>",
|
|
67
|
+
" subagent abort <runId|groupId|runId,runId|all>",
|
|
68
68
|
" subagent remove <runId|runId,runId|all>",
|
|
69
69
|
"",
|
|
70
70
|
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
|
@@ -88,6 +88,7 @@ export const SUBAGENT_CLI_HELP_TEXT = [
|
|
|
88
88
|
" subagent status 22",
|
|
89
89
|
" subagent detail 22",
|
|
90
90
|
" subagent abort 22",
|
|
91
|
+
" subagent abort p_1712...",
|
|
91
92
|
" subagent remove all",
|
|
92
93
|
"",
|
|
93
94
|
"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━",
|
|
@@ -508,8 +509,14 @@ export function parseSubagentToolCommand(
|
|
|
508
509
|
if (!target)
|
|
509
510
|
return {
|
|
510
511
|
type: "error",
|
|
511
|
-
message:
|
|
512
|
+
message:
|
|
513
|
+
verb === "abort"
|
|
514
|
+
? "❌ abort requires <runId|groupId|runId,runId|all>\n\n✓ Examples:\n subagent abort 22\n subagent abort p_1712_abcd\n subagent abort 22,23,24\n subagent abort all"
|
|
515
|
+
: "❌ remove requires <runId|runId,runId|all>\n\n✓ Examples:\n subagent remove 22\n subagent remove 22,23,24\n subagent remove all",
|
|
512
516
|
};
|
|
517
|
+
if (verb === "abort" && isGroupId(target)) {
|
|
518
|
+
return { type: "params", params: { asyncAction: "abort", groupId: target } };
|
|
519
|
+
}
|
|
513
520
|
const parsedTarget = parseRunTarget(target, options.knownRunIds);
|
|
514
521
|
if ("error" in parsedTarget)
|
|
515
522
|
return {
|
package/package.json
CHANGED
package/run-utils.ts
CHANGED
|
@@ -242,18 +242,18 @@ export function snapshotBatchGroup(
|
|
|
242
242
|
let failed = 0;
|
|
243
243
|
let aborted = 0;
|
|
244
244
|
const members: FinishedGroupMember[] = batch.runIds.map((runId) => {
|
|
245
|
-
const run = store.commandRuns.get(runId);
|
|
245
|
+
const run = batch.completedRuns.get(runId) ?? store.commandRuns.get(runId);
|
|
246
246
|
if (!run) {
|
|
247
247
|
if (batch.abortedRunIds.has(runId)) aborted++;
|
|
248
248
|
else if (batch.failedRunIds.has(runId)) failed++;
|
|
249
249
|
return {
|
|
250
250
|
summaryLine: `#${runId} [gone] (run no longer available)`,
|
|
251
|
-
output:
|
|
251
|
+
output: "(no output)",
|
|
252
252
|
};
|
|
253
253
|
}
|
|
254
254
|
if (run.errorClass === "aborted" || batch.abortedRunIds.has(runId)) aborted++;
|
|
255
255
|
else if (run.status === "error" || batch.failedRunIds.has(runId)) failed++;
|
|
256
|
-
return { summaryLine: formatCommandRunSummary(run), output: memberOutput(run
|
|
256
|
+
return { summaryLine: formatCommandRunSummary(run), output: memberOutput(run) };
|
|
257
257
|
});
|
|
258
258
|
return {
|
|
259
259
|
groupId: batch.batchId,
|
package/tool-execute.ts
CHANGED
|
@@ -502,7 +502,13 @@ function recordBatchResult(batch: BatchGroupState, finalized: FinalizedRun): voi
|
|
|
502
502
|
batch.completedRunIds.add(runId);
|
|
503
503
|
if (status === "aborted") batch.abortedRunIds.add(runId);
|
|
504
504
|
else if (status === "error") batch.failedRunIds.add(runId);
|
|
505
|
-
batch.
|
|
505
|
+
batch.completedRuns.set(runId, { ...finalized.runState, abortController: undefined });
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function getCompletedBatchRuns(batch: BatchGroupState): CommandRunState[] {
|
|
509
|
+
return batch.runIds
|
|
510
|
+
.map((runId) => batch.completedRuns.get(runId))
|
|
511
|
+
.filter((run): run is CommandRunState => Boolean(run));
|
|
506
512
|
}
|
|
507
513
|
|
|
508
514
|
function buildRunCompletionMessage(finalized: FinalizedRun, options?: { display?: boolean }) {
|
|
@@ -1040,6 +1046,45 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1040
1046
|
};
|
|
1041
1047
|
}
|
|
1042
1048
|
|
|
1049
|
+
let abortGroupTarget: { groupId: string; kind: "batch" | "chain" } | undefined;
|
|
1050
|
+
if (asyncAction === "abort" && typeof cmdParams.groupId === "string") {
|
|
1051
|
+
evictStaleFinishedGroups(store);
|
|
1052
|
+
const groupId = cmdParams.groupId;
|
|
1053
|
+
const finished = store.finishedGroups.get(groupId);
|
|
1054
|
+
if (finished) {
|
|
1055
|
+
return {
|
|
1056
|
+
content: [{ type: "text", text: `Subagent ${finished.kind} ${groupId} has already finished.` }],
|
|
1057
|
+
details: makeDetails("single"),
|
|
1058
|
+
};
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
const batch = store.batchGroups.get(groupId);
|
|
1062
|
+
const pipeline = store.pipelines.get(groupId);
|
|
1063
|
+
if (!batch && !pipeline) {
|
|
1064
|
+
return {
|
|
1065
|
+
content: [{ type: "text", text: `Unknown subagent group "${groupId}".` }],
|
|
1066
|
+
details: makeDetails("single"),
|
|
1067
|
+
isError: true,
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
abortGroupTarget = { groupId, kind: batch ? "batch" : "chain" };
|
|
1072
|
+
if (pipeline) pipeline.abortRequested = true;
|
|
1073
|
+
const groupRunIds = (batch?.runIds ?? pipeline?.stepRunIds ?? []).filter((runId) => {
|
|
1074
|
+
const run = store.globalLiveRuns.get(runId)?.runState ?? store.commandRuns.get(runId);
|
|
1075
|
+
return batch ? run?.batchId === groupId : run?.pipelineId === groupId;
|
|
1076
|
+
});
|
|
1077
|
+
if (groupRunIds.length === 0) {
|
|
1078
|
+
return {
|
|
1079
|
+
content: [
|
|
1080
|
+
{ type: "text", text: `Subagent ${abortGroupTarget.kind} ${groupId} has no started runs to abort.` },
|
|
1081
|
+
],
|
|
1082
|
+
details: makeDetails("single"),
|
|
1083
|
+
};
|
|
1084
|
+
}
|
|
1085
|
+
cmdParams.runIds = groupRunIds;
|
|
1086
|
+
}
|
|
1087
|
+
|
|
1043
1088
|
if ((asyncAction === "status" || asyncAction === "detail") && typeof cmdParams.groupId === "string") {
|
|
1044
1089
|
evictStaleFinishedGroups(store);
|
|
1045
1090
|
const groupId = cmdParams.groupId;
|
|
@@ -1178,7 +1223,9 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1178
1223
|
const unknown: number[] = [];
|
|
1179
1224
|
|
|
1180
1225
|
for (const runId of targetRunIds) {
|
|
1181
|
-
const run =
|
|
1226
|
+
const run = abortGroupTarget
|
|
1227
|
+
? (store.globalLiveRuns.get(runId)?.runState ?? store.commandRuns.get(runId))
|
|
1228
|
+
: store.commandRuns.get(runId);
|
|
1182
1229
|
if (!run) {
|
|
1183
1230
|
unknown.push(runId);
|
|
1184
1231
|
continue;
|
|
@@ -1200,7 +1247,13 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1200
1247
|
updateCommandRunsWidget(store, ctx as WidgetRenderCtx);
|
|
1201
1248
|
}
|
|
1202
1249
|
|
|
1203
|
-
if (
|
|
1250
|
+
if (
|
|
1251
|
+
!abortGroupTarget &&
|
|
1252
|
+
targetRunIds.length === 1 &&
|
|
1253
|
+
aborting.length === 1 &&
|
|
1254
|
+
notRunning.length === 0 &&
|
|
1255
|
+
unknown.length === 0
|
|
1256
|
+
) {
|
|
1204
1257
|
return {
|
|
1205
1258
|
content: [{ type: "text", text: `Aborting subagent run #${aborting[0]}...` }],
|
|
1206
1259
|
details: makeDetails("single"),
|
|
@@ -1208,6 +1261,9 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1208
1261
|
}
|
|
1209
1262
|
|
|
1210
1263
|
const lines: string[] = [];
|
|
1264
|
+
if (abortGroupTarget) {
|
|
1265
|
+
lines.push(`Subagent ${abortGroupTarget.kind} ${abortGroupTarget.groupId}:`);
|
|
1266
|
+
}
|
|
1211
1267
|
if (aborting.length > 0) lines.push(`Aborting: ${aborting.map((id) => `#${id}`).join(", ")}.`);
|
|
1212
1268
|
if (notRunning.length > 0) lines.push(`Not running: ${notRunning.map((id) => `#${id}`).join(", ")}.`);
|
|
1213
1269
|
if (unknown.length > 0) lines.push(`Unknown: ${unknown.map((id) => `#${id}`).join(", ")}.`);
|
|
@@ -1413,6 +1469,13 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1413
1469
|
store.recentLaunchTimestamps.delete(runId);
|
|
1414
1470
|
}
|
|
1415
1471
|
|
|
1472
|
+
function cleanupGroupRunAfterFinalDelivery(runId: number, groupId: string, kind: "batch" | "chain") {
|
|
1473
|
+
const run = store.globalLiveRuns.get(runId)?.runState ?? store.commandRuns.get(runId);
|
|
1474
|
+
const ownsGroup = kind === "batch" ? run?.batchId === groupId : run?.pipelineId === groupId;
|
|
1475
|
+
if (run && !ownsGroup) return;
|
|
1476
|
+
cleanupRunAfterFinalDelivery(runId);
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1416
1479
|
function launchRunInBackground(runState: CommandRunState, taskForAgent: string): Promise<FinalizedRun> {
|
|
1417
1480
|
let claudeCheckpointSent = !!runState.claudeSessionId;
|
|
1418
1481
|
const abortSignal = runState.abortController?.signal;
|
|
@@ -1734,7 +1797,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1734
1797
|
abortedRunIds: new Set(),
|
|
1735
1798
|
originSessionFile,
|
|
1736
1799
|
createdAt: Date.now(),
|
|
1737
|
-
|
|
1800
|
+
completedRuns: new Map(),
|
|
1738
1801
|
});
|
|
1739
1802
|
updateCommandRunsWidget(store, ctx as WidgetRenderCtx);
|
|
1740
1803
|
|
|
@@ -1750,11 +1813,13 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1750
1813
|
}
|
|
1751
1814
|
}),
|
|
1752
1815
|
);
|
|
1753
|
-
const orderedRuns = runStates.map(({ runState }) => runState);
|
|
1754
1816
|
const batchForSnapshot = store.batchGroups.get(batchId);
|
|
1755
1817
|
if (batchForSnapshot) {
|
|
1756
1818
|
for (const finalized of finalizedRuns) recordBatchResult(batchForSnapshot, finalized);
|
|
1757
1819
|
}
|
|
1820
|
+
const orderedRuns = batchForSnapshot
|
|
1821
|
+
? getCompletedBatchRuns(batchForSnapshot)
|
|
1822
|
+
: runStates.map(({ runState }) => runState);
|
|
1758
1823
|
const terminalStatus = resolveGroupTerminalStatus(
|
|
1759
1824
|
batchForSnapshot?.failedRunIds.size ?? 0,
|
|
1760
1825
|
batchForSnapshot?.abortedRunIds.size ?? 0,
|
|
@@ -1763,7 +1828,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1763
1828
|
if (batchForSnapshot) {
|
|
1764
1829
|
retireFinishedGroup(store, snapshotBatchGroup(store, batchForSnapshot, terminalStatus));
|
|
1765
1830
|
}
|
|
1766
|
-
for (const { runState } of runStates)
|
|
1831
|
+
for (const { runState } of runStates) cleanupGroupRunAfterFinalDelivery(runState.id, batchId, "batch");
|
|
1767
1832
|
clearPendingGroupCompletion("batch", batchId);
|
|
1768
1833
|
store.batchGroups.delete(batchId);
|
|
1769
1834
|
trimCommandRunHistory(store, {
|
|
@@ -1799,9 +1864,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1799
1864
|
updateCommandRunsWidget(store);
|
|
1800
1865
|
|
|
1801
1866
|
if (batch.completedRunIds.size === batch.runIds.length) {
|
|
1802
|
-
const orderedRuns = batch
|
|
1803
|
-
.map((runId) => store.commandRuns.get(runId))
|
|
1804
|
-
.filter((run): run is CommandRunState => Boolean(run));
|
|
1867
|
+
const orderedRuns = getCompletedBatchRuns(batch);
|
|
1805
1868
|
const batchTerminalStatus = resolveGroupTerminalStatus(batch.failedRunIds.size, batch.abortedRunIds.size);
|
|
1806
1869
|
const content = formatBatchSummary(batchId, orderedRuns, batchTerminalStatus);
|
|
1807
1870
|
const message = {
|
|
@@ -1819,7 +1882,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1819
1882
|
if (isInOriginSession(ctx, batch.originSessionFile)) {
|
|
1820
1883
|
pi.sendMessage(message, { deliverAs: "followUp", triggerTurn: true });
|
|
1821
1884
|
clearPendingGroupCompletion("batch", batchId);
|
|
1822
|
-
for (const runId of batch.runIds)
|
|
1885
|
+
for (const runId of batch.runIds) cleanupGroupRunAfterFinalDelivery(runId, batchId, "batch");
|
|
1823
1886
|
store.batchGroups.delete(batchId);
|
|
1824
1887
|
} else {
|
|
1825
1888
|
batch.pendingCompletion = makePendingCompletion(message, true);
|
|
@@ -1853,9 +1916,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1853
1916
|
if (!batch) return;
|
|
1854
1917
|
recordBatchResult(batch, finalized);
|
|
1855
1918
|
if (batch.completedRunIds.size === batch.runIds.length) {
|
|
1856
|
-
const orderedRuns = batch
|
|
1857
|
-
.map((runId) => store.commandRuns.get(runId))
|
|
1858
|
-
.filter((run): run is CommandRunState => Boolean(run));
|
|
1919
|
+
const orderedRuns = getCompletedBatchRuns(batch);
|
|
1859
1920
|
const batchTerminalStatus = resolveGroupTerminalStatus(batch.failedRunIds.size, batch.abortedRunIds.size);
|
|
1860
1921
|
const message = {
|
|
1861
1922
|
customType: "subagent-tool" as const,
|
|
@@ -1872,7 +1933,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1872
1933
|
if (isInOriginSession(ctx, batch.originSessionFile)) {
|
|
1873
1934
|
pi.sendMessage(message, { deliverAs: "followUp", triggerTurn: true });
|
|
1874
1935
|
clearPendingGroupCompletion("batch", batchId);
|
|
1875
|
-
for (const runId of batch.runIds)
|
|
1936
|
+
for (const runId of batch.runIds) cleanupGroupRunAfterFinalDelivery(runId, batchId, "batch");
|
|
1876
1937
|
store.batchGroups.delete(batchId);
|
|
1877
1938
|
} else {
|
|
1878
1939
|
batch.pendingCompletion = makePendingCompletion(message, true);
|
|
@@ -1931,6 +1992,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1931
1992
|
store.pipelines.set(pipelineId, {
|
|
1932
1993
|
pipelineId,
|
|
1933
1994
|
currentIndex: 0,
|
|
1995
|
+
abortRequested: false,
|
|
1934
1996
|
stepRunIds: [],
|
|
1935
1997
|
stepResults: [],
|
|
1936
1998
|
originSessionFile,
|
|
@@ -1952,6 +2014,10 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
1952
2014
|
|
|
1953
2015
|
try {
|
|
1954
2016
|
for (let index = 0; index < steps.length; index++) {
|
|
2017
|
+
if (pipeline.abortRequested) {
|
|
2018
|
+
terminalStatus = "aborted";
|
|
2019
|
+
break;
|
|
2020
|
+
}
|
|
1955
2021
|
pipeline.currentIndex = index;
|
|
1956
2022
|
const step = steps[index];
|
|
1957
2023
|
const pipelineReferenceSection =
|
|
@@ -2005,26 +2071,20 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
2005
2071
|
}
|
|
2006
2072
|
finalizedRuns.push(finalized);
|
|
2007
2073
|
|
|
2008
|
-
|
|
2009
|
-
terminalStatus = "aborted";
|
|
2010
|
-
pipeline.stepResults.push({
|
|
2011
|
-
runId: runState.id,
|
|
2012
|
-
agent: runState.agent,
|
|
2013
|
-
task: step.task,
|
|
2014
|
-
output: finalized.rawOutput || "Run removed before pipeline completion.",
|
|
2015
|
-
status: "aborted",
|
|
2016
|
-
});
|
|
2017
|
-
break;
|
|
2018
|
-
}
|
|
2019
|
-
|
|
2020
|
-
const stepStatus = getFinalizedRunStatus(finalized);
|
|
2074
|
+
const stepStatus = runState.removed ? "aborted" : getFinalizedRunStatus(finalized);
|
|
2021
2075
|
pipeline.stepResults.push({
|
|
2022
2076
|
runId: runState.id,
|
|
2023
2077
|
agent: runState.agent,
|
|
2024
2078
|
task: step.task,
|
|
2025
|
-
output:
|
|
2079
|
+
output: runState.removed
|
|
2080
|
+
? finalized.rawOutput || "Run removed before pipeline completion."
|
|
2081
|
+
: finalized.rawOutput,
|
|
2026
2082
|
status: stepStatus,
|
|
2027
2083
|
});
|
|
2084
|
+
if (runState.removed || pipeline.abortRequested) {
|
|
2085
|
+
terminalStatus = "aborted";
|
|
2086
|
+
break;
|
|
2087
|
+
}
|
|
2028
2088
|
previousOutput = finalized.rawOutput;
|
|
2029
2089
|
updateCommandRunsWidget(store);
|
|
2030
2090
|
|
|
@@ -2050,7 +2110,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
2050
2110
|
else if (terminalStatus === "completed" && hasAborted) terminalStatus = "aborted";
|
|
2051
2111
|
const content = formatPipelineSummary(pipelineId, pipeline.stepResults, terminalStatus);
|
|
2052
2112
|
retireFinishedGroup(store, snapshotPipeline(pipeline, terminalStatus));
|
|
2053
|
-
for (const runId of pipeline.stepRunIds)
|
|
2113
|
+
for (const runId of pipeline.stepRunIds) cleanupGroupRunAfterFinalDelivery(runId, pipelineId, "chain");
|
|
2054
2114
|
clearPendingGroupCompletion("chain", pipelineId);
|
|
2055
2115
|
store.pipelines.delete(pipelineId);
|
|
2056
2116
|
trimCommandRunHistory(store, {
|
|
@@ -2082,6 +2142,10 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
2082
2142
|
for (let index = 0; index < steps.length; index++) {
|
|
2083
2143
|
const pipeline = store.pipelines.get(pipelineId);
|
|
2084
2144
|
if (!pipeline) return;
|
|
2145
|
+
if (pipeline.abortRequested) {
|
|
2146
|
+
terminalStatus = "aborted";
|
|
2147
|
+
break;
|
|
2148
|
+
}
|
|
2085
2149
|
pipeline.currentIndex = index;
|
|
2086
2150
|
|
|
2087
2151
|
const step = steps[index];
|
|
@@ -2134,26 +2198,20 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
2134
2198
|
} finally {
|
|
2135
2199
|
clearRunAbortState(runState);
|
|
2136
2200
|
}
|
|
2137
|
-
if (runState.removed) {
|
|
2138
|
-
terminalStatus = "aborted";
|
|
2139
|
-
pipeline.stepResults.push({
|
|
2140
|
-
runId: runState.id,
|
|
2141
|
-
agent: runState.agent,
|
|
2142
|
-
task: step.task,
|
|
2143
|
-
output: finalized.rawOutput || "Run removed before pipeline completion.",
|
|
2144
|
-
status: "aborted",
|
|
2145
|
-
});
|
|
2146
|
-
break;
|
|
2147
|
-
}
|
|
2148
|
-
|
|
2149
2201
|
const stepResult: PipelineStepResult = {
|
|
2150
2202
|
runId: runState.id,
|
|
2151
2203
|
agent: runState.agent,
|
|
2152
2204
|
task: step.task,
|
|
2153
|
-
output:
|
|
2154
|
-
|
|
2205
|
+
output: runState.removed
|
|
2206
|
+
? finalized.rawOutput || "Run removed before pipeline completion."
|
|
2207
|
+
: finalized.rawOutput,
|
|
2208
|
+
status: runState.removed ? "aborted" : getFinalizedRunStatus(finalized),
|
|
2155
2209
|
};
|
|
2156
2210
|
pipeline.stepResults.push(stepResult);
|
|
2211
|
+
if (runState.removed || pipeline.abortRequested) {
|
|
2212
|
+
terminalStatus = "aborted";
|
|
2213
|
+
break;
|
|
2214
|
+
}
|
|
2157
2215
|
previousOutput = finalized.rawOutput;
|
|
2158
2216
|
updateCommandRunsWidget(store);
|
|
2159
2217
|
|
|
@@ -2199,7 +2257,7 @@ export function createSubagentToolExecute(pi: ExtensionAPI, store: SubagentStore
|
|
|
2199
2257
|
if (isInOriginSession(ctx, pipeline.originSessionFile)) {
|
|
2200
2258
|
pi.sendMessage(message, { deliverAs: "followUp", triggerTurn: true });
|
|
2201
2259
|
clearPendingGroupCompletion("chain", pipelineId);
|
|
2202
|
-
for (const runId of pipeline.stepRunIds)
|
|
2260
|
+
for (const runId of pipeline.stepRunIds) cleanupGroupRunAfterFinalDelivery(runId, pipelineId, "chain");
|
|
2203
2261
|
store.pipelines.delete(pipelineId);
|
|
2204
2262
|
} else {
|
|
2205
2263
|
pipeline.pendingCompletion = makePendingCompletion(message, true);
|
package/types.ts
CHANGED
|
@@ -177,7 +177,8 @@ export interface BatchGroupState {
|
|
|
177
177
|
abortedRunIds: Set<number>;
|
|
178
178
|
originSessionFile: string;
|
|
179
179
|
createdAt: number;
|
|
180
|
-
|
|
180
|
+
/** Immutable member states captured as each batch run completes. */
|
|
181
|
+
completedRuns: Map<number, CommandRunState>;
|
|
181
182
|
pendingCompletion?: PendingCompletion;
|
|
182
183
|
}
|
|
183
184
|
|
|
@@ -192,6 +193,8 @@ export interface PipelineStepResult {
|
|
|
192
193
|
export interface PipelineState {
|
|
193
194
|
pipelineId: string;
|
|
194
195
|
currentIndex: number;
|
|
196
|
+
/** Set by `abort <pipelineId>` to prevent any subsequent step from launching. */
|
|
197
|
+
abortRequested: boolean;
|
|
195
198
|
stepRunIds: number[];
|
|
196
199
|
stepResults: PipelineStepResult[];
|
|
197
200
|
originSessionFile: string;
|