1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { useEffect, useState } from "https://esm.sh/react@18.2.0?dev";
3import { CreateProjectModal } from "./CreateProject.tsx";
4// Component for the loading spinner
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React from "https://esm.sh/react@18.2.0?dev";
3import { DirectoryTree } from "./DirectoryTree.tsx";
4import { LoadingSpinner } from "./LoadingSpinner.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { useLocalStorage } from "https://esm.sh/react-use?dev&deps=react@18.2.0&react-dom@18.2.0";
3import React, { useEffect, useRef, useState } from "https://esm.sh/react@18.2.0?dev";
4
5interface PreviewProps {
49
50 // Handle endpoint selection change
51 const handleEndpointChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
52 setSelectedEndpointIndex(Number(e.target.value));
53 };
54
55 // Handle path input change
56 const handlePathChange = (e: React.ChangeEvent<HTMLInputElement>) => {
57 setCustomPath(e.target.value);
58 };
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { useEffect, useState } from "https://esm.sh/react@18.2.0?dev";
3
4// Utility to format milliseconds into a readable time string
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { type Message } from "https://esm.sh/@ai-sdk/react?dev&deps=react@18.2.0&react-dom@18.2.0";
3import ReactMarkdown from "https://esm.sh/react-markdown?dev&deps=react@18.2.0&react-dom@18.2.0";
4import { ImagePreview } from "./ImageUpload.tsx";
5
48 // Use the triple backtick syntax for code blocks
49 const codeBlock = "```" + language + "\n" + content + "\n```";
50 return <ReactMarkdown>{codeBlock}</ReactMarkdown>;
51};
52
87
88export function MessagePart({ part }: { part: NonNullable<Message["parts"]>[number] }) {
89 if (part.type === "text") return <ReactMarkdown>{part.text}</ReactMarkdown>;
90 if (part.type === "reasoning")
91 return (
95 </summary>
96 <div>
97 <ReactMarkdown>{part.reasoning}</ReactMarkdown>
98 {part.details && part.details.map((detail, index) => (
99 <div key={index} className="mt-2">
100 <ReactMarkdown>{detail.text}</ReactMarkdown>
101 </div>
102 ))}
147 return (
148 <div className="think-content text-lg">
149 <ReactMarkdown>{args.thought}</ReactMarkdown>
150 </div>
151 );
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React from "https://esm.sh/react@18.2.0?dev";
3import { MessagePart } from "./MessagePart.tsx";
4import { MessageTimer } from "./MessageTimer.tsx";
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { useLocalStorage } from "https://esm.sh/react-use?dev&deps=react@18.2.0&react-dom@18.2.0";
3
4export function Login() {
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React from "https://esm.sh/react@18.2.0?dev";
3
4export const LoadingSpinner = () => (
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import { createRoot } from "https://esm.sh/react-dom@18.2.0/client?dev";
3import { App } from "./components/App.tsx";
4
1/** @jsxImportSource https://esm.sh/react@18.2.0?dev */
2import React, { useRef, useState } from "https://esm.sh/react@18.2.0?dev";
3
4// Maximum number of images that can be uploaded
15
16 // Handle file selection
17 const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
18 if (e.target.files) {
19 processFiles(Array.from(e.target.files));
74
75 {/* Expose the file input ref for external access */}
76 {React.cloneElement(<></>, { fileInputRef })}
77 </div>
78 );