@slkiser/opencode-quota 5.0.2 → 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 +32 -46
- 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/data/modelsdev-pricing.min.json +248 -22
- 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 +34 -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 -510
- 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 -5
- package/dist/lib/ollama-cloud.d.ts.map +1 -1
- package/dist/lib/ollama-cloud.js +77 -46
- package/dist/lib/ollama-cloud.js.map +1 -1
- package/dist/lib/openai.d.ts +19 -29
- package/dist/lib/openai.d.ts.map +1 -1
- package/dist/lib/openai.js +134 -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 +23 -7
- package/dist/lib/opencode-zen.d.ts.map +1 -1
- package/dist/lib/opencode-zen.js +175 -62
- 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 -772
- 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 +46 -340
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/types.js +2 -69
- 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 +45 -91
- 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.map +1 -1
- package/dist/providers/google-agy.js +41 -179
- 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 -5
- package/dist/providers/ollama-cloud.d.ts.map +1 -1
- package/dist/providers/ollama-cloud.js +86 -87
- package/dist/providers/ollama-cloud.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +157 -150
- 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 +104 -141
- 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 -1083
- 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 -26
- package/dist/lib/quota-surface-data.d.ts.map +0 -1
- package/dist/lib/quota-surface-data.js +0 -299
- 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,323 +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
|
-
|
|
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)
|
|
62
77
|
return null;
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const
|
|
86
|
-
|
|
87
|
-
buckets.input = input;
|
|
88
|
-
if (typeof output === "number" && Number.isFinite(output))
|
|
89
|
-
buckets.output = output;
|
|
90
|
-
if (typeof cacheRead === "number" && Number.isFinite(cacheRead))
|
|
91
|
-
buckets.cache_read = cacheRead;
|
|
92
|
-
if (typeof cacheWrite === "number" && Number.isFinite(cacheWrite)) {
|
|
93
|
-
buckets.cache_write = cacheWrite;
|
|
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
|
-
|
|
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;
|
|
149
171
|
}
|
|
150
|
-
function
|
|
151
|
-
const
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (hasSnapshotData(bundled)) {
|
|
156
|
-
return { snapshot: bundled, source: "bundled" };
|
|
157
|
-
}
|
|
158
|
-
return { snapshot: EMPTY_SNAPSHOT, source: "empty" };
|
|
159
|
-
}
|
|
160
|
-
if (selection === "runtime") {
|
|
161
|
-
if (runtime) {
|
|
162
|
-
return { snapshot: runtime, source: "runtime" };
|
|
163
|
-
}
|
|
164
|
-
if (hasSnapshotData(bundled)) {
|
|
165
|
-
return { snapshot: bundled, source: "bundled" };
|
|
166
|
-
}
|
|
167
|
-
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;
|
|
168
177
|
}
|
|
169
|
-
|
|
170
|
-
|
|
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);
|
|
171
183
|
}
|
|
172
|
-
if (
|
|
173
|
-
|
|
184
|
+
if (typeof record.lastResult === "string" && REFRESH_RESULTS.has(record.lastResult)) {
|
|
185
|
+
state.lastResult = record.lastResult;
|
|
174
186
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
SNAPSHOT_SOURCE = source;
|
|
180
|
-
MODEL_INDEX = null;
|
|
181
|
-
}
|
|
182
|
-
function applySnapshotSelection(params) {
|
|
183
|
-
const selected = chooseSnapshot(params);
|
|
184
|
-
setSnapshot(selected.snapshot, selected.source);
|
|
185
|
-
return selected;
|
|
186
|
-
}
|
|
187
|
-
function ensureLoaded() {
|
|
188
|
-
if (SNAPSHOT)
|
|
189
|
-
return SNAPSHOT;
|
|
190
|
-
const selected = applySnapshotSelection();
|
|
191
|
-
return selected.snapshot;
|
|
192
|
-
}
|
|
193
|
-
function ensureModelIndex() {
|
|
194
|
-
if (MODEL_INDEX)
|
|
195
|
-
return MODEL_INDEX;
|
|
196
|
-
const snap = ensureLoaded();
|
|
197
|
-
const idx = new Map();
|
|
198
|
-
for (const providerId of Object.keys(snap.providers)) {
|
|
199
|
-
const models = snap.providers[providerId] ?? {};
|
|
200
|
-
for (const modelId of Object.keys(models)) {
|
|
201
|
-
const existing = idx.get(modelId);
|
|
202
|
-
if (existing)
|
|
203
|
-
existing.push(providerId);
|
|
204
|
-
else
|
|
205
|
-
idx.set(modelId, [providerId]);
|
|
206
|
-
}
|
|
187
|
+
for (const key of ["lastError", "etag", "lastModified"]) {
|
|
188
|
+
const text = record[key];
|
|
189
|
+
if (typeof text === "string" && text)
|
|
190
|
+
state[key] = text;
|
|
207
191
|
}
|
|
208
|
-
|
|
209
|
-
return idx;
|
|
192
|
+
return state;
|
|
210
193
|
}
|
|
211
|
-
function
|
|
212
|
-
const obj = asRecord(raw);
|
|
213
|
-
if (!obj)
|
|
214
|
-
return null;
|
|
215
|
-
const version = Number(obj.version);
|
|
216
|
-
const updatedAt = Number(obj.updatedAt);
|
|
217
|
-
if (version !== 1 || !Number.isFinite(updatedAt) || updatedAt <= 0)
|
|
218
|
-
return null;
|
|
219
|
-
const out = {
|
|
220
|
-
version: 1,
|
|
221
|
-
updatedAt: Math.trunc(updatedAt),
|
|
222
|
-
};
|
|
223
|
-
const lastAttemptAt = Number(obj.lastAttemptAt);
|
|
224
|
-
const lastSuccessAt = Number(obj.lastSuccessAt);
|
|
225
|
-
const lastFailureAt = Number(obj.lastFailureAt);
|
|
226
|
-
if (Number.isFinite(lastAttemptAt) && lastAttemptAt > 0)
|
|
227
|
-
out.lastAttemptAt = Math.trunc(lastAttemptAt);
|
|
228
|
-
if (Number.isFinite(lastSuccessAt) && lastSuccessAt > 0)
|
|
229
|
-
out.lastSuccessAt = Math.trunc(lastSuccessAt);
|
|
230
|
-
if (Number.isFinite(lastFailureAt) && lastFailureAt > 0)
|
|
231
|
-
out.lastFailureAt = Math.trunc(lastFailureAt);
|
|
232
|
-
if (typeof obj.lastResult === "string") {
|
|
233
|
-
const allowed = new Set([
|
|
234
|
-
"success",
|
|
235
|
-
"not_modified",
|
|
236
|
-
"skipped_fresh",
|
|
237
|
-
"skipped_throttled",
|
|
238
|
-
"failed",
|
|
239
|
-
]);
|
|
240
|
-
if (allowed.has(obj.lastResult)) {
|
|
241
|
-
out.lastResult = obj.lastResult;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (typeof obj.lastError === "string" && obj.lastError)
|
|
245
|
-
out.lastError = obj.lastError;
|
|
246
|
-
if (typeof obj.etag === "string" && obj.etag)
|
|
247
|
-
out.etag = obj.etag;
|
|
248
|
-
if (typeof obj.lastModified === "string" && obj.lastModified)
|
|
249
|
-
out.lastModified = obj.lastModified;
|
|
250
|
-
return out;
|
|
251
|
-
}
|
|
252
|
-
async function readRefreshState(path) {
|
|
194
|
+
export async function readPricingRefreshState(runtimeDirs) {
|
|
253
195
|
try {
|
|
254
|
-
const raw = await readFile(
|
|
196
|
+
const raw = await readFile(getRuntimePricingRefreshStatePath(runtimeDirs), "utf-8");
|
|
255
197
|
return normalizeRefreshState(JSON.parse(raw));
|
|
256
198
|
}
|
|
257
199
|
catch {
|
|
258
200
|
return null;
|
|
259
201
|
}
|
|
260
202
|
}
|
|
261
|
-
|
|
262
|
-
return await readRefreshState(getRuntimePricingRefreshStatePath(runtimeDirs));
|
|
263
|
-
}
|
|
264
|
-
function makeDefaultRefreshState(nowMs) {
|
|
265
|
-
return {
|
|
266
|
-
version: 1,
|
|
267
|
-
updatedAt: nowMs,
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
|
-
function pickCostBuckets(rawCost) {
|
|
271
|
-
const obj = asRecord(rawCost);
|
|
272
|
-
if (!obj)
|
|
273
|
-
return null;
|
|
274
|
-
const picked = {};
|
|
275
|
-
for (const key of COST_KEYS) {
|
|
276
|
-
const value = obj[key];
|
|
277
|
-
if (typeof value === "number" && Number.isFinite(value)) {
|
|
278
|
-
picked[key] = value;
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
return Object.keys(picked).length > 0 ? picked : null;
|
|
282
|
-
}
|
|
283
|
-
function buildSnapshotFromApi(apiRaw, providerIDs, generatedAt) {
|
|
284
|
-
const api = asRecord(apiRaw) ?? {};
|
|
285
|
-
const providers = {};
|
|
286
|
-
for (const providerID of providerIDs) {
|
|
287
|
-
const providerNode = asRecord(api[providerID]);
|
|
288
|
-
const models = asRecord(providerNode?.models);
|
|
289
|
-
if (!models)
|
|
290
|
-
continue;
|
|
291
|
-
const pricedModels = {};
|
|
292
|
-
for (const modelID of Object.keys(models)) {
|
|
293
|
-
const modelNode = asRecord(models[modelID]);
|
|
294
|
-
const cost = pickCostBuckets(modelNode?.cost);
|
|
295
|
-
if (cost) {
|
|
296
|
-
pricedModels[modelID] = cost;
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
if (Object.keys(pricedModels).length > 0) {
|
|
300
|
-
providers[providerID] = sortRecordByKeys(pricedModels);
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
const providerList = Object.keys(providers).sort((a, b) => a.localeCompare(b));
|
|
304
|
-
return {
|
|
305
|
-
_meta: {
|
|
306
|
-
generatedAt,
|
|
307
|
-
providers: providerList,
|
|
308
|
-
source: SOURCE_URL,
|
|
309
|
-
units: "USD per 1M tokens",
|
|
310
|
-
},
|
|
311
|
-
providers: sortRecordByKeys(providers),
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
function countPricedModels(snapshot) {
|
|
315
|
-
let total = 0;
|
|
316
|
-
for (const models of Object.values(snapshot.providers)) {
|
|
317
|
-
total += Object.keys(models).length;
|
|
318
|
-
}
|
|
319
|
-
return total;
|
|
320
|
-
}
|
|
321
|
-
function getErrorMessage(error) {
|
|
322
|
-
return error instanceof Error ? error.message : String(error);
|
|
323
|
-
}
|
|
324
|
-
async function fetchModelsDevSnapshot(params) {
|
|
203
|
+
async function fetchModelsDev(params) {
|
|
325
204
|
const headers = new Headers();
|
|
326
205
|
if (params.state.etag)
|
|
327
206
|
headers.set("If-None-Match", params.state.etag);
|
|
@@ -332,293 +211,183 @@ async function fetchModelsDevSnapshot(params) {
|
|
|
332
211
|
timeoutMs: params.timeoutMs,
|
|
333
212
|
fetchFn: params.fetchFn,
|
|
334
213
|
consume: async (response) => {
|
|
335
|
-
const
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
if (response.status === 304) {
|
|
340
|
-
return { kind: "not_modified", ...responseMetadata };
|
|
341
|
-
}
|
|
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 };
|
|
342
218
|
if (!response.ok) {
|
|
343
219
|
throw new Error(`Failed to fetch ${SOURCE_URL}: ${response.status} ${response.statusText}`);
|
|
344
220
|
}
|
|
345
|
-
return {
|
|
346
|
-
kind: "success",
|
|
347
|
-
api: await response.json(),
|
|
348
|
-
...responseMetadata,
|
|
349
|
-
};
|
|
221
|
+
return { kind: "success", api: await response.json(), etag, lastModified };
|
|
350
222
|
},
|
|
351
223
|
});
|
|
352
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
|
+
*/
|
|
353
233
|
export async function maybeRefreshPricingSnapshot(opts = {}) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
return {
|
|
388
|
-
attempted: false,
|
|
389
|
-
updated: false,
|
|
390
|
-
reason: "already_checked_this_process",
|
|
391
|
-
state: previousState,
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
PROCESS_REFRESH_CHECKED = true;
|
|
395
|
-
const health = getPricingSnapshotHealth({ nowMs, maxAgeMs });
|
|
396
|
-
if (!force && !policy.enabled) {
|
|
397
|
-
return {
|
|
398
|
-
attempted: false,
|
|
399
|
-
updated: false,
|
|
400
|
-
reason: "disabled",
|
|
401
|
-
state: {
|
|
402
|
-
...previousState,
|
|
403
|
-
updatedAt: nowMs,
|
|
404
|
-
lastResult: "skipped_fresh",
|
|
405
|
-
},
|
|
406
|
-
};
|
|
407
|
-
}
|
|
408
|
-
if (!force && !health.stale) {
|
|
409
|
-
return {
|
|
410
|
-
attempted: false,
|
|
411
|
-
updated: false,
|
|
412
|
-
reason: "fresh",
|
|
413
|
-
state: {
|
|
414
|
-
...previousState,
|
|
415
|
-
updatedAt: nowMs,
|
|
416
|
-
lastResult: "skipped_fresh",
|
|
417
|
-
},
|
|
418
|
-
};
|
|
419
|
-
}
|
|
420
|
-
if (!force &&
|
|
421
|
-
previousState.lastAttemptAt &&
|
|
422
|
-
nowMs - previousState.lastAttemptAt < minAttemptIntervalMs) {
|
|
423
|
-
return {
|
|
424
|
-
attempted: false,
|
|
425
|
-
updated: false,
|
|
426
|
-
reason: "throttled",
|
|
427
|
-
state: {
|
|
428
|
-
...previousState,
|
|
429
|
-
updatedAt: nowMs,
|
|
430
|
-
lastResult: "skipped_throttled",
|
|
431
|
-
},
|
|
432
|
-
};
|
|
433
|
-
}
|
|
434
|
-
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", {
|
|
435
267
|
...previousState,
|
|
436
|
-
version: 1,
|
|
437
268
|
updatedAt: nowMs,
|
|
438
|
-
|
|
439
|
-
};
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
bootstrapSnapshotOverride: opts.bootstrapSnapshotOverride,
|
|
459
|
-
selection,
|
|
460
|
-
});
|
|
461
|
-
const nextState = {
|
|
462
|
-
...attemptingState,
|
|
463
|
-
updatedAt: nowMs,
|
|
464
|
-
lastSuccessAt: nowMs,
|
|
465
|
-
lastResult: "not_modified",
|
|
466
|
-
lastError: undefined,
|
|
467
|
-
etag: fetchResult.etag ?? attemptingState.etag,
|
|
468
|
-
lastModified: fetchResult.lastModified ?? attemptingState.lastModified,
|
|
469
|
-
};
|
|
470
|
-
try {
|
|
471
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
472
|
-
}
|
|
473
|
-
catch {
|
|
474
|
-
// best effort; keep refreshed in-memory/runtime snapshot active
|
|
475
|
-
}
|
|
476
|
-
return {
|
|
477
|
-
attempted: true,
|
|
478
|
-
updated: true,
|
|
479
|
-
state: nextState,
|
|
480
|
-
};
|
|
481
|
-
}
|
|
482
|
-
const snapshot = buildSnapshotFromApi(fetchResult.api, opts.providerAllowlist ?? DEFAULT_MODELSDEV_PROVIDERS, nowMs);
|
|
483
|
-
if (countPricedModels(snapshot) === 0) {
|
|
484
|
-
throw new Error("Refusing to persist empty pricing snapshot from models.dev");
|
|
485
|
-
}
|
|
486
|
-
await writeJsonAtomic(snapshotPath, snapshot, { trailingNewline: true });
|
|
487
|
-
applySnapshotSelection({
|
|
488
|
-
runtimeDirs,
|
|
489
|
-
bootstrapSnapshotOverride: opts.bootstrapSnapshotOverride,
|
|
490
|
-
selection,
|
|
491
|
-
});
|
|
492
|
-
const nextState = {
|
|
493
|
-
...attemptingState,
|
|
494
|
-
updatedAt: nowMs,
|
|
495
|
-
lastSuccessAt: nowMs,
|
|
496
|
-
lastResult: "success",
|
|
497
|
-
lastError: undefined,
|
|
498
|
-
etag: fetchResult.etag ?? attemptingState.etag,
|
|
499
|
-
lastModified: fetchResult.lastModified ?? attemptingState.lastModified,
|
|
500
|
-
};
|
|
501
|
-
try {
|
|
502
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
503
|
-
}
|
|
504
|
-
catch {
|
|
505
|
-
// best effort; snapshot has already been updated
|
|
506
|
-
}
|
|
507
|
-
return {
|
|
508
|
-
attempted: true,
|
|
509
|
-
updated: true,
|
|
510
|
-
state: nextState,
|
|
511
|
-
};
|
|
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);
|
|
512
289
|
}
|
|
513
|
-
|
|
514
|
-
const
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
updatedAt: nowMs,
|
|
518
|
-
lastFailureAt: nowMs,
|
|
519
|
-
lastResult: "failed",
|
|
520
|
-
lastError: errorMessage,
|
|
521
|
-
};
|
|
522
|
-
try {
|
|
523
|
-
await writeJsonAtomic(statePath, nextState, { trailingNewline: true });
|
|
524
|
-
}
|
|
525
|
-
catch {
|
|
526
|
-
// 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");
|
|
527
294
|
}
|
|
528
|
-
|
|
529
|
-
attempted: true,
|
|
530
|
-
updated: false,
|
|
531
|
-
error: errorMessage,
|
|
532
|
-
state: nextState,
|
|
533
|
-
};
|
|
295
|
+
snapshot = keepRetiredModels(fresh, [runtimeBefore, bundled], providerIDs);
|
|
534
296
|
}
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
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 };
|
|
539
321
|
}
|
|
540
322
|
export function setPricingSnapshotSelection(selection) {
|
|
541
323
|
if (SNAPSHOT_SELECTION === selection)
|
|
542
324
|
return;
|
|
543
325
|
SNAPSHOT_SELECTION = selection;
|
|
544
|
-
|
|
545
|
-
MODEL_INDEX = null;
|
|
326
|
+
LOADED = null;
|
|
546
327
|
}
|
|
547
328
|
export function getPricingSnapshotSelection() {
|
|
548
329
|
return SNAPSHOT_SELECTION;
|
|
549
330
|
}
|
|
550
331
|
export function getPricingSnapshotMeta() {
|
|
551
|
-
return
|
|
332
|
+
return loaded().snapshot._meta;
|
|
552
333
|
}
|
|
553
334
|
export function getPricingSnapshotSource() {
|
|
554
|
-
|
|
555
|
-
return SNAPSHOT_SOURCE;
|
|
335
|
+
return loaded().source;
|
|
556
336
|
}
|
|
557
337
|
export function getPricingSnapshotHealth(opts) {
|
|
558
338
|
const generatedAt = getPricingSnapshotMeta().generatedAt;
|
|
559
|
-
const nowMs = opts?.nowMs ?? Date.now();
|
|
560
339
|
const maxAgeMs = opts?.maxAgeMs ?? DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
561
|
-
const ageMs = Math.max(0, nowMs - generatedAt);
|
|
562
|
-
return {
|
|
563
|
-
generatedAt,
|
|
564
|
-
ageMs,
|
|
565
|
-
maxAgeMs,
|
|
566
|
-
stale: ageMs > maxAgeMs,
|
|
567
|
-
};
|
|
340
|
+
const ageMs = Math.max(0, (opts?.nowMs ?? Date.now()) - generatedAt);
|
|
341
|
+
return { generatedAt, ageMs, maxAgeMs, stale: ageMs > maxAgeMs };
|
|
568
342
|
}
|
|
569
343
|
export function hasProvider(providerId) {
|
|
570
|
-
return !!
|
|
571
|
-
}
|
|
572
|
-
export function isModelsDevProviderId(providerId) {
|
|
573
|
-
return hasProvider(providerId);
|
|
344
|
+
return !!pricedProviders()[providerId];
|
|
574
345
|
}
|
|
575
346
|
export function hasModel(providerId, modelId) {
|
|
576
|
-
|
|
577
|
-
if (!p)
|
|
578
|
-
return false;
|
|
579
|
-
return !!p[modelId];
|
|
580
|
-
}
|
|
581
|
-
/**
|
|
582
|
-
* Infer the snapshot provider that owns a modelId.
|
|
583
|
-
* Returns null when model is not found or is ambiguous across providers.
|
|
584
|
-
*/
|
|
585
|
-
export function inferProviderForModelId(modelId) {
|
|
586
|
-
const providers = listProvidersForModelId(modelId);
|
|
587
|
-
if (!providers || providers.length !== 1)
|
|
588
|
-
return null;
|
|
589
|
-
return providers[0] ?? null;
|
|
590
|
-
}
|
|
591
|
-
export function getProviderModelCount(providerId) {
|
|
592
|
-
return Object.keys(ensureLoaded().providers[providerId] || {}).length;
|
|
347
|
+
return !!pricedProviders()[providerId]?.[modelId];
|
|
593
348
|
}
|
|
594
349
|
export function listProviders() {
|
|
595
|
-
return Object.keys(
|
|
350
|
+
return Object.keys(pricedProviders());
|
|
596
351
|
}
|
|
597
352
|
export function listModelsForProvider(providerId) {
|
|
598
|
-
return Object.keys(
|
|
353
|
+
return Object.keys(pricedProviders()[providerId] ?? {});
|
|
599
354
|
}
|
|
600
355
|
export function listProvidersForModelId(modelId) {
|
|
601
|
-
const providers =
|
|
602
|
-
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);
|
|
603
380
|
}
|
|
604
381
|
export function lookupCost(providerId, modelId) {
|
|
605
|
-
|
|
606
|
-
if (!p)
|
|
607
|
-
return null;
|
|
608
|
-
const c = p[modelId];
|
|
609
|
-
if (!c)
|
|
610
|
-
return null;
|
|
611
|
-
return c;
|
|
382
|
+
return pricedProviders()[providerId]?.[modelId] ?? null;
|
|
612
383
|
}
|
|
613
384
|
export function hasCost(providerId, modelId) {
|
|
614
385
|
return lookupCost(providerId, modelId) != null;
|
|
615
386
|
}
|
|
616
387
|
export function __resetPricingSnapshotForTests() {
|
|
617
|
-
|
|
618
|
-
SNAPSHOT_SOURCE = "bundled";
|
|
388
|
+
LOADED = null;
|
|
619
389
|
SNAPSHOT_SELECTION = "auto";
|
|
620
|
-
|
|
621
|
-
MODEL_INDEX = null;
|
|
390
|
+
CONFIGURED_MAX_AGE_MS = DEFAULT_PRICING_SNAPSHOT_MAX_AGE_MS;
|
|
622
391
|
REFRESH_IN_FLIGHT = null;
|
|
623
392
|
PROCESS_REFRESH_CHECKED = false;
|
|
624
393
|
}
|