@absolutejs/absolute 0.19.0-beta.615 → 0.19.0-beta.617
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 +93 -46
- 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 +1544 -253
- package/dist/ai/index.js.map +14 -12
- package/dist/ai/rag/quality.js +49 -6
- 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/angular/index.js +2 -2
- package/dist/angular/index.js.map +1 -1
- package/dist/angular/server.js +2 -2
- package/dist/angular/server.js.map +1 -1
- package/dist/build.js +2 -2
- package/dist/build.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/react/ai/index.js +97 -50
- 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/ai/rag/quality.d.ts +20 -10
- 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 +93 -46
- package/dist/svelte/ai/index.js.map +7 -7
- package/dist/types/ai.d.ts +190 -0
- package/dist/vue/ai/index.js +93 -46
- 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,
|
|
@@ -2991,16 +2995,32 @@ var loadRAGRetrievalComparisonHistory = async ({
|
|
|
2991
2995
|
suiteId,
|
|
2992
2996
|
label,
|
|
2993
2997
|
winnerId,
|
|
2998
|
+
corpusGroupKey,
|
|
2994
2999
|
groupKey,
|
|
2995
3000
|
tag
|
|
2996
|
-
}) => normalizeRetrievalComparisonRuns(await Promise.resolve(store.listRuns({
|
|
3001
|
+
}) => normalizeRetrievalComparisonRuns(await Promise.resolve(store.listRuns({
|
|
3002
|
+
corpusGroupKey,
|
|
3003
|
+
groupKey,
|
|
3004
|
+
label,
|
|
3005
|
+
limit,
|
|
3006
|
+
suiteId,
|
|
3007
|
+
tag,
|
|
3008
|
+
winnerId
|
|
3009
|
+
})));
|
|
2997
3010
|
var loadRAGRetrievalBaselines = async ({
|
|
2998
3011
|
store,
|
|
3012
|
+
corpusGroupKey,
|
|
2999
3013
|
groupKey,
|
|
3000
3014
|
tag,
|
|
3001
3015
|
limit,
|
|
3002
3016
|
status
|
|
3003
|
-
}) => normalizeRetrievalBaselineRecords(await Promise.resolve(store.listBaselines({
|
|
3017
|
+
}) => normalizeRetrievalBaselineRecords(await Promise.resolve(store.listBaselines({
|
|
3018
|
+
corpusGroupKey,
|
|
3019
|
+
groupKey,
|
|
3020
|
+
limit,
|
|
3021
|
+
status,
|
|
3022
|
+
tag
|
|
3023
|
+
})));
|
|
3004
3024
|
var persistRAGRetrievalBaseline = async ({
|
|
3005
3025
|
store,
|
|
3006
3026
|
record
|
|
@@ -3010,18 +3030,21 @@ var persistRAGRetrievalBaseline = async ({
|
|
|
3010
3030
|
};
|
|
3011
3031
|
var loadRAGRetrievalReleaseDecisions = async ({
|
|
3012
3032
|
store,
|
|
3033
|
+
corpusGroupKey,
|
|
3013
3034
|
groupKey,
|
|
3014
3035
|
limit,
|
|
3015
3036
|
kind
|
|
3016
|
-
}) => normalizeRetrievalReleaseDecisionRecords(await Promise.resolve(store.listDecisions({ groupKey, kind, limit })));
|
|
3037
|
+
}) => normalizeRetrievalReleaseDecisionRecords(await Promise.resolve(store.listDecisions({ corpusGroupKey, groupKey, kind, limit })));
|
|
3017
3038
|
var loadRAGRetrievalLaneHandoffDecisions = async ({
|
|
3018
3039
|
store,
|
|
3040
|
+
corpusGroupKey,
|
|
3019
3041
|
groupKey,
|
|
3020
3042
|
limit,
|
|
3021
3043
|
kind,
|
|
3022
3044
|
sourceRolloutLabel,
|
|
3023
3045
|
targetRolloutLabel
|
|
3024
3046
|
}) => normalizeRetrievalLaneHandoffDecisionRecords(await Promise.resolve(store.listDecisions({
|
|
3047
|
+
corpusGroupKey,
|
|
3025
3048
|
groupKey,
|
|
3026
3049
|
kind,
|
|
3027
3050
|
limit,
|
|
@@ -3044,12 +3067,14 @@ var loadRAGRetrievalReleaseIncidents = async ({
|
|
|
3044
3067
|
})));
|
|
3045
3068
|
var loadRAGRetrievalLaneHandoffIncidents = async ({
|
|
3046
3069
|
store,
|
|
3070
|
+
corpusGroupKey,
|
|
3047
3071
|
groupKey,
|
|
3048
3072
|
limit,
|
|
3049
3073
|
targetRolloutLabel,
|
|
3050
3074
|
status,
|
|
3051
3075
|
severity
|
|
3052
3076
|
}) => normalizeRetrievalReleaseIncidentRecords(await Promise.resolve(store.listIncidents({
|
|
3077
|
+
corpusGroupKey,
|
|
3053
3078
|
groupKey,
|
|
3054
3079
|
limit,
|
|
3055
3080
|
severity,
|
|
@@ -3058,12 +3083,14 @@ var loadRAGRetrievalLaneHandoffIncidents = async ({
|
|
|
3058
3083
|
})));
|
|
3059
3084
|
var loadRAGRetrievalLaneHandoffIncidentHistory = async ({
|
|
3060
3085
|
store,
|
|
3086
|
+
corpusGroupKey,
|
|
3061
3087
|
action,
|
|
3062
3088
|
groupKey,
|
|
3063
3089
|
incidentId,
|
|
3064
3090
|
limit,
|
|
3065
3091
|
targetRolloutLabel
|
|
3066
3092
|
}) => await Promise.resolve(store.listRecords({
|
|
3093
|
+
corpusGroupKey,
|
|
3067
3094
|
action,
|
|
3068
3095
|
groupKey,
|
|
3069
3096
|
incidentId,
|
|
@@ -3108,21 +3135,25 @@ var loadRAGRetrievalIncidentRemediationExecutionHistory = async ({
|
|
|
3108
3135
|
})));
|
|
3109
3136
|
var loadRAGRetrievalLaneHandoffAutoCompletePolicyHistory = async ({
|
|
3110
3137
|
store,
|
|
3138
|
+
corpusGroupKey,
|
|
3111
3139
|
groupKey,
|
|
3112
3140
|
limit,
|
|
3113
3141
|
targetRolloutLabel
|
|
3114
3142
|
}) => await Promise.resolve(store.listRecords({
|
|
3143
|
+
corpusGroupKey,
|
|
3115
3144
|
groupKey,
|
|
3116
3145
|
limit,
|
|
3117
3146
|
targetRolloutLabel
|
|
3118
3147
|
}));
|
|
3119
3148
|
var loadRAGRetrievalReleaseLanePolicyHistory = async ({
|
|
3120
3149
|
store,
|
|
3150
|
+
corpusGroupKey,
|
|
3121
3151
|
groupKey,
|
|
3122
3152
|
limit,
|
|
3123
3153
|
rolloutLabel,
|
|
3124
3154
|
scope
|
|
3125
3155
|
}) => await Promise.resolve(store.listRecords({
|
|
3156
|
+
corpusGroupKey,
|
|
3126
3157
|
groupKey,
|
|
3127
3158
|
limit,
|
|
3128
3159
|
rolloutLabel,
|
|
@@ -3130,11 +3161,13 @@ var loadRAGRetrievalReleaseLanePolicyHistory = async ({
|
|
|
3130
3161
|
}));
|
|
3131
3162
|
var loadRAGRetrievalBaselineGatePolicyHistory = async ({
|
|
3132
3163
|
store,
|
|
3164
|
+
corpusGroupKey,
|
|
3133
3165
|
groupKey,
|
|
3134
3166
|
limit,
|
|
3135
3167
|
rolloutLabel,
|
|
3136
3168
|
scope
|
|
3137
3169
|
}) => await Promise.resolve(store.listRecords({
|
|
3170
|
+
corpusGroupKey,
|
|
3138
3171
|
groupKey,
|
|
3139
3172
|
limit,
|
|
3140
3173
|
rolloutLabel,
|
|
@@ -3142,6 +3175,7 @@ var loadRAGRetrievalBaselineGatePolicyHistory = async ({
|
|
|
3142
3175
|
}));
|
|
3143
3176
|
var loadRAGRetrievalReleaseLaneEscalationPolicyHistory = async ({
|
|
3144
3177
|
store,
|
|
3178
|
+
corpusGroupKey,
|
|
3145
3179
|
groupKey,
|
|
3146
3180
|
limit,
|
|
3147
3181
|
targetRolloutLabel
|
|
@@ -3229,11 +3263,15 @@ var persistRAGRetrievalReleaseLaneEscalationPolicyHistory = async ({
|
|
|
3229
3263
|
};
|
|
3230
3264
|
var buildRAGEvaluationResponse = (cases) => {
|
|
3231
3265
|
const totalCases = cases.length;
|
|
3266
|
+
const corpusKeys = [
|
|
3267
|
+
...new Set(cases.flatMap((entry) => entry.corpusKey ?? []))
|
|
3268
|
+
];
|
|
3232
3269
|
const passedCases = cases.filter((entry) => entry.status === "pass").length;
|
|
3233
3270
|
const partialCases = cases.filter((entry) => entry.status === "partial").length;
|
|
3234
3271
|
const failedCases = cases.filter((entry) => entry.status === "fail").length;
|
|
3235
3272
|
return {
|
|
3236
3273
|
cases,
|
|
3274
|
+
...corpusKeys.length > 0 ? { corpusKeys } : {},
|
|
3237
3275
|
elapsedMs: cases.reduce((sum, result) => sum + result.elapsedMs, 0),
|
|
3238
3276
|
ok: true,
|
|
3239
3277
|
passingRate: totalCases > 0 ? passedCases / totalCases * 100 : 0,
|
|
@@ -3459,6 +3497,9 @@ var compareRAGRetrievalStrategies = async ({
|
|
|
3459
3497
|
traceSummary: entry.traceSummary
|
|
3460
3498
|
})));
|
|
3461
3499
|
return {
|
|
3500
|
+
corpusKeys: [
|
|
3501
|
+
...new Set(entries.flatMap((entry) => entry.response.corpusKeys ?? []))
|
|
3502
|
+
],
|
|
3462
3503
|
entries,
|
|
3463
3504
|
leaderboard,
|
|
3464
3505
|
summary: summarizeRAGRetrievalComparison(entries),
|
|
@@ -3491,6 +3532,7 @@ var compareRAGRetrievalTraceSummaries = (current, previous) => ({
|
|
|
3491
3532
|
});
|
|
3492
3533
|
var buildSearchTraceResultSnapshots = (results) => results.map((result) => ({
|
|
3493
3534
|
chunkId: result.chunkId,
|
|
3535
|
+
corpusKey: result.corpusKey ?? (typeof result.metadata?.corpusKey === "string" ? result.metadata.corpusKey : undefined),
|
|
3494
3536
|
documentId: typeof result.metadata?.documentId === "string" ? result.metadata.documentId : undefined,
|
|
3495
3537
|
score: result.score,
|
|
3496
3538
|
source: result.source,
|
|
@@ -3690,6 +3732,7 @@ var summarizeRAGEvaluationCase = ({
|
|
|
3690
3732
|
const status = expectedCount === 0 ? "partial" : matchedCount === expectedCount ? "pass" : matchedCount > 0 ? "partial" : "fail";
|
|
3691
3733
|
return {
|
|
3692
3734
|
caseId: caseInput.id ?? `case-${caseIndex + 1}`,
|
|
3735
|
+
corpusKey: caseInput.corpusKey,
|
|
3693
3736
|
elapsedMs,
|
|
3694
3737
|
expectedCount,
|
|
3695
3738
|
expectedIds,
|
|
@@ -4289,10 +4332,14 @@ var buildProvenanceLabel2 = (metadata) => {
|
|
|
4289
4332
|
const transcriptSource = getContextString2(metadata.transcriptSource);
|
|
4290
4333
|
const pdfTextMode = getContextString2(metadata.pdfTextMode);
|
|
4291
4334
|
const ocrEngine = getContextString2(metadata.ocrEngine);
|
|
4335
|
+
const extractorRegistryMatch = getContextString2(metadata.extractorRegistryMatch);
|
|
4336
|
+
const chunkingProfile = getContextString2(metadata.chunkingProfile);
|
|
4292
4337
|
const ocrConfidence = getContextNumber2(metadata.ocrRegionConfidence) ?? getContextNumber2(metadata.ocrConfidence);
|
|
4293
4338
|
const labels = [
|
|
4294
4339
|
pdfTextMode ? `PDF ${pdfTextMode}` : "",
|
|
4295
4340
|
ocrEngine ? `OCR ${ocrEngine}` : "",
|
|
4341
|
+
extractorRegistryMatch ? `Extractor ${extractorRegistryMatch}` : "",
|
|
4342
|
+
chunkingProfile ? `Chunking ${chunkingProfile}` : "",
|
|
4296
4343
|
typeof ocrConfidence === "number" ? `Confidence ${ocrConfidence.toFixed(2)}` : "",
|
|
4297
4344
|
mediaKind ? `Media ${mediaKind}` : "",
|
|
4298
4345
|
transcriptSource ? `Transcript ${transcriptSource}` : "",
|
|
@@ -6741,12 +6788,12 @@ var checkBackpressure = async (socket) => {
|
|
|
6741
6788
|
await delay(BACKPRESSURE_DELAY);
|
|
6742
6789
|
}
|
|
6743
6790
|
};
|
|
6744
|
-
var sendMessage = async (socket,
|
|
6791
|
+
var sendMessage = async (socket, message) => {
|
|
6745
6792
|
if (socket.readyState !== WS_OPEN) {
|
|
6746
6793
|
return false;
|
|
6747
6794
|
}
|
|
6748
6795
|
await checkBackpressure(socket);
|
|
6749
|
-
socket.send(serializeAIMessage(
|
|
6796
|
+
socket.send(serializeAIMessage(message));
|
|
6750
6797
|
return true;
|
|
6751
6798
|
};
|
|
6752
6799
|
var buildToolDefinitions = (tools) => Object.entries(tools).map(([name, def]) => ({
|
|
@@ -9689,6 +9736,7 @@ var createEmailExtractor = () => ({
|
|
|
9689
9736
|
chunking: input.chunking,
|
|
9690
9737
|
contentType: attachment.contentType,
|
|
9691
9738
|
data: attachment.data,
|
|
9739
|
+
extractorRegistry: input.extractorRegistry,
|
|
9692
9740
|
format: inferFormatFromContentType(attachment.contentType ?? null) ?? inferFormatFromName(attachment.fileName),
|
|
9693
9741
|
metadata: {
|
|
9694
9742
|
...messageMetadata,
|
|
@@ -9844,6 +9892,8 @@ ${slide.text}`),
|
|
|
9844
9892
|
});
|
|
9845
9893
|
var createRAGArchiveExpander = (expander) => expander;
|
|
9846
9894
|
var createRAGFileExtractor = (extractor) => extractor;
|
|
9895
|
+
var createRAGFileExtractorRegistry = (registry) => registry;
|
|
9896
|
+
var createRAGChunkingRegistry = (registry) => registry;
|
|
9847
9897
|
var createRAGImageOCRExtractor = (provider) => ({
|
|
9848
9898
|
name: `absolute_image_ocr:${provider.name}`,
|
|
9849
9899
|
supports: imageExtractorSupports,
|
|
@@ -9934,11 +9984,12 @@ var createTextFileExtractor = () => ({
|
|
|
9934
9984
|
title: input.title
|
|
9935
9985
|
})
|
|
9936
9986
|
});
|
|
9937
|
-
var expandArchiveEntry = async (entry, archiveInput, extractors) => {
|
|
9987
|
+
var expandArchiveEntry = async (entry, archiveInput, extractors, registry) => {
|
|
9938
9988
|
const documents = await extractRAGFileDocuments({
|
|
9939
9989
|
chunking: archiveInput.chunking,
|
|
9940
9990
|
contentType: entry.contentType,
|
|
9941
9991
|
data: entry.data,
|
|
9992
|
+
extractorRegistry: archiveInput.extractorRegistry,
|
|
9942
9993
|
format: entry.format,
|
|
9943
9994
|
metadata: {
|
|
9944
9995
|
...archiveInput.metadata ?? {},
|
|
@@ -9952,7 +10003,7 @@ var expandArchiveEntry = async (entry, archiveInput, extractors) => {
|
|
|
9952
10003
|
name: basename(entry.path),
|
|
9953
10004
|
source: archiveInput.source && !archiveInput.source.startsWith("http") ? `${archiveInput.source}#${entry.path}` : entry.path,
|
|
9954
10005
|
title: basename(entry.path)
|
|
9955
|
-
}, extractors);
|
|
10006
|
+
}, extractors, registry);
|
|
9956
10007
|
return documents;
|
|
9957
10008
|
};
|
|
9958
10009
|
var createPDFFileExtractor = () => ({
|
|
@@ -10053,8 +10104,83 @@ var DEFAULT_FILE_EXTRACTORS = [
|
|
|
10053
10104
|
createPDFFileExtractor(),
|
|
10054
10105
|
createTextFileExtractor()
|
|
10055
10106
|
];
|
|
10056
|
-
var
|
|
10057
|
-
|
|
10107
|
+
var resolveExtractorRegistry = (registry) => {
|
|
10108
|
+
if (!registry) {
|
|
10109
|
+
return {
|
|
10110
|
+
defaultOrder: "registry_first",
|
|
10111
|
+
includeDefaults: true,
|
|
10112
|
+
registrations: []
|
|
10113
|
+
};
|
|
10114
|
+
}
|
|
10115
|
+
if (Array.isArray(registry)) {
|
|
10116
|
+
return {
|
|
10117
|
+
defaultOrder: "registry_first",
|
|
10118
|
+
includeDefaults: true,
|
|
10119
|
+
registrations: registry
|
|
10120
|
+
};
|
|
10121
|
+
}
|
|
10122
|
+
return {
|
|
10123
|
+
defaultOrder: registry.defaultOrder ?? "registry_first",
|
|
10124
|
+
includeDefaults: registry.includeDefaults ?? true,
|
|
10125
|
+
registrations: registry.registrations
|
|
10126
|
+
};
|
|
10127
|
+
};
|
|
10128
|
+
var createExtractorRegistryInput = (input) => ({
|
|
10129
|
+
...input,
|
|
10130
|
+
inferredContentType: input.contentType ?? null,
|
|
10131
|
+
inferredExtension: inferExtensionFromInput(input) || null,
|
|
10132
|
+
inferredFormat: input.format ?? inferFormatFromContentType(input.contentType ?? null) ?? inferFormatFromName(input.path ?? input.source ?? input.name ?? input.title)
|
|
10133
|
+
});
|
|
10134
|
+
var registrationMatches = async (registration, input) => {
|
|
10135
|
+
const normalizedContentType = input.inferredContentType?.toLowerCase();
|
|
10136
|
+
const normalizedExtension = input.inferredExtension?.toLowerCase();
|
|
10137
|
+
const normalizedName = (input.path ?? input.source ?? input.name ?? input.title ?? "").toLowerCase();
|
|
10138
|
+
if (registration.contentTypes?.length && !registration.contentTypes.some((entry) => normalizedContentType === entry.toLowerCase())) {
|
|
10139
|
+
return false;
|
|
10140
|
+
}
|
|
10141
|
+
if (registration.extensions?.length && !registration.extensions.some((entry) => normalizedExtension === entry.toLowerCase())) {
|
|
10142
|
+
return false;
|
|
10143
|
+
}
|
|
10144
|
+
if (registration.formats?.length && (!input.inferredFormat || !registration.formats.includes(input.inferredFormat))) {
|
|
10145
|
+
return false;
|
|
10146
|
+
}
|
|
10147
|
+
if (registration.names?.length && !registration.names.some((entry) => normalizedName.includes(entry.toLowerCase()))) {
|
|
10148
|
+
return false;
|
|
10149
|
+
}
|
|
10150
|
+
if (registration.match) {
|
|
10151
|
+
return registration.match(input);
|
|
10152
|
+
}
|
|
10153
|
+
return true;
|
|
10154
|
+
};
|
|
10155
|
+
var dedupeResolvedExtractors = (extractors) => {
|
|
10156
|
+
const seen = new Set;
|
|
10157
|
+
const ordered = [];
|
|
10158
|
+
for (const entry of extractors) {
|
|
10159
|
+
if (seen.has(entry.extractor.name)) {
|
|
10160
|
+
continue;
|
|
10161
|
+
}
|
|
10162
|
+
seen.add(entry.extractor.name);
|
|
10163
|
+
ordered.push(entry);
|
|
10164
|
+
}
|
|
10165
|
+
return ordered;
|
|
10166
|
+
};
|
|
10167
|
+
var resolveFileExtractors = async (input, extractors, registry) => {
|
|
10168
|
+
const explicit = extractors ?? [];
|
|
10169
|
+
const resolvedRegistry = resolveExtractorRegistry(registry);
|
|
10170
|
+
const registryInput = createExtractorRegistryInput(input);
|
|
10171
|
+
const matchedRegistrations = (await Promise.all(resolvedRegistry.registrations.map(async (registration) => ({
|
|
10172
|
+
matches: await registrationMatches(registration, registryInput),
|
|
10173
|
+
priority: registration.priority ?? 0,
|
|
10174
|
+
registration
|
|
10175
|
+
})))).filter((entry) => entry.matches).sort((left, right) => right.priority - left.priority).map((entry) => ({
|
|
10176
|
+
extractor: entry.registration.extractor,
|
|
10177
|
+
registryMatchName: entry.registration.name ?? entry.registration.extractor.name
|
|
10178
|
+
}));
|
|
10179
|
+
const defaults = resolvedRegistry.includeDefaults ? DEFAULT_FILE_EXTRACTORS.map((extractor) => ({ extractor })) : [];
|
|
10180
|
+
const explicitResolved = explicit.map((extractor) => ({ extractor }));
|
|
10181
|
+
return dedupeResolvedExtractors(resolvedRegistry.defaultOrder === "defaults_first" ? [...explicitResolved, ...defaults, ...matchedRegistrations] : [...explicitResolved, ...matchedRegistrations, ...defaults]);
|
|
10182
|
+
};
|
|
10183
|
+
var applyExtractorDefaults = (document, input, extractorName, registryMatchName) => ({
|
|
10058
10184
|
chunking: document.chunking ?? input.chunking,
|
|
10059
10185
|
format: document.format ?? input.format ?? inferFormatFromContentType(document.contentType ?? input.contentType ?? null) ?? inferFormatFromName(document.source ?? input.source ?? input.path ?? input.name),
|
|
10060
10186
|
id: document.id,
|
|
@@ -10062,20 +10188,22 @@ var applyExtractorDefaults = (document, input, extractorName) => ({
|
|
|
10062
10188
|
...input.metadata ?? {},
|
|
10063
10189
|
...document.metadata ?? {},
|
|
10064
10190
|
contentType: document.contentType ?? input.contentType,
|
|
10065
|
-
extractor: document.extractor ?? extractorName
|
|
10191
|
+
extractor: document.extractor ?? extractorName,
|
|
10192
|
+
...registryMatchName ? { extractorRegistryMatch: registryMatchName } : {}
|
|
10066
10193
|
},
|
|
10067
10194
|
source: document.source ?? input.source ?? input.path ?? input.name,
|
|
10068
10195
|
text: document.text,
|
|
10069
10196
|
title: document.title ?? input.title
|
|
10070
10197
|
});
|
|
10071
|
-
var extractRAGFileDocuments = async (input, extractors) => {
|
|
10072
|
-
for (const
|
|
10198
|
+
var extractRAGFileDocuments = async (input, extractors, registry) => {
|
|
10199
|
+
for (const resolvedExtractor of await resolveFileExtractors(input, extractors, registry)) {
|
|
10200
|
+
const { extractor, registryMatchName } = resolvedExtractor;
|
|
10073
10201
|
if (!await extractor.supports(input)) {
|
|
10074
10202
|
continue;
|
|
10075
10203
|
}
|
|
10076
10204
|
const extracted = await extractor.extract(input);
|
|
10077
10205
|
const documents = Array.isArray(extracted) ? extracted : [extracted];
|
|
10078
|
-
return documents.map((document) => applyExtractorDefaults(document, input, extractor.name));
|
|
10206
|
+
return documents.map((document) => applyExtractorDefaults(document, input, extractor.name, registryMatchName));
|
|
10079
10207
|
}
|
|
10080
10208
|
throw new Error(`No RAG file extractor matched ${inferNameFromInput(input)}. Register a custom extractor for this file type.`);
|
|
10081
10209
|
};
|
|
@@ -10086,7 +10214,7 @@ var getFirstExtractedDocument = (documents, label) => {
|
|
|
10086
10214
|
}
|
|
10087
10215
|
return document;
|
|
10088
10216
|
};
|
|
10089
|
-
var loadExtractedDocuments = async (input, extractors) => extractRAGFileDocuments(input, extractors);
|
|
10217
|
+
var loadExtractedDocuments = async (input, extractors, registry) => extractRAGFileDocuments(input, extractors, registry);
|
|
10090
10218
|
var sentenceUnits = (text) => {
|
|
10091
10219
|
const matches = text.match(/[^.!?\n]+(?:[.!?]+|$)/g);
|
|
10092
10220
|
if (!matches) {
|
|
@@ -10283,11 +10411,92 @@ var resolveChunkingUnits = (text, options) => {
|
|
|
10283
10411
|
}
|
|
10284
10412
|
return paragraphUnits(text);
|
|
10285
10413
|
};
|
|
10286
|
-
var
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
|
|
10290
|
-
const
|
|
10414
|
+
var resolveChunkingProfiles = (registry) => {
|
|
10415
|
+
if (!registry) {
|
|
10416
|
+
return [];
|
|
10417
|
+
}
|
|
10418
|
+
const profiles = Array.isArray(registry) ? registry : registry.profiles;
|
|
10419
|
+
return profiles.map((profile, index) => normalizeChunkingProfile(profile, index)).sort((left, right) => right.priority - left.priority).map(({ profile }) => profile);
|
|
10420
|
+
};
|
|
10421
|
+
var normalizeChunkingProfile = (profile, index) => {
|
|
10422
|
+
if ("resolve" in profile) {
|
|
10423
|
+
return {
|
|
10424
|
+
priority: 0,
|
|
10425
|
+
profile
|
|
10426
|
+
};
|
|
10427
|
+
}
|
|
10428
|
+
const options = normalizeChunkingProfileOptions(profile.profile);
|
|
10429
|
+
const sourceSet = profile.sources?.filter((value) => typeof value === "string") ?? [];
|
|
10430
|
+
const documentIdSet = profile.documentIds?.filter((value) => typeof value === "string") ?? [];
|
|
10431
|
+
const formatSet = profile.formats?.filter((value) => typeof value === "string") ?? [];
|
|
10432
|
+
const sourceNativeKindSet = profile.sourceNativeKinds?.filter((value) => typeof value === "string") ?? [];
|
|
10433
|
+
return {
|
|
10434
|
+
priority: profile.priority ?? 0,
|
|
10435
|
+
profile: {
|
|
10436
|
+
name: profile.name ?? `chunking_profile_${String(index + 1).padStart(2, "0")}`,
|
|
10437
|
+
resolve: (input) => {
|
|
10438
|
+
const documentId = input.document.id?.trim() || (typeof input.metadata.documentId === "string" ? input.metadata.documentId : undefined);
|
|
10439
|
+
const source = input.document.source?.trim();
|
|
10440
|
+
if (formatSet.length > 0 && !formatSet.includes(input.format)) {
|
|
10441
|
+
return;
|
|
10442
|
+
}
|
|
10443
|
+
if (sourceNativeKindSet.length > 0 && (!input.sourceNativeKind || !sourceNativeKindSet.includes(input.sourceNativeKind))) {
|
|
10444
|
+
return;
|
|
10445
|
+
}
|
|
10446
|
+
if (sourceSet.length > 0 && (!source || !sourceSet.includes(source))) {
|
|
10447
|
+
return;
|
|
10448
|
+
}
|
|
10449
|
+
if (documentIdSet.length > 0 && (!documentId || !documentIdSet.includes(documentId))) {
|
|
10450
|
+
return;
|
|
10451
|
+
}
|
|
10452
|
+
return options;
|
|
10453
|
+
}
|
|
10454
|
+
}
|
|
10455
|
+
};
|
|
10456
|
+
};
|
|
10457
|
+
var normalizeChunkingProfileOptions = (profile) => isChunkingProfileOptionsWrapper(profile) ? profile.options ?? {} : profile;
|
|
10458
|
+
var isChunkingProfileOptionsWrapper = (profile) => Object.prototype.hasOwnProperty.call(profile, "options");
|
|
10459
|
+
var resolveChunkingProfileOverrides = ({
|
|
10460
|
+
defaults,
|
|
10461
|
+
document,
|
|
10462
|
+
format,
|
|
10463
|
+
normalizedText,
|
|
10464
|
+
registry
|
|
10465
|
+
}) => {
|
|
10466
|
+
const metadata = document.metadata ?? {};
|
|
10467
|
+
const sourceNativeKind = typeof metadata.sourceNativeKind === "string" ? metadata.sourceNativeKind : undefined;
|
|
10468
|
+
for (const profile of resolveChunkingProfiles(registry)) {
|
|
10469
|
+
const options = profile.resolve({
|
|
10470
|
+
defaults,
|
|
10471
|
+
document,
|
|
10472
|
+
format,
|
|
10473
|
+
metadata,
|
|
10474
|
+
normalizedText,
|
|
10475
|
+
sourceNativeKind
|
|
10476
|
+
});
|
|
10477
|
+
if (options) {
|
|
10478
|
+
return {
|
|
10479
|
+
name: profile.name,
|
|
10480
|
+
options
|
|
10481
|
+
};
|
|
10482
|
+
}
|
|
10483
|
+
}
|
|
10484
|
+
return;
|
|
10485
|
+
};
|
|
10486
|
+
var resolveChunkingOptions = (document, defaults, registry, format, normalizedText) => {
|
|
10487
|
+
const resolvedFormat = format ?? inferFormat(document);
|
|
10488
|
+
const resolvedNormalizedText = normalizedText ?? normalizeDocumentText(document.text, resolvedFormat);
|
|
10489
|
+
const profileOverrides = resolveChunkingProfileOverrides({
|
|
10490
|
+
defaults,
|
|
10491
|
+
document,
|
|
10492
|
+
format: resolvedFormat,
|
|
10493
|
+
normalizedText: resolvedNormalizedText,
|
|
10494
|
+
registry
|
|
10495
|
+
});
|
|
10496
|
+
const maxChunkLength = document.chunking?.maxChunkLength ?? profileOverrides?.options.maxChunkLength ?? defaults?.maxChunkLength ?? DEFAULT_MAX_CHUNK_LENGTH;
|
|
10497
|
+
const chunkOverlap = document.chunking?.chunkOverlap ?? profileOverrides?.options.chunkOverlap ?? defaults?.chunkOverlap ?? DEFAULT_CHUNK_OVERLAP;
|
|
10498
|
+
const minChunkLength = document.chunking?.minChunkLength ?? profileOverrides?.options.minChunkLength ?? defaults?.minChunkLength ?? DEFAULT_MIN_CHUNK_LENGTH;
|
|
10499
|
+
const strategy = document.chunking?.strategy ?? profileOverrides?.options.strategy ?? defaults?.strategy ?? DEFAULT_STRATEGY;
|
|
10291
10500
|
return {
|
|
10292
10501
|
chunkOverlap: Math.max(0, Math.min(chunkOverlap, maxChunkLength - 1)),
|
|
10293
10502
|
maxChunkLength: Math.max(RAG_MIN_CHUNK_LENGTH_FLOOR, maxChunkLength),
|
|
@@ -10305,10 +10514,17 @@ var createChunkEntries = (document, format, text, options) => {
|
|
|
10305
10514
|
const units = resolveChunkingUnits(text, options);
|
|
10306
10515
|
return chunkFromUnits(units, options.maxChunkLength, options.chunkOverlap, options.minChunkLength).map((entry) => ({ text: entry }));
|
|
10307
10516
|
};
|
|
10308
|
-
var prepareRAGDocument = (document, defaultChunking) => {
|
|
10517
|
+
var prepareRAGDocument = (document, defaultChunking, chunkingRegistry) => {
|
|
10309
10518
|
const format = inferFormat(document);
|
|
10310
10519
|
const normalizedText = normalizeDocumentText(document.text, format);
|
|
10311
|
-
const
|
|
10520
|
+
const chunkingProfileOverrides = resolveChunkingProfileOverrides({
|
|
10521
|
+
defaults: defaultChunking,
|
|
10522
|
+
document,
|
|
10523
|
+
format,
|
|
10524
|
+
normalizedText,
|
|
10525
|
+
registry: chunkingRegistry
|
|
10526
|
+
});
|
|
10527
|
+
const chunking = resolveChunkingOptions(document, defaultChunking, chunkingRegistry, format, normalizedText);
|
|
10312
10528
|
const documentId = document.id?.trim() || slugify(document.source || document.title || normalizedText.slice(0, RAG_DOCUMENT_ID_PREVIEW_LENGTH));
|
|
10313
10529
|
const title = document.title?.trim() || documentId;
|
|
10314
10530
|
let sourceExtension = "txt";
|
|
@@ -10318,9 +10534,12 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10318
10534
|
sourceExtension = "html";
|
|
10319
10535
|
}
|
|
10320
10536
|
const source = document.source?.trim() || `${documentId}.${sourceExtension}`;
|
|
10537
|
+
const corpusKey = document.corpusKey?.trim() || (typeof document.metadata?.corpusKey === "string" ? document.metadata.corpusKey.trim() : undefined) || undefined;
|
|
10321
10538
|
const metadata = {
|
|
10322
10539
|
...document.metadata ?? {},
|
|
10540
|
+
...corpusKey ? { corpusKey } : {},
|
|
10323
10541
|
documentId,
|
|
10542
|
+
...chunkingProfileOverrides?.name ? { chunkingProfile: chunkingProfileOverrides.name } : {},
|
|
10324
10543
|
format,
|
|
10325
10544
|
source,
|
|
10326
10545
|
title
|
|
@@ -10344,6 +10563,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10344
10563
|
const nextChunkId = index + 1 < chunkEntries.length ? `${documentId}:${String(index + 2).padStart(RAG_CHUNK_ID_PAD_LENGTH, "0")}` : undefined;
|
|
10345
10564
|
return {
|
|
10346
10565
|
chunkId: `${documentId}:${String(index + 1).padStart(RAG_CHUNK_ID_PAD_LENGTH, "0")}`,
|
|
10566
|
+
...corpusKey ? { corpusKey } : {},
|
|
10347
10567
|
metadata: {
|
|
10348
10568
|
...metadata,
|
|
10349
10569
|
chunkCount: chunkEntries.length,
|
|
@@ -10366,6 +10586,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10366
10586
|
};
|
|
10367
10587
|
});
|
|
10368
10588
|
return {
|
|
10589
|
+
...corpusKey ? { corpusKey } : {},
|
|
10369
10590
|
chunks,
|
|
10370
10591
|
documentId,
|
|
10371
10592
|
format,
|
|
@@ -10375,7 +10596,7 @@ var prepareRAGDocument = (document, defaultChunking) => {
|
|
|
10375
10596
|
title
|
|
10376
10597
|
};
|
|
10377
10598
|
};
|
|
10378
|
-
var prepareRAGDocuments = (input) => input.documents.map((document) => prepareRAGDocument(document, input.defaultChunking));
|
|
10599
|
+
var prepareRAGDocuments = (input) => input.documents.map((document) => prepareRAGDocument(document, input.defaultChunking, input.chunkingRegistry));
|
|
10379
10600
|
var mergeMetadata = (inputMetadata, extraMetadata, baseMetadata) => ({
|
|
10380
10601
|
...baseMetadata ?? {},
|
|
10381
10602
|
...inputMetadata ?? {},
|
|
@@ -10390,12 +10611,13 @@ var loadRAGDocumentFile = async (input) => {
|
|
|
10390
10611
|
chunking: input.chunking,
|
|
10391
10612
|
contentType: input.contentType,
|
|
10392
10613
|
data,
|
|
10614
|
+
extractorRegistry: input.extractorRegistry,
|
|
10393
10615
|
format: input.format,
|
|
10394
10616
|
metadata: input.metadata,
|
|
10395
10617
|
path: input.path,
|
|
10396
10618
|
source: input.source,
|
|
10397
10619
|
title: input.title
|
|
10398
|
-
}, input.extractors);
|
|
10620
|
+
}, input.extractors, input.extractorRegistry);
|
|
10399
10621
|
return getFirstExtractedDocument(documents, "for file input");
|
|
10400
10622
|
};
|
|
10401
10623
|
var loadRAGDocumentFromURL = async (input) => {
|
|
@@ -10412,12 +10634,13 @@ var loadRAGDocumentFromURL = async (input) => {
|
|
|
10412
10634
|
chunking: input.chunking,
|
|
10413
10635
|
contentType: input.contentType ?? response.headers.get("content-type") ?? undefined,
|
|
10414
10636
|
data,
|
|
10637
|
+
extractorRegistry: input.extractorRegistry,
|
|
10415
10638
|
format: input.format ?? inferFormatFromUrl(url),
|
|
10416
10639
|
metadata: input.metadata,
|
|
10417
10640
|
name: basename(new URL(url).pathname),
|
|
10418
10641
|
source: input.source ?? url,
|
|
10419
10642
|
title: input.title
|
|
10420
|
-
}, input.extractors);
|
|
10643
|
+
}, input.extractors, input.extractorRegistry);
|
|
10421
10644
|
return getFirstExtractedDocument(documents, "for URL input");
|
|
10422
10645
|
};
|
|
10423
10646
|
var loadRAGDocumentsFromUploads = async (input) => {
|
|
@@ -10426,12 +10649,13 @@ var loadRAGDocumentsFromUploads = async (input) => {
|
|
|
10426
10649
|
chunking: upload.chunking,
|
|
10427
10650
|
contentType: upload.contentType,
|
|
10428
10651
|
data: decodeUploadContent(upload),
|
|
10652
|
+
extractorRegistry: input.extractorRegistry,
|
|
10429
10653
|
format: upload.format,
|
|
10430
10654
|
metadata: upload.metadata,
|
|
10431
10655
|
name: upload.name,
|
|
10432
10656
|
source: upload.source ?? upload.name,
|
|
10433
10657
|
title: upload.title
|
|
10434
|
-
}, input.extractors);
|
|
10658
|
+
}, input.extractors, input.extractorRegistry);
|
|
10435
10659
|
return loaded.map((document) => ({
|
|
10436
10660
|
...document,
|
|
10437
10661
|
metadata: mergeMetadata(document.metadata, { uploadFile: upload.name }, input.baseMetadata)
|
|
@@ -10439,6 +10663,7 @@ var loadRAGDocumentsFromUploads = async (input) => {
|
|
|
10439
10663
|
}));
|
|
10440
10664
|
return {
|
|
10441
10665
|
defaultChunking: input.defaultChunking,
|
|
10666
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10442
10667
|
documents: documents.flat()
|
|
10443
10668
|
};
|
|
10444
10669
|
};
|
|
@@ -10457,12 +10682,13 @@ var loadRAGDocumentsFromURLs = async (input) => {
|
|
|
10457
10682
|
chunking: urlInput.chunking,
|
|
10458
10683
|
contentType: urlInput.contentType ?? response.headers.get("content-type") ?? undefined,
|
|
10459
10684
|
data,
|
|
10685
|
+
extractorRegistry: urlInput.extractorRegistry ?? input.extractorRegistry,
|
|
10460
10686
|
format: urlInput.format ?? inferFormatFromUrl(url),
|
|
10461
10687
|
metadata: urlInput.metadata,
|
|
10462
10688
|
name: basename(new URL(url).pathname),
|
|
10463
10689
|
source: urlInput.source ?? url,
|
|
10464
10690
|
title: urlInput.title
|
|
10465
|
-
}, urlInput.extractors ?? input.extractors);
|
|
10691
|
+
}, urlInput.extractors ?? input.extractors, urlInput.extractorRegistry ?? input.extractorRegistry);
|
|
10466
10692
|
return loaded.map((document) => ({
|
|
10467
10693
|
...document,
|
|
10468
10694
|
metadata: mergeMetadata(document.metadata, { sourceUrl: urlInput.url }, input.baseMetadata)
|
|
@@ -10470,6 +10696,7 @@ var loadRAGDocumentsFromURLs = async (input) => {
|
|
|
10470
10696
|
}));
|
|
10471
10697
|
return {
|
|
10472
10698
|
defaultChunking: input.defaultChunking,
|
|
10699
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10473
10700
|
documents: documents.flat()
|
|
10474
10701
|
};
|
|
10475
10702
|
};
|
|
@@ -10478,15 +10705,16 @@ var loadRAGDocumentUpload = async (input) => {
|
|
|
10478
10705
|
chunking: input.chunking,
|
|
10479
10706
|
contentType: input.contentType,
|
|
10480
10707
|
data: decodeUploadContent(input),
|
|
10708
|
+
extractorRegistry: input.extractorRegistry,
|
|
10481
10709
|
format: input.format,
|
|
10482
10710
|
metadata: input.metadata,
|
|
10483
10711
|
name: input.name,
|
|
10484
10712
|
source: input.source ?? input.name,
|
|
10485
10713
|
title: input.title
|
|
10486
|
-
}, input.extractors);
|
|
10714
|
+
}, input.extractors, input.extractorRegistry);
|
|
10487
10715
|
return getFirstExtractedDocument(documents, "for upload input");
|
|
10488
10716
|
};
|
|
10489
|
-
var prepareRAGDocumentFile = async (input, defaultChunking) => prepareRAGDocument(await loadRAGDocumentFile(input), defaultChunking);
|
|
10717
|
+
var prepareRAGDocumentFile = async (input, defaultChunking, chunkingRegistry) => prepareRAGDocument(await loadRAGDocumentFile(input), defaultChunking, chunkingRegistry);
|
|
10490
10718
|
var DEFAULT_DIRECTORY_EXTENSIONS = [
|
|
10491
10719
|
".txt",
|
|
10492
10720
|
".md",
|
|
@@ -10546,7 +10774,7 @@ var buildRAGUpsertInputFromUploads = async (input) => ({
|
|
|
10546
10774
|
});
|
|
10547
10775
|
var loadRAGDocumentsFromDirectory = async (input) => {
|
|
10548
10776
|
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()}`));
|
|
10777
|
+
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
10778
|
const files = await collectDirectoryFiles(root, input.recursive !== false, includeExtensions);
|
|
10551
10779
|
const documents = await Promise.all(files.map(async (path) => {
|
|
10552
10780
|
const source = relative(root, path).replace(/\\/g, "/");
|
|
@@ -10554,13 +10782,14 @@ var loadRAGDocumentsFromDirectory = async (input) => {
|
|
|
10554
10782
|
const loaded = await loadExtractedDocuments({
|
|
10555
10783
|
chunking: input.defaultChunking,
|
|
10556
10784
|
data,
|
|
10785
|
+
extractorRegistry: input.extractorRegistry,
|
|
10557
10786
|
metadata: {
|
|
10558
10787
|
fileName: basename(path),
|
|
10559
10788
|
relativePath: source
|
|
10560
10789
|
},
|
|
10561
10790
|
path,
|
|
10562
10791
|
source
|
|
10563
|
-
}, input.extractors);
|
|
10792
|
+
}, input.extractors, input.extractorRegistry);
|
|
10564
10793
|
return loaded.map((document) => ({
|
|
10565
10794
|
...document,
|
|
10566
10795
|
metadata: mergeMetadata(document.metadata, undefined, input.baseMetadata)
|
|
@@ -10568,6 +10797,7 @@ var loadRAGDocumentsFromDirectory = async (input) => {
|
|
|
10568
10797
|
}));
|
|
10569
10798
|
return {
|
|
10570
10799
|
defaultChunking: input.defaultChunking,
|
|
10800
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
10571
10801
|
documents: documents.flat()
|
|
10572
10802
|
};
|
|
10573
10803
|
};
|
|
@@ -11782,6 +12012,7 @@ var isRAGDocumentUrlArray = (value) => Array.isArray(value) && value.every((entr
|
|
|
11782
12012
|
var isRAGDocumentChunkArray = (value) => Array.isArray(value) && value.every((entry) => isRAGDocumentChunk(entry));
|
|
11783
12013
|
var buildSources2 = (results) => results.map((result) => ({
|
|
11784
12014
|
chunkId: result.chunkId,
|
|
12015
|
+
corpusKey: result.corpusKey ?? (typeof result.metadata?.corpusKey === "string" ? result.metadata.corpusKey : undefined),
|
|
11785
12016
|
labels: buildRAGSourceLabels({
|
|
11786
12017
|
metadata: result.metadata,
|
|
11787
12018
|
source: result.source,
|
|
@@ -11932,6 +12163,8 @@ var buildRAGContextFromQuery = async (config, topK, scoreThreshold, queryText, r
|
|
|
11932
12163
|
};
|
|
11933
12164
|
var ragChat = (config) => {
|
|
11934
12165
|
const path = config.path ?? DEFAULT_PATH2;
|
|
12166
|
+
const authorizeRAGAction = config.authorizeRAGAction;
|
|
12167
|
+
const resolveRAGAccessScope = config.resolveRAGAccessScope;
|
|
11935
12168
|
const topK = config.topK ?? DEFAULT_TOP_K3;
|
|
11936
12169
|
const { scoreThreshold } = config;
|
|
11937
12170
|
const { extractors } = config;
|
|
@@ -11946,6 +12179,13 @@ var ragChat = (config) => {
|
|
|
11946
12179
|
const adminActions = [];
|
|
11947
12180
|
const adminJobs = [];
|
|
11948
12181
|
const syncJobs = [];
|
|
12182
|
+
const { jobStateStore } = config;
|
|
12183
|
+
const jobHistoryRetention = {
|
|
12184
|
+
maxAdminActions: config.jobHistoryRetention?.maxAdminActions ?? MAX_ADMIN_ACTIONS,
|
|
12185
|
+
maxAdminJobs: config.jobHistoryRetention?.maxAdminJobs ?? MAX_ADMIN_JOBS,
|
|
12186
|
+
maxIngestJobs: config.jobHistoryRetention?.maxIngestJobs ?? MAX_INGEST_JOBS,
|
|
12187
|
+
maxSyncJobs: config.jobHistoryRetention?.maxSyncJobs ?? MAX_ADMIN_JOBS
|
|
12188
|
+
};
|
|
11949
12189
|
const { searchTraceStore } = config;
|
|
11950
12190
|
const { searchTraceRetention } = config;
|
|
11951
12191
|
const { searchTraceRetentionSchedule } = config;
|
|
@@ -11964,6 +12204,153 @@ var ragChat = (config) => {
|
|
|
11964
12204
|
retention: searchTraceRetention,
|
|
11965
12205
|
schedule: searchTraceRetentionSchedule
|
|
11966
12206
|
};
|
|
12207
|
+
let jobStateLoaded = false;
|
|
12208
|
+
let jobStateLoadPromise;
|
|
12209
|
+
const normalizeAuthorizationDecision = (decision) => typeof decision === "boolean" ? { allowed: decision } : decision ?? { allowed: true };
|
|
12210
|
+
const checkAuthorization = async (request, action, resource) => {
|
|
12211
|
+
if (!authorizeRAGAction) {
|
|
12212
|
+
return { allowed: true };
|
|
12213
|
+
}
|
|
12214
|
+
return normalizeAuthorizationDecision(await authorizeRAGAction({
|
|
12215
|
+
action,
|
|
12216
|
+
request,
|
|
12217
|
+
resource
|
|
12218
|
+
}));
|
|
12219
|
+
};
|
|
12220
|
+
const isAuthorized = async (request, action, resource) => (await checkAuthorization(request, action, resource)).allowed;
|
|
12221
|
+
const buildAuthorizationFailure = (decision, fallback = "Forbidden") => ({
|
|
12222
|
+
error: decision.reason ?? fallback,
|
|
12223
|
+
ok: false
|
|
12224
|
+
});
|
|
12225
|
+
const isAccessScopeError = (error) => typeof error === "string" && (error.includes("allowed RAG access scope") || error.includes("Scoped sync-all is not allowed"));
|
|
12226
|
+
const authorizeMutationRoute = async (request, action, input) => {
|
|
12227
|
+
const decision = await checkAuthorization(request, action, input.resource);
|
|
12228
|
+
return decision.allowed ? null : buildAuthorizationFailure(decision, input.fallback);
|
|
12229
|
+
};
|
|
12230
|
+
const normalizeAccessScope = (scope) => {
|
|
12231
|
+
if (!scope) {
|
|
12232
|
+
return;
|
|
12233
|
+
}
|
|
12234
|
+
const normalizeStringArray3 = (values) => {
|
|
12235
|
+
const next = (values ?? []).map((value) => value.trim()).filter((value) => value.length > 0);
|
|
12236
|
+
return next.length > 0 ? [...new Set(next)] : undefined;
|
|
12237
|
+
};
|
|
12238
|
+
const requiredMetadata = scope.requiredMetadata && Object.keys(scope.requiredMetadata).length > 0 ? scope.requiredMetadata : undefined;
|
|
12239
|
+
return {
|
|
12240
|
+
allowedComparisonGroupKeys: normalizeStringArray3(scope.allowedComparisonGroupKeys),
|
|
12241
|
+
allowedCorpusGroupKeys: normalizeStringArray3(scope.allowedCorpusGroupKeys),
|
|
12242
|
+
allowedCorpusKeys: normalizeStringArray3(scope.allowedCorpusKeys),
|
|
12243
|
+
allowedDocumentIds: normalizeStringArray3(scope.allowedDocumentIds),
|
|
12244
|
+
allowedSourcePrefixes: normalizeStringArray3(scope.allowedSourcePrefixes),
|
|
12245
|
+
allowedSources: normalizeStringArray3(scope.allowedSources),
|
|
12246
|
+
allowedSyncSourceIds: normalizeStringArray3(scope.allowedSyncSourceIds),
|
|
12247
|
+
requiredMetadata
|
|
12248
|
+
};
|
|
12249
|
+
};
|
|
12250
|
+
const loadAccessScope = async (request) => request && resolveRAGAccessScope ? normalizeAccessScope(await resolveRAGAccessScope(request)) : undefined;
|
|
12251
|
+
const matchesRequiredMetadata = (requiredMetadata, metadata) => {
|
|
12252
|
+
if (!requiredMetadata) {
|
|
12253
|
+
return true;
|
|
12254
|
+
}
|
|
12255
|
+
return Object.entries(requiredMetadata).every(([key, value]) => metadata?.[key] === value);
|
|
12256
|
+
};
|
|
12257
|
+
const matchesAccessScope = (scope, input) => {
|
|
12258
|
+
if (!scope) {
|
|
12259
|
+
return true;
|
|
12260
|
+
}
|
|
12261
|
+
const corpusKey = input.corpusKey ?? (typeof input.metadata?.corpusKey === "string" ? input.metadata.corpusKey : undefined);
|
|
12262
|
+
if (scope.allowedCorpusKeys?.length && (!corpusKey || !scope.allowedCorpusKeys.includes(corpusKey))) {
|
|
12263
|
+
return false;
|
|
12264
|
+
}
|
|
12265
|
+
if (scope.allowedDocumentIds?.length && (!input.documentId || !scope.allowedDocumentIds.includes(input.documentId))) {
|
|
12266
|
+
return false;
|
|
12267
|
+
}
|
|
12268
|
+
if (scope.allowedSources?.length && (!input.source || !scope.allowedSources.includes(input.source))) {
|
|
12269
|
+
return false;
|
|
12270
|
+
}
|
|
12271
|
+
if (scope.allowedSourcePrefixes?.length && (!input.source || !scope.allowedSourcePrefixes.some((prefix) => (input.source ?? "").startsWith(prefix)))) {
|
|
12272
|
+
return false;
|
|
12273
|
+
}
|
|
12274
|
+
return matchesRequiredMetadata(scope.requiredMetadata, input.metadata);
|
|
12275
|
+
};
|
|
12276
|
+
const matchesSyncSourceScope = (scope, source) => !scope?.allowedSyncSourceIds?.length || scope.allowedSyncSourceIds.includes(source.id);
|
|
12277
|
+
const deriveCorpusGroupKey = (input) => {
|
|
12278
|
+
const explicitCorpusGroupKey = input.corpusGroupKey?.trim();
|
|
12279
|
+
if (explicitCorpusGroupKey) {
|
|
12280
|
+
return explicitCorpusGroupKey;
|
|
12281
|
+
}
|
|
12282
|
+
const normalizedCorpusKeys = [
|
|
12283
|
+
...new Set((input.corpusKeys ?? []).map((value) => value.trim()).filter((value) => value.length > 0))
|
|
12284
|
+
].sort((left, right) => left.localeCompare(right));
|
|
12285
|
+
if (normalizedCorpusKeys.length === 0) {
|
|
12286
|
+
return;
|
|
12287
|
+
}
|
|
12288
|
+
if (normalizedCorpusKeys.length === 1) {
|
|
12289
|
+
return normalizedCorpusKeys[0];
|
|
12290
|
+
}
|
|
12291
|
+
return normalizedCorpusKeys.join("+");
|
|
12292
|
+
};
|
|
12293
|
+
const isAllowedCorpusGroupKey = (scope, corpusGroupKey) => !scope?.allowedCorpusGroupKeys?.length || typeof corpusGroupKey === "string" && scope.allowedCorpusGroupKeys.includes(corpusGroupKey);
|
|
12294
|
+
const isAllowedComparisonGroupKey = (scope, groupKey) => !scope?.allowedComparisonGroupKeys?.length || typeof groupKey === "string" && scope.allowedComparisonGroupKeys.includes(groupKey);
|
|
12295
|
+
const filterByComparisonGroupKey = (scope, records) => scope?.allowedComparisonGroupKeys?.length ? records.filter((record) => isAllowedComparisonGroupKey(scope, record.groupKey)) : records;
|
|
12296
|
+
const filterByCorpusGroupKey = (scope, records) => scope?.allowedCorpusGroupKeys?.length ? records.filter((record) => isAllowedCorpusGroupKey(scope, record.corpusGroupKey)) : records;
|
|
12297
|
+
const persistJobStateIfConfigured = async () => {
|
|
12298
|
+
if (!jobStateStore) {
|
|
12299
|
+
return;
|
|
12300
|
+
}
|
|
12301
|
+
await jobStateStore.save({
|
|
12302
|
+
adminActions: adminActions.slice(0, Math.max(0, jobHistoryRetention.maxAdminActions)),
|
|
12303
|
+
adminJobs: adminJobs.slice(0, Math.max(0, jobHistoryRetention.maxAdminJobs)),
|
|
12304
|
+
ingestJobs: ingestJobs.slice(0, Math.max(0, jobHistoryRetention.maxIngestJobs)),
|
|
12305
|
+
syncJobs: syncJobs.slice(0, Math.max(0, jobHistoryRetention.maxSyncJobs))
|
|
12306
|
+
});
|
|
12307
|
+
};
|
|
12308
|
+
const recoverIngestJob = (job, recoveredAt) => job.status === "running" ? {
|
|
12309
|
+
...job,
|
|
12310
|
+
elapsedMs: Math.max(0, recoveredAt - job.startedAt),
|
|
12311
|
+
error: job.error ?? "Interrupted before completion during recovery",
|
|
12312
|
+
finishedAt: recoveredAt,
|
|
12313
|
+
status: "failed"
|
|
12314
|
+
} : job;
|
|
12315
|
+
const recoverAdminJob = (job, recoveredAt) => job.status === "running" ? {
|
|
12316
|
+
...job,
|
|
12317
|
+
elapsedMs: Math.max(0, recoveredAt - job.startedAt),
|
|
12318
|
+
error: job.error ?? "Interrupted before completion during recovery",
|
|
12319
|
+
finishedAt: recoveredAt,
|
|
12320
|
+
status: "failed"
|
|
12321
|
+
} : job;
|
|
12322
|
+
const ensureJobStateLoaded = async () => {
|
|
12323
|
+
if (jobStateLoaded) {
|
|
12324
|
+
return;
|
|
12325
|
+
}
|
|
12326
|
+
if (jobStateLoadPromise) {
|
|
12327
|
+
await jobStateLoadPromise;
|
|
12328
|
+
return;
|
|
12329
|
+
}
|
|
12330
|
+
jobStateLoadPromise = (async () => {
|
|
12331
|
+
if (!jobStateStore) {
|
|
12332
|
+
jobStateLoaded = true;
|
|
12333
|
+
return;
|
|
12334
|
+
}
|
|
12335
|
+
const loaded = await jobStateStore.load();
|
|
12336
|
+
const recoveredAt = Date.now();
|
|
12337
|
+
const nextIngestJobs = (loaded?.ingestJobs ?? []).map((job) => recoverIngestJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxIngestJobs));
|
|
12338
|
+
const nextAdminActions = (loaded?.adminActions ?? []).slice(0, Math.max(0, jobHistoryRetention.maxAdminActions));
|
|
12339
|
+
const nextAdminJobs = (loaded?.adminJobs ?? []).map((job) => recoverAdminJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxAdminJobs));
|
|
12340
|
+
const nextSyncJobs = (loaded?.syncJobs ?? []).map((job) => recoverAdminJob(job, recoveredAt)).slice(0, Math.max(0, jobHistoryRetention.maxSyncJobs));
|
|
12341
|
+
adminActions.splice(0, adminActions.length, ...nextAdminActions);
|
|
12342
|
+
ingestJobs.splice(0, ingestJobs.length, ...nextIngestJobs);
|
|
12343
|
+
adminJobs.splice(0, adminJobs.length, ...nextAdminJobs);
|
|
12344
|
+
syncJobs.splice(0, syncJobs.length, ...nextSyncJobs);
|
|
12345
|
+
jobStateLoaded = true;
|
|
12346
|
+
await persistJobStateIfConfigured();
|
|
12347
|
+
})();
|
|
12348
|
+
try {
|
|
12349
|
+
await jobStateLoadPromise;
|
|
12350
|
+
} finally {
|
|
12351
|
+
jobStateLoadPromise = undefined;
|
|
12352
|
+
}
|
|
12353
|
+
};
|
|
11967
12354
|
const createIngestJob = (inputKind, requestedCount) => {
|
|
11968
12355
|
const job = {
|
|
11969
12356
|
id: generateId(),
|
|
@@ -11973,9 +12360,10 @@ var ragChat = (config) => {
|
|
|
11973
12360
|
status: "running"
|
|
11974
12361
|
};
|
|
11975
12362
|
ingestJobs.unshift(job);
|
|
11976
|
-
if (ingestJobs.length >
|
|
11977
|
-
ingestJobs.length =
|
|
12363
|
+
if (ingestJobs.length > jobHistoryRetention.maxIngestJobs) {
|
|
12364
|
+
ingestJobs.length = jobHistoryRetention.maxIngestJobs;
|
|
11978
12365
|
}
|
|
12366
|
+
persistJobStateIfConfigured();
|
|
11979
12367
|
return job;
|
|
11980
12368
|
};
|
|
11981
12369
|
const completeIngestJob = (job, input) => {
|
|
@@ -11986,6 +12374,7 @@ var ragChat = (config) => {
|
|
|
11986
12374
|
job.chunkCount = input.chunkCount;
|
|
11987
12375
|
job.documentCount = input.documentCount;
|
|
11988
12376
|
job.extractorNames = input.extractorNames;
|
|
12377
|
+
persistJobStateIfConfigured();
|
|
11989
12378
|
};
|
|
11990
12379
|
const failIngestJob = (job, error, extractorNames) => {
|
|
11991
12380
|
const finishedAt = Date.now();
|
|
@@ -11994,6 +12383,7 @@ var ragChat = (config) => {
|
|
|
11994
12383
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
11995
12384
|
job.error = error;
|
|
11996
12385
|
job.extractorNames = extractorNames;
|
|
12386
|
+
persistJobStateIfConfigured();
|
|
11997
12387
|
};
|
|
11998
12388
|
const createAdminAction = (action, documentId, target) => {
|
|
11999
12389
|
const record = {
|
|
@@ -12005,9 +12395,10 @@ var ragChat = (config) => {
|
|
|
12005
12395
|
target
|
|
12006
12396
|
};
|
|
12007
12397
|
adminActions.unshift(record);
|
|
12008
|
-
if (adminActions.length >
|
|
12009
|
-
adminActions.length =
|
|
12398
|
+
if (adminActions.length > jobHistoryRetention.maxAdminActions) {
|
|
12399
|
+
adminActions.length = jobHistoryRetention.maxAdminActions;
|
|
12010
12400
|
}
|
|
12401
|
+
persistJobStateIfConfigured();
|
|
12011
12402
|
return record;
|
|
12012
12403
|
};
|
|
12013
12404
|
const createAdminJob = (action, target, bucket = adminJobs) => {
|
|
@@ -12019,9 +12410,11 @@ var ragChat = (config) => {
|
|
|
12019
12410
|
target
|
|
12020
12411
|
};
|
|
12021
12412
|
bucket.unshift(job);
|
|
12022
|
-
|
|
12023
|
-
|
|
12413
|
+
const maxJobs = bucket === syncJobs ? jobHistoryRetention.maxSyncJobs : jobHistoryRetention.maxAdminJobs;
|
|
12414
|
+
if (bucket.length > maxJobs) {
|
|
12415
|
+
bucket.length = maxJobs;
|
|
12024
12416
|
}
|
|
12417
|
+
persistJobStateIfConfigured();
|
|
12025
12418
|
return job;
|
|
12026
12419
|
};
|
|
12027
12420
|
const completeAdminAction = (record) => {
|
|
@@ -12029,6 +12422,7 @@ var ragChat = (config) => {
|
|
|
12029
12422
|
record.status = "completed";
|
|
12030
12423
|
record.finishedAt = finishedAt;
|
|
12031
12424
|
record.elapsedMs = finishedAt - record.startedAt;
|
|
12425
|
+
persistJobStateIfConfigured();
|
|
12032
12426
|
};
|
|
12033
12427
|
const failAdminAction = (record, error) => {
|
|
12034
12428
|
const finishedAt = Date.now();
|
|
@@ -12036,12 +12430,14 @@ var ragChat = (config) => {
|
|
|
12036
12430
|
record.finishedAt = finishedAt;
|
|
12037
12431
|
record.elapsedMs = finishedAt - record.startedAt;
|
|
12038
12432
|
record.error = error;
|
|
12433
|
+
persistJobStateIfConfigured();
|
|
12039
12434
|
};
|
|
12040
12435
|
const completeAdminJob = (job) => {
|
|
12041
12436
|
const finishedAt = Date.now();
|
|
12042
12437
|
job.status = "completed";
|
|
12043
12438
|
job.finishedAt = finishedAt;
|
|
12044
12439
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
12440
|
+
persistJobStateIfConfigured();
|
|
12045
12441
|
};
|
|
12046
12442
|
const failAdminJob = (job, error) => {
|
|
12047
12443
|
const finishedAt = Date.now();
|
|
@@ -12049,8 +12445,10 @@ var ragChat = (config) => {
|
|
|
12049
12445
|
job.finishedAt = finishedAt;
|
|
12050
12446
|
job.elapsedMs = finishedAt - job.startedAt;
|
|
12051
12447
|
job.error = error;
|
|
12448
|
+
persistJobStateIfConfigured();
|
|
12052
12449
|
};
|
|
12053
12450
|
const runSearchTracePrune = async (input, trigger = "manual") => {
|
|
12451
|
+
await ensureJobStateLoaded();
|
|
12054
12452
|
if (!searchTraceStore) {
|
|
12055
12453
|
throw new Error("RAG search trace store is not configured");
|
|
12056
12454
|
}
|
|
@@ -12138,11 +12536,12 @@ var ragChat = (config) => {
|
|
|
12138
12536
|
throw error;
|
|
12139
12537
|
}
|
|
12140
12538
|
};
|
|
12141
|
-
const buildSyncSources = async () => {
|
|
12539
|
+
const buildSyncSources = async (scope) => {
|
|
12142
12540
|
if (!indexManager?.listSyncSources) {
|
|
12143
12541
|
return [];
|
|
12144
12542
|
}
|
|
12145
|
-
|
|
12543
|
+
const sources = await indexManager.listSyncSources();
|
|
12544
|
+
return sources.filter((source) => matchesSyncSourceScope(scope, source));
|
|
12146
12545
|
};
|
|
12147
12546
|
const toHTMXResponse = (html, status, extraHeaders) => new Response(html, {
|
|
12148
12547
|
headers: {
|
|
@@ -12306,6 +12705,7 @@ var ragChat = (config) => {
|
|
|
12306
12705
|
return null;
|
|
12307
12706
|
}
|
|
12308
12707
|
return {
|
|
12708
|
+
corpusKey: getStringProperty(candidate, "corpusKey") ?? undefined,
|
|
12309
12709
|
filter: caseFilter,
|
|
12310
12710
|
id: getStringProperty(candidate, "id") ?? `case-${caseIndex + 1}`,
|
|
12311
12711
|
retrieval: parsedCaseRetrieval === undefined || parsedCaseRetrieval === null ? undefined : parsedCaseRetrieval,
|
|
@@ -12343,7 +12743,7 @@ var ragChat = (config) => {
|
|
|
12343
12743
|
scoreThreshold: typeof getNumberProperty(body, "scoreThreshold") === "number" ? getNumberProperty(body, "scoreThreshold") : undefined
|
|
12344
12744
|
};
|
|
12345
12745
|
};
|
|
12346
|
-
const handleEvaluate = async (body) => {
|
|
12746
|
+
const handleEvaluate = async (body, request) => {
|
|
12347
12747
|
const input = toRAGEvaluationInput(body);
|
|
12348
12748
|
if (!input) {
|
|
12349
12749
|
return {
|
|
@@ -12351,6 +12751,17 @@ var ragChat = (config) => {
|
|
|
12351
12751
|
ok: false
|
|
12352
12752
|
};
|
|
12353
12753
|
}
|
|
12754
|
+
const accessScope = await loadAccessScope(request);
|
|
12755
|
+
for (const evaluationCase of input.cases) {
|
|
12756
|
+
if (evaluationCase.corpusKey && !matchesAccessScope(accessScope, {
|
|
12757
|
+
corpusKey: evaluationCase.corpusKey
|
|
12758
|
+
}) || (evaluationCase.expectedDocumentIds ?? []).some((documentId) => !matchesAccessScope(accessScope, { documentId })) || (evaluationCase.expectedSources ?? []).some((source) => !matchesAccessScope(accessScope, { source }))) {
|
|
12759
|
+
return {
|
|
12760
|
+
error: "Evaluation case is outside the allowed RAG access scope",
|
|
12761
|
+
ok: false
|
|
12762
|
+
};
|
|
12763
|
+
}
|
|
12764
|
+
}
|
|
12354
12765
|
const collection = resolveCollection();
|
|
12355
12766
|
if (!collection) {
|
|
12356
12767
|
return {
|
|
@@ -12393,6 +12804,7 @@ var ragChat = (config) => {
|
|
|
12393
12804
|
...input,
|
|
12394
12805
|
baselineRetrievalId: getStringProperty(body, "baselineRetrievalId"),
|
|
12395
12806
|
candidateRetrievalId: getStringProperty(body, "candidateRetrievalId"),
|
|
12807
|
+
corpusGroupKey: getStringProperty(body, "corpusGroupKey"),
|
|
12396
12808
|
groupKey: getStringProperty(body, "groupKey"),
|
|
12397
12809
|
label: getStringProperty(body, "label"),
|
|
12398
12810
|
persistRun: getBooleanProperty(body, "persistRun") === true,
|
|
@@ -12410,6 +12822,7 @@ var ragChat = (config) => {
|
|
|
12410
12822
|
return null;
|
|
12411
12823
|
}
|
|
12412
12824
|
return {
|
|
12825
|
+
corpusGroupKey: getStringProperty(body, "corpusGroupKey"),
|
|
12413
12826
|
groupKey,
|
|
12414
12827
|
approvedAt: getIntegerLikeProperty(body, "approvedAt"),
|
|
12415
12828
|
approvedBy: getStringProperty(body, "approvedBy"),
|
|
@@ -12438,6 +12851,7 @@ var ragChat = (config) => {
|
|
|
12438
12851
|
return null;
|
|
12439
12852
|
}
|
|
12440
12853
|
return {
|
|
12854
|
+
corpusGroupKey: getStringProperty(body, "corpusGroupKey"),
|
|
12441
12855
|
groupKey,
|
|
12442
12856
|
overrideGate: getBooleanProperty(body, "overrideGate") === true,
|
|
12443
12857
|
overrideReason: getStringProperty(body, "overrideReason"),
|
|
@@ -12468,6 +12882,7 @@ var ragChat = (config) => {
|
|
|
12468
12882
|
return null;
|
|
12469
12883
|
}
|
|
12470
12884
|
return {
|
|
12885
|
+
corpusGroupKey: getStringProperty(body, "corpusGroupKey"),
|
|
12471
12886
|
groupKey,
|
|
12472
12887
|
approvedAt: getIntegerLikeProperty(body, "approvedAt"),
|
|
12473
12888
|
approvedBy: getStringProperty(body, "approvedBy"),
|
|
@@ -12514,6 +12929,7 @@ var ragChat = (config) => {
|
|
|
12514
12929
|
}
|
|
12515
12930
|
return {
|
|
12516
12931
|
candidateRetrievalId: getStringProperty(body, "candidateRetrievalId"),
|
|
12932
|
+
corpusGroupKey: getStringProperty(body, "corpusGroupKey"),
|
|
12517
12933
|
decidedAt: getIntegerLikeProperty(body, "decidedAt"),
|
|
12518
12934
|
decidedBy: getStringProperty(body, "decidedBy"),
|
|
12519
12935
|
executePromotion: getBooleanProperty(body, "executePromotion") === true,
|
|
@@ -12853,7 +13269,7 @@ var ragChat = (config) => {
|
|
|
12853
13269
|
});
|
|
12854
13270
|
return incidents.find((entry) => entry.id === incidentId);
|
|
12855
13271
|
};
|
|
12856
|
-
const handleEvaluateRetrievals = async (body) => {
|
|
13272
|
+
const handleEvaluateRetrievals = async (body, request) => {
|
|
12857
13273
|
const input = toRAGRetrievalComparisonRequest(body);
|
|
12858
13274
|
if (!input) {
|
|
12859
13275
|
return {
|
|
@@ -12861,6 +13277,29 @@ var ragChat = (config) => {
|
|
|
12861
13277
|
ok: false
|
|
12862
13278
|
};
|
|
12863
13279
|
}
|
|
13280
|
+
const accessScope = await loadAccessScope(request);
|
|
13281
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
13282
|
+
return {
|
|
13283
|
+
error: "Retrieval comparison group is outside the allowed RAG access scope",
|
|
13284
|
+
ok: false
|
|
13285
|
+
};
|
|
13286
|
+
}
|
|
13287
|
+
if (!isAllowedCorpusGroupKey(accessScope, input.corpusGroupKey)) {
|
|
13288
|
+
return {
|
|
13289
|
+
error: "Retrieval comparison corpus group is outside the allowed RAG access scope",
|
|
13290
|
+
ok: false
|
|
13291
|
+
};
|
|
13292
|
+
}
|
|
13293
|
+
for (const evaluationCase of input.cases) {
|
|
13294
|
+
if (evaluationCase.corpusKey && !matchesAccessScope(accessScope, {
|
|
13295
|
+
corpusKey: evaluationCase.corpusKey
|
|
13296
|
+
}) || (evaluationCase.expectedDocumentIds ?? []).some((documentId) => !matchesAccessScope(accessScope, { documentId })) || (evaluationCase.expectedSources ?? []).some((source) => !matchesAccessScope(accessScope, { source }))) {
|
|
13297
|
+
return {
|
|
13298
|
+
error: "Retrieval comparison case is outside the allowed RAG access scope",
|
|
13299
|
+
ok: false
|
|
13300
|
+
};
|
|
13301
|
+
}
|
|
13302
|
+
}
|
|
12864
13303
|
const collection = resolveCollection();
|
|
12865
13304
|
if (!collection) {
|
|
12866
13305
|
return {
|
|
@@ -12896,6 +13335,19 @@ var ragChat = (config) => {
|
|
|
12896
13335
|
label: suiteLabel
|
|
12897
13336
|
}
|
|
12898
13337
|
});
|
|
13338
|
+
const corpusGroupKey = deriveCorpusGroupKey({
|
|
13339
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13340
|
+
corpusKeys: comparison.corpusKeys
|
|
13341
|
+
});
|
|
13342
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
13343
|
+
return {
|
|
13344
|
+
error: "Retrieval comparison corpus group is outside the allowed RAG access scope",
|
|
13345
|
+
ok: false
|
|
13346
|
+
};
|
|
13347
|
+
}
|
|
13348
|
+
if (corpusGroupKey) {
|
|
13349
|
+
comparison.corpusGroupKey = corpusGroupKey;
|
|
13350
|
+
}
|
|
12899
13351
|
if (input.persistRun && retrievalComparisonHistoryStore) {
|
|
12900
13352
|
const finishedAt = Date.now();
|
|
12901
13353
|
const decisionSummary = buildRAGRetrievalComparisonDecisionSummary({
|
|
@@ -12907,6 +13359,8 @@ var ragChat = (config) => {
|
|
|
12907
13359
|
await persistRAGRetrievalComparisonRun({
|
|
12908
13360
|
run: {
|
|
12909
13361
|
comparison,
|
|
13362
|
+
corpusGroupKey,
|
|
13363
|
+
corpusKeys: comparison.corpusKeys,
|
|
12910
13364
|
decisionSummary,
|
|
12911
13365
|
elapsedMs: finishedAt - startedAt,
|
|
12912
13366
|
finishedAt,
|
|
@@ -12930,15 +13384,31 @@ var ragChat = (config) => {
|
|
|
12930
13384
|
ok: true
|
|
12931
13385
|
};
|
|
12932
13386
|
};
|
|
12933
|
-
const handleRetrievalComparisonHistory = async (queryInput) => {
|
|
13387
|
+
const handleRetrievalComparisonHistory = async (queryInput, request) => {
|
|
12934
13388
|
if (!retrievalComparisonHistoryStore) {
|
|
12935
13389
|
return {
|
|
12936
13390
|
error: "RAG retrieval comparison history store is not configured",
|
|
12937
13391
|
ok: false
|
|
12938
13392
|
};
|
|
12939
13393
|
}
|
|
13394
|
+
const accessScope = await loadAccessScope(request);
|
|
13395
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
13396
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
13397
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
13398
|
+
return {
|
|
13399
|
+
error: "Retrieval comparison group is outside the allowed RAG access scope",
|
|
13400
|
+
ok: false
|
|
13401
|
+
};
|
|
13402
|
+
}
|
|
13403
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
13404
|
+
return {
|
|
13405
|
+
error: "Retrieval comparison corpus group is outside the allowed RAG access scope",
|
|
13406
|
+
ok: false
|
|
13407
|
+
};
|
|
13408
|
+
}
|
|
12940
13409
|
const runs = await loadRAGRetrievalComparisonHistory({
|
|
12941
|
-
|
|
13410
|
+
corpusGroupKey,
|
|
13411
|
+
groupKey,
|
|
12942
13412
|
label: getStringProperty(queryInput, "label"),
|
|
12943
13413
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
12944
13414
|
store: retrievalComparisonHistoryStore,
|
|
@@ -12948,25 +13418,41 @@ var ragChat = (config) => {
|
|
|
12948
13418
|
});
|
|
12949
13419
|
return {
|
|
12950
13420
|
ok: true,
|
|
12951
|
-
runs
|
|
13421
|
+
runs: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, runs))
|
|
12952
13422
|
};
|
|
12953
13423
|
};
|
|
12954
|
-
const handleRetrievalBaselineList = async (queryInput) => {
|
|
13424
|
+
const handleRetrievalBaselineList = async (queryInput, request) => {
|
|
12955
13425
|
if (!retrievalBaselineStore) {
|
|
12956
13426
|
return {
|
|
12957
13427
|
error: "RAG retrieval baseline store is not configured",
|
|
12958
13428
|
ok: false
|
|
12959
13429
|
};
|
|
12960
13430
|
}
|
|
13431
|
+
const accessScope = await loadAccessScope(request);
|
|
13432
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
13433
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
13434
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
13435
|
+
return {
|
|
13436
|
+
error: "Retrieval baseline group is outside the allowed RAG access scope",
|
|
13437
|
+
ok: false
|
|
13438
|
+
};
|
|
13439
|
+
}
|
|
13440
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
13441
|
+
return {
|
|
13442
|
+
error: "Retrieval baseline corpus group is outside the allowed RAG access scope",
|
|
13443
|
+
ok: false
|
|
13444
|
+
};
|
|
13445
|
+
}
|
|
12961
13446
|
const baselines = await loadRAGRetrievalBaselines({
|
|
12962
|
-
|
|
13447
|
+
corpusGroupKey,
|
|
13448
|
+
groupKey,
|
|
12963
13449
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
12964
13450
|
status: getStringProperty(queryInput, "status") === "active" || getStringProperty(queryInput, "status") === "superseded" ? getStringProperty(queryInput, "status") : undefined,
|
|
12965
13451
|
store: retrievalBaselineStore,
|
|
12966
13452
|
tag: getStringProperty(queryInput, "tag")
|
|
12967
13453
|
});
|
|
12968
13454
|
return {
|
|
12969
|
-
baselines,
|
|
13455
|
+
baselines: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, baselines)),
|
|
12970
13456
|
ok: true
|
|
12971
13457
|
};
|
|
12972
13458
|
};
|
|
@@ -12977,6 +13463,7 @@ var ragChat = (config) => {
|
|
|
12977
13463
|
await persistRAGRetrievalReleaseDecision({
|
|
12978
13464
|
record: {
|
|
12979
13465
|
baselineId: input.baseline?.id,
|
|
13466
|
+
corpusGroupKey: input.baseline?.corpusGroupKey ?? input.corpusGroupKey,
|
|
12980
13467
|
decidedAt: input.baseline?.promotedAt ?? input.decidedAt ?? Date.now(),
|
|
12981
13468
|
decidedBy: input.decidedBy,
|
|
12982
13469
|
groupKey: input.baseline?.groupKey ?? input.groupKey,
|
|
@@ -13093,6 +13580,7 @@ var ragChat = (config) => {
|
|
|
13093
13580
|
await persistRAGRetrievalLaneHandoffIncidentHistory({
|
|
13094
13581
|
record: {
|
|
13095
13582
|
action: input.action,
|
|
13583
|
+
corpusGroupKey: input.incident.corpusGroupKey,
|
|
13096
13584
|
groupKey: input.incident.groupKey,
|
|
13097
13585
|
id: generateId(),
|
|
13098
13586
|
incidentId: input.incident.id,
|
|
@@ -13115,6 +13603,7 @@ var ragChat = (config) => {
|
|
|
13115
13603
|
await persistRAGRetrievalLaneHandoffAutoCompletePolicyHistory({
|
|
13116
13604
|
record: {
|
|
13117
13605
|
changeKind: input.changeKind,
|
|
13606
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13118
13607
|
enabled: input.enabled,
|
|
13119
13608
|
groupKey: input.groupKey,
|
|
13120
13609
|
id: generateId(),
|
|
@@ -13135,6 +13624,7 @@ var ragChat = (config) => {
|
|
|
13135
13624
|
record: {
|
|
13136
13625
|
approvalMaxAgeMs: input.approvalMaxAgeMs,
|
|
13137
13626
|
changeKind: input.changeKind,
|
|
13627
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13138
13628
|
groupKey: input.groupKey,
|
|
13139
13629
|
id: generateId(),
|
|
13140
13630
|
previousApprovalMaxAgeMs: input.previousApprovalMaxAgeMs,
|
|
@@ -13154,6 +13644,7 @@ var ragChat = (config) => {
|
|
|
13154
13644
|
await persistRAGRetrievalBaselineGatePolicyHistory({
|
|
13155
13645
|
record: {
|
|
13156
13646
|
changeKind: input.changeKind,
|
|
13647
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13157
13648
|
groupKey: input.groupKey,
|
|
13158
13649
|
id: generateId(),
|
|
13159
13650
|
policy: input.policy,
|
|
@@ -13173,6 +13664,7 @@ var ragChat = (config) => {
|
|
|
13173
13664
|
record: {
|
|
13174
13665
|
approvalExpiredSeverity: input.approvalExpiredSeverity,
|
|
13175
13666
|
changeKind: input.changeKind,
|
|
13667
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13176
13668
|
gateFailureSeverity: input.gateFailureSeverity,
|
|
13177
13669
|
groupKey: input.groupKey,
|
|
13178
13670
|
id: generateId(),
|
|
@@ -13261,6 +13753,7 @@ var ragChat = (config) => {
|
|
|
13261
13753
|
const matchingHandoff = (input.handoffs ?? []).find((entry) => entry.groupKey === incident.groupKey && entry.targetRolloutLabel === incident.targetRolloutLabel);
|
|
13262
13754
|
const laneIncident = {
|
|
13263
13755
|
...incident,
|
|
13756
|
+
corpusGroupKey: matchingHandoff?.corpusGroupKey,
|
|
13264
13757
|
kind: "handoff_stale",
|
|
13265
13758
|
sourceRolloutLabel: matchingHandoff?.sourceRolloutLabel
|
|
13266
13759
|
};
|
|
@@ -13660,6 +14153,7 @@ var ragChat = (config) => {
|
|
|
13660
14153
|
approvedAt: input.approvedAt,
|
|
13661
14154
|
approvedBy: input.approvedBy,
|
|
13662
14155
|
approvalNotes: input.approvalNotes,
|
|
14156
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13663
14157
|
groupKey: input.groupKey,
|
|
13664
14158
|
id: generateId(),
|
|
13665
14159
|
label: input.label ?? input.retrievalId,
|
|
@@ -13679,7 +14173,7 @@ var ragChat = (config) => {
|
|
|
13679
14173
|
});
|
|
13680
14174
|
return baseline;
|
|
13681
14175
|
};
|
|
13682
|
-
const handlePromoteRetrievalBaseline = async (body) => {
|
|
14176
|
+
const handlePromoteRetrievalBaseline = async (body, request) => {
|
|
13683
14177
|
if (!retrievalBaselineStore) {
|
|
13684
14178
|
return {
|
|
13685
14179
|
error: "RAG retrieval baseline store is not configured",
|
|
@@ -13693,6 +14187,19 @@ var ragChat = (config) => {
|
|
|
13693
14187
|
ok: false
|
|
13694
14188
|
};
|
|
13695
14189
|
}
|
|
14190
|
+
const accessScope = await loadAccessScope(request);
|
|
14191
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
14192
|
+
return {
|
|
14193
|
+
error: "Retrieval baseline group is outside the allowed RAG access scope",
|
|
14194
|
+
ok: false
|
|
14195
|
+
};
|
|
14196
|
+
}
|
|
14197
|
+
if (!isAllowedCorpusGroupKey(accessScope, input.corpusGroupKey)) {
|
|
14198
|
+
return {
|
|
14199
|
+
error: "Retrieval baseline corpus group is outside the allowed RAG access scope",
|
|
14200
|
+
ok: false
|
|
14201
|
+
};
|
|
14202
|
+
}
|
|
13696
14203
|
const job = createAdminJob("promote_retrieval_baseline", input.groupKey);
|
|
13697
14204
|
const action = createAdminAction("promote_retrieval_baseline", undefined, input.groupKey);
|
|
13698
14205
|
try {
|
|
@@ -13735,6 +14242,7 @@ var ragChat = (config) => {
|
|
|
13735
14242
|
approvedAt: input.approvedAt,
|
|
13736
14243
|
approvedBy: input.approvedBy,
|
|
13737
14244
|
approvalNotes: input.approvalNotes,
|
|
14245
|
+
corpusGroupKey: input.corpusGroupKey,
|
|
13738
14246
|
groupKey: input.groupKey,
|
|
13739
14247
|
label: input.label,
|
|
13740
14248
|
metadata: input.metadata,
|
|
@@ -13748,6 +14256,7 @@ var ragChat = (config) => {
|
|
|
13748
14256
|
});
|
|
13749
14257
|
await persistRetrievalReleaseDecisionIfConfigured({
|
|
13750
14258
|
baseline,
|
|
14259
|
+
corpusGroupKey: baseline.corpusGroupKey,
|
|
13751
14260
|
decidedBy: input.approvedBy,
|
|
13752
14261
|
kind: "promote",
|
|
13753
14262
|
notes: input.approvalNotes,
|
|
@@ -13776,7 +14285,7 @@ var ragChat = (config) => {
|
|
|
13776
14285
|
};
|
|
13777
14286
|
}
|
|
13778
14287
|
};
|
|
13779
|
-
const handlePromoteRetrievalBaselineFromRun = async (body) => {
|
|
14288
|
+
const handlePromoteRetrievalBaselineFromRun = async (body, request) => {
|
|
13780
14289
|
if (!retrievalBaselineStore || !retrievalComparisonHistoryStore) {
|
|
13781
14290
|
return {
|
|
13782
14291
|
error: "RAG retrieval baseline store and retrieval comparison history store are required",
|
|
@@ -13790,6 +14299,19 @@ var ragChat = (config) => {
|
|
|
13790
14299
|
ok: false
|
|
13791
14300
|
};
|
|
13792
14301
|
}
|
|
14302
|
+
const accessScope = await loadAccessScope(request);
|
|
14303
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
14304
|
+
return {
|
|
14305
|
+
error: "Retrieval baseline group is outside the allowed RAG access scope",
|
|
14306
|
+
ok: false
|
|
14307
|
+
};
|
|
14308
|
+
}
|
|
14309
|
+
if (!isAllowedCorpusGroupKey(accessScope, input.corpusGroupKey)) {
|
|
14310
|
+
return {
|
|
14311
|
+
error: "Retrieval baseline corpus group is outside the allowed RAG access scope",
|
|
14312
|
+
ok: false
|
|
14313
|
+
};
|
|
14314
|
+
}
|
|
13793
14315
|
const job = createAdminJob("promote_retrieval_baseline", input.groupKey);
|
|
13794
14316
|
const action = createAdminAction("promote_retrieval_baseline", undefined, input.groupKey);
|
|
13795
14317
|
try {
|
|
@@ -13801,6 +14323,13 @@ var ragChat = (config) => {
|
|
|
13801
14323
|
if (!sourceRun) {
|
|
13802
14324
|
throw new Error("Retrieval comparison run was not found");
|
|
13803
14325
|
}
|
|
14326
|
+
const corpusGroupKey = deriveCorpusGroupKey({
|
|
14327
|
+
corpusGroupKey: input.corpusGroupKey ?? sourceRun.corpusGroupKey ?? sourceRun.comparison.corpusGroupKey,
|
|
14328
|
+
corpusKeys: sourceRun.corpusKeys ?? sourceRun.comparison.corpusKeys
|
|
14329
|
+
});
|
|
14330
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14331
|
+
throw new Error("Retrieval baseline corpus group is outside the allowed RAG access scope");
|
|
14332
|
+
}
|
|
13804
14333
|
const retrievalId = input.retrievalId ?? sourceRun.decisionSummary?.candidateRetrievalId ?? sourceRun.comparison.summary.bestByPassingRate ?? sourceRun.comparison.entries[0]?.retrievalId;
|
|
13805
14334
|
if (!retrievalId) {
|
|
13806
14335
|
throw new Error("Unable to resolve retrieval candidate from comparison run");
|
|
@@ -13832,6 +14361,7 @@ var ragChat = (config) => {
|
|
|
13832
14361
|
approvedAt: input.approvedAt,
|
|
13833
14362
|
approvedBy: input.approvedBy,
|
|
13834
14363
|
approvalNotes: input.approvalNotes,
|
|
14364
|
+
corpusGroupKey,
|
|
13835
14365
|
groupKey: input.groupKey,
|
|
13836
14366
|
label: entry?.label ?? retrievalId,
|
|
13837
14367
|
metadata: input.metadata,
|
|
@@ -13845,6 +14375,7 @@ var ragChat = (config) => {
|
|
|
13845
14375
|
});
|
|
13846
14376
|
await persistRetrievalReleaseDecisionIfConfigured({
|
|
13847
14377
|
baseline,
|
|
14378
|
+
corpusGroupKey,
|
|
13848
14379
|
decidedBy: input.approvedBy,
|
|
13849
14380
|
gateStatus: gate?.status,
|
|
13850
14381
|
kind: "promote",
|
|
@@ -13876,7 +14407,7 @@ var ragChat = (config) => {
|
|
|
13876
14407
|
};
|
|
13877
14408
|
}
|
|
13878
14409
|
};
|
|
13879
|
-
const handleRevertRetrievalBaseline = async (body) => {
|
|
14410
|
+
const handleRevertRetrievalBaseline = async (body, request) => {
|
|
13880
14411
|
if (!retrievalBaselineStore) {
|
|
13881
14412
|
return {
|
|
13882
14413
|
error: "RAG retrieval baseline store is not configured",
|
|
@@ -13890,6 +14421,19 @@ var ragChat = (config) => {
|
|
|
13890
14421
|
ok: false
|
|
13891
14422
|
};
|
|
13892
14423
|
}
|
|
14424
|
+
const accessScope = await loadAccessScope(request);
|
|
14425
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
14426
|
+
return {
|
|
14427
|
+
error: "Retrieval baseline group is outside the allowed RAG access scope",
|
|
14428
|
+
ok: false
|
|
14429
|
+
};
|
|
14430
|
+
}
|
|
14431
|
+
if (!isAllowedCorpusGroupKey(accessScope, input.corpusGroupKey)) {
|
|
14432
|
+
return {
|
|
14433
|
+
error: "Retrieval baseline corpus group is outside the allowed RAG access scope",
|
|
14434
|
+
ok: false
|
|
14435
|
+
};
|
|
14436
|
+
}
|
|
13893
14437
|
const job = createAdminJob("revert_retrieval_baseline", input.groupKey);
|
|
13894
14438
|
const action = createAdminAction("revert_retrieval_baseline", undefined, input.groupKey);
|
|
13895
14439
|
try {
|
|
@@ -13901,10 +14445,14 @@ var ragChat = (config) => {
|
|
|
13901
14445
|
if (!targetBaseline) {
|
|
13902
14446
|
throw new Error("Retrieval baseline version was not found");
|
|
13903
14447
|
}
|
|
14448
|
+
if (!isAllowedCorpusGroupKey(accessScope, targetBaseline.corpusGroupKey)) {
|
|
14449
|
+
throw new Error("Retrieval baseline corpus group is outside the allowed RAG access scope");
|
|
14450
|
+
}
|
|
13904
14451
|
const baseline = await promoteRetrievalBaselineRecord({
|
|
13905
14452
|
approvedAt: input.approvedAt,
|
|
13906
14453
|
approvedBy: input.approvedBy,
|
|
13907
14454
|
approvalNotes: input.approvalNotes,
|
|
14455
|
+
corpusGroupKey: targetBaseline.corpusGroupKey,
|
|
13908
14456
|
groupKey: input.groupKey,
|
|
13909
14457
|
label: targetBaseline.label,
|
|
13910
14458
|
metadata: {
|
|
@@ -13921,6 +14469,7 @@ var ragChat = (config) => {
|
|
|
13921
14469
|
});
|
|
13922
14470
|
await persistRetrievalReleaseDecisionIfConfigured({
|
|
13923
14471
|
baseline,
|
|
14472
|
+
corpusGroupKey: baseline.corpusGroupKey,
|
|
13924
14473
|
decidedBy: input.approvedBy,
|
|
13925
14474
|
kind: "revert",
|
|
13926
14475
|
notes: input.approvalNotes,
|
|
@@ -13951,24 +14500,40 @@ var ragChat = (config) => {
|
|
|
13951
14500
|
};
|
|
13952
14501
|
}
|
|
13953
14502
|
};
|
|
13954
|
-
const handleRetrievalReleaseDecisionList = async (queryInput) => {
|
|
14503
|
+
const handleRetrievalReleaseDecisionList = async (queryInput, request) => {
|
|
13955
14504
|
if (!config.retrievalReleaseDecisionStore) {
|
|
13956
14505
|
return {
|
|
13957
14506
|
error: "RAG retrieval release decision store is not configured",
|
|
13958
14507
|
ok: false
|
|
13959
14508
|
};
|
|
13960
14509
|
}
|
|
14510
|
+
const accessScope = await loadAccessScope(request);
|
|
14511
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14512
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14513
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14514
|
+
return {
|
|
14515
|
+
error: "Retrieval release decision group is outside the allowed RAG access scope",
|
|
14516
|
+
ok: false
|
|
14517
|
+
};
|
|
14518
|
+
}
|
|
14519
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14520
|
+
return {
|
|
14521
|
+
error: "Retrieval release decision corpus group is outside the allowed RAG access scope",
|
|
14522
|
+
ok: false
|
|
14523
|
+
};
|
|
14524
|
+
}
|
|
13961
14525
|
const kind = getStringProperty(queryInput, "kind");
|
|
13962
14526
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
13963
14527
|
const freshnessStatusFilter = getStringProperty(queryInput, "freshnessStatus");
|
|
13964
14528
|
const decisions = await loadRAGRetrievalReleaseDecisions({
|
|
13965
|
-
|
|
14529
|
+
corpusGroupKey,
|
|
14530
|
+
groupKey,
|
|
13966
14531
|
kind: kind === "approve" || kind === "promote" || kind === "reject" || kind === "revert" ? kind : undefined,
|
|
13967
14532
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
13968
14533
|
store: config.retrievalReleaseDecisionStore
|
|
13969
14534
|
});
|
|
13970
14535
|
return {
|
|
13971
|
-
decisions: decisions.map((decision) => ({
|
|
14536
|
+
decisions: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, decisions)).map((decision) => ({
|
|
13972
14537
|
...decision,
|
|
13973
14538
|
...getDecisionFreshness({ record: decision })
|
|
13974
14539
|
})).filter((decision) => {
|
|
@@ -13986,7 +14551,7 @@ var ragChat = (config) => {
|
|
|
13986
14551
|
ok: true
|
|
13987
14552
|
};
|
|
13988
14553
|
};
|
|
13989
|
-
const handleRetrievalReleaseDecisionAction = async (body, kind) => {
|
|
14554
|
+
const handleRetrievalReleaseDecisionAction = async (body, kind, request) => {
|
|
13990
14555
|
if (!retrievalComparisonHistoryStore || !config.retrievalReleaseDecisionStore) {
|
|
13991
14556
|
return {
|
|
13992
14557
|
error: "RAG retrieval comparison history store and release decision store are required",
|
|
@@ -14000,6 +14565,13 @@ var ragChat = (config) => {
|
|
|
14000
14565
|
ok: false
|
|
14001
14566
|
};
|
|
14002
14567
|
}
|
|
14568
|
+
const accessScope = await loadAccessScope(request);
|
|
14569
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
14570
|
+
return {
|
|
14571
|
+
error: "Retrieval release decision group is outside the allowed RAG access scope",
|
|
14572
|
+
ok: false
|
|
14573
|
+
};
|
|
14574
|
+
}
|
|
14003
14575
|
const runs = await loadRAGRetrievalComparisonHistory({
|
|
14004
14576
|
groupKey: input.groupKey,
|
|
14005
14577
|
store: retrievalComparisonHistoryStore
|
|
@@ -14011,6 +14583,16 @@ var ragChat = (config) => {
|
|
|
14011
14583
|
ok: false
|
|
14012
14584
|
};
|
|
14013
14585
|
}
|
|
14586
|
+
const corpusGroupKey = deriveCorpusGroupKey({
|
|
14587
|
+
corpusGroupKey: sourceRun.corpusGroupKey ?? sourceRun.comparison.corpusGroupKey,
|
|
14588
|
+
corpusKeys: sourceRun.corpusKeys ?? sourceRun.comparison.corpusKeys
|
|
14589
|
+
});
|
|
14590
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14591
|
+
return {
|
|
14592
|
+
error: "Retrieval release decision corpus group is outside the allowed RAG access scope",
|
|
14593
|
+
ok: false
|
|
14594
|
+
};
|
|
14595
|
+
}
|
|
14014
14596
|
const retrievalId = input.retrievalId ?? sourceRun.decisionSummary?.candidateRetrievalId ?? sourceRun.comparison.summary.bestByPassingRate ?? sourceRun.comparison.entries[0]?.retrievalId;
|
|
14015
14597
|
if (!retrievalId) {
|
|
14016
14598
|
return {
|
|
@@ -14040,6 +14622,7 @@ var ragChat = (config) => {
|
|
|
14040
14622
|
const decidedAt = Date.now();
|
|
14041
14623
|
await persistRetrievalReleaseDecisionIfConfigured({
|
|
14042
14624
|
baseline: undefined,
|
|
14625
|
+
corpusGroupKey,
|
|
14043
14626
|
decidedAt: input.decidedAt,
|
|
14044
14627
|
decidedBy: input.decidedBy,
|
|
14045
14628
|
gateStatus: gate?.status,
|
|
@@ -14053,17 +14636,19 @@ var ragChat = (config) => {
|
|
|
14053
14636
|
targetRolloutLabel: input.targetRolloutLabel
|
|
14054
14637
|
});
|
|
14055
14638
|
const decisions = await loadRAGRetrievalReleaseDecisions({
|
|
14639
|
+
corpusGroupKey,
|
|
14056
14640
|
groupKey: input.groupKey,
|
|
14057
14641
|
limit: 10,
|
|
14058
14642
|
store: config.retrievalReleaseDecisionStore
|
|
14059
14643
|
});
|
|
14060
14644
|
return {
|
|
14061
|
-
decisions,
|
|
14645
|
+
decisions: filterByCorpusGroupKey(accessScope, decisions),
|
|
14062
14646
|
ok: true
|
|
14063
14647
|
};
|
|
14064
14648
|
};
|
|
14065
|
-
const handleRetrievalReleaseGroupHistory = async (queryInput) => {
|
|
14649
|
+
const handleRetrievalReleaseGroupHistory = async (queryInput, request) => {
|
|
14066
14650
|
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14651
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14067
14652
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14068
14653
|
if (!groupKey) {
|
|
14069
14654
|
return {
|
|
@@ -14071,7 +14656,21 @@ var ragChat = (config) => {
|
|
|
14071
14656
|
ok: false
|
|
14072
14657
|
};
|
|
14073
14658
|
}
|
|
14659
|
+
const accessScope = await loadAccessScope(request);
|
|
14660
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14661
|
+
return {
|
|
14662
|
+
error: "Retrieval release decision group is outside the allowed RAG access scope",
|
|
14663
|
+
ok: false
|
|
14664
|
+
};
|
|
14665
|
+
}
|
|
14666
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14667
|
+
return {
|
|
14668
|
+
error: "Retrieval release corpus group is outside the allowed RAG access scope",
|
|
14669
|
+
ok: false
|
|
14670
|
+
};
|
|
14671
|
+
}
|
|
14074
14672
|
const decisions = config.retrievalReleaseDecisionStore ? (await loadRAGRetrievalReleaseDecisions({
|
|
14673
|
+
corpusGroupKey,
|
|
14075
14674
|
groupKey,
|
|
14076
14675
|
limit: getIntegerLikeProperty(queryInput, "decisionLimit") ?? 20,
|
|
14077
14676
|
store: config.retrievalReleaseDecisionStore
|
|
@@ -14080,11 +14679,13 @@ var ragChat = (config) => {
|
|
|
14080
14679
|
...getDecisionFreshness({ record: decision })
|
|
14081
14680
|
})).filter((decision) => targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? decision.targetRolloutLabel === targetRolloutLabel : true) : undefined;
|
|
14082
14681
|
const baselines = retrievalBaselineStore ? await loadRAGRetrievalBaselines({
|
|
14682
|
+
corpusGroupKey,
|
|
14083
14683
|
groupKey,
|
|
14084
14684
|
limit: getIntegerLikeProperty(queryInput, "baselineLimit") ?? 20,
|
|
14085
14685
|
store: retrievalBaselineStore
|
|
14086
14686
|
}).then((entries) => targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? entries.filter((entry) => entry.rolloutLabel === targetRolloutLabel) : entries) : undefined;
|
|
14087
14687
|
const runs = retrievalComparisonHistoryStore ? await loadRAGRetrievalComparisonHistory({
|
|
14688
|
+
corpusGroupKey,
|
|
14088
14689
|
groupKey,
|
|
14089
14690
|
limit: getIntegerLikeProperty(queryInput, "runLimit") ?? 20,
|
|
14090
14691
|
store: retrievalComparisonHistoryStore
|
|
@@ -14092,11 +14693,13 @@ var ragChat = (config) => {
|
|
|
14092
14693
|
const latest = decisions?.[0];
|
|
14093
14694
|
return {
|
|
14094
14695
|
baselines,
|
|
14696
|
+
corpusGroupKey: corpusGroupKey ?? decisions?.[0]?.corpusGroupKey ?? baselines?.[0]?.corpusGroupKey ?? runs?.[0]?.corpusGroupKey,
|
|
14095
14697
|
decisions,
|
|
14096
14698
|
groupKey,
|
|
14097
14699
|
ok: true,
|
|
14098
14700
|
runs,
|
|
14099
14701
|
timeline: {
|
|
14702
|
+
corpusGroupKey: corpusGroupKey ?? decisions?.[0]?.corpusGroupKey ?? baselines?.[0]?.corpusGroupKey ?? runs?.[0]?.corpusGroupKey,
|
|
14100
14703
|
groupKey,
|
|
14101
14704
|
lastApprovedAt: decisions?.find((entry) => entry.kind === "approve")?.decidedAt,
|
|
14102
14705
|
lastPromotedAt: decisions?.find((entry) => entry.kind === "promote")?.decidedAt,
|
|
@@ -14108,29 +14711,53 @@ var ragChat = (config) => {
|
|
|
14108
14711
|
}
|
|
14109
14712
|
};
|
|
14110
14713
|
};
|
|
14111
|
-
const handleRetrievalLaneHandoffList = async (queryInput) => {
|
|
14714
|
+
const handleRetrievalLaneHandoffList = async (queryInput, request) => {
|
|
14112
14715
|
const result = await buildOperationsPayload();
|
|
14716
|
+
const accessScope = await loadAccessScope(request);
|
|
14717
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14718
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14719
|
+
return {
|
|
14720
|
+
error: "Retrieval lane handoff corpus group is outside the allowed RAG access scope",
|
|
14721
|
+
ok: false
|
|
14722
|
+
};
|
|
14723
|
+
}
|
|
14113
14724
|
const sourceRolloutLabel = getStringProperty(queryInput, "sourceRolloutLabel");
|
|
14114
14725
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14115
14726
|
const limit = getIntegerLikeProperty(queryInput, "limit");
|
|
14116
|
-
const handoffs = (result.retrievalComparisons?.releaseLaneHandoffs ?? []).filter((entry) => (!getStringProperty(queryInput, "groupKey") || entry.groupKey === getStringProperty(queryInput, "groupKey")) && (sourceRolloutLabel !== "canary" && sourceRolloutLabel !== "stable" && sourceRolloutLabel !== "rollback_target" || entry.sourceRolloutLabel === sourceRolloutLabel) && (targetRolloutLabel !== "canary" && targetRolloutLabel !== "stable" && targetRolloutLabel !== "rollback_target" || entry.targetRolloutLabel === targetRolloutLabel));
|
|
14727
|
+
const handoffs = (result.retrievalComparisons?.releaseLaneHandoffs ?? []).filter((entry) => (!corpusGroupKey || entry.corpusGroupKey === corpusGroupKey) && (!getStringProperty(queryInput, "groupKey") || entry.groupKey === getStringProperty(queryInput, "groupKey")) && (sourceRolloutLabel !== "canary" && sourceRolloutLabel !== "stable" && sourceRolloutLabel !== "rollback_target" || entry.sourceRolloutLabel === sourceRolloutLabel) && (targetRolloutLabel !== "canary" && targetRolloutLabel !== "stable" && targetRolloutLabel !== "rollback_target" || entry.targetRolloutLabel === targetRolloutLabel));
|
|
14117
14728
|
return {
|
|
14118
14729
|
handoffs: typeof limit === "number" ? handoffs.slice(0, limit) : handoffs,
|
|
14119
14730
|
ok: true
|
|
14120
14731
|
};
|
|
14121
14732
|
};
|
|
14122
|
-
const handleRetrievalLaneHandoffDecisionList = async (queryInput) => {
|
|
14733
|
+
const handleRetrievalLaneHandoffDecisionList = async (queryInput, request) => {
|
|
14123
14734
|
if (!config.retrievalLaneHandoffDecisionStore) {
|
|
14124
14735
|
return {
|
|
14125
14736
|
error: "RAG retrieval lane handoff decision store is not configured",
|
|
14126
14737
|
ok: false
|
|
14127
14738
|
};
|
|
14128
14739
|
}
|
|
14740
|
+
const accessScope = await loadAccessScope(request);
|
|
14741
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14742
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14743
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14744
|
+
return {
|
|
14745
|
+
error: "Retrieval lane handoff decision group is outside the allowed RAG access scope",
|
|
14746
|
+
ok: false
|
|
14747
|
+
};
|
|
14748
|
+
}
|
|
14749
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14750
|
+
return {
|
|
14751
|
+
error: "Retrieval lane handoff decision corpus group is outside the allowed RAG access scope",
|
|
14752
|
+
ok: false
|
|
14753
|
+
};
|
|
14754
|
+
}
|
|
14129
14755
|
const sourceRolloutLabel = getStringProperty(queryInput, "sourceRolloutLabel");
|
|
14130
14756
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14131
14757
|
const kind = getStringProperty(queryInput, "kind");
|
|
14132
14758
|
const decisions = await loadRAGRetrievalLaneHandoffDecisions({
|
|
14133
|
-
|
|
14759
|
+
corpusGroupKey,
|
|
14760
|
+
groupKey,
|
|
14134
14761
|
kind: kind === "approve" || kind === "reject" || kind === "complete" ? kind : undefined,
|
|
14135
14762
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14136
14763
|
sourceRolloutLabel: sourceRolloutLabel === "canary" || sourceRolloutLabel === "stable" || sourceRolloutLabel === "rollback_target" ? sourceRolloutLabel : undefined,
|
|
@@ -14138,116 +14765,230 @@ var ragChat = (config) => {
|
|
|
14138
14765
|
targetRolloutLabel: targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? targetRolloutLabel : undefined
|
|
14139
14766
|
});
|
|
14140
14767
|
return {
|
|
14141
|
-
decisions,
|
|
14768
|
+
decisions: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, decisions)),
|
|
14142
14769
|
ok: true
|
|
14143
14770
|
};
|
|
14144
14771
|
};
|
|
14145
|
-
const handleRetrievalLaneHandoffIncidentList = async (queryInput) => {
|
|
14772
|
+
const handleRetrievalLaneHandoffIncidentList = async (queryInput, request) => {
|
|
14146
14773
|
if (!config.retrievalLaneHandoffIncidentStore) {
|
|
14147
14774
|
return {
|
|
14148
14775
|
error: "RAG retrieval lane handoff incident store is not configured",
|
|
14149
14776
|
ok: false
|
|
14150
14777
|
};
|
|
14151
14778
|
}
|
|
14779
|
+
const accessScope = await loadAccessScope(request);
|
|
14780
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14781
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14782
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14783
|
+
return {
|
|
14784
|
+
error: "Retrieval lane handoff incident group is outside the allowed RAG access scope",
|
|
14785
|
+
ok: false
|
|
14786
|
+
};
|
|
14787
|
+
}
|
|
14788
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14789
|
+
return {
|
|
14790
|
+
error: "Retrieval lane handoff incident corpus group is outside the allowed RAG access scope",
|
|
14791
|
+
ok: false
|
|
14792
|
+
};
|
|
14793
|
+
}
|
|
14152
14794
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14153
14795
|
const status = getStringProperty(queryInput, "status");
|
|
14154
14796
|
const severity = getStringProperty(queryInput, "severity");
|
|
14155
14797
|
const incidents = await loadRAGRetrievalLaneHandoffIncidents({
|
|
14156
|
-
|
|
14798
|
+
corpusGroupKey,
|
|
14799
|
+
groupKey,
|
|
14157
14800
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14158
14801
|
severity: severity === "warning" || severity === "critical" ? severity : undefined,
|
|
14159
14802
|
status: status === "open" || status === "resolved" ? status : undefined,
|
|
14160
14803
|
store: config.retrievalLaneHandoffIncidentStore,
|
|
14161
14804
|
targetRolloutLabel: targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? targetRolloutLabel : undefined
|
|
14162
14805
|
});
|
|
14163
|
-
return {
|
|
14806
|
+
return {
|
|
14807
|
+
incidents: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, incidents)),
|
|
14808
|
+
ok: true
|
|
14809
|
+
};
|
|
14164
14810
|
};
|
|
14165
|
-
const handleRetrievalLaneHandoffIncidentHistoryList = async (queryInput) => {
|
|
14811
|
+
const handleRetrievalLaneHandoffIncidentHistoryList = async (queryInput, request) => {
|
|
14166
14812
|
if (!config.retrievalLaneHandoffIncidentHistoryStore) {
|
|
14167
14813
|
return {
|
|
14168
14814
|
error: "RAG retrieval lane handoff incident history store is not configured",
|
|
14169
14815
|
ok: false
|
|
14170
14816
|
};
|
|
14171
14817
|
}
|
|
14818
|
+
const accessScope = await loadAccessScope(request);
|
|
14819
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14820
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14821
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14822
|
+
return {
|
|
14823
|
+
error: "Retrieval lane handoff incident history group is outside the allowed RAG access scope",
|
|
14824
|
+
ok: false
|
|
14825
|
+
};
|
|
14826
|
+
}
|
|
14827
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14828
|
+
return {
|
|
14829
|
+
error: "Retrieval lane handoff incident history corpus group is outside the allowed RAG access scope",
|
|
14830
|
+
ok: false
|
|
14831
|
+
};
|
|
14832
|
+
}
|
|
14172
14833
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14173
14834
|
const action = getStringProperty(queryInput, "action");
|
|
14174
14835
|
const records = await loadRAGRetrievalLaneHandoffIncidentHistory({
|
|
14836
|
+
corpusGroupKey,
|
|
14175
14837
|
action: action === "opened" || action === "acknowledged" || action === "unacknowledged" || action === "resolved" ? action : undefined,
|
|
14176
|
-
groupKey
|
|
14838
|
+
groupKey,
|
|
14177
14839
|
incidentId: getStringProperty(queryInput, "incidentId"),
|
|
14178
14840
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14179
14841
|
store: config.retrievalLaneHandoffIncidentHistoryStore,
|
|
14180
14842
|
targetRolloutLabel: targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? targetRolloutLabel : undefined
|
|
14181
14843
|
});
|
|
14182
|
-
return {
|
|
14844
|
+
return {
|
|
14845
|
+
ok: true,
|
|
14846
|
+
records: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, records))
|
|
14847
|
+
};
|
|
14183
14848
|
};
|
|
14184
|
-
const handleRetrievalLaneHandoffAutoCompletePolicyHistoryList = async (queryInput) => {
|
|
14849
|
+
const handleRetrievalLaneHandoffAutoCompletePolicyHistoryList = async (queryInput, request) => {
|
|
14185
14850
|
if (!config.retrievalLaneHandoffAutoCompletePolicyHistoryStore) {
|
|
14186
14851
|
return {
|
|
14187
14852
|
error: "RAG retrieval lane handoff auto-complete policy history store is not configured",
|
|
14188
14853
|
ok: false
|
|
14189
14854
|
};
|
|
14190
14855
|
}
|
|
14856
|
+
const accessScope = await loadAccessScope(request);
|
|
14857
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14858
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14859
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14860
|
+
return {
|
|
14861
|
+
error: "Retrieval lane handoff auto-complete policy group is outside the allowed RAG access scope",
|
|
14862
|
+
ok: false
|
|
14863
|
+
};
|
|
14864
|
+
}
|
|
14865
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14866
|
+
return {
|
|
14867
|
+
error: "Retrieval lane handoff auto-complete policy corpus group is outside the allowed RAG access scope",
|
|
14868
|
+
ok: false
|
|
14869
|
+
};
|
|
14870
|
+
}
|
|
14191
14871
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14192
14872
|
const records = await loadRAGRetrievalLaneHandoffAutoCompletePolicyHistory({
|
|
14193
|
-
|
|
14873
|
+
corpusGroupKey,
|
|
14874
|
+
groupKey,
|
|
14194
14875
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14195
14876
|
store: config.retrievalLaneHandoffAutoCompletePolicyHistoryStore,
|
|
14196
14877
|
targetRolloutLabel: targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? targetRolloutLabel : undefined
|
|
14197
14878
|
});
|
|
14198
|
-
return {
|
|
14879
|
+
return {
|
|
14880
|
+
ok: true,
|
|
14881
|
+
records: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, records))
|
|
14882
|
+
};
|
|
14199
14883
|
};
|
|
14200
|
-
const handleRetrievalReleaseLanePolicyHistoryList = async (queryInput) => {
|
|
14884
|
+
const handleRetrievalReleaseLanePolicyHistoryList = async (queryInput, request) => {
|
|
14201
14885
|
if (!config.retrievalReleaseLanePolicyHistoryStore) {
|
|
14202
14886
|
return {
|
|
14203
14887
|
error: "RAG retrieval release lane policy history store is not configured",
|
|
14204
14888
|
ok: false
|
|
14205
14889
|
};
|
|
14206
14890
|
}
|
|
14891
|
+
const accessScope = await loadAccessScope(request);
|
|
14892
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14893
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14894
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14895
|
+
return {
|
|
14896
|
+
error: "Retrieval release lane policy group is outside the allowed RAG access scope",
|
|
14897
|
+
ok: false
|
|
14898
|
+
};
|
|
14899
|
+
}
|
|
14900
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14901
|
+
return {
|
|
14902
|
+
error: "Retrieval release lane policy corpus group is outside the allowed RAG access scope",
|
|
14903
|
+
ok: false
|
|
14904
|
+
};
|
|
14905
|
+
}
|
|
14207
14906
|
const rolloutLabel = getStringProperty(queryInput, "rolloutLabel");
|
|
14208
14907
|
const scope = getStringProperty(queryInput, "scope");
|
|
14209
14908
|
const records = await loadRAGRetrievalReleaseLanePolicyHistory({
|
|
14210
|
-
|
|
14909
|
+
corpusGroupKey,
|
|
14910
|
+
groupKey,
|
|
14211
14911
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14212
14912
|
rolloutLabel: rolloutLabel === "canary" || rolloutLabel === "stable" || rolloutLabel === "rollback_target" ? rolloutLabel : undefined,
|
|
14213
14913
|
scope: scope === "rollout_label" || scope === "group_rollout_label" ? scope : undefined,
|
|
14214
14914
|
store: config.retrievalReleaseLanePolicyHistoryStore
|
|
14215
14915
|
});
|
|
14216
|
-
return {
|
|
14916
|
+
return {
|
|
14917
|
+
ok: true,
|
|
14918
|
+
records: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, records))
|
|
14919
|
+
};
|
|
14217
14920
|
};
|
|
14218
|
-
const handleRetrievalBaselineGatePolicyHistoryList = async (queryInput) => {
|
|
14921
|
+
const handleRetrievalBaselineGatePolicyHistoryList = async (queryInput, request) => {
|
|
14219
14922
|
if (!config.retrievalBaselineGatePolicyHistoryStore) {
|
|
14220
14923
|
return {
|
|
14221
14924
|
error: "RAG retrieval baseline gate policy history store is not configured",
|
|
14222
14925
|
ok: false
|
|
14223
14926
|
};
|
|
14224
14927
|
}
|
|
14928
|
+
const accessScope = await loadAccessScope(request);
|
|
14929
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14930
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14931
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14932
|
+
return {
|
|
14933
|
+
error: "Retrieval baseline gate policy group is outside the allowed RAG access scope",
|
|
14934
|
+
ok: false
|
|
14935
|
+
};
|
|
14936
|
+
}
|
|
14937
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14938
|
+
return {
|
|
14939
|
+
error: "Retrieval baseline gate policy corpus group is outside the allowed RAG access scope",
|
|
14940
|
+
ok: false
|
|
14941
|
+
};
|
|
14942
|
+
}
|
|
14225
14943
|
const rolloutLabel = getStringProperty(queryInput, "rolloutLabel");
|
|
14226
14944
|
const scope = getStringProperty(queryInput, "scope");
|
|
14227
14945
|
const records = await loadRAGRetrievalBaselineGatePolicyHistory({
|
|
14228
|
-
|
|
14946
|
+
corpusGroupKey,
|
|
14947
|
+
groupKey,
|
|
14229
14948
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14230
14949
|
rolloutLabel: rolloutLabel === "canary" || rolloutLabel === "stable" || rolloutLabel === "rollback_target" ? rolloutLabel : undefined,
|
|
14231
14950
|
scope: scope === "rollout_label" || scope === "group_rollout_label" ? scope : undefined,
|
|
14232
14951
|
store: config.retrievalBaselineGatePolicyHistoryStore
|
|
14233
14952
|
});
|
|
14234
|
-
return {
|
|
14953
|
+
return {
|
|
14954
|
+
ok: true,
|
|
14955
|
+
records: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, records))
|
|
14956
|
+
};
|
|
14235
14957
|
};
|
|
14236
|
-
const handleRetrievalReleaseLaneEscalationPolicyHistoryList = async (queryInput) => {
|
|
14958
|
+
const handleRetrievalReleaseLaneEscalationPolicyHistoryList = async (queryInput, request) => {
|
|
14237
14959
|
if (!config.retrievalReleaseLaneEscalationPolicyHistoryStore) {
|
|
14238
14960
|
return {
|
|
14239
14961
|
error: "RAG retrieval release lane escalation policy history store is not configured",
|
|
14240
14962
|
ok: false
|
|
14241
14963
|
};
|
|
14242
14964
|
}
|
|
14965
|
+
const accessScope = await loadAccessScope(request);
|
|
14966
|
+
const groupKey = getStringProperty(queryInput, "groupKey");
|
|
14967
|
+
const corpusGroupKey = getStringProperty(queryInput, "corpusGroupKey");
|
|
14968
|
+
if (!isAllowedComparisonGroupKey(accessScope, groupKey)) {
|
|
14969
|
+
return {
|
|
14970
|
+
error: "Retrieval release lane escalation policy group is outside the allowed RAG access scope",
|
|
14971
|
+
ok: false
|
|
14972
|
+
};
|
|
14973
|
+
}
|
|
14974
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
14975
|
+
return {
|
|
14976
|
+
error: "Retrieval release lane escalation policy corpus group is outside the allowed RAG access scope",
|
|
14977
|
+
ok: false
|
|
14978
|
+
};
|
|
14979
|
+
}
|
|
14243
14980
|
const targetRolloutLabel = getStringProperty(queryInput, "targetRolloutLabel");
|
|
14244
14981
|
const records = await loadRAGRetrievalReleaseLaneEscalationPolicyHistory({
|
|
14245
|
-
|
|
14982
|
+
corpusGroupKey,
|
|
14983
|
+
groupKey,
|
|
14246
14984
|
limit: getIntegerLikeProperty(queryInput, "limit"),
|
|
14247
14985
|
store: config.retrievalReleaseLaneEscalationPolicyHistoryStore,
|
|
14248
14986
|
targetRolloutLabel: targetRolloutLabel === "canary" || targetRolloutLabel === "stable" || targetRolloutLabel === "rollback_target" ? targetRolloutLabel : undefined
|
|
14249
14987
|
});
|
|
14250
|
-
return {
|
|
14988
|
+
return {
|
|
14989
|
+
ok: true,
|
|
14990
|
+
records: filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, records))
|
|
14991
|
+
};
|
|
14251
14992
|
};
|
|
14252
14993
|
const handleRetrievalLaneHandoffDecision = async (body) => {
|
|
14253
14994
|
if (!config.retrievalLaneHandoffDecisionStore) {
|
|
@@ -14263,6 +15004,19 @@ var ragChat = (config) => {
|
|
|
14263
15004
|
ok: false
|
|
14264
15005
|
};
|
|
14265
15006
|
}
|
|
15007
|
+
const accessScope = await loadAccessScope();
|
|
15008
|
+
if (!isAllowedComparisonGroupKey(accessScope, input.groupKey)) {
|
|
15009
|
+
return {
|
|
15010
|
+
error: "Retrieval lane handoff group is outside the allowed RAG access scope",
|
|
15011
|
+
ok: false
|
|
15012
|
+
};
|
|
15013
|
+
}
|
|
15014
|
+
if (!isAllowedCorpusGroupKey(accessScope, input.corpusGroupKey)) {
|
|
15015
|
+
return {
|
|
15016
|
+
error: "Retrieval lane handoff corpus group is outside the allowed RAG access scope",
|
|
15017
|
+
ok: false
|
|
15018
|
+
};
|
|
15019
|
+
}
|
|
14266
15020
|
const ops = await buildOperationsPayload();
|
|
14267
15021
|
const handoff = ops.retrievalComparisons?.releaseLaneHandoffs?.find((entry) => entry.groupKey === input.groupKey && entry.sourceRolloutLabel === input.sourceRolloutLabel && entry.targetRolloutLabel === input.targetRolloutLabel);
|
|
14268
15022
|
if (!handoff) {
|
|
@@ -14271,6 +15025,13 @@ var ragChat = (config) => {
|
|
|
14271
15025
|
ok: false
|
|
14272
15026
|
};
|
|
14273
15027
|
}
|
|
15028
|
+
const corpusGroupKey = input.corpusGroupKey ?? handoff.corpusGroupKey;
|
|
15029
|
+
if (!isAllowedCorpusGroupKey(accessScope, corpusGroupKey)) {
|
|
15030
|
+
return {
|
|
15031
|
+
error: "Retrieval lane handoff corpus group is outside the allowed RAG access scope",
|
|
15032
|
+
ok: false
|
|
15033
|
+
};
|
|
15034
|
+
}
|
|
14274
15035
|
if (input.kind === "approve" && handoff.readyForHandoff !== true) {
|
|
14275
15036
|
return {
|
|
14276
15037
|
error: `handoff is not ready: ${handoff.reasons.join("; ")}`,
|
|
@@ -14295,6 +15056,7 @@ var ragChat = (config) => {
|
|
|
14295
15056
|
approvalNotes: input.notes,
|
|
14296
15057
|
approvedAt: input.decidedAt,
|
|
14297
15058
|
approvedBy: input.decidedBy,
|
|
15059
|
+
corpusGroupKey,
|
|
14298
15060
|
groupKey: input.groupKey,
|
|
14299
15061
|
retrievalId: input.candidateRetrievalId ?? handoff.candidateRetrievalId,
|
|
14300
15062
|
rolloutLabel: input.targetRolloutLabel,
|
|
@@ -14310,6 +15072,7 @@ var ragChat = (config) => {
|
|
|
14310
15072
|
const decision = await persistRAGRetrievalLaneHandoffDecision({
|
|
14311
15073
|
record: {
|
|
14312
15074
|
candidateRetrievalId: input.candidateRetrievalId ?? handoff.candidateRetrievalId,
|
|
15075
|
+
corpusGroupKey,
|
|
14313
15076
|
decidedAt: input.decidedAt ?? Date.now(),
|
|
14314
15077
|
decidedBy: input.decidedBy,
|
|
14315
15078
|
groupKey: input.groupKey,
|
|
@@ -14337,6 +15100,7 @@ var ragChat = (config) => {
|
|
|
14337
15100
|
approvalNotes: input.notes,
|
|
14338
15101
|
approvedAt,
|
|
14339
15102
|
approvedBy: input.decidedBy,
|
|
15103
|
+
corpusGroupKey,
|
|
14340
15104
|
groupKey: input.groupKey,
|
|
14341
15105
|
retrievalId: input.candidateRetrievalId ?? handoff.candidateRetrievalId,
|
|
14342
15106
|
rolloutLabel: input.targetRolloutLabel,
|
|
@@ -14351,6 +15115,7 @@ var ragChat = (config) => {
|
|
|
14351
15115
|
await persistRAGRetrievalLaneHandoffDecision({
|
|
14352
15116
|
record: {
|
|
14353
15117
|
candidateRetrievalId: input.candidateRetrievalId ?? handoff.candidateRetrievalId,
|
|
15118
|
+
corpusGroupKey,
|
|
14354
15119
|
decidedAt: Date.now(),
|
|
14355
15120
|
decidedBy: input.decidedBy,
|
|
14356
15121
|
groupKey: input.groupKey,
|
|
@@ -15313,7 +16078,7 @@ var ragChat = (config) => {
|
|
|
15313
16078
|
return { error: message, ok: false };
|
|
15314
16079
|
}
|
|
15315
16080
|
};
|
|
15316
|
-
const handleSearch = async (body) => {
|
|
16081
|
+
const handleSearch = async (body, request) => {
|
|
15317
16082
|
if (!isObjectRecord2(body)) {
|
|
15318
16083
|
return { error: "Invalid payload", ok: false };
|
|
15319
16084
|
}
|
|
@@ -15325,6 +16090,7 @@ var ragChat = (config) => {
|
|
|
15325
16090
|
};
|
|
15326
16091
|
}
|
|
15327
16092
|
const collection = resolveCollection();
|
|
16093
|
+
const accessScope = await loadAccessScope(request);
|
|
15328
16094
|
if (!collection) {
|
|
15329
16095
|
return { error: "RAG collection is not configured", ok: false };
|
|
15330
16096
|
}
|
|
@@ -15367,14 +16133,28 @@ var ragChat = (config) => {
|
|
|
15367
16133
|
trace: result.trace
|
|
15368
16134
|
});
|
|
15369
16135
|
}
|
|
16136
|
+
const scopedResults = buildSources2(result.results).filter((entry) => matchesAccessScope(accessScope, {
|
|
16137
|
+
corpusKey: entry.corpusKey,
|
|
16138
|
+
documentId: typeof entry.metadata?.documentId === "string" ? entry.metadata.documentId : entry.chunkId.split(":")[0],
|
|
16139
|
+
metadata: entry.metadata,
|
|
16140
|
+
source: entry.source
|
|
16141
|
+
}));
|
|
15370
16142
|
return {
|
|
15371
16143
|
ok: true,
|
|
15372
|
-
results:
|
|
16144
|
+
results: scopedResults,
|
|
15373
16145
|
trace: result.trace
|
|
15374
16146
|
};
|
|
15375
16147
|
}
|
|
15376
16148
|
const results = await collection.search(input);
|
|
15377
|
-
return {
|
|
16149
|
+
return {
|
|
16150
|
+
ok: true,
|
|
16151
|
+
results: buildSources2(results).filter((entry) => matchesAccessScope(accessScope, {
|
|
16152
|
+
corpusKey: entry.corpusKey,
|
|
16153
|
+
documentId: typeof entry.metadata?.documentId === "string" ? entry.metadata.documentId : entry.chunkId.split(":")[0],
|
|
16154
|
+
metadata: entry.metadata,
|
|
16155
|
+
source: entry.source
|
|
16156
|
+
}))
|
|
16157
|
+
};
|
|
15378
16158
|
};
|
|
15379
16159
|
const handleTraceHistory = async (queryInput) => {
|
|
15380
16160
|
if (!searchTraceStore) {
|
|
@@ -15520,7 +16300,10 @@ var ragChat = (config) => {
|
|
|
15520
16300
|
let inspectedChunks = 0;
|
|
15521
16301
|
let documentsWithSourceLabels = 0;
|
|
15522
16302
|
let chunksWithSourceLabels = 0;
|
|
16303
|
+
const corpusKeys = new Map;
|
|
15523
16304
|
const sourceNativeKinds = new Map;
|
|
16305
|
+
const extractorRegistryMatches = new Map;
|
|
16306
|
+
const chunkingProfiles = new Map;
|
|
15524
16307
|
const sampleDocuments = [];
|
|
15525
16308
|
const sampleChunks = [];
|
|
15526
16309
|
let oldestDocumentAgeMs;
|
|
@@ -15572,11 +16355,26 @@ var ragChat = (config) => {
|
|
|
15572
16355
|
documentsWithSourceLabels += 1;
|
|
15573
16356
|
}
|
|
15574
16357
|
const documentSourceNativeKind = typeof document.metadata?.sourceNativeKind === "string" ? document.metadata.sourceNativeKind : undefined;
|
|
16358
|
+
const documentCorpusKey = document.corpusKey ?? (typeof document.metadata?.corpusKey === "string" ? document.metadata.corpusKey : undefined);
|
|
16359
|
+
const documentExtractorRegistryMatch = typeof document.metadata?.extractorRegistryMatch === "string" ? document.metadata.extractorRegistryMatch : undefined;
|
|
16360
|
+
const documentChunkingProfile = typeof document.metadata?.chunkingProfile === "string" ? document.metadata.chunkingProfile : undefined;
|
|
15575
16361
|
if (documentSourceNativeKind) {
|
|
15576
16362
|
sourceNativeKinds.set(documentSourceNativeKind, (sourceNativeKinds.get(documentSourceNativeKind) ?? 0) + 1);
|
|
15577
16363
|
}
|
|
15578
|
-
if (
|
|
16364
|
+
if (documentCorpusKey) {
|
|
16365
|
+
corpusKeys.set(documentCorpusKey, (corpusKeys.get(documentCorpusKey) ?? 0) + 1);
|
|
16366
|
+
}
|
|
16367
|
+
if (documentExtractorRegistryMatch) {
|
|
16368
|
+
extractorRegistryMatches.set(documentExtractorRegistryMatch, (extractorRegistryMatches.get(documentExtractorRegistryMatch) ?? 0) + 1);
|
|
16369
|
+
}
|
|
16370
|
+
if (documentChunkingProfile) {
|
|
16371
|
+
chunkingProfiles.set(documentChunkingProfile, (chunkingProfiles.get(documentChunkingProfile) ?? 0) + 1);
|
|
16372
|
+
}
|
|
16373
|
+
if (sampleDocuments.length < 5 && (documentCorpusKey || documentLabels || documentSourceNativeKind || documentExtractorRegistryMatch || documentChunkingProfile)) {
|
|
15579
16374
|
sampleDocuments.push({
|
|
16375
|
+
corpusKey: documentCorpusKey,
|
|
16376
|
+
chunkingProfile: documentChunkingProfile,
|
|
16377
|
+
extractorRegistryMatch: documentExtractorRegistryMatch,
|
|
15580
16378
|
id: document.id,
|
|
15581
16379
|
labels: documentLabels,
|
|
15582
16380
|
source: document.source,
|
|
@@ -15602,13 +16400,28 @@ var ragChat = (config) => {
|
|
|
15602
16400
|
chunksWithSourceLabels += 1;
|
|
15603
16401
|
}
|
|
15604
16402
|
const chunkSourceNativeKind = typeof chunk.metadata?.sourceNativeKind === "string" ? chunk.metadata.sourceNativeKind : undefined;
|
|
16403
|
+
const chunkCorpusKey = chunk.corpusKey ?? (typeof chunk.metadata?.corpusKey === "string" ? chunk.metadata.corpusKey : documentCorpusKey);
|
|
16404
|
+
const chunkExtractorRegistryMatch = typeof chunk.metadata?.extractorRegistryMatch === "string" ? chunk.metadata.extractorRegistryMatch : undefined;
|
|
16405
|
+
const chunkChunkingProfile = typeof chunk.metadata?.chunkingProfile === "string" ? chunk.metadata.chunkingProfile : undefined;
|
|
15605
16406
|
if (chunkSourceNativeKind) {
|
|
15606
16407
|
sourceNativeKinds.set(chunkSourceNativeKind, (sourceNativeKinds.get(chunkSourceNativeKind) ?? 0) + 1);
|
|
15607
16408
|
}
|
|
15608
|
-
if (
|
|
16409
|
+
if (chunkCorpusKey) {
|
|
16410
|
+
corpusKeys.set(chunkCorpusKey, (corpusKeys.get(chunkCorpusKey) ?? 0) + 1);
|
|
16411
|
+
}
|
|
16412
|
+
if (chunkExtractorRegistryMatch) {
|
|
16413
|
+
extractorRegistryMatches.set(chunkExtractorRegistryMatch, (extractorRegistryMatches.get(chunkExtractorRegistryMatch) ?? 0) + 1);
|
|
16414
|
+
}
|
|
16415
|
+
if (chunkChunkingProfile) {
|
|
16416
|
+
chunkingProfiles.set(chunkChunkingProfile, (chunkingProfiles.get(chunkChunkingProfile) ?? 0) + 1);
|
|
16417
|
+
}
|
|
16418
|
+
if (sampleChunks.length < 8 && (chunkCorpusKey || chunkLabels || chunkSourceNativeKind || chunkExtractorRegistryMatch || chunkChunkingProfile)) {
|
|
15609
16419
|
sampleChunks.push({
|
|
15610
16420
|
chunkId: chunk.chunkId,
|
|
16421
|
+
chunkingProfile: chunkChunkingProfile,
|
|
16422
|
+
corpusKey: chunkCorpusKey,
|
|
15611
16423
|
documentId: document.id,
|
|
16424
|
+
extractorRegistryMatch: chunkExtractorRegistryMatch,
|
|
15612
16425
|
labels: chunkLabels,
|
|
15613
16426
|
source: chunk.source ?? preview.document.source,
|
|
15614
16427
|
sourceNativeKind: chunkSourceNativeKind
|
|
@@ -15671,8 +16484,11 @@ var ragChat = (config) => {
|
|
|
15671
16484
|
inspectedChunks,
|
|
15672
16485
|
inspectedDocuments,
|
|
15673
16486
|
inspection: {
|
|
16487
|
+
chunkingProfiles: Object.fromEntries(chunkingProfiles.entries()),
|
|
16488
|
+
corpusKeys: Object.fromEntries(corpusKeys.entries()),
|
|
15674
16489
|
chunksWithSourceLabels,
|
|
15675
16490
|
documentsWithSourceLabels,
|
|
16491
|
+
extractorRegistryMatches: Object.fromEntries(extractorRegistryMatches.entries()),
|
|
15676
16492
|
sampleChunks,
|
|
15677
16493
|
sampleDocuments,
|
|
15678
16494
|
sourceNativeKinds: Object.fromEntries(sourceNativeKinds.entries())
|
|
@@ -15695,28 +16511,35 @@ var ragChat = (config) => {
|
|
|
15695
16511
|
providerName: typeof config.provider === "function" ? config.readinessProviderName : undefined,
|
|
15696
16512
|
rerankerConfigured: Boolean(config.rerank ?? config.collection)
|
|
15697
16513
|
});
|
|
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)
|
|
16514
|
+
const buildAdminCapabilities = async (request) => ({
|
|
16515
|
+
canClearIndex: Boolean(ragStore?.clear) && (request ? await isAuthorized(request, "clear_index") : true),
|
|
16516
|
+
canCreateDocument: Boolean(indexManager?.createDocument) && (request ? await isAuthorized(request, "create_document") : true),
|
|
16517
|
+
canDeleteDocument: Boolean(indexManager?.deleteDocument) && (request ? await isAuthorized(request, "delete_document") : true),
|
|
16518
|
+
canListSyncSources: Boolean(indexManager?.listSyncSources) && (request ? await isAuthorized(request, "list_sync_sources") : true),
|
|
16519
|
+
canManageRetrievalBaselines: Boolean(retrievalBaselineStore) && (request ? await isAuthorized(request, "manage_retrieval_admin") : true),
|
|
16520
|
+
canPruneSearchTraces: Boolean(searchTraceStore) && (request ? await isAuthorized(request, "prune_search_traces") : true),
|
|
16521
|
+
canReindexDocument: Boolean(indexManager?.reindexDocument) && (request ? await isAuthorized(request, "reindex_document") : true),
|
|
16522
|
+
canReindexSource: Boolean(indexManager?.reindexSource) && (request ? await isAuthorized(request, "reindex_source") : true),
|
|
16523
|
+
canReseed: Boolean(indexManager?.reseed) && (request ? await isAuthorized(request, "reseed") : true),
|
|
16524
|
+
canReset: Boolean(indexManager?.reset) && (request ? await isAuthorized(request, "reset") : true),
|
|
16525
|
+
canSyncAllSources: Boolean(indexManager?.syncAllSources) && (request ? await isAuthorized(request, "sync_all_sources") : true),
|
|
16526
|
+
canSyncSource: Boolean(indexManager?.syncSource) && (request ? await isAuthorized(request, "sync_source") : true)
|
|
15711
16527
|
});
|
|
15712
|
-
const buildOperationsPayload = async () => {
|
|
16528
|
+
const buildOperationsPayload = async (request) => {
|
|
16529
|
+
const accessScope = await loadAccessScope(request);
|
|
16530
|
+
const filterScopedGovernanceEntries = (entries) => entries ? filterByCorpusGroupKey(accessScope, filterByComparisonGroupKey(accessScope, entries)) : undefined;
|
|
15713
16531
|
const collection = config.collection ?? (ragStore ? createRAGCollection({
|
|
15714
16532
|
defaultModel: config.embeddingModel,
|
|
15715
16533
|
defaultTopK: topK,
|
|
15716
16534
|
embedding: config.embedding,
|
|
15717
16535
|
store: ragStore
|
|
15718
16536
|
}) : null);
|
|
15719
|
-
const indexedDocuments = indexManager ? await indexManager.listDocuments({})
|
|
16537
|
+
const indexedDocuments = indexManager ? (await indexManager.listDocuments({})).filter((document) => matchesAccessScope(accessScope, {
|
|
16538
|
+
corpusKey: document.corpusKey,
|
|
16539
|
+
documentId: document.id,
|
|
16540
|
+
metadata: document.metadata,
|
|
16541
|
+
source: document.source
|
|
16542
|
+
})) : [];
|
|
15720
16543
|
const traceStats = searchTraceStore ? await summarizeRAGSearchTraceStore({
|
|
15721
16544
|
store: searchTraceStore
|
|
15722
16545
|
}) : undefined;
|
|
@@ -15724,51 +16547,51 @@ var ragChat = (config) => {
|
|
|
15724
16547
|
limit: 5,
|
|
15725
16548
|
store: searchTracePruneHistoryStore
|
|
15726
16549
|
}) : undefined;
|
|
15727
|
-
const recentRetrievalComparisonRuns = retrievalComparisonHistoryStore ? await loadRAGRetrievalComparisonHistory({
|
|
16550
|
+
const recentRetrievalComparisonRuns = filterScopedGovernanceEntries(retrievalComparisonHistoryStore ? await loadRAGRetrievalComparisonHistory({
|
|
15728
16551
|
limit: 5,
|
|
15729
16552
|
store: retrievalComparisonHistoryStore
|
|
15730
|
-
}) : undefined;
|
|
15731
|
-
const activeRetrievalBaselines = retrievalBaselineStore ? await loadRAGRetrievalBaselines({
|
|
16553
|
+
}) : undefined);
|
|
16554
|
+
const activeRetrievalBaselines = filterScopedGovernanceEntries(retrievalBaselineStore ? await loadRAGRetrievalBaselines({
|
|
15732
16555
|
limit: 5,
|
|
15733
16556
|
status: "active",
|
|
15734
16557
|
store: retrievalBaselineStore
|
|
15735
|
-
}) : undefined;
|
|
15736
|
-
const retrievalBaselineHistory = retrievalBaselineStore ? await loadRAGRetrievalBaselines({
|
|
16558
|
+
}) : undefined);
|
|
16559
|
+
const retrievalBaselineHistory = filterScopedGovernanceEntries(retrievalBaselineStore ? await loadRAGRetrievalBaselines({
|
|
15737
16560
|
limit: 10,
|
|
15738
16561
|
store: retrievalBaselineStore
|
|
15739
|
-
}) : undefined;
|
|
15740
|
-
const recentRetrievalReleaseDecisions = config.retrievalReleaseDecisionStore ? await loadRAGRetrievalReleaseDecisions({
|
|
16562
|
+
}) : undefined);
|
|
16563
|
+
const recentRetrievalReleaseDecisions = filterScopedGovernanceEntries(config.retrievalReleaseDecisionStore ? await loadRAGRetrievalReleaseDecisions({
|
|
15741
16564
|
limit: 10,
|
|
15742
16565
|
store: config.retrievalReleaseDecisionStore
|
|
15743
|
-
}) : undefined;
|
|
15744
|
-
const recentRetrievalLaneHandoffDecisions = config.retrievalLaneHandoffDecisionStore ? await loadRAGRetrievalLaneHandoffDecisions({
|
|
16566
|
+
}) : undefined);
|
|
16567
|
+
const recentRetrievalLaneHandoffDecisions = filterScopedGovernanceEntries(config.retrievalLaneHandoffDecisionStore ? await loadRAGRetrievalLaneHandoffDecisions({
|
|
15745
16568
|
limit: 10,
|
|
15746
16569
|
store: config.retrievalLaneHandoffDecisionStore
|
|
15747
|
-
}) : undefined;
|
|
15748
|
-
const recentRetrievalLaneHandoffIncidents = config.retrievalLaneHandoffIncidentStore ? await loadRAGRetrievalLaneHandoffIncidents({
|
|
16570
|
+
}) : undefined);
|
|
16571
|
+
const recentRetrievalLaneHandoffIncidents = filterScopedGovernanceEntries(config.retrievalLaneHandoffIncidentStore ? await loadRAGRetrievalLaneHandoffIncidents({
|
|
15749
16572
|
limit: 10,
|
|
15750
16573
|
store: config.retrievalLaneHandoffIncidentStore
|
|
15751
|
-
}) : undefined;
|
|
15752
|
-
const recentRetrievalLaneHandoffIncidentHistory = config.retrievalLaneHandoffIncidentHistoryStore ? await loadRAGRetrievalLaneHandoffIncidentHistory({
|
|
16574
|
+
}) : undefined);
|
|
16575
|
+
const recentRetrievalLaneHandoffIncidentHistory = filterScopedGovernanceEntries(config.retrievalLaneHandoffIncidentHistoryStore ? await loadRAGRetrievalLaneHandoffIncidentHistory({
|
|
15753
16576
|
limit: 10,
|
|
15754
16577
|
store: config.retrievalLaneHandoffIncidentHistoryStore
|
|
15755
|
-
}) : undefined;
|
|
15756
|
-
const recentHandoffAutoCompletePolicyHistory = config.retrievalLaneHandoffAutoCompletePolicyHistoryStore ? await loadRAGRetrievalLaneHandoffAutoCompletePolicyHistory({
|
|
16578
|
+
}) : undefined);
|
|
16579
|
+
const recentHandoffAutoCompletePolicyHistory = filterScopedGovernanceEntries(config.retrievalLaneHandoffAutoCompletePolicyHistoryStore ? await loadRAGRetrievalLaneHandoffAutoCompletePolicyHistory({
|
|
15757
16580
|
limit: 10,
|
|
15758
16581
|
store: config.retrievalLaneHandoffAutoCompletePolicyHistoryStore
|
|
15759
|
-
}) : undefined;
|
|
15760
|
-
const recentReleaseLanePolicyHistory = config.retrievalReleaseLanePolicyHistoryStore ? await loadRAGRetrievalReleaseLanePolicyHistory({
|
|
16582
|
+
}) : undefined);
|
|
16583
|
+
const recentReleaseLanePolicyHistory = filterScopedGovernanceEntries(config.retrievalReleaseLanePolicyHistoryStore ? await loadRAGRetrievalReleaseLanePolicyHistory({
|
|
15761
16584
|
limit: 10,
|
|
15762
16585
|
store: config.retrievalReleaseLanePolicyHistoryStore
|
|
15763
|
-
}) : undefined;
|
|
15764
|
-
const recentBaselineGatePolicyHistory = config.retrievalBaselineGatePolicyHistoryStore ? await loadRAGRetrievalBaselineGatePolicyHistory({
|
|
16586
|
+
}) : undefined);
|
|
16587
|
+
const recentBaselineGatePolicyHistory = filterScopedGovernanceEntries(config.retrievalBaselineGatePolicyHistoryStore ? await loadRAGRetrievalBaselineGatePolicyHistory({
|
|
15765
16588
|
limit: 10,
|
|
15766
16589
|
store: config.retrievalBaselineGatePolicyHistoryStore
|
|
15767
|
-
}) : undefined;
|
|
15768
|
-
const recentReleaseLaneEscalationPolicyHistory = config.retrievalReleaseLaneEscalationPolicyHistoryStore ? await loadRAGRetrievalReleaseLaneEscalationPolicyHistory({
|
|
16590
|
+
}) : undefined);
|
|
16591
|
+
const recentReleaseLaneEscalationPolicyHistory = filterScopedGovernanceEntries(config.retrievalReleaseLaneEscalationPolicyHistoryStore ? await loadRAGRetrievalReleaseLaneEscalationPolicyHistory({
|
|
15769
16592
|
limit: 10,
|
|
15770
16593
|
store: config.retrievalReleaseLaneEscalationPolicyHistoryStore
|
|
15771
|
-
}) : undefined;
|
|
16594
|
+
}) : undefined);
|
|
15772
16595
|
const recentIncidentRemediationDecisions = config.retrievalIncidentRemediationDecisionStore ? await loadRAGRetrievalIncidentRemediationDecisions({
|
|
15773
16596
|
limit: 10,
|
|
15774
16597
|
store: config.retrievalIncidentRemediationDecisionStore
|
|
@@ -15833,6 +16656,12 @@ var ragChat = (config) => {
|
|
|
15833
16656
|
targetRolloutLabel
|
|
15834
16657
|
};
|
|
15835
16658
|
}) : undefined;
|
|
16659
|
+
const getComparisonCorpusGroupKey = (groupKey) => {
|
|
16660
|
+
if (!groupKey) {
|
|
16661
|
+
return;
|
|
16662
|
+
}
|
|
16663
|
+
return (recentRetrievalComparisonRuns ?? []).find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey ?? (activeRetrievalBaselines ?? []).find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey ?? (recentRetrievalReleaseDecisions ?? []).find((entry) => entry.groupKey === groupKey && typeof entry.corpusGroupKey === "string")?.corpusGroupKey;
|
|
16664
|
+
};
|
|
15836
16665
|
const baseReleaseGroups = (() => {
|
|
15837
16666
|
const groups = new Set;
|
|
15838
16667
|
for (const run of recentRetrievalComparisonRuns ?? []) {
|
|
@@ -15894,6 +16723,7 @@ var ragChat = (config) => {
|
|
|
15894
16723
|
approvalMaxAgeMs: getRetrievalReleasePolicy(groupKey).approvalMaxAgeMs,
|
|
15895
16724
|
approvalRequired: getRetrievalReleasePolicy(groupKey).requireApprovalBeforePromotion === true,
|
|
15896
16725
|
blockedReasons,
|
|
16726
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
15897
16727
|
escalationSeverity,
|
|
15898
16728
|
groupKey,
|
|
15899
16729
|
latestDecisionAt: latestDecision?.decidedAt,
|
|
@@ -15943,6 +16773,7 @@ var ragChat = (config) => {
|
|
|
15943
16773
|
const groupDecisions = (enrichedRecentRetrievalReleaseDecisions ?? []).filter((entry) => entry.groupKey === groupKey);
|
|
15944
16774
|
const latest = groupDecisions[0];
|
|
15945
16775
|
return {
|
|
16776
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
15946
16777
|
groupKey,
|
|
15947
16778
|
lastApprovedAt: groupDecisions.find((entry) => entry.kind === "approve")?.decidedAt,
|
|
15948
16779
|
lastPromotedAt: groupDecisions.find((entry) => entry.kind === "promote")?.decidedAt,
|
|
@@ -15974,6 +16805,7 @@ var ragChat = (config) => {
|
|
|
15974
16805
|
const laneDecisions = (enrichedRecentRetrievalReleaseDecisions ?? []).filter((entry) => entry.groupKey === groupKey && (entry.targetRolloutLabel ?? undefined) === targetRolloutLabel);
|
|
15975
16806
|
const latest = laneDecisions[0];
|
|
15976
16807
|
summaries.push({
|
|
16808
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
15977
16809
|
groupKey,
|
|
15978
16810
|
lastApprovedAt: laneDecisions.find((entry) => entry.kind === "approve")?.decidedAt,
|
|
15979
16811
|
lastPromotedAt: laneDecisions.find((entry) => entry.kind === "promote")?.decidedAt,
|
|
@@ -16009,6 +16841,7 @@ var ragChat = (config) => {
|
|
|
16009
16841
|
const latest = laneDecisions[0];
|
|
16010
16842
|
summaries.push({
|
|
16011
16843
|
approvalCount: laneDecisions.filter((entry) => entry.kind === "approve").length,
|
|
16844
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16012
16845
|
decisionCount: laneDecisions.length,
|
|
16013
16846
|
groupKey,
|
|
16014
16847
|
latestDecisionAt: latest?.decidedAt,
|
|
@@ -16302,6 +17135,7 @@ var ragChat = (config) => {
|
|
|
16302
17135
|
if (!latest) {
|
|
16303
17136
|
await persistLaneHandoffAutoCompletePolicyHistoryRecord({
|
|
16304
17137
|
changeKind: "snapshot",
|
|
17138
|
+
corpusGroupKey: getComparisonCorpusGroupKey(policy.groupKey),
|
|
16305
17139
|
enabled: policy.enabled,
|
|
16306
17140
|
groupKey: policy.groupKey,
|
|
16307
17141
|
maxApprovedDecisionAgeMs: policy.maxApprovedDecisionAgeMs,
|
|
@@ -16312,6 +17146,7 @@ var ragChat = (config) => {
|
|
|
16312
17146
|
if (latest.enabled !== policy.enabled || latest.maxApprovedDecisionAgeMs !== policy.maxApprovedDecisionAgeMs) {
|
|
16313
17147
|
await persistLaneHandoffAutoCompletePolicyHistoryRecord({
|
|
16314
17148
|
changeKind: "changed",
|
|
17149
|
+
corpusGroupKey: getComparisonCorpusGroupKey(policy.groupKey),
|
|
16315
17150
|
enabled: policy.enabled,
|
|
16316
17151
|
groupKey: policy.groupKey,
|
|
16317
17152
|
maxApprovedDecisionAgeMs: policy.maxApprovedDecisionAgeMs,
|
|
@@ -16349,6 +17184,7 @@ var ragChat = (config) => {
|
|
|
16349
17184
|
const latest = laneIncidents[0];
|
|
16350
17185
|
summaries.push({
|
|
16351
17186
|
acknowledgedOpenCount,
|
|
17187
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16352
17188
|
groupKey,
|
|
16353
17189
|
highestSeverity: laneIncidents.some((entry) => entry.severity === "critical") ? "critical" : laneIncidents.some((entry) => entry.severity === "warning") ? "warning" : undefined,
|
|
16354
17190
|
latestKind: latest?.kind,
|
|
@@ -16404,6 +17240,7 @@ var ragChat = (config) => {
|
|
|
16404
17240
|
await persistReleaseLanePolicyHistoryRecord({
|
|
16405
17241
|
approvalMaxAgeMs: policy.approvalMaxAgeMs,
|
|
16406
17242
|
changeKind: "snapshot",
|
|
17243
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16407
17244
|
groupKey,
|
|
16408
17245
|
requireApprovalBeforePromotion: policy.requireApprovalBeforePromotion,
|
|
16409
17246
|
rolloutLabel: policy.rolloutLabel,
|
|
@@ -16415,6 +17252,7 @@ var ragChat = (config) => {
|
|
|
16415
17252
|
await persistReleaseLanePolicyHistoryRecord({
|
|
16416
17253
|
approvalMaxAgeMs: policy.approvalMaxAgeMs,
|
|
16417
17254
|
changeKind: "changed",
|
|
17255
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16418
17256
|
groupKey,
|
|
16419
17257
|
previousApprovalMaxAgeMs: latest.approvalMaxAgeMs,
|
|
16420
17258
|
previousRequireApprovalBeforePromotion: latest.requireApprovalBeforePromotion,
|
|
@@ -16434,6 +17272,7 @@ var ragChat = (config) => {
|
|
|
16434
17272
|
if (!latest) {
|
|
16435
17273
|
await persistBaselineGatePolicyHistoryRecord({
|
|
16436
17274
|
changeKind: "snapshot",
|
|
17275
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16437
17276
|
groupKey,
|
|
16438
17277
|
policy: policy.policy,
|
|
16439
17278
|
rolloutLabel: policy.rolloutLabel,
|
|
@@ -16444,6 +17283,7 @@ var ragChat = (config) => {
|
|
|
16444
17283
|
if (previousPolicy !== currentPolicy) {
|
|
16445
17284
|
await persistBaselineGatePolicyHistoryRecord({
|
|
16446
17285
|
changeKind: "changed",
|
|
17286
|
+
corpusGroupKey: getComparisonCorpusGroupKey(groupKey),
|
|
16447
17287
|
groupKey,
|
|
16448
17288
|
policy: policy.policy,
|
|
16449
17289
|
previousPolicy: latest.policy,
|
|
@@ -16498,6 +17338,7 @@ var ragChat = (config) => {
|
|
|
16498
17338
|
await persistReleaseLaneEscalationPolicyHistoryRecord({
|
|
16499
17339
|
approvalExpiredSeverity: policy.approvalExpiredSeverity,
|
|
16500
17340
|
changeKind: "snapshot",
|
|
17341
|
+
corpusGroupKey: getComparisonCorpusGroupKey(policy.groupKey),
|
|
16501
17342
|
gateFailureSeverity: policy.gateFailureSeverity,
|
|
16502
17343
|
groupKey: policy.groupKey,
|
|
16503
17344
|
openIncidentSeverity: policy.openIncidentSeverity,
|
|
@@ -16510,6 +17351,7 @@ var ragChat = (config) => {
|
|
|
16510
17351
|
await persistReleaseLaneEscalationPolicyHistoryRecord({
|
|
16511
17352
|
approvalExpiredSeverity: policy.approvalExpiredSeverity,
|
|
16512
17353
|
changeKind: "changed",
|
|
17354
|
+
corpusGroupKey: getComparisonCorpusGroupKey(policy.groupKey),
|
|
16513
17355
|
gateFailureSeverity: policy.gateFailureSeverity,
|
|
16514
17356
|
groupKey: policy.groupKey,
|
|
16515
17357
|
openIncidentSeverity: policy.openIncidentSeverity,
|
|
@@ -16564,6 +17406,7 @@ var ragChat = (config) => {
|
|
|
16564
17406
|
const latestWinner = latestRetrievalComparisonRun.comparison.summary.bestByPassingRate;
|
|
16565
17407
|
if (latestWinner && stableWinnerByPassingRate?.retrievalId && stableWinnerByPassingRate.retrievalId !== latestWinner) {
|
|
16566
17408
|
alerts.push({
|
|
17409
|
+
corpusGroupKey: latestRetrievalComparisonRun.corpusGroupKey,
|
|
16567
17410
|
groupKey: latestRetrievalComparisonRun.groupKey,
|
|
16568
17411
|
kind: "stable_winner_changed",
|
|
16569
17412
|
latestRunId: latestRetrievalComparisonRun.id,
|
|
@@ -16580,6 +17423,7 @@ var ragChat = (config) => {
|
|
|
16580
17423
|
baselineRetrievalId: latestRetrievalComparisonRun.decisionSummary?.baselineRetrievalId,
|
|
16581
17424
|
candidateRetrievalId: latestRetrievalComparisonRun.decisionSummary?.candidateRetrievalId,
|
|
16582
17425
|
delta,
|
|
17426
|
+
corpusGroupKey: latestRetrievalComparisonRun.corpusGroupKey,
|
|
16583
17427
|
groupKey: latestRetrievalComparisonRun.groupKey,
|
|
16584
17428
|
kind: "baseline_regression",
|
|
16585
17429
|
latestRunId: latestRetrievalComparisonRun.id,
|
|
@@ -16594,6 +17438,7 @@ var ragChat = (config) => {
|
|
|
16594
17438
|
candidateRetrievalId: latestRetrievalComparisonRun.decisionSummary?.candidateRetrievalId,
|
|
16595
17439
|
delta,
|
|
16596
17440
|
gate,
|
|
17441
|
+
corpusGroupKey: latestRetrievalComparisonRun.corpusGroupKey,
|
|
16597
17442
|
groupKey: latestRetrievalComparisonRun.groupKey,
|
|
16598
17443
|
kind: "baseline_gate_failed",
|
|
16599
17444
|
latestRunId: latestRetrievalComparisonRun.id,
|
|
@@ -16611,6 +17456,7 @@ var ragChat = (config) => {
|
|
|
16611
17456
|
const kind = reasonSet.has("no active canary baseline exists for this group") ? "handoff_auto_complete_source_lane_missing" : reasonSet.has("latest approved handoff decision is older than the auto-complete policy allows") ? "handoff_auto_complete_stale_approval" : reasonSet.has("approved handoff decision is required before auto-complete") ? "handoff_auto_complete_approval_missing" : reasonText.includes("gate") || reasonText.includes("passing rate delta") || reasonText.includes("average") || reasonText.includes("candidate does not match") ? "handoff_auto_complete_gate_blocked" : "handoff_auto_complete_policy_drift";
|
|
16612
17457
|
alerts.push({
|
|
16613
17458
|
candidateRetrievalId: entry.candidateRetrievalId,
|
|
17459
|
+
corpusGroupKey: getComparisonCorpusGroupKey(entry.groupKey),
|
|
16614
17460
|
groupKey: entry.groupKey,
|
|
16615
17461
|
kind,
|
|
16616
17462
|
latestRunId: entry.sourceRunId ?? latestRetrievalComparisonRun.id,
|
|
@@ -16707,7 +17553,7 @@ var ragChat = (config) => {
|
|
|
16707
17553
|
searchTraceRuntime.stats = traceStats;
|
|
16708
17554
|
searchTraceRuntime.recentRuns = recentTraceRuns;
|
|
16709
17555
|
return {
|
|
16710
|
-
admin: buildAdminCapabilities(),
|
|
17556
|
+
admin: await buildAdminCapabilities(request),
|
|
16711
17557
|
adminActions: [...adminActions],
|
|
16712
17558
|
adminJobs: [...adminJobs, ...syncJobs].sort((left, right) => right.startedAt - left.startedAt),
|
|
16713
17559
|
capabilities: collection?.getCapabilities?.(),
|
|
@@ -16721,6 +17567,7 @@ var ragChat = (config) => {
|
|
|
16721
17567
|
latest: latestRetrievalComparisonRun ? {
|
|
16722
17568
|
bestByAverageF1: latestRetrievalComparisonRun.comparison.summary.bestByAverageF1,
|
|
16723
17569
|
bestByPassingRate: latestRetrievalComparisonRun.comparison.summary.bestByPassingRate,
|
|
17570
|
+
corpusGroupKey: latestRetrievalComparisonRun.corpusGroupKey,
|
|
16724
17571
|
elapsedMs: latestRetrievalComparisonRun.elapsedMs,
|
|
16725
17572
|
fastest: latestRetrievalComparisonRun.comparison.summary.fastest,
|
|
16726
17573
|
finishedAt: latestRetrievalComparisonRun.finishedAt,
|
|
@@ -16786,27 +17633,27 @@ var ragChat = (config) => {
|
|
|
16786
17633
|
stats: traceStats
|
|
16787
17634
|
},
|
|
16788
17635
|
status: collection?.getStatus?.(),
|
|
16789
|
-
syncSources: await buildSyncSources()
|
|
17636
|
+
syncSources: await buildSyncSources(accessScope)
|
|
16790
17637
|
};
|
|
16791
17638
|
};
|
|
16792
|
-
const handleStatus = async () => buildOperationsPayload();
|
|
16793
|
-
const handleRetrievalReleaseStatus = async () => {
|
|
16794
|
-
const result = await buildOperationsPayload();
|
|
17639
|
+
const handleStatus = async (request) => buildOperationsPayload(request);
|
|
17640
|
+
const handleRetrievalReleaseStatus = async (request) => {
|
|
17641
|
+
const result = await buildOperationsPayload(request);
|
|
16795
17642
|
return {
|
|
16796
17643
|
ok: true,
|
|
16797
17644
|
retrievalComparisons: result.retrievalComparisons
|
|
16798
17645
|
};
|
|
16799
17646
|
};
|
|
16800
|
-
const handleRetrievalReleaseDriftStatus = async () => {
|
|
16801
|
-
const result = await buildOperationsPayload();
|
|
17647
|
+
const handleRetrievalReleaseDriftStatus = async (request) => {
|
|
17648
|
+
const result = await buildOperationsPayload(request);
|
|
16802
17649
|
return {
|
|
16803
17650
|
handoffDriftCountsByLane: result.retrievalComparisons?.handoffDriftCountsByLane,
|
|
16804
17651
|
handoffDriftRollups: result.retrievalComparisons?.handoffDriftRollups,
|
|
16805
17652
|
ok: true
|
|
16806
17653
|
};
|
|
16807
17654
|
};
|
|
16808
|
-
const handleRetrievalLaneHandoffIncidentStatus = async () => {
|
|
16809
|
-
const result = await buildOperationsPayload();
|
|
17655
|
+
const handleRetrievalLaneHandoffIncidentStatus = async (request) => {
|
|
17656
|
+
const result = await buildOperationsPayload(request);
|
|
16810
17657
|
const incidents = result.retrievalComparisons?.recentLaneHandoffIncidents;
|
|
16811
17658
|
return {
|
|
16812
17659
|
freshnessWindows: result.retrievalComparisons?.handoffFreshnessWindows,
|
|
@@ -16816,8 +17663,8 @@ var ragChat = (config) => {
|
|
|
16816
17663
|
ok: true
|
|
16817
17664
|
};
|
|
16818
17665
|
};
|
|
16819
|
-
const handleRetrievalLaneHandoffStatus = async () => {
|
|
16820
|
-
const result = await buildOperationsPayload();
|
|
17666
|
+
const handleRetrievalLaneHandoffStatus = async (request) => {
|
|
17667
|
+
const result = await buildOperationsPayload(request);
|
|
16821
17668
|
const incidents = result.retrievalComparisons?.recentLaneHandoffIncidents;
|
|
16822
17669
|
return {
|
|
16823
17670
|
autoComplete: result.retrievalComparisons?.handoffAutoComplete,
|
|
@@ -16830,7 +17677,7 @@ var ragChat = (config) => {
|
|
|
16830
17677
|
ok: true
|
|
16831
17678
|
};
|
|
16832
17679
|
};
|
|
16833
|
-
const handleOps = async () => buildOperationsPayload();
|
|
17680
|
+
const handleOps = async (request) => buildOperationsPayload(request);
|
|
16834
17681
|
if (searchTraceStore && searchTraceRetention && searchTraceRetentionSchedule) {
|
|
16835
17682
|
const runScheduledSearchTracePrune = async () => {
|
|
16836
17683
|
searchTraceRuntime.nextScheduledAt = Date.now() + searchTraceRetentionSchedule.intervalMs;
|
|
@@ -16848,14 +17695,20 @@ var ragChat = (config) => {
|
|
|
16848
17695
|
}, searchTraceRetentionSchedule.intervalMs);
|
|
16849
17696
|
timer.unref?.();
|
|
16850
17697
|
}
|
|
16851
|
-
const handleDocuments = async (kind) => {
|
|
17698
|
+
const handleDocuments = async (kind, request) => {
|
|
16852
17699
|
if (!indexManager) {
|
|
16853
17700
|
return {
|
|
16854
17701
|
error: "RAG index document management is not configured",
|
|
16855
17702
|
ok: false
|
|
16856
17703
|
};
|
|
16857
17704
|
}
|
|
16858
|
-
const
|
|
17705
|
+
const accessScope = await loadAccessScope(request);
|
|
17706
|
+
const documents = (await indexManager.listDocuments({ kind })).filter((document) => matchesAccessScope(accessScope, {
|
|
17707
|
+
corpusKey: document.corpusKey,
|
|
17708
|
+
documentId: document.id,
|
|
17709
|
+
metadata: document.metadata,
|
|
17710
|
+
source: document.source
|
|
17711
|
+
}));
|
|
16859
17712
|
return {
|
|
16860
17713
|
documents: documents.map((document) => ({
|
|
16861
17714
|
...document,
|
|
@@ -16868,7 +17721,7 @@ var ragChat = (config) => {
|
|
|
16868
17721
|
ok: true
|
|
16869
17722
|
};
|
|
16870
17723
|
};
|
|
16871
|
-
const handleCreateDocument = async (body) => {
|
|
17724
|
+
const handleCreateDocument = async (body, request) => {
|
|
16872
17725
|
if (!indexManager?.createDocument) {
|
|
16873
17726
|
return {
|
|
16874
17727
|
error: "RAG document creation is not configured",
|
|
@@ -16887,6 +17740,18 @@ var ragChat = (config) => {
|
|
|
16887
17740
|
ok: false
|
|
16888
17741
|
};
|
|
16889
17742
|
}
|
|
17743
|
+
const accessScope = await loadAccessScope(request);
|
|
17744
|
+
if (!matchesAccessScope(accessScope, {
|
|
17745
|
+
documentId: body.id,
|
|
17746
|
+
corpusKey: body.corpusKey,
|
|
17747
|
+
metadata: body.metadata,
|
|
17748
|
+
source: body.source
|
|
17749
|
+
})) {
|
|
17750
|
+
return {
|
|
17751
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17752
|
+
ok: false
|
|
17753
|
+
};
|
|
17754
|
+
}
|
|
16890
17755
|
const job = createAdminJob("create_document", body.id);
|
|
16891
17756
|
try {
|
|
16892
17757
|
const result = await indexManager.createDocument(body);
|
|
@@ -16902,7 +17767,7 @@ var ragChat = (config) => {
|
|
|
16902
17767
|
throw caught;
|
|
16903
17768
|
}
|
|
16904
17769
|
};
|
|
16905
|
-
const handleDocumentChunks = async (id) => {
|
|
17770
|
+
const handleDocumentChunks = async (id, request) => {
|
|
16906
17771
|
if (!indexManager) {
|
|
16907
17772
|
return {
|
|
16908
17773
|
error: "RAG chunk preview is not configured",
|
|
@@ -16922,6 +17787,18 @@ var ragChat = (config) => {
|
|
|
16922
17787
|
ok: false
|
|
16923
17788
|
};
|
|
16924
17789
|
}
|
|
17790
|
+
const accessScope = await loadAccessScope(request);
|
|
17791
|
+
if (!matchesAccessScope(accessScope, {
|
|
17792
|
+
documentId: preview.document.id,
|
|
17793
|
+
corpusKey: preview.document.corpusKey,
|
|
17794
|
+
metadata: preview.document.metadata,
|
|
17795
|
+
source: preview.document.source
|
|
17796
|
+
})) {
|
|
17797
|
+
return {
|
|
17798
|
+
error: "document not found",
|
|
17799
|
+
ok: false
|
|
17800
|
+
};
|
|
17801
|
+
}
|
|
16925
17802
|
const chunks = preview.chunks.map((chunk) => ({
|
|
16926
17803
|
...chunk,
|
|
16927
17804
|
labels: buildRAGSourceLabels({
|
|
@@ -16952,7 +17829,7 @@ var ragChat = (config) => {
|
|
|
16952
17829
|
})
|
|
16953
17830
|
};
|
|
16954
17831
|
};
|
|
16955
|
-
const handleDeleteDocument = async (id) => {
|
|
17832
|
+
const handleDeleteDocument = async (id, request) => {
|
|
16956
17833
|
if (!indexManager?.deleteDocument) {
|
|
16957
17834
|
return {
|
|
16958
17835
|
error: "RAG document deletion is not configured",
|
|
@@ -16965,6 +17842,13 @@ var ragChat = (config) => {
|
|
|
16965
17842
|
ok: false
|
|
16966
17843
|
};
|
|
16967
17844
|
}
|
|
17845
|
+
const accessScope = await loadAccessScope(request);
|
|
17846
|
+
if (accessScope && !matchesAccessScope(accessScope, { documentId: id })) {
|
|
17847
|
+
return {
|
|
17848
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17849
|
+
ok: false
|
|
17850
|
+
};
|
|
17851
|
+
}
|
|
16968
17852
|
const job = createAdminJob("delete_document", id);
|
|
16969
17853
|
const deleted = await indexManager.deleteDocument(id);
|
|
16970
17854
|
if (!deleted) {
|
|
@@ -16984,7 +17868,7 @@ var ragChat = (config) => {
|
|
|
16984
17868
|
ok: true
|
|
16985
17869
|
};
|
|
16986
17870
|
};
|
|
16987
|
-
const handleReindexDocument = async (id) => {
|
|
17871
|
+
const handleReindexDocument = async (id, request) => {
|
|
16988
17872
|
if (!indexManager?.reindexDocument) {
|
|
16989
17873
|
return {
|
|
16990
17874
|
error: "RAG document reindex is not configured",
|
|
@@ -16997,6 +17881,13 @@ var ragChat = (config) => {
|
|
|
16997
17881
|
ok: false
|
|
16998
17882
|
};
|
|
16999
17883
|
}
|
|
17884
|
+
const accessScope = await loadAccessScope(request);
|
|
17885
|
+
if (accessScope && !matchesAccessScope(accessScope, { documentId: id })) {
|
|
17886
|
+
return {
|
|
17887
|
+
error: "Document is outside the allowed RAG access scope",
|
|
17888
|
+
ok: false
|
|
17889
|
+
};
|
|
17890
|
+
}
|
|
17000
17891
|
const job = createAdminJob("reindex_document", id);
|
|
17001
17892
|
try {
|
|
17002
17893
|
const result = {
|
|
@@ -17016,7 +17907,7 @@ var ragChat = (config) => {
|
|
|
17016
17907
|
throw caught;
|
|
17017
17908
|
}
|
|
17018
17909
|
};
|
|
17019
|
-
const handleReindexSource = async (source) => {
|
|
17910
|
+
const handleReindexSource = async (source, request) => {
|
|
17020
17911
|
if (!indexManager?.reindexSource) {
|
|
17021
17912
|
return {
|
|
17022
17913
|
error: "RAG source reindex is not configured",
|
|
@@ -17029,6 +17920,15 @@ var ragChat = (config) => {
|
|
|
17029
17920
|
ok: false
|
|
17030
17921
|
};
|
|
17031
17922
|
}
|
|
17923
|
+
const accessScope = await loadAccessScope(request);
|
|
17924
|
+
if (!matchesAccessScope(accessScope, {
|
|
17925
|
+
source
|
|
17926
|
+
})) {
|
|
17927
|
+
return {
|
|
17928
|
+
error: "Source is outside the allowed RAG access scope",
|
|
17929
|
+
ok: false
|
|
17930
|
+
};
|
|
17931
|
+
}
|
|
17032
17932
|
const job = createAdminJob("reindex_source", source);
|
|
17033
17933
|
try {
|
|
17034
17934
|
const result = {
|
|
@@ -17112,25 +18012,33 @@ var ragChat = (config) => {
|
|
|
17112
18012
|
...normalized
|
|
17113
18013
|
};
|
|
17114
18014
|
};
|
|
17115
|
-
const handleSyncSources = async () => {
|
|
18015
|
+
const handleSyncSources = async (request) => {
|
|
17116
18016
|
if (!indexManager?.listSyncSources) {
|
|
17117
18017
|
return {
|
|
17118
18018
|
error: "RAG source sync is not configured",
|
|
17119
18019
|
ok: false
|
|
17120
18020
|
};
|
|
17121
18021
|
}
|
|
18022
|
+
const accessScope = await loadAccessScope(request);
|
|
17122
18023
|
return {
|
|
17123
18024
|
ok: true,
|
|
17124
|
-
sources: await
|
|
18025
|
+
sources: await buildSyncSources(accessScope)
|
|
17125
18026
|
};
|
|
17126
18027
|
};
|
|
17127
|
-
const handleSyncAllSources = async (options) => {
|
|
18028
|
+
const handleSyncAllSources = async (request, options) => {
|
|
17128
18029
|
if (!indexManager?.syncAllSources) {
|
|
17129
18030
|
return {
|
|
17130
18031
|
error: "RAG source sync is not configured",
|
|
17131
18032
|
ok: false
|
|
17132
18033
|
};
|
|
17133
18034
|
}
|
|
18035
|
+
const accessScope = await loadAccessScope(request);
|
|
18036
|
+
if (accessScope?.allowedSyncSourceIds?.length) {
|
|
18037
|
+
return {
|
|
18038
|
+
error: "Scoped sync-all is not allowed; sync individual sources instead",
|
|
18039
|
+
ok: false
|
|
18040
|
+
};
|
|
18041
|
+
}
|
|
17134
18042
|
const job = createAdminJob("sync_all_sources", undefined, syncJobs);
|
|
17135
18043
|
const action = createAdminAction("sync_all_sources");
|
|
17136
18044
|
try {
|
|
@@ -17156,7 +18064,7 @@ var ragChat = (config) => {
|
|
|
17156
18064
|
completeAdminAction(action);
|
|
17157
18065
|
return {
|
|
17158
18066
|
ok: true,
|
|
17159
|
-
sources: await buildSyncSources()
|
|
18067
|
+
sources: await buildSyncSources(accessScope)
|
|
17160
18068
|
};
|
|
17161
18069
|
} catch (caught) {
|
|
17162
18070
|
const message = caught instanceof Error ? caught.message : String(caught);
|
|
@@ -17165,7 +18073,7 @@ var ragChat = (config) => {
|
|
|
17165
18073
|
throw caught;
|
|
17166
18074
|
}
|
|
17167
18075
|
};
|
|
17168
|
-
const handleSyncSource = async (id, options) => {
|
|
18076
|
+
const handleSyncSource = async (id, request, options) => {
|
|
17169
18077
|
if (!indexManager?.syncSource) {
|
|
17170
18078
|
return {
|
|
17171
18079
|
error: "RAG source sync is not configured",
|
|
@@ -17178,6 +18086,13 @@ var ragChat = (config) => {
|
|
|
17178
18086
|
ok: false
|
|
17179
18087
|
};
|
|
17180
18088
|
}
|
|
18089
|
+
const accessScope = await loadAccessScope(request);
|
|
18090
|
+
if (!matchesSyncSourceScope(accessScope, { id })) {
|
|
18091
|
+
return {
|
|
18092
|
+
error: "Sync source is outside the allowed RAG access scope",
|
|
18093
|
+
ok: false
|
|
18094
|
+
};
|
|
18095
|
+
}
|
|
17181
18096
|
const job = createAdminJob("sync_source", id, syncJobs);
|
|
17182
18097
|
const action = createAdminAction("sync_source", undefined, id);
|
|
17183
18098
|
try {
|
|
@@ -17194,7 +18109,7 @@ var ragChat = (config) => {
|
|
|
17194
18109
|
}
|
|
17195
18110
|
completeAdminJob(job);
|
|
17196
18111
|
completeAdminAction(action);
|
|
17197
|
-
const source = (await buildSyncSources()).find((record) => record.id === id);
|
|
18112
|
+
const source = (await buildSyncSources(accessScope)).find((record) => record.id === id);
|
|
17198
18113
|
return source ? { ok: true, source } : {
|
|
17199
18114
|
error: "sync source not found",
|
|
17200
18115
|
ok: false
|
|
@@ -17260,7 +18175,7 @@ var ragChat = (config) => {
|
|
|
17260
18175
|
};
|
|
17261
18176
|
return;
|
|
17262
18177
|
}
|
|
17263
|
-
const lastMessage = conversation.messages.findLast((
|
|
18178
|
+
const lastMessage = conversation.messages.findLast((message) => message.id === messageId && message.role === "user");
|
|
17264
18179
|
if (!lastMessage) {
|
|
17265
18180
|
yield {
|
|
17266
18181
|
data: renderers.error("Message not found"),
|
|
@@ -17304,7 +18219,7 @@ var ragChat = (config) => {
|
|
|
17304
18219
|
const controller = new AbortController;
|
|
17305
18220
|
abortControllers.set(conversationId, controller);
|
|
17306
18221
|
const history = buildHistory(conversation);
|
|
17307
|
-
const lastMessageIndex = conversation.messages.findIndex((
|
|
18222
|
+
const lastMessageIndex = conversation.messages.findIndex((message) => message.id === messageId);
|
|
17308
18223
|
const userHistory = lastMessageIndex >= 0 ? history.slice(0, lastMessageIndex) : history;
|
|
17309
18224
|
const messageWithContext = buildUserMessage2(content, lastMessage.attachments, ragContext);
|
|
17310
18225
|
const sseStream = streamAIToSSE(conversationId, assistantMessageId, {
|
|
@@ -17330,24 +18245,24 @@ var ragChat = (config) => {
|
|
|
17330
18245
|
};
|
|
17331
18246
|
return new Elysia2().ws(path, {
|
|
17332
18247
|
message: async (ws, raw) => {
|
|
17333
|
-
const
|
|
17334
|
-
if (!
|
|
18248
|
+
const message = parseAIMessage(raw);
|
|
18249
|
+
if (!message) {
|
|
17335
18250
|
return;
|
|
17336
18251
|
}
|
|
17337
|
-
if (
|
|
17338
|
-
handleCancel(
|
|
18252
|
+
if (message.type === "cancel") {
|
|
18253
|
+
handleCancel(message.conversationId);
|
|
17339
18254
|
return;
|
|
17340
18255
|
}
|
|
17341
|
-
if (
|
|
17342
|
-
await handleBranch(ws,
|
|
18256
|
+
if (message.type === "branch") {
|
|
18257
|
+
await handleBranch(ws, message.messageId, message.conversationId);
|
|
17343
18258
|
return;
|
|
17344
18259
|
}
|
|
17345
|
-
if (
|
|
17346
|
-
await handleMessage(ws,
|
|
18260
|
+
if (message.type === "message") {
|
|
18261
|
+
await handleMessage(ws, message.content, message.conversationId, message.attachments);
|
|
17347
18262
|
}
|
|
17348
18263
|
}
|
|
17349
18264
|
}).post(`${path}/search`, async ({ body, request, set }) => {
|
|
17350
|
-
const result = await handleSearch(body);
|
|
18265
|
+
const result = await handleSearch(body, request);
|
|
17351
18266
|
if (!result.ok) {
|
|
17352
18267
|
set.status = result.error === "Invalid payload" || result.error?.startsWith("Expected payload shape:") ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
17353
18268
|
}
|
|
@@ -17424,6 +18339,16 @@ var ragChat = (config) => {
|
|
|
17424
18339
|
}
|
|
17425
18340
|
return result;
|
|
17426
18341
|
}).post(`${path}/traces/prune`, async ({ body, request, set }) => {
|
|
18342
|
+
const denied = await authorizeMutationRoute(request, "prune_search_traces", {
|
|
18343
|
+
fallback: "Search trace pruning is not allowed"
|
|
18344
|
+
});
|
|
18345
|
+
if (denied) {
|
|
18346
|
+
set.status = 403;
|
|
18347
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18348
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Search trace prune failed"), getNumericStatus(set.status));
|
|
18349
|
+
}
|
|
18350
|
+
return denied;
|
|
18351
|
+
}
|
|
17427
18352
|
const result = await handleTracePrune(body);
|
|
17428
18353
|
if (!result.ok) {
|
|
17429
18354
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17454,7 +18379,7 @@ var ragChat = (config) => {
|
|
|
17454
18379
|
}
|
|
17455
18380
|
return result;
|
|
17456
18381
|
}).post(`${path}/compare/retrieval`, async ({ body, request, set }) => {
|
|
17457
|
-
const result = await handleEvaluateRetrievals(body);
|
|
18382
|
+
const result = await handleEvaluateRetrievals(body, request);
|
|
17458
18383
|
if (!result.ok) {
|
|
17459
18384
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17460
18385
|
}
|
|
@@ -17469,7 +18394,7 @@ var ragChat = (config) => {
|
|
|
17469
18394
|
}
|
|
17470
18395
|
return result;
|
|
17471
18396
|
}).get(`${path}/compare/retrieval/history`, async ({ query, request, set }) => {
|
|
17472
|
-
const result = await handleRetrievalComparisonHistory(query);
|
|
18397
|
+
const result = await handleRetrievalComparisonHistory(query, request);
|
|
17473
18398
|
if (!result.ok) {
|
|
17474
18399
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17475
18400
|
}
|
|
@@ -17484,7 +18409,7 @@ var ragChat = (config) => {
|
|
|
17484
18409
|
}
|
|
17485
18410
|
return result;
|
|
17486
18411
|
}).get(`${path}/compare/retrieval/baselines`, async ({ query, request, set }) => {
|
|
17487
|
-
const result = await handleRetrievalBaselineList(query);
|
|
18412
|
+
const result = await handleRetrievalBaselineList(query, request);
|
|
17488
18413
|
if (!result.ok) {
|
|
17489
18414
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17490
18415
|
}
|
|
@@ -17499,7 +18424,7 @@ var ragChat = (config) => {
|
|
|
17499
18424
|
}
|
|
17500
18425
|
return result;
|
|
17501
18426
|
}).get(`${path}/compare/retrieval/baselines/decisions`, async ({ query, request, set }) => {
|
|
17502
|
-
const result = await handleRetrievalReleaseDecisionList(query);
|
|
18427
|
+
const result = await handleRetrievalReleaseDecisionList(query, request);
|
|
17503
18428
|
if (!result.ok) {
|
|
17504
18429
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17505
18430
|
}
|
|
@@ -17514,7 +18439,7 @@ var ragChat = (config) => {
|
|
|
17514
18439
|
}
|
|
17515
18440
|
return result;
|
|
17516
18441
|
}).get(`${path}/compare/retrieval/release-history`, async ({ query, request, set }) => {
|
|
17517
|
-
const result = await handleRetrievalReleaseGroupHistory(query);
|
|
18442
|
+
const result = await handleRetrievalReleaseGroupHistory(query, request);
|
|
17518
18443
|
if (!result.ok) {
|
|
17519
18444
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17520
18445
|
}
|
|
@@ -17529,7 +18454,7 @@ var ragChat = (config) => {
|
|
|
17529
18454
|
}
|
|
17530
18455
|
return result;
|
|
17531
18456
|
}).get(`${path}/compare/retrieval/handoffs`, async ({ query, request, set }) => {
|
|
17532
|
-
const result = await handleRetrievalLaneHandoffList(query);
|
|
18457
|
+
const result = await handleRetrievalLaneHandoffList(query, request);
|
|
17533
18458
|
if (!result.ok) {
|
|
17534
18459
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17535
18460
|
}
|
|
@@ -17544,7 +18469,7 @@ var ragChat = (config) => {
|
|
|
17544
18469
|
}
|
|
17545
18470
|
return result;
|
|
17546
18471
|
}).get(`${path}/compare/retrieval/handoffs/decisions`, async ({ query, request, set }) => {
|
|
17547
|
-
const result = await handleRetrievalLaneHandoffDecisionList(query);
|
|
18472
|
+
const result = await handleRetrievalLaneHandoffDecisionList(query, request);
|
|
17548
18473
|
if (!result.ok) {
|
|
17549
18474
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17550
18475
|
}
|
|
@@ -17559,7 +18484,7 @@ var ragChat = (config) => {
|
|
|
17559
18484
|
}
|
|
17560
18485
|
return result;
|
|
17561
18486
|
}).get(`${path}/compare/retrieval/handoffs/incidents`, async ({ query, request, set }) => {
|
|
17562
|
-
const result = await handleRetrievalLaneHandoffIncidentList(query);
|
|
18487
|
+
const result = await handleRetrievalLaneHandoffIncidentList(query, request);
|
|
17563
18488
|
if (!result.ok) {
|
|
17564
18489
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17565
18490
|
}
|
|
@@ -17574,7 +18499,7 @@ var ragChat = (config) => {
|
|
|
17574
18499
|
}
|
|
17575
18500
|
return result;
|
|
17576
18501
|
}).get(`${path}/compare/retrieval/handoffs/incidents/history`, async ({ query, request, set }) => {
|
|
17577
|
-
const result = await handleRetrievalLaneHandoffIncidentHistoryList(query);
|
|
18502
|
+
const result = await handleRetrievalLaneHandoffIncidentHistoryList(query, request);
|
|
17578
18503
|
if (!result.ok) {
|
|
17579
18504
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17580
18505
|
}
|
|
@@ -17604,6 +18529,16 @@ var ragChat = (config) => {
|
|
|
17604
18529
|
}
|
|
17605
18530
|
return result;
|
|
17606
18531
|
}).post(`${path}/compare/retrieval/handoffs/incidents/acknowledge`, async ({ body, request, set }) => {
|
|
18532
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18533
|
+
fallback: "Retrieval lane handoff incident acknowledgement is not allowed"
|
|
18534
|
+
});
|
|
18535
|
+
if (denied) {
|
|
18536
|
+
set.status = 403;
|
|
18537
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18538
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident acknowledgement failed"), getNumericStatus(set.status));
|
|
18539
|
+
}
|
|
18540
|
+
return denied;
|
|
18541
|
+
}
|
|
17607
18542
|
const result = await handleRetrievalLaneHandoffIncidentAcknowledge(body);
|
|
17608
18543
|
if (!result.ok) {
|
|
17609
18544
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17619,6 +18554,16 @@ var ragChat = (config) => {
|
|
|
17619
18554
|
}
|
|
17620
18555
|
return result;
|
|
17621
18556
|
}).post(`${path}/compare/retrieval/handoffs/incidents/unacknowledge`, async ({ body, request, set }) => {
|
|
18557
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18558
|
+
fallback: "Retrieval lane handoff incident unacknowledge is not allowed"
|
|
18559
|
+
});
|
|
18560
|
+
if (denied) {
|
|
18561
|
+
set.status = 403;
|
|
18562
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18563
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident unacknowledge failed"), getNumericStatus(set.status));
|
|
18564
|
+
}
|
|
18565
|
+
return denied;
|
|
18566
|
+
}
|
|
17622
18567
|
const result = await handleRetrievalLaneHandoffIncidentUnacknowledge(body);
|
|
17623
18568
|
if (!result.ok) {
|
|
17624
18569
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17634,6 +18579,16 @@ var ragChat = (config) => {
|
|
|
17634
18579
|
}
|
|
17635
18580
|
return result;
|
|
17636
18581
|
}).post(`${path}/compare/retrieval/handoffs/incidents/resolve`, async ({ body, request, set }) => {
|
|
18582
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18583
|
+
fallback: "Retrieval lane handoff incident resolve is not allowed"
|
|
18584
|
+
});
|
|
18585
|
+
if (denied) {
|
|
18586
|
+
set.status = 403;
|
|
18587
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18588
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff incident resolve failed"), getNumericStatus(set.status));
|
|
18589
|
+
}
|
|
18590
|
+
return denied;
|
|
18591
|
+
}
|
|
17637
18592
|
const result = await handleResolveRetrievalLaneHandoffIncident(body);
|
|
17638
18593
|
if (!result.ok) {
|
|
17639
18594
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17649,6 +18604,16 @@ var ragChat = (config) => {
|
|
|
17649
18604
|
}
|
|
17650
18605
|
return result;
|
|
17651
18606
|
}).post(`${path}/compare/retrieval/handoffs/decide`, async ({ body, request, set }) => {
|
|
18607
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18608
|
+
fallback: "Retrieval lane handoff decision is not allowed"
|
|
18609
|
+
});
|
|
18610
|
+
if (denied) {
|
|
18611
|
+
set.status = 403;
|
|
18612
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18613
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval lane handoff decision failed"), getNumericStatus(set.status));
|
|
18614
|
+
}
|
|
18615
|
+
return denied;
|
|
18616
|
+
}
|
|
17652
18617
|
const result = await handleRetrievalLaneHandoffDecision(body);
|
|
17653
18618
|
if (!result.ok) {
|
|
17654
18619
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17709,6 +18674,16 @@ var ragChat = (config) => {
|
|
|
17709
18674
|
}
|
|
17710
18675
|
return result;
|
|
17711
18676
|
}).post(`${path}/compare/retrieval/incidents/remediations`, async ({ body, request, set }) => {
|
|
18677
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18678
|
+
fallback: "Retrieval incident remediation decision record is not allowed"
|
|
18679
|
+
});
|
|
18680
|
+
if (denied) {
|
|
18681
|
+
set.status = 403;
|
|
18682
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18683
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval incident remediation decision record failed"), getNumericStatus(set.status));
|
|
18684
|
+
}
|
|
18685
|
+
return denied;
|
|
18686
|
+
}
|
|
17712
18687
|
const result = await handleRecordRetrievalIncidentRemediationDecision(body);
|
|
17713
18688
|
if (!result.ok) {
|
|
17714
18689
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17724,6 +18699,16 @@ var ragChat = (config) => {
|
|
|
17724
18699
|
}
|
|
17725
18700
|
return result;
|
|
17726
18701
|
}).post(`${path}/compare/retrieval/incidents/remediations/execute`, async ({ body, request, set }) => {
|
|
18702
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18703
|
+
fallback: "Retrieval incident remediation execution is not allowed"
|
|
18704
|
+
});
|
|
18705
|
+
if (denied) {
|
|
18706
|
+
set.status = 403;
|
|
18707
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18708
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval incident remediation execution failed"), getNumericStatus(set.status));
|
|
18709
|
+
}
|
|
18710
|
+
return denied;
|
|
18711
|
+
}
|
|
17727
18712
|
const result = await handleExecuteRetrievalIncidentRemediation(body);
|
|
17728
18713
|
if (!result.ok) {
|
|
17729
18714
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17739,6 +18724,16 @@ var ragChat = (config) => {
|
|
|
17739
18724
|
}
|
|
17740
18725
|
return result;
|
|
17741
18726
|
}).post(`${path}/compare/retrieval/incidents/remediations/execute/bulk`, async ({ body, request, set }) => {
|
|
18727
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18728
|
+
fallback: "Bulk retrieval incident remediation execution is not allowed"
|
|
18729
|
+
});
|
|
18730
|
+
if (denied) {
|
|
18731
|
+
set.status = 403;
|
|
18732
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18733
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Bulk retrieval incident remediation execution failed"), getNumericStatus(set.status));
|
|
18734
|
+
}
|
|
18735
|
+
return denied;
|
|
18736
|
+
}
|
|
17742
18737
|
const result = await handleBulkExecuteRetrievalIncidentRemediations(body);
|
|
17743
18738
|
if (!result.ok) {
|
|
17744
18739
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17754,6 +18749,16 @@ var ragChat = (config) => {
|
|
|
17754
18749
|
}
|
|
17755
18750
|
return result;
|
|
17756
18751
|
}).post(`${path}/compare/retrieval/incidents/acknowledge`, async ({ body, request, set }) => {
|
|
18752
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18753
|
+
fallback: "Retrieval release incident acknowledgement is not allowed"
|
|
18754
|
+
});
|
|
18755
|
+
if (denied) {
|
|
18756
|
+
set.status = 403;
|
|
18757
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18758
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident acknowledgement failed"), getNumericStatus(set.status));
|
|
18759
|
+
}
|
|
18760
|
+
return denied;
|
|
18761
|
+
}
|
|
17757
18762
|
const result = await handleAcknowledgeRetrievalReleaseIncident(body);
|
|
17758
18763
|
if (!result.ok) {
|
|
17759
18764
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17769,6 +18774,16 @@ var ragChat = (config) => {
|
|
|
17769
18774
|
}
|
|
17770
18775
|
return result;
|
|
17771
18776
|
}).post(`${path}/compare/retrieval/incidents/unacknowledge`, async ({ body, request, set }) => {
|
|
18777
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18778
|
+
fallback: "Retrieval release incident unacknowledge is not allowed"
|
|
18779
|
+
});
|
|
18780
|
+
if (denied) {
|
|
18781
|
+
set.status = 403;
|
|
18782
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18783
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident unacknowledge failed"), getNumericStatus(set.status));
|
|
18784
|
+
}
|
|
18785
|
+
return denied;
|
|
18786
|
+
}
|
|
17772
18787
|
const result = await handleUnacknowledgeRetrievalReleaseIncident(body);
|
|
17773
18788
|
if (!result.ok) {
|
|
17774
18789
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17784,6 +18799,16 @@ var ragChat = (config) => {
|
|
|
17784
18799
|
}
|
|
17785
18800
|
return result;
|
|
17786
18801
|
}).post(`${path}/compare/retrieval/incidents/resolve`, async ({ body, request, set }) => {
|
|
18802
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18803
|
+
fallback: "Retrieval release incident resolve is not allowed"
|
|
18804
|
+
});
|
|
18805
|
+
if (denied) {
|
|
18806
|
+
set.status = 403;
|
|
18807
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18808
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval release incident resolve failed"), getNumericStatus(set.status));
|
|
18809
|
+
}
|
|
18810
|
+
return denied;
|
|
18811
|
+
}
|
|
17787
18812
|
const result = await handleResolveRetrievalReleaseIncident(body);
|
|
17788
18813
|
if (!result.ok) {
|
|
17789
18814
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17814,7 +18839,15 @@ var ragChat = (config) => {
|
|
|
17814
18839
|
}
|
|
17815
18840
|
return result;
|
|
17816
18841
|
}).post(`${path}/compare/retrieval/baselines/approve`, async ({ body, request, set }) => {
|
|
17817
|
-
const
|
|
18842
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval approval is not allowed" });
|
|
18843
|
+
if (denied) {
|
|
18844
|
+
set.status = 403;
|
|
18845
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18846
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval approval failed"), getNumericStatus(set.status));
|
|
18847
|
+
}
|
|
18848
|
+
return denied;
|
|
18849
|
+
}
|
|
18850
|
+
const result = await handleRetrievalReleaseDecisionAction(body, "approve", request);
|
|
17818
18851
|
if (!result.ok) {
|
|
17819
18852
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17820
18853
|
}
|
|
@@ -17829,7 +18862,15 @@ var ragChat = (config) => {
|
|
|
17829
18862
|
}
|
|
17830
18863
|
return result;
|
|
17831
18864
|
}).post(`${path}/compare/retrieval/baselines/reject`, async ({ body, request, set }) => {
|
|
17832
|
-
const
|
|
18865
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval rejection is not allowed" });
|
|
18866
|
+
if (denied) {
|
|
18867
|
+
set.status = 403;
|
|
18868
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18869
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval rejection failed"), getNumericStatus(set.status));
|
|
18870
|
+
}
|
|
18871
|
+
return denied;
|
|
18872
|
+
}
|
|
18873
|
+
const result = await handleRetrievalReleaseDecisionAction(body, "reject", request);
|
|
17833
18874
|
if (!result.ok) {
|
|
17834
18875
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17835
18876
|
}
|
|
@@ -17844,7 +18885,15 @@ var ragChat = (config) => {
|
|
|
17844
18885
|
}
|
|
17845
18886
|
return result;
|
|
17846
18887
|
}).post(`${path}/compare/retrieval/baselines/promote`, async ({ body, request, set }) => {
|
|
17847
|
-
const
|
|
18888
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval baseline promotion is not allowed" });
|
|
18889
|
+
if (denied) {
|
|
18890
|
+
set.status = 403;
|
|
18891
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18892
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline promotion failed"), getNumericStatus(set.status));
|
|
18893
|
+
}
|
|
18894
|
+
return denied;
|
|
18895
|
+
}
|
|
18896
|
+
const result = await handlePromoteRetrievalBaseline(body, request);
|
|
17848
18897
|
if (!result.ok) {
|
|
17849
18898
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17850
18899
|
}
|
|
@@ -17859,6 +18908,16 @@ var ragChat = (config) => {
|
|
|
17859
18908
|
}
|
|
17860
18909
|
return result;
|
|
17861
18910
|
}).post(`${path}/compare/retrieval/baselines/promote-lane`, async ({ body, request, set }) => {
|
|
18911
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18912
|
+
fallback: "Retrieval rollout-lane promotion is not allowed"
|
|
18913
|
+
});
|
|
18914
|
+
if (denied) {
|
|
18915
|
+
set.status = 403;
|
|
18916
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18917
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval rollout-lane promotion failed"), getNumericStatus(set.status));
|
|
18918
|
+
}
|
|
18919
|
+
return denied;
|
|
18920
|
+
}
|
|
17862
18921
|
const result = await handlePromoteRetrievalBaselineToLane(body);
|
|
17863
18922
|
if (!result.ok) {
|
|
17864
18923
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -17874,7 +18933,17 @@ var ragChat = (config) => {
|
|
|
17874
18933
|
}
|
|
17875
18934
|
return result;
|
|
17876
18935
|
}).post(`${path}/compare/retrieval/baselines/promote-run`, async ({ body, request, set }) => {
|
|
17877
|
-
const
|
|
18936
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", {
|
|
18937
|
+
fallback: "Retrieval baseline promotion from run is not allowed"
|
|
18938
|
+
});
|
|
18939
|
+
if (denied) {
|
|
18940
|
+
set.status = 403;
|
|
18941
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18942
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline promotion from run failed"), getNumericStatus(set.status));
|
|
18943
|
+
}
|
|
18944
|
+
return denied;
|
|
18945
|
+
}
|
|
18946
|
+
const result = await handlePromoteRetrievalBaselineFromRun(body, request);
|
|
17878
18947
|
if (!result.ok) {
|
|
17879
18948
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17880
18949
|
}
|
|
@@ -17889,7 +18958,15 @@ var ragChat = (config) => {
|
|
|
17889
18958
|
}
|
|
17890
18959
|
return result;
|
|
17891
18960
|
}).post(`${path}/compare/retrieval/baselines/revert`, async ({ body, request, set }) => {
|
|
17892
|
-
const
|
|
18961
|
+
const denied = await authorizeMutationRoute(request, "manage_retrieval_admin", { fallback: "Retrieval baseline revert is not allowed" });
|
|
18962
|
+
if (denied) {
|
|
18963
|
+
set.status = 403;
|
|
18964
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
18965
|
+
return toHTMXResponse(workflowRenderers.error(denied.error ?? "Retrieval baseline revert failed"), getNumericStatus(set.status));
|
|
18966
|
+
}
|
|
18967
|
+
return denied;
|
|
18968
|
+
}
|
|
18969
|
+
const result = await handleRevertRetrievalBaseline(body, request);
|
|
17893
18970
|
if (!result.ok) {
|
|
17894
18971
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17895
18972
|
}
|
|
@@ -17904,7 +18981,7 @@ var ragChat = (config) => {
|
|
|
17904
18981
|
}
|
|
17905
18982
|
return result;
|
|
17906
18983
|
}).post(`${path}/evaluate`, async ({ body, request, set }) => {
|
|
17907
|
-
const result = await handleEvaluate(body);
|
|
18984
|
+
const result = await handleEvaluate(body, request);
|
|
17908
18985
|
if (!result.ok) {
|
|
17909
18986
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17910
18987
|
}
|
|
@@ -17919,7 +18996,7 @@ var ragChat = (config) => {
|
|
|
17919
18996
|
}
|
|
17920
18997
|
return result;
|
|
17921
18998
|
}).get(`${path}/status`, async ({ request }) => {
|
|
17922
|
-
const result = await handleStatus();
|
|
18999
|
+
const result = await handleStatus(request);
|
|
17923
19000
|
if (config.htmx && isHTMXRequest(request)) {
|
|
17924
19001
|
return toHTMXResponse(workflowRenderers.status({
|
|
17925
19002
|
capabilities: result.capabilities,
|
|
@@ -17959,7 +19036,7 @@ var ragChat = (config) => {
|
|
|
17959
19036
|
}
|
|
17960
19037
|
return result;
|
|
17961
19038
|
}).get(`${path}/compare/retrieval/escalation-policies/history`, async ({ query, request, set }) => {
|
|
17962
|
-
const result = await handleRetrievalReleaseLaneEscalationPolicyHistoryList(query);
|
|
19039
|
+
const result = await handleRetrievalReleaseLaneEscalationPolicyHistoryList(query, request);
|
|
17963
19040
|
if (!result.ok) {
|
|
17964
19041
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17965
19042
|
}
|
|
@@ -17974,7 +19051,7 @@ var ragChat = (config) => {
|
|
|
17974
19051
|
}
|
|
17975
19052
|
return result;
|
|
17976
19053
|
}).get(`${path}/compare/retrieval/incident-policies/history`, async ({ query, request, set }) => {
|
|
17977
|
-
const result = await handleRetrievalReleaseLaneEscalationPolicyHistoryList(query);
|
|
19054
|
+
const result = await handleRetrievalReleaseLaneEscalationPolicyHistoryList(query, request);
|
|
17978
19055
|
if (!result.ok) {
|
|
17979
19056
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
17980
19057
|
}
|
|
@@ -17988,20 +19065,21 @@ var ragChat = (config) => {
|
|
|
17988
19065
|
});
|
|
17989
19066
|
}
|
|
17990
19067
|
return result;
|
|
17991
|
-
}).get(`${path}/status/release`, async () => {
|
|
17992
|
-
return handleRetrievalReleaseStatus();
|
|
19068
|
+
}).get(`${path}/status/release`, async ({ request }) => {
|
|
19069
|
+
return handleRetrievalReleaseStatus(request);
|
|
17993
19070
|
}).get(`${path}/status/release/incidents`, async () => {
|
|
17994
19071
|
return handleRetrievalReleaseIncidentStatus();
|
|
17995
19072
|
}).get(`${path}/status/release/remediations`, async () => {
|
|
17996
19073
|
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();
|
|
19074
|
+
}).get(`${path}/status/release/drift`, async ({ request }) => {
|
|
19075
|
+
return handleRetrievalReleaseDriftStatus(request);
|
|
19076
|
+
}).get(`${path}/status/handoffs/incidents`, async ({ request }) => {
|
|
19077
|
+
return handleRetrievalLaneHandoffIncidentStatus(request);
|
|
19078
|
+
}).get(`${path}/status/handoffs`, async ({ request }) => {
|
|
19079
|
+
return handleRetrievalLaneHandoffStatus(request);
|
|
18003
19080
|
}).get(`${path}/ops`, async ({ request }) => {
|
|
18004
|
-
|
|
19081
|
+
await ensureJobStateLoaded();
|
|
19082
|
+
const result = await handleOps(request);
|
|
18005
19083
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18006
19084
|
return toHTMXResponse(workflowRenderers.status({
|
|
18007
19085
|
capabilities: result.capabilities,
|
|
@@ -18011,7 +19089,7 @@ var ragChat = (config) => {
|
|
|
18011
19089
|
}
|
|
18012
19090
|
return result;
|
|
18013
19091
|
}).get(`${path}/documents`, async ({ query, request, set }) => {
|
|
18014
|
-
const result = await handleDocuments(getStringProperty(query, "kind"));
|
|
19092
|
+
const result = await handleDocuments(getStringProperty(query, "kind"), request);
|
|
18015
19093
|
if (!result.ok) {
|
|
18016
19094
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18017
19095
|
}
|
|
@@ -18025,9 +19103,19 @@ var ragChat = (config) => {
|
|
|
18025
19103
|
}
|
|
18026
19104
|
return result;
|
|
18027
19105
|
}).post(`${path}/documents`, async ({ body, request, set }) => {
|
|
18028
|
-
|
|
19106
|
+
await ensureJobStateLoaded();
|
|
19107
|
+
const authorization = await checkAuthorization(request, "create_document");
|
|
19108
|
+
if (!authorization.allowed) {
|
|
19109
|
+
set.status = 403;
|
|
19110
|
+
const result2 = buildAuthorizationFailure(authorization, "Document creation is not allowed");
|
|
19111
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19112
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to create document"), getNumericStatus(set.status));
|
|
19113
|
+
}
|
|
19114
|
+
return result2;
|
|
19115
|
+
}
|
|
19116
|
+
const result = await handleCreateDocument(body, request);
|
|
18029
19117
|
if (!result.ok) {
|
|
18030
|
-
const status = result.error?.includes("not configured") ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_BAD_REQUEST;
|
|
19118
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error?.includes("not configured") ? HTTP_STATUS_NOT_FOUND : HTTP_STATUS_BAD_REQUEST;
|
|
18031
19119
|
set.status = status;
|
|
18032
19120
|
}
|
|
18033
19121
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18038,9 +19126,9 @@ var ragChat = (config) => {
|
|
|
18038
19126
|
}
|
|
18039
19127
|
return result;
|
|
18040
19128
|
}).get(`${path}/documents/:id/chunks`, async ({ params, request, set }) => {
|
|
18041
|
-
const result = await handleDocumentChunks(typeof params.id === "string" ? params.id.trim() : "");
|
|
19129
|
+
const result = await handleDocumentChunks(typeof params.id === "string" ? params.id.trim() : "", request);
|
|
18042
19130
|
if (!result.ok) {
|
|
18043
|
-
const status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
19131
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18044
19132
|
set.status = status;
|
|
18045
19133
|
}
|
|
18046
19134
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18054,10 +19142,13 @@ var ragChat = (config) => {
|
|
|
18054
19142
|
const result = await handleBackends();
|
|
18055
19143
|
if (!result.ok) {
|
|
18056
19144
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
19145
|
+
if (isAccessScopeError(result.error)) {
|
|
19146
|
+
set.status = 403;
|
|
19147
|
+
}
|
|
18057
19148
|
}
|
|
18058
19149
|
return result;
|
|
18059
19150
|
}).get(`${path}/sync`, async ({ request, set }) => {
|
|
18060
|
-
const result = await handleSyncSources();
|
|
19151
|
+
const result = await handleSyncSources(request);
|
|
18061
19152
|
if (!result.ok) {
|
|
18062
19153
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18063
19154
|
}
|
|
@@ -18072,8 +19163,18 @@ var ragChat = (config) => {
|
|
|
18072
19163
|
}
|
|
18073
19164
|
return result;
|
|
18074
19165
|
}).post(`${path}/sync`, async ({ body, request, set }) => {
|
|
19166
|
+
await ensureJobStateLoaded();
|
|
19167
|
+
const authorization = await checkAuthorization(request, "sync_all_sources");
|
|
19168
|
+
if (!authorization.allowed) {
|
|
19169
|
+
set.status = 403;
|
|
19170
|
+
const result2 = buildAuthorizationFailure(authorization, "Source sync is not allowed");
|
|
19171
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19172
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to sync sources"), getNumericStatus(set.status));
|
|
19173
|
+
}
|
|
19174
|
+
return result2;
|
|
19175
|
+
}
|
|
18075
19176
|
const background = getBooleanProperty(body, "background");
|
|
18076
|
-
const result = await handleSyncAllSources({ background });
|
|
19177
|
+
const result = await handleSyncAllSources(request, { background });
|
|
18077
19178
|
if (!result.ok) {
|
|
18078
19179
|
set.status = HTTP_STATUS_NOT_FOUND;
|
|
18079
19180
|
}
|
|
@@ -18088,10 +19189,28 @@ var ragChat = (config) => {
|
|
|
18088
19189
|
}
|
|
18089
19190
|
return result;
|
|
18090
19191
|
}).post(`${path}/sync/:id`, async ({ body, params, request, set }) => {
|
|
19192
|
+
await ensureJobStateLoaded();
|
|
19193
|
+
const syncSourceId = typeof params.id === "string" ? params.id.trim() : "";
|
|
19194
|
+
const authorization = await checkAuthorization(request, "sync_source", {
|
|
19195
|
+
sourceId: syncSourceId
|
|
19196
|
+
});
|
|
19197
|
+
if (!authorization.allowed) {
|
|
19198
|
+
set.status = 403;
|
|
19199
|
+
const result2 = buildAuthorizationFailure(authorization, "Source sync is not allowed");
|
|
19200
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19201
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to sync source"), getNumericStatus(set.status));
|
|
19202
|
+
}
|
|
19203
|
+
return result2;
|
|
19204
|
+
}
|
|
18091
19205
|
const background = getBooleanProperty(body, "background");
|
|
18092
|
-
const result = await handleSyncSource(
|
|
19206
|
+
const result = await handleSyncSource(syncSourceId, request, {
|
|
19207
|
+
background
|
|
19208
|
+
});
|
|
18093
19209
|
if (!result.ok) {
|
|
18094
19210
|
set.status = result.error === "sync source id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
19211
|
+
if (isAccessScopeError(result.error)) {
|
|
19212
|
+
set.status = 403;
|
|
19213
|
+
}
|
|
18095
19214
|
}
|
|
18096
19215
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18097
19216
|
const html = result.ok ? workflowRenderers.mutationResult({
|
|
@@ -18104,6 +19223,18 @@ var ragChat = (config) => {
|
|
|
18104
19223
|
}
|
|
18105
19224
|
return result;
|
|
18106
19225
|
}).post(`${path}/ingest`, async ({ body, request, set }) => {
|
|
19226
|
+
await ensureJobStateLoaded();
|
|
19227
|
+
const authorization = await checkAuthorization(request, "ingest", {
|
|
19228
|
+
path: `${path}/ingest`
|
|
19229
|
+
});
|
|
19230
|
+
if (!authorization.allowed) {
|
|
19231
|
+
set.status = 403;
|
|
19232
|
+
const result2 = buildAuthorizationFailure(authorization, "RAG ingest is not allowed");
|
|
19233
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19234
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "RAG ingest failed"), getNumericStatus(set.status));
|
|
19235
|
+
}
|
|
19236
|
+
return result2;
|
|
19237
|
+
}
|
|
18107
19238
|
const result = await handleIngest(body);
|
|
18108
19239
|
if (!result.ok) {
|
|
18109
19240
|
set.status = HTTP_STATUS_BAD_REQUEST;
|
|
@@ -18115,7 +19246,13 @@ var ragChat = (config) => {
|
|
|
18115
19246
|
return toHTMXResponse(workflowRenderers.mutationResult(result), HTTP_STATUS_OK, { "HX-Trigger": "rag:mutated" });
|
|
18116
19247
|
}
|
|
18117
19248
|
return result;
|
|
18118
|
-
}).delete(`${path}/index`, async () => {
|
|
19249
|
+
}).delete(`${path}/index`, async ({ request, set }) => {
|
|
19250
|
+
await ensureJobStateLoaded();
|
|
19251
|
+
const authorization = await checkAuthorization(request, "clear_index");
|
|
19252
|
+
if (!authorization.allowed) {
|
|
19253
|
+
set.status = 403;
|
|
19254
|
+
return buildAuthorizationFailure(authorization, "Index clearing is not allowed");
|
|
19255
|
+
}
|
|
18119
19256
|
if (!ragStore) {
|
|
18120
19257
|
return { ok: false };
|
|
18121
19258
|
}
|
|
@@ -18134,9 +19271,22 @@ var ragChat = (config) => {
|
|
|
18134
19271
|
}
|
|
18135
19272
|
return { ok: true };
|
|
18136
19273
|
}).delete(`${path}/documents/:id`, async ({ params, request, set }) => {
|
|
18137
|
-
|
|
19274
|
+
await ensureJobStateLoaded();
|
|
19275
|
+
const documentId = typeof params.id === "string" ? params.id.trim() : "";
|
|
19276
|
+
const authorization = await checkAuthorization(request, "delete_document", {
|
|
19277
|
+
documentId
|
|
19278
|
+
});
|
|
19279
|
+
if (!authorization.allowed) {
|
|
19280
|
+
set.status = 403;
|
|
19281
|
+
const result2 = buildAuthorizationFailure(authorization, "Document deletion is not allowed");
|
|
19282
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19283
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to delete document"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
19284
|
+
}
|
|
19285
|
+
return result2;
|
|
19286
|
+
}
|
|
19287
|
+
const result = await handleDeleteDocument(documentId, request);
|
|
18138
19288
|
if (!result.ok) {
|
|
18139
|
-
const status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
19289
|
+
const status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18140
19290
|
set.status = status;
|
|
18141
19291
|
}
|
|
18142
19292
|
if (config.htmx && isHTMXRequest(request)) {
|
|
@@ -18147,9 +19297,20 @@ var ragChat = (config) => {
|
|
|
18147
19297
|
}
|
|
18148
19298
|
return result;
|
|
18149
19299
|
}).post(`${path}/reindex/documents/:id`, async ({ params, request, set }) => {
|
|
18150
|
-
|
|
19300
|
+
await ensureJobStateLoaded();
|
|
19301
|
+
const documentId = typeof params.id === "string" ? params.id.trim() : "";
|
|
19302
|
+
const authorization = await checkAuthorization(request, "reindex_document", { documentId });
|
|
19303
|
+
if (!authorization.allowed) {
|
|
19304
|
+
set.status = 403;
|
|
19305
|
+
const result2 = buildAuthorizationFailure(authorization, "Document reindex is not allowed");
|
|
19306
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19307
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reindex document"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
19308
|
+
}
|
|
19309
|
+
return result2;
|
|
19310
|
+
}
|
|
19311
|
+
const result = await handleReindexDocument(documentId, request);
|
|
18151
19312
|
if (!result.ok) {
|
|
18152
|
-
set.status = result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
19313
|
+
set.status = isAccessScopeError(result.error) ? 403 : result.error === "document id is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18153
19314
|
}
|
|
18154
19315
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18155
19316
|
const html = result.ok ? workflowRenderers.mutationResult(result) : workflowRenderers.error(result.error ?? "Failed to reindex document");
|
|
@@ -18159,10 +19320,22 @@ var ragChat = (config) => {
|
|
|
18159
19320
|
}
|
|
18160
19321
|
return result;
|
|
18161
19322
|
}).post(`${path}/reindex/source`, async ({ body, request, set }) => {
|
|
19323
|
+
await ensureJobStateLoaded();
|
|
18162
19324
|
const source = getStringProperty(body, "source")?.trim() ?? "";
|
|
18163
|
-
const
|
|
19325
|
+
const authorization = await checkAuthorization(request, "reindex_source", {
|
|
19326
|
+
source
|
|
19327
|
+
});
|
|
19328
|
+
if (!authorization.allowed) {
|
|
19329
|
+
set.status = 403;
|
|
19330
|
+
const result2 = buildAuthorizationFailure(authorization, "Source reindex is not allowed");
|
|
19331
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19332
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reindex source"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
19333
|
+
}
|
|
19334
|
+
return result2;
|
|
19335
|
+
}
|
|
19336
|
+
const result = await handleReindexSource(source, request);
|
|
18164
19337
|
if (!result.ok) {
|
|
18165
|
-
set.status = result.error === "source is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
19338
|
+
set.status = isAccessScopeError(result.error) ? 403 : result.error === "source is required" ? HTTP_STATUS_BAD_REQUEST : HTTP_STATUS_NOT_FOUND;
|
|
18166
19339
|
}
|
|
18167
19340
|
if (config.htmx && isHTMXRequest(request)) {
|
|
18168
19341
|
const html = result.ok ? workflowRenderers.mutationResult(result) : workflowRenderers.error(result.error ?? "Failed to reindex source");
|
|
@@ -18172,6 +19345,16 @@ var ragChat = (config) => {
|
|
|
18172
19345
|
}
|
|
18173
19346
|
return result;
|
|
18174
19347
|
}).post(`${path}/reseed`, async ({ request, set }) => {
|
|
19348
|
+
await ensureJobStateLoaded();
|
|
19349
|
+
const authorization = await checkAuthorization(request, "reseed");
|
|
19350
|
+
if (!authorization.allowed) {
|
|
19351
|
+
set.status = 403;
|
|
19352
|
+
const result2 = buildAuthorizationFailure(authorization, "Index reseed is not allowed");
|
|
19353
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19354
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reseed index"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
19355
|
+
}
|
|
19356
|
+
return result2;
|
|
19357
|
+
}
|
|
18175
19358
|
const result = await handleReseed();
|
|
18176
19359
|
if (!result.ok) {
|
|
18177
19360
|
set.status = 404;
|
|
@@ -18184,6 +19367,16 @@ var ragChat = (config) => {
|
|
|
18184
19367
|
}
|
|
18185
19368
|
return result;
|
|
18186
19369
|
}).post(`${path}/reset`, async ({ request, set }) => {
|
|
19370
|
+
await ensureJobStateLoaded();
|
|
19371
|
+
const authorization = await checkAuthorization(request, "reset");
|
|
19372
|
+
if (!authorization.allowed) {
|
|
19373
|
+
set.status = 403;
|
|
19374
|
+
const result2 = buildAuthorizationFailure(authorization, "Index reset is not allowed");
|
|
19375
|
+
if (config.htmx && isHTMXRequest(request)) {
|
|
19376
|
+
return toHTMXResponse(workflowRenderers.error(result2.error ?? "Failed to reset index"), getNumericStatus(set.status), { "HX-Trigger": "rag:mutated" });
|
|
19377
|
+
}
|
|
19378
|
+
return result2;
|
|
19379
|
+
}
|
|
18187
19380
|
const result = await handleReset();
|
|
18188
19381
|
if (!result.ok) {
|
|
18189
19382
|
set.status = 404;
|
|
@@ -18271,6 +19464,31 @@ var createHeuristicRAGRetrievalStrategy = (options = {}) => ({
|
|
|
18271
19464
|
return;
|
|
18272
19465
|
}
|
|
18273
19466
|
});
|
|
19467
|
+
// src/ai/rag/accessControl.ts
|
|
19468
|
+
var createRAGAccessControl = (options) => {
|
|
19469
|
+
const authorize = options.authorize;
|
|
19470
|
+
const contextCache = new WeakMap;
|
|
19471
|
+
const resolveScope = options.resolveScope;
|
|
19472
|
+
const loadContext = (request) => {
|
|
19473
|
+
const existing = contextCache.get(request);
|
|
19474
|
+
if (existing) {
|
|
19475
|
+
return existing;
|
|
19476
|
+
}
|
|
19477
|
+
const next = Promise.resolve(options.resolveContext(request));
|
|
19478
|
+
contextCache.set(request, next);
|
|
19479
|
+
return next;
|
|
19480
|
+
};
|
|
19481
|
+
return {
|
|
19482
|
+
authorizeRAGAction: authorize ? async (input) => authorize({
|
|
19483
|
+
...input,
|
|
19484
|
+
context: await loadContext(input.request)
|
|
19485
|
+
}) : undefined,
|
|
19486
|
+
resolveRAGAccessScope: resolveScope ? async (request) => resolveScope({
|
|
19487
|
+
context: await loadContext(request),
|
|
19488
|
+
request
|
|
19489
|
+
}) : undefined
|
|
19490
|
+
};
|
|
19491
|
+
};
|
|
18274
19492
|
// src/ai/rag/embeddingProviders.ts
|
|
18275
19493
|
var DEFAULT_OPENAI_BASE_URL = "https://api.openai.com";
|
|
18276
19494
|
var DEFAULT_GEMINI_BASE_URL = "https://generativelanguage.googleapis.com";
|
|
@@ -19128,6 +20346,8 @@ var isManagedBySyncSource = (document, sourceId) => document.metadata?.syncSourc
|
|
|
19128
20346
|
var getDocumentSyncFingerprint = (document) => typeof document.metadata?.syncFingerprint === "string" ? document.metadata.syncFingerprint : undefined;
|
|
19129
20347
|
var reconcileManagedDocuments = async (input) => {
|
|
19130
20348
|
const prepared = prepareRAGDocuments({
|
|
20349
|
+
chunkingRegistry: input.chunkingRegistry,
|
|
20350
|
+
defaultChunking: input.defaultChunking,
|
|
19131
20351
|
documents: input.documents
|
|
19132
20352
|
});
|
|
19133
20353
|
const nextDocumentIds = new Set(prepared.map((document) => document.documentId));
|
|
@@ -19172,6 +20392,19 @@ var toSourceRecord = (source, overrides) => ({
|
|
|
19172
20392
|
target: source.target,
|
|
19173
20393
|
...overrides
|
|
19174
20394
|
});
|
|
20395
|
+
var recoverSyncSourceRecord = (source, record, recoveredAt) => record.status === "running" ? toSourceRecord(source, {
|
|
20396
|
+
...record,
|
|
20397
|
+
lastError: record.lastError ?? "Interrupted before completion during recovery",
|
|
20398
|
+
lastSyncedAt: recoveredAt,
|
|
20399
|
+
nextRetryAt: undefined,
|
|
20400
|
+
status: "failed"
|
|
20401
|
+
}) : toSourceRecord(source, {
|
|
20402
|
+
...record,
|
|
20403
|
+
metadata: {
|
|
20404
|
+
...source.metadata ?? {},
|
|
20405
|
+
...record.metadata ?? {}
|
|
20406
|
+
}
|
|
20407
|
+
});
|
|
19175
20408
|
var createRAGDirectorySyncSource = (options) => ({
|
|
19176
20409
|
description: options.description,
|
|
19177
20410
|
id: options.id,
|
|
@@ -19185,14 +20418,18 @@ var createRAGDirectorySyncSource = (options) => ({
|
|
|
19185
20418
|
const loaded = await loadRAGDocumentsFromDirectory({
|
|
19186
20419
|
baseMetadata: options.baseMetadata,
|
|
19187
20420
|
defaultChunking: options.defaultChunking,
|
|
20421
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19188
20422
|
directory: options.directory,
|
|
19189
20423
|
extractors: options.extractors,
|
|
20424
|
+
extractorRegistry: options.extractorRegistry,
|
|
19190
20425
|
includeExtensions: options.includeExtensions,
|
|
19191
20426
|
recursive: options.recursive
|
|
19192
20427
|
});
|
|
19193
20428
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.relativePath === "string" ? document.metadata.relativePath : document.source ?? document.title ?? ""));
|
|
19194
20429
|
const reconciled = await reconcileManagedDocuments({
|
|
20430
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19195
20431
|
collection,
|
|
20432
|
+
defaultChunking: options.defaultChunking,
|
|
19196
20433
|
deleteDocument,
|
|
19197
20434
|
documents: managedDocuments,
|
|
19198
20435
|
listDocuments,
|
|
@@ -19223,12 +20460,16 @@ var createRAGUrlSyncSource = (options) => ({
|
|
|
19223
20460
|
const loaded = await loadRAGDocumentsFromURLs({
|
|
19224
20461
|
baseMetadata: options.baseMetadata,
|
|
19225
20462
|
defaultChunking: options.defaultChunking,
|
|
20463
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19226
20464
|
extractors: options.extractors,
|
|
20465
|
+
extractorRegistry: options.extractorRegistry,
|
|
19227
20466
|
urls: options.urls
|
|
19228
20467
|
});
|
|
19229
20468
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.sourceUrl === "string" ? document.metadata.sourceUrl : document.source ?? document.title ?? ""));
|
|
19230
20469
|
const reconciled = await reconcileManagedDocuments({
|
|
20470
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19231
20471
|
collection,
|
|
20472
|
+
defaultChunking: options.defaultChunking,
|
|
19232
20473
|
deleteDocument,
|
|
19233
20474
|
documents: managedDocuments,
|
|
19234
20475
|
listDocuments,
|
|
@@ -19326,12 +20567,16 @@ var createRAGStorageSyncSource = (options) => ({
|
|
|
19326
20567
|
const loaded = await loadRAGDocumentsFromUploads({
|
|
19327
20568
|
baseMetadata: options.baseMetadata,
|
|
19328
20569
|
defaultChunking: options.defaultChunking,
|
|
20570
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19329
20571
|
extractors: options.extractors,
|
|
20572
|
+
extractorRegistry: options.extractorRegistry,
|
|
19330
20573
|
uploads
|
|
19331
20574
|
});
|
|
19332
20575
|
const managedDocuments = loaded.documents.map((document) => toManagedSyncDocument(options.id, document, typeof document.metadata?.storageKey === "string" ? document.metadata.storageKey : document.source ?? document.title ?? ""));
|
|
19333
20576
|
const reconciled = await reconcileManagedDocuments({
|
|
20577
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19334
20578
|
collection,
|
|
20579
|
+
defaultChunking: options.defaultChunking,
|
|
19335
20580
|
deleteDocument,
|
|
19336
20581
|
documents: managedDocuments,
|
|
19337
20582
|
listDocuments,
|
|
@@ -19412,7 +20657,9 @@ var createRAGEmailSyncSource = (options) => ({
|
|
|
19412
20657
|
const loadedAttachments = attachmentUploads.length > 0 ? await loadRAGDocumentsFromUploads({
|
|
19413
20658
|
baseMetadata: options.baseMetadata,
|
|
19414
20659
|
defaultChunking: options.defaultChunking,
|
|
20660
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19415
20661
|
extractors: options.extractors,
|
|
20662
|
+
extractorRegistry: options.extractorRegistry,
|
|
19416
20663
|
uploads: attachmentUploads
|
|
19417
20664
|
}) : { documents: [] };
|
|
19418
20665
|
const managedDocuments = [
|
|
@@ -19420,7 +20667,9 @@ var createRAGEmailSyncSource = (options) => ({
|
|
|
19420
20667
|
...loadedAttachments.documents.map((document) => toManagedSyncDocument(options.id, document, `attachment:${String(document.metadata?.attachmentId ?? document.source ?? document.title ?? "")}`))
|
|
19421
20668
|
];
|
|
19422
20669
|
const reconciled = await reconcileManagedDocuments({
|
|
20670
|
+
chunkingRegistry: options.chunkingRegistry,
|
|
19423
20671
|
collection,
|
|
20672
|
+
defaultChunking: options.defaultChunking,
|
|
19424
20673
|
deleteDocument,
|
|
19425
20674
|
documents: managedDocuments,
|
|
19426
20675
|
listDocuments,
|
|
@@ -19455,22 +20704,18 @@ var createRAGSyncManager = (options) => {
|
|
|
19455
20704
|
}
|
|
19456
20705
|
if (!hydrationPromise) {
|
|
19457
20706
|
hydrationPromise = Promise.resolve(options.loadState()).then((records) => {
|
|
20707
|
+
const recoveredAt = Date.now();
|
|
19458
20708
|
for (const record of records ?? []) {
|
|
19459
20709
|
const source = sourceMap.get(record.id);
|
|
19460
20710
|
if (!source) {
|
|
19461
20711
|
continue;
|
|
19462
20712
|
}
|
|
19463
|
-
state.set(record.id,
|
|
19464
|
-
...record,
|
|
19465
|
-
metadata: {
|
|
19466
|
-
...source.metadata ?? {},
|
|
19467
|
-
...record.metadata ?? {}
|
|
19468
|
-
}
|
|
19469
|
-
}));
|
|
20713
|
+
state.set(record.id, recoverSyncSourceRecord(source, record, recoveredAt));
|
|
19470
20714
|
}
|
|
19471
20715
|
});
|
|
19472
20716
|
}
|
|
19473
20717
|
await hydrationPromise;
|
|
20718
|
+
await persistState();
|
|
19474
20719
|
};
|
|
19475
20720
|
const resolveRetryAttempts = (source) => Math.max(0, source.retryAttempts ?? options.retryAttempts ?? 0);
|
|
19476
20721
|
const resolveRetryDelayMs = (source) => Math.max(0, source.retryDelayMs ?? options.retryDelayMs ?? 0);
|
|
@@ -19716,6 +20961,48 @@ var createRAGSyncScheduler = (input) => {
|
|
|
19716
20961
|
listSchedules: () => [...input.schedules]
|
|
19717
20962
|
};
|
|
19718
20963
|
};
|
|
20964
|
+
// src/ai/rag/jobState.ts
|
|
20965
|
+
import { mkdir as mkdir3, readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
|
|
20966
|
+
import { dirname as dirname3, resolve as resolve3 } from "path";
|
|
20967
|
+
var parseJobState = (content) => {
|
|
20968
|
+
try {
|
|
20969
|
+
const parsed = JSON.parse(content);
|
|
20970
|
+
return {
|
|
20971
|
+
adminActions: Array.isArray(parsed.adminActions) ? parsed.adminActions : [],
|
|
20972
|
+
adminJobs: Array.isArray(parsed.adminJobs) ? parsed.adminJobs : [],
|
|
20973
|
+
ingestJobs: Array.isArray(parsed.ingestJobs) ? parsed.ingestJobs : [],
|
|
20974
|
+
syncJobs: Array.isArray(parsed.syncJobs) ? parsed.syncJobs : []
|
|
20975
|
+
};
|
|
20976
|
+
} catch {
|
|
20977
|
+
return {
|
|
20978
|
+
adminActions: [],
|
|
20979
|
+
adminJobs: [],
|
|
20980
|
+
ingestJobs: [],
|
|
20981
|
+
syncJobs: []
|
|
20982
|
+
};
|
|
20983
|
+
}
|
|
20984
|
+
};
|
|
20985
|
+
var createRAGFileJobStateStore = (path) => {
|
|
20986
|
+
const resolvedPath = resolve3(path);
|
|
20987
|
+
return {
|
|
20988
|
+
load: async () => {
|
|
20989
|
+
try {
|
|
20990
|
+
return parseJobState(await readFile4(resolvedPath, "utf8"));
|
|
20991
|
+
} catch {
|
|
20992
|
+
return {
|
|
20993
|
+
adminActions: [],
|
|
20994
|
+
adminJobs: [],
|
|
20995
|
+
ingestJobs: [],
|
|
20996
|
+
syncJobs: []
|
|
20997
|
+
};
|
|
20998
|
+
}
|
|
20999
|
+
},
|
|
21000
|
+
save: async (state) => {
|
|
21001
|
+
await mkdir3(dirname3(resolvedPath), { recursive: true });
|
|
21002
|
+
await writeFile3(resolvedPath, JSON.stringify(state, null, 2), "utf8");
|
|
21003
|
+
}
|
|
21004
|
+
};
|
|
21005
|
+
};
|
|
19719
21006
|
// src/ai/rag/adapters/utils.ts
|
|
19720
21007
|
var vectorDimensionDefault = 24;
|
|
19721
21008
|
var createRAGVector = (text, dimensions = vectorDimensionDefault) => {
|
|
@@ -19874,7 +21161,7 @@ import { existsSync as existsSync2 } from "fs";
|
|
|
19874
21161
|
// src/ai/rag/resolveAbsoluteSQLiteVec.ts
|
|
19875
21162
|
import { existsSync, readFileSync } from "fs";
|
|
19876
21163
|
import { arch, platform } from "os";
|
|
19877
|
-
import { dirname as
|
|
21164
|
+
import { dirname as dirname4, join as join2 } from "path";
|
|
19878
21165
|
var PLATFORM_PACKAGE_MAP = {
|
|
19879
21166
|
"darwin-arm64": {
|
|
19880
21167
|
libraryFile: "vec0.dylib",
|
|
@@ -19923,12 +21210,12 @@ var resolveAbsoluteSQLiteVec = () => {
|
|
|
19923
21210
|
};
|
|
19924
21211
|
}
|
|
19925
21212
|
try {
|
|
19926
|
-
const
|
|
19927
|
-
if (typeof
|
|
21213
|
+
const resolve4 = import.meta.resolve;
|
|
21214
|
+
if (typeof resolve4 !== "function") {
|
|
19928
21215
|
throw new Error("AbsoluteJS sqlite-vec package resolution requires import.meta.resolve support.");
|
|
19929
21216
|
}
|
|
19930
|
-
const packageJsonPath = new URL(
|
|
19931
|
-
const packageRoot =
|
|
21217
|
+
const packageJsonPath = new URL(resolve4(`${packageInfo.packageName}/package.json`)).pathname;
|
|
21218
|
+
const packageRoot = dirname4(packageJsonPath);
|
|
19932
21219
|
const libraryPath = join2(packageRoot, packageInfo.libraryFile);
|
|
19933
21220
|
const packageVersion = readPackageVersion(packageJsonPath);
|
|
19934
21221
|
if (!existsSync(libraryPath)) {
|
|
@@ -20629,73 +21916,73 @@ var createConversationManager = () => {
|
|
|
20629
21916
|
};
|
|
20630
21917
|
};
|
|
20631
21918
|
// src/ai/client/actions.ts
|
|
20632
|
-
var serverMessageToAction = (
|
|
20633
|
-
switch (
|
|
21919
|
+
var serverMessageToAction = (message) => {
|
|
21920
|
+
switch (message.type) {
|
|
20634
21921
|
case "chunk":
|
|
20635
21922
|
return {
|
|
20636
|
-
content:
|
|
20637
|
-
conversationId:
|
|
20638
|
-
messageId:
|
|
21923
|
+
content: message.content,
|
|
21924
|
+
conversationId: message.conversationId,
|
|
21925
|
+
messageId: message.messageId,
|
|
20639
21926
|
type: "chunk"
|
|
20640
21927
|
};
|
|
20641
21928
|
case "thinking":
|
|
20642
21929
|
return {
|
|
20643
|
-
content:
|
|
20644
|
-
conversationId:
|
|
20645
|
-
messageId:
|
|
21930
|
+
content: message.content,
|
|
21931
|
+
conversationId: message.conversationId,
|
|
21932
|
+
messageId: message.messageId,
|
|
20646
21933
|
type: "thinking"
|
|
20647
21934
|
};
|
|
20648
21935
|
case "tool_status":
|
|
20649
21936
|
return {
|
|
20650
|
-
conversationId:
|
|
20651
|
-
input:
|
|
20652
|
-
messageId:
|
|
20653
|
-
name:
|
|
20654
|
-
result:
|
|
20655
|
-
status:
|
|
21937
|
+
conversationId: message.conversationId,
|
|
21938
|
+
input: message.input,
|
|
21939
|
+
messageId: message.messageId,
|
|
21940
|
+
name: message.name,
|
|
21941
|
+
result: message.result,
|
|
21942
|
+
status: message.status,
|
|
20656
21943
|
type: "tool_status"
|
|
20657
21944
|
};
|
|
20658
21945
|
case "image":
|
|
20659
21946
|
return {
|
|
20660
|
-
conversationId:
|
|
20661
|
-
data:
|
|
20662
|
-
format:
|
|
20663
|
-
imageId:
|
|
20664
|
-
isPartial:
|
|
20665
|
-
messageId:
|
|
20666
|
-
revisedPrompt:
|
|
21947
|
+
conversationId: message.conversationId,
|
|
21948
|
+
data: message.data,
|
|
21949
|
+
format: message.format,
|
|
21950
|
+
imageId: message.imageId,
|
|
21951
|
+
isPartial: message.isPartial,
|
|
21952
|
+
messageId: message.messageId,
|
|
21953
|
+
revisedPrompt: message.revisedPrompt,
|
|
20667
21954
|
type: "image"
|
|
20668
21955
|
};
|
|
20669
21956
|
case "complete":
|
|
20670
21957
|
return {
|
|
20671
|
-
conversationId:
|
|
20672
|
-
durationMs:
|
|
20673
|
-
messageId:
|
|
20674
|
-
model:
|
|
20675
|
-
sources:
|
|
21958
|
+
conversationId: message.conversationId,
|
|
21959
|
+
durationMs: message.durationMs,
|
|
21960
|
+
messageId: message.messageId,
|
|
21961
|
+
model: message.model,
|
|
21962
|
+
sources: message.sources,
|
|
20676
21963
|
type: "complete",
|
|
20677
|
-
usage:
|
|
21964
|
+
usage: message.usage
|
|
20678
21965
|
};
|
|
20679
21966
|
case "rag_retrieving":
|
|
20680
21967
|
return {
|
|
20681
|
-
conversationId:
|
|
20682
|
-
messageId:
|
|
20683
|
-
retrievalStartedAt:
|
|
21968
|
+
conversationId: message.conversationId,
|
|
21969
|
+
messageId: message.messageId,
|
|
21970
|
+
retrievalStartedAt: message.retrievalStartedAt,
|
|
20684
21971
|
type: "rag_retrieving"
|
|
20685
21972
|
};
|
|
20686
21973
|
case "rag_retrieved":
|
|
20687
21974
|
return {
|
|
20688
|
-
conversationId:
|
|
20689
|
-
messageId:
|
|
20690
|
-
retrievalDurationMs:
|
|
20691
|
-
retrievalStartedAt:
|
|
20692
|
-
retrievedAt:
|
|
20693
|
-
sources:
|
|
20694
|
-
trace:
|
|
21975
|
+
conversationId: message.conversationId,
|
|
21976
|
+
messageId: message.messageId,
|
|
21977
|
+
retrievalDurationMs: message.retrievalDurationMs,
|
|
21978
|
+
retrievalStartedAt: message.retrievalStartedAt,
|
|
21979
|
+
retrievedAt: message.retrievedAt,
|
|
21980
|
+
sources: message.sources,
|
|
21981
|
+
trace: message.trace,
|
|
20695
21982
|
type: "rag_retrieved"
|
|
20696
21983
|
};
|
|
20697
21984
|
case "error":
|
|
20698
|
-
return { message:
|
|
21985
|
+
return { message: message.message, type: "error" };
|
|
20699
21986
|
default:
|
|
20700
21987
|
return null;
|
|
20701
21988
|
}
|
|
@@ -21154,8 +22441,8 @@ var createAIStream = (path, conversationId) => {
|
|
|
21154
22441
|
listeners.forEach((listener) => listener());
|
|
21155
22442
|
};
|
|
21156
22443
|
const unsubscribeStore = store.subscribe(syncState);
|
|
21157
|
-
const unsubscribeConnection = connection.subscribe((
|
|
21158
|
-
const action = serverMessageToAction(
|
|
22444
|
+
const unsubscribeConnection = connection.subscribe((message) => {
|
|
22445
|
+
const action = serverMessageToAction(message);
|
|
21159
22446
|
if (action) {
|
|
21160
22447
|
store.dispatch(action);
|
|
21161
22448
|
}
|
|
@@ -22514,6 +23801,8 @@ export {
|
|
|
22514
23801
|
createRAGFileRetrievalComparisonHistoryStore,
|
|
22515
23802
|
createRAGFileRetrievalBaselineStore,
|
|
22516
23803
|
createRAGFileRetrievalBaselineGatePolicyHistoryStore,
|
|
23804
|
+
createRAGFileJobStateStore,
|
|
23805
|
+
createRAGFileExtractorRegistry,
|
|
22517
23806
|
createRAGFileExtractor,
|
|
22518
23807
|
createRAGFileEvaluationHistoryStore,
|
|
22519
23808
|
createRAGFileAnswerGroundingEvaluationHistoryStore,
|
|
@@ -22524,9 +23813,11 @@ export {
|
|
|
22524
23813
|
createRAGDirectorySyncSource,
|
|
22525
23814
|
createRAGCollection,
|
|
22526
23815
|
createRAGClient,
|
|
23816
|
+
createRAGChunkingRegistry,
|
|
22527
23817
|
createRAGBunS3SyncClient,
|
|
22528
23818
|
createRAGArchiveFileExtractor,
|
|
22529
23819
|
createRAGArchiveExpander,
|
|
23820
|
+
createRAGAccessControl,
|
|
22530
23821
|
createPDFFileExtractor,
|
|
22531
23822
|
createOfficeDocumentExtractor,
|
|
22532
23823
|
createMemoryStore,
|
|
@@ -22569,5 +23860,5 @@ export {
|
|
|
22569
23860
|
aiChat
|
|
22570
23861
|
};
|
|
22571
23862
|
|
|
22572
|
-
//# debugId=
|
|
23863
|
+
//# debugId=98118EA892F30E7564756E2164756E21
|
|
22573
23864
|
//# sourceMappingURL=index.js.map
|