@dudousxd/nestjs-agent-telescope 0.7.0 → 0.8.0

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/dist/index.js CHANGED
@@ -492,7 +492,180 @@ function agentDashboard(opts = {}) {
492
492
  ]
493
493
  }
494
494
  ]
495
- }
495
+ },
496
+ {
497
+ // RAG. Fed by the `aviary:rag:retrieval` telemetry `@dudousxd/nestjs-agent-rag` emits, NOT
498
+ // derived from tool-call rows: a tool call that retrieved nothing and one that retrieved
499
+ // five perfect passages are the same row with the same `ok` status, so every number here
500
+ // would have been unanswerable from that side.
501
+ title: "Retrieval",
502
+ cols: 3,
503
+ panels: [
504
+ {
505
+ kind: "stat",
506
+ title: "Retrievals",
507
+ data: {
508
+ provider: "agent.rag.retrievals"
509
+ }
510
+ },
511
+ {
512
+ kind: "stat",
513
+ title: "Zero-hit rate",
514
+ data: {
515
+ provider: "agent.rag.zeroHitRate"
516
+ },
517
+ format: "percent"
518
+ },
519
+ {
520
+ kind: "stat",
521
+ title: "Passages per retrieval",
522
+ data: {
523
+ provider: "agent.rag.chunks"
524
+ },
525
+ format: "number"
526
+ },
527
+ {
528
+ // A real histogram, unlike the run-duration pair above: retrieval events carry the raw
529
+ // per-call duration, so there ARE samples to bucket and markers to place.
530
+ kind: "distribution",
531
+ title: "Retrieval latency",
532
+ data: {
533
+ provider: "agent.rag.latency"
534
+ },
535
+ markers: [
536
+ "p50",
537
+ "p95",
538
+ "p99"
539
+ ],
540
+ format: "duration"
541
+ },
542
+ {
543
+ // Bound to ONE retriever kind on purpose — a cosine similarity, a BM25 score and an RRF
544
+ // rank score share no scale, so a histogram over all of them has bins that mean a
545
+ // different thing per bar. See `toScoreDistribution`.
546
+ kind: "distribution",
547
+ title: "Top score (dense)",
548
+ data: {
549
+ provider: "agent.rag.scores",
550
+ query: {
551
+ retriever: "embedding"
552
+ }
553
+ },
554
+ markers: [
555
+ "p50",
556
+ "p95"
557
+ ],
558
+ format: "number"
559
+ },
560
+ {
561
+ kind: "timeseries",
562
+ title: "Retrievals & zero-hits",
563
+ data: {
564
+ provider: "agent.rag.trend"
565
+ },
566
+ series: [
567
+ "retrievals",
568
+ "zeroHits"
569
+ ],
570
+ style: "stacked"
571
+ }
572
+ ]
573
+ },
574
+ {
575
+ title: "Retrieval sources",
576
+ cols: 2,
577
+ panels: [
578
+ {
579
+ kind: "breakdown",
580
+ title: "Retrievals by store",
581
+ data: {
582
+ provider: "agent.rag.byStore"
583
+ },
584
+ style: "donut"
585
+ },
586
+ {
587
+ kind: "breakdown",
588
+ title: "Retrievals by retriever",
589
+ data: {
590
+ provider: "agent.rag.byRetriever"
591
+ },
592
+ style: "donut"
593
+ },
594
+ {
595
+ kind: "table",
596
+ title: "By collection",
597
+ data: {
598
+ provider: "agent.rag.byCollection"
599
+ },
600
+ columns: [
601
+ {
602
+ key: "collection",
603
+ label: "Collection"
604
+ },
605
+ {
606
+ key: "store",
607
+ label: "Store"
608
+ },
609
+ {
610
+ key: "retrievals",
611
+ label: "Retrievals"
612
+ },
613
+ {
614
+ key: "zeroHits",
615
+ label: "Zero-hits"
616
+ },
617
+ {
618
+ key: "p95Ms",
619
+ label: "p95 (ms)"
620
+ },
621
+ {
622
+ key: "meanTopScore",
623
+ label: "Mean top score"
624
+ }
625
+ ]
626
+ },
627
+ {
628
+ kind: "table",
629
+ title: "Slowest retrievals",
630
+ data: {
631
+ provider: "agent.rag.slowest"
632
+ },
633
+ // Seven columns, matching the recent-runs table's width: this is the widest a table can
634
+ // get here before it overflows its card.
635
+ columns: [
636
+ {
637
+ key: "at",
638
+ label: "When"
639
+ },
640
+ {
641
+ key: "retriever",
642
+ label: "Retriever"
643
+ },
644
+ {
645
+ key: "store",
646
+ label: "Store"
647
+ },
648
+ {
649
+ key: "collection",
650
+ label: "Collection"
651
+ },
652
+ {
653
+ key: "chunks",
654
+ label: "Passages"
655
+ },
656
+ {
657
+ key: "topScore",
658
+ label: "Top score"
659
+ },
660
+ {
661
+ key: "durationMs",
662
+ label: "Duration (ms)"
663
+ }
664
+ ]
665
+ }
666
+ ]
667
+ },
668
+ ...opts.sections ?? []
496
669
  ]
497
670
  };
498
671
  }
@@ -1066,22 +1239,478 @@ var AgentTelescopeWatcher = class {
1066
1239
  }
1067
1240
  };
1068
1241
 
1242
+ // src/rag-data-providers.ts
1243
+ import { TELESCOPE_STORAGE as TELESCOPE_STORAGE2 } from "@dudousxd/nestjs-telescope";
1244
+
1245
+ // src/rag-telescope.watcher.ts
1246
+ import { subscribe as subscribe2, unsubscribe as unsubscribe2 } from "node:diagnostics_channel";
1247
+ import { channelName as channelName2, claimDiagnostics as claimDiagnostics2 } from "@dudousxd/nestjs-diagnostics";
1248
+ var RAG_LIB = "rag";
1249
+ var RETRIEVAL_EVENT = "retrieval";
1250
+ var RAG_ENTRY_TYPE = "agent-rag";
1251
+ function isEnvelope(message) {
1252
+ return typeof message === "object" && message !== null && typeof Reflect.get(message, "payload") === "object" && Reflect.get(message, "payload") !== null;
1253
+ }
1254
+ __name(isEnvelope, "isEnvelope");
1255
+ var RagTelescopeWatcher = class {
1256
+ static {
1257
+ __name(this, "RagTelescopeWatcher");
1258
+ }
1259
+ type = RAG_ENTRY_TYPE;
1260
+ disposers = [];
1261
+ register(ctx) {
1262
+ this.disposers.push(claimDiagnostics2(RAG_LIB, [
1263
+ RETRIEVAL_EVENT
1264
+ ]));
1265
+ const channel = channelName2(RAG_LIB, RETRIEVAL_EVENT);
1266
+ const onMessage = /* @__PURE__ */ __name((message) => {
1267
+ if (!isEnvelope(message)) {
1268
+ return;
1269
+ }
1270
+ ctx.record({
1271
+ type: RAG_ENTRY_TYPE,
1272
+ content: {
1273
+ event: RETRIEVAL_EVENT,
1274
+ ...message.payload,
1275
+ ...message.durationMs !== void 0 ? {
1276
+ durationMs: message.durationMs
1277
+ } : {}
1278
+ },
1279
+ // Tagged by store and retriever kind so the Entries screen can filter to "every retrieval
1280
+ // pgvector served" without a provider — the same tag-per-dimension the agent watcher uses.
1281
+ tags: tagsOf(message.payload)
1282
+ });
1283
+ }, "onMessage");
1284
+ subscribe2(channel, onMessage);
1285
+ this.disposers.push(() => unsubscribe2(channel, onMessage));
1286
+ }
1287
+ /** Detach the subscription and release the diagnostics claim (e.g. on module destroy). */
1288
+ dispose() {
1289
+ while (this.disposers.length) this.disposers.pop()?.();
1290
+ }
1291
+ };
1292
+ function tagsOf(payload) {
1293
+ const tags = [
1294
+ RETRIEVAL_EVENT
1295
+ ];
1296
+ if (typeof payload.retriever === "string") {
1297
+ tags.push(`retriever:${payload.retriever}`);
1298
+ }
1299
+ if (typeof payload.store === "string") {
1300
+ tags.push(`store:${payload.store}`);
1301
+ }
1302
+ if (payload.zeroHit === true) {
1303
+ tags.push("zero-hit");
1304
+ }
1305
+ if (payload.failed === true) {
1306
+ tags.push("failed");
1307
+ }
1308
+ return tags;
1309
+ }
1310
+ __name(tagsOf, "tagsOf");
1311
+
1312
+ // src/rag-data-providers.ts
1313
+ var RETRIEVAL_WINDOW = 5e3;
1314
+ var TABLE_LIMIT = 10;
1315
+ var TREND_HOURS = 24;
1316
+ var NO_VALUE2 = "\u2014";
1317
+ function isRecord2(value) {
1318
+ return typeof value === "object" && value !== null;
1319
+ }
1320
+ __name(isRecord2, "isRecord");
1321
+ function readString(source, key) {
1322
+ const value = source[key];
1323
+ return typeof value === "string" ? value : null;
1324
+ }
1325
+ __name(readString, "readString");
1326
+ function readNumber(source, key) {
1327
+ const value = source[key];
1328
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
1329
+ }
1330
+ __name(readNumber, "readNumber");
1331
+ function isEntryStorage(value) {
1332
+ return isRecord2(value) && typeof value.get === "function";
1333
+ }
1334
+ __name(isEntryStorage, "isEntryStorage");
1335
+ function toRagRetrieval(entry) {
1336
+ if (!isRecord2(entry) || !isRecord2(entry.content)) {
1337
+ return null;
1338
+ }
1339
+ const content = entry.content;
1340
+ const retriever = readString(content, "retriever");
1341
+ if (retriever === null) {
1342
+ return null;
1343
+ }
1344
+ const chunks = readNumber(content, "chunks") ?? 0;
1345
+ const createdAt = entry.createdAt;
1346
+ return {
1347
+ at: createdAt instanceof Date ? createdAt : /* @__PURE__ */ new Date(0),
1348
+ retriever,
1349
+ store: readString(content, "store"),
1350
+ collection: readString(content, "collection"),
1351
+ chunks,
1352
+ zeroHit: content.zeroHit === true || chunks === 0,
1353
+ topScore: readNumber(content, "topScore"),
1354
+ durationMs: readNumber(content, "durationMs"),
1355
+ failed: content.failed === true
1356
+ };
1357
+ }
1358
+ __name(toRagRetrieval, "toRagRetrieval");
1359
+ async function readRetrievals(storage) {
1360
+ if (!isEntryStorage(storage)) {
1361
+ return [];
1362
+ }
1363
+ const page = await storage.get({
1364
+ type: RAG_ENTRY_TYPE,
1365
+ limit: RETRIEVAL_WINDOW
1366
+ });
1367
+ const retrievals = [];
1368
+ for (const entry of page.data) {
1369
+ const retrieval = toRagRetrieval(entry);
1370
+ if (retrieval !== null) {
1371
+ retrievals.push(retrieval);
1372
+ }
1373
+ }
1374
+ return retrievals;
1375
+ }
1376
+ __name(readRetrievals, "readRetrievals");
1377
+ function retrievalStorage(ctx) {
1378
+ try {
1379
+ return ctx.moduleRef.get(TELESCOPE_STORAGE2, {
1380
+ strict: false
1381
+ });
1382
+ } catch {
1383
+ return void 0;
1384
+ }
1385
+ }
1386
+ __name(retrievalStorage, "retrievalStorage");
1387
+ function percentile(samples, fraction) {
1388
+ if (samples.length === 0) {
1389
+ return null;
1390
+ }
1391
+ const sorted = [
1392
+ ...samples
1393
+ ].sort((a, b) => a - b);
1394
+ const rank = Math.ceil(fraction * sorted.length);
1395
+ return sorted[Math.min(Math.max(rank, 1), sorted.length) - 1] ?? null;
1396
+ }
1397
+ __name(percentile, "percentile");
1398
+ function round(value, places) {
1399
+ const factor = 10 ** places;
1400
+ return Math.round(value * factor) / factor;
1401
+ }
1402
+ __name(round, "round");
1403
+ function zeroHitRate(retrievals) {
1404
+ if (retrievals.length === 0) {
1405
+ return 0;
1406
+ }
1407
+ const zeroHits = retrievals.filter((retrieval) => retrieval.zeroHit).length;
1408
+ return round(zeroHits / retrievals.length, 4);
1409
+ }
1410
+ __name(zeroHitRate, "zeroHitRate");
1411
+ function meanChunks(retrievals) {
1412
+ if (retrievals.length === 0) {
1413
+ return 0;
1414
+ }
1415
+ const total = retrievals.reduce((sum, retrieval) => sum + retrieval.chunks, 0);
1416
+ return round(total / retrievals.length, 2);
1417
+ }
1418
+ __name(meanChunks, "meanChunks");
1419
+ var LATENCY_EDGES = [
1420
+ 10,
1421
+ 25,
1422
+ 50,
1423
+ 100,
1424
+ 250,
1425
+ 500,
1426
+ 1e3,
1427
+ 2500,
1428
+ 5e3
1429
+ ];
1430
+ function latencyLabel(index) {
1431
+ const upper = LATENCY_EDGES[index];
1432
+ if (upper === void 0) {
1433
+ return `\u2265${LATENCY_EDGES[LATENCY_EDGES.length - 1] ?? 0}ms`;
1434
+ }
1435
+ return `${index === 0 ? 0 : LATENCY_EDGES[index - 1] ?? 0}\u2013${upper}ms`;
1436
+ }
1437
+ __name(latencyLabel, "latencyLabel");
1438
+ function toLatencyDistribution(retrievals) {
1439
+ const samples = [];
1440
+ const counts = new Array(LATENCY_EDGES.length + 1).fill(0);
1441
+ for (const { durationMs } of retrievals) {
1442
+ if (durationMs === null) {
1443
+ continue;
1444
+ }
1445
+ samples.push(durationMs);
1446
+ const found = LATENCY_EDGES.findIndex((edge) => durationMs < edge);
1447
+ const index = found === -1 ? LATENCY_EDGES.length : found;
1448
+ counts[index] = (counts[index] ?? 0) + 1;
1449
+ }
1450
+ const buckets = counts.map((count, index) => ({
1451
+ label: latencyLabel(index),
1452
+ count
1453
+ }));
1454
+ const p50 = percentile(samples, 0.5);
1455
+ const p95 = percentile(samples, 0.95);
1456
+ const p99 = percentile(samples, 0.99);
1457
+ return {
1458
+ buckets,
1459
+ ...p50 !== null ? {
1460
+ p50
1461
+ } : {},
1462
+ ...p95 !== null ? {
1463
+ p95
1464
+ } : {},
1465
+ ...p99 !== null ? {
1466
+ p99
1467
+ } : {}
1468
+ };
1469
+ }
1470
+ __name(toLatencyDistribution, "toLatencyDistribution");
1471
+ var SCORE_BINS = 10;
1472
+ function toScoreDistribution(retrievals, retriever) {
1473
+ const samples = [];
1474
+ const counts = new Array(SCORE_BINS).fill(0);
1475
+ for (const retrieval of retrievals) {
1476
+ if (retrieval.retriever !== retriever || retrieval.topScore === null) {
1477
+ continue;
1478
+ }
1479
+ samples.push(retrieval.topScore);
1480
+ const clamped = Math.min(Math.max(retrieval.topScore, 0), 1);
1481
+ const index = Math.min(Math.floor(clamped * SCORE_BINS), SCORE_BINS - 1);
1482
+ counts[index] = (counts[index] ?? 0) + 1;
1483
+ }
1484
+ const buckets = counts.map((count, index) => ({
1485
+ label: `${round(index / SCORE_BINS, 1)}\u2013${round((index + 1) / SCORE_BINS, 1)}`,
1486
+ count
1487
+ }));
1488
+ const p50 = percentile(samples, 0.5);
1489
+ const p95 = percentile(samples, 0.95);
1490
+ return {
1491
+ buckets,
1492
+ ...p50 !== null ? {
1493
+ p50: round(p50, 4)
1494
+ } : {},
1495
+ ...p95 !== null ? {
1496
+ p95: round(p95, 4)
1497
+ } : {}
1498
+ };
1499
+ }
1500
+ __name(toScoreDistribution, "toScoreDistribution");
1501
+ function hourStart(at) {
1502
+ return Math.floor(at.getTime() / 36e5) * 36e5;
1503
+ }
1504
+ __name(hourStart, "hourStart");
1505
+ function toRetrievalTrendRows(retrievals, now = /* @__PURE__ */ new Date()) {
1506
+ const latest = hourStart(now);
1507
+ const earliest = latest - (TREND_HOURS - 1) * 36e5;
1508
+ const buckets = /* @__PURE__ */ new Map();
1509
+ for (let hour = earliest; hour <= latest; hour += 36e5) {
1510
+ buckets.set(hour, {
1511
+ retrievals: 0,
1512
+ zeroHits: 0
1513
+ });
1514
+ }
1515
+ for (const retrieval of retrievals) {
1516
+ const bucket = buckets.get(hourStart(retrieval.at));
1517
+ if (bucket === void 0) {
1518
+ continue;
1519
+ }
1520
+ bucket.retrievals += 1;
1521
+ if (retrieval.zeroHit) {
1522
+ bucket.zeroHits += 1;
1523
+ }
1524
+ }
1525
+ return [
1526
+ ...buckets.entries()
1527
+ ].map(([hour, counts]) => ({
1528
+ label: `${new Date(hour).toISOString().slice(11, 13)}:00`,
1529
+ retrievals: counts.retrievals,
1530
+ zeroHits: counts.zeroHits
1531
+ }));
1532
+ }
1533
+ __name(toRetrievalTrendRows, "toRetrievalTrendRows");
1534
+ function segmentsBy(retrievals, pick) {
1535
+ const counts = /* @__PURE__ */ new Map();
1536
+ for (const retrieval of retrievals) {
1537
+ const label = pick(retrieval) ?? NO_VALUE2;
1538
+ counts.set(label, (counts.get(label) ?? 0) + 1);
1539
+ }
1540
+ return [
1541
+ ...counts.entries()
1542
+ ].map(([label, value]) => ({
1543
+ label,
1544
+ value
1545
+ })).sort((a, b) => b.value - a.value);
1546
+ }
1547
+ __name(segmentsBy, "segmentsBy");
1548
+ function toStoreSegments(retrievals) {
1549
+ return segmentsBy(retrievals, (retrieval) => retrieval.store);
1550
+ }
1551
+ __name(toStoreSegments, "toStoreSegments");
1552
+ function toRetrieverSegments(retrievals) {
1553
+ return segmentsBy(retrievals, (retrieval) => retrieval.retriever);
1554
+ }
1555
+ __name(toRetrieverSegments, "toRetrieverSegments");
1556
+ function toCollectionRows(retrievals, limit = TABLE_LIMIT) {
1557
+ const groups = /* @__PURE__ */ new Map();
1558
+ for (const retrieval of retrievals) {
1559
+ const key = retrieval.collection ?? NO_VALUE2;
1560
+ const group = groups.get(key);
1561
+ if (group === void 0) {
1562
+ groups.set(key, [
1563
+ retrieval
1564
+ ]);
1565
+ } else {
1566
+ group.push(retrieval);
1567
+ }
1568
+ }
1569
+ return [
1570
+ ...groups.entries()
1571
+ ].map(([collection, group]) => {
1572
+ const durations = [];
1573
+ const scores = [];
1574
+ for (const retrieval of group) {
1575
+ if (retrieval.durationMs !== null) {
1576
+ durations.push(retrieval.durationMs);
1577
+ }
1578
+ if (retrieval.topScore !== null) {
1579
+ scores.push(retrieval.topScore);
1580
+ }
1581
+ }
1582
+ const p95 = percentile(durations, 0.95);
1583
+ const meanScore = scores.length === 0 ? null : scores.reduce((sum, score) => sum + score, 0) / scores.length;
1584
+ return {
1585
+ collection,
1586
+ store: group[0]?.store ?? NO_VALUE2,
1587
+ retrievals: group.length,
1588
+ zeroHits: group.filter((retrieval) => retrieval.zeroHit).length,
1589
+ p95Ms: p95 === null ? NO_VALUE2 : Math.round(p95),
1590
+ meanTopScore: meanScore === null ? NO_VALUE2 : round(meanScore, 3)
1591
+ };
1592
+ }).sort((a, b) => b.retrievals - a.retrievals).slice(0, limit);
1593
+ }
1594
+ __name(toCollectionRows, "toCollectionRows");
1595
+ function toSlowestRows(retrievals, limit = TABLE_LIMIT) {
1596
+ return retrievals.filter((retrieval) => retrieval.durationMs !== null).sort((a, b) => (b.durationMs ?? 0) - (a.durationMs ?? 0)).slice(0, limit).map((retrieval) => ({
1597
+ at: retrieval.at.toISOString(),
1598
+ retriever: retrieval.retriever,
1599
+ store: retrieval.store ?? NO_VALUE2,
1600
+ collection: retrieval.collection ?? NO_VALUE2,
1601
+ chunks: retrieval.chunks,
1602
+ topScore: retrieval.topScore === null ? NO_VALUE2 : round(retrieval.topScore, 3),
1603
+ durationMs: retrieval.durationMs === null ? NO_VALUE2 : Math.round(retrieval.durationMs)
1604
+ }));
1605
+ }
1606
+ __name(toSlowestRows, "toSlowestRows");
1607
+ function retrievalProvider(name, format) {
1608
+ return {
1609
+ name,
1610
+ async resolve(query, ctx) {
1611
+ return format(await readRetrievals(retrievalStorage(ctx)), query);
1612
+ }
1613
+ };
1614
+ }
1615
+ __name(retrievalProvider, "retrievalProvider");
1616
+ function ragRetrievalsProvider() {
1617
+ return retrievalProvider("agent.rag.retrievals", (retrievals) => ({
1618
+ value: retrievals.length
1619
+ }));
1620
+ }
1621
+ __name(ragRetrievalsProvider, "ragRetrievalsProvider");
1622
+ function ragZeroHitRateProvider() {
1623
+ return retrievalProvider("agent.rag.zeroHitRate", (retrievals) => ({
1624
+ value: zeroHitRate(retrievals)
1625
+ }));
1626
+ }
1627
+ __name(ragZeroHitRateProvider, "ragZeroHitRateProvider");
1628
+ function ragChunksProvider() {
1629
+ return retrievalProvider("agent.rag.chunks", (retrievals) => ({
1630
+ value: meanChunks(retrievals)
1631
+ }));
1632
+ }
1633
+ __name(ragChunksProvider, "ragChunksProvider");
1634
+ function ragLatencyProvider() {
1635
+ return retrievalProvider("agent.rag.latency", toLatencyDistribution);
1636
+ }
1637
+ __name(ragLatencyProvider, "ragLatencyProvider");
1638
+ function ragScoresProvider() {
1639
+ return retrievalProvider("agent.rag.scores", (retrievals, query) => {
1640
+ const requested = query?.retriever;
1641
+ return toScoreDistribution(retrievals, typeof requested === "string" ? requested : "embedding");
1642
+ });
1643
+ }
1644
+ __name(ragScoresProvider, "ragScoresProvider");
1645
+ function ragTrendProvider() {
1646
+ return retrievalProvider("agent.rag.trend", (retrievals) => ({
1647
+ rows: toRetrievalTrendRows(retrievals)
1648
+ }));
1649
+ }
1650
+ __name(ragTrendProvider, "ragTrendProvider");
1651
+ function ragStoreBreakdownProvider() {
1652
+ return retrievalProvider("agent.rag.byStore", (retrievals) => ({
1653
+ segments: toStoreSegments(retrievals)
1654
+ }));
1655
+ }
1656
+ __name(ragStoreBreakdownProvider, "ragStoreBreakdownProvider");
1657
+ function ragRetrieverBreakdownProvider() {
1658
+ return retrievalProvider("agent.rag.byRetriever", (retrievals) => ({
1659
+ segments: toRetrieverSegments(retrievals)
1660
+ }));
1661
+ }
1662
+ __name(ragRetrieverBreakdownProvider, "ragRetrieverBreakdownProvider");
1663
+ function ragCollectionsTableProvider() {
1664
+ return retrievalProvider("agent.rag.byCollection", (retrievals) => ({
1665
+ rows: toCollectionRows(retrievals)
1666
+ }));
1667
+ }
1668
+ __name(ragCollectionsTableProvider, "ragCollectionsTableProvider");
1669
+ function ragSlowestTableProvider() {
1670
+ return retrievalProvider("agent.rag.slowest", (retrievals) => ({
1671
+ rows: toSlowestRows(retrievals)
1672
+ }));
1673
+ }
1674
+ __name(ragSlowestTableProvider, "ragSlowestTableProvider");
1675
+
1069
1676
  // src/agent-telescope.extension.ts
1677
+ var RESERVED_PROVIDER_PREFIX = "agent.";
1070
1678
  function agentTelescopeExtension(opts = {}) {
1679
+ const hostProviders = opts.providers ?? [];
1680
+ const reserved = hostProviders.filter((provider) => provider.name.startsWith(RESERVED_PROVIDER_PREFIX));
1681
+ if (reserved.length > 0) {
1682
+ throw new Error(`agentTelescopeExtension: host-contributed data providers may not use the reserved "${RESERVED_PROVIDER_PREFIX}" prefix \u2014 rename ${reserved.map((provider) => `"${provider.name}"`).join(", ")} to your own namespace.`);
1683
+ }
1071
1684
  return defineTelescopeExtension({
1072
1685
  name: "agent",
1073
1686
  watchers: /* @__PURE__ */ __name(() => [
1074
- new AgentTelescopeWatcher()
1687
+ new AgentTelescopeWatcher(),
1688
+ new RagTelescopeWatcher()
1075
1689
  ], "watchers"),
1076
1690
  entryTypes: /* @__PURE__ */ __name(() => [
1077
1691
  {
1078
1692
  id: "agent",
1079
1693
  label: "Agent",
1080
1694
  dot: "bg-violet-400"
1695
+ },
1696
+ {
1697
+ id: "agent-rag",
1698
+ label: "RAG",
1699
+ dot: "bg-emerald-400"
1081
1700
  }
1082
1701
  ], "entryTypes"),
1083
1702
  dashboards: /* @__PURE__ */ __name(() => [
1084
- agentDashboard(opts)
1703
+ agentDashboard({
1704
+ ...opts.threadHref !== void 0 ? {
1705
+ threadHref: opts.threadHref
1706
+ } : {},
1707
+ ...opts.runHref !== void 0 ? {
1708
+ runHref: opts.runHref
1709
+ } : {},
1710
+ ...opts.sections !== void 0 ? {
1711
+ sections: opts.sections
1712
+ } : {}
1713
+ })
1085
1714
  ], "dashboards"),
1086
1715
  dataProviders: /* @__PURE__ */ __name(() => [
1087
1716
  agentRunsProvider(),
@@ -1111,13 +1740,26 @@ function agentTelescopeExtension(opts = {}) {
1111
1740
  agentThreadsPagedTableProvider(),
1112
1741
  agentPendingApprovalsCountProvider(),
1113
1742
  agentPendingApprovalsTableProvider(),
1114
- agentToolStatsTableProvider()
1743
+ agentToolStatsTableProvider(),
1744
+ ragRetrievalsProvider(),
1745
+ ragZeroHitRateProvider(),
1746
+ ragChunksProvider(),
1747
+ ragLatencyProvider(),
1748
+ ragScoresProvider(),
1749
+ ragTrendProvider(),
1750
+ ragStoreBreakdownProvider(),
1751
+ ragRetrieverBreakdownProvider(),
1752
+ ragCollectionsTableProvider(),
1753
+ ragSlowestTableProvider(),
1754
+ ...hostProviders
1115
1755
  ], "dataProviders")
1116
1756
  });
1117
1757
  }
1118
1758
  __name(agentTelescopeExtension, "agentTelescopeExtension");
1119
1759
  export {
1120
1760
  AgentTelescopeWatcher,
1761
+ RAG_ENTRY_TYPE,
1762
+ RagTelescopeWatcher,
1121
1763
  agentActorSpendTableProvider,
1122
1764
  agentDashboard,
1123
1765
  agentModelSpendTableProvider,
@@ -1147,24 +1789,46 @@ export {
1147
1789
  agentTopThreadsTableProvider,
1148
1790
  agentUsageTrendProvider,
1149
1791
  capErrorMessage,
1792
+ meanChunks,
1793
+ percentile,
1794
+ ragChunksProvider,
1795
+ ragCollectionsTableProvider,
1796
+ ragLatencyProvider,
1797
+ ragRetrievalsProvider,
1798
+ ragRetrieverBreakdownProvider,
1799
+ ragScoresProvider,
1800
+ ragSlowestTableProvider,
1801
+ ragStoreBreakdownProvider,
1802
+ ragTrendProvider,
1803
+ ragZeroHitRateProvider,
1804
+ readRetrievals,
1150
1805
  resolveRange,
1151
1806
  shiftUtcDay,
1152
1807
  shortPromptHash,
1153
1808
  toActorSpendRows,
1154
1809
  toActorSpendSegments,
1810
+ toCollectionRows,
1811
+ toLatencyDistribution,
1155
1812
  toModelSpendRows,
1156
1813
  toModelSpendSegments,
1157
1814
  toPendingApprovalTableRows,
1815
+ toRagRetrieval,
1158
1816
  toRecentRunTableRows,
1159
1817
  toRecentThreadTableRows,
1160
1818
  toRecentToolCallRows,
1819
+ toRetrievalTrendRows,
1820
+ toRetrieverSegments,
1161
1821
  toRunAgentTableRows,
1162
1822
  toRunErrorSegments,
1163
1823
  toRunTrendRows,
1824
+ toScoreDistribution,
1825
+ toSlowestRows,
1826
+ toStoreSegments,
1164
1827
  toThreadSpendRows,
1165
1828
  toToolStatTableRows,
1166
1829
  toUsageTrendRows,
1167
1830
  totalCostUsd,
1168
- totalTokens
1831
+ totalTokens,
1832
+ zeroHitRate
1169
1833
  };
1170
1834
  //# sourceMappingURL=index.js.map