@ax-llm/ax 11.0.20 → 11.0.22

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.js CHANGED
@@ -1,26 +1,6 @@
1
1
  // ai/base.ts
2
2
  import { SpanKind } from "@opentelemetry/api";
3
3
 
4
- // dsp/modelinfo.ts
5
- function getModelInfo({
6
- model,
7
- modelInfo,
8
- models
9
- }) {
10
- const mappedModel = models?.find((v) => v.key === model)?.model ?? model;
11
- const exactMatch = modelInfo.find((v) => v.name === model);
12
- if (exactMatch) return exactMatch;
13
- const normalizedName = mappedModel.replace(/^(anthropic\.|openai\.)/, "").replace(/-latest$/, "").replace(/-\d{8}$/, "").replace(/-v\d+:\d+$/, "").replace(/@\d{8}$/, "").replace(/-\d{2,}(-[a-zA-Z0-9-]+)?$/, "").replace(/-v\d+@\d{8}$/, "").replace(/-v\d+$/, "");
14
- const normalizedMatch = modelInfo.find((v) => v.name === normalizedName);
15
- if (normalizedMatch) return normalizedMatch;
16
- return {
17
- name: model,
18
- currency: "usd",
19
- promptTokenCostPer1M: 0,
20
- completionTokenCostPer1M: 0
21
- };
22
- }
23
-
24
4
  // trace/trace.ts
25
5
  var axSpanAttributes = {
26
6
  // LLM
@@ -746,6 +726,9 @@ var AxBaseAI = class {
746
726
  throw new Error("No model defined");
747
727
  }
748
728
  this.setOptions(options);
729
+ if (models) {
730
+ validateModels(models);
731
+ }
749
732
  }
750
733
  debug = false;
751
734
  rt;
@@ -824,33 +807,19 @@ var AxBaseAI = class {
824
807
  tracer: this.tracer
825
808
  };
826
809
  }
827
- getModelInfo() {
828
- const mi = getModelInfo({
829
- model: this.defaults.model,
830
- modelInfo: this.modelInfo,
831
- models: this.models
832
- });
833
- return {
834
- ...mi,
835
- provider: this.name
836
- };
810
+ getModelList() {
811
+ return this.models?.filter((model) => !model.isInternal)?.map((model) => ({
812
+ key: model.key,
813
+ description: model.description,
814
+ model: model.model
815
+ }));
837
816
  }
838
- getEmbedModelInfo() {
839
- if (!this.defaults.embedModel) {
840
- return;
841
- }
842
- const mi = getModelInfo({
843
- model: this.defaults.embedModel,
844
- modelInfo: this.modelInfo
845
- });
817
+ getDefaultModels() {
846
818
  return {
847
- ...mi,
848
- provider: this.name
819
+ model: this.defaults.model,
820
+ embedModel: this.defaults.embedModel
849
821
  };
850
822
  }
851
- getModelList() {
852
- return this.models;
853
- }
854
823
  getName() {
855
824
  return this.name;
856
825
  }
@@ -1136,14 +1105,25 @@ var AxBaseAI = class {
1136
1105
  return { ...headers, ...await this.headers() };
1137
1106
  }
1138
1107
  };
1139
- var setResponseAttr = (res, span) => {
1108
+ function setResponseAttr(res, span) {
1140
1109
  if (res.modelUsage) {
1141
1110
  span.setAttributes({
1142
1111
  [axSpanAttributes.LLM_USAGE_COMPLETION_TOKENS]: res.modelUsage.completionTokens ?? 0,
1143
1112
  [axSpanAttributes.LLM_USAGE_PROMPT_TOKENS]: res.modelUsage.promptTokens
1144
1113
  });
1145
1114
  }
1146
- };
1115
+ }
1116
+ function validateModels(models) {
1117
+ const keys = /* @__PURE__ */ new Set();
1118
+ for (const model of models) {
1119
+ if (keys.has(model.key)) {
1120
+ throw new Error(
1121
+ `Duplicate model key detected: "${model.key}". Each model key must be unique.`
1122
+ );
1123
+ }
1124
+ keys.add(model.key);
1125
+ }
1126
+ }
1147
1127
 
1148
1128
  // ai/google-vertex/auth.ts
1149
1129
  import { GoogleAuth } from "google-auth-library";
@@ -1799,7 +1779,7 @@ var AxAIOpenAIImpl = class {
1799
1779
  response_format: this.config?.responseFormat ? { type: this.config?.responseFormat } : void 0,
1800
1780
  tools,
1801
1781
  tool_choice: toolsChoice,
1802
- max_tokens: req.modelConfig?.maxTokens ?? this.config.maxTokens ?? 500,
1782
+ max_completion_tokens: req.modelConfig?.maxTokens ?? this.config.maxTokens ?? 500,
1803
1783
  temperature: req.modelConfig?.temperature ?? this.config.temperature,
1804
1784
  top_p: req.modelConfig?.topP ?? this.config.topP ?? 1,
1805
1785
  n: req.modelConfig?.n ?? this.config.n,
@@ -2596,10 +2576,10 @@ var axAIGoogleGeminiDefaultConfig = () => structuredClone({
2596
2576
  ...axBaseAIDefaultConfig()
2597
2577
  });
2598
2578
  var AxAIGoogleGeminiImpl = class {
2599
- constructor(config, isVertex, endpoint, apiKey, options) {
2579
+ constructor(config, isVertex, endpointId, apiKey, options) {
2600
2580
  this.config = config;
2601
2581
  this.isVertex = isVertex;
2602
- this.endpoint = endpoint;
2582
+ this.endpointId = endpointId;
2603
2583
  this.apiKey = apiKey;
2604
2584
  this.options = options;
2605
2585
  }
@@ -2625,9 +2605,9 @@ var AxAIGoogleGeminiImpl = class {
2625
2605
  throw new Error("Chat prompt is empty");
2626
2606
  }
2627
2607
  let apiConfig;
2628
- if (this.endpoint) {
2608
+ if (this.endpointId) {
2629
2609
  apiConfig = {
2630
- name: stream ? `/${this.endpoint}:streamGenerateContent?alt=sse` : `/${this.endpoint}:generateContent`
2610
+ name: stream ? `/${this.endpointId}:streamGenerateContent?alt=sse` : `/${this.endpointId}:generateContent`
2631
2611
  };
2632
2612
  } else {
2633
2613
  apiConfig = {
@@ -2786,9 +2766,9 @@ var AxAIGoogleGeminiImpl = class {
2786
2766
  let apiConfig;
2787
2767
  let reqValue;
2788
2768
  if (this.isVertex) {
2789
- if (this.endpoint) {
2769
+ if (this.endpointId) {
2790
2770
  apiConfig = {
2791
- name: `/${this.endpoint}:predict`
2771
+ name: `/${this.endpointId}:predict`
2792
2772
  };
2793
2773
  } else {
2794
2774
  apiConfig = {
@@ -2892,7 +2872,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
2892
2872
  apiKey,
2893
2873
  projectId,
2894
2874
  region,
2895
- endpoint,
2875
+ endpointId,
2896
2876
  config,
2897
2877
  options,
2898
2878
  models
@@ -2902,7 +2882,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
2902
2882
  let headers;
2903
2883
  if (isVertex) {
2904
2884
  let path;
2905
- if (endpoint) {
2885
+ if (endpointId) {
2906
2886
  path = "endpoints";
2907
2887
  } else {
2908
2888
  path = "publishers/google";
@@ -2930,7 +2910,7 @@ var AxAIGoogleGemini = class extends AxBaseAI {
2930
2910
  const aiImpl = new AxAIGoogleGeminiImpl(
2931
2911
  _config,
2932
2912
  isVertex,
2933
- endpoint,
2913
+ endpointId,
2934
2914
  apiKey,
2935
2915
  options
2936
2916
  );
@@ -3651,18 +3631,15 @@ var AxAI = class {
3651
3631
  getId() {
3652
3632
  return this.ai.getId();
3653
3633
  }
3654
- getModelInfo() {
3655
- return this.ai.getModelInfo();
3656
- }
3657
- getEmbedModelInfo() {
3658
- return this.ai.getEmbedModelInfo();
3659
- }
3660
3634
  getFeatures(model) {
3661
3635
  return this.ai.getFeatures(model);
3662
3636
  }
3663
3637
  getModelList() {
3664
3638
  return this.ai.getModelList();
3665
3639
  }
3640
+ getDefaultModels() {
3641
+ return this.ai.getDefaultModels();
3642
+ }
3666
3643
  getMetrics() {
3667
3644
  return this.ai.getMetrics();
3668
3645
  }
@@ -3899,10 +3876,11 @@ var AxAssertionError = class extends Error {
3899
3876
  }
3900
3877
  getFixingInstructions = () => {
3901
3878
  const extraFields = [];
3879
+ const message = this.message.trim();
3902
3880
  extraFields.push({
3903
3881
  name: "error",
3904
- title: "Error In Output",
3905
- description: `You must follow the following instructions, "${this.message}".`
3882
+ title: "Follow these instructions",
3883
+ description: message + (message.endsWith(".") ? "" : ".")
3906
3884
  });
3907
3885
  return extraFields;
3908
3886
  };
@@ -5639,7 +5617,8 @@ async function processFieldProcessors(fieldProcessors, values, mem, sessionId) {
5639
5617
  if (values[processor.field.name] === void 0) {
5640
5618
  continue;
5641
5619
  }
5642
- const result = await processor.process(values[processor.field.name], {
5620
+ const processFn = processor.process;
5621
+ const result = await processFn(values[processor.field.name], {
5643
5622
  sessionId,
5644
5623
  values,
5645
5624
  done: true
@@ -5657,7 +5636,8 @@ async function processStreamingFieldProcessors(fieldProcessors, content, xstate,
5657
5636
  value = value.replace(/^[ ]*```[a-zA-Z0-9]*\n\s*/, "");
5658
5637
  value = value.replace(/\s*```\s*$/, "");
5659
5638
  }
5660
- const result = await processor.process(value, {
5639
+ const processFn = processor.process;
5640
+ const result = await processFn(value, {
5661
5641
  sessionId,
5662
5642
  values,
5663
5643
  done
@@ -5927,7 +5907,7 @@ var AxGen = class extends AxProgramWithSignature {
5927
5907
  addStreamingAssert = (fieldName, fn, message) => {
5928
5908
  this.streamingAsserts.push({ fieldName, fn, message });
5929
5909
  };
5930
- addFieldProcessor = (fieldName, fn, streaming = false) => {
5910
+ addFieldProcessorInternal = (fieldName, fn, streaming = false) => {
5931
5911
  const field = this.signature.getOutputFields().find((f) => f.name === fieldName);
5932
5912
  if (!field) {
5933
5913
  throw new Error(`addFieldProcessor: field ${fieldName} not found`);
@@ -5945,6 +5925,12 @@ var AxGen = class extends AxProgramWithSignature {
5945
5925
  this.fieldProcessors.push({ field, process: fn });
5946
5926
  }
5947
5927
  };
5928
+ addStreamingFieldProcessor = (fieldName, fn) => {
5929
+ this.addFieldProcessorInternal(fieldName, fn, true);
5930
+ };
5931
+ addFieldProcessor = (fieldName, fn) => {
5932
+ this.addFieldProcessorInternal(fieldName, fn, false);
5933
+ };
5948
5934
  async forwardSendRequest({
5949
5935
  ai,
5950
5936
  mem,
@@ -5990,9 +5976,10 @@ var AxGen = class extends AxProgramWithSignature {
5990
5976
  }) {
5991
5977
  const { sessionId, traceId, model, functions } = options ?? {};
5992
5978
  const fastFail = options?.fastFail ?? this.options?.fastFail;
5979
+ const modelName = model ?? ai.getDefaultModels().model;
5993
5980
  const usageInfo = {
5994
5981
  ai: ai.getName(),
5995
- model: ai.getModelInfo().name
5982
+ model: modelName
5996
5983
  };
5997
5984
  const res = await this.forwardSendRequest({
5998
5985
  ai,
@@ -6076,7 +6063,9 @@ var AxGen = class extends AxProgramWithSignature {
6076
6063
  content,
6077
6064
  streamingValidation
6078
6065
  );
6079
- assertStreamingAssertions(this.streamingAsserts, xstate, content);
6066
+ if (this.streamingAsserts.length !== 0) {
6067
+ assertStreamingAssertions(this.streamingAsserts, xstate, content);
6068
+ }
6080
6069
  if (this.streamingFieldProcessors.length !== 0) {
6081
6070
  await processStreamingFieldProcessors(
6082
6071
  this.streamingFieldProcessors,
@@ -6702,8 +6691,9 @@ var AxBalancer = class _AxBalancer {
6702
6691
  if (services.length === 0) {
6703
6692
  throw new Error("No AI services provided.");
6704
6693
  }
6694
+ validateModels2(services);
6705
6695
  this.services = [...services].sort(
6706
- options?.comparator ?? _AxBalancer.costComparator
6696
+ options?.comparator ?? _AxBalancer.metricComparator
6707
6697
  );
6708
6698
  const cs = this.services[this.currentServiceIndex];
6709
6699
  if (cs === void 0) {
@@ -6722,16 +6712,31 @@ var AxBalancer = class _AxBalancer {
6722
6712
  /**
6723
6713
  * Service comparator that sorts services by cost.
6724
6714
  */
6725
- static costComparator = (a, b) => {
6726
- const aInfo = a.getModelInfo();
6727
- const bInfo = b.getModelInfo();
6728
- const aTotalCost = (aInfo.promptTokenCostPer1M || Infinity) + (aInfo.completionTokenCostPer1M || Infinity);
6729
- const bTotalCost = (bInfo.promptTokenCostPer1M || Infinity) + (bInfo.completionTokenCostPer1M || Infinity);
6730
- return aTotalCost - bTotalCost;
6715
+ // Requires a rethink
6716
+ /*
6717
+ public static costComparator = (a: AxAIService, b: AxAIService) => {
6718
+ const aInfo = a.getModelInfo()
6719
+ const bInfo = b.getModelInfo()
6720
+ const aTotalCost =
6721
+ (aInfo.promptTokenCostPer1M || Infinity) +
6722
+ (aInfo.completionTokenCostPer1M || Infinity)
6723
+ const bTotalCost =
6724
+ (bInfo.promptTokenCostPer1M || Infinity) +
6725
+ (bInfo.completionTokenCostPer1M || Infinity)
6726
+ return aTotalCost - bTotalCost
6727
+ }
6728
+ */
6729
+ static metricComparator = (a, b) => {
6730
+ const aMetrics = a.getMetrics();
6731
+ const bMetrics = b.getMetrics();
6732
+ return aMetrics.latency.chat.mean - bMetrics.latency.chat.mean;
6731
6733
  };
6732
6734
  getModelList() {
6733
6735
  return this.currentService.getModelList();
6734
6736
  }
6737
+ getDefaultModels() {
6738
+ return this.currentService.getDefaultModels();
6739
+ }
6735
6740
  getNextService() {
6736
6741
  const cs = this.services[++this.currentServiceIndex];
6737
6742
  if (cs === void 0) {
@@ -6754,12 +6759,6 @@ var AxBalancer = class _AxBalancer {
6754
6759
  getId() {
6755
6760
  return this.currentService.getId();
6756
6761
  }
6757
- getModelInfo() {
6758
- return this.currentService.getModelInfo();
6759
- }
6760
- getEmbedModelInfo() {
6761
- return this.currentService.getEmbedModelInfo();
6762
- }
6763
6762
  getFeatures(model) {
6764
6763
  return this.currentService.getFeatures(model);
6765
6764
  }
@@ -6869,6 +6868,46 @@ var AxBalancer = class _AxBalancer {
6869
6868
  return this.currentService.getOptions();
6870
6869
  }
6871
6870
  };
6871
+ function validateModels2(services) {
6872
+ const serviceWithModel = services.find(
6873
+ (service) => service.getModelList() !== void 0
6874
+ );
6875
+ if (!serviceWithModel) {
6876
+ return;
6877
+ }
6878
+ const referenceModelList = serviceWithModel.getModelList();
6879
+ if (!referenceModelList) {
6880
+ throw new Error("No model list found in any service.");
6881
+ }
6882
+ const referenceKeys = new Set(referenceModelList.map((model) => model.key));
6883
+ for (let i = 0; i < services.length; i++) {
6884
+ const service = services[i];
6885
+ if (!service) {
6886
+ throw new Error(`Service at index ${i} is undefined`);
6887
+ }
6888
+ const modelList = service.getModelList();
6889
+ if (!modelList) {
6890
+ throw new Error(
6891
+ `Service at index ${i} (${service.getName()}) has no model list while another service does.`
6892
+ );
6893
+ }
6894
+ const serviceKeys = new Set(modelList.map((model) => model.key));
6895
+ for (const key of referenceKeys) {
6896
+ if (!serviceKeys.has(key)) {
6897
+ throw new Error(
6898
+ `Service at index ${i} (${service.getName()}) is missing model "${key}"`
6899
+ );
6900
+ }
6901
+ }
6902
+ for (const key of serviceKeys) {
6903
+ if (!referenceKeys.has(key)) {
6904
+ throw new Error(
6905
+ `Service at index ${i} (${service.getName()}) has extra model "${key}"`
6906
+ );
6907
+ }
6908
+ }
6909
+ }
6910
+ }
6872
6911
 
6873
6912
  // dsp/optimize.ts
6874
6913
  var AxBootstrapFewShot = class {
@@ -8100,18 +8139,6 @@ var AxMockAIService = class {
8100
8139
  getId() {
8101
8140
  return this.config.id ?? "mock-ai-service-id";
8102
8141
  }
8103
- getModelInfo() {
8104
- return {
8105
- name: "mock-model",
8106
- provider: "mock-provider",
8107
- promptTokenCostPer1M: 100,
8108
- completionTokenCostPer1M: 100,
8109
- ...this.config.modelInfo
8110
- };
8111
- }
8112
- getEmbedModelInfo() {
8113
- return this.config.embedModelInfo;
8114
- }
8115
8142
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
8116
8143
  getFeatures(_model) {
8117
8144
  return {
@@ -8122,6 +8149,12 @@ var AxMockAIService = class {
8122
8149
  getModelList() {
8123
8150
  return this.config.models;
8124
8151
  }
8152
+ getDefaultModels() {
8153
+ return {
8154
+ model: this.config.modelInfo?.name ?? "mock-model",
8155
+ embedModel: this.config.embedModelInfo?.name
8156
+ };
8157
+ }
8125
8158
  getMetrics() {
8126
8159
  return this.metrics;
8127
8160
  }
@@ -8199,7 +8232,7 @@ var AxMockAIService = class {
8199
8232
 
8200
8233
  // dsp/router.ts
8201
8234
  var colorLog6 = new ColorLog();
8202
- var AxRoute = class {
8235
+ var AxSimpleClassifierClass = class {
8203
8236
  name;
8204
8237
  context;
8205
8238
  constructor(name, context) {
@@ -8213,7 +8246,7 @@ var AxRoute = class {
8213
8246
  return this.context;
8214
8247
  }
8215
8248
  };
8216
- var AxRouter = class {
8249
+ var AxSimpleClassifier = class {
8217
8250
  ai;
8218
8251
  db;
8219
8252
  debug;
@@ -8227,12 +8260,12 @@ var AxRouter = class {
8227
8260
  setState(state) {
8228
8261
  this.db.setDB(state);
8229
8262
  }
8230
- setRoutes = async (routes) => {
8231
- for (const ro of routes) {
8232
- const ret = await this.ai.embed({ texts: ro.getContext() });
8263
+ setClasses = async (classes) => {
8264
+ for (const c of classes) {
8265
+ const ret = await this.ai.embed({ texts: c.getContext() });
8233
8266
  await this.db.upsert({
8234
- id: ro.getName(),
8235
- table: "routes",
8267
+ id: c.getName(),
8268
+ table: "classes",
8236
8269
  values: ret.embeddings[0]
8237
8270
  });
8238
8271
  }
@@ -8240,7 +8273,7 @@ var AxRouter = class {
8240
8273
  async forward(text, options) {
8241
8274
  const { embeddings } = await this.ai.embed({ texts: [text] });
8242
8275
  const matches = await this.db.query({
8243
- table: "routes",
8276
+ table: "classes",
8244
8277
  values: embeddings[0]
8245
8278
  });
8246
8279
  let m = matches.matches;
@@ -8255,11 +8288,11 @@ var AxRouter = class {
8255
8288
  )
8256
8289
  );
8257
8290
  }
8258
- const route = m.at(0);
8259
- if (!route) {
8291
+ const matchedClass = m.at(0);
8292
+ if (!matchedClass) {
8260
8293
  return "";
8261
8294
  }
8262
- return route.id;
8295
+ return matchedClass.id;
8263
8296
  }
8264
8297
  setOptions(options) {
8265
8298
  if (typeof options.debug === "boolean") {
@@ -8466,6 +8499,160 @@ var AxEmbeddingAdapter = class {
8466
8499
  }
8467
8500
  };
8468
8501
 
8502
+ // ai/multiservice.ts
8503
+ var AxMultiServiceRouter = class {
8504
+ services = /* @__PURE__ */ new Map();
8505
+ /**
8506
+ * Constructs a new multi-service router.
8507
+ * It validates that each service provides a unique set of model keys,
8508
+ * then builds a lookup (map) for routing the chat/embed requests.
8509
+ */
8510
+ constructor(services) {
8511
+ if (services.length === 0) {
8512
+ throw new Error("No AI services provided.");
8513
+ }
8514
+ for (const [index, item] of services.entries()) {
8515
+ const isKeyBased = "key" in item;
8516
+ if (isKeyBased) {
8517
+ if (this.services.has(item.key)) {
8518
+ throw new Error(`Duplicate model key: ${item.key}`);
8519
+ }
8520
+ const { service, description, isInternal } = item;
8521
+ this.services.set(item.key, {
8522
+ service,
8523
+ description,
8524
+ isInternal,
8525
+ model: item.service.getDefaultModels().model,
8526
+ useDefaultModel: true
8527
+ });
8528
+ } else {
8529
+ const modelList = item.getModelList();
8530
+ if (!modelList) {
8531
+ throw new Error(
8532
+ `Service ${index} \`${item.getName()}\` has no model list.`
8533
+ );
8534
+ }
8535
+ for (const { key, description, model } of modelList ?? []) {
8536
+ if (this.services.has(key)) {
8537
+ const otherService = this.services.get(key)?.service;
8538
+ throw new Error(
8539
+ `Service ${index} \`${item.getName()}\` has duplicate model key: ${key} as service ${otherService?.getName()}`
8540
+ );
8541
+ }
8542
+ this.services.set(key, {
8543
+ description,
8544
+ service: item,
8545
+ model
8546
+ });
8547
+ }
8548
+ }
8549
+ }
8550
+ }
8551
+ /**
8552
+ * Delegates the chat call to the service matching the provided model key.
8553
+ */
8554
+ async chat(req, options) {
8555
+ const modelKey = req.model;
8556
+ if (!modelKey) {
8557
+ throw new Error("Model key must be specified for multi-service");
8558
+ }
8559
+ const item = this.services.get(modelKey);
8560
+ if (!item) {
8561
+ throw new Error(`No service found for model key: ${modelKey}`);
8562
+ }
8563
+ const service = item.service;
8564
+ const model = item.useDefaultModel ? req.model : modelKey;
8565
+ return await service.chat({ model, ...req }, options);
8566
+ }
8567
+ /**
8568
+ * Delegates the embed call to the service matching the provided embed model key.
8569
+ */
8570
+ async embed(req, options) {
8571
+ const modelKey = req.embedModel;
8572
+ if (!modelKey) {
8573
+ throw new Error("Embed model key must be specified for multi-service");
8574
+ }
8575
+ const item = this.services.get(modelKey);
8576
+ if (!item) {
8577
+ throw new Error(`No service found for embed model key: ${modelKey}`);
8578
+ }
8579
+ const service = item.service;
8580
+ const embedModel = item.useDefaultModel ? req.embedModel : modelKey;
8581
+ return await service.embed({ embedModel, ...req }, options);
8582
+ }
8583
+ /**
8584
+ * Returns a composite ID built from the IDs of the underlying services.
8585
+ */
8586
+ getId() {
8587
+ return "MultiServiceRouter:" + Array.from(this.services.values()).map((s) => s.service.getId()).join(",");
8588
+ }
8589
+ /**
8590
+ * Returns the name of this router.
8591
+ */
8592
+ getName() {
8593
+ return "MultiServiceRouter";
8594
+ }
8595
+ /**
8596
+ * Aggregates all available models across the underlying services.
8597
+ */
8598
+ getModelList() {
8599
+ return Array.from(this.services).filter(([, value]) => !value.isInternal).map(([key, { description, model }]) => ({
8600
+ key,
8601
+ description,
8602
+ model
8603
+ }));
8604
+ }
8605
+ getDefaultModels() {
8606
+ throw new Error(
8607
+ "getDefaultModels is not supported for multi-service router."
8608
+ );
8609
+ }
8610
+ /**
8611
+ * If a model key is provided, delegate to the corresponding service's features.
8612
+ * Otherwise, returns a default feature set.
8613
+ */
8614
+ getFeatures(model) {
8615
+ if (model) {
8616
+ const service = this.services.get(model);
8617
+ if (service) {
8618
+ return service.service.getFeatures(model);
8619
+ }
8620
+ }
8621
+ return { functions: false, streaming: false };
8622
+ }
8623
+ /**
8624
+ * Returns aggregated metrics from the underlying service.
8625
+ * Uses the metrics from the last service that was used,
8626
+ * or falls back to the first service if none has been used.
8627
+ */
8628
+ getMetrics() {
8629
+ const service = this.services.values().next().value;
8630
+ if (!service) {
8631
+ throw new Error("No service available to get metrics.");
8632
+ }
8633
+ return service.service.getMetrics();
8634
+ }
8635
+ /**
8636
+ * Sets options on all underlying services.
8637
+ */
8638
+ setOptions(options) {
8639
+ for (const service of this.services.values()) {
8640
+ service.service.setOptions(options);
8641
+ }
8642
+ }
8643
+ /**
8644
+ * Returns the options from the last used service,
8645
+ * or falls back to the first service if none has been used.
8646
+ */
8647
+ getOptions() {
8648
+ const service = this.services.values().next().value;
8649
+ if (!service) {
8650
+ throw new Error("No service available to get options.");
8651
+ }
8652
+ return service.service.getOptions();
8653
+ }
8654
+ };
8655
+
8469
8656
  // prompts/rag.ts
8470
8657
  var AxRAG = class extends AxChainOfThought {
8471
8658
  genQuery;
@@ -8565,14 +8752,15 @@ export {
8565
8752
  AxLLMRequestTypeValues,
8566
8753
  AxMemory,
8567
8754
  AxMockAIService,
8755
+ AxMultiServiceRouter,
8568
8756
  AxProgram,
8569
8757
  AxProgramWithSignature,
8570
8758
  AxPromptTemplate,
8571
8759
  AxRAG,
8572
8760
  AxRateLimiterTokenUsage,
8573
- AxRoute,
8574
- AxRouter,
8575
8761
  AxSignature,
8762
+ AxSimpleClassifier,
8763
+ AxSimpleClassifierClass,
8576
8764
  AxSpanKindValues,
8577
8765
  AxTestPrompt
8578
8766
  };