client/components/ToolPanel.jsx (122 lines of code) (raw):
import { useEffect, useState } from "react";
const functionDescription = `
Call this function when a user asks for a color palette.
`;
const sessionUpdate = {
type: "session.update",
session: {
tools: [
{
type: "function",
name: "display_color_palette",
description: functionDescription,
parameters: {
type: "object",
strict: true,
properties: {
theme: {
type: "string",
description: "Description of the theme for the color scheme.",
},
colors: {
type: "array",
description: "Array of five hex color codes based on the theme.",
items: {
type: "string",
description: "Hex color code",
},
},
},
required: ["theme", "colors"],
},
},
],
tool_choice: "auto",
},
};
function FunctionCallOutput({ functionCallOutput }) {
const { theme, colors } = JSON.parse(functionCallOutput.arguments);
const colorBoxes = colors.map((color) => (
<div
key={color}
className="w-full h-16 rounded-md flex items-center justify-center border border-gray-200"
style={{ backgroundColor: color }}
>
<p className="text-sm font-bold text-black bg-slate-100 rounded-md p-2 border border-black">
{color}
</p>
</div>
));
return (
<div className="flex flex-col gap-2">
<p>Theme: {theme}</p>
{colorBoxes}
<pre className="text-xs bg-gray-100 rounded-md p-2 overflow-x-auto">
{JSON.stringify(functionCallOutput, null, 2)}
</pre>
</div>
);
}
export default function ToolPanel({
isSessionActive,
sendClientEvent,
events,
}) {
const [functionAdded, setFunctionAdded] = useState(false);
const [functionCallOutput, setFunctionCallOutput] = useState(null);
useEffect(() => {
if (!events || events.length === 0) return;
const firstEvent = events[events.length - 1];
if (!functionAdded && firstEvent.type === "session.created") {
sendClientEvent(sessionUpdate);
setFunctionAdded(true);
}
const mostRecentEvent = events[0];
if (
mostRecentEvent.type === "response.done" &&
mostRecentEvent.response.output
) {
mostRecentEvent.response.output.forEach((output) => {
if (
output.type === "function_call" &&
output.name === "display_color_palette"
) {
setFunctionCallOutput(output);
setTimeout(() => {
sendClientEvent({
type: "response.create",
response: {
instructions: `
ask for feedback about the color palette - don't repeat
the colors, just ask if they like the colors.
`,
},
});
}, 500);
}
});
}
}, [events]);
useEffect(() => {
if (!isSessionActive) {
setFunctionAdded(false);
setFunctionCallOutput(null);
}
}, [isSessionActive]);
return (
<section className="h-full w-full flex flex-col gap-4">
<div className="h-full bg-gray-50 rounded-md p-4">
<h2 className="text-lg font-bold">Color Palette Tool</h2>
{isSessionActive ? (
functionCallOutput ? (
<FunctionCallOutput functionCallOutput={functionCallOutput} />
) : (
<p>Ask for advice on a color palette...</p>
)
) : (
<p>Start the session to use this tool...</p>
)}
</div>
</section>
);
}