@bitkyc08/opencodex 2.8.0 → 2.9.0
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 +24 -0
- package/bin/ocx.mjs +32 -4
- package/gui/dist/assets/index-CHwf3tTD.css +1 -0
- package/gui/dist/assets/index-u5eFOv2y.js +67 -0
- package/gui/dist/index.html +2 -2
- package/package.json +1 -1
- package/src/adapters/anthropic-image-normalize.ts +114 -20
- package/src/adapters/anthropic.ts +126 -10
- package/src/adapters/azure.ts +3 -3
- package/src/adapters/base.ts +7 -3
- package/src/adapters/cursor/discovery.ts +14 -4
- package/src/adapters/cursor/effort-map.ts +18 -6
- package/src/adapters/cursor/framing.ts +102 -27
- package/src/adapters/cursor/kv-store.ts +30 -3
- package/src/adapters/cursor/live-models.ts +22 -2
- package/src/adapters/cursor/live-transport.ts +245 -49
- package/src/adapters/cursor/mcp-manager.ts +105 -8
- package/src/adapters/cursor/native-exec-mcp.ts +5 -3
- package/src/adapters/cursor/native-exec-shell.ts +296 -14
- package/src/adapters/cursor/native-exec.ts +381 -33
- package/src/adapters/cursor/protobuf-events.ts +28 -1
- package/src/adapters/cursor/protobuf-request.ts +71 -39
- package/src/adapters/cursor/request-builder.ts +2 -2
- package/src/adapters/cursor/transport.ts +2 -0
- package/src/adapters/cursor.ts +13 -2
- package/src/adapters/google-antigravity-replay.ts +184 -17
- package/src/adapters/google.ts +58 -8
- package/src/adapters/kiro-thinking.ts +23 -9
- package/src/adapters/kiro-tools.ts +49 -18
- package/src/adapters/kiro.ts +377 -133
- package/src/adapters/mimo-free.ts +36 -4
- package/src/adapters/openai-chat.ts +143 -17
- package/src/adapters/openai-responses.ts +130 -14
- package/src/adapters/run-turn-queue.ts +7 -1
- package/src/bridge.ts +466 -69
- package/src/chat/outbound.ts +144 -38
- package/src/claude/inbound-debug.ts +53 -8
- package/src/claude/outbound.ts +224 -38
- package/src/cli/agent-driven.ts +34 -1
- package/src/cli/catalog-prewarm.ts +5 -2
- package/src/cli/claude-desktop.ts +2 -2
- package/src/cli/doctor.ts +12 -0
- package/src/cli/export-command.ts +187 -0
- package/src/cli/help.ts +11 -0
- package/src/cli/index.ts +13 -3
- package/src/cli/init.ts +129 -102
- package/src/cli/opencode.ts +36 -151
- package/src/cli/star-prompt.ts +13 -4
- package/src/cli/status-oauth.ts +12 -2
- package/src/clients/config-export.ts +377 -0
- package/src/codex/account-runtime-state.ts +19 -1
- package/src/codex/account-store.ts +162 -82
- package/src/codex/auth-api.ts +467 -159
- package/src/codex/auth-context.ts +15 -2
- package/src/codex/catalog/aggregation.ts +15 -0
- package/src/codex/catalog/effort.ts +16 -6
- package/src/codex/catalog/metadata.ts +6 -0
- package/src/codex/catalog/parsing.ts +3 -1
- package/src/codex/catalog/provider-fetch.ts +29 -0
- package/src/codex/catalog/sync.ts +64 -7
- package/src/codex/catalog.ts +2 -2
- package/src/codex/inject.ts +5 -5
- package/src/codex/main-account-cache.ts +8 -1
- package/src/codex/model-cache.ts +81 -2
- package/src/codex/pool-rotation.ts +39 -0
- package/src/codex/project-config-warnings.ts +12 -1
- package/src/codex/quota.ts +35 -3
- package/src/codex/routing.ts +46 -1
- package/src/codex/shim.ts +10 -4
- package/src/codex/subagent-model-fallback.ts +12 -0
- package/src/codex/websocket-registry.ts +27 -0
- package/src/combos/failover.ts +31 -1
- package/src/combos/request.ts +9 -0
- package/src/combos/resolve.ts +60 -4
- package/src/combos/types.ts +12 -0
- package/src/config.ts +510 -55
- package/src/github/star-state.ts +13 -1
- package/src/images/fulfill.ts +39 -1
- package/src/images/loop.ts +52 -12
- package/src/lib/admission.ts +83 -0
- package/src/lib/app-owned-memory-stores.ts +173 -0
- package/src/lib/app-owned-memory.ts +265 -0
- package/src/lib/bun-stream-caps.ts +31 -7
- package/src/lib/config-ownership.ts +33 -0
- package/src/lib/crash-guard.ts +65 -5
- package/src/lib/debug-log-buffer.ts +47 -6
- package/src/lib/destination-policy.ts +12 -1
- package/src/lib/errors.ts +3 -0
- package/src/lib/gcp-adc.ts +40 -2
- package/src/lib/injection-debug-log.ts +26 -2
- package/src/lib/provider-outbound.ts +3 -0
- package/src/lib/sidecar-tracker.ts +5 -2
- package/src/lib/sse-decoder.ts +257 -37
- package/src/lib/state-store-registrations.ts +109 -0
- package/src/lib/state-store-sweeper.ts +184 -0
- package/src/lib/translator-budget.ts +356 -0
- package/src/lib/windows-secret-acl.ts +33 -12
- package/src/lib/winsw.ts +14 -1
- package/src/oauth/anthropic-routing.ts +31 -7
- package/src/oauth/google-antigravity.ts +2 -1
- package/src/oauth/health.ts +30 -12
- package/src/oauth/index.ts +127 -23
- package/src/oauth/kiro-credentials.ts +72 -1
- package/src/oauth/kiro.ts +23 -4
- package/src/oauth/store.ts +165 -18
- package/src/oauth/token-guardian.ts +43 -4
- package/src/oauth/types.ts +2 -1
- package/src/providers/base-url-choices.ts +10 -0
- package/src/providers/derive.ts +12 -0
- package/src/providers/free-directory.ts +4 -1
- package/src/providers/key-failover.ts +12 -0
- package/src/providers/openai-sidecar.ts +4 -1
- package/src/providers/quota.ts +68 -7
- package/src/providers/registry.ts +279 -3
- package/src/responses/parser.ts +5 -1
- package/src/responses/spill-store.ts +394 -0
- package/src/responses/state.ts +520 -102
- package/src/router.ts +18 -1
- package/src/server/adapter-resolve.ts +20 -3
- package/src/server/auth-cors.ts +121 -28
- package/src/server/chat-completions.ts +57 -12
- package/src/server/claude-messages.ts +85 -13
- package/src/server/index.ts +242 -100
- package/src/server/lifecycle.ts +155 -25
- package/src/server/management/agent-settings-routes.ts +79 -36
- package/src/server/management/api-key-usage.ts +167 -0
- package/src/server/management/body.ts +35 -0
- package/src/server/management/combo-routes.ts +5 -1
- package/src/server/management/config-routes.ts +42 -12
- package/src/server/management/logs-usage-routes.ts +41 -21
- package/src/server/management/model-routes.ts +188 -54
- package/src/server/management/oauth-account-routes.ts +115 -26
- package/src/server/management/provider-routes.ts +56 -6
- package/src/server/management/shared.ts +16 -3
- package/src/server/management/sidebar-routes.ts +50 -1
- package/src/server/management/system-restart.ts +13 -6
- package/src/server/management/system-routes.ts +15 -3
- package/src/server/management/usage-summary-cache.ts +86 -0
- package/src/server/management-api.ts +39 -5
- package/src/server/management-auth.ts +65 -14
- package/src/server/port-reclaim.ts +58 -12
- package/src/server/ports.ts +2 -0
- package/src/server/proxy-liveness.ts +60 -14
- package/src/server/relay-eager.ts +20 -4
- package/src/server/relay.ts +548 -154
- package/src/server/request-decompress.ts +51 -4
- package/src/server/request-log.ts +134 -15
- package/src/server/responses/collaboration.ts +15 -4
- package/src/server/responses/compact.ts +3 -0
- package/src/server/responses/core.ts +241 -66
- package/src/server/responses-image-gen-repair.ts +19 -5
- package/src/server/responses-item-id-repair.ts +23 -5
- package/src/server/sse-payload-rewrite.ts +71 -12
- package/src/server/startup-health-cache.ts +14 -1
- package/src/server/system-env.ts +8 -1
- package/src/server/windows-tcp-drop.ts +15 -5
- package/src/server/ws-bridge.ts +25 -0
- package/src/service.ts +179 -13
- package/src/storage/policy-job.ts +93 -23
- package/src/storage/policy-worker.ts +6 -0
- package/src/storage/restore-job.ts +62 -16
- package/src/storage/restore-worker.ts +6 -0
- package/src/storage/storage-mutation-coordinator.ts +36 -6
- package/src/storage/worker-lifecycle.ts +181 -47
- package/src/tray/windows.ts +97 -25
- package/src/types.ts +39 -6
- package/src/update/index.ts +24 -5
- package/src/update/job.ts +598 -73
- package/src/usage/log.ts +115 -17
- package/src/usage/summary.ts +67 -2
- package/src/vision/index.ts +112 -22
- package/src/web-search/loop.ts +38 -6
- package/src/web-search/progress-stream.ts +14 -3
- package/gui/dist/assets/index-BDjpkcRN.js +0 -67
- package/gui/dist/assets/index-BHsKRFh9.css +0 -1
|
@@ -26,6 +26,18 @@ export interface DecodedConnectFrames {
|
|
|
26
26
|
remainder: Uint8Array;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
+
interface CopyReservation {
|
|
30
|
+
commitRetained(): void;
|
|
31
|
+
release(): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface InspectedConnectFrame {
|
|
35
|
+
flags: number;
|
|
36
|
+
length: number;
|
|
37
|
+
payloadStart: number;
|
|
38
|
+
readBytes: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
29
41
|
export class ConnectFrameError extends Error {
|
|
30
42
|
constructor(
|
|
31
43
|
public readonly code: ConnectFrameErrorCode,
|
|
@@ -65,27 +77,33 @@ export function encodeConnectFrame(
|
|
|
65
77
|
return frame;
|
|
66
78
|
}
|
|
67
79
|
|
|
68
|
-
export function tryDecodeConnectFrame(
|
|
80
|
+
export function tryDecodeConnectFrame(
|
|
81
|
+
input: Uint8Array,
|
|
82
|
+
offset = 0,
|
|
83
|
+
maxPayloadBytes = MAX_CONNECT_FRAME_PAYLOAD_BYTES,
|
|
84
|
+
reservePayloadCopy?: (bytes: number) => CopyReservation | undefined,
|
|
85
|
+
): DecodedConnectFrame | null {
|
|
69
86
|
assertOffset(input, offset);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
const inspected = inspectConnectFrame(input, offset, maxPayloadBytes);
|
|
88
|
+
if (!inspected) return null;
|
|
89
|
+
const payloadEnd = inspected.payloadStart + inspected.length;
|
|
90
|
+
const reservation = reservePayloadCopy?.(inspected.length);
|
|
91
|
+
let payload: Uint8Array;
|
|
92
|
+
try {
|
|
93
|
+
payload = input.slice(inspected.payloadStart, payloadEnd);
|
|
94
|
+
reservation?.commitRetained();
|
|
95
|
+
} catch (error) {
|
|
96
|
+
reservation?.release();
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
81
99
|
return {
|
|
82
100
|
frame: {
|
|
83
|
-
flags,
|
|
101
|
+
flags: inspected.flags,
|
|
84
102
|
payload,
|
|
85
|
-
compressed: isConnectFrameCompressed(flags),
|
|
86
|
-
endStream: isConnectFrameEndStream(flags),
|
|
103
|
+
compressed: isConnectFrameCompressed(inspected.flags),
|
|
104
|
+
endStream: isConnectFrameEndStream(inspected.flags),
|
|
87
105
|
},
|
|
88
|
-
readBytes,
|
|
106
|
+
readBytes: inspected.readBytes,
|
|
89
107
|
};
|
|
90
108
|
}
|
|
91
109
|
|
|
@@ -108,19 +126,76 @@ export function decodeConnectFrames(input: Uint8Array): ConnectFrame[] {
|
|
|
108
126
|
return frames;
|
|
109
127
|
}
|
|
110
128
|
|
|
111
|
-
export function decodeAvailableConnectFrames(
|
|
112
|
-
|
|
129
|
+
export function decodeAvailableConnectFrames(
|
|
130
|
+
input: Uint8Array,
|
|
131
|
+
maxPayloadBytes = MAX_CONNECT_FRAME_PAYLOAD_BYTES,
|
|
132
|
+
availableFrameSlots = Number.POSITIVE_INFINITY,
|
|
133
|
+
reservePayloadCopy?: (bytes: number) => CopyReservation | undefined,
|
|
134
|
+
): DecodedConnectFrames {
|
|
135
|
+
const planned: Array<InspectedConnectFrame & { reservation?: CopyReservation }> = [];
|
|
113
136
|
let offset = 0;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
137
|
+
let remainderReservation: CopyReservation | undefined;
|
|
138
|
+
try {
|
|
139
|
+
while (offset < input.length && planned.length < availableFrameSlots) {
|
|
140
|
+
const inspected = inspectConnectFrame(input, offset, maxPayloadBytes);
|
|
141
|
+
if (!inspected) break;
|
|
142
|
+
const reservation = reservePayloadCopy?.(inspected.length);
|
|
143
|
+
planned.push({ ...inspected, reservation });
|
|
144
|
+
offset += inspected.readBytes;
|
|
145
|
+
}
|
|
146
|
+
const remainderBytes = offset === input.length ? 0 : bufferedPayloadBytes(input, offset);
|
|
147
|
+
remainderReservation = reservePayloadCopy?.(remainderBytes);
|
|
148
|
+
|
|
149
|
+
// Keep every reservation transient until every batch allocation succeeds. A later admission
|
|
150
|
+
// failure can then roll the entire batch back without needing ownership of unreturned frames.
|
|
151
|
+
const frames = planned.map(({ flags, length, payloadStart }) => {
|
|
152
|
+
const payload = input.slice(payloadStart, payloadStart + length);
|
|
153
|
+
return {
|
|
154
|
+
flags,
|
|
155
|
+
payload,
|
|
156
|
+
compressed: isConnectFrameCompressed(flags),
|
|
157
|
+
endStream: isConnectFrameEndStream(flags),
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
const remainder = offset === input.length ? new Uint8Array() : input.slice(offset);
|
|
161
|
+
for (const entry of planned) entry.reservation?.commitRetained();
|
|
162
|
+
remainderReservation?.commitRetained();
|
|
163
|
+
return { frames, remainder };
|
|
164
|
+
} catch (error) {
|
|
165
|
+
for (const entry of planned) entry.reservation?.release();
|
|
166
|
+
remainderReservation?.release();
|
|
167
|
+
throw error;
|
|
119
168
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function inspectConnectFrame(
|
|
172
|
+
input: Uint8Array,
|
|
173
|
+
offset: number,
|
|
174
|
+
maxPayloadBytes: number,
|
|
175
|
+
): InspectedConnectFrame | null {
|
|
176
|
+
if (input.length - offset < CONNECT_FRAME_HEADER_BYTES) return null;
|
|
177
|
+
const view = new DataView(input.buffer, input.byteOffset + offset, input.byteLength - offset);
|
|
178
|
+
const flags = view.getUint8(0);
|
|
179
|
+
const length = view.getUint32(1, false);
|
|
180
|
+
if (length > maxPayloadBytes) {
|
|
181
|
+
throw new ConnectFrameError("payload_too_large", `Connect frame payload too large: ${length}`);
|
|
182
|
+
}
|
|
183
|
+
const readBytes = CONNECT_FRAME_HEADER_BYTES + length;
|
|
184
|
+
if (input.length - offset < readBytes) return null;
|
|
185
|
+
return { flags, length, payloadStart: offset + CONNECT_FRAME_HEADER_BYTES, readBytes };
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function bufferedPayloadBytes(input: Uint8Array, start: number): number {
|
|
189
|
+
let offset = start;
|
|
190
|
+
let payloadBytes = 0;
|
|
191
|
+
while (input.byteLength - offset >= CONNECT_FRAME_HEADER_BYTES) {
|
|
192
|
+
const length = new DataView(input.buffer, input.byteOffset + offset, input.byteLength - offset).getUint32(1, false);
|
|
193
|
+
const available = Math.min(length, input.byteLength - offset - CONNECT_FRAME_HEADER_BYTES);
|
|
194
|
+
payloadBytes += available;
|
|
195
|
+
if (available < length) break;
|
|
196
|
+
offset += CONNECT_FRAME_HEADER_BYTES + length;
|
|
197
|
+
}
|
|
198
|
+
return payloadBytes;
|
|
124
199
|
}
|
|
125
200
|
|
|
126
201
|
function assertOffset(input: Uint8Array, offset: number): void {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { TranslatorBudget } from "../../lib/translator-budget";
|
|
2
|
+
|
|
1
3
|
export interface CursorKvStore {
|
|
2
4
|
get(key: string): Uint8Array | undefined;
|
|
3
5
|
set(key: string, value: Uint8Array): void;
|
|
@@ -7,19 +9,44 @@ function cloneBytes(value: Uint8Array): Uint8Array {
|
|
|
7
9
|
return new Uint8Array(value);
|
|
8
10
|
}
|
|
9
11
|
|
|
10
|
-
export function createCursorKvStore(
|
|
12
|
+
export function createCursorKvStore(
|
|
13
|
+
seed: Record<string, Uint8Array>,
|
|
14
|
+
budget: TranslatorBudget,
|
|
15
|
+
): CursorKvStore {
|
|
11
16
|
const values = new Map<string, Uint8Array>();
|
|
17
|
+
const encoder = new TextEncoder();
|
|
18
|
+
const sizes = new Map<string, number>();
|
|
12
19
|
for (const [key, value] of Object.entries(seed)) {
|
|
20
|
+
const bytes = encoder.encode(key).byteLength + value.byteLength;
|
|
21
|
+
budget.chargeRetained(bytes, { kind: "cursor_kv" });
|
|
13
22
|
values.set(key, cloneBytes(value));
|
|
23
|
+
sizes.set(key, bytes);
|
|
14
24
|
}
|
|
15
25
|
|
|
16
26
|
return {
|
|
17
27
|
get(key) {
|
|
18
28
|
const value = values.get(key);
|
|
19
|
-
|
|
29
|
+
if (!value) return undefined;
|
|
30
|
+
budget.chargeRetained(value.byteLength, { kind: "cursor_kv" });
|
|
31
|
+
const cloned = cloneBytes(value);
|
|
32
|
+
queueMicrotask(() => budget.releaseRetained(value.byteLength, { kind: "cursor_kv" }));
|
|
33
|
+
return cloned;
|
|
20
34
|
},
|
|
21
35
|
set(key, value) {
|
|
22
|
-
|
|
36
|
+
const nextBytes = encoder.encode(key).byteLength + value.byteLength;
|
|
37
|
+
const previousBytes = sizes.get(key) ?? 0;
|
|
38
|
+
const reservation = budget.reserveTransient(nextBytes, { kind: "cursor_kv" });
|
|
39
|
+
let cloned: Uint8Array;
|
|
40
|
+
try {
|
|
41
|
+
cloned = cloneBytes(value);
|
|
42
|
+
} catch (error) {
|
|
43
|
+
reservation.release();
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
values.set(key, cloned);
|
|
47
|
+
sizes.set(key, nextBytes);
|
|
48
|
+
reservation.commitRetained();
|
|
49
|
+
budget.releaseRetained(previousBytes, { kind: "cursor_kv" });
|
|
23
50
|
},
|
|
24
51
|
};
|
|
25
52
|
}
|
|
@@ -18,6 +18,7 @@ import { GetUsableModelsResponseSchema } from "./gen/agent_pb";
|
|
|
18
18
|
|
|
19
19
|
const CURSOR_GET_USABLE_MODELS_PATH = "/agent.v1.AgentService/GetUsableModels";
|
|
20
20
|
const CURSOR_DISCOVERY_CLIENT_VERSION = "cli-2026.02.13-41ac335";
|
|
21
|
+
const CURSOR_MODEL_DISCOVERY_MAX_BYTES = 4 * 1024 * 1024;
|
|
21
22
|
|
|
22
23
|
export interface CursorUsableModelsOptions {
|
|
23
24
|
apiKey: string;
|
|
@@ -28,7 +29,7 @@ export interface CursorUsableModelsOptions {
|
|
|
28
29
|
|
|
29
30
|
export type CursorUsableModelsResult =
|
|
30
31
|
| { ok: true; models: string[] }
|
|
31
|
-
| { ok: false; error: "auth" | "http" | "transport" | "timeout" | "decode" | "empty"; detail?: string };
|
|
32
|
+
| { ok: false; error: "auth" | "http" | "transport" | "timeout" | "decode" | "empty" | "too_large"; detail?: string };
|
|
32
33
|
|
|
33
34
|
const RETRYABLE_DISCOVERY_ERRORS = new Set(["timeout", "transport"]);
|
|
34
35
|
const DISCOVERY_RETRY_TIMEOUT_MS = 3_000;
|
|
@@ -97,12 +98,31 @@ async function fetchCursorUsableModelsOnce(opts: CursorUsableModelsOptions): Pro
|
|
|
97
98
|
|
|
98
99
|
let status = 0;
|
|
99
100
|
const chunks: Buffer[] = [];
|
|
101
|
+
let receivedBytes = 0;
|
|
102
|
+
let bodyRejected = false;
|
|
100
103
|
req.on("response", headers => {
|
|
101
104
|
status = Number(headers[":status"] ?? 0);
|
|
105
|
+
const contentLength = Number(headers["content-length"] ?? 0);
|
|
106
|
+
if (Number.isFinite(contentLength) && contentLength > CURSOR_MODEL_DISCOVERY_MAX_BYTES) {
|
|
107
|
+
bodyRejected = true;
|
|
108
|
+
req.close(http2.constants.NGHTTP2_CANCEL);
|
|
109
|
+
close({ ok: false, error: "too_large", detail: "GetUsableModels response exceeds 4 MiB" });
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
req.on("data", (chunk: Buffer) => {
|
|
113
|
+
if (bodyRejected) return;
|
|
114
|
+
receivedBytes += chunk.byteLength;
|
|
115
|
+
if (receivedBytes > CURSOR_MODEL_DISCOVERY_MAX_BYTES) {
|
|
116
|
+
bodyRejected = true;
|
|
117
|
+
req.close(http2.constants.NGHTTP2_CANCEL);
|
|
118
|
+
close({ ok: false, error: "too_large", detail: "GetUsableModels response exceeds 4 MiB" });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
chunks.push(chunk);
|
|
102
122
|
});
|
|
103
|
-
req.on("data", (chunk: Buffer) => chunks.push(chunk));
|
|
104
123
|
req.on("error", () => close({ ok: false, error: "transport", detail: "HTTP/2 request failed" }));
|
|
105
124
|
req.on("end", () => {
|
|
125
|
+
if (bodyRejected) return;
|
|
106
126
|
if (status === 401 || status === 403) {
|
|
107
127
|
return close({ ok: false, error: "auth", detail: `HTTP ${status}` });
|
|
108
128
|
}
|