@prestyj/core 5.25.0 → 5.26.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
@@ -48,6 +48,7 @@ __export(index_exports, {
48
48
  clearLocalDiscoveryCache: () => clearLocalDiscoveryCache,
49
49
  clearRuntimeModels: () => clearRuntimeModels,
50
50
  closeLogger: () => closeLogger,
51
+ compareClaudeCodeVersions: () => compareClaudeCodeVersions,
51
52
  createAutoUpdater: () => createAutoUpdater,
52
53
  decodeOggOpus: () => decodeOggOpus,
53
54
  discoverLocalModels: () => discoverLocalModels,
@@ -101,6 +102,7 @@ __export(index_exports, {
101
102
  probeEndpoint: () => probeEndpoint,
102
103
  providerStorageKeys: () => providerStorageKeys,
103
104
  readStoredBaseUrlSync: () => readStoredBaseUrlSync,
105
+ recordRequiredClaudeCodeVersion: () => recordRequiredClaudeCodeVersion,
104
106
  refreshAnthropicToken: () => refreshAnthropicToken,
105
107
  refreshGeminiToken: () => refreshGeminiToken,
106
108
  refreshKimiToken: () => refreshKimiToken,
@@ -365,7 +367,7 @@ async function refreshKimiToken(refreshToken) {
365
367
 
366
368
  // src/auth-storage.ts
367
369
  var import_promises4 = __toESM(require("fs/promises"), 1);
368
- var import_node_fs3 = require("fs");
370
+ var import_node_fs4 = require("fs");
369
371
  var import_node_crypto6 = __toESM(require("crypto"), 1);
370
372
 
371
373
  // src/oauth/anthropic.ts
@@ -391,6 +393,7 @@ async function generatePKCE() {
391
393
 
392
394
  // src/claude-code-version.ts
393
395
  var import_promises = __toESM(require("fs/promises"), 1);
396
+ var import_node_fs3 = require("fs");
394
397
  var import_node_path4 = __toESM(require("path"), 1);
395
398
 
396
399
  // src/logger.ts
@@ -518,19 +521,41 @@ function closeLogger(opts) {
518
521
 
519
522
  // src/claude-code-version.ts
520
523
  var NPM_LATEST_URL = "https://registry.npmjs.org/@anthropic-ai/claude-code/latest";
521
- var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
524
+ var CACHE_FRESH_MS = 60 * 60 * 1e3;
525
+ var CACHE_HARD_MS = 24 * 60 * 60 * 1e3;
522
526
  var FETCH_TIMEOUT_MS = 3e3;
523
- var FALLBACK_VERSION = "2.1.88";
527
+ var FALLBACK_VERSION = "2.1.280";
524
528
  var memoryCache = null;
525
529
  var inflight = null;
530
+ var backgroundRefresh = null;
531
+ var versionFloor = null;
526
532
  function cachePath() {
527
533
  return import_node_path4.default.join(getAppPaths().agentDir, "claude-code-version.json");
528
534
  }
535
+ function compareClaudeCodeVersions(a, b) {
536
+ const parse = (v) => v.split(".").map((part) => Number.parseInt(part, 10)).map((n) => Number.isFinite(n) ? n : 0);
537
+ const left = parse(a);
538
+ const right = parse(b);
539
+ for (let i = 0; i < Math.max(left.length, right.length); i += 1) {
540
+ const diff = (left[i] ?? 0) - (right[i] ?? 0);
541
+ if (diff !== 0) return diff;
542
+ }
543
+ return 0;
544
+ }
545
+ function applyFloor(version) {
546
+ if (!versionFloor) return version;
547
+ return compareClaudeCodeVersions(versionFloor, version) > 0 ? versionFloor : version;
548
+ }
529
549
  async function readDiskCache() {
530
550
  try {
531
551
  const raw = await import_promises.default.readFile(cachePath(), "utf-8");
532
552
  const parsed = JSON.parse(raw);
533
553
  if (typeof parsed.version === "string" && typeof parsed.fetchedAt === "number") {
554
+ if (typeof parsed.minVersion === "string") {
555
+ if (!versionFloor || compareClaudeCodeVersions(parsed.minVersion, versionFloor) > 0) {
556
+ versionFloor = parsed.minVersion;
557
+ }
558
+ }
534
559
  return parsed;
535
560
  }
536
561
  return null;
@@ -541,7 +566,11 @@ async function readDiskCache() {
541
566
  async function writeDiskCache(data) {
542
567
  try {
543
568
  await import_promises.default.mkdir(getAppPaths().agentDir, { recursive: true, mode: 448 });
544
- await import_promises.default.writeFile(cachePath(), JSON.stringify(data), { mode: 384 });
569
+ await import_promises.default.writeFile(
570
+ cachePath(),
571
+ JSON.stringify({ ...data, ...versionFloor ? { minVersion: versionFloor } : {} }),
572
+ { mode: 384 }
573
+ );
545
574
  } catch (err) {
546
575
  log(
547
576
  "WARN",
@@ -567,6 +596,19 @@ async function fetchLatest() {
567
596
  clearTimeout(timer);
568
597
  }
569
598
  }
599
+ function refreshInBackground() {
600
+ if (backgroundRefresh) return;
601
+ backgroundRefresh = (async () => {
602
+ const fetched = await fetchLatest();
603
+ if (fetched) {
604
+ await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
605
+ memoryCache = { version: applyFloor(fetched), expiresAt: Date.now() + CACHE_FRESH_MS };
606
+ }
607
+ })().catch(() => {
608
+ }).finally(() => {
609
+ backgroundRefresh = null;
610
+ });
611
+ }
570
612
  async function getClaudeCodeVersion() {
571
613
  if (memoryCache && Date.now() < memoryCache.expiresAt) {
572
614
  return memoryCache.version;
@@ -574,18 +616,26 @@ async function getClaudeCodeVersion() {
574
616
  if (inflight) return inflight;
575
617
  inflight = (async () => {
576
618
  const disk = await readDiskCache();
577
- const diskFresh = disk && Date.now() - disk.fetchedAt < CACHE_TTL_MS;
578
- if (disk && diskFresh) {
579
- memoryCache = { version: disk.version, expiresAt: Date.now() + CACHE_TTL_MS };
580
- return disk.version;
619
+ const age = disk ? Date.now() - disk.fetchedAt : Infinity;
620
+ if (disk && age < CACHE_FRESH_MS) {
621
+ const version = applyFloor(disk.version);
622
+ memoryCache = { version, expiresAt: Date.now() + CACHE_FRESH_MS };
623
+ return version;
624
+ }
625
+ if (disk && age < CACHE_HARD_MS) {
626
+ const version = applyFloor(disk.version);
627
+ memoryCache = { version, expiresAt: Date.now() + 5 * 60 * 1e3 };
628
+ refreshInBackground();
629
+ return version;
581
630
  }
582
631
  const fetched = await fetchLatest();
583
632
  if (fetched) {
584
633
  await writeDiskCache({ version: fetched, fetchedAt: Date.now() });
585
- memoryCache = { version: fetched, expiresAt: Date.now() + CACHE_TTL_MS };
586
- return fetched;
634
+ const version = applyFloor(fetched);
635
+ memoryCache = { version, expiresAt: Date.now() + CACHE_FRESH_MS };
636
+ return version;
587
637
  }
588
- const resolved = disk?.version ?? FALLBACK_VERSION;
638
+ const resolved = applyFloor(disk?.version ?? FALLBACK_VERSION);
589
639
  memoryCache = { version: resolved, expiresAt: Date.now() + 5 * 60 * 1e3 };
590
640
  log(
591
641
  "WARN",
@@ -600,6 +650,44 @@ async function getClaudeCodeVersion() {
600
650
  inflight = null;
601
651
  }
602
652
  }
653
+ var REQUIRED_VERSION_PATTERN = /version\s+(\d+(?:\.\d+)+)\s+or\s+newer\s+is\s+required/i;
654
+ function recordRequiredClaudeCodeVersion(message) {
655
+ const required = REQUIRED_VERSION_PATTERN.exec(message ?? "")?.[1];
656
+ if (!required) return null;
657
+ if (versionFloor && compareClaudeCodeVersions(required, versionFloor) <= 0) return versionFloor;
658
+ versionFloor = required;
659
+ memoryCache = null;
660
+ log(
661
+ "WARN",
662
+ "claude-code-version",
663
+ `Provider requires Claude Code >= ${required}; pinning User-Agent floor`
664
+ );
665
+ try {
666
+ const dir = getAppPaths().agentDir;
667
+ (0, import_node_fs3.mkdirSync)(dir, { recursive: true, mode: 448 });
668
+ let existing = {};
669
+ try {
670
+ existing = JSON.parse((0, import_node_fs3.readFileSync)(cachePath(), "utf-8"));
671
+ } catch {
672
+ }
673
+ (0, import_node_fs3.writeFileSync)(
674
+ cachePath(),
675
+ JSON.stringify({
676
+ version: existing.version ?? required,
677
+ fetchedAt: existing.fetchedAt ?? 0,
678
+ minVersion: required
679
+ }),
680
+ { mode: 384 }
681
+ );
682
+ } catch (err) {
683
+ log(
684
+ "WARN",
685
+ "claude-code-version",
686
+ `Failed to persist required version: ${err instanceof Error ? err.message : String(err)}`
687
+ );
688
+ }
689
+ return required;
690
+ }
603
691
  async function getClaudeCliUserAgent() {
604
692
  const version = await getClaudeCodeVersion();
605
693
  return `claude-cli/${version} (external, cli)`;
@@ -1587,7 +1675,7 @@ function activeBaseUrlEntry(data, provider) {
1587
1675
  }
1588
1676
  function readStoredBaseUrlSync(authFile, provider) {
1589
1677
  try {
1590
- const data = JSON.parse((0, import_node_fs3.readFileSync)(authFile, "utf-8"));
1678
+ const data = JSON.parse((0, import_node_fs4.readFileSync)(authFile, "utf-8"));
1591
1679
  return activeBaseUrlEntry(data, provider)?.baseUrl;
1592
1680
  } catch {
1593
1681
  return void 0;
@@ -2169,6 +2257,42 @@ var MODELS = [
2169
2257
  costTier: "high",
2170
2258
  maxThinkingLevel: "ultra"
2171
2259
  },
2260
+ {
2261
+ // GPT-6 Sol — "Workhorse model for coding and everyday work." (Codex
2262
+ // catalog priority 2, default medium, requires Codex client >= 0.155.0).
2263
+ // Launched Sep 22 2026 at $2/$10 per 1M tokens — half of GPT-5.6 Sol.
2264
+ // Same 1.05M public / 272K Codex split and low → ultra ladder as Astra.
2265
+ id: "gpt-6-sol",
2266
+ name: "GPT-6 Sol",
2267
+ provider: "openai",
2268
+ contextWindow: 105e4,
2269
+ codexContextWindow: 272e3,
2270
+ maxOutputTokens: 128e3,
2271
+ supportsThinking: true,
2272
+ defaultThinkingLevel: "medium",
2273
+ supportsImages: true,
2274
+ supportsVideo: false,
2275
+ costTier: "medium",
2276
+ maxThinkingLevel: "ultra"
2277
+ },
2278
+ {
2279
+ // GPT-6 Luna — "Fast and affordable model for easier tasks." (Codex
2280
+ // catalog priority 3, default medium, client >= 0.155.0). $0.10/$0.50 per
2281
+ // 1M tokens. Reasoning tops out at `max` (no ultra preset). Listed ahead of
2282
+ // GPT-5.6 Luna so getFastModel picks it as the OpenAI fast tier.
2283
+ id: "gpt-6-luna",
2284
+ name: "GPT-6 Luna",
2285
+ provider: "openai",
2286
+ contextWindow: 105e4,
2287
+ codexContextWindow: 272e3,
2288
+ maxOutputTokens: 128e3,
2289
+ supportsThinking: true,
2290
+ defaultThinkingLevel: "medium",
2291
+ supportsImages: true,
2292
+ supportsVideo: false,
2293
+ costTier: "low",
2294
+ maxThinkingLevel: "max"
2295
+ },
2172
2296
  // GPT-5.6 family — three agentic coding tiers launched July 2026. The public
2173
2297
  // Responses API advertises a 1.05M context window; OpenAI's Codex product
2174
2298
  // catalog advertises 272K on the ChatGPT OAuth route (corrected from the
@@ -2678,7 +2802,7 @@ function getVideoByteLimit(modelId) {
2678
2802
  }
2679
2803
  function getDefaultModel(provider) {
2680
2804
  if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.6-pro");
2681
- if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.6-sol");
2805
+ if (provider === "openai") return MODELS.find((m) => m.id === "gpt-6-sol");
2682
2806
  if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite");
2683
2807
  if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.3");
2684
2808
  if (provider === "moonshot") return MODELS.find((m) => m.id === "kimi-k3");
@@ -2870,7 +2994,7 @@ var FALLBACK_CONTEXT_WINDOW = 4096;
2870
2994
  var LOCAL_API_KEY_PLACEHOLDER = "local";
2871
2995
  var DEFAULT_PROBE_TIMEOUT_MS = 1200;
2872
2996
  var ENRICH_CONCURRENCY = 6;
2873
- var CACHE_TTL_MS2 = 3e4;
2997
+ var CACHE_TTL_MS = 3e4;
2874
2998
  var NON_CHAT_ID_PATTERN = /(?:^|[-_/])(?:embed|embedding|rerank|reranker|bge|nomic-embed)/i;
2875
2999
  var LOCAL_ID_PREFIX = "local/";
2876
3000
  function formatLocalModelId(endpointId, rawId) {
@@ -3111,7 +3235,7 @@ function cacheKey(endpoints) {
3111
3235
  }
3112
3236
  async function discoverLocalModels(endpoints = DEFAULT_LOCAL_ENDPOINTS, options = {}) {
3113
3237
  const key = cacheKey(endpoints);
3114
- if (!options.force && cache && cache.key === key && Date.now() - cache.at < CACHE_TTL_MS2) {
3238
+ if (!options.force && cache && cache.key === key && Date.now() - cache.at < CACHE_TTL_MS) {
3115
3239
  return cache.result;
3116
3240
  }
3117
3241
  const probes = await Promise.all(endpoints.map((endpoint) => probeEndpoint(endpoint, options)));
@@ -3684,7 +3808,7 @@ async function transcribeVoice(fileUrl) {
3684
3808
 
3685
3809
  // src/auto-update.ts
3686
3810
  var import_node_child_process2 = require("child_process");
3687
- var import_node_fs4 = __toESM(require("fs"), 1);
3811
+ var import_node_fs5 = __toESM(require("fs"), 1);
3688
3812
  var import_node_path5 = __toESM(require("path"), 1);
3689
3813
  var CHECK_INTERVAL_MS = 60 * 60 * 1e3;
3690
3814
  var FETCH_TIMEOUT_MS2 = 1e4;
@@ -3718,7 +3842,7 @@ function createAutoUpdater(config) {
3718
3842
  }
3719
3843
  function readState() {
3720
3844
  try {
3721
- const raw = import_node_fs4.default.readFileSync(stateFilePath(), "utf-8");
3845
+ const raw = import_node_fs5.default.readFileSync(stateFilePath(), "utf-8");
3722
3846
  return JSON.parse(raw);
3723
3847
  } catch {
3724
3848
  return null;
@@ -3727,8 +3851,8 @@ function createAutoUpdater(config) {
3727
3851
  function writeState(state) {
3728
3852
  try {
3729
3853
  const filePath = stateFilePath();
3730
- import_node_fs4.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
3731
- import_node_fs4.default.writeFileSync(filePath, JSON.stringify(state));
3854
+ import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(filePath), { recursive: true, mode: 448 });
3855
+ import_node_fs5.default.writeFileSync(filePath, JSON.stringify(state));
3732
3856
  } catch {
3733
3857
  }
3734
3858
  }
@@ -3870,6 +3994,7 @@ function createAutoUpdater(config) {
3870
3994
  clearLocalDiscoveryCache,
3871
3995
  clearRuntimeModels,
3872
3996
  closeLogger,
3997
+ compareClaudeCodeVersions,
3873
3998
  createAutoUpdater,
3874
3999
  decodeOggOpus,
3875
4000
  discoverLocalModels,
@@ -3923,6 +4048,7 @@ function createAutoUpdater(config) {
3923
4048
  probeEndpoint,
3924
4049
  providerStorageKeys,
3925
4050
  readStoredBaseUrlSync,
4051
+ recordRequiredClaudeCodeVersion,
3926
4052
  refreshAnthropicToken,
3927
4053
  refreshGeminiToken,
3928
4054
  refreshKimiToken,