@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/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
- if (normalizedQuery.length === 0 || normalizedText.length === 0) {
2185
- return 0;
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 scoreHeuristicMatch = (queryTokens, result) => {
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 normalizedQuery = queryTokens.join(" ");
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(queryTokens, result)
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
- adminJobs.unshift(job);
4983
- if (adminJobs.length > MAX_ADMIN_JOBS) {
4984
- adminJobs.length = MAX_ADMIN_JOBS;
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=7CB5678D47F7B89564756E2164756E21
9324
+ //# debugId=59C623D542A7B40F64756E2164756E21
8904
9325
  //# sourceMappingURL=index.js.map