@absolutejs/absolute 0.19.0-beta.524 → 0.19.0-beta.526

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 (53) hide show
  1. package/dist/ai/client/index.js +83 -6
  2. package/dist/ai/client/index.js.map +3 -3
  3. package/dist/ai/index.js +82 -5
  4. package/dist/ai/index.js.map +3 -3
  5. package/dist/ai-client/angular/ai/index.js +880 -862
  6. package/dist/ai-client/react/ai/index.js +24 -24
  7. package/dist/ai-client/vue/ai/index.js +21 -21
  8. package/dist/angular/ai/index.js +873 -855
  9. package/dist/angular/ai/index.js.map +7 -6
  10. package/dist/angular/index.js +2 -2
  11. package/dist/angular/index.js.map +1 -1
  12. package/dist/angular/server.js +2 -2
  13. package/dist/angular/server.js.map +1 -1
  14. package/dist/build.js +2 -2
  15. package/dist/build.js.map +1 -1
  16. package/dist/index.js +2 -2
  17. package/dist/index.js.map +1 -1
  18. package/dist/react/ai/index.js +103 -26
  19. package/dist/react/ai/index.js.map +7 -7
  20. package/dist/src/ai/client/createRAGStream.d.ts +2 -0
  21. package/dist/src/ai/client/createRAGWorkflow.d.ts +3 -0
  22. package/dist/src/ai/client/index.d.ts +8 -7
  23. package/dist/src/ai/index.d.ts +5 -4
  24. package/dist/src/ai/rag/index.d.ts +2 -2
  25. package/dist/src/angular/ai/ai-rag-stream.service.d.ts +1 -1
  26. package/dist/src/angular/ai/ai-rag-workflow.service.d.ts +33 -0
  27. package/dist/src/angular/ai/index.d.ts +2 -1
  28. package/dist/src/react/ai/index.d.ts +6 -3
  29. package/dist/src/react/ai/useRAG.d.ts +3 -2
  30. package/dist/src/svelte/ai/createRAG.d.ts +5 -4
  31. package/dist/src/svelte/ai/createRAGStream.d.ts +1 -1
  32. package/dist/src/svelte/ai/createRAGStreamProgress.d.ts +1 -1
  33. package/dist/src/svelte/ai/createRAGWorkflow.d.ts +1 -1
  34. package/dist/src/svelte/ai/index.d.ts +4 -2
  35. package/dist/src/vue/ai/index.d.ts +5 -3
  36. package/dist/src/vue/ai/useRAG.d.ts +5 -4
  37. package/dist/src/vue/ai/useRAGStream.d.ts +1 -1
  38. package/dist/src/vue/ai/useRAGStreamProgress.d.ts +1 -1
  39. package/dist/src/vue/ai/useRAGWorkflow.d.ts +1 -1
  40. package/dist/svelte/ai/index.js +100 -23
  41. package/dist/svelte/ai/index.js.map +6 -6
  42. package/dist/types/ai.d.ts +11 -0
  43. package/dist/vue/ai/index.js +100 -23
  44. package/dist/vue/ai/index.js.map +7 -7
  45. package/package.json +7 -7
  46. package/dist/src/ai/client/createRAGTransport.d.ts +0 -2
  47. package/dist/src/angular/ai/ai-rag-transport.service.d.ts +0 -1
  48. package/dist/src/react/ai/useRAGTransport.d.ts +0 -2
  49. package/dist/src/react/ai/useRAGTransportProgress.d.ts +0 -2
  50. package/dist/src/svelte/ai/createRAGTransport.d.ts +0 -2
  51. package/dist/src/svelte/ai/createRAGTransportProgress.d.ts +0 -2
  52. package/dist/src/vue/ai/useRAGTransport.d.ts +0 -2
  53. package/dist/src/vue/ai/useRAGTransportProgress.d.ts +0 -2
@@ -703,917 +703,935 @@ class AIStreamService {
703
703
  AIStreamService = __legacyDecorateClassTS([
704
704
  Injectable({ providedIn: "root" })
705
705
  ], AIStreamService);
706
- // src/angular/ai/rag-client.service.ts
707
- import { Injectable as Injectable2 } from "@angular/core";
706
+ // src/angular/ai/ai-rag-workflow.service.ts
707
+ import { computed as computed3, Injectable as Injectable3 } from "@angular/core";
708
708
 
709
- // src/constants.ts
710
- var HOURS_IN_DAY = 24;
711
- var MILLISECONDS_IN_A_SECOND = 1000;
712
- var MINUTES_IN_AN_HOUR = 60;
713
- var SECONDS_IN_A_MINUTE = 60;
714
- var MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
715
- var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
716
- var TWO_THIRDS = 2 / 3;
717
- var UNFOUND_INDEX = -1;
709
+ // src/angular/ai/ai-rag-stream.service.ts
710
+ import { computed as computed2, Injectable as Injectable2 } from "@angular/core";
718
711
 
719
- // src/ai/client/ragClient.ts
720
- var jsonHeaders = {
721
- "Content-Type": "application/json"
712
+ // src/ai/rag/presentation.ts
713
+ var buildSourceGroupKey = (source) => source.source ?? source.title ?? source.chunkId;
714
+ var buildSourceLabel = (source) => source.source ?? source.title ?? source.chunkId;
715
+ var getContextNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
716
+ var getContextString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
717
+ var formatTimestampLabel = (value) => {
718
+ const timestamp = typeof value === "number" && Number.isFinite(value) ? value : typeof value === "string" ? Date.parse(value) : Number.NaN;
719
+ if (!Number.isFinite(timestamp)) {
720
+ return;
721
+ }
722
+ return new Date(timestamp).toLocaleString("en-US", {
723
+ dateStyle: "medium",
724
+ timeStyle: "short"
725
+ });
722
726
  };
723
- var normalizeBasePath = (path) => path.endsWith("/") ? path.slice(0, UNFOUND_INDEX) : path;
724
- var parseJson = async (response) => {
725
- const payload = JSON.parse(await response.text());
726
- return payload;
727
+ var formatMediaTimestamp = (value) => {
728
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
729
+ return;
730
+ }
731
+ const totalSeconds = Math.floor(value / 1000);
732
+ const minutes = Math.floor(totalSeconds / 60);
733
+ const seconds = totalSeconds % 60;
734
+ const milliseconds = Math.floor(value % 1000);
735
+ return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds).padStart(3, "0")}`;
727
736
  };
728
- var isErrorPayload = (value) => {
729
- if (!value || typeof value !== "object") {
730
- return false;
737
+ var getAttachmentName = (source, title) => {
738
+ const sourceAttachment = source?.split("/").at(-1);
739
+ if (sourceAttachment && sourceAttachment.includes(".")) {
740
+ return sourceAttachment;
731
741
  }
732
- return !("error" in value) || typeof value.error === "string";
742
+ const titleAttachment = title?.split(" · ").at(-1);
743
+ if (titleAttachment && titleAttachment.includes(".")) {
744
+ return titleAttachment;
745
+ }
746
+ return;
733
747
  };
734
- var toErrorMessage = async (response) => {
735
- try {
736
- const payload = JSON.parse(await response.text());
737
- if (isErrorPayload(payload) && typeof payload.error === "string" && payload.error) {
738
- return payload.error;
748
+ var buildContextLabel = (metadata) => {
749
+ if (!metadata) {
750
+ return;
751
+ }
752
+ const emailKind = getContextString(metadata.emailKind);
753
+ if (emailKind === "attachment") {
754
+ return "Attachment evidence";
755
+ }
756
+ if (emailKind === "message") {
757
+ const from = getContextString(metadata.from);
758
+ return from ? `Message from ${from}` : "Message evidence";
759
+ }
760
+ const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
761
+ if (page) {
762
+ return `Page ${page}`;
763
+ }
764
+ const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
765
+ if (sheet) {
766
+ return `Sheet ${sheet}`;
767
+ }
768
+ const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
769
+ if (slide) {
770
+ return `Slide ${slide}`;
771
+ }
772
+ const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
773
+ if (archiveEntry) {
774
+ return `Archive entry ${archiveEntry}`;
775
+ }
776
+ const threadTopic = getContextString(metadata.threadTopic);
777
+ if (threadTopic) {
778
+ return `Thread ${threadTopic}`;
779
+ }
780
+ const speaker = getContextString(metadata.speaker);
781
+ if (speaker) {
782
+ return `Speaker ${speaker}`;
783
+ }
784
+ return;
785
+ };
786
+ var buildLocatorLabel = (metadata, source, title) => {
787
+ if (!metadata) {
788
+ return;
789
+ }
790
+ const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
791
+ if (page) {
792
+ return `Page ${page}`;
793
+ }
794
+ const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
795
+ if (sheet) {
796
+ return `Sheet ${sheet}`;
797
+ }
798
+ const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
799
+ if (slide) {
800
+ return `Slide ${slide}`;
801
+ }
802
+ const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
803
+ if (archiveEntry) {
804
+ return `Archive entry ${archiveEntry}`;
805
+ }
806
+ const emailKind = getContextString(metadata.emailKind);
807
+ if (emailKind === "attachment") {
808
+ const attachmentName = getContextString(metadata.attachmentName) ?? getAttachmentName(source, title);
809
+ return attachmentName ? `Attachment ${attachmentName}` : "Attachment";
810
+ }
811
+ const mediaStart = formatMediaTimestamp(metadata.startMs);
812
+ const mediaEnd = formatMediaTimestamp(metadata.endMs);
813
+ if (mediaStart && mediaEnd) {
814
+ return `Timestamp ${mediaStart} - ${mediaEnd}`;
815
+ }
816
+ if (mediaStart) {
817
+ return `Timestamp ${mediaStart}`;
818
+ }
819
+ return;
820
+ };
821
+ var buildProvenanceLabel = (metadata) => {
822
+ if (!metadata) {
823
+ return;
824
+ }
825
+ const threadTopic = getContextString(metadata.threadTopic);
826
+ const from = getContextString(metadata.from);
827
+ const sentAt = formatTimestampLabel(metadata.sentAt) ?? formatTimestampLabel(metadata.receivedAt);
828
+ const speaker = getContextString(metadata.speaker);
829
+ const mediaKind = getContextString(metadata.mediaKind);
830
+ const transcriptSource = getContextString(metadata.transcriptSource);
831
+ const pdfTextMode = getContextString(metadata.pdfTextMode);
832
+ const ocrEngine = getContextString(metadata.ocrEngine);
833
+ const labels = [
834
+ pdfTextMode ? `PDF ${pdfTextMode}` : "",
835
+ ocrEngine ? `OCR ${ocrEngine}` : "",
836
+ mediaKind ? `Media ${mediaKind}` : "",
837
+ transcriptSource ? `Transcript ${transcriptSource}` : "",
838
+ threadTopic ? `Thread ${threadTopic}` : "",
839
+ speaker ? `Speaker ${speaker}` : "",
840
+ from ? `Sender ${from}` : "",
841
+ sentAt ? `Sent ${sentAt}` : ""
842
+ ].filter((value) => value.length > 0);
843
+ return labels.length > 0 ? labels.join(" · ") : undefined;
844
+ };
845
+ var buildRAGCitationReferenceMap = (citations) => Object.fromEntries(citations.map((citation, index) => [citation.chunkId, index + 1]));
846
+ var buildRAGCitations = (sources) => {
847
+ const unique = new Map;
848
+ for (const source of sources) {
849
+ const key = source.chunkId;
850
+ const existing = unique.get(key);
851
+ const hasBetterExisting = existing !== undefined && existing.score >= source.score;
852
+ if (hasBetterExisting)
853
+ continue;
854
+ unique.set(key, {
855
+ chunkId: source.chunkId,
856
+ contextLabel: buildContextLabel(source.metadata),
857
+ key,
858
+ label: buildSourceLabel(source),
859
+ locatorLabel: buildLocatorLabel(source.metadata, source.source, source.title),
860
+ metadata: source.metadata,
861
+ provenanceLabel: buildProvenanceLabel(source.metadata),
862
+ score: source.score,
863
+ source: source.source,
864
+ text: source.text,
865
+ title: source.title
866
+ });
867
+ }
868
+ return [...unique.values()].sort((left, right) => {
869
+ if (right.score !== left.score) {
870
+ return right.score - left.score;
739
871
  }
740
- } catch {}
741
- return `Request failed with status ${response.status}`;
872
+ return left.label.localeCompare(right.label);
873
+ });
742
874
  };
743
- var createRAGClient = (options) => {
744
- const basePath = normalizeBasePath(options.path);
745
- const fetchImpl = options.fetch ?? fetch;
746
- return {
747
- async backends() {
748
- const response = await fetchImpl(`${basePath}/backends`);
749
- if (!response.ok) {
750
- throw new Error(await toErrorMessage(response));
751
- }
752
- return parseJson(response);
753
- },
754
- async clearIndex() {
755
- const response = await fetchImpl(`${basePath}/index`, {
756
- method: "DELETE"
875
+ var buildExcerpt = (text, maxLength = 160) => {
876
+ const normalized = text.replaceAll(/\s+/g, " ").trim();
877
+ if (normalized.length <= maxLength) {
878
+ return normalized;
879
+ }
880
+ return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
881
+ };
882
+ 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(" · ");
883
+ var buildGroundingReferenceEvidenceSummary = (reference) => [
884
+ reference.source ?? reference.title ?? reference.chunkId,
885
+ reference.provenanceLabel
886
+ ].filter((value) => Boolean(value && value.length > 0)).join(" · ");
887
+ var buildGroundedAnswerCitationDetail = (reference) => ({
888
+ contextLabel: reference.contextLabel,
889
+ evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
890
+ evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
891
+ excerpt: reference.excerpt,
892
+ label: reference.label,
893
+ locatorLabel: reference.locatorLabel,
894
+ number: reference.number,
895
+ provenanceLabel: reference.provenanceLabel,
896
+ source: reference.source,
897
+ title: reference.title
898
+ });
899
+ var buildRAGGroundedAnswer = (content, sources) => {
900
+ const references = buildRAGGroundingReferences(sources);
901
+ const referenceMap = new Map(references.map((reference) => [reference.number, reference]));
902
+ const parts = [];
903
+ const ungroundedReferenceNumbers = new Set;
904
+ const citationPattern = /\[(\d+(?:\s*,\s*\d+)*)\]/g;
905
+ let cursor = 0;
906
+ for (const match of content.matchAll(citationPattern)) {
907
+ const raw = match[0];
908
+ const numbers = (match[1] ?? "").split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isInteger(value) && value > 0);
909
+ const start = match.index ?? cursor;
910
+ if (start > cursor) {
911
+ parts.push({
912
+ text: content.slice(cursor, start),
913
+ type: "text"
757
914
  });
758
- if (!response.ok) {
759
- throw new Error(await toErrorMessage(response));
915
+ }
916
+ const resolvedReferences = numbers.map((number) => referenceMap.get(number)).filter((reference) => Boolean(reference));
917
+ for (const number of numbers) {
918
+ if (!referenceMap.has(number)) {
919
+ ungroundedReferenceNumbers.add(number);
760
920
  }
761
- return parseJson(response);
762
- },
763
- async createDocument(input) {
764
- const response = await fetchImpl(`${basePath}/documents`, {
765
- body: JSON.stringify(input),
766
- headers: jsonHeaders,
767
- method: "POST"
768
- });
769
- if (!response.ok) {
770
- return {
771
- error: await toErrorMessage(response),
772
- ok: false
773
- };
774
- }
775
- return parseJson(response);
776
- },
777
- async deleteDocument(id) {
778
- const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}`, {
779
- method: "DELETE"
780
- });
781
- if (!response.ok) {
782
- return {
783
- error: await toErrorMessage(response),
784
- ok: false
785
- };
786
- }
787
- return parseJson(response);
788
- },
789
- async documentChunks(id) {
790
- const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}/chunks`);
791
- if (!response.ok) {
792
- const error = await toErrorMessage(response);
793
- const errorResponse = {
794
- error,
795
- ok: false
796
- };
797
- return errorResponse;
798
- }
799
- return parseJson(response);
800
- },
801
- async documents(kind) {
802
- const query = kind ? `?kind=${encodeURIComponent(kind)}` : "";
803
- const response = await fetchImpl(`${basePath}/documents${query}`);
804
- if (!response.ok) {
805
- throw new Error(await toErrorMessage(response));
806
- }
807
- return parseJson(response);
808
- },
809
- async evaluate(input) {
810
- const response = await fetchImpl(`${basePath}/evaluate`, {
811
- body: JSON.stringify(input),
812
- headers: jsonHeaders,
813
- method: "POST"
814
- });
815
- if (!response.ok) {
816
- throw new Error(await toErrorMessage(response));
817
- }
818
- return parseJson(response);
819
- },
820
- async ingest(chunks) {
821
- const response = await fetchImpl(`${basePath}/ingest`, {
822
- body: JSON.stringify({ chunks }),
823
- headers: jsonHeaders,
824
- method: "POST"
825
- });
826
- if (!response.ok) {
827
- return {
828
- error: await toErrorMessage(response),
829
- ok: false
830
- };
831
- }
832
- return parseJson(response);
833
- },
834
- async ingestDocuments(input) {
835
- const response = await fetchImpl(`${basePath}/ingest`, {
836
- body: JSON.stringify(input),
837
- headers: jsonHeaders,
838
- method: "POST"
839
- });
840
- if (!response.ok) {
841
- return {
842
- error: await toErrorMessage(response),
843
- ok: false
844
- };
845
- }
846
- return parseJson(response);
847
- },
848
- async ingestUploads(input) {
849
- const response = await fetchImpl(`${basePath}/ingest`, {
850
- body: JSON.stringify(input),
851
- headers: jsonHeaders,
852
- method: "POST"
853
- });
854
- if (!response.ok) {
855
- return {
856
- error: await toErrorMessage(response),
857
- ok: false
858
- };
859
- }
860
- return parseJson(response);
861
- },
862
- async ingestUrls(input) {
863
- const response = await fetchImpl(`${basePath}/ingest`, {
864
- body: JSON.stringify(input),
865
- headers: jsonHeaders,
866
- method: "POST"
867
- });
868
- if (!response.ok) {
869
- return {
870
- error: await toErrorMessage(response),
871
- ok: false
872
- };
873
- }
874
- return parseJson(response);
875
- },
876
- async ops() {
877
- const response = await fetchImpl(`${basePath}/ops`);
878
- if (!response.ok) {
879
- throw new Error(await toErrorMessage(response));
880
- }
881
- return parseJson(response);
882
- },
883
- async syncSources() {
884
- const response = await fetchImpl(`${basePath}/sync`);
885
- if (!response.ok) {
886
- throw new Error(await toErrorMessage(response));
887
- }
888
- return parseJson(response);
889
- },
890
- async syncAllSources(options2) {
891
- const response = await fetchImpl(`${basePath}/sync`, {
892
- body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
893
- headers: options2?.background === true ? jsonHeaders : undefined,
894
- method: "POST"
895
- });
896
- if (!response.ok) {
897
- return {
898
- error: await toErrorMessage(response),
899
- ok: false
900
- };
901
- }
902
- return parseJson(response);
903
- },
904
- async syncSource(id, options2) {
905
- const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
906
- body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
907
- headers: options2?.background === true ? jsonHeaders : undefined,
908
- method: "POST"
909
- });
910
- if (!response.ok) {
911
- return {
912
- error: await toErrorMessage(response),
913
- ok: false
914
- };
915
- }
916
- return parseJson(response);
917
- },
918
- async reindexDocument(id) {
919
- const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
920
- method: "POST"
921
- });
922
- if (!response.ok) {
923
- return {
924
- error: await toErrorMessage(response),
925
- ok: false
926
- };
927
- }
928
- return parseJson(response);
929
- },
930
- async reindexSource(source) {
931
- const response = await fetchImpl(`${basePath}/reindex/source`, {
932
- body: JSON.stringify({ source }),
933
- headers: jsonHeaders,
934
- method: "POST"
935
- });
936
- if (!response.ok) {
937
- return {
938
- error: await toErrorMessage(response),
939
- ok: false
940
- };
941
- }
942
- return parseJson(response);
943
- },
944
- async reseed() {
945
- const response = await fetchImpl(`${basePath}/reseed`, {
946
- method: "POST"
947
- });
948
- if (!response.ok) {
949
- return {
950
- error: await toErrorMessage(response),
951
- ok: false
952
- };
953
- }
954
- return parseJson(response);
955
- },
956
- async reset() {
957
- const response = await fetchImpl(`${basePath}/reset`, {
958
- method: "POST"
959
- });
960
- if (!response.ok) {
961
- return {
962
- error: await toErrorMessage(response),
963
- ok: false
964
- };
965
- }
966
- return parseJson(response);
967
- },
968
- async search(input) {
969
- const response = await fetchImpl(`${basePath}/search`, {
970
- body: JSON.stringify(input),
971
- headers: jsonHeaders,
972
- method: "POST"
973
- });
974
- if (!response.ok) {
975
- throw new Error(await toErrorMessage(response));
976
- }
977
- const payload = await parseJson(response);
978
- if (!payload.ok) {
979
- throw new Error(payload.error ?? "RAG search failed");
980
- }
981
- return payload.results ?? [];
982
- },
983
- async status() {
984
- const response = await fetchImpl(`${basePath}/status`);
985
- if (!response.ok) {
986
- throw new Error(await toErrorMessage(response));
987
- }
988
- return parseJson(response);
989
- }
990
- };
991
- };
992
-
993
- // src/angular/ai/rag-client.service.ts
994
- class RAGClientService {
995
- clients = new Map;
996
- client(path) {
997
- const existing = this.clients.get(path);
998
- if (existing) {
999
- return existing;
1000
921
  }
1001
- const created = createRAGClient({ path });
1002
- this.clients.set(path, created);
1003
- return created;
1004
- }
1005
- ingest(path, chunks) {
1006
- return this.client(path).ingest(chunks);
1007
- }
1008
- ingestDocuments(path, input) {
1009
- return this.client(path).ingestDocuments(input);
922
+ const unresolvedNumbers = numbers.filter((number) => !referenceMap.has(number));
923
+ parts.push({
924
+ referenceNumbers: numbers,
925
+ referenceDetails: resolvedReferences.map(buildGroundedAnswerCitationDetail),
926
+ references: resolvedReferences,
927
+ text: raw,
928
+ type: "citation",
929
+ unresolvedReferenceNumbers: unresolvedNumbers
930
+ });
931
+ cursor = start + raw.length;
1010
932
  }
1011
- ingestUrls(path, input) {
1012
- return this.client(path).ingestUrls(input);
933
+ if (cursor < content.length || parts.length === 0) {
934
+ parts.push({
935
+ text: content.slice(cursor),
936
+ type: "text"
937
+ });
1013
938
  }
1014
- ingestUploads(path, input) {
1015
- return this.client(path).ingestUploads(input);
1016
- }
1017
- search(path, input) {
1018
- return this.client(path).search(input);
939
+ const hasCitations = parts.some((part) => part.type === "citation");
940
+ const coverage = !hasCitations ? "ungrounded" : ungroundedReferenceNumbers.size === 0 ? "grounded" : references.length > 0 ? "partial" : "ungrounded";
941
+ return {
942
+ content,
943
+ coverage,
944
+ hasCitations,
945
+ parts,
946
+ references,
947
+ ungroundedReferenceNumbers: [...ungroundedReferenceNumbers].sort((left, right) => left - right)
948
+ };
949
+ };
950
+ var buildRAGGroundingReferences = (sources) => {
951
+ const citations = buildRAGCitations(sources);
952
+ const citationReferenceMap = buildRAGCitationReferenceMap(citations);
953
+ return citations.map((citation) => ({
954
+ chunkId: citation.chunkId,
955
+ contextLabel: buildContextLabel(citation.metadata),
956
+ excerpt: buildExcerpt(citation.text),
957
+ label: citation.label,
958
+ locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
959
+ metadata: citation.metadata,
960
+ number: citationReferenceMap[citation.chunkId] ?? 0,
961
+ provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
962
+ score: citation.score,
963
+ source: citation.source,
964
+ text: citation.text,
965
+ title: citation.title
966
+ }));
967
+ };
968
+ var buildRAGRetrievedState = (messages) => {
969
+ const message = getLatestRetrievedMessage(messages);
970
+ if (!message) {
971
+ return null;
1019
972
  }
1020
- evaluate(path, input) {
1021
- return this.client(path).evaluate(input);
973
+ const sources = message.sources ?? [];
974
+ const groundedAnswer = buildRAGGroundedAnswer(message.content, sources);
975
+ return {
976
+ citationReferenceMap: buildRAGCitationReferenceMap(buildRAGCitations(sources)),
977
+ citations: buildRAGCitations(sources),
978
+ conversationId: message.conversationId,
979
+ groundedAnswer,
980
+ messageId: message.id,
981
+ retrievalDurationMs: message.retrievalDurationMs,
982
+ retrievalStartedAt: message.retrievalStartedAt,
983
+ retrievedAt: message.retrievedAt,
984
+ sourceGroups: buildRAGSourceGroups(sources),
985
+ sourceSummaries: buildRAGSourceSummaries(sources),
986
+ sources
987
+ };
988
+ };
989
+ var buildRAGSourceSummaries = (sources) => {
990
+ const sourceGroups = buildRAGSourceGroups(sources);
991
+ const citations = buildRAGCitations(sources);
992
+ const citationReferenceMap = buildRAGCitationReferenceMap(citations);
993
+ return sourceGroups.map((group) => {
994
+ const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
995
+ const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
996
+ return {
997
+ bestScore: group.bestScore,
998
+ citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
999
+ citations: groupCitations,
1000
+ chunkIds: group.chunks.map((chunk) => chunk.chunkId),
1001
+ contextLabel: buildContextLabel(leadChunk?.metadata),
1002
+ count: group.count,
1003
+ excerpt: buildExcerpt(leadChunk?.text ?? ""),
1004
+ key: group.key,
1005
+ label: group.label,
1006
+ locatorLabel: buildLocatorLabel(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),
1007
+ provenanceLabel: buildProvenanceLabel(leadChunk?.metadata),
1008
+ source: group.source,
1009
+ title: group.title
1010
+ };
1011
+ });
1012
+ };
1013
+ var buildStreamProgressState = (messages) => {
1014
+ const latestMessage = getLatestAssistantMessage(messages);
1015
+ const retrieved = latestMessage ? buildRAGRetrievedState(messages) : undefined;
1016
+ return {
1017
+ conversationId: latestMessage?.conversationId,
1018
+ latestMessage,
1019
+ messageId: latestMessage?.id,
1020
+ retrieved,
1021
+ sourceCount: retrieved?.sources.length ?? latestMessage?.sources?.length ?? 0
1022
+ };
1023
+ };
1024
+ var buildRAGStreamProgress = ({
1025
+ error,
1026
+ isStreaming,
1027
+ messages
1028
+ }) => {
1029
+ const stage = resolveRAGStreamStage({
1030
+ error,
1031
+ isStreaming,
1032
+ messages
1033
+ });
1034
+ const state = buildStreamProgressState(messages);
1035
+ const hasSources = state.sourceCount > 0;
1036
+ const hasRetrieved = stage === "retrieved" || state.retrieved !== undefined || state.latestMessage?.retrievedAt !== undefined;
1037
+ const hasThinking = typeof state.latestMessage?.thinking === "string" && state.latestMessage.thinking.length > 0;
1038
+ const hasToolCalls = (state.latestMessage?.toolCalls?.length ?? 0) > 0;
1039
+ return {
1040
+ conversationId: state.conversationId,
1041
+ hasContent: typeof state.latestMessage?.content === "string" && state.latestMessage.content.length > 0,
1042
+ hasRetrieved,
1043
+ hasSources,
1044
+ hasThinking,
1045
+ hasToolCalls,
1046
+ isComplete: stage === "complete",
1047
+ isError: stage === "error",
1048
+ isIdle: stage === "idle",
1049
+ isRetrieved: stage === "retrieved",
1050
+ isRetrieving: stage === "submitting" || stage === "retrieving",
1051
+ isStreaming: stage === "streaming",
1052
+ isSubmitting: stage === "submitting",
1053
+ latestMessage: state.latestMessage,
1054
+ messageId: state.messageId,
1055
+ retrievalDurationMs: state.retrieved?.retrievalDurationMs,
1056
+ retrievalStartedAt: state.retrieved?.retrievalStartedAt,
1057
+ retrievedAt: state.retrieved?.retrievedAt,
1058
+ sourceCount: state.sourceCount,
1059
+ stage
1060
+ };
1061
+ };
1062
+ var buildRAGAnswerWorkflowState = ({
1063
+ error,
1064
+ isStreaming,
1065
+ messages
1066
+ }) => {
1067
+ const latestAssistantMessage = getLatestAssistantMessage(messages);
1068
+ const sources = getLatestRAGSources(messages);
1069
+ const sourceGroups = buildRAGSourceGroups(sources);
1070
+ const citations = buildRAGCitations(sources);
1071
+ const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1072
+ const sourceSummaries = buildRAGSourceSummaries(sources);
1073
+ const groundingReferences = buildRAGGroundingReferences(sources);
1074
+ const groundedAnswer = buildRAGGroundedAnswer(latestAssistantMessage?.content ?? "", sources);
1075
+ const retrieval = buildRAGRetrievedState(messages);
1076
+ const progress = buildRAGStreamProgress({
1077
+ error,
1078
+ isStreaming,
1079
+ messages
1080
+ });
1081
+ return {
1082
+ citationReferenceMap,
1083
+ citations,
1084
+ coverage: groundedAnswer.coverage,
1085
+ error,
1086
+ groundedAnswer,
1087
+ groundingReferences,
1088
+ hasCitations: groundedAnswer.hasCitations,
1089
+ hasGrounding: groundingReferences.length > 0,
1090
+ hasRetrieved: progress.hasRetrieved,
1091
+ hasSources: sources.length > 0,
1092
+ isAnswerStreaming: progress.isStreaming,
1093
+ isComplete: progress.isComplete,
1094
+ isError: progress.isError,
1095
+ isIdle: progress.isIdle,
1096
+ isRetrieved: progress.isRetrieved,
1097
+ isRetrieving: progress.isRetrieving,
1098
+ isRunning: progress.isSubmitting || progress.isRetrieving || progress.isStreaming,
1099
+ isSubmitting: progress.isSubmitting,
1100
+ latestAssistantMessage,
1101
+ messages,
1102
+ retrieval,
1103
+ retrievalDurationMs: retrieval?.retrievalDurationMs,
1104
+ retrievalStartedAt: retrieval?.retrievalStartedAt,
1105
+ retrievedAt: retrieval?.retrievedAt,
1106
+ sourceGroups,
1107
+ sourceSummaries,
1108
+ sources,
1109
+ stage: progress.stage,
1110
+ ungroundedReferenceNumbers: groundedAnswer.ungroundedReferenceNumbers
1111
+ };
1112
+ };
1113
+ var buildRAGSourceGroups = (sources) => {
1114
+ const groups = new Map;
1115
+ for (const source of sources) {
1116
+ updateSourceGroup(groups, source);
1022
1117
  }
1023
- status(path) {
1024
- return this.client(path).status();
1118
+ return [...groups.values()].sort((left, right) => {
1119
+ if (right.bestScore !== left.bestScore) {
1120
+ return right.bestScore - left.bestScore;
1121
+ }
1122
+ return left.label.localeCompare(right.label);
1123
+ });
1124
+ };
1125
+ var buildSourceGroup = (source, key) => ({
1126
+ bestScore: source.score,
1127
+ chunks: [source],
1128
+ count: 1,
1129
+ key,
1130
+ label: buildSourceLabel(source),
1131
+ source: source.source,
1132
+ title: source.title
1133
+ });
1134
+ var updateSourceGroup = (groups, source) => {
1135
+ const key = buildSourceGroupKey(source);
1136
+ const existing = groups.get(key);
1137
+ if (!existing) {
1138
+ groups.set(key, buildSourceGroup(source, key));
1139
+ return;
1025
1140
  }
1026
- ops(path) {
1027
- return this.client(path).ops();
1141
+ existing.bestScore = Math.max(existing.bestScore, source.score);
1142
+ existing.count += 1;
1143
+ existing.chunks.push(source);
1144
+ };
1145
+ var getLatestAssistantMessage = (messages) => {
1146
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
1147
+ const message = messages[index];
1148
+ if (message?.role === "assistant") {
1149
+ return message;
1150
+ }
1028
1151
  }
1029
- syncSources(path) {
1030
- return this.client(path).syncSources();
1152
+ return;
1153
+ };
1154
+ var getLatestRAGSources = (messages) => getLatestAssistantMessage(messages)?.sources ?? [];
1155
+ var getLatestRetrievedMessage = (messages) => {
1156
+ for (let index = messages.length - 1;index >= 0; index -= 1) {
1157
+ const message = messages[index];
1158
+ if (message?.role === "assistant" && (typeof message.retrievedAt === "number" || (message.sources?.length ?? 0) > 0)) {
1159
+ return message;
1160
+ }
1031
1161
  }
1032
- syncAllSources(path, options) {
1033
- return this.client(path).syncAllSources(options);
1162
+ return;
1163
+ };
1164
+ var resolveRAGStreamStage = ({
1165
+ error,
1166
+ isStreaming,
1167
+ messages
1168
+ }) => {
1169
+ if (error) {
1170
+ return "error";
1034
1171
  }
1035
- syncSource(path, id, options) {
1036
- return this.client(path).syncSource(id, options);
1172
+ const assistantMessage = getLatestAssistantMessage(messages);
1173
+ if (!assistantMessage) {
1174
+ return isStreaming ? "submitting" : "idle";
1037
1175
  }
1038
- documents(path, kind) {
1039
- return this.client(path).documents(kind);
1176
+ const isRetrieving = typeof assistantMessage.retrievalStartedAt === "number" && typeof assistantMessage.retrievedAt !== "number";
1177
+ if (isRetrieving) {
1178
+ return "retrieving";
1040
1179
  }
1041
- documentChunks(path, id) {
1042
- return this.client(path).documentChunks(id);
1180
+ if (!isStreaming) {
1181
+ return "complete";
1043
1182
  }
1044
- createDocument(path, input) {
1045
- return this.client(path).createDocument(input);
1046
- }
1047
- deleteDocument(path, id) {
1048
- return this.client(path).deleteDocument(id);
1049
- }
1050
- reseed(path) {
1051
- return this.client(path).reseed();
1052
- }
1053
- reset(path) {
1054
- return this.client(path).reset();
1055
- }
1056
- reindexDocument(path, id) {
1057
- return this.client(path).reindexDocument(id);
1058
- }
1059
- reindexSource(path, source) {
1060
- return this.client(path).reindexSource(source);
1061
- }
1062
- backends(path) {
1063
- return this.client(path).backends();
1183
+ const hasRetrieved = typeof assistantMessage.retrievedAt === "number";
1184
+ const hasContent = assistantMessage.content.trim().length > 0 || assistantMessage.thinking?.trim().length || (assistantMessage.toolCalls?.length ?? 0) > 0 || (assistantMessage.images?.length ?? 0) > 0;
1185
+ if (hasRetrieved && !hasContent) {
1186
+ return "retrieved";
1064
1187
  }
1065
- clearIndex(path) {
1066
- return this.client(path).clearIndex();
1188
+ return "streaming";
1189
+ };
1190
+
1191
+ // src/angular/ai/ai-rag-stream.service.ts
1192
+ class RAGStreamService extends AIStreamService {
1193
+ connect(path, conversationId) {
1194
+ const stream = super.connect(path, conversationId);
1195
+ const workflow = computed2(() => buildRAGAnswerWorkflowState({
1196
+ error: stream.error(),
1197
+ isStreaming: stream.isStreaming(),
1198
+ messages: stream.messages()
1199
+ }));
1200
+ const progress = computed2(() => buildRAGStreamProgress({
1201
+ error: stream.error(),
1202
+ isStreaming: stream.isStreaming(),
1203
+ messages: stream.messages()
1204
+ }));
1205
+ const latestAssistantMessage = computed2(() => workflow().latestAssistantMessage);
1206
+ const sources = computed2(() => workflow().sources);
1207
+ const sourceGroups = computed2(() => workflow().sourceGroups);
1208
+ const citations = computed2(() => workflow().citations);
1209
+ const sourceSummaries = computed2(() => workflow().sourceSummaries);
1210
+ const citationReferenceMap = computed2(() => workflow().citationReferenceMap);
1211
+ const retrieval = computed2(() => workflow().retrieval);
1212
+ const groundedAnswer = computed2(() => workflow().groundedAnswer);
1213
+ const groundingReferences = computed2(() => workflow().groundingReferences);
1214
+ const hasRetrieved = computed2(() => workflow().hasRetrieved);
1215
+ const hasSources = computed2(() => workflow().hasSources);
1216
+ const isRetrieving = computed2(() => workflow().isRetrieving);
1217
+ const isRetrieved = computed2(() => workflow().isRetrieved);
1218
+ const isAnswerStreaming = computed2(() => workflow().isAnswerStreaming);
1219
+ const isComplete = computed2(() => workflow().isComplete);
1220
+ const isError = computed2(() => workflow().isError);
1221
+ const isRunning = computed2(() => workflow().isRunning);
1222
+ const stage = computed2(() => workflow().stage);
1223
+ return {
1224
+ ...stream,
1225
+ citations,
1226
+ citationReferenceMap,
1227
+ groundedAnswer,
1228
+ groundingReferences,
1229
+ hasRetrieved,
1230
+ hasSources,
1231
+ isAnswerStreaming,
1232
+ isComplete,
1233
+ isError,
1234
+ isRetrieved,
1235
+ isRetrieving,
1236
+ isRunning,
1237
+ latestAssistantMessage,
1238
+ progress,
1239
+ query: stream.send,
1240
+ retrieval,
1241
+ sourceGroups,
1242
+ sourceSummaries,
1243
+ sources,
1244
+ stage,
1245
+ workflow
1246
+ };
1067
1247
  }
1068
1248
  }
1069
- RAGClientService = __legacyDecorateClassTS([
1249
+ RAGStreamService = __legacyDecorateClassTS([
1070
1250
  Injectable2({ providedIn: "root" })
1071
- ], RAGClientService);
1072
- // src/angular/ai/ai-rag-stream.service.ts
1073
- import { computed as computed2, Injectable as Injectable3 } from "@angular/core";
1251
+ ], RAGStreamService);
1074
1252
 
1075
- // src/ai/rag/presentation.ts
1076
- var buildSourceGroupKey = (source) => source.source ?? source.title ?? source.chunkId;
1077
- var buildSourceLabel = (source) => source.source ?? source.title ?? source.chunkId;
1078
- var getContextNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : undefined;
1079
- var getContextString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
1080
- var formatTimestampLabel = (value) => {
1081
- const timestamp = typeof value === "number" && Number.isFinite(value) ? value : typeof value === "string" ? Date.parse(value) : Number.NaN;
1082
- if (!Number.isFinite(timestamp)) {
1083
- return;
1084
- }
1085
- return new Date(timestamp).toLocaleString("en-US", {
1086
- dateStyle: "medium",
1087
- timeStyle: "short"
1088
- });
1089
- };
1090
- var formatMediaTimestamp = (value) => {
1091
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0) {
1092
- return;
1093
- }
1094
- const totalSeconds = Math.floor(value / 1000);
1095
- const minutes = Math.floor(totalSeconds / 60);
1096
- const seconds = totalSeconds % 60;
1097
- const milliseconds = Math.floor(value % 1000);
1098
- return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}.${String(milliseconds).padStart(3, "0")}`;
1099
- };
1100
- var getAttachmentName = (source, title) => {
1101
- const sourceAttachment = source?.split("/").at(-1);
1102
- if (sourceAttachment && sourceAttachment.includes(".")) {
1103
- return sourceAttachment;
1104
- }
1105
- const titleAttachment = title?.split(" · ").at(-1);
1106
- if (titleAttachment && titleAttachment.includes(".")) {
1107
- return titleAttachment;
1253
+ // src/angular/ai/ai-rag-workflow.service.ts
1254
+ class RAGWorkflowService extends RAGStreamService {
1255
+ connect(path, conversationId) {
1256
+ const stream = super.connect(path, conversationId);
1257
+ return {
1258
+ ...stream,
1259
+ state: computed3(() => stream.workflow())
1260
+ };
1108
1261
  }
1109
- return;
1262
+ }
1263
+ RAGWorkflowService = __legacyDecorateClassTS([
1264
+ Injectable3({ providedIn: "root" })
1265
+ ], RAGWorkflowService);
1266
+ // src/angular/ai/rag-client.service.ts
1267
+ import { Injectable as Injectable4 } from "@angular/core";
1268
+
1269
+ // src/constants.ts
1270
+ var HOURS_IN_DAY = 24;
1271
+ var MILLISECONDS_IN_A_SECOND = 1000;
1272
+ var MINUTES_IN_AN_HOUR = 60;
1273
+ var SECONDS_IN_A_MINUTE = 60;
1274
+ var MILLISECONDS_IN_A_MINUTE = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE;
1275
+ var MILLISECONDS_IN_A_DAY = MILLISECONDS_IN_A_SECOND * SECONDS_IN_A_MINUTE * MINUTES_IN_AN_HOUR * HOURS_IN_DAY;
1276
+ var TWO_THIRDS = 2 / 3;
1277
+ var UNFOUND_INDEX = -1;
1278
+
1279
+ // src/ai/client/ragClient.ts
1280
+ var jsonHeaders = {
1281
+ "Content-Type": "application/json"
1110
1282
  };
1111
- var buildContextLabel = (metadata) => {
1112
- if (!metadata) {
1113
- return;
1114
- }
1115
- const emailKind = getContextString(metadata.emailKind);
1116
- if (emailKind === "attachment") {
1117
- return "Attachment evidence";
1118
- }
1119
- if (emailKind === "message") {
1120
- const from = getContextString(metadata.from);
1121
- return from ? `Message from ${from}` : "Message evidence";
1122
- }
1123
- const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
1124
- if (page) {
1125
- return `Page ${page}`;
1126
- }
1127
- const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
1128
- if (sheet) {
1129
- return `Sheet ${sheet}`;
1130
- }
1131
- const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
1132
- if (slide) {
1133
- return `Slide ${slide}`;
1134
- }
1135
- const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
1136
- if (archiveEntry) {
1137
- return `Archive entry ${archiveEntry}`;
1138
- }
1139
- const threadTopic = getContextString(metadata.threadTopic);
1140
- if (threadTopic) {
1141
- return `Thread ${threadTopic}`;
1142
- }
1143
- const speaker = getContextString(metadata.speaker);
1144
- if (speaker) {
1145
- return `Speaker ${speaker}`;
1146
- }
1147
- return;
1283
+ var normalizeBasePath = (path) => path.endsWith("/") ? path.slice(0, UNFOUND_INDEX) : path;
1284
+ var parseJson = async (response) => {
1285
+ const payload = JSON.parse(await response.text());
1286
+ return payload;
1148
1287
  };
1149
- var buildLocatorLabel = (metadata, source, title) => {
1150
- if (!metadata) {
1151
- return;
1152
- }
1153
- const page = getContextNumber(metadata.page) ?? getContextNumber(metadata.pageNumber) ?? (typeof metadata.pageIndex === "number" ? metadata.pageIndex + 1 : undefined);
1154
- if (page) {
1155
- return `Page ${page}`;
1156
- }
1157
- const sheet = getContextString(metadata.sheetName) ?? (Array.isArray(metadata.sheetNames) ? getContextString(metadata.sheetNames[0]) : undefined);
1158
- if (sheet) {
1159
- return `Sheet ${sheet}`;
1160
- }
1161
- const slide = getContextNumber(metadata.slide) ?? getContextNumber(metadata.slideNumber) ?? (typeof metadata.slideIndex === "number" ? metadata.slideIndex + 1 : undefined);
1162
- if (slide) {
1163
- return `Slide ${slide}`;
1164
- }
1165
- const archiveEntry = getContextString(metadata.archiveEntryPath) ?? getContextString(metadata.entryPath);
1166
- if (archiveEntry) {
1167
- return `Archive entry ${archiveEntry}`;
1168
- }
1169
- const emailKind = getContextString(metadata.emailKind);
1170
- if (emailKind === "attachment") {
1171
- const attachmentName = getContextString(metadata.attachmentName) ?? getAttachmentName(source, title);
1172
- return attachmentName ? `Attachment ${attachmentName}` : "Attachment";
1173
- }
1174
- const mediaStart = formatMediaTimestamp(metadata.startMs);
1175
- const mediaEnd = formatMediaTimestamp(metadata.endMs);
1176
- if (mediaStart && mediaEnd) {
1177
- return `Timestamp ${mediaStart} - ${mediaEnd}`;
1178
- }
1179
- if (mediaStart) {
1180
- return `Timestamp ${mediaStart}`;
1288
+ var isErrorPayload = (value) => {
1289
+ if (!value || typeof value !== "object") {
1290
+ return false;
1181
1291
  }
1182
- return;
1292
+ return !("error" in value) || typeof value.error === "string";
1183
1293
  };
1184
- var buildProvenanceLabel = (metadata) => {
1185
- if (!metadata) {
1186
- return;
1187
- }
1188
- const threadTopic = getContextString(metadata.threadTopic);
1189
- const from = getContextString(metadata.from);
1190
- const sentAt = formatTimestampLabel(metadata.sentAt) ?? formatTimestampLabel(metadata.receivedAt);
1191
- const speaker = getContextString(metadata.speaker);
1192
- const mediaKind = getContextString(metadata.mediaKind);
1193
- const transcriptSource = getContextString(metadata.transcriptSource);
1194
- const pdfTextMode = getContextString(metadata.pdfTextMode);
1195
- const ocrEngine = getContextString(metadata.ocrEngine);
1196
- const labels = [
1197
- pdfTextMode ? `PDF ${pdfTextMode}` : "",
1198
- ocrEngine ? `OCR ${ocrEngine}` : "",
1199
- mediaKind ? `Media ${mediaKind}` : "",
1200
- transcriptSource ? `Transcript ${transcriptSource}` : "",
1201
- threadTopic ? `Thread ${threadTopic}` : "",
1202
- speaker ? `Speaker ${speaker}` : "",
1203
- from ? `Sender ${from}` : "",
1204
- sentAt ? `Sent ${sentAt}` : ""
1205
- ].filter((value) => value.length > 0);
1206
- return labels.length > 0 ? labels.join(" · ") : undefined;
1294
+ var toErrorMessage = async (response) => {
1295
+ try {
1296
+ const payload = JSON.parse(await response.text());
1297
+ if (isErrorPayload(payload) && typeof payload.error === "string" && payload.error) {
1298
+ return payload.error;
1299
+ }
1300
+ } catch {}
1301
+ return `Request failed with status ${response.status}`;
1207
1302
  };
1208
- var buildRAGCitationReferenceMap = (citations) => Object.fromEntries(citations.map((citation, index) => [citation.chunkId, index + 1]));
1209
- var buildRAGCitations = (sources) => {
1210
- const unique = new Map;
1211
- for (const source of sources) {
1212
- const key = source.chunkId;
1213
- const existing = unique.get(key);
1214
- const hasBetterExisting = existing !== undefined && existing.score >= source.score;
1215
- if (hasBetterExisting)
1216
- continue;
1217
- unique.set(key, {
1218
- chunkId: source.chunkId,
1219
- contextLabel: buildContextLabel(source.metadata),
1220
- key,
1221
- label: buildSourceLabel(source),
1222
- locatorLabel: buildLocatorLabel(source.metadata, source.source, source.title),
1223
- metadata: source.metadata,
1224
- provenanceLabel: buildProvenanceLabel(source.metadata),
1225
- score: source.score,
1226
- source: source.source,
1227
- text: source.text,
1228
- title: source.title
1229
- });
1230
- }
1231
- return [...unique.values()].sort((left, right) => {
1232
- if (right.score !== left.score) {
1233
- return right.score - left.score;
1234
- }
1235
- return left.label.localeCompare(right.label);
1236
- });
1237
- };
1238
- var buildExcerpt = (text, maxLength = 160) => {
1239
- const normalized = text.replaceAll(/\s+/g, " ").trim();
1240
- if (normalized.length <= maxLength) {
1241
- return normalized;
1242
- }
1243
- return `${normalized.slice(0, Math.max(0, maxLength - 1)).trimEnd()}…`;
1244
- };
1245
- 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(" · ");
1246
- var buildGroundingReferenceEvidenceSummary = (reference) => [
1247
- reference.source ?? reference.title ?? reference.chunkId,
1248
- reference.provenanceLabel
1249
- ].filter((value) => Boolean(value && value.length > 0)).join(" · ");
1250
- var buildGroundedAnswerCitationDetail = (reference) => ({
1251
- contextLabel: reference.contextLabel,
1252
- evidenceLabel: buildGroundingReferenceEvidenceLabel(reference),
1253
- evidenceSummary: buildGroundingReferenceEvidenceSummary(reference),
1254
- excerpt: reference.excerpt,
1255
- label: reference.label,
1256
- locatorLabel: reference.locatorLabel,
1257
- number: reference.number,
1258
- provenanceLabel: reference.provenanceLabel,
1259
- source: reference.source,
1260
- title: reference.title
1261
- });
1262
- var buildRAGGroundedAnswer = (content, sources) => {
1263
- const references = buildRAGGroundingReferences(sources);
1264
- const referenceMap = new Map(references.map((reference) => [reference.number, reference]));
1265
- const parts = [];
1266
- const ungroundedReferenceNumbers = new Set;
1267
- const citationPattern = /\[(\d+(?:\s*,\s*\d+)*)\]/g;
1268
- let cursor = 0;
1269
- for (const match of content.matchAll(citationPattern)) {
1270
- const raw = match[0];
1271
- const numbers = (match[1] ?? "").split(",").map((value) => Number.parseInt(value.trim(), 10)).filter((value) => Number.isInteger(value) && value > 0);
1272
- const start = match.index ?? cursor;
1273
- if (start > cursor) {
1274
- parts.push({
1275
- text: content.slice(cursor, start),
1276
- type: "text"
1303
+ var createRAGClient = (options) => {
1304
+ const basePath = normalizeBasePath(options.path);
1305
+ const fetchImpl = options.fetch ?? fetch;
1306
+ return {
1307
+ async backends() {
1308
+ const response = await fetchImpl(`${basePath}/backends`);
1309
+ if (!response.ok) {
1310
+ throw new Error(await toErrorMessage(response));
1311
+ }
1312
+ return parseJson(response);
1313
+ },
1314
+ async clearIndex() {
1315
+ const response = await fetchImpl(`${basePath}/index`, {
1316
+ method: "DELETE"
1277
1317
  });
1278
- }
1279
- const resolvedReferences = numbers.map((number) => referenceMap.get(number)).filter((reference) => Boolean(reference));
1280
- for (const number of numbers) {
1281
- if (!referenceMap.has(number)) {
1282
- ungroundedReferenceNumbers.add(number);
1318
+ if (!response.ok) {
1319
+ throw new Error(await toErrorMessage(response));
1283
1320
  }
1284
- }
1285
- const unresolvedNumbers = numbers.filter((number) => !referenceMap.has(number));
1286
- parts.push({
1287
- referenceNumbers: numbers,
1288
- referenceDetails: resolvedReferences.map(buildGroundedAnswerCitationDetail),
1289
- references: resolvedReferences,
1290
- text: raw,
1291
- type: "citation",
1292
- unresolvedReferenceNumbers: unresolvedNumbers
1293
- });
1294
- cursor = start + raw.length;
1295
- }
1296
- if (cursor < content.length || parts.length === 0) {
1297
- parts.push({
1298
- text: content.slice(cursor),
1299
- type: "text"
1300
- });
1301
- }
1302
- const hasCitations = parts.some((part) => part.type === "citation");
1303
- const coverage = !hasCitations ? "ungrounded" : ungroundedReferenceNumbers.size === 0 ? "grounded" : references.length > 0 ? "partial" : "ungrounded";
1304
- return {
1305
- content,
1306
- coverage,
1307
- hasCitations,
1308
- parts,
1309
- references,
1310
- ungroundedReferenceNumbers: [...ungroundedReferenceNumbers].sort((left, right) => left - right)
1311
- };
1312
- };
1313
- var buildRAGGroundingReferences = (sources) => {
1314
- const citations = buildRAGCitations(sources);
1315
- const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1316
- return citations.map((citation) => ({
1317
- chunkId: citation.chunkId,
1318
- contextLabel: buildContextLabel(citation.metadata),
1319
- excerpt: buildExcerpt(citation.text),
1320
- label: citation.label,
1321
- locatorLabel: citation.locatorLabel ?? buildLocatorLabel(citation.metadata, citation.source, citation.title),
1322
- metadata: citation.metadata,
1323
- number: citationReferenceMap[citation.chunkId] ?? 0,
1324
- provenanceLabel: citation.provenanceLabel ?? buildProvenanceLabel(citation.metadata),
1325
- score: citation.score,
1326
- source: citation.source,
1327
- text: citation.text,
1328
- title: citation.title
1329
- }));
1330
- };
1331
- var buildRAGRetrievedState = (messages) => {
1332
- const message = getLatestRetrievedMessage(messages);
1333
- if (!message) {
1334
- return null;
1335
- }
1336
- const sources = message.sources ?? [];
1337
- const groundedAnswer = buildRAGGroundedAnswer(message.content, sources);
1338
- return {
1339
- citationReferenceMap: buildRAGCitationReferenceMap(buildRAGCitations(sources)),
1340
- citations: buildRAGCitations(sources),
1341
- conversationId: message.conversationId,
1342
- groundedAnswer,
1343
- messageId: message.id,
1344
- retrievalDurationMs: message.retrievalDurationMs,
1345
- retrievalStartedAt: message.retrievalStartedAt,
1346
- retrievedAt: message.retrievedAt,
1347
- sourceGroups: buildRAGSourceGroups(sources),
1348
- sourceSummaries: buildRAGSourceSummaries(sources),
1349
- sources
1350
- };
1351
- };
1352
- var buildRAGSourceSummaries = (sources) => {
1353
- const sourceGroups = buildRAGSourceGroups(sources);
1354
- const citations = buildRAGCitations(sources);
1355
- const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1356
- return sourceGroups.map((group) => {
1357
- const groupCitations = citations.filter((citation) => group.chunks.some((chunk) => chunk.chunkId === citation.chunkId));
1358
- const leadChunk = group.chunks.slice().sort((left, right) => right.score - left.score)[0];
1359
- return {
1360
- bestScore: group.bestScore,
1361
- citationNumbers: groupCitations.map((citation) => citationReferenceMap[citation.chunkId] ?? 0),
1362
- citations: groupCitations,
1363
- chunkIds: group.chunks.map((chunk) => chunk.chunkId),
1364
- contextLabel: buildContextLabel(leadChunk?.metadata),
1365
- count: group.count,
1366
- excerpt: buildExcerpt(leadChunk?.text ?? ""),
1367
- key: group.key,
1368
- label: group.label,
1369
- locatorLabel: buildLocatorLabel(leadChunk?.metadata, leadChunk?.source, leadChunk?.title),
1370
- provenanceLabel: buildProvenanceLabel(leadChunk?.metadata),
1371
- source: group.source,
1372
- title: group.title
1373
- };
1374
- });
1375
- };
1376
- var buildStreamProgressState = (messages) => {
1377
- const latestMessage = getLatestAssistantMessage(messages);
1378
- const retrieved = latestMessage ? buildRAGRetrievedState(messages) : undefined;
1379
- return {
1380
- conversationId: latestMessage?.conversationId,
1381
- latestMessage,
1382
- messageId: latestMessage?.id,
1383
- retrieved,
1384
- sourceCount: retrieved?.sources.length ?? latestMessage?.sources?.length ?? 0
1385
- };
1386
- };
1387
- var buildRAGStreamProgress = ({
1388
- error,
1389
- isStreaming,
1390
- messages
1391
- }) => {
1392
- const stage = resolveRAGStreamStage({
1393
- error,
1394
- isStreaming,
1395
- messages
1396
- });
1397
- const state = buildStreamProgressState(messages);
1398
- const hasSources = state.sourceCount > 0;
1399
- const hasRetrieved = stage === "retrieved" || state.retrieved !== undefined || state.latestMessage?.retrievedAt !== undefined;
1400
- const hasThinking = typeof state.latestMessage?.thinking === "string" && state.latestMessage.thinking.length > 0;
1401
- const hasToolCalls = (state.latestMessage?.toolCalls?.length ?? 0) > 0;
1402
- return {
1403
- conversationId: state.conversationId,
1404
- hasContent: typeof state.latestMessage?.content === "string" && state.latestMessage.content.length > 0,
1405
- hasRetrieved,
1406
- hasSources,
1407
- hasThinking,
1408
- hasToolCalls,
1409
- isComplete: stage === "complete",
1410
- isError: stage === "error",
1411
- isIdle: stage === "idle",
1412
- isRetrieved: stage === "retrieved",
1413
- isRetrieving: stage === "submitting" || stage === "retrieving",
1414
- isStreaming: stage === "streaming",
1415
- isSubmitting: stage === "submitting",
1416
- latestMessage: state.latestMessage,
1417
- messageId: state.messageId,
1418
- retrievalDurationMs: state.retrieved?.retrievalDurationMs,
1419
- retrievalStartedAt: state.retrieved?.retrievalStartedAt,
1420
- retrievedAt: state.retrieved?.retrievedAt,
1421
- sourceCount: state.sourceCount,
1422
- stage
1423
- };
1424
- };
1425
- var buildRAGAnswerWorkflowState = ({
1426
- error,
1427
- isStreaming,
1428
- messages
1429
- }) => {
1430
- const latestAssistantMessage = getLatestAssistantMessage(messages);
1431
- const sources = getLatestRAGSources(messages);
1432
- const sourceGroups = buildRAGSourceGroups(sources);
1433
- const citations = buildRAGCitations(sources);
1434
- const citationReferenceMap = buildRAGCitationReferenceMap(citations);
1435
- const sourceSummaries = buildRAGSourceSummaries(sources);
1436
- const groundingReferences = buildRAGGroundingReferences(sources);
1437
- const groundedAnswer = buildRAGGroundedAnswer(latestAssistantMessage?.content ?? "", sources);
1438
- const retrieval = buildRAGRetrievedState(messages);
1439
- const progress = buildRAGStreamProgress({
1440
- error,
1441
- isStreaming,
1442
- messages
1443
- });
1444
- return {
1445
- citationReferenceMap,
1446
- citations,
1447
- coverage: groundedAnswer.coverage,
1448
- error,
1449
- groundedAnswer,
1450
- groundingReferences,
1451
- hasCitations: groundedAnswer.hasCitations,
1452
- hasGrounding: groundingReferences.length > 0,
1453
- hasRetrieved: progress.hasRetrieved,
1454
- hasSources: sources.length > 0,
1455
- isAnswerStreaming: progress.isStreaming,
1456
- isComplete: progress.isComplete,
1457
- isError: progress.isError,
1458
- isIdle: progress.isIdle,
1459
- isRetrieved: progress.isRetrieved,
1460
- isRetrieving: progress.isRetrieving,
1461
- isRunning: progress.isSubmitting || progress.isRetrieving || progress.isStreaming,
1462
- isSubmitting: progress.isSubmitting,
1463
- latestAssistantMessage,
1464
- messages,
1465
- retrieval,
1466
- retrievalDurationMs: retrieval?.retrievalDurationMs,
1467
- retrievalStartedAt: retrieval?.retrievalStartedAt,
1468
- retrievedAt: retrieval?.retrievedAt,
1469
- sourceGroups,
1470
- sourceSummaries,
1471
- sources,
1472
- stage: progress.stage,
1473
- ungroundedReferenceNumbers: groundedAnswer.ungroundedReferenceNumbers
1321
+ return parseJson(response);
1322
+ },
1323
+ async createDocument(input) {
1324
+ const response = await fetchImpl(`${basePath}/documents`, {
1325
+ body: JSON.stringify(input),
1326
+ headers: jsonHeaders,
1327
+ method: "POST"
1328
+ });
1329
+ if (!response.ok) {
1330
+ return {
1331
+ error: await toErrorMessage(response),
1332
+ ok: false
1333
+ };
1334
+ }
1335
+ return parseJson(response);
1336
+ },
1337
+ async deleteDocument(id) {
1338
+ const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}`, {
1339
+ method: "DELETE"
1340
+ });
1341
+ if (!response.ok) {
1342
+ return {
1343
+ error: await toErrorMessage(response),
1344
+ ok: false
1345
+ };
1346
+ }
1347
+ return parseJson(response);
1348
+ },
1349
+ async documentChunks(id) {
1350
+ const response = await fetchImpl(`${basePath}/documents/${encodeURIComponent(id)}/chunks`);
1351
+ if (!response.ok) {
1352
+ const error = await toErrorMessage(response);
1353
+ const errorResponse = {
1354
+ error,
1355
+ ok: false
1356
+ };
1357
+ return errorResponse;
1358
+ }
1359
+ return parseJson(response);
1360
+ },
1361
+ async documents(kind) {
1362
+ const query = kind ? `?kind=${encodeURIComponent(kind)}` : "";
1363
+ const response = await fetchImpl(`${basePath}/documents${query}`);
1364
+ if (!response.ok) {
1365
+ throw new Error(await toErrorMessage(response));
1366
+ }
1367
+ return parseJson(response);
1368
+ },
1369
+ async evaluate(input) {
1370
+ const response = await fetchImpl(`${basePath}/evaluate`, {
1371
+ body: JSON.stringify(input),
1372
+ headers: jsonHeaders,
1373
+ method: "POST"
1374
+ });
1375
+ if (!response.ok) {
1376
+ throw new Error(await toErrorMessage(response));
1377
+ }
1378
+ return parseJson(response);
1379
+ },
1380
+ async ingest(chunks) {
1381
+ const response = await fetchImpl(`${basePath}/ingest`, {
1382
+ body: JSON.stringify({ chunks }),
1383
+ headers: jsonHeaders,
1384
+ method: "POST"
1385
+ });
1386
+ if (!response.ok) {
1387
+ return {
1388
+ error: await toErrorMessage(response),
1389
+ ok: false
1390
+ };
1391
+ }
1392
+ return parseJson(response);
1393
+ },
1394
+ async ingestDocuments(input) {
1395
+ const response = await fetchImpl(`${basePath}/ingest`, {
1396
+ body: JSON.stringify(input),
1397
+ headers: jsonHeaders,
1398
+ method: "POST"
1399
+ });
1400
+ if (!response.ok) {
1401
+ return {
1402
+ error: await toErrorMessage(response),
1403
+ ok: false
1404
+ };
1405
+ }
1406
+ return parseJson(response);
1407
+ },
1408
+ async ingestUploads(input) {
1409
+ const response = await fetchImpl(`${basePath}/ingest`, {
1410
+ body: JSON.stringify(input),
1411
+ headers: jsonHeaders,
1412
+ method: "POST"
1413
+ });
1414
+ if (!response.ok) {
1415
+ return {
1416
+ error: await toErrorMessage(response),
1417
+ ok: false
1418
+ };
1419
+ }
1420
+ return parseJson(response);
1421
+ },
1422
+ async ingestUrls(input) {
1423
+ const response = await fetchImpl(`${basePath}/ingest`, {
1424
+ body: JSON.stringify(input),
1425
+ headers: jsonHeaders,
1426
+ method: "POST"
1427
+ });
1428
+ if (!response.ok) {
1429
+ return {
1430
+ error: await toErrorMessage(response),
1431
+ ok: false
1432
+ };
1433
+ }
1434
+ return parseJson(response);
1435
+ },
1436
+ async ops() {
1437
+ const response = await fetchImpl(`${basePath}/ops`);
1438
+ if (!response.ok) {
1439
+ throw new Error(await toErrorMessage(response));
1440
+ }
1441
+ return parseJson(response);
1442
+ },
1443
+ async syncSources() {
1444
+ const response = await fetchImpl(`${basePath}/sync`);
1445
+ if (!response.ok) {
1446
+ throw new Error(await toErrorMessage(response));
1447
+ }
1448
+ return parseJson(response);
1449
+ },
1450
+ async syncAllSources(options2) {
1451
+ const response = await fetchImpl(`${basePath}/sync`, {
1452
+ body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
1453
+ headers: options2?.background === true ? jsonHeaders : undefined,
1454
+ method: "POST"
1455
+ });
1456
+ if (!response.ok) {
1457
+ return {
1458
+ error: await toErrorMessage(response),
1459
+ ok: false
1460
+ };
1461
+ }
1462
+ return parseJson(response);
1463
+ },
1464
+ async syncSource(id, options2) {
1465
+ const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
1466
+ body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
1467
+ headers: options2?.background === true ? jsonHeaders : undefined,
1468
+ method: "POST"
1469
+ });
1470
+ if (!response.ok) {
1471
+ return {
1472
+ error: await toErrorMessage(response),
1473
+ ok: false
1474
+ };
1475
+ }
1476
+ return parseJson(response);
1477
+ },
1478
+ async reindexDocument(id) {
1479
+ const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
1480
+ method: "POST"
1481
+ });
1482
+ if (!response.ok) {
1483
+ return {
1484
+ error: await toErrorMessage(response),
1485
+ ok: false
1486
+ };
1487
+ }
1488
+ return parseJson(response);
1489
+ },
1490
+ async reindexSource(source) {
1491
+ const response = await fetchImpl(`${basePath}/reindex/source`, {
1492
+ body: JSON.stringify({ source }),
1493
+ headers: jsonHeaders,
1494
+ method: "POST"
1495
+ });
1496
+ if (!response.ok) {
1497
+ return {
1498
+ error: await toErrorMessage(response),
1499
+ ok: false
1500
+ };
1501
+ }
1502
+ return parseJson(response);
1503
+ },
1504
+ async reseed() {
1505
+ const response = await fetchImpl(`${basePath}/reseed`, {
1506
+ method: "POST"
1507
+ });
1508
+ if (!response.ok) {
1509
+ return {
1510
+ error: await toErrorMessage(response),
1511
+ ok: false
1512
+ };
1513
+ }
1514
+ return parseJson(response);
1515
+ },
1516
+ async reset() {
1517
+ const response = await fetchImpl(`${basePath}/reset`, {
1518
+ method: "POST"
1519
+ });
1520
+ if (!response.ok) {
1521
+ return {
1522
+ error: await toErrorMessage(response),
1523
+ ok: false
1524
+ };
1525
+ }
1526
+ return parseJson(response);
1527
+ },
1528
+ async search(input) {
1529
+ const response = await fetchImpl(`${basePath}/search`, {
1530
+ body: JSON.stringify(input),
1531
+ headers: jsonHeaders,
1532
+ method: "POST"
1533
+ });
1534
+ if (!response.ok) {
1535
+ throw new Error(await toErrorMessage(response));
1536
+ }
1537
+ const payload = await parseJson(response);
1538
+ if (!payload.ok) {
1539
+ throw new Error(payload.error ?? "RAG search failed");
1540
+ }
1541
+ return payload.results ?? [];
1542
+ },
1543
+ async status() {
1544
+ const response = await fetchImpl(`${basePath}/status`);
1545
+ if (!response.ok) {
1546
+ throw new Error(await toErrorMessage(response));
1547
+ }
1548
+ return parseJson(response);
1549
+ }
1474
1550
  };
1475
1551
  };
1476
- var buildRAGSourceGroups = (sources) => {
1477
- const groups = new Map;
1478
- for (const source of sources) {
1479
- updateSourceGroup(groups, source);
1480
- }
1481
- return [...groups.values()].sort((left, right) => {
1482
- if (right.bestScore !== left.bestScore) {
1483
- return right.bestScore - left.bestScore;
1552
+
1553
+ // src/angular/ai/rag-client.service.ts
1554
+ class RAGClientService {
1555
+ clients = new Map;
1556
+ client(path) {
1557
+ const existing = this.clients.get(path);
1558
+ if (existing) {
1559
+ return existing;
1484
1560
  }
1485
- return left.label.localeCompare(right.label);
1486
- });
1487
- };
1488
- var buildSourceGroup = (source, key) => ({
1489
- bestScore: source.score,
1490
- chunks: [source],
1491
- count: 1,
1492
- key,
1493
- label: buildSourceLabel(source),
1494
- source: source.source,
1495
- title: source.title
1496
- });
1497
- var updateSourceGroup = (groups, source) => {
1498
- const key = buildSourceGroupKey(source);
1499
- const existing = groups.get(key);
1500
- if (!existing) {
1501
- groups.set(key, buildSourceGroup(source, key));
1502
- return;
1561
+ const created = createRAGClient({ path });
1562
+ this.clients.set(path, created);
1563
+ return created;
1503
1564
  }
1504
- existing.bestScore = Math.max(existing.bestScore, source.score);
1505
- existing.count += 1;
1506
- existing.chunks.push(source);
1507
- };
1508
- var getLatestAssistantMessage = (messages) => {
1509
- for (let index = messages.length - 1;index >= 0; index -= 1) {
1510
- const message = messages[index];
1511
- if (message?.role === "assistant") {
1512
- return message;
1513
- }
1565
+ ingest(path, chunks) {
1566
+ return this.client(path).ingest(chunks);
1514
1567
  }
1515
- return;
1516
- };
1517
- var getLatestRAGSources = (messages) => getLatestAssistantMessage(messages)?.sources ?? [];
1518
- var getLatestRetrievedMessage = (messages) => {
1519
- for (let index = messages.length - 1;index >= 0; index -= 1) {
1520
- const message = messages[index];
1521
- if (message?.role === "assistant" && (typeof message.retrievedAt === "number" || (message.sources?.length ?? 0) > 0)) {
1522
- return message;
1523
- }
1568
+ ingestDocuments(path, input) {
1569
+ return this.client(path).ingestDocuments(input);
1524
1570
  }
1525
- return;
1526
- };
1527
- var resolveRAGStreamStage = ({
1528
- error,
1529
- isStreaming,
1530
- messages
1531
- }) => {
1532
- if (error) {
1533
- return "error";
1571
+ ingestUrls(path, input) {
1572
+ return this.client(path).ingestUrls(input);
1534
1573
  }
1535
- const assistantMessage = getLatestAssistantMessage(messages);
1536
- if (!assistantMessage) {
1537
- return isStreaming ? "submitting" : "idle";
1574
+ ingestUploads(path, input) {
1575
+ return this.client(path).ingestUploads(input);
1538
1576
  }
1539
- const isRetrieving = typeof assistantMessage.retrievalStartedAt === "number" && typeof assistantMessage.retrievedAt !== "number";
1540
- if (isRetrieving) {
1541
- return "retrieving";
1577
+ search(path, input) {
1578
+ return this.client(path).search(input);
1542
1579
  }
1543
- if (!isStreaming) {
1544
- return "complete";
1580
+ evaluate(path, input) {
1581
+ return this.client(path).evaluate(input);
1545
1582
  }
1546
- const hasRetrieved = typeof assistantMessage.retrievedAt === "number";
1547
- const hasContent = assistantMessage.content.trim().length > 0 || assistantMessage.thinking?.trim().length || (assistantMessage.toolCalls?.length ?? 0) > 0 || (assistantMessage.images?.length ?? 0) > 0;
1548
- if (hasRetrieved && !hasContent) {
1549
- return "retrieved";
1583
+ status(path) {
1584
+ return this.client(path).status();
1550
1585
  }
1551
- return "streaming";
1552
- };
1553
-
1554
- // src/angular/ai/ai-rag-stream.service.ts
1555
- class RAGStreamService extends AIStreamService {
1556
- connect(path, conversationId) {
1557
- const stream = super.connect(path, conversationId);
1558
- const workflow = computed2(() => buildRAGAnswerWorkflowState({
1559
- error: stream.error(),
1560
- isStreaming: stream.isStreaming(),
1561
- messages: stream.messages()
1562
- }));
1563
- const progress = computed2(() => buildRAGStreamProgress({
1564
- error: stream.error(),
1565
- isStreaming: stream.isStreaming(),
1566
- messages: stream.messages()
1567
- }));
1568
- const latestAssistantMessage = computed2(() => workflow().latestAssistantMessage);
1569
- const sources = computed2(() => workflow().sources);
1570
- const sourceGroups = computed2(() => workflow().sourceGroups);
1571
- const citations = computed2(() => workflow().citations);
1572
- const sourceSummaries = computed2(() => workflow().sourceSummaries);
1573
- const citationReferenceMap = computed2(() => workflow().citationReferenceMap);
1574
- const retrieval = computed2(() => workflow().retrieval);
1575
- const groundedAnswer = computed2(() => workflow().groundedAnswer);
1576
- const groundingReferences = computed2(() => workflow().groundingReferences);
1577
- const hasRetrieved = computed2(() => workflow().hasRetrieved);
1578
- const hasSources = computed2(() => workflow().hasSources);
1579
- const isRetrieving = computed2(() => workflow().isRetrieving);
1580
- const isRetrieved = computed2(() => workflow().isRetrieved);
1581
- const isAnswerStreaming = computed2(() => workflow().isAnswerStreaming);
1582
- const isComplete = computed2(() => workflow().isComplete);
1583
- const isError = computed2(() => workflow().isError);
1584
- const isRunning = computed2(() => workflow().isRunning);
1585
- const stage = computed2(() => workflow().stage);
1586
- return {
1587
- ...stream,
1588
- citations,
1589
- citationReferenceMap,
1590
- groundedAnswer,
1591
- groundingReferences,
1592
- hasRetrieved,
1593
- hasSources,
1594
- isAnswerStreaming,
1595
- isComplete,
1596
- isError,
1597
- isRetrieved,
1598
- isRetrieving,
1599
- isRunning,
1600
- latestAssistantMessage,
1601
- progress,
1602
- query: stream.send,
1603
- retrieval,
1604
- sourceGroups,
1605
- sourceSummaries,
1606
- sources,
1607
- stage,
1608
- workflow
1609
- };
1586
+ ops(path) {
1587
+ return this.client(path).ops();
1588
+ }
1589
+ syncSources(path) {
1590
+ return this.client(path).syncSources();
1591
+ }
1592
+ syncAllSources(path, options) {
1593
+ return this.client(path).syncAllSources(options);
1594
+ }
1595
+ syncSource(path, id, options) {
1596
+ return this.client(path).syncSource(id, options);
1597
+ }
1598
+ documents(path, kind) {
1599
+ return this.client(path).documents(kind);
1600
+ }
1601
+ documentChunks(path, id) {
1602
+ return this.client(path).documentChunks(id);
1603
+ }
1604
+ createDocument(path, input) {
1605
+ return this.client(path).createDocument(input);
1606
+ }
1607
+ deleteDocument(path, id) {
1608
+ return this.client(path).deleteDocument(id);
1609
+ }
1610
+ reseed(path) {
1611
+ return this.client(path).reseed();
1612
+ }
1613
+ reset(path) {
1614
+ return this.client(path).reset();
1615
+ }
1616
+ reindexDocument(path, id) {
1617
+ return this.client(path).reindexDocument(id);
1618
+ }
1619
+ reindexSource(path, source) {
1620
+ return this.client(path).reindexSource(source);
1621
+ }
1622
+ backends(path) {
1623
+ return this.client(path).backends();
1624
+ }
1625
+ clearIndex(path) {
1626
+ return this.client(path).clearIndex();
1610
1627
  }
1611
1628
  }
1612
- RAGStreamService = __legacyDecorateClassTS([
1613
- Injectable3({ providedIn: "root" })
1614
- ], RAGStreamService);
1629
+ RAGClientService = __legacyDecorateClassTS([
1630
+ Injectable4({ providedIn: "root" })
1631
+ ], RAGClientService);
1615
1632
  export {
1616
- RAGStreamService as RAGTransportService,
1633
+ RAGWorkflowService,
1634
+ RAGStreamService,
1617
1635
  RAGClientService,
1618
1636
  AIStreamService
1619
1637
  };