sneakoscope 8.0.2 → 8.0.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 +47 -23
- package/config/skills-hash-ledger.v1.json +1 -1
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +55 -13
- package/dist/bin/sks-dispatch.js +1 -1
- package/dist/cli/command-manifest-lite.js +4 -0
- package/dist/cli/command-registry.js +4 -0
- package/dist/cli/install-helpers-codex-lb-chain.js +187 -0
- package/dist/cli/install-helpers-codex-lb-config.js +74 -8
- package/dist/cli/install-helpers.js +89 -44
- package/dist/commands/codex-lb.js +117 -19
- package/dist/commands/doctor.js +697 -37
- package/dist/config/skills-manifest.json +3 -2
- package/dist/core/agents/agent-runner-codex-exec.js +5 -3
- package/dist/core/codex/codex-config-guard.js +238 -52
- package/dist/core/codex-adapter.js +5 -3
- package/dist/core/codex-app/menubar/constants.js +10 -1
- package/dist/core/codex-app/menubar/global-install.js +288 -0
- package/dist/core/codex-app/menubar/installer.js +79 -14
- package/dist/core/codex-app/menubar/launch-agent.js +267 -45
- package/dist/core/codex-app/menubar/paths.js +3 -0
- package/dist/core/codex-app/menubar/rollback.js +55 -7
- package/dist/core/codex-app/menubar/status.js +75 -4
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +3 -1
- package/dist/core/codex-control/codex-0139-web-search-probe.js +3 -1
- package/dist/core/codex-control/codex-app-server-runtime-env.js +13 -4
- package/dist/core/codex-control/codex-app-server-v2-client.js +3 -3
- package/dist/core/codex-exec-output-schema.js +4 -1
- package/dist/core/codex-lb/codex-lb-env.js +63 -72
- package/dist/core/codex-lb/codex-lb-setup.js +15 -2
- package/dist/core/codex-lb/desktop-center-credentials.js +517 -58
- package/dist/core/codex-lb/desktop-controller.js +153 -24
- package/dist/core/codex-lb/routing-truth.js +327 -0
- package/dist/core/codex-native/core-skill-manifest.js +1 -1
- package/dist/core/commands/basic-cli.js +7 -1
- package/dist/core/commands/qa-loop-command.js +3 -1
- package/dist/core/commands/telegram-command.js +241 -0
- package/dist/core/config-adopt/config-adopt-command.js +35 -0
- package/dist/core/config-adopt/config-adopt.js +346 -0
- package/dist/core/config-adopt/index.js +3 -0
- package/dist/core/doctor/command-alias-cleanup.js +4 -1
- package/dist/core/doctor/current-project-guidance-nested.js +37 -6
- package/dist/core/doctor/current-project-guidance.js +11 -6
- package/dist/core/doctor/doctor-readiness-matrix.js +14 -0
- package/dist/core/doctor/retired-managed-residue-private.js +1 -1
- package/dist/core/doctor/sks-menubar-doctor.js +4 -0
- package/dist/core/feature-fixtures.js +8 -0
- package/dist/core/hooks-runtime/hook-context.js +9 -0
- package/dist/core/hooks-runtime/managed-skill-admission.js +54 -4
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +69 -1
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +2 -2
- package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +3 -3
- package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +43 -5
- package/dist/core/hooks-runtime/subagent-skill-availability.js +64 -30
- package/dist/core/hooks-runtime/subagent-stop-hook.js +15 -2
- package/dist/core/hooks-runtime.js +148 -4
- package/dist/core/imagegen/imagegen-capability.js +46 -0
- package/dist/core/imagegen/require-imagegen.js +2 -2
- package/dist/core/init/skills.js +17 -3
- package/dist/core/install/installed-package-smoke.js +8 -2
- package/dist/core/naruto/hardware-capacity-probe.js +9 -3
- package/dist/core/naruto/naruto-concurrency-governor.js +68 -24
- package/dist/core/perf/import-graph-budget.js +0 -1
- package/dist/core/product-design-app-server.js +13 -1
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/release-pack-receipt.js +1 -2
- package/dist/core/routes/dollar-manifest-lite.js +1 -1
- package/dist/core/routes.js +1 -1
- package/dist/core/security/private-credential-file.js +209 -0
- package/dist/core/subagents/agent-catalog.js +17 -32
- package/dist/core/subagents/naruto-help-contract.js +5 -5
- package/dist/core/subagents/official-subagent-config.js +16 -6
- package/dist/core/subagents/official-subagent-preparation.js +34 -15
- package/dist/core/subagents/official-subagent-prompt.js +4 -4
- package/dist/core/subagents/official-subagent-runner.js +27 -4
- package/dist/core/subagents/thread-budget.js +19 -12
- package/dist/core/subagents/wave-lifecycle.js +18 -6
- package/dist/core/telegram/access.js +54 -0
- package/dist/core/telegram/client.js +144 -0
- package/dist/core/telegram/confirmation.js +37 -0
- package/dist/core/telegram/doctor.js +151 -0
- package/dist/core/telegram/index.js +9 -0
- package/dist/core/telegram/keychain.js +265 -0
- package/dist/core/telegram/liveness.js +109 -0
- package/dist/core/telegram/poller.js +90 -0
- package/dist/core/telegram/redaction.js +15 -0
- package/dist/core/telegram/types.js +1 -0
- package/dist/core/update/update-diagnostics.js +52 -0
- package/dist/core/update/update-migration-state.js +5 -1
- package/dist/core/update/update-operation.js +2 -1
- package/dist/core/update/update-stage-diagnostics.js +38 -0
- package/dist/core/update/update-status.js +2 -9
- package/dist/core/update-check.js +147 -31
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-launcher.js +23 -4
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +13 -0
- package/dist/native/sks-menubar/Sources/AppIdentity.swift +7 -0
- package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +3 -2
- package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +115 -0
- package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +17 -0
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +190 -0
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +100 -59
- package/dist/native/sks-menubar/Sources/SingletonInstanceGuard.swift +328 -0
- package/dist/native/sks-menubar/Sources/TelegramPrivateFileStore.swift +320 -0
- package/dist/native/sks-menubar/Sources/TelegramPrivateFileSupport.swift +303 -0
- package/dist/native/sks-menubar/Sources/TelegramProcessGateway.swift +238 -0
- package/dist/native/sks-menubar/Sources/TelegramRuntimeSupport.swift +56 -0
- package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
- package/dist/native/sks-menubar/Sources/TelegramTransport.swift +474 -0
- package/dist/native/sks-menubar/Sources/main.swift +15 -1
- package/dist/native/sks-menubar/Tests/OperationCoordinatorTests.swift +4 -3
- package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +129 -0
- package/dist/native/sks-menubar/Tests/SingletonInstanceGuardTests.swift +183 -0
- package/dist/native/sks-menubar/Tests/TelegramRuntimeSmokeTests.swift +267 -0
- package/dist/native/sks-menubar/Tests/TelegramRuntimeTests.swift +222 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -1
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +1 -1
- package/dist/scripts/current-command-surface-check.js +2 -4
- package/dist/scripts/official-subagent-workflow-check.js +1 -1
- package/dist/scripts/packlist-performance-check.js +1 -2
- package/package.json +1 -1
|
@@ -13,14 +13,42 @@ import { escapeRegExp } from '../core/text/regex.js';
|
|
|
13
13
|
export const CODEX_LB_DESKTOP_BRIDGE_MARKER = '# sks-codex-lb-managed-desktop-bridge';
|
|
14
14
|
export const CODEX_LB_DESKTOP_COMPAT_MARKER = '# sks-codex-lb-managed-desktop-compat';
|
|
15
15
|
export const CODEX_LB_MODEL_CATALOG_MARKER = '# sks-codex-lb-managed-model-catalog';
|
|
16
|
-
const
|
|
16
|
+
export const CODEX_LB_PROVIDER_SELECTION_MARKER = '# sks-codex-lb-managed-provider-selection';
|
|
17
|
+
export const CODEX_LB_OAUTH_SELECTION_MARKER = '# sks-codex-lb-managed-oauth-selection';
|
|
18
|
+
export const LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER = '# sks-codex-lb-managed-openai-base-url';
|
|
19
|
+
export function removeCodexLbOrphanManagedMarkers(text) {
|
|
20
|
+
const source = String(text || '');
|
|
21
|
+
const selectedProvider = topLevelTomlString(source, 'model_provider');
|
|
22
|
+
const markerTargets = [
|
|
23
|
+
[CODEX_LB_DESKTOP_BRIDGE_MARKER, Boolean(topLevelTomlString(source, 'openai_base_url'))],
|
|
24
|
+
[LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER, Boolean(topLevelTomlString(source, 'openai_base_url'))],
|
|
25
|
+
[CODEX_LB_DESKTOP_COMPAT_MARKER, selectedProvider === 'codex-lb'],
|
|
26
|
+
[CODEX_LB_MODEL_CATALOG_MARKER, Boolean(topLevelTomlString(source, 'model_catalog_json'))],
|
|
27
|
+
[CODEX_LB_PROVIDER_SELECTION_MARKER, selectedProvider === 'codex-lb'],
|
|
28
|
+
[CODEX_LB_OAUTH_SELECTION_MARKER, selectedProvider === 'openai']
|
|
29
|
+
];
|
|
30
|
+
const orphanMarkers = markerTargets
|
|
31
|
+
.filter(([marker, hasManagedContent]) => topLevelHasLine(source, marker) && !hasManagedContent)
|
|
32
|
+
.map(([marker]) => marker);
|
|
33
|
+
let next = source;
|
|
34
|
+
for (const marker of orphanMarkers)
|
|
35
|
+
next = removeTopLevelLine(next, marker);
|
|
36
|
+
return {
|
|
37
|
+
schema: 'sks.codex-lb-orphan-managed-marker-cleanup.v1',
|
|
38
|
+
changed: orphanMarkers.length > 0,
|
|
39
|
+
orphan_markers: orphanMarkers,
|
|
40
|
+
text: next
|
|
41
|
+
};
|
|
42
|
+
}
|
|
17
43
|
export function upsertCodexLbNativeDesktopConfig(text, input) {
|
|
18
|
-
let next = String(text || '');
|
|
44
|
+
let next = removeCodexLbOrphanManagedMarkers(String(text || '')).text;
|
|
19
45
|
const selectedProvider = topLevelTomlString(next, 'model_provider');
|
|
20
46
|
if (selectedProvider && selectedProvider !== 'openai' && selectedProvider !== 'codex-lb') {
|
|
21
47
|
throw new Error('codex_lb_user_owned_model_provider_conflict');
|
|
22
48
|
}
|
|
23
|
-
if (selectedProvider === 'codex-lb'
|
|
49
|
+
if (selectedProvider === 'codex-lb'
|
|
50
|
+
&& !topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)
|
|
51
|
+
&& !topLevelHasLine(next, CODEX_LB_PROVIDER_SELECTION_MARKER)) {
|
|
24
52
|
throw new Error('codex_lb_legacy_desktop_config_requires_migration');
|
|
25
53
|
}
|
|
26
54
|
if (topLevelHasLine(next, LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER)
|
|
@@ -31,10 +59,10 @@ export function upsertCodexLbNativeDesktopConfig(text, input) {
|
|
|
31
59
|
if (modelCatalog && !topLevelHasLine(next, CODEX_LB_MODEL_CATALOG_MARKER)) {
|
|
32
60
|
throw new Error('codex_lb_user_owned_model_catalog_json_conflict');
|
|
33
61
|
}
|
|
34
|
-
next =
|
|
62
|
+
next = removeManagedCodexLbSelection(next);
|
|
35
63
|
next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
|
|
36
64
|
next = removeManagedModelCatalogJson(next);
|
|
37
|
-
next = upsertManagedTopLevelTomlString(next, 'openai_base_url', input.bridgeBaseUrl, CODEX_LB_DESKTOP_BRIDGE_MARKER);
|
|
65
|
+
next = upsertManagedTopLevelTomlString(next, 'openai_base_url', input.bridgeBaseUrl, CODEX_LB_DESKTOP_BRIDGE_MARKER, [LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER]);
|
|
38
66
|
next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
|
|
39
67
|
return ensureTrailingNewline(next);
|
|
40
68
|
}
|
|
@@ -55,19 +83,50 @@ export function upsertCodexLbCompatDesktopConfig(text, input) {
|
|
|
55
83
|
return ensureTrailingNewline(next);
|
|
56
84
|
}
|
|
57
85
|
export function upsertCodexLbCliProviderConfig(text, input) {
|
|
86
|
+
const cleaned = removeCodexLbOrphanManagedMarkers(String(text || '')).text;
|
|
87
|
+
if (topLevelHasLine(cleaned, LEGACY_CODEX_LB_OPENAI_ROUTING_MARKER)) {
|
|
88
|
+
throw new Error('codex_lb_legacy_desktop_config_requires_migration');
|
|
89
|
+
}
|
|
90
|
+
const cliBase = removeCodexLbManagedDesktopConfig(cleaned);
|
|
91
|
+
const claimedSelection = input.selectGlobally === true
|
|
92
|
+
&& topLevelTomlString(cliBase, 'model_provider') === 'codex-lb'
|
|
93
|
+
&& !topLevelHasLine(cliBase, CODEX_LB_PROVIDER_SELECTION_MARKER)
|
|
94
|
+
? addTopLevelMarkerBeforeKey(cliBase, 'model_provider', CODEX_LB_PROVIDER_SELECTION_MARKER)
|
|
95
|
+
: cliBase;
|
|
58
96
|
let next = input.selectGlobally === true
|
|
59
|
-
?
|
|
60
|
-
:
|
|
97
|
+
? upsertManagedTopLevelTomlString(removeTopLevelTomlKeyIfValue(removeManagedOAuthSelection(claimedSelection), 'model_provider', 'openai'), 'model_provider', 'codex-lb', CODEX_LB_PROVIDER_SELECTION_MARKER)
|
|
98
|
+
: removeManagedCodexLbSelection(cliBase);
|
|
61
99
|
next = upsertTomlTable(next, 'model_providers.codex-lb', cliProviderBlock(input.remoteBaseUrl));
|
|
62
100
|
return ensureTrailingNewline(next);
|
|
63
101
|
}
|
|
102
|
+
export function restoreCodexLbOAuthSelectionConfig(text) {
|
|
103
|
+
let next = removeManagedCodexLbSelection(String(text || ''));
|
|
104
|
+
next = upsertManagedTopLevelTomlString(next, 'model_provider', 'openai', CODEX_LB_OAUTH_SELECTION_MARKER);
|
|
105
|
+
return ensureTrailingNewline(next);
|
|
106
|
+
}
|
|
107
|
+
export function removeManagedCodexLbSelection(text) {
|
|
108
|
+
let next = removeTopLevelTomlKeyIfValue(String(text || ''), 'model_provider', 'codex-lb');
|
|
109
|
+
next = removeTopLevelLine(next, CODEX_LB_PROVIDER_SELECTION_MARKER);
|
|
110
|
+
return next;
|
|
111
|
+
}
|
|
112
|
+
function removeManagedOAuthSelection(text) {
|
|
113
|
+
let next = String(text || '');
|
|
114
|
+
if (topLevelHasLine(next, CODEX_LB_OAUTH_SELECTION_MARKER)) {
|
|
115
|
+
next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'openai');
|
|
116
|
+
next = removeTopLevelLine(next, CODEX_LB_OAUTH_SELECTION_MARKER);
|
|
117
|
+
}
|
|
118
|
+
return next;
|
|
119
|
+
}
|
|
64
120
|
export function removeCodexLbManagedDesktopConfig(text) {
|
|
65
|
-
let next = removeManagedDesktopBridgeRouting(String(text || ''));
|
|
121
|
+
let next = removeManagedDesktopBridgeRouting(removeCodexLbOrphanManagedMarkers(String(text || '')).text);
|
|
66
122
|
if (topLevelHasLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER)) {
|
|
67
123
|
next = removeTopLevelTomlKeyIfValue(next, 'model_provider', 'codex-lb');
|
|
68
124
|
next = removeTopLevelLine(next, CODEX_LB_DESKTOP_COMPAT_MARKER);
|
|
69
125
|
}
|
|
70
126
|
next = removeManagedModelCatalogJson(next);
|
|
127
|
+
if (topLevelTomlString(next, 'model_provider') === 'codex-lb') {
|
|
128
|
+
next = restoreCodexLbOAuthSelectionConfig(next);
|
|
129
|
+
}
|
|
71
130
|
return ensureTrailingNewline(next);
|
|
72
131
|
}
|
|
73
132
|
export function removeManagedModelCatalogJson(text) {
|
|
@@ -159,6 +218,13 @@ export function upsertCodexLbSharedOpenAiRouting(text = '', baseUrl = '') {
|
|
|
159
218
|
}
|
|
160
219
|
export function removeCodexLbSharedOpenAiRouting(text = '', baseUrl = '') {
|
|
161
220
|
const state = codexLbSharedOpenAiRoutingState(text, baseUrl);
|
|
221
|
+
if (state.status === 'missing' && state.managed) {
|
|
222
|
+
return {
|
|
223
|
+
...state,
|
|
224
|
+
changed: true,
|
|
225
|
+
text: removeTopLevelLine(String(text || ''), CODEX_LB_SHARED_OPENAI_ROUTING_MARKER)
|
|
226
|
+
};
|
|
227
|
+
}
|
|
162
228
|
if (state.status !== 'matched' || !state.managed)
|
|
163
229
|
return { ...state, changed: false, text: String(text || '') };
|
|
164
230
|
const withoutValue = removeTopLevelTomlKeyIfValue(text, 'openai_base_url', state.expected_base_url);
|
|
@@ -29,7 +29,7 @@ import { canAskYesNo, compareVersions, hasCodexUnstableFeatureWarningSuppression
|
|
|
29
29
|
import { printCodexLbSetupWarnings } from './codex-lb-setup-warning-output.js';
|
|
30
30
|
import { checkCodexLbResponseChain } from './install-helpers-codex-lb-chain.js';
|
|
31
31
|
import { CODEX_LB_CANONICAL_FAST_SERVICE_TIER, CODEX_LB_PROVIDER_ENV_KEY, askPostinstallQuestion, codexAuthChatgptBackupPath, codexAuthPath, codexLbConfigPath, codexLbEnvPath, hasTopLevelCodexLbSelected, normalizeCodexLbBaseUrl, parseCodexLbEnvKey, redactSecretText } from './install-helpers-codex-lb-shared.js';
|
|
32
|
-
import { CODEX_LB_DESKTOP_BRIDGE_MARKER, CODEX_LB_DESKTOP_COMPAT_MARKER, appliedCodexLbPersistenceModes, captureCodexLbSetupWriteState, codexLbSharedOpenAiRoutingState, detectCodexLbSetupDrift, ensureGlobalCodexAppGlmProfile, ensureStoredOpenRouterProviderDuringInstall, hardenCodexLbSetupRecoveryPath,
|
|
32
|
+
import { CODEX_LB_DESKTOP_BRIDGE_MARKER, CODEX_LB_DESKTOP_COMPAT_MARKER, CODEX_LB_PROVIDER_SELECTION_MARKER, appliedCodexLbPersistenceModes, captureCodexLbSetupWriteState, codexLbSharedOpenAiRoutingState, detectCodexLbSetupDrift, ensureGlobalCodexAppGlmProfile, ensureStoredOpenRouterProviderDuringInstall, hardenCodexLbSetupRecoveryPath, removeCodexLbSetupRecoveryPath, removeCodexLbOrphanManagedMarkers, removeCodexLbSharedOpenAiRouting, removeCodexLbManagedDesktopConfig, restoreCodexLbSetupWriteState, sha256Text, shellSingleQuote, upsertCodexAppGlmConfig, upsertCodexLbConfig, upsertCodexLbCliProviderConfig, upsertCodexLbCompatDesktopConfig, upsertCodexLbNativeDesktopConfig, upsertCodexLbSharedOpenAiRouting, writeCodexLbSetupFileIfUnchanged } from './install-helpers-codex-lb-config.js';
|
|
33
33
|
import { detectLegacyCodexLbDesktopState } from '../core/codex-lb/legacy-migration.js';
|
|
34
34
|
import { ensureCodexImagegenDuringInstall, ensureGlobalCodexSkillsDuringInstall, ensureGlobalContext7DuringInstall, ensureGlobalGetdesignSkillDuringInstall, ensureSksCommandDuringInstall } from './install-helpers-install-support.js';
|
|
35
35
|
import { escapeRegExp } from '../core/text/regex.js';
|
|
@@ -236,7 +236,7 @@ async function reportPostinstallCodexLbAuth(snapshot = null) {
|
|
|
236
236
|
else if (codexLbAuth.status === 'skipped')
|
|
237
237
|
console.log(`codex-lb auth: skipped (${codexLbAuth.reason}).`);
|
|
238
238
|
else if (codexLbAuth.status === 'missing_env_key')
|
|
239
|
-
console.log('codex-lb auth: stored key missing.
|
|
239
|
+
console.log('codex-lb auth: stored key missing. Store it in ~/.codex/sks-codex-lb.env, run `sks codex-lb setup --host <domain> --api-key-stdin --yes`, or provide CODEX_LB_API_KEY in the environment.');
|
|
240
240
|
else if (codexLbAuth.status === 'missing_base_url')
|
|
241
241
|
console.log('codex-lb auth: stored key has no recoverable base URL. Run `sks codex-lb reconfigure --host <domain> --api-key-stdin` once.');
|
|
242
242
|
else if (codexLbAuth.status === 'legacy_migration_required')
|
|
@@ -557,17 +557,16 @@ function codexLbRoutingPlane(mode) {
|
|
|
557
557
|
return 'desktop_compat_provider';
|
|
558
558
|
return 'cli_provider';
|
|
559
559
|
}
|
|
560
|
-
async function capturePostinstallCodexLbConfigSnapshot(home = process.env.HOME || os.homedir()) {
|
|
560
|
+
export async function capturePostinstallCodexLbConfigSnapshot(home = process.env.HOME || os.homedir()) {
|
|
561
561
|
const configPath = codexLbConfigPath(home);
|
|
562
562
|
const envPath = codexLbEnvPath(home);
|
|
563
563
|
const authPath = codexAuthPath(home);
|
|
564
564
|
const config = await readText(configPath, '');
|
|
565
|
-
const envText = await readText(envPath, '');
|
|
566
565
|
const auth = await captureCodexAuthSnapshot({ home, authPath });
|
|
567
566
|
const envLoad = await loadCodexLbEnv({ home, envPath });
|
|
568
567
|
const envKey = envLoad.secret_api_key || '';
|
|
569
568
|
const providerConfigured = /\[model_providers\.codex-lb\]/.test(config);
|
|
570
|
-
const baseUrl = envLoad.base_url || codexLbProviderBaseUrl(config)
|
|
569
|
+
const baseUrl = envLoad.base_url || codexLbProviderBaseUrl(config);
|
|
571
570
|
const desktopMode = managedCodexLbDesktopMode(config);
|
|
572
571
|
const bridgeBaseUrl = desktopMode === 'desktop-native-bridge'
|
|
573
572
|
? topLevelTomlString(config, 'openai_base_url')
|
|
@@ -590,7 +589,7 @@ async function capturePostinstallCodexLbConfigSnapshot(home = process.env.HOME |
|
|
|
590
589
|
secret_api_key: envKey || null
|
|
591
590
|
};
|
|
592
591
|
}
|
|
593
|
-
async function restorePostinstallCodexLbConfigSnapshot(snapshot) {
|
|
592
|
+
export async function restorePostinstallCodexLbConfigSnapshot(snapshot) {
|
|
594
593
|
if (!snapshot)
|
|
595
594
|
return { status: 'skipped', reason: 'no_snapshot' };
|
|
596
595
|
let configRestored = false;
|
|
@@ -608,15 +607,12 @@ async function restorePostinstallCodexLbConfigSnapshot(snapshot) {
|
|
|
608
607
|
else if (snapshot.desktop_mode === 'desktop-dual-auth-compat') {
|
|
609
608
|
next = upsertCodexLbCompatDesktopConfig(current, { remoteBaseUrl: snapshot.base_url });
|
|
610
609
|
}
|
|
611
|
-
else
|
|
610
|
+
else {
|
|
612
611
|
next = upsertCodexLbCliProviderConfig(current, {
|
|
613
612
|
remoteBaseUrl: snapshot.base_url,
|
|
614
|
-
selectGlobally:
|
|
613
|
+
selectGlobally: snapshot.selected === true
|
|
615
614
|
});
|
|
616
615
|
}
|
|
617
|
-
else {
|
|
618
|
-
configStatus = 'legacy_migration_required';
|
|
619
|
-
}
|
|
620
616
|
}
|
|
621
617
|
catch (error) {
|
|
622
618
|
return {
|
|
@@ -629,7 +625,7 @@ async function restorePostinstallCodexLbConfigSnapshot(snapshot) {
|
|
|
629
625
|
error: error instanceof Error ? error.message : String(error)
|
|
630
626
|
};
|
|
631
627
|
}
|
|
632
|
-
if (
|
|
628
|
+
if (ensureTrailingNewline(next) !== ensureTrailingNewline(current)) {
|
|
633
629
|
const safeWrite = await safeWriteCodexConfigToml(snapshot.config_path, current, next, 'codex-lb-safe-routing-restore', { verifyUnchangedBeforeWrite: true });
|
|
634
630
|
configRestored = safeWrite.ok && safeWrite.changed === true;
|
|
635
631
|
configStatus = safeWrite.ok ? (configRestored ? 'restored' : 'present') : safeWrite.status;
|
|
@@ -728,7 +724,11 @@ export async function configureCodexLb(opts = {}) {
|
|
|
728
724
|
? Buffer.from(String(configBeforeEntry.bytes_base64 || ''), 'base64').toString('utf8')
|
|
729
725
|
: '';
|
|
730
726
|
const preservedDesktopMode = managedCodexLbDesktopMode(initialConfig);
|
|
731
|
-
const
|
|
727
|
+
const managedCliSelection = hasTopLevelMarker(initialConfig, CODEX_LB_PROVIDER_SELECTION_MARKER)
|
|
728
|
+
&& hasTopLevelCodexLbSelected(initialConfig);
|
|
729
|
+
const preservedLegacySelection = hasTopLevelCodexLbSelected(initialConfig)
|
|
730
|
+
&& !preservedDesktopMode
|
|
731
|
+
&& !managedCliSelection;
|
|
732
732
|
const desktopMode = preservedDesktopMode || 'cli-provider';
|
|
733
733
|
if (desktopModeRequiresGlobalSecretEnvironment(desktopMode)) {
|
|
734
734
|
return {
|
|
@@ -739,11 +739,15 @@ export async function configureCodexLb(opts = {}) {
|
|
|
739
739
|
error: 'desktop_dual_auth_compat_requires_global_secret_environment'
|
|
740
740
|
};
|
|
741
741
|
}
|
|
742
|
-
const useDefaultProvider = desktopMode === 'desktop-dual-auth-compat'
|
|
742
|
+
const useDefaultProvider = desktopMode === 'desktop-dual-auth-compat'
|
|
743
|
+
|| preservedLegacySelection
|
|
744
|
+
|| managedCliSelection
|
|
745
|
+
|| (desktopMode === 'cli-provider' && opts.useDefaultProvider === true);
|
|
743
746
|
const setupAnswers = {
|
|
744
747
|
host_or_base_url: rawHost,
|
|
745
748
|
api_key_source: opts.apiKeySource || 'stdin',
|
|
746
749
|
desktop_mode: 'cli-provider',
|
|
750
|
+
use_as_default_provider: useDefaultProvider,
|
|
747
751
|
gateway_auth_transport: (opts.gatewayAuthTransport || DEFAULT_CODEX_LB_GATEWAY_AUTH_TRANSPORT),
|
|
748
752
|
write_env_file: writeEnvFile,
|
|
749
753
|
store_keychain: storeKeychain,
|
|
@@ -823,7 +827,7 @@ export async function configureCodexLb(opts = {}) {
|
|
|
823
827
|
else if (!preservedLegacySelection) {
|
|
824
828
|
providerOnly = upsertCodexLbCliProviderConfig(current, {
|
|
825
829
|
remoteBaseUrl: baseUrl,
|
|
826
|
-
selectGlobally:
|
|
830
|
+
selectGlobally: useDefaultProvider
|
|
827
831
|
});
|
|
828
832
|
}
|
|
829
833
|
}
|
|
@@ -1235,7 +1239,7 @@ export async function configureCodexLb(opts = {}) {
|
|
|
1235
1239
|
}
|
|
1236
1240
|
const skipLaunchEnvironment = opts.syncLaunchEnv === false
|
|
1237
1241
|
|| process.env.SKS_SKIP_CODEX_LB_LAUNCH_ENV === '1';
|
|
1238
|
-
const {
|
|
1242
|
+
const { repairCodexLbLegacyKeychainMigration, syncDesktopCenterLaunchCredentials } = await import('../core/codex-lb/desktop-center-credentials.js');
|
|
1239
1243
|
const centerCredentials = skipLaunchEnvironment
|
|
1240
1244
|
? {
|
|
1241
1245
|
schema: 'sks.codex-lb-desktop-center-credentials.v1',
|
|
@@ -1493,43 +1497,36 @@ export async function configureCodexLb(opts = {}) {
|
|
|
1493
1497
|
};
|
|
1494
1498
|
if ((opts.platform || process.platform) === 'darwin' && writeEnvFile && !storeKeychain) {
|
|
1495
1499
|
await opts.testHooks?.beforeLegacyKeychainCleanup?.({ envPath, metadataPath });
|
|
1496
|
-
const
|
|
1500
|
+
const migration = await repairCodexLbLegacyKeychainMigration({
|
|
1497
1501
|
home,
|
|
1502
|
+
baseUrl,
|
|
1498
1503
|
envPath,
|
|
1499
1504
|
metadataPath,
|
|
1500
1505
|
account: opts.account || process.env.USER || 'sks',
|
|
1501
|
-
|
|
1502
|
-
});
|
|
1503
|
-
const cleanup = await purgeStaleCodexLbCredentialTwins({
|
|
1504
|
-
home,
|
|
1505
|
-
account: opts.account || process.env.USER || 'sks',
|
|
1506
|
-
platform: 'darwin',
|
|
1507
|
-
skipStaleEnvTwins: true,
|
|
1506
|
+
platform: opts.platform || process.platform,
|
|
1508
1507
|
...(opts.securityBin ? { securityBin: opts.securityBin } : {}),
|
|
1509
1508
|
...(opts.runProcessImpl ? { runProcessImpl: opts.runProcessImpl } : {}),
|
|
1510
|
-
|
|
1511
|
-
? { legacyKeychainMigrationReceipt: replacement.receipt }
|
|
1512
|
-
: {})
|
|
1509
|
+
expectedApiKeySha256: keyFingerprint
|
|
1513
1510
|
});
|
|
1514
|
-
const cleanupBlockers = [
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1511
|
+
const cleanupBlockers = [...new Set(migration.blockers)];
|
|
1512
|
+
const replacementStoreVerified = migration.env_key_valid
|
|
1513
|
+
&& migration.status !== 'replacement_store_unverified'
|
|
1514
|
+
&& migration.status !== 'env_file_unsafe';
|
|
1515
|
+
const cleanupOk = replacementStoreVerified
|
|
1516
|
+
&& migration.ok
|
|
1517
|
+
&& cleanupBlockers.length === 0;
|
|
1521
1518
|
legacyKeychainCleanup = {
|
|
1522
1519
|
ok: cleanupOk,
|
|
1523
|
-
status: !
|
|
1520
|
+
status: !replacementStoreVerified
|
|
1524
1521
|
? 'legacy_keychain_cleanup_blocked_replacement_store_unverified'
|
|
1525
|
-
:
|
|
1526
|
-
?
|
|
1522
|
+
: cleanupOk
|
|
1523
|
+
? migration.keychain_cleared.length > 0
|
|
1527
1524
|
? 'legacy_keychain_removed'
|
|
1528
1525
|
: 'legacy_keychain_absent'
|
|
1529
1526
|
: 'legacy_keychain_cleanup_failed_secure_store_retained',
|
|
1530
|
-
replacement_store_verified:
|
|
1531
|
-
keychain_cleared:
|
|
1532
|
-
blockers:
|
|
1527
|
+
replacement_store_verified: replacementStoreVerified,
|
|
1528
|
+
keychain_cleared: migration.keychain_cleared,
|
|
1529
|
+
blockers: cleanupBlockers
|
|
1533
1530
|
};
|
|
1534
1531
|
appliedActions.push({
|
|
1535
1532
|
type: 'migrate_legacy_keychain',
|
|
@@ -1601,9 +1598,10 @@ export async function codexLbStatus(opts = {}) {
|
|
|
1601
1598
|
const home = opts.home || process.env.HOME || os.homedir();
|
|
1602
1599
|
const configPath = opts.configPath || codexLbConfigPath(home);
|
|
1603
1600
|
const envPath = opts.envPath || codexLbEnvPath(home);
|
|
1604
|
-
const
|
|
1601
|
+
const rawConfig = await readText(configPath, '');
|
|
1602
|
+
const orphanManagedMarkerCleanup = removeCodexLbOrphanManagedMarkers(rawConfig);
|
|
1603
|
+
const config = orphanManagedMarkerCleanup.text;
|
|
1605
1604
|
const envExists = await exists(envPath);
|
|
1606
|
-
const envText = envExists ? await readText(envPath, '') : '';
|
|
1607
1605
|
const envLoad = await loadCodexLbEnv({ ...opts, home, envPath });
|
|
1608
1606
|
const authPath = opts.authPath || codexAuthPath(home);
|
|
1609
1607
|
const authText = await readText(authPath, '');
|
|
@@ -1638,6 +1636,7 @@ export async function codexLbStatus(opts = {}) {
|
|
|
1638
1636
|
&& providerSupportsWebsockets === true
|
|
1639
1637
|
&& providerOpenAiAuthDisabled;
|
|
1640
1638
|
const retiredCompatConfigured = desktopMode === 'desktop-dual-auth-compat';
|
|
1639
|
+
const definedButNotSelected = providerConfigured && !selected && desktopMode === null;
|
|
1641
1640
|
const providerContractOk = !retiredCompatConfigured && cliProviderContractOk;
|
|
1642
1641
|
const providerUsesCodexLbEnvAuth = providerConfigured && providerEnvKey === CODEX_LB_PROVIDER_ENV_KEY && providerOpenAiAuthDisabled;
|
|
1643
1642
|
const oauthAvailable = authMode.mode === 'chatgpt_oauth' || authMode.mode === 'browser_marker';
|
|
@@ -1682,9 +1681,23 @@ export async function codexLbStatus(opts = {}) {
|
|
|
1682
1681
|
allowUnverified: opts.allowUnverifiedToolOutputRecovery === true
|
|
1683
1682
|
|| codexLbToolOutputRecoveryOverrideAcknowledged({ env: opts.env || process.env })
|
|
1684
1683
|
});
|
|
1684
|
+
const secretResolution = {
|
|
1685
|
+
source: envLoad.source,
|
|
1686
|
+
path: envLoad.source === 'env-file' ? envLoad.env_paths[0] || envPath : null,
|
|
1687
|
+
prompt_risk: 'none'
|
|
1688
|
+
};
|
|
1685
1689
|
return {
|
|
1686
1690
|
ok: providerReady && (!selected || !probeToolOutputRecovery || toolOutputRecovery.ok),
|
|
1687
1691
|
blockers,
|
|
1692
|
+
warnings: definedButNotSelected ? ['codex_lb_defined_but_not_selected'] : [],
|
|
1693
|
+
orphan_managed_markers: orphanManagedMarkerCleanup.orphan_markers,
|
|
1694
|
+
managed_marker_cleanup_required: orphanManagedMarkerCleanup.changed,
|
|
1695
|
+
activation_guidance: definedButNotSelected
|
|
1696
|
+
? [
|
|
1697
|
+
'Run `sks codex-lb use-cli` to select the CLI provider.',
|
|
1698
|
+
'Run `sks codex-lb use-desktop-full` to activate managed Desktop bridge mode.'
|
|
1699
|
+
]
|
|
1700
|
+
: [],
|
|
1688
1701
|
provider_ready: providerReady,
|
|
1689
1702
|
config_path: configPath,
|
|
1690
1703
|
env_path: envPath,
|
|
@@ -1717,10 +1730,13 @@ export async function codexLbStatus(opts = {}) {
|
|
|
1717
1730
|
source: envLoad.source,
|
|
1718
1731
|
source_priority: envLoad.source_priority,
|
|
1719
1732
|
api_key: envLoad.api_key,
|
|
1733
|
+
blockers: envLoad.blockers,
|
|
1734
|
+
guidance: envLoad.guidance,
|
|
1720
1735
|
credential_binding: envLoad.credential_binding,
|
|
1721
1736
|
keychain: envLoad.keychain,
|
|
1722
1737
|
env_paths: envLoad.env_paths
|
|
1723
1738
|
},
|
|
1739
|
+
secret_resolution: secretResolution,
|
|
1724
1740
|
base_url: baseUrl,
|
|
1725
1741
|
auth_path: authPath,
|
|
1726
1742
|
auth_mode: authMode.mode,
|
|
@@ -1746,6 +1762,19 @@ export async function codexLbStatus(opts = {}) {
|
|
|
1746
1762
|
export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
1747
1763
|
const backupPresent = Boolean(opts.backupPresent);
|
|
1748
1764
|
const backupPath = opts.backupPath || '';
|
|
1765
|
+
const resolution = status.secret_resolution || {};
|
|
1766
|
+
const resolutionSource = String(resolution.source || status.env_loader?.source || 'missing');
|
|
1767
|
+
const resolutionPath = resolution.path
|
|
1768
|
+
|| (resolutionSource === 'env-file' ? status.env_loader?.env_paths?.[0] || status.env_path : null);
|
|
1769
|
+
const displayResolutionPath = resolutionPath
|
|
1770
|
+
? formatCodexLbStatusPath(String(resolutionPath), opts.home || os.homedir())
|
|
1771
|
+
: '';
|
|
1772
|
+
const resolutionLabel = displayResolutionPath
|
|
1773
|
+
? `${resolutionSource} (${displayResolutionPath})`
|
|
1774
|
+
: resolutionSource;
|
|
1775
|
+
const keychainUsage = resolutionSource === 'keychain' ? 'used' : 'not used';
|
|
1776
|
+
const promptRisk = String(resolution.prompt_risk
|
|
1777
|
+
|| (resolutionSource === 'keychain' ? 'possible' : 'none'));
|
|
1749
1778
|
const lines = [
|
|
1750
1779
|
'SKS codex-lb',
|
|
1751
1780
|
'',
|
|
@@ -1755,7 +1784,8 @@ export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
|
1755
1784
|
`Provider OpenAI Auth: ${status.provider_requires_openai_auth ? 'required' : 'not required/drifted'} (${status.provider_name || 'missing'})`,
|
|
1756
1785
|
`Codex App auth: ${status.auth_usable_for_codex_app ? 'ok' : 'needs sign-in/repair'} (${status.auth_mode || 'unknown'})`,
|
|
1757
1786
|
`Shared OpenAI routing: ${status.shared_openai_routing?.safe === false ? 'unsafe' : status.shared_openai_routing?.status || 'unknown'}${status.shared_openai_routing?.managed ? ' (sks-managed)' : ''}`,
|
|
1758
|
-
`Auth/routing coherent: ${status.auth_routing_coherent ? 'yes' : 'no'}
|
|
1787
|
+
`Auth/routing coherent: ${status.auth_routing_coherent ? 'yes' : 'no'}`,
|
|
1788
|
+
`Key source: ${resolutionLabel} · keychain: ${keychainUsage} · prompt risk: ${promptRisk}`
|
|
1759
1789
|
];
|
|
1760
1790
|
if (status.tool_output_recovery?.status && status.tool_output_recovery.status !== 'not_selected') {
|
|
1761
1791
|
const recovery = status.tool_output_recovery;
|
|
@@ -1777,13 +1807,18 @@ export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
|
1777
1807
|
if (status.base_url)
|
|
1778
1808
|
lines.push(`Base URL: ${status.base_url}`);
|
|
1779
1809
|
lines.push(`ChatGPT backup: ${backupPresent ? `yes (${backupPath})` : 'no'}`);
|
|
1810
|
+
if ((status.warnings || []).includes('codex_lb_defined_but_not_selected')) {
|
|
1811
|
+
lines.push('', 'Warning [codex_lb_defined_but_not_selected]: the codex-lb provider is defined but not selected.');
|
|
1812
|
+
for (const action of status.activation_guidance || [])
|
|
1813
|
+
lines.push(` ${action}`);
|
|
1814
|
+
}
|
|
1780
1815
|
if (status.legacy_migration_required || status.shared_openai_routing?.safe === false)
|
|
1781
1816
|
lines.push('', 'Run: sks codex-lb migrate-legacy-desktop --restart-app. Ordinary repair will not rewrite shared Codex auth.');
|
|
1782
1817
|
else if (status.provider_configured && !status.provider_contract_ok)
|
|
1783
1818
|
lines.push('', 'Run: sks codex-lb repair to rewrite the provider block to the current codex-lb App contract.');
|
|
1784
1819
|
else if (status.desktop_mode === 'desktop-native-bridge' && !status.auth_usable_for_codex_app)
|
|
1785
1820
|
lines.push('', 'Sign in with ChatGPT OAuth, then run: sks codex-lb use-desktop-full.');
|
|
1786
|
-
else if (status.ok && status.desktop_mode === 'cli-provider' && !status.selected)
|
|
1821
|
+
else if (status.ok && status.desktop_mode === 'cli-provider' && !status.selected && !(status.warnings || []).includes('codex_lb_defined_but_not_selected'))
|
|
1787
1822
|
lines.push('', 'CLI provider is stored but unselected. Run `sks codex-lb use-cli` for CLI use or `sks codex-lb use-desktop-full` for managed Desktop routing.');
|
|
1788
1823
|
else if (status.desktop_mode === 'desktop-dual-auth-compat')
|
|
1789
1824
|
lines.push('', 'The retired compatibility route is blocked. Run `sks codex-lb use-desktop-full` or `sks codex-lb disable`.');
|
|
@@ -1791,12 +1826,22 @@ export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
|
1791
1826
|
lines.push('', 'Status: configured; no ordinary repair needed.');
|
|
1792
1827
|
else if (!status.ok && status.base_url && status.env_key_configured)
|
|
1793
1828
|
lines.push('', 'Run: sks codex-lb repair. To change routing explicitly, use `use-desktop-full`, `use-cli`, or `disable`.');
|
|
1829
|
+
else if (!status.ok && !status.env_key_configured)
|
|
1830
|
+
lines.push('', 'Gateway key missing. Store CODEX_LB_API_KEY in ~/.codex/sks-codex-lb.env, run `sks codex-lb setup --host <domain> --api-key-stdin --yes`, or provide CODEX_LB_API_KEY in the environment.');
|
|
1794
1831
|
else if (!status.ok)
|
|
1795
1832
|
lines.push('', 'Run: sks codex-lb setup --host <domain> --api-key-stdin');
|
|
1796
1833
|
if (backupPresent)
|
|
1797
1834
|
lines.push('Legacy OAuth backup detected; use `sks codex-lb migrate-legacy-desktop --restart-app` instead of background auth switching.');
|
|
1798
1835
|
return `${lines.join('\n')}\n`;
|
|
1799
1836
|
}
|
|
1837
|
+
function formatCodexLbStatusPath(file, home) {
|
|
1838
|
+
const resolvedFile = path.resolve(file);
|
|
1839
|
+
const resolvedHome = path.resolve(String(home || ''));
|
|
1840
|
+
const relative = path.relative(resolvedHome, resolvedFile);
|
|
1841
|
+
return relative && relative !== '..' && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative)
|
|
1842
|
+
? `~/${relative.split(path.sep).join('/')}`
|
|
1843
|
+
: file;
|
|
1844
|
+
}
|
|
1800
1845
|
export function formatCodexLbRepairResultText(result = {}) {
|
|
1801
1846
|
const lines = [
|
|
1802
1847
|
'codex-lb credential/provider configuration repaired without changing Codex shared auth.',
|