sneakoscope 6.1.0 → 6.1.2
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 +28 -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 +108 -303
- 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 +30 -38
- 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 +7 -2
- 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/sks-menubar.js +128 -2
- 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 +278 -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 +33 -8
- package/dist/core/commands/naruto-command.js +643 -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/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/harness-conflicts.js +18 -9
- 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/payload-signals.js +270 -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 +411 -258
- package/dist/core/init/skills.js +16 -30
- package/dist/core/init.js +144 -36
- package/dist/core/managed-assets/managed-assets-manifest.js +417 -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 +50 -1
- package/dist/core/proof/route-proof-gate.js +7 -2
- package/dist/core/proof-field.js +1 -1
- package/dist/core/provider/model-router.js +33 -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 +5 -0
- 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-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 +184 -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 +429 -280
- package/dist/core/routes/constants.js +1 -1
- package/dist/core/routes/dollar-manifest-lite.js +11 -11
- package/dist/core/routes.js +90 -63
- 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 +215 -0
- package/dist/core/subagents/model-policy.js +118 -0
- package/dist/core/subagents/naruto-help-contract.js +40 -0
- package/dist/core/subagents/official-subagent-config.js +488 -0
- package/dist/core/subagents/official-subagent-preparation.js +251 -0
- package/dist/core/subagents/official-subagent-prompt.js +137 -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 +65 -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/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 +37 -8
- 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-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-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/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-native-agent-role-content-check.js +15 -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-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/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 +17 -3
- package/dist/scripts/parallel-verification-engine-check.js +2 -2
- package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
- 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 +8 -0
- 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 +13 -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-control-tool-call-sequence-repair-check.js +0 -14
|
@@ -17,6 +17,7 @@ import { cleanupMacLaunchSecretEnvironment } from '../core/codex-app/sks-menubar
|
|
|
17
17
|
import { recordCodexLbHealthEvent } from '../core/codex-lb-circuit.js';
|
|
18
18
|
import { loadCodexLbEnv, writeCodexLbKeychain, codexLbMetadataPath } from '../core/codex-lb/codex-lb-env.js';
|
|
19
19
|
import { codexLbToolCatalogPath, ensureCodexLbToolCatalog } from '../core/codex-lb/codex-lb-tool-catalog.js';
|
|
20
|
+
import { codexLbToolOutputRecoveryNotChecked, codexLbToolOutputRecoveryNotSelected, codexLbToolOutputRecoveryOverrideAcknowledged, probeCodexLbToolOutputRecovery } from '../core/codex-lb/codex-lb-tool-output-recovery.js';
|
|
20
21
|
import { GLM_CODEX_CONFIG_PROFILE_ID, GLM_CODEX_CONFIG_PROVIDER_ID, GLM_CODEX_CONFIG_REASONING_PROFILES } from '../core/providers/glm/glm-52-profile.js';
|
|
21
22
|
import { GLM_52_OPENROUTER_MODEL } from '../core/providers/glm/glm-52-settings.js';
|
|
22
23
|
import { buildCodexLbSetupPlan, codexLbPersistenceSummary, installCodexLbShellProfileSnippet, selectedCodexLbPersistenceModes } from '../core/codex-lb/codex-lb-setup.js';
|
|
@@ -24,6 +25,8 @@ import { extractTomlTable, writeCodexConfigGuarded } from '../core/codex/codex-c
|
|
|
24
25
|
import { ensureGlobalCodexFastModeDuringInstall, ensureTrailingNewline, normalizeCodexFastModeUiConfig, removeTopLevelTomlKeyIfValue, safeWriteCodexConfigToml, upsertTopLevelTomlString, upsertTomlTable } from '../core/codex-runtime/codex-desktop-config-policy.js';
|
|
25
26
|
import { runPostinstallGlobalDoctorAndMarkPending } from '../core/update/update-migration-state.js';
|
|
26
27
|
import { repairCodexImagegen } from '../core/doctor/imagegen-repair.js';
|
|
28
|
+
import { canAskYesNo, compareVersions, hasCodexUnstableFeatureWarningSuppression, hasDeprecatedCodexHooksFeatureFlag, hasTopLevelCodexModeLock, isProjectSetupCandidate } from './install-tool-helpers.js';
|
|
29
|
+
export { checkContext7, ensureCodexCliTool, ensureMadLaunchDependencies, ensureRelatedCliTools, ensureZellijCliTool, formatMadLaunchDependencyAction, maybePromptCodexUpdateForLaunch, maybePromptSksUpdateForLaunch, shouldAutoApproveInstall } from './install-tool-helpers.js';
|
|
27
30
|
export { codexFastModeDesktopStatus, ensureGlobalCodexFastModeDuringInstall, normalizeCodexFastModeUiConfig, safeWriteCodexConfigToml } from '../core/codex-runtime/codex-desktop-config-policy.js';
|
|
28
31
|
const CODEX_LB_PROVIDER_NAME = 'openai';
|
|
29
32
|
const CODEX_LB_PROVIDER_ENV_KEY = 'CODEX_LB_API_KEY';
|
|
@@ -515,6 +518,26 @@ export async function configureCodexLb(opts = {}) {
|
|
|
515
518
|
return { ok: false, status: 'invalid_host_or_base_url', config_path: configPath, env_path: envPath, error: 'host_or_base_url_contains_whitespace_or_control_character' };
|
|
516
519
|
if (!apiKey)
|
|
517
520
|
return { ok: false, status: 'missing_api_key', config_path: configPath, env_path: envPath };
|
|
521
|
+
const toolOutputRecovery = await probeCodexLbToolOutputRecovery({
|
|
522
|
+
baseUrl,
|
|
523
|
+
...(typeof opts.toolOutputRecoveryFetch === 'function' ? { fetchImpl: opts.toolOutputRecoveryFetch } : {}),
|
|
524
|
+
timeoutMs: Number(opts.toolOutputRecoveryTimeoutMs || 4_000),
|
|
525
|
+
allowUnverified: opts.allowUnverifiedToolOutputRecovery === true
|
|
526
|
+
|| codexLbToolOutputRecoveryOverrideAcknowledged({ env: opts.env || process.env })
|
|
527
|
+
});
|
|
528
|
+
if (!toolOutputRecovery.ok) {
|
|
529
|
+
return {
|
|
530
|
+
ok: false,
|
|
531
|
+
status: 'tool_output_recovery_blocked',
|
|
532
|
+
plan: plan,
|
|
533
|
+
config_path: configPath,
|
|
534
|
+
env_path: envPath,
|
|
535
|
+
base_url: baseUrl,
|
|
536
|
+
tool_output_recovery: toolOutputRecovery,
|
|
537
|
+
drift: toolOutputRecovery.blockers,
|
|
538
|
+
warnings: toolOutputRecovery.warnings
|
|
539
|
+
};
|
|
540
|
+
}
|
|
518
541
|
const insecureLocalWarning = /^http:\/\//i.test(baseUrl) && !/^http:\/\/(?:localhost|127\.0\.0\.1|\[::1\])(?::|\/|$)/i.test(baseUrl) && !opts.allowInsecureHttp
|
|
519
542
|
? ['codex-lb base URL uses http outside localhost; prefer https or pass an explicit allow flag in the calling surface.']
|
|
520
543
|
: [];
|
|
@@ -628,6 +651,7 @@ export async function configureCodexLb(opts = {}) {
|
|
|
628
651
|
codex_environment: codexEnvironment,
|
|
629
652
|
codex_login: codexLogin,
|
|
630
653
|
tool_catalog: toolCatalog,
|
|
654
|
+
tool_output_recovery: toolOutputRecovery,
|
|
631
655
|
error: authReconcile.error || codexEnvironment.error || codexLogin.error || null
|
|
632
656
|
};
|
|
633
657
|
}
|
|
@@ -667,8 +691,22 @@ export async function codexLbStatus(opts = {}) {
|
|
|
667
691
|
status: 'inspect_failed',
|
|
668
692
|
error: err.message
|
|
669
693
|
}));
|
|
694
|
+
const providerReady = providerContractOk && envKeyConfigured && Boolean(baseUrl) && authMode.codex_app_usable;
|
|
695
|
+
const probeToolOutputRecovery = opts.probeToolOutputRecovery === true;
|
|
696
|
+
const toolOutputRecovery = !selected
|
|
697
|
+
? codexLbToolOutputRecoveryNotSelected()
|
|
698
|
+
: !probeToolOutputRecovery
|
|
699
|
+
? codexLbToolOutputRecoveryNotChecked(true)
|
|
700
|
+
: await probeCodexLbToolOutputRecovery({
|
|
701
|
+
baseUrl,
|
|
702
|
+
...(typeof opts.toolOutputRecoveryFetch === 'function' ? { fetchImpl: opts.toolOutputRecoveryFetch } : {}),
|
|
703
|
+
timeoutMs: Number(opts.toolOutputRecoveryTimeoutMs || 4_000),
|
|
704
|
+
allowUnverified: opts.allowUnverifiedToolOutputRecovery === true
|
|
705
|
+
|| codexLbToolOutputRecoveryOverrideAcknowledged({ env: opts.env || process.env })
|
|
706
|
+
});
|
|
670
707
|
return {
|
|
671
|
-
ok:
|
|
708
|
+
ok: providerReady && (!selected || !probeToolOutputRecovery || toolOutputRecovery.ok),
|
|
709
|
+
provider_ready: providerReady,
|
|
672
710
|
config_path: configPath,
|
|
673
711
|
env_path: envPath,
|
|
674
712
|
provider_configured: providerConfigured,
|
|
@@ -699,7 +737,8 @@ export async function codexLbStatus(opts = {}) {
|
|
|
699
737
|
auth_usable_for_codex_app: authMode.codex_app_usable || codexAppUsableWithCodexLb,
|
|
700
738
|
auth_summary: codexAppUsableWithCodexLb ? `codex-lb provider uses ${authMode.mode} OpenAI-style auth through Codex App` : authMode.summary,
|
|
701
739
|
fast_mode: fastMode,
|
|
702
|
-
launch_environment: launchEnvironment
|
|
740
|
+
launch_environment: launchEnvironment,
|
|
741
|
+
tool_output_recovery: toolOutputRecovery
|
|
703
742
|
};
|
|
704
743
|
}
|
|
705
744
|
export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
@@ -714,6 +753,14 @@ export function formatCodexLbStatusText(status = {}, opts = {}) {
|
|
|
714
753
|
`Provider OpenAI Auth: ${status.provider_requires_openai_auth ? 'required' : 'not required/drifted'} (${status.provider_name || 'missing'})`,
|
|
715
754
|
`Codex App auth: ${status.auth_usable_for_codex_app ? 'ok' : 'needs sign-in/repair'} (${status.auth_mode || 'unknown'})`
|
|
716
755
|
];
|
|
756
|
+
if (status.tool_output_recovery?.status && status.tool_output_recovery.status !== 'not_selected') {
|
|
757
|
+
const recovery = status.tool_output_recovery;
|
|
758
|
+
lines.push(`Interrupted tool-output recovery: ${recovery.ok ? 'ready' : 'blocked'} (${recovery.observed_version || recovery.status}; minimum ${recovery.minimum_version})`);
|
|
759
|
+
if (!recovery.ok) {
|
|
760
|
+
for (const action of recovery.operator_actions || [])
|
|
761
|
+
lines.push(` action: ${action}`);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
717
764
|
if (status.auth_summary)
|
|
718
765
|
lines.push(`Auth detail: ${status.auth_summary}`);
|
|
719
766
|
if (status.fast_mode) {
|
|
@@ -1088,17 +1135,39 @@ function tomlTableString(text = '', table, key) {
|
|
|
1088
1135
|
return block.match(new RegExp(`(^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]+)"\\s*(?:#.*)?(?=\\n|$)`))?.[2] || '';
|
|
1089
1136
|
}
|
|
1090
1137
|
export async function repairCodexLbAuth(opts = {}) {
|
|
1091
|
-
let status = await codexLbStatus(
|
|
1138
|
+
let status = await codexLbStatus({
|
|
1139
|
+
...opts,
|
|
1140
|
+
probeToolOutputRecovery: true,
|
|
1141
|
+
allowUnverifiedToolOutputRecovery: opts.allowUnverifiedToolOutputRecovery === true
|
|
1142
|
+
});
|
|
1092
1143
|
let configRepaired = false;
|
|
1093
1144
|
let legacyAuthMigrated = false;
|
|
1094
1145
|
let legacyAuthPath = null;
|
|
1146
|
+
const toolOutputRecovery = status.base_url
|
|
1147
|
+
? await probeCodexLbToolOutputRecovery({
|
|
1148
|
+
baseUrl: status.base_url,
|
|
1149
|
+
...(typeof opts.toolOutputRecoveryFetch === 'function' ? { fetchImpl: opts.toolOutputRecoveryFetch } : {}),
|
|
1150
|
+
timeoutMs: Number(opts.toolOutputRecoveryTimeoutMs || 4_000),
|
|
1151
|
+
allowUnverified: opts.allowUnverifiedToolOutputRecovery === true
|
|
1152
|
+
|| codexLbToolOutputRecoveryOverrideAcknowledged({ env: opts.env || process.env })
|
|
1153
|
+
})
|
|
1154
|
+
: status.tool_output_recovery;
|
|
1155
|
+
if (status.base_url && toolOutputRecovery?.ok !== true) {
|
|
1156
|
+
return {
|
|
1157
|
+
ok: false,
|
|
1158
|
+
status: 'tool_output_recovery_blocked',
|
|
1159
|
+
codex_lb: status,
|
|
1160
|
+
tool_output_recovery: toolOutputRecovery,
|
|
1161
|
+
error: toolOutputRecovery?.blockers?.join(', ') || 'codex-lb interrupted tool-output recovery is unverified'
|
|
1162
|
+
};
|
|
1163
|
+
}
|
|
1095
1164
|
const currentConfig = await readText(status.config_path, '');
|
|
1096
1165
|
if (!status.env_key_configured && status.base_url && (status.provider_configured || status.selected || status.env_base_url_configured)) {
|
|
1097
1166
|
const legacyAuth = await restoreCodexLbEnvFromSharedLogin(status, opts);
|
|
1098
1167
|
if (legacyAuth.ok) {
|
|
1099
1168
|
legacyAuthMigrated = true;
|
|
1100
1169
|
legacyAuthPath = legacyAuth.auth_path;
|
|
1101
|
-
status = await codexLbStatus(opts);
|
|
1170
|
+
status = await codexLbStatus({ ...opts, probeToolOutputRecovery: true });
|
|
1102
1171
|
}
|
|
1103
1172
|
}
|
|
1104
1173
|
if (status.env_key_configured && status.base_url && (!status.provider_contract_ok || !status.selected || legacyAuthMigrated || hasTopLevelCodexModeLock(currentConfig) || (opts.forceCodexLbApiKeyAuth === true && !status.ok))) {
|
|
@@ -1109,7 +1178,7 @@ export async function repairCodexLbAuth(opts = {}) {
|
|
|
1109
1178
|
});
|
|
1110
1179
|
const safeWrite = await safeWriteCodexConfigToml(status.config_path, currentConfig, next, 'codex-lb-repair');
|
|
1111
1180
|
configRepaired = safeWrite.ok && safeWrite.changed === true;
|
|
1112
|
-
status = await codexLbStatus(opts);
|
|
1181
|
+
status = await codexLbStatus({ ...opts, probeToolOutputRecovery: true });
|
|
1113
1182
|
}
|
|
1114
1183
|
const canRepairAuthMode = opts.forceCodexLbApiKeyAuth === true && status.provider_contract_ok && status.env_key_configured && Boolean(status.base_url);
|
|
1115
1184
|
if (!status.ok && !canRepairAuthMode) {
|
|
@@ -1135,7 +1204,7 @@ export async function repairCodexLbAuth(opts = {}) {
|
|
|
1135
1204
|
const codexLogin = forceCodexLbApiKeyAuth
|
|
1136
1205
|
? { ok: ['apikey_forced', 'apikey_auth_active'].includes(authReconcile.status), status: authReconcile.status, ...(authReconcile.reason ? { reason: authReconcile.reason } : {}), error: authReconcile.error || null }
|
|
1137
1206
|
: await maybeSyncCodexLbSharedLogin(apiKey, { ...opts, home: opts.home || process.env.HOME || os.homedir(), force: true });
|
|
1138
|
-
const finalStatus = await codexLbStatus(opts);
|
|
1207
|
+
const finalStatus = await codexLbStatus({ ...opts, probeToolOutputRecovery: true });
|
|
1139
1208
|
const ok = Boolean(codexEnvironment.ok && codexLogin.ok && (toolCatalog.required === false || toolCatalog.ok === true));
|
|
1140
1209
|
return {
|
|
1141
1210
|
ok,
|
|
@@ -1666,7 +1735,24 @@ async function rollbackCodexAuthRestore(input) {
|
|
|
1666
1735
|
export async function maybePromptCodexLbSetupForLaunch(args = [], opts = {}) {
|
|
1667
1736
|
if (args.includes('--json') || args.includes('--skip-codex-lb') || process.env.SKS_SKIP_CODEX_LB_PROMPT === '1')
|
|
1668
1737
|
return { status: 'skipped' };
|
|
1669
|
-
|
|
1738
|
+
const allowUnverifiedToolOutputRecovery = opts.allowUnverifiedToolOutputRecovery === true
|
|
1739
|
+
|| codexLbToolOutputRecoveryOverrideAcknowledged({ args, env: opts.env || process.env });
|
|
1740
|
+
let status = await codexLbStatus({
|
|
1741
|
+
...opts,
|
|
1742
|
+
probeToolOutputRecovery: true,
|
|
1743
|
+
allowUnverifiedToolOutputRecovery
|
|
1744
|
+
});
|
|
1745
|
+
if (status.selected && status.tool_output_recovery?.ok !== true) {
|
|
1746
|
+
return {
|
|
1747
|
+
status: 'tool_output_recovery_blocked',
|
|
1748
|
+
ok: false,
|
|
1749
|
+
codex_lb: status,
|
|
1750
|
+
tool_output_recovery: status.tool_output_recovery,
|
|
1751
|
+
blockers: status.tool_output_recovery.blockers,
|
|
1752
|
+
operator_actions: status.tool_output_recovery.operator_actions,
|
|
1753
|
+
bypass_codex_lb: false
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1670
1756
|
if (status.env_key_configured && status.base_url && !status.selected && status.auth_mode === 'chatgpt_oauth') {
|
|
1671
1757
|
return { status: 'continued_to_codex', ok: false, chain_health: null, codex_lb: status, reason: 'chatgpt_oauth_active_codex_lb_unselected' };
|
|
1672
1758
|
}
|
|
@@ -1678,8 +1764,20 @@ export async function maybePromptCodexLbSetupForLaunch(args = [], opts = {}) {
|
|
|
1678
1764
|
if (/^(n|no|아니|아니요|ㄴ)$/i.test(restore))
|
|
1679
1765
|
return { status: 'continued_to_codex', codex_lb: status };
|
|
1680
1766
|
}
|
|
1681
|
-
const repaired = await repairCodexLbAuth(opts);
|
|
1682
|
-
status = await codexLbStatus(opts);
|
|
1767
|
+
const repaired = await repairCodexLbAuth({ ...opts, allowUnverifiedToolOutputRecovery });
|
|
1768
|
+
status = await codexLbStatus({ ...opts, probeToolOutputRecovery: true, allowUnverifiedToolOutputRecovery });
|
|
1769
|
+
if (status.selected && status.tool_output_recovery?.ok !== true) {
|
|
1770
|
+
return {
|
|
1771
|
+
status: 'tool_output_recovery_blocked',
|
|
1772
|
+
ok: false,
|
|
1773
|
+
repair: repaired,
|
|
1774
|
+
codex_lb: status,
|
|
1775
|
+
tool_output_recovery: status.tool_output_recovery,
|
|
1776
|
+
blockers: status.tool_output_recovery.blockers,
|
|
1777
|
+
operator_actions: status.tool_output_recovery.operator_actions,
|
|
1778
|
+
bypass_codex_lb: false
|
|
1779
|
+
};
|
|
1780
|
+
}
|
|
1683
1781
|
if (!status.ok)
|
|
1684
1782
|
return { status: 'repair_failed', ok: false, repair: repaired, codex_lb: status };
|
|
1685
1783
|
if (!repaired.ok && repaired.error && promptedRestore)
|
|
@@ -1746,7 +1844,7 @@ export async function maybePromptCodexLbSetupForLaunch(args = [], opts = {}) {
|
|
|
1746
1844
|
return { status: 'continued_to_codex' };
|
|
1747
1845
|
const host = (await askPostinstallQuestion('codex-lb host domain [http://127.0.0.1:2455]: ')).trim() || 'http://127.0.0.1:2455';
|
|
1748
1846
|
const apiKey = (await askPostinstallQuestion('codex-lb API key: ')).trim();
|
|
1749
|
-
const configured = await configureCodexLb({ ...opts, host, apiKey });
|
|
1847
|
+
const configured = await configureCodexLb({ ...opts, host, apiKey, allowUnverifiedToolOutputRecovery });
|
|
1750
1848
|
if (configured.ok)
|
|
1751
1849
|
console.log(`codex-lb configured: ${configured.base_url}`);
|
|
1752
1850
|
else
|
|
@@ -2342,273 +2440,6 @@ export async function ensureCodexImagegenDuringInstall(opts = {}) {
|
|
|
2342
2440
|
return { status: 'recovered', report };
|
|
2343
2441
|
return { status: 'blocked', blockers: report.blockers || ['codex_imagegen_unavailable'], report };
|
|
2344
2442
|
}
|
|
2345
|
-
export async function ensureRelatedCliTools(args = []) {
|
|
2346
|
-
const skip = args.includes('--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
|
|
2347
|
-
const codex = await ensureCodexCliTool({ skip, args });
|
|
2348
|
-
const zellijRepair = skip ? { status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' } : await ensureZellijCliTool(args);
|
|
2349
|
-
const zellij = await checkZellijCapability({ require: false, writeReport: false });
|
|
2350
|
-
return {
|
|
2351
|
-
codex,
|
|
2352
|
-
zellij: {
|
|
2353
|
-
ok: zellij.status === 'ok',
|
|
2354
|
-
bin: zellij.bin,
|
|
2355
|
-
version: zellij.version,
|
|
2356
|
-
min_version: zellij.min_version,
|
|
2357
|
-
current_session: false,
|
|
2358
|
-
repair: zellijRepair,
|
|
2359
|
-
install_hint: zellij.status === 'ok' ? null : zellijInstallHint(),
|
|
2360
|
-
error: zellijRepair.error || zellij.blockers[0] || zellij.warnings[0] || null
|
|
2361
|
-
}
|
|
2362
|
-
};
|
|
2363
|
-
}
|
|
2364
|
-
export async function ensureMadLaunchDependencies(args = []) {
|
|
2365
|
-
const skip = args.includes('--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
|
|
2366
|
-
const zellijRepair = skip ? { target: 'zellij', status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' } : await ensureZellijCliTool(args);
|
|
2367
|
-
const zellij = await checkZellijCapability({ require: false, writeReport: false });
|
|
2368
|
-
const ready = zellij.status === 'ok';
|
|
2369
|
-
return {
|
|
2370
|
-
ready,
|
|
2371
|
-
actions: ready ? [] : [{
|
|
2372
|
-
target: 'zellij',
|
|
2373
|
-
status: zellijRepair.status,
|
|
2374
|
-
command: zellijRepair.command || zellijInstallHint(),
|
|
2375
|
-
error: zellijRepair.error || zellij.blockers[0] || zellij.warnings[0] || null,
|
|
2376
|
-
repair: zellijRepair
|
|
2377
|
-
}],
|
|
2378
|
-
status: {
|
|
2379
|
-
zellij: {
|
|
2380
|
-
ok: ready,
|
|
2381
|
-
status: zellij.status,
|
|
2382
|
-
version: zellij.version,
|
|
2383
|
-
min_version: zellij.min_version,
|
|
2384
|
-
repair: zellijRepair,
|
|
2385
|
-
install_hint: ready ? null : zellijInstallHint()
|
|
2386
|
-
}
|
|
2387
|
-
}
|
|
2388
|
-
};
|
|
2389
|
-
}
|
|
2390
|
-
export function formatMadLaunchDependencyAction(action = {}) {
|
|
2391
|
-
const command = action.command ? ` Run: ${action.command}.` : '';
|
|
2392
|
-
const error = action.error ? ` ${action.error}` : '';
|
|
2393
|
-
return `${action.target || 'dependency'} ${action.status || 'blocked'}.${command}${error}`.trim();
|
|
2394
|
-
}
|
|
2395
|
-
export async function ensureCodexCliTool({ skip = false, args = [] } = {}) {
|
|
2396
|
-
if (skip)
|
|
2397
|
-
return { status: 'skipped', reason: 'SKS_SKIP_CLI_TOOLS=1 or --skip-cli-tools' };
|
|
2398
|
-
const before = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
2399
|
-
if (before.bin)
|
|
2400
|
-
return { status: 'present', bin: before.bin, version: before.version || null };
|
|
2401
|
-
const npmBin = await which('npm');
|
|
2402
|
-
if (!npmBin)
|
|
2403
|
-
return { status: 'failed', error: 'npm not found on PATH; install Codex CLI manually with npm i -g @openai/codex@latest.' };
|
|
2404
|
-
const command = 'npm i -g @openai/codex@latest';
|
|
2405
|
-
if (args.includes('--dry-run'))
|
|
2406
|
-
return { status: 'dry_run', command, error: 'Codex CLI not found on PATH.' };
|
|
2407
|
-
if (!await confirmInstallYesDefault(`Codex CLI is missing. Install latest Codex CLI with ${command}?`, args)) {
|
|
2408
|
-
return { status: 'needs_approval', command, error: 'Codex CLI not found on PATH.' };
|
|
2409
|
-
}
|
|
2410
|
-
// Global package install is a confirmation-required mutation: route it through
|
|
2411
|
-
// the mutation guard so it is scope-checked and recorded in the ledger. The
|
|
2412
|
-
// user already approved via confirmInstallYesDefault above (confirmed:true).
|
|
2413
|
-
const installRoot = globalSksRoot();
|
|
2414
|
-
const installContract = createRequestedScopeContract({
|
|
2415
|
-
route: 'install', userRequest: command, projectRoot: installRoot, overrides: { package_install: true }
|
|
2416
|
-
});
|
|
2417
|
-
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 }));
|
|
2418
|
-
if (install.code !== 0) {
|
|
2419
|
-
return { status: 'failed', error: `${install.stderr || install.stdout || 'npm i -g @openai/codex@latest failed'}`.trim() };
|
|
2420
|
-
}
|
|
2421
|
-
const after = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
2422
|
-
return {
|
|
2423
|
-
status: after.bin ? 'installed' : 'installed_not_on_path',
|
|
2424
|
-
bin: after.bin || null,
|
|
2425
|
-
version: after.version || null,
|
|
2426
|
-
hint: after.bin ? null : 'npm completed, but codex is not on PATH. Restart the shell or set SKS_CODEX_BIN.'
|
|
2427
|
-
};
|
|
2428
|
-
}
|
|
2429
|
-
export async function ensureZellijCliTool(args = [], opts = {}) {
|
|
2430
|
-
const before = await checkZellijCapability({ require: false, writeReport: false });
|
|
2431
|
-
if (before.status === 'ok')
|
|
2432
|
-
return { target: 'zellij', status: 'present', bin: before.bin, version: before.version || null };
|
|
2433
|
-
const command = zellijInstallHint();
|
|
2434
|
-
if (process.platform !== 'darwin')
|
|
2435
|
-
return { target: 'zellij', status: 'manual_required', command, error: before.blockers[0] || before.warnings[0] || 'zellij not found' };
|
|
2436
|
-
const brew = await which('brew').catch(() => null);
|
|
2437
|
-
if (!brew)
|
|
2438
|
-
return { target: 'zellij', status: 'manual_required', command: 'Install Homebrew, then run: brew install zellij', error: before.blockers[0] || before.warnings[0] || 'zellij not found' };
|
|
2439
|
-
const repairCommand = command;
|
|
2440
|
-
if (args.includes('--dry-run') || opts.dryRun)
|
|
2441
|
-
return { target: 'zellij', status: 'dry_run', command: repairCommand, error: before.blockers[0] || before.warnings[0] || null };
|
|
2442
|
-
const hasInstalledZellij = Boolean(before.version);
|
|
2443
|
-
const question = hasInstalledZellij
|
|
2444
|
-
? `Homebrew Zellij ${before.version || 'unknown'} is not ready. Upgrade to latest Zellij with ${repairCommand}?`
|
|
2445
|
-
: `Zellij is missing. Install latest Zellij with ${repairCommand}?`;
|
|
2446
|
-
if (!await confirmInstallYesDefault(question, args))
|
|
2447
|
-
return { target: 'zellij', status: 'needs_approval', command: repairCommand, error: before.blockers[0] || before.warnings[0] || null };
|
|
2448
|
-
const brewArgs = hasInstalledZellij ? ['upgrade', 'zellij'] : ['install', 'zellij'];
|
|
2449
|
-
const zellijRoot = globalSksRoot();
|
|
2450
|
-
const zellijContract = createRequestedScopeContract({
|
|
2451
|
-
route: 'install', userRequest: repairCommand, projectRoot: zellijRoot, overrides: { package_install: true, zellij_install: true }
|
|
2452
|
-
});
|
|
2453
|
-
const install = await guardedPackageInstall(guardContextForRoute(zellijRoot, zellijContract, repairCommand), 'zellij', { confirmed: true, command: brew, args: brewArgs, timeoutMs: 180000 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
2454
|
-
if (install.code !== 0)
|
|
2455
|
-
return { target: 'zellij', status: 'failed', command: repairCommand, error: `${install.stderr || install.stdout || repairCommand + ' failed'}`.trim() };
|
|
2456
|
-
const after = await checkZellijCapability({ require: false, writeReport: false });
|
|
2457
|
-
if (after.status !== 'ok')
|
|
2458
|
-
return { target: 'zellij', status: 'installed_not_ready', command: repairCommand, error: after.blockers[0] || after.warnings[0] || 'zellij installed but not ready' };
|
|
2459
|
-
return { target: 'zellij', status: hasInstalledZellij ? 'upgraded' : 'installed', command: repairCommand, bin: after.bin, version: after.version || null };
|
|
2460
|
-
}
|
|
2461
|
-
function zellijInstallHint() {
|
|
2462
|
-
return process.platform === 'darwin' ? 'brew install zellij' : 'Install Zellij from https://zellij.dev/documentation/installation.html';
|
|
2463
|
-
}
|
|
2464
|
-
async function confirmInstallYesDefault(question, args = []) {
|
|
2465
|
-
if (hasFlag(args, '--from-postinstall') && process.env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS !== '1')
|
|
2466
|
-
return false;
|
|
2467
|
-
if (shouldAutoApproveInstall(args))
|
|
2468
|
-
return true;
|
|
2469
|
-
if (!canAskYesNo())
|
|
2470
|
-
return false;
|
|
2471
|
-
const answer = (await askPostinstallQuestion(`${question} [Y/n] `)).trim();
|
|
2472
|
-
return answer === '' || /^(y|yes|예|네|응)$/i.test(answer);
|
|
2473
|
-
}
|
|
2474
|
-
export async function maybePromptCodexUpdateForLaunch(args = [], opts = {}) {
|
|
2475
|
-
if (hasFlag(args, '--json') || hasFlag(args, '--skip-cli-tools') || hasFlag(args, '--skip-codex-update') || process.env.SKS_SKIP_CODEX_UPDATE === '1')
|
|
2476
|
-
return { status: 'skipped' };
|
|
2477
|
-
const latest = await npmPackageVersion('@openai/codex');
|
|
2478
|
-
const codex = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
2479
|
-
const current = codexCliVersionNumber(codex.version);
|
|
2480
|
-
const command = 'npm i -g @openai/codex@latest';
|
|
2481
|
-
const label = opts.label || 'Zellij launch';
|
|
2482
|
-
const missing = !codex.bin;
|
|
2483
|
-
const updateAvailable = Boolean(latest.version && current && compareVersions(latest.version, current) > 0);
|
|
2484
|
-
if (!missing && !updateAvailable)
|
|
2485
|
-
return { status: 'current', latest: latest.version || null, current, bin: codex.bin || null, error: latest.error || null };
|
|
2486
|
-
const prompt = missing
|
|
2487
|
-
? `Codex CLI missing. Install @openai/codex${latest.version ? ` ${latest.version}` : '@latest'} before ${label}? [Y/n] `
|
|
2488
|
-
: `Codex CLI ${current} -> ${latest.version} update before ${label}? [Y/n] `;
|
|
2489
|
-
if (shouldAutoApproveInstall(args))
|
|
2490
|
-
return installCodexLatest(command, latest.version, current);
|
|
2491
|
-
if (!canAskYesNo()) {
|
|
2492
|
-
const reason = missing ? 'Codex CLI missing' : `Codex CLI update available: ${current} -> ${latest.version}`;
|
|
2493
|
-
console.log(`${reason}. Run: ${command}`);
|
|
2494
|
-
return { status: missing ? 'missing' : 'available', latest: latest.version || null, current, command, bin: codex.bin || null };
|
|
2495
|
-
}
|
|
2496
|
-
const answer = (await askPostinstallQuestion(prompt)).trim();
|
|
2497
|
-
const yes = answer === '' || /^(y|yes|예|네|응)$/i.test(answer);
|
|
2498
|
-
if (!yes)
|
|
2499
|
-
return { status: 'skipped_by_user', latest: latest.version || null, current, command, bin: codex.bin || null };
|
|
2500
|
-
return installCodexLatest(command, latest.version, current);
|
|
2501
|
-
}
|
|
2502
|
-
export async function maybePromptSksUpdateForLaunch(args = [], opts = {}) {
|
|
2503
|
-
void args;
|
|
2504
|
-
void opts;
|
|
2505
|
-
return {
|
|
2506
|
-
status: 'skipped',
|
|
2507
|
-
reason: 'manual_update_commands_only',
|
|
2508
|
-
current: PACKAGE_VERSION,
|
|
2509
|
-
latest: null,
|
|
2510
|
-
command: null
|
|
2511
|
-
};
|
|
2512
|
-
}
|
|
2513
|
-
export function shouldAutoApproveInstall(args = [], env = process.env) {
|
|
2514
|
-
if (hasFlag(args, '--from-postinstall') && env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS !== '1')
|
|
2515
|
-
return false;
|
|
2516
|
-
if (hasFlag(args, '--from-postinstall') && env.SKS_POSTINSTALL_AUTO_INSTALL_CLI_TOOLS === '1')
|
|
2517
|
-
return true;
|
|
2518
|
-
return hasFlag(args, '--yes') || hasFlag(args, '-y') || isAgentRuntime(env);
|
|
2519
|
-
}
|
|
2520
|
-
function canAskYesNo() {
|
|
2521
|
-
return Boolean(input.isTTY && output.isTTY && process.env.CI !== 'true');
|
|
2522
|
-
}
|
|
2523
|
-
function hasFlag(args = [], name) {
|
|
2524
|
-
return args.includes(name);
|
|
2525
|
-
}
|
|
2526
|
-
function isAgentRuntime(env = process.env) {
|
|
2527
|
-
return [
|
|
2528
|
-
'SKS_OPENCLAW',
|
|
2529
|
-
'OPENCLAW',
|
|
2530
|
-
'OPENCLAW_AGENT',
|
|
2531
|
-
'OPENCLAW_RUN_ID',
|
|
2532
|
-
'OPENCLAW_SESSION_ID',
|
|
2533
|
-
'SKS_HERMES',
|
|
2534
|
-
'HERMES_AGENT',
|
|
2535
|
-
'HERMES_RUN_ID',
|
|
2536
|
-
'HERMES_SESSION_ID'
|
|
2537
|
-
]
|
|
2538
|
-
.some((key) => /^(1|true|yes|y)$/i.test(String(env[key] || '').trim()));
|
|
2539
|
-
}
|
|
2540
|
-
async function installCodexLatest(command, latestVersion, previousVersion = null) {
|
|
2541
|
-
const npm = await which('npm').catch(() => null);
|
|
2542
|
-
if (!npm)
|
|
2543
|
-
return { status: 'failed', latest: latestVersion || null, previous: previousVersion || null, command, error: 'npm not found on PATH' };
|
|
2544
|
-
const install = await runProcess(npm, ['i', '-g', '@openai/codex@latest'], { timeoutMs: 180000, maxOutputBytes: 128 * 1024 }).catch((err) => ({ code: 1, stdout: '', stderr: err.message }));
|
|
2545
|
-
if (install.code !== 0)
|
|
2546
|
-
return { status: 'failed', latest: latestVersion || null, previous: previousVersion || null, command, error: `${install.stderr || install.stdout || command + ' failed'}`.trim() };
|
|
2547
|
-
const after = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
2548
|
-
const afterVersion = codexCliVersionNumber(after.version);
|
|
2549
|
-
if (!after.bin)
|
|
2550
|
-
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.' };
|
|
2551
|
-
if (latestVersion && afterVersion && compareVersions(afterVersion, latestVersion) < 0) {
|
|
2552
|
-
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}.` };
|
|
2553
|
-
}
|
|
2554
|
-
console.log(`Codex CLI ready: ${previousVersion || 'missing'} -> ${after.version || after.bin}`);
|
|
2555
|
-
return { status: previousVersion ? 'updated' : 'installed', latest: latestVersion || null, previous: previousVersion || null, version: afterVersion || null, raw_version: after.version || null, bin: after.bin || null, command };
|
|
2556
|
-
}
|
|
2557
|
-
function codexCliVersionNumber(versionText = '') {
|
|
2558
|
-
const match = String(versionText || '').match(/(\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?)/);
|
|
2559
|
-
return match ? match[1] : null;
|
|
2560
|
-
}
|
|
2561
|
-
async function npmPackageVersion(name) {
|
|
2562
|
-
const envName = `SKS_NPM_VIEW_${String(name || '').replace(/[^A-Za-z0-9]+/g, '_').toUpperCase()}_VERSION`;
|
|
2563
|
-
if (process.env[envName])
|
|
2564
|
-
return { version: process.env[envName] };
|
|
2565
|
-
const npm = await which('npm').catch(() => null);
|
|
2566
|
-
if (!npm)
|
|
2567
|
-
return { error: 'npm not found' };
|
|
2568
|
-
const result = await runProcess(npm, ['view', name, 'version'], { timeoutMs: 5000, maxOutputBytes: 4096 });
|
|
2569
|
-
if (result.code !== 0)
|
|
2570
|
-
return { error: `${result.stderr || result.stdout || 'npm view failed'}`.trim() };
|
|
2571
|
-
return { version: result.stdout.trim().split(/\s+/).pop() };
|
|
2572
|
-
}
|
|
2573
|
-
function compareVersions(a, b) {
|
|
2574
|
-
const pa = String(a || '').split(/[.-]/).map((x) => Number.parseInt(x, 10) || 0);
|
|
2575
|
-
const pb = String(b || '').split(/[.-]/).map((x) => Number.parseInt(x, 10) || 0);
|
|
2576
|
-
for (let i = 0; i < Math.max(pa.length, pb.length, 3); i++) {
|
|
2577
|
-
if ((pa[i] || 0) > (pb[i] || 0))
|
|
2578
|
-
return 1;
|
|
2579
|
-
if ((pa[i] || 0) < (pb[i] || 0))
|
|
2580
|
-
return -1;
|
|
2581
|
-
}
|
|
2582
|
-
return 0;
|
|
2583
|
-
}
|
|
2584
|
-
async function isProjectSetupCandidate(root) {
|
|
2585
|
-
const markers = ['package.json', '.git', 'AGENTS.md', '.codex', '.sneakoscope'];
|
|
2586
|
-
for (const marker of markers) {
|
|
2587
|
-
if (await exists(path.join(root, marker)))
|
|
2588
|
-
return true;
|
|
2589
|
-
}
|
|
2590
|
-
return false;
|
|
2591
|
-
}
|
|
2592
|
-
export async function checkContext7(root) {
|
|
2593
|
-
const projectPath = path.join(root, '.codex', 'config.toml');
|
|
2594
|
-
const globalPath = path.join(process.env.HOME || '', '.codex', 'config.toml');
|
|
2595
|
-
const projectText = await safeReadText(projectPath);
|
|
2596
|
-
const globalText = await safeReadText(globalPath);
|
|
2597
|
-
const codex = await getCodexInfo().catch(() => EMPTY_CODEX_INFO);
|
|
2598
|
-
let list = { checked: false, ok: false, stdout: '', stderr: '' };
|
|
2599
|
-
if (codex.bin) {
|
|
2600
|
-
const out = await runProcess(codex.bin, ['mcp', 'list'], { timeoutMs: 8000, maxOutputBytes: 32 * 1024 }).catch((err) => ({ code: 1, stderr: err.message, stdout: '' }));
|
|
2601
|
-
list = { checked: true, ok: out.code === 0 && /context7/i.test(`${out.stdout}\n${out.stderr}`), stdout: out.stdout || '', stderr: out.stderr || '' };
|
|
2602
|
-
}
|
|
2603
|
-
const result = {
|
|
2604
|
-
ok: false,
|
|
2605
|
-
project: { path: projectPath, ok: hasContext7ConfigText(projectText) },
|
|
2606
|
-
global: { path: globalPath, ok: hasContext7ConfigText(globalText) },
|
|
2607
|
-
codex_mcp_list: list
|
|
2608
|
-
};
|
|
2609
|
-
result.ok = result.project.ok || result.codex_mcp_list.ok || (result.global.ok && !list.checked);
|
|
2610
|
-
return result;
|
|
2611
|
-
}
|
|
2612
2443
|
export async function ensureProjectContext7Config(root, transport = 'local') {
|
|
2613
2444
|
const configPath = path.join(root, '.codex', 'config.toml');
|
|
2614
2445
|
await ensureDir(path.dirname(configPath));
|
|
@@ -3234,30 +3065,4 @@ export async function selftestCodexLb(tmp) {
|
|
|
3234
3065
|
if (!madLaunchSource.includes('const lb = await deps.maybePromptCodexLbSetupForLaunch(args)') || !madLaunchSource.includes("const launchLb = lb.status === 'present'") || !madLaunchSource.includes('codexLbImmediateLaunchOpts(cleanArgs, launchLb') || !madLaunchSource.includes('bypass_codex_lb') || !madLaunchSource.includes('model_provider="openai"') || !madLaunchSource.includes('codexLbFreshSession: true'))
|
|
3235
3066
|
throw new Error('selftest: MAD launch does not sync codex-lb auth and fresh-session launch options');
|
|
3236
3067
|
}
|
|
3237
|
-
function hasTopLevelCodexModeLock(text = '') {
|
|
3238
|
-
const lines = String(text || '').split('\n');
|
|
3239
|
-
const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
|
|
3240
|
-
const top = (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
|
|
3241
|
-
return /(^|\n)\s*model_reasoning_effort\s*=/.test(top);
|
|
3242
|
-
}
|
|
3243
|
-
function hasDeprecatedCodexHooksFeatureFlag(text = '') {
|
|
3244
|
-
const lines = String(text || '').split('\n');
|
|
3245
|
-
const start = lines.findIndex((line) => line.trim() === '[features]');
|
|
3246
|
-
if (start === -1)
|
|
3247
|
-
return false;
|
|
3248
|
-
let end = lines.length;
|
|
3249
|
-
for (let i = start + 1; i < lines.length; i += 1) {
|
|
3250
|
-
const line = lines[i];
|
|
3251
|
-
if (line === undefined)
|
|
3252
|
-
continue;
|
|
3253
|
-
if (/^\s*\[.+\]\s*$/.test(line)) {
|
|
3254
|
-
end = i;
|
|
3255
|
-
break;
|
|
3256
|
-
}
|
|
3257
|
-
}
|
|
3258
|
-
return lines.slice(start + 1, end).some((line) => /^\s*codex_hooks\s*=/.test(line));
|
|
3259
|
-
}
|
|
3260
|
-
function hasCodexUnstableFeatureWarningSuppression(text = '') {
|
|
3261
|
-
return /(^|\n)\s*suppress_unstable_features_warning\s*=\s*true\s*(?:#.*)?(?=\n|$)/.test(String(text || ''));
|
|
3262
|
-
}
|
|
3263
3068
|
//# sourceMappingURL=install-helpers.js.map
|