openclaw/apps/web/app/components/workspace/file-manager-tree.tsx

1284 lines
42 KiB
TypeScript
Raw Normal View History

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
"use client";
import { useState, useCallback, useRef, useEffect } from "react";
import {
DndContext,
DragOverlay,
useDraggable,
useDroppable,
closestCenter,
type DragStartEvent,
type DragEndEvent,
type DragOverEvent,
PointerSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import { ContextMenu, type ContextMenuAction, type ContextMenuTarget } from "./context-menu";
import { InlineRename, RENAME_SHAKE_STYLE } from "./inline-rename";
// --- Types ---
export type TreeNode = {
name: string;
path: string;
type: "object" | "document" | "folder" | "file" | "database" | "report";
icon?: string;
defaultView?: "table" | "kanban";
children?: TreeNode[];
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
/** When true, the node represents a virtual folder/file outside the real workspace (e.g. Skills, Memories). CRUD ops are disabled. */
virtual?: boolean;
/** True when the entry is a symbolic link / shortcut. */
symlink?: boolean;
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
};
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
/** Folder names reserved for virtual sections -- cannot be created/renamed to. */
const RESERVED_FOLDER_NAMES = new Set(["Chats", "Skills", "Memories"]);
/** Check if a node (or any of its ancestors) is virtual. Paths starting with ~ are always virtual. */
function isVirtualNode(node: TreeNode): boolean {
return !!node.virtual || node.path.startsWith("~");
}
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
type FileManagerTreeProps = {
tree: TreeNode[];
activePath: string | null;
onSelect: (node: TreeNode) => void;
onRefresh: () => void;
compact?: boolean;
2026-02-13 15:16:36 -08:00
/** Parent directory path for ".." navigation. Null when at filesystem root or in workspace mode without browsing. */
parentDir?: string | null;
/** Callback when user clicks ".." to navigate up. */
onNavigateUp?: () => void;
/** Current browse directory (absolute path), or null when in workspace mode. */
browseDir?: string | null;
2026-02-13 19:24:24 -08:00
/** Absolute path of the workspace root. Nodes matching this path are rendered as a special non-collapsible workspace entry point. */
workspaceRoot?: string | null;
2026-02-15 23:42:13 -08:00
/** Called when a node is dragged and dropped outside the tree onto an external drop target (e.g. chat input). */
onExternalDrop?: (node: TreeNode) => void;
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
};
// --- System file detection (client-side mirror) ---
/** Always protected regardless of depth. */
const ALWAYS_SYSTEM_PATTERNS = [
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
/^\.object\.yaml$/,
/\.wal$/,
/\.tmp$/,
];
/** Only protected at the workspace root (no "/" in the relative path). */
const ROOT_ONLY_SYSTEM_PATTERNS = [
/^workspace\.duckdb/,
/^workspace_context\.yaml$/,
];
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
function isSystemFile(path: string): boolean {
const base = path.split("/").pop() ?? "";
if (ALWAYS_SYSTEM_PATTERNS.some((p) => p.test(base))) {return true;}
const isRoot = !path.includes("/");
return isRoot && ROOT_ONLY_SYSTEM_PATTERNS.some((p) => p.test(base));
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
}
// --- Icons (inline SVG, zero-dep) ---
function FolderIcon({ open }: { open?: boolean }) {
return (
<img
src={open ? "/icons/folder-open.png" : "/icons/folder.png"}
alt=""
width={16}
height={16}
draggable={false}
style={{ flexShrink: 0 }}
/>
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
);
}
function TableIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M12 3v18" /><rect width="18" height="18" x="3" y="3" rx="2" /><path d="M3 9h18" /><path d="M3 15h18" />
</svg>
);
}
function KanbanIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect width="6" height="14" x="2" y="5" rx="1" /><rect width="6" height="10" x="9" y="5" rx="1" /><rect width="6" height="16" x="16" y="3" rx="1" />
</svg>
);
}
function DocumentIcon() {
return (
<img src="/icons/document.png" alt="" width={16} height={16} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
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
);
}
function FileIcon() {
return (
<img src="/icons/document.png" alt="" width={16} height={16} draggable={false} style={{ flexShrink: 0, filter: "drop-shadow(0 0.5px 1.5px rgba(0,0,0,0.2))" }} />
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
);
}
function DatabaseIcon() {
return (
<svg width="16" height="16" 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 ReportIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<line x1="12" x2="12" y1="20" y2="10" /><line x1="18" x2="18" y1="20" y2="4" /><line x1="6" x2="6" y1="20" y2="14" />
</svg>
);
}
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 ChatBubbleIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
</svg>
);
}
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
function LockBadge() {
return (
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ opacity: 0.4 }}>
<rect width="18" height="11" x="3" y="11" rx="2" ry="2" /><path d="M7 11V7a5 5 0 0 1 10 0v4" />
</svg>
);
}
function SymlinkBadge() {
return (
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round" style={{ opacity: 0.55 }}>
<path d="m9 18 6-6-6-6" />
</svg>
);
}
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
function ChevronIcon({ open }: { open: boolean }) {
return (
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"
style={{ transform: open ? "rotate(90deg)" : "rotate(0deg)", transition: "transform 150ms ease" }}>
<path d="m9 18 6-6-6-6" />
</svg>
);
}
2026-02-13 19:24:24 -08:00
function WorkspaceGridIcon() {
return (
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<rect width="7" height="7" x="3" y="3" rx="1" />
<rect width="7" height="7" x="14" y="3" rx="1" />
<rect width="7" height="7" x="14" y="14" rx="1" />
<rect width="7" height="7" x="3" y="14" rx="1" />
</svg>
);
}
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
function NodeIcon({ node, open }: { node: TreeNode; open?: boolean }) {
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
// Chat items use the chat bubble icon
if (node.path.startsWith("~chats/") || node.path === "~chats") {
return <ChatBubbleIcon />;
}
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
switch (node.type) {
case "object":
return node.defaultView === "kanban" ? <KanbanIcon /> : <TableIcon />;
case "document":
return <DocumentIcon />;
case "folder":
return <FolderIcon open={open} />;
case "database":
return <DatabaseIcon />;
case "report":
return <ReportIcon />;
default:
return <FileIcon />;
}
}
function typeColor(node: TreeNode): string {
switch (node.type) {
case "object": return "var(--color-accent)";
case "document": return "#60a5fa";
case "database": return "#c084fc";
case "report": return "#22c55e";
default: return "var(--color-text-muted)";
}
}
// --- API helpers ---
async function apiRename(path: string, newName: string) {
const res = await fetch("/api/workspace/rename", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path, newName }),
});
return res.json();
}
async function apiDelete(path: string) {
const res = await fetch("/api/workspace/file", {
method: "DELETE",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path }),
});
return res.json();
}
async function apiMove(sourcePath: string, destinationDir: string) {
const res = await fetch("/api/workspace/move", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ sourcePath, destinationDir }),
});
return res.json();
}
async function apiDuplicate(path: string) {
const res = await fetch("/api/workspace/copy", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path }),
});
return res.json();
}
async function apiMkdir(path: string) {
const res = await fetch("/api/workspace/mkdir", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path }),
});
return res.json();
}
async function apiCreateFile(path: string, content: string = "") {
const res = await fetch("/api/workspace/file", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ path, content }),
});
return res.json();
}
// --- Confirm dialog ---
function ConfirmDialog({
message,
onConfirm,
onCancel,
}: {
message: string;
onConfirm: () => void;
onCancel: () => void;
}) {
useEffect(() => {
function handleKey(e: KeyboardEvent) {
if (e.key === "Escape") {onCancel();}
if (e.key === "Enter") {onConfirm();}
}
document.addEventListener("keydown", handleKey);
return () => document.removeEventListener("keydown", handleKey);
}, [onConfirm, onCancel]);
return (
<div className="fixed inset-0 z-[10000] flex items-center justify-center" style={{ background: "rgba(0,0,0,0.5)" }}>
<div className="rounded-xl p-5 max-w-sm w-full shadow-2xl border" style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}>
<p className="text-sm mb-4" style={{ color: "var(--color-text)" }}>{message}</p>
<div className="flex justify-end gap-2">
<button
type="button"
onClick={onCancel}
className="px-3 py-1.5 rounded-md text-sm"
style={{ color: "var(--color-text-muted)", background: "var(--color-surface-hover)" }}
>
Cancel
</button>
<button
type="button"
onClick={onConfirm}
className="px-3 py-1.5 rounded-md text-sm text-white"
style={{ background: "#ef4444" }}
>
Delete
</button>
</div>
</div>
</div>
);
}
// --- New item prompt ---
function NewItemPrompt({
kind,
parentPath,
onSubmit,
onCancel,
}: {
kind: "file" | "folder";
parentPath: string;
onSubmit: (name: string) => void;
onCancel: () => void;
}) {
const [value, setValue] = useState(kind === "file" ? "untitled.md" : "new-folder");
const inputRef = useRef<HTMLInputElement>(null);
useEffect(() => {
const el = inputRef.current;
if (!el) {return;}
el.focus();
if (kind === "file") {
const dot = value.lastIndexOf(".");
el.setSelectionRange(0, dot > 0 ? dot : value.length);
} else {
el.select();
}
}, []);
return (
<div className="fixed inset-0 z-[10000] flex items-center justify-center" style={{ background: "rgba(0,0,0,0.5)" }}>
<div className="rounded-xl p-5 max-w-sm w-full shadow-2xl border" style={{ background: "var(--color-surface)", borderColor: "var(--color-border)" }}>
<p className="text-sm mb-3 font-medium" style={{ color: "var(--color-text)" }}>
New {kind} in <span style={{ color: "var(--color-accent)" }}>{parentPath || "/"}</span>
</p>
<input
ref={inputRef}
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
onKeyDown={(e) => {
if (e.key === "Enter") {onSubmit(value.trim());}
if (e.key === "Escape") {onCancel();}
}}
className="w-full px-3 py-2 rounded-md text-sm outline-none border"
style={{ background: "var(--color-bg)", color: "var(--color-text)", borderColor: "var(--color-border)" }}
/>
<div className="flex justify-end gap-2 mt-3">
<button type="button" onClick={onCancel} className="px-3 py-1.5 rounded-md text-sm" style={{ color: "var(--color-text-muted)", background: "var(--color-surface-hover)" }}>
Cancel
</button>
<button type="button" onClick={() => onSubmit(value.trim())} className="px-3 py-1.5 rounded-md text-sm text-white" style={{ background: "var(--color-accent)" }}>
Create
</button>
</div>
</div>
</div>
);
}
// --- Draggable + Droppable Node ---
function DraggableNode({
node,
depth,
activePath,
selectedPath,
onSelect,
onNodeSelect,
expandedPaths,
onToggleExpand,
renamingPath,
onStartRename,
onCommitRename,
onCancelRename,
onContextMenu,
compact,
dragOverPath,
2026-02-13 19:24:24 -08:00
workspaceRoot,
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
}: {
node: TreeNode;
depth: number;
activePath: string | null;
selectedPath: string | null;
onSelect: (node: TreeNode) => void;
onNodeSelect: (path: string) => void;
expandedPaths: Set<string>;
onToggleExpand: (path: string) => void;
renamingPath: string | null;
onStartRename: (path: string) => void;
onCommitRename: (newName: string) => void;
onCancelRename: () => void;
onContextMenu: (e: React.MouseEvent, node: TreeNode) => void;
compact?: boolean;
dragOverPath: string | null;
2026-02-13 19:24:24 -08:00
workspaceRoot?: string | null;
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
}) {
2026-02-13 19:24:24 -08:00
// Workspace root in browse mode: non-expandable entry point back to workspace
const isWorkspaceRoot = !!workspaceRoot && node.path === workspaceRoot;
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
const hasChildren = node.children && node.children.length > 0;
2026-02-13 19:24:24 -08:00
const isExpandable = isWorkspaceRoot ? false : (hasChildren || node.type === "folder" || node.type === "object");
const isExpanded = isWorkspaceRoot ? false : expandedPaths.has(node.path);
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
const isActive = activePath === node.path;
const isSelected = selectedPath === node.path;
const isRenaming = renamingPath === node.path;
const isSysFile = isSystemFile(node.path);
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
const isVirtual = isVirtualNode(node);
2026-02-13 19:24:24 -08:00
const isProtected = isSysFile || isVirtual || isWorkspaceRoot;
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
const isDragOver = dragOverPath === node.path && isExpandable;
const { attributes, listeners, setNodeRef: setDragRef, isDragging } = useDraggable({
id: `drag-${node.path}`,
data: { node },
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
disabled: isProtected,
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
});
const { setNodeRef: setDropRef, isOver } = useDroppable({
id: `drop-${node.path}`,
data: { node },
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
disabled: !isExpandable || isVirtual,
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
});
const handleClick = useCallback(() => {
onNodeSelect(node.path);
onSelect(node);
if (isExpandable) {
onToggleExpand(node.path);
}
}, [node, isExpandable, onSelect, onNodeSelect, onToggleExpand]);
const handleDoubleClick = useCallback(() => {
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
if (!isProtected) {
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
onStartRename(node.path);
}
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
}, [node.path, isProtected, onStartRename]);
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
const handleContextMenu = useCallback(
(e: React.MouseEvent) => {
e.preventDefault();
e.stopPropagation();
onNodeSelect(node.path);
onContextMenu(e, node);
},
[node, onNodeSelect, onContextMenu],
);
// Merge drag + drop refs
const mergedRef = useCallback(
(el: HTMLElement | null) => {
setDragRef(el);
setDropRef(el);
},
[setDragRef, setDropRef],
);
const showDropHighlight = (isOver || isDragOver) && isExpandable;
return (
<div style={{ opacity: isDragging ? 0.4 : 1 }}>
<div
ref={mergedRef}
{...attributes}
{...listeners}
role="treeitem"
tabIndex={-1}
Web app: add syntax highlighting, diff viewer, rich chat editor, and file search Syntax highlighting & code viewer: - Add shiki for syntax-highlighted fenced code blocks in chat messages - New SyntaxBlock component (lazy shiki, dual light/dark theme) - New CodeViewer for workspace file panel (routes code files via isCodeFile()) - API routes (browse-file, virtual-file) now return "code" type for known extensions Diff rendering: - New DiffCard component for rendering unified diffs with add/remove colors - diff-blocks.ts parser to extract fenced blocks from markdown - Chain-of-thought tool steps show inline diffs for edit/write tools (synthetic from old_string/new_string or direct from tool output) - Agent runner passes through diff/firstChangedLine from edit tool results - Document view handles diff blocks alongside report blocks Rich chat editor (Tiptap): - Replace plain textarea with Tiptap-based ChatEditor - File mention extension (@-mention files with autocomplete dropdown) - File mention list with keyboard navigation and search via suggest-files API - New suggest-files API endpoint for fuzzy file search File search & navigation: - FileSearch component in workspace sidebar (debounced search, keyboard nav) - Search results navigate sidebar to file location and open in panel - File picker modal for browsing/selecting workspace files Drag & drop: - File tree nodes support native HTML5 drag (application/x-file-mention) for cross-component drops (e.g. dragging files into chat editor) Chat attachments reworked: - Switch from browser File objects to path-based references (name + path) - Simplified attachment strip (no media previews, shows shortened paths) Also adds software-engineering skill and related CSS for code blocks/shiki.
2026-02-13 18:06:59 -08:00
draggable={!isProtected}
onDragStart={(e) => {
// Native HTML5 drag for cross-component drops (e.g. into chat editor).
// Coexists with @dnd-kit which uses pointer events for intra-tree reordering.
e.dataTransfer.setData(
"application/x-file-mention",
JSON.stringify({ name: node.name, path: node.path }),
);
e.dataTransfer.setData("text/plain", node.path);
e.dataTransfer.effectAllowed = "copy";
}}
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
onClick={handleClick}
onDoubleClick={handleDoubleClick}
onContextMenu={handleContextMenu}
className="w-full flex items-center gap-1.5 py-1 px-2 rounded-md text-left text-sm transition-colors duration-100 cursor-pointer select-none"
style={{
paddingLeft: `${depth * 16 + 8}px`,
2026-02-13 19:24:24 -08:00
background: isWorkspaceRoot
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
? "var(--color-accent-light)"
2026-02-13 19:24:24 -08:00
: showDropHighlight
? "var(--color-accent-light)"
: isSelected
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
? "var(--color-surface-hover)"
2026-02-13 19:24:24 -08:00
: isActive
? "var(--color-surface-hover)"
: "transparent",
color: isWorkspaceRoot
? "var(--color-accent)"
: isActive || isSelected ? "var(--color-text)" : "var(--color-text-muted)",
outline: isWorkspaceRoot
? "1.5px solid var(--color-accent)"
: showDropHighlight ? "1px dashed var(--color-accent)" : "none",
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
outlineOffset: "-1px",
2026-02-13 19:24:24 -08:00
borderRadius: isWorkspaceRoot ? "8px" : "6px",
marginTop: isWorkspaceRoot ? "2px" : undefined,
marginBottom: isWorkspaceRoot ? "2px" : undefined,
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
}}
onMouseEnter={(e) => {
2026-02-13 19:24:24 -08:00
if (isWorkspaceRoot) {
(e.currentTarget as HTMLElement).style.opacity = "0.8";
} else if (!isActive && !isSelected && !showDropHighlight) {
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
(e.currentTarget as HTMLElement).style.background = "var(--color-surface-hover)";
}
}}
onMouseLeave={(e) => {
2026-02-13 19:24:24 -08:00
if (isWorkspaceRoot) {
(e.currentTarget as HTMLElement).style.opacity = "1";
} else if (!isActive && !isSelected && !showDropHighlight) {
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
(e.currentTarget as HTMLElement).style.background = "transparent";
}
}}
>
2026-02-13 19:24:24 -08:00
{/* Expand/collapse chevron intercept click so it only toggles without navigating */}
<span
className="flex-shrink-0 w-4 h-4 flex items-center justify-center"
style={{ opacity: isExpandable ? 1 : 0, cursor: isExpandable ? "pointer" : undefined }}
onClick={isExpandable ? (e) => { e.stopPropagation(); onToggleExpand(node.path); } : undefined}
>
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
{isExpandable && <ChevronIcon open={isExpanded} />}
</span>
{/* Icon */}
2026-02-13 19:24:24 -08:00
<span className="flex-shrink-0 flex items-center" style={{ color: isWorkspaceRoot ? "var(--color-accent)" : typeColor(node) }}>
{isWorkspaceRoot ? <WorkspaceGridIcon /> : <NodeIcon node={node} open={isExpanded} />}
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
</span>
{/* Label or rename input */}
{isRenaming ? (
<InlineRename
currentName={node.name}
onCommit={onCommitRename}
onCancel={onCancelRename}
/>
) : (
<span className="truncate flex-1">{node.name}</span>
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
)}
2026-02-13 19:24:24 -08:00
{/* Workspace badge for the workspace root entry point */}
{isWorkspaceRoot && (
<span className="text-[10px] px-1.5 py-0.5 rounded-full flex-shrink-0 font-medium"
style={{ background: "var(--color-accent)", color: "white" }}>
workspace
</span>
)}
{/* Lock badge for system/virtual files (skip for workspace root -- it has its own badge) */}
{isProtected && !isWorkspaceRoot && !compact && (
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
<span className="flex-shrink-0 ml-1">
<LockBadge />
</span>
)}
{/* Symlink indicator */}
{node.symlink && !compact && (
<span className="flex-shrink-0 ml-0.5" title="Symbolic link" style={{ color: "var(--color-text-muted)" }}>
<SymlinkBadge />
</span>
)}
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
{/* Type badge for objects */}
{node.type === "object" && (
<span className="text-[10px] px-1.5 py-0.5 rounded-full flex-shrink-0"
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={{ background: "var(--color-accent-light)", color: "var(--color-accent)" }}>
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
{node.defaultView === "kanban" ? "board" : "table"}
</span>
)}
</div>
{/* Children */}
{isExpanded && hasChildren && (
<div className="relative" style={{
borderLeft: depth > 0 ? "1px solid var(--color-border)" : "none",
marginLeft: `${depth * 16 + 16}px`,
}}>
{node.children!.map((child) => (
<DraggableNode
key={child.path}
node={child}
depth={depth + 1}
activePath={activePath}
selectedPath={selectedPath}
onSelect={onSelect}
onNodeSelect={onNodeSelect}
expandedPaths={expandedPaths}
onToggleExpand={onToggleExpand}
renamingPath={renamingPath}
onStartRename={onStartRename}
onCommitRename={onCommitRename}
onCancelRename={onCancelRename}
onContextMenu={onContextMenu}
compact={compact}
dragOverPath={dragOverPath}
2026-02-13 19:24:24 -08:00
workspaceRoot={workspaceRoot}
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
/>
))}
</div>
)}
</div>
);
}
// --- Root drop zone (allows dropping items back to the top level) ---
function RootDropZone({ isDragging }: { isDragging: boolean }) {
const { setNodeRef, isOver } = useDroppable({
id: "drop-__root__",
data: { rootDrop: true },
});
const showHighlight = isOver && isDragging;
return (
<div
ref={setNodeRef}
className="flex-1 min-h-[48px]"
style={{
margin: isDragging ? "4px 8px" : undefined,
borderRadius: "6px",
border: showHighlight ? "1.5px dashed var(--color-accent)" : isDragging ? "1.5px dashed var(--color-border)" : "1.5px dashed transparent",
background: showHighlight ? "var(--color-accent-light)" : "transparent",
transition: "all 150ms ease",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{isDragging && (
<span className="text-[11px] select-none" style={{ color: showHighlight ? "var(--color-accent)" : "var(--color-text-muted)", opacity: showHighlight ? 1 : 0.6 }}>
Drop here to move to root
</span>
)}
</div>
);
}
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
// --- Drag Overlay ---
function DragOverlayContent({ node }: { node: TreeNode }) {
return (
<div
className="flex items-center gap-2 px-3 py-1.5 rounded-lg text-sm shadow-lg border"
style={{
background: "var(--color-surface)",
borderColor: "var(--color-border)",
color: "var(--color-text)",
pointerEvents: "none",
}}
>
<span style={{ color: typeColor(node) }}>
<NodeIcon node={node} />
</span>
<span>{node.name}</span>
</div>
);
}
// --- Helper: find node by path ---
function findNode(tree: TreeNode[], path: string): TreeNode | null {
for (const n of tree) {
if (n.path === path) {return n;}
if (n.children) {
const found = findNode(n.children, path);
if (found) {return found;}
}
}
return null;
}
// --- Helper: get parent path ---
function parentPath(path: string): string {
const parts = path.split("/");
parts.pop();
return parts.join("/") || ".";
}
// --- Flatten tree for keyboard navigation ---
function flattenVisible(tree: TreeNode[], expanded: Set<string>): TreeNode[] {
const result: TreeNode[] = [];
function walk(nodes: TreeNode[]) {
for (const n of nodes) {
result.push(n);
if (n.children && expanded.has(n.path)) {
walk(n.children);
}
}
}
walk(tree);
return result;
}
// --- Main Exported Component ---
2026-02-15 23:42:13 -08:00
export function FileManagerTree({ tree, activePath, onSelect, onRefresh, compact, parentDir, onNavigateUp, browseDir: _browseDir, workspaceRoot, onExternalDrop }: FileManagerTreeProps) {
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
const [expandedPaths, setExpandedPaths] = useState<Set<string>>(() => new Set());
const [selectedPath, setSelectedPath] = useState<string | null>(null);
const [renamingPath, setRenamingPath] = useState<string | null>(null);
const [dragOverPath, setDragOverPath] = useState<string | null>(null);
const [activeNode, setActiveNode] = useState<TreeNode | null>(null);
2026-02-15 23:42:13 -08:00
// Track pointer position during @dnd-kit drags for cross-component drops.
2026-02-15 23:54:05 -08:00
// Installed synchronously in handleDragStart (not useEffect) to avoid
// missing early pointer moves. Capture-phase on window fires before
// @dnd-kit's own document-level listener.
2026-02-15 23:42:13 -08:00
const pointerPosRef = useRef({ x: 0, y: 0 });
2026-02-15 23:54:05 -08:00
const pointerListenerRef = useRef<((e: PointerEvent) => void) | null>(null);
2026-02-15 23:42:13 -08:00
2026-02-15 23:54:05 -08:00
const installPointerTracker = useCallback(() => {
const handler = (e: PointerEvent) => {
2026-02-15 23:42:13 -08:00
pointerPosRef.current = { x: e.clientX, y: e.clientY };
// Toggle visual drop indicator on external chat drop target
const el = document.elementFromPoint(e.clientX, e.clientY);
const target = el?.closest("[data-chat-drop-target]") as HTMLElement | null;
const prev = document.querySelector("[data-drag-hover]");
if (target && !target.hasAttribute("data-drag-hover")) {
target.setAttribute("data-drag-hover", "");
}
if (prev && prev !== target) {
prev.removeAttribute("data-drag-hover");
}
};
2026-02-15 23:54:05 -08:00
pointerListenerRef.current = handler;
window.addEventListener("pointermove", handler, true);
}, []);
2026-02-15 23:42:13 -08:00
2026-02-15 23:54:05 -08:00
const removePointerTracker = useCallback(() => {
if (pointerListenerRef.current) {
window.removeEventListener("pointermove", pointerListenerRef.current, true);
pointerListenerRef.current = null;
}
document.querySelector("[data-drag-hover]")?.removeAttribute("data-drag-hover");
}, []);
// Clean up on unmount
useEffect(() => removePointerTracker, [removePointerTracker]);
2026-02-15 23:42:13 -08:00
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
// Context menu state
const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number; target: ContextMenuTarget } | null>(null);
// Confirm dialog
const [confirmDelete, setConfirmDelete] = useState<string | null>(null);
// New item prompt
const [newItemPrompt, setNewItemPrompt] = useState<{ kind: "file" | "folder"; parentPath: string } | null>(null);
const containerRef = useRef<HTMLDivElement>(null);
2026-02-12 09:04:34 -08:00
// Auto-expand first level on mount.
// Keep ~skills and ~memories collapsed by default; always expand ~chats.
const collapsedByDefault = new Set(["~skills", "~memories"]);
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
useEffect(() => {
if (tree.length > 0 && expandedPaths.size === 0) {
const initial = new Set<string>();
for (const node of tree) {
2026-02-12 09:04:34 -08:00
if (collapsedByDefault.has(node.path)) {continue;}
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
if (node.children && node.children.length > 0) {
initial.add(node.path);
}
}
setExpandedPaths(initial);
}
}, [tree]);
const handleToggleExpand = useCallback((path: string) => {
setExpandedPaths((prev) => {
const next = new Set(prev);
if (next.has(path)) {next.delete(path);}
else {next.add(path);}
return next;
});
}, []);
// DnD sensors -- require 8px movement before dragging starts (prevents accidental drags on click)
const sensors = useSensors(
useSensor(PointerSensor, { activationConstraint: { distance: 8 } }),
);
const handleDragStart = useCallback((event: DragStartEvent) => {
const data = event.active.data.current as { node: TreeNode } | undefined;
2026-02-15 23:54:05 -08:00
if (data?.node) {
setActiveNode(data.node);
installPointerTracker();
}
}, [installPointerTracker]);
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
const handleDragOver = useCallback((event: DragOverEvent) => {
const overData = event.over?.data.current as { node?: TreeNode; rootDrop?: boolean } | undefined;
if (overData?.rootDrop) {
setDragOverPath("__root__");
} else if (overData?.node) {
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
setDragOverPath(overData.node.path);
// Auto-expand folders on drag hover (300ms delay)
const path = overData.node.path;
if (overData.node.type === "folder" || overData.node.type === "object") {
setTimeout(() => {
setExpandedPaths((prev) => {
if (prev.has(path)) {return prev;}
const next = new Set(prev);
next.add(path);
return next;
});
}, 300);
}
} else {
setDragOverPath(null);
}
}, []);
const handleDragEnd = useCallback(
async (event: DragEndEvent) => {
setActiveNode(null);
setDragOverPath(null);
2026-02-15 23:54:05 -08:00
removePointerTracker();
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
const activeData = event.active.data.current as { node: TreeNode } | undefined;
if (!activeData?.node) {return;}
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
const source = activeData.node;
2026-02-15 23:54:05 -08:00
// Check for external drop targets FIRST (e.g. chat input).
// closestCenter always returns a droppable even when the pointer is
// far outside the tree, so we can't rely on `event.over === null`.
if (onExternalDrop) {
const { x, y } = pointerPosRef.current;
const el = document.elementFromPoint(x, y);
if (el?.closest("[data-chat-drop-target]")) {
onExternalDrop(source);
return;
}
}
const overData = event.over?.data.current as { node?: TreeNode; rootDrop?: boolean } | undefined;
// Drop onto root level
if (overData?.rootDrop) {
// Already at root? No-op
if (parentPath(source.path) === ".") {return;}
const result = await apiMove(source.path, ".");
if (result.ok) {
onRefresh();
}
return;
}
2026-02-15 23:54:05 -08:00
if (!overData?.node) {return;}
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
const target = overData.node;
// Only drop onto expandable targets (folders/objects)
if (target.type !== "folder" && target.type !== "object") {return;}
// Prevent dropping into self or children
if (target.path === source.path || target.path.startsWith(source.path + "/")) {return;}
// Prevent no-op moves (already in same parent)
if (parentPath(source.path) === target.path) {return;}
const result = await apiMove(source.path, target.path);
if (result.ok) {
onRefresh();
}
},
2026-02-15 23:54:05 -08:00
[onRefresh, onExternalDrop, removePointerTracker],
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
);
const handleDragCancel = useCallback(() => {
setActiveNode(null);
setDragOverPath(null);
2026-02-15 23:54:05 -08:00
removePointerTracker();
}, [removePointerTracker]);
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
// Context menu handlers
const handleContextMenu = useCallback((e: React.MouseEvent, node: TreeNode) => {
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
const isSys = isSystemFile(node.path) || isVirtualNode(node);
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
const isFolder = node.type === "folder" || node.type === "object";
setCtxMenu({
x: e.clientX,
y: e.clientY,
target: {
kind: isFolder ? "folder" : "file",
path: node.path,
name: node.name,
isSystem: isSys,
},
});
}, []);
const handleEmptyContextMenu = useCallback((e: React.MouseEvent) => {
e.preventDefault();
setCtxMenu({
x: e.clientX,
y: e.clientY,
target: { kind: "empty" },
});
}, []);
const handleContextMenuAction = useCallback(
async (action: ContextMenuAction) => {
const target = ctxMenu?.target;
if (!target) {return;}
switch (action) {
case "open": {
if (target.kind !== "empty") {
const node = findNode(tree, target.path);
if (node) {onSelect(node);}
}
break;
}
case "rename": {
if (target.kind !== "empty") {
setRenamingPath(target.path);
}
break;
}
case "duplicate": {
if (target.kind !== "empty") {
await apiDuplicate(target.path);
onRefresh();
}
break;
}
case "copy": {
if (target.kind !== "empty") {
await navigator.clipboard.writeText(target.path);
}
break;
}
case "delete": {
if (target.kind !== "empty") {
setConfirmDelete(target.path);
}
break;
}
case "newFile": {
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
const parent = target.kind === "folder" ? target.path : target.kind === "file" ? parentPath(target.path) : "";
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
setNewItemPrompt({ kind: "file", parentPath: parent });
break;
}
case "newFolder": {
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
const parent = target.kind === "folder" ? target.path : target.kind === "file" ? parentPath(target.path) : "";
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
setNewItemPrompt({ kind: "folder", parentPath: parent });
break;
}
case "getInfo": {
// Future: show info panel. For now, copy path.
if (target.kind !== "empty") {
await navigator.clipboard.writeText(target.path);
}
break;
}
}
},
[ctxMenu, tree, onSelect, onRefresh],
);
// Rename handlers
const handleCommitRename = useCallback(
async (newName: string) => {
if (!renamingPath) {return;}
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
// Block reserved folder names
if (RESERVED_FOLDER_NAMES.has(newName)) {
alert(`"${newName}" is a reserved name and cannot be used.`);
setRenamingPath(null);
return;
}
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
const result = await apiRename(renamingPath, newName);
setRenamingPath(null);
if (result.ok) {onRefresh();}
},
[renamingPath, onRefresh],
);
const handleCancelRename = useCallback(() => {
setRenamingPath(null);
}, []);
// Delete confirm
const handleConfirmDelete = useCallback(async () => {
if (!confirmDelete) {return;}
const result = await apiDelete(confirmDelete);
setConfirmDelete(null);
if (result.ok) {onRefresh();}
}, [confirmDelete, onRefresh]);
// New item submit
const handleNewItemSubmit = useCallback(
async (name: string) => {
if (!newItemPrompt || !name) {return;}
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
// Block reserved folder names
if (RESERVED_FOLDER_NAMES.has(name)) {
alert(`"${name}" is a reserved name and cannot be used.`);
return;
}
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
const fullPath = newItemPrompt.parentPath ? `${newItemPrompt.parentPath}/${name}` : name;
if (newItemPrompt.kind === "folder") {
await apiMkdir(fullPath);
} else {
await apiCreateFile(fullPath, "");
}
setNewItemPrompt(null);
onRefresh();
// Auto-expand parent
setExpandedPaths((prev) => {
const next = new Set(prev);
next.add(newItemPrompt.parentPath);
return next;
});
},
[newItemPrompt, onRefresh],
);
// Keyboard shortcuts
const handleKeyDown = useCallback(
(e: React.KeyboardEvent) => {
// Don't capture keyboard events when renaming
if (renamingPath) {return;}
const flat = flattenVisible(tree, expandedPaths);
const curIdx = flat.findIndex((n) => n.path === selectedPath);
const curNode = curIdx >= 0 ? flat[curIdx] : null;
switch (e.key) {
case "ArrowDown": {
e.preventDefault();
const next = curIdx < flat.length - 1 ? flat[curIdx + 1] : flat[0];
if (next) {setSelectedPath(next.path);}
break;
}
case "ArrowUp": {
e.preventDefault();
const prev = curIdx > 0 ? flat[curIdx - 1] : flat[flat.length - 1];
if (prev) {setSelectedPath(prev.path);}
break;
}
case "ArrowRight": {
e.preventDefault();
if (curNode && (curNode.type === "folder" || curNode.type === "object")) {
setExpandedPaths((p) => new Set([...p, curNode.path]));
}
break;
}
case "ArrowLeft": {
e.preventDefault();
if (curNode && expandedPaths.has(curNode.path)) {
setExpandedPaths((p) => {
const n = new Set(p);
n.delete(curNode.path);
return n;
});
}
break;
}
case "Enter": {
e.preventDefault();
if (curNode) {
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
const curProtected = isSystemFile(curNode.path) || isVirtualNode(curNode);
if (e.shiftKey || curProtected) {
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
onSelect(curNode);
} else {
setRenamingPath(curNode.path);
}
}
break;
}
case "F2": {
e.preventDefault();
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
if (curNode && !isSystemFile(curNode.path) && !isVirtualNode(curNode)) {
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
setRenamingPath(curNode.path);
}
break;
}
case "Backspace":
case "Delete": {
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
if (curNode && !isSystemFile(curNode.path) && !isVirtualNode(curNode)) {
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
e.preventDefault();
setConfirmDelete(curNode.path);
}
break;
}
default: {
// Cmd+key shortcuts
if (e.metaKey || e.ctrlKey) {
if (e.key === "c" && curNode) {
e.preventDefault();
2026-02-13 15:52:13 -08:00
void navigator.clipboard.writeText(curNode.path);
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
} else if (e.key === "d" && curNode && !isSystemFile(curNode.path)) {
e.preventDefault();
2026-02-13 15:52:13 -08:00
void apiDuplicate(curNode.path).then(() => onRefresh());
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
} else if (e.key === "n") {
e.preventDefault();
const parent = curNode
? curNode.type === "folder" || curNode.type === "object"
? curNode.path
: parentPath(curNode.path)
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
: "";
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
if (e.shiftKey) {
setNewItemPrompt({ kind: "folder", parentPath: parent });
} else {
setNewItemPrompt({ kind: "file", parentPath: parent });
}
}
}
break;
}
}
},
[tree, expandedPaths, selectedPath, renamingPath, onSelect, onRefresh],
);
if (tree.length === 0) {
return (
<div
className="px-4 py-6 text-center text-sm"
style={{ color: "var(--color-text-muted)" }}
onContextMenu={handleEmptyContextMenu}
>
No files in workspace
{ctxMenu && (
<ContextMenu
x={ctxMenu.x}
y={ctxMenu.y}
target={ctxMenu.target}
onAction={handleContextMenuAction}
onClose={() => setCtxMenu(null)}
/>
)}
{newItemPrompt && (
<NewItemPrompt
kind={newItemPrompt.kind}
parentPath={newItemPrompt.parentPath}
onSubmit={handleNewItemSubmit}
onCancel={() => setNewItemPrompt(null)}
/>
)}
</div>
);
}
return (
<DndContext
sensors={sensors}
collisionDetection={closestCenter}
onDragStart={handleDragStart}
onDragOver={handleDragOver}
onDragEnd={handleDragEnd}
onDragCancel={handleDragCancel}
>
<div
ref={containerRef}
className="py-1 outline-none flex flex-col min-h-full"
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
tabIndex={0}
role="tree"
onKeyDown={handleKeyDown}
onContextMenu={handleEmptyContextMenu}
>
2026-02-13 15:16:36 -08:00
{/* ".." navigation entry for browsing up */}
{parentDir != null && onNavigateUp && (
<div
role="treeitem"
tabIndex={-1}
onClick={onNavigateUp}
className="w-full flex items-center gap-1.5 py-1 px-2 rounded-md text-left text-sm transition-colors duration-100 cursor-pointer select-none"
style={{
paddingLeft: "8px",
color: "var(--color-text-muted)",
borderRadius: "6px",
}}
onMouseEnter={(e) => {
(e.currentTarget as HTMLElement).style.background = "var(--color-surface-hover)";
}}
onMouseLeave={(e) => {
(e.currentTarget as HTMLElement).style.background = "transparent";
}}
>
<span className="flex-shrink-0 w-4 h-4 flex items-center justify-center">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<path d="m15 18-6-6 6-6" />
</svg>
</span>
<span className="flex-shrink-0 flex items-center" style={{ color: "var(--color-text-muted)" }}>
<FolderIcon />
</span>
<span className="truncate flex-1">..</span>
</div>
)}
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
{tree.map((node) => (
<DraggableNode
key={node.path}
node={node}
depth={0}
activePath={activePath}
selectedPath={selectedPath}
onSelect={onSelect}
onNodeSelect={setSelectedPath}
expandedPaths={expandedPaths}
onToggleExpand={handleToggleExpand}
renamingPath={renamingPath}
onStartRename={setRenamingPath}
onCommitRename={handleCommitRename}
onCancelRename={handleCancelRename}
onContextMenu={handleContextMenu}
compact={compact}
dragOverPath={dragOverPath}
2026-02-13 19:24:24 -08:00
workspaceRoot={workspaceRoot}
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
/>
))}
{/* Root-level drop zone: fills remaining space so items can be moved to root */}
<RootDropZone isDragging={!!activeNode} />
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
</div>
2026-02-15 23:54:05 -08:00
{/* Drag overlay (ghost) — pointer-events:none so elementFromPoint sees through it */}
<DragOverlay dropAnimation={null} style={{ pointerEvents: "none" }}>
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
{activeNode ? <DragOverlayContent node={activeNode} /> : null}
</DragOverlay>
{/* Context menu */}
{ctxMenu && (
<ContextMenu
x={ctxMenu.x}
y={ctxMenu.y}
target={ctxMenu.target}
onAction={handleContextMenuAction}
onClose={() => setCtxMenu(null)}
/>
)}
{/* Delete confirmation dialog */}
{confirmDelete && (
<ConfirmDialog
message={`Are you sure you want to delete "${confirmDelete.split("/").pop()}"? This action cannot be undone.`}
onConfirm={handleConfirmDelete}
onCancel={() => setConfirmDelete(null)}
/>
)}
{/* New file/folder prompt */}
{newItemPrompt && (
<NewItemPrompt
kind={newItemPrompt.kind}
parentPath={newItemPrompt.parentPath}
onSubmit={handleNewItemSubmit}
onCancel={() => setNewItemPrompt(null)}
/>
)}
{/* Inject animation styles */}
<style>{RENAME_SHAKE_STYLE}</style>
</DndContext>
);
}