@bitkyc08/opencodex 2.46.0 → 2.47.0-preview.20260908
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 +22 -0
- package/SPONSORS.md +105 -0
- package/gui/dist/assets/index-B8ZZ0ivI.css +1 -0
- package/gui/dist/assets/index-CNTWhC5F.js +115 -0
- package/gui/dist/index.html +2 -2
- package/package.json +2 -1
- package/src/adapters/cursor/protobuf-request.ts +34 -21
- package/src/adapters/cursor/tool-guidance.ts +2 -2
- package/src/adapters/cursor/tool-result-normalize.ts +22 -2
- package/src/adapters/exec-tool-result-normalize.ts +87 -0
- package/src/adapters/kiro.ts +29 -18
- package/src/adapters/responses-code-mode.ts +14 -4
- package/src/adapters/tool-catalog-nudge.ts +2 -2
- package/src/bridge.ts +40 -24
- package/src/claude/inbound.ts +21 -6
- package/src/claude/outbound.ts +43 -26
- package/src/cli/capabilities.ts +27 -0
- package/src/cli/integrations.ts +1 -1
- package/src/cli/models-runtime-subcommands.ts +2 -0
- package/src/cli/models-runtime.ts +108 -1
- package/src/cli/observe.ts +18 -3
- package/src/cli/usage-report.ts +6 -1
- package/src/clients/config-export.ts +5 -3
- package/src/codex/auth-api.ts +36 -0
- package/src/codex/catalog/provider-fetch.ts +2 -1
- package/src/codex/quota-auto-refresh-state.ts +8 -0
- package/src/codex/quota-auto-refresh.ts +157 -27
- package/src/codex/warmup.ts +5 -0
- package/src/config/provider-validation.ts +70 -1
- package/src/config.ts +73 -1
- package/src/generated/compatibility-version.json +67 -55
- package/src/lib/json-byte-size.ts +61 -0
- package/src/lib/provider-outbound.ts +11 -10
- package/src/oauth/index.ts +42 -8
- package/src/oauth/orcarouter.ts +200 -0
- package/src/providers/key-store.ts +22 -0
- package/src/providers/registry.ts +78 -29
- package/src/responses/citation-markers.ts +56 -24
- package/src/responses/reasoning-envelope.ts +53 -19
- package/src/server/auth-cors.ts +8 -0
- package/src/server/chat-completions.ts +7 -0
- package/src/server/chat-native.ts +65 -3
- package/src/server/claude-messages.ts +30 -10
- package/src/server/effort-policy.ts +183 -1
- package/src/server/management/agent-settings-routes.ts +50 -9
- package/src/server/management/config-routes.ts +2 -0
- package/src/server/management/logs-usage-routes.ts +11 -3
- package/src/server/management/model-routes.ts +65 -1
- package/src/server/management/model-rows.ts +5 -0
- package/src/server/management/provider-routes.ts +99 -6
- package/src/server/management/route-registry.ts +2 -0
- package/src/server/management/usage-aggregate-cache.ts +14 -7
- package/src/server/responses/compact.ts +3 -2
- package/src/server/responses/core.ts +16 -2
- package/src/server/startup-health-cache.ts +31 -9
- package/src/types/config.ts +5 -0
- package/src/types/provider.ts +4 -0
- package/src/usage/cost.ts +27 -31
- package/src/usage/summary.ts +52 -9
- package/src/usage/time-range.ts +48 -0
- package/src/usage/user-cost-overlays.ts +35 -3
- package/src/vision/anthropic-describe.ts +46 -2
- package/src/web-search/anthropic-executor.ts +49 -3
- package/src/web-search/parse.ts +1 -1
- package/gui/dist/assets/index-B72RPblC.js +0 -115
- package/gui/dist/assets/index-BFgUC17B.css +0 -1
|
@@ -5,7 +5,11 @@ import { CLAUDE_CODE_HEADERS, claudeCodeSessionId } from "../adapters/client-fin
|
|
|
5
5
|
import { signalWithTimeout, cancelBodyOnAbort } from "../lib/abort";
|
|
6
6
|
import { sidecarEnter } from "../lib/sidecar-tracker";
|
|
7
7
|
import { applyUpstreamRecoveryInit, fetchWithResetRetry } from "../lib/upstream-retry";
|
|
8
|
-
import
|
|
8
|
+
import {
|
|
9
|
+
MAX_SIDECAR_RESPONSE_BYTES,
|
|
10
|
+
cancelReaderWithoutWaiting,
|
|
11
|
+
type WebSearchSource,
|
|
12
|
+
} from "./parse";
|
|
9
13
|
import { BASE_INSTRUCTION, IMAGE_INSTRUCTION, type SidecarOutcome, type SidecarSettings } from "./executor";
|
|
10
14
|
|
|
11
15
|
/** Hardcoded per-turn search bound handed to the server tool (mirrors the loop's maxSearches intent). */
|
|
@@ -17,6 +21,33 @@ function isRec(v: unknown): v is Record<string, unknown> {
|
|
|
17
21
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
18
22
|
}
|
|
19
23
|
|
|
24
|
+
/** Read at most `MAX_SIDECAR_RESPONSE_BYTES` of an untrusted upstream body, then stop reading. */
|
|
25
|
+
async function readBoundedText(res: Response): Promise<string> {
|
|
26
|
+
if (!res.body) return "";
|
|
27
|
+
const reader = res.body.getReader();
|
|
28
|
+
const decoder = new TextDecoder();
|
|
29
|
+
let out = "";
|
|
30
|
+
let seen = 0;
|
|
31
|
+
try {
|
|
32
|
+
for (;;) {
|
|
33
|
+
const { done, value } = await reader.read();
|
|
34
|
+
if (done) break;
|
|
35
|
+
const remaining = MAX_SIDECAR_RESPONSE_BYTES - seen;
|
|
36
|
+
const accepted = value.byteLength <= remaining ? value : value.subarray(0, remaining);
|
|
37
|
+
seen += accepted.byteLength;
|
|
38
|
+
out += decoder.decode(accepted, { stream: true });
|
|
39
|
+
if (seen >= MAX_SIDECAR_RESPONSE_BYTES) {
|
|
40
|
+
cancelReaderWithoutWaiting(reader, "sidecar error body byte limit reached");
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
out += decoder.decode();
|
|
45
|
+
} catch {
|
|
46
|
+
/* a failed error-body read must not mask the HTTP status we are about to report */
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
|
|
20
51
|
/**
|
|
21
52
|
* Fold an Anthropic Messages SSE stream (a web_search_20250305 turn) into a WebSearchResult.
|
|
22
53
|
*
|
|
@@ -41,6 +72,7 @@ export async function parseAnthropicSidecarSSE(res: Response): Promise<SidecarOu
|
|
|
41
72
|
const decoder = new TextDecoder();
|
|
42
73
|
const reader = res.body.getReader();
|
|
43
74
|
let buffer = "";
|
|
75
|
+
let responseBytes = 0;
|
|
44
76
|
|
|
45
77
|
const handleFrame = (data: Record<string, unknown>): void => {
|
|
46
78
|
const type = typeof data.type === "string" ? data.type : "";
|
|
@@ -82,15 +114,27 @@ export async function parseAnthropicSidecarSSE(res: Response): Promise<SidecarOu
|
|
|
82
114
|
for (;;) {
|
|
83
115
|
const { done, value } = await reader.read();
|
|
84
116
|
if (done) break;
|
|
117
|
+
// A sidecar that never emits a frame separator would otherwise grow `buffer` without
|
|
118
|
+
// limit. Bound the accepted bytes exactly like the Responses sidecar parser does.
|
|
119
|
+
const remaining = MAX_SIDECAR_RESPONSE_BYTES - responseBytes;
|
|
120
|
+
const accepted = value.byteLength <= remaining ? value : value.subarray(0, remaining);
|
|
121
|
+
responseBytes += accepted.byteLength;
|
|
85
122
|
// Normalize CRLF on the ACCUMULATED buffer so a `\r\n` pair split across two network chunks
|
|
86
123
|
// (chunk ends in `\r`, next starts with `\n`) still collapses to `\n` (audit round-2 F2).
|
|
87
|
-
buffer = (buffer + decoder.decode(
|
|
124
|
+
buffer = (buffer + decoder.decode(accepted, { stream: true })).replace(/\r\n/g, "\n");
|
|
88
125
|
let sep: number;
|
|
89
126
|
while ((sep = buffer.indexOf("\n\n")) !== -1) {
|
|
90
127
|
const rawFrame = buffer.slice(0, sep);
|
|
91
128
|
buffer = buffer.slice(sep + 2);
|
|
92
129
|
processFrame(rawFrame);
|
|
93
130
|
}
|
|
131
|
+
if (responseBytes >= MAX_SIDECAR_RESPONSE_BYTES) {
|
|
132
|
+
// Keep the frames already folded above, drop the unterminated tail, and do not wait on
|
|
133
|
+
// upstream teardown.
|
|
134
|
+
cancelReaderWithoutWaiting(reader, "sidecar response byte limit reached");
|
|
135
|
+
buffer = "";
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
94
138
|
}
|
|
95
139
|
// Flush the decoder and process any final unterminated frame (a stream that ends without \n\n).
|
|
96
140
|
buffer = (buffer + decoder.decode()).replace(/\r\n/g, "\n");
|
|
@@ -177,7 +221,9 @@ export async function runAnthropicWebSearch(
|
|
|
177
221
|
// (found investigating #1419).
|
|
178
222
|
const detachBodyGuard = cancelBodyOnAbort(res.body, linkedSignal.signal);
|
|
179
223
|
if (!res.ok) {
|
|
180
|
-
|
|
224
|
+
// Untrusted upstream error bodies are only used for an auth-failure message, so read a
|
|
225
|
+
// bounded prefix instead of buffering an arbitrarily large response.
|
|
226
|
+
const t = await readBoundedText(res);
|
|
181
227
|
detachBodyGuard();
|
|
182
228
|
console.warn(`[web-search] anthropic sidecar HTTP ${res.status} for query "${query.slice(0, 80)}" (${Date.now() - t0}ms)`);
|
|
183
229
|
if (res.status === 401) {
|
package/src/web-search/parse.ts
CHANGED
|
@@ -193,7 +193,7 @@ function fromOutputArray(output: OutputItem[], seen: Set<string>): WebSearchResu
|
|
|
193
193
|
return { text, sources };
|
|
194
194
|
}
|
|
195
195
|
|
|
196
|
-
function cancelReaderWithoutWaiting(
|
|
196
|
+
export function cancelReaderWithoutWaiting(
|
|
197
197
|
reader: ReadableStreamDefaultReader<Uint8Array>,
|
|
198
198
|
reason: string,
|
|
199
199
|
): void {
|