privateboard 0.1.20 → 0.1.21
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/dist/boot.js +239 -34
- package/dist/boot.js.map +1 -1
- package/dist/cli.js +239 -34
- package/dist/cli.js.map +1 -1
- package/dist/server.js +239 -34
- package/dist/server.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/version.js.map +1 -1
- package/package.json +14 -3
- package/public/adjourn-overlay.css +19 -19
- package/public/agent-overlay.css +71 -71
- package/public/agent-profile.css +66 -66
- package/public/agent-profile.js +32 -31
- package/public/app.js +80 -22
- package/public/i18n.js +20 -16
- package/public/icons/fold.png +0 -0
- package/public/index.html +190 -94
- package/public/new-agent.css +111 -110
- package/public/new-agent.js +4 -1
- package/public/onboarding.css +96 -96
- package/public/onboarding.js +53 -24
- package/public/quote-cta.css +38 -38
- package/public/room-settings.css +145 -144
- package/public/themes.css +43 -64
- package/public/user-settings.css +257 -215
- package/public/user-settings.js +94 -13
- package/public/voice-onboarding.css +33 -33
- package/public/voice-replay.css +34 -34
package/dist/cli.js
CHANGED
|
@@ -955,6 +955,7 @@ import open from "open";
|
|
|
955
955
|
init_db();
|
|
956
956
|
var VALID_CARRIER_PREFS = /* @__PURE__ */ new Set([
|
|
957
957
|
"openrouter",
|
|
958
|
+
"bai",
|
|
958
959
|
"anthropic",
|
|
959
960
|
"openai",
|
|
960
961
|
"google",
|
|
@@ -2268,6 +2269,7 @@ var MODELS = {
|
|
|
2268
2269
|
provider: "anthropic",
|
|
2269
2270
|
directApiId: "claude-sonnet-4-6",
|
|
2270
2271
|
openrouterId: "anthropic/claude-sonnet-4.6",
|
|
2272
|
+
baiId: "claude-sonnet-4-6",
|
|
2271
2273
|
displayName: "Sonnet 4.6",
|
|
2272
2274
|
contextBudget: 2e5,
|
|
2273
2275
|
deck: "balanced \xB7 default"
|
|
@@ -2277,6 +2279,7 @@ var MODELS = {
|
|
|
2277
2279
|
provider: "anthropic",
|
|
2278
2280
|
directApiId: "claude-opus-4-6",
|
|
2279
2281
|
openrouterId: "anthropic/claude-opus-4.6",
|
|
2282
|
+
baiId: "claude-opus-4-6",
|
|
2280
2283
|
displayName: "Opus 4.6",
|
|
2281
2284
|
contextBudget: 1e6,
|
|
2282
2285
|
deck: "deep reasoning \xB7 1M ctx"
|
|
@@ -2286,6 +2289,7 @@ var MODELS = {
|
|
|
2286
2289
|
provider: "anthropic",
|
|
2287
2290
|
directApiId: "claude-opus-4-7",
|
|
2288
2291
|
openrouterId: "anthropic/claude-opus-4.7",
|
|
2292
|
+
baiId: "claude-opus-4-7",
|
|
2289
2293
|
displayName: "Opus 4.7",
|
|
2290
2294
|
contextBudget: 2e5,
|
|
2291
2295
|
deck: "deep reasoning"
|
|
@@ -2295,6 +2299,9 @@ var MODELS = {
|
|
|
2295
2299
|
provider: "anthropic",
|
|
2296
2300
|
directApiId: "claude-opus-4-6-fast",
|
|
2297
2301
|
openrouterId: "anthropic/claude-opus-4.6-fast",
|
|
2302
|
+
// No baiId · B.AI's catalog doesn't carry Anthropic's "fast"
|
|
2303
|
+
// variants (only the base models). Routing this through B.AI 503s
|
|
2304
|
+
// with "no available channel". Direct Anthropic key or OR carries it.
|
|
2298
2305
|
displayName: "Opus 4.6 Fast",
|
|
2299
2306
|
contextBudget: 2e5,
|
|
2300
2307
|
deck: "faster 4.6 \xB7 same intelligence"
|
|
@@ -2306,6 +2313,7 @@ var MODELS = {
|
|
|
2306
2313
|
// the unsuffixed `claude-haiku-4-5` 404s on the direct API.
|
|
2307
2314
|
directApiId: "claude-haiku-4-5-20251001",
|
|
2308
2315
|
openrouterId: "anthropic/claude-haiku-4.5",
|
|
2316
|
+
baiId: "claude-haiku-4-5",
|
|
2309
2317
|
displayName: "Haiku 4.5",
|
|
2310
2318
|
contextBudget: 2e5,
|
|
2311
2319
|
deck: "fast \xB7 low-cost"
|
|
@@ -2320,6 +2328,7 @@ var MODELS = {
|
|
|
2320
2328
|
provider: "openai",
|
|
2321
2329
|
directApiId: "gpt-5.5",
|
|
2322
2330
|
openrouterId: "openai/gpt-5.5",
|
|
2331
|
+
baiId: "gpt-5-5",
|
|
2323
2332
|
displayName: "GPT-5.5",
|
|
2324
2333
|
contextBudget: 1e6,
|
|
2325
2334
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -2329,6 +2338,7 @@ var MODELS = {
|
|
|
2329
2338
|
provider: "openai",
|
|
2330
2339
|
directApiId: "gpt-5.4",
|
|
2331
2340
|
openrouterId: "openai/gpt-5.4",
|
|
2341
|
+
baiId: "gpt-5-4",
|
|
2332
2342
|
displayName: "GPT-5.4",
|
|
2333
2343
|
contextBudget: 1e6,
|
|
2334
2344
|
deck: "general \xB7 1M ctx"
|
|
@@ -2338,6 +2348,10 @@ var MODELS = {
|
|
|
2338
2348
|
provider: "openai",
|
|
2339
2349
|
directApiId: "gpt-5.4-mini",
|
|
2340
2350
|
openrouterId: "openai/gpt-5.4-mini",
|
|
2351
|
+
// No baiId · B.AI's catalog reports "No available channel for
|
|
2352
|
+
// model gpt-5-4-mini" on the OneAPI distributor — the mini
|
|
2353
|
+
// variant isn't routed there. The full `gpt-5-4` IS available on
|
|
2354
|
+
// B.AI; pick that or use direct / OR for the mini tier.
|
|
2341
2355
|
displayName: "GPT-5.4 Mini",
|
|
2342
2356
|
contextBudget: 4e5,
|
|
2343
2357
|
deck: "fast \xB7 400k ctx"
|
|
@@ -2348,20 +2362,23 @@ var MODELS = {
|
|
|
2348
2362
|
provider: "openai",
|
|
2349
2363
|
directApiId: "gpt-5.5-pro",
|
|
2350
2364
|
openrouterId: "openai/gpt-5.5-pro",
|
|
2365
|
+
baiId: "gpt-5-5-pro",
|
|
2351
2366
|
displayName: "GPT-5.5 Pro",
|
|
2352
2367
|
contextBudget: 1e6,
|
|
2353
2368
|
deck: "deep reasoning \xB7 1M ctx",
|
|
2354
|
-
|
|
2369
|
+
viaUniversalOnly: true
|
|
2355
2370
|
},
|
|
2356
2371
|
"codex-5-4": {
|
|
2357
2372
|
v: "codex-5-4",
|
|
2358
2373
|
provider: "openai",
|
|
2359
2374
|
directApiId: "gpt-5.3-codex",
|
|
2360
2375
|
openrouterId: "openai/gpt-5.3-codex",
|
|
2376
|
+
// No baiId · B.AI's catalog doesn't list a codex variant; the
|
|
2377
|
+
// preview only ships via OR. Routing it through B.AI 503s.
|
|
2361
2378
|
displayName: "ChatGPT Codex 5.4",
|
|
2362
2379
|
contextBudget: 4e5,
|
|
2363
2380
|
deck: "code \xB7 agents",
|
|
2364
|
-
|
|
2381
|
+
viaUniversalOnly: true
|
|
2365
2382
|
},
|
|
2366
2383
|
// ── Google · current frontier (3.1 Pro / 3 Flash / 3.1 Flash Lite) ──
|
|
2367
2384
|
// Replaced the legacy gemini-2.5-pro / gemini-2.5-flash entries — all
|
|
@@ -2373,6 +2390,7 @@ var MODELS = {
|
|
|
2373
2390
|
provider: "google",
|
|
2374
2391
|
directApiId: "gemini-3.1-pro-preview",
|
|
2375
2392
|
openrouterId: "google/gemini-3.1-pro-preview",
|
|
2393
|
+
baiId: "gemini-3-1-pro",
|
|
2376
2394
|
displayName: "Gemini 3.1 Pro",
|
|
2377
2395
|
contextBudget: 1e6,
|
|
2378
2396
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -2382,6 +2400,7 @@ var MODELS = {
|
|
|
2382
2400
|
provider: "google",
|
|
2383
2401
|
directApiId: "gemini-3-flash-preview",
|
|
2384
2402
|
openrouterId: "google/gemini-3-flash-preview",
|
|
2403
|
+
baiId: "gemini-3-flash",
|
|
2385
2404
|
displayName: "Gemini 3 Flash",
|
|
2386
2405
|
contextBudget: 1e6,
|
|
2387
2406
|
deck: "frontier flash \xB7 1M ctx"
|
|
@@ -2391,6 +2410,11 @@ var MODELS = {
|
|
|
2391
2410
|
provider: "google",
|
|
2392
2411
|
directApiId: "gemini-3.1-flash-lite-preview",
|
|
2393
2412
|
openrouterId: "google/gemini-3.1-flash-lite-preview",
|
|
2413
|
+
// No baiId · B.AI's catalog only has `gemini-3-1-pro` and
|
|
2414
|
+
// `gemini-3-flash` for the Gemini family — no 3.1 Flash Lite
|
|
2415
|
+
// channel. Earlier mapping to `gemini-3-1-flash` 503'd with
|
|
2416
|
+
// "no available channel for model gemini-3-1-flash". Direct
|
|
2417
|
+
// Google key or OR carries this preview model.
|
|
2394
2418
|
displayName: "Gemini 3.1 Flash Lite",
|
|
2395
2419
|
contextBudget: 1e6,
|
|
2396
2420
|
deck: "fast \xB7 1M ctx"
|
|
@@ -2405,6 +2429,7 @@ var MODELS = {
|
|
|
2405
2429
|
provider: "xai",
|
|
2406
2430
|
directApiId: "grok-4.3",
|
|
2407
2431
|
openrouterId: "x-ai/grok-4.3",
|
|
2432
|
+
baiId: "grok-4-3",
|
|
2408
2433
|
displayName: "Grok 4.3",
|
|
2409
2434
|
contextBudget: 1e6,
|
|
2410
2435
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -2414,6 +2439,7 @@ var MODELS = {
|
|
|
2414
2439
|
provider: "xai",
|
|
2415
2440
|
directApiId: "grok-4.1-fast",
|
|
2416
2441
|
openrouterId: "x-ai/grok-4.1-fast",
|
|
2442
|
+
baiId: "grok-4-1-fast",
|
|
2417
2443
|
displayName: "Grok 4.1 Fast",
|
|
2418
2444
|
contextBudget: 256e3,
|
|
2419
2445
|
deck: "fast \xB7 256k ctx"
|
|
@@ -2423,10 +2449,11 @@ var MODELS = {
|
|
|
2423
2449
|
provider: "xai",
|
|
2424
2450
|
directApiId: "grok-4.20",
|
|
2425
2451
|
openrouterId: "x-ai/grok-4.20",
|
|
2452
|
+
baiId: "grok-4-20",
|
|
2426
2453
|
displayName: "Grok 4.20",
|
|
2427
2454
|
contextBudget: 2e6,
|
|
2428
2455
|
deck: "2M ctx \xB7 big context",
|
|
2429
|
-
|
|
2456
|
+
viaUniversalOnly: true
|
|
2430
2457
|
},
|
|
2431
2458
|
// ── DeepSeek (OR-only · no @ai-sdk/deepseek shipped) ──
|
|
2432
2459
|
"deepseek-v4-pro": {
|
|
@@ -2434,10 +2461,11 @@ var MODELS = {
|
|
|
2434
2461
|
provider: "deepseek",
|
|
2435
2462
|
directApiId: "deepseek-v4-pro",
|
|
2436
2463
|
openrouterId: "deepseek/deepseek-v4-pro",
|
|
2464
|
+
baiId: "deepseek-v4-pro",
|
|
2437
2465
|
displayName: "DeepSeek V4 Pro",
|
|
2438
2466
|
contextBudget: 128e3,
|
|
2439
2467
|
deck: "reasoning \xB7 open weights",
|
|
2440
|
-
|
|
2468
|
+
viaUniversalOnly: true
|
|
2441
2469
|
},
|
|
2442
2470
|
// OpenRouter catalog id · deepseek/deepseek-v4-flash ("V4 Flash" — lite tier).
|
|
2443
2471
|
"deepseek-v4-flash": {
|
|
@@ -2445,10 +2473,41 @@ var MODELS = {
|
|
|
2445
2473
|
provider: "deepseek",
|
|
2446
2474
|
directApiId: "deepseek-v4-flash",
|
|
2447
2475
|
openrouterId: "deepseek/deepseek-v4-flash",
|
|
2476
|
+
baiId: "deepseek-v4-flash",
|
|
2448
2477
|
displayName: "DeepSeek Lite",
|
|
2449
2478
|
contextBudget: 1e6,
|
|
2450
2479
|
deck: "V4 Flash \xB7 fast \xB7 1M ctx",
|
|
2451
|
-
|
|
2480
|
+
viaUniversalOnly: true
|
|
2481
|
+
},
|
|
2482
|
+
// ── Zhipu (Z.AI) · GLM family · OR + B.AI only ──
|
|
2483
|
+
// OpenRouter catalog convention: `z-ai/glm-X.Y`. B.AI uses
|
|
2484
|
+
// hyphenated lowercase: `glm-5-1`. No direct @ai-sdk client ·
|
|
2485
|
+
// viaUniversalOnly skips the direct path.
|
|
2486
|
+
"glm-5-1": {
|
|
2487
|
+
v: "glm-5-1",
|
|
2488
|
+
provider: "zhipu",
|
|
2489
|
+
directApiId: "glm-5.1",
|
|
2490
|
+
openrouterId: "z-ai/glm-5.1",
|
|
2491
|
+
baiId: "glm-5-1",
|
|
2492
|
+
displayName: "GLM 5.1",
|
|
2493
|
+
contextBudget: 2e5,
|
|
2494
|
+
deck: "Zhipu flagship \xB7 200k ctx",
|
|
2495
|
+
viaUniversalOnly: true
|
|
2496
|
+
},
|
|
2497
|
+
// ── Moonshot · Kimi family · OR + B.AI only ──
|
|
2498
|
+
// OpenRouter catalog convention: `moonshotai/kimi-…`. B.AI uses
|
|
2499
|
+
// hyphenated lowercase: `kimi-2-6`. No direct @ai-sdk client ·
|
|
2500
|
+
// viaUniversalOnly skips the direct path.
|
|
2501
|
+
"kimi-2-6": {
|
|
2502
|
+
v: "kimi-2-6",
|
|
2503
|
+
provider: "moonshot",
|
|
2504
|
+
directApiId: "kimi-2.6",
|
|
2505
|
+
openrouterId: "moonshotai/kimi-2.6",
|
|
2506
|
+
baiId: "kimi-2-6",
|
|
2507
|
+
displayName: "Kimi 2.6",
|
|
2508
|
+
contextBudget: 256e3,
|
|
2509
|
+
deck: "Moonshot \xB7 long-context",
|
|
2510
|
+
viaUniversalOnly: true
|
|
2452
2511
|
}
|
|
2453
2512
|
};
|
|
2454
2513
|
function getModel(v) {
|
|
@@ -3486,6 +3545,7 @@ var NoKeyError = class extends Error {
|
|
|
3486
3545
|
provider;
|
|
3487
3546
|
};
|
|
3488
3547
|
var OPENROUTER_BASE = "https://openrouter.ai/api/v1";
|
|
3548
|
+
var BAI_BASE = "https://api.b.ai/v1";
|
|
3489
3549
|
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
3490
3550
|
"authorization",
|
|
3491
3551
|
"x-api-key",
|
|
@@ -3613,70 +3673,107 @@ function formatStreamError(e) {
|
|
|
3613
3673
|
}
|
|
3614
3674
|
return String(e);
|
|
3615
3675
|
}
|
|
3616
|
-
function resolveModel(modelV, carrier) {
|
|
3676
|
+
function resolveModel(modelV, carrier, excludeCarriers) {
|
|
3617
3677
|
const meta = getModel(modelV);
|
|
3618
|
-
const
|
|
3619
|
-
const
|
|
3678
|
+
const skip = (c) => excludeCarriers?.has(c) === true;
|
|
3679
|
+
const orKey = !skip("openrouter") ? getKey("openrouter") : void 0;
|
|
3680
|
+
const baiKey = !skip("bai") ? getKey("bai") : void 0;
|
|
3681
|
+
const directKey = !skip(meta.provider) ? getKey(meta.provider) : void 0;
|
|
3620
3682
|
if (carrier === "openrouter" && orKey) {
|
|
3621
3683
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId} (pinned)
|
|
3622
3684
|
`);
|
|
3623
3685
|
return openRouterResolved(meta, orKey);
|
|
3624
3686
|
}
|
|
3625
|
-
if (carrier
|
|
3626
|
-
|
|
3687
|
+
if (carrier === "bai" && baiKey && meta.baiId) {
|
|
3688
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 bai:${meta.baiId} (pinned)
|
|
3689
|
+
`);
|
|
3690
|
+
return baiResolved(meta, baiKey);
|
|
3691
|
+
}
|
|
3692
|
+
if (carrier && carrier !== "openrouter" && carrier !== "bai" && carrier === meta.provider) {
|
|
3693
|
+
const pinnedKey = !skip(carrier) ? getKey(carrier) : void 0;
|
|
3627
3694
|
if (pinnedKey) {
|
|
3628
3695
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (pinned)
|
|
3629
3696
|
`);
|
|
3630
3697
|
return directResolved(meta, pinnedKey);
|
|
3631
3698
|
}
|
|
3632
3699
|
}
|
|
3633
|
-
if (carrier) {
|
|
3700
|
+
if (carrier && !excludeCarriers?.size) {
|
|
3634
3701
|
process.stderr.write(
|
|
3635
3702
|
`[adapter] modelV=${modelV} pinned carrier=${carrier} unreachable; falling back to default routing
|
|
3636
3703
|
`
|
|
3637
3704
|
);
|
|
3638
3705
|
}
|
|
3639
|
-
if (meta.
|
|
3706
|
+
if (meta.viaUniversalOnly && orKey) {
|
|
3640
3707
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId} (preferred)
|
|
3641
3708
|
`);
|
|
3642
3709
|
return openRouterResolved(meta, orKey);
|
|
3643
3710
|
}
|
|
3644
|
-
if (directKey && !meta.
|
|
3711
|
+
if (directKey && !meta.viaUniversalOnly) {
|
|
3645
3712
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId}
|
|
3646
3713
|
`);
|
|
3647
3714
|
return directResolved(meta, directKey);
|
|
3648
3715
|
}
|
|
3716
|
+
if (baiKey && meta.baiId) {
|
|
3717
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 bai:${meta.baiId}
|
|
3718
|
+
`);
|
|
3719
|
+
return baiResolved(meta, baiKey);
|
|
3720
|
+
}
|
|
3649
3721
|
if (orKey) {
|
|
3650
3722
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId}
|
|
3651
3723
|
`);
|
|
3652
3724
|
return openRouterResolved(meta, orKey);
|
|
3653
3725
|
}
|
|
3654
|
-
if (meta.
|
|
3655
|
-
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (
|
|
3726
|
+
if (meta.viaUniversalOnly && directKey) {
|
|
3727
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (viaUniversalOnly fallback \xB7 no OR / B.AI key)
|
|
3656
3728
|
`);
|
|
3657
3729
|
return directResolved(meta, directKey);
|
|
3658
3730
|
}
|
|
3659
3731
|
throw new NoKeyError(meta.provider);
|
|
3660
3732
|
}
|
|
3733
|
+
function isCarrierAccessDenied(message) {
|
|
3734
|
+
if (!message) return false;
|
|
3735
|
+
const m = message.toLowerCase();
|
|
3736
|
+
if (/\b40[23]\b/.test(m) && /(access|deposit|payment|paid|premium|subscri|quota|balance|fund)/.test(m)) return true;
|
|
3737
|
+
if (/access[_\s-]?denied/.test(m)) return true;
|
|
3738
|
+
if (/deposit\s+required/.test(m)) return true;
|
|
3739
|
+
if (/paid[_\s-]?plan[_\s-]?required/.test(m)) return true;
|
|
3740
|
+
if (/premium[_\s-]?model/.test(m)) return true;
|
|
3741
|
+
if (/insufficient[_\s-]?(?:quota|balance|fund)/.test(m)) return true;
|
|
3742
|
+
if (/quota[_\s-]?exceeded/.test(m)) return true;
|
|
3743
|
+
if (/payment[_\s-]?required/.test(m)) return true;
|
|
3744
|
+
if (/billing/.test(m) && /(disabled|inactive|required|invalid|missing)/.test(m)) return true;
|
|
3745
|
+
if (/model[_\s-]?not[_\s-]?found/.test(m)) return true;
|
|
3746
|
+
if (/no\s+available\s+channel/.test(m)) return true;
|
|
3747
|
+
if (/no\s+endpoints?\s+found/.test(m)) return true;
|
|
3748
|
+
if (/invalid\s+model/.test(m)) return true;
|
|
3749
|
+
if (/model.*(unavailable|not\s+(?:supported|available))/.test(m)) return true;
|
|
3750
|
+
if (/prohibited.*(?:terms?\s+of\s+service|provider)/.test(m)) return true;
|
|
3751
|
+
if (/provider.*terms?\s+of\s+service/.test(m)) return true;
|
|
3752
|
+
if (/violates?\s+(?:our|the)?\s*(?:terms|policy|content)/.test(m)) return true;
|
|
3753
|
+
return false;
|
|
3754
|
+
}
|
|
3661
3755
|
function directResolved(meta, apiKey) {
|
|
3662
3756
|
switch (meta.provider) {
|
|
3663
3757
|
case "anthropic":
|
|
3664
3758
|
return {
|
|
3665
|
-
model: createAnthropic({ apiKey, fetch: makeLoggedFetch("anthropic") })(meta.directApiId)
|
|
3759
|
+
model: createAnthropic({ apiKey, fetch: makeLoggedFetch("anthropic") })(meta.directApiId),
|
|
3760
|
+
carrier: "anthropic"
|
|
3666
3761
|
};
|
|
3667
3762
|
case "openai":
|
|
3668
3763
|
return {
|
|
3669
3764
|
model: createOpenAI({ apiKey, fetch: makeLoggedFetch("openai") }).responses(meta.directApiId),
|
|
3670
3765
|
providerOptions: {
|
|
3671
3766
|
openai: { reasoningEffort: "none" }
|
|
3672
|
-
}
|
|
3767
|
+
},
|
|
3768
|
+
carrier: "openai"
|
|
3673
3769
|
};
|
|
3674
3770
|
case "google":
|
|
3675
3771
|
return {
|
|
3676
3772
|
model: createGoogleGenerativeAI({ apiKey, fetch: makeLoggedFetch("google") })(meta.directApiId),
|
|
3677
3773
|
providerOptions: {
|
|
3678
3774
|
google: { thinkingConfig: { thinkingBudget: 0 } }
|
|
3679
|
-
}
|
|
3775
|
+
},
|
|
3776
|
+
carrier: "google"
|
|
3680
3777
|
};
|
|
3681
3778
|
case "xai": {
|
|
3682
3779
|
return {
|
|
@@ -3684,13 +3781,31 @@ function directResolved(meta, apiKey) {
|
|
|
3684
3781
|
apiKey,
|
|
3685
3782
|
baseURL: "https://api.x.ai/v1",
|
|
3686
3783
|
fetch: makeLoggedFetch("xai")
|
|
3687
|
-
}).responses(meta.directApiId)
|
|
3784
|
+
}).responses(meta.directApiId),
|
|
3785
|
+
carrier: "xai"
|
|
3688
3786
|
};
|
|
3689
3787
|
}
|
|
3690
3788
|
default:
|
|
3691
3789
|
throw new NoKeyError(meta.provider);
|
|
3692
3790
|
}
|
|
3693
3791
|
}
|
|
3792
|
+
function baiResolved(meta, apiKey) {
|
|
3793
|
+
const baiId = meta.baiId;
|
|
3794
|
+
if (!baiId) {
|
|
3795
|
+
throw new NoKeyError(meta.provider);
|
|
3796
|
+
}
|
|
3797
|
+
const compat = createOpenAICompatible({
|
|
3798
|
+
name: "bai",
|
|
3799
|
+
apiKey,
|
|
3800
|
+
baseURL: BAI_BASE,
|
|
3801
|
+
fetch: baiLoggedFetch
|
|
3802
|
+
});
|
|
3803
|
+
return {
|
|
3804
|
+
model: compat.chatModel(baiId),
|
|
3805
|
+
carrier: "bai"
|
|
3806
|
+
};
|
|
3807
|
+
}
|
|
3808
|
+
var baiLoggedFetch = makeLoggedFetch("bai");
|
|
3694
3809
|
function openRouterResolved(meta, apiKey) {
|
|
3695
3810
|
const compat = createOpenAICompatible({
|
|
3696
3811
|
name: "openrouter",
|
|
@@ -3715,7 +3830,8 @@ function openRouterResolved(meta, apiKey) {
|
|
|
3715
3830
|
openrouter: {
|
|
3716
3831
|
provider: { allow_fallbacks: false }
|
|
3717
3832
|
}
|
|
3718
|
-
}
|
|
3833
|
+
},
|
|
3834
|
+
carrier: "openrouter"
|
|
3719
3835
|
};
|
|
3720
3836
|
}
|
|
3721
3837
|
var RETRY_MAX_ATTEMPTS = 3;
|
|
@@ -3766,6 +3882,8 @@ async function* callLLMStream(req) {
|
|
|
3766
3882
|
let attempt = 0;
|
|
3767
3883
|
let lastTransientMessage = "";
|
|
3768
3884
|
let yieldedText = false;
|
|
3885
|
+
const triedCarriers = /* @__PURE__ */ new Set();
|
|
3886
|
+
triedCarriers.add(resolved.carrier);
|
|
3769
3887
|
while (attempt < RETRY_MAX_ATTEMPTS) {
|
|
3770
3888
|
attempt++;
|
|
3771
3889
|
if (req.signal?.aborted) {
|
|
@@ -3807,6 +3925,21 @@ async function* callLLMStream(req) {
|
|
|
3807
3925
|
retriableErrorMessage = msg;
|
|
3808
3926
|
break;
|
|
3809
3927
|
}
|
|
3928
|
+
if (!yieldedText && isCarrierAccessDenied(msg)) {
|
|
3929
|
+
try {
|
|
3930
|
+
const next = resolveModel(req.modelV, null, triedCarriers);
|
|
3931
|
+
triedCarriers.add(next.carrier);
|
|
3932
|
+
process.stderr.write(
|
|
3933
|
+
`[adapter] modelV=${req.modelV} carrier=${resolved.carrier} rejected (access denied); retrying via ${next.carrier}
|
|
3934
|
+
`
|
|
3935
|
+
);
|
|
3936
|
+
resolved = next;
|
|
3937
|
+
attempt = 0;
|
|
3938
|
+
retriableErrorMessage = msg;
|
|
3939
|
+
break;
|
|
3940
|
+
} catch {
|
|
3941
|
+
}
|
|
3942
|
+
}
|
|
3810
3943
|
sawError = true;
|
|
3811
3944
|
yield { type: "error", message: msg };
|
|
3812
3945
|
}
|
|
@@ -3849,6 +3982,20 @@ async function* callLLMStream(req) {
|
|
|
3849
3982
|
lastTransientMessage = msg;
|
|
3850
3983
|
continue;
|
|
3851
3984
|
}
|
|
3985
|
+
if (!yieldedText && isCarrierAccessDenied(msg)) {
|
|
3986
|
+
try {
|
|
3987
|
+
const next = resolveModel(req.modelV, null, triedCarriers);
|
|
3988
|
+
triedCarriers.add(next.carrier);
|
|
3989
|
+
process.stderr.write(
|
|
3990
|
+
`[adapter] modelV=${req.modelV} carrier=${resolved.carrier} rejected (access denied / threw); retrying via ${next.carrier}
|
|
3991
|
+
`
|
|
3992
|
+
);
|
|
3993
|
+
resolved = next;
|
|
3994
|
+
attempt = 0;
|
|
3995
|
+
continue;
|
|
3996
|
+
} catch {
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3852
3999
|
yield { type: "error", message: msg };
|
|
3853
4000
|
return;
|
|
3854
4001
|
}
|
|
@@ -3888,25 +4035,31 @@ async function callLLMWithUsage(req) {
|
|
|
3888
4035
|
// src/storage/reconcile-models.ts
|
|
3889
4036
|
var PRIMARY_BY_CARRIER = {
|
|
3890
4037
|
openrouter: "opus-4-6-fast",
|
|
4038
|
+
bai: "haiku-4-5",
|
|
3891
4039
|
anthropic: "haiku-4-5",
|
|
3892
4040
|
openai: "gpt-5-4-mini",
|
|
3893
4041
|
google: "gemini-3-1-flash",
|
|
3894
4042
|
xai: "grok-4-1-fast"
|
|
3895
4043
|
};
|
|
3896
|
-
var CARRIER_PRIORITY = ["openrouter", "anthropic", "openai", "google", "xai"];
|
|
4044
|
+
var CARRIER_PRIORITY = ["openrouter", "bai", "anthropic", "openai", "google", "xai"];
|
|
3897
4045
|
function reachableModelVs() {
|
|
3898
4046
|
const out = /* @__PURE__ */ new Set();
|
|
3899
4047
|
const orKey = !!getKey("openrouter");
|
|
4048
|
+
const baiKey = !!getKey("bai");
|
|
3900
4049
|
for (const [v, meta] of Object.entries(MODELS)) {
|
|
3901
4050
|
if (orKey) {
|
|
3902
4051
|
out.add(v);
|
|
3903
4052
|
continue;
|
|
3904
4053
|
}
|
|
3905
|
-
if (
|
|
4054
|
+
if (baiKey && meta.baiId) {
|
|
3906
4055
|
out.add(v);
|
|
3907
4056
|
continue;
|
|
3908
4057
|
}
|
|
3909
|
-
if (meta.
|
|
4058
|
+
if (!meta.viaUniversalOnly && hasDirectKey(meta.provider)) {
|
|
4059
|
+
out.add(v);
|
|
4060
|
+
continue;
|
|
4061
|
+
}
|
|
4062
|
+
if (meta.viaUniversalOnly && hasDirectKey(meta.provider)) {
|
|
3910
4063
|
out.add(v);
|
|
3911
4064
|
}
|
|
3912
4065
|
}
|
|
@@ -3928,14 +4081,16 @@ function activeCarrier() {
|
|
|
3928
4081
|
if (prefs.defaultModelV) {
|
|
3929
4082
|
const meta = MODELS[prefs.defaultModelV];
|
|
3930
4083
|
if (meta) {
|
|
3931
|
-
if (meta.
|
|
4084
|
+
if (meta.viaUniversalOnly && getKey("openrouter")) return "openrouter";
|
|
3932
4085
|
if (hasDirectKey(meta.provider)) return meta.provider;
|
|
4086
|
+
if (getKey("bai") && meta.baiId) return "bai";
|
|
3933
4087
|
if (getKey("openrouter")) return "openrouter";
|
|
3934
4088
|
}
|
|
3935
4089
|
}
|
|
3936
4090
|
for (const c of CARRIER_PRIORITY) {
|
|
3937
4091
|
if (c === "openrouter" && getKey("openrouter")) return "openrouter";
|
|
3938
|
-
if (c
|
|
4092
|
+
if (c === "bai" && getKey("bai")) return "bai";
|
|
4093
|
+
if (c !== "openrouter" && c !== "bai" && hasDirectKey(c)) return c;
|
|
3939
4094
|
}
|
|
3940
4095
|
return null;
|
|
3941
4096
|
}
|
|
@@ -3946,8 +4101,18 @@ function reconcileAgentModels(opts = {}) {
|
|
|
3946
4101
|
const forcePrimary = opts.forcePrimary === true;
|
|
3947
4102
|
const switched = [];
|
|
3948
4103
|
const cleared = [];
|
|
4104
|
+
const orReachable = !!getKey("openrouter");
|
|
4105
|
+
const baiReachable = !!getKey("bai");
|
|
4106
|
+
function carrierKeyReachable(c) {
|
|
4107
|
+
if (c === "openrouter") return orReachable;
|
|
4108
|
+
if (c === "bai") return baiReachable;
|
|
4109
|
+
return hasDirectKey(c);
|
|
4110
|
+
}
|
|
3949
4111
|
for (const agent of listAllAgents()) {
|
|
3950
4112
|
const v = (agent.modelV || "").trim();
|
|
4113
|
+
if (agent.carrierPref && !carrierKeyReachable(agent.carrierPref)) {
|
|
4114
|
+
updateAgent(agent.id, { carrierPref: null });
|
|
4115
|
+
}
|
|
3951
4116
|
if (!forcePrimary && v && reachable.has(v)) continue;
|
|
3952
4117
|
if (primary && carrier) {
|
|
3953
4118
|
const isChair = agent.roleKind === "moderator";
|
|
@@ -3976,26 +4141,29 @@ function reconcileAgentModels(opts = {}) {
|
|
|
3976
4141
|
function getProviderKeyState() {
|
|
3977
4142
|
const directProviders = /* @__PURE__ */ new Set();
|
|
3978
4143
|
let hasOpenRouter = false;
|
|
4144
|
+
let hasBai = false;
|
|
3979
4145
|
for (const meta of listKeyMeta()) {
|
|
3980
4146
|
if (!meta.configured) continue;
|
|
3981
4147
|
if (meta.provider === "openrouter") hasOpenRouter = true;
|
|
4148
|
+
else if (meta.provider === "bai") hasBai = true;
|
|
3982
4149
|
else if (meta.provider === "brave" || meta.provider === "tavily" || meta.provider === "minimax" || meta.provider === "elevenlabs") continue;
|
|
3983
4150
|
else directProviders.add(meta.provider);
|
|
3984
4151
|
}
|
|
3985
|
-
return { hasOpenRouter, directProviders };
|
|
4152
|
+
return { hasOpenRouter, hasBai, directProviders };
|
|
3986
4153
|
}
|
|
3987
4154
|
function availabilityFor(meta, keys) {
|
|
3988
|
-
const directReachable = !meta.
|
|
4155
|
+
const directReachable = !meta.viaUniversalOnly && keys.directProviders.has(meta.provider);
|
|
3989
4156
|
const orReachable = keys.hasOpenRouter && !!meta.openrouterId;
|
|
3990
|
-
const
|
|
4157
|
+
const baiReachable = keys.hasBai && !!meta.baiId;
|
|
4158
|
+
const reachable = directReachable || orReachable || baiReachable;
|
|
3991
4159
|
return {
|
|
3992
4160
|
modelV: meta.v,
|
|
3993
4161
|
displayName: meta.displayName,
|
|
3994
4162
|
provider: meta.provider,
|
|
3995
4163
|
deck: meta.deck,
|
|
3996
|
-
routes: { direct: directReachable, openrouter: orReachable },
|
|
4164
|
+
routes: { direct: directReachable, openrouter: orReachable, bai: baiReachable },
|
|
3997
4165
|
reachable,
|
|
3998
|
-
preferredRoute: directReachable ? "direct" : orReachable ? "openrouter" : null
|
|
4166
|
+
preferredRoute: directReachable ? "direct" : baiReachable ? "bai" : orReachable ? "openrouter" : null
|
|
3999
4167
|
};
|
|
4000
4168
|
}
|
|
4001
4169
|
function modelAvailability() {
|
|
@@ -4007,7 +4175,7 @@ function reachableModels() {
|
|
|
4007
4175
|
}
|
|
4008
4176
|
function hasAnyModelKey() {
|
|
4009
4177
|
const keys = getProviderKeyState();
|
|
4010
|
-
return keys.hasOpenRouter || keys.directProviders.size > 0;
|
|
4178
|
+
return keys.hasOpenRouter || keys.hasBai || keys.directProviders.size > 0;
|
|
4011
4179
|
}
|
|
4012
4180
|
var PROVIDER_FLAGSHIP = {
|
|
4013
4181
|
anthropic: "opus-4-7",
|
|
@@ -4015,7 +4183,10 @@ var PROVIDER_FLAGSHIP = {
|
|
|
4015
4183
|
google: "gemini-3-flash",
|
|
4016
4184
|
xai: "grok-4-3",
|
|
4017
4185
|
deepseek: "deepseek-v4-pro",
|
|
4186
|
+
zhipu: "glm-5-1",
|
|
4187
|
+
moonshot: "kimi-2-6",
|
|
4018
4188
|
openrouter: "opus-4-7",
|
|
4189
|
+
bai: "opus-4-7",
|
|
4019
4190
|
brave: null,
|
|
4020
4191
|
tavily: null,
|
|
4021
4192
|
minimax: null,
|
|
@@ -4027,7 +4198,13 @@ var PROVIDER_FAST = {
|
|
|
4027
4198
|
google: "gemini-3-1-flash",
|
|
4028
4199
|
xai: "grok-4-1-fast",
|
|
4029
4200
|
deepseek: "deepseek-v4-flash",
|
|
4201
|
+
// GLM / Kimi · no separate fast/flash tier in our registry yet, so
|
|
4202
|
+
// both providers' "fast pick" falls back to the same flagship that
|
|
4203
|
+
// PROVIDER_FLAGSHIP names. Reachability-via-OR/B.AI carries it.
|
|
4204
|
+
zhipu: "glm-5-1",
|
|
4205
|
+
moonshot: "kimi-2-6",
|
|
4030
4206
|
openrouter: "opus-4-6-fast",
|
|
4207
|
+
bai: "haiku-4-5",
|
|
4031
4208
|
brave: null,
|
|
4032
4209
|
tavily: null,
|
|
4033
4210
|
minimax: null,
|
|
@@ -4043,6 +4220,21 @@ var FAST_POOL_BY_CARRIER = {
|
|
|
4043
4220
|
"grok-4-1-fast",
|
|
4044
4221
|
"deepseek-v4-flash"
|
|
4045
4222
|
],
|
|
4223
|
+
// B.AI carries the same brand-spanning fast catalog as OpenRouter ·
|
|
4224
|
+
// identical pool gives a B.AI-only user the same visibly-mixed
|
|
4225
|
+
// director cast (different brand badges per seat) that the OpenRouter
|
|
4226
|
+
// path produces. Members are filtered against reachability inside
|
|
4227
|
+
// `pickRandomFastModel`, so models without a baiId fall out naturally
|
|
4228
|
+
// if B.AI ends up not carrying one of them in practice.
|
|
4229
|
+
bai: [
|
|
4230
|
+
"opus-4-6-fast",
|
|
4231
|
+
"haiku-4-5",
|
|
4232
|
+
"gpt-5-4-mini",
|
|
4233
|
+
"gemini-3-flash",
|
|
4234
|
+
"gemini-3-1-flash",
|
|
4235
|
+
"grok-4-1-fast",
|
|
4236
|
+
"deepseek-v4-flash"
|
|
4237
|
+
],
|
|
4046
4238
|
anthropic: ["opus-4-6-fast", "haiku-4-5"],
|
|
4047
4239
|
openai: ["gpt-5-4-mini"],
|
|
4048
4240
|
google: ["gemini-3-flash", "gemini-3-1-flash"],
|
|
@@ -4070,7 +4262,10 @@ var FLAGSHIP_TIER = /* @__PURE__ */ new Set([
|
|
|
4070
4262
|
// xAI
|
|
4071
4263
|
"grok-4-3",
|
|
4072
4264
|
// DeepSeek
|
|
4073
|
-
"deepseek-v4-pro"
|
|
4265
|
+
"deepseek-v4-pro",
|
|
4266
|
+
// Zhipu · Moonshot · single flagship each (both OR + B.AI routed).
|
|
4267
|
+
"glm-5-1",
|
|
4268
|
+
"kimi-2-6"
|
|
4074
4269
|
]);
|
|
4075
4270
|
function effectiveDefaultModel() {
|
|
4076
4271
|
const prefs = getPrefs();
|
|
@@ -4100,6 +4295,12 @@ function defaultModelFor(keys = getProviderKeyState()) {
|
|
|
4100
4295
|
const opus = reachable.find((m) => m.modelV === "opus-4-7");
|
|
4101
4296
|
if (opus) return opus.modelV;
|
|
4102
4297
|
}
|
|
4298
|
+
if (keys.hasBai) {
|
|
4299
|
+
const fast = reachable.find((m) => m.modelV === "haiku-4-5");
|
|
4300
|
+
if (fast) return fast.modelV;
|
|
4301
|
+
const opus = reachable.find((m) => m.modelV === "opus-4-7");
|
|
4302
|
+
if (opus) return opus.modelV;
|
|
4303
|
+
}
|
|
4103
4304
|
for (const provider of keys.directProviders) {
|
|
4104
4305
|
const fast = PROVIDER_FAST[provider];
|
|
4105
4306
|
if (fast && reachable.find((m) => m.modelV === fast)) return fast;
|
|
@@ -4112,6 +4313,8 @@ function defaultModelFor(keys = getProviderKeyState()) {
|
|
|
4112
4313
|
}
|
|
4113
4314
|
var CHEAP_BY_CARRIER = {
|
|
4114
4315
|
openrouter: "haiku-4-5",
|
|
4316
|
+
bai: "haiku-4-5",
|
|
4317
|
+
// B.AI carries Haiku 4.5 (claude-haiku-4-5)
|
|
4115
4318
|
anthropic: "sonnet-4-6",
|
|
4116
4319
|
// only direct-routable Claude
|
|
4117
4320
|
openai: "gpt-5-4-mini",
|
|
@@ -7632,7 +7835,7 @@ function agentsRouter() {
|
|
|
7632
7835
|
patch.carrierPref = null;
|
|
7633
7836
|
} else if (typeof b.carrierPref === "string") {
|
|
7634
7837
|
const v = b.carrierPref.trim();
|
|
7635
|
-
const allowed = /* @__PURE__ */ new Set(["openrouter", "anthropic", "openai", "google", "xai"]);
|
|
7838
|
+
const allowed = /* @__PURE__ */ new Set(["openrouter", "bai", "anthropic", "openai", "google", "xai"]);
|
|
7636
7839
|
if (!allowed.has(v)) {
|
|
7637
7840
|
return c.json({ error: `unknown carrier: ${v}` }, 400);
|
|
7638
7841
|
}
|
|
@@ -15200,6 +15403,7 @@ function defaultVoiceForProvider(provider) {
|
|
|
15200
15403
|
// src/routes/keys.ts
|
|
15201
15404
|
var PROVIDERS = /* @__PURE__ */ new Set([
|
|
15202
15405
|
"openrouter",
|
|
15406
|
+
"bai",
|
|
15203
15407
|
"anthropic",
|
|
15204
15408
|
"openai",
|
|
15205
15409
|
"google",
|
|
@@ -15212,6 +15416,7 @@ var PROVIDERS = /* @__PURE__ */ new Set([
|
|
|
15212
15416
|
]);
|
|
15213
15417
|
var LLM_PROVIDERS = /* @__PURE__ */ new Set([
|
|
15214
15418
|
"openrouter",
|
|
15419
|
+
"bai",
|
|
15215
15420
|
"anthropic",
|
|
15216
15421
|
"openai",
|
|
15217
15422
|
"google",
|
|
@@ -23343,7 +23548,7 @@ function voicesRouter() {
|
|
|
23343
23548
|
init_paths();
|
|
23344
23549
|
|
|
23345
23550
|
// src/version.ts
|
|
23346
|
-
var VERSION = "0.1.
|
|
23551
|
+
var VERSION = "0.1.21";
|
|
23347
23552
|
|
|
23348
23553
|
// src/server.ts
|
|
23349
23554
|
function createApp() {
|