@bastani/atomic 0.9.12 → 0.9.13-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 +20 -0
- package/dist/builtin/intercom/CHANGELOG.md +6 -0
- package/dist/builtin/intercom/README.md +5 -12
- package/dist/builtin/intercom/broker/client.ts +11 -2
- package/dist/builtin/intercom/contact-supervisor-tool.ts +13 -3
- package/dist/builtin/intercom/index-heavy.ts +13 -3
- package/dist/builtin/intercom/index.ts +43 -19
- package/dist/builtin/intercom/intercom-utils.ts +15 -29
- package/dist/builtin/intercom/package.json +1 -1
- package/dist/builtin/intercom/source-ownership.ts +9 -12
- package/dist/builtin/mcp/CHANGELOG.md +6 -0
- package/dist/builtin/mcp/README.md +3 -1
- package/dist/builtin/mcp/index.ts +10 -16
- package/dist/builtin/mcp/package.json +1 -1
- package/dist/builtin/mcp/startup-warmup.ts +20 -8
- package/dist/builtin/subagents/CHANGELOG.md +30 -0
- package/dist/builtin/subagents/README.md +22 -30
- package/dist/builtin/subagents/package.json +1 -1
- package/dist/builtin/subagents/src/extension/doctor.ts +1 -1
- package/dist/builtin/subagents/src/extension/fanout-child.ts +76 -56
- package/dist/builtin/subagents/src/extension/index.ts +23 -32
- package/dist/builtin/subagents/src/extension/startup-maintenance.ts +25 -44
- package/dist/builtin/subagents/src/intercom/result-intercom.ts +7 -7
- package/dist/builtin/subagents/src/runs/background/async-job-tracker.ts +166 -434
- package/dist/builtin/subagents/src/runs/background/notify.ts +29 -8
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-dynamic-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-runner.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-parallel-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/chain-execution-sequential-step.ts +2 -2
- package/dist/builtin/subagents/src/runs/foreground/execution-run-sync.ts +1 -281
- package/dist/builtin/subagents/src/runs/foreground/execution-structured-retries.ts +11 -75
- package/dist/builtin/subagents/src/runs/foreground/inprocess-run-sync.ts +457 -0
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-async.ts +119 -246
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-chain.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-context.ts +18 -9
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel-task.ts +1 -1
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-parallel.ts +4 -4
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-resume.ts +1 -646
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-runtime.ts +2 -7
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-single.ts +5 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-status.ts +7 -8
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor-types.ts +14 -5
- package/dist/builtin/subagents/src/runs/foreground/subagent-executor.ts +158 -93
- package/dist/builtin/subagents/src/runs/inprocess/background-single.ts +179 -0
- package/dist/builtin/subagents/src/runs/inprocess/background.ts +89 -0
- package/dist/builtin/subagents/src/runs/inprocess/child-policy.ts +27 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-registry.ts +55 -0
- package/dist/builtin/subagents/src/runs/inprocess/control-status.ts +106 -0
- package/dist/builtin/subagents/src/runs/inprocess/index.ts +50 -0
- package/dist/builtin/subagents/src/runs/inprocess/nested-routing.ts +218 -0
- package/dist/builtin/subagents/src/runs/{shared/subagent-prompt-runtime.ts → inprocess/prompt-behavior.ts} +37 -75
- package/dist/builtin/subagents/src/runs/inprocess/runner.ts +1138 -0
- package/dist/builtin/subagents/src/runs/{shared/nested-events.ts → inprocess/runtime-support/nested-api.ts} +13 -7
- package/dist/builtin/subagents/src/runs/{shared/nested-events-control.ts → inprocess/runtime-support/nested-control.ts} +18 -17
- package/dist/builtin/subagents/src/runs/{shared/nested-events-core.ts → inprocess/runtime-support/nested-core.ts} +14 -61
- package/dist/builtin/subagents/src/runs/{shared/nested-events-projection.ts → inprocess/runtime-support/nested-projection.ts} +4 -10
- package/dist/builtin/subagents/src/runs/{shared/nested-events-registry.ts → inprocess/runtime-support/nested-registry.ts} +19 -4
- package/dist/builtin/subagents/src/runs/{shared/nested-render.ts → inprocess/runtime-support/nested-rendering.ts} +3 -3
- package/dist/builtin/subagents/src/runs/{shared/nested-events-sanitize.ts → inprocess/runtime-support/nested-sanitize.ts} +3 -3
- package/dist/builtin/subagents/src/runs/inprocess.ts +1 -0
- package/dist/builtin/subagents/src/runs/shared/dynamic-fanout.ts +10 -4
- package/dist/builtin/subagents/src/runs/shared/model-candidate-filter.ts +0 -1
- package/dist/builtin/subagents/src/runs/shared/model-fallback.ts +15 -492
- package/dist/builtin/subagents/src/runs/shared/parallel-utils.ts +13 -11
- package/dist/builtin/subagents/src/runs/shared/run-history.ts +3 -5
- package/dist/builtin/subagents/src/runs/shared/single-output.ts +4 -4
- package/dist/builtin/subagents/src/runs/shared/workflow-graph.ts +5 -5
- package/dist/builtin/subagents/src/shared/types-async.ts +0 -1
- package/dist/builtin/subagents/src/shared/types-config.ts +18 -0
- package/dist/builtin/subagents/src/shared/types-results.ts +9 -2
- package/dist/builtin/subagents/src/slash/prompt-template-bridge.ts +2 -3
- package/dist/builtin/subagents/src/slash/slash-live-state.ts +2 -2
- package/dist/builtin/subagents/src/tui/render-chain-graph.ts +10 -4
- package/dist/builtin/subagents/src/tui/render-event-formatting.ts +12 -11
- package/dist/builtin/subagents/src/tui/render-result-compact.ts +49 -12
- package/dist/builtin/subagents/src/tui/render-result.ts +46 -17
- package/dist/builtin/subagents/src/tui/render-stable-output.ts +1 -1
- package/dist/builtin/subagents/src/tui/render-status-progress.ts +8 -5
- package/dist/builtin/subagents/src/tui/render-widget-graph.ts +0 -8
- package/dist/builtin/subagents/src/tui/render-widget.ts +0 -24
- package/dist/builtin/web-access/package.json +1 -1
- package/dist/builtin/workflows/CHANGELOG.md +25 -0
- package/dist/builtin/workflows/README.md +13 -3
- package/dist/builtin/workflows/package.json +1 -1
- package/dist/builtin/workflows/src/durable/backend.ts +7 -0
- package/dist/builtin/workflows/src/durable/dbos-metadata.ts +11 -1
- package/dist/builtin/workflows/src/durable/resume-runtime.ts +1 -0
- package/dist/builtin/workflows/src/durable/tool-primitive.ts +4 -28
- package/dist/builtin/workflows/src/durable/types.ts +5 -0
- package/dist/builtin/workflows/src/engine/run.ts +17 -1
- package/dist/builtin/workflows/src/extension/atomic-stage-session.ts +12 -39
- package/dist/builtin/workflows/src/extension/config-file-loader.ts +10 -1
- package/dist/builtin/workflows/src/extension/config-loader.ts +1 -1
- package/dist/builtin/workflows/src/extension/dispatcher.ts +4 -0
- package/dist/builtin/workflows/src/extension/index.bundle.mjs +1151 -737
- package/dist/builtin/workflows/src/extension/lifecycle-notifications.ts +303 -38
- package/dist/builtin/workflows/src/extension/render-result.ts +4 -0
- package/dist/builtin/workflows/src/extension/runtime-durable-resume.ts +6 -3
- package/dist/builtin/workflows/src/extension/runtime.ts +7 -1
- package/dist/builtin/workflows/src/extension/wiring.ts +53 -11
- package/dist/builtin/workflows/src/extension/workflow-command-registration.ts +12 -3
- package/dist/builtin/workflows/src/extension/workflow-durable-resume-command.ts +5 -2
- package/dist/builtin/workflows/src/extension/workflow-run-control-command.ts +9 -7
- package/dist/builtin/workflows/src/extension/workflow-status-summary.ts +11 -0
- package/dist/builtin/workflows/src/extension/workflow-tool-content.ts +18 -1
- package/dist/builtin/workflows/src/extension/workflow-tool-control.ts +10 -8
- package/dist/builtin/workflows/src/extension/workflow-tool.ts +9 -4
- package/dist/builtin/workflows/src/runs/background/quit.ts +28 -4
- package/dist/builtin/workflows/src/runs/background/resume-acknowledgements.ts +2 -1
- package/dist/builtin/workflows/src/runs/background/status.ts +55 -8
- package/dist/builtin/workflows/src/runs/foreground/executor-direct-helpers.ts +4 -0
- package/dist/builtin/workflows/src/runs/foreground/executor-prompt-nodes.ts +3 -1
- package/dist/builtin/workflows/src/runs/foreground/executor-stage-control.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-context.ts +1 -1
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-controller.ts +688 -38
- package/dist/builtin/workflows/src/runs/foreground/stage-runner-types.ts +3 -1
- package/dist/builtin/workflows/src/runs/shared/model-fallback-failures.ts +19 -514
- package/dist/builtin/workflows/src/runs/shared/retry.ts +44 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.d.ts +5 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-stage.ts +6 -0
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.d.ts +5 -1
- package/dist/builtin/workflows/src/shared/authoring-contract-ui.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore-helpers.ts +5 -0
- package/dist/builtin/workflows/src/shared/persistence-restore.ts +3 -0
- package/dist/builtin/workflows/src/shared/persistence-session-entries.ts +4 -0
- package/dist/builtin/workflows/src/shared/run-indicator-status.ts +75 -0
- package/dist/builtin/workflows/src/shared/store-public-types.ts +43 -7
- package/dist/builtin/workflows/src/shared/store-run-methods.ts +42 -8
- package/dist/builtin/workflows/src/shared/store-stage-methods.ts +31 -8
- package/dist/builtin/workflows/src/shared/store-types.ts +34 -0
- package/dist/builtin/workflows/src/shared/timing.ts +10 -0
- package/dist/builtin/workflows/src/tui/chat-surface-message.ts +22 -2
- package/dist/builtin/workflows/src/tui/session-list.ts +1 -1
- package/dist/builtin/workflows/src/tui/session-overlays.ts +14 -10
- package/dist/builtin/workflows/src/tui/session-picker.ts +20 -4
- package/dist/builtin/workflows/src/tui/status-list.ts +31 -47
- package/dist/builtin/workflows/src/tui/store-widget-installer.ts +9 -1
- package/dist/builtin/workflows/src/tui/widget.ts +16 -46
- package/dist/core/agent-session-auto-compaction.d.ts.map +1 -1
- package/dist/core/agent-session-auto-compaction.js +54 -11
- package/dist/core/agent-session-auto-compaction.js.map +1 -1
- package/dist/core/agent-session-events.d.ts.map +1 -1
- package/dist/core/agent-session-events.js +49 -14
- package/dist/core/agent-session-events.js.map +1 -1
- package/dist/core/agent-session-methods.d.ts +13 -0
- 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-models.d.ts.map +1 -1
- package/dist/core/agent-session-models.js +12 -1
- package/dist/core/agent-session-models.js.map +1 -1
- package/dist/core/agent-session-prompt.d.ts.map +1 -1
- package/dist/core/agent-session-prompt.js +4 -0
- package/dist/core/agent-session-prompt.js.map +1 -1
- package/dist/core/agent-session-retry.d.ts +21 -4
- package/dist/core/agent-session-retry.d.ts.map +1 -1
- package/dist/core/agent-session-retry.js +232 -106
- package/dist/core/agent-session-retry.js.map +1 -1
- package/dist/core/agent-session-state.d.ts.map +1 -1
- package/dist/core/agent-session-state.js +2 -1
- package/dist/core/agent-session-state.js.map +1 -1
- package/dist/core/agent-session-tool-hooks.d.ts.map +1 -1
- package/dist/core/agent-session-tool-hooks.js +12 -0
- package/dist/core/agent-session-tool-hooks.js.map +1 -1
- package/dist/core/agent-session-tool-registry.d.ts.map +1 -1
- package/dist/core/agent-session-tool-registry.js +1 -1
- package/dist/core/agent-session-tool-registry.js.map +1 -1
- package/dist/core/agent-session-types.d.ts +3 -1
- package/dist/core/agent-session-types.d.ts.map +1 -1
- package/dist/core/agent-session-types.js.map +1 -1
- package/dist/core/agent-session.d.ts +12 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +7 -0
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/context-types.d.ts +25 -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/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner-context.d.ts +2 -1
- package/dist/core/extensions/runner-context.d.ts.map +1 -1
- package/dist/core/extensions/runner-context.js +4 -0
- package/dist/core/extensions/runner-context.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +3 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/model-fallback-failures.d.ts +30 -0
- package/dist/core/model-fallback-failures.d.ts.map +1 -0
- package/dist/core/model-fallback-failures.js +610 -0
- package/dist/core/model-fallback-failures.js.map +1 -0
- package/dist/core/retry-policy.d.ts +30 -0
- package/dist/core/retry-policy.d.ts.map +1 -0
- package/dist/core/retry-policy.js +25 -0
- package/dist/core/retry-policy.js.map +1 -0
- package/dist/core/sdk-types.d.ts +8 -2
- package/dist/core/sdk-types.d.ts.map +1 -1
- package/dist/core/sdk-types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +6 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager-core.d.ts +2 -0
- package/dist/core/session-manager-core.d.ts.map +1 -1
- package/dist/core/session-manager-core.js +7 -0
- package/dist/core/session-manager-core.js.map +1 -1
- package/dist/index-extensions.d.ts +1 -1
- package/dist/index-extensions.d.ts.map +1 -1
- package/dist/index-extensions.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/docs/intercom.md +5 -10
- package/docs/settings.md +7 -1
- package/docs/subagents.md +19 -19
- package/docs/workflows.md +21 -5
- package/examples/extensions/gondolin/package-lock.json +3 -3
- package/npm-shrinkwrap.json +29 -29
- package/package.json +2 -2
- package/dist/builtin/subagents/src/runs/background/async-event-journal.ts +0 -112
- package/dist/builtin/subagents/src/runs/background/async-execution-chain.ts +0 -543
- package/dist/builtin/subagents/src/runs/background/async-execution-common.ts +0 -140
- package/dist/builtin/subagents/src/runs/background/async-execution-single.ts +0 -279
- package/dist/builtin/subagents/src/runs/background/async-execution-types.ts +0 -99
- package/dist/builtin/subagents/src/runs/background/async-execution.ts +0 -17
- package/dist/builtin/subagents/src/runs/background/async-resume.ts +0 -402
- package/dist/builtin/subagents/src/runs/background/async-status.ts +0 -411
- package/dist/builtin/subagents/src/runs/background/completion-claims.ts +0 -196
- package/dist/builtin/subagents/src/runs/background/completion-dedupe.ts +0 -102
- package/dist/builtin/subagents/src/runs/background/parallel-groups.ts +0 -59
- package/dist/builtin/subagents/src/runs/background/result-delivery-processor.ts +0 -300
- package/dist/builtin/subagents/src/runs/background/result-file-claims.ts +0 -166
- package/dist/builtin/subagents/src/runs/background/result-quarantine.ts +0 -77
- package/dist/builtin/subagents/src/runs/background/result-retry-scheduler.ts +0 -48
- package/dist/builtin/subagents/src/runs/background/result-status.ts +0 -87
- package/dist/builtin/subagents/src/runs/background/result-watcher-data.ts +0 -72
- package/dist/builtin/subagents/src/runs/background/result-watcher.ts +0 -320
- package/dist/builtin/subagents/src/runs/background/run-id-resolver.ts +0 -105
- package/dist/builtin/subagents/src/runs/background/run-status.ts +0 -358
- package/dist/builtin/subagents/src/runs/background/stale-run-reconciler.ts +0 -457
- package/dist/builtin/subagents/src/runs/background/subagent-runner-dynamic.ts +0 -376
- package/dist/builtin/subagents/src/runs/background/subagent-runner-finalize.ts +0 -150
- package/dist/builtin/subagents/src/runs/background/subagent-runner-output.ts +0 -109
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel-helpers.ts +0 -128
- package/dist/builtin/subagents/src/runs/background/subagent-runner-parallel.ts +0 -309
- package/dist/builtin/subagents/src/runs/background/subagent-runner-sequential.ts +0 -173
- package/dist/builtin/subagents/src/runs/background/subagent-runner-state.ts +0 -578
- package/dist/builtin/subagents/src/runs/background/subagent-runner-step.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-streaming.ts +0 -330
- package/dist/builtin/subagents/src/runs/background/subagent-runner-types.ts +0 -210
- package/dist/builtin/subagents/src/runs/background/subagent-runner-utils.ts +0 -69
- package/dist/builtin/subagents/src/runs/background/subagent-runner.ts +0 -90
- package/dist/builtin/subagents/src/runs/background/top-level-async.ts +0 -12
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-control.ts +0 -140
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-finalize.ts +0 -108
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt-types.ts +0 -17
- package/dist/builtin/subagents/src/runs/foreground/execution-attempt.ts +0 -558
- package/dist/builtin/subagents/src/runs/shared/attempt-watchdog.ts +0 -126
- package/dist/builtin/subagents/src/runs/shared/final-drain.ts +0 -39
- package/dist/builtin/subagents/src/runs/shared/pi-args.ts +0 -339
- package/dist/builtin/subagents/src/runs/shared/pi-spawn.ts +0 -165
- package/dist/builtin/subagents/src/runs/shared/spawn-env.ts +0 -21
- package/dist/builtin/subagents/src/shared/post-exit-stdio-guard.ts +0 -86
- /package/dist/builtin/subagents/src/runs/{shared/nested-path.ts → inprocess/runtime-support/nested-paths.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AgentSession, CreateAgentSessionOptions, PromptOptions } from "@bastani/atomic";
|
|
1
|
+
import type { AgentSession, CreateAgentSessionOptions, PromptOptions, SettingsManager } from "@bastani/atomic";
|
|
2
2
|
import type {
|
|
3
3
|
CompleteStageOpts,
|
|
4
4
|
StageContext,
|
|
@@ -18,9 +18,11 @@ export type WorkflowFastModeSettings = {
|
|
|
18
18
|
readonly chat: boolean;
|
|
19
19
|
readonly workflow: boolean;
|
|
20
20
|
};
|
|
21
|
+
export type WorkflowRetrySettings = ReturnType<SettingsManager["getRetrySettings"]>;
|
|
21
22
|
|
|
22
23
|
export type WorkflowFastModeSettingsManager = {
|
|
23
24
|
getCodexFastModeSettings(): WorkflowFastModeSettings;
|
|
25
|
+
getRetrySettings?(): WorkflowRetrySettings;
|
|
24
26
|
};
|
|
25
27
|
|
|
26
28
|
export type StageUserMessageDeliveryAction = "prompt" | "steer" | "followUp" | "handled";
|
|
@@ -1,514 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/service\s*unavailable/i,
|
|
21
|
-
/network/i,
|
|
22
|
-
/fetch/i,
|
|
23
|
-
/socket/i,
|
|
24
|
-
/connection\s*refused/i,
|
|
25
|
-
/upstream/i,
|
|
26
|
-
/timeout/i,
|
|
27
|
-
/timed\s*out/i,
|
|
28
|
-
/\b50[0-4]\b/,
|
|
29
|
-
];
|
|
30
|
-
|
|
31
|
-
const NON_RETRYABLE_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
32
|
-
/command failed/i,
|
|
33
|
-
/tests? failed/i,
|
|
34
|
-
/shell/i,
|
|
35
|
-
/missing file/i,
|
|
36
|
-
/no such file/i,
|
|
37
|
-
/cancel/i,
|
|
38
|
-
/abort/i,
|
|
39
|
-
/interrupted/i,
|
|
40
|
-
];
|
|
41
|
-
|
|
42
|
-
const CANCELLED_FAILURE_PATTERNS: readonly RegExp[] = [/cancel/i, /abort/i, /interrupted/i];
|
|
43
|
-
|
|
44
|
-
export type ModelFallbackFailureKind =
|
|
45
|
-
| "auth_on_candidate_provider"
|
|
46
|
-
| "rate_limit"
|
|
47
|
-
| "provider_unavailable"
|
|
48
|
-
| "network_timeout"
|
|
49
|
-
| "transport_error"
|
|
50
|
-
| "model_unavailable"
|
|
51
|
-
| "request_incompatible"
|
|
52
|
-
| "cancelled"
|
|
53
|
-
| "task_failure"
|
|
54
|
-
| "unknown";
|
|
55
|
-
|
|
56
|
-
export type ModelFallbackFailureSource =
|
|
57
|
-
| "assistant_message"
|
|
58
|
-
| "diagnostic"
|
|
59
|
-
| "throw"
|
|
60
|
-
| "structured"
|
|
61
|
-
| "string_fallback";
|
|
62
|
-
|
|
63
|
-
export interface ModelFallbackFailureSignal {
|
|
64
|
-
readonly kind: ModelFallbackFailureKind;
|
|
65
|
-
readonly message: string;
|
|
66
|
-
readonly source: ModelFallbackFailureSource;
|
|
67
|
-
readonly stopReason?: string;
|
|
68
|
-
readonly status?: number;
|
|
69
|
-
readonly code?: string | number;
|
|
70
|
-
readonly name?: string;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const FALLBACKABLE_FAILURE_KINDS: ReadonlySet<ModelFallbackFailureKind> = new Set([
|
|
74
|
-
"auth_on_candidate_provider",
|
|
75
|
-
"rate_limit",
|
|
76
|
-
"provider_unavailable",
|
|
77
|
-
"network_timeout",
|
|
78
|
-
"transport_error",
|
|
79
|
-
"model_unavailable",
|
|
80
|
-
"request_incompatible",
|
|
81
|
-
]);
|
|
82
|
-
|
|
83
|
-
function asRecord(value: unknown): Record<string, unknown> | undefined {
|
|
84
|
-
return value !== null && typeof value === "object" ? (value as Record<string, unknown>) : undefined;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function field(value: unknown, key: string): unknown {
|
|
88
|
-
return asRecord(value)?.[key];
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function stringField(value: unknown, key: string): string | undefined {
|
|
92
|
-
const raw = field(value, key);
|
|
93
|
-
return typeof raw === "string" && raw.trim().length > 0 ? raw : undefined;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
function errorName(value: unknown): string | undefined {
|
|
97
|
-
return value instanceof Error ? value.name : stringField(value, "name");
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
function directMessageFrom(value: unknown): string | undefined {
|
|
101
|
-
return stringField(value, "errorMessage") ?? stringField(value, "message") ?? stringField(value, "statusText");
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function integerFrom(value: unknown): number | undefined {
|
|
105
|
-
if (typeof value === "number" && Number.isInteger(value)) return value;
|
|
106
|
-
if (typeof value !== "string" || value.trim().length === 0) return undefined;
|
|
107
|
-
const parsed = Number(value.trim());
|
|
108
|
-
return Number.isInteger(parsed) ? parsed : undefined;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
function statusFrom(value: unknown): number | undefined {
|
|
112
|
-
return (
|
|
113
|
-
integerFrom(field(value, "status")) ??
|
|
114
|
-
integerFrom(field(value, "statusCode")) ??
|
|
115
|
-
integerFrom(field(value, "httpStatus"))
|
|
116
|
-
);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
function codeFrom(value: unknown): string | number | undefined {
|
|
120
|
-
const rawCode = field(value, "code");
|
|
121
|
-
return typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function stopReasonFrom(value: unknown): string | undefined {
|
|
125
|
-
return stringField(value, "stopReason");
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
function finishReasonFrom(value: unknown): string | undefined {
|
|
129
|
-
return stringField(value, "finish_reason") ?? stringField(value, "finishReason");
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
function causeOf(value: unknown): unknown {
|
|
133
|
-
return value instanceof Error ? value.cause : field(value, "cause");
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function diagnosticErrors(value: unknown): readonly unknown[] {
|
|
137
|
-
const diagnostics = field(value, "diagnostics");
|
|
138
|
-
if (!Array.isArray(diagnostics)) return [];
|
|
139
|
-
const errors: unknown[] = [];
|
|
140
|
-
for (const diagnostic of diagnostics) {
|
|
141
|
-
const diagnosticError = field(diagnostic, "error");
|
|
142
|
-
errors.push(diagnosticError ?? diagnostic);
|
|
143
|
-
}
|
|
144
|
-
return errors;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
function normalizeCode(value: string | number | undefined): string | undefined {
|
|
148
|
-
if (value === undefined) return undefined;
|
|
149
|
-
const normalized = String(value)
|
|
150
|
-
.trim()
|
|
151
|
-
.toLowerCase()
|
|
152
|
-
.replace(/[^a-z0-9]+/g, "_")
|
|
153
|
-
.replace(/^_+|_+$/g, "");
|
|
154
|
-
return normalized.length > 0 ? normalized : undefined;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function kindFromStatus(status: number | undefined): ModelFallbackFailureKind | undefined {
|
|
158
|
-
switch (status) {
|
|
159
|
-
case 400:
|
|
160
|
-
case 413:
|
|
161
|
-
case 422:
|
|
162
|
-
return "request_incompatible";
|
|
163
|
-
case 401:
|
|
164
|
-
case 403:
|
|
165
|
-
return "auth_on_candidate_provider";
|
|
166
|
-
case 408:
|
|
167
|
-
return "network_timeout";
|
|
168
|
-
case 404:
|
|
169
|
-
return "model_unavailable";
|
|
170
|
-
case 429:
|
|
171
|
-
return "rate_limit";
|
|
172
|
-
default:
|
|
173
|
-
if (status !== undefined && status >= 500 && status <= 599) return "provider_unavailable";
|
|
174
|
-
return undefined;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function refusalKindFromCode(code: string | number | undefined): ModelFallbackFailureKind | undefined {
|
|
179
|
-
const normalizedCode = normalizeCode(code);
|
|
180
|
-
if (normalizedCode === undefined) return undefined;
|
|
181
|
-
if (normalizedCode.includes("content_filter") || normalizedCode.includes("contentfilter")) return "task_failure";
|
|
182
|
-
if (normalizedCode.includes("safety") || normalizedCode.includes("policy")) return "task_failure";
|
|
183
|
-
switch (normalizedCode) {
|
|
184
|
-
case "blocked":
|
|
185
|
-
case "blocked_by_provider":
|
|
186
|
-
case "blocked_by_safety":
|
|
187
|
-
case "blocked_by_policy":
|
|
188
|
-
case "provider_refusal":
|
|
189
|
-
case "refusal":
|
|
190
|
-
case "tool_refusal":
|
|
191
|
-
case "tool_call_refusal":
|
|
192
|
-
case "tool_use_refusal":
|
|
193
|
-
return "task_failure";
|
|
194
|
-
default:
|
|
195
|
-
return undefined;
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
const REQUEST_INCOMPATIBLE_CODES: ReadonlySet<string> = new Set([
|
|
200
|
-
"invalid_request",
|
|
201
|
-
"invalid_request_error",
|
|
202
|
-
"bad_request",
|
|
203
|
-
"context_length_exceeded",
|
|
204
|
-
"request_too_large",
|
|
205
|
-
"too_large",
|
|
206
|
-
"request_entity_too_large",
|
|
207
|
-
"max_tokens",
|
|
208
|
-
"max_context_length",
|
|
209
|
-
"context_window_exceeded",
|
|
210
|
-
]);
|
|
211
|
-
function requestIncompatibleKindFromCode(code: string | number | undefined): ModelFallbackFailureKind | undefined {
|
|
212
|
-
const normalizedCode = normalizeCode(code);
|
|
213
|
-
return normalizedCode !== undefined && REQUEST_INCOMPATIBLE_CODES.has(normalizedCode)
|
|
214
|
-
? "request_incompatible"
|
|
215
|
-
: undefined;
|
|
216
|
-
}
|
|
217
|
-
function kindFromCode(code: string | number | undefined): ModelFallbackFailureKind | undefined {
|
|
218
|
-
const normalizedCode = normalizeCode(code);
|
|
219
|
-
if (normalizedCode === undefined) return undefined;
|
|
220
|
-
const refusalKind = refusalKindFromCode(code);
|
|
221
|
-
if (refusalKind !== undefined) return refusalKind;
|
|
222
|
-
const httpStatusKind = kindFromStatus(integerFrom(code));
|
|
223
|
-
if (httpStatusKind !== undefined) return httpStatusKind;
|
|
224
|
-
const requestIncompatibleKind = requestIncompatibleKindFromCode(code);
|
|
225
|
-
if (requestIncompatibleKind !== undefined) return requestIncompatibleKind;
|
|
226
|
-
|
|
227
|
-
switch (normalizedCode) {
|
|
228
|
-
case "auth":
|
|
229
|
-
case "auth_required":
|
|
230
|
-
case "authentication_required":
|
|
231
|
-
case "unauthorized":
|
|
232
|
-
case "forbidden":
|
|
233
|
-
case "invalid_api_key":
|
|
234
|
-
case "missing_api_key":
|
|
235
|
-
case "invalid_key":
|
|
236
|
-
return "auth_on_candidate_provider";
|
|
237
|
-
case "etimedout":
|
|
238
|
-
case "econnreset":
|
|
239
|
-
case "econnrefused":
|
|
240
|
-
case "enotfound":
|
|
241
|
-
case "eai_again":
|
|
242
|
-
case "fetch_failed":
|
|
243
|
-
case "network_error":
|
|
244
|
-
case "timeout":
|
|
245
|
-
case "timeout_error":
|
|
246
|
-
case "und_err_connect_timeout":
|
|
247
|
-
return "network_timeout";
|
|
248
|
-
case "rate_limit":
|
|
249
|
-
case "rate_limit_exceeded":
|
|
250
|
-
case "too_many_requests":
|
|
251
|
-
case "quota_exceeded":
|
|
252
|
-
case "insufficient_quota":
|
|
253
|
-
case "usage_limit":
|
|
254
|
-
case "usage_limit_reached":
|
|
255
|
-
case "usage_limit_exceeded":
|
|
256
|
-
return "rate_limit";
|
|
257
|
-
case "aborterror":
|
|
258
|
-
case "aborted":
|
|
259
|
-
case "cancelled":
|
|
260
|
-
case "canceled":
|
|
261
|
-
return "cancelled";
|
|
262
|
-
case "model_not_found":
|
|
263
|
-
case "model_unavailable":
|
|
264
|
-
case "model_disabled":
|
|
265
|
-
case "unknown_model":
|
|
266
|
-
return "model_unavailable";
|
|
267
|
-
case "provider_error":
|
|
268
|
-
case "api_error":
|
|
269
|
-
case "service_unavailable":
|
|
270
|
-
case "temporarily_unavailable":
|
|
271
|
-
case "overloaded":
|
|
272
|
-
return "provider_unavailable";
|
|
273
|
-
default:
|
|
274
|
-
return undefined;
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
|
|
278
|
-
const REQUEST_INCOMPATIBLE_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
279
|
-
/\bcontext[_\s-]?length(?:[_\s-]?exceeded)?\b/i,
|
|
280
|
-
/\bcontext[_\s-]?window(?:[_\s-]?exceeded)?\b/i,
|
|
281
|
-
/\bmax[_\s-]?context\b/i,
|
|
282
|
-
/\bmax[_\s-]?tokens?\b/i,
|
|
283
|
-
/\brequest(?:[_\s-]?entity)?[_\s-]?too[_\s-]?large\b/i,
|
|
284
|
-
/\btoo[_\s-]?large\b/i,
|
|
285
|
-
/\b(?:unsupported|unknown|invalid)\s+(?:tool|parameter|function)\b/i,
|
|
286
|
-
/\b(?:tool|parameter|function)\s+(?:not\s+(?:supported|found|allowed)|unknown|invalid)\b/i,
|
|
287
|
-
/\binvalid[_\s-]?request(?:[_\s-]?error)?\b/i,
|
|
288
|
-
/\bbad[_\s-]?request\b/i,
|
|
289
|
-
];
|
|
290
|
-
const PROVIDER_REFUSAL_FAILURE_PATTERNS: readonly RegExp[] = [
|
|
291
|
-
/\bfinish[_\s-]?reason\b[^\n]*\bcontent[_\s-]?filter\b/i,
|
|
292
|
-
/\bcontent[_\s-]?filter(?:ed|ing)?\b/i,
|
|
293
|
-
/\b(?:safety|policy)\b[^\n]*\b(?:refus(?:e|al|ed|es|ing)?|block(?:ed|ing)?|filter(?:ed|ing)?|violat(?:e|ion|ed|ing)?|disallow(?:ed|ing)?|reject(?:ed|ion|ing)?)\b/i,
|
|
294
|
-
/\b(?:refus(?:e|al|ed|es|ing)?|block(?:ed|ing)?|filter(?:ed|ing)?|violat(?:e|ion|ed|ing)?|disallow(?:ed|ing)?|reject(?:ed|ion|ing)?)\b[^\n]*\b(?:safety|policy)\b/i,
|
|
295
|
-
/\btool[_\s-]?(?:call|use)?[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
296
|
-
/\btool(?:\s+call|\s+use)?\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b/i,
|
|
297
|
-
/\brefus(?:e|al|ed|es|ing)?\b[^\n]*\btool(?:\s+call|\s+use)?\b/i,
|
|
298
|
-
/\bprovider[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
299
|
-
/\bprovider\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b[^\n]*\b(?:prompt|request|content|policy|safety)\b/i,
|
|
300
|
-
];
|
|
301
|
-
|
|
302
|
-
const TRANSPORT_OUTAGE_FAILURE_PATTERNS: readonly RegExp[] = [/^connection\s+error\.?$/i, /^fetch\s+failed\.?$/i];
|
|
303
|
-
|
|
304
|
-
function transportOutageKindFromMessage(message: string): ModelFallbackFailureKind | undefined {
|
|
305
|
-
return TRANSPORT_OUTAGE_FAILURE_PATTERNS.some((pattern) => pattern.test(message.trim()))
|
|
306
|
-
? "transport_error"
|
|
307
|
-
: undefined;
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
function refusalKindFromMessage(message: string): ModelFallbackFailureKind | undefined {
|
|
311
|
-
if (CANCELLED_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "cancelled";
|
|
312
|
-
if (NON_RETRYABLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "task_failure";
|
|
313
|
-
if (PROVIDER_REFUSAL_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "task_failure";
|
|
314
|
-
return undefined;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
function fallbackKindFromMessage(message: string, name: string | undefined): ModelFallbackFailureKind | undefined {
|
|
318
|
-
const refusalKind = refusalKindFromMessage(message);
|
|
319
|
-
if (refusalKind !== undefined) return refusalKind;
|
|
320
|
-
const transportOutageKind = transportOutageKindFromMessage(message);
|
|
321
|
-
if (transportOutageKind !== undefined) return transportOutageKind;
|
|
322
|
-
if (REQUEST_INCOMPATIBLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return "request_incompatible";
|
|
323
|
-
const nameKind = kindFromCode(name);
|
|
324
|
-
if (nameKind !== undefined) return nameKind;
|
|
325
|
-
if (!RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(message))) return undefined;
|
|
326
|
-
if (/rate\s*limit|too\s*many\s*requests|\b429\b|quota|usage[\s_-]*limit|billing|credit/i.test(message))
|
|
327
|
-
return "rate_limit";
|
|
328
|
-
if (/auth|unauthori[sz]ed|\b40[13]\b|api\s*key|token\s*expired|forbidden|invalid\s*key/i.test(message))
|
|
329
|
-
return "auth_on_candidate_provider";
|
|
330
|
-
if (
|
|
331
|
-
/model.*(?:unavailable|disabled|not\s*found|unknown)|(?:unavailable|disabled|not\s*found|unknown).*model/i.test(
|
|
332
|
-
message,
|
|
333
|
-
)
|
|
334
|
-
)
|
|
335
|
-
return "model_unavailable";
|
|
336
|
-
if (/network|fetch|socket|connection\s*refused|timeout|timed\s*out/i.test(message)) return "network_timeout";
|
|
337
|
-
return "provider_unavailable";
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
function signalSource(value: unknown, fallback: ModelFallbackFailureSource | undefined): ModelFallbackFailureSource {
|
|
341
|
-
if (fallback !== undefined) return fallback;
|
|
342
|
-
if (stopReasonFrom(value) !== undefined || diagnosticErrors(value).length > 0) return "assistant_message";
|
|
343
|
-
if (value instanceof Error) return "throw";
|
|
344
|
-
return "structured";
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
function makeSignal(
|
|
348
|
-
kind: ModelFallbackFailureKind,
|
|
349
|
-
value: unknown,
|
|
350
|
-
source: ModelFallbackFailureSource | undefined,
|
|
351
|
-
): ModelFallbackFailureSignal {
|
|
352
|
-
const status = statusFrom(value);
|
|
353
|
-
const code = codeFrom(value);
|
|
354
|
-
const name = errorName(value);
|
|
355
|
-
const stopReason = stopReasonFrom(value);
|
|
356
|
-
return {
|
|
357
|
-
kind,
|
|
358
|
-
message: errorMessage(value),
|
|
359
|
-
source: signalSource(value, source),
|
|
360
|
-
...(stopReason !== undefined ? { stopReason } : {}),
|
|
361
|
-
...(status !== undefined ? { status } : {}),
|
|
362
|
-
...(code !== undefined ? { code } : {}),
|
|
363
|
-
...(name !== undefined ? { name } : {}),
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
function fallbackSignalFromDirectMessage(
|
|
368
|
-
value: unknown,
|
|
369
|
-
source: ModelFallbackFailureSource | undefined,
|
|
370
|
-
): ModelFallbackFailureSignal | undefined {
|
|
371
|
-
const message = directMessageFrom(value);
|
|
372
|
-
if (message === undefined) return undefined;
|
|
373
|
-
const kind = fallbackKindFromMessage(message, errorName(value));
|
|
374
|
-
return kind === undefined ? undefined : makeSignal(kind, value, source);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
function fallbackSignalFromMessage(
|
|
378
|
-
value: unknown,
|
|
379
|
-
source: ModelFallbackFailureSource | undefined,
|
|
380
|
-
): ModelFallbackFailureSignal | undefined {
|
|
381
|
-
const message = errorMessage(value);
|
|
382
|
-
if (!message.trim()) return undefined;
|
|
383
|
-
const kind = fallbackKindFromMessage(message, errorName(value));
|
|
384
|
-
return kind === undefined ? undefined : makeSignal(kind, value, source);
|
|
385
|
-
}
|
|
386
|
-
|
|
387
|
-
function classifyAssistantRefusalSignal(
|
|
388
|
-
value: unknown,
|
|
389
|
-
source: ModelFallbackFailureSource | undefined,
|
|
390
|
-
): ModelFallbackFailureSignal | undefined {
|
|
391
|
-
const codeRefusalKind =
|
|
392
|
-
refusalKindFromCode(codeFrom(value)) ??
|
|
393
|
-
refusalKindFromCode(errorName(value)) ??
|
|
394
|
-
refusalKindFromCode(finishReasonFrom(value));
|
|
395
|
-
if (codeRefusalKind !== undefined) return makeSignal(codeRefusalKind, value, source);
|
|
396
|
-
|
|
397
|
-
const messageRefusalKind = refusalKindFromMessage(directMessageFrom(value) ?? "");
|
|
398
|
-
return messageRefusalKind === undefined ? undefined : makeSignal(messageRefusalKind, value, source);
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
function isRefusalSignal(signal: ModelFallbackFailureSignal): boolean {
|
|
402
|
-
return signal.kind === "cancelled" || signal.kind === "task_failure";
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
function structuredSignal(
|
|
406
|
-
value: unknown,
|
|
407
|
-
seen: Set<unknown>,
|
|
408
|
-
source?: ModelFallbackFailureSource,
|
|
409
|
-
): ModelFallbackFailureSignal | undefined {
|
|
410
|
-
if (value === undefined || value === null || seen.has(value)) return undefined;
|
|
411
|
-
if (typeof value === "object") seen.add(value);
|
|
412
|
-
|
|
413
|
-
const stopReason = stopReasonFrom(value)?.toLowerCase();
|
|
414
|
-
if (stopReason === "aborted") return makeSignal("cancelled", value, source);
|
|
415
|
-
|
|
416
|
-
const directRefusalSignal = classifyAssistantRefusalSignal(value, source);
|
|
417
|
-
if (directRefusalSignal !== undefined) return directRefusalSignal;
|
|
418
|
-
|
|
419
|
-
const codeKind = kindFromCode(codeFrom(value));
|
|
420
|
-
const nameKind = kindFromCode(errorName(value));
|
|
421
|
-
if (codeKind === "cancelled" || nameKind === "cancelled") return makeSignal("cancelled", value, source);
|
|
422
|
-
|
|
423
|
-
let firstNestedFallbackSignal: ModelFallbackFailureSignal | undefined;
|
|
424
|
-
const nestedSeen = new Set(seen);
|
|
425
|
-
for (const diagnosticError of diagnosticErrors(value)) {
|
|
426
|
-
const diagnosticSignal =
|
|
427
|
-
structuredSignal(diagnosticError, nestedSeen, "diagnostic") ??
|
|
428
|
-
fallbackSignalFromMessage(diagnosticError, "diagnostic");
|
|
429
|
-
if (diagnosticSignal === undefined) continue;
|
|
430
|
-
if (isRefusalSignal(diagnosticSignal)) return diagnosticSignal;
|
|
431
|
-
firstNestedFallbackSignal ??= diagnosticSignal;
|
|
432
|
-
}
|
|
433
|
-
const cause = causeOf(value);
|
|
434
|
-
const causeSignal = structuredSignal(cause, nestedSeen, source) ?? fallbackSignalFromMessage(cause, source);
|
|
435
|
-
if (causeSignal !== undefined) {
|
|
436
|
-
if (isRefusalSignal(causeSignal)) return causeSignal;
|
|
437
|
-
firstNestedFallbackSignal ??= causeSignal;
|
|
438
|
-
}
|
|
439
|
-
|
|
440
|
-
// Direct-message classification runs after nested traversal so a generic wrapper
|
|
441
|
-
// ("invalid request"/"400 bad request") cannot mask a non-retryable nested signal.
|
|
442
|
-
const directMessageSignal = fallbackSignalFromDirectMessage(value, source);
|
|
443
|
-
if (directMessageSignal !== undefined) return directMessageSignal;
|
|
444
|
-
|
|
445
|
-
const statusKind = kindFromStatus(statusFrom(value));
|
|
446
|
-
if (statusKind !== undefined) return makeSignal(statusKind, value, source);
|
|
447
|
-
if (codeKind !== undefined) return makeSignal(codeKind, value, source);
|
|
448
|
-
if (nameKind !== undefined) return makeSignal(nameKind, value, source);
|
|
449
|
-
|
|
450
|
-
if (firstNestedFallbackSignal !== undefined) return firstNestedFallbackSignal;
|
|
451
|
-
|
|
452
|
-
if (stopReason === "error") return makeSignal("provider_unavailable", value, source);
|
|
453
|
-
|
|
454
|
-
return undefined;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
function messageFromUnknown(value: unknown, seen: Set<unknown>): string | undefined {
|
|
458
|
-
if (value === undefined || value === null || seen.has(value)) return undefined;
|
|
459
|
-
if (typeof value === "string") return value.trim().length > 0 ? value : undefined;
|
|
460
|
-
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint") return String(value);
|
|
461
|
-
if (typeof value === "symbol" || typeof value === "function") return undefined;
|
|
462
|
-
seen.add(value);
|
|
463
|
-
|
|
464
|
-
if (value instanceof Error && value.message.trim().length > 0) return value.message;
|
|
465
|
-
const directMessage = directMessageFrom(value);
|
|
466
|
-
if (directMessage !== undefined) return directMessage;
|
|
467
|
-
|
|
468
|
-
for (const diagnosticError of diagnosticErrors(value)) {
|
|
469
|
-
const diagnosticMessage = messageFromUnknown(diagnosticError, seen);
|
|
470
|
-
if (diagnosticMessage !== undefined) return diagnosticMessage;
|
|
471
|
-
}
|
|
472
|
-
|
|
473
|
-
const causeMessage = messageFromUnknown(causeOf(value), seen);
|
|
474
|
-
if (causeMessage !== undefined) return causeMessage;
|
|
475
|
-
|
|
476
|
-
const stopReason = stopReasonFrom(value);
|
|
477
|
-
if (stopReason !== undefined) return `Assistant message ended with stopReason:${stopReason}`;
|
|
478
|
-
const finishReason = finishReasonFrom(value);
|
|
479
|
-
if (finishReason !== undefined) return `Model request finished with finish_reason:${finishReason}`;
|
|
480
|
-
const status = statusFrom(value);
|
|
481
|
-
if (status !== undefined) return `Model request failed with status ${status}`;
|
|
482
|
-
const code = codeFrom(value);
|
|
483
|
-
if (code !== undefined) return `Model request failed with code ${String(code)}`;
|
|
484
|
-
|
|
485
|
-
return undefined;
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
export function errorMessage(error: unknown): string {
|
|
489
|
-
const structuredMessage = messageFromUnknown(error, new Set());
|
|
490
|
-
if (structuredMessage !== undefined) return structuredMessage;
|
|
491
|
-
const rendered = String(error);
|
|
492
|
-
return rendered === "[object Object]" ? "Model request failed" : rendered;
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
export function normalizeModelFailureSignal(error: unknown): ModelFallbackFailureSignal {
|
|
496
|
-
const structured = structuredSignal(error, new Set());
|
|
497
|
-
if (structured !== undefined) return structured;
|
|
498
|
-
|
|
499
|
-
const message = errorMessage(error);
|
|
500
|
-
const name = errorName(error);
|
|
501
|
-
const fallbackKind = message.trim().length > 0 ? fallbackKindFromMessage(message, name) : undefined;
|
|
502
|
-
return {
|
|
503
|
-
kind: fallbackKind ?? "unknown",
|
|
504
|
-
message,
|
|
505
|
-
source: "string_fallback",
|
|
506
|
-
...(name !== undefined ? { name } : {}),
|
|
507
|
-
};
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
export function isRetryableModelFailure(error: unknown): boolean {
|
|
511
|
-
if (error === undefined) return false;
|
|
512
|
-
const signal = normalizeModelFailureSignal(error);
|
|
513
|
-
return FALLBACKABLE_FAILURE_KINDS.has(signal.kind);
|
|
514
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility exports for the shared Atomic model-failure classifier.
|
|
3
|
+
*
|
|
4
|
+
* The implementation lives in @bastani/atomic so the main chat, workflows,
|
|
5
|
+
* and subagents cannot drift into separate fallback decisions.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type {
|
|
9
|
+
ModelFallbackFailureKind,
|
|
10
|
+
ModelFallbackFailureSignal,
|
|
11
|
+
ModelFallbackFailureSource,
|
|
12
|
+
} from "@bastani/atomic";
|
|
13
|
+
export {
|
|
14
|
+
errorMessage,
|
|
15
|
+
isRetryableModelFailure,
|
|
16
|
+
isRetryableSameModelFailure,
|
|
17
|
+
modelFailureMessage,
|
|
18
|
+
normalizeModelFailureSignal,
|
|
19
|
+
} from "@bastani/atomic";
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compatibility exports for the shared Atomic retry policy, plus the workflow's
|
|
3
|
+
* abort-aware sleep.
|
|
4
|
+
*
|
|
5
|
+
* The decision/backoff policy is implemented in @bastani/atomic so main chat and
|
|
6
|
+
* workflow stages cannot drift into different budgets for the same
|
|
7
|
+
* `settings.retry` values.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export type { RetryDecision, RetryPolicySettings } from "@bastani/atomic";
|
|
11
|
+
export { nextRetryDecision } from "@bastani/atomic";
|
|
12
|
+
|
|
13
|
+
type WorkflowAbortReason = Error | DOMException | string;
|
|
14
|
+
|
|
15
|
+
function abortReason(signal: AbortSignal | undefined): WorkflowAbortReason {
|
|
16
|
+
const reason = signal?.reason;
|
|
17
|
+
if (reason instanceof Error || reason instanceof DOMException || typeof reason === "string") return reason;
|
|
18
|
+
return new Error("atomic-workflows: workflow cancelled");
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Sleep for a bounded interval and reject promptly when the signal aborts. */
|
|
22
|
+
export function sleepOrAbort(ms: number, signal?: AbortSignal): Promise<void> {
|
|
23
|
+
if (signal?.aborted) return Promise.reject(abortReason(signal));
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
let settled = false;
|
|
26
|
+
const cleanup = (): void => signal?.removeEventListener("abort", onAbort);
|
|
27
|
+
const finish = (): void => {
|
|
28
|
+
if (settled) return;
|
|
29
|
+
settled = true;
|
|
30
|
+
cleanup();
|
|
31
|
+
resolve();
|
|
32
|
+
};
|
|
33
|
+
const fail = (error: WorkflowAbortReason): void => {
|
|
34
|
+
if (settled) return;
|
|
35
|
+
settled = true;
|
|
36
|
+
clearTimeout(timer);
|
|
37
|
+
cleanup();
|
|
38
|
+
reject(error);
|
|
39
|
+
};
|
|
40
|
+
const timer = setTimeout(finish, Math.max(0, ms));
|
|
41
|
+
const onAbort = (): void => fail(abortReason(signal));
|
|
42
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
43
|
+
});
|
|
44
|
+
}
|
|
@@ -24,6 +24,11 @@ export type WorkflowThinkingLevel = "off" | "minimal" | "low" | "medium" | "high
|
|
|
24
24
|
export type WorkflowExecutionMode = "interactive" | "non_interactive";
|
|
25
25
|
export type WorkflowExitStatus = "completed" | "skipped" | "cancelled" | "blocked";
|
|
26
26
|
export type RunStatus = "pending" | "running" | "paused" | WorkflowExitStatus | "failed" | "killed";
|
|
27
|
+
/**
|
|
28
|
+
* Who performed a workflow lifecycle action. Mirrors the store-side union; the
|
|
29
|
+
* authoring contract keeps its own copy so it stays independent of store types.
|
|
30
|
+
*/
|
|
31
|
+
export type WorkflowActor = "user" | "agent";
|
|
27
32
|
export type WorkflowDetailsMode = "named" | "inspection" | "control";
|
|
28
33
|
export type WorkflowDetailsStatus = "accepted" | "running" | WorkflowExitStatus | "failed" | "killed" | "noop";
|
|
29
34
|
export type WorkflowAction = "list" | "get" | "inputs" | "run" | "status" | "interrupt" | "resume";
|
|
@@ -33,6 +33,12 @@ export type WorkflowThinkingLevel = "off" | "minimal" | "low" | "medium" | "high
|
|
|
33
33
|
export type WorkflowExecutionMode = "interactive" | "non_interactive";
|
|
34
34
|
export type WorkflowExitStatus = "completed" | "skipped" | "cancelled" | "blocked";
|
|
35
35
|
export type RunStatus = "pending" | "running" | "paused" | WorkflowExitStatus | "failed" | "killed";
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Who performed a workflow lifecycle action. Mirrors the store-side union; the
|
|
39
|
+
* authoring contract keeps its own copy so it stays independent of store types.
|
|
40
|
+
*/
|
|
41
|
+
export type WorkflowActor = "user" | "agent";
|
|
36
42
|
export type WorkflowDetailsMode = "named" | "inspection" | "control";
|
|
37
43
|
export type WorkflowDetailsStatus = "accepted" | "running" | WorkflowExitStatus | "failed" | "killed" | "noop";
|
|
38
44
|
export type WorkflowAction = "list" | "get" | "inputs" | "run" | "status" | "interrupt" | "resume";
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import type { KeybindingsManager, Theme } from "@bastani/atomic";
|
|
3
3
|
import type { Component, OverlayHandle, OverlayOptions, TUI } from "@earendil-works/pi-tui";
|
|
4
4
|
import type { TSchema } from "typebox";
|
|
5
|
-
import type { RunStatus, StageAdapters, StageContext, StageOptions, WorkflowAction, WorkflowArtifact, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExitOptions, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowMcpPort, WorkflowModelCatalogPort, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowRunChildArgs, WorkflowSerializableObject, WorkflowSerializableValue, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskStep } from "./authoring-contract-stage.js";
|
|
5
|
+
import type { RunStatus, StageAdapters, StageContext, StageOptions, WorkflowAction, WorkflowActor, WorkflowArtifact, WorkflowChainOptions, WorkflowChildResult, WorkflowContextMode, WorkflowDetailsMode, WorkflowDetailsStatus, WorkflowExecutionMode, WorkflowExitOptions, WorkflowInputSchemaMap, WorkflowInputValues, WorkflowMcpPort, WorkflowModelCatalogPort, WorkflowOutputSchemaMap, WorkflowOutputValues, WorkflowParallelOptions, WorkflowPersistencePort, WorkflowRunChildArgs, WorkflowSerializableObject, WorkflowSerializableValue, WorkflowTaskOptions, WorkflowTaskResult, WorkflowTaskStep } from "./authoring-contract-stage.js";
|
|
6
6
|
export type WorkflowCustomUiComponent = Component & {
|
|
7
7
|
dispose?(): void;
|
|
8
8
|
};
|
|
@@ -208,6 +208,10 @@ export interface RunOpts {
|
|
|
208
208
|
readonly toolAdmissionBoundary?: object;
|
|
209
209
|
readonly runId?: string;
|
|
210
210
|
readonly continuation?: RunContinuationOpts;
|
|
211
|
+
/** Who launched this run. A continuation inherits its source run's origin instead. */
|
|
212
|
+
readonly origin?: WorkflowActor;
|
|
213
|
+
/** Who requested the resume that produced this continuation run. */
|
|
214
|
+
readonly resumeActor?: WorkflowActor;
|
|
211
215
|
readonly parentRun?: WorkflowParentRunLink;
|
|
212
216
|
readonly onRunStart?: (snapshot: RunSnapshot) => void;
|
|
213
217
|
readonly onStageStart?: (runId: string, snapshot: StageSnapshot) => void;
|
|
@@ -9,6 +9,7 @@ import type {
|
|
|
9
9
|
StageContext,
|
|
10
10
|
StageOptions,
|
|
11
11
|
WorkflowAction,
|
|
12
|
+
WorkflowActor,
|
|
12
13
|
WorkflowArtifact,
|
|
13
14
|
WorkflowChainOptions,
|
|
14
15
|
WorkflowChildResult,
|
|
@@ -298,6 +299,10 @@ export interface RunOpts {
|
|
|
298
299
|
readonly toolAdmissionBoundary?: object;
|
|
299
300
|
readonly runId?: string;
|
|
300
301
|
readonly continuation?: RunContinuationOpts;
|
|
302
|
+
/** Who launched this run. A continuation inherits its source run's origin instead. */
|
|
303
|
+
readonly origin?: WorkflowActor;
|
|
304
|
+
/** Who requested the resume that produced this continuation run. */
|
|
305
|
+
readonly resumeActor?: WorkflowActor;
|
|
301
306
|
readonly parentRun?: WorkflowParentRunLink;
|
|
302
307
|
readonly onRunStart?: (snapshot: RunSnapshot) => void;
|
|
303
308
|
readonly onStageStart?: (runId: string, snapshot: StageSnapshot) => void;
|