sneakoscope 6.5.1 → 6.7.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 +9 -7
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/dist/cli/command-manifest-lite.js +2 -2
- package/dist/cli/command-registry.js +2 -2
- package/dist/config/skills-manifest.json +62 -62
- package/dist/core/agents/agent-effort-policy.js +13 -7
- package/dist/core/agents/agent-orchestrator.js +0 -6
- package/dist/core/agents/agent-output-validator.js +2 -1
- package/dist/core/agents/agent-patch-queue-store.js +0 -8
- package/dist/core/agents/agent-worker-pipeline.js +12 -6
- package/dist/core/agents/native-worker-backend-router.js +1 -1
- package/dist/core/bench.js +1 -1
- package/dist/core/codex/official-goal-mode.js +4 -2
- package/dist/core/codex-control/codex-control-proof.js +1 -0
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +1 -1
- package/dist/core/codex-control/codex-lb-launch-recovery.js +7 -3
- package/dist/core/codex-control/codex-sdk-adapter.js +8 -7
- package/dist/core/codex-control/codex-sdk-config-policy.js +4 -24
- package/dist/core/codex-control/codex-sdk-env-policy.js +396 -11
- package/dist/core/codex-control/codex-task-runner.js +112 -57
- package/dist/core/codex-control/gpt-final-arbiter.js +1 -2
- package/dist/core/codex-control/python-codex-sdk-adapter.js +38 -15
- package/dist/core/codex-native/core-skill-manifest.js +4 -7
- package/dist/core/codex-runtime/resolve-codex-runtime.js +199 -0
- package/dist/core/commands/command-utils.js +2 -2
- package/dist/core/commands/eval-command.js +19 -2
- package/dist/core/commands/goal-command.js +37 -86
- package/dist/core/commands/naruto-command.js +189 -135
- package/dist/core/evaluation.js +83 -21
- package/dist/core/feature-fixtures.js +4 -3
- package/dist/core/fsx.js +141 -12
- package/dist/core/goal-workflow.js +71 -140
- package/dist/core/hooks-runtime/hook-io.js +2 -2
- package/dist/core/hooks-runtime.js +228 -50
- package/dist/core/init/skills.js +7 -6
- package/dist/core/init.js +52 -33
- package/dist/core/lean-engineering-policy.js +25 -23
- package/dist/core/locks/file-lock.js +5 -4
- package/dist/core/managed-assets/managed-assets-manifest.js +1 -1
- package/dist/core/mission.js +99 -3
- package/dist/core/pipeline-internals/runtime-core.js +67 -95
- package/dist/core/pipeline-internals/runtime-gates.js +25 -6
- package/dist/core/proof/fake-real-proof-policy.js +32 -9
- package/dist/core/proof/route-proof-gate.js +49 -1
- package/dist/core/provider/model-router.js +2 -0
- package/dist/core/questions.js +31 -5
- package/dist/core/recallpulse.js +1 -1
- package/dist/core/release/canonical-test-proof.js +135 -0
- package/dist/core/release/release-closure-contract.js +1 -0
- package/dist/core/release/release-closure-validation.js +25 -12
- package/dist/core/release/release-closure.js +34 -5
- package/dist/core/release/release-gate-contract.js +0 -3
- package/dist/core/release/release-gate-dag.js +4 -2
- package/dist/core/release/release-real-contract.js +41 -2
- package/dist/core/retention.js +90 -1
- package/dist/core/routes/dollar-manifest-lite.js +1 -1
- package/dist/core/routes.js +17 -18
- package/dist/core/safety/ssot-guard.js +1 -54
- package/dist/core/stop-gate/stop-gate-check.js +0 -14
- package/dist/core/stop-gate/stop-gate-writer.js +0 -4
- package/dist/core/subagents/agent-catalog.js +28 -5
- package/dist/core/subagents/model-policy.js +52 -11
- package/dist/core/subagents/naruto-proof-projection.js +40 -9
- package/dist/core/subagents/official-subagent-preparation.js +340 -52
- package/dist/core/subagents/official-subagent-prompt.js +16 -6
- package/dist/core/subagents/official-subagent-runner.js +122 -11
- package/dist/core/subagents/subagent-evidence.js +44 -8
- package/dist/core/subagents/wave-lifecycle.js +238 -0
- package/dist/core/verification/machine-feedback.js +39 -19
- package/dist/core/version.js +1 -1
- package/dist/native/sks-menubar/Sources/OverviewViewController.swift +194 -24
- package/dist/native/sks-menubar/Sources/ProcessClient.swift +47 -5
- package/dist/scripts/architecture-guard-check.js +1 -9
- package/dist/scripts/canonical-test-runner.js +51 -8
- package/dist/scripts/codex-0144-binary-identity-check.js +10 -4
- package/dist/scripts/codex-0144-policy-check.js +4 -0
- package/dist/scripts/codex-sdk-real-smoke-check.js +20 -2
- package/dist/scripts/current-command-surface-check.js +1 -1
- package/dist/scripts/docs-truthfulness-check.js +4 -2
- package/dist/scripts/gate-policy-audit-check.js +7 -1
- package/dist/scripts/loop-directive-check-lib.js +14 -13
- package/dist/scripts/product-design-plugin-routing-check.js +4 -9
- package/dist/scripts/release-affected-selector-check.js +7 -1
- package/dist/scripts/release-check-stamp.js +151 -18
- package/dist/scripts/release-dynamic-presets-check.js +5 -2
- package/dist/scripts/release-real-check.js +21 -3
- package/package.json +1 -1
- package/release-gates.v2.json +19 -20
- package/schemas/codex/agent-result.schema.json +4 -0
- package/dist/core/loops/goal-to-loop-compat.js +0 -22
|
@@ -1158,9 +1158,6 @@ function enforceWorkerQualityProtocolForSlice(result, slice) {
|
|
|
1158
1158
|
const kind = String(slice?.work_item_kind || result?.work_item_kind || '').toLowerCase();
|
|
1159
1159
|
const text = [kind, slice?.id, slice?.title].join(' ').toLowerCase();
|
|
1160
1160
|
const blockers = [];
|
|
1161
|
-
if ((kind === 'bugfix' || /\b(fix|bug|regression|broken|failure|crash|error)\b|버그|회귀/.test(text)) && !validRegressionProof(result.regression_proof || firstEnvelopeField(result, 'regression_proof'))) {
|
|
1162
|
-
blockers.push('tdd_evidence_missing');
|
|
1163
|
-
}
|
|
1164
1161
|
if ((kind === 'conflict_resolution' || /\b(repair|conflict|rebase|rollback)\b|수리|충돌/.test(text)) && !(result.repair_hypothesis || firstEnvelopeField(result, 'repair_hypothesis'))) {
|
|
1165
1162
|
blockers.push('repair_without_hypothesis');
|
|
1166
1163
|
}
|
|
@@ -1176,9 +1173,6 @@ function enforceWorkerQualityProtocolForSlice(result, slice) {
|
|
|
1176
1173
|
function firstEnvelopeField(result, field) {
|
|
1177
1174
|
return (Array.isArray(result?.patch_envelopes) ? result.patch_envelopes : []).find((envelope) => envelope?.[field])?.[field] || null;
|
|
1178
1175
|
}
|
|
1179
|
-
function validRegressionProof(proof) {
|
|
1180
|
-
return Boolean(proof && proof.failed_before === true && proof.passed_after === true && String(proof.test_file || '').trim());
|
|
1181
|
-
}
|
|
1182
1176
|
function normalizePathList(values) {
|
|
1183
1177
|
return (Array.isArray(values) ? values : []).map((file) => String(file || '').replace(/\\/g, '/').replace(/^\.\/+/, '').replace(/\/+$/, '')).filter(Boolean);
|
|
1184
1178
|
}
|
|
@@ -62,7 +62,8 @@ export const AGENT_RESULT_RUNTIME_SCHEMA = {
|
|
|
62
62
|
required: ['status', 'checks'],
|
|
63
63
|
properties: {
|
|
64
64
|
status: { type: 'string' },
|
|
65
|
-
checks: { type: 'array', items: { type: 'string' } }
|
|
65
|
+
checks: { type: 'array', items: { type: 'string' } },
|
|
66
|
+
reason: { type: 'string', minLength: 1 }
|
|
66
67
|
},
|
|
67
68
|
additionalProperties: false
|
|
68
69
|
},
|
|
@@ -64,7 +64,6 @@ export class PersistentAgentPatchQueueStore {
|
|
|
64
64
|
...(impact.cochange_required?.length && !cochangeAck ? [`impact_scan_cochange_missing:${impact.cochange_required.slice(0, 5).join(',')}`] : []),
|
|
65
65
|
...((diffQuality.errors || []).map((issue) => `diff_quality:${issue}`)),
|
|
66
66
|
...(feedback.ok === false ? ['machine_feedback_failed'] : []),
|
|
67
|
-
...(isBugfixKind(context.work_item_kind, envelope.task_slice_id) && !validRegressionProof(envelope.regression_proof || context.regression_proof) ? ['tdd_evidence_missing'] : []),
|
|
68
67
|
...(isRepairKind(context.work_item_kind, envelope.task_slice_id) && !(envelope.repair_hypothesis || context.repair_hypothesis) ? ['repair_without_hypothesis'] : [])
|
|
69
68
|
];
|
|
70
69
|
return {
|
|
@@ -145,17 +144,10 @@ export class PersistentAgentPatchQueueStore {
|
|
|
145
144
|
await appendJsonlMany(path.join(this.artifactDir, AGENT_PATCH_QUEUE_EVENTS_ARTIFACT), events.filter(Boolean));
|
|
146
145
|
}
|
|
147
146
|
}
|
|
148
|
-
function isBugfixKind(kind, id) {
|
|
149
|
-
const text = `${String(kind || '')} ${String(id || '')}`.toLowerCase();
|
|
150
|
-
return /\b(bugfix|fix|bug|regression|broken|failure|crash|error)\b|버그|회귀/.test(text);
|
|
151
|
-
}
|
|
152
147
|
function isRepairKind(kind, id) {
|
|
153
148
|
const text = `${String(kind || '')} ${String(id || '')}`.toLowerCase();
|
|
154
149
|
return /\b(conflict_resolution|repair|conflict|rebase|rollback)\b|수리|충돌/.test(text);
|
|
155
150
|
}
|
|
156
|
-
function validRegressionProof(proof) {
|
|
157
|
-
return Boolean(proof && proof.failed_before === true && proof.passed_after === true && String(proof.test_file || '').trim());
|
|
158
|
-
}
|
|
159
151
|
function changedFilesForEnvelope(envelope) {
|
|
160
152
|
const files = envelope.git_worktree?.changed_files?.length
|
|
161
153
|
? envelope.git_worktree.changed_files
|
|
@@ -100,17 +100,22 @@ function qualityProtocolBlockers(result) {
|
|
|
100
100
|
return [];
|
|
101
101
|
const kind = String(result.work_item_kind || result.naruto_runtime?.work_item_kind || '').toLowerCase();
|
|
102
102
|
const text = [kind, result.task_slice_id].join(' ').toLowerCase();
|
|
103
|
-
const proof = result.regression_proof || result.patch_envelopes?.find((envelope) => envelope.regression_proof)?.regression_proof || null;
|
|
104
103
|
const repair = result.repair_hypothesis || result.patch_envelopes?.find((envelope) => envelope.repair_hypothesis)?.repair_hypothesis || null;
|
|
105
104
|
const blockers = [];
|
|
106
|
-
if (
|
|
107
|
-
blockers.push('
|
|
105
|
+
if (!validWriteVerification(result.verification))
|
|
106
|
+
blockers.push('verification_evidence_missing');
|
|
108
107
|
if ((kind === 'conflict_resolution' || /\b(repair|conflict|rebase|rollback)\b|수리|충돌/.test(text)) && !repair)
|
|
109
108
|
blockers.push('repair_without_hypothesis');
|
|
110
109
|
return blockers;
|
|
111
110
|
}
|
|
112
|
-
function
|
|
113
|
-
|
|
111
|
+
function validWriteVerification(verification) {
|
|
112
|
+
const status = String(verification?.status || '').trim().toLowerCase();
|
|
113
|
+
const checks = Array.isArray(verification?.checks)
|
|
114
|
+
? verification.checks.map((check) => String(check || '').trim()).filter(Boolean)
|
|
115
|
+
: [];
|
|
116
|
+
if (status === 'passed')
|
|
117
|
+
return checks.length > 0;
|
|
118
|
+
return status === 'not_applicable' && Boolean(String(verification?.reason || '').trim());
|
|
114
119
|
}
|
|
115
120
|
export function agentWorkerPipelineContract() {
|
|
116
121
|
return {
|
|
@@ -169,7 +174,8 @@ function isRecord(value) {
|
|
|
169
174
|
function normalizeVerification(value) {
|
|
170
175
|
return {
|
|
171
176
|
status: String(value?.status || 'not_run'),
|
|
172
|
-
checks: Array.isArray(value?.checks) ? value.checks : []
|
|
177
|
+
checks: Array.isArray(value?.checks) ? value.checks : [],
|
|
178
|
+
...(String(value?.reason || '').trim() ? { reason: String(value.reason).trim() } : {})
|
|
173
179
|
};
|
|
174
180
|
}
|
|
175
181
|
function acceptsNoPatchReadOnlyOrNoop(value) {
|
|
@@ -418,7 +418,7 @@ function buildWorkerPrompt(slice) {
|
|
|
418
418
|
? 'Quality gates run before queue acceptance: impact-scan requires cochanged callers for exported signature changes, machine-feedback runs type/lint/related tests, diff-quality blocks dead exports, and compiled mistake rules block repeated mistakes.'
|
|
419
419
|
: '',
|
|
420
420
|
write.length
|
|
421
|
-
? '
|
|
421
|
+
? 'Every write result must report verification status passed with at least one concrete check, or status not_applicable with a specific reason. For a reproducible bug or changed observable behavior, add the smallest regression check that would catch it. Do not manufacture a dedicated test when a smaller real check is sufficient. For repair work, include repair_hypothesis before patching.'
|
|
422
422
|
: '',
|
|
423
423
|
leanEngineeringCompactText(),
|
|
424
424
|
'Required JSON fields: status, summary, findings, changed_files, patch_envelopes, verification, rollback_notes, blockers.'
|
package/dist/core/bench.js
CHANGED
|
@@ -343,7 +343,7 @@ export async function runLeanPolicyBench(root = process.cwd()) {
|
|
|
343
343
|
async function fakeGptFinalScenario(candidate, leanEnabled) {
|
|
344
344
|
const prompt = [
|
|
345
345
|
leanEnabled ? leanEngineeringCompactText() : 'Baseline implementation context without lean policy.',
|
|
346
|
-
leanEnabled ? '
|
|
346
|
+
leanEnabled ? 'Apply the Core Engineering Directive to the candidate and the available evidence.' : 'Review only catastrophic safety issues.',
|
|
347
347
|
`Candidate: ${candidate}`
|
|
348
348
|
].join('\n');
|
|
349
349
|
const result = await runFakeCodexSdkTask({
|
|
@@ -20,7 +20,7 @@ export async function detectOfficialGoalMode(opts = {}) {
|
|
|
20
20
|
ok: true,
|
|
21
21
|
official_goal_available: official,
|
|
22
22
|
default_enabled: official,
|
|
23
|
-
mode: official ? 'official_goal_default' : '
|
|
23
|
+
mode: official ? 'official_goal_default' : 'official_goal_unavailable',
|
|
24
24
|
codex_help_checked: Boolean(helpText),
|
|
25
25
|
codex_goal_help_checked: Boolean(goalHelpText),
|
|
26
26
|
codex_features_checked: Boolean(featuresText),
|
|
@@ -28,9 +28,11 @@ export async function detectOfficialGoalMode(opts = {}) {
|
|
|
28
28
|
codex_goals_feature_enabled: goalsFeature,
|
|
29
29
|
config_goal_defaults_detected: configDefault,
|
|
30
30
|
blockers: [],
|
|
31
|
-
warnings: official ? [] : ['
|
|
31
|
+
warnings: official ? [] : ['official_goal_unavailable_no_fallback']
|
|
32
32
|
};
|
|
33
33
|
}
|
|
34
|
+
// Capability evidence for non-Goal routes. This records whether the active
|
|
35
|
+
// Codex runtime exposes native Goal; it never creates or controls a goal.
|
|
34
36
|
export async function writeOfficialGoalModeArtifact(dir, detection) {
|
|
35
37
|
const artifact = path.join(dir, 'goal-mode-applied.json');
|
|
36
38
|
await writeJsonAtomic(artifact, detection);
|
|
@@ -18,6 +18,7 @@ export async function writeCodexControlProof(root, input) {
|
|
|
18
18
|
zellij_pane_id: input.task.zellijPaneId || null,
|
|
19
19
|
sdk_thread_id: input.result.sdkThreadId,
|
|
20
20
|
sdk_run_id: input.result.sdkRunId,
|
|
21
|
+
runtime_identity: input.result.runtimeIdentity || null,
|
|
21
22
|
stream_event_count: input.result.streamEventCount,
|
|
22
23
|
structured_output_valid: input.result.structuredOutputValid,
|
|
23
24
|
output_schema_id: input.task.outputSchemaId,
|
|
@@ -31,7 +31,7 @@ export async function runFakeCodexSdkTask(input) {
|
|
|
31
31
|
function fakeStructuredOutput(input) {
|
|
32
32
|
if (input.outputSchemaId === GPT_FINAL_ARBITER_RESULT_SCHEMA_ID) {
|
|
33
33
|
const prompt = String(input.prompt || '');
|
|
34
|
-
const leanEnabled = /\b(
|
|
34
|
+
const leanEnabled = /\b(Core Engineering Directive|sks\.lean-engineering-policy)\b/i.test(prompt);
|
|
35
35
|
const unsafe = /\b(truncate|delete all|drop table|credential|delete validation|validation removed|path traversal|sql injection|secret leak)\b/i.test(prompt);
|
|
36
36
|
const overbuild = leanEnabled ? classifyLeanOverbuild(prompt) : null;
|
|
37
37
|
const status = unsafe ? 'rejected' : overbuild ? 'needs_more_work' : 'approved';
|
|
@@ -46,9 +46,8 @@ export async function inspectCodexLbCliLaunchRecovery(input) {
|
|
|
46
46
|
: configLayer(await readText(projectConfigPath, '').catch(() => ''), 'project');
|
|
47
47
|
const overrides = cliConfigOverrides(args);
|
|
48
48
|
const environmentSelectsCodexLb = env.SKS_PROVIDER === 'codex-lb' || env.SKS_USE_CODEX_LB === '1';
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
if (cliSelectsLocalProvider(args) || (overrides.modelProvider && overrides.modelProvider !== 'codex-lb')) {
|
|
49
|
+
// Local-provider CLI options are the final operator intent.
|
|
50
|
+
if (cliSelectsLocalProvider(args)) {
|
|
52
51
|
return codexLbToolOutputRecoveryNotSelected();
|
|
53
52
|
}
|
|
54
53
|
const loadedLayers = [userConfig, profileConfig, projectConfig];
|
|
@@ -60,6 +59,11 @@ export async function inspectCodexLbCliLaunchRecovery(input) {
|
|
|
60
59
|
if (projectConfig.hasMachineLocalProviderConfig) {
|
|
61
60
|
return projectProviderConfigBlocked();
|
|
62
61
|
}
|
|
62
|
+
// Explicit model-provider overrides still win over user/profile defaults,
|
|
63
|
+
// but only after repository-local provider redirects have been rejected.
|
|
64
|
+
if (overrides.modelProvider && overrides.modelProvider !== 'codex-lb') {
|
|
65
|
+
return codexLbToolOutputRecoveryNotSelected();
|
|
66
|
+
}
|
|
63
67
|
const selectedProvider = overrides.modelProvider
|
|
64
68
|
?? (environmentSelectsCodexLb ? 'codex-lb' : null)
|
|
65
69
|
?? profileConfig.modelProvider
|
|
@@ -5,7 +5,7 @@ import { buildCodexExecutionPolicy, buildCodexSdkConfig } from './codex-sdk-conf
|
|
|
5
5
|
import { buildCodexSdkEnv } from './codex-sdk-env-policy.js';
|
|
6
6
|
import { translateCodexSdkEvent } from './codex-event-translator.js';
|
|
7
7
|
import { codexTimeoutClassForRoute } from './codex-reliability-shield.js';
|
|
8
|
-
import {
|
|
8
|
+
import { resolveOfficialCodexPackageRuntime } from '../codex-runtime/resolve-codex-runtime.js';
|
|
9
9
|
import { codexLbToolCatalogPath, ensureCodexLbToolCatalog, isCodexLbGpt56Model } from '../codex-lb/codex-lb-tool-catalog.js';
|
|
10
10
|
export async function runRealCodexSdkTask(input, policy) {
|
|
11
11
|
if (codexSdkTurnTimeoutMs(input) <= 0) {
|
|
@@ -23,16 +23,14 @@ export async function runRealCodexSdkTask(input, policy) {
|
|
|
23
23
|
raw: { aborted: true, hard_deadline_exceeded: true }
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
const runtime = await resolveCodexSdkRuntime(input);
|
|
27
|
+
if (!runtime.ok || !runtime.identity) {
|
|
28
|
+
throw new Error(`Trusted Codex SDK runtime unavailable: ${runtime.blockers.join(',')}`);
|
|
29
|
+
}
|
|
26
30
|
const mod = await import('@openai/codex-sdk');
|
|
27
31
|
const Codex = mod.Codex || mod.default?.Codex || mod.default;
|
|
28
32
|
if (typeof Codex !== 'function')
|
|
29
33
|
throw new Error('Codex SDK export Codex not found');
|
|
30
|
-
const runtime = await resolveCodexRuntime({
|
|
31
|
-
explicitPath: typeof input.requestedScopeContract?.codex_bin === 'string' ? input.requestedScopeContract.codex_bin : null,
|
|
32
|
-
requestedBy: 'codex-sdk-adapter'
|
|
33
|
-
});
|
|
34
|
-
if (!runtime.identity)
|
|
35
|
-
throw new Error(`Codex runtime not found: ${runtime.blockers.join(',')}`);
|
|
36
34
|
const toolCatalog = await prepareCodexLbToolCatalog(input, policy);
|
|
37
35
|
if (toolCatalog.required && !toolCatalog.ok) {
|
|
38
36
|
return {
|
|
@@ -160,6 +158,9 @@ export async function runRealCodexSdkTask(input, policy) {
|
|
|
160
158
|
raw: { item_count: events.filter((event) => String(event?.type || '').startsWith('item.')).length, tool_catalog: toolCatalog }
|
|
161
159
|
};
|
|
162
160
|
}
|
|
161
|
+
export async function resolveCodexSdkRuntime(_input) {
|
|
162
|
+
return resolveOfficialCodexPackageRuntime({ requestedBy: 'codex-sdk-adapter' });
|
|
163
|
+
}
|
|
163
164
|
export function codexSdkRuntimePolicies(input) {
|
|
164
165
|
const env = buildCodexSdkEnv(input);
|
|
165
166
|
const config = buildCodexSdkConfig(input);
|
|
@@ -3,6 +3,10 @@ export function buildCodexSdkConfig(input) {
|
|
|
3
3
|
const model = String(input.model || process.env.SKS_CODEX_MODEL || process.env.CODEX_MODEL || '').trim();
|
|
4
4
|
const serviceTier = String(input.serviceTier || process.env.SKS_SERVICE_TIER || 'fast');
|
|
5
5
|
const config = {
|
|
6
|
+
// Internal control-plane work is always native Codex. Ambient proxy
|
|
7
|
+
// credentials are not provider-selection consent.
|
|
8
|
+
model_provider: 'openai',
|
|
9
|
+
forced_login_method: 'chatgpt',
|
|
6
10
|
service_tier: serviceTier === 'standard' ? 'standard' : 'fast',
|
|
7
11
|
model_reasoning_effort: String(input.modelReasoningEffort || input.reasoningEffort || process.env.SKS_CODEX_REASONING || process.env.CODEX_MODEL_REASONING_EFFORT || 'medium'),
|
|
8
12
|
mcp_servers: {},
|
|
@@ -20,21 +24,6 @@ export function buildCodexSdkConfig(input) {
|
|
|
20
24
|
config.mcp_servers = {};
|
|
21
25
|
config.sks = { ...config.sks, no_mcp: true };
|
|
22
26
|
}
|
|
23
|
-
const codexLbApiKey = String(process.env.CODEX_LB_API_KEY || '').trim();
|
|
24
|
-
const codexLbBaseUrl = normalizeCodexLbBaseUrl(process.env.CODEX_LB_BASE_URL);
|
|
25
|
-
if (process.env.SKS_CODEX_LB_AUTOBYPASS !== '1' && codexLbApiKey && codexLbBaseUrl) {
|
|
26
|
-
config.model_provider = 'codex-lb';
|
|
27
|
-
config.model_providers = {
|
|
28
|
-
'codex-lb': {
|
|
29
|
-
name: 'openai',
|
|
30
|
-
base_url: codexLbBaseUrl,
|
|
31
|
-
wire_api: 'responses',
|
|
32
|
-
env_key: 'CODEX_LB_API_KEY',
|
|
33
|
-
supports_websockets: true,
|
|
34
|
-
requires_openai_auth: true
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
}
|
|
38
27
|
return config;
|
|
39
28
|
}
|
|
40
29
|
export function buildCodexExecutionPolicy(input) {
|
|
@@ -60,12 +49,3 @@ export function redactCodexSdkConfig(config) {
|
|
|
60
49
|
return value;
|
|
61
50
|
}));
|
|
62
51
|
}
|
|
63
|
-
function normalizeCodexLbBaseUrl(value) {
|
|
64
|
-
let host = String(value || '').trim();
|
|
65
|
-
if (!host)
|
|
66
|
-
return '';
|
|
67
|
-
if (!/^[a-z][a-z0-9+.-]*:\/\//i.test(host))
|
|
68
|
-
host = `https://${host}`;
|
|
69
|
-
host = host.replace(/\/+$/, '');
|
|
70
|
-
return /\/backend-api\/codex$/i.test(host) ? host : `${host}/backend-api/codex`;
|
|
71
|
-
}
|