@bankr/cli 0.3.23 → 0.3.35

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 },
149
+ },
150
+ {
151
+ id: "gemini-3.5-flash",
152
+ name: "Gemini 3.5 Flash",
153
+ owned_by: "google",
154
+ contextWindow: 1048576,
155
+ maxTokens: 65536,
156
+ input: IMAGE_INPUT,
157
+ cost: { input: 1.5, output: 9.0, cacheRead: 0.15, cacheWrite: 0.08333 },
122
158
  },
123
159
  {
124
- id: "gemini-3.1-flash-lite",
125
- name: "Gemini 3.1 Flash Lite",
160
+ id: "gemini-3.1-pro",
161
+ name: "Gemini 3.1 Pro",
126
162
  owned_by: "google",
127
163
  contextWindow: 1048576,
128
164
  maxTokens: 65536,
129
165
  input: IMAGE_INPUT,
130
- cost: { input: 0.25, output: 1.5, cacheRead: 0.025, cacheWrite: 0.08333 },
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,84 @@ 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-image-2.5-flare",
217
+ name: "GPT Image 2.5 Flare",
218
+ owned_by: "openai",
219
+ contextWindow: 400000,
220
+ maxTokens: 16384,
221
+ input: IMAGE_INPUT,
222
+ output: ["image"],
223
+ // Image model — served via /v1/images/generations; output rate is per
224
+ // million image tokens.
225
+ cost: { input: 5.0, output: 30.0, cacheRead: 1.25, cacheWrite: 0 },
226
+ },
227
+ {
228
+ id: "gpt-image-2.5-sunburst",
229
+ name: "GPT Image 2.5 Sunburst",
230
+ owned_by: "openai",
231
+ contextWindow: 400000,
232
+ maxTokens: 16384,
233
+ input: IMAGE_INPUT,
234
+ output: ["image"],
235
+ cost: { input: 5.0, output: 30.0, cacheRead: 1.25, cacheWrite: 0 },
236
+ },
237
+ {
238
+ id: "gpt-6-astra",
239
+ name: "GPT 6 Astra",
240
+ owned_by: "openai",
241
+ contextWindow: 1050000,
242
+ maxTokens: 128000,
243
+ input: IMAGE_INPUT,
244
+ cost: { input: 10.0, output: 50.0, cacheRead: 1.0, cacheWrite: 12.5 },
245
+ },
246
+ {
247
+ id: "gpt-5.6-sol",
248
+ name: "GPT 5.6 Sol",
249
+ owned_by: "openai",
250
+ contextWindow: 1050000,
251
+ maxTokens: 128000,
252
+ input: IMAGE_INPUT,
253
+ cost: { input: 4.0, output: 20.0, cacheRead: 0.4, cacheWrite: 5.0 },
254
+ },
255
+ {
256
+ id: "gpt-5.6-terra",
257
+ name: "GPT 5.6 Terra",
258
+ owned_by: "openai",
259
+ contextWindow: 1050000,
260
+ maxTokens: 128000,
261
+ input: IMAGE_INPUT,
262
+ cost: { input: 2.0, output: 12.0, cacheRead: 0.2, cacheWrite: 2.5 },
263
+ },
264
+ {
265
+ id: "gpt-5.6-luna",
266
+ name: "GPT 5.6 Luna",
267
+ owned_by: "openai",
268
+ contextWindow: 1050000,
269
+ maxTokens: 128000,
270
+ input: IMAGE_INPUT,
271
+ cost: { input: 0.2, output: 1.2, cacheRead: 0.02, cacheWrite: 0.25 },
272
+ },
160
273
  {
161
274
  id: "gpt-image-2",
162
275
  name: "GPT Image 2",
@@ -167,7 +280,7 @@ const GATEWAY_MODELS = [
167
280
  output: ["image"],
168
281
  // Image model — served via /v1/images/generations; output rate is per
169
282
  // million image tokens.
170
- cost: { input: 5.0, output: 30.0, cacheRead: 0, cacheWrite: 0 },
283
+ cost: { input: 5.0, output: 30.0, cacheRead: 1.25, cacheWrite: 0 },
171
284
  },
172
285
  {
173
286
  id: "gpt-5.5",
@@ -242,6 +355,33 @@ const GATEWAY_MODELS = [
242
355
  cost: { input: 0.05, output: 0.4, cacheRead: 0.005, cacheWrite: 0 },
243
356
  },
244
357
  // Other providers
358
+ {
359
+ id: "grok-4.6",
360
+ name: "Grok 4.6",
361
+ owned_by: "x-ai",
362
+ contextWindow: 500000,
363
+ maxTokens: 500000,
364
+ input: IMAGE_INPUT,
365
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.5, cacheWrite: 0 },
366
+ },
367
+ {
368
+ id: "grok-4.5",
369
+ name: "Grok 4.5",
370
+ owned_by: "x-ai",
371
+ contextWindow: 500000,
372
+ maxTokens: 500000,
373
+ input: IMAGE_INPUT,
374
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.3, cacheWrite: 0 },
375
+ },
376
+ {
377
+ id: "grok-4.20",
378
+ name: "Grok 4.20",
379
+ owned_by: "x-ai",
380
+ contextWindow: 2000000,
381
+ maxTokens: 2000000,
382
+ input: IMAGE_INPUT,
383
+ cost: { input: 1.25, output: 2.5, cacheRead: 0.2, cacheWrite: 0 },
384
+ },
245
385
  {
246
386
  id: "grok-4.3",
247
387
  name: "Grok 4.3",
@@ -259,6 +399,48 @@ const GATEWAY_MODELS = [
259
399
  maxTokens: 30000,
260
400
  input: TEXT_INPUT,
261
401
  cost: { input: 0.2, output: 0.5, cacheRead: 0.05, cacheWrite: 0 },
402
+ // Hard-deprecated in the seed — the gateway 410s it. Without this the
403
+ // offline catalog would advertise it as active.
404
+ deprecation: {
405
+ replaced_by: "grok-4.3",
406
+ removed_at: "2026-06-17T00:00:00.000Z",
407
+ },
408
+ },
409
+ {
410
+ id: "deepseek-v4.1-flash",
411
+ name: "DeepSeek V4.1 Flash",
412
+ owned_by: "deepseek",
413
+ contextWindow: 1048576,
414
+ maxTokens: 384000,
415
+ input: IMAGE_INPUT,
416
+ cost: { input: 0.3, output: 1.2, cacheRead: 0.006, cacheWrite: 0 },
417
+ },
418
+ {
419
+ id: "deepseek-v4-pro-0813",
420
+ name: "DeepSeek V4 Pro 0813",
421
+ owned_by: "deepseek",
422
+ contextWindow: 1048576,
423
+ maxTokens: 384000,
424
+ input: TEXT_INPUT,
425
+ cost: { input: 1.32, output: 3.96, cacheRead: 0.044, cacheWrite: 0 },
426
+ },
427
+ {
428
+ id: "deepseek-v4-pro",
429
+ name: "DeepSeek V4 Pro",
430
+ owned_by: "deepseek",
431
+ contextWindow: 1048576,
432
+ maxTokens: 384000,
433
+ input: TEXT_INPUT,
434
+ cost: { input: 0.435, output: 0.87, cacheRead: 0.003625, cacheWrite: 0 },
435
+ },
436
+ {
437
+ id: "deepseek-v4-flash",
438
+ name: "DeepSeek V4 Flash",
439
+ owned_by: "deepseek",
440
+ contextWindow: 1048576,
441
+ maxTokens: 384000,
442
+ input: TEXT_INPUT,
443
+ cost: { input: 0.14, output: 0.28, cacheRead: 0.0028, cacheWrite: 0 },
262
444
  },
263
445
  {
264
446
  id: "deepseek-v3.2",
@@ -269,6 +451,42 @@ const GATEWAY_MODELS = [
269
451
  input: TEXT_INPUT,
270
452
  cost: { input: 0.26, output: 0.38, cacheRead: 0.13, cacheWrite: 0 },
271
453
  },
454
+ {
455
+ id: "qwen3.8-max",
456
+ name: "Qwen3.8 Max",
457
+ owned_by: "qwen",
458
+ contextWindow: 1000000,
459
+ maxTokens: 131072,
460
+ input: IMAGE_INPUT,
461
+ cost: { input: 2.0, output: 6.0, cacheRead: 0.25, cacheWrite: 2.5 },
462
+ },
463
+ {
464
+ id: "qwen3.8-flash",
465
+ name: "Qwen3.8 Flash",
466
+ owned_by: "qwen",
467
+ contextWindow: 1000000,
468
+ maxTokens: 131072,
469
+ input: IMAGE_INPUT,
470
+ cost: { input: 0.15, output: 0.47, cacheRead: 0.016, cacheWrite: 0.2 },
471
+ },
472
+ {
473
+ id: "qwen3.7-max",
474
+ name: "Qwen3.7 Max",
475
+ owned_by: "qwen",
476
+ contextWindow: 1000000,
477
+ maxTokens: 65536,
478
+ input: TEXT_INPUT,
479
+ cost: { input: 2.5, output: 7.5, cacheRead: 0.25, cacheWrite: 0 },
480
+ },
481
+ {
482
+ id: "qwen3.7-flash",
483
+ name: "Qwen3.7 Flash",
484
+ owned_by: "qwen",
485
+ contextWindow: 1000000,
486
+ maxTokens: 65536,
487
+ input: IMAGE_INPUT,
488
+ cost: { input: 0.1, output: 0.4, cacheRead: 0.02, cacheWrite: 0.125 },
489
+ },
272
490
  {
273
491
  id: "qwen3-coder",
274
492
  name: "Qwen3 Coder",
@@ -276,7 +494,7 @@ const GATEWAY_MODELS = [
276
494
  contextWindow: 262144,
277
495
  maxTokens: 65536,
278
496
  input: TEXT_INPUT,
279
- cost: { input: 0.12, output: 0.75, cacheRead: 0.06, cacheWrite: 0 },
497
+ cost: { input: 0.3, output: 1.5, cacheRead: 0.06, cacheWrite: 0 },
280
498
  },
281
499
  {
282
500
  id: "qwen3.7-plus",
@@ -294,7 +512,7 @@ const GATEWAY_MODELS = [
294
512
  contextWindow: 1000000,
295
513
  maxTokens: 65536,
296
514
  input: TEXT_INPUT,
297
- cost: { input: 0.25, output: 1.5, cacheRead: 0, cacheWrite: 0 },
515
+ cost: { input: 0.1875, output: 1.125, cacheRead: 0, cacheWrite: 0.234375 },
298
516
  },
299
517
  {
300
518
  id: "qwen3.5-plus",
@@ -312,7 +530,7 @@ const GATEWAY_MODELS = [
312
530
  contextWindow: 1000000,
313
531
  maxTokens: 65536,
314
532
  input: TEXT_INPUT,
315
- cost: { input: 0.1, output: 0.4, cacheRead: 0, cacheWrite: 0 },
533
+ cost: { input: 0.065, output: 0.26, cacheRead: 0, cacheWrite: 0 },
316
534
  },
317
535
  {
318
536
  id: "kimi-k3",
@@ -348,7 +566,16 @@ const GATEWAY_MODELS = [
348
566
  contextWindow: 262144,
349
567
  maxTokens: 65535,
350
568
  input: TEXT_INPUT,
351
- cost: { input: 0.45, output: 2.2, cacheRead: 0.225, cacheWrite: 0 },
569
+ cost: { input: 0.6, output: 3.0, cacheRead: 0.1, cacheWrite: 0 },
570
+ },
571
+ {
572
+ id: "minimax-m3",
573
+ name: "MiniMax M3",
574
+ owned_by: "minimax",
575
+ contextWindow: 524288,
576
+ maxTokens: 524288,
577
+ input: IMAGE_INPUT,
578
+ cost: { input: 0.3, output: 1.2, cacheRead: 0.06, cacheWrite: 0 },
352
579
  },
353
580
  {
354
581
  id: "minimax-m2.5",
@@ -377,6 +604,42 @@ const GATEWAY_MODELS = [
377
604
  input: TEXT_INPUT,
378
605
  cost: { input: 0.6, output: 2.4, cacheRead: 0.06, cacheWrite: 0 },
379
606
  },
607
+ {
608
+ id: "glm-5.3-flash",
609
+ name: "GLM-5.3 Flash",
610
+ owned_by: "z-ai",
611
+ contextWindow: 1048576,
612
+ maxTokens: 131072,
613
+ input: IMAGE_INPUT,
614
+ cost: { input: 0.15, output: 0.5, cacheRead: 0.03, cacheWrite: 0 },
615
+ },
616
+ {
617
+ id: "glm-5.3",
618
+ name: "GLM-5.3",
619
+ owned_by: "z-ai",
620
+ contextWindow: 1048576,
621
+ maxTokens: 131072,
622
+ input: TEXT_INPUT,
623
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
624
+ },
625
+ {
626
+ id: "glm-5.2",
627
+ name: "GLM-5.2",
628
+ owned_by: "z-ai",
629
+ contextWindow: 1048576,
630
+ maxTokens: 131072,
631
+ input: TEXT_INPUT,
632
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
633
+ },
634
+ {
635
+ id: "glm-5.1",
636
+ name: "GLM-5.1",
637
+ owned_by: "z-ai",
638
+ contextWindow: 202800,
639
+ maxTokens: 202800,
640
+ input: TEXT_INPUT,
641
+ cost: { input: 1.4, output: 4.4, cacheRead: 0.26, cacheWrite: 0 },
642
+ },
380
643
  {
381
644
  id: "glm-5",
382
645
  name: "GLM-5",
@@ -384,7 +647,7 @@ const GATEWAY_MODELS = [
384
647
  contextWindow: 202752,
385
648
  maxTokens: 131072,
386
649
  input: TEXT_INPUT,
387
- cost: { input: 0.72, output: 2.3, cacheRead: 0, cacheWrite: 0 },
650
+ cost: { input: 1.0, output: 3.2, cacheRead: 0.2, cacheWrite: 0 },
388
651
  },
389
652
  {
390
653
  id: "glm-5-turbo",
@@ -616,8 +879,7 @@ export async function modelsCommand(opts = {}) {
616
879
  export async function creditsCommand() {
617
880
  const llmKey = getLlmKey();
618
881
  if (!llmKey) {
619
- output.error("Not authenticated. Run `bankr login` first.");
620
- process.exit(1);
882
+ output.fatal("Not authenticated. Run `bankr login` first.");
621
883
  }
622
884
  const llmUrl = getLlmUrl();
623
885
  const spin = output.spinner("Fetching credit balance…");
@@ -636,12 +898,10 @@ export async function creditsCommand() {
636
898
  return;
637
899
  }
638
900
  if (res.status === 401 || res.status === 403) {
639
- output.error("Authentication failed. Check your API key or run: bankr login");
640
- process.exit(1);
901
+ output.fatal("Authentication failed. Check your API key or run: bankr login");
641
902
  }
642
903
  if (!res.ok) {
643
- output.error(`Failed to fetch credits (HTTP ${res.status})`);
644
- process.exit(1);
904
+ output.fatal(`Failed to fetch credits (HTTP ${res.status})`);
645
905
  }
646
906
  const body = (await res.json());
647
907
  output.brandBold("Bankr LLM Gateway — Credits");
@@ -652,8 +912,7 @@ export async function creditsCommand() {
652
912
  }
653
913
  catch (err) {
654
914
  spin.stop();
655
- output.error(`Failed to fetch credits: ${getErrorMessage(err)}`);
656
- process.exit(1);
915
+ output.fatal(`Failed to fetch credits: ${getErrorMessage(err)}`);
657
916
  }
658
917
  }
659
918
  /* ─────────────────────── bankr llm credits add ──────────────────────────── */
@@ -748,8 +1007,7 @@ export async function creditsAddCommand(amount, opts) {
748
1007
  // Validate amount
749
1008
  const amountUsd = Number(amount);
750
1009
  if (Number.isNaN(amountUsd) || amountUsd < 1 || amountUsd > 1000) {
751
- output.error("Amount must be between $1 and $1,000");
752
- process.exit(1);
1010
+ output.fatal("Amount must be between $1 and $1,000");
753
1011
  }
754
1012
  // Fetch current balance for display (skip when --yes/--not-interactive since user won't see it)
755
1013
  let currentBalance = "unknown";
@@ -790,8 +1048,7 @@ export async function creditsAddCommand(amount, opts) {
790
1048
  output.warn(`Could not fetch balances: ${getErrorMessage(err)}`);
791
1049
  }
792
1050
  if (!resolved) {
793
- output.error(`Token "${opts.token}" not found in your wallet on any supported chain.`);
794
- process.exit(1);
1051
+ output.fatal(`Token "${opts.token}" not found in your wallet on any supported chain.`);
795
1052
  }
796
1053
  }
797
1054
  const targetChain = resolved?.chain ?? "base";
@@ -838,22 +1095,18 @@ export async function creditsAddCommand(amount, opts) {
838
1095
  spin.stop();
839
1096
  if (res.status === 402) {
840
1097
  const errBody = (await res.json().catch(() => ({})));
841
- output.error(errBody.error ??
1098
+ output.fatal(errBody.error ??
842
1099
  "Insufficient wallet balance. Add funds to your wallet first.");
843
- process.exit(1);
844
1100
  }
845
1101
  if (res.status === 403) {
846
- output.error(ERR_LLM_NOT_ENABLED);
847
- process.exit(1);
1102
+ output.fatal(ERR_LLM_NOT_ENABLED);
848
1103
  }
849
1104
  if (res.status === 502) {
850
- output.error("Token swap failed. Try USDC or a different token.");
851
- process.exit(1);
1105
+ output.fatal("Token swap failed. Try USDC or a different token.");
852
1106
  }
853
1107
  if (!res.ok) {
854
1108
  const errBody = (await res.json().catch(() => ({})));
855
- output.error(errBody.error ?? `Failed to add credits (HTTP ${res.status})`);
856
- process.exit(1);
1109
+ output.fatal(errBody.error ?? `Failed to add credits (HTTP ${res.status})`);
857
1110
  }
858
1111
  const result = (await res.json());
859
1112
  console.log();
@@ -865,8 +1118,7 @@ export async function creditsAddCommand(amount, opts) {
865
1118
  }
866
1119
  catch (err) {
867
1120
  spin.stop();
868
- output.error(`Failed to add credits: ${getErrorMessage(err)}`);
869
- process.exit(1);
1121
+ output.fatal(`Failed to add credits: ${getErrorMessage(err)}`);
870
1122
  }
871
1123
  }
872
1124
  function formatTimeAgo(dateStr) {
@@ -907,12 +1159,10 @@ export async function creditsAutoCommand(opts) {
907
1159
  });
908
1160
  spin.stop();
909
1161
  if (res.status === 403) {
910
- output.error(ERR_LLM_NOT_ENABLED);
911
- process.exit(1);
1162
+ output.fatal(ERR_LLM_NOT_ENABLED);
912
1163
  }
913
1164
  if (!res.ok) {
914
- output.error(`Failed to fetch config (HTTP ${res.status})`);
915
- process.exit(1);
1165
+ output.fatal(`Failed to fetch config (HTTP ${res.status})`);
916
1166
  }
917
1167
  const { config } = (await res.json());
918
1168
  output.brandBold("Bankr LLM Gateway — Auto Top-Up");
@@ -927,15 +1177,13 @@ export async function creditsAutoCommand(opts) {
927
1177
  }
928
1178
  catch (err) {
929
1179
  spin.stop();
930
- output.error(`Failed to fetch config: ${getErrorMessage(err)}`);
931
- process.exit(1);
1180
+ output.fatal(`Failed to fetch config: ${getErrorMessage(err)}`);
932
1181
  }
933
1182
  return;
934
1183
  }
935
1184
  // POST update config
936
1185
  if (opts.enable && opts.disable) {
937
- output.error("Cannot use --enable and --disable together");
938
- process.exit(1);
1186
+ output.fatal("Cannot use --enable and --disable together");
939
1187
  }
940
1188
  const body = {};
941
1189
  if (opts.disable) {
@@ -951,16 +1199,14 @@ export async function creditsAutoCommand(opts) {
951
1199
  if (opts.amount) {
952
1200
  const amt = Number(opts.amount);
953
1201
  if (Number.isNaN(amt) || amt < 1 || amt > 1000) {
954
- output.error("Amount must be between $1 and $1,000");
955
- process.exit(1);
1202
+ output.fatal("Amount must be between $1 and $1,000");
956
1203
  }
957
1204
  body.amountUsd = amt;
958
1205
  }
959
1206
  if (opts.threshold) {
960
1207
  const thr = Number(opts.threshold);
961
1208
  if (Number.isNaN(thr) || thr < 1 || thr > 500) {
962
- output.error("Threshold must be between $1 and $500");
963
- process.exit(1);
1209
+ output.fatal("Threshold must be between $1 and $500");
964
1210
  }
965
1211
  body.thresholdUsd = thr;
966
1212
  }
@@ -972,8 +1218,7 @@ export async function creditsAutoCommand(opts) {
972
1218
  .map((s) => s.trim())
973
1219
  .filter(Boolean);
974
1220
  if (inputs.length === 0 || inputs.length > 3) {
975
- output.error("Provide 1-3 comma-separated token symbols or addresses");
976
- process.exit(1);
1221
+ output.fatal("Provide 1-3 comma-separated token symbols or addresses");
977
1222
  }
978
1223
  const resolved = [];
979
1224
  // Highest USD balance wins when the same symbol exists on multiple chains.
@@ -1004,8 +1249,7 @@ export async function creditsAutoCommand(opts) {
1004
1249
  }
1005
1250
  }
1006
1251
  if (resolved.length === 0) {
1007
- output.error("No valid tokens resolved. Check your token symbols.");
1008
- process.exit(1);
1252
+ output.fatal("No valid tokens resolved. Check your token symbols.");
1009
1253
  }
1010
1254
  body.tokens = resolved;
1011
1255
  }
@@ -1028,13 +1272,11 @@ export async function creditsAutoCommand(opts) {
1028
1272
  });
1029
1273
  spin.stop();
1030
1274
  if (res.status === 403) {
1031
- output.error(ERR_LLM_NOT_ENABLED);
1032
- process.exit(1);
1275
+ output.fatal(ERR_LLM_NOT_ENABLED);
1033
1276
  }
1034
1277
  if (!res.ok) {
1035
1278
  const errBody = (await res.json().catch(() => ({})));
1036
- output.error(errBody.error ?? `Failed to update config (HTTP ${res.status})`);
1037
- process.exit(1);
1279
+ output.fatal(errBody.error ?? `Failed to update config (HTTP ${res.status})`);
1038
1280
  }
1039
1281
  output.success(opts.disable ? "Auto top-up disabled" : "Auto top-up settings updated");
1040
1282
  // Show config from POST response (avoids extra GET round-trip)
@@ -1052,8 +1294,7 @@ export async function creditsAutoCommand(opts) {
1052
1294
  }
1053
1295
  catch (err) {
1054
1296
  spin.stop();
1055
- output.error(`Failed to update config: ${getErrorMessage(err)}`);
1056
- process.exit(1);
1297
+ output.fatal(`Failed to update config: ${getErrorMessage(err)}`);
1057
1298
  }
1058
1299
  }
1059
1300
  /* ──────────────────────── bankr llm setup openclaw ────────────────────────── */
@@ -1073,7 +1314,7 @@ export async function setupOpenclawCommand(opts) {
1073
1314
  ? { baseUrl: imageBaseUrl, apiKey: llmKey ?? "${BANKR_API_KEY}" }
1074
1315
  : null;
1075
1316
  const imageGenerationModel = opts.images
1076
- ? { primary: "openai/gpt-image-2", timeoutMs: 180000 }
1317
+ ? { primary: "openai/gpt-image-2.5-flare", timeoutMs: 180000 }
1077
1318
  : null;
1078
1319
  const warnImagesSlot = () => {
1079
1320
  if (opts.images)
@@ -1211,7 +1452,7 @@ export async function setupCursorCommand() {
1211
1452
  const { models } = await resolveModels();
1212
1453
  const activeModels = models.filter((m) => !m.deprecation);
1213
1454
  // Pick one model per provider as recommended examples
1214
- const recommendedIds = ["claude-fable-5", "gemini-3.1-pro", "gpt-5.5"];
1455
+ const recommendedIds = ["claude-fable-5.1", "gemini-3.1-pro", "gpt-5.5"];
1215
1456
  const recommended = recommendedIds.filter((id) => activeModels.some((m) => m.id === id));
1216
1457
  output.brandBold("Cursor — Bankr LLM Gateway");
1217
1458
  console.log();
@@ -1257,8 +1498,7 @@ export async function setupClaudeCodeCommand() {
1257
1498
  function requireAuth() {
1258
1499
  const llmKey = getLlmKey();
1259
1500
  if (!llmKey) {
1260
- output.error("Not authenticated. Run `bankr login` first.");
1261
- process.exit(1);
1501
+ output.fatal("Not authenticated. Run `bankr login` first.");
1262
1502
  }
1263
1503
  return llmKey;
1264
1504
  }
@@ -1298,8 +1538,8 @@ function fileContains(filePath, search) {
1298
1538
  * `--model` flag appears honored but the real request is a different
1299
1539
  * model. Any suffix (e.g. `[1m]` context tier) is preserved.
1300
1540
  */
1301
- function toAnthropicModelId(model) {
1302
- return model.replace(/^(claude-(?:opus|sonnet|haiku)-)(\d+)\.(\d+)(.*)$/, "$1$2-$3$4");
1541
+ export function toAnthropicModelId(model) {
1542
+ return model.replace(/^(claude-(?:opus|sonnet|haiku|fable)-)(\d+)\.(\d+)(.*)$/, "$1$2-$3$4");
1303
1543
  }
1304
1544
  function translateClaudeModelArgs(args) {
1305
1545
  const out = [...args];