summaryrefslogtreecommitdiffhomepage
path: root/packages
AgeCommit message (Collapse)Author
2026-05-21feat: system prompt editor, tool permissions save-on-send, responsive ↵Adam Malczewski
sidebar, UI polish - System Prompt sidebar view: editable textarea, save-on-send, reset button - Tool permissions: save-on-send pattern (not immediate), reset button - Dynamic system prompt: buildSystemPrompt reads from DB, tool list auto-generated - Responsive sidebar: overlay on small screens with backdrop - Chat bubbles: user=fit-width, assistant=full-width - Fix infinite loops (use onMount for data fetching) - Fix sendMessage race condition (await settings saves before chat POST) - Model selector: auto-open model modal after key selection - Rename views: Permissions->Tools, Tab Settings->Model Choice - Shared appSettings store for cross-component reactive state - Delete old chat.svelte.ts
2026-05-21feat: tool permission toggles, settings improvements, UI polishAdam Malczewski
- Tool permissions (read, edit, bash) stored in DB and control Agent tool registration - Agent invalidated when permissions change; cache warning in Permissions panel - Default: read=allow, edit=ask, bash=ask (matches UI checkboxes) - Settings: auto-save title model on selection (removed save button) - Settings: auto-expand thinking checkbox with shared reactive store - Permissions panel: renamed from Permission Log, shows tool toggles + collapsible log - Sidebar: renamed Current Model to Model Choice - Chat input: allow typing while agent runs (just disable send) - Chat cursor: fix doubled rectangle (removed unicode char) - Generic GET/PUT /tabs/settings/:key endpoints for key-value settings
2026-05-21feat: tab system with per-tab agents, DB persistence, and DaisyUI tabs-lift UIAdam Malczewski
- Add tabs, messages, and settings tables to SQLite database - Backend: refactor AgentManager to manage per-tab Agent instances via Map<tabId, TabAgent> - Backend: WebSocket events tagged with tabId for multiplexing - Backend: tab CRUD routes (create, list, update, archive, messages) - Backend: persist user and assistant messages to DB during chat - Frontend: new tabStore replaces single chatStore with multi-tab reactive state - Frontend: TabBar component using DaisyUI tabs-lift style with status dots - Frontend: Settings sidebar panel for title generation model selection - Frontend: wire ChatPanel, ChatInput, Header to use tabStore - Fix HMR listener accumulation via wsClient.clearCallbacks() - Delete old single-chat chatStore (chat.svelte.ts)
2026-05-21refactor: gut model/tag/fallback/agent-template system, fix Docker setupAdam Malczewski
- Remove ModelResolver, model definitions, model tags, fallback order, agent templates - Remove all [[models]], [agents], and fallback from dispatch.toml and config schema - ModelRegistry is now a pure key-state manager - dispatch.toml reduced to keys + permissions only - Docker: fix entrypoint for existing UID, skip bun install in frontend container - Docker: scoped build cache prune in bin/clean
2026-05-21feat: SQLite database for all credentials, keys, wake schedule, and usage cacheAdam Malczewski
- Add SQLite database at ~/.local/share/dispatch/dispatch.db with tables: credentials, api_keys, wake_schedule, usage_cache - Store Claude OAuth credentials in DB with import button in Model Status UI - Store OpenCode/Copilot API keys in DB with paste-to-import modal - Store OpenCode cookie and workspace IDs in DB - Migrate wake schedule from .wake-schedule.json to DB - Migrate usage cache from in-memory Map + localStorage to DB - Remove all env var and file fallbacks — DB is the single source of truth - Add seed scripts: bin/import-credentials.ts, bin/seed-opencode-keys.ts - Docker: container runs as host UID/GID with matching home directory - Clean up dispatch.toml: remove env fields, update comments - Progress bar time markers for usage cycle tracking
2026-05-21fix: wake scheduler persistence/retry, credential filtering, usage cache and ↵Adam Malczewski
display names - Wake scheduler: fix Bun timer leak, make recurring daily, persist to disk, retry failed wakes every 5min for 30min, start at boot - Key usage: localStorage cache survives page refresh, spinner during all refreshes, show cached data immediately - Credential filtering: key-usage and wake only use configured credentials_file, exclude unconfigured accounts - Display: remove counter suffix from Claude labels, format opencode/copilot key names
2026-05-21feat: usage cache with spinner refresh — shows cached data immediately, ↵Adam Malczewski
refreshes in background
2026-05-21fix: compact panel sizing, close button on new panels (not first)Adam Malczewski
2026-05-21feat: + button to add new sidebar panels, each with independent view selectionAdam Malczewski
2026-05-21fix: remove orphaned SidebarPanel props from App.svelteAdam Malczewski
2026-05-21refactor: move ModelSelector into dropdown as 'Current Model' optionAdam Malczewski
2026-05-21fix: key usage fills available sidebar height (flex-1 instead of max-h-96)Adam Malczewski
2026-05-21fix: include time in reset brackets (e.g. 'in 3w 2d (05/28 4:36 PM)')Adam Malczewski
2026-05-21feat: natural English reset times beyond 48h (e.g. 'in 3w 2d (05/28)')Adam Malczewski
2026-05-21feat: cache Claude usage — return last successful result on fetch failureAdam Malczewski
2026-05-21feat: show countdown for resets within 48h (e.g. 'in 5:30')Adam Malczewski
2026-05-21feat: key usage auto-refreshes every 90sAdam Malczewski
2026-05-21fix: backend wake scheduler with atomic toggle API, American time displayAdam Malczewski
- Replaced POST /wake-schedule (full-replace) with POST /wake-schedule/toggle (atomic single-hour toggle) to eliminate race conditions between frontend and scheduler - Recursive setTimeout prevents overlapping wake executions - HMR-safe via global timer reference - Frontend now uses toggle endpoint instead of full schedule POST - Display shows reset time (wake hour + 5h) in American 12h format e.g. '8:15 → Reset at 1:00 PM' instead of European 24h
2026-05-20feat: Claude Reset scheduler + fix key config and Claude groupingAdam Malczewski
- Added claude-pro key pointing to default credentials, claude-max pointing to .credentials-2.json (docker path /root/.claude/) - POST /models/wake sends 'hi' to haiku for all Claude accounts - ClaudeReset.svelte: 2 AM rows + 2 PM rows of 6 hour blocks each (12-hour American format). Click blocks to schedule wake at :15 - Key Usage now groups all Claude accounts under one 'Claude' card instead of duplicating under claude-pro and claude-max cards
2026-05-20fix: per-key independent loading, better spacing between Claude accountsAdam Malczewski
- Each key now loads independently with its own spinner - Claude account sub-cards separated by border + spacing - Fixed Svelte 5 if/else chain and class: directive issues
2026-05-20feat: key usage shows all keys at once, removes dropdown, multi-account ClaudeAdam Malczewski
- /key-usage route now returns all Claude accounts (not just first) - Added ClaudeAccountUsage type for per-account data - Frontend shows all keys stacked in scrollable cards - Each Claude account rendered separately with label + subscription badge - Removed key selector dropdown
2026-05-20feat: key usage panel — display usage data for Claude, OpenCode, and CopilotAdam Malczewski
Adds 'Key Usage' to the sidebar dropdown with per-provider live usage: - Claude: 5-hour and weekly utilization bars with reset timestamps (normalizes Anthropic's 0-100% API response to 0-1 internally) - OpenCode: Scrapes usage from workspace page via OPENCODE_COOKIE session cookie, mapping key IDs to OPENCODE_WS1_ID/OPENCODE_WS2_ID - Copilot: Fetches from api.github.com/copilot_internal/user with entitlement/remaining/quota reset tracking New files: opencode.ts, copilot.ts (usage fetchers), KeyUsage.svelte New route: GET /models/key-usage?keyId=X dispatches by provider
2026-05-20feat: claude max oauth support with multi-account switching, reasoning ↵Adam Malczewski
effort, and dynamic model listing
2026-05-20fix: sidebar uses flex-1 min-h-0 for reliable scrolling instead of absolute ↵Adam Malczewski
inset-0
2026-05-20fix: sidebar layout, copilot auth script, config setupAdam Malczewski
- Sidebar uses absolute inset-0 with overflow-y-auto for proper scrolling - Border moved to inner div so it hides with sidebar - Copilot auth script uses portable sed instead of grep -P (macOS compat) - dispatch.toml with 3 keys, 4 models, fallback order - .env.dispatch with key placeholders and script reference - docker-compose loads .env.dispatch via env_file
2026-05-20feat: phase 3 — config, skills, model groups, task list, and sidebar UIAdam Malczewski
- Config system: TOML-based dispatch.toml with hot-reload via chokidar - Model/key resolution: tag-based model selection, key fallback chains - Skills system: directory loader with TOML frontmatter, agent mappings - Task list tool: add/update/list/get operations with WebSocket events - API routes: GET /config, /skills, /skills/:name, /models, /models/resolve - Frontend: sidebar with model status, task list, config viewer, skills browser, permission log - Sliding sidebar animation using CSS transitions (not Svelte transitions)
2026-05-20fix: make agent chat bubbles transparent (bg-transparent)Adam Malczewski
2026-05-20fix: both user and assistant chat bubbles on left sideAdam Malczewski
2026-05-20feat: smart scroll — auto-follow during streaming, manual mode on scroll ↵Adam Malczewski
up, scroll-to-bottom button
2026-05-20fix: gemini review — XSS sanitization, collapse-arrow padding, redundant aliasAdam Malczewski
2026-05-20fix: highlight.js crash from unknown languages, add lazy loading and hot ↵Adam Malczewski
preload set
2026-05-20feat: markdown rendering, daisyUI 5 compliance fixes, garden/luxury themesAdam Malczewski
2026-05-19feat: Phase 2 — shell permissions, tree-sitter analysis, permission UIAdam Malczewski
Permission engine: - Rule-based engine: wildcard matching, last-match-wins, reject cascade - PermissionService with pending/approved state, PermissionChecker interface - dispatch.yaml config loader with per-permission pattern rules Shell tool: - run_shell tool with child_process spawn, timeout, streaming output - Tree-sitter static analysis (web-tree-sitter + tree-sitter-bash WASM) - BashArity command normalization for 'always allow' patterns - FILE_COMMANDS set: rm, cp, mv, mkdir, ls, find, grep, cat, etc. Agent loop refactored: - Removed maxSteps, manual step loop with tool execution - Permission checks on shell commands (external_directory only) - Permission checks on file tools outside workspace boundary - Symlink bypass fix (realpathSync), .. false positive fix - Shell output streaming via Promise.race + setImmediate polling API layer: - PermissionManager wraps PermissionService, broadcasts via WebSocket - WebSocket handles permission-reply messages from frontend - Config loaded from dispatch.yaml, converted to ruleset Frontend: - Permission prompt modal (native dialog, focus trap, ARIA) - Always-allow confirmation flow with pattern preview - Shell output display (live streaming + final parsed result) - Permission log panel (fixed bottom-right overlay) - Exit code badge (green 0, red non-zero) 134 tests, typecheck clean on all 3 packages
2026-05-19feat: inline tool display and thinking/reasoning supportAdam Malczewski
- Tool calls now appear at their stream position within messages (ContentSegment model) - Added reasoning/thinking display: collapsible <details> block above content - Set DeepSeek V4 Flash reasoningEffort to max via providerOptions - ChatMessage.content changed from string to ContentSegment[] (text | tool-call) - Agent handles AI SDK reasoning events, yields reasoning-delta - Fixed duplicate key in ChatMessage.svelte each block
2026-05-19fix: review findings — multi-turn history, race condition, collapse UIAdam Malczewski
- Core: toCoreMessages now includes tool calls and tool results in history - Core: isError read from step tool results instead of hardcoded false - API: status set synchronously before async generator to prevent race - Frontend: DaisyUI collapse-open class applied dynamically on expanded state - Frontend: removed duplicate isConnected update in wsClient.onEvent
2026-05-19fix: DeepSeek reasoning_content dropped on multi-step tool callsAdam Malczewski
- Base URL corrected: zen/v1 -> zen/go/v1 (opencode-go provider) - Model changed: deepseek-v4-flash-free -> deepseek-v4-flash - Added wrapLanguageModel middleware to inject reasoning_content via providerMetadata.openaiCompatible before each stream call - Fixed test mocks: removed vi.importActual (unsupported in Bun), added tool factory mocks, preserved real tool export in ai mock - Added 11 tests for the normalizeMessages middleware
2026-05-19Phase 1: single agent + basic UIAdam Malczewski
- Bun monorepo with @dispatch/core, @dispatch/api, @dispatch/frontend - Agent runtime with Vercel AI SDK, streaming via WebSocket - Tools: read_file, write_file, list_files (scoped to working directory) - Hono API server with POST /chat, GET /status, GET /health, WS /ws - Svelte 5 + DaisyUI frontend with chat UI, theme switcher, copy button - OpenCode Go (Zen) as LLM provider, deepseek-v4-flash-free model - Docker setup (dev + prod) with bin/ scripts and gopass secrets - Biome v2 linting/formatting, Vitest tests (44 passing) - Debug info attached to error messages for diagnostics