codex-copilot-dx 0.4.12 → 0.4.14
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/bin/cli.mjs +11 -5
- package/package.json +1 -1
- package/src/adapter.mjs +11 -1
- package/src/models.mjs +46 -16
package/bin/cli.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { ensureClaudeConfig } from "../src/claude-config.mjs";
|
|
|
6
6
|
import { applyClaudeDesktopConfig, formatClaudeDesktopApplyResult, generatedClaudeDesktopApiKey } from "../src/claude-desktop-config.mjs";
|
|
7
7
|
import { startAdapter } from "../src/adapter.mjs";
|
|
8
8
|
import { listModels, refreshVSCodeVersion } from "../src/copilot.mjs";
|
|
9
|
-
import { claudeDesktopModelDefsFromCopilotModels, claudeDesktopModelIds, parseModelAliasEnv } from "../src/models.mjs";
|
|
9
|
+
import { claudeDesktopModelDefsFromCopilotModels, claudeDesktopModelIds, gptModelIdsFromCopilotModels, parseModelAliasEnv } from "../src/models.mjs";
|
|
10
10
|
import { status } from "../src/status.mjs";
|
|
11
11
|
import { printUsageSummary } from "../src/usage.mjs";
|
|
12
12
|
import { checkForUpdate, localPackageVersion } from "../src/version.mjs";
|
|
@@ -36,7 +36,15 @@ async function refreshClaudeDesktopModelDefs() {
|
|
|
36
36
|
if (httpStatus < 200 || httpStatus >= 300) {
|
|
37
37
|
throw new Error(`Copilot models returned HTTP ${httpStatus}`);
|
|
38
38
|
}
|
|
39
|
-
const
|
|
39
|
+
const models = JSON.parse(body);
|
|
40
|
+
const gptModelIds = gptModelIdsFromCopilotModels(models);
|
|
41
|
+
if (gptModelIds.length) {
|
|
42
|
+
console.log(status("ok", `Refreshed GPT models from GitHub Copilot: ${gptModelIds.join(", ")}`));
|
|
43
|
+
} else {
|
|
44
|
+
console.log(status("warn", "Copilot models response contained no GPT models"));
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const modelDefs = claudeDesktopModelDefsFromCopilotModels(models);
|
|
40
48
|
if (!modelDefs.length) throw new Error("Copilot models response contained no Claude models");
|
|
41
49
|
console.log(status("ok", `Refreshed Claude models from GitHub Copilot: ${modelDefs.map((model) => model.id).join(", ")}`));
|
|
42
50
|
return modelDefs;
|
|
@@ -113,9 +121,7 @@ try {
|
|
|
113
121
|
openCodex();
|
|
114
122
|
|
|
115
123
|
console.log(`
|
|
116
|
-
${status("ok",
|
|
117
|
-
? "Ready. Codex, Claude Code, and Claude App are using your GitHub Copilot subscription."
|
|
118
|
-
: "Ready. Codex and Claude Code are using your GitHub Copilot subscription. Claude App support is available with --configure-claude-desktop.")}
|
|
124
|
+
${status("ok", "Ready, Claude Code, Claude App and Codex App are now ready to use")}
|
|
119
125
|
|
|
120
126
|
Adapter: http://${ADAPTER_HOST}:${ADAPTER_PORT}
|
|
121
127
|
|
package/package.json
CHANGED
package/src/adapter.mjs
CHANGED
|
@@ -750,8 +750,18 @@ export function startAdapter(port = 2026, host = "127.0.0.1", options = {}) {
|
|
|
750
750
|
socket.destroy();
|
|
751
751
|
});
|
|
752
752
|
|
|
753
|
-
return new Promise((resolve) => {
|
|
753
|
+
return new Promise((resolve, reject) => {
|
|
754
|
+
const onListenError = (e) => {
|
|
755
|
+
if (e?.code === "EADDRINUSE") {
|
|
756
|
+
reject(new Error(`Adapter address http://${host}:${port} is already in use. Stop the existing codex-copilot-dx process or set ADAPTER_PORT to another port.`));
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
reject(e);
|
|
760
|
+
};
|
|
761
|
+
|
|
762
|
+
server.once("error", onListenError);
|
|
754
763
|
server.listen(port, host, () => {
|
|
764
|
+
server.off("error", onListenError);
|
|
755
765
|
const actualPort = server.address()?.port || port;
|
|
756
766
|
console.log(status("ok", `Adapter listening on http://${host}:${actualPort}`));
|
|
757
767
|
resolve(server);
|
package/src/models.mjs
CHANGED
|
@@ -31,6 +31,9 @@ const DEFAULT_CLAUDE_DESKTOP_MODEL_DEFS = [
|
|
|
31
31
|
maxInputTokens: 200000,
|
|
32
32
|
maxOutputTokens: 8192,
|
|
33
33
|
},
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
const DEFAULT_CLAUDE_MODEL_ALIAS_DEFS = [
|
|
34
37
|
{
|
|
35
38
|
id: "claude-sonnet-4-6",
|
|
36
39
|
upstream: "claude-sonnet-4.6",
|
|
@@ -94,6 +97,29 @@ function hasMessagesEndpoint(model) {
|
|
|
94
97
|
return endpoints.includes("/v1/messages") || endpoints.includes("/chat/completions");
|
|
95
98
|
}
|
|
96
99
|
|
|
100
|
+
function hasOpenAIEndpoint(model) {
|
|
101
|
+
const endpoints = Array.isArray(model?.supported_endpoints) ? model.supported_endpoints : [];
|
|
102
|
+
return endpoints.includes("/responses") || endpoints.includes("/v1/responses") || endpoints.includes("/chat/completions");
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
function copilotModelData(models) {
|
|
106
|
+
const data = Array.isArray(models) ? models : models?.data;
|
|
107
|
+
return Array.isArray(data) ? data : [];
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function uniqueIds(models, predicate) {
|
|
111
|
+
const ids = [];
|
|
112
|
+
const seen = new Set();
|
|
113
|
+
for (const model of models) {
|
|
114
|
+
if (!predicate(model)) continue;
|
|
115
|
+
const id = String(model.id || "").trim();
|
|
116
|
+
if (!id || seen.has(id)) continue;
|
|
117
|
+
ids.push(id);
|
|
118
|
+
seen.add(id);
|
|
119
|
+
}
|
|
120
|
+
return ids;
|
|
121
|
+
}
|
|
122
|
+
|
|
97
123
|
function isClaudeCopilotModel(model) {
|
|
98
124
|
const id = String(model?.id || "").trim();
|
|
99
125
|
const vendor = String(model?.vendor || "").toLowerCase();
|
|
@@ -103,9 +129,17 @@ function isClaudeCopilotModel(model) {
|
|
|
103
129
|
&& hasMessagesEndpoint(model);
|
|
104
130
|
}
|
|
105
131
|
|
|
132
|
+
export function gptModelIdsFromCopilotModels(models) {
|
|
133
|
+
return uniqueIds(copilotModelData(models), (model) => {
|
|
134
|
+
const id = String(model?.id || "").trim();
|
|
135
|
+
return id.startsWith("gpt-")
|
|
136
|
+
&& model?.model_picker_enabled !== false
|
|
137
|
+
&& hasOpenAIEndpoint(model);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
106
141
|
export function claudeDesktopModelDefsFromCopilotModels(models) {
|
|
107
|
-
const data =
|
|
108
|
-
if (!Array.isArray(data)) return [];
|
|
142
|
+
const data = copilotModelData(models);
|
|
109
143
|
|
|
110
144
|
const defs = [];
|
|
111
145
|
const seen = new Set();
|
|
@@ -126,19 +160,6 @@ export function claudeDesktopModelDefsFromCopilotModels(models) {
|
|
|
126
160
|
});
|
|
127
161
|
}
|
|
128
162
|
|
|
129
|
-
const upstreamIds = new Set(defs.map((model) => model.upstream));
|
|
130
|
-
for (const alias of DEFAULT_CLAUDE_DESKTOP_MODEL_DEFS) {
|
|
131
|
-
if (alias.id === alias.upstream || seen.has(alias.id) || !upstreamIds.has(alias.upstream)) continue;
|
|
132
|
-
const upstream = defs.find((model) => model.upstream === alias.upstream);
|
|
133
|
-
defs.push({
|
|
134
|
-
...alias,
|
|
135
|
-
displayName: upstream?.displayName || alias.displayName,
|
|
136
|
-
maxInputTokens: upstream?.maxInputTokens || alias.maxInputTokens,
|
|
137
|
-
maxOutputTokens: upstream?.maxOutputTokens || alias.maxOutputTokens,
|
|
138
|
-
});
|
|
139
|
-
seen.add(alias.id);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
163
|
return defs;
|
|
143
164
|
}
|
|
144
165
|
|
|
@@ -153,9 +174,18 @@ export function claudeDesktopModelIds(env = process.env, options = {}) {
|
|
|
153
174
|
return claudeDesktopModelDefs(env, options).map((model) => model.id);
|
|
154
175
|
}
|
|
155
176
|
|
|
177
|
+
function claudeModelResolutionDefs(env = process.env, options = {}) {
|
|
178
|
+
const defs = claudeDesktopModelDefs(env, options);
|
|
179
|
+
if (parseModelAliasEnv(env.CCDX_CLAUDE_MODEL_ALIASES).length) return defs;
|
|
180
|
+
|
|
181
|
+
const upstreamIds = new Set(defs.map((model) => model.upstream));
|
|
182
|
+
const aliases = DEFAULT_CLAUDE_MODEL_ALIAS_DEFS.filter((alias) => upstreamIds.has(alias.upstream));
|
|
183
|
+
return [...defs, ...aliases];
|
|
184
|
+
}
|
|
185
|
+
|
|
156
186
|
export function resolveAnthropicModel(model, env = process.env, options = {}) {
|
|
157
187
|
const requestedModel = String(model || "");
|
|
158
|
-
const match =
|
|
188
|
+
const match = claudeModelResolutionDefs(env, options).find((entry) => entry.id === requestedModel);
|
|
159
189
|
return {
|
|
160
190
|
requestedModel,
|
|
161
191
|
upstreamModel: match?.upstream || requestedModel,
|