@ax-llm/ax 12.0.16 → 12.0.17

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/index.cjs CHANGED
@@ -65,6 +65,7 @@ __export(index_exports, {
65
65
  AxAIOpenAIResponsesBase: () => AxAIOpenAIResponsesBase,
66
66
  AxAIOpenAIResponsesImpl: () => AxAIOpenAIResponsesImpl,
67
67
  AxAIOpenAIResponsesModel: () => AxAIOpenAIResponsesModel,
68
+ AxAIRefusalError: () => AxAIRefusalError,
68
69
  AxAIReka: () => AxAIReka,
69
70
  AxAIRekaModel: () => AxAIRekaModel,
70
71
  AxAIServiceAbortedError: () => AxAIServiceAbortedError,
@@ -96,6 +97,7 @@ __export(index_exports, {
96
97
  AxDockerSession: () => AxDockerSession,
97
98
  AxEmbeddingAdapter: () => AxEmbeddingAdapter,
98
99
  AxEvalUtil: () => AxEvalUtil,
100
+ AxFlow: () => AxFlow,
99
101
  AxFunctionError: () => AxFunctionError,
100
102
  AxFunctionProcessor: () => AxFunctionProcessor,
101
103
  AxGen: () => AxGen,
@@ -184,74 +186,6 @@ __export(index_exports, {
184
186
  });
185
187
  module.exports = __toCommonJS(index_exports);
186
188
 
187
- // ai/base.ts
188
- var import_crypto2 = __toESM(require("crypto"), 1);
189
- var import_api2 = require("@opentelemetry/api");
190
-
191
- // trace/trace.ts
192
- var axSpanAttributes = {
193
- // LLM
194
- LLM_SYSTEM: "gen_ai.system",
195
- LLM_OPERATION_NAME: "gen_ai.operation.name",
196
- LLM_REQUEST_MODEL: "gen_ai.request.model",
197
- LLM_REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
198
- LLM_REQUEST_TEMPERATURE: "gen_ai.request.temperature",
199
- LLM_REQUEST_TOP_K: "gen_ai.request.top_k",
200
- LLM_REQUEST_FREQUENCY_PENALTY: "gen_ai.request.frequency_penalty",
201
- LLM_REQUEST_PRESENCE_PENALTY: "gen_ai.request.presence_penalty",
202
- LLM_REQUEST_STOP_SEQUENCES: "gen_ai.request.stop_sequences",
203
- LLM_REQUEST_LLM_IS_STREAMING: "gen_ai.request.llm_is_streaming",
204
- LLM_REQUEST_TOP_P: "gen_ai.request.top_p",
205
- LLM_USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
206
- LLM_USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
207
- LLM_USAGE_TOTAL_TOKENS: "gen_ai.usage.total_tokens",
208
- LLM_USAGE_THOUGHTS_TOKENS: "gen_ai.usage.thoughts_tokens",
209
- // Vector DB
210
- DB_SYSTEM: "db.system",
211
- DB_TABLE: "db.table",
212
- DB_NAMESPACE: "db.namespace",
213
- DB_ID: "db.id",
214
- DB_QUERY_TEXT: "db.query.text",
215
- DB_VECTOR: "db.vector",
216
- DB_OPERATION_NAME: "db.operation.name",
217
- DB_VECTOR_QUERY_TOP_K: "db.vector.query.top_k",
218
- DB_QUERY_EMBEDDINGS: "db.query.embeddings",
219
- DB_QUERY_RESULT: "db.query.result",
220
- // Query Embeddings
221
- DB_QUERY_EMBEDDINGS_VECTOR: "db.query.embeddings.vector",
222
- // Query Result (canonical format)
223
- DB_QUERY_RESULT_ID: "db.query.result.id",
224
- DB_QUERY_RESULT_SCORE: "db.query.result.score",
225
- DB_QUERY_RESULT_DISTANCE: "db.query.result.distance",
226
- DB_QUERY_RESULT_METADATA: "db.query.result.metadata",
227
- DB_QUERY_RESULT_VECTOR: "db.query.result.vector",
228
- DB_QUERY_RESULT_DOCUMENT: "db.query.result.document"
229
- };
230
- var axSpanEvents = {
231
- GEN_AI_USER_MESSAGE: "gen_ai.user.message",
232
- GEN_AI_SYSTEM_MESSAGE: "gen_ai.system.message",
233
- GEN_AI_ASSISTANT_MESSAGE: "gen_ai.assistant.message",
234
- GEN_AI_TOOL_MESSAGE: "gen_ai.tool.message",
235
- // For tool messages in request & response tool calls
236
- GEN_AI_CHOICE: "gen_ai.choice",
237
- GEN_AI_USAGE: "gen_ai.usage"
238
- };
239
- var AxLLMRequestTypeValues = /* @__PURE__ */ ((AxLLMRequestTypeValues2) => {
240
- AxLLMRequestTypeValues2["COMPLETION"] = "completion";
241
- AxLLMRequestTypeValues2["CHAT"] = "chat";
242
- AxLLMRequestTypeValues2["RERANK"] = "rerank";
243
- AxLLMRequestTypeValues2["UNKNOWN"] = "unknown";
244
- return AxLLMRequestTypeValues2;
245
- })(AxLLMRequestTypeValues || {});
246
- var AxSpanKindValues = /* @__PURE__ */ ((AxSpanKindValues2) => {
247
- AxSpanKindValues2["WORKFLOW"] = "workflow";
248
- AxSpanKindValues2["TASK"] = "task";
249
- AxSpanKindValues2["AGENT"] = "agent";
250
- AxSpanKindValues2["TOOL"] = "tool";
251
- AxSpanKindValues2["UNKNOWN"] = "unknown";
252
- return AxSpanKindValues2;
253
- })(AxSpanKindValues || {});
254
-
255
189
  // util/apicall.ts
256
190
  var import_crypto = __toESM(require("crypto"), 1);
257
191
  var import_web3 = require("stream/web");
@@ -500,6 +434,33 @@ var AxAIServiceAuthenticationError = class extends AxAIServiceError {
500
434
  this.name = this.constructor.name;
501
435
  }
502
436
  };
437
+ var AxAIRefusalError = class extends Error {
438
+ constructor(refusalMessage, model, requestId) {
439
+ super(`Model refused to fulfill request: ${refusalMessage}`);
440
+ this.refusalMessage = refusalMessage;
441
+ this.model = model;
442
+ this.requestId = requestId;
443
+ this.name = "AxAIRefusalError";
444
+ this.timestamp = (/* @__PURE__ */ new Date()).toISOString();
445
+ this.errorId = import_crypto.default.randomUUID();
446
+ }
447
+ timestamp;
448
+ errorId;
449
+ toString() {
450
+ return [
451
+ `${this.name}: ${this.message}`,
452
+ `Refusal: ${this.refusalMessage}`,
453
+ this.model ? `Model: ${this.model}` : "",
454
+ this.requestId ? `Request ID: ${this.requestId}` : "",
455
+ `Timestamp: ${this.timestamp}`,
456
+ `Error ID: ${this.errorId}`
457
+ ].filter(Boolean).join("\n");
458
+ }
459
+ // For Node.js, override the custom inspect method so console.log shows our custom string.
460
+ [Symbol.for("nodejs.util.inspect.custom")](_depth, _options) {
461
+ return this.toString();
462
+ }
463
+ };
503
464
  async function safeReadResponseBody(response) {
504
465
  try {
505
466
  if (response.headers.get("content-type")?.includes("application/json")) {
@@ -803,6 +764,74 @@ var apiCall = async (api, json) => {
803
764
  }
804
765
  };
805
766
 
767
+ // ai/base.ts
768
+ var import_crypto2 = __toESM(require("crypto"), 1);
769
+ var import_api2 = require("@opentelemetry/api");
770
+
771
+ // trace/trace.ts
772
+ var axSpanAttributes = {
773
+ // LLM
774
+ LLM_SYSTEM: "gen_ai.system",
775
+ LLM_OPERATION_NAME: "gen_ai.operation.name",
776
+ LLM_REQUEST_MODEL: "gen_ai.request.model",
777
+ LLM_REQUEST_MAX_TOKENS: "gen_ai.request.max_tokens",
778
+ LLM_REQUEST_TEMPERATURE: "gen_ai.request.temperature",
779
+ LLM_REQUEST_TOP_K: "gen_ai.request.top_k",
780
+ LLM_REQUEST_FREQUENCY_PENALTY: "gen_ai.request.frequency_penalty",
781
+ LLM_REQUEST_PRESENCE_PENALTY: "gen_ai.request.presence_penalty",
782
+ LLM_REQUEST_STOP_SEQUENCES: "gen_ai.request.stop_sequences",
783
+ LLM_REQUEST_LLM_IS_STREAMING: "gen_ai.request.llm_is_streaming",
784
+ LLM_REQUEST_TOP_P: "gen_ai.request.top_p",
785
+ LLM_USAGE_INPUT_TOKENS: "gen_ai.usage.input_tokens",
786
+ LLM_USAGE_OUTPUT_TOKENS: "gen_ai.usage.output_tokens",
787
+ LLM_USAGE_TOTAL_TOKENS: "gen_ai.usage.total_tokens",
788
+ LLM_USAGE_THOUGHTS_TOKENS: "gen_ai.usage.thoughts_tokens",
789
+ // Vector DB
790
+ DB_SYSTEM: "db.system",
791
+ DB_TABLE: "db.table",
792
+ DB_NAMESPACE: "db.namespace",
793
+ DB_ID: "db.id",
794
+ DB_QUERY_TEXT: "db.query.text",
795
+ DB_VECTOR: "db.vector",
796
+ DB_OPERATION_NAME: "db.operation.name",
797
+ DB_VECTOR_QUERY_TOP_K: "db.vector.query.top_k",
798
+ DB_QUERY_EMBEDDINGS: "db.query.embeddings",
799
+ DB_QUERY_RESULT: "db.query.result",
800
+ // Query Embeddings
801
+ DB_QUERY_EMBEDDINGS_VECTOR: "db.query.embeddings.vector",
802
+ // Query Result (canonical format)
803
+ DB_QUERY_RESULT_ID: "db.query.result.id",
804
+ DB_QUERY_RESULT_SCORE: "db.query.result.score",
805
+ DB_QUERY_RESULT_DISTANCE: "db.query.result.distance",
806
+ DB_QUERY_RESULT_METADATA: "db.query.result.metadata",
807
+ DB_QUERY_RESULT_VECTOR: "db.query.result.vector",
808
+ DB_QUERY_RESULT_DOCUMENT: "db.query.result.document"
809
+ };
810
+ var axSpanEvents = {
811
+ GEN_AI_USER_MESSAGE: "gen_ai.user.message",
812
+ GEN_AI_SYSTEM_MESSAGE: "gen_ai.system.message",
813
+ GEN_AI_ASSISTANT_MESSAGE: "gen_ai.assistant.message",
814
+ GEN_AI_TOOL_MESSAGE: "gen_ai.tool.message",
815
+ // For tool messages in request & response tool calls
816
+ GEN_AI_CHOICE: "gen_ai.choice",
817
+ GEN_AI_USAGE: "gen_ai.usage"
818
+ };
819
+ var AxLLMRequestTypeValues = /* @__PURE__ */ ((AxLLMRequestTypeValues2) => {
820
+ AxLLMRequestTypeValues2["COMPLETION"] = "completion";
821
+ AxLLMRequestTypeValues2["CHAT"] = "chat";
822
+ AxLLMRequestTypeValues2["RERANK"] = "rerank";
823
+ AxLLMRequestTypeValues2["UNKNOWN"] = "unknown";
824
+ return AxLLMRequestTypeValues2;
825
+ })(AxLLMRequestTypeValues || {});
826
+ var AxSpanKindValues = /* @__PURE__ */ ((AxSpanKindValues2) => {
827
+ AxSpanKindValues2["WORKFLOW"] = "workflow";
828
+ AxSpanKindValues2["TASK"] = "task";
829
+ AxSpanKindValues2["AGENT"] = "agent";
830
+ AxSpanKindValues2["TOOL"] = "tool";
831
+ AxSpanKindValues2["UNKNOWN"] = "unknown";
832
+ return AxSpanKindValues2;
833
+ })(AxSpanKindValues || {});
834
+
806
835
  // util/transform.ts
807
836
  var import_web4 = require("stream/web");
808
837
  var TypeTransformer = class {
@@ -2166,7 +2195,13 @@ var AxAIAnthropicImpl = class {
2166
2195
  };
2167
2196
  createChatResp = (resp) => {
2168
2197
  if (resp.type === "error") {
2169
- throw new Error(`Anthropic Chat API Error: ${resp.error.message}`);
2198
+ throw new AxAIRefusalError(
2199
+ resp.error.message,
2200
+ void 0,
2201
+ // model not specified in error response
2202
+ void 0
2203
+ // requestId not specified in error response
2204
+ );
2170
2205
  }
2171
2206
  const finishReason = mapFinishReason(resp.stop_reason);
2172
2207
  const showThoughts = this.currentPromptConfig?.thinkingTokenBudget !== "none" && this.currentPromptConfig?.showThoughts !== false;
@@ -2222,7 +2257,13 @@ var AxAIAnthropicImpl = class {
2222
2257
  }
2223
2258
  if (resp.type === "error") {
2224
2259
  const { error } = resp;
2225
- throw new Error(error.message);
2260
+ throw new AxAIRefusalError(
2261
+ error.message,
2262
+ void 0,
2263
+ // model not specified in error event
2264
+ void 0
2265
+ // requestId not specified in error event
2266
+ );
2226
2267
  }
2227
2268
  const index = 0;
2228
2269
  if (resp.type === "message_start") {
@@ -2850,6 +2891,9 @@ var AxAIOpenAIImpl = class {
2850
2891
  totalTokens: usage.total_tokens
2851
2892
  } : void 0;
2852
2893
  const results = choices.map((choice) => {
2894
+ if (choice.message.refusal) {
2895
+ throw new AxAIRefusalError(choice.message.refusal, resp.model, resp.id);
2896
+ }
2853
2897
  const finishReason = mapFinishReason2(choice.finish_reason);
2854
2898
  const functionCalls = choice.message.tool_calls?.map(
2855
2899
  ({ id: id2, function: { arguments: params, name } }) => ({
@@ -2861,8 +2905,9 @@ var AxAIOpenAIImpl = class {
2861
2905
  return {
2862
2906
  index: choice.index,
2863
2907
  id: `${choice.index}`,
2864
- content: choice.message.content,
2908
+ content: choice.message.content ?? void 0,
2865
2909
  thought: choice.message.reasoning_content,
2910
+ annotations: choice.message.annotations,
2866
2911
  functionCalls,
2867
2912
  finishReason
2868
2913
  };
@@ -2889,11 +2934,16 @@ var AxAIOpenAIImpl = class {
2889
2934
  delta: {
2890
2935
  content,
2891
2936
  role,
2937
+ refusal,
2892
2938
  tool_calls: toolCalls,
2893
- reasoning_content: thought
2939
+ reasoning_content: thought,
2940
+ annotations
2894
2941
  },
2895
2942
  finish_reason: oaiFinishReason
2896
2943
  }) => {
2944
+ if (refusal) {
2945
+ throw new AxAIRefusalError(refusal, void 0, id);
2946
+ }
2897
2947
  const finishReason = mapFinishReason2(oaiFinishReason);
2898
2948
  const functionCalls = toolCalls?.map(({ id: _id, index: index2, function: { name, arguments: params } }) => {
2899
2949
  if (typeof _id === "string" && typeof index2 === "number" && !sstate.indexIdMap[index2]) {
@@ -2911,9 +2961,10 @@ var AxAIOpenAIImpl = class {
2911
2961
  }).filter((v) => v !== null);
2912
2962
  return {
2913
2963
  index,
2914
- content,
2964
+ content: content ?? void 0,
2915
2965
  role,
2916
2966
  thought,
2967
+ annotations,
2917
2968
  functionCalls,
2918
2969
  finishReason,
2919
2970
  id
@@ -4010,11 +4061,29 @@ var AxAIGoogleGeminiImpl = class {
4010
4061
  result.finishReason = "stop";
4011
4062
  break;
4012
4063
  case "SAFETY":
4013
- throw new Error("Finish reason: SAFETY");
4064
+ throw new AxAIRefusalError(
4065
+ "Content was blocked due to safety settings",
4066
+ void 0,
4067
+ // model not available in candidate
4068
+ void 0
4069
+ // requestId not available
4070
+ );
4014
4071
  case "RECITATION":
4015
- throw new Error("Finish reason: RECITATION");
4072
+ throw new AxAIRefusalError(
4073
+ "Content was blocked due to recitation policy",
4074
+ void 0,
4075
+ // model not available in candidate
4076
+ void 0
4077
+ // requestId not available
4078
+ );
4016
4079
  case "MALFORMED_FUNCTION_CALL":
4017
- throw new Error("Finish reason: MALFORMED_FUNCTION_CALL");
4080
+ throw new AxAIRefusalError(
4081
+ "Function call was malformed and blocked",
4082
+ void 0,
4083
+ // model not available in candidate
4084
+ void 0
4085
+ // requestId not available
4086
+ );
4018
4087
  }
4019
4088
  if (!candidate.content || !candidate.content.parts) {
4020
4089
  return result;
@@ -4892,7 +4961,7 @@ var AxAIOpenAIResponsesImpl = class {
4892
4961
  switch (item.type) {
4893
4962
  case "message":
4894
4963
  currentResult.id = item.id;
4895
- currentResult.content = contentToText(item.content);
4964
+ currentResult.content = contentToText(item.content, id);
4896
4965
  currentResult.finishReason = item.status === "completed" ? "stop" : "content_filter";
4897
4966
  break;
4898
4967
  case "reasoning":
@@ -5065,7 +5134,10 @@ var AxAIOpenAIResponsesImpl = class {
5065
5134
  switch (event.item.type) {
5066
5135
  case "message":
5067
5136
  baseResult.id = event.item.id;
5068
- baseResult.content = contentToText(event.item.content);
5137
+ baseResult.content = contentToText(
5138
+ event.item.content,
5139
+ event.item.id
5140
+ );
5069
5141
  break;
5070
5142
  case "function_call":
5071
5143
  baseResult.id = event.item.id;
@@ -5235,7 +5307,7 @@ var AxAIOpenAIResponsesImpl = class {
5235
5307
  break;
5236
5308
  case "response.content_part.added":
5237
5309
  baseResult.id = event.item_id;
5238
- baseResult.content = contentToText([event.part]);
5310
+ baseResult.content = contentToText([event.part], event.item_id);
5239
5311
  break;
5240
5312
  case "response.output_text.delta":
5241
5313
  baseResult.id = event.item_id;
@@ -5420,11 +5492,13 @@ var AxAIOpenAIResponsesImpl = class {
5420
5492
  return [apiConfig, reqValue];
5421
5493
  }
5422
5494
  };
5423
- var contentToText = (content) => {
5424
- return [
5425
- ...content.filter((c) => c.type === "output_text").map((c) => c.text),
5426
- ...content.filter((c) => c.type === "refusal").map((c) => c.refusal)
5427
- ].join("\n");
5495
+ var contentToText = (content, responseId) => {
5496
+ const refusalContent = content.filter((c) => c.type === "refusal");
5497
+ if (refusalContent.length > 0) {
5498
+ const refusalMessage = refusalContent.map((c) => c.refusal).join("\n");
5499
+ throw new AxAIRefusalError(refusalMessage, void 0, responseId);
5500
+ }
5501
+ return content.filter((c) => c.type === "output_text").map((c) => c.text).join("\n");
5428
5502
  };
5429
5503
 
5430
5504
  // ai/openai/responses_api_base.ts
@@ -6008,213 +6082,279 @@ var import_api22 = require("@opentelemetry/api");
6008
6082
 
6009
6083
  // ai/validate.ts
6010
6084
  function axValidateChatRequestMessage(item) {
6085
+ const value = (v) => JSON.stringify(v, null, 2);
6011
6086
  if (!item) {
6012
- throw new Error("Chat request message item cannot be null or undefined");
6087
+ throw new Error(
6088
+ `Chat request message item cannot be null or undefined, received: ${value(item)}`
6089
+ );
6013
6090
  }
6014
- if (!item.role) {
6015
- throw new Error("Chat request message must have a role");
6091
+ const role = item?.role;
6092
+ if (!role) {
6093
+ throw new Error(
6094
+ `Chat request message must have a role, received: ${value(role)}`
6095
+ );
6016
6096
  }
6017
- switch (item.role) {
6018
- case "system":
6019
- if (!item.content || item.content.trim() === "") {
6097
+ switch (role) {
6098
+ case "system": {
6099
+ const systemItem = item;
6100
+ if (!systemItem.content || systemItem.content.trim() === "") {
6020
6101
  throw new Error(
6021
- "System message content cannot be empty or whitespace-only"
6102
+ `System message content cannot be empty or whitespace-only, received: ${value(systemItem.content)}`
6022
6103
  );
6023
6104
  }
6024
6105
  break;
6025
- case "user":
6026
- if (!item.content) {
6027
- throw new Error("User message content cannot be undefined");
6106
+ }
6107
+ case "user": {
6108
+ const userItem = item;
6109
+ if (!userItem.content) {
6110
+ throw new Error(
6111
+ `User message content cannot be undefined, received: ${value(userItem.content)}`
6112
+ );
6028
6113
  }
6029
- if (typeof item.content === "string") {
6030
- if (item.content.trim() === "") {
6114
+ if (typeof userItem.content === "string") {
6115
+ if (userItem.content.trim() === "") {
6031
6116
  throw new Error(
6032
- "User message content cannot be empty or whitespace-only"
6117
+ `User message content cannot be empty or whitespace-only, received: ${value(userItem.content)}`
6033
6118
  );
6034
6119
  }
6035
- } else if (Array.isArray(item.content)) {
6036
- if (item.content.length === 0) {
6037
- throw new Error("User message content array cannot be empty");
6120
+ } else if (Array.isArray(userItem.content)) {
6121
+ if (userItem.content.length === 0) {
6122
+ throw new Error(
6123
+ `User message content array cannot be empty, received: ${value(userItem.content)}`
6124
+ );
6038
6125
  }
6039
- for (let index = 0; index < item.content.length; index++) {
6040
- const contentItem = item.content[index];
6126
+ for (let index = 0; index < userItem.content.length; index++) {
6127
+ const contentItem = userItem.content[index];
6041
6128
  if (!contentItem || typeof contentItem !== "object") {
6042
6129
  throw new Error(
6043
- `User message content item at index ${index} must be an object`
6130
+ `User message content item at index ${index} must be an object, received: ${value(contentItem)}`
6044
6131
  );
6045
6132
  }
6046
- if (!contentItem.type) {
6133
+ const contentType = contentItem?.type;
6134
+ if (!contentType) {
6047
6135
  throw new Error(
6048
- `User message content item at index ${index} must have a type`
6136
+ `User message content item at index ${index} must have a type, received: ${value(contentType)}`
6049
6137
  );
6050
6138
  }
6051
- switch (contentItem.type) {
6052
- case "text":
6053
- if (!contentItem.text || contentItem.text.trim() === "") {
6139
+ switch (contentType) {
6140
+ case "text": {
6141
+ const textItem = contentItem;
6142
+ if (!textItem.text || textItem.text.trim() === "") {
6054
6143
  throw new Error(
6055
- `User message text content at index ${index} cannot be empty or whitespace-only`
6144
+ `User message text content at index ${index} cannot be empty or whitespace-only, received: ${value(textItem.text)}`
6056
6145
  );
6057
6146
  }
6058
6147
  break;
6059
- case "image":
6060
- if (!contentItem.image || contentItem.image.trim() === "") {
6148
+ }
6149
+ case "image": {
6150
+ const imageItem = contentItem;
6151
+ if (!imageItem.image || imageItem.image.trim() === "") {
6061
6152
  throw new Error(
6062
- `User message image content at index ${index} cannot be empty`
6153
+ `User message image content at index ${index} cannot be empty, received: ${value(imageItem.image)}`
6063
6154
  );
6064
6155
  }
6065
- if (!contentItem.mimeType || contentItem.mimeType.trim() === "") {
6156
+ if (!imageItem.mimeType || imageItem.mimeType.trim() === "") {
6066
6157
  throw new Error(
6067
- `User message image content at index ${index} must have a mimeType`
6158
+ `User message image content at index ${index} must have a mimeType, received: ${value(imageItem.mimeType)}`
6068
6159
  );
6069
6160
  }
6070
6161
  break;
6071
- case "audio":
6072
- if (!contentItem.data || contentItem.data.trim() === "") {
6162
+ }
6163
+ case "audio": {
6164
+ const audioItem = contentItem;
6165
+ if (!audioItem.data || audioItem.data.trim() === "") {
6073
6166
  throw new Error(
6074
- `User message audio content at index ${index} cannot be empty`
6167
+ `User message audio content at index ${index} cannot be empty, received: ${value(audioItem.data)}`
6075
6168
  );
6076
6169
  }
6077
6170
  break;
6171
+ }
6078
6172
  default:
6079
6173
  throw new Error(
6080
- `User message content item at index ${index} has unsupported type: ${contentItem.type}`
6174
+ `User message content item at index ${index} has unsupported type: ${value(contentType)}`
6081
6175
  );
6082
6176
  }
6083
6177
  }
6084
6178
  } else {
6085
6179
  throw new Error(
6086
- "User message content must be a string or array of content objects"
6180
+ `User message content must be a string or array of content objects, received: ${value(userItem.content)}`
6087
6181
  );
6088
6182
  }
6089
6183
  break;
6090
- case "assistant":
6091
- if (!item.content && !item.functionCalls) {
6184
+ }
6185
+ case "assistant": {
6186
+ const assistantItem = item;
6187
+ if (!assistantItem.content && !assistantItem.functionCalls) {
6092
6188
  throw new Error(
6093
- "Assistant message must have either content or function calls"
6189
+ `Assistant message must have either content or function calls, received content: ${value(assistantItem.content)}, functionCalls: ${value(assistantItem.functionCalls)}`
6094
6190
  );
6095
6191
  }
6096
- if (item.content && typeof item.content !== "string") {
6097
- throw new Error("Assistant message content must be a string");
6192
+ if (assistantItem.content && typeof assistantItem.content !== "string") {
6193
+ throw new Error(
6194
+ `Assistant message content must be a string, received: ${value(assistantItem.content)}`
6195
+ );
6098
6196
  }
6099
- if (item.functionCalls && !Array.isArray(item.functionCalls)) {
6100
- throw new Error("Assistant message function calls must be an array");
6197
+ if (assistantItem.functionCalls && !Array.isArray(assistantItem.functionCalls)) {
6198
+ throw new Error(
6199
+ `Assistant message function calls must be an array, received: ${value(assistantItem.functionCalls)}`
6200
+ );
6101
6201
  }
6102
6202
  break;
6103
- case "function":
6104
- if (!item.functionId || item.functionId.trim() === "") {
6105
- throw new Error("Function message must have a non-empty functionId");
6203
+ }
6204
+ case "function": {
6205
+ const functionItem = item;
6206
+ if (!functionItem.functionId || functionItem.functionId.trim() === "") {
6207
+ throw new Error(
6208
+ `Function message must have a non-empty functionId, received: ${value(functionItem.functionId)}`
6209
+ );
6106
6210
  }
6107
- if (item.result === void 0 || item.result === null) {
6108
- throw new Error("Function message must have a result");
6211
+ if (functionItem.result === void 0 || functionItem.result === null) {
6212
+ throw new Error(
6213
+ `Function message must have a result, received: ${value(functionItem.result)}`
6214
+ );
6109
6215
  }
6110
- if (typeof item.result !== "string") {
6111
- throw new Error("Function message result must be a string");
6216
+ if (typeof functionItem.result !== "string") {
6217
+ throw new Error(
6218
+ `Function message result must be a string, received: ${value(functionItem.result)}`
6219
+ );
6112
6220
  }
6113
6221
  break;
6222
+ }
6114
6223
  default:
6115
- throw new Error(
6116
- `Unsupported message role: ${item.role}`
6117
- );
6224
+ throw new Error(`Unsupported message role: ${value(role)}`);
6118
6225
  }
6119
6226
  }
6120
6227
  function axValidateChatResponseResult(results) {
6228
+ const value = (v) => JSON.stringify(v, null, 2);
6121
6229
  const resultsArray = Array.isArray(results) ? results : [results];
6122
6230
  if (resultsArray.length === 0) {
6123
- throw new Error("Chat response results cannot be empty");
6231
+ throw new Error(
6232
+ `Chat response results cannot be empty, received: ${value(resultsArray)}`
6233
+ );
6124
6234
  }
6125
6235
  for (let arrayIndex = 0; arrayIndex < resultsArray.length; arrayIndex++) {
6126
6236
  const result = resultsArray[arrayIndex];
6127
6237
  if (!result) {
6128
6238
  throw new Error(
6129
- `Chat response result at index ${arrayIndex} cannot be null or undefined`
6239
+ `Chat response result at index ${arrayIndex} cannot be null or undefined, received: ${value(result)}`
6130
6240
  );
6131
6241
  }
6132
6242
  if (typeof result.index !== "number") {
6133
6243
  throw new Error(
6134
- `Chat response result at index ${arrayIndex} must have a numeric index`
6244
+ `Chat response result at index ${arrayIndex} must have a numeric index, received: ${value(result.index)}`
6135
6245
  );
6136
6246
  }
6137
6247
  if (result.index < 0) {
6138
6248
  throw new Error(
6139
- `Chat response result at index ${arrayIndex} must have a non-negative index`
6249
+ `Chat response result at index ${arrayIndex} must have a non-negative index, received: ${value(result.index)}`
6140
6250
  );
6141
6251
  }
6142
6252
  if (!result.content && !result.thought && !result.functionCalls && !result.finishReason) {
6143
6253
  throw new Error(
6144
- `Chat response result at index ${arrayIndex} must have at least one of: content, thought, functionCalls, or finishReason`
6254
+ `Chat response result at index ${arrayIndex} must have at least one of: content, thought, functionCalls, or finishReason, received: ${value({ content: result.content, thought: result.thought, functionCalls: result.functionCalls, finishReason: result.finishReason })}`
6145
6255
  );
6146
6256
  }
6147
6257
  if (result.content !== void 0 && typeof result.content !== "string") {
6148
6258
  throw new Error(
6149
- `Chat response result content at index ${arrayIndex} must be a string`
6259
+ `Chat response result content at index ${arrayIndex} must be a string, received: ${value(result.content)}`
6150
6260
  );
6151
6261
  }
6152
6262
  if (result.thought !== void 0 && typeof result.thought !== "string") {
6153
6263
  throw new Error(
6154
- `Chat response result thought at index ${arrayIndex} must be a string`
6264
+ `Chat response result thought at index ${arrayIndex} must be a string, received: ${value(result.thought)}`
6155
6265
  );
6156
6266
  }
6157
6267
  if (result.name !== void 0) {
6158
6268
  if (typeof result.name !== "string") {
6159
6269
  throw new Error(
6160
- `Chat response result name at index ${arrayIndex} must be a string`
6270
+ `Chat response result name at index ${arrayIndex} must be a string, received: ${value(result.name)}`
6161
6271
  );
6162
6272
  }
6163
6273
  if (result.name.trim() === "") {
6164
6274
  throw new Error(
6165
- `Chat response result name at index ${arrayIndex} cannot be empty or whitespace-only`
6275
+ `Chat response result name at index ${arrayIndex} cannot be empty or whitespace-only, received: ${value(result.name)}`
6166
6276
  );
6167
6277
  }
6168
6278
  }
6279
+ if (result.annotations !== void 0) {
6280
+ if (!Array.isArray(result.annotations)) {
6281
+ throw new Error(
6282
+ `Chat response result annotations at index ${arrayIndex} must be an array, received: ${value(result.annotations)}`
6283
+ );
6284
+ }
6285
+ for (let i = 0; i < result.annotations.length; i++) {
6286
+ const annotation = result.annotations[i];
6287
+ if (!annotation || typeof annotation !== "object") {
6288
+ throw new Error(
6289
+ `Chat response result annotation at index ${arrayIndex}[${i}] must be an object, received: ${value(annotation)}`
6290
+ );
6291
+ }
6292
+ if (annotation.type !== "url_citation") {
6293
+ throw new Error(
6294
+ `Chat response result annotation at index ${arrayIndex}[${i}] must have type 'url_citation', received: ${value(annotation.type)}`
6295
+ );
6296
+ }
6297
+ if (!annotation.url_citation || typeof annotation.url_citation !== "object") {
6298
+ throw new Error(
6299
+ `Chat response result annotation at index ${arrayIndex}[${i}] must have a valid url_citation object, received: ${value(annotation.url_citation)}`
6300
+ );
6301
+ }
6302
+ if (typeof annotation.url_citation.url !== "string") {
6303
+ throw new Error(
6304
+ `Chat response result annotation at index ${arrayIndex}[${i}] url_citation.url must be a string, received: ${value(annotation.url_citation.url)}`
6305
+ );
6306
+ }
6307
+ }
6308
+ }
6169
6309
  if (result.id !== void 0) {
6170
6310
  if (typeof result.id !== "string") {
6171
6311
  throw new Error(
6172
- `Chat response result id at index ${arrayIndex} must be a string`
6312
+ `Chat response result id at index ${arrayIndex} must be a string, received: ${value(result.id)}`
6173
6313
  );
6174
6314
  }
6175
6315
  if (result.id.trim() === "") {
6176
6316
  throw new Error(
6177
- `Chat response result id at index ${arrayIndex} cannot be empty or whitespace-only`
6317
+ `Chat response result id at index ${arrayIndex} cannot be empty or whitespace-only, received: ${value(result.id)}`
6178
6318
  );
6179
6319
  }
6180
6320
  }
6181
6321
  if (result.functionCalls !== void 0) {
6182
6322
  if (!Array.isArray(result.functionCalls)) {
6183
6323
  throw new Error(
6184
- `Chat response result functionCalls at index ${arrayIndex} must be an array`
6324
+ `Chat response result functionCalls at index ${arrayIndex} must be an array, received: ${value(result.functionCalls)}`
6185
6325
  );
6186
6326
  }
6187
6327
  for (let callIndex = 0; callIndex < result.functionCalls.length; callIndex++) {
6188
6328
  const functionCall = result.functionCalls[callIndex];
6189
6329
  if (!functionCall) {
6190
6330
  throw new Error(
6191
- `Function call at index ${callIndex} in result ${arrayIndex} cannot be null or undefined`
6331
+ `Function call at index ${callIndex} in result ${arrayIndex} cannot be null or undefined, received: ${value(functionCall)}`
6192
6332
  );
6193
6333
  }
6194
6334
  if (!functionCall.id || typeof functionCall.id !== "string" || functionCall.id.trim() === "") {
6195
6335
  throw new Error(
6196
- `Function call at index ${callIndex} in result ${arrayIndex} must have a non-empty string id`
6336
+ `Function call at index ${callIndex} in result ${arrayIndex} must have a non-empty string id, received: ${value(functionCall.id)}`
6197
6337
  );
6198
6338
  }
6199
6339
  if (functionCall.type !== "function") {
6200
6340
  throw new Error(
6201
- `Function call at index ${callIndex} in result ${arrayIndex} must have type 'function'`
6341
+ `Function call at index ${callIndex} in result ${arrayIndex} must have type 'function', received: ${value(functionCall.type)}`
6202
6342
  );
6203
6343
  }
6204
6344
  if (!functionCall.function) {
6205
6345
  throw new Error(
6206
- `Function call at index ${callIndex} in result ${arrayIndex} must have a function object`
6346
+ `Function call at index ${callIndex} in result ${arrayIndex} must have a function object, received: ${value(functionCall.function)}`
6207
6347
  );
6208
6348
  }
6209
6349
  if (!functionCall.function.name || typeof functionCall.function.name !== "string" || functionCall.function.name.trim() === "") {
6210
6350
  throw new Error(
6211
- `Function call at index ${callIndex} in result ${arrayIndex} must have a non-empty function name`
6351
+ `Function call at index ${callIndex} in result ${arrayIndex} must have a non-empty function name, received: ${value(functionCall.function.name)}`
6212
6352
  );
6213
6353
  }
6214
6354
  if (functionCall.function.params !== void 0) {
6215
6355
  if (typeof functionCall.function.params !== "string" && typeof functionCall.function.params !== "object") {
6216
6356
  throw new Error(
6217
- `Function call params at index ${callIndex} in result ${arrayIndex} must be a string or object`
6357
+ `Function call params at index ${callIndex} in result ${arrayIndex} must be a string or object, received: ${value(functionCall.function.params)}`
6218
6358
  );
6219
6359
  }
6220
6360
  }
@@ -6230,7 +6370,7 @@ function axValidateChatResponseResult(results) {
6230
6370
  ];
6231
6371
  if (!validFinishReasons.includes(result.finishReason)) {
6232
6372
  throw new Error(
6233
- `Chat response result finishReason at index ${arrayIndex} must be one of: ${validFinishReasons.join(", ")}`
6373
+ `Chat response result finishReason at index ${arrayIndex} must be one of: ${validFinishReasons.join(", ")}, received: ${value(result.finishReason)}`
6234
6374
  );
6235
6375
  }
6236
6376
  }
@@ -16287,6 +16427,198 @@ var AxEvalUtil = {
16287
16427
  novelF1ScoreOptimized
16288
16428
  };
16289
16429
 
16430
+ // flow/flow.ts
16431
+ var AxFlow = class extends AxProgramWithSignature {
16432
+ nodes = /* @__PURE__ */ new Map();
16433
+ flowDefinition = [];
16434
+ nodeGenerators = /* @__PURE__ */ new Map();
16435
+ loopStack = [];
16436
+ constructor(signature = "userInput:string -> flowOutput:string") {
16437
+ super(signature);
16438
+ }
16439
+ /**
16440
+ * Declares a reusable computational node and its input/output signature.
16441
+ *
16442
+ * @param name - The name of the node
16443
+ * @param signature - An object where the key is a string representation of inputs
16444
+ * and the value is an object representing outputs
16445
+ * @returns this (for chaining)
16446
+ *
16447
+ * @example
16448
+ * ```typescript
16449
+ * flow.node('summarizer', { 'text:string': { summary: f.string() } })
16450
+ * ```
16451
+ */
16452
+ node(name, signature) {
16453
+ const [inputSignature, outputSignature] = Object.entries(signature)[0] ?? [
16454
+ "",
16455
+ {}
16456
+ ];
16457
+ if (!inputSignature || !outputSignature) {
16458
+ throw new Error(
16459
+ `Invalid signature for node '${name}': signature must have at least one input->output mapping`
16460
+ );
16461
+ }
16462
+ const outputFields = Object.entries(outputSignature).map(([key, value]) => {
16463
+ if (typeof value === "object" && value !== null && "type" in value) {
16464
+ const fieldType = value;
16465
+ let fieldString = `${key}:`;
16466
+ if (fieldType.isOptional) {
16467
+ const colonIndex = fieldString.lastIndexOf(":");
16468
+ fieldString = fieldString.slice(0, colonIndex) + "?" + fieldString.slice(colonIndex);
16469
+ }
16470
+ if (fieldType.isInternal) {
16471
+ const colonIndex = fieldString.lastIndexOf(":");
16472
+ fieldString = fieldString.slice(0, colonIndex) + "!" + fieldString.slice(colonIndex);
16473
+ }
16474
+ fieldString += fieldType.type;
16475
+ if (fieldType.isArray) {
16476
+ fieldString += "[]";
16477
+ }
16478
+ if (fieldType.type === "class" && fieldType.options) {
16479
+ fieldString += ` "${fieldType.options.join(", ")}"`;
16480
+ }
16481
+ if (fieldType.description && (fieldType.type !== "class" || !fieldType.options)) {
16482
+ fieldString += ` "${fieldType.description}"`;
16483
+ }
16484
+ return fieldString;
16485
+ }
16486
+ return `${key}:string`;
16487
+ }).join(", ");
16488
+ const signatureString = `${inputSignature} -> ${outputFields}`;
16489
+ this.nodes.set(name, {
16490
+ inputs: { [inputSignature]: true },
16491
+ outputs: outputSignature
16492
+ });
16493
+ this.nodeGenerators.set(name, new AxGen(signatureString));
16494
+ return this;
16495
+ }
16496
+ /**
16497
+ * Applies a synchronous transformation to the state object.
16498
+ *
16499
+ * @param transform - Function that takes the current state and returns a new state
16500
+ * @returns this (for chaining)
16501
+ *
16502
+ * @example
16503
+ * ```typescript
16504
+ * flow.map(state => ({ ...state, processedText: state.text.toLowerCase() }))
16505
+ * ```
16506
+ */
16507
+ map(transform) {
16508
+ this.flowDefinition.push((state) => {
16509
+ return transform(state);
16510
+ });
16511
+ return this;
16512
+ }
16513
+ /**
16514
+ * Executes a previously defined node.
16515
+ *
16516
+ * @param nodeName - The name of the node to execute (must exist in the nodes map)
16517
+ * @param mapping - Function that takes the current state and returns the input object required by the node
16518
+ * @param dynamicContext - Optional object to override the AI service or options for this specific step
16519
+ * @returns this (for chaining)
16520
+ *
16521
+ * @example
16522
+ * ```typescript
16523
+ * flow.execute('summarizer', state => ({ text: state.originalText }), { ai: cheapAI })
16524
+ * ```
16525
+ */
16526
+ execute(nodeName, mapping, dynamicContext) {
16527
+ if (!this.nodes.has(nodeName)) {
16528
+ throw new Error(
16529
+ `Node '${nodeName}' not found. Make sure to define it with .node() first.`
16530
+ );
16531
+ }
16532
+ const nodeGenerator = this.nodeGenerators.get(nodeName);
16533
+ if (!nodeGenerator) {
16534
+ throw new Error(`Node generator for '${nodeName}' not found.`);
16535
+ }
16536
+ this.flowDefinition.push(async (state, context3) => {
16537
+ const ai = dynamicContext?.ai ?? context3.mainAi;
16538
+ const options = dynamicContext?.options ?? context3.mainOptions;
16539
+ const nodeInputs = mapping(state);
16540
+ const result = await nodeGenerator.forward(ai, nodeInputs, options);
16541
+ return {
16542
+ ...state,
16543
+ [`${nodeName}Result`]: result
16544
+ };
16545
+ });
16546
+ return this;
16547
+ }
16548
+ /**
16549
+ * Marks the beginning of a loop block.
16550
+ *
16551
+ * @param condition - Function that takes the current state and returns a boolean
16552
+ * @returns this (for chaining)
16553
+ *
16554
+ * @example
16555
+ * ```typescript
16556
+ * flow.while(state => state.iterations < 3)
16557
+ * .map(state => ({ ...state, iterations: (state.iterations || 0) + 1 }))
16558
+ * .endWhile()
16559
+ * ```
16560
+ */
16561
+ while(condition) {
16562
+ const loopStartIndex = this.flowDefinition.length;
16563
+ this.loopStack.push(loopStartIndex);
16564
+ const placeholderStep = Object.assign(
16565
+ (state) => state,
16566
+ {
16567
+ _condition: condition,
16568
+ _isLoopStart: true
16569
+ }
16570
+ );
16571
+ this.flowDefinition.push(placeholderStep);
16572
+ return this;
16573
+ }
16574
+ /**
16575
+ * Marks the end of a loop block.
16576
+ *
16577
+ * @returns this (for chaining)
16578
+ */
16579
+ endWhile() {
16580
+ if (this.loopStack.length === 0) {
16581
+ throw new Error("endWhile() called without matching while()");
16582
+ }
16583
+ const loopStartIndex = this.loopStack.pop();
16584
+ const placeholderStep = this.flowDefinition[loopStartIndex];
16585
+ if (!placeholderStep || !("_isLoopStart" in placeholderStep)) {
16586
+ throw new Error("Loop start step not found or invalid");
16587
+ }
16588
+ const condition = placeholderStep._condition;
16589
+ const loopBodySteps = this.flowDefinition.splice(loopStartIndex + 1);
16590
+ this.flowDefinition[loopStartIndex] = async (state, context3) => {
16591
+ let currentState = state;
16592
+ while (condition(currentState)) {
16593
+ for (const step of loopBodySteps) {
16594
+ currentState = await step(currentState, context3);
16595
+ }
16596
+ }
16597
+ return currentState;
16598
+ };
16599
+ return this;
16600
+ }
16601
+ /**
16602
+ * Executes the flow with the given AI service and input values.
16603
+ *
16604
+ * @param ai - The AI service to use as the default for all steps
16605
+ * @param values - The input values for the flow
16606
+ * @param options - Optional forward options to use as defaults
16607
+ * @returns Promise that resolves to the final output
16608
+ */
16609
+ async forward(ai, values, options) {
16610
+ let state = { ...values };
16611
+ const context3 = {
16612
+ mainAi: ai,
16613
+ mainOptions: options
16614
+ };
16615
+ for (const step of this.flowDefinition) {
16616
+ state = await step(state, context3);
16617
+ }
16618
+ return state;
16619
+ }
16620
+ };
16621
+
16290
16622
  // ../../node_modules/uuid/dist/esm-node/rng.js
16291
16623
  var import_crypto5 = __toESM(require("crypto"));
16292
16624
  var rnds8Pool = new Uint8Array(256);
@@ -16824,6 +17156,7 @@ var AxRAG = class extends AxChainOfThought {
16824
17156
  AxAIOpenAIResponsesBase,
16825
17157
  AxAIOpenAIResponsesImpl,
16826
17158
  AxAIOpenAIResponsesModel,
17159
+ AxAIRefusalError,
16827
17160
  AxAIReka,
16828
17161
  AxAIRekaModel,
16829
17162
  AxAIServiceAbortedError,
@@ -16855,6 +17188,7 @@ var AxRAG = class extends AxChainOfThought {
16855
17188
  AxDockerSession,
16856
17189
  AxEmbeddingAdapter,
16857
17190
  AxEvalUtil,
17191
+ AxFlow,
16858
17192
  AxFunctionError,
16859
17193
  AxFunctionProcessor,
16860
17194
  AxGen,