import { Suspense, useCallback, useEffect, useRef, useState } from "react"; import { useAgent } from "agents/react"; import { useAgentChat } from "@cloudflare/ai-chat/react"; import { isToolUIPart } from "ai"; import { Button, Surface, Text, InputArea, Empty, Badge } from "@cloudflare/kumo"; import { PaperPlaneRightIcon, TrashIcon, LightningIcon, CaretRightIcon, CheckCircleIcon, WarningCircleIcon, CircleNotchIcon, CodeIcon, TerminalIcon } from "@phosphor-icons/react"; import { Streamdown } from "streamdown"; import { DemoWrapper } from "../../layout"; import { ConnectionStatus, CodeExplanation, type CodeSection } from "../../components"; import { useUserId } from "../../hooks"; const codeSections: CodeSection[] = [ { title: "AI-powered code generation", description: "Codemode uses an AI model to generate and edit code based on natural language prompts. The generated code runs in a sandboxed environment.", code: `import { AIChatAgent } from "@cloudflare/ai-chat"; import { createCodeTool } from "@cloudflare/codemode/ai"; class CodemodeAgent extends AIChatAgent { async onChatMessage(onFinish) { const result = streamText({ model: workersai("@cf/moonshotai/kimi-k2.5"), messages: this.messages, tools: { code: createCodeTool(this.env), }, onFinish, }); return result.toDataStreamResponse(); } }` } ]; interface ToolPart { type: string; toolCallId?: string; state?: string; errorText?: string; input?: Record; output?: { code?: string; result?: unknown; logs?: string[]; [key: string]: unknown; }; } function extractFunctionCalls(code?: string): string[] { if (!code) return []; const matches = code.match(/codemode\.(\w+)/g); if (!matches) return []; return [...new Set(matches.map((m) => m.replace("codemode.", "")))]; } function ToolCard({ toolPart }: { toolPart: ToolPart }) { const [expanded, setExpanded] = useState(false); const hasError = toolPart.state === "output-error" || !!toolPart.errorText; const isComplete = toolPart.state === "output-available"; const isRunning = !isComplete && !hasError; const functionCalls = extractFunctionCalls( toolPart.output?.code || (toolPart.input?.code as string) ); const summary = functionCalls.length > 0 ? functionCalls.join(", ") : "code execution"; return ( {expanded && (
{toolPart.output?.code && (
Code
                {toolPart.output.code}
              
)} {toolPart.output?.result !== undefined && (
Result
                {JSON.stringify(toolPart.output.result, null, 2)}
              
)} {toolPart.output?.logs && toolPart.output.logs.length > 0 && (
Console
                {toolPart.output.logs.join("\n")}
              
)} {toolPart.errorText && (
Error
                {toolPart.errorText}
              
)}
)}
); } function CodemodeUI() { const userId = useUserId(); const [connectionStatus, setConnectionStatus] = useState< "connected" | "connecting" | "disconnected" >("connecting"); const [input, setInput] = useState(""); const messagesContainerRef = useRef(null); const agent = useAgent({ agent: "CodemodeAgent", name: `codemode-demo-${userId}`, onOpen: useCallback(() => setConnectionStatus("connected"), []), onClose: useCallback(() => setConnectionStatus("disconnected"), []), onError: useCallback(() => setConnectionStatus("disconnected"), []) }); const { messages, sendMessage, clearHistory, status } = useAgentChat({ agent }); const isStreaming = status === "streaming"; const isConnected = connectionStatus === "connected"; useEffect(() => { const el = messagesContainerRef.current; if (el) el.scrollTop = el.scrollHeight; }, [messages]); const send = useCallback(() => { const text = input.trim(); if (!text || isStreaming) return; setInput(""); sendMessage({ role: "user", parts: [{ type: "text", text }] }); }, [input, isStreaming, sendMessage]); return ( Instead of calling tools one at a time, the LLM writes and executes code that orchestrates multiple tools together. This lets the model compose complex operations — loops, conditionals, data transformations — that would be impossible with single tool calls. The generated code runs in a sandboxed environment. } statusIndicator={} >
CodeAct pattern Dynamic Worker sandbox
{messages.length === 0 && ( } title="Try Codemode" description={ 'Try "What is 17 + 25?", "Get weather in London and Paris", ' + 'or "Create a project called Alpha and list all projects"' } /> )} {messages.map((message, index) => { const isUser = message.role === "user"; const isLastAssistant = message.role === "assistant" && index === messages.length - 1; const isAnimating = isStreaming && isLastAssistant; if (isUser) { return (
{message.parts .filter((p) => p.type === "text") .map((p) => (p.type === "text" ? p.text : "")) .join("")}
); } return (
{message.parts.map((part, partIdx) => { if (part.type === "text") { if (!part.text || part.text.trim() === "") return null; return (
{part.text}
); } if (part.type === "step-start") return null; if (isToolUIPart(part)) { const toolPart = part as unknown as ToolPart; return (
); } return null; })}
); })}
{ e.preventDefault(); send(); }} >
{ if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); send(); } }} placeholder={ isConnected ? "Ask me to calculate, check weather, manage projects..." : "Connecting to agent..." } disabled={!isConnected || isStreaming} rows={2} className="flex-1 ring-0! focus:ring-0! shadow-none! bg-transparent! outline-none!" />
); } export function CodemodeDemo() { return (
Loading codemode demo...
} >
); }