@jaypie/llm 1.2.24 → 1.2.26

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.
@@ -554,6 +554,50 @@ function formatOperateInput(input, options) {
554
554
  return [input];
555
555
  }
556
556
 
557
+ /**
558
+ * Converts a JSON Schema (Draft 2020-12) object to the OpenAPI 3.0 schema subset
559
+ * that Gemini's `responseSchema` accepts. This constrains generation (not just validation)
560
+ * and avoids the `items`-keyword leakage bug in `responseJsonSchema`.
561
+ *
562
+ * Strips: $schema, additionalProperties, $defs, $ref (inlines where possible), const
563
+ * Preserves: type, properties, required, items, enum, description, nullable
564
+ */
565
+ function jsonSchemaToOpenApi3(schema) {
566
+ if (typeof schema !== "object" || schema === null || Array.isArray(schema)) {
567
+ return schema;
568
+ }
569
+ const result = {};
570
+ for (const [key, value] of Object.entries(schema)) {
571
+ // Strip JSON Schema keywords not in OpenAPI 3.0 subset
572
+ if (key === "$schema" ||
573
+ key === "$defs" ||
574
+ key === "additionalProperties" ||
575
+ key === "const" ||
576
+ key === "$ref") {
577
+ continue;
578
+ }
579
+ if (key === "properties" &&
580
+ typeof value === "object" &&
581
+ value !== null &&
582
+ !Array.isArray(value)) {
583
+ const convertedProps = {};
584
+ for (const [propKey, propValue] of Object.entries(value)) {
585
+ convertedProps[propKey] = jsonSchemaToOpenApi3(propValue);
586
+ }
587
+ result[key] = convertedProps;
588
+ }
589
+ else if (key === "items" &&
590
+ typeof value === "object" &&
591
+ value !== null) {
592
+ result[key] = jsonSchemaToOpenApi3(value);
593
+ }
594
+ else {
595
+ result[key] = value;
596
+ }
597
+ }
598
+ return result;
599
+ }
600
+
557
601
  const getLogger$5 = () => log$1.log.lib({ lib: kit.JAYPIE.LIB.LLM });
558
602
 
559
603
  // Turn policy constants
@@ -1021,6 +1065,24 @@ const NOT_RETRYABLE_ERROR_NAMES = [
1021
1065
  "NotFoundError",
1022
1066
  "PermissionDeniedError",
1023
1067
  ];
1068
+ // Models known not to accept `temperature`.
1069
+ // Patterns (not exact names) so dated variants and future releases are covered
1070
+ // without code changes — Anthropic is trending toward removing temperature on
1071
+ // newer Claude models.
1072
+ const MODELS_WITHOUT_TEMPERATURE = [
1073
+ /^claude-opus-4-[789]/,
1074
+ /^claude-opus-[5-9]/,
1075
+ ];
1076
+ function isTemperatureDeprecationError(error) {
1077
+ if (!error || typeof error !== "object")
1078
+ return false;
1079
+ const err = error;
1080
+ const name = error?.constructor?.name;
1081
+ if (name !== "BadRequestError" && err.status !== 400)
1082
+ return false;
1083
+ const messages = [err.message, err.error?.message].filter((m) => typeof m === "string");
1084
+ return messages.some((m) => m.toLowerCase().includes("temperature"));
1085
+ }
1024
1086
  //
1025
1087
  //
1026
1088
  // Main
@@ -1035,6 +1097,20 @@ class AnthropicAdapter extends BaseProviderAdapter {
1035
1097
  super(...arguments);
1036
1098
  this.name = PROVIDER.ANTHROPIC.NAME;
1037
1099
  this.defaultModel = PROVIDER.ANTHROPIC.MODEL.DEFAULT;
1100
+ // Session-level cache of models observed to reject `temperature` at runtime.
1101
+ // Populated by executeRequest on 400 errors so repeat calls skip the param.
1102
+ this.runtimeNoTemperatureModels = new Set();
1103
+ }
1104
+ rememberModelRejectsTemperature(model) {
1105
+ this.runtimeNoTemperatureModels.add(model);
1106
+ }
1107
+ clearRuntimeNoTemperatureModels() {
1108
+ this.runtimeNoTemperatureModels.clear();
1109
+ }
1110
+ supportsTemperature(model) {
1111
+ if (this.runtimeNoTemperatureModels.has(model))
1112
+ return false;
1113
+ return !MODELS_WITHOUT_TEMPERATURE.some((pattern) => pattern.test(model));
1038
1114
  }
1039
1115
  //
1040
1116
  // Request Building
@@ -1126,6 +1202,11 @@ class AnthropicAdapter extends BaseProviderAdapter {
1126
1202
  if (request.temperature !== undefined) {
1127
1203
  anthropicRequest.temperature = request.temperature;
1128
1204
  }
1205
+ // Strip temperature for models that don't support it (denylist + runtime cache)
1206
+ if (anthropicRequest.temperature !== undefined &&
1207
+ !this.supportsTemperature(anthropicRequest.model)) {
1208
+ delete anthropicRequest.temperature;
1209
+ }
1129
1210
  return anthropicRequest;
1130
1211
  }
1131
1212
  formatTools(toolkit, outputSchema) {
@@ -1176,22 +1257,48 @@ class AnthropicAdapter extends BaseProviderAdapter {
1176
1257
  //
1177
1258
  async executeRequest(client, request, signal) {
1178
1259
  const anthropic = client;
1260
+ const anthropicRequest = request;
1179
1261
  try {
1180
- return (await anthropic.messages.create(request, signal ? { signal } : undefined));
1262
+ return (await anthropic.messages.create(anthropicRequest, signal ? { signal } : undefined));
1181
1263
  }
1182
1264
  catch (error) {
1183
1265
  if (signal?.aborted)
1184
1266
  return undefined;
1267
+ // If the model rejected `temperature`, cache it and retry without the param
1268
+ if (anthropicRequest.temperature !== undefined &&
1269
+ isTemperatureDeprecationError(error)) {
1270
+ this.rememberModelRejectsTemperature(anthropicRequest.model);
1271
+ const retryRequest = { ...anthropicRequest };
1272
+ delete retryRequest.temperature;
1273
+ return (await anthropic.messages.create(retryRequest, signal ? { signal } : undefined));
1274
+ }
1185
1275
  throw error;
1186
1276
  }
1187
1277
  }
1188
1278
  async *executeStreamRequest(client, request, signal) {
1189
1279
  const anthropic = client;
1190
- const streamRequest = {
1280
+ let streamRequest = {
1191
1281
  ...request,
1192
1282
  stream: true,
1193
1283
  };
1194
- const stream = await anthropic.messages.create(streamRequest, signal ? { signal } : undefined);
1284
+ let stream;
1285
+ try {
1286
+ stream = await anthropic.messages.create(streamRequest, signal ? { signal } : undefined);
1287
+ }
1288
+ catch (error) {
1289
+ if (streamRequest.temperature !== undefined &&
1290
+ isTemperatureDeprecationError(error)) {
1291
+ this.rememberModelRejectsTemperature(streamRequest.model);
1292
+ streamRequest = {
1293
+ ...streamRequest,
1294
+ };
1295
+ delete streamRequest.temperature;
1296
+ stream = await anthropic.messages.create(streamRequest, signal ? { signal } : undefined);
1297
+ }
1298
+ else {
1299
+ throw error;
1300
+ }
1301
+ }
1195
1302
  // Track current tool call being built
1196
1303
  let currentToolCall = null;
1197
1304
  // Track usage for final chunk
@@ -1540,11 +1647,21 @@ class GeminiAdapter extends BaseProviderAdapter {
1540
1647
  // Gemini doesn't support combining function calling with responseMimeType: 'application/json'
1541
1648
  // When tools are present, structured output is handled via the structured_output tool
1542
1649
  if (request.format && !(request.tools && request.tools.length > 0)) {
1543
- geminiRequest.config = {
1544
- ...geminiRequest.config,
1545
- responseMimeType: "application/json",
1546
- responseJsonSchema: request.format,
1547
- };
1650
+ const useJsonSchema = request.providerOptions?.useJsonSchema === true;
1651
+ if (useJsonSchema) {
1652
+ geminiRequest.config = {
1653
+ ...geminiRequest.config,
1654
+ responseMimeType: "application/json",
1655
+ responseJsonSchema: request.format,
1656
+ };
1657
+ }
1658
+ else {
1659
+ geminiRequest.config = {
1660
+ ...geminiRequest.config,
1661
+ responseMimeType: "application/json",
1662
+ responseSchema: jsonSchemaToOpenApi3(request.format),
1663
+ };
1664
+ }
1548
1665
  }
1549
1666
  // When format is specified with tools, add instruction to use structured_output tool
1550
1667
  if (request.format && request.tools && request.tools.length > 0) {
@@ -1612,11 +1729,7 @@ class GeminiAdapter extends BaseProviderAdapter {
1612
1729
  : naturalZodSchema(schema);
1613
1730
  jsonSchema = v4.z.toJSONSchema(zodSchema);
1614
1731
  }
1615
- // Remove $schema property (Gemini doesn't need it)
1616
- if (jsonSchema.$schema) {
1617
- delete jsonSchema.$schema;
1618
- }
1619
- return jsonSchema;
1732
+ return jsonSchemaToOpenApi3(jsonSchema);
1620
1733
  }
1621
1734
  //
1622
1735
  // API Execution