wip: context-meter + model-label UI and provider/inference tweaks

Checkpoint of in-flight work so the orchestrator branch can rebase onto a
clean main: ContextBar → ContextMeter, model-label helper, model/agent picker
+ provider-snapshot/registry changes, inference payload + message-columns.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-03 14:55:38 +00:00
parent 5f4c7a9050
commit 163b5b86f7
21 changed files with 471 additions and 233 deletions

View File

@@ -1,6 +1,7 @@
import { useCallback, useEffect, useState } from 'react';
import { Archive, Code, MessageSquare, RotateCcw, Terminal, Trash2 } from 'lucide-react';
import { Archive, ChevronLeft, Code, MessageSquare, RotateCcw, Terminal, Trash2 } from 'lucide-react';
import { toast } from 'sonner';
import mascot from '@/assets/brand/banner-mascot.png';
import { ChatInput } from '@/components/ChatInput';
import { Button } from '@/components/ui/button';
import {
@@ -33,6 +34,10 @@ interface Props {
onUnarchiveChat: (chatId: string) => Promise<void>;
onArchiveChat: (chatId: string) => Promise<void>;
onDeleteChat: (chatId: string) => Promise<void>;
// Controlled session-history view: the new-chat hero is the default; the
// header's "Session history" button flips this on (and Back flips it off).
openHistory: boolean;
onCloseHistory: () => void;
}
@@ -63,6 +68,8 @@ export function SessionLandingPage({
onUnarchiveChat,
onArchiveChat,
onDeleteChat,
openHistory,
onCloseHistory,
}: Props) {
const [chatId, setChatId] = useState<string | null>(null);
const [archived, setArchived] = useState<Chat[]>([]);
@@ -129,13 +136,41 @@ export function SessionLandingPage({
return (
<div className="flex flex-col h-full min-h-0">
<div className="flex-1 min-h-0 overflow-y-auto">
<div className="max-w-[760px] mx-auto w-full px-4 py-4">
{isEmpty ? (
<p className="text-sm text-muted-foreground text-center py-8">
No conversations yet. Send a message to start.
</p>
<div className="max-w-[760px] mx-auto w-full px-4 py-4 h-full">
{!openHistory ? (
/* Landing hero — BooCode mascot + prompt, vertically centered to
match the coder pane's empty state (a flex-1 fill).
Session history lives in the header (see Session.tsx row 2). */
<div className="flex flex-col items-center justify-center text-center gap-4 h-full">
<img
src={mascot}
alt="BooCode"
draggable={false}
className="w-20 h-auto select-none"
/>
<p className="text-sm text-muted-foreground">
Send a message to start a new conversation
</p>
</div>
) : (
<>
<div className="flex items-center gap-1.5 mb-3">
<button
type="button"
onClick={onCloseHistory}
className="inline-flex items-center gap-1 -ml-1 px-2 min-h-[44px] rounded text-sm text-muted-foreground hover:text-foreground hover:bg-muted/60"
aria-label="Back to new conversation"
>
<ChevronLeft size={16} className="shrink-0" />
Back
</button>
<h2 className="text-sm font-medium ml-auto mr-1">Session history</h2>
</div>
{isEmpty ? (
<p className="text-sm text-muted-foreground text-center py-8">
No conversations yet. Send a message to start.
</p>
) : (<>
{openChats.length > 0 && (
<>
<h3 className="text-xs font-medium uppercase tracking-wide text-muted-foreground px-1 mb-1.5">
@@ -165,7 +200,7 @@ export function SessionLandingPage({
{formatRelative(c.updated_at)}
</span>
</button>
<div className="shrink-0 flex items-center gap-0.5 opacity-0 group-hover/row:opacity-100 focus-within:opacity-100 transition-opacity">
<div className="shrink-0 flex items-center gap-0.5 opacity-0 group-hover/row:opacity-100 focus-within:opacity-100 max-md:opacity-100 transition-opacity">
<button
type="button"
onClick={(e) => { e.stopPropagation(); void onArchiveChat(c.id); }}
@@ -213,13 +248,13 @@ export function SessionLandingPage({
<span className="shrink-0 text-xs">{formatRelative(c.updated_at)}</span>
<RotateCcw
size={13}
className="shrink-0 opacity-0 group-hover/arch:opacity-100"
className="shrink-0 opacity-0 group-hover/arch:opacity-100 max-md:opacity-100"
/>
</button>
<button
type="button"
onClick={(e) => { e.stopPropagation(); setDeleteConfirm({ id: c.id, name: c.name }); }}
className="shrink-0 inline-flex items-center justify-center size-7 rounded hover:bg-destructive/20 hover:text-destructive max-md:size-9 opacity-0 group-hover/arch:opacity-100 focus-within:opacity-100 transition-opacity"
className="shrink-0 inline-flex items-center justify-center size-7 rounded hover:bg-destructive/20 hover:text-destructive max-md:size-9 opacity-0 group-hover/arch:opacity-100 focus-within:opacity-100 max-md:opacity-100 transition-opacity"
aria-label="Delete chat"
title="Delete"
>
@@ -230,6 +265,7 @@ export function SessionLandingPage({
</div>
</>
)}
</>)}
</>
)}
</div>