@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.cjs CHANGED
@@ -162,10 +162,15 @@ __export(index_exports, {
162
162
  axAITogetherDefaultConfig: () => axAITogetherDefaultConfig,
163
163
  axBaseAIDefaultConfig: () => axBaseAIDefaultConfig,
164
164
  axBaseAIDefaultCreativeConfig: () => axBaseAIDefaultCreativeConfig,
165
+ axCheckMetricsHealth: () => axCheckMetricsHealth,
165
166
  axCreateDefaultLogger: () => axCreateDefaultLogger,
166
167
  axCreateDefaultTextLogger: () => axCreateDefaultTextLogger,
167
168
  axCreateOptimizerLogger: () => axCreateOptimizerLogger,
169
+ axDefaultMetricsConfig: () => axDefaultMetricsConfig,
168
170
  axDefaultOptimizerLogger: () => axDefaultOptimizerLogger,
171
+ axDefaultOptimizerMetricsConfig: () => axDefaultOptimizerMetricsConfig,
172
+ axGetMetricsConfig: () => axGetMetricsConfig,
173
+ axGetOptimizerMetricsConfig: () => axGetOptimizerMetricsConfig,
169
174
  axGlobals: () => axGlobals,
170
175
  axModelInfoAnthropic: () => axModelInfoAnthropic,
171
176
  axModelInfoCohere: () => axModelInfoCohere,
@@ -181,6 +186,8 @@ __export(index_exports, {
181
186
  axModelInfoTogether: () => axModelInfoTogether,
182
187
  axSpanAttributes: () => axSpanAttributes,
183
188
  axSpanEvents: () => axSpanEvents,
189
+ axUpdateMetricsConfig: () => axUpdateMetricsConfig,
190
+ axUpdateOptimizerMetricsConfig: () => axUpdateOptimizerMetricsConfig,
184
191
  axValidateChatRequestMessage: () => axValidateChatRequestMessage,
185
192
  axValidateChatResponseResult: () => axValidateChatResponseResult,
186
193
  f: () => f,
@@ -1214,6 +1221,27 @@ var logResponseDelta = (delta, logger = defaultLogger) => {
1214
1221
  };
1215
1222
 
1216
1223
  // ai/metrics.ts
1224
+ var sanitizeLabels = (labels) => {
1225
+ const sanitized = {};
1226
+ for (const [key, value] of Object.entries(labels)) {
1227
+ if (value !== void 0 && value !== null) {
1228
+ const stringValue = String(value);
1229
+ sanitized[key] = stringValue.length > 100 ? stringValue.substring(0, 100) : stringValue;
1230
+ }
1231
+ }
1232
+ return sanitized;
1233
+ };
1234
+ var globalAIMetricsInstruments;
1235
+ var getOrCreateAIMetricsInstruments = (meter) => {
1236
+ if (globalAIMetricsInstruments) {
1237
+ return globalAIMetricsInstruments;
1238
+ }
1239
+ if (meter) {
1240
+ globalAIMetricsInstruments = createMetricsInstruments(meter);
1241
+ return globalAIMetricsInstruments;
1242
+ }
1243
+ return void 0;
1244
+ };
1217
1245
  var createMetricsInstruments = (meter) => {
1218
1246
  return {
1219
1247
  latencyHistogram: meter.createHistogram("ax_llm_request_duration_ms", {
@@ -1314,12 +1342,17 @@ var createMetricsInstruments = (meter) => {
1314
1342
  };
1315
1343
  };
1316
1344
  var recordLatencyMetric = (instruments, type, duration, aiService, model) => {
1317
- if (instruments.latencyHistogram) {
1318
- instruments.latencyHistogram.record(duration, {
1319
- operation: type,
1320
- ai_service: aiService,
1321
- ...model ? { model } : {}
1322
- });
1345
+ try {
1346
+ if (instruments.latencyHistogram) {
1347
+ const labels = sanitizeLabels({
1348
+ operation: type,
1349
+ ai_service: aiService,
1350
+ ...model ? { model } : {}
1351
+ });
1352
+ instruments.latencyHistogram.record(duration, labels);
1353
+ }
1354
+ } catch (error) {
1355
+ console.warn("Failed to record latency metric:", error);
1323
1356
  }
1324
1357
  };
1325
1358
  var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99Latency, aiService, model) => {
@@ -1339,12 +1372,17 @@ var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99
1339
1372
  }
1340
1373
  };
1341
1374
  var recordErrorMetric = (instruments, type, aiService, model) => {
1342
- if (instruments.errorCounter) {
1343
- instruments.errorCounter.add(1, {
1344
- operation: type,
1345
- ai_service: aiService,
1346
- ...model ? { model } : {}
1347
- });
1375
+ try {
1376
+ if (instruments.errorCounter) {
1377
+ const labels = sanitizeLabels({
1378
+ operation: type,
1379
+ ai_service: aiService,
1380
+ ...model ? { model } : {}
1381
+ });
1382
+ instruments.errorCounter.add(1, labels);
1383
+ }
1384
+ } catch (error) {
1385
+ console.warn("Failed to record error metric:", error);
1348
1386
  }
1349
1387
  };
1350
1388
  var recordErrorRateMetric = (instruments, type, errorRate, aiService, model) => {
@@ -1367,21 +1405,25 @@ var recordRequestMetric = (instruments, type, aiService, model) => {
1367
1405
  }
1368
1406
  };
1369
1407
  var recordTokenMetric = (instruments, type, tokens, aiService, model) => {
1370
- const labels = {
1371
- ai_service: aiService,
1372
- ...model ? { model } : {}
1373
- };
1374
- if (instruments.tokenCounter) {
1375
- instruments.tokenCounter.add(tokens, {
1376
- token_type: type,
1377
- ...labels
1408
+ try {
1409
+ const labels = sanitizeLabels({
1410
+ ai_service: aiService,
1411
+ ...model ? { model } : {}
1378
1412
  });
1379
- }
1380
- if (type === "input" && instruments.inputTokenCounter) {
1381
- instruments.inputTokenCounter.add(tokens, labels);
1382
- }
1383
- if (type === "output" && instruments.outputTokenCounter) {
1384
- instruments.outputTokenCounter.add(tokens, labels);
1413
+ if (instruments.tokenCounter) {
1414
+ instruments.tokenCounter.add(tokens, {
1415
+ token_type: type,
1416
+ ...labels
1417
+ });
1418
+ }
1419
+ if (type === "input" && instruments.inputTokenCounter) {
1420
+ instruments.inputTokenCounter.add(tokens, labels);
1421
+ }
1422
+ if (type === "output" && instruments.outputTokenCounter) {
1423
+ instruments.outputTokenCounter.add(tokens, labels);
1424
+ }
1425
+ } catch (error) {
1426
+ console.warn("Failed to record token metric:", error);
1385
1427
  }
1386
1428
  };
1387
1429
  var recordStreamingRequestMetric = (instruments, type, isStreaming, aiService, model) => {
@@ -1540,7 +1582,6 @@ var AxBaseAI = class {
1540
1582
  throw new Error("No model defined");
1541
1583
  }
1542
1584
  this.setOptions(options);
1543
- this.initializeMetricsInstruments();
1544
1585
  if (models) {
1545
1586
  validateModels(models);
1546
1587
  }
@@ -1555,8 +1596,6 @@ var AxBaseAI = class {
1555
1596
  models;
1556
1597
  abortSignal;
1557
1598
  logger = defaultLogger2;
1558
- // OpenTelemetry metrics instruments
1559
- metricsInstruments;
1560
1599
  modelInfo;
1561
1600
  modelUsage;
1562
1601
  embedModelUsage;
@@ -1598,10 +1637,8 @@ var AxBaseAI = class {
1598
1637
  }
1599
1638
  }
1600
1639
  };
1601
- initializeMetricsInstruments() {
1602
- if (this.meter) {
1603
- this.metricsInstruments = createMetricsInstruments(this.meter);
1604
- }
1640
+ getMetricsInstruments() {
1641
+ return getOrCreateAIMetricsInstruments(this.meter);
1605
1642
  }
1606
1643
  setName(name) {
1607
1644
  this.name = name;
@@ -1625,7 +1662,6 @@ var AxBaseAI = class {
1625
1662
  this.excludeContentFromTrace = options.excludeContentFromTrace;
1626
1663
  this.abortSignal = options.abortSignal;
1627
1664
  this.logger = options.logger ?? defaultLogger2;
1628
- this.initializeMetricsInstruments();
1629
1665
  }
1630
1666
  getOptions() {
1631
1667
  return {
@@ -1698,17 +1734,12 @@ var AxBaseAI = class {
1698
1734
  metrics.mean = metrics.samples.reduce((a, b) => a + b, 0) / metrics.samples.length;
1699
1735
  metrics.p95 = this.calculatePercentile(metrics.samples, 95);
1700
1736
  metrics.p99 = this.calculatePercentile(metrics.samples, 99);
1701
- if (this.metricsInstruments) {
1737
+ const metricsInstruments = this.getMetricsInstruments();
1738
+ if (metricsInstruments) {
1702
1739
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1703
- recordLatencyMetric(
1704
- this.metricsInstruments,
1705
- type,
1706
- duration,
1707
- this.name,
1708
- model
1709
- );
1740
+ recordLatencyMetric(metricsInstruments, type, duration, this.name, model);
1710
1741
  recordLatencyStatsMetrics(
1711
- this.metricsInstruments,
1742
+ metricsInstruments,
1712
1743
  type,
1713
1744
  metrics.mean,
1714
1745
  metrics.p95,
@@ -1726,14 +1757,15 @@ var AxBaseAI = class {
1726
1757
  metrics.count++;
1727
1758
  }
1728
1759
  metrics.rate = metrics.count / metrics.total;
1729
- if (this.metricsInstruments) {
1760
+ const metricsInstruments = this.getMetricsInstruments();
1761
+ if (metricsInstruments) {
1730
1762
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1731
- recordRequestMetric(this.metricsInstruments, type, this.name, model);
1763
+ recordRequestMetric(metricsInstruments, type, this.name, model);
1732
1764
  if (isError) {
1733
- recordErrorMetric(this.metricsInstruments, type, this.name, model);
1765
+ recordErrorMetric(metricsInstruments, type, this.name, model);
1734
1766
  }
1735
1767
  recordErrorRateMetric(
1736
- this.metricsInstruments,
1768
+ metricsInstruments,
1737
1769
  type,
1738
1770
  metrics.rate,
1739
1771
  this.name,
@@ -1743,11 +1775,12 @@ var AxBaseAI = class {
1743
1775
  }
1744
1776
  // Method to record token usage metrics
1745
1777
  recordTokenUsage(modelUsage) {
1746
- if (this.metricsInstruments && modelUsage?.tokens) {
1778
+ const metricsInstruments = this.getMetricsInstruments();
1779
+ if (metricsInstruments && modelUsage?.tokens) {
1747
1780
  const { promptTokens, completionTokens, totalTokens, thoughtsTokens } = modelUsage.tokens;
1748
1781
  if (promptTokens) {
1749
1782
  recordTokenMetric(
1750
- this.metricsInstruments,
1783
+ metricsInstruments,
1751
1784
  "input",
1752
1785
  promptTokens,
1753
1786
  this.name,
@@ -1756,7 +1789,7 @@ var AxBaseAI = class {
1756
1789
  }
1757
1790
  if (completionTokens) {
1758
1791
  recordTokenMetric(
1759
- this.metricsInstruments,
1792
+ metricsInstruments,
1760
1793
  "output",
1761
1794
  completionTokens,
1762
1795
  this.name,
@@ -1765,7 +1798,7 @@ var AxBaseAI = class {
1765
1798
  }
1766
1799
  if (totalTokens) {
1767
1800
  recordTokenMetric(
1768
- this.metricsInstruments,
1801
+ metricsInstruments,
1769
1802
  "total",
1770
1803
  totalTokens,
1771
1804
  this.name,
@@ -1774,7 +1807,7 @@ var AxBaseAI = class {
1774
1807
  }
1775
1808
  if (thoughtsTokens) {
1776
1809
  recordTokenMetric(
1777
- this.metricsInstruments,
1810
+ metricsInstruments,
1778
1811
  "thoughts",
1779
1812
  thoughtsTokens,
1780
1813
  this.name,
@@ -1881,11 +1914,12 @@ var AxBaseAI = class {
1881
1914
  }
1882
1915
  // Helper method to record function call metrics
1883
1916
  recordFunctionCallMetrics(functionCalls, model) {
1884
- if (!this.metricsInstruments || !functionCalls) return;
1917
+ const metricsInstruments = this.getMetricsInstruments();
1918
+ if (!metricsInstruments || !functionCalls) return;
1885
1919
  for (const call of functionCalls) {
1886
1920
  if (call && typeof call === "object" && "function" in call && call.function && typeof call.function === "object" && "name" in call.function) {
1887
1921
  recordFunctionCallMetric(
1888
- this.metricsInstruments,
1922
+ metricsInstruments,
1889
1923
  call.function.name,
1890
1924
  void 0,
1891
1925
  // latency would need to be tracked separately
@@ -1897,26 +1931,29 @@ var AxBaseAI = class {
1897
1931
  }
1898
1932
  // Helper method to record timeout metrics
1899
1933
  recordTimeoutMetric(type) {
1900
- if (this.metricsInstruments) {
1934
+ const metricsInstruments = this.getMetricsInstruments();
1935
+ if (metricsInstruments) {
1901
1936
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1902
- recordTimeoutMetric(this.metricsInstruments, type, this.name, model);
1937
+ recordTimeoutMetric(metricsInstruments, type, this.name, model);
1903
1938
  }
1904
1939
  }
1905
1940
  // Helper method to record abort metrics
1906
1941
  recordAbortMetric(type) {
1907
- if (this.metricsInstruments) {
1942
+ const metricsInstruments = this.getMetricsInstruments();
1943
+ if (metricsInstruments) {
1908
1944
  const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1909
- recordAbortMetric(this.metricsInstruments, type, this.name, model);
1945
+ recordAbortMetric(metricsInstruments, type, this.name, model);
1910
1946
  }
1911
1947
  }
1912
1948
  // Comprehensive method to record all chat-related metrics
1913
1949
  recordChatMetrics(req, options, result) {
1914
- if (!this.metricsInstruments) return;
1950
+ const metricsInstruments = this.getMetricsInstruments();
1951
+ if (!metricsInstruments) return;
1915
1952
  const model = this.lastUsedChatModel;
1916
1953
  const modelConfig = this.lastUsedModelConfig;
1917
1954
  const isStreaming = modelConfig?.stream ?? false;
1918
1955
  recordStreamingRequestMetric(
1919
- this.metricsInstruments,
1956
+ metricsInstruments,
1920
1957
  "chat",
1921
1958
  isStreaming,
1922
1959
  this.name,
@@ -1924,21 +1961,16 @@ var AxBaseAI = class {
1924
1961
  );
1925
1962
  const { hasImages, hasAudio } = this.detectMultimodalContent(req);
1926
1963
  recordMultimodalRequestMetric(
1927
- this.metricsInstruments,
1964
+ metricsInstruments,
1928
1965
  hasImages,
1929
1966
  hasAudio,
1930
1967
  this.name,
1931
1968
  model
1932
1969
  );
1933
1970
  const promptLength = this.calculatePromptLength(req);
1934
- recordPromptLengthMetric(
1935
- this.metricsInstruments,
1936
- promptLength,
1937
- this.name,
1938
- model
1939
- );
1971
+ recordPromptLengthMetric(metricsInstruments, promptLength, this.name, model);
1940
1972
  recordModelConfigMetrics(
1941
- this.metricsInstruments,
1973
+ metricsInstruments,
1942
1974
  modelConfig?.temperature,
1943
1975
  modelConfig?.maxTokens,
1944
1976
  this.name,
@@ -1946,7 +1978,7 @@ var AxBaseAI = class {
1946
1978
  );
1947
1979
  if (options?.thinkingTokenBudget && this.modelUsage?.tokens?.thoughtsTokens) {
1948
1980
  recordThinkingBudgetUsageMetric(
1949
- this.metricsInstruments,
1981
+ metricsInstruments,
1950
1982
  this.modelUsage.tokens.thoughtsTokens,
1951
1983
  this.name,
1952
1984
  model
@@ -1954,7 +1986,7 @@ var AxBaseAI = class {
1954
1986
  }
1955
1987
  const requestSize = this.calculateRequestSize(req);
1956
1988
  recordRequestSizeMetric(
1957
- this.metricsInstruments,
1989
+ metricsInstruments,
1958
1990
  "chat",
1959
1991
  requestSize,
1960
1992
  this.name,
@@ -1964,7 +1996,7 @@ var AxBaseAI = class {
1964
1996
  const chatResponse = result;
1965
1997
  const responseSize = this.calculateResponseSize(chatResponse);
1966
1998
  recordResponseSizeMetric(
1967
- this.metricsInstruments,
1999
+ metricsInstruments,
1968
2000
  "chat",
1969
2001
  responseSize,
1970
2002
  this.name,
@@ -1986,7 +2018,7 @@ var AxBaseAI = class {
1986
2018
  );
1987
2019
  if (contextUsage > 0) {
1988
2020
  recordContextWindowUsageMetric(
1989
- this.metricsInstruments,
2021
+ metricsInstruments,
1990
2022
  contextUsage,
1991
2023
  this.name,
1992
2024
  model
@@ -1998,7 +2030,7 @@ var AxBaseAI = class {
1998
2030
  );
1999
2031
  if (estimatedCost > 0) {
2000
2032
  recordEstimatedCostMetric(
2001
- this.metricsInstruments,
2033
+ metricsInstruments,
2002
2034
  "chat",
2003
2035
  estimatedCost,
2004
2036
  this.name,
@@ -2009,11 +2041,12 @@ var AxBaseAI = class {
2009
2041
  }
2010
2042
  // Comprehensive method to record all embed-related metrics
2011
2043
  recordEmbedMetrics(req, result) {
2012
- if (!this.metricsInstruments) return;
2044
+ const metricsInstruments = this.getMetricsInstruments();
2045
+ if (!metricsInstruments) return;
2013
2046
  const model = this.lastUsedEmbedModel;
2014
2047
  const requestSize = this.calculateRequestSize(req);
2015
2048
  recordRequestSizeMetric(
2016
- this.metricsInstruments,
2049
+ metricsInstruments,
2017
2050
  "embed",
2018
2051
  requestSize,
2019
2052
  this.name,
@@ -2021,7 +2054,7 @@ var AxBaseAI = class {
2021
2054
  );
2022
2055
  const responseSize = this.calculateResponseSize(result);
2023
2056
  recordResponseSizeMetric(
2024
- this.metricsInstruments,
2057
+ metricsInstruments,
2025
2058
  "embed",
2026
2059
  responseSize,
2027
2060
  this.name,
@@ -2030,7 +2063,7 @@ var AxBaseAI = class {
2030
2063
  const estimatedCost = this.estimateCostByName(model, result.modelUsage);
2031
2064
  if (estimatedCost > 0) {
2032
2065
  recordEstimatedCostMetric(
2033
- this.metricsInstruments,
2066
+ metricsInstruments,
2034
2067
  "embed",
2035
2068
  estimatedCost,
2036
2069
  this.name,
@@ -8700,196 +8733,691 @@ function createFunctionConfig(functionList, definedFunctionCall, firstStep) {
8700
8733
  return { functions, functionCall };
8701
8734
  }
8702
8735
 
8703
- // dsp/processResponse.ts
8704
- var import_web5 = require("stream/web");
8705
-
8706
- // ai/util.ts
8707
- function mergeFunctionCalls(functionCalls, functionCallDeltas) {
8708
- for (const _fc of functionCallDeltas) {
8709
- const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
8710
- if (fc) {
8711
- if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
8712
- fc.function.name += _fc.function.name;
8713
- }
8714
- if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
8715
- fc.function.params += _fc.function.params;
8716
- }
8717
- if (typeof _fc.function.params == "object") {
8718
- fc.function.params = _fc.function.params;
8719
- }
8720
- } else {
8721
- functionCalls.push(_fc);
8722
- }
8736
+ // dsp/metrics.ts
8737
+ var axDefaultMetricsConfig = {
8738
+ enabled: true,
8739
+ enabledCategories: [
8740
+ "generation",
8741
+ "streaming",
8742
+ "functions",
8743
+ "errors",
8744
+ "performance"
8745
+ ],
8746
+ maxLabelLength: 100,
8747
+ samplingRate: 1
8748
+ };
8749
+ var globalGenMetricsInstruments;
8750
+ var getOrCreateGenMetricsInstruments = (meter) => {
8751
+ if (globalGenMetricsInstruments) {
8752
+ return globalGenMetricsInstruments;
8723
8753
  }
8724
- }
8725
-
8726
- // dsp/sig.ts
8727
- var import_crypto3 = require("crypto");
8728
-
8729
- // dsp/parser.ts
8730
- var SignatureValidationError = class extends Error {
8731
- constructor(message, position, context3, suggestion) {
8732
- super(message);
8733
- this.position = position;
8734
- this.context = context3;
8735
- this.suggestion = suggestion;
8736
- this.name = "SignatureValidationError";
8754
+ const activeMeter = meter ?? axGlobals.meter;
8755
+ if (activeMeter) {
8756
+ globalGenMetricsInstruments = createGenMetricsInstruments(activeMeter);
8757
+ return globalGenMetricsInstruments;
8737
8758
  }
8759
+ return void 0;
8738
8760
  };
8739
- var SignatureParser = class {
8740
- input;
8741
- position;
8742
- currentFieldName = null;
8743
- currentSection = "description";
8744
- constructor(input) {
8745
- this.input = input.trim();
8746
- this.position = 0;
8747
- if (!this.input) {
8748
- throw new SignatureValidationError(
8749
- "Empty signature provided",
8750
- 0,
8751
- "",
8752
- 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
8753
- );
8754
- }
8761
+ var axCheckMetricsHealth = () => {
8762
+ const issues = [];
8763
+ if (!axGlobals.meter) {
8764
+ issues.push("Global meter not initialized");
8755
8765
  }
8756
- parse() {
8757
- try {
8758
- this.skipWhitespace();
8759
- const optionalDesc = this.parseParsedString();
8760
- this.skipWhitespace();
8761
- this.currentSection = "inputs";
8762
- const inputs = this.parseFieldList(
8763
- this.parseInputField.bind(this),
8764
- "input"
8765
- );
8766
- this.skipWhitespace();
8767
- if (this.position >= this.input.length) {
8768
- throw new SignatureValidationError(
8769
- "Incomplete signature: Missing output section",
8770
- this.position,
8771
- this.getErrorContext(),
8772
- 'Add "->" followed by output fields. Example: "-> responseText:string"'
8773
- );
8766
+ if (!globalGenMetricsInstruments && axGlobals.meter) {
8767
+ issues.push("Metrics instruments not created despite available meter");
8768
+ }
8769
+ return {
8770
+ healthy: issues.length === 0,
8771
+ issues
8772
+ };
8773
+ };
8774
+ var createGenMetricsInstruments = (meter) => {
8775
+ return {
8776
+ // Generation flow metrics
8777
+ // Note: Histogram buckets should be configured at the exporter level
8778
+ // Recommended buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000] ms
8779
+ generationLatencyHistogram: meter.createHistogram(
8780
+ "ax_gen_generation_duration_ms",
8781
+ {
8782
+ description: "End-to-end duration of AxGen generation requests",
8783
+ unit: "ms"
8774
8784
  }
8775
- this.expectArrow();
8776
- this.skipWhitespace();
8777
- if (this.position >= this.input.length) {
8778
- throw new SignatureValidationError(
8779
- 'Incomplete signature: No output fields specified after "->"',
8780
- this.position,
8781
- this.getErrorContext(),
8782
- 'Add at least one output field. Example: "-> responseText:string"'
8783
- );
8785
+ ),
8786
+ generationRequestsCounter: meter.createCounter(
8787
+ "ax_gen_generation_requests_total",
8788
+ {
8789
+ description: "Total number of AxGen generation requests"
8784
8790
  }
8785
- this.currentSection = "outputs";
8786
- const outputs = this.parseFieldList(
8787
- this.parseOutputField.bind(this),
8788
- "output"
8789
- );
8790
- this.skipWhitespace();
8791
- if (this.position < this.input.length) {
8792
- const remaining = this.input.slice(this.position);
8793
- throw new SignatureValidationError(
8794
- `Unexpected content after signature: "${remaining}"`,
8795
- this.position,
8796
- this.getErrorContext(),
8797
- "Remove any extra content after the output fields"
8798
- );
8791
+ ),
8792
+ generationErrorsCounter: meter.createCounter(
8793
+ "ax_gen_generation_errors_total",
8794
+ {
8795
+ description: "Total number of failed AxGen generations"
8799
8796
  }
8800
- this.validateParsedSignature({
8801
- desc: optionalDesc?.trim(),
8802
- inputs,
8803
- outputs
8804
- });
8805
- return {
8806
- desc: optionalDesc?.trim(),
8807
- inputs,
8808
- outputs
8809
- };
8810
- } catch (error) {
8811
- if (error instanceof SignatureValidationError) {
8812
- throw error;
8797
+ ),
8798
+ // Multi-step flow metrics
8799
+ multiStepGenerationsCounter: meter.createCounter(
8800
+ "ax_gen_multistep_generations_total",
8801
+ {
8802
+ description: "Total number of generations that required multiple steps"
8813
8803
  }
8814
- const errorMessage = error instanceof Error ? error.message : "Unknown error";
8815
- throw new SignatureValidationError(
8816
- errorMessage,
8817
- this.position,
8818
- this.getErrorContext()
8819
- );
8820
- }
8821
- }
8822
- validateParsedSignature(signature) {
8823
- const inputNames = /* @__PURE__ */ new Set();
8824
- for (const field of signature.inputs) {
8825
- if (inputNames.has(field.name)) {
8826
- throw new SignatureValidationError(
8827
- `Duplicate input field name: "${field.name}"`,
8828
- 0,
8829
- "",
8830
- "Each field name must be unique within the signature"
8831
- );
8804
+ ),
8805
+ stepsPerGenerationHistogram: meter.createHistogram(
8806
+ "ax_gen_steps_per_generation",
8807
+ {
8808
+ description: "Number of steps taken per generation"
8832
8809
  }
8833
- inputNames.add(field.name);
8834
- }
8835
- const outputNames = /* @__PURE__ */ new Set();
8836
- for (const field of signature.outputs) {
8837
- if (outputNames.has(field.name)) {
8838
- throw new SignatureValidationError(
8839
- `Duplicate output field name: "${field.name}"`,
8840
- 0,
8841
- "",
8842
- "Each field name must be unique within the signature"
8843
- );
8810
+ ),
8811
+ maxStepsReachedCounter: meter.createCounter(
8812
+ "ax_gen_max_steps_reached_total",
8813
+ {
8814
+ description: "Total number of generations that hit max steps limit"
8844
8815
  }
8845
- outputNames.add(field.name);
8846
- }
8847
- for (const outputField of signature.outputs) {
8848
- if (inputNames.has(outputField.name)) {
8849
- throw new SignatureValidationError(
8850
- `Field name "${outputField.name}" appears in both inputs and outputs`,
8851
- 0,
8852
- "",
8853
- "Use different names for input and output fields to avoid confusion"
8854
- );
8816
+ ),
8817
+ // Error correction metrics
8818
+ validationErrorsCounter: meter.createCounter(
8819
+ "ax_gen_validation_errors_total",
8820
+ {
8821
+ description: "Total number of validation errors encountered"
8855
8822
  }
8856
- }
8857
- if (signature.inputs.length === 0) {
8858
- throw new SignatureValidationError(
8859
- "Signature must have at least one input field",
8860
- 0,
8861
- "",
8862
- 'Add an input field before "->". Example: "userInput:string -> ..."'
8863
- );
8864
- }
8865
- if (signature.outputs.length === 0) {
8866
- throw new SignatureValidationError(
8867
- "Signature must have at least one output field",
8868
- 0,
8869
- "",
8870
- 'Add an output field after "->". Example: "... -> responseText:string"'
8871
- );
8872
- }
8873
- }
8874
- getErrorContext() {
8875
- const start = Math.max(0, this.position - 25);
8876
- const end = Math.min(this.input.length, this.position + 25);
8877
- const before = this.input.slice(start, this.position);
8878
- const after = this.input.slice(this.position, end);
8879
- const pointer = " ".repeat(before.length) + "^";
8880
- const lines = [
8881
- `Position ${this.position} in signature:`,
8882
- `"${before}${after}"`,
8883
- ` ${pointer}`
8884
- ];
8885
- return lines.join("\n");
8886
- }
8887
- parseFieldList(parseFieldFn, section) {
8888
- const fields = [];
8889
- this.skipWhitespace();
8890
- if (this.position >= this.input.length) {
8891
- throw new SignatureValidationError(
8892
- `Empty ${section} section: Expected at least one field`,
8823
+ ),
8824
+ assertionErrorsCounter: meter.createCounter(
8825
+ "ax_gen_assertion_errors_total",
8826
+ {
8827
+ description: "Total number of assertion errors encountered"
8828
+ }
8829
+ ),
8830
+ errorCorrectionAttemptsHistogram: meter.createHistogram(
8831
+ "ax_gen_error_correction_attempts",
8832
+ {
8833
+ description: "Number of error correction attempts per generation"
8834
+ }
8835
+ ),
8836
+ errorCorrectionSuccessCounter: meter.createCounter(
8837
+ "ax_gen_error_correction_success_total",
8838
+ {
8839
+ description: "Total number of successful error corrections"
8840
+ }
8841
+ ),
8842
+ errorCorrectionFailureCounter: meter.createCounter(
8843
+ "ax_gen_error_correction_failure_total",
8844
+ {
8845
+ description: "Total number of failed error corrections"
8846
+ }
8847
+ ),
8848
+ maxRetriesReachedCounter: meter.createCounter(
8849
+ "ax_gen_max_retries_reached_total",
8850
+ {
8851
+ description: "Total number of generations that hit max retries limit"
8852
+ }
8853
+ ),
8854
+ // Function calling metrics
8855
+ functionsEnabledGenerationsCounter: meter.createCounter(
8856
+ "ax_gen_functions_enabled_generations_total",
8857
+ {
8858
+ description: "Total number of generations with functions enabled"
8859
+ }
8860
+ ),
8861
+ functionCallStepsCounter: meter.createCounter(
8862
+ "ax_gen_function_call_steps_total",
8863
+ {
8864
+ description: "Total number of steps that included function calls"
8865
+ }
8866
+ ),
8867
+ functionsExecutedPerGenerationHistogram: meter.createHistogram(
8868
+ "ax_gen_functions_executed_per_generation",
8869
+ {
8870
+ description: "Number of unique functions executed per generation"
8871
+ }
8872
+ ),
8873
+ functionErrorCorrectionCounter: meter.createCounter(
8874
+ "ax_gen_function_error_correction_total",
8875
+ {
8876
+ description: "Total number of function-related error corrections"
8877
+ }
8878
+ ),
8879
+ // Field processing metrics
8880
+ fieldProcessorsExecutedCounter: meter.createCounter(
8881
+ "ax_gen_field_processors_executed_total",
8882
+ {
8883
+ description: "Total number of field processors executed"
8884
+ }
8885
+ ),
8886
+ streamingFieldProcessorsExecutedCounter: meter.createCounter(
8887
+ "ax_gen_streaming_field_processors_executed_total",
8888
+ {
8889
+ description: "Total number of streaming field processors executed"
8890
+ }
8891
+ ),
8892
+ // Streaming specific metrics
8893
+ streamingGenerationsCounter: meter.createCounter(
8894
+ "ax_gen_streaming_generations_total",
8895
+ {
8896
+ description: "Total number of streaming generations"
8897
+ }
8898
+ ),
8899
+ streamingDeltasEmittedCounter: meter.createCounter(
8900
+ "ax_gen_streaming_deltas_emitted_total",
8901
+ {
8902
+ description: "Total number of streaming deltas emitted"
8903
+ }
8904
+ ),
8905
+ streamingFinalizationLatencyHistogram: meter.createHistogram(
8906
+ "ax_gen_streaming_finalization_duration_ms",
8907
+ {
8908
+ description: "Duration of streaming response finalization",
8909
+ unit: "ms"
8910
+ }
8911
+ ),
8912
+ // Memory and samples metrics
8913
+ samplesGeneratedHistogram: meter.createHistogram(
8914
+ "ax_gen_samples_generated",
8915
+ {
8916
+ description: "Number of samples generated per request"
8917
+ }
8918
+ ),
8919
+ resultPickerUsageCounter: meter.createCounter(
8920
+ "ax_gen_result_picker_usage_total",
8921
+ {
8922
+ description: "Total number of times result picker was used"
8923
+ }
8924
+ ),
8925
+ resultPickerLatencyHistogram: meter.createHistogram(
8926
+ "ax_gen_result_picker_duration_ms",
8927
+ {
8928
+ description: "Duration of result picker execution",
8929
+ unit: "ms"
8930
+ }
8931
+ ),
8932
+ // Signature complexity metrics
8933
+ inputFieldsGauge: meter.createGauge("ax_gen_input_fields", {
8934
+ description: "Number of input fields in signature"
8935
+ }),
8936
+ outputFieldsGauge: meter.createGauge("ax_gen_output_fields", {
8937
+ description: "Number of output fields in signature"
8938
+ }),
8939
+ examplesUsedGauge: meter.createGauge("ax_gen_examples_used", {
8940
+ description: "Number of examples used in generation"
8941
+ }),
8942
+ demosUsedGauge: meter.createGauge("ax_gen_demos_used", {
8943
+ description: "Number of demos used in generation"
8944
+ }),
8945
+ // Performance metrics
8946
+ promptRenderLatencyHistogram: meter.createHistogram(
8947
+ "ax_gen_prompt_render_duration_ms",
8948
+ {
8949
+ description: "Duration of prompt template rendering",
8950
+ unit: "ms"
8951
+ }
8952
+ ),
8953
+ extractionLatencyHistogram: meter.createHistogram(
8954
+ "ax_gen_extraction_duration_ms",
8955
+ {
8956
+ description: "Duration of value extraction from responses",
8957
+ unit: "ms"
8958
+ }
8959
+ ),
8960
+ assertionLatencyHistogram: meter.createHistogram(
8961
+ "ax_gen_assertion_duration_ms",
8962
+ {
8963
+ description: "Duration of assertion checking",
8964
+ unit: "ms"
8965
+ }
8966
+ ),
8967
+ // State management
8968
+ stateCreationLatencyHistogram: meter.createHistogram(
8969
+ "ax_gen_state_creation_duration_ms",
8970
+ {
8971
+ description: "Duration of state creation for multiple samples",
8972
+ unit: "ms"
8973
+ }
8974
+ ),
8975
+ memoryUpdateLatencyHistogram: meter.createHistogram(
8976
+ "ax_gen_memory_update_duration_ms",
8977
+ {
8978
+ description: "Duration of memory updates during generation",
8979
+ unit: "ms"
8980
+ }
8981
+ )
8982
+ };
8983
+ };
8984
+ var currentMetricsConfig = axDefaultMetricsConfig;
8985
+ var axUpdateMetricsConfig = (config) => {
8986
+ currentMetricsConfig = { ...currentMetricsConfig, ...config };
8987
+ };
8988
+ var axGetMetricsConfig = () => {
8989
+ return { ...currentMetricsConfig };
8990
+ };
8991
+ var sanitizeLabels2 = (labels) => {
8992
+ const sanitized = {};
8993
+ for (const [key, value] of Object.entries(labels)) {
8994
+ if (value !== void 0 && value !== null) {
8995
+ const stringValue = String(value);
8996
+ const maxLength = currentMetricsConfig.maxLabelLength;
8997
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
8998
+ }
8999
+ }
9000
+ return sanitized;
9001
+ };
9002
+ var recordGenerationMetric = (instruments, duration, success, signatureName, aiService, model) => {
9003
+ try {
9004
+ const labels = sanitizeLabels2({
9005
+ success: success.toString(),
9006
+ ...signatureName ? { signature: signatureName } : {},
9007
+ ...aiService ? { ai_service: aiService } : {},
9008
+ ...model ? { model } : {}
9009
+ });
9010
+ if (instruments.generationLatencyHistogram) {
9011
+ instruments.generationLatencyHistogram.record(duration, labels);
9012
+ }
9013
+ if (instruments.generationRequestsCounter) {
9014
+ instruments.generationRequestsCounter.add(1, labels);
9015
+ }
9016
+ if (!success && instruments.generationErrorsCounter) {
9017
+ instruments.generationErrorsCounter.add(1, labels);
9018
+ }
9019
+ } catch (error) {
9020
+ console.warn("Failed to record generation metric:", error);
9021
+ }
9022
+ };
9023
+ var recordMultiStepMetric = (instruments, stepsUsed, maxSteps, signatureName) => {
9024
+ try {
9025
+ const labels = sanitizeLabels2({
9026
+ ...signatureName ? { signature: signatureName } : {}
9027
+ });
9028
+ if (stepsUsed > 1 && instruments.multiStepGenerationsCounter) {
9029
+ instruments.multiStepGenerationsCounter.add(1, labels);
9030
+ }
9031
+ if (instruments.stepsPerGenerationHistogram) {
9032
+ instruments.stepsPerGenerationHistogram.record(stepsUsed, labels);
9033
+ }
9034
+ if (stepsUsed >= maxSteps && instruments.maxStepsReachedCounter) {
9035
+ instruments.maxStepsReachedCounter.add(1, labels);
9036
+ }
9037
+ } catch (error) {
9038
+ console.warn("Failed to record multi-step metric:", error);
9039
+ }
9040
+ };
9041
+ var recordValidationErrorMetric = (instruments, errorType, signatureName) => {
9042
+ try {
9043
+ const labels = sanitizeLabels2({
9044
+ error_type: errorType,
9045
+ ...signatureName ? { signature: signatureName } : {}
9046
+ });
9047
+ if (errorType === "validation" && instruments.validationErrorsCounter) {
9048
+ instruments.validationErrorsCounter.add(1, labels);
9049
+ }
9050
+ if (errorType === "assertion" && instruments.assertionErrorsCounter) {
9051
+ instruments.assertionErrorsCounter.add(1, labels);
9052
+ }
9053
+ } catch (error) {
9054
+ console.warn("Failed to record validation error metric:", error);
9055
+ }
9056
+ };
9057
+ var recordErrorCorrectionMetric = (instruments, attempts, success, maxRetries, signatureName) => {
9058
+ try {
9059
+ const labels = sanitizeLabels2({
9060
+ success: success.toString(),
9061
+ ...signatureName ? { signature: signatureName } : {}
9062
+ });
9063
+ if (instruments.errorCorrectionAttemptsHistogram) {
9064
+ instruments.errorCorrectionAttemptsHistogram.record(attempts, labels);
9065
+ }
9066
+ if (success && instruments.errorCorrectionSuccessCounter) {
9067
+ instruments.errorCorrectionSuccessCounter.add(1, labels);
9068
+ }
9069
+ if (!success) {
9070
+ if (instruments.errorCorrectionFailureCounter) {
9071
+ instruments.errorCorrectionFailureCounter.add(1, labels);
9072
+ }
9073
+ if (attempts >= maxRetries && instruments.maxRetriesReachedCounter) {
9074
+ instruments.maxRetriesReachedCounter.add(1, labels);
9075
+ }
9076
+ }
9077
+ } catch (error) {
9078
+ console.warn("Failed to record error correction metric:", error);
9079
+ }
9080
+ };
9081
+ var recordFunctionCallingMetric = (instruments, functionsEnabled, functionsExecuted, hadFunctionCalls, functionErrorCorrection = false, signatureName) => {
9082
+ try {
9083
+ const labels = sanitizeLabels2({
9084
+ functions_enabled: functionsEnabled.toString(),
9085
+ had_function_calls: hadFunctionCalls.toString(),
9086
+ ...signatureName ? { signature: signatureName } : {}
9087
+ });
9088
+ if (functionsEnabled && instruments.functionsEnabledGenerationsCounter) {
9089
+ instruments.functionsEnabledGenerationsCounter.add(1, labels);
9090
+ }
9091
+ if (hadFunctionCalls && instruments.functionCallStepsCounter) {
9092
+ instruments.functionCallStepsCounter.add(1, labels);
9093
+ }
9094
+ if (functionsExecuted > 0 && instruments.functionsExecutedPerGenerationHistogram) {
9095
+ instruments.functionsExecutedPerGenerationHistogram.record(
9096
+ functionsExecuted,
9097
+ labels
9098
+ );
9099
+ }
9100
+ if (functionErrorCorrection && instruments.functionErrorCorrectionCounter) {
9101
+ instruments.functionErrorCorrectionCounter.add(1, labels);
9102
+ }
9103
+ } catch (error) {
9104
+ console.warn("Failed to record function calling metric:", error);
9105
+ }
9106
+ };
9107
+ var recordFieldProcessingMetric = (instruments, fieldProcessorsExecuted, streamingFieldProcessorsExecuted, signatureName) => {
9108
+ try {
9109
+ const labels = sanitizeLabels2({
9110
+ ...signatureName ? { signature: signatureName } : {}
9111
+ });
9112
+ if (fieldProcessorsExecuted > 0 && instruments.fieldProcessorsExecutedCounter) {
9113
+ instruments.fieldProcessorsExecutedCounter.add(
9114
+ fieldProcessorsExecuted,
9115
+ labels
9116
+ );
9117
+ }
9118
+ if (streamingFieldProcessorsExecuted > 0 && instruments.streamingFieldProcessorsExecutedCounter) {
9119
+ instruments.streamingFieldProcessorsExecutedCounter.add(
9120
+ streamingFieldProcessorsExecuted,
9121
+ labels
9122
+ );
9123
+ }
9124
+ } catch (error) {
9125
+ console.warn("Failed to record field processing metric:", error);
9126
+ }
9127
+ };
9128
+ var recordStreamingMetric = (instruments, isStreaming, deltasEmitted, finalizationDuration, signatureName) => {
9129
+ try {
9130
+ const labels = sanitizeLabels2({
9131
+ is_streaming: isStreaming.toString(),
9132
+ ...signatureName ? { signature: signatureName } : {}
9133
+ });
9134
+ if (isStreaming && instruments.streamingGenerationsCounter) {
9135
+ instruments.streamingGenerationsCounter.add(1, labels);
9136
+ }
9137
+ if (deltasEmitted > 0 && instruments.streamingDeltasEmittedCounter) {
9138
+ instruments.streamingDeltasEmittedCounter.add(deltasEmitted, labels);
9139
+ }
9140
+ if (finalizationDuration && instruments.streamingFinalizationLatencyHistogram) {
9141
+ instruments.streamingFinalizationLatencyHistogram.record(
9142
+ finalizationDuration,
9143
+ labels
9144
+ );
9145
+ }
9146
+ } catch (error) {
9147
+ console.warn("Failed to record streaming metric:", error);
9148
+ }
9149
+ };
9150
+ var recordSamplesMetric = (instruments, samplesCount, resultPickerUsed, resultPickerLatency, signatureName) => {
9151
+ try {
9152
+ const labels = sanitizeLabels2({
9153
+ result_picker_used: resultPickerUsed.toString(),
9154
+ ...signatureName ? { signature: signatureName } : {}
9155
+ });
9156
+ if (instruments.samplesGeneratedHistogram) {
9157
+ instruments.samplesGeneratedHistogram.record(samplesCount, labels);
9158
+ }
9159
+ if (resultPickerUsed && instruments.resultPickerUsageCounter) {
9160
+ instruments.resultPickerUsageCounter.add(1, labels);
9161
+ }
9162
+ if (resultPickerLatency && instruments.resultPickerLatencyHistogram) {
9163
+ instruments.resultPickerLatencyHistogram.record(
9164
+ resultPickerLatency,
9165
+ labels
9166
+ );
9167
+ }
9168
+ } catch (error) {
9169
+ console.warn("Failed to record samples metric:", error);
9170
+ }
9171
+ };
9172
+ var recordSignatureComplexityMetrics = (instruments, inputFields, outputFields, examplesCount, demosCount, signatureName) => {
9173
+ try {
9174
+ const labels = sanitizeLabels2({
9175
+ ...signatureName ? { signature: signatureName } : {}
9176
+ });
9177
+ if (instruments.inputFieldsGauge) {
9178
+ instruments.inputFieldsGauge.record(inputFields, labels);
9179
+ }
9180
+ if (instruments.outputFieldsGauge) {
9181
+ instruments.outputFieldsGauge.record(outputFields, labels);
9182
+ }
9183
+ if (instruments.examplesUsedGauge) {
9184
+ instruments.examplesUsedGauge.record(examplesCount, labels);
9185
+ }
9186
+ if (instruments.demosUsedGauge) {
9187
+ instruments.demosUsedGauge.record(demosCount, labels);
9188
+ }
9189
+ } catch (error) {
9190
+ console.warn("Failed to record signature complexity metrics:", error);
9191
+ }
9192
+ };
9193
+ var recordPerformanceMetric = (instruments, metricType, duration, signatureName) => {
9194
+ try {
9195
+ const labels = sanitizeLabels2({
9196
+ metric_type: metricType,
9197
+ ...signatureName ? { signature: signatureName } : {}
9198
+ });
9199
+ switch (metricType) {
9200
+ case "prompt_render":
9201
+ if (instruments.promptRenderLatencyHistogram) {
9202
+ instruments.promptRenderLatencyHistogram.record(duration, labels);
9203
+ }
9204
+ break;
9205
+ case "extraction":
9206
+ if (instruments.extractionLatencyHistogram) {
9207
+ instruments.extractionLatencyHistogram.record(duration, labels);
9208
+ }
9209
+ break;
9210
+ case "assertion":
9211
+ if (instruments.assertionLatencyHistogram) {
9212
+ instruments.assertionLatencyHistogram.record(duration, labels);
9213
+ }
9214
+ break;
9215
+ case "state_creation":
9216
+ if (instruments.stateCreationLatencyHistogram) {
9217
+ instruments.stateCreationLatencyHistogram.record(duration, labels);
9218
+ }
9219
+ break;
9220
+ case "memory_update":
9221
+ if (instruments.memoryUpdateLatencyHistogram) {
9222
+ instruments.memoryUpdateLatencyHistogram.record(duration, labels);
9223
+ }
9224
+ break;
9225
+ }
9226
+ } catch (error) {
9227
+ console.warn("Failed to record performance metric:", error);
9228
+ }
9229
+ };
9230
+
9231
+ // dsp/processResponse.ts
9232
+ var import_web5 = require("stream/web");
9233
+
9234
+ // ai/util.ts
9235
+ function mergeFunctionCalls(functionCalls, functionCallDeltas) {
9236
+ for (const _fc of functionCallDeltas) {
9237
+ const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
9238
+ if (fc) {
9239
+ if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
9240
+ fc.function.name += _fc.function.name;
9241
+ }
9242
+ if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
9243
+ fc.function.params += _fc.function.params;
9244
+ }
9245
+ if (typeof _fc.function.params == "object") {
9246
+ fc.function.params = _fc.function.params;
9247
+ }
9248
+ } else {
9249
+ functionCalls.push(_fc);
9250
+ }
9251
+ }
9252
+ }
9253
+
9254
+ // dsp/sig.ts
9255
+ var import_crypto3 = require("crypto");
9256
+
9257
+ // dsp/parser.ts
9258
+ var SignatureValidationError = class extends Error {
9259
+ constructor(message, position, context3, suggestion) {
9260
+ super(message);
9261
+ this.position = position;
9262
+ this.context = context3;
9263
+ this.suggestion = suggestion;
9264
+ this.name = "SignatureValidationError";
9265
+ }
9266
+ };
9267
+ var SignatureParser = class {
9268
+ input;
9269
+ position;
9270
+ currentFieldName = null;
9271
+ currentSection = "description";
9272
+ constructor(input) {
9273
+ this.input = input.trim();
9274
+ this.position = 0;
9275
+ if (!this.input) {
9276
+ throw new SignatureValidationError(
9277
+ "Empty signature provided",
9278
+ 0,
9279
+ "",
9280
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
9281
+ );
9282
+ }
9283
+ }
9284
+ parse() {
9285
+ try {
9286
+ this.skipWhitespace();
9287
+ const optionalDesc = this.parseParsedString();
9288
+ this.skipWhitespace();
9289
+ this.currentSection = "inputs";
9290
+ const inputs = this.parseFieldList(
9291
+ this.parseInputField.bind(this),
9292
+ "input"
9293
+ );
9294
+ this.skipWhitespace();
9295
+ if (this.position >= this.input.length) {
9296
+ throw new SignatureValidationError(
9297
+ "Incomplete signature: Missing output section",
9298
+ this.position,
9299
+ this.getErrorContext(),
9300
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
9301
+ );
9302
+ }
9303
+ this.expectArrow();
9304
+ this.skipWhitespace();
9305
+ if (this.position >= this.input.length) {
9306
+ throw new SignatureValidationError(
9307
+ 'Incomplete signature: No output fields specified after "->"',
9308
+ this.position,
9309
+ this.getErrorContext(),
9310
+ 'Add at least one output field. Example: "-> responseText:string"'
9311
+ );
9312
+ }
9313
+ this.currentSection = "outputs";
9314
+ const outputs = this.parseFieldList(
9315
+ this.parseOutputField.bind(this),
9316
+ "output"
9317
+ );
9318
+ this.skipWhitespace();
9319
+ if (this.position < this.input.length) {
9320
+ const remaining = this.input.slice(this.position);
9321
+ throw new SignatureValidationError(
9322
+ `Unexpected content after signature: "${remaining}"`,
9323
+ this.position,
9324
+ this.getErrorContext(),
9325
+ "Remove any extra content after the output fields"
9326
+ );
9327
+ }
9328
+ this.validateParsedSignature({
9329
+ desc: optionalDesc?.trim(),
9330
+ inputs,
9331
+ outputs
9332
+ });
9333
+ return {
9334
+ desc: optionalDesc?.trim(),
9335
+ inputs,
9336
+ outputs
9337
+ };
9338
+ } catch (error) {
9339
+ if (error instanceof SignatureValidationError) {
9340
+ throw error;
9341
+ }
9342
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
9343
+ throw new SignatureValidationError(
9344
+ errorMessage,
9345
+ this.position,
9346
+ this.getErrorContext()
9347
+ );
9348
+ }
9349
+ }
9350
+ validateParsedSignature(signature) {
9351
+ const inputNames = /* @__PURE__ */ new Set();
9352
+ for (const field of signature.inputs) {
9353
+ if (inputNames.has(field.name)) {
9354
+ throw new SignatureValidationError(
9355
+ `Duplicate input field name: "${field.name}"`,
9356
+ 0,
9357
+ "",
9358
+ "Each field name must be unique within the signature"
9359
+ );
9360
+ }
9361
+ inputNames.add(field.name);
9362
+ }
9363
+ const outputNames = /* @__PURE__ */ new Set();
9364
+ for (const field of signature.outputs) {
9365
+ if (outputNames.has(field.name)) {
9366
+ throw new SignatureValidationError(
9367
+ `Duplicate output field name: "${field.name}"`,
9368
+ 0,
9369
+ "",
9370
+ "Each field name must be unique within the signature"
9371
+ );
9372
+ }
9373
+ outputNames.add(field.name);
9374
+ }
9375
+ for (const outputField of signature.outputs) {
9376
+ if (inputNames.has(outputField.name)) {
9377
+ throw new SignatureValidationError(
9378
+ `Field name "${outputField.name}" appears in both inputs and outputs`,
9379
+ 0,
9380
+ "",
9381
+ "Use different names for input and output fields to avoid confusion"
9382
+ );
9383
+ }
9384
+ }
9385
+ if (signature.inputs.length === 0) {
9386
+ throw new SignatureValidationError(
9387
+ "Signature must have at least one input field",
9388
+ 0,
9389
+ "",
9390
+ 'Add an input field before "->". Example: "userInput:string -> ..."'
9391
+ );
9392
+ }
9393
+ if (signature.outputs.length === 0) {
9394
+ throw new SignatureValidationError(
9395
+ "Signature must have at least one output field",
9396
+ 0,
9397
+ "",
9398
+ 'Add an output field after "->". Example: "... -> responseText:string"'
9399
+ );
9400
+ }
9401
+ }
9402
+ getErrorContext() {
9403
+ const start = Math.max(0, this.position - 25);
9404
+ const end = Math.min(this.input.length, this.position + 25);
9405
+ const before = this.input.slice(start, this.position);
9406
+ const after = this.input.slice(this.position, end);
9407
+ const pointer = " ".repeat(before.length) + "^";
9408
+ const lines = [
9409
+ `Position ${this.position} in signature:`,
9410
+ `"${before}${after}"`,
9411
+ ` ${pointer}`
9412
+ ];
9413
+ return lines.join("\n");
9414
+ }
9415
+ parseFieldList(parseFieldFn, section) {
9416
+ const fields = [];
9417
+ this.skipWhitespace();
9418
+ if (this.position >= this.input.length) {
9419
+ throw new SignatureValidationError(
9420
+ `Empty ${section} section: Expected at least one field`,
8893
9421
  this.position,
8894
9422
  this.getErrorContext(),
8895
9423
  `Add a ${section} field. Example: ${section === "input" ? "userInput:string" : "responseText:string"}`
@@ -11092,6 +11620,15 @@ var AxGen = class extends AxProgramWithSignature {
11092
11620
  this.functions = parseFunctions(options.functions);
11093
11621
  }
11094
11622
  }
11623
+ getSignatureName() {
11624
+ return this.signature.getDescription() || "unknown_signature";
11625
+ }
11626
+ getMetricsInstruments() {
11627
+ return getOrCreateGenMetricsInstruments();
11628
+ }
11629
+ updateMeter(meter) {
11630
+ getOrCreateGenMetricsInstruments(meter);
11631
+ }
11095
11632
  createStates(n) {
11096
11633
  return Array.from({ length: n }, (_, index) => ({
11097
11634
  index,
@@ -11281,6 +11818,7 @@ var AxGen = class extends AxProgramWithSignature {
11281
11818
  );
11282
11819
  }
11283
11820
  let prompt;
11821
+ const promptRenderStart = performance.now();
11284
11822
  if (Array.isArray(values)) {
11285
11823
  validateAxMessageArray(values);
11286
11824
  prompt = this.promptTemplate.render(values, {
@@ -11294,7 +11832,27 @@ var AxGen = class extends AxProgramWithSignature {
11294
11832
  demos: this.demos
11295
11833
  });
11296
11834
  }
11835
+ const promptRenderDuration = performance.now() - promptRenderStart;
11836
+ const metricsInstruments = this.getMetricsInstruments();
11837
+ if (metricsInstruments) {
11838
+ recordPerformanceMetric(
11839
+ metricsInstruments,
11840
+ "prompt_render",
11841
+ promptRenderDuration,
11842
+ this.getSignatureName()
11843
+ );
11844
+ }
11845
+ const memoryUpdateStart = performance.now();
11297
11846
  mem.addRequest(prompt, options.sessionId);
11847
+ const memoryUpdateDuration = performance.now() - memoryUpdateStart;
11848
+ if (metricsInstruments) {
11849
+ recordPerformanceMetric(
11850
+ metricsInstruments,
11851
+ "memory_update",
11852
+ memoryUpdateDuration,
11853
+ this.getSignatureName()
11854
+ );
11855
+ }
11298
11856
  multiStepLoop: for (let n = 0; n < maxSteps; n++) {
11299
11857
  const firstStep = n === 0;
11300
11858
  for (let errCount = 0; errCount < maxRetries; errCount++) {
@@ -11323,8 +11881,48 @@ var AxGen = class extends AxProgramWithSignature {
11323
11881
  options?.sessionId
11324
11882
  );
11325
11883
  if (shouldContinue) {
11884
+ const metricsInstruments4 = this.getMetricsInstruments();
11885
+ if (metricsInstruments4) {
11886
+ recordMultiStepMetric(
11887
+ metricsInstruments4,
11888
+ n + 1,
11889
+ maxSteps,
11890
+ this.getSignatureName()
11891
+ );
11892
+ }
11326
11893
  continue multiStepLoop;
11327
11894
  }
11895
+ const metricsInstruments3 = this.getMetricsInstruments();
11896
+ if (metricsInstruments3) {
11897
+ recordMultiStepMetric(
11898
+ metricsInstruments3,
11899
+ n + 1,
11900
+ maxSteps,
11901
+ this.getSignatureName()
11902
+ );
11903
+ const allFunctionsExecuted = /* @__PURE__ */ new Set();
11904
+ states.forEach((state) => {
11905
+ state.functionsExecuted.forEach(
11906
+ (func) => allFunctionsExecuted.add(func)
11907
+ );
11908
+ });
11909
+ if (allFunctionsExecuted.size > 0) {
11910
+ recordFunctionCallingMetric(
11911
+ metricsInstruments3,
11912
+ true,
11913
+ allFunctionsExecuted.size,
11914
+ true,
11915
+ false,
11916
+ this.getSignatureName()
11917
+ );
11918
+ }
11919
+ recordFieldProcessingMetric(
11920
+ metricsInstruments3,
11921
+ this.fieldProcessors.length,
11922
+ this.streamingFieldProcessors.length,
11923
+ this.getSignatureName()
11924
+ );
11925
+ }
11328
11926
  this.getLogger(ai, options)?.("", { tags: ["responseEnd"] });
11329
11927
  return;
11330
11928
  } catch (e) {
@@ -11333,6 +11931,14 @@ var AxGen = class extends AxProgramWithSignature {
11333
11931
  if (e instanceof ValidationError) {
11334
11932
  errorFields = e.getFixingInstructions();
11335
11933
  err = e;
11934
+ const metricsInstruments3 = this.getMetricsInstruments();
11935
+ if (metricsInstruments3) {
11936
+ recordValidationErrorMetric(
11937
+ metricsInstruments3,
11938
+ "validation",
11939
+ this.getSignatureName()
11940
+ );
11941
+ }
11336
11942
  if (span) {
11337
11943
  span.addEvent("validation.error", {
11338
11944
  message: e.toString(),
@@ -11343,6 +11949,14 @@ var AxGen = class extends AxProgramWithSignature {
11343
11949
  const e1 = e;
11344
11950
  errorFields = e1.getFixingInstructions();
11345
11951
  err = e;
11952
+ const assertionMetricsInstruments = this.getMetricsInstruments();
11953
+ if (assertionMetricsInstruments) {
11954
+ recordValidationErrorMetric(
11955
+ assertionMetricsInstruments,
11956
+ "assertion",
11957
+ this.getSignatureName()
11958
+ );
11959
+ }
11346
11960
  if (span) {
11347
11961
  span.addEvent("assertion.error", {
11348
11962
  message: e1.toString(),
@@ -11364,12 +11978,31 @@ var AxGen = class extends AxProgramWithSignature {
11364
11978
  }
11365
11979
  }
11366
11980
  }
11981
+ const metricsInstruments2 = this.getMetricsInstruments();
11982
+ if (metricsInstruments2) {
11983
+ recordErrorCorrectionMetric(
11984
+ metricsInstruments2,
11985
+ maxRetries,
11986
+ false,
11987
+ // failed
11988
+ maxRetries,
11989
+ this.getSignatureName()
11990
+ );
11991
+ }
11367
11992
  throw enhanceError(
11368
11993
  new Error(`Unable to fix validation error: ${err?.toString()}`),
11369
11994
  ai,
11370
11995
  this.signature
11371
11996
  );
11372
11997
  }
11998
+ if (metricsInstruments) {
11999
+ recordMultiStepMetric(
12000
+ metricsInstruments,
12001
+ maxSteps,
12002
+ maxSteps,
12003
+ this.getSignatureName()
12004
+ );
12005
+ }
11373
12006
  throw enhanceError(
11374
12007
  new Error(`Max steps reached: ${maxSteps}`),
11375
12008
  ai,
@@ -11377,7 +12010,18 @@ var AxGen = class extends AxProgramWithSignature {
11377
12010
  );
11378
12011
  }
11379
12012
  async *_forward1(ai, values, options) {
12013
+ const stateCreationStart = performance.now();
11380
12014
  const states = this.createStates(options.sampleCount ?? 1);
12015
+ const stateCreationDuration = performance.now() - stateCreationStart;
12016
+ const metricsInstruments = this.getMetricsInstruments();
12017
+ if (metricsInstruments) {
12018
+ recordPerformanceMetric(
12019
+ metricsInstruments,
12020
+ "state_creation",
12021
+ stateCreationDuration,
12022
+ this.getSignatureName()
12023
+ );
12024
+ }
11381
12025
  const tracer = options?.tracer ?? this.options?.tracer ?? ai.getOptions().tracer;
11382
12026
  let functions = this.functions;
11383
12027
  if (options?.functions) {
@@ -11436,29 +12080,111 @@ var AxGen = class extends AxProgramWithSignature {
11436
12080
  }
11437
12081
  }
11438
12082
  async forward(ai, values, options) {
11439
- const generator = this._forward1(ai, values, options ?? {});
11440
- let buffer = [];
11441
- let currentVersion = 0;
11442
- for await (const delta of generator) {
11443
- if (delta.version !== currentVersion) {
11444
- buffer = [];
12083
+ const startTime = performance.now();
12084
+ const signatureName = this.getSignatureName();
12085
+ const isStreaming = options?.stream ?? false;
12086
+ let success = false;
12087
+ let errorCorrectionAttempts = 0;
12088
+ let functionsEnabled = false;
12089
+ let functionsExecuted = 0;
12090
+ let resultPickerUsed = false;
12091
+ try {
12092
+ const metricsInstruments = this.getMetricsInstruments();
12093
+ if (metricsInstruments) {
12094
+ recordSignatureComplexityMetrics(
12095
+ metricsInstruments,
12096
+ this.signature.getInputFields().length,
12097
+ this.signature.getOutputFields().length,
12098
+ this.examples?.length ?? 0,
12099
+ this.demos?.length ?? 0,
12100
+ signatureName
12101
+ );
11445
12102
  }
11446
- currentVersion = delta.version;
11447
- buffer = mergeDeltas(buffer, delta);
11448
- }
11449
- const selectedIndex = await selectFromSamples(
11450
- buffer,
11451
- {
11452
- resultPicker: options?.resultPicker
11453
- },
11454
- // Pass memory to enable function result selection
11455
- options?.mem,
11456
- options?.sessionId
11457
- );
11458
- const selectedResult = buffer[selectedIndex];
11459
- const result = selectedResult?.delta ?? {};
11460
- this.trace = { ...values, ...result };
11461
- return result;
12103
+ functionsEnabled = !!(options?.functions || this.functions);
12104
+ const generator = this._forward1(ai, values, options ?? {});
12105
+ let buffer = [];
12106
+ let currentVersion = 0;
12107
+ let deltasEmitted = 0;
12108
+ for await (const delta of generator) {
12109
+ if (delta.version !== currentVersion) {
12110
+ buffer = [];
12111
+ }
12112
+ currentVersion = delta.version;
12113
+ buffer = mergeDeltas(buffer, delta);
12114
+ deltasEmitted++;
12115
+ }
12116
+ errorCorrectionAttempts = currentVersion;
12117
+ const resultPickerStart = performance.now();
12118
+ resultPickerUsed = !!options?.resultPicker;
12119
+ const selectedIndex = await selectFromSamples(
12120
+ buffer,
12121
+ {
12122
+ resultPicker: options?.resultPicker
12123
+ },
12124
+ // Pass memory to enable function result selection
12125
+ options?.mem,
12126
+ options?.sessionId
12127
+ );
12128
+ const resultPickerLatency = performance.now() - resultPickerStart;
12129
+ const selectedResult = buffer[selectedIndex];
12130
+ const result = selectedResult?.delta ?? {};
12131
+ this.trace = { ...values, ...result };
12132
+ success = true;
12133
+ if (metricsInstruments) {
12134
+ recordSamplesMetric(
12135
+ metricsInstruments,
12136
+ buffer.length,
12137
+ resultPickerUsed,
12138
+ resultPickerUsed ? resultPickerLatency : void 0,
12139
+ signatureName
12140
+ );
12141
+ recordStreamingMetric(
12142
+ metricsInstruments,
12143
+ isStreaming,
12144
+ deltasEmitted,
12145
+ void 0,
12146
+ // finalization latency not applicable here
12147
+ signatureName
12148
+ );
12149
+ }
12150
+ return result;
12151
+ } catch (error) {
12152
+ success = false;
12153
+ throw error;
12154
+ } finally {
12155
+ const duration = performance.now() - startTime;
12156
+ const finalMetricsInstruments = this.getMetricsInstruments();
12157
+ if (finalMetricsInstruments) {
12158
+ recordGenerationMetric(
12159
+ finalMetricsInstruments,
12160
+ duration,
12161
+ success,
12162
+ signatureName,
12163
+ ai.getName(),
12164
+ options?.model
12165
+ );
12166
+ if (functionsEnabled) {
12167
+ recordFunctionCallingMetric(
12168
+ finalMetricsInstruments,
12169
+ functionsEnabled,
12170
+ functionsExecuted,
12171
+ functionsExecuted > 0,
12172
+ false,
12173
+ // function error correction tracking would need more complex logic
12174
+ signatureName
12175
+ );
12176
+ }
12177
+ if (errorCorrectionAttempts > 0) {
12178
+ recordErrorCorrectionMetric(
12179
+ finalMetricsInstruments,
12180
+ errorCorrectionAttempts,
12181
+ success,
12182
+ options?.maxRetries ?? 10,
12183
+ signatureName
12184
+ );
12185
+ }
12186
+ }
12187
+ }
11462
12188
  }
11463
12189
  async *streamingForward(ai, values, options) {
11464
12190
  if (!options?.resultPicker) {
@@ -12014,143 +12740,603 @@ var AxBalancer = class _AxBalancer {
12014
12740
  );
12015
12741
  return timeSinceLastFailure >= backoffMs;
12016
12742
  }
12017
- handleFailure() {
12018
- const failure = this.serviceFailures.get(this.currentService.getId());
12019
- const retries = (failure?.retries ?? 0) + 1;
12020
- this.serviceFailures.set(this.currentService.getId(), {
12021
- retries,
12022
- lastFailureTime: Date.now()
12743
+ handleFailure() {
12744
+ const failure = this.serviceFailures.get(this.currentService.getId());
12745
+ const retries = (failure?.retries ?? 0) + 1;
12746
+ this.serviceFailures.set(this.currentService.getId(), {
12747
+ retries,
12748
+ lastFailureTime: Date.now()
12749
+ });
12750
+ if (this.debug) {
12751
+ console.warn(
12752
+ `AxBalancer: Service ${this.currentService.getName()} failed (retry ${retries}/${this.maxRetries})`
12753
+ );
12754
+ }
12755
+ if (retries >= this.maxRetries) {
12756
+ const gotNextService = this.getNextService();
12757
+ if (this.debug) {
12758
+ console.warn(
12759
+ `AxBalancer: Switching to service ${this.currentService.getName()}`
12760
+ );
12761
+ }
12762
+ return gotNextService;
12763
+ }
12764
+ return true;
12765
+ }
12766
+ handleSuccess() {
12767
+ this.serviceFailures.delete(this.currentService.getId());
12768
+ }
12769
+ async chat(req, options) {
12770
+ this.reset();
12771
+ while (true) {
12772
+ if (!this.canRetryService()) {
12773
+ if (!this.getNextService()) {
12774
+ throw new Error("All services exhausted");
12775
+ }
12776
+ continue;
12777
+ }
12778
+ try {
12779
+ const response = await this.currentService.chat(req, options);
12780
+ this.handleSuccess();
12781
+ return response;
12782
+ } catch (e) {
12783
+ if (!(e instanceof AxAIServiceError)) {
12784
+ throw e;
12785
+ }
12786
+ switch (e.constructor) {
12787
+ case AxAIServiceAuthenticationError:
12788
+ throw e;
12789
+ case AxAIServiceStatusError:
12790
+ break;
12791
+ case AxAIServiceNetworkError:
12792
+ break;
12793
+ case AxAIServiceResponseError:
12794
+ break;
12795
+ case AxAIServiceStreamTerminatedError:
12796
+ break;
12797
+ case AxAIServiceTimeoutError:
12798
+ break;
12799
+ default:
12800
+ throw e;
12801
+ }
12802
+ if (!this.handleFailure()) {
12803
+ throw e;
12804
+ }
12805
+ }
12806
+ }
12807
+ }
12808
+ async embed(req, options) {
12809
+ this.reset();
12810
+ while (true) {
12811
+ if (!this.canRetryService()) {
12812
+ if (!this.getNextService()) {
12813
+ throw new Error("All services exhausted");
12814
+ }
12815
+ continue;
12816
+ }
12817
+ try {
12818
+ const response = await this.currentService.embed(req, options);
12819
+ this.handleSuccess();
12820
+ return response;
12821
+ } catch (e) {
12822
+ if (!this.handleFailure()) {
12823
+ throw e;
12824
+ }
12825
+ }
12826
+ }
12827
+ }
12828
+ setOptions(options) {
12829
+ this.currentService.setOptions(options);
12830
+ }
12831
+ getOptions() {
12832
+ return this.currentService.getOptions();
12833
+ }
12834
+ getLogger() {
12835
+ return this.currentService.getLogger();
12836
+ }
12837
+ };
12838
+ function validateModels2(services) {
12839
+ const serviceWithModel = services.find(
12840
+ (service) => service.getModelList() !== void 0
12841
+ );
12842
+ if (!serviceWithModel) {
12843
+ return;
12844
+ }
12845
+ const referenceModelList = serviceWithModel.getModelList();
12846
+ if (!referenceModelList) {
12847
+ throw new Error("No model list found in any service.");
12848
+ }
12849
+ const referenceKeys = new Set(referenceModelList.map((model) => model.key));
12850
+ for (let i = 0; i < services.length; i++) {
12851
+ const service = services[i];
12852
+ if (!service) {
12853
+ throw new Error(`Service at index ${i} is undefined`);
12854
+ }
12855
+ const modelList = service.getModelList();
12856
+ if (!modelList) {
12857
+ throw new Error(
12858
+ `Service at index ${i} (${service.getName()}) has no model list while another service does.`
12859
+ );
12860
+ }
12861
+ const serviceKeys = new Set(modelList.map((model) => model.key));
12862
+ for (const key of referenceKeys) {
12863
+ if (!serviceKeys.has(key)) {
12864
+ throw new Error(
12865
+ `Service at index ${i} (${service.getName()}) is missing model "${key}"`
12866
+ );
12867
+ }
12868
+ }
12869
+ for (const key of serviceKeys) {
12870
+ if (!referenceKeys.has(key)) {
12871
+ throw new Error(
12872
+ `Service at index ${i} (${service.getName()}) has extra model "${key}"`
12873
+ );
12874
+ }
12875
+ }
12876
+ }
12877
+ }
12878
+
12879
+ // dsp/optimizer.ts
12880
+ var axDefaultOptimizerMetricsConfig = {
12881
+ enabled: true,
12882
+ enabledCategories: [
12883
+ "optimization",
12884
+ "convergence",
12885
+ "resource_usage",
12886
+ "teacher_student",
12887
+ "checkpointing",
12888
+ "pareto"
12889
+ ],
12890
+ maxLabelLength: 100,
12891
+ samplingRate: 1
12892
+ };
12893
+ var globalOptimizerMetricsInstruments;
12894
+ var getOrCreateOptimizerMetricsInstruments = (meter) => {
12895
+ if (globalOptimizerMetricsInstruments) {
12896
+ return globalOptimizerMetricsInstruments;
12897
+ }
12898
+ if (meter) {
12899
+ globalOptimizerMetricsInstruments = createOptimizerMetricsInstruments(meter);
12900
+ return globalOptimizerMetricsInstruments;
12901
+ }
12902
+ return void 0;
12903
+ };
12904
+ var currentOptimizerMetricsConfig = axDefaultOptimizerMetricsConfig;
12905
+ var axUpdateOptimizerMetricsConfig = (config) => {
12906
+ currentOptimizerMetricsConfig = {
12907
+ ...currentOptimizerMetricsConfig,
12908
+ ...config
12909
+ };
12910
+ };
12911
+ var axGetOptimizerMetricsConfig = () => {
12912
+ return { ...currentOptimizerMetricsConfig };
12913
+ };
12914
+ var createOptimizerMetricsInstruments = (meter) => {
12915
+ return {
12916
+ // Optimization flow metrics
12917
+ optimizationLatencyHistogram: meter.createHistogram(
12918
+ "ax_optimizer_optimization_duration_ms",
12919
+ {
12920
+ description: "End-to-end duration of optimization runs",
12921
+ unit: "ms"
12922
+ }
12923
+ ),
12924
+ optimizationRequestsCounter: meter.createCounter(
12925
+ "ax_optimizer_optimization_requests_total",
12926
+ {
12927
+ description: "Total number of optimization requests"
12928
+ }
12929
+ ),
12930
+ optimizationErrorsCounter: meter.createCounter(
12931
+ "ax_optimizer_optimization_errors_total",
12932
+ {
12933
+ description: "Total number of failed optimizations"
12934
+ }
12935
+ ),
12936
+ // Convergence metrics
12937
+ convergenceRoundsHistogram: meter.createHistogram(
12938
+ "ax_optimizer_convergence_rounds",
12939
+ {
12940
+ description: "Number of rounds until convergence"
12941
+ }
12942
+ ),
12943
+ convergenceScoreGauge: meter.createGauge("ax_optimizer_convergence_score", {
12944
+ description: "Current best score during optimization"
12945
+ }),
12946
+ convergenceImprovementGauge: meter.createGauge(
12947
+ "ax_optimizer_convergence_improvement",
12948
+ {
12949
+ description: "Improvement in score from baseline"
12950
+ }
12951
+ ),
12952
+ stagnationRoundsGauge: meter.createGauge("ax_optimizer_stagnation_rounds", {
12953
+ description: "Number of rounds without improvement"
12954
+ }),
12955
+ earlyStoppingCounter: meter.createCounter(
12956
+ "ax_optimizer_early_stopping_total",
12957
+ {
12958
+ description: "Total number of early stopping events"
12959
+ }
12960
+ ),
12961
+ // Resource usage metrics
12962
+ tokenUsageCounter: meter.createCounter("ax_optimizer_token_usage_total", {
12963
+ description: "Total tokens used during optimization"
12964
+ }),
12965
+ costUsageCounter: meter.createCounter("ax_optimizer_cost_usage_total", {
12966
+ description: "Total cost incurred during optimization",
12967
+ unit: "$"
12968
+ }),
12969
+ memoryUsageGauge: meter.createGauge("ax_optimizer_memory_usage_bytes", {
12970
+ description: "Peak memory usage during optimization",
12971
+ unit: "By"
12972
+ }),
12973
+ optimizationDurationHistogram: meter.createHistogram(
12974
+ "ax_optimizer_duration_ms",
12975
+ {
12976
+ description: "Duration of optimization runs",
12977
+ unit: "ms"
12978
+ }
12979
+ ),
12980
+ // Teacher-student metrics
12981
+ teacherStudentUsageCounter: meter.createCounter(
12982
+ "ax_optimizer_teacher_student_usage_total",
12983
+ {
12984
+ description: "Total number of teacher-student interactions"
12985
+ }
12986
+ ),
12987
+ teacherStudentLatencyHistogram: meter.createHistogram(
12988
+ "ax_optimizer_teacher_student_latency_ms",
12989
+ {
12990
+ description: "Latency of teacher-student interactions",
12991
+ unit: "ms"
12992
+ }
12993
+ ),
12994
+ teacherStudentScoreImprovementGauge: meter.createGauge(
12995
+ "ax_optimizer_teacher_student_score_improvement",
12996
+ {
12997
+ description: "Score improvement from teacher-student interactions"
12998
+ }
12999
+ ),
13000
+ // Checkpointing metrics
13001
+ checkpointSaveCounter: meter.createCounter(
13002
+ "ax_optimizer_checkpoint_save_total",
13003
+ {
13004
+ description: "Total number of checkpoint saves"
13005
+ }
13006
+ ),
13007
+ checkpointLoadCounter: meter.createCounter(
13008
+ "ax_optimizer_checkpoint_load_total",
13009
+ {
13010
+ description: "Total number of checkpoint loads"
13011
+ }
13012
+ ),
13013
+ checkpointSaveLatencyHistogram: meter.createHistogram(
13014
+ "ax_optimizer_checkpoint_save_latency_ms",
13015
+ {
13016
+ description: "Latency of checkpoint save operations",
13017
+ unit: "ms"
13018
+ }
13019
+ ),
13020
+ checkpointLoadLatencyHistogram: meter.createHistogram(
13021
+ "ax_optimizer_checkpoint_load_latency_ms",
13022
+ {
13023
+ description: "Latency of checkpoint load operations",
13024
+ unit: "ms"
13025
+ }
13026
+ ),
13027
+ // Pareto optimization metrics
13028
+ paretoOptimizationsCounter: meter.createCounter(
13029
+ "ax_optimizer_pareto_optimizations_total",
13030
+ {
13031
+ description: "Total number of Pareto optimizations"
13032
+ }
13033
+ ),
13034
+ paretoFrontSizeHistogram: meter.createHistogram(
13035
+ "ax_optimizer_pareto_front_size",
13036
+ {
13037
+ description: "Size of Pareto frontier"
13038
+ }
13039
+ ),
13040
+ paretoHypervolumeGauge: meter.createGauge(
13041
+ "ax_optimizer_pareto_hypervolume",
13042
+ {
13043
+ description: "Hypervolume of Pareto frontier"
13044
+ }
13045
+ ),
13046
+ paretoSolutionsGeneratedHistogram: meter.createHistogram(
13047
+ "ax_optimizer_pareto_solutions_generated",
13048
+ {
13049
+ description: "Number of solutions generated for Pareto optimization"
13050
+ }
13051
+ ),
13052
+ // Program complexity metrics
13053
+ programInputFieldsGauge: meter.createGauge(
13054
+ "ax_optimizer_program_input_fields",
13055
+ {
13056
+ description: "Number of input fields in optimized program"
13057
+ }
13058
+ ),
13059
+ programOutputFieldsGauge: meter.createGauge(
13060
+ "ax_optimizer_program_output_fields",
13061
+ {
13062
+ description: "Number of output fields in optimized program"
13063
+ }
13064
+ ),
13065
+ examplesCountGauge: meter.createGauge("ax_optimizer_examples_count", {
13066
+ description: "Number of training examples used"
13067
+ }),
13068
+ validationSetSizeGauge: meter.createGauge(
13069
+ "ax_optimizer_validation_set_size",
13070
+ {
13071
+ description: "Size of validation set used"
13072
+ }
13073
+ ),
13074
+ // Performance metrics
13075
+ evaluationLatencyHistogram: meter.createHistogram(
13076
+ "ax_optimizer_evaluation_latency_ms",
13077
+ {
13078
+ description: "Latency of program evaluations",
13079
+ unit: "ms"
13080
+ }
13081
+ ),
13082
+ demoGenerationLatencyHistogram: meter.createHistogram(
13083
+ "ax_optimizer_demo_generation_latency_ms",
13084
+ {
13085
+ description: "Latency of demo generation",
13086
+ unit: "ms"
13087
+ }
13088
+ ),
13089
+ metricComputationLatencyHistogram: meter.createHistogram(
13090
+ "ax_optimizer_metric_computation_latency_ms",
13091
+ {
13092
+ description: "Latency of metric computation",
13093
+ unit: "ms"
13094
+ }
13095
+ ),
13096
+ // Configuration metrics
13097
+ optimizerTypeGauge: meter.createGauge("ax_optimizer_type", {
13098
+ description: "Type of optimizer being used"
13099
+ }),
13100
+ targetScoreGauge: meter.createGauge("ax_optimizer_target_score", {
13101
+ description: "Target score for optimization"
13102
+ }),
13103
+ maxRoundsGauge: meter.createGauge("ax_optimizer_max_rounds", {
13104
+ description: "Maximum rounds for optimization"
13105
+ })
13106
+ };
13107
+ };
13108
+ var sanitizeOptimizerLabels = (labels) => {
13109
+ const sanitized = {};
13110
+ for (const [key, value] of Object.entries(labels)) {
13111
+ if (value !== void 0 && value !== null) {
13112
+ const stringValue = String(value);
13113
+ const maxLength = currentOptimizerMetricsConfig.maxLabelLength;
13114
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
13115
+ }
13116
+ }
13117
+ return sanitized;
13118
+ };
13119
+ var recordOptimizationMetric = (instruments, duration, success, optimizerType, programSignature) => {
13120
+ try {
13121
+ const labels = sanitizeOptimizerLabels({
13122
+ success: success.toString(),
13123
+ optimizer_type: optimizerType,
13124
+ ...programSignature ? { program_signature: programSignature } : {}
13125
+ });
13126
+ if (instruments.optimizationLatencyHistogram) {
13127
+ instruments.optimizationLatencyHistogram.record(duration, labels);
13128
+ }
13129
+ if (instruments.optimizationRequestsCounter) {
13130
+ instruments.optimizationRequestsCounter.add(1, labels);
13131
+ }
13132
+ if (!success && instruments.optimizationErrorsCounter) {
13133
+ instruments.optimizationErrorsCounter.add(1, labels);
13134
+ }
13135
+ } catch (error) {
13136
+ console.warn("Failed to record optimization metric:", error);
13137
+ }
13138
+ };
13139
+ var recordConvergenceMetric = (instruments, rounds, currentScore, improvement, stagnationRounds, optimizerType) => {
13140
+ try {
13141
+ const labels = sanitizeOptimizerLabels({
13142
+ optimizer_type: optimizerType
13143
+ });
13144
+ if (instruments.convergenceRoundsHistogram) {
13145
+ instruments.convergenceRoundsHistogram.record(rounds, labels);
13146
+ }
13147
+ if (instruments.convergenceScoreGauge) {
13148
+ instruments.convergenceScoreGauge.record(currentScore, labels);
13149
+ }
13150
+ if (instruments.convergenceImprovementGauge) {
13151
+ instruments.convergenceImprovementGauge.record(improvement, labels);
13152
+ }
13153
+ if (instruments.stagnationRoundsGauge) {
13154
+ instruments.stagnationRoundsGauge.record(stagnationRounds, labels);
13155
+ }
13156
+ } catch (error) {
13157
+ console.warn("Failed to record convergence metric:", error);
13158
+ }
13159
+ };
13160
+ var recordEarlyStoppingMetric = (instruments, reason, optimizerType) => {
13161
+ try {
13162
+ const labels = sanitizeOptimizerLabels({
13163
+ reason,
13164
+ optimizer_type: optimizerType
12023
13165
  });
12024
- if (this.debug) {
12025
- console.warn(
12026
- `AxBalancer: Service ${this.currentService.getName()} failed (retry ${retries}/${this.maxRetries})`
12027
- );
13166
+ if (instruments.earlyStoppingCounter) {
13167
+ instruments.earlyStoppingCounter.add(1, labels);
12028
13168
  }
12029
- if (retries >= this.maxRetries) {
12030
- const gotNextService = this.getNextService();
12031
- if (this.debug) {
12032
- console.warn(
12033
- `AxBalancer: Switching to service ${this.currentService.getName()}`
12034
- );
12035
- }
12036
- return gotNextService;
13169
+ } catch (error) {
13170
+ console.warn("Failed to record early stopping metric:", error);
13171
+ }
13172
+ };
13173
+ var recordResourceUsageMetric = (instruments, tokensUsed, costIncurred, optimizerType, memoryUsage) => {
13174
+ try {
13175
+ const labels = sanitizeOptimizerLabels({
13176
+ optimizer_type: optimizerType
13177
+ });
13178
+ if (instruments.tokenUsageCounter) {
13179
+ instruments.tokenUsageCounter.add(tokensUsed, labels);
12037
13180
  }
12038
- return true;
13181
+ if (instruments.costUsageCounter) {
13182
+ instruments.costUsageCounter.add(costIncurred, labels);
13183
+ }
13184
+ if (memoryUsage !== void 0 && instruments.memoryUsageGauge) {
13185
+ instruments.memoryUsageGauge.record(memoryUsage, labels);
13186
+ }
13187
+ } catch (error) {
13188
+ console.warn("Failed to record resource usage metric:", error);
12039
13189
  }
12040
- handleSuccess() {
12041
- this.serviceFailures.delete(this.currentService.getId());
13190
+ };
13191
+ var recordOptimizationDurationMetric = (instruments, duration, optimizerType) => {
13192
+ try {
13193
+ const labels = sanitizeOptimizerLabels({
13194
+ optimizer_type: optimizerType
13195
+ });
13196
+ if (instruments.optimizationDurationHistogram) {
13197
+ instruments.optimizationDurationHistogram.record(duration, labels);
13198
+ }
13199
+ } catch (error) {
13200
+ console.warn("Failed to record optimization duration metric:", error);
12042
13201
  }
12043
- async chat(req, options) {
12044
- this.reset();
12045
- while (true) {
12046
- if (!this.canRetryService()) {
12047
- if (!this.getNextService()) {
12048
- throw new Error("All services exhausted");
12049
- }
12050
- continue;
12051
- }
12052
- try {
12053
- const response = await this.currentService.chat(req, options);
12054
- this.handleSuccess();
12055
- return response;
12056
- } catch (e) {
12057
- if (!(e instanceof AxAIServiceError)) {
12058
- throw e;
12059
- }
12060
- switch (e.constructor) {
12061
- case AxAIServiceAuthenticationError:
12062
- throw e;
12063
- case AxAIServiceStatusError:
12064
- break;
12065
- case AxAIServiceNetworkError:
12066
- break;
12067
- case AxAIServiceResponseError:
12068
- break;
12069
- case AxAIServiceStreamTerminatedError:
12070
- break;
12071
- case AxAIServiceTimeoutError:
12072
- break;
12073
- default:
12074
- throw e;
12075
- }
12076
- if (!this.handleFailure()) {
12077
- throw e;
12078
- }
12079
- }
13202
+ };
13203
+ var recordTeacherStudentMetric = (instruments, latency, scoreImprovement, optimizerType) => {
13204
+ try {
13205
+ const labels = sanitizeOptimizerLabels({
13206
+ optimizer_type: optimizerType
13207
+ });
13208
+ if (instruments.teacherStudentUsageCounter) {
13209
+ instruments.teacherStudentUsageCounter.add(1, labels);
13210
+ }
13211
+ if (instruments.teacherStudentLatencyHistogram) {
13212
+ instruments.teacherStudentLatencyHistogram.record(latency, labels);
13213
+ }
13214
+ if (instruments.teacherStudentScoreImprovementGauge) {
13215
+ instruments.teacherStudentScoreImprovementGauge.record(
13216
+ scoreImprovement,
13217
+ labels
13218
+ );
12080
13219
  }
13220
+ } catch (error) {
13221
+ console.warn("Failed to record teacher-student metric:", error);
12081
13222
  }
12082
- async embed(req, options) {
12083
- this.reset();
12084
- while (true) {
12085
- if (!this.canRetryService()) {
12086
- if (!this.getNextService()) {
12087
- throw new Error("All services exhausted");
12088
- }
12089
- continue;
13223
+ };
13224
+ var recordCheckpointMetric = (instruments, operation, latency, success, optimizerType) => {
13225
+ try {
13226
+ const labels = sanitizeOptimizerLabels({
13227
+ operation,
13228
+ success: success.toString(),
13229
+ optimizer_type: optimizerType
13230
+ });
13231
+ if (operation === "save") {
13232
+ if (instruments.checkpointSaveCounter) {
13233
+ instruments.checkpointSaveCounter.add(1, labels);
12090
13234
  }
12091
- try {
12092
- const response = await this.currentService.embed(req, options);
12093
- this.handleSuccess();
12094
- return response;
12095
- } catch (e) {
12096
- if (!this.handleFailure()) {
12097
- throw e;
12098
- }
13235
+ if (instruments.checkpointSaveLatencyHistogram) {
13236
+ instruments.checkpointSaveLatencyHistogram.record(latency, labels);
13237
+ }
13238
+ } else {
13239
+ if (instruments.checkpointLoadCounter) {
13240
+ instruments.checkpointLoadCounter.add(1, labels);
13241
+ }
13242
+ if (instruments.checkpointLoadLatencyHistogram) {
13243
+ instruments.checkpointLoadLatencyHistogram.record(latency, labels);
12099
13244
  }
12100
13245
  }
12101
- }
12102
- setOptions(options) {
12103
- this.currentService.setOptions(options);
12104
- }
12105
- getOptions() {
12106
- return this.currentService.getOptions();
12107
- }
12108
- getLogger() {
12109
- return this.currentService.getLogger();
13246
+ } catch (error) {
13247
+ console.warn("Failed to record checkpoint metric:", error);
12110
13248
  }
12111
13249
  };
12112
- function validateModels2(services) {
12113
- const serviceWithModel = services.find(
12114
- (service) => service.getModelList() !== void 0
12115
- );
12116
- if (!serviceWithModel) {
12117
- return;
13250
+ var recordParetoMetric = (instruments, frontSize, solutionsGenerated, optimizerType, hypervolume) => {
13251
+ try {
13252
+ const labels = sanitizeOptimizerLabels({
13253
+ optimizer_type: optimizerType
13254
+ });
13255
+ if (instruments.paretoOptimizationsCounter) {
13256
+ instruments.paretoOptimizationsCounter.add(1, labels);
13257
+ }
13258
+ if (instruments.paretoFrontSizeHistogram) {
13259
+ instruments.paretoFrontSizeHistogram.record(frontSize, labels);
13260
+ }
13261
+ if (hypervolume !== void 0 && instruments.paretoHypervolumeGauge) {
13262
+ instruments.paretoHypervolumeGauge.record(hypervolume, labels);
13263
+ }
13264
+ if (instruments.paretoSolutionsGeneratedHistogram) {
13265
+ instruments.paretoSolutionsGeneratedHistogram.record(
13266
+ solutionsGenerated,
13267
+ labels
13268
+ );
13269
+ }
13270
+ } catch (error) {
13271
+ console.warn("Failed to record Pareto metric:", error);
12118
13272
  }
12119
- const referenceModelList = serviceWithModel.getModelList();
12120
- if (!referenceModelList) {
12121
- throw new Error("No model list found in any service.");
13273
+ };
13274
+ var recordProgramComplexityMetric = (instruments, inputFields, outputFields, examplesCount, validationSetSize, optimizerType) => {
13275
+ try {
13276
+ const labels = sanitizeOptimizerLabels({
13277
+ optimizer_type: optimizerType
13278
+ });
13279
+ if (instruments.programInputFieldsGauge) {
13280
+ instruments.programInputFieldsGauge.record(inputFields, labels);
13281
+ }
13282
+ if (instruments.programOutputFieldsGauge) {
13283
+ instruments.programOutputFieldsGauge.record(outputFields, labels);
13284
+ }
13285
+ if (instruments.examplesCountGauge) {
13286
+ instruments.examplesCountGauge.record(examplesCount, labels);
13287
+ }
13288
+ if (instruments.validationSetSizeGauge) {
13289
+ instruments.validationSetSizeGauge.record(validationSetSize, labels);
13290
+ }
13291
+ } catch (error) {
13292
+ console.warn("Failed to record program complexity metric:", error);
12122
13293
  }
12123
- const referenceKeys = new Set(referenceModelList.map((model) => model.key));
12124
- for (let i = 0; i < services.length; i++) {
12125
- const service = services[i];
12126
- if (!service) {
12127
- throw new Error(`Service at index ${i} is undefined`);
13294
+ };
13295
+ var recordOptimizerPerformanceMetric = (instruments, metricType, duration, optimizerType) => {
13296
+ try {
13297
+ const labels = sanitizeOptimizerLabels({
13298
+ metric_type: metricType,
13299
+ optimizer_type: optimizerType
13300
+ });
13301
+ switch (metricType) {
13302
+ case "evaluation":
13303
+ if (instruments.evaluationLatencyHistogram) {
13304
+ instruments.evaluationLatencyHistogram.record(duration, labels);
13305
+ }
13306
+ break;
13307
+ case "demo_generation":
13308
+ if (instruments.demoGenerationLatencyHistogram) {
13309
+ instruments.demoGenerationLatencyHistogram.record(duration, labels);
13310
+ }
13311
+ break;
13312
+ case "metric_computation":
13313
+ if (instruments.metricComputationLatencyHistogram) {
13314
+ instruments.metricComputationLatencyHistogram.record(duration, labels);
13315
+ }
13316
+ break;
12128
13317
  }
12129
- const modelList = service.getModelList();
12130
- if (!modelList) {
12131
- throw new Error(
12132
- `Service at index ${i} (${service.getName()}) has no model list while another service does.`
12133
- );
13318
+ } catch (error) {
13319
+ console.warn("Failed to record optimizer performance metric:", error);
13320
+ }
13321
+ };
13322
+ var recordOptimizerConfigurationMetric = (instruments, optimizerType, targetScore, maxRounds) => {
13323
+ try {
13324
+ const labels = sanitizeOptimizerLabels({
13325
+ optimizer_type: optimizerType
13326
+ });
13327
+ if (instruments.optimizerTypeGauge) {
13328
+ instruments.optimizerTypeGauge.record(1, labels);
12134
13329
  }
12135
- const serviceKeys = new Set(modelList.map((model) => model.key));
12136
- for (const key of referenceKeys) {
12137
- if (!serviceKeys.has(key)) {
12138
- throw new Error(
12139
- `Service at index ${i} (${service.getName()}) is missing model "${key}"`
12140
- );
12141
- }
13330
+ if (targetScore !== void 0 && instruments.targetScoreGauge) {
13331
+ instruments.targetScoreGauge.record(targetScore, labels);
12142
13332
  }
12143
- for (const key of serviceKeys) {
12144
- if (!referenceKeys.has(key)) {
12145
- throw new Error(
12146
- `Service at index ${i} (${service.getName()}) has extra model "${key}"`
12147
- );
12148
- }
13333
+ if (maxRounds !== void 0 && instruments.maxRoundsGauge) {
13334
+ instruments.maxRoundsGauge.record(maxRounds, labels);
12149
13335
  }
13336
+ } catch (error) {
13337
+ console.warn("Failed to record optimizer configuration metric:", error);
12150
13338
  }
12151
- }
12152
-
12153
- // dsp/optimizer.ts
13339
+ };
12154
13340
  var AxDefaultCostTracker = class {
12155
13341
  tokenUsage = {};
12156
13342
  totalTokens = 0;
@@ -12224,6 +13410,8 @@ var AxBaseOptimizer = class {
12224
13410
  configurationHistory = [];
12225
13411
  // Common optimization statistics
12226
13412
  stats;
13413
+ // Metrics instruments
13414
+ metricsInstruments;
12227
13415
  constructor(args) {
12228
13416
  if (args.examples.length === 0) {
12229
13417
  throw new Error("No examples found");
@@ -12247,6 +13435,9 @@ var AxBaseOptimizer = class {
12247
13435
  maxTokens: 1e6
12248
13436
  });
12249
13437
  this.costTracker = args.costTracker ?? costTracker;
13438
+ this.metricsInstruments = getOrCreateOptimizerMetricsInstruments(
13439
+ axGlobals.meter
13440
+ );
12250
13441
  this.stats = this.initializeStats();
12251
13442
  }
12252
13443
  /**
@@ -12318,6 +13509,7 @@ var AxBaseOptimizer = class {
12318
13509
  patienceExhausted: reason.includes("improvement"),
12319
13510
  reason
12320
13511
  };
13512
+ this.recordEarlyStoppingMetrics(reason, "unknown");
12321
13513
  if (this.onEarlyStop) {
12322
13514
  this.onEarlyStop(reason, this.stats);
12323
13515
  }
@@ -12461,6 +13653,12 @@ var AxBaseOptimizer = class {
12461
13653
  }
12462
13654
  this.updateResourceUsage(startTime);
12463
13655
  this.stats.convergenceInfo.converged = true;
13656
+ this.recordParetoMetrics(
13657
+ paretoFront.length,
13658
+ allSolutions.length,
13659
+ "base_optimizer",
13660
+ hypervolume
13661
+ );
12464
13662
  const bestScore = paretoFront.length > 0 ? Math.max(
12465
13663
  ...paretoFront.map((sol) => Math.max(...Object.values(sol.scores)))
12466
13664
  ) : 0;
@@ -12767,23 +13965,36 @@ var AxBaseOptimizer = class {
12767
13965
  async saveCheckpoint(optimizerType, optimizerConfig, bestScore, bestConfiguration, optimizerState = {}, options) {
12768
13966
  const saveFn = options?.overrideCheckpointSave || this.checkpointSave;
12769
13967
  if (!saveFn) return void 0;
12770
- const checkpoint = {
12771
- version: "1.0.0",
12772
- timestamp: Date.now(),
12773
- optimizerType,
12774
- optimizerConfig,
12775
- currentRound: this.currentRound,
12776
- totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
12777
- bestScore,
12778
- bestConfiguration,
12779
- scoreHistory: [...this.scoreHistory],
12780
- configurationHistory: [...this.configurationHistory],
12781
- stats: { ...this.stats },
12782
- optimizerState,
12783
- examples: this.examples,
12784
- validationSet: this.validationSet
12785
- };
12786
- return await saveFn(checkpoint);
13968
+ const startTime = Date.now();
13969
+ let success = false;
13970
+ let checkpointId;
13971
+ try {
13972
+ const checkpoint = {
13973
+ version: "1.0.0",
13974
+ timestamp: Date.now(),
13975
+ optimizerType,
13976
+ optimizerConfig,
13977
+ currentRound: this.currentRound,
13978
+ totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
13979
+ bestScore,
13980
+ bestConfiguration,
13981
+ scoreHistory: [...this.scoreHistory],
13982
+ configurationHistory: [...this.configurationHistory],
13983
+ stats: { ...this.stats },
13984
+ optimizerState,
13985
+ examples: this.examples,
13986
+ validationSet: this.validationSet
13987
+ };
13988
+ checkpointId = await saveFn(checkpoint);
13989
+ success = true;
13990
+ } catch (error) {
13991
+ success = false;
13992
+ throw error;
13993
+ } finally {
13994
+ const latency = Date.now() - startTime;
13995
+ this.recordCheckpointMetrics("save", latency, success, optimizerType);
13996
+ }
13997
+ return checkpointId;
12787
13998
  }
12788
13999
  /**
12789
14000
  * Load optimization state from checkpoint
@@ -12791,7 +14002,20 @@ var AxBaseOptimizer = class {
12791
14002
  async loadCheckpoint(checkpointId, options) {
12792
14003
  const loadFn = options?.overrideCheckpointLoad || this.checkpointLoad;
12793
14004
  if (!loadFn) return null;
12794
- return await loadFn(checkpointId);
14005
+ const startTime = Date.now();
14006
+ let success = false;
14007
+ let checkpoint = null;
14008
+ try {
14009
+ checkpoint = await loadFn(checkpointId);
14010
+ success = checkpoint !== null;
14011
+ } catch (error) {
14012
+ success = false;
14013
+ throw error;
14014
+ } finally {
14015
+ const latency = Date.now() - startTime;
14016
+ this.recordCheckpointMetrics("load", latency, success, "unknown");
14017
+ }
14018
+ return checkpoint;
12795
14019
  }
12796
14020
  /**
12797
14021
  * Restore optimizer state from checkpoint
@@ -12868,6 +14092,128 @@ var AxBaseOptimizer = class {
12868
14092
  }
12869
14093
  return this.verbose ?? true;
12870
14094
  }
14095
+ /**
14096
+ * Record optimization start metrics
14097
+ */
14098
+ recordOptimizationStart(optimizerType, programSignature) {
14099
+ if (!this.metricsInstruments) return;
14100
+ if (programSignature) {
14101
+ const inputFields = (programSignature.match(/input:/g) || []).length;
14102
+ const outputFields = (programSignature.match(/output:/g) || []).length;
14103
+ recordProgramComplexityMetric(
14104
+ this.metricsInstruments,
14105
+ inputFields,
14106
+ outputFields,
14107
+ this.examples.length,
14108
+ this.getValidationSet().length,
14109
+ optimizerType
14110
+ );
14111
+ }
14112
+ recordOptimizerConfigurationMetric(
14113
+ this.metricsInstruments,
14114
+ optimizerType,
14115
+ this.targetScore,
14116
+ void 0
14117
+ // maxRounds would be set by concrete optimizers
14118
+ );
14119
+ }
14120
+ /**
14121
+ * Record optimization completion metrics
14122
+ */
14123
+ recordOptimizationComplete(duration, success, optimizerType, programSignature) {
14124
+ if (!this.metricsInstruments) return;
14125
+ recordOptimizationMetric(
14126
+ this.metricsInstruments,
14127
+ duration,
14128
+ success,
14129
+ optimizerType,
14130
+ programSignature
14131
+ );
14132
+ recordOptimizationDurationMetric(
14133
+ this.metricsInstruments,
14134
+ duration,
14135
+ optimizerType
14136
+ );
14137
+ const currentCost = this.costTracker?.getCurrentCost() ?? 0;
14138
+ const totalTokens = this.costTracker?.getTotalTokens() ?? 0;
14139
+ recordResourceUsageMetric(
14140
+ this.metricsInstruments,
14141
+ totalTokens,
14142
+ currentCost,
14143
+ optimizerType
14144
+ );
14145
+ }
14146
+ /**
14147
+ * Record convergence metrics
14148
+ */
14149
+ recordConvergenceMetrics(rounds, currentScore, improvement, stagnationRounds, optimizerType) {
14150
+ if (!this.metricsInstruments) return;
14151
+ recordConvergenceMetric(
14152
+ this.metricsInstruments,
14153
+ rounds,
14154
+ currentScore,
14155
+ improvement,
14156
+ stagnationRounds,
14157
+ optimizerType
14158
+ );
14159
+ }
14160
+ /**
14161
+ * Record early stopping metrics
14162
+ */
14163
+ recordEarlyStoppingMetrics(reason, optimizerType) {
14164
+ if (!this.metricsInstruments) return;
14165
+ recordEarlyStoppingMetric(this.metricsInstruments, reason, optimizerType);
14166
+ }
14167
+ /**
14168
+ * Record teacher-student interaction metrics
14169
+ */
14170
+ recordTeacherStudentMetrics(latency, scoreImprovement, optimizerType) {
14171
+ if (!this.metricsInstruments) return;
14172
+ recordTeacherStudentMetric(
14173
+ this.metricsInstruments,
14174
+ latency,
14175
+ scoreImprovement,
14176
+ optimizerType
14177
+ );
14178
+ }
14179
+ /**
14180
+ * Record checkpoint metrics
14181
+ */
14182
+ recordCheckpointMetrics(operation, latency, success, optimizerType) {
14183
+ if (!this.metricsInstruments) return;
14184
+ recordCheckpointMetric(
14185
+ this.metricsInstruments,
14186
+ operation,
14187
+ latency,
14188
+ success,
14189
+ optimizerType
14190
+ );
14191
+ }
14192
+ /**
14193
+ * Record Pareto optimization metrics
14194
+ */
14195
+ recordParetoMetrics(frontSize, solutionsGenerated, optimizerType, hypervolume) {
14196
+ if (!this.metricsInstruments) return;
14197
+ recordParetoMetric(
14198
+ this.metricsInstruments,
14199
+ frontSize,
14200
+ solutionsGenerated,
14201
+ optimizerType,
14202
+ hypervolume
14203
+ );
14204
+ }
14205
+ /**
14206
+ * Record performance metrics
14207
+ */
14208
+ recordPerformanceMetrics(metricType, duration, optimizerType) {
14209
+ if (!this.metricsInstruments) return;
14210
+ recordOptimizerPerformanceMetric(
14211
+ this.metricsInstruments,
14212
+ metricType,
14213
+ duration,
14214
+ optimizerType
14215
+ );
14216
+ }
12871
14217
  };
12872
14218
 
12873
14219
  // db/base.ts
@@ -18410,10 +19756,15 @@ var AxRAG = class extends AxChainOfThought {
18410
19756
  axAITogetherDefaultConfig,
18411
19757
  axBaseAIDefaultConfig,
18412
19758
  axBaseAIDefaultCreativeConfig,
19759
+ axCheckMetricsHealth,
18413
19760
  axCreateDefaultLogger,
18414
19761
  axCreateDefaultTextLogger,
18415
19762
  axCreateOptimizerLogger,
19763
+ axDefaultMetricsConfig,
18416
19764
  axDefaultOptimizerLogger,
19765
+ axDefaultOptimizerMetricsConfig,
19766
+ axGetMetricsConfig,
19767
+ axGetOptimizerMetricsConfig,
18417
19768
  axGlobals,
18418
19769
  axModelInfoAnthropic,
18419
19770
  axModelInfoCohere,
@@ -18429,6 +19780,8 @@ var AxRAG = class extends AxChainOfThought {
18429
19780
  axModelInfoTogether,
18430
19781
  axSpanAttributes,
18431
19782
  axSpanEvents,
19783
+ axUpdateMetricsConfig,
19784
+ axUpdateOptimizerMetricsConfig,
18432
19785
  axValidateChatRequestMessage,
18433
19786
  axValidateChatResponseResult,
18434
19787
  f,