@absolutejs/absolute 0.19.0-beta.496 → 0.19.0-beta.498
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai/client/index.js +32 -1
- package/dist/ai/client/index.js.map +3 -3
- package/dist/ai/index.js +439 -18
- package/dist/ai/index.js.map +9 -8
- package/dist/ai-client/angular/ai/index.js +40 -0
- package/dist/ai-client/react/ai/index.js +64 -2
- package/dist/ai-client/vue/ai/index.js +64 -2
- package/dist/angular/ai/index.js +41 -1
- package/dist/angular/ai/index.js.map +4 -4
- package/dist/react/ai/index.js +65 -3
- package/dist/react/ai/index.js.map +5 -5
- package/dist/src/ai/client/ragClient.d.ts +4 -1
- package/dist/src/ai/index.d.ts +2 -2
- package/dist/src/ai/rag/chat.d.ts +59 -4
- package/dist/src/ai/rag/index.d.ts +2 -1
- package/dist/src/ai/rag/sync.d.ts +4 -0
- package/dist/src/ai/rag/types.d.ts +1 -1
- package/dist/src/angular/ai/rag-client.service.d.ts +3 -0
- package/dist/src/react/ai/useRAG.d.ts +17 -0
- package/dist/src/react/ai/useRAGIndexAdmin.d.ts +17 -1
- package/dist/src/react/ai/useRAGOps.d.ts +2 -1
- package/dist/src/svelte/ai/createRAG.d.ts +17 -0
- package/dist/src/svelte/ai/createRAGIndexAdmin.d.ts +17 -1
- package/dist/src/svelte/ai/createRAGOps.d.ts +2 -1
- package/dist/src/vue/ai/useRAG.d.ts +119 -4
- package/dist/src/vue/ai/useRAGIndexAdmin.d.ts +87 -1
- package/dist/src/vue/ai/useRAGOps.d.ts +34 -5
- package/dist/svelte/ai/index.js +65 -3
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/types/ai.d.ts +85 -2
- package/dist/vue/ai/index.js +65 -3
- package/dist/vue/ai/index.js.map +5 -5
- package/package.json +1 -1
package/dist/ai/index.js
CHANGED
|
@@ -2165,6 +2165,31 @@ var collectMetadataStrings = (value) => {
|
|
|
2165
2165
|
};
|
|
2166
2166
|
var normalizeSourceForLexical = (source) => source.replace(/[#/_.-]+/g, " ").replace(/\bmd\b/g, "markdown").replace(/\bpptx\b/g, "presentation").replace(/\bxlsx\b/g, "spreadsheet workbook sheet").replace(/\bmp3\b/g, "audio transcript media").replace(/\bmp4\b/g, "video transcript media").replace(/\bzip\b/g, "archive bundle");
|
|
2167
2167
|
var toFieldText = (value) => collectMetadataStrings(value).filter(Boolean).join(" ");
|
|
2168
|
+
var normalizeLooseText = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().replace(/\s+/g, " ");
|
|
2169
|
+
var scoreLoosePhraseMatch = (query, text) => {
|
|
2170
|
+
const normalizedQuery = normalizeLooseText(query);
|
|
2171
|
+
const normalizedText = normalizeLooseText(text ?? "");
|
|
2172
|
+
if (normalizedQuery.length === 0 || normalizedText.length === 0) {
|
|
2173
|
+
return 0;
|
|
2174
|
+
}
|
|
2175
|
+
if (normalizedText.includes(normalizedQuery)) {
|
|
2176
|
+
return 1;
|
|
2177
|
+
}
|
|
2178
|
+
const words = normalizedQuery.split(" ").filter(Boolean);
|
|
2179
|
+
for (let size = Math.min(5, words.length);size >= 2; size -= 1) {
|
|
2180
|
+
for (let index = 0;index <= words.length - size; index += 1) {
|
|
2181
|
+
const phraseWords = words.slice(index, index + size);
|
|
2182
|
+
if (phraseWords.every((word) => STOP_WORDS.has(word))) {
|
|
2183
|
+
continue;
|
|
2184
|
+
}
|
|
2185
|
+
const phrase = phraseWords.join(" ");
|
|
2186
|
+
if (normalizedText.includes(phrase)) {
|
|
2187
|
+
return Math.min(1, size / 4);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
return 0;
|
|
2192
|
+
};
|
|
2168
2193
|
var scoreTokenCoverage = (queryTokens, text) => {
|
|
2169
2194
|
const normalizedText = (text ?? "").toLowerCase();
|
|
2170
2195
|
if (normalizedText.length === 0) {
|
|
@@ -2181,10 +2206,8 @@ var scoreTokenCoverage = (queryTokens, text) => {
|
|
|
2181
2206
|
var scorePhraseMatch = (query, text) => {
|
|
2182
2207
|
const normalizedQuery = tokenize(query).join(" ");
|
|
2183
2208
|
const normalizedText = tokenize(text ?? "").join(" ");
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
}
|
|
2187
|
-
return normalizedText.includes(normalizedQuery) ? 1 : 0;
|
|
2209
|
+
const tokenPhraseMatch = normalizedQuery.length > 0 && normalizedText.length > 0 ? normalizedText.includes(normalizedQuery) ? 1 : 0 : 0;
|
|
2210
|
+
return Math.max(tokenPhraseMatch, scoreLoosePhraseMatch(query, text ?? ""));
|
|
2188
2211
|
};
|
|
2189
2212
|
var scoreWeightedField = ({
|
|
2190
2213
|
coverageWeight,
|
|
@@ -2774,7 +2797,36 @@ var collectMetadataStrings2 = (value) => {
|
|
|
2774
2797
|
}
|
|
2775
2798
|
return [];
|
|
2776
2799
|
};
|
|
2777
|
-
var
|
|
2800
|
+
var normalizeLooseText2 = (value) => value.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim().replace(/\s+/g, " ");
|
|
2801
|
+
var scoreLoosePhraseMatch2 = (query, text) => {
|
|
2802
|
+
const normalizedQuery = normalizeLooseText2(query);
|
|
2803
|
+
const normalizedText = normalizeLooseText2(text);
|
|
2804
|
+
if (normalizedQuery.length === 0 || normalizedText.length === 0) {
|
|
2805
|
+
return 0;
|
|
2806
|
+
}
|
|
2807
|
+
if (normalizedText.includes(normalizedQuery)) {
|
|
2808
|
+
return 1;
|
|
2809
|
+
}
|
|
2810
|
+
const words = normalizedQuery.split(" ").filter(Boolean);
|
|
2811
|
+
for (let size = Math.min(5, words.length);size >= 2; size -= 1) {
|
|
2812
|
+
for (let index = 0;index <= words.length - size; index += 1) {
|
|
2813
|
+
const phraseWords = words.slice(index, index + size);
|
|
2814
|
+
if (phraseWords.every((word) => STOP_WORDS3.has(word))) {
|
|
2815
|
+
continue;
|
|
2816
|
+
}
|
|
2817
|
+
const phrase = phraseWords.join(" ");
|
|
2818
|
+
if (normalizedText.includes(phrase)) {
|
|
2819
|
+
return Math.min(1, size / 4);
|
|
2820
|
+
}
|
|
2821
|
+
}
|
|
2822
|
+
}
|
|
2823
|
+
return 0;
|
|
2824
|
+
};
|
|
2825
|
+
var scoreHeuristicMatch = ({
|
|
2826
|
+
query,
|
|
2827
|
+
queryTokens,
|
|
2828
|
+
result
|
|
2829
|
+
}) => {
|
|
2778
2830
|
if (queryTokens.length === 0) {
|
|
2779
2831
|
return result.score;
|
|
2780
2832
|
}
|
|
@@ -2783,8 +2835,7 @@ var scoreHeuristicMatch = (queryTokens, result) => {
|
|
|
2783
2835
|
const haystackSet = new Set(haystack);
|
|
2784
2836
|
const overlap = queryTokens.filter((token) => haystackSet.has(token)).length;
|
|
2785
2837
|
const overlapBoost = overlap / queryTokens.length;
|
|
2786
|
-
const
|
|
2787
|
-
const exactPhraseBoost = normalizeText([result.title, result.source, result.chunkText, ...metadataValues].filter(Boolean).join(" ")).includes(normalizedQuery) ? 1 : 0;
|
|
2838
|
+
const exactPhraseBoost = Math.max(normalizeText([result.title, result.source, result.chunkText, ...metadataValues].filter(Boolean).join(" ")).includes(queryTokens.join(" ")) ? 1 : 0, scoreLoosePhraseMatch2(query, [result.title, result.source, result.chunkText, ...metadataValues].filter(Boolean).join(" ")));
|
|
2788
2839
|
const sourcePathBoost = typeof result.source === "string" && queryTokens.some((token) => result.source?.toLowerCase().includes(token)) ? 0.5 : 0;
|
|
2789
2840
|
const metadataBoost = metadataValues.length > 0 ? queryTokens.filter((token) => metadataValues.some((value) => value.toLowerCase().includes(token))).length / queryTokens.length : 0;
|
|
2790
2841
|
return result.score + overlapBoost + exactPhraseBoost + sourcePathBoost + metadataBoost;
|
|
@@ -2812,7 +2863,11 @@ var createHeuristicRAGReranker = (options = {}) => createRAGReranker({
|
|
|
2812
2863
|
return [...results].map((result, index) => ({
|
|
2813
2864
|
index,
|
|
2814
2865
|
result,
|
|
2815
|
-
score: scoreHeuristicMatch(
|
|
2866
|
+
score: scoreHeuristicMatch({
|
|
2867
|
+
query,
|
|
2868
|
+
queryTokens,
|
|
2869
|
+
result
|
|
2870
|
+
})
|
|
2816
2871
|
})).sort((left, right) => {
|
|
2817
2872
|
if (right.score !== left.score) {
|
|
2818
2873
|
return right.score - left.score;
|
|
@@ -4924,6 +4979,7 @@ var ragChat = (config) => {
|
|
|
4924
4979
|
const ingestJobs = [];
|
|
4925
4980
|
const adminActions = [];
|
|
4926
4981
|
const adminJobs = [];
|
|
4982
|
+
const syncJobs = [];
|
|
4927
4983
|
const workflowRenderConfig = typeof config.htmx === "object" ? config.htmx.workflowRender ?? config.htmx.workflow?.render : undefined;
|
|
4928
4984
|
const workflowRenderers = resolveRAGWorkflowRenderers(workflowRenderConfig);
|
|
4929
4985
|
const createIngestJob = (inputKind, requestedCount) => {
|
|
@@ -4957,13 +5013,14 @@ var ragChat = (config) => {
|
|
|
4957
5013
|
job.error = error;
|
|
4958
5014
|
job.extractorNames = extractorNames;
|
|
4959
5015
|
};
|
|
4960
|
-
const createAdminAction = (action, documentId) => {
|
|
5016
|
+
const createAdminAction = (action, documentId, target) => {
|
|
4961
5017
|
const record = {
|
|
4962
5018
|
action,
|
|
4963
5019
|
documentId,
|
|
4964
5020
|
id: generateId(),
|
|
4965
5021
|
startedAt: Date.now(),
|
|
4966
|
-
status: "completed"
|
|
5022
|
+
status: "completed",
|
|
5023
|
+
target
|
|
4967
5024
|
};
|
|
4968
5025
|
adminActions.unshift(record);
|
|
4969
5026
|
if (adminActions.length > MAX_ADMIN_ACTIONS) {
|
|
@@ -4971,7 +5028,7 @@ var ragChat = (config) => {
|
|
|
4971
5028
|
}
|
|
4972
5029
|
return record;
|
|
4973
5030
|
};
|
|
4974
|
-
const createAdminJob = (action, target) => {
|
|
5031
|
+
const createAdminJob = (action, target, bucket = adminJobs) => {
|
|
4975
5032
|
const job = {
|
|
4976
5033
|
action,
|
|
4977
5034
|
id: generateId(),
|
|
@@ -4979,9 +5036,9 @@ var ragChat = (config) => {
|
|
|
4979
5036
|
status: "running",
|
|
4980
5037
|
target
|
|
4981
5038
|
};
|
|
4982
|
-
|
|
4983
|
-
if (
|
|
4984
|
-
|
|
5039
|
+
bucket.unshift(job);
|
|
5040
|
+
if (bucket.length > MAX_ADMIN_JOBS) {
|
|
5041
|
+
bucket.length = MAX_ADMIN_JOBS;
|
|
4985
5042
|
}
|
|
4986
5043
|
return job;
|
|
4987
5044
|
};
|
|
@@ -5011,6 +5068,12 @@ var ragChat = (config) => {
|
|
|
5011
5068
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
5012
5069
|
job.error = error;
|
|
5013
5070
|
};
|
|
5071
|
+
const buildSyncSources = async () => {
|
|
5072
|
+
if (!indexManager?.listSyncSources) {
|
|
5073
|
+
return [];
|
|
5074
|
+
}
|
|
5075
|
+
return await indexManager.listSyncSources();
|
|
5076
|
+
};
|
|
5014
5077
|
const toHTMXResponse = (html, status, extraHeaders) => new Response(html, {
|
|
5015
5078
|
headers: {
|
|
5016
5079
|
...HTML_HEADERS,
|
|
@@ -5446,6 +5509,12 @@ var ragChat = (config) => {
|
|
|
5446
5509
|
}
|
|
5447
5510
|
failuresByAdminAction.set(job.action, (failuresByAdminAction.get(job.action) ?? 0) + 1);
|
|
5448
5511
|
}
|
|
5512
|
+
for (const job of syncJobs) {
|
|
5513
|
+
if (job.status !== "failed") {
|
|
5514
|
+
continue;
|
|
5515
|
+
}
|
|
5516
|
+
failuresByAdminAction.set(job.action, (failuresByAdminAction.get(job.action) ?? 0) + 1);
|
|
5517
|
+
}
|
|
5449
5518
|
return {
|
|
5450
5519
|
averageChunksPerDocument: documents.length > 0 ? Number((documents.reduce((sum, document) => sum + (document.chunkCount ?? 0), 0) / documents.length).toFixed(2)) : 0,
|
|
5451
5520
|
duplicateDocumentIds: [...documentIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id),
|
|
@@ -5491,10 +5560,13 @@ var ragChat = (config) => {
|
|
|
5491
5560
|
canClearIndex: Boolean(ragStore?.clear),
|
|
5492
5561
|
canCreateDocument: Boolean(indexManager?.createDocument),
|
|
5493
5562
|
canDeleteDocument: Boolean(indexManager?.deleteDocument),
|
|
5563
|
+
canListSyncSources: Boolean(indexManager?.listSyncSources),
|
|
5494
5564
|
canReindexDocument: Boolean(indexManager?.reindexDocument),
|
|
5495
5565
|
canReindexSource: Boolean(indexManager?.reindexSource),
|
|
5496
5566
|
canReseed: Boolean(indexManager?.reseed),
|
|
5497
|
-
canReset: Boolean(indexManager?.reset)
|
|
5567
|
+
canReset: Boolean(indexManager?.reset),
|
|
5568
|
+
canSyncAllSources: Boolean(indexManager?.syncAllSources),
|
|
5569
|
+
canSyncSource: Boolean(indexManager?.syncSource)
|
|
5498
5570
|
});
|
|
5499
5571
|
const buildOperationsPayload = async () => {
|
|
5500
5572
|
const collection = config.collection ?? (ragStore ? createRAGCollection({
|
|
@@ -5507,14 +5579,15 @@ var ragChat = (config) => {
|
|
|
5507
5579
|
return {
|
|
5508
5580
|
admin: buildAdminCapabilities(),
|
|
5509
5581
|
adminActions: [...adminActions],
|
|
5510
|
-
adminJobs: [...adminJobs],
|
|
5582
|
+
adminJobs: [...adminJobs, ...syncJobs].sort((left, right) => right.startedAt - left.startedAt),
|
|
5511
5583
|
capabilities: collection?.getCapabilities?.(),
|
|
5512
5584
|
documents: indexManager ? summarizeDocuments(indexedDocuments) : undefined,
|
|
5513
5585
|
health: await summarizeHealth(indexedDocuments),
|
|
5514
5586
|
ingestJobs: [...ingestJobs],
|
|
5515
5587
|
ok: true,
|
|
5516
5588
|
readiness: buildReadiness(),
|
|
5517
|
-
status: collection?.getStatus?.()
|
|
5589
|
+
status: collection?.getStatus?.(),
|
|
5590
|
+
syncSources: await buildSyncSources()
|
|
5518
5591
|
};
|
|
5519
5592
|
};
|
|
5520
5593
|
const handleStatus = async () => buildOperationsPayload();
|
|
@@ -5751,6 +5824,81 @@ var ragChat = (config) => {
|
|
|
5751
5824
|
...normalized
|
|
5752
5825
|
};
|
|
5753
5826
|
};
|
|
5827
|
+
const handleSyncSources = async () => {
|
|
5828
|
+
if (!indexManager?.listSyncSources) {
|
|
5829
|
+
return {
|
|
5830
|
+
error: "RAG source sync is not configured",
|
|
5831
|
+
ok: false
|
|
5832
|
+
};
|
|
5833
|
+
}
|
|
5834
|
+
return {
|
|
5835
|
+
ok: true,
|
|
5836
|
+
sources: await indexManager.listSyncSources()
|
|
5837
|
+
};
|
|
5838
|
+
};
|
|
5839
|
+
const handleSyncAllSources = async () => {
|
|
5840
|
+
if (!indexManager?.syncAllSources) {
|
|
5841
|
+
return {
|
|
5842
|
+
error: "RAG source sync is not configured",
|
|
5843
|
+
ok: false
|
|
5844
|
+
};
|
|
5845
|
+
}
|
|
5846
|
+
const job = createAdminJob("sync_all_sources", undefined, syncJobs);
|
|
5847
|
+
try {
|
|
5848
|
+
const result = await indexManager.syncAllSources();
|
|
5849
|
+
const action = createAdminAction("sync_all_sources");
|
|
5850
|
+
completeAdminJob(job);
|
|
5851
|
+
completeAdminAction(action);
|
|
5852
|
+
if (result && "ok" in result) {
|
|
5853
|
+
return result;
|
|
5854
|
+
}
|
|
5855
|
+
return {
|
|
5856
|
+
ok: true,
|
|
5857
|
+
sources: await buildSyncSources()
|
|
5858
|
+
};
|
|
5859
|
+
} catch (caught) {
|
|
5860
|
+
const message = caught instanceof Error ? caught.message : String(caught);
|
|
5861
|
+
failAdminJob(job, message);
|
|
5862
|
+
const action = createAdminAction("sync_all_sources");
|
|
5863
|
+
failAdminAction(action, message);
|
|
5864
|
+
throw caught;
|
|
5865
|
+
}
|
|
5866
|
+
};
|
|
5867
|
+
const handleSyncSource = async (id) => {
|
|
5868
|
+
if (!indexManager?.syncSource) {
|
|
5869
|
+
return {
|
|
5870
|
+
error: "RAG source sync is not configured",
|
|
5871
|
+
ok: false
|
|
5872
|
+
};
|
|
5873
|
+
}
|
|
5874
|
+
if (!id) {
|
|
5875
|
+
return {
|
|
5876
|
+
error: "sync source id is required",
|
|
5877
|
+
ok: false
|
|
5878
|
+
};
|
|
5879
|
+
}
|
|
5880
|
+
const job = createAdminJob("sync_source", id, syncJobs);
|
|
5881
|
+
try {
|
|
5882
|
+
const result = await indexManager.syncSource(id);
|
|
5883
|
+
const action = createAdminAction("sync_source", undefined, id);
|
|
5884
|
+
completeAdminJob(job);
|
|
5885
|
+
completeAdminAction(action);
|
|
5886
|
+
if (result && "ok" in result) {
|
|
5887
|
+
return result;
|
|
5888
|
+
}
|
|
5889
|
+
const source = (await buildSyncSources()).find((record) => record.id === id);
|
|
5890
|
+
return source ? { ok: true, source } : {
|
|
5891
|
+
error: "sync source not found",
|
|
5892
|
+
ok: false
|
|
5893
|
+
};
|
|
5894
|
+
} catch (caught) {
|
|
5895
|
+
const message = caught instanceof Error ? caught.message : String(caught);
|
|
5896
|
+
failAdminJob(job, message);
|
|
5897
|
+
const action = createAdminAction("sync_source", undefined, id);
|
|
5898
|
+
failAdminAction(action, message);
|
|
5899
|
+
throw caught;
|
|
5900
|
+
}
|
|
5901
|
+
};
|
|
5754
5902
|
const htmxRoutes = () => {
|
|
5755
5903
|
if (!config.htmx) {
|
|
5756
5904
|
return new Elysia2;
|
|
@@ -5987,6 +6135,51 @@ var ragChat = (config) => {
|
|
|
5987
6135
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
5988
6136
|
}
|
|
5989
6137
|
return result;
|
|
6138
|
+
}).get(`${path}/sync`, async ({ request, set }) => {
|
|
6139
|
+
const result = await handleSyncSources();
|
|
6140
|
+
if (!result.ok) {
|
|
6141
|
+
set.status = HTTP_STATUS_NOT_FOUND;
|
|
6142
|
+
}
|
|
6143
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6144
|
+
if (!result.ok) {
|
|
6145
|
+
return toHTMXResponse(workflowRenderers.error(result.error), getNumericStatus(set.status));
|
|
6146
|
+
}
|
|
6147
|
+
return toHTMXResponse(workflowRenderers.mutationResult({
|
|
6148
|
+
ok: true,
|
|
6149
|
+
status: `loaded ${"sources" in result ? result.sources.length : 1} sync sources`
|
|
6150
|
+
}));
|
|
6151
|
+
}
|
|
6152
|
+
return result;
|
|
6153
|
+
}).post(`${path}/sync`, async ({ request, set }) => {
|
|
6154
|
+
const result = await handleSyncAllSources();
|
|
6155
|
+
if (!result.ok) {
|
|
6156
|
+
set.status = HTTP_STATUS_NOT_FOUND;
|
|
6157
|
+
}
|
|
6158
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6159
|
+
const html = result.ok ? workflowRenderers.mutationResult({
|
|
6160
|
+
ok: true,
|
|
6161
|
+
status: "source sync started and completed successfully"
|
|
6162
|
+
}) : workflowRenderers.error(result.error ?? "Failed to sync sources");
|
|
6163
|
+
return toHTMXResponse(html, getNumericStatus(set.status), {
|
|
6164
|
+
"HX-Trigger": "rag:mutated"
|
|
6165
|
+
});
|
|
6166
|
+
}
|
|
6167
|
+
return result;
|
|
6168
|
+
}).post(`${path}/sync/:id`, async ({ params, request, set }) => {
|
|
6169
|
+
const result = await handleSyncSource(typeof params.id === "string" ? params.id.trim() : "");
|
|
6170
|
+
if (!result.ok) {
|
|
6171
|
+
set.status = result.error === "sync source id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
6172
|
+
}
|
|
6173
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6174
|
+
const html = result.ok ? workflowRenderers.mutationResult({
|
|
6175
|
+
ok: true,
|
|
6176
|
+
status: "source sync started and completed successfully"
|
|
6177
|
+
}) : workflowRenderers.error(result.error ?? "Failed to sync source");
|
|
6178
|
+
return toHTMXResponse(html, getNumericStatus(set.status), {
|
|
6179
|
+
"HX-Trigger": "rag:mutated"
|
|
6180
|
+
});
|
|
6181
|
+
}
|
|
6182
|
+
return result;
|
|
5990
6183
|
}).post(`${path}/ingest`, async ({ body, request, set }) => {
|
|
5991
6184
|
const result = await handleIngest(body);
|
|
5992
6185
|
if (!result.ok) {
|
|
@@ -6965,6 +7158,200 @@ var resolveRAGStreamStage = ({
|
|
|
6965
7158
|
}
|
|
6966
7159
|
return "streaming";
|
|
6967
7160
|
};
|
|
7161
|
+
// src/ai/rag/sync.ts
|
|
7162
|
+
import { createHash } from "crypto";
|
|
7163
|
+
var toSyncError = (caught) => caught instanceof Error ? caught.message : String(caught);
|
|
7164
|
+
var createSyncFingerprint = (document) => createHash("sha1").update(document.source ?? "").update(`
|
|
7165
|
+
`).update(document.title ?? "").update(`
|
|
7166
|
+
`).update(document.text).digest("hex");
|
|
7167
|
+
var toManagedSyncDocument = (sourceId, document, syncKey) => ({
|
|
7168
|
+
...document,
|
|
7169
|
+
metadata: {
|
|
7170
|
+
...document.metadata ?? {},
|
|
7171
|
+
syncFingerprint: createSyncFingerprint(document),
|
|
7172
|
+
syncKey,
|
|
7173
|
+
syncSourceId: sourceId
|
|
7174
|
+
}
|
|
7175
|
+
});
|
|
7176
|
+
var isManagedBySyncSource = (document, sourceId) => document.metadata?.syncSourceId === sourceId;
|
|
7177
|
+
var getDocumentSyncFingerprint = (document) => typeof document.metadata?.syncFingerprint === "string" ? document.metadata.syncFingerprint : undefined;
|
|
7178
|
+
var reconcileManagedDocuments = async (input) => {
|
|
7179
|
+
const prepared = prepareRAGDocuments({
|
|
7180
|
+
documents: input.documents
|
|
7181
|
+
});
|
|
7182
|
+
const nextDocumentIds = new Set(prepared.map((document) => document.documentId));
|
|
7183
|
+
const nextFingerprintById = new Map(prepared.map((document, index) => [
|
|
7184
|
+
document.documentId,
|
|
7185
|
+
createSyncFingerprint(input.documents[index])
|
|
7186
|
+
]));
|
|
7187
|
+
const existingDocuments = input.listDocuments ? await input.listDocuments() : [];
|
|
7188
|
+
const managedDocuments = existingDocuments.filter((document) => isManagedBySyncSource(document, input.sourceId));
|
|
7189
|
+
const staleDocuments = managedDocuments.filter((document) => !nextDocumentIds.has(document.id));
|
|
7190
|
+
const changedPrepared = prepared.filter((document) => {
|
|
7191
|
+
const existing = managedDocuments.find((entry) => entry.id === document.documentId);
|
|
7192
|
+
if (!existing) {
|
|
7193
|
+
return true;
|
|
7194
|
+
}
|
|
7195
|
+
return getDocumentSyncFingerprint(existing) !== nextFingerprintById.get(document.documentId);
|
|
7196
|
+
});
|
|
7197
|
+
if (input.deleteDocument) {
|
|
7198
|
+
await Promise.all(staleDocuments.map(async (document) => {
|
|
7199
|
+
await input.deleteDocument?.(document.id);
|
|
7200
|
+
}));
|
|
7201
|
+
}
|
|
7202
|
+
if (changedPrepared.length > 0) {
|
|
7203
|
+
await input.collection.ingest({
|
|
7204
|
+
chunks: changedPrepared.flatMap((document) => document.chunks)
|
|
7205
|
+
});
|
|
7206
|
+
}
|
|
7207
|
+
return {
|
|
7208
|
+
chunkCount: prepared.reduce((sum, document) => sum + document.chunks.length, 0),
|
|
7209
|
+
deletedCount: staleDocuments.length,
|
|
7210
|
+
documentCount: prepared.length,
|
|
7211
|
+
updatedCount: changedPrepared.length
|
|
7212
|
+
};
|
|
7213
|
+
};
|
|
7214
|
+
var toSourceRecord = (source, overrides) => ({
|
|
7215
|
+
description: source.description,
|
|
7216
|
+
id: source.id,
|
|
7217
|
+
kind: source.kind,
|
|
7218
|
+
label: source.label,
|
|
7219
|
+
metadata: source.metadata,
|
|
7220
|
+
status: "idle",
|
|
7221
|
+
target: source.target,
|
|
7222
|
+
...overrides
|
|
7223
|
+
});
|
|
7224
|
+
var createRAGDirectorySyncSource = (options) => ({
|
|
7225
|
+
description: options.description,
|
|
7226
|
+
id: options.id,
|
|
7227
|
+
kind: "directory",
|
|
7228
|
+
label: options.label,
|
|
7229
|
+
metadata: options.metadata,
|
|
7230
|
+
target: options.directory,
|
|
7231
|
+
sync: async ({ collection, deleteDocument, listDocuments }) => {
|
|
7232
|
+
const loaded = await loadRAGDocumentsFromDirectory({
|
|
7233
|
+
baseMetadata: options.baseMetadata,
|
|
7234
|
+
defaultChunking: options.defaultChunking,
|
|
7235
|
+
directory: options.directory,
|
|
7236
|
+
extractors: options.extractors,
|
|
7237
|
+
includeExtensions: options.includeExtensions,
|
|
7238
|
+
recursive: options.recursive
|
|
7239
|
+
});
|
|
7240
|
+
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.relativePath === "string" ? document.metadata.relativePath : document.source ?? document.title ?? ""));
|
|
7241
|
+
const reconciled = await reconcileManagedDocuments({
|
|
7242
|
+
collection,
|
|
7243
|
+
deleteDocument,
|
|
7244
|
+
documents: managedDocuments,
|
|
7245
|
+
listDocuments,
|
|
7246
|
+
sourceId: options.id
|
|
7247
|
+
});
|
|
7248
|
+
return {
|
|
7249
|
+
chunkCount: reconciled.chunkCount,
|
|
7250
|
+
documentCount: reconciled.documentCount,
|
|
7251
|
+
metadata: {
|
|
7252
|
+
deletedCount: reconciled.deletedCount,
|
|
7253
|
+
directory: options.directory,
|
|
7254
|
+
recursive: options.recursive !== false,
|
|
7255
|
+
updatedCount: reconciled.updatedCount
|
|
7256
|
+
}
|
|
7257
|
+
};
|
|
7258
|
+
}
|
|
7259
|
+
});
|
|
7260
|
+
var createRAGUrlSyncSource = (options) => ({
|
|
7261
|
+
description: options.description,
|
|
7262
|
+
id: options.id,
|
|
7263
|
+
kind: "url",
|
|
7264
|
+
label: options.label,
|
|
7265
|
+
metadata: options.metadata,
|
|
7266
|
+
target: options.urls.length === 1 ? options.urls[0]?.url : `${options.urls.length} urls`,
|
|
7267
|
+
sync: async ({ collection, deleteDocument, listDocuments }) => {
|
|
7268
|
+
const loaded = await loadRAGDocumentsFromURLs({
|
|
7269
|
+
baseMetadata: options.baseMetadata,
|
|
7270
|
+
defaultChunking: options.defaultChunking,
|
|
7271
|
+
extractors: options.extractors,
|
|
7272
|
+
urls: options.urls
|
|
7273
|
+
});
|
|
7274
|
+
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.sourceUrl === "string" ? document.metadata.sourceUrl : document.source ?? document.title ?? ""));
|
|
7275
|
+
const reconciled = await reconcileManagedDocuments({
|
|
7276
|
+
collection,
|
|
7277
|
+
deleteDocument,
|
|
7278
|
+
documents: managedDocuments,
|
|
7279
|
+
listDocuments,
|
|
7280
|
+
sourceId: options.id
|
|
7281
|
+
});
|
|
7282
|
+
return {
|
|
7283
|
+
chunkCount: reconciled.chunkCount,
|
|
7284
|
+
documentCount: reconciled.documentCount,
|
|
7285
|
+
metadata: {
|
|
7286
|
+
deletedCount: reconciled.deletedCount,
|
|
7287
|
+
updatedCount: reconciled.updatedCount,
|
|
7288
|
+
urlCount: options.urls.length
|
|
7289
|
+
}
|
|
7290
|
+
};
|
|
7291
|
+
}
|
|
7292
|
+
});
|
|
7293
|
+
var createRAGSyncManager = (options) => {
|
|
7294
|
+
const sourceMap = new Map(options.sources.map((source) => [source.id, source]));
|
|
7295
|
+
const state = new Map(options.sources.map((source) => [source.id, toSourceRecord(source)]));
|
|
7296
|
+
const runSource = async (source) => {
|
|
7297
|
+
const running = toSourceRecord(source, {
|
|
7298
|
+
lastError: undefined,
|
|
7299
|
+
status: "running"
|
|
7300
|
+
});
|
|
7301
|
+
state.set(source.id, running);
|
|
7302
|
+
const startedAt = Date.now();
|
|
7303
|
+
try {
|
|
7304
|
+
const result = await source.sync({
|
|
7305
|
+
collection: options.collection,
|
|
7306
|
+
deleteDocument: options.deleteDocument,
|
|
7307
|
+
listDocuments: options.listDocuments
|
|
7308
|
+
});
|
|
7309
|
+
const completed = toSourceRecord(source, {
|
|
7310
|
+
chunkCount: result.chunkCount,
|
|
7311
|
+
documentCount: result.documentCount,
|
|
7312
|
+
lastError: undefined,
|
|
7313
|
+
lastSyncedAt: Date.now(),
|
|
7314
|
+
lastSyncDurationMs: Date.now() - startedAt,
|
|
7315
|
+
metadata: result.metadata === undefined ? source.metadata : {
|
|
7316
|
+
...source.metadata ?? {},
|
|
7317
|
+
...result.metadata
|
|
7318
|
+
},
|
|
7319
|
+
status: "completed"
|
|
7320
|
+
});
|
|
7321
|
+
state.set(source.id, completed);
|
|
7322
|
+
return completed;
|
|
7323
|
+
} catch (caught) {
|
|
7324
|
+
const failed = toSourceRecord(source, {
|
|
7325
|
+
lastError: toSyncError(caught),
|
|
7326
|
+
lastSyncedAt: Date.now(),
|
|
7327
|
+
lastSyncDurationMs: Date.now() - startedAt,
|
|
7328
|
+
status: "failed"
|
|
7329
|
+
});
|
|
7330
|
+
state.set(source.id, failed);
|
|
7331
|
+
throw caught;
|
|
7332
|
+
}
|
|
7333
|
+
};
|
|
7334
|
+
return {
|
|
7335
|
+
listSyncSources: () => [...state.values()],
|
|
7336
|
+
syncAllSources: async () => {
|
|
7337
|
+
const sources = await Promise.all(options.sources.map(async (source) => runSource(source)));
|
|
7338
|
+
return { ok: true, sources };
|
|
7339
|
+
},
|
|
7340
|
+
syncSource: async (id) => {
|
|
7341
|
+
const source = sourceMap.get(id);
|
|
7342
|
+
if (!source) {
|
|
7343
|
+
return {
|
|
7344
|
+
error: `RAG sync source ${id} is not configured`,
|
|
7345
|
+
ok: false
|
|
7346
|
+
};
|
|
7347
|
+
}
|
|
7348
|
+
return {
|
|
7349
|
+
ok: true,
|
|
7350
|
+
source: await runSource(source)
|
|
7351
|
+
};
|
|
7352
|
+
}
|
|
7353
|
+
};
|
|
7354
|
+
};
|
|
6968
7355
|
// src/ai/rag/adapters/utils.ts
|
|
6969
7356
|
var vectorDimensionDefault = 24;
|
|
6970
7357
|
var createRAGVector = (text, dimensions = vectorDimensionDefault) => {
|
|
@@ -8705,6 +9092,37 @@ var createRAGClient = (options) => {
|
|
|
8705
9092
|
}
|
|
8706
9093
|
return parseJson(response);
|
|
8707
9094
|
},
|
|
9095
|
+
async syncSources() {
|
|
9096
|
+
const response = await fetchImpl(`${basePath}/sync`);
|
|
9097
|
+
if (!response.ok) {
|
|
9098
|
+
throw new Error(await toErrorMessage3(response));
|
|
9099
|
+
}
|
|
9100
|
+
return parseJson(response);
|
|
9101
|
+
},
|
|
9102
|
+
async syncAllSources() {
|
|
9103
|
+
const response = await fetchImpl(`${basePath}/sync`, {
|
|
9104
|
+
method: "POST"
|
|
9105
|
+
});
|
|
9106
|
+
if (!response.ok) {
|
|
9107
|
+
return {
|
|
9108
|
+
error: await toErrorMessage3(response),
|
|
9109
|
+
ok: false
|
|
9110
|
+
};
|
|
9111
|
+
}
|
|
9112
|
+
return parseJson(response);
|
|
9113
|
+
},
|
|
9114
|
+
async syncSource(id) {
|
|
9115
|
+
const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
|
|
9116
|
+
method: "POST"
|
|
9117
|
+
});
|
|
9118
|
+
if (!response.ok) {
|
|
9119
|
+
return {
|
|
9120
|
+
error: await toErrorMessage3(response),
|
|
9121
|
+
ok: false
|
|
9122
|
+
};
|
|
9123
|
+
}
|
|
9124
|
+
return parseJson(response);
|
|
9125
|
+
},
|
|
8708
9126
|
async reindexDocument(id) {
|
|
8709
9127
|
const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
|
|
8710
9128
|
method: "POST"
|
|
@@ -8847,7 +9265,9 @@ export {
|
|
|
8847
9265
|
createTextFileExtractor,
|
|
8848
9266
|
createSQLiteRAGStore,
|
|
8849
9267
|
createRAGVector,
|
|
9268
|
+
createRAGUrlSyncSource,
|
|
8850
9269
|
createAIStream as createRAGTransport,
|
|
9270
|
+
createRAGSyncManager,
|
|
8851
9271
|
createRAGReranker,
|
|
8852
9272
|
createRAGQueryTransform,
|
|
8853
9273
|
createRAGPDFOCRExtractor,
|
|
@@ -8860,6 +9280,7 @@ export {
|
|
|
8860
9280
|
createRAGFileExtractor,
|
|
8861
9281
|
createRAGEvaluationSuite,
|
|
8862
9282
|
createRAGEmbeddingProvider,
|
|
9283
|
+
createRAGDirectorySyncSource,
|
|
8863
9284
|
createRAGCollection,
|
|
8864
9285
|
createRAGClient,
|
|
8865
9286
|
createRAGArchiveFileExtractor,
|
|
@@ -8900,5 +9321,5 @@ export {
|
|
|
8900
9321
|
aiChat
|
|
8901
9322
|
};
|
|
8902
9323
|
|
|
8903
|
-
//# debugId=
|
|
9324
|
+
//# debugId=59C623D542A7B40F64756E2164756E21
|
|
8904
9325
|
//# sourceMappingURL=index.js.map
|