2026-02-11 16:45:07 -08:00
|
|
|
"use client";
|
|
|
|
|
|
2026-02-13 18:06:59 -08:00
|
|
|
import { useEffect, useState, useRef, useCallback } from "react";
|
Dench workspace: file manager, relation resolution, and chat refactor
File Manager & Filesystem Operations:
- Add FileManagerTree component with drag-and-drop (dnd-kit), inline
rename, right-click context menu, and compact sidebar mode
- Add context-menu component (open, new file/folder, rename, duplicate,
copy, paste, move, delete) rendered via portal
- Add InlineRename component with validation and shake-on-error animation
- Add useWorkspaceWatcher hook with SSE live-reload and polling fallback
- Add API routes: mkdir, rename, copy, move, watch (SSE file-change
events), and DELETE on /api/workspace/file with system-file protection
- Add safeResolveNewPath and isSystemFile helpers to workspace lib
- Replace inline WorkspaceTreeNode in sidebar with shared FileManagerTree
(compact mode), add workspace refresh callback
Object Relation Resolution:
- Resolve relation fields to human-readable display labels server-side
(resolveRelationLabels, resolveDisplayField helpers)
- Add reverse relation discovery (findReverseRelations) — surfaces
incoming links from other objects
- Add display_field column migration (idempotent ALTER TABLE) and
PATCH /api/workspace/objects/[name]/display-field endpoint
- Enrich object API response with relationLabels, reverseRelations,
effectiveDisplayField, and related_object_name per field
- Add RelationCell, RelationChip, ReverseRelationCell, LinkIcon
components to object-table with clickable cross-object navigation
- Add relation label rendering to kanban cards
- Extract ObjectView component in workspace page with display-field
selector dropdown and relation/reverse-relation badge counts
Chat Panel Extraction:
- Extract chat logic from page.tsx into standalone ChatPanel component
with forwardRef/useImperativeHandle for session control
- ChatPanel supports file-scoped sessions (filePath param) and
context-aware file chat sidebar
- Simplify page.tsx to thin orchestrator delegating to ChatPanel
- Add filePath filter to GET /api/web-sessions for scoped session lists
Dependencies:
- Add @dnd-kit/core, @dnd-kit/sortable, @dnd-kit/utilities
- Add duckdbExec and parseRelationValue to workspace lib
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 19:22:53 -08:00
|
|
|
import { FileManagerTree, type TreeNode } from "./file-manager-tree";
|
2026-02-19 14:59:34 -08:00
|
|
|
import { ProfileSwitcher } from "./profile-switcher";
|
|
|
|
|
import { CreateWorkspaceDialog } from "./create-workspace-dialog";
|
2026-02-19 16:50:52 -08:00
|
|
|
import { UnicodeSpinner } from "../unicode-spinner";
|
2026-02-11 16:45:07 -08:00
|
|
|
|
2026-02-13 18:06:59 -08:00
|
|
|
/** Shape returned by /api/workspace/suggest-files */
|
|
|
|
|
type SuggestItem = {
|
|
|
|
|
name: string;
|
|
|
|
|
path: string;
|
|
|
|
|
type: "folder" | "file" | "document" | "database";
|
|
|
|
|
};
|
|
|
|
|
|
2026-02-11 16:45:07 -08:00
|
|
|
type WorkspaceSidebarProps = {
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
tree: TreeNode[];
|
|
|
|
|
activePath: string | null;
|
|
|
|
|
onSelect: (node: TreeNode) => void;
|
|
|
|
|
onRefresh: () => void;
|
|
|
|
|
orgName?: string;
|
|
|
|
|
loading?: boolean;
|
2026-02-13 15:16:36 -08:00
|
|
|
/** Current browse directory (absolute path), or null when in workspace mode. */
|
|
|
|
|
browseDir?: string | null;
|
|
|
|
|
/** Parent directory for ".." navigation. Null at filesystem root or when browsing is unavailable. */
|
|
|
|
|
parentDir?: string | null;
|
|
|
|
|
/** Navigate up one directory. */
|
|
|
|
|
onNavigateUp?: () => void;
|
|
|
|
|
/** Return to workspace mode from browse mode. */
|
|
|
|
|
onGoHome?: () => void;
|
2026-02-13 18:06:59 -08:00
|
|
|
/** Called when a file/folder is selected from the search dropdown. */
|
|
|
|
|
onFileSearchSelect?: (item: SuggestItem) => void;
|
2026-02-13 19:24:24 -08:00
|
|
|
/** Absolute path of the workspace root folder, used to render it as a special entry in browse mode. */
|
|
|
|
|
workspaceRoot?: string | null;
|
2026-02-15 23:00:25 -08:00
|
|
|
/** Navigate to the main chat / home panel. */
|
|
|
|
|
onGoToChat?: () => void;
|
2026-02-15 23:42:13 -08:00
|
|
|
/** Called when a tree node is dragged and dropped onto an external target (e.g. chat input). */
|
|
|
|
|
onExternalDrop?: (node: TreeNode) => void;
|
2026-02-16 00:30:13 -08:00
|
|
|
/** When true, renders as a mobile overlay drawer instead of a static sidebar. */
|
|
|
|
|
mobile?: boolean;
|
|
|
|
|
/** Close the mobile drawer. */
|
|
|
|
|
onClose?: () => void;
|
2026-02-19 14:59:34 -08:00
|
|
|
/** Active workspace profile name (null = default). */
|
|
|
|
|
activeProfile?: string | null;
|
2026-02-19 15:42:23 -08:00
|
|
|
/** Fixed width in px when not mobile (overrides default 260). */
|
|
|
|
|
width?: number;
|
2026-02-19 14:59:34 -08:00
|
|
|
/** Called after the user switches to a different profile. */
|
|
|
|
|
onProfileSwitch?: () => void;
|
2026-02-21 14:39:55 -08:00
|
|
|
/** Whether hidden (dot) files/folders are currently shown. */
|
|
|
|
|
showHidden?: boolean;
|
|
|
|
|
/** Toggle hidden files visibility. */
|
|
|
|
|
onToggleHidden?: () => void;
|
2026-02-19 23:15:39 -08:00
|
|
|
/** Called when the user clicks the collapse/hide sidebar button. */
|
|
|
|
|
onCollapse?: () => void;
|
2026-02-11 16:45:07 -08:00
|
|
|
};
|
|
|
|
|
|
Dench workspace: virtual folders (Skills, Memories, Chats), landing page, and unified workspace layout
Add virtual folder system that surfaces Skills, Memories, and Chat sessions
in the workspace sidebar alongside real dench files. Rearchitect the home
page into a landing hub and move the ChatPanel into the workspace as the
default view.
New API route — virtual-file:
- apps/web/app/api/workspace/virtual-file/route.ts: new GET/POST API that
resolves virtual paths (~skills/*, ~memories/*) to absolute filesystem
paths in ~/.openclaw/skills/ d ~/.openclaw/workspace/. Includes path
traversal protection and directory allowlisting.
Tree API — virtual folder builders:
- apps/web/app/api/workspace/tree/route.ts: add `virtual` field to TreeNode
type. Add ildSkillsVirtualFolder() scanning ~/.openclaw/skills/ and
~/.openclaw/workspace/skills/ with SKILL.md frontmatter parsing (name +
emoji). Add buildMemoriesVirtualFolder() scanning MEMORY.md and daily
logs from ~/.openclaw/workspace/memory/. Virtual folders are appended
after real workspace entries and are also returned when no dench root
exists.
File manager tree — virtual node awareness:
- apps/web/app/components/workspace/file-manager-tree.tsx: add isVirtualNode()
helper and RESERVED_FOLDER_NAMES set (Chats, Skills, Memories). Virtual
nodes show a lock badge, disable drag-and-drop, block rename/delete, and
reject reserved names during create/rename. Add ChatBubbleIcon for ~chats/
paths.
Markdown editor — virtual path routing:
- apps/web/app/components/workspace/markdown-editor.tsx: save to
/api/workspace/virtual-file for paths starting with ~ instead of the
regular /api/workspace/file endpoint.
Home page redesign:
- apps/web/app/page.tsx: replace the chat-first layout (SidebarhatPanel)
with a branded landing page showing the OpenClaw Dench heading, tagline,
and a single "Open Workspace" CTA linking to /workspace.
Workspace page — unified layout with integrated chat:
- apps/web/app/workspace/page.tsx: ChatPanel is now the default main view
when no file is selected. Add session fetching from /api/web-sessions and
build an enhanced tree with a virtual "Chats" folder listing all sessions.
Clicking ~chats/<id> loads the session; clicking ~chats starts a new one.
Add isVirtualPath()/fileApiUrl() helpers for virtual file reads. Add a
"Back to chat" button in the top bar alongside the chat sidebar toggle.
Sidebar + empty-state cosmetic updates:
- apps/web/app/components/workspace/workspace-sidebar.tsx: rename BackIcon
to HomeIcon (house SVG), change label from "Back to Chat" to "Home".
- apps/web/app/components/workspace/empty-state.tsx: update link text from
"Back to Chat" to "Back to Home".
2026-02-11 22:09:59 -08:00
|
|
|
function HomeIcon() {
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
return (
|
|
|
|
|
<svg
|
|
|
|
|
width="16"
|
|
|
|
|
height="16"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
|
|
|
|
<polyline points="9 22 9 12 15 12 15 22" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 15:16:36 -08:00
|
|
|
function FolderOpenIcon() {
|
|
|
|
|
return (
|
2026-02-19 22:50:34 -08:00
|
|
|
<img
|
|
|
|
|
src="/icons/folder-open.png"
|
|
|
|
|
alt=""
|
|
|
|
|
width={20}
|
|
|
|
|
height={20}
|
|
|
|
|
draggable={false}
|
|
|
|
|
style={{ flexShrink: 0 }}
|
|
|
|
|
/>
|
2026-02-13 15:16:36 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
/* ─── Theme toggle ─── */
|
|
|
|
|
|
|
|
|
|
function ThemeToggle() {
|
|
|
|
|
const [isDark, setIsDark] = useState(false);
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
setIsDark(document.documentElement.classList.contains("dark"));
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const toggle = () => {
|
|
|
|
|
const next = !isDark;
|
|
|
|
|
setIsDark(next);
|
|
|
|
|
if (next) {
|
|
|
|
|
document.documentElement.classList.add("dark");
|
|
|
|
|
localStorage.setItem("theme", "dark");
|
|
|
|
|
} else {
|
|
|
|
|
document.documentElement.classList.remove("dark");
|
|
|
|
|
localStorage.setItem("theme", "light");
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={toggle}
|
|
|
|
|
className="p-1.5 rounded-lg"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
|
|
|
|
title={isDark ? "Switch to light mode" : "Switch to dark mode"}
|
|
|
|
|
>
|
|
|
|
|
{isDark ? (
|
|
|
|
|
/* Sun icon */
|
|
|
|
|
<svg
|
|
|
|
|
width="16"
|
|
|
|
|
height="16"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
<circle cx="12" cy="12" r="4" />
|
|
|
|
|
<path d="M12 2v2" />
|
|
|
|
|
<path d="M12 20v2" />
|
|
|
|
|
<path d="m4.93 4.93 1.41 1.41" />
|
|
|
|
|
<path d="m17.66 17.66 1.41 1.41" />
|
|
|
|
|
<path d="M2 12h2" />
|
|
|
|
|
<path d="M20 12h2" />
|
|
|
|
|
<path d="m6.34 17.66-1.41 1.41" />
|
|
|
|
|
<path d="m19.07 4.93-1.41 1.41" />
|
|
|
|
|
</svg>
|
|
|
|
|
) : (
|
|
|
|
|
/* Moon icon */
|
|
|
|
|
<svg
|
|
|
|
|
width="16"
|
|
|
|
|
height="16"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z" />
|
|
|
|
|
</svg>
|
|
|
|
|
)}
|
|
|
|
|
</button>
|
|
|
|
|
);
|
2026-02-11 16:45:07 -08:00
|
|
|
}
|
|
|
|
|
|
2026-02-13 18:06:59 -08:00
|
|
|
function SearchIcon() {
|
|
|
|
|
return (
|
|
|
|
|
<svg
|
|
|
|
|
width="14"
|
|
|
|
|
height="14"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
<circle cx="11" cy="11" r="8" />
|
|
|
|
|
<path d="m21 21-4.3-4.3" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SmallFolderIcon() {
|
|
|
|
|
return (
|
2026-02-19 22:50:34 -08:00
|
|
|
<img
|
|
|
|
|
src="/icons/folder.png"
|
|
|
|
|
alt=""
|
|
|
|
|
width={14}
|
|
|
|
|
height={14}
|
|
|
|
|
draggable={false}
|
|
|
|
|
style={{ flexShrink: 0 }}
|
|
|
|
|
/>
|
2026-02-13 18:06:59 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SmallFileIcon() {
|
|
|
|
|
return (
|
2026-02-19 22:50:34 -08:00
|
|
|
<img src="/icons/document.png" alt="" width={14} height={14} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
|
2026-02-13 18:06:59 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SmallDocIcon() {
|
|
|
|
|
return (
|
2026-02-19 22:50:34 -08:00
|
|
|
<img src="/icons/document.png" alt="" width={14} height={14} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
|
2026-02-13 18:06:59 -08:00
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SmallDbIcon() {
|
|
|
|
|
return (
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
|
<ellipse cx="12" cy="5" rx="9" ry="3" /><path d="M3 5V19A9 3 0 0 0 21 19V5" /><path d="M3 12A9 3 0 0 0 21 12" />
|
|
|
|
|
</svg>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function SuggestTypeIcon({ type }: { type: string }) {
|
|
|
|
|
switch (type) {
|
|
|
|
|
case "folder": return <SmallFolderIcon />;
|
|
|
|
|
case "document": return <SmallDocIcon />;
|
|
|
|
|
case "database": return <SmallDbIcon />;
|
|
|
|
|
default: return <SmallFileIcon />;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ─── File search ─── */
|
|
|
|
|
|
|
|
|
|
function FileSearch({ onSelect }: { onSelect: (item: SuggestItem) => void }) {
|
|
|
|
|
const [query, setQuery] = useState("");
|
|
|
|
|
const [results, setResults] = useState<SuggestItem[]>([]);
|
|
|
|
|
const [open, setOpen] = useState(false);
|
|
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
|
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
|
|
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
|
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
|
|
|
|
|
|
|
|
// Debounced fetch from the same suggest-files API that tiptap uses
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
if (!query.trim()) {
|
|
|
|
|
setResults([]);
|
|
|
|
|
setOpen(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setLoading(true);
|
|
|
|
|
const timer = setTimeout(async () => {
|
|
|
|
|
try {
|
|
|
|
|
const res = await fetch(
|
|
|
|
|
`/api/workspace/suggest-files?q=${encodeURIComponent(query.trim())}`,
|
|
|
|
|
);
|
|
|
|
|
const data = await res.json();
|
|
|
|
|
setResults(data.items ?? []);
|
|
|
|
|
setOpen(true);
|
|
|
|
|
setSelectedIndex(0);
|
|
|
|
|
} catch {
|
|
|
|
|
setResults([]);
|
|
|
|
|
} finally {
|
|
|
|
|
setLoading(false);
|
|
|
|
|
}
|
|
|
|
|
}, 150);
|
|
|
|
|
|
|
|
|
|
return () => clearTimeout(timer);
|
|
|
|
|
}, [query]);
|
|
|
|
|
|
|
|
|
|
// Click outside to close
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
function handleClickOutside(e: MouseEvent) {
|
|
|
|
|
if (containerRef.current && !containerRef.current.contains(e.target as Node)) {
|
|
|
|
|
setOpen(false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
|
|
|
return () => document.removeEventListener("mousedown", handleClickOutside);
|
|
|
|
|
}, []);
|
|
|
|
|
|
|
|
|
|
const handleKeyDown = useCallback(
|
|
|
|
|
(e: React.KeyboardEvent) => {
|
|
|
|
|
if (e.key === "ArrowDown") {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
setSelectedIndex((i) => Math.min(i + 1, results.length - 1));
|
|
|
|
|
} else if (e.key === "ArrowUp") {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
setSelectedIndex((i) => Math.max(i - 1, 0));
|
|
|
|
|
} else if (e.key === "Enter" && results[selectedIndex]) {
|
|
|
|
|
e.preventDefault();
|
|
|
|
|
onSelect(results[selectedIndex]);
|
|
|
|
|
setQuery("");
|
|
|
|
|
setOpen(false);
|
|
|
|
|
inputRef.current?.blur();
|
|
|
|
|
} else if (e.key === "Escape") {
|
|
|
|
|
setOpen(false);
|
|
|
|
|
setQuery("");
|
|
|
|
|
inputRef.current?.blur();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
[results, selectedIndex, onSelect],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const handleSelect = useCallback(
|
|
|
|
|
(item: SuggestItem) => {
|
|
|
|
|
onSelect(item);
|
|
|
|
|
setQuery("");
|
|
|
|
|
setOpen(false);
|
|
|
|
|
},
|
|
|
|
|
[onSelect],
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div ref={containerRef} className="relative px-3 pt-2 pb-1">
|
|
|
|
|
<div className="relative">
|
|
|
|
|
<span
|
|
|
|
|
className="absolute left-2.5 top-1/2 -translate-y-1/2 pointer-events-none"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
|
|
|
|
>
|
|
|
|
|
<SearchIcon />
|
|
|
|
|
</span>
|
|
|
|
|
<input
|
|
|
|
|
ref={inputRef}
|
|
|
|
|
type="text"
|
|
|
|
|
value={query}
|
|
|
|
|
onChange={(e) => setQuery(e.target.value)}
|
|
|
|
|
onKeyDown={handleKeyDown}
|
|
|
|
|
onFocus={() => { if (results.length > 0) {setOpen(true);} }}
|
|
|
|
|
placeholder="Search files..."
|
|
|
|
|
className="w-full pl-8 pr-3 py-1.5 rounded-lg text-xs outline-none transition-colors"
|
|
|
|
|
style={{
|
|
|
|
|
background: "var(--color-bg)",
|
|
|
|
|
color: "var(--color-text)",
|
|
|
|
|
border: "1px solid var(--color-border)",
|
|
|
|
|
}}
|
|
|
|
|
/>
|
|
|
|
|
{loading && (
|
|
|
|
|
<span className="absolute right-2.5 top-1/2 -translate-y-1/2">
|
2026-02-19 16:50:52 -08:00
|
|
|
<UnicodeSpinner
|
|
|
|
|
name="braille"
|
|
|
|
|
className="text-sm"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
2026-02-13 18:06:59 -08:00
|
|
|
/>
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{open && results.length > 0 && (
|
|
|
|
|
<div
|
|
|
|
|
className="absolute left-3 right-3 mt-1 rounded-lg shadow-lg border overflow-hidden z-50 max-h-[300px] overflow-y-auto"
|
|
|
|
|
style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}
|
|
|
|
|
>
|
|
|
|
|
{results.map((item, i) => (
|
|
|
|
|
<button
|
|
|
|
|
key={item.path}
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={() => handleSelect(item)}
|
|
|
|
|
className="w-full flex items-center gap-2 px-3 py-2 text-left text-xs cursor-pointer transition-colors"
|
|
|
|
|
style={{
|
|
|
|
|
background: i === selectedIndex ? "var(--color-surface-hover)" : "transparent",
|
|
|
|
|
color: "var(--color-text)",
|
|
|
|
|
}}
|
|
|
|
|
onMouseEnter={() => setSelectedIndex(i)}
|
|
|
|
|
>
|
|
|
|
|
<span className="flex-shrink-0" style={{ color: "var(--color-text-muted)" }}>
|
|
|
|
|
<SuggestTypeIcon type={item.type} />
|
|
|
|
|
</span>
|
|
|
|
|
<div className="min-w-0 flex-1">
|
|
|
|
|
<div className="truncate font-medium">{item.name}</div>
|
|
|
|
|
<div className="truncate" style={{ color: "var(--color-text-muted)", fontSize: "10px" }}>
|
|
|
|
|
{item.path.split("/").slice(0, -1).join("/")}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<span
|
|
|
|
|
className="text-[10px] px-1.5 py-0.5 rounded-full flex-shrink-0 capitalize"
|
|
|
|
|
style={{ background: "var(--color-surface-hover)", color: "var(--color-text-muted)" }}
|
|
|
|
|
>
|
|
|
|
|
{item.type}
|
|
|
|
|
</span>
|
|
|
|
|
</button>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
|
|
|
|
|
{open && query.trim() && !loading && results.length === 0 && (
|
|
|
|
|
<div
|
|
|
|
|
className="absolute left-3 right-3 mt-1 rounded-lg shadow-lg border z-50 px-3 py-3 text-center"
|
|
|
|
|
style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}
|
|
|
|
|
>
|
|
|
|
|
<p className="text-xs" style={{ color: "var(--color-text-muted)" }}>
|
|
|
|
|
No files found
|
|
|
|
|
</p>
|
|
|
|
|
</div>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-13 15:16:36 -08:00
|
|
|
/** Extract the directory name from an absolute path for display. */
|
|
|
|
|
function dirDisplayName(dir: string): string {
|
|
|
|
|
if (dir === "/") {return "/";}
|
|
|
|
|
return dir.split("/").pop() || dir;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-11 16:45:07 -08:00
|
|
|
export function WorkspaceSidebar({
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
tree,
|
|
|
|
|
activePath,
|
|
|
|
|
onSelect,
|
|
|
|
|
onRefresh,
|
|
|
|
|
orgName,
|
|
|
|
|
loading,
|
2026-02-13 15:16:36 -08:00
|
|
|
browseDir,
|
|
|
|
|
parentDir,
|
|
|
|
|
onNavigateUp,
|
|
|
|
|
onGoHome,
|
2026-02-13 18:06:59 -08:00
|
|
|
onFileSearchSelect,
|
2026-02-13 19:24:24 -08:00
|
|
|
workspaceRoot,
|
2026-02-15 23:00:25 -08:00
|
|
|
onGoToChat,
|
2026-02-15 23:42:13 -08:00
|
|
|
onExternalDrop,
|
2026-02-16 00:30:13 -08:00
|
|
|
mobile,
|
|
|
|
|
onClose,
|
2026-02-19 14:59:34 -08:00
|
|
|
activeProfile,
|
|
|
|
|
onProfileSwitch,
|
2026-02-21 14:39:55 -08:00
|
|
|
showHidden,
|
|
|
|
|
onToggleHidden,
|
2026-02-19 15:42:23 -08:00
|
|
|
width: widthProp,
|
2026-02-19 23:15:39 -08:00
|
|
|
onCollapse,
|
2026-02-11 16:45:07 -08:00
|
|
|
}: WorkspaceSidebarProps) {
|
2026-02-13 15:16:36 -08:00
|
|
|
const isBrowsing = browseDir != null;
|
2026-02-19 14:59:34 -08:00
|
|
|
const [showCreateWorkspace, setShowCreateWorkspace] = useState(false);
|
2026-02-19 15:42:23 -08:00
|
|
|
const width = mobile ? "280px" : (widthProp ?? 260);
|
2026-02-13 15:16:36 -08:00
|
|
|
|
2026-02-16 00:30:13 -08:00
|
|
|
const sidebar = (
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
<aside
|
2026-02-19 16:50:52 -08:00
|
|
|
className={`flex flex-col h-screen shrink-0 ${mobile ? "drawer-left" : "border-r"}`}
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
style={{
|
2026-02-19 15:42:23 -08:00
|
|
|
width: typeof width === "number" ? `${width}px` : width,
|
2026-02-19 16:50:52 -08:00
|
|
|
minWidth: typeof width === "number" ? `${width}px` : width,
|
2026-02-19 22:50:34 -08:00
|
|
|
background: "var(--color-sidebar-bg)",
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
borderColor: "var(--color-border)",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
{/* Header */}
|
|
|
|
|
<div
|
2026-02-19 22:50:34 -08:00
|
|
|
className="flex items-center gap-2 px-3 py-2.5 border-b"
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
style={{ borderColor: "var(--color-border)" }}
|
|
|
|
|
>
|
2026-02-13 15:16:36 -08:00
|
|
|
{isBrowsing ? (
|
|
|
|
|
<>
|
|
|
|
|
<span
|
|
|
|
|
className="w-8 h-8 rounded-lg flex items-center justify-center flex-shrink-0"
|
|
|
|
|
style={{
|
|
|
|
|
background: "var(--color-surface-hover)",
|
|
|
|
|
color: "var(--color-text-muted)",
|
|
|
|
|
}}
|
|
|
|
|
>
|
|
|
|
|
<FolderOpenIcon />
|
|
|
|
|
</span>
|
|
|
|
|
<div className="flex-1 min-w-0">
|
|
|
|
|
<div
|
|
|
|
|
className="text-sm font-medium truncate"
|
|
|
|
|
style={{ color: "var(--color-text)" }}
|
|
|
|
|
title={browseDir}
|
|
|
|
|
>
|
|
|
|
|
{dirDisplayName(browseDir)}
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
|
|
|
|
className="text-[11px] truncate"
|
|
|
|
|
style={{
|
|
|
|
|
color: "var(--color-text-muted)",
|
|
|
|
|
}}
|
|
|
|
|
title={browseDir}
|
|
|
|
|
>
|
|
|
|
|
{browseDir}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
{/* Home button to return to workspace */}
|
|
|
|
|
{onGoHome && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onGoHome}
|
|
|
|
|
className="p-1.5 rounded-lg flex-shrink-0"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
|
|
|
|
title="Return to workspace"
|
|
|
|
|
>
|
|
|
|
|
<HomeIcon />
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
2026-02-15 23:00:25 -08:00
|
|
|
<button
|
|
|
|
|
type="button"
|
2026-02-16 00:30:13 -08:00
|
|
|
onClick={() => void onGoToChat?.()}
|
2026-02-19 22:50:34 -08:00
|
|
|
className="w-7 h-7 rounded-lg flex items-center justify-center shrink-0 cursor-pointer transition-colors hover:bg-stone-200 dark:hover:bg-stone-700"
|
2026-02-13 15:16:36 -08:00
|
|
|
style={{
|
2026-02-19 22:50:34 -08:00
|
|
|
background: "transparent",
|
|
|
|
|
color: "var(--color-text-muted)",
|
2026-02-13 15:16:36 -08:00
|
|
|
}}
|
2026-02-15 23:00:25 -08:00
|
|
|
title="All Chats"
|
2026-02-13 15:16:36 -08:00
|
|
|
>
|
2026-02-19 22:50:34 -08:00
|
|
|
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
2026-02-15 23:00:25 -08:00
|
|
|
<path d="m3 9 9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
|
|
|
|
<polyline points="9 22 9 12 15 12 15 22" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
2026-02-19 15:42:23 -08:00
|
|
|
<ProfileSwitcher
|
|
|
|
|
onProfileSwitch={onProfileSwitch}
|
|
|
|
|
onCreateWorkspace={() => setShowCreateWorkspace(true)}
|
2026-02-21 14:39:55 -08:00
|
|
|
activeProfileHint={activeProfile}
|
2026-02-19 15:42:23 -08:00
|
|
|
trigger={({ isOpen, onClick, activeProfile: profileName, switching }) => (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
disabled={switching}
|
2026-02-19 22:50:34 -08:00
|
|
|
className="flex-1 min-w-0 w-full flex items-center justify-between gap-1.5 text-left rounded-lg py-1 px-1.5 transition-colors hover:bg-stone-100 dark:hover:bg-stone-800 disabled:opacity-50"
|
2026-02-19 15:42:23 -08:00
|
|
|
title="Switch workspace profile"
|
|
|
|
|
>
|
|
|
|
|
<div className="min-w-0 truncate">
|
|
|
|
|
<div
|
2026-02-19 22:50:34 -08:00
|
|
|
className="text-[13px] font-semibold truncate text-stone-700 dark:text-stone-200"
|
2026-02-19 15:42:23 -08:00
|
|
|
>
|
|
|
|
|
{orgName || "Workspace"}
|
|
|
|
|
</div>
|
|
|
|
|
<div
|
2026-02-19 22:50:34 -08:00
|
|
|
className="text-[11px] flex items-center gap-1 truncate text-stone-400 dark:text-stone-500"
|
2026-02-19 15:42:23 -08:00
|
|
|
>
|
|
|
|
|
<span>Ironclaw</span>
|
|
|
|
|
{profileName && profileName !== "default" && (
|
|
|
|
|
<span
|
2026-02-19 22:50:34 -08:00
|
|
|
className="px-1 py-0.5 rounded text-[10px] shrink-0 bg-stone-200 text-stone-500 dark:bg-stone-700 dark:text-stone-400"
|
2026-02-19 15:42:23 -08:00
|
|
|
>
|
|
|
|
|
{profileName}
|
|
|
|
|
</span>
|
|
|
|
|
)}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<svg
|
2026-02-19 22:50:34 -08:00
|
|
|
className={`w-3 h-3 shrink-0 transition-transform text-stone-400 ${isOpen ? "rotate-180" : ""}`}
|
2026-02-19 15:42:23 -08:00
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
viewBox="0 0 24 24"
|
2026-02-19 14:59:34 -08:00
|
|
|
>
|
2026-02-19 15:42:23 -08:00
|
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
/>
|
2026-02-13 15:16:36 -08:00
|
|
|
</>
|
|
|
|
|
)}
|
2026-02-19 23:15:39 -08:00
|
|
|
{onCollapse && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onCollapse}
|
|
|
|
|
className="p-1 rounded-md shrink-0 transition-colors hover:bg-stone-200 dark:hover:bg-stone-700"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
|
|
|
|
title="Hide sidebar (⌘B)"
|
|
|
|
|
>
|
|
|
|
|
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
|
|
|
|
|
<rect width="18" height="18" x="3" y="3" rx="2" />
|
|
|
|
|
<path d="M9 3v18" />
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
</div>
|
2026-02-11 16:45:07 -08:00
|
|
|
|
2026-02-19 14:59:34 -08:00
|
|
|
{/* Create workspace dialog */}
|
|
|
|
|
<CreateWorkspaceDialog
|
|
|
|
|
isOpen={showCreateWorkspace}
|
|
|
|
|
onClose={() => setShowCreateWorkspace(false)}
|
|
|
|
|
onCreated={onProfileSwitch}
|
|
|
|
|
/>
|
|
|
|
|
|
2026-02-13 18:06:59 -08:00
|
|
|
{/* File search */}
|
|
|
|
|
{onFileSearchSelect && (
|
|
|
|
|
<FileSearch onSelect={onFileSearchSelect} />
|
|
|
|
|
)}
|
|
|
|
|
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
{/* Tree */}
|
|
|
|
|
<div className="flex-1 overflow-y-auto px-1">
|
|
|
|
|
{loading ? (
|
|
|
|
|
<div className="flex items-center justify-center py-12">
|
2026-02-19 16:50:52 -08:00
|
|
|
<UnicodeSpinner
|
|
|
|
|
name="braille"
|
|
|
|
|
className="text-2xl"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
) : (
|
2026-02-15 23:42:13 -08:00
|
|
|
<FileManagerTree
|
|
|
|
|
tree={tree}
|
|
|
|
|
activePath={activePath}
|
|
|
|
|
onSelect={onSelect}
|
|
|
|
|
onRefresh={onRefresh}
|
|
|
|
|
parentDir={parentDir}
|
|
|
|
|
onNavigateUp={onNavigateUp}
|
|
|
|
|
browseDir={browseDir}
|
|
|
|
|
workspaceRoot={workspaceRoot}
|
|
|
|
|
onExternalDrop={onExternalDrop}
|
|
|
|
|
/>
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
)}
|
|
|
|
|
</div>
|
2026-02-11 16:45:07 -08:00
|
|
|
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
{/* Footer */}
|
|
|
|
|
<div
|
|
|
|
|
className="px-3 py-2.5 border-t flex items-center justify-between"
|
|
|
|
|
style={{ borderColor: "var(--color-border)" }}
|
|
|
|
|
>
|
2026-02-13 15:52:13 -08:00
|
|
|
<a
|
2026-02-13 19:24:24 -08:00
|
|
|
href="https://ironclaw.sh"
|
|
|
|
|
target="_blank"
|
|
|
|
|
rel="noopener noreferrer"
|
2026-02-13 15:52:13 -08:00
|
|
|
className="flex items-center gap-2 px-2 py-1.5 rounded-lg text-sm"
|
|
|
|
|
style={{ color: "var(--color-text-muted)" }}
|
|
|
|
|
>
|
2026-02-13 19:24:24 -08:00
|
|
|
ironclaw.sh
|
2026-02-13 15:52:13 -08:00
|
|
|
</a>
|
2026-02-21 14:39:55 -08:00
|
|
|
<div className="flex items-center gap-0.5">
|
|
|
|
|
{onToggleHidden && (
|
|
|
|
|
<button
|
|
|
|
|
type="button"
|
|
|
|
|
onClick={onToggleHidden}
|
|
|
|
|
className="p-1.5 rounded-lg transition-colors"
|
|
|
|
|
style={{ color: showHidden ? "var(--color-accent)" : "var(--color-text-muted)" }}
|
|
|
|
|
title={showHidden ? "Hide dotfiles" : "Show dotfiles"}
|
|
|
|
|
>
|
|
|
|
|
<svg
|
|
|
|
|
width="16"
|
|
|
|
|
height="16"
|
|
|
|
|
viewBox="0 0 24 24"
|
|
|
|
|
fill="none"
|
|
|
|
|
stroke="currentColor"
|
|
|
|
|
strokeWidth="2"
|
|
|
|
|
strokeLinecap="round"
|
|
|
|
|
strokeLinejoin="round"
|
|
|
|
|
>
|
|
|
|
|
{showHidden ? (
|
|
|
|
|
<>
|
|
|
|
|
<path d="M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" />
|
|
|
|
|
<circle cx="12" cy="12" r="3" />
|
|
|
|
|
</>
|
|
|
|
|
) : (
|
|
|
|
|
<>
|
|
|
|
|
<path d="M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" />
|
|
|
|
|
<path d="M14.084 14.158a3 3 0 0 1-4.242-4.242" />
|
|
|
|
|
<path d="M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" />
|
|
|
|
|
<path d="m2 2 20 20" />
|
|
|
|
|
</>
|
|
|
|
|
)}
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
)}
|
|
|
|
|
<ThemeToggle />
|
|
|
|
|
</div>
|
feat(web): full UI redesign with light/dark theme, TanStack data tables, media rendering, and gateway-routed agent execution
Overhaul the Dench web app with a comprehensive visual redesign and several
major feature additions across the chat interface, workspace, and agent
runtime layer.
Theme & Design System
- Replace the dark-only palette with a full light/dark theme system that
respects system preference via localStorage + inline script (no FOUC).
- Introduce new design tokens: glassmorphism surfaces, semantic colors
(success/warning/error/info), object-type chip palettes, and a tiered
shadow scale (sm/md/lg/xl).
- Add Instrument Serif + Inter via Google Fonts for a refined typographic
hierarchy; headings use the serif face, body uses Inter.
- Rebrand UI from "Ironclaw" to "Dench" across the landing page and
metadata.
Chat & Chain-of-Thought
- Rewrite the chain-of-thought component with inline media detection and
rendering — images, video, audio, and PDFs referenced in agent output
are now displayed directly in the conversation thread.
- Add status indicator parts (e.g. "Preparing response...",
"Optimizing session context...") that render as subtle activity badges
instead of verbose reasoning blocks.
- Integrate react-markdown with remark-gfm for proper markdown rendering
in assistant messages (tables, strikethrough, autolinks, etc.).
- Improve report-block splitting and lazy-loaded ReportCard rendering.
Workspace
- Introduce @tanstack/react-table for the object table, replacing the
hand-rolled table with full column sorting, fuzzy filtering via
match-sorter-utils, row selection, and bulk actions.
- Add a new media viewer component for in-workspace image/video/PDF
preview.
- New API routes: bulk-delete entries, field management (CRUD + reorder),
raw-file serving endpoint for media assets.
- Redesign workspace sidebar, empty state, and entry detail modal with
the new theme tokens and improved layout.
Agent Runtime
- Switch web agent execution from --local to gateway-routed mode so
concurrent chat threads share the gateway's lane-based concurrency
system, eliminating cross-process file-lock contention.
- Advertise "tool-events" capability during WebSocket handshake so the
gateway streams tool start/update/result events to the UI.
- Add new agent callback hooks: onLifecycleStart, onCompactionStart/End,
and onToolUpdate for richer real-time feedback.
- Forward media URLs emitted by agent events into the chat stream.
Dependencies
- Add @tanstack/match-sorter-utils and @tanstack/react-table to the web
app.
Published as ironclaw@2026.2.10-1.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 11:17:23 -08:00
|
|
|
</div>
|
|
|
|
|
</aside>
|
|
|
|
|
);
|
2026-02-16 00:30:13 -08:00
|
|
|
|
|
|
|
|
if (!mobile) { return sidebar; }
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className="drawer-backdrop" onClick={() => void onClose?.()}>
|
|
|
|
|
{/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}
|
|
|
|
|
<div onClick={(e) => e.stopPropagation()} className="fixed inset-y-0 left-0 z-50">
|
|
|
|
|
{sidebar}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
2026-02-11 16:45:07 -08:00
|
|
|
}
|