- new design system in globals.css: warm graphite surfaces, ivory text, honey
accent; semantic status/data-type/syntax tokens replacing hardcoded colors
- IBM Plex Mono as the universal UI font (sans + mono), tabular numerals
- custom CodeMirror SQL theme (src/lib/editor-theme.ts) matching the palette
- data grid: zebra striping + honey row hover, stronger sticky header
- route status dots, JSON syntax, EXPLAIN cost, schema-tree icons and the
read/write toggle through the new tokens
- TUSK wordmark in the toolbar
Two changes that close the "everything lives in one global pool" gap.
UI: Saved Queries sidebar now defaults to "This connection" and lists
only entries with `connection_id == activeConnectionId` plus unattached
entries (legacy global saves before F2). A small toggle ("All") above
the search box brings the previous behavior back when copying queries
between databases. Each row in "All" mode shows a tag with the source
connection's name; legacy global entries show "unattached".
Backend: delete_connection now best-effort cleans persisted state for
that connection — removes `memory/<id>.md` (delete_memory_core in
memory.rs) and drops every entry in saved_queries.json with the
matching `connection_id` (delete_by_connection_core in
saved_queries.rs). Entries with `connection_id == None` are deliberately
preserved. Cleanup errors are logged but don't block the deletion since
connections.json is the source of truth.
Memory was already per-connection (F1); query history already filters
by connection. This commit makes saved queries behave the same and
stops orphan files from accumulating.
@uiw/react-codemirror's outer wrapper inherited h-full but the inner
.cm-editor / .cm-scroller had no height constraint, so long queries
spilled outside the visible area with no way to scroll. Pass
`height="100%"` to the CodeMirror component and pin .cm-editor to the
wrapper height via a Tailwind arbitrary selector so the scroller
renders correctly inside the resizable panel.
Routes chat-completions through a managed OpenAI-compatible inference
endpoint as an alternative to local Ollama, useful when the agent needs
fast multi-hop reasoning that local hardware can't sustain.
- backend: rename `call_ollama_chat_messages` → `call_chat_messages`,
dispatch by provider; add `call_fireworks` branch (Bearer auth,
`response_format: json_object` mapped from internal `format="json"`)
and `list_fireworks_models` Tauri command
- settings: extend `AiProvider` enum + `AiSettings.fireworks_api_key`
(serde-default for legacy config compat); Fireworks base URL hardcoded
- UI: provider selector in both popover and AppSettingsSheet (only
ollama+fireworks shown; legacy openai/anthropic kept for serde-compat
but normalized to ollama in UI); password input + dynamic model list
for Fireworks; switching provider clears stale model selection
- 4 unit tests: serde round-trip, legacy settings deserialization,
Fireworks chat-completions parsing, models-list parsing
Adds inline data visualisation to the chat agent. After a successful
run_query, the agent can call make_chart(chart_type, x, y, [group,
title, orientation]) and the result is rendered as a bar / line / area
/ pie chart inline in the chat thread, sourced from the previous query
result.
Backend (commands/chat.rs, models/chat.rs)
- New ChartConfig{chart_type, x, y, group?, title?, orientation?} model.
- New AgentAction::MakeChart{config} variant. Parser accepts both
`chart_type` and the alternative `type` field name (qwen3 sometimes
emits the latter). Validates chart_type is one of bar/line/area/pie.
- last_successful_query_result helper finds the most recent successful
run_query in the working thread.
- MakeChart dispatcher: validates that x/y/group columns exist in the
attached query result, emits a tool_result with the same QueryResult
in `result` and the chart_config JSON in `text`. Mismatches surface
as a clear error ("y column `name` is not in the last result.
Available: company_name, legal_name, …").
- build_history compression unchanged: make_chart's tool_result text
field (the small chart_config JSON) is included in LLM history; the
large QueryResult.rows are NOT, since the per-tool branch only emits
text for non-run_query tools.
- System prompt: documents make_chart with concrete usage hints
(top-N → bar, time series → line/area, proportions → pie; skip for
≤2 or >500 rows). 7 new parser/dispatcher tests.
Frontend (src/components/chat/)
- recharts ^3.8 added.
- New ChartPreview component renders bar (vertical+horizontal), line,
area, pie. Supports grouped series via the `group` config field by
pivoting rows into a wide format. Y values coerced to numbers
(parses strings, nulls → 0). Caps to 500 points to keep things
responsive on huge results.
- ChatMessageView routes tool=="make_chart" tool_result through a new
ChartToolResult that parses the config JSON from the message text
and feeds the embedded QueryResult into ChartPreview.
- New labels/icons (BarChart3) and preview-extraction for make_chart
in tool-call collapsed headers (`bar: carrier_name → trip_count`).
Verification: cargo test --lib 77 pass (+7), tsc clean, vitest 20
pass.
INTERVAL handling
- pg_value_to_json now decodes PG INTERVAL via PgInterval and renders
it psql-style: `1 year 2 mons 3 days 04:05:06`. Previously
AVG(timestamp - timestamp) and similar interval-returning queries
showed `<unsupported type: INTERVAL>` in chat results.
- 7 unit tests covering zero, days-only, mixed, negative, microsecond
fraction, and the singular/plural unit rules.
Compact reliability
- Sharper system prompt: explicitly instructs plain text starting with
`-`, no JSON, no fences, no field names. qwen3-coder is heavily
trained on the agent JSON protocol and was sometimes returning
`{"action":"final","text":"..."}` even for the compact prompt.
- New clean_summary helper strips ``` fences (with or without lang
identifier) and extracts the underlying string from a JSON envelope
if the model still wraps the answer (looks for text/summary/content/
answer/output keys). 6 unit tests.
- Frontend useChat.compact: success/no-op/error toasts via sonner so
the user sees what happened. "Nothing to compact" appears when there
is no older history beyond the last user turn (previously silent).
Verification: cargo test --lib 66 pass (+13), tsc clean, vitest 20
pass.
Adds visibility into how much of the model context window the chat agent
is using and a way to free space when it fills up.
Backend
- New ContextUsage{used_chars, budget_chars} returned from chat_send
alongside messages (return type ChatTurnResult). Computed by running
build_history once at end of turn and counting char bytes — same data
path as the actual LLM call, so the count is exact for the chosen
budget unit.
- CONTEXT_BUDGET_CHARS = 24,000 (~6-8K tokens). Tuned for Ollama
defaults; can be exposed via AiSettings later.
- New chat_compact Tauri command. Splits the thread at the last user
turn, LLM-summarises everything before it (3-6 bullet points,
language-aware, < 800 chars), and returns a thread of
[Assistant("📋 Compacted N messages: …"), <last_user_turn?>]. The
recent user turn is preserved untouched so the agent can keep
answering it.
- render_thread_for_summary skips QueryResult.rows entirely so a single
large run_query can't blow the summariser's context.
- 3 new unit tests (last_user_turn_index, render skipping rows, empty
thread no-op).
Frontend
- ChatPanel header gets a usage badge: progress bar + `Xk / Yk tok ·
P%`, color-coded green (<30%) / muted (<60%) / amber (<85%) / red
(≥85%). Tooltip explains and nudges /compact when ≥60%.
- Compact button next to Clear in the header.
- Slash commands in ChatComposer: /compact, /clear.
- Empty-state shows the slash-command hint.
- Auto-compact: if the previous turn pushed usage past 85% AND the
thread has more than one message, the next user turn first runs
chat_compact transparently before chat_send. The compaction surfaces
as a visible Assistant("📋 Compacted …") message so the user can see
what the agent kept.
- app-store gets chatUsage map per tab + replaceChatThread + setChatUsage
actions; closeTab and clearChatThread clean up usage too.
Verification: cargo check clean, cargo test --lib 53 pass (+3),
tsc --noEmit clean, vitest run 20 pass.
Removes enterprise/DBA features and replaces the marginal AI bar with a
central chat agent that has progressive-discovery tools, cross-session
memory, saved-query reuse, and inline result actions. Adds ClickHouse
support alongside PostgreSQL/Greenplum.
Cleanup
- Drop ~10k LOC of advanced features: Docker, Snapshots, Validation,
Index Advisor, Role/User Management, Data Generator, ERD, Lookup.
- Trim deps: drop @xyflow/react, dagre, @types/dagre; cut tokio features
to rt-multi-thread/sync/time/net/macros.
- Remove unused TuskError variants and dead helpers (topological_sort,
invalidate_schema_cache).
Multi-DB (PostgreSQL + ClickHouse)
- New src-tauri/src/db/ module: ChClient (HTTP-based, reuses reqwest),
sql_guard (cross-flavor read-only whitelist with 8 tests).
- ConnectionConfig gains db_flavor and secure fields with serde defaults
for backwards-compatible connections.json.
- All connection/query/schema/data commands dispatch by flavor; CH
covers connect, execute_query, list_databases/schemas/tables/views/
columns/completion_schema, paginated table fetch.
- Frontend: dbCapabilities matrix, ConnectionDialog engine selector
with port auto-swap and HTTPS toggle, SqlEditor switches to
StandardSQL dialect for CH, TableDataView surfaces CH connections as
read-only.
AI-first chat agent
- New src/components/chat/ panel with composer, message rendering,
collapsible tool-call/result blocks, top-level ErrorBoundary.
- Backend agent loop in commands/chat.rs with strict-JSON tool
protocol. Nine tools: list_databases, list_tables, get_columns,
switch_database, run_query, remember, save_query, find_queries, final.
Forgiving parser accepts both flat and nested-input shapes.
- Compressed history: only the last 4 run_query results carry sample
rows (≤10, cells truncated to 200 chars) into LLM context; older
results marked omitted.
- System prompt uses lite OVERVIEW (DB list + active-DB tables only)
instead of full DDL — schema details are loaded on demand via
get_columns. CH OVERVIEW shows cross-DB tables since CH allows
db.table queries.
Cross-session memory (F1)
- Per-connection markdown file at app_data_dir/memory/<connection_id>.md,
16KB cap with oldest-block eviction. Agent appends via remember()
tool; the file is injected into LEARNED NOTES section of every system
prompt.
- New Memory sidebar tab with editable textarea, badge for note count,
empty-state with template. Edits picked up on the next agent turn.
Saved-query reuse (F2)
- Tools save_query and find_queries scoped to current connection.
save_query attaches a UUID + timestamp; find_queries returns top 10
matches with SQL preview ≤500 chars.
- Storage shared with the sidebar Saved panel.
Inline result actions (F3)
- run_query result block in chat gets Open-full (90vw × 80vh modal with
full ResultsTable, no row cap) and Export (reuses ExportDialog for
CSV/JSON via existing exportCsv/exportJson commands).
Verification
- cargo check clean, zero warnings.
- cargo test --lib: 50 pass (20 chat parser + 4 memory + 8 sql_guard +
6 clean_sql + 12 escape_ident).
- npx tsc --noEmit clean.
- npx vitest run: 20 pass.
Replace raw WHERE input with a dual-mode filter:
- Visual mode: column/operator/value dropdowns with AND/OR support
- SQL mode: raw WHERE clause input (auto-strips "where" prefix)
Replace useEffect-based state resets in dialogs with React's render-time
state adjustment pattern. Wrap ref assignments in hooks with useEffect.
Suppress known third-party library warnings (shadcn CVA exports,
TanStack Table). Remove warn downgrades from eslint config.
Reformat Rust code with rustfmt, suppress clippy::too_many_arguments
for Tauri IPC commands, derive Default for AppSettings, fix unused
variable pattern in TableDataView, and add unit tests for utils.
Replace install -D with mkdir -p + install for macOS portability,
add vitest with jsdom and testing-library, configure eslint for
react-hooks v7 warnings, and add tokio test deps for Rust.
Outfit + JetBrains Mono typography, soft dark palette with blue
undertones, electric teal primary, purple-branded AI features,
noise texture, glow effects, glassmorphism, and refined grid/tree.
Four new killer features leveraging AI (Ollama) and PostgreSQL internals:
- Data Validation: describe quality rules in natural language, AI generates
SQL to find violations, run with pass/fail results and sample violations
- Test Data Generator: right-click table to generate realistic FK-aware test
data with AI, preview before inserting in a transaction
- Index Advisor: analyze pg_stat tables + AI recommendations for CREATE/DROP
INDEX with one-click apply
- Data Snapshots: export selected tables to JSON (FK-ordered), restore from
file with optional truncate in a transaction
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix SQL injection in data.rs by wrapping get_table_data in READ ONLY transaction
- Fix SQL injection in docker.rs CREATE DATABASE via escape_ident
- Fix command injection in docker.rs by validating pg_version/container_name
and escaping shell-interpolated values
- Fix UTF-8 panic on stderr truncation with char_indices
- Wrap delete_rows in a transaction for atomicity
- Replace .expect() with proper error propagation in lib.rs
- Cache AI settings in AppState to avoid repeated disk reads
- Cap JSONB column discovery at 50 to prevent unbounded queries
- Fix ERD colorMode to respect system theme via useTheme()
- Extract AppState::get_pool() replacing ~19 inline pool patterns
- Extract shared AiSettingsFields component (DRY popover + sheet)
- Make get_connections_path pub(crate) and reuse from docker.rs
- Deduplicate check_docker by delegating to check_docker_internal
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a table has no PRIMARY KEY, use PostgreSQL's ctid (physical row ID)
to identify rows for UPDATE/DELETE operations instead of blocking edits.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add AppSettingsSheet (gear icon in Toolbar) with MCP, Docker, and AI sections
- MCP Server: toggle on/off, port config, status badge, endpoint URL with copy
- Docker: local/remote daemon selector with remote URL input
- AI: moved Ollama settings into the unified sheet
- MCP status probes actual TCP port for reliable running detection
- Docker commands respect configurable docker host (-H flag) for remote daemons
- MCP server supports graceful shutdown via tokio watch channel
- Settings persisted to app_settings.json alongside existing config files
- StatusBar shows MCP indicator (green/gray dot) with tooltip
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use bash with pipefail instead of sh to detect pg_dump failures in pipes
- Switch full clone from binary format (pg_dump -Fc | pg_restore) to plain
text (pg_dump | psql) for reliable transfer through docker exec
- Add --no-owner --no-acl flags to avoid errors from missing roles
- Extract shared run_pipe_cmd helper with proper error handling
- Remove shell commands from progress events to prevent credential leaks
- Fix process log layout overflow with break-all and block-level details
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Clone any database to a local Docker PostgreSQL container with schema
and/or data transfer via pg_dump. Supports three modes: schema only,
full clone, and sample data. Includes container lifecycle management
(start/stop/remove) in the Admin panel, progress tracking with
collapsible process log, and automatic connection creation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add interactive ER diagram with ReactFlow + dagre auto-layout, accessible
via right-click context menu on schema nodes in the sidebar
- Enhance TableStructure: column comments, FK referenced table/columns,
ON UPDATE/DELETE rules, new Triggers tab
- Backend: rewrite get_table_constraints using pg_constraint for proper
composite FK support, add get_table_triggers and get_schema_erd commands
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Render all tabs simultaneously with display:none for inactive ones,
instead of conditionally rendering only the active tab. This prevents
React from unmounting/remounting components on tab switch, preserving
query results, editor cursor, AI explanations, and other local state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Radix ScrollArea with plain overflow-auto div to allow nested
horizontal scrolling in lookup result tables. Add overflow-auto to
table containers. Increase per-database search timeout from 30s to 120s.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add select-text to override global user-select:none on results table,
JSON view, error messages, and AI explanation. Also keep AI prompt text
after generation with a clear button.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract shared call_ollama_chat helper from generate_sql to reuse
settings loading and Ollama API call logic. Add two new AI commands:
- explain_sql: explains what a SQL query does in plain language
- fix_sql_error: suggests corrected SQL based on the error and schema
UI additions: "AI Explain" toolbar button, "Explain" and "Fix with AI"
action buttons on query errors, inline explanation display in results.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Reduce unnecessary re-fetches on large DWH by caching schema/management
queries for 5 minutes, and add a refresh button in the sidebar to
force-reload when needed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Greenplum 7 (PG12-based) compatibility:
- Auto-detect GP via version() string, store DbFlavor per connection
- connect returns ConnectResult with version + flavor
- Fix pg_total_relation_size to use c.oid (universal, safer on both PG/GP)
- Branch is_identity column query for GP (lacks the column)
- Branch list_sessions wait_event fields for GP
- Exclude gp_toolkit schema in schema listing, completion, lookup, AI context
- Smart StatusBar version display: GP shows "GP 7.0.0 (PG 12.4)"
- Fix connection list spinner showing on all cards during connect
AI SQL generation (Ollama):
- Add AI settings, model selection, and generate_sql command
- Frontend AI panel with prompt input and SQL output
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Enables searching for a specific column value (e.g. carrier_id=123) across all databases on a PostgreSQL server. The backend creates temporary connection pools per database (semaphore-limited to 5), queries information_schema for matching columns, and executes read-only SELECTs with real-time progress events. Results are grouped by database/table in a new "Entity Lookup" tab.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a Table/JSON segmented toggle to both the query workspace and
table data viewer, allowing users to switch between tabular and
pretty-printed JSON display of results without exporting to a file.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Column sort by header click in table view (ASC/DESC/none cycle, server-side)
- SQL formatter with Format button and Shift+Alt+F keybinding (sql-formatter)
- Table size and row count display in schema tree via pg_class
- Insert row dialog with column type hints and auto-skip for identity columns
- Saved queries (bookmarks) with CRUD backend, sidebar panel, and save dialog
- Active sessions monitor (pg_stat_activity) with auto-refresh, cancel & terminate
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a refresh/reconnect button next to the connection selector.
Clicking it disconnects and reconnects the active connection, then
invalidates all cached queries to refresh schema, tables, roles, etc.
Shows a spinning animation while reconnecting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Fields/DSN toggle in New Connection dialog. DSN mode accepts a
PostgreSQL connection string (postgresql://user:pass@host:port/db?sslmode=...)
and auto-parses it into individual fields. Switching between modes
syncs the data bidirectionally.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add Admin sidebar tab with database/role management panels, role manager
workspace tab, and privilege dialogs. Backend provides 10 new Tauri
commands for CRUD on databases, roles, and privileges with read-only
mode enforcement. Context menus on schema tree nodes allow dropping
databases and viewing/granting table privileges.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Changed from fixed w-[200px] to w-auto max-w-[280px] so the trigger
sizes to its content without clipping the environment badge.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SelectValue already renders the color dot from the selected item,
so the explicit one in the trigger was redundant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
SelectValue already renders the badge from the selected item content,
so the explicit badge in the trigger and the standalone toolbar badge
were redundant.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Visual badges help distinguish environments across the UI to prevent
running dangerous queries on production. Environment color takes
priority over custom connection color for the toolbar border.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Export dropdown (CSV/JSON) appears in the WorkspacePanel toolbar when
query results are available, and in the TableDataView toolbar for table
data. Uses the Tauri save dialog for file path selection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add four developer/QA features:
- Connection color coding: color picker in dialog, colored indicators across toolbar, tabs, status bar, and connection selectors
- Query history: Rust backend with JSON file storage (500 entry cap), sidebar panel with search/clear, auto-recording from workspace
- Schema-aware SQL autocomplete: backend fetches column metadata, CodeMirror receives schema namespace with public tables unprefixed
- EXPLAIN ANALYZE visualizer: recursive tree view with cost-colored bars, expand/collapse nodes, buffers info, Results/Explain tab toggle
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Connections default to read-only. SQL editor wraps queries in a
read-only transaction so PostgreSQL rejects mutations. Data mutation
commands (update_row, insert_row, delete_rows) are blocked at the
Rust layer. Toolbar toggle with confirmation dialog lets users
switch to read-write. Badges shown in workspace, table viewer, and
status bar.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add TableDataView with pagination, filtering, and inline editing,
TableStructure with columns/constraints/indexes tabs,
PaginationControls, and ExportDialog for CSV/JSON export.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add CodeMirror 6 SQL editor with Ctrl+Enter execution, ResultsTable
with virtual scrolling and resizable columns, ResultsPanel, EditableCell,
WorkspacePanel (editor + results split), and TabContent router.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add SchemaTree with database/schema/category hierarchy, Sidebar with
search, Toolbar, TabBar, StatusBar, and full app layout with
resizable panels.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Set up Vite + React 19 + TypeScript, Tauri v2, Tailwind v4,
shadcn/ui (dark theme), and all core frontend dependencies
(Zustand, TanStack Query/Table/Virtual, CodeMirror, lucide-react).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>