@prestyj/core 5.3.1 → 5.4.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
@@ -35,12 +35,14 @@ __export(index_exports, {
35
35
  MODELS: () => MODELS,
36
36
  MOONSHOT_OAUTH_KEY: () => MOONSHOT_OAUTH_KEY,
37
37
  NotLoggedInError: () => NotLoggedInError,
38
+ SubscriptionUsageError: () => SubscriptionUsageError,
38
39
  TelegramBot: () => TelegramBot,
39
40
  XIAOMI_CREDITS_KEY: () => XIAOMI_CREDITS_KEY,
40
41
  closeLogger: () => closeLogger,
41
42
  createAutoUpdater: () => createAutoUpdater,
42
43
  decodeOggOpus: () => decodeOggOpus,
43
44
  downmixToMono: () => downmixToMono,
45
+ fetchSubscriptionUsage: () => fetchSubscriptionUsage,
44
46
  generatePKCE: () => generatePKCE,
45
47
  getAppPaths: () => getAppPaths,
46
48
  getAuthStorageKey: () => getAuthStorageKey,
@@ -1535,49 +1537,63 @@ var MODELS = [
1535
1537
  maxThinkingLevel: "high"
1536
1538
  },
1537
1539
  // ── OpenAI (Codex) ─────────────────────────────────────
1540
+ // GPT-5.6 family — three agentic coding tiers launched July 2026. All share a
1541
+ // 372K context window: the Codex repo's models.json lists both `context_window`
1542
+ // AND `max_context_window` as 372000 for every 5.6 variant, so (unlike 5.4/5.5,
1543
+ // whose public-API 1M window exceeds the Codex-product cap) there's no split
1544
+ // between the API and Codex-transport windows — a single `contextWindow` is
1545
+ // correct in both code paths. All three take text+image input, freeform
1546
+ // apply_patch, text+image web search, and parallel tool calls.
1538
1547
  {
1539
- id: "gpt-5.5",
1540
- name: "GPT-5.5",
1548
+ // Sol — "Latest frontier agentic coding model." (priority 1, default low).
1549
+ // Reasoning ladder: low → medium → high → xhigh → max → ultra. gg-ai's
1550
+ // ThinkingLevel tops out at `max`, so that's the cap here; the `ultra` rung
1551
+ // (auto task delegation) needs a ThinkingLevel extension to expose.
1552
+ id: "gpt-5.6-sol",
1553
+ name: "GPT-5.6 Sol",
1541
1554
  provider: "openai",
1542
- contextWindow: 105e4,
1543
- codexContextWindow: 272e3,
1555
+ contextWindow: 372e3,
1544
1556
  maxOutputTokens: 128e3,
1545
1557
  supportsThinking: true,
1546
1558
  supportsImages: true,
1547
1559
  supportsVideo: false,
1548
1560
  costTier: "high",
1549
- maxThinkingLevel: "xhigh"
1561
+ maxThinkingLevel: "max"
1550
1562
  },
1551
1563
  {
1552
- id: "gpt-5.4",
1553
- name: "GPT-5.4",
1564
+ // Terra — "Balanced agentic coding model for everyday work." (priority 2,
1565
+ // default medium). Same 372K context + ultra reasoning ladder as Sol.
1566
+ id: "gpt-5.6-terra",
1567
+ name: "GPT-5.6 Terra",
1554
1568
  provider: "openai",
1555
- contextWindow: 105e4,
1556
- codexContextWindow: 272e3,
1569
+ contextWindow: 372e3,
1557
1570
  maxOutputTokens: 128e3,
1558
1571
  supportsThinking: true,
1559
1572
  supportsImages: true,
1560
1573
  supportsVideo: false,
1561
- costTier: "high",
1562
- maxThinkingLevel: "xhigh"
1574
+ costTier: "medium",
1575
+ maxThinkingLevel: "max"
1563
1576
  },
1564
1577
  {
1565
- id: "gpt-5.4-mini",
1566
- name: "GPT-5.4 Mini",
1578
+ // Luna — "Fast and affordable agentic coding model." (priority 3, default
1579
+ // medium). Same 372K context; reasoning tops out at `max` (no `ultra` rung).
1580
+ id: "gpt-5.6-luna",
1581
+ name: "GPT-5.6 Luna",
1567
1582
  provider: "openai",
1568
- contextWindow: 4e5,
1583
+ contextWindow: 372e3,
1569
1584
  maxOutputTokens: 128e3,
1570
1585
  supportsThinking: true,
1571
1586
  supportsImages: true,
1572
1587
  supportsVideo: false,
1573
1588
  costTier: "low",
1574
- maxThinkingLevel: "xhigh"
1589
+ maxThinkingLevel: "max"
1575
1590
  },
1576
1591
  {
1577
- id: "gpt-5.3-codex",
1578
- name: "GPT-5.3 Codex",
1592
+ id: "gpt-5.5",
1593
+ name: "GPT-5.5",
1579
1594
  provider: "openai",
1580
- contextWindow: 4e5,
1595
+ contextWindow: 105e4,
1596
+ codexContextWindow: 272e3,
1581
1597
  maxOutputTokens: 128e3,
1582
1598
  supportsThinking: true,
1583
1599
  supportsImages: true,
@@ -1617,8 +1633,8 @@ var MODELS = [
1617
1633
  },
1618
1634
  // ── Gemini ─────────────────────────────────────────────
1619
1635
  {
1620
- id: "gemini-3.1-flash-lite-preview",
1621
- name: "Gemini 3.1 Flash Lite Preview",
1636
+ id: "gemini-3.1-flash-lite",
1637
+ name: "Gemini 3.1 Flash Lite",
1622
1638
  provider: "gemini",
1623
1639
  contextWindow: 1048576,
1624
1640
  maxOutputTokens: 65536,
@@ -1630,7 +1646,10 @@ var MODELS = [
1630
1646
  maxThinkingLevel: "high"
1631
1647
  },
1632
1648
  {
1633
- id: "gemini-3.5-flash",
1649
+ // Wire name `gemini-3-flash` — the Code Assist (OAuth) backend rejects the
1650
+ // display string `gemini-3.5-flash` with a 404, so gemini-cli keeps this
1651
+ // alternative name (SECONDARY_GEMINI_3_5_FLASH_MODEL) for that endpoint.
1652
+ id: "gemini-3-flash",
1634
1653
  name: "Gemini 3.5 Flash",
1635
1654
  provider: "gemini",
1636
1655
  contextWindow: 1048576,
@@ -1642,6 +1661,22 @@ var MODELS = [
1642
1661
  costTier: "low",
1643
1662
  maxThinkingLevel: "high"
1644
1663
  },
1664
+ {
1665
+ // Gemini 3.1 Pro is public preview — gated behind Code Assist preview
1666
+ // enablement, so free/personal OAuth accounts 404 on it (see
1667
+ // ACCOUNT_GATED_MODELS in gg-ai's gemini provider).
1668
+ id: "gemini-3.1-pro-preview",
1669
+ name: "Gemini 3.1 Pro (Preview)",
1670
+ provider: "gemini",
1671
+ contextWindow: 1048576,
1672
+ maxOutputTokens: 65536,
1673
+ supportsThinking: true,
1674
+ supportsImages: true,
1675
+ supportsVideo: true,
1676
+ maxVideoBytes: 20 * 1024 * 1024,
1677
+ costTier: "high",
1678
+ maxThinkingLevel: "high"
1679
+ },
1645
1680
  // ── Moonshot (Kimi) ────────────────────────────────────
1646
1681
  {
1647
1682
  id: "kimi-k2.7-code",
@@ -1832,8 +1867,8 @@ function getVideoByteLimit(modelId) {
1832
1867
  }
1833
1868
  function getDefaultModel(provider) {
1834
1869
  if (provider === "xiaomi") return MODELS.find((m) => m.id === "mimo-v2.5-pro");
1835
- if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.5");
1836
- if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite-preview");
1870
+ if (provider === "openai") return MODELS.find((m) => m.id === "gpt-5.6-sol");
1871
+ if (provider === "gemini") return MODELS.find((m) => m.id === "gemini-3.1-flash-lite");
1837
1872
  if (provider === "glm") return MODELS.find((m) => m.id === "glm-5.2");
1838
1873
  if (provider === "moonshot") return MODELS.find((m) => m.id === "kimi-k2.7-code");
1839
1874
  if (provider === "minimax") return MODELS.find((m) => m.id === "MiniMax-M3");
@@ -1873,6 +1908,13 @@ function getFastModel(provider, currentModelId) {
1873
1908
 
1874
1909
  // src/thinking-level.ts
1875
1910
  var OPENAI_GPT_THINKING_LEVELS = ["medium", "high", "xhigh"];
1911
+ var OPENAI_GPT_56_THINKING_LEVELS = [
1912
+ "low",
1913
+ "medium",
1914
+ "high",
1915
+ "xhigh",
1916
+ "max"
1917
+ ];
1876
1918
  var SAKANA_THINKING_LEVELS = ["high", "xhigh"];
1877
1919
  var ANTHROPIC_OPUS_48_47_THINKING_LEVELS = [
1878
1920
  "low",
@@ -1902,10 +1944,10 @@ function isAnthropicAdaptiveModel(provider, model) {
1902
1944
  function getSupportedThinkingLevels(provider, model) {
1903
1945
  const maxLevel = getMaxThinkingLevel(model);
1904
1946
  if (isAnthropicAdaptiveModel(provider, model)) {
1905
- const levels = isAnthropicOpus48Or47Model(provider, model) ? ANTHROPIC_OPUS_48_47_THINKING_LEVELS : ANTHROPIC_ADAPTIVE_THINKING_LEVELS;
1906
- const maxIndex2 = levels.indexOf(maxLevel);
1947
+ const levels2 = isAnthropicOpus48Or47Model(provider, model) ? ANTHROPIC_OPUS_48_47_THINKING_LEVELS : ANTHROPIC_ADAPTIVE_THINKING_LEVELS;
1948
+ const maxIndex2 = levels2.indexOf(maxLevel);
1907
1949
  if (maxIndex2 === -1) return ["low", "medium", "high"];
1908
- return levels.slice(0, maxIndex2 + 1);
1950
+ return levels2.slice(0, maxIndex2 + 1);
1909
1951
  }
1910
1952
  if (isSakanaModel(provider)) {
1911
1953
  const maxIndex2 = SAKANA_THINKING_LEVELS.indexOf(maxLevel);
@@ -1913,9 +1955,10 @@ function getSupportedThinkingLevels(provider, model) {
1913
1955
  return SAKANA_THINKING_LEVELS.slice(0, maxIndex2 + 1);
1914
1956
  }
1915
1957
  if (!isOpenAIGptModel(provider, model)) return [maxLevel];
1916
- const maxIndex = OPENAI_GPT_THINKING_LEVELS.indexOf(maxLevel);
1958
+ const levels = model.startsWith("gpt-5.6-") ? OPENAI_GPT_56_THINKING_LEVELS : OPENAI_GPT_THINKING_LEVELS;
1959
+ const maxIndex = levels.indexOf(maxLevel);
1917
1960
  if (maxIndex === -1) return ["medium"];
1918
- return OPENAI_GPT_THINKING_LEVELS.slice(0, maxIndex + 1);
1961
+ return levels.slice(0, maxIndex + 1);
1919
1962
  }
1920
1963
  function isThinkingLevelSupported(provider, model, level) {
1921
1964
  return getSupportedThinkingLevels(provider, model).includes(level);
@@ -1932,6 +1975,147 @@ function getNextThinkingLevel(provider, model, current) {
1932
1975
  return supportedLevels[index + 1];
1933
1976
  }
1934
1977
 
1978
+ // src/provider-usage.ts
1979
+ var SubscriptionUsageError = class extends Error {
1980
+ constructor(message, status) {
1981
+ super(message);
1982
+ this.status = status;
1983
+ this.name = "SubscriptionUsageError";
1984
+ }
1985
+ };
1986
+ var ANTHROPIC_USAGE_URL = "https://api.anthropic.com/api/oauth/usage";
1987
+ var CODEX_USAGE_URL = "https://chatgpt.com/backend-api/wham/usage";
1988
+ function finiteNumber(value) {
1989
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
1990
+ }
1991
+ function clampPercent(value) {
1992
+ const number = finiteNumber(value);
1993
+ return number === void 0 ? void 0 : Math.min(100, Math.max(0, number));
1994
+ }
1995
+ function isoTimestamp(value) {
1996
+ if (typeof value !== "string" || !value.trim()) return void 0;
1997
+ const timestamp = Date.parse(value);
1998
+ return Number.isFinite(timestamp) ? timestamp : void 0;
1999
+ }
2000
+ function unixTimestamp(value) {
2001
+ const seconds = finiteNumber(value);
2002
+ return seconds === void 0 ? void 0 : seconds * 1e3;
2003
+ }
2004
+ function codexResetAt(window, now) {
2005
+ const absolute = unixTimestamp(window.reset_at);
2006
+ if (absolute !== void 0) return absolute;
2007
+ const afterSeconds = finiteNumber(window.reset_after_seconds);
2008
+ return afterSeconds === void 0 ? void 0 : now + afterSeconds * 1e3;
2009
+ }
2010
+ function currentWindowLabel(seconds, fallbackHours) {
2011
+ const duration = finiteNumber(seconds);
2012
+ const hours = Math.max(1, Math.round((duration ?? fallbackHours * 3600) / 3600));
2013
+ return `${hours}-hour`;
2014
+ }
2015
+ async function readUsageResponse(response) {
2016
+ const text = await response.text();
2017
+ if (!response.ok) {
2018
+ throw new SubscriptionUsageError(
2019
+ `Subscription usage request failed with HTTP ${response.status}`,
2020
+ response.status
2021
+ );
2022
+ }
2023
+ try {
2024
+ return JSON.parse(text);
2025
+ } catch {
2026
+ throw new SubscriptionUsageError("Subscription usage response was not valid JSON");
2027
+ }
2028
+ }
2029
+ async function fetchAnthropicUsage(credentials, fetchFn, signal, now) {
2030
+ const response = await fetchFn(ANTHROPIC_USAGE_URL, {
2031
+ method: "GET",
2032
+ signal,
2033
+ headers: {
2034
+ Authorization: `Bearer ${credentials.accessToken}`,
2035
+ Accept: "application/json",
2036
+ "anthropic-version": "2023-06-01",
2037
+ "anthropic-beta": "oauth-2025-04-20",
2038
+ "User-Agent": "ezcoder"
2039
+ }
2040
+ });
2041
+ const data = await readUsageResponse(response);
2042
+ const windows = [];
2043
+ const currentPercent = clampPercent(data.five_hour?.utilization);
2044
+ if (currentPercent !== void 0) {
2045
+ windows.push({
2046
+ kind: "current",
2047
+ label: "5-hour",
2048
+ usedPercent: currentPercent,
2049
+ resetsAt: isoTimestamp(data.five_hour?.resets_at)
2050
+ });
2051
+ }
2052
+ const weeklyPercent = clampPercent(data.seven_day?.utilization);
2053
+ if (weeklyPercent !== void 0) {
2054
+ windows.push({
2055
+ kind: "weekly",
2056
+ label: "Weekly",
2057
+ usedPercent: weeklyPercent,
2058
+ resetsAt: isoTimestamp(data.seven_day?.resets_at)
2059
+ });
2060
+ }
2061
+ return {
2062
+ provider: "anthropic",
2063
+ displayName: "Anthropic",
2064
+ windows,
2065
+ fetchedAt: now()
2066
+ };
2067
+ }
2068
+ async function fetchCodexUsage(credentials, fetchFn, signal, now) {
2069
+ const headers = {
2070
+ Authorization: `Bearer ${credentials.accessToken}`,
2071
+ Accept: "application/json",
2072
+ originator: "ezcoder",
2073
+ "User-Agent": "ezcoder"
2074
+ };
2075
+ if (credentials.accountId) headers["ChatGPT-Account-Id"] = credentials.accountId;
2076
+ const response = await fetchFn(CODEX_USAGE_URL, { method: "GET", signal, headers });
2077
+ const data = await readUsageResponse(response);
2078
+ const windows = [];
2079
+ const current = data.rate_limit?.primary_window;
2080
+ const currentPercent = clampPercent(current?.used_percent);
2081
+ if (current && currentPercent !== void 0) {
2082
+ windows.push({
2083
+ kind: "current",
2084
+ label: currentWindowLabel(current.limit_window_seconds, 5),
2085
+ usedPercent: currentPercent,
2086
+ resetsAt: codexResetAt(current, now())
2087
+ });
2088
+ }
2089
+ const weekly = data.rate_limit?.secondary_window;
2090
+ const weeklyPercent = clampPercent(weekly?.used_percent);
2091
+ if (weekly && weeklyPercent !== void 0) {
2092
+ windows.push({
2093
+ kind: "weekly",
2094
+ label: "Weekly",
2095
+ usedPercent: weeklyPercent,
2096
+ resetsAt: codexResetAt(weekly, now())
2097
+ });
2098
+ }
2099
+ return {
2100
+ provider: "openai",
2101
+ displayName: "Codex",
2102
+ windows,
2103
+ fetchedAt: now()
2104
+ };
2105
+ }
2106
+ async function fetchSubscriptionUsage(provider, credentials, options = {}) {
2107
+ const fetchFn = options.fetchFn ?? fetch;
2108
+ const now = options.now ?? Date.now;
2109
+ const signal = AbortSignal.timeout(options.timeoutMs ?? 8e3);
2110
+ try {
2111
+ return provider === "anthropic" ? await fetchAnthropicUsage(credentials, fetchFn, signal, now) : await fetchCodexUsage(credentials, fetchFn, signal, now);
2112
+ } catch (error) {
2113
+ if (error instanceof SubscriptionUsageError) throw error;
2114
+ const message = error instanceof Error ? error.message : String(error);
2115
+ throw new SubscriptionUsageError(message);
2116
+ }
2117
+ }
2118
+
1935
2119
  // src/telegram.ts
1936
2120
  var TELEGRAM_API = "https://api.telegram.org";
1937
2121
  var MAX_MESSAGE_LENGTH = 4096;
@@ -2414,12 +2598,14 @@ function createAutoUpdater(config) {
2414
2598
  MODELS,
2415
2599
  MOONSHOT_OAUTH_KEY,
2416
2600
  NotLoggedInError,
2601
+ SubscriptionUsageError,
2417
2602
  TelegramBot,
2418
2603
  XIAOMI_CREDITS_KEY,
2419
2604
  closeLogger,
2420
2605
  createAutoUpdater,
2421
2606
  decodeOggOpus,
2422
2607
  downmixToMono,
2608
+ fetchSubscriptionUsage,
2423
2609
  generatePKCE,
2424
2610
  getAppPaths,
2425
2611
  getAuthStorageKey,