Improve chat navigation, model selection, and streaming

This commit is contained in:
Rami Bitar
2026-09-16 13:14:55 -04:00
parent 8790cfb1e2
commit dd04493e25
73 changed files with 1272 additions and 1367 deletions
@@ -0,0 +1,46 @@
import { tool } from 'ai';
import { z } from 'zod';
export const firecrawlWebFetch = tool({
description:
'Fetch a web page and return its content as markdown. Use this tool when the user asks to read, summarize, or extract information from a URL.',
inputSchema: z.object({
url: z.string().url().describe('The URL of the web page to fetch'),
}),
execute: async ({ url }, { abortSignal }) => {
try {
const response = await fetch('https://api.firecrawl.dev/v1/scrape', {
method: 'POST',
signal: abortSignal,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY!}`,
},
body: JSON.stringify({
url,
formats: ['markdown'],
}),
});
if (!response.ok) {
const errorText = await response.text();
return { success: false, error: `Firecrawl API error: ${errorText}` };
}
const data = await response.json();
if (!data?.data?.markdown) {
return { success: false, error: 'No content retrieved for this URL' };
}
return { success: true, markdown: data.data.markdown };
} catch (error) {
console.error('Error fetching web page:', error);
return {
success: false,
error:
error instanceof Error ? error.message : 'Failed to fetch web page',
};
}
},
});
@@ -0,0 +1,53 @@
import { tool } from 'ai';
import { z } from 'zod';
export const firecrawlWebSearch = tool({
description:
'Search the web and return results as markdown. Use this tool when the user asks to search for information on the web.',
inputSchema: z.object({
query: z.string().describe('The search query'),
limit: z
.number()
.min(1)
.max(10)
.default(3)
.describe('Number of results to return (max 10)'),
}),
execute: async ({ query, limit }, { abortSignal }) => {
try {
const response = await fetch('https://api.firecrawl.dev/v1/search', {
method: 'POST',
signal: abortSignal,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.FIRECRAWL_API_KEY!}`,
},
body: JSON.stringify({
query,
limit,
scrapeOptions: { formats: ['markdown'] },
}),
});
if (!response.ok) {
const errorText = await response.text();
return { success: false, error: `Firecrawl API error: ${errorText}` };
}
const data = await response.json();
if (!data?.success || !data?.data) {
return { success: false, error: 'No results found for this query' };
}
return { success: true, results: data.data };
} catch (error) {
console.error('Error searching web:', error);
return {
success: false,
error:
error instanceof Error ? error.message : 'Failed to search the web',
};
}
},
});
+8
View File
@@ -0,0 +1,8 @@
import { firecrawlWebFetch } from './firecrawl-web-fetch';
import { firecrawlWebSearch } from './firecrawl-web-search';
// Keep these keys stable: saved conversations reference tool names.
export const chatTools = {
firecrawlWebSearch,
firecrawlWebFetch,
};