mirror of
https://github.com/eigent-ai/eigent.git
synced 2026-07-10 01:38:37 +00:00
feat/renaming files
This commit is contained in:
parent
97d7554438
commit
58dbd49f5e
53 changed files with 330 additions and 330 deletions
|
|
@ -22,7 +22,7 @@ type Props = {
|
|||
};
|
||||
};
|
||||
|
||||
export default function FolderComponent({ selectedFile }: Props) {
|
||||
export default function ContextComponent({ selectedFile }: Props) {
|
||||
const sanitizedHtml = useMemo(() => {
|
||||
const raw = selectedFile?.content || '';
|
||||
if (!raw) return '';
|
||||
|
|
@ -51,7 +51,7 @@ import {
|
|||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import FolderComponent from './FolderComponent';
|
||||
import ContextComponent from './ContextComponent';
|
||||
|
||||
import { fetchGet, getBaseURL } from '@/api/http';
|
||||
import { MarkDown } from '@/components/ChatBox/MessageItem/MarkDown';
|
||||
|
|
@ -530,14 +530,14 @@ export const FileTree: React.FC<FileTreeProps> = ({
|
|||
onSelectFile(fileInfo);
|
||||
}
|
||||
}}
|
||||
className={`mb-1 flex w-full min-w-0 flex-row items-center justify-start gap-2 rounded-lg px-2 py-1.5 text-left transition-colors hover:bg-ds-bg-neutral-subtle-hover ${
|
||||
className={`mb-1 min-w-0 gap-2 rounded-lg px-2 py-1.5 hover:bg-ds-bg-neutral-subtle-hover flex w-full flex-row items-center justify-start text-left transition-colors ${
|
||||
isRowSelected
|
||||
? 'bg-ds-bg-neutral-default-default text-ds-text-neutral-default-default'
|
||||
: 'bg-transparent text-ds-text-neutral-muted-default'
|
||||
: 'text-ds-text-neutral-muted-default bg-transparent'
|
||||
}`}
|
||||
>
|
||||
{child.isFolder ? (
|
||||
<span className="inline-flex w-4 shrink-0 items-center justify-start">
|
||||
<span className="w-4 inline-flex shrink-0 items-center justify-start">
|
||||
{isExpanded ? (
|
||||
<ChevronDown className={rowIconClass} />
|
||||
) : (
|
||||
|
|
@ -556,13 +556,13 @@ export const FileTree: React.FC<FileTreeProps> = ({
|
|||
)
|
||||
)}
|
||||
|
||||
<span className="min-w-0 flex-1 truncate text-left text-body-sm font-medium leading-normal">
|
||||
<span className="min-w-0 text-body-sm font-medium leading-normal flex-1 truncate text-left">
|
||||
{child.name}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{hasNested ? (
|
||||
<div className="ml-4 border-y-0 border-l border-r-0 border-solid border-ds-border-neutral-subtle-default pl-1">
|
||||
<div className="ml-4 border-ds-border-neutral-subtle-default pl-1 border-y-0 border-r-0 border-l border-solid">
|
||||
<FileTree
|
||||
node={child}
|
||||
level={level + 1}
|
||||
|
|
@ -1598,15 +1598,15 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
return (
|
||||
<div className="flex h-full w-full flex-col overflow-hidden">
|
||||
{/* header */}
|
||||
<div className="border-b-1 flex w-full shrink-0 items-center gap-2 border-x-0 border-t-0 border-solid border-ds-border-neutral-subtle-default p-2">
|
||||
<div className="flex min-w-0 max-w-[min(20rem,45%)] items-center">
|
||||
<div className="gap-2 border-ds-border-neutral-subtle-default p-2 flex w-full shrink-0 items-center border-x-0 border-t-0 border-b-1 border-solid">
|
||||
<div className="min-w-0 flex max-w-[min(20rem,45%)] items-center">
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
aria-pressed={isFileSidebarOpen}
|
||||
className="shrink-0 text-ds-icon-neutral-default-default"
|
||||
className="text-ds-icon-neutral-default-default shrink-0"
|
||||
aria-label={
|
||||
isFileSidebarOpen
|
||||
? t('chat.hide-file-sidebar', {
|
||||
|
|
@ -1634,21 +1634,21 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
)}
|
||||
</Button>
|
||||
<span
|
||||
className="min-w-0 truncate text-body-sm font-semibold leading-none text-ds-text-neutral-default-default"
|
||||
className="min-w-0 text-body-sm font-semibold text-ds-text-neutral-default-default truncate leading-none"
|
||||
title={folderHeaderTitle}
|
||||
>
|
||||
{folderHeaderTitle}
|
||||
</span>
|
||||
</div>
|
||||
<div className="ml-auto flex min-w-0 items-center gap-2">
|
||||
<div className="relative h-7 w-32 min-w-[10rem] max-w-xs shrink-0 rounded-lg">
|
||||
<Search className="pointer-events-none absolute left-2 top-1/2 h-3.5 w-3.5 -translate-y-1/2 text-ds-text-brand-default-default" />
|
||||
<div className="min-w-0 gap-2 ml-auto flex items-center">
|
||||
<div className="h-7 w-32 max-w-xs rounded-lg relative min-w-[10rem] shrink-0">
|
||||
<Search className="left-2 h-3.5 w-3.5 text-ds-text-brand-default-default pointer-events-none absolute top-1/2 -translate-y-1/2" />
|
||||
<input
|
||||
type="text"
|
||||
value={fileSearchQuery}
|
||||
onChange={(e) => setFileSearchQuery(e.target.value)}
|
||||
placeholder={t('chat.search')}
|
||||
className="h-7 w-full rounded-lg border border-solid border-ds-border-neutral-subtle-default py-0 pl-7 pr-2 text-sm leading-none focus:outline-none focus:ring-2 focus:ring-ds-ring-brand-default-focus focus:ring-offset-0"
|
||||
className="h-7 rounded-lg border-ds-border-neutral-subtle-default py-0 pl-7 pr-2 text-sm focus:ring-ds-ring-brand-default-focus w-full border border-solid leading-none focus:ring-2 focus:ring-offset-0 focus:outline-none"
|
||||
aria-label={t('chat.search')}
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -1669,18 +1669,18 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
align="end"
|
||||
className="z-50 border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default"
|
||||
className="border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default z-50"
|
||||
>
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleOpenInIDE('system')}
|
||||
className="cursor-pointer bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover"
|
||||
className="bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover cursor-pointer"
|
||||
>
|
||||
<FolderIcon className="size-4 shrink-0" aria-hidden />
|
||||
{t('chat.open-in-file-manager')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleOpenInIDE('cursor')}
|
||||
className="cursor-pointer bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover"
|
||||
className="bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src={cursorIcon}
|
||||
|
|
@ -1692,7 +1692,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={() => handleOpenInIDE('vscode')}
|
||||
className="cursor-pointer bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover"
|
||||
className="bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover cursor-pointer"
|
||||
>
|
||||
<img
|
||||
src={vsCodeIcon}
|
||||
|
|
@ -1708,11 +1708,11 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-1 overflow-hidden">
|
||||
<div className="min-h-0 flex flex-1 overflow-hidden">
|
||||
{/* sidebar */}
|
||||
{isFileSidebarOpen ? (
|
||||
<div className="flex h-full w-64 flex-shrink-0 flex-col border-y-0 border-l-0 border-r border-solid border-ds-border-neutral-subtle-default">
|
||||
<div className="flex h-8 items-center px-1">
|
||||
<div className="w-64 border-ds-border-neutral-subtle-default flex h-full flex-shrink-0 flex-col border-y-0 border-r border-l-0 border-solid">
|
||||
<div className="h-8 px-1 flex items-center">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
|
|
@ -1721,7 +1721,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
size="sm"
|
||||
buttonContent="text"
|
||||
>
|
||||
<span className="min-w-0 truncate text-left font-bold">
|
||||
<span className="min-w-0 font-bold truncate text-left">
|
||||
{t('chat.files')}
|
||||
</span>
|
||||
<ChevronDown className="size-3.5 shrink-0 opacity-70" />
|
||||
|
|
@ -1730,7 +1730,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
<DropdownMenuContent
|
||||
side="bottom"
|
||||
align="start"
|
||||
className="z-50 min-w-[10rem] border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default"
|
||||
className="border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default z-50 min-w-[10rem]"
|
||||
>
|
||||
<DropdownMenuRadioGroup
|
||||
value={fileTreeScope}
|
||||
|
|
@ -1740,7 +1740,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
>
|
||||
<DropdownMenuRadioItem
|
||||
value="all"
|
||||
className="cursor-pointer bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover"
|
||||
className="bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover cursor-pointer"
|
||||
>
|
||||
{t('folder.files-scope-all', {
|
||||
defaultValue: 'All files',
|
||||
|
|
@ -1748,7 +1748,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</DropdownMenuRadioItem>
|
||||
<DropdownMenuRadioItem
|
||||
value="new"
|
||||
className="cursor-pointer bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover"
|
||||
className="bg-dropdown-item-bg-default hover:bg-dropdown-item-bg-hover cursor-pointer"
|
||||
>
|
||||
{t('folder.files-scope-new', {
|
||||
defaultValue: 'New files',
|
||||
|
|
@ -1759,7 +1759,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</DropdownMenu>
|
||||
</div>
|
||||
<div className="scrollbar-always-visible min-h-0 flex-1 overflow-y-auto">
|
||||
<div className="h-full pl-1.5">
|
||||
<div className="pl-1.5 h-full">
|
||||
<FileTree
|
||||
node={sidebarFileTree}
|
||||
selectedFile={selectedFile}
|
||||
|
|
@ -1776,10 +1776,10 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
) : null}
|
||||
|
||||
{/* content */}
|
||||
<div className="flex min-w-0 flex-1 flex-col overflow-hidden bg-ds-bg-neutral-subtle-default">
|
||||
<div className="min-w-0 bg-ds-bg-neutral-subtle-default flex flex-1 flex-col overflow-hidden">
|
||||
{/* head */}
|
||||
{selectedFile && (
|
||||
<div className="flex h-8 flex-shrink-0 items-center justify-between gap-2 pl-3 pr-2">
|
||||
<div className="h-8 gap-2 pl-3 pr-2 flex flex-shrink-0 items-center justify-between">
|
||||
<div
|
||||
onClick={() => {
|
||||
// if file is remote, don't call reveal-in-folder
|
||||
|
|
@ -1789,10 +1789,10 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
}
|
||||
ipcRenderer?.invoke('reveal-in-folder', selectedFile.path);
|
||||
}}
|
||||
className="flex min-w-0 flex-1 cursor-pointer items-center overflow-hidden"
|
||||
className="min-w-0 flex flex-1 cursor-pointer items-center overflow-hidden"
|
||||
>
|
||||
<nav
|
||||
className="scrollbar-always-visible flex min-w-0 max-w-full items-center gap-1 overflow-x-auto text-body-sm text-ds-text-neutral-muted-default"
|
||||
className="scrollbar-always-visible min-w-0 gap-1 text-body-sm text-ds-text-neutral-muted-default flex max-w-full items-center overflow-x-auto"
|
||||
aria-label={t('folder.file-path-breadcrumb', {
|
||||
defaultValue: 'File path',
|
||||
})}
|
||||
|
|
@ -1803,15 +1803,15 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
<Fragment key={`${index}-${segment}`}>
|
||||
{index > 0 ? (
|
||||
<ChevronRight
|
||||
className="h-3.5 w-3.5 shrink-0 text-ds-icon-neutral-muted-default"
|
||||
className="h-3.5 w-3.5 text-ds-icon-neutral-muted-default shrink-0"
|
||||
aria-hidden
|
||||
/>
|
||||
) : null}
|
||||
<span
|
||||
className={
|
||||
isLast
|
||||
? 'shrink-0 font-bold text-ds-text-neutral-default-default'
|
||||
: 'shrink-0 font-normal'
|
||||
? 'font-bold text-ds-text-neutral-default-default shrink-0'
|
||||
: 'font-normal shrink-0'
|
||||
}
|
||||
>
|
||||
{segment}
|
||||
|
|
@ -1821,7 +1821,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
})}
|
||||
</nav>
|
||||
</div>
|
||||
<div className="flex flex-shrink-0 items-center gap-0.5">
|
||||
<div className="gap-0.5 flex flex-shrink-0 items-center">
|
||||
<Button
|
||||
size="icon"
|
||||
variant="ghost"
|
||||
|
|
@ -1850,7 +1850,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
|
||||
{/* content */}
|
||||
<div
|
||||
className={`flex min-h-0 flex-1 flex-col ${
|
||||
className={`min-h-0 flex flex-1 flex-col ${
|
||||
selectedFile?.type === 'html' && !isShowSourceCode
|
||||
? 'overflow-hidden'
|
||||
: 'scrollbar-always-visible overflow-y-auto'
|
||||
|
|
@ -1859,8 +1859,8 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
<div
|
||||
className={`flex flex-col ${
|
||||
selectedFile?.type === 'html' && !isShowSourceCode
|
||||
? 'h-full min-h-0'
|
||||
: 'min-h-full py-2 pl-4 pr-2'
|
||||
? 'min-h-0 h-full'
|
||||
: 'py-2 pl-4 pr-2 min-h-full'
|
||||
} file-viewer-content`}
|
||||
>
|
||||
{selectedFile ? (
|
||||
|
|
@ -1886,7 +1886,7 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
) : ['csv', 'doc', 'docx', 'pptx', 'xlsx'].includes(
|
||||
selectedFile.type
|
||||
) ? (
|
||||
<FolderComponent selectedFile={selectedFile} />
|
||||
<ContextComponent selectedFile={selectedFile} />
|
||||
) : selectedFile.type === 'html' ? (
|
||||
isShowSourceCode ? (
|
||||
<>{selectedFile.content}</>
|
||||
|
|
@ -1897,9 +1897,9 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
/>
|
||||
)
|
||||
) : selectedFile.type === 'zip' ? (
|
||||
<div className="flex h-full w-full items-center justify-center text-ds-text-neutral-muted-default">
|
||||
<div className="text-ds-text-neutral-muted-default flex h-full w-full items-center justify-center">
|
||||
<div className="text-center">
|
||||
<FileText className="mx-auto mb-4 h-12 w-12 text-ds-text-neutral-muted-default" />
|
||||
<FileText className="mb-4 h-12 w-12 text-ds-text-neutral-muted-default mx-auto" />
|
||||
<p className="text-sm">
|
||||
{t('folder.zip-file-is-not-supported-yet')}
|
||||
</p>
|
||||
|
|
@ -1918,14 +1918,14 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
<ImageLoader selectedFile={selectedFile} />
|
||||
</div>
|
||||
) : (
|
||||
<pre className="overflow-auto whitespace-pre-wrap break-words font-mono text-sm text-ds-text-neutral-default-default">
|
||||
<pre className="font-mono text-sm text-ds-text-neutral-default-default overflow-auto break-words whitespace-pre-wrap">
|
||||
{selectedFile.content}
|
||||
</pre>
|
||||
)
|
||||
) : (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="text-center">
|
||||
<div className="mx-auto mb-4 h-8 w-8 animate-spin rounded-full"></div>
|
||||
<div className="mb-4 h-8 w-8 animate-spin mx-auto rounded-full"></div>
|
||||
<p className="text-body-sm text-ds-text-neutral-muted-default">
|
||||
{t('chat.loading')}
|
||||
</p>
|
||||
|
|
@ -1933,9 +1933,9 @@ export default function Folder({ data: _data }: { data?: Agent }) {
|
|||
</div>
|
||||
)
|
||||
) : (
|
||||
<div className="flex h-full w-full flex-1 items-center justify-center text-ds-text-neutral-muted-default">
|
||||
<div className="text-ds-text-neutral-muted-default flex h-full w-full flex-1 items-center justify-center">
|
||||
<div className="text-center">
|
||||
<FileText className="mx-auto mb-4 h-12 w-12 text-ds-text-neutral-muted-default" />
|
||||
<FileText className="mb-4 h-12 w-12 text-ds-text-neutral-muted-default mx-auto" />
|
||||
<p className="text-sm">
|
||||
{t('chat.select-a-file-to-view-its-contents')}
|
||||
</p>
|
||||
|
|
@ -2029,7 +2029,7 @@ function ImageLoader({ selectedFile }: { selectedFile: FileInfo }) {
|
|||
if (!src) {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="mx-auto h-8 w-8 animate-spin rounded-full" />
|
||||
<div className="h-8 w-8 animate-spin mx-auto rounded-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -2058,7 +2058,7 @@ function AudioLoader({ selectedFile }: { selectedFile: FileInfo }) {
|
|||
}, [selectedFile]);
|
||||
|
||||
return (
|
||||
<div className="flex w-full flex-col items-center gap-4 px-8">
|
||||
<div className="gap-4 px-8 flex w-full flex-col items-center">
|
||||
<p className="text-sm font-medium text-ds-text-neutral-default-default">
|
||||
{selectedFile.name}
|
||||
</p>
|
||||
|
|
@ -2948,7 +2948,7 @@ function HtmlRenderer({
|
|||
if (selectedFile.content && !processedHtml) {
|
||||
return (
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
<div className="mx-auto mb-4 h-8 w-8 animate-spin rounded-full" />
|
||||
<div className="mb-4 h-8 w-8 animate-spin mx-auto rounded-full" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -2965,7 +2965,7 @@ function HtmlRenderer({
|
|||
|
||||
{/* Content area with zoom */}
|
||||
<div
|
||||
className="min-h-0 flex-1 overflow-hidden bg-code-surface"
|
||||
className="min-h-0 bg-code-surface flex-1 overflow-hidden"
|
||||
onWheel={handleWheel}
|
||||
>
|
||||
<div
|
||||
|
|
@ -16,7 +16,7 @@ import larkIcon from '@/assets/icon/lark.png';
|
|||
import telegramIcon from '@/assets/icon/telegram.svg';
|
||||
import whatsappIcon from '@/assets/icon/whatsapp.svg';
|
||||
import { isDesktop } from '@/client/platform';
|
||||
import { SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Session/sessionSidePanelLayout';
|
||||
import { PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Project/projectSidePanelLayout';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
createRemoteControlSession,
|
||||
|
|
@ -77,15 +77,15 @@ function BentoSessionGrid({
|
|||
|
||||
if (count === 1) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full flex-col">
|
||||
<div className="h-1/2 min-h-0 w-full">{renderCard(sessions[0])}</div>
|
||||
<div className="min-h-0 flex h-full w-full flex-col">
|
||||
<div className="min-h-0 h-1/2 w-full">{renderCard(sessions[0])}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (count === 2) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full flex-col gap-3">
|
||||
<div className="min-h-0 gap-3 flex h-full w-full flex-col">
|
||||
{sessions.map((session) => (
|
||||
<div key={session.sessionId} className="min-h-0 flex-1">
|
||||
{renderCard(session)}
|
||||
|
|
@ -103,7 +103,7 @@ function BentoSessionGrid({
|
|||
return (
|
||||
<div className={gridClassName}>
|
||||
{sessions.map((session) => (
|
||||
<div key={session.sessionId} className="h-full min-h-0">
|
||||
<div key={session.sessionId} className="min-h-0 h-full">
|
||||
{renderCard(session)}
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -121,14 +121,14 @@ function BentoCard({
|
|||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 flex-col gap-2 rounded-2xl border border-ds-border-neutral-subtle-default bg-ds-bg-neutral-default-default p-3">
|
||||
<div className="min-h-0 gap-2 rounded-2xl border-ds-border-neutral-subtle-default bg-ds-bg-neutral-default-default p-3 flex h-full flex-col border">
|
||||
{/* Header */}
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<div className="min-w-0 gap-2 flex items-center">
|
||||
<MonitorSmartphone
|
||||
className="h-4 w-4 shrink-0 text-ds-text-neutral-muted-default"
|
||||
className="h-4 w-4 text-ds-text-neutral-muted-default shrink-0"
|
||||
aria-hidden
|
||||
/>
|
||||
<span className="min-w-0 flex-1 truncate text-body-sm font-semibold text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-body-sm font-semibold text-ds-text-neutral-default-default flex-1 truncate">
|
||||
{session.title}
|
||||
</span>
|
||||
<Button
|
||||
|
|
@ -136,7 +136,7 @@ function BentoCard({
|
|||
variant="primary"
|
||||
size="xs"
|
||||
buttonContent="text"
|
||||
className="no-drag shrink-0 gap-1.5"
|
||||
className="no-drag gap-1.5 shrink-0"
|
||||
onClick={onCopy}
|
||||
>
|
||||
<Copy className="h-3 w-3" aria-hidden />
|
||||
|
|
@ -148,7 +148,7 @@ function BentoCard({
|
|||
tone="error"
|
||||
size="xs"
|
||||
buttonContent="text"
|
||||
className="no-drag shrink-0 gap-1"
|
||||
className="no-drag gap-1 shrink-0"
|
||||
disabled={stopping}
|
||||
onClick={onStop}
|
||||
>
|
||||
|
|
@ -162,7 +162,7 @@ function BentoCard({
|
|||
</div>
|
||||
|
||||
{/* Log */}
|
||||
<div className="min-h-0 flex-1 border-t border-ds-border-neutral-subtle-default pt-2">
|
||||
<div className="min-h-0 border-ds-border-neutral-subtle-default pt-2 flex-1 border-t">
|
||||
<LogPanel logs={logs} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -195,8 +195,8 @@ function ChannelRow({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'group/row flex h-[44px] w-full cursor-default select-none items-center gap-3 rounded-xl',
|
||||
'border border-transparent bg-ds-bg-neutral-default-default px-3',
|
||||
'group/row gap-3 rounded-xl flex h-[44px] w-full cursor-default items-center select-none',
|
||||
'bg-ds-bg-neutral-default-default px-3 border border-transparent',
|
||||
'transition-colors duration-150',
|
||||
!disabled && 'hover:border-ds-border-neutral-subtle-default',
|
||||
hasActiveSessions && 'border-ds-border-neutral-subtle-default',
|
||||
|
|
@ -214,20 +214,20 @@ function ChannelRow({
|
|||
/>
|
||||
)}
|
||||
</div>
|
||||
<span className="flex-1 truncate text-body-sm font-medium text-ds-text-neutral-default-default">
|
||||
<span className="text-body-sm font-medium text-ds-text-neutral-default-default flex-1 truncate">
|
||||
{name}
|
||||
</span>
|
||||
|
||||
{/* Right slot — always the same reserved width so all rows stay the same height */}
|
||||
<div className="flex h-6 w-[72px] shrink-0 items-center justify-end">
|
||||
<div className="h-6 flex w-[72px] shrink-0 items-center justify-end">
|
||||
{comingSoon && (
|
||||
<span className="shrink-0 rounded-full bg-ds-bg-neutral-muted-default px-2 py-0.5 text-label-xs text-ds-text-neutral-muted-default">
|
||||
<span className="bg-ds-bg-neutral-muted-default px-2 py-0.5 text-label-xs text-ds-text-neutral-muted-default shrink-0 rounded-full">
|
||||
{t('layout.dispatch-coming-soon', { defaultValue: 'Coming soon' })}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{!disabled && !comingSoon && hasActiveSessions && (
|
||||
<span className="shrink-0 rounded-full bg-ds-bg-success-subtle-default px-2 py-0.5 text-label-xs text-ds-text-success-strong-default">
|
||||
<span className="bg-ds-bg-success-subtle-default px-2 py-0.5 text-label-xs text-ds-text-success-strong-default shrink-0 rounded-full">
|
||||
{t('layout.dispatch-connected', { defaultValue: 'Connected' })}
|
||||
</span>
|
||||
)}
|
||||
|
|
@ -238,7 +238,7 @@ function ChannelRow({
|
|||
variant="secondary"
|
||||
size="xs"
|
||||
buttonContent="text"
|
||||
className="no-drag shrink-0 gap-1"
|
||||
className="no-drag gap-1 shrink-0"
|
||||
disabled={loading}
|
||||
onClick={onStart}
|
||||
>
|
||||
|
|
@ -286,12 +286,12 @@ function LogPanel({ logs }: { logs: RemoteControlLogEntry[] }) {
|
|||
{[...logs].reverse().map((entry) => (
|
||||
<div
|
||||
key={entry.id}
|
||||
className="flex min-w-0 items-center gap-3 px-1 py-1.5 text-label-xs"
|
||||
className="min-w-0 gap-3 px-1 py-1.5 text-label-xs flex items-center"
|
||||
>
|
||||
<span className="w-[72px] shrink-0 tabular-nums text-ds-text-neutral-muted-default">
|
||||
<span className="text-ds-text-neutral-muted-default w-[72px] shrink-0 tabular-nums">
|
||||
{formatLogTime(entry.time)}
|
||||
</span>
|
||||
<span className="min-w-0 flex-1 truncate text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-ds-text-neutral-default-default flex-1 truncate">
|
||||
{entry.name}
|
||||
</span>
|
||||
<span
|
||||
|
|
@ -538,14 +538,14 @@ export function WorkspaceDispatch() {
|
|||
);
|
||||
|
||||
const channelList = (
|
||||
<div className="flex w-full flex-col gap-1">
|
||||
<div className="gap-1 flex w-full flex-col">
|
||||
<ChannelRow
|
||||
name={t('layout.workspace-work-with-remote-control', {
|
||||
defaultValue: 'Remote Control',
|
||||
})}
|
||||
icon={
|
||||
<MonitorSmartphone
|
||||
className="h-4 w-4 shrink-0 text-ds-text-neutral-muted-default"
|
||||
className="h-4 w-4 text-ds-text-neutral-muted-default shrink-0"
|
||||
aria-hidden
|
||||
/>
|
||||
}
|
||||
|
|
@ -554,7 +554,7 @@ export function WorkspaceDispatch() {
|
|||
onStart={() => void handleCreateRemoteControl()}
|
||||
/>
|
||||
|
||||
<div className="mx-1 border-t border-ds-border-neutral-subtle-default" />
|
||||
<div className="mx-1 border-ds-border-neutral-subtle-default border-t" />
|
||||
|
||||
<ChannelRow
|
||||
name={t('layout.channels-telegram', { defaultValue: 'Telegram' })}
|
||||
|
|
@ -578,28 +578,28 @@ export function WorkspaceDispatch() {
|
|||
);
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full flex-col overflow-hidden">
|
||||
<div className="min-h-0 flex h-full w-full flex-col overflow-hidden">
|
||||
{/* Header */}
|
||||
<div className="border-b-1 box-border flex h-[45.5px] w-full shrink-0 items-center gap-2 border-x-0 border-t-0 border-solid border-ds-border-neutral-subtle-default px-3">
|
||||
<div className="gap-2 border-ds-border-neutral-subtle-default px-3 box-border flex h-[45.5px] w-full shrink-0 items-center border-x-0 border-t-0 border-b-1 border-solid">
|
||||
<span className="text-body-md font-bold text-ds-text-neutral-muted-default">
|
||||
{t('layout.workspace-work-with-title', { defaultValue: 'Work with' })}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
<div className="relative flex min-h-0 w-full flex-1 overflow-hidden">
|
||||
<div className="min-h-0 relative flex w-full flex-1 overflow-hidden">
|
||||
{/* Centered default state */}
|
||||
<AnimatePresence initial={false}>
|
||||
{!hasSessions && (
|
||||
<motion.div
|
||||
key="centered"
|
||||
className="absolute inset-0 flex items-start justify-center overflow-y-auto p-6"
|
||||
className="inset-0 p-6 absolute flex items-start justify-center overflow-y-auto"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, transition: { duration: 0.15 } }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
<div className="w-full max-w-xl">{channelList}</div>
|
||||
<div className="max-w-xl w-full">{channelList}</div>
|
||||
</motion.div>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
|
|
@ -609,14 +609,14 @@ export function WorkspaceDispatch() {
|
|||
{hasSessions && (
|
||||
<motion.div
|
||||
key="split"
|
||||
className="absolute inset-0 flex overflow-hidden"
|
||||
className="inset-0 absolute flex overflow-hidden"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
exit={{ opacity: 0, transition: { duration: 0.15 } }}
|
||||
transition={{ duration: 0.2 }}
|
||||
>
|
||||
{/* Left column: dynamic bento layout by session count */}
|
||||
<div className="flex min-h-0 flex-1 flex-col overflow-hidden p-3">
|
||||
<div className="min-h-0 p-3 flex flex-1 flex-col overflow-hidden">
|
||||
<BentoSessionGrid
|
||||
sessions={activeSessions}
|
||||
logs={logs}
|
||||
|
|
@ -629,8 +629,8 @@ export function WorkspaceDispatch() {
|
|||
{/* Right panel — same width as session side panel */}
|
||||
<motion.div
|
||||
className={cn(
|
||||
'flex shrink-0 flex-col gap-1 overflow-y-auto border-l border-ds-border-neutral-subtle-default p-3',
|
||||
SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS
|
||||
'gap-1 border-ds-border-neutral-subtle-default p-3 flex shrink-0 flex-col overflow-y-auto border-l',
|
||||
PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS
|
||||
)}
|
||||
initial={{ x: 40, opacity: 0 }}
|
||||
animate={{ x: 0, opacity: 1 }}
|
||||
|
|
|
|||
|
|
@ -82,8 +82,8 @@ export function NavTabReconnectSuffix({
|
|||
<button
|
||||
type="button"
|
||||
className={cn(
|
||||
'no-drag flex h-8 w-8 shrink-0 items-center justify-center rounded-xl text-ds-icon-neutral-muted-default outline-none transition-colors hover:bg-ds-bg-neutral-strong-default',
|
||||
'focus-visible:z-10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ds-ring-neutral-subtle-default'
|
||||
'no-drag h-8 w-8 rounded-xl text-ds-icon-neutral-muted-default hover:bg-ds-bg-neutral-strong-default flex shrink-0 items-center justify-center transition-colors outline-none',
|
||||
'focus-visible:ring-ds-ring-neutral-subtle-default focus-visible:z-10 focus-visible:ring-2 focus-visible:outline-none'
|
||||
)}
|
||||
aria-label={reconnectLabel}
|
||||
onClick={(e) => {
|
||||
|
|
@ -163,7 +163,7 @@ function tabMainInner({
|
|||
<>
|
||||
{leading}
|
||||
<motion.div
|
||||
className="flex min-w-0 flex-1 items-center gap-3 overflow-hidden"
|
||||
className="min-w-0 gap-3 flex flex-1 items-center overflow-hidden"
|
||||
initial={false}
|
||||
animate={{
|
||||
opacity: folded ? 0 : 1,
|
||||
|
|
@ -267,7 +267,7 @@ export function NavTab({
|
|||
</button>
|
||||
{suffix || endAction ? (
|
||||
<motion.div
|
||||
className="flex min-h-8 min-w-0 items-stretch overflow-hidden"
|
||||
className="min-h-8 min-w-0 flex items-stretch overflow-hidden"
|
||||
initial={false}
|
||||
animate={{
|
||||
opacity: folded ? 0 : 1,
|
||||
|
|
@ -281,7 +281,7 @@ export function NavTab({
|
|||
{endAction ? (
|
||||
<div
|
||||
className={cn(
|
||||
'flex max-w-0 shrink-0 items-center justify-end overflow-hidden opacity-0 transition-[max-width,opacity] duration-150 ease-out',
|
||||
'max-w-0 ease-out flex shrink-0 items-center justify-end overflow-hidden opacity-0 transition-[max-width,opacity] duration-150',
|
||||
'pointer-events-none opacity-0',
|
||||
'group-hover:pointer-events-auto group-hover:opacity-100',
|
||||
endActionMaxWidthClass ??
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
import {
|
||||
NavListSessionRows,
|
||||
type NavListSession,
|
||||
} from '@/components/ProjectPageSidebar/NavList';
|
||||
} from '@/components/PageSidebar/NavList';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { TooltipSimple } from '@/components/ui/tooltip';
|
||||
import { taskIdToCreatedMs } from '@/lib/chatTaskIdTime';
|
||||
|
|
@ -30,7 +30,7 @@ import { useTranslation } from 'react-i18next';
|
|||
|
||||
export { default as SessionWorkspace } from '.';
|
||||
|
||||
type SessionsProps = {
|
||||
type ProjectGroupProps = {
|
||||
className?: string;
|
||||
tasks: ChatStore['tasks'];
|
||||
activeSessionId?: string | null;
|
||||
|
|
@ -38,13 +38,13 @@ type SessionsProps = {
|
|||
onDeleteSession: (sessionId: string) => void;
|
||||
};
|
||||
|
||||
export default function Sessions({
|
||||
export default function ProjectGroup({
|
||||
className,
|
||||
tasks,
|
||||
activeSessionId,
|
||||
onSelectSession,
|
||||
onDeleteSession,
|
||||
}: SessionsProps) {
|
||||
}: ProjectGroupProps) {
|
||||
const { t } = useTranslation();
|
||||
const setActiveWorkspaceTab = usePageTabStore((s) => s.setActiveWorkspaceTab);
|
||||
const backToWorkspaceTooltip = t('layout.back-to-workspace-tooltip');
|
||||
|
|
@ -73,11 +73,11 @@ export default function Sessions({
|
|||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden',
|
||||
'min-h-0 min-w-0 flex h-full w-full flex-col overflow-hidden',
|
||||
className
|
||||
)}
|
||||
>
|
||||
<div className="border-b-1 flex w-full shrink-0 items-center gap-2 border-x-0 border-t-0 border-solid border-ds-border-neutral-subtle-default px-2 py-2">
|
||||
<div className="gap-2 border-ds-border-neutral-subtle-default px-2 py-2 flex w-full shrink-0 items-center border-x-0 border-t-0 border-b-1 border-solid">
|
||||
<TooltipSimple content={backToWorkspaceTooltip}>
|
||||
<Button
|
||||
type="button"
|
||||
|
|
@ -85,19 +85,19 @@ export default function Sessions({
|
|||
size="sm"
|
||||
buttonContent="icon-only"
|
||||
onClick={() => setActiveWorkspaceTab('workforce')}
|
||||
className="no-drag shrink-0 text-ds-text-neutral-muted-default hover:bg-ds-bg-neutral-strong-default"
|
||||
className="no-drag text-ds-text-neutral-muted-default hover:bg-ds-bg-neutral-strong-default shrink-0"
|
||||
aria-label={backToWorkspaceTooltip}
|
||||
>
|
||||
<ArrowLeft className="h-4 w-4" aria-hidden />
|
||||
</Button>
|
||||
</TooltipSimple>
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2 px-1 text-body-md font-bold text-ds-text-neutral-default-default">
|
||||
<div className="min-w-0 gap-2 px-1 text-body-md font-bold text-ds-text-neutral-default-default flex flex-1 items-center">
|
||||
<span className="truncate">{t('layout.sessions-full-title')}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="m-0 mx-auto flex min-h-0 w-full max-w-[800px] flex-1 flex-col gap-0.5 overflow-y-auto p-2">
|
||||
<div className="m-0 min-h-0 gap-0.5 p-2 mx-auto flex w-full max-w-[800px] flex-1 flex-col overflow-y-auto">
|
||||
{sessions.length === 0 ? (
|
||||
<p className="m-0 px-3 py-6 text-center text-body-sm text-ds-text-neutral-muted-default">
|
||||
<p className="m-0 px-3 py-6 text-body-sm text-ds-text-neutral-muted-default text-center">
|
||||
{t('layout.sessions-create-task-hint')}
|
||||
</p>
|
||||
) : (
|
||||
|
|
@ -12,12 +12,12 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SessionSidePanelHeader } from '@/components/Session/SessionSidePanelHeader';
|
||||
import { SingleAgentSidePanel } from '@/components/Session/SingleAgent/SingleAgentSidePanel';
|
||||
import { TurnTabs } from '@/components/Session/TurnTabs';
|
||||
import { WorkforceSidePanel } from '@/components/Session/Workforce/WorkforceSidePanel';
|
||||
import { WorkforceSidePanelHeaderEnd } from '@/components/Session/Workforce/WorkforceSidePanelHeaderEnd';
|
||||
import { SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Session/sessionSidePanelLayout';
|
||||
import { ProjectSidePanelHeader } from '@/components/Project/ProjectSidePanelHeader';
|
||||
import { SingleAgentSidePanel } from '@/components/Project/SingleAgent/SingleAgentSidePanel';
|
||||
import { TurnTabs } from '@/components/Project/TurnTabs';
|
||||
import { WorkforceSidePanel } from '@/components/Project/Workforce/WorkforceSidePanel';
|
||||
import { WorkforceSidePanelHeaderEnd } from '@/components/Project/Workforce/WorkforceSidePanelHeaderEnd';
|
||||
import { PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Project/projectSidePanelLayout';
|
||||
import { TooltipSimple } from '@/components/ui/tooltip';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { SessionMode, type SessionModeType } from '@/types/constants';
|
||||
|
|
@ -35,7 +35,7 @@ export interface SessionSidePanelProps {
|
|||
onCloseExpandedOverlay: () => void;
|
||||
}
|
||||
|
||||
export function SessionSidePanel({
|
||||
export function ProjectSidePanel({
|
||||
mode,
|
||||
workforcePanelKey,
|
||||
hasAnyMessages,
|
||||
|
|
@ -68,12 +68,12 @@ export function SessionSidePanel({
|
|||
<div
|
||||
className={cn(
|
||||
'min-h-0 flex h-full flex-shrink-0 flex-col overflow-hidden',
|
||||
SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS,
|
||||
PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS,
|
||||
isFolded &&
|
||||
'pointer-events-none opacity-40 transition-opacity duration-200 group-hover:opacity-80'
|
||||
)}
|
||||
>
|
||||
<SessionSidePanelHeader
|
||||
<ProjectSidePanelHeader
|
||||
title={headerTitle}
|
||||
mode={mode}
|
||||
isSidePanelVisible={isSidePanelVisible}
|
||||
|
|
@ -19,19 +19,19 @@ import type { SessionModeType } from '@/types/constants';
|
|||
import { PanelRight, PanelRightClose } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export interface SessionSidePanelFoldButtonProps {
|
||||
export interface ProjectSidePanelFoldButtonProps {
|
||||
sessionSidePanelMode: SessionModeType;
|
||||
isSidePanelVisible: boolean;
|
||||
onToggle: () => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function SessionSidePanelFoldButton({
|
||||
export function ProjectSidePanelFoldButton({
|
||||
sessionSidePanelMode,
|
||||
isSidePanelVisible,
|
||||
onToggle,
|
||||
className,
|
||||
}: SessionSidePanelFoldButtonProps) {
|
||||
}: ProjectSidePanelFoldButtonProps) {
|
||||
const { t } = useTranslation();
|
||||
const sessionSidePanelTooltip =
|
||||
sessionSidePanelMode === 'single-agent'
|
||||
|
|
@ -12,11 +12,11 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SessionSidePanelFoldButton } from '@/components/Session/SessionSidePanelFoldButton';
|
||||
import { ProjectSidePanelFoldButton } from '@/components/Project/ProjectSidePanelFoldButton';
|
||||
import type { SessionModeType } from '@/types/constants';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
export interface SessionSidePanelHeaderProps {
|
||||
export interface ProjectSidePanelHeaderProps {
|
||||
title: string;
|
||||
mode: SessionModeType;
|
||||
isSidePanelVisible: boolean;
|
||||
|
|
@ -27,18 +27,18 @@ export interface SessionSidePanelHeaderProps {
|
|||
end?: ReactNode;
|
||||
}
|
||||
|
||||
export function SessionSidePanelHeader({
|
||||
export function ProjectSidePanelHeader({
|
||||
title,
|
||||
mode,
|
||||
isSidePanelVisible,
|
||||
onToggle,
|
||||
start,
|
||||
end,
|
||||
}: SessionSidePanelHeaderProps) {
|
||||
}: ProjectSidePanelHeaderProps) {
|
||||
return (
|
||||
<div className="p-2 min-w-0 relative z-50 flex w-full shrink-0 items-center">
|
||||
<div className="min-w-0 gap-1 flex flex-1 items-center justify-start">
|
||||
<SessionSidePanelFoldButton
|
||||
<ProjectSidePanelFoldButton
|
||||
sessionSidePanelMode={mode}
|
||||
isSidePanelVisible={isSidePanelVisible}
|
||||
onToggle={onToggle}
|
||||
|
|
@ -12,8 +12,8 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SidePanelAccordionBox } from '@/components/Session/SidePanelAccordionBox';
|
||||
import { SidePanelListRow } from '@/components/Session/SidePanelSections/primitives';
|
||||
import { SidePanelAccordionBox } from '@/components/Project/SidePanelAccordionBox';
|
||||
import { SidePanelListRow } from '@/components/Project/SidePanelSections/primitives';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import {
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SidePanelAccordionBox } from '@/components/Session/SidePanelAccordionBox';
|
||||
import { SidePanelAccordionBox } from '@/components/Project/SidePanelAccordionBox';
|
||||
import ShinyText from '@/components/ui/ShinyText/ShinyText';
|
||||
import { agentMap, type WorkflowAgentType } from '@/components/WorkFlow/agents';
|
||||
import { getToolkitIcon } from '@/lib/toolkitIcons';
|
||||
|
|
@ -12,11 +12,11 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SidePanelAccordionBox } from '@/components/Session/SidePanelAccordionBox';
|
||||
import { SidePanelAccordionBox } from '@/components/Project/SidePanelAccordionBox';
|
||||
import {
|
||||
CategoryLabel,
|
||||
SidePanelListRow,
|
||||
} from '@/components/Session/SidePanelSections/primitives';
|
||||
} from '@/components/Project/SidePanelSections/primitives';
|
||||
import { AnimatePresence, motion } from 'framer-motion';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
|
|
@ -12,13 +12,13 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SidePanelAccordionBox } from '@/components/Session/SidePanelAccordionBox';
|
||||
import { SidePanelAccordionBox } from '@/components/Project/SidePanelAccordionBox';
|
||||
import {
|
||||
CountPill,
|
||||
ProgressCircle,
|
||||
ProgressConnector,
|
||||
SidePanelListRow,
|
||||
} from '@/components/Session/SidePanelSections/primitives';
|
||||
} from '@/components/Project/SidePanelSections/primitives';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { usePageTabStore } from '@/store/pageTabStore';
|
||||
import { TaskStatus } from '@/types/constants';
|
||||
|
|
@ -12,15 +12,15 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { AgentFolderSection } from '@/components/Session/SidePanelSections/AgentFolderSection';
|
||||
import { ExecutionContextSection } from '@/components/Session/SidePanelSections/ExecutionContextSection';
|
||||
import { ProgressSection } from '@/components/Session/SidePanelSections/ProgressSection';
|
||||
import { buildContextItems } from '@/components/Session/SidePanelSections/buildContextItems';
|
||||
import { AgentFolderSection } from '@/components/Project/SidePanelSections/AgentFolderSection';
|
||||
import { ExecutionContextSection } from '@/components/Project/SidePanelSections/ExecutionContextSection';
|
||||
import { ProgressSection } from '@/components/Project/SidePanelSections/ProgressSection';
|
||||
import { buildContextItems } from '@/components/Project/SidePanelSections/buildContextItems';
|
||||
import {
|
||||
collectSidePanelOutputFiles,
|
||||
mergeSidePanelOutputFiles,
|
||||
} from '@/components/Session/SidePanelSections/collectSidePanelOutputFiles';
|
||||
import { useProjectOutputFiles } from '@/components/Session/SidePanelSections/useProjectOutputFiles';
|
||||
} from '@/components/Project/SidePanelSections/collectSidePanelOutputFiles';
|
||||
import { useProjectOutputFiles } from '@/components/Project/SidePanelSections/useProjectOutputFiles';
|
||||
import useChatStoreAdapter from '@/hooks/useChatStoreAdapter';
|
||||
import { useSelectedProjectTurn } from '@/hooks/useSelectedProjectTurn';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
|
@ -12,11 +12,11 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import BrowserAgentWorkspace from '@/components/BrowserAgentWorkspace';
|
||||
import Folder from '@/components/Folder';
|
||||
import TerminalAgentWorkspace from '@/components/TerminalAgentWorkspace';
|
||||
import Context from '@/components/Context';
|
||||
import Workflow from '@/components/WorkFlow';
|
||||
import WorkforceMenu from '@/components/WorkforceMenu';
|
||||
import BrowserAgentWorkspace from '@/components/WorkFlow/BrowserAgentWorkspace';
|
||||
import TerminalAgentWorkspace from '@/components/WorkFlow/TerminalAgentWorkspace';
|
||||
import WorkflowMenu from '@/components/WorkFlow/WorkflowMenu';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { TooltipSimple } from '@/components/ui/tooltip';
|
||||
import type { SelectedProjectTurn } from '@/hooks/useSelectedProjectTurn';
|
||||
|
|
@ -90,7 +90,7 @@ function WorkforceOverlayCanvas({
|
|||
<div className="relative flex h-full w-full flex-col">
|
||||
<div className="backdrop-blur-sm inset-0 rounded-xl bg-ds-bg-neutral-default-default pointer-events-none absolute"></div>
|
||||
<div className="relative z-10 h-full w-full">
|
||||
<Folder />
|
||||
<Context />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -102,7 +102,7 @@ function WorkforceOverlayCanvas({
|
|||
<div className="relative flex h-full w-full flex-col">
|
||||
<div className="backdrop-blur-sm inset-0 rounded-xl bg-ds-bg-neutral-default-default pointer-events-none absolute"></div>
|
||||
<div className="relative z-10 h-full w-full">
|
||||
<Folder
|
||||
<Context
|
||||
data={activeTask.taskAssigning?.find(
|
||||
(agent) => agent.agent_id === activeWorkSpace
|
||||
)}
|
||||
|
|
@ -116,7 +116,7 @@ function WorkforceOverlayCanvas({
|
|||
<div className="relative flex h-full w-full flex-col">
|
||||
<div className="backdrop-blur-sm inset-0 rounded-xl bg-ds-bg-neutral-default-default pointer-events-none absolute"></div>
|
||||
<div className="relative z-10 h-full w-full">
|
||||
<Folder />
|
||||
<Context />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -239,7 +239,7 @@ export default function ExpandedOverlay({
|
|||
</div>
|
||||
<div className="relative z-50 shrink-0">
|
||||
<div className="pointer-events-auto">
|
||||
<WorkforceMenu
|
||||
<WorkflowMenu
|
||||
onToggleChatBox={onToggleSidePanel}
|
||||
isChatBoxVisible={!isSidePanelVisible}
|
||||
/>
|
||||
|
|
@ -12,7 +12,7 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import Folder from '@/components/Folder';
|
||||
import Context from '@/components/Context';
|
||||
import { TaskState, type TaskStateType } from '@/components/TaskState';
|
||||
import Terminal from '@/components/Terminal';
|
||||
import { TaskLogPanelContent } from '@/components/WorkFlow/TaskLogPanelContent';
|
||||
|
|
@ -190,10 +190,10 @@ export function AgentDetailPane({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden rounded-xl bg-ds-bg-neutral-strong-default">
|
||||
<div className="min-h-0 min-w-0 rounded-xl bg-ds-bg-neutral-strong-default flex h-full w-full flex-col overflow-hidden">
|
||||
<div
|
||||
className={cn(
|
||||
'top-0 min-h-0 w-full min-w-0 max-w-full shrink-0 bg-ds-bg-neutral-strong-default pb-2 pt-2'
|
||||
'top-0 min-h-0 min-w-0 bg-ds-bg-neutral-strong-default pb-2 pt-2 w-full max-w-full shrink-0'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
@ -205,7 +205,7 @@ export function AgentDetailPane({
|
|||
{preset?.name ?? agent.name}
|
||||
</div>
|
||||
<div
|
||||
className="mt-sm min-h-4 w-full min-w-0 max-w-full px-3"
|
||||
className="mt-sm min-h-4 min-w-0 px-3 w-full max-w-full"
|
||||
onPointerEnter={() => setToolkitHovered(true)}
|
||||
onPointerLeave={() => setToolkitHovered(false)}
|
||||
>
|
||||
|
|
@ -217,7 +217,7 @@ export function AgentDetailPane({
|
|||
/>
|
||||
</div>
|
||||
{agent.tasks && agent.tasks.length > 0 && (
|
||||
<div className="flex flex-col items-start justify-between gap-1 border-0 border-b border-solid border-ds-border-neutral-default-default px-3 py-sm">
|
||||
<div className="gap-1 border-ds-border-neutral-default-default px-3 py-sm flex flex-col items-start justify-between border-0 border-b border-solid">
|
||||
<div className="flex w-full flex-1 justify-start">
|
||||
<TaskState
|
||||
all={agent.tasks?.length || 0}
|
||||
|
|
@ -268,26 +268,26 @@ export function AgentDetailPane({
|
|||
</div>
|
||||
|
||||
{/* Content: agent summary + task list; task log slides in from the right */}
|
||||
<div className="relative min-h-0 flex-1 overflow-hidden">
|
||||
<div className="min-h-0 relative flex-1 overflow-hidden">
|
||||
<div
|
||||
className="scrollbar scrollbar-always-visible h-full min-h-0 overflow-y-auto"
|
||||
className="scrollbar scrollbar-always-visible min-h-0 h-full overflow-y-auto"
|
||||
onWheel={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div
|
||||
className="mb-2 mt-1 max-h-[180px] w-full pl-3"
|
||||
className="mb-2 mt-1 pl-3 max-h-[180px] w-full"
|
||||
onClick={focusAgent}
|
||||
>
|
||||
{browserImages.length > 0 && (
|
||||
<div
|
||||
className={`grid h-[180px] w-full gap-1 overflow-hidden ${browserImageGridClass}`}
|
||||
className={`gap-1 grid h-[180px] w-full overflow-hidden ${browserImageGridClass}`}
|
||||
>
|
||||
{browserImages.map((img, index) => (
|
||||
<div
|
||||
key={`${img.img}-${index}`}
|
||||
className="relative h-full w-full overflow-hidden rounded-lg"
|
||||
className="rounded-lg relative h-full w-full overflow-hidden"
|
||||
>
|
||||
<img
|
||||
className="absolute left-0 top-0 h-[250%] w-[250%] origin-top-left scale-[0.4] object-cover"
|
||||
className="left-0 top-0 absolute h-[250%] w-[250%] origin-top-left scale-[0.4] object-cover"
|
||||
src={img.img}
|
||||
alt={agent.type}
|
||||
/>
|
||||
|
|
@ -297,7 +297,7 @@ export function AgentDetailPane({
|
|||
(_, index) => (
|
||||
<div
|
||||
key={`browser-placeholder-${index}`}
|
||||
className="h-full w-full rounded-sm bg-ds-bg-neutral-subtle-default"
|
||||
className="rounded-sm bg-ds-bg-neutral-subtle-default h-full w-full"
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
|
@ -306,23 +306,23 @@ export function AgentDetailPane({
|
|||
{agent.type === 'document_agent' &&
|
||||
agent.tasks &&
|
||||
agent.tasks.length > 0 && (
|
||||
<div className="relative h-[180px] w-full overflow-hidden rounded-sm">
|
||||
<div className="absolute left-0 top-0 h-[500px] w-[900px] origin-top-left scale-[0.36]">
|
||||
<Folder data={agent} />
|
||||
<div className="rounded-sm relative h-[180px] w-full overflow-hidden">
|
||||
<div className="left-0 top-0 absolute h-[500px] w-[900px] origin-top-left scale-[0.36]">
|
||||
<Context data={agent} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{agent.type === 'developer_agent' && terminalTasks.length > 0 && (
|
||||
<div
|
||||
className={`grid h-[180px] w-full gap-1 overflow-hidden ${terminalGridClass}`}
|
||||
className={`gap-1 grid h-[180px] w-full overflow-hidden ${terminalGridClass}`}
|
||||
>
|
||||
{terminalTasks.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="relative h-full w-full overflow-hidden rounded-lg object-cover"
|
||||
className="rounded-lg relative h-full w-full overflow-hidden object-cover"
|
||||
>
|
||||
<div className="absolute left-0 top-0 h-[250%] w-[250%] origin-top-left scale-[0.4]">
|
||||
<div className="left-0 top-0 absolute h-[250%] w-[250%] origin-top-left scale-[0.4]">
|
||||
<Terminal content={task.terminal} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -331,7 +331,7 @@ export function AgentDetailPane({
|
|||
(_, index) => (
|
||||
<div
|
||||
key={`terminal-placeholder-${index}`}
|
||||
className="h-full w-full rounded-lg bg-ds-bg-neutral-subtle-default"
|
||||
className="rounded-lg bg-ds-bg-neutral-subtle-default h-full w-full"
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
|
@ -339,7 +339,7 @@ export function AgentDetailPane({
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-2 pb-3 pl-3">
|
||||
<div className="gap-2 pb-3 pl-3 flex flex-col">
|
||||
{agent.tasks &&
|
||||
filterTasks.map((task) => {
|
||||
const lastActiveToolkit = task.toolkits
|
||||
|
|
@ -363,7 +363,7 @@ export function AgentDetailPane({
|
|||
}
|
||||
}}
|
||||
className={cn(
|
||||
'flex cursor-pointer flex-col gap-1 rounded-xl border border-solid px-6 py-sm transition-all duration-300',
|
||||
'gap-1 rounded-xl px-6 py-sm flex cursor-pointer flex-col border border-solid transition-all duration-300',
|
||||
task.reAssignTo
|
||||
? 'bg-ds-bg-status-blocked-subtle-default'
|
||||
: task.status === TaskStatus.COMPLETED
|
||||
|
|
@ -395,9 +395,9 @@ export function AgentDetailPane({
|
|||
'border-transparent'
|
||||
)}
|
||||
>
|
||||
<div className="flex w-full items-center justify-between gap-2">
|
||||
<div className="flex min-w-0 items-center gap-x-2 gap-y-0.5">
|
||||
<div className="flex h-4 shrink-0 items-center justify-center">
|
||||
<div className="gap-2 flex w-full items-center justify-between">
|
||||
<div className="min-w-0 gap-x-2 gap-y-0.5 flex items-center">
|
||||
<div className="h-4 flex shrink-0 items-center justify-center">
|
||||
{task.reAssignTo ? (
|
||||
<CircleSlash2
|
||||
size={16}
|
||||
|
|
@ -451,12 +451,12 @@ export function AgentDetailPane({
|
|||
</>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5">
|
||||
<span className="shrink-0 text-xs font-bold leading-13 text-ds-text-neutral-default-default">
|
||||
<div className="min-w-0 gap-x-2 gap-y-0.5 flex flex-wrap items-center">
|
||||
<span className="text-xs font-bold leading-13 text-ds-text-neutral-default-default shrink-0">
|
||||
No. {getTaskIdDisplay(task.id)}
|
||||
</span>
|
||||
{task.reAssignTo ? (
|
||||
<div className="rounded-lg bg-ds-bg-document-subtle-default px-1 py-0.5 text-xs font-bold leading-none text-ds-text-warning-strong-default">
|
||||
<div className="rounded-lg bg-ds-bg-document-subtle-default px-1 py-0.5 text-xs font-bold text-ds-text-warning-strong-default leading-none">
|
||||
Reassigned to {task.reAssignTo}
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -483,7 +483,7 @@ export function AgentDetailPane({
|
|||
size="xxs"
|
||||
buttonContent="icon-only"
|
||||
buttonRadius="lg"
|
||||
className="shrink-0 text-ds-icon-neutral-muted-default opacity-50"
|
||||
className="text-ds-icon-neutral-muted-default shrink-0 opacity-50"
|
||||
aria-expanded={isExpanded}
|
||||
aria-label={
|
||||
isExpanded ? 'Collapse task details' : 'Expand task'
|
||||
|
|
@ -507,7 +507,7 @@ export function AgentDetailPane({
|
|||
</div>
|
||||
<div
|
||||
className={cn(
|
||||
'mt-0.5 w-full min-w-0 max-w-full pl-4 text-left',
|
||||
'mt-0.5 min-w-0 pl-4 w-full max-w-full text-left',
|
||||
task.status === TaskStatus.FAILED
|
||||
? 'text-ds-text-status-error-strong-default'
|
||||
: task.status === TaskStatus.BLOCKED
|
||||
|
|
@ -517,7 +517,7 @@ export function AgentDetailPane({
|
|||
>
|
||||
<div
|
||||
className={cn(
|
||||
'block select-text break-words text-label-xs font-medium',
|
||||
'text-label-xs font-medium block break-words select-text',
|
||||
!isExpanded && 'line-clamp-2 overflow-hidden',
|
||||
isExpanded && 'whitespace-pre-line'
|
||||
)}
|
||||
|
|
@ -526,17 +526,17 @@ export function AgentDetailPane({
|
|||
</div>
|
||||
</div>
|
||||
{task.status === TaskStatus.RUNNING && isExpanded && (
|
||||
<div className="duration-400 ml-4 mt-0.5 flex items-center gap-2">
|
||||
<div className="ml-4 mt-0.5 gap-2 flex items-center duration-400">
|
||||
{lastActiveToolkit?.toolkitStatus ===
|
||||
AgentStatusValue.RUNNING && (
|
||||
<div className="flex min-w-0 flex-1 items-center justify-start gap-sm duration-300">
|
||||
<div className="min-w-0 gap-sm flex flex-1 items-center justify-start duration-300">
|
||||
{getToolkitIcon(
|
||||
lastActiveToolkit.toolkitName ?? ''
|
||||
)}
|
||||
<div className="min-w-0 max-w-full flex-shrink flex-grow-0 overflow-hidden text-ellipsis whitespace-nowrap pt-1 text-xs leading-17 text-ds-text-neutral-default-default">
|
||||
<div className="min-w-0 pt-1 text-xs leading-17 text-ds-text-neutral-default-default max-w-full flex-shrink flex-grow-0 overflow-hidden text-ellipsis whitespace-nowrap">
|
||||
<ShinyText
|
||||
text={task.toolkits?.[0]?.toolkitName ?? ''}
|
||||
className="pointer-events-auto w-full select-text overflow-hidden text-ellipsis whitespace-nowrap text-xs font-bold leading-17 text-ds-text-neutral-default-default"
|
||||
className="text-xs font-bold leading-17 text-ds-text-neutral-default-default pointer-events-auto w-full overflow-hidden text-ellipsis whitespace-nowrap select-text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -557,28 +557,28 @@ export function AgentDetailPane({
|
|||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
className="absolute inset-0 z-20 flex flex-col overflow-hidden rounded-br-xl bg-ds-bg-neutral-strong-default will-change-transform"
|
||||
className="inset-0 rounded-br-xl bg-ds-bg-neutral-strong-default absolute z-20 flex flex-col overflow-hidden will-change-transform"
|
||||
>
|
||||
<div className="flex shrink-0 items-center gap-1 px-2 pb-2">
|
||||
<div className="gap-1 px-2 pb-2 flex shrink-0 items-center">
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="xxs"
|
||||
buttonContent="icon-only"
|
||||
buttonRadius="lg"
|
||||
className="shrink-0 text-ds-icon-neutral-muted-default"
|
||||
className="text-ds-icon-neutral-muted-default shrink-0"
|
||||
aria-label="Back to agent details"
|
||||
onClick={() => setDetailTask(null)}
|
||||
>
|
||||
<ChevronLeft className="size-4" aria-hidden />
|
||||
</Button>
|
||||
<span className="min-w-0 truncate text-label-sm font-bold text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-label-sm font-bold text-ds-text-neutral-default-default truncate">
|
||||
No. {getTaskIdDisplay(detailTask.id)}
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
onWheel={(e) => e.stopPropagation()}
|
||||
className="scrollbar scrollbar-always-visible min-h-0 flex-1 overflow-y-auto pb-2 pl-3 pr-1"
|
||||
className="scrollbar scrollbar-always-visible min-h-0 pb-2 pl-3 pr-1 flex-1 overflow-y-auto"
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
<motion.div
|
||||
|
|
@ -587,7 +587,7 @@ export function AgentDetailPane({
|
|||
initial="initial"
|
||||
animate="animate"
|
||||
exit="exit"
|
||||
className="flex w-full flex-col gap-sm"
|
||||
className="gap-sm flex w-full flex-col"
|
||||
>
|
||||
<TaskLogPanelContent
|
||||
selectedTask={detailTask}
|
||||
|
|
@ -12,17 +12,17 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { AgentFolderSection } from '@/components/Session/SidePanelSections/AgentFolderSection';
|
||||
import { AgentPoolSection } from '@/components/Session/SidePanelSections/AgentPoolSection';
|
||||
import { buildContextItems } from '@/components/Session/SidePanelSections/buildContextItems';
|
||||
import { AgentFolderSection } from '@/components/Project/SidePanelSections/AgentFolderSection';
|
||||
import { AgentPoolSection } from '@/components/Project/SidePanelSections/AgentPoolSection';
|
||||
import { buildContextItems } from '@/components/Project/SidePanelSections/buildContextItems';
|
||||
import {
|
||||
collectSidePanelOutputFiles,
|
||||
mergeSidePanelOutputFiles,
|
||||
} from '@/components/Session/SidePanelSections/collectSidePanelOutputFiles';
|
||||
import { ExecutionContextSection } from '@/components/Session/SidePanelSections/ExecutionContextSection';
|
||||
import { ProgressSection } from '@/components/Session/SidePanelSections/ProgressSection';
|
||||
import { useProjectOutputFiles } from '@/components/Session/SidePanelSections/useProjectOutputFiles';
|
||||
import ExpandedOverlay from '@/components/Session/Workforce/ExpandedOverlay';
|
||||
} from '@/components/Project/SidePanelSections/collectSidePanelOutputFiles';
|
||||
import { ExecutionContextSection } from '@/components/Project/SidePanelSections/ExecutionContextSection';
|
||||
import { ProgressSection } from '@/components/Project/SidePanelSections/ProgressSection';
|
||||
import { useProjectOutputFiles } from '@/components/Project/SidePanelSections/useProjectOutputFiles';
|
||||
import ExpandedOverlay from '@/components/Project/Workforce/ExpandedOverlay';
|
||||
import useChatStoreAdapter from '@/hooks/useChatStoreAdapter';
|
||||
import { useSelectedProjectTurn } from '@/hooks/useSelectedProjectTurn';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
|
@ -31,7 +31,7 @@ import { useSkillsStore } from '@/store/skillsStore';
|
|||
import { useCallback, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
/** Main column under `SessionSidePanel` header: fills remaining height in flex parent */
|
||||
/** Main column under `ProjectSidePanel` header: fills remaining height in flex parent */
|
||||
export const WORKFORCE_MAIN_SURFACE_CLASS =
|
||||
'min-w-0 flex w-full min-h-0 flex-1 flex-col overflow-hidden';
|
||||
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import ChatBox from '@/components/ChatBox';
|
||||
import { HeaderBox } from '@/components/Session/HeaderBox';
|
||||
import { HeaderBox } from '@/components/Project/HeaderBox';
|
||||
import Workspace from '@/components/Workspace';
|
||||
import useChatStoreAdapter from '@/hooks/useChatStoreAdapter';
|
||||
import { inferSessionModeFromTask } from '@/lib/sessionMode';
|
||||
|
|
@ -27,23 +27,23 @@ import {
|
|||
type SessionModeType,
|
||||
} from '@/types/constants';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { SessionSidePanel } from './SessionSidePanel';
|
||||
import { ProjectSidePanel } from './ProjectSidePanel';
|
||||
import {
|
||||
SESSION_SIDE_PANEL_EXPANDED_OUTER_CLASS,
|
||||
SESSION_SIDE_PANEL_FOLDED_OUTER_CLASS,
|
||||
} from './sessionSidePanelLayout';
|
||||
PROJECT_SIDE_PANEL_EXPANDED_OUTER_CLASS,
|
||||
PROJECT_SIDE_PANEL_FOLDED_OUTER_CLASS,
|
||||
} from './projectSidePanelLayout';
|
||||
|
||||
/**
|
||||
* Active Project: header + chat (left) and a mode-dependent side panel (right).
|
||||
* The side panel is selected from Project.mode. Task/session mode fields are
|
||||
* retained only to render legacy runs that do not have a Project mode yet.
|
||||
*/
|
||||
interface SessionProps {
|
||||
interface ProjectProps {
|
||||
/** New Project shell: empty Project that promotes to a live Project on send. */
|
||||
isNewProject?: boolean;
|
||||
}
|
||||
|
||||
export default function Session({ isNewProject = false }: SessionProps) {
|
||||
export default function Project({ isNewProject = false }: ProjectProps) {
|
||||
const { chatStore, projectStore } = useChatStoreAdapter();
|
||||
const activeWorkspaceTab = usePageTabStore((s) => s.activeWorkspaceTab);
|
||||
const setActiveWorkspaceTab = usePageTabStore((s) => s.setActiveWorkspaceTab);
|
||||
|
|
@ -226,7 +226,7 @@ export default function Session({ isNewProject = false }: SessionProps) {
|
|||
}
|
||||
|
||||
const sessionSidePanel = displaySessionMode ? (
|
||||
<SessionSidePanel
|
||||
<ProjectSidePanel
|
||||
key={displaySessionMode}
|
||||
mode={displaySessionMode}
|
||||
workforcePanelKey={workforcePanelKey}
|
||||
|
|
@ -241,10 +241,10 @@ export default function Session({ isNewProject = false }: SessionProps) {
|
|||
|
||||
if (isNewProject) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full min-w-0 flex-1 flex-row overflow-hidden">
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex h-full w-full flex-1 flex-row overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex flex-1 flex-col overflow-hidden">
|
||||
<HeaderBox empty />
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex flex-1 flex-col overflow-hidden">
|
||||
<Workspace
|
||||
variant="new-project"
|
||||
embedded
|
||||
|
|
@ -257,10 +257,10 @@ export default function Session({ isNewProject = false }: SessionProps) {
|
|||
<div
|
||||
id="session-side-panel"
|
||||
className={cn(
|
||||
'flex min-h-0 shrink-0 flex-col overflow-hidden transition-[width] duration-200 ease-out',
|
||||
'min-h-0 ease-out flex shrink-0 flex-col overflow-hidden transition-[width] duration-200',
|
||||
isSidePanelVisible
|
||||
? SESSION_SIDE_PANEL_EXPANDED_OUTER_CLASS
|
||||
: cn(SESSION_SIDE_PANEL_FOLDED_OUTER_CLASS, 'rounded-l-xl')
|
||||
? PROJECT_SIDE_PANEL_EXPANDED_OUTER_CLASS
|
||||
: cn(PROJECT_SIDE_PANEL_FOLDED_OUTER_CLASS, 'rounded-l-xl')
|
||||
)}
|
||||
>
|
||||
{sessionSidePanel}
|
||||
|
|
@ -270,14 +270,14 @@ export default function Session({ isNewProject = false }: SessionProps) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full min-w-0 flex-1 flex-row overflow-hidden">
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex h-full w-full flex-1 flex-row overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex flex-1 flex-col overflow-hidden">
|
||||
{chatStore.activeTaskId && hasAnyMessages && (
|
||||
<HeaderBox
|
||||
totalTokens={chatStore.tasks[chatStore.activeTaskId]?.tokens || 0}
|
||||
/>
|
||||
)}
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex flex-1 flex-col overflow-hidden">
|
||||
<ChatBox />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -285,10 +285,10 @@ export default function Session({ isNewProject = false }: SessionProps) {
|
|||
<div
|
||||
id="session-side-panel"
|
||||
className={cn(
|
||||
'flex min-h-0 shrink-0 flex-col overflow-hidden transition-[width] duration-200 ease-out',
|
||||
'min-h-0 ease-out flex shrink-0 flex-col overflow-hidden transition-[width] duration-200',
|
||||
isSidePanelVisible
|
||||
? SESSION_SIDE_PANEL_EXPANDED_OUTER_CLASS
|
||||
: cn(SESSION_SIDE_PANEL_FOLDED_OUTER_CLASS, 'rounded-l-xl')
|
||||
? PROJECT_SIDE_PANEL_EXPANDED_OUTER_CLASS
|
||||
: cn(PROJECT_SIDE_PANEL_FOLDED_OUTER_CLASS, 'rounded-l-xl')
|
||||
)}
|
||||
>
|
||||
{sessionSidePanel}
|
||||
|
|
@ -13,12 +13,12 @@
|
|||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
/** Full logical width of the session side panel content (clipped by the outer when folded to 40px). */
|
||||
export const SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS =
|
||||
export const PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS =
|
||||
'w-[min(360px,40vw)] max-w-[400px]';
|
||||
|
||||
/** Outer `#session-side-panel` when expanded (same as content width; no extra clip). */
|
||||
export const SESSION_SIDE_PANEL_EXPANDED_OUTER_CLASS =
|
||||
SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS;
|
||||
export const PROJECT_SIDE_PANEL_EXPANDED_OUTER_CLASS =
|
||||
PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS;
|
||||
|
||||
/** Outer shell when folded: fixed 40px; content layer keeps `SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS`. */
|
||||
export const SESSION_SIDE_PANEL_FOLDED_OUTER_CLASS = 'w-[40px]';
|
||||
/** Outer shell when folded: fixed 40px; content layer keeps `PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS`. */
|
||||
export const PROJECT_SIDE_PANEL_FOLDED_OUTER_CLASS = 'w-[40px]';
|
||||
|
|
@ -215,8 +215,8 @@ export default function SpacesHub() {
|
|||
|
||||
if (spaceSections.length === 0) {
|
||||
return (
|
||||
<div className="flex h-full min-h-0 items-center justify-center px-6">
|
||||
<div className="flex max-w-md flex-col items-center gap-3 text-center">
|
||||
<div className="min-h-0 px-6 flex h-full items-center justify-center">
|
||||
<div className="max-w-md gap-3 flex flex-col items-center text-center">
|
||||
<FolderKanban
|
||||
className="h-10 w-10 text-ds-icon-neutral-muted-default"
|
||||
aria-hidden
|
||||
|
|
@ -233,8 +233,8 @@ export default function SpacesHub() {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="relative flex h-full min-h-0 flex-col overflow-hidden">
|
||||
<div className="flex shrink-0 items-end justify-between gap-4 border-0 border-b border-solid border-ds-border-neutral-subtle-default px-8 py-6">
|
||||
<div className="min-h-0 relative flex h-full flex-col overflow-hidden">
|
||||
<div className="gap-4 border-ds-border-neutral-subtle-default px-8 py-6 flex shrink-0 items-end justify-between border-0 border-b border-solid">
|
||||
<div className="min-w-0">
|
||||
<h1 className="text-heading-2xl m-0 font-semibold text-ds-text-neutral-default-default">
|
||||
{t('layout.spaces-hub-title')}
|
||||
|
|
@ -243,7 +243,7 @@ export default function SpacesHub() {
|
|||
{t('layout.spaces-hub-description')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="hidden shrink-0 items-center gap-2 text-body-sm text-ds-text-neutral-subtle-default md:flex">
|
||||
<div className="gap-2 text-body-sm text-ds-text-neutral-subtle-default md:flex hidden shrink-0 items-center">
|
||||
<FolderKanban className="h-4 w-4" aria-hidden />
|
||||
<span>
|
||||
{t('layout.spaces-hub-space-count', {
|
||||
|
|
@ -253,8 +253,8 @@ export default function SpacesHub() {
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div className="min-h-0 flex-1 overflow-y-auto px-8 py-6">
|
||||
<div className="grid grid-cols-1 gap-4 xl:grid-cols-2 2xl:grid-cols-3">
|
||||
<div className="min-h-0 px-8 py-6 flex-1 overflow-y-auto">
|
||||
<div className="gap-4 xl:grid-cols-2 2xl:grid-cols-3 grid grid-cols-1">
|
||||
{spaceSections.map(({ space, projects }) => {
|
||||
const isActive = space.id === activeSpaceId;
|
||||
const canCreate = canCreateProjectInSpace(space);
|
||||
|
|
@ -271,15 +271,15 @@ export default function SpacesHub() {
|
|||
isActive && 'border-ds-border-brand-default-default'
|
||||
)}
|
||||
>
|
||||
<div className="flex shrink-0 items-start justify-between gap-3 border-0 border-b border-solid border-ds-border-neutral-subtle-default p-4">
|
||||
<div className="gap-3 border-ds-border-neutral-subtle-default p-4 flex shrink-0 items-start justify-between border-0 border-b border-solid">
|
||||
<button
|
||||
type="button"
|
||||
className="flex min-w-0 flex-1 cursor-pointer flex-col items-start gap-1 rounded-md text-left outline-none focus-visible:ring-2 focus-visible:ring-ds-border-brand-default-focus"
|
||||
className="min-w-0 gap-1 rounded-md focus-visible:ring-ds-border-brand-default-focus flex flex-1 cursor-pointer flex-col items-start text-left outline-none focus-visible:ring-2"
|
||||
onClick={() => openSpace(space.id)}
|
||||
>
|
||||
<span className="flex min-w-0 max-w-full items-center gap-2">
|
||||
<Folder className="h-4 w-4 shrink-0 text-ds-icon-neutral-muted-default" />
|
||||
<span className="truncate text-body-md font-semibold text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 gap-2 flex max-w-full items-center">
|
||||
<Folder className="h-4 w-4 text-ds-icon-neutral-muted-default shrink-0" />
|
||||
<span className="text-body-md font-semibold text-ds-text-neutral-default-default truncate">
|
||||
{space.name?.trim() || t('layout.spaces-untitled')}
|
||||
</span>
|
||||
{isLegacySpace(space) ? (
|
||||
|
|
@ -291,7 +291,7 @@ export default function SpacesHub() {
|
|||
/>
|
||||
) : null}
|
||||
</span>
|
||||
<span className="max-w-full truncate text-body-xs text-ds-text-neutral-muted-default">
|
||||
<span className="text-body-xs text-ds-text-neutral-muted-default max-w-full truncate">
|
||||
{subtitle}
|
||||
</span>
|
||||
</button>
|
||||
|
|
@ -314,12 +314,12 @@ export default function SpacesHub() {
|
|||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-1 flex-col gap-1 overflow-y-auto p-2">
|
||||
<div className="min-h-0 gap-1 p-2 flex flex-1 flex-col overflow-y-auto">
|
||||
{projects.length === 0 ? (
|
||||
canCreate ? (
|
||||
<button
|
||||
type="button"
|
||||
className="flex min-h-20 cursor-pointer flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-ds-border-neutral-subtle-default px-4 py-5 text-center text-body-sm text-ds-text-neutral-muted-default transition-colors hover:bg-ds-bg-neutral-subtle-default"
|
||||
className="min-h-20 gap-2 rounded-lg border-ds-border-neutral-subtle-default px-4 py-5 text-body-sm text-ds-text-neutral-muted-default hover:bg-ds-bg-neutral-subtle-default flex cursor-pointer flex-col items-center justify-center border border-dashed text-center transition-colors"
|
||||
onClick={() => void createProject(space)}
|
||||
>
|
||||
<Plus className="h-4 w-4" aria-hidden />
|
||||
|
|
@ -328,7 +328,7 @@ export default function SpacesHub() {
|
|||
</span>
|
||||
</button>
|
||||
) : (
|
||||
<div className="flex min-h-20 flex-col items-center justify-center gap-2 rounded-lg border border-dashed border-ds-border-neutral-subtle-default px-4 py-5 text-center text-body-sm text-ds-text-neutral-muted-default">
|
||||
<div className="min-h-20 gap-2 rounded-lg border-ds-border-neutral-subtle-default px-4 py-5 text-body-sm text-ds-text-neutral-muted-default flex flex-col items-center justify-center border border-dashed text-center">
|
||||
<span>
|
||||
{t('layout.spaces-legacy-readonly-hint', {
|
||||
defaultValue:
|
||||
|
|
@ -347,8 +347,8 @@ export default function SpacesHub() {
|
|||
key={project.id}
|
||||
type="button"
|
||||
className={cn(
|
||||
'group flex min-h-11 w-full cursor-pointer items-center gap-3 rounded-md px-3 py-2 text-left transition-colors',
|
||||
'hover:bg-ds-bg-neutral-subtle-default focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ds-border-brand-default-focus',
|
||||
'group min-h-11 gap-3 rounded-md px-3 py-2 flex w-full cursor-pointer items-center text-left transition-colors',
|
||||
'hover:bg-ds-bg-neutral-subtle-default focus-visible:ring-ds-border-brand-default-focus focus-visible:ring-2 focus-visible:outline-none',
|
||||
isActiveProject &&
|
||||
'bg-ds-bg-neutral-subtle-default text-ds-text-neutral-default-default'
|
||||
)}
|
||||
|
|
@ -356,23 +356,23 @@ export default function SpacesHub() {
|
|||
>
|
||||
{isProjectLoading ? (
|
||||
<Loader2
|
||||
className="h-4 w-4 shrink-0 animate-spin text-ds-icon-neutral-muted-default"
|
||||
className="h-4 w-4 animate-spin text-ds-icon-neutral-muted-default shrink-0"
|
||||
aria-hidden
|
||||
/>
|
||||
) : (
|
||||
<History
|
||||
className="h-4 w-4 shrink-0 text-ds-icon-neutral-muted-default"
|
||||
className="h-4 w-4 text-ds-icon-neutral-muted-default shrink-0"
|
||||
aria-hidden
|
||||
/>
|
||||
)}
|
||||
<span className="min-w-0 flex-1 truncate text-body-sm text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-body-sm text-ds-text-neutral-default-default flex-1 truncate">
|
||||
{projectTitle(
|
||||
project,
|
||||
t('layout.sessions-start-new')
|
||||
)}
|
||||
</span>
|
||||
<ArrowRight
|
||||
className="h-4 w-4 shrink-0 text-ds-icon-neutral-subtle-default opacity-0 transition-opacity group-hover:opacity-100"
|
||||
className="h-4 w-4 text-ds-icon-neutral-subtle-default shrink-0 opacity-0 transition-opacity group-hover:opacity-100"
|
||||
aria-hidden
|
||||
/>
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import eigentAppIconWhite from '@/assets/logo/icon_white.svg';
|
|||
import { type HistoryTabId } from '@/components/Dashboard/HistoryTabsNav';
|
||||
import InviteCodeDialog from '@/components/Dialog/InviteCodeDialog';
|
||||
import ReportBugDialog from '@/components/Dialog/ReportBugDialog';
|
||||
import { SpaceSwitchDropdown } from '@/components/ProjectPageSidebar/SpaceSwitchDropdown';
|
||||
import { SpaceSwitchDropdown } from '@/components/PageSidebar/SpaceSwitchDropdown';
|
||||
import AlertDialog from '@/components/ui/alertDialog';
|
||||
import { Blocks } from '@/components/ui/animate-ui/icons/blocks';
|
||||
import { Bot } from '@/components/ui/animate-ui/icons/bot';
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ import {
|
|||
Image,
|
||||
} from 'lucide-react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { TaskState } from '../TaskState';
|
||||
import { Button } from '../ui/button';
|
||||
import { TaskState } from '../../TaskState';
|
||||
import { Button } from '../../ui/button';
|
||||
|
||||
export default function BrowserAgentWorkspace({
|
||||
selectedTurn,
|
||||
|
|
@ -32,7 +32,7 @@ import {
|
|||
} from 'lucide-react';
|
||||
import { useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Button } from '../ui/button';
|
||||
import { Button } from '../../ui/button';
|
||||
|
||||
export default function TerminalAgentWorkspace({
|
||||
selectedTurn,
|
||||
|
|
@ -37,7 +37,7 @@ export interface WorkforceMenuProps {
|
|||
isChatBoxVisible?: boolean;
|
||||
}
|
||||
|
||||
export default function WorkforceMenu({
|
||||
export default function WorkflowMenu({
|
||||
onToggleChatBox: _onToggleChatBox,
|
||||
isChatBoxVisible: _isChatBoxVisible = true,
|
||||
}: WorkforceMenuProps) {
|
||||
|
|
@ -38,7 +38,7 @@ import {
|
|||
TriangleAlert,
|
||||
} from 'lucide-react';
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import Folder from '../Folder';
|
||||
import Context from '../Context';
|
||||
import { TaskState, TaskStateType } from '../TaskState';
|
||||
import Terminal from '../Terminal';
|
||||
import {
|
||||
|
|
@ -406,18 +406,18 @@ export function Node({ id, data }: NodeProps) {
|
|||
: 'w-[342px]'
|
||||
} ${
|
||||
data.isEditMode ? 'h-full' : 'max-h-[calc(100vh-200px)]'
|
||||
} flex overflow-hidden rounded-xl border border-solid border-ds-border-neutral-subtle-default bg-ds-bg-neutral-subtle-default shadow-sm ${
|
||||
} rounded-xl border-ds-border-neutral-subtle-default bg-ds-bg-neutral-subtle-default shadow-sm flex overflow-hidden border border-solid ${
|
||||
getCurrentTask()?.activeAgent === id
|
||||
? `${displayInfo?.borderColor} z-50`
|
||||
: 'z-10 border-ds-border-neutral-default-default'
|
||||
} transition-all duration-300 ease-in-out ${
|
||||
: 'border-ds-border-neutral-default-default z-10'
|
||||
} ease-in-out transition-all duration-300 ${
|
||||
(data.agent?.tasks?.length ?? 0) === 0 && 'opacity-30'
|
||||
}`}
|
||||
>
|
||||
<div className="flex w-[342px] shrink-0 flex-col border-y-0 border-l-0 border-r-[0.5px] border-solid border-ds-border-neutral-default-default">
|
||||
<div className="border-ds-border-neutral-default-default flex w-[342px] shrink-0 flex-col border-y-0 border-r-[0.5px] border-l-0 border-solid">
|
||||
{/* header */}
|
||||
<div className="flex items-center justify-between gap-sm px-3 pb-1 pt-2">
|
||||
<div className="flex items-center justify-between gap-md">
|
||||
<div className="gap-sm px-3 pb-1 pt-2 flex items-center justify-between">
|
||||
<div className="gap-md flex items-center justify-between">
|
||||
<div
|
||||
className={`text-base font-bold leading-relaxed ${
|
||||
displayInfo?.textColor
|
||||
|
|
@ -426,7 +426,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
{displayInfo?.name || data.agent?.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-center gap-xs">
|
||||
<div className="gap-xs flex items-center">
|
||||
<Button
|
||||
onClick={handleShowLog}
|
||||
variant="ghost"
|
||||
|
|
@ -448,7 +448,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
<Ellipsis />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent className="w-[98px] rounded-[12px] border border-solid border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default p-sm">
|
||||
<PopoverContent className="border-ds-border-neutral-default-default bg-ds-bg-neutral-strong-default p-sm w-[98px] rounded-[12px] border border-solid">
|
||||
<div className="space-y-1">
|
||||
<PopoverClose asChild>
|
||||
<AddWorker
|
||||
|
|
@ -460,7 +460,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className="w-full justify-start gap-2"
|
||||
className="gap-2 w-full justify-start"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
const newWorkerList = workerList.filter(
|
||||
|
|
@ -485,7 +485,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
{/* tools */}
|
||||
<div
|
||||
ref={toolsRef}
|
||||
className="mb-sm flex min-h-4 flex-shrink-0 flex-wrap px-3 text-xs font-normal leading-tight text-ds-text-neutral-muted-default"
|
||||
className="mb-sm min-h-4 px-3 text-xs font-normal leading-tight text-ds-text-neutral-muted-default flex flex-shrink-0 flex-wrap"
|
||||
>
|
||||
{/* {JSON.stringify(data.agent)} */}
|
||||
{toolkitLabels.map((toolkit, index) => (
|
||||
|
|
@ -496,7 +496,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
</div>
|
||||
{/* workspace */}
|
||||
<div
|
||||
className="mb-2 max-h-[180px] px-3"
|
||||
className="mb-2 px-3 max-h-[180px]"
|
||||
onClick={() => {
|
||||
chatStore.setActiveWorkspace(
|
||||
chatStore.activeTaskId as string,
|
||||
|
|
@ -508,15 +508,15 @@ export function Node({ id, data }: NodeProps) {
|
|||
>
|
||||
{browserImages.length > 0 && (
|
||||
<div
|
||||
className={`grid h-[180px] w-full gap-1 overflow-hidden ${browserImageGridClass}`}
|
||||
className={`gap-1 grid h-[180px] w-full overflow-hidden ${browserImageGridClass}`}
|
||||
>
|
||||
{browserImages.map((img, index) => (
|
||||
<div
|
||||
key={`${img.img}-${index}`}
|
||||
className="relative h-full w-full overflow-hidden rounded-lg"
|
||||
className="rounded-lg relative h-full w-full overflow-hidden"
|
||||
>
|
||||
<img
|
||||
className="absolute left-0 top-0 h-[250%] w-[250%] origin-top-left scale-[0.4] object-cover"
|
||||
className="left-0 top-0 absolute h-[250%] w-[250%] origin-top-left scale-[0.4] object-cover"
|
||||
src={img.img}
|
||||
alt={data.type}
|
||||
/>
|
||||
|
|
@ -526,7 +526,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
(_, index) => (
|
||||
<div
|
||||
key={`browser-placeholder-${index}`}
|
||||
className="h-full w-full rounded-sm bg-ds-bg-neutral-subtle-default"
|
||||
className="rounded-sm bg-ds-bg-neutral-subtle-default h-full w-full"
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
|
@ -535,23 +535,23 @@ export function Node({ id, data }: NodeProps) {
|
|||
{data.type === 'document_agent' &&
|
||||
data?.agent?.tasks &&
|
||||
data.agent.tasks.length > 0 && (
|
||||
<div className="relative h-[180px] w-full overflow-hidden rounded-sm">
|
||||
<div className="absolute left-0 top-0 h-[500px] w-[900px] origin-top-left scale-[0.36]">
|
||||
<Folder data={data.agent as Agent} />
|
||||
<div className="rounded-sm relative h-[180px] w-full overflow-hidden">
|
||||
<div className="left-0 top-0 absolute h-[500px] w-[900px] origin-top-left scale-[0.36]">
|
||||
<Context data={data.agent as Agent} />
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{data.type === 'developer_agent' && terminalTasks.length > 0 && (
|
||||
<div
|
||||
className={`grid h-[180px] w-full gap-1 overflow-hidden ${terminalGridClass}`}
|
||||
className={`gap-1 grid h-[180px] w-full overflow-hidden ${terminalGridClass}`}
|
||||
>
|
||||
{terminalTasks.map((task) => (
|
||||
<div
|
||||
key={task.id}
|
||||
className="relative h-full w-full overflow-hidden rounded-lg object-cover"
|
||||
className="rounded-lg relative h-full w-full overflow-hidden object-cover"
|
||||
>
|
||||
<div className="absolute left-0 top-0 h-[250%] w-[250%] origin-top-left scale-[0.4]">
|
||||
<div className="left-0 top-0 absolute h-[250%] w-[250%] origin-top-left scale-[0.4]">
|
||||
<Terminal content={task.terminal} />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -560,7 +560,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
(_, index) => (
|
||||
<div
|
||||
key={`terminal-placeholder-${index}`}
|
||||
className="h-full w-full rounded-lg bg-ds-bg-neutral-subtle-default"
|
||||
className="rounded-lg bg-ds-bg-neutral-subtle-default h-full w-full"
|
||||
/>
|
||||
)
|
||||
)}
|
||||
|
|
@ -569,7 +569,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
</div>
|
||||
{/* subtasks */}
|
||||
{data.agent?.tasks && data.agent?.tasks.length > 0 && (
|
||||
<div className="flex flex-col items-start justify-between gap-1 border-[0px] border-t border-solid border-ds-border-neutral-default-default px-3 py-sm">
|
||||
<div className="gap-1 border-ds-border-neutral-default-default px-3 py-sm flex flex-col items-start justify-between border-[0px] border-t border-solid">
|
||||
{/* <div className="font-bold leading-tight text-xs">Subtasks</div> */}
|
||||
<div className="flex flex-1 justify-end">
|
||||
<TaskState
|
||||
|
|
@ -621,7 +621,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
onWheel={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className="scrollbar scrollbar-always-visible flex flex-col gap-2 overflow-y-auto px-3 pb-2 duration-500 ease-out animate-in fade-in-0 slide-in-from-bottom-4"
|
||||
className="scrollbar scrollbar-always-visible gap-2 px-3 pb-2 ease-out animate-in fade-in-0 slide-in-from-bottom-4 flex flex-col overflow-y-auto duration-500"
|
||||
style={{
|
||||
maxHeight:
|
||||
data.img && data.img.length > 0
|
||||
|
|
@ -682,7 +682,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
}
|
||||
}}
|
||||
key={`taskList-${task.id}-${task.failure_count}`}
|
||||
className={`flex gap-2 rounded-xl px-sm py-sm transition-all duration-300 ease-in-out animate-in fade-in-0 slide-in-from-left-2 ${taskRowBgHover} cursor-pointer border border-solid border-transparent ${
|
||||
className={`gap-2 rounded-xl px-sm py-sm ease-in-out animate-in fade-in-0 slide-in-from-left-2 flex transition-all duration-300 ${taskRowBgHover} cursor-pointer border border-solid border-transparent ${
|
||||
task.status === TaskStatus.COMPLETED
|
||||
? 'hover:border-ds-border-status-completed-subtle-focus'
|
||||
: task.status === TaskStatus.FAILED
|
||||
|
|
@ -767,16 +767,16 @@ export function Node({ id, data }: NodeProps) {
|
|||
</div>
|
||||
<div className="flex flex-1 flex-col items-start justify-center">
|
||||
<div
|
||||
className={`w-full flex-grow-0 ${taskTextClass} pointer-events-auto select-text whitespace-pre-line text-wrap break-all text-xs font-medium leading-13`}
|
||||
className={`w-full flex-grow-0 ${taskTextClass} text-xs font-medium leading-13 pointer-events-auto text-wrap break-all whitespace-pre-line select-text`}
|
||||
>
|
||||
<div className="flex items-center gap-sm">
|
||||
<div className="gap-sm flex items-center">
|
||||
<div
|
||||
className={`text-xs font-bold leading-13 ${taskTextClass}`}
|
||||
>
|
||||
No. {getTaskId(task.id)}
|
||||
</div>
|
||||
{task.reAssignTo ? (
|
||||
<div className="rounded-lg bg-ds-bg-document-subtle-default px-1 py-0.5 text-xs font-bold leading-none text-ds-text-document-default-default hover:bg-ds-bg-document-subtle-hover">
|
||||
<div className="rounded-lg bg-ds-bg-document-subtle-default px-1 py-0.5 text-xs font-bold text-ds-text-document-default-default hover:bg-ds-bg-document-subtle-hover leading-none">
|
||||
Reassigned to {task.reAssignTo}
|
||||
</div>
|
||||
) : (
|
||||
|
|
@ -798,11 +798,11 @@ export function Node({ id, data }: NodeProps) {
|
|||
<div>{task.content}</div>
|
||||
</div>
|
||||
{task?.status === TaskStatus.RUNNING && (
|
||||
<div className="duration-400 mt-xs flex items-center gap-2 animate-in fade-in-0 slide-in-from-bottom-2">
|
||||
<div className="mt-xs gap-2 animate-in fade-in-0 slide-in-from-bottom-2 flex items-center duration-400">
|
||||
{/* active toolkit */}
|
||||
{lastActiveToolkit?.toolkitStatus ===
|
||||
AgentStatusValue.RUNNING && (
|
||||
<div className="flex min-w-0 flex-1 items-center justify-start gap-sm duration-300 animate-in fade-in-0 slide-in-from-right-2">
|
||||
<div className="min-w-0 gap-sm animate-in fade-in-0 slide-in-from-right-2 flex flex-1 items-center justify-start duration-300">
|
||||
{getToolkitIcon(
|
||||
lastActiveToolkit.toolkitName ?? ''
|
||||
)}
|
||||
|
|
@ -813,11 +813,11 @@ export function Node({ id, data }: NodeProps) {
|
|||
].activeWorkspace
|
||||
? '!w-[100px]'
|
||||
: '!w-[500px]'
|
||||
} min-w-0 flex-shrink-0 flex-grow-0 overflow-hidden text-ellipsis whitespace-nowrap pt-1 text-xs leading-17 text-ds-text-status-running-default-default`}
|
||||
} min-w-0 pt-1 text-xs leading-17 text-ds-text-status-running-default-default flex-shrink-0 flex-grow-0 overflow-hidden text-ellipsis whitespace-nowrap`}
|
||||
>
|
||||
<ShinyText
|
||||
text={task.toolkits?.[0].toolkitName}
|
||||
className="pointer-events-auto w-full select-text overflow-hidden text-ellipsis whitespace-nowrap text-xs font-bold leading-17 text-ds-text-status-running-default-default"
|
||||
className="text-xs font-bold leading-17 text-ds-text-status-running-default-default pointer-events-auto w-full overflow-hidden text-ellipsis whitespace-nowrap select-text"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -838,14 +838,14 @@ export function Node({ id, data }: NodeProps) {
|
|||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: 24 }}
|
||||
transition={{ duration: 0.3, ease: 'easeIn' }}
|
||||
className="flex w-[342px] shrink-0 flex-col gap-sm overflow-hidden rounded-r-xl bg-ds-bg-neutral-subtle-default py-2 pl-sm"
|
||||
className="gap-sm rounded-r-xl bg-ds-bg-neutral-subtle-default py-2 pl-sm flex w-[342px] shrink-0 flex-col overflow-hidden"
|
||||
>
|
||||
<div
|
||||
ref={logRef}
|
||||
onWheel={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
className="scrollbar scrollbar-always-visible max-h-[calc(100vh-200px)] overflow-y-scroll rounded-xl pr-sm"
|
||||
className="scrollbar scrollbar-always-visible rounded-xl pr-sm max-h-[calc(100vh-200px)] overflow-y-scroll"
|
||||
>
|
||||
<AnimatePresence mode="wait">
|
||||
{selectedTask && (
|
||||
|
|
@ -855,7 +855,7 @@ export function Node({ id, data }: NodeProps) {
|
|||
animate={{ opacity: 1, x: 0 }}
|
||||
exit={{ opacity: 0, x: -16 }}
|
||||
transition={{ duration: 0.25, ease: 'easeIn' }}
|
||||
className="flex w-full flex-col gap-sm"
|
||||
className="gap-sm flex w-full flex-col"
|
||||
>
|
||||
<TaskLogPanelContent
|
||||
selectedTask={selectedTask}
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import {
|
|||
import { type ReactNode, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
/** Sub icons aligned with `WorkforceMenu` / `ui/menu-button` → `MenuToggleItem` (top-right badge, 10px). */
|
||||
/** Sub icons aligned with `WorkflowMenu` / `ui/menu-button` → `MenuToggleItem` (top-right badge, 10px). */
|
||||
function getWorkforceMenuStyleSubIcon(agentType: string): ReactNode {
|
||||
const key = agentType as WorkflowAgentType;
|
||||
const iconClass = WORKFLOW_AGENT_SUB_ICON_CLASS[key];
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
import {
|
||||
ProjectNavListRows,
|
||||
type ProjectNavItem,
|
||||
} from '@/components/ProjectPageSidebar/ProjectNavListRows';
|
||||
} from '@/components/PageSidebar/ProjectNavListRows';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface WorkspaceAllSessionsProps {
|
||||
|
|
@ -32,10 +32,10 @@ export function WorkspaceAllSessions({
|
|||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<div className="flex h-full min-h-0 w-full min-w-0 flex-col overflow-hidden">
|
||||
<div className="m-0 mx-auto flex min-h-0 w-full max-w-3xl flex-1 flex-col gap-0.5 overflow-y-auto p-2">
|
||||
<div className="min-h-0 min-w-0 flex h-full w-full flex-col overflow-hidden">
|
||||
<div className="m-0 min-h-0 max-w-3xl gap-0.5 p-2 mx-auto flex w-full flex-1 flex-col overflow-y-auto">
|
||||
{projects.length === 0 ? (
|
||||
<p className="m-0 px-3 py-6 text-center text-body-sm text-ds-text-neutral-muted-default">
|
||||
<p className="m-0 px-3 py-6 text-body-sm text-ds-text-neutral-muted-default text-center">
|
||||
{t('layout.sessions-create-task-hint')}
|
||||
</p>
|
||||
) : (
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
// limitations under the License.
|
||||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
import { SpaceSwitchDropdown } from '@/components/ProjectPageSidebar/SpaceSwitchDropdown';
|
||||
import { SpaceSwitchDropdown } from '@/components/PageSidebar/SpaceSwitchDropdown';
|
||||
import AlertDialog from '@/components/ui/alertDialog';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
|
|
@ -537,7 +537,7 @@ export function WorkspaceProjectPicker({
|
|||
aria-label={activeSpaceTitle}
|
||||
>
|
||||
<FolderIcon className="size-4 shrink-0" aria-hidden />
|
||||
<span className="min-w-0 truncate text-label-sm text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-label-sm text-ds-text-neutral-default-default truncate">
|
||||
{activeSpaceTitle}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -607,13 +607,13 @@ export function WorkspaceProjectPicker({
|
|||
buttonRadius="full"
|
||||
className={cn(
|
||||
PROJECT_PICKER_SHELL_CLASS,
|
||||
'no-drag justify-between hover:bg-ds-bg-neutral-default-hover'
|
||||
'no-drag hover:bg-ds-bg-neutral-default-hover justify-between'
|
||||
)}
|
||||
aria-expanded={menuOpen}
|
||||
aria-haspopup="menu"
|
||||
>
|
||||
<FolderIcon className="size-4 shrink-0" aria-hidden />
|
||||
<span className="min-w-0 truncate text-label-sm text-ds-text-neutral-default-default">
|
||||
<span className="min-w-0 text-label-sm text-ds-text-neutral-default-default truncate">
|
||||
{activeSpaceTitle}
|
||||
</span>
|
||||
<ChevronsUpDown
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import {
|
|||
NAV_LIST_PROJECTS_RECENT_MAX,
|
||||
ProjectNavListRows,
|
||||
type ProjectNavItem,
|
||||
} from '@/components/ProjectPageSidebar/ProjectNavListRows';
|
||||
} from '@/components/PageSidebar/ProjectNavListRows';
|
||||
|
||||
import { ArrowRight } from 'lucide-react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
|
@ -45,26 +45,26 @@ export function WorkspaceRecentSessions({
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="mx-auto flex min-h-full w-full max-w-[600px] flex-col pb-4">
|
||||
<div className="mb-3 flex w-full min-w-0 items-center justify-between gap-2 px-3 text-ds-text-neutral-muted-default">
|
||||
<h2 className="min-w-0 text-left text-body-sm font-semibold">
|
||||
<div className="pb-4 mx-auto flex min-h-full w-full max-w-[600px] flex-col">
|
||||
<div className="mb-3 min-w-0 gap-2 px-3 text-ds-text-neutral-muted-default flex w-full items-center justify-between">
|
||||
<h2 className="min-w-0 text-body-sm font-semibold text-left">
|
||||
{t('layout.workspace-recent-sessions-heading')}
|
||||
</h2>
|
||||
<button
|
||||
type="button"
|
||||
onClick={onOpenAllProjects}
|
||||
className="group inline-flex shrink-0 items-center gap-0.5 text-body-sm font-medium text-ds-text-neutral-muted-default outline-none transition-colors hover:underline focus-visible:rounded focus-visible:ring-2 focus-visible:ring-ds-ring-neutral-default-focus"
|
||||
className="group gap-0.5 text-body-sm font-medium text-ds-text-neutral-muted-default focus-visible:rounded focus-visible:ring-ds-ring-neutral-default-focus inline-flex shrink-0 items-center transition-colors outline-none hover:underline focus-visible:ring-2"
|
||||
>
|
||||
{t('layout.all', { defaultValue: 'All' })}
|
||||
<span
|
||||
className="inline-flex max-w-0 overflow-hidden transition-[max-width] duration-200 ease-out group-hover:max-w-4"
|
||||
className="max-w-0 ease-out group-hover:max-w-4 inline-flex overflow-hidden transition-[max-width] duration-200"
|
||||
aria-hidden
|
||||
>
|
||||
<ArrowRight className="h-3.5 w-3.5 shrink-0" />
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div className="m-0 flex min-h-0 w-full flex-col gap-0.5 p-0">
|
||||
<div className="m-0 min-h-0 gap-0.5 p-0 flex w-full flex-col">
|
||||
<ProjectNavListRows
|
||||
projects={projects}
|
||||
activeProjectId={activeProjectId}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
import { AddWorker } from '@/components/AddWorker';
|
||||
import BottomBox, { type FileAttachment } from '@/components/ChatBox/BottomBox';
|
||||
import { SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Session/sessionSidePanelLayout';
|
||||
import { PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS } from '@/components/Project/projectSidePanelLayout';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { BASE_WORKFLOW_AGENTS } from '@/components/WorkFlow/baseWorkers';
|
||||
import { isBaseWorkflowAgent } from '@/components/Workspace/FoldedAgentCard';
|
||||
|
|
@ -482,12 +482,12 @@ export default function Workspace({
|
|||
const composerTop = (
|
||||
<>
|
||||
<div className="mb-8 flex w-full justify-center">{projectPicker}</div>
|
||||
<span className="mb-8 w-full text-center text-heading-lg font-bold text-ds-text-neutral-default-default">
|
||||
<span className="mb-8 text-heading-lg font-bold text-ds-text-neutral-default-default w-full text-center">
|
||||
{effectiveSessionMode === SessionMode.SINGLE_AGENT
|
||||
? t('layout.workspace-cowork-single-agent')
|
||||
: t('layout.workspace-cowork-workforce')}
|
||||
</span>
|
||||
<div className="mb-8 flex w-full justify-center px-5">
|
||||
<div className="mb-8 px-5 flex w-full justify-center">
|
||||
{effectiveSessionMode === SessionMode.SINGLE_AGENT ? (
|
||||
<SingleAgentList />
|
||||
) : (
|
||||
|
|
@ -536,7 +536,7 @@ export default function Workspace({
|
|||
|
||||
const composer = (
|
||||
<div className="mx-auto my-auto flex w-full max-w-[600px] shrink-0 flex-col">
|
||||
<div className="flex min-h-[50vh] w-full min-w-0 flex-col justify-end">
|
||||
<div className="min-w-0 flex min-h-[50vh] w-full flex-col justify-end">
|
||||
{composerTop}
|
||||
{composerInput}
|
||||
</div>
|
||||
|
|
@ -551,10 +551,10 @@ export default function Workspace({
|
|||
|
||||
if (embedded && isNewProjectVariant) {
|
||||
return (
|
||||
<div className="relative z-[1] flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden px-3">
|
||||
<div className="min-h-0 min-w-0 px-3 relative z-[1] flex flex-1 flex-col overflow-hidden">
|
||||
{composer}
|
||||
<div
|
||||
className="flex min-h-0 w-full flex-1 flex-col overflow-y-auto pt-6"
|
||||
className="min-h-0 pt-6 flex w-full flex-1 flex-col overflow-y-auto"
|
||||
id="workspace-bottom-group"
|
||||
aria-hidden
|
||||
/>
|
||||
|
|
@ -568,7 +568,7 @@ export default function Workspace({
|
|||
<div
|
||||
className={cn(
|
||||
'flex h-full flex-col overflow-hidden',
|
||||
SESSION_SIDE_PANEL_CONTENT_WIDTH_CLASS
|
||||
PROJECT_SIDE_PANEL_CONTENT_WIDTH_CLASS
|
||||
)}
|
||||
>
|
||||
<WorkspaceCoworkPanel
|
||||
|
|
@ -580,13 +580,13 @@ export default function Workspace({
|
|||
) : null;
|
||||
|
||||
return (
|
||||
<div className="relative z-[1] flex h-full min-h-0 w-full min-w-0 flex-row overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 relative z-[1] flex h-full w-full flex-row overflow-hidden">
|
||||
{/* Center section: header + content */}
|
||||
<div className="flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 flex flex-1 flex-col overflow-hidden">
|
||||
{/* Header toolbar */}
|
||||
<div
|
||||
className={cn(
|
||||
'relative flex h-[44px] w-full shrink-0 flex-row items-center justify-start gap-1',
|
||||
'gap-1 relative flex h-[44px] w-full shrink-0 flex-row items-center justify-start',
|
||||
!isNewProjectVariant && 'px-3'
|
||||
)}
|
||||
>
|
||||
|
|
@ -605,8 +605,8 @@ export default function Workspace({
|
|||
</Button>
|
||||
)}
|
||||
{!isNewProjectVariant && workspaceSubPage !== null && (
|
||||
<div className="pointer-events-none absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<span className="block max-w-[60vw] truncate text-center !text-label-sm font-semibold text-ds-text-neutral-default-default">
|
||||
<div className="pointer-events-none absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<span className="!text-label-sm font-semibold text-ds-text-neutral-default-default block max-w-[60vw] truncate text-center">
|
||||
{SUB_PAGE_TITLES[workspaceSubPage]}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -635,7 +635,7 @@ export default function Workspace({
|
|||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex min-h-0 w-full flex-1 flex-col overflow-hidden">
|
||||
<div className="min-h-0 flex w-full flex-1 flex-col overflow-hidden">
|
||||
{/* Sub-pages */}
|
||||
{!isNewProjectVariant && workspaceSubPage === 'all-sessions' && (
|
||||
<WorkspaceAllSessions
|
||||
|
|
@ -658,17 +658,17 @@ export default function Workspace({
|
|||
|
||||
{/* Main content (hidden when a sub-page is active) */}
|
||||
{workspaceSubPage === null && (
|
||||
<div className="relative flex min-h-0 min-w-0 flex-1 flex-col items-stretch overflow-hidden">
|
||||
<div className="min-h-0 min-w-0 relative flex flex-1 flex-col items-stretch overflow-hidden">
|
||||
<div
|
||||
className={cn(
|
||||
'flex min-h-0 w-full flex-1 flex-col',
|
||||
'min-h-0 flex w-full flex-1 flex-col',
|
||||
!isNewProjectVariant && 'px-3'
|
||||
)}
|
||||
>
|
||||
{composer}
|
||||
|
||||
<div
|
||||
className="flex min-h-0 w-full flex-1 flex-col overflow-y-auto pt-6"
|
||||
className="min-h-0 pt-6 flex w-full flex-1 flex-col overflow-y-auto"
|
||||
id="workspace-bottom-group"
|
||||
>
|
||||
{showBottomExamplePrompts ? (
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
// ========= Copyright 2025-2026 @ Eigent.ai All Rights Reserved. =========
|
||||
|
||||
/**
|
||||
* Scoped font style for HTML fragments rendered in the main document (e.g. CSV in FolderComponent).
|
||||
* Scoped font style for HTML fragments rendered in the main document (e.g. CSV in ContextComponent).
|
||||
* Uses a wrapper class so styles do not leak to the rest of the app (sidebar, file list, etc.).
|
||||
*/
|
||||
const SCOPED_FONT_STYLE = `<style data-eigent-fonts>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ const TAB_ALIASES: Record<string, HistoryTabId> = {
|
|||
spaces: 'home',
|
||||
};
|
||||
|
||||
export default function History() {
|
||||
export default function HomePage() {
|
||||
const { t } = useTranslation();
|
||||
const navigate = useNavigate();
|
||||
const [searchParams] = useSearchParams();
|
||||
|
|
@ -123,10 +123,10 @@ export default function History() {
|
|||
};
|
||||
|
||||
return (
|
||||
<div className="flex h-full w-full flex-1 flex-col px-1 pb-1 pt-10">
|
||||
<div className="px-1 pb-1 pt-10 flex h-full w-full flex-1 flex-col">
|
||||
<div
|
||||
ref={scrollContainerRef}
|
||||
className="scrollbar-hide h-full overflow-y-auto rounded-2xl bg-ds-bg-neutral-subtle-default"
|
||||
className="scrollbar-hide rounded-2xl bg-ds-bg-neutral-subtle-default h-full overflow-y-auto"
|
||||
>
|
||||
{/* alert dialog */}
|
||||
<AlertDialog
|
||||
|
|
@ -139,17 +139,17 @@ export default function History() {
|
|||
cancelText={t('layout.cancel')}
|
||||
/>
|
||||
{/* welcome text */}
|
||||
<div className="flex w-full flex-row bg-gradient-to-b from-ds-bg-neutral-default-default to-ds-bg-neutral-default-default px-[74px] py-8">
|
||||
<p className="m-0 inline-flex flex-wrap items-baseline gap-2">
|
||||
<div className="from-ds-bg-neutral-default-default to-ds-bg-neutral-default-default py-8 flex w-full flex-row bg-gradient-to-b px-[74px]">
|
||||
<p className="m-0 gap-2 inline-flex flex-wrap items-baseline">
|
||||
<WordCarousel
|
||||
words={[t(timeGreetingKey)]}
|
||||
className="history-welcome-headline text-heading-xl font-bold not-italic tracking-tight"
|
||||
className="history-welcome-headline text-heading-xl font-bold tracking-tight not-italic"
|
||||
rotateIntervalMs={100}
|
||||
sweepDurationMs={2000}
|
||||
sweepOnce
|
||||
gradient="linear-gradient(90deg, var(--ds-text-brand-subtle-default) 0%, var(--ds-text-brand-muted-default) 100%)"
|
||||
/>
|
||||
<span className="history-welcome-headline text-heading-xl font-bold italic tracking-tight text-ds-text-brand-default-default">
|
||||
<span className="history-welcome-headline text-heading-xl font-bold tracking-tight text-ds-text-brand-default-default italic">
|
||||
{`, ${welcomeName} !`}
|
||||
</span>
|
||||
</p>
|
||||
|
|
@ -157,7 +157,7 @@ export default function History() {
|
|||
{/* Navbar */}
|
||||
{/* -top-px avoids a visible hairline: at top-0 subpixel rounding can leave a gap; */}
|
||||
<div
|
||||
className={`border-b-1 sticky -top-px z-20 flex flex-col items-center justify-between border-x-0 border-t-0 border-solid border-ds-border-neutral-subtle-disabled bg-ds-bg-neutral-default-default px-[70px] pt-2`}
|
||||
className={`border-ds-border-neutral-subtle-disabled bg-ds-bg-neutral-default-default pt-2 sticky -top-px z-20 flex flex-col items-center justify-between border-x-0 border-t-0 border-b-1 border-solid px-[70px]`}
|
||||
>
|
||||
<div className="mx-auto flex w-full flex-row items-center">
|
||||
<HistoryTabsNav activeTab={activeTab} onChange={handleTabChange} />
|
||||
|
|
@ -176,7 +176,7 @@ export default function History() {
|
|||
</div>
|
||||
)}
|
||||
<div className="m-auto flex h-auto w-full max-w-[1020px] flex-1 flex-col">
|
||||
<div className="flex h-auto w-full px-6 pb-[120px] [--home-hub-history-tabs-offset:49px]">
|
||||
<div className="px-6 flex h-auto w-full pb-[120px] [--home-hub-history-tabs-offset:49px]">
|
||||
{visitedTabs.includes('agents') && (
|
||||
<div
|
||||
className={activeTab === 'agents' ? 'contents' : 'hidden'}
|
||||
|
|
@ -20,14 +20,14 @@ import {
|
|||
GridPatternBackground,
|
||||
RuledLinesBackground,
|
||||
} from '@/components/Background';
|
||||
import Context from '@/components/Context';
|
||||
import { WorkspaceDispatch } from '@/components/Dispatch';
|
||||
import Folder from '@/components/Folder';
|
||||
import ProjectPageSidebar from '@/components/ProjectPageSidebar';
|
||||
import PageSidebar from '@/components/PageSidebar';
|
||||
import {
|
||||
PROJECT_SIDEBAR_FOLD_SPRING,
|
||||
PROJECT_SIDEBAR_RAIL_WIDTH_PX,
|
||||
} from '@/components/ProjectPageSidebar/constants';
|
||||
import SessionGroup from '@/components/Session/SessionGroup';
|
||||
} from '@/components/PageSidebar/constants';
|
||||
import ProjectGroup from '@/components/Project/ProjectGroup';
|
||||
import TriggerPanel from '@/components/Trigger';
|
||||
import UpdateElectron from '@/components/update';
|
||||
import Workspace from '@/components/Workspace';
|
||||
|
|
@ -56,7 +56,7 @@ import {
|
|||
type TriggerSortKey,
|
||||
} from '../components/Trigger/Triggers';
|
||||
|
||||
import Session from '@/components/Session';
|
||||
import Project from '@/components/Project';
|
||||
import {
|
||||
ResizableHandle,
|
||||
ResizablePanel,
|
||||
|
|
@ -692,7 +692,7 @@ export default function WorkspacePage() {
|
|||
<div className={workspaceMainContentClass}>
|
||||
{workspacePatternOverlayEl}
|
||||
<div className={workspaceMainForegroundClass}>
|
||||
<Session />
|
||||
<Project />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -701,7 +701,7 @@ export default function WorkspacePage() {
|
|||
<div className={workspaceMainContentClass}>
|
||||
{workspacePatternOverlayEl}
|
||||
<div className={workspaceMainForegroundClass}>
|
||||
<Session isNewProject />
|
||||
<Project isNewProject />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -714,7 +714,7 @@ export default function WorkspacePage() {
|
|||
case 'inbox':
|
||||
return (
|
||||
<div className={mainPanelContentClass}>
|
||||
<Folder />
|
||||
<Context />
|
||||
</div>
|
||||
);
|
||||
case 'triggers':
|
||||
|
|
@ -733,7 +733,7 @@ export default function WorkspacePage() {
|
|||
);
|
||||
case 'runs':
|
||||
return (
|
||||
<SessionGroup
|
||||
<ProjectGroup
|
||||
className={mainPanelContentClass}
|
||||
tasks={chatStore?.tasks ?? {}}
|
||||
activeSessionId={chatStore?.activeTaskId ?? undefined}
|
||||
|
|
@ -771,7 +771,7 @@ export default function WorkspacePage() {
|
|||
maxSize={sidebarPct.max}
|
||||
className="min-h-0 min-w-0 pl-1 py-1"
|
||||
>
|
||||
<ProjectPageSidebar chatStore={chatStore} />
|
||||
<PageSidebar chatStore={chatStore} />
|
||||
</ResizablePanel>
|
||||
<ResizableHandle
|
||||
className={cn(
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import Layout from '@/components/Layout';
|
|||
const Login = lazy(() => import('@/pages/Login'));
|
||||
const Signup = lazy(() => import('@/pages/SignUp'));
|
||||
const Workspace = lazy(() => import('@/pages/Workspace'));
|
||||
const History = lazy(() => import('@/pages/History'));
|
||||
const HomePage = lazy(() => import('@/pages/HomePage'));
|
||||
const NotFound = lazy(() => import('@/pages/NotFound'));
|
||||
const RemoteControl = lazy(() => import('@/pages/RemoteControl'));
|
||||
|
||||
|
|
@ -138,7 +138,7 @@ const ProtectedRoute = () => {
|
|||
if (state.loading || !state.initialized) {
|
||||
return (
|
||||
<div className="flex h-screen items-center justify-center">
|
||||
<div className="h-8 w-8 animate-spin rounded-full border-b-2 border-blue-600"></div>
|
||||
<div className="h-8 w-8 animate-spin border-blue-600 rounded-full border-b-2"></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -163,14 +163,14 @@ const AppRoutes = () => (
|
|||
<Route element={<ProtectedRoute />}>
|
||||
<Route element={<Layout />}>
|
||||
<Route path="/" element={<Workspace />} />
|
||||
<Route path="/history" element={<History />} />
|
||||
<Route path="/home" element={<HomePage />} />
|
||||
<Route
|
||||
path="/setting"
|
||||
element={<Navigate to="/history?tab=settings" replace />}
|
||||
element={<Navigate to="/home?tab=settings" replace />}
|
||||
/>
|
||||
<Route
|
||||
path="/setting/*"
|
||||
element={<Navigate to="/history?tab=settings" replace />}
|
||||
element={<Navigate to="/home?tab=settings" replace />}
|
||||
/>
|
||||
</Route>
|
||||
</Route>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue