40 KiB
Roadmap — Chat Switchboard
See also:
- ARCHITECTURE.md — Core services design, store layer, scope model
- EXTENSIONS.md — Extension system spec (Browser/Starlark/Sidecar tiers, manifests, browser tool bridge, surfaces/modes, model roles)
- CHANGELOG.md — Detailed release notes for all completed versions
Versioning (pre-1.0): 0.<major>.<minor> — hotfixes use quad: 0.x.y.z
No compatibility guarantees before 1.0.
Dependency Graph
Features have real dependencies. This ordering respects them.
v0.9.x Stability + Quick UX Wins ✅
│
v0.9.3 Content Visibility & Block Controls ✅
│
v0.9.4 API Key Encryption + Vault ✅
│
v0.10.0 Model Roles (utility + embedding) ✅
+ Usage Tracking
│
v0.10.2 Summarize & Continue ✅
│
v0.10.3 Frontend Refactor ✅
│
v0.10.4 Model Type Pipeline + Role Fixes ✅
│
v0.10.5 UI Primitives + Extension Surfaces ✅
│
v0.11.0 Extension Foundation (browser tier) ✅
│
┌───────┴──────────────┐
│ │
v0.12.0 File Handling v0.13.0 Admin Panel
+ Vision ✅ Refactor (fullscreen) ✅
│ │
│ v0.13.1 Web Search
│ + url_fetch ✅
│ │
└───────┬──────────────┘
│
v0.14.0 Knowledge Bases ✅ (embedding role + file storage + pgvector)
│
v0.15.0 Compaction ✅ (utility role + background job)
│
v0.15.1 Context Recall Tools ✅ (attachment_recall, conversation_search)
│
┌───────┴──────────────┐
│ │
v0.16.0 User Groups v0.17.0 Persona-KB Binding
+ Resource Grants ✅ + Enterprise KB Mode
│ + QOL / UX Wins
└───────┬──────────────┘
│
┌───────┴──────────────┐
│ │
v0.17.1 SQLite Backend ✅ v0.17.2 CodeMirror 6 ✅
v0.17.3 Notes Graph + Wikilinks ✅
(dual DB) (editor bundle, chat
│ input, ext editor)
└───────┬──────────────┘
│
v0.18.0 Memory ✅ (user + persona scopes, review pipeline)
│
v0.18.1 Side Panel Architecture ✅ (single-slot, ctx.ui primitives, mermaid refactor)
│
v0.19.0 Projects / Workspaces ✅ (project groups, KB resolution, drag-drop sidebar)
│
v0.20.0 Notifications + @mention Routing + Multi-model
│
v0.21.0 Extension Surfaces + Modes (depends on CM6 from v0.17.2)
│
v0.22.0 Smart Routing + Provider Extensions
│
v0.23.0 Multi-Participant Channels + Presence
│
v0.24.0 Auth Strategy (mTLS/OIDC) + Full RBAC + Group permissions
│
┌───────┴──────────────┐
│ │
v0.25.0 Workflow v0.26.0 Tasks /
Engine Autonomous Agents
(team-owned, (service channels,
staged processes, scheduler, unattended
human + AI collab) execution)
Completed Releases
Full details for all completed versions are in CHANGELOG.md.
✅ v0.9.0 — Schema Consolidation + BYOK
21 migrations → single schema, store layer abstraction, persona-as-trust-boundary, BYOK with auto-fetch, composite model IDs, journey integration tests.
✅ v0.9.1 — Capability Architecture + Docs
Removed static known model table. Resolution chain: catalog → heuristic only. Frontend relies solely on backend for capabilities. Docs rewrite.
✅ v0.9.2 — Quick UX Wins + Hardening
Collapsible code blocks, HTML preview, token counter, context warning, proxy interception detection, environment injection, team admin audit scoping.
✅ v0.9.3 — Content Visibility & Block Controls
Button-driven code collapse, always-rendered thinking blocks, tool call
persistence in history, Notes panel → unified side panel, streaming refactor
(streamWithToolLoop), regenerate fix.
✅ v0.9.4 — API Key Encryption + Vault
Two-tier AES-256-GCM: env-var key for global/team, per-user UEK (Argon2id)
for personal BYOK. server/crypto/ package. Migration 003. Startup backfill.
DOMPurify strict allowlist (XSS fix).
✅ v0.10.0 — Model Roles + Usage Tracking + Vault Debt
Named role slots (utility, embedding) with fallback. Provider.Embed() interface.
usage_log + model_pricing tables. Streaming token capture. Vault debt:
UEK re-wrap on password change, destruction on admin reset.
✅ v0.10.1 — Polish + UX
Admin system prompt injection, Personas tab, Team Management modal extraction, preview pane enhancements, code download, personal usage scoped to BYOK.
✅ v0.10.2 — Summarize & Continue + Role Cleanup
User-triggered conversation compaction via utility role. Summary as tree node with boundary metadata. BYOK role overrides (personal → team → global). Utility rate limiting. Generation role removed.
✅ v0.10.3 — Frontend Refactor
2 monolith files → 13 domain-scoped files (~544 lines avg). Zero features, no function renames. Vanilla JS, no build step. See REFACTOR-0.10.3.md.
✅ v0.10.4 — Model Type Pipeline + Role Fixes
model_type (chat/embedding/image) captured end-to-end from provider API
through catalog to frontend. Role dropdowns filter by type.
✅ v0.10.5 — UI Primitives + Extension Surfaces
Shared Providers/Roles registries, 6 consolidated render primitives,
showConfirm() replacing native dialogs, .popup-menu CSS primitive.
Removed ~400 lines of duplication.
✅ v0.11.0 — Extension Foundation (Browser Tier)
Full extension lifecycle: manifest, loader, scoped ctx.* API, browser tool
bridge via WebSocket. Custom renderer pipeline. 2 server tools (calculator,
datetime), 6 built-in browser extensions (Mermaid, KaTeX, CSV, Diff, JS
Sandbox, Regex). See EXTENSIONS.md.
✅ v0.12.0 — File Handling + Vision
S3/PVC storage backend, image/file upload (📎, drag-drop, paste), multimodal
message assembly, text extraction pipeline (PDF/DOCX/XLSX/PPTX/ODT/RTF),
vault CLI (rekey/status), per-chat model persistence.
✅ v0.13.0 — Admin Panel Refactor
12-tab modal → fullscreen admin panel. 4 categories (People, AI, System, Monitoring) × section sidebar. URL-based routing, responsive, banner-aware. CSS design token cleanup.
✅ v0.13.1 — Web Search + URL Fetch
web_search + url_fetch tools. Search provider abstraction (DuckDuckGo,
SearXNG). Tool categories with per-tool toggle UI in chat bar.
✅ v0.14.0 — Knowledge Bases
RAG: upload → chunk → embed (pgvector) → kb_search tool. Channel KB toggle.
Team/personal KB scopes. Notes semantic search. Admin panel KB management.
See DESIGN-0.14.0.md.
✅ v0.15.0 — Compaction
Background scanner with configurable thresholds. Automatic summarization via utility role. Per-channel opt-in/out. Context budget guard rail (80% ceiling).
✅ v0.15.1 — Context Recall Tools
attachment_recall (list + read, channel-scoped), conversation_search
(full-text via plainto_tsquery). Token estimator attachment awareness.
✅ v0.16.0 — User Groups + Resource Grants
Groups (global/team-scoped ACLs) decoupled from team membership. Three-way
resource grants (team_only/global/groups) for Personas and KBs. Grant picker
UI. Schema consolidation: 9 migrations → single 001_v016_schema.sql.
v0.17.0 — Persona-KB Binding + Enterprise KB Mode + QOL ✅
Personas become gateways to knowledge. In enterprise deployments, users don't interact with KBs directly — they talk to Personas that have KBs attached. Plus quality-of-life improvements: chat rename, token display, state persistence, utility model auto-naming.
Depends on: knowledge bases (v0.14.0), user groups (v0.16.0).
Persona-KB Binding
persona_knowledge_basestable:persona_id,kb_id,auto_search(bool — always search vs tool-only)- When a channel uses a Persona with bound KBs,
kb_searchis auto-scoped to those KBs - No user toggle needed — Persona carries its own KB context
- Channel KB toggle becomes "additional KBs" on top of Persona-provided ones
- Persona system prompt auto-includes KB listing hint (reuses
BuildKBHintpattern) - Admin/team admin UI: KB picker on Persona create/edit form
Enterprise KB Mode
discoverableflag on knowledge_bases:true(default — appears in user's KB popup) orfalse(hidden, only accessible through Persona binding)- Hidden KBs don't appear in
GET /api/v1/knowledge-bases-discoverablefor non-admins - Hidden KBs still searchable by
kb_searchtool when accessed through a Persona - Admin panel: toggle discoverability per KB
- Platform policy:
kb_direct_access— whenfalse, disables channel KB popup entirely (strict enterprise mode)
Access Control Integration
- Persona grants (v0.16.0 groups) control who can use a Persona
- KB grants control who can manage a KB (upload/delete docs)
- Persona-KB binding grants implicit search access through the Persona
- Users who can use a Persona can search its KBs, even if they can't see those KBs directly
Team Admin Workflow
- Team admin creates KB → uploads documents → marks non-discoverable
- Team admin creates Persona → binds KBs → sets access to Team Only or specific Groups
- Team members see the Persona in their preset list, use it, get KB-powered answers
- Team members never see or manage the underlying KBs
Technical Debt (carried forward)
- Security: KB create handler authorization — team/global scope verified
- Test hygiene: stripped DIAG diagnostics from
TestGroupBasedPersonaAccess - Architecture:
KnowledgeBaseStore.UpdateDocumentStorageKey()— moved to store layer - UX: Embedding dropdown fix — tolerant type filter, manual model ID fallback, auto-switch on empty (already implemented in
ui-primitives.js) - Minor: Paste-to-file character threshold — synced from backend
PublicSettings(storage.paste_to_file_chars), admin-configurable, default 2000
Role Fallback Alerts (#69)
- Audit log entry on fallback fire:
action = "role.fallback"with primary/fallback model IDs and error string role.fallbackWebSocket event via EventBus (PublishAsync, zero latency impact on completion path)- In-memory cooldown on
Resolver(per-role, 5-minute TTL) to deduplicate repeated fallback alerts - Admin UI: persistent alert banner on
role.fallbackevent (persists until dismissed) - Wire
*events.Busintoroles.NewResolvervia.WithBus()builder
QOL / UX Wins
- Chat rename: inline edit on sidebar item — dblclick title → input → blur/Enter saves via
API.updateChannel(id, { title }) - Chat token count: display
Tokens.estimateConversation()in model bar, update onselectChatand after each message - State restore on refresh: persist
App.currentChatIdtosessionStorageon select, restore on load - Utility model auto-naming: after first assistant response, background utility role request →
POST /channels/:id/generate-title→ re-render sidebar. Fallback to truncation when no utility model configured. Debounced via_autoNamePendingset - SW extension cache fix: exclude
/extensions/from service worker fetch handler - Mermaid renderer: promoted enhanced version (v2.0 — pan/zoom, SVG/PNG export, source copy) to
extensions/builtin/mermaid-renderer/
v0.17.1 — SQLite Backend ✅
Dual-database support. Every subsequent schema change is developed against both Postgres and SQLite from day one — no retrofit. SQLite enables single-binary deployment for dev, demo, edge, and single-user.
Depends on: v0.17.0 DB debt cleanup (store layer is sole DB interface).
Store Layer
- 19 SQLite store implementations covering all domain interfaces
DB_DRIVERenv var:postgres(default) |sqlite- Separate migration files per driver (
migrations/sqlite/) - WAL mode + single-writer connection pooling for SQLite concurrency
- CI matrix: full handler integration tests against both Postgres and SQLite
Vector Search
- App-level cosine similarity in Go (pure Go, no CGO/sqlite-vec required)
- Embeddings stored as JSON text in
kb_chunks.embeddingcolumn - Full feature parity with pgvector:
SimilaritySearch,InsertChunks - Graceful: adequate performance for SQLite-scale deployments (single-user, not millions of chunks)
Schema Compatibility
- UUID generation: application-side
store.NewID()(Gouuid.New()) - JSONB → JSON text columns with
ToJSON()/ScanJSON()helpers UUID[]arrays → JSON arrays withToJSONArray()/ScanJSONArray()TIMESTAMPTZ→ SQLiteTEXTwithdatetime('now')ON CONFLICT excluded.*pattern (works in both dialects)INSERT RETURNING id→ separate query pattern for SQLite
Test Infrastructure
dialectSQL()converts$N→?and strips::jsonbat runtimedatabase.PH(n)returns dialect-appropriate placeholderdatabase.TruncateAll()dialect-aware (DELETE + PRAGMA vs TRUNCATE CASCADE)- Generic provider config:
PROVIDER/PROVIDER_KEY/PROVIDER_URL(replacesVENICE_API_KEY) - Model selection prefers non-reasoning models in live tests
What SQLite mode skips (feature-gated, not broken):
LISTEN/NOTIFY— WebSocket event fan-out uses in-process EventBus (already works)- Full-text search
tsvector— conversation_search uses LIKE fallback
v0.17.2 — CodeMirror 6 Integration ✅
Rich editor infrastructure for the frontend. CM6 is ESM-native; the build
step runs in Docker (esbuild → single IIFE bundle). No change to dev
experience for non-editor code — the rest of src/js/ stays vanilla.
Depends on: nothing (frontend-only). Prerequisite for: extension surfaces (v0.21.0 editor mode). See DESIGN-CM6.md for full spec.
Build Pipeline
src/editor/directory:package.json,build.mjs,index.mjs, language/theme modulesscripts/build-editor.sh: shared build script for both Dockerfiles and local dev- New Docker stage (
cm6-build):npm ci+node build.mjs→vendor/codemirror/ - Both
Dockerfile.frontendandDockerfile(unified) use the shared build script - Bundle output:
codemirror.bundle.js(~295KB min, ~90KB gzip) - Graceful degradation: all integration points check
window.CM— falls back to<textarea>if bundle unavailable
Languages (bundled)
- Markdown, JavaScript, JSON, SQL, HTML, CSS, YAML, Go, Python, Rust
- Additional modes: one-line import + rebuild
Phase 1: Extension Editor (admin panel)
CM.codeEditor()factory: line numbers, bracket matching, auto-indent, search/replace- Replace manifest
<textarea>→ CM6 JSON mode - Replace script
<textarea>→ CM6 JavaScript mode - Remove manual Tab-key handler in
admin-handlers.js(CM6 handles it) - Update
saveAdminExtension()to use.getValue()
Phase 2: Chat Input (markdown mode)
CM.chatInput()factory: markdown highlighting, minimal chrome (no line numbers, no gutter)- Enter=send, Shift+Enter=newline keybindings
- Auto-growing height, placeholder text
- Wire
onChange→updateInputTokens() - Update
chat.js,attachments.js,tokens.jsto use CM API - WYSIWYG fenced code block decorations (visual container matching claude.ai UX)
- Inline code shortcut (Ctrl/Cmd+E)
Phase 3: Polish
- Theme integration: CSS variable overrides (
--bg,--border,--accent, etc.) - Dark/light/system mode toggle in appearance settings
- Vim/Emacs keybinding preference in appearance settings (
@replit/codemirror-vim,@replit/codemirror-emacs) - Vim/Emacs applies to code editor + extension editor only (never chat input)
- SW cache: exclude
vendor/codemirror/with version bust - Update
debug.jssnapshot to include CM6 version - Documentation in ARCHITECTURE.md
CI/CD
- Path-based change detection gating (FE-only → skip BE tests, docs-only → skip all)
v0.17.3 — Notes Graph + Wikilinks ✅
Knowledge graph and bi-directional linking for the notes system. Transforms
notes from flat documents into an interconnected knowledge base with
Obsidian-style [[wikilinks]], backlinks, graph visualization, and
transclusion.
Depends on: CodeMirror 6 (v0.17.2), Notes CRUD (v0.13.x). See DESIGN-0.17.3.md for full spec.
Backend: Note Links
note_linkstable (Postgres + SQLite migrations)NoteLinkStoreinterface + both implementationsExtractWikilinks()regex parser + tests- Link extraction on note create/update
- Dangling link resolution on note create
notes.source_message_idcolumn for chat-to-note provenance
API Endpoints
GET /notes/:id/backlinks— notes linking to this noteGET /notes/search-titles?q=— lightweight fuzzy search for autocompleteGET /notes/graph— full graph topology (nodes + edges + unresolved)
CM6 Note Editor
note-editor.mjsfactory: markdown live preview (heading sizes, blockquotes, code blocks)wikilink.mjsCM6 extension: parse, decorate as clickable chips, autocomplete on[[- Textarea → CM6 swap in
notes.jswith graceful fallback noteEditorThemeintheme.mjs
Graph Visualization
- Canvas-based force-directed graph (~200 lines, no d3 dependency)
- O(n²) Coulomb repulsion + Hooke spring + center gravity
- Pan, zoom (0.15–4.0x), drag nodes, hover highlight, click to open
- Node sizing by link_count, folder-based coloring
- Ghost nodes for unresolved
[[links]]with toggle - Energy-based pause (stop rAF below KE threshold)
- ResizeObserver for responsive canvas
Note-from-Selection + Daily Notes
- "Note" button in message action bar
- Selection-aware capture (
window.getSelection()within message) - Provenance tracking (
source_channel_id+source_message_id) - "Today" button → find-or-create daily note in
/daily/
Read Mode
[[link]]rendered as clickable wikilink chips![[embed]]transclusion with async content fetch, recursion guard- Backlinks panel (collapsible, with count badge)
v0.18.0 — Memory (User + Persona Scopes) ✅
Long-term memory across conversations, with scope-aware isolation. Unlike KB (static documents) or compaction (within-conversation), this captures facts and preferences that persist across channels.
Key differentiator: Persona-scoped memory. Each Persona can build its own memory independently of user memory, preventing cross-context contamination and enabling specialized knowledge accumulation.
Depends on: compaction (v0.15.0), knowledge bases (v0.14.0), persona-KB binding (v0.17.0), SQLite backend (v0.17.1).
See DESIGN-0.18.0.md for full spec.
Memory Scopes
user— personal facts/preferences, persists across all conversations (current industry standard)persona— shared across all users of that Persona, accumulated from conversations (differentiator)persona+user— per-user within a Persona context (e.g. tutoring progress per student)- Configurable per Persona: which scopes are active, whether user memory is passed through
Data Model
memoriestable:id,scope(user, persona, persona_user),owner_id(user_id or persona_id),user_id(nullable — for persona+user scope),key,value,source_channel_id,confidence(float),status(active, pending_review, archived),created_at,updated_at- Index on
(scope, owner_id, user_id)for fast lookup - Embedding column (
vector(3072)) for semantic memory search
Tools
memory_savetool: LLM explicitly stores a fact- Scope-aware: saves to the active memory scope for the current Persona context
- Structured:
key(short label) +value(detail) +confidence
memory_recalltool: LLM queries stored facts relevant to current context- Merges results from applicable scopes (user + persona + persona+user)
- Semantic search via embeddings + keyword fallback
Automatic Extraction
- Background job: post-conversation analysis identifies memorable facts (opt-in)
- Configurable extraction prompt per Persona (e.g. "extract FAQ-worthy Q&A pairs")
- Extracted memories start in
pending_reviewstatus
Review Pipeline
- Admin/team admin review queue: pending memories with approve/reject/edit
- Persona memory review: team admins see what Personas are "learning"
- User memory review: users see their own memories in Settings
Memory Injection
- At completion time: inject relevant memories into system prompt
- Context budget aware: limit injected memory tokens
- Scope priority: persona+user > persona > user (most specific wins on conflicts)
Use Cases
- Helpdesk Persona: builds FAQ from repeated questions, human-reviewable
- Roleplay Persona: isolated memory prevents tone/context bleeding from user's other conversations
- Tutoring Persona: tracks per-student progress, common misconceptions
- Sales Persona: accumulates objection responses from real conversations
- Onboarding Persona: learns what new hires commonly struggle with
User Controls
- Settings → Memory: view, edit, delete personal memories
- Per-Persona memory toggle: "Allow this persona to remember things about me"
- Admin: enable/disable, retention policies, per-team scoping
- Privacy: user memories never cross team boundaries; persona memories respect group access
v0.18.1 — Side Panel Architecture ✅
Refactored the side panel from a shared-tab layout to independent single-slot panels. Any action fills the slot, replacing whatever was there — no tabs, no association between panel types. Extension UI primitives give browser extensions safe access to host app features.
Depends on: Notes graph + wikilinks (v0.17.3). Prerequisite for: live collaboration (v0.23.0) where multiple panels need simultaneous visibility.
Panel System
- Panel registry: named panels with independent open/close state
- Single-slot model: action-driven, each open replaces the previous
- Dual-view mode: two panels side-by-side (configurable split ratio via drag divider)
- Panel-persistent state: each panel remembers scroll position, open note, etc.
- Header label shows active panel name (replaces tab bar)
- Keyboard shortcut: Ctrl/Cmd+\ cycles panels, Ctrl/Cmd+Shift+\ toggles dual
Preview Panel
- Dedicated preview panel (independent of Notes)
- HTML/document preview with iframe sandbox
- Code output preview (extension-rendered blocks via pop-out)
- Live-updating during streaming responses (500ms debounce)
Extension UI Primitives
ctx.ui.toast()— toast notificationsctx.ui.openPreview()— load HTML into side panel previewctx.ui.isDark()— theme detectionctx.ui.isMobile()— viewport width checkctx.ui.isPanelOpen()— side panel visibilityctx.ui.confirm()— modal confirm dialog- Mermaid extension refactored to use primitives exclusively (zero direct globals)
- Context-aware expand: single button, fullscreen or side panel pop-out
Mobile
- Swipe navigation between panels
- Tap-to-close overlay
- Graceful collapse to single-panel on narrow viewports
- Enlarged touch targets, fullscreen close button (40px desktop, 48px mobile)
✅ v0.19.0 — Projects / Workspaces
Organizational containers that group related conversations, KBs, and notes into a single workspace with shared access controls.
Depends on: user groups (v0.16.0), knowledge bases (v0.14.0).
Data Model
projectstable:id,name,description,color,icon,scope(personal/team/global),owner_id,team_id,is_archived,settings(JSONB)project_channelsjunction: ordered membership with UNIQUEchannel_id, denormalized FK onchannels.project_idproject_knowledge_basesjunction: withauto_searchflagproject_notesjunctionresource_grantsCHECK extended to include'project'
Features
- Channels can belong to a project (optional
project_idFK) - KBs can belong to a project → auto-linked to all channels in the project (BuildKBHint + kbsearch)
- Notes can belong to a project → auto-associated when created from project channel
- KB resolution chain: Persona → Project → Channel → Personal
- Project sidebar section: collapsible groups above time-based Recent section
UI
- Sidebar: projects as collapsible groups with color dots, counts, options menu
- Right-click context menu: move chat to project / remove / create-and-assign
- Drag-and-drop channels between project groups and Recent
- New Project button in split dropdown
- Channel list
project_idfilter (?project_id=uuidor?project_id=none) - Collapse state persisted in localStorage
Deferred to later versions:
- Project creation dialog (name, description, default Persona, default KBs) — using prompt() for now
- Project detail panel (KB + note management within a project)
- Project-level Persona default
- Folders within projects
- Project templates
- Admin-level team/global project management
- Notifications (moved to v0.20.0)
v0.20.0 — Notifications + @mention Routing + Multi-model
Notification infrastructure that makes collaboration real-time, plus the channel schema already supports multiple models — this adds routing.
(Notifications shifted from v0.19.0; @mention routing shifted from v0.17.0)
Notifications
notificationstable:id,user_id,type,title,body,resource_type,resource_id,is_read,created_at- In-app notification bell (header bar, unread count badge)
- Notification dropdown: grouped by type, mark read, click-to-navigate
- WebSocket push: real-time delivery via existing EventBus (
notification.newevent) - Notification sources: group membership changes, grant updates, KB processing complete, project invites, team invites
- Email transport (optional): SMTP config in admin settings, per-user opt-in/out
- Email templates: HTML + plaintext, branded with instance name
- Digest mode: batch low-priority notifications into periodic email (hourly/daily)
- Admin settings: enable/disable email, SMTP config, default notification preferences
- User preferences: per-type toggles (in-app, email, off)
@mention Routing
- @mention parsing in messages (users and AI models)
- Resolve mentions against
channel_models - Multi-model channels: fire completions per mentioned model
- "Add a model" UI per channel
- Enables: second opinions, cross-model conversations
v0.21.0 — Extension Surfaces + Modes
Depends on: extension foundation (v0.11.0), CodeMirror 6 (v0.17.2). See EXTENSIONS.md §6.
(Shifted from v0.18.0 — no content changes)
- Surface registration and activation API
- Mode selector in sidebar (below brand, above chat history)
ctx.ui.replace()/ctx.ui.restore()for region managementsurface.activated/surface.deactivatedevents- Editor mode (extension: file tree + CM6 code editor + AI chat split pane)
- Article mode (extension: outline + rich text + AI assistant panel)
- Document generation output storage: extension → attachment → download pipeline (prerequisite for editor/article output)
REPL / Debug Console (#70)
- Fourth tab in debug modal (Ctrl+Shift+L):
[ Console | Network | State | REPL ⚠ ] AsyncFunctionwrapper for top-levelawait— injectsAPI,Events,Extensions,DebugLogas globals- Pretty-print results: collapsible JSON (reuse State tab renderer), errors in red with stack
- Command history: ↑/↓ navigation,
sessionStorage(notlocalStorage— no stale credentials across sessions) - Tab-completion on live object graphs: walk
Object.getOwnPropertyNames+ prototype chain, own-first sort - Event label hints: secondary completion when typing
Events.publish('orEvents.on('— sourced from routeTable constants - Every executed command echoed as
REPL:EXECentry in Console tab (trace of what ran) - Toolbar: Clear (output only), Copy session (full transcript), Help (available globals guide)
- Multi-line input: Shift+Enter for newline, Enter to run
- Access gate: admin-role only (same
isAdmincheck as admin panel) OR?debug=1URL param - Nice-to-have: snippets library dropdown ("List channels", "Show current user", "Ping WebSocket", "List loaded extensions")
- Nice-to-have: method signature tooltip from
fn.toString()parsing on autocomplete selection - Files:
index.html(tab markup),debug.js(ReplRunner object),debug.css(output, input, suggestion dropdown)
v0.22.0 — Smart Routing + Provider Extensions
Depends on: model roles (v0.10.0), usage tracking (v0.10.0). Rules-based routing engine — policy, not ML. Plus declarative provider configuration to replace hardcoded provider-specific behavior.
(Shifted from v0.19.0 — routing content unchanged, provider extensions added)
Routing
- Admin routing policies: "cheapest model with required capabilities", "prefer private providers, fallback to cloud", "for team X, use Y"
- Fallback chains: primary provider down → next with same model
- Cost-aware: factor pricing into routing decisions
- Latency-aware: track response times per provider, prefer faster
Provider Extensions (declarative provider config)
provider_profilestable (or JSONB onapi_configs): per-provider configuration schema- System prompt injection: provider-specific preambles (e.g. Venice character system prompt)
- Thinking mode toggle: per-provider
thinkparameter support (Venicevenice_parameters.include_venice_system_prompt, Anthropicthinking, etc.) - Request transform hooks: provider-specific parameter mapping before API call
- Response transform hooks: normalize provider-specific response fields
- Admin UI: provider profile editor (key-value config per provider type)
- Preset-level overrides: Persona can override provider-specific settings (e.g. "always enable thinking for this Persona")
- Provider health: track error rates, latency percentiles, auto-disable unhealthy providers
- Search/URL fetch rate limiting per provider
- Capability admin/user override: manual correction for model capabilities (
intrinsic.goadmin override layer)
v0.23.0 — Multi-Participant Channels + Presence
The channel foundation for workflows and real-time collaboration. Today channels are single-user direct chats. This release makes channels a shared space that multiple actors can inhabit.
Depends on: extension surfaces (v0.21.0), WebSocket infrastructure (already exists).
(Shifted from v0.20.0 — no content changes)
Channel Participants
channel_participantstable:channel_id,participant_type(user, session, persona),participant_id,role(owner, member, observer),joined_at- Channel access queries rewritten:
WHERE user_id = $1→ participant-based lookup - Backward compatible: existing single-user channels auto-have one participant (owner)
- Channel
typecolumn:direct(current),group(multi-user),workflow(staged)
Presence + Real-time
- Typing indicators and presence (who's online, who's in this channel)
- Participant join/leave events via WebSocket
- Co-editing for extension surfaces (editor mode, article mode)
- Cursor sharing, selection highlighting
Channel-Scoped Notes
- Optional
channel_idFK on notes (NULL = personal notebook, set = channel-attached) - Notes created by tool calls within a channel auto-attach to that channel
- Channel notes visible to all participants (not just creator)
v0.24.0 — Auth Strategy (mTLS/OIDC) + Full RBAC
Enterprise auth modes on top of the teams + groups foundation. Depends on: vault passphrase support from v0.9.3 (conditional unlock for personal providers under external auth), user groups (v0.16.0).
(Shifted from v0.21.0 — enhanced with group-based permissions)
AUTH_MODEenv var:builtin|mtls|oidc- All three resolve to the same internal user model
auth_source+external_idcolumns on users table- mTLS: header trust, auto-provision from cert DN
- OIDC: Keycloak/Okta token validation, claim extraction, role mapping
- Per-source auto-activate policy: auto_activate, default_team, default_role
- Vault passphrase prompt for mTLS/OIDC users (v0.9.3 conditional unlock)
- Fine-grained permissions: model access, KB write, task create, token budgets
- Group-based permission sets: assign permissions to groups, users inherit from membership
- OIDC claim → group mapping: external IdP groups auto-sync to internal groups
Anonymous / Session Participants
- Session-based identity for unauthenticated visitors (workflow intake)
- mTLS: cert CN/fingerprint as stable session identity (no
usersrow required) - Non-mTLS: ephemeral session token (cookie or URL token)
- Session participants can send messages and trigger tool calls within workflow channels
- Session identity visible to assigned team members (cert DN, display name, or "Anonymous #N")
v0.25.0 — Workflow Engine
Team-owned, stage-based process execution. The channel is the runtime, personas drive each stage, and the existing tool/notes infrastructure handles structured data collection. See ARCHITECTURE.md — Workflow Architecture for the conceptual model.
Depends on: multi-participant channels (v0.23.0), anonymous identity (v0.24.0).
(Shifted from v0.22.0 — no content changes, dependency refs updated)
Workflow Definitions
workflowstable:team_id(owner),name,description,is_active,entry_mode(public_link, team_internal, api)workflow_stagestable:workflow_id,ordinal,persona_id,assignment_team_id,form_template(JSONB, structured note schema),transition_rules(JSONB)- Team-admin CRUD: create/edit/delete workflows and stages
- Workflow versioning: edits create new version, active instances continue on their version
Workflow Instances (Channels)
- Workflow-typed channels:
type='workflow',workflow_id,current_stage,stage_version - Entry point: public link generates workflow channel, adds anonymous participant, binds stage 1 persona
- Stage transitions: triggered by AI (tool call), team member (button), or rule (form complete)
- On transition: swap active persona, notify assignment team, update channel metadata
AI Intake
- Stage persona drives structured collection via system prompt
- Form template → persona system prompt injection ("collect these fields: ...")
- Tool calls create channel-scoped notes as form responses
- AI determines readiness: "I have everything needed" → trigger transition
Assignment + Queue
- Assignment queue: unassigned workflow channels visible to team members
- Claim model: team member claims channel (becomes participant with
memberrole) - Round-robin / rule-based auto-assignment (optional, per-stage config)
- Assignment notifications via WebSocket + optional webhook
Team Member Collaboration
- Assigned member sees full history (AI intake + artifacts + notes)
- Persona remains active — assists both visitor and team member
- Member can trigger stage transitions, add notes, invoke tools
- Member can reassign to different team member or escalate to different team
Frontend
- Workflow builder UI in team admin panel (stage list, persona picker, form template editor)
- Queue view: sidebar section showing unassigned workflow channels for user's teams
- Channel header: workflow stage indicator, transition controls
- Anonymous visitor view: minimal UI, persona-driven conversation (public link entry)
v0.26.0 — Tasks / Autonomous Agents
Unattended execution — workflows without a human in the loop. Depends on: workflow engine (v0.25.0).
(Shifted from v0.23.0 — no content changes, dependency refs updated)
- Scheduler + task runner (cron-like triggers for workflow instantiation)
task_createtool (AI can spawn sub-workflows)type: 'service'channels: workflow instances with no human participants- Execution budgets: max tokens, max tool calls, max wall-clock per stage
- Admin controls for resource limits and kill switches
- Completion webhooks (notify external systems when workflow completes)
TBD (unscheduled — real features, no immediate need)
Items that are real but don't yet have a version assignment. Pull left based on need.
Extension System — Additional Extensions
- Image generation tool (browser or sidecar, provider-agnostic)
- STT/TTS (browser extension, Web Speech API — personal use case)
- Code execution sandbox (server-side, container isolation)
Extension System — Server Tiers
- Starlark runtime integration (Tier 1 — server sandbox)
- Sidecar HTTP tool protocol (Tier 2 — container isolation)
- Server-side tool execution in completion handler
Desktop + Mobile
- Desktop app (Tauri)
- Full PWA with offline capability
- Mobile-optimized layouts (beyond current responsive)
Data + Portability
- Bulk export/import (account data, conversations, settings)
- ChatGPT/other tool import
- GDPR-style "download my data"
- Backup/restore CronJob manifests
UX / Multi-Seat
- "Group" scope badge on model selector / KB list: show access-source annotation so users see why they have access (global, team, group grant). Requires backend to include
access_sourcein list responses. - Per-provider model preferences:
user_model_settingsunique key is(user_id, model_id)— same model from different providers shares one visibility toggle. Needsprovider_config_iddimension in DB constraint, store, API, and frontendhiddenModelskeying. Frontend composite key (configId:modelId) already exists inApp.models[].id.
Knowledge Bases — Future
- KB auto-injection: top-K chunk prepend to system prompt, context budget aware, per-channel toggle (latency budgeting required)
- Hybrid search: combine vector similarity with full-text
tsvector, re-rank - Semantic chunking: embedding-based boundary detection for smarter splits
- HNSW index: better query performance than IVFFlat for large datasets
- Web scraping source: ingest URLs as KB documents (extends url_fetch)
- Scheduled re-indexing: periodic rebuild when source documents update
Store cleanup: add(done in v0.17.0) (currently uses directUpdateDocumentStorageKey()toKnowledgeBaseStoreinterfacedatabase.DB.ExecContextin handler — works but bypasses store layer)
Memory — Future
- Memory compaction: summarize old memories to save context tokens
- Memory confidence decay: reduce confidence over time, prune low-confidence entries
- Memory export/import: portable memory format across instances
- Cross-persona memory sharing (opt-in): e.g. "coding assistant" can read facts from "project manager"
- Memory analytics: dashboard showing what Personas are learning, memory growth trends
Platform
- Rate limiting per user/team/tier (token budgets)
Provider health monitoring→ v0.22.0 + key rotation- Multi-tenant SaaS mode
- Plugin/extension marketplace
- Virtual scroll for long conversations
SQLite backend option (single-user / dev)→ v0.17.1