Microwave AI is a chat‑based agent that helps users clean, validate, and enrich CSV contact lists.
The assistant uses Gemini 3, Supabase, and a Vercel Sandbox worker to generate and execute AI‑written scraping/enrichment code, while the UI is orchestrated through tool calls rendered inside the chat.
-
Frontend (Next.js App Router)
- Chat page:
app/chat/[id]/page.tsxfetches the conversation and messages from Supabase and rendersChatInterface. - Tool rendering:
components/chat/tool-renderer.tsxmaps AI tool calls to concrete React components:UploadComponent– CSV uploadDataSelector– enrichment optionsProgressTracker– job statusEnrichedDataTable– results table for a jobDownloadButton– download enriched CSV
- Chat page:
-
AI Agent (Chat & Tools)
- System prompt:
lib/ai/system-prompt.ts- Specializes the agent in contact‑list cleaning and enrichment.
- Defines strict workflow rules (always call tools, never fabricate CSV paths or configs).
- Chat endpoint:
app/api/chat/route.ts- Uses
google(gemini-3-*)via theaiSDK. - Applies
SYSTEM_PROMPTand exposes thetoolsfromlib/ai/tools.ts. - Streams responses to the UI and persists messages + conversation metadata in Supabase.
- Uses
- System prompt:
-
Enrichment Orchestrator
- Tool definitions:
lib/ai/tools.tsshowUploadComponent– ask UI to show CSV upload.showDataSelector– show enrichment choices.startEnrichment– create a job, normalize CSV path, and trigger the enrichment pipeline.showProgressTracker/checkJobProgress– show or fetch job status.showDataTable– tell the UI to display job results.showDownloadButton– show download CTA for a finished job.
- AI Coding Agent:
lib/enrichment/ai-coding-agent.ts- Class
AiCodingAgentusesgoogle('gemini-3-pro-preview')and a dedicated coding system prompt. - For each active enrichment type (
linkedin,website,custom):- Builds a prompt from
csvSample,csvPath, and the enrichment config. - Uses tools (
getApifyDocs,getFirecrawlDocs,getDownloadLink,getUploadLink) to discover APIs and get signed URLs from Supabase. - Generates JavaScript code that:
- Downloads input CSV from Supabase.
- Calls external services (Apify, Firecrawl) using provided API keys.
- Writes an enriched CSV to Supabase (typically
*-enriched.csv).
- Runs the code in a sandbox and retries on runtime errors.
- Builds a prompt from
- Class
- Sandbox Worker:
lib/sandbox/worker.tsSandboxWorkerreceives aWorkerContextwith:jobId,csvPath,enrichmentType,generatedCode, Supabase credentials, and external API tokens.
- Flow:
- Creates a Vercel
Sandboxusing a Puppeteer‑ready snapshot. - Writes the AI‑generated code to
/vercel/sandbox/enrichment.js. - Starts it in the background and tails
/vercel/sandbox/enrichment.log. - Parses
PROGRESS: {...}lines from logs to update thejobstable (status,processed_rows,progress). - Searches the log for a final JSON line with
{ success: boolean, ... }and returns it to the orchestrator.
- Creates a Vercel
- The worker never marks the job as completed itself; it reports progress and results back to the orchestrator.
- Tool definitions:
-
Backend API Routes
- Start enrichment (fire‑and‑forget):
app/api/enrich/route.tsPOST /api/enrichaccepts{ jobId, request }, whererequestis aStartEnrichmentRequest.- Marks the job as
processing, callsaiCodingAgent.enrichData(...), and then:- Optionally uploads
result.enrichedCsvas a new file and links it to the job. - Or finds / creates a
filesrecord for anyoutputPathreturned by enrichment steps. - Updates the
jobsrow withstatus='completed',progress=100, and a serializedresult.
- Optionally uploads
- Response is
202 Accepted; the heavy work runs in the background.
- Job status:
app/api/job/[id]/status/route.tsGET /api/job/:id/status(auth‑protected).- Returns
status,progress,processedRows,totalRows,errorMessage, andresult. - Used by
ProgressTrackerand thecheckJobProgresstool.
- Download enriched CSV:
app/api/job/[id]/download/route.tsGET /api/job/:id/download(auth + job ownership required).- Locates the output via:
job.output_file_id→files.storage_path, orjob.result.enrichments[*].outputPath/output_path/output.path, orjob.result.enrichedCsv(streams inline), or- Fallback
job.config.csvPath→*-enriched.csv.
- Returns a short‑lived Supabase signed URL or a streamed CSV download.
- Start enrichment (fire‑and‑forget):
- File:
app/chat/[id]/page.tsx - Flow
- User navigates to
/chat/:id. - Page:
- Verifies the Supabase user (redirects to
/loginif missing). - Loads the conversation and messages from the database.
- Renders
ChatInterfacewithinitialMessagesand the tool invocation stream.
- Verifies the Supabase user (redirects to
- User navigates to
- System behavior (from
lib/ai/system-prompt.ts):- When the user mentions uploading / cleaning / enriching a CSV:
- The agent must call
showUploadComponentimmediately (no “please upload below” text‑only UX).
- The agent must call
- After file upload:
- Agent analyzes the sample, explains what it sees, and then calls
showDataSelector.
- Agent analyzes the sample, explains what it sees, and then calls
- After the user confirms their selections:
- Agent extracts:
csvPathand sample rows/columns from the actual upload tool response.- The exact
configobject from theselectEnrichmentscallback (no modifications).
- Calls
startEnrichmentonce with these real values.
- Agent extracts:
- When the user mentions uploading / cleaning / enriching a CSV:
- Tool:
startEnrichmentinlib/ai/tools.ts- Validates the logged‑in user via
getCurrentUser. - Normalizes
csvPath:- Cross‑checks Supabase
filesfor the user. - Verifies the path exists in
csv-files. - Prefers an existing
*-enriched.csvas the new input, if present.
- Cross‑checks Supabase
- Creates a
jobsrow viacreateJob('data_enrichment', { ... })withconfigthat includes the resolvedcsvPath. - Reads
FIRECRAWL_API_KEYandAPIFY_API_TOKENfrom the environment. - Calls the fire‑and‑forget
/api/enrichendpoint with{ jobId, request }. - Returns a tool result with:
type: 'progress'jobId- Initial tasks (LinkedIn, Website, Custom) set to
pending.
- Validates the logged‑in user via
- UI:
ToolRendererreceives thestartEnrichmenttool result withtype: 'progress'.- Renders
ProgressTrackerfor the returnedjobId.
- Component:
components/chat/tools/progress-tracker.tsx- Auto‑polls
GET /api/job/:id/statusevery few seconds until the job is completed or failed. - Displays:
- Overall progress bar.
- Per‑task chips (LinkedIn, Website, Custom) and statuses.
- Processed vs total rows, lightweight ETA estimate, and error messages.
- When the backend marks the job as
completed:- Sends a message back to the agent (via
onMessage) instructing it to show the data table and explaining thatjobIdshould be reused for later table/download actions.
- Sends a message back to the agent (via
- Auto‑polls
- Tool:
showDataTableinlib/ai/tools.ts- The agent calls this tool with the
jobIdand an optional message. ToolRendererresponds by renderingEnrichedDataTable.
- The agent calls this tool with the
- Data grid UI:
components/chat/tools/data-table.tsx- Generic, column‑driven
@tanstack/react-tableimplementation. - Features:
- Sortable column headers.
- Global search across all fields.
- Pagination with row counts and page navigation.
- Optional summary stats (cleaned / enriched / failed).
- Optional
onDownloadcallback for direct CSV download.
- The backing API that serves actual row data lives elsewhere; this component focuses purely on rendering behavior and controls.
- Generic, column‑driven
- Tool:
showDownloadButtoninlib/ai/tools.ts- The agent calls this when the user is satisfied with the results.
ToolRendererrendersDownloadButton, which:- Calls
GET /api/job/:id/download. - Receives
{ downloadUrl, fileName }. - Creates a temporary
<a>element and triggers a browser download.
- Calls
- Additionally,
ToolRendererhandlesstartEnrichmentmessages of typeenrichment_completeby:- Showing a compact summary of enrichments and columns added.
- Rendering another
DownloadButtonwired to the same download logic.
-
Agent behavior
lib/ai/system-prompt.ts– natural‑language spec for the assistant’s role and tool usage rules.lib/ai/tools.ts– structured tool definitions consumed by theaiSDK and the UI.
-
Chat & conversations
app/api/chat/route.ts– Gemini 3 streaming chat endpoint with tools and system prompt.app/chat/[id]/page.tsx– server component that gates access and initializes the chat UI.
-
Enrichment pipeline
lib/enrichment/ai-coding-agent.ts– orchestrates AI code generation + sandbox execution for each enrichment type.lib/sandbox/worker.ts– Vercel Sandbox integration, job log parsing, and progress updates into Supabase.app/api/enrich/route.ts– background job entrypoint and job finalization logic.app/api/job/[id]/status/route.ts– job progress polling API.app/api/job/[id]/download/route.ts– secure download API for the enriched CSV.
-
UI tools
components/chat/tool-renderer.tsx– maps tool names → UI components and handles tool result lifecycles.components/chat/tools/progress-tracker.tsx– live job progress visualization + callbacks back to the agent.components/chat/tools/data-table.tsx– generic, searchable, paginated data grid for job results.
- Node.js: v18+ recommended.
- Supabase project with:
- Auth (users)
- Tables such as
conversations,messages,jobs, andfiles - Storage bucket
csv-files
- External APIs
- Apify account and token
- Firecrawl API key
- Vercel Sandbox / Puppeteer snapshot configured (for
PUPPETEER_SNAPSHOT_ID)
Set these in your .env.local (and in Vercel for production):
- Supabase
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_ANON_KEYSUPABASE_SERVICE_ROLE_KEY
- AI / Models
GOOGLE_GENERATIVE_AI_API_KEY(for Gemini 3 via@ai-sdk/google)
- Enrichment / scraping
APIFY_API_TOKENFIRECRAWL_API_KEY
- Sandbox / Vercel
PUPPETEER_SNAPSHOT_IDVERCEL_URL(automatically set in production; used bystartEnrichmentto call/api/enrich)
Install dependencies and run the dev server:
npm install
npm run devThen open http://localhost:3000 in your browser and log in via Supabase auth to start a conversation.
- Tool discipline: The agent is designed to always use tools for UI actions (upload, data selection, progress, tables, downloads). Avoid adding text‑only flows that bypass these tools.
- Job lifecycle:
- The sandbox worker only moves jobs between
processingandfailedand updatesprocessed_rows/progress. - The orchestrator in
/api/enrichis responsible for marking jobscompletedand attaching output files.
- The sandbox worker only moves jobs between
- Extending enrichment types:
- Add new flags to the enrichment config (
EnrichmentConfig+startEnrichmentschema). - Update
ai-coding-agentto include a newtypeand instructions. - Ensure the generated code writes either:
enrichedCsvto logs, oroutputPath/output_pathin the final JSON result, so download discovery continues to work.
- Add new flags to the enrichment config (