@ax-llm/ax 12.0.19 → 12.0.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -586,6 +586,16 @@ var apiCall = async (api, json) => {
586
586
  import crypto2 from "crypto";
587
587
  import { context, SpanKind } from "@opentelemetry/api";
588
588
 
589
+ // dsp/globals.ts
590
+ var axGlobals = {
591
+ signatureStrict: true,
592
+ // Controls reservedNames enforcement in signature parsing/validation
593
+ tracer: void 0,
594
+ // Global OpenTelemetry tracer for all AI operations
595
+ meter: void 0
596
+ // Global OpenTelemetry meter for metrics collection
597
+ };
598
+
589
599
  // trace/trace.ts
590
600
  var axSpanAttributes = {
591
601
  // LLM
@@ -1021,6 +1031,326 @@ var logResponseDelta = (delta, logger = defaultLogger) => {
1021
1031
  logger(delta, { tags: ["responseContent"] });
1022
1032
  };
1023
1033
 
1034
+ // ai/metrics.ts
1035
+ var sanitizeLabels = (labels) => {
1036
+ const sanitized = {};
1037
+ for (const [key, value] of Object.entries(labels)) {
1038
+ if (value !== void 0 && value !== null) {
1039
+ const stringValue = String(value);
1040
+ sanitized[key] = stringValue.length > 100 ? stringValue.substring(0, 100) : stringValue;
1041
+ }
1042
+ }
1043
+ return sanitized;
1044
+ };
1045
+ var globalAIMetricsInstruments;
1046
+ var getOrCreateAIMetricsInstruments = (meter) => {
1047
+ if (globalAIMetricsInstruments) {
1048
+ return globalAIMetricsInstruments;
1049
+ }
1050
+ if (meter) {
1051
+ globalAIMetricsInstruments = createMetricsInstruments(meter);
1052
+ return globalAIMetricsInstruments;
1053
+ }
1054
+ return void 0;
1055
+ };
1056
+ var createMetricsInstruments = (meter) => {
1057
+ return {
1058
+ latencyHistogram: meter.createHistogram("ax_llm_request_duration_ms", {
1059
+ description: "Duration of LLM requests in milliseconds",
1060
+ unit: "ms"
1061
+ }),
1062
+ errorCounter: meter.createCounter("ax_llm_errors_total", {
1063
+ description: "Total number of LLM request errors"
1064
+ }),
1065
+ requestCounter: meter.createCounter("ax_llm_requests_total", {
1066
+ description: "Total number of LLM requests"
1067
+ }),
1068
+ tokenCounter: meter.createCounter("ax_llm_tokens_total", {
1069
+ description: "Total number of LLM tokens consumed"
1070
+ }),
1071
+ inputTokenCounter: meter.createCounter("ax_llm_input_tokens_total", {
1072
+ description: "Total number of input/prompt tokens consumed"
1073
+ }),
1074
+ outputTokenCounter: meter.createCounter("ax_llm_output_tokens_total", {
1075
+ description: "Total number of output/completion tokens generated"
1076
+ }),
1077
+ errorRateGauge: meter.createGauge("ax_llm_error_rate", {
1078
+ description: "Current error rate as a percentage (0-100)"
1079
+ }),
1080
+ meanLatencyGauge: meter.createGauge("ax_llm_mean_latency_ms", {
1081
+ description: "Mean latency of LLM requests in milliseconds",
1082
+ unit: "ms"
1083
+ }),
1084
+ p95LatencyGauge: meter.createGauge("ax_llm_p95_latency_ms", {
1085
+ description: "95th percentile latency of LLM requests in milliseconds",
1086
+ unit: "ms"
1087
+ }),
1088
+ p99LatencyGauge: meter.createGauge("ax_llm_p99_latency_ms", {
1089
+ description: "99th percentile latency of LLM requests in milliseconds",
1090
+ unit: "ms"
1091
+ }),
1092
+ streamingRequestsCounter: meter.createCounter(
1093
+ "ax_llm_streaming_requests_total",
1094
+ {
1095
+ description: "Total number of streaming LLM requests"
1096
+ }
1097
+ ),
1098
+ functionCallsCounter: meter.createCounter("ax_llm_function_calls_total", {
1099
+ description: "Total number of function/tool calls made"
1100
+ }),
1101
+ functionCallLatencyHistogram: meter.createHistogram(
1102
+ "ax_llm_function_call_latency_ms",
1103
+ {
1104
+ description: "Latency of function calls in milliseconds",
1105
+ unit: "ms"
1106
+ }
1107
+ ),
1108
+ requestSizeHistogram: meter.createHistogram("ax_llm_request_size_bytes", {
1109
+ description: "Size of LLM request payloads in bytes",
1110
+ unit: "By"
1111
+ }),
1112
+ responseSizeHistogram: meter.createHistogram("ax_llm_response_size_bytes", {
1113
+ description: "Size of LLM response payloads in bytes",
1114
+ unit: "By"
1115
+ }),
1116
+ temperatureGauge: meter.createGauge("ax_llm_temperature_gauge", {
1117
+ description: "Temperature setting used for LLM requests"
1118
+ }),
1119
+ maxTokensGauge: meter.createGauge("ax_llm_max_tokens_gauge", {
1120
+ description: "Maximum tokens setting used for LLM requests"
1121
+ }),
1122
+ estimatedCostCounter: meter.createCounter("ax_llm_estimated_cost_total", {
1123
+ description: "Estimated cost of LLM requests in USD",
1124
+ unit: "$"
1125
+ }),
1126
+ promptLengthHistogram: meter.createHistogram("ax_llm_prompt_length_chars", {
1127
+ description: "Length of prompts in characters"
1128
+ }),
1129
+ contextWindowUsageGauge: meter.createGauge(
1130
+ "ax_llm_context_window_usage_ratio",
1131
+ {
1132
+ description: "Context window utilization ratio (0-1)"
1133
+ }
1134
+ ),
1135
+ timeoutsCounter: meter.createCounter("ax_llm_timeouts_total", {
1136
+ description: "Total number of timed out LLM requests"
1137
+ }),
1138
+ abortsCounter: meter.createCounter("ax_llm_aborts_total", {
1139
+ description: "Total number of aborted LLM requests"
1140
+ }),
1141
+ thinkingBudgetUsageCounter: meter.createCounter(
1142
+ "ax_llm_thinking_budget_usage_total",
1143
+ {
1144
+ description: "Total thinking budget tokens used"
1145
+ }
1146
+ ),
1147
+ multimodalRequestsCounter: meter.createCounter(
1148
+ "ax_llm_multimodal_requests_total",
1149
+ {
1150
+ description: "Total number of multimodal requests (with images/audio)"
1151
+ }
1152
+ )
1153
+ };
1154
+ };
1155
+ var recordLatencyMetric = (instruments, type, duration, aiService, model) => {
1156
+ try {
1157
+ if (instruments.latencyHistogram) {
1158
+ const labels = sanitizeLabels({
1159
+ operation: type,
1160
+ ai_service: aiService,
1161
+ ...model ? { model } : {}
1162
+ });
1163
+ instruments.latencyHistogram.record(duration, labels);
1164
+ }
1165
+ } catch (error) {
1166
+ console.warn("Failed to record latency metric:", error);
1167
+ }
1168
+ };
1169
+ var recordLatencyStatsMetrics = (instruments, type, meanLatency, p95Latency, p99Latency, aiService, model) => {
1170
+ const labels = {
1171
+ operation: type,
1172
+ ai_service: aiService,
1173
+ ...model ? { model } : {}
1174
+ };
1175
+ if (instruments.meanLatencyGauge) {
1176
+ instruments.meanLatencyGauge.record(meanLatency, labels);
1177
+ }
1178
+ if (instruments.p95LatencyGauge) {
1179
+ instruments.p95LatencyGauge.record(p95Latency, labels);
1180
+ }
1181
+ if (instruments.p99LatencyGauge) {
1182
+ instruments.p99LatencyGauge.record(p99Latency, labels);
1183
+ }
1184
+ };
1185
+ var recordErrorMetric = (instruments, type, aiService, model) => {
1186
+ try {
1187
+ if (instruments.errorCounter) {
1188
+ const labels = sanitizeLabels({
1189
+ operation: type,
1190
+ ai_service: aiService,
1191
+ ...model ? { model } : {}
1192
+ });
1193
+ instruments.errorCounter.add(1, labels);
1194
+ }
1195
+ } catch (error) {
1196
+ console.warn("Failed to record error metric:", error);
1197
+ }
1198
+ };
1199
+ var recordErrorRateMetric = (instruments, type, errorRate, aiService, model) => {
1200
+ if (instruments.errorRateGauge) {
1201
+ instruments.errorRateGauge.record(errorRate * 100, {
1202
+ // Convert to percentage
1203
+ operation: type,
1204
+ ai_service: aiService,
1205
+ ...model ? { model } : {}
1206
+ });
1207
+ }
1208
+ };
1209
+ var recordRequestMetric = (instruments, type, aiService, model) => {
1210
+ if (instruments.requestCounter) {
1211
+ instruments.requestCounter.add(1, {
1212
+ operation: type,
1213
+ ai_service: aiService,
1214
+ ...model ? { model } : {}
1215
+ });
1216
+ }
1217
+ };
1218
+ var recordTokenMetric = (instruments, type, tokens, aiService, model) => {
1219
+ try {
1220
+ const labels = sanitizeLabels({
1221
+ ai_service: aiService,
1222
+ ...model ? { model } : {}
1223
+ });
1224
+ if (instruments.tokenCounter) {
1225
+ instruments.tokenCounter.add(tokens, {
1226
+ token_type: type,
1227
+ ...labels
1228
+ });
1229
+ }
1230
+ if (type === "input" && instruments.inputTokenCounter) {
1231
+ instruments.inputTokenCounter.add(tokens, labels);
1232
+ }
1233
+ if (type === "output" && instruments.outputTokenCounter) {
1234
+ instruments.outputTokenCounter.add(tokens, labels);
1235
+ }
1236
+ } catch (error) {
1237
+ console.warn("Failed to record token metric:", error);
1238
+ }
1239
+ };
1240
+ var recordStreamingRequestMetric = (instruments, type, isStreaming, aiService, model) => {
1241
+ if (isStreaming && instruments.streamingRequestsCounter) {
1242
+ instruments.streamingRequestsCounter.add(1, {
1243
+ operation: type,
1244
+ ai_service: aiService,
1245
+ ...model ? { model } : {}
1246
+ });
1247
+ }
1248
+ };
1249
+ var recordFunctionCallMetric = (instruments, functionName, latency, aiService, model) => {
1250
+ const labels = {
1251
+ function_name: functionName,
1252
+ ...aiService ? { ai_service: aiService } : {},
1253
+ ...model ? { model } : {}
1254
+ };
1255
+ if (instruments.functionCallsCounter) {
1256
+ instruments.functionCallsCounter.add(1, labels);
1257
+ }
1258
+ if (latency && instruments.functionCallLatencyHistogram) {
1259
+ instruments.functionCallLatencyHistogram.record(latency, labels);
1260
+ }
1261
+ };
1262
+ var recordRequestSizeMetric = (instruments, type, sizeBytes, aiService, model) => {
1263
+ if (instruments.requestSizeHistogram) {
1264
+ instruments.requestSizeHistogram.record(sizeBytes, {
1265
+ operation: type,
1266
+ ai_service: aiService,
1267
+ ...model ? { model } : {}
1268
+ });
1269
+ }
1270
+ };
1271
+ var recordResponseSizeMetric = (instruments, type, sizeBytes, aiService, model) => {
1272
+ if (instruments.responseSizeHistogram) {
1273
+ instruments.responseSizeHistogram.record(sizeBytes, {
1274
+ operation: type,
1275
+ ai_service: aiService,
1276
+ ...model ? { model } : {}
1277
+ });
1278
+ }
1279
+ };
1280
+ var recordModelConfigMetrics = (instruments, temperature, maxTokens, aiService, model) => {
1281
+ const labels = {
1282
+ ...aiService ? { ai_service: aiService } : {},
1283
+ ...model ? { model } : {}
1284
+ };
1285
+ if (temperature !== void 0 && instruments.temperatureGauge) {
1286
+ instruments.temperatureGauge.record(temperature, labels);
1287
+ }
1288
+ if (maxTokens !== void 0 && instruments.maxTokensGauge) {
1289
+ instruments.maxTokensGauge.record(maxTokens, labels);
1290
+ }
1291
+ };
1292
+ var recordEstimatedCostMetric = (instruments, type, costUSD, aiService, model) => {
1293
+ if (instruments.estimatedCostCounter) {
1294
+ instruments.estimatedCostCounter.add(costUSD, {
1295
+ operation: type,
1296
+ ai_service: aiService,
1297
+ ...model ? { model } : {}
1298
+ });
1299
+ }
1300
+ };
1301
+ var recordPromptLengthMetric = (instruments, lengthChars, aiService, model) => {
1302
+ if (instruments.promptLengthHistogram) {
1303
+ instruments.promptLengthHistogram.record(lengthChars, {
1304
+ ai_service: aiService,
1305
+ ...model ? { model } : {}
1306
+ });
1307
+ }
1308
+ };
1309
+ var recordContextWindowUsageMetric = (instruments, usageRatio, aiService, model) => {
1310
+ if (instruments.contextWindowUsageGauge) {
1311
+ instruments.contextWindowUsageGauge.record(usageRatio, {
1312
+ ai_service: aiService,
1313
+ ...model ? { model } : {}
1314
+ });
1315
+ }
1316
+ };
1317
+ var recordTimeoutMetric = (instruments, type, aiService, model) => {
1318
+ if (instruments.timeoutsCounter) {
1319
+ instruments.timeoutsCounter.add(1, {
1320
+ operation: type,
1321
+ ai_service: aiService,
1322
+ ...model ? { model } : {}
1323
+ });
1324
+ }
1325
+ };
1326
+ var recordAbortMetric = (instruments, type, aiService, model) => {
1327
+ if (instruments.abortsCounter) {
1328
+ instruments.abortsCounter.add(1, {
1329
+ operation: type,
1330
+ ai_service: aiService,
1331
+ ...model ? { model } : {}
1332
+ });
1333
+ }
1334
+ };
1335
+ var recordThinkingBudgetUsageMetric = (instruments, tokensUsed, aiService, model) => {
1336
+ if (instruments.thinkingBudgetUsageCounter) {
1337
+ instruments.thinkingBudgetUsageCounter.add(tokensUsed, {
1338
+ ai_service: aiService,
1339
+ ...model ? { model } : {}
1340
+ });
1341
+ }
1342
+ };
1343
+ var recordMultimodalRequestMetric = (instruments, hasImages, hasAudio, aiService, model) => {
1344
+ if ((hasImages || hasAudio) && instruments.multimodalRequestsCounter) {
1345
+ instruments.multimodalRequestsCounter.add(1, {
1346
+ ai_service: aiService,
1347
+ has_images: hasImages.toString(),
1348
+ has_audio: hasAudio.toString(),
1349
+ ...model ? { model } : {}
1350
+ });
1351
+ }
1352
+ };
1353
+
1024
1354
  // ai/base.ts
1025
1355
  var axBaseAIDefaultConfig = () => structuredClone({
1026
1356
  temperature: 0,
@@ -1051,7 +1381,8 @@ var AxBaseAI = class {
1051
1381
  this.apiURL = apiURL;
1052
1382
  this.headers = headers;
1053
1383
  this.supportFor = supportFor;
1054
- this.tracer = options.tracer;
1384
+ this.tracer = options.tracer ?? axGlobals.tracer;
1385
+ this.meter = options.meter ?? axGlobals.meter;
1055
1386
  this.modelInfo = modelInfo;
1056
1387
  this.models = models;
1057
1388
  this.id = crypto2.randomUUID();
@@ -1070,6 +1401,7 @@ var AxBaseAI = class {
1070
1401
  rt;
1071
1402
  fetch;
1072
1403
  tracer;
1404
+ meter;
1073
1405
  timeout;
1074
1406
  excludeContentFromTrace;
1075
1407
  models;
@@ -1116,6 +1448,9 @@ var AxBaseAI = class {
1116
1448
  }
1117
1449
  }
1118
1450
  };
1451
+ getMetricsInstruments() {
1452
+ return getOrCreateAIMetricsInstruments(this.meter);
1453
+ }
1119
1454
  setName(name) {
1120
1455
  this.name = name;
1121
1456
  }
@@ -1133,7 +1468,8 @@ var AxBaseAI = class {
1133
1468
  this.rt = options.rateLimiter;
1134
1469
  this.fetch = options.fetch;
1135
1470
  this.timeout = options.timeout;
1136
- this.tracer = options.tracer;
1471
+ this.tracer = options.tracer ?? axGlobals.tracer;
1472
+ this.meter = options.meter ?? axGlobals.meter;
1137
1473
  this.excludeContentFromTrace = options.excludeContentFromTrace;
1138
1474
  this.abortSignal = options.abortSignal;
1139
1475
  this.logger = options.logger ?? defaultLogger2;
@@ -1144,6 +1480,7 @@ var AxBaseAI = class {
1144
1480
  rateLimiter: this.rt,
1145
1481
  fetch: this.fetch,
1146
1482
  tracer: this.tracer,
1483
+ meter: this.meter,
1147
1484
  timeout: this.timeout,
1148
1485
  excludeContentFromTrace: this.excludeContentFromTrace,
1149
1486
  abortSignal: this.abortSignal,
@@ -1208,6 +1545,20 @@ var AxBaseAI = class {
1208
1545
  metrics.mean = metrics.samples.reduce((a, b) => a + b, 0) / metrics.samples.length;
1209
1546
  metrics.p95 = this.calculatePercentile(metrics.samples, 95);
1210
1547
  metrics.p99 = this.calculatePercentile(metrics.samples, 99);
1548
+ const metricsInstruments = this.getMetricsInstruments();
1549
+ if (metricsInstruments) {
1550
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1551
+ recordLatencyMetric(metricsInstruments, type, duration, this.name, model);
1552
+ recordLatencyStatsMetrics(
1553
+ metricsInstruments,
1554
+ type,
1555
+ metrics.mean,
1556
+ metrics.p95,
1557
+ metrics.p99,
1558
+ this.name,
1559
+ model
1560
+ );
1561
+ }
1211
1562
  }
1212
1563
  // Method to update error metrics
1213
1564
  updateErrorMetrics(type, isError) {
@@ -1217,6 +1568,319 @@ var AxBaseAI = class {
1217
1568
  metrics.count++;
1218
1569
  }
1219
1570
  metrics.rate = metrics.count / metrics.total;
1571
+ const metricsInstruments = this.getMetricsInstruments();
1572
+ if (metricsInstruments) {
1573
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1574
+ recordRequestMetric(metricsInstruments, type, this.name, model);
1575
+ if (isError) {
1576
+ recordErrorMetric(metricsInstruments, type, this.name, model);
1577
+ }
1578
+ recordErrorRateMetric(
1579
+ metricsInstruments,
1580
+ type,
1581
+ metrics.rate,
1582
+ this.name,
1583
+ model
1584
+ );
1585
+ }
1586
+ }
1587
+ // Method to record token usage metrics
1588
+ recordTokenUsage(modelUsage) {
1589
+ const metricsInstruments = this.getMetricsInstruments();
1590
+ if (metricsInstruments && modelUsage?.tokens) {
1591
+ const { promptTokens, completionTokens, totalTokens, thoughtsTokens } = modelUsage.tokens;
1592
+ if (promptTokens) {
1593
+ recordTokenMetric(
1594
+ metricsInstruments,
1595
+ "input",
1596
+ promptTokens,
1597
+ this.name,
1598
+ modelUsage.model
1599
+ );
1600
+ }
1601
+ if (completionTokens) {
1602
+ recordTokenMetric(
1603
+ metricsInstruments,
1604
+ "output",
1605
+ completionTokens,
1606
+ this.name,
1607
+ modelUsage.model
1608
+ );
1609
+ }
1610
+ if (totalTokens) {
1611
+ recordTokenMetric(
1612
+ metricsInstruments,
1613
+ "total",
1614
+ totalTokens,
1615
+ this.name,
1616
+ modelUsage.model
1617
+ );
1618
+ }
1619
+ if (thoughtsTokens) {
1620
+ recordTokenMetric(
1621
+ metricsInstruments,
1622
+ "thoughts",
1623
+ thoughtsTokens,
1624
+ this.name,
1625
+ modelUsage.model
1626
+ );
1627
+ }
1628
+ }
1629
+ }
1630
+ // Helper method to calculate request size in bytes
1631
+ calculateRequestSize(req) {
1632
+ try {
1633
+ return new TextEncoder().encode(JSON.stringify(req)).length;
1634
+ } catch {
1635
+ return 0;
1636
+ }
1637
+ }
1638
+ // Helper method to calculate response size in bytes
1639
+ calculateResponseSize(response) {
1640
+ try {
1641
+ return new TextEncoder().encode(JSON.stringify(response)).length;
1642
+ } catch {
1643
+ return 0;
1644
+ }
1645
+ }
1646
+ // Helper method to detect multimodal content
1647
+ detectMultimodalContent(req) {
1648
+ let hasImages = false;
1649
+ let hasAudio = false;
1650
+ if (req.chatPrompt && Array.isArray(req.chatPrompt)) {
1651
+ for (const message of req.chatPrompt) {
1652
+ if (message.role === "user" && Array.isArray(message.content)) {
1653
+ for (const part of message.content) {
1654
+ if (part.type === "image") {
1655
+ hasImages = true;
1656
+ } else if (part.type === "audio") {
1657
+ hasAudio = true;
1658
+ }
1659
+ }
1660
+ }
1661
+ }
1662
+ }
1663
+ return { hasImages, hasAudio };
1664
+ }
1665
+ // Helper method to calculate prompt length
1666
+ calculatePromptLength(req) {
1667
+ let totalLength = 0;
1668
+ if (req.chatPrompt && Array.isArray(req.chatPrompt)) {
1669
+ for (const message of req.chatPrompt) {
1670
+ if (message.role === "system" || message.role === "assistant") {
1671
+ if (message.content) {
1672
+ totalLength += message.content.length;
1673
+ }
1674
+ } else if (message.role === "user") {
1675
+ if (typeof message.content === "string") {
1676
+ totalLength += message.content.length;
1677
+ } else if (Array.isArray(message.content)) {
1678
+ for (const part of message.content) {
1679
+ if (part.type === "text") {
1680
+ totalLength += part.text.length;
1681
+ }
1682
+ }
1683
+ }
1684
+ } else if (message.role === "function") {
1685
+ if (message.result) {
1686
+ totalLength += message.result.length;
1687
+ }
1688
+ }
1689
+ }
1690
+ }
1691
+ return totalLength;
1692
+ }
1693
+ // Helper method to calculate context window usage
1694
+ calculateContextWindowUsage(model, modelUsage) {
1695
+ if (!modelUsage?.tokens?.promptTokens) return 0;
1696
+ const modelInfo = this.modelInfo.find(
1697
+ (info) => info.name === model
1698
+ );
1699
+ if (!modelInfo?.contextWindow) return 0;
1700
+ return modelUsage.tokens.promptTokens / modelInfo.contextWindow;
1701
+ }
1702
+ // Helper method to estimate cost
1703
+ estimateCost(model, modelUsage) {
1704
+ if (!modelUsage?.tokens) return 0;
1705
+ const modelInfo = this.modelInfo.find(
1706
+ (info) => info.name === model
1707
+ );
1708
+ if (!modelInfo || !modelInfo.promptTokenCostPer1M && !modelInfo.completionTokenCostPer1M)
1709
+ return 0;
1710
+ const { promptTokens = 0, completionTokens = 0 } = modelUsage.tokens;
1711
+ const promptCostPer1M = modelInfo.promptTokenCostPer1M || 0;
1712
+ const completionCostPer1M = modelInfo.completionTokenCostPer1M || 0;
1713
+ return promptTokens * promptCostPer1M / 1e6 + completionTokens * completionCostPer1M / 1e6;
1714
+ }
1715
+ // Helper method to estimate cost by model name
1716
+ estimateCostByName(modelName, modelUsage) {
1717
+ if (!modelUsage?.tokens) return 0;
1718
+ const modelInfo = this.modelInfo.find((info) => info.name === modelName);
1719
+ if (!modelInfo || !modelInfo.promptTokenCostPer1M && !modelInfo.completionTokenCostPer1M)
1720
+ return 0;
1721
+ const { promptTokens = 0, completionTokens = 0 } = modelUsage.tokens;
1722
+ const promptCostPer1M = modelInfo.promptTokenCostPer1M || 0;
1723
+ const completionCostPer1M = modelInfo.completionTokenCostPer1M || 0;
1724
+ return promptTokens * promptCostPer1M / 1e6 + completionTokens * completionCostPer1M / 1e6;
1725
+ }
1726
+ // Helper method to record function call metrics
1727
+ recordFunctionCallMetrics(functionCalls, model) {
1728
+ const metricsInstruments = this.getMetricsInstruments();
1729
+ if (!metricsInstruments || !functionCalls) return;
1730
+ for (const call of functionCalls) {
1731
+ if (call && typeof call === "object" && "function" in call && call.function && typeof call.function === "object" && "name" in call.function) {
1732
+ recordFunctionCallMetric(
1733
+ metricsInstruments,
1734
+ call.function.name,
1735
+ void 0,
1736
+ // latency would need to be tracked separately
1737
+ this.name,
1738
+ model
1739
+ );
1740
+ }
1741
+ }
1742
+ }
1743
+ // Helper method to record timeout metrics
1744
+ recordTimeoutMetric(type) {
1745
+ const metricsInstruments = this.getMetricsInstruments();
1746
+ if (metricsInstruments) {
1747
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1748
+ recordTimeoutMetric(metricsInstruments, type, this.name, model);
1749
+ }
1750
+ }
1751
+ // Helper method to record abort metrics
1752
+ recordAbortMetric(type) {
1753
+ const metricsInstruments = this.getMetricsInstruments();
1754
+ if (metricsInstruments) {
1755
+ const model = type === "chat" ? this.lastUsedChatModel : this.lastUsedEmbedModel;
1756
+ recordAbortMetric(metricsInstruments, type, this.name, model);
1757
+ }
1758
+ }
1759
+ // Comprehensive method to record all chat-related metrics
1760
+ recordChatMetrics(req, options, result) {
1761
+ const metricsInstruments = this.getMetricsInstruments();
1762
+ if (!metricsInstruments) return;
1763
+ const model = this.lastUsedChatModel;
1764
+ const modelConfig = this.lastUsedModelConfig;
1765
+ const isStreaming = modelConfig?.stream ?? false;
1766
+ recordStreamingRequestMetric(
1767
+ metricsInstruments,
1768
+ "chat",
1769
+ isStreaming,
1770
+ this.name,
1771
+ model
1772
+ );
1773
+ const { hasImages, hasAudio } = this.detectMultimodalContent(req);
1774
+ recordMultimodalRequestMetric(
1775
+ metricsInstruments,
1776
+ hasImages,
1777
+ hasAudio,
1778
+ this.name,
1779
+ model
1780
+ );
1781
+ const promptLength = this.calculatePromptLength(req);
1782
+ recordPromptLengthMetric(metricsInstruments, promptLength, this.name, model);
1783
+ recordModelConfigMetrics(
1784
+ metricsInstruments,
1785
+ modelConfig?.temperature,
1786
+ modelConfig?.maxTokens,
1787
+ this.name,
1788
+ model
1789
+ );
1790
+ if (options?.thinkingTokenBudget && this.modelUsage?.tokens?.thoughtsTokens) {
1791
+ recordThinkingBudgetUsageMetric(
1792
+ metricsInstruments,
1793
+ this.modelUsage.tokens.thoughtsTokens,
1794
+ this.name,
1795
+ model
1796
+ );
1797
+ }
1798
+ const requestSize = this.calculateRequestSize(req);
1799
+ recordRequestSizeMetric(
1800
+ metricsInstruments,
1801
+ "chat",
1802
+ requestSize,
1803
+ this.name,
1804
+ model
1805
+ );
1806
+ if (result && !isStreaming) {
1807
+ const chatResponse = result;
1808
+ const responseSize = this.calculateResponseSize(chatResponse);
1809
+ recordResponseSizeMetric(
1810
+ metricsInstruments,
1811
+ "chat",
1812
+ responseSize,
1813
+ this.name,
1814
+ model
1815
+ );
1816
+ if (chatResponse.results) {
1817
+ for (const chatResult of chatResponse.results) {
1818
+ if (chatResult.functionCalls) {
1819
+ this.recordFunctionCallMetrics(
1820
+ chatResult.functionCalls,
1821
+ this.lastUsedChatModel
1822
+ );
1823
+ }
1824
+ }
1825
+ }
1826
+ const contextUsage = this.calculateContextWindowUsage(
1827
+ this.lastUsedChatModel,
1828
+ chatResponse.modelUsage
1829
+ );
1830
+ if (contextUsage > 0) {
1831
+ recordContextWindowUsageMetric(
1832
+ metricsInstruments,
1833
+ contextUsage,
1834
+ this.name,
1835
+ model
1836
+ );
1837
+ }
1838
+ const estimatedCost = this.estimateCost(
1839
+ this.lastUsedChatModel,
1840
+ chatResponse.modelUsage
1841
+ );
1842
+ if (estimatedCost > 0) {
1843
+ recordEstimatedCostMetric(
1844
+ metricsInstruments,
1845
+ "chat",
1846
+ estimatedCost,
1847
+ this.name,
1848
+ model
1849
+ );
1850
+ }
1851
+ }
1852
+ }
1853
+ // Comprehensive method to record all embed-related metrics
1854
+ recordEmbedMetrics(req, result) {
1855
+ const metricsInstruments = this.getMetricsInstruments();
1856
+ if (!metricsInstruments) return;
1857
+ const model = this.lastUsedEmbedModel;
1858
+ const requestSize = this.calculateRequestSize(req);
1859
+ recordRequestSizeMetric(
1860
+ metricsInstruments,
1861
+ "embed",
1862
+ requestSize,
1863
+ this.name,
1864
+ model
1865
+ );
1866
+ const responseSize = this.calculateResponseSize(result);
1867
+ recordResponseSizeMetric(
1868
+ metricsInstruments,
1869
+ "embed",
1870
+ responseSize,
1871
+ this.name,
1872
+ model
1873
+ );
1874
+ const estimatedCost = this.estimateCostByName(model, result.modelUsage);
1875
+ if (estimatedCost > 0) {
1876
+ recordEstimatedCostMetric(
1877
+ metricsInstruments,
1878
+ "embed",
1879
+ estimatedCost,
1880
+ this.name,
1881
+ model
1882
+ );
1883
+ }
1220
1884
  }
1221
1885
  // Public method to get metrics
1222
1886
  getMetrics() {
@@ -1225,16 +1889,27 @@ var AxBaseAI = class {
1225
1889
  async chat(req, options) {
1226
1890
  const startTime = performance.now();
1227
1891
  let isError = false;
1892
+ let result;
1228
1893
  try {
1229
- const result = await this._chat1(req, options);
1894
+ result = await this._chat1(req, options);
1230
1895
  return result;
1231
1896
  } catch (error) {
1232
1897
  isError = true;
1898
+ if (error instanceof Error) {
1899
+ if (error.message.includes("timeout") || error.name === "TimeoutError") {
1900
+ this.recordTimeoutMetric("chat");
1901
+ } else if (error.message.includes("abort") || error.name === "AbortError") {
1902
+ this.recordAbortMetric("chat");
1903
+ }
1904
+ }
1233
1905
  throw error;
1234
1906
  } finally {
1235
1907
  const duration = performance.now() - startTime;
1236
1908
  this.updateLatencyMetrics("chat", duration);
1237
1909
  this.updateErrorMetrics("chat", isError);
1910
+ if (!isError) {
1911
+ this.recordChatMetrics(req, options, result);
1912
+ }
1238
1913
  }
1239
1914
  }
1240
1915
  async _chat1(req, options) {
@@ -1381,6 +2056,7 @@ var AxBaseAI = class {
1381
2056
  }
1382
2057
  }
1383
2058
  this.modelUsage = res2.modelUsage;
2059
+ this.recordTokenUsage(res2.modelUsage);
1384
2060
  if (span?.isRecording()) {
1385
2061
  setChatResponseEvents(res2, span, this.excludeContentFromTrace);
1386
2062
  }
@@ -1423,6 +2099,7 @@ var AxBaseAI = class {
1423
2099
  }
1424
2100
  if (res.modelUsage) {
1425
2101
  this.modelUsage = res.modelUsage;
2102
+ this.recordTokenUsage(res.modelUsage);
1426
2103
  }
1427
2104
  if (span?.isRecording()) {
1428
2105
  setChatResponseEvents(res, span, this.excludeContentFromTrace);
@@ -1439,15 +2116,27 @@ var AxBaseAI = class {
1439
2116
  async embed(req, options) {
1440
2117
  const startTime = performance.now();
1441
2118
  let isError = false;
2119
+ let result;
1442
2120
  try {
1443
- return this._embed1(req, options);
2121
+ result = await this._embed1(req, options);
2122
+ return result;
1444
2123
  } catch (error) {
1445
2124
  isError = true;
2125
+ if (error instanceof Error) {
2126
+ if (error.message.includes("timeout") || error.name === "TimeoutError") {
2127
+ this.recordTimeoutMetric("embed");
2128
+ } else if (error.message.includes("abort") || error.name === "AbortError") {
2129
+ this.recordAbortMetric("embed");
2130
+ }
2131
+ }
1446
2132
  throw error;
1447
2133
  } finally {
1448
2134
  const duration = performance.now() - startTime;
1449
2135
  this.updateLatencyMetrics("embed", duration);
1450
2136
  this.updateErrorMetrics("embed", isError);
2137
+ if (!isError) {
2138
+ this.recordEmbedMetrics(req, result);
2139
+ }
1451
2140
  }
1452
2141
  }
1453
2142
  async _embed1(req, options) {
@@ -1522,6 +2211,7 @@ var AxBaseAI = class {
1522
2211
  }
1523
2212
  }
1524
2213
  this.embedModelUsage = res.modelUsage;
2214
+ this.recordTokenUsage(res.modelUsage);
1525
2215
  if (span?.isRecording() && res.modelUsage?.tokens) {
1526
2216
  span.addEvent(axSpanEvents.GEN_AI_USAGE, {
1527
2217
  [axSpanAttributes.LLM_USAGE_INPUT_TOKENS]: res.modelUsage.tokens.promptTokens,
@@ -7858,88 +8548,577 @@ function createFunctionConfig(functionList, definedFunctionCall, firstStep) {
7858
8548
  return { functions, functionCall };
7859
8549
  }
7860
8550
 
7861
- // dsp/processResponse.ts
7862
- import "stream/web";
7863
-
7864
- // ai/util.ts
7865
- function mergeFunctionCalls(functionCalls, functionCallDeltas) {
7866
- for (const _fc of functionCallDeltas) {
7867
- const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
7868
- if (fc) {
7869
- if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
7870
- fc.function.name += _fc.function.name;
7871
- }
7872
- if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
7873
- fc.function.params += _fc.function.params;
7874
- }
7875
- if (typeof _fc.function.params == "object") {
7876
- fc.function.params = _fc.function.params;
7877
- }
7878
- } else {
7879
- functionCalls.push(_fc);
7880
- }
7881
- }
7882
- }
7883
-
7884
- // dsp/sig.ts
7885
- import { createHash } from "crypto";
7886
-
7887
- // dsp/globals.ts
7888
- var axGlobals = {
7889
- signatureStrict: true
7890
- // Controls reservedNames enforcement in signature parsing/validation
8551
+ // dsp/metrics.ts
8552
+ var axDefaultMetricsConfig = {
8553
+ enabled: true,
8554
+ enabledCategories: [
8555
+ "generation",
8556
+ "streaming",
8557
+ "functions",
8558
+ "errors",
8559
+ "performance"
8560
+ ],
8561
+ maxLabelLength: 100,
8562
+ samplingRate: 1
7891
8563
  };
7892
-
7893
- // dsp/parser.ts
7894
- var SignatureValidationError = class extends Error {
7895
- constructor(message, position, context3, suggestion) {
7896
- super(message);
7897
- this.position = position;
7898
- this.context = context3;
7899
- this.suggestion = suggestion;
7900
- this.name = "SignatureValidationError";
8564
+ var globalGenMetricsInstruments;
8565
+ var getOrCreateGenMetricsInstruments = (meter) => {
8566
+ if (globalGenMetricsInstruments) {
8567
+ return globalGenMetricsInstruments;
7901
8568
  }
8569
+ const activeMeter = meter ?? axGlobals.meter;
8570
+ if (activeMeter) {
8571
+ globalGenMetricsInstruments = createGenMetricsInstruments(activeMeter);
8572
+ return globalGenMetricsInstruments;
8573
+ }
8574
+ return void 0;
7902
8575
  };
7903
- var SignatureParser = class {
7904
- input;
7905
- position;
7906
- currentFieldName = null;
7907
- currentSection = "description";
7908
- constructor(input) {
7909
- this.input = input.trim();
7910
- this.position = 0;
7911
- if (!this.input) {
7912
- throw new SignatureValidationError(
7913
- "Empty signature provided",
7914
- 0,
7915
- "",
7916
- 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
7917
- );
7918
- }
8576
+ var axCheckMetricsHealth = () => {
8577
+ const issues = [];
8578
+ if (!axGlobals.meter) {
8579
+ issues.push("Global meter not initialized");
7919
8580
  }
7920
- parse() {
7921
- try {
7922
- this.skipWhitespace();
7923
- const optionalDesc = this.parseParsedString();
7924
- this.skipWhitespace();
7925
- this.currentSection = "inputs";
7926
- const inputs = this.parseFieldList(
7927
- this.parseInputField.bind(this),
7928
- "input"
7929
- );
7930
- this.skipWhitespace();
7931
- if (this.position >= this.input.length) {
7932
- throw new SignatureValidationError(
7933
- "Incomplete signature: Missing output section",
7934
- this.position,
7935
- this.getErrorContext(),
7936
- 'Add "->" followed by output fields. Example: "-> responseText:string"'
7937
- );
7938
- }
7939
- this.expectArrow();
7940
- this.skipWhitespace();
7941
- if (this.position >= this.input.length) {
7942
- throw new SignatureValidationError(
8581
+ if (!globalGenMetricsInstruments && axGlobals.meter) {
8582
+ issues.push("Metrics instruments not created despite available meter");
8583
+ }
8584
+ return {
8585
+ healthy: issues.length === 0,
8586
+ issues
8587
+ };
8588
+ };
8589
+ var createGenMetricsInstruments = (meter) => {
8590
+ return {
8591
+ // Generation flow metrics
8592
+ // Note: Histogram buckets should be configured at the exporter level
8593
+ // Recommended buckets: [1, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000] ms
8594
+ generationLatencyHistogram: meter.createHistogram(
8595
+ "ax_gen_generation_duration_ms",
8596
+ {
8597
+ description: "End-to-end duration of AxGen generation requests",
8598
+ unit: "ms"
8599
+ }
8600
+ ),
8601
+ generationRequestsCounter: meter.createCounter(
8602
+ "ax_gen_generation_requests_total",
8603
+ {
8604
+ description: "Total number of AxGen generation requests"
8605
+ }
8606
+ ),
8607
+ generationErrorsCounter: meter.createCounter(
8608
+ "ax_gen_generation_errors_total",
8609
+ {
8610
+ description: "Total number of failed AxGen generations"
8611
+ }
8612
+ ),
8613
+ // Multi-step flow metrics
8614
+ multiStepGenerationsCounter: meter.createCounter(
8615
+ "ax_gen_multistep_generations_total",
8616
+ {
8617
+ description: "Total number of generations that required multiple steps"
8618
+ }
8619
+ ),
8620
+ stepsPerGenerationHistogram: meter.createHistogram(
8621
+ "ax_gen_steps_per_generation",
8622
+ {
8623
+ description: "Number of steps taken per generation"
8624
+ }
8625
+ ),
8626
+ maxStepsReachedCounter: meter.createCounter(
8627
+ "ax_gen_max_steps_reached_total",
8628
+ {
8629
+ description: "Total number of generations that hit max steps limit"
8630
+ }
8631
+ ),
8632
+ // Error correction metrics
8633
+ validationErrorsCounter: meter.createCounter(
8634
+ "ax_gen_validation_errors_total",
8635
+ {
8636
+ description: "Total number of validation errors encountered"
8637
+ }
8638
+ ),
8639
+ assertionErrorsCounter: meter.createCounter(
8640
+ "ax_gen_assertion_errors_total",
8641
+ {
8642
+ description: "Total number of assertion errors encountered"
8643
+ }
8644
+ ),
8645
+ errorCorrectionAttemptsHistogram: meter.createHistogram(
8646
+ "ax_gen_error_correction_attempts",
8647
+ {
8648
+ description: "Number of error correction attempts per generation"
8649
+ }
8650
+ ),
8651
+ errorCorrectionSuccessCounter: meter.createCounter(
8652
+ "ax_gen_error_correction_success_total",
8653
+ {
8654
+ description: "Total number of successful error corrections"
8655
+ }
8656
+ ),
8657
+ errorCorrectionFailureCounter: meter.createCounter(
8658
+ "ax_gen_error_correction_failure_total",
8659
+ {
8660
+ description: "Total number of failed error corrections"
8661
+ }
8662
+ ),
8663
+ maxRetriesReachedCounter: meter.createCounter(
8664
+ "ax_gen_max_retries_reached_total",
8665
+ {
8666
+ description: "Total number of generations that hit max retries limit"
8667
+ }
8668
+ ),
8669
+ // Function calling metrics
8670
+ functionsEnabledGenerationsCounter: meter.createCounter(
8671
+ "ax_gen_functions_enabled_generations_total",
8672
+ {
8673
+ description: "Total number of generations with functions enabled"
8674
+ }
8675
+ ),
8676
+ functionCallStepsCounter: meter.createCounter(
8677
+ "ax_gen_function_call_steps_total",
8678
+ {
8679
+ description: "Total number of steps that included function calls"
8680
+ }
8681
+ ),
8682
+ functionsExecutedPerGenerationHistogram: meter.createHistogram(
8683
+ "ax_gen_functions_executed_per_generation",
8684
+ {
8685
+ description: "Number of unique functions executed per generation"
8686
+ }
8687
+ ),
8688
+ functionErrorCorrectionCounter: meter.createCounter(
8689
+ "ax_gen_function_error_correction_total",
8690
+ {
8691
+ description: "Total number of function-related error corrections"
8692
+ }
8693
+ ),
8694
+ // Field processing metrics
8695
+ fieldProcessorsExecutedCounter: meter.createCounter(
8696
+ "ax_gen_field_processors_executed_total",
8697
+ {
8698
+ description: "Total number of field processors executed"
8699
+ }
8700
+ ),
8701
+ streamingFieldProcessorsExecutedCounter: meter.createCounter(
8702
+ "ax_gen_streaming_field_processors_executed_total",
8703
+ {
8704
+ description: "Total number of streaming field processors executed"
8705
+ }
8706
+ ),
8707
+ // Streaming specific metrics
8708
+ streamingGenerationsCounter: meter.createCounter(
8709
+ "ax_gen_streaming_generations_total",
8710
+ {
8711
+ description: "Total number of streaming generations"
8712
+ }
8713
+ ),
8714
+ streamingDeltasEmittedCounter: meter.createCounter(
8715
+ "ax_gen_streaming_deltas_emitted_total",
8716
+ {
8717
+ description: "Total number of streaming deltas emitted"
8718
+ }
8719
+ ),
8720
+ streamingFinalizationLatencyHistogram: meter.createHistogram(
8721
+ "ax_gen_streaming_finalization_duration_ms",
8722
+ {
8723
+ description: "Duration of streaming response finalization",
8724
+ unit: "ms"
8725
+ }
8726
+ ),
8727
+ // Memory and samples metrics
8728
+ samplesGeneratedHistogram: meter.createHistogram(
8729
+ "ax_gen_samples_generated",
8730
+ {
8731
+ description: "Number of samples generated per request"
8732
+ }
8733
+ ),
8734
+ resultPickerUsageCounter: meter.createCounter(
8735
+ "ax_gen_result_picker_usage_total",
8736
+ {
8737
+ description: "Total number of times result picker was used"
8738
+ }
8739
+ ),
8740
+ resultPickerLatencyHistogram: meter.createHistogram(
8741
+ "ax_gen_result_picker_duration_ms",
8742
+ {
8743
+ description: "Duration of result picker execution",
8744
+ unit: "ms"
8745
+ }
8746
+ ),
8747
+ // Signature complexity metrics
8748
+ inputFieldsGauge: meter.createGauge("ax_gen_input_fields", {
8749
+ description: "Number of input fields in signature"
8750
+ }),
8751
+ outputFieldsGauge: meter.createGauge("ax_gen_output_fields", {
8752
+ description: "Number of output fields in signature"
8753
+ }),
8754
+ examplesUsedGauge: meter.createGauge("ax_gen_examples_used", {
8755
+ description: "Number of examples used in generation"
8756
+ }),
8757
+ demosUsedGauge: meter.createGauge("ax_gen_demos_used", {
8758
+ description: "Number of demos used in generation"
8759
+ }),
8760
+ // Performance metrics
8761
+ promptRenderLatencyHistogram: meter.createHistogram(
8762
+ "ax_gen_prompt_render_duration_ms",
8763
+ {
8764
+ description: "Duration of prompt template rendering",
8765
+ unit: "ms"
8766
+ }
8767
+ ),
8768
+ extractionLatencyHistogram: meter.createHistogram(
8769
+ "ax_gen_extraction_duration_ms",
8770
+ {
8771
+ description: "Duration of value extraction from responses",
8772
+ unit: "ms"
8773
+ }
8774
+ ),
8775
+ assertionLatencyHistogram: meter.createHistogram(
8776
+ "ax_gen_assertion_duration_ms",
8777
+ {
8778
+ description: "Duration of assertion checking",
8779
+ unit: "ms"
8780
+ }
8781
+ ),
8782
+ // State management
8783
+ stateCreationLatencyHistogram: meter.createHistogram(
8784
+ "ax_gen_state_creation_duration_ms",
8785
+ {
8786
+ description: "Duration of state creation for multiple samples",
8787
+ unit: "ms"
8788
+ }
8789
+ ),
8790
+ memoryUpdateLatencyHistogram: meter.createHistogram(
8791
+ "ax_gen_memory_update_duration_ms",
8792
+ {
8793
+ description: "Duration of memory updates during generation",
8794
+ unit: "ms"
8795
+ }
8796
+ )
8797
+ };
8798
+ };
8799
+ var currentMetricsConfig = axDefaultMetricsConfig;
8800
+ var axUpdateMetricsConfig = (config) => {
8801
+ currentMetricsConfig = { ...currentMetricsConfig, ...config };
8802
+ };
8803
+ var axGetMetricsConfig = () => {
8804
+ return { ...currentMetricsConfig };
8805
+ };
8806
+ var sanitizeLabels2 = (labels) => {
8807
+ const sanitized = {};
8808
+ for (const [key, value] of Object.entries(labels)) {
8809
+ if (value !== void 0 && value !== null) {
8810
+ const stringValue = String(value);
8811
+ const maxLength = currentMetricsConfig.maxLabelLength;
8812
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
8813
+ }
8814
+ }
8815
+ return sanitized;
8816
+ };
8817
+ var recordGenerationMetric = (instruments, duration, success, signatureName, aiService, model) => {
8818
+ try {
8819
+ const labels = sanitizeLabels2({
8820
+ success: success.toString(),
8821
+ ...signatureName ? { signature: signatureName } : {},
8822
+ ...aiService ? { ai_service: aiService } : {},
8823
+ ...model ? { model } : {}
8824
+ });
8825
+ if (instruments.generationLatencyHistogram) {
8826
+ instruments.generationLatencyHistogram.record(duration, labels);
8827
+ }
8828
+ if (instruments.generationRequestsCounter) {
8829
+ instruments.generationRequestsCounter.add(1, labels);
8830
+ }
8831
+ if (!success && instruments.generationErrorsCounter) {
8832
+ instruments.generationErrorsCounter.add(1, labels);
8833
+ }
8834
+ } catch (error) {
8835
+ console.warn("Failed to record generation metric:", error);
8836
+ }
8837
+ };
8838
+ var recordMultiStepMetric = (instruments, stepsUsed, maxSteps, signatureName) => {
8839
+ try {
8840
+ const labels = sanitizeLabels2({
8841
+ ...signatureName ? { signature: signatureName } : {}
8842
+ });
8843
+ if (stepsUsed > 1 && instruments.multiStepGenerationsCounter) {
8844
+ instruments.multiStepGenerationsCounter.add(1, labels);
8845
+ }
8846
+ if (instruments.stepsPerGenerationHistogram) {
8847
+ instruments.stepsPerGenerationHistogram.record(stepsUsed, labels);
8848
+ }
8849
+ if (stepsUsed >= maxSteps && instruments.maxStepsReachedCounter) {
8850
+ instruments.maxStepsReachedCounter.add(1, labels);
8851
+ }
8852
+ } catch (error) {
8853
+ console.warn("Failed to record multi-step metric:", error);
8854
+ }
8855
+ };
8856
+ var recordValidationErrorMetric = (instruments, errorType, signatureName) => {
8857
+ try {
8858
+ const labels = sanitizeLabels2({
8859
+ error_type: errorType,
8860
+ ...signatureName ? { signature: signatureName } : {}
8861
+ });
8862
+ if (errorType === "validation" && instruments.validationErrorsCounter) {
8863
+ instruments.validationErrorsCounter.add(1, labels);
8864
+ }
8865
+ if (errorType === "assertion" && instruments.assertionErrorsCounter) {
8866
+ instruments.assertionErrorsCounter.add(1, labels);
8867
+ }
8868
+ } catch (error) {
8869
+ console.warn("Failed to record validation error metric:", error);
8870
+ }
8871
+ };
8872
+ var recordErrorCorrectionMetric = (instruments, attempts, success, maxRetries, signatureName) => {
8873
+ try {
8874
+ const labels = sanitizeLabels2({
8875
+ success: success.toString(),
8876
+ ...signatureName ? { signature: signatureName } : {}
8877
+ });
8878
+ if (instruments.errorCorrectionAttemptsHistogram) {
8879
+ instruments.errorCorrectionAttemptsHistogram.record(attempts, labels);
8880
+ }
8881
+ if (success && instruments.errorCorrectionSuccessCounter) {
8882
+ instruments.errorCorrectionSuccessCounter.add(1, labels);
8883
+ }
8884
+ if (!success) {
8885
+ if (instruments.errorCorrectionFailureCounter) {
8886
+ instruments.errorCorrectionFailureCounter.add(1, labels);
8887
+ }
8888
+ if (attempts >= maxRetries && instruments.maxRetriesReachedCounter) {
8889
+ instruments.maxRetriesReachedCounter.add(1, labels);
8890
+ }
8891
+ }
8892
+ } catch (error) {
8893
+ console.warn("Failed to record error correction metric:", error);
8894
+ }
8895
+ };
8896
+ var recordFunctionCallingMetric = (instruments, functionsEnabled, functionsExecuted, hadFunctionCalls, functionErrorCorrection = false, signatureName) => {
8897
+ try {
8898
+ const labels = sanitizeLabels2({
8899
+ functions_enabled: functionsEnabled.toString(),
8900
+ had_function_calls: hadFunctionCalls.toString(),
8901
+ ...signatureName ? { signature: signatureName } : {}
8902
+ });
8903
+ if (functionsEnabled && instruments.functionsEnabledGenerationsCounter) {
8904
+ instruments.functionsEnabledGenerationsCounter.add(1, labels);
8905
+ }
8906
+ if (hadFunctionCalls && instruments.functionCallStepsCounter) {
8907
+ instruments.functionCallStepsCounter.add(1, labels);
8908
+ }
8909
+ if (functionsExecuted > 0 && instruments.functionsExecutedPerGenerationHistogram) {
8910
+ instruments.functionsExecutedPerGenerationHistogram.record(
8911
+ functionsExecuted,
8912
+ labels
8913
+ );
8914
+ }
8915
+ if (functionErrorCorrection && instruments.functionErrorCorrectionCounter) {
8916
+ instruments.functionErrorCorrectionCounter.add(1, labels);
8917
+ }
8918
+ } catch (error) {
8919
+ console.warn("Failed to record function calling metric:", error);
8920
+ }
8921
+ };
8922
+ var recordFieldProcessingMetric = (instruments, fieldProcessorsExecuted, streamingFieldProcessorsExecuted, signatureName) => {
8923
+ try {
8924
+ const labels = sanitizeLabels2({
8925
+ ...signatureName ? { signature: signatureName } : {}
8926
+ });
8927
+ if (fieldProcessorsExecuted > 0 && instruments.fieldProcessorsExecutedCounter) {
8928
+ instruments.fieldProcessorsExecutedCounter.add(
8929
+ fieldProcessorsExecuted,
8930
+ labels
8931
+ );
8932
+ }
8933
+ if (streamingFieldProcessorsExecuted > 0 && instruments.streamingFieldProcessorsExecutedCounter) {
8934
+ instruments.streamingFieldProcessorsExecutedCounter.add(
8935
+ streamingFieldProcessorsExecuted,
8936
+ labels
8937
+ );
8938
+ }
8939
+ } catch (error) {
8940
+ console.warn("Failed to record field processing metric:", error);
8941
+ }
8942
+ };
8943
+ var recordStreamingMetric = (instruments, isStreaming, deltasEmitted, finalizationDuration, signatureName) => {
8944
+ try {
8945
+ const labels = sanitizeLabels2({
8946
+ is_streaming: isStreaming.toString(),
8947
+ ...signatureName ? { signature: signatureName } : {}
8948
+ });
8949
+ if (isStreaming && instruments.streamingGenerationsCounter) {
8950
+ instruments.streamingGenerationsCounter.add(1, labels);
8951
+ }
8952
+ if (deltasEmitted > 0 && instruments.streamingDeltasEmittedCounter) {
8953
+ instruments.streamingDeltasEmittedCounter.add(deltasEmitted, labels);
8954
+ }
8955
+ if (finalizationDuration && instruments.streamingFinalizationLatencyHistogram) {
8956
+ instruments.streamingFinalizationLatencyHistogram.record(
8957
+ finalizationDuration,
8958
+ labels
8959
+ );
8960
+ }
8961
+ } catch (error) {
8962
+ console.warn("Failed to record streaming metric:", error);
8963
+ }
8964
+ };
8965
+ var recordSamplesMetric = (instruments, samplesCount, resultPickerUsed, resultPickerLatency, signatureName) => {
8966
+ try {
8967
+ const labels = sanitizeLabels2({
8968
+ result_picker_used: resultPickerUsed.toString(),
8969
+ ...signatureName ? { signature: signatureName } : {}
8970
+ });
8971
+ if (instruments.samplesGeneratedHistogram) {
8972
+ instruments.samplesGeneratedHistogram.record(samplesCount, labels);
8973
+ }
8974
+ if (resultPickerUsed && instruments.resultPickerUsageCounter) {
8975
+ instruments.resultPickerUsageCounter.add(1, labels);
8976
+ }
8977
+ if (resultPickerLatency && instruments.resultPickerLatencyHistogram) {
8978
+ instruments.resultPickerLatencyHistogram.record(
8979
+ resultPickerLatency,
8980
+ labels
8981
+ );
8982
+ }
8983
+ } catch (error) {
8984
+ console.warn("Failed to record samples metric:", error);
8985
+ }
8986
+ };
8987
+ var recordSignatureComplexityMetrics = (instruments, inputFields, outputFields, examplesCount, demosCount, signatureName) => {
8988
+ try {
8989
+ const labels = sanitizeLabels2({
8990
+ ...signatureName ? { signature: signatureName } : {}
8991
+ });
8992
+ if (instruments.inputFieldsGauge) {
8993
+ instruments.inputFieldsGauge.record(inputFields, labels);
8994
+ }
8995
+ if (instruments.outputFieldsGauge) {
8996
+ instruments.outputFieldsGauge.record(outputFields, labels);
8997
+ }
8998
+ if (instruments.examplesUsedGauge) {
8999
+ instruments.examplesUsedGauge.record(examplesCount, labels);
9000
+ }
9001
+ if (instruments.demosUsedGauge) {
9002
+ instruments.demosUsedGauge.record(demosCount, labels);
9003
+ }
9004
+ } catch (error) {
9005
+ console.warn("Failed to record signature complexity metrics:", error);
9006
+ }
9007
+ };
9008
+ var recordPerformanceMetric = (instruments, metricType, duration, signatureName) => {
9009
+ try {
9010
+ const labels = sanitizeLabels2({
9011
+ metric_type: metricType,
9012
+ ...signatureName ? { signature: signatureName } : {}
9013
+ });
9014
+ switch (metricType) {
9015
+ case "prompt_render":
9016
+ if (instruments.promptRenderLatencyHistogram) {
9017
+ instruments.promptRenderLatencyHistogram.record(duration, labels);
9018
+ }
9019
+ break;
9020
+ case "extraction":
9021
+ if (instruments.extractionLatencyHistogram) {
9022
+ instruments.extractionLatencyHistogram.record(duration, labels);
9023
+ }
9024
+ break;
9025
+ case "assertion":
9026
+ if (instruments.assertionLatencyHistogram) {
9027
+ instruments.assertionLatencyHistogram.record(duration, labels);
9028
+ }
9029
+ break;
9030
+ case "state_creation":
9031
+ if (instruments.stateCreationLatencyHistogram) {
9032
+ instruments.stateCreationLatencyHistogram.record(duration, labels);
9033
+ }
9034
+ break;
9035
+ case "memory_update":
9036
+ if (instruments.memoryUpdateLatencyHistogram) {
9037
+ instruments.memoryUpdateLatencyHistogram.record(duration, labels);
9038
+ }
9039
+ break;
9040
+ }
9041
+ } catch (error) {
9042
+ console.warn("Failed to record performance metric:", error);
9043
+ }
9044
+ };
9045
+
9046
+ // dsp/processResponse.ts
9047
+ import "stream/web";
9048
+
9049
+ // ai/util.ts
9050
+ function mergeFunctionCalls(functionCalls, functionCallDeltas) {
9051
+ for (const _fc of functionCallDeltas) {
9052
+ const fc = functionCalls.find((fc2) => fc2.id === _fc.id);
9053
+ if (fc) {
9054
+ if (typeof _fc.function.name == "string" && _fc.function.name.length > 0) {
9055
+ fc.function.name += _fc.function.name;
9056
+ }
9057
+ if (typeof _fc.function.params == "string" && _fc.function.params.length > 0) {
9058
+ fc.function.params += _fc.function.params;
9059
+ }
9060
+ if (typeof _fc.function.params == "object") {
9061
+ fc.function.params = _fc.function.params;
9062
+ }
9063
+ } else {
9064
+ functionCalls.push(_fc);
9065
+ }
9066
+ }
9067
+ }
9068
+
9069
+ // dsp/sig.ts
9070
+ import { createHash } from "crypto";
9071
+
9072
+ // dsp/parser.ts
9073
+ var SignatureValidationError = class extends Error {
9074
+ constructor(message, position, context3, suggestion) {
9075
+ super(message);
9076
+ this.position = position;
9077
+ this.context = context3;
9078
+ this.suggestion = suggestion;
9079
+ this.name = "SignatureValidationError";
9080
+ }
9081
+ };
9082
+ var SignatureParser = class {
9083
+ input;
9084
+ position;
9085
+ currentFieldName = null;
9086
+ currentSection = "description";
9087
+ constructor(input) {
9088
+ this.input = input.trim();
9089
+ this.position = 0;
9090
+ if (!this.input) {
9091
+ throw new SignatureValidationError(
9092
+ "Empty signature provided",
9093
+ 0,
9094
+ "",
9095
+ 'A signature must contain at least input and output fields separated by "->". Example: "userQuery:string -> aiResponse:string"'
9096
+ );
9097
+ }
9098
+ }
9099
+ parse() {
9100
+ try {
9101
+ this.skipWhitespace();
9102
+ const optionalDesc = this.parseParsedString();
9103
+ this.skipWhitespace();
9104
+ this.currentSection = "inputs";
9105
+ const inputs = this.parseFieldList(
9106
+ this.parseInputField.bind(this),
9107
+ "input"
9108
+ );
9109
+ this.skipWhitespace();
9110
+ if (this.position >= this.input.length) {
9111
+ throw new SignatureValidationError(
9112
+ "Incomplete signature: Missing output section",
9113
+ this.position,
9114
+ this.getErrorContext(),
9115
+ 'Add "->" followed by output fields. Example: "-> responseText:string"'
9116
+ );
9117
+ }
9118
+ this.expectArrow();
9119
+ this.skipWhitespace();
9120
+ if (this.position >= this.input.length) {
9121
+ throw new SignatureValidationError(
7943
9122
  'Incomplete signature: No output fields specified after "->"',
7944
9123
  this.position,
7945
9124
  this.getErrorContext(),
@@ -10256,6 +11435,15 @@ var AxGen = class extends AxProgramWithSignature {
10256
11435
  this.functions = parseFunctions(options.functions);
10257
11436
  }
10258
11437
  }
11438
+ getSignatureName() {
11439
+ return this.signature.getDescription() || "unknown_signature";
11440
+ }
11441
+ getMetricsInstruments() {
11442
+ return getOrCreateGenMetricsInstruments();
11443
+ }
11444
+ updateMeter(meter) {
11445
+ getOrCreateGenMetricsInstruments(meter);
11446
+ }
10259
11447
  createStates(n) {
10260
11448
  return Array.from({ length: n }, (_, index) => ({
10261
11449
  index,
@@ -10445,6 +11633,7 @@ var AxGen = class extends AxProgramWithSignature {
10445
11633
  );
10446
11634
  }
10447
11635
  let prompt;
11636
+ const promptRenderStart = performance.now();
10448
11637
  if (Array.isArray(values)) {
10449
11638
  validateAxMessageArray(values);
10450
11639
  prompt = this.promptTemplate.render(values, {
@@ -10458,7 +11647,27 @@ var AxGen = class extends AxProgramWithSignature {
10458
11647
  demos: this.demos
10459
11648
  });
10460
11649
  }
11650
+ const promptRenderDuration = performance.now() - promptRenderStart;
11651
+ const metricsInstruments = this.getMetricsInstruments();
11652
+ if (metricsInstruments) {
11653
+ recordPerformanceMetric(
11654
+ metricsInstruments,
11655
+ "prompt_render",
11656
+ promptRenderDuration,
11657
+ this.getSignatureName()
11658
+ );
11659
+ }
11660
+ const memoryUpdateStart = performance.now();
10461
11661
  mem.addRequest(prompt, options.sessionId);
11662
+ const memoryUpdateDuration = performance.now() - memoryUpdateStart;
11663
+ if (metricsInstruments) {
11664
+ recordPerformanceMetric(
11665
+ metricsInstruments,
11666
+ "memory_update",
11667
+ memoryUpdateDuration,
11668
+ this.getSignatureName()
11669
+ );
11670
+ }
10462
11671
  multiStepLoop: for (let n = 0; n < maxSteps; n++) {
10463
11672
  const firstStep = n === 0;
10464
11673
  for (let errCount = 0; errCount < maxRetries; errCount++) {
@@ -10487,8 +11696,48 @@ var AxGen = class extends AxProgramWithSignature {
10487
11696
  options?.sessionId
10488
11697
  );
10489
11698
  if (shouldContinue) {
11699
+ const metricsInstruments4 = this.getMetricsInstruments();
11700
+ if (metricsInstruments4) {
11701
+ recordMultiStepMetric(
11702
+ metricsInstruments4,
11703
+ n + 1,
11704
+ maxSteps,
11705
+ this.getSignatureName()
11706
+ );
11707
+ }
10490
11708
  continue multiStepLoop;
10491
11709
  }
11710
+ const metricsInstruments3 = this.getMetricsInstruments();
11711
+ if (metricsInstruments3) {
11712
+ recordMultiStepMetric(
11713
+ metricsInstruments3,
11714
+ n + 1,
11715
+ maxSteps,
11716
+ this.getSignatureName()
11717
+ );
11718
+ const allFunctionsExecuted = /* @__PURE__ */ new Set();
11719
+ states.forEach((state) => {
11720
+ state.functionsExecuted.forEach(
11721
+ (func) => allFunctionsExecuted.add(func)
11722
+ );
11723
+ });
11724
+ if (allFunctionsExecuted.size > 0) {
11725
+ recordFunctionCallingMetric(
11726
+ metricsInstruments3,
11727
+ true,
11728
+ allFunctionsExecuted.size,
11729
+ true,
11730
+ false,
11731
+ this.getSignatureName()
11732
+ );
11733
+ }
11734
+ recordFieldProcessingMetric(
11735
+ metricsInstruments3,
11736
+ this.fieldProcessors.length,
11737
+ this.streamingFieldProcessors.length,
11738
+ this.getSignatureName()
11739
+ );
11740
+ }
10492
11741
  this.getLogger(ai, options)?.("", { tags: ["responseEnd"] });
10493
11742
  return;
10494
11743
  } catch (e) {
@@ -10497,6 +11746,14 @@ var AxGen = class extends AxProgramWithSignature {
10497
11746
  if (e instanceof ValidationError) {
10498
11747
  errorFields = e.getFixingInstructions();
10499
11748
  err = e;
11749
+ const metricsInstruments3 = this.getMetricsInstruments();
11750
+ if (metricsInstruments3) {
11751
+ recordValidationErrorMetric(
11752
+ metricsInstruments3,
11753
+ "validation",
11754
+ this.getSignatureName()
11755
+ );
11756
+ }
10500
11757
  if (span) {
10501
11758
  span.addEvent("validation.error", {
10502
11759
  message: e.toString(),
@@ -10507,6 +11764,14 @@ var AxGen = class extends AxProgramWithSignature {
10507
11764
  const e1 = e;
10508
11765
  errorFields = e1.getFixingInstructions();
10509
11766
  err = e;
11767
+ const assertionMetricsInstruments = this.getMetricsInstruments();
11768
+ if (assertionMetricsInstruments) {
11769
+ recordValidationErrorMetric(
11770
+ assertionMetricsInstruments,
11771
+ "assertion",
11772
+ this.getSignatureName()
11773
+ );
11774
+ }
10510
11775
  if (span) {
10511
11776
  span.addEvent("assertion.error", {
10512
11777
  message: e1.toString(),
@@ -10528,12 +11793,31 @@ var AxGen = class extends AxProgramWithSignature {
10528
11793
  }
10529
11794
  }
10530
11795
  }
11796
+ const metricsInstruments2 = this.getMetricsInstruments();
11797
+ if (metricsInstruments2) {
11798
+ recordErrorCorrectionMetric(
11799
+ metricsInstruments2,
11800
+ maxRetries,
11801
+ false,
11802
+ // failed
11803
+ maxRetries,
11804
+ this.getSignatureName()
11805
+ );
11806
+ }
10531
11807
  throw enhanceError(
10532
11808
  new Error(`Unable to fix validation error: ${err?.toString()}`),
10533
11809
  ai,
10534
11810
  this.signature
10535
11811
  );
10536
11812
  }
11813
+ if (metricsInstruments) {
11814
+ recordMultiStepMetric(
11815
+ metricsInstruments,
11816
+ maxSteps,
11817
+ maxSteps,
11818
+ this.getSignatureName()
11819
+ );
11820
+ }
10537
11821
  throw enhanceError(
10538
11822
  new Error(`Max steps reached: ${maxSteps}`),
10539
11823
  ai,
@@ -10541,7 +11825,18 @@ var AxGen = class extends AxProgramWithSignature {
10541
11825
  );
10542
11826
  }
10543
11827
  async *_forward1(ai, values, options) {
11828
+ const stateCreationStart = performance.now();
10544
11829
  const states = this.createStates(options.sampleCount ?? 1);
11830
+ const stateCreationDuration = performance.now() - stateCreationStart;
11831
+ const metricsInstruments = this.getMetricsInstruments();
11832
+ if (metricsInstruments) {
11833
+ recordPerformanceMetric(
11834
+ metricsInstruments,
11835
+ "state_creation",
11836
+ stateCreationDuration,
11837
+ this.getSignatureName()
11838
+ );
11839
+ }
10545
11840
  const tracer = options?.tracer ?? this.options?.tracer ?? ai.getOptions().tracer;
10546
11841
  let functions = this.functions;
10547
11842
  if (options?.functions) {
@@ -10600,29 +11895,111 @@ var AxGen = class extends AxProgramWithSignature {
10600
11895
  }
10601
11896
  }
10602
11897
  async forward(ai, values, options) {
10603
- const generator = this._forward1(ai, values, options ?? {});
10604
- let buffer = [];
10605
- let currentVersion = 0;
10606
- for await (const delta of generator) {
10607
- if (delta.version !== currentVersion) {
10608
- buffer = [];
11898
+ const startTime = performance.now();
11899
+ const signatureName = this.getSignatureName();
11900
+ const isStreaming = options?.stream ?? false;
11901
+ let success = false;
11902
+ let errorCorrectionAttempts = 0;
11903
+ let functionsEnabled = false;
11904
+ let functionsExecuted = 0;
11905
+ let resultPickerUsed = false;
11906
+ try {
11907
+ const metricsInstruments = this.getMetricsInstruments();
11908
+ if (metricsInstruments) {
11909
+ recordSignatureComplexityMetrics(
11910
+ metricsInstruments,
11911
+ this.signature.getInputFields().length,
11912
+ this.signature.getOutputFields().length,
11913
+ this.examples?.length ?? 0,
11914
+ this.demos?.length ?? 0,
11915
+ signatureName
11916
+ );
11917
+ }
11918
+ functionsEnabled = !!(options?.functions || this.functions);
11919
+ const generator = this._forward1(ai, values, options ?? {});
11920
+ let buffer = [];
11921
+ let currentVersion = 0;
11922
+ let deltasEmitted = 0;
11923
+ for await (const delta of generator) {
11924
+ if (delta.version !== currentVersion) {
11925
+ buffer = [];
11926
+ }
11927
+ currentVersion = delta.version;
11928
+ buffer = mergeDeltas(buffer, delta);
11929
+ deltasEmitted++;
11930
+ }
11931
+ errorCorrectionAttempts = currentVersion;
11932
+ const resultPickerStart = performance.now();
11933
+ resultPickerUsed = !!options?.resultPicker;
11934
+ const selectedIndex = await selectFromSamples(
11935
+ buffer,
11936
+ {
11937
+ resultPicker: options?.resultPicker
11938
+ },
11939
+ // Pass memory to enable function result selection
11940
+ options?.mem,
11941
+ options?.sessionId
11942
+ );
11943
+ const resultPickerLatency = performance.now() - resultPickerStart;
11944
+ const selectedResult = buffer[selectedIndex];
11945
+ const result = selectedResult?.delta ?? {};
11946
+ this.trace = { ...values, ...result };
11947
+ success = true;
11948
+ if (metricsInstruments) {
11949
+ recordSamplesMetric(
11950
+ metricsInstruments,
11951
+ buffer.length,
11952
+ resultPickerUsed,
11953
+ resultPickerUsed ? resultPickerLatency : void 0,
11954
+ signatureName
11955
+ );
11956
+ recordStreamingMetric(
11957
+ metricsInstruments,
11958
+ isStreaming,
11959
+ deltasEmitted,
11960
+ void 0,
11961
+ // finalization latency not applicable here
11962
+ signatureName
11963
+ );
11964
+ }
11965
+ return result;
11966
+ } catch (error) {
11967
+ success = false;
11968
+ throw error;
11969
+ } finally {
11970
+ const duration = performance.now() - startTime;
11971
+ const finalMetricsInstruments = this.getMetricsInstruments();
11972
+ if (finalMetricsInstruments) {
11973
+ recordGenerationMetric(
11974
+ finalMetricsInstruments,
11975
+ duration,
11976
+ success,
11977
+ signatureName,
11978
+ ai.getName(),
11979
+ options?.model
11980
+ );
11981
+ if (functionsEnabled) {
11982
+ recordFunctionCallingMetric(
11983
+ finalMetricsInstruments,
11984
+ functionsEnabled,
11985
+ functionsExecuted,
11986
+ functionsExecuted > 0,
11987
+ false,
11988
+ // function error correction tracking would need more complex logic
11989
+ signatureName
11990
+ );
11991
+ }
11992
+ if (errorCorrectionAttempts > 0) {
11993
+ recordErrorCorrectionMetric(
11994
+ finalMetricsInstruments,
11995
+ errorCorrectionAttempts,
11996
+ success,
11997
+ options?.maxRetries ?? 10,
11998
+ signatureName
11999
+ );
12000
+ }
10609
12001
  }
10610
- currentVersion = delta.version;
10611
- buffer = mergeDeltas(buffer, delta);
10612
12002
  }
10613
- const selectedIndex = await selectFromSamples(
10614
- buffer,
10615
- {
10616
- resultPicker: options?.resultPicker
10617
- },
10618
- // Pass memory to enable function result selection
10619
- options?.mem,
10620
- options?.sessionId
10621
- );
10622
- const selectedResult = buffer[selectedIndex];
10623
- const result = selectedResult?.delta ?? {};
10624
- this.trace = { ...values, ...result };
10625
- return result;
10626
12003
  }
10627
12004
  async *streamingForward(ai, values, options) {
10628
12005
  if (!options?.resultPicker) {
@@ -11315,6 +12692,466 @@ function validateModels2(services) {
11315
12692
  }
11316
12693
 
11317
12694
  // dsp/optimizer.ts
12695
+ var axDefaultOptimizerMetricsConfig = {
12696
+ enabled: true,
12697
+ enabledCategories: [
12698
+ "optimization",
12699
+ "convergence",
12700
+ "resource_usage",
12701
+ "teacher_student",
12702
+ "checkpointing",
12703
+ "pareto"
12704
+ ],
12705
+ maxLabelLength: 100,
12706
+ samplingRate: 1
12707
+ };
12708
+ var globalOptimizerMetricsInstruments;
12709
+ var getOrCreateOptimizerMetricsInstruments = (meter) => {
12710
+ if (globalOptimizerMetricsInstruments) {
12711
+ return globalOptimizerMetricsInstruments;
12712
+ }
12713
+ if (meter) {
12714
+ globalOptimizerMetricsInstruments = createOptimizerMetricsInstruments(meter);
12715
+ return globalOptimizerMetricsInstruments;
12716
+ }
12717
+ return void 0;
12718
+ };
12719
+ var currentOptimizerMetricsConfig = axDefaultOptimizerMetricsConfig;
12720
+ var axUpdateOptimizerMetricsConfig = (config) => {
12721
+ currentOptimizerMetricsConfig = {
12722
+ ...currentOptimizerMetricsConfig,
12723
+ ...config
12724
+ };
12725
+ };
12726
+ var axGetOptimizerMetricsConfig = () => {
12727
+ return { ...currentOptimizerMetricsConfig };
12728
+ };
12729
+ var createOptimizerMetricsInstruments = (meter) => {
12730
+ return {
12731
+ // Optimization flow metrics
12732
+ optimizationLatencyHistogram: meter.createHistogram(
12733
+ "ax_optimizer_optimization_duration_ms",
12734
+ {
12735
+ description: "End-to-end duration of optimization runs",
12736
+ unit: "ms"
12737
+ }
12738
+ ),
12739
+ optimizationRequestsCounter: meter.createCounter(
12740
+ "ax_optimizer_optimization_requests_total",
12741
+ {
12742
+ description: "Total number of optimization requests"
12743
+ }
12744
+ ),
12745
+ optimizationErrorsCounter: meter.createCounter(
12746
+ "ax_optimizer_optimization_errors_total",
12747
+ {
12748
+ description: "Total number of failed optimizations"
12749
+ }
12750
+ ),
12751
+ // Convergence metrics
12752
+ convergenceRoundsHistogram: meter.createHistogram(
12753
+ "ax_optimizer_convergence_rounds",
12754
+ {
12755
+ description: "Number of rounds until convergence"
12756
+ }
12757
+ ),
12758
+ convergenceScoreGauge: meter.createGauge("ax_optimizer_convergence_score", {
12759
+ description: "Current best score during optimization"
12760
+ }),
12761
+ convergenceImprovementGauge: meter.createGauge(
12762
+ "ax_optimizer_convergence_improvement",
12763
+ {
12764
+ description: "Improvement in score from baseline"
12765
+ }
12766
+ ),
12767
+ stagnationRoundsGauge: meter.createGauge("ax_optimizer_stagnation_rounds", {
12768
+ description: "Number of rounds without improvement"
12769
+ }),
12770
+ earlyStoppingCounter: meter.createCounter(
12771
+ "ax_optimizer_early_stopping_total",
12772
+ {
12773
+ description: "Total number of early stopping events"
12774
+ }
12775
+ ),
12776
+ // Resource usage metrics
12777
+ tokenUsageCounter: meter.createCounter("ax_optimizer_token_usage_total", {
12778
+ description: "Total tokens used during optimization"
12779
+ }),
12780
+ costUsageCounter: meter.createCounter("ax_optimizer_cost_usage_total", {
12781
+ description: "Total cost incurred during optimization",
12782
+ unit: "$"
12783
+ }),
12784
+ memoryUsageGauge: meter.createGauge("ax_optimizer_memory_usage_bytes", {
12785
+ description: "Peak memory usage during optimization",
12786
+ unit: "By"
12787
+ }),
12788
+ optimizationDurationHistogram: meter.createHistogram(
12789
+ "ax_optimizer_duration_ms",
12790
+ {
12791
+ description: "Duration of optimization runs",
12792
+ unit: "ms"
12793
+ }
12794
+ ),
12795
+ // Teacher-student metrics
12796
+ teacherStudentUsageCounter: meter.createCounter(
12797
+ "ax_optimizer_teacher_student_usage_total",
12798
+ {
12799
+ description: "Total number of teacher-student interactions"
12800
+ }
12801
+ ),
12802
+ teacherStudentLatencyHistogram: meter.createHistogram(
12803
+ "ax_optimizer_teacher_student_latency_ms",
12804
+ {
12805
+ description: "Latency of teacher-student interactions",
12806
+ unit: "ms"
12807
+ }
12808
+ ),
12809
+ teacherStudentScoreImprovementGauge: meter.createGauge(
12810
+ "ax_optimizer_teacher_student_score_improvement",
12811
+ {
12812
+ description: "Score improvement from teacher-student interactions"
12813
+ }
12814
+ ),
12815
+ // Checkpointing metrics
12816
+ checkpointSaveCounter: meter.createCounter(
12817
+ "ax_optimizer_checkpoint_save_total",
12818
+ {
12819
+ description: "Total number of checkpoint saves"
12820
+ }
12821
+ ),
12822
+ checkpointLoadCounter: meter.createCounter(
12823
+ "ax_optimizer_checkpoint_load_total",
12824
+ {
12825
+ description: "Total number of checkpoint loads"
12826
+ }
12827
+ ),
12828
+ checkpointSaveLatencyHistogram: meter.createHistogram(
12829
+ "ax_optimizer_checkpoint_save_latency_ms",
12830
+ {
12831
+ description: "Latency of checkpoint save operations",
12832
+ unit: "ms"
12833
+ }
12834
+ ),
12835
+ checkpointLoadLatencyHistogram: meter.createHistogram(
12836
+ "ax_optimizer_checkpoint_load_latency_ms",
12837
+ {
12838
+ description: "Latency of checkpoint load operations",
12839
+ unit: "ms"
12840
+ }
12841
+ ),
12842
+ // Pareto optimization metrics
12843
+ paretoOptimizationsCounter: meter.createCounter(
12844
+ "ax_optimizer_pareto_optimizations_total",
12845
+ {
12846
+ description: "Total number of Pareto optimizations"
12847
+ }
12848
+ ),
12849
+ paretoFrontSizeHistogram: meter.createHistogram(
12850
+ "ax_optimizer_pareto_front_size",
12851
+ {
12852
+ description: "Size of Pareto frontier"
12853
+ }
12854
+ ),
12855
+ paretoHypervolumeGauge: meter.createGauge(
12856
+ "ax_optimizer_pareto_hypervolume",
12857
+ {
12858
+ description: "Hypervolume of Pareto frontier"
12859
+ }
12860
+ ),
12861
+ paretoSolutionsGeneratedHistogram: meter.createHistogram(
12862
+ "ax_optimizer_pareto_solutions_generated",
12863
+ {
12864
+ description: "Number of solutions generated for Pareto optimization"
12865
+ }
12866
+ ),
12867
+ // Program complexity metrics
12868
+ programInputFieldsGauge: meter.createGauge(
12869
+ "ax_optimizer_program_input_fields",
12870
+ {
12871
+ description: "Number of input fields in optimized program"
12872
+ }
12873
+ ),
12874
+ programOutputFieldsGauge: meter.createGauge(
12875
+ "ax_optimizer_program_output_fields",
12876
+ {
12877
+ description: "Number of output fields in optimized program"
12878
+ }
12879
+ ),
12880
+ examplesCountGauge: meter.createGauge("ax_optimizer_examples_count", {
12881
+ description: "Number of training examples used"
12882
+ }),
12883
+ validationSetSizeGauge: meter.createGauge(
12884
+ "ax_optimizer_validation_set_size",
12885
+ {
12886
+ description: "Size of validation set used"
12887
+ }
12888
+ ),
12889
+ // Performance metrics
12890
+ evaluationLatencyHistogram: meter.createHistogram(
12891
+ "ax_optimizer_evaluation_latency_ms",
12892
+ {
12893
+ description: "Latency of program evaluations",
12894
+ unit: "ms"
12895
+ }
12896
+ ),
12897
+ demoGenerationLatencyHistogram: meter.createHistogram(
12898
+ "ax_optimizer_demo_generation_latency_ms",
12899
+ {
12900
+ description: "Latency of demo generation",
12901
+ unit: "ms"
12902
+ }
12903
+ ),
12904
+ metricComputationLatencyHistogram: meter.createHistogram(
12905
+ "ax_optimizer_metric_computation_latency_ms",
12906
+ {
12907
+ description: "Latency of metric computation",
12908
+ unit: "ms"
12909
+ }
12910
+ ),
12911
+ // Configuration metrics
12912
+ optimizerTypeGauge: meter.createGauge("ax_optimizer_type", {
12913
+ description: "Type of optimizer being used"
12914
+ }),
12915
+ targetScoreGauge: meter.createGauge("ax_optimizer_target_score", {
12916
+ description: "Target score for optimization"
12917
+ }),
12918
+ maxRoundsGauge: meter.createGauge("ax_optimizer_max_rounds", {
12919
+ description: "Maximum rounds for optimization"
12920
+ })
12921
+ };
12922
+ };
12923
+ var sanitizeOptimizerLabels = (labels) => {
12924
+ const sanitized = {};
12925
+ for (const [key, value] of Object.entries(labels)) {
12926
+ if (value !== void 0 && value !== null) {
12927
+ const stringValue = String(value);
12928
+ const maxLength = currentOptimizerMetricsConfig.maxLabelLength;
12929
+ sanitized[key] = stringValue.length > maxLength ? stringValue.substring(0, maxLength) : stringValue;
12930
+ }
12931
+ }
12932
+ return sanitized;
12933
+ };
12934
+ var recordOptimizationMetric = (instruments, duration, success, optimizerType, programSignature) => {
12935
+ try {
12936
+ const labels = sanitizeOptimizerLabels({
12937
+ success: success.toString(),
12938
+ optimizer_type: optimizerType,
12939
+ ...programSignature ? { program_signature: programSignature } : {}
12940
+ });
12941
+ if (instruments.optimizationLatencyHistogram) {
12942
+ instruments.optimizationLatencyHistogram.record(duration, labels);
12943
+ }
12944
+ if (instruments.optimizationRequestsCounter) {
12945
+ instruments.optimizationRequestsCounter.add(1, labels);
12946
+ }
12947
+ if (!success && instruments.optimizationErrorsCounter) {
12948
+ instruments.optimizationErrorsCounter.add(1, labels);
12949
+ }
12950
+ } catch (error) {
12951
+ console.warn("Failed to record optimization metric:", error);
12952
+ }
12953
+ };
12954
+ var recordConvergenceMetric = (instruments, rounds, currentScore, improvement, stagnationRounds, optimizerType) => {
12955
+ try {
12956
+ const labels = sanitizeOptimizerLabels({
12957
+ optimizer_type: optimizerType
12958
+ });
12959
+ if (instruments.convergenceRoundsHistogram) {
12960
+ instruments.convergenceRoundsHistogram.record(rounds, labels);
12961
+ }
12962
+ if (instruments.convergenceScoreGauge) {
12963
+ instruments.convergenceScoreGauge.record(currentScore, labels);
12964
+ }
12965
+ if (instruments.convergenceImprovementGauge) {
12966
+ instruments.convergenceImprovementGauge.record(improvement, labels);
12967
+ }
12968
+ if (instruments.stagnationRoundsGauge) {
12969
+ instruments.stagnationRoundsGauge.record(stagnationRounds, labels);
12970
+ }
12971
+ } catch (error) {
12972
+ console.warn("Failed to record convergence metric:", error);
12973
+ }
12974
+ };
12975
+ var recordEarlyStoppingMetric = (instruments, reason, optimizerType) => {
12976
+ try {
12977
+ const labels = sanitizeOptimizerLabels({
12978
+ reason,
12979
+ optimizer_type: optimizerType
12980
+ });
12981
+ if (instruments.earlyStoppingCounter) {
12982
+ instruments.earlyStoppingCounter.add(1, labels);
12983
+ }
12984
+ } catch (error) {
12985
+ console.warn("Failed to record early stopping metric:", error);
12986
+ }
12987
+ };
12988
+ var recordResourceUsageMetric = (instruments, tokensUsed, costIncurred, optimizerType, memoryUsage) => {
12989
+ try {
12990
+ const labels = sanitizeOptimizerLabels({
12991
+ optimizer_type: optimizerType
12992
+ });
12993
+ if (instruments.tokenUsageCounter) {
12994
+ instruments.tokenUsageCounter.add(tokensUsed, labels);
12995
+ }
12996
+ if (instruments.costUsageCounter) {
12997
+ instruments.costUsageCounter.add(costIncurred, labels);
12998
+ }
12999
+ if (memoryUsage !== void 0 && instruments.memoryUsageGauge) {
13000
+ instruments.memoryUsageGauge.record(memoryUsage, labels);
13001
+ }
13002
+ } catch (error) {
13003
+ console.warn("Failed to record resource usage metric:", error);
13004
+ }
13005
+ };
13006
+ var recordOptimizationDurationMetric = (instruments, duration, optimizerType) => {
13007
+ try {
13008
+ const labels = sanitizeOptimizerLabels({
13009
+ optimizer_type: optimizerType
13010
+ });
13011
+ if (instruments.optimizationDurationHistogram) {
13012
+ instruments.optimizationDurationHistogram.record(duration, labels);
13013
+ }
13014
+ } catch (error) {
13015
+ console.warn("Failed to record optimization duration metric:", error);
13016
+ }
13017
+ };
13018
+ var recordTeacherStudentMetric = (instruments, latency, scoreImprovement, optimizerType) => {
13019
+ try {
13020
+ const labels = sanitizeOptimizerLabels({
13021
+ optimizer_type: optimizerType
13022
+ });
13023
+ if (instruments.teacherStudentUsageCounter) {
13024
+ instruments.teacherStudentUsageCounter.add(1, labels);
13025
+ }
13026
+ if (instruments.teacherStudentLatencyHistogram) {
13027
+ instruments.teacherStudentLatencyHistogram.record(latency, labels);
13028
+ }
13029
+ if (instruments.teacherStudentScoreImprovementGauge) {
13030
+ instruments.teacherStudentScoreImprovementGauge.record(
13031
+ scoreImprovement,
13032
+ labels
13033
+ );
13034
+ }
13035
+ } catch (error) {
13036
+ console.warn("Failed to record teacher-student metric:", error);
13037
+ }
13038
+ };
13039
+ var recordCheckpointMetric = (instruments, operation, latency, success, optimizerType) => {
13040
+ try {
13041
+ const labels = sanitizeOptimizerLabels({
13042
+ operation,
13043
+ success: success.toString(),
13044
+ optimizer_type: optimizerType
13045
+ });
13046
+ if (operation === "save") {
13047
+ if (instruments.checkpointSaveCounter) {
13048
+ instruments.checkpointSaveCounter.add(1, labels);
13049
+ }
13050
+ if (instruments.checkpointSaveLatencyHistogram) {
13051
+ instruments.checkpointSaveLatencyHistogram.record(latency, labels);
13052
+ }
13053
+ } else {
13054
+ if (instruments.checkpointLoadCounter) {
13055
+ instruments.checkpointLoadCounter.add(1, labels);
13056
+ }
13057
+ if (instruments.checkpointLoadLatencyHistogram) {
13058
+ instruments.checkpointLoadLatencyHistogram.record(latency, labels);
13059
+ }
13060
+ }
13061
+ } catch (error) {
13062
+ console.warn("Failed to record checkpoint metric:", error);
13063
+ }
13064
+ };
13065
+ var recordParetoMetric = (instruments, frontSize, solutionsGenerated, optimizerType, hypervolume) => {
13066
+ try {
13067
+ const labels = sanitizeOptimizerLabels({
13068
+ optimizer_type: optimizerType
13069
+ });
13070
+ if (instruments.paretoOptimizationsCounter) {
13071
+ instruments.paretoOptimizationsCounter.add(1, labels);
13072
+ }
13073
+ if (instruments.paretoFrontSizeHistogram) {
13074
+ instruments.paretoFrontSizeHistogram.record(frontSize, labels);
13075
+ }
13076
+ if (hypervolume !== void 0 && instruments.paretoHypervolumeGauge) {
13077
+ instruments.paretoHypervolumeGauge.record(hypervolume, labels);
13078
+ }
13079
+ if (instruments.paretoSolutionsGeneratedHistogram) {
13080
+ instruments.paretoSolutionsGeneratedHistogram.record(
13081
+ solutionsGenerated,
13082
+ labels
13083
+ );
13084
+ }
13085
+ } catch (error) {
13086
+ console.warn("Failed to record Pareto metric:", error);
13087
+ }
13088
+ };
13089
+ var recordProgramComplexityMetric = (instruments, inputFields, outputFields, examplesCount, validationSetSize, optimizerType) => {
13090
+ try {
13091
+ const labels = sanitizeOptimizerLabels({
13092
+ optimizer_type: optimizerType
13093
+ });
13094
+ if (instruments.programInputFieldsGauge) {
13095
+ instruments.programInputFieldsGauge.record(inputFields, labels);
13096
+ }
13097
+ if (instruments.programOutputFieldsGauge) {
13098
+ instruments.programOutputFieldsGauge.record(outputFields, labels);
13099
+ }
13100
+ if (instruments.examplesCountGauge) {
13101
+ instruments.examplesCountGauge.record(examplesCount, labels);
13102
+ }
13103
+ if (instruments.validationSetSizeGauge) {
13104
+ instruments.validationSetSizeGauge.record(validationSetSize, labels);
13105
+ }
13106
+ } catch (error) {
13107
+ console.warn("Failed to record program complexity metric:", error);
13108
+ }
13109
+ };
13110
+ var recordOptimizerPerformanceMetric = (instruments, metricType, duration, optimizerType) => {
13111
+ try {
13112
+ const labels = sanitizeOptimizerLabels({
13113
+ metric_type: metricType,
13114
+ optimizer_type: optimizerType
13115
+ });
13116
+ switch (metricType) {
13117
+ case "evaluation":
13118
+ if (instruments.evaluationLatencyHistogram) {
13119
+ instruments.evaluationLatencyHistogram.record(duration, labels);
13120
+ }
13121
+ break;
13122
+ case "demo_generation":
13123
+ if (instruments.demoGenerationLatencyHistogram) {
13124
+ instruments.demoGenerationLatencyHistogram.record(duration, labels);
13125
+ }
13126
+ break;
13127
+ case "metric_computation":
13128
+ if (instruments.metricComputationLatencyHistogram) {
13129
+ instruments.metricComputationLatencyHistogram.record(duration, labels);
13130
+ }
13131
+ break;
13132
+ }
13133
+ } catch (error) {
13134
+ console.warn("Failed to record optimizer performance metric:", error);
13135
+ }
13136
+ };
13137
+ var recordOptimizerConfigurationMetric = (instruments, optimizerType, targetScore, maxRounds) => {
13138
+ try {
13139
+ const labels = sanitizeOptimizerLabels({
13140
+ optimizer_type: optimizerType
13141
+ });
13142
+ if (instruments.optimizerTypeGauge) {
13143
+ instruments.optimizerTypeGauge.record(1, labels);
13144
+ }
13145
+ if (targetScore !== void 0 && instruments.targetScoreGauge) {
13146
+ instruments.targetScoreGauge.record(targetScore, labels);
13147
+ }
13148
+ if (maxRounds !== void 0 && instruments.maxRoundsGauge) {
13149
+ instruments.maxRoundsGauge.record(maxRounds, labels);
13150
+ }
13151
+ } catch (error) {
13152
+ console.warn("Failed to record optimizer configuration metric:", error);
13153
+ }
13154
+ };
11318
13155
  var AxDefaultCostTracker = class {
11319
13156
  tokenUsage = {};
11320
13157
  totalTokens = 0;
@@ -11388,6 +13225,8 @@ var AxBaseOptimizer = class {
11388
13225
  configurationHistory = [];
11389
13226
  // Common optimization statistics
11390
13227
  stats;
13228
+ // Metrics instruments
13229
+ metricsInstruments;
11391
13230
  constructor(args) {
11392
13231
  if (args.examples.length === 0) {
11393
13232
  throw new Error("No examples found");
@@ -11411,6 +13250,9 @@ var AxBaseOptimizer = class {
11411
13250
  maxTokens: 1e6
11412
13251
  });
11413
13252
  this.costTracker = args.costTracker ?? costTracker;
13253
+ this.metricsInstruments = getOrCreateOptimizerMetricsInstruments(
13254
+ axGlobals.meter
13255
+ );
11414
13256
  this.stats = this.initializeStats();
11415
13257
  }
11416
13258
  /**
@@ -11482,6 +13324,7 @@ var AxBaseOptimizer = class {
11482
13324
  patienceExhausted: reason.includes("improvement"),
11483
13325
  reason
11484
13326
  };
13327
+ this.recordEarlyStoppingMetrics(reason, "unknown");
11485
13328
  if (this.onEarlyStop) {
11486
13329
  this.onEarlyStop(reason, this.stats);
11487
13330
  }
@@ -11625,6 +13468,12 @@ var AxBaseOptimizer = class {
11625
13468
  }
11626
13469
  this.updateResourceUsage(startTime);
11627
13470
  this.stats.convergenceInfo.converged = true;
13471
+ this.recordParetoMetrics(
13472
+ paretoFront.length,
13473
+ allSolutions.length,
13474
+ "base_optimizer",
13475
+ hypervolume
13476
+ );
11628
13477
  const bestScore = paretoFront.length > 0 ? Math.max(
11629
13478
  ...paretoFront.map((sol) => Math.max(...Object.values(sol.scores)))
11630
13479
  ) : 0;
@@ -11931,23 +13780,36 @@ var AxBaseOptimizer = class {
11931
13780
  async saveCheckpoint(optimizerType, optimizerConfig, bestScore, bestConfiguration, optimizerState = {}, options) {
11932
13781
  const saveFn = options?.overrideCheckpointSave || this.checkpointSave;
11933
13782
  if (!saveFn) return void 0;
11934
- const checkpoint = {
11935
- version: "1.0.0",
11936
- timestamp: Date.now(),
11937
- optimizerType,
11938
- optimizerConfig,
11939
- currentRound: this.currentRound,
11940
- totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
11941
- bestScore,
11942
- bestConfiguration,
11943
- scoreHistory: [...this.scoreHistory],
11944
- configurationHistory: [...this.configurationHistory],
11945
- stats: { ...this.stats },
11946
- optimizerState,
11947
- examples: this.examples,
11948
- validationSet: this.validationSet
11949
- };
11950
- return await saveFn(checkpoint);
13783
+ const startTime = Date.now();
13784
+ let success = false;
13785
+ let checkpointId;
13786
+ try {
13787
+ const checkpoint = {
13788
+ version: "1.0.0",
13789
+ timestamp: Date.now(),
13790
+ optimizerType,
13791
+ optimizerConfig,
13792
+ currentRound: this.currentRound,
13793
+ totalRounds: this.stats.resourceUsage.totalTime > 0 ? this.currentRound : 0,
13794
+ bestScore,
13795
+ bestConfiguration,
13796
+ scoreHistory: [...this.scoreHistory],
13797
+ configurationHistory: [...this.configurationHistory],
13798
+ stats: { ...this.stats },
13799
+ optimizerState,
13800
+ examples: this.examples,
13801
+ validationSet: this.validationSet
13802
+ };
13803
+ checkpointId = await saveFn(checkpoint);
13804
+ success = true;
13805
+ } catch (error) {
13806
+ success = false;
13807
+ throw error;
13808
+ } finally {
13809
+ const latency = Date.now() - startTime;
13810
+ this.recordCheckpointMetrics("save", latency, success, optimizerType);
13811
+ }
13812
+ return checkpointId;
11951
13813
  }
11952
13814
  /**
11953
13815
  * Load optimization state from checkpoint
@@ -11955,7 +13817,20 @@ var AxBaseOptimizer = class {
11955
13817
  async loadCheckpoint(checkpointId, options) {
11956
13818
  const loadFn = options?.overrideCheckpointLoad || this.checkpointLoad;
11957
13819
  if (!loadFn) return null;
11958
- return await loadFn(checkpointId);
13820
+ const startTime = Date.now();
13821
+ let success = false;
13822
+ let checkpoint = null;
13823
+ try {
13824
+ checkpoint = await loadFn(checkpointId);
13825
+ success = checkpoint !== null;
13826
+ } catch (error) {
13827
+ success = false;
13828
+ throw error;
13829
+ } finally {
13830
+ const latency = Date.now() - startTime;
13831
+ this.recordCheckpointMetrics("load", latency, success, "unknown");
13832
+ }
13833
+ return checkpoint;
11959
13834
  }
11960
13835
  /**
11961
13836
  * Restore optimizer state from checkpoint
@@ -12032,6 +13907,128 @@ var AxBaseOptimizer = class {
12032
13907
  }
12033
13908
  return this.verbose ?? true;
12034
13909
  }
13910
+ /**
13911
+ * Record optimization start metrics
13912
+ */
13913
+ recordOptimizationStart(optimizerType, programSignature) {
13914
+ if (!this.metricsInstruments) return;
13915
+ if (programSignature) {
13916
+ const inputFields = (programSignature.match(/input:/g) || []).length;
13917
+ const outputFields = (programSignature.match(/output:/g) || []).length;
13918
+ recordProgramComplexityMetric(
13919
+ this.metricsInstruments,
13920
+ inputFields,
13921
+ outputFields,
13922
+ this.examples.length,
13923
+ this.getValidationSet().length,
13924
+ optimizerType
13925
+ );
13926
+ }
13927
+ recordOptimizerConfigurationMetric(
13928
+ this.metricsInstruments,
13929
+ optimizerType,
13930
+ this.targetScore,
13931
+ void 0
13932
+ // maxRounds would be set by concrete optimizers
13933
+ );
13934
+ }
13935
+ /**
13936
+ * Record optimization completion metrics
13937
+ */
13938
+ recordOptimizationComplete(duration, success, optimizerType, programSignature) {
13939
+ if (!this.metricsInstruments) return;
13940
+ recordOptimizationMetric(
13941
+ this.metricsInstruments,
13942
+ duration,
13943
+ success,
13944
+ optimizerType,
13945
+ programSignature
13946
+ );
13947
+ recordOptimizationDurationMetric(
13948
+ this.metricsInstruments,
13949
+ duration,
13950
+ optimizerType
13951
+ );
13952
+ const currentCost = this.costTracker?.getCurrentCost() ?? 0;
13953
+ const totalTokens = this.costTracker?.getTotalTokens() ?? 0;
13954
+ recordResourceUsageMetric(
13955
+ this.metricsInstruments,
13956
+ totalTokens,
13957
+ currentCost,
13958
+ optimizerType
13959
+ );
13960
+ }
13961
+ /**
13962
+ * Record convergence metrics
13963
+ */
13964
+ recordConvergenceMetrics(rounds, currentScore, improvement, stagnationRounds, optimizerType) {
13965
+ if (!this.metricsInstruments) return;
13966
+ recordConvergenceMetric(
13967
+ this.metricsInstruments,
13968
+ rounds,
13969
+ currentScore,
13970
+ improvement,
13971
+ stagnationRounds,
13972
+ optimizerType
13973
+ );
13974
+ }
13975
+ /**
13976
+ * Record early stopping metrics
13977
+ */
13978
+ recordEarlyStoppingMetrics(reason, optimizerType) {
13979
+ if (!this.metricsInstruments) return;
13980
+ recordEarlyStoppingMetric(this.metricsInstruments, reason, optimizerType);
13981
+ }
13982
+ /**
13983
+ * Record teacher-student interaction metrics
13984
+ */
13985
+ recordTeacherStudentMetrics(latency, scoreImprovement, optimizerType) {
13986
+ if (!this.metricsInstruments) return;
13987
+ recordTeacherStudentMetric(
13988
+ this.metricsInstruments,
13989
+ latency,
13990
+ scoreImprovement,
13991
+ optimizerType
13992
+ );
13993
+ }
13994
+ /**
13995
+ * Record checkpoint metrics
13996
+ */
13997
+ recordCheckpointMetrics(operation, latency, success, optimizerType) {
13998
+ if (!this.metricsInstruments) return;
13999
+ recordCheckpointMetric(
14000
+ this.metricsInstruments,
14001
+ operation,
14002
+ latency,
14003
+ success,
14004
+ optimizerType
14005
+ );
14006
+ }
14007
+ /**
14008
+ * Record Pareto optimization metrics
14009
+ */
14010
+ recordParetoMetrics(frontSize, solutionsGenerated, optimizerType, hypervolume) {
14011
+ if (!this.metricsInstruments) return;
14012
+ recordParetoMetric(
14013
+ this.metricsInstruments,
14014
+ frontSize,
14015
+ solutionsGenerated,
14016
+ optimizerType,
14017
+ hypervolume
14018
+ );
14019
+ }
14020
+ /**
14021
+ * Record performance metrics
14022
+ */
14023
+ recordPerformanceMetrics(metricType, duration, optimizerType) {
14024
+ if (!this.metricsInstruments) return;
14025
+ recordOptimizerPerformanceMetric(
14026
+ this.metricsInstruments,
14027
+ metricType,
14028
+ duration,
14029
+ optimizerType
14030
+ );
14031
+ }
12035
14032
  };
12036
14033
 
12037
14034
  // db/base.ts
@@ -17573,10 +19570,15 @@ export {
17573
19570
  axAITogetherDefaultConfig,
17574
19571
  axBaseAIDefaultConfig,
17575
19572
  axBaseAIDefaultCreativeConfig,
19573
+ axCheckMetricsHealth,
17576
19574
  axCreateDefaultLogger,
17577
19575
  axCreateDefaultTextLogger,
17578
19576
  axCreateOptimizerLogger,
19577
+ axDefaultMetricsConfig,
17579
19578
  axDefaultOptimizerLogger,
19579
+ axDefaultOptimizerMetricsConfig,
19580
+ axGetMetricsConfig,
19581
+ axGetOptimizerMetricsConfig,
17580
19582
  axGlobals,
17581
19583
  axModelInfoAnthropic,
17582
19584
  axModelInfoCohere,
@@ -17592,6 +19594,8 @@ export {
17592
19594
  axModelInfoTogether,
17593
19595
  axSpanAttributes,
17594
19596
  axSpanEvents,
19597
+ axUpdateMetricsConfig,
19598
+ axUpdateOptimizerMetricsConfig,
17595
19599
  axValidateChatRequestMessage,
17596
19600
  axValidateChatResponseResult,
17597
19601
  f,