@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.cjs CHANGED
@@ -43,6 +43,7 @@ __export(index_exports, {
43
43
  palsuText: () => palsuText,
44
44
  palsuThinking: () => palsuThinking,
45
45
  palsuToolCall: () => palsuToolCall,
46
+ prewarmAnthropicCache: () => prewarmAnthropicCache,
46
47
  providerRegistry: () => providerRegistry,
47
48
  registerPalsuProvider: () => registerPalsuProvider,
48
49
  setProviderDiagnostic: () => setProviderDiagnostic,
@@ -418,10 +419,15 @@ var StreamResult = class {
418
419
 
419
420
  // src/utils/zod-to-json-schema.ts
420
421
  var import_zod = require("zod");
422
+ var schemaCache = /* @__PURE__ */ new WeakMap();
421
423
  function zodToJsonSchema(schema) {
424
+ const cached = schemaCache.get(schema);
425
+ if (cached) return cached;
422
426
  const jsonSchema = import_zod.z.toJSONSchema(schema);
423
427
  const { $schema: _schema, ...rest } = jsonSchema;
424
- return normalizeRootForAnthropic(rest);
428
+ const normalized = normalizeRootForAnthropic(rest);
429
+ schemaCache.set(schema, normalized);
430
+ return normalized;
425
431
  }
426
432
  function resolveToolSchema(tool) {
427
433
  return tool.rawInputSchema ?? zodToJsonSchema(tool.parameters);
@@ -1029,26 +1035,87 @@ function parseToolArguments(argsJson) {
1029
1035
  }
1030
1036
 
1031
1037
  // src/providers/anthropic.ts
1038
+ var NON_STREAMING_TIMEOUT_MS = 60 * 60 * 1e3;
1039
+ var anthropicClientCache = /* @__PURE__ */ new Map();
1032
1040
  function createClient(options) {
1033
1041
  const isOAuth = options.apiKey?.startsWith("sk-ant-oat");
1034
- return new import_sdk.default({
1042
+ const userAgent = isOAuth ? options.userAgent ?? "claude-cli/2.1.75 (external, cli)" : "";
1043
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${userAgent}`;
1044
+ if (!options.fetch) {
1045
+ const cached = anthropicClientCache.get(cacheKey);
1046
+ if (cached) return cached;
1047
+ }
1048
+ const client = new import_sdk.default({
1035
1049
  ...isOAuth ? { apiKey: null, authToken: options.apiKey } : { apiKey: options.apiKey },
1036
1050
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
1037
1051
  ...options.fetch ? { fetch: options.fetch } : {},
1038
- // Disable SDK retries — the agent loop has its own stall/overload retry
1039
- // logic that surfaces errors properly. SDK retries on 429s can cause
1040
- // multi-minute hangs when the provider stops responding mid-retry.
1041
1052
  maxRetries: 0,
1042
1053
  ...isOAuth ? {
1043
1054
  defaultHeaders: {
1044
1055
  // Anthropic's OAuth edge validates the claude-cli version. Callers
1045
1056
  // (ezcoder) resolve the live version at runtime; the literal here
1046
- // is the offline fallback for direct gg-ai consumers.
1047
- "user-agent": options.userAgent ?? "claude-cli/2.1.75 (external, cli)",
1057
+ // is the offline fallback for direct ai consumers.
1058
+ "user-agent": userAgent,
1048
1059
  "x-app": "cli"
1049
1060
  }
1050
1061
  } : {}
1051
1062
  });
1063
+ if (!options.fetch) {
1064
+ if (anthropicClientCache.size >= 8) {
1065
+ const oldest = anthropicClientCache.keys().next().value;
1066
+ if (oldest) anthropicClientCache.delete(oldest);
1067
+ }
1068
+ anthropicClientCache.set(cacheKey, client);
1069
+ }
1070
+ return client;
1071
+ }
1072
+ async function prewarmAnthropicCache(options) {
1073
+ try {
1074
+ const client = createClient({
1075
+ apiKey: options.apiKey,
1076
+ baseUrl: options.baseUrl,
1077
+ userAgent: options.userAgent
1078
+ });
1079
+ const cacheControl = toAnthropicCacheControl(options.cacheRetention ?? "long", options.baseUrl);
1080
+ const { system, messages } = toAnthropicMessages(
1081
+ [
1082
+ { role: "system", content: options.system },
1083
+ { role: "user", content: "." }
1084
+ ],
1085
+ cacheControl
1086
+ );
1087
+ const isOAuth = options.apiKey.startsWith("sk-ant-oat");
1088
+ const fullSystem = isOAuth ? [
1089
+ {
1090
+ type: "text",
1091
+ text: "You are Claude Code, Anthropic's official CLI for Claude."
1092
+ },
1093
+ ...system ?? []
1094
+ ] : system;
1095
+ const tools = options.tools?.length ? toAnthropicTools(options.tools, {
1096
+ cacheControl,
1097
+ enableFineGrainedToolStreaming: true
1098
+ }) : void 0;
1099
+ await client.messages.create(
1100
+ {
1101
+ model: options.model,
1102
+ max_tokens: 1,
1103
+ messages,
1104
+ ...fullSystem ? { system: fullSystem } : {},
1105
+ ...tools ? {
1106
+ tools: [
1107
+ ...tools,
1108
+ ...options.serverTools ?? []
1109
+ ]
1110
+ } : {}
1111
+ },
1112
+ {
1113
+ signal: options.signal ?? void 0,
1114
+ ...isOAuth ? { headers: { "anthropic-beta": "claude-code-20250219,oauth-2025-04-20" } } : {}
1115
+ }
1116
+ );
1117
+ } catch {
1118
+ }
1052
1119
  }
1053
1120
  function streamAnthropic(options) {
1054
1121
  return new StreamResult(runStream(options), options.signal);
@@ -1135,8 +1202,9 @@ async function* runStream(options) {
1135
1202
  ...betaHeaders.length ? { headers: { "anthropic-beta": betaHeaders.join(",") } } : {}
1136
1203
  };
1137
1204
  if (!useStreaming) {
1205
+ const nonStreamingClient = client.withOptions({ timeout: NON_STREAMING_TIMEOUT_MS });
1138
1206
  try {
1139
- const message = await client.messages.create(
1207
+ const message = await nonStreamingClient.messages.create(
1140
1208
  { ...params, stream: false },
1141
1209
  requestOptions
1142
1210
  );
@@ -1628,13 +1696,27 @@ function extractOpenAIUsage(usage) {
1628
1696
  cacheRead
1629
1697
  };
1630
1698
  }
1699
+ var openaiClientCache = /* @__PURE__ */ new Map();
1631
1700
  function createClient2(options) {
1632
- return new import_openai.default({
1701
+ const cacheKey = `${options.apiKey ?? ""}|${options.baseUrl ?? ""}|${JSON.stringify(options.defaultHeaders ?? {})}`;
1702
+ if (!options.fetch) {
1703
+ const cached = openaiClientCache.get(cacheKey);
1704
+ if (cached) return cached;
1705
+ }
1706
+ const client = new import_openai.default({
1633
1707
  apiKey: options.apiKey,
1634
1708
  ...options.baseUrl ? { baseURL: options.baseUrl } : {},
1635
1709
  ...options.fetch ? { fetch: options.fetch } : {},
1636
1710
  ...options.defaultHeaders ? { defaultHeaders: options.defaultHeaders } : {}
1637
1711
  });
1712
+ if (!options.fetch) {
1713
+ if (openaiClientCache.size >= 8) {
1714
+ const oldest = openaiClientCache.keys().next().value;
1715
+ if (oldest) openaiClientCache.delete(oldest);
1716
+ }
1717
+ openaiClientCache.set(cacheKey, client);
1718
+ }
1719
+ return client;
1638
1720
  }
1639
1721
  function streamOpenAI(options) {
1640
1722
  return new StreamResult(runStream2(options), options.signal);
@@ -2049,9 +2131,6 @@ async function* runStream3(options) {
2049
2131
  body.tools = toCodexTools(options.tools);
2050
2132
  }
2051
2133
  body.prompt_cache_key = normalizePromptCacheKey(options.promptCacheKey ?? "ezcoder");
2052
- if (options.cacheRetention === "long") {
2053
- body.prompt_cache_retention = "24h";
2054
- }
2055
2134
  if (options.temperature != null && !options.thinking) {
2056
2135
  body.temperature = options.temperature;
2057
2136
  }
@@ -3365,6 +3444,7 @@ function registerPalsuProvider(config) {
3365
3444
  palsuText,
3366
3445
  palsuThinking,
3367
3446
  palsuToolCall,
3447
+ prewarmAnthropicCache,
3368
3448
  providerRegistry,
3369
3449
  registerPalsuProvider,
3370
3450
  setProviderDiagnostic,