sneakoscope 2.0.1 → 2.0.4
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 +26 -5
- package/crates/sks-core/Cargo.lock +1 -1
- package/crates/sks-core/Cargo.toml +1 -1
- package/crates/sks-core/src/main.rs +1 -1
- package/dist/.sks-build-stamp.json +4 -4
- package/dist/bin/sks.js +1 -1
- package/dist/build-manifest.json +28 -8
- package/dist/cli/command-registry.js +2 -0
- package/dist/commands/doctor.js +29 -3
- package/dist/core/agents/agent-command-surface.js +13 -3
- package/dist/core/agents/agent-orchestrator.js +92 -4
- package/dist/core/agents/agent-output-validator.js +2 -1
- package/dist/core/agents/agent-patch-proof.js +5 -0
- package/dist/core/agents/agent-patch-schema.js +2 -1
- package/dist/core/agents/agent-proof-evidence.js +26 -0
- package/dist/core/agents/agent-roster.js +1 -1
- package/dist/core/agents/agent-runner-ollama.js +411 -0
- package/dist/core/agents/agent-schema.js +1 -1
- package/dist/core/agents/intelligent-work-graph.js +45 -3
- package/dist/core/agents/native-cli-session-swarm.js +8 -1
- package/dist/core/agents/native-cli-worker.js +1 -1
- package/dist/core/agents/native-worker-backend-router.js +44 -2
- package/dist/core/agents/ollama-worker-config.js +118 -0
- package/dist/core/auto-review.js +39 -6
- package/dist/core/codex-app/codex-app-fast-ui-repair.js +42 -3
- package/dist/core/codex-control/codex-fake-sdk-adapter.js +20 -0
- package/dist/core/codex-control/codex-output-schemas.js +5 -1
- package/dist/core/codex-control/gpt-final-arbiter.js +160 -0
- package/dist/core/codex-control/gpt-final-context-compressor.js +17 -0
- package/dist/core/codex-control/gpt-final-proof-pack.js +120 -0
- package/dist/core/codex-control/gpt-final-review-schema.js +71 -0
- package/dist/core/commands/basic-cli.js +36 -1
- package/dist/core/commands/local-model-command.js +120 -0
- package/dist/core/commands/mad-sks-command.js +58 -9
- package/dist/core/commands/naruto-command.js +77 -5
- package/dist/core/commands/run-command.js +33 -1
- package/dist/core/commands/team-command.js +31 -2
- package/dist/core/doctor/doctor-readiness-matrix.js +19 -0
- package/dist/core/feature-fixtures.js +5 -0
- package/dist/core/fsx.js +1 -1
- package/dist/core/git-simple.js +143 -4
- package/dist/core/hooks-runtime.js +1 -1
- package/dist/core/init.js +2 -0
- package/dist/core/local-llm/local-collaboration-policy.js +93 -0
- package/dist/core/local-llm/local-llm-config.js +15 -0
- package/dist/core/pipeline/final-gpt-patch-stage.js +31 -0
- package/dist/core/pipeline/final-gpt-review-stage.js +5 -0
- package/dist/core/provider/provider-context.js +72 -9
- package/dist/core/retention.js +11 -0
- package/dist/core/routes.js +21 -1
- package/dist/core/safety/mutation-guard.js +2 -0
- package/dist/core/team-live.js +7 -1
- package/dist/core/update-check.js +215 -25
- package/dist/core/verification/verification-worker-pool.js +12 -0
- package/dist/core/version.js +1 -1
- package/dist/core/zellij/zellij-worker-pane-manager.js +19 -2
- package/dist/scripts/agent-ast-aware-work-graph-check.js +1 -1
- package/dist/scripts/codex-sdk-team-naruto-agent-pipeline-check.js +2 -1
- package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -2
- package/dist/scripts/gpt-final-arbiter-check.js +63 -0
- package/dist/scripts/gpt-final-arbiter-performance-check.js +36 -0
- package/dist/scripts/local-collab-gpt-final-availability-check.js +58 -0
- package/dist/scripts/local-collab-no-local-only-final-check.js +27 -0
- package/dist/scripts/local-collab-policy-check.js +17 -0
- package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +92 -0
- package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +37 -0
- package/dist/scripts/mad-sks-zellij-launch-check.js +2 -1
- package/dist/scripts/provider-context-config-toml-check.js +63 -0
- package/dist/scripts/release-gate-existence-audit.js +4 -0
- package/dist/scripts/runtime-no-mjs-scripts-check.js +3 -2
- package/dist/scripts/zellij-worker-pane-manager-check.js +3 -0
- package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +39 -0
- package/package.json +13 -4
- package/schemas/local-llm/local-collaboration-policy.schema.json +57 -0
|
@@ -2,6 +2,8 @@ import path from 'node:path';
|
|
|
2
2
|
import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
3
|
import { buildFixturePatchEnvelopes } from './agent-runner-fake.js';
|
|
4
4
|
import { runProcessAgent } from './agent-runner-process.js';
|
|
5
|
+
import { classifyOllamaWorkerSlice, runOllamaAgent } from './agent-runner-ollama.js';
|
|
6
|
+
import { resolveOllamaWorkerConfig } from './ollama-worker-config.js';
|
|
5
7
|
import { runZellijAgent } from './agent-runner-zellij.js';
|
|
6
8
|
import { validateAgentWorkerResult } from './agent-worker-pipeline.js';
|
|
7
9
|
import { normalizeAgentPatchEnvelope } from './agent-patch-schema.js';
|
|
@@ -11,7 +13,8 @@ export const NATIVE_WORKER_BACKEND_ROUTER_SCHEMA = 'sks.native-worker-backend-ro
|
|
|
11
13
|
export async function runNativeWorkerBackendRouter(input) {
|
|
12
14
|
const root = path.resolve(input.agentRoot);
|
|
13
15
|
const requestedBackend = String(input.backend || '');
|
|
14
|
-
|
|
16
|
+
let backend = normalizeBackend(requestedBackend);
|
|
17
|
+
backend = await maybeAutoSelectOllamaBackend(backend, input);
|
|
15
18
|
const reportRel = path.join(input.workerDirRel, 'worker-backend-router-report.json');
|
|
16
19
|
const startedAt = nowIso();
|
|
17
20
|
let result;
|
|
@@ -61,6 +64,28 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
61
64
|
verification: { status: processRun.status === 'done' ? 'passed' : 'failed', checks: [...(processRun.verification?.checks || []), 'native-worker-backend-router', 'process-child-execution'] }
|
|
62
65
|
});
|
|
63
66
|
}
|
|
67
|
+
else if (backend === 'ollama') {
|
|
68
|
+
const ollamaRun = await runOllamaAgent(input.agent, input.slice, {
|
|
69
|
+
...input.intake,
|
|
70
|
+
missionId: input.intake.mission_id || input.intake.parent_mission_id || '',
|
|
71
|
+
agentRoot: root,
|
|
72
|
+
workerDirRel: input.workerDirRel,
|
|
73
|
+
cwd: input.intake.cwd || root,
|
|
74
|
+
route: input.intake.route || '$Agent',
|
|
75
|
+
fastMode: input.fastModePolicy.fast_mode,
|
|
76
|
+
serviceTier: input.fastModePolicy.service_tier
|
|
77
|
+
});
|
|
78
|
+
patchEnvelopes = Array.isArray(ollamaRun.patch_envelopes) ? ollamaRun.patch_envelopes : [];
|
|
79
|
+
proofLevel = ollamaRun.status === 'done' ? (patchEnvelopes.length ? 'model_authored' : 'ollama_worker_proven') : 'blocked';
|
|
80
|
+
result = validateAgentWorkerResult({
|
|
81
|
+
...ollamaRun,
|
|
82
|
+
backend: 'ollama',
|
|
83
|
+
patch_envelopes: patchEnvelopes,
|
|
84
|
+
model_authored_patch_envelopes: patchEnvelopes.length > 0,
|
|
85
|
+
fixture_patch_envelopes: false,
|
|
86
|
+
verification: { status: ollamaRun.status === 'done' ? 'passed' : 'failed', checks: [...(ollamaRun.verification?.checks || []), 'native-worker-backend-router', 'ollama-api-generate'] }
|
|
87
|
+
});
|
|
88
|
+
}
|
|
64
89
|
else if (backend === 'codex-sdk' || backend === 'zellij') {
|
|
65
90
|
const sdkTask = await runCodexTask({
|
|
66
91
|
route: String(input.intake.route || '$Agent'),
|
|
@@ -155,6 +180,7 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
155
180
|
finished_at: nowIso(),
|
|
156
181
|
ok: result.status === 'done',
|
|
157
182
|
selected_backend: backend || input.backend,
|
|
183
|
+
requested_backend: requestedBackend,
|
|
158
184
|
agent_id: input.agent.id,
|
|
159
185
|
session_id: input.agent.session_id,
|
|
160
186
|
worker_process_id: process.pid,
|
|
@@ -170,6 +196,7 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
170
196
|
sdk_run_id: childReports.find((report) => report?.sdk_run_id)?.sdk_run_id || null,
|
|
171
197
|
stream_event_count: Number(childReports.find((report) => report?.stream_event_count)?.stream_event_count || 0),
|
|
172
198
|
structured_output_valid: childReports.some((report) => report?.structured_output_valid === true),
|
|
199
|
+
ollama_request_ids: patchEnvelopes.map((envelope) => envelope.backend_ollama_request_id).filter(Boolean),
|
|
173
200
|
blockers: result.blockers || []
|
|
174
201
|
};
|
|
175
202
|
await writeJsonAtomic(path.join(root, reportRel), report);
|
|
@@ -184,8 +211,23 @@ export async function runNativeWorkerBackendRouter(input) {
|
|
|
184
211
|
patchEnvelopes
|
|
185
212
|
};
|
|
186
213
|
}
|
|
214
|
+
async function maybeAutoSelectOllamaBackend(backend, input) {
|
|
215
|
+
if (backend !== 'codex-sdk')
|
|
216
|
+
return backend;
|
|
217
|
+
if (input.intake?.backend_explicit === true || input.intake?.no_ollama === true)
|
|
218
|
+
return backend;
|
|
219
|
+
const config = await resolveOllamaWorkerConfig({
|
|
220
|
+
ollamaEnabled: input.intake?.ollama_enabled === true,
|
|
221
|
+
model: input.intake?.ollama_model || null,
|
|
222
|
+
baseUrl: input.intake?.ollama_base_url || null
|
|
223
|
+
}).catch(() => null);
|
|
224
|
+
if (!config?.ok || config.enabled !== true)
|
|
225
|
+
return backend;
|
|
226
|
+
const policy = classifyOllamaWorkerSlice(input.slice, { route: input.intake?.route, agent: input.agent });
|
|
227
|
+
return policy.ok ? 'ollama' : backend;
|
|
228
|
+
}
|
|
187
229
|
function normalizeBackend(value) {
|
|
188
|
-
return value === 'fake' || value === 'process' || value === 'codex-sdk' || value === 'zellij' ? value : null;
|
|
230
|
+
return value === 'fake' || value === 'process' || value === 'codex-sdk' || value === 'zellij' || value === 'ollama' ? value : null;
|
|
189
231
|
}
|
|
190
232
|
function envelopeOpts(input, source, childPid) {
|
|
191
233
|
return {
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { ensureDir, exists, nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
4
|
+
export const LOCAL_MODEL_CONFIG_SCHEMA = 'sks.local-model-config.v1';
|
|
5
|
+
export const OLLAMA_WORKER_CONFIG_SCHEMA = 'sks.ollama-worker-config.v1';
|
|
6
|
+
export const DEFAULT_OLLAMA_CODER_MODEL = 'rafw007/qwen36-a3b-claude-coder:q4_K_M';
|
|
7
|
+
export const DEFAULT_OLLAMA_BASE_URL = 'http://127.0.0.1:11434';
|
|
8
|
+
export const DEFAULT_OLLAMA_KEEP_ALIVE = '30m';
|
|
9
|
+
export const DEFAULT_OLLAMA_TIMEOUT_MS = 120_000;
|
|
10
|
+
export const DEFAULT_OLLAMA_THINK = false;
|
|
11
|
+
export function localModelConfigPath() {
|
|
12
|
+
return process.env.SKS_LOCAL_MODEL_CONFIG
|
|
13
|
+
? path.resolve(process.env.SKS_LOCAL_MODEL_CONFIG)
|
|
14
|
+
: path.join(os.homedir(), '.sneakoscope', 'local-model.json');
|
|
15
|
+
}
|
|
16
|
+
export async function readLocalModelConfig() {
|
|
17
|
+
const raw = await readJson(localModelConfigPath(), null);
|
|
18
|
+
return normalizeLocalModelConfig(raw || {});
|
|
19
|
+
}
|
|
20
|
+
export async function writeLocalModelConfig(patch) {
|
|
21
|
+
const current = await readLocalModelConfig();
|
|
22
|
+
const next = normalizeLocalModelConfig({ ...current, ...patch, updated_at: nowIso() });
|
|
23
|
+
await ensureDir(path.dirname(localModelConfigPath()));
|
|
24
|
+
await writeJsonAtomic(localModelConfigPath(), next);
|
|
25
|
+
return next;
|
|
26
|
+
}
|
|
27
|
+
export async function resolveOllamaWorkerConfig(input = {}) {
|
|
28
|
+
const configExists = await exists(localModelConfigPath());
|
|
29
|
+
const stored = await readLocalModelConfig();
|
|
30
|
+
const explicitDisable = boolEnv(process.env.SKS_OLLAMA_WORKERS) === false;
|
|
31
|
+
const explicitEnable = boolEnv(process.env.SKS_OLLAMA_WORKERS) === true || input.ollamaEnabled === true || input.backend === 'ollama';
|
|
32
|
+
const enabled = explicitDisable ? false : explicitEnable || stored.enabled === true;
|
|
33
|
+
const model = firstText(process.env.SKS_OLLAMA_MODEL, input.model, stored.model, DEFAULT_OLLAMA_CODER_MODEL);
|
|
34
|
+
const baseUrl = trimTrailingSlash(firstText(process.env.SKS_OLLAMA_BASE_URL, input.baseUrl, stored.base_url, DEFAULT_OLLAMA_BASE_URL));
|
|
35
|
+
const keepAlive = firstText(process.env.SKS_OLLAMA_KEEP_ALIVE, input.keepAlive, stored.keep_alive, DEFAULT_OLLAMA_KEEP_ALIVE);
|
|
36
|
+
const timeoutMs = positiveNumber(process.env.SKS_OLLAMA_TIMEOUT_MS, input.timeoutMs, stored.timeout_ms, DEFAULT_OLLAMA_TIMEOUT_MS);
|
|
37
|
+
const temperature = finiteNumber(process.env.SKS_OLLAMA_TEMPERATURE, input.temperature, stored.temperature, 0.1);
|
|
38
|
+
const think = boolEnv(process.env.SKS_OLLAMA_THINK) ?? input.think ?? stored.think ?? DEFAULT_OLLAMA_THINK;
|
|
39
|
+
const blockers = [
|
|
40
|
+
...(enabled ? [] : ['ollama_workers_disabled']),
|
|
41
|
+
...(!model ? ['ollama_model_missing'] : []),
|
|
42
|
+
...(!baseUrl ? ['ollama_base_url_missing'] : [])
|
|
43
|
+
];
|
|
44
|
+
return {
|
|
45
|
+
schema: OLLAMA_WORKER_CONFIG_SCHEMA,
|
|
46
|
+
ok: blockers.length === 0,
|
|
47
|
+
enabled,
|
|
48
|
+
provider: 'ollama',
|
|
49
|
+
model,
|
|
50
|
+
base_url: baseUrl,
|
|
51
|
+
keep_alive: keepAlive,
|
|
52
|
+
timeout_ms: timeoutMs,
|
|
53
|
+
temperature,
|
|
54
|
+
think,
|
|
55
|
+
config_path: localModelConfigPath(),
|
|
56
|
+
explicit_disable: explicitDisable,
|
|
57
|
+
explicit_enable: explicitEnable,
|
|
58
|
+
blockers
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export function normalizeLocalModelConfig(raw = {}) {
|
|
62
|
+
return {
|
|
63
|
+
schema: LOCAL_MODEL_CONFIG_SCHEMA,
|
|
64
|
+
...(raw.generated_at ? { generated_at: String(raw.generated_at) } : { generated_at: nowIso() }),
|
|
65
|
+
...(raw.updated_at ? { updated_at: String(raw.updated_at) } : {}),
|
|
66
|
+
enabled: raw.enabled === true,
|
|
67
|
+
provider: 'ollama',
|
|
68
|
+
model: firstText(raw.model, DEFAULT_OLLAMA_CODER_MODEL),
|
|
69
|
+
base_url: trimTrailingSlash(firstText(raw.base_url, raw.baseUrl, DEFAULT_OLLAMA_BASE_URL)),
|
|
70
|
+
keep_alive: firstText(raw.keep_alive, raw.keepAlive, DEFAULT_OLLAMA_KEEP_ALIVE),
|
|
71
|
+
timeout_ms: positiveNumber(raw.timeout_ms, raw.timeoutMs, DEFAULT_OLLAMA_TIMEOUT_MS),
|
|
72
|
+
temperature: finiteNumber(raw.temperature, 0.1),
|
|
73
|
+
think: typeof raw.think === 'boolean' ? raw.think : DEFAULT_OLLAMA_THINK,
|
|
74
|
+
policy: {
|
|
75
|
+
worker_only: true,
|
|
76
|
+
no_strategy_planning_design: true,
|
|
77
|
+
allowed_work: ['simple_code_patch_envelopes', 'read_only_collection']
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
export function boolEnv(value) {
|
|
82
|
+
const text = String(value ?? '').trim().toLowerCase();
|
|
83
|
+
if (!text)
|
|
84
|
+
return null;
|
|
85
|
+
if (['1', 'true', 'on', 'yes', 'enable', 'enabled'].includes(text))
|
|
86
|
+
return true;
|
|
87
|
+
if (['0', 'false', 'off', 'no', 'disable', 'disabled'].includes(text))
|
|
88
|
+
return false;
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
function firstText(...values) {
|
|
92
|
+
for (const value of values) {
|
|
93
|
+
const text = String(value ?? '').trim();
|
|
94
|
+
if (text)
|
|
95
|
+
return text;
|
|
96
|
+
}
|
|
97
|
+
return '';
|
|
98
|
+
}
|
|
99
|
+
function trimTrailingSlash(value) {
|
|
100
|
+
return value.replace(/\/+$/, '');
|
|
101
|
+
}
|
|
102
|
+
function positiveNumber(...values) {
|
|
103
|
+
for (const value of values) {
|
|
104
|
+
const n = Number(value);
|
|
105
|
+
if (Number.isFinite(n) && n > 0)
|
|
106
|
+
return Math.floor(n);
|
|
107
|
+
}
|
|
108
|
+
return DEFAULT_OLLAMA_TIMEOUT_MS;
|
|
109
|
+
}
|
|
110
|
+
function finiteNumber(...values) {
|
|
111
|
+
for (const value of values) {
|
|
112
|
+
const n = Number(value);
|
|
113
|
+
if (Number.isFinite(n))
|
|
114
|
+
return n;
|
|
115
|
+
}
|
|
116
|
+
return 0;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=ollama-worker-config.js.map
|
package/dist/core/auto-review.js
CHANGED
|
@@ -108,7 +108,7 @@ export const SKS_CONFIG_PROFILES = [
|
|
|
108
108
|
{ name: 'sks-research-xhigh', stripTable: true, block: sksProfileFileBlock({ effort: 'xhigh' }) },
|
|
109
109
|
{ name: 'sks-research', stripTable: true, block: sksProfileFileBlock({ effort: 'xhigh', approvalPolicy: 'never' }) },
|
|
110
110
|
{ name: 'sks-team', stripTable: true, block: sksProfileFileBlock({ effort: 'medium' }) },
|
|
111
|
-
{ name: MAD_HIGH_PROFILE, stripTable: true, block: sksProfileFileBlock({ effort: '
|
|
111
|
+
{ name: MAD_HIGH_PROFILE, stripTable: true, block: sksProfileFileBlock({ effort: 'xhigh', approvalPolicy: 'never', sandboxMode: 'danger-full-access', reviewer: AUTO_REVIEW_REVIEWER }) },
|
|
112
112
|
{ name: 'sks-default', stripTable: true, block: sksProfileFileBlock({ effort: 'high' }) }
|
|
113
113
|
];
|
|
114
114
|
function sksProfileFileBlock(opts = {}) {
|
|
@@ -146,7 +146,32 @@ export async function migrateSksProfilesToPerFile(opts = {}) {
|
|
|
146
146
|
tables_stripped: SKS_CONFIG_PROFILES.filter((profile) => profile.stripTable).map((profile) => profile.name)
|
|
147
147
|
};
|
|
148
148
|
}
|
|
149
|
-
export
|
|
149
|
+
export function buildMadHighLaunchProfileNoWrite(opts = {}) {
|
|
150
|
+
const env = opts.env || process.env;
|
|
151
|
+
const profileName = String(opts.profileName || MAD_HIGH_PROFILE);
|
|
152
|
+
return {
|
|
153
|
+
config_path: codexConfigPath(env),
|
|
154
|
+
profile_config_path: codexProfileConfigPath(profileName, env),
|
|
155
|
+
profile_name: profileName,
|
|
156
|
+
launch_args: [
|
|
157
|
+
'--sandbox',
|
|
158
|
+
'danger-full-access',
|
|
159
|
+
'--ask-for-approval',
|
|
160
|
+
'never',
|
|
161
|
+
'-c',
|
|
162
|
+
'service_tier=fast',
|
|
163
|
+
'-c',
|
|
164
|
+
'model_reasoning_effort=xhigh'
|
|
165
|
+
],
|
|
166
|
+
sandbox_mode: 'danger-full-access',
|
|
167
|
+
approval_policy: 'never',
|
|
168
|
+
model_reasoning_effort: 'xhigh',
|
|
169
|
+
service_tier: 'fast',
|
|
170
|
+
scope: 'explicit_launch_only',
|
|
171
|
+
writes_user_codex_config: false
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
export async function ensureMadHighProfileForSetupOrRepair(opts = {}) {
|
|
150
175
|
const configPath = opts.configPath || codexConfigPath(opts.env || process.env);
|
|
151
176
|
const env = opts.env || process.env;
|
|
152
177
|
await ensureDir(path.dirname(configPath));
|
|
@@ -160,7 +185,7 @@ export async function enableMadHighProfile(opts = {}) {
|
|
|
160
185
|
// selectors so Codex stops warning about the legacy config profile on launch.
|
|
161
186
|
await migrateSksProfilesToPerFile({ configPath, env });
|
|
162
187
|
await writeProfileConfig(configPath, MAD_HIGH_PROFILE, profileConfigBlock({
|
|
163
|
-
effort: '
|
|
188
|
+
effort: 'xhigh',
|
|
164
189
|
approvalPolicy: 'never',
|
|
165
190
|
sandboxMode: 'danger-full-access'
|
|
166
191
|
}));
|
|
@@ -168,14 +193,22 @@ export async function enableMadHighProfile(opts = {}) {
|
|
|
168
193
|
config_path: configPath,
|
|
169
194
|
profile_config_path: path.join(path.dirname(configPath), `${MAD_HIGH_PROFILE}.config.toml`),
|
|
170
195
|
profile_name: MAD_HIGH_PROFILE,
|
|
171
|
-
launch_args: ['--profile', MAD_HIGH_PROFILE, '--sandbox', 'danger-full-access', '--ask-for-approval', 'never', '-c', 'service_tier=fast'],
|
|
196
|
+
launch_args: ['--profile', MAD_HIGH_PROFILE, '--sandbox', 'danger-full-access', '--ask-for-approval', 'never', '-c', 'service_tier=fast', '-c', 'model_reasoning_effort=xhigh'],
|
|
172
197
|
sandbox_mode: 'danger-full-access',
|
|
173
198
|
approval_policy: 'never',
|
|
174
199
|
approvals_reviewer: AUTO_REVIEW_REVIEWER,
|
|
175
|
-
model_reasoning_effort: '
|
|
176
|
-
|
|
200
|
+
model_reasoning_effort: 'xhigh',
|
|
201
|
+
service_tier: 'fast',
|
|
202
|
+
scope: 'setup_or_repair_only',
|
|
203
|
+
writes_user_codex_config: true
|
|
177
204
|
};
|
|
178
205
|
}
|
|
206
|
+
export async function enableMadHighProfile(opts = {}) {
|
|
207
|
+
if (opts.allowUserConfigWrite !== true) {
|
|
208
|
+
throw new Error('enableMadHighProfile writes Codex user config; use buildMadHighLaunchProfileNoWrite for sks --mad');
|
|
209
|
+
}
|
|
210
|
+
return ensureMadHighProfileForSetupOrRepair(opts);
|
|
211
|
+
}
|
|
179
212
|
export function madHighProfileName() {
|
|
180
213
|
return MAD_HIGH_PROFILE;
|
|
181
214
|
}
|
|
@@ -16,6 +16,9 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
|
|
|
16
16
|
{ scope: 'codex_home', file: path.join(home, 'config.toml'), mode: 'sks_caused_host_owned_keys' }
|
|
17
17
|
];
|
|
18
18
|
const actions = [];
|
|
19
|
+
const detectedProjectLocalForbiddenKeys = [];
|
|
20
|
+
const unsafeReasons = [];
|
|
21
|
+
let detectedSksCausedMutation = false;
|
|
19
22
|
for (const candidate of candidates) {
|
|
20
23
|
const text = await readText(candidate.file, null);
|
|
21
24
|
if (text == null) {
|
|
@@ -25,8 +28,16 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
|
|
|
25
28
|
const repaired = candidate.mode === 'project_forbidden_keys'
|
|
26
29
|
? stripProjectLocalForbiddenKeys(text)
|
|
27
30
|
: stripSksCausedHostOwnedLines(text);
|
|
31
|
+
if (candidate.mode === 'project_forbidden_keys')
|
|
32
|
+
detectedProjectLocalForbiddenKeys.push(...repaired.removedKeys);
|
|
33
|
+
if (candidate.mode === 'sks_caused_host_owned_keys') {
|
|
34
|
+
const unsafe = detectUnsafeFastUiRepair(text);
|
|
35
|
+
unsafeReasons.push(...unsafe);
|
|
36
|
+
if (repaired.text !== text)
|
|
37
|
+
detectedSksCausedMutation = true;
|
|
38
|
+
}
|
|
28
39
|
if (repaired.text === text) {
|
|
29
|
-
actions.push({ scope: candidate.scope, file: displayPath(candidate.file), status: 'ok', changed: false, removed_keys: repaired.removedKeys });
|
|
40
|
+
actions.push({ scope: candidate.scope, file: displayPath(candidate.file), status: unsafeReasons.length && candidate.mode === 'sks_caused_host_owned_keys' ? 'requires_confirmation' : 'ok', changed: false, removed_keys: repaired.removedKeys });
|
|
30
41
|
continue;
|
|
31
42
|
}
|
|
32
43
|
const backupPath = `${candidate.file}.codex-app-ui-repair-${Date.now().toString(36)}.bak`;
|
|
@@ -49,9 +60,12 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
|
|
|
49
60
|
}
|
|
50
61
|
const after = await snapshotCodexAppUiState(resolvedRoot, { codexHome: home });
|
|
51
62
|
const changed = actions.some((action) => action.changed);
|
|
63
|
+
const requiresConfirmation = unsafeReasons.length > 0 && input.force !== true;
|
|
64
|
+
const safeAutoApply = changed && !requiresConfirmation;
|
|
52
65
|
const manual = changed && !input.apply;
|
|
53
66
|
const blockers = [
|
|
54
|
-
...(
|
|
67
|
+
...(requiresConfirmation ? ['codex_app_fast_ui_repair_requires_confirmation'] : []),
|
|
68
|
+
...(manual && !safeAutoApply ? ['codex_app_fast_ui_repair_requires_explicit_apply'] : []),
|
|
55
69
|
...(after.indicators.secret_leak_suspected ? ['codex_app_ui_repair_secret_leak_suspected'] : [])
|
|
56
70
|
];
|
|
57
71
|
const report = {
|
|
@@ -59,19 +73,44 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
|
|
|
59
73
|
generated_at: nowIso(),
|
|
60
74
|
ok: blockers.length === 0,
|
|
61
75
|
apply: input.apply === true,
|
|
76
|
+
safe_auto_apply: safeAutoApply,
|
|
77
|
+
requires_confirmation: requiresConfirmation,
|
|
78
|
+
detected_sks_caused_mutation: detectedSksCausedMutation,
|
|
79
|
+
detected_project_local_forbidden_keys: [...new Set(detectedProjectLocalForbiddenKeys)],
|
|
80
|
+
unsafe_repair_reasons: [...new Set(unsafeReasons)],
|
|
62
81
|
fast_selector: changed ? (input.apply ? 'repaired' : 'manual_action_required') : before.indicators.fast_selector === 'maybe_hidden_or_locked' ? 'manual_action_required' : 'ok',
|
|
63
82
|
provider_selector: 'ok',
|
|
64
83
|
host_owned_config: input.apply && changed ? 'repaired_with_backup' : changed ? 'preserved_until_explicit_apply' : 'preserved',
|
|
65
84
|
actions,
|
|
66
85
|
before_fast_selector: before.indicators.fast_selector,
|
|
67
86
|
after_fast_selector: after.indicators.fast_selector,
|
|
68
|
-
next_action: manual ? 'Run `sks doctor --fix --repair-codex-app-ui` after reviewing the repair plan.' : changed ? 'Restart Codex App if the selector was already hidden.' : 'No Codex App UI repair needed.',
|
|
87
|
+
next_action: requiresConfirmation ? 'Run `sks doctor --fix --repair-codex-app-ui` after reviewing the repair plan.' : manual && safeAutoApply ? 'Run `sks doctor --fix` to apply the safe Codex App UI repair.' : manual ? 'Run `sks doctor --fix --repair-codex-app-ui` after reviewing the repair plan.' : changed ? 'Restart Codex App if the selector was already hidden.' : 'No Codex App UI repair needed.',
|
|
69
88
|
blockers
|
|
70
89
|
};
|
|
71
90
|
if (input.reportPath)
|
|
72
91
|
await writeJsonAtomic(input.reportPath, report);
|
|
73
92
|
return report;
|
|
74
93
|
}
|
|
94
|
+
function detectUnsafeFastUiRepair(text) {
|
|
95
|
+
const reasons = [];
|
|
96
|
+
const lines = text.split(/\r?\n/);
|
|
97
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
98
|
+
const line = lines[i] || '';
|
|
99
|
+
const serviceTier = line.match(/^\s*service_tier\s*=\s*"(standard|flex)"\s*(?:#.*)?$/i)?.[1];
|
|
100
|
+
const sksMarked = SKS_CAUSED_RE.test(line) || SKS_CAUSED_RE.test(lines[i - 1] || '') || SKS_CAUSED_RE.test(lines[i + 1] || '');
|
|
101
|
+
if (serviceTier && !sksMarked)
|
|
102
|
+
reasons.push(`user_selected_service_tier_${serviceTier.toLowerCase()}`);
|
|
103
|
+
}
|
|
104
|
+
if (hasOddUnescapedQuotes(text))
|
|
105
|
+
reasons.push('unparseable_config_requires_manual_review');
|
|
106
|
+
return [...new Set(reasons)];
|
|
107
|
+
}
|
|
108
|
+
function hasOddUnescapedQuotes(text) {
|
|
109
|
+
return text.split(/\r?\n/).some((line) => {
|
|
110
|
+
const stripped = line.replace(/\\"/g, '');
|
|
111
|
+
return (stripped.match(/"/g) || []).length % 2 === 1;
|
|
112
|
+
});
|
|
113
|
+
}
|
|
75
114
|
function stripProjectLocalForbiddenKeys(text) {
|
|
76
115
|
const forbidden = scanProjectLocalForbiddenKeys(text);
|
|
77
116
|
if (!forbidden.length)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nowIso, randomId } from '../fsx.js';
|
|
2
|
+
import { GPT_FINAL_ARBITER_RESULT_SCHEMA_ID } from './gpt-final-review-schema.js';
|
|
2
3
|
export function fakeCodexSdkAllowed() {
|
|
3
4
|
return process.env.NODE_ENV === 'test'
|
|
4
5
|
|| process.env.SKS_CODEX_SDK_FAKE === '1'
|
|
@@ -25,6 +26,25 @@ export async function runFakeCodexSdkTask(input) {
|
|
|
25
26
|
};
|
|
26
27
|
}
|
|
27
28
|
function fakeStructuredOutput(input) {
|
|
29
|
+
if (input.outputSchemaId === GPT_FINAL_ARBITER_RESULT_SCHEMA_ID) {
|
|
30
|
+
const unsafe = /\b(truncate|delete all|drop table|credential)\b/i.test(input.prompt || '');
|
|
31
|
+
return {
|
|
32
|
+
schema: GPT_FINAL_ARBITER_RESULT_SCHEMA_ID,
|
|
33
|
+
status: unsafe ? 'rejected' : 'approved',
|
|
34
|
+
summary: unsafe
|
|
35
|
+
? 'Fake Codex SDK GPT final arbiter rejected an unsafe candidate for hermetic verification.'
|
|
36
|
+
: 'Fake Codex SDK GPT final arbiter approved the candidate for hermetic verification.',
|
|
37
|
+
gpt_review_findings: unsafe ? [{ severity: 'high', message: 'unsafe candidate rejected' }] : [],
|
|
38
|
+
accepted_patch_envelopes: unsafe ? [] : [],
|
|
39
|
+
modified_patch_envelopes: [],
|
|
40
|
+
rejected_patch_envelopes: unsafe ? [{ reason: 'unsafe candidate' }] : [],
|
|
41
|
+
required_followup_work: unsafe ? [{ blocker: 'unsafe_candidate_patch' }] : [],
|
|
42
|
+
verification_plan: ['schema validation', 'local collaboration final gate'],
|
|
43
|
+
rollback_notes: [],
|
|
44
|
+
blockers: unsafe ? ['unsafe_candidate_patch'] : [],
|
|
45
|
+
confidence: unsafe ? 'medium' : 'high'
|
|
46
|
+
};
|
|
47
|
+
}
|
|
28
48
|
return {
|
|
29
49
|
status: 'done',
|
|
30
50
|
summary: `Fake Codex SDK task completed for ${input.workItemId || input.route}.`,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { CODEX_AGENT_WORKER_RESULT_SCHEMA_ID, codexAgentWorkerResultSchema } from './schemas/agent-worker-result.schema.js';
|
|
2
|
+
import { GPT_FINAL_ARBITER_RESULT_SCHEMA_ID, gptFinalArbiterResultSchema } from './gpt-final-review-schema.js';
|
|
2
3
|
export const CODEX_OUTPUT_SCHEMA_IDS = [
|
|
3
4
|
CODEX_AGENT_WORKER_RESULT_SCHEMA_ID,
|
|
4
5
|
'sks.patch-envelope-result.v1',
|
|
@@ -6,11 +7,14 @@ export const CODEX_OUTPUT_SCHEMA_IDS = [
|
|
|
6
7
|
'sks.research-digest.v1',
|
|
7
8
|
'sks.release-failure-analysis.v1',
|
|
8
9
|
'sks.ux-ppt-review-result.v1',
|
|
9
|
-
'sks.core-skill-heldout-validation.v1'
|
|
10
|
+
'sks.core-skill-heldout-validation.v1',
|
|
11
|
+
GPT_FINAL_ARBITER_RESULT_SCHEMA_ID
|
|
10
12
|
];
|
|
11
13
|
export function resolveCodexOutputSchema(schemaId, fallback) {
|
|
12
14
|
if (schemaId === CODEX_AGENT_WORKER_RESULT_SCHEMA_ID)
|
|
13
15
|
return codexAgentWorkerResultSchema;
|
|
16
|
+
if (schemaId === GPT_FINAL_ARBITER_RESULT_SCHEMA_ID)
|
|
17
|
+
return gptFinalArbiterResultSchema;
|
|
14
18
|
if (fallback && typeof fallback === 'object')
|
|
15
19
|
return fallback;
|
|
16
20
|
return {
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import path from 'node:path';
|
|
2
|
+
import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
|
|
3
|
+
import { validateJsonSchemaRecursive } from '../json-schema-validator.js';
|
|
4
|
+
import { evaluateLocalCollaborationFinalGate, resolveLocalCollaborationPolicy } from '../local-llm/local-collaboration-policy.js';
|
|
5
|
+
import { runCodexTask } from './codex-control-plane.js';
|
|
6
|
+
import { GPT_FINAL_ARBITER_INPUT_SCHEMA, GPT_FINAL_ARBITER_RESULT_SCHEMA_ID, gptFinalArbiterResultSchema, normalizeGptFinalArbiterResult } from './gpt-final-review-schema.js';
|
|
7
|
+
import { compressGptFinalContext } from './gpt-final-context-compressor.js';
|
|
8
|
+
export const GPT_FINAL_ARBITER_RUN_SCHEMA = 'sks.gpt-final-arbiter-run.v1';
|
|
9
|
+
export async function runGptFinalArbiter(input, opts = {}) {
|
|
10
|
+
const started = Date.now();
|
|
11
|
+
const cwd = path.resolve(opts.cwd || process.cwd());
|
|
12
|
+
const root = path.resolve(opts.mutationLedgerRoot || path.join(cwd, '.sneakoscope', 'tmp', 'gpt-final-arbiter', safeName(input.mission_id || 'mission')));
|
|
13
|
+
const policy = resolveLocalCollaborationPolicy({ mode: input.local_mode });
|
|
14
|
+
const compressed = compressGptFinalContext(input);
|
|
15
|
+
if (policy.local_only_draft) {
|
|
16
|
+
return finalize(root, input, policy, compressed, blockedResult('needs_gpt_final_review', 'Local-only draft mode cannot produce final accepted proof.'), started, opts);
|
|
17
|
+
}
|
|
18
|
+
if (opts.forceUnavailable || process.env.SKS_GPT_FINAL_ARBITER_UNAVAILABLE === '1') {
|
|
19
|
+
return finalize(root, input, policy, compressed, blockedResult('gpt_final_arbiter_unavailable', 'GPT final arbiter backend is unavailable.'), started, opts);
|
|
20
|
+
}
|
|
21
|
+
let codexTask = null;
|
|
22
|
+
let parsed = null;
|
|
23
|
+
try {
|
|
24
|
+
codexTask = await runCodexTask({
|
|
25
|
+
route: String(input.route || '$Pipeline'),
|
|
26
|
+
tier: 'orchestrator',
|
|
27
|
+
missionId: String(input.mission_id || ''),
|
|
28
|
+
workItemId: 'gpt-final-arbiter',
|
|
29
|
+
slotId: 'gpt-final-arbiter',
|
|
30
|
+
generationIndex: 1,
|
|
31
|
+
sessionId: `gpt-final-${safeName(input.mission_id || 'mission')}`,
|
|
32
|
+
cwd,
|
|
33
|
+
prompt: buildArbiterPrompt(input, compressed),
|
|
34
|
+
inputFiles: [],
|
|
35
|
+
inputImages: [],
|
|
36
|
+
outputSchemaId: GPT_FINAL_ARBITER_RESULT_SCHEMA_ID,
|
|
37
|
+
outputSchema: gptFinalArbiterResultSchema,
|
|
38
|
+
sandboxPolicy: 'read-only',
|
|
39
|
+
requestedScopeContract: {
|
|
40
|
+
id: `gpt-final:${input.mission_id || 'mission'}`,
|
|
41
|
+
route: String(input.route || '$Pipeline'),
|
|
42
|
+
read_only: true,
|
|
43
|
+
allowed_paths: [],
|
|
44
|
+
write_paths: [],
|
|
45
|
+
user_confirmed_full_access: false,
|
|
46
|
+
mad_sks_authorized: process.env.SKS_MAD_SKS_ACTIVE === '1'
|
|
47
|
+
},
|
|
48
|
+
mutationLedgerRoot: root,
|
|
49
|
+
reliabilityPolicy: {
|
|
50
|
+
maxEmptyResultRetries: 1,
|
|
51
|
+
timeoutClass: 'standard'
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
parsed = parseFinalResponse(codexTask.finalResponse);
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
return finalize(root, input, policy, compressed, blockedResult('gpt_final_arbiter_unavailable', error instanceof Error ? error.message : String(error)), started, opts);
|
|
58
|
+
}
|
|
59
|
+
const normalized = normalizeGptFinalArbiterResult(parsed);
|
|
60
|
+
const validation = validateJsonSchemaRecursive(normalized, gptFinalArbiterResultSchema);
|
|
61
|
+
const taskBlockers = Array.isArray(codexTask?.blockers) ? codexTask.blockers.map(String) : [];
|
|
62
|
+
const result = {
|
|
63
|
+
...normalized,
|
|
64
|
+
blockers: [
|
|
65
|
+
...normalized.blockers,
|
|
66
|
+
...(codexTask?.ok === true ? [] : ['gpt_final_arbiter_unavailable']),
|
|
67
|
+
...taskBlockers,
|
|
68
|
+
...(validation.ok ? [] : ['gpt_final_result_schema_invalid', ...validation.issues.map((issue) => `schema:${issue}`)])
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
return finalize(root, input, policy, compressed, result, started, opts, codexTask);
|
|
72
|
+
}
|
|
73
|
+
function finalize(root, input, policy, compressed, result, started, opts, codexTask) {
|
|
74
|
+
const latencyMs = Math.max(0, Date.now() - started);
|
|
75
|
+
const gate = evaluateLocalCollaborationFinalGate({
|
|
76
|
+
policy,
|
|
77
|
+
localParticipated: true,
|
|
78
|
+
gptFinalStatus: result.status,
|
|
79
|
+
gptFinalAvailable: !result.blockers.includes('gpt_final_arbiter_unavailable'),
|
|
80
|
+
gptFinalBackend: codexTask ? 'codex-sdk' : null,
|
|
81
|
+
applyPatches: false
|
|
82
|
+
});
|
|
83
|
+
const artifact = {
|
|
84
|
+
schema: GPT_FINAL_ARBITER_RUN_SCHEMA,
|
|
85
|
+
generated_at: nowIso(),
|
|
86
|
+
ok: gate.ok && result.blockers.length === 0,
|
|
87
|
+
input_schema: input.schema || GPT_FINAL_ARBITER_INPUT_SCHEMA,
|
|
88
|
+
route: input.route,
|
|
89
|
+
mission_id: input.mission_id,
|
|
90
|
+
local_mode: policy.mode,
|
|
91
|
+
backend: codexTask ? 'codex-sdk' : 'unavailable',
|
|
92
|
+
backend_family: codexTask ? 'remote-gpt' : 'none',
|
|
93
|
+
local_outputs_count: Array.isArray(input.local_outputs) ? input.local_outputs.length : 0,
|
|
94
|
+
proof_pack: compressed.proof_pack,
|
|
95
|
+
latency_budget: {
|
|
96
|
+
...compressed.latency_budget,
|
|
97
|
+
latency_ms: latencyMs
|
|
98
|
+
},
|
|
99
|
+
result,
|
|
100
|
+
final_gate: gate,
|
|
101
|
+
codex_task: codexTask ? {
|
|
102
|
+
ok: codexTask.ok === true,
|
|
103
|
+
sdk_thread_id: codexTask.sdkThreadId || null,
|
|
104
|
+
sdk_run_id: codexTask.sdkRunId || null,
|
|
105
|
+
stream_event_count: codexTask.streamEventCount || 0,
|
|
106
|
+
structured_output_valid: codexTask.structuredOutputValid === true,
|
|
107
|
+
worker_result_path: codexTask.workerResultPath || null,
|
|
108
|
+
blockers: codexTask.blockers || []
|
|
109
|
+
} : null,
|
|
110
|
+
blockers: [
|
|
111
|
+
...result.blockers,
|
|
112
|
+
...gate.blockers,
|
|
113
|
+
...compressed.blockers
|
|
114
|
+
]
|
|
115
|
+
};
|
|
116
|
+
artifact.ok = artifact.blockers.length === 0 && (result.status === 'approved' || result.status === 'modified');
|
|
117
|
+
if (opts.writeArtifact !== false)
|
|
118
|
+
return writeArtifact(root, artifact);
|
|
119
|
+
return artifact;
|
|
120
|
+
}
|
|
121
|
+
async function writeArtifact(root, artifact) {
|
|
122
|
+
await writeJsonAtomic(path.join(root, 'gpt-final-arbiter.json'), artifact);
|
|
123
|
+
return artifact;
|
|
124
|
+
}
|
|
125
|
+
function blockedResult(blocker, summary) {
|
|
126
|
+
return normalizeGptFinalArbiterResult({
|
|
127
|
+
status: 'needs_more_work',
|
|
128
|
+
summary,
|
|
129
|
+
blockers: [blocker],
|
|
130
|
+
confidence: 'low',
|
|
131
|
+
required_followup_work: [{ blocker }]
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function parseFinalResponse(value) {
|
|
135
|
+
if (typeof value !== 'string')
|
|
136
|
+
return value || {};
|
|
137
|
+
try {
|
|
138
|
+
return JSON.parse(value);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return {};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
function buildArbiterPrompt(input, compressed) {
|
|
145
|
+
return [
|
|
146
|
+
'You are the GPT Final Arbiter for an SKS local collaboration run.',
|
|
147
|
+
'Local model outputs are drafts only. Review the proof pack, candidate diff, patch envelopes, verification results, side effects, mutation ledger, and rollback plan.',
|
|
148
|
+
'Approve or modify only when the candidate is safe and supported. Reject unsafe local patches. Return only the requested structured JSON schema.',
|
|
149
|
+
JSON.stringify({
|
|
150
|
+
route: input.route,
|
|
151
|
+
mission_id: input.mission_id,
|
|
152
|
+
local_mode: input.local_mode,
|
|
153
|
+
proof_pack: compressed.proof_pack
|
|
154
|
+
})
|
|
155
|
+
].join('\n');
|
|
156
|
+
}
|
|
157
|
+
function safeName(value) {
|
|
158
|
+
return String(value || 'unknown').replace(/[^a-zA-Z0-9_.-]+/g, '-').slice(0, 80);
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=gpt-final-arbiter.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { buildGptFinalLatencyBudgetReport, buildGptFinalProofPack } from './gpt-final-proof-pack.js';
|
|
2
|
+
export function compressGptFinalContext(input, opts = {}) {
|
|
3
|
+
const proofPack = buildGptFinalProofPack(input, opts);
|
|
4
|
+
const latencyBudget = buildGptFinalLatencyBudgetReport({
|
|
5
|
+
workerCount: proofPack.worker_count,
|
|
6
|
+
tokenBudgetEstimate: proofPack.token_budget_estimate,
|
|
7
|
+
latencyMs: opts.latencyMs ?? null
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
schema: 'sks.gpt-final-context-compressor.v1',
|
|
11
|
+
ok: latencyBudget.ok,
|
|
12
|
+
proof_pack: proofPack,
|
|
13
|
+
latency_budget: latencyBudget,
|
|
14
|
+
blockers: latencyBudget.ok ? [] : ['gpt_final_context_budget_exceeded']
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=gpt-final-context-compressor.js.map
|