@srouterhq/server 0.0.0-stage → 0.9.0
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/LICENSE +21 -0
- package/client/dist/assets/am-TQ7Jmdqe.js +1 -0
- package/client/dist/assets/ar-Bf5a7yfC.js +1 -0
- package/client/dist/assets/az-CrosE1xH.js +1 -0
- package/client/dist/assets/bg-BvWnmcUz.js +1 -0
- package/client/dist/assets/bn-ams5TsJp.js +1 -0
- package/client/dist/assets/cs-Dh67CaJ_.js +1 -0
- package/client/dist/assets/da-9WlT8Iq7.js +1 -0
- package/client/dist/assets/de-lWhJJzz7.js +1 -0
- package/client/dist/assets/el-Cu7_GhNq.js +1 -0
- package/client/dist/assets/es-BZuzsBcP.js +1 -0
- package/client/dist/assets/fa-Dwdn-jKS.js +1 -0
- package/client/dist/assets/fi-BFrFyOTy.js +1 -0
- package/client/dist/assets/fr-XhbtmPpj.js +1 -0
- package/client/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
- package/client/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
- package/client/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
- package/client/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
- package/client/dist/assets/geist-mono-cyrillic-ext-wght-normal-I4S5GZfc.woff2 +0 -0
- package/client/dist/assets/geist-mono-cyrillic-wght-normal-BmXc_FBt.woff2 +0 -0
- package/client/dist/assets/geist-mono-latin-ext-wght-normal-DrnZ1wKl.woff2 +0 -0
- package/client/dist/assets/geist-mono-latin-wght-normal-B_7UjwxQ.woff2 +0 -0
- package/client/dist/assets/geist-mono-symbols2-wght-normal-GZpp1pK2.woff2 +0 -0
- package/client/dist/assets/geist-mono-vietnamese-wght-normal-D8KDMBhC.woff2 +0 -0
- package/client/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
- package/client/dist/assets/gu-D0uhLUB8.js +1 -0
- package/client/dist/assets/ha-CVlm9pqp.js +1 -0
- package/client/dist/assets/he-CMIFeoWr.js +1 -0
- package/client/dist/assets/hi-ENTwhBpn.js +1 -0
- package/client/dist/assets/hr-fc03vMy_.js +1 -0
- package/client/dist/assets/hu-YBo2BIYt.js +1 -0
- package/client/dist/assets/id-BEWXYX69.js +1 -0
- package/client/dist/assets/ig-BKLZFKka.js +1 -0
- package/client/dist/assets/index-D9I4KtvR.js +145 -0
- package/client/dist/assets/index-txhEmCdb.css +2 -0
- package/client/dist/assets/it-Bzmei1Y2.js +1 -0
- package/client/dist/assets/ja-BfcpuqEl.js +1 -0
- package/client/dist/assets/ka-CnWjRgLo.js +1 -0
- package/client/dist/assets/km-BAjPR3Qj.js +1 -0
- package/client/dist/assets/kn-B15WKU5m.js +1 -0
- package/client/dist/assets/ko-C61fAB-w.js +1 -0
- package/client/dist/assets/lt-CYTr4_YW.js +1 -0
- package/client/dist/assets/ml-CtqxgyH3.js +1 -0
- package/client/dist/assets/mr-X5TMY7aR.js +1 -0
- package/client/dist/assets/ms-DSg8RqPS.js +1 -0
- package/client/dist/assets/my-D7RqR8uE.js +1 -0
- package/client/dist/assets/ne-DaflxkDj.js +1 -0
- package/client/dist/assets/nl-BOqqtsC8.js +1 -0
- package/client/dist/assets/no-BSHp_StB.js +1 -0
- package/client/dist/assets/or-BkLR9Vub.js +1 -0
- package/client/dist/assets/pa-CarJ2XgI.js +1 -0
- package/client/dist/assets/pl-C2n0V-0k.js +1 -0
- package/client/dist/assets/pt-BR-CqJdNhg2.js +1 -0
- package/client/dist/assets/pt-PT-C_HpMyKz.js +1 -0
- package/client/dist/assets/ro-DVRZqSAS.js +1 -0
- package/client/dist/assets/ru-DwAJG7VC.js +1 -0
- package/client/dist/assets/si-BxUezXm0.js +1 -0
- package/client/dist/assets/sk-eI1VcIfY.js +1 -0
- package/client/dist/assets/sr-CJF3auCr.js +1 -0
- package/client/dist/assets/srouter-logo-C6ZfjGIi.svg +14 -0
- package/client/dist/assets/sv-nqvwHAq_.js +1 -0
- package/client/dist/assets/sw-DWynE2pW.js +1 -0
- package/client/dist/assets/ta-BVM12knC.js +1 -0
- package/client/dist/assets/te-oyzEkF7_.js +1 -0
- package/client/dist/assets/th-COVeE0ZQ.js +1 -0
- package/client/dist/assets/tl-DsJANnQz.js +1 -0
- package/client/dist/assets/tr-B-Fl-urO.js +1 -0
- package/client/dist/assets/uk-C5qketAO.js +1 -0
- package/client/dist/assets/ur-QU9KugfV.js +1 -0
- package/client/dist/assets/uz-DL9cG_mY.js +1 -0
- package/client/dist/assets/vi-CQiVy3Pu.js +1 -0
- package/client/dist/assets/yo-DqazMdrZ.js +1 -0
- package/client/dist/assets/zh-CN-DnYL_Kio.js +1 -0
- package/client/dist/assets/zh-TW-5bdbosKj.js +1 -0
- package/client/dist/favicon.svg +14 -0
- package/client/dist/icons.svg +24 -0
- package/client/dist/index.html +37 -0
- package/dist/app.d.ts +4 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +372 -0
- package/dist/app.js.map +1 -0
- package/dist/db/index.d.ts +49 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +203 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/migrate/TEMPLATE.d.ts +4 -0
- package/dist/db/migrate/TEMPLATE.d.ts.map +1 -0
- package/dist/db/migrate/TEMPLATE.js +18 -0
- package/dist/db/migrate/TEMPLATE.js.map +1 -0
- package/dist/db/migrate/cli.d.ts +2 -0
- package/dist/db/migrate/cli.d.ts.map +1 -0
- package/dist/db/migrate/cli.js +177 -0
- package/dist/db/migrate/cli.js.map +1 -0
- package/dist/db/migrate/defaults.d.ts +52 -0
- package/dist/db/migrate/defaults.d.ts.map +1 -0
- package/dist/db/migrate/defaults.js +126 -0
- package/dist/db/migrate/defaults.js.map +1 -0
- package/dist/db/migrate/runner.d.ts +16 -0
- package/dist/db/migrate/runner.d.ts.map +1 -0
- package/dist/db/migrate/runner.js +178 -0
- package/dist/db/migrate/runner.js.map +1 -0
- package/dist/db/migrations/20260101_000000_legacy_baseline.d.ts +4 -0
- package/dist/db/migrations/20260101_000000_legacy_baseline.d.ts.map +1 -0
- package/dist/db/migrations/20260101_000000_legacy_baseline.js +2240 -0
- package/dist/db/migrations/20260101_000000_legacy_baseline.js.map +1 -0
- package/dist/db/migrations/20260627_000001_custom_provider_modalities.d.ts +4 -0
- package/dist/db/migrations/20260627_000001_custom_provider_modalities.d.ts.map +1 -0
- package/dist/db/migrations/20260627_000001_custom_provider_modalities.js +27 -0
- package/dist/db/migrations/20260627_000001_custom_provider_modalities.js.map +1 -0
- package/dist/db/migrations/20260627_000002_catalog_model_state.d.ts +4 -0
- package/dist/db/migrations/20260627_000002_catalog_model_state.d.ts.map +1 -0
- package/dist/db/migrations/20260627_000002_catalog_model_state.js +30 -0
- package/dist/db/migrations/20260627_000002_catalog_model_state.js.map +1 -0
- package/dist/db/migrations/20260628_120000_request_aggregates.d.ts +6 -0
- package/dist/db/migrations/20260628_120000_request_aggregates.d.ts.map +1 -0
- package/dist/db/migrations/20260628_120000_request_aggregates.js +104 -0
- package/dist/db/migrations/20260628_120000_request_aggregates.js.map +1 -0
- package/dist/db/migrations/20260630_000001_github_gpt41_context.d.ts +9 -0
- package/dist/db/migrations/20260630_000001_github_gpt41_context.d.ts.map +1 -0
- package/dist/db/migrations/20260630_000001_github_gpt41_context.js +22 -0
- package/dist/db/migrations/20260630_000001_github_gpt41_context.js.map +1 -0
- package/dist/db/migrations/20260706_000001_request_client_info.d.ts +4 -0
- package/dist/db/migrations/20260706_000001_request_client_info.d.ts.map +1 -0
- package/dist/db/migrations/20260706_000001_request_client_info.js +30 -0
- package/dist/db/migrations/20260706_000001_request_client_info.js.map +1 -0
- package/dist/db/migrations/20260706_000002_custom_model_tool_support.d.ts +17 -0
- package/dist/db/migrations/20260706_000002_custom_model_tool_support.d.ts.map +1 -0
- package/dist/db/migrations/20260706_000002_custom_model_tool_support.js +20 -0
- package/dist/db/migrations/20260706_000002_custom_model_tool_support.js.map +1 -0
- package/dist/db/migrations/20260714_000001_profile_chain_backfill.d.ts +12 -0
- package/dist/db/migrations/20260714_000001_profile_chain_backfill.d.ts.map +1 -0
- package/dist/db/migrations/20260714_000001_profile_chain_backfill.js +45 -0
- package/dist/db/migrations/20260714_000001_profile_chain_backfill.js.map +1 -0
- package/dist/db/migrations/20260720_000001_key_health_error.d.ts +5 -0
- package/dist/db/migrations/20260720_000001_key_health_error.d.ts.map +1 -0
- package/dist/db/migrations/20260720_000001_key_health_error.js +16 -0
- package/dist/db/migrations/20260720_000001_key_health_error.js.map +1 -0
- package/dist/db/migrations/20260726_000001_cooldown_probe_provenance.d.ts +4 -0
- package/dist/db/migrations/20260726_000001_cooldown_probe_provenance.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000001_cooldown_probe_provenance.js +38 -0
- package/dist/db/migrations/20260726_000001_cooldown_probe_provenance.js.map +1 -0
- package/dist/db/migrations/20260726_000002_request_attempts.d.ts +4 -0
- package/dist/db/migrations/20260726_000002_request_attempts.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000002_request_attempts.js +43 -0
- package/dist/db/migrations/20260726_000002_request_attempts.js.map +1 -0
- package/dist/db/migrations/20260726_000003_model_source_provenance.d.ts +4 -0
- package/dist/db/migrations/20260726_000003_model_source_provenance.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000003_model_source_provenance.js +80 -0
- package/dist/db/migrations/20260726_000003_model_source_provenance.js.map +1 -0
- package/dist/db/migrations/20260726_000004_media_model_meta.d.ts +4 -0
- package/dist/db/migrations/20260726_000004_media_model_meta.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000004_media_model_meta.js +34 -0
- package/dist/db/migrations/20260726_000004_media_model_meta.js.map +1 -0
- package/dist/db/migrations/20260726_000005_request_served_model.d.ts +4 -0
- package/dist/db/migrations/20260726_000005_request_served_model.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000005_request_served_model.js +31 -0
- package/dist/db/migrations/20260726_000005_request_served_model.js.map +1 -0
- package/dist/db/migrations/20260726_000006_attempt_error_summary.d.ts +4 -0
- package/dist/db/migrations/20260726_000006_attempt_error_summary.d.ts.map +1 -0
- package/dist/db/migrations/20260726_000006_attempt_error_summary.js +29 -0
- package/dist/db/migrations/20260726_000006_attempt_error_summary.js.map +1 -0
- package/dist/db/migrations/20260727_000001_agent_compatibility.d.ts +4 -0
- package/dist/db/migrations/20260727_000001_agent_compatibility.d.ts.map +1 -0
- package/dist/db/migrations/20260727_000001_agent_compatibility.js +41 -0
- package/dist/db/migrations/20260727_000001_agent_compatibility.js.map +1 -0
- package/dist/db/migrations/20260728_000001_tombstone_provenance.d.ts +12 -0
- package/dist/db/migrations/20260728_000001_tombstone_provenance.d.ts.map +1 -0
- package/dist/db/migrations/20260728_000001_tombstone_provenance.js +37 -0
- package/dist/db/migrations/20260728_000001_tombstone_provenance.js.map +1 -0
- package/dist/db/migrations/20260729_000001_custom_model_endpoint_identity.d.ts +4 -0
- package/dist/db/migrations/20260729_000001_custom_model_endpoint_identity.d.ts.map +1 -0
- package/dist/db/migrations/20260729_000001_custom_model_endpoint_identity.js +145 -0
- package/dist/db/migrations/20260729_000001_custom_model_endpoint_identity.js.map +1 -0
- package/dist/db/migrations/20260802_000001_custom_endpoint_host_labels.d.ts +6 -0
- package/dist/db/migrations/20260802_000001_custom_endpoint_host_labels.d.ts.map +1 -0
- package/dist/db/migrations/20260802_000001_custom_endpoint_host_labels.js +52 -0
- package/dist/db/migrations/20260802_000001_custom_endpoint_host_labels.js.map +1 -0
- package/dist/db/migrations/20260805_000001_key_model_scope.d.ts +6 -0
- package/dist/db/migrations/20260805_000001_key_model_scope.d.ts.map +1 -0
- package/dist/db/migrations/20260805_000001_key_model_scope.js +17 -0
- package/dist/db/migrations/20260805_000001_key_model_scope.js.map +1 -0
- package/dist/db/migrations/20260805_000002_client_profiles.d.ts +4 -0
- package/dist/db/migrations/20260805_000002_client_profiles.d.ts.map +1 -0
- package/dist/db/migrations/20260805_000002_client_profiles.js +33 -0
- package/dist/db/migrations/20260805_000002_client_profiles.js.map +1 -0
- package/dist/db/migrations/20260810_000001_api_key_proxy.d.ts +4 -0
- package/dist/db/migrations/20260810_000001_api_key_proxy.d.ts.map +1 -0
- package/dist/db/migrations/20260810_000001_api_key_proxy.js +33 -0
- package/dist/db/migrations/20260810_000001_api_key_proxy.js.map +1 -0
- package/dist/db/migrations/20260819_000001_custom_model_tombstones.d.ts +4 -0
- package/dist/db/migrations/20260819_000001_custom_model_tombstones.d.ts.map +1 -0
- package/dist/db/migrations/20260819_000001_custom_model_tombstones.js +19 -0
- package/dist/db/migrations/20260819_000001_custom_model_tombstones.js.map +1 -0
- package/dist/db/migrations/20260820_000001_playground_conversations.d.ts +4 -0
- package/dist/db/migrations/20260820_000001_playground_conversations.d.ts.map +1 -0
- package/dist/db/migrations/20260820_000001_playground_conversations.js +47 -0
- package/dist/db/migrations/20260820_000001_playground_conversations.js.map +1 -0
- package/dist/db/migrations/20260823_000001_server_logs.d.ts +4 -0
- package/dist/db/migrations/20260823_000001_server_logs.d.ts.map +1 -0
- package/dist/db/migrations/20260823_000001_server_logs.js +53 -0
- package/dist/db/migrations/20260823_000001_server_logs.js.map +1 -0
- package/dist/db/migrations/20260823_000002_backups_table.d.ts +8 -0
- package/dist/db/migrations/20260823_000002_backups_table.d.ts.map +1 -0
- package/dist/db/migrations/20260823_000002_backups_table.js +22 -0
- package/dist/db/migrations/20260823_000002_backups_table.js.map +1 -0
- package/dist/db/migrations/20260823_000003_attempt_key_label.d.ts +19 -0
- package/dist/db/migrations/20260823_000003_attempt_key_label.d.ts.map +1 -0
- package/dist/db/migrations/20260823_000003_attempt_key_label.js +28 -0
- package/dist/db/migrations/20260823_000003_attempt_key_label.js.map +1 -0
- package/dist/db/migrations/20260823_000004_profile_auto_include.d.ts +14 -0
- package/dist/db/migrations/20260823_000004_profile_auto_include.d.ts.map +1 -0
- package/dist/db/migrations/20260823_000004_profile_auto_include.js +25 -0
- package/dist/db/migrations/20260823_000004_profile_auto_include.js.map +1 -0
- package/dist/db/migrations/20260901_000001_idempotency_claims.d.ts +4 -0
- package/dist/db/migrations/20260901_000001_idempotency_claims.d.ts.map +1 -0
- package/dist/db/migrations/20260901_000001_idempotency_claims.js +46 -0
- package/dist/db/migrations/20260901_000001_idempotency_claims.js.map +1 -0
- package/dist/db/migrations/20260901_000002_quota_observation_lookup.d.ts +4 -0
- package/dist/db/migrations/20260901_000002_quota_observation_lookup.d.ts.map +1 -0
- package/dist/db/migrations/20260901_000002_quota_observation_lookup.js +37 -0
- package/dist/db/migrations/20260901_000002_quota_observation_lookup.js.map +1 -0
- package/dist/db/migrations/20260901_000003_request_caller.d.ts +4 -0
- package/dist/db/migrations/20260901_000003_request_caller.d.ts.map +1 -0
- package/dist/db/migrations/20260901_000003_request_caller.js +27 -0
- package/dist/db/migrations/20260901_000003_request_caller.js.map +1 -0
- package/dist/db/migrations/20260902_000001_analytics_latency_percentile_index.d.ts +4 -0
- package/dist/db/migrations/20260902_000001_analytics_latency_percentile_index.d.ts.map +1 -0
- package/dist/db/migrations/20260902_000001_analytics_latency_percentile_index.js +35 -0
- package/dist/db/migrations/20260902_000001_analytics_latency_percentile_index.js.map +1 -0
- package/dist/db/migrations/20260903_000001_mcp_enabled_default.d.ts +4 -0
- package/dist/db/migrations/20260903_000001_mcp_enabled_default.d.ts.map +1 -0
- package/dist/db/migrations/20260903_000001_mcp_enabled_default.js +37 -0
- package/dist/db/migrations/20260903_000001_mcp_enabled_default.js.map +1 -0
- package/dist/db/migrations/20260903_000002_response_cache.d.ts +4 -0
- package/dist/db/migrations/20260903_000002_response_cache.d.ts.map +1 -0
- package/dist/db/migrations/20260903_000002_response_cache.js +53 -0
- package/dist/db/migrations/20260903_000002_response_cache.js.map +1 -0
- package/dist/db/migrations/20260904_000001_key_monthly_budget.d.ts +13 -0
- package/dist/db/migrations/20260904_000001_key_monthly_budget.d.ts.map +1 -0
- package/dist/db/migrations/20260904_000001_key_monthly_budget.js +35 -0
- package/dist/db/migrations/20260904_000001_key_monthly_budget.js.map +1 -0
- package/dist/db/migrations/20260913_000001_request_model_attribution.d.ts +4 -0
- package/dist/db/migrations/20260913_000001_request_model_attribution.d.ts.map +1 -0
- package/dist/db/migrations/20260913_000001_request_model_attribution.js +68 -0
- package/dist/db/migrations/20260913_000001_request_model_attribution.js.map +1 -0
- package/dist/db/migrations/20260914_000001_key_monthly_usage.d.ts +5 -0
- package/dist/db/migrations/20260914_000001_key_monthly_usage.d.ts.map +1 -0
- package/dist/db/migrations/20260914_000001_key_monthly_usage.js +37 -0
- package/dist/db/migrations/20260914_000001_key_monthly_usage.js.map +1 -0
- package/dist/db/migrations/20260915_000001_quota_snapshot_freshness.d.ts +4 -0
- package/dist/db/migrations/20260915_000001_quota_snapshot_freshness.d.ts.map +1 -0
- package/dist/db/migrations/20260915_000001_quota_snapshot_freshness.js +28 -0
- package/dist/db/migrations/20260915_000001_quota_snapshot_freshness.js.map +1 -0
- package/dist/db/migrations/20261004_000001_unified_key_sr_prefix.d.ts +4 -0
- package/dist/db/migrations/20261004_000001_unified_key_sr_prefix.d.ts.map +1 -0
- package/dist/db/migrations/20261004_000001_unified_key_sr_prefix.js +25 -0
- package/dist/db/migrations/20261004_000001_unified_key_sr_prefix.js.map +1 -0
- package/dist/db/migrations/20261005_000001_key_budget_period.d.ts +10 -0
- package/dist/db/migrations/20261005_000001_key_budget_period.d.ts.map +1 -0
- package/dist/db/migrations/20261005_000001_key_budget_period.js +78 -0
- package/dist/db/migrations/20261005_000001_key_budget_period.js.map +1 -0
- package/dist/db/migrations/20261005_000002_key_budget_period_auto.d.ts +21 -0
- package/dist/db/migrations/20261005_000002_key_budget_period_auto.d.ts.map +1 -0
- package/dist/db/migrations/20261005_000002_key_budget_period_auto.js +41 -0
- package/dist/db/migrations/20261005_000002_key_budget_period_auto.js.map +1 -0
- package/dist/db/model-pricing.d.ts +39 -0
- package/dist/db/model-pricing.d.ts.map +1 -0
- package/dist/db/model-pricing.js +274 -0
- package/dist/db/model-pricing.js.map +1 -0
- package/dist/db/node-sqlite.d.ts +9 -0
- package/dist/db/node-sqlite.d.ts.map +1 -0
- package/dist/db/node-sqlite.js +87 -0
- package/dist/db/node-sqlite.js.map +1 -0
- package/dist/db/types.d.ts +22 -0
- package/dist/db/types.d.ts.map +1 -0
- package/dist/db/types.js +2 -0
- package/dist/db/types.js.map +1 -0
- package/dist/docs/docs-page.d.ts +2 -0
- package/dist/docs/docs-page.d.ts.map +1 -0
- package/dist/docs/docs-page.js +319 -0
- package/dist/docs/docs-page.js.map +1 -0
- package/dist/docs/openapi.d.ts +1896 -0
- package/dist/docs/openapi.d.ts.map +1 -0
- package/dist/docs/openapi.js +1096 -0
- package/dist/docs/openapi.js.map +1 -0
- package/dist/env.d.ts +2 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +9 -0
- package/dist/env.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +144 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/anthropic-documents.d.ts +41 -0
- package/dist/lib/anthropic-documents.d.ts.map +1 -0
- package/dist/lib/anthropic-documents.js +132 -0
- package/dist/lib/anthropic-documents.js.map +1 -0
- package/dist/lib/app-version.d.ts +5 -0
- package/dist/lib/app-version.d.ts.map +1 -0
- package/dist/lib/app-version.js +61 -0
- package/dist/lib/app-version.js.map +1 -0
- package/dist/lib/attempt-trace.d.ts +23 -0
- package/dist/lib/attempt-trace.d.ts.map +1 -0
- package/dist/lib/attempt-trace.js +32 -0
- package/dist/lib/attempt-trace.js.map +1 -0
- package/dist/lib/budget.d.ts +6 -0
- package/dist/lib/budget.d.ts.map +1 -0
- package/dist/lib/budget.js +40 -0
- package/dist/lib/budget.js.map +1 -0
- package/dist/lib/client-classifier.d.ts +10 -0
- package/dist/lib/client-classifier.d.ts.map +1 -0
- package/dist/lib/client-classifier.js +126 -0
- package/dist/lib/client-classifier.js.map +1 -0
- package/dist/lib/client-context.d.ts +10 -0
- package/dist/lib/client-context.d.ts.map +1 -0
- package/dist/lib/client-context.js +39 -0
- package/dist/lib/client-context.js.map +1 -0
- package/dist/lib/config.d.ts +33 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +94 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/content.d.ts +33 -0
- package/dist/lib/content.d.ts.map +1 -0
- package/dist/lib/content.js +201 -0
- package/dist/lib/content.js.map +1 -0
- package/dist/lib/credential.d.ts +11 -0
- package/dist/lib/credential.d.ts.map +1 -0
- package/dist/lib/credential.js +18 -0
- package/dist/lib/credential.js.map +1 -0
- package/dist/lib/crypto.d.ts +31 -0
- package/dist/lib/crypto.d.ts.map +1 -0
- package/dist/lib/crypto.js +206 -0
- package/dist/lib/crypto.js.map +1 -0
- package/dist/lib/custom-provider-cleanup.d.ts +13 -0
- package/dist/lib/custom-provider-cleanup.d.ts.map +1 -0
- package/dist/lib/custom-provider-cleanup.js +43 -0
- package/dist/lib/custom-provider-cleanup.js.map +1 -0
- package/dist/lib/db-backup.d.ts +31 -0
- package/dist/lib/db-backup.d.ts.map +1 -0
- package/dist/lib/db-backup.js +255 -0
- package/dist/lib/db-backup.js.map +1 -0
- package/dist/lib/endpoint-scope.d.ts +42 -0
- package/dist/lib/endpoint-scope.d.ts.map +1 -0
- package/dist/lib/endpoint-scope.js +95 -0
- package/dist/lib/endpoint-scope.js.map +1 -0
- package/dist/lib/env-drift.d.ts +17 -0
- package/dist/lib/env-drift.d.ts.map +1 -0
- package/dist/lib/env-drift.js +108 -0
- package/dist/lib/env-drift.js.map +1 -0
- package/dist/lib/error-classify.d.ts +40 -0
- package/dist/lib/error-classify.d.ts.map +1 -0
- package/dist/lib/error-classify.js +687 -0
- package/dist/lib/error-classify.js.map +1 -0
- package/dist/lib/error-redaction.d.ts +8 -0
- package/dist/lib/error-redaction.d.ts.map +1 -0
- package/dist/lib/error-redaction.js +45 -0
- package/dist/lib/error-redaction.js.map +1 -0
- package/dist/lib/fallback-loop.d.ts +306 -0
- package/dist/lib/fallback-loop.d.ts.map +1 -0
- package/dist/lib/fallback-loop.js +1336 -0
- package/dist/lib/fallback-loop.js.map +1 -0
- package/dist/lib/file-permissions.d.ts +98 -0
- package/dist/lib/file-permissions.d.ts.map +1 -0
- package/dist/lib/file-permissions.js +159 -0
- package/dist/lib/file-permissions.js.map +1 -0
- package/dist/lib/gemini-wire.d.ts +76 -0
- package/dist/lib/gemini-wire.d.ts.map +1 -0
- package/dist/lib/gemini-wire.js +392 -0
- package/dist/lib/gemini-wire.js.map +1 -0
- package/dist/lib/guardrails.d.ts +37 -0
- package/dist/lib/guardrails.d.ts.map +1 -0
- package/dist/lib/guardrails.js +106 -0
- package/dist/lib/guardrails.js.map +1 -0
- package/dist/lib/header-value.d.ts +8 -0
- package/dist/lib/header-value.d.ts.map +1 -0
- package/dist/lib/header-value.js +55 -0
- package/dist/lib/header-value.js.map +1 -0
- package/dist/lib/image-normalize.d.ts +21 -0
- package/dist/lib/image-normalize.d.ts.map +1 -0
- package/dist/lib/image-normalize.js +218 -0
- package/dist/lib/image-normalize.js.map +1 -0
- package/dist/lib/inbound-chat.d.ts +48 -0
- package/dist/lib/inbound-chat.d.ts.map +1 -0
- package/dist/lib/inbound-chat.js +406 -0
- package/dist/lib/inbound-chat.js.map +1 -0
- package/dist/lib/key-parser.d.ts +79 -0
- package/dist/lib/key-parser.d.ts.map +1 -0
- package/dist/lib/key-parser.js +701 -0
- package/dist/lib/key-parser.js.map +1 -0
- package/dist/lib/key-proxy.d.ts +49 -0
- package/dist/lib/key-proxy.d.ts.map +1 -0
- package/dist/lib/key-proxy.js +92 -0
- package/dist/lib/key-proxy.js.map +1 -0
- package/dist/lib/log-redaction.d.ts +28 -0
- package/dist/lib/log-redaction.d.ts.map +1 -0
- package/dist/lib/log-redaction.js +166 -0
- package/dist/lib/log-redaction.js.map +1 -0
- package/dist/lib/model-scope.d.ts +9 -0
- package/dist/lib/model-scope.d.ts.map +1 -0
- package/dist/lib/model-scope.js +29 -0
- package/dist/lib/model-scope.js.map +1 -0
- package/dist/lib/one-time-code.d.ts +15 -0
- package/dist/lib/one-time-code.d.ts.map +1 -0
- package/dist/lib/one-time-code.js +41 -0
- package/dist/lib/one-time-code.js.map +1 -0
- package/dist/lib/output-cap.d.ts +24 -0
- package/dist/lib/output-cap.d.ts.map +1 -0
- package/dist/lib/output-cap.js +80 -0
- package/dist/lib/output-cap.js.map +1 -0
- package/dist/lib/password.d.ts +3 -0
- package/dist/lib/password.d.ts.map +1 -0
- package/dist/lib/password.js +27 -0
- package/dist/lib/password.js.map +1 -0
- package/dist/lib/process-safety-net.d.ts +32 -0
- package/dist/lib/process-safety-net.d.ts.map +1 -0
- package/dist/lib/process-safety-net.js +123 -0
- package/dist/lib/process-safety-net.js.map +1 -0
- package/dist/lib/provider-identity.d.ts +37 -0
- package/dist/lib/provider-identity.d.ts.map +1 -0
- package/dist/lib/provider-identity.js +110 -0
- package/dist/lib/provider-identity.js.map +1 -0
- package/dist/lib/provider-size-parser.d.ts +6 -0
- package/dist/lib/provider-size-parser.d.ts.map +1 -0
- package/dist/lib/provider-size-parser.js +72 -0
- package/dist/lib/provider-size-parser.js.map +1 -0
- package/dist/lib/provider-timeout.d.ts +17 -0
- package/dist/lib/provider-timeout.d.ts.map +1 -0
- package/dist/lib/provider-timeout.js +70 -0
- package/dist/lib/provider-timeout.js.map +1 -0
- package/dist/lib/proxy.d.ts +180 -0
- package/dist/lib/proxy.d.ts.map +1 -0
- package/dist/lib/proxy.js +1002 -0
- package/dist/lib/proxy.js.map +1 -0
- package/dist/lib/request-log.d.ts +4 -0
- package/dist/lib/request-log.d.ts.map +1 -0
- package/dist/lib/request-log.js +161 -0
- package/dist/lib/request-log.js.map +1 -0
- package/dist/lib/reset-code.d.ts +5 -0
- package/dist/lib/reset-code.d.ts.map +1 -0
- package/dist/lib/reset-code.js +39 -0
- package/dist/lib/reset-code.js.map +1 -0
- package/dist/lib/retry-hint.d.ts +14 -0
- package/dist/lib/retry-hint.d.ts.map +1 -0
- package/dist/lib/retry-hint.js +36 -0
- package/dist/lib/retry-hint.js.map +1 -0
- package/dist/lib/route-live.d.ts +29 -0
- package/dist/lib/route-live.d.ts.map +1 -0
- package/dist/lib/route-live.js +97 -0
- package/dist/lib/route-live.js.map +1 -0
- package/dist/lib/sampling-params.d.ts +183 -0
- package/dist/lib/sampling-params.d.ts.map +1 -0
- package/dist/lib/sampling-params.js +386 -0
- package/dist/lib/sampling-params.js.map +1 -0
- package/dist/lib/scheduler.d.ts +13 -0
- package/dist/lib/scheduler.d.ts.map +1 -0
- package/dist/lib/scheduler.js +11 -0
- package/dist/lib/scheduler.js.map +1 -0
- package/dist/lib/served-model.d.ts +16 -0
- package/dist/lib/served-model.d.ts.map +1 -0
- package/dist/lib/served-model.js +0 -0
- package/dist/lib/served-model.js.map +1 -0
- package/dist/lib/server-logs.d.ts +132 -0
- package/dist/lib/server-logs.d.ts.map +1 -0
- package/dist/lib/server-logs.js +473 -0
- package/dist/lib/server-logs.js.map +1 -0
- package/dist/lib/setup-code.d.ts +5 -0
- package/dist/lib/setup-code.d.ts.map +1 -0
- package/dist/lib/setup-code.js +35 -0
- package/dist/lib/setup-code.js.map +1 -0
- package/dist/lib/structured-output.d.ts +9 -0
- package/dist/lib/structured-output.d.ts.map +1 -0
- package/dist/lib/structured-output.js +72 -0
- package/dist/lib/structured-output.js.map +1 -0
- package/dist/lib/system-prompt.d.ts +30 -0
- package/dist/lib/system-prompt.d.ts.map +1 -0
- package/dist/lib/system-prompt.js +66 -0
- package/dist/lib/system-prompt.js.map +1 -0
- package/dist/lib/task-type.d.ts +18 -0
- package/dist/lib/task-type.d.ts.map +1 -0
- package/dist/lib/task-type.js +92 -0
- package/dist/lib/task-type.js.map +1 -0
- package/dist/lib/think-tags.d.ts +37 -0
- package/dist/lib/think-tags.d.ts.map +1 -0
- package/dist/lib/think-tags.js +203 -0
- package/dist/lib/think-tags.js.map +1 -0
- package/dist/lib/tool-args.d.ts +36 -0
- package/dist/lib/tool-args.d.ts.map +1 -0
- package/dist/lib/tool-args.js +190 -0
- package/dist/lib/tool-args.js.map +1 -0
- package/dist/lib/tool-call-rescue.d.ts +62 -0
- package/dist/lib/tool-call-rescue.d.ts.map +1 -0
- package/dist/lib/tool-call-rescue.js +258 -0
- package/dist/lib/tool-call-rescue.js.map +1 -0
- package/dist/lib/tool-capability.d.ts +13 -0
- package/dist/lib/tool-capability.d.ts.map +1 -0
- package/dist/lib/tool-capability.js +70 -0
- package/dist/lib/tool-capability.js.map +1 -0
- package/dist/lib/tool-validate.d.ts +44 -0
- package/dist/lib/tool-validate.d.ts.map +1 -0
- package/dist/lib/tool-validate.js +165 -0
- package/dist/lib/tool-validate.js.map +1 -0
- package/dist/lib/ttfb-budget.d.ts +13 -0
- package/dist/lib/ttfb-budget.d.ts.map +1 -0
- package/dist/lib/ttfb-budget.js +153 -0
- package/dist/lib/ttfb-budget.js.map +1 -0
- package/dist/lib/url-guard.d.ts +47 -0
- package/dist/lib/url-guard.d.ts.map +1 -0
- package/dist/lib/url-guard.js +229 -0
- package/dist/lib/url-guard.js.map +1 -0
- package/dist/lib/wake-detect.d.ts +12 -0
- package/dist/lib/wake-detect.d.ts.map +1 -0
- package/dist/lib/wake-detect.js +99 -0
- package/dist/lib/wake-detect.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +3 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +45 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +4 -0
- package/dist/middleware/rateLimit.d.ts.map +1 -0
- package/dist/middleware/rateLimit.js +125 -0
- package/dist/middleware/rateLimit.js.map +1 -0
- package/dist/middleware/requireAuth.d.ts +3 -0
- package/dist/middleware/requireAuth.d.ts.map +1 -0
- package/dist/middleware/requireAuth.js +17 -0
- package/dist/middleware/requireAuth.js.map +1 -0
- package/dist/providers/aclide.d.ts +18 -0
- package/dist/providers/aclide.d.ts.map +1 -0
- package/dist/providers/aclide.js +174 -0
- package/dist/providers/aclide.js.map +1 -0
- package/dist/providers/aihorde.d.ts +42 -0
- package/dist/providers/aihorde.d.ts.map +1 -0
- package/dist/providers/aihorde.js +192 -0
- package/dist/providers/aihorde.js.map +1 -0
- package/dist/providers/airforce.d.ts +11 -0
- package/dist/providers/airforce.d.ts.map +1 -0
- package/dist/providers/airforce.js +32 -0
- package/dist/providers/airforce.js.map +1 -0
- package/dist/providers/base.d.ts +177 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +354 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/blaze.d.ts +11 -0
- package/dist/providers/blaze.d.ts.map +1 -0
- package/dist/providers/blaze.js +33 -0
- package/dist/providers/blaze.js.map +1 -0
- package/dist/providers/blockrun.d.ts +14 -0
- package/dist/providers/blockrun.d.ts.map +1 -0
- package/dist/providers/blockrun.js +36 -0
- package/dist/providers/blockrun.js.map +1 -0
- package/dist/providers/clod.d.ts +11 -0
- package/dist/providers/clod.d.ts.map +1 -0
- package/dist/providers/clod.js +39 -0
- package/dist/providers/clod.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +15 -0
- package/dist/providers/cloudflare.d.ts.map +1 -0
- package/dist/providers/cloudflare.js +175 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/cohere.d.ts +11 -0
- package/dist/providers/cohere.d.ts.map +1 -0
- package/dist/providers/cohere.js +117 -0
- package/dist/providers/cohere.js.map +1 -0
- package/dist/providers/dreamprompting.d.ts +11 -0
- package/dist/providers/dreamprompting.d.ts.map +1 -0
- package/dist/providers/dreamprompting.js +41 -0
- package/dist/providers/dreamprompting.js.map +1 -0
- package/dist/providers/electronhub.d.ts +10 -0
- package/dist/providers/electronhub.d.ts.map +1 -0
- package/dist/providers/electronhub.js +56 -0
- package/dist/providers/electronhub.js.map +1 -0
- package/dist/providers/experiential.d.ts +10 -0
- package/dist/providers/experiential.d.ts.map +1 -0
- package/dist/providers/experiential.js +33 -0
- package/dist/providers/experiential.js.map +1 -0
- package/dist/providers/gizmo.d.ts +15 -0
- package/dist/providers/gizmo.d.ts.map +1 -0
- package/dist/providers/gizmo.js +54 -0
- package/dist/providers/gizmo.js.map +1 -0
- package/dist/providers/google.d.ts +30 -0
- package/dist/providers/google.d.ts.map +1 -0
- package/dist/providers/google.js +766 -0
- package/dist/providers/google.js.map +1 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +561 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/llmtr.d.ts +15 -0
- package/dist/providers/llmtr.d.ts.map +1 -0
- package/dist/providers/llmtr.js +51 -0
- package/dist/providers/llmtr.js.map +1 -0
- package/dist/providers/logfare.d.ts +11 -0
- package/dist/providers/logfare.d.ts.map +1 -0
- package/dist/providers/logfare.js +33 -0
- package/dist/providers/logfare.js.map +1 -0
- package/dist/providers/lucidity.d.ts +11 -0
- package/dist/providers/lucidity.d.ts.map +1 -0
- package/dist/providers/lucidity.js +37 -0
- package/dist/providers/lucidity.js.map +1 -0
- package/dist/providers/modelscope.d.ts +50 -0
- package/dist/providers/modelscope.d.ts.map +1 -0
- package/dist/providers/modelscope.js +143 -0
- package/dist/providers/modelscope.js.map +1 -0
- package/dist/providers/moondream.d.ts +17 -0
- package/dist/providers/moondream.d.ts.map +1 -0
- package/dist/providers/moondream.js +140 -0
- package/dist/providers/moondream.js.map +1 -0
- package/dist/providers/openai-compat.d.ts +140 -0
- package/dist/providers/openai-compat.d.ts.map +1 -0
- package/dist/providers/openai-compat.js +537 -0
- package/dist/providers/openai-compat.js.map +1 -0
- package/dist/providers/opencode-free.d.ts +24 -0
- package/dist/providers/opencode-free.d.ts.map +1 -0
- package/dist/providers/opencode-free.js +262 -0
- package/dist/providers/opencode-free.js.map +1 -0
- package/dist/providers/pollinations.d.ts +32 -0
- package/dist/providers/pollinations.d.ts.map +1 -0
- package/dist/providers/pollinations.js +65 -0
- package/dist/providers/pollinations.js.map +1 -0
- package/dist/providers/router9.d.ts +16 -0
- package/dist/providers/router9.d.ts.map +1 -0
- package/dist/providers/router9.js +42 -0
- package/dist/providers/router9.js.map +1 -0
- package/dist/providers/sail.d.ts +44 -0
- package/dist/providers/sail.d.ts.map +1 -0
- package/dist/providers/sail.js +302 -0
- package/dist/providers/sail.js.map +1 -0
- package/dist/providers/septor.d.ts +10 -0
- package/dist/providers/septor.d.ts.map +1 -0
- package/dist/providers/septor.js +36 -0
- package/dist/providers/septor.js.map +1 -0
- package/dist/providers/speechify.d.ts +14 -0
- package/dist/providers/speechify.d.ts.map +1 -0
- package/dist/providers/speechify.js +28 -0
- package/dist/providers/speechify.js.map +1 -0
- package/dist/providers/speka.d.ts +12 -0
- package/dist/providers/speka.d.ts.map +1 -0
- package/dist/providers/speka.js +37 -0
- package/dist/providers/speka.js.map +1 -0
- package/dist/providers/waterfall.d.ts +11 -0
- package/dist/providers/waterfall.d.ts.map +1 -0
- package/dist/providers/waterfall.js +33 -0
- package/dist/providers/waterfall.js.map +1 -0
- package/dist/providers/xkiro.d.ts +71 -0
- package/dist/providers/xkiro.d.ts.map +1 -0
- package/dist/providers/xkiro.js +119 -0
- package/dist/providers/xkiro.js.map +1 -0
- package/dist/providers/zhipu.d.ts +43 -0
- package/dist/providers/zhipu.d.ts.map +1 -0
- package/dist/providers/zhipu.js +95 -0
- package/dist/providers/zhipu.js.map +1 -0
- package/dist/routes/analytics.d.ts +2 -0
- package/dist/routes/analytics.d.ts.map +1 -0
- package/dist/routes/analytics.js +738 -0
- package/dist/routes/analytics.js.map +1 -0
- package/dist/routes/anthropic.d.ts +7 -0
- package/dist/routes/anthropic.d.ts.map +1 -0
- package/dist/routes/anthropic.js +1076 -0
- package/dist/routes/anthropic.js.map +1 -0
- package/dist/routes/auth.d.ts +2 -0
- package/dist/routes/auth.d.ts.map +1 -0
- package/dist/routes/auth.js +310 -0
- package/dist/routes/auth.js.map +1 -0
- package/dist/routes/backups.d.ts +2 -0
- package/dist/routes/backups.d.ts.map +1 -0
- package/dist/routes/backups.js +127 -0
- package/dist/routes/backups.js.map +1 -0
- package/dist/routes/cache.d.ts +2 -0
- package/dist/routes/cache.d.ts.map +1 -0
- package/dist/routes/cache.js +40 -0
- package/dist/routes/cache.js.map +1 -0
- package/dist/routes/client-profiles.d.ts +2 -0
- package/dist/routes/client-profiles.d.ts.map +1 -0
- package/dist/routes/client-profiles.js +128 -0
- package/dist/routes/client-profiles.js.map +1 -0
- package/dist/routes/compression.d.ts +2 -0
- package/dist/routes/compression.d.ts.map +1 -0
- package/dist/routes/compression.js +82 -0
- package/dist/routes/compression.js.map +1 -0
- package/dist/routes/conversations.d.ts +3 -0
- package/dist/routes/conversations.d.ts.map +1 -0
- package/dist/routes/conversations.js +215 -0
- package/dist/routes/conversations.js.map +1 -0
- package/dist/routes/docs.d.ts +2 -0
- package/dist/routes/docs.d.ts.map +1 -0
- package/dist/routes/docs.js +21 -0
- package/dist/routes/docs.js.map +1 -0
- package/dist/routes/embeddings.d.ts +2 -0
- package/dist/routes/embeddings.d.ts.map +1 -0
- package/dist/routes/embeddings.js +255 -0
- package/dist/routes/embeddings.js.map +1 -0
- package/dist/routes/fallback.d.ts +2 -0
- package/dist/routes/fallback.d.ts.map +1 -0
- package/dist/routes/fallback.js +631 -0
- package/dist/routes/fallback.js.map +1 -0
- package/dist/routes/free-tier.d.ts +22 -0
- package/dist/routes/free-tier.d.ts.map +1 -0
- package/dist/routes/free-tier.js +175 -0
- package/dist/routes/free-tier.js.map +1 -0
- package/dist/routes/gemini.d.ts +2 -0
- package/dist/routes/gemini.d.ts.map +1 -0
- package/dist/routes/gemini.js +218 -0
- package/dist/routes/gemini.js.map +1 -0
- package/dist/routes/health.d.ts +2 -0
- package/dist/routes/health.d.ts.map +1 -0
- package/dist/routes/health.js +72 -0
- package/dist/routes/health.js.map +1 -0
- package/dist/routes/keys.d.ts +17 -0
- package/dist/routes/keys.d.ts.map +1 -0
- package/dist/routes/keys.js +1787 -0
- package/dist/routes/keys.js.map +1 -0
- package/dist/routes/logs.d.ts +2 -0
- package/dist/routes/logs.d.ts.map +1 -0
- package/dist/routes/logs.js +88 -0
- package/dist/routes/logs.js.map +1 -0
- package/dist/routes/mcp.d.ts +4 -0
- package/dist/routes/mcp.d.ts.map +1 -0
- package/dist/routes/mcp.js +563 -0
- package/dist/routes/mcp.js.map +1 -0
- package/dist/routes/media.d.ts +2 -0
- package/dist/routes/media.d.ts.map +1 -0
- package/dist/routes/media.js +180 -0
- package/dist/routes/media.js.map +1 -0
- package/dist/routes/models.d.ts +2 -0
- package/dist/routes/models.d.ts.map +1 -0
- package/dist/routes/models.js +439 -0
- package/dist/routes/models.js.map +1 -0
- package/dist/routes/ollama.d.ts +7 -0
- package/dist/routes/ollama.d.ts.map +1 -0
- package/dist/routes/ollama.js +595 -0
- package/dist/routes/ollama.js.map +1 -0
- package/dist/routes/profiles.d.ts +3 -0
- package/dist/routes/profiles.d.ts.map +1 -0
- package/dist/routes/profiles.js +431 -0
- package/dist/routes/profiles.js.map +1 -0
- package/dist/routes/proxy.d.ts +32 -0
- package/dist/routes/proxy.d.ts.map +1 -0
- package/dist/routes/proxy.js +2793 -0
- package/dist/routes/proxy.js.map +1 -0
- package/dist/routes/responses.d.ts +1161 -0
- package/dist/routes/responses.d.ts.map +1 -0
- package/dist/routes/responses.js +1521 -0
- package/dist/routes/responses.js.map +1 -0
- package/dist/routes/settings.d.ts +2 -0
- package/dist/routes/settings.d.ts.map +1 -0
- package/dist/routes/settings.js +549 -0
- package/dist/routes/settings.js.map +1 -0
- package/dist/routes/status.d.ts +3 -0
- package/dist/routes/status.d.ts.map +1 -0
- package/dist/routes/status.js +214 -0
- package/dist/routes/status.js.map +1 -0
- package/dist/routes/update.d.ts +31 -0
- package/dist/routes/update.d.ts.map +1 -0
- package/dist/routes/update.js +536 -0
- package/dist/routes/update.js.map +1 -0
- package/dist/routes/url-tokens.d.ts +2 -0
- package/dist/routes/url-tokens.d.ts.map +1 -0
- package/dist/routes/url-tokens.js +31 -0
- package/dist/routes/url-tokens.js.map +1 -0
- package/dist/scripts/export-catalog.d.ts +2 -0
- package/dist/scripts/export-catalog.d.ts.map +1 -0
- package/dist/scripts/export-catalog.js +114 -0
- package/dist/scripts/export-catalog.js.map +1 -0
- package/dist/scripts/rotate-encryption-key.d.ts +81 -0
- package/dist/scripts/rotate-encryption-key.d.ts.map +1 -0
- package/dist/scripts/rotate-encryption-key.js +232 -0
- package/dist/scripts/rotate-encryption-key.js.map +1 -0
- package/dist/scripts/routing-sim.d.ts +2 -0
- package/dist/scripts/routing-sim.d.ts.map +1 -0
- package/dist/scripts/routing-sim.js +130 -0
- package/dist/scripts/routing-sim.js.map +1 -0
- package/dist/scripts/test-all-models.d.ts +2 -0
- package/dist/scripts/test-all-models.d.ts.map +1 -0
- package/dist/scripts/test-all-models.js +56 -0
- package/dist/scripts/test-all-models.js.map +1 -0
- package/dist/services/anthropic-map.d.ts +39 -0
- package/dist/services/anthropic-map.d.ts.map +1 -0
- package/dist/services/anthropic-map.js +138 -0
- package/dist/services/anthropic-map.js.map +1 -0
- package/dist/services/auth.d.ts +30 -0
- package/dist/services/auth.d.ts.map +1 -0
- package/dist/services/auth.js +124 -0
- package/dist/services/auth.js.map +1 -0
- package/dist/services/auto-discover.d.ts +77 -0
- package/dist/services/auto-discover.d.ts.map +1 -0
- package/dist/services/auto-discover.js +1047 -0
- package/dist/services/auto-discover.js.map +1 -0
- package/dist/services/backups.d.ts +67 -0
- package/dist/services/backups.d.ts.map +1 -0
- package/dist/services/backups.js +444 -0
- package/dist/services/backups.js.map +1 -0
- package/dist/services/builtin-model-discovery.d.ts +107 -0
- package/dist/services/builtin-model-discovery.d.ts.map +1 -0
- package/dist/services/builtin-model-discovery.js +296 -0
- package/dist/services/builtin-model-discovery.js.map +1 -0
- package/dist/services/cache.d.ts +190 -0
- package/dist/services/cache.d.ts.map +1 -0
- package/dist/services/cache.js +617 -0
- package/dist/services/cache.js.map +1 -0
- package/dist/services/catalog-sync.d.ts +257 -0
- package/dist/services/catalog-sync.d.ts.map +1 -0
- package/dist/services/catalog-sync.js +1041 -0
- package/dist/services/catalog-sync.js.map +1 -0
- package/dist/services/compression/config.d.ts +33 -0
- package/dist/services/compression/config.d.ts.map +1 -0
- package/dist/services/compression/config.js +158 -0
- package/dist/services/compression/config.js.map +1 -0
- package/dist/services/compression/engines/aging.d.ts +2 -0
- package/dist/services/compression/engines/aging.d.ts.map +1 -0
- package/dist/services/compression/engines/aging.js +53 -0
- package/dist/services/compression/engines/aging.js.map +1 -0
- package/dist/services/compression/engines/custom-filters.d.ts +4 -0
- package/dist/services/compression/engines/custom-filters.d.ts.map +1 -0
- package/dist/services/compression/engines/custom-filters.js +49 -0
- package/dist/services/compression/engines/custom-filters.js.map +1 -0
- package/dist/services/compression/engines/dedup.d.ts +2 -0
- package/dist/services/compression/engines/dedup.d.ts.map +1 -0
- package/dist/services/compression/engines/dedup.js +61 -0
- package/dist/services/compression/engines/dedup.js.map +1 -0
- package/dist/services/compression/engines/filter-definitions.d.ts +75 -0
- package/dist/services/compression/engines/filter-definitions.d.ts.map +1 -0
- package/dist/services/compression/engines/filter-definitions.js +45 -0
- package/dist/services/compression/engines/filter-definitions.js.map +1 -0
- package/dist/services/compression/engines/hard-budget.d.ts +2 -0
- package/dist/services/compression/engines/hard-budget.d.ts.map +1 -0
- package/dist/services/compression/engines/hard-budget.js +52 -0
- package/dist/services/compression/engines/hard-budget.js.map +1 -0
- package/dist/services/compression/engines/index.d.ts +9 -0
- package/dist/services/compression/engines/index.d.ts.map +1 -0
- package/dist/services/compression/engines/index.js +9 -0
- package/dist/services/compression/engines/index.js.map +1 -0
- package/dist/services/compression/engines/jsoncompact.d.ts +3 -0
- package/dist/services/compression/engines/jsoncompact.d.ts.map +1 -0
- package/dist/services/compression/engines/jsoncompact.js +145 -0
- package/dist/services/compression/engines/jsoncompact.js.map +1 -0
- package/dist/services/compression/engines/lite.d.ts +2 -0
- package/dist/services/compression/engines/lite.d.ts.map +1 -0
- package/dist/services/compression/engines/lite.js +34 -0
- package/dist/services/compression/engines/lite.js.map +1 -0
- package/dist/services/compression/engines/read-lifecycle.d.ts +2 -0
- package/dist/services/compression/engines/read-lifecycle.d.ts.map +1 -0
- package/dist/services/compression/engines/read-lifecycle.js +70 -0
- package/dist/services/compression/engines/read-lifecycle.js.map +1 -0
- package/dist/services/compression/engines/relevance.d.ts +2 -0
- package/dist/services/compression/engines/relevance.d.ts.map +1 -0
- package/dist/services/compression/engines/relevance.js +74 -0
- package/dist/services/compression/engines/relevance.js.map +1 -0
- package/dist/services/compression/engines/toolfilter.d.ts +2 -0
- package/dist/services/compression/engines/toolfilter.d.ts.map +1 -0
- package/dist/services/compression/engines/toolfilter.js +195 -0
- package/dist/services/compression/engines/toolfilter.js.map +1 -0
- package/dist/services/compression/fidelity-gate.d.ts +12 -0
- package/dist/services/compression/fidelity-gate.d.ts.map +1 -0
- package/dist/services/compression/fidelity-gate.js +90 -0
- package/dist/services/compression/fidelity-gate.js.map +1 -0
- package/dist/services/compression/helpers.d.ts +9 -0
- package/dist/services/compression/helpers.d.ts.map +1 -0
- package/dist/services/compression/helpers.js +52 -0
- package/dist/services/compression/helpers.js.map +1 -0
- package/dist/services/compression/pipeline.d.ts +7 -0
- package/dist/services/compression/pipeline.d.ts.map +1 -0
- package/dist/services/compression/pipeline.js +245 -0
- package/dist/services/compression/pipeline.js.map +1 -0
- package/dist/services/compression/preservation.d.ts +27 -0
- package/dist/services/compression/preservation.d.ts.map +1 -0
- package/dist/services/compression/preservation.js +109 -0
- package/dist/services/compression/preservation.js.map +1 -0
- package/dist/services/compression/registry.d.ts +6 -0
- package/dist/services/compression/registry.d.ts.map +1 -0
- package/dist/services/compression/registry.js +16 -0
- package/dist/services/compression/registry.js.map +1 -0
- package/dist/services/compression/stats.d.ts +29 -0
- package/dist/services/compression/stats.d.ts.map +1 -0
- package/dist/services/compression/stats.js +55 -0
- package/dist/services/compression/stats.js.map +1 -0
- package/dist/services/compression/types.d.ts +90 -0
- package/dist/services/compression/types.d.ts.map +1 -0
- package/dist/services/compression/types.js +2 -0
- package/dist/services/compression/types.js.map +1 -0
- package/dist/services/context-handoff.d.ts +22 -0
- package/dist/services/context-handoff.d.ts.map +1 -0
- package/dist/services/context-handoff.js +164 -0
- package/dist/services/context-handoff.js.map +1 -0
- package/dist/services/cooldown-probe.d.ts +24 -0
- package/dist/services/cooldown-probe.d.ts.map +1 -0
- package/dist/services/cooldown-probe.js +181 -0
- package/dist/services/cooldown-probe.js.map +1 -0
- package/dist/services/custom-endpoint.d.ts +58 -0
- package/dist/services/custom-endpoint.d.ts.map +1 -0
- package/dist/services/custom-endpoint.js +167 -0
- package/dist/services/custom-endpoint.js.map +1 -0
- package/dist/services/custom-media-register.d.ts +22 -0
- package/dist/services/custom-media-register.d.ts.map +1 -0
- package/dist/services/custom-media-register.js +45 -0
- package/dist/services/custom-media-register.js.map +1 -0
- package/dist/services/custom-model-register.d.ts +50 -0
- package/dist/services/custom-model-register.d.ts.map +1 -0
- package/dist/services/custom-model-register.js +103 -0
- package/dist/services/custom-model-register.js.map +1 -0
- package/dist/services/custom-model-seed.d.ts +18 -0
- package/dist/services/custom-model-seed.d.ts.map +1 -0
- package/dist/services/custom-model-seed.js +42 -0
- package/dist/services/custom-model-seed.js.map +1 -0
- package/dist/services/custom-model-sync.d.ts +37 -0
- package/dist/services/custom-model-sync.d.ts.map +1 -0
- package/dist/services/custom-model-sync.js +118 -0
- package/dist/services/custom-model-sync.js.map +1 -0
- package/dist/services/custom-model-tombstone.d.ts +5 -0
- package/dist/services/custom-model-tombstone.d.ts.map +1 -0
- package/dist/services/custom-model-tombstone.js +30 -0
- package/dist/services/custom-model-tombstone.js.map +1 -0
- package/dist/services/declarative-config.d.ts +356 -0
- package/dist/services/declarative-config.d.ts.map +1 -0
- package/dist/services/declarative-config.js +427 -0
- package/dist/services/declarative-config.js.map +1 -0
- package/dist/services/degradation.d.ts +40 -0
- package/dist/services/degradation.d.ts.map +1 -0
- package/dist/services/degradation.js +119 -0
- package/dist/services/degradation.js.map +1 -0
- package/dist/services/embeddings.d.ts +76 -0
- package/dist/services/embeddings.d.ts.map +1 -0
- package/dist/services/embeddings.js +319 -0
- package/dist/services/embeddings.js.map +1 -0
- package/dist/services/fusion.d.ts +162 -0
- package/dist/services/fusion.d.ts.map +1 -0
- package/dist/services/fusion.js +789 -0
- package/dist/services/fusion.js.map +1 -0
- package/dist/services/gemini-map.d.ts +14 -0
- package/dist/services/gemini-map.d.ts.map +1 -0
- package/dist/services/gemini-map.js +78 -0
- package/dist/services/gemini-map.js.map +1 -0
- package/dist/services/health.d.ts +52 -0
- package/dist/services/health.d.ts.map +1 -0
- package/dist/services/health.js +352 -0
- package/dist/services/health.js.map +1 -0
- package/dist/services/idempotency.d.ts +49 -0
- package/dist/services/idempotency.d.ts.map +1 -0
- package/dist/services/idempotency.js +140 -0
- package/dist/services/idempotency.js.map +1 -0
- package/dist/services/key-budget.d.ts +74 -0
- package/dist/services/key-budget.d.ts.map +1 -0
- package/dist/services/key-budget.js +200 -0
- package/dist/services/key-budget.js.map +1 -0
- package/dist/services/media.d.ts +123 -0
- package/dist/services/media.d.ts.map +1 -0
- package/dist/services/media.js +954 -0
- package/dist/services/media.js.map +1 -0
- package/dist/services/model-discovery.d.ts +126 -0
- package/dist/services/model-discovery.d.ts.map +1 -0
- package/dist/services/model-discovery.js +662 -0
- package/dist/services/model-discovery.js.map +1 -0
- package/dist/services/model-groups.d.ts +149 -0
- package/dist/services/model-groups.d.ts.map +1 -0
- package/dist/services/model-groups.js +314 -0
- package/dist/services/model-groups.js.map +1 -0
- package/dist/services/model-listing.d.ts +18 -0
- package/dist/services/model-listing.d.ts.map +1 -0
- package/dist/services/model-listing.js +94 -0
- package/dist/services/model-listing.js.map +1 -0
- package/dist/services/model-retirement.d.ts +29 -0
- package/dist/services/model-retirement.d.ts.map +1 -0
- package/dist/services/model-retirement.js +86 -0
- package/dist/services/model-retirement.js.map +1 -0
- package/dist/services/model-state.d.ts +90 -0
- package/dist/services/model-state.d.ts.map +1 -0
- package/dist/services/model-state.js +342 -0
- package/dist/services/model-state.js.map +1 -0
- package/dist/services/model-weight-overrides.d.ts +48 -0
- package/dist/services/model-weight-overrides.d.ts.map +1 -0
- package/dist/services/model-weight-overrides.js +127 -0
- package/dist/services/model-weight-overrides.js.map +1 -0
- package/dist/services/notification-emitter.d.ts +50 -0
- package/dist/services/notification-emitter.d.ts.map +1 -0
- package/dist/services/notification-emitter.js +177 -0
- package/dist/services/notification-emitter.js.map +1 -0
- package/dist/services/opencode-free-sync.d.ts +29 -0
- package/dist/services/opencode-free-sync.d.ts.map +1 -0
- package/dist/services/opencode-free-sync.js +206 -0
- package/dist/services/opencode-free-sync.js.map +1 -0
- package/dist/services/penalty-inspector.d.ts +56 -0
- package/dist/services/penalty-inspector.d.ts.map +1 -0
- package/dist/services/penalty-inspector.js +167 -0
- package/dist/services/penalty-inspector.js.map +1 -0
- package/dist/services/profile-models.d.ts +5 -0
- package/dist/services/profile-models.d.ts.map +1 -0
- package/dist/services/profile-models.js +62 -0
- package/dist/services/profile-models.js.map +1 -0
- package/dist/services/provider-credential.d.ts +19 -0
- package/dist/services/provider-credential.d.ts.map +1 -0
- package/dist/services/provider-credential.js +51 -0
- package/dist/services/provider-credential.js.map +1 -0
- package/dist/services/provider-quota.d.ts +64 -0
- package/dist/services/provider-quota.d.ts.map +1 -0
- package/dist/services/provider-quota.js +563 -0
- package/dist/services/provider-quota.js.map +1 -0
- package/dist/services/quirks.d.ts +0 -0
- package/dist/services/quirks.d.ts.map +1 -0
- package/dist/services/quirks.js +0 -0
- package/dist/services/quirks.js.map +1 -0
- package/dist/services/quota-forecast.d.ts +50 -0
- package/dist/services/quota-forecast.d.ts.map +1 -0
- package/dist/services/quota-forecast.js +150 -0
- package/dist/services/quota-forecast.js.map +1 -0
- package/dist/services/quota-outlook.d.ts +4 -0
- package/dist/services/quota-outlook.d.ts.map +1 -0
- package/dist/services/quota-outlook.js +92 -0
- package/dist/services/quota-outlook.js.map +1 -0
- package/dist/services/ratelimit.d.ts +249 -0
- package/dist/services/ratelimit.d.ts.map +1 -0
- package/dist/services/ratelimit.js +1182 -0
- package/dist/services/ratelimit.js.map +1 -0
- package/dist/services/request-retention.d.ts +60 -0
- package/dist/services/request-retention.d.ts.map +1 -0
- package/dist/services/request-retention.js +229 -0
- package/dist/services/request-retention.js.map +1 -0
- package/dist/services/router.d.ts +384 -0
- package/dist/services/router.d.ts.map +1 -0
- package/dist/services/router.js +1986 -0
- package/dist/services/router.js.map +1 -0
- package/dist/services/scoring.d.ts +156 -0
- package/dist/services/scoring.d.ts.map +1 -0
- package/dist/services/scoring.js +435 -0
- package/dist/services/scoring.js.map +1 -0
- package/dist/services/url-tokens.d.ts +15 -0
- package/dist/services/url-tokens.d.ts.map +1 -0
- package/dist/services/url-tokens.js +55 -0
- package/dist/services/url-tokens.js.map +1 -0
- package/package.json +77 -4
- package/README.md +0 -3
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
// Upstream-error classification shared by the proxy chat path, the responses
|
|
2
|
+
// path, and the fusion panel. Pure functions over an error's message/status —
|
|
3
|
+
// no I/O — so they live in a neutral lib module that any of those can import
|
|
4
|
+
// without forming an import cycle (fusion ↔ proxy in particular).
|
|
5
|
+
export function isRetryableError(err) {
|
|
6
|
+
const msg = (err.message ?? '').toLowerCase();
|
|
7
|
+
// Trust the upstream HTTP status the provider attached to the error first
|
|
8
|
+
// (providerHttpError in providers/base.ts sets err.status on every adapter).
|
|
9
|
+
// This structured check is the robust primary signal; the message-substring
|
|
10
|
+
// rules below are the fallback for errors that carry a code in their text but
|
|
11
|
+
// no numeric status. It's the fix for #337/#339: an Ollama "410 Gone", or any
|
|
12
|
+
// upstream 5xx the substring allowlist never enumerated (502/504/507…), used to
|
|
13
|
+
// fall through to a 502 and STRAND the healthy paid routes still queued later in
|
|
14
|
+
// the chain — because the old code matched specific substrings and ignored
|
|
15
|
+
// err.status for every code except 403. 408 (request timeout), 409 (conflict),
|
|
16
|
+
// 410 (model pulled upstream), 429 (rate limit) and all 5xx are transient or
|
|
17
|
+
// fail-over-able; 400/401 stay fatal (status 0 here, handled by the absence of a
|
|
18
|
+
// matching rule) and 403 is handled by isModelAccessForbiddenError below.
|
|
19
|
+
// 422 (notably Mistral's strict validation) is a provider-side request-shape
|
|
20
|
+
// rejection: fail over to another provider, but if the whole chain rejects it
|
|
21
|
+
// exhaustedRetryError renders a client-facing 400 via isProviderBadRequestError.
|
|
22
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
23
|
+
if (status === 408 || status === 409 || status === 410 || status === 422 || status === 429 || status >= 500)
|
|
24
|
+
return true;
|
|
25
|
+
return msg.includes('429') || msg.includes('rate limit') || msg.includes('too many requests')
|
|
26
|
+
|| msg.includes('quota') || msg.includes('resource_exhausted')
|
|
27
|
+
|| msg.includes('aborted') || msg.includes('timeout') || msg.includes('etimedout')
|
|
28
|
+
|| msg.includes('econnrefused') || msg.includes('econnreset')
|
|
29
|
+
|| msg.includes('fetch failed') // undici transport error (proxy down, DNS, TLS, etc.)
|
|
30
|
+
|| msg.includes('503') || msg.includes('unavailable')
|
|
31
|
+
// Provider marks the hosted deployment itself as sick (NVIDIA NIM's
|
|
32
|
+
// "DEGRADED function cannot be invoked" arrives as a 400, #522). The
|
|
33
|
+
// 'api error 400' rule below already catches the NIM shape; this keeps
|
|
34
|
+
// degraded conditions retryable even when a provider words it differently.
|
|
35
|
+
|| msg.includes('degraded')
|
|
36
|
+
|| msg.includes('500') || msg.includes('internal server error')
|
|
37
|
+
// 413: this model's payload limit is too small for the request, but another
|
|
38
|
+
// provider in the fallback chain may have a larger limit. Same reasoning as 503.
|
|
39
|
+
|| msg.includes('413') || msg.includes('payload too large') || msg.includes('request body too large')
|
|
40
|
+
|| msg.includes('request entity too large') || msg.includes('content too large')
|
|
41
|
+
// Context/prompt-too-large in all its provider wordings (Anthropic "prompt
|
|
42
|
+
// is too long", Google "input token count ... exceeds", OpenAI "maximum
|
|
43
|
+
// context length", …): another candidate may have a larger window, so fail
|
|
44
|
+
// over; if EVERY candidate rejects it the exhaustion ladder renders an
|
|
45
|
+
// honest 413 instead of a generic failure.
|
|
46
|
+
|| isContextTooLargeError(err)
|
|
47
|
+
// 404: model deprecated/removed upstream (e.g. OpenRouter's "no endpoints found"
|
|
48
|
+
// for a model that's been pulled). Rotate to the next model in the chain —
|
|
49
|
+
// setCooldown + the health checker will avoid this model on subsequent requests.
|
|
50
|
+
|| msg.includes('404') || msg.includes('not found') || msg.includes('no endpoints found')
|
|
51
|
+
// 410: the model/endpoint was permanently removed upstream (e.g. Ollama Cloud
|
|
52
|
+
// "API error 410: Gone", #339). Like a 404 it won't return on this provider, so
|
|
53
|
+
// rotate to the next route; isModelNotFoundError benches the whole model. The
|
|
54
|
+
// structured status check above already catches the 410 when the provider
|
|
55
|
+
// attaches err.status — this is the text fallback for errors that don't.
|
|
56
|
+
|| msg.includes('410') || msg.includes('gone')
|
|
57
|
+
// 403: the key is valid (it passed validateKey, and the health checker
|
|
58
|
+
// disables truly-forbidden keys) but this specific model is off-limits to
|
|
59
|
+
// the key's tier — e.g. gpt-4o on GitHub Models' free tier, subscription-only
|
|
60
|
+
// models on Cloudflare. Another model in the chain is reachable, so fail over
|
|
61
|
+
// instead of 502-ing the whole request. Paired with isModelAccessForbiddenError
|
|
62
|
+
// to rule the model out for this request and a day-long bench. See issue #256.
|
|
63
|
+
|| isModelAccessForbiddenError(err)
|
|
64
|
+
// 400: one provider may reject parameters another accepts (e.g. max_tokens
|
|
65
|
+
// limits, unsupported params). The matching pattern is "api error 400"
|
|
66
|
+
// which comes from the OpenAI-compat provider's error formatting, not
|
|
67
|
+
// a bare "400" which is deliberately non-retryable for validation errors.
|
|
68
|
+
|| msg.includes('api error 400')
|
|
69
|
+
// 422: Mistral and other strict OpenAI-compatible endpoints use
|
|
70
|
+
// Unprocessable Entity for request-shape validation. Rotate to a provider
|
|
71
|
+
// that accepts the same OpenAI payload; if every provider rejects it, render
|
|
72
|
+
// a clean invalid_request_error instead of a rate-limit exhaustion.
|
|
73
|
+
|| msg.includes('api error 422') || msg.includes('unprocessable entity')
|
|
74
|
+
// 402: this provider/key is out of credits (e.g. HuggingFace Router
|
|
75
|
+
// "API error 402: Payment required"). The SAME model often lives on another
|
|
76
|
+
// provider (Kimi K2.6 is on HF + Cloudflare + NVIDIA), so fail over instead
|
|
77
|
+
// of killing the workflow. Paired with a long cooldown (isPaymentRequiredError)
|
|
78
|
+
// so we don't re-hammer the broke key every retry.
|
|
79
|
+
|| isPaymentRequiredError(err)
|
|
80
|
+
// Dead-turn classes from the stream turn-integrity layer (#231 audit):
|
|
81
|
+
// all thrown before any byte reached the client, so another model can
|
|
82
|
+
// serve the request invisibly.
|
|
83
|
+
|| msg.includes('empty completion')
|
|
84
|
+
// The model answered in prose despite a response_format request (and the
|
|
85
|
+
// JSON couldn't be healed out of the text) — thrown before any byte
|
|
86
|
+
// reached the client, so the next candidate can serve it invisibly.
|
|
87
|
+
|| msg.includes('ignored response_format')
|
|
88
|
+
// The model DID emit JSON but ran out of max_tokens mid-value
|
|
89
|
+
// (finish_reason 'length'). A terser model may fit the same schema in the
|
|
90
|
+
// same budget, so fail over — but the thrower marks the model skipped for
|
|
91
|
+
// this request: retrying the same model would truncate identically.
|
|
92
|
+
|| msg.includes('truncated json')
|
|
93
|
+
|| msg.includes('in-band provider error')
|
|
94
|
+
|| msg.includes('stream ended unexpectedly')
|
|
95
|
+
|| msg.includes('stream stalled')
|
|
96
|
+
// First-byte timeout (#584): the grace budget expired before ANY byte
|
|
97
|
+
// reached the client, so the next candidate can serve it invisibly.
|
|
98
|
+
|| msg.includes('no first byte')
|
|
99
|
+
|| msg.includes('unparseable inline tool-call dialect')
|
|
100
|
+
// The model emitted a tool call whose arguments violate the schema the
|
|
101
|
+
// caller declared (opt-in check, lib/tool-validate.ts). Thrown before any
|
|
102
|
+
// byte reached the client, and a different model usually gets the same
|
|
103
|
+
// call right — the thrower marks the model skipped for this request, since
|
|
104
|
+
// a sibling key would misbehave identically.
|
|
105
|
+
|| msg.includes('invalid tool arguments')
|
|
106
|
+
// A transport failure undici buried in `err.cause` rather than the
|
|
107
|
+
// top-level message (see isTransportError). Purely additive: every rule
|
|
108
|
+
// above is unchanged, and this is a second, structured signal for the
|
|
109
|
+
// errors whose real cause never reaches the text we match on.
|
|
110
|
+
|| isTransportError(err);
|
|
111
|
+
}
|
|
112
|
+
// ── Transport failures hidden in the cause chain (undici) ────────────────────
|
|
113
|
+
// Every rule in isRetryableError above reads the TOP-LEVEL message, and undici
|
|
114
|
+
// does not always put the real failure there. The INITIAL-CONNECT case is
|
|
115
|
+
// covered by luck: undici words a connection that never opened "fetch failed",
|
|
116
|
+
// and the allowlist matches that string. A socket that dies MID-request does
|
|
117
|
+
// not get the same treatment — it surfaces as a generic wrapper (a bare
|
|
118
|
+
// `TypeError: terminated`, or an adapter's own re-throw) whose `.cause` carries
|
|
119
|
+
// the actual ECONNRESET / EPIPE / "socket hang up" / "premature close" /
|
|
120
|
+
// "other side closed" error, sometimes nested a link or two deeper still.
|
|
121
|
+
// Those fell through every rule and classified FATAL: the client got a 502
|
|
122
|
+
// while the healthy paid routes queued behind the dead one were never tried.
|
|
123
|
+
//
|
|
124
|
+
// Everything matched here is a transient network fault that says nothing about
|
|
125
|
+
// the request or the model, so the next candidate in the chain can serve it.
|
|
126
|
+
// The walk is bounded and cycle-safe: `cause` is attacker-adjacent data (it can
|
|
127
|
+
// come from a provider's own error object) and a self-referential chain on this
|
|
128
|
+
// hot path would hang the request, not just slow it.
|
|
129
|
+
const TRANSPORT_CAUSE_MAX_DEPTH = 5;
|
|
130
|
+
const TRANSPORT_ERROR_CODES = new Set([
|
|
131
|
+
// Node socket-level codes. A dead/refused/unreachable host is transient from
|
|
132
|
+
// the chain's point of view either way: the next candidate is a DIFFERENT
|
|
133
|
+
// host, so even a permanently bad one here is worth failing over rather than
|
|
134
|
+
// 502-ing the caller.
|
|
135
|
+
'ECONNRESET', 'ECONNREFUSED', 'ECONNABORTED', 'EPIPE', 'ETIMEDOUT',
|
|
136
|
+
'EAI_AGAIN', 'ENOTFOUND', 'EHOSTUNREACH', 'ENETUNREACH', 'EADDRNOTAVAIL',
|
|
137
|
+
]);
|
|
138
|
+
// undici stamps its own transport failures with a `UND_ERR_*` code
|
|
139
|
+
// (UND_ERR_SOCKET, UND_ERR_CONNECT_TIMEOUT, UND_ERR_HEADERS_TIMEOUT,
|
|
140
|
+
// UND_ERR_BODY_TIMEOUT, …). Matched by PREFIX rather than enumerated: the list
|
|
141
|
+
// grows with undici releases, and every member of it is a transport condition.
|
|
142
|
+
const UNDICI_ERROR_CODE_PREFIX = 'UND_ERR_';
|
|
143
|
+
const TRANSPORT_MESSAGE_HINTS = [
|
|
144
|
+
'socket hang up',
|
|
145
|
+
'premature close',
|
|
146
|
+
'other side closed',
|
|
147
|
+
// A socket dropped before the TLS handshake finished — undici's full wording
|
|
148
|
+
// is "Client network socket disconnected before secure TLS connection was
|
|
149
|
+
// established". The peer closed the TCP connection mid-handshake; transient.
|
|
150
|
+
'client network socket disconnected',
|
|
151
|
+
// The same codes as above, for the links that carry them in text only (an
|
|
152
|
+
// error stringified across a boundary keeps the code in its message but
|
|
153
|
+
// loses the `code` property).
|
|
154
|
+
'econnreset', 'econnrefused', 'epipe', 'etimedout', 'eai_again',
|
|
155
|
+
];
|
|
156
|
+
/** Walk an error's `cause` chain, yielding each link's `code` and `message`.
|
|
157
|
+
* Includes the error itself as the first link. Bounded to
|
|
158
|
+
* TRANSPORT_CAUSE_MAX_DEPTH hops and cycle-safe. */
|
|
159
|
+
function errorChainLinks(err) {
|
|
160
|
+
const links = [];
|
|
161
|
+
const seen = new Set();
|
|
162
|
+
let cur = err;
|
|
163
|
+
for (let depth = 0; cur != null && depth <= TRANSPORT_CAUSE_MAX_DEPTH; depth++) {
|
|
164
|
+
if (typeof cur !== 'object' && typeof cur !== 'function')
|
|
165
|
+
break;
|
|
166
|
+
if (seen.has(cur))
|
|
167
|
+
break;
|
|
168
|
+
seen.add(cur);
|
|
169
|
+
links.push({
|
|
170
|
+
code: typeof cur.code === 'string' ? cur.code : '',
|
|
171
|
+
message: typeof cur.message === 'string' ? cur.message : '',
|
|
172
|
+
});
|
|
173
|
+
cur = cur.cause;
|
|
174
|
+
}
|
|
175
|
+
return links;
|
|
176
|
+
}
|
|
177
|
+
/** True when the error — or anything in its bounded cause chain — is a
|
|
178
|
+
* transient network transport failure: a reset, dropped, refused or timed-out
|
|
179
|
+
* socket, a failed TLS handshake, or an undici transport code. */
|
|
180
|
+
export function isTransportError(err) {
|
|
181
|
+
if (err == null)
|
|
182
|
+
return false;
|
|
183
|
+
// A client hang-up and the fallback time-budget hedge BOTH reach undici as an
|
|
184
|
+
// aborted socket, and undici labels that abort UND_ERR_ABORTED — the very
|
|
185
|
+
// same code a genuine mid-flight socket death carries. Neither is provider
|
|
186
|
+
// health, so classifying either retryable would resurrect exactly what the
|
|
187
|
+
// two marked abort errors exist to prevent (no cooldown, no health penalty,
|
|
188
|
+
// no failure stats for a request the GATEWAY canceled). The structured
|
|
189
|
+
// markers are authoritative and win over any transport evidence below.
|
|
190
|
+
if (isClientAbortError(err) || isHedgeAbortError(err))
|
|
191
|
+
return false;
|
|
192
|
+
for (const { code, message } of errorChainLinks(err)) {
|
|
193
|
+
if (code && (TRANSPORT_ERROR_CODES.has(code) || code.startsWith(UNDICI_ERROR_CODE_PREFIX)))
|
|
194
|
+
return true;
|
|
195
|
+
const msg = message.toLowerCase();
|
|
196
|
+
if (!msg)
|
|
197
|
+
continue;
|
|
198
|
+
if (TRANSPORT_MESSAGE_HINTS.some(hint => msg.includes(hint)))
|
|
199
|
+
return true;
|
|
200
|
+
// undici's wording for a response body whose socket died mid-read is the
|
|
201
|
+
// bare word "terminated". Matched as the WHOLE message and never as a
|
|
202
|
+
// substring: "your account has been terminated" is a fatal billing/auth
|
|
203
|
+
// condition, and retrying that around the entire chain would burn every
|
|
204
|
+
// candidate on a request that can never succeed.
|
|
205
|
+
if (msg.trim() === 'terminated')
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
// A genuine provider QUOTA signal: a structured 429 or rate-limit/quota wording.
|
|
211
|
+
// Distinct from the much broader isRetryableError: timeouts, 5xx, transport
|
|
212
|
+
// failures and dead-turn classes are retryable but say nothing about quotas.
|
|
213
|
+
// The null-limits exhaustion heuristic in getCooldownDecisionForLimit (services/
|
|
214
|
+
// ratelimit.ts) keys off this: only an actual quota signal may feed its
|
|
215
|
+
// "effectively daily-exhausted" escalation ladder. Before this split, a slow
|
|
216
|
+
// local Ollama route timing out twice classified retryable → recorded as a
|
|
217
|
+
// null-limit "429" → escalated 2m→10m→1h→24h and 429'd every request while the
|
|
218
|
+
// server was merely busy generating (#592).
|
|
219
|
+
// Mirrors the other classifiers: trust the structured status when the adapter
|
|
220
|
+
// attached one (providerHttpError sets err.status everywhere); fall back to
|
|
221
|
+
// message markers only when there is no status.
|
|
222
|
+
export function isRateLimitSignal(err) {
|
|
223
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
224
|
+
if (status !== 0)
|
|
225
|
+
return status === 429;
|
|
226
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
227
|
+
return msg.includes('429') || msg.includes('rate limit') || msg.includes('too many requests')
|
|
228
|
+
|| msg.includes('quota') || msg.includes('resource_exhausted');
|
|
229
|
+
}
|
|
230
|
+
// ── Timeout wording ─────────────────────────────────────────────────────────
|
|
231
|
+
// The message markers that mean "this attempt ran out of time", in every
|
|
232
|
+
// wording the stack produces: the per-attempt HTTP deadline ("The operation was
|
|
233
|
+
// aborted (groq, chat, 120s)" — enrichAbort in lib/proxy.ts), the mid-stream
|
|
234
|
+
// inactivity watchdog ("… stream stalled: no data for 90000ms (timeout)"), the
|
|
235
|
+
// first-byte grace budget, and a raw socket ETIMEDOUT.
|
|
236
|
+
//
|
|
237
|
+
// A client hang-up is deliberately NOT in here: newClientAbortError's message
|
|
238
|
+
// ("client disconnected — upstream request canceled") carries none of these
|
|
239
|
+
// markers precisely so a vanished client is never read as provider slowness.
|
|
240
|
+
//
|
|
241
|
+
// Single source of truth for two consumers: the attempt-trail classifier
|
|
242
|
+
// (classifyAttemptError) and the analytics query that folds timeouts into the
|
|
243
|
+
// speed score (refreshStatsCache, #619) — so the trail and the score always
|
|
244
|
+
// agree about what a timeout is.
|
|
245
|
+
export const TIMEOUT_ERROR_MARKERS = ['timeout', 'stalled', 'etimedout', 'aborted'];
|
|
246
|
+
/** True when an error message reads as a timeout. Expects raw text; caller need
|
|
247
|
+
* not lowercase it. */
|
|
248
|
+
export function isTimeoutErrorText(message) {
|
|
249
|
+
const msg = (typeof message === 'string' ? message : String(message ?? '')).toLowerCase();
|
|
250
|
+
return TIMEOUT_ERROR_MARKERS.some(marker => msg.includes(marker));
|
|
251
|
+
}
|
|
252
|
+
// ── Client-caused aborts ─────────────────────────────────────────────────────
|
|
253
|
+
// When the gateway's OWN client hangs up, the proxy surfaces abort the composed
|
|
254
|
+
// fetch signal with this marked error, and undici rejects the in-flight fetch /
|
|
255
|
+
// body read / stream read with the same object (fetch propagates the signal's
|
|
256
|
+
// abort reason). It is deliberately NOT an AbortError and its message contains
|
|
257
|
+
// neither "aborted" nor "timeout": enrichAbort (lib/proxy.ts) must pass it
|
|
258
|
+
// through untouched, and it must never classify as a retryable provider
|
|
259
|
+
// timeout — a vanished client says nothing about provider health, so the
|
|
260
|
+
// fallback loop stops without a cooldown, health penalty, or failure stats.
|
|
261
|
+
export function newClientAbortError() {
|
|
262
|
+
const err = new Error('client disconnected — upstream request canceled');
|
|
263
|
+
err.clientAbort = true;
|
|
264
|
+
return err;
|
|
265
|
+
}
|
|
266
|
+
/** True when an error is (or wraps) the client-disconnect abort above. The
|
|
267
|
+
* structured marker is the primary signal; `cause` is checked because some
|
|
268
|
+
* transports re-wrap the abort reason, and the message substring is the last
|
|
269
|
+
* resort for errors that were stringified across a boundary. */
|
|
270
|
+
export function isClientAbortError(err) {
|
|
271
|
+
if (err?.clientAbort === true)
|
|
272
|
+
return true;
|
|
273
|
+
if (err?.cause && err.cause.clientAbort === true)
|
|
274
|
+
return true;
|
|
275
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
276
|
+
return msg.includes('client disconnected');
|
|
277
|
+
}
|
|
278
|
+
// ── Fallback time-budget hedging (fallback-v2) ──────────────────────────────
|
|
279
|
+
// When the wall-clock retry budget expires MID-FLIGHT (the current attempt is
|
|
280
|
+
// still waiting on a stalled upstream), the fallback loop aborts the composed
|
|
281
|
+
// fetch signal with this marked error. Same rationale as the client abort: it
|
|
282
|
+
// is NOT a provider-health signal, so it must never bench/cooldown/penalize
|
|
283
|
+
// the model+key, and enrichAbort must pass it through untouched. The loop
|
|
284
|
+
// catches it, renders timedOut exhaustion (the budget is spent — nothing left
|
|
285
|
+
// to try), and stops without failure bookkeeping.
|
|
286
|
+
export function newHedgeAbortError() {
|
|
287
|
+
const err = new Error('fallback time budget expired — upstream request canceled');
|
|
288
|
+
err.hedgeAbort = true;
|
|
289
|
+
return err;
|
|
290
|
+
}
|
|
291
|
+
/** True when an error is (or wraps) the time-budget hedge abort above. */
|
|
292
|
+
export function isHedgeAbortError(err) {
|
|
293
|
+
if (err?.hedgeAbort === true)
|
|
294
|
+
return true;
|
|
295
|
+
if (err?.cause && err.cause.hedgeAbort === true)
|
|
296
|
+
return true;
|
|
297
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
298
|
+
return msg.includes('fallback time budget expired');
|
|
299
|
+
}
|
|
300
|
+
/** True for any fetch-abort rejection surfacing out of a body read — the
|
|
301
|
+
* per-attempt timeout ('request'-bounds deadline in fetchWithTimeout), an
|
|
302
|
+
* AbortSignal.timeout, or the client disconnect above. Adapters that wrap
|
|
303
|
+
* res.json() in a diagnostic catch (openai-compat's non-JSON-body split) must
|
|
304
|
+
* rethrow these instead of classifying them as a malformed provider body. */
|
|
305
|
+
export function isAbortLikeError(err) {
|
|
306
|
+
if (isClientAbortError(err))
|
|
307
|
+
return true;
|
|
308
|
+
const name = err?.name;
|
|
309
|
+
return name === 'AbortError' || name === 'TimeoutError' || /\baborted\b/i.test(err?.message ?? '');
|
|
310
|
+
}
|
|
311
|
+
// A 401 / invalid-API-key error from a provider. KEY-fatal, not request-fatal:
|
|
312
|
+
// the same request is fine on the provider's sibling key or on another provider,
|
|
313
|
+
// so the fallback loop rotates past the bad key (and triggers an immediate
|
|
314
|
+
// health revalidation) instead of 502-ing the whole request. Deliberately NOT
|
|
315
|
+
// added to isRetryableError: a bad key must be skipped and revalidated, not
|
|
316
|
+
// blindly re-benched like a rate limit — the loop handles it as its own class.
|
|
317
|
+
//
|
|
318
|
+
// Status handling: every provider adapter attaches err.status (providerHttpError
|
|
319
|
+
// in providers/base.ts), so the structured status is the primary signal.
|
|
320
|
+
// - 401 → always key-auth.
|
|
321
|
+
// - 400 → key-auth ONLY for Google-style key-specific phrasings: Google
|
|
322
|
+
// reports a bad/expired key as HTTP 400 INVALID_ARGUMENT with "API key not
|
|
323
|
+
// valid" / "API key expired" / API_KEY_INVALID (#268, providers/google.ts).
|
|
324
|
+
// Without this a dead Google key classified as a provider bad-request and
|
|
325
|
+
// could exhaust into a client-blaming 400 "rejected the request as invalid".
|
|
326
|
+
// Generic auth wording (unauthorized etc.) stays excluded on a 400 so
|
|
327
|
+
// ordinary payload rejections never classify as key-auth.
|
|
328
|
+
// - any other status → not key-auth (e.g. a 403 stays model-forbidden).
|
|
329
|
+
// - no status at all → key-specific OR generic auth substrings.
|
|
330
|
+
export function isKeyAuthError(err) {
|
|
331
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
332
|
+
if (status === 401)
|
|
333
|
+
return true;
|
|
334
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
335
|
+
const keySpecific = msg.includes('api key not valid')
|
|
336
|
+
|| msg.includes('api key expired')
|
|
337
|
+
|| msg.includes('api_key_invalid');
|
|
338
|
+
if (status === 400)
|
|
339
|
+
return keySpecific;
|
|
340
|
+
if (status !== 0)
|
|
341
|
+
return false;
|
|
342
|
+
return keySpecific
|
|
343
|
+
|| msg.includes('401')
|
|
344
|
+
|| msg.includes('unauthorized')
|
|
345
|
+
|| msg.includes('invalid api key')
|
|
346
|
+
|| msg.includes('invalid_api_key')
|
|
347
|
+
|| msg.includes('incorrect api key')
|
|
348
|
+
|| msg.includes('authentication failed');
|
|
349
|
+
}
|
|
350
|
+
// A 429 whose body says the provider's DAILY free allocation is spent (observed
|
|
351
|
+
// live: Cloudflare "you have used up your daily free allocation of 10,000
|
|
352
|
+
// neurons"; OpenRouter "free-models-per-day"). A transient 90s cooldown just
|
|
353
|
+
// makes the router re-pick a dead-for-the-day provider all day, so the caller
|
|
354
|
+
// benches until the next UTC midnight instead. Requires BOTH a daily marker and
|
|
355
|
+
// a quota/allocation marker so an ordinary per-minute 429 never matches.
|
|
356
|
+
//
|
|
357
|
+
// Groq ends every limit error, per-minute and request-too-large alike, with
|
|
358
|
+
// "Need more tokens? Upgrade to Dev Tier today at …". That "today" is sales
|
|
359
|
+
// copy, not a window, so it is cut before looking for a daily marker; and a
|
|
360
|
+
// request too big for the model is never a spent allowance.
|
|
361
|
+
const UPGRADE_UPSELL = /\bupgrade to [^.?!]*?\btoday\b/g;
|
|
362
|
+
export function isDailyQuotaExhaustedError(err) {
|
|
363
|
+
if (err?.dailyQuotaExhausted === true)
|
|
364
|
+
return true;
|
|
365
|
+
if (isContextTooLargeError(err))
|
|
366
|
+
return false;
|
|
367
|
+
const msg = (err?.message ?? '').toLowerCase().replace(UPGRADE_UPSELL, '');
|
|
368
|
+
if (!/daily|per[ -_]?day|\btoday\b/.test(msg))
|
|
369
|
+
return false;
|
|
370
|
+
return /allocation|quota|limit|exhaust|used up/.test(msg);
|
|
371
|
+
}
|
|
372
|
+
// A provider-side "this hosted model is temporarily degraded" condition dressed
|
|
373
|
+
// up as a 400. Observed live on NVIDIA NIM (issue #522): a degraded function
|
|
374
|
+
// returns `400 {"detail":"Function id '...': DEGRADED function cannot be
|
|
375
|
+
// invoked"}` — the request is fine; the deployment is sick. Must NOT classify
|
|
376
|
+
// as a provider bad-request: exhausting on it would render a client-blaming
|
|
377
|
+
// 400 invalid_request_error for what is capacity/health, not request shape.
|
|
378
|
+
export function isProviderDegradedError(err) {
|
|
379
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
380
|
+
return msg.includes('degraded');
|
|
381
|
+
}
|
|
382
|
+
// #788: provider-level failures — 5xx, timeouts, transport/network errors, a
|
|
383
|
+
// degraded deployment — are symptoms of the PROVIDER being sick, not of this
|
|
384
|
+
// particular key. Retrying the same provider with a sibling key would fail
|
|
385
|
+
// identically, so the fallback loop must skip the WHOLE platform for the
|
|
386
|
+
// request instead of burning one failover hop per key. Key-scoped failures
|
|
387
|
+
// (auth, quota, 403 tier) stay out of here so a dead key can still rotate to
|
|
388
|
+
// a healthy sibling on the same platform.
|
|
389
|
+
//
|
|
390
|
+
// Classified on the STRUCTURED status — every adapter attaches one to an HTTP
|
|
391
|
+
// failure (providerHttpError in providers/base.ts) — plus the two families that
|
|
392
|
+
// carry no status at all: a timeout and a transport-level failure. Deliberately
|
|
393
|
+
// NO bare '500' / '503' / 'unavailable' / 'internal server error' substrings: a
|
|
394
|
+
// token count, a duration ("… took 5003ms") or a key-scoped message naming an
|
|
395
|
+
// unavailable model would each condemn a healthy platform for the whole request.
|
|
396
|
+
// A message check therefore only runs when there is no status to trust.
|
|
397
|
+
export function isProviderLevelError(err) {
|
|
398
|
+
// A failure the thrower explicitly scoped to the MODEL (`skipModelForRequest`
|
|
399
|
+
// — an ignored response_format, invalid tool arguments) is never provider
|
|
400
|
+
// health, and its message quotes caller- and model-supplied text: a tool
|
|
401
|
+
// named `set_timeout`, or an Ajv complaint about an instance path `/timeout`,
|
|
402
|
+
// would otherwise trip the substring checks below and condemn a healthy
|
|
403
|
+
// platform for the whole request. The structured marker is authoritative;
|
|
404
|
+
// the text is not.
|
|
405
|
+
if (err?.skipModelForRequest === true)
|
|
406
|
+
return false;
|
|
407
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
408
|
+
if (status >= 500)
|
|
409
|
+
return true;
|
|
410
|
+
// A DEGRADED hosted deployment (NVIDIA NIM, #522) is provider health wearing
|
|
411
|
+
// a 400 — same source of truth as everywhere else, not a second substring.
|
|
412
|
+
if (isProviderDegradedError(err))
|
|
413
|
+
return true;
|
|
414
|
+
if (status !== 0)
|
|
415
|
+
return false;
|
|
416
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
417
|
+
return isTimeoutErrorText(msg)
|
|
418
|
+
|| msg.includes('econnrefused') || msg.includes('econnreset')
|
|
419
|
+
|| msg.includes('fetch failed'); // undici transport error (DNS/TLS/proxy down)
|
|
420
|
+
}
|
|
421
|
+
// #809: kilo's free relay occasionally answers with a bare classification
|
|
422
|
+
// word ("safe" / "unsafe") instead of a real reply — an upstream content
|
|
423
|
+
// filter, not the requested model. Such a turn is a dead turn: treat it like
|
|
424
|
+
// an empty completion so the fallback loop fails over to the next provider
|
|
425
|
+
// instead of surfacing "safe"/"unsafe" as the answer.
|
|
426
|
+
//
|
|
427
|
+
// Scoped to the relay that actually does this. "safe"/"unsafe" is a LEGITIMATE
|
|
428
|
+
// one-word answer for moderation and guard-model workloads, so applying the
|
|
429
|
+
// rule everywhere would throw away correct responses and burn the whole
|
|
430
|
+
// fallback chain for anyone doing classification. Only platforms observed
|
|
431
|
+
// injecting a filter verdict in place of the model's reply belong here.
|
|
432
|
+
const CLASSIFICATION_RELAY_PLATFORMS = new Set(['kilo']);
|
|
433
|
+
export function isUpstreamClassificationOutput(text, platform) {
|
|
434
|
+
if (!platform || !CLASSIFICATION_RELAY_PLATFORMS.has(platform.toLowerCase()))
|
|
435
|
+
return false;
|
|
436
|
+
const t = (typeof text === 'string' ? text : '').trim().toLowerCase();
|
|
437
|
+
return t === 'safe' || t === 'unsafe';
|
|
438
|
+
}
|
|
439
|
+
// Provider-side 400s are retryable because another provider may accept the same
|
|
440
|
+
// request shape. If every routed provider rejects it, however, the client should
|
|
441
|
+
// see an invalid-request error rather than a misleading rate-limit exhaustion.
|
|
442
|
+
export function isProviderBadRequestError(err) {
|
|
443
|
+
if (isProviderDegradedError(err))
|
|
444
|
+
return false;
|
|
445
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
446
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
447
|
+
if (status === 400)
|
|
448
|
+
return msg.includes('api error 400');
|
|
449
|
+
if (status === 422)
|
|
450
|
+
return msg.includes('api error 422') || msg.includes('unprocessable entity');
|
|
451
|
+
if (status !== 0)
|
|
452
|
+
return false;
|
|
453
|
+
return msg.includes('api error 400') || msg.includes('api error 422') || msg.includes('unprocessable entity');
|
|
454
|
+
}
|
|
455
|
+
// A "this request/prompt is too large" rejection. Providers word it very
|
|
456
|
+
// differently and even disagree on the HTTP status:
|
|
457
|
+
// - OpenAI-compat: 400 with code `context_length_exceeded` — "This model's
|
|
458
|
+
// maximum context length is 8192 tokens. However, your messages resulted
|
|
459
|
+
// in 10001 tokens. Please reduce the length of the messages."
|
|
460
|
+
// - Anthropic: 400 invalid_request_error — "prompt is too long: 210000
|
|
461
|
+
// tokens > 200000 maximum" (Bedrock words it "Input is too long for
|
|
462
|
+
// requested model.")
|
|
463
|
+
// - Google/Gemini: 400 INVALID_ARGUMENT — "The input token count (1200000)
|
|
464
|
+
// exceeds the maximum number of tokens allowed (1048576)."
|
|
465
|
+
// - Groq: a literal HTTP 413 — "Request too large for model `x` ... on
|
|
466
|
+
// tokens per minute (TPM): Limit 30000, Requested 33476". Requested >
|
|
467
|
+
// Limit can never fit that candidate's window, so it belongs here (too
|
|
468
|
+
// large for the candidate), not with transient per-minute 429s.
|
|
469
|
+
// - Reverse proxies / gateways: 413 "Payload Too Large" / "request entity
|
|
470
|
+
// too large" / "content too large".
|
|
471
|
+
// Structured status first (providerHttpError attaches err.status on every
|
|
472
|
+
// adapter), then the code field, then message markers — mirroring how the
|
|
473
|
+
// other classifiers in this file work. Retryable (a sibling candidate may have
|
|
474
|
+
// a larger window), but when EVERY attempt dies this way the exhaustion ladder
|
|
475
|
+
// renders an honest 413 instead of a generic failure.
|
|
476
|
+
export function isContextTooLargeError(err) {
|
|
477
|
+
if (err?.status === 413)
|
|
478
|
+
return true;
|
|
479
|
+
if (typeof err?.code === 'string' && err.code.toLowerCase() === 'context_length_exceeded')
|
|
480
|
+
return true;
|
|
481
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
482
|
+
return msg.includes('context_length_exceeded')
|
|
483
|
+
|| msg.includes('maximum context length')
|
|
484
|
+
|| msg.includes('context length exceeded')
|
|
485
|
+
|| /exceeds[^.]*context (length|window|size)/.test(msg)
|
|
486
|
+
|| msg.includes('prompt is too long')
|
|
487
|
+
|| msg.includes('input is too long')
|
|
488
|
+
|| /input token count[^.]*exceeds/.test(msg)
|
|
489
|
+
|| msg.includes('exceeds the maximum number of tokens')
|
|
490
|
+
|| msg.includes('request too large')
|
|
491
|
+
|| msg.includes('payload too large')
|
|
492
|
+
|| msg.includes('request entity too large')
|
|
493
|
+
|| msg.includes('request body too large')
|
|
494
|
+
|| msg.includes('content too large')
|
|
495
|
+
// Zhipu AI (bigmodel.cn) 400, error code 1261: "Prompt exceeds max length"
|
|
496
|
+
// (#873). Its wording matches none of the markers above, so without this it
|
|
497
|
+
// was mis-bucketed as provider_bad_request instead of context_too_large.
|
|
498
|
+
|| msg.includes('exceeds max length')
|
|
499
|
+
|| msg.includes('api error 413');
|
|
500
|
+
}
|
|
501
|
+
// A 402 Payment Required / out-of-credits error. Distinct from a transient 429:
|
|
502
|
+
// it won't recover on the next window, so the caller benches the model+key with
|
|
503
|
+
// PAYMENT_REQUIRED_COOLDOWN_MS (a full day) rather than the 90s transient cooldown.
|
|
504
|
+
//
|
|
505
|
+
// The digits 402 only count as the STATUS. A bare `includes('402')` also
|
|
506
|
+
// matched token counts and request ids ("Limit 30000, Requested 34026",
|
|
507
|
+
// "14023 tokens used"), and since the 402 bench covers the key on every model
|
|
508
|
+
// of the platform for a day (#1239), one unlucky number took a whole provider
|
|
509
|
+
// out. So: an error that states another status is never a 402 by its digits,
|
|
510
|
+
// and otherwise 402 has to stand alone rather than sit inside a longer number.
|
|
511
|
+
const STATED_STATUS = /\bapi error (\d{3})\b|\(http (\d{3})\)/;
|
|
512
|
+
const STANDALONE_402 = /(?<![\w.])402(?![\w.])/;
|
|
513
|
+
export function isPaymentRequiredError(err) {
|
|
514
|
+
const msg = String(err?.message ?? '').toLowerCase();
|
|
515
|
+
if (msg.includes('payment required')
|
|
516
|
+
|| msg.includes('insufficient_quota') || msg.includes('insufficient credit')
|
|
517
|
+
|| msg.includes('insufficient balance'))
|
|
518
|
+
return true;
|
|
519
|
+
const stated = msg.match(STATED_STATUS);
|
|
520
|
+
const status = typeof err?.status === 'number' ? err.status : Number(stated?.[1] ?? stated?.[2]);
|
|
521
|
+
if (Number.isFinite(status))
|
|
522
|
+
return status === 402;
|
|
523
|
+
return STANDALONE_402.test(msg);
|
|
524
|
+
}
|
|
525
|
+
// "model 'x' does not exist" / "model \"x\" does not exist" / "model x does not
|
|
526
|
+
// exist" — one non-space token (optionally quoted) between the word "model" and
|
|
527
|
+
// the verdict. Bounded so an unrelated sentence containing both words never
|
|
528
|
+
// matches; the model id itself is never inspected.
|
|
529
|
+
const MODEL_ID_DOES_NOT_EXIST = /\bmodel\b\s+['"`]?[^\s'"`]{1,200}['"`]?\s+(?:does\s+not|doesn't)\s+exist\b/;
|
|
530
|
+
// A 404 "model removed/deprecated upstream" error. It's a MODEL-level failure,
|
|
531
|
+
// not a key-level one: every key for the platform will 404 the same way, so the
|
|
532
|
+
// retry loop skips the entire model for the rest of the request instead of
|
|
533
|
+
// burning one fallback attempt per key on the same dead route.
|
|
534
|
+
// (PR #111, credits @barbotkonv.)
|
|
535
|
+
export function isModelNotFoundError(err) {
|
|
536
|
+
// 404 (removed/deprecated) and 410 (permanently Gone) are both MODEL-level: every
|
|
537
|
+
// key for the platform fails the same way, so skip the whole model for the rest
|
|
538
|
+
// of the request instead of burning one fallback attempt per sibling key. 410
|
|
539
|
+
// added for #339 (Ollama Cloud "Gone"); prefer the structured status when present.
|
|
540
|
+
if (err?.status === 404 || err?.status === 410)
|
|
541
|
+
return true;
|
|
542
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
543
|
+
return msg.includes('404') || msg.includes('not found') || msg.includes('no endpoints found')
|
|
544
|
+
|| msg.includes('410') || msg.includes('gone')
|
|
545
|
+
// Some aggregators report a removed/stale model with a 400 (not a 404) whose
|
|
546
|
+
// body reads "No model found: <id>", "model not found", "unknown model" or
|
|
547
|
+
// "model does not exist" (#: Routeway 400 "No model found: llama-3.3-70b-instruct:free").
|
|
548
|
+
// Note "No model found" does NOT contain the substring "not found" (words are
|
|
549
|
+
// no/model/found), so it slipped past the checks above and fell through to
|
|
550
|
+
// isProviderBadRequestError — surfacing as a request-blaming 400 instead of a
|
|
551
|
+
// stale-catalog 404. These phrasings are MODEL-level (every sibling key fails
|
|
552
|
+
// identically), so they belong here for the whole-model skip.
|
|
553
|
+
|| msg.includes('no model found') || msg.includes('model not found')
|
|
554
|
+
|| msg.includes('unknown model') || msg.includes('model does not exist')
|
|
555
|
+
|| msg.includes('no such model')
|
|
556
|
+
// The same verdict with the model id quoted in the middle (#1239: NavyAI
|
|
557
|
+
// 400 "The model 'o3-mini' does not exist or is not supported for chat
|
|
558
|
+
// completions."). The bare "model does not exist" substring above never
|
|
559
|
+
// matches that wording, so every one of a platform's stale rows was booked
|
|
560
|
+
// as provider_bad_request — no whole-model skip, a hop burned per dead
|
|
561
|
+
// model, and the exhaustion body blamed the caller's request.
|
|
562
|
+
|| MODEL_ID_DOES_NOT_EXIST.test(msg)
|
|
563
|
+
// "not supported for chat completions" is MODEL-level too: the id is real
|
|
564
|
+
// but this platform cannot serve it on the endpoint we use, and a sibling
|
|
565
|
+
// key would be told the same. Route it out for the request like a 404.
|
|
566
|
+
|| msg.includes('not supported for chat completions');
|
|
567
|
+
}
|
|
568
|
+
// A 403 that suspends the ACCOUNT, not one model: NavyAI answers every model
|
|
569
|
+
// behind a benched free key with "The Free plan is temporarily disabled due to
|
|
570
|
+
// abuse. You can purchase a plan ...". Every model of the platform fails the
|
|
571
|
+
// same way, so classifying it as model-forbidden benched ONE model per attempt:
|
|
572
|
+
// with 93 catalog rows on that platform, each request burned its whole failover
|
|
573
|
+
// budget re-discovering the same dead account. Not key-auth either: the
|
|
574
|
+
// credential itself is valid, the plan behind it is not, and validateKey's
|
|
575
|
+
// /models probe still passes, so the health checker never demotes the key.
|
|
576
|
+
// Status-gated to 403 (or a status-less message that names one) so provider
|
|
577
|
+
// wording alone can never condemn a healthy key.
|
|
578
|
+
export function isAccountSuspendedError(err) {
|
|
579
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
580
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
581
|
+
if (status !== 403 && !(status === 0 && msg.includes('403')))
|
|
582
|
+
return false;
|
|
583
|
+
return /\b(plan|account|subscription) (is|has been|was) (temporarily )?(disabled|suspended|banned|deactivated)\b/.test(msg)
|
|
584
|
+
|| msg.includes('due to abuse');
|
|
585
|
+
}
|
|
586
|
+
// A 403 Forbidden returned for a specific model behind an otherwise-valid key.
|
|
587
|
+
// Drives the same whole-model skip as a 404: every key on this platform's tier
|
|
588
|
+
// would be forbidden the same model, so rule it out for the rest of the request
|
|
589
|
+
// rather than trying it again with a sibling key. Distinct from a dead key —
|
|
590
|
+
// validateKey returns false on 401/403, so the health checker disables genuinely
|
|
591
|
+
// forbidden keys; a 403 reaching here is model-not-on-this-tier. See issue #256.
|
|
592
|
+
export function isModelAccessForbiddenError(err) {
|
|
593
|
+
if (err?.status === 403)
|
|
594
|
+
return true;
|
|
595
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
596
|
+
if (msg.includes('403') || msg.includes('forbidden'))
|
|
597
|
+
return true;
|
|
598
|
+
// Not every provider spells "this key may not use this model" as a 403 (issue
|
|
599
|
+
// #618): observed live as a 400 whose body reads "user is not allowed to
|
|
600
|
+
// access model kat-coder-pro-v2.5", and as plan-gate wordings like "action
|
|
601
|
+
// plan limited". Classified transient, those took the 90s bench — and the
|
|
602
|
+
// auto-router re-picked the same permanently-unreachable model the moment it
|
|
603
|
+
// expired, failing and re-benching forever with an ever-growing penalty.
|
|
604
|
+
// Deliberately narrow: only 400/401 (or a status-less error), and only for
|
|
605
|
+
// phrasings that name access/permission to the MODEL. A bare "Bad Request",
|
|
606
|
+
// a generic "Unauthorized" (which isKeyAuthError owns), or a parameter
|
|
607
|
+
// rejection must keep their current classification.
|
|
608
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
609
|
+
if (status !== 0 && status !== 400 && status !== 401)
|
|
610
|
+
return false;
|
|
611
|
+
return MODEL_ACCESS_DENIED_PHRASES.some(phrase => msg.includes(phrase));
|
|
612
|
+
}
|
|
613
|
+
const MODEL_ACCESS_DENIED_PHRASES = [
|
|
614
|
+
'not allowed to access',
|
|
615
|
+
'not allowed to use',
|
|
616
|
+
'not authorized to access',
|
|
617
|
+
'not authorized to use',
|
|
618
|
+
'unauthorized to access',
|
|
619
|
+
'not permitted to access',
|
|
620
|
+
'not permitted to use',
|
|
621
|
+
'do not have access to',
|
|
622
|
+
'does not have access to',
|
|
623
|
+
'no access to model',
|
|
624
|
+
'no access to this model',
|
|
625
|
+
'model access denied',
|
|
626
|
+
'access to this model is restricted',
|
|
627
|
+
// Plan/subscription gates the provider words as a limit rather than a denial.
|
|
628
|
+
'action plan limited',
|
|
629
|
+
];
|
|
630
|
+
const END_OF_LIFE_PHRASES = [
|
|
631
|
+
'end of life',
|
|
632
|
+
'end-of-life',
|
|
633
|
+
'has been retired',
|
|
634
|
+
'has been decommissioned',
|
|
635
|
+
'has been sunset',
|
|
636
|
+
];
|
|
637
|
+
const MODEL_GONE_PHRASES = [
|
|
638
|
+
'no longer available',
|
|
639
|
+
'no longer offered',
|
|
640
|
+
'no longer supported',
|
|
641
|
+
'has been removed',
|
|
642
|
+
'was removed',
|
|
643
|
+
'has been discontinued',
|
|
644
|
+
'has been deprecated',
|
|
645
|
+
'is deprecated',
|
|
646
|
+
];
|
|
647
|
+
export function modelRetirementSignal(err) {
|
|
648
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
649
|
+
const status = typeof err?.status === 'number' ? err.status : 0;
|
|
650
|
+
const gone = status === 410 || /\berror 410\b/.test(msg) || /\b410 gone\b/.test(msg);
|
|
651
|
+
// An end-of-life phrase is only definitive when the status agrees the model
|
|
652
|
+
// is not there. On its own it is just text, and 'definitive' skips the
|
|
653
|
+
// corroboration gate in noteModelRetirementSignal — so a 429 or 500 whose
|
|
654
|
+
// body happens to mention a retirement (an advisory notice, a status-page
|
|
655
|
+
// quote, a message about a DIFFERENT model) disabled a live model on one
|
|
656
|
+
// response. Unmatched here means it falls through and teaches nothing.
|
|
657
|
+
if (gone || (isModelNotFoundError(err) && END_OF_LIFE_PHRASES.some(phrase => msg.includes(phrase))))
|
|
658
|
+
return 'definitive';
|
|
659
|
+
if (!isModelNotFoundError(err))
|
|
660
|
+
return null;
|
|
661
|
+
return MODEL_GONE_PHRASES.some(phrase => msg.includes(phrase)) ? 'probable' : null;
|
|
662
|
+
}
|
|
663
|
+
// A stream that ended without its terminal marker (`[DONE]` and/or a
|
|
664
|
+
// finish_reason): the upstream connection was reset or the response truncated
|
|
665
|
+
// mid-generation. Observed live on Kilo Gateway (5 attempts in one session,
|
|
666
|
+
// #1218): the gateway answers 200, streams content, then dies without
|
|
667
|
+
// `data: [DONE]` — `readSseStream` throws
|
|
668
|
+
// "…stream ended unexpectedly (no [DONE], no finish_reason)".
|
|
669
|
+
//
|
|
670
|
+
// The truncation is UPSTREAM transport, not request shape, so the plain
|
|
671
|
+
// retryable path (a fresh attempt on a sibling key, or even the same key
|
|
672
|
+
// later) is the right response — but a stream that dies with zero content
|
|
673
|
+
// deltas is usually the ROUTE (platform+model+key edge) that is sick, not
|
|
674
|
+
// bad luck: three empty-ended truncations in a row on the same route
|
|
675
|
+
// reliably precede another one. Callers use this signal to bench the route
|
|
676
|
+
// after a short streak instead of re-paying the round trip every request.
|
|
677
|
+
export function isStreamTruncatedError(err) {
|
|
678
|
+
const msg = (err?.message ?? '').toLowerCase();
|
|
679
|
+
return msg.includes('stream ended unexpectedly')
|
|
680
|
+
|| msg.includes('no [done], no finish_reason')
|
|
681
|
+
// undici surfaces an abrupt RST as "terminated" on the body read; with
|
|
682
|
+
// our SSE reader the top-level message is "terminated" and the real
|
|
683
|
+
// cause is buried in err.cause (see isTransportError). Count it too:
|
|
684
|
+
// a terminated mid-stream body is the same dead route either way.
|
|
685
|
+
|| msg === 'terminated';
|
|
686
|
+
}
|
|
687
|
+
//# sourceMappingURL=error-classify.js.map
|