@bastani/atomic 0.8.26-alpha.4 → 0.8.26-alpha.6
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/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/mcp/CHANGELOG.md +12 -0
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +12 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +48 -10
- package/dist/builtin/subagents/src/runs/foreground/execution.ts +30 -9
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +34 -0
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +416 -7
- package/dist/builtin/web-access/CHANGELOG.md +12 -0
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +12 -0
- package/dist/builtin/workflows/builtin/deep-research-codebase.ts +6 -6
- package/dist/builtin/workflows/builtin/goal.ts +10 -10
- package/dist/builtin/workflows/builtin/open-claude-design.ts +4 -4
- package/dist/builtin/workflows/builtin/ralph.ts +16 -16
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/extension/index.ts +10 -2
- package/dist/builtin/workflows/src/extension/runtime.ts +35 -3
- package/dist/builtin/workflows/src/runs/background/status.ts +52 -6
- package/dist/builtin/workflows/src/runs/foreground/executor.ts +441 -15
- package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +69 -8
- package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +402 -8
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +182 -6
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +76 -6
- package/dist/builtin/workflows/src/shared/stage-prompt.ts +33 -2
- package/dist/builtin/workflows/src/shared/store-types.ts +31 -0
- package/dist/builtin/workflows/src/shared/store.ts +99 -11
- package/dist/builtin/workflows/src/shared/workflow-failures.ts +758 -132
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +74 -74
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/format-answer.js +5 -5
- package/dist/core/tools/ask-user-question/tool/format-answer.js.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts +16 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.d.ts.map +1 -1
- package/dist/core/tools/ask-user-question/tool/response-envelope.js +21 -3
- package/dist/core/tools/ask-user-question/tool/response-envelope.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.26-alpha.6] - 2026-06-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Bumped package version for the Atomic 0.8.26-alpha.6 prerelease.
|
|
10
|
+
|
|
11
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
16
|
+
|
|
5
17
|
## [0.8.26-alpha.4] - 2026-06-05
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -4,6 +4,18 @@ All notable changes to the `pi-intercom` extension will be documented in this fi
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.8.26-alpha.6] - 2026-06-06
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
|
|
11
|
+
- Bumped package version for the Atomic 0.8.26-alpha.6 prerelease.
|
|
12
|
+
|
|
13
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
18
|
+
|
|
7
19
|
## [0.8.26-alpha.4] - 2026-06-05
|
|
8
20
|
|
|
9
21
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/intercom",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.6",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension providing a private coordination channel between parent and child agent sessions. Fork of: https://github.com/nicobailon/pi-intercom",
|
|
6
6
|
"contributors": [
|
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.8.26-alpha.6] - 2026-06-06
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Bumped package version for the Atomic 0.8.26-alpha.6 prerelease.
|
|
15
|
+
|
|
16
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
17
|
+
|
|
18
|
+
### Changed
|
|
19
|
+
|
|
20
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
21
|
+
|
|
10
22
|
## [0.8.26-alpha.4] - 2026-06-05
|
|
11
23
|
|
|
12
24
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/mcp",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.6",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension that adapts MCP (Model Context Protocol) servers into the coding agent. Fork of: https://github.com/nicobailon/pi-mcp-adapter",
|
|
6
6
|
"contributors": [
|
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.8.26-alpha.6] - 2026-06-06
|
|
6
|
+
|
|
7
|
+
### Changed
|
|
8
|
+
|
|
9
|
+
- Bumped package version for the Atomic 0.8.26-alpha.6 prerelease.
|
|
10
|
+
|
|
11
|
+
## [0.8.26-alpha.5] - 2026-06-06
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
|
|
15
|
+
- Bumped package version for the Atomic 0.8.26-alpha.5 prerelease.
|
|
16
|
+
|
|
5
17
|
## [0.8.26-alpha.4] - 2026-06-05
|
|
6
18
|
|
|
7
19
|
### Changed
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.8.26-alpha.
|
|
3
|
+
"version": "0.8.26-alpha.6",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with chains, parallel execution, and TUI clarification. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -48,7 +48,12 @@ import { outputEntryFromAsyncResult, resolveOutputReferences } from "../shared/c
|
|
|
48
48
|
import { createStructuredOutputRuntime, readStructuredOutput } from "../shared/structured-output.ts";
|
|
49
49
|
import { collectDynamicResults, DynamicFanoutError, materializeDynamicParallelStep, validateDynamicCollection } from "../shared/dynamic-fanout.ts";
|
|
50
50
|
import { nestedSummaryFromAsyncStatus, writeNestedEvent } from "../shared/nested-events.ts";
|
|
51
|
-
import { formatModelAttemptNote, isRetryableModelFailure } from "../shared/model-fallback.ts";
|
|
51
|
+
import { formatModelAttemptNote, isRetryableModelFailure, modelFailureMessage } from "../shared/model-fallback.ts";
|
|
52
|
+
import {
|
|
53
|
+
assistantStopReason,
|
|
54
|
+
isAssistantFailureStopReason,
|
|
55
|
+
shouldStartSubagentFinalDrain,
|
|
56
|
+
} from "../shared/final-drain.ts";
|
|
52
57
|
import { attachPostExitStdioGuard, trySignalChild } from "../../shared/post-exit-stdio-guard.ts";
|
|
53
58
|
import { detectSubagentError, extractTextFromContent, extractToolArgsPreview, getFinalOutput } from "../../shared/utils.ts";
|
|
54
59
|
import { evaluateCompletionMutationGuard } from "../shared/completion-guard.ts";
|
|
@@ -230,6 +235,7 @@ interface RunPiStreamingResult {
|
|
|
230
235
|
finalOutput: string;
|
|
231
236
|
interrupted?: boolean;
|
|
232
237
|
observedMutationAttempt?: boolean;
|
|
238
|
+
modelFailureSignal?: unknown;
|
|
233
239
|
}
|
|
234
240
|
|
|
235
241
|
function runPiStreaming(
|
|
@@ -270,6 +276,7 @@ function runPiStreaming(
|
|
|
270
276
|
let model: string | undefined;
|
|
271
277
|
let error: string | undefined;
|
|
272
278
|
let assistantError: string | undefined;
|
|
279
|
+
let assistantFailureSignal: unknown;
|
|
273
280
|
let interrupted = false;
|
|
274
281
|
let observedMutationAttempt = false;
|
|
275
282
|
const rawStdoutLines: string[] = [];
|
|
@@ -330,7 +337,6 @@ function runPiStreaming(
|
|
|
330
337
|
|
|
331
338
|
if (event.type !== "message_end" || event.message.role !== "assistant") return;
|
|
332
339
|
if (event.message.model) model = event.message.model;
|
|
333
|
-
if (event.message.errorMessage) assistantError = event.message.errorMessage;
|
|
334
340
|
const eventUsage = event.message.usage;
|
|
335
341
|
if (eventUsage) {
|
|
336
342
|
usage.turns++;
|
|
@@ -340,12 +346,21 @@ function runPiStreaming(
|
|
|
340
346
|
usage.cacheWrite += eventUsage.cacheWrite ?? 0;
|
|
341
347
|
usage.cost += eventUsage.cost?.total ?? 0;
|
|
342
348
|
}
|
|
343
|
-
const stopReason = (event.message
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
+
const stopReason = assistantStopReason(event.message);
|
|
350
|
+
if (event.message.errorMessage) {
|
|
351
|
+
assistantError = event.message.errorMessage;
|
|
352
|
+
assistantFailureSignal = event.message;
|
|
353
|
+
}
|
|
354
|
+
if (isAssistantFailureStopReason(stopReason)) {
|
|
355
|
+
assistantError = modelFailureMessage(event.message);
|
|
356
|
+
assistantFailureSignal = event.message;
|
|
357
|
+
}
|
|
358
|
+
if (shouldStartSubagentFinalDrain(event.message)) {
|
|
359
|
+
if (extractTextFromContent(event.message.content).trim()) {
|
|
360
|
+
assistantError = undefined;
|
|
361
|
+
assistantFailureSignal = undefined;
|
|
362
|
+
}
|
|
363
|
+
cleanTerminalAssistantStopReceived = true;
|
|
349
364
|
startFinalDrain();
|
|
350
365
|
}
|
|
351
366
|
}
|
|
@@ -448,6 +463,9 @@ function runPiStreaming(
|
|
|
448
463
|
finalOutput,
|
|
449
464
|
interrupted,
|
|
450
465
|
observedMutationAttempt,
|
|
466
|
+
...(assistantFailureSignal !== undefined && finalError === assistantError
|
|
467
|
+
? { modelFailureSignal: assistantFailureSignal }
|
|
468
|
+
: {}),
|
|
451
469
|
});
|
|
452
470
|
});
|
|
453
471
|
|
|
@@ -459,7 +477,20 @@ function runPiStreaming(
|
|
|
459
477
|
outputStream.end();
|
|
460
478
|
const finalOutput = getFinalOutput(messages) || rawStdoutLines.join("\n").trim();
|
|
461
479
|
const spawnErrorMessage = spawnError instanceof Error ? spawnError.message : String(spawnError);
|
|
462
|
-
|
|
480
|
+
const finalError = error ?? assistantError ?? spawnErrorMessage;
|
|
481
|
+
resolve({
|
|
482
|
+
stderr,
|
|
483
|
+
exitCode: 1,
|
|
484
|
+
messages,
|
|
485
|
+
usage,
|
|
486
|
+
model,
|
|
487
|
+
error: finalError,
|
|
488
|
+
finalOutput,
|
|
489
|
+
observedMutationAttempt,
|
|
490
|
+
...(assistantFailureSignal !== undefined && finalError === assistantError
|
|
491
|
+
? { modelFailureSignal: assistantFailureSignal }
|
|
492
|
+
: {}),
|
|
493
|
+
});
|
|
463
494
|
});
|
|
464
495
|
});
|
|
465
496
|
}
|
|
@@ -770,7 +801,14 @@ async function runSingleStep(
|
|
|
770
801
|
finalOutputSnapshot = outputSnapshot;
|
|
771
802
|
finalResult = { ...run, exitCode: effectiveExitCode, model: candidate ?? run.model, error, structuredOutput } as RunPiStreamingResult & { structuredOutput?: unknown };
|
|
772
803
|
if (attempt.success) break;
|
|
773
|
-
|
|
804
|
+
const retrySignal = run.modelFailureSignal ?? error;
|
|
805
|
+
if (
|
|
806
|
+
!completionGuardTriggered
|
|
807
|
+
&& structuredError === undefined
|
|
808
|
+
&& hiddenError?.hasError !== true
|
|
809
|
+
&& isRetryableModelFailure(retrySignal)
|
|
810
|
+
&& index < candidates.length - 1
|
|
811
|
+
) {
|
|
774
812
|
pendingAttemptNotes.push(formatModelAttemptNote(attempt, candidates[index + 1]));
|
|
775
813
|
continue;
|
|
776
814
|
}
|
|
@@ -54,7 +54,13 @@ import {
|
|
|
54
54
|
buildModelCandidates,
|
|
55
55
|
formatModelAttemptNote,
|
|
56
56
|
isRetryableModelFailure,
|
|
57
|
+
modelFailureMessage,
|
|
57
58
|
} from "../shared/model-fallback.ts";
|
|
59
|
+
import {
|
|
60
|
+
assistantStopReason,
|
|
61
|
+
isAssistantFailureStopReason,
|
|
62
|
+
shouldStartSubagentFinalDrain,
|
|
63
|
+
} from "../shared/final-drain.ts";
|
|
58
64
|
import {
|
|
59
65
|
createMutatingFailureState,
|
|
60
66
|
didMutatingToolFail,
|
|
@@ -76,6 +82,7 @@ import { acceptanceFailureMessage, evaluateAcceptance, formatAcceptancePrompt, r
|
|
|
76
82
|
|
|
77
83
|
const artifactOutputByResult = new WeakMap<SingleResult, string>();
|
|
78
84
|
const acceptanceOutputByResult = new WeakMap<SingleResult, string>();
|
|
85
|
+
const modelFailureSignalByResult = new WeakMap<SingleResult, unknown>();
|
|
79
86
|
|
|
80
87
|
function emptyUsage(): Usage {
|
|
81
88
|
return { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, cost: 0, turns: 0 };
|
|
@@ -293,6 +300,7 @@ async function runSingleAttempt(
|
|
|
293
300
|
let detached = false;
|
|
294
301
|
let intercomStarted = false;
|
|
295
302
|
let assistantError: string | undefined;
|
|
303
|
+
let assistantFailureSignal: unknown;
|
|
296
304
|
let removeAbortListener: (() => void) | undefined;
|
|
297
305
|
let removeInterruptListener: (() => void) | undefined;
|
|
298
306
|
let activityTimer: NodeJS.Timeout | undefined;
|
|
@@ -544,16 +552,25 @@ async function runSingleAttempt(
|
|
|
544
552
|
progress.tokens = result.usage.input + result.usage.output;
|
|
545
553
|
}
|
|
546
554
|
if (!result.model && evt.message.model) result.model = evt.message.model;
|
|
547
|
-
if (evt.message.errorMessage) assistantError = evt.message.errorMessage;
|
|
548
555
|
const assistantText = extractTextFromContent(evt.message.content);
|
|
549
556
|
appendRecentOutput(progress, assistantText.split("\n").slice(-10));
|
|
550
|
-
//
|
|
551
|
-
|
|
552
|
-
const
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
+
// Clean final assistant stops start the exit drain window; provider error/aborted
|
|
558
|
+
// stop reasons remain failure evidence so pi-ai can auto-retry before exit.
|
|
559
|
+
const stopReason = assistantStopReason(evt.message);
|
|
560
|
+
if (evt.message.errorMessage) {
|
|
561
|
+
assistantError = evt.message.errorMessage;
|
|
562
|
+
assistantFailureSignal = evt.message;
|
|
563
|
+
}
|
|
564
|
+
if (isAssistantFailureStopReason(stopReason)) {
|
|
565
|
+
assistantError = modelFailureMessage(evt.message);
|
|
566
|
+
assistantFailureSignal = evt.message;
|
|
567
|
+
}
|
|
568
|
+
if (shouldStartSubagentFinalDrain(evt.message)) {
|
|
569
|
+
if (assistantText.trim()) {
|
|
570
|
+
assistantError = undefined;
|
|
571
|
+
assistantFailureSignal = undefined;
|
|
572
|
+
}
|
|
573
|
+
cleanTerminalAssistantStopReceived = true;
|
|
557
574
|
startFinalDrain();
|
|
558
575
|
}
|
|
559
576
|
}
|
|
@@ -633,6 +650,9 @@ async function runSingleAttempt(
|
|
|
633
650
|
processClosed = true;
|
|
634
651
|
if (buf.trim()) processLine(buf);
|
|
635
652
|
if (!result.error && assistantError) result.error = assistantError;
|
|
653
|
+
if (assistantFailureSignal !== undefined && result.error === assistantError) {
|
|
654
|
+
modelFailureSignalByResult.set(result, assistantFailureSignal);
|
|
655
|
+
}
|
|
636
656
|
const forcedDrainAfterFinalSuccess = forcedTerminationSignal && cleanTerminalAssistantStopReceived && !result.error;
|
|
637
657
|
if (code !== 0 && stderrBuf.trim() && !result.error && !forcedDrainAfterFinalSuccess) {
|
|
638
658
|
result.error = stderrBuf.trim();
|
|
@@ -964,7 +984,8 @@ export async function runSync(
|
|
|
964
984
|
if (attemptSucceeded) {
|
|
965
985
|
break;
|
|
966
986
|
}
|
|
967
|
-
|
|
987
|
+
const retrySignal = modelFailureSignalByResult.get(result) ?? result.error;
|
|
988
|
+
if (isRetryableModelFailure(retrySignal) && i < modelsToTry.length - 1) {
|
|
968
989
|
pendingAttemptNotes.push(formatModelAttemptNote(attempt, modelsToTry[i + 1]));
|
|
969
990
|
continue;
|
|
970
991
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface SubagentAssistantDrainMessage {
|
|
2
|
+
readonly role?: unknown;
|
|
3
|
+
readonly content?: unknown;
|
|
4
|
+
readonly stopReason?: unknown;
|
|
5
|
+
readonly errorMessage?: unknown;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function assistantStopReason(message: SubagentAssistantDrainMessage): string | undefined {
|
|
9
|
+
return typeof message.stopReason === "string" ? message.stopReason : undefined;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function isAssistantFailureStopReason(stopReason: string | undefined): boolean {
|
|
13
|
+
return stopReason === "error" || stopReason === "aborted";
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function assistantMessageHasToolCall(message: SubagentAssistantDrainMessage): boolean {
|
|
17
|
+
return Array.isArray(message.content)
|
|
18
|
+
&& message.content.some((part) => part !== null
|
|
19
|
+
&& typeof part === "object"
|
|
20
|
+
&& (part as { readonly type?: unknown }).type === "toolCall");
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function assistantMessageHasError(message: SubagentAssistantDrainMessage): boolean {
|
|
24
|
+
const errorMessage = message.errorMessage;
|
|
25
|
+
if (typeof errorMessage === "string") return errorMessage.trim().length > 0;
|
|
26
|
+
return errorMessage !== undefined && errorMessage !== null;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function shouldStartSubagentFinalDrain(message: SubagentAssistantDrainMessage): boolean {
|
|
30
|
+
if (message.role !== undefined && message.role !== "assistant") return false;
|
|
31
|
+
return assistantStopReason(message) === "stop"
|
|
32
|
+
&& !assistantMessageHasError(message)
|
|
33
|
+
&& !assistantMessageHasToolCall(message);
|
|
34
|
+
}
|