@bankr/cli 0.3.23 → 0.3.32

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.
@@ -20,6 +20,15 @@ const IMAGE_INPUT = ["text", "image"];
20
20
  const TEXT_INPUT = ["text"];
21
21
  const GATEWAY_MODELS = [
22
22
  // Claude
23
+ {
24
+ id: "claude-fable-5.1",
25
+ name: "Claude Fable 5.1",
26
+ owned_by: "anthropic",
27
+ contextWindow: 1000000,
28
+ maxTokens: 128000,
29
+ input: IMAGE_INPUT,
30
+ cost: { input: 10.0, output: 50.0, cacheRead: 0.25, cacheWrite: 12.5 },
31
+ },
23
32
  {
24
33
  id: "claude-fable-5",
25
34
  name: "Claude Fable 5",
@@ -29,6 +38,15 @@ const GATEWAY_MODELS = [
29
38
  input: IMAGE_INPUT,
30
39
  cost: { input: 10.0, output: 50.0, cacheRead: 1.0, cacheWrite: 12.5 },
31
40
  },
41
+ {
42
+ id: "claude-opus-5",
43
+ name: "Claude Opus 5",
44
+ owned_by: "anthropic",
45
+ contextWindow: 1000000,
46
+ maxTokens: 128000,
47
+ input: IMAGE_INPUT,
48
+ cost: { input: 5.0, output: 25.0, cacheRead: 0.5, cacheWrite: 6.25 },
49
+ },
32
50
  {
33
51
  id: "claude-opus-4.8",
34
52
  name: "Claude Opus 4.8",
@@ -65,6 +83,15 @@ const GATEWAY_MODELS = [
65
83
  input: IMAGE_INPUT,
66
84
  cost: { input: 5.0, output: 25.0, cacheRead: 0.5, cacheWrite: 6.25 },
67
85
  },
86
+ {
87
+ id: "claude-sonnet-5",
88
+ name: "Claude Sonnet 5",
89
+ owned_by: "anthropic",
90
+ contextWindow: 1000000,
91
+ maxTokens: 128000,
92
+ input: IMAGE_INPUT,
93
+ cost: { input: 2.0, output: 10.0, cacheRead: 0.2, cacheWrite: 2.5 },
94
+ },
68
95
  {
69
96
  id: "claude-sonnet-4.6",
70
97
  name: "Claude Sonnet 4.6",
@@ -94,40 +121,49 @@ const GATEWAY_MODELS = [
94
121
  },
95
122
  // Gemini
96
123
  {
97
- id: "gemini-3.6-flash",
98
- name: "Gemini 3.6 Flash",
124
+ id: "gemini-3.8-flash",
125
+ name: "Gemini 3.8 Flash",
99
126
  owned_by: "google",
100
127
  contextWindow: 1048576,
101
128
  maxTokens: 65536,
102
129
  input: IMAGE_INPUT,
103
- cost: { input: 1.5, output: 7.5, cacheRead: 0.15, cacheWrite: 0.08333 },
130
+ cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.04167 },
104
131
  },
105
132
  {
106
- id: "gemini-3.5-flash-lite",
107
- name: "Gemini 3.5 Flash Lite",
133
+ id: "gemini-3.7-flash",
134
+ name: "Gemini 3.7 Flash",
108
135
  owned_by: "google",
109
136
  contextWindow: 1048576,
110
137
  maxTokens: 65536,
111
138
  input: IMAGE_INPUT,
112
- cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.08333 },
139
+ cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.04167 },
113
140
  },
114
141
  {
115
- id: "gemini-3.1-pro",
116
- name: "Gemini 3.1 Pro",
142
+ id: "gemini-3.6-flash",
143
+ name: "Gemini 3.6 Flash",
117
144
  owned_by: "google",
118
145
  contextWindow: 1048576,
119
146
  maxTokens: 65536,
120
147
  input: IMAGE_INPUT,
121
- cost: { input: 2.0, output: 12.0, cacheRead: 0.2, cacheWrite: 0.375 },
148
+ cost: { input: 0.75, output: 3.75, cacheRead: 0.075, cacheWrite: 0.04167 },
122
149
  },
123
150
  {
124
- id: "gemini-3.1-flash-lite",
125
- name: "Gemini 3.1 Flash Lite",
151
+ id: "gemini-3.5-flash",
152
+ name: "Gemini 3.5 Flash",
126
153
  owned_by: "google",
127
154
  contextWindow: 1048576,
128
155
  maxTokens: 65536,
129
156
  input: IMAGE_INPUT,
130
- cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.08333 },
157
+ cost: { input: 1.5, output: 9.0, cacheRead: 0.15, cacheWrite: 0.08333 },
158
+ },
159
+ {
160
+ id: "gemini-3.1-pro",
161
+ name: "Gemini 3.1 Pro",
162
+ owned_by: "google",
163
+ contextWindow: 1048576,
164
+ maxTokens: 65536,
165
+ input: IMAGE_INPUT,
166
+ cost: { input: 2.0, output: 12.0, cacheRead: 0.2, cacheWrite: 0.375 },
131
167
  },
132
168
  {
133
169
  id: "gemini-3-flash",
@@ -156,7 +192,62 @@ const GATEWAY_MODELS = [
156
192
  input: IMAGE_INPUT,
157
193
  cost: { input: 0.3, output: 2.5, cacheRead: 0.03, cacheWrite: 0.0833 },
158
194
  },
195
+ // Gemma
196
+ {
197
+ id: "gemma-4-31b-it",
198
+ name: "Gemma 4 31B IT",
199
+ owned_by: "google",
200
+ contextWindow: 262144,
201
+ maxTokens: 131072,
202
+ input: IMAGE_INPUT,
203
+ cost: { input: 0.14, output: 0.4, cacheRead: 0, cacheWrite: 0 },
204
+ },
205
+ {
206
+ id: "gemma-4-26b-a4b-it",
207
+ name: "Gemma 4 26B A4B IT",
208
+ owned_by: "google",
209
+ contextWindow: 262144,
210
+ maxTokens: 262144,
211
+ input: IMAGE_INPUT,
212
+ cost: { input: 0.15, output: 0.6, cacheRead: 0, cacheWrite: 0 },
213
+ },
159
214
  // OpenAI
215
+ {
216
+ id: "gpt-6-astra",
217
+ name: "GPT 6 Astra",
218
+ owned_by: "openai",
219
+ contextWindow: 1050000,
220
+ maxTokens: 128000,
221
+ input: IMAGE_INPUT,
222
+ cost: { input: 10.0, output: 50.0, cacheRead: 1.0, cacheWrite: 12.5 },
223
+ },
224
+ {
225
+ id: "gpt-5.6-sol",
226
+ name: "GPT 5.6 Sol",
227
+ owned_by: "openai",
228
+ contextWindow: 1050000,
229
+ maxTokens: 128000,
230
+ input: IMAGE_INPUT,
231
+ cost: { input: 4.0, output: 20.0, cacheRead: 0.4, cacheWrite: 5.0 },
232
+ },
233
+ {
234
+ id: "gpt-5.6-terra",
235
+ name: "GPT 5.6 Terra",
236
+ owned_by: "openai",
237
+ contextWindow: 1050000,
238
+ maxTokens: 128000,
239
+ input: IMAGE_INPUT,
240
+ cost: { input: 2.0, output: 12.0, cacheRead: 0.2, cacheWrite: 2.5 },
241
+ },
242
+ {
243
+ id: "gpt-5.6-luna",
244
+ name: "GPT 5.6 Luna",
245
+ owned_by: "openai",
246
+ contextWindow: 1050000,
247
+ maxTokens: 128000,
248
+ input: IMAGE_INPUT,
249
+ cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 },
250
+ },
160
251
  {
161
252
  id: "gpt-image-2",
162
253
  name: "GPT Image 2",
@@ -242,6 +333,33 @@ const GATEWAY_MODELS = [
242
333
  cost: { input: 0.05, output: 0.4, cacheRead: 0.005, cacheWrite: 0 },
243
334
  },
244
335
  // Other providers
336
+ {
337
+ id: "grok-4.6",
338
+ name: "Grok 4.6",
339
+ owned_by: "x-ai",
340
+ contextWindow: 500000,
341
+ maxTokens: 500000,
342
+ input: IMAGE_INPUT,
343
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.5, cacheWrite: 0 },
344
+ },
345
+ {
346
+ id: "grok-4.5",
347
+ name: "Grok 4.5",
348
+ owned_by: "x-ai",
349
+ contextWindow: 500000,
350
+ maxTokens: 500000,
351
+ input: IMAGE_INPUT,
352
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.3, cacheWrite: 0 },
353
+ },
354
+ {
355
+ id: "grok-4.20",
356
+ name: "Grok 4.20",
357
+ owned_by: "x-ai",
358
+ contextWindow: 2000000,
359
+ maxTokens: 2000000,
360
+ input: IMAGE_INPUT,
361
+ cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 },
362
+ },
245
363
  {
246
364
  id: "grok-4.3",
247
365
  name: "Grok 4.3",
@@ -259,6 +377,39 @@ const GATEWAY_MODELS = [
259
377
  maxTokens: 30000,
260
378
  input: TEXT_INPUT,
261
379
  cost: { input: 0.2, output: 0.5, cacheRead: 0.05, cacheWrite: 0 },
380
+ // Hard-deprecated in the seed — the gateway 410s it. Without this the
381
+ // offline catalog would advertise it as active.
382
+ deprecation: {
383
+ replaced_by: "grok-4.3",
384
+ removed_at: "2026-06-17T00:00:00.000Z",
385
+ },
386
+ },
387
+ {
388
+ id: "deepseek-v4-pro-0813",
389
+ name: "DeepSeek V4 Pro 0813",
390
+ owned_by: "deepseek",
391
+ contextWindow: 1048576,
392
+ maxTokens: 384000,
393
+ input: TEXT_INPUT,
394
+ cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0 },
395
+ },
396
+ {
397
+ id: "deepseek-v4-pro",
398
+ name: "DeepSeek V4 Pro",
399
+ owned_by: "deepseek",
400
+ contextWindow: 1048576,
401
+ maxTokens: 384000,
402
+ input: TEXT_INPUT,
403
+ cost: { input: 0.435, output: 0.87, cacheRead: 0.003625, cacheWrite: 0 },
404
+ },
405
+ {
406
+ id: "deepseek-v4-flash",
407
+ name: "DeepSeek V4 Flash",
408
+ owned_by: "deepseek",
409
+ contextWindow: 1048576,
410
+ maxTokens: 384000,
411
+ input: TEXT_INPUT,
412
+ cost: { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 },
262
413
  },
263
414
  {
264
415
  id: "deepseek-v3.2",
@@ -269,6 +420,42 @@ const GATEWAY_MODELS = [
269
420
  input: TEXT_INPUT,
270
421
  cost: { input: 0.26, output: 0.38, cacheRead: 0.13, cacheWrite: 0 },
271
422
  },
423
+ {
424
+ id: "qwen3.8-max",
425
+ name: "Qwen3.8 Max",
426
+ owned_by: "qwen",
427
+ contextWindow: 1000000,
428
+ maxTokens: 131072,
429
+ input: IMAGE_INPUT,
430
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.25, cacheWrite: 2.5 },
431
+ },
432
+ {
433
+ id: "qwen3.8-flash",
434
+ name: "Qwen3.8 Flash",
435
+ owned_by: "qwen",
436
+ contextWindow: 1000000,
437
+ maxTokens: 131072,
438
+ input: IMAGE_INPUT,
439
+ cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 },
440
+ },
441
+ {
442
+ id: "qwen3.7-max",
443
+ name: "Qwen3.7 Max",
444
+ owned_by: "qwen",
445
+ contextWindow: 1000000,
446
+ maxTokens: 65536,
447
+ input: TEXT_INPUT,
448
+ cost: { input: 2.5, output: 7.5, cacheRead: 0.25, cacheWrite: 0 },
449
+ },
450
+ {
451
+ id: "qwen3.7-flash",
452
+ name: "Qwen3.7 Flash",
453
+ owned_by: "qwen",
454
+ contextWindow: 1000000,
455
+ maxTokens: 65536,
456
+ input: IMAGE_INPUT,
457
+ cost: { input: 0.1, output: 0.4, cacheRead: 0.02, cacheWrite: 0.125 },
458
+ },
272
459
  {
273
460
  id: "qwen3-coder",
274
461
  name: "Qwen3 Coder",
@@ -276,7 +463,7 @@ const GATEWAY_MODELS = [
276
463
  contextWindow: 262144,
277
464
  maxTokens: 65536,
278
465
  input: TEXT_INPUT,
279
- cost: { input: 0.12, output: 0.75, cacheRead: 0.06, cacheWrite: 0 },
466
+ cost: { input: 0.3, output: 1.5, cacheRead: 0.06, cacheWrite: 0 },
280
467
  },
281
468
  {
282
469
  id: "qwen3.7-plus",
@@ -294,7 +481,7 @@ const GATEWAY_MODELS = [
294
481
  contextWindow: 1000000,
295
482
  maxTokens: 65536,
296
483
  input: TEXT_INPUT,
297
- cost: { input: 0.25, output: 1.5, cacheRead: 0, cacheWrite: 0 },
484
+ cost: { input: 0.1875, output: 1.125, cacheRead: 0, cacheWrite: 0.234375 },
298
485
  },
299
486
  {
300
487
  id: "qwen3.5-plus",
@@ -312,7 +499,7 @@ const GATEWAY_MODELS = [
312
499
  contextWindow: 1000000,
313
500
  maxTokens: 65536,
314
501
  input: TEXT_INPUT,
315
- cost: { input: 0.1, output: 0.4, cacheRead: 0, cacheWrite: 0 },
502
+ cost: { input: 0.065, output: 0.26, cacheRead: 0, cacheWrite: 0 },
316
503
  },
317
504
  {
318
505
  id: "kimi-k3",
@@ -348,7 +535,16 @@ const GATEWAY_MODELS = [
348
535
  contextWindow: 262144,
349
536
  maxTokens: 65535,
350
537
  input: TEXT_INPUT,
351
- cost: { input: 0.45, output: 2.2, cacheRead: 0.225, cacheWrite: 0 },
538
+ cost: { input: 0.6, output: 3.0, cacheRead: 0.1, cacheWrite: 0 },
539
+ },
540
+ {
541
+ id: "minimax-m3",
542
+ name: "MiniMax M3",
543
+ owned_by: "minimax",
544
+ contextWindow: 524288,
545
+ maxTokens: 524288,
546
+ input: IMAGE_INPUT,
547
+ cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
352
548
  },
353
549
  {
354
550
  id: "minimax-m2.5",
@@ -377,6 +573,42 @@ const GATEWAY_MODELS = [
377
573
  input: TEXT_INPUT,
378
574
  cost: { input: 0.6, output: 2.4, cacheRead: 0.06, cacheWrite: 0 },
379
575
  },
576
+ {
577
+ id: "glm-5.3-flash",
578
+ name: "GLM-5.3 Flash",
579
+ owned_by: "z-ai",
580
+ contextWindow: 1048576,
581
+ maxTokens: 131072,
582
+ input: IMAGE_INPUT,
583
+ cost: { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 },
584
+ },
585
+ {
586
+ id: "glm-5.3",
587
+ name: "GLM-5.3",
588
+ owned_by: "z-ai",
589
+ contextWindow: 1048576,
590
+ maxTokens: 131072,
591
+ input: TEXT_INPUT,
592
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
593
+ },
594
+ {
595
+ id: "glm-5.2",
596
+ name: "GLM-5.2",
597
+ owned_by: "z-ai",
598
+ contextWindow: 1048576,
599
+ maxTokens: 131072,
600
+ input: TEXT_INPUT,
601
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
602
+ },
603
+ {
604
+ id: "glm-5.1",
605
+ name: "GLM-5.1",
606
+ owned_by: "z-ai",
607
+ contextWindow: 202800,
608
+ maxTokens: 202800,
609
+ input: TEXT_INPUT,
610
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
611
+ },
380
612
  {
381
613
  id: "glm-5",
382
614
  name: "GLM-5",
@@ -384,7 +616,7 @@ const GATEWAY_MODELS = [
384
616
  contextWindow: 202752,
385
617
  maxTokens: 131072,
386
618
  input: TEXT_INPUT,
387
- cost: { input: 0.72, output: 2.3, cacheRead: 0, cacheWrite: 0 },
619
+ cost: { input: 1.0, output: 3.2, cacheRead: 0.2, cacheWrite: 0 },
388
620
  },
389
621
  {
390
622
  id: "glm-5-turbo",
@@ -616,8 +848,7 @@ export async function modelsCommand(opts = {}) {
616
848
  export async function creditsCommand() {
617
849
  const llmKey = getLlmKey();
618
850
  if (!llmKey) {
619
- output.error("Not authenticated. Run `bankr login` first.");
620
- process.exit(1);
851
+ output.fatal("Not authenticated. Run `bankr login` first.");
621
852
  }
622
853
  const llmUrl = getLlmUrl();
623
854
  const spin = output.spinner("Fetching credit balance…");
@@ -636,12 +867,10 @@ export async function creditsCommand() {
636
867
  return;
637
868
  }
638
869
  if (res.status === 401 || res.status === 403) {
639
- output.error("Authentication failed. Check your API key or run: bankr login");
640
- process.exit(1);
870
+ output.fatal("Authentication failed. Check your API key or run: bankr login");
641
871
  }
642
872
  if (!res.ok) {
643
- output.error(`Failed to fetch credits (HTTP ${res.status})`);
644
- process.exit(1);
873
+ output.fatal(`Failed to fetch credits (HTTP ${res.status})`);
645
874
  }
646
875
  const body = (await res.json());
647
876
  output.brandBold("Bankr LLM Gateway — Credits");
@@ -652,8 +881,7 @@ export async function creditsCommand() {
652
881
  }
653
882
  catch (err) {
654
883
  spin.stop();
655
- output.error(`Failed to fetch credits: ${getErrorMessage(err)}`);
656
- process.exit(1);
884
+ output.fatal(`Failed to fetch credits: ${getErrorMessage(err)}`);
657
885
  }
658
886
  }
659
887
  /* ─────────────────────── bankr llm credits add ──────────────────────────── */
@@ -748,8 +976,7 @@ export async function creditsAddCommand(amount, opts) {
748
976
  // Validate amount
749
977
  const amountUsd = Number(amount);
750
978
  if (Number.isNaN(amountUsd) || amountUsd < 1 || amountUsd > 1000) {
751
- output.error("Amount must be between $1 and $1,000");
752
- process.exit(1);
979
+ output.fatal("Amount must be between $1 and $1,000");
753
980
  }
754
981
  // Fetch current balance for display (skip when --yes/--not-interactive since user won't see it)
755
982
  let currentBalance = "unknown";
@@ -790,8 +1017,7 @@ export async function creditsAddCommand(amount, opts) {
790
1017
  output.warn(`Could not fetch balances: ${getErrorMessage(err)}`);
791
1018
  }
792
1019
  if (!resolved) {
793
- output.error(`Token "${opts.token}" not found in your wallet on any supported chain.`);
794
- process.exit(1);
1020
+ output.fatal(`Token "${opts.token}" not found in your wallet on any supported chain.`);
795
1021
  }
796
1022
  }
797
1023
  const targetChain = resolved?.chain ?? "base";
@@ -838,22 +1064,18 @@ export async function creditsAddCommand(amount, opts) {
838
1064
  spin.stop();
839
1065
  if (res.status === 402) {
840
1066
  const errBody = (await res.json().catch(() => ({})));
841
- output.error(errBody.error ??
1067
+ output.fatal(errBody.error ??
842
1068
  "Insufficient wallet balance. Add funds to your wallet first.");
843
- process.exit(1);
844
1069
  }
845
1070
  if (res.status === 403) {
846
- output.error(ERR_LLM_NOT_ENABLED);
847
- process.exit(1);
1071
+ output.fatal(ERR_LLM_NOT_ENABLED);
848
1072
  }
849
1073
  if (res.status === 502) {
850
- output.error("Token swap failed. Try USDC or a different token.");
851
- process.exit(1);
1074
+ output.fatal("Token swap failed. Try USDC or a different token.");
852
1075
  }
853
1076
  if (!res.ok) {
854
1077
  const errBody = (await res.json().catch(() => ({})));
855
- output.error(errBody.error ?? `Failed to add credits (HTTP ${res.status})`);
856
- process.exit(1);
1078
+ output.fatal(errBody.error ?? `Failed to add credits (HTTP ${res.status})`);
857
1079
  }
858
1080
  const result = (await res.json());
859
1081
  console.log();
@@ -865,8 +1087,7 @@ export async function creditsAddCommand(amount, opts) {
865
1087
  }
866
1088
  catch (err) {
867
1089
  spin.stop();
868
- output.error(`Failed to add credits: ${getErrorMessage(err)}`);
869
- process.exit(1);
1090
+ output.fatal(`Failed to add credits: ${getErrorMessage(err)}`);
870
1091
  }
871
1092
  }
872
1093
  function formatTimeAgo(dateStr) {
@@ -907,12 +1128,10 @@ export async function creditsAutoCommand(opts) {
907
1128
  });
908
1129
  spin.stop();
909
1130
  if (res.status === 403) {
910
- output.error(ERR_LLM_NOT_ENABLED);
911
- process.exit(1);
1131
+ output.fatal(ERR_LLM_NOT_ENABLED);
912
1132
  }
913
1133
  if (!res.ok) {
914
- output.error(`Failed to fetch config (HTTP ${res.status})`);
915
- process.exit(1);
1134
+ output.fatal(`Failed to fetch config (HTTP ${res.status})`);
916
1135
  }
917
1136
  const { config } = (await res.json());
918
1137
  output.brandBold("Bankr LLM Gateway — Auto Top-Up");
@@ -927,15 +1146,13 @@ export async function creditsAutoCommand(opts) {
927
1146
  }
928
1147
  catch (err) {
929
1148
  spin.stop();
930
- output.error(`Failed to fetch config: ${getErrorMessage(err)}`);
931
- process.exit(1);
1149
+ output.fatal(`Failed to fetch config: ${getErrorMessage(err)}`);
932
1150
  }
933
1151
  return;
934
1152
  }
935
1153
  // POST update config
936
1154
  if (opts.enable && opts.disable) {
937
- output.error("Cannot use --enable and --disable together");
938
- process.exit(1);
1155
+ output.fatal("Cannot use --enable and --disable together");
939
1156
  }
940
1157
  const body = {};
941
1158
  if (opts.disable) {
@@ -951,16 +1168,14 @@ export async function creditsAutoCommand(opts) {
951
1168
  if (opts.amount) {
952
1169
  const amt = Number(opts.amount);
953
1170
  if (Number.isNaN(amt) || amt < 1 || amt > 1000) {
954
- output.error("Amount must be between $1 and $1,000");
955
- process.exit(1);
1171
+ output.fatal("Amount must be between $1 and $1,000");
956
1172
  }
957
1173
  body.amountUsd = amt;
958
1174
  }
959
1175
  if (opts.threshold) {
960
1176
  const thr = Number(opts.threshold);
961
1177
  if (Number.isNaN(thr) || thr < 1 || thr > 500) {
962
- output.error("Threshold must be between $1 and $500");
963
- process.exit(1);
1178
+ output.fatal("Threshold must be between $1 and $500");
964
1179
  }
965
1180
  body.thresholdUsd = thr;
966
1181
  }
@@ -972,8 +1187,7 @@ export async function creditsAutoCommand(opts) {
972
1187
  .map((s) => s.trim())
973
1188
  .filter(Boolean);
974
1189
  if (inputs.length === 0 || inputs.length > 3) {
975
- output.error("Provide 1-3 comma-separated token symbols or addresses");
976
- process.exit(1);
1190
+ output.fatal("Provide 1-3 comma-separated token symbols or addresses");
977
1191
  }
978
1192
  const resolved = [];
979
1193
  // Highest USD balance wins when the same symbol exists on multiple chains.
@@ -1004,8 +1218,7 @@ export async function creditsAutoCommand(opts) {
1004
1218
  }
1005
1219
  }
1006
1220
  if (resolved.length === 0) {
1007
- output.error("No valid tokens resolved. Check your token symbols.");
1008
- process.exit(1);
1221
+ output.fatal("No valid tokens resolved. Check your token symbols.");
1009
1222
  }
1010
1223
  body.tokens = resolved;
1011
1224
  }
@@ -1028,13 +1241,11 @@ export async function creditsAutoCommand(opts) {
1028
1241
  });
1029
1242
  spin.stop();
1030
1243
  if (res.status === 403) {
1031
- output.error(ERR_LLM_NOT_ENABLED);
1032
- process.exit(1);
1244
+ output.fatal(ERR_LLM_NOT_ENABLED);
1033
1245
  }
1034
1246
  if (!res.ok) {
1035
1247
  const errBody = (await res.json().catch(() => ({})));
1036
- output.error(errBody.error ?? `Failed to update config (HTTP ${res.status})`);
1037
- process.exit(1);
1248
+ output.fatal(errBody.error ?? `Failed to update config (HTTP ${res.status})`);
1038
1249
  }
1039
1250
  output.success(opts.disable ? "Auto top-up disabled" : "Auto top-up settings updated");
1040
1251
  // Show config from POST response (avoids extra GET round-trip)
@@ -1052,8 +1263,7 @@ export async function creditsAutoCommand(opts) {
1052
1263
  }
1053
1264
  catch (err) {
1054
1265
  spin.stop();
1055
- output.error(`Failed to update config: ${getErrorMessage(err)}`);
1056
- process.exit(1);
1266
+ output.fatal(`Failed to update config: ${getErrorMessage(err)}`);
1057
1267
  }
1058
1268
  }
1059
1269
  /* ──────────────────────── bankr llm setup openclaw ────────────────────────── */
@@ -1211,7 +1421,7 @@ export async function setupCursorCommand() {
1211
1421
  const { models } = await resolveModels();
1212
1422
  const activeModels = models.filter((m) => !m.deprecation);
1213
1423
  // Pick one model per provider as recommended examples
1214
- const recommendedIds = ["claude-fable-5", "gemini-3.1-pro", "gpt-5.5"];
1424
+ const recommendedIds = ["claude-fable-5.1", "gemini-3.1-pro", "gpt-5.5"];
1215
1425
  const recommended = recommendedIds.filter((id) => activeModels.some((m) => m.id === id));
1216
1426
  output.brandBold("Cursor — Bankr LLM Gateway");
1217
1427
  console.log();
@@ -1257,8 +1467,7 @@ export async function setupClaudeCodeCommand() {
1257
1467
  function requireAuth() {
1258
1468
  const llmKey = getLlmKey();
1259
1469
  if (!llmKey) {
1260
- output.error("Not authenticated. Run `bankr login` first.");
1261
- process.exit(1);
1470
+ output.fatal("Not authenticated. Run `bankr login` first.");
1262
1471
  }
1263
1472
  return llmKey;
1264
1473
  }
@@ -1298,8 +1507,8 @@ function fileContains(filePath, search) {
1298
1507
  * `--model` flag appears honored but the real request is a different
1299
1508
  * model. Any suffix (e.g. `[1m]` context tier) is preserved.
1300
1509
  */
1301
- function toAnthropicModelId(model) {
1302
- return model.replace(/^(claude-(?:opus|sonnet|haiku)-)(\d+)\.(\d+)(.*)$/, "$1$2-$3$4");
1510
+ export function toAnthropicModelId(model) {
1511
+ return model.replace(/^(claude-(?:opus|sonnet|haiku|fable)-)(\d+)\.(\d+)(.*)$/, "$1$2-$3$4");
1303
1512
  }
1304
1513
  function translateClaudeModelArgs(args) {
1305
1514
  const out = [...args];