@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.
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +4 -2
- package/README.ru.md +1 -1
- package/README.zh-CN.md +1 -1
- package/bin/ocx.mjs +52 -0
- package/gui/dist/assets/index-BpX-hoSd.css +1 -0
- package/gui/dist/assets/index-ZmFopEYw.js +52 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/cursor/cursor-errors.ts +38 -1
- package/src/adapters/cursor/discovery.ts +1 -0
- package/src/adapters/cursor/effort-map.ts +1 -0
- package/src/adapters/cursor/live-models.ts +22 -5
- package/src/adapters/cursor/live-transport.ts +82 -7
- package/src/adapters/cursor/transport.ts +2 -0
- package/src/adapters/cursor.ts +5 -2
- package/src/adapters/openai-responses.ts +64 -1
- package/src/cli/doctor.ts +10 -0
- package/src/cli/help.ts +10 -0
- package/src/cli/index.ts +88 -9
- package/src/cli/internal-dispatch.ts +20 -0
- package/src/cli/status.ts +15 -4
- package/src/cli/tray-proxy.ts +52 -0
- package/src/codex/auth-api.ts +46 -5
- package/src/codex/autostart-health.ts +149 -0
- package/src/codex/catalog/aggregation.ts +268 -0
- package/src/codex/catalog/bundled.ts +188 -0
- package/src/codex/catalog/effort.ts +263 -0
- package/src/codex/catalog/metadata.ts +176 -0
- package/src/codex/catalog/parsing.ts +399 -0
- package/src/codex/catalog/provider-fetch.ts +609 -0
- package/src/codex/catalog/sync.ts +540 -0
- package/src/codex/catalog.ts +11 -2426
- package/src/codex/inject.ts +165 -3
- package/src/codex/shim.ts +141 -8
- package/src/codex/sync.ts +17 -2
- package/src/config.ts +23 -0
- package/src/lib/errors.ts +11 -0
- package/src/providers/antigravity-models.ts +33 -0
- package/src/providers/kiro-models.ts +2 -0
- package/src/providers/registry.ts +2 -2
- package/src/responses/state.ts +69 -6
- package/src/server/auth-cors.ts +3 -0
- package/src/server/management/agent-settings-routes.ts +536 -0
- package/src/server/management/combo-routes.ts +210 -0
- package/src/server/management/config-routes.ts +302 -0
- package/src/server/management/context.ts +21 -0
- package/src/server/management/logs-usage-routes.ts +176 -0
- package/src/server/management/model-routes.ts +253 -0
- package/src/server/management/oauth-account-routes.ts +301 -0
- package/src/server/management/provider-routes.ts +408 -0
- package/src/server/management/shared.ts +186 -0
- package/src/server/management-api.ts +23 -1806
- package/src/server/responses/collaboration.ts +300 -0
- package/src/server/responses/compact.ts +342 -0
- package/src/server/responses/core.ts +1498 -0
- package/src/server/responses/encrypted-payload.ts +231 -0
- package/src/server/responses/fetch-helpers.ts +157 -0
- package/src/server/responses.ts +9 -2172
- package/src/server/startup-action-control.ts +41 -0
- package/src/server/startup-health-cache.ts +100 -0
- package/src/server/windows-tray-control.ts +41 -0
- package/src/service.ts +171 -19
- package/src/tray/assets/opencodex-tray-offline.ico +0 -0
- package/src/tray/assets/opencodex-tray-online.ico +0 -0
- package/src/tray/assets/opencodex-tray-warning.ico +0 -0
- package/src/tray/assets/opencodex-tray.png +0 -0
- package/src/tray/windows-tray.ps1 +290 -0
- package/src/tray/windows.ts +628 -0
- package/src/types.ts +5 -0
- package/src/update/index.ts +43 -0
- package/src/update/job.ts +46 -0
- package/src/update/tray-update-plan.d.mts +18 -0
- package/src/update/tray-update-plan.mjs +38 -0
- package/src/usage/cost.ts +0 -0
- package/src/usage/expected-prices.ts +9 -2
- package/src/usage/summary.ts +42 -7
- package/gui/dist/assets/index-BunUANVE.js +0 -52
- package/gui/dist/assets/index-Sg-7L_oZ.css +0 -1
package/src/responses/state.ts
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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(
|
|
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)
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
package/src/server/auth-cors.ts
CHANGED
|
@@ -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");
|