@absolutejs/absolute 0.19.0-beta.615 → 0.19.0-beta.616
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 +60 -43
- package/dist/ai/client/index.js.map +7 -7
- package/dist/ai/client/ui.js +5 -1
- package/dist/ai/client/ui.js.map +3 -3
- package/dist/ai/index.js +1101 -196
- package/dist/ai/index.js.map +14 -12
- package/dist/ai/rag/quality.js +16 -3
- package/dist/ai/rag/quality.js.map +4 -4
- package/dist/ai/rag/ui.js +5 -1
- package/dist/ai/rag/ui.js.map +3 -3
- package/dist/ai-client/angular/ai/index.js +44 -40
- package/dist/ai-client/react/ai/index.js +46 -42
- package/dist/ai-client/vue/ai/index.js +44 -40
- package/dist/angular/ai/index.js +46 -42
- package/dist/angular/ai/index.js.map +6 -6
- package/dist/react/ai/index.js +64 -47
- package/dist/react/ai/index.js.map +9 -9
- package/dist/src/ai/client/actions.d.ts +1 -1
- package/dist/src/ai/index.d.ts +2 -2
- package/dist/src/ai/protocol.d.ts +1 -1
- package/dist/src/ai/rag/accessControl.d.ts +2 -0
- package/dist/src/ai/rag/chat.d.ts +21 -23
- package/dist/src/ai/rag/index.d.ts +4 -2
- package/dist/src/ai/rag/ingestion.d.ts +12 -3
- package/dist/src/ai/rag/jobState.d.ts +2 -0
- package/dist/src/vue/ai/useRAG.d.ts +26 -0
- package/dist/src/vue/ai/useRAGChunkPreview.d.ts +4 -0
- package/dist/src/vue/ai/useRAGDocuments.d.ts +4 -0
- package/dist/src/vue/ai/useRAGEvaluate.d.ts +14 -0
- package/dist/src/vue/ai/useRAGIndexAdmin.d.ts +2 -0
- package/dist/src/vue/ai/useRAGSearch.d.ts +2 -0
- package/dist/svelte/ai/index.js +60 -43
- package/dist/svelte/ai/index.js.map +7 -7
- package/dist/types/ai.d.ts +147 -0
- package/dist/vue/ai/index.js +60 -43
- package/dist/vue/ai/index.js.map +7 -7
- package/package.json +7 -7
package/dist/ai/index.js
CHANGED
|
@@ -187,7 +187,7 @@ var parseAIMessage = (raw) => {
|
|
|
187
187
|
return null;
|
|
188
188
|
}
|
|
189
189
|
};
|
|
190
|
-
var serializeAIMessage = (
|
|
190
|
+
var serializeAIMessage = (message) => JSON.stringify(message);
|
|
191
191
|
|
|
192
192
|
// src/ai/rag/grounding.ts
|
|
193
193
|
var getContextString = (value) => typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
@@ -1275,7 +1275,10 @@ var evaluateRAGCollectionCases = async ({
|
|
|
1275
1275
|
const expectedIds = normalizeExpectedIds(mode === "chunkId" ? caseInput.expectedChunkIds ?? [] : mode === "source" ? caseInput.expectedSources ?? [] : caseInput.expectedDocumentIds ?? []);
|
|
1276
1276
|
const topK = typeof caseInput.topK === "number" ? caseInput.topK : typeof input.topK === "number" ? input.topK : defaultTopK;
|
|
1277
1277
|
const searchInput = {
|
|
1278
|
-
filter:
|
|
1278
|
+
filter: caseInput.corpusKey ? {
|
|
1279
|
+
...(typeof caseInput.filter === "object" ? caseInput.filter : input.filter) ?? {},
|
|
1280
|
+
corpusKey: caseInput.corpusKey
|
|
1281
|
+
} : typeof caseInput.filter === "object" ? caseInput.filter : input.filter,
|
|
1279
1282
|
model: caseInput.model ?? input.model,
|
|
1280
1283
|
query,
|
|
1281
1284
|
rerank,
|
|
@@ -1677,6 +1680,7 @@ var buildEvaluationCaseTraceSnapshot = ({
|
|
|
1677
1680
|
return {
|
|
1678
1681
|
candidateTopK: currentTrace?.candidateTopK ?? 0,
|
|
1679
1682
|
caseId: caseResult.caseId,
|
|
1683
|
+
corpusKey: caseResult.corpusKey,
|
|
1680
1684
|
inputFilter: filter,
|
|
1681
1685
|
finalCount: currentTrace?.resultCounts.final ?? 0,
|
|
1682
1686
|
label: caseResult.label,
|
|
@@ -3229,11 +3233,15 @@ var persistRAGRetrievalReleaseLaneEscalationPolicyHistory = async ({
|
|
|
3229
3233
|
};
|
|
3230
3234
|
var buildRAGEvaluationResponse = (cases) => {
|
|
3231
3235
|
const totalCases = cases.length;
|
|
3236
|
+
const corpusKeys = [
|
|
3237
|
+
...new Set(cases.flatMap((entry) => entry.corpusKey ?? []))
|
|
3238
|
+
];
|
|
3232
3239
|
const passedCases = cases.filter((entry) => entry.status === "pass").length;
|
|
3233
3240
|
const partialCases = cases.filter((entry) => entry.status === "partial").length;
|
|
3234
3241
|
const failedCases = cases.filter((entry) => entry.status === "fail").length;
|
|
3235
3242
|
return {
|
|
3236
3243
|
cases,
|
|
3244
|
+
...corpusKeys.length > 0 ? { corpusKeys } : {},
|
|
3237
3245
|
elapsedMs: cases.reduce((sum, result) => sum + result.elapsedMs, 0),
|
|
3238
3246
|
ok: true,
|
|
3239
3247
|
passingRate: totalCases > 0 ? passedCases / totalCases * 100 : 0,
|
|
@@ -3459,6 +3467,9 @@ var compareRAGRetrievalStrategies = async ({
|
|
|
3459
3467
|
traceSummary: entry.traceSummary
|
|
3460
3468
|
})));
|
|
3461
3469
|
return {
|
|
3470
|
+
corpusKeys: [
|
|
3471
|
+
...new Set(entries.flatMap((entry) => entry.response.corpusKeys ?? []))
|
|
3472
|
+
],
|
|
3462
3473
|
entries,
|
|
3463
3474
|
leaderboard,
|
|
3464
3475
|
summary: summarizeRAGRetrievalComparison(entries),
|
|
@@ -3491,6 +3502,7 @@ var compareRAGRetrievalTraceSummaries = (current, previous) => ({
|
|
|
3491
3502
|
});
|
|
3492
3503
|
var buildSearchTraceResultSnapshots = (results) => results.map((result) => ({
|
|
3493
3504
|
chunkId: result.chunkId,
|
|
3505
|
+
corpusKey: result.corpusKey ?? (typeof result.metadata?.corpusKey === "string" ? result.metadata.corpusKey : undefined),
|
|
3494
3506
|
documentId: typeof result.metadata?.documentId === "string" ? result.metadata.documentId : undefined,
|
|
3495
3507
|
score: result.score,
|
|
3496
3508
|
source: result.source,
|
|
@@ -3690,6 +3702,7 @@ var summarizeRAGEvaluationCase = ({
|
|
|
3690
3702
|
const status = expectedCount === 0 ? "partial" : matchedCount === expectedCount ? "pass" : matchedCount > 0 ? "partial" : "fail";
|
|
3691
3703
|
return {
|
|
3692
3704
|
caseId: caseInput.id ?? `case-${caseIndex + 1}`,
|
|
3705
|
+
corpusKey: caseInput.corpusKey,
|
|
3693
3706
|
elapsedMs,
|
|
3694
3707
|
expectedCount,
|
|
3695
3708
|
expectedIds,
|
|
@@ -4289,10 +4302,14 @@ var buildProvenanceLabel2 = (metadata) => {
|
|
|
4289
4302
|
const transcriptSource = getContextString2(metadata.transcriptSource);
|
|
4290
4303
|
const pdfTextMode = getContextString2(metadata.pdfTextMode);
|
|
4291
4304
|
const ocrEngine = getContextString2(metadata.ocrEngine);
|
|
4305
|
+
const extractorRegistryMatch = getContextString2(metadata.extractorRegistryMatch);
|
|
4306
|
+
const chunkingProfile = getContextString2(metadata.chunkingProfile);
|
|
4292
4307
|
const ocrConfidence = getContextNumber2(metadata.ocrRegionConfidence) ?? getContextNumber2(metadata.ocrConfidence);
|
|
4293
4308
|
const labels = [
|
|
4294
4309
|
pdfTextMode ? `PDF ${pdfTextMode}` : "",
|
|
4295
4310
|
ocrEngine ? `OCR ${ocrEngine}` : "",
|
|
4311
|
+
extractorRegistryMatch ? `Extractor ${extractorRegistryMatch}` : "",
|
|
4312
|
+
chunkingProfile ? `Chunking ${chunkingProfile}` : "",
|
|
4296
4313
|
typeof ocrConfidence === "number" ? `Confidence ${ocrConfidence.toFixed(2)}` : "",
|
|
4297
4314
|
mediaKind ? `Media ${mediaKind}` : "",
|
|
4298
4315
|
transcriptSource ? `Transcript ${transcriptSource}` : "",
|
|
@@ -6741,12 +6758,12 @@ var checkBackpressure = async (socket) => {
|
|
|
6741
6758
|
await delay(BACKPRESSURE_DELAY);
|
|
6742
6759
|
}
|
|
6743
6760
|
};
|
|
6744
|
-
var sendMessage = async (socket,
|
|
6761
|
+
var sendMessage = async (socket, message) => {
|
|
6745
6762
|
if (socket.readyState !== WS_OPEN) {
|
|
6746
6763
|
return false;
|
|
6747
6764
|
}
|
|
6748
6765
|
await checkBackpressure(socket);
|
|
6749
|
-
socket.send(serializeAIMessage(
|
|
6766
|
+
socket.send(serializeAIMessage(message));
|
|
6750
6767
|
return true;
|
|
6751
6768
|
};
|
|
6752
6769
|
var buildToolDefinitions = (tools) => Object.entries(tools).map(([name, def]) => ({
|
|
@@ -9689,6 +9706,7 @@ var createEmailExtractor = () => ({
|
|
|
9689
9706
|
chunking: input.chunking,
|
|
9690
9707
|
contentType: attachment.contentType,
|
|
9691
9708
|
data: attachment.data,
|
|
9709
|
+
extractorRegistry: input.extractorRegistry,
|
|
9692
9710
|
format: inferFormatFromContentType(attachment.contentType ?? null) ?? inferFormatFromName(attachment.fileName),
|
|
9693
9711
|
metadata: {
|
|
9694
9712
|
...messageMetadata,
|
|
@@ -9844,6 +9862,8 @@ ${slide.text}`),
|
|
|
9844
9862
|
});
|
|
9845
9863
|
var createRAGArchiveExpander = (expander) => expander;
|
|
9846
9864
|
var createRAGFileExtractor = (extractor) => extractor;
|
|
9865
|
+
var createRAGFileExtractorRegistry = (registry) => registry;
|
|
9866
|
+
var createRAGChunkingRegistry = (registry) => registry;
|
|
9847
9867
|
var createRAGImageOCRExtractor = (provider) => ({
|
|
9848
9868
|
name: `absolute_image_ocr:${provider.name}`,
|
|
9849
9869
|
supports: imageExtractorSupports,
|
|
@@ -9934,11 +9954,12 @@ var createTextFileExtractor = () => ({
|
|
|
9934
9954
|
title: input.title
|
|
9935
9955
|
})
|
|
9936
9956
|
});
|
|
9937
|
-
var expandArchiveEntry = async (entry, archiveInput, extractors) => {
|
|
9957
|
+
var expandArchiveEntry = async (entry, archiveInput, extractors, registry) => {
|
|
9938
9958
|
const documents = await extractRAGFileDocuments({
|
|
9939
9959
|
chunking: archiveInput.chunking,
|
|
9940
9960
|
contentType: entry.contentType,
|
|
9941
9961
|
data: entry.data,
|
|
9962
|
+
extractorRegistry: archiveInput.extractorRegistry,
|
|
9942
9963
|
format: entry.format,
|
|
9943
9964
|
metadata: {
|
|
9944
9965
|
...archiveInput.metadata ?? {},
|
|
@@ -9952,7 +9973,7 @@ var expandArchiveEntry = async (entry, archiveInput, extractors) => {
|
|
|
9952
9973
|
name: basename(entry.path),
|
|
9953
9974
|
source: archiveInput.source && !archiveInput.source.startsWith("http") ? `${archiveInput.source}#${entry.path}` : entry.path,
|
|
9954
9975
|
title: basename(entry.path)
|
|
9955
|
-
}, extractors);
|
|
9976
|
+
}, extractors, registry);
|
|
9956
9977
|
return documents;
|
|
9957
9978
|
};
|
|
9958
9979
|
var createPDFFileExtractor = () => ({
|
|
@@ -10053,8 +10074,83 @@ var DEFAULT_FILE_EXTRACTORS = [
|
|
|
10053
10074
|
createPDFFileExtractor(),
|
|
10054
10075
|
createTextFileExtractor()
|
|
10055
10076
|
];
|
|
10056
|
-
var
|
|
10057
|
-
|
|
10077
|
+
var resolveExtractorRegistry = (registry) => {
|
|
10078
|
+
if (!registry) {
|
|
10079
|
+
return {
|
|
10080
|
+
defaultOrder: "registry_first",
|
|
10081
|
+
includeDefaults: true,
|
|
10082
|
+
registrations: []
|
|
10083
|
+
};
|
|
10084
|
+
}
|
|
10085
|
+
if (Array.isArray(registry)) {
|
|
10086
|
+
return {
|
|
10087
|
+
defaultOrder: "registry_first",
|
|
10088
|
+
includeDefaults: true,
|
|
10089
|
+
registrations: registry
|
|
10090
|
+
};
|
|
10091
|
+
}
|
|
10092
|
+
return {
|
|
10093
|
+
defaultOrder: registry.defaultOrder ?? "registry_first",
|
|
10094
|
+
includeDefaults: registry.includeDefaults ?? true,
|
|
10095
|
+
registrations: registry.registrations
|
|
10096
|
+
};
|
|
10097
|
+
};
|
|
10098
|
+
var createExtractorRegistryInput = (input) => ({
|
|
10099
|
+
...input,
|
|
10100
|
+
inferredContentType: input.contentType ?? null,
|
|
10101
|
+
inferredExtension: inferExtensionFromInput(input) || null,
|
|
10102
|
+
inferredFormat: input.format ?? inferFormatFromContentType(input.contentType ?? null) ?? inferFormatFromName(input.path ?? input.source ?? input.name ?? input.title)
|
|
10103
|
+
});
|
|
10104
|
+
var registrationMatches = async (registration, input) => {
|
|
10105
|
+
const normalizedContentType = input.inferredContentType?.toLowerCase();
|
|
10106
|
+
const normalizedExtension = input.inferredExtension?.toLowerCase();
|
|
10107
|
+
const normalizedName = (input.path ?? input.source ?? input.name ?? input.title ?? "").toLowerCase();
|
|
10108
|
+
if (registration.contentTypes?.length && !registration.contentTypes.some((entry) => normalizedContentType === entry.toLowerCase())) {
|
|
10109
|
+
return false;
|
|
10110
|
+
}
|
|
10111
|
+
if (registration.extensions?.length && !registration.extensions.some((entry) => normalizedExtension === entry.toLowerCase())) {
|
|
10112
|
+
return false;
|
|
10113
|
+
}
|
|
10114
|
+
if (registration.formats?.length && (!input.inferredFormat || !registration.formats.includes(input.inferredFormat))) {
|
|
10115
|
+
return false;
|
|
10116
|
+
}
|
|
10117
|
+
if (registration.names?.length && !registration.names.some((entry) => normalizedName.includes(entry.toLowerCase()))) {
|
|
10118
|
+
return false;
|
|
10119
|
+
}
|
|
10120
|
+
if (registration.match) {
|
|
10121
|
+
return registration.match(input);
|
|
10122
|
+
}
|
|
10123
|
+
return true;
|
|
10124
|
+
};
|
|
10125
|
+
var dedupeResolvedExtractors = (extractors) => {
|
|
10126
|
+
const seen = new Set;
|
|
10127
|
+
const ordered = [];
|
|
10128
|
+
for (const entry of extractors) {
|
|
10129
|
+
if (seen.has(entry.extractor.name)) {
|
|
10130
|
+
continue;
|
|
10131
|
+
}
|
|
10132
|
+
seen.add(entry.extractor.name);
|
|
10133
|
+
ordered.push(entry);
|
|
10134
|
+
}
|
|
10135
|
+
return ordered;
|
|
10136
|
+
};
|
|
10137
|
+
var resolveFileExtractors = async (input, extractors, registry) => {
|
|
10138
|
+
const explicit = extractors ?? [];
|
|
10139
|
+
const resolvedRegistry = resolveExtractorRegistry(registry);
|
|
10140
|
+
const registryInput = createExtractorRegistryInput(input);
|
|
10141
|
+
const matchedRegistrations = (await Promise.all(resolvedRegistry.registrations.map(async (registration) => ({
|
|
10142
|
+
matches: await registrationMatches(registration, registryInput),
|
|
10143
|
+
priority: registration.priority ?? 0,
|
|
10144
|
+
registration
|
|
10145
|
+
})))).filter((entry) => entry.matches).sort((left, right) => right.priority - left.priority).map((entry) => ({
|
|
10146
|
+
extractor: entry.registration.extractor,
|
|
10147
|
+
registryMatchName: entry.registration.name ?? entry.registration.extractor.name
|
|
10148
|
+
}));
|
|
10149
|
+
const defaults = resolvedRegistry.includeDefaults ? DEFAULT_FILE_EXTRACTORS.map((extractor) => ({ extractor })) : [];
|
|
10150
|
+
const explicitResolved = explicit.map((extractor) => ({ extractor }));
|
|
10151
|
+
return dedupeResolvedExtractors(resolvedRegistry.defaultOrder === "defaults_first" ? [...explicitResolved, ...defaults, ...matchedRegistrations] : [...explicitResolved, ...matchedRegistrations, ...defaults]);
|
|
10152
|
+
};
|
|
10153
|
+
var applyExtractorDefaults = (document, input, extractorName, registryMatchName) => ({
|
|
10058
10154
|
chunking: document.chunking ?? input.chunking,
|
|
10059
10155
|
format: document.format ?? input.format ?? inferFormatFromContentType(document.contentType ?? input.contentType ?? null) ?? inferFormatFromName(document.source ?? input.source ?? input.path ?? input.name),
|
|
10060
10156
|
id: document.id,
|
|
@@ -10062,20 +10158,22 @@ var applyExtractorDefaults = (document, input, extractorName) => ({
|
|
|
10062
10158
|
...input.metadata ?? {},
|
|
10063
10159
|
...document.metadata ?? {},
|
|
10064
10160
|
contentType: document.contentType ?? input.contentType,
|
|
10065
|
-
extractor: document.extractor ?? extractorName
|
|
10161
|
+
extractor: document.extractor ?? extractorName,
|
|
10162
|
+
...registryMatchName ? { extractorRegistryMatch: registryMatchName } : {}
|
|
10066
10163
|
},
|
|
10067
10164
|
source: document.source ?? input.source ?? input.path ?? input.name,
|
|
10068
10165
|
text: document.text,
|
|
10069
10166
|
title: document.title ?? input.title
|
|
10070
10167
|
});
|
|
10071
|
-
var extractRAGFileDocuments = async (input, extractors) => {
|
|
10072
|
-
for (const
|
|
10168
|
+
var extractRAGFileDocuments = async (input, extractors, registry) => {
|
|
10169
|
+
for (const resolvedExtractor of await resolveFileExtractors(input, extractors, registry)) {
|
|
10170
|
+
const { extractor, registryMatchName } = resolvedExtractor;
|
|
10073
10171
|
if (!await extractor.supports(input)) {
|
|
10074
10172
|
continue;
|
|
10075
10173
|
}
|
|
10076
10174
|
const extracted = await extractor.extract(input);
|
|
10077
10175
|
const documents = Array.isArray(extracted) ? extracted : [extracted];
|
|
10078
|
-
return documents.map((document) => applyExtractorDefaults(document, input, extractor.name));
|
|
10176
|
+
return documents.map((document) => applyExtractorDefaults(document, input, extractor.name, registryMatchName));
|
|
10079
10177
|
}
|
|
10080
10178
|
throw new Error(`No RAG file extractor matched ${inferNameFromInput(input)}. Register a custom extractor for this file type.`);
|
|
10081
10179
|
};
|
|
@@ -10086,7 +10184,7 @@ var getFirstExtractedDocument = (documents, label) => {
|
|
|
10086
10184
|
}
|
|
10087
10185
|
return document;
|
|
10088
10186
|
};
|
|
10089
|
-
var loadExtractedDocuments = async (input, extractors) => extractRAGFileDocuments(input, extractors);
|
|
10187
|
+
var loadExtractedDocuments = async (input, extractors, registry) => extractRAGFileDocuments(input, extractors, registry);
|
|
10090
10188
|
var sentenceUnits = (text) => {
|
|
10091
10189
|
const matches = text.match(/[^.!?\n]+(?:[.!?]+|$)/g);
|
|
10092
10190
|
if (!matches) {
|
|
@@ -10283,11 +10381,92 @@ var resolveChunkingUnits = (text, options) => {
|
|
|
10283
10381
|
}
|
|
10284
10382
|
return paragraphUnits(text);
|
|
10285
10383
|
};
|
|
10286
|
-
var
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
const
|
|
10384
|
+
var resolveChunkingProfiles = (registry) => {
|
|
10385
|
+
if (!registry) {
|
|
10386
|
+
return [];
|
|
10387
|
+
}
|
|
10388
|
+
const profiles = Array.isArray(registry) ? registry : registry.profiles;
|
|
10389
|
+
return profiles.map((profile, index) => normalizeChunkingProfile(profile, index)).sort((left, right) => right.priority - left.priority).map(({ profile }) => profile);
|
|
10390
|
+
};
|
|
10391
|
+
var normalizeChunkingProfile = (profile, index) => {
|
|
10392
|
+
if ("resolve" in profile) {
|
|
10393
|
+
return {
|
|
10394
|
+
priority: 0,
|
|
10395
|
+
profile
|
|
10396
|
+
};
|
|
10397
|
+
}
|
|
10398
|
+
const options = normalizeChunkingProfileOptions(profile.profile);
|
|
10399
|
+
const sourceSet = profile.sources?.filter((value) => typeof value === "string") ?? [];
|
|
10400
|
+
const documentIdSet = profile.documentIds?.filter((value) => typeof value === "string") ?? [];
|
|
10401
|
+
const formatSet = profile.formats?.filter((value) => typeof value === "string") ?? [];
|
|
10402
|
+
const sourceNativeKindSet = profile.sourceNativeKinds?.filter((value) => typeof value === "string") ?? [];
|
|
10403
|
+
return {
|
|
10404
|
+
priority: profile.priority ?? 0,
|
|
10405
|
+
profile: {
|
|
10406
|
+
name: profile.name ?? `chunking_profile_${String(index + 1).padStart(2, "0")}`,
|
|
10407
|
+
resolve: (input) => {
|
|
10408
|
+
const documentId = input.document.id?.trim() || (typeof input.metadata.documentId === "string" ? input.metadata.documentId : undefined);
|
|
10409
|
+
const source = input.document.source?.trim();
|
|
10410
|
+
if (formatSet.length > 0 && !formatSet.includes(input.format)) {
|
|
10411
|
+
return;
|
|
10412
|
+
}
|
|
10413
|
+
if (sourceNativeKindSet.length > 0 && (!input.sourceNativeKind || !sourceNativeKindSet.includes(input.sourceNativeKind))) {
|
|
10414
|
+
return;
|
|
10415
|
+
}
|
|
10416
|
+
if (sourceSet.length > 0 && (!source || !sourceSet.includes(source))) {
|
|
10417
|
+
return;
|
|
10418
|
+
}
|
|
10419
|
+
if (documentIdSet.length > 0 && (!documentId || !documentIdSet.includes(documentId))) {
|
|
10420
|
+
return;
|
|
10421
|
+
}
|
|
10422
|
+
return options;
|
|
10423
|
+
}
|
|
10424
|
+
}
|
|
10425
|
+
};
|
|
10426
|
+
};
|
|
10427
|
+
var normalizeChunkingProfileOptions = (profile) => isChunkingProfileOptionsWrapper(profile) ? profile.options ?? {} : profile;
|
|
10428
|
+
var isChunkingProfileOptionsWrapper = (profile) => Object.prototype.hasOwnProperty.call(profile, "options");
|
|
10429
|
+
var resolveChunkingProfileOverrides = ({
|
|
10430
|
+
defaults,
|
|
10431
|
+
document,
|
|
10432
|
+
format,
|
|
10433
|
+
normalizedText,
|
|
10434
|
+
registry
|
|
10435
|
+
}) => {
|
|
10436
|
+
const metadata = document.metadata ?? {};
|
|
10437
|
+
const sourceNativeKind = typeof metadata.sourceNativeKind === "string" ? metadata.sourceNativeKind : undefined;
|
|
10438
|
+
for (const profile of resolveChunkingProfiles(registry)) {
|
|
10439
|
+
const options = profile.resolve({
|
|
10440
|
+
defaults,
|
|
10441
|
+
document,
|
|
10442
|
+
format,
|
|
10443
|
+
metadata,
|
|
10444
|
+
normalizedText,
|
|
10445
|
+
sourceNativeKind
|
|
10446
|
+
});
|
|
10447
|
+
if (options) {
|
|
10448
|
+
return {
|
|
10449
|
+
name: profile.name,
|
|
10450
|
+
options
|
|
10451
|
+
};
|
|
10452
|
+
}
|
|
10453
|
+
}
|
|
10454
|
+
return;
|
|
10455
|
+
};
|
|
10456
|
+
var resolveChunkingOptions = (document, defaults, registry, format, normalizedText) => {
|
|
10457
|
+
const resolvedFormat = format ?? inferFormat(document);
|
|
10458
|
+
const resolvedNormalizedText = normalizedText ?? normalizeDocumentText(document.text, resolvedFormat);
|
|
10459
|
+
const profileOverrides = resolveChunkingProfileOverrides({
|
|
10460
|
+
defaults,
|
|
10461
|
+
document,
|
|
10462
|
+
format: resolvedFormat,
|
|
10463
|
+
normalizedText: resolvedNormalizedText,
|
|
10464
|
+
registry
|
|
10465
|
+
});
|
|
10466
|
+
const maxChunkLength = document.chunking?.maxChunkLength ?? profileOverrides?.options.maxChunkLength ?? defaults?.maxChunkLength ?? DEFAULT_MAX_CHUNK_LENGTH;
|
|
10467
|
+
const chunkOverlap = document.chunking?.chunkOverlap ?? profileOverrides?.options.chunkOverlap ?? defaults?.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;
|
|
10468
|
+
const minChunkLength = document.chunking?.minChunkLength ?? profileOverrides?.options.minChunkLength ?? defaults?.minChunkLength ?? DEFAULT_MIN_CHUNK_LENGTH;
|
|
10469
|
+
const strategy = document.chunking?.strategy ?? profileOverrides?.options.strategy ?? defaults?.strategy ?? DEFAULT_STRATEGY;
|
|
10291
10470
|
return {
|
|
10292
10471
|
chunkOverlap: Math.max(0, Math.min(chunkOverlap, maxChunkLength - 1)),
|
|
10293
10472
|
maxChunkLength: Math.max(RAG_MIN_CHUNK_LENGTH_FLOOR, maxChunkLength),
|
|
@@ -10305,10 +10484,17 @@ var createChunkEntries = (document, format, text, options) => {
|
|
|
10305
10484
|
const units = resolveChunkingUnits(text, options);
|
|
10306
10485
|
return chunkFromUnits(units, options.maxChunkLength, options.chunkOverlap, options.minChunkLength).map((entry) => ({ text: entry }));
|
|
10307
10486
|
};
|
|
10308
|
-
var prepareRAGDocument = (document, defaultChunking) => {
|
|
10487
|
+
var prepareRAGDocument = (document, defaultChunking, chunkingRegistry) => {
|
|
10309
10488
|
const format = inferFormat(document);
|
|
10310
10489
|
const normalizedText = normalizeDocumentText(document.text, format);
|
|
10311
|
-
const
|
|
10490
|
+
const chunkingProfileOverrides = resolveChunkingProfileOverrides({
|
|
10491
|
+
defaults: defaultChunking,
|
|
10492
|
+
document,
|
|
10493
|
+
format,
|
|
10494
|
+
normalizedText,
|
|
10495
|
+
registry: chunkingRegistry
|
|
10496
|
+
});
|
|
10497
|
+
const chunking = resolveChunkingOptions(document, defaultChunking, chunkingRegistry, format, normalizedText);
|
|
10312
10498
|
const documentId = document.id?.trim() || slugify(document.source || document.title || normalizedText.slice(0, RAG_DOCUMENT_ID_PREVIEW_LENGTH));
|
|
10313
10499
|
const title = document.title?.trim() || documentId;
|
|
10314
10500
|
let sourceExtension = "txt";
|
|
@@ -10318,9 +10504,12 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10318
10504
|
sourceExtension = "html";
|
|
10319
10505
|
}
|
|
10320
10506
|
const source = document.source?.trim() || `${documentId}.${sourceExtension}`;
|
|
10507
|
+
const corpusKey = document.corpusKey?.trim() || (typeof document.metadata?.corpusKey === "string" ? document.metadata.corpusKey.trim() : undefined) || undefined;
|
|
10321
10508
|
const metadata = {
|
|
10322
10509
|
...document.metadata ?? {},
|
|
10510
|
+
...corpusKey ? { corpusKey } : {},
|
|
10323
10511
|
documentId,
|
|
10512
|
+
...chunkingProfileOverrides?.name ? { chunkingProfile: chunkingProfileOverrides.name } : {},
|
|
10324
10513
|
format,
|
|
10325
10514
|
source,
|
|
10326
10515
|
title
|
|
@@ -10344,6 +10533,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10344
10533
|
const nextChunkId = index + 1 < chunkEntries.length ? `${documentId}:${String(index + 2).padStart(RAG_CHUNK_ID_PAD_LENGTH, "0")}` : undefined;
|
|
10345
10534
|
return {
|
|
10346
10535
|
chunkId: `${documentId}:${String(index + 1).padStart(RAG_CHUNK_ID_PAD_LENGTH, "0")}`,
|
|
10536
|
+
...corpusKey ? { corpusKey } : {},
|
|
10347
10537
|
metadata: {
|
|
10348
10538
|
...metadata,
|
|
10349
10539
|
chunkCount: chunkEntries.length,
|
|
@@ -10366,6 +10556,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10366
10556
|
};
|
|
10367
10557
|
});
|
|
10368
10558
|
return {
|
|
10559
|
+
...corpusKey ? { corpusKey } : {},
|
|
10369
10560
|
chunks,
|
|
10370
10561
|
documentId,
|
|
10371
10562
|
format,
|
|
@@ -10375,7 +10566,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10375
10566
|
title
|
|
10376
10567
|
};
|
|
10377
10568
|
};
|
|
10378
|
-
var prepareRAGDocuments = (input) => input.documents.map((document) => prepareRAGDocument(document, input.defaultChunking));
|
|
10569
|
+
var prepareRAGDocuments = (input) => input.documents.map((document) => prepareRAGDocument(document, input.defaultChunking, input.chunkingRegistry));
|
|
10379
10570
|
var mergeMetadata = (inputMetadata, extraMetadata, baseMetadata) => ({
|
|
10380
10571
|
...baseMetadata ?? {},
|
|
10381
10572
|
...inputMetadata ?? {},
|
|
@@ -10390,12 +10581,13 @@ var loadRAGDocumentFile = async (input) => {
|
|
|
10390
10581
|
chunking: input.chunking,
|
|
10391
10582
|
contentType: input.contentType,
|
|
10392
10583
|
data,
|
|
10584
|
+
extractorRegistry: input.extractorRegistry,
|
|
10393
10585
|
format: input.format,
|
|
10394
10586
|
metadata: input.metadata,
|
|
10395
10587
|
path: input.path,
|
|
10396
10588
|
source: input.source,
|
|
10397
10589
|
title: input.title
|
|
10398
|
-
}, input.extractors);
|
|
10590
|
+
}, input.extractors, input.extractorRegistry);
|
|
10399
10591
|
return getFirstExtractedDocument(documents, "for file input");
|
|
10400
10592
|
};
|
|
10401
10593
|
var loadRAGDocumentFromURL = async (input) => {
|
|
@@ -10412,12 +10604,13 @@ var loadRAGDocumentFromURL = async (input) => {
|
|
|
10412
10604
|
chunking: input.chunking,
|
|
10413
10605
|
contentType: input.contentType ?? response.headers.get("content-type") ?? undefined,
|
|
10414
10606
|
data,
|
|
10607
|
+
extractorRegistry: input.extractorRegistry,
|
|
10415
10608
|
format: input.format ?? inferFormatFromUrl(url),
|
|
10416
10609
|
metadata: input.metadata,
|
|
10417
10610
|
name: basename(new URL(url).pathname),
|
|
10418
10611
|
source: input.source ?? url,
|
|
10419
10612
|
title: input.title
|
|
10420
|
-
}, input.extractors);
|
|
10613
|
+
}, input.extractors, input.extractorRegistry);
|
|
10421
10614
|
return getFirstExtractedDocument(documents, "for URL input");
|
|
10422
10615
|
};
|
|
10423
10616
|
var loadRAGDocumentsFromUploads = async (input) => {
|
|
@@ -10426,12 +10619,13 @@ var loadRAGDocumentsFromUploads = async (input) => {
|
|
|
10426
10619
|
chunking: upload.chunking,
|
|
10427
10620
|
contentType: upload.contentType,
|
|
10428
10621
|
data: decodeUploadContent(upload),
|
|
10622
|
+
extractorRegistry: input.extractorRegistry,
|
|
10429
10623
|
format: upload.format,
|
|
10430
10624
|
metadata: upload.metadata,
|
|
10431
10625
|
name: upload.name,
|
|
10432
10626
|
source: upload.source ?? upload.name,
|
|
10433
10627
|
title: upload.title
|
|
10434
|
-
}, input.extractors);
|
|
10628
|
+
}, input.extractors, input.extractorRegistry);
|
|
10435
10629
|
return loaded.map((document) => ({
|
|
10436
10630
|
...document,
|
|
10437
10631
|
metadata: mergeMetadata(document.metadata, { uploadFile: upload.name }, input.baseMetadata)
|
|
@@ -10439,6 +10633,7 @@ var loadRAGDocumentsFromUploads = async (input) => {
|
|
|
10439
10633
|
}));
|
|
10440
10634
|
return {
|
|
10441
10635
|
defaultChunking: input.defaultChunking,
|
|
10636
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10442
10637
|
documents: documents.flat()
|
|
10443
10638
|
};
|
|
10444
10639
|
};
|
|
@@ -10457,12 +10652,13 @@ var loadRAGDocumentsFromURLs = async (input) => {
|
|
|
10457
10652
|
chunking: urlInput.chunking,
|
|
10458
10653
|
contentType: urlInput.contentType ?? response.headers.get("content-type") ?? undefined,
|
|
10459
10654
|
data,
|
|
10655
|
+
extractorRegistry: urlInput.extractorRegistry ?? input.extractorRegistry,
|
|
10460
10656
|
format: urlInput.format ?? inferFormatFromUrl(url),
|
|
10461
10657
|
metadata: urlInput.metadata,
|
|
10462
10658
|
name: basename(new URL(url).pathname),
|
|
10463
10659
|
source: urlInput.source ?? url,
|
|
10464
10660
|
title: urlInput.title
|
|
10465
|
-
}, urlInput.extractors ?? input.extractors);
|
|
10661
|
+
}, urlInput.extractors ?? input.extractors, urlInput.extractorRegistry ?? input.extractorRegistry);
|
|
10466
10662
|
return loaded.map((document) => ({
|
|
10467
10663
|
...document,
|
|
10468
10664
|
metadata: mergeMetadata(document.metadata, { sourceUrl: urlInput.url }, input.baseMetadata)
|
|
@@ -10470,6 +10666,7 @@ var loadRAGDocumentsFromURLs = async (input) => {
|
|
|
10470
10666
|
}));
|
|
10471
10667
|
return {
|
|
10472
10668
|
defaultChunking: input.defaultChunking,
|
|
10669
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10473
10670
|
documents: documents.flat()
|
|
10474
10671
|
};
|
|
10475
10672
|
};
|
|
@@ -10478,15 +10675,16 @@ var loadRAGDocumentUpload = async (input) => {
|
|
|
10478
10675
|
chunking: input.chunking,
|
|
10479
10676
|
contentType: input.contentType,
|
|
10480
10677
|
data: decodeUploadContent(input),
|
|
10678
|
+
extractorRegistry: input.extractorRegistry,
|
|
10481
10679
|
format: input.format,
|
|
10482
10680
|
metadata: input.metadata,
|
|
10483
10681
|
name: input.name,
|
|
10484
10682
|
source: input.source ?? input.name,
|
|
10485
10683
|
title: input.title
|
|
10486
|
-
}, input.extractors);
|
|
10684
|
+
}, input.extractors, input.extractorRegistry);
|
|
10487
10685
|
return getFirstExtractedDocument(documents, "for upload input");
|
|
10488
10686
|
};
|
|
10489
|
-
var prepareRAGDocumentFile = async (input, defaultChunking) => prepareRAGDocument(await loadRAGDocumentFile(input), defaultChunking);
|
|
10687
|
+
var prepareRAGDocumentFile = async (input, defaultChunking, chunkingRegistry) => prepareRAGDocument(await loadRAGDocumentFile(input), defaultChunking, chunkingRegistry);
|
|
10490
10688
|
var DEFAULT_DIRECTORY_EXTENSIONS = [
|
|
10491
10689
|
".txt",
|
|
10492
10690
|
".md",
|
|
@@ -10546,7 +10744,7 @@ var buildRAGUpsertInputFromUploads = async (input) => ({
|
|
|
10546
10744
|
});
|
|
10547
10745
|
var loadRAGDocumentsFromDirectory = async (input) => {
|
|
10548
10746
|
const root = resolve(input.directory);
|
|
10549
|
-
const includeExtensions = input.includeExtensions === undefined && input.extractors?.length ? null : new Set((input.includeExtensions ?? DEFAULT_DIRECTORY_EXTENSIONS).map((entry) => entry.startsWith(".") ? entry.toLowerCase() : `.${entry.toLowerCase()}`));
|
|
10747
|
+
const includeExtensions = input.includeExtensions === undefined && (input.extractors?.length || input.extractorRegistry) ? null : new Set((input.includeExtensions ?? DEFAULT_DIRECTORY_EXTENSIONS).map((entry) => entry.startsWith(".") ? entry.toLowerCase() : `.${entry.toLowerCase()}`));
|
|
10550
10748
|
const files = await collectDirectoryFiles(root, input.recursive !== false, includeExtensions);
|
|
10551
10749
|
const documents = await Promise.all(files.map(async (path) => {
|
|
10552
10750
|
const source = relative(root, path).replace(/\\/g, "/");
|
|
@@ -10554,13 +10752,14 @@ var loadRAGDocumentsFromDirectory = async (input) => {
|
|
|
10554
10752
|
const loaded = await loadExtractedDocuments({
|
|
10555
10753
|
chunking: input.defaultChunking,
|
|
10556
10754
|
data,
|
|
10755
|
+
extractorRegistry: input.extractorRegistry,
|
|
10557
10756
|
metadata: {
|
|
10558
10757
|
fileName: basename(path),
|
|
10559
10758
|
relativePath: source
|
|
10560
10759
|
},
|
|
10561
10760
|
path,
|
|
10562
10761
|
source
|
|
10563
|
-
}, input.extractors);
|
|
10762
|
+
}, input.extractors, input.extractorRegistry);
|
|
10564
10763
|
return loaded.map((document) => ({
|
|
10565
10764
|
...document,
|
|
10566
10765
|
metadata: mergeMetadata(document.metadata, undefined, input.baseMetadata)
|
|
@@ -10568,6 +10767,7 @@ var loadRAGDocumentsFromDirectory = async (input) => {
|
|
|
10568
10767
|
}));
|
|
10569
10768
|
return {
|
|
10570
10769
|
defaultChunking: input.defaultChunking,
|
|
10770
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10571
10771
|
documents: documents.flat()
|
|
10572
10772
|
};
|
|
10573
10773
|
};
|
|
@@ -11782,6 +11982,7 @@ var isRAGDocumentUrlArray = (value) => Array.isArray(value) && value.every((entr
|
|
|
11782
11982
|
var isRAGDocumentChunkArray = (value) => Array.isArray(value) && value.every((entry) => isRAGDocumentChunk(entry));
|
|
11783
11983
|
var buildSources2 = (results) => results.map((result) => ({
|
|
11784
11984
|
chunkId: result.chunkId,
|
|
11985
|
+
corpusKey: result.corpusKey ?? (typeof result.metadata?.corpusKey === "string" ? result.metadata.corpusKey : undefined),
|
|
11785
11986
|
labels: buildRAGSourceLabels({
|
|
11786
11987
|
metadata: result.metadata,
|
|
11787
11988
|
source: result.source,
|
|
@@ -11932,6 +12133,8 @@ var buildRAGContextFromQuery = async (config, topK, scoreThreshold, queryText, r
|
|
|
11932
12133
|
};
|
|
11933
12134
|
var ragChat = (config) => {
|
|
11934
12135
|
const path = config.path ?? DEFAULT_PATH2;
|
|
12136
|
+
const authorizeRAGAction = config.authorizeRAGAction;
|
|
12137
|
+
const resolveRAGAccessScope = config.resolveRAGAccessScope;
|
|
11935
12138
|
const topK = config.topK ?? DEFAULT_TOP_K3;
|
|
11936
12139
|
const { scoreThreshold } = config;
|
|
11937
12140
|
const { extractors } = config;
|
|
@@ -11946,6 +12149,13 @@ var ragChat = (config) => {
|
|
|
11946
12149
|
const adminActions = [];
|
|
11947
12150
|
const adminJobs = [];
|
|
11948
12151
|
const syncJobs = [];
|
|
12152
|
+
const { jobStateStore } = config;
|
|
12153
|
+
const jobHistoryRetention = {
|
|
12154
|
+
maxAdminActions: config.jobHistoryRetention?.maxAdminActions ?? MAX_ADMIN_ACTIONS,
|
|
12155
|
+
maxAdminJobs: config.jobHistoryRetention?.maxAdminJobs ?? MAX_ADMIN_JOBS,
|
|
12156
|
+
maxIngestJobs: config.jobHistoryRetention?.maxIngestJobs ?? MAX_INGEST_JOBS,
|
|
12157
|
+
maxSyncJobs: config.jobHistoryRetention?.maxSyncJobs ?? MAX_ADMIN_JOBS
|
|
12158
|
+
};
|
|
11949
12159
|
const { searchTraceStore } = config;
|
|
11950
12160
|
const { searchTraceRetention } = config;
|
|
11951
12161
|
const { searchTraceRetentionSchedule } = config;
|
|
@@ -11964,6 +12174,134 @@ var ragChat = (config) => {
|
|
|
11964
12174
|
retention: searchTraceRetention,
|
|
11965
12175
|
schedule: searchTraceRetentionSchedule
|
|
11966
12176
|
};
|
|
12177
|
+
let jobStateLoaded = false;
|
|
12178
|
+
let jobStateLoadPromise;
|
|
12179
|
+
const normalizeAuthorizationDecision = (decision) => typeof decision === "boolean" ? { allowed: decision } : decision ?? { allowed: true };
|
|
12180
|
+
const checkAuthorization = async (request, action, resource) => {
|
|
12181
|
+
if (!authorizeRAGAction) {
|
|
12182
|
+
return { allowed: true };
|
|
12183
|
+
}
|
|
12184
|
+
return normalizeAuthorizationDecision(await authorizeRAGAction({
|
|
12185
|
+
action,
|
|
12186
|
+
request,
|
|
12187
|
+
resource
|
|
12188
|
+
}));
|
|
12189
|
+
};
|
|
12190
|
+
const isAuthorized = async (request, action, resource) => (await checkAuthorization(request, action, resource)).allowed;
|
|
12191
|
+
const buildAuthorizationFailure = (decision, fallback = "Forbidden") => ({
|
|
12192
|
+
error: decision.reason ?? fallback,
|
|
12193
|
+
ok: false
|
|
12194
|
+
});
|
|
12195
|
+
const isAccessScopeError = (error) => typeof error === "string" && (error.includes("allowed RAG access scope") || error.includes("Scoped sync-all is not allowed"));
|
|
12196
|
+
const authorizeMutationRoute = async (request, action, input) => {
|
|
12197
|
+
const decision = await checkAuthorization(request, action, input.resource);
|
|
12198
|
+
return decision.allowed ? null : buildAuthorizationFailure(decision, input.fallback);
|
|
12199
|
+
};
|
|
12200
|
+
const normalizeAccessScope = (scope) => {
|
|
12201
|
+
if (!scope) {
|
|
12202
|
+
return;
|
|
12203
|
+
}
|
|
12204
|
+
const normalizeStringArray3 = (values) => {
|
|
12205
|
+
const next = (values ?? []).map((value) => value.trim()).filter((value) => value.length > 0);
|
|
12206
|
+
return next.length > 0 ? [...new Set(next)] : undefined;
|
|
12207
|
+
};
|
|
12208
|
+
const requiredMetadata = scope.requiredMetadata && Object.keys(scope.requiredMetadata).length > 0 ? scope.requiredMetadata : undefined;
|
|
12209
|
+
return {
|
|
12210
|
+
allowedComparisonGroupKeys: normalizeStringArray3(scope.allowedComparisonGroupKeys),
|
|
12211
|
+
allowedCorpusKeys: normalizeStringArray3(scope.allowedCorpusKeys),
|
|
12212
|
+
allowedDocumentIds: normalizeStringArray3(scope.allowedDocumentIds),
|
|
12213
|
+
allowedSourcePrefixes: normalizeStringArray3(scope.allowedSourcePrefixes),
|
|
12214
|
+
allowedSources: normalizeStringArray3(scope.allowedSources),
|
|
12215
|
+
allowedSyncSourceIds: normalizeStringArray3(scope.allowedSyncSourceIds),
|
|
12216
|
+
requiredMetadata
|
|
12217
|
+
};
|
|
12218
|
+
};
|
|
12219
|
+
const loadAccessScope = async (request) => request && resolveRAGAccessScope ? normalizeAccessScope(await resolveRAGAccessScope(request)) : undefined;
|
|
12220
|
+
const matchesRequiredMetadata = (requiredMetadata, metadata) => {
|
|
12221
|
+
if (!requiredMetadata) {
|
|
12222
|
+
return true;
|
|
12223
|
+
}
|
|
12224
|
+
return Object.entries(requiredMetadata).every(([key, value]) => metadata?.[key] === value);
|
|
12225
|
+
};
|
|
12226
|
+
const matchesAccessScope = (scope, input) => {
|
|
12227
|
+
if (!scope) {
|
|
12228
|
+
return true;
|
|
12229
|
+
}
|
|
12230
|
+
const corpusKey = input.corpusKey ?? (typeof input.metadata?.corpusKey === "string" ? input.metadata.corpusKey : undefined);
|
|
12231
|
+
if (scope.allowedCorpusKeys?.length && (!corpusKey || !scope.allowedCorpusKeys.includes(corpusKey))) {
|
|
12232
|
+
return false;
|
|
12233
|
+
}
|
|
12234
|
+
if (scope.allowedDocumentIds?.length && (!input.documentId || !scope.allowedDocumentIds.includes(input.documentId))) {
|
|
12235
|
+
return false;
|
|
12236
|
+
}
|
|
12237
|
+
if (scope.allowedSources?.length && (!input.source || !scope.allowedSources.includes(input.source))) {
|
|
12238
|
+
return false;
|
|
12239
|
+
}
|
|
12240
|
+
if (scope.allowedSourcePrefixes?.length && (!input.source || !scope.allowedSourcePrefixes.some((prefix) => (input.source ?? "").startsWith(prefix)))) {
|
|
12241
|
+
return false;
|
|
12242
|
+
}
|
|
12243
|
+
return matchesRequiredMetadata(scope.requiredMetadata, input.metadata);
|
|
12244
|
+
};
|
|
12245
|
+
const matchesSyncSourceScope = (scope, source) => !scope?.allowedSyncSourceIds?.length || scope.allowedSyncSourceIds.includes(source.id);
|
|
12246
|
+
const isAllowedComparisonGroupKey = (scope, groupKey) => !scope?.allowedComparisonGroupKeys?.length || typeof groupKey === "string" && scope.allowedComparisonGroupKeys.includes(groupKey);
|
|
12247
|
+
const filterByComparisonGroupKey = (scope, records) => scope?.allowedComparisonGroupKeys?.length ? records.filter((record) => isAllowedComparisonGroupKey(scope, record.groupKey)) : records;
|
|
12248
|
+
const persistJobStateIfConfigured = async () => {
|
|
12249
|
+
if (!jobStateStore) {
|
|
12250
|
+
return;
|
|
12251
|
+
}
|
|
12252
|
+
await jobStateStore.save({
|
|
12253
|
+
adminActions: adminActions.slice(0, Math.max(0, jobHistoryRetention.maxAdminActions)),
|
|
12254
|
+
adminJobs: adminJobs.slice(0, Math.max(0, jobHistoryRetention.maxAdminJobs)),
|
|
12255
|
+
ingestJobs: ingestJobs.slice(0, Math.max(0, jobHistoryRetention.maxIngestJobs)),
|
|
12256
|
+
syncJobs: syncJobs.slice(0, Math.max(0, jobHistoryRetention.maxSyncJobs))
|
|
12257
|
+
});
|
|
12258
|
+
};
|
|
12259
|
+
const recoverIngestJob = (job, recoveredAt) => job.status === "running" ? {
|
|
12260
|
+
...job,
|
|
12261
|
+
elapsedMs: Math.max(0, recoveredAt - job.startedAt),
|
|
12262
|
+
error: job.error ?? "Interrupted before completion during recovery",
|
|
12263
|
+
finishedAt: recoveredAt,
|
|
12264
|
+
status: "failed"
|
|
12265
|
+
} : job;
|
|
12266
|
+
const recoverAdminJob = (job, recoveredAt) => job.status === "running" ? {
|
|
12267
|
+
...job,
|
|
12268
|
+
elapsedMs: Math.max(0, recoveredAt - job.startedAt),
|
|
12269
|
+
error: job.error ?? "Interrupted before completion during recovery",
|
|
12270
|
+
finishedAt: recoveredAt,
|
|
12271
|
+
status: "failed"
|
|
12272
|
+
} : job;
|
|
12273
|
+
const ensureJobStateLoaded = async () => {
|
|
12274
|
+
if (jobStateLoaded) {
|
|
12275
|
+
return;
|
|
12276
|
+
}
|
|
12277
|
+
if (jobStateLoadPromise) {
|
|
12278
|
+
await jobStateLoadPromise;
|
|
12279
|
+
return;
|
|
12280
|
+
}
|
|
12281
|
+
jobStateLoadPromise = (async () => {
|
|
12282
|
+
if (!jobStateStore) {
|
|
12283
|
+
jobStateLoaded = true;
|
|
12284
|
+
return;
|
|
12285
|
+
}
|
|
12286
|
+
const loaded = await jobStateStore.load();
|
|
12287
|
+
const recoveredAt = Date.now();
|
|
12288
|
+
const nextIngestJobs = (loaded?.ingestJobs ?? []).map((job) => recoverIngestJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxIngestJobs));
|
|
12289
|
+
const nextAdminActions = (loaded?.adminActions ?? []).slice(0, Math.max(0, jobHistoryRetention.maxAdminActions));
|
|
12290
|
+
const nextAdminJobs = (loaded?.adminJobs ?? []).map((job) => recoverAdminJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxAdminJobs));
|
|
12291
|
+
const nextSyncJobs = (loaded?.syncJobs ?? []).map((job) => recoverAdminJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxSyncJobs));
|
|
12292
|
+
adminActions.splice(0, adminActions.length, ...nextAdminActions);
|
|
12293
|
+
ingestJobs.splice(0, ingestJobs.length, ...nextIngestJobs);
|
|
12294
|
+
adminJobs.splice(0, adminJobs.length, ...nextAdminJobs);
|
|
12295
|
+
syncJobs.splice(0, syncJobs.length, ...nextSyncJobs);
|
|
12296
|
+
jobStateLoaded = true;
|
|
12297
|
+
await persistJobStateIfConfigured();
|
|
12298
|
+
})();
|
|
12299
|
+
try {
|
|
12300
|
+
await jobStateLoadPromise;
|
|
12301
|
+
} finally {
|
|
12302
|
+
jobStateLoadPromise = undefined;
|
|
12303
|
+
}
|
|
12304
|
+
};
|
|
11967
12305
|
const createIngestJob = (inputKind, requestedCount) => {
|
|
11968
12306
|
const job = {
|
|
11969
12307
|
id: generateId(),
|
|
@@ -11973,9 +12311,10 @@ var ragChat = (config) => {
|
|
|
11973
12311
|
status: "running"
|
|
11974
12312
|
};
|
|
11975
12313
|
ingestJobs.unshift(job);
|
|
11976
|
-
if (ingestJobs.length >
|
|
11977
|
-
ingestJobs.length =
|
|
12314
|
+
if (ingestJobs.length > jobHistoryRetention.maxIngestJobs) {
|
|
12315
|
+
ingestJobs.length = jobHistoryRetention.maxIngestJobs;
|
|
11978
12316
|
}
|
|
12317
|
+
persistJobStateIfConfigured();
|
|
11979
12318
|
return job;
|
|
11980
12319
|
};
|
|
11981
12320
|
const completeIngestJob = (job, input) => {
|
|
@@ -11986,6 +12325,7 @@ var ragChat = (config) => {
|
|
|
11986
12325
|
job.chunkCount = input.chunkCount;
|
|
11987
12326
|
job.documentCount = input.documentCount;
|
|
11988
12327
|
job.extractorNames = input.extractorNames;
|
|
12328
|
+
persistJobStateIfConfigured();
|
|
11989
12329
|
};
|
|
11990
12330
|
const failIngestJob = (job, error, extractorNames) => {
|
|
11991
12331
|
const finishedAt = Date.now();
|
|
@@ -11994,6 +12334,7 @@ var ragChat = (config) => {
|
|
|
11994
12334
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
11995
12335
|
job.error = error;
|
|
11996
12336
|
job.extractorNames = extractorNames;
|
|
12337
|
+
persistJobStateIfConfigured();
|
|
11997
12338
|
};
|
|
11998
12339
|
const createAdminAction = (action, documentId, target) => {
|
|
11999
12340
|
const record = {
|
|
@@ -12005,9 +12346,10 @@ var ragChat = (config) => {
|
|
|
12005
12346
|
target
|
|
12006
12347
|
};
|
|
12007
12348
|
adminActions.unshift(record);
|
|
12008
|
-
if (adminActions.length >
|
|
12009
|
-
adminActions.length =
|
|
12349
|
+
if (adminActions.length > jobHistoryRetention.maxAdminActions) {
|
|
12350
|
+
adminActions.length = jobHistoryRetention.maxAdminActions;
|
|
12010
12351
|
}
|
|
12352
|
+
persistJobStateIfConfigured();
|
|
12011
12353
|
return record;
|
|
12012
12354
|
};
|
|
12013
12355
|
const createAdminJob = (action, target, bucket = adminJobs) => {
|
|
@@ -12019,9 +12361,11 @@ var ragChat = (config) => {
|
|
|
12019
12361
|
target
|
|
12020
12362
|
};
|
|
12021
12363
|
bucket.unshift(job);
|
|
12022
|
-
|
|
12023
|
-
|
|
12364
|
+
const maxJobs = bucket === syncJobs ? jobHistoryRetention.maxSyncJobs : jobHistoryRetention.maxAdminJobs;
|
|
12365
|
+
if (bucket.length > maxJobs) {
|
|
12366
|
+
bucket.length = maxJobs;
|
|
12024
12367
|
}
|
|
12368
|
+
persistJobStateIfConfigured();
|
|
12025
12369
|
return job;
|
|
12026
12370
|
};
|
|
12027
12371
|
const completeAdminAction = (record) => {
|
|
@@ -12029,6 +12373,7 @@ var ragChat = (config) => {
|
|
|
12029
12373
|
record.status = "completed";
|
|
12030
12374
|
record.finishedAt = finishedAt;
|
|
12031
12375
|
record.elapsedMs = finishedAt - record.startedAt;
|
|
12376
|
+
persistJobStateIfConfigured();
|
|
12032
12377
|
};
|
|
12033
12378
|
const failAdminAction = (record, error) => {
|
|
12034
12379
|
const finishedAt = Date.now();
|
|
@@ -12036,12 +12381,14 @@ var ragChat = (config) => {
|
|
|
12036
12381
|
record.finishedAt = finishedAt;
|
|
12037
12382
|
record.elapsedMs = finishedAt - record.startedAt;
|
|
12038
12383
|
record.error = error;
|
|
12384
|
+
persistJobStateIfConfigured();
|
|
12039
12385
|
};
|
|
12040
12386
|
const completeAdminJob = (job) => {
|
|
12041
12387
|
const finishedAt = Date.now();
|
|
12042
12388
|
job.status = "completed";
|
|
12043
12389
|
job.finishedAt = finishedAt;
|
|
12044
12390
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
12391
|
+
persistJobStateIfConfigured();
|
|
12045
12392
|
};
|
|
12046
12393
|
const failAdminJob = (job, error) => {
|
|
12047
12394
|
const finishedAt = Date.now();
|
|
@@ -12049,8 +12396,10 @@ var ragChat = (config) => {
|
|
|
12049
12396
|
job.finishedAt = finishedAt;
|
|
12050
12397
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
12051
12398
|
job.error = error;
|
|
12399
|
+
persistJobStateIfConfigured();
|
|
12052
12400
|
};
|
|
12053
12401
|
const runSearchTracePrune = async (input, trigger = "manual") => {
|
|
12402
|
+
await ensureJobStateLoaded();
|
|
12054
12403
|
if (!searchTraceStore) {
|
|
12055
12404
|
throw new Error("RAG search trace store is not configured");
|
|
12056
12405
|
}
|
|
@@ -12138,11 +12487,12 @@ var ragChat = (config) => {
|
|
|
12138
12487
|
throw error;
|
|
12139
12488
|
}
|
|
12140
12489
|
};
|
|
12141
|
-
const buildSyncSources = async () => {
|
|
12490
|
+
const buildSyncSources = async (scope) => {
|
|
12142
12491
|
if (!indexManager?.listSyncSources) {
|
|
12143
12492
|
return [];
|
|
12144
12493
|
}
|
|
12145
|
-
|
|
12494
|
+
const sources = await indexManager.listSyncSources();
|
|
12495
|
+
return sources.filter((source) => matchesSyncSourceScope(scope, source));
|
|
12146
12496
|
};
|
|
12147
12497
|
const toHTMXResponse = (html, status, extraHeaders) => new Response(html, {
|
|
12148
12498
|
headers: {
|
|
@@ -12306,6 +12656,7 @@ var ragChat = (config) => {
|
|
|
12306
12656
|
return null;
|
|
12307
12657
|
}
|
|
12308
12658
|
return {
|
|
12659
|
+
corpusKey: getStringProperty(candidate, "corpusKey") ?? undefined,
|
|
12309
12660
|
filter: caseFilter,
|
|
12310
12661
|
id: getStringProperty(candidate, "id") ?? `case-${caseIndex + 1}`,
|
|
12311
12662
|
retrieval: parsedCaseRetrieval === undefined || parsedCaseRetrieval === null ? undefined : parsedCaseRetrieval,
|
|
@@ -12343,7 +12694,7 @@ var ragChat = (config) => {
|
|
|
12343
12694
|
scoreThreshold: typeof getNumberProperty(body, "scoreThreshold") === "number" ? getNumberProperty(body, "scoreThreshold") : undefined
|
|
12344
12695
|
};
|
|
12345
12696
|
};
|
|
12346
|
-
const handleEvaluate = async (body) => {
|
|
12697
|
+
const handleEvaluate = async (body, request) => {
|
|
12347
12698
|
const input = toRAGEvaluationInput(body);
|
|
12348
12699
|
if (!input) {
|
|
12349
12700
|
return {
|
|
@@ -12351,6 +12702,17 @@ var ragChat = (config) => {
|
|
|
12351
12702
|
ok: false
|
|
12352
12703
|
};
|
|
12353
12704
|
}
|
|
12705
|
+
const accessScope = await loadAccessScope(request);
|
|
12706
|
+
for (const evaluationCase of input.cases) {
|
|
12707
|
+
if (evaluationCase.corpusKey && !matchesAccessScope(accessScope, {
|
|
12708
|
+
corpusKey: evaluationCase.corpusKey
|
|
12709
|
+
}) || (evaluationCase.expectedDocumentIds ?? []).some((documentId) => !matchesAccessScope(accessScope, { documentId })) || (evaluationCase.expectedSources ?? []).some((source) => !matchesAccessScope(accessScope, { source }))) {
|
|
12710
|
+
return {
|
|
12711
|
+
error: "Evaluation case is outside the allowed RAG access scope",
|
|
12712
|
+
ok: false
|
|
12713
|
+
};
|
|
12714
|
+
}
|
|
12715
|
+
}
|
|
12354
12716
|
const collection = resolveCollection();
|
|
12355
12717
|
if (!collection) {
|
|
12356
12718
|
return {
|
|
@@ -12853,7 +13215,7 @@ var ragChat = (config) => {
|
|
|
12853
13215
|
});
|
|
12854
13216
|
return incidents.find((entry) => entry.id === incidentId);
|
|
12855
13217
|
};
|
|
12856
|
-
const handleEvaluateRetrievals = async (body) => {
|
|
13218
|
+
const handleEvaluateRetrievals = async (body, request) => {
|
|
12857
13219
|
const input = toRAGRetrievalComparisonRequest(body);
|
|
12858
13220
|
if (!input) {
|
|
12859
13221
|
return {
|
|
@@ -12861,6 +13223,23 @@ var ragChat = (config) => {
|
|
|
12861
13223
|
ok: false
|
|
12862
13224
|
};
|
|
12863
13225
|
}
|
|
13226
|
+
const accessScope = await loadAccessScope(request);
|
|
13227
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
13228
|
+
return {
|
|
13229
|
+
error: "Retrieval comparison group is outside the allowed RAG access scope",
|
|
13230
|
+
ok: false
|
|
13231
|
+
};
|
|
13232
|
+
}
|
|
13233
|
+
for (const evaluationCase of input.cases) {
|
|
13234
|
+
if (evaluationCase.corpusKey && !matchesAccessScope(accessScope, {
|
|
13235
|
+
corpusKey: evaluationCase.corpusKey
|
|
13236
|
+
}) || (evaluationCase.expectedDocumentIds ?? []).some((documentId) => !matchesAccessScope(accessScope, { documentId })) || (evaluationCase.expectedSources ?? []).some((source) => !matchesAccessScope(accessScope, { source }))) {
|
|
13237
|
+
return {
|
|
13238
|
+
error: "Retrieval comparison case is outside the allowed RAG access scope",
|
|
13239
|
+
ok: false
|
|
13240
|
+
};
|
|
13241
|
+
}
|
|
13242
|
+
}
|
|
12864
13243
|
const collection = resolveCollection();
|
|
12865
13244
|
if (!collection) {
|
|
12866
13245
|
return {
|
|
@@ -12907,6 +13286,7 @@ var ragChat = (config) => {
|
|
|
12907
13286
|
await persistRAGRetrievalComparisonRun({
|
|
12908
13287
|
run: {
|
|
12909
13288
|
comparison,
|
|
13289
|
+
corpusKeys: comparison.corpusKeys,
|
|
12910
13290
|
decisionSummary,
|
|
12911
13291
|
elapsedMs: finishedAt - startedAt,
|
|
12912
13292
|
finishedAt,
|
|
@@ -12930,15 +13310,23 @@ var ragChat = (config) => {
|
|
|
12930
13310
|
ok: true
|
|
12931
13311
|
};
|
|
12932
13312
|
};
|
|
12933
|
-
const handleRetrievalComparisonHistory = async (queryInput) => {
|
|
13313
|
+
const handleRetrievalComparisonHistory = async (queryInput, request) => {
|
|
12934
13314
|
if (!retrievalComparisonHistoryStore) {
|
|
12935
13315
|
return {
|
|
12936
13316
|
error: "RAG retrieval comparison history store is not configured",
|
|
12937
13317
|
ok: false
|
|
12938
13318
|
};
|
|
12939
13319
|
}
|
|
13320
|
+
const accessScope = await loadAccessScope(request);
|
|
13321
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
13322
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
13323
|
+
return {
|
|
13324
|
+
error: "Retrieval comparison group is outside the allowed RAG access scope",
|
|
13325
|
+
ok: false
|
|
13326
|
+
};
|
|
13327
|
+
}
|
|
12940
13328
|
const runs = await loadRAGRetrievalComparisonHistory({
|
|
12941
|
-
groupKey
|
|
13329
|
+
groupKey,
|
|
12942
13330
|
label: getStringProperty(queryInput, "label"),
|
|
12943
13331
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
12944
13332
|
store: retrievalComparisonHistoryStore,
|
|
@@ -12948,25 +13336,33 @@ var ragChat = (config) => {
|
|
|
12948
13336
|
});
|
|
12949
13337
|
return {
|
|
12950
13338
|
ok: true,
|
|
12951
|
-
runs
|
|
13339
|
+
runs: filterByComparisonGroupKey(accessScope, runs)
|
|
12952
13340
|
};
|
|
12953
13341
|
};
|
|
12954
|
-
const handleRetrievalBaselineList = async (queryInput) => {
|
|
13342
|
+
const handleRetrievalBaselineList = async (queryInput, request) => {
|
|
12955
13343
|
if (!retrievalBaselineStore) {
|
|
12956
13344
|
return {
|
|
12957
13345
|
error: "RAG retrieval baseline store is not configured",
|
|
12958
13346
|
ok: false
|
|
12959
13347
|
};
|
|
12960
13348
|
}
|
|
13349
|
+
const accessScope = await loadAccessScope(request);
|
|
13350
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
13351
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
13352
|
+
return {
|
|
13353
|
+
error: "Retrieval baseline group is outside the allowed RAG access scope",
|
|
13354
|
+
ok: false
|
|
13355
|
+
};
|
|
13356
|
+
}
|
|
12961
13357
|
const baselines = await loadRAGRetrievalBaselines({
|
|
12962
|
-
groupKey
|
|
13358
|
+
groupKey,
|
|
12963
13359
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
12964
13360
|
status: getStringProperty(queryInput, "status") === "active" || getStringProperty(queryInput, "status") === "superseded" ? getStringProperty(queryInput, "status") : undefined,
|
|
12965
13361
|
store: retrievalBaselineStore,
|
|
12966
13362
|
tag: getStringProperty(queryInput, "tag")
|
|
12967
13363
|
});
|
|
12968
13364
|
return {
|
|
12969
|
-
baselines,
|
|
13365
|
+
baselines: filterByComparisonGroupKey(accessScope, baselines),
|
|
12970
13366
|
ok: true
|
|
12971
13367
|
};
|
|
12972
13368
|
};
|
|
@@ -13679,7 +14075,7 @@ var ragChat = (config) => {
|
|
|
13679
14075
|
});
|
|
13680
14076
|
return baseline;
|
|
13681
14077
|
};
|
|
13682
|
-
const handlePromoteRetrievalBaseline = async (body) => {
|
|
14078
|
+
const handlePromoteRetrievalBaseline = async (body, request) => {
|
|
13683
14079
|
if (!retrievalBaselineStore) {
|
|
13684
14080
|
return {
|
|
13685
14081
|
error: "RAG retrieval baseline store is not configured",
|
|
@@ -13776,7 +14172,7 @@ var ragChat = (config) => {
|
|
|
13776
14172
|
};
|
|
13777
14173
|
}
|
|
13778
14174
|
};
|
|
13779
|
-
const handlePromoteRetrievalBaselineFromRun = async (body) => {
|
|
14175
|
+
const handlePromoteRetrievalBaselineFromRun = async (body, request) => {
|
|
13780
14176
|
if (!retrievalBaselineStore || !retrievalComparisonHistoryStore) {
|
|
13781
14177
|
return {
|
|
13782
14178
|
error: "RAG retrieval baseline store and retrieval comparison history store are required",
|
|
@@ -13876,7 +14272,7 @@ var ragChat = (config) => {
|
|
|
13876
14272
|
};
|
|
13877
14273
|
}
|
|
13878
14274
|
};
|
|
13879
|
-
const handleRevertRetrievalBaseline = async (body) => {
|
|
14275
|
+
const handleRevertRetrievalBaseline = async (body, request) => {
|
|
13880
14276
|
if (!retrievalBaselineStore) {
|
|
13881
14277
|
return {
|
|
13882
14278
|
error: "RAG retrieval baseline store is not configured",
|
|
@@ -13951,24 +14347,32 @@ var ragChat = (config) => {
|
|
|
13951
14347
|
};
|
|
13952
14348
|
}
|
|
13953
14349
|
};
|
|
13954
|
-
const handleRetrievalReleaseDecisionList = async (queryInput) => {
|
|
14350
|
+
const handleRetrievalReleaseDecisionList = async (queryInput, request) => {
|
|
13955
14351
|
if (!config.retrievalReleaseDecisionStore) {
|
|
13956
14352
|
return {
|
|
13957
14353
|
error: "RAG retrieval release decision store is not configured",
|
|
13958
14354
|
ok: false
|
|
13959
14355
|
};
|
|
13960
14356
|
}
|
|
14357
|
+
const accessScope = await loadAccessScope(request);
|
|
14358
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14359
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14360
|
+
return {
|
|
14361
|
+
error: "Retrieval release decision group is outside the allowed RAG access scope",
|
|
14362
|
+
ok: false
|
|
14363
|
+
};
|
|
14364
|
+
}
|
|
13961
14365
|
const kind = getStringProperty(queryInput, "kind");
|
|
13962
14366
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
13963
14367
|
const freshnessStatusFilter = getStringProperty(queryInput, "freshnessStatus");
|
|
13964
14368
|
const decisions = await loadRAGRetrievalReleaseDecisions({
|
|
13965
|
-
groupKey
|
|
14369
|
+
groupKey,
|
|
13966
14370
|
kind: kind === "approve" || kind === "promote" || kind === "reject" || kind === "revert" ? kind : undefined,
|
|
13967
14371
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
13968
14372
|
store: config.retrievalReleaseDecisionStore
|
|
13969
14373
|
});
|
|
13970
14374
|
return {
|
|
13971
|
-
decisions: decisions.map((decision) => ({
|
|
14375
|
+
decisions: filterByComparisonGroupKey(accessScope, decisions).map((decision) => ({
|
|
13972
14376
|
...decision,
|
|
13973
14377
|
...getDecisionFreshness({ record: decision })
|
|
13974
14378
|
})).filter((decision) => {
|
|
@@ -13986,7 +14390,7 @@ var ragChat = (config) => {
|
|
|
13986
14390
|
ok: true
|
|
13987
14391
|
};
|
|
13988
14392
|
};
|
|
13989
|
-
const handleRetrievalReleaseDecisionAction = async (body, kind) => {
|
|
14393
|
+
const handleRetrievalReleaseDecisionAction = async (body, kind, request) => {
|
|
13990
14394
|
if (!retrievalComparisonHistoryStore || !config.retrievalReleaseDecisionStore) {
|
|
13991
14395
|
return {
|
|
13992
14396
|
error: "RAG retrieval comparison history store and release decision store are required",
|
|
@@ -15313,7 +15717,7 @@ var ragChat = (config) => {
|
|
|
15313
15717
|
return { error: message, ok: false };
|
|
15314
15718
|
}
|
|
15315
15719
|
};
|
|
15316
|
-
const handleSearch = async (body) => {
|
|
15720
|
+
const handleSearch = async (body, request) => {
|
|
15317
15721
|
if (!isObjectRecord2(body)) {
|
|
15318
15722
|
return { error: "Invalid payload", ok: false };
|
|
15319
15723
|
}
|
|
@@ -15325,6 +15729,7 @@ var ragChat = (config) => {
|
|
|
15325
15729
|
};
|
|
15326
15730
|
}
|
|
15327
15731
|
const collection = resolveCollection();
|
|
15732
|
+
const accessScope = await loadAccessScope(request);
|
|
15328
15733
|
if (!collection) {
|
|
15329
15734
|
return { error: "RAG collection is not configured", ok: false };
|
|
15330
15735
|
}
|
|
@@ -15367,14 +15772,28 @@ var ragChat = (config) => {
|
|
|
15367
15772
|
trace: result.trace
|
|
15368
15773
|
});
|
|
15369
15774
|
}
|
|
15775
|
+
const scopedResults = buildSources2(result.results).filter((entry) => matchesAccessScope(accessScope, {
|
|
15776
|
+
corpusKey: entry.corpusKey,
|
|
15777
|
+
documentId: typeof entry.metadata?.documentId === "string" ? entry.metadata.documentId : entry.chunkId.split(":")[0],
|
|
15778
|
+
metadata: entry.metadata,
|
|
15779
|
+
source: entry.source
|
|
15780
|
+
}));
|
|
15370
15781
|
return {
|
|
15371
15782
|
ok: true,
|
|
15372
|
-
results:
|
|
15783
|
+
results: scopedResults,
|
|
15373
15784
|
trace: result.trace
|
|
15374
15785
|
};
|
|
15375
15786
|
}
|
|
15376
15787
|
const results = await collection.search(input);
|
|
15377
|
-
return {
|
|
15788
|
+
return {
|
|
15789
|
+
ok: true,
|
|
15790
|
+
results: buildSources2(results).filter((entry) => matchesAccessScope(accessScope, {
|
|
15791
|
+
corpusKey: entry.corpusKey,
|
|
15792
|
+
documentId: typeof entry.metadata?.documentId === "string" ? entry.metadata.documentId : entry.chunkId.split(":")[0],
|
|
15793
|
+
metadata: entry.metadata,
|
|
15794
|
+
source: entry.source
|
|
15795
|
+
}))
|
|
15796
|
+
};
|
|
15378
15797
|
};
|
|
15379
15798
|
const handleTraceHistory = async (queryInput) => {
|
|
15380
15799
|
if (!searchTraceStore) {
|
|
@@ -15520,7 +15939,10 @@ var ragChat = (config) => {
|
|
|
15520
15939
|
let inspectedChunks = 0;
|
|
15521
15940
|
let documentsWithSourceLabels = 0;
|
|
15522
15941
|
let chunksWithSourceLabels = 0;
|
|
15942
|
+
const corpusKeys = new Map;
|
|
15523
15943
|
const sourceNativeKinds = new Map;
|
|
15944
|
+
const extractorRegistryMatches = new Map;
|
|
15945
|
+
const chunkingProfiles = new Map;
|
|
15524
15946
|
const sampleDocuments = [];
|
|
15525
15947
|
const sampleChunks = [];
|
|
15526
15948
|
let oldestDocumentAgeMs;
|
|
@@ -15572,11 +15994,26 @@ var ragChat = (config) => {
|
|
|
15572
15994
|
documentsWithSourceLabels += 1;
|
|
15573
15995
|
}
|
|
15574
15996
|
const documentSourceNativeKind = typeof document.metadata?.sourceNativeKind === "string" ? document.metadata.sourceNativeKind : undefined;
|
|
15997
|
+
const documentCorpusKey = document.corpusKey ?? (typeof document.metadata?.corpusKey === "string" ? document.metadata.corpusKey : undefined);
|
|
15998
|
+
const documentExtractorRegistryMatch = typeof document.metadata?.extractorRegistryMatch === "string" ? document.metadata.extractorRegistryMatch : undefined;
|
|
15999
|
+
const documentChunkingProfile = typeof document.metadata?.chunkingProfile === "string" ? document.metadata.chunkingProfile : undefined;
|
|
15575
16000
|
if (documentSourceNativeKind) {
|
|
15576
16001
|
sourceNativeKinds.set(documentSourceNativeKind, (sourceNativeKinds.get(documentSourceNativeKind) ?? 0) + 1);
|
|
15577
16002
|
}
|
|
15578
|
-
if (
|
|
16003
|
+
if (documentCorpusKey) {
|
|
16004
|
+
corpusKeys.set(documentCorpusKey, (corpusKeys.get(documentCorpusKey) ?? 0) + 1);
|
|
16005
|
+
}
|
|
16006
|
+
if (documentExtractorRegistryMatch) {
|
|
16007
|
+
extractorRegistryMatches.set(documentExtractorRegistryMatch, (extractorRegistryMatches.get(documentExtractorRegistryMatch) ?? 0) + 1);
|
|
16008
|
+
}
|
|
16009
|
+
if (documentChunkingProfile) {
|
|
16010
|
+
chunkingProfiles.set(documentChunkingProfile, (chunkingProfiles.get(documentChunkingProfile) ?? 0) + 1);
|
|
16011
|
+
}
|
|
16012
|
+
if (sampleDocuments.length < 5 && (documentCorpusKey || documentLabels || documentSourceNativeKind || documentExtractorRegistryMatch || documentChunkingProfile)) {
|
|
15579
16013
|
sampleDocuments.push({
|
|
16014
|
+
corpusKey: documentCorpusKey,
|
|
16015
|
+
chunkingProfile: documentChunkingProfile,
|
|
16016
|
+
extractorRegistryMatch: documentExtractorRegistryMatch,
|
|
15580
16017
|
id: document.id,
|
|
15581
16018
|
labels: documentLabels,
|
|
15582
16019
|
source: document.source,
|
|
@@ -15602,13 +16039,28 @@ var ragChat = (config) => {
|
|
|
15602
16039
|
chunksWithSourceLabels += 1;
|
|
15603
16040
|
}
|
|
15604
16041
|
const chunkSourceNativeKind = typeof chunk.metadata?.sourceNativeKind === "string" ? chunk.metadata.sourceNativeKind : undefined;
|
|
16042
|
+
const chunkCorpusKey = chunk.corpusKey ?? (typeof chunk.metadata?.corpusKey === "string" ? chunk.metadata.corpusKey : documentCorpusKey);
|
|
16043
|
+
const chunkExtractorRegistryMatch = typeof chunk.metadata?.extractorRegistryMatch === "string" ? chunk.metadata.extractorRegistryMatch : undefined;
|
|
16044
|
+
const chunkChunkingProfile = typeof chunk.metadata?.chunkingProfile === "string" ? chunk.metadata.chunkingProfile : undefined;
|
|
15605
16045
|
if (chunkSourceNativeKind) {
|
|
15606
16046
|
sourceNativeKinds.set(chunkSourceNativeKind, (sourceNativeKinds.get(chunkSourceNativeKind) ?? 0) + 1);
|
|
15607
16047
|
}
|
|
15608
|
-
if (
|
|
16048
|
+
if (chunkCorpusKey) {
|
|
16049
|
+
corpusKeys.set(chunkCorpusKey, (corpusKeys.get(chunkCorpusKey) ?? 0) + 1);
|
|
16050
|
+
}
|
|
16051
|
+
if (chunkExtractorRegistryMatch) {
|
|
16052
|
+
extractorRegistryMatches.set(chunkExtractorRegistryMatch, (extractorRegistryMatches.get(chunkExtractorRegistryMatch) ?? 0) + 1);
|
|
16053
|
+
}
|
|
16054
|
+
if (chunkChunkingProfile) {
|
|
16055
|
+
chunkingProfiles.set(chunkChunkingProfile, (chunkingProfiles.get(chunkChunkingProfile) ?? 0) + 1);
|
|
16056
|
+
}
|
|
16057
|
+
if (sampleChunks.length < 8 && (chunkCorpusKey || chunkLabels || chunkSourceNativeKind || chunkExtractorRegistryMatch || chunkChunkingProfile)) {
|
|
15609
16058
|
sampleChunks.push({
|
|
15610
16059
|
chunkId: chunk.chunkId,
|
|
16060
|
+
chunkingProfile: chunkChunkingProfile,
|
|
16061
|
+
corpusKey: chunkCorpusKey,
|
|
15611
16062
|
documentId: document.id,
|
|
16063
|
+
extractorRegistryMatch: chunkExtractorRegistryMatch,
|
|
15612
16064
|
labels: chunkLabels,
|
|
15613
16065
|
source: chunk.source ?? preview.document.source,
|
|
15614
16066
|
sourceNativeKind: chunkSourceNativeKind
|
|
@@ -15671,8 +16123,11 @@ var ragChat = (config) => {
|
|
|
15671
16123
|
inspectedChunks,
|
|
15672
16124
|
inspectedDocuments,
|
|
15673
16125
|
inspection: {
|
|
16126
|
+
chunkingProfiles: Object.fromEntries(chunkingProfiles.entries()),
|
|
16127
|
+
corpusKeys: Object.fromEntries(corpusKeys.entries()),
|
|
15674
16128
|
chunksWithSourceLabels,
|
|
15675
16129
|
documentsWithSourceLabels,
|
|
16130
|
+
extractorRegistryMatches: Object.fromEntries(extractorRegistryMatches.entries()),
|
|
15676
16131
|
sampleChunks,
|
|
15677
16132
|
sampleDocuments,
|
|
15678
16133
|
sourceNativeKinds: Object.fromEntries(sourceNativeKinds.entries())
|
|
@@ -15695,28 +16150,34 @@ var ragChat = (config) => {
|
|
|
15695
16150
|
providerName: typeof config.provider === "function" ? config.readinessProviderName : undefined,
|
|
15696
16151
|
rerankerConfigured: Boolean(config.rerank ?? config.collection)
|
|
15697
16152
|
});
|
|
15698
|
-
const buildAdminCapabilities = () => ({
|
|
15699
|
-
canClearIndex: Boolean(ragStore?.clear),
|
|
15700
|
-
canCreateDocument: Boolean(indexManager?.createDocument),
|
|
15701
|
-
canDeleteDocument: Boolean(indexManager?.deleteDocument),
|
|
15702
|
-
canListSyncSources: Boolean(indexManager?.listSyncSources),
|
|
15703
|
-
canManageRetrievalBaselines: Boolean(retrievalBaselineStore),
|
|
15704
|
-
canPruneSearchTraces: Boolean(searchTraceStore),
|
|
15705
|
-
canReindexDocument: Boolean(indexManager?.reindexDocument),
|
|
15706
|
-
canReindexSource: Boolean(indexManager?.reindexSource),
|
|
15707
|
-
canReseed: Boolean(indexManager?.reseed),
|
|
15708
|
-
canReset: Boolean(indexManager?.reset),
|
|
15709
|
-
canSyncAllSources: Boolean(indexManager?.syncAllSources),
|
|
15710
|
-
canSyncSource: Boolean(indexManager?.syncSource)
|
|
16153
|
+
const buildAdminCapabilities = async (request) => ({
|
|
16154
|
+
canClearIndex: Boolean(ragStore?.clear) && (request ? await isAuthorized(request, "clear_index") : true),
|
|
16155
|
+
canCreateDocument: Boolean(indexManager?.createDocument) && (request ? await isAuthorized(request, "create_document") : true),
|
|
16156
|
+
canDeleteDocument: Boolean(indexManager?.deleteDocument) && (request ? await isAuthorized(request, "delete_document") : true),
|
|
16157
|
+
canListSyncSources: Boolean(indexManager?.listSyncSources) && (request ? await isAuthorized(request, "list_sync_sources") : true),
|
|
16158
|
+
canManageRetrievalBaselines: Boolean(retrievalBaselineStore) && (request ? await isAuthorized(request, "manage_retrieval_admin") : true),
|
|
16159
|
+
canPruneSearchTraces: Boolean(searchTraceStore) && (request ? await isAuthorized(request, "prune_search_traces") : true),
|
|
16160
|
+
canReindexDocument: Boolean(indexManager?.reindexDocument) && (request ? await isAuthorized(request, "reindex_document") : true),
|
|
16161
|
+
canReindexSource: Boolean(indexManager?.reindexSource) && (request ? await isAuthorized(request, "reindex_source") : true),
|
|
16162
|
+
canReseed: Boolean(indexManager?.reseed) && (request ? await isAuthorized(request, "reseed") : true),
|
|
16163
|
+
canReset: Boolean(indexManager?.reset) && (request ? await isAuthorized(request, "reset") : true),
|
|
16164
|
+
canSyncAllSources: Boolean(indexManager?.syncAllSources) && (request ? await isAuthorized(request, "sync_all_sources") : true),
|
|
16165
|
+
canSyncSource: Boolean(indexManager?.syncSource) && (request ? await isAuthorized(request, "sync_source") : true)
|
|
15711
16166
|
});
|
|
15712
|
-
const buildOperationsPayload = async () => {
|
|
16167
|
+
const buildOperationsPayload = async (request) => {
|
|
16168
|
+
const accessScope = await loadAccessScope(request);
|
|
15713
16169
|
const collection = config.collection ?? (ragStore ? createRAGCollection({
|
|
15714
16170
|
defaultModel: config.embeddingModel,
|
|
15715
16171
|
defaultTopK: topK,
|
|
15716
16172
|
embedding: config.embedding,
|
|
15717
16173
|
store: ragStore
|
|
15718
16174
|
}) : null);
|
|
15719
|
-
const indexedDocuments = indexManager ? await indexManager.listDocuments({})
|
|
16175
|
+
const indexedDocuments = indexManager ? (await indexManager.listDocuments({})).filter((document) => matchesAccessScope(accessScope, {
|
|
16176
|
+
corpusKey: document.corpusKey,
|
|
16177
|
+
documentId: document.id,
|
|
16178
|
+
metadata: document.metadata,
|
|
16179
|
+
source: document.source
|
|
16180
|
+
})) : [];
|
|
15720
16181
|
const traceStats = searchTraceStore ? await summarizeRAGSearchTraceStore({
|
|
15721
16182
|
store: searchTraceStore
|
|
15722
16183
|
}) : undefined;
|
|
@@ -16707,7 +17168,7 @@ var ragChat = (config) => {
|
|
|
16707
17168
|
searchTraceRuntime.stats = traceStats;
|
|
16708
17169
|
searchTraceRuntime.recentRuns = recentTraceRuns;
|
|
16709
17170
|
return {
|
|
16710
|
-
admin: buildAdminCapabilities(),
|
|
17171
|
+
admin: await buildAdminCapabilities(request),
|
|
16711
17172
|
adminActions: [...adminActions],
|
|
16712
17173
|
adminJobs: [...adminJobs, ...syncJobs].sort((left, right) => right.startedAt - left.startedAt),
|
|
16713
17174
|
capabilities: collection?.getCapabilities?.(),
|
|
@@ -16786,27 +17247,27 @@ var ragChat = (config) => {
|
|
|
16786
17247
|
stats: traceStats
|
|
16787
17248
|
},
|
|
16788
17249
|
status: collection?.getStatus?.(),
|
|
16789
|
-
syncSources: await buildSyncSources()
|
|
17250
|
+
syncSources: await buildSyncSources(accessScope)
|
|
16790
17251
|
};
|
|
16791
17252
|
};
|
|
16792
|
-
const handleStatus = async () => buildOperationsPayload();
|
|
16793
|
-
const handleRetrievalReleaseStatus = async () => {
|
|
16794
|
-
const result = await buildOperationsPayload();
|
|
17253
|
+
const handleStatus = async (request) => buildOperationsPayload(request);
|
|
17254
|
+
const handleRetrievalReleaseStatus = async (request) => {
|
|
17255
|
+
const result = await buildOperationsPayload(request);
|
|
16795
17256
|
return {
|
|
16796
17257
|
ok: true,
|
|
16797
17258
|
retrievalComparisons: result.retrievalComparisons
|
|
16798
17259
|
};
|
|
16799
17260
|
};
|
|
16800
|
-
const handleRetrievalReleaseDriftStatus = async () => {
|
|
16801
|
-
const result = await buildOperationsPayload();
|
|
17261
|
+
const handleRetrievalReleaseDriftStatus = async (request) => {
|
|
17262
|
+
const result = await buildOperationsPayload(request);
|
|
16802
17263
|
return {
|
|
16803
17264
|
handoffDriftCountsByLane: result.retrievalComparisons?.handoffDriftCountsByLane,
|
|
16804
17265
|
handoffDriftRollups: result.retrievalComparisons?.handoffDriftRollups,
|
|
16805
17266
|
ok: true
|
|
16806
17267
|
};
|
|
16807
17268
|
};
|
|
16808
|
-
const handleRetrievalLaneHandoffIncidentStatus = async () => {
|
|
16809
|
-
const result = await buildOperationsPayload();
|
|
17269
|
+
const handleRetrievalLaneHandoffIncidentStatus = async (request) => {
|
|
17270
|
+
const result = await buildOperationsPayload(request);
|
|
16810
17271
|
const incidents = result.retrievalComparisons?.recentLaneHandoffIncidents;
|
|
16811
17272
|
return {
|
|
16812
17273
|
freshnessWindows: result.retrievalComparisons?.handoffFreshnessWindows,
|
|
@@ -16816,8 +17277,8 @@ var ragChat = (config) => {
|
|
|
16816
17277
|
ok: true
|
|
16817
17278
|
};
|
|
16818
17279
|
};
|
|
16819
|
-
const handleRetrievalLaneHandoffStatus = async () => {
|
|
16820
|
-
const result = await buildOperationsPayload();
|
|
17280
|
+
const handleRetrievalLaneHandoffStatus = async (request) => {
|
|
17281
|
+
const result = await buildOperationsPayload(request);
|
|
16821
17282
|
const incidents = result.retrievalComparisons?.recentLaneHandoffIncidents;
|
|
16822
17283
|
return {
|
|
16823
17284
|
autoComplete: result.retrievalComparisons?.handoffAutoComplete,
|
|
@@ -16830,7 +17291,7 @@ var ragChat = (config) => {
|
|
|
16830
17291
|
ok: true
|
|
16831
17292
|
};
|
|
16832
17293
|
};
|
|
16833
|
-
const handleOps = async () => buildOperationsPayload();
|
|
17294
|
+
const handleOps = async (request) => buildOperationsPayload(request);
|
|
16834
17295
|
if (searchTraceStore && searchTraceRetention && searchTraceRetentionSchedule) {
|
|
16835
17296
|
const runScheduledSearchTracePrune = async () => {
|
|
16836
17297
|
searchTraceRuntime.nextScheduledAt = Date.now() + searchTraceRetentionSchedule.intervalMs;
|
|
@@ -16848,14 +17309,20 @@ var ragChat = (config) => {
|
|
|
16848
17309
|
}, searchTraceRetentionSchedule.intervalMs);
|
|
16849
17310
|
timer.unref?.();
|
|
16850
17311
|
}
|
|
16851
|
-
const handleDocuments = async (kind) => {
|
|
17312
|
+
const handleDocuments = async (kind, request) => {
|
|
16852
17313
|
if (!indexManager) {
|
|
16853
17314
|
return {
|
|
16854
17315
|
error: "RAG index document management is not configured",
|
|
16855
17316
|
ok: false
|
|
16856
17317
|
};
|
|
16857
17318
|
}
|
|
16858
|
-
const
|
|
17319
|
+
const accessScope = await loadAccessScope(request);
|
|
17320
|
+
const documents = (await indexManager.listDocuments({ kind })).filter((document) => matchesAccessScope(accessScope, {
|
|
17321
|
+
corpusKey: document.corpusKey,
|
|
17322
|
+
documentId: document.id,
|
|
17323
|
+
metadata: document.metadata,
|
|
17324
|
+
source: document.source
|
|
17325
|
+
}));
|
|
16859
17326
|
return {
|
|
16860
17327
|
documents: documents.map((document) => ({
|
|
16861
17328
|
...document,
|
|
@@ -16868,7 +17335,7 @@ var ragChat = (config) => {
|
|
|
16868
17335
|
ok: true
|
|
16869
17336
|
};
|
|
16870
17337
|
};
|
|
16871
|
-
const handleCreateDocument = async (body) => {
|
|
17338
|
+
const handleCreateDocument = async (body, request) => {
|
|
16872
17339
|
if (!indexManager?.createDocument) {
|
|
16873
17340
|
return {
|
|
16874
17341
|
error: "RAG document creation is not configured",
|
|
@@ -16887,6 +17354,18 @@ var ragChat = (config) => {
|
|
|
16887
17354
|
ok: false
|
|
16888
17355
|
};
|
|
16889
17356
|
}
|
|
17357
|
+
const accessScope = await loadAccessScope(request);
|
|
17358
|
+
if (!matchesAccessScope(accessScope, {
|
|
17359
|
+
documentId: body.id,
|
|
17360
|
+
corpusKey: body.corpusKey,
|
|
17361
|
+
metadata: body.metadata,
|
|
17362
|
+
source: body.source
|
|
17363
|
+
})) {
|
|
17364
|
+
return {
|
|
17365
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17366
|
+
ok: false
|
|
17367
|
+
};
|
|
17368
|
+
}
|
|
16890
17369
|
const job = createAdminJob("create_document", body.id);
|
|
16891
17370
|
try {
|
|
16892
17371
|
const result = await indexManager.createDocument(body);
|
|
@@ -16902,7 +17381,7 @@ var ragChat = (config) => {
|
|
|
16902
17381
|
throw caught;
|
|
16903
17382
|
}
|
|
16904
17383
|
};
|
|
16905
|
-
const handleDocumentChunks = async (id) => {
|
|
17384
|
+
const handleDocumentChunks = async (id, request) => {
|
|
16906
17385
|
if (!indexManager) {
|
|
16907
17386
|
return {
|
|
16908
17387
|
error: "RAG chunk preview is not configured",
|
|
@@ -16922,6 +17401,18 @@ var ragChat = (config) => {
|
|
|
16922
17401
|
ok: false
|
|
16923
17402
|
};
|
|
16924
17403
|
}
|
|
17404
|
+
const accessScope = await loadAccessScope(request);
|
|
17405
|
+
if (!matchesAccessScope(accessScope, {
|
|
17406
|
+
documentId: preview.document.id,
|
|
17407
|
+
corpusKey: preview.document.corpusKey,
|
|
17408
|
+
metadata: preview.document.metadata,
|
|
17409
|
+
source: preview.document.source
|
|
17410
|
+
})) {
|
|
17411
|
+
return {
|
|
17412
|
+
error: "document not found",
|
|
17413
|
+
ok: false
|
|
17414
|
+
};
|
|
17415
|
+
}
|
|
16925
17416
|
const chunks = preview.chunks.map((chunk) => ({
|
|
16926
17417
|
...chunk,
|
|
16927
17418
|
labels: buildRAGSourceLabels({
|
|
@@ -16952,7 +17443,7 @@ var ragChat = (config) => {
|
|
|
16952
17443
|
})
|
|
16953
17444
|
};
|
|
16954
17445
|
};
|
|
16955
|
-
const handleDeleteDocument = async (id) => {
|
|
17446
|
+
const handleDeleteDocument = async (id, request) => {
|
|
16956
17447
|
if (!indexManager?.deleteDocument) {
|
|
16957
17448
|
return {
|
|
16958
17449
|
error: "RAG document deletion is not configured",
|
|
@@ -16965,6 +17456,13 @@ var ragChat = (config) => {
|
|
|
16965
17456
|
ok: false
|
|
16966
17457
|
};
|
|
16967
17458
|
}
|
|
17459
|
+
const accessScope = await loadAccessScope(request);
|
|
17460
|
+
if (accessScope && !matchesAccessScope(accessScope, { documentId: id })) {
|
|
17461
|
+
return {
|
|
17462
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17463
|
+
ok: false
|
|
17464
|
+
};
|
|
17465
|
+
}
|
|
16968
17466
|
const job = createAdminJob("delete_document", id);
|
|
16969
17467
|
const deleted = await indexManager.deleteDocument(id);
|
|
16970
17468
|
if (!deleted) {
|
|
@@ -16984,7 +17482,7 @@ var ragChat = (config) => {
|
|
|
16984
17482
|
ok: true
|
|
16985
17483
|
};
|
|
16986
17484
|
};
|
|
16987
|
-
const handleReindexDocument = async (id) => {
|
|
17485
|
+
const handleReindexDocument = async (id, request) => {
|
|
16988
17486
|
if (!indexManager?.reindexDocument) {
|
|
16989
17487
|
return {
|
|
16990
17488
|
error: "RAG document reindex is not configured",
|
|
@@ -16997,6 +17495,13 @@ var ragChat = (config) => {
|
|
|
16997
17495
|
ok: false
|
|
16998
17496
|
};
|
|
16999
17497
|
}
|
|
17498
|
+
const accessScope = await loadAccessScope(request);
|
|
17499
|
+
if (accessScope && !matchesAccessScope(accessScope, { documentId: id })) {
|
|
17500
|
+
return {
|
|
17501
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17502
|
+
ok: false
|
|
17503
|
+
};
|
|
17504
|
+
}
|
|
17000
17505
|
const job = createAdminJob("reindex_document", id);
|
|
17001
17506
|
try {
|
|
17002
17507
|
const result = {
|
|
@@ -17016,7 +17521,7 @@ var ragChat = (config) => {
|
|
|
17016
17521
|
throw caught;
|
|
17017
17522
|
}
|
|
17018
17523
|
};
|
|
17019
|
-
const handleReindexSource = async (source) => {
|
|
17524
|
+
const handleReindexSource = async (source, request) => {
|
|
17020
17525
|
if (!indexManager?.reindexSource) {
|
|
17021
17526
|
return {
|
|
17022
17527
|
error: "RAG source reindex is not configured",
|
|
@@ -17029,6 +17534,15 @@ var ragChat = (config) => {
|
|
|
17029
17534
|
ok: false
|
|
17030
17535
|
};
|
|
17031
17536
|
}
|
|
17537
|
+
const accessScope = await loadAccessScope(request);
|
|
17538
|
+
if (!matchesAccessScope(accessScope, {
|
|
17539
|
+
source
|
|
17540
|
+
})) {
|
|
17541
|
+
return {
|
|
17542
|
+
error: "Source is outside the allowed RAG access scope",
|
|
17543
|
+
ok: false
|
|
17544
|
+
};
|
|
17545
|
+
}
|
|
17032
17546
|
const job = createAdminJob("reindex_source", source);
|
|
17033
17547
|
try {
|
|
17034
17548
|
const result = {
|
|
@@ -17112,25 +17626,33 @@ var ragChat = (config) => {
|
|
|
17112
17626
|
...normalized
|
|
17113
17627
|
};
|
|
17114
17628
|
};
|
|
17115
|
-
const handleSyncSources = async () => {
|
|
17629
|
+
const handleSyncSources = async (request) => {
|
|
17116
17630
|
if (!indexManager?.listSyncSources) {
|
|
17117
17631
|
return {
|
|
17118
17632
|
error: "RAG source sync is not configured",
|
|
17119
17633
|
ok: false
|
|
17120
17634
|
};
|
|
17121
17635
|
}
|
|
17636
|
+
const accessScope = await loadAccessScope(request);
|
|
17122
17637
|
return {
|
|
17123
17638
|
ok: true,
|
|
17124
|
-
sources: await
|
|
17639
|
+
sources: await buildSyncSources(accessScope)
|
|
17125
17640
|
};
|
|
17126
17641
|
};
|
|
17127
|
-
const handleSyncAllSources = async (options) => {
|
|
17642
|
+
const handleSyncAllSources = async (request, options) => {
|
|
17128
17643
|
if (!indexManager?.syncAllSources) {
|
|
17129
17644
|
return {
|
|
17130
17645
|
error: "RAG source sync is not configured",
|
|
17131
17646
|
ok: false
|
|
17132
17647
|
};
|
|
17133
17648
|
}
|
|
17649
|
+
const accessScope = await loadAccessScope(request);
|
|
17650
|
+
if (accessScope?.allowedSyncSourceIds?.length) {
|
|
17651
|
+
return {
|
|
17652
|
+
error: "Scoped sync-all is not allowed; sync individual sources instead",
|
|
17653
|
+
ok: false
|
|
17654
|
+
};
|
|
17655
|
+
}
|
|
17134
17656
|
const job = createAdminJob("sync_all_sources", undefined, syncJobs);
|
|
17135
17657
|
const action = createAdminAction("sync_all_sources");
|
|
17136
17658
|
try {
|
|
@@ -17156,7 +17678,7 @@ var ragChat = (config) => {
|
|
|
17156
17678
|
completeAdminAction(action);
|
|
17157
17679
|
return {
|
|
17158
17680
|
ok: true,
|
|
17159
|
-
sources: await buildSyncSources()
|
|
17681
|
+
sources: await buildSyncSources(accessScope)
|
|
17160
17682
|
};
|
|
17161
17683
|
} catch (caught) {
|
|
17162
17684
|
const message = caught instanceof Error ? caught.message : String(caught);
|
|
@@ -17165,7 +17687,7 @@ var ragChat = (config) => {
|
|
|
17165
17687
|
throw caught;
|
|
17166
17688
|
}
|
|
17167
17689
|
};
|
|
17168
|
-
const handleSyncSource = async (id, options) => {
|
|
17690
|
+
const handleSyncSource = async (id, request, options) => {
|
|
17169
17691
|
if (!indexManager?.syncSource) {
|
|
17170
17692
|
return {
|
|
17171
17693
|
error: "RAG source sync is not configured",
|
|
@@ -17178,6 +17700,13 @@ var ragChat = (config) => {
|
|
|
17178
17700
|
ok: false
|
|
17179
17701
|
};
|
|
17180
17702
|
}
|
|
17703
|
+
const accessScope = await loadAccessScope(request);
|
|
17704
|
+
if (!matchesSyncSourceScope(accessScope, { id })) {
|
|
17705
|
+
return {
|
|
17706
|
+
error: "Sync source is outside the allowed RAG access scope",
|
|
17707
|
+
ok: false
|
|
17708
|
+
};
|
|
17709
|
+
}
|
|
17181
17710
|
const job = createAdminJob("sync_source", id, syncJobs);
|
|
17182
17711
|
const action = createAdminAction("sync_source", undefined, id);
|
|
17183
17712
|
try {
|
|
@@ -17194,7 +17723,7 @@ var ragChat = (config) => {
|
|
|
17194
17723
|
}
|
|
17195
17724
|
completeAdminJob(job);
|
|
17196
17725
|
completeAdminAction(action);
|
|
17197
|
-
const source = (await buildSyncSources()).find((record) => record.id === id);
|
|
17726
|
+
const source = (await buildSyncSources(accessScope)).find((record) => record.id === id);
|
|
17198
17727
|
return source ? { ok: true, source } : {
|
|
17199
17728
|
error: "sync source not found",
|
|
17200
17729
|
ok: false
|
|
@@ -17260,7 +17789,7 @@ var ragChat = (config) => {
|
|
|
17260
17789
|
};
|
|
17261
17790
|
return;
|
|
17262
17791
|
}
|
|
17263
|
-
const lastMessage = conversation.messages.findLast((
|
|
17792
|
+
const lastMessage = conversation.messages.findLast((message) => message.id === messageId && message.role === "user");
|
|
17264
17793
|
if (!lastMessage) {
|
|
17265
17794
|
yield {
|
|
17266
17795
|
data: renderers.error("Message not found"),
|
|
@@ -17304,7 +17833,7 @@ var ragChat = (config) => {
|
|
|
17304
17833
|
const controller = new AbortController;
|
|
17305
17834
|
abortControllers.set(conversationId, controller);
|
|
17306
17835
|
const history = buildHistory(conversation);
|
|
17307
|
-
const lastMessageIndex = conversation.messages.findIndex((
|
|
17836
|
+
const lastMessageIndex = conversation.messages.findIndex((message) => message.id === messageId);
|
|
17308
17837
|
const userHistory = lastMessageIndex >= 0 ? history.slice(0, lastMessageIndex) : history;
|
|
17309
17838
|
const messageWithContext = buildUserMessage2(content, lastMessage.attachments, ragContext);
|
|
17310
17839
|
const sseStream = streamAIToSSE(conversationId, assistantMessageId, {
|
|
@@ -17330,24 +17859,24 @@ var ragChat = (config) => {
|
|
|
17330
17859
|
};
|
|
17331
17860
|
return new Elysia2().ws(path, {
|
|
17332
17861
|
message: async (ws, raw) => {
|
|
17333
|
-
const
|
|
17334
|
-
if (!
|
|
17862
|
+
const message = parseAIMessage(raw);
|
|
17863
|
+
if (!message) {
|
|
17335
17864
|
return;
|
|
17336
17865
|
}
|
|
17337
|
-
if (
|
|
17338
|
-
handleCancel(
|
|
17866
|
+
if (message.type === "cancel") {
|
|
17867
|
+
handleCancel(message.conversationId);
|
|
17339
17868
|
return;
|
|
17340
17869
|
}
|
|
17341
|
-
if (
|
|
17342
|
-
await handleBranch(ws,
|
|
17870
|
+
if (message.type === "branch") {
|
|
17871
|
+
await handleBranch(ws, message.messageId, message.conversationId);
|
|
17343
17872
|
return;
|
|
17344
17873
|
}
|
|
17345
|
-
if (
|
|
17346
|
-
await handleMessage(ws,
|
|
17874
|
+
if (message.type === "message") {
|
|
17875
|
+
await handleMessage(ws, message.content, message.conversationId, message.attachments);
|
|
17347
17876
|
}
|
|
17348
17877
|
}
|
|
17349
17878
|
}).post(`${path}/search`, async ({ body, request, set }) => {
|
|
17350
|
-
const result = await handleSearch(body);
|
|
17879
|
+
const result = await handleSearch(body, request);
|
|
17351
17880
|
if (!result.ok) {
|
|
17352
17881
|
set.status = result.error === "Invalid payload" || result.error?.startsWith("Expected payload shape:") ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
17353
17882
|
}
|
|
@@ -17424,6 +17953,16 @@ var ragChat = (config) => {
|
|
|
17424
17953
|
}
|
|
17425
17954
|
return result;
|
|
17426
17955
|
}).post(`${path}/traces/prune`, async ({ body, request, set }) => {
|
|
17956
|
+
const denied = await authorizeMutationRoute(request, "prune_search_traces", {
|
|
17957
|
+
fallback: "Search trace pruning is not allowed"
|
|
17958
|
+
});
|
|
17959
|
+
if (denied) {
|
|
17960
|
+
set.status = 403;
|
|
17961
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
17962
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Search trace prune failed"), getNumericStatus(set.status));
|
|
17963
|
+
}
|
|
17964
|
+
return denied;
|
|
17965
|
+
}
|
|
17427
17966
|
const result = await handleTracePrune(body);
|
|
17428
17967
|
if (!result.ok) {
|
|
17429
17968
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17454,7 +17993,7 @@ var ragChat = (config) => {
|
|
|
17454
17993
|
}
|
|
17455
17994
|
return result;
|
|
17456
17995
|
}).post(`${path}/compare/retrieval`, async ({ body, request, set }) => {
|
|
17457
|
-
const result = await handleEvaluateRetrievals(body);
|
|
17996
|
+
const result = await handleEvaluateRetrievals(body, request);
|
|
17458
17997
|
if (!result.ok) {
|
|
17459
17998
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17460
17999
|
}
|
|
@@ -17469,7 +18008,7 @@ var ragChat = (config) => {
|
|
|
17469
18008
|
}
|
|
17470
18009
|
return result;
|
|
17471
18010
|
}).get(`${path}/compare/retrieval/history`, async ({ query, request, set }) => {
|
|
17472
|
-
const result = await handleRetrievalComparisonHistory(query);
|
|
18011
|
+
const result = await handleRetrievalComparisonHistory(query, request);
|
|
17473
18012
|
if (!result.ok) {
|
|
17474
18013
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17475
18014
|
}
|
|
@@ -17484,7 +18023,7 @@ var ragChat = (config) => {
|
|
|
17484
18023
|
}
|
|
17485
18024
|
return result;
|
|
17486
18025
|
}).get(`${path}/compare/retrieval/baselines`, async ({ query, request, set }) => {
|
|
17487
|
-
const result = await handleRetrievalBaselineList(query);
|
|
18026
|
+
const result = await handleRetrievalBaselineList(query, request);
|
|
17488
18027
|
if (!result.ok) {
|
|
17489
18028
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17490
18029
|
}
|
|
@@ -17499,7 +18038,7 @@ var ragChat = (config) => {
|
|
|
17499
18038
|
}
|
|
17500
18039
|
return result;
|
|
17501
18040
|
}).get(`${path}/compare/retrieval/baselines/decisions`, async ({ query, request, set }) => {
|
|
17502
|
-
const result = await handleRetrievalReleaseDecisionList(query);
|
|
18041
|
+
const result = await handleRetrievalReleaseDecisionList(query, request);
|
|
17503
18042
|
if (!result.ok) {
|
|
17504
18043
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17505
18044
|
}
|
|
@@ -17604,6 +18143,16 @@ var ragChat = (config) => {
|
|
|
17604
18143
|
}
|
|
17605
18144
|
return result;
|
|
17606
18145
|
}).post(`${path}/compare/retrieval/handoffs/incidents/acknowledge`, async ({ body, request, set }) => {
|
|
18146
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18147
|
+
fallback: "Retrieval lane handoff incident acknowledgement is not allowed"
|
|
18148
|
+
});
|
|
18149
|
+
if (denied) {
|
|
18150
|
+
set.status = 403;
|
|
18151
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18152
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident acknowledgement failed"), getNumericStatus(set.status));
|
|
18153
|
+
}
|
|
18154
|
+
return denied;
|
|
18155
|
+
}
|
|
17607
18156
|
const result = await handleRetrievalLaneHandoffIncidentAcknowledge(body);
|
|
17608
18157
|
if (!result.ok) {
|
|
17609
18158
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17619,6 +18168,16 @@ var ragChat = (config) => {
|
|
|
17619
18168
|
}
|
|
17620
18169
|
return result;
|
|
17621
18170
|
}).post(`${path}/compare/retrieval/handoffs/incidents/unacknowledge`, async ({ body, request, set }) => {
|
|
18171
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18172
|
+
fallback: "Retrieval lane handoff incident unacknowledge is not allowed"
|
|
18173
|
+
});
|
|
18174
|
+
if (denied) {
|
|
18175
|
+
set.status = 403;
|
|
18176
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18177
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident unacknowledge failed"), getNumericStatus(set.status));
|
|
18178
|
+
}
|
|
18179
|
+
return denied;
|
|
18180
|
+
}
|
|
17622
18181
|
const result = await handleRetrievalLaneHandoffIncidentUnacknowledge(body);
|
|
17623
18182
|
if (!result.ok) {
|
|
17624
18183
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17634,6 +18193,16 @@ var ragChat = (config) => {
|
|
|
17634
18193
|
}
|
|
17635
18194
|
return result;
|
|
17636
18195
|
}).post(`${path}/compare/retrieval/handoffs/incidents/resolve`, async ({ body, request, set }) => {
|
|
18196
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18197
|
+
fallback: "Retrieval lane handoff incident resolve is not allowed"
|
|
18198
|
+
});
|
|
18199
|
+
if (denied) {
|
|
18200
|
+
set.status = 403;
|
|
18201
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18202
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident resolve failed"), getNumericStatus(set.status));
|
|
18203
|
+
}
|
|
18204
|
+
return denied;
|
|
18205
|
+
}
|
|
17637
18206
|
const result = await handleResolveRetrievalLaneHandoffIncident(body);
|
|
17638
18207
|
if (!result.ok) {
|
|
17639
18208
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17649,6 +18218,16 @@ var ragChat = (config) => {
|
|
|
17649
18218
|
}
|
|
17650
18219
|
return result;
|
|
17651
18220
|
}).post(`${path}/compare/retrieval/handoffs/decide`, async ({ body, request, set }) => {
|
|
18221
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18222
|
+
fallback: "Retrieval lane handoff decision is not allowed"
|
|
18223
|
+
});
|
|
18224
|
+
if (denied) {
|
|
18225
|
+
set.status = 403;
|
|
18226
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18227
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff decision failed"), getNumericStatus(set.status));
|
|
18228
|
+
}
|
|
18229
|
+
return denied;
|
|
18230
|
+
}
|
|
17652
18231
|
const result = await handleRetrievalLaneHandoffDecision(body);
|
|
17653
18232
|
if (!result.ok) {
|
|
17654
18233
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17709,6 +18288,16 @@ var ragChat = (config) => {
|
|
|
17709
18288
|
}
|
|
17710
18289
|
return result;
|
|
17711
18290
|
}).post(`${path}/compare/retrieval/incidents/remediations`, async ({ body, request, set }) => {
|
|
18291
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18292
|
+
fallback: "Retrieval incident remediation decision record is not allowed"
|
|
18293
|
+
});
|
|
18294
|
+
if (denied) {
|
|
18295
|
+
set.status = 403;
|
|
18296
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18297
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval incident remediation decision record failed"), getNumericStatus(set.status));
|
|
18298
|
+
}
|
|
18299
|
+
return denied;
|
|
18300
|
+
}
|
|
17712
18301
|
const result = await handleRecordRetrievalIncidentRemediationDecision(body);
|
|
17713
18302
|
if (!result.ok) {
|
|
17714
18303
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17724,6 +18313,16 @@ var ragChat = (config) => {
|
|
|
17724
18313
|
}
|
|
17725
18314
|
return result;
|
|
17726
18315
|
}).post(`${path}/compare/retrieval/incidents/remediations/execute`, async ({ body, request, set }) => {
|
|
18316
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18317
|
+
fallback: "Retrieval incident remediation execution is not allowed"
|
|
18318
|
+
});
|
|
18319
|
+
if (denied) {
|
|
18320
|
+
set.status = 403;
|
|
18321
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18322
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval incident remediation execution failed"), getNumericStatus(set.status));
|
|
18323
|
+
}
|
|
18324
|
+
return denied;
|
|
18325
|
+
}
|
|
17727
18326
|
const result = await handleExecuteRetrievalIncidentRemediation(body);
|
|
17728
18327
|
if (!result.ok) {
|
|
17729
18328
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17739,6 +18338,16 @@ var ragChat = (config) => {
|
|
|
17739
18338
|
}
|
|
17740
18339
|
return result;
|
|
17741
18340
|
}).post(`${path}/compare/retrieval/incidents/remediations/execute/bulk`, async ({ body, request, set }) => {
|
|
18341
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18342
|
+
fallback: "Bulk retrieval incident remediation execution is not allowed"
|
|
18343
|
+
});
|
|
18344
|
+
if (denied) {
|
|
18345
|
+
set.status = 403;
|
|
18346
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18347
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Bulk retrieval incident remediation execution failed"), getNumericStatus(set.status));
|
|
18348
|
+
}
|
|
18349
|
+
return denied;
|
|
18350
|
+
}
|
|
17742
18351
|
const result = await handleBulkExecuteRetrievalIncidentRemediations(body);
|
|
17743
18352
|
if (!result.ok) {
|
|
17744
18353
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17754,6 +18363,16 @@ var ragChat = (config) => {
|
|
|
17754
18363
|
}
|
|
17755
18364
|
return result;
|
|
17756
18365
|
}).post(`${path}/compare/retrieval/incidents/acknowledge`, async ({ body, request, set }) => {
|
|
18366
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18367
|
+
fallback: "Retrieval release incident acknowledgement is not allowed"
|
|
18368
|
+
});
|
|
18369
|
+
if (denied) {
|
|
18370
|
+
set.status = 403;
|
|
18371
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18372
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident acknowledgement failed"), getNumericStatus(set.status));
|
|
18373
|
+
}
|
|
18374
|
+
return denied;
|
|
18375
|
+
}
|
|
17757
18376
|
const result = await handleAcknowledgeRetrievalReleaseIncident(body);
|
|
17758
18377
|
if (!result.ok) {
|
|
17759
18378
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17769,6 +18388,16 @@ var ragChat = (config) => {
|
|
|
17769
18388
|
}
|
|
17770
18389
|
return result;
|
|
17771
18390
|
}).post(`${path}/compare/retrieval/incidents/unacknowledge`, async ({ body, request, set }) => {
|
|
18391
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18392
|
+
fallback: "Retrieval release incident unacknowledge is not allowed"
|
|
18393
|
+
});
|
|
18394
|
+
if (denied) {
|
|
18395
|
+
set.status = 403;
|
|
18396
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18397
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident unacknowledge failed"), getNumericStatus(set.status));
|
|
18398
|
+
}
|
|
18399
|
+
return denied;
|
|
18400
|
+
}
|
|
17772
18401
|
const result = await handleUnacknowledgeRetrievalReleaseIncident(body);
|
|
17773
18402
|
if (!result.ok) {
|
|
17774
18403
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17784,6 +18413,16 @@ var ragChat = (config) => {
|
|
|
17784
18413
|
}
|
|
17785
18414
|
return result;
|
|
17786
18415
|
}).post(`${path}/compare/retrieval/incidents/resolve`, async ({ body, request, set }) => {
|
|
18416
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18417
|
+
fallback: "Retrieval release incident resolve is not allowed"
|
|
18418
|
+
});
|
|
18419
|
+
if (denied) {
|
|
18420
|
+
set.status = 403;
|
|
18421
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18422
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident resolve failed"), getNumericStatus(set.status));
|
|
18423
|
+
}
|
|
18424
|
+
return denied;
|
|
18425
|
+
}
|
|
17787
18426
|
const result = await handleResolveRetrievalReleaseIncident(body);
|
|
17788
18427
|
if (!result.ok) {
|
|
17789
18428
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17814,7 +18453,15 @@ var ragChat = (config) => {
|
|
|
17814
18453
|
}
|
|
17815
18454
|
return result;
|
|
17816
18455
|
}).post(`${path}/compare/retrieval/baselines/approve`, async ({ body, request, set }) => {
|
|
17817
|
-
const
|
|
18456
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval approval is not allowed" });
|
|
18457
|
+
if (denied) {
|
|
18458
|
+
set.status = 403;
|
|
18459
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18460
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval approval failed"), getNumericStatus(set.status));
|
|
18461
|
+
}
|
|
18462
|
+
return denied;
|
|
18463
|
+
}
|
|
18464
|
+
const result = await handleRetrievalReleaseDecisionAction(body, "approve", request);
|
|
17818
18465
|
if (!result.ok) {
|
|
17819
18466
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17820
18467
|
}
|
|
@@ -17829,7 +18476,15 @@ var ragChat = (config) => {
|
|
|
17829
18476
|
}
|
|
17830
18477
|
return result;
|
|
17831
18478
|
}).post(`${path}/compare/retrieval/baselines/reject`, async ({ body, request, set }) => {
|
|
17832
|
-
const
|
|
18479
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval rejection is not allowed" });
|
|
18480
|
+
if (denied) {
|
|
18481
|
+
set.status = 403;
|
|
18482
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18483
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval rejection failed"), getNumericStatus(set.status));
|
|
18484
|
+
}
|
|
18485
|
+
return denied;
|
|
18486
|
+
}
|
|
18487
|
+
const result = await handleRetrievalReleaseDecisionAction(body, "reject", request);
|
|
17833
18488
|
if (!result.ok) {
|
|
17834
18489
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17835
18490
|
}
|
|
@@ -17844,7 +18499,15 @@ var ragChat = (config) => {
|
|
|
17844
18499
|
}
|
|
17845
18500
|
return result;
|
|
17846
18501
|
}).post(`${path}/compare/retrieval/baselines/promote`, async ({ body, request, set }) => {
|
|
17847
|
-
const
|
|
18502
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval baseline promotion is not allowed" });
|
|
18503
|
+
if (denied) {
|
|
18504
|
+
set.status = 403;
|
|
18505
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18506
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline promotion failed"), getNumericStatus(set.status));
|
|
18507
|
+
}
|
|
18508
|
+
return denied;
|
|
18509
|
+
}
|
|
18510
|
+
const result = await handlePromoteRetrievalBaseline(body, request);
|
|
17848
18511
|
if (!result.ok) {
|
|
17849
18512
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17850
18513
|
}
|
|
@@ -17859,6 +18522,16 @@ var ragChat = (config) => {
|
|
|
17859
18522
|
}
|
|
17860
18523
|
return result;
|
|
17861
18524
|
}).post(`${path}/compare/retrieval/baselines/promote-lane`, async ({ body, request, set }) => {
|
|
18525
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18526
|
+
fallback: "Retrieval rollout-lane promotion is not allowed"
|
|
18527
|
+
});
|
|
18528
|
+
if (denied) {
|
|
18529
|
+
set.status = 403;
|
|
18530
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18531
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval rollout-lane promotion failed"), getNumericStatus(set.status));
|
|
18532
|
+
}
|
|
18533
|
+
return denied;
|
|
18534
|
+
}
|
|
17862
18535
|
const result = await handlePromoteRetrievalBaselineToLane(body);
|
|
17863
18536
|
if (!result.ok) {
|
|
17864
18537
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17874,7 +18547,17 @@ var ragChat = (config) => {
|
|
|
17874
18547
|
}
|
|
17875
18548
|
return result;
|
|
17876
18549
|
}).post(`${path}/compare/retrieval/baselines/promote-run`, async ({ body, request, set }) => {
|
|
17877
|
-
const
|
|
18550
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18551
|
+
fallback: "Retrieval baseline promotion from run is not allowed"
|
|
18552
|
+
});
|
|
18553
|
+
if (denied) {
|
|
18554
|
+
set.status = 403;
|
|
18555
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18556
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline promotion from run failed"), getNumericStatus(set.status));
|
|
18557
|
+
}
|
|
18558
|
+
return denied;
|
|
18559
|
+
}
|
|
18560
|
+
const result = await handlePromoteRetrievalBaselineFromRun(body, request);
|
|
17878
18561
|
if (!result.ok) {
|
|
17879
18562
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17880
18563
|
}
|
|
@@ -17889,7 +18572,15 @@ var ragChat = (config) => {
|
|
|
17889
18572
|
}
|
|
17890
18573
|
return result;
|
|
17891
18574
|
}).post(`${path}/compare/retrieval/baselines/revert`, async ({ body, request, set }) => {
|
|
17892
|
-
const
|
|
18575
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval baseline revert is not allowed" });
|
|
18576
|
+
if (denied) {
|
|
18577
|
+
set.status = 403;
|
|
18578
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18579
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline revert failed"), getNumericStatus(set.status));
|
|
18580
|
+
}
|
|
18581
|
+
return denied;
|
|
18582
|
+
}
|
|
18583
|
+
const result = await handleRevertRetrievalBaseline(body, request);
|
|
17893
18584
|
if (!result.ok) {
|
|
17894
18585
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17895
18586
|
}
|
|
@@ -17904,7 +18595,7 @@ var ragChat = (config) => {
|
|
|
17904
18595
|
}
|
|
17905
18596
|
return result;
|
|
17906
18597
|
}).post(`${path}/evaluate`, async ({ body, request, set }) => {
|
|
17907
|
-
const result = await handleEvaluate(body);
|
|
18598
|
+
const result = await handleEvaluate(body, request);
|
|
17908
18599
|
if (!result.ok) {
|
|
17909
18600
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17910
18601
|
}
|
|
@@ -17919,7 +18610,7 @@ var ragChat = (config) => {
|
|
|
17919
18610
|
}
|
|
17920
18611
|
return result;
|
|
17921
18612
|
}).get(`${path}/status`, async ({ request }) => {
|
|
17922
|
-
const result = await handleStatus();
|
|
18613
|
+
const result = await handleStatus(request);
|
|
17923
18614
|
if (config.htmx && isHTMXRequest(request)) {
|
|
17924
18615
|
return toHTMXResponse(workflowRenderers.status({
|
|
17925
18616
|
capabilities: result.capabilities,
|
|
@@ -17988,20 +18679,21 @@ var ragChat = (config) => {
|
|
|
17988
18679
|
});
|
|
17989
18680
|
}
|
|
17990
18681
|
return result;
|
|
17991
|
-
}).get(`${path}/status/release`, async () => {
|
|
17992
|
-
return handleRetrievalReleaseStatus();
|
|
18682
|
+
}).get(`${path}/status/release`, async ({ request }) => {
|
|
18683
|
+
return handleRetrievalReleaseStatus(request);
|
|
17993
18684
|
}).get(`${path}/status/release/incidents`, async () => {
|
|
17994
18685
|
return handleRetrievalReleaseIncidentStatus();
|
|
17995
18686
|
}).get(`${path}/status/release/remediations`, async () => {
|
|
17996
18687
|
return handleRetrievalIncidentRemediationStatus();
|
|
17997
|
-
}).get(`${path}/status/release/drift`, async () => {
|
|
17998
|
-
return handleRetrievalReleaseDriftStatus();
|
|
17999
|
-
}).get(`${path}/status/handoffs/incidents`, async () => {
|
|
18000
|
-
return handleRetrievalLaneHandoffIncidentStatus();
|
|
18001
|
-
}).get(`${path}/status/handoffs`, async () => {
|
|
18002
|
-
return handleRetrievalLaneHandoffStatus();
|
|
18688
|
+
}).get(`${path}/status/release/drift`, async ({ request }) => {
|
|
18689
|
+
return handleRetrievalReleaseDriftStatus(request);
|
|
18690
|
+
}).get(`${path}/status/handoffs/incidents`, async ({ request }) => {
|
|
18691
|
+
return handleRetrievalLaneHandoffIncidentStatus(request);
|
|
18692
|
+
}).get(`${path}/status/handoffs`, async ({ request }) => {
|
|
18693
|
+
return handleRetrievalLaneHandoffStatus(request);
|
|
18003
18694
|
}).get(`${path}/ops`, async ({ request }) => {
|
|
18004
|
-
|
|
18695
|
+
await ensureJobStateLoaded();
|
|
18696
|
+
const result = await handleOps(request);
|
|
18005
18697
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18006
18698
|
return toHTMXResponse(workflowRenderers.status({
|
|
18007
18699
|
capabilities: result.capabilities,
|
|
@@ -18011,7 +18703,7 @@ var ragChat = (config) => {
|
|
|
18011
18703
|
}
|
|
18012
18704
|
return result;
|
|
18013
18705
|
}).get(`${path}/documents`, async ({ query, request, set }) => {
|
|
18014
|
-
const result = await handleDocuments(getStringProperty(query, "kind"));
|
|
18706
|
+
const result = await handleDocuments(getStringProperty(query, "kind"), request);
|
|
18015
18707
|
if (!result.ok) {
|
|
18016
18708
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18017
18709
|
}
|
|
@@ -18025,9 +18717,19 @@ var ragChat = (config) => {
|
|
|
18025
18717
|
}
|
|
18026
18718
|
return result;
|
|
18027
18719
|
}).post(`${path}/documents`, async ({ body, request, set }) => {
|
|
18028
|
-
|
|
18720
|
+
await ensureJobStateLoaded();
|
|
18721
|
+
const authorization = await checkAuthorization(request, "create_document");
|
|
18722
|
+
if (!authorization.allowed) {
|
|
18723
|
+
set.status = 403;
|
|
18724
|
+
const result2 = buildAuthorizationFailure(authorization, "Document creation is not allowed");
|
|
18725
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18726
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to create document"), getNumericStatus(set.status));
|
|
18727
|
+
}
|
|
18728
|
+
return result2;
|
|
18729
|
+
}
|
|
18730
|
+
const result = await handleCreateDocument(body, request);
|
|
18029
18731
|
if (!result.ok) {
|
|
18030
|
-
const status = result.error?.includes("not configured") ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_BAD_REQUEST;
|
|
18732
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error?.includes("not configured") ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_BAD_REQUEST;
|
|
18031
18733
|
set.status = status;
|
|
18032
18734
|
}
|
|
18033
18735
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18038,9 +18740,9 @@ var ragChat = (config) => {
|
|
|
18038
18740
|
}
|
|
18039
18741
|
return result;
|
|
18040
18742
|
}).get(`${path}/documents/:id/chunks`, async ({ params, request, set }) => {
|
|
18041
|
-
const result = await handleDocumentChunks(typeof params.id === "string" ? params.id.trim() : "");
|
|
18743
|
+
const result = await handleDocumentChunks(typeof params.id === "string" ? params.id.trim() : "", request);
|
|
18042
18744
|
if (!result.ok) {
|
|
18043
|
-
const status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18745
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18044
18746
|
set.status = status;
|
|
18045
18747
|
}
|
|
18046
18748
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18054,10 +18756,13 @@ var ragChat = (config) => {
|
|
|
18054
18756
|
const result = await handleBackends();
|
|
18055
18757
|
if (!result.ok) {
|
|
18056
18758
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18759
|
+
if (isAccessScopeError(result.error)) {
|
|
18760
|
+
set.status = 403;
|
|
18761
|
+
}
|
|
18057
18762
|
}
|
|
18058
18763
|
return result;
|
|
18059
18764
|
}).get(`${path}/sync`, async ({ request, set }) => {
|
|
18060
|
-
const result = await handleSyncSources();
|
|
18765
|
+
const result = await handleSyncSources(request);
|
|
18061
18766
|
if (!result.ok) {
|
|
18062
18767
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18063
18768
|
}
|
|
@@ -18072,8 +18777,18 @@ var ragChat = (config) => {
|
|
|
18072
18777
|
}
|
|
18073
18778
|
return result;
|
|
18074
18779
|
}).post(`${path}/sync`, async ({ body, request, set }) => {
|
|
18780
|
+
await ensureJobStateLoaded();
|
|
18781
|
+
const authorization = await checkAuthorization(request, "sync_all_sources");
|
|
18782
|
+
if (!authorization.allowed) {
|
|
18783
|
+
set.status = 403;
|
|
18784
|
+
const result2 = buildAuthorizationFailure(authorization, "Source sync is not allowed");
|
|
18785
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18786
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to sync sources"), getNumericStatus(set.status));
|
|
18787
|
+
}
|
|
18788
|
+
return result2;
|
|
18789
|
+
}
|
|
18075
18790
|
const background = getBooleanProperty(body, "background");
|
|
18076
|
-
const result = await handleSyncAllSources({ background });
|
|
18791
|
+
const result = await handleSyncAllSources(request, { background });
|
|
18077
18792
|
if (!result.ok) {
|
|
18078
18793
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18079
18794
|
}
|
|
@@ -18088,10 +18803,28 @@ var ragChat = (config) => {
|
|
|
18088
18803
|
}
|
|
18089
18804
|
return result;
|
|
18090
18805
|
}).post(`${path}/sync/:id`, async ({ body, params, request, set }) => {
|
|
18806
|
+
await ensureJobStateLoaded();
|
|
18807
|
+
const syncSourceId = typeof params.id === "string" ? params.id.trim() : "";
|
|
18808
|
+
const authorization = await checkAuthorization(request, "sync_source", {
|
|
18809
|
+
sourceId: syncSourceId
|
|
18810
|
+
});
|
|
18811
|
+
if (!authorization.allowed) {
|
|
18812
|
+
set.status = 403;
|
|
18813
|
+
const result2 = buildAuthorizationFailure(authorization, "Source sync is not allowed");
|
|
18814
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18815
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to sync source"), getNumericStatus(set.status));
|
|
18816
|
+
}
|
|
18817
|
+
return result2;
|
|
18818
|
+
}
|
|
18091
18819
|
const background = getBooleanProperty(body, "background");
|
|
18092
|
-
const result = await handleSyncSource(
|
|
18820
|
+
const result = await handleSyncSource(syncSourceId, request, {
|
|
18821
|
+
background
|
|
18822
|
+
});
|
|
18093
18823
|
if (!result.ok) {
|
|
18094
18824
|
set.status = result.error === "sync source id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18825
|
+
if (isAccessScopeError(result.error)) {
|
|
18826
|
+
set.status = 403;
|
|
18827
|
+
}
|
|
18095
18828
|
}
|
|
18096
18829
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18097
18830
|
const html = result.ok ? workflowRenderers.mutationResult({
|
|
@@ -18104,6 +18837,18 @@ var ragChat = (config) => {
|
|
|
18104
18837
|
}
|
|
18105
18838
|
return result;
|
|
18106
18839
|
}).post(`${path}/ingest`, async ({ body, request, set }) => {
|
|
18840
|
+
await ensureJobStateLoaded();
|
|
18841
|
+
const authorization = await checkAuthorization(request, "ingest", {
|
|
18842
|
+
path: `${path}/ingest`
|
|
18843
|
+
});
|
|
18844
|
+
if (!authorization.allowed) {
|
|
18845
|
+
set.status = 403;
|
|
18846
|
+
const result2 = buildAuthorizationFailure(authorization, "RAG ingest is not allowed");
|
|
18847
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18848
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "RAG ingest failed"), getNumericStatus(set.status));
|
|
18849
|
+
}
|
|
18850
|
+
return result2;
|
|
18851
|
+
}
|
|
18107
18852
|
const result = await handleIngest(body);
|
|
18108
18853
|
if (!result.ok) {
|
|
18109
18854
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -18115,7 +18860,13 @@ var ragChat = (config) => {
|
|
|
18115
18860
|
return toHTMXResponse(workflowRenderers.mutationResult(result), HTTP_STATUS_OK, { "HX-Trigger": "rag:mutated" });
|
|
18116
18861
|
}
|
|
18117
18862
|
return result;
|
|
18118
|
-
}).delete(`${path}/index`, async () => {
|
|
18863
|
+
}).delete(`${path}/index`, async ({ request, set }) => {
|
|
18864
|
+
await ensureJobStateLoaded();
|
|
18865
|
+
const authorization = await checkAuthorization(request, "clear_index");
|
|
18866
|
+
if (!authorization.allowed) {
|
|
18867
|
+
set.status = 403;
|
|
18868
|
+
return buildAuthorizationFailure(authorization, "Index clearing is not allowed");
|
|
18869
|
+
}
|
|
18119
18870
|
if (!ragStore) {
|
|
18120
18871
|
return { ok: false };
|
|
18121
18872
|
}
|
|
@@ -18134,9 +18885,22 @@ var ragChat = (config) => {
|
|
|
18134
18885
|
}
|
|
18135
18886
|
return { ok: true };
|
|
18136
18887
|
}).delete(`${path}/documents/:id`, async ({ params, request, set }) => {
|
|
18137
|
-
|
|
18888
|
+
await ensureJobStateLoaded();
|
|
18889
|
+
const documentId = typeof params.id === "string" ? params.id.trim() : "";
|
|
18890
|
+
const authorization = await checkAuthorization(request, "delete_document", {
|
|
18891
|
+
documentId
|
|
18892
|
+
});
|
|
18893
|
+
if (!authorization.allowed) {
|
|
18894
|
+
set.status = 403;
|
|
18895
|
+
const result2 = buildAuthorizationFailure(authorization, "Document deletion is not allowed");
|
|
18896
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18897
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to delete document"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
18898
|
+
}
|
|
18899
|
+
return result2;
|
|
18900
|
+
}
|
|
18901
|
+
const result = await handleDeleteDocument(documentId, request);
|
|
18138
18902
|
if (!result.ok) {
|
|
18139
|
-
const status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18903
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18140
18904
|
set.status = status;
|
|
18141
18905
|
}
|
|
18142
18906
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18147,9 +18911,20 @@ var ragChat = (config) => {
|
|
|
18147
18911
|
}
|
|
18148
18912
|
return result;
|
|
18149
18913
|
}).post(`${path}/reindex/documents/:id`, async ({ params, request, set }) => {
|
|
18150
|
-
|
|
18914
|
+
await ensureJobStateLoaded();
|
|
18915
|
+
const documentId = typeof params.id === "string" ? params.id.trim() : "";
|
|
18916
|
+
const authorization = await checkAuthorization(request, "reindex_document", { documentId });
|
|
18917
|
+
if (!authorization.allowed) {
|
|
18918
|
+
set.status = 403;
|
|
18919
|
+
const result2 = buildAuthorizationFailure(authorization, "Document reindex is not allowed");
|
|
18920
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18921
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reindex document"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
18922
|
+
}
|
|
18923
|
+
return result2;
|
|
18924
|
+
}
|
|
18925
|
+
const result = await handleReindexDocument(documentId, request);
|
|
18151
18926
|
if (!result.ok) {
|
|
18152
|
-
set.status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18927
|
+
set.status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18153
18928
|
}
|
|
18154
18929
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18155
18930
|
const html = result.ok ? workflowRenderers.mutationResult(result) : workflowRenderers.error(result.error ?? "Failed to reindex document");
|
|
@@ -18159,10 +18934,22 @@ var ragChat = (config) => {
|
|
|
18159
18934
|
}
|
|
18160
18935
|
return result;
|
|
18161
18936
|
}).post(`${path}/reindex/source`, async ({ body, request, set }) => {
|
|
18937
|
+
await ensureJobStateLoaded();
|
|
18162
18938
|
const source = getStringProperty(body, "source")?.trim() ?? "";
|
|
18163
|
-
const
|
|
18939
|
+
const authorization = await checkAuthorization(request, "reindex_source", {
|
|
18940
|
+
source
|
|
18941
|
+
});
|
|
18942
|
+
if (!authorization.allowed) {
|
|
18943
|
+
set.status = 403;
|
|
18944
|
+
const result2 = buildAuthorizationFailure(authorization, "Source reindex is not allowed");
|
|
18945
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18946
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reindex source"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
18947
|
+
}
|
|
18948
|
+
return result2;
|
|
18949
|
+
}
|
|
18950
|
+
const result = await handleReindexSource(source, request);
|
|
18164
18951
|
if (!result.ok) {
|
|
18165
|
-
set.status = result.error === "source is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18952
|
+
set.status = isAccessScopeError(result.error) ? 403 : result.error === "source is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18166
18953
|
}
|
|
18167
18954
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18168
18955
|
const html = result.ok ? workflowRenderers.mutationResult(result) : workflowRenderers.error(result.error ?? "Failed to reindex source");
|
|
@@ -18172,6 +18959,16 @@ var ragChat = (config) => {
|
|
|
18172
18959
|
}
|
|
18173
18960
|
return result;
|
|
18174
18961
|
}).post(`${path}/reseed`, async ({ request, set }) => {
|
|
18962
|
+
await ensureJobStateLoaded();
|
|
18963
|
+
const authorization = await checkAuthorization(request, "reseed");
|
|
18964
|
+
if (!authorization.allowed) {
|
|
18965
|
+
set.status = 403;
|
|
18966
|
+
const result2 = buildAuthorizationFailure(authorization, "Index reseed is not allowed");
|
|
18967
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18968
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reseed index"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
18969
|
+
}
|
|
18970
|
+
return result2;
|
|
18971
|
+
}
|
|
18175
18972
|
const result = await handleReseed();
|
|
18176
18973
|
if (!result.ok) {
|
|
18177
18974
|
set.status = 404;
|
|
@@ -18184,6 +18981,16 @@ var ragChat = (config) => {
|
|
|
18184
18981
|
}
|
|
18185
18982
|
return result;
|
|
18186
18983
|
}).post(`${path}/reset`, async ({ request, set }) => {
|
|
18984
|
+
await ensureJobStateLoaded();
|
|
18985
|
+
const authorization = await checkAuthorization(request, "reset");
|
|
18986
|
+
if (!authorization.allowed) {
|
|
18987
|
+
set.status = 403;
|
|
18988
|
+
const result2 = buildAuthorizationFailure(authorization, "Index reset is not allowed");
|
|
18989
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18990
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reset index"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
18991
|
+
}
|
|
18992
|
+
return result2;
|
|
18993
|
+
}
|
|
18187
18994
|
const result = await handleReset();
|
|
18188
18995
|
if (!result.ok) {
|
|
18189
18996
|
set.status = 404;
|
|
@@ -18271,6 +19078,31 @@ var createHeuristicRAGRetrievalStrategy = (options = {}) => ({
|
|
|
18271
19078
|
return;
|
|
18272
19079
|
}
|
|
18273
19080
|
});
|
|
19081
|
+
// src/ai/rag/accessControl.ts
|
|
19082
|
+
var createRAGAccessControl = (options) => {
|
|
19083
|
+
const authorize = options.authorize;
|
|
19084
|
+
const contextCache = new WeakMap;
|
|
19085
|
+
const resolveScope = options.resolveScope;
|
|
19086
|
+
const loadContext = (request) => {
|
|
19087
|
+
const existing = contextCache.get(request);
|
|
19088
|
+
if (existing) {
|
|
19089
|
+
return existing;
|
|
19090
|
+
}
|
|
19091
|
+
const next = Promise.resolve(options.resolveContext(request));
|
|
19092
|
+
contextCache.set(request, next);
|
|
19093
|
+
return next;
|
|
19094
|
+
};
|
|
19095
|
+
return {
|
|
19096
|
+
authorizeRAGAction: authorize ? async (input) => authorize({
|
|
19097
|
+
...input,
|
|
19098
|
+
context: await loadContext(input.request)
|
|
19099
|
+
}) : undefined,
|
|
19100
|
+
resolveRAGAccessScope: resolveScope ? async (request) => resolveScope({
|
|
19101
|
+
context: await loadContext(request),
|
|
19102
|
+
request
|
|
19103
|
+
}) : undefined
|
|
19104
|
+
};
|
|
19105
|
+
};
|
|
18274
19106
|
// src/ai/rag/embeddingProviders.ts
|
|
18275
19107
|
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com";
|
|
18276
19108
|
var DEFAULT_GEMINI_BASE_URL = "https://generativelanguage.googleapis.com";
|
|
@@ -19128,6 +19960,8 @@ var isManagedBySyncSource = (document, sourceId) => document.metadata?.syncSourc
|
|
|
19128
19960
|
var getDocumentSyncFingerprint = (document) => typeof document.metadata?.syncFingerprint === "string" ? document.metadata.syncFingerprint : undefined;
|
|
19129
19961
|
var reconcileManagedDocuments = async (input) => {
|
|
19130
19962
|
const prepared = prepareRAGDocuments({
|
|
19963
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
19964
|
+
defaultChunking: input.defaultChunking,
|
|
19131
19965
|
documents: input.documents
|
|
19132
19966
|
});
|
|
19133
19967
|
const nextDocumentIds = new Set(prepared.map((document) => document.documentId));
|
|
@@ -19172,6 +20006,19 @@ var toSourceRecord = (source, overrides) => ({
|
|
|
19172
20006
|
target: source.target,
|
|
19173
20007
|
...overrides
|
|
19174
20008
|
});
|
|
20009
|
+
var recoverSyncSourceRecord = (source, record, recoveredAt) => record.status === "running" ? toSourceRecord(source, {
|
|
20010
|
+
...record,
|
|
20011
|
+
lastError: record.lastError ?? "Interrupted before completion during recovery",
|
|
20012
|
+
lastSyncedAt: recoveredAt,
|
|
20013
|
+
nextRetryAt: undefined,
|
|
20014
|
+
status: "failed"
|
|
20015
|
+
}) : toSourceRecord(source, {
|
|
20016
|
+
...record,
|
|
20017
|
+
metadata: {
|
|
20018
|
+
...source.metadata ?? {},
|
|
20019
|
+
...record.metadata ?? {}
|
|
20020
|
+
}
|
|
20021
|
+
});
|
|
19175
20022
|
var createRAGDirectorySyncSource = (options) => ({
|
|
19176
20023
|
description: options.description,
|
|
19177
20024
|
id: options.id,
|
|
@@ -19185,14 +20032,18 @@ var createRAGDirectorySyncSource = (options) => ({
|
|
|
19185
20032
|
const loaded = await loadRAGDocumentsFromDirectory({
|
|
19186
20033
|
baseMetadata: options.baseMetadata,
|
|
19187
20034
|
defaultChunking: options.defaultChunking,
|
|
20035
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19188
20036
|
directory: options.directory,
|
|
19189
20037
|
extractors: options.extractors,
|
|
20038
|
+
extractorRegistry: options.extractorRegistry,
|
|
19190
20039
|
includeExtensions: options.includeExtensions,
|
|
19191
20040
|
recursive: options.recursive
|
|
19192
20041
|
});
|
|
19193
20042
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.relativePath === "string" ? document.metadata.relativePath : document.source ?? document.title ?? ""));
|
|
19194
20043
|
const reconciled = await reconcileManagedDocuments({
|
|
20044
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19195
20045
|
collection,
|
|
20046
|
+
defaultChunking: options.defaultChunking,
|
|
19196
20047
|
deleteDocument,
|
|
19197
20048
|
documents: managedDocuments,
|
|
19198
20049
|
listDocuments,
|
|
@@ -19223,12 +20074,16 @@ var createRAGUrlSyncSource = (options) => ({
|
|
|
19223
20074
|
const loaded = await loadRAGDocumentsFromURLs({
|
|
19224
20075
|
baseMetadata: options.baseMetadata,
|
|
19225
20076
|
defaultChunking: options.defaultChunking,
|
|
20077
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19226
20078
|
extractors: options.extractors,
|
|
20079
|
+
extractorRegistry: options.extractorRegistry,
|
|
19227
20080
|
urls: options.urls
|
|
19228
20081
|
});
|
|
19229
20082
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.sourceUrl === "string" ? document.metadata.sourceUrl : document.source ?? document.title ?? ""));
|
|
19230
20083
|
const reconciled = await reconcileManagedDocuments({
|
|
20084
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19231
20085
|
collection,
|
|
20086
|
+
defaultChunking: options.defaultChunking,
|
|
19232
20087
|
deleteDocument,
|
|
19233
20088
|
documents: managedDocuments,
|
|
19234
20089
|
listDocuments,
|
|
@@ -19326,12 +20181,16 @@ var createRAGStorageSyncSource = (options) => ({
|
|
|
19326
20181
|
const loaded = await loadRAGDocumentsFromUploads({
|
|
19327
20182
|
baseMetadata: options.baseMetadata,
|
|
19328
20183
|
defaultChunking: options.defaultChunking,
|
|
20184
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19329
20185
|
extractors: options.extractors,
|
|
20186
|
+
extractorRegistry: options.extractorRegistry,
|
|
19330
20187
|
uploads
|
|
19331
20188
|
});
|
|
19332
20189
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.storageKey === "string" ? document.metadata.storageKey : document.source ?? document.title ?? ""));
|
|
19333
20190
|
const reconciled = await reconcileManagedDocuments({
|
|
20191
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19334
20192
|
collection,
|
|
20193
|
+
defaultChunking: options.defaultChunking,
|
|
19335
20194
|
deleteDocument,
|
|
19336
20195
|
documents: managedDocuments,
|
|
19337
20196
|
listDocuments,
|
|
@@ -19412,7 +20271,9 @@ var createRAGEmailSyncSource = (options) => ({
|
|
|
19412
20271
|
const loadedAttachments = attachmentUploads.length > 0 ? await loadRAGDocumentsFromUploads({
|
|
19413
20272
|
baseMetadata: options.baseMetadata,
|
|
19414
20273
|
defaultChunking: options.defaultChunking,
|
|
20274
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19415
20275
|
extractors: options.extractors,
|
|
20276
|
+
extractorRegistry: options.extractorRegistry,
|
|
19416
20277
|
uploads: attachmentUploads
|
|
19417
20278
|
}) : { documents: [] };
|
|
19418
20279
|
const managedDocuments = [
|
|
@@ -19420,7 +20281,9 @@ var createRAGEmailSyncSource = (options) => ({
|
|
|
19420
20281
|
...loadedAttachments.documents.map((document) => toManagedSyncDocument(options.id, document, `attachment:${String(document.metadata?.attachmentId ?? document.source ?? document.title ?? "")}`))
|
|
19421
20282
|
];
|
|
19422
20283
|
const reconciled = await reconcileManagedDocuments({
|
|
20284
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19423
20285
|
collection,
|
|
20286
|
+
defaultChunking: options.defaultChunking,
|
|
19424
20287
|
deleteDocument,
|
|
19425
20288
|
documents: managedDocuments,
|
|
19426
20289
|
listDocuments,
|
|
@@ -19455,22 +20318,18 @@ var createRAGSyncManager = (options) => {
|
|
|
19455
20318
|
}
|
|
19456
20319
|
if (!hydrationPromise) {
|
|
19457
20320
|
hydrationPromise = Promise.resolve(options.loadState()).then((records) => {
|
|
20321
|
+
const recoveredAt = Date.now();
|
|
19458
20322
|
for (const record of records ?? []) {
|
|
19459
20323
|
const source = sourceMap.get(record.id);
|
|
19460
20324
|
if (!source) {
|
|
19461
20325
|
continue;
|
|
19462
20326
|
}
|
|
19463
|
-
state.set(record.id,
|
|
19464
|
-
...record,
|
|
19465
|
-
metadata: {
|
|
19466
|
-
...source.metadata ?? {},
|
|
19467
|
-
...record.metadata ?? {}
|
|
19468
|
-
}
|
|
19469
|
-
}));
|
|
20327
|
+
state.set(record.id, recoverSyncSourceRecord(source, record, recoveredAt));
|
|
19470
20328
|
}
|
|
19471
20329
|
});
|
|
19472
20330
|
}
|
|
19473
20331
|
await hydrationPromise;
|
|
20332
|
+
await persistState();
|
|
19474
20333
|
};
|
|
19475
20334
|
const resolveRetryAttempts = (source) => Math.max(0, source.retryAttempts ?? options.retryAttempts ?? 0);
|
|
19476
20335
|
const resolveRetryDelayMs = (source) => Math.max(0, source.retryDelayMs ?? options.retryDelayMs ?? 0);
|
|
@@ -19716,6 +20575,48 @@ var createRAGSyncScheduler = (input) => {
|
|
|
19716
20575
|
listSchedules: () => [...input.schedules]
|
|
19717
20576
|
};
|
|
19718
20577
|
};
|
|
20578
|
+
// src/ai/rag/jobState.ts
|
|
20579
|
+
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
20580
|
+
import { dirname as dirname3, resolve as resolve3 } from "path";
|
|
20581
|
+
var parseJobState = (content) => {
|
|
20582
|
+
try {
|
|
20583
|
+
const parsed = JSON.parse(content);
|
|
20584
|
+
return {
|
|
20585
|
+
adminActions: Array.isArray(parsed.adminActions) ? parsed.adminActions : [],
|
|
20586
|
+
adminJobs: Array.isArray(parsed.adminJobs) ? parsed.adminJobs : [],
|
|
20587
|
+
ingestJobs: Array.isArray(parsed.ingestJobs) ? parsed.ingestJobs : [],
|
|
20588
|
+
syncJobs: Array.isArray(parsed.syncJobs) ? parsed.syncJobs : []
|
|
20589
|
+
};
|
|
20590
|
+
} catch {
|
|
20591
|
+
return {
|
|
20592
|
+
adminActions: [],
|
|
20593
|
+
adminJobs: [],
|
|
20594
|
+
ingestJobs: [],
|
|
20595
|
+
syncJobs: []
|
|
20596
|
+
};
|
|
20597
|
+
}
|
|
20598
|
+
};
|
|
20599
|
+
var createRAGFileJobStateStore = (path) => {
|
|
20600
|
+
const resolvedPath = resolve3(path);
|
|
20601
|
+
return {
|
|
20602
|
+
load: async () => {
|
|
20603
|
+
try {
|
|
20604
|
+
return parseJobState(await readFile4(resolvedPath, "utf8"));
|
|
20605
|
+
} catch {
|
|
20606
|
+
return {
|
|
20607
|
+
adminActions: [],
|
|
20608
|
+
adminJobs: [],
|
|
20609
|
+
ingestJobs: [],
|
|
20610
|
+
syncJobs: []
|
|
20611
|
+
};
|
|
20612
|
+
}
|
|
20613
|
+
},
|
|
20614
|
+
save: async (state) => {
|
|
20615
|
+
await mkdir3(dirname3(resolvedPath), { recursive: true });
|
|
20616
|
+
await writeFile3(resolvedPath, JSON.stringify(state, null, 2), "utf8");
|
|
20617
|
+
}
|
|
20618
|
+
};
|
|
20619
|
+
};
|
|
19719
20620
|
// src/ai/rag/adapters/utils.ts
|
|
19720
20621
|
var vectorDimensionDefault = 24;
|
|
19721
20622
|
var createRAGVector = (text, dimensions = vectorDimensionDefault) => {
|
|
@@ -19874,7 +20775,7 @@ import { existsSync as existsSync2 } from "fs";
|
|
|
19874
20775
|
// src/ai/rag/resolveAbsoluteSQLiteVec.ts
|
|
19875
20776
|
import { existsSync, readFileSync } from "fs";
|
|
19876
20777
|
import { arch, platform } from "os";
|
|
19877
|
-
import { dirname as
|
|
20778
|
+
import { dirname as dirname4, join as join2 } from "path";
|
|
19878
20779
|
var PLATFORM_PACKAGE_MAP = {
|
|
19879
20780
|
"darwin-arm64": {
|
|
19880
20781
|
libraryFile: "vec0.dylib",
|
|
@@ -19923,12 +20824,12 @@ var resolveAbsoluteSQLiteVec = () => {
|
|
|
19923
20824
|
};
|
|
19924
20825
|
}
|
|
19925
20826
|
try {
|
|
19926
|
-
const
|
|
19927
|
-
if (typeof
|
|
20827
|
+
const resolve4 = import.meta.resolve;
|
|
20828
|
+
if (typeof resolve4 !== "function") {
|
|
19928
20829
|
throw new Error("AbsoluteJS sqlite-vec package resolution requires import.meta.resolve support.");
|
|
19929
20830
|
}
|
|
19930
|
-
const packageJsonPath = new URL(
|
|
19931
|
-
const packageRoot =
|
|
20831
|
+
const packageJsonPath = new URL(resolve4(`${packageInfo.packageName}/package.json`)).pathname;
|
|
20832
|
+
const packageRoot = dirname4(packageJsonPath);
|
|
19932
20833
|
const libraryPath = join2(packageRoot, packageInfo.libraryFile);
|
|
19933
20834
|
const packageVersion = readPackageVersion(packageJsonPath);
|
|
19934
20835
|
if (!existsSync(libraryPath)) {
|
|
@@ -20629,73 +21530,73 @@ var createConversationManager = () => {
|
|
|
20629
21530
|
};
|
|
20630
21531
|
};
|
|
20631
21532
|
// src/ai/client/actions.ts
|
|
20632
|
-
var serverMessageToAction = (
|
|
20633
|
-
switch (
|
|
21533
|
+
var serverMessageToAction = (message) => {
|
|
21534
|
+
switch (message.type) {
|
|
20634
21535
|
case "chunk":
|
|
20635
21536
|
return {
|
|
20636
|
-
content:
|
|
20637
|
-
conversationId:
|
|
20638
|
-
messageId:
|
|
21537
|
+
content: message.content,
|
|
21538
|
+
conversationId: message.conversationId,
|
|
21539
|
+
messageId: message.messageId,
|
|
20639
21540
|
type: "chunk"
|
|
20640
21541
|
};
|
|
20641
21542
|
case "thinking":
|
|
20642
21543
|
return {
|
|
20643
|
-
content:
|
|
20644
|
-
conversationId:
|
|
20645
|
-
messageId:
|
|
21544
|
+
content: message.content,
|
|
21545
|
+
conversationId: message.conversationId,
|
|
21546
|
+
messageId: message.messageId,
|
|
20646
21547
|
type: "thinking"
|
|
20647
21548
|
};
|
|
20648
21549
|
case "tool_status":
|
|
20649
21550
|
return {
|
|
20650
|
-
conversationId:
|
|
20651
|
-
input:
|
|
20652
|
-
messageId:
|
|
20653
|
-
name:
|
|
20654
|
-
result:
|
|
20655
|
-
status:
|
|
21551
|
+
conversationId: message.conversationId,
|
|
21552
|
+
input: message.input,
|
|
21553
|
+
messageId: message.messageId,
|
|
21554
|
+
name: message.name,
|
|
21555
|
+
result: message.result,
|
|
21556
|
+
status: message.status,
|
|
20656
21557
|
type: "tool_status"
|
|
20657
21558
|
};
|
|
20658
21559
|
case "image":
|
|
20659
21560
|
return {
|
|
20660
|
-
conversationId:
|
|
20661
|
-
data:
|
|
20662
|
-
format:
|
|
20663
|
-
imageId:
|
|
20664
|
-
isPartial:
|
|
20665
|
-
messageId:
|
|
20666
|
-
revisedPrompt:
|
|
21561
|
+
conversationId: message.conversationId,
|
|
21562
|
+
data: message.data,
|
|
21563
|
+
format: message.format,
|
|
21564
|
+
imageId: message.imageId,
|
|
21565
|
+
isPartial: message.isPartial,
|
|
21566
|
+
messageId: message.messageId,
|
|
21567
|
+
revisedPrompt: message.revisedPrompt,
|
|
20667
21568
|
type: "image"
|
|
20668
21569
|
};
|
|
20669
21570
|
case "complete":
|
|
20670
21571
|
return {
|
|
20671
|
-
conversationId:
|
|
20672
|
-
durationMs:
|
|
20673
|
-
messageId:
|
|
20674
|
-
model:
|
|
20675
|
-
sources:
|
|
21572
|
+
conversationId: message.conversationId,
|
|
21573
|
+
durationMs: message.durationMs,
|
|
21574
|
+
messageId: message.messageId,
|
|
21575
|
+
model: message.model,
|
|
21576
|
+
sources: message.sources,
|
|
20676
21577
|
type: "complete",
|
|
20677
|
-
usage:
|
|
21578
|
+
usage: message.usage
|
|
20678
21579
|
};
|
|
20679
21580
|
case "rag_retrieving":
|
|
20680
21581
|
return {
|
|
20681
|
-
conversationId:
|
|
20682
|
-
messageId:
|
|
20683
|
-
retrievalStartedAt:
|
|
21582
|
+
conversationId: message.conversationId,
|
|
21583
|
+
messageId: message.messageId,
|
|
21584
|
+
retrievalStartedAt: message.retrievalStartedAt,
|
|
20684
21585
|
type: "rag_retrieving"
|
|
20685
21586
|
};
|
|
20686
21587
|
case "rag_retrieved":
|
|
20687
21588
|
return {
|
|
20688
|
-
conversationId:
|
|
20689
|
-
messageId:
|
|
20690
|
-
retrievalDurationMs:
|
|
20691
|
-
retrievalStartedAt:
|
|
20692
|
-
retrievedAt:
|
|
20693
|
-
sources:
|
|
20694
|
-
trace:
|
|
21589
|
+
conversationId: message.conversationId,
|
|
21590
|
+
messageId: message.messageId,
|
|
21591
|
+
retrievalDurationMs: message.retrievalDurationMs,
|
|
21592
|
+
retrievalStartedAt: message.retrievalStartedAt,
|
|
21593
|
+
retrievedAt: message.retrievedAt,
|
|
21594
|
+
sources: message.sources,
|
|
21595
|
+
trace: message.trace,
|
|
20695
21596
|
type: "rag_retrieved"
|
|
20696
21597
|
};
|
|
20697
21598
|
case "error":
|
|
20698
|
-
return { message:
|
|
21599
|
+
return { message: message.message, type: "error" };
|
|
20699
21600
|
default:
|
|
20700
21601
|
return null;
|
|
20701
21602
|
}
|
|
@@ -21154,8 +22055,8 @@ var createAIStream = (path, conversationId) => {
|
|
|
21154
22055
|
listeners.forEach((listener) => listener());
|
|
21155
22056
|
};
|
|
21156
22057
|
const unsubscribeStore = store.subscribe(syncState);
|
|
21157
|
-
const unsubscribeConnection = connection.subscribe((
|
|
21158
|
-
const action = serverMessageToAction(
|
|
22058
|
+
const unsubscribeConnection = connection.subscribe((message) => {
|
|
22059
|
+
const action = serverMessageToAction(message);
|
|
21159
22060
|
if (action) {
|
|
21160
22061
|
store.dispatch(action);
|
|
21161
22062
|
}
|
|
@@ -22514,6 +23415,8 @@ export {
|
|
|
22514
23415
|
createRAGFileRetrievalComparisonHistoryStore,
|
|
22515
23416
|
createRAGFileRetrievalBaselineStore,
|
|
22516
23417
|
createRAGFileRetrievalBaselineGatePolicyHistoryStore,
|
|
23418
|
+
createRAGFileJobStateStore,
|
|
23419
|
+
createRAGFileExtractorRegistry,
|
|
22517
23420
|
createRAGFileExtractor,
|
|
22518
23421
|
createRAGFileEvaluationHistoryStore,
|
|
22519
23422
|
createRAGFileAnswerGroundingEvaluationHistoryStore,
|
|
@@ -22524,9 +23427,11 @@ export {
|
|
|
22524
23427
|
createRAGDirectorySyncSource,
|
|
22525
23428
|
createRAGCollection,
|
|
22526
23429
|
createRAGClient,
|
|
23430
|
+
createRAGChunkingRegistry,
|
|
22527
23431
|
createRAGBunS3SyncClient,
|
|
22528
23432
|
createRAGArchiveFileExtractor,
|
|
22529
23433
|
createRAGArchiveExpander,
|
|
23434
|
+
createRAGAccessControl,
|
|
22530
23435
|
createPDFFileExtractor,
|
|
22531
23436
|
createOfficeDocumentExtractor,
|
|
22532
23437
|
createMemoryStore,
|
|
@@ -22569,5 +23474,5 @@ export {
|
|
|
22569
23474
|
aiChat
|
|
22570
23475
|
};
|
|
22571
23476
|
|
|
22572
|
-
//# debugId=
|
|
23477
|
+
//# debugId=01B4F90C8AC5AD4364756E2164756E21
|
|
22573
23478
|
//# sourceMappingURL=index.js.map
|