@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
|
@@ -0,0 +1,610 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared model/provider failure classification.
|
|
3
|
+
*
|
|
4
|
+
* Workflows, subagents, and the main chat all need the same decision about
|
|
5
|
+
* whether a provider failure may spend another model candidate. Keep this
|
|
6
|
+
* module free of AgentSession and workflow imports so the published SDK can
|
|
7
|
+
* expose it to the raw-TypeScript companion packages without a cycle.
|
|
8
|
+
*/
|
|
9
|
+
const RETRYABLE_MODEL_FAILURE_PATTERNS = [
|
|
10
|
+
/rate\s*limit/i,
|
|
11
|
+
/too\s*many\s*requests/i,
|
|
12
|
+
/\b429\b/,
|
|
13
|
+
/quota/i,
|
|
14
|
+
/usage[\s_-]*limit/i,
|
|
15
|
+
/billing/i,
|
|
16
|
+
/credit/i,
|
|
17
|
+
/auth(?:entication|orization)?/i,
|
|
18
|
+
/unauthori[sz]ed/i,
|
|
19
|
+
/\b40[13]\b/,
|
|
20
|
+
/api[_\s-]*key/i,
|
|
21
|
+
/token[_\s-]*expired/i,
|
|
22
|
+
/token[_\s-]*(?:revoked|invalidated)/i,
|
|
23
|
+
/invalidated[_\s-]+(?:oauth|auth)[_\s-]+token/i,
|
|
24
|
+
/forbidden/i,
|
|
25
|
+
/invalid\s*key/i,
|
|
26
|
+
/overloaded/i,
|
|
27
|
+
/temporarily\s*unavailable/i,
|
|
28
|
+
/service\s*unavailable/i,
|
|
29
|
+
/network/i,
|
|
30
|
+
/fetch/i,
|
|
31
|
+
/getaddrinfo/i,
|
|
32
|
+
/ENOTFOUND/i,
|
|
33
|
+
/EAI_AGAIN/i,
|
|
34
|
+
/socket/i,
|
|
35
|
+
/connection\s*refused/i,
|
|
36
|
+
/upstream/i,
|
|
37
|
+
/timeout/i,
|
|
38
|
+
/timed\s*out/i,
|
|
39
|
+
/\b50[0-4]\b/,
|
|
40
|
+
/\b524\b/,
|
|
41
|
+
/provider.?returned.?error/i,
|
|
42
|
+
/server.?error/i,
|
|
43
|
+
/internal.?error/i,
|
|
44
|
+
/connection.?error/i,
|
|
45
|
+
/connection.?lost/i,
|
|
46
|
+
/other side closed/i,
|
|
47
|
+
/websocket.?closed/i,
|
|
48
|
+
/websocket.?error/i,
|
|
49
|
+
/reset before headers/i,
|
|
50
|
+
/socket hang up/i,
|
|
51
|
+
/ended without/i,
|
|
52
|
+
/stream ended before message_stop/i,
|
|
53
|
+
/stream ended before a terminal response event/i,
|
|
54
|
+
/http2 request did not get a response/i,
|
|
55
|
+
/retry delay/i,
|
|
56
|
+
/finish.?reason:?\s*error/i,
|
|
57
|
+
/terminated/i,
|
|
58
|
+
/you can retry your request/i,
|
|
59
|
+
/try your request again/i,
|
|
60
|
+
/please retry your request/i,
|
|
61
|
+
// gRPC based providers (e.g. NVIDIA NIM); upstream pi-ai retries this too.
|
|
62
|
+
/ResourceExhausted/i,
|
|
63
|
+
];
|
|
64
|
+
const NON_RETRYABLE_FAILURE_PATTERNS = [
|
|
65
|
+
/command failed/i,
|
|
66
|
+
/tests? failed/i,
|
|
67
|
+
/shell/i,
|
|
68
|
+
/missing file/i,
|
|
69
|
+
/no such file/i,
|
|
70
|
+
/cancel/i,
|
|
71
|
+
/abort/i,
|
|
72
|
+
/interrupted/i,
|
|
73
|
+
];
|
|
74
|
+
const CANCELLED_FAILURE_PATTERNS = [/cancel/i, /abort/i, /interrupted/i];
|
|
75
|
+
const TRANSPORT_CANCELLATION_FAILURE_PATTERNS = [/getaddrinfo|ENOTFOUND|EAI_AGAIN/i];
|
|
76
|
+
const FALLBACKABLE_FAILURE_KINDS = new Set([
|
|
77
|
+
"auth_on_candidate_provider",
|
|
78
|
+
"rate_limit",
|
|
79
|
+
"provider_unavailable",
|
|
80
|
+
"network_timeout",
|
|
81
|
+
"transport_error",
|
|
82
|
+
"model_unavailable",
|
|
83
|
+
"request_incompatible",
|
|
84
|
+
]);
|
|
85
|
+
function asRecord(value) {
|
|
86
|
+
return value !== null && typeof value === "object" ? value : undefined;
|
|
87
|
+
}
|
|
88
|
+
function field(value, key) {
|
|
89
|
+
return asRecord(value)?.[key];
|
|
90
|
+
}
|
|
91
|
+
function stringField(value, key) {
|
|
92
|
+
const raw = field(value, key);
|
|
93
|
+
return typeof raw === "string" && raw.trim().length > 0 ? raw : undefined;
|
|
94
|
+
}
|
|
95
|
+
function errorName(value) {
|
|
96
|
+
return value instanceof Error ? value.name : stringField(value, "name");
|
|
97
|
+
}
|
|
98
|
+
function directMessageFrom(value) {
|
|
99
|
+
return stringField(value, "errorMessage") ?? stringField(value, "message") ?? stringField(value, "statusText");
|
|
100
|
+
}
|
|
101
|
+
function integerFrom(value) {
|
|
102
|
+
if (typeof value === "number" && Number.isInteger(value))
|
|
103
|
+
return value;
|
|
104
|
+
if (typeof value !== "string" || value.trim().length === 0)
|
|
105
|
+
return undefined;
|
|
106
|
+
const parsed = Number(value.trim());
|
|
107
|
+
return Number.isInteger(parsed) ? parsed : undefined;
|
|
108
|
+
}
|
|
109
|
+
function statusFrom(value) {
|
|
110
|
+
return (integerFrom(field(value, "status")) ??
|
|
111
|
+
integerFrom(field(value, "statusCode")) ??
|
|
112
|
+
integerFrom(field(value, "httpStatus")));
|
|
113
|
+
}
|
|
114
|
+
function codeFrom(value) {
|
|
115
|
+
const rawCode = field(value, "code");
|
|
116
|
+
return typeof rawCode === "string" || typeof rawCode === "number" ? rawCode : undefined;
|
|
117
|
+
}
|
|
118
|
+
function stopReasonFrom(value) {
|
|
119
|
+
return stringField(value, "stopReason");
|
|
120
|
+
}
|
|
121
|
+
function finishReasonFrom(value) {
|
|
122
|
+
return stringField(value, "finish_reason") ?? stringField(value, "finishReason");
|
|
123
|
+
}
|
|
124
|
+
function causeOf(value) {
|
|
125
|
+
return value instanceof Error ? value.cause : field(value, "cause");
|
|
126
|
+
}
|
|
127
|
+
function diagnosticErrors(value) {
|
|
128
|
+
const diagnostics = field(value, "diagnostics");
|
|
129
|
+
if (!Array.isArray(diagnostics))
|
|
130
|
+
return [];
|
|
131
|
+
const errors = [];
|
|
132
|
+
for (const diagnostic of diagnostics) {
|
|
133
|
+
const diagnosticType = stringField(diagnostic, "type");
|
|
134
|
+
const diagnosticError = field(diagnostic, "error");
|
|
135
|
+
errors.push(normalizeCode(diagnosticType) === "provider_transport_failure" ? diagnostic : (diagnosticError ?? diagnostic));
|
|
136
|
+
}
|
|
137
|
+
return errors;
|
|
138
|
+
}
|
|
139
|
+
function normalizeCode(value) {
|
|
140
|
+
if (value === undefined)
|
|
141
|
+
return undefined;
|
|
142
|
+
const raw = String(value).trim().toLowerCase();
|
|
143
|
+
if (!raw)
|
|
144
|
+
return undefined;
|
|
145
|
+
let normalized = "";
|
|
146
|
+
let needsSeparator = false;
|
|
147
|
+
for (const char of raw) {
|
|
148
|
+
const code = char.charCodeAt(0);
|
|
149
|
+
const isLowerAlpha = code >= 97 && code <= 122;
|
|
150
|
+
const isDigit = code >= 48 && code <= 57;
|
|
151
|
+
if (isLowerAlpha || isDigit) {
|
|
152
|
+
normalized += char;
|
|
153
|
+
needsSeparator = true;
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (needsSeparator && normalized[normalized.length - 1] !== "_")
|
|
157
|
+
normalized += "_";
|
|
158
|
+
}
|
|
159
|
+
if (normalized.endsWith("_"))
|
|
160
|
+
normalized = normalized.slice(0, -1);
|
|
161
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
162
|
+
}
|
|
163
|
+
function messageLooksLikeModelUnavailable(message) {
|
|
164
|
+
const lower = message.toLowerCase();
|
|
165
|
+
return (lower.includes("model") &&
|
|
166
|
+
(lower.includes("unavailable") ||
|
|
167
|
+
lower.includes("disabled") ||
|
|
168
|
+
lower.includes("not found") ||
|
|
169
|
+
lower.includes("unknown")));
|
|
170
|
+
}
|
|
171
|
+
function kindFromStatus(status) {
|
|
172
|
+
switch (status) {
|
|
173
|
+
case 400:
|
|
174
|
+
case 413:
|
|
175
|
+
case 422:
|
|
176
|
+
return "request_incompatible";
|
|
177
|
+
case 401:
|
|
178
|
+
case 403:
|
|
179
|
+
return "auth_on_candidate_provider";
|
|
180
|
+
case 408:
|
|
181
|
+
return "network_timeout";
|
|
182
|
+
case 404:
|
|
183
|
+
return "model_unavailable";
|
|
184
|
+
case 429:
|
|
185
|
+
return "rate_limit";
|
|
186
|
+
default:
|
|
187
|
+
if (status !== undefined && status >= 500 && status <= 599)
|
|
188
|
+
return "provider_unavailable";
|
|
189
|
+
return undefined;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function refusalKindFromCode(code) {
|
|
193
|
+
const normalizedCode = normalizeCode(code);
|
|
194
|
+
if (normalizedCode === undefined)
|
|
195
|
+
return undefined;
|
|
196
|
+
if (normalizedCode.includes("content_filter") || normalizedCode.includes("contentfilter"))
|
|
197
|
+
return "task_failure";
|
|
198
|
+
if (normalizedCode.includes("safety") || normalizedCode.includes("policy"))
|
|
199
|
+
return "task_failure";
|
|
200
|
+
switch (normalizedCode) {
|
|
201
|
+
case "blocked":
|
|
202
|
+
case "blocked_by_provider":
|
|
203
|
+
case "blocked_by_safety":
|
|
204
|
+
case "blocked_by_policy":
|
|
205
|
+
case "provider_refusal":
|
|
206
|
+
case "refusal":
|
|
207
|
+
case "tool_refusal":
|
|
208
|
+
case "tool_call_refusal":
|
|
209
|
+
case "tool_use_refusal":
|
|
210
|
+
return "task_failure";
|
|
211
|
+
default:
|
|
212
|
+
return undefined;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
const REQUEST_INCOMPATIBLE_CODES = new Set([
|
|
216
|
+
"invalid_request",
|
|
217
|
+
"invalid_request_error",
|
|
218
|
+
"bad_request",
|
|
219
|
+
"context_length_exceeded",
|
|
220
|
+
"request_too_large",
|
|
221
|
+
"too_large",
|
|
222
|
+
"request_entity_too_large",
|
|
223
|
+
"max_tokens",
|
|
224
|
+
"max_context_length",
|
|
225
|
+
"context_window_exceeded",
|
|
226
|
+
]);
|
|
227
|
+
function requestIncompatibleKindFromCode(code) {
|
|
228
|
+
const normalized = normalizeCode(code);
|
|
229
|
+
return normalized !== undefined && REQUEST_INCOMPATIBLE_CODES.has(normalized) ? "request_incompatible" : undefined;
|
|
230
|
+
}
|
|
231
|
+
function kindFromCode(code) {
|
|
232
|
+
const normalizedCode = normalizeCode(code);
|
|
233
|
+
if (normalizedCode === undefined)
|
|
234
|
+
return undefined;
|
|
235
|
+
const refusalKind = refusalKindFromCode(code);
|
|
236
|
+
if (refusalKind !== undefined)
|
|
237
|
+
return refusalKind;
|
|
238
|
+
const httpStatusKind = kindFromStatus(integerFrom(code));
|
|
239
|
+
if (httpStatusKind !== undefined)
|
|
240
|
+
return httpStatusKind;
|
|
241
|
+
const requestIncompatibleKind = requestIncompatibleKindFromCode(code);
|
|
242
|
+
if (requestIncompatibleKind !== undefined)
|
|
243
|
+
return requestIncompatibleKind;
|
|
244
|
+
switch (normalizedCode) {
|
|
245
|
+
case "auth":
|
|
246
|
+
case "auth_required":
|
|
247
|
+
case "authentication_required":
|
|
248
|
+
case "unauthorized":
|
|
249
|
+
case "forbidden":
|
|
250
|
+
case "invalid_api_key":
|
|
251
|
+
case "missing_api_key":
|
|
252
|
+
case "invalid_key":
|
|
253
|
+
case "token_expired":
|
|
254
|
+
case "token_revoked":
|
|
255
|
+
case "token_invalidated":
|
|
256
|
+
case "oauth_token_invalidated":
|
|
257
|
+
return "auth_on_candidate_provider";
|
|
258
|
+
case "etimedout":
|
|
259
|
+
case "econnreset":
|
|
260
|
+
case "econnrefused":
|
|
261
|
+
case "enotfound":
|
|
262
|
+
case "eai_again":
|
|
263
|
+
case "fetch_failed":
|
|
264
|
+
case "network_error":
|
|
265
|
+
case "timeout":
|
|
266
|
+
case "timeout_error":
|
|
267
|
+
case "und_err_connect_timeout":
|
|
268
|
+
return "network_timeout";
|
|
269
|
+
case "rate_limit":
|
|
270
|
+
case "rate_limit_exceeded":
|
|
271
|
+
case "too_many_requests":
|
|
272
|
+
case "quota_exceeded":
|
|
273
|
+
case "insufficient_quota":
|
|
274
|
+
case "usage_limit":
|
|
275
|
+
case "usage_limit_reached":
|
|
276
|
+
case "usage_limit_exceeded":
|
|
277
|
+
return "rate_limit";
|
|
278
|
+
case "aborterror":
|
|
279
|
+
case "aborted":
|
|
280
|
+
case "cancelled":
|
|
281
|
+
case "canceled":
|
|
282
|
+
return "cancelled";
|
|
283
|
+
case "model_not_found":
|
|
284
|
+
case "model_unavailable":
|
|
285
|
+
case "model_disabled":
|
|
286
|
+
case "unknown_model":
|
|
287
|
+
return "model_unavailable";
|
|
288
|
+
case "provider_error":
|
|
289
|
+
case "api_error":
|
|
290
|
+
case "service_unavailable":
|
|
291
|
+
case "temporarily_unavailable":
|
|
292
|
+
case "overloaded":
|
|
293
|
+
return "provider_unavailable";
|
|
294
|
+
default:
|
|
295
|
+
return undefined;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
const REQUEST_INCOMPATIBLE_FAILURE_PATTERNS = [
|
|
299
|
+
/\bcontext[_\s-]?length(?:[_\s-]?exceeded)?\b/i,
|
|
300
|
+
/\bcontext[_\s-]?window(?:[_\s-]?exceeded)?\b/i,
|
|
301
|
+
/\bmax[_\s-]?context\b/i,
|
|
302
|
+
/\bmax[_\s-]?tokens?\b/i,
|
|
303
|
+
/\brequest(?:[_\s-]?entity)?[_\s-]?too[_\s-]?large\b/i,
|
|
304
|
+
/\btoo[_\s-]?large\b/i,
|
|
305
|
+
/\b(?:unsupported|unknown|invalid)\s+(?:tool|parameter|function)\b/i,
|
|
306
|
+
/\b(?:tool|parameter|function)\s+(?:not\s+(?:supported|found|allowed)|unknown|invalid)\b/i,
|
|
307
|
+
/\binvalid[_\s-]?request(?:[_\s-]?error)?\b/i,
|
|
308
|
+
/\bbad[_\s-]?request\b/i,
|
|
309
|
+
];
|
|
310
|
+
const PROVIDER_REFUSAL_FAILURE_PATTERNS = [
|
|
311
|
+
/\bthe\s+model\s+refused\s+to\s+complete\s+the\s+request\b/i,
|
|
312
|
+
/\bfinish[_\s-]?reason\b[^\n]*\bcontent[_\s-]?filter\b/i,
|
|
313
|
+
/\bcontent[_\s-]?filter(?:ed|ing)?\b/i,
|
|
314
|
+
/\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,
|
|
315
|
+
/\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,
|
|
316
|
+
/\btool[_\s-]?(?:call|use)?[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
317
|
+
/\btool(?:\s+call|\s+use)?\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b/i,
|
|
318
|
+
/\brefus(?:e|al|ed|es|ing)?\b[^\n]*\btool(?:\s+call|\s+use)?\b/i,
|
|
319
|
+
/\bprovider[_\s-]?refus(?:e|al|ed|es|ing)?\b/i,
|
|
320
|
+
/\bprovider\b[^\n]*\brefus(?:e|al|ed|es|ing)?\b[^\n]*\b(?:prompt|request|content|policy|safety)\b/i,
|
|
321
|
+
];
|
|
322
|
+
const TRANSPORT_OUTAGE_FAILURE_PATTERNS = [/^connection\s+error\.?$/i, /^fetch\s+failed\.?$/i];
|
|
323
|
+
function transportOutageKindFromMessage(message) {
|
|
324
|
+
return TRANSPORT_OUTAGE_FAILURE_PATTERNS.some((pattern) => pattern.test(message.trim()))
|
|
325
|
+
? "transport_error"
|
|
326
|
+
: undefined;
|
|
327
|
+
}
|
|
328
|
+
function refusalKindFromMessage(message) {
|
|
329
|
+
if (TRANSPORT_CANCELLATION_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
330
|
+
return "network_timeout";
|
|
331
|
+
if (CANCELLED_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
332
|
+
return "cancelled";
|
|
333
|
+
if (NON_RETRYABLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
334
|
+
return "task_failure";
|
|
335
|
+
if (PROVIDER_REFUSAL_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
336
|
+
return "task_failure";
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
function fallbackKindFromMessage(message, name) {
|
|
340
|
+
const refusalKind = refusalKindFromMessage(message);
|
|
341
|
+
if (refusalKind !== undefined)
|
|
342
|
+
return refusalKind;
|
|
343
|
+
const transportOutageKind = transportOutageKindFromMessage(message);
|
|
344
|
+
if (transportOutageKind !== undefined)
|
|
345
|
+
return transportOutageKind;
|
|
346
|
+
if (REQUEST_INCOMPATIBLE_FAILURE_PATTERNS.some((pattern) => pattern.test(message)))
|
|
347
|
+
return "request_incompatible";
|
|
348
|
+
const nameKind = kindFromCode(name);
|
|
349
|
+
if (nameKind !== undefined)
|
|
350
|
+
return nameKind;
|
|
351
|
+
const hasRetryablePattern = RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(message)) ||
|
|
352
|
+
messageLooksLikeModelUnavailable(message);
|
|
353
|
+
if (!hasRetryablePattern)
|
|
354
|
+
return undefined;
|
|
355
|
+
if (/rate\s*limit|too\s*many\s*requests|\b429\b|quota|usage[\s_-]*limit|billing|credit/i.test(message))
|
|
356
|
+
return "rate_limit";
|
|
357
|
+
if (/auth|unauthori[sz]ed|\b40[13]\b|api[_\s-]*key|token[_\s-]*(?:expired|revoked|invalidated|rejected)|forbidden|invalid[_\s-]*key/i.test(message))
|
|
358
|
+
return "auth_on_candidate_provider";
|
|
359
|
+
if (messageLooksLikeModelUnavailable(message))
|
|
360
|
+
return "model_unavailable";
|
|
361
|
+
if (/network|fetch|socket|connection\s*refused|getaddrinfo|ENOTFOUND|EAI_AGAIN|timeout|timed\s*out/i.test(message))
|
|
362
|
+
return "network_timeout";
|
|
363
|
+
return "provider_unavailable";
|
|
364
|
+
}
|
|
365
|
+
function signalSource(value, fallback) {
|
|
366
|
+
if (fallback !== undefined)
|
|
367
|
+
return fallback;
|
|
368
|
+
if (stopReasonFrom(value) !== undefined || diagnosticErrors(value).length > 0)
|
|
369
|
+
return "assistant_message";
|
|
370
|
+
if (value instanceof Error)
|
|
371
|
+
return "throw";
|
|
372
|
+
return "structured";
|
|
373
|
+
}
|
|
374
|
+
function makeSignal(kind, value, source) {
|
|
375
|
+
const status = statusFrom(value);
|
|
376
|
+
const code = codeFrom(value);
|
|
377
|
+
const name = errorName(value);
|
|
378
|
+
const stopReason = stopReasonFrom(value);
|
|
379
|
+
return {
|
|
380
|
+
kind,
|
|
381
|
+
message: errorMessage(value),
|
|
382
|
+
source: signalSource(value, source),
|
|
383
|
+
...(stopReason !== undefined ? { stopReason } : {}),
|
|
384
|
+
...(status !== undefined ? { status } : {}),
|
|
385
|
+
...(code !== undefined ? { code } : {}),
|
|
386
|
+
...(name !== undefined ? { name } : {}),
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
function fallbackSignalFromDirectMessage(value, source) {
|
|
390
|
+
const message = directMessageFrom(value);
|
|
391
|
+
if (message === undefined)
|
|
392
|
+
return undefined;
|
|
393
|
+
const kind = fallbackKindFromMessage(message, errorName(value));
|
|
394
|
+
return kind === undefined ? undefined : makeSignal(kind, value, source);
|
|
395
|
+
}
|
|
396
|
+
function fallbackSignalFromMessage(value, source) {
|
|
397
|
+
const message = errorMessage(value);
|
|
398
|
+
if (!message.trim())
|
|
399
|
+
return undefined;
|
|
400
|
+
const kind = fallbackKindFromMessage(message, errorName(value));
|
|
401
|
+
return kind === undefined ? undefined : makeSignal(kind, value, source);
|
|
402
|
+
}
|
|
403
|
+
function classifyAssistantRefusalSignal(value, source) {
|
|
404
|
+
const codeRefusalKind = refusalKindFromCode(codeFrom(value)) ??
|
|
405
|
+
refusalKindFromCode(errorName(value)) ??
|
|
406
|
+
refusalKindFromCode(finishReasonFrom(value));
|
|
407
|
+
if (codeRefusalKind !== undefined)
|
|
408
|
+
return makeSignal(codeRefusalKind, value, source);
|
|
409
|
+
const messageRefusalKind = refusalKindFromMessage(directMessageFrom(value) ?? "");
|
|
410
|
+
return messageRefusalKind === undefined ? undefined : makeSignal(messageRefusalKind, value, source);
|
|
411
|
+
}
|
|
412
|
+
function isRefusalSignal(signal) {
|
|
413
|
+
return signal.kind === "cancelled" || signal.kind === "task_failure";
|
|
414
|
+
}
|
|
415
|
+
function nestedSignalPriority(signal) {
|
|
416
|
+
switch (signal.kind) {
|
|
417
|
+
case "cancelled":
|
|
418
|
+
case "task_failure":
|
|
419
|
+
return 100;
|
|
420
|
+
case "auth_on_candidate_provider":
|
|
421
|
+
return 90;
|
|
422
|
+
case "request_incompatible":
|
|
423
|
+
return 85;
|
|
424
|
+
case "model_unavailable":
|
|
425
|
+
return 80;
|
|
426
|
+
case "rate_limit":
|
|
427
|
+
return 70;
|
|
428
|
+
case "provider_unavailable":
|
|
429
|
+
return 60;
|
|
430
|
+
case "network_timeout":
|
|
431
|
+
return 50;
|
|
432
|
+
case "transport_error":
|
|
433
|
+
return 82;
|
|
434
|
+
case "unknown":
|
|
435
|
+
return 0;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
function structuredSignal(value, seen, source) {
|
|
439
|
+
if (value === undefined || value === null || seen.has(value))
|
|
440
|
+
return undefined;
|
|
441
|
+
if (typeof value === "object")
|
|
442
|
+
seen.add(value);
|
|
443
|
+
const stopReason = stopReasonFrom(value)?.toLowerCase();
|
|
444
|
+
const diagnosticType = stringField(value, "type");
|
|
445
|
+
const providerTransportSignal = diagnosticType !== undefined && normalizeCode(diagnosticType) === "provider_transport_failure"
|
|
446
|
+
? makeSignal("transport_error", value, source)
|
|
447
|
+
: undefined;
|
|
448
|
+
if (stopReason === "aborted")
|
|
449
|
+
return makeSignal("cancelled", value, source);
|
|
450
|
+
// Defer direct refusal/cancellation signals until nested diagnostics and
|
|
451
|
+
// causes have been inspected. A transport wrapper can carry a cancellation
|
|
452
|
+
// or provider refusal that must win over the wrapper's transport label.
|
|
453
|
+
const directRefusalSignal = classifyAssistantRefusalSignal(value, source);
|
|
454
|
+
const codeKind = kindFromCode(codeFrom(value));
|
|
455
|
+
const nameKind = kindFromCode(errorName(value));
|
|
456
|
+
const directCancellationSignal = codeKind === "cancelled" || nameKind === "cancelled" ? makeSignal("cancelled", value, source) : undefined;
|
|
457
|
+
let bestNestedFallbackSignal;
|
|
458
|
+
const nestedSeen = new Set(seen);
|
|
459
|
+
const nestedValues = [
|
|
460
|
+
...diagnosticErrors(value).map((diagnosticError) => ({ value: diagnosticError, source: "diagnostic" })),
|
|
461
|
+
...(field(value, "error") === undefined ? [] : [{ value: field(value, "error"), source }]),
|
|
462
|
+
];
|
|
463
|
+
for (const nested of nestedValues) {
|
|
464
|
+
const nestedSignal = structuredSignal(nested.value, nestedSeen, nested.source) ??
|
|
465
|
+
fallbackSignalFromMessage(nested.value, nested.source);
|
|
466
|
+
if (nestedSignal === undefined)
|
|
467
|
+
continue;
|
|
468
|
+
if (isRefusalSignal(nestedSignal))
|
|
469
|
+
return nestedSignal;
|
|
470
|
+
if (bestNestedFallbackSignal === undefined ||
|
|
471
|
+
nestedSignalPriority(nestedSignal) > nestedSignalPriority(bestNestedFallbackSignal)) {
|
|
472
|
+
bestNestedFallbackSignal = nestedSignal;
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
const cause = causeOf(value);
|
|
476
|
+
const causeSignal = structuredSignal(cause, nestedSeen, source) ?? fallbackSignalFromMessage(cause, source);
|
|
477
|
+
if (causeSignal !== undefined) {
|
|
478
|
+
if (isRefusalSignal(causeSignal))
|
|
479
|
+
return causeSignal;
|
|
480
|
+
if (bestNestedFallbackSignal === undefined ||
|
|
481
|
+
nestedSignalPriority(causeSignal) > nestedSignalPriority(bestNestedFallbackSignal)) {
|
|
482
|
+
bestNestedFallbackSignal = causeSignal;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
const directSignals = [
|
|
486
|
+
directRefusalSignal,
|
|
487
|
+
directCancellationSignal,
|
|
488
|
+
providerTransportSignal,
|
|
489
|
+
fallbackSignalFromDirectMessage(value, source),
|
|
490
|
+
kindFromStatus(statusFrom(value)) === undefined
|
|
491
|
+
? undefined
|
|
492
|
+
: makeSignal(kindFromStatus(statusFrom(value)), value, source),
|
|
493
|
+
kindFromCode(codeFrom(value)) === undefined
|
|
494
|
+
? undefined
|
|
495
|
+
: makeSignal(kindFromCode(codeFrom(value)), value, source),
|
|
496
|
+
kindFromCode(errorName(value)) === undefined
|
|
497
|
+
? undefined
|
|
498
|
+
: makeSignal(kindFromCode(errorName(value)), value, source),
|
|
499
|
+
].filter((signal) => signal !== undefined);
|
|
500
|
+
for (const directSignal of directSignals) {
|
|
501
|
+
if (isRefusalSignal(directSignal))
|
|
502
|
+
return directSignal;
|
|
503
|
+
if (bestNestedFallbackSignal === undefined ||
|
|
504
|
+
nestedSignalPriority(directSignal) > nestedSignalPriority(bestNestedFallbackSignal)) {
|
|
505
|
+
bestNestedFallbackSignal = directSignal;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
if (bestNestedFallbackSignal !== undefined)
|
|
509
|
+
return bestNestedFallbackSignal;
|
|
510
|
+
if (stopReason === "error")
|
|
511
|
+
return makeSignal("provider_unavailable", value, source);
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
function messageFromUnknown(value, seen) {
|
|
515
|
+
if (value === undefined || value === null || seen.has(value))
|
|
516
|
+
return undefined;
|
|
517
|
+
if (typeof value === "string")
|
|
518
|
+
return value.trim().length > 0 ? value : undefined;
|
|
519
|
+
if (typeof value === "number" || typeof value === "boolean" || typeof value === "bigint")
|
|
520
|
+
return String(value);
|
|
521
|
+
if (typeof value === "symbol" || typeof value === "function")
|
|
522
|
+
return undefined;
|
|
523
|
+
seen.add(value);
|
|
524
|
+
if (value instanceof Error && value.message.trim().length > 0)
|
|
525
|
+
return value.message;
|
|
526
|
+
const directMessage = directMessageFrom(value);
|
|
527
|
+
if (directMessage !== undefined)
|
|
528
|
+
return directMessage;
|
|
529
|
+
for (const diagnosticError of diagnosticErrors(value)) {
|
|
530
|
+
const diagnosticMessage = messageFromUnknown(diagnosticError, seen);
|
|
531
|
+
if (diagnosticMessage !== undefined)
|
|
532
|
+
return diagnosticMessage;
|
|
533
|
+
}
|
|
534
|
+
const causeMessage = messageFromUnknown(causeOf(value), seen);
|
|
535
|
+
if (causeMessage !== undefined)
|
|
536
|
+
return causeMessage;
|
|
537
|
+
const finishReason = finishReasonFrom(value);
|
|
538
|
+
if (finishReason !== undefined)
|
|
539
|
+
return `Model request finished with finish_reason:${finishReason}`;
|
|
540
|
+
const stopReason = stopReasonFrom(value);
|
|
541
|
+
if (stopReason !== undefined)
|
|
542
|
+
return `Assistant message ended with stopReason:${stopReason}`;
|
|
543
|
+
const status = statusFrom(value);
|
|
544
|
+
if (status !== undefined)
|
|
545
|
+
return `Model request failed with status ${status}`;
|
|
546
|
+
const code = codeFrom(value);
|
|
547
|
+
if (code !== undefined)
|
|
548
|
+
return `Model request failed with code ${String(code)}`;
|
|
549
|
+
return undefined;
|
|
550
|
+
}
|
|
551
|
+
export function errorMessage(error) {
|
|
552
|
+
const structuredMessage = messageFromUnknown(error, new Set());
|
|
553
|
+
if (structuredMessage !== undefined)
|
|
554
|
+
return structuredMessage;
|
|
555
|
+
const rendered = String(error);
|
|
556
|
+
return rendered === "[object Object]" ? "Model request failed" : rendered;
|
|
557
|
+
}
|
|
558
|
+
/** Alias used by the subagent package's older public helper name. */
|
|
559
|
+
export const modelFailureMessage = errorMessage;
|
|
560
|
+
export function normalizeModelFailureSignal(error) {
|
|
561
|
+
const structured = structuredSignal(error, new Set());
|
|
562
|
+
if (structured !== undefined)
|
|
563
|
+
return structured;
|
|
564
|
+
const message = errorMessage(error);
|
|
565
|
+
const name = errorName(error);
|
|
566
|
+
const fallbackKind = message.trim().length > 0 ? fallbackKindFromMessage(message, name) : undefined;
|
|
567
|
+
return {
|
|
568
|
+
kind: fallbackKind ?? "unknown",
|
|
569
|
+
message,
|
|
570
|
+
source: "string_fallback",
|
|
571
|
+
...(name !== undefined ? { name } : {}),
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
/** Whether a task-failure signal is a provider safety/refusal response. */
|
|
575
|
+
export function isSafetyRefusalFailure(error) {
|
|
576
|
+
const signal = normalizeModelFailureSignal(error);
|
|
577
|
+
if (signal.kind !== "task_failure")
|
|
578
|
+
return false;
|
|
579
|
+
const text = `${signal.message}\n${signal.code ?? ""}\n${signal.name ?? ""}`;
|
|
580
|
+
return PROVIDER_REFUSAL_FAILURE_PATTERNS.some((pattern) => pattern.test(text));
|
|
581
|
+
}
|
|
582
|
+
/** True when this failure may spend a configured model fallback candidate. */
|
|
583
|
+
export function isRetryableModelFailure(error) {
|
|
584
|
+
if (error === undefined)
|
|
585
|
+
return false;
|
|
586
|
+
return FALLBACKABLE_FAILURE_KINDS.has(normalizeModelFailureSignal(error).kind);
|
|
587
|
+
}
|
|
588
|
+
const SAME_MODEL_RETRYABLE_FAILURE_KINDS = new Set([
|
|
589
|
+
"rate_limit",
|
|
590
|
+
"provider_unavailable",
|
|
591
|
+
"network_timeout",
|
|
592
|
+
"transport_error",
|
|
593
|
+
]);
|
|
594
|
+
/** True when the same model may be requested again before fallback advances. */
|
|
595
|
+
export function isRetryableSameModelFailure(error) {
|
|
596
|
+
if (!isRetryableModelFailure(error))
|
|
597
|
+
return false;
|
|
598
|
+
const signal = normalizeModelFailureSignal(error);
|
|
599
|
+
if (!SAME_MODEL_RETRYABLE_FAILURE_KINDS.has(signal.kind))
|
|
600
|
+
return false;
|
|
601
|
+
if (signal.kind === "provider_unavailable" &&
|
|
602
|
+
signal.source === "assistant_message" &&
|
|
603
|
+
signal.status === undefined &&
|
|
604
|
+
signal.code === undefined &&
|
|
605
|
+
signal.name === undefined &&
|
|
606
|
+
!RETRYABLE_MODEL_FAILURE_PATTERNS.some((pattern) => pattern.test(signal.message)))
|
|
607
|
+
return false;
|
|
608
|
+
return true;
|
|
609
|
+
}
|
|
610
|
+
//# sourceMappingURL=model-fallback-failures.js.map
|