merge conflict resolved
This commit is contained in:
@@ -23,6 +23,7 @@ type FileGridProps = {
|
||||
onRenamingChange: (name: string | null) => void;
|
||||
getMatchingTasks: (fileName: string, entryType: 'file' | 'directory') => TaskSummary[];
|
||||
onRunTask: (task: TaskSummary, entry: DirEntry) => void;
|
||||
onCreateWorkspace: (entry: DirEntry) => void;
|
||||
scrollRef: React.RefObject<HTMLDivElement | null>;
|
||||
};
|
||||
|
||||
@@ -72,6 +73,7 @@ export const FileGrid = ({
|
||||
onRenamingChange,
|
||||
getMatchingTasks,
|
||||
onRunTask,
|
||||
onCreateWorkspace,
|
||||
scrollRef,
|
||||
}: FileGridProps) => {
|
||||
const lastClickedIdx = useRef<number>(-1);
|
||||
@@ -153,6 +155,7 @@ export const FileGrid = ({
|
||||
onRenamingChange={onRenamingChange}
|
||||
matchingTasks={getMatchingTasks(entry.name, entry.type)}
|
||||
onRunTask={onRunTask}
|
||||
onCreateWorkspace={onCreateWorkspace}
|
||||
/>
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
import { Folder, Trash2, Pencil, MoreVertical, MessageSquare, Scissors, Copy, Check, Play, Download } from 'lucide-react';
|
||||
import { Folder, Trash2, Pencil, MoreVertical, MessageSquare, Scissors, Copy, Check, Play, Download, LayoutGrid } from 'lucide-react';
|
||||
import { getIcon } from 'material-file-icons';
|
||||
import {
|
||||
DropdownMenu,
|
||||
@@ -43,6 +43,7 @@ export type FileItemProps = {
|
||||
onRenamingChange: (name: string | null) => void;
|
||||
matchingTasks: TaskSummary[];
|
||||
onRunTask: (task: TaskSummary, entry: DirEntry) => void;
|
||||
onCreateWorkspace: (entry: DirEntry) => void;
|
||||
};
|
||||
|
||||
function formatSize(bytes: number): string {
|
||||
@@ -70,6 +71,7 @@ type MenuItemsProps = {
|
||||
onCopy: () => void;
|
||||
matchingTasks: TaskSummary[];
|
||||
onRunTask: (task: TaskSummary, entry: DirEntry) => void;
|
||||
onCreateWorkspace: (e: DirEntry) => void;
|
||||
};
|
||||
|
||||
const DropdownMenuItems = ({
|
||||
@@ -83,6 +85,7 @@ const DropdownMenuItems = ({
|
||||
onCopy,
|
||||
matchingTasks,
|
||||
onRunTask,
|
||||
onCreateWorkspace,
|
||||
}: MenuItemsProps) => (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => onChat(entry)} className="cursor-pointer">
|
||||
@@ -108,6 +111,15 @@ const DropdownMenuItems = ({
|
||||
</DropdownMenuSubContent>
|
||||
</DropdownMenuSub>
|
||||
)}
|
||||
{entry.type === 'directory' && (
|
||||
<>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={() => onCreateWorkspace(entry)} className="cursor-pointer">
|
||||
<LayoutGrid className="mr-2 h-4 w-4" />
|
||||
Create Workspace here
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem onClick={onCut} className="cursor-pointer">
|
||||
<Scissors className="mr-2 h-4 w-4" />
|
||||
@@ -142,6 +154,7 @@ const ContextMenuItems = ({
|
||||
onCopy,
|
||||
matchingTasks,
|
||||
onRunTask,
|
||||
onCreateWorkspace,
|
||||
}: MenuItemsProps) => (
|
||||
<>
|
||||
<ContextMenuItem onClick={() => onChat(entry)} className="cursor-pointer">
|
||||
@@ -167,6 +180,15 @@ const ContextMenuItems = ({
|
||||
</ContextMenuSubContent>
|
||||
</ContextMenuSub>
|
||||
)}
|
||||
{entry.type === 'directory' && (
|
||||
<>
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem onClick={() => onCreateWorkspace(entry)} className="cursor-pointer">
|
||||
<LayoutGrid className="mr-2 h-4 w-4" />
|
||||
Create Workspace here
|
||||
</ContextMenuItem>
|
||||
</>
|
||||
)}
|
||||
<ContextMenuSeparator />
|
||||
<ContextMenuItem onClick={onCut} className="cursor-pointer">
|
||||
<Scissors className="mr-2 h-4 w-4" />
|
||||
@@ -300,6 +322,7 @@ export const FileItem = ({
|
||||
onRenamingChange,
|
||||
matchingTasks,
|
||||
onRunTask,
|
||||
onCreateWorkspace,
|
||||
}: FileItemProps) => {
|
||||
const [renaming, setRenaming] = useState(false);
|
||||
const clickTimer = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
@@ -376,6 +399,7 @@ export const FileItem = ({
|
||||
onCopy,
|
||||
matchingTasks,
|
||||
onRunTask,
|
||||
onCreateWorkspace,
|
||||
};
|
||||
|
||||
const cutOpacity = isCut ? 'opacity-50' : '';
|
||||
|
||||
@@ -33,7 +33,11 @@ type ClipboardState = { paths: string[]; mode: 'copy' | 'cut' } | null;
|
||||
|
||||
type HomeRoot = 'home' | '~' | 'officer.dev';
|
||||
|
||||
export const Files = () => {
|
||||
type FilesProps = {
|
||||
basePath?: string;
|
||||
};
|
||||
|
||||
export const Files = ({ basePath = '/' }: FilesProps) => {
|
||||
const { user } = useAuth();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams, setSearchParams] = useSearchParams();
|
||||
@@ -86,6 +90,10 @@ export const Files = () => {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (basePath !== '/' && !currentPath.startsWith(basePath)) {
|
||||
setCurrentPath(basePath);
|
||||
return;
|
||||
}
|
||||
refresh();
|
||||
}, [currentPath, homeRoot]);
|
||||
|
||||
@@ -137,6 +145,10 @@ export const Files = () => {
|
||||
const selectedPaths = () => Array.from(selected).map(entryPath);
|
||||
|
||||
const handleNavigate = (path: string) => {
|
||||
if (basePath !== '/' && !path.startsWith(basePath)) {
|
||||
setCurrentPath(basePath);
|
||||
return;
|
||||
}
|
||||
setCurrentPath(path);
|
||||
};
|
||||
|
||||
@@ -262,6 +274,18 @@ export const Files = () => {
|
||||
setRunningTask({ task, entry });
|
||||
};
|
||||
|
||||
const handleCreateWorkspace = (entry: DirEntry) => {
|
||||
const folderPath = currentPath === '/' ? `/${entry.name}` : `${currentPath}/${entry.name}`;
|
||||
navigate(`/workspaces/new?name=${encodeURIComponent(entry.name)}&cwd=${encodeURIComponent(folderPath)}`);
|
||||
};
|
||||
|
||||
const handleCreateWorkspaceHere = () => {
|
||||
const dirName = currentPath === '/' ? '' : currentPath.split('/').pop()!;
|
||||
const params = new URLSearchParams({ cwd: currentPath });
|
||||
if (dirName) params.set('name', dirName);
|
||||
navigate(`/workspaces/new?${params}`);
|
||||
};
|
||||
|
||||
const handleGitClone = async () => {
|
||||
const url = cloneUrl.trim();
|
||||
if (!url) return;
|
||||
@@ -509,7 +533,7 @@ export const Files = () => {
|
||||
</div>
|
||||
|
||||
{/* Home dir selector (Super Admin only) */}
|
||||
{user?.role === 'Super Admin' && (
|
||||
{basePath === '/' && user?.role === 'Super Admin' && (
|
||||
<div className="shrink-0 border-b border-duck-dark/10 px-4 py-2">
|
||||
<RadioGroup
|
||||
value={homeRoot}
|
||||
@@ -539,7 +563,7 @@ export const Files = () => {
|
||||
|
||||
{/* Breadcrumb */}
|
||||
<div className="shrink-0 border-b border-duck-dark/10 px-4 py-2">
|
||||
<Breadcrumb path={currentPath} onNavigate={handleNavigate} />
|
||||
<Breadcrumb path={currentPath} onNavigate={handleNavigate} basePath={basePath} />
|
||||
</div>
|
||||
|
||||
{/* Upload progress */}
|
||||
@@ -625,6 +649,7 @@ export const Files = () => {
|
||||
onRenamingChange={setRenamingName}
|
||||
getMatchingTasks={getMatchingTasks}
|
||||
onRunTask={handleRunTask}
|
||||
onCreateWorkspace={handleCreateWorkspace}
|
||||
scrollRef={fileScrollRef}
|
||||
/>
|
||||
)}
|
||||
@@ -645,6 +670,10 @@ export const Files = () => {
|
||||
<FolderPlus className="mr-2 h-4 w-4" />
|
||||
New folder
|
||||
</ContextMenuItem>
|
||||
<ContextMenuItem onClick={handleCreateWorkspaceHere} className="cursor-pointer">
|
||||
<LayoutGrid className="mr-2 h-4 w-4" />
|
||||
Create Workspace here
|
||||
</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
</ContextMenu>
|
||||
)}
|
||||
|
||||
@@ -5,8 +5,19 @@ import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useGlobal } from 'hooks/useGlobal';
|
||||
import { useClient } from 'hooks/useClient';
|
||||
import { generateSlug } from 'helpers/slug';
|
||||
import { useUserState } from '@/state/useUserState';
|
||||
import { useWorkspacesState } from '@/state/useWorkspacesState';
|
||||
import type { WorkspaceDefinition } from '@/components/Workspace';
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import {
|
||||
SELECTED_WORKSPACE_KEY,
|
||||
CREATING_WORKSPACE_KEY,
|
||||
@@ -28,8 +39,10 @@ export const WorkspaceListApp = () => {
|
||||
const [, setName] = useGlobal<string>(NEW_WS_NAME_KEY, '');
|
||||
const [, setDescription] = useGlobal<string>(NEW_WS_DESC_KEY, '');
|
||||
const [, setTemplateIdx] = useGlobal<number>(NEW_WS_TEMPLATE_KEY, 0);
|
||||
const [, setFilePath] = useUserState<string>('files/currentPath', '/');
|
||||
|
||||
const [search, setSearch] = useState('');
|
||||
const [deleting, setDeleting] = useState<WorkspaceDefinition | null>(null);
|
||||
const isWorkspacesPage = location.pathname === '/workspaces';
|
||||
const filtered = search
|
||||
? workspaces.filter((ws) => {
|
||||
@@ -46,18 +59,26 @@ export const WorkspaceListApp = () => {
|
||||
setName(ws.name);
|
||||
setDescription(ws.description ?? '');
|
||||
setTemplateIdx(ws.templateIdx ?? 0);
|
||||
const cwdPath = !ws.cwd || ws.cwd === '~' ? '/' : ws.cwd.replace(/^~\//, '/');
|
||||
setFilePath(cwdPath);
|
||||
};
|
||||
|
||||
const handleDelete = (ev: React.MouseEvent, ws: WorkspaceDefinition) => {
|
||||
ev.stopPropagation();
|
||||
setWorkspaces((prev) => prev.filter((w) => w.id !== ws.id));
|
||||
if (selected === ws.id) setSelected(null);
|
||||
setDeleting(ws);
|
||||
};
|
||||
|
||||
const layoutKey = `ws-layout-${ws.id}`;
|
||||
const confirmDelete = () => {
|
||||
if (!deleting) return;
|
||||
setWorkspaces((prev) => prev.filter((w) => w.id !== deleting.id));
|
||||
if (selected === deleting.id) setSelected(null);
|
||||
|
||||
const layoutKey = `ws-layout-${deleting.id}`;
|
||||
const currentState = queryClient.getQueryData<Record<string, unknown>>(['WORKSPACES_STATE']) ?? {};
|
||||
const { [layoutKey]: _, ...rest } = currentState;
|
||||
queryClient.setQueryData(['WORKSPACES_STATE'], rest);
|
||||
client.patch('/user/workspaces-state', { [layoutKey]: null }).catch(() => {});
|
||||
setDeleting(null);
|
||||
};
|
||||
|
||||
const handleClick = (ws: WorkspaceDefinition) => {
|
||||
@@ -88,6 +109,7 @@ export const WorkspaceListApp = () => {
|
||||
setName(generateSlug());
|
||||
setDescription('');
|
||||
setTemplateIdx(0);
|
||||
setFilePath('/');
|
||||
setCreating(true);
|
||||
if (!isWorkspacesPage) navigate('/workspaces');
|
||||
}}
|
||||
@@ -146,6 +168,23 @@ export const WorkspaceListApp = () => {
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<AlertDialog open={deleting !== null} onOpenChange={(open) => { if (!open) setDeleting(null); }}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Delete workspace</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Are you sure you want to delete <strong>{deleting?.name}</strong>? This action cannot be undone.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel>Cancel</AlertDialogCancel>
|
||||
<AlertDialogAction onClick={confirmDelete} className="bg-red-600 hover:bg-red-700">
|
||||
Delete
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { Link, Navigate, useNavigate, useSearchParams } from 'react-router';
|
||||
import { LayoutGrid, Plus, ArrowRight, Type, Rocket, FileText, Layout } from 'lucide-react';
|
||||
import { FolderOpen, LayoutGrid, Plus, ArrowRight, Type, Rocket, FileText, Layout } from 'lucide-react';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useGlobal } from 'hooks/useGlobal';
|
||||
import { useClient } from 'hooks/useClient';
|
||||
@@ -9,6 +10,7 @@ import { WorkspaceLayout, WorkspaceView, createDefaultLayout } from '@/component
|
||||
import type { LayoutNode, WorkspaceDefinition } from '@/components/Workspace';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { generateSlug, slugify } from 'helpers/slug';
|
||||
import { Files } from '../Files';
|
||||
import { appRegistry } from './app-registry';
|
||||
import { SELECTED_WORKSPACE_KEY, CREATING_WORKSPACE_KEY, EDITING_WORKSPACE_KEY, NEW_WS_NAME_KEY, NEW_WS_DESC_KEY, NEW_WS_TEMPLATE_KEY } from './constants';
|
||||
|
||||
@@ -389,6 +391,14 @@ const CreatePanel = () => {
|
||||
);
|
||||
};
|
||||
|
||||
// --- CwdFileBrowser (basePath-constrained file browser for workspace form) ---
|
||||
|
||||
const CwdFileBrowser = () => {
|
||||
const [currentPath] = useUserState<string>('files/currentPath', '/');
|
||||
const [basePath] = useState(currentPath);
|
||||
return <Files basePath={basePath} />;
|
||||
};
|
||||
|
||||
// --- New Workspace Layout ---
|
||||
|
||||
const newWsLayout: LayoutNode = {
|
||||
@@ -403,7 +413,7 @@ const newWsLayout: LayoutNode = {
|
||||
direction: 'horizontal',
|
||||
children: [
|
||||
{ node: { type: 'panel', id: 'new-ws-name', appType: 'new-ws-name' }, size: 30 },
|
||||
{ node: { type: 'panel', id: 'new-ws-dir', appType: 'file-browser' }, size: 70 },
|
||||
{ node: { type: 'panel', id: 'new-ws-dir', appType: 'file-browser-cwd' }, size: 70 },
|
||||
],
|
||||
},
|
||||
size: 50,
|
||||
@@ -425,6 +435,7 @@ const newWsLayout: LayoutNode = {
|
||||
|
||||
const newWsRegistry = {
|
||||
...appRegistry,
|
||||
'file-browser-cwd': { name: 'File Browser', icon: FolderOpen, component: CwdFileBrowser },
|
||||
'new-ws-name': { name: 'Name', icon: Type, component: NamePanel },
|
||||
'new-ws-template': { name: 'Template', icon: Layout, component: TemplatePanel },
|
||||
'new-ws-create': { name: 'Create', icon: Rocket, component: CreatePanel },
|
||||
@@ -440,6 +451,7 @@ const WorkspacePreviewEmpty = () => {
|
||||
const [, setName] = useGlobal<string>(NEW_WS_NAME_KEY, '');
|
||||
const [, setDescription] = useGlobal<string>(NEW_WS_DESC_KEY, '');
|
||||
const [, setTemplateIdx] = useGlobal<number>(NEW_WS_TEMPLATE_KEY, 0);
|
||||
const [, setFilePath] = useUserState<string>('files/currentPath', '/');
|
||||
|
||||
if (creating || editingId) return <NewWorkspaceForm />;
|
||||
|
||||
@@ -447,6 +459,7 @@ const WorkspacePreviewEmpty = () => {
|
||||
setName(generateSlug());
|
||||
setDescription('');
|
||||
setTemplateIdx(0);
|
||||
setFilePath('/');
|
||||
setCreating(true);
|
||||
};
|
||||
|
||||
@@ -505,6 +518,7 @@ export const WorkspaceListScreen = () => {
|
||||
};
|
||||
|
||||
export const NewWorkspaceRedirect = () => {
|
||||
const navigate = useNavigate();
|
||||
const [params] = useSearchParams();
|
||||
const [, setName] = useGlobal<string>(NEW_WS_NAME_KEY, '');
|
||||
const [, setDescription] = useGlobal<string>(NEW_WS_DESC_KEY, '');
|
||||
@@ -514,16 +528,16 @@ export const NewWorkspaceRedirect = () => {
|
||||
const [, setSelected] = useGlobal<string | null>(SELECTED_WORKSPACE_KEY, null);
|
||||
const [, setFilePath] = useUserState<string>('files/currentPath', '/');
|
||||
|
||||
const name = params.get('name');
|
||||
const cwd = params.get('cwd');
|
||||
useEffect(() => {
|
||||
setSelected(null);
|
||||
setEditing(null);
|
||||
setName(params.get('name') || generateSlug());
|
||||
setDescription('');
|
||||
setTemplateIdx(0);
|
||||
setFilePath(params.get('cwd') || '/');
|
||||
setCreating(true);
|
||||
navigate('/workspaces', { replace: true });
|
||||
}, []);
|
||||
|
||||
setSelected(null);
|
||||
setEditing(null);
|
||||
setName(name || generateSlug());
|
||||
setDescription('');
|
||||
setTemplateIdx(0);
|
||||
setCreating(true);
|
||||
if (cwd) setFilePath(cwd);
|
||||
|
||||
return <Navigate to="/workspaces" replace />;
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { MessageSquare, FolderOpen, History, Music, Code, TerminalSquare, Monitor, LayoutGrid, LayoutDashboard, Sparkles } from 'lucide-react';
|
||||
import { useAuth } from 'hooks/useAuth';
|
||||
import type { AppRegistry } from '@/components/Workspace';
|
||||
@@ -48,12 +48,24 @@ const PiMonoChatWidget = ({ onProviderChange }: { onProviderChange: (p: 'claude'
|
||||
return <ChatPanel chat={piMono} provider="pi-mono" availableModels={models} onProviderChange={onProviderChange} />;
|
||||
};
|
||||
|
||||
const cwdToPath = (cwd: string) => (cwd === '~' ? '/' : cwd.slice(1));
|
||||
|
||||
const FileBrowserWrapper = () => {
|
||||
const { cwd } = useWorkspace();
|
||||
const basePath = cwdToPath(cwd);
|
||||
return <Files basePath={basePath} />;
|
||||
};
|
||||
|
||||
const CodeEditorWrapper = () => <CodeEditorView className="h-full w-full" />;
|
||||
|
||||
const EMPTY_TERMINALS: Record<string, string> = {};
|
||||
|
||||
const TerminalWrapper = ({ panelId }: { panelId: string }) => {
|
||||
const { workspaceId } = useWorkspace();
|
||||
const { workspaceId, cwd } = useWorkspace();
|
||||
const stateKey = workspaceId ? `ws-terminals-${workspaceId}` : 'ws-terminals-default';
|
||||
const [terminals, setTerminals] = useWorkspacesState<Record<string, string>>(stateKey, {});
|
||||
const [terminals, setTerminals] = useWorkspacesState<Record<string, string>>(stateKey, EMPTY_TERMINALS);
|
||||
const setTerminalsRef = useRef(setTerminals);
|
||||
setTerminalsRef.current = setTerminals;
|
||||
|
||||
const sessionId = terminals[panelId];
|
||||
|
||||
@@ -63,16 +75,27 @@ const TerminalWrapper = ({ panelId }: { panelId: string }) => {
|
||||
}
|
||||
}, [panelId, sessionId, setTerminals]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setTerminalsRef.current((prev) => {
|
||||
const { [panelId]: _, ...rest } = prev;
|
||||
return rest;
|
||||
});
|
||||
};
|
||||
}, [panelId]);
|
||||
|
||||
if (!sessionId) return null;
|
||||
|
||||
return <TerminalView className="h-full w-full p-2" sessionId={sessionId} />;
|
||||
return <TerminalView className="h-full w-full p-2" sessionId={sessionId} cwd={cwd} />;
|
||||
};
|
||||
|
||||
const HostTerminalWrapper = ({ panelId }: { panelId: string }) => {
|
||||
const { user } = useAuth();
|
||||
const { workspaceId } = useWorkspace();
|
||||
const { workspaceId, cwd } = useWorkspace();
|
||||
const stateKey = workspaceId ? `ws-host-terminals-${workspaceId}` : 'ws-host-terminals-default';
|
||||
const [terminals, setTerminals] = useWorkspacesState<Record<string, string>>(stateKey, {});
|
||||
const [terminals, setTerminals] = useWorkspacesState<Record<string, string>>(stateKey, EMPTY_TERMINALS);
|
||||
const setTerminalsRef = useRef(setTerminals);
|
||||
setTerminalsRef.current = setTerminals;
|
||||
|
||||
const sessionId = terminals[panelId];
|
||||
|
||||
@@ -82,6 +105,15 @@ const HostTerminalWrapper = ({ panelId }: { panelId: string }) => {
|
||||
}
|
||||
}, [panelId, sessionId, setTerminals]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
setTerminalsRef.current((prev) => {
|
||||
const { [panelId]: _, ...rest } = prev;
|
||||
return rest;
|
||||
});
|
||||
};
|
||||
}, [panelId]);
|
||||
|
||||
if (user?.role !== 'Super Admin') {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center text-sm text-muted-foreground">
|
||||
@@ -92,12 +124,12 @@ const HostTerminalWrapper = ({ panelId }: { panelId: string }) => {
|
||||
|
||||
if (!sessionId) return null;
|
||||
|
||||
return <TerminalView className="h-full w-full p-2" sessionId={sessionId} sandboxed={false} />;
|
||||
return <TerminalView className="h-full w-full p-2" sessionId={sessionId} sandboxed={false} cwd={cwd} />;
|
||||
};
|
||||
|
||||
export const appRegistry: AppRegistry = {
|
||||
'chat': { name: 'Chat', icon: MessageSquare, component: ChatWidget },
|
||||
'file-browser': { name: 'File Browser', icon: FolderOpen, component: () => <Files /> },
|
||||
'file-browser': { name: 'File Browser', icon: FolderOpen, component: FileBrowserWrapper },
|
||||
'chat-history': { name: 'Chat History', icon: History, component: () => <ChatHistory /> },
|
||||
'sound-library': { name: 'Sound Library', icon: Music, component: () => <Catalog /> },
|
||||
'code-editor': { name: 'Code Editor', icon: Code, component: CodeEditorWrapper },
|
||||
|
||||
Reference in New Issue
Block a user