@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
|
@@ -1,36 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isIsoTime } from "../core/validate.js";
|
|
2
|
+
import { getApiKeyCheckedPaths, resolveApiKey } from "./api-key-resolver.js";
|
|
2
3
|
import { sanitizeSingleLineDisplayText } from "./display-sanitize.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { fmtUsdAmount } from "./format-utils.js";
|
|
5
|
+
import { REQUEST_TIMEOUT_MS } from "./http.js";
|
|
6
|
+
import { hasOnlyKeys, isRecord } from "./json-guards.js";
|
|
7
|
+
import { getCredentialDatabasePaths } from "./opencode-auth.js";
|
|
8
|
+
import { CUSTOM_RESULT_TYPES, customRow, customRowKey, JSON_V1_MAX_DISPLAY_CODE_POINTS, JSON_V1_MAX_NUMBER_MAGNITUDE, normalizeJsonV1Timestamp, } from "./quota-providers.js";
|
|
6
9
|
export const QUOTA_PROVIDER_MAX_BODY_BYTES = 256 * 1024;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
|
|
22
|
-
|
|
10
|
+
const MAX_REMOTE_ROWS = 100;
|
|
11
|
+
const JSON_V1_MAX_RESPONSE_DEPTH = 32;
|
|
12
|
+
const JSON_V1_MAX_CANDIDATES = 1_600;
|
|
13
|
+
const JSON_V1_MAX_ENTRIES = 100;
|
|
14
|
+
const JSON_V1_MAX_DETAILED_ERRORS = 16;
|
|
15
|
+
const PERCENT_RESULT_TYPES = new Set(["quota", "rate_limit", "budget"]);
|
|
16
|
+
/** `right` and `observedAtIso` are checked but not shown. */
|
|
17
|
+
const QUOTA_V1_ROW_KEYS = [
|
|
18
|
+
"kind",
|
|
19
|
+
"name",
|
|
20
|
+
"resultType",
|
|
21
|
+
"percentRemaining",
|
|
22
|
+
"value",
|
|
23
|
+
"label",
|
|
24
|
+
"right",
|
|
25
|
+
"resetTimeIso",
|
|
26
|
+
"observedAtIso",
|
|
27
|
+
];
|
|
23
28
|
const JSON_V1_DECIMAL_TEXT_RE = /^-?\d+(?:\.\d+)?$/;
|
|
24
|
-
function isRecord(value) {
|
|
25
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
26
|
-
}
|
|
27
|
-
function hasOnlyKeys(value, allowed) {
|
|
28
|
-
const allowedSet = new Set(allowed);
|
|
29
|
-
return Object.keys(value).every((key) => allowedSet.has(key));
|
|
30
|
-
}
|
|
31
|
-
function isIsoTimestamp(value) {
|
|
32
|
-
return (typeof value === "string" && ISO_TIMESTAMP_RE.test(value) && Number.isFinite(Date.parse(value)));
|
|
33
|
-
}
|
|
34
29
|
function boundedDisplayText(value, maxCodePoints) {
|
|
35
30
|
if (typeof value !== "string")
|
|
36
31
|
return null;
|
|
@@ -38,185 +33,156 @@ function boundedDisplayText(value, maxCodePoints) {
|
|
|
38
33
|
const length = Array.from(normalized).length;
|
|
39
34
|
return length >= 1 && length <= maxCodePoints ? normalized : null;
|
|
40
35
|
}
|
|
41
|
-
function formatUsd(value) {
|
|
42
|
-
return `$${value.toFixed(2)}`;
|
|
43
|
-
}
|
|
44
|
-
function accountingMetadata(resultType, observedAtIso) {
|
|
45
|
-
return {
|
|
46
|
-
resultType,
|
|
47
|
-
acquisitionMethod: "remote_api",
|
|
48
|
-
ownership: "user_configured",
|
|
49
|
-
authority: "provider_reported",
|
|
50
|
-
...(observedAtIso ? { observedAtIso } : {}),
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
36
|
export async function resolveQuotaProviderApiKey(source) {
|
|
54
|
-
|
|
55
|
-
|
|
37
|
+
// A switched-off provider's key is never read, whoever asks.
|
|
38
|
+
if (source.enabled === false) {
|
|
39
|
+
return { source: null, checkedPaths: [], credentialDatabasePaths: [] };
|
|
40
|
+
}
|
|
41
|
+
const spec = {
|
|
42
|
+
envVars: source.apiKeyEnv ? [source.apiKeyEnv] : [],
|
|
56
43
|
providerKeys: [source.providerId],
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
// Key logins only: `providerId` can name an integration with OAuth sign-ins
|
|
63
|
-
// (for example `opencode`), and resolving one could refresh its token for nothing.
|
|
64
|
-
readAuth: () => readAuthFile({ integrationIds: [source.providerId], methods: ["key"] }),
|
|
65
|
-
authKeys: [source.providerId],
|
|
66
|
-
authSource: "opencode.db",
|
|
67
|
-
},
|
|
68
|
-
});
|
|
69
|
-
const resolved = await resolver.resolve();
|
|
44
|
+
// Key logins only: `providerId` can name an integration with OAuth sign-ins
|
|
45
|
+
// (for example `opencode`), and resolving one could refresh its token for nothing.
|
|
46
|
+
keyLoginsOnly: true,
|
|
47
|
+
};
|
|
48
|
+
const resolved = await resolveApiKey(spec);
|
|
70
49
|
return {
|
|
71
50
|
...(resolved ? { key: resolved.key } : {}),
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
51
|
+
// Custom providers report every environment variable source as plain "env".
|
|
52
|
+
source: !resolved
|
|
53
|
+
? null
|
|
54
|
+
: resolved.source.startsWith("env:")
|
|
55
|
+
? "env"
|
|
56
|
+
: resolved.source,
|
|
57
|
+
checkedPaths: getApiKeyCheckedPaths(spec),
|
|
77
58
|
credentialDatabasePaths: getCredentialDatabasePaths(),
|
|
78
59
|
};
|
|
79
60
|
}
|
|
61
|
+
function isJsonContentType(response) {
|
|
62
|
+
const type = response.headers.get("content-type")?.split(";", 1)[0]?.trim().toLowerCase();
|
|
63
|
+
if (!type)
|
|
64
|
+
return false;
|
|
65
|
+
return type === "application/json" || (type.startsWith("application/") && type.endsWith("+json"));
|
|
66
|
+
}
|
|
67
|
+
/** Reads at most QUOTA_PROVIDER_MAX_BODY_BYTES, so a huge reply never sits in memory. */
|
|
80
68
|
async function readBoundedJson(response) {
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
if (
|
|
89
|
-
|
|
90
|
-
if (Number.isFinite(parsedLength) && parsedLength > QUOTA_PROVIDER_MAX_BODY_BYTES) {
|
|
91
|
-
throw new Error("Response exceeded 262144 bytes");
|
|
92
|
-
}
|
|
69
|
+
const tooLarge = {
|
|
70
|
+
ok: false,
|
|
71
|
+
error: `Response exceeded ${QUOTA_PROVIDER_MAX_BODY_BYTES} bytes`,
|
|
72
|
+
};
|
|
73
|
+
if (!isJsonContentType(response))
|
|
74
|
+
return { ok: false, error: "Expected a JSON response" };
|
|
75
|
+
const declaredLength = Number(response.headers.get("content-length"));
|
|
76
|
+
if (Number.isFinite(declaredLength) && declaredLength > QUOTA_PROVIDER_MAX_BODY_BYTES) {
|
|
77
|
+
return tooLarge;
|
|
93
78
|
}
|
|
94
|
-
let
|
|
79
|
+
let text = "";
|
|
95
80
|
if (response.body) {
|
|
96
81
|
const reader = response.body.getReader();
|
|
97
|
-
const
|
|
82
|
+
const decoder = new TextDecoder();
|
|
98
83
|
let total = 0;
|
|
99
84
|
try {
|
|
100
|
-
|
|
101
|
-
const next = await reader.read();
|
|
102
|
-
if (next.done)
|
|
103
|
-
break;
|
|
85
|
+
for (let next = await reader.read(); !next.done; next = await reader.read()) {
|
|
104
86
|
total += next.value.byteLength;
|
|
105
87
|
if (total > QUOTA_PROVIDER_MAX_BODY_BYTES) {
|
|
106
88
|
await reader.cancel();
|
|
107
|
-
|
|
89
|
+
return tooLarge;
|
|
108
90
|
}
|
|
109
|
-
|
|
91
|
+
text += decoder.decode(next.value, { stream: true });
|
|
110
92
|
}
|
|
93
|
+
text += decoder.decode();
|
|
111
94
|
}
|
|
112
95
|
finally {
|
|
113
96
|
reader.releaseLock();
|
|
114
97
|
}
|
|
115
|
-
bytes = new Uint8Array(total);
|
|
116
|
-
let offset = 0;
|
|
117
|
-
for (const chunk of chunks) {
|
|
118
|
-
bytes.set(chunk, offset);
|
|
119
|
-
offset += chunk.byteLength;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
const buffer = new Uint8Array(await response.arrayBuffer());
|
|
124
|
-
if (buffer.byteLength > QUOTA_PROVIDER_MAX_BODY_BYTES) {
|
|
125
|
-
throw new Error("Response exceeded 262144 bytes");
|
|
126
|
-
}
|
|
127
|
-
bytes = buffer;
|
|
128
98
|
}
|
|
129
99
|
try {
|
|
130
|
-
return JSON.parse(
|
|
100
|
+
return { ok: true, body: JSON.parse(text) };
|
|
131
101
|
}
|
|
132
102
|
catch {
|
|
133
|
-
|
|
103
|
+
return { ok: false, error: "Invalid JSON response" };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/** A quota-v1 row keyed by its name. */
|
|
107
|
+
function parseQuotaV1Row(raw) {
|
|
108
|
+
if (!isRecord(raw) || !hasOnlyKeys(raw, QUOTA_V1_ROW_KEYS))
|
|
109
|
+
return null;
|
|
110
|
+
const name = boundedDisplayText(raw.name, 80);
|
|
111
|
+
const resultType = typeof raw.resultType === "string" &&
|
|
112
|
+
CUSTOM_RESULT_TYPES.has(raw.resultType)
|
|
113
|
+
? raw.resultType
|
|
114
|
+
: null;
|
|
115
|
+
// Optional fields are undefined when absent and null when present but invalid.
|
|
116
|
+
const label = raw.label === undefined ? undefined : boundedDisplayText(raw.label, 80);
|
|
117
|
+
const right = raw.right === undefined ? undefined : boundedDisplayText(raw.right, 160);
|
|
118
|
+
const resetTimeIso = raw.resetTimeIso === undefined
|
|
119
|
+
? undefined
|
|
120
|
+
: isIsoTime(raw.resetTimeIso)
|
|
121
|
+
? raw.resetTimeIso
|
|
122
|
+
: null;
|
|
123
|
+
const observedAtIso = raw.observedAtIso === undefined
|
|
124
|
+
? undefined
|
|
125
|
+
: isIsoTime(raw.observedAtIso)
|
|
126
|
+
? raw.observedAtIso
|
|
127
|
+
: null;
|
|
128
|
+
if (!name ||
|
|
129
|
+
!resultType ||
|
|
130
|
+
label === null ||
|
|
131
|
+
right === null ||
|
|
132
|
+
resetTimeIso === null ||
|
|
133
|
+
observedAtIso === null) {
|
|
134
|
+
return null;
|
|
134
135
|
}
|
|
136
|
+
const row = (value) => customRow({
|
|
137
|
+
key: customRowKey(name),
|
|
138
|
+
name,
|
|
139
|
+
label,
|
|
140
|
+
resultType,
|
|
141
|
+
method: "remote_api",
|
|
142
|
+
value,
|
|
143
|
+
resetsAt: resetTimeIso,
|
|
144
|
+
});
|
|
145
|
+
if (raw.kind === "percent" &&
|
|
146
|
+
typeof raw.percentRemaining === "number" &&
|
|
147
|
+
Number.isFinite(raw.percentRemaining) &&
|
|
148
|
+
raw.percentRemaining <= 100 &&
|
|
149
|
+
PERCENT_RESULT_TYPES.has(resultType) &&
|
|
150
|
+
raw.value === undefined) {
|
|
151
|
+
return row({ percentRemaining: raw.percentRemaining });
|
|
152
|
+
}
|
|
153
|
+
const value = boundedDisplayText(raw.value, 160);
|
|
154
|
+
if (raw.kind === "value" && value !== null && raw.percentRemaining === undefined) {
|
|
155
|
+
return row({ text: value });
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
135
158
|
}
|
|
136
|
-
function parseQuotaV1(
|
|
159
|
+
function parseQuotaV1(body) {
|
|
160
|
+
const invalid = { success: false, error: "Invalid quota-v1 response" };
|
|
137
161
|
if (!isRecord(body) ||
|
|
138
162
|
!hasOnlyKeys(body, ["version", "entries"]) ||
|
|
139
163
|
body.version !== "quota-v1" ||
|
|
140
|
-
!Array.isArray(body.entries)
|
|
141
|
-
|
|
164
|
+
!Array.isArray(body.entries) ||
|
|
165
|
+
body.entries.length < 1 ||
|
|
166
|
+
body.entries.length > MAX_REMOTE_ROWS) {
|
|
167
|
+
return invalid;
|
|
142
168
|
}
|
|
143
|
-
|
|
144
|
-
return { success: false, error: "Invalid quota-v1 response" };
|
|
145
|
-
}
|
|
146
|
-
const entries = [];
|
|
169
|
+
const rows = [];
|
|
147
170
|
for (const raw of body.entries) {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
"resultType",
|
|
153
|
-
"percentRemaining",
|
|
154
|
-
"value",
|
|
155
|
-
"label",
|
|
156
|
-
"right",
|
|
157
|
-
"resetTimeIso",
|
|
158
|
-
"observedAtIso",
|
|
159
|
-
])) {
|
|
160
|
-
return { success: false, error: "Invalid quota-v1 response" };
|
|
161
|
-
}
|
|
162
|
-
const name = boundedDisplayText(raw.name, 80);
|
|
163
|
-
const resultType = typeof raw.resultType === "string" && RESULT_TYPES.has(raw.resultType)
|
|
164
|
-
? raw.resultType
|
|
165
|
-
: null;
|
|
166
|
-
const label = raw.label === undefined ? undefined : boundedDisplayText(raw.label, 80);
|
|
167
|
-
const right = raw.right === undefined ? undefined : boundedDisplayText(raw.right, 160);
|
|
168
|
-
const resetTimeIso = raw.resetTimeIso === undefined
|
|
169
|
-
? undefined
|
|
170
|
-
: isIsoTimestamp(raw.resetTimeIso)
|
|
171
|
-
? raw.resetTimeIso
|
|
172
|
-
: null;
|
|
173
|
-
const observedAtIso = raw.observedAtIso === undefined
|
|
174
|
-
? undefined
|
|
175
|
-
: isIsoTimestamp(raw.observedAtIso)
|
|
176
|
-
? raw.observedAtIso
|
|
177
|
-
: null;
|
|
178
|
-
if (!name ||
|
|
179
|
-
!resultType ||
|
|
180
|
-
(raw.label !== undefined && label === null) ||
|
|
181
|
-
(raw.right !== undefined && right === null) ||
|
|
182
|
-
resetTimeIso === null ||
|
|
183
|
-
observedAtIso === null) {
|
|
184
|
-
return { success: false, error: "Invalid quota-v1 response" };
|
|
185
|
-
}
|
|
186
|
-
const common = {
|
|
187
|
-
accounting: accountingMetadata(resultType, observedAtIso),
|
|
188
|
-
name: `${source.label} ${name}`,
|
|
189
|
-
group: source.label,
|
|
190
|
-
...(label ? { label } : {}),
|
|
191
|
-
...(right ? { right } : {}),
|
|
192
|
-
...(resetTimeIso ? { resetTimeIso } : {}),
|
|
193
|
-
};
|
|
194
|
-
if (raw.kind === "percent" &&
|
|
195
|
-
typeof raw.percentRemaining === "number" &&
|
|
196
|
-
Number.isFinite(raw.percentRemaining) &&
|
|
197
|
-
raw.percentRemaining <= 100 &&
|
|
198
|
-
["quota", "rate_limit", "budget"].includes(resultType) &&
|
|
199
|
-
raw.value === undefined) {
|
|
200
|
-
entries.push({ ...common, kind: "percent", percentRemaining: raw.percentRemaining });
|
|
201
|
-
continue;
|
|
202
|
-
}
|
|
203
|
-
const value = boundedDisplayText(raw.value, 160);
|
|
204
|
-
if (raw.kind === "value" && value !== null && raw.percentRemaining === undefined) {
|
|
205
|
-
entries.push({ ...common, kind: "value", value });
|
|
206
|
-
continue;
|
|
207
|
-
}
|
|
208
|
-
return { success: false, error: "Invalid quota-v1 response" };
|
|
171
|
+
const row = parseQuotaV1Row(raw);
|
|
172
|
+
if (!row)
|
|
173
|
+
return invalid;
|
|
174
|
+
rows.push(row);
|
|
209
175
|
}
|
|
210
|
-
return { success: true,
|
|
176
|
+
return { success: true, rows };
|
|
211
177
|
}
|
|
212
|
-
function
|
|
178
|
+
function exceedsJsonDepth(value, maxDepth) {
|
|
213
179
|
if (!value || typeof value !== "object")
|
|
214
|
-
return
|
|
180
|
+
return false;
|
|
215
181
|
const stack = [{ value, depth: 1 }];
|
|
216
182
|
while (stack.length > 0) {
|
|
217
183
|
const current = stack.pop();
|
|
218
|
-
if (current.depth >
|
|
219
|
-
return
|
|
184
|
+
if (current.depth > maxDepth)
|
|
185
|
+
return true;
|
|
220
186
|
const children = Array.isArray(current.value) ? current.value : Object.values(current.value);
|
|
221
187
|
for (const child of children) {
|
|
222
188
|
if (child && typeof child === "object") {
|
|
@@ -224,270 +190,169 @@ function isJsonV1ResponseDepthValid(value) {
|
|
|
224
190
|
}
|
|
225
191
|
}
|
|
226
192
|
}
|
|
227
|
-
return
|
|
193
|
+
return false;
|
|
228
194
|
}
|
|
229
195
|
function resolveJsonV1Path(root, path) {
|
|
230
196
|
let current = root;
|
|
231
|
-
for (
|
|
197
|
+
for (const segment of path) {
|
|
232
198
|
if (!isRecord(current))
|
|
233
|
-
return {
|
|
234
|
-
const segment = path[index];
|
|
199
|
+
return { ok: false, issue: "had wrong type" };
|
|
235
200
|
if (!Object.hasOwn(current, segment))
|
|
236
|
-
return {
|
|
201
|
+
return { ok: false, issue: "was missing" };
|
|
237
202
|
current = current[segment];
|
|
238
203
|
if (current === null)
|
|
239
|
-
return {
|
|
240
|
-
if (index < path.length - 1 && !isRecord(current))
|
|
241
|
-
return { state: "wrong-type" };
|
|
204
|
+
return { ok: false, issue: "was null" };
|
|
242
205
|
}
|
|
243
|
-
return {
|
|
206
|
+
return { ok: true, value: current };
|
|
244
207
|
}
|
|
245
|
-
function
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
return resolveJsonV1Path(row, source.path);
|
|
250
|
-
}
|
|
251
|
-
function jsonV1ResolutionIssue(resolution) {
|
|
252
|
-
switch (resolution.state) {
|
|
253
|
-
case "missing":
|
|
254
|
-
return "was missing";
|
|
255
|
-
case "null":
|
|
256
|
-
return "was null";
|
|
257
|
-
case "wrong-type":
|
|
258
|
-
return "had wrong type";
|
|
259
|
-
}
|
|
208
|
+
function resolveJsonV1Source(row, source) {
|
|
209
|
+
return "literal" in source
|
|
210
|
+
? { ok: true, value: source.literal }
|
|
211
|
+
: resolveJsonV1Path(row, source.path);
|
|
260
212
|
}
|
|
261
213
|
function resolveJsonV1Number(row, source) {
|
|
262
|
-
const
|
|
263
|
-
if (
|
|
264
|
-
return
|
|
265
|
-
}
|
|
214
|
+
const resolved = resolveJsonV1Source(row, source);
|
|
215
|
+
if (!resolved.ok)
|
|
216
|
+
return resolved;
|
|
266
217
|
// Some APIs write numbers as text (`"95.50"`); only a plain decimal is read as a number.
|
|
267
|
-
const raw = typeof
|
|
268
|
-
? Number(
|
|
269
|
-
:
|
|
218
|
+
const raw = typeof resolved.value === "string" && JSON_V1_DECIMAL_TEXT_RE.test(resolved.value.trim())
|
|
219
|
+
? Number(resolved.value.trim())
|
|
220
|
+
: resolved.value;
|
|
270
221
|
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
271
222
|
return { ok: false, issue: "had wrong type" };
|
|
272
223
|
}
|
|
273
224
|
if (Math.abs(raw) > JSON_V1_MAX_NUMBER_MAGNITUDE) {
|
|
274
225
|
return { ok: false, issue: "exceeded the numeric magnitude limit" };
|
|
275
226
|
}
|
|
276
|
-
const
|
|
277
|
-
return
|
|
278
|
-
? { ok: true, value }
|
|
279
|
-
: { ok: false, issue: "did not resolve to a finite number" };
|
|
227
|
+
const divideBy = "path" in source ? source.divideBy : undefined;
|
|
228
|
+
return { ok: true, value: divideBy === undefined ? raw : raw / divideBy };
|
|
280
229
|
}
|
|
281
230
|
function resolveJsonV1Text(row, source) {
|
|
282
|
-
const
|
|
283
|
-
if (
|
|
284
|
-
return
|
|
285
|
-
|
|
286
|
-
if (typeof resolution.value !== "string") {
|
|
231
|
+
const resolved = resolveJsonV1Source(row, source);
|
|
232
|
+
if (!resolved.ok)
|
|
233
|
+
return resolved;
|
|
234
|
+
if (typeof resolved.value !== "string")
|
|
287
235
|
return { ok: false, issue: "had wrong type" };
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
? { ok: true, value: normalized }
|
|
236
|
+
const text = boundedDisplayText(resolved.value, JSON_V1_MAX_DISPLAY_CODE_POINTS);
|
|
237
|
+
return text
|
|
238
|
+
? { ok: true, value: text }
|
|
292
239
|
: { ok: false, issue: "did not resolve to bounded display text" };
|
|
293
240
|
}
|
|
294
|
-
function
|
|
295
|
-
const
|
|
296
|
-
if (
|
|
297
|
-
return
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
? { ok: true, value: normalized }
|
|
241
|
+
function resolveJsonV1Timestamp(row, source) {
|
|
242
|
+
const resolved = resolveJsonV1Source(row, source);
|
|
243
|
+
if (!resolved.ok)
|
|
244
|
+
return resolved;
|
|
245
|
+
const timestamp = normalizeJsonV1Timestamp(resolved.value, source.encoding);
|
|
246
|
+
return timestamp
|
|
247
|
+
? { ok: true, value: timestamp }
|
|
302
248
|
: { ok: false, issue: "did not resolve to a valid timestamp" };
|
|
303
249
|
}
|
|
304
250
|
function jsonV1CandidateError(mappingIndex, field, issue, rowIndex) {
|
|
305
251
|
return `adapter.mappings[${mappingIndex}].${field} ${issue} at row ${rowIndex}`;
|
|
306
252
|
}
|
|
307
253
|
function formatJsonV1Value(value, mapping) {
|
|
308
|
-
const text = String(value);
|
|
309
|
-
if (!mapping.unit)
|
|
310
|
-
return text;
|
|
311
|
-
return mapping.unitPosition === "prefix" ? `${mapping.unit}${text}` : `${text} ${mapping.unit}`;
|
|
312
|
-
}
|
|
313
|
-
function formatJsonV1Pair(left, right, mapping) {
|
|
314
|
-
const pair = `${String(left)}/${String(right)}`;
|
|
315
254
|
if (!mapping.unit)
|
|
316
|
-
return
|
|
317
|
-
return mapping.unitPosition === "prefix"
|
|
318
|
-
? `${mapping.unit}${String(left)}/${mapping.unit}${String(right)}`
|
|
319
|
-
: `${pair} ${mapping.unit}`;
|
|
255
|
+
return `${value}`;
|
|
256
|
+
return mapping.unitPosition === "prefix" ? `${mapping.unit}${value}` : `${value} ${mapping.unit}`;
|
|
320
257
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
return "produced a non-finite percentage";
|
|
324
|
-
if (Math.abs(value) > JSON_V1_MAX_NUMBER_MAGNITUDE) {
|
|
325
|
-
return "produced a percentage beyond the numeric magnitude limit";
|
|
326
|
-
}
|
|
327
|
-
return null;
|
|
328
|
-
}
|
|
329
|
-
function mapJsonV1Candidate(source, row, rowIndex, mapping, mappingIndex) {
|
|
258
|
+
/** One mapping applied to one reply row: a row keyed by the mapping's name, or why not. */
|
|
259
|
+
function mapJsonV1Candidate(row, rowIndex, mapping, mappingIndex) {
|
|
330
260
|
const fail = (field, issue) => ({
|
|
331
261
|
error: jsonV1CandidateError(mappingIndex, field, issue, rowIndex),
|
|
332
262
|
});
|
|
333
263
|
let resetTimeIso;
|
|
334
264
|
if (mapping.resetTime) {
|
|
335
|
-
const resolved =
|
|
265
|
+
const resolved = resolveJsonV1Timestamp(row, mapping.resetTime);
|
|
336
266
|
if (!resolved.ok)
|
|
337
267
|
return fail("resetTime", resolved.issue);
|
|
338
268
|
resetTimeIso = resolved.value;
|
|
339
269
|
}
|
|
340
|
-
|
|
270
|
+
// The observed time is checked but not shown.
|
|
341
271
|
if (mapping.observedTime) {
|
|
342
|
-
const resolved =
|
|
272
|
+
const resolved = resolveJsonV1Timestamp(row, mapping.observedTime);
|
|
343
273
|
if (!resolved.ok)
|
|
344
274
|
return fail("observedTime", resolved.issue);
|
|
345
|
-
observedAtIso = resolved.value;
|
|
346
275
|
}
|
|
347
|
-
const
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
276
|
+
const mapped = (value) => ({
|
|
277
|
+
row: customRow({
|
|
278
|
+
key: customRowKey(mapping.name),
|
|
279
|
+
name: mapping.name,
|
|
280
|
+
label: mapping.label,
|
|
281
|
+
resultType: mapping.resultType,
|
|
282
|
+
method: "remote_api",
|
|
283
|
+
value,
|
|
284
|
+
resetsAt: resetTimeIso,
|
|
285
|
+
}),
|
|
286
|
+
});
|
|
287
|
+
// Shared by used-limit, remaining-limit, spend-budget and remaining-budget:
|
|
288
|
+
// an amount (used, spent, or remaining) out of a positive total.
|
|
289
|
+
const share = (amountKey, amountSource, totalKey, totalSource) => {
|
|
290
|
+
const amountField = `metric.${amountKey}`;
|
|
291
|
+
const totalField = `metric.${totalKey}`;
|
|
292
|
+
const amountIsRemaining = amountKey === "remaining";
|
|
293
|
+
const amount = resolveJsonV1Number(row, amountSource);
|
|
294
|
+
if (!amount.ok)
|
|
295
|
+
return fail(amountField, amount.issue);
|
|
296
|
+
const total = resolveJsonV1Number(row, totalSource);
|
|
297
|
+
if (!total.ok)
|
|
298
|
+
return fail(totalField, total.issue);
|
|
299
|
+
if (!amountIsRemaining && amount.value < 0)
|
|
300
|
+
return fail(amountField, "must be non-negative");
|
|
301
|
+
if (total.value <= 0)
|
|
302
|
+
return fail(totalField, "must be greater than zero");
|
|
303
|
+
if (amountIsRemaining && amount.value > total.value) {
|
|
304
|
+
return fail(amountField, `must not exceed ${totalKey}`);
|
|
305
|
+
}
|
|
306
|
+
const percentRemaining = amountIsRemaining
|
|
307
|
+
? (amount.value / total.value) * 100
|
|
308
|
+
: ((total.value - amount.value) / total.value) * 100;
|
|
309
|
+
// Finite operands can still overflow, for example a tiny literal total.
|
|
310
|
+
if (!Number.isFinite(percentRemaining)) {
|
|
311
|
+
return fail(totalField, "produced a non-finite percentage");
|
|
312
|
+
}
|
|
313
|
+
if (Math.abs(percentRemaining) > JSON_V1_MAX_NUMBER_MAGNITUDE) {
|
|
314
|
+
return fail(totalField, "produced a percentage beyond the numeric magnitude limit");
|
|
315
|
+
}
|
|
316
|
+
return mapped({ percentRemaining });
|
|
353
317
|
};
|
|
354
|
-
|
|
318
|
+
const { metric } = mapping;
|
|
319
|
+
switch (metric.type) {
|
|
355
320
|
case "percentage": {
|
|
356
|
-
const percentage = resolveJsonV1Number(row,
|
|
321
|
+
const percentage = resolveJsonV1Number(row, metric.percentage);
|
|
357
322
|
if (!percentage.ok)
|
|
358
323
|
return fail("metric.percentage", percentage.issue);
|
|
359
|
-
if (
|
|
324
|
+
if (metric.meaning === "remaining" && percentage.value > 100) {
|
|
360
325
|
return fail("metric.percentage", "must not exceed 100 for remaining meaning");
|
|
361
326
|
}
|
|
362
|
-
if (
|
|
327
|
+
if (metric.meaning === "used" && percentage.value < 0) {
|
|
363
328
|
return fail("metric.percentage", "must be non-negative for used meaning");
|
|
364
329
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
...common,
|
|
368
|
-
kind: "percent",
|
|
369
|
-
percentRemaining: mapping.metric.meaning === "remaining" ? percentage.value : 100 - percentage.value,
|
|
370
|
-
},
|
|
371
|
-
};
|
|
372
|
-
}
|
|
373
|
-
case "used-limit": {
|
|
374
|
-
const used = resolveJsonV1Number(row, mapping.metric.used);
|
|
375
|
-
if (!used.ok)
|
|
376
|
-
return fail("metric.used", used.issue);
|
|
377
|
-
const limit = resolveJsonV1Number(row, mapping.metric.limit);
|
|
378
|
-
if (!limit.ok)
|
|
379
|
-
return fail("metric.limit", limit.issue);
|
|
380
|
-
if (used.value < 0)
|
|
381
|
-
return fail("metric.used", "must be non-negative");
|
|
382
|
-
if (limit.value <= 0)
|
|
383
|
-
return fail("metric.limit", "must be greater than zero");
|
|
384
|
-
const percentRemaining = ((limit.value - used.value) / limit.value) * 100;
|
|
385
|
-
const percentageIssue = jsonV1DerivedPercentageIssue(percentRemaining);
|
|
386
|
-
if (percentageIssue)
|
|
387
|
-
return fail("metric.limit", percentageIssue);
|
|
388
|
-
return {
|
|
389
|
-
entry: {
|
|
390
|
-
...common,
|
|
391
|
-
kind: "percent",
|
|
392
|
-
percentRemaining,
|
|
393
|
-
right: formatJsonV1Pair(used.value, limit.value, mapping),
|
|
394
|
-
},
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
case "remaining-limit": {
|
|
398
|
-
const remaining = resolveJsonV1Number(row, mapping.metric.remaining);
|
|
399
|
-
if (!remaining.ok)
|
|
400
|
-
return fail("metric.remaining", remaining.issue);
|
|
401
|
-
const limit = resolveJsonV1Number(row, mapping.metric.limit);
|
|
402
|
-
if (!limit.ok)
|
|
403
|
-
return fail("metric.limit", limit.issue);
|
|
404
|
-
if (limit.value <= 0)
|
|
405
|
-
return fail("metric.limit", "must be greater than zero");
|
|
406
|
-
if (remaining.value > limit.value) {
|
|
407
|
-
return fail("metric.remaining", "must not exceed limit");
|
|
408
|
-
}
|
|
409
|
-
const percentRemaining = (remaining.value / limit.value) * 100;
|
|
410
|
-
const percentageIssue = jsonV1DerivedPercentageIssue(percentRemaining);
|
|
411
|
-
if (percentageIssue)
|
|
412
|
-
return fail("metric.limit", percentageIssue);
|
|
413
|
-
return {
|
|
414
|
-
entry: {
|
|
415
|
-
...common,
|
|
416
|
-
kind: "percent",
|
|
417
|
-
percentRemaining,
|
|
418
|
-
right: formatJsonV1Pair(remaining.value, limit.value, mapping),
|
|
419
|
-
},
|
|
420
|
-
};
|
|
421
|
-
}
|
|
422
|
-
case "spend-budget": {
|
|
423
|
-
const spend = resolveJsonV1Number(row, mapping.metric.spend);
|
|
424
|
-
if (!spend.ok)
|
|
425
|
-
return fail("metric.spend", spend.issue);
|
|
426
|
-
const budget = resolveJsonV1Number(row, mapping.metric.budget);
|
|
427
|
-
if (!budget.ok)
|
|
428
|
-
return fail("metric.budget", budget.issue);
|
|
429
|
-
if (spend.value < 0)
|
|
430
|
-
return fail("metric.spend", "must be non-negative");
|
|
431
|
-
if (budget.value <= 0)
|
|
432
|
-
return fail("metric.budget", "must be greater than zero");
|
|
433
|
-
const percentRemaining = ((budget.value - spend.value) / budget.value) * 100;
|
|
434
|
-
const percentageIssue = jsonV1DerivedPercentageIssue(percentRemaining);
|
|
435
|
-
if (percentageIssue)
|
|
436
|
-
return fail("metric.budget", percentageIssue);
|
|
437
|
-
return {
|
|
438
|
-
entry: {
|
|
439
|
-
...common,
|
|
440
|
-
kind: "percent",
|
|
441
|
-
percentRemaining,
|
|
442
|
-
right: formatJsonV1Pair(spend.value, budget.value, mapping),
|
|
443
|
-
},
|
|
444
|
-
};
|
|
445
|
-
}
|
|
446
|
-
case "remaining-budget": {
|
|
447
|
-
const remaining = resolveJsonV1Number(row, mapping.metric.remaining);
|
|
448
|
-
if (!remaining.ok)
|
|
449
|
-
return fail("metric.remaining", remaining.issue);
|
|
450
|
-
const budget = resolveJsonV1Number(row, mapping.metric.budget);
|
|
451
|
-
if (!budget.ok)
|
|
452
|
-
return fail("metric.budget", budget.issue);
|
|
453
|
-
if (budget.value <= 0)
|
|
454
|
-
return fail("metric.budget", "must be greater than zero");
|
|
455
|
-
if (remaining.value > budget.value) {
|
|
456
|
-
return fail("metric.remaining", "must not exceed budget");
|
|
457
|
-
}
|
|
458
|
-
const percentRemaining = (remaining.value / budget.value) * 100;
|
|
459
|
-
const percentageIssue = jsonV1DerivedPercentageIssue(percentRemaining);
|
|
460
|
-
if (percentageIssue)
|
|
461
|
-
return fail("metric.budget", percentageIssue);
|
|
462
|
-
return {
|
|
463
|
-
entry: {
|
|
464
|
-
...common,
|
|
465
|
-
kind: "percent",
|
|
466
|
-
percentRemaining,
|
|
467
|
-
right: formatJsonV1Pair(remaining.value, budget.value, mapping),
|
|
468
|
-
},
|
|
469
|
-
};
|
|
330
|
+
const percentRemaining = metric.meaning === "remaining" ? percentage.value : 100 - percentage.value;
|
|
331
|
+
return mapped({ percentRemaining });
|
|
470
332
|
}
|
|
333
|
+
case "used-limit":
|
|
334
|
+
return share("used", metric.used, "limit", metric.limit);
|
|
335
|
+
case "remaining-limit":
|
|
336
|
+
return share("remaining", metric.remaining, "limit", metric.limit);
|
|
337
|
+
case "spend-budget":
|
|
338
|
+
return share("spend", metric.spend, "budget", metric.budget);
|
|
339
|
+
case "remaining-budget":
|
|
340
|
+
return share("remaining", metric.remaining, "budget", metric.budget);
|
|
471
341
|
case "value": {
|
|
472
|
-
const value = resolveJsonV1Number(row,
|
|
342
|
+
const value = resolveJsonV1Number(row, metric.value);
|
|
473
343
|
if (!value.ok)
|
|
474
344
|
return fail("metric.value", value.issue);
|
|
475
|
-
|
|
345
|
+
// Remaining and balance values may legitimately be negative (overdrawn).
|
|
346
|
+
const mayBeNegative = metric.valueType === "remaining" || metric.valueType === "balance";
|
|
347
|
+
if (!mayBeNegative && value.value < 0)
|
|
476
348
|
return fail("metric.value", "must be non-negative");
|
|
477
|
-
}
|
|
478
|
-
return {
|
|
479
|
-
entry: {
|
|
480
|
-
...common,
|
|
481
|
-
kind: "value",
|
|
482
|
-
value: formatJsonV1Value(value.value, mapping),
|
|
483
|
-
},
|
|
484
|
-
};
|
|
349
|
+
return mapped({ text: formatJsonV1Value(value.value, mapping) });
|
|
485
350
|
}
|
|
486
351
|
case "status": {
|
|
487
|
-
const value = resolveJsonV1Text(row,
|
|
352
|
+
const value = resolveJsonV1Text(row, metric.value);
|
|
488
353
|
if (!value.ok)
|
|
489
354
|
return fail("metric.value", value.issue);
|
|
490
|
-
return {
|
|
355
|
+
return mapped({ text: value.value });
|
|
491
356
|
}
|
|
492
357
|
}
|
|
493
358
|
}
|
|
@@ -496,7 +361,7 @@ function parseJsonV1(source, body) {
|
|
|
496
361
|
success: false,
|
|
497
362
|
error: `Invalid json-v1 response: ${message}`,
|
|
498
363
|
});
|
|
499
|
-
if (
|
|
364
|
+
if (exceedsJsonDepth(body, JSON_V1_MAX_RESPONSE_DEPTH)) {
|
|
500
365
|
return invalid(`nesting depth exceeded ${JSON_V1_MAX_RESPONSE_DEPTH}`);
|
|
501
366
|
}
|
|
502
367
|
let rows;
|
|
@@ -504,9 +369,8 @@ function parseJsonV1(source, body) {
|
|
|
504
369
|
if (!isRecord(body))
|
|
505
370
|
return invalid("adapter.rowsPath requires an object root");
|
|
506
371
|
const resolved = resolveJsonV1Path(body, source.adapter.rowsPath);
|
|
507
|
-
if (resolved.
|
|
508
|
-
return invalid(`adapter.rowsPath ${
|
|
509
|
-
}
|
|
372
|
+
if (!resolved.ok)
|
|
373
|
+
return invalid(`adapter.rowsPath ${resolved.issue}`);
|
|
510
374
|
if (!Array.isArray(resolved.value)) {
|
|
511
375
|
return invalid("adapter.rowsPath did not resolve to an array");
|
|
512
376
|
}
|
|
@@ -521,13 +385,14 @@ function parseJsonV1(source, body) {
|
|
|
521
385
|
else {
|
|
522
386
|
return invalid("expected an object or array root");
|
|
523
387
|
}
|
|
524
|
-
if (rows.length < 1 || rows.length >
|
|
525
|
-
return invalid(`selected rows must contain 1-${
|
|
388
|
+
if (rows.length < 1 || rows.length > MAX_REMOTE_ROWS) {
|
|
389
|
+
return invalid(`selected rows must contain 1-${MAX_REMOTE_ROWS} elements`);
|
|
526
390
|
}
|
|
527
|
-
|
|
391
|
+
const { mappings } = source.adapter;
|
|
392
|
+
if (rows.length * mappings.length > JSON_V1_MAX_CANDIDATES) {
|
|
528
393
|
return invalid(`candidate count exceeded ${JSON_V1_MAX_CANDIDATES}`);
|
|
529
394
|
}
|
|
530
|
-
const
|
|
395
|
+
const mappedRows = [];
|
|
531
396
|
const rowErrors = [];
|
|
532
397
|
let errorCount = 0;
|
|
533
398
|
const recordError = (error) => {
|
|
@@ -535,25 +400,24 @@ function parseJsonV1(source, body) {
|
|
|
535
400
|
if (rowErrors.length < JSON_V1_MAX_DETAILED_ERRORS)
|
|
536
401
|
rowErrors.push(error);
|
|
537
402
|
};
|
|
538
|
-
for (
|
|
539
|
-
const
|
|
540
|
-
for (let mappingIndex = 0; mappingIndex < source.adapter.mappings.length; mappingIndex += 1) {
|
|
403
|
+
for (const [rowIndex, row] of rows.entries()) {
|
|
404
|
+
for (const [mappingIndex, mapping] of mappings.entries()) {
|
|
541
405
|
if (!isRecord(row)) {
|
|
542
406
|
recordError(jsonV1CandidateError(mappingIndex, "metric", "requires an object row", rowIndex));
|
|
543
407
|
continue;
|
|
544
408
|
}
|
|
545
|
-
const mapped = mapJsonV1Candidate(
|
|
409
|
+
const mapped = mapJsonV1Candidate(row, rowIndex, mapping, mappingIndex);
|
|
546
410
|
if ("error" in mapped) {
|
|
547
411
|
recordError(mapped.error);
|
|
548
412
|
continue;
|
|
549
413
|
}
|
|
550
|
-
|
|
551
|
-
if (
|
|
414
|
+
mappedRows.push(mapped.row);
|
|
415
|
+
if (mappedRows.length > JSON_V1_MAX_ENTRIES) {
|
|
552
416
|
return invalid(`more than ${JSON_V1_MAX_ENTRIES} entries were produced`);
|
|
553
417
|
}
|
|
554
418
|
}
|
|
555
419
|
}
|
|
556
|
-
if (
|
|
420
|
+
if (mappedRows.length === 0) {
|
|
557
421
|
return invalid(rowErrors[0] ?? "no mappings produced entries");
|
|
558
422
|
}
|
|
559
423
|
if (errorCount > rowErrors.length) {
|
|
@@ -561,70 +425,71 @@ function parseJsonV1(source, body) {
|
|
|
561
425
|
}
|
|
562
426
|
return {
|
|
563
427
|
success: true,
|
|
564
|
-
|
|
428
|
+
rows: mappedRows,
|
|
565
429
|
...(rowErrors.length > 0 ? { rowErrors } : {}),
|
|
566
430
|
};
|
|
567
431
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
(remaining
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
432
|
+
/**
|
|
433
|
+
* The key's budget (percent left), or its spend when the key has no limit: this month's
|
|
434
|
+
* (`usage_monthly`, the current UTC month) when the reply has it, else all time.
|
|
435
|
+
*/
|
|
436
|
+
function parseOpenRouterKeyV1(body) {
|
|
437
|
+
const invalid = { success: false, error: "Invalid openrouter-key-v1 response" };
|
|
438
|
+
if (!isRecord(body) || !isRecord(body.data))
|
|
439
|
+
return invalid;
|
|
440
|
+
const { usage, usage_monthly: usageMonthly, limit, limit_remaining: remaining } = body.data;
|
|
441
|
+
const isValidUsage = typeof usage === "number" && Number.isFinite(usage) && usage >= 0;
|
|
442
|
+
const isValidLimit = limit === null ||
|
|
443
|
+
limit === undefined ||
|
|
444
|
+
(typeof limit === "number" && Number.isFinite(limit) && limit >= 0);
|
|
445
|
+
// A null remaining is valid only for a key without a limit (free tier).
|
|
446
|
+
const isValidRemaining = remaining === undefined ||
|
|
447
|
+
(remaining === null
|
|
448
|
+
? limit === null
|
|
449
|
+
: typeof remaining === "number" && Number.isFinite(remaining));
|
|
450
|
+
if (!isValidUsage || !isValidLimit || !isValidRemaining)
|
|
451
|
+
return invalid;
|
|
588
452
|
if (typeof limit === "number" && limit > 0) {
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
const percentRemaining = (remainingValue / limit) * 100;
|
|
597
|
-
const usedUsd = typeof remaining === "number" ? limit - remainingValue : usage;
|
|
453
|
+
// `limit_remaining` covers the current limit window, while `usage` is the key's lifetime total.
|
|
454
|
+
const remainingUsd = typeof remaining === "number" ? remaining : limit - usage;
|
|
455
|
+
if (remainingUsd > limit)
|
|
456
|
+
return invalid;
|
|
457
|
+
const percentRemaining = (remainingUsd / limit) * 100;
|
|
598
458
|
return {
|
|
599
459
|
success: true,
|
|
600
|
-
|
|
601
|
-
{
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
},
|
|
460
|
+
rows: [
|
|
461
|
+
customRow({
|
|
462
|
+
key: "budget",
|
|
463
|
+
name: "budget",
|
|
464
|
+
label: "Budget",
|
|
465
|
+
resultType: "budget",
|
|
466
|
+
method: "remote_api",
|
|
467
|
+
value: { percentRemaining },
|
|
468
|
+
}),
|
|
610
469
|
],
|
|
611
470
|
};
|
|
612
471
|
}
|
|
472
|
+
// A reply without a usable monthly figure (an older or compatible endpoint) keeps the
|
|
473
|
+
// all-time spend.
|
|
474
|
+
const hasMonthly = typeof usageMonthly === "number" && Number.isFinite(usageMonthly) && usageMonthly >= 0;
|
|
613
475
|
return {
|
|
614
476
|
success: true,
|
|
615
|
-
|
|
616
|
-
{
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
value:
|
|
623
|
-
},
|
|
477
|
+
rows: [
|
|
478
|
+
customRow({
|
|
479
|
+
key: "spend",
|
|
480
|
+
name: "spend",
|
|
481
|
+
label: hasMonthly ? "This month" : "Spend",
|
|
482
|
+
resultType: "spend",
|
|
483
|
+
method: "remote_api",
|
|
484
|
+
value: { text: fmtUsdAmount(hasMonthly ? usageMonthly : usage) },
|
|
485
|
+
}),
|
|
624
486
|
],
|
|
625
487
|
};
|
|
626
488
|
}
|
|
627
489
|
export async function fetchRemoteQuotaProvider(source, apiKey, requestTimeoutMs) {
|
|
490
|
+
// A switched-off provider is never sent a request or its key, whoever asks.
|
|
491
|
+
if (source.enabled === false)
|
|
492
|
+
return { success: false, error: "Provider is switched off" };
|
|
628
493
|
const timeoutMs = requestTimeoutMs ?? REQUEST_TIMEOUT_MS;
|
|
629
494
|
const controller = new AbortController();
|
|
630
495
|
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
@@ -644,14 +509,16 @@ export async function fetchRemoteQuotaProvider(source, apiKey, requestTimeoutMs)
|
|
|
644
509
|
if (!response.ok) {
|
|
645
510
|
return { success: false, error: `HTTP ${response.status}` };
|
|
646
511
|
}
|
|
647
|
-
const
|
|
512
|
+
const read = await readBoundedJson(response);
|
|
513
|
+
if (!read.ok)
|
|
514
|
+
return { success: false, error: read.error };
|
|
648
515
|
switch (source.format) {
|
|
649
516
|
case "quota-v1":
|
|
650
|
-
return parseQuotaV1(
|
|
517
|
+
return parseQuotaV1(read.body);
|
|
651
518
|
case "openrouter-key-v1":
|
|
652
|
-
return parseOpenRouterKeyV1(
|
|
519
|
+
return parseOpenRouterKeyV1(read.body);
|
|
653
520
|
case "json-v1":
|
|
654
|
-
return parseJsonV1(source, body);
|
|
521
|
+
return parseJsonV1(source, read.body);
|
|
655
522
|
}
|
|
656
523
|
}
|
|
657
524
|
catch (error) {
|
|
@@ -661,14 +528,7 @@ export async function fetchRemoteQuotaProvider(source, apiKey, requestTimeoutMs)
|
|
|
661
528
|
error: `Request timeout after ${Math.round(timeoutMs / 1000)}s`,
|
|
662
529
|
};
|
|
663
530
|
}
|
|
664
|
-
|
|
665
|
-
[
|
|
666
|
-
"Response exceeded 262144 bytes",
|
|
667
|
-
"Expected a JSON response",
|
|
668
|
-
"Invalid JSON response",
|
|
669
|
-
].includes(error.message)) {
|
|
670
|
-
return { success: false, error: error.message };
|
|
671
|
-
}
|
|
531
|
+
// Never echo thrown text: it can contain the endpoint or response data.
|
|
672
532
|
return { success: false, error: "Failed to read accounting data" };
|
|
673
533
|
}
|
|
674
534
|
finally {
|