@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.
Files changed (2) hide show
  1. package/dist/cli.js +142 -87
  2. 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
- init.headers = { authorization: `Bearer ${apiKey}` };
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
- Authorization: `token ${githubToken}`,
41123
- Accept: "application/json",
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 json = await response.json().catch(() => ({}));
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", `GitHub Copilot token exchange failed (HTTP ${response.status})`);
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
- let expiresInSeconds;
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.100",
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.100",
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": {