betahi-copilot-bridge 0.20.7 → 0.20.9
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 +20 -6
- package/dist/main.js +99 -24
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<h1 align="center">copilot-bridge</h1>
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
|
-
<a href="https://www.npmjs.com/package/betahi-copilot-bridge"><img src="https://img.shields.io/npm/v/betahi-copilot-bridge.svg?v=0.20.
|
|
4
|
+
<a href="https://www.npmjs.com/package/betahi-copilot-bridge"><img src="https://img.shields.io/npm/v/betahi-copilot-bridge.svg?v=0.20.8" alt="npm version"></a>
|
|
5
5
|
<a href="https://github.com/betahi/copilot-bridge/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/betahi-copilot-bridge.svg" alt="license"></a>
|
|
6
6
|
</p>
|
|
7
7
|
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
## Contents
|
|
15
15
|
- [Demo](#demo)
|
|
16
|
+
- [Why this bridge?](#why-this-bridge)
|
|
16
17
|
- [Install & run](#install--run)
|
|
17
18
|
- [Configure Codex CLI](#configure-codex-cli)
|
|
18
19
|
- [Configure Claude Code](#configure-claude-code)
|
|
@@ -34,6 +35,19 @@
|
|
|
34
35
|
|
|
35
36
|

|
|
36
37
|
|
|
38
|
+
## Why this bridge?
|
|
39
|
+
|
|
40
|
+
copilot-bridge is more than a raw HTTP proxy:
|
|
41
|
+
|
|
42
|
+
1. **Codex and Claude support.** Exposes Codex `/v1/responses`, Claude Code
|
|
43
|
+
`/v1/messages`, and OpenAI-compatible chat, embeddings, and models routes.
|
|
44
|
+
2. **Web search support.** Model-selected web search can be executed by the
|
|
45
|
+
bridge and fed back into a final model pass.
|
|
46
|
+
3. **End-to-end reasoning support.** Normalizes model aliases and
|
|
47
|
+
`reasoning_effort`, routes through the right upstream API, and preserves
|
|
48
|
+
returned `reasoning_text` / `reasoning_content` in streaming and
|
|
49
|
+
non-streaming responses.
|
|
50
|
+
|
|
37
51
|
## Install & run
|
|
38
52
|
|
|
39
53
|
```sh
|
|
@@ -169,7 +183,7 @@ COPILOT_WEB_SEARCH_BACKEND = "gpt-5.5"
|
|
|
169
183
|
|
|
170
184
|
| Value | Search path | Requirement |
|
|
171
185
|
| ----- | ----------- | ----------- |
|
|
172
|
-
| Copilot model id, for example `gpt-5.5` | Copilot HTTP `/responses` + `web_search_preview` |
|
|
186
|
+
| Copilot model id, for example `gpt-5.5` | Copilot HTTP `/responses` + `web_search_preview` | Recommended: `gpt-5.5`, `gpt-5.4`, `gpt-5.4-mini`, `gpt-5.3-codex`, `gpt-5.2`, `gpt-5.2-codex`. |
|
|
173
187
|
| `searxng`, use `"COPILOT_WEB_SEARCH_BACKEND": "searxng"` | Local SearXNG at `http://localhost:8080` | Start SearXNG yourself. Setup guide: https://github.com/betaHi/openclaw-searxng-search. |
|
|
174
188
|
| `copilot-cli` or `copilot`, use `"COPILOT_WEB_SEARCH_BACKEND": "copilot-cli"` | GitHub Copilot CLI `web_search` tool, using the current request model | Install and sign in to GitHub Copilot CLI yourself. |
|
|
175
189
|
|
|
@@ -254,11 +268,11 @@ accepts upstream.
|
|
|
254
268
|
| Model | Reasoning efforts | Notes |
|
|
255
269
|
| -------------------------------- | --------------------------------------- | -------------------------------------- |
|
|
256
270
|
| `claude-opus-4.7` | `medium` | Effort sent as `output_config.effort`. |
|
|
257
|
-
| `claude-opus-4.7-1m` | `low`, `medium`, `high`, `xhigh` | 1M-token context window
|
|
258
|
-
| `claude-opus-4.7-high` | `high` | Fixed high reasoning
|
|
259
|
-
| `claude-opus-4.7-xhigh` | `xhigh` | Fixed extra-high reasoning
|
|
271
|
+
| `claude-opus-4.7-1m` | `low`, `medium`, `high`, `xhigh` | 1M-token context window, prefer use `claude-opus-4.7-[1m]` in config|
|
|
272
|
+
| `claude-opus-4.7-high` | `high` | Fixed high reasoning|
|
|
273
|
+
| `claude-opus-4.7-xhigh` | `xhigh` | Fixed extra-high reasoning|
|
|
260
274
|
| `claude-opus-4.6` | `low`, `medium`, `high` | |
|
|
261
|
-
| `claude-opus-4.6-1m` | `low`, `medium`, `high` | 1M-token context window.
|
|
275
|
+
| `claude-opus-4.6-1m` | `low`, `medium`, `high` | 1M-token context window, prefer use `claude-opus-4.6-[1m]` in config |
|
|
262
276
|
| `claude-sonnet-4.6` | `low`, `medium`, `high` | |
|
|
263
277
|
| `claude-opus-4.5` | — | Reasoning not accepted upstream. |
|
|
264
278
|
| `claude-sonnet-4.5` | — | Reasoning not accepted upstream. |
|
package/dist/main.js
CHANGED
|
@@ -3,9 +3,11 @@ import { defineCommand, runMain } from "citty";
|
|
|
3
3
|
import consola from "consola";
|
|
4
4
|
import fs, { appendFile } from "node:fs/promises";
|
|
5
5
|
import os from "node:os";
|
|
6
|
-
import path from "node:path";
|
|
6
|
+
import path, { dirname, resolve } from "node:path";
|
|
7
7
|
import { createHash, randomUUID } from "node:crypto";
|
|
8
8
|
import { z } from "zod";
|
|
9
|
+
import { accessSync, constants, readFileSync } from "node:fs";
|
|
10
|
+
import { fileURLToPath } from "node:url";
|
|
9
11
|
import { serve } from "@hono/node-server";
|
|
10
12
|
import { Hono } from "hono";
|
|
11
13
|
import { cors } from "hono/cors";
|
|
@@ -13,7 +15,6 @@ import { logger } from "hono/logger";
|
|
|
13
15
|
import { streamSSE } from "hono/streaming";
|
|
14
16
|
import { events } from "fetch-event-stream";
|
|
15
17
|
import { execFile } from "node:child_process";
|
|
16
|
-
import { accessSync, constants } from "node:fs";
|
|
17
18
|
|
|
18
19
|
//#region src/lib/error.ts
|
|
19
20
|
var BridgeNotImplementedError = class extends Error {
|
|
@@ -148,8 +149,8 @@ const standardHeaders = () => ({
|
|
|
148
149
|
accept: "application/json",
|
|
149
150
|
"content-type": "application/json"
|
|
150
151
|
});
|
|
151
|
-
const sleep$1 = (ms) => new Promise((resolve) => {
|
|
152
|
-
setTimeout(resolve, ms);
|
|
152
|
+
const sleep$1 = (ms) => new Promise((resolve$1) => {
|
|
153
|
+
setTimeout(resolve$1, ms);
|
|
153
154
|
});
|
|
154
155
|
const readGitHubToken$1 = async () => {
|
|
155
156
|
return (await fs.readFile(PATHS.GITHUB_TOKEN_PATH, "utf8")).trim();
|
|
@@ -208,7 +209,7 @@ const getCopilotToken = async (githubToken, vsCodeVersion) => {
|
|
|
208
209
|
return await response.json();
|
|
209
210
|
};
|
|
210
211
|
const isCopilotTokenError = (error) => error instanceof HTTPError && error.message === "Failed to get Copilot token";
|
|
211
|
-
const ensureGitHubToken = async (
|
|
212
|
+
const ensureGitHubToken = async (options = {}) => {
|
|
212
213
|
await ensurePaths();
|
|
213
214
|
const existingToken = options.force ? "" : await readGitHubToken$1();
|
|
214
215
|
if (existingToken) return existingToken;
|
|
@@ -217,17 +218,23 @@ const ensureGitHubToken = async (config, options = {}) => {
|
|
|
217
218
|
const githubToken = await pollAccessToken(deviceCode);
|
|
218
219
|
await writeGitHubToken(githubToken);
|
|
219
220
|
if (options.showToken) consola.info("GitHub token:", githubToken);
|
|
220
|
-
const user = await getGitHubUser(githubToken, config.vsCodeVersion);
|
|
221
|
-
consola.success(`Logged in as ${user.login}`);
|
|
222
221
|
return githubToken;
|
|
223
222
|
};
|
|
223
|
+
const loadGitHubLogin = async (githubToken, vsCodeVersion) => {
|
|
224
|
+
try {
|
|
225
|
+
return (await getGitHubUser(githubToken, vsCodeVersion)).login;
|
|
226
|
+
} catch (error) {
|
|
227
|
+
consola.warn("Could not load GitHub user:", error);
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
};
|
|
224
231
|
const setupBridgeAuth = async (config, options = {}) => {
|
|
225
232
|
if (config.copilotToken) {
|
|
226
233
|
if (options.showToken) consola.info("Using COPILOT_TOKEN from environment");
|
|
227
234
|
await loadModels(config);
|
|
228
|
-
return;
|
|
235
|
+
return { source: "copilot-token" };
|
|
229
236
|
}
|
|
230
|
-
let githubToken = await ensureGitHubToken(
|
|
237
|
+
let githubToken = await ensureGitHubToken(options);
|
|
231
238
|
const applyCopilotToken = async () => {
|
|
232
239
|
const { refresh_in, token } = await getCopilotToken(githubToken, config.vsCodeVersion);
|
|
233
240
|
config.copilotToken = token;
|
|
@@ -240,7 +247,7 @@ const setupBridgeAuth = async (config, options = {}) => {
|
|
|
240
247
|
} catch (error) {
|
|
241
248
|
if (options.force || !isCopilotTokenError(error)) throw error;
|
|
242
249
|
consola.warn("Cached GitHub auth could not get a Copilot token; running device auth again.");
|
|
243
|
-
githubToken = await ensureGitHubToken(
|
|
250
|
+
githubToken = await ensureGitHubToken({
|
|
244
251
|
...options,
|
|
245
252
|
force: true
|
|
246
253
|
});
|
|
@@ -256,6 +263,10 @@ const setupBridgeAuth = async (config, options = {}) => {
|
|
|
256
263
|
}
|
|
257
264
|
}, refreshInterval);
|
|
258
265
|
await loadModels(config);
|
|
266
|
+
return {
|
|
267
|
+
githubLogin: await loadGitHubLogin(githubToken, config.vsCodeVersion),
|
|
268
|
+
source: "github-token"
|
|
269
|
+
};
|
|
259
270
|
};
|
|
260
271
|
const loadModels = async (config) => {
|
|
261
272
|
try {
|
|
@@ -321,10 +332,11 @@ const auth = defineCommand({
|
|
|
321
332
|
port: Number(args.port)
|
|
322
333
|
});
|
|
323
334
|
config.copilotToken = void 0;
|
|
324
|
-
await setupBridgeAuth(config, {
|
|
335
|
+
const authSession = await setupBridgeAuth(config, {
|
|
325
336
|
force: true,
|
|
326
337
|
showToken: args["show-token"]
|
|
327
338
|
});
|
|
339
|
+
if (authSession.githubLogin) consola.info(`Logged in as ${authSession.githubLogin}`);
|
|
328
340
|
consola.success("copilot-bridge auth completed");
|
|
329
341
|
}
|
|
330
342
|
});
|
|
@@ -475,9 +487,11 @@ function tomlEscape(value) {
|
|
|
475
487
|
}
|
|
476
488
|
function buildManagedBlock(input) {
|
|
477
489
|
const { baseUrl, settings } = input;
|
|
490
|
+
const modelContextWindow = normalizeModelContextWindow(input.modelContextWindow);
|
|
478
491
|
const lines = [];
|
|
479
492
|
lines.push(BEGIN_MARK);
|
|
480
493
|
if (settings.setAsDefault) lines.push(`model_provider = "${tomlEscape(settings.providerId)}"`);
|
|
494
|
+
if (modelContextWindow !== void 0) lines.push(`model_context_window = ${modelContextWindow}`);
|
|
481
495
|
lines.push("model_supports_reasoning_summaries = true");
|
|
482
496
|
lines.push("");
|
|
483
497
|
lines.push(`[model_providers.${settings.providerId}]`);
|
|
@@ -489,6 +503,15 @@ function buildManagedBlock(input) {
|
|
|
489
503
|
lines.push(END_MARK);
|
|
490
504
|
return lines.join("\n");
|
|
491
505
|
}
|
|
506
|
+
function extractPreservedContentFromManagedBlock(content) {
|
|
507
|
+
const lines = content.split("\n");
|
|
508
|
+
const preserveStart = lines.findIndex((line) => {
|
|
509
|
+
const trimmed = line.trim();
|
|
510
|
+
return trimmed.startsWith("[") && !trimmed.startsWith("[model_providers.");
|
|
511
|
+
});
|
|
512
|
+
if (preserveStart === -1) return "";
|
|
513
|
+
return lines.slice(preserveStart).join("\n").replace(/^\n+|\n+$/g, "");
|
|
514
|
+
}
|
|
492
515
|
function stripManagedBlock(content) {
|
|
493
516
|
let next = content;
|
|
494
517
|
for (const [begin, end] of [[BEGIN_MARK, END_MARK], [LEGACY_BEGIN_MARK, LEGACY_END_MARK]]) while (true) {
|
|
@@ -496,8 +519,9 @@ function stripManagedBlock(content) {
|
|
|
496
519
|
if (beginIdx === -1) break;
|
|
497
520
|
const endIdx = next.indexOf(end, beginIdx);
|
|
498
521
|
if (endIdx === -1) break;
|
|
522
|
+
const preserved = extractPreservedContentFromManagedBlock(next.slice(beginIdx + begin.length, endIdx));
|
|
499
523
|
const before = next.slice(0, beginIdx).replace(/\n*$/, "");
|
|
500
|
-
const after = next.slice(endIdx + end.length).replace(/^\n+/, "");
|
|
524
|
+
const after = [preserved, next.slice(endIdx + end.length)].filter(Boolean).join("\n").replace(/^\n+/, "");
|
|
501
525
|
if (before.length === 0) next = after;
|
|
502
526
|
else if (after.length === 0) next = `${before}\n`;
|
|
503
527
|
else next = `${before}\n\n${after}`;
|
|
@@ -541,6 +565,19 @@ function removeTopKey(topSection, key) {
|
|
|
541
565
|
const re = /* @__PURE__ */ new RegExp(`^\\s*${key}\\s*=`);
|
|
542
566
|
return lines.filter((line) => !re.test(line)).join("\n");
|
|
543
567
|
}
|
|
568
|
+
function normalizeModelContextWindow(value) {
|
|
569
|
+
if (value === void 0 || !Number.isFinite(value)) return;
|
|
570
|
+
const normalized = Math.trunc(value);
|
|
571
|
+
return normalized > 0 ? normalized : void 0;
|
|
572
|
+
}
|
|
573
|
+
function removeTopLevelContextWindowWhenManaged(content, input) {
|
|
574
|
+
if (normalizeModelContextWindow(input.modelContextWindow) === void 0) return content;
|
|
575
|
+
const { top, rest } = splitTopSection(content);
|
|
576
|
+
const nextTop = removeTopKey(top, "model_context_window");
|
|
577
|
+
if (nextTop === top) return content;
|
|
578
|
+
if (rest.length === 0) return nextTop.endsWith("\n") ? nextTop : `${nextTop}\n`;
|
|
579
|
+
return `${nextTop}${nextTop.endsWith("\n") ? "" : "\n"}${rest}`;
|
|
580
|
+
}
|
|
544
581
|
function sanitizeTopReasoningEffort(topSection) {
|
|
545
582
|
const match = topSection.match(scalarRegex("model_reasoning_effort"));
|
|
546
583
|
if (!match) return topSection;
|
|
@@ -571,9 +608,14 @@ async function applyCodexConfig(input) {
|
|
|
571
608
|
}
|
|
572
609
|
let stripped = stripManagedBlock(existing);
|
|
573
610
|
stripped = applyUserScalars(stripped, input);
|
|
611
|
+
stripped = removeTopLevelContextWindowWhenManaged(stripped, input);
|
|
574
612
|
const block = buildManagedBlock(input);
|
|
575
|
-
const
|
|
576
|
-
const next =
|
|
613
|
+
const { top, rest } = splitTopSection(stripped);
|
|
614
|
+
const next = `${[
|
|
615
|
+
top,
|
|
616
|
+
block,
|
|
617
|
+
rest
|
|
618
|
+
].map((part) => part.replace(/^\n+|\n+$/g, "")).filter(Boolean).join("\n\n")}\n`;
|
|
577
619
|
if (next === existing) return {
|
|
578
620
|
configPath,
|
|
579
621
|
changed: false,
|
|
@@ -858,10 +900,28 @@ const clampReasoningEffort = (modelId, requested) => {
|
|
|
858
900
|
};
|
|
859
901
|
};
|
|
860
902
|
|
|
903
|
+
//#endregion
|
|
904
|
+
//#region src/lib/version.ts
|
|
905
|
+
const PACKAGE_NAME = "betahi-copilot-bridge";
|
|
906
|
+
const readPackageVersion = () => {
|
|
907
|
+
let currentDir = dirname(fileURLToPath(import.meta.url));
|
|
908
|
+
while (true) {
|
|
909
|
+
try {
|
|
910
|
+
const packageJsonPath = resolve(currentDir, "package.json");
|
|
911
|
+
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
912
|
+
if (packageJson.name === PACKAGE_NAME && typeof packageJson.version === "string") return packageJson.version;
|
|
913
|
+
} catch {}
|
|
914
|
+
const parentDir = dirname(currentDir);
|
|
915
|
+
if (parentDir === currentDir) return "unknown";
|
|
916
|
+
currentDir = parentDir;
|
|
917
|
+
}
|
|
918
|
+
};
|
|
919
|
+
const BRIDGE_VERSION = readPackageVersion();
|
|
920
|
+
|
|
861
921
|
//#endregion
|
|
862
922
|
//#region src/lib/rate-limit.ts
|
|
863
|
-
const sleep = (ms) => new Promise((resolve) => {
|
|
864
|
-
setTimeout(resolve, ms);
|
|
923
|
+
const sleep = (ms) => new Promise((resolve$1) => {
|
|
924
|
+
setTimeout(resolve$1, ms);
|
|
865
925
|
});
|
|
866
926
|
/**
|
|
867
927
|
* Enforces the configured rate limit window between mutating upstream calls.
|
|
@@ -2492,7 +2552,7 @@ const findCopilotCliCommand = () => {
|
|
|
2492
2552
|
const candidates = (process.env.PATH ?? "").split(path.delimiter).filter(Boolean).flatMap((directory) => copilotExecutableNames().map((name) => path.join(directory, name))).filter(canExecute);
|
|
2493
2553
|
return candidates.find((candidate) => !COPILOT_CHAT_WRAPPER_PATH_PATTERN.test(candidate)) ?? candidates[0] ?? "copilot";
|
|
2494
2554
|
};
|
|
2495
|
-
const runCopilotCliCommand = (args, timeout) => new Promise((resolve, reject) => {
|
|
2555
|
+
const runCopilotCliCommand = (args, timeout) => new Promise((resolve$1, reject) => {
|
|
2496
2556
|
execFile(findCopilotCliCommand(), args, {
|
|
2497
2557
|
encoding: "utf8",
|
|
2498
2558
|
timeout
|
|
@@ -2505,7 +2565,7 @@ const runCopilotCliCommand = (args, timeout) => new Promise((resolve, reject) =>
|
|
|
2505
2565
|
});
|
|
2506
2566
|
return;
|
|
2507
2567
|
}
|
|
2508
|
-
resolve({
|
|
2568
|
+
resolve$1({
|
|
2509
2569
|
stdout,
|
|
2510
2570
|
stderr
|
|
2511
2571
|
});
|
|
@@ -2666,6 +2726,9 @@ const webSearchResponseToEvents = (response) => {
|
|
|
2666
2726
|
content_block: block.type === "text" ? {
|
|
2667
2727
|
type: "text",
|
|
2668
2728
|
text: ""
|
|
2729
|
+
} : block.type === "server_tool_use" || block.type === "tool_use" ? {
|
|
2730
|
+
...block,
|
|
2731
|
+
input: {}
|
|
2669
2732
|
} : block
|
|
2670
2733
|
});
|
|
2671
2734
|
if (block.type === "text" && block.text) events$1.push({
|
|
@@ -2676,7 +2739,7 @@ const webSearchResponseToEvents = (response) => {
|
|
|
2676
2739
|
text: block.text
|
|
2677
2740
|
}
|
|
2678
2741
|
});
|
|
2679
|
-
else if (block.type === "server_tool_use") events$1.push({
|
|
2742
|
+
else if (block.type === "server_tool_use" || block.type === "tool_use") events$1.push({
|
|
2680
2743
|
type: "content_block_delta",
|
|
2681
2744
|
index,
|
|
2682
2745
|
delta: {
|
|
@@ -4064,6 +4127,12 @@ const fetchAvailableModels = async (config) => {
|
|
|
4064
4127
|
return [];
|
|
4065
4128
|
}
|
|
4066
4129
|
};
|
|
4130
|
+
const getCodexModelContextWindow = (model) => {
|
|
4131
|
+
if (!model) return void 0;
|
|
4132
|
+
const resolvedModel = resolveModelId(model);
|
|
4133
|
+
const contextWindow = (runtimeState.models?.data.find((candidate) => candidate.id === resolvedModel || candidate.id === model || getPublicModelId(candidate.id) === model || getPublicModelId(candidate.id) === resolvedModel))?.capabilities?.limits?.max_context_window_tokens;
|
|
4134
|
+
return typeof contextWindow === "number" && contextWindow > 0 ? Math.trunc(contextWindow) : void 0;
|
|
4135
|
+
};
|
|
4067
4136
|
const start = defineCommand({
|
|
4068
4137
|
meta: {
|
|
4069
4138
|
name: "start",
|
|
@@ -4139,8 +4208,12 @@ const start = defineCommand({
|
|
|
4139
4208
|
runtimeState.rateLimitWait = Boolean(args.wait);
|
|
4140
4209
|
consola.info(`Rate limit: ${parsed}s between requests (${runtimeState.rateLimitWait ? "wait" : "reject"} on overflow)`);
|
|
4141
4210
|
}
|
|
4142
|
-
await setupBridgeAuth(config, { showToken: args["show-token"] });
|
|
4211
|
+
const authSession = await setupBridgeAuth(config, { showToken: args["show-token"] });
|
|
4143
4212
|
const server = startServer(config);
|
|
4213
|
+
consola.info(`copilot-bridge version: ${BRIDGE_VERSION}`);
|
|
4214
|
+
if (authSession.githubLogin) consola.info(`GitHub user: ${authSession.githubLogin}`);
|
|
4215
|
+
else if (authSession.source === "copilot-token") consola.info("GitHub user: unavailable (using COPILOT_TOKEN)");
|
|
4216
|
+
else consola.warn("GitHub user: unavailable");
|
|
4144
4217
|
consola.success(`copilot-bridge listening on http://${config.host}:${config.port}`);
|
|
4145
4218
|
consola.info(`copilot base url: ${config.copilotBaseUrl}`);
|
|
4146
4219
|
const baseUrl = `http://${config.host}:${config.port}`;
|
|
@@ -4177,7 +4250,8 @@ const start = defineCommand({
|
|
|
4177
4250
|
configPath: codexConfigPath,
|
|
4178
4251
|
settings: CODEX_DEFAULTS,
|
|
4179
4252
|
model: chosenModel,
|
|
4180
|
-
modelReasoningEffort: chosenEffort
|
|
4253
|
+
modelReasoningEffort: chosenEffort,
|
|
4254
|
+
modelContextWindow: getCodexModelContextWindow(chosenModel)
|
|
4181
4255
|
});
|
|
4182
4256
|
if (result.changed) {
|
|
4183
4257
|
consola.success(`codex config ${result.created ? "created" : "updated"}: ${result.configPath}`);
|
|
@@ -4218,7 +4292,8 @@ const start = defineCommand({
|
|
|
4218
4292
|
configPath: codexConfigPath,
|
|
4219
4293
|
settings: CODEX_DEFAULTS,
|
|
4220
4294
|
model: chosenModel,
|
|
4221
|
-
modelReasoningEffort: chosenEffort
|
|
4295
|
+
modelReasoningEffort: chosenEffort,
|
|
4296
|
+
modelContextWindow: getCodexModelContextWindow(chosenModel)
|
|
4222
4297
|
});
|
|
4223
4298
|
if (result.changed) consola.success(`codex config updated: ${result.configPath}`);
|
|
4224
4299
|
} catch (error) {
|
|
@@ -4226,8 +4301,8 @@ const start = defineCommand({
|
|
|
4226
4301
|
}
|
|
4227
4302
|
}
|
|
4228
4303
|
}
|
|
4229
|
-
await new Promise((resolve, reject) => {
|
|
4230
|
-
server.on("close", resolve);
|
|
4304
|
+
await new Promise((resolve$1, reject) => {
|
|
4305
|
+
server.on("close", resolve$1);
|
|
4231
4306
|
server.on("error", reject);
|
|
4232
4307
|
});
|
|
4233
4308
|
}
|