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/server.js
CHANGED
|
@@ -968,6 +968,7 @@ var MODELS = {
|
|
|
968
968
|
provider: "anthropic",
|
|
969
969
|
directApiId: "claude-sonnet-4-6",
|
|
970
970
|
openrouterId: "anthropic/claude-sonnet-4.6",
|
|
971
|
+
baiId: "claude-sonnet-4-6",
|
|
971
972
|
displayName: "Sonnet 4.6",
|
|
972
973
|
contextBudget: 2e5,
|
|
973
974
|
deck: "balanced \xB7 default"
|
|
@@ -977,6 +978,7 @@ var MODELS = {
|
|
|
977
978
|
provider: "anthropic",
|
|
978
979
|
directApiId: "claude-opus-4-6",
|
|
979
980
|
openrouterId: "anthropic/claude-opus-4.6",
|
|
981
|
+
baiId: "claude-opus-4-6",
|
|
980
982
|
displayName: "Opus 4.6",
|
|
981
983
|
contextBudget: 1e6,
|
|
982
984
|
deck: "deep reasoning \xB7 1M ctx"
|
|
@@ -986,6 +988,7 @@ var MODELS = {
|
|
|
986
988
|
provider: "anthropic",
|
|
987
989
|
directApiId: "claude-opus-4-7",
|
|
988
990
|
openrouterId: "anthropic/claude-opus-4.7",
|
|
991
|
+
baiId: "claude-opus-4-7",
|
|
989
992
|
displayName: "Opus 4.7",
|
|
990
993
|
contextBudget: 2e5,
|
|
991
994
|
deck: "deep reasoning"
|
|
@@ -995,6 +998,9 @@ var MODELS = {
|
|
|
995
998
|
provider: "anthropic",
|
|
996
999
|
directApiId: "claude-opus-4-6-fast",
|
|
997
1000
|
openrouterId: "anthropic/claude-opus-4.6-fast",
|
|
1001
|
+
// No baiId · B.AI's catalog doesn't carry Anthropic's "fast"
|
|
1002
|
+
// variants (only the base models). Routing this through B.AI 503s
|
|
1003
|
+
// with "no available channel". Direct Anthropic key or OR carries it.
|
|
998
1004
|
displayName: "Opus 4.6 Fast",
|
|
999
1005
|
contextBudget: 2e5,
|
|
1000
1006
|
deck: "faster 4.6 \xB7 same intelligence"
|
|
@@ -1006,6 +1012,7 @@ var MODELS = {
|
|
|
1006
1012
|
// the unsuffixed `claude-haiku-4-5` 404s on the direct API.
|
|
1007
1013
|
directApiId: "claude-haiku-4-5-20251001",
|
|
1008
1014
|
openrouterId: "anthropic/claude-haiku-4.5",
|
|
1015
|
+
baiId: "claude-haiku-4-5",
|
|
1009
1016
|
displayName: "Haiku 4.5",
|
|
1010
1017
|
contextBudget: 2e5,
|
|
1011
1018
|
deck: "fast \xB7 low-cost"
|
|
@@ -1020,6 +1027,7 @@ var MODELS = {
|
|
|
1020
1027
|
provider: "openai",
|
|
1021
1028
|
directApiId: "gpt-5.5",
|
|
1022
1029
|
openrouterId: "openai/gpt-5.5",
|
|
1030
|
+
baiId: "gpt-5-5",
|
|
1023
1031
|
displayName: "GPT-5.5",
|
|
1024
1032
|
contextBudget: 1e6,
|
|
1025
1033
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -1029,6 +1037,7 @@ var MODELS = {
|
|
|
1029
1037
|
provider: "openai",
|
|
1030
1038
|
directApiId: "gpt-5.4",
|
|
1031
1039
|
openrouterId: "openai/gpt-5.4",
|
|
1040
|
+
baiId: "gpt-5-4",
|
|
1032
1041
|
displayName: "GPT-5.4",
|
|
1033
1042
|
contextBudget: 1e6,
|
|
1034
1043
|
deck: "general \xB7 1M ctx"
|
|
@@ -1038,6 +1047,10 @@ var MODELS = {
|
|
|
1038
1047
|
provider: "openai",
|
|
1039
1048
|
directApiId: "gpt-5.4-mini",
|
|
1040
1049
|
openrouterId: "openai/gpt-5.4-mini",
|
|
1050
|
+
// No baiId · B.AI's catalog reports "No available channel for
|
|
1051
|
+
// model gpt-5-4-mini" on the OneAPI distributor — the mini
|
|
1052
|
+
// variant isn't routed there. The full `gpt-5-4` IS available on
|
|
1053
|
+
// B.AI; pick that or use direct / OR for the mini tier.
|
|
1041
1054
|
displayName: "GPT-5.4 Mini",
|
|
1042
1055
|
contextBudget: 4e5,
|
|
1043
1056
|
deck: "fast \xB7 400k ctx"
|
|
@@ -1048,20 +1061,23 @@ var MODELS = {
|
|
|
1048
1061
|
provider: "openai",
|
|
1049
1062
|
directApiId: "gpt-5.5-pro",
|
|
1050
1063
|
openrouterId: "openai/gpt-5.5-pro",
|
|
1064
|
+
baiId: "gpt-5-5-pro",
|
|
1051
1065
|
displayName: "GPT-5.5 Pro",
|
|
1052
1066
|
contextBudget: 1e6,
|
|
1053
1067
|
deck: "deep reasoning \xB7 1M ctx",
|
|
1054
|
-
|
|
1068
|
+
viaUniversalOnly: true
|
|
1055
1069
|
},
|
|
1056
1070
|
"codex-5-4": {
|
|
1057
1071
|
v: "codex-5-4",
|
|
1058
1072
|
provider: "openai",
|
|
1059
1073
|
directApiId: "gpt-5.3-codex",
|
|
1060
1074
|
openrouterId: "openai/gpt-5.3-codex",
|
|
1075
|
+
// No baiId · B.AI's catalog doesn't list a codex variant; the
|
|
1076
|
+
// preview only ships via OR. Routing it through B.AI 503s.
|
|
1061
1077
|
displayName: "ChatGPT Codex 5.4",
|
|
1062
1078
|
contextBudget: 4e5,
|
|
1063
1079
|
deck: "code \xB7 agents",
|
|
1064
|
-
|
|
1080
|
+
viaUniversalOnly: true
|
|
1065
1081
|
},
|
|
1066
1082
|
// ── Google · current frontier (3.1 Pro / 3 Flash / 3.1 Flash Lite) ──
|
|
1067
1083
|
// Replaced the legacy gemini-2.5-pro / gemini-2.5-flash entries — all
|
|
@@ -1073,6 +1089,7 @@ var MODELS = {
|
|
|
1073
1089
|
provider: "google",
|
|
1074
1090
|
directApiId: "gemini-3.1-pro-preview",
|
|
1075
1091
|
openrouterId: "google/gemini-3.1-pro-preview",
|
|
1092
|
+
baiId: "gemini-3-1-pro",
|
|
1076
1093
|
displayName: "Gemini 3.1 Pro",
|
|
1077
1094
|
contextBudget: 1e6,
|
|
1078
1095
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -1082,6 +1099,7 @@ var MODELS = {
|
|
|
1082
1099
|
provider: "google",
|
|
1083
1100
|
directApiId: "gemini-3-flash-preview",
|
|
1084
1101
|
openrouterId: "google/gemini-3-flash-preview",
|
|
1102
|
+
baiId: "gemini-3-flash",
|
|
1085
1103
|
displayName: "Gemini 3 Flash",
|
|
1086
1104
|
contextBudget: 1e6,
|
|
1087
1105
|
deck: "frontier flash \xB7 1M ctx"
|
|
@@ -1091,6 +1109,11 @@ var MODELS = {
|
|
|
1091
1109
|
provider: "google",
|
|
1092
1110
|
directApiId: "gemini-3.1-flash-lite-preview",
|
|
1093
1111
|
openrouterId: "google/gemini-3.1-flash-lite-preview",
|
|
1112
|
+
// No baiId · B.AI's catalog only has `gemini-3-1-pro` and
|
|
1113
|
+
// `gemini-3-flash` for the Gemini family — no 3.1 Flash Lite
|
|
1114
|
+
// channel. Earlier mapping to `gemini-3-1-flash` 503'd with
|
|
1115
|
+
// "no available channel for model gemini-3-1-flash". Direct
|
|
1116
|
+
// Google key or OR carries this preview model.
|
|
1094
1117
|
displayName: "Gemini 3.1 Flash Lite",
|
|
1095
1118
|
contextBudget: 1e6,
|
|
1096
1119
|
deck: "fast \xB7 1M ctx"
|
|
@@ -1105,6 +1128,7 @@ var MODELS = {
|
|
|
1105
1128
|
provider: "xai",
|
|
1106
1129
|
directApiId: "grok-4.3",
|
|
1107
1130
|
openrouterId: "x-ai/grok-4.3",
|
|
1131
|
+
baiId: "grok-4-3",
|
|
1108
1132
|
displayName: "Grok 4.3",
|
|
1109
1133
|
contextBudget: 1e6,
|
|
1110
1134
|
deck: "flagship \xB7 1M ctx"
|
|
@@ -1114,6 +1138,7 @@ var MODELS = {
|
|
|
1114
1138
|
provider: "xai",
|
|
1115
1139
|
directApiId: "grok-4.1-fast",
|
|
1116
1140
|
openrouterId: "x-ai/grok-4.1-fast",
|
|
1141
|
+
baiId: "grok-4-1-fast",
|
|
1117
1142
|
displayName: "Grok 4.1 Fast",
|
|
1118
1143
|
contextBudget: 256e3,
|
|
1119
1144
|
deck: "fast \xB7 256k ctx"
|
|
@@ -1123,10 +1148,11 @@ var MODELS = {
|
|
|
1123
1148
|
provider: "xai",
|
|
1124
1149
|
directApiId: "grok-4.20",
|
|
1125
1150
|
openrouterId: "x-ai/grok-4.20",
|
|
1151
|
+
baiId: "grok-4-20",
|
|
1126
1152
|
displayName: "Grok 4.20",
|
|
1127
1153
|
contextBudget: 2e6,
|
|
1128
1154
|
deck: "2M ctx \xB7 big context",
|
|
1129
|
-
|
|
1155
|
+
viaUniversalOnly: true
|
|
1130
1156
|
},
|
|
1131
1157
|
// ── DeepSeek (OR-only · no @ai-sdk/deepseek shipped) ──
|
|
1132
1158
|
"deepseek-v4-pro": {
|
|
@@ -1134,10 +1160,11 @@ var MODELS = {
|
|
|
1134
1160
|
provider: "deepseek",
|
|
1135
1161
|
directApiId: "deepseek-v4-pro",
|
|
1136
1162
|
openrouterId: "deepseek/deepseek-v4-pro",
|
|
1163
|
+
baiId: "deepseek-v4-pro",
|
|
1137
1164
|
displayName: "DeepSeek V4 Pro",
|
|
1138
1165
|
contextBudget: 128e3,
|
|
1139
1166
|
deck: "reasoning \xB7 open weights",
|
|
1140
|
-
|
|
1167
|
+
viaUniversalOnly: true
|
|
1141
1168
|
},
|
|
1142
1169
|
// OpenRouter catalog id · deepseek/deepseek-v4-flash ("V4 Flash" — lite tier).
|
|
1143
1170
|
"deepseek-v4-flash": {
|
|
@@ -1145,10 +1172,41 @@ var MODELS = {
|
|
|
1145
1172
|
provider: "deepseek",
|
|
1146
1173
|
directApiId: "deepseek-v4-flash",
|
|
1147
1174
|
openrouterId: "deepseek/deepseek-v4-flash",
|
|
1175
|
+
baiId: "deepseek-v4-flash",
|
|
1148
1176
|
displayName: "DeepSeek Lite",
|
|
1149
1177
|
contextBudget: 1e6,
|
|
1150
1178
|
deck: "V4 Flash \xB7 fast \xB7 1M ctx",
|
|
1151
|
-
|
|
1179
|
+
viaUniversalOnly: true
|
|
1180
|
+
},
|
|
1181
|
+
// ── Zhipu (Z.AI) · GLM family · OR + B.AI only ──
|
|
1182
|
+
// OpenRouter catalog convention: `z-ai/glm-X.Y`. B.AI uses
|
|
1183
|
+
// hyphenated lowercase: `glm-5-1`. No direct @ai-sdk client ·
|
|
1184
|
+
// viaUniversalOnly skips the direct path.
|
|
1185
|
+
"glm-5-1": {
|
|
1186
|
+
v: "glm-5-1",
|
|
1187
|
+
provider: "zhipu",
|
|
1188
|
+
directApiId: "glm-5.1",
|
|
1189
|
+
openrouterId: "z-ai/glm-5.1",
|
|
1190
|
+
baiId: "glm-5-1",
|
|
1191
|
+
displayName: "GLM 5.1",
|
|
1192
|
+
contextBudget: 2e5,
|
|
1193
|
+
deck: "Zhipu flagship \xB7 200k ctx",
|
|
1194
|
+
viaUniversalOnly: true
|
|
1195
|
+
},
|
|
1196
|
+
// ── Moonshot · Kimi family · OR + B.AI only ──
|
|
1197
|
+
// OpenRouter catalog convention: `moonshotai/kimi-…`. B.AI uses
|
|
1198
|
+
// hyphenated lowercase: `kimi-2-6`. No direct @ai-sdk client ·
|
|
1199
|
+
// viaUniversalOnly skips the direct path.
|
|
1200
|
+
"kimi-2-6": {
|
|
1201
|
+
v: "kimi-2-6",
|
|
1202
|
+
provider: "moonshot",
|
|
1203
|
+
directApiId: "kimi-2.6",
|
|
1204
|
+
openrouterId: "moonshotai/kimi-2.6",
|
|
1205
|
+
baiId: "kimi-2-6",
|
|
1206
|
+
displayName: "Kimi 2.6",
|
|
1207
|
+
contextBudget: 256e3,
|
|
1208
|
+
deck: "Moonshot \xB7 long-context",
|
|
1209
|
+
viaUniversalOnly: true
|
|
1152
1210
|
}
|
|
1153
1211
|
};
|
|
1154
1212
|
function getModel(v) {
|
|
@@ -1164,6 +1222,7 @@ function isModelV(v) {
|
|
|
1164
1222
|
init_db();
|
|
1165
1223
|
var VALID_CARRIER_PREFS = /* @__PURE__ */ new Set([
|
|
1166
1224
|
"openrouter",
|
|
1225
|
+
"bai",
|
|
1167
1226
|
"anthropic",
|
|
1168
1227
|
"openai",
|
|
1169
1228
|
"google",
|
|
@@ -2764,6 +2823,7 @@ var NoKeyError = class extends Error {
|
|
|
2764
2823
|
provider;
|
|
2765
2824
|
};
|
|
2766
2825
|
var OPENROUTER_BASE = "https://openrouter.ai/api/v1";
|
|
2826
|
+
var BAI_BASE = "https://api.b.ai/v1";
|
|
2767
2827
|
var SENSITIVE_HEADER_NAMES = /* @__PURE__ */ new Set([
|
|
2768
2828
|
"authorization",
|
|
2769
2829
|
"x-api-key",
|
|
@@ -2891,70 +2951,107 @@ function formatStreamError(e) {
|
|
|
2891
2951
|
}
|
|
2892
2952
|
return String(e);
|
|
2893
2953
|
}
|
|
2894
|
-
function resolveModel(modelV, carrier) {
|
|
2954
|
+
function resolveModel(modelV, carrier, excludeCarriers) {
|
|
2895
2955
|
const meta = getModel(modelV);
|
|
2896
|
-
const
|
|
2897
|
-
const
|
|
2956
|
+
const skip = (c) => excludeCarriers?.has(c) === true;
|
|
2957
|
+
const orKey = !skip("openrouter") ? getKey("openrouter") : void 0;
|
|
2958
|
+
const baiKey = !skip("bai") ? getKey("bai") : void 0;
|
|
2959
|
+
const directKey = !skip(meta.provider) ? getKey(meta.provider) : void 0;
|
|
2898
2960
|
if (carrier === "openrouter" && orKey) {
|
|
2899
2961
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId} (pinned)
|
|
2900
2962
|
`);
|
|
2901
2963
|
return openRouterResolved(meta, orKey);
|
|
2902
2964
|
}
|
|
2903
|
-
if (carrier
|
|
2904
|
-
|
|
2965
|
+
if (carrier === "bai" && baiKey && meta.baiId) {
|
|
2966
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 bai:${meta.baiId} (pinned)
|
|
2967
|
+
`);
|
|
2968
|
+
return baiResolved(meta, baiKey);
|
|
2969
|
+
}
|
|
2970
|
+
if (carrier && carrier !== "openrouter" && carrier !== "bai" && carrier === meta.provider) {
|
|
2971
|
+
const pinnedKey = !skip(carrier) ? getKey(carrier) : void 0;
|
|
2905
2972
|
if (pinnedKey) {
|
|
2906
2973
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (pinned)
|
|
2907
2974
|
`);
|
|
2908
2975
|
return directResolved(meta, pinnedKey);
|
|
2909
2976
|
}
|
|
2910
2977
|
}
|
|
2911
|
-
if (carrier) {
|
|
2978
|
+
if (carrier && !excludeCarriers?.size) {
|
|
2912
2979
|
process.stderr.write(
|
|
2913
2980
|
`[adapter] modelV=${modelV} pinned carrier=${carrier} unreachable; falling back to default routing
|
|
2914
2981
|
`
|
|
2915
2982
|
);
|
|
2916
2983
|
}
|
|
2917
|
-
if (meta.
|
|
2984
|
+
if (meta.viaUniversalOnly && orKey) {
|
|
2918
2985
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId} (preferred)
|
|
2919
2986
|
`);
|
|
2920
2987
|
return openRouterResolved(meta, orKey);
|
|
2921
2988
|
}
|
|
2922
|
-
if (directKey && !meta.
|
|
2989
|
+
if (directKey && !meta.viaUniversalOnly) {
|
|
2923
2990
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId}
|
|
2924
2991
|
`);
|
|
2925
2992
|
return directResolved(meta, directKey);
|
|
2926
2993
|
}
|
|
2994
|
+
if (baiKey && meta.baiId) {
|
|
2995
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 bai:${meta.baiId}
|
|
2996
|
+
`);
|
|
2997
|
+
return baiResolved(meta, baiKey);
|
|
2998
|
+
}
|
|
2927
2999
|
if (orKey) {
|
|
2928
3000
|
process.stderr.write(`[adapter] modelV=${modelV} \u2192 openrouter:${meta.openrouterId}
|
|
2929
3001
|
`);
|
|
2930
3002
|
return openRouterResolved(meta, orKey);
|
|
2931
3003
|
}
|
|
2932
|
-
if (meta.
|
|
2933
|
-
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (
|
|
3004
|
+
if (meta.viaUniversalOnly && directKey) {
|
|
3005
|
+
process.stderr.write(`[adapter] modelV=${modelV} \u2192 direct:${meta.provider}/${meta.directApiId} (viaUniversalOnly fallback \xB7 no OR / B.AI key)
|
|
2934
3006
|
`);
|
|
2935
3007
|
return directResolved(meta, directKey);
|
|
2936
3008
|
}
|
|
2937
3009
|
throw new NoKeyError(meta.provider);
|
|
2938
3010
|
}
|
|
3011
|
+
function isCarrierAccessDenied(message) {
|
|
3012
|
+
if (!message) return false;
|
|
3013
|
+
const m = message.toLowerCase();
|
|
3014
|
+
if (/\b40[23]\b/.test(m) && /(access|deposit|payment|paid|premium|subscri|quota|balance|fund)/.test(m)) return true;
|
|
3015
|
+
if (/access[_\s-]?denied/.test(m)) return true;
|
|
3016
|
+
if (/deposit\s+required/.test(m)) return true;
|
|
3017
|
+
if (/paid[_\s-]?plan[_\s-]?required/.test(m)) return true;
|
|
3018
|
+
if (/premium[_\s-]?model/.test(m)) return true;
|
|
3019
|
+
if (/insufficient[_\s-]?(?:quota|balance|fund)/.test(m)) return true;
|
|
3020
|
+
if (/quota[_\s-]?exceeded/.test(m)) return true;
|
|
3021
|
+
if (/payment[_\s-]?required/.test(m)) return true;
|
|
3022
|
+
if (/billing/.test(m) && /(disabled|inactive|required|invalid|missing)/.test(m)) return true;
|
|
3023
|
+
if (/model[_\s-]?not[_\s-]?found/.test(m)) return true;
|
|
3024
|
+
if (/no\s+available\s+channel/.test(m)) return true;
|
|
3025
|
+
if (/no\s+endpoints?\s+found/.test(m)) return true;
|
|
3026
|
+
if (/invalid\s+model/.test(m)) return true;
|
|
3027
|
+
if (/model.*(unavailable|not\s+(?:supported|available))/.test(m)) return true;
|
|
3028
|
+
if (/prohibited.*(?:terms?\s+of\s+service|provider)/.test(m)) return true;
|
|
3029
|
+
if (/provider.*terms?\s+of\s+service/.test(m)) return true;
|
|
3030
|
+
if (/violates?\s+(?:our|the)?\s*(?:terms|policy|content)/.test(m)) return true;
|
|
3031
|
+
return false;
|
|
3032
|
+
}
|
|
2939
3033
|
function directResolved(meta, apiKey) {
|
|
2940
3034
|
switch (meta.provider) {
|
|
2941
3035
|
case "anthropic":
|
|
2942
3036
|
return {
|
|
2943
|
-
model: createAnthropic({ apiKey, fetch: makeLoggedFetch("anthropic") })(meta.directApiId)
|
|
3037
|
+
model: createAnthropic({ apiKey, fetch: makeLoggedFetch("anthropic") })(meta.directApiId),
|
|
3038
|
+
carrier: "anthropic"
|
|
2944
3039
|
};
|
|
2945
3040
|
case "openai":
|
|
2946
3041
|
return {
|
|
2947
3042
|
model: createOpenAI({ apiKey, fetch: makeLoggedFetch("openai") }).responses(meta.directApiId),
|
|
2948
3043
|
providerOptions: {
|
|
2949
3044
|
openai: { reasoningEffort: "none" }
|
|
2950
|
-
}
|
|
3045
|
+
},
|
|
3046
|
+
carrier: "openai"
|
|
2951
3047
|
};
|
|
2952
3048
|
case "google":
|
|
2953
3049
|
return {
|
|
2954
3050
|
model: createGoogleGenerativeAI({ apiKey, fetch: makeLoggedFetch("google") })(meta.directApiId),
|
|
2955
3051
|
providerOptions: {
|
|
2956
3052
|
google: { thinkingConfig: { thinkingBudget: 0 } }
|
|
2957
|
-
}
|
|
3053
|
+
},
|
|
3054
|
+
carrier: "google"
|
|
2958
3055
|
};
|
|
2959
3056
|
case "xai": {
|
|
2960
3057
|
return {
|
|
@@ -2962,13 +3059,31 @@ function directResolved(meta, apiKey) {
|
|
|
2962
3059
|
apiKey,
|
|
2963
3060
|
baseURL: "https://api.x.ai/v1",
|
|
2964
3061
|
fetch: makeLoggedFetch("xai")
|
|
2965
|
-
}).responses(meta.directApiId)
|
|
3062
|
+
}).responses(meta.directApiId),
|
|
3063
|
+
carrier: "xai"
|
|
2966
3064
|
};
|
|
2967
3065
|
}
|
|
2968
3066
|
default:
|
|
2969
3067
|
throw new NoKeyError(meta.provider);
|
|
2970
3068
|
}
|
|
2971
3069
|
}
|
|
3070
|
+
function baiResolved(meta, apiKey) {
|
|
3071
|
+
const baiId = meta.baiId;
|
|
3072
|
+
if (!baiId) {
|
|
3073
|
+
throw new NoKeyError(meta.provider);
|
|
3074
|
+
}
|
|
3075
|
+
const compat = createOpenAICompatible({
|
|
3076
|
+
name: "bai",
|
|
3077
|
+
apiKey,
|
|
3078
|
+
baseURL: BAI_BASE,
|
|
3079
|
+
fetch: baiLoggedFetch
|
|
3080
|
+
});
|
|
3081
|
+
return {
|
|
3082
|
+
model: compat.chatModel(baiId),
|
|
3083
|
+
carrier: "bai"
|
|
3084
|
+
};
|
|
3085
|
+
}
|
|
3086
|
+
var baiLoggedFetch = makeLoggedFetch("bai");
|
|
2972
3087
|
function openRouterResolved(meta, apiKey) {
|
|
2973
3088
|
const compat = createOpenAICompatible({
|
|
2974
3089
|
name: "openrouter",
|
|
@@ -2993,7 +3108,8 @@ function openRouterResolved(meta, apiKey) {
|
|
|
2993
3108
|
openrouter: {
|
|
2994
3109
|
provider: { allow_fallbacks: false }
|
|
2995
3110
|
}
|
|
2996
|
-
}
|
|
3111
|
+
},
|
|
3112
|
+
carrier: "openrouter"
|
|
2997
3113
|
};
|
|
2998
3114
|
}
|
|
2999
3115
|
var RETRY_MAX_ATTEMPTS = 3;
|
|
@@ -3044,6 +3160,8 @@ async function* callLLMStream(req) {
|
|
|
3044
3160
|
let attempt = 0;
|
|
3045
3161
|
let lastTransientMessage = "";
|
|
3046
3162
|
let yieldedText = false;
|
|
3163
|
+
const triedCarriers = /* @__PURE__ */ new Set();
|
|
3164
|
+
triedCarriers.add(resolved.carrier);
|
|
3047
3165
|
while (attempt < RETRY_MAX_ATTEMPTS) {
|
|
3048
3166
|
attempt++;
|
|
3049
3167
|
if (req.signal?.aborted) {
|
|
@@ -3085,6 +3203,21 @@ async function* callLLMStream(req) {
|
|
|
3085
3203
|
retriableErrorMessage = msg;
|
|
3086
3204
|
break;
|
|
3087
3205
|
}
|
|
3206
|
+
if (!yieldedText && isCarrierAccessDenied(msg)) {
|
|
3207
|
+
try {
|
|
3208
|
+
const next = resolveModel(req.modelV, null, triedCarriers);
|
|
3209
|
+
triedCarriers.add(next.carrier);
|
|
3210
|
+
process.stderr.write(
|
|
3211
|
+
`[adapter] modelV=${req.modelV} carrier=${resolved.carrier} rejected (access denied); retrying via ${next.carrier}
|
|
3212
|
+
`
|
|
3213
|
+
);
|
|
3214
|
+
resolved = next;
|
|
3215
|
+
attempt = 0;
|
|
3216
|
+
retriableErrorMessage = msg;
|
|
3217
|
+
break;
|
|
3218
|
+
} catch {
|
|
3219
|
+
}
|
|
3220
|
+
}
|
|
3088
3221
|
sawError = true;
|
|
3089
3222
|
yield { type: "error", message: msg };
|
|
3090
3223
|
}
|
|
@@ -3127,6 +3260,20 @@ async function* callLLMStream(req) {
|
|
|
3127
3260
|
lastTransientMessage = msg;
|
|
3128
3261
|
continue;
|
|
3129
3262
|
}
|
|
3263
|
+
if (!yieldedText && isCarrierAccessDenied(msg)) {
|
|
3264
|
+
try {
|
|
3265
|
+
const next = resolveModel(req.modelV, null, triedCarriers);
|
|
3266
|
+
triedCarriers.add(next.carrier);
|
|
3267
|
+
process.stderr.write(
|
|
3268
|
+
`[adapter] modelV=${req.modelV} carrier=${resolved.carrier} rejected (access denied / threw); retrying via ${next.carrier}
|
|
3269
|
+
`
|
|
3270
|
+
);
|
|
3271
|
+
resolved = next;
|
|
3272
|
+
attempt = 0;
|
|
3273
|
+
continue;
|
|
3274
|
+
} catch {
|
|
3275
|
+
}
|
|
3276
|
+
}
|
|
3130
3277
|
yield { type: "error", message: msg };
|
|
3131
3278
|
return;
|
|
3132
3279
|
}
|
|
@@ -3166,25 +3313,31 @@ async function callLLMWithUsage(req) {
|
|
|
3166
3313
|
// src/storage/reconcile-models.ts
|
|
3167
3314
|
var PRIMARY_BY_CARRIER = {
|
|
3168
3315
|
openrouter: "opus-4-6-fast",
|
|
3316
|
+
bai: "haiku-4-5",
|
|
3169
3317
|
anthropic: "haiku-4-5",
|
|
3170
3318
|
openai: "gpt-5-4-mini",
|
|
3171
3319
|
google: "gemini-3-1-flash",
|
|
3172
3320
|
xai: "grok-4-1-fast"
|
|
3173
3321
|
};
|
|
3174
|
-
var CARRIER_PRIORITY = ["openrouter", "anthropic", "openai", "google", "xai"];
|
|
3322
|
+
var CARRIER_PRIORITY = ["openrouter", "bai", "anthropic", "openai", "google", "xai"];
|
|
3175
3323
|
function reachableModelVs() {
|
|
3176
3324
|
const out = /* @__PURE__ */ new Set();
|
|
3177
3325
|
const orKey = !!getKey("openrouter");
|
|
3326
|
+
const baiKey = !!getKey("bai");
|
|
3178
3327
|
for (const [v, meta] of Object.entries(MODELS)) {
|
|
3179
3328
|
if (orKey) {
|
|
3180
3329
|
out.add(v);
|
|
3181
3330
|
continue;
|
|
3182
3331
|
}
|
|
3183
|
-
if (
|
|
3332
|
+
if (baiKey && meta.baiId) {
|
|
3184
3333
|
out.add(v);
|
|
3185
3334
|
continue;
|
|
3186
3335
|
}
|
|
3187
|
-
if (meta.
|
|
3336
|
+
if (!meta.viaUniversalOnly && hasDirectKey(meta.provider)) {
|
|
3337
|
+
out.add(v);
|
|
3338
|
+
continue;
|
|
3339
|
+
}
|
|
3340
|
+
if (meta.viaUniversalOnly && hasDirectKey(meta.provider)) {
|
|
3188
3341
|
out.add(v);
|
|
3189
3342
|
}
|
|
3190
3343
|
}
|
|
@@ -3206,14 +3359,16 @@ function activeCarrier() {
|
|
|
3206
3359
|
if (prefs.defaultModelV) {
|
|
3207
3360
|
const meta = MODELS[prefs.defaultModelV];
|
|
3208
3361
|
if (meta) {
|
|
3209
|
-
if (meta.
|
|
3362
|
+
if (meta.viaUniversalOnly && getKey("openrouter")) return "openrouter";
|
|
3210
3363
|
if (hasDirectKey(meta.provider)) return meta.provider;
|
|
3364
|
+
if (getKey("bai") && meta.baiId) return "bai";
|
|
3211
3365
|
if (getKey("openrouter")) return "openrouter";
|
|
3212
3366
|
}
|
|
3213
3367
|
}
|
|
3214
3368
|
for (const c of CARRIER_PRIORITY) {
|
|
3215
3369
|
if (c === "openrouter" && getKey("openrouter")) return "openrouter";
|
|
3216
|
-
if (c
|
|
3370
|
+
if (c === "bai" && getKey("bai")) return "bai";
|
|
3371
|
+
if (c !== "openrouter" && c !== "bai" && hasDirectKey(c)) return c;
|
|
3217
3372
|
}
|
|
3218
3373
|
return null;
|
|
3219
3374
|
}
|
|
@@ -3224,8 +3379,18 @@ function reconcileAgentModels(opts = {}) {
|
|
|
3224
3379
|
const forcePrimary = opts.forcePrimary === true;
|
|
3225
3380
|
const switched = [];
|
|
3226
3381
|
const cleared = [];
|
|
3382
|
+
const orReachable = !!getKey("openrouter");
|
|
3383
|
+
const baiReachable = !!getKey("bai");
|
|
3384
|
+
function carrierKeyReachable(c) {
|
|
3385
|
+
if (c === "openrouter") return orReachable;
|
|
3386
|
+
if (c === "bai") return baiReachable;
|
|
3387
|
+
return hasDirectKey(c);
|
|
3388
|
+
}
|
|
3227
3389
|
for (const agent of listAllAgents()) {
|
|
3228
3390
|
const v = (agent.modelV || "").trim();
|
|
3391
|
+
if (agent.carrierPref && !carrierKeyReachable(agent.carrierPref)) {
|
|
3392
|
+
updateAgent(agent.id, { carrierPref: null });
|
|
3393
|
+
}
|
|
3229
3394
|
if (!forcePrimary && v && reachable.has(v)) continue;
|
|
3230
3395
|
if (primary && carrier) {
|
|
3231
3396
|
const isChair = agent.roleKind === "moderator";
|
|
@@ -3254,26 +3419,29 @@ function reconcileAgentModels(opts = {}) {
|
|
|
3254
3419
|
function getProviderKeyState() {
|
|
3255
3420
|
const directProviders = /* @__PURE__ */ new Set();
|
|
3256
3421
|
let hasOpenRouter = false;
|
|
3422
|
+
let hasBai = false;
|
|
3257
3423
|
for (const meta of listKeyMeta()) {
|
|
3258
3424
|
if (!meta.configured) continue;
|
|
3259
3425
|
if (meta.provider === "openrouter") hasOpenRouter = true;
|
|
3426
|
+
else if (meta.provider === "bai") hasBai = true;
|
|
3260
3427
|
else if (meta.provider === "brave" || meta.provider === "tavily" || meta.provider === "minimax" || meta.provider === "elevenlabs") continue;
|
|
3261
3428
|
else directProviders.add(meta.provider);
|
|
3262
3429
|
}
|
|
3263
|
-
return { hasOpenRouter, directProviders };
|
|
3430
|
+
return { hasOpenRouter, hasBai, directProviders };
|
|
3264
3431
|
}
|
|
3265
3432
|
function availabilityFor(meta, keys) {
|
|
3266
|
-
const directReachable = !meta.
|
|
3433
|
+
const directReachable = !meta.viaUniversalOnly && keys.directProviders.has(meta.provider);
|
|
3267
3434
|
const orReachable = keys.hasOpenRouter && !!meta.openrouterId;
|
|
3268
|
-
const
|
|
3435
|
+
const baiReachable = keys.hasBai && !!meta.baiId;
|
|
3436
|
+
const reachable = directReachable || orReachable || baiReachable;
|
|
3269
3437
|
return {
|
|
3270
3438
|
modelV: meta.v,
|
|
3271
3439
|
displayName: meta.displayName,
|
|
3272
3440
|
provider: meta.provider,
|
|
3273
3441
|
deck: meta.deck,
|
|
3274
|
-
routes: { direct: directReachable, openrouter: orReachable },
|
|
3442
|
+
routes: { direct: directReachable, openrouter: orReachable, bai: baiReachable },
|
|
3275
3443
|
reachable,
|
|
3276
|
-
preferredRoute: directReachable ? "direct" : orReachable ? "openrouter" : null
|
|
3444
|
+
preferredRoute: directReachable ? "direct" : baiReachable ? "bai" : orReachable ? "openrouter" : null
|
|
3277
3445
|
};
|
|
3278
3446
|
}
|
|
3279
3447
|
function modelAvailability() {
|
|
@@ -3285,7 +3453,7 @@ function reachableModels() {
|
|
|
3285
3453
|
}
|
|
3286
3454
|
function hasAnyModelKey() {
|
|
3287
3455
|
const keys = getProviderKeyState();
|
|
3288
|
-
return keys.hasOpenRouter || keys.directProviders.size > 0;
|
|
3456
|
+
return keys.hasOpenRouter || keys.hasBai || keys.directProviders.size > 0;
|
|
3289
3457
|
}
|
|
3290
3458
|
var PROVIDER_FLAGSHIP = {
|
|
3291
3459
|
anthropic: "opus-4-7",
|
|
@@ -3293,7 +3461,10 @@ var PROVIDER_FLAGSHIP = {
|
|
|
3293
3461
|
google: "gemini-3-flash",
|
|
3294
3462
|
xai: "grok-4-3",
|
|
3295
3463
|
deepseek: "deepseek-v4-pro",
|
|
3464
|
+
zhipu: "glm-5-1",
|
|
3465
|
+
moonshot: "kimi-2-6",
|
|
3296
3466
|
openrouter: "opus-4-7",
|
|
3467
|
+
bai: "opus-4-7",
|
|
3297
3468
|
brave: null,
|
|
3298
3469
|
tavily: null,
|
|
3299
3470
|
minimax: null,
|
|
@@ -3305,7 +3476,13 @@ var PROVIDER_FAST = {
|
|
|
3305
3476
|
google: "gemini-3-1-flash",
|
|
3306
3477
|
xai: "grok-4-1-fast",
|
|
3307
3478
|
deepseek: "deepseek-v4-flash",
|
|
3479
|
+
// GLM / Kimi · no separate fast/flash tier in our registry yet, so
|
|
3480
|
+
// both providers' "fast pick" falls back to the same flagship that
|
|
3481
|
+
// PROVIDER_FLAGSHIP names. Reachability-via-OR/B.AI carries it.
|
|
3482
|
+
zhipu: "glm-5-1",
|
|
3483
|
+
moonshot: "kimi-2-6",
|
|
3308
3484
|
openrouter: "opus-4-6-fast",
|
|
3485
|
+
bai: "haiku-4-5",
|
|
3309
3486
|
brave: null,
|
|
3310
3487
|
tavily: null,
|
|
3311
3488
|
minimax: null,
|
|
@@ -3321,6 +3498,21 @@ var FAST_POOL_BY_CARRIER = {
|
|
|
3321
3498
|
"grok-4-1-fast",
|
|
3322
3499
|
"deepseek-v4-flash"
|
|
3323
3500
|
],
|
|
3501
|
+
// B.AI carries the same brand-spanning fast catalog as OpenRouter ·
|
|
3502
|
+
// identical pool gives a B.AI-only user the same visibly-mixed
|
|
3503
|
+
// director cast (different brand badges per seat) that the OpenRouter
|
|
3504
|
+
// path produces. Members are filtered against reachability inside
|
|
3505
|
+
// `pickRandomFastModel`, so models without a baiId fall out naturally
|
|
3506
|
+
// if B.AI ends up not carrying one of them in practice.
|
|
3507
|
+
bai: [
|
|
3508
|
+
"opus-4-6-fast",
|
|
3509
|
+
"haiku-4-5",
|
|
3510
|
+
"gpt-5-4-mini",
|
|
3511
|
+
"gemini-3-flash",
|
|
3512
|
+
"gemini-3-1-flash",
|
|
3513
|
+
"grok-4-1-fast",
|
|
3514
|
+
"deepseek-v4-flash"
|
|
3515
|
+
],
|
|
3324
3516
|
anthropic: ["opus-4-6-fast", "haiku-4-5"],
|
|
3325
3517
|
openai: ["gpt-5-4-mini"],
|
|
3326
3518
|
google: ["gemini-3-flash", "gemini-3-1-flash"],
|
|
@@ -3348,7 +3540,10 @@ var FLAGSHIP_TIER = /* @__PURE__ */ new Set([
|
|
|
3348
3540
|
// xAI
|
|
3349
3541
|
"grok-4-3",
|
|
3350
3542
|
// DeepSeek
|
|
3351
|
-
"deepseek-v4-pro"
|
|
3543
|
+
"deepseek-v4-pro",
|
|
3544
|
+
// Zhipu · Moonshot · single flagship each (both OR + B.AI routed).
|
|
3545
|
+
"glm-5-1",
|
|
3546
|
+
"kimi-2-6"
|
|
3352
3547
|
]);
|
|
3353
3548
|
function effectiveDefaultModel() {
|
|
3354
3549
|
const prefs = getPrefs();
|
|
@@ -3378,6 +3573,12 @@ function defaultModelFor(keys = getProviderKeyState()) {
|
|
|
3378
3573
|
const opus = reachable.find((m) => m.modelV === "opus-4-7");
|
|
3379
3574
|
if (opus) return opus.modelV;
|
|
3380
3575
|
}
|
|
3576
|
+
if (keys.hasBai) {
|
|
3577
|
+
const fast = reachable.find((m) => m.modelV === "haiku-4-5");
|
|
3578
|
+
if (fast) return fast.modelV;
|
|
3579
|
+
const opus = reachable.find((m) => m.modelV === "opus-4-7");
|
|
3580
|
+
if (opus) return opus.modelV;
|
|
3581
|
+
}
|
|
3381
3582
|
for (const provider of keys.directProviders) {
|
|
3382
3583
|
const fast = PROVIDER_FAST[provider];
|
|
3383
3584
|
if (fast && reachable.find((m) => m.modelV === fast)) return fast;
|
|
@@ -3390,6 +3591,8 @@ function defaultModelFor(keys = getProviderKeyState()) {
|
|
|
3390
3591
|
}
|
|
3391
3592
|
var CHEAP_BY_CARRIER = {
|
|
3392
3593
|
openrouter: "haiku-4-5",
|
|
3594
|
+
bai: "haiku-4-5",
|
|
3595
|
+
// B.AI carries Haiku 4.5 (claude-haiku-4-5)
|
|
3393
3596
|
anthropic: "sonnet-4-6",
|
|
3394
3597
|
// only direct-routable Claude
|
|
3395
3598
|
openai: "gpt-5-4-mini",
|
|
@@ -6905,7 +7108,7 @@ function agentsRouter() {
|
|
|
6905
7108
|
patch.carrierPref = null;
|
|
6906
7109
|
} else if (typeof b.carrierPref === "string") {
|
|
6907
7110
|
const v = b.carrierPref.trim();
|
|
6908
|
-
const allowed = /* @__PURE__ */ new Set(["openrouter", "anthropic", "openai", "google", "xai"]);
|
|
7111
|
+
const allowed = /* @__PURE__ */ new Set(["openrouter", "bai", "anthropic", "openai", "google", "xai"]);
|
|
6909
7112
|
if (!allowed.has(v)) {
|
|
6910
7113
|
return c.json({ error: `unknown carrier: ${v}` }, 400);
|
|
6911
7114
|
}
|
|
@@ -14437,6 +14640,7 @@ function defaultVoiceForProvider(provider) {
|
|
|
14437
14640
|
// src/routes/keys.ts
|
|
14438
14641
|
var PROVIDERS = /* @__PURE__ */ new Set([
|
|
14439
14642
|
"openrouter",
|
|
14643
|
+
"bai",
|
|
14440
14644
|
"anthropic",
|
|
14441
14645
|
"openai",
|
|
14442
14646
|
"google",
|
|
@@ -14449,6 +14653,7 @@ var PROVIDERS = /* @__PURE__ */ new Set([
|
|
|
14449
14653
|
]);
|
|
14450
14654
|
var LLM_PROVIDERS = /* @__PURE__ */ new Set([
|
|
14451
14655
|
"openrouter",
|
|
14656
|
+
"bai",
|
|
14452
14657
|
"anthropic",
|
|
14453
14658
|
"openai",
|
|
14454
14659
|
"google",
|
|
@@ -22570,7 +22775,7 @@ function voicesRouter() {
|
|
|
22570
22775
|
init_paths();
|
|
22571
22776
|
|
|
22572
22777
|
// src/version.ts
|
|
22573
|
-
var VERSION = "0.1.
|
|
22778
|
+
var VERSION = "0.1.21";
|
|
22574
22779
|
|
|
22575
22780
|
// src/server.ts
|
|
22576
22781
|
function createApp() {
|