@absolutejs/absolute 0.19.0-beta.497 → 0.19.0-beta.499
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 +36 -1
- package/dist/ai/client/index.js.map +3 -3
- package/dist/ai/index.js +647 -12
- package/dist/ai/index.js.map +7 -6
- package/dist/ai-client/angular/ai/index.js +44 -0
- package/dist/ai-client/react/ai/index.js +68 -2
- package/dist/ai-client/vue/ai/index.js +68 -2
- package/dist/angular/ai/index.js +45 -1
- package/dist/angular/ai/index.js.map +4 -4
- package/dist/react/ai/index.js +69 -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 +9 -0
- package/dist/src/ai/rag/types.d.ts +1 -1
- package/dist/src/angular/ai/rag-client.service.d.ts +4 -1
- package/dist/src/react/ai/useRAG.d.ts +25 -0
- package/dist/src/react/ai/useRAGIndexAdmin.d.ts +25 -1
- package/dist/src/react/ai/useRAGOps.d.ts +2 -1
- package/dist/src/svelte/ai/createRAG.d.ts +25 -0
- package/dist/src/svelte/ai/createRAGIndexAdmin.d.ts +25 -1
- package/dist/src/svelte/ai/createRAGOps.d.ts +2 -1
- package/dist/src/vue/ai/useRAG.d.ts +165 -4
- package/dist/src/vue/ai/useRAGIndexAdmin.d.ts +123 -1
- package/dist/src/vue/ai/useRAGOps.d.ts +44 -5
- package/dist/svelte/ai/index.js +69 -3
- package/dist/svelte/ai/index.js.map +5 -5
- package/dist/types/ai.d.ts +127 -2
- package/dist/vue/ai/index.js +69 -3
- package/dist/vue/ai/index.js.map +5 -5
- package/package.json +1 -1
package/dist/ai/index.js
CHANGED
|
@@ -4846,6 +4846,12 @@ var normalizeStringArray2 = (value) => {
|
|
|
4846
4846
|
};
|
|
4847
4847
|
var normalizeChunkingOptions = (value) => isMetadataMap(value) ? value : undefined;
|
|
4848
4848
|
var getNumericStatus = (status) => typeof status === "number" ? status : HTTP_STATUS_OK;
|
|
4849
|
+
var getBooleanProperty = (value, key) => {
|
|
4850
|
+
if (!isObjectRecord(value)) {
|
|
4851
|
+
return;
|
|
4852
|
+
}
|
|
4853
|
+
return typeof value[key] === "boolean" ? value[key] : undefined;
|
|
4854
|
+
};
|
|
4849
4855
|
var isRAGDocumentChunk = (value) => isObjectRecord(value) && typeof value.chunkId === "string" && typeof value.text === "string";
|
|
4850
4856
|
var isRAGDocument = (value) => isObjectRecord(value) && typeof value.text === "string";
|
|
4851
4857
|
var isRAGDocumentUrl = (value) => isObjectRecord(value) && typeof value.url === "string" && value.url.trim().length > 0;
|
|
@@ -4979,6 +4985,7 @@ var ragChat = (config) => {
|
|
|
4979
4985
|
const ingestJobs = [];
|
|
4980
4986
|
const adminActions = [];
|
|
4981
4987
|
const adminJobs = [];
|
|
4988
|
+
const syncJobs = [];
|
|
4982
4989
|
const workflowRenderConfig = typeof config.htmx === "object" ? config.htmx.workflowRender ?? config.htmx.workflow?.render : undefined;
|
|
4983
4990
|
const workflowRenderers = resolveRAGWorkflowRenderers(workflowRenderConfig);
|
|
4984
4991
|
const createIngestJob = (inputKind, requestedCount) => {
|
|
@@ -5012,13 +5019,14 @@ var ragChat = (config) => {
|
|
|
5012
5019
|
job.error = error;
|
|
5013
5020
|
job.extractorNames = extractorNames;
|
|
5014
5021
|
};
|
|
5015
|
-
const createAdminAction = (action, documentId) => {
|
|
5022
|
+
const createAdminAction = (action, documentId, target) => {
|
|
5016
5023
|
const record = {
|
|
5017
5024
|
action,
|
|
5018
5025
|
documentId,
|
|
5019
5026
|
id: generateId(),
|
|
5020
5027
|
startedAt: Date.now(),
|
|
5021
|
-
status: "completed"
|
|
5028
|
+
status: "completed",
|
|
5029
|
+
target
|
|
5022
5030
|
};
|
|
5023
5031
|
adminActions.unshift(record);
|
|
5024
5032
|
if (adminActions.length > MAX_ADMIN_ACTIONS) {
|
|
@@ -5026,7 +5034,7 @@ var ragChat = (config) => {
|
|
|
5026
5034
|
}
|
|
5027
5035
|
return record;
|
|
5028
5036
|
};
|
|
5029
|
-
const createAdminJob = (action, target) => {
|
|
5037
|
+
const createAdminJob = (action, target, bucket = adminJobs) => {
|
|
5030
5038
|
const job = {
|
|
5031
5039
|
action,
|
|
5032
5040
|
id: generateId(),
|
|
@@ -5034,9 +5042,9 @@ var ragChat = (config) => {
|
|
|
5034
5042
|
status: "running",
|
|
5035
5043
|
target
|
|
5036
5044
|
};
|
|
5037
|
-
|
|
5038
|
-
if (
|
|
5039
|
-
|
|
5045
|
+
bucket.unshift(job);
|
|
5046
|
+
if (bucket.length > MAX_ADMIN_JOBS) {
|
|
5047
|
+
bucket.length = MAX_ADMIN_JOBS;
|
|
5040
5048
|
}
|
|
5041
5049
|
return job;
|
|
5042
5050
|
};
|
|
@@ -5066,6 +5074,12 @@ var ragChat = (config) => {
|
|
|
5066
5074
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
5067
5075
|
job.error = error;
|
|
5068
5076
|
};
|
|
5077
|
+
const buildSyncSources = async () => {
|
|
5078
|
+
if (!indexManager?.listSyncSources) {
|
|
5079
|
+
return [];
|
|
5080
|
+
}
|
|
5081
|
+
return await indexManager.listSyncSources();
|
|
5082
|
+
};
|
|
5069
5083
|
const toHTMXResponse = (html, status, extraHeaders) => new Response(html, {
|
|
5070
5084
|
headers: {
|
|
5071
5085
|
...HTML_HEADERS,
|
|
@@ -5501,6 +5515,12 @@ var ragChat = (config) => {
|
|
|
5501
5515
|
}
|
|
5502
5516
|
failuresByAdminAction.set(job.action, (failuresByAdminAction.get(job.action) ?? 0) + 1);
|
|
5503
5517
|
}
|
|
5518
|
+
for (const job of syncJobs) {
|
|
5519
|
+
if (job.status !== "failed") {
|
|
5520
|
+
continue;
|
|
5521
|
+
}
|
|
5522
|
+
failuresByAdminAction.set(job.action, (failuresByAdminAction.get(job.action) ?? 0) + 1);
|
|
5523
|
+
}
|
|
5504
5524
|
return {
|
|
5505
5525
|
averageChunksPerDocument: documents.length > 0 ? Number((documents.reduce((sum, document) => sum + (document.chunkCount ?? 0), 0) / documents.length).toFixed(2)) : 0,
|
|
5506
5526
|
duplicateDocumentIds: [...documentIdCounts.entries()].filter(([, count]) => count > 1).map(([id]) => id),
|
|
@@ -5546,10 +5566,13 @@ var ragChat = (config) => {
|
|
|
5546
5566
|
canClearIndex: Boolean(ragStore?.clear),
|
|
5547
5567
|
canCreateDocument: Boolean(indexManager?.createDocument),
|
|
5548
5568
|
canDeleteDocument: Boolean(indexManager?.deleteDocument),
|
|
5569
|
+
canListSyncSources: Boolean(indexManager?.listSyncSources),
|
|
5549
5570
|
canReindexDocument: Boolean(indexManager?.reindexDocument),
|
|
5550
5571
|
canReindexSource: Boolean(indexManager?.reindexSource),
|
|
5551
5572
|
canReseed: Boolean(indexManager?.reseed),
|
|
5552
|
-
canReset: Boolean(indexManager?.reset)
|
|
5573
|
+
canReset: Boolean(indexManager?.reset),
|
|
5574
|
+
canSyncAllSources: Boolean(indexManager?.syncAllSources),
|
|
5575
|
+
canSyncSource: Boolean(indexManager?.syncSource)
|
|
5553
5576
|
});
|
|
5554
5577
|
const buildOperationsPayload = async () => {
|
|
5555
5578
|
const collection = config.collection ?? (ragStore ? createRAGCollection({
|
|
@@ -5562,14 +5585,15 @@ var ragChat = (config) => {
|
|
|
5562
5585
|
return {
|
|
5563
5586
|
admin: buildAdminCapabilities(),
|
|
5564
5587
|
adminActions: [...adminActions],
|
|
5565
|
-
adminJobs: [...adminJobs],
|
|
5588
|
+
adminJobs: [...adminJobs, ...syncJobs].sort((left, right) => right.startedAt - left.startedAt),
|
|
5566
5589
|
capabilities: collection?.getCapabilities?.(),
|
|
5567
5590
|
documents: indexManager ? summarizeDocuments(indexedDocuments) : undefined,
|
|
5568
5591
|
health: await summarizeHealth(indexedDocuments),
|
|
5569
5592
|
ingestJobs: [...ingestJobs],
|
|
5570
5593
|
ok: true,
|
|
5571
5594
|
readiness: buildReadiness(),
|
|
5572
|
-
status: collection?.getStatus?.()
|
|
5595
|
+
status: collection?.getStatus?.(),
|
|
5596
|
+
syncSources: await buildSyncSources()
|
|
5573
5597
|
};
|
|
5574
5598
|
};
|
|
5575
5599
|
const handleStatus = async () => buildOperationsPayload();
|
|
@@ -5806,6 +5830,100 @@ var ragChat = (config) => {
|
|
|
5806
5830
|
...normalized
|
|
5807
5831
|
};
|
|
5808
5832
|
};
|
|
5833
|
+
const handleSyncSources = async () => {
|
|
5834
|
+
if (!indexManager?.listSyncSources) {
|
|
5835
|
+
return {
|
|
5836
|
+
error: "RAG source sync is not configured",
|
|
5837
|
+
ok: false
|
|
5838
|
+
};
|
|
5839
|
+
}
|
|
5840
|
+
return {
|
|
5841
|
+
ok: true,
|
|
5842
|
+
sources: await indexManager.listSyncSources()
|
|
5843
|
+
};
|
|
5844
|
+
};
|
|
5845
|
+
const handleSyncAllSources = async (options) => {
|
|
5846
|
+
if (!indexManager?.syncAllSources) {
|
|
5847
|
+
return {
|
|
5848
|
+
error: "RAG source sync is not configured",
|
|
5849
|
+
ok: false
|
|
5850
|
+
};
|
|
5851
|
+
}
|
|
5852
|
+
const job = createAdminJob("sync_all_sources", undefined, syncJobs);
|
|
5853
|
+
const action = createAdminAction("sync_all_sources");
|
|
5854
|
+
try {
|
|
5855
|
+
const result = await indexManager.syncAllSources(options);
|
|
5856
|
+
if (result && "ok" in result) {
|
|
5857
|
+
if (!result.ok) {
|
|
5858
|
+
failAdminJob(job, result.error);
|
|
5859
|
+
failAdminAction(action, result.error);
|
|
5860
|
+
return result;
|
|
5861
|
+
}
|
|
5862
|
+
if (result.partial) {
|
|
5863
|
+
const failedSourceIds = "sources" in result ? result.failedSourceIds : undefined;
|
|
5864
|
+
const message = failedSourceIds?.length ? `Partial source sync failure: ${failedSourceIds.join(", ")}` : "Partial source sync failure";
|
|
5865
|
+
failAdminJob(job, message);
|
|
5866
|
+
failAdminAction(action, message);
|
|
5867
|
+
return result;
|
|
5868
|
+
}
|
|
5869
|
+
completeAdminJob(job);
|
|
5870
|
+
completeAdminAction(action);
|
|
5871
|
+
return result;
|
|
5872
|
+
}
|
|
5873
|
+
completeAdminJob(job);
|
|
5874
|
+
completeAdminAction(action);
|
|
5875
|
+
return {
|
|
5876
|
+
ok: true,
|
|
5877
|
+
sources: await buildSyncSources()
|
|
5878
|
+
};
|
|
5879
|
+
} catch (caught) {
|
|
5880
|
+
const message = caught instanceof Error ? caught.message : String(caught);
|
|
5881
|
+
failAdminJob(job, message);
|
|
5882
|
+
failAdminAction(action, message);
|
|
5883
|
+
throw caught;
|
|
5884
|
+
}
|
|
5885
|
+
};
|
|
5886
|
+
const handleSyncSource = async (id, options) => {
|
|
5887
|
+
if (!indexManager?.syncSource) {
|
|
5888
|
+
return {
|
|
5889
|
+
error: "RAG source sync is not configured",
|
|
5890
|
+
ok: false
|
|
5891
|
+
};
|
|
5892
|
+
}
|
|
5893
|
+
if (!id) {
|
|
5894
|
+
return {
|
|
5895
|
+
error: "sync source id is required",
|
|
5896
|
+
ok: false
|
|
5897
|
+
};
|
|
5898
|
+
}
|
|
5899
|
+
const job = createAdminJob("sync_source", id, syncJobs);
|
|
5900
|
+
const action = createAdminAction("sync_source", undefined, id);
|
|
5901
|
+
try {
|
|
5902
|
+
const result = await indexManager.syncSource(id, options);
|
|
5903
|
+
if (result && "ok" in result) {
|
|
5904
|
+
if (!result.ok) {
|
|
5905
|
+
failAdminJob(job, result.error);
|
|
5906
|
+
failAdminAction(action, result.error);
|
|
5907
|
+
return result;
|
|
5908
|
+
}
|
|
5909
|
+
completeAdminJob(job);
|
|
5910
|
+
completeAdminAction(action);
|
|
5911
|
+
return result;
|
|
5912
|
+
}
|
|
5913
|
+
completeAdminJob(job);
|
|
5914
|
+
completeAdminAction(action);
|
|
5915
|
+
const source = (await buildSyncSources()).find((record) => record.id === id);
|
|
5916
|
+
return source ? { ok: true, source } : {
|
|
5917
|
+
error: "sync source not found",
|
|
5918
|
+
ok: false
|
|
5919
|
+
};
|
|
5920
|
+
} catch (caught) {
|
|
5921
|
+
const message = caught instanceof Error ? caught.message : String(caught);
|
|
5922
|
+
failAdminJob(job, message);
|
|
5923
|
+
failAdminAction(action, message);
|
|
5924
|
+
throw caught;
|
|
5925
|
+
}
|
|
5926
|
+
};
|
|
5809
5927
|
const htmxRoutes = () => {
|
|
5810
5928
|
if (!config.htmx) {
|
|
5811
5929
|
return new Elysia2;
|
|
@@ -6042,6 +6160,53 @@ var ragChat = (config) => {
|
|
|
6042
6160
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
6043
6161
|
}
|
|
6044
6162
|
return result;
|
|
6163
|
+
}).get(`${path}/sync`, async ({ request, set }) => {
|
|
6164
|
+
const result = await handleSyncSources();
|
|
6165
|
+
if (!result.ok) {
|
|
6166
|
+
set.status = HTTP_STATUS_NOT_FOUND;
|
|
6167
|
+
}
|
|
6168
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6169
|
+
if (!result.ok) {
|
|
6170
|
+
return toHTMXResponse(workflowRenderers.error(result.error), getNumericStatus(set.status));
|
|
6171
|
+
}
|
|
6172
|
+
return toHTMXResponse(workflowRenderers.mutationResult({
|
|
6173
|
+
ok: true,
|
|
6174
|
+
status: `loaded ${"sources" in result ? result.sources.length : 1} sync sources`
|
|
6175
|
+
}));
|
|
6176
|
+
}
|
|
6177
|
+
return result;
|
|
6178
|
+
}).post(`${path}/sync`, async ({ body, request, set }) => {
|
|
6179
|
+
const background = getBooleanProperty(body, "background");
|
|
6180
|
+
const result = await handleSyncAllSources({ background });
|
|
6181
|
+
if (!result.ok) {
|
|
6182
|
+
set.status = HTTP_STATUS_NOT_FOUND;
|
|
6183
|
+
}
|
|
6184
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6185
|
+
const html = result.ok ? workflowRenderers.mutationResult({
|
|
6186
|
+
ok: true,
|
|
6187
|
+
status: background === true ? "source sync queued in the background" : "source sync started and completed successfully"
|
|
6188
|
+
}) : workflowRenderers.error(result.error ?? "Failed to sync sources");
|
|
6189
|
+
return toHTMXResponse(html, getNumericStatus(set.status), {
|
|
6190
|
+
"HX-Trigger": "rag:mutated"
|
|
6191
|
+
});
|
|
6192
|
+
}
|
|
6193
|
+
return result;
|
|
6194
|
+
}).post(`${path}/sync/:id`, async ({ body, params, request, set }) => {
|
|
6195
|
+
const background = getBooleanProperty(body, "background");
|
|
6196
|
+
const result = await handleSyncSource(typeof params.id === "string" ? params.id.trim() : "", { background });
|
|
6197
|
+
if (!result.ok) {
|
|
6198
|
+
set.status = result.error === "sync source id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
6199
|
+
}
|
|
6200
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
6201
|
+
const html = result.ok ? workflowRenderers.mutationResult({
|
|
6202
|
+
ok: true,
|
|
6203
|
+
status: background === true ? "source sync queued in the background" : "source sync started and completed successfully"
|
|
6204
|
+
}) : workflowRenderers.error(result.error ?? "Failed to sync source");
|
|
6205
|
+
return toHTMXResponse(html, getNumericStatus(set.status), {
|
|
6206
|
+
"HX-Trigger": "rag:mutated"
|
|
6207
|
+
});
|
|
6208
|
+
}
|
|
6209
|
+
return result;
|
|
6045
6210
|
}).post(`${path}/ingest`, async ({ body, request, set }) => {
|
|
6046
6211
|
const result = await handleIngest(body);
|
|
6047
6212
|
if (!result.ok) {
|
|
@@ -7020,6 +7185,436 @@ var resolveRAGStreamStage = ({
|
|
|
7020
7185
|
}
|
|
7021
7186
|
return "streaming";
|
|
7022
7187
|
};
|
|
7188
|
+
// src/ai/rag/sync.ts
|
|
7189
|
+
import { createHash } from "crypto";
|
|
7190
|
+
import { mkdir, readFile as readFile2, writeFile } from "fs/promises";
|
|
7191
|
+
import { dirname, resolve as resolve2 } from "path";
|
|
7192
|
+
var toSyncError = (caught) => caught instanceof Error ? caught.message : String(caught);
|
|
7193
|
+
var wait = async (delayMs) => {
|
|
7194
|
+
if (!(delayMs > 0)) {
|
|
7195
|
+
return;
|
|
7196
|
+
}
|
|
7197
|
+
await new Promise((resolve3) => setTimeout(resolve3, delayMs));
|
|
7198
|
+
};
|
|
7199
|
+
var parseSyncState = (content) => {
|
|
7200
|
+
try {
|
|
7201
|
+
const parsed = JSON.parse(content);
|
|
7202
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
7203
|
+
} catch {
|
|
7204
|
+
return [];
|
|
7205
|
+
}
|
|
7206
|
+
};
|
|
7207
|
+
var createSyncFingerprint = (document) => createHash("sha1").update(document.source ?? "").update(`
|
|
7208
|
+
`).update(document.title ?? "").update(`
|
|
7209
|
+
`).update(document.text).digest("hex");
|
|
7210
|
+
var toManagedSyncDocument = (sourceId, document, syncKey) => ({
|
|
7211
|
+
...document,
|
|
7212
|
+
metadata: {
|
|
7213
|
+
...document.metadata ?? {},
|
|
7214
|
+
syncFingerprint: createSyncFingerprint(document),
|
|
7215
|
+
syncKey,
|
|
7216
|
+
syncSourceId: sourceId
|
|
7217
|
+
}
|
|
7218
|
+
});
|
|
7219
|
+
var isManagedBySyncSource = (document, sourceId) => document.metadata?.syncSourceId === sourceId;
|
|
7220
|
+
var getDocumentSyncFingerprint = (document) => typeof document.metadata?.syncFingerprint === "string" ? document.metadata.syncFingerprint : undefined;
|
|
7221
|
+
var reconcileManagedDocuments = async (input) => {
|
|
7222
|
+
const prepared = prepareRAGDocuments({
|
|
7223
|
+
documents: input.documents
|
|
7224
|
+
});
|
|
7225
|
+
const nextDocumentIds = new Set(prepared.map((document) => document.documentId));
|
|
7226
|
+
const nextFingerprintById = new Map(prepared.map((document, index) => [
|
|
7227
|
+
document.documentId,
|
|
7228
|
+
createSyncFingerprint(input.documents[index])
|
|
7229
|
+
]));
|
|
7230
|
+
const existingDocuments = input.listDocuments ? await input.listDocuments() : [];
|
|
7231
|
+
const managedDocuments = existingDocuments.filter((document) => isManagedBySyncSource(document, input.sourceId));
|
|
7232
|
+
const staleDocuments = managedDocuments.filter((document) => !nextDocumentIds.has(document.id));
|
|
7233
|
+
const changedPrepared = prepared.filter((document) => {
|
|
7234
|
+
const existing = managedDocuments.find((entry) => entry.id === document.documentId);
|
|
7235
|
+
if (!existing) {
|
|
7236
|
+
return true;
|
|
7237
|
+
}
|
|
7238
|
+
return getDocumentSyncFingerprint(existing) !== nextFingerprintById.get(document.documentId);
|
|
7239
|
+
});
|
|
7240
|
+
if (input.deleteDocument) {
|
|
7241
|
+
await Promise.all(staleDocuments.map(async (document) => {
|
|
7242
|
+
await input.deleteDocument?.(document.id);
|
|
7243
|
+
}));
|
|
7244
|
+
}
|
|
7245
|
+
if (changedPrepared.length > 0) {
|
|
7246
|
+
await input.collection.ingest({
|
|
7247
|
+
chunks: changedPrepared.flatMap((document) => document.chunks)
|
|
7248
|
+
});
|
|
7249
|
+
}
|
|
7250
|
+
return {
|
|
7251
|
+
chunkCount: prepared.reduce((sum, document) => sum + document.chunks.length, 0),
|
|
7252
|
+
deletedCount: staleDocuments.length,
|
|
7253
|
+
documentCount: prepared.length,
|
|
7254
|
+
updatedCount: changedPrepared.length
|
|
7255
|
+
};
|
|
7256
|
+
};
|
|
7257
|
+
var toSourceRecord = (source, overrides) => ({
|
|
7258
|
+
description: source.description,
|
|
7259
|
+
id: source.id,
|
|
7260
|
+
kind: source.kind,
|
|
7261
|
+
label: source.label,
|
|
7262
|
+
metadata: source.metadata,
|
|
7263
|
+
status: "idle",
|
|
7264
|
+
target: source.target,
|
|
7265
|
+
...overrides
|
|
7266
|
+
});
|
|
7267
|
+
var createRAGDirectorySyncSource = (options) => ({
|
|
7268
|
+
description: options.description,
|
|
7269
|
+
id: options.id,
|
|
7270
|
+
kind: "directory",
|
|
7271
|
+
label: options.label,
|
|
7272
|
+
metadata: options.metadata,
|
|
7273
|
+
retryAttempts: options.retryAttempts,
|
|
7274
|
+
retryDelayMs: options.retryDelayMs,
|
|
7275
|
+
target: options.directory,
|
|
7276
|
+
sync: async ({ collection, deleteDocument, listDocuments }) => {
|
|
7277
|
+
const loaded = await loadRAGDocumentsFromDirectory({
|
|
7278
|
+
baseMetadata: options.baseMetadata,
|
|
7279
|
+
defaultChunking: options.defaultChunking,
|
|
7280
|
+
directory: options.directory,
|
|
7281
|
+
extractors: options.extractors,
|
|
7282
|
+
includeExtensions: options.includeExtensions,
|
|
7283
|
+
recursive: options.recursive
|
|
7284
|
+
});
|
|
7285
|
+
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.relativePath === "string" ? document.metadata.relativePath : document.source ?? document.title ?? ""));
|
|
7286
|
+
const reconciled = await reconcileManagedDocuments({
|
|
7287
|
+
collection,
|
|
7288
|
+
deleteDocument,
|
|
7289
|
+
documents: managedDocuments,
|
|
7290
|
+
listDocuments,
|
|
7291
|
+
sourceId: options.id
|
|
7292
|
+
});
|
|
7293
|
+
return {
|
|
7294
|
+
chunkCount: reconciled.chunkCount,
|
|
7295
|
+
documentCount: reconciled.documentCount,
|
|
7296
|
+
metadata: {
|
|
7297
|
+
deletedCount: reconciled.deletedCount,
|
|
7298
|
+
directory: options.directory,
|
|
7299
|
+
recursive: options.recursive !== false,
|
|
7300
|
+
updatedCount: reconciled.updatedCount
|
|
7301
|
+
}
|
|
7302
|
+
};
|
|
7303
|
+
}
|
|
7304
|
+
});
|
|
7305
|
+
var createRAGUrlSyncSource = (options) => ({
|
|
7306
|
+
description: options.description,
|
|
7307
|
+
id: options.id,
|
|
7308
|
+
kind: "url",
|
|
7309
|
+
label: options.label,
|
|
7310
|
+
metadata: options.metadata,
|
|
7311
|
+
retryAttempts: options.retryAttempts,
|
|
7312
|
+
retryDelayMs: options.retryDelayMs,
|
|
7313
|
+
target: options.urls.length === 1 ? options.urls[0]?.url : `${options.urls.length} urls`,
|
|
7314
|
+
sync: async ({ collection, deleteDocument, listDocuments }) => {
|
|
7315
|
+
const loaded = await loadRAGDocumentsFromURLs({
|
|
7316
|
+
baseMetadata: options.baseMetadata,
|
|
7317
|
+
defaultChunking: options.defaultChunking,
|
|
7318
|
+
extractors: options.extractors,
|
|
7319
|
+
urls: options.urls
|
|
7320
|
+
});
|
|
7321
|
+
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.sourceUrl === "string" ? document.metadata.sourceUrl : document.source ?? document.title ?? ""));
|
|
7322
|
+
const reconciled = await reconcileManagedDocuments({
|
|
7323
|
+
collection,
|
|
7324
|
+
deleteDocument,
|
|
7325
|
+
documents: managedDocuments,
|
|
7326
|
+
listDocuments,
|
|
7327
|
+
sourceId: options.id
|
|
7328
|
+
});
|
|
7329
|
+
return {
|
|
7330
|
+
chunkCount: reconciled.chunkCount,
|
|
7331
|
+
documentCount: reconciled.documentCount,
|
|
7332
|
+
metadata: {
|
|
7333
|
+
deletedCount: reconciled.deletedCount,
|
|
7334
|
+
updatedCount: reconciled.updatedCount,
|
|
7335
|
+
urlCount: options.urls.length
|
|
7336
|
+
}
|
|
7337
|
+
};
|
|
7338
|
+
}
|
|
7339
|
+
});
|
|
7340
|
+
var createRAGSyncManager = (options) => {
|
|
7341
|
+
const sourceMap = new Map(options.sources.map((source) => [source.id, source]));
|
|
7342
|
+
const state = new Map(options.sources.map((source) => [source.id, toSourceRecord(source)]));
|
|
7343
|
+
const activeRuns = new Map;
|
|
7344
|
+
let hydrationPromise = null;
|
|
7345
|
+
const persistState = async () => {
|
|
7346
|
+
if (!options.saveState) {
|
|
7347
|
+
return;
|
|
7348
|
+
}
|
|
7349
|
+
await options.saveState([...state.values()]);
|
|
7350
|
+
};
|
|
7351
|
+
const ensureHydrated = async () => {
|
|
7352
|
+
if (!options.loadState) {
|
|
7353
|
+
return;
|
|
7354
|
+
}
|
|
7355
|
+
if (!hydrationPromise) {
|
|
7356
|
+
hydrationPromise = Promise.resolve(options.loadState()).then((records) => {
|
|
7357
|
+
for (const record of records ?? []) {
|
|
7358
|
+
const source = sourceMap.get(record.id);
|
|
7359
|
+
if (!source) {
|
|
7360
|
+
continue;
|
|
7361
|
+
}
|
|
7362
|
+
state.set(record.id, toSourceRecord(source, {
|
|
7363
|
+
...record,
|
|
7364
|
+
metadata: {
|
|
7365
|
+
...source.metadata ?? {},
|
|
7366
|
+
...record.metadata ?? {}
|
|
7367
|
+
}
|
|
7368
|
+
}));
|
|
7369
|
+
}
|
|
7370
|
+
});
|
|
7371
|
+
}
|
|
7372
|
+
await hydrationPromise;
|
|
7373
|
+
};
|
|
7374
|
+
const resolveRetryAttempts = (source) => Math.max(0, source.retryAttempts ?? options.retryAttempts ?? 0);
|
|
7375
|
+
const resolveRetryDelayMs = (source) => Math.max(0, source.retryDelayMs ?? options.retryDelayMs ?? 0);
|
|
7376
|
+
const setSourceState = async (record) => {
|
|
7377
|
+
state.set(record.id, record);
|
|
7378
|
+
await persistState();
|
|
7379
|
+
};
|
|
7380
|
+
const runSource = async (source) => {
|
|
7381
|
+
await ensureHydrated();
|
|
7382
|
+
const existingRun = activeRuns.get(source.id);
|
|
7383
|
+
if (existingRun) {
|
|
7384
|
+
return existingRun;
|
|
7385
|
+
}
|
|
7386
|
+
const previous = state.get(source.id);
|
|
7387
|
+
const retryAttempts = resolveRetryAttempts(source);
|
|
7388
|
+
const retryDelayMs = resolveRetryDelayMs(source);
|
|
7389
|
+
const startedAt = Date.now();
|
|
7390
|
+
const running = toSourceRecord(source, {
|
|
7391
|
+
chunkCount: previous?.chunkCount,
|
|
7392
|
+
consecutiveFailures: previous?.consecutiveFailures ?? 0,
|
|
7393
|
+
documentCount: previous?.documentCount,
|
|
7394
|
+
lastError: undefined,
|
|
7395
|
+
lastStartedAt: startedAt,
|
|
7396
|
+
lastSuccessfulSyncAt: previous?.lastSuccessfulSyncAt,
|
|
7397
|
+
lastSyncedAt: previous?.lastSyncedAt,
|
|
7398
|
+
lastSyncDurationMs: previous?.lastSyncDurationMs,
|
|
7399
|
+
nextRetryAt: undefined,
|
|
7400
|
+
retryAttempts,
|
|
7401
|
+
status: "running"
|
|
7402
|
+
});
|
|
7403
|
+
const runPromise = (async () => {
|
|
7404
|
+
await setSourceState(running);
|
|
7405
|
+
for (let attempt = 0;attempt <= retryAttempts; attempt++) {
|
|
7406
|
+
try {
|
|
7407
|
+
const result = await source.sync({
|
|
7408
|
+
collection: options.collection,
|
|
7409
|
+
deleteDocument: options.deleteDocument,
|
|
7410
|
+
listDocuments: options.listDocuments
|
|
7411
|
+
});
|
|
7412
|
+
const finishedAt = Date.now();
|
|
7413
|
+
const completed = toSourceRecord(source, {
|
|
7414
|
+
chunkCount: result.chunkCount,
|
|
7415
|
+
consecutiveFailures: 0,
|
|
7416
|
+
documentCount: result.documentCount,
|
|
7417
|
+
lastError: undefined,
|
|
7418
|
+
lastStartedAt: startedAt,
|
|
7419
|
+
lastSuccessfulSyncAt: finishedAt,
|
|
7420
|
+
lastSyncedAt: finishedAt,
|
|
7421
|
+
lastSyncDurationMs: finishedAt - startedAt,
|
|
7422
|
+
metadata: result.metadata === undefined ? source.metadata : {
|
|
7423
|
+
...source.metadata ?? {},
|
|
7424
|
+
...result.metadata
|
|
7425
|
+
},
|
|
7426
|
+
nextRetryAt: undefined,
|
|
7427
|
+
retryAttempts,
|
|
7428
|
+
status: "completed"
|
|
7429
|
+
});
|
|
7430
|
+
await setSourceState(completed);
|
|
7431
|
+
return completed;
|
|
7432
|
+
} catch (caught) {
|
|
7433
|
+
const message = toSyncError(caught);
|
|
7434
|
+
const finishedAt = Date.now();
|
|
7435
|
+
const hasRetriesRemaining = attempt < retryAttempts;
|
|
7436
|
+
const consecutiveFailures = (previous?.consecutiveFailures ?? 0) + attempt + 1;
|
|
7437
|
+
const failed = toSourceRecord(source, {
|
|
7438
|
+
chunkCount: previous?.chunkCount,
|
|
7439
|
+
consecutiveFailures,
|
|
7440
|
+
documentCount: previous?.documentCount,
|
|
7441
|
+
lastError: message,
|
|
7442
|
+
lastStartedAt: startedAt,
|
|
7443
|
+
lastSuccessfulSyncAt: previous?.lastSuccessfulSyncAt,
|
|
7444
|
+
lastSyncedAt: finishedAt,
|
|
7445
|
+
lastSyncDurationMs: finishedAt - startedAt,
|
|
7446
|
+
nextRetryAt: hasRetriesRemaining ? finishedAt + retryDelayMs : undefined,
|
|
7447
|
+
retryAttempts,
|
|
7448
|
+
status: "failed"
|
|
7449
|
+
});
|
|
7450
|
+
await setSourceState(failed);
|
|
7451
|
+
if (!hasRetriesRemaining) {
|
|
7452
|
+
return failed;
|
|
7453
|
+
}
|
|
7454
|
+
await wait(retryDelayMs);
|
|
7455
|
+
}
|
|
7456
|
+
}
|
|
7457
|
+
return state.get(source.id) ?? toSourceRecord(source, { status: "failed" });
|
|
7458
|
+
})().finally(() => {
|
|
7459
|
+
activeRuns.delete(source.id);
|
|
7460
|
+
});
|
|
7461
|
+
activeRuns.set(source.id, runPromise);
|
|
7462
|
+
return runPromise;
|
|
7463
|
+
};
|
|
7464
|
+
const resolveBackground = (runOptions) => runOptions?.background ?? options.backgroundByDefault ?? false;
|
|
7465
|
+
return {
|
|
7466
|
+
listSyncSources: async () => {
|
|
7467
|
+
await ensureHydrated();
|
|
7468
|
+
return [...state.values()];
|
|
7469
|
+
},
|
|
7470
|
+
syncAllSources: async (runOptions) => {
|
|
7471
|
+
await ensureHydrated();
|
|
7472
|
+
if (resolveBackground(runOptions)) {
|
|
7473
|
+
for (const source of options.sources) {
|
|
7474
|
+
runSource(source);
|
|
7475
|
+
}
|
|
7476
|
+
return {
|
|
7477
|
+
ok: true,
|
|
7478
|
+
sources: [...state.values()]
|
|
7479
|
+
};
|
|
7480
|
+
}
|
|
7481
|
+
const sources = [];
|
|
7482
|
+
const failedSourceIds = [];
|
|
7483
|
+
const errorsBySource = {};
|
|
7484
|
+
for (const source of options.sources) {
|
|
7485
|
+
const record = await runSource(source);
|
|
7486
|
+
sources.push(record);
|
|
7487
|
+
if (record.status === "failed") {
|
|
7488
|
+
failedSourceIds.push(record.id);
|
|
7489
|
+
if (record.lastError) {
|
|
7490
|
+
errorsBySource[record.id] = record.lastError;
|
|
7491
|
+
}
|
|
7492
|
+
if (options.continueOnError === false) {
|
|
7493
|
+
return {
|
|
7494
|
+
errorsBySource,
|
|
7495
|
+
failedSourceIds,
|
|
7496
|
+
ok: true,
|
|
7497
|
+
partial: true,
|
|
7498
|
+
sources
|
|
7499
|
+
};
|
|
7500
|
+
}
|
|
7501
|
+
}
|
|
7502
|
+
}
|
|
7503
|
+
return {
|
|
7504
|
+
errorsBySource: failedSourceIds.length > 0 ? errorsBySource : undefined,
|
|
7505
|
+
failedSourceIds: failedSourceIds.length > 0 ? failedSourceIds : undefined,
|
|
7506
|
+
ok: true,
|
|
7507
|
+
partial: failedSourceIds.length > 0,
|
|
7508
|
+
sources
|
|
7509
|
+
};
|
|
7510
|
+
},
|
|
7511
|
+
syncSource: async (id, runOptions) => {
|
|
7512
|
+
await ensureHydrated();
|
|
7513
|
+
const source = sourceMap.get(id);
|
|
7514
|
+
if (!source) {
|
|
7515
|
+
return {
|
|
7516
|
+
error: `RAG sync source ${id} is not configured`,
|
|
7517
|
+
ok: false
|
|
7518
|
+
};
|
|
7519
|
+
}
|
|
7520
|
+
if (resolveBackground(runOptions)) {
|
|
7521
|
+
const existingRecord = state.get(id);
|
|
7522
|
+
if (existingRecord?.status !== "running") {
|
|
7523
|
+
const running = toSourceRecord(source, {
|
|
7524
|
+
chunkCount: existingRecord?.chunkCount,
|
|
7525
|
+
consecutiveFailures: existingRecord?.consecutiveFailures ?? 0,
|
|
7526
|
+
documentCount: existingRecord?.documentCount,
|
|
7527
|
+
lastError: undefined,
|
|
7528
|
+
lastStartedAt: Date.now(),
|
|
7529
|
+
lastSuccessfulSyncAt: existingRecord?.lastSuccessfulSyncAt,
|
|
7530
|
+
lastSyncedAt: existingRecord?.lastSyncedAt,
|
|
7531
|
+
lastSyncDurationMs: existingRecord?.lastSyncDurationMs,
|
|
7532
|
+
nextRetryAt: undefined,
|
|
7533
|
+
retryAttempts: resolveRetryAttempts(source),
|
|
7534
|
+
status: "running"
|
|
7535
|
+
});
|
|
7536
|
+
await setSourceState(running);
|
|
7537
|
+
runSource(source);
|
|
7538
|
+
}
|
|
7539
|
+
return {
|
|
7540
|
+
ok: true,
|
|
7541
|
+
source: state.get(id) ?? toSourceRecord(source, {
|
|
7542
|
+
status: "running"
|
|
7543
|
+
})
|
|
7544
|
+
};
|
|
7545
|
+
}
|
|
7546
|
+
const record = await runSource(source);
|
|
7547
|
+
if (record.status === "failed") {
|
|
7548
|
+
return {
|
|
7549
|
+
error: record.lastError ?? `RAG sync source ${id} failed`,
|
|
7550
|
+
ok: false
|
|
7551
|
+
};
|
|
7552
|
+
}
|
|
7553
|
+
return {
|
|
7554
|
+
ok: true,
|
|
7555
|
+
source: record
|
|
7556
|
+
};
|
|
7557
|
+
}
|
|
7558
|
+
};
|
|
7559
|
+
};
|
|
7560
|
+
var createRAGFileSyncStateStore = (path) => {
|
|
7561
|
+
const resolvedPath = resolve2(path);
|
|
7562
|
+
return {
|
|
7563
|
+
load: async () => {
|
|
7564
|
+
try {
|
|
7565
|
+
return parseSyncState(await readFile2(resolvedPath, "utf8"));
|
|
7566
|
+
} catch {
|
|
7567
|
+
return [];
|
|
7568
|
+
}
|
|
7569
|
+
},
|
|
7570
|
+
save: async (records) => {
|
|
7571
|
+
await mkdir(dirname(resolvedPath), { recursive: true });
|
|
7572
|
+
await writeFile(resolvedPath, JSON.stringify(records, null, 2), "utf8");
|
|
7573
|
+
}
|
|
7574
|
+
};
|
|
7575
|
+
};
|
|
7576
|
+
var createRAGSyncScheduler = (input) => {
|
|
7577
|
+
const timers = new Map;
|
|
7578
|
+
let running = false;
|
|
7579
|
+
const runSchedule = async (schedule) => {
|
|
7580
|
+
if (schedule.sourceIds?.length) {
|
|
7581
|
+
for (const sourceId of schedule.sourceIds) {
|
|
7582
|
+
await input.manager.syncSource?.(sourceId, {
|
|
7583
|
+
background: schedule.background
|
|
7584
|
+
});
|
|
7585
|
+
}
|
|
7586
|
+
return;
|
|
7587
|
+
}
|
|
7588
|
+
await input.manager.syncAllSources?.({
|
|
7589
|
+
background: schedule.background
|
|
7590
|
+
});
|
|
7591
|
+
};
|
|
7592
|
+
return {
|
|
7593
|
+
start: async () => {
|
|
7594
|
+
if (running) {
|
|
7595
|
+
return;
|
|
7596
|
+
}
|
|
7597
|
+
running = true;
|
|
7598
|
+
for (const schedule of input.schedules) {
|
|
7599
|
+
if (schedule.runImmediately) {
|
|
7600
|
+
runSchedule(schedule);
|
|
7601
|
+
}
|
|
7602
|
+
timers.set(schedule.id, setInterval(() => {
|
|
7603
|
+
runSchedule(schedule);
|
|
7604
|
+
}, schedule.intervalMs));
|
|
7605
|
+
}
|
|
7606
|
+
},
|
|
7607
|
+
stop: () => {
|
|
7608
|
+
for (const timer of timers.values()) {
|
|
7609
|
+
clearInterval(timer);
|
|
7610
|
+
}
|
|
7611
|
+
timers.clear();
|
|
7612
|
+
running = false;
|
|
7613
|
+
},
|
|
7614
|
+
isRunning: () => running,
|
|
7615
|
+
listSchedules: () => [...input.schedules]
|
|
7616
|
+
};
|
|
7617
|
+
};
|
|
7023
7618
|
// src/ai/rag/adapters/utils.ts
|
|
7024
7619
|
var vectorDimensionDefault = 24;
|
|
7025
7620
|
var createRAGVector = (text, dimensions = vectorDimensionDefault) => {
|
|
@@ -7178,7 +7773,7 @@ import { existsSync as existsSync2 } from "fs";
|
|
|
7178
7773
|
import { existsSync, readFileSync } from "fs";
|
|
7179
7774
|
import { createRequire } from "module";
|
|
7180
7775
|
import { arch, platform } from "os";
|
|
7181
|
-
import { dirname, join as join2 } from "path";
|
|
7776
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
7182
7777
|
var require2 = createRequire(import.meta.url);
|
|
7183
7778
|
var PLATFORM_PACKAGE_MAP = {
|
|
7184
7779
|
"darwin-arm64": {
|
|
@@ -7229,7 +7824,7 @@ var resolveAbsoluteSQLiteVec = () => {
|
|
|
7229
7824
|
}
|
|
7230
7825
|
try {
|
|
7231
7826
|
const packageJsonPath = require2.resolve(`${packageInfo.packageName}/package.json`);
|
|
7232
|
-
const packageRoot =
|
|
7827
|
+
const packageRoot = dirname2(packageJsonPath);
|
|
7233
7828
|
const libraryPath = join2(packageRoot, packageInfo.libraryFile);
|
|
7234
7829
|
const packageVersion = readPackageVersion(packageJsonPath);
|
|
7235
7830
|
if (!existsSync(libraryPath)) {
|
|
@@ -8760,6 +9355,41 @@ var createRAGClient = (options) => {
|
|
|
8760
9355
|
}
|
|
8761
9356
|
return parseJson(response);
|
|
8762
9357
|
},
|
|
9358
|
+
async syncSources() {
|
|
9359
|
+
const response = await fetchImpl(`${basePath}/sync`);
|
|
9360
|
+
if (!response.ok) {
|
|
9361
|
+
throw new Error(await toErrorMessage3(response));
|
|
9362
|
+
}
|
|
9363
|
+
return parseJson(response);
|
|
9364
|
+
},
|
|
9365
|
+
async syncAllSources(options2) {
|
|
9366
|
+
const response = await fetchImpl(`${basePath}/sync`, {
|
|
9367
|
+
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
9368
|
+
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
9369
|
+
method: "POST"
|
|
9370
|
+
});
|
|
9371
|
+
if (!response.ok) {
|
|
9372
|
+
return {
|
|
9373
|
+
error: await toErrorMessage3(response),
|
|
9374
|
+
ok: false
|
|
9375
|
+
};
|
|
9376
|
+
}
|
|
9377
|
+
return parseJson(response);
|
|
9378
|
+
},
|
|
9379
|
+
async syncSource(id, options2) {
|
|
9380
|
+
const response = await fetchImpl(`${basePath}/sync/${encodeURIComponent(id)}`, {
|
|
9381
|
+
body: options2?.background === true ? JSON.stringify({ background: true }) : undefined,
|
|
9382
|
+
headers: options2?.background === true ? jsonHeaders : undefined,
|
|
9383
|
+
method: "POST"
|
|
9384
|
+
});
|
|
9385
|
+
if (!response.ok) {
|
|
9386
|
+
return {
|
|
9387
|
+
error: await toErrorMessage3(response),
|
|
9388
|
+
ok: false
|
|
9389
|
+
};
|
|
9390
|
+
}
|
|
9391
|
+
return parseJson(response);
|
|
9392
|
+
},
|
|
8763
9393
|
async reindexDocument(id) {
|
|
8764
9394
|
const response = await fetchImpl(`${basePath}/reindex/documents/${encodeURIComponent(id)}`, {
|
|
8765
9395
|
method: "POST"
|
|
@@ -8902,7 +9532,10 @@ export {
|
|
|
8902
9532
|
createTextFileExtractor,
|
|
8903
9533
|
createSQLiteRAGStore,
|
|
8904
9534
|
createRAGVector,
|
|
9535
|
+
createRAGUrlSyncSource,
|
|
8905
9536
|
createAIStream as createRAGTransport,
|
|
9537
|
+
createRAGSyncScheduler,
|
|
9538
|
+
createRAGSyncManager,
|
|
8906
9539
|
createRAGReranker,
|
|
8907
9540
|
createRAGQueryTransform,
|
|
8908
9541
|
createRAGPDFOCRExtractor,
|
|
@@ -8912,9 +9545,11 @@ export {
|
|
|
8912
9545
|
createRAGImageOCRExtractor,
|
|
8913
9546
|
createRAGHTMXWorkflowRenderConfig,
|
|
8914
9547
|
createRAGHTMXConfig,
|
|
9548
|
+
createRAGFileSyncStateStore,
|
|
8915
9549
|
createRAGFileExtractor,
|
|
8916
9550
|
createRAGEvaluationSuite,
|
|
8917
9551
|
createRAGEmbeddingProvider,
|
|
9552
|
+
createRAGDirectorySyncSource,
|
|
8918
9553
|
createRAGCollection,
|
|
8919
9554
|
createRAGClient,
|
|
8920
9555
|
createRAGArchiveFileExtractor,
|
|
@@ -8955,5 +9590,5 @@ export {
|
|
|
8955
9590
|
aiChat
|
|
8956
9591
|
};
|
|
8957
9592
|
|
|
8958
|
-
//# debugId=
|
|
9593
|
+
//# debugId=61173B84573291CC64756E2164756E21
|
|
8959
9594
|
//# sourceMappingURL=index.js.map
|