@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.
Files changed (66) hide show
  1. package/README.md +22 -0
  2. package/SPONSORS.md +105 -0
  3. package/gui/dist/assets/index-B8ZZ0ivI.css +1 -0
  4. package/gui/dist/assets/index-CNTWhC5F.js +115 -0
  5. package/gui/dist/index.html +2 -2
  6. package/package.json +2 -1
  7. package/src/adapters/cursor/protobuf-request.ts +34 -21
  8. package/src/adapters/cursor/tool-guidance.ts +2 -2
  9. package/src/adapters/cursor/tool-result-normalize.ts +22 -2
  10. package/src/adapters/exec-tool-result-normalize.ts +87 -0
  11. package/src/adapters/kiro.ts +29 -18
  12. package/src/adapters/responses-code-mode.ts +14 -4
  13. package/src/adapters/tool-catalog-nudge.ts +2 -2
  14. package/src/bridge.ts +40 -24
  15. package/src/claude/inbound.ts +21 -6
  16. package/src/claude/outbound.ts +43 -26
  17. package/src/cli/capabilities.ts +27 -0
  18. package/src/cli/integrations.ts +1 -1
  19. package/src/cli/models-runtime-subcommands.ts +2 -0
  20. package/src/cli/models-runtime.ts +108 -1
  21. package/src/cli/observe.ts +18 -3
  22. package/src/cli/usage-report.ts +6 -1
  23. package/src/clients/config-export.ts +5 -3
  24. package/src/codex/auth-api.ts +36 -0
  25. package/src/codex/catalog/provider-fetch.ts +2 -1
  26. package/src/codex/quota-auto-refresh-state.ts +8 -0
  27. package/src/codex/quota-auto-refresh.ts +157 -27
  28. package/src/codex/warmup.ts +5 -0
  29. package/src/config/provider-validation.ts +70 -1
  30. package/src/config.ts +73 -1
  31. package/src/generated/compatibility-version.json +67 -55
  32. package/src/lib/json-byte-size.ts +61 -0
  33. package/src/lib/provider-outbound.ts +11 -10
  34. package/src/oauth/index.ts +42 -8
  35. package/src/oauth/orcarouter.ts +200 -0
  36. package/src/providers/key-store.ts +22 -0
  37. package/src/providers/registry.ts +78 -29
  38. package/src/responses/citation-markers.ts +56 -24
  39. package/src/responses/reasoning-envelope.ts +53 -19
  40. package/src/server/auth-cors.ts +8 -0
  41. package/src/server/chat-completions.ts +7 -0
  42. package/src/server/chat-native.ts +65 -3
  43. package/src/server/claude-messages.ts +30 -10
  44. package/src/server/effort-policy.ts +183 -1
  45. package/src/server/management/agent-settings-routes.ts +50 -9
  46. package/src/server/management/config-routes.ts +2 -0
  47. package/src/server/management/logs-usage-routes.ts +11 -3
  48. package/src/server/management/model-routes.ts +65 -1
  49. package/src/server/management/model-rows.ts +5 -0
  50. package/src/server/management/provider-routes.ts +99 -6
  51. package/src/server/management/route-registry.ts +2 -0
  52. package/src/server/management/usage-aggregate-cache.ts +14 -7
  53. package/src/server/responses/compact.ts +3 -2
  54. package/src/server/responses/core.ts +16 -2
  55. package/src/server/startup-health-cache.ts +31 -9
  56. package/src/types/config.ts +5 -0
  57. package/src/types/provider.ts +4 -0
  58. package/src/usage/cost.ts +27 -31
  59. package/src/usage/summary.ts +52 -9
  60. package/src/usage/time-range.ts +48 -0
  61. package/src/usage/user-cost-overlays.ts +35 -3
  62. package/src/vision/anthropic-describe.ts +46 -2
  63. package/src/web-search/anthropic-executor.ts +49 -3
  64. package/src/web-search/parse.ts +1 -1
  65. package/gui/dist/assets/index-B72RPblC.js +0 -115
  66. 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 type { WebSearchSource } from "./parse";
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(value, { stream: true })).replace(/\r\n/g, "\n");
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
- const t = await res.text().catch(() => "");
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) {
@@ -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 {