@bitkyc08/opencodex 2.7.35 → 2.7.36

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 (80) hide show
  1. package/README.ja.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +4 -2
  4. package/README.ru.md +1 -1
  5. package/README.zh-CN.md +1 -1
  6. package/bin/ocx.mjs +52 -0
  7. package/gui/dist/assets/index-BpX-hoSd.css +1 -0
  8. package/gui/dist/assets/index-ZmFopEYw.js +52 -0
  9. package/gui/dist/index.html +2 -2
  10. package/package.json +1 -1
  11. package/src/adapters/cursor/cursor-errors.ts +38 -1
  12. package/src/adapters/cursor/discovery.ts +1 -0
  13. package/src/adapters/cursor/effort-map.ts +1 -0
  14. package/src/adapters/cursor/live-models.ts +22 -5
  15. package/src/adapters/cursor/live-transport.ts +82 -7
  16. package/src/adapters/cursor/transport.ts +2 -0
  17. package/src/adapters/cursor.ts +5 -2
  18. package/src/adapters/openai-responses.ts +64 -1
  19. package/src/cli/doctor.ts +10 -0
  20. package/src/cli/help.ts +10 -0
  21. package/src/cli/index.ts +88 -9
  22. package/src/cli/internal-dispatch.ts +20 -0
  23. package/src/cli/status.ts +15 -4
  24. package/src/cli/tray-proxy.ts +52 -0
  25. package/src/codex/auth-api.ts +46 -5
  26. package/src/codex/autostart-health.ts +149 -0
  27. package/src/codex/catalog/aggregation.ts +268 -0
  28. package/src/codex/catalog/bundled.ts +188 -0
  29. package/src/codex/catalog/effort.ts +263 -0
  30. package/src/codex/catalog/metadata.ts +176 -0
  31. package/src/codex/catalog/parsing.ts +399 -0
  32. package/src/codex/catalog/provider-fetch.ts +609 -0
  33. package/src/codex/catalog/sync.ts +540 -0
  34. package/src/codex/catalog.ts +11 -2426
  35. package/src/codex/inject.ts +165 -3
  36. package/src/codex/shim.ts +141 -8
  37. package/src/codex/sync.ts +17 -2
  38. package/src/config.ts +23 -0
  39. package/src/lib/errors.ts +11 -0
  40. package/src/providers/antigravity-models.ts +33 -0
  41. package/src/providers/kiro-models.ts +2 -0
  42. package/src/providers/registry.ts +2 -2
  43. package/src/responses/state.ts +69 -6
  44. package/src/server/auth-cors.ts +3 -0
  45. package/src/server/management/agent-settings-routes.ts +536 -0
  46. package/src/server/management/combo-routes.ts +210 -0
  47. package/src/server/management/config-routes.ts +302 -0
  48. package/src/server/management/context.ts +21 -0
  49. package/src/server/management/logs-usage-routes.ts +176 -0
  50. package/src/server/management/model-routes.ts +253 -0
  51. package/src/server/management/oauth-account-routes.ts +301 -0
  52. package/src/server/management/provider-routes.ts +408 -0
  53. package/src/server/management/shared.ts +186 -0
  54. package/src/server/management-api.ts +23 -1806
  55. package/src/server/responses/collaboration.ts +300 -0
  56. package/src/server/responses/compact.ts +342 -0
  57. package/src/server/responses/core.ts +1498 -0
  58. package/src/server/responses/encrypted-payload.ts +231 -0
  59. package/src/server/responses/fetch-helpers.ts +157 -0
  60. package/src/server/responses.ts +9 -2172
  61. package/src/server/startup-action-control.ts +41 -0
  62. package/src/server/startup-health-cache.ts +100 -0
  63. package/src/server/windows-tray-control.ts +41 -0
  64. package/src/service.ts +171 -19
  65. package/src/tray/assets/opencodex-tray-offline.ico +0 -0
  66. package/src/tray/assets/opencodex-tray-online.ico +0 -0
  67. package/src/tray/assets/opencodex-tray-warning.ico +0 -0
  68. package/src/tray/assets/opencodex-tray.png +0 -0
  69. package/src/tray/windows-tray.ps1 +290 -0
  70. package/src/tray/windows.ts +628 -0
  71. package/src/types.ts +5 -0
  72. package/src/update/index.ts +43 -0
  73. package/src/update/job.ts +46 -0
  74. package/src/update/tray-update-plan.d.mts +18 -0
  75. package/src/update/tray-update-plan.mjs +38 -0
  76. package/src/usage/cost.ts +0 -0
  77. package/src/usage/expected-prices.ts +9 -2
  78. package/src/usage/summary.ts +42 -7
  79. package/gui/dist/assets/index-BunUANVE.js +0 -52
  80. package/gui/dist/assets/index-Sg-7L_oZ.css +0 -1
@@ -6,6 +6,10 @@ import type { OcxProviderContinuationState } from "../types";
6
6
  const MAX_STORED_RESPONSES = 1_000;
7
7
  const RESPONSE_TTL_MS = 60 * 60 * 1_000;
8
8
  const SNAPSHOT_DEBOUNCE_MS = 2_000;
9
+ /** In-memory high-water byte cap across all entries. Forced store:false retention (kiro/cursor
10
+ * continuation chains) stores the full expanded input each turn — ~quadratic bytes per chain —
11
+ * so a count cap alone cannot bound memory. Oldest-first eviction applies past this mark. */
12
+ const MAX_STORED_RESPONSE_BYTES = 64 * 1024 * 1024;
9
13
  /** Entries whose serialized size exceeds this are kept in memory but skipped on disk: inputs can
10
14
  * carry base64 `input_image` data URLs, and one screenshot-heavy thread must not balloon the file. */
11
15
  const SNAPSHOT_ENTRY_MAX_BYTES = 2 * 1024 * 1024;
@@ -19,9 +23,55 @@ interface StoredResponseState {
19
23
  /** v1 Cursor-only metadata, accepted only while loading old snapshots. */
20
24
  conversationId?: string;
21
25
  cursorCheckpointUsable?: boolean;
26
+ /** Approximate in-memory size, computed locally at insert time (never trusted from disk). */
27
+ sizeBytes?: number;
22
28
  }
23
29
 
24
30
  const states = new Map<string, StoredResponseState>();
31
+ let storedResponseBytes = 0;
32
+ let byteCapOverride: number | null = null;
33
+
34
+ function byteCap(): number {
35
+ return byteCapOverride ?? MAX_STORED_RESPONSE_BYTES;
36
+ }
37
+
38
+ /** Test-only: lower/restore the in-memory byte cap (null restores the default). */
39
+ export function setResponseStateByteCapForTests(bytes: number | null): void {
40
+ byteCapOverride = bytes;
41
+ }
42
+
43
+ /** Test-only: current in-memory byte accounting (proves evictions release their bytes). */
44
+ export function getStoredResponseBytesForTests(): number {
45
+ return storedResponseBytes;
46
+ }
47
+
48
+ /** The ONLY size computation: approximate entry weight from its items payload. */
49
+ function measuredEntry(entry: Omit<StoredResponseState, "sizeBytes">): StoredResponseState {
50
+ let sizeBytes = 0;
51
+ try {
52
+ sizeBytes = JSON.stringify(entry.items).length;
53
+ } catch {
54
+ /* unserializable items: weightless rather than fatal */
55
+ }
56
+ return { ...entry, sizeBytes };
57
+ }
58
+
59
+ /** The ONLY insertion point: keeps the byte counter consistent on replacement. */
60
+ function setEntry(id: string, entry: Omit<StoredResponseState, "sizeBytes">): void {
61
+ deleteEntry(id);
62
+ const measured = measuredEntry(entry);
63
+ storedResponseBytes += measured.sizeBytes ?? 0;
64
+ states.set(id, measured);
65
+ }
66
+
67
+ /** The ONLY deletion point: TTL, count, byte, and explicit deletes all route here. */
68
+ function deleteEntry(id: string): void {
69
+ const existing = states.get(id);
70
+ if (!existing) return;
71
+ storedResponseBytes -= existing.sizeBytes ?? 0;
72
+ if (storedResponseBytes < 0) storedResponseBytes = 0;
73
+ states.delete(id);
74
+ }
25
75
  // Expansion provenance must stay proxy-private: a WeakMap distinguishes replayed history from the
26
76
  // newly appended input suffix without adding an unknown field that native passthrough could send
27
77
  // upstream. The parser uses this boundary to acknowledge historical compaction markers exactly once.
@@ -69,7 +119,9 @@ function ensureLoaded(): void {
69
119
  },
70
120
  }
71
121
  : undefined);
72
- states.set(id, {
122
+ // Recompute sizes locally while loading — persisted sizeBytes (absent in v1/v2
123
+ // snapshots anyway) is never trusted.
124
+ setEntry(id, {
73
125
  createdAt: rec.createdAt,
74
126
  items: rec.items,
75
127
  ...(providers ? { providers } : {}),
@@ -92,11 +144,15 @@ function persistNow(path: string): void {
92
144
  let total = 0;
93
145
  // Newest-first so the most recent chains survive both caps.
94
146
  for (const entry of [...states].reverse()) {
95
- const size = JSON.stringify(entry).length;
147
+ // sizeBytes is in-memory accounting only; keep it out of the disk snapshot.
148
+ const [id, state] = entry;
149
+ const { sizeBytes: _sizeBytes, ...persistable } = state;
150
+ const persistEntry: [string, StoredResponseState] = [id, persistable];
151
+ const size = JSON.stringify(persistEntry).length;
96
152
  if (size > SNAPSHOT_ENTRY_MAX_BYTES) continue;
97
153
  if (total + size > SNAPSHOT_TOTAL_MAX_BYTES) break;
98
154
  total += size;
99
- entries.push(entry);
155
+ entries.push(persistEntry);
100
156
  }
101
157
  entries.reverse();
102
158
  mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
@@ -135,12 +191,18 @@ function inputItems(input: unknown): unknown[] {
135
191
 
136
192
  function pruneResponses(at = now()): void {
137
193
  for (const [id, state] of states) {
138
- if (at - state.createdAt > RESPONSE_TTL_MS) states.delete(id);
194
+ if (at - state.createdAt > RESPONSE_TTL_MS) deleteEntry(id);
139
195
  }
140
196
  while (states.size > MAX_STORED_RESPONSES) {
141
197
  const oldest = states.keys().next().value;
142
198
  if (!oldest) break;
143
- states.delete(oldest);
199
+ deleteEntry(oldest);
200
+ }
201
+ // Byte high-water eviction, oldest-first (Map preserves insertion order).
202
+ while (storedResponseBytes > byteCap() && states.size > 1) {
203
+ const oldest = states.keys().next().value;
204
+ if (!oldest) break;
205
+ deleteEntry(oldest);
144
206
  }
145
207
  }
146
208
 
@@ -204,7 +266,7 @@ export function rememberResponseState(
204
266
  return !!item && typeof item === "object" && (item as { type?: unknown }).type === "function_call";
205
267
  });
206
268
  }
207
- states.set(response.id, {
269
+ setEntry(response.id, {
208
270
  createdAt: now(),
209
271
  items: [...inputItems(request.input), ...response.output],
210
272
  // Always preserve the Cursor conversation id so the next tool-result turn can continue the SAME
@@ -225,6 +287,7 @@ export function clearResponseStateMemoryForTests(): void {
225
287
  persistTimer = null;
226
288
  }
227
289
  states.clear();
290
+ storedResponseBytes = 0;
228
291
  loaded = false;
229
292
  }
230
293
 
@@ -1,6 +1,7 @@
1
1
  import { timingSafeEqual } from "node:crypto";
2
2
  import { formatErrorResponse } from "../bridge";
3
3
  import {
4
+ booleanRecordConfigError,
4
5
  codexAutoStartEnabled,
5
6
  positiveIntegerConfigError,
6
7
  positiveIntegerRecordConfigError,
@@ -228,6 +229,8 @@ export function providerManagementConfigError(name: unknown, provider: unknown):
228
229
  if (headersError) return `provider ${name} ${headersError}`;
229
230
  const maxInputError = positiveIntegerRecordConfigError(raw.modelMaxInputTokens, "modelMaxInputTokens");
230
231
  if (maxInputError) return `provider ${name} ${maxInputError}`;
232
+ const reasoningSummariesError = booleanRecordConfigError(raw.modelSupportsReasoningSummaries, "modelSupportsReasoningSummaries");
233
+ if (reasoningSummariesError) return `provider ${name} ${reasoningSummariesError}`;
231
234
  const defaultMaxOutputError = positiveIntegerConfigError(raw.defaultMaxOutputTokens, "defaultMaxOutputTokens");
232
235
  if (defaultMaxOutputError) return `provider ${name} ${defaultMaxOutputError}`;
233
236
  const maxOutputError = positiveIntegerRecordConfigError(raw.modelMaxOutputTokens, "modelMaxOutputTokens");