@kenkaiiii/gg-core 5.91.0 → 5.91.1

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/index.cjs CHANGED
@@ -45,6 +45,7 @@ __export(index_exports, {
45
45
  MODELS: () => MODELS,
46
46
  MOONSHOT_OAUTH_KEY: () => MOONSHOT_OAUTH_KEY,
47
47
  NotLoggedInError: () => NotLoggedInError,
48
+ OPENROUTER_DEFAULT_BASE_URL: () => OPENROUTER_DEFAULT_BASE_URL,
48
49
  PLAN_MODE_THINKING_CAP: () => PLAN_MODE_THINKING_CAP,
49
50
  SubscriptionUsageError: () => SubscriptionUsageError,
50
51
  TelegramBot: () => TelegramBot,
@@ -86,6 +87,7 @@ __export(index_exports, {
86
87
  getModel: () => getModel,
87
88
  getModelsForProvider: () => getModelsForProvider,
88
89
  getNextThinkingLevel: () => getNextThinkingLevel,
90
+ getProviderCatalog: () => getProviderCatalog,
89
91
  getSessionId: () => getSessionId,
90
92
  getSummaryModel: () => getSummaryModel,
91
93
  getSupportedThinkingLevels: () => getSupportedThinkingLevels,
@@ -115,6 +117,7 @@ __export(index_exports, {
115
117
  ollamaServedContext: () => ollamaServedContext,
116
118
  openLog: () => openLog,
117
119
  parseLocalModelId: () => parseLocalModelId,
120
+ parseOpenRouterCatalog: () => parseOpenRouterCatalog,
118
121
  pendingClaudeCodeVersionRefresh: () => import_gg_ai.pendingClaudeCodeVersionRefresh,
119
122
  probeEndpoint: () => probeEndpoint,
120
123
  providerStorageKeys: () => providerStorageKeys,
@@ -128,6 +131,7 @@ __export(index_exports, {
128
131
  registerRuntimeModels: () => registerRuntimeModels,
129
132
  resample: () => resample,
130
133
  setProgressCallback: () => setProgressCallback,
134
+ setProviderCatalog: () => setProviderCatalog,
131
135
  toModelInfo: () => toModelInfo,
132
136
  transcribeVoice: () => transcribeVoice,
133
137
  usesOpenAICodexTransport: () => usesOpenAICodexTransport,
@@ -1334,9 +1338,13 @@ async function acquireLock(lockPath) {
1334
1338
  continue;
1335
1339
  }
1336
1340
  } catch {
1337
- await import_promises.default.unlink(lockPath).catch(() => {
1338
- });
1339
- continue;
1341
+ const stat = await import_promises.default.stat(lockPath).catch(() => null);
1342
+ if (!stat) continue;
1343
+ if (Date.now() - stat.mtimeMs > STALE_TIMEOUT_MS) {
1344
+ await import_promises.default.unlink(lockPath).catch(() => {
1345
+ });
1346
+ continue;
1347
+ }
1340
1348
  }
1341
1349
  if (Date.now() - startTime > MAX_WAIT_MS) {
1342
1350
  await import_promises.default.unlink(lockPath).catch(() => {
@@ -2960,11 +2968,44 @@ function clearRuntimeModels(predicate) {
2960
2968
  if (predicate(model)) runtimeModels.delete(id);
2961
2969
  }
2962
2970
  }
2971
+ var providerCatalogs = /* @__PURE__ */ new Map();
2972
+ function setProviderCatalog(provider, models) {
2973
+ if (!models) {
2974
+ providerCatalogs.delete(provider);
2975
+ return [];
2976
+ }
2977
+ const installed = /* @__PURE__ */ new Map();
2978
+ for (const model of models) {
2979
+ if (model.provider !== provider) continue;
2980
+ if (MODELS.some((m) => m.id === model.id && m.provider !== provider)) continue;
2981
+ installed.set(model.id, model);
2982
+ }
2983
+ providerCatalogs.set(provider, installed);
2984
+ return [...installed.values()];
2985
+ }
2986
+ function getProviderCatalog(provider) {
2987
+ const catalog = providerCatalogs.get(provider);
2988
+ return catalog ? [...catalog.values()] : void 0;
2989
+ }
2963
2990
  function getAllModels() {
2964
- return [...MODELS, ...runtimeModels.values()];
2991
+ const synced = [...providerCatalogs.values()].flatMap((c) => [...c.values()]);
2992
+ return [
2993
+ ...MODELS.filter((m) => !providerCatalogs.has(m.provider)),
2994
+ ...synced,
2995
+ ...runtimeModels.values()
2996
+ ];
2965
2997
  }
2966
2998
  function getModel(id) {
2967
- return MODELS.find((m) => m.id === id) ?? runtimeModels.get(id);
2999
+ const fixed = MODELS.find((m) => m.id === id);
3000
+ if (fixed && !providerCatalogs.has(fixed.provider)) return fixed;
3001
+ return findSynced(id) ?? fixed ?? runtimeModels.get(id);
3002
+ }
3003
+ function findSynced(id) {
3004
+ for (const catalog of providerCatalogs.values()) {
3005
+ const hit = catalog.get(id);
3006
+ if (hit) return hit;
3007
+ }
3008
+ return void 0;
2968
3009
  }
2969
3010
  function getModelsForProvider(provider) {
2970
3011
  return getAllModels().filter((m) => m.provider === provider);
@@ -3070,6 +3111,59 @@ function getSummaryModel(provider, currentModelId) {
3070
3111
  return tagged ?? getModel(currentModelId) ?? getDefaultModel(provider);
3071
3112
  }
3072
3113
 
3114
+ // src/openrouter-catalog.ts
3115
+ var OPENROUTER_DEFAULT_BASE_URL = "https://openrouter.ai/api/v1";
3116
+ var EFFORT_LADDER = ["low", "medium", "high", "xhigh", "max"];
3117
+ function positiveInt(value) {
3118
+ return typeof value === "number" && Number.isSafeInteger(value) && value > 0 ? value : void 0;
3119
+ }
3120
+ function strings(value) {
3121
+ return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
3122
+ }
3123
+ function costTier(prompt) {
3124
+ const perToken = typeof prompt === "string" ? Number(prompt) : NaN;
3125
+ if (!Number.isFinite(perToken) || perToken < 5e-7) return "low";
3126
+ return perToken < 3e-6 ? "medium" : "high";
3127
+ }
3128
+ function parseOpenRouterCatalog(body) {
3129
+ const data = body?.data;
3130
+ if (!Array.isArray(data)) return { models: [], skipped: 0 };
3131
+ const models = [];
3132
+ let skipped = 0;
3133
+ const seen = /* @__PURE__ */ new Set();
3134
+ for (const raw of data) {
3135
+ const id = typeof raw?.id === "string" ? raw.id.trim() : "";
3136
+ const params = strings(raw?.supported_parameters);
3137
+ const contextWindow = positiveInt(raw?.top_provider?.context_length) ?? positiveInt(raw?.context_length);
3138
+ if (!id || seen.has(id) || !params.includes("tools") || !contextWindow) {
3139
+ skipped++;
3140
+ continue;
3141
+ }
3142
+ seen.add(id);
3143
+ const efforts = strings(raw.reasoning?.supported_efforts);
3144
+ const ladder = EFFORT_LADDER.filter((rung) => efforts.includes(rung));
3145
+ const supportsThinking = ladder.length > 0 || params.includes("reasoning") || params.includes("reasoning_effort");
3146
+ const defaultEffort = raw.reasoning?.default_effort;
3147
+ const maxOutput = positiveInt(raw.top_provider?.max_completion_tokens) ?? Math.min(contextWindow, 16384);
3148
+ models.push({
3149
+ id,
3150
+ name: typeof raw.name === "string" && raw.name.trim() ? raw.name.trim() : id,
3151
+ provider: "openrouter",
3152
+ contextWindow,
3153
+ maxOutputTokens: Math.min(maxOutput, contextWindow),
3154
+ supportsThinking,
3155
+ supportsImages: strings(raw.architecture?.input_modalities).includes("image"),
3156
+ // Video needs a per-transport payload cap the catalog doesn't publish.
3157
+ supportsVideo: false,
3158
+ costTier: costTier(raw.pricing?.prompt),
3159
+ maxThinkingLevel: ladder[ladder.length - 1] ?? "high",
3160
+ ...ladder.length > 0 ? { thinkingLevels: ladder } : {},
3161
+ ...typeof defaultEffort === "string" && ladder.includes(defaultEffort) ? { defaultThinkingLevel: defaultEffort } : {}
3162
+ });
3163
+ }
3164
+ return { models, skipped };
3165
+ }
3166
+
3073
3167
  // src/thinking-level.ts
3074
3168
  var OPENAI_GPT_THINKING_LEVELS = ["medium", "high", "xhigh"];
3075
3169
  var OPENAI_GPT_56_THINKING_LEVELS = [
@@ -3137,6 +3231,8 @@ function getSupportedThinkingLevels(provider, model) {
3137
3231
  const maxIndex2 = LOCAL_THINKING_LEVELS.indexOf(info.maxThinkingLevel);
3138
3232
  return maxIndex2 === -1 ? LOCAL_THINKING_LEVELS.slice(0, 3) : LOCAL_THINKING_LEVELS.slice(0, maxIndex2 + 1);
3139
3233
  }
3234
+ const declared = getModel(model)?.thinkingLevels;
3235
+ if (declared && declared.length > 0) return declared;
3140
3236
  const maxLevel = getMaxThinkingLevel(model);
3141
3237
  if (isAnthropicAdaptiveModel(provider, model)) {
3142
3238
  const levels2 = isAnthropicXhighModel(provider, model) ? ANTHROPIC_XHIGH_THINKING_LEVELS : ANTHROPIC_ADAPTIVE_THINKING_LEVELS;
@@ -3292,7 +3388,9 @@ async function probeEndpoint(endpoint, { timeoutMs = DEFAULT_PROBE_TIMEOUT_MS, s
3292
3388
  const entries = (list.data ?? []).filter(
3293
3389
  (entry) => typeof entry.id === "string" && entry.id.length > 0 && !NON_CHAT_ID_PATTERN.test(entry.id)
3294
3390
  );
3295
- const models = await enrich(endpoint, entries, { timeoutMs, signal });
3391
+ const enriched = await enrich(endpoint, entries, { timeoutMs, signal });
3392
+ const pinned = contextLength(endpoint.contextLength);
3393
+ const models = pinned === void 0 ? enriched : enriched.map((m) => ({ ...m, contextWindow: pinned, contextWindowKnown: true }));
3296
3394
  log("INFO", "local-models", `Probed ${endpoint.label}`, {
3297
3395
  baseUrl: endpoint.baseUrl,
3298
3396
  models: String(models.length)
@@ -3318,7 +3416,7 @@ async function enrichCustom(endpoint, entries, options) {
3318
3416
  return generic;
3319
3417
  }
3320
3418
  function genericModel(endpoint, entry) {
3321
- const declared = contextLength(entry.max_model_len) ?? contextLength(entry.context_length);
3419
+ const declared = contextLength(entry.max_model_len) ?? contextLength(entry.context_length) ?? contextLength(entry.meta?.n_ctx);
3322
3420
  return {
3323
3421
  rawId: entry.id,
3324
3422
  endpointId: endpoint.id,
@@ -3498,7 +3596,7 @@ function toModelInfo(model, endpoint) {
3498
3596
  }
3499
3597
  var cache;
3500
3598
  function cacheKey(endpoints) {
3501
- return endpoints.map((e) => `${e.id}@${e.baseUrl}`).join("|");
3599
+ return endpoints.map((e) => `${e.id}@${e.baseUrl}#${e.contextLength ?? ""}`).join("|");
3502
3600
  }
3503
3601
  async function discoverLocalModels(endpoints = DEFAULT_LOCAL_ENDPOINTS, options = {}) {
3504
3602
  const key = cacheKey(endpoints);
@@ -4457,6 +4555,7 @@ function createAutoUpdater(config) {
4457
4555
  MODELS,
4458
4556
  MOONSHOT_OAUTH_KEY,
4459
4557
  NotLoggedInError,
4558
+ OPENROUTER_DEFAULT_BASE_URL,
4460
4559
  PLAN_MODE_THINKING_CAP,
4461
4560
  SubscriptionUsageError,
4462
4561
  TelegramBot,
@@ -4498,6 +4597,7 @@ function createAutoUpdater(config) {
4498
4597
  getModel,
4499
4598
  getModelsForProvider,
4500
4599
  getNextThinkingLevel,
4600
+ getProviderCatalog,
4501
4601
  getSessionId,
4502
4602
  getSummaryModel,
4503
4603
  getSupportedThinkingLevels,
@@ -4527,6 +4627,7 @@ function createAutoUpdater(config) {
4527
4627
  ollamaServedContext,
4528
4628
  openLog,
4529
4629
  parseLocalModelId,
4630
+ parseOpenRouterCatalog,
4530
4631
  pendingClaudeCodeVersionRefresh,
4531
4632
  probeEndpoint,
4532
4633
  providerStorageKeys,
@@ -4540,6 +4641,7 @@ function createAutoUpdater(config) {
4540
4641
  registerRuntimeModels,
4541
4642
  resample,
4542
4643
  setProgressCallback,
4644
+ setProviderCatalog,
4543
4645
  toModelInfo,
4544
4646
  transcribeVoice,
4545
4647
  usesOpenAICodexTransport,