@absolutejs/absolute 0.19.0-beta.609 → 0.19.0-beta.610

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.
Files changed (44) hide show
  1. package/dist/ai/client/index.js +244 -21
  2. package/dist/ai/client/index.js.map +4 -4
  3. package/dist/ai/client/ui.js +245 -21
  4. package/dist/ai/client/ui.js.map +4 -4
  5. package/dist/ai/index.js +294 -28
  6. package/dist/ai/index.js.map +7 -7
  7. package/dist/ai/rag/quality.js +53 -11
  8. package/dist/ai/rag/quality.js.map +3 -3
  9. package/dist/ai/rag/ui.js +245 -21
  10. package/dist/ai/rag/ui.js.map +4 -4
  11. package/dist/ai-client/angular/ai/index.js +243 -20
  12. package/dist/ai-client/react/ai/index.js +262 -20
  13. package/dist/ai-client/vue/ai/index.js +262 -20
  14. package/dist/angular/ai/index.js +244 -21
  15. package/dist/angular/ai/index.js.map +4 -4
  16. package/dist/angular/index.js +2 -2
  17. package/dist/angular/index.js.map +1 -1
  18. package/dist/angular/server.js +2 -2
  19. package/dist/angular/server.js.map +1 -1
  20. package/dist/build.js +2 -2
  21. package/dist/build.js.map +1 -1
  22. package/dist/index.js +2 -2
  23. package/dist/index.js.map +1 -1
  24. package/dist/react/ai/index.js +263 -21
  25. package/dist/react/ai/index.js.map +6 -6
  26. package/dist/src/ai/client/ui.d.ts +1 -1
  27. package/dist/src/ai/rag/index.d.ts +1 -1
  28. package/dist/src/ai/rag/presentation.d.ts +8 -1
  29. package/dist/src/ai/rag/ui.d.ts +1 -1
  30. package/dist/src/react/ai/useRAG.d.ts +3 -0
  31. package/dist/src/react/ai/useRAGChunkPreview.d.ts +2 -0
  32. package/dist/src/react/ai/useRAGSources.d.ts +1 -0
  33. package/dist/src/svelte/ai/createRAG.d.ts +3 -0
  34. package/dist/src/svelte/ai/createRAGChunkPreview.d.ts +2 -0
  35. package/dist/src/svelte/ai/createRAGSources.d.ts +1 -0
  36. package/dist/src/vue/ai/useRAG.d.ts +11 -0
  37. package/dist/src/vue/ai/useRAGChunkPreview.d.ts +10 -0
  38. package/dist/src/vue/ai/useRAGSources.d.ts +1 -0
  39. package/dist/svelte/ai/index.js +263 -21
  40. package/dist/svelte/ai/index.js.map +6 -6
  41. package/dist/types/ai.d.ts +56 -0
  42. package/dist/vue/ai/index.js +263 -21
  43. package/dist/vue/ai/index.js.map +6 -6
  44. package/package.json +1 -1
@@ -871,21 +871,48 @@ var buildExcerpt = (text, maxLength = 160) => {
871
871
  };
872
872
  var selectPreferredExcerpt = (excerpts, sectionChunkCount) => {
873
873
  if (!excerpts) {
874
- return "";
874
+ return {
875
+ excerpt: "",
876
+ mode: "chunk",
877
+ reason: "single_chunk"
878
+ };
875
879
  }
876
880
  const chunkExcerpt = excerpts.chunkExcerpt?.trim() ?? "";
877
881
  const windowExcerpt = excerpts.windowExcerpt?.trim() ?? "";
878
882
  const sectionExcerpt = excerpts.sectionExcerpt?.trim() ?? "";
879
883
  if (sectionChunkCount && sectionChunkCount > 1 && chunkExcerpt.length > 0 && chunkExcerpt.length < 72) {
880
884
  if (sectionChunkCount <= 3 && sectionExcerpt) {
881
- return sectionExcerpt;
885
+ return {
886
+ excerpt: sectionExcerpt,
887
+ mode: "section",
888
+ reason: "section_small_enough"
889
+ };
882
890
  }
883
891
  if (windowExcerpt) {
884
- return windowExcerpt;
892
+ return {
893
+ excerpt: windowExcerpt,
894
+ mode: "window",
895
+ reason: "section_too_large_use_window"
896
+ };
885
897
  }
898
+ return {
899
+ excerpt: chunkExcerpt,
900
+ mode: "chunk",
901
+ reason: "chunk_too_narrow"
902
+ };
886
903
  }
887
- return chunkExcerpt || windowExcerpt || sectionExcerpt;
904
+ return {
905
+ excerpt: chunkExcerpt || windowExcerpt || sectionExcerpt,
906
+ mode: "chunk",
907
+ reason: (sectionChunkCount ?? 0) > 1 ? "chunk_too_narrow" : "single_chunk"
908
+ };
888
909
  };
910
+ var buildExcerptModeCounts = (references) => references.reduce((counts, reference) => {
911
+ if (reference?.excerptSelection) {
912
+ counts[reference.excerptSelection.mode] += 1;
913
+ }
914
+ return counts;
915
+ }, { chunk: 0, section: 0, window: 0 });
889
916
  var buildGroundingChunkExcerpts = (sources, activeChunkId) => {
890
917
  if (sources.length === 0) {
891
918
  return;
@@ -941,8 +968,9 @@ var buildGroundedAnswerCitationDetail = (reference) => ({
941
968
  contextLabel: reference.contextLabel,
942
969
  evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
943
970
  evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
944
- excerpt: selectPreferredExcerpt(reference.excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || reference.excerpt,
971
+ excerpt: selectPreferredExcerpt(reference.excerpts, getContextNumber(reference.metadata?.sectionChunkCount)).excerpt || reference.excerpt,
945
972
  excerpts: reference.excerpts,
973
+ excerptSelection: reference.excerptSelection,
946
974
  label: reference.label,
947
975
  locatorLabel: reference.locatorLabel,
948
976
  number: reference.number,
@@ -959,11 +987,14 @@ var buildRAGCitations = (sources) => {
959
987
  const hasBetterExisting = existing !== undefined && existing.score >= source.score;
960
988
  if (hasBetterExisting)
961
989
  continue;
990
+ const excerpts = buildGroundingChunkExcerpts(sources, source.chunkId);
991
+ const excerptSelection = selectPreferredExcerpt(excerpts, getContextNumber(source.metadata?.sectionChunkCount));
962
992
  unique.set(key, {
963
993
  chunkId: source.chunkId,
964
994
  contextLabel: source.labels?.contextLabel ?? buildContextLabel(source.metadata),
965
- excerpt: selectPreferredExcerpt(buildGroundingChunkExcerpts(sources, source.chunkId), getContextNumber(source.metadata?.sectionChunkCount)) || buildExcerpt(source.text),
966
- excerpts: buildGroundingChunkExcerpts(sources, source.chunkId),
995
+ excerpt: excerptSelection.excerpt || buildExcerpt(source.text),
996
+ excerpts,
997
+ excerptSelection,
967
998
  key,
968
999
  label: buildSourceLabel(source),
969
1000
  locatorLabel: source.labels?.locatorLabel ?? buildLocatorLabel(source.metadata, source.source, source.title),
@@ -984,6 +1015,7 @@ var buildRAGCitations = (sources) => {
984
1015
  };
985
1016
  var buildRAGGroundedAnswer = (content, sources) => {
986
1017
  const references = buildRAGGroundingReferences(sources);
1018
+ const sectionSummaries = buildRAGGroundedAnswerSectionSummaries(references);
987
1019
  const referenceMap = new Map(references.map((reference) => [reference.number, reference]));
988
1020
  const parts = [];
989
1021
  const ungroundedReferenceNumbers = new Set;
@@ -1027,10 +1059,14 @@ var buildRAGGroundedAnswer = (content, sources) => {
1027
1059
  return {
1028
1060
  content,
1029
1061
  coverage,
1062
+ excerptModeCounts: buildExcerptModeCounts([
1063
+ ...references,
1064
+ ...sectionSummaries
1065
+ ]),
1030
1066
  hasCitations,
1031
1067
  parts,
1032
1068
  references,
1033
- sectionSummaries: buildRAGGroundedAnswerSectionSummaries(references),
1069
+ sectionSummaries,
1034
1070
  ungroundedReferenceNumbers: [...ungroundedReferenceNumbers].sort((left, right) => left - right)
1035
1071
  };
1036
1072
  };
@@ -1049,8 +1085,9 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
1049
1085
  chunkIds: [reference.chunkId],
1050
1086
  contextLabel: reference.contextLabel,
1051
1087
  count: 1,
1052
- excerpt: selectPreferredExcerpt(excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || excerpts?.sectionExcerpt || reference.excerpt,
1088
+ excerpt: selectPreferredExcerpt(excerpts, getContextNumber(reference.metadata?.sectionChunkCount)).excerpt || excerpts?.sectionExcerpt || reference.excerpt,
1053
1089
  excerpts,
1090
+ excerptSelection: reference.excerptSelection,
1054
1091
  key,
1055
1092
  label: key,
1056
1093
  locatorLabel: reference.locatorLabel,
@@ -1086,6 +1123,9 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
1086
1123
  };
1087
1124
  existing.excerpt = reference.excerpts.sectionExcerpt;
1088
1125
  }
1126
+ if (!existing.excerptSelection && reference.excerptSelection) {
1127
+ existing.excerptSelection = reference.excerptSelection;
1128
+ }
1089
1129
  }
1090
1130
  return [...groups.values()].map((group) => ({
1091
1131
  ...group,
@@ -1105,11 +1145,13 @@ var buildRAGGroundingReferences = (sources) => {
1105
1145
  const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1106
1146
  return citations.map((citation) => {
1107
1147
  const excerpts = buildGroundingChunkExcerpts(sources, citation.chunkId);
1148
+ const excerptSelection = selectPreferredExcerpt(excerpts, getContextNumber(citation.metadata?.sectionChunkCount));
1108
1149
  return {
1109
1150
  chunkId: citation.chunkId,
1110
1151
  contextLabel: citation.contextLabel ?? buildContextLabel(citation.metadata),
1111
- excerpt: selectPreferredExcerpt(excerpts, getContextNumber(citation.metadata?.sectionChunkCount)) || excerpts?.chunkExcerpt || buildExcerpt(citation.text),
1152
+ excerpt: excerptSelection.excerpt || excerpts?.chunkExcerpt || buildExcerpt(citation.text),
1112
1153
  excerpts,
1154
+ excerptSelection,
1113
1155
  label: citation.label,
1114
1156
  locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1115
1157
  metadata: citation.metadata,
@@ -1363,22 +1405,49 @@ var buildRAGChunkExcerpts = (chunks, activeChunkId) => {
1363
1405
  windowExcerpt: buildExcerpt2(collectText(orderedWindowIds), 240)
1364
1406
  };
1365
1407
  };
1366
- var buildRAGPreferredExcerpt = (excerpts, structure) => {
1408
+ var buildRAGExcerptSelection = (excerpts, structure) => {
1367
1409
  if (!excerpts) {
1368
- return "";
1410
+ return {
1411
+ excerpt: "",
1412
+ mode: "chunk",
1413
+ reason: "single_chunk"
1414
+ };
1369
1415
  }
1370
1416
  const chunkLength = excerpts.chunkExcerpt.trim().length;
1371
1417
  const sectionChunkCount = structure?.sequence?.sectionChunkCount ?? 1;
1372
1418
  if (sectionChunkCount > 1 && chunkLength > 0 && chunkLength < 72) {
1373
1419
  if (sectionChunkCount <= 3 && excerpts.sectionExcerpt.trim().length > 0) {
1374
- return excerpts.sectionExcerpt;
1420
+ return {
1421
+ excerpt: excerpts.sectionExcerpt,
1422
+ mode: "section",
1423
+ reason: "section_small_enough"
1424
+ };
1375
1425
  }
1376
1426
  if (excerpts.windowExcerpt.trim().length > 0) {
1377
- return excerpts.windowExcerpt;
1427
+ return {
1428
+ excerpt: excerpts.windowExcerpt,
1429
+ mode: "window",
1430
+ reason: "section_too_large_use_window"
1431
+ };
1378
1432
  }
1433
+ return {
1434
+ excerpt: excerpts.chunkExcerpt,
1435
+ mode: "chunk",
1436
+ reason: "chunk_too_narrow"
1437
+ };
1379
1438
  }
1380
- return excerpts.chunkExcerpt;
1439
+ return {
1440
+ excerpt: excerpts.chunkExcerpt,
1441
+ mode: "chunk",
1442
+ reason: sectionChunkCount > 1 ? "chunk_too_narrow" : "single_chunk"
1443
+ };
1381
1444
  };
1445
+ var buildRAGExcerptModeCounts = (selections) => selections.reduce((counts, selection) => {
1446
+ if (selection) {
1447
+ counts[selection.mode] += 1;
1448
+ }
1449
+ return counts;
1450
+ }, { chunk: 0, section: 0, window: 0 });
1382
1451
  var buildRAGChunkGraph = (chunks) => {
1383
1452
  const nodes = [];
1384
1453
  const edges = [];
@@ -1567,19 +1636,27 @@ var buildRAGRetrievedState = (messages) => {
1567
1636
  return null;
1568
1637
  }
1569
1638
  const sources = message.sources ?? [];
1639
+ const citations = buildRAGCitations(sources);
1640
+ const sectionDiagnostics = buildRAGSectionRetrievalDiagnostics(sources, isRAGRetrievalTrace(message.retrievalTrace) ? message.retrievalTrace : undefined);
1641
+ const sourceSummaries = buildRAGSourceSummaries(sources);
1570
1642
  const groundedAnswer = buildRAGGroundedAnswer(message.content, sources);
1571
1643
  return {
1572
- citationReferenceMap: buildRAGCitationReferenceMap(buildRAGCitations(sources)),
1573
- citations: buildRAGCitations(sources),
1644
+ citationReferenceMap: buildRAGCitationReferenceMap(citations),
1645
+ citations,
1574
1646
  conversationId: message.conversationId,
1647
+ excerptModeCounts: buildRAGExcerptModeCounts([
1648
+ ...citations.map((citation) => citation.excerptSelection),
1649
+ ...sourceSummaries.map((summary) => summary.excerptSelection)
1650
+ ]),
1575
1651
  groundedAnswer,
1576
1652
  messageId: message.id,
1577
1653
  retrievalDurationMs: message.retrievalDurationMs,
1578
1654
  retrievalStartedAt: message.retrievalStartedAt,
1579
1655
  retrievedAt: message.retrievedAt,
1580
1656
  trace: isRAGRetrievalTrace(message.retrievalTrace) ? message.retrievalTrace : undefined,
1657
+ sectionDiagnostics,
1581
1658
  sourceGroups: buildRAGSourceGroups(sources),
1582
- sourceSummaries: buildRAGSourceSummaries(sources),
1659
+ sourceSummaries,
1583
1660
  sources
1584
1661
  };
1585
1662
  };
@@ -1591,6 +1668,8 @@ var buildRAGSourceSummaries = (sources) => {
1591
1668
  const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
1592
1669
  const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
1593
1670
  const excerpts = leadChunk ? buildRAGChunkExcerpts(group.chunks, leadChunk.chunkId) : undefined;
1671
+ const structure = leadChunk?.structure ?? buildRAGChunkStructure(leadChunk?.metadata);
1672
+ const excerptSelection = buildRAGExcerptSelection(excerpts, structure);
1594
1673
  return {
1595
1674
  bestScore: group.bestScore,
1596
1675
  citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
@@ -1598,18 +1677,154 @@ var buildRAGSourceSummaries = (sources) => {
1598
1677
  chunkIds: group.chunks.map((chunk) => chunk.chunkId),
1599
1678
  contextLabel: leadChunk?.labels?.contextLabel ?? buildContextLabel2(leadChunk?.metadata),
1600
1679
  count: group.count,
1601
- excerpt: buildRAGPreferredExcerpt(excerpts, leadChunk?.structure ?? buildRAGChunkStructure(leadChunk?.metadata)) || buildExcerpt2(leadChunk?.text ?? ""),
1680
+ excerpt: excerptSelection.excerpt || buildExcerpt2(leadChunk?.text ?? ""),
1602
1681
  excerpts,
1682
+ excerptSelection,
1603
1683
  key: group.key,
1604
1684
  label: group.label,
1605
1685
  locatorLabel: leadChunk?.labels?.locatorLabel ?? buildLocatorLabel2(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),
1606
1686
  provenanceLabel: leadChunk?.labels?.provenanceLabel ?? buildProvenanceLabel2(leadChunk?.metadata),
1607
- structure: leadChunk?.structure ?? buildRAGChunkStructure(leadChunk?.metadata),
1687
+ structure,
1608
1688
  source: group.source,
1609
1689
  title: group.title
1610
1690
  };
1611
1691
  });
1612
1692
  };
1693
+ var getSectionPathFromSource = (source) => {
1694
+ const path = source.structure?.section?.path ?? (Array.isArray(source.metadata?.sectionPath) ? source.metadata.sectionPath.map((value) => getContextString2(value)).filter((value) => typeof value === "string") : []);
1695
+ return path.length > 0 ? path : undefined;
1696
+ };
1697
+ var buildRAGSectionRetrievalDiagnostics = (sources, trace) => {
1698
+ const totalScore = sources.reduce((sum, source) => sum + source.score, 0);
1699
+ if (sources.length === 0 || totalScore <= 0) {
1700
+ return [];
1701
+ }
1702
+ const sections = new Map;
1703
+ for (const source of sources) {
1704
+ const path = getSectionPathFromSource(source);
1705
+ if (!path) {
1706
+ continue;
1707
+ }
1708
+ const key = path.join(" > ");
1709
+ const label = path.at(-1) ?? key;
1710
+ const parentLabel = path.length > 1 ? path.slice(0, -1).join(" > ") : undefined;
1711
+ const existing = sections.get(key);
1712
+ const channels = Array.isArray(source.metadata?.retrievalChannels) ? source.metadata.retrievalChannels.filter((value) => value === "vector" || value === "lexical") : [];
1713
+ const isHybrid = channels.includes("vector") && channels.includes("lexical");
1714
+ const vectorHits = channels.includes("vector") ? 1 : 0;
1715
+ const lexicalHits = channels.includes("lexical") ? 1 : 0;
1716
+ const hybridHits = isHybrid ? 1 : 0;
1717
+ if (!existing) {
1718
+ sections.set(key, {
1719
+ bestScore: source.score,
1720
+ count: 1,
1721
+ hybridHits,
1722
+ key,
1723
+ label,
1724
+ lexicalHits,
1725
+ parentLabel,
1726
+ path,
1727
+ sourceSet: new Set(source.source ? [source.source] : []),
1728
+ topChunkId: source.chunkId,
1729
+ topSource: source.source,
1730
+ totalScore: source.score,
1731
+ vectorHits
1732
+ });
1733
+ continue;
1734
+ }
1735
+ existing.count += 1;
1736
+ existing.totalScore += source.score;
1737
+ if (source.source) {
1738
+ existing.sourceSet.add(source.source);
1739
+ }
1740
+ existing.vectorHits += vectorHits;
1741
+ existing.lexicalHits += lexicalHits;
1742
+ existing.hybridHits += hybridHits;
1743
+ if (source.score > existing.bestScore) {
1744
+ existing.bestScore = source.score;
1745
+ existing.topChunkId = source.chunkId;
1746
+ existing.topSource = source.source;
1747
+ }
1748
+ }
1749
+ const diagnostics = [...sections.values()];
1750
+ const strongestBestHit = diagnostics.reduce((highest, section) => Math.max(highest, section.bestScore), 0);
1751
+ return diagnostics.map((section) => {
1752
+ const siblingPool = diagnostics.filter((entry) => entry.parentLabel === section.parentLabel);
1753
+ const siblings = siblingPool.filter((entry) => entry.key !== section.key);
1754
+ const strongestSibling = siblings.slice().sort((left, right) => right.totalScore - left.totalScore)[0];
1755
+ const parentTotal = siblingPool.reduce((sum, entry) => sum + entry.totalScore, 0);
1756
+ const scoreShare = section.totalScore / totalScore;
1757
+ const parentShare = parentTotal > 0 ? section.totalScore / parentTotal : undefined;
1758
+ const parentDistribution = parentTotal > 0 ? siblingPool.map((entry) => ({
1759
+ count: entry.count,
1760
+ isActive: entry.key === section.key,
1761
+ key: entry.key,
1762
+ label: entry.label,
1763
+ parentShare: entry.totalScore / parentTotal,
1764
+ totalScore: entry.totalScore
1765
+ })).sort((left, right) => right.totalScore - left.totalScore) : [];
1766
+ const reasons = [];
1767
+ if (section.bestScore >= strongestBestHit) {
1768
+ reasons.push("best_hit");
1769
+ }
1770
+ if (section.count > 1) {
1771
+ reasons.push("multi_hit_section");
1772
+ }
1773
+ if (siblings.length === 0) {
1774
+ reasons.push("only_section_in_parent");
1775
+ } else if (!strongestSibling || section.totalScore >= strongestSibling.totalScore) {
1776
+ reasons.push("dominant_within_parent");
1777
+ }
1778
+ if (scoreShare >= 0.5 || (parentShare ?? 0) >= 0.6) {
1779
+ reasons.push("concentrated_evidence");
1780
+ }
1781
+ const summaryParts = [
1782
+ `${section.count} hit${section.count === 1 ? "" : "s"}`,
1783
+ `${(scoreShare * 100).toFixed(0)}% score share`,
1784
+ `vector ${section.vectorHits} · lexical ${section.lexicalHits} · hybrid ${section.hybridHits}`,
1785
+ typeof parentShare === "number" ? `${(parentShare * 100).toFixed(0)}% of parent section set` : "",
1786
+ strongestSibling ? `ahead of ${strongestSibling.label} by ${(section.totalScore - strongestSibling.totalScore).toFixed(2)}` : "no sibling competition"
1787
+ ].filter(Boolean);
1788
+ return {
1789
+ averageScore: section.totalScore / section.count,
1790
+ bestScore: section.bestScore,
1791
+ count: section.count,
1792
+ key: section.key,
1793
+ label: section.label,
1794
+ parentLabel: section.parentLabel,
1795
+ parentDistribution,
1796
+ parentShare,
1797
+ parentShareGap: typeof parentShare === "number" && strongestSibling && parentTotal > 0 ? parentShare - strongestSibling.totalScore / parentTotal : undefined,
1798
+ path: section.path,
1799
+ retrievalMode: trace?.mode,
1800
+ reasons,
1801
+ rerankApplied: trace?.steps.some((step) => step.stage === "rerank" && step.metadata?.applied === true),
1802
+ scoreShare,
1803
+ scoreThresholdApplied: trace?.steps.some((step) => step.stage === "score_filter"),
1804
+ siblingCount: siblings.length,
1805
+ siblingScoreGap: strongestSibling ? section.totalScore - strongestSibling.totalScore : undefined,
1806
+ sourceCount: section.sourceSet.size,
1807
+ sourceBalanceApplied: trace?.steps.some((step) => step.stage === "source_balance"),
1808
+ strongestSiblingLabel: strongestSibling?.label,
1809
+ strongestSiblingScore: strongestSibling?.totalScore,
1810
+ summary: summaryParts.join(" · "),
1811
+ topChunkId: section.topChunkId,
1812
+ topSource: section.topSource,
1813
+ totalScore: section.totalScore,
1814
+ hybridHits: section.hybridHits,
1815
+ lexicalHits: section.lexicalHits,
1816
+ vectorHits: section.vectorHits
1817
+ };
1818
+ }).sort((left, right) => {
1819
+ if (right.totalScore !== left.totalScore) {
1820
+ return right.totalScore - left.totalScore;
1821
+ }
1822
+ if (right.bestScore !== left.bestScore) {
1823
+ return right.bestScore - left.bestScore;
1824
+ }
1825
+ return left.label.localeCompare(right.label);
1826
+ });
1827
+ };
1613
1828
  var buildStreamProgressState = (messages) => {
1614
1829
  const latestMessage = getLatestAssistantMessage(messages);
1615
1830
  const retrieved = latestMessage ? buildRAGRetrievedState(messages) : undefined;
@@ -1673,12 +1888,19 @@ var buildRAGAnswerWorkflowState = ({
1673
1888
  const groundingReferences = buildRAGGroundingReferences(sources);
1674
1889
  const groundedAnswer = buildRAGGroundedAnswer(latestAssistantMessage?.content ?? "", sources);
1675
1890
  const retrieval = buildRAGRetrievedState(messages);
1891
+ const sectionDiagnostics = buildRAGSectionRetrievalDiagnostics(sources, retrieval?.trace);
1676
1892
  const progress = buildRAGStreamProgress({
1677
1893
  error,
1678
1894
  isStreaming,
1679
1895
  messages
1680
1896
  });
1681
1897
  return {
1898
+ excerptModeCounts: buildRAGExcerptModeCounts([
1899
+ ...citations.map((citation) => citation.excerptSelection),
1900
+ ...sourceSummaries.map((summary) => summary.excerptSelection),
1901
+ ...groundingReferences.map((reference) => reference.excerptSelection),
1902
+ ...groundedAnswer.sectionSummaries.map((summary) => summary.excerptSelection)
1903
+ ]),
1682
1904
  citationReferenceMap,
1683
1905
  citations,
1684
1906
  coverage: groundedAnswer.coverage,
@@ -1703,6 +1925,7 @@ var buildRAGAnswerWorkflowState = ({
1703
1925
  retrievalDurationMs: retrieval?.retrievalDurationMs,
1704
1926
  retrievalStartedAt: retrieval?.retrievalStartedAt,
1705
1927
  retrievedAt: retrieval?.retrievedAt,
1928
+ sectionDiagnostics,
1706
1929
  sourceGroups,
1707
1930
  sourceSummaries,
1708
1931
  sources,