sneakoscope 4.7.1 → 4.7.3
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.
- package/README.md +5 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/bin/sks.js +1 -1
- package/dist/cli/install-helpers.js +215 -57
- package/dist/commands/codex-lb.js +143 -7
- package/dist/commands/doctor.js +9 -0
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +11 -1
- package/dist/core/codex-app/codex-app-restart.js +65 -0
- package/dist/core/codex-app.js +235 -3
- package/dist/core/codex-control/codex-sdk-config-policy.js +2 -2
- package/dist/core/codex-control/codex-task-runner.js +2 -2
- package/dist/core/codex-lb/codex-lb-setup.js +1 -1
- package/dist/core/fsx.js +1 -1
- package/dist/core/imagegen/imagegen-capability.js +2 -2
- package/dist/core/init.js +1 -1
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/provider/provider-context.js +1 -1
- package/dist/core/routes.js +1 -1
- package/dist/core/version.js +1 -1
- package/dist/scripts/codex-app-provider-model-ui-check.js +114 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +90 -0
- package/dist/scripts/codex-lb-setup-truthfulness-check.js +6 -1
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +5 -1
- package/dist/scripts/gpt-image-2-real-file-smoke.js +2 -2
- package/dist/scripts/provider-context-config-toml-check.js +2 -2
- package/package.json +3 -1
package/dist/core/codex-app.js
CHANGED
|
@@ -6,6 +6,10 @@ import { EMPTY_CODEX_INFO, getCodexInfo } from './codex-adapter.js';
|
|
|
6
6
|
import { CODEX_CHROME_EXTENSION_DOC_URL, DEFAULT_CODEX_APP_PLUGINS as DEFAULT_CODEX_APP_PLUGIN_TUPLES, RESERVED_CODEX_PLUGIN_SKILL_NAMES } from './routes.js';
|
|
7
7
|
import { PRODUCT_DESIGN_PLUGIN, normalizeProductDesignPluginEvidence } from './product-design-plugin.js';
|
|
8
8
|
import { PRODUCT_DESIGN_AUTO_INSTALL_ENV, ensureProductDesignPluginInstalled, productDesignAutoInstallRequested } from './product-design-app-server.js';
|
|
9
|
+
import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_CODEX_CONFIG_REASONING_PROFILES } from './codex-app/glm-model-profile.js';
|
|
10
|
+
import { GLM_52_OPENROUTER_MODEL } from './providers/glm/glm-52-settings.js';
|
|
11
|
+
import { resolveOpenRouterApiKey } from './providers/openrouter/openrouter-secret-store.js';
|
|
12
|
+
import { codexLbEnvPath, parseShellEnvValue } from './codex-lb/codex-lb-env.js';
|
|
9
13
|
export const CODEX_APP_DOCS_URL = 'https://developers.openai.com/codex/app/features';
|
|
10
14
|
export const CODEX_CHANGELOG_URL = 'https://developers.openai.com/codex/changelog';
|
|
11
15
|
export const CODEX_ACCESS_TOKENS_DOCS_URL = 'https://developers.openai.com/codex/enterprise/access-tokens';
|
|
@@ -133,6 +137,8 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
133
137
|
const productDesignPlugin = await codexProductDesignPluginStatus(opts);
|
|
134
138
|
const pluginSkillShadows = await codexPluginSkillShadowStatus(opts);
|
|
135
139
|
const fastModeConfig = await codexFastModeConfigStatus(opts);
|
|
140
|
+
const providerModelUi = await codexProviderModelUiStatus(opts);
|
|
141
|
+
const nativeSksMenu = codexNativeSksMenuStatus();
|
|
136
142
|
const computerUseMcpListed = /computer[-_ ]?use/i.test(mcpText);
|
|
137
143
|
const browserUseMcpListed = /browser[-_ ]?use/i.test(mcpText);
|
|
138
144
|
const imageGenerationReady = codexFeatureEnabled(featureText, 'image_generation');
|
|
@@ -161,7 +167,8 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
161
167
|
app: {
|
|
162
168
|
installed: appInstalled,
|
|
163
169
|
path: appPath,
|
|
164
|
-
docs_url: CODEX_APP_DOCS_URL
|
|
170
|
+
docs_url: CODEX_APP_DOCS_URL,
|
|
171
|
+
sks_menu: nativeSksMenu
|
|
165
172
|
},
|
|
166
173
|
codex_cli: {
|
|
167
174
|
ok: Boolean(codex.bin),
|
|
@@ -186,6 +193,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
186
193
|
required_flags: requiredFeatureFlags,
|
|
187
194
|
required_flags_ok: requiredFeatureFlagsOk,
|
|
188
195
|
fast_mode_config: fastModeConfig,
|
|
196
|
+
provider_model_ui: providerModelUi,
|
|
189
197
|
git_actions: gitActions,
|
|
190
198
|
image_generation: imageGenerationReady,
|
|
191
199
|
image_generation_source: imageGenerationReady ? 'codex_features_list' : 'missing',
|
|
@@ -223,7 +231,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
223
231
|
}
|
|
224
232
|
},
|
|
225
233
|
chrome_extension: chromeExtension,
|
|
226
|
-
guidance: codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags, requiredFeatureFlagsOk, defaultPlugins, productDesignPlugin, pluginSkillShadows, fastModeConfig, gitActions, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl })
|
|
234
|
+
guidance: codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags, requiredFeatureFlagsOk, defaultPlugins, productDesignPlugin, pluginSkillShadows, fastModeConfig, providerModelUi, nativeSksMenu, gitActions, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl })
|
|
227
235
|
};
|
|
228
236
|
}
|
|
229
237
|
export async function codexChromeExtensionStatus(opts = {}) {
|
|
@@ -442,7 +450,25 @@ export function codexAccessTokenStatus(env = process.env) {
|
|
|
442
450
|
: ['No CODEX_ACCESS_TOKEN detected in the current process environment. This is fine for interactive ChatGPT login or API-key auth.']
|
|
443
451
|
};
|
|
444
452
|
}
|
|
445
|
-
|
|
453
|
+
function codexNativeSksMenuStatus() {
|
|
454
|
+
return {
|
|
455
|
+
schema: 'sks.codex-app-native-menu.v1',
|
|
456
|
+
supported: false,
|
|
457
|
+
status: 'unsupported_official_api',
|
|
458
|
+
requested_label: 'SKS',
|
|
459
|
+
requested_position: 'between Window and Help',
|
|
460
|
+
alternatives: [
|
|
461
|
+
'sks codex-lb use-codex-lb',
|
|
462
|
+
'sks codex-lb use-oauth',
|
|
463
|
+
'sks codex-app set-openrouter-key --api-key-stdin',
|
|
464
|
+
'codex://settings'
|
|
465
|
+
],
|
|
466
|
+
evidence: [
|
|
467
|
+
'Codex official docs expose settings deep links, slash commands, skills/plugins, and app-server/remote-control surfaces, not third-party native macOS menu insertion.'
|
|
468
|
+
]
|
|
469
|
+
};
|
|
470
|
+
}
|
|
471
|
+
export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, requiredFeatureFlags = {}, requiredFeatureFlagsOk = true, defaultPlugins = { ok: true, missing_enabled: [] }, productDesignPlugin = null, pluginSkillShadows = { ok: true, blocking: [] }, fastModeConfig = { ok: true, blockers: [] }, providerModelUi = null, nativeSksMenu = null, gitActions = { ok: true, blockers: [] }, imageGenerationReady, inAppBrowserReady, browserUseFeatureReady, computerUseReady, browserUseReady, browserToolReady, computerUseMcpListed, browserUseMcpListed, chromeExtension, remoteControl }) {
|
|
446
472
|
const lines = [];
|
|
447
473
|
if (!appInstalled) {
|
|
448
474
|
lines.push('Install and open Codex App for first-party MCP/plugin tools. SKS Zellij launch can still run with Codex CLI alone, but Codex Computer Use and imagegen/gpt-image-2 evidence will be unavailable until Codex App is ready.');
|
|
@@ -503,6 +529,28 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
503
529
|
lines.push(`Codex App speed selector can be hidden or locked by config: ${fastModeConfig.blockers.join(', ')}.`);
|
|
504
530
|
lines.push('Run: sks doctor --fix');
|
|
505
531
|
}
|
|
532
|
+
if (providerModelUi?.glm?.exposed && providerModelUi.glm.openrouter_key_present) {
|
|
533
|
+
lines.push(`GLM model selector profile is exposed: ${providerModelUi.glm.model} via profiles ${providerModelUi.glm.profiles_present.join(', ')}.`);
|
|
534
|
+
}
|
|
535
|
+
else if (providerModelUi?.glm?.exposed) {
|
|
536
|
+
lines.push(`GLM model selector profile is exposed for ${providerModelUi.glm.model}, but the OpenRouter key is missing.`);
|
|
537
|
+
lines.push(`Run: ${providerModelUi.glm.key_command}; restart Codex App if the model picker was already open.`);
|
|
538
|
+
}
|
|
539
|
+
else if (providerModelUi?.glm) {
|
|
540
|
+
lines.push(`GLM model selector profile is not exposed yet: ${providerModelUi.glm.blockers.join(', ') || 'profile setup required'}.`);
|
|
541
|
+
lines.push(`Run: ${providerModelUi.glm.key_command}; then ${providerModelUi.glm.install_command}; restart Codex App if the model picker was already open.`);
|
|
542
|
+
}
|
|
543
|
+
if (providerModelUi?.codex_lb?.key_entry_visible && providerModelUi.codex_lb.key_present && providerModelUi.codex_lb.provider_present && providerModelUi.codex_lb.provider_contract_ok && providerModelUi.codex_lb.base_url_present) {
|
|
544
|
+
lines.push(`codex-lb key entry path is visible and configured; update command ${providerModelUi.codex_lb.set_key_command}.`);
|
|
545
|
+
}
|
|
546
|
+
else if (providerModelUi?.codex_lb?.key_entry_visible) {
|
|
547
|
+
lines.push(`codex-lb key entry path is visible, but setup is incomplete: ${providerModelUi.codex_lb.blockers.join(', ') || 'setup required'}.`);
|
|
548
|
+
lines.push(`Run: ${providerModelUi.codex_lb.setup_command} or ${providerModelUi.codex_lb.set_key_command}.`);
|
|
549
|
+
}
|
|
550
|
+
else if (providerModelUi?.codex_lb) {
|
|
551
|
+
lines.push(`codex-lb key entry path is not exposed yet: ${providerModelUi.codex_lb.blockers.join(', ') || 'setup required'}.`);
|
|
552
|
+
lines.push(`Run: ${providerModelUi.codex_lb.setup_command} or ${providerModelUi.codex_lb.set_key_command}.`);
|
|
553
|
+
}
|
|
506
554
|
if (!gitActions?.ok) {
|
|
507
555
|
lines.push(`Codex App git commit/push actions are blocked: ${gitActions?.blockers?.join(', ') || 'git action readiness'}. The app Commit, Push, Commit and Push, and PR flows need codex_git_commit, hooks, and Codex CLI remote-control support.`);
|
|
508
556
|
lines.push(`Run: sks doctor --fix; if remote-control is still blocked, update Codex CLI to ${CODEX_REMOTE_CONTROL_MIN_VERSION}+ and restart older app-server/TUI sessions.`);
|
|
@@ -510,6 +558,9 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
510
558
|
else {
|
|
511
559
|
lines.push('Codex App git actions are enabled for Commit, Push, Commit and Push, and PR flows; SKS hooks treat those app metadata actions as lightweight git UI actions.');
|
|
512
560
|
}
|
|
561
|
+
if (nativeSksMenu?.supported === false) {
|
|
562
|
+
lines.push('Native macOS SKS menu is not installed because Codex App does not expose a documented third-party native menu extension API; use `sks codex-lb use-codex-lb`, `sks codex-lb use-oauth`, and `sks codex-app set-openrouter-key --api-key-stdin` instead.');
|
|
563
|
+
}
|
|
513
564
|
if (appInstalled && (!computerUseReady || !browserToolReady)) {
|
|
514
565
|
lines.push('Open Codex App settings and enable recommended MCP/plugin tools. Codex CLI 0.130.0+ remote-control/app-server sessions can pick up config changes live; restart older CLI/TUI sessions.');
|
|
515
566
|
lines.push(`Required for SKS web QA/UX/browser evidence: Codex Chrome Extension first (${CODEX_CHROME_EXTENSION_SETUP_DOCS_URL}). Computer Use is reserved for native Mac/non-web surfaces.`);
|
|
@@ -551,6 +602,10 @@ export function formatCodexAppStatus(status, { includeRaw = false } = {}) {
|
|
|
551
602
|
`Remote Ctrl: ${status.remote_control?.ok ? 'ok' : 'missing'}${status.remote_control?.codex_cli?.version_number ? ` min ${status.remote_control.min_version}` : ''}`,
|
|
552
603
|
`App Flags: ${status.features?.required_flags_ok ? 'ok' : `missing ${missingRequiredFeatureFlags(status.features?.required_flags).join(', ') || 'required flags'}`}`,
|
|
553
604
|
`Fast UI: ${status.features?.fast_mode_config?.ok ? 'ok' : `locked ${(status.features?.fast_mode_config?.blockers || []).join(', ') || 'config'}`}`,
|
|
605
|
+
`SKS Menu: ${sksNativeMenuSummary(status.app?.sks_menu)}`,
|
|
606
|
+
`Provider UI:${providerModelUiSummary(status.features?.provider_model_ui)}`,
|
|
607
|
+
`GLM Model: ${glmModelUiSummary(status.features?.provider_model_ui?.glm)}`,
|
|
608
|
+
`codex-lb Key:${codexLbKeyUiSummary(status.features?.provider_model_ui?.codex_lb)}`,
|
|
554
609
|
`Default Plugins:${status.plugins?.default_plugins?.ok ? ' ok' : ` missing ${defaultPluginMissingSummary(status.plugins?.default_plugins) || 'plugin install/config'}`}`,
|
|
555
610
|
`Product Design:${productDesignStatusSummary(status.plugins?.design_product)}`,
|
|
556
611
|
`Plugin Picker:${status.plugins?.picker?.ok ? ' ok' : ` blocked ${pluginPickerBlockers(status).join(', ') || 'config'}`}`,
|
|
@@ -817,6 +872,134 @@ async function codexFastModeConfigStatus(opts = {}) {
|
|
|
817
872
|
blockers
|
|
818
873
|
};
|
|
819
874
|
}
|
|
875
|
+
export async function codexProviderModelUiStatus(opts = {}) {
|
|
876
|
+
const inputEnv = opts.env || process.env;
|
|
877
|
+
const home = opts.home || inputEnv.HOME || os.homedir();
|
|
878
|
+
const cwd = opts.cwd || process.cwd();
|
|
879
|
+
const env = { ...inputEnv, HOME: String(opts.home || inputEnv.HOME || home) };
|
|
880
|
+
const globalConfigPath = opts.configPath || path.join(home || '', '.codex', 'config.toml');
|
|
881
|
+
const projectConfigPath = path.join(cwd || '', '.codex', 'config.toml');
|
|
882
|
+
const globalConfig = await readTextIfExists(globalConfigPath);
|
|
883
|
+
const projectConfig = path.resolve(projectConfigPath) === path.resolve(globalConfigPath)
|
|
884
|
+
? ''
|
|
885
|
+
: await readTextIfExists(projectConfigPath);
|
|
886
|
+
const configText = `${globalConfig}\n${projectConfig}`;
|
|
887
|
+
const openRouterKey = await resolveOpenRouterApiKey({ env }).catch((err) => ({
|
|
888
|
+
key: null,
|
|
889
|
+
source: null,
|
|
890
|
+
key_preview: null,
|
|
891
|
+
blockers: ['openrouter_key_lookup_failed'],
|
|
892
|
+
warnings: [err?.message || 'openrouter key lookup failed']
|
|
893
|
+
}));
|
|
894
|
+
const codexLbEnvFilePath = opts.codexLbEnvPath || codexLbEnvPath(home);
|
|
895
|
+
const codexLbEnvText = await readTextIfExists(codexLbEnvFilePath);
|
|
896
|
+
const codexLbApiKeySource = String(env.CODEX_LB_API_KEY || '').trim()
|
|
897
|
+
? 'process.env'
|
|
898
|
+
: parseShellEnvValue(codexLbEnvText, 'CODEX_LB_API_KEY')
|
|
899
|
+
? 'env-file'
|
|
900
|
+
: 'missing';
|
|
901
|
+
const codexLbBaseUrlSource = String(env.CODEX_LB_BASE_URL || '').trim()
|
|
902
|
+
? 'process.env'
|
|
903
|
+
: parseShellEnvValue(codexLbEnvText, 'CODEX_LB_BASE_URL')
|
|
904
|
+
? 'env-file'
|
|
905
|
+
: 'missing';
|
|
906
|
+
const openrouterProvider = tomlTableAny(configText, [
|
|
907
|
+
`model_providers.${GLM_CODEX_CONFIG_PROVIDER_ID}`,
|
|
908
|
+
`model_providers."${GLM_CODEX_CONFIG_PROVIDER_ID}"`
|
|
909
|
+
]);
|
|
910
|
+
const glmProviderPresent = Boolean(openrouterProvider);
|
|
911
|
+
const profilesPresent = [];
|
|
912
|
+
const profilesMissing = [];
|
|
913
|
+
const glmProfileBlockers = [];
|
|
914
|
+
for (const profile of GLM_CODEX_CONFIG_REASONING_PROFILES) {
|
|
915
|
+
const body = tomlTableAny(configText, [`profiles.${profile.id}`, `profiles."${profile.id}"`]);
|
|
916
|
+
if (!body) {
|
|
917
|
+
profilesMissing.push(profile.id);
|
|
918
|
+
glmProfileBlockers.push(`glm_profile_missing:${profile.id}`);
|
|
919
|
+
continue;
|
|
920
|
+
}
|
|
921
|
+
profilesPresent.push(profile.id);
|
|
922
|
+
if (!hasTomlString(body, 'model_provider', GLM_CODEX_CONFIG_PROVIDER_ID))
|
|
923
|
+
glmProfileBlockers.push(`glm_profile_provider_invalid:${profile.id}`);
|
|
924
|
+
if (!hasTomlString(body, 'model', GLM_52_OPENROUTER_MODEL))
|
|
925
|
+
glmProfileBlockers.push(`glm_profile_model_invalid:${profile.id}`);
|
|
926
|
+
if (!hasTomlString(body, 'model_reasoning_effort', profile.reasoning_effort))
|
|
927
|
+
glmProfileBlockers.push(`glm_profile_reasoning_invalid:${profile.id}`);
|
|
928
|
+
}
|
|
929
|
+
const codexLbProvider = tomlTableAny(configText, ['model_providers.codex-lb', 'model_providers."codex-lb"']);
|
|
930
|
+
const codexLbProviderPresent = Boolean(codexLbProvider);
|
|
931
|
+
const codexLbProviderContractOk = codexLbProviderPresent
|
|
932
|
+
&& hasTomlString(codexLbProvider, 'name', 'openai')
|
|
933
|
+
&& hasTomlString(codexLbProvider, 'wire_api', 'responses')
|
|
934
|
+
&& hasTomlString(codexLbProvider, 'env_key', 'CODEX_LB_API_KEY')
|
|
935
|
+
&& hasTomlBoolean(codexLbProvider, 'supports_websockets', true)
|
|
936
|
+
&& hasTomlBoolean(codexLbProvider, 'requires_openai_auth', true);
|
|
937
|
+
const codexLbSelectedDefault = /(?:^|\n)\s*model_provider\s*=\s*"codex-lb"\s*(?:#.*)?(?=\n|$)/.test(topLevelToml(globalConfig));
|
|
938
|
+
const glmBlockers = [
|
|
939
|
+
...(glmProviderPresent ? [] : ['glm_openrouter_provider_missing']),
|
|
940
|
+
...glmProfileBlockers,
|
|
941
|
+
...(openRouterKey.key ? [] : ['openrouter_key_missing'])
|
|
942
|
+
];
|
|
943
|
+
const codexLbBlockers = [
|
|
944
|
+
...(codexLbProviderPresent ? [] : ['codex_lb_provider_missing']),
|
|
945
|
+
...(codexLbProviderPresent && !codexLbProviderContractOk ? ['codex_lb_provider_contract_drift'] : []),
|
|
946
|
+
...(codexLbApiKeySource !== 'missing' ? [] : ['codex_lb_api_key_missing']),
|
|
947
|
+
...(codexLbBaseUrlSource !== 'missing' ? [] : ['codex_lb_base_url_missing'])
|
|
948
|
+
];
|
|
949
|
+
const blockers = [...glmBlockers, ...codexLbBlockers];
|
|
950
|
+
const keyCommand = 'sks codex-app set-openrouter-key --api-key-stdin';
|
|
951
|
+
const installCommand = 'sks codex-app glm-profile install';
|
|
952
|
+
const setupCommand = 'sks codex-lb setup --host <domain> --api-key-stdin --yes';
|
|
953
|
+
const setKeyCommand = 'sks codex-lb set-key --api-key-stdin';
|
|
954
|
+
return {
|
|
955
|
+
schema: 'sks.codex-app-provider-model-ui.v1',
|
|
956
|
+
ok: blockers.length === 0,
|
|
957
|
+
checked: true,
|
|
958
|
+
status: blockers.length === 0 ? 'ready' : 'setup_required',
|
|
959
|
+
config_paths: {
|
|
960
|
+
codex_config: globalConfigPath,
|
|
961
|
+
project_config: projectConfig ? projectConfigPath : null,
|
|
962
|
+
codex_lb_env: codexLbEnvFilePath
|
|
963
|
+
},
|
|
964
|
+
glm: {
|
|
965
|
+
exposed: glmProviderPresent && profilesMissing.length === 0 && glmProfileBlockers.length === 0,
|
|
966
|
+
provider_present: glmProviderPresent,
|
|
967
|
+
provider: GLM_CODEX_CONFIG_PROVIDER_ID,
|
|
968
|
+
model: GLM_52_OPENROUTER_MODEL,
|
|
969
|
+
profiles_present: profilesPresent,
|
|
970
|
+
profiles_missing: profilesMissing,
|
|
971
|
+
openrouter_key_present: Boolean(openRouterKey.key),
|
|
972
|
+
openrouter_key_source: openRouterKey.source || null,
|
|
973
|
+
openrouter_key_preview: openRouterKey.key_preview || null,
|
|
974
|
+
key_command: keyCommand,
|
|
975
|
+
install_command: installCommand,
|
|
976
|
+
doctor_command: 'sks codex-app glm-profile doctor',
|
|
977
|
+
blockers: glmBlockers
|
|
978
|
+
},
|
|
979
|
+
codex_lb: {
|
|
980
|
+
key_entry_visible: true,
|
|
981
|
+
provider_present: codexLbProviderPresent,
|
|
982
|
+
provider_contract_ok: codexLbProviderContractOk,
|
|
983
|
+
selected_default: codexLbSelectedDefault,
|
|
984
|
+
key_present: codexLbApiKeySource !== 'missing',
|
|
985
|
+
api_key_source: codexLbApiKeySource,
|
|
986
|
+
base_url_present: codexLbBaseUrlSource !== 'missing',
|
|
987
|
+
base_url_source: codexLbBaseUrlSource,
|
|
988
|
+
setup_command: setupCommand,
|
|
989
|
+
set_key_command: setKeyCommand,
|
|
990
|
+
status_command: 'sks codex-lb status',
|
|
991
|
+
blockers: codexLbBlockers
|
|
992
|
+
},
|
|
993
|
+
ui_actions: [
|
|
994
|
+
keyCommand,
|
|
995
|
+
installCommand,
|
|
996
|
+
setupCommand,
|
|
997
|
+
setKeyCommand,
|
|
998
|
+
'sks codex-app status'
|
|
999
|
+
],
|
|
1000
|
+
blockers
|
|
1001
|
+
};
|
|
1002
|
+
}
|
|
820
1003
|
async function readTextIfExists(file) {
|
|
821
1004
|
try {
|
|
822
1005
|
return await fsp.readFile(file, 'utf8');
|
|
@@ -876,6 +1059,38 @@ function productDesignStatusSummary(status = {}) {
|
|
|
876
1059
|
return ' app-server unverified';
|
|
877
1060
|
return ' not checked';
|
|
878
1061
|
}
|
|
1062
|
+
function providerModelUiSummary(status = {}) {
|
|
1063
|
+
if (!status?.checked)
|
|
1064
|
+
return ' not checked';
|
|
1065
|
+
if (status.ok)
|
|
1066
|
+
return ' ok (GLM + codex-lb)';
|
|
1067
|
+
return ` setup ${(status.blockers || []).join(', ') || 'required'}`;
|
|
1068
|
+
}
|
|
1069
|
+
function sksNativeMenuSummary(status = {}) {
|
|
1070
|
+
if (!status)
|
|
1071
|
+
return 'not checked';
|
|
1072
|
+
if (status.supported)
|
|
1073
|
+
return 'ok';
|
|
1074
|
+
return `${status.status || 'unsupported'} (use CLI/settings)`;
|
|
1075
|
+
}
|
|
1076
|
+
function glmModelUiSummary(status = {}) {
|
|
1077
|
+
if (!status)
|
|
1078
|
+
return 'not checked';
|
|
1079
|
+
if (status.exposed) {
|
|
1080
|
+
const key = status.openrouter_key_present ? `key ${status.openrouter_key_source || 'present'}` : 'key missing';
|
|
1081
|
+
return `ok ${status.model} (${status.profiles_present?.length || 0} profiles, ${key})`;
|
|
1082
|
+
}
|
|
1083
|
+
return `setup ${(status.blockers || []).join(', ') || 'profile missing'}; run ${status.key_command || 'sks codex-app set-openrouter-key --api-key-stdin'}`;
|
|
1084
|
+
}
|
|
1085
|
+
function codexLbKeyUiSummary(status = {}) {
|
|
1086
|
+
if (!status)
|
|
1087
|
+
return ' not checked';
|
|
1088
|
+
if (status.key_present && status.provider_contract_ok !== false)
|
|
1089
|
+
return ` configured (${status.api_key_source || 'present'})`;
|
|
1090
|
+
if (status.key_present)
|
|
1091
|
+
return ` setup provider drift; run ${status.setup_command || 'sks codex-lb setup --host <domain> --api-key-stdin --yes'}`;
|
|
1092
|
+
return ` missing (input: ${status.setup_command || 'sks codex-lb setup --host <domain> --api-key-stdin --yes'})`;
|
|
1093
|
+
}
|
|
879
1094
|
function defaultPluginMissingSummary(defaultPlugins = {}) {
|
|
880
1095
|
return [
|
|
881
1096
|
...(defaultPlugins?.missing_installed || []),
|
|
@@ -891,6 +1106,23 @@ function tomlTable(text = '', table = '') {
|
|
|
891
1106
|
const re = new RegExp(`(?:^|\\n)\\[${escapeRegExp(table)}\\]([\\s\\S]*?)(?=\\n\\[[^\\]]+\\]|\\s*$)`);
|
|
892
1107
|
return String(text || '').match(re)?.[1] || '';
|
|
893
1108
|
}
|
|
1109
|
+
function tomlTableAny(text = '', tables = []) {
|
|
1110
|
+
for (const table of tables) {
|
|
1111
|
+
const body = tomlTable(text, table);
|
|
1112
|
+
if (body)
|
|
1113
|
+
return body;
|
|
1114
|
+
}
|
|
1115
|
+
return '';
|
|
1116
|
+
}
|
|
1117
|
+
function hasTomlString(text = '', key = '', value = '') {
|
|
1118
|
+
const re = new RegExp(`(?:^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*"${escapeRegExp(value)}"\\s*(?:#.*)?(?=\\n|$)`);
|
|
1119
|
+
return re.test(String(text || ''));
|
|
1120
|
+
}
|
|
1121
|
+
function hasTomlBoolean(text = '', key = '', value) {
|
|
1122
|
+
const expected = value ? 'true' : 'false';
|
|
1123
|
+
const re = new RegExp(`(?:^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*${expected}\\s*(?:#.*)?(?=\\n|$)`);
|
|
1124
|
+
return re.test(String(text || ''));
|
|
1125
|
+
}
|
|
894
1126
|
function escapeRegExp(text = '') {
|
|
895
1127
|
return String(text).replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
896
1128
|
}
|
|
@@ -19,12 +19,12 @@ export function buildCodexSdkConfig(input) {
|
|
|
19
19
|
config.model_provider = 'codex-lb';
|
|
20
20
|
config.model_providers = {
|
|
21
21
|
'codex-lb': {
|
|
22
|
-
name: '
|
|
22
|
+
name: 'openai',
|
|
23
23
|
base_url: codexLbBaseUrl,
|
|
24
24
|
wire_api: 'responses',
|
|
25
25
|
env_key: 'CODEX_LB_API_KEY',
|
|
26
26
|
supports_websockets: true,
|
|
27
|
-
requires_openai_auth:
|
|
27
|
+
requires_openai_auth: true
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
}
|
|
@@ -464,12 +464,12 @@ async function ensurePythonCodexLbConfig(env, config) {
|
|
|
464
464
|
'approval_policy = "never"',
|
|
465
465
|
'',
|
|
466
466
|
'[model_providers.codex-lb]',
|
|
467
|
-
'name = "
|
|
467
|
+
'name = "openai"',
|
|
468
468
|
`base_url = ${tomlQuote(lbBaseUrl)}`,
|
|
469
469
|
'wire_api = "responses"',
|
|
470
470
|
'env_key = "CODEX_LB_API_KEY"',
|
|
471
471
|
'supports_websockets = true',
|
|
472
|
-
'requires_openai_auth =
|
|
472
|
+
'requires_openai_auth = true',
|
|
473
473
|
''
|
|
474
474
|
].join('\n');
|
|
475
475
|
await writeTextAtomic(path.join(codexHome, 'config.toml'), text);
|
|
@@ -14,7 +14,7 @@ export function buildCodexLbSetupPlan(answers, opts = {}) {
|
|
|
14
14
|
if (answers.install_shell_profile !== 'skip' && !answers.write_env_file)
|
|
15
15
|
blockers.push('shell_profile_snippet_requires_env_file');
|
|
16
16
|
const actions = [
|
|
17
|
-
{ type: 'write_config_provider', target: configPath, effect: 'write or update [model_providers.codex-lb] with the normalized base URL, CODEX_LB_API_KEY env_key, and requires_openai_auth=
|
|
17
|
+
{ type: 'write_config_provider', target: configPath, effect: 'write or update [model_providers.codex-lb] with name="openai", the normalized base URL, CODEX_LB_API_KEY env_key, WebSocket support, and requires_openai_auth=true for Codex App routing' }
|
|
18
18
|
];
|
|
19
19
|
if (answers.use_as_default_provider) {
|
|
20
20
|
actions.push({ type: 'select_default_provider', target: configPath, effect: 'set top-level model_provider = "codex-lb"' });
|
package/dist/core/fsx.js
CHANGED
|
@@ -5,7 +5,7 @@ import os from 'node:os';
|
|
|
5
5
|
import crypto from 'node:crypto';
|
|
6
6
|
import { spawn } from 'node:child_process';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
-
export const PACKAGE_VERSION = '4.7.
|
|
8
|
+
export const PACKAGE_VERSION = '4.7.3';
|
|
9
9
|
export const DEFAULT_PROCESS_TAIL_BYTES = 256 * 1024;
|
|
10
10
|
export const DEFAULT_PROCESS_TIMEOUT_MS = 30 * 60 * 1000;
|
|
11
11
|
export function nowIso() {
|
|
@@ -137,8 +137,8 @@ function codexLbAuthBlocker(state) {
|
|
|
137
137
|
return 'codex_lb_not_selected';
|
|
138
138
|
if (!state.providerConfigured)
|
|
139
139
|
return 'codex_lb_provider_missing';
|
|
140
|
-
if (state.requiresOpenAiAuth !==
|
|
141
|
-
return state.requiresOpenAiAuth ===
|
|
140
|
+
if (state.requiresOpenAiAuth !== true) {
|
|
141
|
+
return state.requiresOpenAiAuth === false ? 'codex_lb_legacy_openai_auth_disabled' : 'codex_lb_requires_openai_auth_missing';
|
|
142
142
|
}
|
|
143
143
|
if (state.envKey !== 'CODEX_LB_API_KEY')
|
|
144
144
|
return 'codex_lb_env_key_missing_or_unsupported';
|
package/dist/core/init.js
CHANGED
|
@@ -643,7 +643,7 @@ export async function initProject(root, opts = {}) {
|
|
|
643
643
|
next = shouldSelectCodexLb
|
|
644
644
|
? upsertTopLevelTomlString(next, 'model_provider', 'codex-lb')
|
|
645
645
|
: removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
|
|
646
|
-
next = upsertTomlTable(next, 'model_providers.codex-lb', `[model_providers.codex-lb]\nname = "
|
|
646
|
+
next = upsertTomlTable(next, 'model_providers.codex-lb', `[model_providers.codex-lb]\nname = "openai"\nbase_url = "${baseUrl}"\nwire_api = "responses"\nenv_key = "CODEX_LB_API_KEY"\nsupports_websockets = true\nrequires_openai_auth = true`);
|
|
647
647
|
return `${next.trim()}\n`;
|
|
648
648
|
}
|
|
649
649
|
function parseCodexLbEnvKey(text = '') {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { REQUIRED_CODEX_MODEL } from '../codex-model-guard.js';
|
|
2
2
|
export const MANAGED_ASSET_SCHEMA_VERSION = 1;
|
|
3
|
-
export const MANAGED_ASSET_VERSION = '4.7.
|
|
3
|
+
export const MANAGED_ASSET_VERSION = '4.7.3';
|
|
4
4
|
export const MANAGED_ASSET_MARKER = 'SKS-MANAGED-ASSET';
|
|
5
5
|
export const MANAGED_AGENT_ROLES = Object.freeze([
|
|
6
6
|
role('sks-explorer', 'analysis-scout.toml', 'analysis_scout', 'SKS analysis scout for bounded read/write slices retained for stale Codex agent-role config repair.', 'workspace-write', ['analysis-scout', 'analysis_scout']),
|
|
@@ -10,7 +10,7 @@ export async function resolveProviderContext(input = {}) {
|
|
|
10
10
|
const codexLbProviderBlockPresent = hasCodexLbProviderBlock(configText);
|
|
11
11
|
const codexLbEnvKey = codexLbProviderEnvKey(configText) || (codexLbProviderBlockPresent ? 'CODEX_LB_API_KEY' : null);
|
|
12
12
|
const codexLbRequiresOpenAiAuth = codexLbProviderRequiresOpenAiAuth(configText);
|
|
13
|
-
const codexLbProviderValid = codexLbProviderBlockPresent &&
|
|
13
|
+
const codexLbProviderValid = codexLbProviderBlockPresent && codexLbRequiresOpenAiAuth === true;
|
|
14
14
|
const openaiKey = Boolean(String(env.OPENAI_API_KEY || '').trim());
|
|
15
15
|
const lbKey = Boolean(String((codexLbEnvKey ? env[codexLbEnvKey] : env.CODEX_LB_API_KEY) || env.CODEX_LB_API_KEY || '').trim());
|
|
16
16
|
const envProvider = String(env.SKS_MODEL_PROVIDER || env.CODEX_MODEL_PROVIDER || env.OPENAI_MODEL_PROVIDER || '').trim();
|
package/dist/core/routes.js
CHANGED
|
@@ -702,7 +702,7 @@ export const COMMAND_CATALOG = [
|
|
|
702
702
|
{ name: 'update', usage: 'sks update check|now [--version <version>] [--json] [--dry-run]', description: 'Check for SKS updates or install the requested package version through npm global mode.' },
|
|
703
703
|
{ name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm, Codex CLI, and Zellij readiness; pass --yes to repair missing Codex CLI/Zellij tooling when supported.' },
|
|
704
704
|
{ name: 'codex', usage: 'sks codex compatibility|version|doctor|schema|0.142 [--json]', description: 'Check Codex CLI rust-v0.142.0 compatibility, installed version, 0.142 manifest/capability evidence, inherited legacy baselines, and vendored hook schema snapshot freshness.' },
|
|
705
|
-
{ name: 'codex-app', usage: 'sks codex-app [check|
|
|
705
|
+
{ name: 'codex-app', usage: 'sks codex-app [check|glm-profile install|set-openrouter-key --api-key-stdin|product-design|chrome-extension|pat status|remote-control]', description: 'Check Codex App install, GLM/OpenRouter model profile visibility, codex-lb key-entry guidance, Product Design plugin readiness, Codex Chrome Extension web verification readiness, PAT-safe status, first-party MCP/plugin readiness, and Codex CLI 0.130.0+ remote-control availability.' },
|
|
706
706
|
{ name: 'codex-native', usage: 'sks codex-native status|feature-broker|invocation-plan|init-deep [--json]', description: 'Inspect Codex Native feature broker readiness, invocation routing, pattern evidence, and managed memory setup.' },
|
|
707
707
|
{ name: 'hooks', usage: 'sks hooks explain|status|trust-report|replay|codex-validate|warning-check ... [--json]', description: 'Explain Codex hook events, validate vendored latest 10-event output schemas, replay fixtures, and enforce warning-zero SKS hook policies under the 0.134 compatibility matrix.' },
|
|
708
708
|
{ name: 'codex-lb', usage: 'sks codex-lb status|health|metrics|doctor|circuit|repair|setup ...', description: 'Configure, health-check, repair, and record circuit evidence for codex-lb provider auth without confusing ChatGPT OAuth and proxy keys.' },
|
package/dist/core/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export const PACKAGE_VERSION = '4.7.
|
|
1
|
+
export const PACKAGE_VERSION = '4.7.3';
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { codexProviderModelUiStatus, formatCodexAppStatus } from '../core/codex-app.js';
|
|
6
|
+
import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_CODEX_CONFIG_REASONING_PROFILES } from '../core/codex-app/glm-model-profile.js';
|
|
7
|
+
import { GLM_52_OPENROUTER_MODEL } from '../core/providers/glm/glm-52-settings.js';
|
|
8
|
+
const tmp = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-app-provider-ui-'));
|
|
9
|
+
const home = path.join(tmp, 'home');
|
|
10
|
+
const cwd = path.join(tmp, 'project');
|
|
11
|
+
await fs.mkdir(path.join(home, '.codex'), { recursive: true });
|
|
12
|
+
await fs.mkdir(path.join(cwd, '.codex'), { recursive: true });
|
|
13
|
+
const missing = await codexProviderModelUiStatus({ home, cwd, env: { HOME: home } });
|
|
14
|
+
const missingText = formatCodexAppStatus(statusFixture(missing));
|
|
15
|
+
await fs.writeFile(path.join(home, '.codex', 'config.toml'), readyConfig(), 'utf8');
|
|
16
|
+
await fs.writeFile(path.join(home, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\nexport CODEX_LB_API_KEY='sk-codex-lb-fixture'\n", 'utf8');
|
|
17
|
+
const ready = await codexProviderModelUiStatus({
|
|
18
|
+
home,
|
|
19
|
+
cwd,
|
|
20
|
+
env: { HOME: home, OPENROUTER_API_KEY: 'sk-or-fixture' }
|
|
21
|
+
});
|
|
22
|
+
const readyText = formatCodexAppStatus(statusFixture(ready));
|
|
23
|
+
const ok = missing.ok === false
|
|
24
|
+
&& missing.glm.exposed === false
|
|
25
|
+
&& missing.codex_lb.key_entry_visible === true
|
|
26
|
+
&& missing.ui_actions.includes('sks codex-app set-openrouter-key --api-key-stdin')
|
|
27
|
+
&& missing.ui_actions.includes('sks codex-lb setup --host <domain> --api-key-stdin --yes')
|
|
28
|
+
&& /Provider UI:\s*setup/.test(missingText)
|
|
29
|
+
&& /GLM Model:\s*setup/.test(missingText)
|
|
30
|
+
&& /codex-lb Key:\s*missing \(input: sks codex-lb setup/.test(missingText)
|
|
31
|
+
&& ready.ok === true
|
|
32
|
+
&& ready.glm.exposed === true
|
|
33
|
+
&& ready.glm.model === GLM_52_OPENROUTER_MODEL
|
|
34
|
+
&& ready.glm.profiles_present.length === GLM_CODEX_CONFIG_REASONING_PROFILES.length
|
|
35
|
+
&& ready.codex_lb.provider_present === true
|
|
36
|
+
&& ready.codex_lb.key_present === true
|
|
37
|
+
&& /Provider UI:\s*ok/.test(readyText)
|
|
38
|
+
&& readyText.includes(`GLM Model: ok ${GLM_52_OPENROUTER_MODEL}`)
|
|
39
|
+
&& /codex-lb Key:\s*configured/.test(readyText)
|
|
40
|
+
&& !JSON.stringify({ missing, ready, missingText, readyText }).includes('sk-codex-lb-fixture');
|
|
41
|
+
emit({
|
|
42
|
+
schema: 'sks.codex-app-provider-model-ui-check.v1',
|
|
43
|
+
ok,
|
|
44
|
+
missing,
|
|
45
|
+
ready,
|
|
46
|
+
secret_safe: !JSON.stringify({ missing, ready, missingText, readyText }).includes('sk-codex-lb-fixture'),
|
|
47
|
+
blockers: ok ? [] : ['codex_app_provider_model_ui_check_failed']
|
|
48
|
+
});
|
|
49
|
+
function readyConfig() {
|
|
50
|
+
return [
|
|
51
|
+
`[model_providers.${GLM_CODEX_CONFIG_PROVIDER_ID}]`,
|
|
52
|
+
'name = "OpenRouter"',
|
|
53
|
+
'base_url = "https://openrouter.ai/api/v1"',
|
|
54
|
+
'wire_api = "responses"',
|
|
55
|
+
'env_key = "OPENROUTER_API_KEY"',
|
|
56
|
+
'requires_openai_auth = false',
|
|
57
|
+
'',
|
|
58
|
+
...GLM_CODEX_CONFIG_REASONING_PROFILES.flatMap((profile) => [
|
|
59
|
+
`[profiles.${profile.id}]`,
|
|
60
|
+
`model_provider = "${GLM_CODEX_CONFIG_PROVIDER_ID}"`,
|
|
61
|
+
`model = "${GLM_52_OPENROUTER_MODEL}"`,
|
|
62
|
+
`model_reasoning_effort = "${profile.reasoning_effort}"`,
|
|
63
|
+
'service_tier = "default"',
|
|
64
|
+
'approval_policy = "on-request"',
|
|
65
|
+
''
|
|
66
|
+
]),
|
|
67
|
+
'[model_providers.codex-lb]',
|
|
68
|
+
'name = "openai"',
|
|
69
|
+
'base_url = "https://lb.example.test/backend-api/codex"',
|
|
70
|
+
'wire_api = "responses"',
|
|
71
|
+
'env_key = "CODEX_LB_API_KEY"',
|
|
72
|
+
'supports_websockets = true',
|
|
73
|
+
'requires_openai_auth = true',
|
|
74
|
+
''
|
|
75
|
+
].join('\n');
|
|
76
|
+
}
|
|
77
|
+
function statusFixture(providerModelUi) {
|
|
78
|
+
return {
|
|
79
|
+
ok: providerModelUi.ok,
|
|
80
|
+
app: { installed: true, path: '/Applications/Codex.app' },
|
|
81
|
+
codex_cli: { ok: true, version: '0.142.0' },
|
|
82
|
+
remote_control: { ok: true, min_version: '0.130.0', codex_cli: { version_number: '0.142.0' } },
|
|
83
|
+
features: {
|
|
84
|
+
checked: true,
|
|
85
|
+
required_flags_ok: true,
|
|
86
|
+
required_flags: {},
|
|
87
|
+
fast_mode_config: { ok: true, blockers: [] },
|
|
88
|
+
provider_model_ui: providerModelUi,
|
|
89
|
+
git_actions: { ok: true, blockers: [] },
|
|
90
|
+
browser_tool_ready: true,
|
|
91
|
+
browser_tool_source: 'fixture',
|
|
92
|
+
image_generation: true
|
|
93
|
+
},
|
|
94
|
+
plugins: {
|
|
95
|
+
default_plugins: { ok: true },
|
|
96
|
+
design_product: { ok: true, id: 'product-design' },
|
|
97
|
+
picker: { ok: true }
|
|
98
|
+
},
|
|
99
|
+
chrome_extension: { ok: true, blockers: [] },
|
|
100
|
+
mcp: {
|
|
101
|
+
has_computer_use: true,
|
|
102
|
+
computer_use_source: 'mcp_list',
|
|
103
|
+
has_browser_use: true,
|
|
104
|
+
browser_use_source: 'mcp_list'
|
|
105
|
+
},
|
|
106
|
+
guidance: []
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function emit(report) {
|
|
110
|
+
console.log(JSON.stringify(report, null, 2));
|
|
111
|
+
if (!report.ok)
|
|
112
|
+
process.exitCode = 1;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=codex-app-provider-model-ui-check.js.map
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import fs from 'node:fs/promises';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { run } from '../commands/codex-lb.js';
|
|
6
|
+
const calls = [];
|
|
7
|
+
const home = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-lb-fast-truth-'));
|
|
8
|
+
await fs.mkdir(path.join(home, '.codex'), { recursive: true });
|
|
9
|
+
await fs.writeFile(path.join(home, '.codex', 'config.toml'), [
|
|
10
|
+
'model_provider = "codex-lb"',
|
|
11
|
+
'service_tier = "fast"',
|
|
12
|
+
'',
|
|
13
|
+
'[model_providers.codex-lb]',
|
|
14
|
+
'name = "openai"',
|
|
15
|
+
'base_url = "https://lb.example.test/backend-api/codex"',
|
|
16
|
+
'wire_api = "responses"',
|
|
17
|
+
'env_key = "CODEX_LB_API_KEY"',
|
|
18
|
+
'supports_websockets = true',
|
|
19
|
+
'requires_openai_auth = true',
|
|
20
|
+
''
|
|
21
|
+
].join('\n'));
|
|
22
|
+
await fs.writeFile(path.join(home, '.codex', 'auth.json'), `${JSON.stringify({ auth_mode: 'apikey', OPENAI_API_KEY: 'sk-fixture' })}\n`);
|
|
23
|
+
await fs.writeFile(path.join(home, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\nexport CODEX_LB_API_KEY='sk-fixture'\n");
|
|
24
|
+
const chain = await runFastCheck({
|
|
25
|
+
HOME: home,
|
|
26
|
+
CODEX_LB_API_KEY: 'sk-fixture',
|
|
27
|
+
CODEX_LB_BASE_URL: 'https://lb.example.test/backend-api/codex'
|
|
28
|
+
});
|
|
29
|
+
const requestedOnly = await runFastCheck({
|
|
30
|
+
HOME: home,
|
|
31
|
+
CODEX_LB_API_KEY: 'sk-fixture',
|
|
32
|
+
CODEX_LB_BASE_URL: 'https://lb.example.test/backend-api/codex',
|
|
33
|
+
SKS_TEST_FAST_ACTUAL_DEFAULT: '1'
|
|
34
|
+
});
|
|
35
|
+
const ok = chain.ok === true
|
|
36
|
+
&& chain.status === 'fast_verified'
|
|
37
|
+
&& calls[0]?.body?.service_tier === 'priority'
|
|
38
|
+
&& requestedOnly.ok === false
|
|
39
|
+
&& requestedOnly.status === 'fast_requested_but_actual_unverified'
|
|
40
|
+
&& requestedOnly.blockers.includes('codex_lb_actual_fast_service_tier_unverified');
|
|
41
|
+
console.log(JSON.stringify({
|
|
42
|
+
schema: 'sks.codex-lb-fast-mode-truth-check.v1',
|
|
43
|
+
ok,
|
|
44
|
+
priority_request_sent: calls[0]?.body?.service_tier === 'priority',
|
|
45
|
+
verified_case: chain,
|
|
46
|
+
requested_only_case: requestedOnly,
|
|
47
|
+
blockers: ok ? [] : ['codex_lb_fast_mode_truth_check_failed']
|
|
48
|
+
}, null, 2));
|
|
49
|
+
if (!ok)
|
|
50
|
+
process.exitCode = 1;
|
|
51
|
+
async function runFastCheck(env) {
|
|
52
|
+
const originalFetch = globalThis.fetch;
|
|
53
|
+
const originalEnv = { ...process.env };
|
|
54
|
+
const outputs = [];
|
|
55
|
+
const originalWrite = process.stdout.write.bind(process.stdout);
|
|
56
|
+
const originalExitCode = process.exitCode;
|
|
57
|
+
try {
|
|
58
|
+
Object.assign(process.env, env);
|
|
59
|
+
process.exitCode = 0;
|
|
60
|
+
globalThis.fetch = async (_url, init) => {
|
|
61
|
+
const body = JSON.parse(String(init.body || '{}'));
|
|
62
|
+
calls.push({ body });
|
|
63
|
+
const id = calls.length % 2 === 1 ? 'resp_fast_1' : 'resp_fast_2';
|
|
64
|
+
const actual = env.SKS_TEST_FAST_ACTUAL_DEFAULT === '1' ? 'default' : 'priority';
|
|
65
|
+
return new Response(JSON.stringify({
|
|
66
|
+
id,
|
|
67
|
+
requestedServiceTier: 'priority',
|
|
68
|
+
actualServiceTier: actual,
|
|
69
|
+
serviceTier: actual
|
|
70
|
+
}), { status: 200, headers: { 'content-type': 'application/json' } });
|
|
71
|
+
};
|
|
72
|
+
process.stdout.write = (chunk) => {
|
|
73
|
+
outputs.push(String(chunk));
|
|
74
|
+
return true;
|
|
75
|
+
};
|
|
76
|
+
await run(null, ['fast-check', '--json']);
|
|
77
|
+
return JSON.parse(outputs.join('') || '{}');
|
|
78
|
+
}
|
|
79
|
+
finally {
|
|
80
|
+
globalThis.fetch = originalFetch;
|
|
81
|
+
process.stdout.write = originalWrite;
|
|
82
|
+
process.exitCode = originalExitCode;
|
|
83
|
+
for (const key of Object.keys(process.env)) {
|
|
84
|
+
if (!(key in originalEnv))
|
|
85
|
+
delete process.env[key];
|
|
86
|
+
}
|
|
87
|
+
Object.assign(process.env, originalEnv);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=codex-lb-fast-mode-truth-check.js.map
|