@ax-llm/ax 12.0.20 → 12.0.21

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
@@ -1032,6 +1032,27 @@ var logResponseDelta = (delta, logger = defaultLogger) => {
1032
1032
  };
1033
1033
 
1034
1034
  // ai/metrics.ts
1035
+ var sanitizeLabels = (labels) => {
1036
+ const sanitized = {};
1037
+ for (const [key, value] of Object.entries(labels)) {
1038
+ if (value !== void 0 && value !== null) {
1039
+ const stringValue = String(value);
1040
+ sanitized[key] = stringValue.length > 100 ? stringValue.substring(0, 100) : stringValue;
1041
+ }
1042
+ }
1043
+ return sanitized;
1044
+ };
1045
+ var globalAIMetricsInstruments;
1046
+ var getOrCreateAIMetricsInstruments = (meter) => {
1047
+ if (globalAIMetricsInstruments) {
1048
+ return globalAIMetricsInstruments;
1049
+ }
1050
+ if (meter) {
1051
+ globalAIMetricsInstruments = createMetricsInstruments(meter);
1052
+ return globalAIMetricsInstruments;
1053
+ }
1054
+ return void 0;
1055
+ };
1035
1056
  var createMetricsInstruments = (meter) => {
1036
1057
  return {
1037
1058
  latencyHistogram: meter.createHistogram("ax_llm_request_duration_ms", {
@@ -1132,12 +1153,17 @@ var createMetricsInstruments = (meter) => {
1132
1153
  };
1133
1154
  };
1134
1155
  var recordLatencyMetric = (instruments, type, duration, aiService, model) => {
1135
- if (instruments.latencyHistogram) {
1136
- instruments.latencyHistogram.record(duration, {
1137
- operation: type,
1138
- ai_service: aiService,
1139
- ...model ? { model } : {}
1140
- });
1156
+ try {
1157
+ if (instruments.latencyHistogram) {
1158
+ const labels = sanitizeLabels({
1159
+ operation: type,
1160
+ ai_service: aiService,
1161
+ ...model ? { model } : {}
1162
+ });
1163
+ instruments.latencyHistogram.record(duration, labels);
1164
+ }
1165
+ } catch (error) {
1166
+ console.warn("Failed to record latency metric:", error);
1141
1167
  }
1142
1168
  };
1143
1169
  var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99Latency, aiService, model) => {
@@ -1157,12 +1183,17 @@ var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99
1157
1183
  }
1158
1184
  };
1159
1185
  var recordErrorMetric = (instruments, type, aiService, model) => {
1160
- if (instruments.errorCounter) {
1161
- instruments.errorCounter.add(1, {
1162
- operation: type,
1163
- ai_service: aiService,
1164
- ...model ? { model } : {}
1165
- });
1186
+ try {
1187
+ if (instruments.errorCounter) {
1188
+ const labels = sanitizeLabels({
1189
+ operation: type,
1190
+ ai_service: aiService,
1191
+ ...model ? { model } : {}
1192
+ });
1193
+ instruments.errorCounter.add(1, labels);
1194
+ }
1195
+ } catch (error) {
1196
+ console.warn("Failed to record error metric:", error);
1166
1197
  }
1167
1198
  };
1168
1199
  var recordErrorRateMetric = (instruments, type, errorRate, aiService, model) => {
@@ -1185,21 +1216,25 @@ var recordRequestMetric = (instruments, type, aiService, model) => {
1185
1216
  }
1186
1217
  };
1187
1218
  var recordTokenMetric = (instruments, type, tokens, aiService, model) => {
1188
- const labels = {
1189
- ai_service: aiService,
1190
- ...model ? { model } : {}
1191
- };
1192
- if (instruments.tokenCounter) {
1193
- instruments.tokenCounter.add(tokens, {
1194
- token_type: type,
1195
- ...labels
1219
+ try {
1220
+ const labels = sanitizeLabels({
1221
+ ai_service: aiService,
1222
+ ...model ? { model } : {}
1196
1223
  });
1197
- }
1198
- if (type === "input" && instruments.inputTokenCounter) {
1199
- instruments.inputTokenCounter.add(tokens, labels);
1200
- }
1201
- if (type === "output" && instruments.outputTokenCounter) {
1202
- instruments.outputTokenCounter.add(tokens, labels);
1224
+ if (instruments.tokenCounter) {
1225
+ instruments.tokenCounter.add(tokens, {
1226
+ token_type: type,
1227
+ ...labels
1228
+ });
1229
+ }
1230
+ if (type === "input" && instruments.inputTokenCounter) {
1231
+ instruments.inputTokenCounter.add(tokens, labels);
1232
+ }
1233
+ if (type === "output" && instruments.outputTokenCounter) {
1234
+ instruments.outputTokenCounter.add(tokens, labels);
1235
+ }
1236
+ } catch (error) {
1237
+ console.warn("Failed to record token metric:", error);
1203
1238
  }
1204
1239
  };
1205
1240
  var recordStreamingRequestMetric = (instruments, type, isStreaming, aiService, model) => {
@@ -1358,7 +1393,6 @@ var AxBaseAI = class {
1358
1393
  throw new Error("No model defined");
1359
1394
  }
1360
1395
  this.setOptions(options);
1361
- this.initializeMetricsInstruments();
1362
1396
  if (models) {
1363
1397
  validateModels(models);
1364
1398
  }
@@ -1373,8 +1407,6 @@ var AxBaseAI = class {
1373
1407
  models;
1374
1408
  abortSignal;
1375
1409
  logger = defaultLogger2;
1376
- // OpenTelemetry metrics instruments
1377
- metricsInstruments;
1378
1410
  modelInfo;
1379
1411
  modelUsage;
1380
1412
  embedModelUsage;
@@ -1416,10 +1448,8 @@ var AxBaseAI = class {
1416
1448
  }
1417
1449
  }
1418
1450
  };
1419
- initializeMetricsInstruments() {
1420
- if (this.meter) {
1421
- this.metricsInstruments = createMetricsInstruments(this.meter);
1422
- }
1451
+ getMetricsInstruments() {
1452
+ return getOrCreateAIMetricsInstruments(this.meter);
1423
1453
  }
1424
1454
  setName(name) {
1425
1455
  this.name = name;
@@ -1443,7 +1473,6 @@ var AxBaseAI = class {
1443
1473
  this.excludeContentFromTrace = options.excludeContentFromTrace;
1444
1474
  this.abortSignal = options.abortSignal;
1445
1475
  this.logger = options.logger ?? defaultLogger2;
1446
- this.initializeMetricsInstruments();
1447
1476
  }
1448
1477
  getOptions() {
1449
1478
  return {
@@ -1516,17 +1545,12 @@ var AxBaseAI = class {
1516
1545
  metrics.mean = metrics.samples.reduce((a, b) => a + b, 0) / metrics.samples.length;
1517
1546
  metrics.p95 = this.calculatePercentile(metrics.samples, 95);
1518
1547
  metrics.p99 = this.calculatePercentile(metrics.samples, 99);
1519
- if (this.metricsInstruments) {
1548
+ const metricsInstruments = this.getMetricsInstruments();
1549
+ if (metricsInstruments) {
1520
1550
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1521
- recordLatencyMetric(
1522
- this.metricsInstruments,
1523
- type,
1524
- duration,
1525
- this.name,
1526
- model
1527
- );
1551
+ recordLatencyMetric(metricsInstruments, type, duration, this.name, model);
1528
1552
  recordLatencyStatsMetrics(
1529
- this.metricsInstruments,
1553
+ metricsInstruments,
1530
1554
  type,
1531
1555
  metrics.mean,
1532
1556
  metrics.p95,
@@ -1544,14 +1568,15 @@ var AxBaseAI = class {
1544
1568
  metrics.count++;
1545
1569
  }
1546
1570
  metrics.rate = metrics.count / metrics.total;
1547
- if (this.metricsInstruments) {
1571
+ const metricsInstruments = this.getMetricsInstruments();
1572
+ if (metricsInstruments) {
1548
1573
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1549
- recordRequestMetric(this.metricsInstruments, type, this.name, model);
1574
+ recordRequestMetric(metricsInstruments, type, this.name, model);
1550
1575
  if (isError) {
1551
- recordErrorMetric(this.metricsInstruments, type, this.name, model);
1576
+ recordErrorMetric(metricsInstruments, type, this.name, model);
1552
1577
  }
1553
1578
  recordErrorRateMetric(
1554
- this.metricsInstruments,
1579
+ metricsInstruments,
1555
1580
  type,
1556
1581
  metrics.rate,
1557
1582
  this.name,
@@ -1561,11 +1586,12 @@ var AxBaseAI = class {
1561
1586
  }
1562
1587
  // Method to record token usage metrics
1563
1588
  recordTokenUsage(modelUsage) {
1564
- if (this.metricsInstruments && modelUsage?.tokens) {
1589
+ const metricsInstruments = this.getMetricsInstruments();
1590
+ if (metricsInstruments && modelUsage?.tokens) {
1565
1591
  const { promptTokens, completionTokens, totalTokens, thoughtsTokens } = modelUsage.tokens;
1566
1592
  if (promptTokens) {
1567
1593
  recordTokenMetric(
1568
- this.metricsInstruments,
1594
+ metricsInstruments,
1569
1595
  "input",
1570
1596
  promptTokens,
1571
1597
  this.name,
@@ -1574,7 +1600,7 @@ var AxBaseAI = class {
1574
1600
  }
1575
1601
  if (completionTokens) {
1576
1602
  recordTokenMetric(
1577
- this.metricsInstruments,
1603
+ metricsInstruments,
1578
1604
  "output",
1579
1605
  completionTokens,
1580
1606
  this.name,
@@ -1583,7 +1609,7 @@ var AxBaseAI = class {
1583
1609
  }
1584
1610
  if (totalTokens) {
1585
1611
  recordTokenMetric(
1586
- this.metricsInstruments,
1612
+ metricsInstruments,
1587
1613
  "total",
1588
1614
  totalTokens,
1589
1615
  this.name,
@@ -1592,7 +1618,7 @@ var AxBaseAI = class {
1592
1618
  }
1593
1619
  if (thoughtsTokens) {
1594
1620
  recordTokenMetric(
1595
- this.metricsInstruments,
1621
+ metricsInstruments,
1596
1622
  "thoughts",
1597
1623
  thoughtsTokens,
1598
1624
  this.name,
@@ -1699,11 +1725,12 @@ var AxBaseAI = class {
1699
1725
  }
1700
1726
  // Helper method to record function call metrics
1701
1727
  recordFunctionCallMetrics(functionCalls, model) {
1702
- if (!this.metricsInstruments || !functionCalls) return;
1728
+ const metricsInstruments = this.getMetricsInstruments();
1729
+ if (!metricsInstruments || !functionCalls) return;
1703
1730
  for (const call of functionCalls) {
1704
1731
  if (call && typeof call === "object" && "function" in call && call.function && typeof call.function === "object" && "name" in call.function) {
1705
1732
  recordFunctionCallMetric(
1706
- this.metricsInstruments,
1733
+ metricsInstruments,
1707
1734
  call.function.name,
1708
1735
  void 0,
1709
1736
  // latency would need to be tracked separately
@@ -1715,26 +1742,29 @@ var AxBaseAI = class {
1715
1742
  }
1716
1743
  // Helper method to record timeout metrics
1717
1744
  recordTimeoutMetric(type) {
1718
- if (this.metricsInstruments) {
1745
+ const metricsInstruments = this.getMetricsInstruments();
1746
+ if (metricsInstruments) {
1719
1747
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1720
- recordTimeoutMetric(this.metricsInstruments, type, this.name, model);
1748
+ recordTimeoutMetric(metricsInstruments, type, this.name, model);
1721
1749
  }
1722
1750
  }
1723
1751
  // Helper method to record abort metrics
1724
1752
  recordAbortMetric(type) {
1725
- if (this.metricsInstruments) {
1753
+ const metricsInstruments = this.getMetricsInstruments();
1754
+ if (metricsInstruments) {
1726
1755
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1727
- recordAbortMetric(this.metricsInstruments, type, this.name, model);
1756
+ recordAbortMetric(metricsInstruments, type, this.name, model);
1728
1757
  }
1729
1758
  }
1730
1759
  // Comprehensive method to record all chat-related metrics
1731
1760
  recordChatMetrics(req, options, result) {
1732
- if (!this.metricsInstruments) return;
1761
+ const metricsInstruments = this.getMetricsInstruments();
1762
+ if (!metricsInstruments) return;
1733
1763
  const model = this.lastUsedChatModel;
1734
1764
  const modelConfig = this.lastUsedModelConfig;
1735
1765
  const isStreaming = modelConfig?.stream ?? false;
1736
1766
  recordStreamingRequestMetric(
1737
- this.metricsInstruments,
1767
+ metricsInstruments,
1738
1768
  "chat",
1739
1769
  isStreaming,
1740
1770
  this.name,
@@ -1742,21 +1772,16 @@ var AxBaseAI = class {
1742
1772
  );
1743
1773
  const { hasImages, hasAudio } = this.detectMultimodalContent(req);
1744
1774
  recordMultimodalRequestMetric(
1745
- this.metricsInstruments,
1775
+ metricsInstruments,
1746
1776
  hasImages,
1747
1777
  hasAudio,
1748
1778
  this.name,
1749
1779
  model
1750
1780
  );
1751
1781
  const promptLength = this.calculatePromptLength(req);
1752
- recordPromptLengthMetric(
1753
- this.metricsInstruments,
1754
- promptLength,
1755
- this.name,
1756
- model
1757
- );
1782
+ recordPromptLengthMetric(metricsInstruments, promptLength, this.name, model);
1758
1783
  recordModelConfigMetrics(
1759
- this.metricsInstruments,
1784
+ metricsInstruments,
1760
1785
  modelConfig?.temperature,
1761
1786
  modelConfig?.maxTokens,
1762
1787
  this.name,
@@ -1764,7 +1789,7 @@ var AxBaseAI = class {
1764
1789
  );
1765
1790
  if (options?.thinkingTokenBudget && this.modelUsage?.tokens?.thoughtsTokens) {
1766
1791
  recordThinkingBudgetUsageMetric(
1767
- this.metricsInstruments,
1792
+ metricsInstruments,
1768
1793
  this.modelUsage.tokens.thoughtsTokens,
1769
1794
  this.name,
1770
1795
  model
@@ -1772,7 +1797,7 @@ var AxBaseAI = class {
1772
1797
  }
1773
1798
  const requestSize = this.calculateRequestSize(req);
1774
1799
  recordRequestSizeMetric(
1775
- this.metricsInstruments,
1800
+ metricsInstruments,
1776
1801
  "chat",
1777
1802
  requestSize,
1778
1803
  this.name,
@@ -1782,7 +1807,7 @@ var AxBaseAI = class {
1782
1807
  const chatResponse = result;
1783
1808
  const responseSize = this.calculateResponseSize(chatResponse);
1784
1809
  recordResponseSizeMetric(
1785
- this.metricsInstruments,
1810
+ metricsInstruments,
1786
1811
  "chat",
1787
1812
  responseSize,
1788
1813
  this.name,
@@ -1804,7 +1829,7 @@ var AxBaseAI = class {
1804
1829
  );
1805
1830
  if (contextUsage > 0) {
1806
1831
  recordContextWindowUsageMetric(
1807
- this.metricsInstruments,
1832
+ metricsInstruments,
1808
1833
  contextUsage,
1809
1834
  this.name,
1810
1835
  model
@@ -1816,7 +1841,7 @@ var AxBaseAI = class {
1816
1841
  );
1817
1842
  if (estimatedCost > 0) {
1818
1843
  recordEstimatedCostMetric(
1819
- this.metricsInstruments,
1844
+ metricsInstruments,
1820
1845
  "chat",
1821
1846
  estimatedCost,
1822
1847
  this.name,
@@ -1827,11 +1852,12 @@ var AxBaseAI = class {
1827
1852
  }
1828
1853
  // Comprehensive method to record all embed-related metrics
1829
1854
  recordEmbedMetrics(req, result) {
1830
- if (!this.metricsInstruments) return;
1855
+ const metricsInstruments = this.getMetricsInstruments();
1856
+ if (!metricsInstruments) return;
1831
1857
  const model = this.lastUsedEmbedModel;
1832
1858
  const requestSize = this.calculateRequestSize(req);
1833
1859
  recordRequestSizeMetric(
1834
- this.metricsInstruments,
1860
+ metricsInstruments,
1835
1861
  "embed",
1836
1862
  requestSize,
1837
1863
  this.name,
@@ -1839,7 +1865,7 @@ var AxBaseAI = class {
1839
1865
  );
1840
1866
  const responseSize = this.calculateResponseSize(result);
1841
1867
  recordResponseSizeMetric(
1842
- this.metricsInstruments,
1868
+ metricsInstruments,
1843
1869
  "embed",
1844
1870
  responseSize,
1845
1871
  this.name,
@@ -1848,7 +1874,7 @@ var AxBaseAI = class {
1848
1874
  const estimatedCost = this.estimateCostByName(model, result.modelUsage);
1849
1875
  if (estimatedCost > 0) {
1850
1876
  recordEstimatedCostMetric(
1851
- this.metricsInstruments,
1877
+ metricsInstruments,
1852
1878
  "embed",
1853
1879
  estimatedCost,
1854
1880
  this.name,
@@ -8522,196 +8548,691 @@ function createFunctionConfig(functionList, definedFunctionCall, firstStep) {
8522
8548
  return { functions, functionCall };
8523
8549
  }
8524
8550
 
8525
- // dsp/processResponse.ts
8526
- import "stream/web";
8527
-
8528
- // ai/util.ts
8529
- function mergeFunctionCalls(functionCalls, functionCallDeltas) {
8530
- for (const _fc of functionCallDeltas) {
8531
- const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
8532
- if (fc) {
8533
- if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
8534
- fc.function.name += _fc.function.name;
8535
- }
8536
- if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
8537
- fc.function.params += _fc.function.params;
8538
- }
8539
- if (typeof _fc.function.params == "object") {
8540
- fc.function.params = _fc.function.params;
8541
- }
8542
- } else {
8543
- functionCalls.push(_fc);
8544
- }
8551
+ // dsp/metrics.ts
8552
+ var axDefaultMetricsConfig = {
8553
+ enabled: true,
8554
+ enabledCategories: [
8555
+ "generation",
8556
+ "streaming",
8557
+ "functions",
8558
+ "errors",
8559
+ "performance"
8560
+ ],
8561
+ maxLabelLength: 100,
8562
+ samplingRate: 1
8563
+ };
8564
+ var globalGenMetricsInstruments;
8565
+ var getOrCreateGenMetricsInstruments = (meter) => {
8566
+ if (globalGenMetricsInstruments) {
8567
+ return globalGenMetricsInstruments;
8545
8568
  }
8546
- }
8547
-
8548
- // dsp/sig.ts
8549
- import { createHash } from "crypto";
8550
-
8551
- // dsp/parser.ts
8552
- var SignatureValidationError = class extends Error {
8553
- constructor(message, position, context3, suggestion) {
8554
- super(message);
8555
- this.position = position;
8556
- this.context = context3;
8557
- this.suggestion = suggestion;
8558
- this.name = "SignatureValidationError";
8569
+ const activeMeter = meter ?? axGlobals.meter;
8570
+ if (activeMeter) {
8571
+ globalGenMetricsInstruments = createGenMetricsInstruments(activeMeter);
8572
+ return globalGenMetricsInstruments;
8559
8573
  }
8574
+ return void 0;
8560
8575
  };
8561
- var SignatureParser = class {
8562
- input;
8563
- position;
8564
- currentFieldName = null;
8565
- currentSection = "description";
8566
- constructor(input) {
8567
- this.input = input.trim();
8568
- this.position = 0;
8569
- if (!this.input) {
8570
- throw new SignatureValidationError(
8571
- "Empty signature provided",
8572
- 0,
8573
- "",
8574
- 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
8575
- );
8576
- }
8576
+ var axCheckMetricsHealth = () => {
8577
+ const issues = [];
8578
+ if (!axGlobals.meter) {
8579
+ issues.push("Global meter not initialized");
8577
8580
  }
8578
- parse() {
8579
- try {
8580
- this.skipWhitespace();
8581
- const optionalDesc = this.parseParsedString();
8582
- this.skipWhitespace();
8583
- this.currentSection = "inputs";
8584
- const inputs = this.parseFieldList(
8585
- this.parseInputField.bind(this),
8586
- "input"
8587
- );
8588
- this.skipWhitespace();
8589
- if (this.position >= this.input.length) {
8590
- throw new SignatureValidationError(
8591
- "Incomplete signature: Missing output section",
8592
- this.position,
8593
- this.getErrorContext(),
8594
- 'Add "->" followed by output fields. Example: "-> responseText:string"'
8595
- );
8581
+ if (!globalGenMetricsInstruments && axGlobals.meter) {
8582
+ issues.push("Metrics instruments not created despite available meter");
8583
+ }
8584
+ return {
8585
+ healthy: issues.length === 0,
8586
+ issues
8587
+ };
8588
+ };
8589
+ var createGenMetricsInstruments = (meter) => {
8590
+ return {
8591
+ // Generation flow metrics
8592
+ // Note: Histogram buckets should be configured at the exporter level
8593
+ // Recommended buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000] ms
8594
+ generationLatencyHistogram: meter.createHistogram(
8595
+ "ax_gen_generation_duration_ms",
8596
+ {
8597
+ description: "End-to-end duration of AxGen generation requests",
8598
+ unit: "ms"
8596
8599
  }
8597
- this.expectArrow();
8598
- this.skipWhitespace();
8599
- if (this.position >= this.input.length) {
8600
- throw new SignatureValidationError(
8601
- 'Incomplete signature: No output fields specified after "->"',
8602
- this.position,
8603
- this.getErrorContext(),
8604
- 'Add at least one output field. Example: "-> responseText:string"'
8605
- );
8600
+ ),
8601
+ generationRequestsCounter: meter.createCounter(
8602
+ "ax_gen_generation_requests_total",
8603
+ {
8604
+ description: "Total number of AxGen generation requests"
8606
8605
  }
8607
- this.currentSection = "outputs";
8608
- const outputs = this.parseFieldList(
8609
- this.parseOutputField.bind(this),
8610
- "output"
8611
- );
8612
- this.skipWhitespace();
8613
- if (this.position < this.input.length) {
8614
- const remaining = this.input.slice(this.position);
8615
- throw new SignatureValidationError(
8616
- `Unexpected content after signature: "${remaining}"`,
8617
- this.position,
8618
- this.getErrorContext(),
8619
- "Remove any extra content after the output fields"
8620
- );
8606
+ ),
8607
+ generationErrorsCounter: meter.createCounter(
8608
+ "ax_gen_generation_errors_total",
8609
+ {
8610
+ description: "Total number of failed AxGen generations"
8621
8611
  }
8622
- this.validateParsedSignature({
8623
- desc: optionalDesc?.trim(),
8624
- inputs,
8625
- outputs
8626
- });
8627
- return {
8628
- desc: optionalDesc?.trim(),
8629
- inputs,
8630
- outputs
8631
- };
8632
- } catch (error) {
8633
- if (error instanceof SignatureValidationError) {
8634
- throw error;
8612
+ ),
8613
+ // Multi-step flow metrics
8614
+ multiStepGenerationsCounter: meter.createCounter(
8615
+ "ax_gen_multistep_generations_total",
8616
+ {
8617
+ description: "Total number of generations that required multiple steps"
8635
8618
  }
8636
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
8637
- throw new SignatureValidationError(
8638
- errorMessage,
8639
- this.position,
8640
- this.getErrorContext()
8641
- );
8642
- }
8643
- }
8644
- validateParsedSignature(signature) {
8645
- const inputNames = /* @__PURE__ */ new Set();
8646
- for (const field of signature.inputs) {
8647
- if (inputNames.has(field.name)) {
8648
- throw new SignatureValidationError(
8649
- `Duplicate input field name: "${field.name}"`,
8650
- 0,
8651
- "",
8652
- "Each field name must be unique within the signature"
8653
- );
8619
+ ),
8620
+ stepsPerGenerationHistogram: meter.createHistogram(
8621
+ "ax_gen_steps_per_generation",
8622
+ {
8623
+ description: "Number of steps taken per generation"
8654
8624
  }
8655
- inputNames.add(field.name);
8656
- }
8657
- const outputNames = /* @__PURE__ */ new Set();
8658
- for (const field of signature.outputs) {
8659
- if (outputNames.has(field.name)) {
8660
- throw new SignatureValidationError(
8661
- `Duplicate output field name: "${field.name}"`,
8662
- 0,
8663
- "",
8664
- "Each field name must be unique within the signature"
8665
- );
8625
+ ),
8626
+ maxStepsReachedCounter: meter.createCounter(
8627
+ "ax_gen_max_steps_reached_total",
8628
+ {
8629
+ description: "Total number of generations that hit max steps limit"
8666
8630
  }
8667
- outputNames.add(field.name);
8668
- }
8669
- for (const outputField of signature.outputs) {
8670
- if (inputNames.has(outputField.name)) {
8671
- throw new SignatureValidationError(
8672
- `Field name "${outputField.name}" appears in both inputs and outputs`,
8673
- 0,
8674
- "",
8675
- "Use different names for input and output fields to avoid confusion"
8676
- );
8631
+ ),
8632
+ // Error correction metrics
8633
+ validationErrorsCounter: meter.createCounter(
8634
+ "ax_gen_validation_errors_total",
8635
+ {
8636
+ description: "Total number of validation errors encountered"
8677
8637
  }
8678
- }
8679
- if (signature.inputs.length === 0) {
8680
- throw new SignatureValidationError(
8681
- "Signature must have at least one input field",
8682
- 0,
8683
- "",
8684
- 'Add an input field before "->". Example: "userInput:string -> ..."'
8685
- );
8686
- }
8687
- if (signature.outputs.length === 0) {
8688
- throw new SignatureValidationError(
8689
- "Signature must have at least one output field",
8690
- 0,
8691
- "",
8692
- 'Add an output field after "->". Example: "... -> responseText:string"'
8693
- );
8694
- }
8695
- }
8696
- getErrorContext() {
8697
- const start = Math.max(0, this.position - 25);
8698
- const end = Math.min(this.input.length, this.position + 25);
8699
- const before = this.input.slice(start, this.position);
8700
- const after = this.input.slice(this.position, end);
8701
- const pointer = " ".repeat(before.length) + "^";
8702
- const lines = [
8703
- `Position ${this.position} in signature:`,
8704
- `"${before}${after}"`,
8705
- ` ${pointer}`
8706
- ];
8707
- return lines.join("\n");
8708
- }
8709
- parseFieldList(parseFieldFn, section) {
8710
- const fields = [];
8711
- this.skipWhitespace();
8712
- if (this.position >= this.input.length) {
8713
- throw new SignatureValidationError(
8714
- `Empty ${section} section: Expected at least one field`,
8638
+ ),
8639
+ assertionErrorsCounter: meter.createCounter(
8640
+ "ax_gen_assertion_errors_total",
8641
+ {
8642
+ description: "Total number of assertion errors encountered"
8643
+ }
8644
+ ),
8645
+ errorCorrectionAttemptsHistogram: meter.createHistogram(
8646
+ "ax_gen_error_correction_attempts",
8647
+ {
8648
+ description: "Number of error correction attempts per generation"
8649
+ }
8650
+ ),
8651
+ errorCorrectionSuccessCounter: meter.createCounter(
8652
+ "ax_gen_error_correction_success_total",
8653
+ {
8654
+ description: "Total number of successful error corrections"
8655
+ }
8656
+ ),
8657
+ errorCorrectionFailureCounter: meter.createCounter(
8658
+ "ax_gen_error_correction_failure_total",
8659
+ {
8660
+ description: "Total number of failed error corrections"
8661
+ }
8662
+ ),
8663
+ maxRetriesReachedCounter: meter.createCounter(
8664
+ "ax_gen_max_retries_reached_total",
8665
+ {
8666
+ description: "Total number of generations that hit max retries limit"
8667
+ }
8668
+ ),
8669
+ // Function calling metrics
8670
+ functionsEnabledGenerationsCounter: meter.createCounter(
8671
+ "ax_gen_functions_enabled_generations_total",
8672
+ {
8673
+ description: "Total number of generations with functions enabled"
8674
+ }
8675
+ ),
8676
+ functionCallStepsCounter: meter.createCounter(
8677
+ "ax_gen_function_call_steps_total",
8678
+ {
8679
+ description: "Total number of steps that included function calls"
8680
+ }
8681
+ ),
8682
+ functionsExecutedPerGenerationHistogram: meter.createHistogram(
8683
+ "ax_gen_functions_executed_per_generation",
8684
+ {
8685
+ description: "Number of unique functions executed per generation"
8686
+ }
8687
+ ),
8688
+ functionErrorCorrectionCounter: meter.createCounter(
8689
+ "ax_gen_function_error_correction_total",
8690
+ {
8691
+ description: "Total number of function-related error corrections"
8692
+ }
8693
+ ),
8694
+ // Field processing metrics
8695
+ fieldProcessorsExecutedCounter: meter.createCounter(
8696
+ "ax_gen_field_processors_executed_total",
8697
+ {
8698
+ description: "Total number of field processors executed"
8699
+ }
8700
+ ),
8701
+ streamingFieldProcessorsExecutedCounter: meter.createCounter(
8702
+ "ax_gen_streaming_field_processors_executed_total",
8703
+ {
8704
+ description: "Total number of streaming field processors executed"
8705
+ }
8706
+ ),
8707
+ // Streaming specific metrics
8708
+ streamingGenerationsCounter: meter.createCounter(
8709
+ "ax_gen_streaming_generations_total",
8710
+ {
8711
+ description: "Total number of streaming generations"
8712
+ }
8713
+ ),
8714
+ streamingDeltasEmittedCounter: meter.createCounter(
8715
+ "ax_gen_streaming_deltas_emitted_total",
8716
+ {
8717
+ description: "Total number of streaming deltas emitted"
8718
+ }
8719
+ ),
8720
+ streamingFinalizationLatencyHistogram: meter.createHistogram(
8721
+ "ax_gen_streaming_finalization_duration_ms",
8722
+ {
8723
+ description: "Duration of streaming response finalization",
8724
+ unit: "ms"
8725
+ }
8726
+ ),
8727
+ // Memory and samples metrics
8728
+ samplesGeneratedHistogram: meter.createHistogram(
8729
+ "ax_gen_samples_generated",
8730
+ {
8731
+ description: "Number of samples generated per request"
8732
+ }
8733
+ ),
8734
+ resultPickerUsageCounter: meter.createCounter(
8735
+ "ax_gen_result_picker_usage_total",
8736
+ {
8737
+ description: "Total number of times result picker was used"
8738
+ }
8739
+ ),
8740
+ resultPickerLatencyHistogram: meter.createHistogram(
8741
+ "ax_gen_result_picker_duration_ms",
8742
+ {
8743
+ description: "Duration of result picker execution",
8744
+ unit: "ms"
8745
+ }
8746
+ ),
8747
+ // Signature complexity metrics
8748
+ inputFieldsGauge: meter.createGauge("ax_gen_input_fields", {
8749
+ description: "Number of input fields in signature"
8750
+ }),
8751
+ outputFieldsGauge: meter.createGauge("ax_gen_output_fields", {
8752
+ description: "Number of output fields in signature"
8753
+ }),
8754
+ examplesUsedGauge: meter.createGauge("ax_gen_examples_used", {
8755
+ description: "Number of examples used in generation"
8756
+ }),
8757
+ demosUsedGauge: meter.createGauge("ax_gen_demos_used", {
8758
+ description: "Number of demos used in generation"
8759
+ }),
8760
+ // Performance metrics
8761
+ promptRenderLatencyHistogram: meter.createHistogram(
8762
+ "ax_gen_prompt_render_duration_ms",
8763
+ {
8764
+ description: "Duration of prompt template rendering",
8765
+ unit: "ms"
8766
+ }
8767
+ ),
8768
+ extractionLatencyHistogram: meter.createHistogram(
8769
+ "ax_gen_extraction_duration_ms",
8770
+ {
8771
+ description: "Duration of value extraction from responses",
8772
+ unit: "ms"
8773
+ }
8774
+ ),
8775
+ assertionLatencyHistogram: meter.createHistogram(
8776
+ "ax_gen_assertion_duration_ms",
8777
+ {
8778
+ description: "Duration of assertion checking",
8779
+ unit: "ms"
8780
+ }
8781
+ ),
8782
+ // State management
8783
+ stateCreationLatencyHistogram: meter.createHistogram(
8784
+ "ax_gen_state_creation_duration_ms",
8785
+ {
8786
+ description: "Duration of state creation for multiple samples",
8787
+ unit: "ms"
8788
+ }
8789
+ ),
8790
+ memoryUpdateLatencyHistogram: meter.createHistogram(
8791
+ "ax_gen_memory_update_duration_ms",
8792
+ {
8793
+ description: "Duration of memory updates during generation",
8794
+ unit: "ms"
8795
+ }
8796
+ )
8797
+ };
8798
+ };
8799
+ var currentMetricsConfig = axDefaultMetricsConfig;
8800
+ var axUpdateMetricsConfig = (config) => {
8801
+ currentMetricsConfig = { ...currentMetricsConfig, ...config };
8802
+ };
8803
+ var axGetMetricsConfig = () => {
8804
+ return { ...currentMetricsConfig };
8805
+ };
8806
+ var sanitizeLabels2 = (labels) => {
8807
+ const sanitized = {};
8808
+ for (const [key, value] of Object.entries(labels)) {
8809
+ if (value !== void 0 && value !== null) {
8810
+ const stringValue = String(value);
8811
+ const maxLength = currentMetricsConfig.maxLabelLength;
8812
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
8813
+ }
8814
+ }
8815
+ return sanitized;
8816
+ };
8817
+ var recordGenerationMetric = (instruments, duration, success, signatureName, aiService, model) => {
8818
+ try {
8819
+ const labels = sanitizeLabels2({
8820
+ success: success.toString(),
8821
+ ...signatureName ? { signature: signatureName } : {},
8822
+ ...aiService ? { ai_service: aiService } : {},
8823
+ ...model ? { model } : {}
8824
+ });
8825
+ if (instruments.generationLatencyHistogram) {
8826
+ instruments.generationLatencyHistogram.record(duration, labels);
8827
+ }
8828
+ if (instruments.generationRequestsCounter) {
8829
+ instruments.generationRequestsCounter.add(1, labels);
8830
+ }
8831
+ if (!success && instruments.generationErrorsCounter) {
8832
+ instruments.generationErrorsCounter.add(1, labels);
8833
+ }
8834
+ } catch (error) {
8835
+ console.warn("Failed to record generation metric:", error);
8836
+ }
8837
+ };
8838
+ var recordMultiStepMetric = (instruments, stepsUsed, maxSteps, signatureName) => {
8839
+ try {
8840
+ const labels = sanitizeLabels2({
8841
+ ...signatureName ? { signature: signatureName } : {}
8842
+ });
8843
+ if (stepsUsed > 1 && instruments.multiStepGenerationsCounter) {
8844
+ instruments.multiStepGenerationsCounter.add(1, labels);
8845
+ }
8846
+ if (instruments.stepsPerGenerationHistogram) {
8847
+ instruments.stepsPerGenerationHistogram.record(stepsUsed, labels);
8848
+ }
8849
+ if (stepsUsed >= maxSteps && instruments.maxStepsReachedCounter) {
8850
+ instruments.maxStepsReachedCounter.add(1, labels);
8851
+ }
8852
+ } catch (error) {
8853
+ console.warn("Failed to record multi-step metric:", error);
8854
+ }
8855
+ };
8856
+ var recordValidationErrorMetric = (instruments, errorType, signatureName) => {
8857
+ try {
8858
+ const labels = sanitizeLabels2({
8859
+ error_type: errorType,
8860
+ ...signatureName ? { signature: signatureName } : {}
8861
+ });
8862
+ if (errorType === "validation" && instruments.validationErrorsCounter) {
8863
+ instruments.validationErrorsCounter.add(1, labels);
8864
+ }
8865
+ if (errorType === "assertion" && instruments.assertionErrorsCounter) {
8866
+ instruments.assertionErrorsCounter.add(1, labels);
8867
+ }
8868
+ } catch (error) {
8869
+ console.warn("Failed to record validation error metric:", error);
8870
+ }
8871
+ };
8872
+ var recordErrorCorrectionMetric = (instruments, attempts, success, maxRetries, signatureName) => {
8873
+ try {
8874
+ const labels = sanitizeLabels2({
8875
+ success: success.toString(),
8876
+ ...signatureName ? { signature: signatureName } : {}
8877
+ });
8878
+ if (instruments.errorCorrectionAttemptsHistogram) {
8879
+ instruments.errorCorrectionAttemptsHistogram.record(attempts, labels);
8880
+ }
8881
+ if (success && instruments.errorCorrectionSuccessCounter) {
8882
+ instruments.errorCorrectionSuccessCounter.add(1, labels);
8883
+ }
8884
+ if (!success) {
8885
+ if (instruments.errorCorrectionFailureCounter) {
8886
+ instruments.errorCorrectionFailureCounter.add(1, labels);
8887
+ }
8888
+ if (attempts >= maxRetries && instruments.maxRetriesReachedCounter) {
8889
+ instruments.maxRetriesReachedCounter.add(1, labels);
8890
+ }
8891
+ }
8892
+ } catch (error) {
8893
+ console.warn("Failed to record error correction metric:", error);
8894
+ }
8895
+ };
8896
+ var recordFunctionCallingMetric = (instruments, functionsEnabled, functionsExecuted, hadFunctionCalls, functionErrorCorrection = false, signatureName) => {
8897
+ try {
8898
+ const labels = sanitizeLabels2({
8899
+ functions_enabled: functionsEnabled.toString(),
8900
+ had_function_calls: hadFunctionCalls.toString(),
8901
+ ...signatureName ? { signature: signatureName } : {}
8902
+ });
8903
+ if (functionsEnabled && instruments.functionsEnabledGenerationsCounter) {
8904
+ instruments.functionsEnabledGenerationsCounter.add(1, labels);
8905
+ }
8906
+ if (hadFunctionCalls && instruments.functionCallStepsCounter) {
8907
+ instruments.functionCallStepsCounter.add(1, labels);
8908
+ }
8909
+ if (functionsExecuted > 0 && instruments.functionsExecutedPerGenerationHistogram) {
8910
+ instruments.functionsExecutedPerGenerationHistogram.record(
8911
+ functionsExecuted,
8912
+ labels
8913
+ );
8914
+ }
8915
+ if (functionErrorCorrection && instruments.functionErrorCorrectionCounter) {
8916
+ instruments.functionErrorCorrectionCounter.add(1, labels);
8917
+ }
8918
+ } catch (error) {
8919
+ console.warn("Failed to record function calling metric:", error);
8920
+ }
8921
+ };
8922
+ var recordFieldProcessingMetric = (instruments, fieldProcessorsExecuted, streamingFieldProcessorsExecuted, signatureName) => {
8923
+ try {
8924
+ const labels = sanitizeLabels2({
8925
+ ...signatureName ? { signature: signatureName } : {}
8926
+ });
8927
+ if (fieldProcessorsExecuted > 0 && instruments.fieldProcessorsExecutedCounter) {
8928
+ instruments.fieldProcessorsExecutedCounter.add(
8929
+ fieldProcessorsExecuted,
8930
+ labels
8931
+ );
8932
+ }
8933
+ if (streamingFieldProcessorsExecuted > 0 && instruments.streamingFieldProcessorsExecutedCounter) {
8934
+ instruments.streamingFieldProcessorsExecutedCounter.add(
8935
+ streamingFieldProcessorsExecuted,
8936
+ labels
8937
+ );
8938
+ }
8939
+ } catch (error) {
8940
+ console.warn("Failed to record field processing metric:", error);
8941
+ }
8942
+ };
8943
+ var recordStreamingMetric = (instruments, isStreaming, deltasEmitted, finalizationDuration, signatureName) => {
8944
+ try {
8945
+ const labels = sanitizeLabels2({
8946
+ is_streaming: isStreaming.toString(),
8947
+ ...signatureName ? { signature: signatureName } : {}
8948
+ });
8949
+ if (isStreaming && instruments.streamingGenerationsCounter) {
8950
+ instruments.streamingGenerationsCounter.add(1, labels);
8951
+ }
8952
+ if (deltasEmitted > 0 && instruments.streamingDeltasEmittedCounter) {
8953
+ instruments.streamingDeltasEmittedCounter.add(deltasEmitted, labels);
8954
+ }
8955
+ if (finalizationDuration && instruments.streamingFinalizationLatencyHistogram) {
8956
+ instruments.streamingFinalizationLatencyHistogram.record(
8957
+ finalizationDuration,
8958
+ labels
8959
+ );
8960
+ }
8961
+ } catch (error) {
8962
+ console.warn("Failed to record streaming metric:", error);
8963
+ }
8964
+ };
8965
+ var recordSamplesMetric = (instruments, samplesCount, resultPickerUsed, resultPickerLatency, signatureName) => {
8966
+ try {
8967
+ const labels = sanitizeLabels2({
8968
+ result_picker_used: resultPickerUsed.toString(),
8969
+ ...signatureName ? { signature: signatureName } : {}
8970
+ });
8971
+ if (instruments.samplesGeneratedHistogram) {
8972
+ instruments.samplesGeneratedHistogram.record(samplesCount, labels);
8973
+ }
8974
+ if (resultPickerUsed && instruments.resultPickerUsageCounter) {
8975
+ instruments.resultPickerUsageCounter.add(1, labels);
8976
+ }
8977
+ if (resultPickerLatency && instruments.resultPickerLatencyHistogram) {
8978
+ instruments.resultPickerLatencyHistogram.record(
8979
+ resultPickerLatency,
8980
+ labels
8981
+ );
8982
+ }
8983
+ } catch (error) {
8984
+ console.warn("Failed to record samples metric:", error);
8985
+ }
8986
+ };
8987
+ var recordSignatureComplexityMetrics = (instruments, inputFields, outputFields, examplesCount, demosCount, signatureName) => {
8988
+ try {
8989
+ const labels = sanitizeLabels2({
8990
+ ...signatureName ? { signature: signatureName } : {}
8991
+ });
8992
+ if (instruments.inputFieldsGauge) {
8993
+ instruments.inputFieldsGauge.record(inputFields, labels);
8994
+ }
8995
+ if (instruments.outputFieldsGauge) {
8996
+ instruments.outputFieldsGauge.record(outputFields, labels);
8997
+ }
8998
+ if (instruments.examplesUsedGauge) {
8999
+ instruments.examplesUsedGauge.record(examplesCount, labels);
9000
+ }
9001
+ if (instruments.demosUsedGauge) {
9002
+ instruments.demosUsedGauge.record(demosCount, labels);
9003
+ }
9004
+ } catch (error) {
9005
+ console.warn("Failed to record signature complexity metrics:", error);
9006
+ }
9007
+ };
9008
+ var recordPerformanceMetric = (instruments, metricType, duration, signatureName) => {
9009
+ try {
9010
+ const labels = sanitizeLabels2({
9011
+ metric_type: metricType,
9012
+ ...signatureName ? { signature: signatureName } : {}
9013
+ });
9014
+ switch (metricType) {
9015
+ case "prompt_render":
9016
+ if (instruments.promptRenderLatencyHistogram) {
9017
+ instruments.promptRenderLatencyHistogram.record(duration, labels);
9018
+ }
9019
+ break;
9020
+ case "extraction":
9021
+ if (instruments.extractionLatencyHistogram) {
9022
+ instruments.extractionLatencyHistogram.record(duration, labels);
9023
+ }
9024
+ break;
9025
+ case "assertion":
9026
+ if (instruments.assertionLatencyHistogram) {
9027
+ instruments.assertionLatencyHistogram.record(duration, labels);
9028
+ }
9029
+ break;
9030
+ case "state_creation":
9031
+ if (instruments.stateCreationLatencyHistogram) {
9032
+ instruments.stateCreationLatencyHistogram.record(duration, labels);
9033
+ }
9034
+ break;
9035
+ case "memory_update":
9036
+ if (instruments.memoryUpdateLatencyHistogram) {
9037
+ instruments.memoryUpdateLatencyHistogram.record(duration, labels);
9038
+ }
9039
+ break;
9040
+ }
9041
+ } catch (error) {
9042
+ console.warn("Failed to record performance metric:", error);
9043
+ }
9044
+ };
9045
+
9046
+ // dsp/processResponse.ts
9047
+ import "stream/web";
9048
+
9049
+ // ai/util.ts
9050
+ function mergeFunctionCalls(functionCalls, functionCallDeltas) {
9051
+ for (const _fc of functionCallDeltas) {
9052
+ const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
9053
+ if (fc) {
9054
+ if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
9055
+ fc.function.name += _fc.function.name;
9056
+ }
9057
+ if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
9058
+ fc.function.params += _fc.function.params;
9059
+ }
9060
+ if (typeof _fc.function.params == "object") {
9061
+ fc.function.params = _fc.function.params;
9062
+ }
9063
+ } else {
9064
+ functionCalls.push(_fc);
9065
+ }
9066
+ }
9067
+ }
9068
+
9069
+ // dsp/sig.ts
9070
+ import { createHash } from "crypto";
9071
+
9072
+ // dsp/parser.ts
9073
+ var SignatureValidationError = class extends Error {
9074
+ constructor(message, position, context3, suggestion) {
9075
+ super(message);
9076
+ this.position = position;
9077
+ this.context = context3;
9078
+ this.suggestion = suggestion;
9079
+ this.name = "SignatureValidationError";
9080
+ }
9081
+ };
9082
+ var SignatureParser = class {
9083
+ input;
9084
+ position;
9085
+ currentFieldName = null;
9086
+ currentSection = "description";
9087
+ constructor(input) {
9088
+ this.input = input.trim();
9089
+ this.position = 0;
9090
+ if (!this.input) {
9091
+ throw new SignatureValidationError(
9092
+ "Empty signature provided",
9093
+ 0,
9094
+ "",
9095
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
9096
+ );
9097
+ }
9098
+ }
9099
+ parse() {
9100
+ try {
9101
+ this.skipWhitespace();
9102
+ const optionalDesc = this.parseParsedString();
9103
+ this.skipWhitespace();
9104
+ this.currentSection = "inputs";
9105
+ const inputs = this.parseFieldList(
9106
+ this.parseInputField.bind(this),
9107
+ "input"
9108
+ );
9109
+ this.skipWhitespace();
9110
+ if (this.position >= this.input.length) {
9111
+ throw new SignatureValidationError(
9112
+ "Incomplete signature: Missing output section",
9113
+ this.position,
9114
+ this.getErrorContext(),
9115
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
9116
+ );
9117
+ }
9118
+ this.expectArrow();
9119
+ this.skipWhitespace();
9120
+ if (this.position >= this.input.length) {
9121
+ throw new SignatureValidationError(
9122
+ 'Incomplete signature: No output fields specified after "->"',
9123
+ this.position,
9124
+ this.getErrorContext(),
9125
+ 'Add at least one output field. Example: "-> responseText:string"'
9126
+ );
9127
+ }
9128
+ this.currentSection = "outputs";
9129
+ const outputs = this.parseFieldList(
9130
+ this.parseOutputField.bind(this),
9131
+ "output"
9132
+ );
9133
+ this.skipWhitespace();
9134
+ if (this.position < this.input.length) {
9135
+ const remaining = this.input.slice(this.position);
9136
+ throw new SignatureValidationError(
9137
+ `Unexpected content after signature: "${remaining}"`,
9138
+ this.position,
9139
+ this.getErrorContext(),
9140
+ "Remove any extra content after the output fields"
9141
+ );
9142
+ }
9143
+ this.validateParsedSignature({
9144
+ desc: optionalDesc?.trim(),
9145
+ inputs,
9146
+ outputs
9147
+ });
9148
+ return {
9149
+ desc: optionalDesc?.trim(),
9150
+ inputs,
9151
+ outputs
9152
+ };
9153
+ } catch (error) {
9154
+ if (error instanceof SignatureValidationError) {
9155
+ throw error;
9156
+ }
9157
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
9158
+ throw new SignatureValidationError(
9159
+ errorMessage,
9160
+ this.position,
9161
+ this.getErrorContext()
9162
+ );
9163
+ }
9164
+ }
9165
+ validateParsedSignature(signature) {
9166
+ const inputNames = /* @__PURE__ */ new Set();
9167
+ for (const field of signature.inputs) {
9168
+ if (inputNames.has(field.name)) {
9169
+ throw new SignatureValidationError(
9170
+ `Duplicate input field name: "${field.name}"`,
9171
+ 0,
9172
+ "",
9173
+ "Each field name must be unique within the signature"
9174
+ );
9175
+ }
9176
+ inputNames.add(field.name);
9177
+ }
9178
+ const outputNames = /* @__PURE__ */ new Set();
9179
+ for (const field of signature.outputs) {
9180
+ if (outputNames.has(field.name)) {
9181
+ throw new SignatureValidationError(
9182
+ `Duplicate output field name: "${field.name}"`,
9183
+ 0,
9184
+ "",
9185
+ "Each field name must be unique within the signature"
9186
+ );
9187
+ }
9188
+ outputNames.add(field.name);
9189
+ }
9190
+ for (const outputField of signature.outputs) {
9191
+ if (inputNames.has(outputField.name)) {
9192
+ throw new SignatureValidationError(
9193
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
9194
+ 0,
9195
+ "",
9196
+ "Use different names for input and output fields to avoid confusion"
9197
+ );
9198
+ }
9199
+ }
9200
+ if (signature.inputs.length === 0) {
9201
+ throw new SignatureValidationError(
9202
+ "Signature must have at least one input field",
9203
+ 0,
9204
+ "",
9205
+ 'Add an input field before "->". Example: "userInput:string -> ..."'
9206
+ );
9207
+ }
9208
+ if (signature.outputs.length === 0) {
9209
+ throw new SignatureValidationError(
9210
+ "Signature must have at least one output field",
9211
+ 0,
9212
+ "",
9213
+ 'Add an output field after "->". Example: "... -> responseText:string"'
9214
+ );
9215
+ }
9216
+ }
9217
+ getErrorContext() {
9218
+ const start = Math.max(0, this.position - 25);
9219
+ const end = Math.min(this.input.length, this.position + 25);
9220
+ const before = this.input.slice(start, this.position);
9221
+ const after = this.input.slice(this.position, end);
9222
+ const pointer = " ".repeat(before.length) + "^";
9223
+ const lines = [
9224
+ `Position ${this.position} in signature:`,
9225
+ `"${before}${after}"`,
9226
+ ` ${pointer}`
9227
+ ];
9228
+ return lines.join("\n");
9229
+ }
9230
+ parseFieldList(parseFieldFn, section) {
9231
+ const fields = [];
9232
+ this.skipWhitespace();
9233
+ if (this.position >= this.input.length) {
9234
+ throw new SignatureValidationError(
9235
+ `Empty ${section} section: Expected at least one field`,
8715
9236
  this.position,
8716
9237
  this.getErrorContext(),
8717
9238
  `Add a ${section} field. Example: ${section === "input" ? "userInput:string" : "responseText:string"}`
@@ -10914,6 +11435,15 @@ var AxGen = class extends AxProgramWithSignature {
10914
11435
  this.functions = parseFunctions(options.functions);
10915
11436
  }
10916
11437
  }
11438
+ getSignatureName() {
11439
+ return this.signature.getDescription() || "unknown_signature";
11440
+ }
11441
+ getMetricsInstruments() {
11442
+ return getOrCreateGenMetricsInstruments();
11443
+ }
11444
+ updateMeter(meter) {
11445
+ getOrCreateGenMetricsInstruments(meter);
11446
+ }
10917
11447
  createStates(n) {
10918
11448
  return Array.from({ length: n }, (_, index) => ({
10919
11449
  index,
@@ -11103,6 +11633,7 @@ var AxGen = class extends AxProgramWithSignature {
11103
11633
  );
11104
11634
  }
11105
11635
  let prompt;
11636
+ const promptRenderStart = performance.now();
11106
11637
  if (Array.isArray(values)) {
11107
11638
  validateAxMessageArray(values);
11108
11639
  prompt = this.promptTemplate.render(values, {
@@ -11116,7 +11647,27 @@ var AxGen = class extends AxProgramWithSignature {
11116
11647
  demos: this.demos
11117
11648
  });
11118
11649
  }
11650
+ const promptRenderDuration = performance.now() - promptRenderStart;
11651
+ const metricsInstruments = this.getMetricsInstruments();
11652
+ if (metricsInstruments) {
11653
+ recordPerformanceMetric(
11654
+ metricsInstruments,
11655
+ "prompt_render",
11656
+ promptRenderDuration,
11657
+ this.getSignatureName()
11658
+ );
11659
+ }
11660
+ const memoryUpdateStart = performance.now();
11119
11661
  mem.addRequest(prompt, options.sessionId);
11662
+ const memoryUpdateDuration = performance.now() - memoryUpdateStart;
11663
+ if (metricsInstruments) {
11664
+ recordPerformanceMetric(
11665
+ metricsInstruments,
11666
+ "memory_update",
11667
+ memoryUpdateDuration,
11668
+ this.getSignatureName()
11669
+ );
11670
+ }
11120
11671
  multiStepLoop: for (let n = 0; n < maxSteps; n++) {
11121
11672
  const firstStep = n === 0;
11122
11673
  for (let errCount = 0; errCount < maxRetries; errCount++) {
@@ -11145,8 +11696,48 @@ var AxGen = class extends AxProgramWithSignature {
11145
11696
  options?.sessionId
11146
11697
  );
11147
11698
  if (shouldContinue) {
11699
+ const metricsInstruments4 = this.getMetricsInstruments();
11700
+ if (metricsInstruments4) {
11701
+ recordMultiStepMetric(
11702
+ metricsInstruments4,
11703
+ n + 1,
11704
+ maxSteps,
11705
+ this.getSignatureName()
11706
+ );
11707
+ }
11148
11708
  continue multiStepLoop;
11149
11709
  }
11710
+ const metricsInstruments3 = this.getMetricsInstruments();
11711
+ if (metricsInstruments3) {
11712
+ recordMultiStepMetric(
11713
+ metricsInstruments3,
11714
+ n + 1,
11715
+ maxSteps,
11716
+ this.getSignatureName()
11717
+ );
11718
+ const allFunctionsExecuted = /* @__PURE__ */ new Set();
11719
+ states.forEach((state) => {
11720
+ state.functionsExecuted.forEach(
11721
+ (func) => allFunctionsExecuted.add(func)
11722
+ );
11723
+ });
11724
+ if (allFunctionsExecuted.size > 0) {
11725
+ recordFunctionCallingMetric(
11726
+ metricsInstruments3,
11727
+ true,
11728
+ allFunctionsExecuted.size,
11729
+ true,
11730
+ false,
11731
+ this.getSignatureName()
11732
+ );
11733
+ }
11734
+ recordFieldProcessingMetric(
11735
+ metricsInstruments3,
11736
+ this.fieldProcessors.length,
11737
+ this.streamingFieldProcessors.length,
11738
+ this.getSignatureName()
11739
+ );
11740
+ }
11150
11741
  this.getLogger(ai, options)?.("", { tags: ["responseEnd"] });
11151
11742
  return;
11152
11743
  } catch (e) {
@@ -11155,6 +11746,14 @@ var AxGen = class extends AxProgramWithSignature {
11155
11746
  if (e instanceof ValidationError) {
11156
11747
  errorFields = e.getFixingInstructions();
11157
11748
  err = e;
11749
+ const metricsInstruments3 = this.getMetricsInstruments();
11750
+ if (metricsInstruments3) {
11751
+ recordValidationErrorMetric(
11752
+ metricsInstruments3,
11753
+ "validation",
11754
+ this.getSignatureName()
11755
+ );
11756
+ }
11158
11757
  if (span) {
11159
11758
  span.addEvent("validation.error", {
11160
11759
  message: e.toString(),
@@ -11165,6 +11764,14 @@ var AxGen = class extends AxProgramWithSignature {
11165
11764
  const e1 = e;
11166
11765
  errorFields = e1.getFixingInstructions();
11167
11766
  err = e;
11767
+ const assertionMetricsInstruments = this.getMetricsInstruments();
11768
+ if (assertionMetricsInstruments) {
11769
+ recordValidationErrorMetric(
11770
+ assertionMetricsInstruments,
11771
+ "assertion",
11772
+ this.getSignatureName()
11773
+ );
11774
+ }
11168
11775
  if (span) {
11169
11776
  span.addEvent("assertion.error", {
11170
11777
  message: e1.toString(),
@@ -11186,12 +11793,31 @@ var AxGen = class extends AxProgramWithSignature {
11186
11793
  }
11187
11794
  }
11188
11795
  }
11796
+ const metricsInstruments2 = this.getMetricsInstruments();
11797
+ if (metricsInstruments2) {
11798
+ recordErrorCorrectionMetric(
11799
+ metricsInstruments2,
11800
+ maxRetries,
11801
+ false,
11802
+ // failed
11803
+ maxRetries,
11804
+ this.getSignatureName()
11805
+ );
11806
+ }
11189
11807
  throw enhanceError(
11190
11808
  new Error(`Unable to fix validation error: ${err?.toString()}`),
11191
11809
  ai,
11192
11810
  this.signature
11193
11811
  );
11194
11812
  }
11813
+ if (metricsInstruments) {
11814
+ recordMultiStepMetric(
11815
+ metricsInstruments,
11816
+ maxSteps,
11817
+ maxSteps,
11818
+ this.getSignatureName()
11819
+ );
11820
+ }
11195
11821
  throw enhanceError(
11196
11822
  new Error(`Max steps reached: ${maxSteps}`),
11197
11823
  ai,
@@ -11199,7 +11825,18 @@ var AxGen = class extends AxProgramWithSignature {
11199
11825
  );
11200
11826
  }
11201
11827
  async *_forward1(ai, values, options) {
11828
+ const stateCreationStart = performance.now();
11202
11829
  const states = this.createStates(options.sampleCount ?? 1);
11830
+ const stateCreationDuration = performance.now() - stateCreationStart;
11831
+ const metricsInstruments = this.getMetricsInstruments();
11832
+ if (metricsInstruments) {
11833
+ recordPerformanceMetric(
11834
+ metricsInstruments,
11835
+ "state_creation",
11836
+ stateCreationDuration,
11837
+ this.getSignatureName()
11838
+ );
11839
+ }
11203
11840
  const tracer = options?.tracer ?? this.options?.tracer ?? ai.getOptions().tracer;
11204
11841
  let functions = this.functions;
11205
11842
  if (options?.functions) {
@@ -11258,29 +11895,111 @@ var AxGen = class extends AxProgramWithSignature {
11258
11895
  }
11259
11896
  }
11260
11897
  async forward(ai, values, options) {
11261
- const generator = this._forward1(ai, values, options ?? {});
11262
- let buffer = [];
11263
- let currentVersion = 0;
11264
- for await (const delta of generator) {
11265
- if (delta.version !== currentVersion) {
11266
- buffer = [];
11898
+ const startTime = performance.now();
11899
+ const signatureName = this.getSignatureName();
11900
+ const isStreaming = options?.stream ?? false;
11901
+ let success = false;
11902
+ let errorCorrectionAttempts = 0;
11903
+ let functionsEnabled = false;
11904
+ let functionsExecuted = 0;
11905
+ let resultPickerUsed = false;
11906
+ try {
11907
+ const metricsInstruments = this.getMetricsInstruments();
11908
+ if (metricsInstruments) {
11909
+ recordSignatureComplexityMetrics(
11910
+ metricsInstruments,
11911
+ this.signature.getInputFields().length,
11912
+ this.signature.getOutputFields().length,
11913
+ this.examples?.length ?? 0,
11914
+ this.demos?.length ?? 0,
11915
+ signatureName
11916
+ );
11267
11917
  }
11268
- currentVersion = delta.version;
11269
- buffer = mergeDeltas(buffer, delta);
11270
- }
11271
- const selectedIndex = await selectFromSamples(
11272
- buffer,
11273
- {
11274
- resultPicker: options?.resultPicker
11275
- },
11276
- // Pass memory to enable function result selection
11277
- options?.mem,
11278
- options?.sessionId
11279
- );
11280
- const selectedResult = buffer[selectedIndex];
11281
- const result = selectedResult?.delta ?? {};
11282
- this.trace = { ...values, ...result };
11283
- return result;
11918
+ functionsEnabled = !!(options?.functions || this.functions);
11919
+ const generator = this._forward1(ai, values, options ?? {});
11920
+ let buffer = [];
11921
+ let currentVersion = 0;
11922
+ let deltasEmitted = 0;
11923
+ for await (const delta of generator) {
11924
+ if (delta.version !== currentVersion) {
11925
+ buffer = [];
11926
+ }
11927
+ currentVersion = delta.version;
11928
+ buffer = mergeDeltas(buffer, delta);
11929
+ deltasEmitted++;
11930
+ }
11931
+ errorCorrectionAttempts = currentVersion;
11932
+ const resultPickerStart = performance.now();
11933
+ resultPickerUsed = !!options?.resultPicker;
11934
+ const selectedIndex = await selectFromSamples(
11935
+ buffer,
11936
+ {
11937
+ resultPicker: options?.resultPicker
11938
+ },
11939
+ // Pass memory to enable function result selection
11940
+ options?.mem,
11941
+ options?.sessionId
11942
+ );
11943
+ const resultPickerLatency = performance.now() - resultPickerStart;
11944
+ const selectedResult = buffer[selectedIndex];
11945
+ const result = selectedResult?.delta ?? {};
11946
+ this.trace = { ...values, ...result };
11947
+ success = true;
11948
+ if (metricsInstruments) {
11949
+ recordSamplesMetric(
11950
+ metricsInstruments,
11951
+ buffer.length,
11952
+ resultPickerUsed,
11953
+ resultPickerUsed ? resultPickerLatency : void 0,
11954
+ signatureName
11955
+ );
11956
+ recordStreamingMetric(
11957
+ metricsInstruments,
11958
+ isStreaming,
11959
+ deltasEmitted,
11960
+ void 0,
11961
+ // finalization latency not applicable here
11962
+ signatureName
11963
+ );
11964
+ }
11965
+ return result;
11966
+ } catch (error) {
11967
+ success = false;
11968
+ throw error;
11969
+ } finally {
11970
+ const duration = performance.now() - startTime;
11971
+ const finalMetricsInstruments = this.getMetricsInstruments();
11972
+ if (finalMetricsInstruments) {
11973
+ recordGenerationMetric(
11974
+ finalMetricsInstruments,
11975
+ duration,
11976
+ success,
11977
+ signatureName,
11978
+ ai.getName(),
11979
+ options?.model
11980
+ );
11981
+ if (functionsEnabled) {
11982
+ recordFunctionCallingMetric(
11983
+ finalMetricsInstruments,
11984
+ functionsEnabled,
11985
+ functionsExecuted,
11986
+ functionsExecuted > 0,
11987
+ false,
11988
+ // function error correction tracking would need more complex logic
11989
+ signatureName
11990
+ );
11991
+ }
11992
+ if (errorCorrectionAttempts > 0) {
11993
+ recordErrorCorrectionMetric(
11994
+ finalMetricsInstruments,
11995
+ errorCorrectionAttempts,
11996
+ success,
11997
+ options?.maxRetries ?? 10,
11998
+ signatureName
11999
+ );
12000
+ }
12001
+ }
12002
+ }
11284
12003
  }
11285
12004
  async *streamingForward(ai, values, options) {
11286
12005
  if (!options?.resultPicker) {
@@ -11836,143 +12555,603 @@ var AxBalancer = class _AxBalancer {
11836
12555
  );
11837
12556
  return timeSinceLastFailure >= backoffMs;
11838
12557
  }
11839
- handleFailure() {
11840
- const failure = this.serviceFailures.get(this.currentService.getId());
11841
- const retries = (failure?.retries ?? 0) + 1;
11842
- this.serviceFailures.set(this.currentService.getId(), {
11843
- retries,
11844
- lastFailureTime: Date.now()
12558
+ handleFailure() {
12559
+ const failure = this.serviceFailures.get(this.currentService.getId());
12560
+ const retries = (failure?.retries ?? 0) + 1;
12561
+ this.serviceFailures.set(this.currentService.getId(), {
12562
+ retries,
12563
+ lastFailureTime: Date.now()
12564
+ });
12565
+ if (this.debug) {
12566
+ console.warn(
12567
+ `AxBalancer: Service ${this.currentService.getName()} failed (retry ${retries}/${this.maxRetries})`
12568
+ );
12569
+ }
12570
+ if (retries >= this.maxRetries) {
12571
+ const gotNextService = this.getNextService();
12572
+ if (this.debug) {
12573
+ console.warn(
12574
+ `AxBalancer: Switching to service ${this.currentService.getName()}`
12575
+ );
12576
+ }
12577
+ return gotNextService;
12578
+ }
12579
+ return true;
12580
+ }
12581
+ handleSuccess() {
12582
+ this.serviceFailures.delete(this.currentService.getId());
12583
+ }
12584
+ async chat(req, options) {
12585
+ this.reset();
12586
+ while (true) {
12587
+ if (!this.canRetryService()) {
12588
+ if (!this.getNextService()) {
12589
+ throw new Error("All services exhausted");
12590
+ }
12591
+ continue;
12592
+ }
12593
+ try {
12594
+ const response = await this.currentService.chat(req, options);
12595
+ this.handleSuccess();
12596
+ return response;
12597
+ } catch (e) {
12598
+ if (!(e instanceof AxAIServiceError)) {
12599
+ throw e;
12600
+ }
12601
+ switch (e.constructor) {
12602
+ case AxAIServiceAuthenticationError:
12603
+ throw e;
12604
+ case AxAIServiceStatusError:
12605
+ break;
12606
+ case AxAIServiceNetworkError:
12607
+ break;
12608
+ case AxAIServiceResponseError:
12609
+ break;
12610
+ case AxAIServiceStreamTerminatedError:
12611
+ break;
12612
+ case AxAIServiceTimeoutError:
12613
+ break;
12614
+ default:
12615
+ throw e;
12616
+ }
12617
+ if (!this.handleFailure()) {
12618
+ throw e;
12619
+ }
12620
+ }
12621
+ }
12622
+ }
12623
+ async embed(req, options) {
12624
+ this.reset();
12625
+ while (true) {
12626
+ if (!this.canRetryService()) {
12627
+ if (!this.getNextService()) {
12628
+ throw new Error("All services exhausted");
12629
+ }
12630
+ continue;
12631
+ }
12632
+ try {
12633
+ const response = await this.currentService.embed(req, options);
12634
+ this.handleSuccess();
12635
+ return response;
12636
+ } catch (e) {
12637
+ if (!this.handleFailure()) {
12638
+ throw e;
12639
+ }
12640
+ }
12641
+ }
12642
+ }
12643
+ setOptions(options) {
12644
+ this.currentService.setOptions(options);
12645
+ }
12646
+ getOptions() {
12647
+ return this.currentService.getOptions();
12648
+ }
12649
+ getLogger() {
12650
+ return this.currentService.getLogger();
12651
+ }
12652
+ };
12653
+ function validateModels2(services) {
12654
+ const serviceWithModel = services.find(
12655
+ (service) => service.getModelList() !== void 0
12656
+ );
12657
+ if (!serviceWithModel) {
12658
+ return;
12659
+ }
12660
+ const referenceModelList = serviceWithModel.getModelList();
12661
+ if (!referenceModelList) {
12662
+ throw new Error("No model list found in any service.");
12663
+ }
12664
+ const referenceKeys = new Set(referenceModelList.map((model) => model.key));
12665
+ for (let i = 0; i < services.length; i++) {
12666
+ const service = services[i];
12667
+ if (!service) {
12668
+ throw new Error(`Service at index ${i} is undefined`);
12669
+ }
12670
+ const modelList = service.getModelList();
12671
+ if (!modelList) {
12672
+ throw new Error(
12673
+ `Service at index ${i} (${service.getName()}) has no model list while another service does.`
12674
+ );
12675
+ }
12676
+ const serviceKeys = new Set(modelList.map((model) => model.key));
12677
+ for (const key of referenceKeys) {
12678
+ if (!serviceKeys.has(key)) {
12679
+ throw new Error(
12680
+ `Service at index ${i} (${service.getName()}) is missing model "${key}"`
12681
+ );
12682
+ }
12683
+ }
12684
+ for (const key of serviceKeys) {
12685
+ if (!referenceKeys.has(key)) {
12686
+ throw new Error(
12687
+ `Service at index ${i} (${service.getName()}) has extra model "${key}"`
12688
+ );
12689
+ }
12690
+ }
12691
+ }
12692
+ }
12693
+
12694
+ // dsp/optimizer.ts
12695
+ var axDefaultOptimizerMetricsConfig = {
12696
+ enabled: true,
12697
+ enabledCategories: [
12698
+ "optimization",
12699
+ "convergence",
12700
+ "resource_usage",
12701
+ "teacher_student",
12702
+ "checkpointing",
12703
+ "pareto"
12704
+ ],
12705
+ maxLabelLength: 100,
12706
+ samplingRate: 1
12707
+ };
12708
+ var globalOptimizerMetricsInstruments;
12709
+ var getOrCreateOptimizerMetricsInstruments = (meter) => {
12710
+ if (globalOptimizerMetricsInstruments) {
12711
+ return globalOptimizerMetricsInstruments;
12712
+ }
12713
+ if (meter) {
12714
+ globalOptimizerMetricsInstruments = createOptimizerMetricsInstruments(meter);
12715
+ return globalOptimizerMetricsInstruments;
12716
+ }
12717
+ return void 0;
12718
+ };
12719
+ var currentOptimizerMetricsConfig = axDefaultOptimizerMetricsConfig;
12720
+ var axUpdateOptimizerMetricsConfig = (config) => {
12721
+ currentOptimizerMetricsConfig = {
12722
+ ...currentOptimizerMetricsConfig,
12723
+ ...config
12724
+ };
12725
+ };
12726
+ var axGetOptimizerMetricsConfig = () => {
12727
+ return { ...currentOptimizerMetricsConfig };
12728
+ };
12729
+ var createOptimizerMetricsInstruments = (meter) => {
12730
+ return {
12731
+ // Optimization flow metrics
12732
+ optimizationLatencyHistogram: meter.createHistogram(
12733
+ "ax_optimizer_optimization_duration_ms",
12734
+ {
12735
+ description: "End-to-end duration of optimization runs",
12736
+ unit: "ms"
12737
+ }
12738
+ ),
12739
+ optimizationRequestsCounter: meter.createCounter(
12740
+ "ax_optimizer_optimization_requests_total",
12741
+ {
12742
+ description: "Total number of optimization requests"
12743
+ }
12744
+ ),
12745
+ optimizationErrorsCounter: meter.createCounter(
12746
+ "ax_optimizer_optimization_errors_total",
12747
+ {
12748
+ description: "Total number of failed optimizations"
12749
+ }
12750
+ ),
12751
+ // Convergence metrics
12752
+ convergenceRoundsHistogram: meter.createHistogram(
12753
+ "ax_optimizer_convergence_rounds",
12754
+ {
12755
+ description: "Number of rounds until convergence"
12756
+ }
12757
+ ),
12758
+ convergenceScoreGauge: meter.createGauge("ax_optimizer_convergence_score", {
12759
+ description: "Current best score during optimization"
12760
+ }),
12761
+ convergenceImprovementGauge: meter.createGauge(
12762
+ "ax_optimizer_convergence_improvement",
12763
+ {
12764
+ description: "Improvement in score from baseline"
12765
+ }
12766
+ ),
12767
+ stagnationRoundsGauge: meter.createGauge("ax_optimizer_stagnation_rounds", {
12768
+ description: "Number of rounds without improvement"
12769
+ }),
12770
+ earlyStoppingCounter: meter.createCounter(
12771
+ "ax_optimizer_early_stopping_total",
12772
+ {
12773
+ description: "Total number of early stopping events"
12774
+ }
12775
+ ),
12776
+ // Resource usage metrics
12777
+ tokenUsageCounter: meter.createCounter("ax_optimizer_token_usage_total", {
12778
+ description: "Total tokens used during optimization"
12779
+ }),
12780
+ costUsageCounter: meter.createCounter("ax_optimizer_cost_usage_total", {
12781
+ description: "Total cost incurred during optimization",
12782
+ unit: "$"
12783
+ }),
12784
+ memoryUsageGauge: meter.createGauge("ax_optimizer_memory_usage_bytes", {
12785
+ description: "Peak memory usage during optimization",
12786
+ unit: "By"
12787
+ }),
12788
+ optimizationDurationHistogram: meter.createHistogram(
12789
+ "ax_optimizer_duration_ms",
12790
+ {
12791
+ description: "Duration of optimization runs",
12792
+ unit: "ms"
12793
+ }
12794
+ ),
12795
+ // Teacher-student metrics
12796
+ teacherStudentUsageCounter: meter.createCounter(
12797
+ "ax_optimizer_teacher_student_usage_total",
12798
+ {
12799
+ description: "Total number of teacher-student interactions"
12800
+ }
12801
+ ),
12802
+ teacherStudentLatencyHistogram: meter.createHistogram(
12803
+ "ax_optimizer_teacher_student_latency_ms",
12804
+ {
12805
+ description: "Latency of teacher-student interactions",
12806
+ unit: "ms"
12807
+ }
12808
+ ),
12809
+ teacherStudentScoreImprovementGauge: meter.createGauge(
12810
+ "ax_optimizer_teacher_student_score_improvement",
12811
+ {
12812
+ description: "Score improvement from teacher-student interactions"
12813
+ }
12814
+ ),
12815
+ // Checkpointing metrics
12816
+ checkpointSaveCounter: meter.createCounter(
12817
+ "ax_optimizer_checkpoint_save_total",
12818
+ {
12819
+ description: "Total number of checkpoint saves"
12820
+ }
12821
+ ),
12822
+ checkpointLoadCounter: meter.createCounter(
12823
+ "ax_optimizer_checkpoint_load_total",
12824
+ {
12825
+ description: "Total number of checkpoint loads"
12826
+ }
12827
+ ),
12828
+ checkpointSaveLatencyHistogram: meter.createHistogram(
12829
+ "ax_optimizer_checkpoint_save_latency_ms",
12830
+ {
12831
+ description: "Latency of checkpoint save operations",
12832
+ unit: "ms"
12833
+ }
12834
+ ),
12835
+ checkpointLoadLatencyHistogram: meter.createHistogram(
12836
+ "ax_optimizer_checkpoint_load_latency_ms",
12837
+ {
12838
+ description: "Latency of checkpoint load operations",
12839
+ unit: "ms"
12840
+ }
12841
+ ),
12842
+ // Pareto optimization metrics
12843
+ paretoOptimizationsCounter: meter.createCounter(
12844
+ "ax_optimizer_pareto_optimizations_total",
12845
+ {
12846
+ description: "Total number of Pareto optimizations"
12847
+ }
12848
+ ),
12849
+ paretoFrontSizeHistogram: meter.createHistogram(
12850
+ "ax_optimizer_pareto_front_size",
12851
+ {
12852
+ description: "Size of Pareto frontier"
12853
+ }
12854
+ ),
12855
+ paretoHypervolumeGauge: meter.createGauge(
12856
+ "ax_optimizer_pareto_hypervolume",
12857
+ {
12858
+ description: "Hypervolume of Pareto frontier"
12859
+ }
12860
+ ),
12861
+ paretoSolutionsGeneratedHistogram: meter.createHistogram(
12862
+ "ax_optimizer_pareto_solutions_generated",
12863
+ {
12864
+ description: "Number of solutions generated for Pareto optimization"
12865
+ }
12866
+ ),
12867
+ // Program complexity metrics
12868
+ programInputFieldsGauge: meter.createGauge(
12869
+ "ax_optimizer_program_input_fields",
12870
+ {
12871
+ description: "Number of input fields in optimized program"
12872
+ }
12873
+ ),
12874
+ programOutputFieldsGauge: meter.createGauge(
12875
+ "ax_optimizer_program_output_fields",
12876
+ {
12877
+ description: "Number of output fields in optimized program"
12878
+ }
12879
+ ),
12880
+ examplesCountGauge: meter.createGauge("ax_optimizer_examples_count", {
12881
+ description: "Number of training examples used"
12882
+ }),
12883
+ validationSetSizeGauge: meter.createGauge(
12884
+ "ax_optimizer_validation_set_size",
12885
+ {
12886
+ description: "Size of validation set used"
12887
+ }
12888
+ ),
12889
+ // Performance metrics
12890
+ evaluationLatencyHistogram: meter.createHistogram(
12891
+ "ax_optimizer_evaluation_latency_ms",
12892
+ {
12893
+ description: "Latency of program evaluations",
12894
+ unit: "ms"
12895
+ }
12896
+ ),
12897
+ demoGenerationLatencyHistogram: meter.createHistogram(
12898
+ "ax_optimizer_demo_generation_latency_ms",
12899
+ {
12900
+ description: "Latency of demo generation",
12901
+ unit: "ms"
12902
+ }
12903
+ ),
12904
+ metricComputationLatencyHistogram: meter.createHistogram(
12905
+ "ax_optimizer_metric_computation_latency_ms",
12906
+ {
12907
+ description: "Latency of metric computation",
12908
+ unit: "ms"
12909
+ }
12910
+ ),
12911
+ // Configuration metrics
12912
+ optimizerTypeGauge: meter.createGauge("ax_optimizer_type", {
12913
+ description: "Type of optimizer being used"
12914
+ }),
12915
+ targetScoreGauge: meter.createGauge("ax_optimizer_target_score", {
12916
+ description: "Target score for optimization"
12917
+ }),
12918
+ maxRoundsGauge: meter.createGauge("ax_optimizer_max_rounds", {
12919
+ description: "Maximum rounds for optimization"
12920
+ })
12921
+ };
12922
+ };
12923
+ var sanitizeOptimizerLabels = (labels) => {
12924
+ const sanitized = {};
12925
+ for (const [key, value] of Object.entries(labels)) {
12926
+ if (value !== void 0 && value !== null) {
12927
+ const stringValue = String(value);
12928
+ const maxLength = currentOptimizerMetricsConfig.maxLabelLength;
12929
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
12930
+ }
12931
+ }
12932
+ return sanitized;
12933
+ };
12934
+ var recordOptimizationMetric = (instruments, duration, success, optimizerType, programSignature) => {
12935
+ try {
12936
+ const labels = sanitizeOptimizerLabels({
12937
+ success: success.toString(),
12938
+ optimizer_type: optimizerType,
12939
+ ...programSignature ? { program_signature: programSignature } : {}
12940
+ });
12941
+ if (instruments.optimizationLatencyHistogram) {
12942
+ instruments.optimizationLatencyHistogram.record(duration, labels);
12943
+ }
12944
+ if (instruments.optimizationRequestsCounter) {
12945
+ instruments.optimizationRequestsCounter.add(1, labels);
12946
+ }
12947
+ if (!success && instruments.optimizationErrorsCounter) {
12948
+ instruments.optimizationErrorsCounter.add(1, labels);
12949
+ }
12950
+ } catch (error) {
12951
+ console.warn("Failed to record optimization metric:", error);
12952
+ }
12953
+ };
12954
+ var recordConvergenceMetric = (instruments, rounds, currentScore, improvement, stagnationRounds, optimizerType) => {
12955
+ try {
12956
+ const labels = sanitizeOptimizerLabels({
12957
+ optimizer_type: optimizerType
12958
+ });
12959
+ if (instruments.convergenceRoundsHistogram) {
12960
+ instruments.convergenceRoundsHistogram.record(rounds, labels);
12961
+ }
12962
+ if (instruments.convergenceScoreGauge) {
12963
+ instruments.convergenceScoreGauge.record(currentScore, labels);
12964
+ }
12965
+ if (instruments.convergenceImprovementGauge) {
12966
+ instruments.convergenceImprovementGauge.record(improvement, labels);
12967
+ }
12968
+ if (instruments.stagnationRoundsGauge) {
12969
+ instruments.stagnationRoundsGauge.record(stagnationRounds, labels);
12970
+ }
12971
+ } catch (error) {
12972
+ console.warn("Failed to record convergence metric:", error);
12973
+ }
12974
+ };
12975
+ var recordEarlyStoppingMetric = (instruments, reason, optimizerType) => {
12976
+ try {
12977
+ const labels = sanitizeOptimizerLabels({
12978
+ reason,
12979
+ optimizer_type: optimizerType
11845
12980
  });
11846
- if (this.debug) {
11847
- console.warn(
11848
- `AxBalancer: Service ${this.currentService.getName()} failed (retry ${retries}/${this.maxRetries})`
11849
- );
12981
+ if (instruments.earlyStoppingCounter) {
12982
+ instruments.earlyStoppingCounter.add(1, labels);
11850
12983
  }
11851
- if (retries >= this.maxRetries) {
11852
- const gotNextService = this.getNextService();
11853
- if (this.debug) {
11854
- console.warn(
11855
- `AxBalancer: Switching to service ${this.currentService.getName()}`
11856
- );
11857
- }
11858
- return gotNextService;
12984
+ } catch (error) {
12985
+ console.warn("Failed to record early stopping metric:", error);
12986
+ }
12987
+ };
12988
+ var recordResourceUsageMetric = (instruments, tokensUsed, costIncurred, optimizerType, memoryUsage) => {
12989
+ try {
12990
+ const labels = sanitizeOptimizerLabels({
12991
+ optimizer_type: optimizerType
12992
+ });
12993
+ if (instruments.tokenUsageCounter) {
12994
+ instruments.tokenUsageCounter.add(tokensUsed, labels);
11859
12995
  }
11860
- return true;
12996
+ if (instruments.costUsageCounter) {
12997
+ instruments.costUsageCounter.add(costIncurred, labels);
12998
+ }
12999
+ if (memoryUsage !== void 0 && instruments.memoryUsageGauge) {
13000
+ instruments.memoryUsageGauge.record(memoryUsage, labels);
13001
+ }
13002
+ } catch (error) {
13003
+ console.warn("Failed to record resource usage metric:", error);
11861
13004
  }
11862
- handleSuccess() {
11863
- this.serviceFailures.delete(this.currentService.getId());
13005
+ };
13006
+ var recordOptimizationDurationMetric = (instruments, duration, optimizerType) => {
13007
+ try {
13008
+ const labels = sanitizeOptimizerLabels({
13009
+ optimizer_type: optimizerType
13010
+ });
13011
+ if (instruments.optimizationDurationHistogram) {
13012
+ instruments.optimizationDurationHistogram.record(duration, labels);
13013
+ }
13014
+ } catch (error) {
13015
+ console.warn("Failed to record optimization duration metric:", error);
11864
13016
  }
11865
- async chat(req, options) {
11866
- this.reset();
11867
- while (true) {
11868
- if (!this.canRetryService()) {
11869
- if (!this.getNextService()) {
11870
- throw new Error("All services exhausted");
11871
- }
11872
- continue;
11873
- }
11874
- try {
11875
- const response = await this.currentService.chat(req, options);
11876
- this.handleSuccess();
11877
- return response;
11878
- } catch (e) {
11879
- if (!(e instanceof AxAIServiceError)) {
11880
- throw e;
11881
- }
11882
- switch (e.constructor) {
11883
- case AxAIServiceAuthenticationError:
11884
- throw e;
11885
- case AxAIServiceStatusError:
11886
- break;
11887
- case AxAIServiceNetworkError:
11888
- break;
11889
- case AxAIServiceResponseError:
11890
- break;
11891
- case AxAIServiceStreamTerminatedError:
11892
- break;
11893
- case AxAIServiceTimeoutError:
11894
- break;
11895
- default:
11896
- throw e;
11897
- }
11898
- if (!this.handleFailure()) {
11899
- throw e;
11900
- }
11901
- }
13017
+ };
13018
+ var recordTeacherStudentMetric = (instruments, latency, scoreImprovement, optimizerType) => {
13019
+ try {
13020
+ const labels = sanitizeOptimizerLabels({
13021
+ optimizer_type: optimizerType
13022
+ });
13023
+ if (instruments.teacherStudentUsageCounter) {
13024
+ instruments.teacherStudentUsageCounter.add(1, labels);
13025
+ }
13026
+ if (instruments.teacherStudentLatencyHistogram) {
13027
+ instruments.teacherStudentLatencyHistogram.record(latency, labels);
13028
+ }
13029
+ if (instruments.teacherStudentScoreImprovementGauge) {
13030
+ instruments.teacherStudentScoreImprovementGauge.record(
13031
+ scoreImprovement,
13032
+ labels
13033
+ );
11902
13034
  }
13035
+ } catch (error) {
13036
+ console.warn("Failed to record teacher-student metric:", error);
11903
13037
  }
11904
- async embed(req, options) {
11905
- this.reset();
11906
- while (true) {
11907
- if (!this.canRetryService()) {
11908
- if (!this.getNextService()) {
11909
- throw new Error("All services exhausted");
11910
- }
11911
- continue;
13038
+ };
13039
+ var recordCheckpointMetric = (instruments, operation, latency, success, optimizerType) => {
13040
+ try {
13041
+ const labels = sanitizeOptimizerLabels({
13042
+ operation,
13043
+ success: success.toString(),
13044
+ optimizer_type: optimizerType
13045
+ });
13046
+ if (operation === "save") {
13047
+ if (instruments.checkpointSaveCounter) {
13048
+ instruments.checkpointSaveCounter.add(1, labels);
11912
13049
  }
11913
- try {
11914
- const response = await this.currentService.embed(req, options);
11915
- this.handleSuccess();
11916
- return response;
11917
- } catch (e) {
11918
- if (!this.handleFailure()) {
11919
- throw e;
11920
- }
13050
+ if (instruments.checkpointSaveLatencyHistogram) {
13051
+ instruments.checkpointSaveLatencyHistogram.record(latency, labels);
13052
+ }
13053
+ } else {
13054
+ if (instruments.checkpointLoadCounter) {
13055
+ instruments.checkpointLoadCounter.add(1, labels);
13056
+ }
13057
+ if (instruments.checkpointLoadLatencyHistogram) {
13058
+ instruments.checkpointLoadLatencyHistogram.record(latency, labels);
11921
13059
  }
11922
13060
  }
11923
- }
11924
- setOptions(options) {
11925
- this.currentService.setOptions(options);
11926
- }
11927
- getOptions() {
11928
- return this.currentService.getOptions();
11929
- }
11930
- getLogger() {
11931
- return this.currentService.getLogger();
13061
+ } catch (error) {
13062
+ console.warn("Failed to record checkpoint metric:", error);
11932
13063
  }
11933
13064
  };
11934
- function validateModels2(services) {
11935
- const serviceWithModel = services.find(
11936
- (service) => service.getModelList() !== void 0
11937
- );
11938
- if (!serviceWithModel) {
11939
- return;
13065
+ var recordParetoMetric = (instruments, frontSize, solutionsGenerated, optimizerType, hypervolume) => {
13066
+ try {
13067
+ const labels = sanitizeOptimizerLabels({
13068
+ optimizer_type: optimizerType
13069
+ });
13070
+ if (instruments.paretoOptimizationsCounter) {
13071
+ instruments.paretoOptimizationsCounter.add(1, labels);
13072
+ }
13073
+ if (instruments.paretoFrontSizeHistogram) {
13074
+ instruments.paretoFrontSizeHistogram.record(frontSize, labels);
13075
+ }
13076
+ if (hypervolume !== void 0 && instruments.paretoHypervolumeGauge) {
13077
+ instruments.paretoHypervolumeGauge.record(hypervolume, labels);
13078
+ }
13079
+ if (instruments.paretoSolutionsGeneratedHistogram) {
13080
+ instruments.paretoSolutionsGeneratedHistogram.record(
13081
+ solutionsGenerated,
13082
+ labels
13083
+ );
13084
+ }
13085
+ } catch (error) {
13086
+ console.warn("Failed to record Pareto metric:", error);
11940
13087
  }
11941
- const referenceModelList = serviceWithModel.getModelList();
11942
- if (!referenceModelList) {
11943
- throw new Error("No model list found in any service.");
13088
+ };
13089
+ var recordProgramComplexityMetric = (instruments, inputFields, outputFields, examplesCount, validationSetSize, optimizerType) => {
13090
+ try {
13091
+ const labels = sanitizeOptimizerLabels({
13092
+ optimizer_type: optimizerType
13093
+ });
13094
+ if (instruments.programInputFieldsGauge) {
13095
+ instruments.programInputFieldsGauge.record(inputFields, labels);
13096
+ }
13097
+ if (instruments.programOutputFieldsGauge) {
13098
+ instruments.programOutputFieldsGauge.record(outputFields, labels);
13099
+ }
13100
+ if (instruments.examplesCountGauge) {
13101
+ instruments.examplesCountGauge.record(examplesCount, labels);
13102
+ }
13103
+ if (instruments.validationSetSizeGauge) {
13104
+ instruments.validationSetSizeGauge.record(validationSetSize, labels);
13105
+ }
13106
+ } catch (error) {
13107
+ console.warn("Failed to record program complexity metric:", error);
11944
13108
  }
11945
- const referenceKeys = new Set(referenceModelList.map((model) => model.key));
11946
- for (let i = 0; i < services.length; i++) {
11947
- const service = services[i];
11948
- if (!service) {
11949
- throw new Error(`Service at index ${i} is undefined`);
13109
+ };
13110
+ var recordOptimizerPerformanceMetric = (instruments, metricType, duration, optimizerType) => {
13111
+ try {
13112
+ const labels = sanitizeOptimizerLabels({
13113
+ metric_type: metricType,
13114
+ optimizer_type: optimizerType
13115
+ });
13116
+ switch (metricType) {
13117
+ case "evaluation":
13118
+ if (instruments.evaluationLatencyHistogram) {
13119
+ instruments.evaluationLatencyHistogram.record(duration, labels);
13120
+ }
13121
+ break;
13122
+ case "demo_generation":
13123
+ if (instruments.demoGenerationLatencyHistogram) {
13124
+ instruments.demoGenerationLatencyHistogram.record(duration, labels);
13125
+ }
13126
+ break;
13127
+ case "metric_computation":
13128
+ if (instruments.metricComputationLatencyHistogram) {
13129
+ instruments.metricComputationLatencyHistogram.record(duration, labels);
13130
+ }
13131
+ break;
11950
13132
  }
11951
- const modelList = service.getModelList();
11952
- if (!modelList) {
11953
- throw new Error(
11954
- `Service at index ${i} (${service.getName()}) has no model list while another service does.`
11955
- );
13133
+ } catch (error) {
13134
+ console.warn("Failed to record optimizer performance metric:", error);
13135
+ }
13136
+ };
13137
+ var recordOptimizerConfigurationMetric = (instruments, optimizerType, targetScore, maxRounds) => {
13138
+ try {
13139
+ const labels = sanitizeOptimizerLabels({
13140
+ optimizer_type: optimizerType
13141
+ });
13142
+ if (instruments.optimizerTypeGauge) {
13143
+ instruments.optimizerTypeGauge.record(1, labels);
11956
13144
  }
11957
- const serviceKeys = new Set(modelList.map((model) => model.key));
11958
- for (const key of referenceKeys) {
11959
- if (!serviceKeys.has(key)) {
11960
- throw new Error(
11961
- `Service at index ${i} (${service.getName()}) is missing model "${key}"`
11962
- );
11963
- }
13145
+ if (targetScore !== void 0 && instruments.targetScoreGauge) {
13146
+ instruments.targetScoreGauge.record(targetScore, labels);
11964
13147
  }
11965
- for (const key of serviceKeys) {
11966
- if (!referenceKeys.has(key)) {
11967
- throw new Error(
11968
- `Service at index ${i} (${service.getName()}) has extra model "${key}"`
11969
- );
11970
- }
13148
+ if (maxRounds !== void 0 && instruments.maxRoundsGauge) {
13149
+ instruments.maxRoundsGauge.record(maxRounds, labels);
11971
13150
  }
13151
+ } catch (error) {
13152
+ console.warn("Failed to record optimizer configuration metric:", error);
11972
13153
  }
11973
- }
11974
-
11975
- // dsp/optimizer.ts
13154
+ };
11976
13155
  var AxDefaultCostTracker = class {
11977
13156
  tokenUsage = {};
11978
13157
  totalTokens = 0;
@@ -12046,6 +13225,8 @@ var AxBaseOptimizer = class {
12046
13225
  configurationHistory = [];
12047
13226
  // Common optimization statistics
12048
13227
  stats;
13228
+ // Metrics instruments
13229
+ metricsInstruments;
12049
13230
  constructor(args) {
12050
13231
  if (args.examples.length === 0) {
12051
13232
  throw new Error("No examples found");
@@ -12069,6 +13250,9 @@ var AxBaseOptimizer = class {
12069
13250
  maxTokens: 1e6
12070
13251
  });
12071
13252
  this.costTracker = args.costTracker ?? costTracker;
13253
+ this.metricsInstruments = getOrCreateOptimizerMetricsInstruments(
13254
+ axGlobals.meter
13255
+ );
12072
13256
  this.stats = this.initializeStats();
12073
13257
  }
12074
13258
  /**
@@ -12140,6 +13324,7 @@ var AxBaseOptimizer = class {
12140
13324
  patienceExhausted: reason.includes("improvement"),
12141
13325
  reason
12142
13326
  };
13327
+ this.recordEarlyStoppingMetrics(reason, "unknown");
12143
13328
  if (this.onEarlyStop) {
12144
13329
  this.onEarlyStop(reason, this.stats);
12145
13330
  }
@@ -12283,6 +13468,12 @@ var AxBaseOptimizer = class {
12283
13468
  }
12284
13469
  this.updateResourceUsage(startTime);
12285
13470
  this.stats.convergenceInfo.converged = true;
13471
+ this.recordParetoMetrics(
13472
+ paretoFront.length,
13473
+ allSolutions.length,
13474
+ "base_optimizer",
13475
+ hypervolume
13476
+ );
12286
13477
  const bestScore = paretoFront.length > 0 ? Math.max(
12287
13478
  ...paretoFront.map((sol) => Math.max(...Object.values(sol.scores)))
12288
13479
  ) : 0;
@@ -12589,23 +13780,36 @@ var AxBaseOptimizer = class {
12589
13780
  async saveCheckpoint(optimizerType, optimizerConfig, bestScore, bestConfiguration, optimizerState = {}, options) {
12590
13781
  const saveFn = options?.overrideCheckpointSave || this.checkpointSave;
12591
13782
  if (!saveFn) return void 0;
12592
- const checkpoint = {
12593
- version: "1.0.0",
12594
- timestamp: Date.now(),
12595
- optimizerType,
12596
- optimizerConfig,
12597
- currentRound: this.currentRound,
12598
- totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
12599
- bestScore,
12600
- bestConfiguration,
12601
- scoreHistory: [...this.scoreHistory],
12602
- configurationHistory: [...this.configurationHistory],
12603
- stats: { ...this.stats },
12604
- optimizerState,
12605
- examples: this.examples,
12606
- validationSet: this.validationSet
12607
- };
12608
- return await saveFn(checkpoint);
13783
+ const startTime = Date.now();
13784
+ let success = false;
13785
+ let checkpointId;
13786
+ try {
13787
+ const checkpoint = {
13788
+ version: "1.0.0",
13789
+ timestamp: Date.now(),
13790
+ optimizerType,
13791
+ optimizerConfig,
13792
+ currentRound: this.currentRound,
13793
+ totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
13794
+ bestScore,
13795
+ bestConfiguration,
13796
+ scoreHistory: [...this.scoreHistory],
13797
+ configurationHistory: [...this.configurationHistory],
13798
+ stats: { ...this.stats },
13799
+ optimizerState,
13800
+ examples: this.examples,
13801
+ validationSet: this.validationSet
13802
+ };
13803
+ checkpointId = await saveFn(checkpoint);
13804
+ success = true;
13805
+ } catch (error) {
13806
+ success = false;
13807
+ throw error;
13808
+ } finally {
13809
+ const latency = Date.now() - startTime;
13810
+ this.recordCheckpointMetrics("save", latency, success, optimizerType);
13811
+ }
13812
+ return checkpointId;
12609
13813
  }
12610
13814
  /**
12611
13815
  * Load optimization state from checkpoint
@@ -12613,7 +13817,20 @@ var AxBaseOptimizer = class {
12613
13817
  async loadCheckpoint(checkpointId, options) {
12614
13818
  const loadFn = options?.overrideCheckpointLoad || this.checkpointLoad;
12615
13819
  if (!loadFn) return null;
12616
- return await loadFn(checkpointId);
13820
+ const startTime = Date.now();
13821
+ let success = false;
13822
+ let checkpoint = null;
13823
+ try {
13824
+ checkpoint = await loadFn(checkpointId);
13825
+ success = checkpoint !== null;
13826
+ } catch (error) {
13827
+ success = false;
13828
+ throw error;
13829
+ } finally {
13830
+ const latency = Date.now() - startTime;
13831
+ this.recordCheckpointMetrics("load", latency, success, "unknown");
13832
+ }
13833
+ return checkpoint;
12617
13834
  }
12618
13835
  /**
12619
13836
  * Restore optimizer state from checkpoint
@@ -12690,6 +13907,128 @@ var AxBaseOptimizer = class {
12690
13907
  }
12691
13908
  return this.verbose ?? true;
12692
13909
  }
13910
+ /**
13911
+ * Record optimization start metrics
13912
+ */
13913
+ recordOptimizationStart(optimizerType, programSignature) {
13914
+ if (!this.metricsInstruments) return;
13915
+ if (programSignature) {
13916
+ const inputFields = (programSignature.match(/input:/g) || []).length;
13917
+ const outputFields = (programSignature.match(/output:/g) || []).length;
13918
+ recordProgramComplexityMetric(
13919
+ this.metricsInstruments,
13920
+ inputFields,
13921
+ outputFields,
13922
+ this.examples.length,
13923
+ this.getValidationSet().length,
13924
+ optimizerType
13925
+ );
13926
+ }
13927
+ recordOptimizerConfigurationMetric(
13928
+ this.metricsInstruments,
13929
+ optimizerType,
13930
+ this.targetScore,
13931
+ void 0
13932
+ // maxRounds would be set by concrete optimizers
13933
+ );
13934
+ }
13935
+ /**
13936
+ * Record optimization completion metrics
13937
+ */
13938
+ recordOptimizationComplete(duration, success, optimizerType, programSignature) {
13939
+ if (!this.metricsInstruments) return;
13940
+ recordOptimizationMetric(
13941
+ this.metricsInstruments,
13942
+ duration,
13943
+ success,
13944
+ optimizerType,
13945
+ programSignature
13946
+ );
13947
+ recordOptimizationDurationMetric(
13948
+ this.metricsInstruments,
13949
+ duration,
13950
+ optimizerType
13951
+ );
13952
+ const currentCost = this.costTracker?.getCurrentCost() ?? 0;
13953
+ const totalTokens = this.costTracker?.getTotalTokens() ?? 0;
13954
+ recordResourceUsageMetric(
13955
+ this.metricsInstruments,
13956
+ totalTokens,
13957
+ currentCost,
13958
+ optimizerType
13959
+ );
13960
+ }
13961
+ /**
13962
+ * Record convergence metrics
13963
+ */
13964
+ recordConvergenceMetrics(rounds, currentScore, improvement, stagnationRounds, optimizerType) {
13965
+ if (!this.metricsInstruments) return;
13966
+ recordConvergenceMetric(
13967
+ this.metricsInstruments,
13968
+ rounds,
13969
+ currentScore,
13970
+ improvement,
13971
+ stagnationRounds,
13972
+ optimizerType
13973
+ );
13974
+ }
13975
+ /**
13976
+ * Record early stopping metrics
13977
+ */
13978
+ recordEarlyStoppingMetrics(reason, optimizerType) {
13979
+ if (!this.metricsInstruments) return;
13980
+ recordEarlyStoppingMetric(this.metricsInstruments, reason, optimizerType);
13981
+ }
13982
+ /**
13983
+ * Record teacher-student interaction metrics
13984
+ */
13985
+ recordTeacherStudentMetrics(latency, scoreImprovement, optimizerType) {
13986
+ if (!this.metricsInstruments) return;
13987
+ recordTeacherStudentMetric(
13988
+ this.metricsInstruments,
13989
+ latency,
13990
+ scoreImprovement,
13991
+ optimizerType
13992
+ );
13993
+ }
13994
+ /**
13995
+ * Record checkpoint metrics
13996
+ */
13997
+ recordCheckpointMetrics(operation, latency, success, optimizerType) {
13998
+ if (!this.metricsInstruments) return;
13999
+ recordCheckpointMetric(
14000
+ this.metricsInstruments,
14001
+ operation,
14002
+ latency,
14003
+ success,
14004
+ optimizerType
14005
+ );
14006
+ }
14007
+ /**
14008
+ * Record Pareto optimization metrics
14009
+ */
14010
+ recordParetoMetrics(frontSize, solutionsGenerated, optimizerType, hypervolume) {
14011
+ if (!this.metricsInstruments) return;
14012
+ recordParetoMetric(
14013
+ this.metricsInstruments,
14014
+ frontSize,
14015
+ solutionsGenerated,
14016
+ optimizerType,
14017
+ hypervolume
14018
+ );
14019
+ }
14020
+ /**
14021
+ * Record performance metrics
14022
+ */
14023
+ recordPerformanceMetrics(metricType, duration, optimizerType) {
14024
+ if (!this.metricsInstruments) return;
14025
+ recordOptimizerPerformanceMetric(
14026
+ this.metricsInstruments,
14027
+ metricType,
14028
+ duration,
14029
+ optimizerType
14030
+ );
14031
+ }
12693
14032
  };
12694
14033
 
12695
14034
  // db/base.ts
@@ -18231,10 +19570,15 @@ export {
18231
19570
  axAITogetherDefaultConfig,
18232
19571
  axBaseAIDefaultConfig,
18233
19572
  axBaseAIDefaultCreativeConfig,
19573
+ axCheckMetricsHealth,
18234
19574
  axCreateDefaultLogger,
18235
19575
  axCreateDefaultTextLogger,
18236
19576
  axCreateOptimizerLogger,
19577
+ axDefaultMetricsConfig,
18237
19578
  axDefaultOptimizerLogger,
19579
+ axDefaultOptimizerMetricsConfig,
19580
+ axGetMetricsConfig,
19581
+ axGetOptimizerMetricsConfig,
18238
19582
  axGlobals,
18239
19583
  axModelInfoAnthropic,
18240
19584
  axModelInfoCohere,
@@ -18250,6 +19594,8 @@ export {
18250
19594
  axModelInfoTogether,
18251
19595
  axSpanAttributes,
18252
19596
  axSpanEvents,
19597
+ axUpdateMetricsConfig,
19598
+ axUpdateOptimizerMetricsConfig,
18253
19599
  axValidateChatRequestMessage,
18254
19600
  axValidateChatResponseResult,
18255
19601
  f,