sneakoscope 7.3.0 → 7.6.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.
- package/README.md +129 -10
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/codex-app-command.js +1 -1
- package/dist/cli/command-manifest-lite.js +4 -1
- package/dist/cli/command-registry.js +2 -0
- package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
- package/dist/cli/install-helpers-codex-lb-config.js +114 -9
- package/dist/cli/install-helpers-install-support.js +6 -16
- package/dist/cli/install-helpers.js +788 -600
- package/dist/cli/router.js +30 -2
- package/dist/commands/codex-app.js +37 -1
- package/dist/commands/codex-lb.js +491 -300
- package/dist/config/skills-manifest.json +57 -71
- package/dist/core/align/align-route.js +127 -0
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
- package/dist/core/codex-app/codex-app-restart.js +83 -0
- package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
- package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
- package/dist/core/codex-app/menubar/constants.js +5 -0
- package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
- package/dist/core/codex-app/menubar/installer.js +18 -0
- package/dist/core/codex-app/multi-provider-router.js +22 -10
- package/dist/core/codex-app/openrouter-activate.js +26 -1
- package/dist/core/codex-app.js +118 -26
- package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
- package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
- package/dist/core/codex-control/codex-task-runner.js +2 -2
- package/dist/core/codex-lb/capability-runner.js +204 -0
- package/dist/core/codex-lb/capability-types.js +1 -0
- package/dist/core/codex-lb/codex-lb-env.js +9 -13
- package/dist/core/codex-lb/codex-lb-setup.js +45 -8
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
- package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
- package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
- package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
- package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
- package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
- package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
- package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
- package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
- package/dist/core/codex-lb/desktop-controller.js +1410 -0
- package/dist/core/codex-lb/desktop-mode.js +32 -0
- package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
- package/dist/core/codex-lb/desktop-service.js +613 -0
- package/dist/core/codex-lb/legacy-migration.js +575 -0
- package/dist/core/codex-lb/migration-receipt.js +246 -0
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
- package/dist/core/codex-lb/probes/bridge-probe.js +75 -0
- package/dist/core/codex-lb/probes/catalog-probe.js +128 -0
- package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
- package/dist/core/codex-lb/probes/image-generation-probe.js +47 -0
- package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
- package/dist/core/codex-native/core-skill-manifest.js +22 -6
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
- package/dist/core/commands/align-command.js +220 -0
- package/dist/core/commands/image-ux-review-command.js +280 -68
- package/dist/core/commands/naruto-command.js +257 -8
- package/dist/core/commands/ppt-command.js +2 -2
- package/dist/core/commands/telegram-command.js +402 -34
- package/dist/core/commands/triwiki-command.js +11 -1
- package/dist/core/commands/triwiki-graph-command.js +160 -0
- package/dist/core/commands/wiki-command.js +100 -20
- package/dist/core/doctor/skill-legacy-surface.js +1 -3
- package/dist/core/errors/message.js +3 -0
- package/dist/core/evidence/evidence-freshness.js +14 -0
- package/dist/core/feature-fixtures.js +9 -1
- package/dist/core/feature-registry.js +5 -3
- package/dist/core/fsx.js +7 -3
- package/dist/core/hooks-runtime/codex-commit-hooks-selftest.js +82 -0
- package/dist/core/hooks-runtime/context-graph-freshness-preflight.js +113 -0
- package/dist/core/hooks-runtime/hook-context.js +15 -2
- package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
- package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
- package/dist/core/hooks-runtime/official-subagent-lifecycle.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +33 -89
- package/dist/core/image-ux-review/callout-extraction.js +6 -0
- package/dist/core/image-ux-review/imagegen-adapter.js +64 -23
- package/dist/core/image-ux-review/real-callout-extractor.js +1 -0
- package/dist/core/image-ux-review.js +230 -12
- package/dist/core/imagegen/codex-lb-imagegen-target.js +21 -7
- package/dist/core/imagegen/imagegen-capability.js +10 -4
- package/dist/core/imagegen/require-imagegen.js +29 -5
- package/dist/core/init/skills.js +25 -13
- package/dist/core/init.js +1 -1
- package/dist/core/install/installed-package-smoke.js +157 -4
- package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
- package/dist/core/managed-path-safety.js +8 -10
- package/dist/core/mcp-config/backup.js +2 -4
- package/dist/core/mcp-config/config-reader.js +2 -4
- package/dist/core/mcp-config/scope.js +3 -5
- package/dist/core/naruto/context-graph-advisor-scope.js +242 -0
- package/dist/core/naruto/context-graph-advisor.js +0 -0
- package/dist/core/perf/release-latency-slo.js +12 -6
- package/dist/core/pipeline-internals/runtime-core.js +78 -0
- package/dist/core/pipeline-internals/runtime-gates.js +5 -2
- package/dist/core/policy/latest-version-guidance.js +113 -0
- package/dist/core/ppt.js +8 -8
- package/dist/core/preflight/parallel-preflight-engine.js +1 -1
- package/dist/core/proof/auto-finalize.js +98 -6
- package/dist/core/proof/route-proof-gate.js +12 -1
- package/dist/core/proof/route-proof-policy.js +8 -8
- package/dist/core/release/gate-manifest.js +32 -1
- package/dist/core/release/npm-stage-contract.js +21 -0
- package/dist/core/release/package-size-budget.js +2 -2
- package/dist/core/release/release-gate-contract.js +5 -0
- package/dist/core/release/release-proof-io.js +1 -3
- package/dist/core/release/release-real-contract.js +5 -4
- package/dist/core/release/release-stamp-proof.js +1 -3
- package/dist/core/release/stage-publish.js +27 -0
- package/dist/core/remote/audit-idempotency.js +50 -18
- package/dist/core/remote/codex-public-activity.js +283 -0
- package/dist/core/remote/index.js +1 -0
- package/dist/core/remote/ssh-worker-client.js +4 -1
- package/dist/core/remote/worker.js +206 -27
- package/dist/core/research/research-adversarial-review.js +1 -3
- package/dist/core/research/research-claim-synthesizer.js +1 -3
- package/dist/core/research/research-falsification-runner.js +1 -3
- package/dist/core/research/research-source-evidence.js +1 -3
- package/dist/core/responses-stream.js +65 -19
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/design-policy.js +7 -2
- package/dist/core/routes/dollar-manifest-lite.js +2 -4
- package/dist/core/routes/evidence.js +1 -1
- package/dist/core/routes.js +30 -10
- package/dist/core/safety/command-contract/contracts.js +2 -0
- package/dist/core/safety/command-contract/types.js +1 -1
- package/dist/core/search/context-graph-seeds.js +205 -0
- package/dist/core/search/context.js +0 -0
- package/dist/core/search/provider.js +2 -2
- package/dist/core/secret-redaction.js +6 -0
- package/dist/core/subagents/naruto-help-contract.js +2 -1
- package/dist/core/subagents/naruto-host-credentials.js +161 -0
- package/dist/core/subagents/official-subagent-preparation.js +4 -1
- package/dist/core/subagents/official-subagent-prompt.js +44 -2
- package/dist/core/subagents/official-subagent-runner.js +26 -8
- package/dist/core/subagents/triwiki-attention.js +135 -123
- package/dist/core/telegram/bot-api.js +85 -10
- package/dist/core/telegram/center-snapshot.js +718 -0
- package/dist/core/telegram/config.js +158 -31
- package/dist/core/telegram/hub.js +288 -33
- package/dist/core/telegram/index.js +2 -0
- package/dist/core/telegram/ingress-spool.js +419 -0
- package/dist/core/telegram/ledgers.js +188 -29
- package/dist/core/telegram/messages.js +26 -6
- package/dist/core/telegram/owner-lock.js +10 -7
- package/dist/core/telegram/runtime-projection.js +38 -3
- package/dist/core/telegram/runtime.js +298 -63
- package/dist/core/telegram/service.js +137 -8
- package/dist/core/telegram/setup.js +291 -73
- package/dist/core/text/strings.js +3 -0
- package/dist/core/triwiki/code-pack.js +12 -120
- package/dist/core/triwiki/context-graph/compiler/cache-key.js +277 -0
- package/dist/core/triwiki/context-graph/compiler/extract.js +104 -0
- package/dist/core/triwiki/context-graph/compiler/freshness.js +108 -0
- package/dist/core/triwiki/context-graph/compiler/index.js +237 -0
- package/dist/core/triwiki/context-graph/compiler/merge.js +0 -0
- package/dist/core/triwiki/context-graph/compiler/serialize.js +115 -0
- package/dist/core/triwiki/context-graph/contracts.js +236 -0
- package/dist/core/triwiki/context-graph/extractors/code/builders.js +150 -0
- package/dist/core/triwiki/context-graph/extractors/code/declarations.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/index.js +265 -0
- package/dist/core/triwiki/context-graph/extractors/code/inventory.js +237 -0
- package/dist/core/triwiki/context-graph/extractors/code/module-graph.js +252 -0
- package/dist/core/triwiki/context-graph/extractors/code/modules.js +79 -0
- package/dist/core/triwiki/context-graph/extractors/code/references.js +184 -0
- package/dist/core/triwiki/context-graph/extractors/code/selection.js +100 -0
- package/dist/core/triwiki/context-graph/extractors/code/ts-config.js +161 -0
- package/dist/core/triwiki/context-graph/extractors/code/types.js +18 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/claims.js +289 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/index.js +54 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proof-index.js +213 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/proofs.js +266 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/redaction.js +177 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/shared.js +0 -0
- package/dist/core/triwiki/context-graph/extractors/evidence/sources.js +154 -0
- package/dist/core/triwiki/context-graph/extractors/index.js +7 -0
- package/dist/core/triwiki/context-graph/extractors/topology/commands.js +207 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gate-edges.js +201 -0
- package/dist/core/triwiki/context-graph/extractors/topology/gates.js +182 -0
- package/dist/core/triwiki/context-graph/extractors/topology/globs.js +124 -0
- package/dist/core/triwiki/context-graph/extractors/topology/index.js +92 -0
- package/dist/core/triwiki/context-graph/extractors/topology/routes.js +135 -0
- package/dist/core/triwiki/context-graph/extractors/topology/shared.js +215 -0
- package/dist/core/triwiki/context-graph/graph-index.js +143 -0
- package/dist/core/triwiki/context-graph/ids.js +0 -0
- package/dist/core/triwiki/context-graph/lint/index.js +0 -0
- package/dist/core/triwiki/context-graph/lint/rules.js +232 -0
- package/dist/core/triwiki/context-graph/lint/warnings.js +93 -0
- package/dist/core/triwiki/context-graph/paths.js +116 -0
- package/dist/core/triwiki/context-graph/profiles.js +78 -0
- package/dist/core/triwiki/context-graph/projections/anchors.js +91 -0
- package/dist/core/triwiki/context-graph/projections/attention.js +58 -0
- package/dist/core/triwiki/context-graph/projections/code-pack-workspace.js +62 -0
- package/dist/core/triwiki/context-graph/projections/code-pack.js +144 -0
- package/dist/core/triwiki/context-graph/projections/index.js +7 -0
- package/dist/core/triwiki/context-graph/projections/module-view.js +140 -0
- package/dist/core/triwiki/context-graph/projections/node-summary.js +118 -0
- package/dist/core/triwiki/context-graph/projections/pack-contract.js +6 -0
- package/dist/core/triwiki/context-graph/query/explain.js +0 -0
- package/dist/core/triwiki/context-graph/query/index.js +178 -0
- package/dist/core/triwiki/context-graph/query/load.js +116 -0
- package/dist/core/triwiki/context-graph/query/pack.js +117 -0
- package/dist/core/triwiki/context-graph/query/rank.js +142 -0
- package/dist/core/triwiki/context-graph/query/ranking-config.js +64 -0
- package/dist/core/triwiki/context-graph/query/seeds.js +241 -0
- package/dist/core/triwiki/context-graph/query/snapshot-cache.js +72 -0
- package/dist/core/triwiki/context-graph/query/traverse.js +154 -0
- package/dist/core/triwiki/context-graph/query-types.js +29 -0
- package/dist/core/triwiki/context-graph/store/compile-lock.js +21 -0
- package/dist/core/triwiki/context-graph/store/event-log.js +48 -0
- package/dist/core/triwiki/context-graph/store/fragment-cache.js +85 -0
- package/dist/core/triwiki/context-graph/store/graph-status.js +85 -0
- package/dist/core/triwiki/context-graph/store/snapshot-store.js +155 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-repair.js +115 -0
- package/dist/core/triwiki/triwiki-proof-bank-index-store.js +290 -0
- package/dist/core/triwiki/triwiki-proof-bank-index.js +126 -0
- package/dist/core/triwiki/triwiki-proof-bank.js +7 -1
- package/dist/core/verification/context-graph-affected.js +271 -0
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
- package/dist/native/sks-menubar/Sources/AppDelegate.swift +9 -0
- package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +25 -3
- package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
- package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
- package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
- package/dist/native/sks-menubar/Sources/OverviewSummary.swift +162 -0
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +136 -190
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +107 -11
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +288 -341
- package/dist/native/sks-menubar/Sources/RemoteTelegramCenterState.swift +447 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramRendering.swift +484 -0
- package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +364 -115
- package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
- package/dist/native/sks-menubar/Sources/SidebarItem.swift +3 -3
- package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
- package/dist/native/sks-menubar/Sources/TelegramHubSupervisor.swift +469 -0
- package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
- package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
- package/dist/native/sks-menubar/Tests/NativeTelegramRegressionRunner.swift +55 -0
- package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +33 -0
- package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
- package/dist/native/sks-menubar/Tests/RemoteTelegramCenterStateTests.swift +56 -0
- package/dist/native/sks-menubar/Tests/TelegramHubSupervisorTests.swift +55 -0
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
- package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
- package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
- package/dist/scripts/context-graph-check.js +191 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
- package/dist/scripts/gate-policy-audit-check.js +1 -1
- package/dist/scripts/helper-dedup-check.js +0 -2
- package/dist/scripts/installed-package-smoke-check.js +4 -1
- package/dist/scripts/latest-version-guidance-check.js +74 -0
- package/dist/scripts/release-metadata-check.js +21 -4
- package/dist/scripts/release-real-check.js +7 -0
- package/dist/scripts/ux-review-imagegen-blackbox-check.js +25 -1
- package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -1
- package/package.json +8 -3
- package/release-gates.v2.json +176 -1
- package/runtime-required-scripts.json +30 -0
- package/schemas/triwiki/context-graph.schema.json +119 -0
- package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
- package/dist/cli/install-helpers-codex-lb-selftest.js +0 -481
- package/dist/core/triwiki/code-index-scanner.js +0 -309
|
@@ -1,5 +1,77 @@
|
|
|
1
1
|
import { exists, runProcess, which } from '../fsx.js';
|
|
2
2
|
import { inspectCodexLbCliLaunchRecovery } from '../codex-control/codex-lb-launch-recovery.js';
|
|
3
|
+
export async function quitCodexApp(opts = {}) {
|
|
4
|
+
const env = opts.env || process.env;
|
|
5
|
+
const appName = String(opts.appName || env.SKS_CODEX_APP_NAME || 'ChatGPT');
|
|
6
|
+
const bundleId = String(opts.bundleId || env.SKS_CODEX_APP_BUNDLE_ID || 'com.openai.codex');
|
|
7
|
+
if (opts.enabled === false)
|
|
8
|
+
return quitSkipped(appName, 'disabled');
|
|
9
|
+
if ((opts.platform || process.platform) !== 'darwin')
|
|
10
|
+
return quitSkipped(appName, 'not_macos');
|
|
11
|
+
const run = opts.runProcessImpl || runProcess;
|
|
12
|
+
const osascript = opts.osascriptPath
|
|
13
|
+
|| await which('osascript').catch(() => null)
|
|
14
|
+
|| await exists('/usr/bin/osascript').then((ok) => ok ? '/usr/bin/osascript' : null).catch(() => null);
|
|
15
|
+
if (!osascript) {
|
|
16
|
+
return {
|
|
17
|
+
schema: 'sks.codex-app-quit.v1',
|
|
18
|
+
ok: false,
|
|
19
|
+
status: 'blocked',
|
|
20
|
+
app_name: appName,
|
|
21
|
+
bundle_id: bundleId,
|
|
22
|
+
blockers: ['osascript_missing']
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const appTarget = bundleId ? `application id ${JSON.stringify(bundleId)}` : `application ${JSON.stringify(appName)}`;
|
|
26
|
+
const quit = await run(osascript, ['-e', `tell ${appTarget} to quit`], {
|
|
27
|
+
timeoutMs: 5000,
|
|
28
|
+
maxOutputBytes: 8192
|
|
29
|
+
}).catch((err) => ({
|
|
30
|
+
code: 1,
|
|
31
|
+
stdout: '',
|
|
32
|
+
stderr: err?.message || String(err)
|
|
33
|
+
}));
|
|
34
|
+
const quitOk = quit.code === 0
|
|
35
|
+
|| /not running|Can't get application|application isn't running/i.test(String(quit.stderr || quit.stdout || ''));
|
|
36
|
+
const exitTimeoutMs = Math.max(250, Number(opts.exitTimeoutMs ?? env.SKS_CODEX_APP_EXIT_TIMEOUT_MS ?? 5000));
|
|
37
|
+
const pollMs = Math.max(50, Number(opts.pollMs ?? 100));
|
|
38
|
+
let exited = !quitOk;
|
|
39
|
+
let attempts = 0;
|
|
40
|
+
const deadline = Date.now() + exitTimeoutMs;
|
|
41
|
+
while (quitOk && Date.now() < deadline) {
|
|
42
|
+
attempts += 1;
|
|
43
|
+
const probe = await run(osascript, ['-e', `${appTarget} is running`], {
|
|
44
|
+
timeoutMs: 1000,
|
|
45
|
+
maxOutputBytes: 1024
|
|
46
|
+
}).catch(() => null);
|
|
47
|
+
if (probe?.code === 0 && String(probe.stdout || '').trim().toLowerCase() === 'false') {
|
|
48
|
+
exited = true;
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
await sleep(pollMs);
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
schema: 'sks.codex-app-quit.v1',
|
|
55
|
+
ok: quitOk && exited,
|
|
56
|
+
status: quitOk && exited ? 'quit' : 'blocked',
|
|
57
|
+
app_name: appName,
|
|
58
|
+
bundle_id: bundleId,
|
|
59
|
+
quit: {
|
|
60
|
+
ok: quitOk,
|
|
61
|
+
code: quit.code,
|
|
62
|
+
error: quitOk ? null : String(quit.stderr || quit.stdout || '').trim()
|
|
63
|
+
},
|
|
64
|
+
exit_wait: {
|
|
65
|
+
ok: exited,
|
|
66
|
+
attempts,
|
|
67
|
+
error: exited ? null : 'codex_app_exit_timeout'
|
|
68
|
+
},
|
|
69
|
+
blockers: [
|
|
70
|
+
...(quitOk ? [] : ['codex_app_quit_failed']),
|
|
71
|
+
...(exited ? [] : ['codex_app_exit_timeout'])
|
|
72
|
+
]
|
|
73
|
+
};
|
|
74
|
+
}
|
|
3
75
|
export async function restartCodexApp(opts = {}) {
|
|
4
76
|
const env = opts.env || process.env;
|
|
5
77
|
const appName = String(opts.appName || env.SKS_CODEX_APP_NAME || 'ChatGPT');
|
|
@@ -110,6 +182,17 @@ function skipped(appName, reason) {
|
|
|
110
182
|
blockers: []
|
|
111
183
|
};
|
|
112
184
|
}
|
|
185
|
+
function quitSkipped(appName, reason) {
|
|
186
|
+
return {
|
|
187
|
+
schema: 'sks.codex-app-quit.v1',
|
|
188
|
+
ok: true,
|
|
189
|
+
status: 'skipped',
|
|
190
|
+
skipped: true,
|
|
191
|
+
reason,
|
|
192
|
+
app_name: appName,
|
|
193
|
+
blockers: []
|
|
194
|
+
};
|
|
195
|
+
}
|
|
113
196
|
function sleep(ms) {
|
|
114
197
|
return new Promise((resolve) => setTimeout(resolve, Math.max(0, ms)));
|
|
115
198
|
}
|
|
@@ -325,12 +325,16 @@ function hasActiveCodexLbProviderSelectionSignals(signals) {
|
|
|
325
325
|
const selected = signals.some((signal) => signal.key_path === 'model_provider' && signal.value_preview === 'codex-lb');
|
|
326
326
|
if (!selected)
|
|
327
327
|
return false;
|
|
328
|
-
const has = (key, value) => signals.some((signal) => signal.key_path === key && signal.value_preview === value);
|
|
328
|
+
const has = (key, value) => signals.some((signal) => (signal.key_path === key && signal.value_preview.toLowerCase() === value));
|
|
329
329
|
const present = (key) => signals.some((signal) => signal.key_path === key);
|
|
330
|
-
|
|
331
|
-
&&
|
|
332
|
-
|
|
330
|
+
const cliProviderAuth = present('model_providers.codex-lb.env_key')
|
|
331
|
+
&& present('model_providers.codex-lb.requires_openai_auth');
|
|
332
|
+
const desktopCompatAuth = present('model_providers.codex-lb.env_http_headers')
|
|
333
333
|
&& present('model_providers.codex-lb.requires_openai_auth');
|
|
334
|
+
return (has('model_providers.codex-lb.name', 'openai') || has('model_providers.codex-lb.name', 'codex-lb'))
|
|
335
|
+
&& present('model_providers.codex-lb.base_url')
|
|
336
|
+
&& has('model_providers.codex-lb.wire_api', 'responses')
|
|
337
|
+
&& (cliProviderAuth || desktopCompatAuth);
|
|
334
338
|
}
|
|
335
339
|
function redactValuePreview(keyPath, value) {
|
|
336
340
|
if (SECRET_KEY_RE.test(keyPath))
|
|
@@ -139,7 +139,7 @@ export async function restoreDesktopRoutingSnapshot(input) {
|
|
|
139
139
|
status: 'snapshot_missing',
|
|
140
140
|
blockers: ['desktop_routing_snapshot_missing'],
|
|
141
141
|
warnings: [],
|
|
142
|
-
hint: 'No previous Desktop routing snapshot. Use sks codex-lb use-codex-lb
|
|
142
|
+
hint: 'No previous Desktop routing snapshot. Use `sks codex-lb use-desktop-full` to enable managed routing or `sks codex-lb disable` to remove only SKS-managed routing.'
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
145
|
const configPath = input.configPath || path.join(codexHomePath({ home, env }), 'config.toml');
|
|
@@ -17,13 +17,18 @@ export const NATIVE_SOURCE_FILES = [
|
|
|
17
17
|
'SidebarItem.swift',
|
|
18
18
|
'ControlKit.swift',
|
|
19
19
|
'OverviewViewController.swift',
|
|
20
|
+
'OverviewSummary.swift',
|
|
20
21
|
'UpdatesViewController.swift',
|
|
21
22
|
'MCPServersViewController.swift',
|
|
22
23
|
'ProvidersViewController.swift',
|
|
24
|
+
'ProvidersRoutingTruth.swift',
|
|
23
25
|
'ProvidersOpenRouter.swift',
|
|
24
26
|
'ProvidersRoleModels.swift',
|
|
25
27
|
'ProvidersMultiProvider.swift',
|
|
28
|
+
'TelegramHubSupervisor.swift',
|
|
26
29
|
'RemoteTelegramViewController.swift',
|
|
30
|
+
'RemoteTelegramCenterState.swift',
|
|
31
|
+
'RemoteTelegramRendering.swift',
|
|
27
32
|
'DiagnosticsViewController.swift',
|
|
28
33
|
'SettingsViewController.swift',
|
|
29
34
|
'OperationCoordinator.swift',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { readJson, writeJsonAtomic } from '../../fsx.js';
|
|
4
|
+
export { messageOf as errorMessage } from '../../errors/message.js';
|
|
4
5
|
export const JOURNAL_SCHEMA = 'sks.menubar-generation-transaction.v1';
|
|
5
6
|
const OUTCOME_SCHEMA = 'sks.menubar-generation-transaction-outcome.v1';
|
|
6
7
|
export async function loadJournal(input) {
|
|
@@ -87,9 +88,6 @@ export async function outcomeFromUnknownJournal(purpose, journalPath, status, er
|
|
|
87
88
|
export async function existsNoFollow(file) {
|
|
88
89
|
return fs.lstat(file).then(() => true).catch(() => false);
|
|
89
90
|
}
|
|
90
|
-
export function errorMessage(error) {
|
|
91
|
-
return error instanceof Error ? error.message : String(error);
|
|
92
|
-
}
|
|
93
91
|
async function pairOutcome(pair) {
|
|
94
92
|
return {
|
|
95
93
|
kind: pair.kind,
|
|
@@ -73,6 +73,24 @@ export async function installSksMenuBar(opts = {}) {
|
|
|
73
73
|
cleanup = await cleanupMacLaunchSecretEnvironment({ env });
|
|
74
74
|
if (!cleanup.ok)
|
|
75
75
|
warnings.push('launch_secret_env_cleanup_incomplete');
|
|
76
|
+
try {
|
|
77
|
+
const { syncDesktopCenterLaunchCredentials } = await import('../../codex-lb/desktop-center-credentials.js');
|
|
78
|
+
const { CODEX_LB_DESKTOP_COMPAT_MARKER } = await import('../../../cli/install-helpers-codex-lb-config.js');
|
|
79
|
+
const { readText } = await import('../../fsx.js');
|
|
80
|
+
const configText = await readText(path.join(paths.home, '.codex', 'config.toml'), '');
|
|
81
|
+
if (configText.includes(CODEX_LB_DESKTOP_COMPAT_MARKER)) {
|
|
82
|
+
const restored = await syncDesktopCenterLaunchCredentials({
|
|
83
|
+
mode: 'desktop-dual-auth-compat',
|
|
84
|
+
home: paths.home
|
|
85
|
+
});
|
|
86
|
+
if (!restored.ok)
|
|
87
|
+
warnings.push('desktop_compat_launch_env_restore_incomplete');
|
|
88
|
+
else
|
|
89
|
+
actions.push('restored Center Codex LB credentials into Desktop launch environment');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch {
|
|
93
|
+
}
|
|
76
94
|
const swiftc = env.SKS_MENUBAR_SWIFTC || await which('swiftc').catch(() => null) || '/usr/bin/swiftc';
|
|
77
95
|
const codesign = env.SKS_MENUBAR_CODESIGN || await which('codesign').catch(() => null) || '/usr/bin/codesign';
|
|
78
96
|
const launchctl = env.SKS_MENUBAR_LAUNCHCTL || await which('launchctl').catch(() => null) || '/bin/launchctl';
|
|
@@ -254,11 +254,6 @@ export async function useMultiProviderRouter(input) {
|
|
|
254
254
|
hint: OPENCODEX_DESIGN_B_FORCE_HINT
|
|
255
255
|
};
|
|
256
256
|
}
|
|
257
|
-
const unselect = await unselectCodexLbProvider({
|
|
258
|
-
home,
|
|
259
|
-
configPath,
|
|
260
|
-
allowActiveSharedAuthTransition: true
|
|
261
|
-
}).catch((err) => ({ ok: false, status: 'failed', provider_error: err?.message || String(err) }));
|
|
262
257
|
const providerBody = tomlTableBody(current, `model_providers.${MULTI_PROVIDER_ROUTER_ID}`);
|
|
263
258
|
const existingProviderName = tomlString(providerBody, 'name');
|
|
264
259
|
if (providerBody && existingProviderName !== MULTI_PROVIDER_ROUTER_NAME) {
|
|
@@ -285,6 +280,26 @@ export async function useMultiProviderRouter(input) {
|
|
|
285
280
|
hint: 'Re-run with --replace-catalog only if replacing the current user model catalog is intentional.'
|
|
286
281
|
};
|
|
287
282
|
}
|
|
283
|
+
const unselect = await unselectCodexLbProvider({
|
|
284
|
+
home,
|
|
285
|
+
configPath,
|
|
286
|
+
processEnv: env
|
|
287
|
+
}).catch((err) => ({ ok: false, status: 'failed', provider_error: err?.message || String(err) }));
|
|
288
|
+
if (unselect?.ok !== true) {
|
|
289
|
+
return {
|
|
290
|
+
...routerBlocked('sks.codex-app-use-multi-provider-router.v1', unselect?.reason === 'shared_codex_lb_auth_active'
|
|
291
|
+
? 'legacy_codex_lb_desktop_config_requires_migration'
|
|
292
|
+
: String(unselect?.status || 'codex_lb_unselect_failed')),
|
|
293
|
+
model,
|
|
294
|
+
base_url: baseUrlResult.value,
|
|
295
|
+
catalog_path: catalogPath,
|
|
296
|
+
unselect,
|
|
297
|
+
guidance: unselect?.reason === 'shared_codex_lb_auth_active'
|
|
298
|
+
? ['Run: sks codex-lb migrate-legacy-desktop --restart-app']
|
|
299
|
+
: []
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const currentAfterUnselect = await readText(configPath, '');
|
|
288
303
|
const providerBlock = [
|
|
289
304
|
`[model_providers.${MULTI_PROVIDER_ROUTER_ID}]`,
|
|
290
305
|
`name = ${JSON.stringify(MULTI_PROVIDER_ROUTER_NAME)}`,
|
|
@@ -292,13 +307,13 @@ export async function useMultiProviderRouter(input) {
|
|
|
292
307
|
'wire_api = "responses"',
|
|
293
308
|
'requires_openai_auth = false'
|
|
294
309
|
].join('\n');
|
|
295
|
-
let next = upsertTomlTable(
|
|
310
|
+
let next = upsertTomlTable(currentAfterUnselect, `model_providers.${MULTI_PROVIDER_ROUTER_ID}`, providerBlock);
|
|
296
311
|
next = upsertTopLevelTomlString(next, 'model_catalog_json', catalogPath);
|
|
297
312
|
next = upsertTopLevelTomlString(next, 'model_provider', MULTI_PROVIDER_ROUTER_ID);
|
|
298
313
|
next = upsertTopLevelTomlString(next, 'model', model);
|
|
299
314
|
next = normalizeCodexFastModeUiConfig(next);
|
|
300
315
|
next = ensureTrailingNewline(next);
|
|
301
|
-
const write = await safeWriteCodexConfigToml(configPath,
|
|
316
|
+
const write = await safeWriteCodexConfigToml(configPath, currentAfterUnselect, next, 'multi-provider-router-use', {
|
|
302
317
|
verifyUnchangedBeforeWrite: true,
|
|
303
318
|
expectedBeforeExists: configExistedBefore
|
|
304
319
|
});
|
|
@@ -365,9 +380,6 @@ export async function useMultiProviderRouter(input) {
|
|
|
365
380
|
...catalog.warnings,
|
|
366
381
|
...ownership.warnings,
|
|
367
382
|
...cache.warnings,
|
|
368
|
-
...(unselect?.ok === false
|
|
369
|
-
? [`codex_lb_unselect:${unselect.provider_error || unselect.status}`]
|
|
370
|
-
: []),
|
|
371
383
|
...(catalog.models.find((entry) => entry.model === model)?.multi_agent_version === 'v2'
|
|
372
384
|
? []
|
|
373
385
|
: ['multi_provider_router_model_multi_agent_v2_missing']),
|
|
@@ -188,8 +188,33 @@ export async function useOpenRouter(input) {
|
|
|
188
188
|
const unselect = await unselectCodexLbProvider({
|
|
189
189
|
home,
|
|
190
190
|
configPath,
|
|
191
|
-
|
|
191
|
+
processEnv: env
|
|
192
192
|
}).catch((err) => ({ ok: false, status: 'failed', provider_error: err?.message || String(err) }));
|
|
193
|
+
if (unselect?.ok !== true) {
|
|
194
|
+
const sharedAuthActive = unselect?.reason === 'shared_codex_lb_auth_active';
|
|
195
|
+
return {
|
|
196
|
+
schema: 'sks.codex-app-use-openrouter.v1',
|
|
197
|
+
generated_at: nowIso(),
|
|
198
|
+
ok: false,
|
|
199
|
+
status: 'blocked',
|
|
200
|
+
mode: 'openrouter',
|
|
201
|
+
model,
|
|
202
|
+
profile: activationProfile,
|
|
203
|
+
unselect,
|
|
204
|
+
routing_snapshot: routingSnapshot,
|
|
205
|
+
routing_snapshot_write: snapshotWrite,
|
|
206
|
+
thread_visibility: threadVisibility,
|
|
207
|
+
blockers: [
|
|
208
|
+
sharedAuthActive
|
|
209
|
+
? 'legacy_codex_lb_desktop_config_requires_migration'
|
|
210
|
+
: String(unselect?.status || 'codex_lb_unselect_failed')
|
|
211
|
+
],
|
|
212
|
+
warnings: [],
|
|
213
|
+
...(sharedAuthActive
|
|
214
|
+
? { guidance: ['Run: sks codex-lb migrate-legacy-desktop --restart-app'] }
|
|
215
|
+
: {})
|
|
216
|
+
};
|
|
217
|
+
}
|
|
193
218
|
const modelCatalog = await writeOpenRouterManagedCatalog({ model, home, env });
|
|
194
219
|
const current = await readText(configPath, '');
|
|
195
220
|
const catalogBind = openRouterCatalogBindDecision(current, { home, env, configPath });
|
package/dist/core/codex-app.js
CHANGED
|
@@ -9,8 +9,8 @@ import { PRODUCT_DESIGN_AUTO_INSTALL_ENV, ensureProductDesignPluginInstalled, pr
|
|
|
9
9
|
import { GLM_CODEX_CONFIG_PROVIDER_ID, GLM_52_OPENROUTER_MODEL, RETIRED_GLM_DESKTOP_CONFIG_PROFILE_IDS } from './codex-app/openrouter-provider.js';
|
|
10
10
|
import { sksOpenRouterCatalogPath } from './codex-app/codex-model-catalog.js';
|
|
11
11
|
import { resolveOpenRouterApiKey } from './providers/openrouter/openrouter-secret-store.js';
|
|
12
|
-
import { codexLbEnvPath, loadCodexLbEnv, parseShellEnvValue, readCodexLbModelCatalog } from './codex-lb/codex-lb-env.js';
|
|
13
|
-
import { codexLbToolCatalogPath, inspectCodexLbToolCatalog } from './codex-lb/codex-lb-tool-catalog.js';
|
|
12
|
+
import { codexLbEnvPath, codexLbMetadataPath, loadCodexLbEnv, parseShellEnvValue, readCodexLbModelCatalog } from './codex-lb/codex-lb-env.js';
|
|
13
|
+
import { codexLbToolCatalogPath, inspectCodexLbToolCatalog, shouldBindLocalModelCatalog } from './codex-lb/codex-lb-tool-catalog.js';
|
|
14
14
|
import { isSksOwnedGlobalUiLock } from './codex-app/codex-app-ui-state-snapshot.js';
|
|
15
15
|
import { redactString } from './secret-redaction.js';
|
|
16
16
|
import { escapeRegExp } from './text/regex.js';
|
|
@@ -169,7 +169,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
169
169
|
});
|
|
170
170
|
const pluginPickerReady = requiredFeatureFlags.tool_suggest && requiredFeatureFlags.plugins && requiredFeatureFlags.apps && defaultPlugins.ok && pluginSkillShadows.ok && fastModeConfig.ok;
|
|
171
171
|
const gitActions = codexGitActionReadiness({ requiredFeatureFlags, remoteControl });
|
|
172
|
-
const selectedProviderReady = providerModelUi.
|
|
172
|
+
const selectedProviderReady = providerModelUi.effective_ready === true;
|
|
173
173
|
const ready = appInstalled && Boolean(codex.bin) && mcpList.ok && featureList.ok && requiredFeatureFlagsOk && pluginPickerReady && fastModeConfig.ok && selectedProviderReady && imageGenerationReady && gitActions.ok && computerUseReady && browserToolReady && chromeExtension.ok;
|
|
174
174
|
return {
|
|
175
175
|
ok: ready,
|
|
@@ -204,6 +204,7 @@ export async function codexAppIntegrationStatus(opts = {}) {
|
|
|
204
204
|
fast_mode_config: fastModeConfig,
|
|
205
205
|
provider_model_ui: providerModelUi,
|
|
206
206
|
selected_provider_ready: selectedProviderReady,
|
|
207
|
+
codex_lb_capabilities: opts.codexLbCapabilityReport || null,
|
|
207
208
|
git_actions: gitActions,
|
|
208
209
|
image_generation: imageGenerationReady,
|
|
209
210
|
image_generation_source: imageGenerationReady ? 'codex_features_list' : 'missing',
|
|
@@ -472,8 +473,8 @@ function codexNativeSksMenuStatus() {
|
|
|
472
473
|
companion_install_command: 'sks doctor --fix',
|
|
473
474
|
alternatives: [
|
|
474
475
|
'sks doctor --fix',
|
|
475
|
-
'sks codex-lb use-
|
|
476
|
-
'sks codex-lb
|
|
476
|
+
'sks codex-lb use-desktop-full',
|
|
477
|
+
'sks codex-lb disable',
|
|
477
478
|
'sks codex-app set-openrouter-key --api-key-stdin',
|
|
478
479
|
'codex://settings'
|
|
479
480
|
],
|
|
@@ -568,7 +569,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
568
569
|
}
|
|
569
570
|
if (!gitActions?.ok) {
|
|
570
571
|
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.`);
|
|
571
|
-
lines.push(
|
|
572
|
+
lines.push('Run: sks doctor --fix; if remote-control is still blocked, update Codex CLI to the official latest stable release and restart older app-server/TUI sessions.');
|
|
572
573
|
}
|
|
573
574
|
else {
|
|
574
575
|
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.');
|
|
@@ -577,7 +578,7 @@ export function codexAppGuidance({ appInstalled, codex, mcpList, featureList, re
|
|
|
577
578
|
lines.push('Codex App does not expose a documented third-party API for inserting SKS between Window and Help, so SKS uses a right-side macOS menu bar companion instead. Run `sks doctor --fix` to install or refresh it.');
|
|
578
579
|
}
|
|
579
580
|
if (appInstalled && (!computerUseReady || !browserToolReady)) {
|
|
580
|
-
lines.push('Open Codex App settings and enable recommended MCP/plugin tools. Codex CLI
|
|
581
|
+
lines.push('Open Codex App settings and enable recommended MCP/plugin tools. Codex CLI sessions that expose remote-control/app-server can pick up config changes live; restart older CLI/TUI sessions.');
|
|
581
582
|
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.`);
|
|
582
583
|
lines.push('Verify with: codex features list; codex mcp list');
|
|
583
584
|
}
|
|
@@ -939,13 +940,28 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
939
940
|
}
|
|
940
941
|
const codexLbProvider = tomlTableAny(configText, ['model_providers.codex-lb', 'model_providers."codex-lb"']);
|
|
941
942
|
const codexLbProviderPresent = Boolean(codexLbProvider);
|
|
942
|
-
const
|
|
943
|
-
&& hasTomlString(codexLbProvider, 'name', '
|
|
943
|
+
const codexLbCliProviderContractOk = codexLbProviderPresent
|
|
944
|
+
&& hasTomlString(codexLbProvider, 'name', 'codex-lb')
|
|
944
945
|
&& hasTomlString(codexLbProvider, 'wire_api', 'responses')
|
|
945
946
|
&& hasTomlString(codexLbProvider, 'env_key', 'CODEX_LB_API_KEY')
|
|
946
947
|
&& hasTomlBoolean(codexLbProvider, 'supports_websockets', true)
|
|
947
|
-
&& hasTomlBoolean(codexLbProvider, 'requires_openai_auth',
|
|
948
|
+
&& hasTomlBoolean(codexLbProvider, 'requires_openai_auth', false);
|
|
949
|
+
const codexLbCompatProviderContractOk = codexLbProviderPresent
|
|
950
|
+
&& hasTomlString(codexLbProvider, 'name', 'OpenAI')
|
|
951
|
+
&& hasTomlString(codexLbProvider, 'wire_api', 'responses')
|
|
952
|
+
&& hasTomlBoolean(codexLbProvider, 'supports_websockets', true)
|
|
953
|
+
&& hasTomlBoolean(codexLbProvider, 'requires_openai_auth', true)
|
|
954
|
+
&& !hasTomlKey(codexLbProvider, 'env_key')
|
|
955
|
+
&& hasCodexLbGatewayEnvHeader(codexLbProvider);
|
|
948
956
|
const codexLbSelectedDefault = /(?:^|\n)\s*model_provider\s*=\s*"codex-lb"\s*(?:#.*)?(?=\n|$)/.test(topLevelToml(globalConfig));
|
|
957
|
+
const codexLbDesktopMode = opts.codexLbDesktopMode
|
|
958
|
+
|| inferCodexLbDesktopModeForUi(globalConfig);
|
|
959
|
+
const codexLbProviderContractOk = codexLbDesktopMode === 'desktop-dual-auth-compat'
|
|
960
|
+
? codexLbCompatProviderContractOk
|
|
961
|
+
: codexLbCliProviderContractOk;
|
|
962
|
+
const metadata = await readJsonIfExists(opts.codexLbMetadataPath || codexLbMetadataPath(home));
|
|
963
|
+
const gatewayAuthTransport = normalizeCodexLbGatewayAuthTransportForUi(opts.codexLbGatewayAuthTransport || metadata?.gateway_auth_transport);
|
|
964
|
+
const localCatalogBindingAllowed = shouldBindLocalModelCatalog(codexLbDesktopMode);
|
|
949
965
|
const selectedProviderValue = topLevelToml(globalConfig)
|
|
950
966
|
.match(/(?:^|\n)\s*model_provider\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || null;
|
|
951
967
|
const managedCatalogPath = codexLbToolCatalogPath(path.join(home || '', '.codex'));
|
|
@@ -953,13 +969,18 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
953
969
|
const managedCatalogConfigured = Boolean(configuredCatalogPath)
|
|
954
970
|
&& path.resolve(configuredCatalogPath) === path.resolve(managedCatalogPath);
|
|
955
971
|
let persistedCatalog = null;
|
|
956
|
-
if (!opts.codexLbModelCatalog && managedCatalogConfigured) {
|
|
972
|
+
if (!opts.codexLbModelCatalog && managedCatalogConfigured && localCatalogBindingAllowed) {
|
|
957
973
|
persistedCatalog = await inspectCodexLbToolCatalog(managedCatalogPath).catch(() => null);
|
|
958
974
|
}
|
|
959
975
|
let liveCatalog = opts.codexLbModelCatalog || null;
|
|
960
976
|
if (!liveCatalog && !persistedCatalog?.ok && codexLbProviderContractOk && codexLbApiKeySource !== 'missing' && codexLbBaseUrlSource !== 'missing') {
|
|
961
977
|
const loadedEnv = await loadCodexLbEnv({ home, envPath: codexLbEnvFilePath }).catch(() => null);
|
|
962
|
-
liveCatalog = loadedEnv
|
|
978
|
+
liveCatalog = loadedEnv
|
|
979
|
+
? await readCodexLbModelCatalog({
|
|
980
|
+
loadedEnv,
|
|
981
|
+
gatewayAuthTransport
|
|
982
|
+
}).catch(() => null)
|
|
983
|
+
: null;
|
|
963
984
|
}
|
|
964
985
|
const codexLbModelCatalog = opts.codexLbModelCatalog || (persistedCatalog?.ok
|
|
965
986
|
? {
|
|
@@ -979,9 +1000,8 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
979
1000
|
source: 'persisted_model_catalog_json'
|
|
980
1001
|
}
|
|
981
1002
|
: null);
|
|
982
|
-
const expectedCodexLbModels = ['gpt-5.6-luna', 'gpt-5.6-terra', 'gpt-5.6-sol'];
|
|
983
1003
|
const catalogModels = Array.isArray(codexLbModelCatalog?.models) ? codexLbModelCatalog.models.map(String) : [];
|
|
984
|
-
const
|
|
1004
|
+
const advertisedCodexLbModelsPresent = codexLbModelCatalog?.ok === true && catalogModels.length > 0;
|
|
985
1005
|
const glmBlockers = [
|
|
986
1006
|
...(glmProviderPresent ? [] : ['glm_openrouter_provider_missing']),
|
|
987
1007
|
...glmProfileBlockers,
|
|
@@ -992,11 +1012,14 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
992
1012
|
...(codexLbProviderPresent && !codexLbProviderContractOk ? ['codex_lb_provider_contract_drift'] : []),
|
|
993
1013
|
...(codexLbApiKeySource !== 'missing' ? [] : ['codex_lb_api_key_missing']),
|
|
994
1014
|
...(codexLbBaseUrlSource !== 'missing' ? [] : ['codex_lb_base_url_missing']),
|
|
995
|
-
...(
|
|
1015
|
+
...(codexLbDesktopMode === 'desktop-native-bridge' && managedCatalogConfigured
|
|
1016
|
+
? ['native_bridge_local_catalog_replacement_forbidden']
|
|
1017
|
+
: []),
|
|
1018
|
+
...(codexLbSelectedDefault && localCatalogBindingAllowed && !managedCatalogConfigured && !advertisedCodexLbModelsPresent
|
|
996
1019
|
? ['codex_lb_model_catalog_json_unselected']
|
|
997
1020
|
: []),
|
|
998
|
-
...(codexLbProviderContractOk && codexLbApiKeySource !== 'missing' && codexLbBaseUrlSource !== 'missing' && !
|
|
999
|
-
? ['
|
|
1021
|
+
...(codexLbProviderContractOk && codexLbApiKeySource !== 'missing' && codexLbBaseUrlSource !== 'missing' && !advertisedCodexLbModelsPresent
|
|
1022
|
+
? ['codex_lb_model_catalog_unverified']
|
|
1000
1023
|
: [])
|
|
1001
1024
|
];
|
|
1002
1025
|
const openRouterSelectedDefault = selectedProviderValue === GLM_CODEX_CONFIG_PROVIDER_ID;
|
|
@@ -1027,17 +1050,38 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
1027
1050
|
const installCommand = 'sks codex-app use-openrouter --model z-ai/glm-5.2';
|
|
1028
1051
|
const setupCommand = 'sks codex-lb setup --host <domain> --api-key-stdin --yes';
|
|
1029
1052
|
const setKeyCommand = 'sks codex-lb set-key --api-key-stdin';
|
|
1053
|
+
const desktopPickerEvidence = opts.desktopPickerEvidence || opts.codexLbCapabilityReport?.model_picker || null;
|
|
1054
|
+
const desktopPickerVerified = desktopPickerEvidence?.state === 'verified'
|
|
1055
|
+
|| desktopPickerEvidence?.verified === true;
|
|
1056
|
+
const selectedProviderConfigured = selectedProviderBlockers.length === 0;
|
|
1057
|
+
const selectedProviderAdvertised = codexLbSelectedDefault
|
|
1058
|
+
? advertisedCodexLbModelsPresent
|
|
1059
|
+
: true;
|
|
1060
|
+
const effectiveReady = selectedProviderConfigured && selectedProviderAdvertised && desktopPickerVerified;
|
|
1030
1061
|
return {
|
|
1031
1062
|
schema: 'sks.codex-app-provider-model-ui.v1',
|
|
1032
|
-
ok:
|
|
1033
|
-
selected_provider_ok:
|
|
1063
|
+
ok: effectiveReady,
|
|
1064
|
+
selected_provider_ok: effectiveReady,
|
|
1065
|
+
configured: selectedProviderConfigured,
|
|
1066
|
+
advertised: selectedProviderAdvertised,
|
|
1067
|
+
effective_ready: effectiveReady,
|
|
1034
1068
|
selected_provider: codexLbSelectedDefault ? 'codex-lb' : (selectedProviderValue || 'oauth'),
|
|
1035
1069
|
selected_provider_blockers: selectedProviderBlockers,
|
|
1036
1070
|
optional_provider_blockers: optionalProviderBlockers,
|
|
1037
1071
|
checked: true,
|
|
1038
1072
|
verification_scope: 'config_and_provider_catalog',
|
|
1039
|
-
desktop_picker_verified:
|
|
1040
|
-
|
|
1073
|
+
desktop_picker_verified: desktopPickerVerified,
|
|
1074
|
+
desktop_picker_evidence: desktopPickerEvidence,
|
|
1075
|
+
readiness_state: selectedProviderBlockers.length > 0
|
|
1076
|
+
? 'blocked'
|
|
1077
|
+
: effectiveReady
|
|
1078
|
+
? 'verified'
|
|
1079
|
+
: 'available_unverified',
|
|
1080
|
+
status: selectedProviderBlockers.length > 0
|
|
1081
|
+
? 'setup_required'
|
|
1082
|
+
: effectiveReady
|
|
1083
|
+
? 'ready'
|
|
1084
|
+
: 'available_unverified',
|
|
1041
1085
|
optional_provider_status: optionalProviderBlockers.length === 0 ? 'ready' : 'setup_available',
|
|
1042
1086
|
config_paths: {
|
|
1043
1087
|
codex_config: globalConfigPath,
|
|
@@ -1066,6 +1110,9 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
1066
1110
|
key_entry_visible: true,
|
|
1067
1111
|
provider_present: codexLbProviderPresent,
|
|
1068
1112
|
provider_contract_ok: codexLbProviderContractOk,
|
|
1113
|
+
provider_contract: codexLbDesktopMode === 'desktop-dual-auth-compat'
|
|
1114
|
+
? 'desktop-dual-auth-compat'
|
|
1115
|
+
: 'cli-provider',
|
|
1069
1116
|
selected_default: codexLbSelectedDefault,
|
|
1070
1117
|
key_present: codexLbApiKeySource !== 'missing',
|
|
1071
1118
|
api_key_source: codexLbApiKeySource,
|
|
@@ -1074,11 +1121,15 @@ export async function codexProviderModelUiStatus(opts = {}) {
|
|
|
1074
1121
|
model_catalog_checked: Boolean(codexLbModelCatalog),
|
|
1075
1122
|
model_catalog_ok: codexLbModelCatalog?.ok === true,
|
|
1076
1123
|
model_catalog_source: codexLbModelCatalog?.source || null,
|
|
1124
|
+
desktop_mode: codexLbDesktopMode,
|
|
1125
|
+
gateway_auth_transport: gatewayAuthTransport,
|
|
1126
|
+
local_catalog_binding_allowed: localCatalogBindingAllowed,
|
|
1077
1127
|
model_catalog_json_configured: managedCatalogConfigured,
|
|
1078
1128
|
model_catalog_json_path: managedCatalogConfigured ? managedCatalogPath : configuredCatalogPath || null,
|
|
1079
1129
|
model_catalog_models: catalogModels,
|
|
1080
|
-
expected_models:
|
|
1081
|
-
expected_models_present:
|
|
1130
|
+
expected_models: [],
|
|
1131
|
+
expected_models_present: advertisedCodexLbModelsPresent,
|
|
1132
|
+
advertised_models_present: advertisedCodexLbModelsPresent,
|
|
1082
1133
|
tools_transport: codexLbModelCatalog?.tools_transport || null,
|
|
1083
1134
|
model_catalog_blockers: codexLbModelCatalog?.blockers || [],
|
|
1084
1135
|
setup_command: setupCommand,
|
|
@@ -1104,6 +1155,44 @@ async function readTextIfExists(file) {
|
|
|
1104
1155
|
return '';
|
|
1105
1156
|
}
|
|
1106
1157
|
}
|
|
1158
|
+
async function readJsonIfExists(file) {
|
|
1159
|
+
try {
|
|
1160
|
+
const parsed = JSON.parse(await fsp.readFile(file, 'utf8'));
|
|
1161
|
+
return parsed && typeof parsed === 'object' && !Array.isArray(parsed)
|
|
1162
|
+
? parsed
|
|
1163
|
+
: null;
|
|
1164
|
+
}
|
|
1165
|
+
catch {
|
|
1166
|
+
return null;
|
|
1167
|
+
}
|
|
1168
|
+
}
|
|
1169
|
+
function inferCodexLbDesktopModeForUi(config) {
|
|
1170
|
+
const topLevel = topLevelToml(config);
|
|
1171
|
+
const selected = topLevel.match(/(?:^|\n)\s*model_provider\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || '';
|
|
1172
|
+
const openAiBaseUrl = topLevel.match(/(?:^|\n)\s*openai_base_url\s*=\s*"([^"]+)"\s*(?:#.*)?(?=\n|$)/)?.[1] || '';
|
|
1173
|
+
if (config.includes('# sks-codex-lb-managed-desktop-bridge')
|
|
1174
|
+
&& /^http:\/\/(?:127\.0\.0\.1|\[::1\]):\d+\/backend-api\/codex\/?$/i.test(openAiBaseUrl)) {
|
|
1175
|
+
return 'desktop-native-bridge';
|
|
1176
|
+
}
|
|
1177
|
+
if (config.includes('# sks-codex-lb-managed-desktop-compat')
|
|
1178
|
+
&& selected === 'codex-lb') {
|
|
1179
|
+
return 'desktop-dual-auth-compat';
|
|
1180
|
+
}
|
|
1181
|
+
return tomlTableAny(config, ['model_providers.codex-lb', 'model_providers."codex-lb"'])
|
|
1182
|
+
? 'cli-provider'
|
|
1183
|
+
: 'disabled';
|
|
1184
|
+
}
|
|
1185
|
+
function normalizeCodexLbGatewayAuthTransportForUi(value) {
|
|
1186
|
+
return value === 'authorization-bearer-compat'
|
|
1187
|
+
? 'authorization-bearer-compat'
|
|
1188
|
+
: 'x-codex-lb-api-key';
|
|
1189
|
+
}
|
|
1190
|
+
function hasTomlKey(text, key) {
|
|
1191
|
+
return new RegExp(`(?:^|\\n)\\s*${escapeRegExp(key)}\\s*=`).test(text);
|
|
1192
|
+
}
|
|
1193
|
+
function hasCodexLbGatewayEnvHeader(text) {
|
|
1194
|
+
return /(?:^|\n)\s*env_http_headers\s*=\s*\{[^}\n]*"X-Codex-LB-API-Key"\s*=\s*"CODEX_LB_API_KEY"[^}\n]*\}\s*(?:#.*)?(?=\n|$)/.test(text);
|
|
1195
|
+
}
|
|
1107
1196
|
async function findDefaultPluginSource(plugin, { home, configText }) {
|
|
1108
1197
|
const cached = await findPluginCache(plugin.name, { home });
|
|
1109
1198
|
if (cached)
|
|
@@ -1165,6 +1254,9 @@ function providerModelUiSummary(status = {}) {
|
|
|
1165
1254
|
: '';
|
|
1166
1255
|
return ` ${selected} ready${optionalSetup} (live picker reload required)`;
|
|
1167
1256
|
}
|
|
1257
|
+
if (status.configured && status.readiness_state === 'available_unverified') {
|
|
1258
|
+
return ` ${selected} configured, Desktop picker unverified`;
|
|
1259
|
+
}
|
|
1168
1260
|
return ` ${selected} setup ${(status.selected_provider_blockers || status.blockers || []).join(', ') || 'required'}`;
|
|
1169
1261
|
}
|
|
1170
1262
|
function sksNativeMenuSummary(status = {}) {
|
|
@@ -1226,10 +1318,10 @@ function hasTomlBoolean(text = '', key = '', value) {
|
|
|
1226
1318
|
}
|
|
1227
1319
|
function remoteControlGuidance(status = {}) {
|
|
1228
1320
|
if (!status.codex_cli?.ok)
|
|
1229
|
-
return 'Codex remote-control
|
|
1321
|
+
return 'Codex remote-control needs a Codex CLI that exposes the app-server entrypoint. Install the official latest stable release: npm i -g @openai/codex@latest';
|
|
1230
1322
|
if (status.reason === 'codex_cli_version_unknown')
|
|
1231
|
-
return 'Codex remote-control
|
|
1232
|
-
return
|
|
1323
|
+
return 'Codex remote-control needs a Codex CLI that exposes the app-server entrypoint, but the installed CLI version could not be parsed. Check: codex --version';
|
|
1324
|
+
return 'The installed Codex CLI does not expose remote-control. Update to the official latest stable release: npm i -g @openai/codex@latest';
|
|
1233
1325
|
}
|
|
1234
1326
|
function codexCliVersionNumber(versionText = '') {
|
|
1235
1327
|
const match = String(versionText || '').match(/(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);
|