@slkiser/opencode-quota 5.0.3 → 6.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +30 -44
- package/dist/agent-tools.d.ts +24 -0
- package/dist/agent-tools.d.ts.map +1 -0
- package/dist/agent-tools.js +578 -0
- package/dist/agent-tools.js.map +1 -0
- package/dist/bin/opencode-quota.d.ts.map +1 -1
- package/dist/bin/opencode-quota.js +1 -32
- package/dist/bin/opencode-quota.js.map +1 -1
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +141 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/pace.d.ts +13 -0
- package/dist/core/pace.d.ts.map +1 -0
- package/dist/core/pace.js +52 -0
- package/dist/core/pace.js.map +1 -0
- package/dist/core/persist.d.ts +44 -0
- package/dist/core/persist.d.ts.map +1 -0
- package/dist/core/persist.js +210 -0
- package/dist/core/persist.js.map +1 -0
- package/dist/core/provider-source.d.ts +40 -0
- package/dist/core/provider-source.d.ts.map +1 -0
- package/dist/core/provider-source.js +210 -0
- package/dist/core/provider-source.js.map +1 -0
- package/dist/core/redact.d.ts +17 -0
- package/dist/core/redact.d.ts.map +1 -0
- package/dist/core/redact.js +217 -0
- package/dist/core/redact.js.map +1 -0
- package/dist/core/rows.d.ts +20 -0
- package/dist/core/rows.d.ts.map +1 -0
- package/dist/core/rows.js +142 -0
- package/dist/core/rows.js.map +1 -0
- package/dist/core/selection.d.ts +15 -0
- package/dist/core/selection.d.ts.map +1 -0
- package/dist/core/selection.js +43 -0
- package/dist/core/selection.js.map +1 -0
- package/dist/core/snapshot-publisher.d.ts +15 -0
- package/dist/core/snapshot-publisher.d.ts.map +1 -0
- package/dist/core/snapshot-publisher.js +57 -0
- package/dist/core/snapshot-publisher.js.map +1 -0
- package/dist/core/store.d.ts +93 -0
- package/dist/core/store.d.ts.map +1 -0
- package/dist/core/store.js +563 -0
- package/dist/core/store.js.map +1 -0
- package/dist/core/types.d.ts +186 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +2 -0
- package/dist/core/types.js.map +1 -0
- package/dist/core/usage-ranges.d.ts +46 -0
- package/dist/core/usage-ranges.d.ts.map +1 -0
- package/dist/core/usage-ranges.js +72 -0
- package/dist/core/usage-ranges.js.map +1 -0
- package/dist/core/usage.d.ts +100 -0
- package/dist/core/usage.d.ts.map +1 -0
- package/dist/core/usage.js +373 -0
- package/dist/core/usage.js.map +1 -0
- package/dist/core/validate.d.ts +8 -0
- package/dist/core/validate.d.ts.map +1 -0
- package/dist/core/validate.js +167 -0
- package/dist/core/validate.js.map +1 -0
- package/dist/core/windows.d.ts +24 -0
- package/dist/core/windows.d.ts.map +1 -0
- package/dist/core/windows.js +43 -0
- package/dist/core/windows.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/accounting-format.d.ts +2 -52
- package/dist/lib/accounting-format.d.ts.map +1 -1
- package/dist/lib/accounting-format.js +6 -255
- package/dist/lib/accounting-format.js.map +1 -1
- package/dist/lib/alibaba-auth.d.ts +14 -21
- package/dist/lib/alibaba-auth.d.ts.map +1 -1
- package/dist/lib/alibaba-auth.js +36 -149
- package/dist/lib/alibaba-auth.js.map +1 -1
- package/dist/lib/alibaba-coding-plan-local-quota.d.ts +1 -6
- package/dist/lib/alibaba-coding-plan-local-quota.d.ts.map +1 -1
- package/dist/lib/alibaba-coding-plan-local-quota.js +1 -1
- package/dist/lib/alibaba-coding-plan-local-quota.js.map +1 -1
- package/dist/lib/alibaba-token-plan.d.ts +18 -27
- package/dist/lib/alibaba-token-plan.d.ts.map +1 -1
- package/dist/lib/alibaba-token-plan.js +121 -285
- package/dist/lib/alibaba-token-plan.js.map +1 -1
- package/dist/lib/anthropic-auth.d.ts +3 -5
- package/dist/lib/anthropic-auth.d.ts.map +1 -1
- package/dist/lib/anthropic-auth.js +6 -9
- package/dist/lib/anthropic-auth.js.map +1 -1
- package/dist/lib/anthropic.d.ts +12 -37
- package/dist/lib/anthropic.d.ts.map +1 -1
- package/dist/lib/anthropic.js +348 -698
- package/dist/lib/anthropic.js.map +1 -1
- package/dist/lib/api-key-resolver.d.ts +165 -192
- package/dist/lib/api-key-resolver.d.ts.map +1 -1
- package/dist/lib/api-key-resolver.js +208 -234
- package/dist/lib/api-key-resolver.js.map +1 -1
- package/dist/lib/atomic-json.d.ts +4 -1
- package/dist/lib/atomic-json.d.ts.map +1 -1
- package/dist/lib/atomic-json.js +2 -3
- package/dist/lib/atomic-json.js.map +1 -1
- package/dist/lib/calendar-date.d.ts +15 -0
- package/dist/lib/calendar-date.d.ts.map +1 -0
- package/dist/lib/calendar-date.js +21 -0
- package/dist/lib/calendar-date.js.map +1 -0
- package/dist/lib/chutes.d.ts +0 -1
- package/dist/lib/chutes.d.ts.map +1 -1
- package/dist/lib/chutes.js +2 -4
- package/dist/lib/chutes.js.map +1 -1
- package/dist/lib/cli-reports.d.ts +15 -11
- package/dist/lib/cli-reports.d.ts.map +1 -1
- package/dist/lib/cli-reports.js +34 -107
- package/dist/lib/cli-reports.js.map +1 -1
- package/dist/lib/cli-show.d.ts +9 -22
- package/dist/lib/cli-show.d.ts.map +1 -1
- package/dist/lib/cli-show.js +104 -75
- package/dist/lib/cli-show.js.map +1 -1
- package/dist/lib/config-file-utils.d.ts +3 -15
- package/dist/lib/config-file-utils.d.ts.map +1 -1
- package/dist/lib/config-file-utils.js +4 -63
- package/dist/lib/config-file-utils.js.map +1 -1
- package/dist/lib/config-write-target.d.ts +4 -7
- package/dist/lib/config-write-target.d.ts.map +1 -1
- package/dist/lib/config-write-target.js +4 -18
- package/dist/lib/config-write-target.js.map +1 -1
- package/dist/lib/copilot.d.ts +29 -20
- package/dist/lib/copilot.d.ts.map +1 -1
- package/dist/lib/copilot.js +392 -649
- package/dist/lib/copilot.js.map +1 -1
- package/dist/lib/cursor-detection.d.ts +3 -3
- package/dist/lib/cursor-detection.d.ts.map +1 -1
- package/dist/lib/cursor-detection.js +44 -88
- package/dist/lib/cursor-detection.js.map +1 -1
- package/dist/lib/cursor-pricing.d.ts +71 -8
- package/dist/lib/cursor-pricing.d.ts.map +1 -1
- package/dist/lib/cursor-pricing.js +33 -125
- package/dist/lib/cursor-pricing.js.map +1 -1
- package/dist/lib/cursor-usage.d.ts +6 -4
- package/dist/lib/cursor-usage.d.ts.map +1 -1
- package/dist/lib/cursor-usage.js +27 -40
- package/dist/lib/cursor-usage.js.map +1 -1
- package/dist/lib/deepseek.d.ts +9 -17
- package/dist/lib/deepseek.d.ts.map +1 -1
- package/dist/lib/deepseek.js +24 -54
- package/dist/lib/deepseek.js.map +1 -1
- package/dist/lib/display-sanitize.d.ts +0 -8
- package/dist/lib/display-sanitize.d.ts.map +1 -1
- package/dist/lib/display-sanitize.js +0 -139
- package/dist/lib/display-sanitize.js.map +1 -1
- package/dist/lib/entries.d.ts +13 -239
- package/dist/lib/entries.d.ts.map +1 -1
- package/dist/lib/entries.js +1 -46
- package/dist/lib/entries.js.map +1 -1
- package/dist/lib/file-lock.d.ts +23 -0
- package/dist/lib/file-lock.d.ts.map +1 -0
- package/dist/lib/file-lock.js +122 -0
- package/dist/lib/file-lock.js.map +1 -0
- package/dist/lib/format-utils.d.ts +2 -82
- package/dist/lib/format-utils.d.ts.map +1 -1
- package/dist/lib/format-utils.js +2 -191
- package/dist/lib/format-utils.js.map +1 -1
- package/dist/lib/glm-coding-plan.d.ts +6 -5
- package/dist/lib/glm-coding-plan.d.ts.map +1 -1
- package/dist/lib/glm-coding-plan.js +19 -1
- package/dist/lib/glm-coding-plan.js.map +1 -1
- package/dist/lib/google-agy.d.ts +8 -40
- package/dist/lib/google-agy.d.ts.map +1 -1
- package/dist/lib/google-agy.js +88 -519
- package/dist/lib/google-agy.js.map +1 -1
- package/dist/lib/google-companion-credentials.d.ts +9 -40
- package/dist/lib/google-companion-credentials.d.ts.map +1 -1
- package/dist/lib/google-companion-credentials.js +167 -224
- package/dist/lib/google-companion-credentials.js.map +1 -1
- package/dist/lib/google-gemini-cli.d.ts +5 -38
- package/dist/lib/google-gemini-cli.d.ts.map +1 -1
- package/dist/lib/google-gemini-cli.js +71 -442
- package/dist/lib/google-gemini-cli.js.map +1 -1
- package/dist/lib/google-oauth-quota.d.ts +76 -0
- package/dist/lib/google-oauth-quota.d.ts.map +1 -0
- package/dist/lib/google-oauth-quota.js +297 -0
- package/dist/lib/google-oauth-quota.js.map +1 -0
- package/dist/lib/google-token-cache.d.ts +3 -5
- package/dist/lib/google-token-cache.d.ts.map +1 -1
- package/dist/lib/google-token-cache.js +2 -14
- package/dist/lib/google-token-cache.js.map +1 -1
- package/dist/lib/home-dir-display.d.ts.map +1 -1
- package/dist/lib/home-dir-display.js +21 -39
- package/dist/lib/home-dir-display.js.map +1 -1
- package/dist/lib/http.d.ts +4 -1
- package/dist/lib/http.d.ts.map +1 -1
- package/dist/lib/http.js +2 -1
- package/dist/lib/http.js.map +1 -1
- package/dist/lib/json-guards.d.ts +11 -0
- package/dist/lib/json-guards.d.ts.map +1 -0
- package/dist/lib/json-guards.js +25 -0
- package/dist/lib/json-guards.js.map +1 -0
- package/dist/lib/kilo.d.ts +0 -2
- package/dist/lib/kilo.d.ts.map +1 -1
- package/dist/lib/kilo.js +33 -116
- package/dist/lib/kilo.js.map +1 -1
- package/dist/lib/kimi-endpoints.d.ts +2 -2
- package/dist/lib/kimi-endpoints.d.ts.map +1 -1
- package/dist/lib/kimi-endpoints.js +1 -1
- package/dist/lib/kimi-endpoints.js.map +1 -1
- package/dist/lib/kimi.d.ts.map +1 -1
- package/dist/lib/kimi.js +40 -86
- package/dist/lib/kimi.js.map +1 -1
- package/dist/lib/maintainer-announcements.d.ts +4 -17
- package/dist/lib/maintainer-announcements.d.ts.map +1 -1
- package/dist/lib/maintainer-announcements.js +7 -44
- package/dist/lib/maintainer-announcements.js.map +1 -1
- package/dist/lib/maintainer-home-notice.d.ts +19 -0
- package/dist/lib/maintainer-home-notice.d.ts.map +1 -0
- package/dist/lib/maintainer-home-notice.js +92 -0
- package/dist/lib/maintainer-home-notice.js.map +1 -0
- package/dist/lib/mimo-config.d.ts +6 -9
- package/dist/lib/mimo-config.d.ts.map +1 -1
- package/dist/lib/mimo-config.js +43 -74
- package/dist/lib/mimo-config.js.map +1 -1
- package/dist/lib/mimo.d.ts +2 -5
- package/dist/lib/mimo.d.ts.map +1 -1
- package/dist/lib/mimo.js +57 -109
- package/dist/lib/mimo.js.map +1 -1
- package/dist/lib/minimax-endpoints.d.ts +2 -2
- package/dist/lib/minimax-endpoints.d.ts.map +1 -1
- package/dist/lib/minimax-endpoints.js +1 -1
- package/dist/lib/minimax-endpoints.js.map +1 -1
- package/dist/lib/modelsdev-pricing.d.ts +22 -16
- package/dist/lib/modelsdev-pricing.d.ts.map +1 -1
- package/dist/lib/modelsdev-pricing.js +279 -560
- package/dist/lib/modelsdev-pricing.js.map +1 -1
- package/dist/lib/nanogpt.d.ts +6 -6
- package/dist/lib/nanogpt.d.ts.map +1 -1
- package/dist/lib/nanogpt.js +19 -72
- package/dist/lib/nanogpt.js.map +1 -1
- package/dist/lib/ollama-cloud.d.ts +3 -6
- package/dist/lib/ollama-cloud.d.ts.map +1 -1
- package/dist/lib/ollama-cloud.js +26 -37
- package/dist/lib/ollama-cloud.js.map +1 -1
- package/dist/lib/openai.d.ts +18 -29
- package/dist/lib/openai.d.ts.map +1 -1
- package/dist/lib/openai.js +108 -182
- package/dist/lib/openai.js.map +1 -1
- package/dist/lib/opencode-auth-sqlite.d.ts.map +1 -1
- package/dist/lib/opencode-auth-sqlite.js +22 -23
- package/dist/lib/opencode-auth-sqlite.js.map +1 -1
- package/dist/lib/opencode-auth.d.ts +17 -11
- package/dist/lib/opencode-auth.d.ts.map +1 -1
- package/dist/lib/opencode-auth.js +39 -46
- package/dist/lib/opencode-auth.js.map +1 -1
- package/dist/lib/opencode-config-editor.d.ts +3 -34
- package/dist/lib/opencode-config-editor.d.ts.map +1 -1
- package/dist/lib/opencode-config-editor.js +23 -142
- package/dist/lib/opencode-config-editor.js.map +1 -1
- package/dist/lib/opencode-config-providers.d.ts +4 -3
- package/dist/lib/opencode-config-providers.d.ts.map +1 -1
- package/dist/lib/opencode-config-providers.js +7 -11
- package/dist/lib/opencode-config-providers.js.map +1 -1
- package/dist/lib/opencode-config-read.d.ts +2 -1
- package/dist/lib/opencode-config-read.d.ts.map +1 -1
- package/dist/lib/opencode-config-read.js +3 -2
- package/dist/lib/opencode-config-read.js.map +1 -1
- package/dist/lib/opencode-console-auth.d.ts +2 -3
- package/dist/lib/opencode-console-auth.d.ts.map +1 -1
- package/dist/lib/opencode-console-auth.js +2 -2
- package/dist/lib/opencode-console-auth.js.map +1 -1
- package/dist/lib/opencode-go.d.ts.map +1 -1
- package/dist/lib/opencode-go.js +51 -79
- package/dist/lib/opencode-go.js.map +1 -1
- package/dist/lib/opencode-storage.d.ts +18 -3
- package/dist/lib/opencode-storage.d.ts.map +1 -1
- package/dist/lib/opencode-storage.js +134 -2
- package/dist/lib/opencode-storage.js.map +1 -1
- package/dist/lib/opencode-zen.d.ts +15 -12
- package/dist/lib/opencode-zen.d.ts.map +1 -1
- package/dist/lib/opencode-zen.js +139 -147
- package/dist/lib/opencode-zen.js.map +1 -1
- package/dist/lib/openrouter.d.ts.map +1 -1
- package/dist/lib/openrouter.js +1 -13
- package/dist/lib/openrouter.js.map +1 -1
- package/dist/lib/pricing-key.d.ts +48 -0
- package/dist/lib/pricing-key.d.ts.map +1 -0
- package/dist/lib/pricing-key.js +371 -0
- package/dist/lib/pricing-key.js.map +1 -0
- package/dist/lib/provider-metadata.d.ts +16 -20
- package/dist/lib/provider-metadata.d.ts.map +1 -1
- package/dist/lib/provider-metadata.js +69 -69
- package/dist/lib/provider-metadata.js.map +1 -1
- package/dist/lib/provider-model-matching.d.ts +2 -1
- package/dist/lib/provider-model-matching.d.ts.map +1 -1
- package/dist/lib/provider-registration.d.ts +1 -177
- package/dist/lib/provider-registration.d.ts.map +1 -1
- package/dist/lib/provider-registration.js +1 -163
- package/dist/lib/provider-registration.js.map +1 -1
- package/dist/lib/quota-dialog-commands.d.ts +87 -53
- package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
- package/dist/lib/quota-dialog-commands.js +259 -519
- package/dist/lib/quota-dialog-commands.js.map +1 -1
- package/dist/lib/quota-export-types.d.ts +29 -23
- package/dist/lib/quota-export-types.d.ts.map +1 -1
- package/dist/lib/quota-export.d.ts +16 -26
- package/dist/lib/quota-export.d.ts.map +1 -1
- package/dist/lib/quota-export.js +105 -147
- package/dist/lib/quota-export.js.map +1 -1
- package/dist/lib/quota-providers-local.d.ts +12 -8
- package/dist/lib/quota-providers-local.d.ts.map +1 -1
- package/dist/lib/quota-providers-local.js +150 -223
- package/dist/lib/quota-providers-local.js.map +1 -1
- package/dist/lib/quota-providers-remote.d.ts +3 -8
- package/dist/lib/quota-providers-remote.d.ts.map +1 -1
- package/dist/lib/quota-providers-remote.js +309 -449
- package/dist/lib/quota-providers-remote.js.map +1 -1
- package/dist/lib/quota-providers.d.ts +57 -15
- package/dist/lib/quota-providers.d.ts.map +1 -1
- package/dist/lib/quota-providers.js +157 -64
- package/dist/lib/quota-providers.js.map +1 -1
- package/dist/lib/quota-report-message.d.ts +23 -10
- package/dist/lib/quota-report-message.d.ts.map +1 -1
- package/dist/lib/quota-report-message.js +37 -13
- package/dist/lib/quota-report-message.js.map +1 -1
- package/dist/lib/quota-retry-wait.d.ts +14 -6
- package/dist/lib/quota-retry-wait.d.ts.map +1 -1
- package/dist/lib/quota-retry-wait.js +37 -39
- package/dist/lib/quota-retry-wait.js.map +1 -1
- package/dist/lib/quota-status.d.ts +50 -33
- package/dist/lib/quota-status.d.ts.map +1 -1
- package/dist/lib/quota-status.js +1113 -773
- package/dist/lib/quota-status.js.map +1 -1
- package/dist/lib/quota-telemetry.d.ts +7 -14
- package/dist/lib/quota-telemetry.d.ts.map +1 -1
- package/dist/lib/quota-telemetry.js +46 -97
- package/dist/lib/quota-telemetry.js.map +1 -1
- package/dist/lib/report-document.d.ts +5 -65
- package/dist/lib/report-document.d.ts.map +1 -1
- package/dist/lib/report-document.js +14 -167
- package/dist/lib/report-document.js.map +1 -1
- package/dist/lib/resolved-auth-identity.d.ts +1 -2
- package/dist/lib/resolved-auth-identity.d.ts.map +1 -1
- package/dist/lib/resolved-auth-identity.js +0 -4
- package/dist/lib/resolved-auth-identity.js.map +1 -1
- package/dist/lib/session-tokens.d.ts +19 -19
- package/dist/lib/session-tokens.d.ts.map +1 -1
- package/dist/lib/session-tokens.js +58 -44
- package/dist/lib/session-tokens.js.map +1 -1
- package/dist/lib/synthetic.d.ts +0 -1
- package/dist/lib/synthetic.d.ts.map +1 -1
- package/dist/lib/synthetic.js +43 -94
- package/dist/lib/synthetic.js.map +1 -1
- package/dist/lib/token-buckets.d.ts +0 -1
- package/dist/lib/token-buckets.d.ts.map +1 -1
- package/dist/lib/token-buckets.js +0 -3
- package/dist/lib/token-buckets.js.map +1 -1
- package/dist/lib/token-cost.d.ts +2 -1
- package/dist/lib/token-cost.d.ts.map +1 -1
- package/dist/lib/types.d.ts +25 -333
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +2 -70
- package/dist/lib/types.js.map +1 -1
- package/dist/lib/xai.d.ts +6 -6
- package/dist/lib/xai.d.ts.map +1 -1
- package/dist/lib/xai.js +51 -90
- package/dist/lib/xai.js.map +1 -1
- package/dist/plugin.d.ts +6 -3
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +315 -90
- package/dist/plugin.js.map +1 -1
- package/dist/providers/alibaba-coding-plan.d.ts +4 -0
- package/dist/providers/alibaba-coding-plan.d.ts.map +1 -1
- package/dist/providers/alibaba-coding-plan.js +47 -77
- package/dist/providers/alibaba-coding-plan.js.map +1 -1
- package/dist/providers/alibaba-token-plan.d.ts.map +1 -1
- package/dist/providers/alibaba-token-plan.js +34 -46
- package/dist/providers/alibaba-token-plan.js.map +1 -1
- package/dist/providers/anthropic.d.ts +2 -4
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +80 -162
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/cache-policies.d.ts +0 -2
- package/dist/providers/cache-policies.d.ts.map +1 -1
- package/dist/providers/cache-policies.js +38 -88
- package/dist/providers/cache-policies.js.map +1 -1
- package/dist/providers/chutes.d.ts +0 -3
- package/dist/providers/chutes.d.ts.map +1 -1
- package/dist/providers/chutes.js +16 -28
- package/dist/providers/chutes.js.map +1 -1
- package/dist/providers/contract.d.ts +128 -0
- package/dist/providers/contract.d.ts.map +1 -0
- package/dist/providers/contract.js +101 -0
- package/dist/providers/contract.js.map +1 -0
- package/dist/providers/copilot.d.ts.map +1 -1
- package/dist/providers/copilot.js +171 -175
- package/dist/providers/copilot.js.map +1 -1
- package/dist/providers/cursor.d.ts.map +1 -1
- package/dist/providers/cursor.js +56 -109
- package/dist/providers/cursor.js.map +1 -1
- package/dist/providers/deepseek.d.ts +1 -6
- package/dist/providers/deepseek.d.ts.map +1 -1
- package/dist/providers/deepseek.js +46 -81
- package/dist/providers/deepseek.js.map +1 -1
- package/dist/providers/glm-coding-plan.d.ts +8 -0
- package/dist/providers/glm-coding-plan.d.ts.map +1 -0
- package/dist/providers/glm-coding-plan.js +106 -0
- package/dist/providers/glm-coding-plan.js.map +1 -0
- package/dist/providers/google-agy.d.ts +0 -1
- package/dist/providers/google-agy.d.ts.map +1 -1
- package/dist/providers/google-agy.js +41 -192
- package/dist/providers/google-agy.js.map +1 -1
- package/dist/providers/google-gemini-cli.d.ts.map +1 -1
- package/dist/providers/google-gemini-cli.js +51 -151
- package/dist/providers/google-gemini-cli.js.map +1 -1
- package/dist/providers/google-oauth-provider.d.ts +39 -0
- package/dist/providers/google-oauth-provider.d.ts.map +1 -0
- package/dist/providers/google-oauth-provider.js +161 -0
- package/dist/providers/google-oauth-provider.js.map +1 -0
- package/dist/providers/kilo.d.ts +0 -3
- package/dist/providers/kilo.d.ts.map +1 -1
- package/dist/providers/kilo.js +69 -123
- package/dist/providers/kilo.js.map +1 -1
- package/dist/providers/kimi-code.d.ts +5 -0
- package/dist/providers/kimi-code.d.ts.map +1 -1
- package/dist/providers/kimi-code.js +91 -136
- package/dist/providers/kimi-code.js.map +1 -1
- package/dist/providers/mimo.d.ts.map +1 -1
- package/dist/providers/mimo.js +55 -94
- package/dist/providers/mimo.js.map +1 -1
- package/dist/providers/minimax-coding-plan.d.ts +2 -23
- package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
- package/dist/providers/minimax-coding-plan.js +161 -277
- package/dist/providers/minimax-coding-plan.js.map +1 -1
- package/dist/providers/nanogpt.d.ts +0 -3
- package/dist/providers/nanogpt.d.ts.map +1 -1
- package/dist/providers/nanogpt.js +61 -95
- package/dist/providers/nanogpt.js.map +1 -1
- package/dist/providers/ollama-cloud.d.ts +0 -6
- package/dist/providers/ollama-cloud.d.ts.map +1 -1
- package/dist/providers/ollama-cloud.js +86 -112
- package/dist/providers/ollama-cloud.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +144 -166
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/opencode-go.d.ts.map +1 -1
- package/dist/providers/opencode-go.js +157 -199
- package/dist/providers/opencode-go.js.map +1 -1
- package/dist/providers/opencode-zen.d.ts.map +1 -1
- package/dist/providers/opencode-zen.js +100 -150
- package/dist/providers/opencode-zen.js.map +1 -1
- package/dist/providers/openrouter.d.ts +0 -3
- package/dist/providers/openrouter.d.ts.map +1 -1
- package/dist/providers/openrouter.js +26 -13
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/quota-providers.d.ts +7 -3
- package/dist/providers/quota-providers.d.ts.map +1 -1
- package/dist/providers/quota-providers.js +111 -217
- package/dist/providers/quota-providers.js.map +1 -1
- package/dist/providers/registry.d.ts.map +1 -1
- package/dist/providers/registry.js +1 -2
- package/dist/providers/registry.js.map +1 -1
- package/dist/providers/result-helpers.d.ts +10 -37
- package/dist/providers/result-helpers.d.ts.map +1 -1
- package/dist/providers/result-helpers.js +23 -56
- package/dist/providers/result-helpers.js.map +1 -1
- package/dist/providers/synthetic.d.ts +0 -3
- package/dist/providers/synthetic.d.ts.map +1 -1
- package/dist/providers/synthetic.js +16 -58
- package/dist/providers/synthetic.js.map +1 -1
- package/dist/providers/xai.d.ts +2 -1
- package/dist/providers/xai.d.ts.map +1 -1
- package/dist/providers/xai.js +49 -71
- package/dist/providers/xai.js.map +1 -1
- package/dist/rpc.d.ts +110 -38
- package/dist/rpc.d.ts.map +1 -1
- package/dist/rpc.js +125 -37
- package/dist/rpc.js.map +1 -1
- package/dist/settings/convert.d.ts +60 -0
- package/dist/settings/convert.d.ts.map +1 -0
- package/dist/settings/convert.js +473 -0
- package/dist/settings/convert.js.map +1 -0
- package/dist/settings/file.d.ts +89 -0
- package/dist/settings/file.d.ts.map +1 -0
- package/dist/settings/file.js +452 -0
- package/dist/settings/file.js.map +1 -0
- package/dist/settings/index.d.ts +10 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +3 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/schema.d.ts +607 -0
- package/dist/settings/schema.d.ts.map +1 -0
- package/dist/settings/schema.js +479 -0
- package/dist/settings/schema.js.map +1 -0
- package/dist/tui/client.d.ts +86 -0
- package/dist/tui/client.d.ts.map +1 -0
- package/dist/tui/client.js +229 -0
- package/dist/tui/client.js.map +1 -0
- package/dist/tui/display.d.ts +127 -0
- package/dist/tui/display.d.ts.map +1 -0
- package/dist/tui/display.js +474 -0
- package/dist/tui/display.js.map +1 -0
- package/dist/tui/index.d.ts +21 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +305 -0
- package/dist/tui/server-settings.d.ts +43 -0
- package/dist/tui/server-settings.d.ts.map +1 -0
- package/dist/tui/server-settings.js +233 -0
- package/dist/tui/server-settings.js.map +1 -0
- package/dist/tui/sidebar.d.ts +41 -0
- package/dist/tui/sidebar.d.ts.map +1 -0
- package/dist/tui/sidebar.js +148 -0
- package/dist/tui/status-line.d.ts +14 -0
- package/dist/tui/status-line.d.ts.map +1 -0
- package/dist/tui/status-line.js +225 -0
- package/dist/tui/theme.d.ts +41 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +52 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/toast-colors.d.ts +37 -0
- package/dist/tui/toast-colors.d.ts.map +1 -0
- package/dist/tui/toast-colors.js +77 -0
- package/dist/tui/toasts.d.ts +59 -0
- package/dist/tui/toasts.d.ts.map +1 -0
- package/dist/tui/toasts.js +148 -0
- package/dist/tui/toasts.js.map +1 -0
- package/dist/tui/window/drag.d.ts +26 -0
- package/dist/tui/window/drag.d.ts.map +1 -0
- package/dist/tui/window/drag.js +80 -0
- package/dist/tui/window/drag.js.map +1 -0
- package/dist/tui/window/limits.d.ts +15 -0
- package/dist/tui/window/limits.d.ts.map +1 -0
- package/dist/tui/window/limits.js +227 -0
- package/dist/tui/window/limits.js.map +1 -0
- package/dist/tui/window/rail.d.ts +21 -0
- package/dist/tui/window/rail.d.ts.map +1 -0
- package/dist/tui/window/rail.js +81 -0
- package/dist/tui/window/settings.d.ts +164 -0
- package/dist/tui/window/settings.d.ts.map +1 -0
- package/dist/tui/window/settings.js +1679 -0
- package/dist/tui/window/shell.d.ts +108 -0
- package/dist/tui/window/shell.d.ts.map +1 -0
- package/dist/tui/window/shell.js +1003 -0
- package/dist/tui/window/usage.d.ts +75 -0
- package/dist/tui/window/usage.d.ts.map +1 -0
- package/dist/tui/window/usage.js +928 -0
- package/dist/tui/window/views.d.ts +61 -0
- package/dist/tui/window/views.d.ts.map +1 -0
- package/dist/tui/window/views.js +242 -0
- package/dist/tui.d.ts +1 -5
- package/dist/tui.js +1 -894
- package/dist/view/columns.d.ts +15 -0
- package/dist/view/columns.d.ts.map +1 -0
- package/dist/view/columns.js +48 -0
- package/dist/view/columns.js.map +1 -0
- package/dist/view/format.d.ts +82 -0
- package/dist/view/format.d.ts.map +1 -0
- package/dist/view/format.js +201 -0
- package/dist/view/format.js.map +1 -0
- package/dist/view/quick-look.d.ts +28 -0
- package/dist/view/quick-look.d.ts.map +1 -0
- package/dist/view/quick-look.js +150 -0
- package/dist/view/quick-look.js.map +1 -0
- package/dist/view/select.d.ts +67 -0
- package/dist/view/select.d.ts.map +1 -0
- package/dist/view/select.js +87 -0
- package/dist/view/select.js.map +1 -0
- package/dist/view/text.d.ts +153 -0
- package/dist/view/text.d.ts.map +1 -0
- package/dist/view/text.js +642 -0
- package/dist/view/text.js.map +1 -0
- package/dist/view/usage.d.ts +86 -0
- package/dist/view/usage.d.ts.map +1 -0
- package/dist/view/usage.js +724 -0
- package/dist/view/usage.js.map +1 -0
- package/package.json +4 -6
- package/dist/lib/chutes-config.d.ts +0 -15
- package/dist/lib/chutes-config.d.ts.map +0 -1
- package/dist/lib/chutes-config.js +0 -28
- package/dist/lib/chutes-config.js.map +0 -1
- package/dist/lib/cli-status.d.ts +0 -8
- package/dist/lib/cli-status.d.ts.map +0 -1
- package/dist/lib/cli-status.js +0 -98
- package/dist/lib/cli-status.js.map +0 -1
- package/dist/lib/command-parsing.d.ts +0 -43
- package/dist/lib/command-parsing.d.ts.map +0 -1
- package/dist/lib/command-parsing.js +0 -103
- package/dist/lib/command-parsing.js.map +0 -1
- package/dist/lib/config.d.ts +0 -63
- package/dist/lib/config.d.ts.map +0 -1
- package/dist/lib/config.js +0 -1092
- package/dist/lib/config.js.map +0 -1
- package/dist/lib/deepseek-auth.d.ts +0 -15
- package/dist/lib/deepseek-auth.d.ts.map +0 -1
- package/dist/lib/deepseek-auth.js +0 -28
- package/dist/lib/deepseek-auth.js.map +0 -1
- package/dist/lib/format.d.ts +0 -25
- package/dist/lib/format.d.ts.map +0 -1
- package/dist/lib/format.js +0 -300
- package/dist/lib/format.js.map +0 -1
- package/dist/lib/google-agy-companion.d.ts +0 -8
- package/dist/lib/google-agy-companion.d.ts.map +0 -1
- package/dist/lib/google-agy-companion.js +0 -64
- package/dist/lib/google-agy-companion.js.map +0 -1
- package/dist/lib/google-gemini-cli-companion.d.ts +0 -8
- package/dist/lib/google-gemini-cli-companion.d.ts.map +0 -1
- package/dist/lib/google-gemini-cli-companion.js +0 -64
- package/dist/lib/google-gemini-cli-companion.js.map +0 -1
- package/dist/lib/grouped-entry-normalization.d.ts +0 -12
- package/dist/lib/grouped-entry-normalization.d.ts.map +0 -1
- package/dist/lib/grouped-entry-normalization.js +0 -124
- package/dist/lib/grouped-entry-normalization.js.map +0 -1
- package/dist/lib/grouped-header-format.d.ts +0 -5
- package/dist/lib/grouped-header-format.d.ts.map +0 -1
- package/dist/lib/grouped-header-format.js +0 -16
- package/dist/lib/grouped-header-format.js.map +0 -1
- package/dist/lib/init-installer.d.ts +0 -123
- package/dist/lib/init-installer.d.ts.map +0 -1
- package/dist/lib/init-installer.js +0 -1111
- package/dist/lib/init-installer.js.map +0 -1
- package/dist/lib/jsonc.d.ts +0 -17
- package/dist/lib/jsonc.d.ts.map +0 -1
- package/dist/lib/jsonc.js +0 -23
- package/dist/lib/jsonc.js.map +0 -1
- package/dist/lib/kilo-config.d.ts +0 -15
- package/dist/lib/kilo-config.d.ts.map +0 -1
- package/dist/lib/kilo-config.js +0 -27
- package/dist/lib/kilo-config.js.map +0 -1
- package/dist/lib/kimi-auth.d.ts +0 -49
- package/dist/lib/kimi-auth.d.ts.map +0 -1
- package/dist/lib/kimi-auth.js +0 -82
- package/dist/lib/kimi-auth.js.map +0 -1
- package/dist/lib/markdown-table.d.ts +0 -51
- package/dist/lib/markdown-table.d.ts.map +0 -1
- package/dist/lib/markdown-table.js +0 -179
- package/dist/lib/markdown-table.js.map +0 -1
- package/dist/lib/minimax-auth.d.ts +0 -62
- package/dist/lib/minimax-auth.d.ts.map +0 -1
- package/dist/lib/minimax-auth.js +0 -206
- package/dist/lib/minimax-auth.js.map +0 -1
- package/dist/lib/nanogpt-config.d.ts +0 -15
- package/dist/lib/nanogpt-config.d.ts.map +0 -1
- package/dist/lib/nanogpt-config.js +0 -31
- package/dist/lib/nanogpt-config.js.map +0 -1
- package/dist/lib/ollama-cloud-config.d.ts +0 -15
- package/dist/lib/ollama-cloud-config.d.ts.map +0 -1
- package/dist/lib/ollama-cloud-config.js +0 -27
- package/dist/lib/ollama-cloud-config.js.map +0 -1
- package/dist/lib/opencode-go-auth.d.ts +0 -16
- package/dist/lib/opencode-go-auth.d.ts.map +0 -1
- package/dist/lib/opencode-go-auth.js +0 -42
- package/dist/lib/opencode-go-auth.js.map +0 -1
- package/dist/lib/opencode-version.d.ts +0 -6
- package/dist/lib/opencode-version.d.ts.map +0 -1
- package/dist/lib/opencode-version.js +0 -26
- package/dist/lib/opencode-version.js.map +0 -1
- package/dist/lib/provider-add-command.d.ts +0 -35
- package/dist/lib/provider-add-command.d.ts.map +0 -1
- package/dist/lib/provider-add-command.js +0 -204
- package/dist/lib/provider-add-command.js.map +0 -1
- package/dist/lib/provider-add-json-v1-questionnaire.d.ts +0 -32
- package/dist/lib/provider-add-json-v1-questionnaire.d.ts.map +0 -1
- package/dist/lib/provider-add-json-v1-questionnaire.js +0 -336
- package/dist/lib/provider-add-json-v1-questionnaire.js.map +0 -1
- package/dist/lib/provider-add.d.ts +0 -21
- package/dist/lib/provider-add.d.ts.map +0 -1
- package/dist/lib/provider-add.js +0 -219
- package/dist/lib/provider-add.js.map +0 -1
- package/dist/lib/quota-accounting-projection.d.ts +0 -9
- package/dist/lib/quota-accounting-projection.d.ts.map +0 -1
- package/dist/lib/quota-accounting-projection.js +0 -254
- package/dist/lib/quota-accounting-projection.js.map +0 -1
- package/dist/lib/quota-columns.d.ts +0 -38
- package/dist/lib/quota-columns.d.ts.map +0 -1
- package/dist/lib/quota-columns.js +0 -129
- package/dist/lib/quota-columns.js.map +0 -1
- package/dist/lib/quota-command-format.d.ts +0 -34
- package/dist/lib/quota-command-format.d.ts.map +0 -1
- package/dist/lib/quota-command-format.js +0 -240
- package/dist/lib/quota-command-format.js.map +0 -1
- package/dist/lib/quota-dialog-command-specs.d.ts +0 -63
- package/dist/lib/quota-dialog-command-specs.d.ts.map +0 -1
- package/dist/lib/quota-dialog-command-specs.js +0 -145
- package/dist/lib/quota-dialog-command-specs.js.map +0 -1
- package/dist/lib/quota-entry-display.d.ts +0 -7
- package/dist/lib/quota-entry-display.d.ts.map +0 -1
- package/dist/lib/quota-entry-display.js +0 -59
- package/dist/lib/quota-entry-display.js.map +0 -1
- package/dist/lib/quota-exhaustion-projection.d.ts +0 -11
- package/dist/lib/quota-exhaustion-projection.d.ts.map +0 -1
- package/dist/lib/quota-exhaustion-projection.js +0 -105
- package/dist/lib/quota-exhaustion-projection.js.map +0 -1
- package/dist/lib/quota-format-style.d.ts +0 -21
- package/dist/lib/quota-format-style.d.ts.map +0 -1
- package/dist/lib/quota-format-style.js +0 -38
- package/dist/lib/quota-format-style.js.map +0 -1
- package/dist/lib/quota-render-data.d.ts +0 -102
- package/dist/lib/quota-render-data.d.ts.map +0 -1
- package/dist/lib/quota-render-data.js +0 -419
- package/dist/lib/quota-render-data.js.map +0 -1
- package/dist/lib/quota-reset-notifications.d.ts +0 -20
- package/dist/lib/quota-reset-notifications.d.ts.map +0 -1
- package/dist/lib/quota-reset-notifications.js +0 -331
- package/dist/lib/quota-reset-notifications.js.map +0 -1
- package/dist/lib/quota-runtime-context.d.ts +0 -54
- package/dist/lib/quota-runtime-context.d.ts.map +0 -1
- package/dist/lib/quota-runtime-context.js +0 -110
- package/dist/lib/quota-runtime-context.js.map +0 -1
- package/dist/lib/quota-state-codec.d.ts +0 -16
- package/dist/lib/quota-state-codec.d.ts.map +0 -1
- package/dist/lib/quota-state-codec.js +0 -412
- package/dist/lib/quota-state-codec.js.map +0 -1
- package/dist/lib/quota-state.d.ts +0 -28
- package/dist/lib/quota-state.d.ts.map +0 -1
- package/dist/lib/quota-state.js +0 -473
- package/dist/lib/quota-state.js.map +0 -1
- package/dist/lib/quota-stats-format.d.ts +0 -29
- package/dist/lib/quota-stats-format.d.ts.map +0 -1
- package/dist/lib/quota-stats-format.js +0 -459
- package/dist/lib/quota-stats-format.js.map +0 -1
- package/dist/lib/quota-stats.d.ts +0 -126
- package/dist/lib/quota-stats.d.ts.map +0 -1
- package/dist/lib/quota-stats.js +0 -695
- package/dist/lib/quota-stats.js.map +0 -1
- package/dist/lib/quota-surface-data.d.ts +0 -21
- package/dist/lib/quota-surface-data.d.ts.map +0 -1
- package/dist/lib/quota-surface-data.js +0 -362
- package/dist/lib/quota-surface-data.js.map +0 -1
- package/dist/lib/scoped-update-migration.d.ts +0 -103
- package/dist/lib/scoped-update-migration.d.ts.map +0 -1
- package/dist/lib/scoped-update-migration.js +0 -344
- package/dist/lib/scoped-update-migration.js.map +0 -1
- package/dist/lib/scoped-update.d.ts +0 -77
- package/dist/lib/scoped-update.d.ts.map +0 -1
- package/dist/lib/scoped-update.js +0 -590
- package/dist/lib/scoped-update.js.map +0 -1
- package/dist/lib/session-tokens-format.d.ts +0 -36
- package/dist/lib/session-tokens-format.d.ts.map +0 -1
- package/dist/lib/session-tokens-format.js +0 -111
- package/dist/lib/session-tokens-format.js.map +0 -1
- package/dist/lib/synthetic-config.d.ts +0 -15
- package/dist/lib/synthetic-config.d.ts.map +0 -1
- package/dist/lib/synthetic-config.js +0 -28
- package/dist/lib/synthetic-config.js.map +0 -1
- package/dist/lib/toast-format-grouped.d.ts +0 -25
- package/dist/lib/toast-format-grouped.d.ts.map +0 -1
- package/dist/lib/toast-format-grouped.js +0 -296
- package/dist/lib/toast-format-grouped.js.map +0 -1
- package/dist/lib/tui-compact-format.d.ts +0 -10
- package/dist/lib/tui-compact-format.d.ts.map +0 -1
- package/dist/lib/tui-compact-format.js +0 -460
- package/dist/lib/tui-compact-format.js.map +0 -1
- package/dist/lib/tui-panel-state.d.ts +0 -15
- package/dist/lib/tui-panel-state.d.ts.map +0 -1
- package/dist/lib/tui-panel-state.js +0 -2
- package/dist/lib/tui-panel-state.js.map +0 -1
- package/dist/lib/tui-prompt-bar-format.d.ts +0 -25
- package/dist/lib/tui-prompt-bar-format.d.ts.map +0 -1
- package/dist/lib/tui-prompt-bar-format.js +0 -206
- package/dist/lib/tui-prompt-bar-format.js.map +0 -1
- package/dist/lib/tui-sidebar-format.d.ts +0 -13
- package/dist/lib/tui-sidebar-format.d.ts.map +0 -1
- package/dist/lib/tui-sidebar-format.js +0 -34
- package/dist/lib/tui-sidebar-format.js.map +0 -1
- package/dist/lib/zai-auth.d.ts +0 -15
- package/dist/lib/zai-auth.d.ts.map +0 -1
- package/dist/lib/zai-auth.js +0 -37
- package/dist/lib/zai-auth.js.map +0 -1
- package/dist/lib/zai.d.ts +0 -5
- package/dist/lib/zai.d.ts.map +0 -1
- package/dist/lib/zai.js +0 -14
- package/dist/lib/zai.js.map +0 -1
- package/dist/lib/zhipu-auth.d.ts +0 -15
- package/dist/lib/zhipu-auth.d.ts.map +0 -1
- package/dist/lib/zhipu-auth.js +0 -42
- package/dist/lib/zhipu-auth.js.map +0 -1
- package/dist/lib/zhipu.d.ts +0 -5
- package/dist/lib/zhipu.d.ts.map +0 -1
- package/dist/lib/zhipu.js +0 -13
- package/dist/lib/zhipu.js.map +0 -1
- package/dist/providers/glm-coding-plan-provider.d.ts +0 -56
- package/dist/providers/glm-coding-plan-provider.d.ts.map +0 -1
- package/dist/providers/glm-coding-plan-provider.js +0 -115
- package/dist/providers/glm-coding-plan-provider.js.map +0 -1
- package/dist/providers/google-account-format.d.ts +0 -7
- package/dist/providers/google-account-format.d.ts.map +0 -1
- package/dist/providers/google-account-format.js +0 -52
- package/dist/providers/google-account-format.js.map +0 -1
- package/dist/providers/zai.d.ts +0 -2
- package/dist/providers/zai.d.ts.map +0 -1
- package/dist/providers/zai.js +0 -24
- package/dist/providers/zai.js.map +0 -1
- package/dist/providers/zhipu.d.ts +0 -2
- package/dist/providers/zhipu.d.ts.map +0 -1
- package/dist/providers/zhipu.js +0 -21
- package/dist/providers/zhipu.js.map +0 -1
- package/dist/tui-v2.d.ts +0 -5
- package/dist/tui-v2.d.ts.map +0 -1
- package/dist/tui-v2.jsx +0 -624
- package/dist/tui-v2.jsx.map +0 -1
- package/dist/tui.d.ts.map +0 -1
|
@@ -5,361 +5,202 @@ import { writeJsonAtomic } from "./atomic-json.js";
|
|
|
5
5
|
import { fetchWithTimeout } from "./http.js";
|
|
6
6
|
import { getOpencodeRuntimeDirs } from "./opencode-runtime-paths.js";
|
|
7
7
|
const SOURCE_URL = "https://models.dev/api.json";
|
|
8
|
+
const UNITS = "USD per 1M tokens";
|
|
8
9
|
const DEFAULT_MODELSDEV_PROVIDERS = ["anthropic", "google", "moonshotai", "openai", "xai", "zai"];
|
|
9
|
-
|
|
10
|
-
const
|
|
11
|
-
const
|
|
10
|
+
/** The prices read from models.dev; a saved snapshot may also carry `reasoning`. */
|
|
11
|
+
const API_COST_KEYS = ["input", "output", "cache_read", "cache_write"];
|
|
12
|
+
const SNAPSHOT_COST_KEYS = [...API_COST_KEYS, "reasoning"];
|
|
12
13
|
const DEFAULT_REFRESH_MIN_ATTEMPT_INTERVAL_MS = 6 * 60 * 60 * 1000;
|
|
13
14
|
const DEFAULT_REFRESH_TIMEOUT_MS = 6_000;
|
|
14
15
|
const MS_PER_DAY = 24 * 60 * 60 * 1000;
|
|
15
16
|
export const DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS = 3 * 24 * 60 * 60 * 1000;
|
|
16
17
|
const EMPTY_SNAPSHOT = {
|
|
17
|
-
_meta: {
|
|
18
|
-
source: "none",
|
|
19
|
-
generatedAt: 0,
|
|
20
|
-
providers: [],
|
|
21
|
-
units: "USD per 1M tokens",
|
|
22
|
-
},
|
|
18
|
+
_meta: { source: "none", generatedAt: 0, providers: [], units: UNITS },
|
|
23
19
|
providers: {},
|
|
24
20
|
};
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
const REFRESH_RESULTS = new Set([
|
|
22
|
+
"success",
|
|
23
|
+
"not_modified",
|
|
24
|
+
"skipped_fresh",
|
|
25
|
+
"skipped_throttled",
|
|
26
|
+
"failed",
|
|
27
|
+
]);
|
|
28
|
+
let LOADED = null;
|
|
27
29
|
let SNAPSHOT_SELECTION = "auto";
|
|
28
|
-
let MODEL_INDEX = null;
|
|
29
30
|
let REFRESH_IN_FLIGHT = null;
|
|
30
31
|
let PROCESS_REFRESH_CHECKED = false;
|
|
31
|
-
let
|
|
32
|
+
let CONFIGURED_MAX_AGE_MS = DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
33
|
+
/** An object or an array (an array's entries are keyed by position). */
|
|
32
34
|
function asRecord(value) {
|
|
33
35
|
return value && typeof value === "object" ? value : null;
|
|
34
36
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
out[key] = obj[key];
|
|
39
|
-
}
|
|
40
|
-
return out;
|
|
37
|
+
/** Sorted by key, so a saved snapshot reads and diffs in a stable order. */
|
|
38
|
+
function sortByKey(record) {
|
|
39
|
+
return Object.fromEntries(Object.entries(record).sort(([a], [b]) => a.localeCompare(b)));
|
|
41
40
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
/** The finite prices among `keys`; null when there are none. */
|
|
42
|
+
function pickCosts(raw, keys) {
|
|
43
|
+
const record = asRecord(raw);
|
|
44
|
+
const picked = {};
|
|
45
|
+
for (const key of keys) {
|
|
46
|
+
const value = record?.[key];
|
|
47
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
48
|
+
picked[key] = value;
|
|
45
49
|
}
|
|
46
|
-
return
|
|
50
|
+
return Object.keys(picked).length > 0 ? picked : null;
|
|
47
51
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
maxAgeMs: CONFIGURED_PRICING_SNAPSHOT_MAX_AGE_MS,
|
|
52
|
-
minAttemptIntervalMs: DEFAULT_REFRESH_MIN_ATTEMPT_INTERVAL_MS,
|
|
53
|
-
timeoutMs: DEFAULT_REFRESH_TIMEOUT_MS,
|
|
54
|
-
};
|
|
52
|
+
function withProviders(meta, providers) {
|
|
53
|
+
const sorted = sortByKey(providers);
|
|
54
|
+
return { _meta: { ...meta, providers: Object.keys(sorted) }, providers: sorted };
|
|
55
55
|
}
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
/** A snapshot of the providers with at least one priced model. */
|
|
57
|
+
function makeSnapshot(meta, modelsByProvider, costOf) {
|
|
58
|
+
const providers = {};
|
|
59
|
+
for (const [providerId, modelsRaw] of modelsByProvider) {
|
|
60
|
+
const models = {};
|
|
61
|
+
for (const [modelId, model] of Object.entries(asRecord(modelsRaw) ?? {})) {
|
|
62
|
+
const cost = costOf(model);
|
|
63
|
+
if (cost)
|
|
64
|
+
models[modelId] = cost;
|
|
65
|
+
}
|
|
66
|
+
if (Object.keys(models).length > 0)
|
|
67
|
+
providers[providerId] = sortByKey(models);
|
|
68
|
+
}
|
|
69
|
+
return withProviders(meta, providers);
|
|
58
70
|
}
|
|
71
|
+
/** A saved snapshot (bundled or runtime); null when it has no valid date. */
|
|
59
72
|
function normalizeSnapshot(raw) {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const providersRaw = asRecord(root.providers);
|
|
65
|
-
if (!metaRaw || !providersRaw)
|
|
66
|
-
return null;
|
|
67
|
-
const generatedAt = Number(metaRaw.generatedAt);
|
|
68
|
-
if (!Number.isFinite(generatedAt) || generatedAt <= 0)
|
|
73
|
+
const meta = asRecord(asRecord(raw)?._meta);
|
|
74
|
+
const providers = asRecord(asRecord(raw)?.providers);
|
|
75
|
+
const generatedAt = Number(meta?.generatedAt);
|
|
76
|
+
if (!meta || !providers || !Number.isFinite(generatedAt) || generatedAt <= 0)
|
|
69
77
|
return null;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
}
|
|
95
|
-
if (typeof reasoning === "number" && Number.isFinite(reasoning))
|
|
96
|
-
buckets.reasoning = reasoning;
|
|
97
|
-
if (Object.keys(buckets).length > 0) {
|
|
98
|
-
models[modelId] = buckets;
|
|
78
|
+
return makeSnapshot({
|
|
79
|
+
source: typeof meta.source === "string" && meta.source ? meta.source : SOURCE_URL,
|
|
80
|
+
generatedAt: Math.trunc(generatedAt),
|
|
81
|
+
units: typeof meta.units === "string" && meta.units ? meta.units : UNITS,
|
|
82
|
+
}, Object.entries(providers), (model) => pickCosts(model, SNAPSHOT_COST_KEYS));
|
|
83
|
+
}
|
|
84
|
+
function buildSnapshotFromApi(apiRaw, providerIDs, generatedAt) {
|
|
85
|
+
const api = asRecord(apiRaw) ?? {};
|
|
86
|
+
return makeSnapshot({ source: SOURCE_URL, generatedAt, units: UNITS }, providerIDs.map((providerID) => [providerID, asRecord(api[providerID])?.models]), (model) => pickCosts(asRecord(model)?.cost, API_COST_KEYS));
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* models.dev drops retired models from its list. Keep their last known price so
|
|
90
|
+
* older usage still gets a cost. `current` wins, then `previous` in the order given.
|
|
91
|
+
* Callers list the user's runtime snapshot before the bundled one: its prices come
|
|
92
|
+
* from the user's own last download, while the bundled file's date only says when
|
|
93
|
+
* the file was rewritten, not when a kept model's price was last seen.
|
|
94
|
+
*/
|
|
95
|
+
function keepRetiredModels(current, previous, providerIDs) {
|
|
96
|
+
const providers = { ...current.providers };
|
|
97
|
+
for (const providerID of providerIDs) {
|
|
98
|
+
const models = { ...providers[providerID] };
|
|
99
|
+
for (const snapshot of previous) {
|
|
100
|
+
for (const [modelID, cost] of Object.entries(snapshot?.providers[providerID] ?? {})) {
|
|
101
|
+
models[modelID] ??= cost;
|
|
99
102
|
}
|
|
100
103
|
}
|
|
101
|
-
if (Object.keys(models).length > 0)
|
|
102
|
-
providers[
|
|
103
|
-
}
|
|
104
|
+
if (Object.keys(models).length > 0)
|
|
105
|
+
providers[providerID] = sortByKey(models);
|
|
104
106
|
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
_meta: {
|
|
108
|
-
source: typeof metaRaw.source === "string" && metaRaw.source ? metaRaw.source : SOURCE_URL,
|
|
109
|
-
generatedAt: Math.trunc(generatedAt),
|
|
110
|
-
providers: providerList,
|
|
111
|
-
units: typeof metaRaw.units === "string" && metaRaw.units ? metaRaw.units : "USD per 1M tokens",
|
|
112
|
-
},
|
|
113
|
-
providers: sortRecordByKeys(providers),
|
|
114
|
-
};
|
|
107
|
+
return withProviders(current._meta, providers);
|
|
115
108
|
}
|
|
116
|
-
function
|
|
117
|
-
if (override) {
|
|
118
|
-
return normalizeSnapshot(override) ?? EMPTY_SNAPSHOT;
|
|
119
|
-
}
|
|
109
|
+
function readSnapshotFile(path) {
|
|
120
110
|
try {
|
|
121
|
-
|
|
122
|
-
const raw = readFileSync(url, "utf-8");
|
|
123
|
-
return normalizeSnapshot(JSON.parse(raw)) ?? EMPTY_SNAPSHOT;
|
|
111
|
+
return normalizeSnapshot(JSON.parse(readFileSync(path, "utf-8")));
|
|
124
112
|
}
|
|
125
113
|
catch {
|
|
126
|
-
return
|
|
114
|
+
return null;
|
|
127
115
|
}
|
|
128
116
|
}
|
|
117
|
+
function loadBundledSnapshot(override) {
|
|
118
|
+
const bundled = override
|
|
119
|
+
? normalizeSnapshot(override)
|
|
120
|
+
: readSnapshotFile(new URL("../data/modelsdev-pricing.min.json", import.meta.url));
|
|
121
|
+
return bundled ?? EMPTY_SNAPSHOT;
|
|
122
|
+
}
|
|
123
|
+
function loadRuntimeSnapshot(runtimeDirs) {
|
|
124
|
+
return readSnapshotFile(getRuntimePricingSnapshotPath(runtimeDirs));
|
|
125
|
+
}
|
|
126
|
+
/** "bundled" pins the shipped file, "runtime" prefers the downloaded one, "auto" takes the newer. */
|
|
127
|
+
function chooseSnapshot(selection, runtimeDirs, bundledOverride) {
|
|
128
|
+
const bundled = loadBundledSnapshot(bundledOverride);
|
|
129
|
+
const runtime = selection === "bundled" ? null : loadRuntimeSnapshot(runtimeDirs);
|
|
130
|
+
if (runtime &&
|
|
131
|
+
(selection === "runtime" || runtime._meta.generatedAt >= bundled._meta.generatedAt)) {
|
|
132
|
+
// A runtime snapshot saved by an older version may lack models that models.dev stopped
|
|
133
|
+
// listing; the bundled file fills them until its next refresh.
|
|
134
|
+
const snapshot = keepRetiredModels(runtime, [bundled], DEFAULT_MODELSDEV_PROVIDERS);
|
|
135
|
+
return { snapshot, source: "runtime" };
|
|
136
|
+
}
|
|
137
|
+
return { snapshot: bundled, source: bundled === EMPTY_SNAPSHOT ? "empty" : "bundled" };
|
|
138
|
+
}
|
|
139
|
+
function reloadSnapshot(selection = SNAPSHOT_SELECTION, runtimeDirs, bundledOverride) {
|
|
140
|
+
LOADED = chooseSnapshot(selection, runtimeDirs, bundledOverride);
|
|
141
|
+
return LOADED;
|
|
142
|
+
}
|
|
143
|
+
function loaded() {
|
|
144
|
+
return LOADED ?? reloadSnapshot();
|
|
145
|
+
}
|
|
146
|
+
function pricedProviders() {
|
|
147
|
+
return loaded().snapshot.providers;
|
|
148
|
+
}
|
|
129
149
|
export function getRuntimePricingSnapshotPath(runtimeDirs) {
|
|
130
|
-
const
|
|
131
|
-
return join(
|
|
150
|
+
const { cacheDir } = runtimeDirs ?? getOpencodeRuntimeDirs();
|
|
151
|
+
return join(cacheDir, "opencode-quota", "modelsdev-pricing.runtime.min.json");
|
|
132
152
|
}
|
|
133
153
|
export function getRuntimePricingRefreshStatePath(runtimeDirs) {
|
|
134
|
-
const
|
|
135
|
-
return join(
|
|
154
|
+
const { cacheDir } = runtimeDirs ?? getOpencodeRuntimeDirs();
|
|
155
|
+
return join(cacheDir, "opencode-quota", "modelsdev-pricing.refresh-state.json");
|
|
136
156
|
}
|
|
137
|
-
function
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
157
|
+
export function getPricingRefreshPolicy() {
|
|
158
|
+
return {
|
|
159
|
+
enabled: true,
|
|
160
|
+
maxAgeMs: CONFIGURED_MAX_AGE_MS,
|
|
161
|
+
minAttemptIntervalMs: DEFAULT_REFRESH_MIN_ATTEMPT_INTERVAL_MS,
|
|
162
|
+
timeoutMs: DEFAULT_REFRESH_TIMEOUT_MS,
|
|
163
|
+
};
|
|
146
164
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
function withBundledRetiredModels(runtime, bundled) {
|
|
154
|
-
return keepRetiredModels({
|
|
155
|
-
current: runtime,
|
|
156
|
-
previous: [bundled],
|
|
157
|
-
providerIDs: DEFAULT_MODELSDEV_PROVIDERS,
|
|
158
|
-
});
|
|
165
|
+
/** Days after which the snapshot counts as stale; not a positive number means the default. */
|
|
166
|
+
export function setPricingSnapshotAutoRefresh(days) {
|
|
167
|
+
CONFIGURED_MAX_AGE_MS =
|
|
168
|
+
Number.isFinite(days) && days > 0
|
|
169
|
+
? Math.floor(days * MS_PER_DAY)
|
|
170
|
+
: DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
159
171
|
}
|
|
160
|
-
function
|
|
161
|
-
const
|
|
162
|
-
const
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (hasSnapshotData(bundled)) {
|
|
166
|
-
return { snapshot: bundled, source: "bundled" };
|
|
167
|
-
}
|
|
168
|
-
return { snapshot: EMPTY_SNAPSHOT, source: "empty" };
|
|
169
|
-
}
|
|
170
|
-
if (selection === "runtime") {
|
|
171
|
-
if (runtime) {
|
|
172
|
-
return { snapshot: withBundledRetiredModels(runtime, bundled), source: "runtime" };
|
|
173
|
-
}
|
|
174
|
-
if (hasSnapshotData(bundled)) {
|
|
175
|
-
return { snapshot: bundled, source: "bundled" };
|
|
176
|
-
}
|
|
177
|
-
return { snapshot: EMPTY_SNAPSHOT, source: "empty" };
|
|
172
|
+
function normalizeRefreshState(raw) {
|
|
173
|
+
const record = asRecord(raw);
|
|
174
|
+
const updatedAt = Number(record?.updatedAt);
|
|
175
|
+
if (!record || Number(record.version) !== 1 || !Number.isFinite(updatedAt) || updatedAt <= 0) {
|
|
176
|
+
return null;
|
|
178
177
|
}
|
|
179
|
-
|
|
180
|
-
|
|
178
|
+
const state = { version: 1, updatedAt: Math.trunc(updatedAt) };
|
|
179
|
+
for (const key of ["lastAttemptAt", "lastSuccessAt", "lastFailureAt"]) {
|
|
180
|
+
const at = Number(record[key]);
|
|
181
|
+
if (Number.isFinite(at) && at > 0)
|
|
182
|
+
state[key] = Math.trunc(at);
|
|
181
183
|
}
|
|
182
|
-
if (
|
|
183
|
-
|
|
184
|
+
if (typeof record.lastResult === "string" && REFRESH_RESULTS.has(record.lastResult)) {
|
|
185
|
+
state.lastResult = record.lastResult;
|
|
184
186
|
}
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
SNAPSHOT_SOURCE = source;
|
|
190
|
-
MODEL_INDEX = null;
|
|
191
|
-
}
|
|
192
|
-
function applySnapshotSelection(params) {
|
|
193
|
-
const selected = chooseSnapshot(params);
|
|
194
|
-
setSnapshot(selected.snapshot, selected.source);
|
|
195
|
-
return selected;
|
|
196
|
-
}
|
|
197
|
-
function ensureLoaded() {
|
|
198
|
-
if (SNAPSHOT)
|
|
199
|
-
return SNAPSHOT;
|
|
200
|
-
const selected = applySnapshotSelection();
|
|
201
|
-
return selected.snapshot;
|
|
202
|
-
}
|
|
203
|
-
function ensureModelIndex() {
|
|
204
|
-
if (MODEL_INDEX)
|
|
205
|
-
return MODEL_INDEX;
|
|
206
|
-
const snap = ensureLoaded();
|
|
207
|
-
const idx = new Map();
|
|
208
|
-
for (const providerId of Object.keys(snap.providers)) {
|
|
209
|
-
const models = snap.providers[providerId] ?? {};
|
|
210
|
-
for (const modelId of Object.keys(models)) {
|
|
211
|
-
const existing = idx.get(modelId);
|
|
212
|
-
if (existing)
|
|
213
|
-
existing.push(providerId);
|
|
214
|
-
else
|
|
215
|
-
idx.set(modelId, [providerId]);
|
|
216
|
-
}
|
|
187
|
+
for (const key of ["lastError", "etag", "lastModified"]) {
|
|
188
|
+
const text = record[key];
|
|
189
|
+
if (typeof text === "string" && text)
|
|
190
|
+
state[key] = text;
|
|
217
191
|
}
|
|
218
|
-
|
|
219
|
-
return idx;
|
|
192
|
+
return state;
|
|
220
193
|
}
|
|
221
|
-
function
|
|
222
|
-
const obj = asRecord(raw);
|
|
223
|
-
if (!obj)
|
|
224
|
-
return null;
|
|
225
|
-
const version = Number(obj.version);
|
|
226
|
-
const updatedAt = Number(obj.updatedAt);
|
|
227
|
-
if (version !== 1 || !Number.isFinite(updatedAt) || updatedAt <= 0)
|
|
228
|
-
return null;
|
|
229
|
-
const out = {
|
|
230
|
-
version: 1,
|
|
231
|
-
updatedAt: Math.trunc(updatedAt),
|
|
232
|
-
};
|
|
233
|
-
const lastAttemptAt = Number(obj.lastAttemptAt);
|
|
234
|
-
const lastSuccessAt = Number(obj.lastSuccessAt);
|
|
235
|
-
const lastFailureAt = Number(obj.lastFailureAt);
|
|
236
|
-
if (Number.isFinite(lastAttemptAt) && lastAttemptAt > 0)
|
|
237
|
-
out.lastAttemptAt = Math.trunc(lastAttemptAt);
|
|
238
|
-
if (Number.isFinite(lastSuccessAt) && lastSuccessAt > 0)
|
|
239
|
-
out.lastSuccessAt = Math.trunc(lastSuccessAt);
|
|
240
|
-
if (Number.isFinite(lastFailureAt) && lastFailureAt > 0)
|
|
241
|
-
out.lastFailureAt = Math.trunc(lastFailureAt);
|
|
242
|
-
if (typeof obj.lastResult === "string") {
|
|
243
|
-
const allowed = new Set([
|
|
244
|
-
"success",
|
|
245
|
-
"not_modified",
|
|
246
|
-
"skipped_fresh",
|
|
247
|
-
"skipped_throttled",
|
|
248
|
-
"failed",
|
|
249
|
-
]);
|
|
250
|
-
if (allowed.has(obj.lastResult)) {
|
|
251
|
-
out.lastResult = obj.lastResult;
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
if (typeof obj.lastError === "string" && obj.lastError)
|
|
255
|
-
out.lastError = obj.lastError;
|
|
256
|
-
if (typeof obj.etag === "string" && obj.etag)
|
|
257
|
-
out.etag = obj.etag;
|
|
258
|
-
if (typeof obj.lastModified === "string" && obj.lastModified)
|
|
259
|
-
out.lastModified = obj.lastModified;
|
|
260
|
-
return out;
|
|
261
|
-
}
|
|
262
|
-
async function readRefreshState(path) {
|
|
194
|
+
export async function readPricingRefreshState(runtimeDirs) {
|
|
263
195
|
try {
|
|
264
|
-
const raw = await readFile(
|
|
196
|
+
const raw = await readFile(getRuntimePricingRefreshStatePath(runtimeDirs), "utf-8");
|
|
265
197
|
return normalizeRefreshState(JSON.parse(raw));
|
|
266
198
|
}
|
|
267
199
|
catch {
|
|
268
200
|
return null;
|
|
269
201
|
}
|
|
270
202
|
}
|
|
271
|
-
|
|
272
|
-
return await readRefreshState(getRuntimePricingRefreshStatePath(runtimeDirs));
|
|
273
|
-
}
|
|
274
|
-
function makeDefaultRefreshState(nowMs) {
|
|
275
|
-
return {
|
|
276
|
-
version: 1,
|
|
277
|
-
updatedAt: nowMs,
|
|
278
|
-
};
|
|
279
|
-
}
|
|
280
|
-
function pickCostBuckets(rawCost) {
|
|
281
|
-
const obj = asRecord(rawCost);
|
|
282
|
-
if (!obj)
|
|
283
|
-
return null;
|
|
284
|
-
const picked = {};
|
|
285
|
-
for (const key of COST_KEYS) {
|
|
286
|
-
const value = obj[key];
|
|
287
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
288
|
-
picked[key] = value;
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
return Object.keys(picked).length > 0 ? picked : null;
|
|
292
|
-
}
|
|
293
|
-
function buildSnapshotFromApi(apiRaw, providerIDs, generatedAt) {
|
|
294
|
-
const api = asRecord(apiRaw) ?? {};
|
|
295
|
-
const providers = {};
|
|
296
|
-
for (const providerID of providerIDs) {
|
|
297
|
-
const providerNode = asRecord(api[providerID]);
|
|
298
|
-
const models = asRecord(providerNode?.models);
|
|
299
|
-
if (!models)
|
|
300
|
-
continue;
|
|
301
|
-
const pricedModels = {};
|
|
302
|
-
for (const modelID of Object.keys(models)) {
|
|
303
|
-
const modelNode = asRecord(models[modelID]);
|
|
304
|
-
const cost = pickCostBuckets(modelNode?.cost);
|
|
305
|
-
if (cost) {
|
|
306
|
-
pricedModels[modelID] = cost;
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
if (Object.keys(pricedModels).length > 0) {
|
|
310
|
-
providers[providerID] = sortRecordByKeys(pricedModels);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const providerList = Object.keys(providers).sort((a, b) => a.localeCompare(b));
|
|
314
|
-
return {
|
|
315
|
-
_meta: {
|
|
316
|
-
generatedAt,
|
|
317
|
-
providers: providerList,
|
|
318
|
-
source: SOURCE_URL,
|
|
319
|
-
units: "USD per 1M tokens",
|
|
320
|
-
},
|
|
321
|
-
providers: sortRecordByKeys(providers),
|
|
322
|
-
};
|
|
323
|
-
}
|
|
324
|
-
/**
|
|
325
|
-
* models.dev drops retired models from its list. Keep their last known price so
|
|
326
|
-
* older usage still gets a cost. `current` wins, then `previous` in the order given.
|
|
327
|
-
* Callers list the user's runtime snapshot before the bundled one: its prices come
|
|
328
|
-
* from the user's own last download, while the bundled file's date only says when
|
|
329
|
-
* the file was rewritten, not when a kept model's price was last seen.
|
|
330
|
-
*/
|
|
331
|
-
function keepRetiredModels(params) {
|
|
332
|
-
const previous = params.previous.filter((snapshot) => snapshot !== null);
|
|
333
|
-
const providers = { ...params.current.providers };
|
|
334
|
-
for (const providerID of params.providerIDs) {
|
|
335
|
-
const models = { ...(providers[providerID] ?? {}) };
|
|
336
|
-
for (const snapshot of previous) {
|
|
337
|
-
for (const [modelID, cost] of Object.entries(snapshot.providers[providerID] ?? {})) {
|
|
338
|
-
if (!models[modelID])
|
|
339
|
-
models[modelID] = cost;
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
if (Object.keys(models).length > 0) {
|
|
343
|
-
providers[providerID] = sortRecordByKeys(models);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
const sortedProviders = sortRecordByKeys(providers);
|
|
347
|
-
return {
|
|
348
|
-
_meta: { ...params.current._meta, providers: Object.keys(sortedProviders) },
|
|
349
|
-
providers: sortedProviders,
|
|
350
|
-
};
|
|
351
|
-
}
|
|
352
|
-
function countPricedModels(snapshot) {
|
|
353
|
-
let total = 0;
|
|
354
|
-
for (const models of Object.values(snapshot.providers)) {
|
|
355
|
-
total += Object.keys(models).length;
|
|
356
|
-
}
|
|
357
|
-
return total;
|
|
358
|
-
}
|
|
359
|
-
function getErrorMessage(error) {
|
|
360
|
-
return error instanceof Error ? error.message : String(error);
|
|
361
|
-
}
|
|
362
|
-
async function fetchModelsDevSnapshot(params) {
|
|
203
|
+
async function fetchModelsDev(params) {
|
|
363
204
|
const headers = new Headers();
|
|
364
205
|
if (params.state.etag)
|
|
365
206
|
headers.set("If-None-Match", params.state.etag);
|
|
@@ -370,305 +211,183 @@ async function fetchModelsDevSnapshot(params) {
|
|
|
370
211
|
timeoutMs: params.timeoutMs,
|
|
371
212
|
fetchFn: params.fetchFn,
|
|
372
213
|
consume: async (response) => {
|
|
373
|
-
const
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
if (response.status === 304) {
|
|
378
|
-
return { kind: "not_modified", ...responseMetadata };
|
|
379
|
-
}
|
|
214
|
+
const etag = response.headers.get("etag") ?? undefined;
|
|
215
|
+
const lastModified = response.headers.get("last-modified") ?? undefined;
|
|
216
|
+
if (response.status === 304)
|
|
217
|
+
return { kind: "not_modified", etag, lastModified };
|
|
380
218
|
if (!response.ok) {
|
|
381
219
|
throw new Error(`Failed to fetch ${SOURCE_URL}: ${response.status} ${response.statusText}`);
|
|
382
220
|
}
|
|
383
|
-
return {
|
|
384
|
-
kind: "success",
|
|
385
|
-
api: await response.json(),
|
|
386
|
-
...responseMetadata,
|
|
387
|
-
};
|
|
221
|
+
return { kind: "success", api: await response.json(), etag, lastModified };
|
|
388
222
|
},
|
|
389
223
|
});
|
|
390
224
|
}
|
|
225
|
+
function skipped(reason, state) {
|
|
226
|
+
return { attempted: false, updated: false, reason, state };
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Downloads new models.dev prices when the snapshot is stale: once per process (unless
|
|
230
|
+
* forced), at most every few hours across processes (the refresh state file remembers the
|
|
231
|
+
* last attempt), one download at a time. A failure keeps the snapshot in use.
|
|
232
|
+
*/
|
|
391
233
|
export async function maybeRefreshPricingSnapshot(opts = {}) {
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
}
|
|
426
|
-
if (!force && PROCESS_REFRESH_CHECKED) {
|
|
427
|
-
return {
|
|
428
|
-
attempted: false,
|
|
429
|
-
updated: false,
|
|
430
|
-
reason: "already_checked_this_process",
|
|
431
|
-
state: previousState,
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
PROCESS_REFRESH_CHECKED = true;
|
|
435
|
-
const health = getPricingSnapshotHealth({ nowMs, maxAgeMs });
|
|
436
|
-
if (!force && !policy.enabled) {
|
|
437
|
-
return {
|
|
438
|
-
attempted: false,
|
|
439
|
-
updated: false,
|
|
440
|
-
reason: "disabled",
|
|
441
|
-
state: {
|
|
442
|
-
...previousState,
|
|
443
|
-
updatedAt: nowMs,
|
|
444
|
-
lastResult: "skipped_fresh",
|
|
445
|
-
},
|
|
446
|
-
};
|
|
447
|
-
}
|
|
448
|
-
if (!force && !health.stale) {
|
|
449
|
-
return {
|
|
450
|
-
attempted: false,
|
|
451
|
-
updated: false,
|
|
452
|
-
reason: "fresh",
|
|
453
|
-
state: {
|
|
454
|
-
...previousState,
|
|
455
|
-
updatedAt: nowMs,
|
|
456
|
-
lastResult: "skipped_fresh",
|
|
457
|
-
},
|
|
458
|
-
};
|
|
459
|
-
}
|
|
460
|
-
if (!force &&
|
|
461
|
-
previousState.lastAttemptAt &&
|
|
462
|
-
nowMs - previousState.lastAttemptAt < minAttemptIntervalMs) {
|
|
463
|
-
return {
|
|
464
|
-
attempted: false,
|
|
465
|
-
updated: false,
|
|
466
|
-
reason: "throttled",
|
|
467
|
-
state: {
|
|
468
|
-
...previousState,
|
|
469
|
-
updatedAt: nowMs,
|
|
470
|
-
lastResult: "skipped_throttled",
|
|
471
|
-
},
|
|
472
|
-
};
|
|
473
|
-
}
|
|
474
|
-
const attemptingState = {
|
|
234
|
+
REFRESH_IN_FLIGHT ??= refreshPricingSnapshot(opts).finally(() => {
|
|
235
|
+
REFRESH_IN_FLIGHT = null;
|
|
236
|
+
});
|
|
237
|
+
return REFRESH_IN_FLIGHT;
|
|
238
|
+
}
|
|
239
|
+
async function refreshPricingSnapshot(opts) {
|
|
240
|
+
const nowMs = opts.nowMs ?? Date.now();
|
|
241
|
+
const policy = getPricingRefreshPolicy();
|
|
242
|
+
const force = opts.force === true;
|
|
243
|
+
const { runtimeDirs, bootstrapSnapshotOverride: bundledOverride } = opts;
|
|
244
|
+
const selection = opts.snapshotSelection ?? SNAPSHOT_SELECTION;
|
|
245
|
+
const previousState = (await readPricingRefreshState(runtimeDirs)) ?? {
|
|
246
|
+
version: 1,
|
|
247
|
+
updatedAt: nowMs,
|
|
248
|
+
};
|
|
249
|
+
const runtimeBefore = loadRuntimeSnapshot(runtimeDirs);
|
|
250
|
+
const bundled = loadBundledSnapshot(bundledOverride);
|
|
251
|
+
reloadSnapshot(selection, runtimeDirs, bundledOverride);
|
|
252
|
+
if (selection === "bundled" && opts.allowRefreshWhenSelectionBundled !== true) {
|
|
253
|
+
return skipped("selection_bundled", { ...previousState, updatedAt: nowMs });
|
|
254
|
+
}
|
|
255
|
+
if (!force && PROCESS_REFRESH_CHECKED) {
|
|
256
|
+
return skipped("already_checked_this_process", previousState);
|
|
257
|
+
}
|
|
258
|
+
PROCESS_REFRESH_CHECKED = true;
|
|
259
|
+
const maxAgeMs = opts.maxAgeMs ?? policy.maxAgeMs;
|
|
260
|
+
if (!force && !getPricingSnapshotHealth({ nowMs, maxAgeMs }).stale) {
|
|
261
|
+
return skipped("fresh", { ...previousState, updatedAt: nowMs, lastResult: "skipped_fresh" });
|
|
262
|
+
}
|
|
263
|
+
const minAttemptIntervalMs = opts.minAttemptIntervalMs ?? policy.minAttemptIntervalMs;
|
|
264
|
+
const lastAttemptAt = previousState.lastAttemptAt;
|
|
265
|
+
if (!force && lastAttemptAt && nowMs - lastAttemptAt < minAttemptIntervalMs) {
|
|
266
|
+
return skipped("throttled", {
|
|
475
267
|
...previousState,
|
|
476
|
-
version: 1,
|
|
477
268
|
updatedAt: nowMs,
|
|
478
|
-
|
|
479
|
-
};
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
providerIDs,
|
|
499
|
-
});
|
|
500
|
-
await writeJsonAtomic(snapshotPath, refreshedSnapshot, { trailingNewline: true });
|
|
501
|
-
applySnapshotSelection({
|
|
502
|
-
runtimeDirs,
|
|
503
|
-
bootstrapSnapshotOverride: opts.bootstrapSnapshotOverride,
|
|
504
|
-
selection,
|
|
505
|
-
});
|
|
506
|
-
const nextState = {
|
|
507
|
-
...attemptingState,
|
|
508
|
-
updatedAt: nowMs,
|
|
509
|
-
lastSuccessAt: nowMs,
|
|
510
|
-
lastResult: "not_modified",
|
|
511
|
-
lastError: undefined,
|
|
512
|
-
etag: fetchResult.etag ?? attemptingState.etag,
|
|
513
|
-
lastModified: fetchResult.lastModified ?? attemptingState.lastModified,
|
|
514
|
-
};
|
|
515
|
-
try {
|
|
516
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
517
|
-
}
|
|
518
|
-
catch {
|
|
519
|
-
// best effort; keep refreshed in-memory/runtime snapshot active
|
|
520
|
-
}
|
|
521
|
-
return {
|
|
522
|
-
attempted: true,
|
|
523
|
-
updated: true,
|
|
524
|
-
state: nextState,
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
const fetchedSnapshot = buildSnapshotFromApi(fetchResult.api, providerIDs, nowMs);
|
|
528
|
-
if (countPricedModels(fetchedSnapshot) === 0) {
|
|
529
|
-
throw new Error("Refusing to persist empty pricing snapshot from models.dev");
|
|
530
|
-
}
|
|
531
|
-
const snapshot = keepRetiredModels({
|
|
532
|
-
current: fetchedSnapshot,
|
|
533
|
-
previous: [runtimeSnapshotBeforeRefresh, bundledSnapshot],
|
|
534
|
-
providerIDs,
|
|
535
|
-
});
|
|
536
|
-
await writeJsonAtomic(snapshotPath, snapshot, { trailingNewline: true });
|
|
537
|
-
applySnapshotSelection({
|
|
538
|
-
runtimeDirs,
|
|
539
|
-
bootstrapSnapshotOverride: opts.bootstrapSnapshotOverride,
|
|
540
|
-
selection,
|
|
541
|
-
});
|
|
542
|
-
const nextState = {
|
|
543
|
-
...attemptingState,
|
|
544
|
-
updatedAt: nowMs,
|
|
545
|
-
lastSuccessAt: nowMs,
|
|
546
|
-
lastResult: "success",
|
|
547
|
-
lastError: undefined,
|
|
548
|
-
etag: fetchResult.etag ?? attemptingState.etag,
|
|
549
|
-
lastModified: fetchResult.lastModified ?? attemptingState.lastModified,
|
|
550
|
-
};
|
|
551
|
-
try {
|
|
552
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
553
|
-
}
|
|
554
|
-
catch {
|
|
555
|
-
// best effort; snapshot has already been updated
|
|
556
|
-
}
|
|
557
|
-
return {
|
|
558
|
-
attempted: true,
|
|
559
|
-
updated: true,
|
|
560
|
-
state: nextState,
|
|
561
|
-
};
|
|
269
|
+
lastResult: "skipped_throttled",
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
const attempting = {
|
|
273
|
+
...previousState,
|
|
274
|
+
version: 1,
|
|
275
|
+
updatedAt: nowMs,
|
|
276
|
+
lastAttemptAt: nowMs,
|
|
277
|
+
};
|
|
278
|
+
const providerIDs = opts.providerAllowlist ?? DEFAULT_MODELSDEV_PROVIDERS;
|
|
279
|
+
let next;
|
|
280
|
+
try {
|
|
281
|
+
const timeoutMs = opts.timeoutMs ?? policy.timeoutMs;
|
|
282
|
+
const fetched = await fetchModelsDev({ timeoutMs, state: attempting, fetchFn: opts.fetchFn });
|
|
283
|
+
let snapshot;
|
|
284
|
+
if (fetched.kind === "not_modified") {
|
|
285
|
+
// The same prices, confirmed now; also heals snapshots saved before retired models were kept.
|
|
286
|
+
const base = runtimeBefore ?? loaded().snapshot;
|
|
287
|
+
const confirmed = { _meta: { ...base._meta, generatedAt: nowMs }, providers: base.providers };
|
|
288
|
+
snapshot = keepRetiredModels(confirmed, [bundled], providerIDs);
|
|
562
289
|
}
|
|
563
|
-
|
|
564
|
-
const
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
updatedAt: nowMs,
|
|
568
|
-
lastFailureAt: nowMs,
|
|
569
|
-
lastResult: "failed",
|
|
570
|
-
lastError: errorMessage,
|
|
571
|
-
};
|
|
572
|
-
try {
|
|
573
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
574
|
-
}
|
|
575
|
-
catch {
|
|
576
|
-
// best effort; report original fetch/refresh error
|
|
290
|
+
else {
|
|
291
|
+
const fresh = buildSnapshotFromApi(fetched.api, providerIDs, nowMs);
|
|
292
|
+
if (Object.keys(fresh.providers).length === 0) {
|
|
293
|
+
throw new Error("Refusing to persist empty pricing snapshot from models.dev");
|
|
577
294
|
}
|
|
578
|
-
|
|
579
|
-
attempted: true,
|
|
580
|
-
updated: false,
|
|
581
|
-
error: errorMessage,
|
|
582
|
-
state: nextState,
|
|
583
|
-
};
|
|
295
|
+
snapshot = keepRetiredModels(fresh, [runtimeBefore, bundled], providerIDs);
|
|
584
296
|
}
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
297
|
+
await writeJsonAtomic(getRuntimePricingSnapshotPath(runtimeDirs), snapshot, {
|
|
298
|
+
trailingNewline: true,
|
|
299
|
+
});
|
|
300
|
+
reloadSnapshot(selection, runtimeDirs, bundledOverride);
|
|
301
|
+
next = {
|
|
302
|
+
...attempting,
|
|
303
|
+
lastSuccessAt: nowMs,
|
|
304
|
+
lastResult: fetched.kind,
|
|
305
|
+
lastError: undefined,
|
|
306
|
+
etag: fetched.etag ?? attempting.etag,
|
|
307
|
+
lastModified: fetched.lastModified ?? attempting.lastModified,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
310
|
+
catch (error) {
|
|
311
|
+
const lastError = error instanceof Error ? error.message : String(error);
|
|
312
|
+
next = { ...attempting, lastFailureAt: nowMs, lastResult: "failed", lastError };
|
|
313
|
+
}
|
|
314
|
+
// Best effort: the snapshot in use and the result stay right without the state file.
|
|
315
|
+
await writeJsonAtomic(getRuntimePricingRefreshStatePath(runtimeDirs), next, {
|
|
316
|
+
trailingNewline: true,
|
|
317
|
+
}).catch(() => { });
|
|
318
|
+
return next.lastResult === "failed"
|
|
319
|
+
? { attempted: true, updated: false, error: next.lastError, state: next }
|
|
320
|
+
: { attempted: true, updated: true, state: next };
|
|
589
321
|
}
|
|
590
322
|
export function setPricingSnapshotSelection(selection) {
|
|
591
323
|
if (SNAPSHOT_SELECTION === selection)
|
|
592
324
|
return;
|
|
593
325
|
SNAPSHOT_SELECTION = selection;
|
|
594
|
-
|
|
595
|
-
MODEL_INDEX = null;
|
|
326
|
+
LOADED = null;
|
|
596
327
|
}
|
|
597
328
|
export function getPricingSnapshotSelection() {
|
|
598
329
|
return SNAPSHOT_SELECTION;
|
|
599
330
|
}
|
|
600
331
|
export function getPricingSnapshotMeta() {
|
|
601
|
-
return
|
|
332
|
+
return loaded().snapshot._meta;
|
|
602
333
|
}
|
|
603
334
|
export function getPricingSnapshotSource() {
|
|
604
|
-
|
|
605
|
-
return SNAPSHOT_SOURCE;
|
|
335
|
+
return loaded().source;
|
|
606
336
|
}
|
|
607
337
|
export function getPricingSnapshotHealth(opts) {
|
|
608
338
|
const generatedAt = getPricingSnapshotMeta().generatedAt;
|
|
609
|
-
const nowMs = opts?.nowMs ?? Date.now();
|
|
610
339
|
const maxAgeMs = opts?.maxAgeMs ?? DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
611
|
-
const ageMs = Math.max(0, nowMs - generatedAt);
|
|
612
|
-
return {
|
|
613
|
-
generatedAt,
|
|
614
|
-
ageMs,
|
|
615
|
-
maxAgeMs,
|
|
616
|
-
stale: ageMs > maxAgeMs,
|
|
617
|
-
};
|
|
340
|
+
const ageMs = Math.max(0, (opts?.nowMs ?? Date.now()) - generatedAt);
|
|
341
|
+
return { generatedAt, ageMs, maxAgeMs, stale: ageMs > maxAgeMs };
|
|
618
342
|
}
|
|
619
343
|
export function hasProvider(providerId) {
|
|
620
|
-
return !!
|
|
621
|
-
}
|
|
622
|
-
export function isModelsDevProviderId(providerId) {
|
|
623
|
-
return hasProvider(providerId);
|
|
344
|
+
return !!pricedProviders()[providerId];
|
|
624
345
|
}
|
|
625
346
|
export function hasModel(providerId, modelId) {
|
|
626
|
-
|
|
627
|
-
if (!p)
|
|
628
|
-
return false;
|
|
629
|
-
return !!p[modelId];
|
|
630
|
-
}
|
|
631
|
-
/**
|
|
632
|
-
* Infer the snapshot provider that owns a modelId.
|
|
633
|
-
* Returns null when model is not found or is ambiguous across providers.
|
|
634
|
-
*/
|
|
635
|
-
export function inferProviderForModelId(modelId) {
|
|
636
|
-
const providers = listProvidersForModelId(modelId);
|
|
637
|
-
if (!providers || providers.length !== 1)
|
|
638
|
-
return null;
|
|
639
|
-
return providers[0] ?? null;
|
|
640
|
-
}
|
|
641
|
-
export function getProviderModelCount(providerId) {
|
|
642
|
-
return Object.keys(ensureLoaded().providers[providerId] || {}).length;
|
|
347
|
+
return !!pricedProviders()[providerId]?.[modelId];
|
|
643
348
|
}
|
|
644
349
|
export function listProviders() {
|
|
645
|
-
return Object.keys(
|
|
350
|
+
return Object.keys(pricedProviders());
|
|
646
351
|
}
|
|
647
352
|
export function listModelsForProvider(providerId) {
|
|
648
|
-
return Object.keys(
|
|
353
|
+
return Object.keys(pricedProviders()[providerId] ?? {});
|
|
649
354
|
}
|
|
650
355
|
export function listProvidersForModelId(modelId) {
|
|
651
|
-
const providers =
|
|
652
|
-
return
|
|
356
|
+
const providers = pricedProviders();
|
|
357
|
+
return Object.keys(providers)
|
|
358
|
+
.filter((providerId) => Object.hasOwn(providers[providerId] ?? {}, modelId))
|
|
359
|
+
.sort((a, b) => a.localeCompare(b));
|
|
360
|
+
}
|
|
361
|
+
let BUNDLED_IDS = null;
|
|
362
|
+
/** The provider and model ids of the price list shipped in this package, never a downloaded one. */
|
|
363
|
+
function bundledIds() {
|
|
364
|
+
if (!BUNDLED_IDS) {
|
|
365
|
+
const { providers } = loadBundledSnapshot();
|
|
366
|
+
BUNDLED_IDS = {
|
|
367
|
+
providers: new Set(Object.keys(providers)),
|
|
368
|
+
models: new Set(Object.values(providers).flatMap((models) => Object.keys(models))),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
return BUNDLED_IDS;
|
|
372
|
+
}
|
|
373
|
+
/** True when the shipped price list has this provider id. */
|
|
374
|
+
export function isBundledPricingProviderId(providerId) {
|
|
375
|
+
return bundledIds().providers.has(providerId);
|
|
376
|
+
}
|
|
377
|
+
/** True when the shipped price list has this model id under any provider. */
|
|
378
|
+
export function isBundledPricingModelId(modelId) {
|
|
379
|
+
return bundledIds().models.has(modelId);
|
|
653
380
|
}
|
|
654
381
|
export function lookupCost(providerId, modelId) {
|
|
655
|
-
|
|
656
|
-
if (!p)
|
|
657
|
-
return null;
|
|
658
|
-
const c = p[modelId];
|
|
659
|
-
if (!c)
|
|
660
|
-
return null;
|
|
661
|
-
return c;
|
|
382
|
+
return pricedProviders()[providerId]?.[modelId] ?? null;
|
|
662
383
|
}
|
|
663
384
|
export function hasCost(providerId, modelId) {
|
|
664
385
|
return lookupCost(providerId, modelId) != null;
|
|
665
386
|
}
|
|
666
387
|
export function __resetPricingSnapshotForTests() {
|
|
667
|
-
|
|
668
|
-
SNAPSHOT_SOURCE = "bundled";
|
|
388
|
+
LOADED = null;
|
|
669
389
|
SNAPSHOT_SELECTION = "auto";
|
|
670
|
-
|
|
671
|
-
MODEL_INDEX = null;
|
|
390
|
+
CONFIGURED_MAX_AGE_MS = DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
672
391
|
REFRESH_IN_FLIGHT = null;
|
|
673
392
|
PROCESS_REFRESH_CHECKED = false;
|
|
674
393
|
}
|