diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index 921711b..c026a1b 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -37,7 +37,7 @@ - Agent dispatcher (`src/lib/agent-dispatcher.ts`) is a singleton that routes sidecar events to the agent store. Handles subagent routing (project-scoped sessions skip layout pane, render in TeamAgentsPanel; detached mode creates layout pane). Session persistence via registerSessionProject() + persistSessionForProject() (saves state + messages to SQLite on complete). - AgentQueryOptions supports `permission_mode` field (flows Rust -> sidecar -> SDK). Defaults to 'bypassPermissions', supports 'default' mode. allowDangerouslySkipPermissions is conditionally set. Also supports: `setting_sources` (defaults to ['user', 'project']), `system_prompt`, `model`, `claude_config_dir` (for multi-account), `additional_directories`. - Claude profiles: claude_list_profiles() reads ~/.config/switcher/profiles/ with profile.toml metadata. Profile set per-project in Settings (project.profile field), passed through ClaudeSession -> AgentPane `profile` prop -> resolved to config_dir for SDK. Profile name shown as info-only in ProjectHeader. -- ProjectBox has project-level tab bar: Claude | Files | Context. Content area switches between ClaudeSession+TeamAgentsPanel, ProjectFiles (project-scoped markdown viewer), and ContextPane. ProjectFiles.svelte accepts cwd/projectName props (not workspace store). +- ProjectBox has project-level tab bar: Model | Docs | Context | Files | SSH | Memory. Three mount strategies: PERSISTED-EAGER (Model, Docs, Context — always mounted, display:flex/none), PERSISTED-LAZY (Files, SSH, Memory — mount on first activation via {#if everActivated} + display:flex/none). Tab type: `'model' | 'docs' | 'context' | 'files' | 'ssh' | 'memories'`. Model tab = ClaudeSession+TeamAgentsPanel. Docs tab = ProjectFiles (markdown viewer). Files tab = FilesTab.svelte (VSCode-style directory tree + content viewer, shiki highlighting, image display via convertFileSrc, 10MB gate). SSH tab = SshTab.svelte (CRUD for SSH connections, launch spawns terminal tab in Model tab). Memory tab = MemoriesTab.svelte (pluggable via MemoryAdapter interface in memory-adapter.ts). Rust backend: list_directory_children + read_file_content (FileContent tagged union: Text/Binary/TooLarge). Frontend bridge: files-bridge.ts. - ProjectHeader shows CWD (ellipsized from START via `direction: rtl`) + profile name as info-only text on right side. AgentPane no longer has DIR/ACC toolbar — CWD and profile are props from parent. - Skill discovery: claude_list_skills() reads ~/.claude/skills/ (dirs with SKILL.md or .md files). claude_read_skill() reads content. AgentPane `/` prefix triggers autocomplete menu. Skill content injected as prompt via expandSkillPrompt(). - claude-bridge.ts adapter wraps profile/skill Tauri commands (ClaudeProfile, ClaudeSkill interfaces). diff --git a/CHANGELOG.md b/CHANGELOG.md index b79905d..ae5e29c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `StartupWMClass=bterminal` in install-v2.sh .desktop template for GNOME auto-move extension compatibility - MarkdownPane link navigation: relative file links open in Files tab, external URLs open in system browser via `xdg-open`, anchor links scroll in-page (MarkdownPane.svelte, ProjectFiles.svelte, lib.rs) - `open_url` Tauri command for opening http/https URLs in system browser (lib.rs) +- Tab system overhaul: renamed Claude→Model, Files→Docs, added 3 new tabs (Files, SSH, Memory) with PERSISTED-EAGER/LAZY mount strategies (ProjectBox.svelte) +- FilesTab: VSCode-style directory tree sidebar + content viewer with shiki syntax highlighting, image display via convertFileSrc, 10MB file size gate (FilesTab.svelte) +- SshTab: SSH connection CRUD panel with launch-to-terminal button, reuses existing ssh-bridge.ts model (SshTab.svelte) +- MemoriesTab: pluggable knowledge explorer with MemoryAdapter interface, adapter registry, search, tag display, expandable cards (MemoriesTab.svelte, memory-adapter.ts) +- Rust `list_directory_children` command: lazy tree expansion, hidden files skipped, dirs-first alphabetical sort (lib.rs) +- Rust `read_file_content` command: FileContent tagged union (Text/Binary/TooLarge), 30+ language mappings (lib.rs) +- Frontend `files-bridge.ts` adapter: DirEntry and FileContent TypeScript types + IPC wrappers ### Changed - AgentPane UI redesign: sans-serif root font (system-ui), tool calls paired with results in collapsible `
` groups, hook messages collapsed into compact labels, context window usage meter in status strip, cost bar made minimal (no background), session summary with translucent background, two-phase scroll anchoring, tool-aware output truncation (Bash 500/Read 50/Glob 20 lines), colors softened via `color-mix()`, responsive margins via container queries (AgentPane.svelte) diff --git a/CLAUDE.md b/CLAUDE.md index 6d6b89a..133a6af 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -60,6 +60,8 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src/lib/adapters/claude-bridge.ts` | Claude profiles + skills IPC wrapper | | `v2/src/lib/adapters/groups-bridge.ts` | Groups config IPC wrapper (load/save) | | `v2/src/lib/adapters/remote-bridge.ts` | Remote machine management IPC wrapper | +| `v2/src/lib/adapters/files-bridge.ts` | File browser IPC wrapper (list_directory_children, read_file_content) | +| `v2/src/lib/adapters/memory-adapter.ts` | Pluggable memory adapter interface (MemoryAdapter, registry) | | `v2/src/lib/adapters/telemetry-bridge.ts` | Frontend telemetry bridge (routes events to Rust tracing via IPC) | | `docker/tempo/` | Docker compose: Tempo + Grafana for trace visualization (port 9715) | | `v2/src/lib/stores/machines.svelte.ts` | Remote machine state store (Svelte 5 runes) | @@ -75,7 +77,7 @@ Terminal emulator with SSH and Claude Code session management. v1 (GTK3+VTE Pyth | `v2/src/lib/components/Context/ContextPane.svelte` | ctx database viewer (projects, entries, search) | | `v2/src/lib/components/StatusBar/StatusBar.svelte` | Global status bar (group name, project count, agent count, cost) | | `v2/src/lib/components/Notifications/ToastContainer.svelte` | Toast notification display | -| `v2/src/lib/components/Workspace/` | v3 components: GlobalTabBar, ProjectGrid, ProjectBox, ProjectHeader, ClaudeSession, TeamAgentsPanel, AgentCard, TerminalTabs, ProjectFiles, CommandPalette, DocsTab, SettingsTab | +| `v2/src/lib/components/Workspace/` | v3 components: GlobalTabBar, ProjectGrid, ProjectBox, ProjectHeader, ClaudeSession, TeamAgentsPanel, AgentCard, TerminalTabs, ProjectFiles, FilesTab, SshTab, MemoriesTab, CommandPalette, DocsTab, SettingsTab | | `v2/src/lib/types/groups.ts` | TypeScript interfaces (ProjectConfig, GroupConfig, GroupsFile) | | `v2/src/lib/adapters/session-bridge.ts` | Session/layout/group persistence IPC wrapper | | `v2/src/lib/components/Markdown/MarkdownPane.svelte` | Markdown file viewer (marked.js + shiki, live reload) | diff --git a/TODO.md b/TODO.md index 09a7065..08cad81 100644 --- a/TODO.md +++ b/TODO.md @@ -3,6 +3,9 @@ ## Active ### v2/v3 Remaining +- [ ] **Register Memora adapter** -- MemoryAdapter interface exists but no concrete adapter registered at app init. Need to create a MemoraAdapter that bridges to Memora MCP/CLI and register it on startup. +- [ ] **Files tab PDF viewer** -- FilesTab marks PDFs as Binary. Add pdfjs-dist Canvas 2D rendering for inline PDF viewing. +- [ ] **Files tab CSV table view** -- CSV files render as plain text. Add structured table rendering with column headers. - [ ] **E2E testing — expand coverage** -- 48 tests passing across 8 describe blocks (WebdriverIO v9.24 + tauri-driver, single spec file, ~23s). Add tests for agent sessions, terminal interaction. - [ ] **Multi-machine real-world testing** -- Test bterminal-relay with 2 machines. - [ ] **Multi-machine TLS/certificate pinning** -- TLS support for bterminal-relay + certificate pinning in RemoteManager. @@ -10,6 +13,7 @@ ## Completed +- [x] **Tab system overhaul** -- Renamed Claude→Model, Files→Docs. Added Files (VSCode-style tree+viewer), SSH (CRUD+launch), Memory (pluggable adapter) tabs. PERSISTED-EAGER/LAZY mount strategies. Rust list_directory_children + read_file_content commands. | Done: 2026-03-10 - [x] **AgentPane collapsibles + aspect ratio** -- Text messages collapsible (open by default), cost summary collapsed by default. Project max aspect ratio setting (0.3–3.0, default 1.0) with CSS var + SettingsTab stepper. No-implicit-push rule 52. Desktop StartupWMClass. | Done: 2026-03-09 - [x] **AgentPane + MarkdownPane UI redesign** -- AgentPane: sans-serif font, tool call/result pairing via $derived.by, hook message collapsing, context meter, muted colors via color-mix(), responsive margins via container queries. MarkdownPane: container query wrapper, shared responsive padding variable. Tribunal-elected design (S-3-R4, 88% confidence). 139/139 tests pass. | Done: 2026-03-09 - [x] **E2E testing — consolidated & expanded** -- Consolidated 4 spec files into single bterminal.test.ts (Tauri single-session requirement). 25 tests across 4 describe blocks: Smoke(6), Workspace(8), Settings(6), Keyboard(5). Fixed WebDriver clicks on Svelte components via browser.execute(), removed tauri-plugin-log (redundant with telemetry::init()). | Done: 2026-03-08 diff --git a/docs/v3-progress.md b/docs/v3-progress.md index fb92aca..420b01c 100644 --- a/docs/v3-progress.md +++ b/docs/v3-progress.md @@ -446,3 +446,32 @@ All editor themes map to the same `--ctp-*` CSS custom property names (26 vars). - [x] Fixed keyboard focus: `browser.execute(() => document.body.focus())` before sending shortcuts - [x] Removed old individual spec files (smoke.test.ts, keyboard.test.ts, settings.test.ts, workspace.test.ts) - [x] All 25 E2E tests pass (9s runtime after build) + +### Session: 2026-03-10 — Tab System Overhaul + +#### Tab Renames + New Tabs +- [x] Renamed Claude → Model, Files → Docs in ProjectBox +- [x] Added 3 new tabs: Files (directory browser), SSH (connection manager), Memory (knowledge explorer) +- [x] Implemented PERSISTED-EAGER (Model/Docs/Context — display:flex/none) vs PERSISTED-LAZY (Files/SSH/Memory — {#if everActivated} + display:flex/none) mount strategy +- [x] Tab type union: 'model' | 'docs' | 'context' | 'files' | 'ssh' | 'memories' + +#### Files Tab (FilesTab.svelte) +- [x] VSCode-style tree sidebar (14rem) + content viewer +- [x] Rust list_directory_children command: lazy expansion, hidden files skipped, dirs-first sort +- [x] Rust read_file_content command: FileContent tagged union (Text/Binary/TooLarge), 10MB gate, 30+ language mappings +- [x] Frontend files-bridge.ts adapter (DirEntry, FileContent types) +- [x] Shiki syntax highlighting for code files, image display via convertFileSrc, emoji file icons + +#### SSH Tab (SshTab.svelte) +- [x] CRUD panel for SSH connections using existing ssh-bridge.ts/SshSession model +- [x] Launch button spawns terminal tab in Model tab's TerminalTabs section via addTerminalTab() + +#### Memory Tab (MemoriesTab.svelte) +- [x] Pluggable MemoryAdapter interface (memory-adapter.ts): name, available, list(), search(), get() +- [x] Adapter registry: registerMemoryAdapter(), getDefaultAdapter(), getAvailableAdapters() +- [x] UI: search bar, tag display, expandable cards, adapter switcher, placeholder when no adapter + +#### Verification +- [x] svelte-check: 0 new errors +- [x] vitest: 139/139 tests pass +- [x] cargo check: compiles cleanly