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

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 (38) hide show
  1. package/dist/ai/client/index.js +142 -18
  2. package/dist/ai/client/index.js.map +4 -4
  3. package/dist/ai/client/ui.js +143 -18
  4. package/dist/ai/client/ui.js.map +4 -4
  5. package/dist/ai/index.js +371 -28
  6. package/dist/ai/index.js.map +7 -7
  7. package/dist/ai/rag/quality.js +92 -16
  8. package/dist/ai/rag/quality.js.map +3 -3
  9. package/dist/ai/rag/ui.js +143 -18
  10. package/dist/ai/rag/ui.js.map +4 -4
  11. package/dist/ai-client/angular/ai/index.js +141 -17
  12. package/dist/ai-client/react/ai/index.js +141 -17
  13. package/dist/ai-client/vue/ai/index.js +141 -17
  14. package/dist/angular/ai/index.js +142 -18
  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 +142 -18
  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 +4 -1
  29. package/dist/src/ai/rag/ui.d.ts +1 -1
  30. package/dist/src/vue/ai/useRAG.d.ts +14 -4
  31. package/dist/src/vue/ai/useRAGChunkPreview.d.ts +12 -2
  32. package/dist/src/vue/ai/useRAGSearch.d.ts +2 -2
  33. package/dist/svelte/ai/index.js +142 -18
  34. package/dist/svelte/ai/index.js.map +6 -6
  35. package/dist/types/ai.d.ts +15 -2
  36. package/dist/vue/ai/index.js +142 -18
  37. package/dist/vue/ai/index.js.map +5 -5
  38. package/package.json +1 -1
@@ -869,6 +869,60 @@ var buildExcerpt = (text, maxLength = 160) => {
869
869
  }
870
870
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
871
871
  };
872
+ var selectPreferredExcerpt = (excerpts, sectionChunkCount) => {
873
+ if (!excerpts) {
874
+ return "";
875
+ }
876
+ const chunkExcerpt = excerpts.chunkExcerpt?.trim() ?? "";
877
+ const windowExcerpt = excerpts.windowExcerpt?.trim() ?? "";
878
+ const sectionExcerpt = excerpts.sectionExcerpt?.trim() ?? "";
879
+ if (sectionChunkCount && sectionChunkCount > 1 && chunkExcerpt.length > 0 && chunkExcerpt.length < 72) {
880
+ if (sectionChunkCount <= 3 && sectionExcerpt) {
881
+ return sectionExcerpt;
882
+ }
883
+ if (windowExcerpt) {
884
+ return windowExcerpt;
885
+ }
886
+ }
887
+ return chunkExcerpt || windowExcerpt || sectionExcerpt;
888
+ };
889
+ var buildGroundingChunkExcerpts = (sources, activeChunkId) => {
890
+ if (sources.length === 0) {
891
+ return;
892
+ }
893
+ const activeSource = (activeChunkId ? sources.find((source) => source.chunkId === activeChunkId) : undefined) ?? sources[0];
894
+ if (!activeSource) {
895
+ return;
896
+ }
897
+ const chunkMap = new Map(sources.map((source) => [source.chunkId, source]));
898
+ const activeMetadata = activeSource.metadata ?? {};
899
+ const previousChunkId = getContextString(activeMetadata.previousChunkId);
900
+ const nextChunkId = getContextString(activeMetadata.nextChunkId);
901
+ const sectionChunkId = getContextString(activeMetadata.sectionChunkId);
902
+ const sectionSources = sectionChunkId ? sources.filter((source) => getContextString(source.metadata?.sectionChunkId) === sectionChunkId).sort((left, right) => {
903
+ const leftIndex = getContextNumber(left.metadata?.sectionChunkIndex) ?? Number.MAX_SAFE_INTEGER;
904
+ const rightIndex = getContextNumber(right.metadata?.sectionChunkIndex) ?? Number.MAX_SAFE_INTEGER;
905
+ if (leftIndex !== rightIndex) {
906
+ return leftIndex - rightIndex;
907
+ }
908
+ return left.chunkId.localeCompare(right.chunkId);
909
+ }) : [activeSource];
910
+ const collectText = (chunkIds) => chunkIds.map((chunkId) => chunkMap.get(chunkId)?.text).filter((text) => typeof text === "string").join(`
911
+
912
+ `);
913
+ const orderedWindowIds = [
914
+ previousChunkId,
915
+ activeSource.chunkId,
916
+ nextChunkId
917
+ ].filter((chunkId, index, values) => Boolean(chunkId) && values.indexOf(chunkId) === index);
918
+ return {
919
+ chunkExcerpt: buildExcerpt(activeSource.text, 160),
920
+ sectionExcerpt: buildExcerpt(sectionSources.map((source) => source.text).join(`
921
+
922
+ `), 320),
923
+ windowExcerpt: buildExcerpt(collectText(orderedWindowIds), 240)
924
+ };
925
+ };
872
926
  var buildGroundingReferenceEvidenceLabel = (reference) => [reference.label, reference.locatorLabel, reference.contextLabel].filter((value) => Boolean(value && value.length > 0)).filter((value, index, values) => values.findIndex((entry) => entry === value) === index).join(" · ");
873
927
  var buildGroundingReferenceEvidenceSummary = (reference) => [
874
928
  reference.source ?? reference.title ?? reference.chunkId,
@@ -887,7 +941,8 @@ var buildGroundedAnswerCitationDetail = (reference) => ({
887
941
  contextLabel: reference.contextLabel,
888
942
  evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
889
943
  evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
890
- excerpt: reference.excerpt,
944
+ excerpt: selectPreferredExcerpt(reference.excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || reference.excerpt,
945
+ excerpts: reference.excerpts,
891
946
  label: reference.label,
892
947
  locatorLabel: reference.locatorLabel,
893
948
  number: reference.number,
@@ -907,6 +962,8 @@ var buildRAGCitations = (sources) => {
907
962
  unique.set(key, {
908
963
  chunkId: source.chunkId,
909
964
  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),
910
967
  key,
911
968
  label: buildSourceLabel(source),
912
969
  locatorLabel: source.labels?.locatorLabel ?? buildLocatorLabel(source.metadata, source.source, source.title),
@@ -983,10 +1040,17 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
983
1040
  const key = buildGroundingSectionKey(reference);
984
1041
  const existing = groups.get(key);
985
1042
  if (!existing) {
1043
+ const excerpts = reference.excerpts ? {
1044
+ chunkExcerpt: reference.excerpts.chunkExcerpt,
1045
+ sectionExcerpt: reference.excerpts.sectionExcerpt,
1046
+ windowExcerpt: reference.excerpts.windowExcerpt
1047
+ } : undefined;
986
1048
  groups.set(key, {
987
1049
  chunkIds: [reference.chunkId],
988
1050
  contextLabel: reference.contextLabel,
989
1051
  count: 1,
1052
+ excerpt: selectPreferredExcerpt(excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || excerpts?.sectionExcerpt || reference.excerpt,
1053
+ excerpts,
990
1054
  key,
991
1055
  label: key,
992
1056
  locatorLabel: reference.locatorLabel,
@@ -1014,6 +1078,14 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
1014
1078
  if (!existing.provenanceLabel && reference.provenanceLabel) {
1015
1079
  existing.provenanceLabel = reference.provenanceLabel;
1016
1080
  }
1081
+ if (!existing.excerpts && reference.excerpts) {
1082
+ existing.excerpts = {
1083
+ chunkExcerpt: reference.excerpts.chunkExcerpt,
1084
+ sectionExcerpt: reference.excerpts.sectionExcerpt,
1085
+ windowExcerpt: reference.excerpts.windowExcerpt
1086
+ };
1087
+ existing.excerpt = reference.excerpts.sectionExcerpt;
1088
+ }
1017
1089
  }
1018
1090
  return [...groups.values()].map((group) => ({
1019
1091
  ...group,
@@ -1031,20 +1103,24 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
1031
1103
  var buildRAGGroundingReferences = (sources) => {
1032
1104
  const citations = buildRAGCitations(sources);
1033
1105
  const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1034
- return citations.map((citation) => ({
1035
- chunkId: citation.chunkId,
1036
- contextLabel: citation.contextLabel ?? buildContextLabel(citation.metadata),
1037
- excerpt: buildExcerpt(citation.text),
1038
- label: citation.label,
1039
- locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1040
- metadata: citation.metadata,
1041
- number: citationReferenceMap[citation.chunkId] ?? 0,
1042
- provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
1043
- score: citation.score,
1044
- source: citation.source,
1045
- text: citation.text,
1046
- title: citation.title
1047
- }));
1106
+ return citations.map((citation) => {
1107
+ const excerpts = buildGroundingChunkExcerpts(sources, citation.chunkId);
1108
+ return {
1109
+ chunkId: citation.chunkId,
1110
+ contextLabel: citation.contextLabel ?? buildContextLabel(citation.metadata),
1111
+ excerpt: selectPreferredExcerpt(excerpts, getContextNumber(citation.metadata?.sectionChunkCount)) || excerpts?.chunkExcerpt || buildExcerpt(citation.text),
1112
+ excerpts,
1113
+ label: citation.label,
1114
+ locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1115
+ metadata: citation.metadata,
1116
+ number: citationReferenceMap[citation.chunkId] ?? 0,
1117
+ provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
1118
+ score: citation.score,
1119
+ source: citation.source,
1120
+ text: citation.text,
1121
+ title: citation.title
1122
+ };
1123
+ });
1048
1124
  };
1049
1125
 
1050
1126
  // src/ai/rag/presentation.ts
@@ -1228,7 +1304,7 @@ var buildRAGChunkStructure = (metadata) => {
1228
1304
  return;
1229
1305
  }
1230
1306
  const sectionPath = Array.isArray(metadata.sectionPath) ? metadata.sectionPath.filter((value) => typeof value === "string" && value.trim().length > 0) : undefined;
1231
- const sectionKind = metadata.sectionKind === "markdown_heading" || metadata.sectionKind === "html_heading" ? metadata.sectionKind : undefined;
1307
+ const sectionKind = metadata.sectionKind === "markdown_heading" || metadata.sectionKind === "html_heading" || metadata.sectionKind === "office_heading" || metadata.sectionKind === "spreadsheet_rows" || metadata.sectionKind === "presentation_slide" ? metadata.sectionKind : undefined;
1232
1308
  const section = {
1233
1309
  depth: getContextNumber2(metadata.sectionDepth),
1234
1310
  kind: sectionKind,
@@ -1257,6 +1333,52 @@ var buildExcerpt2 = (text, maxLength = 160) => {
1257
1333
  }
1258
1334
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
1259
1335
  };
1336
+ var buildRAGChunkExcerpts = (chunks, activeChunkId) => {
1337
+ if (chunks.length === 0) {
1338
+ return;
1339
+ }
1340
+ const graph = buildRAGChunkGraph(chunks.map((chunk) => ({
1341
+ chunkId: chunk.chunkId,
1342
+ metadata: chunk.metadata,
1343
+ structure: chunk.structure
1344
+ })));
1345
+ const navigation = buildRAGChunkGraphNavigation(graph, activeChunkId);
1346
+ const activeChunk = chunks.find((chunk) => chunk.chunkId === navigation.activeChunkId) ?? chunks[0];
1347
+ if (!activeChunk) {
1348
+ return;
1349
+ }
1350
+ const chunkMap = new Map(chunks.map((chunk) => [chunk.chunkId, chunk]));
1351
+ const orderedWindowIds = [
1352
+ navigation.previousNode?.chunkId,
1353
+ activeChunk.chunkId,
1354
+ navigation.nextNode?.chunkId
1355
+ ].filter((chunkId, index, ids) => Boolean(chunkId) && ids.indexOf(chunkId) === index);
1356
+ const orderedSectionIds = navigation.sectionNodes.length > 0 ? navigation.sectionNodes.map((node) => node.chunkId) : [activeChunk.chunkId];
1357
+ const collectText = (chunkIds) => chunkIds.map((chunkId) => chunkMap.get(chunkId)?.text).filter((text) => typeof text === "string").join(`
1358
+
1359
+ `);
1360
+ return {
1361
+ chunkExcerpt: buildExcerpt2(activeChunk.text, 160),
1362
+ sectionExcerpt: buildExcerpt2(collectText(orderedSectionIds), 320),
1363
+ windowExcerpt: buildExcerpt2(collectText(orderedWindowIds), 240)
1364
+ };
1365
+ };
1366
+ var buildRAGPreferredExcerpt = (excerpts, structure) => {
1367
+ if (!excerpts) {
1368
+ return "";
1369
+ }
1370
+ const chunkLength = excerpts.chunkExcerpt.trim().length;
1371
+ const sectionChunkCount = structure?.sequence?.sectionChunkCount ?? 1;
1372
+ if (sectionChunkCount > 1 && chunkLength > 0 && chunkLength < 72) {
1373
+ if (sectionChunkCount <= 3 && excerpts.sectionExcerpt.trim().length > 0) {
1374
+ return excerpts.sectionExcerpt;
1375
+ }
1376
+ if (excerpts.windowExcerpt.trim().length > 0) {
1377
+ return excerpts.windowExcerpt;
1378
+ }
1379
+ }
1380
+ return excerpts.chunkExcerpt;
1381
+ };
1260
1382
  var buildRAGChunkGraph = (chunks) => {
1261
1383
  const nodes = [];
1262
1384
  const edges = [];
@@ -1468,6 +1590,7 @@ var buildRAGSourceSummaries = (sources) => {
1468
1590
  return sourceGroups.map((group) => {
1469
1591
  const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
1470
1592
  const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
1593
+ const excerpts = leadChunk ? buildRAGChunkExcerpts(group.chunks, leadChunk.chunkId) : undefined;
1471
1594
  return {
1472
1595
  bestScore: group.bestScore,
1473
1596
  citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
@@ -1475,7 +1598,8 @@ var buildRAGSourceSummaries = (sources) => {
1475
1598
  chunkIds: group.chunks.map((chunk) => chunk.chunkId),
1476
1599
  contextLabel: leadChunk?.labels?.contextLabel ?? buildContextLabel2(leadChunk?.metadata),
1477
1600
  count: group.count,
1478
- excerpt: buildExcerpt2(leadChunk?.text ?? ""),
1601
+ excerpt: buildRAGPreferredExcerpt(excerpts, leadChunk?.structure ?? buildRAGChunkStructure(leadChunk?.metadata)) || buildExcerpt2(leadChunk?.text ?? ""),
1602
+ excerpts,
1479
1603
  key: group.key,
1480
1604
  label: group.label,
1481
1605
  locatorLabel: leadChunk?.labels?.locatorLabel ?? buildLocatorLabel2(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),
@@ -829,6 +829,60 @@ var buildExcerpt = (text, maxLength = 160) => {
829
829
  }
830
830
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
831
831
  };
832
+ var selectPreferredExcerpt = (excerpts, sectionChunkCount) => {
833
+ if (!excerpts) {
834
+ return "";
835
+ }
836
+ const chunkExcerpt = excerpts.chunkExcerpt?.trim() ?? "";
837
+ const windowExcerpt = excerpts.windowExcerpt?.trim() ?? "";
838
+ const sectionExcerpt = excerpts.sectionExcerpt?.trim() ?? "";
839
+ if (sectionChunkCount && sectionChunkCount > 1 && chunkExcerpt.length > 0 && chunkExcerpt.length < 72) {
840
+ if (sectionChunkCount <= 3 && sectionExcerpt) {
841
+ return sectionExcerpt;
842
+ }
843
+ if (windowExcerpt) {
844
+ return windowExcerpt;
845
+ }
846
+ }
847
+ return chunkExcerpt || windowExcerpt || sectionExcerpt;
848
+ };
849
+ var buildGroundingChunkExcerpts = (sources, activeChunkId) => {
850
+ if (sources.length === 0) {
851
+ return;
852
+ }
853
+ const activeSource = (activeChunkId ? sources.find((source) => source.chunkId === activeChunkId) : undefined) ?? sources[0];
854
+ if (!activeSource) {
855
+ return;
856
+ }
857
+ const chunkMap = new Map(sources.map((source) => [source.chunkId, source]));
858
+ const activeMetadata = activeSource.metadata ?? {};
859
+ const previousChunkId = getContextString(activeMetadata.previousChunkId);
860
+ const nextChunkId = getContextString(activeMetadata.nextChunkId);
861
+ const sectionChunkId = getContextString(activeMetadata.sectionChunkId);
862
+ const sectionSources = sectionChunkId ? sources.filter((source) => getContextString(source.metadata?.sectionChunkId) === sectionChunkId).sort((left, right) => {
863
+ const leftIndex = getContextNumber(left.metadata?.sectionChunkIndex) ?? Number.MAX_SAFE_INTEGER;
864
+ const rightIndex = getContextNumber(right.metadata?.sectionChunkIndex) ?? Number.MAX_SAFE_INTEGER;
865
+ if (leftIndex !== rightIndex) {
866
+ return leftIndex - rightIndex;
867
+ }
868
+ return left.chunkId.localeCompare(right.chunkId);
869
+ }) : [activeSource];
870
+ const collectText = (chunkIds) => chunkIds.map((chunkId) => chunkMap.get(chunkId)?.text).filter((text) => typeof text === "string").join(`
871
+
872
+ `);
873
+ const orderedWindowIds = [
874
+ previousChunkId,
875
+ activeSource.chunkId,
876
+ nextChunkId
877
+ ].filter((chunkId, index, values) => Boolean(chunkId) && values.indexOf(chunkId) === index);
878
+ return {
879
+ chunkExcerpt: buildExcerpt(activeSource.text, 160),
880
+ sectionExcerpt: buildExcerpt(sectionSources.map((source) => source.text).join(`
881
+
882
+ `), 320),
883
+ windowExcerpt: buildExcerpt(collectText(orderedWindowIds), 240)
884
+ };
885
+ };
832
886
  var buildGroundingReferenceEvidenceLabel = (reference) => [reference.label, reference.locatorLabel, reference.contextLabel].filter((value) => Boolean(value && value.length > 0)).filter((value, index, values) => values.findIndex((entry) => entry === value) === index).join(" · ");
833
887
  var buildGroundingReferenceEvidenceSummary = (reference) => [
834
888
  reference.source ?? reference.title ?? reference.chunkId,
@@ -847,7 +901,8 @@ var buildGroundedAnswerCitationDetail = (reference) => ({
847
901
  contextLabel: reference.contextLabel,
848
902
  evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
849
903
  evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
850
- excerpt: reference.excerpt,
904
+ excerpt: selectPreferredExcerpt(reference.excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || reference.excerpt,
905
+ excerpts: reference.excerpts,
851
906
  label: reference.label,
852
907
  locatorLabel: reference.locatorLabel,
853
908
  number: reference.number,
@@ -867,6 +922,8 @@ var buildRAGCitations = (sources) => {
867
922
  unique.set(key, {
868
923
  chunkId: source.chunkId,
869
924
  contextLabel: source.labels?.contextLabel ?? buildContextLabel(source.metadata),
925
+ excerpt: selectPreferredExcerpt(buildGroundingChunkExcerpts(sources, source.chunkId), getContextNumber(source.metadata?.sectionChunkCount)) || buildExcerpt(source.text),
926
+ excerpts: buildGroundingChunkExcerpts(sources, source.chunkId),
870
927
  key,
871
928
  label: buildSourceLabel(source),
872
929
  locatorLabel: source.labels?.locatorLabel ?? buildLocatorLabel(source.metadata, source.source, source.title),
@@ -943,10 +1000,17 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
943
1000
  const key = buildGroundingSectionKey(reference);
944
1001
  const existing = groups.get(key);
945
1002
  if (!existing) {
1003
+ const excerpts = reference.excerpts ? {
1004
+ chunkExcerpt: reference.excerpts.chunkExcerpt,
1005
+ sectionExcerpt: reference.excerpts.sectionExcerpt,
1006
+ windowExcerpt: reference.excerpts.windowExcerpt
1007
+ } : undefined;
946
1008
  groups.set(key, {
947
1009
  chunkIds: [reference.chunkId],
948
1010
  contextLabel: reference.contextLabel,
949
1011
  count: 1,
1012
+ excerpt: selectPreferredExcerpt(excerpts, getContextNumber(reference.metadata?.sectionChunkCount)) || excerpts?.sectionExcerpt || reference.excerpt,
1013
+ excerpts,
950
1014
  key,
951
1015
  label: key,
952
1016
  locatorLabel: reference.locatorLabel,
@@ -974,6 +1038,14 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
974
1038
  if (!existing.provenanceLabel && reference.provenanceLabel) {
975
1039
  existing.provenanceLabel = reference.provenanceLabel;
976
1040
  }
1041
+ if (!existing.excerpts && reference.excerpts) {
1042
+ existing.excerpts = {
1043
+ chunkExcerpt: reference.excerpts.chunkExcerpt,
1044
+ sectionExcerpt: reference.excerpts.sectionExcerpt,
1045
+ windowExcerpt: reference.excerpts.windowExcerpt
1046
+ };
1047
+ existing.excerpt = reference.excerpts.sectionExcerpt;
1048
+ }
977
1049
  }
978
1050
  return [...groups.values()].map((group) => ({
979
1051
  ...group,
@@ -991,20 +1063,24 @@ var buildRAGGroundedAnswerSectionSummaries = (references) => {
991
1063
  var buildRAGGroundingReferences = (sources) => {
992
1064
  const citations = buildRAGCitations(sources);
993
1065
  const citationReferenceMap = buildRAGCitationReferenceMap(citations);
994
- return citations.map((citation) => ({
995
- chunkId: citation.chunkId,
996
- contextLabel: citation.contextLabel ?? buildContextLabel(citation.metadata),
997
- excerpt: buildExcerpt(citation.text),
998
- label: citation.label,
999
- locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1000
- metadata: citation.metadata,
1001
- number: citationReferenceMap[citation.chunkId] ?? 0,
1002
- provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
1003
- score: citation.score,
1004
- source: citation.source,
1005
- text: citation.text,
1006
- title: citation.title
1007
- }));
1066
+ return citations.map((citation) => {
1067
+ const excerpts = buildGroundingChunkExcerpts(sources, citation.chunkId);
1068
+ return {
1069
+ chunkId: citation.chunkId,
1070
+ contextLabel: citation.contextLabel ?? buildContextLabel(citation.metadata),
1071
+ excerpt: selectPreferredExcerpt(excerpts, getContextNumber(citation.metadata?.sectionChunkCount)) || excerpts?.chunkExcerpt || buildExcerpt(citation.text),
1072
+ excerpts,
1073
+ label: citation.label,
1074
+ locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1075
+ metadata: citation.metadata,
1076
+ number: citationReferenceMap[citation.chunkId] ?? 0,
1077
+ provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
1078
+ score: citation.score,
1079
+ source: citation.source,
1080
+ text: citation.text,
1081
+ title: citation.title
1082
+ };
1083
+ });
1008
1084
  };
1009
1085
 
1010
1086
  // src/ai/rag/presentation.ts
@@ -1188,7 +1264,7 @@ var buildRAGChunkStructure = (metadata) => {
1188
1264
  return;
1189
1265
  }
1190
1266
  const sectionPath = Array.isArray(metadata.sectionPath) ? metadata.sectionPath.filter((value) => typeof value === "string" && value.trim().length > 0) : undefined;
1191
- const sectionKind = metadata.sectionKind === "markdown_heading" || metadata.sectionKind === "html_heading" ? metadata.sectionKind : undefined;
1267
+ const sectionKind = metadata.sectionKind === "markdown_heading" || metadata.sectionKind === "html_heading" || metadata.sectionKind === "office_heading" || metadata.sectionKind === "spreadsheet_rows" || metadata.sectionKind === "presentation_slide" ? metadata.sectionKind : undefined;
1192
1268
  const section = {
1193
1269
  depth: getContextNumber2(metadata.sectionDepth),
1194
1270
  kind: sectionKind,
@@ -1217,6 +1293,52 @@ var buildExcerpt2 = (text, maxLength = 160) => {
1217
1293
  }
1218
1294
  return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
1219
1295
  };
1296
+ var buildRAGChunkExcerpts = (chunks, activeChunkId) => {
1297
+ if (chunks.length === 0) {
1298
+ return;
1299
+ }
1300
+ const graph = buildRAGChunkGraph(chunks.map((chunk) => ({
1301
+ chunkId: chunk.chunkId,
1302
+ metadata: chunk.metadata,
1303
+ structure: chunk.structure
1304
+ })));
1305
+ const navigation = buildRAGChunkGraphNavigation(graph, activeChunkId);
1306
+ const activeChunk = chunks.find((chunk) => chunk.chunkId === navigation.activeChunkId) ?? chunks[0];
1307
+ if (!activeChunk) {
1308
+ return;
1309
+ }
1310
+ const chunkMap = new Map(chunks.map((chunk) => [chunk.chunkId, chunk]));
1311
+ const orderedWindowIds = [
1312
+ navigation.previousNode?.chunkId,
1313
+ activeChunk.chunkId,
1314
+ navigation.nextNode?.chunkId
1315
+ ].filter((chunkId, index, ids) => Boolean(chunkId) && ids.indexOf(chunkId) === index);
1316
+ const orderedSectionIds = navigation.sectionNodes.length > 0 ? navigation.sectionNodes.map((node) => node.chunkId) : [activeChunk.chunkId];
1317
+ const collectText = (chunkIds) => chunkIds.map((chunkId) => chunkMap.get(chunkId)?.text).filter((text) => typeof text === "string").join(`
1318
+
1319
+ `);
1320
+ return {
1321
+ chunkExcerpt: buildExcerpt2(activeChunk.text, 160),
1322
+ sectionExcerpt: buildExcerpt2(collectText(orderedSectionIds), 320),
1323
+ windowExcerpt: buildExcerpt2(collectText(orderedWindowIds), 240)
1324
+ };
1325
+ };
1326
+ var buildRAGPreferredExcerpt = (excerpts, structure) => {
1327
+ if (!excerpts) {
1328
+ return "";
1329
+ }
1330
+ const chunkLength = excerpts.chunkExcerpt.trim().length;
1331
+ const sectionChunkCount = structure?.sequence?.sectionChunkCount ?? 1;
1332
+ if (sectionChunkCount > 1 && chunkLength > 0 && chunkLength < 72) {
1333
+ if (sectionChunkCount <= 3 && excerpts.sectionExcerpt.trim().length > 0) {
1334
+ return excerpts.sectionExcerpt;
1335
+ }
1336
+ if (excerpts.windowExcerpt.trim().length > 0) {
1337
+ return excerpts.windowExcerpt;
1338
+ }
1339
+ }
1340
+ return excerpts.chunkExcerpt;
1341
+ };
1220
1342
  var buildRAGChunkGraph = (chunks) => {
1221
1343
  const nodes = [];
1222
1344
  const edges = [];
@@ -1428,6 +1550,7 @@ var buildRAGSourceSummaries = (sources) => {
1428
1550
  return sourceGroups.map((group) => {
1429
1551
  const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
1430
1552
  const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
1553
+ const excerpts = leadChunk ? buildRAGChunkExcerpts(group.chunks, leadChunk.chunkId) : undefined;
1431
1554
  return {
1432
1555
  bestScore: group.bestScore,
1433
1556
  citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
@@ -1435,7 +1558,8 @@ var buildRAGSourceSummaries = (sources) => {
1435
1558
  chunkIds: group.chunks.map((chunk) => chunk.chunkId),
1436
1559
  contextLabel: leadChunk?.labels?.contextLabel ?? buildContextLabel2(leadChunk?.metadata),
1437
1560
  count: group.count,
1438
- excerpt: buildExcerpt2(leadChunk?.text ?? ""),
1561
+ excerpt: buildRAGPreferredExcerpt(excerpts, leadChunk?.structure ?? buildRAGChunkStructure(leadChunk?.metadata)) || buildExcerpt2(leadChunk?.text ?? ""),
1562
+ excerpts,
1439
1563
  key: group.key,
1440
1564
  label: group.label,
1441
1565
  locatorLabel: leadChunk?.labels?.locatorLabel ?? buildLocatorLabel2(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),