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
@@ -1,293 +0,0 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
- import fsp from 'node:fs/promises';
4
- import { ensureDir, exists, readText, writeTextAtomic } from '../fsx.js';
5
- import { CODEX_LB_SECURE_KEYCHAIN_SERVICE, codexLbBaseUrlSecurityBlocker, codexLbEnvPath, codexLbMetadataPath, normalizeCodexLbBaseUrl } from './codex-lb-env.js';
6
- import { DEFAULT_CODEX_LB_DESKTOP_MODE, DEFAULT_CODEX_LB_GATEWAY_AUTH_TRANSPORT } from './desktop-mode.js';
7
- export function buildCodexLbSetupPlan(answers, opts = {}) {
8
- const home = opts.home || process.env.HOME || os.homedir();
9
- const baseUrl = normalizeCodexLbBaseUrl(answers.host_or_base_url);
10
- const configPath = opts.configPath || path.join(home, '.codex', 'config.toml');
11
- const envPath = opts.envPath || codexLbEnvPath(home);
12
- const metadataPath = opts.metadataPath || codexLbMetadataPath(home);
13
- const desktopMode = answers.desktop_mode || DEFAULT_CODEX_LB_DESKTOP_MODE;
14
- const gatewayAuthTransport = answers.gateway_auth_transport || DEFAULT_CODEX_LB_GATEWAY_AUTH_TRANSPORT;
15
- const blockers = [];
16
- if (!baseUrl)
17
- blockers.push('missing_host_or_base_url');
18
- else {
19
- const transportBlocker = codexLbBaseUrlSecurityBlocker(baseUrl);
20
- if (transportBlocker)
21
- blockers.push(transportBlocker);
22
- }
23
- if (answers.install_shell_profile !== 'skip' && !answers.write_env_file)
24
- blockers.push('shell_profile_snippet_requires_env_file');
25
- if (answers.store_keychain && answers.keychain_helper_verified !== true) {
26
- blockers.push('keychain_acl_helper_unavailable');
27
- }
28
- const actions = [];
29
- if (desktopMode === 'desktop-native-bridge') {
30
- actions.push({
31
- type: 'configure_desktop_native_bridge',
32
- target: configPath,
33
- effect: `keep built-in OpenAI and ChatGPT OAuth, route model traffic through a loopback bridge, and use explicit gateway auth transport ${gatewayAuthTransport}`
34
- });
35
- actions.push({
36
- type: 'start_desktop_bridge',
37
- target: 'SKS Codex Desktop bridge',
38
- effect: 'start the loopback-only bridge without changing Codex Desktop auth'
39
- });
40
- actions.push({
41
- type: 'verify_oauth_preserved',
42
- target: path.join(home, '.codex', 'auth.json'),
43
- effect: 'verify byte identity before App restart and semantic OAuth identity afterward'
44
- });
45
- }
46
- else if (desktopMode === 'desktop-dual-auth-compat') {
47
- blockers.push('desktop_dual_auth_compat_requires_global_secret_environment');
48
- if (gatewayAuthTransport !== 'x-codex-lb-api-key') {
49
- blockers.push('desktop_compat_requires_x_codex_lb_api_key_transport');
50
- }
51
- actions.push({
52
- type: 'configure_desktop_compat_provider',
53
- target: configPath,
54
- effect: 'configure exact provider name "OpenAI", retain ChatGPT OAuth, and send the separate LB key only with X-Codex-LB-API-Key'
55
- });
56
- actions.push({
57
- type: 'verify_oauth_preserved',
58
- target: path.join(home, '.codex', 'auth.json'),
59
- effect: 'verify Desktop configuration did not change shared OAuth bytes'
60
- });
61
- }
62
- else if (desktopMode === 'cli-provider') {
63
- actions.push({
64
- type: 'write_cli_provider',
65
- target: configPath,
66
- effect: answers.use_as_default_provider === true
67
- ? 'atomically write and select the codex-lb provider using CODEX_LB_API_KEY without changing auth.json'
68
- : 'write an unselected CLI-only codex-lb provider using CODEX_LB_API_KEY without changing Desktop OAuth'
69
- });
70
- }
71
- if (answers.write_env_file) {
72
- actions.push({ type: 'write_env_file', target: envPath, effect: 'write CODEX_LB_BASE_URL and redacted CODEX_LB_API_KEY env loader with chmod 0600' });
73
- }
74
- if (answers.store_keychain) {
75
- actions.push({
76
- type: 'store_keychain',
77
- target: `macOS Keychain service ${CODEX_LB_SECURE_KEYCHAIN_SERVICE}`,
78
- effect: 'blocked until SKS ships a dedicated signed Keychain helper; reusable interpreters are never trusted for secret access'
79
- });
80
- }
81
- if (answers.sync_launchctl) {
82
- const cliProviderSelected = desktopMode === 'cli-provider'
83
- && answers.use_as_default_provider === true;
84
- actions.push({
85
- type: 'sync_launchctl',
86
- target: 'macOS launchctl user environment',
87
- effect: cliProviderSelected
88
- ? 'set CODEX_LB_API_KEY and CODEX_LB_BASE_URL from the canonical owner-only env file for selected CLI-provider mode'
89
- : 'remove CODEX_LB_API_KEY outside selected CLI-provider mode and reconcile the non-secret base URL for the chosen mode',
90
- command: cliProviderSelected
91
- ? 'launchctl setenv CODEX_LB_API_KEY <canonical-env-file-value>; launchctl setenv CODEX_LB_BASE_URL ...; launchctl unsetenv OPENROUTER_API_KEY'
92
- : 'launchctl unsetenv CODEX_LB_API_KEY OPENROUTER_API_KEY; reconcile CODEX_LB_BASE_URL for the chosen mode'
93
- });
94
- }
95
- if (answers.install_shell_profile !== 'skip') {
96
- actions.push({ type: 'install_shell_profile_snippet', target: profileTargets(home, answers.install_shell_profile).join(', '), effect: `install managed shell snippet for ${answers.install_shell_profile}` });
97
- }
98
- if (answers.run_health_check) {
99
- actions.push({ type: 'run_capability_check', target: 'codex-lb response chain', effect: 'run codex-lb capability check after apply' });
100
- }
101
- actions.push({ type: 'write_metadata', target: metadataPath, effect: 'write redacted setup metadata and key fingerprint with chmod 0600' });
102
- const selectedModes = selectedCodexLbPersistenceModes(answers);
103
- const persistence = codexLbPersistenceSummary({
104
- selectedModes,
105
- appliedModes: selectedModes.length ? [] : ['process_only_ephemeral'],
106
- processOnly: selectedModes.length === 0
107
- });
108
- return {
109
- schema: 'sks.codex-lb-setup-plan.v1',
110
- base_url: baseUrl,
111
- actions,
112
- expected_actions: actions,
113
- selected_persistence_modes: selectedModes.length ? selectedModes : ['process_only_ephemeral'],
114
- persistence,
115
- redactions: ['CODEX_LB_API_KEY', 'api_key', 'sk-*', 'sk-clb-*'],
116
- warnings: persistence.warnings,
117
- blockers
118
- };
119
- }
120
- export function renderCodexLbSetupPlan(plan) {
121
- const lines = [
122
- 'codex-lb setup plan',
123
- `base_url: ${plan.base_url || '(missing)'}`,
124
- 'actions:'
125
- ];
126
- for (const action of plan.actions)
127
- lines.push(`- ${action.type}: ${action.target} (${action.effect})`);
128
- if (plan.persistence.warning)
129
- lines.push(`warning: ${plan.persistence.warning}`);
130
- if (plan.blockers.length) {
131
- lines.push('blockers:');
132
- for (const blocker of plan.blockers)
133
- lines.push(`- ${blocker}`);
134
- }
135
- return `${lines.join('\n')}\n`;
136
- }
137
- export async function installCodexLbShellProfileSnippet(opts) {
138
- if (opts.shellProfile === 'skip')
139
- return { ok: true, status: 'skipped', skipped: true, files: [] };
140
- if (!(await exists(opts.envPath))) {
141
- return { ok: true, status: 'skipped', skipped: true, reason: 'env_file_not_written', files: [] };
142
- }
143
- if (Boolean(opts.expectedFiles) !== Boolean(opts.writeFileIfUnchanged)) {
144
- return {
145
- ok: false,
146
- status: 'setup_cas_contract_incomplete',
147
- files: [],
148
- error: 'expectedFiles and writeFileIfUnchanged must be provided together'
149
- };
150
- }
151
- const home = opts.home || process.env.HOME || os.homedir();
152
- const targets = profileTargets(home, opts.shellProfile);
153
- const files = [];
154
- const recoveryPaths = [];
155
- for (const file of targets) {
156
- const expected = opts.expectedFiles?.find((entry) => path.resolve(entry.path) === path.resolve(file));
157
- if (opts.expectedFiles && !expected) {
158
- return {
159
- ok: false,
160
- status: 'setup_snapshot_missing',
161
- files,
162
- recovery_paths: recoveryPaths,
163
- error: `setup_snapshot_missing:${file}`
164
- };
165
- }
166
- if (expected?.existed === true && expected.kind !== 'regular') {
167
- return {
168
- ok: false,
169
- status: 'unsafe_setup_write_target',
170
- files,
171
- recovery_paths: recoveryPaths,
172
- error: `unsafe_setup_write_target:${file}:${expected.kind}`
173
- };
174
- }
175
- const current = expected
176
- ? (expected.existed === true
177
- ? Buffer.from(String(expected.bytes_base64 || ''), 'base64').toString('utf8')
178
- : '')
179
- : await readText(file, '');
180
- const block = shellProfileBlock(file, opts.envPath);
181
- const text = upsertManagedBlock(current, block);
182
- const existingMode = expected
183
- ? (expected.existed === true ? Number(expected.mode) & 0o777 : null)
184
- : await fsp.lstat(file)
185
- .then((stat) => stat.isFile() && !stat.isSymbolicLink() ? stat.mode & 0o777 : null)
186
- .catch(() => null);
187
- const mode = existingMode ?? (0o666 & ~process.umask());
188
- if (expected && opts.writeFileIfUnchanged) {
189
- const result = await opts.writeFileIfUnchanged({ file, expected, text, mode });
190
- if (result.recovery_path)
191
- recoveryPaths.push(result.recovery_path);
192
- if (!result.ok) {
193
- return {
194
- ok: false,
195
- status: result.status,
196
- files,
197
- recovery_paths: recoveryPaths,
198
- error: result.error || `${result.status}:${file}`
199
- };
200
- }
201
- }
202
- else {
203
- await ensureDir(path.dirname(file));
204
- await writeTextAtomic(file, text);
205
- }
206
- await opts.onFileWritten?.({ file, text, mode });
207
- files.push(file);
208
- }
209
- return {
210
- ok: true,
211
- status: 'installed',
212
- files,
213
- ...(recoveryPaths.length ? { recovery_paths: recoveryPaths } : {})
214
- };
215
- }
216
- export function selectedCodexLbPersistenceModes(answers) {
217
- const modes = [];
218
- if (answers.write_env_file)
219
- modes.push('durable_env_file');
220
- if (answers.store_keychain)
221
- modes.push('durable_keychain');
222
- if (answers.install_shell_profile !== 'skip')
223
- modes.push('shell_profile');
224
- return modes;
225
- }
226
- export function codexLbPersistenceSummary({ selectedModes = [], appliedModes = [], processOnly = false } = {}) {
227
- const selected = normalizePersistenceModes(selectedModes);
228
- const applied = normalizePersistenceModes(appliedModes);
229
- const effective = applied.find((mode) => mode !== 'process_only_ephemeral' && mode !== 'none')
230
- || selected.find((mode) => mode !== 'process_only_ephemeral' && mode !== 'none')
231
- || (processOnly || applied.includes('process_only_ephemeral') || selected.length === 0 ? 'process_only_ephemeral' : 'none');
232
- const durable = ['durable_env_file', 'durable_keychain', 'shell_profile'].some((mode) => applied.includes(mode) || selected.includes(mode));
233
- const warnings = effective === 'process_only_ephemeral'
234
- ? [
235
- 'process_only_ephemeral',
236
- 'next_session_requires_center_or_setup',
237
- 'Save credentials in SKS Center (or sks codex-lb setup --write-env-file --keychain) so Desktop can load them automatically'
238
- ]
239
- : [];
240
- return {
241
- selected_modes: selected.length ? selected : ['process_only_ephemeral'],
242
- applied_modes: applied.length ? applied : (effective === 'none' ? ['none'] : [effective]),
243
- effective_mode: effective,
244
- durable,
245
- warning: warnings[0] || null,
246
- warnings
247
- };
248
- }
249
- function normalizePersistenceModes(modes = []) {
250
- const allowed = new Set([
251
- 'durable_env_file',
252
- 'durable_keychain',
253
- 'shell_profile',
254
- 'process_only_ephemeral',
255
- 'none'
256
- ]);
257
- return [...new Set(modes.filter((mode) => allowed.has(mode)))];
258
- }
259
- function profileTargets(home, choice) {
260
- const targets = {
261
- zsh: path.join(home, '.zshrc'),
262
- bash: path.join(home, '.bashrc'),
263
- fish: path.join(home, '.config', 'fish', 'config.fish')
264
- };
265
- if (choice === 'all')
266
- return [targets.zsh, targets.bash, targets.fish];
267
- if (choice === 'skip')
268
- return [];
269
- return [targets[choice]];
270
- }
271
- function shellProfileBlock(file, envPath) {
272
- const fish = file.endsWith(path.join('fish', 'config.fish'));
273
- const sourceLine = fish
274
- ? `test -f ${fishQuote(envPath)}; and source ${fishQuote(envPath)}`
275
- : `[ -f ${shellSingleQuote(envPath)} ] && . ${shellSingleQuote(envPath)}`;
276
- return [
277
- '# BEGIN SKS CODEX-LB',
278
- sourceLine,
279
- '# END SKS CODEX-LB'
280
- ].join('\n');
281
- }
282
- function upsertManagedBlock(text, block) {
283
- const re = /# BEGIN SKS CODEX-LB[\s\S]*?# END SKS CODEX-LB/g;
284
- const trimmed = String(text || '').trimEnd();
285
- const next = re.test(trimmed) ? trimmed.replace(re, block) : `${trimmed}${trimmed ? '\n\n' : ''}${block}`;
286
- return `${next.trimEnd()}\n`;
287
- }
288
- function shellSingleQuote(value) {
289
- return `'${String(value).replace(/'/g, `'\\''`)}'`;
290
- }
291
- function fishQuote(value) {
292
- return `'${String(value).replace(/'/g, "\\'")}'`;
293
- }