feat(desktop): hoisted todo widget, JSON tool summaries, history grouping & timer fixes

- Hoist todo to first-class widget (shadcn checkboxes, brand colors, no
  tool-accordion). Header derives label from active task; non-active rows fade.
- Replace raw JSON dumps with structured key/value summaries via
  formatToolResultSummary; nested error extraction for clearer failures.
- Fix loaded-session grouping: stitch interleaved assistant/tool iterations
  into one bubble instead of orphaned synthetic messages.
- Stable tool/thinking timers via keyed registry so unmount/scroll doesn't
  reset elapsed counts; gate "running" on real live thread state.
- Reorganize chat-only assistant-ui components under components/chat/.
This commit is contained in:
Brooklyn Nicholson
2026-05-11 16:34:25 -04:00
parent 4b3839a8ee
commit 4dd9732a94
34 changed files with 1234 additions and 306 deletions
@@ -43,9 +43,6 @@ interface StatusbarControlsProps extends ComponentProps<'footer'> {
items?: readonly StatusbarItem[]
}
const statusbarItemClass =
'inline-flex h-full cursor-pointer items-center gap-1 rounded-none px-1.5 text-[0.68rem] text-muted-foreground/95 transition-colors hover:bg-(--chrome-action-hover) hover:text-foreground disabled:cursor-default disabled:opacity-45'
export function StatusbarControls({ className, leftItems = [], items = [], ...props }: StatusbarControlsProps) {
const navigate = useNavigate()
@@ -91,7 +88,10 @@ function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate:
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
className={cn(statusbarItemClass, item.className)}
className={cn(
'inline-flex h-full cursor-pointer items-center gap-1 rounded-none px-1.5 text-[0.68rem] text-muted-foreground/95 transition-colors hover:bg-(--chrome-action-hover) hover:text-foreground disabled:cursor-default disabled:opacity-45',
item.className
)}
disabled={item.disabled}
title={title}
type="button"
@@ -162,7 +162,10 @@ function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate:
if (item.href || item.variant === 'link') {
return (
<a
className={cn(statusbarItemClass, item.className)}
className={cn(
'inline-flex h-full cursor-pointer items-center gap-1 rounded-none px-1.5 text-[0.68rem] text-muted-foreground/95 transition-colors hover:bg-(--chrome-action-hover) hover:text-foreground disabled:cursor-default disabled:opacity-45',
item.className
)}
href={item.href}
rel="noreferrer"
target="_blank"
@@ -175,7 +178,10 @@ function StatusbarItemView({ item, navigate }: { item: StatusbarItem; navigate:
return (
<button
className={cn(statusbarItemClass, item.className)}
className={cn(
'inline-flex h-full cursor-pointer items-center gap-1 rounded-none px-1.5 text-[0.68rem] text-muted-foreground/95 transition-colors hover:bg-(--chrome-action-hover) hover:text-foreground disabled:cursor-default disabled:opacity-45',
item.className
)}
disabled={item.disabled}
onClick={() => {
if (item.to) {