sneakoscope 8.1.2 → 8.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +96 -58
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +5 -51
- package/dist/cli/command-manifest-lite.js +2 -1
- package/dist/cli/command-registry.js +2 -1
- package/dist/cli/global-mode-router.js +1 -1
- package/dist/cli/install-helpers-codex-lb-config.js +112 -914
- package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
- package/dist/cli/install-helpers-install-support.js +4 -20
- package/dist/cli/install-helpers.js +36 -2716
- package/dist/cli/router.js +9 -9
- package/dist/commands/bridge-command-output.js +111 -0
- package/dist/commands/bridge.js +320 -0
- package/dist/commands/codex-app.js +39 -123
- package/dist/commands/doctor-helpers.js +380 -0
- package/dist/commands/doctor-profile.js +3 -0
- package/dist/commands/doctor.js +114 -873
- package/dist/commands/mad-sks.js +0 -4
- package/dist/config/skills-manifest.json +1 -1
- package/dist/core/agents/agent-effort-policy.js +11 -21
- package/dist/core/agents/agent-recursion-guard.js +26 -0
- package/dist/core/agents/agent-runner-codex-exec.js +7 -9
- package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
- package/dist/core/architecture-hardening/state/state-service.js +49 -13
- package/dist/core/auto-review.js +15 -9
- package/dist/core/codex/codex-config-guard.js +8 -0
- package/dist/core/codex-adapter.js +8 -10
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
- package/dist/core/codex-app/codex-app-launcher.js +10 -12
- package/dist/core/codex-app/codex-app-restart.js +10 -12
- package/dist/core/codex-app/menubar/constants.js +2 -5
- package/dist/core/codex-app/menubar/global-install.js +3 -2
- package/dist/core/codex-app/menubar/installer/result.js +23 -0
- package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
- package/dist/core/codex-app/menubar/installer.js +5 -96
- package/dist/core/codex-app/menubar/migration.js +1 -42
- package/dist/core/codex-app/openrouter-provider.js +0 -78
- package/dist/core/codex-app.js +97 -360
- package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
- package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
- package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
- package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
- package/dist/core/codex-control/codex-task-runner.js +16 -60
- package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
- package/dist/core/codex-exec-output-schema.js +11 -13
- package/dist/core/codex-lb/bridge-contracts.js +2 -0
- package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
- package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
- package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
- package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
- package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
- package/dist/core/codex-lb/capability-runner.js +505 -201
- package/dist/core/codex-lb/codex-lb-env.js +179 -12
- package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
- package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
- package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
- package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
- package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
- package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
- package/dist/core/codex-lb/combined-catalog.js +12 -0
- package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
- package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
- package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
- package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
- package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
- package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
- package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
- package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
- package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
- package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
- package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
- package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
- package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
- package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
- package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
- package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
- package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
- package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
- package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
- package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
- package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
- package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
- package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
- package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
- package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
- package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
- package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
- package/dist/core/codex-lb/desktop-controller.js +2 -1730
- package/dist/core/codex-lb/desktop-service.js +462 -627
- package/dist/core/codex-lb/migration-receipt.js +560 -118
- package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
- package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
- package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
- package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
- package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
- package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
- package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
- package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
- package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
- package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
- package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
- package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
- package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
- package/dist/core/codex-lb/provider-credentials/types.js +1 -0
- package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
- package/dist/core/codex-lb/provider-credentials.js +5 -0
- package/dist/core/codex-lb/provider-registry.js +323 -0
- package/dist/core/codex-lb/provider-route-policy.js +118 -0
- package/dist/core/codex-lb/request-route-resolver.js +172 -0
- package/dist/core/codex-lb/route-index.js +148 -0
- package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
- package/dist/core/commands/basic-cli.js +1 -1
- package/dist/core/commands/check-command.js +3 -10
- package/dist/core/commands/gate-result-contract.js +10 -14
- package/dist/core/commands/intent-normalization/normalizer.js +1 -1
- package/dist/core/commands/mad-sks-command.js +2 -6
- package/dist/core/commands/release-command.js +11 -1
- package/dist/core/commands/telegram-command.js +46 -6
- package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
- package/dist/core/doctor/skill-legacy-surface.js +5 -5
- package/dist/core/evidence/v2/evidence-key.js +30 -3
- package/dist/core/feature-fixtures.js +8 -1
- package/dist/core/feature-registry.js +3 -2
- package/dist/core/hooks-runtime/stop-finalization.js +11 -1
- package/dist/core/hooks-runtime/subagent-context.js +15 -1
- package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
- package/dist/core/hooks-runtime.js +73 -87
- package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
- package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
- package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
- package/dist/core/imagegen/imagegen-capability.js +43 -151
- package/dist/core/init/skills/filesystem.js +89 -0
- package/dist/core/init/skills/inventory.js +97 -0
- package/dist/core/init/skills/manifest.js +151 -0
- package/dist/core/init/skills.js +5 -325
- package/dist/core/init.js +0 -63
- package/dist/core/install/installed-package-smoke.js +1 -1
- package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
- package/dist/core/policy/latest-version-guidance.js +15 -2
- package/dist/core/preflight/parallel-preflight-engine.js +27 -51
- package/dist/core/provider/provider-badge.js +9 -4
- package/dist/core/provider/provider-context.js +57 -107
- package/dist/core/providers/openrouter/openrouter-account.js +3 -1
- package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
- package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
- package/dist/core/release/gate-manifest.js +0 -1
- package/dist/core/release/main-push-guard.js +13 -0
- package/dist/core/release/main-push-receipt.js +11 -0
- package/dist/core/release/physical-release-gates.js +664 -61
- package/dist/core/release/publish-preflight.js +3 -3
- package/dist/core/release/release-gate-batch-runner.js +19 -6
- package/dist/core/release/release-gate-dag.js +33 -6
- package/dist/core/release/release-gate-node.js +1 -3
- package/dist/core/release/release-gate-output-contract.js +55 -0
- package/dist/core/release/release-pack-contract.js +1 -1
- package/dist/core/release/release-pack-receipt.js +209 -8
- package/dist/core/release/release-real-contract.js +1 -1
- package/dist/core/release/stage-publish.js +106 -28
- package/dist/core/retention/temp-lease.js +204 -0
- package/dist/core/retention.js +18 -195
- package/dist/core/routes.js +1 -2
- package/dist/core/safety/intent-contract/intent-contract.js +3 -3
- package/dist/core/subagents/naruto-host-credentials.js +6 -1
- package/dist/core/subagents/official-subagent-config.js +27 -9
- package/dist/core/subagents/official-subagent-runner.js +14 -31
- package/dist/core/subagents/wave-lifecycle.js +36 -8
- package/dist/core/subagents/wave-parent-guidance.js +2 -1
- package/dist/core/telegram/doctor.js +2 -2
- package/dist/core/telegram/liveness.js +10 -4
- package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
- package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
- package/dist/core/update/update-migration-state/session-state-split.js +247 -0
- package/dist/core/update/update-migration-state/simple-stages.js +46 -0
- package/dist/core/update/update-migration-state.js +4 -481
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
- package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
- package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
- package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
- package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
- package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
- package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
- package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
- package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
- package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
- package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-runtime-schemas.js +7 -2
- package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
- package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
- package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
- package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
- package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
- package/dist/scripts/desktop-bridge-transport-client.js +116 -0
- package/dist/scripts/desktop-bridge-unification-check.js +276 -0
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
- package/dist/scripts/gate-policy-audit-check.js +52 -2
- package/dist/scripts/provider-badge-context-check.js +55 -12
- package/dist/scripts/publish-preflight.js +1 -2
- package/dist/scripts/release-affected-selector-check.js +1 -2
- package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
- package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
- package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
- package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
- package/dist/scripts/release-gate-batch-runner-check.js +9 -0
- package/dist/scripts/release-gate-dag-runner-check.js +6 -0
- package/dist/scripts/release-gate-dag-runner.js +4 -2
- package/dist/scripts/release-metadata-check.js +16 -3
- package/dist/scripts/release-pack-receipt.js +29 -6
- package/dist/scripts/release-physical-gates-check.js +39 -0
- package/dist/scripts/release-real-check.js +7 -5
- package/package.json +6 -8
- package/release-gates.v2.json +156 -157
- package/runtime-required-scripts.json +11 -11
- package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
- package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
- package/schemas/release/release-gate-node.schema.json +2 -3
- package/dist/cli/codex-lb-setup-warning-output.js +0 -17
- package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
- package/dist/commands/codex-lb.js +0 -1232
- package/dist/core/architecture-hardening/migration/migration.js +0 -111
- package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
- package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
- package/dist/core/codex-app/child-policy/child-policy.js +0 -35
- package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
- package/dist/core/codex-app/glm-model-profile.js +0 -1
- package/dist/core/codex-app/glm-profile-installer.js +0 -191
- package/dist/core/codex-app/glm-profile-schema.js +0 -42
- package/dist/core/codex-app/multi-provider-router.js +0 -391
- package/dist/core/codex-app/openrouter-activate.js +0 -405
- package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
- package/dist/core/codex-app/provider-child-policy.js +0 -64
- package/dist/core/codex-app/provider-mode.js +0 -91
- package/dist/core/codex-app/provider-session-policy.js +0 -85
- package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
- package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
- package/dist/core/codex-lb/codex-lb-setup.js +0 -293
- package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
- package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
- package/dist/core/codex-lb/desktop-mode.js +0 -32
- package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
- package/dist/core/codex-lb/legacy-migration.js +0 -576
- package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
- package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
- package/dist/core/codex-lb/routing-truth.js +0 -327
- package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
- package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
- package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
- package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
- package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
- package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
- package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
- package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
- package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { credentialClassForMode, parseProviderPolicySnapshot } from '../../architecture-hardening/contracts/contracts.js';
|
|
2
|
-
export function decideProviderRoute(input) {
|
|
3
|
-
const policy = parseProviderPolicySnapshot(input.policy);
|
|
4
|
-
const base = {
|
|
5
|
-
schema: 'sks.provider-route-decision.v1',
|
|
6
|
-
mode: policy.mode,
|
|
7
|
-
credential_class: policy.credential_class,
|
|
8
|
-
failover_allowed: false
|
|
9
|
-
};
|
|
10
|
-
if (input.requestedMode !== policy.mode)
|
|
11
|
-
return blocked(base, 'provider_route_cross_mode_forbidden');
|
|
12
|
-
if (input.credential.status !== 'ready')
|
|
13
|
-
return blocked(base, `provider_route_credential_${input.credential.status}`);
|
|
14
|
-
const model = String(input.model || '').trim();
|
|
15
|
-
if (!model)
|
|
16
|
-
return blocked(base, 'provider_route_model_invalid');
|
|
17
|
-
const isOpenRouterModel = model.includes('/');
|
|
18
|
-
if ((policy.mode === 'openrouter') !== isOpenRouterModel)
|
|
19
|
-
return blocked(base, 'provider_route_model_family_mismatch');
|
|
20
|
-
if (!policy.allowed_models.includes(model))
|
|
21
|
-
return blocked(base, 'provider_route_model_not_allowed');
|
|
22
|
-
return {
|
|
23
|
-
...base,
|
|
24
|
-
ok: true,
|
|
25
|
-
upstream: policy.mode,
|
|
26
|
-
model,
|
|
27
|
-
source_label: policy.mode === 'chatgpt-oauth' ? 'ChatGPT OAuth' : policy.mode === 'codex-lb' ? 'Codex LB' : 'OpenRouter',
|
|
28
|
-
blockers: []
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
export async function resolveCredentialForRoute(decision, port) {
|
|
32
|
-
if (!decision.ok)
|
|
33
|
-
throw new Error(decision.blockers[0] || 'provider_route_blocked');
|
|
34
|
-
const credential = await port.readCredential(decision.credential_class);
|
|
35
|
-
if (!credential)
|
|
36
|
-
throw new Error('provider_route_credential_unavailable');
|
|
37
|
-
return credential;
|
|
38
|
-
}
|
|
39
|
-
export function classifyProviderRouteFailure(status) {
|
|
40
|
-
if (status === 401 || status === 403)
|
|
41
|
-
return { retry_allowed: false, failover_allowed: false, reason_code: 'provider_route_auth_failed' };
|
|
42
|
-
if (status === 402 || status === 429)
|
|
43
|
-
return { retry_allowed: false, failover_allowed: false, reason_code: 'provider_route_quota_or_rate_limit' };
|
|
44
|
-
if (status >= 500)
|
|
45
|
-
return { retry_allowed: false, failover_allowed: false, reason_code: 'provider_route_upstream_failed' };
|
|
46
|
-
return { retry_allowed: true, failover_allowed: false, reason_code: 'provider_route_request_failed' };
|
|
47
|
-
}
|
|
48
|
-
export function emptyProviderCatalogForCredential(input) {
|
|
49
|
-
if (input.credential.status !== 'ready')
|
|
50
|
-
return [];
|
|
51
|
-
return input.models.filter((model) => (input.mode === 'openrouter') === model.includes('/'));
|
|
52
|
-
}
|
|
53
|
-
function blocked(base, blocker) {
|
|
54
|
-
return { ...base, ok: false, upstream: null, model: null, source_label: null, blockers: [blocker] };
|
|
55
|
-
}
|
|
56
|
-
export function expectedCredentialClass(mode) {
|
|
57
|
-
return credentialClassForMode(mode);
|
|
58
|
-
}
|
|
@@ -1,327 +0,0 @@
|
|
|
1
|
-
import os from 'node:os';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { readJson, writeJsonAtomic } from '../fsx.js';
|
|
4
|
-
import { uniqueTruthyStrings as uniqueStrings } from '../text/strings.js';
|
|
5
|
-
import { codexLbBaseUrlSecurityBlocker, normalizeCodexLbBaseUrl } from './codex-lb-env.js';
|
|
6
|
-
export const CODEX_LB_ROUTING_TRUTH_SCHEMA = 'sks.codex-lb-routing-truth.v1';
|
|
7
|
-
export const CODEX_LB_ROUTING_TRUTH_RECEIPT = 'sks-codex-lb-routing-truth.json';
|
|
8
|
-
export const CODEX_LB_ROUTING_TRUTH_STAMP = CODEX_LB_ROUTING_TRUTH_RECEIPT;
|
|
9
|
-
export const CODEX_LB_ROUTING_TRUTH_STALE_AFTER_MS = 5 * 60 * 1_000;
|
|
10
|
-
export function codexLbRoutingTruthReceiptPath(home = process.env.HOME || os.homedir()) {
|
|
11
|
-
return path.join(home, '.codex', CODEX_LB_ROUTING_TRUTH_RECEIPT);
|
|
12
|
-
}
|
|
13
|
-
export const codexLbRoutingTruthStampPath = codexLbRoutingTruthReceiptPath;
|
|
14
|
-
export async function measureCodexLbRoutingTruth(options) {
|
|
15
|
-
const now = options.now || Date.now;
|
|
16
|
-
const measuredAt = options.nowIso?.() || new Date(now()).toISOString();
|
|
17
|
-
const baseUrl = normalizeCodexLbBaseUrl(options.baseUrl || '');
|
|
18
|
-
const configured = safePublicUrl(baseUrl);
|
|
19
|
-
const mode = options.mode || 'cli-provider';
|
|
20
|
-
const probeBaseUrl = normalizeCodexLbBaseUrl(options.probeBaseUrl || '');
|
|
21
|
-
const bridgeLoopbackProbe = Boolean(probeBaseUrl);
|
|
22
|
-
const authTransport = options.authTransport || (mode === 'cli-provider'
|
|
23
|
-
? 'x-codex-lb-api-key'
|
|
24
|
-
: 'authorization-bearer');
|
|
25
|
-
const base = {
|
|
26
|
-
schema: CODEX_LB_ROUTING_TRUTH_SCHEMA,
|
|
27
|
-
mode,
|
|
28
|
-
selected: options.selected,
|
|
29
|
-
fresh: false,
|
|
30
|
-
stale_after_ms: CODEX_LB_ROUTING_TRUTH_STALE_AFTER_MS,
|
|
31
|
-
age_ms: 0,
|
|
32
|
-
configured_base_url: configured?.url || null,
|
|
33
|
-
configured_host: configured?.host || null,
|
|
34
|
-
actual_url: null,
|
|
35
|
-
actual_host: null,
|
|
36
|
-
measurement_path: bridgeLoopbackProbe ? 'bridge-loopback' : 'direct',
|
|
37
|
-
auth_transport: authTransport,
|
|
38
|
-
http_status: null,
|
|
39
|
-
measured_at: measuredAt,
|
|
40
|
-
checked_at: measuredAt,
|
|
41
|
-
latency_ms: null
|
|
42
|
-
};
|
|
43
|
-
if (!baseUrl) {
|
|
44
|
-
return {
|
|
45
|
-
...base,
|
|
46
|
-
ok: false,
|
|
47
|
-
status: 'missing_base_url',
|
|
48
|
-
measured: false,
|
|
49
|
-
auth_outcome: 'not_attempted',
|
|
50
|
-
blockers: ['codex_lb_missing:CODEX_LB_BASE_URL']
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
const transportBlocker = codexLbBaseUrlSecurityBlocker(baseUrl);
|
|
54
|
-
if (transportBlocker) {
|
|
55
|
-
return {
|
|
56
|
-
...base,
|
|
57
|
-
ok: false,
|
|
58
|
-
status: 'transport_blocked',
|
|
59
|
-
measured: false,
|
|
60
|
-
auth_outcome: 'not_attempted',
|
|
61
|
-
blockers: [transportBlocker]
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
if (bridgeLoopbackProbe && (mode !== 'bridge' || !isHttpLoopbackUrl(probeBaseUrl))) {
|
|
65
|
-
return {
|
|
66
|
-
...base,
|
|
67
|
-
ok: false,
|
|
68
|
-
status: 'transport_blocked',
|
|
69
|
-
measured: false,
|
|
70
|
-
auth_outcome: 'not_attempted',
|
|
71
|
-
blockers: ['codex_lb_bridge_probe_target_not_loopback']
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
const apiKey = String(options.apiKey || '').trim();
|
|
75
|
-
if (!apiKey) {
|
|
76
|
-
return {
|
|
77
|
-
...base,
|
|
78
|
-
ok: false,
|
|
79
|
-
status: 'missing_api_key',
|
|
80
|
-
measured: false,
|
|
81
|
-
auth_outcome: 'not_attempted',
|
|
82
|
-
blockers: ['codex_lb_missing:CODEX_LB_API_KEY']
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
if (options.measure === false) {
|
|
86
|
-
return {
|
|
87
|
-
...base,
|
|
88
|
-
ok: !options.selected,
|
|
89
|
-
status: options.selected ? 'selected_unmeasured' : 'ready_unselected',
|
|
90
|
-
measured: false,
|
|
91
|
-
auth_outcome: 'not_attempted',
|
|
92
|
-
blockers: options.selected ? ['codex_lb_routing_truth_unmeasured'] : []
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
if (!options.selected) {
|
|
96
|
-
return {
|
|
97
|
-
...base,
|
|
98
|
-
ok: true,
|
|
99
|
-
status: 'ready_unselected',
|
|
100
|
-
measured: false,
|
|
101
|
-
auth_outcome: 'not_attempted',
|
|
102
|
-
blockers: []
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
const measurementBaseUrl = bridgeLoopbackProbe ? probeBaseUrl : baseUrl;
|
|
106
|
-
const measurementTarget = safePublicUrl(measurementBaseUrl);
|
|
107
|
-
const endpoint = `${measurementBaseUrl.replace(/\/+$/, '')}/models`;
|
|
108
|
-
const startedAt = now();
|
|
109
|
-
try {
|
|
110
|
-
const headers = authTransport === 'x-codex-lb-api-key'
|
|
111
|
-
? { 'X-Codex-LB-API-Key': apiKey }
|
|
112
|
-
: { Authorization: `Bearer ${apiKey}` };
|
|
113
|
-
const response = await (options.fetchImpl || globalThis.fetch)(endpoint, {
|
|
114
|
-
method: 'GET',
|
|
115
|
-
headers,
|
|
116
|
-
redirect: 'error',
|
|
117
|
-
signal: AbortSignal.timeout(Math.max(250, Number(options.timeoutMs || 8_000)))
|
|
118
|
-
});
|
|
119
|
-
const finishedAt = now();
|
|
120
|
-
const actual = safePublicUrl(response.url || endpoint);
|
|
121
|
-
const authRejected = response.status === 401 || response.status === 403;
|
|
122
|
-
const ok = response.ok && !authRejected && actual?.host === measurementTarget?.host;
|
|
123
|
-
const status = authRejected
|
|
124
|
-
? 'auth_rejected'
|
|
125
|
-
: response.ok && actual?.host !== measurementTarget?.host
|
|
126
|
-
? 'endpoint_unreachable'
|
|
127
|
-
: response.ok
|
|
128
|
-
? 'verified'
|
|
129
|
-
: 'http_error';
|
|
130
|
-
return {
|
|
131
|
-
...base,
|
|
132
|
-
ok,
|
|
133
|
-
status,
|
|
134
|
-
measured: true,
|
|
135
|
-
fresh: true,
|
|
136
|
-
actual_url: actual?.url || null,
|
|
137
|
-
actual_host: actual?.host || null,
|
|
138
|
-
auth_outcome: authRejected ? 'rejected' : response.ok ? 'accepted' : 'indeterminate',
|
|
139
|
-
http_status: response.status,
|
|
140
|
-
latency_ms: Math.max(0, finishedAt - startedAt),
|
|
141
|
-
blockers: ok
|
|
142
|
-
? []
|
|
143
|
-
: [authRejected
|
|
144
|
-
? 'codex_lb_auth_rejected'
|
|
145
|
-
: response.ok
|
|
146
|
-
? 'codex_lb_actual_host_mismatch'
|
|
147
|
-
: `codex_lb_models_http_${response.status}`]
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
catch {
|
|
151
|
-
const finishedAt = now();
|
|
152
|
-
return {
|
|
153
|
-
...base,
|
|
154
|
-
ok: false,
|
|
155
|
-
status: 'endpoint_unreachable',
|
|
156
|
-
measured: true,
|
|
157
|
-
fresh: true,
|
|
158
|
-
auth_outcome: 'indeterminate',
|
|
159
|
-
latency_ms: Math.max(0, finishedAt - startedAt),
|
|
160
|
-
blockers: ['codex_lb_endpoint_unreachable']
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
export async function writeCodexLbRoutingTruthReceipt(truth, options = {}) {
|
|
165
|
-
const receiptPath = options.receiptPath || codexLbRoutingTruthReceiptPath(options.home);
|
|
166
|
-
const canonical = parseReceipt(truth);
|
|
167
|
-
if (!canonical)
|
|
168
|
-
throw new Error('codex_lb_routing_truth_invalid');
|
|
169
|
-
await writeJsonAtomic(receiptPath, canonical, { mode: 0o600 });
|
|
170
|
-
return canonical;
|
|
171
|
-
}
|
|
172
|
-
export async function readCodexLbRoutingTruthReceipt(options = {}) {
|
|
173
|
-
const receiptPath = options.receiptPath || codexLbRoutingTruthReceiptPath(options.home);
|
|
174
|
-
const parsed = parseReceipt(await readJson(receiptPath, null));
|
|
175
|
-
if (!parsed)
|
|
176
|
-
return null;
|
|
177
|
-
if (options.expectedMode !== undefined && parsed.mode !== options.expectedMode)
|
|
178
|
-
return null;
|
|
179
|
-
if (options.expectedSelected !== undefined && parsed.selected !== options.expectedSelected)
|
|
180
|
-
return null;
|
|
181
|
-
if (options.expectedConfiguredHost !== undefined
|
|
182
|
-
&& parsed.configured_host !== options.expectedConfiguredHost)
|
|
183
|
-
return null;
|
|
184
|
-
if (options.expectedAuthTransport !== undefined
|
|
185
|
-
&& parsed.auth_transport !== options.expectedAuthTransport)
|
|
186
|
-
return null;
|
|
187
|
-
return withFreshness(parsed, options);
|
|
188
|
-
}
|
|
189
|
-
export async function readFreshCodexLbRoutingTruthStamp(options = {}) {
|
|
190
|
-
const truth = await readCodexLbRoutingTruthReceipt(options);
|
|
191
|
-
return truth?.measured === true && truth.fresh === true ? truth : null;
|
|
192
|
-
}
|
|
193
|
-
export const writeCodexLbRoutingTruthStamp = writeCodexLbRoutingTruthReceipt;
|
|
194
|
-
export const readCodexLbRoutingTruthStamp = readCodexLbRoutingTruthReceipt;
|
|
195
|
-
export async function measureAndWriteCodexLbRoutingTruth(measureOptions, receiptOptions = {}) {
|
|
196
|
-
const truth = await measureCodexLbRoutingTruth(measureOptions);
|
|
197
|
-
try {
|
|
198
|
-
return await writeCodexLbRoutingTruthReceipt(truth, receiptOptions);
|
|
199
|
-
}
|
|
200
|
-
catch {
|
|
201
|
-
if (!truth.selected)
|
|
202
|
-
return truth;
|
|
203
|
-
return {
|
|
204
|
-
...truth,
|
|
205
|
-
ok: false,
|
|
206
|
-
status: 'receipt_write_failed',
|
|
207
|
-
observed_status: truth.status,
|
|
208
|
-
blockers: uniqueStrings([...truth.blockers, 'codex_lb_routing_truth_receipt_write_failed'])
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
export function codexLbRoutingTruthIsActive(truth) {
|
|
213
|
-
return truth?.selected === true
|
|
214
|
-
&& truth.measured === true
|
|
215
|
-
&& truth.fresh === true
|
|
216
|
-
&& truth.ok === true
|
|
217
|
-
&& truth.status === 'verified';
|
|
218
|
-
}
|
|
219
|
-
function withFreshness(truth, options) {
|
|
220
|
-
const nowMs = (options.now || Date.now)();
|
|
221
|
-
const measuredMs = Date.parse(truth.measured_at);
|
|
222
|
-
const staleAfterMs = Math.max(1_000, Number(options.staleAfterMs || CODEX_LB_ROUTING_TRUTH_STALE_AFTER_MS));
|
|
223
|
-
const ageMs = Number.isFinite(measuredMs) ? Math.max(0, nowMs - measuredMs) : Number.POSITIVE_INFINITY;
|
|
224
|
-
const fresh = truth.measured && Number.isFinite(ageMs) && ageMs <= staleAfterMs;
|
|
225
|
-
if (fresh || !truth.selected) {
|
|
226
|
-
return { ...truth, fresh, stale_after_ms: staleAfterMs, age_ms: Number.isFinite(ageMs) ? ageMs : null };
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
...truth,
|
|
230
|
-
ok: false,
|
|
231
|
-
status: 'stale',
|
|
232
|
-
observed_status: truth.status,
|
|
233
|
-
fresh: false,
|
|
234
|
-
stale_after_ms: staleAfterMs,
|
|
235
|
-
age_ms: Number.isFinite(ageMs) ? ageMs : null,
|
|
236
|
-
blockers: uniqueStrings([...truth.blockers, 'codex_lb_routing_truth_stale'])
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
function parseReceipt(value) {
|
|
240
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
241
|
-
return null;
|
|
242
|
-
const input = value;
|
|
243
|
-
if (input.schema !== CODEX_LB_ROUTING_TRUTH_SCHEMA)
|
|
244
|
-
return null;
|
|
245
|
-
const status = String(input.status || '');
|
|
246
|
-
const statuses = [
|
|
247
|
-
'verified', 'selected_unmeasured', 'ready_unselected', 'missing_base_url', 'missing_api_key',
|
|
248
|
-
'transport_blocked', 'endpoint_unreachable', 'auth_rejected', 'http_error', 'stale',
|
|
249
|
-
'receipt_write_failed'
|
|
250
|
-
];
|
|
251
|
-
const authTransport = String(input.auth_transport || '');
|
|
252
|
-
const mode = String(input.mode || 'cli-provider');
|
|
253
|
-
const authOutcome = String(input.auth_outcome || '');
|
|
254
|
-
const measuredAt = stringOrNull(input.measured_at) || stringOrNull(input.checked_at);
|
|
255
|
-
if (!statuses.includes(status)
|
|
256
|
-
|| !['bridge', 'cli-provider'].includes(mode)
|
|
257
|
-
|| !['authorization-bearer', 'x-codex-lb-api-key'].includes(authTransport)
|
|
258
|
-
|| !['accepted', 'rejected', 'not_attempted', 'indeterminate'].includes(authOutcome)
|
|
259
|
-
|| !measuredAt
|
|
260
|
-
|| !Array.isArray(input.blockers))
|
|
261
|
-
return null;
|
|
262
|
-
return {
|
|
263
|
-
schema: CODEX_LB_ROUTING_TRUTH_SCHEMA,
|
|
264
|
-
ok: input.ok === true,
|
|
265
|
-
status,
|
|
266
|
-
...(typeof input.observed_status === 'string'
|
|
267
|
-
? { observed_status: input.observed_status }
|
|
268
|
-
: {}),
|
|
269
|
-
mode,
|
|
270
|
-
selected: input.selected === true,
|
|
271
|
-
measured: input.measured === true,
|
|
272
|
-
fresh: input.fresh === true,
|
|
273
|
-
stale_after_ms: finiteNumberOrNull(input.stale_after_ms) || CODEX_LB_ROUTING_TRUTH_STALE_AFTER_MS,
|
|
274
|
-
age_ms: finiteNumberOrNull(input.age_ms),
|
|
275
|
-
configured_base_url: safeReceiptUrl(input.configured_base_url),
|
|
276
|
-
configured_host: stringOrNull(input.configured_host),
|
|
277
|
-
actual_url: safeReceiptUrl(input.actual_url),
|
|
278
|
-
actual_host: stringOrNull(input.actual_host),
|
|
279
|
-
measurement_path: input.measurement_path === 'bridge-loopback'
|
|
280
|
-
? 'bridge-loopback'
|
|
281
|
-
: 'direct',
|
|
282
|
-
auth_transport: authTransport,
|
|
283
|
-
auth_outcome: authOutcome,
|
|
284
|
-
http_status: finiteNumberOrNull(input.http_status),
|
|
285
|
-
measured_at: measuredAt,
|
|
286
|
-
checked_at: measuredAt,
|
|
287
|
-
latency_ms: finiteNumberOrNull(input.latency_ms),
|
|
288
|
-
blockers: uniqueStrings(input.blockers.map(String))
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
function safeReceiptUrl(input) {
|
|
292
|
-
if (typeof input !== 'string')
|
|
293
|
-
return null;
|
|
294
|
-
return safePublicUrl(input)?.url || null;
|
|
295
|
-
}
|
|
296
|
-
function stringOrNull(input) {
|
|
297
|
-
return typeof input === 'string' && input ? input : null;
|
|
298
|
-
}
|
|
299
|
-
function finiteNumberOrNull(input) {
|
|
300
|
-
return typeof input === 'number' && Number.isFinite(input) && input >= 0 ? input : null;
|
|
301
|
-
}
|
|
302
|
-
function safePublicUrl(input) {
|
|
303
|
-
try {
|
|
304
|
-
const parsed = new URL(input);
|
|
305
|
-
parsed.username = '';
|
|
306
|
-
parsed.password = '';
|
|
307
|
-
parsed.search = '';
|
|
308
|
-
parsed.hash = '';
|
|
309
|
-
return {
|
|
310
|
-
url: parsed.toString().replace(/\/$/, ''),
|
|
311
|
-
host: parsed.host
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
catch {
|
|
315
|
-
return null;
|
|
316
|
-
}
|
|
317
|
-
}
|
|
318
|
-
function isHttpLoopbackUrl(input) {
|
|
319
|
-
try {
|
|
320
|
-
const parsed = new URL(input);
|
|
321
|
-
return parsed.protocol === 'http:'
|
|
322
|
-
&& (parsed.hostname === '127.0.0.1' || parsed.hostname === '::1');
|
|
323
|
-
}
|
|
324
|
-
catch {
|
|
325
|
-
return false;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import os from 'node:os';
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { readJson, readText } from '../fsx.js';
|
|
4
|
-
import { loadCodexLbEnv } from '../codex-lb/codex-lb-env.js';
|
|
5
|
-
export const CODEX_LB_IMAGEGEN_TARGET_SCHEMA = 'sks.codex-lb-imagegen-target.v1';
|
|
6
|
-
export async function resolveCodexLbImagegenTarget(opts = {}) {
|
|
7
|
-
const env = opts.env || process.env;
|
|
8
|
-
const home = opts.home || env.HOME || os.homedir();
|
|
9
|
-
const codexHome = opts.codexHome || env.CODEX_HOME || path.join(home, '.codex');
|
|
10
|
-
const configText = typeof opts.configText === 'string'
|
|
11
|
-
? opts.configText
|
|
12
|
-
: await readText(path.join(codexHome, 'config.toml'), '').catch(() => '');
|
|
13
|
-
const selected = topLevelTomlString(configText, 'model_provider') === 'codex-lb';
|
|
14
|
-
const authTransport = codexLbAuthTransport(configText);
|
|
15
|
-
const loaded = await loadCodexLbEnv({
|
|
16
|
-
home,
|
|
17
|
-
processEnv: {},
|
|
18
|
-
envPath: path.join(codexHome, 'sks-codex-lb.env'),
|
|
19
|
-
metadataPath: path.join(codexHome, 'sks-codex-lb.json')
|
|
20
|
-
}).catch(() => null);
|
|
21
|
-
const catalogModels = await readCatalogModels(configText, home, codexHome);
|
|
22
|
-
const explicit = String(opts.explicitModel || env.SKS_IMAGEGEN_RESPONSES_MODEL || '').trim();
|
|
23
|
-
const configuredModel = topLevelTomlString(configText, 'model');
|
|
24
|
-
const { model, model_source } = explicit
|
|
25
|
-
? { model: explicit, model_source: 'explicit' }
|
|
26
|
-
: catalogModels.includes(configuredModel)
|
|
27
|
-
? { model: configuredModel, model_source: 'configured_model_in_catalog' }
|
|
28
|
-
: catalogModels.length
|
|
29
|
-
? { model: catalogModels[0], model_source: 'catalog_default' }
|
|
30
|
-
: { model: null, model_source: null };
|
|
31
|
-
return {
|
|
32
|
-
schema: CODEX_LB_IMAGEGEN_TARGET_SCHEMA,
|
|
33
|
-
selected,
|
|
34
|
-
base_url: loaded?.base_url || null,
|
|
35
|
-
api_key: loaded?.secret_api_key || null,
|
|
36
|
-
api_key_source: loaded?.api_key?.source || null,
|
|
37
|
-
auth_transport: authTransport,
|
|
38
|
-
model,
|
|
39
|
-
model_source,
|
|
40
|
-
catalog_models: catalogModels,
|
|
41
|
-
blocker: codexLbImagegenBlocker({ selected, loaded, model })
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
function codexLbAuthTransport(configText) {
|
|
45
|
-
const provider = String(configText || '').match(/(?:^|\n)\[model_providers\.codex-lb\]([\s\S]*?)(?=\n\[[^\]]+\]|\s*$)/)?.[1] || '';
|
|
46
|
-
const customHeader = /(?:^|\n)\s*env_http_headers\s*=\s*\{[^}]*"X-Codex-LB-API-Key"\s*=\s*"CODEX_LB_API_KEY"[^}]*\}/.test(provider);
|
|
47
|
-
const bearerEnvKey = /(?:^|\n)\s*env_key\s*=/.test(provider);
|
|
48
|
-
return customHeader && !bearerEnvKey ? 'x-codex-lb-api-key' : 'authorization-bearer';
|
|
49
|
-
}
|
|
50
|
-
function codexLbImagegenBlocker(state) {
|
|
51
|
-
if (!state.selected)
|
|
52
|
-
return 'codex_lb_not_selected';
|
|
53
|
-
if (!state.loaded?.base_url)
|
|
54
|
-
return 'codex_lb_base_url_missing';
|
|
55
|
-
if (!state.loaded?.secret_api_key)
|
|
56
|
-
return state.loaded?.missing?.includes('CODEX_LB_CREDENTIAL_BINDING')
|
|
57
|
-
? 'codex_lb_credential_binding_invalid'
|
|
58
|
-
: 'codex_lb_api_key_missing';
|
|
59
|
-
if (!state.model)
|
|
60
|
-
return 'codex_lb_imagegen_model_unresolved';
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
async function readCatalogModels(configText, home, codexHome) {
|
|
64
|
-
const configured = topLevelTomlString(configText, 'model_catalog_json');
|
|
65
|
-
const candidates = [
|
|
66
|
-
configured ? resolveCatalogPath(configured, home, codexHome) : '',
|
|
67
|
-
path.join(codexHome, 'sks-codex-lb-tool-catalog.json')
|
|
68
|
-
].filter(Boolean);
|
|
69
|
-
for (const file of candidates) {
|
|
70
|
-
const payload = await readJson(file, null).catch(() => null);
|
|
71
|
-
const rows = Array.isArray(payload?.models) ? payload.models : Array.isArray(payload?.data) ? payload.data : [];
|
|
72
|
-
const slugs = rows
|
|
73
|
-
.filter((row) => row?.supported_in_api !== false && !hiddenCatalogRow(row))
|
|
74
|
-
.map((row) => String(row?.slug || row?.id || row?.model || '').trim())
|
|
75
|
-
.filter(Boolean);
|
|
76
|
-
if (slugs.length)
|
|
77
|
-
return [...new Set(slugs)];
|
|
78
|
-
}
|
|
79
|
-
return [];
|
|
80
|
-
}
|
|
81
|
-
function resolveCatalogPath(configured, home, codexHome) {
|
|
82
|
-
const expanded = configured.replace(/^~(?=\/|$)/, home);
|
|
83
|
-
return path.isAbsolute(expanded) ? expanded : path.resolve(codexHome, expanded);
|
|
84
|
-
}
|
|
85
|
-
function hiddenCatalogRow(row) {
|
|
86
|
-
return ['hide', 'hidden', 'internal', 'none', 'unavailable'].includes(String(row?.visibility || '').trim().toLowerCase());
|
|
87
|
-
}
|
|
88
|
-
function topLevelTomlString(text, key) {
|
|
89
|
-
const topLevel = String(text || '').split(/\n\s*\[/)[0] || '';
|
|
90
|
-
const re = new RegExp(`(^|\\n)\\s*${key.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s*=\\s*"([^"]*)"\\s*(?:#.*)?(?=\\n|$)`);
|
|
91
|
-
return topLevel.match(re)?.[2] || '';
|
|
92
|
-
}
|
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
import Cocoa
|
|
2
|
-
|
|
3
|
-
extension ProvidersViewController {
|
|
4
|
-
func makeCliConnectProgressView() -> NSStackView {
|
|
5
|
-
cliConnectConfigurationStage.setAccessibilityLabel("Codex LB configuration stage: waiting")
|
|
6
|
-
cliConnectConfigurationStage.setAccessibilityIdentifier("sks-center-codex-lb-configuration-stage")
|
|
7
|
-
cliConnectRequestStage.setAccessibilityLabel("Codex LB one-request low-token test stage: waiting")
|
|
8
|
-
cliConnectRequestStage.setAccessibilityIdentifier("sks-center-codex-lb-request-stage")
|
|
9
|
-
cliConnectResponseStage.setAccessibilityLabel("Codex LB response stage: not received")
|
|
10
|
-
cliConnectResponseStage.setAccessibilityIdentifier("sks-center-codex-lb-response-stage")
|
|
11
|
-
cliConnectResult.setAccessibilityLabel("Codex LB connection proof result: not run")
|
|
12
|
-
cliConnectResult.setAccessibilityIdentifier("sks-center-codex-lb-connect-result")
|
|
13
|
-
let title = NativeView.sectionTitle("Connection Proof")
|
|
14
|
-
title.setAccessibilityIdentifier("sks-center-codex-lb-connect-heading")
|
|
15
|
-
let stack = NSStackView(views: [title, cliConnectProgress, cliConnectConfigurationStage, cliConnectRequestStage, cliConnectResponseStage, cliConnectResult])
|
|
16
|
-
stack.orientation = .vertical
|
|
17
|
-
stack.alignment = .width
|
|
18
|
-
stack.spacing = 6
|
|
19
|
-
stack.setAccessibilityRole(.group)
|
|
20
|
-
stack.setAccessibilityLabel("Codex LB connection proof")
|
|
21
|
-
stack.setAccessibilityIdentifier("sks-center-codex-lb-connect-proof")
|
|
22
|
-
return stack
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
func renderCliConnectStages(
|
|
26
|
-
progress: Double,
|
|
27
|
-
configuration: String,
|
|
28
|
-
request: String,
|
|
29
|
-
response: String,
|
|
30
|
-
result: String,
|
|
31
|
-
tone: NSColor
|
|
32
|
-
) {
|
|
33
|
-
cliConnectProgress.doubleValue = min(3, max(0, progress))
|
|
34
|
-
cliConnectProgress.setAccessibilityValue("Stage \(Int(cliConnectProgress.doubleValue)) of 3")
|
|
35
|
-
cliConnectConfigurationStage.stringValue = "1. Configuration · \(configuration)"
|
|
36
|
-
cliConnectConfigurationStage.setAccessibilityLabel("Codex LB configuration stage: \(configuration)")
|
|
37
|
-
cliConnectRequestStage.stringValue = "2. One-request low-token test · \(request)"
|
|
38
|
-
cliConnectRequestStage.setAccessibilityLabel("Codex LB one-request low-token test stage: \(request)")
|
|
39
|
-
cliConnectResponseStage.stringValue = "3. Response · \(response)"
|
|
40
|
-
cliConnectResponseStage.setAccessibilityLabel("Codex LB response stage: \(response)")
|
|
41
|
-
cliConnectResult.stringValue = result
|
|
42
|
-
cliConnectResult.textColor = tone
|
|
43
|
-
cliConnectResult.setAccessibilityLabel("Codex LB connection proof result: \(result)")
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
@objc func testConnection() {
|
|
47
|
-
runConnectTest()
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
func runConnectTest() {
|
|
51
|
-
guard !connectTestInFlight else {
|
|
52
|
-
cliProviderStatus.stringValue = "A Codex LB connection proof is already running."
|
|
53
|
-
return
|
|
54
|
-
}
|
|
55
|
-
guard !busy else { cliProviderStatus.stringValue = "Another provider action is already running."; return }
|
|
56
|
-
guard let snapshot = operations.begin(kind: "codex-lb-connect-test", mutationGroup: nil, summary: "Run Codex LB connect test") else {
|
|
57
|
-
cliProviderStatus.stringValue = "Another guarded operation is already running. Wait or open Diagnostics."
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
connectTestInFlight = true
|
|
61
|
-
setBusy(true)
|
|
62
|
-
cliProviderStatus.stringValue = "Codex LB mode \(codexLbSelectedNow ? "selected" : "selection unconfirmed") · sending one bounded low-token request…"
|
|
63
|
-
renderCliConnectStages(
|
|
64
|
-
progress: 2,
|
|
65
|
-
configuration: codexLbSelectedNow ? "CLI provider selected" : "selection unconfirmed",
|
|
66
|
-
request: "sending one bounded request…",
|
|
67
|
-
response: "waiting",
|
|
68
|
-
result: "Waiting for structured proof. Connectivity has not been claimed.",
|
|
69
|
-
tone: .secondaryLabelColor
|
|
70
|
-
)
|
|
71
|
-
_ = operations.update(snapshot, state: .running, stage: "one-request-low-token-test", progress: 2.0 / 3.0, summary: "Run Codex LB connect test")
|
|
72
|
-
processClient.run(["codex-lb", "connect-test", "--json"], timeout: NativeView.mutationTimeout) { [weak self] result in
|
|
73
|
-
guard let self = self else { return }
|
|
74
|
-
self.connectTestInFlight = false
|
|
75
|
-
self.setBusy(false)
|
|
76
|
-
let parsed = self.json(result.output)
|
|
77
|
-
let proof = parsed.flatMap(CodexLbConnectTestTruth.success(from:))
|
|
78
|
-
let proved = result.code == 0 && proof != nil
|
|
79
|
-
_ = self.operations.update(snapshot, state: proved ? .succeeded : .failed, stage: "complete", progress: 1, summary: proved ? "Codex LB connection proved" : "Codex LB connection proof failed")
|
|
80
|
-
if let proof = proof, result.code == 0 {
|
|
81
|
-
self.codexLbSelectedNow = true
|
|
82
|
-
self.codexLbProvedNow = true
|
|
83
|
-
self.cliProviderStatus.stringValue = "Codex LB mode selected · connection proved by one live response."
|
|
84
|
-
ControlKit.setBadge(self.activeProviderBadge, text: "Codex LB · active · model \(proof.model) · \(proof.latencyMs) ms", tone: .ok)
|
|
85
|
-
self.renderCliConnectStages(
|
|
86
|
-
progress: 3,
|
|
87
|
-
configuration: "CLI provider selected",
|
|
88
|
-
request: "completed · \(proof.outputTokens) output tokens",
|
|
89
|
-
response: "received · id \(proof.responseId)",
|
|
90
|
-
result: proof.renderedSummary,
|
|
91
|
-
tone: .systemGreen
|
|
92
|
-
)
|
|
93
|
-
return
|
|
94
|
-
}
|
|
95
|
-
self.codexLbProvedNow = false
|
|
96
|
-
let selected = self.codexLbSelectedNow
|
|
97
|
-
let code = self.publicFailureCode(parsed)
|
|
98
|
-
let failure = parsed.map(CodexLbConnectTestTruth.validationFailure(from:))
|
|
99
|
-
?? "structured connect-test JSON was not returned"
|
|
100
|
-
self.cliProviderStatus.stringValue = selected
|
|
101
|
-
? "Codex LB mode is selected, but connection proof failed · \(code) · \(failure)."
|
|
102
|
-
: "Codex LB connection proof failed and provider selection is unconfirmed · \(code) · \(failure)."
|
|
103
|
-
if selected {
|
|
104
|
-
ControlKit.setBadge(self.activeProviderBadge, text: "Codex LB · selected · \(code) · connection proof failed", tone: .warning)
|
|
105
|
-
}
|
|
106
|
-
self.renderCliConnectStages(
|
|
107
|
-
progress: 3,
|
|
108
|
-
configuration: selected ? "CLI provider remains selected" : "selection unconfirmed",
|
|
109
|
-
request: "completed without valid proof",
|
|
110
|
-
response: "failed",
|
|
111
|
-
result: selected
|
|
112
|
-
? "\(code) · Mode is selected, but connection proof failed · \(failure). Use Run Connect Test to retry."
|
|
113
|
-
: "\(code) · Connection proof failed · \(failure). Confirm the provider, then retry.",
|
|
114
|
-
tone: .systemRed
|
|
115
|
-
)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import Cocoa
|
|
2
|
-
|
|
3
|
-
extension ProvidersViewController {
|
|
4
|
-
func refreshFastStatus() {
|
|
5
|
-
if !busy { fastStatus.stringValue = "Codex Fast: checking the official service-tier setting…" }
|
|
6
|
-
processClient.run(["fast-mode", "status", "--json"], timeout: NativeView.statusTimeout) { [weak self] result in
|
|
7
|
-
guard let self = self else { return }
|
|
8
|
-
guard result.code == 0, let json = self.json(result.output),
|
|
9
|
-
let global = json["global"] as? [String: Any], let on = global["on"] as? Bool else {
|
|
10
|
-
self.fastStatus.stringValue = "Codex Fast: unavailable — no state was assumed."
|
|
11
|
-
return
|
|
12
|
-
}
|
|
13
|
-
let tier = global["service_tier"] as? String ?? (on ? "fast" : "default")
|
|
14
|
-
self.fastStatus.stringValue = "Codex Fast: \(on ? "On" : "Off") · official service_tier=\(tier) · model and reasoning remain separate."
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|