345 files changed | +39,873 / -17,225
Migrates the entire frontend to SpaceUI, Spacedrive's component library. The local UI primitives (~25 components, ~3000 lines) are gone — replaced by @spacedrive/primitives, @spacedrive/ai, @spacedrive/forms, and @spacedrive/explorer. Tailwind v3 is out, Tailwind v4 via @tailwindcss/vite is in, with SpaceUI's design token system and theme imports.
But this isn't just a component swap. The interface has been restructured from the ground up.
The old flat nav is replaced with a persistent sidebar (220px, Spacedrive-style) with labeled sections, accordion agent sub-nav, and a global workers popover in the footer. The org chart has its own dedicated tab instead of being crammed into the main view.
A new Dashboard serves as the landing page with real data wired to action items (notifications), token usage, and recent activity cards.
Every major view was decomposed from monolithic files into modular components:
- Settings — 2900-line monolith → 12 section components
- AgentConfig — 1452-line monolith → ConfigSidebar, section editors, shared types
- TopologyGraph — 2074-line monolith → OrgGraph, ProfileNode, GroupNode, edge/config panels, graph builder
- Workbench — rewritten with modular WorkbenchSidebar, WorkerColumn, and OpenCode theme inheriting CSS custom properties
Tasks got the biggest conceptual change — the kanban board is gone, replaced with a Linear-style task list with detail views, GitHub metadata badges, and SSE-driven updates.
Wiki — full implementation from scratch. SQLite-backed (wiki_pages + wiki_page_versions), tolerant multi-pass edit matching, 6 tools (create/edit/read/list/search/history), REST API, frontend route with page browser and wiki-link navigation.
Notifications — SQLite store, API endpoints, SSE real-time broadcasting, useNotifications hook with optimistic dismiss, wired into the dashboard's action items card. Task approval and worker failure notifications emitted automatically.
Portal — webchat renamed to portal throughout. Modular PortalPanel/Timeline/Composer/Header replacing the monolithic WebChatPanel. File attachments with multipart upload, drag-and-drop, and timeline rendering. Conversation persistence with full CRUD.
Streaming — prompt_once_streaming on SpacebotHook with token-by-token WorkerText deltas. OpenAI Responses API SSE streaming (~636 lines) supporting function call deltas, text deltas, reasoning summaries.
Built-in skills — compiled into the binary via include_str!, starting with a wiki-writing skill.
Projects elevated from per-agent to instance level — migration with full dedup logic, dropped agent_id from the projects table, updated all store/API/tool paths. Auto logo detection scanning .github/, public/, src-tauri/.
Conversation settings — ConversationSettings struct with memory mode, delegation, worker context, model selection. Per-channel persistence via ChannelSettingsStore with resolution chain (per-channel DB > binding defaults > agent defaults). ModelOverrides threaded through Channel, Branch, Worker, Compactor. Settings hot-reload via ProcessEvent::SettingsUpdated.
Channel settings unification — ResponseMode enum (Active/Observe/MentionOnly) replacing the old listen_only_mode system. Per-channel persistence, [bindings.settings] TOML support, slash commands that persist to DB. MentionOnly fixed to retain context and capture memories even when not responding.
Direct mode — channels can now get full worker-level tools (shell, file, browser, wiki, web search, memory) with tool calls rendered in the portal timeline.
Tool-use enforcement — configurable per-model prompt injection ("you MUST use tools") across all process types.
Token usage tracking — token_usage table with UsageAccumulator flushed per-process, wired to the dashboard chart.
Added: conversation-settings, wiki, token-usage-tracking, cron-outcome-delivery, skill-authoring, worker-briefing, attachment-portal-and-defaults, slash-commands, autonomy, goals. Some implemented, others queued.
14 merge commits omitted — no code changes.
Reformatted Sidebar imports to multi-line, renamed task approval notifications from "Approval"/"Approve" to "Review" with Clock icon, unified cron job button variants to "gray", fixed workbench EmptyState centering.
Deleted the 474-line autonomy-loop.md design doc. Minor Tauri-to-desktop platform abstraction renames (IS_TAURI → IS_DESKTOP).
Rewrote apply_history_after_turn to extract chat_history from PromptCancelled and MaxTurnsError variants instead of the external history param (which Rig doesn't update on error). Flushes accumulated tool calls into chat_history before returning PromptCancelled in SpacebotHook.
New ApprovalModal component — full dialog for task approval notifications with task detail view, approve/dismiss actions, and query invalidation. Replaced the inline action button in ActionItemsCard.
Added CONTRIBUTING.md, switched @spacedrive/* deps from link: to ^0.2.0 (npm published with local bun link override), added just spaceui-link / just spaceui-unlink commands.
Abstracted Tauri into a generic desktop host layer (IS_DESKTOP, hasBundledServer, spawnBundledProcess). Added active-project highlighting in sidebar, pinned "main" agent first, added macOS traffic-light padding, added stubs for cortex_chat and new tool registration.
Built-in skills system (compiled via include_str!, wiki-writing skill). Added company_name to global settings with InstanceSection page. Implemented "direct mode" for channels giving them full worker-level tools (shell, file, browser, wiki, web search, memory). Added tool_call_run timeline items to portal view. Company name switcher popover in sidebar. Ingest section in agent config. Browser tool structs made pub(crate).
Cosmetic Rust formatting only — line-break adjustments in usage.rs, wiki.rs, model.rs, pricing.rs, set_outcome.rs. No functional changes.
Workers panel refactor: added cancel button with channel_id tracking, extracted channel_dispatch.rs from channel.rs, added retrigger prompt fragment, improved wiki store error handling, switched hardcoded hex colors to semantic tokens (text-status-success, etc.).
Wired wiki tools into branches, workers, and channel dispatch. Added wiki_enabled flag to branch/worker prompt templates, wiki_write: bool to WorkerContextMode, propagated wiki store through all process spawn paths.
Full wiki system: SQLite migration (wiki_pages, wiki_page_versions), WikiStore with tolerant multi-pass text matching for edits, 6 wiki tools (create/edit/read/list/search/history), REST API endpoints, frontend Wiki route with page browser/viewer/create form and wiki-link navigation, TypeScript types.
Wiki design document (398 lines — page types, storage schema, tolerant edit matching, tool definitions, versioning, link syntax, agent access patterns, implementation phases). Added sidebar nav for Wiki, wired RecentActivityCard to real task data, added .db* to gitignore.
13. 5cd0398 — "cron outcome delivery rewrite, token usage tracking, dashboard UI, task notifications" +1,968 / -309
Replaced CronReplyBuffer with set_outcome() tool for clean cron delivery. Token usage tracking with new migration/table and UsageAccumulator. Connected TokenUsageCard to real API data. Rewired dashboard cards to SpaceUI primitives. WorkersPanel modal → inline slide-over. Wired ApiState through AgentDeps for task notification emission. Added token-usage-tracking and slash-commands design docs.
Wall-clock cron expression support alongside legacy interval mode. OpenAI Responses API SSE streaming in the LLM layer. Created set_outcome tool and prompt. Token-usage-tracking design doc. README rewrite. Dashboard cards switched to dark variant.
Redesigned ChannelCard from list-style to square aspect-ratio with fade-masked message stream. Replaced inline WorkerBadge/BranchBadge with compact pills. Added PlatformIcon, CircleButton, typing indicator, auto-scroll on send to PortalTimeline.
Complete README rewrite. 6 design docs (autonomy, goals, cron-outcome-delivery, skill-authoring, worker-briefing, attachment-portal-and-defaults). File attachment support for portal chat (multipart upload API, drag-and-drop composer, attachment rendering in timeline, metadata in conversation history).
Global WorkersPanel as a sidebar footer popover with search, history/interactive tabs, per-agent worker queries, live SSE integration, modal detail view. Added PortalHeader component.
Full notification system: SQLite migration, NotificationStore with CRUD/filtering, API endpoints, SSE real-time broadcasting, useNotifications hook with optimistic dismiss, wired ActionItemsCard to real data, cortex observation notifications on worker failure, task approval notification emission.
Dashboard route with four cards (ActionItemsCard, TokenUsageCard, RecentActivityCard, GetSpacedriveCard). Extracted AgentSkills into modular components (SkillsSidebar, SkillsDirectory, SkillInspector, BundledSkills, InstalledSkillRow, RegistrySkillRow).
Decomposed monolithic 1452-line AgentConfig.tsx into modular components: ConfigSidebar, ConfigSectionEditor (routing, tuning, compaction, cortex, coalesce, memory, browser, sandbox, projects), GeneralEditor, IdentityEditor, SaveBar, shared types/constants/utils. Added Config sub-item to sidebar agent nav.
Decomposed monolithic 2900-line Settings page into 12 section components (ApiKeysSection, AppearanceSection, ChangelogSection, ChannelsSection, ChatGptOAuthDialog, ConfigFileSection, OpenCodeSection, ProviderCard, SecretsSection, ServerSection, UpdatesSection, WorkerLogsSection). Replaced ReactFlow Controls in OrgGraph with custom zoom buttons.
Rewrote Workbench into modular components (WorkbenchSidebar, WorkerColumn, EmptyState, utils). Replaced hardcoded hex colors in OpenCode embed theme with CSS custom property references (var(--color-*)) for theme inheritance.
Renamed Orchestrate → Workbench (route + sidebar). Fixed OpenCode proxy path prefix stripping. Fixed worker list to resolve project names from global ProjectStore. Added @layer opencode-portals CSS to prevent style conflicts.
Decomposed 2074-line TopologyGraph.tsx into modular Org Chart components: OrgGraph, OrgGraphInner, ProfileNode, GroupNode, LinkEdge, EdgeConfigPanel, GroupConfigPanel, AgentEditDialog, HumanEditDialog, buildGraph, constants, handles, storage utils.
Foundational SpaceUI component integration across 32 files: converted all UI from inline Tailwind/raw HTML to @spacedrive/primitives (Button, Input, Dialog, Badge, Switch, Select, etc.). Replaced hardcoded color classes with semantic design tokens. Added new TopBar component.
Replaced monolithic WebChatPanel and TopBar with modular Portal system (PortalPanel, PortalTimeline, PortalComposer, PortalHeader, PortalHistoryPopover, PortalActiveWorkers). Added AgentProjects route. Migrated projects from per-agent SQLite DBs to shared instance DB with full dedup migration logic.
Rewrote task management: deleted 868-line TaskBoard (kanban) and replaced with Linear-style TaskList/TaskDetail/TaskCreateForm. Added GitHub metadata badges (issues/PRs) via TaskUtils.tsx. Rebuilt GlobalTasks with full task CRUD and SSE-driven updates.
Pure package rename across all imports and config: @spaceui/* → @spacedrive/* in package.json, vite.config.ts, styles.css, bun.lock.
Three changes: (1) Sidebar redesign to Spacedrive style — 220px, labeled nav items, section headers, accordion agent sub-nav. (2) Projects made global by dropping agent_id from projects table + all Rust store/API/tool updates. (3) Auto project logo detection scanning .github/, public/, src-tauri/ with new GET /projects/{id}/logo endpoint.
Removed the Channel Behaviour tab from agent config — per-channel response modes in channel settings replaced it.
Renamed Quiet response mode to Observe across full stack (Rust enums with serde alias, TS types, UI labels, docs). Observe = agent learns from context and captures memories but never responds.
New getting-started doc covering per-channel settings: response modes, model overrides, memory modes, delegation, worker context, slash commands. Added Channel Settings section to core channels doc.
Updated two helper text strings to mention commands (not just mentions/replies) trigger responses in MentionOnly mode.
Compaction check after injecting suppressed MentionOnly messages. Drops history write lock before async calls. Wraps checkbox inputs in <label> for accessibility.
Fixed MentionOnly to inject suppressed messages into in-memory LLM context and run passive memory capture, so the agent stays aware even when not responding. Added UI descriptions for the behavioral difference between binding-level and channel-level mention filtering.
Version bump 0.4.0 → 0.4.1 with CHANGELOG entry.
Deleted the one-off route audit script added in eba3c4a.
Single CSS change: PromptInspectModal width → 80vw.
Fixed 9 frontend API route paths broken during OpenAPI migration. Added audit-routes.sh script used to discover them.
Fixed ChatGPT OAuth routes and raw config editor route paths.
The foundational SpaceUI commit. Deleted the entire local UI component library (~25 files, ~3000 lines) and replaced all imports with SpaceUI packages. Added Vite aliases for local monorepo HMR. Replaced PostCSS/Tailwind v3 with Tailwind v4 via @tailwindcss/vite. Created new styles.css with SpaceUI design tokens. Extracted API client into packages/api-client.
One-line API client fix for the ingest upload path.
Dockerfile fix: touch stub for openapi-spec binary during dependency cache layer.
Version bump to 0.4.0 with CHANGELOG entry.
Per-channel cap of 64 messages on deferred injection queue, avoids unnecessary cloning on send errors, re-queues inbound message on delivery failure.
Fixed cron output leaking across agents sharing a conversation. Re-keyed active_channels HashMap with compound ActiveChannelKey(agent_id, conversation_id). Added deferred injection queue for cross-agent message buffering.
Three clippy fixes in Azure provider code: ok_or → ok_or_else, collapsed nested ifs, removed unnecessary format!.
Pure formatting on Azure provider code.
HTTPS validation for Azure endpoints, fixed Azure form validation in Settings UI, normalized trailing slashes, JSON errors instead of raw status codes.
Formatting fix on channel_dispatch.rs and config/types.rs.
Removed frontend validation blocking Azure save with empty API key.
Removed frontend validation blocking Azure test with empty key (backend uses stored key).
Backend reads stored Azure API key from config.toml when request has empty key, instead of rejecting.
Removed !keyInput.trim() from disabled conditions on Test/Save buttons, added Azure-specific validation.
Fixed update_azure_provider to construct full azure/{deployment} string before validation.
Removed api_key from ProviderConfigResponse, preserves stored key on empty update, azure/{deployment} routing format, AbortController for stale config fetches, trailing slash strip.
Initial Azure OpenAI implementation: backend handler with validation (endpoint, API version, deployment regex), frontend config UI (base URL, API version, deployment), model routing in LLM layer, docs.
Added failure_class parameter to emit_cron_error() distinguishing execution vs delivery failures. Formatting fixes.
CronRunError enum with Execution/Delivery variants. set_job_enabled_state() helper. Delivery failures now properly feed the circuit breaker. Unit tests.
Pure formatting on cron integration tests.
Returns Ok(()) after delivery failure so consecutive_failures isn't incremented when execution succeeded. Reordered enable/disable lock logic.
4 integration tests for claim_and_advance atomicity: concurrent claim races, duplicate rejection, run-once behavior, stale cursor detection.
5-second backoff after claim error, restores previous job on cursor failure, rejects interval_secs == 0 without cron_expr, fixed cold re-enable sequence.
SAFETY doc comment on ExecutionGuard::drop atomic ordering. Centralized emit_cron_error() helper replacing inline error emission.
Added cron_id to CronExecutionEntry, separated execution-only metrics from delivery, structured error fields with 5s backoff on stale cursor, explicit match arms replacing silent let _ on channel errors.
Docs clarifying at-most-once run-once semantics. claim_and_advance/advance_cursor on CronStore. broadcast_proactive on MessagingManager with bounded retry/backoff. Refactored sandbox detection exports. Cron delivery metrics.
Persistent next_run_at cursor with migration. Claim-before-run scheduling preventing double-firing across restarts. Separate execution/delivery outcome tracking with new migration columns. broadcast_proactive with retry/backoff. src/messaging/traits.rs with delivery target parsing. Cron UI showing split execution/delivery status. Run-once with at-most-once claiming.
Compile-time test verifying Sandbox, SandboxConfig, and detect_backend public API exports.
Added pub fn workspace(&self) -> &Path to Sandbox. Compile-time tests for ShellTool/Sandbox public exports.
70. 85783e0 — "feat(sandbox): implement backend detection for bubblewrap and sandbox-exec" +140 / -27
SandboxBackend enum (Bubblewrap/SandboxExec/None) and detect_backend() probing bwrap on Linux and sandbox-exec on macOS. Renamed internal enum to InternalBackend. Integration tests.
Unit tests for SandboxConfig::default() and SandboxMode variants.
Skips enforcement for compactor (no tools). Moves enforcement after skills rendering. Adds enforcement to resumed idle workers and coalesced-turn prompt. Cortex clones base prompt for fallback. Ingestion returns error on missing memory_persistence_complete. Bare TOML boolean support in deserialization.
Tab-based indentation rewrite of ConversationsSidebar.tsx. Active highlight → bg-app-hover text-ink, hover → bg-app-hover/50. Inline button → <Button variant="outline">. User message bubble → bg-app-hover/30.
User message bubble → bg-accent/15. Empty-state text shows agentDisplayName instead of raw ID.
Queries agents list to look up display_name, renders it in portal chat header.
Avoids unnecessary string allocation in portal conversation and channel settings store lookups.
Five clippy fixes: too_many_arguments allow on Branch::new, collapsed identical if/else, let-chains for nested if-let, flattened nested match, or_default().
Removed leftover settings: None from test initializers, added missing fields to context_dump tests.
Dependency bump pulling in updated signal-hook, rand, chacha20. Motivated by intermittent Slack HTTP client failures.
Added settings: None to every Binding struct in test cases after the field was added.
ChannelCard resets settings from DB on reopen, invalidates channels query on save. WebChatPanel hydrates from cached data on switch. reload_settings preserves existing on DB errors. set_response_mode uses tokio::spawn for non-blocking writes. Config loader warns on unknown enum values instead of silent default.
/status shows resolved model overrides. ChannelCard waits for settings data before rendering. parse_response_mode maps listen_only_mode=false → Active. Binding settings only override when explicitly set in TOML. Idle worker resume loads from ChannelSettingsStore. Batched turn skips memory when MemoryMode is Off. Channel settings API validates channel existence.
Added max-h-[80vh], overflow-y-auto, collisionPadding={16} to settings popover.
Added manual setShowSettings toggle because stopPropagation was blocking Radix's PopoverTrigger click.
ProcessEvent::SettingsUpdated variant with reload_settings() method. Channels API includes response_mode and model from live state. Frontend shows response mode badges on ChannelCard and portal header with current model name.
Deleted entire listen_only_mode/listen_only_session_override system, sync_listen_only_mode_from_runtime(), set_listen_only_mode(), RuntimeConfig fields, SettingsStore methods. Replaced with is_suppressed() checking resolved_settings.response_mode.
87. 9e5b802 — "feat: channel settings unification — ResponseMode, per-channel persistence" +903 / -72
ResponseMode enum (Active/Quiet/MentionOnly), save_attachments on ConversationSettings. channel_settings SQLite table + migration + ChannelSettingsStore. GET/PUT /channels/{channel_id}/settings API. Settings resolution: per-channel DB > binding defaults > agent defaults. [bindings.settings] TOML support. /quiet, /active, /mention-only slash commands persist to DB. ChannelCard gear icon + settings popover.
Visual overhaul of ConversationSettingsPanel: readable multi-line preset definitions, contextual description text per setting, new SettingField component, widened popover to w-96, reformatted advanced section.
89. 5a77c00 — "feat: finish conversation settings — load from DB, model overrides, worker memory tools" +561 / -242
Loads ConversationSettings from PortalConversationStore at channel creation. ModelOverrides struct threaded through Channel, Branch, Worker, Compactor. Worker memory tools wired to WorkerMemoryMode. Memory persistence guard for Ambient/Off. Dynamic available models from models.dev catalog. Frontend Apply Settings button + per-process model override selects.
tool_use_enforcement config section with per-model pattern matching. Appends "you MUST use tools" prompt fragment to system prompts across all process types. Jinja2 template + maybe_append_tool_use_enforcement on prompt engine.
Foundational conversation settings: renamed webchat → portal throughout (API routes, stores, hooks). ConversationSettings struct (memory mode, delegation, worker context, model selection). ResolvedConversationSettings with resolution logic. ConversationSettingsPanel + ConversationsSidebar with conversation CRUD. Portal conversation API endpoints with settings persistence. DB migration. WorkerContextSettings threaded through dispatch/spawning. /portal/defaults endpoint.
Conversation settings design document (1056 lines). Also includes desktop Tauri lockfile/schema changes (global-hotkey, gethostname crates).
prompt_once_streaming on SpacebotHook using StreamingCompletion for token-by-token responses with ProcessEvent::WorkerText deltas. ~636 lines of OpenAI Responses API streaming logic in model.rs (function call deltas, text deltas, reasoning summary deltas, response completion). Channel now calls prompt_once_streaming.
SQLite-backed webchat conversation persistence (webchat_conversations table + migration + WebChatConversationStore with full CRUD). New @spacebot/api-client npm package with typed client, SSE helpers, and re-exported schema types. Expanded OpenAPI schema types.