Coding Assistant (POC)
This example demonstrates how to use Vapi assistant to generate code and update the state of code in sandpack to make a live coding assistant.
Preview
Coding Assistant
Conversation
Code
Copy the following code to your component file for example ai-coder.tsx.
import React, { useEffect, useState } from "react";
import {
SandpackProvider,
SandpackPreview,
useSandpack,
SandpackLayout,
SandpackStack,
FileTabs,
} from "@codesandbox/sandpack-react";
import Editor from "@monaco-editor/react";
import useVapi from "@/hooks/code-assistant";
interface LayoutProps {
children: React.ReactNode;
}
const Layout: React.FC<LayoutProps> = ({ children }) => (
<div className="flex flex-col items-center p-4 min-h-full w-full">
<div className="w-full">{children}</div>
</div>
);
interface TranscriberProps {
conversation: Array<{ role: string; text: string; timestamp: string }>;
}
const Transcriber: React.FC<TranscriberProps> = ({ conversation }) => (
<div className="p-4 border-t-2 mt-4">
<h2 className="text-lg font-semibold">Conversation</h2>
<div className="max-h-64 overflow-y-auto">
{conversation.map((msg, index) => (
<div key={index} className="mt-2">
<strong>{msg.role}:</strong> {msg.text}{" "}
<span className="text-gray-500 text-xs">{msg.timestamp}</span>
</div>
))}
</div>
</div>
);
interface MonacoEditorProps {
code: string;
}
const getLanguageOfFile = (filePath: string) => {
const ext = filePath.split('.').pop();
switch (ext) {
case 'js':
case 'jsx':
return 'javascript';
case 'ts':
case 'tsx':
return 'typescript';
case 'vue':
return 'vue';
case 'html':
return 'html';
case 'css':
return 'css';
case 'json':
return 'json';
default:
return 'plaintext';
}
};
const MonacoEditor: React.FC<MonacoEditorProps> = ({ code }) => {
const { sandpack } = useSandpack();
const language = getLanguageOfFile(sandpack.activeFile);
return (
<SandpackStack style={{ height: "50vh", margin: 0 }}>
<FileTabs />
<div style={{ flex: 1, paddingTop: 8 }}>
<Editor
width="100%"
height="100%"
language={language}
theme="vs-dark"
value={code}
/>
</div>
</SandpackStack>
);
};
const VapiDemoComponent: React.FC = () => {
const { isSessionActive, conversation, toggleCall, code } = useVapi();
const [showSandpack, setShowSandpack] = useState(false);
useEffect(() => {
if (code && code.length > 5) {
setShowSandpack(true);
}
}, [code]);
const files = {
"/pages/index.js": code,
};
return (
<Layout>
<div className="flex justify-between items-center p-4 w-full">
<h1 className="text-xl font-bold">Coding Assistant</h1>
<button
className={`px-4 py-2 rounded ${isSessionActive ? "bg-red-500" : "bg-green-500"} text-white`}
onClick={toggleCall}
>
{isSessionActive ? "Stop Call" : "Start Call"}
</button>
</div>
{showSandpack && code && (
<div className="mt-4 min-h-5xl w-full">
<SandpackProvider template="nextjs" files={files}>
<SandpackLayout>
<MonacoEditor code={code} />
<SandpackPreview style={{ height: "50vh" }} />
</SandpackLayout>
</SandpackProvider>
</div>
)}
<Transcriber conversation={conversation} />
</Layout>
);
};
export default VapiDemoComponent;