@coseung2/opencodex 2.8.0-cs.13 → 2.8.0-cs.14

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.
Files changed (60) hide show
  1. package/gui/dist/assets/index-MUpaVatk.js +67 -0
  2. package/gui/dist/index.html +1 -1
  3. package/package.json +3 -3
  4. package/packages/ocx-notch/README.md +2 -1
  5. package/src/adapters/cursor/discovery.ts +6 -2
  6. package/src/adapters/cursor/effort-map.ts +3 -0
  7. package/src/adapters/google-antigravity-replay.ts +24 -0
  8. package/src/adapters/google.ts +16 -11
  9. package/src/chat/inbound.ts +5 -11
  10. package/src/cli/account-api.ts +9 -1
  11. package/src/cli/account-extended.ts +4 -1
  12. package/src/codex/account-label.ts +14 -1
  13. package/src/codex/account-lifecycle.ts +12 -1
  14. package/src/codex/account-namespaces.ts +21 -0
  15. package/src/codex/account-priority.ts +49 -0
  16. package/src/codex/account-store.ts +2 -1
  17. package/src/codex/auth-api.ts +108 -17
  18. package/src/codex/auth-context.ts +61 -16
  19. package/src/codex/catalog/metadata.ts +34 -12
  20. package/src/codex/catalog/parsing.ts +8 -1
  21. package/src/codex/catalog/provider-fetch.ts +24 -6
  22. package/src/codex/catalog.ts +1 -1
  23. package/src/codex/pool-rotation.ts +51 -4
  24. package/src/codex/quota.ts +154 -35
  25. package/src/codex/routing.ts +133 -33
  26. package/src/codex/warmup.ts +193 -85
  27. package/src/config.ts +84 -1
  28. package/src/lib/bounded-body.ts +13 -6
  29. package/src/lib/bun-stream-caps.ts +5 -6
  30. package/src/lib/redact.ts +13 -0
  31. package/src/oauth/index.ts +79 -12
  32. package/src/oauth/log.ts +3 -1
  33. package/src/oauth/store.ts +31 -8
  34. package/src/providers/antigravity-models.ts +53 -24
  35. package/src/providers/codex-capacity.ts +303 -0
  36. package/src/providers/model-rename-migration.ts +147 -0
  37. package/src/providers/model-rename-startup.ts +29 -0
  38. package/src/providers/quota.ts +126 -16
  39. package/src/providers/registry.ts +258 -38
  40. package/src/responses/parser.ts +19 -12
  41. package/src/responses/spill-store.ts +14 -1
  42. package/src/responses/state.ts +108 -14
  43. package/src/server/index.ts +9 -1
  44. package/src/server/management/logs-usage-routes.ts +1 -0
  45. package/src/server/management/oauth-account-routes.ts +8 -1
  46. package/src/server/relay.ts +10 -42
  47. package/src/server/request-log.ts +42 -1
  48. package/src/server/responses/compact.ts +16 -4
  49. package/src/server/responses/core.ts +217 -59
  50. package/src/server/responses/empty-completion-guard.ts +275 -0
  51. package/src/server/responses/encrypted-payload.ts +54 -39
  52. package/src/server/responses/fetch-helpers.ts +24 -3
  53. package/src/server/responses/ws-upstream.ts +318 -0
  54. package/src/server/sse-frame-buffer.ts +292 -0
  55. package/src/server/ws-bridge.ts +17 -11
  56. package/src/types.ts +8 -0
  57. package/src/usage/log.ts +24 -0
  58. package/src/usage/summary.ts +152 -2
  59. package/vendor/ocx-notch/win32-x64/ocx-notch.exe +0 -0
  60. package/gui/dist/assets/index-BucjyD4I.js +0 -67
@@ -1,6 +1,6 @@
1
1
  import type { CodexAccountMode, OcxProviderConfig } from "../types";
2
2
  import { KIRO_MODELS, KIRO_MODEL_CONTEXT_WINDOWS, KIRO_MODEL_REASONING_EFFORTS } from "./kiro-models";
3
- import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS } from "./antigravity-models";
3
+ import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS, ANTIGRAVITY_MODEL_INPUT_MODALITIES } from "./antigravity-models";
4
4
  import type { ProviderBaseUrlChoice } from "./base-url-choices";
5
5
  import {
6
6
  QWEN_CLOUD_BASE_URL_CHOICES, QWEN_CLOUD_TOKEN_PLAN_BASE_URL,
@@ -216,8 +216,15 @@ export type ProviderConfigSeed = Pick<
216
216
  const ANTHROPIC_MODELS = ["claude-fable-5", "claude-sonnet-5", "claude-opus-5", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-4-6", "claude-sonnet-4-6", "claude-haiku-4-5"];
217
217
  const ANTHROPIC_MODEL_CONTEXT_WINDOWS: Record<string, number> = { "claude-sonnet-5": 1_000_000, "claude-fable-5": 1_000_000, "claude-opus-5": 1_000_000, "claude-opus-4-8": 1_000_000, "claude-haiku-4-5": 200_000 };
218
218
 
219
+ const ZAI_GLM_53_MODELS = ["glm-5.3", "glm-5.3[1m]"];
219
220
  const ZAI_GLM_52_MODELS = ["glm-5.2", "glm-5.2[1m]"];
221
+ const ZAI_GLM_5X_MODELS = [...ZAI_GLM_53_MODELS, ...ZAI_GLM_52_MODELS];
220
222
  const ZAI_GLM_52_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
223
+ const ZAI_GLM_53_REASONING_EFFORTS = ["low", "high", "max"];
224
+ const ZAI_GLM_5X_REASONING_EFFORTS: Record<string, string[]> = {
225
+ ...Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, ZAI_GLM_53_REASONING_EFFORTS])),
226
+ ...Object.fromEntries(ZAI_GLM_52_MODELS.map(id => [id, ZAI_GLM_52_REASONING_EFFORTS])),
227
+ };
221
228
  // 260710 MiniMax models and context windows: Tier-2 evidence in
222
229
  // devlog/_plan/260710_provider_hardening/002_research_cn.md.
223
230
  const MINIMAX_MODELS = [
@@ -298,13 +305,13 @@ const OPENCODE_GO_THINKING_TOGGLE_MODELS = [
298
305
  * images through the proxy's vision sidecar (src/codex/catalog/provider-fetch.ts), a claim nobody
299
306
  * has verified for BigModel-hosted GLM.
300
307
  */
301
- const ZHIPU_BIGMODEL_TEXT_MODELS = ["glm-4.6", "glm-4.7", "glm-4.7-flash", "glm-5", "glm-5.1"];
308
+ const ZHIPU_BIGMODEL_TEXT_MODELS = ["glm-4.6", "glm-4.7", "glm-4.7-flash", "glm-5", "glm-5.1", "glm-5.2", "glm-5.3"];
302
309
  const ZHIPU_BIGMODEL_MODELS = [...ZHIPU_BIGMODEL_TEXT_MODELS, "glm-4.6v"];
303
310
  const ZHIPU_BIGMODEL_INPUT_MODALITIES: Record<string, string[]> = {
304
311
  ...Object.fromEntries(ZHIPU_BIGMODEL_TEXT_MODELS.map(id => [id, ["text"]])),
305
312
  "glm-4.6v": ["text", "image"],
306
313
  };
307
- const ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS = ["glm-4.6", "glm-4.7", "glm-5", "glm-5.1"];
314
+ const ZHIPU_BIGMODEL_THINKING_TOGGLE_MODELS = ["glm-4.6", "glm-4.7", "glm-5", "glm-5.1", "glm-5.2", "glm-5.3"];
308
315
  const THINKING_BUDGET_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
309
316
  const THINKING_BUDGET_MODELS = [
310
317
  "qwen3.5-397b", "qwen3.6-35b",
@@ -312,7 +319,10 @@ const THINKING_BUDGET_MODELS = [
312
319
  ];
313
320
  const OPENCODE_GO_THINKING_BUDGET_MODELS = ["qwen3.5-plus", "qwen3.6-plus", "qwen3.7-max", "qwen3.7-plus"];
314
321
  const DEEPSEEK_THINKING_MODELS = ["deepseek-v4-pro", "deepseek-v4-flash"];
322
+ const DEEPSEEK_VISION_PREVIEW_MODEL = "deepseek-v4-flash-vision-exp";
315
323
  const OPENCODE_FREE_DEEPSEEK_MODELS = ["deepseek-v4-flash-free"];
324
+ const OPENCODE_OX_ALPHA_FREE_MODEL = "x-preview-f-free";
325
+ const OX_ALPHA_CONTEXT_WINDOW = 1_048_576;
316
326
  // "max" is advertised too: the wire map routes xhigh->max and max->max, so the picker
317
327
  // should surface the max tier instead of hiding it behind xhigh.
318
328
  const DEEPSEEK_THINKING_EFFORTS = ["high", "xhigh", "max"];
@@ -329,7 +339,7 @@ const DEEPSEEK_THINKING_REASONING_MAP: Record<string, string> = {
329
339
  // https://help.aliyun.com/en/model-studio/token-plan-quickstart
330
340
  const ALIBABA_TOKEN_PLAN_MODELS = [
331
341
  "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
332
- "glm-5.2", "deepseek-v4-pro",
342
+ "glm-5.3", "glm-5.2", "deepseek-v4-pro",
333
343
  ];
334
344
  const ALIBABA_TOKEN_PLAN_QWEN_MODELS = [
335
345
  "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash",
@@ -339,6 +349,7 @@ const ALIBABA_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
339
349
  "qwen3.7-max": ["text", "image"],
340
350
  "qwen3.7-plus": ["text", "image"],
341
351
  "qwen3.6-flash": ["text", "image"],
352
+ "glm-5.3": ["text"],
342
353
  "glm-5.2": ["text"],
343
354
  "deepseek-v4-pro": ["text"],
344
355
  };
@@ -351,7 +362,7 @@ const ALIBABA_INTL_TOKEN_PLAN_MODELS = [
351
362
  "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash",
352
363
  "deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2",
353
364
  "kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5",
354
- "glm-5.2", "glm-5.1", "glm-5",
365
+ "glm-5.3", "glm-5.2", "glm-5.1", "glm-5",
355
366
  "MiniMax-M2.5",
356
367
  ];
357
368
  const ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS = [
@@ -398,6 +409,7 @@ const VOLCENGINE_CODING_PLAN_MODELS = [
398
409
  "doubao-seed-2.0-code",
399
410
  "deepseek-v4-pro",
400
411
  "deepseek-v4-flash",
412
+ "glm-5.3",
401
413
  "glm-5.2",
402
414
  "kimi-k2.6",
403
415
  "minimax-m3",
@@ -405,6 +417,7 @@ const VOLCENGINE_CODING_PLAN_MODELS = [
405
417
  const VOLCENGINE_AGENT_PLAN_MODELS = [
406
418
  "deepseek-v4-pro",
407
419
  "deepseek-v4-flash",
420
+ "glm-5.3",
408
421
  "glm-5.2",
409
422
  "kimi-k2.6",
410
423
  "minimax-m3",
@@ -422,6 +435,7 @@ const VOLCENGINE_PLAN_TEXT_ONLY_MODELS = [
422
435
  "doubao-seed-2.0-code",
423
436
  "deepseek-v4-pro",
424
437
  "deepseek-v4-flash",
438
+ "glm-5.3",
425
439
  "glm-5.2",
426
440
  "doubao-seed-2.0-pro",
427
441
  ];
@@ -441,6 +455,7 @@ const ALIBABA_INTL_TOKEN_PLAN_INPUT_MODALITIES: Record<string, string[]> = {
441
455
  "glm-5.1": ["text"],
442
456
  "glm-5": ["text"],
443
457
  "MiniMax-M2.5": ["text"],
458
+ "glm-5.3": ["text"],
444
459
  };
445
460
 
446
461
  // 260717 Kimi K3: the subscription endpoint uses one upstream id (`k3`) for both
@@ -503,6 +518,7 @@ const KIMI_CODING_MODEL_INPUT_MODALITIES = Object.fromEntries(
503
518
  KIMI_CODING_K3_MODELS.map(id => [id, ["text", "image"]]),
504
519
  );
505
520
  const NEURALWATT_REASONING_HISTORY_MODELS = [
521
+ "glm-5.3", "glm-5.3-short",
506
522
  "glm-5.2", "glm-5.2-short",
507
523
  "kimi-k2.6", "kimi-k2.7-code",
508
524
  "qwen3.5-397b", "qwen3.6-35b",
@@ -521,6 +537,8 @@ const BASETEN_MODEL_REASONING_EFFORTS: Record<string, string[]> = {
521
537
  "thinkingmachines/inkling": BASETEN_FULL_REASONING_EFFORTS,
522
538
  "openai/gpt-oss-120b": BASETEN_FULL_REASONING_EFFORTS,
523
539
  "moonshotai/Kimi-K3": ["low", "high", "max"],
540
+ "zai-org/GLM-5.3": ["low", "high", "max"],
541
+ "zai-org/GLM-5.3-Fast": ["low", "high", "max"],
524
542
  "zai-org/GLM-5.2": ["high", "max"],
525
543
  "zai-org/GLM-5.2-Fast": ["high", "max"],
526
544
  };
@@ -529,6 +547,8 @@ const BASETEN_MODEL_REASONING_EFFORT_MAP: Record<string, Record<string, string>>
529
547
  "thinkingmachines/inkling": { none: "none", minimal: "minimal" },
530
548
  "openai/gpt-oss-120b": { none: "none", minimal: "minimal" },
531
549
  "moonshotai/Kimi-K3": { none: "none" },
550
+ "zai-org/GLM-5.3": { none: "none" },
551
+ "zai-org/GLM-5.3-Fast": { none: "none" },
532
552
  "zai-org/GLM-5.2": { none: "none" },
533
553
  "zai-org/GLM-5.2-Fast": { none: "none" },
534
554
  };
@@ -544,21 +564,71 @@ const BASETEN_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
544
564
  "moonshotai/Kimi-K2.7-Code": ["text", "image"],
545
565
  "moonshotai/Kimi-K3": ["text", "image"],
546
566
  };
567
+
568
+ const DIGITALOCEAN_CHAT_COMPLETION_MODELS = [
569
+ "arcee-trinity-large-thinking",
570
+ "openai-gpt-5.6-sol",
571
+ "openai-gpt-5.6-terra",
572
+ "openai-gpt-5.6-luna",
573
+ "qwen3-coder-flash",
574
+ "qwen3.5-397b-a17b",
575
+ "deepseek-v4-pro",
576
+ "deepseek-4-flash",
577
+ "deepseek-3.2",
578
+ "gemma-4-31B-it",
579
+ "minimax-m2.5",
580
+ "kimi-k3",
581
+ "kimi-k2.6",
582
+ "kimi-k2.5",
583
+ "llama3.3-70b-instruct",
584
+ "llama-4-maverick",
585
+ "mistral-3-14B",
586
+ "nemotron-3-ultra-550b",
587
+ "nvidia-nemotron-3-super-120b",
588
+ "nemotron-3-nano-omni",
589
+ "nemotron-nano-12b-v2-vl",
590
+ "mimo-v2.5-pro",
591
+ "glm-5.3",
592
+ "glm-5.2",
593
+ "glm-5.1",
594
+ "glm-5",
595
+ "meta-llama/Meta-Llama-3.1-8B-Instruct",
596
+ ] as const;
597
+
598
+ const SCALEWAY_SERVERLESS_CHAT_MODELS = [
599
+ "glm-5.3",
600
+ "glm-5.2",
601
+ "qwen3.6-35b-a3b",
602
+ "qwen3.5-397b-a17b",
603
+ "qwen3-235b-a22b-instruct-2507",
604
+ "qwen3-coder-30b-a3b-instruct",
605
+ "gemma-4-26b-a4b-it",
606
+ "llama-3.3-70b-instruct",
607
+ "mistral-medium-3.5-128b",
608
+ "mistral-small-3.2-24b-instruct-2506",
609
+ "pixtral-12b-2409",
610
+ ] as const;
611
+ const SCALEWAY_MODEL_INPUT_MODALITIES: Record<string, string[]> = {
612
+ "pixtral-12b-2409": ["text", "image"],
613
+ };
547
614
  const UMANS_MODELS = [
548
615
  "umans-coder",
549
616
  "umans-kimi-k2.7",
550
617
  "umans-flash",
618
+ "umans-glm-5.3",
551
619
  "umans-glm-5.2",
552
620
  "umans-glm-5.1",
553
621
  "umans-qwen3.6-35b-a3b",
554
622
  ];
555
623
  const UMANS_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
556
624
  const UMANS_GLM_REASONING_EFFORTS = ["high", "xhigh", "max"];
557
- const UMANS_TEXT_ONLY_MODELS = ["umans-glm-5.2", "umans-glm-5.1"];
625
+ const UMANS_GLM_53_REASONING_EFFORTS = ["low", "high", "max"];
626
+ const UMANS_TEXT_ONLY_MODELS = ["umans-glm-5.3", "umans-glm-5.2", "umans-glm-5.1"];
558
627
  const UMANS_MODEL_CONTEXT_WINDOWS: Record<string, number> = {
559
628
  "umans-coder": 262_144,
560
629
  "umans-kimi-k2.7": 262_144,
561
630
  "umans-flash": 262_144,
631
+ "umans-glm-5.3": 405_504,
562
632
  "umans-glm-5.2": 405_504,
563
633
  "umans-glm-5.1": 202_752,
564
634
  "umans-qwen3.6-35b-a3b": 262_144,
@@ -628,7 +698,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
628
698
  // devlog/model_update/260709_model_refresh/001_xai_lineup.md.
629
699
  // grok-4.20-multi-agent-0309 is intentionally absent: the OAuth chat-completions
630
700
  // transport returns 400 ("Multi Agent requests are not allowed on chat completions").
631
- models: ["grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning", "grok-4.20-0309-non-reasoning", "grok-build-0.1", "grok-composer-2.5-fast"],
701
+ models: ["grok-4.6", "grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning", "grok-4.20-0309-non-reasoning", "grok-build-0.1", "grok-composer-2.5-fast"],
632
702
  defaultModel: "grok-4.5",
633
703
  // Vision lineup per docs.x.ai model-capabilities/images/understanding: the grok-4.x chat
634
704
  // models accept image input (JPEG/PNG, URL or base64). Without this the catalog leaves
@@ -637,6 +707,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
637
707
  // the app blocks attachments client-side. grok-build-0.1 / grok-composer-2.5-fast stay out
638
708
  // (they are already listed in noVisionModels below).
639
709
  modelInputModalities: {
710
+ "grok-4.6": ["text", "image"],
640
711
  "grok-4.5": ["text", "image"],
641
712
  "grok-4.3": ["text", "image"],
642
713
  "grok-4.20-0309-reasoning": ["text", "image"],
@@ -647,10 +718,11 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
647
718
  // reasoning_content as the top cause of prompt-cache misses on multi-turn conversations
648
719
  // (docs.x.ai prompt-caching/multi-turn, verified 2026-07-13 — devlog/_plan/260713_grok_caching).
649
720
  // Models that never emit reasoning simply have no thinking parts to replay (no-op).
650
- preserveReasoningContentModels: ["grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning"],
651
- // grok-4.5 reasoning is always-on with low/medium/high control (no off tier upstream).
652
- modelReasoningEfforts: { "grok-4.5": ["low", "medium", "high"] },
721
+ preserveReasoningContentModels: ["grok-4.6", "grok-4.5", "grok-4.3", "grok-4.20-0309-reasoning"],
722
+ modelReasoningEfforts: { "grok-4.6": ["low", "medium", "high", "xhigh"], "grok-4.5": ["low", "medium", "high"] },
723
+ modelDefaultReasoningEfforts: { "grok-4.6": "high" },
653
724
  modelContextWindows: {
725
+ "grok-4.6": 500_000,
654
726
  "grok-4.5": 500_000,
655
727
  "grok-4.3": 1_000_000,
656
728
  "grok-4.20-0309-reasoning": 1_000_000,
@@ -778,6 +850,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
778
850
  "umans-coder": UMANS_REASONING_EFFORTS,
779
851
  "umans-kimi-k2.7": UMANS_REASONING_EFFORTS,
780
852
  "umans-flash": UMANS_REASONING_EFFORTS,
853
+ "umans-glm-5.3": UMANS_GLM_53_REASONING_EFFORTS,
781
854
  "umans-glm-5.2": UMANS_GLM_REASONING_EFFORTS,
782
855
  "umans-glm-5.1": UMANS_GLM_REASONING_EFFORTS,
783
856
  "umans-qwen3.6-35b-a3b": UMANS_REASONING_EFFORTS,
@@ -789,9 +862,18 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
789
862
  id: "opencode-go", label: "opencode go", adapter: "openai-chat", baseUrl: "https://opencode.ai/zen/go/v1",
790
863
  authKind: "key", featured: true, dashboardUrl: "https://opencode.ai/auth", defaultModel: "kimi-k2.7-code",
791
864
  jawcodeBundle: "opencode-go", note: "GLM, DeepSeek, Kimi, Qwen, MiMo…",
792
- modelContextWindows: { "kimi-k3": KIMI_K3_STANDARD_CONTEXT_WINDOW },
793
- modelInputModalities: { "kimi-k3": ["text", "image"] },
865
+ modelContextWindows: {
866
+ "kimi-k3": KIMI_K3_STANDARD_CONTEXT_WINDOW,
867
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
868
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
869
+ },
870
+ modelInputModalities: {
871
+ "kimi-k3": ["text", "image"],
872
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
873
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
874
+ },
794
875
  modelReasoningEfforts: {
876
+ "glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
795
877
  "glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
796
878
  "kimi-k3": KIMI_CODING_K3_REASONING_EFFORTS,
797
879
  "kimi-k2.7-code": [],
@@ -815,7 +897,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
815
897
  // every model listed here (and the catalog advertises image input on their behalf).
816
898
  // Kimi K2.7 Code accepts text+image+video: do NOT list it here.
817
899
  noVisionModels: [
818
- "glm-5.2", "glm-5", "glm-5.1",
900
+ "glm-5.3", "glm-5.2", "glm-5", "glm-5.1",
819
901
  "deepseek-v4-flash", "deepseek-v4-pro",
820
902
  "mimo-v2-pro", "mimo-v2.5-pro",
821
903
  "minimax-m2.5", "minimax-m2.7",
@@ -826,7 +908,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
826
908
  noPenaltyModels: ["kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
827
909
  autoToolChoiceOnlyModels: ["kimi-k2.7-code", "kimi-k2.7-code-highspeed"],
828
910
  // Issue #78: DeepSeek V4 thinking mode requires reasoning_content replay on tool-call turns.
829
- preserveReasoningContentModels: ["glm-5.2", "kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed", ...DEEPSEEK_THINKING_MODELS],
911
+ preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "kimi-k3", "kimi-k2.7-code", "kimi-k2.7-code-highspeed", ...DEEPSEEK_THINKING_MODELS],
830
912
  },
831
913
  {
832
914
  id: "neuralwatt",
@@ -835,10 +917,11 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
835
917
  baseUrl: "https://api.neuralwatt.com/v1",
836
918
  authKind: "key",
837
919
  dashboardUrl: "https://portal.neuralwatt.com",
838
- defaultModel: "glm-5.2",
920
+ defaultModel: "glm-5.3",
839
921
  // 2026-07-10 live /v1/models: K2.5 rows were removed and GLM-5.2 short variants added.
840
922
  // Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md and https://api.neuralwatt.com/v1/models.
841
923
  models: [
924
+ "glm-5.3", "glm-5.3-fast", "glm-5.3-short", "glm-5.3-short-fast",
842
925
  "glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast",
843
926
  "kimi-k2.6", "kimi-k2.6-fast",
844
927
  "kimi-k2.7-code",
@@ -846,6 +929,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
846
929
  ],
847
930
  // Neuralwatt's /v1/models metadata is authoritative; these static hints are the offline fallback.
848
931
  modelReasoningEfforts: {
932
+ "glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
933
+ "glm-5.3-fast": [],
934
+ "glm-5.3-short": ZAI_GLM_53_REASONING_EFFORTS,
935
+ "glm-5.3-short-fast": [],
849
936
  "glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
850
937
  "glm-5.2-fast": [],
851
938
  "glm-5.2-short": ZAI_GLM_52_REASONING_EFFORTS,
@@ -861,15 +948,21 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
861
948
  "qwen3.6-35b-fast": [],
862
949
  },
863
950
  thinkingBudgetModels: THINKING_BUDGET_MODELS,
864
- noReasoningModels: ["glm-5.2-fast", "glm-5.2-short-fast", "kimi-k2.6-fast", "qwen3.5-397b-fast", "qwen3.6-35b-fast"],
865
- noVisionModels: ["glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast", "qwen3.5-397b", "qwen3.5-397b-fast"],
951
+ noReasoningModels: ["glm-5.3-fast", "glm-5.3-short-fast", "glm-5.2-fast", "glm-5.2-short-fast", "kimi-k2.6-fast", "qwen3.5-397b-fast", "qwen3.6-35b-fast"],
952
+ noVisionModels: ["glm-5.3", "glm-5.3-fast", "glm-5.3-short", "glm-5.3-short-fast", "glm-5.2", "glm-5.2-fast", "glm-5.2-short", "glm-5.2-short-fast", "qwen3.5-397b", "qwen3.5-397b-fast"],
866
953
  noTemperatureModels: ["kimi-k2.7-code"],
867
954
  noTopPModels: ["kimi-k2.7-code"],
868
955
  noPenaltyModels: ["kimi-k2.7-code"],
869
956
  autoToolChoiceOnlyModels: ["kimi-k2.7-code"],
870
957
  preserveReasoningContentModels: NEURALWATT_REASONING_HISTORY_MODELS,
871
958
  },
872
- { id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1", authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter", models: ["anthropic/claude-sonnet-5", ...OPENROUTER_GPT56_MODELS], modelContextWindows: { "anthropic/claude-sonnet-5": 1_000_000, ...OPENROUTER_GPT56_CONTEXT_WINDOWS } },
959
+ {
960
+ id: "openrouter", label: "OpenRouter", adapter: "openai-chat", baseUrl: "https://openrouter.ai/api/v1",
961
+ authKind: "key", featured: true, dashboardUrl: "https://openrouter.ai/keys", jawcodeBundle: "openrouter",
962
+ models: ["anthropic/claude-sonnet-5", "stealth/ox-alpha", ...OPENROUTER_GPT56_MODELS],
963
+ modelContextWindows: { "anthropic/claude-sonnet-5": 1_000_000, "stealth/ox-alpha": OX_ALPHA_CONTEXT_WINDOW, ...OPENROUTER_GPT56_CONTEXT_WINDOWS },
964
+ modelInputModalities: { "stealth/ox-alpha": ["text", "image"] },
965
+ },
873
966
  {
874
967
  // OrcaRouter: OpenAI-compatible adaptive router (api.orcarouter.ai). Model ids are
875
968
  // vendor-namespaced (`<vendor>/<model>`) and pass through to the upstream as-is.
@@ -933,7 +1026,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
933
1026
  // 2026-07-10: defaultModel is frozen pending Vertex-specific Tier-2 evidence; Gemini API
934
1027
  // evidence from ai.google.dev does not establish Vertex publisher availability.
935
1028
  { id: "google-vertex", label: "Google Vertex AI", adapter: "google", baseUrl: "https://aiplatform.googleapis.com", authKind: "key", dashboardUrl: "https://console.cloud.google.com/vertex-ai", defaultModel: "gemini-3-pro", googleMode: "vertex", jawcodeBundle: "google", extraMetadataAliases: ["gemini-vertex"] },
936
- { id: "google-antigravity", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: false, defaultModel: "gemini-3.6-flash", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, modelReasoningEfforts: ANTIGRAVITY_MODEL_EFFORTS, googleMode: "cloud-code-assist", jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"] },
1029
+ { id: "google-antigravity", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: false, defaultModel: "gemini-3.7-flash", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, modelInputModalities: ANTIGRAVITY_MODEL_INPUT_MODALITIES, modelReasoningEfforts: ANTIGRAVITY_MODEL_EFFORTS, googleMode: "cloud-code-assist", jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"] },
937
1030
  { id: "azure-openai", label: "Azure OpenAI", adapter: "azure-openai", baseUrl: "https://{resource}.openai.azure.com/openai", authKind: "key", featured: true, dashboardUrl: "https://portal.azure.com" },
938
1031
  { id: "ollama", label: "Ollama (local)", adapter: "openai-chat", baseUrl: "http://localhost:11434/v1", authKind: "local", allowPrivateNetworkByDefault: true, allowBaseUrlOverride: true, featured: true, note: "Local — key usually blank" },
939
1032
  { id: "vllm", label: "vLLM (local)", adapter: "openai-chat", baseUrl: "http://localhost:8000/v1", authKind: "local", allowPrivateNetworkByDefault: true, allowBaseUrlOverride: true, featured: true, note: "Local — key usually blank" },
@@ -947,9 +1040,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
947
1040
  dashboardUrl: "https://platform.deepseek.com/api_keys",
948
1041
  // deepseek-chat/deepseek-reasoner are upstream-deprecated at 2026-07-24 15:59 UTC;
949
1042
  // kept until then. Evidence: devlog/_plan/260710_provider_hardening/002_research_cn.md.
950
- models: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS],
1043
+ models: ["deepseek-chat", "deepseek-reasoner", ...DEEPSEEK_THINKING_MODELS, DEEPSEEK_VISION_PREVIEW_MODEL],
951
1044
  defaultModel: "deepseek-v4-flash",
952
- modelContextWindows: { "deepseek-v4-flash": 1_000_000, "deepseek-v4-pro": 1_000_000 },
1045
+ modelContextWindows: { "deepseek-v4-flash": 1_048_576, "deepseek-v4-pro": 1_048_576, [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576 },
1046
+ modelInputModalities: { [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"] },
953
1047
  // DeepSeek documents V4-Flash as a native Responses API model adapted for Codex. The
954
1048
  // API id is `deepseek-v4-flash`; `DeepSeek-V4-Flash-0731` is a release/version label.
955
1049
  modelWireDefaults: {
@@ -1021,6 +1115,48 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1021
1115
  },
1022
1116
  note: "Serverless text and vision-language chat models only; Hyperbolic's separate image, audio, and GPU endpoints are out of scope.",
1023
1117
  },
1118
+ {
1119
+ id: "nscale",
1120
+ label: "Nscale Serverless Inference",
1121
+ baseUrl: "https://inference.api.nscale.com/v1",
1122
+ adapter: "openai-chat",
1123
+ authKind: "key",
1124
+ dashboardUrl: "https://console.nscale.com",
1125
+ defaultModel: "meta-llama/Llama-3.1-8B-Instruct",
1126
+ models: ["meta-llama/Llama-3.1-8B-Instruct"],
1127
+ liveModels: true,
1128
+ preserveCustomDestination: true,
1129
+ parallelToolCalls: false,
1130
+ reasoningEfforts: [],
1131
+ modelDiscovery: {
1132
+ path: "models",
1133
+ maxResponseBytes: 256 * 1024,
1134
+ maxModels: 256,
1135
+ filter: { allOf: [{ path: ["id"], equalsAny: ["meta-llama/Llama-3.1-8B-Instruct"] }] },
1136
+ },
1137
+ note: "Live discovery admits only the tool-capable model established by Nscale's official API example.",
1138
+ },
1139
+ {
1140
+ id: "vultr",
1141
+ label: "Vultr Serverless Inference",
1142
+ baseUrl: "https://api.vultrinference.com/v1",
1143
+ adapter: "openai-chat",
1144
+ authKind: "key",
1145
+ dashboardUrl: "https://my.vultr.com",
1146
+ defaultModel: "kimi-k2-instruct",
1147
+ models: ["kimi-k2-instruct"],
1148
+ liveModels: true,
1149
+ preserveCustomDestination: true,
1150
+ parallelToolCalls: false,
1151
+ reasoningEfforts: [],
1152
+ modelDiscovery: {
1153
+ path: "models",
1154
+ maxResponseBytes: 256 * 1024,
1155
+ maxModels: 256,
1156
+ filter: { allOf: [{ path: ["id"], equalsAny: ["kimi-k2-instruct"] }] },
1157
+ },
1158
+ note: "Live discovery exposes only kimi-k2-instruct because Vultr documents it as the sole tool-calling model.",
1159
+ },
1024
1160
  {
1025
1161
  id: "baseten",
1026
1162
  label: "Baseten Model APIs",
@@ -1046,6 +1182,66 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1046
1182
  },
1047
1183
  note: "Shared Model APIs only (personal API key, or team key with Call Model APIs access); dedicated Truss predict endpoints are outside this preset.",
1048
1184
  },
1185
+ {
1186
+ id: "nebius",
1187
+ label: "Nebius Token Factory",
1188
+ baseUrl: "https://api.tokenfactory.nebius.com/v1",
1189
+ adapter: "openai-chat",
1190
+ authKind: "key",
1191
+ dashboardUrl: "https://tokenfactory.nebius.com",
1192
+ liveModels: true,
1193
+ preserveCustomDestination: true,
1194
+ parallelToolCalls: false,
1195
+ reasoningEfforts: [],
1196
+ modelDiscovery: {
1197
+ path: "models",
1198
+ query: { verbose: "true" },
1199
+ maxResponseBytes: 512 * 1024,
1200
+ maxModels: 512,
1201
+ filter: { allOf: [{ path: ["architecture", "modality"], containsAny: ["->text"] }] },
1202
+ },
1203
+ note: "Shared Token Factory text-output inference only; embedding and image-generation rows are excluded.",
1204
+ },
1205
+ {
1206
+ id: "digitalocean",
1207
+ label: "DigitalOcean Serverless Inference",
1208
+ baseUrl: "https://inference.do-ai.run/v1",
1209
+ adapter: "openai-chat",
1210
+ authKind: "key",
1211
+ dashboardUrl: "https://cloud.digitalocean.com/model-studio/manage-keys",
1212
+ liveModels: true,
1213
+ preserveCustomDestination: true,
1214
+ parallelToolCalls: false,
1215
+ reasoningEfforts: [],
1216
+ modelDiscovery: {
1217
+ path: "models",
1218
+ maxResponseBytes: 256 * 1024,
1219
+ maxModels: 256,
1220
+ filter: { allOf: [{ path: ["id"], equalsAny: DIGITALOCEAN_CHAT_COMPLETION_MODELS }] },
1221
+ },
1222
+ note: "Shared Serverless Inference Chat Completions only; non-chat and dedicated endpoints remain excluded.",
1223
+ },
1224
+ {
1225
+ id: "scaleway",
1226
+ label: "Scaleway Generative APIs",
1227
+ baseUrl: "https://api.scaleway.ai/v1",
1228
+ adapter: "openai-chat",
1229
+ authKind: "key",
1230
+ dashboardUrl: "https://console.scaleway.com/generative-api",
1231
+ liveModels: true,
1232
+ freeTier: true,
1233
+ preserveCustomDestination: true,
1234
+ parallelToolCalls: false,
1235
+ reasoningEfforts: [],
1236
+ modelInputModalities: SCALEWAY_MODEL_INPUT_MODALITIES,
1237
+ modelDiscovery: {
1238
+ path: "models",
1239
+ maxResponseBytes: 128 * 1024,
1240
+ maxModels: 128,
1241
+ filter: { allOf: [{ path: ["id"], equalsAny: SCALEWAY_SERVERLESS_CHAT_MODELS }] },
1242
+ },
1243
+ note: "Shared Serverless Chat Completions only; project-qualified and dedicated deployment hosts require a custom provider.",
1244
+ },
1049
1245
  // FREEZE 2026-07-10: exact serverless ids remain auth-gated/unverified. Evidence: devlog/_plan/260710_provider_hardening/003_research_aggregators.md.
1050
1246
  { id: "together", label: "Together", baseUrl: "https://api.together.xyz/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://api.together.xyz/settings/api-keys" },
1051
1247
  { id: "fireworks", label: "Fireworks", baseUrl: "https://api.fireworks.ai/inference/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://fireworks.ai/account/api-keys" },
@@ -1092,15 +1288,17 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1092
1288
  // devlog/_plan/260710_provider_hardening/002_research_cn.md.
1093
1289
  {
1094
1290
  id: "zai", label: "Z.AI — GLM Coding Plan", baseUrl: "https://api.z.ai/api/coding/paas/v4", adapter: "openai-chat", authKind: "key",
1095
- dashboardUrl: "https://z.ai/manage-apikey/apikey-list", defaultModel: "glm-5.2",
1096
- note: "GLM-5.2 coding subscription",
1097
- models: ["glm-5.2", "glm-5.2[1m]", "glm-5.1", "glm-5", "glm-4.6"],
1098
- modelContextWindows: { "glm-5.2": 1_000_000, "glm-5.2[1m]": 1_000_000 },
1291
+ dashboardUrl: "https://z.ai/manage-apikey/apikey-list", defaultModel: "glm-5.3",
1292
+ note: "GLM-5.3 coding subscription",
1293
+ models: ["glm-5.3", "glm-5.3[1m]", "glm-5.2", "glm-5.2[1m]", "glm-5.1", "glm-5", "glm-4.6"],
1294
+ modelContextWindows: { "glm-5.3": 1_000_000, "glm-5.3[1m]": 1_000_000, "glm-5.2": 1_000_000, "glm-5.2[1m]": 1_000_000 },
1099
1295
  // Z.AI's OpenAI path returns 400 code 1211 for bracketed model ids.
1100
1296
  modelSuffixBracketStrip: true,
1101
- noVisionModels: ZAI_GLM_52_MODELS,
1102
- modelReasoningEfforts: Object.fromEntries(ZAI_GLM_52_MODELS.map(id => [id, ZAI_GLM_52_REASONING_EFFORTS])),
1103
- preserveReasoningContentModels: ZAI_GLM_52_MODELS,
1297
+ noVisionModels: ZAI_GLM_5X_MODELS,
1298
+ modelReasoningEfforts: ZAI_GLM_5X_REASONING_EFFORTS,
1299
+ modelDefaultReasoningEfforts: Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, "max"])),
1300
+ modelMaxOutputTokens: Object.fromEntries(ZAI_GLM_53_MODELS.map(id => [id, 131_072])),
1301
+ preserveReasoningContentModels: ZAI_GLM_5X_MODELS,
1104
1302
  },
1105
1303
  // Zhipu's domestic BigModel platform: OpenAI-compatible pay-as-you-go on open.bigmodel.cn — a
1106
1304
  // different host and billing product from the `zai` coding-plan subscription above.
@@ -1273,17 +1471,18 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1273
1471
  modelInputModalities: ALIBABA_TOKEN_PLAN_INPUT_MODALITIES,
1274
1472
  modelContextWindows: {
1275
1473
  "qwen3.8-max-preview": 983_616, "qwen3.7-max": 1_000_000, "qwen3.7-plus": 1_000_000,
1276
- "qwen3.6-flash": 1_000_000, "glm-5.2": 1_000_000, "deepseek-v4-pro": 1_000_000,
1474
+ "qwen3.6-flash": 1_000_000, "glm-5.3": 1_000_000, "glm-5.2": 1_000_000, "deepseek-v4-pro": 1_000_000,
1277
1475
  },
1278
1476
  modelReasoningEfforts: {
1279
1477
  ...Object.fromEntries(ALIBABA_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
1478
+ "glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
1280
1479
  "glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
1281
1480
  "deepseek-v4-pro": DEEPSEEK_THINKING_EFFORTS,
1282
1481
  },
1283
1482
  modelReasoningEffortMap: { "deepseek-v4-pro": DEEPSEEK_THINKING_REASONING_MAP },
1284
1483
  thinkingBudgetModels: ALIBABA_TOKEN_PLAN_QWEN_MODELS,
1285
- preserveReasoningContentModels: ["glm-5.2", "deepseek-v4-pro", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash"],
1286
- noVisionModels: ["glm-5.2", "deepseek-v4-pro"],
1484
+ preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-flash"],
1485
+ noVisionModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro"],
1287
1486
  },
1288
1487
  {
1289
1488
  id: "alibaba-token-plan-intl",
@@ -1305,12 +1504,13 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1305
1504
  "qwen3.7-max": 1_000_000, "qwen3.7-plus": 1_000_000, "qwen3.6-plus": 1_000_000, "qwen3.6-flash": 1_000_000,
1306
1505
  "deepseek-v4-pro": 1_000_000, "deepseek-v4-flash": 1_000_000, "deepseek-v3.2": 131_072,
1307
1506
  "kimi-k2.7-code": 262_144, "kimi-k2.6": 262_144, "kimi-k2.5": 262_144,
1308
- "glm-5.2": 1_000_000, "glm-5.1": 1_000_000, "glm-5": 1_000_000,
1507
+ "glm-5.3": 1_000_000, "glm-5.2": 1_000_000, "glm-5.1": 1_000_000, "glm-5": 1_000_000,
1309
1508
  "MiniMax-M2.5": 204_800,
1310
1509
  },
1311
1510
  modelReasoningEfforts: {
1312
1511
  ...Object.fromEntries(ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS.map(id => [id, THINKING_BUDGET_EFFORTS])),
1313
1512
  "qwen3.8-max-preview": ["low", "high", "xhigh"],
1513
+ "glm-5.3": ZAI_GLM_53_REASONING_EFFORTS,
1314
1514
  "glm-5.2": ZAI_GLM_52_REASONING_EFFORTS,
1315
1515
  "deepseek-v4-pro": DEEPSEEK_THINKING_EFFORTS,
1316
1516
  "deepseek-v4-flash": DEEPSEEK_THINKING_EFFORTS,
@@ -1320,8 +1520,8 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1320
1520
  "deepseek-v4-flash": DEEPSEEK_THINKING_REASONING_MAP,
1321
1521
  },
1322
1522
  thinkingBudgetModels: ALIBABA_INTL_TOKEN_PLAN_QWEN_MODELS,
1323
- preserveReasoningContentModels: ["glm-5.2", "deepseek-v4-pro", "deepseek-v4-flash", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash"],
1324
- noVisionModels: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2", "glm-5.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
1523
+ preserveReasoningContentModels: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "deepseek-v4-flash", "qwen3.8-max-preview", "qwen3.7-max", "qwen3.7-plus", "qwen3.6-plus", "qwen3.6-flash"],
1524
+ noVisionModels: ["deepseek-v4-pro", "deepseek-v4-flash", "deepseek-v3.2", "glm-5.3", "glm-5.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
1325
1525
  noReasoningModels: ["kimi-k2.7-code", "kimi-k2.6", "kimi-k2.5", "deepseek-v3.2", "glm-5.1", "glm-5", "MiniMax-M2.5"],
1326
1526
  modelDefaultReasoningEfforts: { "qwen3.8-max-preview": "xhigh" },
1327
1527
  },
@@ -1353,10 +1553,10 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1353
1553
  authKind: "key",
1354
1554
  dashboardUrl: "https://ollama.com/settings/keys",
1355
1555
  // Live IDs verified 2026-07-10; qwen3-coder:480b retires 2026-07-15.
1356
- models: ["glm-5.2", "deepseek-v4-pro", "qwen3-coder:480b", "gpt-oss:120b", "kimi-k2.6", "minimax-m3", "qwen3.5:397b", "gemma4:31b"],
1357
- defaultModel: "glm-5.2",
1556
+ models: ["glm-5.3", "glm-5.2", "deepseek-v4-pro", "qwen3-coder:480b", "gpt-oss:120b", "kimi-k2.6", "minimax-m3", "qwen3.5:397b", "gemma4:31b"],
1557
+ defaultModel: "glm-5.3",
1358
1558
  noVisionModels: [
1359
- "glm-5.2", "glm-5.1", "glm-5", "glm-4.7",
1559
+ "glm-5.3", "glm-5.2", "glm-5.1", "glm-5", "glm-4.7",
1360
1560
  "minimax-m2.7", "minimax-m2.5", "minimax-m2.1",
1361
1561
  "nemotron-3-ultra", "nemotron-3-super",
1362
1562
  "deepseek-v4-pro", "deepseek-v4-flash",
@@ -1408,7 +1608,18 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1408
1608
  autoToolChoiceOnlyModels: KIMI_AUTO_TOOL_CHOICE_ONLY_MODELS,
1409
1609
  preserveReasoningContentModels: KIMI_THINKING_MODELS,
1410
1610
  },
1411
- { id: "opencode-zen", label: "opencode zen", baseUrl: "https://opencode.ai/zen/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://opencode.ai/auth" },
1611
+ {
1612
+ id: "opencode-zen", label: "opencode zen", baseUrl: "https://opencode.ai/zen/v1",
1613
+ adapter: "openai-chat", authKind: "key", dashboardUrl: "https://opencode.ai/auth",
1614
+ modelContextWindows: {
1615
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
1616
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
1617
+ },
1618
+ modelInputModalities: {
1619
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
1620
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
1621
+ },
1622
+ },
1412
1623
  { id: "vercel-ai-gateway", label: "Vercel AI Gateway", baseUrl: "https://ai-gateway.vercel.sh/v1", adapter: "openai-chat", authKind: "key", dashboardUrl: "https://vercel.com/dashboard" },
1413
1624
  {
1414
1625
  id: "opencode-free",
@@ -1431,6 +1642,14 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1431
1642
  modelReasoningEfforts: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_EFFORTS])),
1432
1643
  modelReasoningEffortMap: Object.fromEntries(OPENCODE_FREE_DEEPSEEK_MODELS.map(id => [id, DEEPSEEK_THINKING_REASONING_MAP])),
1433
1644
  preserveReasoningContentModels: OPENCODE_FREE_DEEPSEEK_MODELS,
1645
+ modelContextWindows: {
1646
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: OX_ALPHA_CONTEXT_WINDOW,
1647
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
1648
+ },
1649
+ modelInputModalities: {
1650
+ [OPENCODE_OX_ALPHA_FREE_MODEL]: ["text", "image"],
1651
+ [DEEPSEEK_VISION_PREVIEW_MODEL]: ["text", "image"],
1652
+ },
1434
1653
  noVisionModels: OPENCODE_FREE_DEEPSEEK_MODELS,
1435
1654
  },
1436
1655
  { id: "xiaomi", label: "Xiaomi MiMo", baseUrl: "https://api.xiaomimimo.com/anthropic", adapter: "anthropic", authKind: "key", dashboardUrl: "https://xiaomimimo.com", defaultModel: "mimo-v2.5-pro" },
@@ -1464,6 +1683,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1464
1683
  "@cf/qwen/qwq-32b",
1465
1684
  "@cf/deepseek-ai/deepseek-r1-distill-qwen-32b",
1466
1685
  "@cf/moonshotai/kimi-k2.7-code",
1686
+ "@cf/zai-org/glm-5.3",
1467
1687
  "@cf/zai-org/glm-5.2",
1468
1688
  "@cf/mistralai/mistral-small-3.1-24b-instruct",
1469
1689
  ],
@@ -151,28 +151,35 @@ function buildTools(tools: unknown[] | undefined): OcxTool[] | undefined {
151
151
  if (namespace) tool.namespace = namespace;
152
152
  out.push(tool);
153
153
  };
154
+ const pushCustom = (t: Record<string, unknown>, namespace?: string) => {
155
+ const inputDescription = t.name === "apply_patch"
156
+ ? "Raw tool input. For apply_patch, begin exactly with `*** Begin Patch` (no trailing `***`), then use its standard patch envelope."
157
+ : "Raw freeform input for this tool.";
158
+ const tool: OcxTool = {
159
+ name: t.name as string,
160
+ description: (t.description as string) ?? "",
161
+ parameters: { type: "object", properties: { input: { type: "string", description: inputDescription } }, required: ["input"] },
162
+ freeform: true,
163
+ };
164
+ if (namespace) tool.namespace = namespace;
165
+ out.push(tool);
166
+ };
154
167
  for (const t of tools) {
155
168
  if (!isObj(t)) continue;
156
169
  if (t.type === "function" && typeof t.name === "string") {
157
170
  pushFn(t);
158
171
  } else if (t.type === "namespace" && Array.isArray(t.tools)) {
159
- // MCP tools arrive grouped under a namespace tool; flatten the inner function tools so
160
- // chat-completions models receive them (round-trip restores the namespace in the bridge).
161
- const ns = typeof t.name === "string" ? t.name : undefined;
172
+ // Codex 0.147 groups ordinary built-ins under `functions`; flatten those
173
+ // without a namespace while preserving MCP-style namespace routing.
174
+ const builtinFunctions = t.name === "functions";
175
+ const ns = typeof t.name === "string" && !builtinFunctions ? t.name : undefined;
162
176
  for (const inner of t.tools as unknown[]) {
163
177
  if (isObj(inner) && inner.type === "function" && typeof inner.name === "string") pushFn(inner, ns);
178
+ else if (builtinFunctions && isObj(inner) && inner.type === "custom" && typeof inner.name === "string") pushCustom(inner);
164
179
  }
165
180
  }
166
181
  else if (t.type === "custom" && typeof t.name === "string") {
167
- // Freeform custom tool (e.g. apply_patch). Chat models can't emit a lark grammar, so expose a
168
- // function with a single string `input` carrying the raw tool body; the bridge relays the model's
169
- // call back as a custom_tool_call (Codex's freeform handler rejects a function_call → fatal abort).
170
- out.push({
171
- name: t.name,
172
- description: (t.description as string) ?? "",
173
- parameters: { type: "object", properties: { input: { type: "string", description: "Raw tool input. For apply_patch, begin exactly with `*** Begin Patch` (no trailing `***`), then use its standard patch envelope." } }, required: ["input"] },
174
- freeform: true,
175
- });
182
+ pushCustom(t);
176
183
  }
177
184
  else if (t.type === "tool_search") {
178
185
  // Client-executed tool discovery — the gateway to deferred tools (subagents, extra MCP tools).