@bitkyc08/opencodex 2.52.0-preview.20260912 → 2.53.0-preview.20260913

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 (236) hide show
  1. package/gui/dist/assets/index-BBOZWGB6.css +1 -0
  2. package/gui/dist/assets/index-D7ynYo2K.js +128 -0
  3. package/gui/dist/index.html +2 -2
  4. package/native/remote-workspace-helper/Cargo.lock +130 -0
  5. package/native/remote-workspace-helper/Cargo.toml +24 -0
  6. package/native/remote-workspace-helper/src/main.rs +49 -0
  7. package/native/remote-workspace-helper/src/protocol.rs +246 -0
  8. package/native/remote-workspace-helper/src/sandbox/macos.rs +19 -0
  9. package/native/remote-workspace-helper/src/sandbox/mod.rs +77 -0
  10. package/native/remote-workspace-helper/src/sandbox/windows.rs +15 -0
  11. package/package.json +6 -1
  12. package/src/adapters/anthropic-image-normalize.ts +30 -2
  13. package/src/adapters/anthropic.ts +1 -1
  14. package/src/adapters/base.ts +8 -2
  15. package/src/adapters/cursor/cursor-errors.ts +12 -0
  16. package/src/adapters/cursor/thread-continuity.ts +93 -0
  17. package/src/adapters/cursor.ts +104 -73
  18. package/src/adapters/devin/cloud-direct/chat.ts +312 -23
  19. package/src/adapters/devin/cloud-direct/metadata.ts +31 -2
  20. package/src/adapters/devin/live-models.ts +70 -3
  21. package/src/adapters/devin.ts +281 -21
  22. package/src/adapters/google-wire-compiler.ts +14 -6
  23. package/src/adapters/google.ts +22 -8
  24. package/src/adapters/kiro/adapter.ts +316 -0
  25. package/src/adapters/kiro/conversation.ts +136 -0
  26. package/src/adapters/kiro/payload.ts +432 -0
  27. package/src/adapters/kiro/reasoning.ts +56 -0
  28. package/src/adapters/kiro/stream.ts +1153 -0
  29. package/src/adapters/kiro/usage.ts +223 -0
  30. package/src/adapters/kiro/wire.ts +76 -0
  31. package/src/adapters/kiro.ts +8 -2319
  32. package/src/adapters/mimo-free.ts +1 -1
  33. package/src/adapters/openai-chat-images.ts +101 -0
  34. package/src/adapters/openai-chat.ts +201 -181
  35. package/src/adapters/openai-responses.ts +92 -224
  36. package/src/adapters/registry.ts +0 -7
  37. package/src/adapters/run-turn-queue.ts +13 -6
  38. package/src/bridge.ts +14 -15
  39. package/src/chat/inbound.ts +29 -4
  40. package/src/chat/outbound.ts +145 -107
  41. package/src/claude/desktop-profile.ts +4 -6
  42. package/src/cli/account-api.ts +14 -0
  43. package/src/cli/account-extended.ts +1 -1
  44. package/src/cli/account-history.ts +60 -0
  45. package/src/cli/account-main.ts +80 -0
  46. package/src/cli/account.ts +11 -3
  47. package/src/cli/capabilities.ts +113 -0
  48. package/src/cli/catalog.ts +109 -0
  49. package/src/cli/dispatch.ts +9 -0
  50. package/src/cli/help.ts +2 -0
  51. package/src/cli/index.ts +2 -2
  52. package/src/cli/observe.ts +28 -1
  53. package/src/cli/opencode.ts +42 -8
  54. package/src/cli/provider-runtime.ts +11 -1
  55. package/src/cli/provider.ts +22 -2
  56. package/src/cli/registry.ts +21 -0
  57. package/src/cli/remote-workspace.ts +154 -0
  58. package/src/cli/status.ts +39 -7
  59. package/src/cli/usage-report.ts +14 -2
  60. package/src/client/hub-client.ts +34 -0
  61. package/src/client/hub-state.ts +9 -1
  62. package/src/codex/account-store.ts +78 -0
  63. package/src/codex/auth-api.ts +81 -54
  64. package/src/codex/auth-context.ts +45 -16
  65. package/src/codex/catalog/effort.ts +1 -1
  66. package/src/codex/catalog/metadata.ts +3 -6
  67. package/src/codex/catalog/native-models.ts +4 -4
  68. package/src/codex/catalog/parsing.ts +2 -20
  69. package/src/codex/catalog/provider-fetch.ts +10 -1
  70. package/src/codex/catalog/remote.ts +233 -0
  71. package/src/codex/catalog/sync.ts +403 -35
  72. package/src/codex/convergence.ts +1 -1
  73. package/src/codex/history-manifest.ts +36 -0
  74. package/src/codex/history-provider.ts +32 -5
  75. package/src/codex/inject.ts +9 -0
  76. package/src/codex/main-account.ts +113 -0
  77. package/src/codex/main-device-reauth-api.ts +89 -0
  78. package/src/codex/main-device-reauth.ts +217 -0
  79. package/src/codex/native-residue.ts +9 -2
  80. package/src/codex/quota-auto-refresh.ts +3 -2
  81. package/src/codex/quota-capacity.ts +98 -0
  82. package/src/codex/quota-history.ts +160 -0
  83. package/src/codex/quota-types.ts +8 -0
  84. package/src/codex/quota.ts +118 -91
  85. package/src/codex/refresh.ts +2 -1
  86. package/src/codex/routing.ts +90 -17
  87. package/src/codex/sync.ts +33 -4
  88. package/src/combos/request.ts +19 -1
  89. package/src/config/multi-agent-surface.ts +61 -0
  90. package/src/config/provider-validation.ts +176 -0
  91. package/src/config.ts +213 -11
  92. package/src/generated/compatibility-version.json +436 -168
  93. package/src/images/loop.ts +119 -36
  94. package/src/lib/admission.ts +12 -6
  95. package/src/lib/redact.ts +7 -0
  96. package/src/lib/translator-budget.ts +4 -3
  97. package/src/lib/windows-atomic-replace.ts +1 -0
  98. package/src/lib/windows-elevation.ts +1 -1
  99. package/src/oauth/chatgpt-device.ts +62 -5
  100. package/src/oauth/devin/cli-import.ts +130 -0
  101. package/src/oauth/devin.ts +63 -8
  102. package/src/oauth/index.ts +29 -14
  103. package/src/oauth/kiro.ts +18 -6
  104. package/src/oauth/login-cli.ts +9 -1
  105. package/src/oauth/meta-muse-device.ts +464 -0
  106. package/src/oauth/meta-muse.ts +123 -32
  107. package/src/oauth/pool-kernel.ts +9 -0
  108. package/src/oauth/pool-settings-capability.ts +2 -2
  109. package/src/oauth/store.ts +57 -0
  110. package/src/oauth/types.ts +31 -0
  111. package/src/providers/derive.ts +13 -3
  112. package/src/providers/devin-cli-authmode-migration.ts +57 -35
  113. package/src/providers/devin-provider-merge-migration.ts +240 -0
  114. package/src/providers/muse-key-quota.ts +117 -0
  115. package/src/providers/muse-subscription-usage.ts +14 -2
  116. package/src/providers/openai-sidecar.ts +25 -3
  117. package/src/providers/opencode-zen-rate-limit.ts +58 -0
  118. package/src/providers/provider-id-rewrite.ts +20 -5
  119. package/src/providers/quota-types.ts +12 -0
  120. package/src/providers/quota.ts +143 -102
  121. package/src/providers/reasoning-metadata.ts +543 -0
  122. package/src/providers/registry.ts +80 -49
  123. package/src/reasoning-effort.ts +26 -2
  124. package/src/remote/hub-usage.ts +32 -0
  125. package/src/remote-control/index.ts +192 -41
  126. package/src/remote-control/workspace-activation.ts +9 -0
  127. package/src/remote-control/workspace-agent-connection.ts +366 -0
  128. package/src/remote-control/workspace-claude-runtime.ts +243 -0
  129. package/src/remote-control/workspace-codex-runtime.ts +531 -0
  130. package/src/remote-control/workspace-codex-sandbox.ts +115 -0
  131. package/src/remote-control/workspace-command-runner.ts +748 -0
  132. package/src/remote-control/workspace-coordinator.ts +231 -0
  133. package/src/remote-control/workspace-device.ts +585 -0
  134. package/src/remote-control/workspace-executable.ts +43 -0
  135. package/src/remote-control/workspace-executor.ts +397 -0
  136. package/src/remote-control/workspace-hub.ts +519 -0
  137. package/src/remote-control/workspace-pi-runtime.ts +382 -0
  138. package/src/remote-control/workspace-process.ts +129 -0
  139. package/src/remote-control/workspace-rpc.ts +304 -0
  140. package/src/remote-control/workspace-runtime.ts +60 -0
  141. package/src/remote-control/workspace-secret-store.ts +39 -0
  142. package/src/remote-control/workspace-sessions.ts +799 -0
  143. package/src/remote-control/workspace-tool-bridge.ts +192 -0
  144. package/src/responses/code-mode-helper-compat.ts +22 -3
  145. package/src/responses/hosted-tool-policy.ts +0 -1
  146. package/src/responses/muse-tool-name-alias.ts +379 -0
  147. package/src/responses/plaintext-v2-agent-messages.ts +902 -0
  148. package/src/router.ts +7 -0
  149. package/src/routing/compatibility/behavior.ts +0 -1
  150. package/src/server/audio-client.ts +64 -0
  151. package/src/server/audio-dictation.ts +91 -0
  152. package/src/server/audio-live.ts +185 -0
  153. package/src/server/audio-transcriptions.ts +183 -0
  154. package/src/server/audio-upstream.ts +153 -0
  155. package/src/server/auth-cors.ts +61 -2
  156. package/src/server/chat-completions.ts +1 -1
  157. package/src/server/chat-native-sse.ts +92 -48
  158. package/src/server/chat-native.ts +37 -15
  159. package/src/server/hub-usage.ts +57 -0
  160. package/src/server/images.ts +4 -0
  161. package/src/server/index.ts +722 -57
  162. package/src/server/lifecycle.ts +5 -6
  163. package/src/server/live-call-bindings.ts +60 -0
  164. package/src/server/live.ts +12 -1
  165. package/src/server/management/agent-settings-routes.ts +25 -4
  166. package/src/server/management/api-access.ts +37 -0
  167. package/src/server/management/api-key-usage.ts +7 -2
  168. package/src/server/management/config-routes.ts +1 -18
  169. package/src/server/management/context.ts +15 -0
  170. package/src/server/management/logs-usage-routes.ts +2 -0
  171. package/src/server/management/oauth-account-routes.ts +39 -12
  172. package/src/server/management/provider-routes.ts +125 -2
  173. package/src/server/management/remote-workspace-routes.ts +140 -0
  174. package/src/server/management/route-registry.ts +15 -0
  175. package/src/server/management/usage-aggregate-cache.ts +14 -15
  176. package/src/server/management/usage-summary-cache.ts +2 -0
  177. package/src/server/management-api.ts +23 -0
  178. package/src/server/ports.ts +17 -0
  179. package/src/server/relay-eager.ts +4 -1
  180. package/src/server/relay.ts +70 -10
  181. package/src/server/request-decompress.ts +6 -3
  182. package/src/server/responses/agent-task-recovery.ts +25 -32
  183. package/src/server/responses/codex-auth-error.ts +11 -0
  184. package/src/server/responses/codex-ws-exchange.ts +52 -3
  185. package/src/server/responses/codex-ws-wire.ts +55 -0
  186. package/src/server/responses/compact.ts +9 -1
  187. package/src/server/responses/core.ts +337 -73
  188. package/src/server/responses/encrypted-payload.ts +45 -2
  189. package/src/server/responses/ws-upstream.ts +4 -1
  190. package/src/server/responses-self-named-namespace-scrub.ts +1 -3
  191. package/src/server/responses-undeclared-tool-guard.ts +1 -1
  192. package/src/server/search.ts +3 -0
  193. package/src/server/sse-payload-rewrite.ts +136 -51
  194. package/src/server/ws-bridge.ts +35 -1
  195. package/src/service/cli.ts +372 -0
  196. package/src/service/diagnostics.ts +340 -0
  197. package/src/service/guards.ts +303 -0
  198. package/src/service/health.ts +222 -0
  199. package/src/service/launchd.ts +853 -0
  200. package/src/service/orchestration.ts +617 -0
  201. package/src/service/repair.ts +334 -0
  202. package/src/service/state.ts +363 -0
  203. package/src/service/systemd.ts +229 -0
  204. package/src/service/windows-ops.ts +690 -0
  205. package/src/service/windows-scheduler.ts +769 -0
  206. package/src/service/windows-taskxml.ts +613 -0
  207. package/src/service.ts +22 -5550
  208. package/src/storage/cleanup/db.ts +258 -0
  209. package/src/storage/cleanup/execute.ts +358 -0
  210. package/src/storage/cleanup/paths.ts +189 -0
  211. package/src/storage/cleanup/pending.ts +140 -0
  212. package/src/storage/cleanup/preview.ts +292 -0
  213. package/src/storage/cleanup/reconcile.ts +347 -0
  214. package/src/storage/cleanup/restore.ts +932 -0
  215. package/src/storage/cleanup/satellite.ts +474 -0
  216. package/src/storage/cleanup/staging.ts +129 -0
  217. package/src/storage/cleanup/types.ts +98 -0
  218. package/src/storage/cleanup.ts +49 -3127
  219. package/src/types/accounts.ts +2 -0
  220. package/src/types/config.ts +13 -12
  221. package/src/types/provider.ts +37 -0
  222. package/src/types/request.ts +2 -0
  223. package/src/types/tools.ts +17 -5
  224. package/src/types.ts +1 -0
  225. package/src/usage/expected-prices.ts +127 -0
  226. package/src/usage/log.ts +58 -1
  227. package/src/vision/eligibility.ts +13 -2
  228. package/src/web-search/loop.ts +56 -3
  229. package/gui/dist/assets/index-D_t6sCWs.js +0 -115
  230. package/gui/dist/assets/index-EdoPnm9_.css +0 -1
  231. package/src/adapters/devin-cli/acp.ts +0 -204
  232. package/src/adapters/devin-cli/adapter.ts +0 -345
  233. package/src/adapters/devin-cli/binary.ts +0 -69
  234. package/src/adapters/devin-cli/models.ts +0 -57
  235. package/src/oauth/devin-cli.ts +0 -149
  236. package/src/server/responses-reasoning-summary-rewrite.ts +0 -178
@@ -1,7 +1,7 @@
1
1
  import type { CodexAccountMode, FastWire, OcxProviderConfig } from "../types";
2
2
  import { fastWireDeclarationError } from "./fastwire";
3
3
  import { KIRO_MODELS, KIRO_MODEL_CONTEXT_WINDOWS, KIRO_MODEL_REASONING_EFFORTS } from "./kiro-models";
4
- import { DEVIN_MODEL_CONTEXT_WINDOWS } from "../adapters/devin/live-models";
4
+ import { DEVIN_MODEL_CONTEXT_WINDOWS, DEVIN_MODEL_EFFORTS, DEVIN_DEFAULT_EFFORTS } from "../adapters/devin/live-models";
5
5
  import { ANTIGRAVITY_MODELS, ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, ANTIGRAVITY_MODEL_EFFORTS, ANTIGRAVITY_MODEL_INPUT_MODALITIES } from "./antigravity-models";
6
6
  import type { ProviderBaseUrlChoice } from "./base-url-choices";
7
7
  import {
@@ -356,6 +356,10 @@ export interface ProviderRegistryEntry {
356
356
  autoToolChoiceOnlyModels?: string[];
357
357
  preserveReasoningContentModels?: string[];
358
358
  requiresReasoningPlaceholderModels?: string[];
359
+ /**
360
+ * Opt this provider into visible thinking summaries (see OcxProviderConfig.showThinkingSummary).
361
+ */
362
+ showThinkingSummary?: boolean;
359
363
  reasoningSplitModels?: string[];
360
364
  reasoningDetailsModels?: string[];
361
365
  thinkingToggleModels?: string[];
@@ -380,7 +384,7 @@ export type ProviderConfigSeed = Pick<
380
384
  | "modelMaxInputTokens" | "defaultMaxOutputTokens" | "modelMaxOutputTokens"
381
385
  | "reasoningEfforts" | "modelReasoningEfforts" | "modelDefaultReasoningEfforts" | "reasoningEffortMap" | "modelReasoningEffortMap" | "reasoningWireFormat"
382
386
  | "noVisionModels" | "noReasoningModels" | "noTemperatureModels" | "noTopPModels" | "noPenaltyModels"
383
- | "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "requiresReasoningPlaceholderModels" | "reasoningSplitModels" | "reasoningDetailsModels" | "thinkingToggleModels" | "thinkingBudgetModels" | "escapeBuiltinToolNames" | "openaiChatEofTolerance"
387
+ | "autoToolChoiceOnlyModels" | "preserveReasoningContentModels" | "requiresReasoningPlaceholderModels" | "reasoningSplitModels" | "reasoningDetailsModels" | "thinkingToggleModels" | "thinkingBudgetModels" | "escapeBuiltinToolNames" | "openaiChatEofTolerance" | "showThinkingSummary"
384
388
  | "googleMode" | "project" | "location" | "headers"
385
389
  >;
386
390
 
@@ -1315,55 +1319,48 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1315
1319
  noVisionModels: [...CURSOR_NO_VISION_MODELS],
1316
1320
  },
1317
1321
  {
1318
- // The signed-in Devin CLI as an account source.
1319
- //
1320
- // The CLI writes a `devin-session-token$<JWT>` to its own credentials.toml,
1321
- // which is the same credential RegisterUser hands `ocx login devin` and which
1322
- // the cloud-direct client already speaks. So this provider imports that token
1323
- // and streams over Connect-RPC like its browser-login sibling, rather than
1324
- // spawning `devin acp`.
1322
+ // The canonical Cognition account provider, after absorbing `devin-cli`
1323
+ // (devlog/_plan/260913_devin_provider_merge). The two ids were the same
1324
+ // `devin` adapter, the same server.codeium.com api-server, and the same
1325
+ // `devin-session-token$<JWT>` credential — only the account source
1326
+ // differed: this entry did an Auth0 browser sign-in while `devin-cli`
1327
+ // imported the token the installed CLI's own PKCE login had already
1328
+ // written to credentials.toml. The merged login is import-first with a
1329
+ // browser fallback: the CLI credential is taken when present (no browser
1330
+ // opens), and the Auth0 flow remains because it is the only path for
1331
+ // users without the CLI. `devin-cli` survives only as a deprecated
1332
+ // alias; a startup migration rewrites saved provider rows, cross-config
1333
+ // references, and auth.json slots to `devin`.
1325
1334
  //
1326
1335
  // `oauth` classifies the ACCOUNT, not the transport. This is not a local
1327
- // runtime: unlike Ollama or LM Studio it cannot answer at all until a vendor
1328
- // account is signed in, and `local` grouped it with things that have no
1329
- // account. It is also the only classification that reaches the dashboard
1330
- // Accounts tab, which is built from OAUTH_PROVIDERS.
1331
- //
1332
- // The ACP adapter stays registered and tested. It is no longer reachable
1333
- // under THIS id — `routedProviderConfig` pins the adapter from the registry
1334
- // for any row whose name is a registry id — but a custom-named row such as
1335
- // `{"devin-acp": {"adapter": "devin-cli", ...}}` is not pinned and still gets it.
1336
- id: "devin-cli",
1337
- label: "Devin CLI",
1338
- adapter: "devin",
1339
- baseUrl: "https://server.codeium.com",
1340
- authKind: "oauth",
1341
- featured: false,
1342
- // Off, like `devin`. `deriveProviderPresets` keys the preset catalog off this
1343
- // flag, so leaving it true would draw the row twice: an Accounts login row and
1344
- // a preset tile.
1345
- dashboardPreset: false,
1346
- note: "Imports the credential your installed Devin CLI already holds (`devin auth login`), then streams over Cognition's Connect-RPC api-server like the `devin` provider. No browser sign-in and no key to paste. For the CLI's own local agent loop over ACP stdio instead, configure a custom-named provider row with \"adapter\": \"devin-cli\".",
1347
- // Degraded-mode seed only; `liveModels` discovers the account's real roster,
1348
- // which is where `swe-2` and the rest of the current catalog come from.
1349
- models: ["swe-2", "swe-1-7", "gpt-5-6-sol", "gpt-6-astra", "claude-opus-5", "claude-fable-5-1", "claude-sonnet-5", "glm-5-3", "kimi-k3", "gemini-3-8-flash", "grok-4-6"],
1350
- liveModels: true,
1351
- defaultModel: "swe-2",
1352
- modelContextWindows: DEVIN_MODEL_CONTEXT_WINDOWS,
1353
- },
1354
- {
1336
+ // runtime: unlike Ollama or LM Studio it cannot answer at all until a
1337
+ // vendor account is signed in, and `local` grouped it with things that
1338
+ // have no account. It is also the only classification that reaches the
1339
+ // dashboard Accounts tab, which is built from OAUTH_PROVIDERS.
1355
1340
  id: "devin",
1356
1341
  label: "Cognition (Devin/Windsurf)",
1357
1342
  adapter: "devin",
1358
1343
  baseUrl: "https://server.codeium.com",
1359
1344
  authKind: "oauth",
1360
1345
  featured: false,
1346
+ // Off: `deriveProviderPresets` keys the preset catalog off this flag, so a
1347
+ // true row would draw the provider twice — an Accounts login row and a
1348
+ // preset tile.
1361
1349
  dashboardPreset: false,
1362
- note: "Experimental unofficial Cognition/Devin bridge. ocx login devin opens Auth0 browser sign-in, then exchanges the token via Cognition's RegisterUser for a long-lived API key.",
1363
- models: ["swe-1-7", "swe-1-7-lightning", "gpt-5-6-sol", "gpt-5-6-luna", "gpt-5-6-terra", "claude-opus-4-8", "claude-fable-5-1", "claude-sonnet-5", "glm-5-2", "kimi-k2-7", "grok-4-5"],
1350
+ note: "Experimental unofficial Cognition/Devin bridge. ocx login devin first imports the credential an installed Devin CLI already holds (no browser); without one it opens Auth0 browser sign-in and exchanges the token via Cognition's RegisterUser for a long-lived API key.",
1351
+ // Union seed of the two merged rosters: the newer devin-cli lineup first
1352
+ // (it is the current catalog, so its default ordering wins), then the ids
1353
+ // only the old devin entry carried. Degraded-mode seed only either way —
1354
+ // `liveModels` discovers the account's real roster.
1355
+ models: ["swe-2", "swe-1-7", "gpt-5-6-sol", "gpt-6-astra", "claude-opus-5", "claude-fable-5-1", "claude-sonnet-5", "glm-5-3", "kimi-k3", "gemini-3-8-flash", "grok-4-6", "swe-1-7-lightning", "gpt-5-6-luna", "gpt-5-6-terra", "claude-opus-4-8", "glm-5-2", "kimi-k2-7", "grok-4-5"],
1364
1356
  liveModels: true,
1365
- defaultModel: "swe-1-7",
1357
+ defaultModel: "swe-2",
1366
1358
  modelContextWindows: DEVIN_MODEL_CONTEXT_WINDOWS,
1359
+ // Degraded-mode ladders only. Once a credential is present the account
1360
+ // catalog supplies each base model its measured rungs; these two fields are
1361
+ // what a signed-out picker and the Pi-shaped client exports fall back to.
1362
+ modelReasoningEfforts: DEVIN_MODEL_EFFORTS,
1363
+ reasoningEfforts: DEVIN_DEFAULT_EFFORTS,
1367
1364
  },
1368
1365
  {
1369
1366
  id: "xai",
@@ -1373,13 +1370,38 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1373
1370
  authKind: "oauth",
1374
1371
  allowKeyAuthOverride: true,
1375
1372
  // Priority Processing is documented for xAI's public API-key Chat Completions and
1376
- // Responses endpoints. OAuth is a separate Grok CLI subscription gateway and remains
1377
- // unclassified; do not turn this into a provider-wide supportsServiceTier declaration.
1373
+ // Responses endpoints. The OAuth lane is classified per-model below, not here:
1374
+ // do not turn this into a provider-wide supportsServiceTier declaration.
1378
1375
  keyAuthServiceTier: {
1379
1376
  supportsServiceTier: true,
1380
1377
  chatServiceTier: true,
1381
1378
  },
1382
- fastTierDescription: "Priority processing, 2x token price",
1379
+ // OAuth (Grok subscription gateway) service-tier capability, classified by live probe
1380
+ // on 2026-09-13 (devlog/_fin/260913_xai_oauth_fast/020_probe-evidence.md): each listed
1381
+ // model accepted service_tier "priority" over grok-oauth and echoed priority upstream.
1382
+ // Key-auth already declares provider-wide support above, so this map only newly opens
1383
+ // the OAuth lane. grok-4.20-multi-agent-0309 is deliberately absent: the gateway accepts
1384
+ // the field but answers service_tier "default" — a live downgrade, not a fast tier.
1385
+ // Unlisted and future-discovered ids stay unclassified.
1386
+ modelSupportsServiceTier: {
1387
+ "grok-4.6": true,
1388
+ "grok-4.5": true,
1389
+ "grok-4.3": true,
1390
+ "grok-4.20-0309-reasoning": true,
1391
+ "grok-4.20-0309-non-reasoning": true,
1392
+ "grok-build-0.1": true,
1393
+ "grok-composer-2.5-fast": true,
1394
+ },
1395
+ // Lets a caller-sent service_tier forward on the Chat wire (fastwire forwardCallerTier
1396
+ // chain). Provider-wide by construction: unclassified chat-wire models then preserve a
1397
+ // caller tier verbatim, the same contract other unclassified Responses routes already
1398
+ // follow; --fast publication and proxy-owned fast injection stay capability-scoped by
1399
+ // the map above. Key-auth declared the same value via keyAuthServiceTier, so the key
1400
+ // lane is unchanged.
1401
+ chatServiceTier: true,
1402
+ // Shared across key and OAuth catalog rows. OAuth subscription has no
1403
+ // per-token price, so the 2x claim is scoped to key auth.
1404
+ fastTierDescription: "Priority processing; tier pricing applies on key auth only",
1383
1405
  featured: true,
1384
1406
  oauthId: "xai",
1385
1407
  jawcodeBundle: "xai",
@@ -1419,20 +1441,20 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1419
1441
  // Grok 4.6/4.5 subscription Responses callers use the native wire with the existing
1420
1442
  // namespace/web-search/replay normalization. Chat remains an explicit modelAdapters
1421
1443
  // opt-in. Multi-agent has no Chat wire and uses Responses under both auth modes.
1422
- // Caller-owned service tiers stay off the unclassified OAuth subscription route; key-auth
1423
- // Fast remains proxy-owned and is still selected through keyAuthServiceTier above.
1444
+ // grok-4.6/4.5 are classified OAuth fast-tier models (modelSupportsServiceTier above),
1445
+ // so a caller-sent service_tier:"priority" forwards on this lane — the Codex fast-toggle
1446
+ // path. Multi-agent keeps its pin: probed 2026-09-13, the gateway downgrades its tier to
1447
+ // "default", so forwarding a caller tier would advertise a tier it does not get.
1424
1448
  modelWireDefaults: {
1425
1449
  "grok-4.6": {
1426
1450
  wire: "openai-responses",
1427
1451
  inbound: ["responses"],
1428
1452
  authModes: ["oauth"],
1429
- forwardCallerServiceTier: false,
1430
1453
  },
1431
1454
  "grok-4.5": {
1432
1455
  wire: "openai-responses",
1433
1456
  inbound: ["responses"],
1434
1457
  authModes: ["oauth"],
1435
- forwardCallerServiceTier: false,
1436
1458
  },
1437
1459
  "grok-4.20-multi-agent-0309": {
1438
1460
  // Even at high effort it emits no reasoning-summary deltas or encrypted replay
@@ -1748,6 +1770,12 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1748
1770
  label: "Meta Muse Code (CLI credential)",
1749
1771
  adapter: "openai-responses",
1750
1772
  baseUrl: "https://api.meta.ai/v1",
1773
+ // Meta own client sends this on every Muse Code call. We never have, so a future
1774
+ // server-side requirement would break every Muse request with no local signal.
1775
+ // Declared here rather than in a transport hook so it also covers model discovery
1776
+ // (src/oauth/index.ts:1176) and still yields to a user-set header
1777
+ // (mergeRegistryStaticHeaders, src/providers/registry.ts:3494).
1778
+ staticHeaders: { "x-api-version": "1.0.0" },
1751
1779
  authKind: "oauth",
1752
1780
  oauthId: "meta-muse",
1753
1781
  dashboardUrl: "https://dev.meta.ai",
@@ -1760,7 +1788,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1760
1788
  modelInputModalities: Object.fromEntries(META_MUSE_MODELS.map(id => [id, ["text", "image"] as ["text", "image"]])),
1761
1789
  modelReasoningEfforts: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORTS])),
1762
1790
  modelReasoningEffortMap: Object.fromEntries(META_MUSE_MODELS.map(id => [id, META_MUSE_REASONING_EFFORT_MAP])),
1763
- note: "Reuses the API key the Muse Code CLI stores after `muse login` (macOS only; requires the CLI installed and signed in). Meta ships no native Windows CLI and the Linux credential storage has not been measured, so on those platforms OpenCodex asks you to paste the Muse Code API key from https://dev.meta.ai instead of importing one; a pasted key faces the same format check and live validation as an imported one. Meta scopes that credential to the Muse Code CLI, so this is an UNSUPPORTED use: Meta does not authorize subscription coverage outside its own CLI, how these calls settle is not observable from the API, and you should treat every call as billable against your account. The key, imported or pasted, is copied into OpenCodex's auth store. OpenCodex reads Meta's subscription windows from streaming responses and shows the last observed value with its age; there is no endpoint to query them on demand, so refreshing one requires another streaming turn, and translated (non-passthrough) turns report none. Rate limits apply per team, not per key. For a supported path use the meta-model provider with your own key (export it as META_MODEL_API_KEY).",
1791
+ note: "Signs in to Meta with a browser device code on any platform, then mints the Muse Code subscription key. That grant is reimplemented from the one the Muse Code CLI performs and has NOT been exercised against Meta from OpenCodex, so treat the first login as unverified. If the Muse Code CLI is already signed in on macOS, the existing key is imported instead of starting a new grant. A pasted key from https://dev.meta.ai still works as a fallback when a device login cannot complete, and faces the same format check and live validation. A device login authenticates as Meta own Muse Code client, which is a stronger claim than reusing a key the CLI already minted. Meta scopes that credential to the Muse Code CLI, so this is an UNSUPPORTED use: Meta does not authorize subscription coverage outside its own CLI, how these calls settle is not observable from the API, and you should treat every call as billable against your account. The key, imported or pasted, is copied into OpenCodex's auth store. For an account signed in with the device login, OpenCodex refreshes Meta's subscription windows on demand from the same key endpoint the login uses, at most once every five minutes. For an imported or pasted key there is no endpoint to query them on demand, so OpenCodex reads them from streaming responses and shows the last observed value with its age; refreshing one then requires another streaming turn, and translated (non-passthrough) turns report none. Rate limits apply per team, not per key. For a supported path use the meta-model provider with your own key (export it as META_MODEL_API_KEY).",
1764
1792
  },
1765
1793
  {
1766
1794
  id: "umans",
@@ -1814,6 +1842,9 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
1814
1842
  },
1815
1843
  modelContextWindows: {
1816
1844
  "kimi-k3": KIMI_K3_STANDARD_CONTEXT_WINDOW,
1845
+ // Zen Go discovers only the gateway id, so carry DeepSeek's official 1M V4.1
1846
+ // window here or Codex falls back to its conservative 128k routed-model default.
1847
+ "deepseek-v4.1-flash": 1_048_576,
1817
1848
  // The DeepSeek vision preview id is metadata-only here: the Go roster is
1818
1849
  // discovered live, so it applies the moment the gateway serves the id.
1819
1850
  [DEEPSEEK_VISION_PREVIEW_MODEL]: 1_048_576,
@@ -2112,7 +2143,7 @@ export const PROVIDER_REGISTRY: readonly ProviderRegistryEntry[] = [
2112
2143
  // path must stay RELATIVE: this row sets `allowBaseUrlOverride`, and an absolute `url` would
2113
2144
  // retarget a user's custom base back to Google. A leading `./` is required because a bare
2114
2145
  // `v1internal:` reads as a URL scheme and `providerModelDiscoverySpecError` rejects it.
2115
- { id: "google-antigravity", alias: "agy", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", allowBaseUrlOverride: true, dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: true, defaultModel: "gemini-3.8-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"], modelDiscovery: { path: "./v1internal:fetchAvailableModels" } },
2146
+ { id: "google-antigravity", alias: "agy", label: "Google Antigravity", adapter: "google", baseUrl: "https://daily-cloudcode-pa.googleapis.com", authKind: "oauth", allowBaseUrlOverride: true, dashboardUrl: "https://antigravity.google", models: ANTIGRAVITY_MODELS, liveModels: true, defaultModel: "gemini-3.8-flash", modelContextWindows: ANTIGRAVITY_MODEL_CONTEXT_WINDOWS, modelInputModalities: ANTIGRAVITY_MODEL_INPUT_MODALITIES, modelReasoningEfforts: ANTIGRAVITY_MODEL_EFFORTS, googleMode: "cloud-code-assist", showThinkingSummary: true, jawcodeBundle: "google", extraMetadataAliases: ["antigravity", "gemini-antigravity"], modelDiscovery: { path: "./v1internal:fetchAvailableModels" } },
2116
2147
  { 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" },
2117
2148
  { 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" },
2118
2149
  { 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" },
@@ -1,5 +1,6 @@
1
1
  import type { OcxProviderConfig } from "./types";
2
2
  import { modelInList } from "./types";
3
+ import { dropLearnedUnsupportedReasoningEfforts, ensureReasoningMetadataSnapshot, reasoningEffortsFromMetadata } from "./providers/reasoning-metadata";
3
4
 
4
5
  // Descriptions mirror the upstream bundled models.json canonical wording (openai/codex PR #31684).
5
6
  export const CODEX_REASONING_LEVELS: { effort: string; description: string }[] = [
@@ -148,8 +149,31 @@ export function sanitizeCodexReasoningEfforts(efforts: readonly string[] | undef
148
149
  export function configuredReasoningEfforts(provider: OcxProviderConfig, modelId: string): string[] | undefined {
149
150
  if (modelInList(provider.noReasoningModels, modelId)) return [];
150
151
  const modelEfforts = modelRecordValue(provider.modelReasoningEfforts, modelId);
151
- if (modelEfforts !== undefined) return healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(modelEfforts) ?? []);
152
- if (provider.reasoningEfforts !== undefined) return healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(provider.reasoningEfforts) ?? []);
152
+ // Rungs this account actually had refused are removed for every ladder source (registry
153
+ // config or models.dev), so a learned refusal is honoured even when the ladder is pinned in
154
+ // code; otherwise a rejected pinned rung would replay-and-fail on every request.
155
+ if (modelEfforts !== undefined) {
156
+ return dropLearnedUnsupportedReasoningEfforts(provider, modelId, healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(modelEfforts) ?? []));
157
+ }
158
+ if (provider.reasoningEfforts !== undefined) {
159
+ return dropLearnedUnsupportedReasoningEfforts(provider, modelId, healMappedTiers(provider, modelId, sanitizeCodexReasoningEfforts(provider.reasoningEfforts) ?? []));
160
+ }
161
+ // models.dev publishes the per-model ladder that routed providers never expose on /models.
162
+ // (OpenCode Zen Go answers ids only). Only consulted when nothing was configured for this
163
+ // model, so every hand-written contract stays authoritative. The snapshot refreshes itself in
164
+ // the background; no snapshot means the previous behaviour.
165
+ // The refresh is asked for only once a snapshot has already answered, which means it only ever
166
+ // refreshes a STALE snapshot. Review asked for the opposite — refresh when the snapshot is
167
+ // missing or corrupt, since that is the case this lookup cannot serve. That is declined here:
168
+ // a missing snapshot is the default state of every fresh install and every test process, so
169
+ // requesting the fetch here puts a models.dev request on the request path of the first routed
170
+ // turn to a gated destination. Refreshing a snapshot that does not exist is catalog-sync work,
171
+ // not request work.
172
+ const fromMetadata = reasoningEffortsFromMetadata(provider, modelId);
173
+ if (fromMetadata !== undefined) {
174
+ ensureReasoningMetadataSnapshot();
175
+ return dropLearnedUnsupportedReasoningEfforts(provider, modelId, healMappedTiers(provider, modelId, fromMetadata));
176
+ }
153
177
  return undefined;
154
178
  }
155
179
 
@@ -0,0 +1,32 @@
1
+ import { z } from "zod";
2
+
3
+ export const MAX_HUB_USAGE_BYTES = 1024 * 1024;
4
+ const count = z.number().finite().nonnegative();
5
+ const label = z.string().min(1).max(2048).refine(value => !/[\x00-\x1f\x7f]/.test(value));
6
+ const costs = { requests: count, totalTokens: count, estimatedCostUsd: count.optional() };
7
+
8
+ // Every object is projected through this schema: account labels, raw entries, and
9
+ // future management-only fields must not hitch a ride on a client data-key read.
10
+ const hubUsageSchema = z.object({
11
+ schemaVersion: z.literal(1), source: z.literal("hub"), scope: z.literal("client"),
12
+ range: z.enum(["today", "7d", "30d", "all"]),
13
+ surface: z.enum(["all", "codex", "claude", "grok"]),
14
+ since: count.nullable(), until: count.optional(), customWindow: z.literal(true).optional(),
15
+ generatedAt: count,
16
+ summary: z.object({ ...costs, inputTokens: count, outputTokens: count,
17
+ cachedInputTokens: count, unpricedRequests: count, unmeteredRequests: count }),
18
+ providers: z.array(z.object({ provider: label, ...costs })).max(2000),
19
+ models: z.array(z.object({ provider: label, model: label, ...costs })).max(2000),
20
+ days: z.array(z.object({ date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/), ...costs })).max(366),
21
+ filter: z.object({ provider: label.nullable(), model: label.nullable(),
22
+ matched: z.boolean(), comboOverlap: z.boolean() }),
23
+ usageIncomplete: z.literal(true).optional(),
24
+ usageIncompleteReason: z.literal("oversized_rows").optional(),
25
+ });
26
+
27
+ export type HubUsageReport = z.infer<typeof hubUsageSchema>;
28
+
29
+ export function parseHubUsage(value: unknown): HubUsageReport | null {
30
+ const result = hubUsageSchema.safeParse(value);
31
+ return result.success ? result.data : null;
32
+ }
@@ -1,3 +1,25 @@
1
+ export {
2
+ parseRemoteControlClientHello,
3
+ parseRemoteControlHostHello,
4
+ serializeRemoteControlHello,
5
+ generateRemoteControlIdentityKeyPair,
6
+ RemoteControlCipher,
7
+ RemoteControlClientHandshake,
8
+ acceptRemoteControlClientHello,
9
+ } from "./crypto";
10
+ export type {
11
+ RemoteControlIdentityKeyPair,
12
+ CreateRemoteControlClientHandshakeOptions,
13
+ AcceptRemoteControlClientHelloOptions,
14
+ } from "./crypto";
15
+ export {
16
+ RemoteControlHost,
17
+ } from "./host";
18
+ export type {
19
+ RemoteControlTerminal,
20
+ RemoteControlTerminalFactory,
21
+ RemoteControlHostOptions,
22
+ } from "./host";
1
23
  export {
2
24
  REMOTE_CONTROL_PROTOCOL_VERSION,
3
25
  REMOTE_CONTROL_RELAY_HEADER_BYTES,
@@ -24,28 +46,6 @@ export type {
24
46
  RemoteControlRelayFrame,
25
47
  RemoteControlApplicationFrame,
26
48
  } from "./protocol";
27
- export {
28
- parseRemoteControlClientHello,
29
- parseRemoteControlHostHello,
30
- serializeRemoteControlHello,
31
- generateRemoteControlIdentityKeyPair,
32
- RemoteControlCipher,
33
- RemoteControlClientHandshake,
34
- acceptRemoteControlClientHello,
35
- } from "./crypto";
36
- export type {
37
- RemoteControlIdentityKeyPair,
38
- CreateRemoteControlClientHandshakeOptions,
39
- AcceptRemoteControlClientHelloOptions,
40
- } from "./crypto";
41
- export {
42
- RemoteControlHost,
43
- } from "./host";
44
- export type {
45
- RemoteControlTerminal,
46
- RemoteControlTerminalFactory,
47
- RemoteControlHostOptions,
48
- } from "./host";
49
49
  export {
50
50
  OpaqueRemoteControlRelay,
51
51
  } from "./relay";
@@ -53,6 +53,176 @@ export type {
53
53
  RemoteControlRelayPeer,
54
54
  OpaqueRemoteControlRelayOptions,
55
55
  } from "./relay";
56
+ export {
57
+ RemoteWorkspaceHubAgentConnection,
58
+ RemoteWorkspaceExecutorAgentConnection,
59
+ } from "./workspace-agent-connection";
60
+ export type {
61
+ RemoteWorkspaceControlSocket,
62
+ } from "./workspace-agent-connection";
63
+ export {
64
+ REMOTE_WORKSPACE_AGENT_PROTOCOL_VERSION,
65
+ REMOTE_WORKSPACE_AGENT_MAX_CONTROL_BYTES,
66
+ isRemoteWorkspaceAgentProfile,
67
+ serializeRemoteWorkspaceHubMessage,
68
+ serializeRemoteWorkspaceAgentMessage,
69
+ parseRemoteWorkspaceHubMessage,
70
+ parseRemoteWorkspaceAgentMessage,
71
+ } from "./workspace-agent-protocol";
72
+ export type {
73
+ RemoteWorkspaceAgentProfile,
74
+ RemoteWorkspaceHubMessage,
75
+ RemoteWorkspaceAgentMessage,
76
+ } from "./workspace-agent-protocol";
77
+ export {
78
+ ClaudeRemoteWorkspaceRuntimeFactory,
79
+ } from "./workspace-claude-runtime";
80
+ export type {
81
+ ClaudeRemoteWorkspaceRuntimeOptions,
82
+ } from "./workspace-claude-runtime";
83
+ export {
84
+ CodexRemoteWorkspaceRuntimeFactory,
85
+ } from "./workspace-codex-runtime";
86
+ export type {
87
+ CodexRemoteWorkspaceRuntimeOptions,
88
+ } from "./workspace-codex-runtime";
89
+ export {
90
+ resolveCodexLinuxSandboxBinary,
91
+ codexRemotePermissionProfileCompatibility,
92
+ } from "./workspace-codex-sandbox";
93
+ export {
94
+ pinRemoteWorkspaceNativeHelper,
95
+ discoverRemoteWorkspaceNativeHelper,
96
+ parseRemoteWorkspaceNativeHelperDescriptor,
97
+ linuxRemoteWorkspaceCommandArgv,
98
+ createLinuxRemoteWorkspaceCommandRunner,
99
+ createNativeRemoteWorkspaceCommandRunner,
100
+ nativeRemoteWorkspaceCommandRunnerAvailable,
101
+ createPlatformRemoteWorkspaceCommandRunner,
102
+ linuxRemoteWorkspaceCommandRunnerAvailable,
103
+ } from "./workspace-command-runner";
104
+ export type {
105
+ LinuxRemoteWorkspaceCommandRunnerOptions,
106
+ RemoteWorkspaceNativeHelperDescriptor,
107
+ NativeRemoteWorkspaceCommandRunnerOptions,
108
+ } from "./workspace-command-runner";
109
+ export {
110
+ remoteWorkspaceThreadStartParams,
111
+ RemoteWorkspaceCoordinator,
112
+ } from "./workspace-coordinator";
113
+ export type {
114
+ RemoteWorkspaceSessionBinding,
115
+ RemoteWorkspaceTransport,
116
+ AppServerDynamicToolRequest,
117
+ AppServerDynamicToolResponse,
118
+ } from "./workspace-coordinator";
119
+ export {
120
+ REMOTE_WORKSPACE_DEVICE_STATE_VERSION,
121
+ normalizeRemoteWorkspaceHubUrl,
122
+ parseRemoteWorkspaceDeviceState,
123
+ RemoteWorkspaceDeviceFileStore,
124
+ pairRemoteWorkspaceDevice,
125
+ remoteWorkspaceCapabilitiesForCommandRunner,
126
+ connectRemoteWorkspaceAgent,
127
+ runRemoteWorkspaceAgent,
128
+ } from "./workspace-device";
129
+ export type {
130
+ RemoteWorkspaceDeviceRoot,
131
+ RemoteWorkspaceDeviceState,
132
+ RemoteWorkspaceDeviceStateStore,
133
+ PairRemoteWorkspaceDeviceOptions,
134
+ RemoteWorkspaceWebSocketLike,
135
+ RemoteWorkspaceWebSocketFactory,
136
+ RemoteWorkspaceAgentHandle,
137
+ RemoteWorkspaceAgentRunStatus,
138
+ } from "./workspace-device";
139
+ export {
140
+ findExecutableOnPath,
141
+ } from "./workspace-executable";
142
+ export {
143
+ validateRemoteWorkspaceRelativePath,
144
+ RemoteWorkspaceExecutor,
145
+ } from "./workspace-executor";
146
+ export type {
147
+ RemoteWorkspaceRoot,
148
+ RemoteWorkspaceExecutionRequest,
149
+ RemoteWorkspaceExecutorOptions,
150
+ RemoteWorkspaceCommandRequest,
151
+ RemoteWorkspaceCommandResult,
152
+ RemoteWorkspaceCommandRunner,
153
+ } from "./workspace-executor";
154
+ export {
155
+ REMOTE_WORKSPACE_HUB_STATE_VERSION,
156
+ REMOTE_WORKSPACE_MAX_DEVICES,
157
+ REMOTE_WORKSPACE_MAX_ROOTS_PER_DEVICE,
158
+ RemoteWorkspacePairingRateLimitError,
159
+ parseRemoteWorkspaceHubState,
160
+ RemoteWorkspaceHubFileStore,
161
+ RemoteWorkspaceHub,
162
+ } from "./workspace-hub";
163
+ export type {
164
+ RemoteWorkspaceRootAdvertisement,
165
+ RemoteWorkspaceStoredDevice,
166
+ RemoteWorkspaceHubState,
167
+ RemoteWorkspaceHubStateStore,
168
+ RemoteWorkspacePublicDevice,
169
+ RemoteWorkspacePairingGrant,
170
+ RemoteWorkspacePairDeviceInput,
171
+ RemoteWorkspacePairDeviceResult,
172
+ } from "./workspace-hub";
173
+ export {
174
+ PiRemoteWorkspaceRuntimeFactory,
175
+ } from "./workspace-pi-runtime";
176
+ export type {
177
+ PiRemoteWorkspaceRuntimeOptions,
178
+ } from "./workspace-pi-runtime";
179
+ export {
180
+ remoteWorkspaceProcessInvocation,
181
+ waitForRemoteWorkspaceProcessExit,
182
+ runRemoteWorkspaceCleanupSteps,
183
+ stopRemoteWorkspaceProcess,
184
+ removeRemoteWorkspaceIsolation,
185
+ } from "./workspace-process";
186
+ export type {
187
+ RemoteWorkspaceProcessInvocationOptions,
188
+ RemoteWorkspaceOwnedProcess,
189
+ StopRemoteWorkspaceProcessOptions,
190
+ } from "./workspace-process";
191
+ export {
192
+ REMOTE_WORKSPACE_RPC_MAX_MESSAGE_BYTES,
193
+ frameRemoteWorkspaceRpcMessage,
194
+ RemoteWorkspaceRpcReassembler,
195
+ } from "./workspace-rpc-framing";
196
+ export {
197
+ EncryptedRemoteWorkspaceTransport,
198
+ EncryptedRemoteWorkspaceExecutorEndpoint,
199
+ } from "./workspace-rpc";
200
+ export type {
201
+ EncryptedRemoteWorkspaceTransportOptions,
202
+ EncryptedRemoteWorkspaceExecutorEndpointOptions,
203
+ } from "./workspace-rpc";
204
+ export {
205
+ REMOTE_WORKSPACE_SESSION_STATE_VERSION,
206
+ parseRemoteWorkspaceSessionState,
207
+ RemoteWorkspaceSessionFileStore,
208
+ RemoteWorkspaceSessionService,
209
+ } from "./workspace-sessions";
210
+ export type {
211
+ RemoteWorkspaceSessionStatus,
212
+ RemoteWorkspaceAccessMode,
213
+ RemoteWorkspaceSessionEvent,
214
+ RemoteWorkspaceSessionSummary,
215
+ RemoteWorkspaceRuntimeHandle,
216
+ RemoteWorkspaceRuntimeFactory,
217
+ RemoteWorkspaceSessionState,
218
+ RemoteWorkspaceSessionStateStore,
219
+ } from "./workspace-sessions";
220
+ export {
221
+ startRemoteWorkspaceToolBridge,
222
+ } from "./workspace-tool-bridge";
223
+ export type {
224
+ RemoteWorkspaceToolBridge,
225
+ } from "./workspace-tool-bridge";
56
226
  export {
57
227
  REMOTE_WORKSPACE_TOOL_NAMESPACE,
58
228
  REMOTE_WORKSPACE_MAX_TOOL_RESULT_BYTES,
@@ -76,25 +246,6 @@ export type {
76
246
  RemoteWorkspaceToolCallParams,
77
247
  RemoteWorkspaceToolResult,
78
248
  } from "./workspace-tools";
79
- export {
80
- REMOTE_WORKSPACE_AGENT_PROTOCOL_VERSION,
81
- REMOTE_WORKSPACE_AGENT_MAX_CONTROL_BYTES,
82
- isRemoteWorkspaceAgentProfile,
83
- serializeRemoteWorkspaceHubMessage,
84
- serializeRemoteWorkspaceAgentMessage,
85
- parseRemoteWorkspaceHubMessage,
86
- parseRemoteWorkspaceAgentMessage,
87
- } from "./workspace-agent-protocol";
88
- export type {
89
- RemoteWorkspaceAgentProfile,
90
- RemoteWorkspaceHubMessage,
91
- RemoteWorkspaceAgentMessage,
92
- } from "./workspace-agent-protocol";
93
- export {
94
- REMOTE_WORKSPACE_RPC_MAX_MESSAGE_BYTES,
95
- frameRemoteWorkspaceRpcMessage,
96
- RemoteWorkspaceRpcReassembler,
97
- } from "./workspace-rpc-framing";
98
249
  export {
99
250
  truncateRemoteWorkspaceUtf8,
100
251
  } from "./workspace-utf8";
@@ -0,0 +1,9 @@
1
+ import type { OcxConfig } from "../types";
2
+
3
+ /** Side-effect-free opt-in; never creates a store, probes a runtime, or opens a listener. */
4
+ export function remoteWorkspaceEnabled(
5
+ config: Pick<OcxConfig, "runtimeRole">,
6
+ enabled = process.env.OCX_REMOTE_WORKSPACE_ENABLED,
7
+ ): boolean {
8
+ return config.runtimeRole === "hub" && enabled === "1";
9
+ }