@absolutejs/rag 0.0.16 → 0.0.18

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/index.js CHANGED
@@ -5666,7 +5666,8 @@ var evaluateRAGCollectionCases = async ({
5666
5666
  input,
5667
5667
  defaultTopK = DEFAULT_TOP_K,
5668
5668
  rerank,
5669
- includeTrace = false
5669
+ includeTrace = false,
5670
+ onCaseSettled
5670
5671
  }) => {
5671
5672
  if (input.dryRun) {
5672
5673
  return executeDryRunRAGEvaluation(input, defaultTopK).map((caseResult, caseIndex) => ({
@@ -5702,18 +5703,20 @@ var evaluateRAGCollectionCases = async ({
5702
5703
  const sources = buildSources(searchOutcome.results);
5703
5704
  const elapsedMs = Date.now() - startedAt;
5704
5705
  const retrievedIds = normalizeExpectedIds(sources.map((source) => extractExpectedId(source, mode)));
5706
+ const caseResult = summarizeRAGEvaluationCase({
5707
+ caseIndex,
5708
+ caseInput: { ...caseInput, topK },
5709
+ elapsedMs,
5710
+ expectedIds,
5711
+ mode,
5712
+ query,
5713
+ retrievedIds,
5714
+ retrievedSources: sources,
5715
+ trace: searchOutcome.trace
5716
+ });
5717
+ onCaseSettled?.({ caseIndex, caseResult, total: input.cases.length });
5705
5718
  return {
5706
- caseResult: summarizeRAGEvaluationCase({
5707
- caseIndex,
5708
- caseInput: { ...caseInput, topK },
5709
- elapsedMs,
5710
- expectedIds,
5711
- mode,
5712
- query,
5713
- retrievedIds,
5714
- retrievedSources: sources,
5715
- trace: searchOutcome.trace
5716
- }),
5719
+ caseResult,
5717
5720
  trace: searchOutcome.trace,
5718
5721
  filter: searchInput.filter,
5719
5722
  retrieval: searchInput.retrieval,
@@ -11077,13 +11080,15 @@ var evaluateRAGCollection = async ({
11077
11080
  collection,
11078
11081
  input,
11079
11082
  defaultTopK = DEFAULT_TOP_K,
11080
- rerank
11083
+ rerank,
11084
+ onCaseSettled
11081
11085
  }) => {
11082
11086
  const evaluated = await evaluateRAGCollectionCases({
11083
11087
  collection,
11084
11088
  defaultTopK,
11085
11089
  includeTrace: false,
11086
11090
  input,
11091
+ onCaseSettled,
11087
11092
  rerank
11088
11093
  });
11089
11094
  return buildRAGEvaluationResponse(evaluated.map((entry) => entry.caseResult));
@@ -11221,6 +11226,210 @@ var summarizeRAGRetrievalComparison = (entries) => ({
11221
11226
  bestByLowestRuntimeCandidateBudgetExhaustedCases: selectComparisonEntryByLowestTraceMetric(entries, "retrievalId", "runtimeCandidateBudgetExhaustedCases"),
11222
11227
  bestByLowestRuntimeUnderfilledTopKCases: selectComparisonEntryByLowestTraceMetric(entries, "retrievalId", "runtimeUnderfilledTopKCases")
11223
11228
  });
11229
+ // src/presentation/htmxCitationFragments.ts
11230
+ var formatScore = (value) => Number.isFinite(value) ? value.toFixed(3) : "0.000";
11231
+ var buildSearchTargetId = (prefix, value) => {
11232
+ const normalized = value.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
11233
+ return `${prefix}-${normalized || "item"}`;
11234
+ };
11235
+ var buildSourceSummarySectionGroups = (summaries) => {
11236
+ const groups = new Map;
11237
+ for (const summary of summaries ?? []) {
11238
+ const label = summary.contextLabel ?? summary.label;
11239
+ const id = buildSearchTargetId("source-summary-section", label);
11240
+ const existing = groups.get(id);
11241
+ if (existing) {
11242
+ existing.summaries.push(summary);
11243
+ existing.summary = `${existing.summaries.length} evidence summar${existing.summaries.length === 1 ? "y" : "ies"}`;
11244
+ continue;
11245
+ }
11246
+ groups.set(id, {
11247
+ id,
11248
+ label,
11249
+ targetId: id,
11250
+ summary: "1 evidence summary",
11251
+ summaries: [summary]
11252
+ });
11253
+ }
11254
+ return [...groups.values()].sort((left, right) => {
11255
+ const leftScore = Math.max(...left.summaries.map((summary) => summary.bestScore));
11256
+ const rightScore = Math.max(...right.summaries.map((summary) => summary.bestScore));
11257
+ return rightScore - leftScore;
11258
+ });
11259
+ };
11260
+ var buildGroundingReferenceGroups = (references) => {
11261
+ const groups = new Map;
11262
+ for (const reference of references ?? []) {
11263
+ const label = reference.contextLabel ?? reference.label ?? reference.source ?? reference.chunkId;
11264
+ const id = buildSearchTargetId("grounding-reference-section", label);
11265
+ const existing = groups.get(id);
11266
+ if (existing) {
11267
+ existing.references.push(reference);
11268
+ existing.summary = `${existing.references.length} grounding reference${existing.references.length === 1 ? "" : "s"}`;
11269
+ continue;
11270
+ }
11271
+ groups.set(id, {
11272
+ id,
11273
+ label,
11274
+ targetId: id,
11275
+ summary: "1 grounding reference",
11276
+ references: [reference]
11277
+ });
11278
+ }
11279
+ return [...groups.values()].sort((left, right) => {
11280
+ const leftScore = Math.max(...left.references.map((reference) => reference.score));
11281
+ const rightScore = Math.max(...right.references.map((reference) => reference.score));
11282
+ return rightScore - leftScore;
11283
+ });
11284
+ };
11285
+ var buildCitationGroups = (citations) => {
11286
+ const groups = new Map;
11287
+ for (const citation of citations ?? []) {
11288
+ const label = citation.contextLabel ?? citation.label ?? citation.source ?? citation.chunkId;
11289
+ const id = buildSearchTargetId("citation-section", label);
11290
+ const existing = groups.get(id);
11291
+ if (existing) {
11292
+ existing.citations.push(citation);
11293
+ existing.summary = `${existing.citations.length} citation${existing.citations.length === 1 ? "" : "s"}`;
11294
+ continue;
11295
+ }
11296
+ groups.set(id, {
11297
+ id,
11298
+ label,
11299
+ targetId: id,
11300
+ summary: "1 citation",
11301
+ citations: [citation]
11302
+ });
11303
+ }
11304
+ return [...groups.values()].sort((left, right) => {
11305
+ const leftScore = Math.max(...left.citations.map((citation) => citation.score));
11306
+ const rightScore = Math.max(...right.citations.map((citation) => citation.score));
11307
+ return rightScore - leftScore;
11308
+ });
11309
+ };
11310
+ var formatCitationLabel = (citation) => [citation.label, citation.contextLabel, citation.locatorLabel].filter(Boolean).join(" \xB7 ");
11311
+ var formatCitationSummary = (citation) => citation.source ?? citation.title ?? citation.chunkId;
11312
+ var formatCitationExcerpt = (citation) => citation.excerpt || citation.text;
11313
+ var formatEvidenceDetailLine = (label, value) => value && value.length > 0 ? `${label}: ${value}` : "";
11314
+ var formatEvidenceContextLine = (contextLabel, locatorLabel) => {
11315
+ const value = [locatorLabel, contextLabel].filter((entry) => Boolean(entry && entry.length > 0)).join(" \xB7 ");
11316
+ return value.length > 0 ? `location: ${value}` : "";
11317
+ };
11318
+ var formatSourceSummaryDetails = (summary) => [
11319
+ `best score: ${formatScore(summary.bestScore)}`,
11320
+ `coverage: ${summary.count} chunk(s) \xB7 citations ${summary.citationNumbers.map((value) => `[${value}]`).join(" ") || "none"}`,
11321
+ formatEvidenceContextLine(summary.contextLabel, summary.locatorLabel),
11322
+ formatEvidenceDetailLine("provenance", summary.provenanceLabel)
11323
+ ].filter((value) => value.length > 0);
11324
+ var formatCitationDetails = (citation) => [
11325
+ formatEvidenceDetailLine("evidence", citation.source ?? citation.title ?? citation.chunkId),
11326
+ formatEvidenceContextLine(citation.contextLabel, citation.locatorLabel),
11327
+ formatEvidenceDetailLine("provenance", citation.provenanceLabel),
11328
+ `score: ${formatScore(citation.score)}`
11329
+ ].filter((value) => value.length > 0);
11330
+ var formatSectionDiagnosticPercent = (value) => typeof value === "number" ? `${Math.round(value * 100)}%` : null;
11331
+ var formatSectionDiagnosticReason = (reason) => reason.replaceAll("_", " ");
11332
+ var formatSectionDiagnosticStage = (stage) => stage.replaceAll("_", " ");
11333
+ var formatSectionDiagnosticWeightReason = (reason) => ({
11334
+ final_stage_concentration: "final stage concentrated on this section",
11335
+ final_stage_dominant_within_parent: "final stage stayed ahead inside its parent",
11336
+ rerank_preserved_lead: "rerank kept this section in front",
11337
+ stage_runner_up_pressure: "runner-up stayed close in this stage",
11338
+ stage_expanded: "this section expanded in this stage",
11339
+ stage_held: "this section held steady in this stage",
11340
+ stage_narrowed: "this section narrowed in this stage"
11341
+ })[reason] ?? reason.replaceAll("_", " ");
11342
+ var formatSectionQueryAttributionReason = (reason) => ({
11343
+ base_query_only: "came only from the base query",
11344
+ transformed_query_only: "came only from the transformed query",
11345
+ variant_only: "came only from query variants",
11346
+ transform_introduced: "the transformed query introduced this section",
11347
+ variant_supported: "query variants reinforced this section",
11348
+ mixed_query_sources: "multiple query forms contributed"
11349
+ })[reason] ?? reason.replaceAll("_", " ");
11350
+ var formatSectionDiagnosticChannels = (diagnostic) => `Channels \xB7 hybrid ${diagnostic.hybridHits} \xB7 vector ${diagnostic.vectorHits} \xB7 lexical ${diagnostic.lexicalHits}`;
11351
+ var formatSectionDiagnosticAttributionFocus = (diagnostic) => {
11352
+ const mode = diagnostic.queryAttribution?.mode ?? "mixed";
11353
+ const label = mode === "primary" ? "Attribution \xB7 base-query-only" : mode === "transformed" ? "Attribution \xB7 transformed-only" : mode === "variant" ? "Attribution \xB7 variant-only" : "Attribution \xB7 mixed";
11354
+ const parts = [label];
11355
+ if ((diagnostic.queryAttribution?.primaryHits ?? 0) > 0)
11356
+ parts.push(`base ${diagnostic.queryAttribution?.primaryHits}`);
11357
+ if ((diagnostic.queryAttribution?.transformedHits ?? 0) > 0)
11358
+ parts.push(`transformed ${diagnostic.queryAttribution?.transformedHits}`);
11359
+ if ((diagnostic.queryAttribution?.variantHits ?? 0) > 0)
11360
+ parts.push(`variant ${diagnostic.queryAttribution?.variantHits}`);
11361
+ return parts.join(" \xB7 ");
11362
+ };
11363
+ var formatSectionDiagnosticPipeline = (diagnostic) => {
11364
+ const requestedMode = diagnostic.requestedMode ?? diagnostic.retrievalMode ?? "n/a";
11365
+ const selectedMode = diagnostic.retrievalMode ?? "n/a";
11366
+ const routeLabel = diagnostic.routingLabel ?? "default route";
11367
+ const transformLabel = diagnostic.queryTransformLabel ?? "no transform";
11368
+ return `Mode ${selectedMode} \xB7 requested ${requestedMode} \xB7 route ${routeLabel} \xB7 transform ${transformLabel} \xB7 rerank ${diagnostic.rerankApplied ? "on" : "off"} \xB7 source balance ${diagnostic.sourceBalanceApplied ? "on" : "off"} \xB7 threshold ${diagnostic.scoreThresholdApplied ? "on" : "off"} \xB7 query ${diagnostic.queryAttribution?.mode ?? "n/a"}`;
11369
+ };
11370
+ var formatSectionDiagnosticStageFlow = (diagnostic) => diagnostic.stageCounts.length > 0 ? `Stage flow \xB7 ${diagnostic.stageCounts.map((entry) => `${formatSectionDiagnosticStage(entry.stage)} ${entry.count}`).join(" \u2192 ")}` : null;
11371
+ var formatSectionDiagnosticStageBounds = (diagnostic) => {
11372
+ const parts = [];
11373
+ if (diagnostic.firstSeenStage)
11374
+ parts.push(`first seen ${formatSectionDiagnosticStage(diagnostic.firstSeenStage)}`);
11375
+ if (diagnostic.lastSeenStage)
11376
+ parts.push(`last seen ${formatSectionDiagnosticStage(diagnostic.lastSeenStage)}`);
11377
+ if (diagnostic.peakStage)
11378
+ parts.push(`peak ${formatSectionDiagnosticStage(diagnostic.peakStage)} ${diagnostic.peakCount}`);
11379
+ const finalRetention = formatSectionDiagnosticPercent(diagnostic.finalRetentionRate);
11380
+ if (finalRetention)
11381
+ parts.push(`final retention ${finalRetention}`);
11382
+ if (typeof diagnostic.dropFromPeak === "number")
11383
+ parts.push(`drop from peak ${diagnostic.dropFromPeak}`);
11384
+ return parts.length > 0 ? parts.join(" \xB7 ") : null;
11385
+ };
11386
+ var formatSectionDiagnosticStageWeightRows = (diagnostic) => (diagnostic.stageWeights ?? []).filter((entry) => entry.reasons.length > 0 || entry.stage === "rerank" || entry.stage === "finalize").map((entry) => {
11387
+ const parts = [
11388
+ `${formatSectionDiagnosticStage(entry.stage)} ${(entry.stageShare * 100).toFixed(0)}% of stage`,
11389
+ typeof entry.stageScoreShare === "number" ? `${(entry.stageScoreShare * 100).toFixed(0)}% of stage score` : null,
11390
+ typeof entry.retentionRate === "number" && entry.previousStage && entry.retentionRate !== 1 ? `${(entry.retentionRate * 100).toFixed(0)}% retained from ${formatSectionDiagnosticStage(entry.previousStage)}` : null,
11391
+ typeof entry.countDelta === "number" && entry.countDelta !== 0 ? `delta ${entry.countDelta >= 0 ? "+" : ""}${entry.countDelta}` : null,
11392
+ typeof entry.parentStageShare === "number" && entry.strongestSiblingLabel ? `${(entry.parentStageShare * 100).toFixed(0)}% of parent stage` : null,
11393
+ typeof entry.parentStageScoreShare === "number" && entry.strongestSiblingLabel ? `${(entry.parentStageScoreShare * 100).toFixed(0)}% of parent stage score` : null,
11394
+ typeof entry.stageShareGap === "number" ? `gap ${(entry.stageShareGap * 100).toFixed(0)}%` : null,
11395
+ typeof entry.stageScoreShareGap === "number" ? `score gap ${(entry.stageScoreShareGap * 100).toFixed(0)}%` : null,
11396
+ entry.strongestSiblingLabel ? `runner-up ${entry.strongestSiblingLabel}` : null
11397
+ ].filter((value) => Boolean(value));
11398
+ return parts.join(" \xB7 ");
11399
+ });
11400
+ var formatSectionDiagnosticStageWeightReasons = (diagnostic) => (diagnostic.stageWeights ?? []).flatMap((entry) => entry.reasons.map((reason) => `${formatSectionDiagnosticStage(entry.stage)} \xB7 ${formatSectionDiagnosticWeightReason(reason)}`));
11401
+ var formatSectionDiagnosticQueryAttributionReasons = (diagnostic) => (diagnostic.queryAttribution?.reasons ?? []).map((reason) => formatSectionQueryAttributionReason(reason));
11402
+ var formatSectionDiagnosticCompetition = (diagnostic) => {
11403
+ const parts = [];
11404
+ const parentShare = formatSectionDiagnosticPercent(diagnostic.parentShare);
11405
+ const parentShareGap = formatSectionDiagnosticPercent(diagnostic.parentShareGap);
11406
+ if (!diagnostic.strongestSiblingLabel)
11407
+ return "";
11408
+ if (parentShare)
11409
+ parts.push(`parent share ${parentShare}`);
11410
+ if (parentShareGap)
11411
+ parts.push(`gap ${parentShareGap}`);
11412
+ parts.push(`runner-up ${diagnostic.strongestSiblingLabel}`);
11413
+ return parts.join(" \xB7 ");
11414
+ };
11415
+ var formatSectionDiagnosticTopEntry = (diagnostic) => {
11416
+ const parts = [];
11417
+ if (diagnostic.topSource)
11418
+ parts.push(`top source ${diagnostic.topSource}`);
11419
+ if (diagnostic.topChunkId)
11420
+ parts.push(`lead chunk ${diagnostic.topChunkId}`);
11421
+ parts.push(`${diagnostic.sourceCount} source${diagnostic.sourceCount === 1 ? "" : "s"}`);
11422
+ parts.push(`primary ${diagnostic.queryAttribution?.primaryHits ?? 0} \xB7 transformed ${diagnostic.queryAttribution?.transformedHits ?? 0} \xB7 variant ${diagnostic.queryAttribution?.variantHits ?? 0}`);
11423
+ return parts.join(" \xB7 ");
11424
+ };
11425
+ var formatSectionDiagnosticReasons = (diagnostic) => [
11426
+ ...diagnostic.reasons.map((reason) => formatSectionDiagnosticReason(reason)),
11427
+ ...formatSectionDiagnosticQueryAttributionReasons(diagnostic),
11428
+ ...diagnostic.routingReason ? [`routing \xB7 ${diagnostic.routingReason}`] : [],
11429
+ ...diagnostic.queryTransformReason ? [`transform \xB7 ${diagnostic.queryTransformReason}`] : []
11430
+ ];
11431
+ var formatSectionDiagnosticDistributionRows = (diagnostic) => diagnostic.parentDistribution.map((entry) => `${entry.isActive ? "Active" : "Peer"} \xB7 ${entry.label} \xB7 ${entry.count} hit${entry.count === 1 ? "" : "s"} \xB7 ${formatSectionDiagnosticPercent(entry.parentShare) ?? "0%"}`);
11432
+
11224
11433
  // src/presentation/htmxRenderers.ts
11225
11434
  var STREAM_STAGES = [
11226
11435
  "submitting",
@@ -11361,15 +11570,87 @@ var makeAdminActionCards = (prefix) => (actions) => {
11361
11570
  </article>`;
11362
11571
  }).join("")}</div>`;
11363
11572
  };
11573
+ var makeCitations = (prefix) => (sources) => {
11574
+ const citations = buildRAGCitations(sources);
11575
+ if (citations.length === 0) {
11576
+ return "";
11577
+ }
11578
+ return [
11579
+ `<div class="${prefix}-results">`,
11580
+ "<h4>Citation Trail</h4>",
11581
+ `<p class="${prefix}-metadata">Each citation maps a concrete retrieved chunk to a stable reference number you can carry into the answer UI.</p>`,
11582
+ `<div class="${prefix}-result-grid">`,
11583
+ buildCitationGroups(citations).map((group) => `
11584
+ <article class="${prefix}-result-item" id="${escapeHtml(group.targetId)}">
11585
+ <h3>${escapeHtml(group.label)}</h3>
11586
+ <p class="${prefix}-result-source">${escapeHtml(group.summary)}</p>
11587
+ <div class="${prefix}-result-grid">
11588
+ ${group.citations.map((citation, index) => `
11589
+ <article class="${prefix}-result-item ${prefix}-citation-card">
11590
+ <p class="${prefix}-citation-badge">[${index + 1}] ${escapeHtml(formatCitationLabel(citation))}</p>
11591
+ <p class="${prefix}-result-score">${escapeHtml(formatCitationSummary(citation))}</p>
11592
+ ${formatCitationDetails(citation).map((line) => `<p class="${prefix}-metadata">${escapeHtml(line)}</p>`).join("")}
11593
+ <p class="${prefix}-result-text">${escapeHtml(formatCitationExcerpt(citation))}</p>
11594
+ </article>`).join("")}
11595
+ </div>
11596
+ </article>`).join(""),
11597
+ "</div>",
11598
+ "</div>"
11599
+ ].join("");
11600
+ };
11601
+ var makeSourceSummaries = (prefix) => (sources) => {
11602
+ const summaries = buildRAGSourceSummaries(sources);
11603
+ if (summaries.length === 0) {
11604
+ return `<p class="${prefix}-metadata">Retrieved source groups: 0</p>`;
11605
+ }
11606
+ const groups = buildSourceSummarySectionGroups(summaries);
11607
+ return [
11608
+ `<p class="${prefix}-metadata">Retrieved source groups: ${summaries.length}</p>`,
11609
+ `<div class="${prefix}-result-grid">`,
11610
+ groups.map((group) => `
11611
+ <article class="${prefix}-result-item" id="${escapeHtml(group.targetId)}">
11612
+ <h3>${escapeHtml(group.label)}</h3>
11613
+ <p class="${prefix}-result-source">${escapeHtml(group.summary)}</p>
11614
+ <div class="${prefix}-result-grid">
11615
+ ${group.summaries.map((summary) => `
11616
+ <article class="${prefix}-result-item">
11617
+ <h4>${escapeHtml(summary.label)}</h4>
11618
+ ${formatSourceSummaryDetails(summary).map((line) => `<p class="${prefix}-metadata">${escapeHtml(line)}</p>`).join("")}
11619
+ <p class="${prefix}-result-text">${escapeHtml(summary.excerpt)}</p>
11620
+ </article>`).join("")}
11621
+ </div>
11622
+ </article>`).join(""),
11623
+ "</div>"
11624
+ ].join("");
11625
+ };
11626
+ var makeSectionDiagnosticCard = (prefix) => (diagnostic) => [
11627
+ `<article class="${prefix}-result-item">`,
11628
+ `<h4>${escapeHtml(diagnostic.label)}</h4>`,
11629
+ `<p class="${prefix}-result-source">${escapeHtml(diagnostic.summary)}</p>`,
11630
+ `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticChannels(diagnostic))}</p>`,
11631
+ `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticAttributionFocus(diagnostic))}</p>`,
11632
+ `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticPipeline(diagnostic))}</p>`,
11633
+ `${formatSectionDiagnosticStageFlow(diagnostic) ? `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticStageFlow(diagnostic) ?? "")}</p>` : ""}`,
11634
+ `${formatSectionDiagnosticStageBounds(diagnostic) ? `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticStageBounds(diagnostic) ?? "")}</p>` : ""}`,
11635
+ `${formatSectionDiagnosticStageWeightRows(diagnostic).map((line) => `<p class="${prefix}-metadata">${escapeHtml(line)}</p>`).join("")}`,
11636
+ `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticTopEntry(diagnostic))}</p>`,
11637
+ `${formatSectionDiagnosticCompetition(diagnostic) ? `<p class="${prefix}-metadata">${escapeHtml(formatSectionDiagnosticCompetition(diagnostic) ?? "")}</p>` : ""}`,
11638
+ `${[...formatSectionDiagnosticReasons(diagnostic), ...formatSectionDiagnosticStageWeightReasons(diagnostic)].length > 0 ? `<div class="${prefix}-badge-row">${[...formatSectionDiagnosticReasons(diagnostic), ...formatSectionDiagnosticStageWeightReasons(diagnostic)].map((reason) => `<span class="${prefix}-state-chip">${escapeHtml(reason)}</span>`).join("")}</div>` : ""}`,
11639
+ `${formatSectionDiagnosticDistributionRows(diagnostic).map((line) => `<p class="${prefix}-metadata">${escapeHtml(line)}</p>`).join("")}`,
11640
+ `</article>`
11641
+ ].join("");
11364
11642
  var resolveRAGHTMXRenderers = (custom = {}) => {
11365
11643
  const classPrefix = custom.classPrefix ?? "rag";
11366
11644
  return {
11367
11645
  adminActionCards: custom.adminActionCards ?? makeAdminActionCards(classPrefix),
11368
11646
  adminJobCards: custom.adminJobCards ?? makeAdminJobCards(classPrefix),
11369
11647
  capabilities: custom.capabilities ?? makeCapabilities(classPrefix),
11648
+ citations: custom.citations ?? makeCitations(classPrefix),
11370
11649
  classPrefix,
11371
11650
  detailList: custom.detailList ?? makeDetailList(classPrefix),
11372
11651
  nativeSource: custom.nativeSource ?? defaultNativeSource,
11652
+ sectionDiagnosticCard: custom.sectionDiagnosticCard ?? makeSectionDiagnosticCard(classPrefix),
11653
+ sourceSummaries: custom.sourceSummaries ?? makeSourceSummaries(classPrefix),
11373
11654
  stageRow: custom.stageRow ?? makeStageRow(classPrefix),
11374
11655
  statusMessage: custom.statusMessage ?? defaultStatusMessage,
11375
11656
  statusSummary: custom.statusSummary ?? defaultStatusSummary,
@@ -30572,6 +30853,85 @@ var ragChat = (config) => {
30572
30853
  }), HTTP_STATUS_OK);
30573
30854
  }
30574
30855
  return result;
30856
+ }).post(`${path}/evaluate/stream`, async function* ({ body, request }) {
30857
+ const input = toRAGEvaluationInput(body);
30858
+ if (!input) {
30859
+ yield {
30860
+ data: JSON.stringify({
30861
+ error: "Expected payload shape: { cases: [{ id, query, expectedChunkIds|expectedSources|expectedDocumentIds }] }"
30862
+ }),
30863
+ event: "error"
30864
+ };
30865
+ return;
30866
+ }
30867
+ const accessScope = await loadAccessScope(request);
30868
+ for (const evaluationCase of input.cases) {
30869
+ if (evaluationCase.corpusKey && !matchesAccessScope(accessScope, {
30870
+ corpusKey: evaluationCase.corpusKey
30871
+ }) || (evaluationCase.expectedDocumentIds ?? []).some((documentId) => !matchesAccessScope(accessScope, { documentId })) || (evaluationCase.expectedSources ?? []).some((source) => !matchesAccessScope(accessScope, { source }))) {
30872
+ yield {
30873
+ data: JSON.stringify({
30874
+ error: "Evaluation case is outside the allowed RAG access scope"
30875
+ }),
30876
+ event: "error"
30877
+ };
30878
+ return;
30879
+ }
30880
+ }
30881
+ const collection = resolveCollection();
30882
+ if (!collection) {
30883
+ yield {
30884
+ data: JSON.stringify({ error: "RAG collection is not configured" }),
30885
+ event: "error"
30886
+ };
30887
+ return;
30888
+ }
30889
+ yield {
30890
+ data: JSON.stringify({ total: input.cases.length }),
30891
+ event: "start"
30892
+ };
30893
+ const pending = [];
30894
+ let resolveNext = null;
30895
+ let finished = false;
30896
+ const wake = () => {
30897
+ const resolve2 = resolveNext;
30898
+ resolveNext = null;
30899
+ resolve2?.();
30900
+ };
30901
+ const resultPromise = evaluateRAGCollection({
30902
+ collection,
30903
+ defaultTopK: topK,
30904
+ input,
30905
+ onCaseSettled: (event) => {
30906
+ pending.push(event);
30907
+ wake();
30908
+ }
30909
+ }).finally(() => {
30910
+ finished = true;
30911
+ wake();
30912
+ });
30913
+ while (true) {
30914
+ while (pending.length > 0) {
30915
+ yield { data: JSON.stringify(pending.shift()), event: "case" };
30916
+ }
30917
+ if (finished) {
30918
+ break;
30919
+ }
30920
+ await new Promise((resolve2) => {
30921
+ resolveNext = resolve2;
30922
+ });
30923
+ }
30924
+ try {
30925
+ const result = await resultPromise;
30926
+ yield { data: JSON.stringify(result), event: "result" };
30927
+ } catch (caught) {
30928
+ yield {
30929
+ data: JSON.stringify({
30930
+ error: caught instanceof Error ? caught.message : String(caught)
30931
+ }),
30932
+ event: "error"
30933
+ };
30934
+ }
30575
30935
  }).get(`${path}/status`, async ({ request }) => {
30576
30936
  const result = await handleStatus(request);
30577
30937
  if (config.htmx && isHTMXRequest(request)) {
@@ -37804,5 +38164,5 @@ export {
37804
38164
  addRAGEvaluationSuiteCase
37805
38165
  };
37806
38166
 
37807
- //# debugId=81C188D9E871FD2564756E2164756E21
38167
+ //# debugId=27BA74206F3A122164756E2164756E21
37808
38168
  //# sourceMappingURL=index.js.map