@mrciphersmith/keryx 0.2.100 → 0.2.101
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/dist/cli.js +142 -87
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -298,6 +298,91 @@ var init_provider_config = __esm(() => {
|
|
|
298
298
|
];
|
|
299
299
|
});
|
|
300
300
|
|
|
301
|
+
// src/lib/oauth/catalog.ts
|
|
302
|
+
function extraRequestHeaders(provider) {
|
|
303
|
+
if (provider === "github-copilot") {
|
|
304
|
+
return GITHUB_COPILOT_REQUEST_HEADERS;
|
|
305
|
+
}
|
|
306
|
+
return;
|
|
307
|
+
}
|
|
308
|
+
function authCatalogEntry(provider) {
|
|
309
|
+
return PROVIDER_AUTH_CATALOG.find((entry) => entry.provider === provider);
|
|
310
|
+
}
|
|
311
|
+
function catalogMethods(provider) {
|
|
312
|
+
return authCatalogEntry(provider)?.methods ?? ["api-key"];
|
|
313
|
+
}
|
|
314
|
+
function catalogAllows(provider, method) {
|
|
315
|
+
return catalogMethods(provider).includes(method);
|
|
316
|
+
}
|
|
317
|
+
function catalogRefusal(provider) {
|
|
318
|
+
return authCatalogEntry(provider)?.refusal;
|
|
319
|
+
}
|
|
320
|
+
function deviceCodeMethodLabel(provider) {
|
|
321
|
+
if (provider === "grok")
|
|
322
|
+
return "SuperGrok Subscription";
|
|
323
|
+
if (provider === "github-copilot")
|
|
324
|
+
return "Login with GitHub Copilot";
|
|
325
|
+
if (provider === "openai")
|
|
326
|
+
return "ChatGPT Plus/Pro (headless)";
|
|
327
|
+
return "Device authorization";
|
|
328
|
+
}
|
|
329
|
+
var XAI_GROK_DEVICE, GITHUB_COPILOT_REQUEST_HEADERS, GITHUB_COPILOT_OAUTH_CLIENT_ID = "Iv1.b507a08c87ecfe98", GITHUB_COPILOT_DEVICE, PROVIDER_AUTH_CATALOG;
|
|
330
|
+
var init_catalog = __esm(() => {
|
|
331
|
+
XAI_GROK_DEVICE = {
|
|
332
|
+
deviceAuthorizationEndpoint: "https://auth.x.ai/oauth2/device/code",
|
|
333
|
+
tokenEndpoint: "https://auth.x.ai/oauth2/token",
|
|
334
|
+
clientId: "b1a00492-073a-47ea-816f-4c329264a828",
|
|
335
|
+
scope: "openid profile email offline_access grok-cli:access api:access",
|
|
336
|
+
extraForm: { referrer: "keryx" },
|
|
337
|
+
headers: { "User-Agent": "keryx" }
|
|
338
|
+
};
|
|
339
|
+
GITHUB_COPILOT_REQUEST_HEADERS = {
|
|
340
|
+
Accept: "application/json",
|
|
341
|
+
"User-Agent": "GitHubCopilotChat/0.26.7",
|
|
342
|
+
"Editor-Version": "vscode/1.99.3",
|
|
343
|
+
"Editor-Plugin-Version": "copilot-chat/0.26.7",
|
|
344
|
+
"Copilot-Integration-Id": "vscode-chat"
|
|
345
|
+
};
|
|
346
|
+
GITHUB_COPILOT_DEVICE = {
|
|
347
|
+
deviceAuthorizationEndpoint: "https://github.com/login/device/code",
|
|
348
|
+
tokenEndpoint: "https://github.com/login/oauth/access_token",
|
|
349
|
+
clientId: GITHUB_COPILOT_OAUTH_CLIENT_ID,
|
|
350
|
+
scope: "read:user",
|
|
351
|
+
headers: GITHUB_COPILOT_REQUEST_HEADERS,
|
|
352
|
+
afterToken: "github-copilot"
|
|
353
|
+
};
|
|
354
|
+
PROVIDER_AUTH_CATALOG = [
|
|
355
|
+
{
|
|
356
|
+
provider: "grok",
|
|
357
|
+
label: "xAI (Grok)",
|
|
358
|
+
methods: ["device-code", "api-key"],
|
|
359
|
+
device: XAI_GROK_DEVICE
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
provider: "openai",
|
|
363
|
+
label: "OpenAI",
|
|
364
|
+
methods: ["oauth-pkce-loopback", "device-code", "api-key"]
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
provider: "github-copilot",
|
|
368
|
+
label: "GitHub Copilot",
|
|
369
|
+
methods: ["device-code"],
|
|
370
|
+
device: GITHUB_COPILOT_DEVICE
|
|
371
|
+
},
|
|
372
|
+
{ provider: "anthropic", label: "Anthropic", methods: ["api-key"], refusal: "Anthropic does not permit third-party Claude Pro/Max login. Use an API key from the Anthropic Console." },
|
|
373
|
+
{ provider: "gemini", label: "Google Gemini", methods: ["api-key"], refusal: "Gemini Google-account login is for Gemini CLI. In keryx use GEMINI_API_KEY from Google AI Studio." },
|
|
374
|
+
{ provider: "deepseek", label: "DeepSeek", methods: ["api-key"], refusal: "DeepSeek has no consumer OAuth grant. Use DEEPSEEK_API_KEY." },
|
|
375
|
+
{ provider: "openrouter", label: "OpenRouter", methods: ["api-key"] },
|
|
376
|
+
{ provider: "zai", label: "Z.AI (GLM)", methods: ["api-key"] },
|
|
377
|
+
{ provider: "zai-coding", label: "Z.AI GLM Coding Plan", methods: ["api-key"] },
|
|
378
|
+
{ provider: "cerebras", label: "Cerebras", methods: ["api-key"] },
|
|
379
|
+
{ provider: "groq", label: "Groq", methods: ["api-key"] },
|
|
380
|
+
{ provider: "moonshot", label: "Moonshot (Kimi)", methods: ["api-key"] },
|
|
381
|
+
{ provider: "ollama", label: "Ollama", methods: ["none"] },
|
|
382
|
+
{ provider: "rapid-mlx", label: "Rapid-MLX (Local)", methods: ["none"] }
|
|
383
|
+
];
|
|
384
|
+
});
|
|
385
|
+
|
|
301
386
|
// src/lib/shell-config.ts
|
|
302
387
|
import { existsSync as existsSync2 } from "fs";
|
|
303
388
|
import path3 from "path";
|
|
@@ -641,8 +726,13 @@ async function fetchOpenAiCompatModelsDetailed(fetchFn, provider, apiKey, opts)
|
|
|
641
726
|
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
642
727
|
try {
|
|
643
728
|
const init = { signal: controller.signal };
|
|
729
|
+
const extraHeaders = extraRequestHeaders(provider.name);
|
|
730
|
+
const headers = extraHeaders === undefined ? {} : { ...extraHeaders };
|
|
644
731
|
if (apiKey !== undefined && apiKey.length > 0) {
|
|
645
|
-
|
|
732
|
+
headers.authorization = `Bearer ${apiKey}`;
|
|
733
|
+
}
|
|
734
|
+
if (Object.keys(headers).length > 0) {
|
|
735
|
+
init.headers = headers;
|
|
646
736
|
}
|
|
647
737
|
const res = await fetchFn(url, init);
|
|
648
738
|
if (!res.ok) {
|
|
@@ -890,6 +980,7 @@ with a stated reason and exits 0 \u2014 that is a normal configuration, not an e
|
|
|
890
980
|
var DEFAULT_MODELS_PATH = "/v1/models", OPENAI_COMPAT_PROVIDERS, MODELS_FETCH_TIMEOUT_MS = 1e4, MODELS_ERROR_BODY_LIMIT = 4096, BALANCE_FETCH_TIMEOUT_MS = 8000;
|
|
891
981
|
var init_providers = __esm(() => {
|
|
892
982
|
init_provider_config();
|
|
983
|
+
init_catalog();
|
|
893
984
|
init_grants();
|
|
894
985
|
init_shell_config();
|
|
895
986
|
init_args();
|
|
@@ -8310,6 +8401,7 @@ function makeProvider(name, _model, opts) {
|
|
|
8310
8401
|
if (needsKey && (apiKey === undefined || apiKey.length === 0)) {
|
|
8311
8402
|
return new FakeProvider([]);
|
|
8312
8403
|
}
|
|
8404
|
+
const extraHeaders = extraRequestHeaders(name);
|
|
8313
8405
|
const grant = {
|
|
8314
8406
|
network: true,
|
|
8315
8407
|
...compat.streamUsage === true ? { streamUsage: true } : {},
|
|
@@ -8317,7 +8409,8 @@ function makeProvider(name, _model, opts) {
|
|
|
8317
8409
|
...compat.allowLoopback === true ? { allowLoopback: true } : {},
|
|
8318
8410
|
...compat.allowPrivateLan === true ? { allowPrivateLan: true } : {},
|
|
8319
8411
|
...compat.chatPath !== undefined ? { chatPath: compat.chatPath } : {},
|
|
8320
|
-
...apiKey !== undefined ? { apiKey } : {}
|
|
8412
|
+
...apiKey !== undefined ? { apiKey } : {},
|
|
8413
|
+
...extraHeaders !== undefined ? { headers: extraHeaders } : {}
|
|
8321
8414
|
};
|
|
8322
8415
|
return new OpenAiCompatEngine({ fetch: opts.fetch, grant }, { ...OLLAMA_COMPAT_IDENTITY, providerLabel: compat.label });
|
|
8323
8416
|
}
|
|
@@ -8326,6 +8419,7 @@ function makeProvider(name, _model, opts) {
|
|
|
8326
8419
|
var OLLAMA_COMPAT_IDENTITY;
|
|
8327
8420
|
var init_make_provider = __esm(() => {
|
|
8328
8421
|
init_providers();
|
|
8422
|
+
init_catalog();
|
|
8329
8423
|
init_anthropic_provider();
|
|
8330
8424
|
init_openai_compat_provider();
|
|
8331
8425
|
init_fake_provider();
|
|
@@ -40876,78 +40970,6 @@ async function startStdioTransport(server) {
|
|
|
40876
40970
|
await server.connect(transport);
|
|
40877
40971
|
}
|
|
40878
40972
|
|
|
40879
|
-
// src/lib/oauth/catalog.ts
|
|
40880
|
-
function authCatalogEntry(provider) {
|
|
40881
|
-
return PROVIDER_AUTH_CATALOG.find((entry) => entry.provider === provider);
|
|
40882
|
-
}
|
|
40883
|
-
function catalogMethods(provider) {
|
|
40884
|
-
return authCatalogEntry(provider)?.methods ?? ["api-key"];
|
|
40885
|
-
}
|
|
40886
|
-
function catalogAllows(provider, method) {
|
|
40887
|
-
return catalogMethods(provider).includes(method);
|
|
40888
|
-
}
|
|
40889
|
-
function catalogRefusal(provider) {
|
|
40890
|
-
return authCatalogEntry(provider)?.refusal;
|
|
40891
|
-
}
|
|
40892
|
-
function deviceCodeMethodLabel(provider) {
|
|
40893
|
-
if (provider === "grok")
|
|
40894
|
-
return "SuperGrok Subscription";
|
|
40895
|
-
if (provider === "github-copilot")
|
|
40896
|
-
return "Login with GitHub Copilot";
|
|
40897
|
-
if (provider === "openai")
|
|
40898
|
-
return "ChatGPT Plus/Pro (headless)";
|
|
40899
|
-
return "Device authorization";
|
|
40900
|
-
}
|
|
40901
|
-
var XAI_GROK_DEVICE, GITHUB_COPILOT_DEVICE, PROVIDER_AUTH_CATALOG;
|
|
40902
|
-
var init_catalog = __esm(() => {
|
|
40903
|
-
XAI_GROK_DEVICE = {
|
|
40904
|
-
deviceAuthorizationEndpoint: "https://auth.x.ai/oauth2/device/code",
|
|
40905
|
-
tokenEndpoint: "https://auth.x.ai/oauth2/token",
|
|
40906
|
-
clientId: "b1a00492-073a-47ea-816f-4c329264a828",
|
|
40907
|
-
scope: "openid profile email offline_access grok-cli:access api:access",
|
|
40908
|
-
extraForm: { referrer: "keryx" },
|
|
40909
|
-
headers: { "User-Agent": "keryx" }
|
|
40910
|
-
};
|
|
40911
|
-
GITHUB_COPILOT_DEVICE = {
|
|
40912
|
-
deviceAuthorizationEndpoint: "https://github.com/login/device/code",
|
|
40913
|
-
tokenEndpoint: "https://github.com/login/oauth/access_token",
|
|
40914
|
-
clientId: "Ov23li8tweQw6odWQebz",
|
|
40915
|
-
scope: "read:user",
|
|
40916
|
-
headers: { Accept: "application/json", "User-Agent": "keryx" },
|
|
40917
|
-
afterToken: "github-copilot"
|
|
40918
|
-
};
|
|
40919
|
-
PROVIDER_AUTH_CATALOG = [
|
|
40920
|
-
{
|
|
40921
|
-
provider: "grok",
|
|
40922
|
-
label: "xAI (Grok)",
|
|
40923
|
-
methods: ["device-code", "api-key"],
|
|
40924
|
-
device: XAI_GROK_DEVICE
|
|
40925
|
-
},
|
|
40926
|
-
{
|
|
40927
|
-
provider: "openai",
|
|
40928
|
-
label: "OpenAI",
|
|
40929
|
-
methods: ["oauth-pkce-loopback", "device-code", "api-key"]
|
|
40930
|
-
},
|
|
40931
|
-
{
|
|
40932
|
-
provider: "github-copilot",
|
|
40933
|
-
label: "GitHub Copilot",
|
|
40934
|
-
methods: ["device-code"],
|
|
40935
|
-
device: GITHUB_COPILOT_DEVICE
|
|
40936
|
-
},
|
|
40937
|
-
{ provider: "anthropic", label: "Anthropic", methods: ["api-key"], refusal: "Anthropic does not permit third-party Claude Pro/Max login. Use an API key from the Anthropic Console." },
|
|
40938
|
-
{ provider: "gemini", label: "Google Gemini", methods: ["api-key"], refusal: "Gemini Google-account login is for Gemini CLI. In keryx use GEMINI_API_KEY from Google AI Studio." },
|
|
40939
|
-
{ provider: "deepseek", label: "DeepSeek", methods: ["api-key"], refusal: "DeepSeek has no consumer OAuth grant. Use DEEPSEEK_API_KEY." },
|
|
40940
|
-
{ provider: "openrouter", label: "OpenRouter", methods: ["api-key"] },
|
|
40941
|
-
{ provider: "zai", label: "Z.AI (GLM)", methods: ["api-key"] },
|
|
40942
|
-
{ provider: "zai-coding", label: "Z.AI GLM Coding Plan", methods: ["api-key"] },
|
|
40943
|
-
{ provider: "cerebras", label: "Cerebras", methods: ["api-key"] },
|
|
40944
|
-
{ provider: "groq", label: "Groq", methods: ["api-key"] },
|
|
40945
|
-
{ provider: "moonshot", label: "Moonshot (Kimi)", methods: ["api-key"] },
|
|
40946
|
-
{ provider: "ollama", label: "Ollama", methods: ["none"] },
|
|
40947
|
-
{ provider: "rapid-mlx", label: "Rapid-MLX (Local)", methods: ["none"] }
|
|
40948
|
-
];
|
|
40949
|
-
});
|
|
40950
|
-
|
|
40951
40973
|
// src/lib/oauth/device-code.ts
|
|
40952
40974
|
function requestInit(base, signal) {
|
|
40953
40975
|
return signal === undefined ? base : { ...base, signal };
|
|
@@ -41115,38 +41137,71 @@ var init_device_code = __esm(() => {
|
|
|
41115
41137
|
});
|
|
41116
41138
|
|
|
41117
41139
|
// src/lib/oauth/copilot.ts
|
|
41140
|
+
function expiresInSecondsFrom(rec, now) {
|
|
41141
|
+
if (typeof rec.expires_at === "string") {
|
|
41142
|
+
const expires = Date.parse(rec.expires_at);
|
|
41143
|
+
if (Number.isFinite(expires)) {
|
|
41144
|
+
return Math.max(1, Math.floor((expires - now) / 1000));
|
|
41145
|
+
}
|
|
41146
|
+
}
|
|
41147
|
+
if (typeof rec.expires_at === "number" && Number.isFinite(rec.expires_at)) {
|
|
41148
|
+
const expiresMs = rec.expires_at < 1000000000000 ? rec.expires_at * 1000 : rec.expires_at;
|
|
41149
|
+
return Math.max(1, Math.floor((expiresMs - now) / 1000));
|
|
41150
|
+
}
|
|
41151
|
+
if (typeof rec.refresh_in === "number" && Number.isFinite(rec.refresh_in) && rec.refresh_in > 0) {
|
|
41152
|
+
return Math.floor(rec.refresh_in);
|
|
41153
|
+
}
|
|
41154
|
+
return;
|
|
41155
|
+
}
|
|
41156
|
+
function describeExchangeFailure(status, json, body) {
|
|
41157
|
+
if (typeof json === "object" && json !== null) {
|
|
41158
|
+
const rec = json;
|
|
41159
|
+
if (rec.error_details?.copilot_access_denied === true) {
|
|
41160
|
+
return `GitHub Copilot token exchange failed (HTTP ${status}): Copilot access denied \u2014 check the GitHub Copilot subscription on this account`;
|
|
41161
|
+
}
|
|
41162
|
+
if (typeof rec.message === "string" && rec.message.length > 0) {
|
|
41163
|
+
return `GitHub Copilot token exchange failed (HTTP ${status}): ${rec.message}`;
|
|
41164
|
+
}
|
|
41165
|
+
}
|
|
41166
|
+
if (/zscaler|blocked because it does not comply/i.test(body)) {
|
|
41167
|
+
return `GitHub Copilot token exchange failed (HTTP ${status}): request was blocked by a gateway or proxy`;
|
|
41168
|
+
}
|
|
41169
|
+
return `GitHub Copilot token exchange failed (HTTP ${status})`;
|
|
41170
|
+
}
|
|
41118
41171
|
async function exchangeGithubTokenForCopilot(githubToken, http) {
|
|
41119
41172
|
const init = {
|
|
41120
41173
|
method: "GET",
|
|
41121
41174
|
headers: {
|
|
41122
|
-
|
|
41123
|
-
|
|
41124
|
-
"User-Agent": "keryx"
|
|
41175
|
+
...GITHUB_COPILOT_REQUEST_HEADERS,
|
|
41176
|
+
Authorization: `token ${githubToken}`
|
|
41125
41177
|
}
|
|
41126
41178
|
};
|
|
41127
41179
|
if (http.signal !== undefined) {
|
|
41128
41180
|
init.signal = http.signal;
|
|
41129
41181
|
}
|
|
41130
41182
|
const response = await http.fetch(COPILOT_TOKEN_URL, init);
|
|
41131
|
-
const
|
|
41183
|
+
const body = await response.text().catch(() => "");
|
|
41184
|
+
let json = {};
|
|
41185
|
+
if (body.length > 0) {
|
|
41186
|
+
try {
|
|
41187
|
+
json = JSON.parse(body);
|
|
41188
|
+
} catch {
|
|
41189
|
+
json = {};
|
|
41190
|
+
}
|
|
41191
|
+
}
|
|
41132
41192
|
if (!response.ok || typeof json !== "object" || json === null) {
|
|
41133
|
-
throw new DeviceCodeError("failed",
|
|
41193
|
+
throw new DeviceCodeError("failed", describeExchangeFailure(response.status, json, body));
|
|
41134
41194
|
}
|
|
41135
41195
|
const rec = json;
|
|
41136
41196
|
if (typeof rec.token !== "string" || rec.token.length === 0) {
|
|
41137
41197
|
throw new DeviceCodeError("failed", "GitHub Copilot token exchange returned no token");
|
|
41138
41198
|
}
|
|
41139
|
-
|
|
41140
|
-
if (typeof rec.expires_at === "string") {
|
|
41141
|
-
const expires = Date.parse(rec.expires_at);
|
|
41142
|
-
if (Number.isFinite(expires)) {
|
|
41143
|
-
expiresInSeconds = Math.max(1, Math.floor((expires - Date.now()) / 1000));
|
|
41144
|
-
}
|
|
41145
|
-
}
|
|
41199
|
+
const expiresInSeconds = expiresInSecondsFrom(rec, Date.now());
|
|
41146
41200
|
return { accessToken: rec.token, ...expiresInSeconds !== undefined ? { expiresInSeconds } : {} };
|
|
41147
41201
|
}
|
|
41148
41202
|
var COPILOT_TOKEN_URL = "https://api.github.com/copilot_internal/v2/token";
|
|
41149
41203
|
var init_copilot = __esm(() => {
|
|
41204
|
+
init_catalog();
|
|
41150
41205
|
init_device_code();
|
|
41151
41206
|
});
|
|
41152
41207
|
|
|
@@ -48173,7 +48228,7 @@ import path47 from "path";
|
|
|
48173
48228
|
// package.json
|
|
48174
48229
|
var package_default = {
|
|
48175
48230
|
name: "@mrciphersmith/keryx",
|
|
48176
|
-
version: "0.2.
|
|
48231
|
+
version: "0.2.101",
|
|
48177
48232
|
description: "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
48178
48233
|
private: false,
|
|
48179
48234
|
publishConfig: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mrciphersmith/keryx",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.101",
|
|
4
4
|
"description": "Version-controlled project context for AI coding agents: code graph, architecture wiki, project memory, relevant tests, quality signals, and task flows.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|