@prestyj/core 5.28.0 → 5.29.0

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
@@ -69,7 +69,7 @@ __export(index_exports, {
69
69
  getContextWindow: () => getContextWindow,
70
70
  getDefaultModel: () => getDefaultModel,
71
71
  getDefaultThinkingLevel: () => getDefaultThinkingLevel,
72
- getFastModel: () => getFastModel,
72
+ getLowestThinkingLevel: () => getLowestThinkingLevel,
73
73
  getMaxThinkingLevel: () => getMaxThinkingLevel,
74
74
  getModel: () => getModel,
75
75
  getModelsForProvider: () => getModelsForProvider,
@@ -152,6 +152,12 @@ function getAppPaths() {
152
152
  };
153
153
  }
154
154
 
155
+ // src/oauth/request-timeout.ts
156
+ var OAUTH_REQUEST_TIMEOUT_MS = 3e4;
157
+ function oauthRequestSignal() {
158
+ return AbortSignal.timeout(OAUTH_REQUEST_TIMEOUT_MS);
159
+ }
160
+
155
161
  // src/oauth/kimi.ts
156
162
  var CLIENT_ID = "17e5f671-d194-4dfb-9706-5516cb48c098";
157
163
  var DEFAULT_OAUTH_HOST = "https://auth.kimi.com";
@@ -239,7 +245,8 @@ async function postForm(endpoint, params) {
239
245
  "Content-Type": "application/x-www-form-urlencoded",
240
246
  Accept: "application/json"
241
247
  },
242
- body: new URLSearchParams(params).toString()
248
+ body: new URLSearchParams(params).toString(),
249
+ signal: oauthRequestSignal()
243
250
  });
244
251
  let data = {};
245
252
  try {
@@ -713,7 +720,12 @@ async function postTokenRequest(body, label) {
713
720
  for (const url of TOKEN_URLS) {
714
721
  let response;
715
722
  try {
716
- response = await fetch(url, { method: "POST", headers, body: encoded });
723
+ response = await fetch(url, {
724
+ method: "POST",
725
+ headers,
726
+ body: encoded,
727
+ signal: oauthRequestSignal()
728
+ });
717
729
  } catch (err) {
718
730
  lastError = err instanceof Error ? err : new Error(String(err));
719
731
  continue;
@@ -962,7 +974,8 @@ async function exchangeOpenAICode(code, verifier) {
962
974
  code,
963
975
  redirect_uri: REDIRECT_URI2,
964
976
  code_verifier: verifier
965
- })
977
+ }),
978
+ signal: oauthRequestSignal()
966
979
  });
967
980
  if (!response.ok) {
968
981
  const text = await response.text();
@@ -983,7 +996,8 @@ async function refreshOpenAIToken(refreshToken) {
983
996
  grant_type: "refresh_token",
984
997
  refresh_token: refreshToken,
985
998
  client_id: CLIENT_ID3
986
- })
999
+ }),
1000
+ signal: oauthRequestSignal()
987
1001
  });
988
1002
  if (!response.ok) {
989
1003
  const text = await response.text();
@@ -1193,7 +1207,8 @@ async function postTokenRequest2(body) {
1193
1207
  const response = await fetch(TOKEN_URL2, {
1194
1208
  method: "POST",
1195
1209
  headers: { "Content-Type": "application/x-www-form-urlencoded" },
1196
- body: new URLSearchParams(body)
1210
+ body: new URLSearchParams(body),
1211
+ signal: oauthRequestSignal()
1197
1212
  });
1198
1213
  if (!response.ok) {
1199
1214
  const text = await response.text();
@@ -1322,7 +1337,8 @@ async function codeAssistGet(accessToken, operationName) {
1322
1337
  async function codeAssistRequest(url, accessToken, label, init) {
1323
1338
  const response = await fetch(url, {
1324
1339
  ...init,
1325
- headers: codeAssistHeaders(accessToken)
1340
+ headers: codeAssistHeaders(accessToken),
1341
+ signal: oauthRequestSignal()
1326
1342
  });
1327
1343
  if (!response.ok) {
1328
1344
  const text = await response.text();
@@ -1408,7 +1424,8 @@ async function postForm2(endpoint, params) {
1408
1424
  Accept: "application/json",
1409
1425
  "User-Agent": `grok-cli/${grokCliVersion()}`
1410
1426
  },
1411
- body: new URLSearchParams(params).toString()
1427
+ body: new URLSearchParams(params).toString(),
1428
+ signal: oauthRequestSignal()
1412
1429
  });
1413
1430
  let data = {};
1414
1431
  try {
@@ -2244,7 +2261,7 @@ var MODELS = [
2244
2261
  // ── OpenAI (Codex) ─────────────────────────────────────
2245
2262
  {
2246
2263
  // GPT-6 Astra — "Our most capable model for complex, demanding work."
2247
- // (Codex catalog priority 1, listed for every ChatGPT plan, requires a
2264
+ // (Codex catalog priority 2, listed for every ChatGPT plan, requires a
2248
2265
  // Codex client >= 0.153.0 — see CODEX_CLIENT_VERSION). Same split as 5.6:
2249
2266
  // 1.05M on the public Responses API, 272K on the ChatGPT OAuth route
2250
2267
  // (openai/codex models.json, `gpt-6-astra`). Reasoning ladder low → medium
@@ -2268,32 +2285,36 @@ var MODELS = [
2268
2285
  },
2269
2286
  // GPT-6 Sol + Luna — released 2026-09-22 below Astra, replacing the whole
2270
2287
  // GPT-5.6 family (Sol/Terra/Luna; there is no GPT-6 Terra — OpenAI's Codex
2271
- // catalog upgrades 5.6 Terra to 6 Sol). Both need a Codex client >= 0.155.0
2272
- // on the ChatGPT OAuth route. Same window split as Astra: 1.05M on the public
2273
- // Responses API, 272K on the Codex route; 128K output, text+image input,
2274
- // freeform apply_patch, responses-lite transport. The 5.6 ids are retired —
2275
- // a saved session on one falls back to the provider default on next start.
2288
+ // catalog upgrades 5.6 Terra to 6 Sol). GPT-6.1 Sol (2026-09-29) then replaced
2289
+ // GPT-6 Sol. Same window split as Astra: 1.05M on the public Responses API,
2290
+ // 272K on the Codex route; 128K output, text+image input, freeform
2291
+ // apply_patch, responses-lite transport. The GPT-5.6 ids and `gpt-6-sol` are
2292
+ // retired — a saved session on one falls back to the provider default on
2293
+ // next start.
2276
2294
  {
2277
- // Sol — "Workhorse model for coding and everyday work." (Codex priority 2,
2278
- // default medium). $2/$10 MTok. Ladder low → medium → high → xhigh → max →
2279
- // ultra; ultra is the Codex orchestration preset (max effort on the wire +
2280
- // proactive local subagent delegation).
2281
- id: "gpt-6-sol",
2282
- name: "GPT-6 Sol",
2295
+ // GPT-6.1 Sol — "Latest workhorse model for coding and everyday work."
2296
+ // (Codex priority 1, default low). The catalog says Codex client >= 0.153.0,
2297
+ // but the ChatGPT backend only serves it from 0.159.0 (see
2298
+ // CODEX_CLIENT_VERSION). $2/$10 MTok, cached input $0.10. Ladder low →
2299
+ // medium → high → xhigh → max → ultra; ultra is the Codex orchestration
2300
+ // preset (max effort on the wire + proactive local subagent delegation).
2301
+ id: "gpt-6.1-sol",
2302
+ name: "GPT-6.1 Sol",
2283
2303
  provider: "openai",
2284
2304
  contextWindow: 105e4,
2285
2305
  codexContextWindow: 272e3,
2286
2306
  maxOutputTokens: 128e3,
2287
2307
  supportsThinking: true,
2288
- defaultThinkingLevel: "medium",
2308
+ defaultThinkingLevel: "low",
2289
2309
  supportsImages: true,
2290
2310
  supportsVideo: false,
2291
2311
  costTier: "medium",
2292
2312
  maxThinkingLevel: "ultra"
2293
2313
  },
2294
2314
  {
2295
- // Luna — "Fast and affordable model for easier tasks." (Codex priority 3,
2296
- // default medium). $0.10/$0.50 MTok. Reasoning tops out at `max`.
2315
+ // Luna — "Fast and affordable model for easier tasks." (Codex priority 4,
2316
+ // default medium, needs a Codex client >= 0.155.0). $0.10/$0.50 MTok.
2317
+ // Reasoning tops out at `max`.
2297
2318
  id: "gpt-6-luna",
2298
2319
  name: "GPT-6 Luna",
2299
2320
  provider: "openai",
@@ -2426,9 +2447,7 @@ var MODELS = [
2426
2447
  // Sent over our Code Assist (OAuth) transport ahead of gemini-cli — upstream
2427
2448
  // hasn't listed 3.7 yet (google-gemini/gemini-cli#28802, still open) — so
2428
2449
  // free/personal accounts 404 (entitlement-gated) while Code Assist
2429
- // Standard/Enterprise accounts get it. Kept after the working flash-lite:
2430
- // getFastModel picks the first low-tier entry, and flash-lite is the one
2431
- // that works on every account.
2450
+ // Standard/Enterprise accounts get it.
2432
2451
  id: "gemini-3.7-flash",
2433
2452
  name: "Gemini 3.7 Flash",
2434
2453
  provider: "gemini",
@@ -2789,7 +2808,7 @@ function getVideoByteLimit(modelId) {
2789
2808
  }
2790
2809
  function getDefaultModel(provider) {
2791
2810
  if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.6-pro");
2792
- if (provider === "openai") return MODELS.find((m) => m.id === "gpt-6-sol");
2811
+ if (provider === "openai") return MODELS.find((m) => m.id === "gpt-6.1-sol");
2793
2812
  if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite");
2794
2813
  if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.3");
2795
2814
  if (provider === "moonshot") return MODELS.find((m) => m.id === "kimi-k3");
@@ -2839,19 +2858,17 @@ function getDefaultThinkingLevel(modelId, options) {
2839
2858
  if (model?.id === "kimi-k3" && isKimiCodingEndpoint(options?.baseUrl)) return "high";
2840
2859
  return model?.defaultThinkingLevel ?? model?.maxThinkingLevel ?? "high";
2841
2860
  }
2861
+ var SUMMARY_COST_TIER = {
2862
+ anthropic: "medium",
2863
+ openai: "low",
2864
+ glm: "low",
2865
+ deepseek: "low",
2866
+ huggingface: "low"
2867
+ };
2842
2868
  function getSummaryModel(provider, currentModelId) {
2843
- if (provider === "anthropic") {
2844
- return MODELS.find((m) => m.id === "claude-sonnet-5-5");
2845
- }
2846
- if (provider === "openai" || provider === "glm" || provider === "deepseek" || provider === "huggingface") {
2847
- const low = getModelsForProvider(provider).find((m) => m.costTier === "low");
2848
- if (low) return low;
2849
- }
2850
- return getModel(currentModelId) ?? getDefaultModel(provider);
2851
- }
2852
- function getFastModel(provider, currentModelId) {
2853
- const low = getModelsForProvider(provider).find((m) => m.costTier === "low");
2854
- return low ?? getModel(currentModelId) ?? getDefaultModel(provider);
2869
+ const tier = SUMMARY_COST_TIER[provider];
2870
+ const tagged = tier ? getModelsForProvider(provider).find((m) => m.costTier === tier) : void 0;
2871
+ return tagged ?? getModel(currentModelId) ?? getDefaultModel(provider);
2855
2872
  }
2856
2873
 
2857
2874
  // src/thinking-level.ts
@@ -2936,11 +2953,15 @@ function getSupportedThinkingLevels(provider, model) {
2936
2953
  return GLM_THINKING_LEVELS.slice(0, maxIndex2 + 1);
2937
2954
  }
2938
2955
  if (!isOpenAIGptModel(provider, model)) return [maxLevel];
2939
- const levels = model.startsWith("gpt-5.6-") || model.startsWith("gpt-6-") ? OPENAI_GPT_56_THINKING_LEVELS : OPENAI_GPT_THINKING_LEVELS;
2956
+ const levels = model.startsWith("gpt-5.6-") || model.startsWith("gpt-6-") || model.startsWith("gpt-6.") ? OPENAI_GPT_56_THINKING_LEVELS : OPENAI_GPT_THINKING_LEVELS;
2940
2957
  const maxIndex = levels.indexOf(maxLevel);
2941
2958
  if (maxIndex === -1) return ["medium"];
2942
2959
  return levels.slice(0, maxIndex + 1);
2943
2960
  }
2961
+ function getLowestThinkingLevel(provider, model) {
2962
+ if (getModel(model)?.supportsThinking === false) return void 0;
2963
+ return getSupportedThinkingLevels(provider, model)[0];
2964
+ }
2944
2965
  function isThinkingLevelSupported(provider, model, level) {
2945
2966
  return getSupportedThinkingLevels(provider, model).includes(level);
2946
2967
  }
@@ -3488,12 +3509,16 @@ async function fetchSubscriptionUsage(provider, credentials, options = {}) {
3488
3509
 
3489
3510
  // src/telegram.ts
3490
3511
  var TELEGRAM_API = "https://api.telegram.org";
3512
+ var LONG_POLL_SECONDS = 30;
3513
+ var API_TIMEOUT_MS = 3e4;
3491
3514
  var MAX_MESSAGE_LENGTH = 4096;
3492
3515
  var TelegramBot = class {
3493
3516
  token;
3494
3517
  allowedUserId;
3495
3518
  offset = 0;
3496
3519
  running = false;
3520
+ /** Aborts the in-flight long poll so stop() takes effect immediately. */
3521
+ pollAbort = null;
3497
3522
  onMessage = null;
3498
3523
  onVoiceMessage = null;
3499
3524
  onCallback = null;
@@ -3546,6 +3571,7 @@ var TelegramBot = class {
3546
3571
  /** Stop long polling. */
3547
3572
  stop() {
3548
3573
  this.running = false;
3574
+ this.pollAbort?.abort();
3549
3575
  }
3550
3576
  /** Send a text message to a specific chat. Converts markdown and splits long messages. */
3551
3577
  async send(chatId, text, buttons) {
@@ -3592,12 +3618,26 @@ var TelegramBot = class {
3592
3618
  }
3593
3619
  // ── Private ───────────────────────────────────────────
3594
3620
  async getUpdates() {
3595
- const result = await this.apiCall("getUpdates", {
3596
- offset: this.offset,
3597
- timeout: 30,
3598
- allowed_updates: ["message", "callback_query", "my_chat_member"]
3599
- });
3600
- if (!result.ok || !Array.isArray(result.result)) return [];
3621
+ const poll = new AbortController();
3622
+ this.pollAbort = poll;
3623
+ let result;
3624
+ try {
3625
+ result = await this.apiCall(
3626
+ "getUpdates",
3627
+ {
3628
+ offset: this.offset,
3629
+ timeout: LONG_POLL_SECONDS,
3630
+ allowed_updates: ["message", "callback_query", "my_chat_member"]
3631
+ },
3632
+ // A half-open socket would otherwise hang the poll forever.
3633
+ AbortSignal.any([poll.signal, AbortSignal.timeout((LONG_POLL_SECONDS + 15) * 1e3)])
3634
+ );
3635
+ } finally {
3636
+ if (this.pollAbort === poll) this.pollAbort = null;
3637
+ }
3638
+ if (!result.ok || !Array.isArray(result.result)) {
3639
+ throw new Error(`getUpdates failed: ${JSON.stringify(result)}`);
3640
+ }
3601
3641
  const updates = result.result;
3602
3642
  if (updates.length > 0) {
3603
3643
  this.offset = updates[updates.length - 1].update_id + 1;
@@ -3645,12 +3685,13 @@ var TelegramBot = class {
3645
3685
  }
3646
3686
  }
3647
3687
  }
3648
- async apiCall(method, body) {
3688
+ async apiCall(method, body, signal = AbortSignal.timeout(API_TIMEOUT_MS)) {
3649
3689
  const url = `${TELEGRAM_API}/bot${this.token}/${method}`;
3650
3690
  const response = await fetch(url, {
3651
3691
  method: "POST",
3652
3692
  headers: { "Content-Type": "application/json" },
3653
- body: body ? JSON.stringify(body) : void 0
3693
+ body: body ? JSON.stringify(body) : void 0,
3694
+ signal
3654
3695
  });
3655
3696
  if (!response.ok) {
3656
3697
  return { ok: false };
@@ -3783,7 +3824,7 @@ function isModelLoaded() {
3783
3824
  return transcriber !== null;
3784
3825
  }
3785
3826
  async function transcribeVoice(fileUrl) {
3786
- const response = await fetch(fileUrl);
3827
+ const response = await fetch(fileUrl, { signal: AbortSignal.timeout(6e4) });
3787
3828
  if (!response.ok) throw new Error(`Failed to download voice file: ${response.status}`);
3788
3829
  const buffer = new Uint8Array(await response.arrayBuffer());
3789
3830
  const pcm = await decodeOggOpus(buffer);
@@ -4002,7 +4043,7 @@ function createAutoUpdater(config) {
4002
4043
  getContextWindow,
4003
4044
  getDefaultModel,
4004
4045
  getDefaultThinkingLevel,
4005
- getFastModel,
4046
+ getLowestThinkingLevel,
4006
4047
  getMaxThinkingLevel,
4007
4048
  getModel,
4008
4049
  getModelsForProvider,