@bastani/atomic 0.9.40 → 0.9.41-alpha.1
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 +50 -0
- package/README.md +1 -1
- package/dist/builtin/intercom/CHANGELOG.md +12 -0
- package/dist/builtin/intercom/README.md +1 -1
- package/dist/builtin/intercom/broker/broker.ts +24 -21
- package/dist/builtin/intercom/broker/client.ts +97 -6
- package/dist/builtin/intercom/broker/list-reply.ts +53 -0
- package/dist/builtin/intercom/index.bundle.mjs +278 -46
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/recoverable-disconnect.ts +27 -1
- package/dist/builtin/intercom/types.ts +8 -1
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/subagents/CHANGELOG.md +14 -0
- package/dist/builtin/subagents/README.md +14 -0
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/index.bundle.mjs +99 -19
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +25 -0
- package/dist/builtin/workflows/README.md +2 -0
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/authoring.d.ts +1 -1
- package/dist/builtin/workflows/src/durable/journal/internal.d.ts +16 -0
- package/dist/builtin/workflows/src/durable/journal/legacy-journal-tables.d.ts +9 -0
- package/dist/builtin/workflows/src/durable/journal/sql-run-journal.d.ts +6 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +441 -90
- package/dist/builtin/workflows/src/index.js +226 -34
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +17 -1
- package/dist/cli/credential-print.d.ts.map +1 -1
- package/dist/cli/credential-print.js +1 -1
- package/dist/cli/credential-print.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-extension-bindings.d.ts +2 -1
- package/dist/core/agent-session-extension-bindings.d.ts.map +1 -1
- package/dist/core/agent-session-extension-bindings.js +33 -18
- package/dist/core/agent-session-extension-bindings.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +2 -1
- package/dist/core/agent-session-methods.d.ts.map +1 -1
- package/dist/core/agent-session-methods.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +114 -21
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +6 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-state.d.ts +19 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +41 -6
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/auth-storage-backends.d.ts +3 -1
- package/dist/core/auth-storage-backends.d.ts.map +1 -1
- package/dist/core/auth-storage-backends.js +79 -12
- package/dist/core/auth-storage-backends.js.map +1 -1
- package/dist/core/client-identity.d.ts +8 -0
- package/dist/core/client-identity.d.ts.map +1 -0
- package/dist/core/client-identity.js +16 -0
- package/dist/core/client-identity.js.map +1 -0
- package/dist/core/compaction/planner-outcome.d.ts.map +1 -1
- package/dist/core/compaction/planner-outcome.js +2 -1
- package/dist/core/compaction/planner-outcome.js.map +1 -1
- package/dist/core/execution-model-router.d.ts +18 -0
- package/dist/core/execution-model-router.d.ts.map +1 -1
- package/dist/core/execution-model-router.js +14 -8
- package/dist/core/execution-model-router.js.map +1 -1
- package/dist/core/extension-oauth-refresh-rejection.d.ts +12 -0
- package/dist/core/extension-oauth-refresh-rejection.d.ts.map +1 -0
- package/dist/core/extension-oauth-refresh-rejection.js +70 -0
- package/dist/core/extension-oauth-refresh-rejection.js.map +1 -0
- package/dist/core/extension-startup-failure.d.ts +30 -0
- package/dist/core/extension-startup-failure.d.ts.map +1 -0
- package/dist/core/extension-startup-failure.js +62 -0
- package/dist/core/extension-startup-failure.js.map +1 -0
- package/dist/core/extensions/context-types.d.ts +2 -0
- package/dist/core/extensions/context-types.d.ts.map +1 -1
- package/dist/core/extensions/context-types.js.map +1 -1
- package/dist/core/extensions/provider-types.d.ts +2 -0
- package/dist/core/extensions/provider-types.d.ts.map +1 -1
- package/dist/core/extensions/provider-types.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +1 -0
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +8 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/runtime-types.d.ts +1 -0
- package/dist/core/extensions/runtime-types.d.ts.map +1 -1
- package/dist/core/extensions/runtime-types.js.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.d.ts +1 -0
- package/dist/core/extensions/workflow-run-control-hub.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control-hub.js +3 -0
- package/dist/core/extensions/workflow-run-control-hub.js.map +1 -1
- package/dist/core/extensions/workflow-run-control.d.ts +8 -0
- package/dist/core/extensions/workflow-run-control.d.ts.map +1 -1
- package/dist/core/extensions/workflow-run-control.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts.map +1 -1
- package/dist/core/model-fallback-failures.js +12 -0
- package/dist/core/model-fallback-failures.js.map +1 -1
- package/dist/core/model-resolver-defaults.js +1 -1
- package/dist/core/model-resolver-defaults.js.map +1 -1
- package/dist/core/model-runtime-streaming.d.ts.map +1 -1
- package/dist/core/model-runtime-streaming.js +9 -3
- package/dist/core/model-runtime-streaming.js.map +1 -1
- package/dist/core/model-runtime.d.ts +5 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +6 -0
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer-internal.d.ts +6 -5
- package/dist/core/provider-composer-internal.d.ts.map +1 -1
- package/dist/core/provider-composer-internal.js +13 -2
- package/dist/core/provider-composer-internal.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +12 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/storage/session/sql-session-store.d.ts +35 -0
- package/dist/core/storage/session/sql-session-store.d.ts.map +1 -1
- package/dist/core/storage/session/sql-session-store.js +158 -42
- package/dist/core/storage/session/sql-session-store.js.map +1 -1
- package/dist/core/structured-output/deadline.d.ts +40 -0
- package/dist/core/structured-output/deadline.d.ts.map +1 -0
- package/dist/core/structured-output/deadline.js +110 -0
- package/dist/core/structured-output/deadline.js.map +1 -0
- package/dist/core/structured-output/index.d.ts.map +1 -1
- package/dist/core/structured-output/index.js +103 -47
- package/dist/core/structured-output/index.js.map +1 -1
- package/dist/core/structured-output/rejection-detail.d.ts +9 -0
- package/dist/core/structured-output/rejection-detail.d.ts.map +1 -0
- package/dist/core/structured-output/rejection-detail.js +129 -0
- package/dist/core/structured-output/rejection-detail.js.map +1 -0
- package/dist/core/structured-output/types.d.ts +8 -1
- package/dist/core/structured-output/types.d.ts.map +1 -1
- package/dist/core/structured-output/types.js.map +1 -1
- package/dist/core/tasks/completion.d.ts +7 -1
- package/dist/core/tasks/completion.d.ts.map +1 -1
- package/dist/core/tasks/completion.js +28 -6
- package/dist/core/tasks/completion.js.map +1 -1
- package/dist/core/tasks/contracts.d.ts +6 -1
- package/dist/core/tasks/contracts.d.ts.map +1 -1
- package/dist/core/tasks/contracts.js.map +1 -1
- package/dist/core/tasks/pause.d.ts +2 -1
- package/dist/core/tasks/pause.d.ts.map +1 -1
- package/dist/core/tasks/pause.js +3 -2
- package/dist/core/tasks/pause.js.map +1 -1
- package/dist/core/tools/bash-pty-native.d.ts.map +1 -1
- package/dist/core/tools/bash-pty-native.js +10 -5
- package/dist/core/tools/bash-pty-native.js.map +1 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +16 -32
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/kill.d.ts.map +1 -1
- package/dist/core/tools/kill.js +17 -3
- package/dist/core/tools/kill.js.map +1 -1
- package/dist/core/tools/shell-task-render.d.ts +55 -0
- package/dist/core/tools/shell-task-render.d.ts.map +1 -0
- package/dist/core/tools/shell-task-render.js +123 -0
- package/dist/core/tools/shell-task-render.js.map +1 -0
- package/dist/core/tools/shell-task-status.d.ts +52 -0
- package/dist/core/tools/shell-task-status.d.ts.map +1 -0
- package/dist/core/tools/shell-task-status.js +184 -0
- package/dist/core/tools/shell-task-status.js.map +1 -0
- package/dist/core/tools/structured-output.d.ts +5 -0
- package/dist/core/tools/structured-output.d.ts.map +1 -1
- package/dist/core/tools/structured-output.js +3 -0
- package/dist/core/tools/structured-output.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +134 -57
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/mcp/config.d.ts.map +1 -1
- package/dist/extensions/mcp/config.js +3 -2
- package/dist/extensions/mcp/config.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -0
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js +3 -0
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +19 -6
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/task-row.d.ts.map +1 -1
- package/dist/modes/interactive/components/task-row.js +11 -1
- package/dist/modes/interactive/components/task-row.js.map +1 -1
- package/dist/modes/interactive/interactive-auth-routing.js +12 -10
- package/dist/modes/interactive/interactive-auth-routing.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-custom-ui.js +20 -30
- package/dist/modes/interactive/interactive-extension-custom-ui.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-dialogs.js +23 -96
- package/dist/modes/interactive/interactive-extension-dialogs.js.map +1 -1
- package/dist/modes/interactive/interactive-extension-runtime.js +7 -8
- package/dist/modes/interactive/interactive-extension-runtime.js.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-input-handling.js +27 -4
- package/dist/modes/interactive/interactive-input-handling.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.d.ts +20 -10
- package/dist/modes/interactive/interactive-mode-base.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-base.js +40 -5
- package/dist/modes/interactive/interactive-mode-base.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts +1 -1
- package/dist/modes/interactive/interactive-mode-deps.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js +1 -1
- package/dist/modes/interactive/interactive-mode-deps.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.d.ts +2 -4
- package/dist/modes/interactive/interactive-mode-surface.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-surface.js.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts +4 -1
- package/dist/modes/interactive/interactive-mode-types.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode-types.js.map +1 -1
- package/dist/modes/interactive/interactive-prompt-restore.d.ts +3 -0
- package/dist/modes/interactive/interactive-prompt-restore.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-prompt-restore.js +9 -1
- package/dist/modes/interactive/interactive-prompt-restore.js.map +1 -1
- package/dist/modes/interactive/interactive-prompt-turn.js +30 -2
- package/dist/modes/interactive/interactive-prompt-turn.js.map +1 -1
- package/dist/modes/interactive/interactive-queueing.js +43 -8
- package/dist/modes/interactive/interactive-queueing.js.map +1 -1
- package/dist/modes/interactive/interactive-startup.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-startup.js +12 -3
- package/dist/modes/interactive/interactive-startup.js.map +1 -1
- package/dist/modes/interactive/theme/color-utils.d.ts +6 -1
- package/dist/modes/interactive/theme/color-utils.d.ts.map +1 -1
- package/dist/modes/interactive/theme/color-utils.js +39 -17
- package/dist/modes/interactive/theme/color-utils.js.map +1 -1
- package/dist/modes/interactive/theme/theme-class.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-class.js +2 -2
- package/dist/modes/interactive/theme/theme-class.js.map +1 -1
- package/dist/modes/interactive/theme/theme-tokens.d.ts +6 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-tokens.js +7 -3
- package/dist/modes/interactive/theme/theme-tokens.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-auth.d.ts +3 -0
- package/dist/modes/interactive-engine/isolated-auth.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-auth.js +13 -1
- package/dist/modes/interactive-engine/isolated-auth.js.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.d.ts.map +1 -1
- package/dist/modes/interactive-engine/isolated-runtime.js +11 -2
- package/dist/modes/interactive-engine/isolated-runtime.js.map +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.d.ts +8 -0
- package/dist/modes/interactive-engine/remote-model-catalog.d.ts.map +1 -1
- package/dist/modes/interactive-engine/remote-model-catalog.js +54 -0
- package/dist/modes/interactive-engine/remote-model-catalog.js.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-command-handler.js +4 -13
- package/dist/modes/rpc/rpc-command-handler.js.map +1 -1
- package/dist/modes/rpc/rpc-model-catalog.d.ts +9 -0
- package/dist/modes/rpc/rpc-model-catalog.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-model-catalog.js +19 -0
- package/dist/modes/rpc/rpc-model-catalog.js.map +1 -0
- package/dist/modes/rpc/rpc-provider-auth.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-provider-auth.js +2 -6
- package/dist/modes/rpc/rpc-provider-auth.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +6 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/changelog.d.ts +6 -0
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +11 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +4 -0
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +3 -2
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/background-tasks.md +5 -3
- package/docs/codemode.md +2 -2
- package/docs/custom-provider/oauth.md +42 -1
- package/docs/custom-provider/registration.md +2 -0
- package/docs/environment-variables.md +1 -0
- package/docs/extensions/api-reference.md +3 -4
- package/docs/extensions/authoring.md +1 -1
- package/docs/extensions/events.md +1 -1
- package/docs/providers.md +3 -3
- package/docs/rpc/protocol.md +4 -2
- package/docs/sdk/reference.md +2 -0
- package/docs/sdk/structured-decisions.md +7 -5
- package/docs/sdk.md +5 -2
- package/docs/settings.md +4 -2
- package/docs/subagents/reference.md +1 -1
- package/docs/subagents.md +15 -1
- package/docs/themes/reference.md +3 -1
- package/docs/usage.md +3 -1
- package/docs/workflows/api-reference.md +28 -0
- package/docs/workflows/operations.md +2 -2
- package/npm-shrinkwrap.json +32 -32
- package/package.json +3 -3
- package/dist/core/provider-attribution.d.ts +0 -4
- package/dist/core/provider-attribution.d.ts.map +0 -1
- package/dist/core/provider-attribution.js +0 -87
- package/dist/core/provider-attribution.js.map +0 -1
|
@@ -18,6 +18,10 @@
|
|
|
18
18
|
* reconnect, or the previous attempt's session is still being torn down), the
|
|
19
19
|
* same bounded retry that recovers a lost socket clears it (#3163). A refusal
|
|
20
20
|
* whose code repeats identically on retry is not recoverable.
|
|
21
|
+
*
|
|
22
|
+
* A broker that accepts the socket but does not answer a registration in time is
|
|
23
|
+
* saturated, not gone. Its timeout is recoverable for the same reason, and a
|
|
24
|
+
* background relay that sees it keeps quiet unless the outage persists.
|
|
21
25
|
*/
|
|
22
26
|
|
|
23
27
|
import { IntercomLiveRouteRefusedError } from "./live-route-refusal.js";
|
|
@@ -47,8 +51,18 @@ export class IntercomClientDisconnectedError extends Error implements Recoverabl
|
|
|
47
51
|
}
|
|
48
52
|
}
|
|
49
53
|
|
|
54
|
+
/** Raised when the broker accepted the socket but did not answer a registration within its bound. */
|
|
55
|
+
export class IntercomBrokerTimeoutError extends Error implements RecoverableDisconnectMarker {
|
|
56
|
+
readonly intercomRecoverableDisconnect = true;
|
|
57
|
+
|
|
58
|
+
constructor(message: string, options?: ErrorOptions) {
|
|
59
|
+
super(message, options);
|
|
60
|
+
this.name = "IntercomBrokerTimeoutError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
50
64
|
/**
|
|
51
|
-
* True for an `IntercomClientDisconnectedError` or a transient
|
|
65
|
+
* True for an `IntercomClientDisconnectedError`, an `IntercomBrokerTimeoutError`, or a transient
|
|
52
66
|
* `IntercomLiveRouteRefusedError`, directly or as a bounded `cause` ancestor.
|
|
53
67
|
*/
|
|
54
68
|
export function isRecoverableIntercomDisconnect(error: unknown): boolean {
|
|
@@ -56,8 +70,20 @@ export function isRecoverableIntercomDisconnect(error: unknown): boolean {
|
|
|
56
70
|
for (let depth = 0; depth <= MAX_CAUSE_DEPTH; depth += 1) {
|
|
57
71
|
if (!(current instanceof Error)) return false;
|
|
58
72
|
if (current instanceof IntercomClientDisconnectedError) return true;
|
|
73
|
+
if (current instanceof IntercomBrokerTimeoutError) return true;
|
|
59
74
|
if (current instanceof IntercomLiveRouteRefusedError) return current.transient;
|
|
60
75
|
current = current.cause;
|
|
61
76
|
}
|
|
62
77
|
return false;
|
|
63
78
|
}
|
|
79
|
+
|
|
80
|
+
/** True for an `IntercomBrokerTimeoutError`, directly or as a bounded `cause` ancestor. */
|
|
81
|
+
export function isIntercomBrokerTimeout(error: unknown): boolean {
|
|
82
|
+
let current: unknown = error;
|
|
83
|
+
for (let depth = 0; depth <= MAX_CAUSE_DEPTH; depth += 1) {
|
|
84
|
+
if (!(current instanceof Error)) return false;
|
|
85
|
+
if (current instanceof IntercomBrokerTimeoutError) return true;
|
|
86
|
+
current = current.cause;
|
|
87
|
+
}
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
@@ -70,6 +70,8 @@ export interface SessionDirectory {
|
|
|
70
70
|
readonly sessions: SessionInfo[];
|
|
71
71
|
readonly workflowStages: WorkflowStageRosterEntry[];
|
|
72
72
|
readonly workflowFutureStages: WorkflowFutureStageRosterEntry[];
|
|
73
|
+
/** The peeked workflow invocation group exists but is visible only to its members. */
|
|
74
|
+
readonly restricted?: true;
|
|
73
75
|
}
|
|
74
76
|
|
|
75
77
|
export interface WorkflowStageRosterAnnouncement {
|
|
@@ -186,6 +188,8 @@ export type ClientMessage =
|
|
|
186
188
|
| { type: "pending_stage_notification_result"; requestId: string; delivered: boolean }
|
|
187
189
|
| {
|
|
188
190
|
type: "register_pending_stage_route";
|
|
191
|
+
/** When present, the broker answers with `pending_stage_route_registered` once the route is applied. */
|
|
192
|
+
requestId?: string;
|
|
189
193
|
runId: string;
|
|
190
194
|
group: string;
|
|
191
195
|
capability: string;
|
|
@@ -230,10 +234,12 @@ export type BrokerMessage =
|
|
|
230
234
|
supervisorSessionId?: string;
|
|
231
235
|
/** #3761: echoed only to a client that advertised it; that client may now send `received`. */
|
|
232
236
|
acknowledgesReceipt?: true;
|
|
237
|
+
/** This broker acknowledges a `register_pending_stage_route` that carries a `requestId`; absent on older brokers. */
|
|
238
|
+
acknowledgesPendingStageRoutes?: true;
|
|
233
239
|
}
|
|
234
240
|
| { type: "registration_failed"; reason: string; code?: LiveWorkflowStageRouteRefusalCode }
|
|
235
241
|
| { type: "question_target"; messageId: string; attemptId: string; sessionId: string }
|
|
236
|
-
| { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[] }
|
|
242
|
+
| { type: "sessions"; requestId: string; sessions: SessionInfo[]; workflowStages?: WorkflowStageRosterEntry[]; workflowFutureStages?: WorkflowFutureStageRosterEntry[]; restricted?: true }
|
|
237
243
|
| { type: "groups"; requestId: string; groups: GroupSummary[] }
|
|
238
244
|
| { type: "membership_ack"; requestId: string; groups: string[] }
|
|
239
245
|
| { type: "supervisor_authorized"; requestId: string; capability: string; supervisorSessionId: string; childName: string }
|
|
@@ -251,6 +257,7 @@ export type BrokerMessage =
|
|
|
251
257
|
live?: boolean;
|
|
252
258
|
}
|
|
253
259
|
| { type: "live_workflow_stage_route_registered"; requestId: string }
|
|
260
|
+
| { type: "pending_stage_route_registered"; requestId: string }
|
|
254
261
|
/** A dormant route's run was resumed by another process, which now owns the run's routes (#3760). */
|
|
255
262
|
| { type: "pending_stage_route_revoked"; runId: string }
|
|
256
263
|
| { type: "presence_update"; session: SessionInfo }
|
|
@@ -2,6 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [0.9.41-alpha.1] - 2026-10-21
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added a `resumeInFlight` subagent setting (`"never"`, `"ask"`, or `"auto"`, default `"never"`) for recovery of paused and quit subagents that are awaiting resume. `ask` confirms once, listing each subagent, and `auto` resumes each from its own session, with its completion reaching the session that launched it; `never` leaves them for a manual `resume`. It applies when Atomic starts or a session is resumed, to that session's own subagents, never to workflow-stage children, and an invalid value is reported and treated as `never` ([#3827](https://github.com/bastani-inc/atomic/issues/3827)).
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- Quitting a subagent now behaves like quitting a workflow. The `quit` and `pause` results say the child is paused · awaiting resume and name `{ action: "resume", id: "<child-id>" }`; the parent's completion notice says the same, with the typed `quit` or `pause` stop reason instead of `parent-handoff` and without "This execution has ended". `{ action: "status", id }` reports a paused or quit child as paused · awaiting resume with its resume call, and `{ action: "status" }` lists every such child, including after Atomic restarts. Launch cards of such children show `‖ Paused · awaiting resume` (or `‖ Quit · paused · awaiting resume`) instead of `(resumable)`.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- A subagent with `model: "auto"` no longer waits indefinitely on a slow routing model. Each routing inference now stops after the `httpIdleTimeoutMs` deadline (10 minutes by default), and the subagent runs on the current chat model when it satisfies the routing constraints ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
|
|
18
|
+
|
|
5
19
|
## [0.9.40] - 2026-10-20
|
|
6
20
|
|
|
7
21
|
### Breaking Changes
|
|
@@ -620,6 +620,20 @@ Subagent configuration controls discovery, parallel limits, session storage, con
|
|
|
620
620
|
|
|
621
621
|
Running capacity is selected when a parent's first child is created. Restart Atomic after changing this setting to apply the new capacity.
|
|
622
622
|
|
|
623
|
+
### `resumeInFlight`
|
|
624
|
+
|
|
625
|
+
```json
|
|
626
|
+
{ "resumeInFlight": "ask" }
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Recovery of paused and quit subagents that are awaiting resume when a session starts or is resumed, using the same values as the workflow setting of that name:
|
|
630
|
+
|
|
631
|
+
- `never` (default): leave them listed under "Awaiting resume" for a manual `resume`.
|
|
632
|
+
- `ask`: confirm once, listing each subagent by name and id. No leaves them awaiting resume; without a UI it behaves like `never`.
|
|
633
|
+
- `auto`: resume each from its own session. Its result reaches the session that launched it.
|
|
634
|
+
|
|
635
|
+
Starting Atomic and resuming a session recover children; a reload, new session, or fork does not. Only children launched by the session being started or resumed are affected; workflow-stage children are never resumed this way. Any other value is reported and treated as `never`.
|
|
636
|
+
|
|
623
637
|
### `defaultSessionDir`
|
|
624
638
|
|
|
625
639
|
```json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/subagents",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.41-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for delegating tasks to subagents with parallel execution. Fork of: https://github.com/nicobailon/pi-subagents",
|
|
6
6
|
"contributors": [
|
|
@@ -8467,6 +8467,7 @@ var SUBAGENT_CONTROL_INTERCOM_EVENT = "subagent:control-intercom";
|
|
|
8467
8467
|
var SUBAGENT_RESULT_INTERCOM_EVENT = "subagent:result-intercom";
|
|
8468
8468
|
var SUBAGENT_TERMINAL_ORDERING_BARRIER_EVENT = "subagent:terminal-ordering-barrier";
|
|
8469
8469
|
var SUBAGENT_RESULT_INTERCOM_DELIVERY_EVENT = "subagent:result-intercom-delivery";
|
|
8470
|
+
var RESUME_IN_FLIGHT_MODES = ["ask", "auto", "never"];
|
|
8470
8471
|
// dist/builtin/subagents/src/shared/types-depth.ts
|
|
8471
8472
|
function isWorkflowStageOrchestrationContext(ctx) {
|
|
8472
8473
|
return ctx.orchestrationContext?.kind === "workflow-stage";
|
|
@@ -10558,7 +10559,11 @@ function retainedTaskOutput(ownerId, taskId) {
|
|
|
10558
10559
|
|
|
10559
10560
|
// dist/builtin/subagents/src/runs/foreground/task-execution.ts
|
|
10560
10561
|
function subagentTaskResultLabel(result) {
|
|
10561
|
-
|
|
10562
|
+
if (result.kind === "cancelled" && result.cause === "user")
|
|
10563
|
+
return "killed (non-resumable)";
|
|
10564
|
+
if (result.kind === "cancelled" && (result.cause === "pause" || result.cause === "quit"))
|
|
10565
|
+
return "paused · awaiting resume";
|
|
10566
|
+
return result.kind;
|
|
10562
10567
|
}
|
|
10563
10568
|
function subagentTaskResponseText(response) {
|
|
10564
10569
|
const outcomes = response.kind === "parallel" ? response.slots.map((slot) => slot.outcome) : [response];
|
|
@@ -10887,7 +10892,7 @@ ${launch.message}` : input.task,
|
|
|
10887
10892
|
});
|
|
10888
10893
|
const stopped = takeSubagentChildStop(context.ref.taskId);
|
|
10889
10894
|
const stoppedByControl = stopped !== undefined && child.status === "interrupted";
|
|
10890
|
-
const stoppedByStagePause = !stoppedByControl && child.status === "interrupted" && context.signal.aborted && context.signal.reason === "
|
|
10895
|
+
const stoppedByStagePause = !stoppedByControl && child.status === "interrupted" && context.signal.aborted && context.signal.reason === "pause";
|
|
10891
10896
|
const endedForGood = ownerClosed() && input.recordChild?.ownerEndedForGood?.() === true;
|
|
10892
10897
|
if (stopped !== undefined && !stoppedByControl)
|
|
10893
10898
|
unparkRunWorktree(runId, index);
|
|
@@ -10921,7 +10926,7 @@ ${launch.message}` : input.task,
|
|
|
10921
10926
|
if (child.interrupted)
|
|
10922
10927
|
return {
|
|
10923
10928
|
kind: "cancelled",
|
|
10924
|
-
cause: stoppedByControl
|
|
10929
|
+
cause: stoppedByControl ? stopped === "quit" ? "quit" : "pause" : stoppedByStagePause ? "pause" : input.options.interruptSignal?.aborted ? "parent-handoff" : "owner-close",
|
|
10925
10930
|
output
|
|
10926
10931
|
};
|
|
10927
10932
|
return child.status === "ok" ? { kind: "completed", output } : {
|
|
@@ -17474,7 +17479,7 @@ async function stopHostChild(deps, host, record, status) {
|
|
|
17474
17479
|
const taskId = record.taskId;
|
|
17475
17480
|
requestSubagentChildStop(taskId, status);
|
|
17476
17481
|
parkRunWorktree(record.runId, record.index);
|
|
17477
|
-
const cancelled = await host.cancelTask(taskId, "
|
|
17482
|
+
const cancelled = await host.cancelTask(taskId, status === "quit" ? "quit" : "pause");
|
|
17478
17483
|
if (!cancelled.ok) {
|
|
17479
17484
|
unparkRunWorktree(record.runId, record.index);
|
|
17480
17485
|
return cancelled.error.message;
|
|
@@ -17550,7 +17555,7 @@ async function stopChildren(deps, ctx, request) {
|
|
|
17550
17555
|
continue;
|
|
17551
17556
|
}
|
|
17552
17557
|
children.push(childDetails(record, status));
|
|
17553
|
-
lines.push(action === "pause" ? `Paused ${label(record)}. Its queued messages are held until resume; resume it with { action: "resume", id: "${record.childId}", message? }.` : `Quit ${label(record)}. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
|
|
17558
|
+
lines.push(action === "pause" ? `Paused ${label(record)} · awaiting resume. Its queued messages are held until resume; resume it with { action: "resume", id: "${record.childId}", message? }.` : `Quit ${label(record)}: paused · awaiting resume, as a quit workflow run is. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
|
|
17554
17559
|
continue;
|
|
17555
17560
|
}
|
|
17556
17561
|
const stopped = stoppedAs(record);
|
|
@@ -17559,7 +17564,7 @@ async function stopChildren(deps, ctx, request) {
|
|
|
17559
17564
|
releasePausedChildHold(key);
|
|
17560
17565
|
await recordSubagentChildStatus(deps.pi, record, "quit");
|
|
17561
17566
|
children.push(childDetails(record, "quit"));
|
|
17562
|
-
lines.push(`Quit paused ${label(record)}. It stays resumable.`);
|
|
17567
|
+
lines.push(`Quit paused ${label(record)}: paused · awaiting resume. It stays resumable with { action: "resume", id: "${record.childId}", message? }.`);
|
|
17563
17568
|
continue;
|
|
17564
17569
|
}
|
|
17565
17570
|
children.push(childDetails(record, stopped));
|
|
@@ -17605,6 +17610,18 @@ async function resumeChild(deps, ctx, request) {
|
|
|
17605
17610
|
...message ? { message } : {}
|
|
17606
17611
|
});
|
|
17607
17612
|
}
|
|
17613
|
+
function awaitingResumeLine(record) {
|
|
17614
|
+
const how = record.terminalStatus === "quit" ? "quit · paused · awaiting resume" : record.terminalStatus === SUBAGENT_CHILD_STAGE_PAUSED_STATUS ? "paused with its workflow stage · awaiting resume" : "paused · awaiting resume";
|
|
17615
|
+
return `${label(record)} ${how}. Resume it with { action: "resume", id: "${record.childId}", message? }.`;
|
|
17616
|
+
}
|
|
17617
|
+
function subagentChildrenAwaitingResume(ctx, id) {
|
|
17618
|
+
const records = ownedRecords(ctx);
|
|
17619
|
+
if (id?.trim()) {
|
|
17620
|
+
const resolved = resolveRecord(records, id);
|
|
17621
|
+
return typeof resolved === "object" && stoppedAs(resolved) ? [awaitingResumeLine(resolved)] : [];
|
|
17622
|
+
}
|
|
17623
|
+
return [...records.values()].filter((record) => stoppedAs(record)).map(awaitingResumeLine);
|
|
17624
|
+
}
|
|
17608
17625
|
function controlSubagentChildren(deps, ctx, request) {
|
|
17609
17626
|
if (request.all && request.id)
|
|
17610
17627
|
return Promise.resolve(errorResult(request.action, "Pass either id or all: true, not both."));
|
|
@@ -17612,6 +17629,42 @@ function controlSubagentChildren(deps, ctx, request) {
|
|
|
17612
17629
|
return Promise.resolve(errorResult(request.action, `${request.action} needs the id of a child, or all: true.`));
|
|
17613
17630
|
return request.action === "resume" ? resumeChild(deps, ctx, request) : stopChildren(deps, ctx, { ...request, action: request.action });
|
|
17614
17631
|
}
|
|
17632
|
+
async function resumeAwaitingSubagentChildren(deps, ctx, mode, isCurrent) {
|
|
17633
|
+
if (mode === "never" || ctx.isPresentationOnly === true)
|
|
17634
|
+
return;
|
|
17635
|
+
if (isSubagentChildSession(ctx) || isWorkflowStageOrchestrationContext(ctx))
|
|
17636
|
+
return;
|
|
17637
|
+
if (mode === "ask" && (ctx.hasUI === false || typeof ctx.ui?.confirm !== "function"))
|
|
17638
|
+
return;
|
|
17639
|
+
const notify = (message, type) => {
|
|
17640
|
+
try {
|
|
17641
|
+
ctx.ui?.notify?.(message, type);
|
|
17642
|
+
} catch {
|
|
17643
|
+
return;
|
|
17644
|
+
}
|
|
17645
|
+
};
|
|
17646
|
+
try {
|
|
17647
|
+
const awaiting = [...ownedRecords(ctx).values()].filter((record) => record.owner.kind === "session" && stoppedAs(record));
|
|
17648
|
+
if (awaiting.length === 0)
|
|
17649
|
+
return;
|
|
17650
|
+
if (mode === "ask" && !await ctx.ui.confirm("Resume interrupted subagents?", `${awaiting.length} interrupted subagent(s) can resume from their own sessions:
|
|
17651
|
+
${awaiting.map((record) => `- ${label(record)}`).join(`
|
|
17652
|
+
`)}
|
|
17653
|
+
Resume now? Choose No to leave them awaiting resume; resume one later with subagent({ action: "resume", id }).`))
|
|
17654
|
+
return;
|
|
17655
|
+
for (const record of awaiting) {
|
|
17656
|
+
if (!isCurrent())
|
|
17657
|
+
return;
|
|
17658
|
+
const result = await controlSubagentChildren(deps, ctx, { action: "resume", id: record.childId });
|
|
17659
|
+
notify(result.content.map((part) => part.type === "text" ? part.text : "").join(`
|
|
17660
|
+
`), result.isError ? "warning" : "info");
|
|
17661
|
+
}
|
|
17662
|
+
} catch (error) {
|
|
17663
|
+
if (!isCurrent())
|
|
17664
|
+
return;
|
|
17665
|
+
notify(`Subagent startup resume failed: ${String(error)}. Use subagent({ action: "resume", id }) to retry.`, "warning");
|
|
17666
|
+
}
|
|
17667
|
+
}
|
|
17615
17668
|
|
|
17616
17669
|
// dist/builtin/subagents/src/runs/foreground/subagent-executor.ts
|
|
17617
17670
|
var MUTATING_MANAGEMENT_ACTIONS = new Set(["create", "update", "delete"]);
|
|
@@ -17693,6 +17746,7 @@ async function handleManagementRequest(input) {
|
|
|
17693
17746
|
});
|
|
17694
17747
|
}
|
|
17695
17748
|
const targetTaskId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
17749
|
+
const awaitingResume = action === "status" ? subagentChildrenAwaitingResume(ctx, targetTaskId) : [];
|
|
17696
17750
|
if (action === "status" && ctx.getAgentTaskHost && targetTaskId) {
|
|
17697
17751
|
const host = ctx.getAgentTaskHost();
|
|
17698
17752
|
const taskId = targetTaskId;
|
|
@@ -17706,7 +17760,9 @@ async function handleManagementRequest(input) {
|
|
|
17706
17760
|
content: [
|
|
17707
17761
|
{
|
|
17708
17762
|
type: "text",
|
|
17709
|
-
text: `${
|
|
17763
|
+
text: `${awaitingResume.length > 0 ? `${awaitingResume.join(`
|
|
17764
|
+
`)}
|
|
17765
|
+
` : ""}${records.some((task) => task.execution.kind === "settled" && subagentTaskResultLabel(task.execution.result) === "killed (non-resumable)") ? `Killed. This child cannot be resumed. Underlying host records:
|
|
17710
17766
|
` : ""}${JSON.stringify(records)}${settledOutput}`
|
|
17711
17767
|
}
|
|
17712
17768
|
],
|
|
@@ -17720,14 +17776,28 @@ async function handleManagementRequest(input) {
|
|
|
17720
17776
|
};
|
|
17721
17777
|
}
|
|
17722
17778
|
}
|
|
17779
|
+
if (targetTaskId && awaitingResume.length > 0)
|
|
17780
|
+
return {
|
|
17781
|
+
content: [{ type: "text", text: awaitingResume.join(`
|
|
17782
|
+
`) }],
|
|
17783
|
+
details: { mode: "management", results: [] }
|
|
17784
|
+
};
|
|
17723
17785
|
if (action === "status") {
|
|
17724
17786
|
const targetRunId = paramsWithResolvedCwd.id ?? paramsWithResolvedCwd.runId;
|
|
17725
|
-
const inProcess = inspectInProcessChildStatus(targetRunId);
|
|
17726
|
-
if (inProcess)
|
|
17727
|
-
return inProcess;
|
|
17728
17787
|
const foreground = getForegroundControl(deps.state, targetRunId);
|
|
17729
|
-
|
|
17730
|
-
|
|
17788
|
+
const live = inspectInProcessChildStatus(targetRunId) ?? (foreground ? foregroundStatusResult(foreground) : undefined);
|
|
17789
|
+
if (awaitingResume.length > 0) {
|
|
17790
|
+
const liveText = live?.content.map((part) => part.type === "text" ? part.text : "").join(`
|
|
17791
|
+
`);
|
|
17792
|
+
const text = [liveText, `Awaiting resume:
|
|
17793
|
+
${awaitingResume.join(`
|
|
17794
|
+
`)}`].filter(Boolean).join(`
|
|
17795
|
+
|
|
17796
|
+
`);
|
|
17797
|
+
return { details: live?.details ?? { mode: "management", results: [] }, content: [{ type: "text", text }] };
|
|
17798
|
+
}
|
|
17799
|
+
if (live)
|
|
17800
|
+
return live;
|
|
17731
17801
|
return {
|
|
17732
17802
|
content: [
|
|
17733
17803
|
{
|
|
@@ -19371,11 +19441,19 @@ function renderSubagentResult(result, options, theme) {
|
|
|
19371
19441
|
// dist/builtin/subagents/src/extension/config.ts
|
|
19372
19442
|
import * as fs19 from "node:fs";
|
|
19373
19443
|
import { getAgentConfigPaths as getAgentConfigPaths5 } from "@bastani/atomic";
|
|
19444
|
+
function withoutInvalidResumeInFlight(config, configPath) {
|
|
19445
|
+
const value = config.resumeInFlight;
|
|
19446
|
+
if (value === undefined || RESUME_IN_FLIGHT_MODES.some((mode) => mode === value))
|
|
19447
|
+
return config;
|
|
19448
|
+
console.error(`Invalid subagent config '${configPath}': "resumeInFlight" must be "ask", "auto", or "never", got ${JSON.stringify(value)}`);
|
|
19449
|
+
const { resumeInFlight: _ignored, ...rest } = config;
|
|
19450
|
+
return rest;
|
|
19451
|
+
}
|
|
19374
19452
|
function loadConfig() {
|
|
19375
19453
|
for (const configPath of getAgentConfigPaths5("extensions", "subagent", "config.json")) {
|
|
19376
19454
|
try {
|
|
19377
19455
|
if (fs19.existsSync(configPath)) {
|
|
19378
|
-
return JSON.parse(fs19.readFileSync(configPath, "utf-8"));
|
|
19456
|
+
return withoutInvalidResumeInFlight(JSON.parse(fs19.readFileSync(configPath, "utf-8")), configPath);
|
|
19379
19457
|
}
|
|
19380
19458
|
} catch (error) {
|
|
19381
19459
|
console.error(`Failed to load subagent config from '${configPath}':`, error);
|
|
@@ -19664,9 +19742,9 @@ MANAGEMENT (use action field, omit agent/task/tasks):
|
|
|
19664
19742
|
• { action: "update", agent: "code-analysis.custom-agent", config: { package: "analysis", ... } } - merge
|
|
19665
19743
|
• { action: "delete", agent: "code-analysis.custom-agent" }
|
|
19666
19744
|
CONTROL:
|
|
19667
|
-
• { action: "status", id: "..." } - inspect an in-process run by id or prefix
|
|
19745
|
+
• { action: "status", id: "..." } - inspect an in-process run by id or prefix; a paused or quit child shows as paused · awaiting resume with its resume call, and { action: "status" } lists every such child
|
|
19668
19746
|
• { action: "pause", id: "..." } / { action: "pause", all: true } - stop a running child and hold its queued messages until resume; it stays resumable
|
|
19669
|
-
• { action: "quit", id: "..." } / { action: "quit", all: true } - stop a child gracefully (including a paused one)
|
|
19747
|
+
• { action: "quit", id: "..." } / { action: "quit", all: true } - stop a child gracefully (including a paused one), as a workflow quit does: it is paused · awaiting resume, not ended, and stays resumable
|
|
19670
19748
|
• { action: "resume", id: "...", message?: "..." } - continue a paused, quit, interrupted, completed or failed child from its own session under the same id and Intercom name; message is delivered once as its next prompt, otherwise it continues where it left off. Children cancelled for good (owner or batch cancellation, the removed kill action), ended with their workflow stage (quit ones included), or reported gone cannot be resumed
|
|
19671
19749
|
• id accepts the child id (<runId>:<index>), its task id, its Intercom name, or the run id of a single-child run. kill and interrupt were removed: use quit`;
|
|
19672
19750
|
|
|
@@ -19686,12 +19764,12 @@ function effectiveParallelTaskCount(tasks) {
|
|
|
19686
19764
|
var SETTLED_VIEWS = {
|
|
19687
19765
|
ok: { icon: "✓", label: "Completed", color: "success" },
|
|
19688
19766
|
error: { icon: "✗", label: "Failed", color: "error" },
|
|
19689
|
-
paused: { icon: "‖", label: "Paused
|
|
19690
|
-
quit: { icon: "
|
|
19767
|
+
paused: { icon: "‖", label: "Paused · awaiting resume", color: "warning" },
|
|
19768
|
+
quit: { icon: "‖", label: "Quit · paused · awaiting resume", color: "warning" },
|
|
19691
19769
|
interrupted: { icon: "○", label: "Interrupted (resumable)", color: "warning" },
|
|
19692
19770
|
[SUBAGENT_CHILD_STAGE_PAUSED_STATUS]: {
|
|
19693
19771
|
icon: "‖",
|
|
19694
|
-
label: "Paused with its workflow stage
|
|
19772
|
+
label: "Paused with its workflow stage · awaiting resume",
|
|
19695
19773
|
color: "warning"
|
|
19696
19774
|
},
|
|
19697
19775
|
killed: { icon: "✗", label: "Terminal · killed", color: "error" },
|
|
@@ -19797,7 +19875,7 @@ function renderSubagentToolResult(result, options, theme, context) {
|
|
|
19797
19875
|
${theme.fg("muted", `│ ${displayText2(line)}`)}`).join("") : ""
|
|
19798
19876
|
].join("");
|
|
19799
19877
|
}
|
|
19800
|
-
const state = observation.kind === "yielded" ? request?.action === "wait" ? "Still running in background" : "Launched in background" : observation.result.kind === "completed" ? "Completed" : observation.result.kind === "failed" ? "Failed" : subagentTaskResultLabel(observation.result) === "killed (non-resumable)" ? "Killed (non-resumable)" : "Stopped";
|
|
19878
|
+
const state = observation.kind === "yielded" ? request?.action === "wait" ? "Still running in background" : "Launched in background" : observation.result.kind === "completed" ? "Completed" : observation.result.kind === "failed" ? "Failed" : subagentTaskResultLabel(observation.result) === "killed (non-resumable)" ? "Killed (non-resumable)" : subagentTaskResultLabel(observation.result) === "paused · awaiting resume" ? "Paused · awaiting resume" : "Stopped";
|
|
19801
19879
|
const icon = observation.kind === "yielded" ? "∀" : observation.result.kind === "completed" ? "✓" : observation.result.kind === "failed" ? "✗" : "○";
|
|
19802
19880
|
const color = observation.kind === "yielded" ? "accent" : observation.result.kind === "failed" ? "error" : observation.result.kind === "completed" ? "success" : "warning";
|
|
19803
19881
|
const identity = labels[index];
|
|
@@ -20326,6 +20404,8 @@ function registerSubagentExtension(pi) {
|
|
|
20326
20404
|
holdRunningSubagentChildren(pi.events, ctx).catch(() => {
|
|
20327
20405
|
return;
|
|
20328
20406
|
});
|
|
20407
|
+
if (opened)
|
|
20408
|
+
resumeAwaitingSubagentChildren(executorDeps, ctx, config.resumeInFlight ?? "never", lifecycle.isCurrent);
|
|
20329
20409
|
}
|
|
20330
20410
|
});
|
|
20331
20411
|
pi.on("session_recovery_restore", async (_event, ctx) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bastani/web-access",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.41-alpha.1",
|
|
4
4
|
"private": true,
|
|
5
5
|
"description": "Atomic extension for web search, URL fetching, GitHub repo cloning, PDF/video extraction. Fork of: https://github.com/nicobailon/pi-web-access",
|
|
6
6
|
"contributors": [
|
|
@@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.9.41-alpha.1] - 2026-10-21
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Added `schemaTimeoutMs` to workflow stage, task, chain, and parallel options: the wall-clock limit in milliseconds for each `structured_output` decision of a schema-backed item, covering its repair attempts, retries, and model fallbacks together. It defaults to the `httpIdleTimeoutMs` setting ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Reopening `/workflow resume` is faster: the run list is kept between opens and rereads only the runs whose journal changed since the last open, including changes made by other Atomic processes. Whether another session still owns a run is checked when you select it.
|
|
18
|
+
- `/workflow connect` and `/workflow status` now list runs the way `/tasks` does. Active runs come before ended ones, with runs waiting for your input or blocked first, then running, then paused; ended runs follow with failed, cancelled, then completed. Within each group the newest run comes first, where before the `/workflow connect` list showed the oldest running run first ([#3824](https://github.com/bastani-inc/atomic/issues/3824)).
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- A workflow stage no longer stays stuck selecting its model when many workflows run at once. A stage with `model: "auto"` now waits at most five minutes for model selection, counting any wait for one of eight routing slots shared by every stage, so a burst of stages queues instead of overloading the router provider. When the wait ends, the stage runs on the current chat model if that model satisfies every routing constraint; otherwise it fails with an error that names the stage and the `model-resolution` startup phase, and its startup status reads `failed` instead of staying active. A failed selection is no longer remembered, so the next prompt on the same stage selects a model again, without launching a replacement workflow.
|
|
23
|
+
- After a blocked workflow run is resumed, Intercom sends to `workflow:<rootRunId>/**`, to stage patterns, and to stages that have not started yet are accepted and delivered again instead of failing with `Workflow execution for <runId> is retired`.
|
|
24
|
+
- In a long-running session, starting a workflow from a turn that an Intercom message started no longer fails with `Workflow execution for <runId> is retired; startup cleanup failed: …` after an earlier workflow run in the session has ended or been quit. The session's Intercom connection is now opened outside the workflow run that first needed it. The `is retired` error now names the run whose execution actually ended, not the run being started.
|
|
25
|
+
- A workflow stage whose fallback session fails to start because an extension's `session_start` failed under load, for example Intercom's `Broker failed to start within timeout` or `connect ECONNREFUSED`, now retries that session with the same-model retry budget and then moves on to its next fallback model, instead of failing the stage and letting fail-fast skip its sibling stages. Any other extension startup error still fails the stage at once. The stage error, model attempts, and fallback warnings now name each failing extension and its error rather than only `Extension startup failed`.
|
|
26
|
+
- When a workflow stage falls back to another model and that fallback session cannot start, the stage now closes the session it was replacing. Before, that session kept its session database open after the stage failed, and on Windows the file could not be deleted until the process exited.
|
|
27
|
+
- Workflow stage sessions now provide `ctx.ui.theme` and the other default UI members, so extensions that read `ctx.ui.theme.fg(...)` in `session_start`, such as `examples/extensions/status-line.ts`, no longer fail stage startup with `Extension startup failed` ([#3801](https://github.com/bastani-inc/atomic/issues/3801))
|
|
28
|
+
- Workflow inputs now reject integer and number values outside the `minimum`/`maximum` declared in the input schema, such as `count: 0` for `Type.Integer({ minimum: 1, maximum: 8 })`, when the run is started, instead of passing them to the workflow body. The error names the input and the violated bound ([#3812](https://github.com/bastani-inc/atomic/issues/3812)).
|
|
29
|
+
- A `ctx.parallel(..., { failFast: false })` call that has a failing step no longer loses the results of the steps that succeeded. The `AggregateError` it rejects with now carries `partialResults`, one entry per step in step order, holding each completed step's result and `undefined` for a step that failed. The `WorkflowParallelFailure` type describes it ([#3809](https://github.com/bastani-inc/atomic/issues/3809))
|
|
30
|
+
- A workflow stage's corrective prompt after a rejected `structured_output` result now names the failing paths and expected types, or reports that the tool arguments were not valid JSON, instead of only saying the response does not match the decision schema ([#3802](https://github.com/bastani-inc/atomic/issues/3802))
|
|
31
|
+
- Disposing a session right after a workflow run reports that it ended no longer leaves the run `running` in the workflow journal, with its lease released, for readers to report as crashed. `session.dispose()` now waits up to 10 seconds for runs that have ended but are still recording their ending, before it closes the journal, and it rejects naming the run when that ending still cannot be recorded. A run whose journal rejects the write of its `completed` status now retries it once, and reports it with an error notice and a rejected `waitForSettled` when it still fails, instead of failing in silence ([#3811](https://github.com/bastani-inc/atomic/issues/3811))
|
|
32
|
+
- A schema-backed workflow stage no longer stays `running` for hours inside one `structured_output` call when a slow model keeps generating without calling the tool. The decision now stops after the `httpIdleTimeoutMs` deadline (10 minutes by default) or the stage's `schemaTimeoutMs`, and the error that names the deadline and each attempt's duration reaches the model and the failed stage unchanged instead of being treated as a structured-output contract failure ([#3806](https://github.com/bastani-inc/atomic/issues/3806))
|
|
33
|
+
|
|
9
34
|
## [0.9.40] - 2026-10-20
|
|
10
35
|
|
|
11
36
|
### Added
|
|
@@ -449,6 +449,8 @@ const decision = await ctx.stage("review-gate", { schema: Decision }).prompt(
|
|
|
449
449
|
|
|
450
450
|
Atomic registers the canonical `structured_output` tool only for schema-enabled items and automatically adds it to explicit `tools` allowlists. The schema is used directly as the tool argument contract. A schema-backed `StageContext` supports one `prompt()` call because the final-answer tool is a single result contract; create another `ctx.stage(..., { schema })` for another structured prompt. If a turn completes without calling `structured_output`, or the tool call fails schema validation, Atomic sends up to three corrective follow-up prompts that include the exact contract/validation error before failing the item. `ctx.task`/`ctx.chain`/`ctx.parallel` results expose the captured value as `result.structured` and keep `result.text` as formatted JSON for handoffs.
|
|
451
451
|
|
|
452
|
+
Each `structured_output` decision has a wall-clock limit that covers its repair attempts, retries, and model fallbacks together. It defaults to the session's `httpIdleTimeoutMs` setting (10 minutes unless changed); set `schemaTimeoutMs` (a positive integer in milliseconds) beside `schema` to change it for one item. An overrun stops the in-flight generation and fails the call with `Structured output decision exceeded its <n>ms deadline; no decision was accepted.` plus how long each attempt took. That is an execution failure, not a structured-output contract failure, and the error text reaches the model unchanged.
|
|
453
|
+
|
|
452
454
|
When an item configures both `schema` and `output`, its successful `structured_output` turn has two separate channels: all ordinary assistant text blocks from that exact message, in order, form the human-readable artifact written to `output`, while the successful tool arguments remain the typed machine-readable workflow result. Atomic never serializes those arguments into the artifact. The runner snapshots the result together with the exact successful tool-call id, so corrective attempts, another call with the same tool name, and later admitted turns cannot replace either side of the pairing. When the successful message has no ordinary text — including after a model-fallback session recreation that leaves the live session without that message — Atomic falls back to the most recent earlier assistant text that made no `structured_output` call; only when no such text exists is the artifact written empty, with the standard empty-artifact warning in the receipt. Items with `schema` but no `output` keep their existing result-text behavior.
|
|
453
455
|
|
|
454
456
|
`subagent` is available as a default workflow-stage tool on the same terms as main chat: a stage is a top-level session, so it can delegate once, and the children it launches cannot delegate further. Delegation is one level deep and nothing configures it. `tools` allowlists apply to bundled extension tools as well as built-ins; if a stage sets `tools`, list every non-mandatory tool it should see. Ordinary `intercom` remains registered and active in every workflow model stage even under `noTools: "all"`, restrictive allowlists, or exclusions. Restrictions on `subagent`, `web_search`, `fetch_content`, and every other tool are unchanged. Bundled `@bastani/subagents` agent definitions are available to the `subagent` tool in workflow stages, including workflows launched from a subagent child process.
|
|
@@ -8,7 +8,7 @@ export type { RunJournalOption, RunJournalSettings } from "./durable/journal/res
|
|
|
8
8
|
export { resolveRunJournal } from "./durable/journal/resolution.js";
|
|
9
9
|
export { openSqlRunJournal, SqlRunJournal } from "./durable/journal/sqlite-run-journal.js";
|
|
10
10
|
export * from "./durable/journal/types.js";
|
|
11
|
-
export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, EffectiveBudget, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageContext, StageExecutionMeta, StageMcpOptions, StageOptions, StageOutputOptions, StagePromptOptions, StageSendUserMessageOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionEvent, StageSessionRuntime, StageSnapshot, StageStatus, StageUserMessageContent, StageUserMessageDelivery, ToolNodeSnapshot, WorkflowAction, WorkflowArtifact, WorkflowBudget, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowExitOptions, WorkflowExitStatus, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildArgs, WorkflowRunChildOptions, WorkflowRunChildOptionsArgument, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowToolContext, WorkflowToolError, WorkflowToolFailure, WorkflowToolOptions, WorkflowToolOutcome, WorkflowToolPrimitive, WorkflowToolReturnOptions, WorkflowToolSuccess, WorkflowToolThrowOptions, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
|
|
11
|
+
export type { AgentSessionAdapter, CompleteAdapter, CompleteStageOpts, EffectiveBudget, GitWorktreeSetupOptions, GitWorktreeSetupResult, PromptAdapter, PromptOptions, ResolvedInputs, RunResult, RunStatus, StageAdapters, StageContext, StageExecutionMeta, StageMcpOptions, StageOptions, StageOutputOptions, StagePromptOptions, StageSendUserMessageOptions, StageSessionCreateOptions, StageSessionCreateResult, StageSessionEvent, StageSessionRuntime, StageSnapshot, StageStatus, StageUserMessageContent, StageUserMessageDelivery, ToolNodeSnapshot, WorkflowAction, WorkflowArtifact, WorkflowBudget, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowControlEvent, WorkflowCustomToolDefinition, WorkflowCustomUiComponent, WorkflowCustomUiFactory, WorkflowCustomUiKeybindings, WorkflowCustomUiOptions, WorkflowCustomUiOverlayHandle, WorkflowCustomUiOverlayOptions, WorkflowCustomUiTheme, WorkflowCustomUiTui, WorkflowDetails, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExecutionPolicy, WorkflowExitOptions, WorkflowExitStatus, WorkflowInputBindings, WorkflowInputSchema, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowIntercomSummary, WorkflowMaxOutput, WorkflowMcpPort, WorkflowModelAttempt, WorkflowModelCatalogPort, WorkflowModelFallbackFields, WorkflowModelInfo, WorkflowModelUsage, WorkflowModelValue, WorkflowOutputMode, WorkflowOutputSchema, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelFailure, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowProgressSummary, WorkflowRunChildArgs, WorkflowRunChildOptions, WorkflowRunChildOptionsArgument, WorkflowRunOutput, WorkflowRuntimeConfig, WorkflowSerializableObject, WorkflowSerializablePrimitive, WorkflowSerializableValue, WorkflowSharedTaskDefaults, WorkflowTaskContext, WorkflowTaskContextInput, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskSessionFields, WorkflowTaskSessionOptions, WorkflowTaskStep, WorkflowThinkingLevel, WorkflowToolContext, WorkflowToolError, WorkflowToolFailure, WorkflowToolOptions, WorkflowToolOutcome, WorkflowToolPrimitive, WorkflowToolReturnOptions, WorkflowToolSuccess, WorkflowToolThrowOptions, WorkflowUIAdapter, WorkflowUIContext, WorkflowWorktreeInputBinding, } from "./shared/authoring-contract.js";
|
|
12
12
|
import type * as AuthoringContract from "./shared/authoring-contract.js";
|
|
13
13
|
import type { AuthoredWorkflowSpec as SharedAuthoredWorkflowSpec, WorkflowInputsFromSchemas, WorkflowOutputsFromSchemas, WorkflowProvidedInputsFromSchemas } from "./shared/workflow-authoring-types.js";
|
|
14
14
|
export type { WorkflowInputsFromSchemas, WorkflowOutputsFromSchemas, WorkflowProvidedInputsFromSchemas, } from "./shared/workflow-authoring-types.js";
|
|
@@ -1 +1,17 @@
|
|
|
1
|
+
import type { RunJournal } from "./types.js";
|
|
1
2
|
export declare const JOURNAL_READ_PAGE_SIZE = 256;
|
|
3
|
+
/** A run's latest event. A run whose history was deleted and recorded again ends with a different event. */
|
|
4
|
+
export interface RunVersion {
|
|
5
|
+
readonly seq: number;
|
|
6
|
+
readonly at: number;
|
|
7
|
+
}
|
|
8
|
+
/** Lets a durable backend re-read only the runs that changed; kept off the public journal shape. */
|
|
9
|
+
export interface RunJournalVersions {
|
|
10
|
+
/** Moves whenever any connection, in this process or another, commits a change to the journal's store. */
|
|
11
|
+
changeToken(): Promise<string>;
|
|
12
|
+
/** Every listed run with its latest event; a run with no events has version `{ seq: 0, at: 0 }`. */
|
|
13
|
+
runVersions(): Promise<ReadonlyMap<string, RunVersion>>;
|
|
14
|
+
}
|
|
15
|
+
export declare function registerRunJournalVersions(journal: RunJournal, versions: RunJournalVersions): void;
|
|
16
|
+
/** Change tracking for a journal that registered it; other journals are re-read in full. */
|
|
17
|
+
export declare function runJournalVersions(journal: RunJournal): RunJournalVersions | undefined;
|
|
@@ -14,6 +14,13 @@ type LegacyEventRow = SqliteRow & {
|
|
|
14
14
|
[c.payload]: string;
|
|
15
15
|
[c.at]: number;
|
|
16
16
|
};
|
|
17
|
+
export type RunVersionRow = SqliteRow & {
|
|
18
|
+
[c.runId]: string;
|
|
19
|
+
[c.seq]: number;
|
|
20
|
+
[c.at]: number;
|
|
21
|
+
};
|
|
22
|
+
/** `seq` and `at` of the latest event of `${runs}.run_id`, through the `(run_id, seq)` primary key. */
|
|
23
|
+
export declare function latestEventColumns(events: string, runs: string): string;
|
|
17
24
|
/**
|
|
18
25
|
* Runs recorded before #3682, kept in the unprefixed `meta`/`runs`/`events`/`leases` tables.
|
|
19
26
|
*
|
|
@@ -32,6 +39,8 @@ export declare class LegacyJournalRuns {
|
|
|
32
39
|
cwd?: string;
|
|
33
40
|
}): Promise<LegacyRunRow[]>;
|
|
34
41
|
find(executor: SqliteExecutor, runId: string): Promise<LegacyRunRow | undefined>;
|
|
42
|
+
/** Latest event of each pending legacy run; the legacy tables are never modified. */
|
|
43
|
+
versions(executor: SqliteExecutor): Promise<RunVersionRow[]>;
|
|
35
44
|
/** Events of an unconverted legacy run, read in place. */
|
|
36
45
|
events(executor: SqliteExecutor, runId: string, fromSeq: number, limit: number): Promise<LegacyEventRow[]>;
|
|
37
46
|
eventByKey(executor: SqliteExecutor, runId: string, key: string): Promise<LegacyEventRow | undefined>;
|
|
@@ -22,6 +22,12 @@ export declare class SqlRunJournal implements RunJournal {
|
|
|
22
22
|
listRuns(filter?: {
|
|
23
23
|
cwd?: string;
|
|
24
24
|
}): Promise<readonly RunSummary[]>;
|
|
25
|
+
/**
|
|
26
|
+
* `data_version` moves when another connection commits and `total_changes()` when this one writes; the
|
|
27
|
+
* table aggregates also catch run changes if the adapter does not serve every statement from one connection.
|
|
28
|
+
*/
|
|
29
|
+
private changeToken;
|
|
30
|
+
private runVersions;
|
|
25
31
|
private requireRun;
|
|
26
32
|
/** Whether this run exists only in the legacy tables, whose events are then read in place. */
|
|
27
33
|
private isUnconvertedLegacyRun;
|