extrait 0.4.0 → 0.5.2

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
@@ -2,27 +2,37 @@ var __defProp = Object.defineProperty;
2
2
  var __getOwnPropNames = Object.getOwnPropertyNames;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __hasOwnProp = Object.prototype.hasOwnProperty;
5
- var __moduleCache = /* @__PURE__ */ new WeakMap;
5
+ function __accessProp(key) {
6
+ return this[key];
7
+ }
6
8
  var __toCommonJS = (from) => {
7
- var entry = __moduleCache.get(from), desc;
9
+ var entry = (__moduleCache ??= new WeakMap).get(from), desc;
8
10
  if (entry)
9
11
  return entry;
10
12
  entry = __defProp({}, "__esModule", { value: true });
11
- if (from && typeof from === "object" || typeof from === "function")
12
- __getOwnPropNames(from).map((key) => !__hasOwnProp.call(entry, key) && __defProp(entry, key, {
13
- get: () => from[key],
14
- enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
15
- }));
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (var key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(entry, key))
16
+ __defProp(entry, key, {
17
+ get: __accessProp.bind(from, key),
18
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
19
+ });
20
+ }
16
21
  __moduleCache.set(from, entry);
17
22
  return entry;
18
23
  };
24
+ var __moduleCache;
25
+ var __returnValue = (v) => v;
26
+ function __exportSetter(name, newValue) {
27
+ this[name] = __returnValue.bind(null, newValue);
28
+ }
19
29
  var __export = (target, all) => {
20
30
  for (var name in all)
21
31
  __defProp(target, name, {
22
32
  get: all[name],
23
33
  enumerable: true,
24
34
  configurable: true,
25
- set: (newValue) => all[name] = () => newValue
35
+ set: __exportSetter.bind(all, name)
26
36
  });
27
37
  };
28
38
 
@@ -35,11 +45,13 @@ __export(exports_src, {
35
45
  sanitizeThink: () => sanitizeThink,
36
46
  s: () => s,
37
47
  resolveSchemaInstruction: () => resolveSchemaInstruction,
48
+ resizeImage: () => resizeImage,
38
49
  registerBuiltinProviders: () => registerBuiltinProviders,
39
50
  prompt: () => prompt,
40
51
  parseLLMOutput: () => parseLLMOutput,
41
52
  inspectSchemaMetadata: () => inspectSchemaMetadata,
42
53
  inferSchemaExample: () => inferSchemaExample,
54
+ images: () => images,
43
55
  formatZodIssues: () => formatZodIssues,
44
56
  formatPrompt: () => formatPrompt,
45
57
  extractMarkdownCodeBlocks: () => extractMarkdownCodeBlocks,
@@ -776,45 +788,38 @@ function unwrap(schema) {
776
788
  let optional = false;
777
789
  let nullable = false;
778
790
  while (true) {
779
- const typeName = current?._def?.typeName;
791
+ const typeName = current?._def?.type;
780
792
  if (!typeName) {
781
793
  break;
782
794
  }
783
- if (typeName === "ZodOptional") {
795
+ if (typeName === "optional") {
784
796
  optional = true;
785
797
  current = current._def?.innerType ?? current;
786
798
  continue;
787
799
  }
788
- if (typeName === "ZodDefault") {
800
+ if (typeName === "default") {
789
801
  optional = true;
790
802
  current = current._def?.innerType ?? current;
791
803
  continue;
792
804
  }
793
- if (typeName === "ZodNullable") {
805
+ if (typeName === "nullable") {
794
806
  nullable = true;
795
807
  current = current._def?.innerType ?? current;
796
808
  continue;
797
809
  }
798
- if (typeName === "ZodEffects") {
799
- current = current._def?.schema ?? current;
800
- continue;
801
- }
802
- if (typeName === "ZodBranded") {
803
- current = current._def?.type ?? current;
804
- continue;
805
- }
806
- if (typeName === "ZodCatch") {
807
- current = current._def?.innerType ?? current;
810
+ if (typeName === "pipe") {
811
+ const outType = current._def?.out?._def?.type;
812
+ if (outType === "transform") {
813
+ current = current._def?.in ?? current;
814
+ } else {
815
+ current = current._def?.out ?? current;
816
+ }
808
817
  continue;
809
818
  }
810
- if (typeName === "ZodReadonly") {
819
+ if (typeName === "catch" || typeName === "readonly") {
811
820
  current = current._def?.innerType ?? current;
812
821
  continue;
813
822
  }
814
- if (typeName === "ZodPipeline") {
815
- current = current._def?.out ?? current;
816
- continue;
817
- }
818
823
  break;
819
824
  }
820
825
  return {
@@ -828,81 +833,74 @@ function formatCore(schema, depth, seen) {
828
833
  return "unknown";
829
834
  }
830
835
  seen.add(schema);
831
- const typeName = schema?._def?.typeName;
836
+ const typeName = schema?._def?.type;
832
837
  switch (typeName) {
833
- case "ZodString":
838
+ case "string":
834
839
  return "string";
835
- case "ZodNumber":
840
+ case "number":
836
841
  return isIntegerNumber(schema) ? "int" : "number";
837
- case "ZodBoolean":
842
+ case "boolean":
838
843
  return "boolean";
839
- case "ZodBigInt":
844
+ case "bigint":
840
845
  return "bigint";
841
- case "ZodDate":
846
+ case "date":
842
847
  return "Date";
843
- case "ZodUndefined":
848
+ case "undefined":
844
849
  return "undefined";
845
- case "ZodNull":
850
+ case "null":
846
851
  return "null";
847
- case "ZodAny":
852
+ case "any":
848
853
  return "any";
849
- case "ZodUnknown":
854
+ case "unknown":
850
855
  return "unknown";
851
- case "ZodNever":
856
+ case "never":
852
857
  return "never";
853
- case "ZodVoid":
858
+ case "void":
854
859
  return "void";
855
- case "ZodLiteral": {
856
- const value = schema._def?.value;
860
+ case "literal": {
861
+ const value = schema._def?.values?.[0];
857
862
  return JSON.stringify(value);
858
863
  }
859
- case "ZodEnum": {
860
- const values = schema._def?.values ?? [];
861
- return values.map((value) => JSON.stringify(value)).join(" | ") || "string";
862
- }
863
- case "ZodNativeEnum": {
864
- const values = Object.values(schema._def?.values ?? {});
865
- const unique = [...new Set(values.filter((value) => typeof value !== "string" || Number.isNaN(Number(value))))];
866
- return unique.map((value) => JSON.stringify(value)).join(" | ") || "string";
864
+ case "enum": {
865
+ const entries = schema._def?.entries;
866
+ const values = Object.values(entries ?? {});
867
+ const unique = [...new Set(values.filter((v) => typeof v !== "string" || Number.isNaN(Number(v))))];
868
+ return unique.map((v) => JSON.stringify(v)).join(" | ") || "string";
867
869
  }
868
- case "ZodArray": {
869
- const inner = formatType(schema._def?.type ?? schema, depth, seen);
870
+ case "array": {
871
+ const inner = formatType(schema._def?.element ?? schema, depth, seen);
870
872
  return requiresParentheses(inner) ? `(${inner})[]` : `${inner}[]`;
871
873
  }
872
- case "ZodTuple": {
874
+ case "tuple": {
873
875
  const items = (schema._def?.items ?? []).map((item) => formatType(item, depth, seen));
874
876
  return `[${items.join(", ")}]`;
875
877
  }
876
- case "ZodUnion": {
878
+ case "union": {
877
879
  const options = (schema._def?.options ?? []).map((option) => formatType(option, depth, seen));
878
880
  return options.join(" | ") || "unknown";
879
881
  }
880
- case "ZodDiscriminatedUnion": {
881
- const options = Array.from((schema._def?.options ?? new Map).values()).map((option) => formatType(option, depth, seen));
882
- return options.join(" | ") || "unknown";
883
- }
884
- case "ZodIntersection": {
882
+ case "intersection": {
885
883
  const left = formatType(schema._def?.left ?? schema, depth, seen);
886
884
  const right = formatType(schema._def?.right ?? schema, depth, seen);
887
885
  return `${left} & ${right}`;
888
886
  }
889
- case "ZodRecord": {
887
+ case "record": {
890
888
  const keyType = formatType(schema._def?.keyType ?? schema, depth, seen);
891
889
  const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
892
890
  return `Record<${keyType}, ${valueType}>`;
893
891
  }
894
- case "ZodMap": {
892
+ case "map": {
895
893
  const keyType = formatType(schema._def?.keyType ?? schema, depth, seen);
896
894
  const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
897
895
  return `Map<${keyType}, ${valueType}>`;
898
896
  }
899
- case "ZodSet": {
897
+ case "set": {
900
898
  const valueType = formatType(schema._def?.valueType ?? schema, depth, seen);
901
899
  return `Set<${valueType}>`;
902
900
  }
903
- case "ZodObject":
901
+ case "object":
904
902
  return formatObject(schema, depth, seen);
905
- case "ZodLazy":
903
+ case "lazy":
906
904
  return "unknown";
907
905
  default:
908
906
  return "unknown";
@@ -938,40 +936,28 @@ function requiresParentheses(typeText) {
938
936
  }
939
937
  function isIntegerNumber(schema) {
940
938
  const checks = schema._def?.checks ?? [];
941
- return checks.some((check) => check.kind === "int");
939
+ return checks.some((check) => check.isInt === true);
942
940
  }
943
941
  function readSchemaDescription(schema) {
944
942
  let current = schema;
945
- while (current?._def?.typeName) {
946
- const direct = current._def.description;
947
- if (typeof direct === "string" && direct.trim().length > 0) {
948
- return sanitizeDescription(direct);
943
+ while (current?._def?.type) {
944
+ const desc = current.description;
945
+ if (typeof desc === "string" && desc.trim().length > 0) {
946
+ return sanitizeDescription(desc);
949
947
  }
950
- const fallback = current.description;
951
- if (typeof fallback === "string" && fallback.trim().length > 0) {
952
- return sanitizeDescription(fallback);
953
- }
954
- const typeName = current._def.typeName;
955
- if (typeName === "ZodOptional" || typeName === "ZodDefault" || typeName === "ZodNullable") {
948
+ const typeName = current._def.type;
949
+ if (typeName === "optional" || typeName === "default" || typeName === "nullable") {
956
950
  current = current._def.innerType ?? current;
957
951
  continue;
958
952
  }
959
- if (typeName === "ZodEffects") {
960
- current = current._def.schema ?? current;
961
- continue;
962
- }
963
- if (typeName === "ZodBranded") {
964
- current = current._def.type ?? current;
953
+ if (typeName === "pipe") {
954
+ current = current._def.in ?? current;
965
955
  continue;
966
956
  }
967
- if (typeName === "ZodCatch" || typeName === "ZodReadonly") {
957
+ if (typeName === "catch" || typeName === "readonly") {
968
958
  current = current._def.innerType ?? current;
969
959
  continue;
970
960
  }
971
- if (typeName === "ZodPipeline") {
972
- current = current._def.out ?? current;
973
- continue;
974
- }
975
961
  break;
976
962
  }
977
963
  return;
@@ -2256,6 +2242,12 @@ function buildHeaders(options) {
2256
2242
  };
2257
2243
  }
2258
2244
  function buildMessages(request) {
2245
+ if (Array.isArray(request.messages) && request.messages.length > 0) {
2246
+ return request.messages.map((message) => toOpenAIMessage(message));
2247
+ }
2248
+ if (typeof request.prompt !== "string" || request.prompt.trim().length === 0) {
2249
+ throw new Error("LLMRequest must include a prompt or messages.");
2250
+ }
2259
2251
  const messages = [];
2260
2252
  if (request.systemPrompt) {
2261
2253
  messages.push({ role: "system", content: request.systemPrompt });
@@ -2267,18 +2259,16 @@ function buildResponsesInput(request) {
2267
2259
  if (isRecord2(request.body) && "input" in request.body) {
2268
2260
  return request.body.input;
2269
2261
  }
2270
- const input = [];
2271
- if (request.systemPrompt) {
2272
- input.push({
2273
- role: "system",
2274
- content: request.systemPrompt
2275
- });
2262
+ if (Array.isArray(request.messages) && request.messages.length > 0) {
2263
+ return request.messages.map((message) => toOpenAIMessage(message));
2276
2264
  }
2277
- input.push({
2278
- role: "user",
2279
- content: request.prompt
2280
- });
2281
- return input;
2265
+ return buildMessages(request);
2266
+ }
2267
+ function toOpenAIMessage(message) {
2268
+ return {
2269
+ role: message.role,
2270
+ content: message.content
2271
+ };
2282
2272
  }
2283
2273
  function toResponsesTools(tools) {
2284
2274
  if (!Array.isArray(tools) || tools.length === 0) {
@@ -2690,6 +2680,7 @@ function createAnthropicCompatibleAdapter(options) {
2690
2680
  if (hasMCPClients(request.mcpClients)) {
2691
2681
  return streamWithMCPToolLoop(options, fetcher, path, request, callbacks);
2692
2682
  }
2683
+ const input = resolveAnthropicInput(request);
2693
2684
  const response = await fetcher(buildURL(options.baseURL, path), {
2694
2685
  method: "POST",
2695
2686
  headers: buildHeaders2(options),
@@ -2697,8 +2688,8 @@ function createAnthropicCompatibleAdapter(options) {
2697
2688
  ...options.defaultBody,
2698
2689
  ...request.body,
2699
2690
  model: options.model,
2700
- system: request.systemPrompt,
2701
- messages: [{ role: "user", content: request.prompt }],
2691
+ system: input.systemPrompt,
2692
+ messages: input.messages,
2702
2693
  temperature: request.temperature,
2703
2694
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2704
2695
  stream: true
@@ -2749,6 +2740,7 @@ function createAnthropicCompatibleAdapter(options) {
2749
2740
  };
2750
2741
  }
2751
2742
  async function completePassThrough(options, fetcher, path, request) {
2743
+ const input = resolveAnthropicInput(request);
2752
2744
  const response = await fetcher(buildURL(options.baseURL, path), {
2753
2745
  method: "POST",
2754
2746
  headers: buildHeaders2(options),
@@ -2756,8 +2748,8 @@ async function completePassThrough(options, fetcher, path, request) {
2756
2748
  ...options.defaultBody,
2757
2749
  ...request.body,
2758
2750
  model: options.model,
2759
- system: request.systemPrompt,
2760
- messages: [{ role: "user", content: request.prompt }],
2751
+ system: input.systemPrompt,
2752
+ messages: input.messages,
2761
2753
  temperature: request.temperature,
2762
2754
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
2763
2755
  stream: false
@@ -2784,7 +2776,8 @@ async function completePassThrough(options, fetcher, path, request) {
2784
2776
  }
2785
2777
  async function completeWithMCPToolLoop(options, fetcher, path, request) {
2786
2778
  const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
2787
- let messages = [{ role: "user", content: request.prompt }];
2779
+ const input = resolveAnthropicInput(request);
2780
+ let messages = input.messages;
2788
2781
  let aggregatedUsage;
2789
2782
  let finishReason;
2790
2783
  let lastPayload;
@@ -2800,7 +2793,7 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
2800
2793
  ...options.defaultBody,
2801
2794
  ...request.body,
2802
2795
  model: options.model,
2803
- system: request.systemPrompt,
2796
+ system: input.systemPrompt,
2804
2797
  messages,
2805
2798
  temperature: request.temperature,
2806
2799
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
@@ -2867,7 +2860,8 @@ async function completeWithMCPToolLoop(options, fetcher, path, request) {
2867
2860
  }
2868
2861
  async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks) {
2869
2862
  const maxToolRounds = normalizeMaxToolRounds(request.maxToolRounds ?? options.defaultMaxToolRounds);
2870
- let messages = [{ role: "user", content: request.prompt }];
2863
+ const input = resolveAnthropicInput(request);
2864
+ let messages = input.messages;
2871
2865
  let aggregatedUsage;
2872
2866
  let finishReason;
2873
2867
  let lastPayload;
@@ -2884,7 +2878,7 @@ async function streamWithMCPToolLoop(options, fetcher, path, request, callbacks)
2884
2878
  ...options.defaultBody,
2885
2879
  ...request.body,
2886
2880
  model: options.model,
2887
- system: request.systemPrompt,
2881
+ system: input.systemPrompt,
2888
2882
  messages,
2889
2883
  temperature: request.temperature,
2890
2884
  max_tokens: resolveMaxTokens(request.maxTokens, options.defaultMaxTokens),
@@ -2995,6 +2989,59 @@ function buildHeaders2(options) {
2995
2989
  ...options.headers
2996
2990
  };
2997
2991
  }
2992
+ function resolveAnthropicInput(request) {
2993
+ if (Array.isArray(request.messages) && request.messages.length > 0) {
2994
+ return toAnthropicInput(request.messages);
2995
+ }
2996
+ if (typeof request.prompt !== "string" || request.prompt.trim().length === 0) {
2997
+ throw new Error("LLMRequest must include a prompt or messages.");
2998
+ }
2999
+ return {
3000
+ systemPrompt: request.systemPrompt,
3001
+ messages: [{ role: "user", content: request.prompt }]
3002
+ };
3003
+ }
3004
+ function toAnthropicInput(messages) {
3005
+ const systemParts = [];
3006
+ const normalizedMessages = [];
3007
+ let sawNonSystem = false;
3008
+ for (const message of messages) {
3009
+ if (message.role === "system") {
3010
+ if (sawNonSystem) {
3011
+ throw new Error('Anthropic-compatible messages only support "system" turns at the beginning.');
3012
+ }
3013
+ systemParts.push(stringifyAnthropicSystemContent(message.content));
3014
+ continue;
3015
+ }
3016
+ sawNonSystem = true;
3017
+ normalizedMessages.push({
3018
+ role: message.role,
3019
+ content: message.content
3020
+ });
3021
+ }
3022
+ if (normalizedMessages.length === 0) {
3023
+ throw new Error("Anthropic-compatible requests require at least one non-system message.");
3024
+ }
3025
+ return {
3026
+ systemPrompt: systemParts.length > 0 ? systemParts.join(`
3027
+
3028
+ `) : undefined,
3029
+ messages: normalizedMessages
3030
+ };
3031
+ }
3032
+ function stringifyAnthropicSystemContent(content) {
3033
+ if (typeof content === "string") {
3034
+ return content;
3035
+ }
3036
+ if (content === null || content === undefined) {
3037
+ return "";
3038
+ }
3039
+ try {
3040
+ return JSON.stringify(content, null, 2) ?? "";
3041
+ } catch {
3042
+ return String(content);
3043
+ }
3044
+ }
2998
3045
  function resolveMaxTokens(value, fallback) {
2999
3046
  const requested = toFiniteNumber(value);
3000
3047
  if (requested !== undefined && requested > 0) {
@@ -3881,22 +3928,25 @@ async function structured(adapter, schemaOrOptions, promptInput, callOptions) {
3881
3928
  const useOutdent = normalized.outdent ?? true;
3882
3929
  const resolvedPrompt = applyPromptOutdent(resolvePrompt(normalized.prompt, { mode }), useOutdent);
3883
3930
  const resolvedSystemPrompt = applyOutdentToOptionalPrompt(normalized.systemPrompt, useOutdent);
3884
- const prompt = shouldInjectFormat(resolvedPrompt.prompt, normalized.schemaInstruction) ? formatPrompt(normalized.schema, resolvedPrompt.prompt, {
3885
- schemaInstruction: normalized.schemaInstruction
3886
- }) : resolvedPrompt.prompt.trim();
3887
- const systemPrompt = mergeSystemPrompts(resolvedPrompt.systemPrompt, resolvedSystemPrompt);
3931
+ const preparedPrompt = prepareStructuredPromptPayload(resolvedPrompt, resolvedSystemPrompt, normalized.schema, normalized.schemaInstruction);
3932
+ const resolvedRequest = normalized.timeout?.tool !== undefined && normalized.request?.mcpClients !== undefined ? {
3933
+ ...normalized.request,
3934
+ mcpClients: applyToolTimeout(normalized.request.mcpClients, normalized.timeout.tool)
3935
+ } : normalized.request;
3888
3936
  const first = await executeAttempt(adapter, {
3889
- prompt,
3937
+ prompt: preparedPrompt.prompt,
3938
+ messages: preparedPrompt.messages,
3890
3939
  schema: normalized.schema,
3891
3940
  parseOptions,
3892
3941
  stream: streamConfig,
3893
- request: normalized.request,
3894
- systemPrompt,
3942
+ request: resolvedRequest,
3943
+ systemPrompt: preparedPrompt.systemPrompt,
3895
3944
  observe: normalized.observe,
3896
3945
  debug: debugConfig,
3897
3946
  attemptNumber: 1,
3898
3947
  selfHeal: false,
3899
- selfHealEnabled: selfHealConfig.enabled
3948
+ selfHealEnabled: selfHealConfig.enabled,
3949
+ timeout: normalized.timeout
3900
3950
  });
3901
3951
  attempts.push(first.trace);
3902
3952
  if (first.trace.success) {
@@ -3950,13 +4000,14 @@ async function structured(adapter, schemaOrOptions, promptInput, callOptions) {
3950
4000
  schema: normalized.schema,
3951
4001
  parseOptions,
3952
4002
  stream: streamConfig,
3953
- request: normalized.request,
3954
- systemPrompt,
4003
+ request: resolvedRequest,
4004
+ systemPrompt: preparedPrompt.systemPrompt,
3955
4005
  observe: normalized.observe,
3956
4006
  debug: debugConfig,
3957
4007
  attemptNumber,
3958
4008
  selfHeal: true,
3959
- selfHealEnabled: selfHealConfig.enabled
4009
+ selfHealEnabled: selfHealConfig.enabled,
4010
+ timeout: normalized.timeout
3960
4011
  });
3961
4012
  attempts.push(healed.trace);
3962
4013
  if (healed.trace.success) {
@@ -4013,12 +4064,15 @@ function isPromptResolver(value) {
4013
4064
  return typeof value === "object" && value !== null && "resolvePrompt" in value && typeof value.resolvePrompt === "function";
4014
4065
  }
4015
4066
  function normalizePromptPayload(value) {
4016
- if (typeof value.prompt !== "string") {
4017
- throw new Error("Structured prompt payload must include a string prompt.");
4067
+ const prompt = typeof value.prompt === "string" ? value.prompt : undefined;
4068
+ const messages = Array.isArray(value.messages) ? value.messages.filter(isLLMMessage) : undefined;
4069
+ if ((!prompt || prompt.trim().length === 0) && (!messages || messages.length === 0)) {
4070
+ throw new Error("Structured prompt payload must include a non-empty prompt or messages.");
4018
4071
  }
4019
4072
  return {
4020
- prompt: value.prompt,
4021
- systemPrompt: typeof value.systemPrompt === "string" ? value.systemPrompt : undefined
4073
+ prompt,
4074
+ systemPrompt: typeof value.systemPrompt === "string" ? value.systemPrompt : undefined,
4075
+ messages: messages && messages.length > 0 ? messages.map((message) => ({ ...message })) : undefined
4022
4076
  };
4023
4077
  }
4024
4078
  function applyPromptOutdent(payload, enabled) {
@@ -4026,10 +4080,24 @@ function applyPromptOutdent(payload, enabled) {
4026
4080
  return payload;
4027
4081
  }
4028
4082
  return {
4029
- prompt: structuredOutdent.string(payload.prompt),
4030
- systemPrompt: applyOutdentToOptionalPrompt(payload.systemPrompt, enabled)
4083
+ prompt: typeof payload.prompt === "string" ? structuredOutdent.string(payload.prompt) : undefined,
4084
+ systemPrompt: applyOutdentToOptionalPrompt(payload.systemPrompt, enabled),
4085
+ messages: payload.messages?.map((message) => ({
4086
+ ...message,
4087
+ content: typeof message.content === "string" ? structuredOutdent.string(message.content) : message.content
4088
+ }))
4031
4089
  };
4032
4090
  }
4091
+ function isLLMMessage(value) {
4092
+ if (typeof value !== "object" || value === null) {
4093
+ return false;
4094
+ }
4095
+ const candidate = value;
4096
+ if (candidate.role !== "system" && candidate.role !== "user" && candidate.role !== "assistant" && candidate.role !== "tool") {
4097
+ return false;
4098
+ }
4099
+ return "content" in candidate;
4100
+ }
4033
4101
  function applyOutdentToOptionalPrompt(value, enabled) {
4034
4102
  if (!enabled || typeof value !== "string") {
4035
4103
  return value;
@@ -4045,6 +4113,73 @@ function mergeSystemPrompts(primary, secondary) {
4045
4113
 
4046
4114
  `);
4047
4115
  }
4116
+ function prepareStructuredPromptPayload(payload, systemPrompt, schema, schemaInstruction) {
4117
+ if (Array.isArray(payload.messages) && payload.messages.length > 0) {
4118
+ const messages = payload.messages.map((message) => ({ ...message }));
4119
+ const mergedSystemPrompt = mergeSystemPrompts(payload.systemPrompt, systemPrompt);
4120
+ const systemMessages = mergedSystemPrompt ? [{ role: "system", content: mergedSystemPrompt }] : [];
4121
+ return {
4122
+ messages: injectStructuredFormatIntoMessages([...systemMessages, ...messages], schema, schemaInstruction)
4123
+ };
4124
+ }
4125
+ const resolvedPrompt = payload.prompt?.trim();
4126
+ if (!resolvedPrompt) {
4127
+ throw new Error("Structured prompt payload must include a non-empty prompt or messages.");
4128
+ }
4129
+ return {
4130
+ prompt: shouldInjectFormat(resolvedPrompt, schemaInstruction) ? formatPrompt(schema, resolvedPrompt, {
4131
+ schemaInstruction
4132
+ }) : resolvedPrompt,
4133
+ systemPrompt: mergeSystemPrompts(payload.systemPrompt, systemPrompt)
4134
+ };
4135
+ }
4136
+ function injectStructuredFormatIntoMessages(messages, schema, schemaInstruction) {
4137
+ const lastUserIndex = findLastUserMessageIndex(messages);
4138
+ if (lastUserIndex === -1) {
4139
+ throw new Error("Structured prompts with messages must include at least one user message.");
4140
+ }
4141
+ const target = messages[lastUserIndex];
4142
+ if (Array.isArray(target?.content)) {
4143
+ const parts = target.content;
4144
+ const textIndex = parts.findIndex((p) => p.type === "text");
4145
+ const existingText = textIndex !== -1 ? (parts[textIndex]?.text ?? "").trim() : "";
4146
+ const formatted2 = shouldInjectFormat(existingText, schemaInstruction) ? formatPrompt(schema, existingText, { schemaInstruction }) : existingText;
4147
+ let newParts;
4148
+ if (textIndex !== -1) {
4149
+ newParts = parts.map((p, i) => i === textIndex ? { ...p, text: formatted2 } : p);
4150
+ } else {
4151
+ newParts = [{ type: "text", text: formatted2 }, ...parts];
4152
+ }
4153
+ return messages.map((message, index) => index === lastUserIndex ? { ...message, content: newParts } : message);
4154
+ }
4155
+ const content = typeof target?.content === "string" ? target.content.trim() : stringifyPromptContent(target?.content);
4156
+ const formatted = shouldInjectFormat(content, schemaInstruction) ? formatPrompt(schema, content, { schemaInstruction }) : content.trim();
4157
+ return messages.map((message, index) => index === lastUserIndex ? {
4158
+ ...message,
4159
+ content: formatted
4160
+ } : message);
4161
+ }
4162
+ function findLastUserMessageIndex(messages) {
4163
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
4164
+ if (messages[index]?.role === "user") {
4165
+ return index;
4166
+ }
4167
+ }
4168
+ return -1;
4169
+ }
4170
+ function stringifyPromptContent(content) {
4171
+ if (typeof content === "string") {
4172
+ return content;
4173
+ }
4174
+ if (content === null || content === undefined) {
4175
+ return "";
4176
+ }
4177
+ try {
4178
+ return JSON.stringify(content, null, 2) ?? "";
4179
+ } catch {
4180
+ return String(content);
4181
+ }
4182
+ }
4048
4183
  function shouldInjectFormat(prompt, schemaInstruction) {
4049
4184
  const instruction = resolveSchemaInstruction(schemaInstruction);
4050
4185
  return !prompt.trimStart().startsWith(instruction);
@@ -4223,6 +4358,7 @@ function normalizeDebugConfig(option) {
4223
4358
  async function executeAttempt(adapter, input) {
4224
4359
  const response = await callModel(adapter, {
4225
4360
  prompt: input.prompt,
4361
+ messages: input.messages,
4226
4362
  systemPrompt: input.systemPrompt,
4227
4363
  request: input.request,
4228
4364
  stream: input.stream,
@@ -4230,7 +4366,8 @@ async function executeAttempt(adapter, input) {
4230
4366
  debug: input.debug,
4231
4367
  attempt: input.attemptNumber,
4232
4368
  selfHeal: input.selfHeal,
4233
- selfHealEnabled: input.selfHealEnabled
4369
+ selfHealEnabled: input.selfHealEnabled,
4370
+ timeout: input.timeout
4234
4371
  });
4235
4372
  const parsed = parseWithObserve(response.text, input.schema, input.parseOptions, {
4236
4373
  observe: input.observe,
@@ -4257,9 +4394,32 @@ async function executeAttempt(adapter, input) {
4257
4394
  trace
4258
4395
  };
4259
4396
  }
4397
+ function withToolTimeout(client, toolTimeoutMs) {
4398
+ return {
4399
+ id: client.id,
4400
+ listTools: client.listTools.bind(client),
4401
+ close: client.close?.bind(client),
4402
+ async callTool(params) {
4403
+ let timeoutId;
4404
+ const timeoutPromise = new Promise((_, reject) => {
4405
+ timeoutId = setTimeout(() => reject(new Error(`Tool call timed out after ${toolTimeoutMs}ms`)), toolTimeoutMs);
4406
+ });
4407
+ try {
4408
+ return await Promise.race([client.callTool(params), timeoutPromise]);
4409
+ } finally {
4410
+ clearTimeout(timeoutId);
4411
+ }
4412
+ }
4413
+ };
4414
+ }
4415
+ function applyToolTimeout(clients, toolTimeoutMs) {
4416
+ return clients.map((client) => withToolTimeout(client, toolTimeoutMs));
4417
+ }
4260
4418
  async function callModel(adapter, options) {
4419
+ const requestSignal = options.request?.signal ?? (options.timeout?.request !== undefined ? AbortSignal.timeout(options.timeout.request) : undefined);
4261
4420
  const requestPayload = {
4262
4421
  prompt: options.prompt,
4422
+ messages: options.messages,
4263
4423
  systemPrompt: options.systemPrompt,
4264
4424
  temperature: options.request?.temperature,
4265
4425
  maxTokens: options.request?.maxTokens,
@@ -4270,7 +4430,7 @@ async function callModel(adapter, options) {
4270
4430
  onToolExecution: options.request?.onToolExecution,
4271
4431
  toolDebug: options.request?.toolDebug,
4272
4432
  body: options.request?.body,
4273
- signal: options.request?.signal
4433
+ signal: requestSignal
4274
4434
  };
4275
4435
  emitDebugRequest(options.debug, {
4276
4436
  provider: adapter.provider,
@@ -4570,6 +4730,7 @@ function emitObserve(observe, event) {
4570
4730
  }
4571
4731
  function emitDebugRequest(config, input) {
4572
4732
  const requestBody = input.requestPayload.body !== undefined ? JSON.stringify(input.requestPayload.body, null, 2) : "(none)";
4733
+ const requestMessages = input.requestPayload.messages !== undefined ? JSON.stringify(input.requestPayload.messages, null, 2) : "(none)";
4573
4734
  const lines = [
4574
4735
  color(config, title(config, [
4575
4736
  "[structured][request]",
@@ -4583,7 +4744,9 @@ function emitDebugRequest(config, input) {
4583
4744
  `stream=${input.stream}`
4584
4745
  ].join(" ")),
4585
4746
  color(config, "prompt:", "yellow"),
4586
- input.requestPayload.prompt,
4747
+ input.requestPayload.prompt ?? "(none)",
4748
+ color(config, "messages:", "yellow"),
4749
+ requestMessages,
4587
4750
  color(config, "systemPrompt:", "yellow"),
4588
4751
  input.requestPayload.systemPrompt ?? "(none)",
4589
4752
  color(config, "request.body:", "yellow"),
@@ -4650,7 +4813,8 @@ function mergeStructuredOptions(defaults, overrides) {
4650
4813
  },
4651
4814
  stream: mergeObjectLike(defaults?.stream, overrides?.stream),
4652
4815
  selfHeal: mergeObjectLike(defaults?.selfHeal, overrides?.selfHeal),
4653
- debug: mergeObjectLike(defaults?.debug, overrides?.debug)
4816
+ debug: mergeObjectLike(defaults?.debug, overrides?.debug),
4817
+ timeout: mergeObjectLike(defaults?.timeout, overrides?.timeout)
4654
4818
  };
4655
4819
  }
4656
4820
  function mergeObjectLike(defaults, overrides) {
@@ -4739,6 +4903,53 @@ function toImplementation(clientInfo) {
4739
4903
  version: clientInfo?.version ?? "0.1.0"
4740
4904
  };
4741
4905
  }
4906
+ // src/image.ts
4907
+ var import_path = require("path");
4908
+ var IMAGE_SIZE_MAP = {
4909
+ low: 256,
4910
+ mid: 512,
4911
+ high: 1024,
4912
+ xhigh: 1280
4913
+ };
4914
+ var IMAGE_MIME_TYPES = {
4915
+ ".png": "image/png",
4916
+ ".jpg": "image/jpeg",
4917
+ ".jpeg": "image/jpeg",
4918
+ ".gif": "image/gif",
4919
+ ".webp": "image/webp"
4920
+ };
4921
+ var MIME_TO_SHARP_FORMAT = {
4922
+ "image/jpeg": "jpeg",
4923
+ "image/png": "png",
4924
+ "image/webp": "webp",
4925
+ "image/gif": "gif"
4926
+ };
4927
+ function images(input) {
4928
+ const inputs = Array.isArray(input) ? input : [input];
4929
+ return inputs.map(({ base64, mimeType }) => ({
4930
+ type: "image_url",
4931
+ image_url: { url: `data:${mimeType};base64,${base64}` }
4932
+ }));
4933
+ }
4934
+ async function resizeImage(source, size, mimeType) {
4935
+ const resolvedMime = mimeType ?? (typeof source === "string" ? IMAGE_MIME_TYPES[import_path.extname(source).toLowerCase()] ?? "image/jpeg" : "image/jpeg");
4936
+ let sharp;
4937
+ try {
4938
+ sharp = (await import("sharp")).default;
4939
+ } catch {
4940
+ throw new Error('resizeImage() requires "sharp" to be installed. Run: bun add sharp');
4941
+ }
4942
+ const input = source instanceof ArrayBuffer ? Buffer.from(source) : source;
4943
+ let img = sharp(input);
4944
+ if (size !== "raw") {
4945
+ const targetPx = typeof size === "number" ? size : IMAGE_SIZE_MAP[size];
4946
+ img = img.resize(targetPx, targetPx, { fit: "inside", withoutEnlargement: true });
4947
+ }
4948
+ const sharpFormat = MIME_TO_SHARP_FORMAT[resolvedMime] ?? "jpeg";
4949
+ const outputMime = MIME_TO_SHARP_FORMAT[resolvedMime] ? resolvedMime : "image/jpeg";
4950
+ const buf = await img.toFormat(sharpFormat).toBuffer();
4951
+ return { base64: buf.toString("base64"), mimeType: outputMime };
4952
+ }
4742
4953
  // src/prompt.ts
4743
4954
  function toPromptString(value) {
4744
4955
  if (value === null || value === undefined) {
@@ -4800,35 +5011,28 @@ function toPromptMessage(input, values) {
4800
5011
  }
4801
5012
  return renderPromptTemplate(input, values);
4802
5013
  }
4803
- function joinMessages(messages) {
4804
- return messages.join(`
4805
-
4806
- `);
4807
- }
4808
5014
 
4809
5015
  class PromptMessageBuilderImpl {
4810
- systemMessages = [];
4811
- userMessages = [];
5016
+ messages = [];
4812
5017
  system(input, ...values) {
4813
- const message = toPromptMessage(input, values);
4814
- if (message.length > 0) {
4815
- this.systemMessages.push(message);
4816
- }
4817
- return this;
5018
+ return this.pushMessage("system", input, values);
4818
5019
  }
4819
5020
  user(input, ...values) {
5021
+ return this.pushMessage("user", input, values);
5022
+ }
5023
+ assistant(input, ...values) {
5024
+ return this.pushMessage("assistant", input, values);
5025
+ }
5026
+ pushMessage(role, input, values) {
4820
5027
  const message = toPromptMessage(input, values);
4821
5028
  if (message.length > 0) {
4822
- this.userMessages.push(message);
5029
+ this.messages.push({ role, content: message });
4823
5030
  }
4824
5031
  return this;
4825
5032
  }
4826
5033
  build() {
4827
- const prompt = joinMessages(this.userMessages);
4828
- const systemPrompt = joinMessages(this.systemMessages);
4829
5034
  return {
4830
- prompt,
4831
- systemPrompt: systemPrompt.length > 0 ? systemPrompt : undefined
5035
+ messages: this.messages.map((message) => ({ ...message }))
4832
5036
  };
4833
5037
  }
4834
5038
  resolvePrompt(_context) {
@@ -4938,8 +5142,8 @@ function inferSchemaExample(schema) {
4938
5142
  }
4939
5143
  function getObjectShape(schema) {
4940
5144
  const unwrapped = unwrap2(schema).schema;
4941
- const typeName = unwrapped._def?.typeName;
4942
- if (typeName !== "ZodObject") {
5145
+ const typeName = unwrapped._def?.type;
5146
+ if (typeName !== "object") {
4943
5147
  return null;
4944
5148
  }
4945
5149
  const rawShape = unwrapped._def?.shape;
@@ -4950,33 +5154,25 @@ function getObjectShape(schema) {
4950
5154
  }
4951
5155
  function readDefaultValue(schema) {
4952
5156
  let current = schema;
4953
- while (current?._def?.typeName) {
4954
- const typeName = current._def.typeName;
4955
- if (typeName === "ZodDefault") {
4956
- const raw = current._def.defaultValue;
4957
- if (typeof raw === "function") {
4958
- try {
5157
+ while (current?._def?.type) {
5158
+ const typeName = current._def.type;
5159
+ if (typeName === "default") {
5160
+ try {
5161
+ const raw = current._def.defaultValue;
5162
+ if (typeof raw === "function") {
4959
5163
  return raw();
4960
- } catch {
4961
- return;
4962
5164
  }
5165
+ return raw;
5166
+ } catch {
5167
+ return;
4963
5168
  }
4964
- return raw;
4965
5169
  }
4966
- if (typeName === "ZodOptional" || typeName === "ZodNullable" || typeName === "ZodCatch" || typeName === "ZodReadonly") {
5170
+ if (typeName === "optional" || typeName === "nullable" || typeName === "catch" || typeName === "readonly") {
4967
5171
  current = current._def.innerType ?? current;
4968
5172
  continue;
4969
5173
  }
4970
- if (typeName === "ZodEffects") {
4971
- current = current._def.schema ?? current;
4972
- continue;
4973
- }
4974
- if (typeName === "ZodBranded") {
4975
- current = current._def.type ?? current;
4976
- continue;
4977
- }
4978
- if (typeName === "ZodPipeline") {
4979
- current = current._def.out ?? current;
5174
+ if (typeName === "pipe") {
5175
+ current = current._def.in ?? current;
4980
5176
  continue;
4981
5177
  }
4982
5178
  return;
@@ -4985,34 +5181,22 @@ function readDefaultValue(schema) {
4985
5181
  }
4986
5182
  function readSchemaDescription2(schema) {
4987
5183
  let current = schema;
4988
- while (current?._def?.typeName) {
4989
- const raw = current._def.description;
4990
- if (typeof raw === "string" && raw.trim().length > 0) {
4991
- return raw.trim();
4992
- }
4993
- const fallback = current.description;
4994
- if (typeof fallback === "string" && fallback.trim().length > 0) {
4995
- return fallback.trim();
5184
+ while (current?._def?.type) {
5185
+ const desc = current.description;
5186
+ if (typeof desc === "string" && desc.trim().length > 0) {
5187
+ return desc.trim();
4996
5188
  }
4997
- const typeName = current._def.typeName;
4998
- if (typeName === "ZodOptional" || typeName === "ZodDefault" || typeName === "ZodNullable") {
5189
+ const typeName = current._def.type;
5190
+ if (typeName === "optional" || typeName === "default" || typeName === "nullable") {
4999
5191
  current = current._def.innerType ?? current;
5000
5192
  continue;
5001
5193
  }
5002
- if (typeName === "ZodCatch" || typeName === "ZodReadonly") {
5194
+ if (typeName === "catch" || typeName === "readonly") {
5003
5195
  current = current._def.innerType ?? current;
5004
5196
  continue;
5005
5197
  }
5006
- if (typeName === "ZodEffects") {
5007
- current = current._def.schema ?? current;
5008
- continue;
5009
- }
5010
- if (typeName === "ZodBranded") {
5011
- current = current._def.type ?? current;
5012
- continue;
5013
- }
5014
- if (typeName === "ZodPipeline") {
5015
- current = current._def.out ?? current;
5198
+ if (typeName === "pipe") {
5199
+ current = current._def.in ?? current;
5016
5200
  continue;
5017
5201
  }
5018
5202
  break;
@@ -5022,27 +5206,19 @@ function readSchemaDescription2(schema) {
5022
5206
  function unwrap2(schema) {
5023
5207
  let current = schema;
5024
5208
  let optional = false;
5025
- while (current?._def?.typeName) {
5026
- const typeName = current._def.typeName;
5027
- if (typeName === "ZodOptional" || typeName === "ZodDefault") {
5209
+ while (current?._def?.type) {
5210
+ const typeName = current._def.type;
5211
+ if (typeName === "optional" || typeName === "default") {
5028
5212
  optional = true;
5029
5213
  current = current._def.innerType ?? current;
5030
5214
  continue;
5031
5215
  }
5032
- if (typeName === "ZodNullable" || typeName === "ZodCatch" || typeName === "ZodReadonly") {
5216
+ if (typeName === "nullable" || typeName === "catch" || typeName === "readonly") {
5033
5217
  current = current._def.innerType ?? current;
5034
5218
  continue;
5035
5219
  }
5036
- if (typeName === "ZodEffects") {
5037
- current = current._def.schema ?? current;
5038
- continue;
5039
- }
5040
- if (typeName === "ZodBranded") {
5041
- current = current._def.type ?? current;
5042
- continue;
5043
- }
5044
- if (typeName === "ZodPipeline") {
5045
- current = current._def.out ?? current;
5220
+ if (typeName === "pipe") {
5221
+ current = current._def.in ?? current;
5046
5222
  continue;
5047
5223
  }
5048
5224
  break;