@retrivora-ai/rag-engine 1.7.0 → 1.7.2
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/{chunk-OHXRQTQH.mjs → chunk-M32ZXLTT.mjs} +399 -20
- package/dist/handlers/index.d.mts +1 -1
- package/dist/handlers/index.d.ts +1 -1
- package/dist/handlers/index.js +402 -22
- package/dist/handlers/index.mjs +5 -3
- package/dist/{index-kUXnRvuI.d.mts → index-BejNscWZ.d.mts} +4 -2
- package/dist/{index-B67KQ9NN.d.ts → index-CbkMJvu5.d.ts} +4 -2
- package/dist/index.js +29 -32
- package/dist/index.mjs +29 -32
- package/dist/server.d.mts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +400 -20
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/components/MessageBubble.tsx +43 -55
- package/src/components/VisualizationRenderer.tsx +341 -0
- package/src/core/Pipeline.ts +39 -19
- package/src/handlers/index.ts +21 -3
- package/src/hooks/useUITransform.ts +54 -0
- package/src/utils/UITransformer.ts +535 -0
package/dist/handlers/index.js
CHANGED
|
@@ -1617,7 +1617,8 @@ __export(handlers_exports, {
|
|
|
1617
1617
|
sseErrorFrame: () => sseErrorFrame,
|
|
1618
1618
|
sseFrame: () => sseFrame,
|
|
1619
1619
|
sseMetaFrame: () => sseMetaFrame,
|
|
1620
|
-
sseTextFrame: () => sseTextFrame
|
|
1620
|
+
sseTextFrame: () => sseTextFrame,
|
|
1621
|
+
sseUIFrame: () => sseUIFrame
|
|
1621
1622
|
});
|
|
1622
1623
|
module.exports = __toCommonJS(handlers_exports);
|
|
1623
1624
|
var import_server = require("next/server");
|
|
@@ -3822,18 +3823,17 @@ var Pipeline = class {
|
|
|
3822
3823
|
async initialize() {
|
|
3823
3824
|
var _a, _b;
|
|
3824
3825
|
if (this.initialised) return;
|
|
3825
|
-
const CHART_MARKER = "<!--
|
|
3826
|
+
const CHART_MARKER = "<!-- UI_PROTOCOL_V6 -->";
|
|
3826
3827
|
const chartInstruction = `
|
|
3827
3828
|
|
|
3828
3829
|
${CHART_MARKER}
|
|
3829
|
-
### UNIVERSAL UI PROTOCOL
|
|
3830
|
-
|
|
3831
|
-
NEVER output naked JSON. If you provide a visualization, do not also provide a markdown table of the same data unless explicitly asked.
|
|
3830
|
+
### UNIVERSAL UI PROTOCOL
|
|
3831
|
+
When the user asks for a visual representation, comparison, distribution, breakdown, table, list, catalog, products, carousel, stock view, or category summary, you MUST include exactly one \`\`\`ui\`\`\` block.
|
|
3832
3832
|
|
|
3833
3833
|
1. VIEW SELECTION
|
|
3834
|
-
- Use "carousel" for browsing products, items, or
|
|
3835
|
-
- Use "chart" ONLY for numerical aggregations
|
|
3836
|
-
- Use "table" for technical
|
|
3834
|
+
- Use "carousel" for browsing specific products, items, or a catalog. This is the DEFAULT for "show me", "what are", or "find me" requests for a specific category (e.g. "beauty").
|
|
3835
|
+
- Use "chart" ONLY for numerical aggregations: distributions, percentages, counts, comparisons over time, or trends (e.g. "how many beauty products?").
|
|
3836
|
+
- Use "table" for detailed technical specifications, row-heavy comparisons, or when the user explicitly asks for a list/table format.
|
|
3837
3837
|
|
|
3838
3838
|
2. REQUIRED JSON SHAPE
|
|
3839
3839
|
{
|
|
@@ -3841,31 +3841,52 @@ NEVER output naked JSON. If you provide a visualization, do not also provide a m
|
|
|
3841
3841
|
"title": "Short heading",
|
|
3842
3842
|
"description": "One sentence describing the view",
|
|
3843
3843
|
"chartType": "pie" | "bar" | "line", // Required if view is "chart"
|
|
3844
|
-
"
|
|
3844
|
+
"xAxisKey": "label",
|
|
3845
|
+
"dataKeys": ["value"],
|
|
3846
|
+
"columns": ["dynamicFieldKey1", "dynamicFieldKey2"],
|
|
3847
|
+
"insights": ["Short takeaway 1", "Short takeaway 2"],
|
|
3848
|
+
"data": []
|
|
3845
3849
|
}
|
|
3846
3850
|
|
|
3847
3851
|
3. DATA RULES
|
|
3848
|
-
- Build the UI payload from retrieved context
|
|
3849
|
-
- For CAROUSEL: "data"
|
|
3850
|
-
-
|
|
3852
|
+
- Build the UI payload from retrieved context only. Do not invent products or values.
|
|
3853
|
+
- For CAROUSEL: "data" must be a list of product objects (id, name, brand, price, image, link).
|
|
3854
|
+
- For CHART: "data" must be aggregated counts or sums. Never put raw product lists in a chart view.
|
|
3855
|
+
- If the user asks for "products in beauty", do NOT return a pie chart of categories; return a carousel of the beauty products themselves.
|
|
3851
3856
|
|
|
3852
3857
|
4. FORMAT RULES
|
|
3853
|
-
-
|
|
3854
|
-
-
|
|
3858
|
+
- Return valid JSON inside the \`\`\`ui\`\`\` block.
|
|
3859
|
+
- Put natural language explanation before or after the block, not inside.
|
|
3855
3860
|
|
|
3856
|
-
5.
|
|
3857
|
-
User: "
|
|
3858
|
-
Assistant:
|
|
3861
|
+
5. EXAMPLES
|
|
3862
|
+
User: "show me beauty products"
|
|
3863
|
+
Assistant:
|
|
3859
3864
|
\`\`\`ui
|
|
3860
3865
|
{
|
|
3861
3866
|
"view": "carousel",
|
|
3862
3867
|
"title": "Beauty Products",
|
|
3863
|
-
"description": "
|
|
3868
|
+
"description": "Browse our latest skincare and makeup collection.",
|
|
3864
3869
|
"data": [
|
|
3865
|
-
{ "id": "1", "name": "Mascara", "brand": "Essence", "price": "$9.99", "image": "
|
|
3870
|
+
{ "id": "1", "name": "Mascara", "brand": "Essence", "price": "$9.99", "image": "...", "link": "..." },
|
|
3871
|
+
{ "id": "2", "name": "Lipstick", "brand": "Chic", "price": "$12.99", "image": "...", "link": "..." }
|
|
3866
3872
|
]
|
|
3867
3873
|
}
|
|
3868
3874
|
\`\`\`
|
|
3875
|
+
|
|
3876
|
+
User: "breakdown of products by category"
|
|
3877
|
+
Assistant:
|
|
3878
|
+
\`\`\`ui
|
|
3879
|
+
{
|
|
3880
|
+
"view": "chart",
|
|
3881
|
+
"title": "Category Breakdown",
|
|
3882
|
+
"chartType": "pie",
|
|
3883
|
+
"xAxisKey": "label",
|
|
3884
|
+
"dataKeys": ["value"],
|
|
3885
|
+
"data": [
|
|
3886
|
+
{ "label": "Beauty", "value": 15 },
|
|
3887
|
+
{ "label": "Fragrances", "value": 8 }
|
|
3888
|
+
]
|
|
3889
|
+
}
|
|
3869
3890
|
\`\`\``;
|
|
3870
3891
|
if (!((_a = this.config.llm.systemPrompt) == null ? void 0 : _a.includes(CHART_MARKER))) {
|
|
3871
3892
|
this.config.llm.systemPrompt = (this.config.llm.systemPrompt || "") + chartInstruction;
|
|
@@ -4074,8 +4095,7 @@ Assistant: "I found several beauty products in our catalog:"
|
|
|
4074
4095
|
sources = sources.slice(0, topK);
|
|
4075
4096
|
}
|
|
4076
4097
|
let context = sources.length ? sources.map((m, i) => `[Source ${i + 1}]
|
|
4077
|
-
|
|
4078
|
-
Metadata: ${JSON.stringify(m.metadata)}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
4098
|
+
${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
4079
4099
|
if (graphData && graphData.nodes.length > 0) {
|
|
4080
4100
|
const graphContext = graphData.nodes.map(
|
|
4081
4101
|
(n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
|
|
@@ -4427,6 +4447,351 @@ var DocumentParser = class {
|
|
|
4427
4447
|
}
|
|
4428
4448
|
};
|
|
4429
4449
|
|
|
4450
|
+
// src/utils/UITransformer.ts
|
|
4451
|
+
var UITransformer = class {
|
|
4452
|
+
/**
|
|
4453
|
+
* Main transformation method
|
|
4454
|
+
* Analyzes user query and retrieved data to determine the best visualization format
|
|
4455
|
+
*
|
|
4456
|
+
* @param userQuery - The original user question/query
|
|
4457
|
+
* @param retrievedData - Vector database retrieval results
|
|
4458
|
+
* @returns Structured JSON response for UI rendering
|
|
4459
|
+
*/
|
|
4460
|
+
static transform(userQuery, retrievedData) {
|
|
4461
|
+
if (!retrievedData || retrievedData.length === 0) {
|
|
4462
|
+
return this.createTextResponse("No data available", "No relevant data found for your query.");
|
|
4463
|
+
}
|
|
4464
|
+
const analysis = this.analyzeData(userQuery, retrievedData);
|
|
4465
|
+
switch (analysis.suggestedType) {
|
|
4466
|
+
case "product_carousel":
|
|
4467
|
+
return this.transformToProductCarousel(retrievedData);
|
|
4468
|
+
case "pie_chart":
|
|
4469
|
+
return this.transformToPieChart(retrievedData);
|
|
4470
|
+
case "bar_chart":
|
|
4471
|
+
return this.transformToBarChart(retrievedData);
|
|
4472
|
+
case "line_chart":
|
|
4473
|
+
return this.transformToLineChart(retrievedData);
|
|
4474
|
+
case "table":
|
|
4475
|
+
return this.transformToTable(retrievedData);
|
|
4476
|
+
default:
|
|
4477
|
+
return this.transformToText(retrievedData);
|
|
4478
|
+
}
|
|
4479
|
+
}
|
|
4480
|
+
/**
|
|
4481
|
+
* Analyzes the data and query to suggest the best visualization type
|
|
4482
|
+
*/
|
|
4483
|
+
static analyzeData(query, data) {
|
|
4484
|
+
const queryLower = query.toLowerCase();
|
|
4485
|
+
const hasProducts = data.some(
|
|
4486
|
+
(item) => this.isProductData(item)
|
|
4487
|
+
);
|
|
4488
|
+
const hasTimeSeries = data.some(
|
|
4489
|
+
(item) => this.isTimeSeriesData(item)
|
|
4490
|
+
);
|
|
4491
|
+
const hasCategories = this.detectCategories(data).length > 0;
|
|
4492
|
+
const isDistributionQuery = queryLower.includes("distribution") || queryLower.includes("breakdown") || queryLower.includes("percentage") || queryLower.includes("proportion");
|
|
4493
|
+
const isComparisonQuery = queryLower.includes("compare") || queryLower.includes("vs") || queryLower.includes("difference");
|
|
4494
|
+
const isTrendQuery = queryLower.includes("trend") || queryLower.includes("over time") || queryLower.includes("growth") || queryLower.includes("decline");
|
|
4495
|
+
if (hasProducts && !hasTimeSeries && !isDistributionQuery) {
|
|
4496
|
+
return { suggestedType: "product_carousel", confidence: 0.95, hasProducts, hasTimeSeries, hasCategories };
|
|
4497
|
+
}
|
|
4498
|
+
if (isTrendQuery && hasTimeSeries) {
|
|
4499
|
+
return { suggestedType: "line_chart", confidence: 0.9, hasProducts, hasTimeSeries, hasCategories };
|
|
4500
|
+
}
|
|
4501
|
+
if (isDistributionQuery && hasCategories) {
|
|
4502
|
+
return { suggestedType: "pie_chart", confidence: 0.85, hasProducts, hasTimeSeries, hasCategories };
|
|
4503
|
+
}
|
|
4504
|
+
if (isComparisonQuery && hasCategories && data.length > 2) {
|
|
4505
|
+
return { suggestedType: "bar_chart", confidence: 0.8, hasProducts, hasTimeSeries, hasCategories };
|
|
4506
|
+
}
|
|
4507
|
+
if (data.length > 5 && this.hasMultipleFields(data)) {
|
|
4508
|
+
return { suggestedType: "table", confidence: 0.75, hasProducts, hasTimeSeries, hasCategories };
|
|
4509
|
+
}
|
|
4510
|
+
return { suggestedType: "text", confidence: 0.5, hasProducts, hasTimeSeries, hasCategories };
|
|
4511
|
+
}
|
|
4512
|
+
/**
|
|
4513
|
+
* Transform data to product carousel format
|
|
4514
|
+
*/
|
|
4515
|
+
static transformToProductCarousel(data) {
|
|
4516
|
+
const products = data.filter((item) => this.isProductData(item)).map((item) => this.extractProductInfo(item)).filter((p) => p !== null);
|
|
4517
|
+
return {
|
|
4518
|
+
type: "product_carousel",
|
|
4519
|
+
title: "Recommended Products",
|
|
4520
|
+
description: `Found ${products.length} relevant products`,
|
|
4521
|
+
data: products
|
|
4522
|
+
};
|
|
4523
|
+
}
|
|
4524
|
+
/**
|
|
4525
|
+
* Transform data to pie chart format
|
|
4526
|
+
*/
|
|
4527
|
+
static transformToPieChart(data) {
|
|
4528
|
+
const categories = this.detectCategories(data);
|
|
4529
|
+
const categoryData = this.aggregateByCategory(data, categories);
|
|
4530
|
+
const pieData = Object.entries(categoryData).map(([label, count]) => ({
|
|
4531
|
+
label,
|
|
4532
|
+
value: count,
|
|
4533
|
+
inStock: this.checkStockStatus(label, data)
|
|
4534
|
+
}));
|
|
4535
|
+
return {
|
|
4536
|
+
type: "pie_chart",
|
|
4537
|
+
title: "Distribution by Category",
|
|
4538
|
+
description: `Showing breakdown across ${categories.length} categories`,
|
|
4539
|
+
data: pieData
|
|
4540
|
+
};
|
|
4541
|
+
}
|
|
4542
|
+
/**
|
|
4543
|
+
* Transform data to bar chart format
|
|
4544
|
+
*/
|
|
4545
|
+
static transformToBarChart(data) {
|
|
4546
|
+
const categories = this.detectCategories(data);
|
|
4547
|
+
const categoryData = this.aggregateByCategory(data, categories);
|
|
4548
|
+
const barData = Object.entries(categoryData).map(([category, value]) => ({
|
|
4549
|
+
category,
|
|
4550
|
+
value,
|
|
4551
|
+
inStock: this.checkStockStatus(category, data)
|
|
4552
|
+
}));
|
|
4553
|
+
return {
|
|
4554
|
+
type: "bar_chart",
|
|
4555
|
+
title: "Comparison by Category",
|
|
4556
|
+
description: `Comparing ${categories.length} categories`,
|
|
4557
|
+
data: barData
|
|
4558
|
+
};
|
|
4559
|
+
}
|
|
4560
|
+
/**
|
|
4561
|
+
* Transform data to line chart format
|
|
4562
|
+
*/
|
|
4563
|
+
static transformToLineChart(data) {
|
|
4564
|
+
const timePoints = this.extractTimeSeriesData(data);
|
|
4565
|
+
const lineData = timePoints.map((point) => ({
|
|
4566
|
+
timestamp: point.timestamp,
|
|
4567
|
+
value: point.value,
|
|
4568
|
+
label: point.label
|
|
4569
|
+
}));
|
|
4570
|
+
return {
|
|
4571
|
+
type: "line_chart",
|
|
4572
|
+
title: "Trend Over Time",
|
|
4573
|
+
description: `Showing ${lineData.length} data points`,
|
|
4574
|
+
data: lineData
|
|
4575
|
+
};
|
|
4576
|
+
}
|
|
4577
|
+
/**
|
|
4578
|
+
* Transform data to table format
|
|
4579
|
+
*/
|
|
4580
|
+
static transformToTable(data) {
|
|
4581
|
+
const columns = this.extractTableColumns(data);
|
|
4582
|
+
const rows = data.map((item) => this.extractTableRow(item, columns));
|
|
4583
|
+
const tableData = {
|
|
4584
|
+
columns,
|
|
4585
|
+
rows
|
|
4586
|
+
};
|
|
4587
|
+
return {
|
|
4588
|
+
type: "table",
|
|
4589
|
+
title: "Detailed Results",
|
|
4590
|
+
description: `Showing ${data.length} results`,
|
|
4591
|
+
data: tableData
|
|
4592
|
+
};
|
|
4593
|
+
}
|
|
4594
|
+
/**
|
|
4595
|
+
* Transform data to text format (fallback)
|
|
4596
|
+
*/
|
|
4597
|
+
static transformToText(data) {
|
|
4598
|
+
const textContent = data.map((item) => item.content).join("\n\n");
|
|
4599
|
+
return this.createTextResponse(
|
|
4600
|
+
"Search Results",
|
|
4601
|
+
textContent,
|
|
4602
|
+
`Found ${data.length} relevant results`
|
|
4603
|
+
);
|
|
4604
|
+
}
|
|
4605
|
+
/**
|
|
4606
|
+
* Helper: Create text response
|
|
4607
|
+
*/
|
|
4608
|
+
static createTextResponse(title, content, description) {
|
|
4609
|
+
return {
|
|
4610
|
+
type: "text",
|
|
4611
|
+
title,
|
|
4612
|
+
description,
|
|
4613
|
+
data: { content }
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
/**
|
|
4617
|
+
* Helper: Check if data item is product-related
|
|
4618
|
+
*/
|
|
4619
|
+
static isProductData(item) {
|
|
4620
|
+
const content = (item.content || "").toLowerCase();
|
|
4621
|
+
const productKeywords = ["product", "price", "stock", "item", "sku", "brand", "model"];
|
|
4622
|
+
return productKeywords.some((kw) => content.includes(kw)) || Object.keys(item.metadata || {}).some(
|
|
4623
|
+
(k) => ["name", "price", "product", "sku"].includes(k.toLowerCase())
|
|
4624
|
+
);
|
|
4625
|
+
}
|
|
4626
|
+
/**
|
|
4627
|
+
* Helper: Check if data contains time series
|
|
4628
|
+
*/
|
|
4629
|
+
static isTimeSeriesData(item) {
|
|
4630
|
+
const content = (item.content || "").toLowerCase();
|
|
4631
|
+
const timeKeywords = ["date", "time", "year", "month", "week", "day", "hour", "trend", "historical"];
|
|
4632
|
+
return timeKeywords.some((kw) => content.includes(kw)) || Object.keys(item.metadata || {}).some(
|
|
4633
|
+
(k) => ["date", "timestamp", "time", "period"].includes(k.toLowerCase())
|
|
4634
|
+
);
|
|
4635
|
+
}
|
|
4636
|
+
/**
|
|
4637
|
+
* Helper: Extract product information from vector match
|
|
4638
|
+
*/
|
|
4639
|
+
static extractProductInfo(item) {
|
|
4640
|
+
const meta = item.metadata || {};
|
|
4641
|
+
if (meta.name || meta.product) {
|
|
4642
|
+
return {
|
|
4643
|
+
id: item.id,
|
|
4644
|
+
name: meta.name || meta.product,
|
|
4645
|
+
price: meta.price,
|
|
4646
|
+
image: meta.image || meta.imageUrl,
|
|
4647
|
+
brand: meta.brand,
|
|
4648
|
+
description: item.content,
|
|
4649
|
+
inStock: this.determineStockStatus(item)
|
|
4650
|
+
};
|
|
4651
|
+
}
|
|
4652
|
+
const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
|
|
4653
|
+
const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d.]+)/i);
|
|
4654
|
+
if (nameMatch) {
|
|
4655
|
+
return {
|
|
4656
|
+
id: item.id,
|
|
4657
|
+
name: nameMatch[1],
|
|
4658
|
+
price: priceMatch ? parseFloat(priceMatch[1]) : void 0,
|
|
4659
|
+
description: item.content,
|
|
4660
|
+
inStock: this.determineStockStatus(item)
|
|
4661
|
+
};
|
|
4662
|
+
}
|
|
4663
|
+
return null;
|
|
4664
|
+
}
|
|
4665
|
+
/**
|
|
4666
|
+
* Helper: Detect categories in data
|
|
4667
|
+
*/
|
|
4668
|
+
static detectCategories(data) {
|
|
4669
|
+
const categories = /* @__PURE__ */ new Set();
|
|
4670
|
+
data.forEach((item) => {
|
|
4671
|
+
const meta = item.metadata || {};
|
|
4672
|
+
if (meta.category) {
|
|
4673
|
+
categories.add(String(meta.category));
|
|
4674
|
+
}
|
|
4675
|
+
if (meta.type) {
|
|
4676
|
+
categories.add(String(meta.type));
|
|
4677
|
+
}
|
|
4678
|
+
if (meta.tag) {
|
|
4679
|
+
const tags = Array.isArray(meta.tag) ? meta.tag : [meta.tag];
|
|
4680
|
+
tags.forEach((t) => categories.add(String(t)));
|
|
4681
|
+
}
|
|
4682
|
+
const categoryMatch = item.content.match(/(?:Category|Type|Class):\s*([^\n]+)/i);
|
|
4683
|
+
if (categoryMatch) {
|
|
4684
|
+
categories.add(categoryMatch[1].trim());
|
|
4685
|
+
}
|
|
4686
|
+
});
|
|
4687
|
+
return Array.from(categories);
|
|
4688
|
+
}
|
|
4689
|
+
/**
|
|
4690
|
+
* Helper: Aggregate data by category
|
|
4691
|
+
*/
|
|
4692
|
+
static aggregateByCategory(data, categories) {
|
|
4693
|
+
const result = {};
|
|
4694
|
+
categories.forEach((cat) => {
|
|
4695
|
+
result[cat] = 0;
|
|
4696
|
+
});
|
|
4697
|
+
data.forEach((item) => {
|
|
4698
|
+
const meta = item.metadata || {};
|
|
4699
|
+
const itemCategory = meta.category || meta.type || "Other";
|
|
4700
|
+
if (result.hasOwnProperty(itemCategory)) {
|
|
4701
|
+
result[itemCategory]++;
|
|
4702
|
+
} else {
|
|
4703
|
+
result["Other"] = (result["Other"] || 0) + 1;
|
|
4704
|
+
}
|
|
4705
|
+
});
|
|
4706
|
+
return result;
|
|
4707
|
+
}
|
|
4708
|
+
/**
|
|
4709
|
+
* Helper: Extract time series data
|
|
4710
|
+
*/
|
|
4711
|
+
static extractTimeSeriesData(data) {
|
|
4712
|
+
return data.map((item) => {
|
|
4713
|
+
const meta = item.metadata || {};
|
|
4714
|
+
return {
|
|
4715
|
+
timestamp: meta.timestamp || meta.date || (/* @__PURE__ */ new Date()).toISOString(),
|
|
4716
|
+
value: meta.value || item.score || 0,
|
|
4717
|
+
label: meta.label || item.content.substring(0, 50)
|
|
4718
|
+
};
|
|
4719
|
+
});
|
|
4720
|
+
}
|
|
4721
|
+
/**
|
|
4722
|
+
* Helper: Extract table columns
|
|
4723
|
+
*/
|
|
4724
|
+
static extractTableColumns(data) {
|
|
4725
|
+
const columnSet = /* @__PURE__ */ new Set();
|
|
4726
|
+
columnSet.add("Content");
|
|
4727
|
+
data.forEach((item) => {
|
|
4728
|
+
Object.keys(item.metadata || {}).forEach((key) => {
|
|
4729
|
+
columnSet.add(key.charAt(0).toUpperCase() + key.slice(1));
|
|
4730
|
+
});
|
|
4731
|
+
});
|
|
4732
|
+
return Array.from(columnSet);
|
|
4733
|
+
}
|
|
4734
|
+
/**
|
|
4735
|
+
* Helper: Extract table row
|
|
4736
|
+
*/
|
|
4737
|
+
static extractTableRow(item, columns) {
|
|
4738
|
+
const meta = item.metadata || {};
|
|
4739
|
+
return columns.map((col) => {
|
|
4740
|
+
if (col === "Content") {
|
|
4741
|
+
return item.content.substring(0, 100);
|
|
4742
|
+
}
|
|
4743
|
+
const metaKey = col.charAt(0).toLowerCase() + col.slice(1);
|
|
4744
|
+
const value = meta[metaKey];
|
|
4745
|
+
return value !== void 0 ? String(value) : "";
|
|
4746
|
+
});
|
|
4747
|
+
}
|
|
4748
|
+
/**
|
|
4749
|
+
* Helper: Check stock status
|
|
4750
|
+
*/
|
|
4751
|
+
static checkStockStatus(category, data) {
|
|
4752
|
+
const item = data.find((d) => {
|
|
4753
|
+
const meta = d.metadata || {};
|
|
4754
|
+
return meta.category === category || meta.type === category;
|
|
4755
|
+
});
|
|
4756
|
+
return this.determineStockStatus(item || {});
|
|
4757
|
+
}
|
|
4758
|
+
/**
|
|
4759
|
+
* Helper: Determine if item is in stock
|
|
4760
|
+
*/
|
|
4761
|
+
static determineStockStatus(item) {
|
|
4762
|
+
const meta = item.metadata || {};
|
|
4763
|
+
if (meta.inStock !== void 0) {
|
|
4764
|
+
return Boolean(meta.inStock);
|
|
4765
|
+
}
|
|
4766
|
+
if (meta.stock !== void 0) {
|
|
4767
|
+
return Boolean(meta.stock);
|
|
4768
|
+
}
|
|
4769
|
+
if (meta.available !== void 0) {
|
|
4770
|
+
return Boolean(meta.available);
|
|
4771
|
+
}
|
|
4772
|
+
const content = (item.content || "").toLowerCase();
|
|
4773
|
+
if (content.includes("out of stock") || content.includes("unavailable")) {
|
|
4774
|
+
return false;
|
|
4775
|
+
}
|
|
4776
|
+
if (content.includes("in stock") || content.includes("available")) {
|
|
4777
|
+
return true;
|
|
4778
|
+
}
|
|
4779
|
+
return true;
|
|
4780
|
+
}
|
|
4781
|
+
/**
|
|
4782
|
+
* Helper: Check if data has multiple fields
|
|
4783
|
+
*/
|
|
4784
|
+
static hasMultipleFields(data) {
|
|
4785
|
+
const fieldCount = /* @__PURE__ */ new Set();
|
|
4786
|
+
data.forEach((item) => {
|
|
4787
|
+
Object.keys(item.metadata || {}).forEach((key) => {
|
|
4788
|
+
fieldCount.add(key);
|
|
4789
|
+
});
|
|
4790
|
+
});
|
|
4791
|
+
return fieldCount.size > 2;
|
|
4792
|
+
}
|
|
4793
|
+
};
|
|
4794
|
+
|
|
4430
4795
|
// src/handlers/index.ts
|
|
4431
4796
|
function sseFrame(payload) {
|
|
4432
4797
|
return `data: ${JSON.stringify(payload)}
|
|
@@ -4441,6 +4806,11 @@ function sseTextFrame(text) {
|
|
|
4441
4806
|
function sseMetaFrame(meta) {
|
|
4442
4807
|
return `data: ${JSON.stringify(__spreadValues({ type: "metadata" }, meta != null ? meta : {}))}
|
|
4443
4808
|
|
|
4809
|
+
`;
|
|
4810
|
+
}
|
|
4811
|
+
function sseUIFrame(uiTransformation) {
|
|
4812
|
+
return `data: ${JSON.stringify(__spreadValues({ type: "ui_transformation" }, uiTransformation != null ? uiTransformation : {}))}
|
|
4813
|
+
|
|
4444
4814
|
`;
|
|
4445
4815
|
}
|
|
4446
4816
|
function sseErrorFrame(message) {
|
|
@@ -4504,6 +4874,15 @@ function createStreamHandler(configOrPlugin) {
|
|
|
4504
4874
|
enqueue(sseTextFrame(chunk));
|
|
4505
4875
|
} else {
|
|
4506
4876
|
enqueue(sseMetaFrame(chunk));
|
|
4877
|
+
const sources = (chunk == null ? void 0 : chunk.sources) || [];
|
|
4878
|
+
if (sources && sources.length > 0) {
|
|
4879
|
+
try {
|
|
4880
|
+
const uiTransformation = UITransformer.transform(message, sources);
|
|
4881
|
+
enqueue(sseUIFrame(uiTransformation));
|
|
4882
|
+
} catch (transformError) {
|
|
4883
|
+
console.warn("[createStreamHandler] UI transformation warning:", transformError);
|
|
4884
|
+
}
|
|
4885
|
+
}
|
|
4507
4886
|
}
|
|
4508
4887
|
}
|
|
4509
4888
|
} catch (temp) {
|
|
@@ -4623,5 +5002,6 @@ function createSuggestionsHandler(configOrPlugin) {
|
|
|
4623
5002
|
sseErrorFrame,
|
|
4624
5003
|
sseFrame,
|
|
4625
5004
|
sseMetaFrame,
|
|
4626
|
-
sseTextFrame
|
|
5005
|
+
sseTextFrame,
|
|
5006
|
+
sseUIFrame
|
|
4627
5007
|
});
|
package/dist/handlers/index.mjs
CHANGED
|
@@ -8,8 +8,9 @@ import {
|
|
|
8
8
|
sseErrorFrame,
|
|
9
9
|
sseFrame,
|
|
10
10
|
sseMetaFrame,
|
|
11
|
-
sseTextFrame
|
|
12
|
-
|
|
11
|
+
sseTextFrame,
|
|
12
|
+
sseUIFrame
|
|
13
|
+
} from "../chunk-M32ZXLTT.mjs";
|
|
13
14
|
import "../chunk-YLTMFW4M.mjs";
|
|
14
15
|
import "../chunk-X4TOT24V.mjs";
|
|
15
16
|
export {
|
|
@@ -22,5 +23,6 @@ export {
|
|
|
22
23
|
sseErrorFrame,
|
|
23
24
|
sseFrame,
|
|
24
25
|
sseMetaFrame,
|
|
25
|
-
sseTextFrame
|
|
26
|
+
sseTextFrame,
|
|
27
|
+
sseUIFrame
|
|
26
28
|
};
|
|
@@ -125,8 +125,10 @@ declare class VectorPlugin {
|
|
|
125
125
|
declare function sseFrame(payload: unknown): string;
|
|
126
126
|
/** Encode a plain text chunk as an SSE frame. */
|
|
127
127
|
declare function sseTextFrame(text: string): string;
|
|
128
|
-
/** Encode the retrieval metadata as an SSE frame. */
|
|
128
|
+
/** Encode the retrieval metadata with UI transformation as an SSE frame. */
|
|
129
129
|
declare function sseMetaFrame(meta: unknown): string;
|
|
130
|
+
/** Encode the UI transformation result as an SSE frame. */
|
|
131
|
+
declare function sseUIFrame(uiTransformation: unknown): string;
|
|
130
132
|
/** Encode a stream error as an SSE frame. */
|
|
131
133
|
declare function sseErrorFrame(message: string): string;
|
|
132
134
|
/**
|
|
@@ -215,4 +217,4 @@ declare function createSuggestionsHandler(configOrPlugin?: Partial<RagConfig> |
|
|
|
215
217
|
suggestions: string[];
|
|
216
218
|
}>>;
|
|
217
219
|
|
|
218
|
-
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseErrorFrame as s };
|
|
220
|
+
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseUIFrame as l, sseErrorFrame as s };
|
|
@@ -125,8 +125,10 @@ declare class VectorPlugin {
|
|
|
125
125
|
declare function sseFrame(payload: unknown): string;
|
|
126
126
|
/** Encode a plain text chunk as an SSE frame. */
|
|
127
127
|
declare function sseTextFrame(text: string): string;
|
|
128
|
-
/** Encode the retrieval metadata as an SSE frame. */
|
|
128
|
+
/** Encode the retrieval metadata with UI transformation as an SSE frame. */
|
|
129
129
|
declare function sseMetaFrame(meta: unknown): string;
|
|
130
|
+
/** Encode the UI transformation result as an SSE frame. */
|
|
131
|
+
declare function sseUIFrame(uiTransformation: unknown): string;
|
|
130
132
|
/** Encode a stream error as an SSE frame. */
|
|
131
133
|
declare function sseErrorFrame(message: string): string;
|
|
132
134
|
/**
|
|
@@ -215,4 +217,4 @@ declare function createSuggestionsHandler(configOrPlugin?: Partial<RagConfig> |
|
|
|
215
217
|
suggestions: string[];
|
|
216
218
|
}>>;
|
|
217
219
|
|
|
218
|
-
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseErrorFrame as s };
|
|
220
|
+
export { ConfigValidator as C, type HealthCheckResult as H, type IProviderValidator as I, type ValidationError as V, type IProviderHealthChecker as a, VectorPlugin as b, createChatHandler as c, createHealthHandler as d, createIngestHandler as e, createStreamHandler as f, createUploadHandler as g, sseFrame as h, sseMetaFrame as i, sseTextFrame as j, createSuggestionsHandler as k, sseUIFrame as l, sseErrorFrame as s };
|