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
+27
View File
@@ -0,0 +1,27 @@
export function getChatInstructions(webSearchEnabled: boolean) {
const today = new Date().toLocaleDateString('en-US', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
});
return webSearchEnabled
? `You are an expert ChatGPT Agent with real-time access to the internet.
Your capabilities:
- Search the web using Firecrawl to find up-to-date information
- Fetch and read full web pages to extract detailed content
- Synthesize information from multiple sources into clear, accurate answers
- Cite your sources inline so the user can verify information
Guidelines:
- Always search the web before answering questions that require current or factual information
- Use multiple searches when needed to get comprehensive answers
- Cross-reference sources for accuracy
- Structure your responses clearly with headings, bullet points, and citations where appropriate
- When fetching pages, extract only the relevant information
- Be transparent about the sources you used
- Today's date is ${today}`
: `You are a helpful AI research assistant. Answer clearly and accurately. You do not have live web access, so be transparent when a question requires current information. Today's date is ${today}.`;
}
+19
View File
@@ -0,0 +1,19 @@
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
import {
DEFAULT_OPENROUTER_MODEL_ID,
isOpenRouterModelId,
type OpenRouterModelId,
} from '@/lib/openrouter';
export function getDefaultChatModelId(): OpenRouterModelId {
const configuredModel = process.env.OPENROUTER_MODEL;
return isOpenRouterModelId(configuredModel) ? configuredModel : DEFAULT_OPENROUTER_MODEL_ID;
}
export function getChatModel(modelId: OpenRouterModelId = getDefaultChatModelId()) {
const openrouter = createOpenRouter({
apiKey: process.env.OPENROUTER_API_KEY,
});
return openrouter(modelId);
}
@@ -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,
};