@bitkyc08/opencodex 2.79.0 → 2.81.0

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 (245) hide show
  1. package/README.md +3 -3
  2. package/gui/dist/assets/App-7yhoys8a.js +54 -0
  3. package/gui/dist/assets/Tray-EwAOsP0S.js +1 -0
  4. package/gui/dist/assets/index-RsoaAxXY.js +94 -0
  5. package/gui/dist/assets/quota-summary-D2lN8tDm.js +1 -0
  6. package/gui/dist/index.html +1 -1
  7. package/gui/dist/provider-icons/claude-green.svg +1 -0
  8. package/package.json +3 -2
  9. package/src/adapters/anthropic-model-contract.ts +8 -2
  10. package/src/adapters/anthropic.ts +7 -2
  11. package/src/adapters/codebuddy/mcp-server.ts +2 -25
  12. package/src/adapters/codebuddy/tool-bridge.ts +1 -7
  13. package/src/adapters/coding-agent/mcp-server.ts +33 -0
  14. package/src/adapters/coding-agent/protocol.ts +122 -17
  15. package/src/adapters/coding-agent/tool-catalog.ts +75 -0
  16. package/src/adapters/coding-agent/turn.ts +101 -44
  17. package/src/adapters/cursor/catalog.ts +8 -0
  18. package/src/adapters/cursor/effort-map.ts +2 -0
  19. package/src/adapters/cursor/live-transport.ts +5 -3
  20. package/src/adapters/cursor/native-exec-fs.ts +12 -9
  21. package/src/adapters/cursor/native-exec.ts +13 -5
  22. package/src/adapters/cursor/protobuf-request.ts +13 -7
  23. package/src/adapters/cursor/request-builder.ts +23 -10
  24. package/src/adapters/cursor/tool-definitions.ts +9 -6
  25. package/src/adapters/cursor/tool-guidance.ts +29 -8
  26. package/src/adapters/cursor/tool-naming.ts +40 -7
  27. package/src/adapters/cursor/tool-wording.ts +46 -0
  28. package/src/adapters/cursor.ts +3 -0
  29. package/src/adapters/devin/live-models.ts +2 -0
  30. package/src/adapters/devin.ts +25 -11
  31. package/src/adapters/kiro-retry.ts +9 -4
  32. package/src/adapters/openai-chat/messages.ts +7 -4
  33. package/src/adapters/physical-send.ts +8 -5
  34. package/src/adapters/qoder/adapter.ts +41 -6
  35. package/src/adapters/qoder/scaffold-guard.ts +2 -3
  36. package/src/adapters/zed.ts +16 -1
  37. package/src/claude/inbound-cache-stabilize.ts +4 -9
  38. package/src/claude/inbound.ts +10 -0
  39. package/src/claude/intercept/model-bindings.ts +1 -0
  40. package/src/claude/intercept/picker-listener.ts +71 -4
  41. package/src/cli/account-anthropic-threshold.ts +14 -5
  42. package/src/cli/account-api.ts +3 -1
  43. package/src/cli/account-extended.ts +13 -9
  44. package/src/cli/account-policy-dto.ts +1 -1
  45. package/src/cli/account-policy.ts +13 -4
  46. package/src/cli/account.ts +3 -3
  47. package/src/cli/capabilities-accounts.ts +2 -2
  48. package/src/cli/capabilities-agents-routing.ts +24 -0
  49. package/src/cli/capabilities-integrations.ts +16 -0
  50. package/src/cli/codex-shim-autorestore.ts +3 -0
  51. package/src/cli/dispatch.ts +10 -1
  52. package/src/cli/help.ts +4 -1
  53. package/src/cli/index.ts +11 -5
  54. package/src/cli/integration-plan-dto.ts +1 -0
  55. package/src/cli/integration-preview.ts +8 -1
  56. package/src/cli/integrations.ts +32 -3
  57. package/src/cli/message-args.ts +34 -0
  58. package/src/cli/message-command.ts +43 -0
  59. package/src/cli/message-runtime.ts +6 -0
  60. package/src/cli/observe.ts +3 -1
  61. package/src/cli/provider.ts +29 -6
  62. package/src/cli/registry.ts +24 -2
  63. package/src/clients/config-export/commandcode.ts +131 -0
  64. package/src/clients/config-export/contracts.ts +12 -0
  65. package/src/clients/config-export.ts +64 -1
  66. package/src/codex/auth-api/account-list.ts +11 -3
  67. package/src/codex/auth-api/main-account-probe.ts +25 -8
  68. package/src/codex/auth-api/pool-mode-gate.ts +33 -9
  69. package/src/codex/auth-api/pool-quota-probe.ts +15 -1
  70. package/src/codex/auth-api/routes.ts +1 -0
  71. package/src/codex/autostart-health.ts +3 -3
  72. package/src/codex/catalog/auto-review.ts +13 -6
  73. package/src/codex/catalog/build-entries.ts +15 -7
  74. package/src/codex/catalog/control-plane.ts +45 -0
  75. package/src/codex/catalog/effort.ts +11 -1
  76. package/src/codex/catalog/gather-capture.ts +5 -3
  77. package/src/codex/catalog/parsing.ts +2 -1
  78. package/src/codex/catalog/provider-models.ts +15 -9
  79. package/src/codex/control-plane-models.ts +6 -0
  80. package/src/codex/journal.ts +36 -5
  81. package/src/codex/shim-overlay.ts +9 -1
  82. package/src/combos/jev-decision-contract.ts +25 -2
  83. package/src/combos/jev.ts +6 -3
  84. package/src/combos/types.ts +1 -1
  85. package/src/config/diagnostics.ts +27 -16
  86. package/src/config/load-degrade.ts +34 -0
  87. package/src/config/schema/anthropic-account-pool.ts +143 -0
  88. package/src/config/schema/config-schema.ts +7 -1
  89. package/src/config/schema/leaf-validators.ts +4 -0
  90. package/src/config.ts +2 -0
  91. package/src/generated/compatibility-version.json +347 -199
  92. package/src/generated/model-metadata.ts +5 -4
  93. package/src/images/loop.ts +2 -1
  94. package/src/integrations/catalog-refresh.ts +1 -1
  95. package/src/integrations/mutation-plan.ts +7 -0
  96. package/src/integrations/registry.ts +8 -0
  97. package/src/integrations/state.ts +9 -2
  98. package/src/integrations/writer.ts +8 -2
  99. package/src/lib/lab-live-route-production.ts +9 -1
  100. package/src/lib/request-execution-budget.ts +236 -58
  101. package/src/lib/spend-pool-alias-validation.ts +79 -0
  102. package/src/lib/spend-pool-continuity.ts +34 -0
  103. package/src/lib/spend-reservation-ledger.ts +412 -50
  104. package/src/lib/state-store-registrations.ts +20 -3
  105. package/src/lib/upstream-retry.ts +17 -5
  106. package/src/lib/workflow-budget.ts +53 -11
  107. package/src/messaging/budget.ts +45 -0
  108. package/src/messaging/discovery.ts +57 -0
  109. package/src/messaging/envelope.ts +49 -0
  110. package/src/messaging/input.ts +37 -0
  111. package/src/messaging/rpc.ts +196 -0
  112. package/src/messaging/send.ts +58 -0
  113. package/src/messaging/socket.ts +72 -0
  114. package/src/messaging/types.ts +29 -0
  115. package/src/oauth/anthropic-account-refusal.ts +51 -17
  116. package/src/oauth/anthropic-account-threshold.ts +8 -2
  117. package/src/oauth/anthropic-continuity.ts +15 -1
  118. package/src/oauth/anthropic-model-quota.ts +120 -48
  119. package/src/oauth/anthropic-model-routes.ts +11 -3
  120. package/src/oauth/anthropic-oauth-definitions.ts +98 -0
  121. package/src/oauth/anthropic-pool-config.ts +30 -0
  122. package/src/oauth/anthropic-rate-limit-policy.ts +64 -9
  123. package/src/oauth/anthropic-routing.ts +1202 -866
  124. package/src/oauth/anthropic-send-ownership.ts +41 -0
  125. package/src/oauth/anthropic.ts +4 -1
  126. package/src/oauth/generic-account-failover.ts +3 -1
  127. package/src/oauth/health.ts +8 -6
  128. package/src/oauth/index.ts +90 -173
  129. package/src/oauth/kiro.ts +22 -9
  130. package/src/oauth/login-cli.ts +2 -0
  131. package/src/oauth/model-discovery-auth.ts +43 -0
  132. package/src/oauth/pool-kernel.ts +11 -5
  133. package/src/oauth/pool-settings-capability.ts +5 -3
  134. package/src/oauth/store-anthropic-instance.ts +87 -0
  135. package/src/oauth/store.ts +67 -9
  136. package/src/oauth/token-guardian.ts +2 -0
  137. package/src/oauth/types.ts +2 -0
  138. package/src/protocols/plan-snapshot.ts +5 -0
  139. package/src/protocols/settings.ts +20 -5
  140. package/src/providers/anthropic-instance-id.ts +47 -0
  141. package/src/providers/anthropic-instance.ts +48 -0
  142. package/src/providers/anthropic-reset-grant-ledger.ts +11 -1
  143. package/src/providers/derive.ts +2 -0
  144. package/src/providers/kiro-models.ts +3 -0
  145. package/src/providers/label.ts +1 -1
  146. package/src/providers/model-rename-fields.ts +2 -0
  147. package/src/providers/quota/account-cache.ts +37 -11
  148. package/src/providers/quota/anthropic-account-quota.ts +93 -0
  149. package/src/providers/quota/anthropic-cooldown-recovery.ts +222 -111
  150. package/src/providers/quota/report-cache.ts +24 -1
  151. package/src/providers/quota/vendor-probes-oauth.ts +46 -14
  152. package/src/providers/quota.ts +22 -32
  153. package/src/providers/registry/entries-core.ts +35 -30
  154. package/src/providers/registry/model-ids.ts +1 -0
  155. package/src/providers/registry/model-seeds.ts +7 -4
  156. package/src/providers/registry/types.ts +3 -0
  157. package/src/providers/registry.ts +3 -3
  158. package/src/responses/spill-store.ts +5 -1
  159. package/src/responses/state/metrics.ts +87 -0
  160. package/src/responses/state/snapshot-codec.ts +6 -0
  161. package/src/responses/state/spill-queue.ts +1 -0
  162. package/src/responses/state/unforced-store-false.ts +55 -0
  163. package/src/responses/state.ts +50 -66
  164. package/src/router.ts +28 -4
  165. package/src/routing/compatibility/assemble.ts +1 -1
  166. package/src/routing/quota.ts +7 -3
  167. package/src/server/auth-cors.ts +5 -0
  168. package/src/server/chat-completions.ts +6 -1
  169. package/src/server/chat-native.ts +45 -25
  170. package/src/server/claude-messages.ts +16 -2
  171. package/src/server/gui-static.ts +38 -4
  172. package/src/server/index/spend-ledger-lifecycle.ts +10 -4
  173. package/src/server/index.ts +16 -16
  174. package/src/server/inference/context.ts +1 -1
  175. package/src/server/lifecycle.ts +1 -1
  176. package/src/server/management/agent-settings-routes.ts +30 -6
  177. package/src/server/management/anthropic-account-threshold.ts +12 -9
  178. package/src/server/management/anthropic-pool-settings.ts +72 -0
  179. package/src/server/management/anthropic-reset-grant-routes.ts +98 -39
  180. package/src/server/management/config-routes.ts +27 -7
  181. package/src/server/management/decision-routes.ts +2 -1
  182. package/src/server/management/integration-routes.ts +25 -2
  183. package/src/server/management/oauth-account-routes.ts +79 -98
  184. package/src/server/management/provider-instance-ownership.ts +44 -0
  185. package/src/server/management/provider-routes.ts +21 -28
  186. package/src/server/management/route-registry.ts +3 -1
  187. package/src/server/management/routing-profile-routes.ts +4 -4
  188. package/src/server/management/system-restart.ts +44 -14
  189. package/src/server/management/system-routes.ts +24 -2
  190. package/src/server/management/vision-sidecar-options.ts +9 -6
  191. package/src/server/management/web-search-sidecar-options.ts +51 -2
  192. package/src/server/management-auth.ts +6 -0
  193. package/src/server/messages-native-eligibility.ts +3 -2
  194. package/src/server/messages-native-oauth.ts +86 -41
  195. package/src/server/messages-native-scope.ts +4 -1
  196. package/src/server/messages-native-selector.ts +39 -0
  197. package/src/server/messages-native.ts +84 -25
  198. package/src/server/request-log.ts +5 -0
  199. package/src/server/responses/adapter-continuation.ts +29 -17
  200. package/src/server/responses/adapter-dispatch.ts +47 -17
  201. package/src/server/responses/antigravity-validation-refusal.ts +20 -6
  202. package/src/server/responses/combo-requested-effort.ts +14 -0
  203. package/src/server/responses/compact.ts +25 -8
  204. package/src/server/responses/compaction-recovery.ts +1 -1
  205. package/src/server/responses/core-combo-native.ts +4 -1
  206. package/src/server/responses/core-combo.ts +21 -18
  207. package/src/server/responses/core-normalize.ts +1 -0
  208. package/src/server/responses/core-options.ts +3 -1
  209. package/src/server/responses/core-replay.ts +5 -0
  210. package/src/server/responses/passthrough-delivery.ts +7 -3
  211. package/src/server/responses/passthrough-dispatch.ts +21 -8
  212. package/src/server/responses/request-prepare.ts +37 -5
  213. package/src/server/responses/request-send-budget.ts +74 -37
  214. package/src/server/responses/request-spend.ts +325 -33
  215. package/src/server/responses/request-transport.ts +132 -52
  216. package/src/server/responses/run-turn-execution.ts +11 -3
  217. package/src/server/responses/sidecar-execution.ts +96 -14
  218. package/src/server/responses-undeclared-tool-guard.ts +5 -1
  219. package/src/server/workflow-refusal.ts +30 -0
  220. package/src/service/desktop-startup.ts +100 -3
  221. package/src/service/ownership-mutation-lease.d.mts +1 -1
  222. package/src/service/ownership-mutation-lease.mjs +5 -7
  223. package/src/sidecar/anthropic-binding.ts +79 -0
  224. package/src/sidecar/auth.ts +76 -2
  225. package/src/types/anthropic-account-pool.ts +33 -0
  226. package/src/types/config.ts +12 -28
  227. package/src/types/provider.ts +5 -0
  228. package/src/types/tools.ts +7 -0
  229. package/src/types.ts +4 -0
  230. package/src/usage/cost.ts +3 -2
  231. package/src/usage/expected-prices.ts +66 -14
  232. package/src/vision/anthropic-describe.ts +16 -3
  233. package/src/vision/index.ts +3 -0
  234. package/src/vision/plan.ts +19 -6
  235. package/src/web-search/alpha-search.ts +7 -1
  236. package/src/web-search/anthropic-executor.ts +16 -4
  237. package/src/web-search/header-deadline.ts +67 -0
  238. package/src/web-search/index.ts +7 -3
  239. package/src/web-search/loop.ts +32 -10
  240. package/src/web-search/passthrough-bridge.ts +4 -1
  241. package/src/web-search/sidecar-providers.ts +4 -3
  242. package/gui/dist/assets/App-BOUa-ek3.js +0 -54
  243. package/gui/dist/assets/Tray-DUtzB4zF.js +0 -1
  244. package/gui/dist/assets/index-DwHNDF4s.js +0 -94
  245. package/gui/dist/assets/quota-summary-BuL4WIBo.js +0 -1
@@ -0,0 +1,143 @@
1
+ import * as z from "zod/v4";
2
+ import { parseAnthropicModelRoutes } from "../../oauth/anthropic-model-routes";
3
+ import { isAnthropicInstanceId } from "../../providers/anthropic-instance-id";
4
+ import { redactSecretString } from "../../lib/redact";
5
+
6
+ /** Historical A load contract, shared verbatim with B: recover only the native preference. */
7
+ export const anthropicAccountPoolSchema = z.object({
8
+ nativeMessages: z.boolean().optional().catch(false),
9
+ }).passthrough().optional().catch(undefined);
10
+
11
+ function record(value: unknown): Record<string, unknown> | undefined {
12
+ return value && typeof value === "object" && !Array.isArray(value)
13
+ ? value as Record<string, unknown> : undefined;
14
+ }
15
+
16
+ /** Write/diagnostic contract preserves A's historical nativeMessages and route validation. */
17
+ function poolError(value: unknown, path: string): string | undefined {
18
+ if (value === undefined) return undefined;
19
+ const pool = record(value);
20
+ if (!pool) return `schema_invalid: ${path}: must be an object`;
21
+ if (Object.hasOwn(pool, "nativeMessages") && typeof pool.nativeMessages !== "boolean") {
22
+ return `schema_invalid: ${path}.nativeMessages: must be a boolean`;
23
+ }
24
+ if (pool.routes !== undefined) {
25
+ const parsed = parseAnthropicModelRoutes(pool.routes);
26
+ if (!parsed.ok) return `schema_invalid: ${path}.routes: ${parsed.error}`;
27
+ }
28
+ return undefined;
29
+ }
30
+
31
+ /** Inspect raw locations before the tolerant load schema can discard a malformed field. */
32
+ export function anthropicAccountPoolConfigError(value: unknown): string | undefined {
33
+ const config = record(value);
34
+ const primaryError = poolError(config?.anthropicAccountPool, "anthropicAccountPool");
35
+ if (primaryError) return primaryError;
36
+ for (const [name, raw] of Object.entries(record(config?.providers) ?? {})) {
37
+ const provider = record(raw);
38
+ if (!provider || !Object.hasOwn(provider, "anthropicAccountPool")) continue;
39
+ const path = `providers.${redactSecretString(name)}.anthropicAccountPool`;
40
+ if (name !== "anthropic2") {
41
+ return `schema_invalid: ${path}: misplaced field; provider-local anthropicAccountPool is valid only on anthropic2 (anthropic uses the top-level field)`;
42
+ }
43
+ const error = poolError(provider.anthropicAccountPool, path);
44
+ if (error) return error;
45
+ }
46
+ return undefined;
47
+ }
48
+
49
+ /** Raw provenance validation runs before tolerant parsing and never adopts or edits a row. */
50
+ export function anthropicOAuthInstanceConfigError(value: unknown): string | undefined {
51
+ const seen = new WeakSet<object>();
52
+ const inspect = (raw: unknown, location: string[]): string | undefined => {
53
+ if (!raw || typeof raw !== "object" || seen.has(raw)) return undefined;
54
+ seen.add(raw);
55
+ for (const [field, descriptor] of Object.entries(Object.getOwnPropertyDescriptors(raw))) {
56
+ const path = [...location, field];
57
+ if (field === "anthropicOAuthInstance") {
58
+ const label = redactSecretString(path.join("."));
59
+ if (!("value" in descriptor)) return `schema_invalid: ${label}: must be an own data property`;
60
+ if (location.length !== 2 || location[0] !== "providers" || location[1] !== "anthropic2") {
61
+ return `schema_invalid: ${label}: misplaced field; valid only on providers.anthropic2`;
62
+ }
63
+ if (descriptor.value !== "anthropic2") return `schema_invalid: ${label}: must be anthropic2`;
64
+ const row = Object.getOwnPropertyDescriptors(raw);
65
+ if (row.adapter?.value !== "anthropic" || row.authMode?.value !== "oauth") {
66
+ return `schema_invalid: ${label}: requires Anthropic adapter and OAuth authMode`;
67
+ }
68
+ }
69
+ if (!("value" in descriptor)) continue;
70
+ const error = inspect(descriptor.value, path);
71
+ if (error) return error;
72
+ }
73
+ seen.delete(raw);
74
+ return undefined;
75
+ };
76
+ return inspect(value, []);
77
+ }
78
+
79
+ /** Validate explicit helper identity without materializing an absent instance preference. */
80
+ export function anthropicSidecarConfigError(value: unknown): string | undefined {
81
+ const config = record(value);
82
+ const claude = record(config?.claudeCode);
83
+ for (const [prefix, owner] of [["", config], ["claudeCode.", claude]] as const) {
84
+ for (const field of ["webSearchSidecar", "visionSidecar"] as const) {
85
+ const rawSidecar = record(owner?.[field]);
86
+ if (!rawSidecar) continue;
87
+ // Claude overrides inherit individual global fields, just like buildClaudeReplayConfig.
88
+ const sidecar = prefix ? { ...record(config?.[field]), ...rawSidecar } : rawSidecar;
89
+ if (!Object.hasOwn(sidecar, "anthropicInstance")) continue;
90
+ const path = `${prefix}${field}.anthropicInstance`;
91
+ if (!isAnthropicInstanceId(sidecar.anthropicInstance)) {
92
+ return `schema_invalid: ${path}: must be anthropic or anthropic2`;
93
+ }
94
+ // Web search defaults to OpenAI; vision's absent backend keeps its credential-based auto mode.
95
+ const backend = sidecar.backend === undefined
96
+ ? (field === "webSearchSidecar" ? "openai" : undefined) : sidecar.backend;
97
+ // An instance inherited from the global block is inert once the override's effective backend
98
+ // leaves Anthropic (the helper resolver only reads it for the Anthropic family), so it is not
99
+ // a conflict. An instance the override sets itself is still validated in full.
100
+ if (prefix && !Object.hasOwn(rawSidecar, "anthropicInstance") && backend !== undefined && backend !== "anthropic") continue;
101
+ const modelProvider = typeof sidecar.model === "string" && sidecar.model.includes("/")
102
+ ? sidecar.model.slice(0, sidecar.model.indexOf("/")) : undefined;
103
+ if (modelProvider && isAnthropicInstanceId(modelProvider) && modelProvider !== sidecar.anthropicInstance) {
104
+ return `schema_invalid: ${path}: conflicts with the model's Anthropic instance`;
105
+ }
106
+ if (backend !== undefined && backend !== "anthropic") {
107
+ return `schema_invalid: ${path}: requires an anthropic backend`;
108
+ }
109
+ }
110
+ }
111
+ return undefined;
112
+ }
113
+
114
+ /** Validate the effective settings before either management route mutates live state. */
115
+ export function anthropicSidecarPatchError(
116
+ config: unknown,
117
+ patches: Record<string, unknown>,
118
+ claude = false,
119
+ ): string | undefined {
120
+ const source = record(config) ?? {};
121
+ const next = { ...source };
122
+ const owner = claude ? { ...record(source.claudeCode) } : next;
123
+ for (const field of ["webSearchSidecar", "visionSidecar"] as const) {
124
+ if (!Object.hasOwn(patches, field)) continue;
125
+ const patch = patches[field];
126
+ if (patch === null) { delete owner[field]; continue; }
127
+ const section = record(patch);
128
+ if (!section) continue; // Shape validation belongs to the route.
129
+ if (section.anthropicInstance !== undefined && section.anthropicInstance !== null
130
+ && !isAnthropicInstanceId(section.anthropicInstance)) {
131
+ return `${field}.anthropicInstance must be anthropic, anthropic2, or null`;
132
+ }
133
+ const settings = { ...record(owner[field]) };
134
+ for (const key of ["backend", "model", "anthropicInstance"] as const) {
135
+ if (section[key] === null || (key === "model" && section[key] === "")) delete settings[key];
136
+ else if (section[key] !== undefined) settings[key] = section[key];
137
+ }
138
+ if (claude && (Object.keys(section).length === 0 || Object.keys(settings).length === 0)) delete owner[field];
139
+ else owner[field] = settings;
140
+ }
141
+ if (claude) next.claudeCode = owner;
142
+ return anthropicSidecarConfigError(next);
143
+ }
@@ -1,5 +1,6 @@
1
1
  import { MAIN_ACCOUNT_HARD_LOCK_MIN_PERCENT } from "../../codex/quota-types";
2
2
  import * as z from "zod/v4";
3
+ import { anthropicAccountPoolSchema } from "./anthropic-account-pool";
3
4
  import { compactionRecoverySchema } from "./compaction-recovery";
4
5
  import { blockedModelRedirectsSchema } from "./blocked-model-redirects";
5
6
  import {
@@ -327,7 +328,7 @@ export const configSchema = z.object({
327
328
  blockedModelRedirects: blockedModelRedirectsSchema.optional().catch(undefined),
328
329
  // Degrade malformed hand edits locally; candidate writes reject them before parsing.
329
330
  // An invalid native preference retains the legacy route instead of enabling native by default.
330
- anthropicAccountPool: z.object({ nativeMessages: z.boolean().optional().catch(false) }).passthrough().optional().catch(undefined),
331
+ anthropicAccountPool: anthropicAccountPoolSchema,
331
332
  // Same degrade-don't-reject rationale as the fields above: a hand-edited
332
333
  // non-string must not trip the backup-and-defaults repair path. Unset then
333
334
  // takes the canonical sideband path (src/server/live.ts normalizeSidebandRoot).
@@ -350,6 +351,11 @@ export const configSchema = z.object({
350
351
  .map(row => apiKeyEntrySchema.parse(row) as OcxApiKeyEntry);
351
352
  }),
352
353
  }).passthrough().superRefine((config, ctx) => {
354
+ // Helper `anthropicInstance` is deliberately not refined here. A document-level issue would send
355
+ // loadConfig through salvage (which refuses pathless issues) to the backup-and-defaults path, so
356
+ // one hand-edited helper preference would hide every provider. Writes reject it explicitly in
357
+ // validateConfigCandidate, diagnostics report it from the raw file, and loadConfig drops only the
358
+ // offending key (sanitizeAnthropicSidecarInstanceForLoad).
353
359
  const claudeCode = (config as { claudeCode?: unknown }).claudeCode;
354
360
  if (claudeCode !== undefined && (!claudeCode || typeof claudeCode !== "object" || Array.isArray(claudeCode))) {
355
361
  ctx.addIssue({ code: "custom", path: ["claudeCode"], message: "claudeCode must be an object" });
@@ -1,4 +1,5 @@
1
1
  import * as z from "zod/v4";
2
+ import { anthropicAccountPoolSchema } from "./anthropic-account-pool";
2
3
  import { join } from "node:path";
3
4
  import { isValidProviderName } from "../provider-name";
4
5
  import {
@@ -285,6 +286,9 @@ const providerNoProxySchema = z.unknown().superRefine((value, ctx) => {
285
286
  * fields pass through (preserved for runtime extensions).
286
287
  */
287
288
  export const providerConfigSchema = z.object({
289
+ anthropicAccountPool: anthropicAccountPoolSchema,
290
+ // Raw diagnostics/writes reject malformed provenance; tolerant loads preserve the custom row.
291
+ anthropicOAuthInstance: z.literal("anthropic2").optional().catch(undefined),
288
292
  modelCapabilities: modelCapabilitiesSchema.optional(),
289
293
  modelContextTiers: z.unknown().superRefine((value, ctx) => {
290
294
  const error = contextTierRecordConfigError(value);
package/src/config.ts CHANGED
@@ -172,6 +172,7 @@ import {
172
172
  sanitizeModelDisplayNamesForLoad,
173
173
  sanitizeAutoReviewForLoad,
174
174
  sanitizeRetryOn429ForLoad,
175
+ sanitizeAnthropicSidecarInstanceForLoad,
175
176
  sanitizeModelCostsForLoad,
176
177
  sanitizeCapabilityDeclarationsForLoad,
177
178
  warnInheritedFastWireConflicts,
@@ -226,6 +227,7 @@ export function loadConfig(): OcxConfig {
226
227
  sanitizeModelDisplayNamesForLoad(parsed);
227
228
  sanitizeAutoReviewForLoad(parsed);
228
229
  sanitizeRetryOn429ForLoad(parsed);
230
+ sanitizeAnthropicSidecarInstanceForLoad(parsed);
229
231
  sanitizeModelCostsForLoad(parsed);
230
232
  sanitizeCapabilityDeclarationsForLoad(parsed);
231
233
  const result = configSchema.safeParse(parsed);