import { Firecrawl } from 'firecrawl';import { ChatOpenAI } from '@langchain/openai';import { StateGraph, Annotation, START, END } from '@langchain/langgraph';const firecrawl = new Firecrawl({ apiKey: process.env.FIRECRAWL_API_KEY });const llm = new ChatOpenAI({ model: "gpt-5-nano", apiKey: process.env.OPENAI_API_KEY });// Define o estado personalizadoconst WorkflowState = Annotation.Root({ urls: Annotation<string[]>(), scrapedData: Annotation<Array<{ url: string; content: string }>>(), summary: Annotation<string>()});// Faz scrape de múltiplas URLsasync function scrapeMultiple(state: typeof WorkflowState.State) { const scrapedData = []; for (const url of state.urls) { const result = await firecrawl.scrape(url, { formats: ['markdown'] }); scrapedData.push({ url, content: result.markdown || '' }); } return { scrapedData };}// Resume todo o conteúdo coletadoasync function summarizeAll(state: typeof WorkflowState.State) { const combinedContent = state.scrapedData .map(item => `Content from ${item.url}:\n${item.content}`) .join('\n\n'); const response = await llm.invoke([ { role: "user", content: `Summarize these websites:\n${combinedContent}` } ]); return { summary: response.content as string };}// Constrói o grafo do fluxo de trabalhoconst workflow = new StateGraph(WorkflowState) .addNode("scrape", scrapeMultiple) .addNode("summarize", summarizeAll) .addEdge(START, "scrape") .addEdge("scrape", "summarize") .addEdge("summarize", END);const app = workflow.compile();// Executa o fluxo de trabalhoconst result = await app.invoke({ urls: ["https://firecrawl.dev", "https://firecrawl.dev/pricing"]});console.log(result.summary);