Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions test/web/workspace.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,8 +202,8 @@ test.describe('Web UI - Sessions', () => {
const sessionId = `test-session-${Date.now()}`;
const filePath = `/home/workspace/.claude/projects/-workspace/${sessionId}.jsonl`;
const sessionContent = [
'{"type":"user","message":{"role":"user","content":"Hello from test"},"timestamp":"2026-01-01T00:00:00.000Z"}',
'{"type":"assistant","message":{"role":"assistant","content":"Hi there"},"timestamp":"2026-01-01T00:00:01.000Z"}',
'{"type":"user","content":"Hello from test","timestamp":"2026-01-01T00:00:00.000Z"}',
'{"type":"assistant","content":"Hi there","timestamp":"2026-01-01T00:00:01.000Z"}',
].join('\n');

await agent.api.createWorkspace({ name: workspaceName });
Expand All @@ -222,7 +222,7 @@ test.describe('Web UI - Sessions', () => {

await sessionItem.click();

await expect(page.getByText('Claude Code')).toBeVisible({ timeout: 30000 });
await expect(page.getByText('Claude Code', { exact: true })).toBeVisible({ timeout: 30000 });
await expect(page.getByPlaceholder('Send a message...')).toBeVisible();
} finally {
await agent.api.deleteWorkspace(workspaceName);
Expand All @@ -234,10 +234,10 @@ test.describe('Web UI - Sessions', () => {
const sessionId = `history-test-${Date.now()}`;
const filePath = `/home/workspace/.claude/projects/-workspace/${sessionId}.jsonl`;
const sessionContent = [
'{"type":"user","message":{"role":"user","content":"What is 2+2?"},"timestamp":"2026-01-01T00:00:00.000Z"}',
'{"type":"assistant","message":{"role":"assistant","content":"2+2 equals 4"},"timestamp":"2026-01-01T00:00:01.000Z"}',
'{"type":"user","message":{"role":"user","content":"Thanks!"},"timestamp":"2026-01-01T00:00:02.000Z"}',
'{"type":"assistant","message":{"role":"assistant","content":"You are welcome!"},"timestamp":"2026-01-01T00:00:03.000Z"}',
'{"type":"user","content":"What is 2+2?","timestamp":"2026-01-01T00:00:00.000Z"}',
'{"type":"assistant","content":"2+2 equals 4","timestamp":"2026-01-01T00:00:01.000Z"}',
'{"type":"user","content":"Thanks!","timestamp":"2026-01-01T00:00:02.000Z"}',
'{"type":"assistant","content":"You are welcome!","timestamp":"2026-01-01T00:00:03.000Z"}',
].join('\n');

await agent.api.createWorkspace({ name: workspaceName });
Expand All @@ -256,7 +256,7 @@ test.describe('Web UI - Sessions', () => {

await sessionItem.click();

await expect(page.getByText('Claude Code')).toBeVisible({ timeout: 30000 });
await expect(page.getByText('Claude Code', { exact: true })).toBeVisible({ timeout: 30000 });
await expect(page.getByText('2+2 equals 4')).toBeVisible({ timeout: 10000 });
await expect(page.getByText('Thanks!')).toBeVisible();
await expect(page.getByText('You are welcome!')).toBeVisible();
Expand Down
23 changes: 11 additions & 12 deletions web/src/components/Chat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -228,13 +228,11 @@ function StreamingMessage({ parts }: { parts: ChatMessagePart[] }) {
return (
<div className="space-y-3">
{renderPartsWithPairedTools(parts)}
{!hasContent && (
<div className="flex gap-1">
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
</div>
)}
<div className={cn("flex gap-1 transition-opacity duration-150", hasContent ? "opacity-0 h-0 overflow-hidden" : "opacity-100")}>
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '0ms' }} />
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '150ms' }} />
<span className="w-2 h-2 bg-muted-foreground/40 rounded-full animate-bounce" style={{ animationDelay: '300ms' }} />
</div>
</div>
)
}
Expand Down Expand Up @@ -542,6 +540,7 @@ export function Chat({ workspaceName, sessionId: initialSessionId, onSessionId,
if (match) {
const newSessionId = match[1].replace(/\.+$/, '')
setSessionId(newSessionId)
hasLoadedHistoryRef.current = true
onSessionIdRef.current?.(newSessionId)
}
return
Expand Down Expand Up @@ -721,14 +720,14 @@ export function Chat({ workspaceName, sessionId: initialSessionId, onSessionId,
)}

<div ref={scrollContainerRef} className="flex-1 overflow-y-auto">
{isLoadingHistory && (
{isLoadingHistory && messages.length === 0 && (
<div className="flex flex-col items-center justify-center h-full text-muted-foreground p-4">
<Loader2 className="h-8 w-8 animate-spin mb-4" />
<p className="text-center">Loading conversation history...</p>
</div>
)}

{!isLoadingHistory && messages.length === 0 && !isStreaming && (
{messages.length === 0 && !isLoadingHistory && !isStreaming && (
<div className="flex flex-col items-center justify-center h-full text-muted-foreground p-4">
<Sparkles className="h-12 w-12 mb-4 opacity-20" />
<p className="text-center">
Expand All @@ -740,7 +739,7 @@ export function Chat({ workspaceName, sessionId: initialSessionId, onSessionId,
</div>
)}

{!isLoadingHistory && messages.length > 0 && containerMounted && (
{messages.length > 0 && containerMounted && (
<>
{isLoadingMore && (
<div className="flex justify-center py-4">
Expand Down Expand Up @@ -788,15 +787,15 @@ export function Chat({ workspaceName, sessionId: initialSessionId, onSessionId,
</>
)}

{!isLoadingHistory && messages.length > 0 && !containerMounted && (
{messages.length > 0 && !containerMounted && (
<div className="space-y-4 p-4">
{messages.map((msg, idx) => (
<MessageBubble key={idx} message={msg} />
))}
</div>
)}

{isStreaming && (
{isStreaming && messages.length > 0 && (
<div className="p-4 pt-0">
<StreamingMessage parts={streamingParts} />
</div>
Expand Down
1 change: 1 addition & 0 deletions web/src/pages/WorkspaceDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,7 @@ export function WorkspaceDetail() {
) : chatMode ? (
chatMode.type === 'chat' ? (
<Chat
key={`chat-${chatMode.agentType}`}
workspaceName={name!}
sessionId={chatMode.sessionId}
agentType={chatMode.agentType}
Expand Down