chore: pnpm lint fix

ran pnpm lint fix and fixed all lint errors
This commit is contained in:
Dustin Loring 2025-01-16 10:47:18 -05:00 committed by GitHub
commit bc5b798760
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
35 changed files with 116 additions and 97 deletions

View File

@ -1,15 +1,14 @@
import type { Message } from 'ai'; import type { Message } from 'ai';
import React, { type RefCallback } from 'react'; import React, { type RefCallback } from 'react';
import { ClientOnly } from 'remix-utils/client-only'; import { ClientOnly } from 'remix-utils/client-only';
import styles from './BaseChat.module.scss';
import FilePreview from './FilePreview';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';
import { Menu } from '~/components/sidebar/Menu.client'; import { Menu } from '~/components/sidebar/Menu.client';
import { IconButton } from '~/components/ui/IconButton'; import { IconButton } from '~/components/ui/IconButton';
import { Workbench } from '~/components/workbench/Workbench.client'; import { Workbench } from '~/components/workbench/Workbench.client';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { Messages } from './Messages.client';
import { SendButton } from './SendButton.client';
import FilePreview from './FilePreview';
import styles from './BaseChat.module.scss';
interface BaseChatProps { interface BaseChatProps {
textareaRef?: React.RefObject<HTMLTextAreaElement> | undefined; textareaRef?: React.RefObject<HTMLTextAreaElement> | undefined;
@ -208,7 +207,12 @@ export const BaseChat = React.forwardRef<HTMLDivElement, BaseChatProps>(
<FilePreview <FilePreview
files={files} files={files}
imageDataList={imageDataList || []} imageDataList={imageDataList || []}
onRemove={onRemoveFile || (() => {})} onRemove={
onRemoveFile ||
function noop() {
/* no-op */
}
}
/> />
</div> </div>
)} )}

View File

@ -4,6 +4,7 @@ import { useChat } from 'ai/react';
import { useAnimate } from 'framer-motion'; import { useAnimate } from 'framer-motion';
import { memo, useEffect, useRef, useState } from 'react'; import { memo, useEffect, useRef, useState } from 'react';
import { cssTransition, toast, ToastContainer } from 'react-toastify'; import { cssTransition, toast, ToastContainer } from 'react-toastify';
import { BaseChat } from './BaseChat';
import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks'; import { useMessageParser, usePromptEnhancer, useShortcuts, useSnapScroll } from '~/lib/hooks';
import { useChatHistory } from '~/lib/persistence'; import { useChatHistory } from '~/lib/persistence';
import { chatStore } from '~/lib/stores/chat'; import { chatStore } from '~/lib/stores/chat';
@ -11,7 +12,6 @@ import { workbenchStore } from '~/lib/stores/workbench';
import { fileModificationsToHTML } from '~/utils/diff'; import { fileModificationsToHTML } from '~/utils/diff';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { createScopedLogger, renderLogger } from '~/utils/logger'; import { createScopedLogger, renderLogger } from '~/utils/logger';
import { BaseChat } from './BaseChat';
const toastAnimation = cssTransition({ const toastAnimation = cssTransition({
enter: 'animated fadeInRight', enter: 'animated fadeInRight',
@ -151,9 +151,10 @@ export const ChatImpl = memo(({ initialMessages, storeMessageHistory }: ChatProp
const handleFileUpload = (fileList: FileList) => { const handleFileUpload = (fileList: FileList) => {
const newFiles = Array.from(fileList); const newFiles = Array.from(fileList);
setFiles((prevFiles) => [...prevFiles, ...newFiles]); setFiles((prevFiles) => [...prevFiles, ...newFiles]);
newFiles.forEach((file) => { newFiles.forEach((file) => {
const reader = new FileReader(); const reader = new FileReader();
reader.onloadend = () => { reader.onloadend = () => {
setImageDataList((prev) => [...prev, reader.result as string]); setImageDataList((prev) => [...prev, reader.result as string]);
}; };

View File

@ -1,10 +1,9 @@
import { memo, useEffect, useState } from 'react'; import { memo, useEffect, useState } from 'react';
import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki'; import { bundledLanguages, codeToHtml, isSpecialLang, type BundledLanguage, type SpecialLanguage } from 'shiki';
import styles from './CodeBlock.module.scss';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { createScopedLogger } from '~/utils/logger'; import { createScopedLogger } from '~/utils/logger';
import styles from './CodeBlock.module.scss';
const logger = createScopedLogger('CodeBlock'); const logger = createScopedLogger('CodeBlock');
interface CodeBlockProps { interface CodeBlockProps {

View File

@ -32,4 +32,4 @@ const FilePreview: React.FC<FilePreviewProps> = ({ files, imageDataList, onRemov
); );
}; };
export default FilePreview; export default FilePreview;

View File

@ -1,12 +1,12 @@
import { memo, useMemo } from 'react'; import { memo, useMemo } from 'react';
import ReactMarkdown, { type Components } from 'react-markdown'; import ReactMarkdown, { type Components } from 'react-markdown';
import type { BundledLanguage } from 'shiki'; import type { BundledLanguage } from 'shiki';
import { createScopedLogger } from '~/utils/logger';
import { rehypePlugins, remarkPlugins, allowedHTMLElements } from '~/utils/markdown';
import { Artifact } from './Artifact'; import { Artifact } from './Artifact';
import { CodeBlock } from './CodeBlock'; import { CodeBlock } from './CodeBlock';
import styles from './Markdown.module.scss'; import styles from './Markdown.module.scss';
import { createScopedLogger } from '~/utils/logger';
import { rehypePlugins, remarkPlugins, allowedHTMLElements } from '~/utils/markdown';
const logger = createScopedLogger('MarkdownComponent'); const logger = createScopedLogger('MarkdownComponent');

View File

@ -1,8 +1,8 @@
import type { Message } from 'ai'; import type { Message } from 'ai';
import React from 'react'; import React from 'react';
import { classNames } from '~/utils/classNames';
import { AssistantMessage } from './AssistantMessage'; import { AssistantMessage } from './AssistantMessage';
import { UserMessage } from './UserMessage'; import { UserMessage } from './UserMessage';
import { classNames } from '~/utils/classNames';
interface MessagesProps { interface MessagesProps {
id?: string; id?: string;

View File

@ -1,5 +1,5 @@
import { modificationsRegex } from '~/utils/diff';
import { Markdown } from './Markdown'; import { Markdown } from './Markdown';
import { modificationsRegex } from '~/utils/diff';
interface MessageContent { interface MessageContent {
type: string; type: string;
@ -18,7 +18,11 @@ export function UserMessage({ content }: UserMessageProps) {
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
{content.map((item, index) => { {content.map((item, index) => {
if (item.type === 'text') { if (item.type === 'text') {
return <Markdown key={index} limitedMarkdown>{sanitizeUserMessage(item.text || '')}</Markdown>; return (
<Markdown key={index} limitedMarkdown>
{sanitizeUserMessage(item.text || '')}
</Markdown>
);
} else if (item.type === 'image') { } else if (item.type === 'image') {
return ( return (
<div key={index} className="max-w-[300px]"> <div key={index} className="max-w-[300px]">
@ -26,6 +30,7 @@ export function UserMessage({ content }: UserMessageProps) {
</div> </div>
); );
} }
return null; return null;
})} })}
</div> </div>

View File

@ -17,14 +17,14 @@ import {
type Tooltip, type Tooltip,
} from '@codemirror/view'; } from '@codemirror/view';
import { memo, useEffect, useRef, useState, type MutableRefObject } from 'react'; import { memo, useEffect, useRef, useState, type MutableRefObject } from 'react';
import type { Theme } from '~/types/theme';
import { classNames } from '~/utils/classNames';
import { debounce } from '~/utils/debounce';
import { createScopedLogger, renderLogger } from '~/utils/logger';
import { BinaryContent } from './BinaryContent'; import { BinaryContent } from './BinaryContent';
import { getTheme, reconfigureTheme } from './cm-theme'; import { getTheme, reconfigureTheme } from './cm-theme';
import { indentKeyBinding } from './indent'; import { indentKeyBinding } from './indent';
import { getLanguage } from './languages'; import { getLanguage } from './languages';
import type { Theme } from '~/types/theme';
import { classNames } from '~/utils/classNames';
import { debounce } from '~/utils/debounce';
import { createScopedLogger, renderLogger } from '~/utils/logger';
const logger = createScopedLogger('CodeMirrorEditor'); const logger = createScopedLogger('CodeMirrorEditor');

View File

@ -1,8 +1,8 @@
import { Compartment, type Extension } from '@codemirror/state'; import { Compartment, type Extension } from '@codemirror/state';
import { EditorView } from '@codemirror/view'; import { EditorView } from '@codemirror/view';
import { vscodeDark, vscodeLight } from '@uiw/codemirror-theme-vscode'; import { vscodeDark, vscodeLight } from '@uiw/codemirror-theme-vscode';
import type { Theme } from '~/types/theme.js';
import type { EditorSettings } from './CodeMirrorEditor.js'; import type { EditorSettings } from './CodeMirrorEditor.js';
import type { Theme } from '~/types/theme.js';
export const darkTheme = EditorView.theme({}, { dark: true }); export const darkTheme = EditorView.theme({}, { dark: true });
export const themeSelection = new Compartment(); export const themeSelection = new Compartment();

View File

@ -1,9 +1,9 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { ClientOnly } from 'remix-utils/client-only'; import { ClientOnly } from 'remix-utils/client-only';
import { chatStore } from '~/lib/stores/chat';
import { classNames } from '~/utils/classNames';
import { HeaderActionButtons } from './HeaderActionButtons.client'; import { HeaderActionButtons } from './HeaderActionButtons.client';
import { ChatDescription } from '~/lib/persistence/ChatDescription.client'; import { ChatDescription } from '~/lib/persistence/ChatDescription.client';
import { chatStore } from '~/lib/stores/chat';
import { classNames } from '~/utils/classNames';
export function Header() { export function Header() {
const chat = useStore(chatStore); const chat = useStore(chatStore);

View File

@ -1,7 +1,7 @@
import { useStore } from '@nanostores/react';
import { chatStore } from '~/lib/stores/chat'; import { chatStore } from '~/lib/stores/chat';
import { workbenchStore } from '~/lib/stores/workbench'; import { workbenchStore } from '~/lib/stores/workbench';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { useStore } from '@nanostores/react';
interface HeaderActionButtonsProps {} interface HeaderActionButtonsProps {}

View File

@ -22,6 +22,7 @@ export function HistoryItem({ item, onDelete, onRename, onExport }: HistoryItemP
function mouseEnter() { function mouseEnter() {
setHovering(true); setHovering(true);
if (timeout) { if (timeout) {
clearTimeout(timeout); clearTimeout(timeout);
} }

View File

@ -1,14 +1,14 @@
import { saveAs } from 'file-saver';
import { motion, type Variants } from 'framer-motion'; import { motion, type Variants } from 'framer-motion';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { saveAs } from 'file-saver'; import { HistoryItem } from './HistoryItem';
import { binDates } from './date-binning';
import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog'; import { Dialog, DialogButton, DialogDescription, DialogRoot, DialogTitle } from '~/components/ui/Dialog';
import { ThemeSwitch } from '~/components/ui/ThemeSwitch'; import { ThemeSwitch } from '~/components/ui/ThemeSwitch';
import { db, deleteById, getAll, chatId, type ChatHistoryItem, setMessages } from '~/lib/persistence'; import { db, deleteById, getAll, chatId, type ChatHistoryItem, setMessages } from '~/lib/persistence';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { logger } from '~/utils/logger'; import { logger } from '~/utils/logger';
import { HistoryItem } from './HistoryItem';
import { binDates } from './date-binning';
const menuVariants = { const menuVariants = {
closed: { closed: {
@ -68,22 +68,26 @@ export function Menu() {
} }
}, []); }, []);
const renameItem = useCallback((id: string, newDescription: string) => { const renameItem = useCallback(
if (db) { (id: string, newDescription: string) => {
const item = list.find((item) => item.id === id); if (db) {
if (item) { const item = list.find((item) => item.id === id);
setMessages(db, id, item.messages, item.urlId, newDescription)
.then(() => { if (item) {
loadEntries(); setMessages(db, id, item.messages, item.urlId, newDescription)
toast.success('Chat renamed successfully'); .then(() => {
}) loadEntries();
.catch((error) => { toast.success('Chat renamed successfully');
toast.error('Failed to rename chat'); })
logger.error(error); .catch((error) => {
}); toast.error('Failed to rename chat');
logger.error(error);
});
}
} }
} },
}, [list]); [list],
);
const exportItem = useCallback((item: ChatHistoryItem) => { const exportItem = useCallback((item: ChatHistoryItem) => {
try { try {

View File

@ -1,9 +1,9 @@
import * as RadixDialog from '@radix-ui/react-dialog'; import * as RadixDialog from '@radix-ui/react-dialog';
import { motion, type Variants } from 'framer-motion'; import { motion, type Variants } from 'framer-motion';
import React, { memo, type ReactNode } from 'react'; import React, { memo, type ReactNode } from 'react';
import { IconButton } from './IconButton';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { IconButton } from './IconButton';
export { Close as DialogClose, Root as DialogRoot } from '@radix-ui/react-dialog'; export { Close as DialogClose, Root as DialogRoot } from '@radix-ui/react-dialog';

View File

@ -64,15 +64,23 @@ export const IconButton = memo(
function getIconSize(size: IconSize) { function getIconSize(size: IconSize) {
switch (size) { switch (size) {
case 'sm': case 'sm': {
return 'text-sm'; return 'text-sm';
case 'md': }
case 'md': {
return 'text-base'; return 'text-base';
case 'lg': }
case 'lg': {
return 'text-lg'; return 'text-lg';
case 'xl': }
case 'xl': {
return 'text-xl'; return 'text-xl';
case 'xxl': }
case 'xxl': {
return 'text-2xl'; return 'text-2xl';
}
default: {
return 'text-base';
}
} }
} }

View File

@ -1,7 +1,7 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { memo, useEffect, useState } from 'react'; import { memo, useEffect, useState } from 'react';
import { themeStore, toggleTheme } from '~/lib/stores/theme';
import { IconButton } from './IconButton'; import { IconButton } from './IconButton';
import { themeStore, toggleTheme } from '~/lib/stores/theme';
interface ThemeSwitchProps { interface ThemeSwitchProps {
className?: string; className?: string;

View File

@ -1,6 +1,9 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { memo, useEffect, useMemo, useRef, useState } from 'react'; import { memo, useEffect, useMemo, useRef, useState } from 'react';
import { Panel, PanelGroup, PanelResizeHandle, type ImperativePanelHandle } from 'react-resizable-panels'; import { Panel, PanelGroup, PanelResizeHandle, type ImperativePanelHandle } from 'react-resizable-panels';
import { FileBreadcrumb } from './FileBreadcrumb';
import { FileTree } from './FileTree';
import { Terminal, type TerminalRef } from './terminal/Terminal';
import { import {
CodeMirrorEditor, CodeMirrorEditor,
type EditorDocument, type EditorDocument,
@ -20,9 +23,6 @@ import { classNames } from '~/utils/classNames';
import { WORK_DIR } from '~/utils/constants'; import { WORK_DIR } from '~/utils/constants';
import { renderLogger } from '~/utils/logger'; import { renderLogger } from '~/utils/logger';
import { isMobile } from '~/utils/mobile'; import { isMobile } from '~/utils/mobile';
import { FileBreadcrumb } from './FileBreadcrumb';
import { FileTree } from './FileTree';
import { Terminal, type TerminalRef } from './terminal/Terminal';
interface EditorPanelProps { interface EditorPanelProps {
files?: FileMap; files?: FileMap;

View File

@ -1,12 +1,12 @@
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'; import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import { AnimatePresence, motion, type Variants } from 'framer-motion'; import { AnimatePresence, motion, type Variants } from 'framer-motion';
import { memo, useEffect, useRef, useState } from 'react'; import { memo, useEffect, useRef, useState } from 'react';
import FileTree from './FileTree';
import type { FileMap } from '~/lib/stores/files'; import type { FileMap } from '~/lib/stores/files';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { WORK_DIR } from '~/utils/constants'; import { WORK_DIR } from '~/utils/constants';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { renderLogger } from '~/utils/logger'; import { renderLogger } from '~/utils/logger';
import FileTree from './FileTree';
const WORK_DIR_REGEX = new RegExp(`^${WORK_DIR.split('/').slice(0, -1).join('/').replaceAll('/', '\\/')}/`); const WORK_DIR_REGEX = new RegExp(`^${WORK_DIR.split('/').slice(0, -1).join('/').replaceAll('/', '\\/')}/`);

View File

@ -1,8 +1,8 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { memo, useCallback, useEffect, useRef, useState } from 'react'; import { memo, useCallback, useEffect, useRef, useState } from 'react';
import { PortDropdown } from './PortDropdown';
import { IconButton } from '~/components/ui/IconButton'; import { IconButton } from '~/components/ui/IconButton';
import { workbenchStore } from '~/lib/stores/workbench'; import { workbenchStore } from '~/lib/stores/workbench';
import { PortDropdown } from './PortDropdown';
export const Preview = memo(() => { export const Preview = memo(() => {
const iframeRef = useRef<HTMLIFrameElement>(null); const iframeRef = useRef<HTMLIFrameElement>(null);

View File

@ -1,10 +1,12 @@
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { saveAs } from 'file-saver';
import { motion, type HTMLMotionProps, type Variants } from 'framer-motion'; import { motion, type HTMLMotionProps, type Variants } from 'framer-motion';
import JSZip from 'jszip';
import { computed } from 'nanostores'; import { computed } from 'nanostores';
import { memo, useCallback, useEffect } from 'react'; import { memo, useCallback, useEffect } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import JSZip from 'jszip'; import { EditorPanel } from './EditorPanel';
import { saveAs } from 'file-saver'; import { Preview } from './Preview';
import { import {
type OnChangeCallback as OnEditorChange, type OnChangeCallback as OnEditorChange,
type OnScrollCallback as OnEditorScroll, type OnScrollCallback as OnEditorScroll,
@ -16,8 +18,6 @@ import { workbenchStore, type WorkbenchViewType } from '~/lib/stores/workbench';
import { classNames } from '~/utils/classNames'; import { classNames } from '~/utils/classNames';
import { cubicEasingFn } from '~/utils/easings'; import { cubicEasingFn } from '~/utils/easings';
import { renderLogger } from '~/utils/logger'; import { renderLogger } from '~/utils/logger';
import { EditorPanel } from './EditorPanel';
import { Preview } from './Preview';
interface WorkspaceProps { interface WorkspaceProps {
chatStarted?: boolean; chatStarted?: boolean;
@ -155,10 +155,7 @@ export const Workbench = memo(({ chatStarted, isStreaming }: WorkspaceProps) =>
<div className="ml-auto" /> <div className="ml-auto" />
{selectedView === 'code' && ( {selectedView === 'code' && (
<> <>
<PanelHeaderButton <PanelHeaderButton className="mr-1 text-sm" onClick={downloadZip}>
className="mr-1 text-sm"
onClick={downloadZip}
>
<div className="i-ph:download-bold" /> <div className="i-ph:download-bold" />
Download Download
</PanelHeaderButton> </PanelHeaderButton>

View File

@ -2,9 +2,9 @@ import { FitAddon } from '@xterm/addon-fit';
import { WebLinksAddon } from '@xterm/addon-web-links'; import { WebLinksAddon } from '@xterm/addon-web-links';
import { Terminal as XTerm } from '@xterm/xterm'; import { Terminal as XTerm } from '@xterm/xterm';
import { forwardRef, memo, useEffect, useImperativeHandle, useRef } from 'react'; import { forwardRef, memo, useEffect, useImperativeHandle, useRef } from 'react';
import { getTerminalTheme } from './theme';
import type { Theme } from '~/lib/stores/theme'; import type { Theme } from '~/lib/stores/theme';
import { createScopedLogger } from '~/utils/logger'; import { createScopedLogger } from '~/utils/logger';
import { getTerminalTheme } from './theme';
const logger = createScopedLogger('Terminal'); const logger = createScopedLogger('Terminal');

View File

@ -1,8 +1,8 @@
import { streamText as _streamText } from 'ai'; import { streamText as _streamText } from 'ai';
import { getAPIKey } from '~/lib/.server/llm/api-key';
import { getAnthropicModel } from '~/lib/.server/llm/model';
import { MAX_TOKENS } from './constants'; import { MAX_TOKENS } from './constants';
import { getSystemPrompt } from './prompts'; import { getSystemPrompt } from './prompts';
import { getAPIKey } from '~/lib/.server/llm/api-key';
import { getAnthropicModel } from '~/lib/.server/llm/model';
interface ToolResult<Name extends string, Args, Result> { interface ToolResult<Name extends string, Args, Result> {
toolCallId: string; toolCallId: string;

View File

@ -1,6 +1,6 @@
import type { Message } from 'ai'; import type { Message } from 'ai';
import { createScopedLogger } from '~/utils/logger';
import type { ChatHistoryItem } from './useChatHistory'; import type { ChatHistoryItem } from './useChatHistory';
import { createScopedLogger } from '~/utils/logger';
const logger = createScopedLogger('ChatHistory'); const logger = createScopedLogger('ChatHistory');

View File

@ -1,10 +1,10 @@
import { useLoaderData, useNavigate } from '@remix-run/react'; import { useLoaderData, useNavigate } from '@remix-run/react';
import { useState, useEffect } from 'react';
import { atom } from 'nanostores';
import type { Message } from 'ai'; import type { Message } from 'ai';
import { atom } from 'nanostores';
import { useState, useEffect } from 'react';
import { toast } from 'react-toastify'; import { toast } from 'react-toastify';
import { workbenchStore } from '~/lib/stores/workbench';
import { getMessages, getNextId, getUrlId, openDatabase, setMessages } from './db'; import { getMessages, getNextId, getUrlId, openDatabase, setMessages } from './db';
import { workbenchStore } from '~/lib/stores/workbench';
export interface ChatHistoryItem { export interface ChatHistoryItem {
id: string; id: string;

View File

@ -1,10 +1,10 @@
import * as nodePath from 'node:path';
import { WebContainer } from '@webcontainer/api'; import { WebContainer } from '@webcontainer/api';
import { map, type MapStore } from 'nanostores'; import { map, type MapStore } from 'nanostores';
import * as nodePath from 'node:path'; import type { ActionCallbackData } from './message-parser';
import type { BoltAction } from '~/types/actions'; import type { BoltAction } from '~/types/actions';
import { createScopedLogger } from '~/utils/logger'; import { createScopedLogger } from '~/utils/logger';
import { unreachable } from '~/utils/unreachable'; import { unreachable } from '~/utils/unreachable';
import type { ActionCallbackData } from './message-parser';
const logger = createScopedLogger('ActionRunner'); const logger = createScopedLogger('ActionRunner');

View File

@ -1,6 +1,6 @@
import { atom, computed, map, type MapStore, type WritableAtom } from 'nanostores'; import { atom, computed, map, type MapStore, type WritableAtom } from 'nanostores';
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor';
import type { FileMap, FilesStore } from './files'; import type { FileMap, FilesStore } from './files';
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor';
export type EditorDocuments = Record<string, EditorDocument>; export type EditorDocuments = Record<string, EditorDocument>;

View File

@ -1,8 +1,8 @@
import { Buffer } from 'node:buffer';
import * as nodePath from 'node:path';
import type { PathWatcherEvent, WebContainer } from '@webcontainer/api'; import type { PathWatcherEvent, WebContainer } from '@webcontainer/api';
import { getEncoding } from 'istextorbinary'; import { getEncoding } from 'istextorbinary';
import { map, type MapStore } from 'nanostores'; import { map, type MapStore } from 'nanostores';
import { Buffer } from 'node:buffer';
import * as nodePath from 'node:path';
import { bufferWatchEvents } from '~/utils/buffer'; import { bufferWatchEvents } from '~/utils/buffer';
import { WORK_DIR } from '~/utils/constants'; import { WORK_DIR } from '~/utils/constants';
import { computeFileModifications } from '~/utils/diff'; import { computeFileModifications } from '~/utils/diff';

View File

@ -1,14 +1,14 @@
import { atom, map, type MapStore, type ReadableAtom, type WritableAtom } from 'nanostores'; import { atom, map, type MapStore, type ReadableAtom, type WritableAtom } from 'nanostores';
import { EditorStore } from './editor';
import { FilesStore, type FileMap } from './files';
import { PreviewsStore } from './previews';
import { TerminalStore } from './terminal';
import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor'; import type { EditorDocument, ScrollPosition } from '~/components/editor/codemirror/CodeMirrorEditor';
import { ActionRunner } from '~/lib/runtime/action-runner'; import { ActionRunner } from '~/lib/runtime/action-runner';
import type { ActionCallbackData, ArtifactCallbackData } from '~/lib/runtime/message-parser'; import type { ActionCallbackData, ArtifactCallbackData } from '~/lib/runtime/message-parser';
import { webcontainer } from '~/lib/webcontainer'; import { webcontainer } from '~/lib/webcontainer';
import type { ITerminal } from '~/types/terminal'; import type { ITerminal } from '~/types/terminal';
import { unreachable } from '~/utils/unreachable'; import { unreachable } from '~/utils/unreachable';
import { EditorStore } from './editor';
import { FilesStore, type FileMap } from './files';
import { PreviewsStore } from './previews';
import { TerminalStore } from './terminal';
export interface ArtifactState { export interface ArtifactState {
id: string; id: string;

View File

@ -2,14 +2,13 @@ import { useStore } from '@nanostores/react';
import type { LinksFunction } from '@remix-run/cloudflare'; import type { LinksFunction } from '@remix-run/cloudflare';
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react'; import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
import tailwindReset from '@unocss/reset/tailwind-compat.css?url'; import tailwindReset from '@unocss/reset/tailwind-compat.css?url';
import { themeStore } from './lib/stores/theme';
import { stripIndents } from './utils/stripIndent';
import { createHead } from 'remix-island';
import { useEffect } from 'react';
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
import globalStyles from './styles/index.scss?url';
import xtermStyles from '@xterm/xterm/css/xterm.css?url'; import xtermStyles from '@xterm/xterm/css/xterm.css?url';
import { useEffect } from 'react';
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
import { createHead } from 'remix-island';
import { themeStore } from './lib/stores/theme';
import globalStyles from './styles/index.scss?url';
import { stripIndents } from './utils/stripIndent';
import 'virtual:uno.css'; import 'virtual:uno.css';

View File

@ -1,5 +1,4 @@
import { type ActionFunctionArgs } from '@remix-run/cloudflare'; import { type ActionFunctionArgs } from '@remix-run/cloudflare';
import { createDataStream, createDataStreamResponse } from 'ai';
import { streamText } from '~/lib/.server/llm/stream-text'; import { streamText } from '~/lib/.server/llm/stream-text';
import { stripIndents } from '~/utils/stripIndent'; import { stripIndents } from '~/utils/stripIndent';
@ -36,21 +35,23 @@ async function enhancerAction({ context, request }: ActionFunctionArgs) {
transform(chunk, controller) { transform(chunk, controller) {
const text = decoder.decode(chunk); const text = decoder.decode(chunk);
const lines = text.split('\n'); const lines = text.split('\n');
for (const line of lines) { for (const line of lines) {
if (line.startsWith('0:')) { if (line.startsWith('0:')) {
// Extract only the content after "0:" // extract only the content after "0:"
const content = line.slice(2); const content = line.slice(2);
controller.enqueue(encoder.encode(content)); controller.enqueue(encoder.encode(content));
} }
// Ignore 'e:' and 'd:' lines as they contain metadata
// ignore 'e:' and 'd:' lines as they contain metadata
} }
} },
}); });
const stream = result.toDataStream().pipeThrough(transformStream); const stream = result.toDataStream().pipeThrough(transformStream);
return new Response(stream, { return new Response(stream, {
headers: { 'Content-Type': 'text/plain; charset=utf-8' } headers: { 'Content-Type': 'text/plain; charset=utf-8' },
}); });
} catch (error) { } catch (error) {
console.log(error); console.log(error);

View File

@ -1,6 +1,6 @@
import { createTwoFilesPatch } from 'diff'; import { createTwoFilesPatch } from 'diff';
import type { FileMap } from '~/lib/stores/files';
import { MODIFICATIONS_TAG_NAME } from './constants'; import { MODIFICATIONS_TAG_NAME } from './constants';
import type { FileMap } from '~/lib/stores/files';
export const modificationsRegex = new RegExp( export const modificationsRegex = new RegExp(
`^<${MODIFICATIONS_TAG_NAME}>[\\s\\S]*?<\\/${MODIFICATIONS_TAG_NAME}>\\s+`, `^<${MODIFICATIONS_TAG_NAME}>[\\s\\S]*?<\\/${MODIFICATIONS_TAG_NAME}>\\s+`,

View File

@ -11,7 +11,7 @@ interface Logger {
setLevel: (level: DebugLevel) => void; setLevel: (level: DebugLevel) => void;
} }
let currentLevel: DebugLevel = import.meta.env.VITE_LOG_LEVEL ?? import.meta.env.DEV ? 'debug' : 'info'; let currentLevel: DebugLevel = (import.meta.env.VITE_LOG_LEVEL ?? import.meta.env.DEV) ? 'debug' : 'info';
const isWorker = 'HTMLRewriter' in globalThis; const isWorker = 'HTMLRewriter' in globalThis;
const supportsColor = !isWorker; const supportsColor = !isWorker;

View File

@ -1,9 +1,9 @@
import type { UnistNode, UnistParent } from 'node_modules/unist-util-visit/lib';
import rehypeRaw from 'rehype-raw'; import rehypeRaw from 'rehype-raw';
import rehypeSanitize, { defaultSchema, type Options as RehypeSanitizeOptions } from 'rehype-sanitize';
import remarkGfm from 'remark-gfm'; import remarkGfm from 'remark-gfm';
import type { PluggableList, Plugin } from 'unified'; import type { PluggableList, Plugin } from 'unified';
import rehypeSanitize, { defaultSchema, type Options as RehypeSanitizeOptions } from 'rehype-sanitize';
import { SKIP, visit } from 'unist-util-visit'; import { SKIP, visit } from 'unist-util-visit';
import type { UnistNode, UnistParent } from 'node_modules/unist-util-visit/lib';
export const allowedHTMLElements = [ export const allowedHTMLElements = [
'a', 'a',

View File

@ -1,6 +1,6 @@
import type { WebContainer } from '@webcontainer/api'; import type { WebContainer } from '@webcontainer/api';
import type { ITerminal } from '~/types/terminal';
import { withResolvers } from './promises'; import { withResolvers } from './promises';
import type { ITerminal } from '~/types/terminal';
export async function newShellProcess(webcontainer: WebContainer, terminal: ITerminal) { export async function newShellProcess(webcontainer: WebContainer, terminal: ITerminal) {
const args: string[] = []; const args: string[] = [];

View File

@ -1,6 +1,6 @@
import { globSync } from 'fast-glob';
import fs from 'node:fs/promises'; import fs from 'node:fs/promises';
import { basename } from 'node:path'; import { basename } from 'node:path';
import { globSync } from 'fast-glob';
import { defineConfig, presetIcons, presetUno, transformerDirectives } from 'unocss'; import { defineConfig, presetIcons, presetUno, transformerDirectives } from 'unocss';
const iconPaths = globSync('./icons/*.svg'); const iconPaths = globSync('./icons/*.svg');