free-coding-models 0.5.89 → 0.5.90
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 +4 -4
- package/changelog/v0.5.90.md +12 -0
- package/package.json +2 -2
- package/sources.js +5 -2
- package/src/core/benchmark.js +9 -0
- package/src/core/cloudflare-account.js +311 -0
- package/src/core/endpoint-installer.js +8 -4
- package/src/core/opencode.js +9 -6
- package/src/core/ping.js +52 -16
- package/src/core/provider-key-tester.js +10 -3
- package/src/core/provider-metadata.js +1 -1
- package/src/core/router-daemon.js +9 -1
- package/src/tui/overlays.js +9 -3
- package/web/dist/assets/{index-C5hgQLYN.js → index-CCkuXrqE.js} +3 -3
- package/web/dist/index.html +1 -1
- package/web/server.js +23 -1
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* runProviderKeyTest, PROVIDER_AUTH_ENDPOINTS
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
-
import { ping } from './ping.js'
|
|
30
|
+
import { ping, getProviderSessionHeaders, resolveCloudflareUrl } from './ping.js'
|
|
31
31
|
import { sleep } from './shared-helpers.js'
|
|
32
32
|
|
|
33
33
|
// ─── Constants ────────────────────────────────────────────────────────────────
|
|
@@ -295,12 +295,19 @@ export async function runProviderKeyTest(apiKey, providerKey, source, options =
|
|
|
295
295
|
|
|
296
296
|
// 📖 Slow path: ping-based verification (providers without auth endpoint or timeouts).
|
|
297
297
|
const discoveredModelIds = []
|
|
298
|
-
|
|
298
|
+
// 📖 Cloudflare's models URL is account-scoped (issue #181): resolve the
|
|
299
|
+
// 📖 {$CLOUDFLARE_ACCOUNT_ID} placeholder so discovery reaches the real API
|
|
300
|
+
// 📖 instead of 404ing on the raw catalog URL and silently falling back.
|
|
301
|
+
const modelsUrl = providerKey === 'cloudflare'
|
|
302
|
+
? resolveCloudflareUrl(buildProviderModelsUrl(source?.url) || '')
|
|
303
|
+
: buildProviderModelsUrl(source?.url)
|
|
299
304
|
let discoveryNote = ''
|
|
300
305
|
|
|
301
306
|
if (modelsUrl) {
|
|
302
307
|
try {
|
|
303
|
-
|
|
308
|
+
// 📖 Mandatory per-provider headers (issue #181): OpenCode Zen gates every
|
|
309
|
+
// 📖 request (model discovery included) behind `x-opencode-session`.
|
|
310
|
+
const headers = { Authorization: `Bearer ${apiKey}`, ...getProviderSessionHeaders(providerKey) }
|
|
304
311
|
if (providerKey === 'openrouter') {
|
|
305
312
|
headers['HTTP-Referer'] = 'https://github.com/vava-nessa/free-coding-models'
|
|
306
313
|
headers['X-Title'] = 'free-coding-models'
|
|
@@ -228,7 +228,7 @@ export const PROVIDER_METADATA = {
|
|
|
228
228
|
label: 'Cloudflare Workers AI',
|
|
229
229
|
color: chalk.rgb(255, 204, 128),
|
|
230
230
|
signupUrl: 'https://dash.cloudflare.com',
|
|
231
|
-
signupHint: 'Create AI API token
|
|
231
|
+
signupHint: 'Create AI API token (account id auto-discovered; CLOUDFLARE_ACCOUNT_ID optional)',
|
|
232
232
|
rateLimits: 'Free: 10k neurons/day, text-gen 300 RPM',
|
|
233
233
|
},
|
|
234
234
|
perplexity: {
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
normalizeRouterConfig,
|
|
48
48
|
saveConfig,
|
|
49
49
|
} from './config.js'
|
|
50
|
-
import { buildChatCompletionPingBody, ping, resolveCloudflareUrl, shouldUseDisabledThinkingForProvider } from './ping.js'
|
|
50
|
+
import { buildChatCompletionPingBody, ping, resolveCloudflareUrl, shouldUseDisabledThinkingForProvider, getProviderSessionHeaders } from './ping.js'
|
|
51
51
|
import { benchmarkModel, BENCHMARK_TIMEOUT_MS } from './benchmark.js'
|
|
52
52
|
import { loadChangelog } from './changelog-loader.js'
|
|
53
53
|
import { sendUsageTelemetry } from './telemetry.js'
|
|
@@ -689,6 +689,11 @@ export function cloneHeadersForUpstream(reqHeaders, apiKey, providerKey) {
|
|
|
689
689
|
headers['HTTP-Referer'] = 'https://github.com/vava-nessa/free-coding-models'
|
|
690
690
|
headers['X-Title'] = 'free-coding-models'
|
|
691
691
|
}
|
|
692
|
+
// 📖 Mandatory per-provider headers (issue #181): OpenCode Zen rejects every
|
|
693
|
+
// 📖 request without `x-opencode-session` with HTTP 400 MissingSessionID.
|
|
694
|
+
// 📖 This function builds headers for BOTH health probes and real forwarded
|
|
695
|
+
// 📖 traffic, so applying it here covers every upstream call in one place.
|
|
696
|
+
Object.assign(headers, getProviderSessionHeaders(providerKey))
|
|
692
697
|
return headers
|
|
693
698
|
}
|
|
694
699
|
|
|
@@ -4378,6 +4383,9 @@ export function createDefaultProbeFn(apiKeys) {
|
|
|
4378
4383
|
headers['HTTP-Referer'] = 'https://github.com/vava-nessa/free-coding-models'
|
|
4379
4384
|
headers['X-Title'] = 'free-coding-models'
|
|
4380
4385
|
}
|
|
4386
|
+
// 📖 Mandatory per-provider headers (issue #181): OpenCode Zen 400s without
|
|
4387
|
+
// 📖 `x-opencode-session`, so default-set probes must carry it too.
|
|
4388
|
+
Object.assign(headers, getProviderSessionHeaders(provider))
|
|
4381
4389
|
}
|
|
4382
4390
|
const started = Date.now()
|
|
4383
4391
|
try {
|
package/src/tui/overlays.js
CHANGED
|
@@ -25,6 +25,7 @@ import { renderRouterV2Dashboard as renderRouterV2DashboardOverlay } from '../co
|
|
|
25
25
|
import { renderPlayground as renderPlaygroundOverlay } from '../core/playground.js'
|
|
26
26
|
import { themeColors, getThemeStatusLabel, getProviderRgb } from './theme.js'
|
|
27
27
|
import { getProviderBillingNote, getProviderLabelWithBilling } from '../core/provider-metadata.js'
|
|
28
|
+
import { pickAccountIdFromSettings } from '../core/cloudflare-account.js'
|
|
28
29
|
import { detectTerminalCapabilities } from '../core/utils.js'
|
|
29
30
|
import { truncateAnsiWidth, loadChangelogCached } from './render-helpers.js'
|
|
30
31
|
import { COMMAND_PALETTE_MAX_RESULTS } from './command-palette.js'
|
|
@@ -222,9 +223,14 @@ export function createOverlayRenderers(state, deps) {
|
|
|
222
223
|
lines.push(themeColors.dim(` 2) ${selectedMeta.signupHint || 'Generate an API key and paste it with Enter on this row'}`))
|
|
223
224
|
lines.push(themeColors.dim(` 3) Press ${themeColors.hotkey('T')} to test your key. Status: ${setupStatus}`))
|
|
224
225
|
if (selectedProviderKey === 'cloudflare') {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
226
|
+
// 📖 Account id resolution has fallbacks since issue #181: env var,
|
|
227
|
+
// 📖 stored config setting, or zero-setup auto-discovery from the API key.
|
|
228
|
+
const hasEnvAccountId = Boolean((process.env.CLOUDFLARE_ACCOUNT_ID || '').trim())
|
|
229
|
+
const hasStoredAccountId = Boolean(pickAccountIdFromSettings(state.config?.settings))
|
|
230
|
+
const accountIdStatus = (hasEnvAccountId || hasStoredAccountId)
|
|
231
|
+
? themeColors.success('account id detected ✅')
|
|
232
|
+
: themeColors.warning('will be auto-discovered from your API key (or export CLOUDFLARE_ACCOUNT_ID) ⚠')
|
|
233
|
+
lines.push(themeColors.dim(` 4) Cloudflare's endpoint is account-scoped. Account id: ${accountIdStatus}`))
|
|
228
234
|
}
|
|
229
235
|
const testDetail = state.settingsTestDetails?.[selectedProviderKey]
|
|
230
236
|
if (testDetail) {
|