@retrivora-ai/rag-engine 1.7.1 → 1.7.3
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 +37 -46
- package/dist/index.mjs +37 -46
- 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 +54 -80
- package/src/components/VisualizationRenderer.tsx +341 -0
- package/src/core/Pipeline.ts +39 -19
- package/src/handlers/index.ts +21 -3
- package/src/utils/UITransformer.ts +535 -0
|
@@ -2259,18 +2259,17 @@ var Pipeline = class {
|
|
|
2259
2259
|
async initialize() {
|
|
2260
2260
|
var _a, _b;
|
|
2261
2261
|
if (this.initialised) return;
|
|
2262
|
-
const CHART_MARKER = "<!--
|
|
2262
|
+
const CHART_MARKER = "<!-- UI_PROTOCOL_V6 -->";
|
|
2263
2263
|
const chartInstruction = `
|
|
2264
2264
|
|
|
2265
2265
|
${CHART_MARKER}
|
|
2266
|
-
### UNIVERSAL UI PROTOCOL
|
|
2267
|
-
|
|
2268
|
-
NEVER output naked JSON. If you provide a visualization, do not also provide a markdown table of the same data unless explicitly asked.
|
|
2266
|
+
### UNIVERSAL UI PROTOCOL
|
|
2267
|
+
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.
|
|
2269
2268
|
|
|
2270
2269
|
1. VIEW SELECTION
|
|
2271
|
-
- Use "carousel" for browsing products, items, or
|
|
2272
|
-
- Use "chart" ONLY for numerical aggregations
|
|
2273
|
-
- Use "table" for technical
|
|
2270
|
+
- 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").
|
|
2271
|
+
- Use "chart" ONLY for numerical aggregations: distributions, percentages, counts, comparisons over time, or trends (e.g. "how many beauty products?").
|
|
2272
|
+
- Use "table" for detailed technical specifications, row-heavy comparisons, or when the user explicitly asks for a list/table format.
|
|
2274
2273
|
|
|
2275
2274
|
2. REQUIRED JSON SHAPE
|
|
2276
2275
|
{
|
|
@@ -2278,31 +2277,52 @@ NEVER output naked JSON. If you provide a visualization, do not also provide a m
|
|
|
2278
2277
|
"title": "Short heading",
|
|
2279
2278
|
"description": "One sentence describing the view",
|
|
2280
2279
|
"chartType": "pie" | "bar" | "line", // Required if view is "chart"
|
|
2281
|
-
"
|
|
2280
|
+
"xAxisKey": "label",
|
|
2281
|
+
"dataKeys": ["value"],
|
|
2282
|
+
"columns": ["dynamicFieldKey1", "dynamicFieldKey2"],
|
|
2283
|
+
"insights": ["Short takeaway 1", "Short takeaway 2"],
|
|
2284
|
+
"data": []
|
|
2282
2285
|
}
|
|
2283
2286
|
|
|
2284
2287
|
3. DATA RULES
|
|
2285
|
-
- Build the UI payload from retrieved context
|
|
2286
|
-
- For CAROUSEL: "data"
|
|
2287
|
-
-
|
|
2288
|
+
- Build the UI payload from retrieved context only. Do not invent products or values.
|
|
2289
|
+
- For CAROUSEL: "data" must be a list of product objects (id, name, brand, price, image, link).
|
|
2290
|
+
- For CHART: "data" must be aggregated counts or sums. Never put raw product lists in a chart view.
|
|
2291
|
+
- If the user asks for "products in beauty", do NOT return a pie chart of categories; return a carousel of the beauty products themselves.
|
|
2288
2292
|
|
|
2289
2293
|
4. FORMAT RULES
|
|
2290
|
-
-
|
|
2291
|
-
-
|
|
2294
|
+
- Return valid JSON inside the \`\`\`ui\`\`\` block.
|
|
2295
|
+
- Put natural language explanation before or after the block, not inside.
|
|
2292
2296
|
|
|
2293
|
-
5.
|
|
2294
|
-
User: "
|
|
2295
|
-
Assistant:
|
|
2297
|
+
5. EXAMPLES
|
|
2298
|
+
User: "show me beauty products"
|
|
2299
|
+
Assistant:
|
|
2296
2300
|
\`\`\`ui
|
|
2297
2301
|
{
|
|
2298
2302
|
"view": "carousel",
|
|
2299
2303
|
"title": "Beauty Products",
|
|
2300
|
-
"description": "
|
|
2304
|
+
"description": "Browse our latest skincare and makeup collection.",
|
|
2301
2305
|
"data": [
|
|
2302
|
-
{ "id": "1", "name": "Mascara", "brand": "Essence", "price": "$9.99", "image": "
|
|
2306
|
+
{ "id": "1", "name": "Mascara", "brand": "Essence", "price": "$9.99", "image": "...", "link": "..." },
|
|
2307
|
+
{ "id": "2", "name": "Lipstick", "brand": "Chic", "price": "$12.99", "image": "...", "link": "..." }
|
|
2303
2308
|
]
|
|
2304
2309
|
}
|
|
2305
2310
|
\`\`\`
|
|
2311
|
+
|
|
2312
|
+
User: "breakdown of products by category"
|
|
2313
|
+
Assistant:
|
|
2314
|
+
\`\`\`ui
|
|
2315
|
+
{
|
|
2316
|
+
"view": "chart",
|
|
2317
|
+
"title": "Category Breakdown",
|
|
2318
|
+
"chartType": "pie",
|
|
2319
|
+
"xAxisKey": "label",
|
|
2320
|
+
"dataKeys": ["value"],
|
|
2321
|
+
"data": [
|
|
2322
|
+
{ "label": "Beauty", "value": 15 },
|
|
2323
|
+
{ "label": "Fragrances", "value": 8 }
|
|
2324
|
+
]
|
|
2325
|
+
}
|
|
2306
2326
|
\`\`\``;
|
|
2307
2327
|
if (!((_a = this.config.llm.systemPrompt) == null ? void 0 : _a.includes(CHART_MARKER))) {
|
|
2308
2328
|
this.config.llm.systemPrompt = (this.config.llm.systemPrompt || "") + chartInstruction;
|
|
@@ -2511,8 +2531,7 @@ Assistant: "I found several beauty products in our catalog:"
|
|
|
2511
2531
|
sources = sources.slice(0, topK);
|
|
2512
2532
|
}
|
|
2513
2533
|
let context = sources.length ? sources.map((m, i) => `[Source ${i + 1}]
|
|
2514
|
-
|
|
2515
|
-
Metadata: ${JSON.stringify(m.metadata)}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
2534
|
+
${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
|
|
2516
2535
|
if (graphData && graphData.nodes.length > 0) {
|
|
2517
2536
|
const graphContext = graphData.nodes.map(
|
|
2518
2537
|
(n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
|
|
@@ -2864,6 +2883,351 @@ var DocumentParser = class {
|
|
|
2864
2883
|
}
|
|
2865
2884
|
};
|
|
2866
2885
|
|
|
2886
|
+
// src/utils/UITransformer.ts
|
|
2887
|
+
var UITransformer = class {
|
|
2888
|
+
/**
|
|
2889
|
+
* Main transformation method
|
|
2890
|
+
* Analyzes user query and retrieved data to determine the best visualization format
|
|
2891
|
+
*
|
|
2892
|
+
* @param userQuery - The original user question/query
|
|
2893
|
+
* @param retrievedData - Vector database retrieval results
|
|
2894
|
+
* @returns Structured JSON response for UI rendering
|
|
2895
|
+
*/
|
|
2896
|
+
static transform(userQuery, retrievedData) {
|
|
2897
|
+
if (!retrievedData || retrievedData.length === 0) {
|
|
2898
|
+
return this.createTextResponse("No data available", "No relevant data found for your query.");
|
|
2899
|
+
}
|
|
2900
|
+
const analysis = this.analyzeData(userQuery, retrievedData);
|
|
2901
|
+
switch (analysis.suggestedType) {
|
|
2902
|
+
case "product_carousel":
|
|
2903
|
+
return this.transformToProductCarousel(retrievedData);
|
|
2904
|
+
case "pie_chart":
|
|
2905
|
+
return this.transformToPieChart(retrievedData);
|
|
2906
|
+
case "bar_chart":
|
|
2907
|
+
return this.transformToBarChart(retrievedData);
|
|
2908
|
+
case "line_chart":
|
|
2909
|
+
return this.transformToLineChart(retrievedData);
|
|
2910
|
+
case "table":
|
|
2911
|
+
return this.transformToTable(retrievedData);
|
|
2912
|
+
default:
|
|
2913
|
+
return this.transformToText(retrievedData);
|
|
2914
|
+
}
|
|
2915
|
+
}
|
|
2916
|
+
/**
|
|
2917
|
+
* Analyzes the data and query to suggest the best visualization type
|
|
2918
|
+
*/
|
|
2919
|
+
static analyzeData(query, data) {
|
|
2920
|
+
const queryLower = query.toLowerCase();
|
|
2921
|
+
const hasProducts = data.some(
|
|
2922
|
+
(item) => this.isProductData(item)
|
|
2923
|
+
);
|
|
2924
|
+
const hasTimeSeries = data.some(
|
|
2925
|
+
(item) => this.isTimeSeriesData(item)
|
|
2926
|
+
);
|
|
2927
|
+
const hasCategories = this.detectCategories(data).length > 0;
|
|
2928
|
+
const isDistributionQuery = queryLower.includes("distribution") || queryLower.includes("breakdown") || queryLower.includes("percentage") || queryLower.includes("proportion");
|
|
2929
|
+
const isComparisonQuery = queryLower.includes("compare") || queryLower.includes("vs") || queryLower.includes("difference");
|
|
2930
|
+
const isTrendQuery = queryLower.includes("trend") || queryLower.includes("over time") || queryLower.includes("growth") || queryLower.includes("decline");
|
|
2931
|
+
if (hasProducts && !hasTimeSeries && !isDistributionQuery) {
|
|
2932
|
+
return { suggestedType: "product_carousel", confidence: 0.95, hasProducts, hasTimeSeries, hasCategories };
|
|
2933
|
+
}
|
|
2934
|
+
if (isTrendQuery && hasTimeSeries) {
|
|
2935
|
+
return { suggestedType: "line_chart", confidence: 0.9, hasProducts, hasTimeSeries, hasCategories };
|
|
2936
|
+
}
|
|
2937
|
+
if (isDistributionQuery && hasCategories) {
|
|
2938
|
+
return { suggestedType: "pie_chart", confidence: 0.85, hasProducts, hasTimeSeries, hasCategories };
|
|
2939
|
+
}
|
|
2940
|
+
if (isComparisonQuery && hasCategories && data.length > 2) {
|
|
2941
|
+
return { suggestedType: "bar_chart", confidence: 0.8, hasProducts, hasTimeSeries, hasCategories };
|
|
2942
|
+
}
|
|
2943
|
+
if (data.length > 5 && this.hasMultipleFields(data)) {
|
|
2944
|
+
return { suggestedType: "table", confidence: 0.75, hasProducts, hasTimeSeries, hasCategories };
|
|
2945
|
+
}
|
|
2946
|
+
return { suggestedType: "text", confidence: 0.5, hasProducts, hasTimeSeries, hasCategories };
|
|
2947
|
+
}
|
|
2948
|
+
/**
|
|
2949
|
+
* Transform data to product carousel format
|
|
2950
|
+
*/
|
|
2951
|
+
static transformToProductCarousel(data) {
|
|
2952
|
+
const products = data.filter((item) => this.isProductData(item)).map((item) => this.extractProductInfo(item)).filter((p) => p !== null);
|
|
2953
|
+
return {
|
|
2954
|
+
type: "product_carousel",
|
|
2955
|
+
title: "Recommended Products",
|
|
2956
|
+
description: `Found ${products.length} relevant products`,
|
|
2957
|
+
data: products
|
|
2958
|
+
};
|
|
2959
|
+
}
|
|
2960
|
+
/**
|
|
2961
|
+
* Transform data to pie chart format
|
|
2962
|
+
*/
|
|
2963
|
+
static transformToPieChart(data) {
|
|
2964
|
+
const categories = this.detectCategories(data);
|
|
2965
|
+
const categoryData = this.aggregateByCategory(data, categories);
|
|
2966
|
+
const pieData = Object.entries(categoryData).map(([label, count]) => ({
|
|
2967
|
+
label,
|
|
2968
|
+
value: count,
|
|
2969
|
+
inStock: this.checkStockStatus(label, data)
|
|
2970
|
+
}));
|
|
2971
|
+
return {
|
|
2972
|
+
type: "pie_chart",
|
|
2973
|
+
title: "Distribution by Category",
|
|
2974
|
+
description: `Showing breakdown across ${categories.length} categories`,
|
|
2975
|
+
data: pieData
|
|
2976
|
+
};
|
|
2977
|
+
}
|
|
2978
|
+
/**
|
|
2979
|
+
* Transform data to bar chart format
|
|
2980
|
+
*/
|
|
2981
|
+
static transformToBarChart(data) {
|
|
2982
|
+
const categories = this.detectCategories(data);
|
|
2983
|
+
const categoryData = this.aggregateByCategory(data, categories);
|
|
2984
|
+
const barData = Object.entries(categoryData).map(([category, value]) => ({
|
|
2985
|
+
category,
|
|
2986
|
+
value,
|
|
2987
|
+
inStock: this.checkStockStatus(category, data)
|
|
2988
|
+
}));
|
|
2989
|
+
return {
|
|
2990
|
+
type: "bar_chart",
|
|
2991
|
+
title: "Comparison by Category",
|
|
2992
|
+
description: `Comparing ${categories.length} categories`,
|
|
2993
|
+
data: barData
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
/**
|
|
2997
|
+
* Transform data to line chart format
|
|
2998
|
+
*/
|
|
2999
|
+
static transformToLineChart(data) {
|
|
3000
|
+
const timePoints = this.extractTimeSeriesData(data);
|
|
3001
|
+
const lineData = timePoints.map((point) => ({
|
|
3002
|
+
timestamp: point.timestamp,
|
|
3003
|
+
value: point.value,
|
|
3004
|
+
label: point.label
|
|
3005
|
+
}));
|
|
3006
|
+
return {
|
|
3007
|
+
type: "line_chart",
|
|
3008
|
+
title: "Trend Over Time",
|
|
3009
|
+
description: `Showing ${lineData.length} data points`,
|
|
3010
|
+
data: lineData
|
|
3011
|
+
};
|
|
3012
|
+
}
|
|
3013
|
+
/**
|
|
3014
|
+
* Transform data to table format
|
|
3015
|
+
*/
|
|
3016
|
+
static transformToTable(data) {
|
|
3017
|
+
const columns = this.extractTableColumns(data);
|
|
3018
|
+
const rows = data.map((item) => this.extractTableRow(item, columns));
|
|
3019
|
+
const tableData = {
|
|
3020
|
+
columns,
|
|
3021
|
+
rows
|
|
3022
|
+
};
|
|
3023
|
+
return {
|
|
3024
|
+
type: "table",
|
|
3025
|
+
title: "Detailed Results",
|
|
3026
|
+
description: `Showing ${data.length} results`,
|
|
3027
|
+
data: tableData
|
|
3028
|
+
};
|
|
3029
|
+
}
|
|
3030
|
+
/**
|
|
3031
|
+
* Transform data to text format (fallback)
|
|
3032
|
+
*/
|
|
3033
|
+
static transformToText(data) {
|
|
3034
|
+
const textContent = data.map((item) => item.content).join("\n\n");
|
|
3035
|
+
return this.createTextResponse(
|
|
3036
|
+
"Search Results",
|
|
3037
|
+
textContent,
|
|
3038
|
+
`Found ${data.length} relevant results`
|
|
3039
|
+
);
|
|
3040
|
+
}
|
|
3041
|
+
/**
|
|
3042
|
+
* Helper: Create text response
|
|
3043
|
+
*/
|
|
3044
|
+
static createTextResponse(title, content, description) {
|
|
3045
|
+
return {
|
|
3046
|
+
type: "text",
|
|
3047
|
+
title,
|
|
3048
|
+
description,
|
|
3049
|
+
data: { content }
|
|
3050
|
+
};
|
|
3051
|
+
}
|
|
3052
|
+
/**
|
|
3053
|
+
* Helper: Check if data item is product-related
|
|
3054
|
+
*/
|
|
3055
|
+
static isProductData(item) {
|
|
3056
|
+
const content = (item.content || "").toLowerCase();
|
|
3057
|
+
const productKeywords = ["product", "price", "stock", "item", "sku", "brand", "model"];
|
|
3058
|
+
return productKeywords.some((kw) => content.includes(kw)) || Object.keys(item.metadata || {}).some(
|
|
3059
|
+
(k) => ["name", "price", "product", "sku"].includes(k.toLowerCase())
|
|
3060
|
+
);
|
|
3061
|
+
}
|
|
3062
|
+
/**
|
|
3063
|
+
* Helper: Check if data contains time series
|
|
3064
|
+
*/
|
|
3065
|
+
static isTimeSeriesData(item) {
|
|
3066
|
+
const content = (item.content || "").toLowerCase();
|
|
3067
|
+
const timeKeywords = ["date", "time", "year", "month", "week", "day", "hour", "trend", "historical"];
|
|
3068
|
+
return timeKeywords.some((kw) => content.includes(kw)) || Object.keys(item.metadata || {}).some(
|
|
3069
|
+
(k) => ["date", "timestamp", "time", "period"].includes(k.toLowerCase())
|
|
3070
|
+
);
|
|
3071
|
+
}
|
|
3072
|
+
/**
|
|
3073
|
+
* Helper: Extract product information from vector match
|
|
3074
|
+
*/
|
|
3075
|
+
static extractProductInfo(item) {
|
|
3076
|
+
const meta = item.metadata || {};
|
|
3077
|
+
if (meta.name || meta.product) {
|
|
3078
|
+
return {
|
|
3079
|
+
id: item.id,
|
|
3080
|
+
name: meta.name || meta.product,
|
|
3081
|
+
price: meta.price,
|
|
3082
|
+
image: meta.image || meta.imageUrl,
|
|
3083
|
+
brand: meta.brand,
|
|
3084
|
+
description: item.content,
|
|
3085
|
+
inStock: this.determineStockStatus(item)
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
|
|
3089
|
+
const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d.]+)/i);
|
|
3090
|
+
if (nameMatch) {
|
|
3091
|
+
return {
|
|
3092
|
+
id: item.id,
|
|
3093
|
+
name: nameMatch[1],
|
|
3094
|
+
price: priceMatch ? parseFloat(priceMatch[1]) : void 0,
|
|
3095
|
+
description: item.content,
|
|
3096
|
+
inStock: this.determineStockStatus(item)
|
|
3097
|
+
};
|
|
3098
|
+
}
|
|
3099
|
+
return null;
|
|
3100
|
+
}
|
|
3101
|
+
/**
|
|
3102
|
+
* Helper: Detect categories in data
|
|
3103
|
+
*/
|
|
3104
|
+
static detectCategories(data) {
|
|
3105
|
+
const categories = /* @__PURE__ */ new Set();
|
|
3106
|
+
data.forEach((item) => {
|
|
3107
|
+
const meta = item.metadata || {};
|
|
3108
|
+
if (meta.category) {
|
|
3109
|
+
categories.add(String(meta.category));
|
|
3110
|
+
}
|
|
3111
|
+
if (meta.type) {
|
|
3112
|
+
categories.add(String(meta.type));
|
|
3113
|
+
}
|
|
3114
|
+
if (meta.tag) {
|
|
3115
|
+
const tags = Array.isArray(meta.tag) ? meta.tag : [meta.tag];
|
|
3116
|
+
tags.forEach((t) => categories.add(String(t)));
|
|
3117
|
+
}
|
|
3118
|
+
const categoryMatch = item.content.match(/(?:Category|Type|Class):\s*([^\n]+)/i);
|
|
3119
|
+
if (categoryMatch) {
|
|
3120
|
+
categories.add(categoryMatch[1].trim());
|
|
3121
|
+
}
|
|
3122
|
+
});
|
|
3123
|
+
return Array.from(categories);
|
|
3124
|
+
}
|
|
3125
|
+
/**
|
|
3126
|
+
* Helper: Aggregate data by category
|
|
3127
|
+
*/
|
|
3128
|
+
static aggregateByCategory(data, categories) {
|
|
3129
|
+
const result = {};
|
|
3130
|
+
categories.forEach((cat) => {
|
|
3131
|
+
result[cat] = 0;
|
|
3132
|
+
});
|
|
3133
|
+
data.forEach((item) => {
|
|
3134
|
+
const meta = item.metadata || {};
|
|
3135
|
+
const itemCategory = meta.category || meta.type || "Other";
|
|
3136
|
+
if (result.hasOwnProperty(itemCategory)) {
|
|
3137
|
+
result[itemCategory]++;
|
|
3138
|
+
} else {
|
|
3139
|
+
result["Other"] = (result["Other"] || 0) + 1;
|
|
3140
|
+
}
|
|
3141
|
+
});
|
|
3142
|
+
return result;
|
|
3143
|
+
}
|
|
3144
|
+
/**
|
|
3145
|
+
* Helper: Extract time series data
|
|
3146
|
+
*/
|
|
3147
|
+
static extractTimeSeriesData(data) {
|
|
3148
|
+
return data.map((item) => {
|
|
3149
|
+
const meta = item.metadata || {};
|
|
3150
|
+
return {
|
|
3151
|
+
timestamp: meta.timestamp || meta.date || (/* @__PURE__ */ new Date()).toISOString(),
|
|
3152
|
+
value: meta.value || item.score || 0,
|
|
3153
|
+
label: meta.label || item.content.substring(0, 50)
|
|
3154
|
+
};
|
|
3155
|
+
});
|
|
3156
|
+
}
|
|
3157
|
+
/**
|
|
3158
|
+
* Helper: Extract table columns
|
|
3159
|
+
*/
|
|
3160
|
+
static extractTableColumns(data) {
|
|
3161
|
+
const columnSet = /* @__PURE__ */ new Set();
|
|
3162
|
+
columnSet.add("Content");
|
|
3163
|
+
data.forEach((item) => {
|
|
3164
|
+
Object.keys(item.metadata || {}).forEach((key) => {
|
|
3165
|
+
columnSet.add(key.charAt(0).toUpperCase() + key.slice(1));
|
|
3166
|
+
});
|
|
3167
|
+
});
|
|
3168
|
+
return Array.from(columnSet);
|
|
3169
|
+
}
|
|
3170
|
+
/**
|
|
3171
|
+
* Helper: Extract table row
|
|
3172
|
+
*/
|
|
3173
|
+
static extractTableRow(item, columns) {
|
|
3174
|
+
const meta = item.metadata || {};
|
|
3175
|
+
return columns.map((col) => {
|
|
3176
|
+
if (col === "Content") {
|
|
3177
|
+
return item.content.substring(0, 100);
|
|
3178
|
+
}
|
|
3179
|
+
const metaKey = col.charAt(0).toLowerCase() + col.slice(1);
|
|
3180
|
+
const value = meta[metaKey];
|
|
3181
|
+
return value !== void 0 ? String(value) : "";
|
|
3182
|
+
});
|
|
3183
|
+
}
|
|
3184
|
+
/**
|
|
3185
|
+
* Helper: Check stock status
|
|
3186
|
+
*/
|
|
3187
|
+
static checkStockStatus(category, data) {
|
|
3188
|
+
const item = data.find((d) => {
|
|
3189
|
+
const meta = d.metadata || {};
|
|
3190
|
+
return meta.category === category || meta.type === category;
|
|
3191
|
+
});
|
|
3192
|
+
return this.determineStockStatus(item || {});
|
|
3193
|
+
}
|
|
3194
|
+
/**
|
|
3195
|
+
* Helper: Determine if item is in stock
|
|
3196
|
+
*/
|
|
3197
|
+
static determineStockStatus(item) {
|
|
3198
|
+
const meta = item.metadata || {};
|
|
3199
|
+
if (meta.inStock !== void 0) {
|
|
3200
|
+
return Boolean(meta.inStock);
|
|
3201
|
+
}
|
|
3202
|
+
if (meta.stock !== void 0) {
|
|
3203
|
+
return Boolean(meta.stock);
|
|
3204
|
+
}
|
|
3205
|
+
if (meta.available !== void 0) {
|
|
3206
|
+
return Boolean(meta.available);
|
|
3207
|
+
}
|
|
3208
|
+
const content = (item.content || "").toLowerCase();
|
|
3209
|
+
if (content.includes("out of stock") || content.includes("unavailable")) {
|
|
3210
|
+
return false;
|
|
3211
|
+
}
|
|
3212
|
+
if (content.includes("in stock") || content.includes("available")) {
|
|
3213
|
+
return true;
|
|
3214
|
+
}
|
|
3215
|
+
return true;
|
|
3216
|
+
}
|
|
3217
|
+
/**
|
|
3218
|
+
* Helper: Check if data has multiple fields
|
|
3219
|
+
*/
|
|
3220
|
+
static hasMultipleFields(data) {
|
|
3221
|
+
const fieldCount = /* @__PURE__ */ new Set();
|
|
3222
|
+
data.forEach((item) => {
|
|
3223
|
+
Object.keys(item.metadata || {}).forEach((key) => {
|
|
3224
|
+
fieldCount.add(key);
|
|
3225
|
+
});
|
|
3226
|
+
});
|
|
3227
|
+
return fieldCount.size > 2;
|
|
3228
|
+
}
|
|
3229
|
+
};
|
|
3230
|
+
|
|
2867
3231
|
// src/handlers/index.ts
|
|
2868
3232
|
function sseFrame(payload) {
|
|
2869
3233
|
return `data: ${JSON.stringify(payload)}
|
|
@@ -2878,6 +3242,11 @@ function sseTextFrame(text) {
|
|
|
2878
3242
|
function sseMetaFrame(meta) {
|
|
2879
3243
|
return `data: ${JSON.stringify(__spreadValues({ type: "metadata" }, meta != null ? meta : {}))}
|
|
2880
3244
|
|
|
3245
|
+
`;
|
|
3246
|
+
}
|
|
3247
|
+
function sseUIFrame(uiTransformation) {
|
|
3248
|
+
return `data: ${JSON.stringify(__spreadValues({ type: "ui_transformation" }, uiTransformation != null ? uiTransformation : {}))}
|
|
3249
|
+
|
|
2881
3250
|
`;
|
|
2882
3251
|
}
|
|
2883
3252
|
function sseErrorFrame(message) {
|
|
@@ -2941,6 +3310,15 @@ function createStreamHandler(configOrPlugin) {
|
|
|
2941
3310
|
enqueue(sseTextFrame(chunk));
|
|
2942
3311
|
} else {
|
|
2943
3312
|
enqueue(sseMetaFrame(chunk));
|
|
3313
|
+
const sources = (chunk == null ? void 0 : chunk.sources) || [];
|
|
3314
|
+
if (sources && sources.length > 0) {
|
|
3315
|
+
try {
|
|
3316
|
+
const uiTransformation = UITransformer.transform(message, sources);
|
|
3317
|
+
enqueue(sseUIFrame(uiTransformation));
|
|
3318
|
+
} catch (transformError) {
|
|
3319
|
+
console.warn("[createStreamHandler] UI transformation warning:", transformError);
|
|
3320
|
+
}
|
|
3321
|
+
}
|
|
2944
3322
|
}
|
|
2945
3323
|
}
|
|
2946
3324
|
} catch (temp) {
|
|
@@ -3073,6 +3451,7 @@ export {
|
|
|
3073
3451
|
sseFrame,
|
|
3074
3452
|
sseTextFrame,
|
|
3075
3453
|
sseMetaFrame,
|
|
3454
|
+
sseUIFrame,
|
|
3076
3455
|
sseErrorFrame,
|
|
3077
3456
|
createChatHandler,
|
|
3078
3457
|
createStreamHandler,
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '../index-Cti1u0y1.mjs';
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame, l as sseUIFrame } from '../index-BejNscWZ.mjs';
|
|
3
3
|
import 'next/server';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import '../index-Cti1u0y1.js';
|
|
2
|
-
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-
|
|
2
|
+
export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, k as createSuggestionsHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame, l as sseUIFrame } from '../index-CbkMJvu5.js';
|
|
3
3
|
import 'next/server';
|