sneakoscope 8.1.2 → 8.2.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 (261) hide show
  1. package/README.md +96 -58
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +5 -51
  5. package/dist/cli/command-manifest-lite.js +2 -1
  6. package/dist/cli/command-registry.js +2 -1
  7. package/dist/cli/global-mode-router.js +1 -1
  8. package/dist/cli/install-helpers-codex-lb-config.js +112 -914
  9. package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
  10. package/dist/cli/install-helpers-install-support.js +4 -20
  11. package/dist/cli/install-helpers.js +36 -2716
  12. package/dist/cli/router.js +9 -9
  13. package/dist/commands/bridge-command-output.js +111 -0
  14. package/dist/commands/bridge.js +320 -0
  15. package/dist/commands/codex-app.js +39 -123
  16. package/dist/commands/doctor-helpers.js +380 -0
  17. package/dist/commands/doctor-profile.js +3 -0
  18. package/dist/commands/doctor.js +114 -873
  19. package/dist/commands/mad-sks.js +0 -4
  20. package/dist/config/skills-manifest.json +1 -1
  21. package/dist/core/agents/agent-effort-policy.js +11 -21
  22. package/dist/core/agents/agent-recursion-guard.js +26 -0
  23. package/dist/core/agents/agent-runner-codex-exec.js +7 -9
  24. package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
  25. package/dist/core/architecture-hardening/state/state-service.js +49 -13
  26. package/dist/core/auto-review.js +15 -9
  27. package/dist/core/codex/codex-config-guard.js +8 -0
  28. package/dist/core/codex-adapter.js +8 -10
  29. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
  30. package/dist/core/codex-app/codex-app-launcher.js +10 -12
  31. package/dist/core/codex-app/codex-app-restart.js +10 -12
  32. package/dist/core/codex-app/menubar/constants.js +2 -5
  33. package/dist/core/codex-app/menubar/global-install.js +3 -2
  34. package/dist/core/codex-app/menubar/installer/result.js +23 -0
  35. package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
  36. package/dist/core/codex-app/menubar/installer.js +5 -96
  37. package/dist/core/codex-app/menubar/migration.js +1 -42
  38. package/dist/core/codex-app/openrouter-provider.js +0 -78
  39. package/dist/core/codex-app.js +97 -360
  40. package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
  41. package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
  42. package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
  43. package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
  44. package/dist/core/codex-control/codex-task-runner.js +16 -60
  45. package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
  46. package/dist/core/codex-exec-output-schema.js +11 -13
  47. package/dist/core/codex-lb/bridge-contracts.js +2 -0
  48. package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
  49. package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
  50. package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
  51. package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
  52. package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
  53. package/dist/core/codex-lb/capability-runner.js +505 -201
  54. package/dist/core/codex-lb/codex-lb-env.js +179 -12
  55. package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
  56. package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
  57. package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
  58. package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
  59. package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
  60. package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
  61. package/dist/core/codex-lb/combined-catalog.js +12 -0
  62. package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
  63. package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
  64. package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
  65. package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
  66. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
  67. package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
  68. package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
  69. package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
  70. package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
  71. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
  72. package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
  73. package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
  74. package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
  75. package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
  76. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
  77. package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
  78. package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
  79. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
  80. package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
  81. package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
  82. package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
  83. package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
  84. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
  85. package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
  86. package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
  87. package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
  88. package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
  89. package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
  90. package/dist/core/codex-lb/desktop-controller.js +2 -1730
  91. package/dist/core/codex-lb/desktop-service.js +462 -627
  92. package/dist/core/codex-lb/migration-receipt.js +560 -118
  93. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
  94. package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
  95. package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
  96. package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
  97. package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
  98. package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
  99. package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
  100. package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
  101. package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
  102. package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
  103. package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
  104. package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
  105. package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
  106. package/dist/core/codex-lb/provider-credentials/types.js +1 -0
  107. package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
  108. package/dist/core/codex-lb/provider-credentials.js +5 -0
  109. package/dist/core/codex-lb/provider-registry.js +323 -0
  110. package/dist/core/codex-lb/provider-route-policy.js +118 -0
  111. package/dist/core/codex-lb/request-route-resolver.js +172 -0
  112. package/dist/core/codex-lb/route-index.js +148 -0
  113. package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
  114. package/dist/core/commands/basic-cli.js +1 -1
  115. package/dist/core/commands/check-command.js +3 -10
  116. package/dist/core/commands/gate-result-contract.js +10 -14
  117. package/dist/core/commands/intent-normalization/normalizer.js +1 -1
  118. package/dist/core/commands/mad-sks-command.js +2 -6
  119. package/dist/core/commands/release-command.js +11 -1
  120. package/dist/core/commands/telegram-command.js +46 -6
  121. package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
  122. package/dist/core/doctor/skill-legacy-surface.js +5 -5
  123. package/dist/core/evidence/v2/evidence-key.js +30 -3
  124. package/dist/core/feature-fixtures.js +8 -1
  125. package/dist/core/feature-registry.js +3 -2
  126. package/dist/core/hooks-runtime/stop-finalization.js +11 -1
  127. package/dist/core/hooks-runtime/subagent-context.js +15 -1
  128. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
  129. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  130. package/dist/core/hooks-runtime.js +73 -87
  131. package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
  132. package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
  133. package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
  134. package/dist/core/imagegen/imagegen-capability.js +43 -151
  135. package/dist/core/init/skills/filesystem.js +89 -0
  136. package/dist/core/init/skills/inventory.js +97 -0
  137. package/dist/core/init/skills/manifest.js +151 -0
  138. package/dist/core/init/skills.js +5 -325
  139. package/dist/core/init.js +0 -63
  140. package/dist/core/install/installed-package-smoke.js +1 -1
  141. package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
  142. package/dist/core/policy/latest-version-guidance.js +15 -2
  143. package/dist/core/preflight/parallel-preflight-engine.js +27 -51
  144. package/dist/core/provider/provider-badge.js +9 -4
  145. package/dist/core/provider/provider-context.js +57 -107
  146. package/dist/core/providers/openrouter/openrouter-account.js +3 -1
  147. package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
  148. package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
  149. package/dist/core/release/gate-manifest.js +0 -1
  150. package/dist/core/release/main-push-guard.js +13 -0
  151. package/dist/core/release/main-push-receipt.js +11 -0
  152. package/dist/core/release/physical-release-gates.js +664 -61
  153. package/dist/core/release/publish-preflight.js +3 -3
  154. package/dist/core/release/release-gate-batch-runner.js +19 -6
  155. package/dist/core/release/release-gate-dag.js +33 -6
  156. package/dist/core/release/release-gate-node.js +1 -3
  157. package/dist/core/release/release-gate-output-contract.js +55 -0
  158. package/dist/core/release/release-pack-contract.js +1 -1
  159. package/dist/core/release/release-pack-receipt.js +209 -8
  160. package/dist/core/release/release-real-contract.js +1 -1
  161. package/dist/core/release/stage-publish.js +106 -28
  162. package/dist/core/retention/temp-lease.js +204 -0
  163. package/dist/core/retention.js +18 -195
  164. package/dist/core/routes.js +1 -2
  165. package/dist/core/safety/intent-contract/intent-contract.js +3 -3
  166. package/dist/core/subagents/naruto-host-credentials.js +6 -1
  167. package/dist/core/subagents/official-subagent-config.js +27 -9
  168. package/dist/core/subagents/official-subagent-runner.js +14 -31
  169. package/dist/core/subagents/wave-lifecycle.js +36 -8
  170. package/dist/core/subagents/wave-parent-guidance.js +2 -1
  171. package/dist/core/telegram/doctor.js +2 -2
  172. package/dist/core/telegram/liveness.js +10 -4
  173. package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
  174. package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
  175. package/dist/core/update/update-migration-state/session-state-split.js +247 -0
  176. package/dist/core/update/update-migration-state/simple-stages.js +46 -0
  177. package/dist/core/update/update-migration-state.js +4 -481
  178. package/dist/core/version.js +1 -1
  179. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
  180. package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
  181. package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
  182. package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
  183. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
  184. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
  185. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
  186. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
  187. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
  188. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
  189. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
  190. package/dist/scripts/canonical-test-runner.js +7 -1
  191. package/dist/scripts/check-runtime-schemas.js +7 -2
  192. package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
  193. package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
  194. package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
  195. package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
  196. package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
  197. package/dist/scripts/desktop-bridge-transport-client.js +116 -0
  198. package/dist/scripts/desktop-bridge-unification-check.js +276 -0
  199. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
  200. package/dist/scripts/gate-policy-audit-check.js +52 -2
  201. package/dist/scripts/provider-badge-context-check.js +55 -12
  202. package/dist/scripts/publish-preflight.js +1 -2
  203. package/dist/scripts/release-affected-selector-check.js +1 -2
  204. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  205. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  206. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
  207. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  208. package/dist/scripts/release-gate-batch-runner-check.js +9 -0
  209. package/dist/scripts/release-gate-dag-runner-check.js +6 -0
  210. package/dist/scripts/release-gate-dag-runner.js +4 -2
  211. package/dist/scripts/release-metadata-check.js +16 -3
  212. package/dist/scripts/release-pack-receipt.js +29 -6
  213. package/dist/scripts/release-physical-gates-check.js +39 -0
  214. package/dist/scripts/release-real-check.js +7 -5
  215. package/package.json +6 -8
  216. package/release-gates.v2.json +156 -157
  217. package/runtime-required-scripts.json +11 -11
  218. package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
  219. package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
  220. package/schemas/release/release-gate-node.schema.json +2 -3
  221. package/dist/cli/codex-lb-setup-warning-output.js +0 -17
  222. package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
  223. package/dist/commands/codex-lb.js +0 -1232
  224. package/dist/core/architecture-hardening/migration/migration.js +0 -111
  225. package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
  226. package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
  227. package/dist/core/codex-app/child-policy/child-policy.js +0 -35
  228. package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
  229. package/dist/core/codex-app/glm-model-profile.js +0 -1
  230. package/dist/core/codex-app/glm-profile-installer.js +0 -191
  231. package/dist/core/codex-app/glm-profile-schema.js +0 -42
  232. package/dist/core/codex-app/multi-provider-router.js +0 -391
  233. package/dist/core/codex-app/openrouter-activate.js +0 -405
  234. package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
  235. package/dist/core/codex-app/provider-child-policy.js +0 -64
  236. package/dist/core/codex-app/provider-mode.js +0 -91
  237. package/dist/core/codex-app/provider-session-policy.js +0 -85
  238. package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
  239. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
  240. package/dist/core/codex-lb/codex-lb-setup.js +0 -293
  241. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
  242. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
  243. package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
  244. package/dist/core/codex-lb/desktop-mode.js +0 -32
  245. package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
  246. package/dist/core/codex-lb/legacy-migration.js +0 -576
  247. package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
  248. package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
  249. package/dist/core/codex-lb/routing-truth.js +0 -327
  250. package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
  251. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
  252. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
  253. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
  254. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
  255. package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
  256. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
  257. package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
  258. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
  259. package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
  260. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
  261. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
@@ -6,11 +6,6 @@ import { EMPTY_CODEX_INFO, getCodexInfo } from './codex-adapter.js';
6
6
  import { CODEX_CHROME_EXTENSION_DOC_URL, DEFAULT_CODEX_APP_PLUGINS as DEFAULT_CODEX_APP_PLUGIN_TUPLES, RESERVED_CODEX_PLUGIN_SKILL_NAMES } from './routes.js';
7
7
  import { PRODUCT_DESIGN_PLUGIN, normalizeProductDesignPluginEvidence } from './product-design-plugin.js';
8
8
  import { PRODUCT_DESIGN_AUTO_INSTALL_ENV, ensureProductDesignPluginInstalled, productDesignAutoInstallRequested } from './product-design-app-server.js';
9
- import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_52_OPENROUTER_MODEL, RETIRED_GLM_DESKTOP_CONFIG_PROFILE_IDS } from './codex-app/openrouter-provider.js';
10
- import { sksOpenRouterCatalogPath } from './codex-app/codex-model-catalog.js';
11
- import { resolveOpenRouterApiKey } from './providers/openrouter/openrouter-secret-store.js';
12
- import { codexLbEnvPath, codexLbMetadataPath, loadCodexLbEnv, parseShellEnvValue, readCodexLbModelCatalog } from './codex-lb/codex-lb-env.js';
13
- import { codexLbToolCatalogPath, inspectCodexLbToolCatalog, shouldBindLocalModelCatalog } from './codex-lb/codex-lb-tool-catalog.js';
14
9
  import { isSksOwnedGlobalUiLock } from './codex-app/codex-app-ui-state-snapshot.js';
15
10
  import { redactString } from './secret-redaction.js';
16
11
  import { escapeRegExp } from './text/regex.js';
@@ -204,7 +199,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
204
199
  fast_mode_config: fastModeConfig,
205
200
  provider_model_ui: providerModelUi,
206
201
  selected_provider_ready: selectedProviderReady,
207
- codex_lb_capabilities: opts.codexLbCapabilityReport || null,
202
+ desktop_bridge_capabilities: opts.desktopBridgeCapabilityReport || null,
208
203
  git_actions: gitActions,
209
204
  image_generation: imageGenerationReady,
210
205
  image_generation_source: imageGenerationReady ? 'codex_features_list' : 'missing',
@@ -473,9 +468,11 @@ function codexNativeSksMenuStatus() {
473
468
  companion_install_command: 'sks doctor --fix',
474
469
  alternatives: [
475
470
  'sks doctor --fix',
476
- 'sks codex-lb use-desktop-full',
477
- 'sks codex-lb disable',
478
- 'sks codex-app set-openrouter-key --api-key-stdin',
471
+ 'sks bridge provider configure',
472
+ 'sks bridge provider validate',
473
+ 'sks bridge provider enable',
474
+ 'sks bridge catalog sync',
475
+ 'sks bridge route set-default',
479
476
  'codex://settings'
480
477
  ],
481
478
  evidence: [
@@ -544,28 +541,12 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
544
541
  lines.push(`Codex App speed selector can be hidden or locked by config: ${fastModeConfig.blockers.join(', ')}.`);
545
542
  lines.push('Run: sks doctor --fix');
546
543
  }
547
- if (providerModelUi?.glm?.exposed && providerModelUi.glm.openrouter_key_present) {
548
- lines.push(`OpenRouter provider is ready: ${providerModelUi.glm.model} (activate with ${providerModelUi.glm.install_command}).`);
544
+ if (providerModelUi?.checked && providerModelUi.effective_ready) {
545
+ lines.push(`Desktop bridge routing is ready${providerModelUi.selected_provider ? ` with ${providerModelUi.selected_provider} selected` : ''}.`);
549
546
  }
550
- else if (providerModelUi?.glm?.exposed) {
551
- lines.push(`OpenRouter provider is present for ${providerModelUi.glm.model}, but the OpenRouter key is missing.`);
552
- lines.push(`Run: ${providerModelUi.glm.key_command}; restart Codex App if the model picker was already open.`);
553
- }
554
- else if (providerModelUi?.glm) {
555
- lines.push(`OpenRouter provider is not ready yet: ${providerModelUi.glm.blockers.join(', ') || 'provider setup required'}.`);
556
- lines.push(`Run: ${providerModelUi.glm.key_command}; then ${providerModelUi.glm.install_command}; restart Codex App if the model picker was already open.`);
557
- }
558
- if (providerModelUi?.codex_lb?.key_entry_visible && providerModelUi.codex_lb.key_present && providerModelUi.codex_lb.provider_present && providerModelUi.codex_lb.provider_contract_ok && providerModelUi.codex_lb.base_url_present) {
559
- lines.push(`codex-lb key entry path is configured; provider catalog ${providerModelUi.codex_lb.expected_models_present ? 'contains GPT-5.6 Sol/Terra/Luna' : 'is not verified'}. Update command: ${providerModelUi.codex_lb.set_key_command}.`);
560
- lines.push('Provider/config readiness does not by itself prove the already-running Desktop picker; auth/profile actions restart ChatGPT/Codex so it reloads model/list.');
561
- }
562
- else if (providerModelUi?.codex_lb?.key_entry_visible) {
563
- lines.push(`codex-lb key entry path is visible, but setup is incomplete: ${providerModelUi.codex_lb.blockers.join(', ') || 'setup required'}.`);
564
- lines.push(`Run: ${providerModelUi.codex_lb.setup_command} or ${providerModelUi.codex_lb.set_key_command}.`);
565
- }
566
- else if (providerModelUi?.codex_lb) {
567
- lines.push(`codex-lb key entry path is not exposed yet: ${providerModelUi.codex_lb.blockers.join(', ') || 'setup required'}.`);
568
- lines.push(`Run: ${providerModelUi.codex_lb.setup_command} or ${providerModelUi.codex_lb.set_key_command}.`);
547
+ else if (providerModelUi) {
548
+ lines.push(`Desktop bridge routing is not ready: ${(providerModelUi.selected_provider_blockers || []).join(', ') || providerModelUi.readiness_state || 'status unavailable'}.`);
549
+ lines.push('Run: sks bridge provider configure; sks bridge provider validate; sks bridge provider enable; sks bridge catalog sync; sks bridge route set-default.');
569
550
  }
570
551
  if (!gitActions?.ok) {
571
552
  lines.push(`Codex App git commit/push actions are blocked: ${gitActions?.blockers?.join(', ') || 'git action readiness'}. The app Commit, Push, Commit and Push, and PR flows need codex_git_commit, hooks, and Codex CLI remote-control support.`);
@@ -620,9 +601,7 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
620
601
  `App Flags: ${status.features?.required_flags_ok ? 'ok' : `missing ${missingRequiredFeatureFlags(status.features?.required_flags).join(', ') || 'required flags'}`}`,
621
602
  `Fast UI: ${status.features?.fast_mode_config?.ok ? 'ok' : `locked ${(status.features?.fast_mode_config?.blockers || []).join(', ') || 'config'}`}`,
622
603
  `SKS Menu: ${sksNativeMenuSummary(status.app?.sks_menu)}`,
623
- `Provider UI:${providerModelUiSummary(status.features?.provider_model_ui)}`,
624
- `GLM Model: ${glmModelUiSummary(status.features?.provider_model_ui?.glm)}`,
625
- `codex-lb Key:${codexLbKeyUiSummary(status.features?.provider_model_ui?.codex_lb)}`,
604
+ `Bridge UI: ${providerModelUiSummary(status.features?.provider_model_ui)}`,
626
605
  `Default Plugins:${status.plugins?.default_plugins?.ok ? ' ok' : ` missing ${defaultPluginMissingSummary(status.plugins?.default_plugins) || 'plugin install/config'}`}`,
627
606
  `Product Design:${productDesignStatusSummary(status.plugins?.design_product)}`,
628
607
  `Plugin Picker:${status.plugins?.picker?.ok ? ' ok' : ` blocked ${pluginPickerBlockers(status).join(', ') || 'config'}`}`,
@@ -893,262 +872,99 @@ async function codexFastModeConfigStatus(opts = {}) {
893
872
  };
894
873
  }
895
874
  export async function codexProviderModelUiStatus(opts = {}) {
896
- const inputEnv = opts.env || process.env;
897
- const home = opts.home || inputEnv.HOME || os.homedir();
898
- const cwd = opts.cwd || process.cwd();
899
- const env = { ...inputEnv, HOME: String(opts.home || inputEnv.HOME || home) };
900
- const globalConfigPath = opts.configPath || path.join(home || '', '.codex', 'config.toml');
901
- const projectConfigPath = path.join(cwd || '', '.codex', 'config.toml');
902
- const globalConfig = await readTextIfExists(globalConfigPath);
903
- const projectConfig = path.resolve(projectConfigPath) === path.resolve(globalConfigPath)
904
- ? ''
905
- : await readTextIfExists(projectConfigPath);
906
- const configText = `${globalConfig}\n${projectConfig}`;
907
- const openRouterKey = await resolveOpenRouterApiKey({ env }).catch((err) => ({
908
- key: null,
909
- source: null,
910
- key_preview: null,
911
- blockers: ['openrouter_key_lookup_failed'],
912
- warnings: [err?.message || 'openrouter key lookup failed']
913
- }));
914
- const codexLbEnvFilePath = opts.codexLbEnvPath || codexLbEnvPath(home);
915
- const codexLbEnvText = await readTextIfExists(codexLbEnvFilePath);
916
- const codexLbApiKeySource = String(env.CODEX_LB_API_KEY || '').trim()
917
- ? 'process.env'
918
- : parseShellEnvValue(codexLbEnvText, 'CODEX_LB_API_KEY')
919
- ? 'env-file'
920
- : 'missing';
921
- const codexLbBaseUrlSource = String(env.CODEX_LB_BASE_URL || '').trim()
922
- ? 'process.env'
923
- : parseShellEnvValue(codexLbEnvText, 'CODEX_LB_BASE_URL')
924
- ? 'env-file'
925
- : 'missing';
926
- const openrouterProvider = tomlTableAny(configText, [
927
- `model_providers.${GLM_CODEX_CONFIG_PROVIDER_ID}`,
928
- `model_providers."${GLM_CODEX_CONFIG_PROVIDER_ID}"`
929
- ]);
930
- const glmProviderPresent = Boolean(openrouterProvider);
931
- const profilesPresent = [];
932
- const profilesMissing = [];
933
- const glmProfileBlockers = [];
934
- for (const profileId of RETIRED_GLM_DESKTOP_CONFIG_PROFILE_IDS) {
935
- const body = tomlTableAny(configText, [`profiles.${profileId}`, `profiles."${profileId}"`]);
936
- if (!body)
937
- continue;
938
- profilesPresent.push(profileId);
939
- glmProfileBlockers.push(`retired_glm_desktop_profile_present:${profileId}`);
875
+ let bridgeStatus;
876
+ try {
877
+ bridgeStatus = opts.desktopBridgeStatus
878
+ || await (opts.desktopBridgeStatusImpl || currentDesktopBridgeStatus)(opts.desktopBridgeStatusOptions || {});
940
879
  }
941
- const codexLbProvider = tomlTableAny(configText, ['model_providers.codex-lb', 'model_providers."codex-lb"']);
942
- const codexLbProviderPresent = Boolean(codexLbProvider);
943
- const codexLbCliProviderContractOk = codexLbProviderPresent
944
- && hasTomlString(codexLbProvider, 'name', 'codex-lb')
945
- && hasTomlString(codexLbProvider, 'wire_api', 'responses')
946
- && /(?:^|\n)\s*env_key\s*=\s*"CODEX_LB_API_KEY"\s*(?:#.*)?(?=\n|$)/.test(codexLbProvider)
947
- && !/X-Codex-LB-API-Key/.test(codexLbProvider)
948
- && hasTomlBoolean(codexLbProvider, 'supports_websockets', true)
949
- && hasTomlBoolean(codexLbProvider, 'requires_openai_auth', false);
950
- const codexLbSelectedDefault = /(?:^|\n)\s*model_provider\s*=\s*"codex-lb"\s*(?:#.*)?(?=\n|$)/.test(topLevelToml(globalConfig));
951
- const codexLbDesktopMode = opts.codexLbDesktopMode
952
- || inferCodexLbDesktopModeForUi(globalConfig);
953
- const retiredCodexLbCompatConfigured = codexLbDesktopMode === 'desktop-dual-auth-compat';
954
- const codexLbProviderContractOk = !retiredCodexLbCompatConfigured
955
- && codexLbCliProviderContractOk;
956
- const metadata = await readJsonIfExists(opts.codexLbMetadataPath || codexLbMetadataPath(home));
957
- const gatewayAuthTransport = normalizeCodexLbGatewayAuthTransportForUi(opts.codexLbGatewayAuthTransport || metadata?.gateway_auth_transport);
958
- const localCatalogBindingAllowed = shouldBindLocalModelCatalog(codexLbDesktopMode);
959
- const selectedProviderValue = topLevelToml(globalConfig)
960
- .match(/(?:^|\n)\s*model_provider\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || null;
961
- const managedCatalogPath = codexLbToolCatalogPath(path.join(home || '', '.codex'));
962
- const configuredCatalogPath = topLevelToml(globalConfig).match(/(?:^|\n)\s*model_catalog_json\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || '';
963
- const managedCatalogConfigured = Boolean(configuredCatalogPath)
964
- && path.resolve(configuredCatalogPath) === path.resolve(managedCatalogPath);
965
- let persistedCatalog = null;
966
- if (!opts.codexLbModelCatalog && managedCatalogConfigured && localCatalogBindingAllowed) {
967
- persistedCatalog = await inspectCodexLbToolCatalog(managedCatalogPath).catch(() => null);
880
+ catch {
881
+ return unavailableProviderModelUiStatus('desktop_bridge_status_unavailable');
968
882
  }
969
- let liveCatalog = opts.codexLbModelCatalog || null;
970
- if (!liveCatalog && !persistedCatalog?.ok && codexLbProviderContractOk && codexLbApiKeySource !== 'missing' && codexLbBaseUrlSource !== 'missing') {
971
- const loadedEnv = await loadCodexLbEnv({ home, envPath: codexLbEnvFilePath }).catch(() => null);
972
- liveCatalog = loadedEnv
973
- ? await readCodexLbModelCatalog({
974
- loadedEnv,
975
- gatewayAuthTransport
976
- }).catch(() => null)
977
- : null;
883
+ if (bridgeStatus?.schema !== 'sks.desktop-bridge-status.v3') {
884
+ return unavailableProviderModelUiStatus('desktop_bridge_status_schema_invalid');
978
885
  }
979
- const codexLbModelCatalog = opts.codexLbModelCatalog || (persistedCatalog?.ok
980
- ? {
981
- ok: true,
982
- models: Array.isArray(persistedCatalog.gpt56_models) ? persistedCatalog.gpt56_models : [],
983
- blockers: [],
984
- source: 'persisted_model_catalog_json',
985
- tools_transport: persistedCatalog.tools_transport || null
986
- }
987
- : liveCatalog
988
- ? { ...liveCatalog, source: liveCatalog.source || 'live_models' }
989
- : persistedCatalog
990
- ? {
991
- ok: false,
992
- models: Array.isArray(persistedCatalog.gpt56_models) ? persistedCatalog.gpt56_models : [],
993
- blockers: persistedCatalog.blockers || ['codex_lb_persisted_catalog_invalid'],
994
- source: 'persisted_model_catalog_json'
995
- }
996
- : null);
997
- const catalogModels = Array.isArray(codexLbModelCatalog?.models) ? codexLbModelCatalog.models.map(String) : [];
998
- const advertisedCodexLbModelsPresent = codexLbModelCatalog?.ok === true && catalogModels.length > 0;
999
- const glmBlockers = [
1000
- ...(glmProviderPresent ? [] : ['glm_openrouter_provider_missing']),
1001
- ...glmProfileBlockers,
1002
- ...(openRouterKey.key ? [] : ['openrouter_key_missing'])
1003
- ];
1004
- const codexLbBlockers = [
1005
- ...(codexLbProviderPresent ? [] : ['codex_lb_provider_missing']),
1006
- ...(retiredCodexLbCompatConfigured
1007
- ? ['desktop_dual_auth_compat_unavailable']
1008
- : codexLbProviderPresent && !codexLbProviderContractOk
1009
- ? ['codex_lb_provider_contract_drift']
1010
- : []),
1011
- ...(codexLbApiKeySource !== 'missing' ? [] : ['codex_lb_api_key_missing']),
1012
- ...(codexLbBaseUrlSource !== 'missing' ? [] : ['codex_lb_base_url_missing']),
1013
- ...(codexLbDesktopMode === 'desktop-native-bridge' && managedCatalogConfigured
1014
- ? ['native_bridge_local_catalog_replacement_forbidden']
1015
- : []),
1016
- ...(codexLbSelectedDefault && localCatalogBindingAllowed && !managedCatalogConfigured && !advertisedCodexLbModelsPresent
1017
- ? ['codex_lb_model_catalog_json_unselected']
1018
- : []),
1019
- ...(codexLbProviderContractOk && codexLbApiKeySource !== 'missing' && codexLbBaseUrlSource !== 'missing' && !advertisedCodexLbModelsPresent
1020
- ? ['codex_lb_model_catalog_unverified']
1021
- : [])
1022
- ];
1023
- const openRouterSelectedDefault = selectedProviderValue === GLM_CODEX_CONFIG_PROVIDER_ID;
1024
- const openRouterManagedCatalogPath = sksOpenRouterCatalogPath({ home });
1025
- const openRouterCatalogBound = Boolean(configuredCatalogPath)
1026
- && path.resolve(configuredCatalogPath) === path.resolve(openRouterManagedCatalogPath);
1027
- const openRouterCatalogDangling = openRouterCatalogBound && !openRouterSelectedDefault;
1028
- const openRouterSelectedBlockers = openRouterSelectedDefault
1029
- ? [
1030
- ...glmBlockers,
1031
- ...(openRouterCatalogBound ? [] : ['openrouter_model_catalog_json_unselected'])
1032
- ]
1033
- : [];
1034
- const selectedProviderBlockers = [
1035
- ...(codexLbSelectedDefault
1036
- ? codexLbBlockers
1037
- : openRouterSelectedDefault
1038
- ? openRouterSelectedBlockers
1039
- : []),
1040
- ...(openRouterCatalogDangling ? ['openrouter_model_catalog_json_dangling'] : [])
1041
- ];
1042
- const optionalProviderBlockers = codexLbSelectedDefault
1043
- ? glmBlockers
1044
- : openRouterSelectedDefault
1045
- ? codexLbBlockers
1046
- : [...glmBlockers, ...codexLbBlockers];
1047
- const keyCommand = 'sks codex-app set-openrouter-key --api-key-stdin';
1048
- const installCommand = 'sks codex-app use-openrouter --model z-ai/glm-5.2';
1049
- const setupCommand = 'sks codex-lb setup --host <domain> --api-key-stdin --yes';
1050
- const setKeyCommand = 'sks codex-lb set-key --api-key-stdin';
1051
- const desktopPickerEvidence = opts.desktopPickerEvidence
1052
- || opts.codexLbCapabilityReport?.model_picker
1053
- || opts.codexLbCapabilityReport?.capabilities?.model_picker
1054
- || opts.codexLbStatus?.capabilities?.model_picker
886
+ return providerModelUiStatusFromDesktopBridge(bridgeStatus);
887
+ }
888
+ async function currentDesktopBridgeStatus(options) {
889
+ const controller = await import('./codex-lb/desktop-controller.js');
890
+ return controller.desktopBridgeStatusV3(options);
891
+ }
892
+ function providerModelUiStatusFromDesktopBridge(status) {
893
+ const selectedProvider = status.routing.selected_route?.provider_id
894
+ || status.routing.policy?.default_provider_id
895
+ || status.routing.session_pin?.provider_id
1055
896
  || null;
1056
- const desktopPickerVerified = desktopPickerEvidence?.state === 'verified'
1057
- || desktopPickerEvidence?.verified === true;
1058
- const selectedProviderConfigured = selectedProviderBlockers.length === 0;
1059
- const selectedProviderAdvertised = codexLbSelectedDefault
1060
- ? advertisedCodexLbModelsPresent
1061
- : true;
1062
- const effectiveReady = selectedProviderConfigured && selectedProviderAdvertised && desktopPickerVerified;
897
+ const selectedProfile = selectedProvider ? status.providers[selectedProvider] : null;
898
+ const selectedProviderBlockers = uniqueStrings([
899
+ ...status.readiness.blockers,
900
+ ...status.routing.blockers,
901
+ ...(selectedProfile?.credential.blockers || []),
902
+ ...(selectedProfile?.catalog.blockers || [])
903
+ ]);
1063
904
  return {
1064
- schema: 'sks.codex-app-provider-model-ui.v1',
1065
- ok: effectiveReady,
1066
- selected_provider_ok: effectiveReady,
1067
- configured: selectedProviderConfigured,
1068
- advertised: selectedProviderAdvertised,
1069
- effective_ready: effectiveReady,
1070
- selected_provider: codexLbSelectedDefault ? 'codex-lb' : (selectedProviderValue || 'oauth'),
905
+ schema: 'sks.codex-app-provider-model-ui.v2',
906
+ ok: status.readiness.ready,
907
+ selected_provider_ok: status.readiness.ready,
908
+ configured: status.management.managed,
909
+ advertised: status.readiness.combined_catalog_ready,
910
+ effective_ready: status.readiness.ready,
911
+ selected_provider: selectedProvider,
1071
912
  selected_provider_blockers: selectedProviderBlockers,
1072
- optional_provider_blockers: optionalProviderBlockers,
913
+ optional_provider_blockers: status.readiness.warnings,
1073
914
  checked: true,
1074
- verification_scope: 'config_and_provider_catalog',
1075
- desktop_picker_verified: desktopPickerVerified,
1076
- desktop_picker_evidence: desktopPickerEvidence,
1077
- readiness_state: selectedProviderBlockers.length > 0
1078
- ? 'blocked'
1079
- : effectiveReady
1080
- ? 'verified'
1081
- : 'available_unverified',
1082
- status: selectedProviderBlockers.length > 0
1083
- ? 'setup_required'
1084
- : effectiveReady
1085
- ? 'ready'
1086
- : 'available_unverified',
1087
- optional_provider_status: optionalProviderBlockers.length === 0 ? 'ready' : 'setup_available',
1088
- config_paths: {
1089
- codex_config: globalConfigPath,
1090
- project_config: projectConfig ? projectConfigPath : null,
1091
- codex_lb_env: codexLbEnvFilePath
1092
- },
1093
- glm: {
1094
- exposed: glmProviderPresent && glmProfileBlockers.length === 0,
1095
- provider_present: glmProviderPresent,
1096
- provider: GLM_CODEX_CONFIG_PROVIDER_ID,
1097
- model: GLM_52_OPENROUTER_MODEL,
1098
- profiles_present: profilesPresent,
1099
- profiles_missing: profilesMissing,
1100
- openrouter_key_present: Boolean(openRouterKey.key),
1101
- openrouter_key_source: openRouterKey.source || null,
1102
- openrouter_key_preview: openRouterKey.key_preview || null,
1103
- openrouter_selected: openRouterSelectedDefault,
1104
- model_catalog_json_configured: openRouterCatalogBound,
1105
- model_catalog_json_path: openRouterManagedCatalogPath,
1106
- key_command: keyCommand,
1107
- install_command: installCommand,
1108
- doctor_command: 'sks codex-app openrouter-status',
1109
- blockers: glmBlockers
1110
- },
1111
- codex_lb: {
1112
- key_entry_visible: true,
1113
- provider_present: codexLbProviderPresent,
1114
- provider_contract_ok: codexLbProviderContractOk,
1115
- provider_contract: retiredCodexLbCompatConfigured
1116
- ? 'retired-desktop-dual-auth-compat'
1117
- : 'cli-provider',
1118
- selected_default: codexLbSelectedDefault,
1119
- key_present: codexLbApiKeySource !== 'missing',
1120
- api_key_source: codexLbApiKeySource,
1121
- base_url_present: codexLbBaseUrlSource !== 'missing',
1122
- base_url_source: codexLbBaseUrlSource,
1123
- model_catalog_checked: Boolean(codexLbModelCatalog),
1124
- model_catalog_ok: codexLbModelCatalog?.ok === true,
1125
- model_catalog_source: codexLbModelCatalog?.source || null,
1126
- desktop_mode: codexLbDesktopMode,
1127
- gateway_auth_transport: gatewayAuthTransport,
1128
- local_catalog_binding_allowed: localCatalogBindingAllowed,
1129
- model_catalog_json_configured: managedCatalogConfigured,
1130
- model_catalog_json_path: managedCatalogConfigured ? managedCatalogPath : configuredCatalogPath || null,
1131
- model_catalog_models: catalogModels,
1132
- expected_models: [],
1133
- expected_models_present: advertisedCodexLbModelsPresent,
1134
- advertised_models_present: advertisedCodexLbModelsPresent,
1135
- tools_transport: codexLbModelCatalog?.tools_transport || null,
1136
- model_catalog_blockers: codexLbModelCatalog?.blockers || [],
1137
- setup_command: setupCommand,
1138
- set_key_command: setKeyCommand,
1139
- status_command: 'sks codex-lb status',
1140
- blockers: codexLbBlockers
1141
- },
915
+ verification_scope: 'desktop_bridge_status_v3',
916
+ readiness_state: status.readiness.state,
917
+ status: status.readiness.ready ? 'ready' : status.readiness.state,
918
+ management: status.management,
919
+ service: status.service,
920
+ routing: status.routing,
921
+ catalog_sync: status.catalog_sync,
922
+ providers: status.providers,
923
+ recovery_actions: status.recovery_actions,
1142
924
  ui_actions: [
1143
- keyCommand,
1144
- installCommand,
1145
- setupCommand,
1146
- setKeyCommand,
1147
- 'sks codex-app status'
925
+ 'sks bridge provider configure',
926
+ 'sks bridge provider validate',
927
+ 'sks bridge provider enable',
928
+ 'sks bridge catalog sync',
929
+ 'sks bridge route set-default'
1148
930
  ],
1149
931
  blockers: selectedProviderBlockers
1150
932
  };
1151
933
  }
934
+ function unavailableProviderModelUiStatus(blocker) {
935
+ return {
936
+ schema: 'sks.codex-app-provider-model-ui.v2',
937
+ ok: false,
938
+ selected_provider_ok: false,
939
+ configured: false,
940
+ advertised: false,
941
+ effective_ready: false,
942
+ selected_provider: null,
943
+ selected_provider_blockers: [blocker],
944
+ optional_provider_blockers: [],
945
+ checked: false,
946
+ verification_scope: 'desktop_bridge_status_v3',
947
+ readiness_state: 'blocked',
948
+ status: 'blocked',
949
+ management: null,
950
+ service: null,
951
+ routing: null,
952
+ catalog_sync: null,
953
+ providers: null,
954
+ recovery_actions: [],
955
+ ui_actions: [
956
+ 'sks bridge provider configure',
957
+ 'sks bridge provider validate',
958
+ 'sks bridge provider enable',
959
+ 'sks bridge catalog sync',
960
+ 'sks bridge route set-default'
961
+ ],
962
+ blockers: [blocker]
963
+ };
964
+ }
965
+ function uniqueStrings(values) {
966
+ return [...new Set(values.map((value) => String(value || '').trim()).filter(Boolean))];
967
+ }
1152
968
  async function readTextIfExists(file) {
1153
969
  try {
1154
970
  return await fsp.readFile(file, 'utf8');
@@ -1157,38 +973,6 @@ async function readTextIfExists(file) {
1157
973
  return '';
1158
974
  }
1159
975
  }
1160
- async function readJsonIfExists(file) {
1161
- try {
1162
- const parsed = JSON.parse(await fsp.readFile(file, 'utf8'));
1163
- return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
1164
- ? parsed
1165
- : null;
1166
- }
1167
- catch {
1168
- return null;
1169
- }
1170
- }
1171
- function inferCodexLbDesktopModeForUi(config) {
1172
- const topLevel = topLevelToml(config);
1173
- const selected = topLevel.match(/(?:^|\n)\s*model_provider\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || '';
1174
- const openAiBaseUrl = topLevel.match(/(?:^|\n)\s*openai_base_url\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || '';
1175
- if (config.includes('# sks-codex-lb-managed-desktop-bridge')
1176
- && /^http:\/\/(?:127\.0\.0\.1|\[::1\]):\d+\/backend-api\/codex\/?$/i.test(openAiBaseUrl)) {
1177
- return 'desktop-native-bridge';
1178
- }
1179
- if (config.includes('# sks-codex-lb-managed-desktop-compat')
1180
- && selected === 'codex-lb') {
1181
- return 'desktop-dual-auth-compat';
1182
- }
1183
- return tomlTableAny(config, ['model_providers.codex-lb', 'model_providers."codex-lb"'])
1184
- ? 'cli-provider'
1185
- : 'disabled';
1186
- }
1187
- function normalizeCodexLbGatewayAuthTransportForUi(value) {
1188
- return value === 'x-codex-lb-api-key'
1189
- ? 'x-codex-lb-api-key'
1190
- : 'authorization-bearer-compat';
1191
- }
1192
976
  async function findDefaultPluginSource(plugin, { home, configText }) {
1193
977
  const cached = await findPluginCache(plugin.name, { home });
1194
978
  if (cached)
@@ -1243,17 +1027,10 @@ function productDesignStatusSummary(status = {}) {
1243
1027
  function providerModelUiSummary(status = {}) {
1244
1028
  if (!status?.checked)
1245
1029
  return ' not checked';
1246
- const selected = status.selected_provider || 'oauth';
1247
- if (status.ok) {
1248
- const optionalSetup = (status.optional_provider_blockers || []).length > 0
1249
- ? ', optional providers can be configured'
1250
- : '';
1251
- return ` ${selected} ready${optionalSetup} (live picker reload required)`;
1252
- }
1253
- if (status.configured && status.readiness_state === 'available_unverified') {
1254
- return ` ${selected} configured, Desktop picker unverified`;
1255
- }
1256
- return ` ${selected} setup ${(status.selected_provider_blockers || status.blockers || []).join(', ') || 'required'}`;
1030
+ const selected = status.selected_provider || 'no provider selected';
1031
+ if (status.ok)
1032
+ return ` ${selected} ready`;
1033
+ return ` ${selected} ${status.readiness_state || 'blocked'} ${(status.selected_provider_blockers || status.blockers || []).join(', ') || 'bridge setup required'}`;
1257
1034
  }
1258
1035
  function sksNativeMenuSummary(status = {}) {
1259
1036
  if (!status)
@@ -1262,56 +1039,16 @@ function sksNativeMenuSummary(status = {}) {
1262
1039
  return 'ok';
1263
1040
  return `${status.status || 'unsupported'} (use CLI/settings)`;
1264
1041
  }
1265
- function glmModelUiSummary(status = {}) {
1266
- if (!status)
1267
- return 'not checked';
1268
- if (status.exposed) {
1269
- const key = status.openrouter_key_present ? `key ${status.openrouter_key_source || 'present'}` : 'key missing';
1270
- return `ok ${status.model} (${key})`;
1271
- }
1272
- return `setup ${(status.blockers || []).join(', ') || 'provider missing'}; run ${status.key_command || 'sks codex-app set-openrouter-key --api-key-stdin'}`;
1273
- }
1274
- function codexLbKeyUiSummary(status = {}) {
1275
- if (!status)
1276
- return ' not checked';
1277
- if (status.key_present && status.provider_contract_ok !== false)
1278
- return ` configured (${status.api_key_source || 'present'})`;
1279
- if (status.key_present)
1280
- return ` setup provider drift; run ${status.setup_command || 'sks codex-lb setup --host <domain> --api-key-stdin --yes'}`;
1281
- return ` missing (input: ${status.setup_command || 'sks codex-lb setup --host <domain> --api-key-stdin --yes'})`;
1282
- }
1283
1042
  function defaultPluginMissingSummary(defaultPlugins = {}) {
1284
1043
  return [
1285
1044
  ...(defaultPlugins?.missing_installed || []),
1286
1045
  ...(defaultPlugins?.missing_enabled || [])
1287
1046
  ].join(', ');
1288
1047
  }
1289
- function topLevelToml(text = '') {
1290
- const lines = String(text || '').split('\n');
1291
- const firstTable = lines.findIndex((line) => /^\s*\[.+\]\s*$/.test(line));
1292
- return (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
1293
- }
1294
1048
  function tomlTable(text = '', table = '') {
1295
1049
  const re = new RegExp(`(?:^|\\n)\\[${escapeRegExp(table)}\\]([\\s\\S]*?)(?=\\n\\[[^\\]]+\\]|\\s*$)`);
1296
1050
  return String(text || '').match(re)?.[1] || '';
1297
1051
  }
1298
- function tomlTableAny(text = '', tables = []) {
1299
- for (const table of tables) {
1300
- const body = tomlTable(text, table);
1301
- if (body)
1302
- return body;
1303
- }
1304
- return '';
1305
- }
1306
- function hasTomlString(text = '', key = '', value = '') {
1307
- const re = new RegExp(`(?:^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*"${escapeRegExp(value)}"\\s*(?:#.*)?(?=\\n|$)`);
1308
- return re.test(String(text || ''));
1309
- }
1310
- function hasTomlBoolean(text = '', key = '', value) {
1311
- const expected = value ? 'true' : 'false';
1312
- const re = new RegExp(`(?:^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*${expected}\\s*(?:#.*)?(?=\\n|$)`);
1313
- return re.test(String(text || ''));
1314
- }
1315
1052
  function remoteControlGuidance(status = {}) {
1316
1053
  if (!status.codex_cli?.ok)
1317
1054
  return 'Codex remote-control needs a Codex CLI that exposes the app-server entrypoint. Install the official latest stable release: npm i -g @openai/codex@latest';
@@ -2,8 +2,7 @@ import fsp from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { readTopLevelTomlString } from '../codex-app/codex-model-catalog.js';
5
- import { loadCodexLbEnv } from '../codex-lb/codex-lb-env.js';
6
- export const CODEX_APP_SERVER_PROVIDER_CREDENTIALS_UNAVAILABLE = 'codex_app_server_provider_credentials_unavailable';
5
+ export const CODEX_APP_SERVER_DIRECT_PROVIDER_SELECTION_RETIRED = 'desktop_bridge_direct_provider_selection_retired';
7
6
  export const CODEX_APP_SERVER_CONFIG_READ_FAILED = 'codex_app_server_config_read_failed';
8
7
  export class CodexAppServerRuntimeEnvError extends Error {
9
8
  code;
@@ -15,11 +14,10 @@ export class CodexAppServerRuntimeEnvError extends Error {
15
14
  this.name = 'CodexAppServerRuntimeEnvError';
16
15
  }
17
16
  }
18
- export function codexAppServerProviderCredentialGuidance(home) {
17
+ export function desktopBridgeMigrationGuidance() {
19
18
  return [
20
- `Store the key in ${path.join(home, '.codex', 'sks-codex-lb.env')} (owner-only mode 0600).`,
21
- 'Run: sks codex-lb setup --host <domain> --api-key-stdin --yes',
22
- 'Alternatively, provide CODEX_LB_API_KEY in the launching environment.'
19
+ 'Run `sks bridge ensure --json` to migrate SKS-owned routing to Desktop Bridge.',
20
+ 'If the direct provider selection is user-owned, review and remove it manually before retrying.'
23
21
  ];
24
22
  }
25
23
  export function codexAppServerExecutablePath(input) {
@@ -68,28 +66,10 @@ export async function prepareCodexAppServerRuntimeEnv(input = {}) {
68
66
  ...(sourceEnv.PATH === undefined ? {} : { inheritedPath: sourceEnv.PATH })
69
67
  })
70
68
  };
71
- if (selectedProvider !== 'codex-lb') {
72
- delete env.CODEX_LB_API_KEY;
73
- delete env.CODEX_LB_BASE_URL;
74
- return env;
69
+ delete env.CODEX_LB_API_KEY;
70
+ delete env.CODEX_LB_BASE_URL;
71
+ if (selectedProvider === 'codex-lb' || selectedProvider === 'openrouter') {
72
+ throw new CodexAppServerRuntimeEnvError(CODEX_APP_SERVER_DIRECT_PROVIDER_SELECTION_RETIRED, desktopBridgeMigrationGuidance());
75
73
  }
76
- const load = input.loadCodexLbEnvImpl || loadCodexLbEnv;
77
- let loaded = null;
78
- try {
79
- loaded = await load({
80
- home,
81
- processEnv: {},
82
- envPath: path.join(codexHome, 'sks-codex-lb.env'),
83
- metadataPath: path.join(codexHome, 'sks-codex-lb.json')
84
- });
85
- }
86
- catch {
87
- throw new CodexAppServerRuntimeEnvError(CODEX_APP_SERVER_PROVIDER_CREDENTIALS_UNAVAILABLE, codexAppServerProviderCredentialGuidance(home));
88
- }
89
- if (!loaded?.configured || !loaded.secret_api_key || !loaded.base_url) {
90
- throw new CodexAppServerRuntimeEnvError(CODEX_APP_SERVER_PROVIDER_CREDENTIALS_UNAVAILABLE, codexAppServerProviderCredentialGuidance(home));
91
- }
92
- env.CODEX_LB_API_KEY = loaded.secret_api_key;
93
- env.CODEX_LB_BASE_URL = loaded.base_url;
94
74
  return env;
95
75
  }
@@ -68,7 +68,6 @@ export async function runCodexCurrentCoreImageReferencedPathRealProbe(input) {
68
68
  maxBufferBytes: 512 * 1024,
69
69
  codexBin,
70
70
  env: runtimeEnv,
71
- ...(typeof input.recoveryFetch === 'function' ? { recoveryFetch: input.recoveryFetch } : {}),
72
71
  ...(typeof input.runProcessImpl === 'function' ? { runProcessImpl: input.runProcessImpl } : {})
73
72
  }).catch((err) => ({ code: 1, stdout: '', stderr: err?.message || String(err) }));
74
73
  const outputText = await fs.readFile(outputFile, 'utf8').catch(() => '');
@@ -98,12 +97,12 @@ export async function runCodexCurrentCoreImageReferencedPathRealProbe(input) {
98
97
  process_exited_successfully: processExitedSuccessfully,
99
98
  process_warning: processExitedSuccessfully ? null : 'Codex emitted the referenced path evidence before process timeout/nonzero exit.',
100
99
  output_file: outputFile,
101
- codex_lb_tool_output_recovery: result.codexLbToolOutputRecovery || null,
100
+ desktop_bridge_launch_guard: result.desktop_bridge_launch_guard || null,
102
101
  contract_blockers: contract.blockers
103
102
  },
104
103
  blockers: ok ? [] : [
105
104
  ...(processExitedSuccessfully ? [] : ['codex_image_referenced_path_process_failed_or_timed_out']),
106
- ...(result.codexLbToolOutputRecovery?.blockers || []),
105
+ ...(result.desktop_bridge_launch_guard?.blockers || []),
107
106
  ...(!exactReferencedPath || !commandReferencesOnlyInputB || !outputReferencesInputB || contract.blockers.length > 0
108
107
  ? ['codex_image_referenced_path_actual_cli_probe_failed']
109
108
  : [])
@@ -33,7 +33,6 @@ export async function runCodexCurrentCoreWebSearchRealProbe(input) {
33
33
  stderrFile: path.join(tempDir, 'codex.stderr.log'),
34
34
  codexBin,
35
35
  env: runtimeEnv,
36
- ...(typeof input.recoveryFetch === 'function' ? { recoveryFetch: input.recoveryFetch } : {}),
37
36
  ...(typeof input.runProcessImpl === 'function' ? { runProcessImpl: input.runProcessImpl } : {})
38
37
  }).catch((err) => ({
39
38
  code: 1,
@@ -76,11 +75,11 @@ export async function runCodexCurrentCoreWebSearchRealProbe(input) {
76
75
  process_exited_successfully: processExitedSuccessfully,
77
76
  process_warning: processExitedSuccessfully ? null : 'Codex emitted web-search evidence before process timeout/nonzero exit.',
78
77
  output_file: outputFile,
79
- codex_lb_tool_output_recovery: result.codexLbToolOutputRecovery || null
78
+ desktop_bridge_launch_guard: result.desktop_bridge_launch_guard || null
80
79
  },
81
80
  blockers: ok ? [] : [
82
81
  ...(processExitedSuccessfully ? [] : ['codex_web_search_process_failed_or_timed_out']),
83
- ...(result.codexLbToolOutputRecovery?.blockers || []),
82
+ ...(result.desktop_bridge_launch_guard?.blockers || []),
84
83
  ...(!sawPlaintextResult || !resultContainsExpectedMarker ? ['codex_web_search_real_probe_failed'] : [])
85
84
  ]
86
85
  };