sneakoscope 7.5.0 → 8.0.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 (242) hide show
  1. package/README.md +12 -11
  2. package/config/perf-budgets.v1.json +0 -1
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/cli/command-manifest-lite.js +9 -14
  6. package/dist/cli/command-registry.js +9 -15
  7. package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
  8. package/dist/cli/install-helpers-codex-lb-config.js +114 -9
  9. package/dist/cli/install-helpers.js +729 -550
  10. package/dist/cli/router.js +23 -6
  11. package/dist/commands/codex-app.js +37 -1
  12. package/dist/commands/codex-lb.js +496 -300
  13. package/dist/config/skills-manifest.json +65 -58
  14. package/dist/core/agent-bridge/agent-manifest.js +6 -11
  15. package/dist/core/align/align-route.js +558 -0
  16. package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
  17. package/dist/core/codex-app/codex-app-restart.js +83 -0
  18. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
  19. package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
  20. package/dist/core/codex-app/menubar/constants.js +3 -1
  21. package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
  22. package/dist/core/codex-app/menubar/installer.js +38 -1
  23. package/dist/core/codex-app/menubar/migration.js +241 -1
  24. package/dist/core/codex-app/menubar/status.js +19 -1
  25. package/dist/core/codex-app/multi-provider-router.js +22 -10
  26. package/dist/core/codex-app/openrouter-activate.js +26 -1
  27. package/dist/core/codex-app.js +113 -21
  28. package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
  29. package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
  30. package/dist/core/codex-control/codex-task-runner.js +2 -2
  31. package/dist/core/codex-lb/capability-runner.js +215 -0
  32. package/dist/core/codex-lb/codex-lb-env.js +9 -13
  33. package/dist/core/codex-lb/codex-lb-setup.js +45 -8
  34. package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
  35. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
  36. package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
  37. package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
  38. package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
  39. package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
  40. package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
  41. package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
  42. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
  43. package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
  44. package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
  45. package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
  46. package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
  47. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
  48. package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
  49. package/dist/core/codex-lb/desktop-controller.js +1478 -0
  50. package/dist/core/codex-lb/desktop-mode.js +32 -0
  51. package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
  52. package/dist/core/codex-lb/desktop-service.js +613 -0
  53. package/dist/core/codex-lb/legacy-migration.js +575 -0
  54. package/dist/core/codex-lb/migration-receipt.js +246 -0
  55. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
  56. package/dist/core/codex-lb/probes/bridge-probe.js +77 -0
  57. package/dist/core/codex-lb/probes/catalog-probe.js +139 -0
  58. package/dist/core/codex-lb/probes/cli-image-tool-probe.js +200 -0
  59. package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
  60. package/dist/core/codex-lb/probes/image-generation-probe.js +53 -0
  61. package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
  62. package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
  63. package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
  64. package/dist/core/codex-native/core-skill-manifest.js +42 -4
  65. package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
  66. package/dist/core/commands/align-command.js +316 -0
  67. package/dist/core/commands/image-ux-review-command.js +37 -18
  68. package/dist/core/commands/mad-sks-command.js +30 -28
  69. package/dist/core/commands/mad-sks-headless.js +44 -0
  70. package/dist/core/commands/naruto-command.js +18 -6
  71. package/dist/core/commands/remote-command.js +5 -4
  72. package/dist/core/db-safety.js +10 -0
  73. package/dist/core/doctor/retired-managed-residue-private.js +1 -1
  74. package/dist/core/doctor/retired-managed-residue-state.js +3 -1
  75. package/dist/core/doctor/skill-legacy-surface.js +1 -3
  76. package/dist/core/evidence/evidence-freshness.js +14 -0
  77. package/dist/core/feature-fixtures.js +10 -5
  78. package/dist/core/feature-registry.js +3 -1
  79. package/dist/core/hooks-runtime/hook-context.js +15 -2
  80. package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
  81. package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
  82. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  83. package/dist/core/hooks-runtime.js +5 -3
  84. package/dist/core/image-ux-review/imagegen-adapter.js +10 -5
  85. package/dist/core/image-ux-review.js +70 -27
  86. package/dist/core/imagegen/codex-lb-imagegen-target.js +1 -2
  87. package/dist/core/imagegen/imagegen-capability.js +17 -4
  88. package/dist/core/imagegen/require-imagegen.js +2 -1
  89. package/dist/core/init/skills.js +24 -20
  90. package/dist/core/init.js +1 -1
  91. package/dist/core/install/installed-package-smoke.js +1 -1
  92. package/dist/core/locks/file-lock.js +27 -11
  93. package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
  94. package/dist/core/perf/release-latency-slo.js +1 -54
  95. package/dist/core/pipeline-internals/runtime-core.js +43 -0
  96. package/dist/core/pipeline-internals/runtime-gates.js +5 -2
  97. package/dist/core/preflight/parallel-preflight-engine.js +1 -1
  98. package/dist/core/proof/auto-finalize.js +98 -6
  99. package/dist/core/proof/route-proof-gate.js +12 -1
  100. package/dist/core/proof/route-proof-policy.js +8 -8
  101. package/dist/core/release/package-size-budget.js +2 -2
  102. package/dist/core/release/release-gate-contract.js +1 -0
  103. package/dist/core/release/release-pack-receipt.js +2 -0
  104. package/dist/core/release/release-proof-io.js +1 -3
  105. package/dist/core/release/release-real-contract.js +5 -4
  106. package/dist/core/release/release-stamp-proof.js +1 -3
  107. package/dist/core/release/release-upgrade-baseline.js +3 -3
  108. package/dist/core/remote/audit-idempotency.js +50 -18
  109. package/dist/core/remote/index.js +0 -1
  110. package/dist/core/remote/owner-proof.js +2 -2
  111. package/dist/core/remote/protocol.js +2 -2
  112. package/dist/core/remote/ssh-worker-client.js +4 -1
  113. package/dist/core/remote/types.js +2 -3
  114. package/dist/core/remote/worker.js +25 -222
  115. package/dist/core/research/research-adversarial-review.js +1 -3
  116. package/dist/core/research/research-claim-synthesizer.js +1 -3
  117. package/dist/core/research/research-falsification-runner.js +1 -3
  118. package/dist/core/research/research-source-evidence.js +1 -3
  119. package/dist/core/routes/constants.js +1 -1
  120. package/dist/core/routes/dollar-manifest-lite.js +2 -0
  121. package/dist/core/routes.js +18 -3
  122. package/dist/core/safety/command-contract/contracts.js +4 -9
  123. package/dist/core/secret-redaction.js +6 -0
  124. package/dist/core/skill-forge.js +21 -6
  125. package/dist/core/skills/skill-agent-metadata.js +348 -0
  126. package/dist/core/stop-gate/stop-gate-resolver.js +47 -2
  127. package/dist/core/subagents/official-subagent-prompt.js +32 -74
  128. package/dist/core/text/strings.js +3 -0
  129. package/dist/core/triwiki/context-graph/extractors/topology/commands.js +0 -1
  130. package/dist/core/update/update-migration-state.js +17 -4
  131. package/dist/core/update-check.js +17 -2
  132. package/dist/core/version.js +1 -1
  133. package/dist/core/work-order-ledger.js +7 -1
  134. package/dist/core/zellij/zellij-official-subagent-activity.js +53 -0
  135. package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
  136. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +20 -3
  137. package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
  138. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
  139. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
  140. package/dist/native/sks-menubar/Sources/OverviewSummary.swift +135 -0
  141. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +139 -200
  142. package/dist/native/sks-menubar/Sources/ProcessClient.swift +101 -12
  143. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
  144. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
  145. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
  146. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
  147. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +302 -341
  148. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +49 -0
  149. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
  150. package/dist/native/sks-menubar/Sources/SidebarItem.swift +4 -4
  151. package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
  152. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
  153. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
  154. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +16 -0
  155. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
  156. package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
  157. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
  158. package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
  159. package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
  160. package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
  161. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
  162. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  163. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
  164. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
  165. package/dist/scripts/current-command-surface-check.js +4 -2
  166. package/dist/scripts/docs-truthfulness-check.js +11 -12
  167. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
  168. package/dist/scripts/gate-policy-audit-check.js +1 -1
  169. package/dist/scripts/helper-dedup-check.js +0 -1
  170. package/dist/scripts/packlist-performance-check.js +2 -0
  171. package/dist/scripts/release-latency-slo-check.js +7 -3
  172. package/dist/scripts/release-metadata-check.js +1 -1
  173. package/dist/scripts/release-real-check.js +7 -0
  174. package/dist/scripts/skill-surface-modernization-check.js +544 -0
  175. package/package.json +6 -4
  176. package/release-gates.v2.json +32 -1
  177. package/runtime-required-scripts.json +40 -0
  178. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
  179. package/dist/cli/install-helpers-codex-lb-selftest.js +0 -482
  180. package/dist/cli/root-fast.js +0 -47
  181. package/dist/commands/aliases.js +0 -2
  182. package/dist/commands/autoresearch.js +0 -5
  183. package/dist/commands/bootstrap.js +0 -2
  184. package/dist/commands/computer-use.js +0 -4
  185. package/dist/commands/context7.js +0 -5
  186. package/dist/commands/deps.js +0 -5
  187. package/dist/commands/dollar-commands.js +0 -2
  188. package/dist/commands/eval.js +0 -5
  189. package/dist/commands/fix-path.js +0 -2
  190. package/dist/commands/gc.js +0 -2
  191. package/dist/commands/goal.js +0 -5
  192. package/dist/commands/gx.js +0 -5
  193. package/dist/commands/postinstall.js +0 -2
  194. package/dist/commands/quickstart.js +0 -2
  195. package/dist/commands/reasoning.js +0 -2
  196. package/dist/commands/run.js +0 -4
  197. package/dist/commands/selftest.js +0 -2
  198. package/dist/commands/setup.js +0 -2
  199. package/dist/commands/skill-dream.js +0 -5
  200. package/dist/commands/stats.js +0 -2
  201. package/dist/commands/trust.js +0 -4
  202. package/dist/commands/usage.js +0 -2
  203. package/dist/commands/validate-artifacts.js +0 -2
  204. package/dist/core/agents/agent-heartbeat.js +0 -1
  205. package/dist/core/codex/app-mentions.js +0 -13
  206. package/dist/core/codex/codex-resume-inventory.js +0 -28
  207. package/dist/core/codex-app/codex-app-provider-badge.js +0 -34
  208. package/dist/core/codex-compat/codex-0-132.js +0 -104
  209. package/dist/core/codex-control/codex-0140-probe-runner.js +0 -4
  210. package/dist/core/codex-control/codex-0140-real-probe-summary.js +0 -11
  211. package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +0 -18
  212. package/dist/core/codex-native/codex-native-capability-cache.js +0 -20
  213. package/dist/core/codex-native/native-media-computer-repair.js +0 -4
  214. package/dist/core/codex-plugins/codex-plugin-cache.js +0 -37
  215. package/dist/core/codex-plugins/codex-plugin-diff.js +0 -72
  216. package/dist/core/commands/command-suggestions.js +0 -12
  217. package/dist/core/commands/telegram-command.js +0 -399
  218. package/dist/core/doctor/macos-tcc-diagnostic.js +0 -18
  219. package/dist/core/dogfood-loop.js +0 -37
  220. package/dist/core/effort-orchestrator.js +0 -111
  221. package/dist/core/from-chat-img-forensics.js +0 -103
  222. package/dist/core/git/git-worktree-cache-policy.js +0 -35
  223. package/dist/core/git/git-worktree-pool.js +0 -26
  224. package/dist/core/local-llm/local-llm-config.js +0 -19
  225. package/dist/core/local-llm/local-llm-prompt-cache.js +0 -11
  226. package/dist/core/local-llm/local-llm-scheduler.js +0 -28
  227. package/dist/core/local-llm/local-llm-warmup.js +0 -19
  228. package/dist/core/loops/loop-iteration-runner.js +0 -1
  229. package/dist/core/remote/session-binding.js +0 -153
  230. package/dist/core/telegram/bot-api.js +0 -154
  231. package/dist/core/telegram/config.js +0 -106
  232. package/dist/core/telegram/hub.js +0 -248
  233. package/dist/core/telegram/index.js +0 -10
  234. package/dist/core/telegram/ledgers.js +0 -207
  235. package/dist/core/telegram/messages.js +0 -298
  236. package/dist/core/telegram/owner-lock.js +0 -132
  237. package/dist/core/telegram/runtime-projection.js +0 -91
  238. package/dist/core/telegram/runtime.js +0 -378
  239. package/dist/core/telegram/service.js +0 -181
  240. package/dist/core/telegram/setup.js +0 -370
  241. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +0 -221
  242. /package/dist/core/{telegram/types.js → codex-lb/capability-types.js} +0 -0
package/README.md CHANGED
@@ -22,7 +22,7 @@ Proof-first orchestration for Codex CLI, ChatGPT Desktop, AI coding agents, mult
22
22
  Sneakoscope Codex (`sks`) is an open-source trust layer for Codex CLI and ChatGPT Desktop. It coordinates bounded AI coding agents, records machine-verifiable evidence, preserves project memory, and blocks release claims that are not supported by current tests or artifacts. Search visibility outcomes are measured separately; SKS does not promise rankings or traffic.
23
23
  <!-- END SKS SEARCH VISIBILITY MARKETING -->
24
24
 
25
- This README documents package **SKS 7.5.0** — its own identity, read from `package.json` and verified by the release gate, not advice about what to install.
25
+ This README documents package **SKS 8.0.0** — its own identity, read from `package.json` and verified by the release gate, not advice about what to install.
26
26
 
27
27
  Use the official latest stable SKS and Codex CLI releases. SKS stays version-agnostic: older hosts keep working where capabilities allow, while Menu Bar / Center induce updates to the latest stable build. Run `sks update-check` for what is installed and read the capability report for what is actually supported — feature availability is decided by capability probes, not by a version number printed in a document. It resolves managed SKS skills from the authoritative global install, preserves a runnable Naruto child slot when `max_threads=2`, and keeps Menu Bar repair transactional so stamped generations remain verifiable. Naruto uses stable opt-in multi-agent V2 when the host exposes it. Local code search is mode-separated (`sks search files|text|structure|symbol|context`); `context` is answered by the compiled TriWiki Context Graph with evidence paths rather than lexical guessing — see [docs/architecture/context-graph.md](docs/architecture/context-graph.md) and [docs/architecture/search-engine-target.md](docs/architecture/search-engine-target.md). See [CHANGELOG.md](CHANGELOG.md).
28
28
 
@@ -63,13 +63,11 @@ The SKS menu bar shows the installed Codex CLI version and latest known version.
63
63
 
64
64
  **Manage MCP Servers…** opens a native macOS manager for the global `~/.codex/config.toml`. It can add remote URL or local stdio servers, enable/disable existing entries, remove entries after confirmation, and refresh the current state. Mutations are lock-protected, backed up, TOML-validated, and written with mode `0600`; configured environment values and command arguments are never rendered in the list. Changes apply to new Codex sessions. The same plumbing is available through the canonical `sks mcp config list|get|add|edit|duplicate|enable|disable|remove|test|login|logout|backups|restore` surface for diagnostics and automation.
65
65
 
66
- ### Telegram remote coding on this Mac
66
+ ### Remote coding: Orca (external option)
67
67
 
68
- Open **SKS Center Remote & Telegram**, create a bot with BotFather, send `/start` to that bot from the Telegram account you want to pair, then choose **Connect Bot & Register Coding Session…** and paste the token. SKS verifies the bot, stores the token only in macOS Keychain, pairs only that private chat/user, and registers one dedicated session bound to the current project. Choose **Start Hub**, then send ordinary text to the bot. On the first real message, the Hub creates the Codex thread and starts its first turn in the same App Server connection so the thread is durably resumable; later messages resume that exact thread and return the final response to Telegram.
68
+ SKS no longer provides a first-party Telegram coding bridge. If you want to monitor or steer coding work from another device, consider [Orca](https://github.com/stablyai/orca), an external MIT-licensed project that can launch Codex in a worktree. Orca is not bundled with SKS, supported by SKS, or required to use SKS; SKS adds no Orca dependency or configuration.
69
69
 
70
- The Hub runs as a user LaunchAgent and uses `caffeinate -i` while the logged-in Mac is available. The Mac still needs to remain powered on, logged in, awake, and network-connected; closing the lid or logging out can stop access. Telegram input has no arbitrary shell path, runs with approvals disabled and network access disabled inside the Codex workspace sandbox, and cannot target an unpaired chat or another project.
71
-
72
- SKS Center is the menu bar companion: install it with `sks menubar install`, then click the SKS icon in the macOS menu bar and choose **Open SKS Control Center…**. Every GUI step above has a CLI equivalent (`sks telegram setup --bot-token-stdin`, `sks telegram hub start`, `sks telegram status`). The hub uses long polling, so a bot with an existing webhook must have that webhook removed before the hub can start; SKS fails closed with `telegram_webhook_conflict` and never clears it automatically. See **[docs/telegram-and-center.md](docs/telegram-and-center.md)** for the complete BotFather setup, optional command menu and privacy-mode guidance, secure token rotation, verification, and troubleshooting.
70
+ Orca's mobile companion and Remote Orca Servers are beta. Their desktop/server runtime remains the source of truth and must keep running; remote access may require a private LAN or Tailscale path. See [the Orca migration and remote-coding guide](docs/orca-remote-coding.md) for scope, setup links, and former Telegram-user migration notes.
73
71
 
74
72
  ## The Front Door
75
73
 
@@ -241,16 +239,19 @@ It shows the current quickstart flow: one-line install, `$sks-plan`, `sks review
241
239
  - macOS optional: menu bar integration and `/usr/bin/open`
242
240
  - The menubar icon shows and hides itself automatically as the Codex desktop app launches/quits; set `quit_with_codex: true` in `~/.codex/sks-menubar/config.json` to have the menubar fully quit with Codex instead of just hiding (default `false`).
243
241
  - Native input dialogs (API keys, codex-lb setup) pass secrets to `sks` via `--api-key-stdin` instead of a visible Terminal window or process arguments.
244
- - Auth/provider changes require a successful app restart; skipped or failed restarts fail the action.
245
- - `sks update` preserves the selected codex-lb or ChatGPT OAuth mode, model, reasoning, catalog, and routing state.
246
- - Providers exposes **Restore Chat / Pro (OAuth)** as an explicit auth-mode switch while retaining saved codex-lb credentials.
242
+ - Codex Desktop always keeps its real ChatGPT OAuth identity. codex-lb setup stores a separate gateway endpoint/key and never replaces `~/.codex/auth.json`.
243
+ - Providers separates **Desktop Full Capability**, **CLI Provider**, and **Capability Matrix**. Desktop Full Capability keeps the built-in OpenAI provider and routes supported traffic through a loopback bridge; CLI Provider is selected only for the CLI process.
244
+ - Authentication and routing modes do not toggle Codex App's native model picker, Fast, image, Browser Use, Computer Use, voice, plugins/apps, or other built-in surfaces. Capability status describes evidence for the codex-lb data path, not permission to use the native feature.
245
+ - `sks update`, setup, repair, and routing changes preserve OAuth, user model/reasoning/Fast settings, unknown catalog fields, and unrelated provider configuration. Legacy shared-auth routing requires explicit `sks codex-lb migrate-legacy-desktop --restart-app`; without a real restart and post-restart identity check it cannot finalize a migration receipt.
246
+ - The remote codex-lb service remains independently hosted and operated. SKS uses only the configured URL and gateway key; it does not deploy, restart, or change credentials on that host.
247
+ - Full release proof blocks with `real_required_missing` until fresh trust-anchored evidence covers the real Desktop feature/lifecycle matrix and the separately hosted other-Mac runtime; fixtures and configuration cannot satisfy that boundary.
247
248
  - Update installs always rebuild the companion with the newly installed SKS package, preventing a previous-version updater from restoring a stale menu binary.
248
249
  - The menubar dropdown's `View Last Log` item opens the most recent background action's log file, so you don't need to keep a Terminal window open to see command output.
249
250
  - `Manage MCP Servers…` provides a resizable native table and add/remove/enable/disable controls for global Codex MCP configuration. Secret environment values and command arguments are accepted through native dialogs/stdin but omitted from list output and logs.
250
251
  - `sks menubar status --json` reports a `codex_sync` object with `bundle_id`, `codex_running`, and `icon_visible_expected` to show Codex-lifecycle detection state.
251
252
  - The menu displays the installed Codex CLI version, adds an `⬆` status icon when `sks codex update-status` sees a newer release, runs the official self-updater through `Update Codex CLI Now`, and exposes `Run sks doctor --fix` as a background repair action.
252
- - Fast mode has a verified status row and direct On/Off actions. Status failures render as unavailable with neither choice falsely selected.
253
- - If Codex shows `[No tool output found for custom tool call ...]`, SKS blocks reuse of that structurally ambiguous thread. Upgrade codex-lb (or explicitly run `sks codex-lb use-oauth`), inspect possible side effects, then continue the persisted mission in a fresh Codex task. SKS never rewrites session JSONL or fabricates a successful tool output.
253
+ - **Codex Fast** is labeled as the official 1.5× Codex speed option, with a verified service-tier status row and direct On/Off actions. Center explains that ChatGPT-sign-in GPT-5.6/GPT-5.5 use 2.5× Standard credits and GPT-5.4 uses 2×, while API-key token pricing and API Priority processing are separate. Model selection, Codex-Spark, and reasoning effort remain independent; status failures render as unavailable with neither choice falsely selected.
254
+ - If Codex shows `[No tool output found for custom tool call ...]`, SKS blocks reuse of that structurally ambiguous thread. Upgrade codex-lb or run `sks codex-lb disable`, inspect possible side effects, then continue the persisted mission in a fresh Codex task. SKS never rewrites session JSONL or fabricates a successful tool output.
254
255
  - Zellij optional but recommended for terminal worker panes
255
256
 
256
257
  ## License
@@ -18,7 +18,6 @@
18
18
  { "id": "control_center_open", "budget_p95_ms": 400, "measured_runs": 5 },
19
19
  { "id": "mcp_static_list", "budget_p95_ms": 250, "measured_runs": 9 },
20
20
  { "id": "update_cache_read", "budget_p95_ms": 50, "measured_runs": 15 },
21
- { "id": "telegram_callback_ack", "budget_p95_ms": 1000, "measured_runs": 7 },
22
21
  { "id": "ssh_worker_hello", "budget_p95_ms": 3000, "measured_runs": 5 }
23
22
  ]
24
23
  }
@@ -259,7 +259,7 @@ dependencies = [
259
259
 
260
260
  [[package]]
261
261
  name = "sks-core"
262
- version = "7.5.0"
262
+ version = "8.0.0"
263
263
  dependencies = [
264
264
  "globset",
265
265
  "grep-matcher",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "7.5.0"
3
+ version = "8.0.0"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -37,7 +37,6 @@ const COMMAND_MANIFEST_LITE_BASE = [
37
37
  { name: 'codex-lb', summary: 'Inspect codex-lb status and circuit health', maturity: 'beta', skipMigrationGate: true },
38
38
  { name: 'menubar', summary: 'Inspect/install/restart/uninstall SKS menu bar', maturity: 'beta', skipMigrationGate: true, allowedDuringActiveRoute: true, diagnostic: true },
39
39
  { name: 'remote', summary: 'Inspect official Remote readiness and run the proof-aware SSH stdio worker', maturity: 'beta' },
40
- { name: 'telegram', summary: 'Pair and run the private local Codex Telegram Hub', maturity: 'beta' },
41
40
  { name: 'hooks', summary: 'Explain and inspect Codex hooks', maturity: 'beta', skipMigrationGate: true },
42
41
  { name: 'zellij-lane', summary: 'Render a Zellij lane frame for SKS sessions', maturity: 'beta' },
43
42
  { name: 'zellij-slot-pane', summary: 'Render a compact Zellij worker slot pane', maturity: 'beta' },
@@ -73,6 +72,7 @@ const COMMAND_MANIFEST_LITE_BASE = [
73
72
  { name: 'versioning', summary: 'Manage release version metadata', maturity: 'stable' },
74
73
  { name: 'reasoning', summary: 'Show reasoning route', maturity: 'labs' },
75
74
  { name: 'aliases', summary: 'Show command aliases', maturity: 'stable' },
75
+ { name: 'align', summary: 'Prepare or inspect the evidence-gated $sks-align GPT-5.6 / Plugins modernization mission', maturity: 'beta', mutatesRouteState: true },
76
76
  { name: 'selftest', summary: 'Run local mock selftest', maturity: 'stable' },
77
77
  { name: 'goal', summary: 'Print stateless Codex native Goal controls', maturity: 'beta' },
78
78
  { name: 'seo-geo-optimizer', summary: 'Run unified SEO/GEO optimizer audit/plan/apply/verify plus research/strategy (--include-marketing) on the search-visibility kernel', maturity: 'beta' },
@@ -106,11 +106,11 @@ const SAFE_COMMAND_CONTRACT_LITE = {
106
106
  latency: 'normal',
107
107
  supportsJson: false,
108
108
  remoteAllowed: false,
109
- telegramAllowed: false,
110
109
  inputProfile: 'none',
111
110
  requiredCapabilities: []
112
111
  };
113
112
  const COMMAND_CONTRACT_OVERRIDES_LITE = {
113
+ align: { latency: 'long', supportsJson: true, inputProfile: 'json-only' },
114
114
  autoresearch: { latency: 'long' },
115
115
  bench: { latency: 'long' },
116
116
  check: { risk: 'R1', latency: 'long' },
@@ -120,8 +120,7 @@ const COMMAND_CONTRACT_OVERRIDES_LITE = {
120
120
  'dollar-commands': { risk: 'R2', latency: 'normal' },
121
121
  eval: { latency: 'long' },
122
122
  gates: {
123
- risk: 'R1', latency: 'long', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
124
- inputProfile: 'gates', requiredCapabilities: ['project.git', 'proof.gates']
123
+ risk: 'R1', latency: 'long', supportsJson: true, remoteAllowed: true, inputProfile: 'gates', requiredCapabilities: ['project.git', 'proof.gates']
125
124
  },
126
125
  harness: { latency: 'long' },
127
126
  'image-ux-review': { latency: 'long' },
@@ -129,8 +128,7 @@ const COMMAND_CONTRACT_OVERRIDES_LITE = {
129
128
  'mad-sks': { risk: 'R3', latency: 'long' },
130
129
  mcp: { risk: 'R2', latency: 'long', supportsJson: true, inputProfile: 'json-only' },
131
130
  naruto: {
132
- risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false,
133
- inputProfile: 'naruto'
131
+ risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, inputProfile: 'naruto'
134
132
  },
135
133
  paths: {
136
134
  supportsJson: true, remoteAllowed: true, inputProfile: 'paths',
@@ -144,13 +142,12 @@ const COMMAND_CONTRACT_OVERRIDES_LITE = {
144
142
  postinstall: { latency: 'long' },
145
143
  ppt: { latency: 'long' },
146
144
  proof: {
147
- risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
148
- inputProfile: 'proof', requiredCapabilities: ['proof.read']
145
+ risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, inputProfile: 'proof', requiredCapabilities: ['proof.read']
149
146
  },
150
147
  'qa-loop': { latency: 'long' },
151
148
  recallpulse: { latency: 'long' },
152
149
  release: { risk: 'R1', latency: 'long' },
153
- remote: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false, inputProfile: 'json-only' },
150
+ remote: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, inputProfile: 'json-only' },
154
151
  research: { latency: 'long' },
155
152
  review: { risk: 'R1' },
156
153
  run: { latency: 'long' },
@@ -160,18 +157,16 @@ const COMMAND_CONTRACT_OVERRIDES_LITE = {
160
157
  requiredCapabilities: ['project.fs.read']
161
158
  },
162
159
  status: {
163
- supportsJson: true, remoteAllowed: true, telegramAllowed: true, inputProfile: 'json-only',
160
+ supportsJson: true, remoteAllowed: true, inputProfile: 'json-only',
164
161
  requiredCapabilities: ['proof.read']
165
162
  },
166
163
  'stop-gate': {
167
- supportsJson: true, remoteAllowed: true, telegramAllowed: true, inputProfile: 'stop-gate',
164
+ supportsJson: true, remoteAllowed: true, inputProfile: 'stop-gate',
168
165
  requiredCapabilities: ['proof.stop-gate']
169
166
  },
170
167
  task: { risk: 'R1', latency: 'long' },
171
- telegram: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false, inputProfile: 'json-only' },
172
168
  trust: {
173
- risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
174
- inputProfile: 'trust', requiredCapabilities: ['proof.trust']
169
+ risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, inputProfile: 'trust', requiredCapabilities: ['proof.trust']
175
170
  },
176
171
  uninstall: { risk: 'R3', latency: 'long' },
177
172
  update: { latency: 'long' },
@@ -4,7 +4,6 @@ const SAFE_COMMAND_CONTRACT = {
4
4
  latency: 'normal',
5
5
  supportsJson: false,
6
6
  remoteAllowed: false,
7
- telegramAllowed: false,
8
7
  inputProfile: 'none',
9
8
  requiredCapabilities: []
10
9
  };
@@ -134,7 +133,6 @@ function applyCommandManifestContract(commands) {
134
133
  latency: manifest.latency,
135
134
  supportsJson: manifest.supportsJson,
136
135
  remoteAllowed: manifest.remoteAllowed,
137
- telegramAllowed: manifest.telegramAllowed,
138
136
  inputProfile: manifest.inputProfile,
139
137
  requiredCapabilities: [...manifest.requiredCapabilities]
140
138
  });
@@ -187,7 +185,6 @@ const COMMAND_DEFINITIONS = {
187
185
  'codex-lb': skipMigrationGate(entry('beta', 'Inspect codex-lb status and circuit health', 'dist/commands/codex-lb.js', directCommand(() => import('../commands/codex-lb.js'), 'dist/commands/codex-lb.js'))),
188
186
  menubar: activeRouteDiagnostic(entry('beta', 'Inspect/install/restart/uninstall SKS menu bar', 'dist/core/commands/menubar-command.js', subcommand(() => import('../core/commands/menubar-command.js'), 'menubarCommand', 'dist/core/commands/menubar-command.js', 'status'))),
189
187
  remote: entry('beta', 'Inspect official Remote readiness and run the proof-aware SSH stdio worker', 'dist/core/commands/remote-command.js', argsCommand(() => import('../core/commands/remote-command.js'), 'remoteCommand', 'dist/core/commands/remote-command.js')),
190
- telegram: entry('beta', 'Pair and run the private local Codex Telegram Hub', 'dist/core/commands/telegram-command.js', argsCommand(() => import('../core/commands/telegram-command.js'), 'telegramCommand', 'dist/core/commands/telegram-command.js')),
191
188
  hooks: skipMigrationGate(entry('beta', 'Explain and inspect Codex hooks', 'dist/commands/hooks.js', directCommand(() => import('../commands/hooks.js'), 'dist/commands/hooks.js'))),
192
189
  'zellij-lane': entry('beta', 'Render a Zellij lane frame for SKS sessions', 'dist/commands/zellij-lane.js', directCommand(() => import('../commands/zellij-lane.js'), 'dist/commands/zellij-lane.js')),
193
190
  'zellij-slot-pane': entry('beta', 'Render a compact Zellij worker slot pane', 'dist/commands/zellij-slot-pane.js', directCommand(() => import('../commands/zellij-slot-pane.js'), 'dist/commands/zellij-slot-pane.js')),
@@ -223,6 +220,7 @@ const COMMAND_DEFINITIONS = {
223
220
  versioning: entry('stable', 'Manage release version metadata', 'dist/commands/versioning.js', directCommand(() => import('../commands/versioning.js'), 'dist/commands/versioning.js')),
224
221
  reasoning: entry('labs', 'Show reasoning route', 'dist/core/commands/basic-cli.js', basicArgs('reasoningCommand')),
225
222
  aliases: entry('stable', 'Show command aliases', 'dist/core/commands/basic-cli.js', basicNoArgs('aliasesCommand')),
223
+ align: routeStateMutator(entry('beta', 'Prepare or inspect the evidence-gated $sks-align GPT-5.6 / Plugins modernization mission', 'dist/core/commands/align-command.js', subcommand(() => import('../core/commands/align-command.js'), 'alignCommand', 'dist/core/commands/align-command.js', 'prepare')), ['align-gate.json']),
226
224
  selftest: entry('stable', 'Run local mock selftest', 'dist/core/commands/basic-cli.js', basicArgs('selftestCommand')),
227
225
  goal: entry('beta', 'Print stateless Codex native Goal controls', 'dist/core/commands/goal-command.js', subcommand(() => import('../core/commands/goal-command.js'), 'goalCommand', 'dist/core/commands/goal-command.js')),
228
226
  'seo-geo-optimizer': entry('beta', 'Run unified SEO/GEO optimizer audit/plan/apply/verify plus research/strategy (--include-marketing) on the search-visibility kernel', 'dist/core/commands/seo-command.js', argsCommand(() => import('../core/commands/seo-command.js'), 'seoGeoOptimizerCommand', 'dist/core/commands/seo-command.js')),
@@ -256,6 +254,7 @@ const COMMAND_DEFINITIONS = {
256
254
  'agent-bridge': readOnly(entry('beta', 'Publish the agent-bridge manifest and print host registration snippets for external agent systems', 'dist/core/commands/agent-bridge-command.js', subcommand(() => import('../core/commands/agent-bridge-command.js'), 'agentBridgeCommand', 'dist/core/commands/agent-bridge-command.js', 'setup')))
257
255
  };
258
256
  const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(COMMAND_DEFINITIONS, {
257
+ align: { latency: 'long', supportsJson: true, inputProfile: 'json-only' },
259
258
  autoresearch: { latency: 'long' },
260
259
  bench: { latency: 'long' },
261
260
  check: { risk: 'R1', latency: 'long' },
@@ -264,8 +263,7 @@ const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(CO
264
263
  dfix: { latency: 'long' },
265
264
  eval: { latency: 'long' },
266
265
  gates: {
267
- risk: 'R1', latency: 'long', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
268
- inputProfile: 'gates', requiredCapabilities: ['project.git', 'proof.gates']
266
+ risk: 'R1', latency: 'long', supportsJson: true, remoteAllowed: true, inputProfile: 'gates', requiredCapabilities: ['project.git', 'proof.gates']
269
267
  },
270
268
  harness: { latency: 'long' },
271
269
  'image-ux-review': { latency: 'long' },
@@ -273,8 +271,7 @@ const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(CO
273
271
  'mad-sks': { risk: 'R3', latency: 'long' },
274
272
  mcp: { risk: 'R2', latency: 'long', supportsJson: true, inputProfile: 'json-only' },
275
273
  naruto: {
276
- risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false,
277
- inputProfile: 'naruto'
274
+ risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, inputProfile: 'naruto'
278
275
  },
279
276
  paths: {
280
277
  supportsJson: true, remoteAllowed: true, inputProfile: 'paths',
@@ -288,13 +285,12 @@ const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(CO
288
285
  postinstall: { latency: 'long' },
289
286
  ppt: { latency: 'long' },
290
287
  proof: {
291
- risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
292
- inputProfile: 'proof', requiredCapabilities: ['proof.read']
288
+ risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, inputProfile: 'proof', requiredCapabilities: ['proof.read']
293
289
  },
294
290
  'qa-loop': { latency: 'long' },
295
291
  recallpulse: { latency: 'long' },
296
292
  release: { risk: 'R1', latency: 'long' },
297
- remote: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false, inputProfile: 'json-only' },
293
+ remote: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, inputProfile: 'json-only' },
298
294
  research: { latency: 'long' },
299
295
  review: { risk: 'R1' },
300
296
  run: { latency: 'long' },
@@ -303,18 +299,16 @@ const COMMANDS_WITH_LEGACY_CONTRACT_OVERRIDES = applyCommandContractOverrides(CO
303
299
  requiredCapabilities: ['project.fs.read']
304
300
  },
305
301
  status: {
306
- supportsJson: true, remoteAllowed: true, telegramAllowed: true, inputProfile: 'json-only',
302
+ supportsJson: true, remoteAllowed: true, inputProfile: 'json-only',
307
303
  requiredCapabilities: ['proof.read']
308
304
  },
309
305
  'stop-gate': {
310
- supportsJson: true, remoteAllowed: true, telegramAllowed: true, inputProfile: 'stop-gate',
306
+ supportsJson: true, remoteAllowed: true, inputProfile: 'stop-gate',
311
307
  requiredCapabilities: ['proof.stop-gate']
312
308
  },
313
309
  task: { risk: 'R1', latency: 'long' },
314
- telegram: { risk: 'R2', latency: 'long', supportsJson: true, remoteAllowed: false, telegramAllowed: false, inputProfile: 'json-only' },
315
310
  trust: {
316
- risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, telegramAllowed: true,
317
- inputProfile: 'trust', requiredCapabilities: ['proof.trust']
311
+ risk: 'R0', latency: 'fast', supportsJson: true, remoteAllowed: true, inputProfile: 'trust', requiredCapabilities: ['proof.trust']
318
312
  },
319
313
  uninstall: { risk: 'R3', latency: 'long' },
320
314
  update: { latency: 'long' },
@@ -4,6 +4,7 @@ import fsp from 'node:fs/promises';
4
4
  import { ensureDir, packageRoot, readText, writeTextAtomic } from '../core/fsx.js';
5
5
  import { recordCodexLbHealthEvent } from '../core/codex-lb-circuit.js';
6
6
  import { codexLbBaseUrlSecurityBlocker } from '../core/codex-lb/codex-lb-env.js';
7
+ import { probeEvidence } from '../core/codex-lb/probes/probe-evidence.js';
7
8
  import { CODEX_LB_CANONICAL_FAST_SERVICE_TIER, codexLbEnvPath, parseCodexLbEnvKey, redactSecretText } from './install-helpers-codex-lb-shared.js';
8
9
  function codexLbResponsesEndpoint(baseUrl = '') {
9
10
  const base = String(baseUrl || '').trim().replace(/\/+$/, '');
@@ -288,6 +289,47 @@ export async function checkCodexLbResponseChain(status = {}, opts = {}) {
288
289
  error: redactSecretText(second.error_payload?.error?.message || second.error_payload?.response?.error?.message || second.text || 'codex-lb chained Responses request failed', [apiKey])
289
290
  }, { endpoint, home, opts, env }), opts);
290
291
  }
292
+ export async function runCodexLbTextResponsesProbe(status = {}, opts = {}) {
293
+ const result = await checkCodexLbResponseChain(status, opts);
294
+ return codexLbResponseChainCapabilityEvidence(result, {
295
+ checkedAt: typeof opts.nowIso === 'function' ? opts.nowIso() : new Date().toISOString()
296
+ });
297
+ }
298
+ export function codexLbResponseChainCapabilityEvidence(result = {}, opts = {}) {
299
+ const checkedAt = opts.checkedAt || new Date().toISOString();
300
+ if (result?.skipped === true || result?.status === 'skipped') {
301
+ return probeEvidence({
302
+ skipped: true,
303
+ source: 'config',
304
+ evidence: {
305
+ probe: 'text_responses',
306
+ status: result?.status || 'skipped',
307
+ reason: result?.reason || null
308
+ }
309
+ }, checkedAt);
310
+ }
311
+ const verified = result?.ok === true && result?.status === 'chain_ok';
312
+ const blockers = verified
313
+ ? []
314
+ : [
315
+ ...(Array.isArray(result?.blockers) ? result.blockers : []),
316
+ `text_responses_${String(result?.status || 'probe_failed')}`
317
+ ];
318
+ return probeEvidence({
319
+ attempted: true,
320
+ verified,
321
+ source: 'transport',
322
+ blockers,
323
+ evidence: {
324
+ probe: 'text_responses',
325
+ status: result?.status || null,
326
+ cached: result?.cached === true,
327
+ http_status: result?.http_status || null,
328
+ response_chain_completed: verified,
329
+ service_tier: result?.service_tier_evidence || null
330
+ }
331
+ }, checkedAt);
332
+ }
291
333
  async function recordCodexLbChainHealth(result, opts = {}) {
292
334
  if (!result || result.skipped || opts.recordCircuit === false)
293
335
  return result;
@@ -4,24 +4,129 @@ import { ensureDir, readText } from '../core/fsx.js';
4
4
  import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_52_OPENROUTER_MODEL, OPENROUTER_AUTH_COMMAND, OPENROUTER_AUTH_REFRESH_INTERVAL_MS, OPENROUTER_AUTH_TIMEOUT_MS, openRouterAuthCommandArgs, OPENROUTER_DEFAULT_PROFILE_ID, RETIRED_GLM_DESKTOP_CONFIG_PROFILE_IDS } from '../core/codex-app/openrouter-provider.js';
5
5
  import { openRouterSecretPaths, resolveOpenRouterApiKey } from '../core/providers/openrouter/openrouter-secret-store.js';
6
6
  import { reconcileRetiredSksConfigText } from '../core/auto-review.js';
7
- import { removeTopLevelTomlKeyIfValue, safeWriteCodexConfigToml, upsertTopLevelTomlString, upsertTomlTable } from '../core/codex-runtime/codex-desktop-config-policy.js';
7
+ import { ensureTrailingNewline, removeTopLevelTomlKeyIfValue, safeWriteCodexConfigToml, upsertTopLevelTomlString, upsertTomlTable } from '../core/codex-runtime/codex-desktop-config-policy.js';
8
8
  import { codexLbConfigPath, normalizeCodexLbBaseUrl } from './install-helpers-codex-lb-shared.js';
9
9
  import { escapeRegExp } from '../core/text/regex.js';
10
- export function upsertCodexLbConfig(text = '', baseUrl, selectDefault = true) {
11
- let next = selectDefault
10
+ export const CODEX_LB_DESKTOP_BRIDGE_MARKER = '# sks-codex-lb-managed-desktop-bridge';
11
+ export const CODEX_LB_DESKTOP_COMPAT_MARKER = '# sks-codex-lb-managed-desktop-compat';
12
+ export const CODEX_LB_MODEL_CATALOG_MARKER = '# sks-codex-lb-managed-model-catalog';
13
+ const LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER = '# sks-codex-lb-managed-openai-base-url';
14
+ export function upsertCodexLbNativeDesktopConfig(text, input) {
15
+ let next = String(text || '');
16
+ const selectedProvider = topLevelTomlString(next, 'model_provider');
17
+ if (selectedProvider && selectedProvider !== 'openai' && selectedProvider !== 'codex-lb') {
18
+ throw new Error('codex_lb_user_owned_model_provider_conflict');
19
+ }
20
+ if (selectedProvider === 'codex-lb' && !topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)) {
21
+ throw new Error('codex_lb_legacy_desktop_config_requires_migration');
22
+ }
23
+ if (topLevelHasLine(next, LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER)
24
+ && !topLevelHasLine(next, CODEX_LB_DESKTOP_BRIDGE_MARKER)) {
25
+ throw new Error('codex_lb_legacy_desktop_config_requires_migration');
26
+ }
27
+ const modelCatalog = topLevelTomlString(next, 'model_catalog_json');
28
+ if (modelCatalog && !topLevelHasLine(next, CODEX_LB_MODEL_CATALOG_MARKER)) {
29
+ throw new Error('codex_lb_user_owned_model_catalog_json_conflict');
30
+ }
31
+ next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
32
+ next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
33
+ next = removeManagedModelCatalogJson(next);
34
+ next = upsertManagedTopLevelTomlString(next, 'openai_base_url', input.bridgeBaseUrl, CODEX_LB_DESKTOP_BRIDGE_MARKER);
35
+ next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
36
+ return ensureTrailingNewline(next);
37
+ }
38
+ export function upsertCodexLbCompatDesktopConfig(text, input) {
39
+ let next = removeManagedDesktopBridgeRouting(String(text || ''));
40
+ next = removeManagedModelCatalogJson(next);
41
+ next = upsertManagedTopLevelTomlString(next, 'model_provider', 'codex-lb', CODEX_LB_DESKTOP_COMPAT_MARKER);
42
+ const block = [
43
+ '[model_providers.codex-lb]',
44
+ 'name = "OpenAI"',
45
+ `base_url = ${JSON.stringify(input.remoteBaseUrl)}`,
46
+ 'wire_api = "responses"',
47
+ 'requires_openai_auth = true',
48
+ 'supports_websockets = true',
49
+ 'env_http_headers = { "X-Codex-LB-API-Key" = "CODEX_LB_API_KEY" }'
50
+ ].join('\n');
51
+ next = upsertTomlTable(next, 'model_providers.codex-lb', block);
52
+ return ensureTrailingNewline(next);
53
+ }
54
+ export function upsertCodexLbCliProviderConfig(text, input) {
55
+ let next = input.selectGlobally === true
12
56
  ? upsertTopLevelTomlString(text, 'model_provider', 'codex-lb')
13
57
  : removeTopLevelTomlKeyIfValue(text, 'model_provider', 'codex-lb');
14
- const block = [
58
+ next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
59
+ return ensureTrailingNewline(next);
60
+ }
61
+ export function removeCodexLbManagedDesktopConfig(text) {
62
+ let next = removeManagedDesktopBridgeRouting(String(text || ''));
63
+ if (topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)) {
64
+ next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
65
+ next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
66
+ }
67
+ next = removeManagedModelCatalogJson(next);
68
+ return ensureTrailingNewline(next);
69
+ }
70
+ export function removeManagedModelCatalogJson(text) {
71
+ if (!topLevelHasLine(text, CODEX_LB_MODEL_CATALOG_MARKER))
72
+ return text;
73
+ const withoutKey = removeTopLevelTomlKey(text, 'model_catalog_json');
74
+ return removeTopLevelLine(withoutKey, CODEX_LB_MODEL_CATALOG_MARKER);
75
+ }
76
+ export function removeManagedDesktopBridgeRouting(text) {
77
+ const markers = [
78
+ CODEX_LB_DESKTOP_BRIDGE_MARKER,
79
+ LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER
80
+ ].filter((marker) => topLevelHasLine(text, marker));
81
+ if (markers.length === 0)
82
+ return text;
83
+ let next = removeTopLevelTomlKey(text, 'openai_base_url');
84
+ for (const marker of markers)
85
+ next = removeTopLevelLine(next, marker);
86
+ return next;
87
+ }
88
+ export function upsertCodexLbConfig(text = '', baseUrl, selectDefault = true) {
89
+ return upsertCodexLbCliProviderConfig(text, {
90
+ remoteBaseUrl: String(baseUrl || ''),
91
+ selectGlobally: selectDefault === true
92
+ });
93
+ }
94
+ function cliProviderBlock(remoteBaseUrl) {
95
+ return [
15
96
  '[model_providers.codex-lb]',
16
- 'name = "openai"',
17
- `base_url = "${baseUrl}"`,
97
+ 'name = "codex-lb"',
98
+ `base_url = ${JSON.stringify(remoteBaseUrl)}`,
18
99
  'wire_api = "responses"',
19
100
  'env_key = "CODEX_LB_API_KEY"',
20
101
  'supports_websockets = true',
21
- 'requires_openai_auth = true'
102
+ 'requires_openai_auth = false'
22
103
  ].join('\n');
23
- next = upsertTomlTable(next, 'model_providers.codex-lb', block);
24
- return `${next.trim()}\n`;
104
+ }
105
+ function upsertManagedTopLevelTomlString(text, key, value, marker, legacyMarkers = []) {
106
+ const acceptedMarkers = [marker, ...legacyMarkers];
107
+ const existing = topLevelTomlString(text, key);
108
+ const ownedMarker = acceptedMarkers.find((candidate) => topLevelHasLine(text, candidate));
109
+ if (existing && !ownedMarker) {
110
+ if (existing === value)
111
+ return text;
112
+ throw new Error(`codex_lb_user_owned_${key}_conflict`);
113
+ }
114
+ let next = text;
115
+ for (const candidate of acceptedMarkers)
116
+ next = removeTopLevelLine(next, candidate);
117
+ next = upsertTopLevelTomlString(next, key, value);
118
+ return addTopLevelMarkerBeforeKey(next, key, marker);
119
+ }
120
+ function removeTopLevelTomlKey(text, key) {
121
+ const lines = String(text || '').split('\n');
122
+ const firstTable = lines.findIndex((line) => /^\s*\[.+\]\s*$/.test(line));
123
+ const end = firstTable === -1 ? lines.length : firstTable;
124
+ const keyPattern = new RegExp(`^\\s*${escapeRegExp(key)}\\s*=`);
125
+ return lines
126
+ .filter((line, index) => index >= end || !keyPattern.test(line))
127
+ .join('\n')
128
+ .replace(/^\n+/, '')
129
+ .replace(/\n{3,}/g, '\n\n');
25
130
  }
26
131
  const CODEX_LB_SHARED_OPENAI_ROUTING_MARKER = '# sks-codex-lb-managed-openai-base-url';
27
132
  export function codexLbSharedOpenAiRoutingState(text = '', baseUrl = '') {