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,91 +0,0 @@
1
- import { normalizeCodexModelId, readTopLevelTomlString } from './codex-model-catalog.js';
2
- export const CODEX_PROVIDER_MODE_MARKER_PREFIX = '# sks-managed-provider-mode:';
3
- export const CODEX_NATIVE_PROVIDER_ID = 'openai';
4
- const MODES = new Set(['chatgpt-oauth', 'codex-lb', 'openrouter']);
5
- export function isCodexProviderMode(value) {
6
- return MODES.has(String(value || '').trim());
7
- }
8
- export function readExplicitCodexProviderMode(configText) {
9
- const values = String(configText || '')
10
- .split('\n')
11
- .map((line) => line.trim())
12
- .filter((line) => line.startsWith(CODEX_PROVIDER_MODE_MARKER_PREFIX))
13
- .map((line) => line.slice(CODEX_PROVIDER_MODE_MARKER_PREFIX.length).trim());
14
- if (!values.length)
15
- return { mode: null, blockers: ['provider_mode_not_explicit'] };
16
- if (values.length !== 1)
17
- return { mode: null, blockers: ['provider_mode_marker_conflict'] };
18
- const mode = values[0];
19
- if (!isCodexProviderMode(mode))
20
- return { mode: null, blockers: ['provider_mode_marker_invalid'] };
21
- return { mode, blockers: [] };
22
- }
23
- export function upsertExplicitCodexProviderMode(configText, mode) {
24
- const lines = String(configText || '').split('\n');
25
- const filtered = lines.filter((line) => !line.trim().startsWith(CODEX_PROVIDER_MODE_MARKER_PREFIX));
26
- const marker = `${CODEX_PROVIDER_MODE_MARKER_PREFIX}${mode}`;
27
- const firstContent = filtered.findIndex((line) => line.trim().length > 0);
28
- if (firstContent < 0)
29
- return `${marker}\n`;
30
- filtered.splice(firstContent, 0, marker);
31
- return `${filtered.join('\n').replace(/^\n+|\n+$/g, '')}\n`;
32
- }
33
- export function codexProviderModeState(configText) {
34
- const explicit = readExplicitCodexProviderMode(configText);
35
- const selectedProvider = readTopLevelTomlString(configText, 'model_provider');
36
- const openAiBaseUrl = readTopLevelTomlString(configText, 'openai_base_url');
37
- const loopbackConfigured = isLoopbackHttpUrl(openAiBaseUrl);
38
- const loopbackRequired = explicit.mode === 'codex-lb' || explicit.mode === 'openrouter';
39
- const blockers = [...explicit.blockers];
40
- if (explicit.mode && selectedProvider !== CODEX_NATIVE_PROVIDER_ID) {
41
- blockers.push('provider_mode_requires_builtin_openai');
42
- }
43
- if (loopbackRequired && !loopbackConfigured)
44
- blockers.push('provider_mode_loopback_missing');
45
- if (explicit.mode === 'chatgpt-oauth' && openAiBaseUrl) {
46
- blockers.push('chatgpt_oauth_mode_loopback_still_configured');
47
- }
48
- return {
49
- schema: 'sks.codex-provider-mode-state.v1',
50
- mode: explicit.mode,
51
- explicit: explicit.blockers.length === 0,
52
- native_provider_selected: selectedProvider === CODEX_NATIVE_PROVIDER_ID,
53
- loopback_required: loopbackRequired,
54
- loopback_configured: loopbackConfigured,
55
- auxiliary_oauth_required: loopbackRequired,
56
- blockers: [...new Set(blockers)]
57
- };
58
- }
59
- export function providerModeOwnsModel(mode, model) {
60
- const normalized = normalizeCodexModelId(model);
61
- if (!normalized)
62
- return false;
63
- if (mode === 'openrouter')
64
- return normalized.includes('/');
65
- return !normalized.includes('/');
66
- }
67
- export function assertProviderModeModel(mode, model, allowedModels) {
68
- const normalized = normalizeCodexModelId(model);
69
- if (!normalized)
70
- throw new Error('provider_mode_model_invalid');
71
- if (!providerModeOwnsModel(mode, normalized))
72
- throw new Error('provider_mode_model_family_mismatch');
73
- const allowed = new Set(allowedModels.map(normalizeCodexModelId).filter((entry) => Boolean(entry)));
74
- if (!allowed.size)
75
- throw new Error('provider_mode_model_catalog_empty');
76
- if (!allowed.has(normalized))
77
- throw new Error('provider_mode_model_not_allowed');
78
- return normalized;
79
- }
80
- function isLoopbackHttpUrl(value) {
81
- if (!value)
82
- return false;
83
- try {
84
- const parsed = new URL(value);
85
- const host = parsed.hostname.replace(/^\[|\]$/g, '').toLowerCase();
86
- return parsed.protocol === 'http:' && (host === '127.0.0.1' || host === '::1' || host === 'localhost');
87
- }
88
- catch {
89
- return false;
90
- }
91
- }
@@ -1,85 +0,0 @@
1
- import { assertProviderModeModel } from './provider-mode.js';
2
- export const PROVIDER_SESSION_SCHEMA = 'sks.provider-session.v1';
3
- export function createProviderSessionPin(input) {
4
- const sessionId = validSessionId(input.sessionId);
5
- if (!sessionId)
6
- throw new Error('provider_session_id_invalid');
7
- if (input.parent) {
8
- if (input.mode !== input.parent.mode)
9
- throw new Error('provider_session_fork_mode_mismatch');
10
- if (input.model !== input.parent.model)
11
- throw new Error('provider_session_fork_model_mismatch');
12
- if (stableModels(input.allowedModels).join('\0') !== stableModels(input.parent.allowed_models).join('\0')) {
13
- throw new Error('provider_session_fork_catalog_mismatch');
14
- }
15
- }
16
- const allowedModels = stableModels(input.allowedModels);
17
- if (input.mode === 'chatgpt-oauth') {
18
- if (!allowedModels.includes(input.model))
19
- throw new Error('provider_session_model_not_allowed');
20
- }
21
- else {
22
- assertProviderModeModel(input.mode, input.model, allowedModels);
23
- }
24
- return {
25
- schema: PROVIDER_SESSION_SCHEMA,
26
- session_id: sessionId,
27
- mode: input.mode,
28
- model: input.model,
29
- allowed_models: allowedModels,
30
- created_at: input.createdAt || new Date().toISOString(),
31
- parent_session_id: input.parent?.session_id || null
32
- };
33
- }
34
- export function providerSessionStatus(input) {
35
- if (!input.pin) {
36
- return {
37
- schema: 'sks.provider-session-status.v1',
38
- ok: false,
39
- status: 'migration_required',
40
- session_mode: null,
41
- new_session_default_mode: input.globalDefaultMode,
42
- mode_changed_since_creation: null,
43
- blockers: ['legacy_session_provider_mode_selection_required'],
44
- action: 'Choose a mode explicitly, then start a new session.'
45
- };
46
- }
47
- const modeChanged = input.pin.mode !== input.globalDefaultMode;
48
- return {
49
- schema: 'sks.provider-session-status.v1',
50
- ok: true,
51
- status: modeChanged ? 'pinned_while_default_changed' : 'pinned',
52
- session_mode: input.pin.mode,
53
- new_session_default_mode: input.globalDefaultMode,
54
- mode_changed_since_creation: modeChanged,
55
- blockers: [],
56
- action: modeChanged
57
- ? `This session continues in ${input.pin.mode}; start a new session to use ${input.globalDefaultMode}.`
58
- : `This session is pinned to ${input.pin.mode}.`
59
- };
60
- }
61
- export function assertProviderSessionRequest(pin, input) {
62
- if (pin.mode !== input.mode)
63
- throw new Error('provider_session_mode_switch_forbidden');
64
- if (!pin.allowed_models.includes(input.model))
65
- throw new Error('provider_session_model_switch_forbidden');
66
- }
67
- export function classifyPinnedProviderFailure(status) {
68
- if (status === 401 || status === 403) {
69
- return { retry_allowed: false, stop_session: true, blocker: 'provider_session_authentication_failed', action: 'Verify this mode credential, then start a new session.' };
70
- }
71
- if (status === 402 || status === 429) {
72
- return { retry_allowed: false, stop_session: true, blocker: 'provider_session_quota_or_rate_limit', action: 'Do not fail over accounts; resolve quota or start a new session explicitly.' };
73
- }
74
- if (status >= 500) {
75
- return { retry_allowed: false, stop_session: true, blocker: 'provider_session_upstream_failed', action: 'Keep the pinned account and retry only after explicit user action.' };
76
- }
77
- return { retry_allowed: true, stop_session: false, blocker: null, action: null };
78
- }
79
- function stableModels(models) {
80
- return [...new Set(models.map((model) => String(model || '').trim()).filter(Boolean))].sort();
81
- }
82
- function validSessionId(value) {
83
- const id = String(value || '').trim();
84
- return /^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(id) ? id : null;
85
- }
@@ -1,68 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { assertProviderPolicyCompatible, stableArchitectureHash } from '../../architecture-hardening/contracts/contracts.js';
3
- export function createSessionPin(input) {
4
- if (!validId(input.sessionId))
5
- throw new Error('session_pin_id_invalid');
6
- const model = String(input.model || '').trim();
7
- if (!input.policy.allowed_models.includes(model))
8
- throw new Error('session_pin_model_not_allowed');
9
- if ((input.policy.mode === 'openrouter') !== model.includes('/'))
10
- throw new Error('session_pin_model_family_mismatch');
11
- if (input.policy.mode === 'codex-lb' && !input.lbAffinityToken)
12
- throw new Error('session_pin_lb_affinity_required');
13
- if (input.policy.mode !== 'codex-lb' && input.lbAffinityToken)
14
- throw new Error('session_pin_lb_affinity_forbidden');
15
- return Object.freeze({
16
- schema: 'sks.session-pin.v1',
17
- session_id: input.sessionId,
18
- mode: input.policy.mode,
19
- model,
20
- credential_class: input.policy.credential_class,
21
- allowed_models: Object.freeze([...input.policy.allowed_models]),
22
- lb_affinity_token_hash: input.lbAffinityToken ? createHash('sha256').update(input.lbAffinityToken).digest('hex') : null,
23
- child_policy_hash: input.policy.child_policy_hash,
24
- catalog_version: input.policy.catalog_version,
25
- parent_session_id: input.parentSessionId || null
26
- });
27
- }
28
- export function forkSessionPin(parent, sessionId) {
29
- if (!validId(sessionId))
30
- throw new Error('session_pin_id_invalid');
31
- return Object.freeze({ ...parent, session_id: sessionId, parent_session_id: parent.session_id, allowed_models: Object.freeze([...parent.allowed_models]) });
32
- }
33
- export function resumeSessionPin(pin, policy) {
34
- if (!pin)
35
- return { schema: 'sks.session-resume-decision.v1', ok: false, status: 'migration_required', pin: null, blocker: 'session_pin_metadata_missing' };
36
- const pinnedPolicy = {
37
- schema: 'sks.provider-policy-snapshot.v1',
38
- contract_version: policy.contract_version,
39
- mode: pin.mode,
40
- credential_class: pin.credential_class,
41
- allowed_models: pin.allowed_models,
42
- child_policy_hash: pin.child_policy_hash,
43
- catalog_version: pin.catalog_version
44
- };
45
- try {
46
- assertProviderPolicyCompatible(pinnedPolicy, policy);
47
- }
48
- catch (error) {
49
- return { schema: 'sks.session-resume-decision.v1', ok: false, status: 'blocked', pin, blocker: error.message };
50
- }
51
- if (!pin.allowed_models.includes(pin.model))
52
- return { schema: 'sks.session-resume-decision.v1', ok: false, status: 'blocked', pin, blocker: 'session_pin_model_restore_mismatch' };
53
- return { schema: 'sks.session-resume-decision.v1', ok: true, status: 'resumable', pin, blocker: null };
54
- }
55
- export function sessionPinHash(pin) {
56
- return stableArchitectureHash(pin);
57
- }
58
- export function assertSessionRequest(pin, input) {
59
- if (pin.mode !== input.mode)
60
- throw new Error('session_pin_mode_switch_forbidden');
61
- if (pin.model !== input.model)
62
- throw new Error('session_pin_model_switch_forbidden');
63
- if (pin.child_policy_hash !== input.childPolicyHash)
64
- throw new Error('session_pin_child_policy_mismatch');
65
- }
66
- function validId(value) {
67
- return /^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(String(value || ''));
68
- }
@@ -1,319 +0,0 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
- import { parseCodexConfigToml } from '../codex/codex-config-toml.js';
4
- import { readText } from '../fsx.js';
5
- import { codexLbToolOutputRecoveryNotChecked, codexLbToolOutputRecoveryNotSelected, codexLbToolOutputRecoveryOverrideAcknowledged, probeCodexLbToolOutputRecovery } from '../codex-lb/codex-lb-tool-output-recovery.js';
6
- import { normalizeCodexLbBaseUrl } from '../codex-lb/codex-lb-env.js';
7
- export async function inspectCodexLbSdkLaunchRecovery(input) {
8
- if (String(input.config.model_provider || '') !== 'codex-lb') {
9
- return codexLbToolOutputRecoveryNotSelected();
10
- }
11
- const providers = input.config.model_providers;
12
- const baseUrl = String(providers?.['codex-lb']?.base_url
13
- || input.env.CODEX_LB_BASE_URL
14
- || '');
15
- return probeCodexLbToolOutputRecovery({
16
- baseUrl,
17
- ...(input.fetchImpl ? { fetchImpl: input.fetchImpl } : {}),
18
- ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
19
- allowUnverified: codexLbToolOutputRecoveryOverrideAcknowledged({
20
- env: input.overrideEnv || input.env
21
- })
22
- });
23
- }
24
- export async function inspectCodexLbCliLaunchRecovery(input) {
25
- const env = input.env || process.env;
26
- const args = (input.cliArgs || []).map((arg) => String(arg));
27
- const codexHome = path.resolve(String(env.CODEX_HOME || path.join(env.HOME || os.homedir(), '.codex')));
28
- const userConfigPath = path.join(codexHome, 'config.toml');
29
- const effectiveRoot = effectiveCodexWorkingRoot(input.root, args);
30
- if (!effectiveRoot.ok)
31
- return configParseBlocked(effectiveRoot.blockers);
32
- const projectConfigPath = path.join(effectiveRoot.root, '.codex', 'config.toml');
33
- const ignoreUserConfig = args.includes('--ignore-user-config');
34
- const profileName = ignoreUserConfig ? null : cliOptionValue(args, ['--profile', '-p', '-P']);
35
- const profileConfigPath = profileName && safeProfileName(profileName)
36
- ? path.join(codexHome, `${profileName}.config.toml`)
37
- : null;
38
- const userConfig = ignoreUserConfig
39
- ? configLayer('', 'user')
40
- : configLayer(await readText(userConfigPath, '').catch(() => ''), 'user');
41
- const profileConfig = profileConfigPath
42
- ? configLayer(await readText(profileConfigPath, '').catch(() => ''), 'profile')
43
- : configLayer('', 'profile');
44
- const projectConfig = path.resolve(projectConfigPath) === path.resolve(userConfigPath)
45
- ? configLayer('', 'project')
46
- : configLayer(await readText(projectConfigPath, '').catch(() => ''), 'project');
47
- const overrides = cliConfigOverrides(args);
48
- const environmentSelectsCodexLb = env.SKS_PROVIDER === 'codex-lb' || env.SKS_USE_CODEX_LB === '1';
49
- if (cliSelectsLocalProvider(args)) {
50
- return codexLbToolOutputRecoveryNotSelected();
51
- }
52
- const loadedLayers = [userConfig, profileConfig, projectConfig];
53
- const parseBlockers = loadedLayers
54
- .filter((layer) => layer.parseFailed && layer.rawSelectsCodexLb)
55
- .map((layer) => `codex_lb_launch_config_parse_failed:${layer.source}`);
56
- if (parseBlockers.length > 0)
57
- return configParseBlocked(parseBlockers);
58
- if (projectConfig.hasMachineLocalProviderConfig) {
59
- return projectProviderConfigBlocked();
60
- }
61
- if (overrides.modelProvider && overrides.modelProvider !== 'codex-lb') {
62
- return codexLbToolOutputRecoveryNotSelected();
63
- }
64
- const selectedProvider = overrides.modelProvider
65
- ?? (environmentSelectsCodexLb ? 'codex-lb' : null)
66
- ?? profileConfig.modelProvider
67
- ?? userConfig.modelProvider
68
- ?? '';
69
- if (selectedProvider !== 'codex-lb') {
70
- return codexLbToolOutputRecoveryNotSelected();
71
- }
72
- const codexProcessSelectsCodexLb = overrides.modelProvider === 'codex-lb'
73
- || profileConfig.modelProvider === 'codex-lb'
74
- || userConfig.modelProvider === 'codex-lb';
75
- if (environmentSelectsCodexLb && !codexProcessSelectsCodexLb) {
76
- return environmentSelectionNotForwardedBlocked();
77
- }
78
- const baseUrl = overrides.baseUrl
79
- ?? profileConfig.baseUrl
80
- ?? userConfig.baseUrl
81
- ?? String(env.CODEX_LB_BASE_URL || '');
82
- const verifiedProbe = reusableVerifiedProbeForBase(input.verifiedProbe, baseUrl);
83
- if (verifiedProbe)
84
- return verifiedProbe;
85
- return probeCodexLbToolOutputRecovery({
86
- baseUrl,
87
- ...(input.fetchImpl ? { fetchImpl: input.fetchImpl } : {}),
88
- ...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
89
- allowUnverified: input.allowUnverified === true
90
- || codexLbToolOutputRecoveryOverrideAcknowledged({ args, env })
91
- });
92
- }
93
- function reusableVerifiedProbeForBase(value, selectedBaseUrl) {
94
- if (!value || value.schema !== 'sks.codex-lb-tool-output-recovery.v1')
95
- return null;
96
- if (value.ok !== true || value.required !== true || value.verified !== true || value.supports_interrupted_tool_output_recovery !== true)
97
- return null;
98
- const verifiedBaseUrl = normalizeCodexLbBaseUrl(value.base_url);
99
- const effectiveBaseUrl = normalizeCodexLbBaseUrl(selectedBaseUrl);
100
- if (!verifiedBaseUrl || !effectiveBaseUrl || verifiedBaseUrl !== effectiveBaseUrl)
101
- return null;
102
- return value;
103
- }
104
- export async function withCodexLbCliLaunchRecovery(input, launch) {
105
- const toolOutputRecovery = await inspectCodexLbCliLaunchRecovery(input);
106
- if (!toolOutputRecovery.ok) {
107
- return {
108
- launched: false,
109
- toolOutputRecovery,
110
- value: null
111
- };
112
- }
113
- return {
114
- launched: true,
115
- toolOutputRecovery,
116
- value: await launch()
117
- };
118
- }
119
- export function codexLbRecoveryBlockedProcessResult(probe) {
120
- const stderr = codexLbRecoveryBlockedMessage(probe);
121
- return {
122
- code: 78,
123
- stdout: '',
124
- stderr,
125
- stdoutBytes: 0,
126
- stderrBytes: Buffer.byteLength(stderr),
127
- truncated: false,
128
- timedOut: false,
129
- codexLbToolOutputRecovery: probe
130
- };
131
- }
132
- export function codexLbRecoveryBlockedMessage(probe) {
133
- if (probe.blockers.includes('codex_lb_launch_selection_not_forwarded')) {
134
- return [
135
- 'Codex launch blocked: codex-lb was requested by the SKS environment but was not selected in the Codex process.',
136
- ...probe.blockers.map((blocker) => `blocker: ${blocker}`),
137
- ...probe.operator_actions
138
- ].join('\n');
139
- }
140
- return [
141
- 'Codex launch blocked: selected codex-lb interrupted tool-output recovery is not verified.',
142
- ...probe.blockers.map((blocker) => `blocker: ${blocker}`),
143
- ...probe.operator_actions
144
- ].join('\n');
145
- }
146
- function configLayer(text, source) {
147
- const raw = String(text || '');
148
- if (!raw.trim()) {
149
- return {
150
- source,
151
- modelProvider: null,
152
- baseUrl: null,
153
- parseFailed: false,
154
- rawSelectsCodexLb: false,
155
- hasMachineLocalProviderConfig: false
156
- };
157
- }
158
- try {
159
- const parsed = parseCodexConfigToml(raw);
160
- return {
161
- source,
162
- modelProvider: stringValue(parsed.model_provider),
163
- baseUrl: stringValue(parsed.model_providers?.['codex-lb']?.base_url),
164
- parseFailed: false,
165
- rawSelectsCodexLb: false,
166
- hasMachineLocalProviderConfig: source === 'project' && Boolean(stringValue(parsed.model_provider)
167
- || (parsed.model_providers && typeof parsed.model_providers === 'object' && Object.keys(parsed.model_providers).length)
168
- || stringValue(parsed.openai_base_url)
169
- || stringValue(parsed.chatgpt_base_url))
170
- };
171
- }
172
- catch {
173
- return {
174
- source,
175
- modelProvider: null,
176
- baseUrl: null,
177
- parseFailed: true,
178
- rawSelectsCodexLb: /^\s*model_provider\s*=\s*(?:"codex-lb"|'codex-lb'|codex-lb)\s*(?:#.*)?$/mi.test(raw),
179
- hasMachineLocalProviderConfig: source === 'project' && /^\s*(?:model_provider|openai_base_url|chatgpt_base_url)\s*=|^\s*\[model_providers(?:\.|\])/mi.test(raw)
180
- };
181
- }
182
- }
183
- function cliConfigOverrides(args) {
184
- let modelProvider = null;
185
- let baseUrl = null;
186
- for (let index = 0; index < args.length; index += 1) {
187
- const arg = args[index] || '';
188
- let override = null;
189
- if (arg === '-c' || arg === '--config') {
190
- override = args[index + 1] || '';
191
- index += 1;
192
- }
193
- else if (arg.startsWith('--config=')) {
194
- override = arg.slice('--config='.length);
195
- }
196
- else if (arg.startsWith('-c=')) {
197
- override = arg.slice(3);
198
- }
199
- if (!override)
200
- continue;
201
- const equals = override.indexOf('=');
202
- if (equals < 1)
203
- continue;
204
- const key = normalizeDottedKey(override.slice(0, equals));
205
- const value = parseCliTomlValue(override.slice(equals + 1));
206
- if (key === 'model_provider')
207
- modelProvider = stringValue(value);
208
- if (key === 'model_providers.codex-lb.base_url')
209
- baseUrl = stringValue(value);
210
- if (key === 'model_providers.codex-lb' && value && typeof value === 'object') {
211
- baseUrl = stringValue(value.base_url) ?? baseUrl;
212
- }
213
- if (key === 'model_providers' && value && typeof value === 'object') {
214
- baseUrl = stringValue(value?.['codex-lb']?.base_url) ?? baseUrl;
215
- }
216
- }
217
- return { modelProvider, baseUrl };
218
- }
219
- function parseCliTomlValue(raw) {
220
- try {
221
- return parseCodexConfigToml(`value = ${raw}\n`).value;
222
- }
223
- catch {
224
- return String(raw || '').trim();
225
- }
226
- }
227
- function cliOptionValue(args, names) {
228
- for (let index = 0; index < args.length; index += 1) {
229
- const arg = args[index] || '';
230
- if (names.includes(arg))
231
- return String(args[index + 1] || '').trim() || null;
232
- for (const name of names) {
233
- if (arg.startsWith(`${name}=`))
234
- return arg.slice(name.length + 1).trim() || null;
235
- }
236
- }
237
- return null;
238
- }
239
- function cliSelectsLocalProvider(args) {
240
- return args.includes('--oss');
241
- }
242
- export function effectiveCodexWorkingRoot(fallbackRoot, args) {
243
- const base = path.resolve(fallbackRoot);
244
- let selected = null;
245
- for (let index = 0; index < args.length; index += 1) {
246
- const arg = args[index] || '';
247
- if (arg === '--')
248
- break;
249
- if (arg === '-C' || arg === '--cd') {
250
- const next = String(args[index + 1] || '').trim();
251
- if (!next || next.startsWith('-')) {
252
- return { ok: false, root: base, blockers: ['codex_lb_launch_working_root_value_missing'] };
253
- }
254
- selected = next;
255
- index += 1;
256
- continue;
257
- }
258
- if (arg.startsWith('--cd=') || arg.startsWith('-C=')) {
259
- const value = arg.slice(arg.indexOf('=') + 1).trim();
260
- if (!value)
261
- return { ok: false, root: base, blockers: ['codex_lb_launch_working_root_value_missing'] };
262
- selected = value;
263
- }
264
- }
265
- return {
266
- ok: true,
267
- root: selected ? path.resolve(base, selected) : base,
268
- blockers: []
269
- };
270
- }
271
- function safeProfileName(value) {
272
- return /^[A-Za-z0-9_.-]{1,128}$/.test(value);
273
- }
274
- function normalizeDottedKey(value) {
275
- return String(value || '').trim().replace(/["']/g, '').replace(/\s+/g, '');
276
- }
277
- function stringValue(value) {
278
- return typeof value === 'string' && value.trim() ? value.trim() : null;
279
- }
280
- function configParseBlocked(blockers) {
281
- const base = codexLbToolOutputRecoveryNotChecked(true);
282
- return {
283
- ...base,
284
- status: 'version_unverified',
285
- blockers,
286
- warnings: ['selected_codex_lb_config_could_not_be_parsed_safely'],
287
- operator_actions: [
288
- 'Repair the selected Codex config TOML, then rerun `sks codex-lb status`.',
289
- ...base.operator_actions
290
- ]
291
- };
292
- }
293
- function projectProviderConfigBlocked() {
294
- const base = codexLbToolOutputRecoveryNotChecked(true);
295
- return {
296
- ...base,
297
- status: 'version_unverified',
298
- blockers: ['codex_lb_launch_project_provider_config_forbidden'],
299
- warnings: ['machine_local_provider_config_must_live_in_codex_home'],
300
- operator_actions: [
301
- 'Run `sks doctor --fix` to move or remove machine-local provider settings from the project `.codex/config.toml`.',
302
- 'Rerun `sks codex-lb status` before launching Codex.',
303
- ...base.operator_actions
304
- ]
305
- };
306
- }
307
- function environmentSelectionNotForwardedBlocked() {
308
- const base = codexLbToolOutputRecoveryNotChecked(true);
309
- return {
310
- ...base,
311
- status: 'version_unverified',
312
- blockers: ['codex_lb_launch_selection_not_forwarded'],
313
- warnings: ['sks_provider_environment_does_not_select_the_codex_process_provider'],
314
- operator_actions: [
315
- `Launch Codex with \`--config model_provider='"codex-lb"'\`, or select codex-lb in the active Codex profile.`,
316
- 'Rerun `sks codex-lb status` before launching Codex.'
317
- ]
318
- };
319
- }