@prestyj/ai 4.11.4 → 4.12.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.d.cts CHANGED
@@ -451,6 +451,28 @@ declare function toOpenAIMessages(messages: Message[], options?: {
451
451
  supportsImages?: boolean;
452
452
  }): OpenAI.ChatCompletionMessageParam[];
453
453
 
454
+ /**
455
+ * Fire a minimal `max_tokens: 1` request that populates the Anthropic prompt
456
+ * cache with the system prompt + tools prefix, so the first real user turn is
457
+ * a cache read instead of a cold cache write. Best-effort: any error is
458
+ * swallowed so a failed pre-warm never blocks the session.
459
+ *
460
+ * Called by AgentSession when speedProfile is "optimized", before the first
461
+ * real agent-loop turn. The cache TTL follows the `cacheRetention` option —
462
+ * pass "long" (1 h) so the pre-warm survives until the user's first message.
463
+ */
464
+ declare function prewarmAnthropicCache(options: {
465
+ apiKey: string;
466
+ model: string;
467
+ system: string;
468
+ tools?: StreamOptions["tools"];
469
+ serverTools?: StreamOptions["serverTools"];
470
+ baseUrl?: string;
471
+ userAgent?: string;
472
+ cacheRetention?: StreamOptions["cacheRetention"];
473
+ signal?: AbortSignal;
474
+ }): Promise<void>;
475
+
454
476
  interface PalsuProviderState {
455
477
  callCount: number;
456
478
  }
@@ -520,4 +542,4 @@ interface PalsuProviderConfig {
520
542
  */
521
543
  declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
522
544
 
523
- export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
545
+ export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
package/dist/index.d.ts CHANGED
@@ -451,6 +451,28 @@ declare function toOpenAIMessages(messages: Message[], options?: {
451
451
  supportsImages?: boolean;
452
452
  }): OpenAI.ChatCompletionMessageParam[];
453
453
 
454
+ /**
455
+ * Fire a minimal `max_tokens: 1` request that populates the Anthropic prompt
456
+ * cache with the system prompt + tools prefix, so the first real user turn is
457
+ * a cache read instead of a cold cache write. Best-effort: any error is
458
+ * swallowed so a failed pre-warm never blocks the session.
459
+ *
460
+ * Called by AgentSession when speedProfile is "optimized", before the first
461
+ * real agent-loop turn. The cache TTL follows the `cacheRetention` option —
462
+ * pass "long" (1 h) so the pre-warm survives until the user's first message.
463
+ */
464
+ declare function prewarmAnthropicCache(options: {
465
+ apiKey: string;
466
+ model: string;
467
+ system: string;
468
+ tools?: StreamOptions["tools"];
469
+ serverTools?: StreamOptions["serverTools"];
470
+ baseUrl?: string;
471
+ userAgent?: string;
472
+ cacheRetention?: StreamOptions["cacheRetention"];
473
+ signal?: AbortSignal;
474
+ }): Promise<void>;
475
+
454
476
  interface PalsuProviderState {
455
477
  callCount: number;
456
478
  }
@@ -520,4 +542,4 @@ interface PalsuProviderConfig {
520
542
  */
521
543
  declare function registerPalsuProvider(config?: PalsuProviderConfig): PalsuProviderHandle;
522
544
 
523
- export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
545
+ export { type AssistantMessage, type CacheRetention, type ContentPart, type DoneEvent, EZCoderAIError, type ErrorEvent, type ErrorSource, EventStream, type FormattedError, type ImageContent, type Message, type PalsuModelConfig, type PalsuModelHandle, type PalsuProviderConfig, type PalsuProviderHandle, type PalsuProviderState, type PalsuResponse, type PalsuResponseFactory, type Provider, type ProviderDiagnosticFn, type ProviderEntry, ProviderError, type ProviderStreamFn, type RawContent, type ServerToolCall, type ServerToolCallEvent, type ServerToolDefinition, type ServerToolResult, type ServerToolResultEvent, type StopReason, type StreamEvent, type StreamOptions, type StreamResponse, StreamResult, type SystemMessage, type TextContent, type TextDeltaEvent, type ThinkingContent, type ThinkingDeltaEvent, type ThinkingLevel, type Tool, type ToolCall, type ToolCallDeltaEvent, type ToolCallDoneEvent, type ToolChoice, type ToolResult, type ToolResultContent, type ToolResultMessage, type Usage, type UserMessage, type VideoContent, classifyProviderError, formatError, formatErrorForDisplay, isHardBillingMessage, isUsageLimitError, palsuAssistantMessage, palsuText, palsuThinking, palsuToolCall, prewarmAnthropicCache, providerRegistry, registerPalsuProvider, setProviderDiagnostic, stream, toAnthropicMessages, toOpenAIMessages };
package/dist/index.js CHANGED
@@ -364,10 +364,15 @@ var StreamResult = class {
364
364
 
365
365
  // src/utils/zod-to-json-schema.ts
366
366
  import { z } from "zod";
367
+ var schemaCache = /* @__PURE__ */ new WeakMap();
367
368
  function zodToJsonSchema(schema) {
369
+ const cached = schemaCache.get(schema);
370
+ if (cached) return cached;
368
371
  const jsonSchema = z.toJSONSchema(schema);
369
372
  const { $schema: _schema, ...rest } = jsonSchema;
370
- return normalizeRootForAnthropic(rest);
373
+ const normalized = normalizeRootForAnthropic(rest);
374
+ schemaCache.set(schema, normalized);
375
+ return normalized;
371
376
  }
372
377
  function resolveToolSchema(tool) {
373
378
  return tool.rawInputSchema ?? zodToJsonSchema(tool.parameters);
@@ -975,26 +980,87 @@ function parseToolArguments(argsJson) {
975
980
  }
976
981
 
977
982
  // src/providers/anthropic.ts
983
+ var NON_STREAMING_TIMEOUT_MS = 60 * 60 * 1e3;
984
+ var anthropicClientCache = /* @__PURE__ */ new Map();
978
985
  function createClient(options) {
979
986
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
980
- return new Anthropic({
987
+ const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
988
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${userAgent}`;
989
+ if (!options.fetch) {
990
+ const cached = anthropicClientCache.get(cacheKey);
991
+ if (cached) return cached;
992
+ }
993
+ const client = new Anthropic({
981
994
  ...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
982
995
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
983
996
  ...options.fetch ? { fetch: options.fetch } : {},
984
- // Disable SDK retries — the agent loop has its own stall/overload retry
985
- // logic that surfaces errors properly. SDK retries on 429s can cause
986
- // multi-minute hangs when the provider stops responding mid-retry.
987
997
  maxRetries: 0,
988
998
  ...isOAuth ? {
989
999
  defaultHeaders: {
990
1000
  // Anthropic's OAuth edge validates the claude-cli version. Callers
991
1001
  // (ezcoder) resolve the live version at runtime; the literal here
992
- // is the offline fallback for direct gg-ai consumers.
993
- "user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
1002
+ // is the offline fallback for direct ai consumers.
1003
+ "user-agent": userAgent,
994
1004
  "x-app": "cli"
995
1005
  }
996
1006
  } : {}
997
1007
  });
1008
+ if (!options.fetch) {
1009
+ if (anthropicClientCache.size >= 8) {
1010
+ const oldest = anthropicClientCache.keys().next().value;
1011
+ if (oldest) anthropicClientCache.delete(oldest);
1012
+ }
1013
+ anthropicClientCache.set(cacheKey, client);
1014
+ }
1015
+ return client;
1016
+ }
1017
+ async function prewarmAnthropicCache(options) {
1018
+ try {
1019
+ const client = createClient({
1020
+ apiKey: options.apiKey,
1021
+ baseUrl: options.baseUrl,
1022
+ userAgent: options.userAgent
1023
+ });
1024
+ const cacheControl = toAnthropicCacheControl(options.cacheRetention ?? "long", options.baseUrl);
1025
+ const { system, messages } = toAnthropicMessages(
1026
+ [
1027
+ { role: "system", content: options.system },
1028
+ { role: "user", content: "." }
1029
+ ],
1030
+ cacheControl
1031
+ );
1032
+ const isOAuth = options.apiKey.startsWith("sk-ant-oat");
1033
+ const fullSystem = isOAuth ? [
1034
+ {
1035
+ type: "text",
1036
+ text: "You are Claude Code, Anthropic's official CLI for Claude."
1037
+ },
1038
+ ...system ?? []
1039
+ ] : system;
1040
+ const tools = options.tools?.length ? toAnthropicTools(options.tools, {
1041
+ cacheControl,
1042
+ enableFineGrainedToolStreaming: true
1043
+ }) : void 0;
1044
+ await client.messages.create(
1045
+ {
1046
+ model: options.model,
1047
+ max_tokens: 1,
1048
+ messages,
1049
+ ...fullSystem ? { system: fullSystem } : {},
1050
+ ...tools ? {
1051
+ tools: [
1052
+ ...tools,
1053
+ ...options.serverTools ?? []
1054
+ ]
1055
+ } : {}
1056
+ },
1057
+ {
1058
+ signal: options.signal ?? void 0,
1059
+ ...isOAuth ? { headers: { "anthropic-beta": "claude-code-20250219,oauth-2025-04-20" } } : {}
1060
+ }
1061
+ );
1062
+ } catch {
1063
+ }
998
1064
  }
999
1065
  function streamAnthropic(options) {
1000
1066
  return new StreamResult(runStream(options), options.signal);
@@ -1081,8 +1147,9 @@ async function* runStream(options) {
1081
1147
  ...betaHeaders.length ? { headers: { "anthropic-beta": betaHeaders.join(",") } } : {}
1082
1148
  };
1083
1149
  if (!useStreaming) {
1150
+ const nonStreamingClient = client.withOptions({ timeout: NON_STREAMING_TIMEOUT_MS });
1084
1151
  try {
1085
- const message = await client.messages.create(
1152
+ const message = await nonStreamingClient.messages.create(
1086
1153
  { ...params, stream: false },
1087
1154
  requestOptions
1088
1155
  );
@@ -1574,13 +1641,27 @@ function extractOpenAIUsage(usage) {
1574
1641
  cacheRead
1575
1642
  };
1576
1643
  }
1644
+ var openaiClientCache = /* @__PURE__ */ new Map();
1577
1645
  function createClient2(options) {
1578
- return new OpenAI({
1646
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${JSON.stringify(options.defaultHeaders ?? {})}`;
1647
+ if (!options.fetch) {
1648
+ const cached = openaiClientCache.get(cacheKey);
1649
+ if (cached) return cached;
1650
+ }
1651
+ const client = new OpenAI({
1579
1652
  apiKey: options.apiKey,
1580
1653
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
1581
1654
  ...options.fetch ? { fetch: options.fetch } : {},
1582
1655
  ...options.defaultHeaders ? { defaultHeaders: options.defaultHeaders } : {}
1583
1656
  });
1657
+ if (!options.fetch) {
1658
+ if (openaiClientCache.size >= 8) {
1659
+ const oldest = openaiClientCache.keys().next().value;
1660
+ if (oldest) openaiClientCache.delete(oldest);
1661
+ }
1662
+ openaiClientCache.set(cacheKey, client);
1663
+ }
1664
+ return client;
1584
1665
  }
1585
1666
  function streamOpenAI(options) {
1586
1667
  return new StreamResult(runStream2(options), options.signal);
@@ -1995,9 +2076,6 @@ async function* runStream3(options) {
1995
2076
  body.tools = toCodexTools(options.tools);
1996
2077
  }
1997
2078
  body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
1998
- if (options.cacheRetention === "long") {
1999
- body.prompt_cache_retention = "24h";
2000
- }
2001
2079
  if (options.temperature != null && !options.thinking) {
2002
2080
  body.temperature = options.temperature;
2003
2081
  }
@@ -3310,6 +3388,7 @@ export {
3310
3388
  palsuText,
3311
3389
  palsuThinking,
3312
3390
  palsuToolCall,
3391
+ prewarmAnthropicCache,
3313
3392
  providerRegistry,
3314
3393
  registerPalsuProvider,
3315
3394
  setProviderDiagnostic,