@bitkyc08/opencodex 2.52.0-preview.20260911 → 2.52.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/gui/dist/assets/index-CWXut3rG.js +115 -0
- package/gui/dist/assets/index-EdoPnm9_.css +1 -0
- package/gui/dist/index.html +2 -2
- package/gui/dist/provider-icons/devin.svg +49 -0
- package/gui/dist/provider-icons/omo.svg +42 -0
- package/package.json +3 -1
- package/src/AGENTS.md +1 -1
- package/src/adapters/cline-pass-deepseek-v4-tool-replay.ts +0 -1
- package/src/adapters/command-code.ts +0 -1
- package/src/adapters/cursor/checkpoint-store.ts +37 -0
- package/src/adapters/cursor/live-transport.ts +74 -2
- package/src/adapters/cursor.ts +6 -0
- package/src/adapters/devin/cloud-direct/auth.ts +264 -0
- package/src/adapters/devin/cloud-direct/catalog.ts +306 -0
- package/src/adapters/devin/cloud-direct/chat.ts +1274 -0
- package/src/adapters/devin/cloud-direct/index.ts +65 -0
- package/src/adapters/devin/cloud-direct/metadata.ts +134 -0
- package/src/adapters/devin/cloud-direct/wire.ts +206 -0
- package/src/adapters/devin/live-models.ts +133 -0
- package/src/adapters/devin-cli/acp.ts +204 -0
- package/src/adapters/devin-cli/adapter.ts +345 -0
- package/src/adapters/devin-cli/binary.ts +69 -0
- package/src/adapters/devin-cli/models.ts +57 -0
- package/src/adapters/devin.ts +326 -0
- package/src/adapters/google.ts +1 -1
- package/src/adapters/openai-chat.ts +31 -10
- package/src/adapters/openai-responses.ts +16 -1
- package/src/adapters/registry.ts +25 -1
- package/src/bridge.ts +8 -2
- package/src/claude/inbound-cache-stabilize.ts +130 -0
- package/src/claude/inbound.ts +45 -5
- package/src/cli/account-auth.ts +60 -1
- package/src/cli/account-extended.ts +23 -30
- package/src/cli/account.ts +2 -1
- package/src/cli/capabilities.ts +50 -8
- package/src/cli/config-command.ts +2 -2
- package/src/cli/dispatch.ts +14 -2
- package/src/cli/export-command.ts +11 -25
- package/src/cli/help.ts +2 -2
- package/src/cli/opencode.ts +5 -0
- package/src/cli/registry.ts +15 -4
- package/src/clients/config-export/cline.ts +71 -0
- package/src/clients/config-export/contracts.ts +10 -1
- package/src/clients/config-export/model-metadata.ts +33 -0
- package/src/clients/config-export/zcode.ts +23 -12
- package/src/clients/config-export.ts +156 -4
- package/src/codex/account-store.ts +7 -2
- package/src/codex/auth-context.ts +1 -1
- package/src/codex/catalog/effort.ts +4 -3
- package/src/codex/catalog/metadata.ts +8 -4
- package/src/codex/catalog/native-models.ts +24 -4
- package/src/codex/catalog/parsing.ts +19 -1
- package/src/codex/catalog/provider-fetch.ts +57 -0
- package/src/codex/catalog/sync.ts +1 -1
- package/src/codex/context-compat.ts +97 -0
- package/src/codex/context-owner.ts +201 -0
- package/src/codex/history-provider.ts +161 -14
- package/src/codex/inject-coordination.ts +3 -2
- package/src/codex/inject.ts +128 -9
- package/src/codex/pool-rotation.ts +8 -292
- package/src/codex/quota.ts +41 -12
- package/src/codex/retired-model-migration.ts +41 -0
- package/src/codex/routing.ts +327 -22
- package/src/codex/warmup.ts +2 -2
- package/src/combos/failover.ts +5 -0
- package/src/combos/resolve.ts +11 -15
- package/src/config.ts +46 -14
- package/src/generated/compatibility-version.json +293 -113
- package/src/grok/grpc-web.ts +120 -0
- package/src/grok/reset-coupon-ledger.ts +139 -0
- package/src/grok/reset-coupons.ts +278 -0
- package/src/integrations/catalog-refresh.ts +1 -1
- package/src/integrations/cline-document.ts +73 -0
- package/src/integrations/cline-io.ts +149 -0
- package/src/integrations/cline-transaction.ts +42 -0
- package/src/integrations/config-io.ts +21 -2
- package/src/integrations/journal.ts +43 -1
- package/src/integrations/omp-yaml-source.ts +123 -4
- package/src/integrations/ownership-policy.ts +7 -0
- package/src/integrations/ownership.ts +36 -0
- package/src/integrations/registry.ts +27 -0
- package/src/integrations/state.ts +5 -2
- package/src/integrations/store.ts +6 -0
- package/src/integrations/writer.ts +53 -9
- package/src/lab/subject/behavior-fingerprint.ts +1 -1
- package/src/lib/abort.ts +36 -0
- package/src/lib/local-destinations.ts +1 -1
- package/src/lib/upstream-retry.ts +36 -1
- package/src/oauth/account-quota-rank.ts +11 -0
- package/src/oauth/callback-server.ts +10 -5
- package/src/oauth/devin/api-base.ts +63 -0
- package/src/oauth/devin/login.ts +1 -0
- package/src/oauth/devin/register-user.ts +186 -0
- package/src/oauth/devin/types.ts +71 -0
- package/src/oauth/devin-cli.ts +149 -0
- package/src/oauth/devin.ts +170 -0
- package/src/oauth/generic-account-failover.ts +169 -1
- package/src/oauth/index.ts +20 -1
- package/src/oauth/login-cli.ts +19 -5
- package/src/oauth/pool-kernel.ts +321 -0
- package/src/oauth/pool-settings-capability.ts +127 -9
- package/src/oauth/store.ts +7 -3
- package/src/oauth/token-guardian.ts +1 -1
- package/src/providers/codebuddy-models.ts +0 -3
- package/src/providers/command-code-efforts.ts +23 -4
- package/src/providers/default-aliases.ts +4 -0
- package/src/providers/derive.ts +8 -0
- package/src/providers/devin-cli-authmode-migration.ts +57 -0
- package/src/providers/key-failover.ts +175 -0
- package/src/providers/model-rename-startup.ts +21 -1
- package/src/providers/qoder-models.ts +0 -1
- package/src/providers/quota-key-accounts.ts +50 -0
- package/src/providers/quota-routing-cache.ts +65 -6
- package/src/providers/quota-types.ts +7 -0
- package/src/providers/quota.ts +113 -30
- package/src/providers/registry.ts +237 -77
- package/src/providers/stale-context-window-migration.ts +92 -0
- package/src/providers/zai-responses-migration.ts +45 -0
- package/src/quota/reset-observer.ts +2 -1
- package/src/quota/reset-seen-store.ts +9 -1
- package/src/remote-control/crypto.ts +442 -0
- package/src/remote-control/host.ts +175 -0
- package/src/remote-control/index.ts +100 -0
- package/src/remote-control/protocol.ts +200 -0
- package/src/remote-control/relay.ts +162 -0
- package/src/remote-control/workspace-agent-protocol.ts +246 -0
- package/src/remote-control/workspace-rpc-framing.ts +128 -0
- package/src/remote-control/workspace-tools.ts +237 -0
- package/src/remote-control/workspace-utf8.ts +24 -0
- package/src/responses/custom-tool-compat.ts +23 -0
- package/src/router.ts +6 -1
- package/src/routing/compatibility/behavior.ts +3 -0
- package/src/server/adapter-resolve.ts +6 -2
- package/src/server/auth-cors.ts +71 -6
- package/src/server/chat-completions.ts +5 -3
- package/src/server/chat-native.ts +9 -0
- package/src/server/claude-messages.ts +25 -30
- package/src/server/context-history.ts +207 -0
- package/src/server/images.ts +28 -1
- package/src/server/index.ts +42 -22
- package/src/server/live.ts +2 -1
- package/src/server/management/agent-settings-routes.ts +7 -1
- package/src/server/management/config-routes.ts +3 -3
- package/src/server/management/grok-coupon-routes.ts +287 -0
- package/src/server/management/integration-routes.ts +6 -1
- package/src/server/management/oauth-account-routes.ts +124 -7
- package/src/server/management/provider-routes.ts +77 -2
- package/src/server/management/route-registry.ts +6 -1
- package/src/server/management-api.ts +7 -0
- package/src/server/request-log.ts +4 -0
- package/src/server/responses/codex-ws-exchange.ts +90 -14
- package/src/server/responses/codex-ws-wire.ts +51 -1
- package/src/server/responses/compact.ts +8 -1
- package/src/server/responses/core.ts +188 -22
- package/src/server/responses/ws-upstream.ts +1 -1
- package/src/server/responses-undeclared-tool-guard.ts +261 -12
- package/src/server/zai-responses-startup.ts +21 -0
- package/src/types/config.ts +33 -3
- package/src/types/provider.ts +54 -4
- package/src/types/request.ts +1 -1
- package/src/types/tools.ts +36 -6
- package/src/update/job.ts +33 -11
- package/src/vision/plan.ts +40 -37
- package/src/web-search/index.ts +1 -0
- package/gui/dist/assets/index-BoBRSehJ.css +0 -1
- package/gui/dist/assets/index-Dx0xv2EA.js +0 -115
package/src/update/job.ts
CHANGED
|
@@ -983,6 +983,11 @@ export interface RestartIo {
|
|
|
983
983
|
spawnStart?: (job: UpdateJobState, installer: Installer, port?: number, launcher?: string) => void;
|
|
984
984
|
/** The package launcher verified after a pnpm group switch or rollback. */
|
|
985
985
|
packageLauncherPathFn?: () => string;
|
|
986
|
+
/** Exercise pinned-start retries without spawning, reclaiming, or killing real processes. */
|
|
987
|
+
spawnDetachedStartFn?: typeof spawnDetachedStart;
|
|
988
|
+
preparePortForPinnedStartFn?: typeof preparePortForPinnedStart;
|
|
989
|
+
waitForGhostListenClearFn?: typeof waitForGhostListenClear;
|
|
990
|
+
killProxyFn?: typeof killProxy;
|
|
986
991
|
serviceInstalledFn?: () => boolean;
|
|
987
992
|
/**
|
|
988
993
|
* After a service reinstall exits 0, only trust the service path when this is true.
|
|
@@ -1332,9 +1337,20 @@ async function restartAfterUpdate(
|
|
|
1332
1337
|
}
|
|
1333
1338
|
}
|
|
1334
1339
|
const attempts = 3;
|
|
1340
|
+
const now = io.now ?? (() => Date.now());
|
|
1341
|
+
const spawnPinnedStart = io.spawnDetachedStartFn ?? spawnDetachedStart;
|
|
1342
|
+
const preparePort = io.preparePortForPinnedStartFn ?? preparePortForPinnedStart;
|
|
1343
|
+
const waitForGhost = io.waitForGhostListenClearFn ?? waitForGhostListenClear;
|
|
1335
1344
|
// Longer than published hard-pin reclaim (30s) so a slow start can still report healthy.
|
|
1336
1345
|
const perAttemptHealthMs = 70_000;
|
|
1337
1346
|
let lastChild: ChildProcess | null = null;
|
|
1347
|
+
const killSpawnAttempt = (child: ChildProcess | null): void => {
|
|
1348
|
+
// A numeric PID can be reused once this particular child has exited.
|
|
1349
|
+
if (!child?.pid || child.exitCode !== null || child.signalCode !== null) return;
|
|
1350
|
+
if (aliveFn(child.pid)) {
|
|
1351
|
+
try { (io.killProxyFn ?? killProxy)(child.pid); } catch { /* best-effort */ }
|
|
1352
|
+
}
|
|
1353
|
+
};
|
|
1338
1354
|
for (let attempt = 1; attempt <= attempts; attempt++) {
|
|
1339
1355
|
if (attempt > 1) {
|
|
1340
1356
|
updateJob(
|
|
@@ -1343,13 +1359,11 @@ async function restartAfterUpdate(
|
|
|
1343
1359
|
`Pinned start attempt ${attempt - 1} did not become healthy on port ${port}; `
|
|
1344
1360
|
+ `retrying (${attempt}/${attempts}).`,
|
|
1345
1361
|
);
|
|
1346
|
-
|
|
1347
|
-
try { killProxy(lastChild.pid); } catch { /* best-effort */ }
|
|
1348
|
-
}
|
|
1362
|
+
killSpawnAttempt(lastChild);
|
|
1349
1363
|
lastChild = null;
|
|
1350
1364
|
}
|
|
1351
|
-
|
|
1352
|
-
const ready = await
|
|
1365
|
+
preparePort(job, port, listPids, aliveFn, verifyOcx);
|
|
1366
|
+
const ready = await waitForGhost(
|
|
1353
1367
|
port,
|
|
1354
1368
|
hostname,
|
|
1355
1369
|
listPids,
|
|
@@ -1365,17 +1379,25 @@ async function restartAfterUpdate(
|
|
|
1365
1379
|
);
|
|
1366
1380
|
continue;
|
|
1367
1381
|
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1382
|
+
const child = spawnPinnedStart(job, job.installer, port, launcher);
|
|
1383
|
+
lastChild = child;
|
|
1384
|
+
const retireChild = () => {
|
|
1385
|
+
if (lastChild === child) lastChild = null;
|
|
1386
|
+
child.removeListener("exit", retireChild);
|
|
1387
|
+
child.removeListener("error", retireChild);
|
|
1388
|
+
child.removeListener("close", retireChild);
|
|
1389
|
+
};
|
|
1390
|
+
child.once("exit", retireChild);
|
|
1391
|
+
child.once("error", retireChild);
|
|
1392
|
+
child.once("close", retireChild);
|
|
1393
|
+
const healthDeadline = now() + perAttemptHealthMs;
|
|
1394
|
+
while (now() < healthDeadline) {
|
|
1371
1395
|
if (await probe(port, hostname)) return;
|
|
1372
1396
|
await sleep(500);
|
|
1373
1397
|
}
|
|
1374
1398
|
}
|
|
1375
1399
|
// Exhausted retries: do not leave a hung pinned-start child owning the port.
|
|
1376
|
-
|
|
1377
|
-
try { killProxy(lastChild.pid); } catch { /* best-effort */ }
|
|
1378
|
-
}
|
|
1400
|
+
killSpawnAttempt(lastChild);
|
|
1379
1401
|
}
|
|
1380
1402
|
|
|
1381
1403
|
/** Compact listen-holder summary for update-job logs when reclaim fails. */
|
package/src/vision/plan.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { resolveSidecarAuth } from "../sidecar/auth";
|
|
|
11
11
|
import { DEFAULT_VISION_TIMEOUT_MS, MAX_VISION_TIMEOUT_MS, MIN_VISION_TIMEOUT_MS } from "./timeout-bounds";
|
|
12
12
|
import { carriesImages } from "./image-rewrite";
|
|
13
13
|
|
|
14
|
-
const DEFAULT_VISION_MODEL = "gpt-5.
|
|
14
|
+
const DEFAULT_VISION_MODEL = "gpt-5.6-luna";
|
|
15
15
|
const DEFAULT_ANTHROPIC_VISION_MODEL = "claude-sonnet-5";
|
|
16
16
|
const DEFAULT_REASONING: VisionReasoningEffort = "low";
|
|
17
17
|
export const DEFAULT_MAX_DESCRIPTIONS_PER_TURN = 8;
|
|
@@ -92,6 +92,20 @@ function messagesHaveImage(parsed: OcxParsedRequest): boolean {
|
|
|
92
92
|
carriesImages(m.role) && Array.isArray(m.content) && (m.content as OcxContentPart[]).some(p => p.type === "image"));
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/** Shared by auth admission and planning so a routed describer never borrows OpenAI auth. */
|
|
96
|
+
function usableRoutedVisionModel(config: OcxConfig): string | undefined {
|
|
97
|
+
const cfg = config.visionSidecar;
|
|
98
|
+
if (cfg?.backend !== "routed") return undefined;
|
|
99
|
+
const routedModel = cfg.model;
|
|
100
|
+
const sep = routedModel ? routedModel.indexOf("/") : -1;
|
|
101
|
+
if (!routedModel || sep <= 0) return undefined;
|
|
102
|
+
const targetProvider = routedModel.slice(0, sep);
|
|
103
|
+
const targetId = routedModel.slice(sep + 1);
|
|
104
|
+
const targetProviderConfig = config.providers?.[targetProvider];
|
|
105
|
+
return modelAcceptsImageInput(config, { provider: targetProvider, id: targetId }) !== false
|
|
106
|
+
&& !(targetProviderConfig && isModelTextOnly(targetProviderConfig, targetId)) ? routedModel : undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
95
109
|
export function shouldResolveOpenAiVisionSidecar(
|
|
96
110
|
config: OcxConfig,
|
|
97
111
|
provider: OcxProviderConfig,
|
|
@@ -101,6 +115,7 @@ export function shouldResolveOpenAiVisionSidecar(
|
|
|
101
115
|
if (!isModelTextOnly(provider, modelId) || !messagesHaveImage(parsed)) return false;
|
|
102
116
|
const cfg = config.visionSidecar ?? {};
|
|
103
117
|
if (cfg.enabled === false) return false;
|
|
118
|
+
if (usableRoutedVisionModel(config)) return false;
|
|
104
119
|
return resolveVisionBackend(cfg.backend, findAnthropicVisionProvider(config)) === "openai";
|
|
105
120
|
}
|
|
106
121
|
|
|
@@ -140,43 +155,31 @@ export function planVisionSidecar(
|
|
|
140
155
|
// fence: the target must not be provably blind, and must not itself be a
|
|
141
156
|
// model this planner would re-enter for (belt; the terminal marker on the
|
|
142
157
|
// loopback request is the braces).
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
},
|
|
167
|
-
settings: {
|
|
168
|
-
model: routedModel,
|
|
169
|
-
reasoning: DEFAULT_REASONING,
|
|
170
|
-
timeoutMs: resolveVisionTimeoutMs(cfg.timeoutMs),
|
|
171
|
-
},
|
|
172
|
-
maxDescriptionsPerTurn: resolveMaxDescriptionsPerTurn(cfg.maxDescriptionsPerTurn),
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
// Misconfigured routed backend (bare id, unknown provider, or provably
|
|
177
|
-
// blind target): fall through to the legacy default order below rather
|
|
178
|
-
// than dispatching a describe that cannot work.
|
|
158
|
+
const routedModel = usableRoutedVisionModel(config);
|
|
159
|
+
if (routedModel) {
|
|
160
|
+
return {
|
|
161
|
+
backend: "routed",
|
|
162
|
+
routedModel,
|
|
163
|
+
routedConfig: {
|
|
164
|
+
port: config.port,
|
|
165
|
+
...(config.apiKeys ? { apiKeys: config.apiKeys } : {}),
|
|
166
|
+
// The self-fetch has to honor the unauthenticated loopback listener AND, with no
|
|
167
|
+
// listener, the bind address — so BOTH fields the destination resolver reads have to
|
|
168
|
+
// survive the narrowing or it silently resolves to the wrong local socket (#4236).
|
|
169
|
+
...(config.hostname ? { hostname: config.hostname } : {}),
|
|
170
|
+
...(config.unauthenticatedLoopbackListener
|
|
171
|
+
? { unauthenticatedLoopbackListener: config.unauthenticatedLoopbackListener }
|
|
172
|
+
: {}),
|
|
173
|
+
},
|
|
174
|
+
settings: {
|
|
175
|
+
model: routedModel,
|
|
176
|
+
reasoning: DEFAULT_REASONING,
|
|
177
|
+
timeoutMs: resolveVisionTimeoutMs(cfg.timeoutMs),
|
|
178
|
+
},
|
|
179
|
+
maxDescriptionsPerTurn: resolveMaxDescriptionsPerTurn(cfg.maxDescriptionsPerTurn),
|
|
180
|
+
};
|
|
179
181
|
}
|
|
182
|
+
// A non-dispatchable routed configuration keeps the legacy backend fallback below.
|
|
180
183
|
|
|
181
184
|
const anthropicSidecar = findAnthropicVisionProvider(config);
|
|
182
185
|
const backend = resolveVisionBackend(cfg.backend, anthropicSidecar);
|
package/src/web-search/index.ts
CHANGED
|
@@ -201,6 +201,7 @@ export function shouldResolveOpenAiWebSearchSidecar(
|
|
|
201
201
|
isPassthrough: boolean,
|
|
202
202
|
): boolean {
|
|
203
203
|
if (!parsed._webSearch || isPassthrough) return false;
|
|
204
|
+
if (!toolChoiceToolPredicate(parsed.options.toolChoice)(buildWebSearchTool())) return false;
|
|
204
205
|
const cfg = config.webSearchSidecar ?? {};
|
|
205
206
|
return cfg.enabled !== false && resolveSidecarBackend(cfg.backend) === "openai";
|
|
206
207
|
}
|