sneakoscope 6.1.0 → 6.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 +35 -11
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/bin/fast-inline.js +18 -9
- package/dist/bin/sks-dispatch.js +2 -2
- package/dist/cli/args.js +2 -0
- package/dist/cli/command-manifest-lite.js +2 -3
- package/dist/cli/command-registry.js +3 -4
- package/dist/cli/help-fast.js +1 -1
- package/dist/cli/install-helpers.js +116 -306
- package/dist/cli/install-tool-helpers.js +287 -0
- package/dist/cli/router.js +40 -4
- package/dist/commands/codex-lb.js +51 -20
- package/dist/commands/codex.js +39 -1
- package/dist/commands/doctor.js +242 -20
- package/dist/commands/tmux.js +5 -1
- package/dist/commands/zellij-monitor-pane.js +2 -0
- package/dist/commands/zellij-viewport-pane.js +3 -1
- package/dist/commands/zellij.js +1 -1
- package/dist/config/skills-manifest.json +59 -59
- package/dist/core/agent-bridge/agent-manifest.js +48 -0
- package/dist/core/agents/agent-command-surface.js +2 -1
- package/dist/core/agents/agent-effort-policy.js +38 -35
- package/dist/core/agents/agent-plan.js +100 -21
- package/dist/core/agents/agent-role-config.js +43 -46
- package/dist/core/agents/agent-runner-codex-exec.js +16 -3
- package/dist/core/agents/agent-schema.js +3 -2
- package/dist/core/agents/native-cli-session-swarm.js +1 -1
- package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
- package/dist/core/codex/agent-config-file-repair.js +94 -193
- package/dist/core/codex/codex-cli-update.js +723 -0
- package/dist/core/codex/codex-config-guard.js +185 -9
- package/dist/core/codex/codex-config-readability.js +21 -8
- package/dist/core/codex/codex-config-toml.js +14 -11
- package/dist/core/codex/codex-project-config-policy.js +3 -6
- package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
- package/dist/core/codex-adapter.js +35 -22
- package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
- package/dist/core/codex-app/codex-app-launcher.js +48 -17
- package/dist/core/codex-app/codex-app-restart.js +23 -2
- package/dist/core/codex-app/mcp-manager.js +679 -0
- package/dist/core/codex-app/sks-menubar.js +533 -8
- package/dist/core/codex-control/codex-0139-image-path-real-probe.js +15 -4
- package/dist/core/codex-control/codex-0139-web-search-probe.js +17 -6
- package/dist/core/codex-control/codex-lb-launch-recovery.js +293 -0
- package/dist/core/codex-control/codex-reliability-shield.js +89 -29
- package/dist/core/codex-control/codex-sdk-adapter.js +44 -8
- package/dist/core/codex-control/codex-task-runner.js +62 -9
- package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
- package/dist/core/codex-exec-output-schema.js +35 -6
- package/dist/core/codex-lb/codex-lb-env.js +1 -1
- package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
- package/dist/core/codex-native/codex-native-feature-broker.js +9 -16
- package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
- package/dist/core/codex-native/core-skill-manifest.js +8 -4
- package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -3
- package/dist/core/commands/agent-bridge-command.js +23 -2
- package/dist/core/commands/agent-command.js +19 -5
- package/dist/core/commands/basic-cli.js +47 -6
- package/dist/core/commands/command-utils.js +1 -1
- package/dist/core/commands/mad-sks-command.js +76 -10
- package/dist/core/commands/menubar-command.js +94 -0
- package/dist/core/commands/naruto-command.js +645 -1156
- package/dist/core/commands/research-command.js +293 -231
- package/dist/core/commands/run-command.js +100 -23
- package/dist/core/commands/team-command.js +2 -3
- package/dist/core/commands/team-legacy-observe-command.js +94 -359
- package/dist/core/commands/wiki-command.js +11 -5
- package/dist/core/db-safety.js +2 -2
- package/dist/core/decision-lattice.js +6 -6
- package/dist/core/doctor/codex-startup-config-repair.js +8 -3
- package/dist/core/doctor/doctor-codex-startup-repair.js +6 -141
- package/dist/core/feature-fixture-executor.js +71 -7
- package/dist/core/feature-fixture-runner.js +53 -12
- package/dist/core/feature-fixtures.js +47 -14
- package/dist/core/feature-registry.js +28 -27
- package/dist/core/fsx.js +1 -0
- package/dist/core/harness-conflicts.js +18 -9
- package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +14 -8
- package/dist/core/hooks-runtime/hook-io.js +8 -4
- package/dist/core/hooks-runtime/light-turn.js +70 -0
- package/dist/core/hooks-runtime/naruto-decision-gate.js +184 -0
- package/dist/core/hooks-runtime/payload-signals.js +270 -0
- package/dist/core/hooks-runtime/stop-repeat-guard.js +89 -0
- package/dist/core/hooks-runtime/team-digest.js +0 -1
- package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
- package/dist/core/hooks-runtime.js +438 -354
- package/dist/core/init/skills.js +16 -30
- package/dist/core/init.js +144 -36
- package/dist/core/managed-assets/managed-assets-manifest.js +566 -10
- package/dist/core/mission.js +24 -1
- package/dist/core/pipeline-internals/runtime-core.js +570 -177
- package/dist/core/pipeline-internals/runtime-gates.js +174 -48
- package/dist/core/preflight/parallel-preflight-engine.js +66 -4
- package/dist/core/proof/route-adapter.js +1 -1
- package/dist/core/proof/route-proof-gate.js +7 -2
- package/dist/core/proof/selftest-proof-fixtures.js +3 -5
- package/dist/core/proof-field.js +1 -1
- package/dist/core/provider/model-router.js +42 -31
- package/dist/core/recallpulse/policy.js +12 -28
- package/dist/core/recallpulse.js +11 -6
- package/dist/core/release/npm-pack-proof.js +247 -0
- package/dist/core/release/package-dist-snapshot.js +151 -0
- package/dist/core/release/package-size-budget.js +4 -1
- package/dist/core/release/release-authorization-snapshot.js +115 -0
- package/dist/core/release/release-gate-affected-selector.js +14 -2
- package/dist/core/release/release-gate-cache-v2.js +30 -0
- package/dist/core/release/release-gate-contract.js +161 -0
- package/dist/core/release/release-gate-dag.js +1 -0
- package/dist/core/release/release-real-contract.js +90 -10
- package/dist/core/release-parallel-full-coverage.js +31 -143
- package/dist/core/research/claim-evidence-matrix.js +41 -6
- package/dist/core/research/experiment-plan.js +14 -10
- package/dist/core/research/falsification.js +9 -2
- package/dist/core/research/implementation-blueprint-densifier.js +82 -60
- package/dist/core/research/implementation-blueprint.js +32 -26
- package/dist/core/research/mock-result.js +122 -11
- package/dist/core/research/replication-pack.js +15 -8
- package/dist/core/research/research-adversarial-review.js +1068 -0
- package/dist/core/research/research-claim-builder.js +69 -17
- package/dist/core/research/research-claim-synthesizer.js +343 -0
- package/dist/core/research/research-cycle-runner.js +53 -3
- package/dist/core/research/research-falsification-runner.js +176 -0
- package/dist/core/research/research-final-reviewer.js +44 -125
- package/dist/core/research/research-plan-markdown.js +123 -0
- package/dist/core/research/research-realistic-report.js +14 -6
- package/dist/core/research/research-review-artifact-digest.js +66 -0
- package/dist/core/research/research-source-evidence.js +144 -0
- package/dist/core/research/research-source-layer-catalog.js +68 -0
- package/dist/core/research/research-source-ledger-merge.js +250 -12
- package/dist/core/research/research-source-shards.js +26 -70
- package/dist/core/research/research-stage-runner.js +237 -247
- package/dist/core/research/research-super-search.js +188 -0
- package/dist/core/research/research-synthesis-prompt.js +20 -1
- package/dist/core/research/research-synthesis-writer.js +86 -5
- package/dist/core/research/research-work-graph.js +25 -18
- package/dist/core/research/source-quality-report.js +21 -0
- package/dist/core/research.js +424 -390
- package/dist/core/retention.js +70 -2
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/dollar-manifest-lite.js +11 -11
- package/dist/core/routes.js +149 -69
- package/dist/core/runtime/task-profile.js +66 -0
- package/dist/core/runtime/verification-budget.js +12 -0
- package/dist/core/security/high-risk-contracts.js +6 -6
- package/dist/core/stop-gate/stop-gate-check.js +49 -12
- package/dist/core/subagents/agent-catalog.js +287 -0
- package/dist/core/subagents/model-policy.js +259 -0
- package/dist/core/subagents/naruto-help-contract.js +47 -0
- package/dist/core/subagents/official-subagent-config.js +488 -0
- package/dist/core/subagents/official-subagent-preparation.js +297 -0
- package/dist/core/subagents/official-subagent-prompt.js +159 -0
- package/dist/core/subagents/official-subagent-runner.js +129 -0
- package/dist/core/subagents/subagent-evidence.js +663 -0
- package/dist/core/subagents/terminology.js +16 -0
- package/dist/core/subagents/thread-budget.js +21 -0
- package/dist/core/subagents/triwiki-attention.js +168 -0
- package/dist/core/super-search/runtime-helpers.js +173 -19
- package/dist/core/super-search/runtime.js +140 -15
- package/dist/core/super-search/source-records.js +49 -8
- package/dist/core/team-review-policy.js +15 -0
- package/dist/core/triwiki/code-pack-head-freshness.js +291 -0
- package/dist/core/triwiki/triwiki-module-card.js +1 -1
- package/dist/core/triwiki-wrongness/wrongness-ledger.js +9 -2
- package/dist/core/version-manager.js +51 -1
- package/dist/core/version.js +1 -1
- package/dist/core/work-order-ledger.js +40 -1
- package/dist/core/zellij/zellij-fake-adapter.js +3 -1
- package/dist/core/zellij/zellij-launcher.js +49 -10
- package/dist/core/zellij/zellij-layout-builder.js +14 -5
- package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
- package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
- package/dist/core/zellij/zellij-pane-proof.js +9 -1
- package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
- package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
- package/dist/core/zellij/zellij-ui-mode.js +1 -1
- package/dist/core/zellij/zellij-update.js +14 -1
- package/dist/core/zellij/zellij-viewport-binder.js +3 -0
- package/dist/scripts/agent-role-config-repair-check.js +14 -16
- package/dist/scripts/architecture-guard-check.js +8 -1
- package/dist/scripts/canonical-test-runner.js +7 -1
- package/dist/scripts/check-route-modularity.js +0 -1
- package/dist/scripts/check-ts-contracts.js +1 -1
- package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
- package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
- package/dist/scripts/codex-lb-fast-mode-truth-check.js +11 -1
- package/dist/scripts/codex-lb-fast-ui-preservation-check.js +9 -2
- package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +13 -2
- package/dist/scripts/codex-native-agent-role-content-check.js +27 -7
- package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
- package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
- package/dist/scripts/codex-sdk-backend-router-check.js +2 -0
- package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
- package/dist/scripts/db-route-materialization-check.js +33 -0
- package/dist/scripts/docs-truthfulness-check.js +3 -1
- package/dist/scripts/doctor-codex-startup-repair-check.js +12 -15
- package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
- package/dist/scripts/doctor-startup-config-repair-blackbox.js +8 -2
- package/dist/scripts/doctor-startup-config-repair-check.js +12 -2
- package/dist/scripts/install-update-preserves-config-check.js +6 -1
- package/dist/scripts/lib/codex-sdk-gate-lib.js +4 -0
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +0 -1
- package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
- package/dist/scripts/naruto-codex-e2e-check.js +14 -7
- package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
- package/dist/scripts/npm-publish-performance-check.js +20 -12
- package/dist/scripts/official-subagent-workflow-check.js +145 -0
- package/dist/scripts/package-published-contract-check.js +6 -29
- package/dist/scripts/packlist-performance-check.js +18 -21
- package/dist/scripts/parallel-verification-engine-check.js +2 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
- package/dist/scripts/python-codex-sdk-all-pipelines-check.js +8 -0
- package/dist/scripts/release-affected-selector-check.js +74 -1
- package/dist/scripts/release-check-stamp.js +153 -248
- package/dist/scripts/release-dag-full-coverage-check.js +7 -15
- package/dist/scripts/release-dynamic-presets-check.js +2 -1
- package/dist/scripts/release-gate-dag-runner-check.js +0 -1
- package/dist/scripts/release-gate-dag-runner.js +12 -1
- package/dist/scripts/release-gate-existence-audit.js +1 -2
- package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
- package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
- package/dist/scripts/release-real-check.js +26 -4
- package/dist/scripts/release-registry-check.js +61 -16
- package/dist/scripts/research-blueprint-densifier-check.js +2 -2
- package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
- package/dist/scripts/sizecheck.js +2 -2
- package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
- package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
- package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
- package/dist/scripts/sks-menubar-install-check.js +14 -1
- package/dist/scripts/super-search-provider-interface-check.js +31 -18
- package/dist/scripts/trust-fixture-check.js +32 -10
- package/dist/scripts/wrongness-fixture-check.js +1 -1
- package/dist/scripts/zellij-layout-valid-check.js +5 -5
- package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
- package/docs/demo.tape +1 -1
- package/infra-harness-gates.json +1486 -0
- package/package.json +15 -10
- package/release-gates.v2.json +4060 -0
- package/runtime-required-scripts.json +9 -0
- package/dist/commands/db.js +0 -6
- package/dist/core/commands/db-command.js +0 -146
- package/dist/core/research/prompt.js +0 -15
- package/dist/scripts/codex-0139-feature-probes-check.js +0 -30
- package/dist/scripts/codex-0139-marketplace-source-check.js +0 -13
- package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
import fsp from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import readline from 'node:readline/promises';
|
|
4
|
+
import { stdin as input, stdout as output } from 'node:process';
|
|
5
|
+
import { EMPTY_CODEX_INFO, getCodexInfo } from '../core/codex-adapter.js';
|
|
6
|
+
import { exists, globalSksRoot, PACKAGE_VERSION, runProcess, which } from '../core/fsx.js';
|
|
7
|
+
import { hasContext7ConfigText } from '../core/routes.js';
|
|
8
|
+
import { createRequestedScopeContract } from '../core/safety/requested-scope-contract.js';
|
|
9
|
+
import { guardedPackageInstall, guardContextForRoute } from '../core/safety/mutation-guard.js';
|
|
10
|
+
import { checkZellijCapability } from '../core/zellij/zellij-capability.js';
|
|
11
|
+
export async function ensureRelatedCliTools(args = []) {
|
|
12
|
+
const skip = args.includes('--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
|
|
13
|
+
const codex = await ensureCodexCliTool({ skip, args });
|
|
14
|
+
const zellijRepair = skip ? { status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' } : await ensureZellijCliTool(args);
|
|
15
|
+
const zellij = await checkZellijCapability({ require: false, writeReport: false });
|
|
16
|
+
return {
|
|
17
|
+
codex,
|
|
18
|
+
zellij: {
|
|
19
|
+
ok: zellij.status === 'ok',
|
|
20
|
+
bin: zellij.bin,
|
|
21
|
+
version: zellij.version,
|
|
22
|
+
min_version: zellij.min_version,
|
|
23
|
+
current_session: false,
|
|
24
|
+
repair: zellijRepair,
|
|
25
|
+
install_hint: zellij.status === 'ok' ? null : zellijInstallHint(),
|
|
26
|
+
error: zellijRepair.error || zellij.blockers[0] || zellij.warnings[0] || null
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export async function ensureMadLaunchDependencies(args = []) {
|
|
31
|
+
const skip = args.includes('--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
|
|
32
|
+
const zellijRepair = skip ? { target: 'zellij', status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' } : await ensureZellijCliTool(args);
|
|
33
|
+
const zellij = await checkZellijCapability({ require: false, writeReport: false });
|
|
34
|
+
const ready = zellij.status === 'ok';
|
|
35
|
+
return {
|
|
36
|
+
ready,
|
|
37
|
+
actions: ready ? [] : [{
|
|
38
|
+
target: 'zellij',
|
|
39
|
+
status: zellijRepair.status,
|
|
40
|
+
command: zellijRepair.command || zellijInstallHint(),
|
|
41
|
+
error: zellijRepair.error || zellij.blockers[0] || zellij.warnings[0] || null,
|
|
42
|
+
repair: zellijRepair
|
|
43
|
+
}],
|
|
44
|
+
status: {
|
|
45
|
+
zellij: {
|
|
46
|
+
ok: ready,
|
|
47
|
+
status: zellij.status,
|
|
48
|
+
version: zellij.version,
|
|
49
|
+
min_version: zellij.min_version,
|
|
50
|
+
repair: zellijRepair,
|
|
51
|
+
install_hint: ready ? null : zellijInstallHint()
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
export function formatMadLaunchDependencyAction(action = {}) {
|
|
57
|
+
const command = action.command ? ` Run: ${action.command}.` : '';
|
|
58
|
+
const error = action.error ? ` ${action.error}` : '';
|
|
59
|
+
return `${action.target || 'dependency'} ${action.status || 'blocked'}.${command}${error}`.trim();
|
|
60
|
+
}
|
|
61
|
+
export async function ensureCodexCliTool({ skip = false, args = [] } = {}) {
|
|
62
|
+
if (skip)
|
|
63
|
+
return { status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' };
|
|
64
|
+
const before = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
65
|
+
if (before.bin)
|
|
66
|
+
return { status: 'present', bin: before.bin, version: before.version || null };
|
|
67
|
+
const npmBin = await which('npm');
|
|
68
|
+
if (!npmBin)
|
|
69
|
+
return { status: 'failed', error: 'npm not found on PATH; install Codex CLI manually with npm i -g @openai/codex@latest.' };
|
|
70
|
+
const command = 'npm i -g @openai/codex@latest';
|
|
71
|
+
if (args.includes('--dry-run'))
|
|
72
|
+
return { status: 'dry_run', command, error: 'Codex CLI not found on PATH.' };
|
|
73
|
+
if (!await confirmInstallYesDefault(`Codex CLI is missing. Install latest Codex CLI with ${command}?`, args)) {
|
|
74
|
+
return { status: 'needs_approval', command, error: 'Codex CLI not found on PATH.' };
|
|
75
|
+
}
|
|
76
|
+
const installRoot = globalSksRoot();
|
|
77
|
+
const installContract = createRequestedScopeContract({
|
|
78
|
+
route: 'install', userRequest: command, projectRoot: installRoot, overrides: { package_install: true }
|
|
79
|
+
});
|
|
80
|
+
const install = await guardedPackageInstall(guardContextForRoute(installRoot, installContract, command), '@openai/codex@latest', { confirmed: true, command: npmBin, args: ['i', '-g', '@openai/codex@latest'], timeoutMs: 120000 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
81
|
+
if (install.code !== 0)
|
|
82
|
+
return { status: 'failed', error: `${install.stderr || install.stdout || 'npm i -g @openai/codex@latest failed'}`.trim() };
|
|
83
|
+
const after = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
84
|
+
return {
|
|
85
|
+
status: after.bin ? 'installed' : 'installed_not_on_path',
|
|
86
|
+
bin: after.bin || null,
|
|
87
|
+
version: after.version || null,
|
|
88
|
+
hint: after.bin ? null : 'npm completed, but codex is not on PATH. Restart the shell or set SKS_CODEX_BIN.'
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
export async function ensureZellijCliTool(args = [], opts = {}) {
|
|
92
|
+
const before = await checkZellijCapability({ require: false, writeReport: false });
|
|
93
|
+
if (before.status === 'ok')
|
|
94
|
+
return { target: 'zellij', status: 'present', bin: before.bin, version: before.version || null };
|
|
95
|
+
const command = zellijInstallHint();
|
|
96
|
+
if (process.platform !== 'darwin')
|
|
97
|
+
return { target: 'zellij', status: 'manual_required', command, error: before.blockers[0] || before.warnings[0] || 'zellij not found' };
|
|
98
|
+
const brew = await which('brew').catch(() => null);
|
|
99
|
+
if (!brew)
|
|
100
|
+
return { target: 'zellij', status: 'manual_required', command: 'Install Homebrew, then run: brew install zellij', error: before.blockers[0] || before.warnings[0] || 'zellij not found' };
|
|
101
|
+
if (args.includes('--dry-run') || opts.dryRun)
|
|
102
|
+
return { target: 'zellij', status: 'dry_run', command, error: before.blockers[0] || before.warnings[0] || null };
|
|
103
|
+
const hasInstalledZellij = Boolean(before.version);
|
|
104
|
+
const question = hasInstalledZellij
|
|
105
|
+
? `Homebrew Zellij ${before.version || 'unknown'} is not ready. Upgrade to latest Zellij with ${command}?`
|
|
106
|
+
: `Zellij is missing. Install latest Zellij with ${command}?`;
|
|
107
|
+
if (!await confirmInstallYesDefault(question, args))
|
|
108
|
+
return { target: 'zellij', status: 'needs_approval', command, error: before.blockers[0] || before.warnings[0] || null };
|
|
109
|
+
const brewArgs = hasInstalledZellij ? ['upgrade', 'zellij'] : ['install', 'zellij'];
|
|
110
|
+
const zellijRoot = globalSksRoot();
|
|
111
|
+
const zellijContract = createRequestedScopeContract({
|
|
112
|
+
route: 'install', userRequest: command, projectRoot: zellijRoot, overrides: { package_install: true, zellij_install: true }
|
|
113
|
+
});
|
|
114
|
+
const install = await guardedPackageInstall(guardContextForRoute(zellijRoot, zellijContract, command), 'zellij', { confirmed: true, command: brew, args: brewArgs, timeoutMs: 180000 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
115
|
+
if (install.code !== 0)
|
|
116
|
+
return { target: 'zellij', status: 'failed', command, error: `${install.stderr || install.stdout || command + ' failed'}`.trim() };
|
|
117
|
+
const after = await checkZellijCapability({ require: false, writeReport: false });
|
|
118
|
+
if (after.status !== 'ok')
|
|
119
|
+
return { target: 'zellij', status: 'installed_not_ready', command, error: after.blockers[0] || after.warnings[0] || 'zellij installed but not ready' };
|
|
120
|
+
return { target: 'zellij', status: hasInstalledZellij ? 'upgraded' : 'installed', command, bin: after.bin, version: after.version || null };
|
|
121
|
+
}
|
|
122
|
+
export async function maybePromptCodexUpdateForLaunch(args = [], opts = {}) {
|
|
123
|
+
if (hasFlag(args, '--json') || hasFlag(args, '--skip-cli-tools') || hasFlag(args, '--skip-codex-update') || process.env.SKS_SKIP_CODEX_UPDATE === '1')
|
|
124
|
+
return { status: 'skipped' };
|
|
125
|
+
const latest = await npmPackageVersion('@openai/codex');
|
|
126
|
+
const codex = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
127
|
+
const current = codexCliVersionNumber(codex.version);
|
|
128
|
+
const command = 'npm i -g @openai/codex@latest';
|
|
129
|
+
const label = opts.label || 'Zellij launch';
|
|
130
|
+
const missing = !codex.bin;
|
|
131
|
+
const updateAvailable = Boolean(latest.version && current && compareVersions(latest.version, current) > 0);
|
|
132
|
+
if (!missing && !updateAvailable)
|
|
133
|
+
return { status: 'current', latest: latest.version || null, current, bin: codex.bin || null, error: latest.error || null };
|
|
134
|
+
const prompt = missing
|
|
135
|
+
? `Codex CLI missing. Install @openai/codex${latest.version ? ` ${latest.version}` : '@latest'} before ${label}? [Y/n] `
|
|
136
|
+
: `Codex CLI ${current} -> ${latest.version} update before ${label}? [Y/n] `;
|
|
137
|
+
if (shouldAutoApproveInstall(args))
|
|
138
|
+
return installCodexLatest(command, latest.version, current);
|
|
139
|
+
if (!canAskYesNo()) {
|
|
140
|
+
const reason = missing ? 'Codex CLI missing' : `Codex CLI update available: ${current} -> ${latest.version}`;
|
|
141
|
+
console.log(`${reason}. Run: ${command}`);
|
|
142
|
+
return { status: missing ? 'missing' : 'available', latest: latest.version || null, current, command, bin: codex.bin || null };
|
|
143
|
+
}
|
|
144
|
+
const answer = (await askQuestion(prompt)).trim();
|
|
145
|
+
if (!(answer === '' || /^(y|yes|예|네|응)$/i.test(answer)))
|
|
146
|
+
return { status: 'skipped_by_user', latest: latest.version || null, current, command, bin: codex.bin || null };
|
|
147
|
+
return installCodexLatest(command, latest.version, current);
|
|
148
|
+
}
|
|
149
|
+
export async function maybePromptSksUpdateForLaunch(args = [], opts = {}) {
|
|
150
|
+
void args;
|
|
151
|
+
void opts;
|
|
152
|
+
return { status: 'skipped', reason: 'manual_update_commands_only', current: PACKAGE_VERSION, latest: null, command: null };
|
|
153
|
+
}
|
|
154
|
+
export function shouldAutoApproveInstall(args = [], env = process.env) {
|
|
155
|
+
if (hasFlag(args, '--from-postinstall') && env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS !== '1')
|
|
156
|
+
return false;
|
|
157
|
+
if (hasFlag(args, '--from-postinstall') && env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS === '1')
|
|
158
|
+
return true;
|
|
159
|
+
return hasFlag(args, '--yes') || hasFlag(args, '-y') || isAgentRuntime(env);
|
|
160
|
+
}
|
|
161
|
+
export function canAskYesNo() {
|
|
162
|
+
return Boolean(input.isTTY && output.isTTY && process.env.CI !== 'true');
|
|
163
|
+
}
|
|
164
|
+
export function compareVersions(a, b) {
|
|
165
|
+
const pa = String(a || '').split(/[.-]/).map((value) => Number.parseInt(value, 10) || 0);
|
|
166
|
+
const pb = String(b || '').split(/[.-]/).map((value) => Number.parseInt(value, 10) || 0);
|
|
167
|
+
for (let index = 0; index < Math.max(pa.length, pb.length, 3); index += 1) {
|
|
168
|
+
if ((pa[index] || 0) > (pb[index] || 0))
|
|
169
|
+
return 1;
|
|
170
|
+
if ((pa[index] || 0) < (pb[index] || 0))
|
|
171
|
+
return -1;
|
|
172
|
+
}
|
|
173
|
+
return 0;
|
|
174
|
+
}
|
|
175
|
+
export async function isProjectSetupCandidate(root) {
|
|
176
|
+
for (const marker of ['package.json', '.git', 'AGENTS.md', '.codex', '.sneakoscope']) {
|
|
177
|
+
if (await exists(path.join(root, marker)))
|
|
178
|
+
return true;
|
|
179
|
+
}
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
export function hasTopLevelCodexModeLock(text = '') {
|
|
183
|
+
const lines = String(text || '').split('\n');
|
|
184
|
+
const firstTable = lines.findIndex((line) => /^\s*\[.+\]\s*$/.test(line));
|
|
185
|
+
const top = (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
|
|
186
|
+
return /(^|\n)\s*model_reasoning_effort\s*=/.test(top);
|
|
187
|
+
}
|
|
188
|
+
export function hasDeprecatedCodexHooksFeatureFlag(text = '') {
|
|
189
|
+
const lines = String(text || '').split('\n');
|
|
190
|
+
const start = lines.findIndex((line) => line.trim() === '[features]');
|
|
191
|
+
if (start === -1)
|
|
192
|
+
return false;
|
|
193
|
+
const end = lines.findIndex((line, index) => index > start && /^\s*\[.+\]\s*$/.test(line));
|
|
194
|
+
return lines.slice(start + 1, end === -1 ? lines.length : end).some((line) => /^\s*codex_hooks\s*=/.test(line));
|
|
195
|
+
}
|
|
196
|
+
export function hasCodexUnstableFeatureWarningSuppression(text = '') {
|
|
197
|
+
return /(^|\n)\s*suppress_unstable_features_warning\s*=\s*true\s*(?:#.*)?(?=\n|$)/.test(String(text || ''));
|
|
198
|
+
}
|
|
199
|
+
export async function checkContext7(root) {
|
|
200
|
+
const projectPath = path.join(root, '.codex', 'config.toml');
|
|
201
|
+
const globalPath = path.join(process.env.HOME || '', '.codex', 'config.toml');
|
|
202
|
+
const [projectText, globalText] = await Promise.all([safeReadText(projectPath), safeReadText(globalPath)]);
|
|
203
|
+
const codex = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
204
|
+
let list = { checked: false, ok: false, stdout: '', stderr: '' };
|
|
205
|
+
if (codex.bin) {
|
|
206
|
+
const out = await runProcess(codex.bin, ['mcp', 'list'], { timeoutMs: 8000, maxOutputBytes: 32 * 1024 }).catch((err) => ({ code: 1, stderr: err.message, stdout: '' }));
|
|
207
|
+
list = { checked: true, ok: out.code === 0 && /context7/i.test(`${out.stdout}\n${out.stderr}`), stdout: out.stdout || '', stderr: out.stderr || '' };
|
|
208
|
+
}
|
|
209
|
+
const result = {
|
|
210
|
+
ok: false,
|
|
211
|
+
project: { path: projectPath, ok: hasContext7ConfigText(projectText) },
|
|
212
|
+
global: { path: globalPath, ok: hasContext7ConfigText(globalText) },
|
|
213
|
+
codex_mcp_list: list
|
|
214
|
+
};
|
|
215
|
+
result.ok = result.project.ok || result.codex_mcp_list.ok || (result.global.ok && !list.checked);
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
218
|
+
function zellijInstallHint() {
|
|
219
|
+
return process.platform === 'darwin' ? 'brew install zellij' : 'Install Zellij from https://zellij.dev/documentation/installation.html';
|
|
220
|
+
}
|
|
221
|
+
async function confirmInstallYesDefault(question, args = []) {
|
|
222
|
+
if (hasFlag(args, '--from-postinstall') && process.env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS !== '1')
|
|
223
|
+
return false;
|
|
224
|
+
if (shouldAutoApproveInstall(args))
|
|
225
|
+
return true;
|
|
226
|
+
if (!canAskYesNo())
|
|
227
|
+
return false;
|
|
228
|
+
const answer = (await askQuestion(`${question} [Y/n] `)).trim();
|
|
229
|
+
return answer === '' || /^(y|yes|예|네|응)$/i.test(answer);
|
|
230
|
+
}
|
|
231
|
+
async function askQuestion(question) {
|
|
232
|
+
const rl = readline.createInterface({ input, output });
|
|
233
|
+
try {
|
|
234
|
+
return await rl.question(question);
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
rl.close();
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
function hasFlag(args = [], name) {
|
|
241
|
+
return args.includes(name);
|
|
242
|
+
}
|
|
243
|
+
function isAgentRuntime(env = process.env) {
|
|
244
|
+
return ['SKS_OPENCLAW', 'OPENCLAW', 'OPENCLAW_AGENT', 'OPENCLAW_RUN_ID', 'OPENCLAW_SESSION_ID', 'SKS_HERMES', 'HERMES_AGENT', 'HERMES_RUN_ID', 'HERMES_SESSION_ID']
|
|
245
|
+
.some((key) => /^(1|true|yes|y)$/i.test(String(env[key] || '').trim()));
|
|
246
|
+
}
|
|
247
|
+
async function installCodexLatest(command, latestVersion, previousVersion = null) {
|
|
248
|
+
const npm = await which('npm').catch(() => null);
|
|
249
|
+
if (!npm)
|
|
250
|
+
return { status: 'failed', latest: latestVersion || null, previous: previousVersion || null, command, error: 'npm not found on PATH' };
|
|
251
|
+
const install = await runProcess(npm, ['i', '-g', '@openai/codex@latest'], { timeoutMs: 180000, maxOutputBytes: 128 * 1024 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
252
|
+
if (install.code !== 0)
|
|
253
|
+
return { status: 'failed', latest: latestVersion || null, previous: previousVersion || null, command, error: `${install.stderr || install.stdout || command + ' failed'}`.trim() };
|
|
254
|
+
const after = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
255
|
+
const afterVersion = codexCliVersionNumber(after.version);
|
|
256
|
+
if (!after.bin)
|
|
257
|
+
return { status: 'updated_not_reflected', latest: latestVersion || null, previous: previousVersion || null, version: afterVersion || null, command, error: 'npm completed, but codex is not on PATH. Restart the shell or set SKS_CODEX_BIN.' };
|
|
258
|
+
if (latestVersion && afterVersion && compareVersions(afterVersion, latestVersion) < 0) {
|
|
259
|
+
return { status: 'updated_not_reflected', latest: latestVersion, previous: previousVersion || null, version: afterVersion, bin: after.bin, command, error: `npm completed, but PATH still resolves Codex CLI ${afterVersion}; expected ${latestVersion}.` };
|
|
260
|
+
}
|
|
261
|
+
console.log(`Codex CLI ready: ${previousVersion || 'missing'} -> ${after.version || after.bin}`);
|
|
262
|
+
return { status: previousVersion ? 'updated' : 'installed', latest: latestVersion || null, previous: previousVersion || null, version: afterVersion || null, raw_version: after.version || null, bin: after.bin || null, command };
|
|
263
|
+
}
|
|
264
|
+
function codexCliVersionNumber(versionText = '') {
|
|
265
|
+
return String(versionText || '').match(/(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/)?.[1] || null;
|
|
266
|
+
}
|
|
267
|
+
async function npmPackageVersion(name) {
|
|
268
|
+
const envName = `SKS_NPM_VIEW_${String(name || '').replace(/[^A-Za-z0-9]+/g, '_').toUpperCase()}_VERSION`;
|
|
269
|
+
if (process.env[envName])
|
|
270
|
+
return { version: process.env[envName] };
|
|
271
|
+
const npm = await which('npm').catch(() => null);
|
|
272
|
+
if (!npm)
|
|
273
|
+
return { error: 'npm not found' };
|
|
274
|
+
const result = await runProcess(npm, ['view', name, 'version'], { timeoutMs: 5000, maxOutputBytes: 4096 });
|
|
275
|
+
if (result.code !== 0)
|
|
276
|
+
return { error: `${result.stderr || result.stdout || 'npm view failed'}`.trim() };
|
|
277
|
+
return { version: result.stdout.trim().split(/\s+/).pop() };
|
|
278
|
+
}
|
|
279
|
+
async function safeReadText(file) {
|
|
280
|
+
try {
|
|
281
|
+
return await fsp.readFile(file, 'utf8');
|
|
282
|
+
}
|
|
283
|
+
catch {
|
|
284
|
+
return '';
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
//# sourceMappingURL=install-tool-helpers.js.map
|
package/dist/cli/router.js
CHANGED
|
@@ -73,6 +73,8 @@ async function dispatchInner(argv) {
|
|
|
73
73
|
command: raw,
|
|
74
74
|
reason: 'unknown_command',
|
|
75
75
|
};
|
|
76
|
+
if (argv.includes('--json'))
|
|
77
|
+
console.log(JSON.stringify(result, null, 2));
|
|
76
78
|
return result;
|
|
77
79
|
}
|
|
78
80
|
const entry = COMMAND_MANIFEST_BY_NAME[command];
|
|
@@ -102,7 +104,11 @@ async function dispatchInner(argv) {
|
|
|
102
104
|
const migrationGate = await ensureCurrentMigrationBeforeCommand({
|
|
103
105
|
command,
|
|
104
106
|
args: rest,
|
|
105
|
-
skipMigrationGate: entry.skipMigrationGate === true
|
|
107
|
+
skipMigrationGate: entry.skipMigrationGate === true
|
|
108
|
+
|| entry.readonly === true
|
|
109
|
+
|| safeReadOnlySubcommand(command, rest)
|
|
110
|
+
|| safeActiveRouteVisualQuery(command, rest)
|
|
111
|
+
|| safeActiveRouteRecoverySubcommand(command, rest)
|
|
106
112
|
});
|
|
107
113
|
if (!migrationGate.ok) {
|
|
108
114
|
console.error('SKS project migration blocked.');
|
|
@@ -146,7 +152,7 @@ async function ensureActiveRouteCommandGate(command, args) {
|
|
|
146
152
|
}
|
|
147
153
|
if (entry.mutatesRouteState !== true)
|
|
148
154
|
return { ok: true, status: 'allowed' };
|
|
149
|
-
if (safeReadOnlySubcommand(args))
|
|
155
|
+
if (safeReadOnlySubcommand(command, args))
|
|
150
156
|
return { ok: true, status: 'allowed_status_subcommand' };
|
|
151
157
|
if (safeActiveRouteVisualQuery(command, args))
|
|
152
158
|
return { ok: true, status: 'allowed_visual_query' };
|
|
@@ -158,6 +164,8 @@ async function ensureActiveRouteCommandGate(command, args) {
|
|
|
158
164
|
]);
|
|
159
165
|
const root = await projectRoot(process.cwd()).catch(() => process.cwd());
|
|
160
166
|
const state = await readJson(stateFile(root), {}).catch(() => ({}));
|
|
167
|
+
if (safeActiveRouteContinuation(command, args, state))
|
|
168
|
+
return { ok: true, status: 'allowed_active_route_continuation' };
|
|
161
169
|
if (!activeRouteStateBlocksCommand(state))
|
|
162
170
|
return { ok: true, status: 'allowed' };
|
|
163
171
|
const visualPreflight = await blockedVisualSourcePreflight(command, args);
|
|
@@ -201,8 +209,11 @@ function printHandledCommandBlock(result) {
|
|
|
201
209
|
for (const line of Array.isArray(result?.guidance) ? result.guidance : [])
|
|
202
210
|
console.error(`- ${line}`);
|
|
203
211
|
}
|
|
204
|
-
function safeReadOnlySubcommand(args) {
|
|
205
|
-
const sub = String(args
|
|
212
|
+
export function safeReadOnlySubcommand(command, args) {
|
|
213
|
+
const sub = String(args[0] || '').toLowerCase();
|
|
214
|
+
if (command === 'naruto' && ['status', 'subagents', 'workers', 'proof'].includes(sub)) {
|
|
215
|
+
return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
|
|
216
|
+
}
|
|
206
217
|
if (!['status', 'show', 'list', 'observe', 'watch', 'doctor', 'help'].includes(sub))
|
|
207
218
|
return false;
|
|
208
219
|
return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
|
|
@@ -213,6 +224,31 @@ function safeActiveRouteRecoverySubcommand(command, args) {
|
|
|
213
224
|
const sub = String(args.find((arg) => !String(arg).startsWith('-')) || '').toLowerCase();
|
|
214
225
|
return ['close', 'cleanup', 'rollback-patches'].includes(sub);
|
|
215
226
|
}
|
|
227
|
+
function safeActiveRouteContinuation(command, args, state = {}) {
|
|
228
|
+
const expectedRoutes = new Map([
|
|
229
|
+
['research', ['RESEARCH']],
|
|
230
|
+
['autoresearch', ['AUTORESEARCH', 'RESEARCH']],
|
|
231
|
+
['qa-loop', ['QALOOP']]
|
|
232
|
+
]).get(command);
|
|
233
|
+
if (!expectedRoutes)
|
|
234
|
+
return false;
|
|
235
|
+
const subcommand = String(args[0] || '').toLowerCase();
|
|
236
|
+
const activeRoute = String(state.route || state.route_command || state.mode || '').replace(/^\$/, '').replace(/[-_]/g, '').toUpperCase();
|
|
237
|
+
if (!expectedRoutes.includes(activeRoute))
|
|
238
|
+
return false;
|
|
239
|
+
if (subcommand === 'prepare') {
|
|
240
|
+
const parentMissionId = String(process.env.SKS_RUN_PARENT_MISSION_ID || '').trim();
|
|
241
|
+
return command !== 'autoresearch'
|
|
242
|
+
&& String(state.mode || '').toUpperCase() === 'RUN'
|
|
243
|
+
&& String(state.phase || '').toUpperCase() === 'RUN_ROUTE_SELECTED'
|
|
244
|
+
&& Boolean(parentMissionId)
|
|
245
|
+
&& parentMissionId === String(state.mission_id || '');
|
|
246
|
+
}
|
|
247
|
+
if (subcommand !== 'run')
|
|
248
|
+
return false;
|
|
249
|
+
const requestedMission = String(args[1] || '').trim();
|
|
250
|
+
return Boolean(state.mission_id) && (requestedMission === String(state.mission_id) || requestedMission === 'latest');
|
|
251
|
+
}
|
|
216
252
|
function activeRouteStateBlocksCommand(state = {}) {
|
|
217
253
|
if (!state?.mission_id || state.route_closed === true)
|
|
218
254
|
return false;
|
|
@@ -7,6 +7,7 @@ import { printJson } from '../cli/output.js';
|
|
|
7
7
|
import { codexLbMetrics, readCodexLbCircuit, recordCodexLbHealthEvent, resetCodexLbCircuit, codexLbProofEvidence } from '../core/codex-lb-circuit.js';
|
|
8
8
|
import { checkCodexLbResponseChain, codexLbStatus, configureCodexLb, formatCodexLbStatusText, releaseCodexLbAuthHold, repairCodexLbAuth, unselectCodexLbProvider } from '../cli/install-helpers.js';
|
|
9
9
|
import { buildCodexLbSetupPlan, codexLbPersistenceSummary, renderCodexLbSetupPlan } from '../core/codex-lb/codex-lb-setup.js';
|
|
10
|
+
import { CODEX_LB_TOOL_OUTPUT_RECOVERY_OVERRIDE_FLAG, codexLbToolOutputRecoveryOverrideAcknowledged } from '../core/codex-lb/codex-lb-tool-output-recovery.js';
|
|
10
11
|
import { restartCodexApp } from '../core/codex-app/codex-app-restart.js';
|
|
11
12
|
import { repairCodexAppFastUi } from '../core/codex-app/codex-app-fast-ui-repair.js';
|
|
12
13
|
export async function run(command, args = []) {
|
|
@@ -22,15 +23,19 @@ export async function run(command, args = []) {
|
|
|
22
23
|
return;
|
|
23
24
|
}
|
|
24
25
|
if (action === 'status' || action === 'check') {
|
|
25
|
-
const
|
|
26
|
+
const allowUnverifiedToolOutputRecovery = codexLbToolOutputRecoveryOverrideAcknowledged({ args });
|
|
27
|
+
const result = await codexLbStatus({ probeToolOutputRecovery: true, allowUnverifiedToolOutputRecovery });
|
|
26
28
|
const shaped = shapeCodexLbStatus(result);
|
|
29
|
+
if (result.selected && result.tool_output_recovery?.ok !== true)
|
|
30
|
+
process.exitCode = 1;
|
|
27
31
|
if (flag(args, '--json'))
|
|
28
32
|
return printJson(shaped);
|
|
29
33
|
process.stdout.write(formatCodexLbStatusText(result));
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
32
36
|
if (action === 'doctor') {
|
|
33
|
-
const
|
|
37
|
+
const allowUnverifiedToolOutputRecovery = codexLbToolOutputRecoveryOverrideAcknowledged({ args });
|
|
38
|
+
const status = shapeCodexLbStatus(await codexLbStatus({ probeToolOutputRecovery: true, allowUnverifiedToolOutputRecovery }));
|
|
34
39
|
const metrics = codexLbMetrics(await readCodexLbCircuit(root));
|
|
35
40
|
const result = { schema: 'sks.codex-lb-doctor.v1', ok: Boolean(status.ok && metrics.ok), deep: flag(args, '--deep'), status, metrics };
|
|
36
41
|
if (flag(args, '--json'))
|
|
@@ -41,9 +46,14 @@ export async function run(command, args = []) {
|
|
|
41
46
|
return;
|
|
42
47
|
}
|
|
43
48
|
if (action === 'health' || action === 'verify-chain' || action === 'chain') {
|
|
44
|
-
const
|
|
49
|
+
const allowUnverifiedToolOutputRecovery = codexLbToolOutputRecoveryOverrideAcknowledged({ args });
|
|
50
|
+
const status = await codexLbStatus({ probeToolOutputRecovery: true, allowUnverifiedToolOutputRecovery });
|
|
45
51
|
const blocker = !status.env_key_configured ? 'missing_env_key' : !status.base_url ? 'missing_base_url' : 'not_configured';
|
|
46
|
-
const result = status.
|
|
52
|
+
const result = status.selected && status.tool_output_recovery?.ok !== true
|
|
53
|
+
? { ok: false, status: 'tool_output_recovery_blocked', codex_lb: status, tool_output_recovery: status.tool_output_recovery }
|
|
54
|
+
: status.ok
|
|
55
|
+
? await checkCodexLbResponseChain(status, { force: true, root, fastMode: flag(args, '--fast') || flag(args, '--priority') })
|
|
56
|
+
: { ok: false, status: blocker, codex_lb: status };
|
|
47
57
|
if (flag(args, '--json'))
|
|
48
58
|
return printJson(result);
|
|
49
59
|
console.log(`codex-lb response chain: ${result.ok ? 'ok' : `failed (${result.status})`}`);
|
|
@@ -52,12 +62,15 @@ export async function run(command, args = []) {
|
|
|
52
62
|
return;
|
|
53
63
|
}
|
|
54
64
|
if (action === 'fast-check' || action === 'fast' || action === 'verify-fast') {
|
|
55
|
-
const
|
|
65
|
+
const allowUnverifiedToolOutputRecovery = codexLbToolOutputRecoveryOverrideAcknowledged({ args });
|
|
66
|
+
const status = await codexLbStatus({ probeToolOutputRecovery: true, allowUnverifiedToolOutputRecovery });
|
|
56
67
|
const blocker = !status.env_key_configured ? 'missing_env_key' : !status.base_url ? 'missing_base_url' : !status.provider_contract_ok ? 'provider_contract_drift' : 'not_configured';
|
|
57
68
|
const modelSelection = await resolveCodexLbFastCheckModel(status);
|
|
58
|
-
const chain = status.
|
|
59
|
-
?
|
|
60
|
-
:
|
|
69
|
+
const chain = status.selected && status.tool_output_recovery?.ok !== true
|
|
70
|
+
? { ok: false, status: 'tool_output_recovery_blocked', codex_lb: status, tool_output_recovery: status.tool_output_recovery }
|
|
71
|
+
: status.env_key_configured && status.base_url && modelSelection.model
|
|
72
|
+
? await checkCodexLbResponseChain(status, { force: true, cache: false, root, fastMode: true, model: modelSelection.model })
|
|
73
|
+
: { ok: false, status: modelSelection.model ? blocker : 'model_unselected', codex_lb: status };
|
|
61
74
|
const evidence = await fastEvidenceFromChain(chain, readOption(args, '--request-log', readOption(args, '--request-log-json', null)));
|
|
62
75
|
const providerReady = status.provider_contract_ok === true;
|
|
63
76
|
const chainVerified = isCodexLbFastChainVerified(chain);
|
|
@@ -103,7 +116,9 @@ export async function run(command, args = []) {
|
|
|
103
116
|
return;
|
|
104
117
|
}
|
|
105
118
|
if (action === 'repair' || action === 'resync' || action === 'login') {
|
|
106
|
-
const result = await repairCodexLbAuth(
|
|
119
|
+
const result = await repairCodexLbAuth({
|
|
120
|
+
allowUnverifiedToolOutputRecovery: codexLbToolOutputRecoveryOverrideAcknowledged({ args })
|
|
121
|
+
});
|
|
107
122
|
const fastUi = await repairCodexAppFastUiAfterMutation(root, Boolean(result.ok));
|
|
108
123
|
const shaped = { ...result, ok: Boolean(result.ok && fastUi.ok), codex_app_fast_ui: fastUi };
|
|
109
124
|
if (!shaped.ok)
|
|
@@ -156,7 +171,13 @@ export async function run(command, args = []) {
|
|
|
156
171
|
process.exitCode = 1;
|
|
157
172
|
return;
|
|
158
173
|
}
|
|
159
|
-
const result = await configureCodexLb({
|
|
174
|
+
const result = await configureCodexLb({
|
|
175
|
+
host,
|
|
176
|
+
apiKey: newKey,
|
|
177
|
+
authMode: flag(args, '--preserve-auth') ? 'preserve' : 'codex-lb',
|
|
178
|
+
forceCodexLbApiKeyAuth: !flag(args, '--preserve-auth'),
|
|
179
|
+
allowUnverifiedToolOutputRecovery: codexLbToolOutputRecoveryOverrideAcknowledged({ args })
|
|
180
|
+
});
|
|
160
181
|
const fastUi = await repairCodexAppFastUiAfterMutation(root, Boolean(result.ok));
|
|
161
182
|
const restart = await maybeRestartCodexAppForAuthSwitch(args, Boolean(result.ok && fastUi.ok));
|
|
162
183
|
const ok = Boolean(result.ok && fastUi.ok && restart?.ok !== false);
|
|
@@ -174,7 +195,12 @@ export async function run(command, args = []) {
|
|
|
174
195
|
}
|
|
175
196
|
if (action === 'use-codex-lb' || action === 'use-lb') {
|
|
176
197
|
// Switch auth mode -> codex-lb (API key). Re-selects the provider and re-syncs auth.
|
|
177
|
-
const result = await repairCodexLbAuth({
|
|
198
|
+
const result = await repairCodexLbAuth({
|
|
199
|
+
forceCodexLbApiKeyAuth: true,
|
|
200
|
+
authMode: 'codex-lb',
|
|
201
|
+
forceFastMode: !flag(args, '--no-fast'),
|
|
202
|
+
allowUnverifiedToolOutputRecovery: codexLbToolOutputRecoveryOverrideAcknowledged({ args })
|
|
203
|
+
});
|
|
178
204
|
const fastUi = await repairCodexAppFastUiAfterMutation(root, Boolean(result.ok));
|
|
179
205
|
const restart = await maybeRestartCodexAppForAuthSwitch(args, Boolean(result.ok && fastUi.ok));
|
|
180
206
|
const ok = Boolean(result.ok && fastUi.ok && restart?.ok !== false);
|
|
@@ -325,7 +351,8 @@ export async function run(command, args = []) {
|
|
|
325
351
|
shellProfile: options.shellProfile,
|
|
326
352
|
runHealth: options.health,
|
|
327
353
|
apiKeySource: options.apiKeySource,
|
|
328
|
-
allowInsecureHttp: options.allowInsecureLocalhost
|
|
354
|
+
allowInsecureHttp: options.allowInsecureLocalhost,
|
|
355
|
+
allowUnverifiedToolOutputRecovery: codexLbToolOutputRecoveryOverrideAcknowledged({ args })
|
|
329
356
|
});
|
|
330
357
|
const fastUi = await repairCodexAppFastUiAfterMutation(root, Boolean(result.ok));
|
|
331
358
|
const restart = await maybeRestartCodexAppForAuthSwitch(args, Boolean(result.ok && fastUi.ok) && !flag(args, '--preserve-auth'));
|
|
@@ -378,6 +405,7 @@ export async function run(command, args = []) {
|
|
|
378
405
|
return;
|
|
379
406
|
}
|
|
380
407
|
console.error('Usage: sks codex-lb status|metrics|doctor --deep|health|setup|set-key|use-codex-lb|use-oauth|repair|release|unselect|circuit reset|circuit record-fixture|proof-evidence [--json]');
|
|
408
|
+
console.error(` ${CODEX_LB_TOOL_OUTPUT_RECOVERY_OVERRIDE_FLAG} explicitly acknowledge an old/unverified proxy for this command (unsafe)`);
|
|
381
409
|
console.error(' set-key swap the codex-lb API key (reuses the stored host): sks codex-lb set-key --api-key-stdin');
|
|
382
410
|
console.error(' use-codex-lb switch auth mode to codex-lb (API key)');
|
|
383
411
|
console.error(' use-oauth switch auth mode to ChatGPT OAuth (restores saved login, else: codex login)');
|
|
@@ -587,9 +615,10 @@ function shapeCodexLbStatus(status = {}) {
|
|
|
587
615
|
return {
|
|
588
616
|
schema: 'sks.codex-lb-status.v1',
|
|
589
617
|
...status,
|
|
590
|
-
configured: Boolean(status.ok),
|
|
591
|
-
setup_needed: !status.ok,
|
|
592
|
-
|
|
618
|
+
configured: Boolean(status.provider_ready ?? status.ok),
|
|
619
|
+
setup_needed: !Boolean(status.provider_ready ?? status.ok),
|
|
620
|
+
upgrade_needed: Boolean(status.selected && status.tool_output_recovery?.ok !== true),
|
|
621
|
+
repair_available: !Boolean(status.provider_ready ?? status.ok),
|
|
593
622
|
api_key: {
|
|
594
623
|
present: Boolean(status.env_key_configured),
|
|
595
624
|
source: status.env_loader?.api_key?.source || null,
|
|
@@ -598,11 +627,13 @@ function shapeCodexLbStatus(status = {}) {
|
|
|
598
627
|
persistence,
|
|
599
628
|
env_loader: status.env_loader || null,
|
|
600
629
|
env_auto_load: Boolean(status.env_file && status.env_key_configured),
|
|
601
|
-
guidance: status.
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
630
|
+
guidance: status.selected && status.tool_output_recovery?.ok !== true
|
|
631
|
+
? status.tool_output_recovery.operator_actions || []
|
|
632
|
+
: status.ok ? [] : [
|
|
633
|
+
'codex-lb API key is not configured.',
|
|
634
|
+
'Run: sks codex-lb setup',
|
|
635
|
+
'Or: sks codex-lb setup --host <domain> --api-key-stdin --yes'
|
|
636
|
+
]
|
|
606
637
|
};
|
|
607
638
|
}
|
|
608
639
|
async function codexLbSetupOptions(args = []) {
|
package/dist/commands/codex.js
CHANGED
|
@@ -6,6 +6,7 @@ import { codexSchemaSnapshotReport } from '../core/codex-compat/codex-schema-sna
|
|
|
6
6
|
import { detectCodex0141Capability } from '../core/codex-control/codex-0141-capability.js';
|
|
7
7
|
import { detectCodex0144Capability } from '../core/codex-control/codex-0144-capability.js';
|
|
8
8
|
import { CURRENT_CODEX_RELEASE_MANIFEST } from '../core/codex-compat/codex-release-manifest.js';
|
|
9
|
+
import { inspectCodexCliUpdate, updateCodexCliNow } from '../core/codex/codex-cli-update.js';
|
|
9
10
|
export async function run(_command, args = []) {
|
|
10
11
|
const action = args[0] || 'compatibility';
|
|
11
12
|
if (action === 'compatibility' || action === 'compat') {
|
|
@@ -27,6 +28,43 @@ export async function run(_command, args = []) {
|
|
|
27
28
|
console.log(`Codex detected: ${result.detected.version || 'not installed'} (${result.policy.status})`);
|
|
28
29
|
return;
|
|
29
30
|
}
|
|
31
|
+
if (action === 'update-status' || action === 'update-check') {
|
|
32
|
+
const result = await inspectCodexCliUpdate({ force: flag(args, '--refresh') || flag(args, '--force') });
|
|
33
|
+
if (flag(args, '--json')) {
|
|
34
|
+
printJson(result);
|
|
35
|
+
if (!result.ok)
|
|
36
|
+
process.exitCode = 1;
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
console.log(`Codex CLI: ${result.current_version || 'not installed'}${result.latest_version ? ` (latest ${result.latest_version})` : ''}`);
|
|
40
|
+
console.log(`Update: ${result.update_available === true ? 'available' : result.update_available === false ? 'current' : 'unverified'}`);
|
|
41
|
+
for (const warning of result.warnings)
|
|
42
|
+
console.log(`- warning: ${warning}`);
|
|
43
|
+
for (const actionLine of result.guidance)
|
|
44
|
+
console.log(`- ${actionLine}`);
|
|
45
|
+
if (!result.ok)
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
if (action === 'update' || action === 'update-now') {
|
|
50
|
+
const result = await updateCodexCliNow();
|
|
51
|
+
if (flag(args, '--json')) {
|
|
52
|
+
printJson(result);
|
|
53
|
+
if (!result.ok)
|
|
54
|
+
process.exitCode = 1;
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
console.log(`Codex CLI update: ${result.status}${result.after_version ? ` (${result.before_version || 'unknown'} -> ${result.after_version})` : ''}`);
|
|
58
|
+
if (result.raw_output)
|
|
59
|
+
console.log(result.raw_output);
|
|
60
|
+
for (const blocker of result.blockers)
|
|
61
|
+
console.log(`- blocker: ${blocker}`);
|
|
62
|
+
for (const actionLine of result.guidance)
|
|
63
|
+
console.log(`- ${actionLine}`);
|
|
64
|
+
if (!result.ok)
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
30
68
|
if (action === '0.141' || action === '0141' || action === 'rust-v0.141.0') {
|
|
31
69
|
const result = await detectCodex0141Capability();
|
|
32
70
|
if (flag(args, '--json'))
|
|
@@ -71,7 +109,7 @@ export async function run(_command, args = []) {
|
|
|
71
109
|
process.exitCode = 1;
|
|
72
110
|
return;
|
|
73
111
|
}
|
|
74
|
-
console.error('Usage: sks codex compatibility|version|doctor|schema|0.144|0.141 [--json]');
|
|
112
|
+
console.error('Usage: sks codex compatibility|version|update-status [--refresh]|update|doctor|schema|0.144|0.141 [--json]');
|
|
75
113
|
process.exitCode = 1;
|
|
76
114
|
}
|
|
77
115
|
//# sourceMappingURL=codex.js.map
|