@coseung2/opencodex 2.8.0-cs.15 → 2.8.0-cs.17
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/gui/dist/assets/{index-BhXIu7c0.js → index-Ch-99jy3.js} +2 -2
- package/gui/dist/index.html +1 -1
- package/package.json +1 -1
- package/packages/ocx-notch/README.md +3 -1
- package/src/adapters/base.ts +12 -0
- package/src/adapters/identity.ts +1 -1
- package/src/adapters/kiro-calibration.ts +83 -0
- package/src/adapters/kiro-constants.ts +11 -2
- package/src/adapters/kiro-errors.ts +11 -0
- package/src/adapters/kiro-events.ts +19 -1
- package/src/adapters/kiro-thinking.ts +18 -2
- package/src/adapters/kiro-tools.ts +12 -3
- package/src/adapters/kiro.ts +300 -78
- package/src/adapters/openai-chat.ts +1 -42
- package/src/adapters/openai-responses.ts +126 -9
- package/src/adapters/xai-schema-analysis.ts +78 -0
- package/src/adapters/xai-tool-schema.ts +274 -0
- package/src/adapters/xai-web-search.ts +138 -0
- package/src/bridge.ts +61 -6
- package/src/cli/observe.ts +18 -3
- package/src/codex/app-server-processes.ts +3 -5
- package/src/codex/catalog/effort.ts +4 -2
- package/src/codex/catalog/metadata.ts +42 -9
- package/src/codex/catalog/parsing.ts +17 -2
- package/src/codex/catalog/provider-fetch.ts +9 -3
- package/src/codex/catalog/sync.ts +11 -5
- package/src/codex/data/upstream-models.json +169 -0
- package/src/grok/inject.ts +1 -1
- package/src/lib/errors.ts +18 -0
- package/src/lib/token-estimate.ts +42 -38
- package/src/lib/translator-budget.ts +34 -0
- package/src/oauth/index.ts +10 -4
- package/src/oauth/kiro.ts +71 -6
- package/src/oauth/store.ts +3 -1
- package/src/oauth/types.ts +4 -0
- package/src/providers/derive.ts +7 -5
- package/src/providers/opencode-go-transport.ts +59 -0
- package/src/providers/quota.ts +68 -60
- package/src/providers/registry.ts +41 -10
- package/src/providers/xai-transport.ts +10 -0
- package/src/responses/compaction.ts +8 -1
- package/src/responses/namespace-aliases.ts +56 -0
- package/src/responses/parser.ts +12 -0
- package/src/responses/reasoning-envelope.ts +9 -1
- package/src/responses/snapshot-policy.ts +108 -0
- package/src/responses/state.ts +23 -10
- package/src/responses/turn-termination.ts +108 -0
- package/src/responses/xai-custom-tool-compat.ts +237 -0
- package/src/server/grok-responses-snapshot-repair.ts +338 -0
- package/src/server/index.ts +2 -1
- package/src/server/relay-eager.ts +1 -0
- package/src/server/request-log-conversation.ts +8 -0
- package/src/server/request-log.ts +5 -4
- package/src/server/responses/core.ts +233 -16
- package/src/server/responses-image-gen-repair.ts +2 -2
- package/src/server/sse-payload-rewrite.ts +20 -3
- package/src/types.ts +10 -1
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +7 -0
- package/src/usage/log.ts +1 -2
- package/vendor/ocx-notch/win32-x64/ocx-notch.exe +0 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
import type { TranslatorBudget } from "../lib/translator-budget";
|
|
2
|
+
import { MAX_COMPLETED_OUTPUT_ITEMS, MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES } from "./relay";
|
|
3
|
+
import type { SsePayloadRewrite } from "./sse-payload-rewrite";
|
|
4
|
+
|
|
5
|
+
interface OpenItemIdentity {
|
|
6
|
+
type: string;
|
|
7
|
+
id?: string;
|
|
8
|
+
sourceBytes: number;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface CompletedItem {
|
|
12
|
+
item: Record<string, unknown>;
|
|
13
|
+
sourceBytes: number;
|
|
14
|
+
visibleToGrok: boolean;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const SUPPORTED_ITEM_TYPES = new Set([
|
|
18
|
+
"message",
|
|
19
|
+
"reasoning",
|
|
20
|
+
"function_call",
|
|
21
|
+
"custom_tool_call",
|
|
22
|
+
"web_search_call",
|
|
23
|
+
"code_interpreter_call",
|
|
24
|
+
"mcp_call",
|
|
25
|
+
]);
|
|
26
|
+
|
|
27
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
28
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function validOptionalId(item: Record<string, unknown>): boolean {
|
|
32
|
+
return !("id" in item) || (typeof item.id === "string" && item.id.trim().length > 0);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function completedStatusWhenPresent(item: Record<string, unknown>): boolean {
|
|
36
|
+
return !("status" in item) || item.status === "completed";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function nullableString(value: unknown): boolean {
|
|
40
|
+
return value === null || typeof value === "string";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function backfillOutputTextPart(part: unknown): unknown {
|
|
44
|
+
if (!isPlainObject(part) || part.type !== "output_text" || Array.isArray(part.annotations)) return part;
|
|
45
|
+
return { ...part, annotations: [] };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function backfillMessageItem(item: unknown): unknown {
|
|
49
|
+
if (!isPlainObject(item) || item.type !== "message" || !Array.isArray(item.content)) return item;
|
|
50
|
+
let changed = false;
|
|
51
|
+
const content = item.content.map(part => {
|
|
52
|
+
const next = backfillOutputTextPart(part);
|
|
53
|
+
changed ||= next !== part;
|
|
54
|
+
return next;
|
|
55
|
+
});
|
|
56
|
+
return changed ? { ...item, content } : item;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function backfillGrokRequiredFields(payload: Record<string, unknown>): Record<string, unknown> {
|
|
60
|
+
let changed = false;
|
|
61
|
+
const next: Record<string, unknown> = { ...payload };
|
|
62
|
+
if (isPlainObject(payload.item)) {
|
|
63
|
+
const item = backfillMessageItem(payload.item);
|
|
64
|
+
if (item !== payload.item) { next.item = item; changed = true; }
|
|
65
|
+
}
|
|
66
|
+
if (isPlainObject(payload.part)) {
|
|
67
|
+
const part = backfillOutputTextPart(payload.part);
|
|
68
|
+
if (part !== payload.part) { next.part = part; changed = true; }
|
|
69
|
+
}
|
|
70
|
+
if (isPlainObject(payload.response) && Array.isArray(payload.response.output)) {
|
|
71
|
+
let outputChanged = false;
|
|
72
|
+
const output = payload.response.output.map(item => {
|
|
73
|
+
const repaired = backfillMessageItem(item);
|
|
74
|
+
outputChanged ||= repaired !== item;
|
|
75
|
+
return repaired;
|
|
76
|
+
});
|
|
77
|
+
if (outputChanged) {
|
|
78
|
+
next.response = { ...payload.response, output };
|
|
79
|
+
changed = true;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return changed ? next : payload;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function validOutputMessagePart(part: unknown): boolean {
|
|
86
|
+
if (!isPlainObject(part)) return false;
|
|
87
|
+
if (part.type === "output_text") {
|
|
88
|
+
return typeof part.text === "string"
|
|
89
|
+
&& (!("annotations" in part) || Array.isArray(part.annotations))
|
|
90
|
+
&& (!("logprobs" in part) || part.logprobs === null || Array.isArray(part.logprobs));
|
|
91
|
+
}
|
|
92
|
+
return part.type === "refusal" && typeof part.refusal === "string";
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function validReasoningPart(part: unknown, type: "summary_text" | "reasoning_text"): boolean {
|
|
96
|
+
return isPlainObject(part) && part.type === type && typeof part.text === "string";
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function validWebSearchAction(value: unknown): boolean {
|
|
100
|
+
if (!isPlainObject(value)) return false;
|
|
101
|
+
if (value.type === "search") {
|
|
102
|
+
return typeof value.query === "string"
|
|
103
|
+
&& (!("sources" in value) || value.sources === null || (Array.isArray(value.sources)
|
|
104
|
+
&& value.sources.every(source => isPlainObject(source)
|
|
105
|
+
&& typeof source.type === "string" && typeof source.url === "string")));
|
|
106
|
+
}
|
|
107
|
+
if (value.type === "open_page") return !("url" in value) || nullableString(value.url);
|
|
108
|
+
if (value.type === "find" || value.type === "find_in_page") {
|
|
109
|
+
return typeof value.url === "string" && typeof value.pattern === "string";
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function validCodeInterpreterOutput(value: unknown): boolean {
|
|
115
|
+
return isPlainObject(value)
|
|
116
|
+
&& ((value.type === "logs" && typeof value.logs === "string")
|
|
117
|
+
|| (value.type === "image" && typeof value.url === "string"));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Accept only semantic-complete items from a real output_item.done. Missing optional ids/status
|
|
122
|
+
* are tolerated, but content is never invented to justify a sparse terminal reconstruction.
|
|
123
|
+
*/
|
|
124
|
+
function trustedCompletedItem(item: Record<string, unknown>): { visibleToGrok: boolean } | null {
|
|
125
|
+
if (!validOptionalId(item) || !completedStatusWhenPresent(item)) return null;
|
|
126
|
+
|
|
127
|
+
if (item.type === "message") {
|
|
128
|
+
if (item.role !== "assistant" || !Array.isArray(item.content)) return null;
|
|
129
|
+
if (!item.content.every(validOutputMessagePart)) return null;
|
|
130
|
+
if ("phase" in item && item.phase !== "commentary" && item.phase !== "final_answer") return null;
|
|
131
|
+
return {
|
|
132
|
+
visibleToGrok: item.content.some(part => isPlainObject(part)
|
|
133
|
+
&& part.type === "output_text" && typeof part.text === "string" && part.text.length > 0),
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (item.type === "reasoning") {
|
|
138
|
+
if (!Array.isArray(item.summary) || !item.summary.every(part => validReasoningPart(part, "summary_text"))) return null;
|
|
139
|
+
if ("content" in item && item.content !== null
|
|
140
|
+
&& (!Array.isArray(item.content) || !item.content.every(part => validReasoningPart(part, "reasoning_text")))) return null;
|
|
141
|
+
if ("encrypted_content" in item && !nullableString(item.encrypted_content)) return null;
|
|
142
|
+
return { visibleToGrok: false };
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (item.type === "function_call") {
|
|
146
|
+
if (typeof item.call_id !== "string" || item.call_id.trim().length === 0
|
|
147
|
+
|| typeof item.name !== "string" || item.name.trim().length === 0
|
|
148
|
+
|| typeof item.arguments !== "string") return null;
|
|
149
|
+
return { visibleToGrok: true };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (item.type === "custom_tool_call") {
|
|
153
|
+
if (typeof item.call_id !== "string" || item.call_id.trim().length === 0
|
|
154
|
+
|| typeof item.name !== "string" || item.name.trim().length === 0
|
|
155
|
+
|| typeof item.input !== "string") return null;
|
|
156
|
+
// xAI restoration runs first: a client-executed function may already be a custom call.
|
|
157
|
+
return { visibleToGrok: true };
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (item.type === "web_search_call") {
|
|
161
|
+
if (item.status !== "completed" || !validWebSearchAction(item.action)) return null;
|
|
162
|
+
return { visibleToGrok: false };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
if (item.type === "code_interpreter_call") {
|
|
166
|
+
if (item.status !== "completed"
|
|
167
|
+
|| typeof item.container_id !== "string" || item.container_id.trim().length === 0
|
|
168
|
+
|| ("code" in item && !nullableString(item.code))
|
|
169
|
+
|| ("outputs" in item && item.outputs !== null
|
|
170
|
+
&& (!Array.isArray(item.outputs) || !item.outputs.every(validCodeInterpreterOutput)))) return null;
|
|
171
|
+
return { visibleToGrok: false };
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (item.type === "mcp_call") {
|
|
175
|
+
if (typeof item.arguments !== "string"
|
|
176
|
+
|| typeof item.name !== "string" || item.name.trim().length === 0
|
|
177
|
+
|| typeof item.server_label !== "string" || item.server_label.trim().length === 0
|
|
178
|
+
|| ("approval_request_id" in item && !nullableString(item.approval_request_id))
|
|
179
|
+
|| ("error" in item && !nullableString(item.error))
|
|
180
|
+
|| ("output" in item && !nullableString(item.output))) return null;
|
|
181
|
+
return { visibleToGrok: false };
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return null;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function plausibleOpenItem(item: Record<string, unknown>): Omit<OpenItemIdentity, "sourceBytes"> | null {
|
|
188
|
+
const type = typeof item.type === "string" ? item.type : "";
|
|
189
|
+
if (!SUPPORTED_ITEM_TYPES.has(type) || !validOptionalId(item)) return null;
|
|
190
|
+
if ("status" in item && item.status !== "in_progress") return null;
|
|
191
|
+
if (type === "message") {
|
|
192
|
+
if ("role" in item && item.role !== "assistant") return null;
|
|
193
|
+
if ("content" in item && !Array.isArray(item.content)) return null;
|
|
194
|
+
}
|
|
195
|
+
return { type, ...(typeof item.id === "string" ? { id: item.id } : {}) };
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Grok Build shows streaming deltas live but persists the final assistant turn from
|
|
200
|
+
* response.completed.response.output. Some native Responses streams leave that terminal array
|
|
201
|
+
* absent/empty while carrying complete items in output_item.done. Reconstruct only the sparse
|
|
202
|
+
* terminal case from unique, contiguous, bounded, validated done events; every ambiguity fails
|
|
203
|
+
* closed and leaves the provider payload byte-equivalent.
|
|
204
|
+
*/
|
|
205
|
+
export function createGrokResponsesSparseTerminalPayloadRewrite(
|
|
206
|
+
budget?: TranslatorBudget,
|
|
207
|
+
): SsePayloadRewrite {
|
|
208
|
+
const openItems = new Map<number, OpenItemIdentity>();
|
|
209
|
+
const completedItems = new Map<number, CompletedItem>();
|
|
210
|
+
let aggregateCompletedBytes = 0;
|
|
211
|
+
let aggregateOpenBytes = 0;
|
|
212
|
+
let tainted = false;
|
|
213
|
+
let hasVisibleOutput = false;
|
|
214
|
+
|
|
215
|
+
const clearRetained = (): void => {
|
|
216
|
+
const retained = aggregateCompletedBytes + aggregateOpenBytes;
|
|
217
|
+
if (retained > 0) budget?.releaseRetained(retained, { kind: "retained_collectors" });
|
|
218
|
+
openItems.clear();
|
|
219
|
+
completedItems.clear();
|
|
220
|
+
aggregateCompletedBytes = 0;
|
|
221
|
+
aggregateOpenBytes = 0;
|
|
222
|
+
hasVisibleOutput = false;
|
|
223
|
+
};
|
|
224
|
+
const reset = (): void => {
|
|
225
|
+
clearRetained();
|
|
226
|
+
tainted = false;
|
|
227
|
+
};
|
|
228
|
+
const taint = (): void => {
|
|
229
|
+
clearRetained();
|
|
230
|
+
tainted = true;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const closeOpen = (index: number): void => {
|
|
234
|
+
const open = openItems.get(index);
|
|
235
|
+
if (!open) return;
|
|
236
|
+
openItems.delete(index);
|
|
237
|
+
aggregateOpenBytes -= open.sourceBytes;
|
|
238
|
+
budget?.releaseRetained(open.sourceBytes, { kind: "retained_collectors" });
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
const rewrite = ((payload: string): string => {
|
|
242
|
+
if (payload === "[DONE]") {
|
|
243
|
+
reset();
|
|
244
|
+
return payload;
|
|
245
|
+
}
|
|
246
|
+
let decoded: unknown;
|
|
247
|
+
try { decoded = JSON.parse(payload); }
|
|
248
|
+
catch { taint(); return payload; }
|
|
249
|
+
if (!isPlainObject(decoded) || typeof decoded.type !== "string") {
|
|
250
|
+
taint();
|
|
251
|
+
return payload;
|
|
252
|
+
}
|
|
253
|
+
const parsed = backfillGrokRequiredFields(decoded);
|
|
254
|
+
const basePayload = parsed === decoded ? payload : JSON.stringify(parsed);
|
|
255
|
+
|
|
256
|
+
const outputIndex = Number.isInteger(parsed.output_index) && (parsed.output_index as number) >= 0
|
|
257
|
+
? parsed.output_index as number
|
|
258
|
+
: undefined;
|
|
259
|
+
|
|
260
|
+
if (parsed.type === "response.output_item.added") {
|
|
261
|
+
const open = isPlainObject(parsed.item) ? plausibleOpenItem(parsed.item) : null;
|
|
262
|
+
if (outputIndex === undefined || !open || openItems.has(outputIndex) || completedItems.has(outputIndex)
|
|
263
|
+
|| openItems.size >= MAX_COMPLETED_OUTPUT_ITEMS) {
|
|
264
|
+
taint();
|
|
265
|
+
} else if (!tainted) {
|
|
266
|
+
const sourceBytes = Buffer.byteLength(JSON.stringify(open), "utf8");
|
|
267
|
+
if (sourceBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES
|
|
268
|
+
|| aggregateOpenBytes + sourceBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES) {
|
|
269
|
+
taint();
|
|
270
|
+
} else {
|
|
271
|
+
budget?.chargeRetained(sourceBytes, { kind: "retained_collectors" });
|
|
272
|
+
openItems.set(outputIndex, { ...open, sourceBytes });
|
|
273
|
+
aggregateOpenBytes += sourceBytes;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return basePayload;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (parsed.type === "response.output_item.done") {
|
|
280
|
+
const item = isPlainObject(parsed.item) ? parsed.item : null;
|
|
281
|
+
const proof = item ? trustedCompletedItem(item) : null;
|
|
282
|
+
if (outputIndex === undefined || !proof || completedItems.has(outputIndex)) {
|
|
283
|
+
taint();
|
|
284
|
+
return basePayload;
|
|
285
|
+
}
|
|
286
|
+
const open = openItems.get(outputIndex);
|
|
287
|
+
const doneId = typeof item!.id === "string" ? item!.id : undefined;
|
|
288
|
+
if (open && (open.type !== item!.type || open.id !== doneId)) {
|
|
289
|
+
taint();
|
|
290
|
+
return basePayload;
|
|
291
|
+
}
|
|
292
|
+
closeOpen(outputIndex);
|
|
293
|
+
if (!tainted) {
|
|
294
|
+
const sourceBytes = Buffer.byteLength(JSON.stringify(item), "utf8");
|
|
295
|
+
if (sourceBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES
|
|
296
|
+
|| completedItems.size >= MAX_COMPLETED_OUTPUT_ITEMS
|
|
297
|
+
|| aggregateCompletedBytes + sourceBytes > MAX_COMPLETED_OUTPUT_ITEM_SOURCE_BYTES) {
|
|
298
|
+
taint();
|
|
299
|
+
} else {
|
|
300
|
+
budget?.chargeRetained(sourceBytes, { kind: "retained_collectors" });
|
|
301
|
+
completedItems.set(outputIndex, { item: item!, sourceBytes, visibleToGrok: proof.visibleToGrok });
|
|
302
|
+
aggregateCompletedBytes += sourceBytes;
|
|
303
|
+
hasVisibleOutput ||= proof.visibleToGrok;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return basePayload;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const terminal = parsed.type === "response.completed"
|
|
310
|
+
|| parsed.type === "response.failed"
|
|
311
|
+
|| parsed.type === "response.incomplete";
|
|
312
|
+
if (!terminal) return basePayload;
|
|
313
|
+
|
|
314
|
+
let rewritten = basePayload;
|
|
315
|
+
if (parsed.type === "response.completed" && !tainted && isPlainObject(parsed.response)) {
|
|
316
|
+
const response = parsed.response;
|
|
317
|
+
const output = response.output;
|
|
318
|
+
const statusConsistent = !("status" in response) || response.status === "completed";
|
|
319
|
+
const authoritative = Array.isArray(output) && output.length > 0;
|
|
320
|
+
const sparse = !("output" in response) || (Array.isArray(output) && output.length === 0);
|
|
321
|
+
if (!authoritative && sparse && statusConsistent && completedItems.size > 0
|
|
322
|
+
&& openItems.size === 0 && hasVisibleOutput) {
|
|
323
|
+
const ordered = [...completedItems.entries()].sort(([a], [b]) => a - b);
|
|
324
|
+
if (ordered.every(([index], position) => index === position)) {
|
|
325
|
+
rewritten = JSON.stringify({
|
|
326
|
+
...parsed,
|
|
327
|
+
response: { ...response, output: ordered.map(([, retained]) => retained.item) },
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
reset();
|
|
333
|
+
return rewritten;
|
|
334
|
+
}) as SsePayloadRewrite;
|
|
335
|
+
|
|
336
|
+
rewrite.dispose = reset;
|
|
337
|
+
return rewrite;
|
|
338
|
+
}
|
package/src/server/index.ts
CHANGED
|
@@ -527,7 +527,7 @@ export function startServer(port?: number) {
|
|
|
527
527
|
// Disabled natives stay in the catalog shape with visibility "hide" (mirrors the
|
|
528
528
|
// on-disk sync; codex-rs keeps them out of the picker itself).
|
|
529
529
|
const maMode = config.multiAgentMode === "v1" || config.multiAgentMode === "v2" ? config.multiAgentMode : "default";
|
|
530
|
-
const entries = buildCatalogEntries(loadCatalogTemplate(), nativeSlugs, goOrdered, config.subagentModels, websocketsEnabled(config), maMode as "v1" | "default" | "v2", exactComboCatalogSlugs(config));
|
|
530
|
+
const entries = buildCatalogEntries(loadCatalogTemplate(), nativeSlugs, goOrdered, config.subagentModels, websocketsEnabled(config), maMode as "v1" | "default" | "v2", exactComboCatalogSlugs(config), config);
|
|
531
531
|
return jsonResponse({ models: applyNativeVisibility(entries, disabledNativeSlugs(config)) }, 200, req, config);
|
|
532
532
|
}
|
|
533
533
|
// OpenAI list shape: native gpt bare + routed models namespaced "<provider>/<id>"
|
|
@@ -709,6 +709,7 @@ export function startServer(port?: number) {
|
|
|
709
709
|
...admissionFields(admission),
|
|
710
710
|
inboundProtocol: "responses",
|
|
711
711
|
};
|
|
712
|
+
if (req.headers.get("x-opencodex-grok") === "1") logCtx.surface = "grok";
|
|
712
713
|
let logged = false;
|
|
713
714
|
const finalizeNativePassthroughLog = (
|
|
714
715
|
status: number,
|
|
@@ -283,6 +283,7 @@ export function relaySseEagerBounded(
|
|
|
283
283
|
if (!cancelled) {
|
|
284
284
|
try { controllerRef?.close(); } catch { /* already closed/errored */ }
|
|
285
285
|
}
|
|
286
|
+
try { rewrite?.dispose?.(); } catch { /* rewrite teardown must not block lifecycle cleanup */ }
|
|
286
287
|
try { hooks.disposeInspection?.(); } catch { /* inspection teardown must not block lifecycle cleanup */ }
|
|
287
288
|
fireDone();
|
|
288
289
|
}
|
|
@@ -61,6 +61,14 @@ export function sessionIdHeaderFromRequest(headers: Headers): string | null {
|
|
|
61
61
|
return headers.get("session_id") ?? headers.get("session-id");
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
export function sessionLaneIdFromRequest(headers: Headers): string | undefined {
|
|
65
|
+
const parent = headers.get("x-codex-parent-thread-id")?.trim();
|
|
66
|
+
const thread = headers.get("thread-id")?.trim();
|
|
67
|
+
const session = sessionIdHeaderFromRequest(headers)?.trim();
|
|
68
|
+
const lane = [parent, thread, session].filter(Boolean);
|
|
69
|
+
return lane.length > 0 ? lane.join("\0") : undefined;
|
|
70
|
+
}
|
|
71
|
+
|
|
64
72
|
export function conversationIdFromResponsesRequest(input: {
|
|
65
73
|
clientThreadId?: string;
|
|
66
74
|
sessionIdHeader?: string | null;
|
|
@@ -4,6 +4,9 @@ import {
|
|
|
4
4
|
classifyError,
|
|
5
5
|
httpStatusFromTerminalError as httpStatusFromClassifiedTerminalError,
|
|
6
6
|
isClientClosedMessage,
|
|
7
|
+
isCyberPolicyCode,
|
|
8
|
+
isCyberPolicyMessage,
|
|
9
|
+
upstreamErrorMessageFromPayload,
|
|
7
10
|
} from "../lib/errors";
|
|
8
11
|
import { CODEX_CONFIG_PATH, readRootTomlString } from "../codex/paths";
|
|
9
12
|
import { readCodexCatalogPath } from "../codex/catalog";
|
|
@@ -674,9 +677,7 @@ function captureUpstreamErrorParsed(
|
|
|
674
677
|
logCtx.terminalIncompleteReason = reason.trim();
|
|
675
678
|
}
|
|
676
679
|
if (logCtx.upstreamError) return;
|
|
677
|
-
const message =
|
|
678
|
-
?? json?.last_error?.message
|
|
679
|
-
?? json?.response?.error?.message;
|
|
680
|
+
const message = upstreamErrorMessageFromPayload(parsed);
|
|
680
681
|
if (typeof message === "string" && message.trim()) {
|
|
681
682
|
logCtx.upstreamError = redactSecretString(message).slice(0, 500);
|
|
682
683
|
return;
|
|
@@ -939,7 +940,7 @@ function finalizedUsage(
|
|
|
939
940
|
const usageFallback = !finalUsage && estimate !== undefined
|
|
940
941
|
? { inputTokens: estimate, outputTokens: 0, estimated: true }
|
|
941
942
|
: undefined;
|
|
942
|
-
const loggedUsage = finalUsage && estimate !== undefined
|
|
943
|
+
const loggedUsage = finalUsage?.estimated && estimate !== undefined
|
|
943
944
|
? {
|
|
944
945
|
...finalUsage,
|
|
945
946
|
inputTokens: Math.max(finalUsage.inputTokens, estimate),
|