@claudexor/harness-codex 3.1.0 → 3.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/dist/effort-gate.d.ts +61 -0
- package/dist/effort-gate.d.ts.map +1 -0
- package/dist/effort-gate.js +61 -0
- package/dist/effort-gate.js.map +1 -0
- package/dist/effort-probe.d.ts +167 -0
- package/dist/effort-probe.d.ts.map +1 -0
- package/dist/effort-probe.js +487 -0
- package/dist/effort-probe.js.map +1 -0
- package/dist/index.d.ts +8 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +54 -50
- package/dist/index.js.map +1 -1
- package/dist/parse.d.ts +4 -0
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +47 -1
- package/dist/parse.js.map +1 -1
- package/dist/toml.d.ts +9 -0
- package/dist/toml.d.ts.map +1 -0
- package/dist/toml.js +33 -0
- package/dist/toml.js.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-model effort discovery for codex.
|
|
3
|
+
*
|
|
4
|
+
* Codex advertises reasoning-effort vocabularies PER MODEL and exposes them
|
|
5
|
+
* machine-readably: `codex app-server --stdio` speaks JSON-RPC, and the v2
|
|
6
|
+
* `model/list` request answers with `data[].supportedReasoningEfforts` +
|
|
7
|
+
* `defaultReasoningEffort`. The ceiling is genuinely model-scoped — gpt-5.6-sol
|
|
8
|
+
* takes `ultra` while gpt-5.4 stops at `xhigh` — so a harness-wide ladder is
|
|
9
|
+
* always wrong for some model.
|
|
10
|
+
*
|
|
11
|
+
* The vendor's own generated schema types `ReasoningEffort` as "a non-empty
|
|
12
|
+
* reasoning effort value advertised by the model" (a bounded string, NOT an
|
|
13
|
+
* enum). We mirror that: whatever the probe reports is what we advertise, so a
|
|
14
|
+
* level newer than this repo starts working the moment codex ships it.
|
|
15
|
+
*
|
|
16
|
+
* A probe is never load-bearing. Missing binary, an older app-server without
|
|
17
|
+
* `model/list`, a timeout or malformed output all fall back to the recorded
|
|
18
|
+
* snapshot below and the run proceeds.
|
|
19
|
+
*/
|
|
20
|
+
import { spawn } from "node:child_process";
|
|
21
|
+
import { EffortHint, effortLevelsForModel, mergeEffortLadders } from "@claudexor/schema";
|
|
22
|
+
import { resolveEffort } from "@claudexor/core";
|
|
23
|
+
import { nowIso } from "@claudexor/util";
|
|
24
|
+
import { BIN, probeEnv } from "./missing-cli.js";
|
|
25
|
+
/**
|
|
26
|
+
* Recorded fallback, captured from a live `model/list` on the CLI version
|
|
27
|
+
* stamped below. Used ONLY when the live probe cannot answer; it is a snapshot
|
|
28
|
+
* of vendor state, never an allow-list this repo maintains by hand.
|
|
29
|
+
* (`defaultModel` is the entry that carried `isDefault: true` in that capture.)
|
|
30
|
+
*/
|
|
31
|
+
export const CODEX_EFFORT_SNAPSHOT = {
|
|
32
|
+
models: {
|
|
33
|
+
"gpt-5.6-sol": {
|
|
34
|
+
levels: ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
35
|
+
default: "low",
|
|
36
|
+
},
|
|
37
|
+
"gpt-5.6-terra": {
|
|
38
|
+
levels: ["low", "medium", "high", "xhigh", "max", "ultra"],
|
|
39
|
+
default: "medium",
|
|
40
|
+
},
|
|
41
|
+
"gpt-5.6-luna": { levels: ["low", "medium", "high", "xhigh", "max"], default: "medium" },
|
|
42
|
+
"gpt-5.5": { levels: ["low", "medium", "high", "xhigh"], default: "medium" },
|
|
43
|
+
"gpt-5.4": { levels: ["low", "medium", "high", "xhigh"], default: "medium" },
|
|
44
|
+
"gpt-5.4-mini": { levels: ["low", "medium", "high", "xhigh"], default: "medium" },
|
|
45
|
+
"gpt-5.3-codex-spark": { levels: ["low", "medium", "high", "xhigh"], default: "high" },
|
|
46
|
+
},
|
|
47
|
+
defaultModel: "gpt-5.6-sol",
|
|
48
|
+
};
|
|
49
|
+
/** Vendor CLI version `CODEX_EFFORT_SNAPSHOT` was captured from. */
|
|
50
|
+
export const CODEX_EFFORT_SNAPSHOT_VERIFIED_AGAINST = "0.144.1";
|
|
51
|
+
/**
|
|
52
|
+
* Harness-wide merged ladder of an advertised catalog, weakest→strongest. Kept
|
|
53
|
+
* as the coarse `effort_levels` fallback so every existing reader (settings
|
|
54
|
+
* validation, the composer's picker, INV-105 disclosure) keeps working while
|
|
55
|
+
* per-model narrowing happens through `effortLevelsForModel`.
|
|
56
|
+
*
|
|
57
|
+
* Ordering authority is the VENDOR: `model/list` returns each model's
|
|
58
|
+
* `supportedReasoningEfforts` already ordered weakest→strongest, so the
|
|
59
|
+
* harness ladder is the positional merge of those lists (`mergeEffortLadders`)
|
|
60
|
+
* — never a table this repo maintains. The Swift composer merges the manifests'
|
|
61
|
+
* already-ordered arrays the same way, so both sides of the wire agree.
|
|
62
|
+
*
|
|
63
|
+
* A level NO model orders against the rest (`unconstrained`) still belongs to
|
|
64
|
+
* the advertised set — some model really accepts it — but has no honest rank,
|
|
65
|
+
* so it trails the ranked merge here (membership/display) while staying
|
|
66
|
+
* excluded from the clamping order (`mergeEffortLadders.order`).
|
|
67
|
+
*/
|
|
68
|
+
export function unionEffortLevels(capability) {
|
|
69
|
+
const merged = mergeEffortLadders(Object.values(capability).map((entry) => entry.levels));
|
|
70
|
+
return [...merged.order, ...merged.unconstrained];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A vendor VALUE that is not an effort level at all. Distinct from `null` (an
|
|
74
|
+
* entry that simply advertises no effort surface, which is normal and skipped):
|
|
75
|
+
* this poisons the whole probe. See `readModelListEfforts`.
|
|
76
|
+
*/
|
|
77
|
+
const MALFORMED = Symbol("malformed-effort-entry");
|
|
78
|
+
/**
|
|
79
|
+
* Shape-check one `model/list` entry; never throws.
|
|
80
|
+
*
|
|
81
|
+
* ABSENCE is skipped (`null`): no id, no `supportedReasoningEfforts` array, an
|
|
82
|
+
* array member without the field, an empty list — a model with no effort surface
|
|
83
|
+
* is ordinary vendor output. A PRESENT value that is not an `EffortHint` is
|
|
84
|
+
* MALFORMED, because `EffortHint` is the wire contract every consumer downstream
|
|
85
|
+
* enforces, right up to `HarnessManifest.parse`.
|
|
86
|
+
*/
|
|
87
|
+
function readEntry(raw) {
|
|
88
|
+
if (typeof raw.id !== "string" || raw.id.trim() === "")
|
|
89
|
+
return null;
|
|
90
|
+
if (!Array.isArray(raw.supportedReasoningEfforts))
|
|
91
|
+
return null;
|
|
92
|
+
const levels = [];
|
|
93
|
+
for (const item of raw.supportedReasoningEfforts) {
|
|
94
|
+
const level = item?.reasoningEffort;
|
|
95
|
+
if (level === undefined)
|
|
96
|
+
continue;
|
|
97
|
+
const parsed = EffortHint.safeParse(level);
|
|
98
|
+
if (!parsed.success)
|
|
99
|
+
return MALFORMED;
|
|
100
|
+
if (!levels.includes(parsed.data))
|
|
101
|
+
levels.push(parsed.data);
|
|
102
|
+
}
|
|
103
|
+
if (levels.length === 0)
|
|
104
|
+
return null;
|
|
105
|
+
// An absent default is normal (the vendor omits it, or sends an empty string);
|
|
106
|
+
// a present one must be a real level, since it is published as the manifest's
|
|
107
|
+
// per-model `default` and read back through the same schema.
|
|
108
|
+
const fallback = raw.defaultReasoningEffort;
|
|
109
|
+
if (fallback === undefined || fallback === null || fallback === "") {
|
|
110
|
+
return [raw.id, { levels, default: null }];
|
|
111
|
+
}
|
|
112
|
+
const parsedDefault = EffortHint.safeParse(fallback);
|
|
113
|
+
if (!parsedDefault.success)
|
|
114
|
+
return MALFORMED;
|
|
115
|
+
return [raw.id, { levels, default: parsedDefault.data }];
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* The whole `model/list` payload as a capability map, or null for a FAILED probe.
|
|
119
|
+
*
|
|
120
|
+
* STRICT on purpose (the reviewed decision): ONE malformed value discards the
|
|
121
|
+
* ENTIRE live catalog and the caller degrades to the recorded snapshot, which is
|
|
122
|
+
* exactly what this module promises. Skipping the bad entry instead would publish
|
|
123
|
+
* a silently NARROWED ladder — a model advertising `["low", "HIGH!"]` would go out
|
|
124
|
+
* as `["low"]`, stamped with the installed CLI version, so a `high` request would
|
|
125
|
+
* clamp down to `low` and the freshness gate would call the ladder fresh. And a
|
|
126
|
+
* malformed value that reached the manifest would fail `HarnessManifest.parse`,
|
|
127
|
+
* breaking discovery rather than degrading it. The snapshot is a real, usable
|
|
128
|
+
* ladder, so strictness costs freshness and never capability.
|
|
129
|
+
*
|
|
130
|
+
* `defaultModel` is the entry the vendor flagged `isDefault: true`
|
|
131
|
+
* (live-verified on 0.144.1). Only a literal boolean true counts: the flag is
|
|
132
|
+
* model identity, not part of the effort wire contract, so an absent or odd
|
|
133
|
+
* value degrades the default to null rather than poisoning the catalog.
|
|
134
|
+
*/
|
|
135
|
+
export function readModelListEfforts(data) {
|
|
136
|
+
if (!Array.isArray(data))
|
|
137
|
+
return null;
|
|
138
|
+
const capability = {};
|
|
139
|
+
let defaultModel = null;
|
|
140
|
+
for (const raw of data) {
|
|
141
|
+
const listed = raw;
|
|
142
|
+
const entry = readEntry(listed);
|
|
143
|
+
if (entry === MALFORMED)
|
|
144
|
+
return null;
|
|
145
|
+
// TWO separate facts per entry. `isDefault` is model IDENTITY and is read
|
|
146
|
+
// even when the entry contributes no ladder: a default model that
|
|
147
|
+
// advertises no effort surface is still the model a hint-less run executes
|
|
148
|
+
// on, and dropping its identity with its (nonexistent) ladder silently
|
|
149
|
+
// re-validated hint-less runs against the harness-wide union — the exact
|
|
150
|
+
// bug the default-model narrowing exists to prevent.
|
|
151
|
+
if (listed.isDefault === true && typeof listed.id === "string" && listed.id.trim() !== "") {
|
|
152
|
+
defaultModel ??= listed.id;
|
|
153
|
+
}
|
|
154
|
+
if (!entry)
|
|
155
|
+
continue;
|
|
156
|
+
capability[entry[0]] = entry[1];
|
|
157
|
+
}
|
|
158
|
+
return Object.keys(capability).length > 0 ? { models: capability, defaultModel } : null;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Ask a live `codex app-server` what each model advertises. Resolves to null on
|
|
162
|
+
* ANY failure — the caller falls back to the snapshot.
|
|
163
|
+
*/
|
|
164
|
+
export async function probeCodexEfforts(bin, opts = {}) {
|
|
165
|
+
const timeoutMs = opts.timeoutMs ?? 10_000;
|
|
166
|
+
return await new Promise((resolve) => {
|
|
167
|
+
let child;
|
|
168
|
+
try {
|
|
169
|
+
child = spawn(bin, ["app-server", "--stdio"], {
|
|
170
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
171
|
+
...(opts.env ? { env: opts.env } : {}),
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
resolve(null);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
let settled = false;
|
|
179
|
+
const finish = (value) => {
|
|
180
|
+
if (settled)
|
|
181
|
+
return;
|
|
182
|
+
settled = true;
|
|
183
|
+
clearTimeout(timer);
|
|
184
|
+
try {
|
|
185
|
+
child.kill("SIGKILL");
|
|
186
|
+
}
|
|
187
|
+
catch {
|
|
188
|
+
/* the child is already gone; nothing to clean up */
|
|
189
|
+
}
|
|
190
|
+
resolve(value);
|
|
191
|
+
};
|
|
192
|
+
const timer = setTimeout(() => finish(null), timeoutMs);
|
|
193
|
+
child.on("error", () => finish(null));
|
|
194
|
+
// `close`, NOT `exit`: `exit` fires when the process is reaped, which can
|
|
195
|
+
// beat the buffered stdout reaching the `data` handler above. An app-server
|
|
196
|
+
// that answers `model/list` and exits promptly would then be recorded as a
|
|
197
|
+
// FAILED probe and silently degrade a perfectly good live catalog to the
|
|
198
|
+
// snapshot. `close` fires only once every stdio stream is done, so by the
|
|
199
|
+
// time it runs the answer has already been parsed and `settled` is true.
|
|
200
|
+
// This does not reintroduce the EPIPE hazard: the asynchronous stream break
|
|
201
|
+
// still lands on the stdin/stdout `error` listeners below.
|
|
202
|
+
child.on("close", () => finish(null));
|
|
203
|
+
// A pipe to a child that already died reports the break ASYNCHRONOUSLY, on
|
|
204
|
+
// the stream's `error` event — `write()` returns normally and the EPIPE
|
|
205
|
+
// arrives a tick later, so the try/catch in `send` can never see it. Left
|
|
206
|
+
// unhandled that event is an UNCAUGHT EXCEPTION: it took down whole test
|
|
207
|
+
// runs on machines with no codex installed while every dev box (codex
|
|
208
|
+
// present, handshake answered) stayed green. Both failure shapes have the
|
|
209
|
+
// same meaning here — no live catalog — so both land on `finish(null)` and
|
|
210
|
+
// the caller degrades to the recorded snapshot.
|
|
211
|
+
child.stdin?.on("error", () => finish(null));
|
|
212
|
+
child.stdout?.on("error", () => finish(null));
|
|
213
|
+
const send = (payload) => {
|
|
214
|
+
// The probe is over: the child has been killed, so a queued frame would
|
|
215
|
+
// only write into a destroyed stream to no purpose.
|
|
216
|
+
if (settled)
|
|
217
|
+
return;
|
|
218
|
+
try {
|
|
219
|
+
child.stdin?.write(`${JSON.stringify(payload)}\n`);
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
// Kept for the SYNCHRONOUS shapes (a destroyed stream, a serialization
|
|
223
|
+
// fault); the asynchronous shape arrives on the listener above.
|
|
224
|
+
finish(null);
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
let buffer = "";
|
|
228
|
+
child.stdout?.on("data", (chunk) => {
|
|
229
|
+
buffer += chunk.toString();
|
|
230
|
+
let newline;
|
|
231
|
+
while ((newline = buffer.indexOf("\n")) >= 0) {
|
|
232
|
+
const line = buffer.slice(0, newline).trim();
|
|
233
|
+
buffer = buffer.slice(newline + 1);
|
|
234
|
+
if (line === "")
|
|
235
|
+
continue;
|
|
236
|
+
let message;
|
|
237
|
+
try {
|
|
238
|
+
message = JSON.parse(line);
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
continue;
|
|
242
|
+
}
|
|
243
|
+
if (message.id === 1) {
|
|
244
|
+
// Handshake accepted: the notification, then the v2 model query.
|
|
245
|
+
send({ method: "initialized", params: null });
|
|
246
|
+
send({ jsonrpc: "2.0", id: 2, method: "model/list", params: {} });
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (message.id !== 2)
|
|
250
|
+
continue;
|
|
251
|
+
finish(readModelListEfforts(message.result?.data));
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
});
|
|
255
|
+
send({
|
|
256
|
+
jsonrpc: "2.0",
|
|
257
|
+
id: 1,
|
|
258
|
+
method: "initialize",
|
|
259
|
+
params: { clientInfo: { name: "claudexor", version: "1" } },
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
// Codex advertises effort PER MODEL (`model/list`), so there is no single codex
|
|
264
|
+
// ladder to declare here — `codexEffortCapability()` below reads the live one and
|
|
265
|
+
// falls back to the recorded snapshot. Cached like cursor's api-key smoke: a
|
|
266
|
+
// bounded TTL map, so discovery and every run share one probe instead of
|
|
267
|
+
// re-spawning an app-server per call.
|
|
268
|
+
const CODEX_EFFORT_CACHE_TTL_MS = 10 * 60_000;
|
|
269
|
+
const CODEX_EFFORT_FAILURE_CACHE_TTL_MS = 60_000;
|
|
270
|
+
/**
|
|
271
|
+
* Hard ceiling on cached catalogs.
|
|
272
|
+
*
|
|
273
|
+
* The cache key is (resolved `CODEX_HOME`, binary), and an API-key route mints a
|
|
274
|
+
* FRESH `mkdtemp` home per run — so in a long-lived daemon every such run inserts
|
|
275
|
+
* a key that can never be read again. Expiry alone does not bound it: expiry is
|
|
276
|
+
* only consulted on a later read of the SAME key, which for an ephemeral home
|
|
277
|
+
* never comes, and `clearCodexEffortCache` is only reached from tests and the
|
|
278
|
+
* doctor's `fresh` path. The cap is what makes the map's size provably bounded
|
|
279
|
+
* regardless of run volume or uptime. Generous next to the real population
|
|
280
|
+
* (native home + one per credential profile, times installed binaries), so
|
|
281
|
+
* eviction only ever bites the ephemeral keys it exists for.
|
|
282
|
+
*/
|
|
283
|
+
const CODEX_EFFORT_CACHE_MAX_ENTRIES = 64;
|
|
284
|
+
const codexEffortCache = new Map();
|
|
285
|
+
/** Drop the cached effort probe (tests; and the doctor's `fresh` path). */
|
|
286
|
+
export function clearCodexEffortCache() {
|
|
287
|
+
codexEffortCache.clear();
|
|
288
|
+
}
|
|
289
|
+
/** Live entry count. Exported so the bound above can be asserted, not assumed. */
|
|
290
|
+
export function codexEffortCacheSize() {
|
|
291
|
+
return codexEffortCache.size;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Insert under the bound: drop everything already expired, then evict
|
|
295
|
+
* oldest-first until there is room. `Map` iterates in insertion order, so the
|
|
296
|
+
* first surviving key is the least recently INSERTED one — good enough here,
|
|
297
|
+
* because entries are rewritten on every refresh and the keys this protects
|
|
298
|
+
* against are write-once by construction.
|
|
299
|
+
*/
|
|
300
|
+
function storeCodexEfforts(key, entry, nowMs) {
|
|
301
|
+
for (const [k, v] of codexEffortCache) {
|
|
302
|
+
if (v.expiresAtMs <= nowMs)
|
|
303
|
+
codexEffortCache.delete(k);
|
|
304
|
+
}
|
|
305
|
+
codexEffortCache.delete(key);
|
|
306
|
+
while (codexEffortCache.size >= CODEX_EFFORT_CACHE_MAX_ENTRIES) {
|
|
307
|
+
const oldest = codexEffortCache.keys().next();
|
|
308
|
+
if (oldest.done)
|
|
309
|
+
break;
|
|
310
|
+
codexEffortCache.delete(oldest.value);
|
|
311
|
+
}
|
|
312
|
+
codexEffortCache.set(key, entry);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Cache identity of ONE codex effort catalog: the resolved `CODEX_HOME` plus the
|
|
316
|
+
* binary path.
|
|
317
|
+
*
|
|
318
|
+
* `model/list` answers for the ACCOUNT the resolved home is logged into, and
|
|
319
|
+
* every credential profile and API-key route gets its own `CODEX_HOME`. Keying by
|
|
320
|
+
* the binary alone therefore served one profile another account's models and
|
|
321
|
+
* ladders for the whole TTL — omitting levels the account really has, or sending
|
|
322
|
+
* levels it does not. The binary stays in the key because two codex versions
|
|
323
|
+
* advertise different catalogs from the same home.
|
|
324
|
+
*/
|
|
325
|
+
function codexEffortCacheKey(bin, env) {
|
|
326
|
+
// A JSON-encoded pair, not a joined string: both halves are paths, so any
|
|
327
|
+
// printable separator would let two different (home, bin) pairs share a key.
|
|
328
|
+
return JSON.stringify([env?.["CODEX_HOME"] ?? "", bin]);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* The per-model effort vocabulary codex currently advertises FOR THIS ENV. Live
|
|
332
|
+
* when the app-server answers, the recorded snapshot otherwise — a probe failure
|
|
333
|
+
* degrades the ladder's freshness, never the run.
|
|
334
|
+
*/
|
|
335
|
+
export async function codexEffortCapability(probe, nowMs, bin, env) {
|
|
336
|
+
const now = nowMs();
|
|
337
|
+
const key = codexEffortCacheKey(bin, env);
|
|
338
|
+
const cached = codexEffortCache.get(key);
|
|
339
|
+
if (cached && cached.expiresAtMs > now) {
|
|
340
|
+
return { catalog: cached.catalog, live: cached.live };
|
|
341
|
+
}
|
|
342
|
+
const probed = await probe(bin, env);
|
|
343
|
+
const live = probed !== null;
|
|
344
|
+
const catalog = probed ?? CODEX_EFFORT_SNAPSHOT;
|
|
345
|
+
storeCodexEfforts(key, {
|
|
346
|
+
catalog,
|
|
347
|
+
live,
|
|
348
|
+
expiresAtMs: now + (live ? CODEX_EFFORT_CACHE_TTL_MS : CODEX_EFFORT_FAILURE_CACHE_TTL_MS),
|
|
349
|
+
}, now);
|
|
350
|
+
return { catalog, live };
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The catalog for the environment a codex child will ACTUALLY run in. ONE owner
|
|
354
|
+
* of that resolution: callers hand over their env PATCH (spec env + provider
|
|
355
|
+
* scrub + the resolved `CODEX_HOME`) and this resolves it exactly the way the
|
|
356
|
+
* spawn will, so the probe env and the cache identity can never disagree.
|
|
357
|
+
*
|
|
358
|
+
* An API-key route uses a fresh temporary `CODEX_HOME` per run, so it re-probes
|
|
359
|
+
* each time by construction. That is the correct trade: one bounded app-server
|
|
360
|
+
* spawn instead of a cross-account catalog served out of the cache.
|
|
361
|
+
*/
|
|
362
|
+
export async function codexEffortsForEnv(deps, envPatch) {
|
|
363
|
+
return await codexEffortCapability(deps.probeEfforts, deps.nowMs, BIN, probeEnv(envPatch));
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* The effort value to send for one (model, requested) pair: advertised passes
|
|
367
|
+
* through verbatim, a level a SIBLING model advertises clamps inside the merged
|
|
368
|
+
* vendor order (`ultra` on gpt-5.4 → `xhigh` because the merged codex ladder
|
|
369
|
+
* places it), anything else sends no flag at all.
|
|
370
|
+
*
|
|
371
|
+
* If a future catalog ever contains two models whose advertised orders
|
|
372
|
+
* genuinely contradict each other, there is no honest merged rank — so
|
|
373
|
+
* cross-model clamping is treated as IMPOSSIBLE (the ladder collapses to the
|
|
374
|
+
* model's own list) and an unadvertised level is refused rather than clamped
|
|
375
|
+
* along an order this repo would have had to invent.
|
|
376
|
+
*/
|
|
377
|
+
export function codexEffortResolution(catalog, model, requested) {
|
|
378
|
+
const merged = mergeEffortLadders(Object.values(catalog.models).map((entry) => entry.levels));
|
|
379
|
+
// No model hint does NOT mean "any model": codex runs the catalog's DEFAULT
|
|
380
|
+
// model (`model/list` isDefault), so the requested level is held to THAT
|
|
381
|
+
// model's ladder. Validating a hint-less run against the harness-wide union
|
|
382
|
+
// let a sibling-only level (`ultra`) ride into a default model that rejects
|
|
383
|
+
// it. A catalog with no recorded default keeps the union fallback — the
|
|
384
|
+
// broadest honest set when the effective model is genuinely unknown.
|
|
385
|
+
//
|
|
386
|
+
// A default model the catalog recorded WITHOUT a ladder is different from an
|
|
387
|
+
// unknown model: the vendor listed it and advertised no effort surface, so
|
|
388
|
+
// its ladder is KNOWN-EMPTY, not unknown. `effortLevelsForModel`'s union
|
|
389
|
+
// fallback would clamp against sibling ladders the run never executes on;
|
|
390
|
+
// an empty advertised set instead sends no flag, and the caller's INV-105
|
|
391
|
+
// seam (`codexEffortIgnoredEvent`) discloses the dropped setting.
|
|
392
|
+
const effectiveModel = model ?? catalog.defaultModel;
|
|
393
|
+
const defaultKnownEffortless = effectiveModel != null &&
|
|
394
|
+
effectiveModel === catalog.defaultModel &&
|
|
395
|
+
!(effectiveModel in catalog.models);
|
|
396
|
+
const advertised = defaultKnownEffortless
|
|
397
|
+
? []
|
|
398
|
+
: effortLevelsForModel({
|
|
399
|
+
effort_levels: [...merged.order, ...merged.unconstrained],
|
|
400
|
+
model_effort_levels: catalog.models,
|
|
401
|
+
}, effectiveModel);
|
|
402
|
+
const check = resolveEffort(requested, advertised, merged.consistent ? merged.order : advertised);
|
|
403
|
+
if (check.status !== "ok")
|
|
404
|
+
return { effort: null, clamped: false, effectiveModel };
|
|
405
|
+
return { effort: check.effort, clamped: check.clamped, effectiveModel };
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* The level the arg builder should emit for one (model, requested) pair, or
|
|
409
|
+
* null when no flag should be sent. Thin projection of
|
|
410
|
+
* `codexEffortResolution`; the run-side disclosure seams read the full
|
|
411
|
+
* resolution so a clamp or a drop is never silent.
|
|
412
|
+
*/
|
|
413
|
+
export function codexEffortFor(catalog, model, requested) {
|
|
414
|
+
return codexEffortResolution(catalog, model, requested).effort;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* The INV-105 disclosure for an effort the RUN itself could not honor, or null
|
|
418
|
+
* when nothing was dropped. Preflight validates against the manifest — the
|
|
419
|
+
* DEFAULT account's catalog — but the adapter resolves against the catalog for
|
|
420
|
+
* the env the child actually runs in (profile / API-key homes have their own
|
|
421
|
+
* accounts), so a level can pass preflight and still resolve to "send no flag"
|
|
422
|
+
* here. Without this event that run silently executed at the vendor default;
|
|
423
|
+
* the payload rides the same `ignored_settings` channel governance uses, so
|
|
424
|
+
* the timeline renders the same warning either way.
|
|
425
|
+
*/
|
|
426
|
+
export function codexEffortIgnoredEvent(catalog, spec) {
|
|
427
|
+
if (!spec.effort_hint)
|
|
428
|
+
return null;
|
|
429
|
+
if (codexEffortFor(catalog, spec.model_hint, spec.effort_hint) !== null)
|
|
430
|
+
return null;
|
|
431
|
+
const target = spec.model_hint ?? catalog.defaultModel;
|
|
432
|
+
// An EMPTY catalog is the version-gated snapshot distrust case
|
|
433
|
+
// (`codexCatalogForRun`): the live probe could not answer and the recorded
|
|
434
|
+
// snapshot belongs to a different CLI version, so the honest statement is
|
|
435
|
+
// "unverifiable", not "not accepted".
|
|
436
|
+
const detail = Object.keys(catalog.models).length > 0
|
|
437
|
+
? `effort=${spec.effort_hint} (not accepted by the codex catalog resolved for this run's ` +
|
|
438
|
+
`environment${target ? ` on model ${target}` : ""}; the run used the vendor default)`
|
|
439
|
+
: `effort=${spec.effort_hint} (could not be verified against the installed codex CLI: ` +
|
|
440
|
+
"the live model/list probe could not answer, and the recorded snapshot was captured " +
|
|
441
|
+
`from CLI ${CODEX_EFFORT_SNAPSHOT_VERIFIED_AGAINST}, a different version, ` +
|
|
442
|
+
"so no effort flag was sent; the run used the vendor default)";
|
|
443
|
+
return {
|
|
444
|
+
type: "message",
|
|
445
|
+
session_id: spec.session_id,
|
|
446
|
+
ts: nowIso(),
|
|
447
|
+
text: `[effort] ignored: ${detail}`,
|
|
448
|
+
payload: { ignored_settings: [detail] },
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* The INV-105 disclosure for an effort the run CLAMPED, or null when the
|
|
453
|
+
* requested level rode through verbatim (or was dropped — that is
|
|
454
|
+
* `codexEffortIgnoredEvent`'s shape, and the two are mutually exclusive: a
|
|
455
|
+
* drop sends no level, a clamp sends a different one). A clamp is quieter than
|
|
456
|
+
* a drop but just as much a changed setting: `--effort ultra` on gpt-5.4 runs
|
|
457
|
+
* at `xhigh`, and without this event nothing in the timeline said so. The
|
|
458
|
+
* payload rides the same `ignored_settings` channel governance and the drop
|
|
459
|
+
* seam use, so every existing reader renders the same warning.
|
|
460
|
+
*/
|
|
461
|
+
/**
|
|
462
|
+
* The one INV-105 seam the run yields: the DROP disclosure or the CLAMP
|
|
463
|
+
* disclosure, whichever applies (they are mutually exclusive by construction —
|
|
464
|
+
* a drop sends no flag, a clamp sends a different one), or null when the
|
|
465
|
+
* requested level rode through verbatim or nothing was requested.
|
|
466
|
+
*/
|
|
467
|
+
export function codexEffortDisclosureEvent(catalog, spec) {
|
|
468
|
+
return codexEffortIgnoredEvent(catalog, spec) ?? codexEffortClampedEvent(catalog, spec);
|
|
469
|
+
}
|
|
470
|
+
export function codexEffortClampedEvent(catalog, spec) {
|
|
471
|
+
if (!spec.effort_hint)
|
|
472
|
+
return null;
|
|
473
|
+
const resolved = codexEffortResolution(catalog, spec.model_hint, spec.effort_hint);
|
|
474
|
+
if (!resolved.clamped || resolved.effort === null)
|
|
475
|
+
return null;
|
|
476
|
+
const detail = `effort=${spec.effort_hint} (clamped to ${resolved.effort}: the requested level is not ` +
|
|
477
|
+
`advertised by${resolved.effectiveModel ? ` model ${resolved.effectiveModel}` : " the resolved model"}, ` +
|
|
478
|
+
`so the run sent ${resolved.effort}, the nearest level that model advertises)`;
|
|
479
|
+
return {
|
|
480
|
+
type: "message",
|
|
481
|
+
session_id: spec.session_id,
|
|
482
|
+
ts: nowIso(),
|
|
483
|
+
text: `[effort] clamped: ${detail}`,
|
|
484
|
+
payload: { ignored_settings: [detail] },
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
//# sourceMappingURL=effort-probe.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effort-probe.js","sourceRoot":"","sources":["../src/effort-probe.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import type { HarnessRunSpec } from "@claudexor/schema";
|
|
2
|
+
import { type CodexEffortCatalog, type CodexEffortProbe } from "./effort-probe.js";
|
|
3
|
+
export { CODEX_EFFORT_SNAPSHOT, clearCodexEffortCache, unionEffortLevels } from "./effort-probe.js";
|
|
2
4
|
import type { HarnessAdapter } from "@claudexor/core";
|
|
3
5
|
import { brokenInstallAdvisory, runCliHarness, selectStrictAuthRoute } from "@claudexor/core";
|
|
4
6
|
import { smokeIsolatedApiKey } from "./smoke.js";
|
|
@@ -7,7 +9,7 @@ import { detectVersion } from "./missing-cli.js";
|
|
|
7
9
|
export { BIN } from "./missing-cli.js";
|
|
8
10
|
/** Exported for focused route-policy tests; runtime uses this exact selector. */
|
|
9
11
|
export declare const selectCodexRunAuthRoute: typeof selectStrictAuthRoute;
|
|
10
|
-
export { CODEX_FILE_AUTH_ARGS, CODEX_FILE_AUTH_OVERRIDE,
|
|
12
|
+
export { CODEX_FILE_AUTH_ARGS, CODEX_FILE_AUTH_OVERRIDE, codexAuthModeAt, defaultNativeCodexHome, ensureCodexApiAuth, probeLogin, } from "./auth.js";
|
|
11
13
|
import { codexApiKey, hasApiKey, probeLogin } from "./auth.js";
|
|
12
14
|
export declare function redactCodexDoctorDetail(text: string): string;
|
|
13
15
|
export declare function codexNativeEnv(base?: Record<string, string | null | undefined>, codexHome?: string): Record<string, string | null | undefined>;
|
|
@@ -36,6 +38,8 @@ export declare function codexExecArgs(spec: Pick<HarnessRunSpec, "access" | "mod
|
|
|
36
38
|
}, opts?: {
|
|
37
39
|
suppressNodeRepl?: boolean;
|
|
38
40
|
outputSchemaPath?: string | null;
|
|
41
|
+
/** The account's advertised effort catalog; the snapshot by default. */
|
|
42
|
+
effortCatalog?: CodexEffortCatalog;
|
|
39
43
|
}): string[];
|
|
40
44
|
/** The runtime surface the profile module needs (test-stubbable). */
|
|
41
45
|
export type CodexProfileRuntimeDeps = Pick<CodexRuntimeDeps, "probeLogin" | "resolveProfileSecret">;
|
|
@@ -50,6 +54,9 @@ type CodexRuntimeDeps = {
|
|
|
50
54
|
resolveProfileSecret: (ref: string) => string | null;
|
|
51
55
|
smokeIsolatedApiKey: typeof smokeIsolatedApiKey;
|
|
52
56
|
runCliHarness: typeof runCliHarness;
|
|
57
|
+
/** Live per-model effort discovery; null on any failure (caller falls back). */
|
|
58
|
+
probeEfforts: CodexEffortProbe;
|
|
59
|
+
nowMs: () => number;
|
|
53
60
|
};
|
|
54
61
|
export declare function createCodexAdapter(deps?: Partial<CodexRuntimeDeps>): HarnessAdapter;
|
|
55
62
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAQV,cAAc,EACf,MAAM,mBAAmB,CAAC;AAK3B,OAAO,EAOL,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACtB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACpG,OAAO,KAAK,EAAc,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAEL,qBAAqB,EAIrB,aAAa,EACb,qBAAqB,EAItB,MAAM,iBAAiB,CAAC;AAIzB,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,yBAAyB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAI/E,OAAO,EAAO,aAAa,EAA+C,MAAM,kBAAkB,CAAC;AACnG,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AAEvC,iFAAiF;AACjF,eAAO,MAAM,uBAAuB,8BAAwB,CAAC;AAE7D,OAAO,EACL,oBAAoB,EACpB,wBAAwB,EACxB,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,UAAU,GACX,MAAM,WAAW,CAAC;AACnB,OAAO,EAGL,WAAW,EAIX,SAAS,EACT,UAAU,EAEX,MAAM,WAAW,CAAC;AAgBnB,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED,wBAAgB,cAAc,CAC5B,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,EAChD,SAAS,CAAC,EAAE,MAAM,GACjB,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAM3C;AAmCD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,cAAc,CAAC,SAAS,CAAC,EAClC,qBAAqB,CAAC,EAAE,cAAc,CAAC,yBAAyB,CAAC,EACjE,eAAe,GAAE,cAAc,CAAC,mBAAmB,CAAM,GACxD,MAAM,EAAE,CA+CV;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAOpF;AAED,wBAAgB,aAAa,CAC3B,IAAI,EAAE,IAAI,CACR,cAAc,EACZ,QAAQ,GACR,YAAY,GACZ,aAAa,GACb,yBAAyB,GACzB,QAAQ,GACR,cAAc,GACd,aAAa,GACb,SAAS,CACZ,GAAG;IACF,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,iBAAiB,CAAC,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAC;CACzD,EACD,IAAI,GAAE;IACJ,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,wEAAwE;IACxE,aAAa,CAAC,EAAE,kBAAkB,CAAC;CAC/B,GACL,MAAM,EAAE,CAsEV;AA6BD,qEAAqE;AACrE,MAAM,MAAM,uBAAuB,GAAG,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,sBAAsB,CAAC,CAAC;AAEpG,KAAK,gBAAgB,GAAG;IACtB,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,qBAAqB,EAAE,OAAO,qBAAqB,CAAC;IACpD,UAAU,EAAE,OAAO,UAAU,CAAC;IAC9B,SAAS,EAAE,OAAO,SAAS,CAAC;IAC5B,WAAW,EAAE,OAAO,WAAW,CAAC;IAChC;0DACsD;IACtD,oBAAoB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC;IACrD,mBAAmB,EAAE,OAAO,mBAAmB,CAAC;IAChD,aAAa,EAAE,OAAO,aAAa,CAAC;IACpC,gFAAgF;IAChF,YAAY,EAAE,gBAAgB,CAAC;IAC/B,KAAK,EAAE,MAAM,MAAM,CAAC;CACrB,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,IAAI,GAAE,OAAO,CAAC,gBAAgB,CAAM,GAAG,cAAc,CAsRvF"}
|