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
package/dist/cli/router.js
CHANGED
|
@@ -23,7 +23,7 @@ export function prepareRouterExecutionIntent(argv, inheritance = {}) {
|
|
|
23
23
|
observedChangedPaths: parent.observed_changed_paths,
|
|
24
24
|
targetHashes: parent.target_hashes,
|
|
25
25
|
policyVersion: parent.policy_version,
|
|
26
|
-
|
|
26
|
+
runtimeSnapshot: parent.runtime_snapshot,
|
|
27
27
|
evidenceState: parent.evidence_state,
|
|
28
28
|
retryBudget: parent.retry_budget,
|
|
29
29
|
requestedRisk: parent.risk,
|
|
@@ -41,7 +41,7 @@ export function prepareRouterExecutionIntent(argv, inheritance = {}) {
|
|
|
41
41
|
effect: inheritance.effect || classifyCliIntentEffect(effectiveArgv),
|
|
42
42
|
targetHashes: [createHash('sha256').update(`${process.cwd()}\0${effectiveArgv[0] || 'doctor'}`).digest('hex')],
|
|
43
43
|
policyVersion: 'sks-cli-router-v1',
|
|
44
|
-
|
|
44
|
+
runtimeSnapshot: inheritance.runtimeSnapshot || 'desktop-bridge',
|
|
45
45
|
evidenceState: inheritance.evidenceState || 'missing',
|
|
46
46
|
retryBudget: inheritance.retryBudget ?? 0,
|
|
47
47
|
force: effectiveArgv.includes('--force'),
|
|
@@ -104,12 +104,6 @@ export async function dispatch(args) {
|
|
|
104
104
|
return result;
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
-
function providerModeFromEnvironment() {
|
|
108
|
-
const mode = String(process.env.SKS_PROVIDER_MODE || '').trim();
|
|
109
|
-
return mode === 'codex-lb' || mode === 'openrouter' || mode === 'chatgpt-oauth'
|
|
110
|
-
? mode
|
|
111
|
-
: 'chatgpt-oauth';
|
|
112
|
-
}
|
|
113
107
|
function classifyCliIntentEffect(argv) {
|
|
114
108
|
const normalized = normalizeCommand(argv);
|
|
115
109
|
const command = normalized.command;
|
|
@@ -133,7 +127,7 @@ function classifyCliIntentEffect(argv) {
|
|
|
133
127
|
async function dispatchInner(argv) {
|
|
134
128
|
const retiredGlm = findRetiredGlobalExecutionArgumentErrors(argv).filter((item) => item.includes('--glm'));
|
|
135
129
|
if (retiredGlm.length && argv.some((arg) => arg === '--glm' || String(arg).startsWith('--glm='))) {
|
|
136
|
-
const hint = 'GLM MAD CLI was removed. Use
|
|
130
|
+
const hint = 'GLM MAD CLI was removed. Use sks bridge provider configure|validate|enable, sks bridge catalog sync, and sks bridge route set-default.';
|
|
137
131
|
console.error(hint);
|
|
138
132
|
process.exitCode = 1;
|
|
139
133
|
const result = {
|
|
@@ -356,6 +350,12 @@ export function safeActiveRouteContinuation(command, args, state = {}) {
|
|
|
356
350
|
return Boolean(state.mission_id)
|
|
357
351
|
&& (requestedMission === String(state.mission_id) || requestedMission === 'latest');
|
|
358
352
|
}
|
|
353
|
+
if (command === 'align') {
|
|
354
|
+
if (activeRoute !== 'ALIGN' || !['run', 'proof'].includes(subcommand))
|
|
355
|
+
return false;
|
|
356
|
+
const requestedMission = String(args[1] || '').trim();
|
|
357
|
+
return Boolean(state.mission_id) && requestedMission === String(state.mission_id);
|
|
358
|
+
}
|
|
359
359
|
const expectedRoutes = new Map([
|
|
360
360
|
['research', ['RESEARCH']],
|
|
361
361
|
['autoresearch', ['AUTORESEARCH', 'RESEARCH']],
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { redactString, REDACTION_MARKER } from '../core/secret-redaction.js';
|
|
2
|
+
import { validateDesktopCapabilityReportV3 } from '../core/codex-lb/bridge-runtime-validation.js';
|
|
3
|
+
const COMMAND_SCHEMA = 'sks.bridge-command.v1';
|
|
4
|
+
const ERROR_SCHEMA = 'sks.bridge-command-error.v1';
|
|
5
|
+
export class BridgeCliError extends Error {
|
|
6
|
+
code;
|
|
7
|
+
recoveryAction;
|
|
8
|
+
constructor(code, recoveryAction = 'review_bridge_command_help') {
|
|
9
|
+
super(code);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.recoveryAction = recoveryAction;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function verificationOutput(value, level, strict) {
|
|
15
|
+
const report = record(value);
|
|
16
|
+
const reportGenerated = validateDesktopCapabilityReportV3(value).ok;
|
|
17
|
+
if (!reportGenerated) {
|
|
18
|
+
return errorOutput('capability_schema_invalid', 'update_sks_and_rebuild_menubar');
|
|
19
|
+
}
|
|
20
|
+
const executionOk = record(report.execution).ok === true;
|
|
21
|
+
const summary = record(report.summary);
|
|
22
|
+
const levelSatisfied = summary.level_satisfied === true;
|
|
23
|
+
const fullFeatureVerified = summary.full_feature_verified === true;
|
|
24
|
+
return {
|
|
25
|
+
...report,
|
|
26
|
+
ok: executionOk && (!strict || levelSatisfied),
|
|
27
|
+
execution_ok: executionOk,
|
|
28
|
+
report_generated: true,
|
|
29
|
+
requested_level: level,
|
|
30
|
+
level_satisfied: levelSatisfied,
|
|
31
|
+
full_feature_verified: fullFeatureVerified,
|
|
32
|
+
strict
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export function ordinaryOutput(value, label) {
|
|
36
|
+
const result = record(value);
|
|
37
|
+
if (Object.keys(result).length === 0 || typeof result.schema !== 'string') {
|
|
38
|
+
return errorOutput('bridge_controller_response_invalid', 'update_sks_and_rebuild_bridge_controller');
|
|
39
|
+
}
|
|
40
|
+
const executionOk = result.execution_ok === false
|
|
41
|
+
? false
|
|
42
|
+
: result.ok === false
|
|
43
|
+
? false
|
|
44
|
+
: record(result.execution).ok === false
|
|
45
|
+
? false
|
|
46
|
+
: true;
|
|
47
|
+
return {
|
|
48
|
+
...result,
|
|
49
|
+
schema: typeof result.schema === 'string' ? result.schema : COMMAND_SCHEMA,
|
|
50
|
+
ok: executionOk,
|
|
51
|
+
execution_ok: executionOk,
|
|
52
|
+
command_summary: label
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
export function errorOutput(blocker, recoveryAction, error) {
|
|
56
|
+
return {
|
|
57
|
+
schema: ERROR_SCHEMA,
|
|
58
|
+
ok: false,
|
|
59
|
+
execution_ok: false,
|
|
60
|
+
status: 'failed',
|
|
61
|
+
blockers: [blocker],
|
|
62
|
+
recovery_action: recoveryAction,
|
|
63
|
+
...(error instanceof BridgeCliError
|
|
64
|
+
? {}
|
|
65
|
+
: error instanceof Error
|
|
66
|
+
? { error: redactString(error.message) }
|
|
67
|
+
: {})
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
export function sanitizeBridgeValue(value, secrets) {
|
|
71
|
+
if (typeof value === 'string') {
|
|
72
|
+
let text = redactString(value);
|
|
73
|
+
for (const secret of secrets)
|
|
74
|
+
text = text.split(secret).join(REDACTION_MARKER);
|
|
75
|
+
return text;
|
|
76
|
+
}
|
|
77
|
+
if (Array.isArray(value))
|
|
78
|
+
return value.map((entry) => sanitizeBridgeValue(entry, secrets));
|
|
79
|
+
if (!value || typeof value !== 'object')
|
|
80
|
+
return value;
|
|
81
|
+
const output = {};
|
|
82
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
83
|
+
output[key] = isSecretValueKey(key)
|
|
84
|
+
? REDACTION_MARKER
|
|
85
|
+
: sanitizeBridgeValue(entry, secrets);
|
|
86
|
+
}
|
|
87
|
+
return output;
|
|
88
|
+
}
|
|
89
|
+
function isSecretValueKey(key) {
|
|
90
|
+
return /^(?:api_key|secret|token|password|authorization|bearer|cookie|set_cookie)$/i.test(key)
|
|
91
|
+
|| /(?:^|_)(?:api_key|secret|token|password|authorization)$/i.test(key)
|
|
92
|
+
|| /^(?:headers?|env)$/i.test(key);
|
|
93
|
+
}
|
|
94
|
+
export function mergeMetadata(output, metadata) {
|
|
95
|
+
return metadata ? { ...output, ...metadata } : output;
|
|
96
|
+
}
|
|
97
|
+
export function textSummary(output) {
|
|
98
|
+
const status = output.ok === false ? 'failed' : 'completed';
|
|
99
|
+
const summary = typeof output.command_summary === 'string'
|
|
100
|
+
? output.command_summary
|
|
101
|
+
: 'Desktop Bridge command';
|
|
102
|
+
const blockers = Array.isArray(output.blockers)
|
|
103
|
+
? output.blockers.map(String).filter(Boolean).join(', ')
|
|
104
|
+
: '';
|
|
105
|
+
return blockers ? `${summary}: ${status} (${blockers})` : `${summary}: ${status}`;
|
|
106
|
+
}
|
|
107
|
+
function record(value) {
|
|
108
|
+
return value && typeof value === 'object' && !Array.isArray(value)
|
|
109
|
+
? value
|
|
110
|
+
: {};
|
|
111
|
+
}
|
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { readStdin } from '../core/fsx.js';
|
|
3
|
+
import { serveDesktopBridge } from '../core/codex-lb/desktop-service.js';
|
|
4
|
+
import { BridgeCliError, errorOutput, mergeMetadata, ordinaryOutput, sanitizeBridgeValue, textSummary, verificationOutput } from './bridge-command-output.js';
|
|
5
|
+
const CONTROLLER_FACADE_EXPORT = 'executeDesktopBridgeCommand';
|
|
6
|
+
const MAX_STDIN_SECRET_BYTES = 64 * 1024;
|
|
7
|
+
const DEFAULT_IO = {
|
|
8
|
+
readStdin,
|
|
9
|
+
stdout: (text) => process.stdout.write(text),
|
|
10
|
+
stderr: (text) => process.stderr.write(text),
|
|
11
|
+
setExitCode: (code) => {
|
|
12
|
+
process.exitCode = code;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export function usage(command = 'bridge') {
|
|
16
|
+
return [
|
|
17
|
+
`Usage: sks ${command} status [--json]`,
|
|
18
|
+
` sks ${command} ensure|repair [--json]`,
|
|
19
|
+
` sks ${command} verify --level shallow|transport|deep [--strict|--require-ready] [--json]`,
|
|
20
|
+
` sks ${command} provider list [--json]`,
|
|
21
|
+
` sks ${command} provider configure codex-lb --host <host> --api-key-stdin [--json]`,
|
|
22
|
+
` sks ${command} provider configure openrouter --api-key-stdin [--json]`,
|
|
23
|
+
` sks ${command} provider validate|enable|disable <codex-lb|openrouter> [--json]`,
|
|
24
|
+
` sks ${command} provider remove-credential <codex-lb|openrouter> --confirm [--json]`,
|
|
25
|
+
` sks ${command} catalog sync|status [--json]`,
|
|
26
|
+
` sks ${command} route list [--json]`,
|
|
27
|
+
` sks ${command} route set-default <codex-lb|openrouter> [--json]`,
|
|
28
|
+
` sks ${command} route explain <model> [--json]`,
|
|
29
|
+
` sks ${command} unmanage --confirm [--json]`,
|
|
30
|
+
` sks ${command} rollback <receipt-id> --confirm [--json]`,
|
|
31
|
+
'',
|
|
32
|
+
'Provider secrets are accepted only through --api-key-stdin. Readiness changes the exit code only with --strict or --require-ready.'
|
|
33
|
+
].join('\n');
|
|
34
|
+
}
|
|
35
|
+
export async function run(_command, args = []) {
|
|
36
|
+
return runBridgeCommand(args);
|
|
37
|
+
}
|
|
38
|
+
export async function runBridgeCommand(args = [], options = {}) {
|
|
39
|
+
const io = options.io || DEFAULT_IO;
|
|
40
|
+
const execution = await executeBridgeCommand(args, options);
|
|
41
|
+
if (execution.json) {
|
|
42
|
+
io.stdout(`${JSON.stringify(execution.output, null, 2)}\n`);
|
|
43
|
+
}
|
|
44
|
+
else if (execution.exit_code === 0) {
|
|
45
|
+
io.stdout(`${textSummary(execution.output)}\n`);
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
io.stderr(`${textSummary(execution.output)}\n`);
|
|
49
|
+
}
|
|
50
|
+
if (execution.exit_code !== 0)
|
|
51
|
+
io.setExitCode(execution.exit_code);
|
|
52
|
+
return execution.output;
|
|
53
|
+
}
|
|
54
|
+
export async function executeBridgeCommand(args = [], options = {}) {
|
|
55
|
+
const io = options.io || DEFAULT_IO;
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = await parseInvocation(args, io);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
const bridgeError = error instanceof BridgeCliError
|
|
62
|
+
? error
|
|
63
|
+
: new BridgeCliError('bridge_command_parse_failed');
|
|
64
|
+
const output = errorOutput(bridgeError.code, bridgeError.recoveryAction, error);
|
|
65
|
+
return {
|
|
66
|
+
output: mergeMetadata(output, options.metadata),
|
|
67
|
+
json: args.includes('--json'),
|
|
68
|
+
exit_code: 1
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
try {
|
|
72
|
+
const raw = parsed.request.operation === 'serve'
|
|
73
|
+
? await (options.serve || serveDesktopBridge)({ settingsPath: parsed.request.settings_path })
|
|
74
|
+
: await (options.facade || await loadBridgeCommandFacade()).execute(parsed.request);
|
|
75
|
+
const output = parsed.request.operation === 'verify'
|
|
76
|
+
? verificationOutput(raw, parsed.request.level, parsed.strict)
|
|
77
|
+
: ordinaryOutput(raw, parsed.label);
|
|
78
|
+
const sanitized = sanitizeBridgeValue(output, parsed.secrets);
|
|
79
|
+
const decorated = mergeMetadata(sanitized, options.metadata);
|
|
80
|
+
return {
|
|
81
|
+
output: decorated,
|
|
82
|
+
json: parsed.json,
|
|
83
|
+
exit_code: decorated.ok === false ? 1 : 0
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
const output = sanitizeBridgeValue(errorOutput(error instanceof BridgeCliError ? error.code : 'bridge_command_internal_error', error instanceof BridgeCliError ? error.recoveryAction : 'retry_or_run_bridge_status', error), parsed.secrets);
|
|
88
|
+
return {
|
|
89
|
+
output: mergeMetadata(output, options.metadata),
|
|
90
|
+
json: parsed.json,
|
|
91
|
+
exit_code: 1
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
export async function loadBridgeCommandFacade() {
|
|
96
|
+
const controller = await import('../core/codex-lb/desktop-controller.js');
|
|
97
|
+
const execute = controller[CONTROLLER_FACADE_EXPORT];
|
|
98
|
+
if (typeof execute !== 'function') {
|
|
99
|
+
throw new BridgeCliError(`bridge_controller_facade_unavailable:${CONTROLLER_FACADE_EXPORT}`, 'update_sks_and_rebuild_bridge_controller');
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
execute: (request) => Promise.resolve(execute(request))
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
async function parseInvocation(args, io) {
|
|
106
|
+
rejectSecretArgv(args);
|
|
107
|
+
const parsed = parseArgs(args);
|
|
108
|
+
const [area = 'status', action, target, extra] = parsed.positionals;
|
|
109
|
+
const json = parsed.flags.has('--json');
|
|
110
|
+
const strict = parsed.flags.has('--strict') || parsed.flags.has('--require-ready');
|
|
111
|
+
const base = { json, strict, secrets: [] };
|
|
112
|
+
if (area === 'status' && action === undefined) {
|
|
113
|
+
allowOnly(parsed, ['--json'], []);
|
|
114
|
+
return { ...base, request: { operation: 'status' }, label: 'Desktop Bridge status' };
|
|
115
|
+
}
|
|
116
|
+
if (area === 'serve' && action === undefined) {
|
|
117
|
+
allowOnly(parsed, ['--json'], ['--settings']);
|
|
118
|
+
const settingsPath = parsed.values.get('--settings') || '';
|
|
119
|
+
if (!path.isAbsolute(settingsPath)) {
|
|
120
|
+
throw new BridgeCliError('desktop_bridge_settings_path_must_be_absolute');
|
|
121
|
+
}
|
|
122
|
+
if (path.basename(settingsPath) !== 'desktop-bridge-settings.json') {
|
|
123
|
+
throw new BridgeCliError('desktop_bridge_settings_path_invalid');
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
...base,
|
|
127
|
+
request: { operation: 'serve', settings_path: settingsPath },
|
|
128
|
+
label: 'Desktop Bridge service'
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if ((area === 'ensure' || area === 'repair') && action === undefined) {
|
|
132
|
+
allowOnly(parsed, ['--json'], []);
|
|
133
|
+
return { ...base, request: { operation: area }, label: `Desktop Bridge ${area}` };
|
|
134
|
+
}
|
|
135
|
+
if (area === 'verify' && action === undefined) {
|
|
136
|
+
allowOnly(parsed, ['--json', '--strict', '--require-ready'], ['--level']);
|
|
137
|
+
const level = capabilityLevel(parsed.values.get('--level') || 'shallow');
|
|
138
|
+
return {
|
|
139
|
+
...base,
|
|
140
|
+
request: { operation: 'verify', level },
|
|
141
|
+
label: `Desktop Bridge ${level} verification`
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
if (area === 'provider') {
|
|
145
|
+
if (action === 'list' && target === undefined) {
|
|
146
|
+
allowOnly(parsed, ['--json'], []);
|
|
147
|
+
return { ...base, request: { operation: 'provider.list' }, label: 'Bridge provider list' };
|
|
148
|
+
}
|
|
149
|
+
if (action === 'configure' && target !== undefined && extra === undefined) {
|
|
150
|
+
allowOnly(parsed, ['--json', '--api-key-stdin'], ['--host']);
|
|
151
|
+
const providerId = provider(target);
|
|
152
|
+
if (!parsed.flags.has('--api-key-stdin')) {
|
|
153
|
+
throw new BridgeCliError('bridge_provider_api_key_stdin_required', 'retry_with_api_key_stdin');
|
|
154
|
+
}
|
|
155
|
+
const host = parsed.values.get('--host');
|
|
156
|
+
if (providerId === 'codex-lb' && !host) {
|
|
157
|
+
throw new BridgeCliError('codex_lb_host_required', 'retry_with_codex_lb_host');
|
|
158
|
+
}
|
|
159
|
+
const apiKey = (await io.readStdin()).trim();
|
|
160
|
+
if (!apiKey)
|
|
161
|
+
throw new BridgeCliError('bridge_provider_api_key_stdin_empty', 'retry_with_api_key_stdin');
|
|
162
|
+
if (Buffer.byteLength(apiKey, 'utf8') > MAX_STDIN_SECRET_BYTES) {
|
|
163
|
+
throw new BridgeCliError('bridge_provider_api_key_stdin_too_large', 'retry_with_valid_api_key');
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
...base,
|
|
167
|
+
secrets: [apiKey],
|
|
168
|
+
request: {
|
|
169
|
+
operation: 'provider.configure',
|
|
170
|
+
provider_id: providerId,
|
|
171
|
+
api_key: apiKey,
|
|
172
|
+
...(host ? { host } : {})
|
|
173
|
+
},
|
|
174
|
+
label: `${providerId} credential configuration`
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
if ((action === 'validate' || action === 'enable' || action === 'disable')
|
|
178
|
+
&& target !== undefined
|
|
179
|
+
&& extra === undefined) {
|
|
180
|
+
allowOnly(parsed, ['--json'], []);
|
|
181
|
+
const providerId = provider(target);
|
|
182
|
+
return {
|
|
183
|
+
...base,
|
|
184
|
+
request: { operation: `provider.${action}`, provider_id: providerId },
|
|
185
|
+
label: `${providerId} ${action}`
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
if (action === 'remove-credential' && target !== undefined && extra === undefined) {
|
|
189
|
+
allowOnly(parsed, ['--json', '--confirm'], []);
|
|
190
|
+
requireConfirmation(parsed);
|
|
191
|
+
const providerId = provider(target);
|
|
192
|
+
return {
|
|
193
|
+
...base,
|
|
194
|
+
request: { operation: 'provider.remove-credential', provider_id: providerId, confirmed: true },
|
|
195
|
+
label: `${providerId} credential removal`
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
if (area === 'catalog' && (action === 'sync' || action === 'status') && target === undefined) {
|
|
200
|
+
allowOnly(parsed, ['--json'], []);
|
|
201
|
+
return {
|
|
202
|
+
...base,
|
|
203
|
+
request: { operation: `catalog.${action}` },
|
|
204
|
+
label: `Combined catalog ${action}`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
if (area === 'route') {
|
|
208
|
+
if (action === 'list' && target === undefined) {
|
|
209
|
+
allowOnly(parsed, ['--json'], []);
|
|
210
|
+
return { ...base, request: { operation: 'route.list' }, label: 'Bridge route list' };
|
|
211
|
+
}
|
|
212
|
+
if (action === 'set-default' && target !== undefined && extra === undefined) {
|
|
213
|
+
allowOnly(parsed, ['--json'], []);
|
|
214
|
+
const providerId = provider(target);
|
|
215
|
+
return {
|
|
216
|
+
...base,
|
|
217
|
+
request: { operation: 'route.set-default', provider_id: providerId },
|
|
218
|
+
label: `Default bridge provider set to ${providerId}`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
if (action === 'explain' && target !== undefined && extra === undefined) {
|
|
222
|
+
allowOnly(parsed, ['--json'], []);
|
|
223
|
+
return {
|
|
224
|
+
...base,
|
|
225
|
+
request: { operation: 'route.explain', model: target },
|
|
226
|
+
label: `Bridge route explanation for ${target}`
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
if (area === 'unmanage' && action === undefined) {
|
|
231
|
+
allowOnly(parsed, ['--json', '--confirm'], []);
|
|
232
|
+
requireConfirmation(parsed);
|
|
233
|
+
return {
|
|
234
|
+
...base,
|
|
235
|
+
request: { operation: 'unmanage', confirmed: true },
|
|
236
|
+
label: 'Desktop Bridge unmanage'
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (area === 'rollback' && action !== undefined && target === undefined) {
|
|
240
|
+
allowOnly(parsed, ['--json', '--confirm'], []);
|
|
241
|
+
requireConfirmation(parsed);
|
|
242
|
+
return {
|
|
243
|
+
...base,
|
|
244
|
+
request: { operation: 'rollback', receipt_id: action, confirmed: true },
|
|
245
|
+
label: `Desktop Bridge rollback ${action}`
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
throw new BridgeCliError('bridge_command_invalid', 'review_bridge_command_help');
|
|
249
|
+
}
|
|
250
|
+
function parseArgs(args) {
|
|
251
|
+
const positionals = [];
|
|
252
|
+
const flags = new Set();
|
|
253
|
+
const values = new Map();
|
|
254
|
+
const booleanOptions = new Set([
|
|
255
|
+
'--json', '--strict', '--require-ready', '--api-key-stdin', '--confirm'
|
|
256
|
+
]);
|
|
257
|
+
const valueOptions = new Set(['--level', '--host', '--settings']);
|
|
258
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
259
|
+
const value = String(args[index] || '');
|
|
260
|
+
if (!value.startsWith('--')) {
|
|
261
|
+
positionals.push(value);
|
|
262
|
+
continue;
|
|
263
|
+
}
|
|
264
|
+
if (value.includes('='))
|
|
265
|
+
throw new BridgeCliError('bridge_command_option_equals_syntax_unsupported');
|
|
266
|
+
if (booleanOptions.has(value)) {
|
|
267
|
+
if (flags.has(value))
|
|
268
|
+
throw new BridgeCliError('bridge_command_duplicate_option');
|
|
269
|
+
flags.add(value);
|
|
270
|
+
continue;
|
|
271
|
+
}
|
|
272
|
+
if (valueOptions.has(value)) {
|
|
273
|
+
if (values.has(value))
|
|
274
|
+
throw new BridgeCliError('bridge_command_duplicate_option');
|
|
275
|
+
const next = args[index + 1];
|
|
276
|
+
if (!next || String(next).startsWith('--'))
|
|
277
|
+
throw new BridgeCliError('bridge_command_option_value_missing');
|
|
278
|
+
values.set(value, String(next));
|
|
279
|
+
index += 1;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
throw new BridgeCliError('bridge_command_unknown_option');
|
|
283
|
+
}
|
|
284
|
+
return { positionals, flags, values };
|
|
285
|
+
}
|
|
286
|
+
function rejectSecretArgv(args) {
|
|
287
|
+
for (const arg of args) {
|
|
288
|
+
const option = String(arg).split('=', 1)[0]?.toLowerCase() || '';
|
|
289
|
+
if (option === '--api-key-stdin')
|
|
290
|
+
continue;
|
|
291
|
+
if (/^--(?:api[-_]?key|secret|token|authorization|bearer|password)(?:$|-)/.test(option)) {
|
|
292
|
+
throw new BridgeCliError('bridge_secret_argv_forbidden', 'retry_with_api_key_stdin');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
function allowOnly(parsed, allowedFlags, allowedValues) {
|
|
297
|
+
const flags = new Set(allowedFlags);
|
|
298
|
+
const values = new Set(allowedValues);
|
|
299
|
+
if ([...parsed.flags].some((entry) => !flags.has(entry))) {
|
|
300
|
+
throw new BridgeCliError('bridge_command_option_not_allowed');
|
|
301
|
+
}
|
|
302
|
+
if ([...parsed.values.keys()].some((entry) => !values.has(entry))) {
|
|
303
|
+
throw new BridgeCliError('bridge_command_option_not_allowed');
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
function requireConfirmation(parsed) {
|
|
307
|
+
if (!parsed.flags.has('--confirm')) {
|
|
308
|
+
throw new BridgeCliError('bridge_explicit_confirmation_required', 'retry_with_confirm');
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
function capabilityLevel(value) {
|
|
312
|
+
if (value === 'shallow' || value === 'transport' || value === 'deep')
|
|
313
|
+
return value;
|
|
314
|
+
throw new BridgeCliError('capability_level_must_be_shallow_transport_or_deep');
|
|
315
|
+
}
|
|
316
|
+
function provider(value) {
|
|
317
|
+
if (value === 'codex-lb' || value === 'openrouter')
|
|
318
|
+
return value;
|
|
319
|
+
throw new BridgeCliError('bridge_provider_must_be_codex_lb_or_openrouter');
|
|
320
|
+
}
|