sneakoscope 9.1.1 → 9.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 (28) hide show
  1. package/README.md +1 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/commands/bridge.js +11 -0
  5. package/dist/config/skills-manifest.json +1 -1
  6. package/dist/core/codex-app.js +1 -1
  7. package/dist/core/codex-control/codex-sdk-env-policy.js +44 -9
  8. package/dist/core/codex-lb/bridge-contracts.js +1 -0
  9. package/dist/core/codex-lb/desktop-bridge/header-policy.js +38 -0
  10. package/dist/core/codex-lb/desktop-bridge/http-forward.js +58 -16
  11. package/dist/core/codex-lb/desktop-bridge/rejection-log.js +1 -0
  12. package/dist/core/codex-lb/desktop-bridge/security.js +55 -3
  13. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  14. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +23 -11
  15. package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +1 -3
  16. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +1 -1
  17. package/dist/core/codex-lb/desktop-bridge-migration.js +2 -4
  18. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +6 -4
  19. package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +36 -2
  20. package/dist/core/codex-lb/desktop-controller-v3.js +3 -1
  21. package/dist/core/codex-lb/desktop-service.js +95 -11
  22. package/dist/core/codex-lb/provider-route-policy.js +30 -1
  23. package/dist/core/codex-lb/request-route-resolver.js +14 -0
  24. package/dist/core/imagegen/desktop-bridge-imagegen-target.js +2 -2
  25. package/dist/core/provider/provider-context.js +2 -1
  26. package/dist/core/release/gate-affected-globs.js +9 -0
  27. package/dist/core/version.js +1 -1
  28. package/package.json +1 -1
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 9.1.1** — its own identity, read from `package.json` and subject to release-gate verification, not advice about what to install.
25
+ This README documents package **SKS 9.2.0** — its own identity, read from `package.json` and subject to release-gate verification, not advice about what to install.
26
26
 
27
27
  Use the official latest stable SKS and Codex CLI releases. The Codex compatibility SSOT is always the **current latest stable** host; capability probes measure what that host can actually do. Product docs do not crown a fixed `0.x.y` string as SSOT (release pins and schema directories are measured artifacts for the current package, not a permanent product version claim). 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 supported. Install SSOT is npm `sneakoscope@latest`; PATH `sks` and Menu Bar stamped generation must match that version or gates fail. 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 (Codex official multi-agent wrap-only; SKS does not reimplement a parallel runtime). Local code search is mode-separated (`sks search files|text|structure|symbol|context`); `context` is answered by the compiled TriWiki Context Graph (`context-graph.json` is exhaustive authority; `context-pack.json` and managed `AGENTS.md` are bounded projections) — see [docs/architecture/context-graph.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/docs/architecture/context-graph.md) and [docs/PRODUCT-CONTRACT.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/docs/PRODUCT-CONTRACT.md). See [CHANGELOG.md](https://github.com/mandarange/Sneakoscope-Codex/blob/main/CHANGELOG.md).
28
28
 
@@ -259,7 +259,7 @@ dependencies = [
259
259
 
260
260
  [[package]]
261
261
  name = "sks-core"
262
- version = "9.1.1"
262
+ version = "9.2.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 = "9.1.1"
3
+ version = "9.2.0"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -27,6 +27,7 @@ export function usage(command = 'bridge') {
27
27
  ` sks ${command} models select --set <public-id,...> [--json]`,
28
28
  ` sks ${command} route list [--json]`,
29
29
  ` sks ${command} route set-default <codex-lb|openrouter> [--json]`,
30
+ ` sks ${command} route official-models <passthrough|gateway|auto> [--json]`,
30
31
  ` sks ${command} route explain <model> [--json]`,
31
32
  ` sks ${command} unmanage --confirm [--json]`,
32
33
  ` sks ${command} rollback <receipt-id> --confirm [--json]`,
@@ -236,6 +237,16 @@ async function parseInvocation(args, io) {
236
237
  label: `Default bridge provider set to ${providerId}`
237
238
  };
238
239
  }
240
+ if (action === 'official-models' && target !== undefined && extra === undefined) {
241
+ allowOnly(parsed, ['--json'], []);
242
+ if (target !== 'passthrough' && target !== 'gateway' && target !== 'auto')
243
+ throw new BridgeCliError('bridge_route_official_models_mode_invalid');
244
+ return {
245
+ ...base,
246
+ request: { operation: 'route.official-models', mode: target },
247
+ label: `Official models routing set to ${target}`
248
+ };
249
+ }
239
250
  if (action === 'explain' && target !== undefined && extra === undefined) {
240
251
  allowOnly(parsed, ['--json'], []);
241
252
  return {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schema": "sks.skills-manifest.v1",
3
- "package_version": "9.1.1",
3
+ "package_version": "9.2.0",
4
4
  "skills": [
5
5
  {
6
6
  "canonical_name": "sks",
@@ -894,7 +894,7 @@ function providerModelUiStatusFromDesktopBridge(status) {
894
894
  || status.routing.policy?.default_provider_id
895
895
  || status.routing.session_pin?.provider_id
896
896
  || null;
897
- const selectedProfile = selectedProvider ? status.providers[selectedProvider] : null;
897
+ const selectedProfile = selectedProvider && selectedProvider !== 'openai' ? status.providers[selectedProvider] : null;
898
898
  const selectedProviderBlockers = uniqueStrings([
899
899
  ...status.readiness.blockers,
900
900
  ...status.routing.blockers,
@@ -160,16 +160,51 @@ export async function prepareNativeCodexAuthBridge(env, opts = {}) {
160
160
  applyCleanupProof(bridgeProof, result);
161
161
  return result;
162
162
  }
163
- await assertSourceAuthUnchanged(sourceAuthCandidate, sourceAuthIdentity, sourceAuthFingerprint);
164
- const hostAuth = { ...tempAuth, ...originalApiKeyFields };
165
- const hostAuthText = `${JSON.stringify(hostAuth, null, 2)}\n`;
166
- await writeAuthFileAtomic(sourceAuthCandidate, hostAuthText, async () => {
163
+ try {
167
164
  await assertSourceAuthUnchanged(sourceAuthCandidate, sourceAuthIdentity, sourceAuthFingerprint);
168
- });
169
- await removeOwnedTempRoot();
170
- const result = { ok: true, status: 'cleaned', outcome: 'refreshed_persisted', cleanup_required: false, blockers: [] };
171
- applyCleanupProof(bridgeProof, result);
172
- return result;
165
+ const hostAuth = { ...tempAuth, ...originalApiKeyFields };
166
+ const hostAuthText = `${JSON.stringify(hostAuth, null, 2)}\n`;
167
+ await writeAuthFileAtomic(sourceAuthCandidate, hostAuthText, async () => {
168
+ await assertSourceAuthUnchanged(sourceAuthCandidate, sourceAuthIdentity, sourceAuthFingerprint);
169
+ });
170
+ await removeOwnedTempRoot();
171
+ const result = { ok: true, status: 'cleaned', outcome: 'refreshed_persisted', cleanup_required: false, blockers: [] };
172
+ applyCleanupProof(bridgeProof, result);
173
+ return result;
174
+ }
175
+ catch (error) {
176
+ if (String(error?.message || error) !== 'native_codex_auth_source_conflict')
177
+ throw error;
178
+ const currentText = await readValidatedAuthFile(sourceAuthCandidate, {
179
+ requirePrivateMode: true,
180
+ requireSingleLink: true,
181
+ errorPrefix: 'native_codex_auth_source'
182
+ });
183
+ const currentAuth = parseStrictChatGptAuth(currentText);
184
+ const sameAccount = String(currentAuth.tokens?.account_id || '') === String(tempAuth.tokens?.account_id || '');
185
+ const hostRefreshedAt = Date.parse(String(currentAuth.last_refresh || ''));
186
+ const oursRefreshedAt = Date.parse(String(tempAuth.last_refresh || ''));
187
+ const hostWins = !sameAccount
188
+ || !Number.isFinite(oursRefreshedAt)
189
+ || (Number.isFinite(hostRefreshedAt) && hostRefreshedAt >= oursRefreshedAt);
190
+ if (hostWins) {
191
+ await removeOwnedTempRoot();
192
+ const result = { ok: true, status: 'cleaned', outcome: 'host_newer_kept', cleanup_required: false, blockers: [] };
193
+ applyCleanupProof(bridgeProof, result);
194
+ return result;
195
+ }
196
+ const currentStat = await fsp.lstat(sourceAuthCandidate);
197
+ const retryIdentity = { dev: currentStat.dev, ino: currentStat.ino };
198
+ const retryFingerprint = fingerprintText(currentText);
199
+ const mergedAuth = { ...currentAuth, tokens: tempAuth.tokens, last_refresh: tempAuth.last_refresh };
200
+ await writeAuthFileAtomic(sourceAuthCandidate, `${JSON.stringify(mergedAuth, null, 2)}\n`, async () => {
201
+ await assertSourceAuthUnchanged(sourceAuthCandidate, retryIdentity, retryFingerprint);
202
+ });
203
+ await removeOwnedTempRoot();
204
+ const result = { ok: true, status: 'cleaned', outcome: 'refreshed_persisted_after_conflict', cleanup_required: false, blockers: [] };
205
+ applyCleanupProof(bridgeProof, result);
206
+ return result;
207
+ }
173
208
  }
174
209
  catch (error) {
175
210
  const reason = String(error?.message || error || 'native_codex_auth_cleanup_failed');
@@ -1,2 +1,3 @@
1
1
  export const MANAGED_ROUTING_RUNTIME = 'desktop-bridge';
2
2
  export const BRIDGE_PROVIDER_IDS = ['codex-lb', 'openrouter'];
3
+ export const BRIDGE_OFFICIAL_ROUTE_ID = 'openai';
@@ -54,6 +54,44 @@ export function buildProviderUpstreamHeaders(inbound, context, upstreamHost) {
54
54
  injectCredential(result, context.providerId, context.authTransport, context.credential);
55
55
  return result;
56
56
  }
57
+ const OFFICIAL_PASSTHROUGH_STRIP = new Set([
58
+ 'forwarded', 'proxy-authorization', 'x-api-key', 'x-codex-lb-api-key',
59
+ 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-port', 'x-forwarded-proto', 'x-real-ip',
60
+ 'host',
61
+ ]);
62
+ export function buildOfficialPassthroughHeaders(inbound, upstreamHost) {
63
+ const result = {};
64
+ const dynamic = connectionTokens(inbound);
65
+ for (const [rawName, rawValue] of Object.entries(inbound)) {
66
+ if (rawValue === undefined)
67
+ continue;
68
+ const name = rawName.toLowerCase();
69
+ if (HOP_BY_HOP.has(name) || dynamic.has(name))
70
+ continue;
71
+ if (name.startsWith(INTERNAL_PREFIX))
72
+ continue;
73
+ if (OFFICIAL_PASSTHROUGH_STRIP.has(name))
74
+ continue;
75
+ result[name] = rawValue;
76
+ }
77
+ result.host = upstreamHost;
78
+ if (result['x-codex-lb-api-key'] !== undefined)
79
+ throw new DesktopBridgeError('bridge_provider_credential_invalid');
80
+ return result;
81
+ }
82
+ export function buildOfficialPassthroughWebSocketHeaders(inbound, upstreamHost) {
83
+ const result = buildOfficialPassthroughHeaders(inbound, upstreamHost);
84
+ for (const [rawName, rawValue] of Object.entries(inbound)) {
85
+ if (rawValue === undefined)
86
+ continue;
87
+ const name = rawName.toLowerCase();
88
+ if (WEBSOCKET_HEADER_ALLOWLIST.has(name))
89
+ result[name] = rawValue;
90
+ }
91
+ result.connection = 'Upgrade';
92
+ result.upgrade = 'websocket';
93
+ return result;
94
+ }
57
95
  export function buildProviderWebSocketHeaders(inbound, context, upstreamHost) {
58
96
  const result = buildProviderUpstreamHeaders(inbound, context, upstreamHost);
59
97
  for (const [rawName, rawValue] of Object.entries(inbound)) {
@@ -2,7 +2,8 @@ import http, {} from 'node:http';
2
2
  import https from 'node:https';
3
3
  import zlib from 'node:zlib';
4
4
  import { pipeline } from 'node:stream/promises';
5
- import { buildProviderUpstreamHeaders, rewriteResponseHeaders } from './header-policy.js';
5
+ import { BRIDGE_OFFICIAL_ROUTE_ID } from '../bridge-contracts.js';
6
+ import { buildOfficialPassthroughHeaders, buildProviderUpstreamHeaders, rewriteResponseHeaders } from './header-policy.js';
6
7
  import { createDesktopBridgeRejectionLogger } from './rejection-log.js';
7
8
  import { resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode, singleBridgeHeader } from './security.js';
8
9
  import { desktopBridgeListenOrigin } from './state.js';
@@ -60,6 +61,8 @@ async function readBoundedBody(req, maximum) {
60
61
  return Buffer.concat(chunks);
61
62
  }
62
63
  async function resolveCredential(config, route) {
64
+ if (route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID)
65
+ throw new DesktopBridgeError('bridge_provider_route_unavailable');
63
66
  const provider = config.providers[route.provider_id];
64
67
  if (!provider)
65
68
  throw new DesktopBridgeError('bridge_provider_route_unavailable');
@@ -107,7 +110,7 @@ export async function prepareDesktopBridgeRequest(req, config) {
107
110
  payload.model = route.upstream_model;
108
111
  body = Buffer.from(JSON.stringify(payload));
109
112
  }
110
- const credential = await resolveCredential(config, route);
113
+ const credential = route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID ? null : await resolveCredential(config, route);
111
114
  return { body, route, credential, contentEncodingStripped };
112
115
  }
113
116
  function connectTimeout(request, config) {
@@ -251,21 +254,30 @@ class StalePooledSocketFailure extends Error {
251
254
  export async function forwardHttp(req, res, config, prepared, authenticatedLocalBaseUrl = desktopBridgeListenOrigin(config)) {
252
255
  try {
253
256
  const request = prepared || await prepareDesktopBridgeRequest(req, config);
254
- const provider = config.providers[request.route.provider_id];
255
- if (!provider)
257
+ const official = request.route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID;
258
+ const provider = official ? null : config.providers[request.route.provider_id];
259
+ if (!official && !provider)
256
260
  throw new DesktopBridgeError('bridge_provider_route_unavailable');
257
- const target = resolveDesktopBridgeTarget(req.url, provider.remote);
258
- const transport = provider.remote.secure ? https : http;
259
- const headers = buildProviderUpstreamHeaders(req.headers, {
260
- providerId: provider.provider_id, authTransport: provider.auth_transport, credential: request.credential,
261
- }, target.host);
261
+ const remote = official ? config.officialRemote : provider?.remote;
262
+ if (!remote)
263
+ throw new DesktopBridgeError('bridge_official_passthrough_unavailable');
264
+ const upstreamBaseUrl = official ? remote.baseUrl : provider.base_url;
265
+ if (!official && !request.credential)
266
+ throw new DesktopBridgeError('bridge_provider_credential_invalid');
267
+ const target = resolveDesktopBridgeTarget(req.url, remote);
268
+ const transport = remote.secure ? https : http;
269
+ const headers = official
270
+ ? buildOfficialPassthroughHeaders(req.headers, target.host)
271
+ : buildProviderUpstreamHeaders(req.headers, {
272
+ providerId: provider.provider_id, authTransport: provider.auth_transport, credential: request.credential,
273
+ }, target.host);
262
274
  if (request.body)
263
275
  headers['content-length'] = String(request.body.length);
264
276
  else
265
277
  delete headers['content-length'];
266
278
  if (request.contentEncodingStripped)
267
279
  delete headers['content-encoding'];
268
- const agent = upstreamAgent(provider.remote.secure, `${provider.remote.address}:${provider.remote.port}`, config.idleTimeoutMs);
280
+ const agent = upstreamAgent(remote.secure, `${remote.address}:${remote.port}`, config.idleTimeoutMs);
269
281
  const replayable = Buffer.isBuffer(request.body);
270
282
  const attempt = (useFreshConnection, canReplay) => new Promise((resolve, reject) => {
271
283
  let responseStarted = false;
@@ -281,10 +293,10 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
281
293
  error ? reject(error) : resolve();
282
294
  };
283
295
  const upstream = transport.request({
284
- protocol: target.protocol, hostname: provider.remote.address, family: provider.remote.family,
285
- port: provider.remote.port, method: req.method, path: `${target.pathname}${target.search}`, headers,
296
+ protocol: target.protocol, hostname: remote.address, family: remote.family,
297
+ port: remote.port, method: req.method, path: `${target.pathname}${target.search}`, headers,
286
298
  agent: useFreshConnection ? false : agent,
287
- ...(provider.remote.tlsServername ? { servername: provider.remote.tlsServername } : {}),
299
+ ...(remote.tlsServername ? { servername: remote.tlsServername } : {}),
288
300
  });
289
301
  connectTimeout(upstream, config);
290
302
  upstream.setTimeout(config.idleTimeoutMs, () => upstream.destroy(new DesktopBridgeError('bridge_upstream_idle_timeout')));
@@ -299,6 +311,36 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
299
311
  });
300
312
  upstream.once('response', (response) => {
301
313
  const statusCode = response.statusCode || 502;
314
+ if (official) {
315
+ if (statusCode >= 400 && TRANSIENT_UPSTREAM_STATUSES.has(statusCode) && replayable && canReplay) {
316
+ response.resume();
317
+ responseStarted = true;
318
+ finish(new StalePooledSocketFailure(new DesktopBridgeError('bridge_upstream_transient_mislabel')));
319
+ return;
320
+ }
321
+ if (statusCode >= 400) {
322
+ logHttpRejection({
323
+ code: `bridge_upstream_status_${statusCode}`,
324
+ transport: 'http',
325
+ ...(req.method === undefined ? {} : { method: req.method }),
326
+ ...(req.url === undefined ? {} : { url: req.url }),
327
+ status: statusCode,
328
+ provider_id: BRIDGE_OFFICIAL_ROUTE_ID,
329
+ public_model: request.route.public_model,
330
+ });
331
+ }
332
+ responseStarted = true;
333
+ try {
334
+ res.writeHead(statusCode, rewriteResponseHeaders(response.headers, upstreamBaseUrl, authenticatedLocalBaseUrl));
335
+ }
336
+ catch (error) {
337
+ response.destroy(error instanceof Error ? error : undefined);
338
+ finish(error);
339
+ return;
340
+ }
341
+ void pipeline(response, res).then(() => finish(), finish);
342
+ return;
343
+ }
302
344
  if (statusCode >= 400) {
303
345
  void readRedactedUpstreamError(response).then(({ upstreamCode, upstreamType }) => {
304
346
  const transientMislabel = isTransientUpstreamFailure(statusCode, upstreamType, upstreamCode);
@@ -323,7 +365,7 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
323
365
  public_model: request.route.public_model,
324
366
  });
325
367
  responseStarted = true;
326
- const responseHeaders = rewriteResponseHeaders(response.headers, provider.base_url, authenticatedLocalBaseUrl);
368
+ const responseHeaders = rewriteResponseHeaders(response.headers, upstreamBaseUrl, authenticatedLocalBaseUrl);
327
369
  responseHeaders['content-length'] = String(body.length);
328
370
  delete responseHeaders['transfer-encoding'];
329
371
  if (transientMislabel)
@@ -337,7 +379,7 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
337
379
  }
338
380
  responseStarted = true;
339
381
  try {
340
- res.writeHead(statusCode, rewriteResponseHeaders(response.headers, provider.base_url, authenticatedLocalBaseUrl));
382
+ res.writeHead(statusCode, rewriteResponseHeaders(response.headers, upstreamBaseUrl, authenticatedLocalBaseUrl));
341
383
  }
342
384
  catch (error) {
343
385
  response.destroy(error instanceof Error ? error : undefined);
@@ -365,7 +407,7 @@ export async function forwardHttp(req, res, config, prepared, authenticatedLocal
365
407
  remainingReplays -= 1;
366
408
  if (!useFreshConnection) {
367
409
  agent.destroy();
368
- upstreamAgents.delete(`${provider.remote.secure ? 'https' : 'http'}:${provider.remote.address}:${provider.remote.port}`);
410
+ upstreamAgents.delete(`${remote.secure ? 'https' : 'http'}:${remote.address}:${remote.port}`);
369
411
  }
370
412
  logHttpRejection({
371
413
  code: `bridge_upstream_socket_stale_replayed:${underlyingErrorCode(error.reason) || 'unknown'}`,
@@ -33,6 +33,7 @@ export function createDesktopBridgeRejectionLogger(options = {}) {
33
33
  write(`${JSON.stringify({
34
34
  schema: DESKTOP_BRIDGE_LOG_SCHEMA,
35
35
  sks_version: PACKAGE_VERSION,
36
+ at: new Date(now()).toISOString(),
36
37
  secret_fields_redacted: true,
37
38
  ...payload,
38
39
  })}\n`);
@@ -1,5 +1,6 @@
1
1
  import dns from 'node:dns/promises';
2
2
  import net from 'node:net';
3
+ import { BRIDGE_OFFICIAL_ROUTE_ID } from '../bridge-contracts.js';
3
4
  import { canonicalizeBridgeModelId, normalizeBridgeUpstreamModelId, } from '../route-index.js';
4
5
  import { DESKTOP_BRIDGE_CLIENT_PATH_PREFIX, DesktopBridgeError } from './types.js';
5
6
  const MIN_HIGH_PORT = 49_152;
@@ -150,6 +151,19 @@ function canonicalPublicModel(value) {
150
151
  throw new DesktopBridgeError('catalog_model_route_missing');
151
152
  return model;
152
153
  }
154
+ export function desktopBridgeOfficialPassthroughEnabled(config) {
155
+ return Boolean(config.officialPassthrough?.baseUrl);
156
+ }
157
+ function officialRouteContext(publicModel, policy, upstreamModel) {
158
+ return {
159
+ provider_id: BRIDGE_OFFICIAL_ROUTE_ID,
160
+ public_model: publicModel,
161
+ upstream_model: upstreamModel || publicModel,
162
+ catalog_generation: policy.catalog_generation,
163
+ route_policy_generation: policy.policy_generation,
164
+ session_pin: null,
165
+ };
166
+ }
153
167
  export function resolveBridgeRequestRoute(request, policy, pins) {
154
168
  const publicModel = canonicalPublicModel(request.public_model);
155
169
  const sessionId = request.session_id ? canonicalSessionId(request.session_id) : null;
@@ -179,6 +193,8 @@ export function resolveBridgeRequestRoute(request, policy, pins) {
179
193
  const route = policy.model_routes[publicModel];
180
194
  if (!route)
181
195
  throw new DesktopBridgeError('catalog_model_route_missing');
196
+ if (route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID)
197
+ return officialRouteContext(publicModel, policy, route.upstream_model);
182
198
  const nextPin = sessionId ? {
183
199
  thread_id: sessionId,
184
200
  provider_id: route.provider_id,
@@ -199,8 +215,36 @@ export function resolveBridgeRequestRoute(request, policy, pins) {
199
215
  }
200
216
  export function assertDesktopBridgeRouteContext(request, config) {
201
217
  const resolver = config.resolveRequestRoute || resolveBridgeRequestRoute;
202
- const route = resolver(request, config.routePolicy, config.providerSessionPins);
203
218
  const policy = config.routePolicy;
219
+ let route;
220
+ try {
221
+ route = resolver(request, policy, config.providerSessionPins);
222
+ }
223
+ catch (error) {
224
+ if (desktopBridgeOfficialPassthroughEnabled(config)
225
+ && error instanceof DesktopBridgeError
226
+ && (error.code === 'catalog_model_route_missing' || error.code === 'session_pin_route_unavailable')) {
227
+ const model = canonicalizeBridgeModelId(request.public_model) || '';
228
+ const live = model ? policy.model_routes[model] : undefined;
229
+ if (!live || live.provider_id === BRIDGE_OFFICIAL_ROUTE_ID) {
230
+ route = officialRouteContext(model, policy, live?.upstream_model);
231
+ }
232
+ else
233
+ throw error;
234
+ }
235
+ else
236
+ throw error;
237
+ }
238
+ if (route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID) {
239
+ if (!desktopBridgeOfficialPassthroughEnabled(config))
240
+ throw new DesktopBridgeError('bridge_official_passthrough_unavailable');
241
+ if (route.catalog_generation !== policy.catalog_generation || route.route_policy_generation !== policy.policy_generation) {
242
+ throw new DesktopBridgeError('session_pin_route_unavailable');
243
+ }
244
+ if (route.session_pin)
245
+ throw new DesktopBridgeError('bridge_session_pin_invalid');
246
+ return route;
247
+ }
204
248
  const expected = policy.model_routes[route.public_model];
205
249
  if (!expected || expected.provider_id !== route.provider_id || expected.upstream_model !== route.upstream_model) {
206
250
  throw new DesktopBridgeError('catalog_model_route_missing');
@@ -399,9 +443,12 @@ function assertRegistryAndPolicy(config, registry) {
399
443
  if (policy.schema !== 'sks.bridge-routing-policy.v1' || policy.fallback !== 'none' || !policy.catalog_generation || !policy.policy_generation) {
400
444
  throw new DesktopBridgeError('bridge_route_policy_invalid');
401
445
  }
446
+ const officialConfigured = desktopBridgeOfficialPassthroughEnabled(config);
402
447
  for (const [model, route] of Object.entries(policy.model_routes)) {
448
+ const routeTargetAllowed = ids.includes(route.provider_id)
449
+ || (route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID && officialConfigured);
403
450
  if (canonicalizeBridgeModelId(model) !== model
404
- || !ids.includes(route.provider_id)
451
+ || !routeTargetAllowed
405
452
  || normalizeBridgeUpstreamModelId(route.upstream_model) !== route.upstream_model) {
406
453
  throw new DesktopBridgeError('bridge_route_policy_invalid');
407
454
  }
@@ -460,6 +507,8 @@ export function validateDesktopBridgeConfig(config) {
460
507
  throw new DesktopBridgeError('bridge_client_capability_invalid');
461
508
  if (typeof config.resolveProviderCredential !== 'function')
462
509
  throw new DesktopBridgeError('bridge_provider_credential_resolver_missing');
510
+ if (config.officialPassthrough)
511
+ validateRemoteUrl(config.officialPassthrough.baseUrl);
463
512
  assertRegistryAndPolicy(config, config.providerRegistry);
464
513
  if (!Object.values(config.providerRegistry.providers).some((provider) => provider.enabled)) {
465
514
  throw new DesktopBridgeError('bridge_provider_registry_no_enabled_provider');
@@ -475,7 +524,10 @@ export async function prepareDesktopBridgeConfig(config, lookup = defaultLookup)
475
524
  return [id, prepared];
476
525
  }));
477
526
  const providers = Object.fromEntries(entries);
478
- return { ...config, providers };
527
+ const officialRemote = config.officialPassthrough
528
+ ? await resolveDesktopBridgeRemoteTarget(config.officialPassthrough.baseUrl, lookup)
529
+ : null;
530
+ return { ...config, providers, officialRemote };
479
531
  }
480
532
  export function validatePreparedDesktopBridgeConfig(config) {
481
533
  validateDesktopBridgeConfig(config);
@@ -12,6 +12,7 @@ export const DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES = [
12
12
  '/api/v1/',
13
13
  '/v1/',
14
14
  ];
15
+ export const DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL = 'https://chatgpt.com/backend-api/codex';
15
16
  export class DesktopBridgeError extends Error {
16
17
  code;
17
18
  constructor(code, options) {
@@ -1,10 +1,11 @@
1
1
  import { createHash, randomBytes } from 'node:crypto';
2
2
  import net from 'node:net';
3
3
  import tls from 'node:tls';
4
- import { buildProviderWebSocketHeaders } from './header-policy.js';
4
+ import { BRIDGE_OFFICIAL_ROUTE_ID } from '../bridge-contracts.js';
5
+ import { buildOfficialPassthroughWebSocketHeaders, buildProviderWebSocketHeaders } from './header-policy.js';
5
6
  import { createDesktopBridgeRejectionLogger } from './rejection-log.js';
6
7
  import { rewriteLocationHeader } from './location-rewrite.js';
7
- import { resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode, singleBridgeHeader, canonicalSessionId } from './security.js';
8
+ import { desktopBridgeOfficialPassthroughEnabled, resolveAndBindDesktopBridgeRouteContext, resolveCodexSessionIdentity, resolveDesktopBridgeTarget, safeBridgeErrorCode, singleBridgeHeader, canonicalSessionId } from './security.js';
8
9
  import { desktopBridgeListenOrigin } from './state.js';
9
10
  import { DESKTOP_BRIDGE_DIAGNOSTIC_PROTOCOL, DesktopBridgeError, } from './types.js';
10
11
  const MAX_HEAD = 64 * 1024;
@@ -82,7 +83,7 @@ export async function prepareDesktopBridgeWebSocketRequest(req, config) {
82
83
  const sessionIdentity = resolveCodexSessionIdentity(req.headers);
83
84
  const pinnedModel = websocketPinnedModel(sessionIdentity.thread_id, config);
84
85
  const publicModel = singleBridgeHeader(req.headers, 'x-sks-model') || pinnedModel || '';
85
- if (!publicModel) {
86
+ if (!publicModel && !(desktopBridgeOfficialPassthroughEnabled(config) && config.officialRemote)) {
86
87
  throw new DesktopBridgeError('bridge_websocket_route_unresolvable');
87
88
  }
88
89
  const route = await resolveAndBindDesktopBridgeRouteContext({
@@ -91,6 +92,8 @@ export async function prepareDesktopBridgeWebSocketRequest(req, config) {
91
92
  pathname: new URL(req.url || '/', 'http://bridge.invalid').pathname,
92
93
  transport: 'websocket', headers: req.headers,
93
94
  }, config);
95
+ if (route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID)
96
+ return { route, provider: null, credential: null };
94
97
  const provider = config.providers[route.provider_id];
95
98
  if (!provider)
96
99
  throw new DesktopBridgeError('bridge_provider_route_unavailable');
@@ -142,11 +145,18 @@ export async function forwardWebSocket(req, client, head, config, authenticatedL
142
145
  writeUpgradeFailure(client, error, req);
143
146
  return;
144
147
  }
145
- const { provider, credential } = prepared;
146
- const target = resolveDesktopBridgeTarget(req.url, provider.remote);
147
- const upstream = provider.remote.secure
148
- ? tls.connect({ host: provider.remote.address, port: provider.remote.port, ...(provider.remote.tlsServername ? { servername: provider.remote.tlsServername } : {}) })
149
- : net.connect({ host: provider.remote.address, port: provider.remote.port, family: provider.remote.family });
148
+ const { provider, credential, route } = prepared;
149
+ const official = route.provider_id === BRIDGE_OFFICIAL_ROUTE_ID;
150
+ const remote = official ? config.officialRemote : provider?.remote;
151
+ if (!remote) {
152
+ writeUpgradeFailure(client, new DesktopBridgeError(official ? 'bridge_official_passthrough_unavailable' : 'bridge_provider_route_unavailable'), req);
153
+ return;
154
+ }
155
+ const upstreamBaseUrl = official ? remote.baseUrl : provider.base_url;
156
+ const target = resolveDesktopBridgeTarget(req.url, remote);
157
+ const upstream = remote.secure
158
+ ? tls.connect({ host: remote.address, port: remote.port, ...(remote.tlsServername ? { servername: remote.tlsServername } : {}) })
159
+ : net.connect({ host: remote.address, port: remote.port, family: remote.family });
150
160
  const key = String(req.headers['sec-websocket-key'] || '');
151
161
  const requestedProtocol = String(req.headers['sec-websocket-protocol'] || '').split(',')[0]?.trim() || null;
152
162
  let connected = false;
@@ -165,7 +175,9 @@ export async function forwardWebSocket(req, client, head, config, authenticatedL
165
175
  const clientSocket = client;
166
176
  if (typeof clientSocket.setKeepAlive === 'function')
167
177
  clientSocket.setKeepAlive(true, 30_000);
168
- const headers = buildProviderWebSocketHeaders(req.headers, { providerId: provider.provider_id, authTransport: provider.auth_transport, credential }, target.host);
178
+ const headers = official
179
+ ? buildOfficialPassthroughWebSocketHeaders(req.headers, target.host)
180
+ : buildProviderWebSocketHeaders(req.headers, { providerId: provider.provider_id, authTransport: provider.auth_transport, credential: credential }, target.host);
169
181
  upstream.write([`${req.method || 'GET'} ${target.pathname}${target.search} HTTP/1.1`, ...serializeHeaders(headers), '', ''].join('\r\n'));
170
182
  if (head.length)
171
183
  upstream.write(head);
@@ -183,7 +195,7 @@ export async function forwardWebSocket(req, client, head, config, authenticatedL
183
195
  const remaining = response.subarray(boundary + 4);
184
196
  try {
185
197
  validateUpgrade(raw, key, requestedProtocol);
186
- client.write(rewriteUpgradeResponseHead(raw, provider.base_url, authenticatedLocalBaseUrl));
198
+ client.write(rewriteUpgradeResponseHead(raw, upstreamBaseUrl, authenticatedLocalBaseUrl));
187
199
  if (remaining.length)
188
200
  client.write(remaining);
189
201
  }
@@ -196,7 +208,7 @@ export async function forwardWebSocket(req, client, head, config, authenticatedL
196
208
  };
197
209
  upstream.on('data', onData);
198
210
  };
199
- if (provider.remote.secure)
211
+ if (remote.secure)
200
212
  upstream.once('secureConnect', onConnected);
201
213
  else
202
214
  upstream.once('connect', onConnected);
@@ -1,8 +1,6 @@
1
1
  export function authSemanticIdentityPreserved(before, after) {
2
2
  if (before.path !== after.path || before.exists !== after.exists)
3
3
  return false;
4
- if (before.sha256 !== after.sha256)
5
- return false;
6
4
  const beforeIsOAuth = before.mode === 'chatgpt_oauth' || before.mode === 'mixed';
7
5
  const afterIsOAuth = after.mode === 'chatgpt_oauth' || after.mode === 'mixed';
8
6
  if (beforeIsOAuth || afterIsOAuth) {
@@ -11,7 +9,7 @@ export function authSemanticIdentityPreserved(before, after) {
11
9
  && before.semantic_fingerprint !== null
12
10
  && before.semantic_fingerprint === after.semantic_fingerprint;
13
11
  }
14
- return true;
12
+ return before.sha256 === after.sha256;
15
13
  }
16
14
  export function buildDesktopBridgeMigrationReceipt(input) {
17
15
  const common = {
@@ -17,7 +17,7 @@ const SETTINGS_V1_KEYS = new Set([
17
17
  const SETTINGS_V2_KEYS = new Set([
18
18
  'schema', 'listen_host', 'listen_port', 'provider_registry', 'route_policy',
19
19
  'provider_session_pins', 'client_capability_sha256', 'allowed_origins',
20
- 'connect_timeout_ms', 'idle_timeout_ms',
20
+ 'connect_timeout_ms', 'idle_timeout_ms', 'official_passthrough',
21
21
  ]);
22
22
  const TRANSFERABLE_V1_KEYS = [
23
23
  'listen_host', 'listen_port', 'allowed_origins', 'connect_timeout_ms', 'idle_timeout_ms',
@@ -90,8 +90,7 @@ async function migrateDesktopBridgeConfigUnlocked(input) {
90
90
  const authPreserved = authSemanticIdentityPreserved(authBefore, authAfter);
91
91
  const configSha = sha256(currentConfig);
92
92
  const configUnchanged = await fileSha256OrMissing(configPath) === configSha;
93
- const authBytesUnchanged = authBefore.sha256 === authAfter.sha256;
94
- if (!authPreserved || !configUnchanged || !authBytesUnchanged) {
93
+ if (!authPreserved || !configUnchanged) {
95
94
  return {
96
95
  ...baseResult,
97
96
  ok: false,
@@ -101,8 +100,7 @@ async function migrateDesktopBridgeConfigUnlocked(input) {
101
100
  auth_semantic_identity_preserved: authPreserved,
102
101
  blockers: [
103
102
  ...(!configUnchanged ? ['desktop_bridge_config_changed_during_noop'] : []),
104
- ...(!authPreserved ? ['desktop_oauth_identity_changed'] : []),
105
- ...(authPreserved && !authBytesUnchanged ? ['desktop_auth_changed_during_noop'] : [])
103
+ ...(!authPreserved ? ['desktop_oauth_identity_changed'] : [])
106
104
  ]
107
105
  };
108
106
  }
@@ -5,12 +5,12 @@ import { listOpenRouterModels } from '../../providers/openrouter/openrouter-acco
5
5
  import { buildCombinedBridgeCatalog, readActiveCombinedBridgeCatalog, stageCombinedBridgeCatalog } from '../combined-catalog.js';
6
6
  import { COMBINED_BRIDGE_CATALOG_TTL_MS } from '../combined-catalog/contracts.js';
7
7
  import { codexLbEnvPath, codexLbMetadataPath, loadCodexLbEnv, readCodexLbModelCatalog } from '../codex-lb-env.js';
8
- import { bootstrapExistingDesktopBridgeService, desktopBridgeServicePaths, desktopBridgeServiceStatus, resolveDesktopBridgeActivationSettings } from '../desktop-service.js';
8
+ import { bootstrapExistingDesktopBridgeService, desktopBridgeServicePaths, desktopBridgeServiceStatus, readDesktopBridgeServiceSettings, resolveDesktopBridgeActivationSettings, resolveEffectiveOfficialModelsMode } from '../desktop-service.js';
9
9
  import { inspectHistoricalDesktopBridgeIntent, migrateDesktopBridgeConfig } from '../desktop-bridge-migration.js';
10
10
  import { rollbackDesktopBridgeUnificationReceipt } from '../migration-receipt.js';
11
11
  import { recordProviderCredentialValidation } from '../provider-credentials.js';
12
12
  import { bridgeProviderRegistryPath, buildStoredBridgeProviderRegistry, loadStoredBridgeProviderRegistry, resolveBridgeProviderRegistry, serializeStoredBridgeProviderRegistry } from '../provider-registry.js';
13
- import { buildBridgeRoutingPolicy, readBridgeRoutingPolicy } from '../provider-route-policy.js';
13
+ import { applyOfficialModelPassthrough, buildBridgeRoutingPolicy, readBridgeRoutingPolicy } from '../provider-route-policy.js';
14
14
  import { sha256Stable } from '../route-index.js';
15
15
  import { bridgeBaseUrl, commandResult, controllerEnv, controllerPaths, nowIso, providerCode, providerRegistrySnapshot, resolveRawCredentials, resolveValidatedCredentials, safeCode, serializedSettings, stringArray, timeoutMs, unique } from './shared.js';
16
16
  import { desktopBridgeStatusV3 } from './status.js';
@@ -76,12 +76,14 @@ export async function syncCatalogInternal(options) {
76
76
  ? previousDefault
77
77
  : historicalDefault && readyProviders.includes(historicalDefault) ? historicalDefault
78
78
  : readyProviders.length === 1 ? readyProviders[0] || null : null;
79
- const policy = buildBridgeRoutingPolicy({
79
+ const persistedSettings = await readDesktopBridgeServiceSettings(desktopBridgeServicePaths(paths.home).settings_path).catch(() => null);
80
+ const officialModelsMode = await resolveEffectiveOfficialModelsMode(persistedSettings?.official_passthrough, { home: paths.home, authPath: paths.authPath });
81
+ const policy = applyOfficialModelPassthrough(buildBridgeRoutingPolicy({
80
82
  route_index: build.route_index,
81
83
  catalog_generation: build.catalog.generation,
82
84
  default_provider_id: defaultProvider,
83
85
  changed_at: nowIso(options)
84
- });
86
+ }), { mode: officialModelsMode, changedAt: nowIso(options) });
85
87
  let settings;
86
88
  let managedBridgeBaseUrl;
87
89
  try {
@@ -2,10 +2,11 @@ import path from 'node:path';
2
2
  import { removeDesktopBridgeManagedConfig } from '../../../cli/install-helpers-codex-lb-config.js';
3
3
  import { safeWriteCodexConfigToml } from '../../codex-runtime/codex-desktop-config-policy.js';
4
4
  import { exists, readText } from '../../fsx.js';
5
- import { bootstrapExistingDesktopBridgeService, desktopBridgeServiceStatus, installAndStartDesktopBridgeService, stopDesktopBridgeService } from '../desktop-service.js';
5
+ import { bootstrapExistingDesktopBridgeService, desktopBridgeServicePaths, desktopBridgeServiceStatus, installAndStartDesktopBridgeService, readDesktopBridgeServiceSettings, resolveEffectiveOfficialModelsMode, stopDesktopBridgeService } from '../desktop-service.js';
6
6
  import { rollbackDesktopBridgeUnificationReceipt } from '../migration-receipt.js';
7
+ import { DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL } from '../desktop-bridge/index.js';
7
8
  import { resolveBridgeRequestRoute } from '../request-route-resolver.js';
8
- import { setBridgeRoutingDefault, writeBridgeRoutingPolicy } from '../provider-route-policy.js';
9
+ import { applyOfficialModelPassthrough, buildBridgeRoutingPolicy, setBridgeRoutingDefault, writeBridgeRoutingPolicy } from '../provider-route-policy.js';
9
10
  import { syncCatalogInternal } from './catalog.js';
10
11
  import { commandResult, controllerPaths, nowIso, persistRuntimeSettings, providerCode, providerRegistrySnapshot, stringArray } from './shared.js';
11
12
  import { desktopBridgeStatusV3, loadCore, statusFromCore } from './status.js';
@@ -70,6 +71,39 @@ export async function setDefaultProvider(providerId, options) {
70
71
  const status = await desktopBridgeStatusV3(options);
71
72
  return commandResult('route.set-default', true, status, { provider_id: providerId, policy_generation: policy.policy_generation }, [], options);
72
73
  }
74
+ export async function setOfficialModelsMode(mode, options) {
75
+ const core = await loadCore(options);
76
+ if (!core.policy || !core.activeCatalog.ok)
77
+ throw new Error('bridge_route_policy_missing');
78
+ const settingsPath = options.settingsPath || desktopBridgeServicePaths(core.paths.home).settings_path;
79
+ const persisted = await readDesktopBridgeServiceSettings(settingsPath).catch(() => null);
80
+ const nextOfficial = {
81
+ enabled: persisted?.official_passthrough?.enabled ?? true,
82
+ base_url: persisted?.official_passthrough?.base_url || DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL,
83
+ models: mode,
84
+ };
85
+ const effective = mode === 'auto'
86
+ ? await resolveEffectiveOfficialModelsMode(nextOfficial, { home: core.paths.home })
87
+ : mode;
88
+ const policy = effective === 'passthrough'
89
+ ? applyOfficialModelPassthrough(core.policy, { mode: 'passthrough', changedAt: nowIso(options) })
90
+ : buildBridgeRoutingPolicy({
91
+ route_index: core.activeCatalog.route_index,
92
+ catalog_generation: core.policy.catalog_generation,
93
+ default_provider_id: core.policy.default_provider_id,
94
+ changed_at: nowIso(options)
95
+ });
96
+ await writeBridgeRoutingPolicy(core.paths.routePolicyPath, policy, core.activeCatalog.route_index);
97
+ await persistRuntimeSettings({ ...core, policy, policyBlockers: [] }, {
98
+ ...options,
99
+ settings: { ...(options.settings || {}), official_passthrough: nextOfficial },
100
+ });
101
+ const status = await desktopBridgeStatusV3(options);
102
+ const officialModels = Object.entries(policy.model_routes)
103
+ .filter(([, route]) => route.provider_id === 'openai')
104
+ .map(([model]) => model);
105
+ return commandResult('route.official-models', true, status, { mode, effective_mode: effective, official_models: officialModels, policy_generation: policy.policy_generation }, [], options);
106
+ }
73
107
  export async function explainRoute(model, options) {
74
108
  const core = await loadCore(options);
75
109
  if (!core.policy || !core.activeCatalog.ok)
@@ -1,5 +1,5 @@
1
1
  import { listSelectableModels, selectExposedModels, syncCatalog } from './desktop-controller-v3/catalog.js';
2
- import { explainRoute, ensureDesktopBridge, repairDesktopBridge, rollbackDesktopBridge, setDefaultProvider, unmanageDesktopBridge } from './desktop-controller-v3/lifecycle-commands.js';
2
+ import { explainRoute, ensureDesktopBridge, repairDesktopBridge, rollbackDesktopBridge, setDefaultProvider, setOfficialModelsMode, unmanageDesktopBridge } from './desktop-controller-v3/lifecycle-commands.js';
3
3
  import { configureProvider, removeCredential, setProviderState, validateProvider } from './desktop-controller-v3/provider-commands.js';
4
4
  import { commandResult, safeCode } from './desktop-controller-v3/shared.js';
5
5
  import { desktopBridgeStatusV3 } from './desktop-controller-v3/status.js';
@@ -56,6 +56,8 @@ export async function executeDesktopBridgeCommandV3(request, options = {}) {
56
56
  }
57
57
  if (request.operation === 'route.set-default')
58
58
  return setDefaultProvider(request.provider_id, options);
59
+ if (request.operation === 'route.official-models')
60
+ return setOfficialModelsMode(request.mode, options);
59
61
  if (request.operation === 'route.explain')
60
62
  return explainRoute(request.model, options);
61
63
  if (request.operation === 'unmanage')
@@ -9,9 +9,11 @@ import { loadCodexLbEnv } from './codex-lb-env.js';
9
9
  import { resolveOpenRouterApiKey } from '../providers/openrouter/openrouter-secret-store.js';
10
10
  import { cleanupRetiredDesktopBridgeRuntime, prepareRetiredDesktopBridgeRuntime, } from './desktop-bridge-migration/retired-runtime-cleanup.js';
11
11
  import { canonicalizeBridgeModelId, normalizeBridgeUpstreamModelId, sha256Stable } from './route-index.js';
12
+ import { captureCodexAuthSnapshot } from './desktop-auth-invariant.js';
13
+ import { applyOfficialModelPassthrough, bridgeRoutePolicyPath, writeBridgeRoutingPolicy } from './provider-route-policy.js';
12
14
  import { desktopBridgeRuntimeVersion, desktopBridgeRuntimeVersionStale } from './desktop-bridge/state.js';
13
15
  import { PACKAGE_VERSION } from '../version.js';
14
- import { DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, DESKTOP_BRIDGE_LAUNCHD_LABEL, desktopBridgeConfigGeneration, desktopBridgeLaunchdPlistPath, desktopBridgeProcessExists, desktopBridgeStatePath, getDesktopBridgeStatus, preflightDesktopBridge, readDesktopBridgeState, safeBridgeErrorCode, writeDesktopBridgeLaunchdPlist, selectAvailableDesktopBridgePort, startPreparedDesktopBridge, DESKTOP_BRIDGE_STATE_SCHEMA, DesktopBridgeError, } from './desktop-bridge/index.js';
16
+ import { DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, DESKTOP_BRIDGE_LAUNCHD_LABEL, desktopBridgeConfigGeneration, desktopBridgeLaunchdPlistPath, desktopBridgeProcessExists, desktopBridgeStatePath, getDesktopBridgeStatus, preflightDesktopBridge, readDesktopBridgeState, safeBridgeErrorCode, writeDesktopBridgeLaunchdPlist, selectAvailableDesktopBridgePort, startPreparedDesktopBridge, DESKTOP_BRIDGE_STATE_SCHEMA, DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL, DesktopBridgeError, } from './desktop-bridge/index.js';
15
17
  export const DEFAULT_DESKTOP_BRIDGE_HOST = '127.0.0.1';
16
18
  export const DEFAULT_DESKTOP_BRIDGE_PORT = 49_152;
17
19
  export const DESKTOP_BRIDGE_SETTINGS_SCHEMA = 'sks.desktop-bridge-settings.v2';
@@ -159,7 +161,7 @@ export async function writeDesktopBridgeServiceSettings(file, settings) {
159
161
  }
160
162
  async function writeDesktopBridgeServiceSettingsUnlocked(file, settings) {
161
163
  const validated = validateDesktopBridgeServiceSettings(settings);
162
- const persisted = { schema: validated.schema, listen_host: validated.listen_host, listen_port: validated.listen_port, provider_registry: validated.provider_registry, route_policy: validated.route_policy, provider_session_pins: validated.provider_session_pins, client_capability_sha256: validated.client_capability_sha256, allowed_origins: validated.allowed_origins, connect_timeout_ms: validated.connect_timeout_ms, idle_timeout_ms: validated.idle_timeout_ms };
164
+ const persisted = { schema: validated.schema, listen_host: validated.listen_host, listen_port: validated.listen_port, provider_registry: validated.provider_registry, route_policy: validated.route_policy, provider_session_pins: validated.provider_session_pins, client_capability_sha256: validated.client_capability_sha256, allowed_origins: validated.allowed_origins, connect_timeout_ms: validated.connect_timeout_ms, idle_timeout_ms: validated.idle_timeout_ms, official_passthrough: validated.official_passthrough };
163
165
  await writeTextAtomic(file, `${JSON.stringify(persisted, null, 2)}\n`, { mode: 0o600 });
164
166
  await fsp.chmod(file, 0o600);
165
167
  }
@@ -246,11 +248,13 @@ export async function resolveDesktopBridgeRuntimeConfig(options = {}) {
246
248
  if (!Object.keys(settings.route_policy.model_routes).length)
247
249
  throw new Error('catalog_model_route_missing');
248
250
  const enabledRoutes = new Set(Object.values(settings.route_policy.model_routes).map((route) => route.provider_id));
249
- if (![...enabledRoutes].some((id) => credentials.registry.providers[id].credential_state === 'ready'))
251
+ const providerRouteIds = [...enabledRoutes].filter((id) => id === 'codex-lb' || id === 'openrouter');
252
+ const officialOnly = providerRouteIds.length === 0 && settings.official_passthrough.enabled;
253
+ if (!officialOnly && !providerRouteIds.some((id) => credentials.registry.providers[id].credential_state === 'ready'))
250
254
  throw new Error('desktop_bridge_provider_credentials_unavailable');
251
255
  const persistProviderSessionPins = options.persistProviderSessionPins
252
256
  || ((pins) => persistDesktopBridgeSessionPins(paths.settings_path, settings, pins));
253
- const config = { providerRegistry: settings.provider_registry, routePolicy: settings.route_policy, providerSessionPins: settings.provider_session_pins, ...(options.resolveRequestRoute ? { resolveRequestRoute: options.resolveRequestRoute } : {}), persistProviderSessionPins, resolveProviderCredential: credentials.resolver, clientCapabilitySha256: settings.client_capability_sha256, listenHost: settings.listen_host, listenPort: settings.listen_port, allowedPathPrefixes: DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, allowedOrigins: settings.allowed_origins, connectTimeoutMs: settings.connect_timeout_ms, idleTimeoutMs: settings.idle_timeout_ms };
257
+ const config = { providerRegistry: settings.provider_registry, routePolicy: settings.route_policy, providerSessionPins: settings.provider_session_pins, ...(options.resolveRequestRoute ? { resolveRequestRoute: options.resolveRequestRoute } : {}), persistProviderSessionPins, resolveProviderCredential: credentials.resolver, clientCapabilitySha256: settings.client_capability_sha256, listenHost: settings.listen_host, listenPort: settings.listen_port, allowedPathPrefixes: DESKTOP_BRIDGE_ALLOWED_PATH_PREFIXES, allowedOrigins: settings.allowed_origins, connectTimeoutMs: settings.connect_timeout_ms, idleTimeoutMs: settings.idle_timeout_ms, officialPassthrough: settings.official_passthrough.enabled ? { baseUrl: settings.official_passthrough.base_url } : null };
254
258
  const primary = credentials.sources['codex-lb'] || credentials.sources.openrouter;
255
259
  if (!primary)
256
260
  throw new Error('desktop_bridge_provider_credentials_unavailable');
@@ -434,24 +438,67 @@ async function installedPackageVersion() {
434
438
  return null;
435
439
  }
436
440
  }
441
+ export const DESKTOP_BRIDGE_SKEW_RESTART_COOLDOWN_MS = 30 * 60_000;
442
+ export function desktopBridgeSkewRestartSuppressed(marker, running, installed, nowMs) {
443
+ return Boolean(marker
444
+ && marker.running === running
445
+ && marker.installed === installed
446
+ && nowMs - Date.parse(marker.at) < DESKTOP_BRIDGE_SKEW_RESTART_COOLDOWN_MS);
447
+ }
448
+ async function readSkewRestartMarker(file) {
449
+ try {
450
+ const parsed = JSON.parse(await fsp.readFile(file, 'utf8'));
451
+ if (typeof parsed.running !== 'string' || typeof parsed.installed !== 'string' || !Number.isFinite(Date.parse(String(parsed.at))))
452
+ return null;
453
+ return { running: parsed.running, installed: parsed.installed, at: String(parsed.at) };
454
+ }
455
+ catch {
456
+ return null;
457
+ }
458
+ }
459
+ async function autoApplyOfficialModelsAtServe(runtime, home, options) {
460
+ const settings = runtime.settings;
461
+ const mode = await resolveEffectiveOfficialModelsMode(settings.official_passthrough, { home });
462
+ if (mode !== 'passthrough')
463
+ return;
464
+ const flipped = applyOfficialModelPassthrough(settings.route_policy, { mode: 'passthrough' });
465
+ if (flipped.policy_generation === settings.route_policy.policy_generation)
466
+ return;
467
+ const nextSettings = { ...settings, route_policy: flipped };
468
+ await writeDesktopBridgeServiceSettings(options.settingsPath || desktopBridgeServicePaths(home).settings_path, nextSettings);
469
+ await writeBridgeRoutingPolicy(bridgeRoutePolicyPath(path.join(path.resolve(home), '.codex')), flipped).catch(() => undefined);
470
+ settings.route_policy = flipped;
471
+ runtime.config.routePolicy = flipped;
472
+ process.stdout.write(`${JSON.stringify({ schema: 'sks.desktop-bridge-log.v2', event: 'sks.desktop_bridge.official_models_auto_applied', at: new Date().toISOString(), sks_version: PACKAGE_VERSION, mode: 'passthrough', policy_generation: flipped.policy_generation, secret_fields_redacted: true })}\n`);
473
+ }
437
474
  export async function serveDesktopBridge(options = {}) {
438
475
  let handle = null;
439
476
  try {
440
477
  const runtime = await resolveDesktopBridgeRuntimeConfig(options);
478
+ const serveHome = options.home || options.env?.HOME || process.env.HOME || os.homedir();
479
+ await autoApplyOfficialModelsAtServe(runtime, serveHome, options);
441
480
  const supervised = desktopBridgeIsSupervised();
481
+ const skewMarkerPath = path.join(path.dirname(runtime.paths.state_path), 'desktop-bridge-skew-restart.json');
442
482
  handle = await startPreparedDesktopBridge(await preflightDesktopBridge(runtime.config), {
443
483
  statePath: runtime.paths.state_path,
444
484
  versionSkew: {
445
485
  readInstalledVersion: installedPackageVersion,
446
486
  onSkew: (installedVersion) => {
447
- process.stdout.write(`${JSON.stringify({ schema: 'sks.desktop-bridge-log.v2', event: 'sks.desktop_bridge.version_skew', running: PACKAGE_VERSION, installed: installedVersion, supervised, action: supervised ? 'restarting' : 'logged_only', secret_fields_redacted: true })}\n`);
448
- if (!supervised)
449
- return;
450
- void handle?.stop().catch(() => undefined).finally(() => process.exit(64));
487
+ void (async () => {
488
+ const marker = await readSkewRestartMarker(skewMarkerPath);
489
+ const cooldownActive = desktopBridgeSkewRestartSuppressed(marker, PACKAGE_VERSION, installedVersion, Date.now());
490
+ const action = !supervised ? 'logged_only' : cooldownActive ? 'suppressed_cooldown' : 'restarting';
491
+ process.stdout.write(`${JSON.stringify({ schema: 'sks.desktop-bridge-log.v2', event: 'sks.desktop_bridge.version_skew', at: new Date().toISOString(), running: PACKAGE_VERSION, installed: installedVersion, supervised, action, secret_fields_redacted: true })}\n`);
492
+ if (!supervised || cooldownActive)
493
+ return;
494
+ await writeTextAtomic(skewMarkerPath, `${JSON.stringify({ running: PACKAGE_VERSION, installed: installedVersion, at: new Date().toISOString() })}\n`, { mode: 0o600 }).catch(() => undefined);
495
+ await handle?.stop().catch(() => undefined);
496
+ process.exit(64);
497
+ })();
451
498
  },
452
499
  },
453
500
  });
454
- process.stdout.write(`${JSON.stringify({ schema: 'sks.desktop-bridge-log.v2', event: 'sks.desktop_bridge.started', pid: handle.state.pid, process_generation: handle.state.schema === DESKTOP_BRIDGE_STATE_SCHEMA ? handle.state.process_generation : null, provider_registry_generation: runtime.config.providerRegistry?.generation, route_policy_generation: runtime.config.routePolicy?.policy_generation, secret_fields_redacted: true })}\n`);
501
+ process.stdout.write(`${JSON.stringify({ schema: 'sks.desktop-bridge-log.v2', event: 'sks.desktop_bridge.started', at: new Date().toISOString(), sks_version: PACKAGE_VERSION, pid: handle.state.pid, process_generation: handle.state.schema === DESKTOP_BRIDGE_STATE_SCHEMA ? handle.state.process_generation : null, provider_registry_generation: runtime.config.providerRegistry?.generation, route_policy_generation: runtime.config.routePolicy?.policy_generation, secret_fields_redacted: true })}\n`);
455
502
  await waitForShutdown(handle);
456
503
  return { schema: 'sks.desktop-bridge-serve.v1', ok: true, status: 'stopped', state: handle.state };
457
504
  }
@@ -470,7 +517,7 @@ function validateDesktopBridgeServiceSettings(value) {
470
517
  const input = row;
471
518
  if (input.schema !== DESKTOP_BRIDGE_SETTINGS_SCHEMA)
472
519
  throw new Error('desktop_bridge_settings_schema_invalid');
473
- const allowedKeys = new Set(['schema', 'listen_host', 'listen_port', 'provider_registry', 'route_policy', 'provider_session_pins', 'client_capability_sha256', 'allowed_origins', 'connect_timeout_ms', 'idle_timeout_ms']);
520
+ const allowedKeys = new Set(['schema', 'listen_host', 'listen_port', 'provider_registry', 'route_policy', 'provider_session_pins', 'client_capability_sha256', 'allowed_origins', 'connect_timeout_ms', 'idle_timeout_ms', 'official_passthrough']);
474
521
  if (Object.keys(input).some((key) => !allowedKeys.has(key)))
475
522
  throw new Error('desktop_bridge_settings_unknown_field');
476
523
  const serialized = JSON.stringify(input);
@@ -502,7 +549,44 @@ function validateDesktopBridgeServiceSettings(value) {
502
549
  throw new Error('desktop_bridge_settings_connect_timeout_invalid');
503
550
  if (!Number.isFinite(idle) || idle < 1_000 || idle > 86_400_000)
504
551
  throw new Error('desktop_bridge_settings_idle_timeout_invalid');
505
- return { schema: DESKTOP_BRIDGE_SETTINGS_SCHEMA, listen_host: host, listen_port: port, provider_registry: registry, route_policy: policy, provider_session_pins: pins, client_capability_sha256: clientCapabilitySha256, allowed_origins: [...new Set(origins)], connect_timeout_ms: connect, idle_timeout_ms: idle };
552
+ const officialPassthrough = validateOfficialPassthroughSettings(input.official_passthrough);
553
+ return { schema: DESKTOP_BRIDGE_SETTINGS_SCHEMA, listen_host: host, listen_port: port, provider_registry: registry, route_policy: policy, provider_session_pins: pins, client_capability_sha256: clientCapabilitySha256, allowed_origins: [...new Set(origins)], connect_timeout_ms: connect, idle_timeout_ms: idle, official_passthrough: officialPassthrough };
554
+ }
555
+ function validateOfficialPassthroughSettings(value) {
556
+ if (value === undefined || value === null) {
557
+ return { enabled: true, base_url: DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL, models: 'auto' };
558
+ }
559
+ if (typeof value !== 'object' || Array.isArray(value))
560
+ throw new Error('desktop_bridge_settings_official_passthrough_invalid');
561
+ const row = value;
562
+ if (Object.keys(row).some((key) => key !== 'enabled' && key !== 'base_url' && key !== 'models'))
563
+ throw new Error('desktop_bridge_settings_official_passthrough_invalid');
564
+ const enabled = row.enabled === true;
565
+ const baseUrl = typeof row.base_url === 'string' && row.base_url.trim() ? row.base_url.trim() : DESKTOP_BRIDGE_OFFICIAL_UPSTREAM_BASE_URL;
566
+ try {
567
+ new URL(baseUrl);
568
+ }
569
+ catch {
570
+ throw new Error('desktop_bridge_settings_official_passthrough_invalid');
571
+ }
572
+ const models = row.models === 'passthrough' || row.models === 'gateway' || row.models === 'auto'
573
+ ? row.models
574
+ : row.models === undefined ? 'auto' : null;
575
+ if (models === null)
576
+ throw new Error('desktop_bridge_settings_official_passthrough_invalid');
577
+ return { enabled, base_url: baseUrl, models };
578
+ }
579
+ export async function resolveEffectiveOfficialModelsMode(official, input) {
580
+ if (official && official.enabled === false)
581
+ return 'gateway';
582
+ const models = official?.models || 'auto';
583
+ if (models === 'passthrough' || models === 'gateway')
584
+ return models;
585
+ const snapshot = await captureCodexAuthSnapshot({
586
+ home: input.home,
587
+ ...(input.authPath ? { authPath: input.authPath } : {}),
588
+ }).catch(() => null);
589
+ return snapshot && (snapshot.mode === 'chatgpt_oauth' || snapshot.mode === 'mixed') ? 'passthrough' : 'gateway';
506
590
  }
507
591
  function validateProviderSessionPins(value) {
508
592
  const pins = Array.isArray(value) ? value : [];
@@ -1,6 +1,7 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
+ import { BRIDGE_OFFICIAL_ROUTE_ID } from './bridge-contracts.js';
4
5
  import { canonicalizeBridgeModelId, normalizeBridgeUpstreamModelId, sha256Stable } from './route-index.js';
5
6
  import { writeJsonAtomic } from '../fsx.js';
6
7
  import { withFileLock } from '../locks/file-lock.js';
@@ -58,6 +59,8 @@ export function validateBridgeRoutingPolicy(policy, routeIndex) {
58
59
  blockers.push('bridge_route_policy_model_invalid');
59
60
  if (routeIndex) {
60
61
  for (const [model, target] of Object.entries(canonical)) {
62
+ if (target.provider_id === BRIDGE_OFFICIAL_ROUTE_ID)
63
+ continue;
61
64
  const indexed = routeIndex.routes[model];
62
65
  if (!indexed || !sameTarget(indexed, target))
63
66
  blockers.push('bridge_route_policy_route_index_mismatch');
@@ -101,7 +104,7 @@ function canonicalRoutes(routes) {
101
104
  for (const [model, target] of Object.entries(routes)) {
102
105
  const canonicalModel = canonicalizeBridgeModelId(model);
103
106
  const upstreamModel = normalizeBridgeUpstreamModelId(target.upstream_model);
104
- if (!canonicalModel || !upstreamModel || !isProviderId(target.provider_id))
107
+ if (!canonicalModel || !upstreamModel || !isRouteTargetId(target.provider_id))
105
108
  continue;
106
109
  rows.push([canonicalModel, { provider_id: target.provider_id, upstream_model: upstreamModel }]);
107
110
  }
@@ -110,6 +113,32 @@ function canonicalRoutes(routes) {
110
113
  function isProviderId(value) {
111
114
  return value === 'codex-lb' || value === 'openrouter';
112
115
  }
116
+ function isRouteTargetId(value) {
117
+ return isProviderId(value) || value === BRIDGE_OFFICIAL_ROUTE_ID;
118
+ }
119
+ export const OFFICIAL_MODEL_ID_PATTERN = /^(?:gpt-[0-9]|o[0-9]|codex-mini)/;
120
+ export function applyOfficialModelPassthrough(policy, input = { mode: 'passthrough' }) {
121
+ if (input.mode === 'gateway')
122
+ return policy;
123
+ const routes = {};
124
+ for (const [model, target] of Object.entries(policy.model_routes)) {
125
+ routes[model] = OFFICIAL_MODEL_ID_PATTERN.test(model) && !model.includes(':')
126
+ ? { provider_id: BRIDGE_OFFICIAL_ROUTE_ID, upstream_model: model }
127
+ : target;
128
+ }
129
+ const semantic = {
130
+ default_provider_id: policy.default_provider_id,
131
+ fallback: 'none',
132
+ model_routes: canonicalRoutes(routes),
133
+ catalog_generation: policy.catalog_generation
134
+ };
135
+ return {
136
+ schema: 'sks.bridge-routing-policy.v1',
137
+ ...semantic,
138
+ policy_generation: sha256Stable(semantic),
139
+ changed_at: input.changedAt || new Date().toISOString()
140
+ };
141
+ }
113
142
  function sameTarget(left, right) {
114
143
  return left.provider_id === right.provider_id && left.upstream_model === right.upstream_model;
115
144
  }
@@ -51,6 +51,20 @@ export function resolveBridgeRequestRoute(request, policy, options) {
51
51
  const policyTarget = policy.model_routes[model];
52
52
  if (!indexed || !policyTarget)
53
53
  return blocked(base, 'catalog_model_route_missing');
54
+ if (policyTarget.provider_id === 'openai') {
55
+ return {
56
+ ...base,
57
+ ok: true,
58
+ route: policyTarget,
59
+ endpoint_url: null,
60
+ source: 'route_index',
61
+ proposed_session_pin: null,
62
+ blockers: [],
63
+ recovery_action: null
64
+ };
65
+ }
66
+ if (indexed.provider_id === 'openai')
67
+ return blocked(base, 'catalog_route_provider_unknown');
54
68
  if (!sameTarget(indexed, policyTarget))
55
69
  return blocked(base, 'bridge_route_policy_route_index_mismatch');
56
70
  if (pinClaim && !sameTarget(indexed, pinClaim))
@@ -18,7 +18,7 @@ export async function resolveDesktopBridgeImagegenTarget(opts = {}) {
18
18
  const route = model && policy?.fallback === 'none'
19
19
  ? policy.model_routes?.[model] || null
20
20
  : null;
21
- const provider = route ? status?.providers?.[route.provider_id] || null : null;
21
+ const provider = route && route.provider_id !== 'openai' ? status?.providers?.[route.provider_id] || null : null;
22
22
  const providerImagegen = provider?.capabilities?.capabilities?.image_generation || null;
23
23
  const blocker = !status || status.schema !== 'sks.desktop-bridge-status.v3'
24
24
  ? 'desktop_bridge_status_unavailable'
@@ -50,7 +50,7 @@ export async function resolveDesktopBridgeImagegenTarget(opts = {}) {
50
50
  model,
51
51
  model_source: model ? 'explicit' : null,
52
52
  route: route || null,
53
- provider_id: route?.provider_id || null,
53
+ provider_id: route && route.provider_id !== 'openai' ? route.provider_id : null,
54
54
  status_source: injected ? 'injected_fixture' : 'runtime',
55
55
  live_evidence_allowed: bridgeVerified && !injected,
56
56
  blocker,
@@ -86,7 +86,8 @@ export async function writeProviderContextReport(root = process.cwd(), input = {
86
86
  return { ...report, report_path: reportPath };
87
87
  }
88
88
  function selectedBridgeProvider(status) {
89
- return status?.routing.selected_route?.provider_id
89
+ const selected = status?.routing.selected_route?.provider_id;
90
+ return (selected === 'codex-lb' || selected === 'openrouter' ? selected : null)
90
91
  || status?.routing.policy?.default_provider_id
91
92
  || status?.routing.session_pin?.provider_id
92
93
  || null;
@@ -59,6 +59,15 @@ export function affectedGlobsFor(id) {
59
59
  'package-lock.json',
60
60
  'src/core/codex-app.ts',
61
61
  'src/core/codex-lb-circuit.ts',
62
+ 'src/core/codex-lb/**',
63
+ `src/scripts/${prefix}-*.ts`
64
+ ];
65
+ case 'desktop-bridge':
66
+ return [
67
+ 'src/core/codex-lb/desktop-bridge/**',
68
+ 'src/core/codex-lb/desktop-service.ts',
69
+ 'src/core/codex-lb/provider-route-policy.ts',
70
+ 'src/core/codex-lb/request-route-resolver.ts',
62
71
  `src/scripts/${prefix}-*.ts`
63
72
  ];
64
73
  case 'context-graph-v2':
@@ -1 +1 @@
1
- export const PACKAGE_VERSION = '9.1.1';
1
+ export const PACKAGE_VERSION = '9.2.0';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "sneakoscope",
3
3
  "displayName": "ㅅㅋㅅ",
4
- "version": "9.1.1",
4
+ "version": "9.2.0",
5
5
  "description": "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.",
6
6
  "type": "module",
7
7
  "homepage": "https://github.com/mandarange/Sneakoscope-Codex#readme",