@prestyj/ai 5.4.0 → 5.5.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.d.cts CHANGED
@@ -3,7 +3,7 @@ import Anthropic from '@anthropic-ai/sdk';
3
3
  import OpenAI from 'openai';
4
4
 
5
5
  type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "palsu";
6
- type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max";
6
+ type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max" | "ultra";
7
7
  type CacheRetention = "none" | "short" | "long";
8
8
  interface TextContent {
9
9
  type: "text";
@@ -175,6 +175,10 @@ interface StreamOptions {
175
175
  serviceTier?: "auto" | "default" | "flex" | "priority";
176
176
  /** OpenAI ChatGPT account ID (from OAuth JWT) for codex endpoint */
177
177
  accountId?: string;
178
+ /** Stable conversation identity for Codex transport headers. This is distinct from
179
+ * promptCacheKey: sessions with matching prefixes may share a cache key, but must
180
+ * retain independent session/thread identities. */
181
+ transportSessionId?: string;
178
182
  /** Google Cloud/Code Assist project ID used by Gemini OAuth transport. */
179
183
  projectId?: string;
180
184
  /** Enable provider-native web search. Each provider uses its own format:
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import Anthropic from '@anthropic-ai/sdk';
3
3
  import OpenAI from 'openai';
4
4
 
5
5
  type Provider = "anthropic" | "xiaomi" | "openai" | "gemini" | "glm" | "moonshot" | "minimax" | "deepseek" | "openrouter" | "sakana" | "palsu";
6
- type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max";
6
+ type ThinkingLevel = "low" | "medium" | "high" | "xhigh" | "max" | "ultra";
7
7
  type CacheRetention = "none" | "short" | "long";
8
8
  interface TextContent {
9
9
  type: "text";
@@ -175,6 +175,10 @@ interface StreamOptions {
175
175
  serviceTier?: "auto" | "default" | "flex" | "priority";
176
176
  /** OpenAI ChatGPT account ID (from OAuth JWT) for codex endpoint */
177
177
  accountId?: string;
178
+ /** Stable conversation identity for Codex transport headers. This is distinct from
179
+ * promptCacheKey: sessions with matching prefixes may share a cache key, but must
180
+ * retain independent session/thread identities. */
181
+ transportSessionId?: string;
178
182
  /** Google Cloud/Code Assist project ID used by Gemini OAuth transport. */
179
183
  projectId?: string;
180
184
  /** Enable provider-native web search. Each provider uses its own format:
package/dist/index.js CHANGED
@@ -818,7 +818,7 @@ function toAnthropicThinking(level, maxTokens, model) {
818
818
  };
819
819
  }
820
820
  const VISIBLE_FLOOR = 1024;
821
- const effectiveLevel = level === "xhigh" || level === "max" ? "high" : level;
821
+ const effectiveLevel = level === "xhigh" || level === "max" || level === "ultra" ? "high" : level;
822
822
  const budgetMap = {
823
823
  low: Math.max(1024, Math.floor(maxTokens * 0.2)),
824
824
  medium: Math.max(2048, Math.floor(maxTokens * 0.45)),
@@ -986,7 +986,7 @@ function toOpenAIToolChoice(choice) {
986
986
  return { type: "function", function: { name: choice.name } };
987
987
  }
988
988
  function toOpenAIReasoningEffort(level, model) {
989
- const effort = level === "max" ? "xhigh" : level;
989
+ const effort = level === "max" || level === "ultra" ? "xhigh" : level;
990
990
  if (model.startsWith("fugu") && (effort === "low" || effort === "medium")) {
991
991
  return "high";
992
992
  }
@@ -1712,11 +1712,16 @@ function getEnvironment() {
1712
1712
  // src/providers/openai.ts
1713
1713
  function extractOpenAIUsage(usage) {
1714
1714
  let cacheRead = 0;
1715
+ let cacheWrite = 0;
1715
1716
  const details = usage.prompt_tokens_details;
1716
1717
  if (details?.cached_tokens) {
1717
1718
  cacheRead = details.cached_tokens;
1718
1719
  }
1719
1720
  const usageAny = usage;
1721
+ const detailsAny = details;
1722
+ if (typeof detailsAny?.cache_write_tokens === "number") {
1723
+ cacheWrite = detailsAny.cache_write_tokens;
1724
+ }
1720
1725
  if (!cacheRead && typeof usageAny.cached_tokens === "number" && usageAny.cached_tokens > 0) {
1721
1726
  cacheRead = usageAny.cached_tokens;
1722
1727
  }
@@ -1724,9 +1729,10 @@ function extractOpenAIUsage(usage) {
1724
1729
  cacheRead = usageAny.prompt_cache_hit_tokens;
1725
1730
  }
1726
1731
  return {
1727
- inputTokens: usage.prompt_tokens - cacheRead,
1732
+ inputTokens: usage.prompt_tokens - cacheRead - cacheWrite,
1728
1733
  outputTokens: usage.completion_tokens,
1729
- cacheRead
1734
+ cacheRead,
1735
+ cacheWrite
1730
1736
  };
1731
1737
  }
1732
1738
  var openaiClientCache = /* @__PURE__ */ new Map();
@@ -1791,8 +1797,9 @@ async function* runStream2(options) {
1791
1797
  if (options.provider === "openai" || options.provider === "moonshot") {
1792
1798
  const paramsAny = params;
1793
1799
  paramsAny.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
1794
- const retention = options.cacheRetention ?? "short";
1795
- if (retention === "long") {
1800
+ if (options.provider === "openai" && options.model.startsWith("gpt-5.6")) {
1801
+ paramsAny.prompt_cache_options = { mode: "implicit", ttl: "30m" };
1802
+ } else if ((options.cacheRetention ?? "short") === "long") {
1796
1803
  paramsAny.prompt_cache_retention = "24h";
1797
1804
  }
1798
1805
  }
@@ -1843,6 +1850,7 @@ async function* runStream2(options) {
1843
1850
  let inputTokens = 0;
1844
1851
  let outputTokens = 0;
1845
1852
  let cacheRead = 0;
1853
+ let cacheWrite = 0;
1846
1854
  let finishReason = null;
1847
1855
  let receivedAnyChunk = false;
1848
1856
  try {
@@ -1850,7 +1858,7 @@ async function* runStream2(options) {
1850
1858
  receivedAnyChunk = true;
1851
1859
  const choice = chunk.choices?.[0];
1852
1860
  if (chunk.usage) {
1853
- ({ inputTokens, outputTokens, cacheRead } = extractOpenAIUsage(chunk.usage));
1861
+ ({ inputTokens, outputTokens, cacheRead, cacheWrite } = extractOpenAIUsage(chunk.usage));
1854
1862
  }
1855
1863
  if (!choice) continue;
1856
1864
  if (choice.finish_reason) {
@@ -1930,7 +1938,12 @@ async function* runStream2(options) {
1930
1938
  content: contentParts.length > 0 ? contentParts : textAccum || ""
1931
1939
  },
1932
1940
  stopReason,
1933
- usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
1941
+ usage: {
1942
+ inputTokens,
1943
+ outputTokens,
1944
+ ...cacheRead > 0 && { cacheRead },
1945
+ ...cacheWrite > 0 && { cacheWrite }
1946
+ }
1934
1947
  };
1935
1948
  yield { type: "done", stopReason };
1936
1949
  return response;
@@ -2003,8 +2016,9 @@ function completionToResponse(completion) {
2003
2016
  let inputTokens = 0;
2004
2017
  let outputTokens = 0;
2005
2018
  let cacheRead = 0;
2019
+ let cacheWrite = 0;
2006
2020
  if (completion.usage) {
2007
- ({ inputTokens, outputTokens, cacheRead } = extractOpenAIUsage(completion.usage));
2021
+ ({ inputTokens, outputTokens, cacheRead, cacheWrite } = extractOpenAIUsage(completion.usage));
2008
2022
  }
2009
2023
  const stopReason = normalizeOpenAIStopReason(choice?.finish_reason ?? null);
2010
2024
  return {
@@ -2013,7 +2027,12 @@ function completionToResponse(completion) {
2013
2027
  content: contentParts.length > 0 ? contentParts : textAccum
2014
2028
  },
2015
2029
  stopReason,
2016
- usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
2030
+ usage: {
2031
+ inputTokens,
2032
+ outputTokens,
2033
+ ...cacheRead > 0 && { cacheRead },
2034
+ ...cacheWrite > 0 && { cacheWrite }
2035
+ }
2017
2036
  };
2018
2037
  }
2019
2038
  function classifyOpenAICompatLimit(args) {
@@ -2135,6 +2154,10 @@ function extractRequestIdFromMessage(message) {
2135
2154
 
2136
2155
  // src/providers/openai-codex.ts
2137
2156
  var DEFAULT_BASE_URL = "https://chatgpt.com/backend-api";
2157
+ var CODEX_CLIENT_VERSION = "0.144.1";
2158
+ function usesResponsesLite(model) {
2159
+ return model.startsWith("gpt-5.6-");
2160
+ }
2138
2161
  function outputTextKey(itemId, contentIndex) {
2139
2162
  return `${itemId ?? ""}:${contentIndex ?? 0}`;
2140
2163
  }
@@ -2150,6 +2173,7 @@ async function* runStream3(options) {
2150
2173
  const downgradedImages = downgradeUnsupportedImages(options.messages, options.supportsImages);
2151
2174
  const downgraded = downgradeUnsupportedVideos(downgradedImages, options.supportsVideo);
2152
2175
  const { system, input } = toCodexInput(downgraded, { supportsImages: options.supportsImages });
2176
+ const responsesLite = usesResponsesLite(options.model);
2153
2177
  const body = {
2154
2178
  model: options.model,
2155
2179
  store: false,
@@ -2157,7 +2181,7 @@ async function* runStream3(options) {
2157
2181
  instructions: system,
2158
2182
  input,
2159
2183
  tool_choice: "auto",
2160
- parallel_tool_calls: true,
2184
+ parallel_tool_calls: !responsesLite,
2161
2185
  include: ["reasoning.encrypted_content"]
2162
2186
  };
2163
2187
  if (options.tools?.length) {
@@ -2168,24 +2192,29 @@ async function* runStream3(options) {
2168
2192
  body.temperature = options.temperature;
2169
2193
  }
2170
2194
  body.reasoning = {
2171
- effort: options.thinking ?? "none",
2172
- summary: "auto"
2195
+ // `ultra` is a client orchestration preset, not a Codex API effort.
2196
+ effort: options.thinking === "ultra" ? "max" : options.thinking ?? "none",
2197
+ summary: "auto",
2198
+ ...responsesLite ? { context: "all_turns" } : {}
2173
2199
  };
2174
2200
  const headers = {
2175
2201
  "Content-Type": "application/json",
2176
2202
  Accept: "text/event-stream",
2177
2203
  Authorization: `Bearer ${options.apiKey}`,
2178
2204
  "OpenAI-Beta": "responses=experimental",
2179
- originator: "ezcoder",
2180
- "User-Agent": `ezcoder (${os.platform()} ${os.release()}; ${os.arch()})`
2205
+ originator: responsesLite ? "codex_cli_rs" : "ezcoder",
2206
+ "User-Agent": responsesLite ? `codex_cli_rs/${CODEX_CLIENT_VERSION}` : `ezcoder (${os.platform()} ${os.release()}; ${os.arch()})`,
2207
+ ...responsesLite ? {
2208
+ version: CODEX_CLIENT_VERSION,
2209
+ "X-OpenAI-Internal-Codex-Responses-Lite": "true"
2210
+ } : {}
2181
2211
  };
2182
2212
  if (options.accountId) {
2183
2213
  headers["chatgpt-account-id"] = options.accountId;
2184
2214
  }
2185
- const cacheScopeId = body.prompt_cache_key;
2186
- if (cacheScopeId) {
2187
- headers["session_id"] = cacheScopeId;
2188
- headers["x-client-request-id"] = cacheScopeId;
2215
+ if (options.transportSessionId) {
2216
+ headers["session_id"] = options.transportSessionId;
2217
+ headers["x-client-request-id"] = options.transportSessionId;
2189
2218
  }
2190
2219
  const response = await fetch(url, {
2191
2220
  method: "POST",
@@ -2229,6 +2258,7 @@ async function* runStream3(options) {
2229
2258
  let inputTokens = 0;
2230
2259
  let outputTokens = 0;
2231
2260
  let cacheRead = 0;
2261
+ let cacheWrite = 0;
2232
2262
  const diagStart = Date.now();
2233
2263
  const diagSeen = /* @__PURE__ */ new Set();
2234
2264
  for await (const event of parseSSE(response.body)) {
@@ -2405,7 +2435,8 @@ async function* runStream3(options) {
2405
2435
  const usage = resp?.usage;
2406
2436
  if (usage) {
2407
2437
  cacheRead = usage.input_tokens_details?.cached_tokens ?? 0;
2408
- inputTokens = (usage.input_tokens ?? 0) - cacheRead;
2438
+ cacheWrite = usage.input_tokens_details?.cache_write_tokens ?? 0;
2439
+ inputTokens = (usage.input_tokens ?? 0) - cacheRead - cacheWrite;
2409
2440
  outputTokens = usage.output_tokens ?? 0;
2410
2441
  }
2411
2442
  }
@@ -2453,7 +2484,12 @@ async function* runStream3(options) {
2453
2484
  content: contentParts.length > 0 ? contentParts : textAccum || ""
2454
2485
  },
2455
2486
  stopReason,
2456
- usage: { inputTokens, outputTokens, ...cacheRead > 0 && { cacheRead } }
2487
+ usage: {
2488
+ inputTokens,
2489
+ outputTokens,
2490
+ ...cacheRead > 0 && { cacheRead },
2491
+ ...cacheWrite > 0 && { cacheWrite }
2492
+ }
2457
2493
  };
2458
2494
  yield { type: "done", stopReason };
2459
2495
  return streamResponse;
@@ -2816,6 +2852,7 @@ function toGemini3ThinkingLevel(level) {
2816
2852
  case "high":
2817
2853
  case "xhigh":
2818
2854
  case "max":
2855
+ case "ultra":
2819
2856
  return "HIGH";
2820
2857
  }
2821
2858
  }
@@ -2828,6 +2865,7 @@ function toThinkingBudget(level) {
2828
2865
  case "high":
2829
2866
  case "xhigh":
2830
2867
  case "max":
2868
+ case "ultra":
2831
2869
  return 8192;
2832
2870
  }
2833
2871
  }