From 0a62c60da2d736b71cbe3ec060763ac264d67f41 Mon Sep 17 00:00:00 2001
From: ItzCrazyKns <95534749+ItzCrazyKns@users.noreply.github.com>
Date: Mon, 24 Nov 2025 15:35:00 +0530
Subject: [PATCH] feat(widgets): add LLM context to prevent context overflow
---
src/lib/agents/search/index.ts | 3 +-
src/lib/agents/search/types.ts | 1 +
.../search/widgets/calculationWidget.ts | 2 +
src/lib/agents/search/widgets/stockWidget.ts | 173 +++++++++---------
.../agents/search/widgets/weatherWidget.ts | 4 +
5 files changed, 99 insertions(+), 84 deletions(-)
diff --git a/src/lib/agents/search/index.ts b/src/lib/agents/search/index.ts
index bacdb88..ab12bfe 100644
--- a/src/lib/agents/search/index.ts
+++ b/src/lib/agents/search/index.ts
@@ -65,14 +65,13 @@ class SearchAgent {
const widgetContext = widgetOutputs
.map((o) => {
- return `${o.type}: ${JSON.stringify(o.data)}`;
+ return `${o.type}: ${o.llmContext}`;
})
.join('\n-------------\n');
const finalContextWithWidgets = `${finalContext}\n${widgetContext}`;
const writerPrompt = getWriterPrompt(finalContextWithWidgets);
-
const answerStream = input.config.llm.streamText({
messages: [
{
diff --git a/src/lib/agents/search/types.ts b/src/lib/agents/search/types.ts
index 421ee7f..82900c5 100644
--- a/src/lib/agents/search/types.ts
+++ b/src/lib/agents/search/types.ts
@@ -43,6 +43,7 @@ export type WidgetConfig = {
export type WidgetOutput = {
type: string;
+ llmContext: string;
data: any;
};
diff --git a/src/lib/agents/search/widgets/calculationWidget.ts b/src/lib/agents/search/widgets/calculationWidget.ts
index c613b40..1c1ba51 100644
--- a/src/lib/agents/search/widgets/calculationWidget.ts
+++ b/src/lib/agents/search/widgets/calculationWidget.ts
@@ -45,6 +45,7 @@ const calculationWidget: Widget = {
return {
type: 'calculation_result',
+ llmContext: `The result of the expression "${params.expression}" is ${result}.`,
data: {
expression: params.expression,
result: result,
@@ -53,6 +54,7 @@ const calculationWidget: Widget = {
} catch (error) {
return {
type: 'calculation_result',
+ llmContext: 'Failed to evaluate mathematical expression.',
data: {
expression: params.expression,
result: `Error evaluating expression: ${error}`,
diff --git a/src/lib/agents/search/widgets/stockWidget.ts b/src/lib/agents/search/widgets/stockWidget.ts
index b4f8b86..c18b734 100644
--- a/src/lib/agents/search/widgets/stockWidget.ts
+++ b/src/lib/agents/search/widgets/stockWidget.ts
@@ -286,120 +286,129 @@ You can set skipSearch to true if the stock widget can fully answer the user's q
chartData: {
'1D': chart1D
? {
- timestamps: chart1D.quotes.map((q: any) => q.date.getTime()),
- prices: chart1D.quotes.map((q: any) => q.close),
- }
+ timestamps: chart1D.quotes.map((q: any) => q.date.getTime()),
+ prices: chart1D.quotes.map((q: any) => q.close),
+ }
: null,
'5D': chart5D
? {
- timestamps: chart5D.quotes.map((q: any) => q.date.getTime()),
- prices: chart5D.quotes.map((q: any) => q.close),
- }
+ timestamps: chart5D.quotes.map((q: any) => q.date.getTime()),
+ prices: chart5D.quotes.map((q: any) => q.close),
+ }
: null,
'1M': chart1M
? {
- timestamps: chart1M.quotes.map((q: any) => q.date.getTime()),
- prices: chart1M.quotes.map((q: any) => q.close),
- }
+ timestamps: chart1M.quotes.map((q: any) => q.date.getTime()),
+ prices: chart1M.quotes.map((q: any) => q.close),
+ }
: null,
'3M': chart3M
? {
- timestamps: chart3M.quotes.map((q: any) => q.date.getTime()),
- prices: chart3M.quotes.map((q: any) => q.close),
- }
+ timestamps: chart3M.quotes.map((q: any) => q.date.getTime()),
+ prices: chart3M.quotes.map((q: any) => q.close),
+ }
: null,
'6M': chart6M
? {
- timestamps: chart6M.quotes.map((q: any) => q.date.getTime()),
- prices: chart6M.quotes.map((q: any) => q.close),
- }
+ timestamps: chart6M.quotes.map((q: any) => q.date.getTime()),
+ prices: chart6M.quotes.map((q: any) => q.close),
+ }
: null,
'1Y': chart1Y
? {
- timestamps: chart1Y.quotes.map((q: any) => q.date.getTime()),
- prices: chart1Y.quotes.map((q: any) => q.close),
- }
+ timestamps: chart1Y.quotes.map((q: any) => q.date.getTime()),
+ prices: chart1Y.quotes.map((q: any) => q.close),
+ }
: null,
MAX: chartMAX
? {
- timestamps: chartMAX.quotes.map((q: any) => q.date.getTime()),
- prices: chartMAX.quotes.map((q: any) => q.close),
- }
+ timestamps: chartMAX.quotes.map((q: any) => q.date.getTime()),
+ prices: chartMAX.quotes.map((q: any) => q.close),
+ }
: null,
},
comparisonData: comparisonData
? comparisonData.map((comp: any) => ({
- ticker: comp.ticker,
- name: comp.name,
- chartData: {
- '1D': comp.charts[0]
- ? {
- timestamps: comp.charts[0].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[0].quotes.map((q: any) => q.close),
- }
- : null,
- '5D': comp.charts[1]
- ? {
- timestamps: comp.charts[1].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[1].quotes.map((q: any) => q.close),
- }
- : null,
- '1M': comp.charts[2]
- ? {
- timestamps: comp.charts[2].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[2].quotes.map((q: any) => q.close),
- }
- : null,
- '3M': comp.charts[3]
- ? {
- timestamps: comp.charts[3].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[3].quotes.map((q: any) => q.close),
- }
- : null,
- '6M': comp.charts[4]
- ? {
- timestamps: comp.charts[4].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[4].quotes.map((q: any) => q.close),
- }
- : null,
- '1Y': comp.charts[5]
- ? {
- timestamps: comp.charts[5].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[5].quotes.map((q: any) => q.close),
- }
- : null,
- MAX: comp.charts[6]
- ? {
- timestamps: comp.charts[6].quotes.map((q: any) =>
- q.date.getTime(),
- ),
- prices: comp.charts[6].quotes.map((q: any) => q.close),
- }
- : null,
- },
- }))
+ ticker: comp.ticker,
+ name: comp.name,
+ chartData: {
+ '1D': comp.charts[0]
+ ? {
+ timestamps: comp.charts[0].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[0].quotes.map((q: any) => q.close),
+ }
+ : null,
+ '5D': comp.charts[1]
+ ? {
+ timestamps: comp.charts[1].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[1].quotes.map((q: any) => q.close),
+ }
+ : null,
+ '1M': comp.charts[2]
+ ? {
+ timestamps: comp.charts[2].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[2].quotes.map((q: any) => q.close),
+ }
+ : null,
+ '3M': comp.charts[3]
+ ? {
+ timestamps: comp.charts[3].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[3].quotes.map((q: any) => q.close),
+ }
+ : null,
+ '6M': comp.charts[4]
+ ? {
+ timestamps: comp.charts[4].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[4].quotes.map((q: any) => q.close),
+ }
+ : null,
+ '1Y': comp.charts[5]
+ ? {
+ timestamps: comp.charts[5].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[5].quotes.map((q: any) => q.close),
+ }
+ : null,
+ MAX: comp.charts[6]
+ ? {
+ timestamps: comp.charts[6].quotes.map((q: any) =>
+ q.date.getTime(),
+ ),
+ prices: comp.charts[6].quotes.map((q: any) => q.close),
+ }
+ : null,
+ },
+ }))
: null,
};
return {
type: 'stock',
+ llmContext: `Current price of ${stockData.shortName} (${stockData.symbol}) is ${stockData.regularMarketPrice} ${stockData.currency}. Other details: ${JSON.stringify({
+ marketState: stockData.marketState,
+ regularMarketChange: stockData.regularMarketChange,
+ regularMarketChangePercent: stockData.regularMarketChangePercent,
+ marketCap: stockData.marketCap,
+ peRatio: stockData.trailingPE,
+ dividendYield: stockData.dividendYield,
+ })}`,
data: stockData,
};
} catch (error: any) {
return {
type: 'stock',
+ llmContext: 'Failed to fetch stock data.',
data: {
error: `Error fetching stock data: ${error.message || error}`,
ticker: params.ticker,
diff --git a/src/lib/agents/search/widgets/weatherWidget.ts b/src/lib/agents/search/widgets/weatherWidget.ts
index 4b2dcf9..3d78df3 100644
--- a/src/lib/agents/search/widgets/weatherWidget.ts
+++ b/src/lib/agents/search/widgets/weatherWidget.ts
@@ -94,6 +94,7 @@ You can set skipSearch to true if the weather widget can fully answer the user's
return {
type: 'weather',
+ llmContext: `Weather in ${params.location} is ${weatherData.current}`,
data: {
location: params.location,
latitude: location.lat,
@@ -138,6 +139,7 @@ You can set skipSearch to true if the weather widget can fully answer the user's
return {
type: 'weather',
+ llmContext: `Weather in ${locationData.display_name} is ${weatherData.current}`,
data: {
location: locationData.display_name,
latitude: params.lat,
@@ -159,11 +161,13 @@ You can set skipSearch to true if the weather widget can fully answer the user's
return {
type: 'weather',
+ llmContext: 'No valid location or coordinates provided.',
data: null,
};
} catch (err) {
return {
type: 'weather',
+ llmContext: 'Failed to fetch weather data.',
data: {
error: `Error fetching weather data: ${err}`,
},