Commit Graph
100 Commits
Author SHA1 Message Date
Abeautifulsnow 760d2c6409 fix(source): open pending tab while loading object source 2026-09-14 19:59:21 +08:00
Abeautifulsnow 8d32cf9ffa fix(import): hide the data-tab import entry for unsupported engines 2026-09-14 14:31:40 +08:00
Abeautifulsnow 638aa48f57 feat(data-grid): hide selected columns from header context menu 2026-09-14 12:39:06 +08:00
Abeautifulsnow 32e070f387 fix(editor): stop replaying stale format and compress requests 2026-09-11 19:58:45 +08:00
Abeautifulsnow 6f259a60c5 fix(ai): retry and diagnose transient provider failures 2026-09-11 18:04:59 +08:00
Abeautifulsnow a9b4470944 fix(mcp): persist query timeout edits reliably 2026-09-10 18:04:05 +08:00
Abeautifulsnow 464f2f33c5 feat(object-browser): add table Add to AI context menu entry 2026-09-10 11:59:20 +08:00
Abeautifulsnow 41b5e51dcc feat(grid): preserve data-grid viewport and selection across tab switches 2026-09-09 22:36:20 +08:00
Abeautifulsnow 4528a15492 feat(redis): add hash field and value copy targets 2026-09-08 22:34:36 +08:00
Abeautifulsnow 2b2d1f0d95 feat(ai): export conversation as markdown or html 2026-09-08 16:46:22 +08:00
Abeautifulsnow 8642e1a599 feat(object-browser): preserve object list on return via stale cache 2026-09-08 11:51:50 +08:00
Abeautifulsnow 39b2d2a6ac feat(ai): add sandboxed HTML preview for AI rich content 2026-09-07 22:44:23 +08:00
Abeautifulsnow 29c6d1fbed feat(ai): render chart-json blocks as interactive charts 2026-09-07 14:03:57 +08:00
Abeautifulsnow 3ee0640fc2 feat(elasticsearch): add visual search profiler 2026-09-04 20:38:26 +08:00
Abeautifulsnow 543bf66905 feat(mcp): execute sql batches with opt-in rollbackable transactions 2026-09-04 13:43:06 +08:00
Abeautifulsnow dd11e42748 fix(editor): anchor wrapped line numbers via inline style 2026-09-03 18:50:05 +08:00
Abeautifulsnow d421bd33fc fix(ui): scroll long error messages in rename dialogs 2026-09-03 17:51:43 +08:00
Abeautifulsnow 3c4d61339e fix(desktop): let data header name chips flex to content 2026-09-03 12:15:56 +08:00
Abeautifulsnow 91f309f6c7 feat(ai): default and last-used templates per db type 2026-09-02 20:37:39 +08:00
Abeautifulsnow d79d357924 feat(sql-library): add collapse all button and collapsed default 2026-09-01 11:00:59 +08:00
Abeautifulsnow e6f8b2187a feat(mcp): add global query timeout override 2026-08-30 12:26:54 +08:00
Abeautifulsnow fdfad88590 feat(editor): add global default transaction commit mode 2026-08-28 12:37:11 +08:00
Abeautifulsnow ec0b6768be feat(grid): add row/column crosshair highlight setting 2026-08-27 22:23:13 +08:00
Abeautifulsnow 40549c9573 fix(dialog): clamp grid track and wrap footer so dialogs stop clipping 2026-08-27 16:06:25 +08:00
Abeautifulsnow bd05c0350d feat(oracle): hide commit/rollback for clean manual-transaction state 2026-08-27 11:30:27 +08:00
Abeautifulsnow eeeb4e5011 feat(ai): run agent sessions as background tasks 2026-08-26 14:09:08 +08:00
Abeautifulsnow ff31f44b42 feat(ai): surface live AI generation status with smooth timing 2026-08-24 20:28:12 +08:00
Abeautifulsnow 12da615daa fix(ai): require exact SQL confirmation for agent writes 2026-08-21 10:36:17 +08:00
Abeautifulsnow 30f5c34729 feat(editor): add code snapshot export 2026-08-19 15:49:15 +08:00
Abeautifulsnow aeba7d81ad feat(objects): add search clear buttons 2026-08-18 22:04:38 +08:00
Abeautifulsnow c712be3e02 feat(agent): support cancelling installs and upgrades 2026-08-18 15:36:52 +08:00
Abeautifulsnow e6fa850a31 feat(editor): add configurable completion shortcut 2026-08-18 10:52:37 +08:00
Abeautifulsnow 99ded5c8bb fix(ai-agent): align table scrollbar themes 2026-08-18 10:52:01 +08:00
Abeautifulsnow 1ff24aaeb4 feat(auth): keep unsaved passwords in session memory 2026-08-14 18:37:53 +08:00
Abeautifulsnow a3eaac3413 feat(redis): add decoded Unicode JSON view 2026-08-13 19:44:48 +08:00
Abeautifulsnow a029888725 feat(connection): allow opting out of password storage 2026-08-12 19:34:00 +08:00
Abeautifulsnow b814b3d9be fix(kingbase): handle TOP-bounded export pagination 2026-08-12 00:19:57 +08:00
Abeautifulsnow 967084c498 feat(updater): support ignoring a specific version 2026-08-11 21:39:44 +08:00
Abeautifulsnow 8d084cc655 fix(mqtt): resolve console labels at render time 2026-08-11 21:36:10 +08:00
Abeautifulsnow 78b8f77e0d fix(codex): relax model discovery timeouts for Windows cold start 2026-08-11 13:06:54 +08:00
Abeautifulsnow 5b85f9eae8 feat(completion): configurable SQL completion trigger modes 2026-08-08 12:00:50 +08:00
Abeautifulsnow 13878a1a30 fix(sidebar): match cross-word table names via prefix concatenation 2026-08-07 13:43:42 +08:00
Abeautifulsnow b437c470e1 fix(sql): keep Ctrl+Enter on current statement at trailing whitespace 2026-08-07 02:56:26 +08:00
Abeautifulsnow 62624786dc feat(mcp): add update notification badge 2026-08-05 15:52:20 +08:00
Abeautifulsnow c0a6d6f2f9 feat(agent): add timezone-aware current time tool 2026-08-05 11:15:35 +08:00
Abeautifulsnow c3547fcb61 docs(redis): document decompressed value views 2026-08-05 02:59:51 +08:00
Abeautifulsnow ec44e09ec8 feat(redis): add decompressed view for compressed values 2026-08-03 20:59:39 +08:00
Abeautifulsnow f64d363abe feat(ai): export assistant analysis result as markdown 2026-07-31 21:17:57 +08:00
Abeautifulsnow c43e8455c4 fix(export): split XLSX sheets and stream worksheet XML 2026-07-31 19:45:37 +08:00
Abeautifulsnow 6c3c6864f3 feat(sql-file): show per-file execution statistics 2026-07-30 18:41:56 +08:00
Abeautifulsnow 52d5c99a92 fix(ai): improve API retry handling 2026-07-29 16:16:39 +08:00
Abeautifulsnow 06ed8dc5f6 feat(desktop): add Driver Store category navigation 2026-07-28 21:56:03 +08:00
Abeautifulsnow 88721925f2 feat(sql-file): preview multiple files with a side list 2026-07-28 20:17:36 +08:00
Abeautifulsnow cb9d0f7cbf fix(ai): harden write SQL confirmation flow 2026-07-28 11:56:23 +08:00
Abeautifulsnow 122853d089 fix(ai): reset action when reselecting active mode 2026-07-27 12:33:06 +08:00
Abeautifulsnow 95db01e359 feat(agents): concurrent all-agent-driver upgrade 2026-07-24 23:50:50 +08:00
Abeautifulsnow 6115771b34 feat(i18n): localize native tray and app menus 2026-07-23 19:07:10 +08:00
Abeautifulsnow 9253203d99 feat(ai): make agent turn limit configurable 2026-07-23 13:57:06 +08:00
Abeautifulsnow ffbd32d203 fix(sidebar): support separator-blind table search 2026-07-22 17:17:37 +08:00
Abeautifulsnow faca91a8e3 fix(data-grid): preserve literal backslashes 2026-07-22 15:11:50 +08:00
Abeautifulsnow 1fb3e2816b feat(ai): add custom prompt templates 2026-07-22 13:43:39 +08:00
Abeautifulsnow af9c052708 fix(settings): resolve editor settings dialog TDZ crash 2026-07-17 21:15:00 +08:00
Abeautifulsnow c417e54698 fix(ai): preserve last-used model during app session 2026-07-17 18:14:49 +08:00
Abeautifulsnow d9ef8b0cac fix(agent): enforce Oracle and Xugu query timeouts 2026-07-16 18:00:08 +08:00
Abeautifulsnow 7c43c03254 feat(ai): show reasoning character count when collapsed 2026-07-16 17:31:21 +08:00
Abeautifulsnow badb3b61b9 feat(diagnostics): add SQL execution debug logging 2026-07-16 17:01:24 +08:00
Abeautifulsnow fab1fa9195 feat(driver-store): add dedicated "Updates Available" section for pending driver updates
feat(driver-store): add dedicated "Updates Available" section for pending driver updates

Move drivers with available updates to a prominent amber-highlighted section
at the top of the Agent drivers tab, improving discoverability. After updating,
drivers automatically return to their original position in the "All Drivers" list.

Changes:
- DriverStoreDialog.vue: add orderedFilteredDrivers, filteredUpdatableCount,
  filteredUpdatableDrivers, filteredStableDrivers computed properties;
  replace flat v-for with two-tier layout using separate v-for loops
  (updates header + updatable list + section divider + stable list)
- 7 i18n locales: add updatesAvailableTitle, updatesAvailableDescription,
  allDriversTitle keys (zh-CN, zh-TW, en, ja, es, it, pt-BR)

Review fixes:
- #C01: rename single-letter variables d -> driver
- Eliminate nested <template> tags for oxfmt compatibility
@
2026-07-16 15:31:35 +08:00
Abeautifulsnow 78b3bb1ba1 feat(export): add streaming TXT data export 2026-07-13 20:44:57 +08:00
Abeautifulsnow 9e1b0c478e feat(editor): prefill new queries from focused tables 2026-07-13 16:15:09 +08:00
Abeautifulsnow 088a4a081b fix(ai): preserve editor content for SQL actions 2026-07-11 08:55:51 +08:00
Abeautifulsnow 0674433eea fix(mcp): disambiguate same-name connections 2026-07-10 14:44:40 +08:00
Abeautifulsnow 2eed0aa66c feat(redis): enable auto-refresh countdown for key TTL by default
Key Viewer panel now defaults auto-refresh ON, showing a live TTL
countdown without requiring the user to click the Clock button.

- Default autoRefreshEnabled from false to true
- Move countdown init + timer start into startAutoRefresh() as single entry
- Remove redundant countdownTtl reset from the tick callback's .then()
- load() finally block calls startAutoRefresh() for all call paths
2026-07-09 19:08:03 +08:00
Abeautifulsnow 1cfb39a7b0 fix(ai): restore global reasoning toggle accidentally reverted by d90847bb
fix(ai): restore global reasoning toggle accidentally reverted by d90847bb

Commit 09f9e446 replaced per-message expandedReasoning (Set<number>) with
a global reasoningExpanded boolean ref, defaulting to collapsed so all
messages share the same toggle state. This avoided the flip-flop where
reasoning auto-expanded during streaming and collapsed afterward.

Commit d90847bb (SQL file references) inadvertently reverted this when
resolving merge conflicts during its large template restructure.

Changes:
- Replace expandedReasoning (Set<number>) with reasoningExpanded (ref(false))
- Replace per-index toggleReasoning(i) with global toggleReasoning()
- Template uses reasoningExpanded instead of expandedReasoning.has(i) || msg.isThinking
@
2026-07-09 13:17:23 +08:00
Abeautifulsnowanddbx-i18n-bot 2c2d9d7fef feat(objects): add checkbox multi-select and grid view for object browser
* feat(objects): add checkbox column toggle for object browser

- Add objectBrowserShowCheckbox setting (default: false) to EditorSettings
- Checkbox column hidden by default; auto-shows when any tables are selected
- Toolbar button toggles multi-select mode (active state highlighted in primary color)
- Clearing the toggle also clears all selections
- Add i18n key objects.toggleCheckbox in en/zh-CN

Closes #2748 (part 2)

* feat(objects): add grid view mode for object browser

- Add objectBrowserViewMode setting (list | grid, default: list) to EditorSettings
- Toolbar segmented control toggles between list and grid views, persisted across sessions
- Grid view renders cards (icon + name + type + row count) in a responsive auto-fill layout
- Reuses existing sort, search, filter, multi-select and context menu
- Partition children not expandable in grid mode (minimal version)
- Add i18n keys objects.viewList/objects.viewGrid across all locales
- Backfill objects.toggleCheckbox in es/it/ja/pt-BR/zh-TW (missed in prior commit)

Refs #2748

* fix(objects): redesign grid view cards for visual polish

- Center-align content (icon + name + metadata) for a proper tile look
- Enlarge type icons (h-7) so color coding is visible at a glance
- Merge type label and row count on one line with separator
- Reduce internal spacing (gap-1.5) and tighten padding
- Replace background hover with border glow + shadow for cleaner feedback
- Narrow min card width (150px) for denser grid, add align-content:start
- Softer rounded-lg corners

Refs #2748

* fix(objects): polish grid view card visual details

- Add colored circle background behind icons (type-matched opacity-10)
- Increase name font from text-xs to text-sm for better legibility
- Separate row count into a primary-tinted badge (only shown when > 0)
- Keep type label clean without mixing row count inline

Refs #2748

* fix(objects): refine grid card min-width, icon shadow, and type label size

* @
feat(object-browser): align tile/grid card metadata with list view columns

Add the metadata categories present in the list view but missing from
the tile/grid card view (objectBrowserViewMode === "grid"):
- Size pill (totalBytes) next to the existing rows pill in the stats row
- Timestamps row showing created_at · updated_at (per-row conditional)
- Comment row (truncated, per-row conditional, with hover tooltip)

Each card now shows: icon, name, type label, rows pill, size pill,
timestamps (when present), and comment (when present) — matching the
same metadata categories the list view displays across its 8 columns.

Also fix a pre-existing bug in the list view where the totalBytes
column tooltip (:title) used formatObjectBrowserCount instead of
formatObjectBrowserBytes, showing a count-formatted number instead
of a byte-formatted size string.
@

* @
feat(object-browser): add sort selector in toolbar for grid/list views

The list view has column header click-to-sort but the grid/tile view
had no way to change sort order. Add a compact sort selector in the
toolbar that works identically in both views:

- Native <select> dropdown with all 7 sort keys (name, type, rows,
  size, created, updated, comment) using existing column i18n labels
- ArrowUp/ArrowDown direction toggle button with localized tooltip
- Positioned between schema selector and view toggle in the toolbar
- Shares the existing sortKey/sortDirection/toggleSort logic — list
  view column headers continue to work as before
- Accessible: aria-label on select, title on direction button

i18n: added sortAsc/sortDesc/sortBy to en.ts and zh-CN.ts
@

* @
fix(object-browser): make sort key options reactive to available data

sortKeyOptions was a static array that always included created_at and
updated_at even when no row had data for those fields. Sorting by an
empty field is a no-op that silently confuses users.

Convert to a computed that mirrors the list view column visibility logic
(hasCreatedAt / hasUpdatedAt): the two time-based sort options only
appear when at least one loaded row has that field populated.

Follows design decision: sort selector remains visible in both list and
grid views (plan B), acting as a shared sort state indicator.
@

* @
fix(object-browser): reset sortKey when selected option disappears from options

When sortKeyOptions loses created_at or updated_at (e.g. after a schema
switch clears all rows), sortKey could remain set to a key no longer in
the dropdown, causing the <select> to show a blank selection.

Add a watch on sortKeyOptions that resets sortKey to "name" and
sortDirection to "asc" whenever the current key is no longer present.
@

* chore(i18n): autofill new translations

* perf(object-browser): virtualize tile/grid view with RecycleScroller

Replaces the flat v-for over filteredRows with a row-chunked
RecycleScroller, matching the list view. Previously, switching to tile
mode on a schema with thousands of tables mounted every card and its
CustomContextMenu at once, stalling the UI for several seconds.

Changes:
- gridRows computed: chunks filteredRows into rows of gridColumns cards
- ResizeObserver on the grid container drives gridColumns; initial read
  uses getComputedStyle to match contentRect.width and avoid a 1-frame
  column jump on mount
- objectGridRowHeight computed: item-size adapts to whether the dataset
  has timestamp/comment rows, minimising wasted row space
- watch(gridContainerRef) re-attaches the observer across list<->grid
  toggles; onBeforeUnmount cleans up
- scrollObjectsToTop() resets scroll position on sort, search,
  object-type filter and view-mode changes
- CSS: new .object-browser-grid-wrapper / -scroller / -row classes with
  will-change / contain parity with the list scroller

---------

Co-authored-by: dbx-i18n-bot <github-actions[bot]@users.noreply.github.com>
2026-07-09 11:59:25 +08:00
Abeautifulsnow ffc0279352 fix(ai): make stop button actually cancel the agent stream
The stop button called aiCancelStream -> notify_one(), but the four
stream_*_with_tools SSE loops only `break`ed and returned Ok(token_usage)
when cancelled. run_agent_loop treated that as a normal completed turn and
kept going (often into contract-repair or the next turn), so isGenerating
stayed true and a single click did not stop the agent.

Return Err(AGENT_CANCELLED_ERROR) from the cancel branch so the existing
Err-cancel match arm sets loop_exit = Cancelled and stops the loop cleanly,
preserving whatever was streamed so far.

Additional:
- Promote AGENT_CANCELLED_ERROR to a shared `pub const` in ai.rs; agent_loop
  now references ai::AGENT_CANCELLED_ERROR.
- Check cancellation before executing requested tools, so a stop landing
  between stream-end and tool execution is honored.
- Wire cancellation into the text-only fallback (previously `_cancelled`,
  ignored) via tokio::select! racing ai::complete against cancelled.notified().

Known limitation left: in-flight tool execution (e.g. execute_query) is
still not interruptible mid-call.
2026-07-08 18:44:13 +08:00
Abeautifulsnow a5359798dc feat(redis): add auto-refresh countdown for key TTL display
* @
feat(redis): add auto-refresh countdown for Redis key TTL display

在 Redis 值查看器的 TTL 徽章旁增加自动刷新按钮,选中时显示 TTL 实时倒计时
(每秒递减),倒计时归零自动刷新数据,刷新按钮持续旋转。TTL 到期或网络异常
时自动关闭自动刷新避免死循环。

改动:
- RedisValueViewer.vue:新增 autoRefresh 状态、定时器与倒计时逻辑,模板增加
  Clock 切换按钮,RefreshCw 按钮支持 animate-spin 旋转
- load() 内复位倒计时;onBeforeUnmount 清理定时器

修复(review):
- #I01 TTL 到期/连接断开后自动关闭 autoRefresh 避免无限重试
- #C01 load() reject 增加 .catch() 处理 UnhandledPromiseRejection

i18n:zh-CN / zh-TW / en / ja / es / it / pt-BR 7 种语言补充 autoRefresh key
@

* @
test(redis): extract auto-refresh logic and add unit tests

将自动刷新核心决策逻辑提取为 lib/redis/redisAutoRefresh.ts 纯函数模块,
并编写 11 个单元测试覆盖状态机转换、TTL 显示计算和自动停止条件。

新增:
- lib/redis/redisAutoRefresh.ts:computeAutoRefreshTick / shouldStopAutoRefresh /
  computeDisplayTtl 纯函数
- lib/__tests__/redis/redisAutoRefresh.spec.ts:11 个测试用例

重构:
- RedisValueViewer.vue 改用提取后的纯函数,确保测试覆盖即实际运行逻辑
@
2026-07-08 15:37:27 +08:00
Abeautifulsnow 0901f176b0 fix(grid): preserve current page on data refresh instead of resetting to page 1
* @
fix(grid): preserve current page on data refresh instead of resetting to page 1

When refreshing table data (toolbar button, Ctrl+R, or auto-refresh), the
offset was hardcoded to 0, causing pagination to always jump back to the
first page. This was frustrating for users viewing later pages.

Use the current page offset (currentPage - 1) * pageSize so the user
stays on the same page after refresh. In infinite-scroll mode, the
offset still evaluates to 0 because resetInfiniteScrollState() sets
currentPage = 1, so behavior is unchanged.
@

* @
fix(grid): auto-redirect to last page when refreshed page no longer exists

Extends the refresh pagination fix with a safety net: when data is deleted
while viewing a later page (e.g. page 5 with only 2 pages remaining), the
grid auto-navigates to the last available page instead of showing an empty
page.

Uses a transient isRefreshingData flag to distinguish refresh/rollback
from normal pagination navigation, avoiding false triggers.
@

* Revert "@"

This reverts commit ff0bf0bb31.

* @
fix(grid): auto-redirect to last page when refreshed page no longer exists

When data is deleted while viewing a later page, the grid now auto-navigates
to the last available page instead of showing an empty page.

Uses a transient isRefreshingData flag to distinguish refresh/rollback
from normal pagination, and a loading-transition watcher (true->false)
placed after displayedTotalRowCount declaration to avoid TDZ errors.
@

* @
test(grid): add pagination offset-preservation and auto-redirect tests

Cover the two new behaviors added to DataGrid.vue:

1. dataGridPagination.test.ts — auto-redirect page calculation:
   - page beyond last page after data deletion → triggers redirect
   - page still valid → no redirect
   - fewer rows than one page → redirects to page 1
   - total=0 / total=undefined → guard prevents redirect

2. useDataGridActions.test.ts — offset preserved on reload:
   - onReloadData(offset=400) passes offset=400 to build-table-select-sql
   - resultPageOffset stored as 400 (not reset to 0)
@
2026-07-08 13:28:36 +08:00
Abeautifulsnow 09f9e44661 fix(ai): make reasoning expand/collapse consistent across messages
fix(ai): make reasoning expand/collapse consistent across messages

Replace per-message expandedReasoning Set with a global reasoningExpanded
boolean ref so all messages share the same toggle state. Default to collapsed.
This avoids the flip-flop where reasoning auto-expands during streaming and
collapses afterward, requiring repeated manual toggles.

- Replace expandedReasoning (Set<number>) with reasoningExpanded (boolean)
- Remove per-index toggleReasoning; use global flip instead
- Template uses reasoningExpanded instead of expandedReasoning.has(i) || msg.isThinking
@
2026-07-07 13:36:53 +08:00
Abeautifulsnow 8539011f25 feat(ai): split Ask/Agent action menus with task-oriented Agent actions
* feat(ai): add task-oriented Agent actions with per-action contract

Introduce three Agent-native actions — query, exploreSchema,
executeAndExplain — so Agent mode surfaces task-oriented operations
instead of reusing Ask's SQL-producing action set.

- ai.ts: extend AiAction with the new actions; add ASK_ACTIONS /
  AGENT_ACTIONS and defaultActionForMode / isValidActionForMode
  helpers; raise maxTokens for the explanatory task actions.
- aiSkills.ts: add skill definitions (zh/en) for the three actions.
- aiAgentPlan.ts: task actions no longer emit a misleading
  "unsupported_action" execute step; they execute via the
  execute_query tool events, not the legacy client-side path.
- agent_loop.rs: per-action task-contract rules in both the prompt
  augmentation and repair paths (query -> execute & answer from real
  data; exploreSchema -> list_tables/get_columns; executeAndExplain
  -> run current SQL & explain).
- i18n (en/zh-CN/zh-TW): new action labels, placeholders, a
  generateNoExec label for Agent mode, and a task-oriented agent
  modeHint.

es/it/ja/pt-BR have no `ai` section and fall back to `en`, matching
existing coverage.

* feat(ai): split Ask/Agent action menus with mode-aware defaults

Wire the new Agent task actions into the assistant UI so each mode
shows a distinct, intent-matching action set.

- actionButtons is now a computed returning Ask or Agent buttons
  based on assistantMode. Agent menu: query / exploreSchema /
  executeAndExplain / generate (labeled "生成但不执行" via
  generateNoExec). Ask menu is unchanged.
- Switching mode lands on that mode's default (Ask -> generate,
  Agent -> query); the shared `generate` is not carried across
  because its label/semantics differ per mode. Vector DBs stay on
  `generate` since their action menu is hidden and they lack SQL
  tools (no execute_query contract).
- External Ask-style triggers (Fix with AI, Explain history) switch
  to Ask mode when invoked from Agent mode so the action is valid
  and the menu reflects what runs.
- Reset the active action to the mode default after each send.

* test(ai): cover Agent task-action contract and mode/action mapping

Lock in the deterministic parts of the Ask/Agent split so only the
LLM-behavior criteria need manual verification.

Backend (agent_loop.rs):
- query contract instructs the LLM to call execute_query and is not
  treated as a SQL-producing action.
- exploreSchema contract points to list_tables/get_columns and says
  not to execute data queries.
- executeAndExplain contract tells the LLM to run the current SQL.
- task actions do not require a SQL deliverable (a conclusion without
  a fenced SQL block still satisfies the contract).
- query repair prompt also targets execute_query.

Frontend (aiActions.spec.ts):
- defaultActionForMode: Ask -> generate, Agent -> query (not generate).
- isValidActionForMode: generate valid in both; Ask-only actions
  rejected in Agent mode and vice versa.
- ASK_ACTIONS / AGENT_ACTIONS composition (Agent menu starts with
  query and still offers generate).

* fix(ai): correct action menu on mode-switched triggers and i18n gaps

Issues found during review of the Ask/Agent action split:

- [#I01] triggerAction (Fix with AI / Explain history) invoked from
  Agent mode switched to Ask and set the action, but the mode-switch
  watch then reset activeAction to the Ask default ("generate"),
  overwriting the action just set — so the menu showed "Generate SQL"
  during a fix. Add a suppressModeActionReset flag so programmatic
  mode switches don't clobber the explicitly-set action.
- [#C01] Remove dead `unsupported_action` reason: buildAiAgentPlan no
  longer produces it, so drop the type variant and the unreachable
  skippedTitleKey case.
- [#I02] es/it/ja/pt-BR were missing the new Agent action keys
  (query/exploreSchema/executeAndExplain/generateNoExec) and their
  placeholders, causing English fallback in the Agent menu. Add the
  translations to match each locale's existing style.

* test(ai): align app-tests with task-action split

- aiSkills: add query/exploreSchema/executeAndExplain to the expected
  action set; broaden the id check (new ids are not _sql-suffixed) and
  relax the userInstruction assertion (schema inspection need not mention SQL).
- aiAgentPlan: drop the unsupported_action skipped step for non-generate
  actions (#C01 removed it from the plan and the reason union); add coverage
  for task-oriented Agent actions not driving client-side execution.

* test(ai): pin locale in dialect prompt spec

buildSystemPrompt selects zh/en copy via currentLocale(), which reflects the
host navigator.language. The spec asserts English strings, so it failed on
zh-CN machines (e.g. Windows with a Chinese system locale) while passing on
CI's en-US runners. Pin the locale to en in beforeAll so the assertions are
deterministic regardless of the host OS locale.
2026-07-06 14:41:39 +08:00
Abeautifulsnow fe4908321e feat(ai): support editing sent user messages
* feat(ai): support editing sent user messages

Adds inline edit support for user messages in the AI chat panel.
Hover over a user message to reveal the edit button; confirming the
edit truncates all subsequent history and re-sends with the new content.

* fix(ai): fix IME composition and ref-focus regression in message edit

- Handle IME composition events in onEditKeydown to prevent accidental
  submission on Enter during CJK candidate selection
- Replace per-render :ref focus callback with nextTick + data attribute
  to avoid cursor jumping on every keystroke
- Extract visibleToActualIndex into aiMessageEdit.ts for testability
- Add 8 unit tests covering index mapping with contextSummary messages

* fix(ai): prevent data loss and mention pollution in message edit

- Guard connection/config before truncating messages to prevent silent data
  loss when send() bails early
- Clear selectedMentions before resend to prevent stale chips from polluting
  edited message content
2026-07-03 15:18:56 +08:00
Abeautifulsnow d6ef9f140a fix(ai): bound schema context and result preview to prevent oversized AI payloads (#2496)
* fix(ai): limit indexes and foreign keys per table in schema context

Prevent AI input token spikes caused by tables with large numbers of
indexes or foreign keys being fully serialized into the system prompt.

Apply a default cap of 10 indexes and 10 FKs per table in all three
schema-loading paths: focused_table mode, database mode, and
loadMentionedTableContext for @-mentioned tables.

Both limits are configurable via buildAiContext options
(maxIndexesPerTable, maxFksPerTable).

* fix(ai): truncate large column values in result preview

Prevent input token explosion when the active tab contains large text
or JSON fields (e.g. request_body, response_body in audit log tables).

formatResultPreview previously serialized each value without any length
limit, so 5 rows from a wide table with multi-KB text columns could
produce 100K+ tokens in the system prompt.

Cap each serialized value at 200 characters with an ellipsis suffix.
2026-07-03 12:04:00 +08:00
Abeautifulsnow e7dffeca37 fix(ai): tool call status cards, table overflow, streaming TextDelta
* fix(ai): merge tool call status cards

* fix(ai): constrain markdown table overflow

* fix(ai): restore streaming of answer text via TextDelta events

The on_chunk closure was missing live AgentEvent::TextDelta emission for text content, causing the AI answer text to appear all at once after the turn completed. Reasoning deltas were unaffected.

Root cause: commit c30033628 rewrote the on_chunk closure and accidentally dropped the TextDelta emit line while keeping ReasoningDelta intact.

Fix: restore TextDelta emit in on_chunk for incremental streaming, and remove the post-turn full-TextDelta workaround which would duplicate content.

* test(ai): extract chunk_to_events and add streaming event tests

Extract the event-generation logic from the on_chunk closure into a pure function chunk_to_events() to make it testable, and add 6 unit tests covering all chunk content combinations: text-only, reasoning-only, mixed, empty, and edge cases.

This ensures a regression like the one fixed in the previous commit (where TextDelta emission was dropped while ReasoningDelta was kept) would be caught by tests.
2026-07-02 18:49:50 +08:00
Abeautifulsnow a0754206d3 feat(ai-config): persist AI settings per provider (#2412)
## 背景说明
AI 设置原本只有一个配置槽,切换模型厂商时会覆盖之前填写的 endpoint、API Key、model 等信息。本次改动让每个模型厂商各自保存一份配置,并在设置页和对话窗口提供已配置状态与快速切换能力。

## 修改内容
- 新增 ai_provider_configs 存储表,用于按 provider 保存独立 AI 配置
- 新增 Tauri/Web API:保存和加载 provider 级 AI 配置
- 设置页 provider 下拉展示“当前/已配置”状态
- 设置页切换 provider 前会先保存当前表单编辑内容,避免未保存输入丢失
- 对话窗口模型选择器支持查看并切换已配置过的其他 provider
- provider 配置保存时强制 config.provider 与 provider key 一致,避免错位配置污染
- 所有语言补齐新增 i18n 文案

## 修复的问题
- 切换模型厂商时原厂商配置会丢失
- 设置页切换 provider 时本地表单编辑态可能未保存
- provider key 与 config.provider 不一致时可能激活错误厂商
- 对话窗口模型选择器只能看到当前 provider 的模型,不能看到其他已配置厂商

## 测试
- npx tsc --noEmit
- cargo check -p dbx-core
- cargo check -p dbx-web
- cargo check --manifest-path src-tauri/Cargo.toml
2026-07-02 14:24:57 +08:00
Abeautifulsnow d55a708d6a feat(query): add manual transaction controls 2026-07-02 01:30:31 +08:00
Abeautifulsnow ee883ce2b8 fix(driver): hide uninstall action for uninstalled PrestoSQL 2026-07-01 15:45:54 +08:00
Abeautifulsnow 8094f4901d fix(browser): ensure connection before mount loads 2026-06-29 12:05:46 +08:00
Abeautifulsnow 5f2b24d700 fix(ai): enforce SQL task contracts structurally instead of keyword heuristics
* fix: enforce agent task contracts

* fix(ai): enforce SQL task contracts structurally
2026-06-26 13:18:49 +08:00
Abeautifulsnow ebfc50e4ff fix(agent-loop): preserve output on exhaustion, interruption, and cancellation 2026-06-24 13:27:23 +08:00
Abeautifulsnow bbd3ccf864 fix(ai): add inline proposal confirmation buttons
* fix(ai): add quick proposal confirmation buttons (all locales)

When the assistant proposes an action, render Yes/No buttons below the
message so the user does not need to type a short reply — fixing the
issue where short replies caused the LLM to re-ask instead of executing.

- aiProposalDetect.ts: pure detectors for proposal sentences/short replies
- AiAssistant.vue: inline Yes/No buttons on last assistant proposal message
- ai.ts: system-prompt rule to skip re-confirmation on short affirmatives
- i18n: 3 keys added to all 7 locales (en/zh-CN/zh-TW/ja/es/it/pt-BR)

Tests: 55/55. TypeCheck: passed.

* fix(ai): add i18n keys and UI changes for proposal confirmation
2026-06-23 18:25:57 +08:00
Abeautifulsnow 629c92bf7e feat: prompt input history navigation with ↑/↓ arrow keys in AI assistant 2026-06-22 10:50:18 +08:00
Abeautifulsnow 320336e84e feat(ai): add inline model selector to AI assistant toolbar 2026-06-18 18:10:28 +08:00
Abeautifulsnow ec28005f20 feat(agent): safety check display
* fix(i18n): add missing agent tool step translations for zh-TW, pt-BR, it, ja

* propagate explainData to agent step items for ExplainPlanViewer

* feat(ai): show safety check result for execute_query tool steps
2026-06-16 13:56:16 +08:00
Abeautifulsnow a1f15f6c45 fix(ai): propagate explainData and add missing agent i18n keys
Thanks @Abeautifulsnow!
2026-06-16 10:28:35 +08:00
Abeautifulsnow c300336281 feat(ai): context window management and token usage tracking
* @
feat(ai): add conversation context management and token usage tracking (Phase 4)

## Background
Phase 4 of AI agent loop upgrade: token usage extraction from LLM responses,
cost estimation display, and automatic context window management (summarization
when approaching limits).

## Changes

### Backend (Rust)
- New token_usage::TokenUsage — cross-turn token accumulation
- New agent_loop::maybe_compact — proactive context compaction: token estimation
  → cut-point selection → LLM summarization → fallback summary
  → tool-pair integrity protection → drain/insert
- New agent_loop::context_window_for_model — auto-detect context window by model
- New agent_loop::is_context_length_error — detect upstream context-length errors
- New agent_loop::compact_tool_result_for_context — JSON/text sampling for large results
- Modified agent_loop::run_agent_loop — pre-turn compaction check, retry on context error
- Modified agent_events::AgentEnd — split total_tokens into input_tokens/output_tokens
- New agent_events::ContextCompacted — compaction event with metrics
- New AiConfig.context_window — user-configurable context window size
- New AiChatMessage.kind — context summary message marker
- Modified stream_with_tools & 3 provider stream functions — extract TokenUsage
  - Claude: message_start(input) + message_delta(output)
  - OpenAI: stream_options { include_usage } → final usage chunk
  - Gemini: usageMetadata per chunk, keep last

### Frontend (TypeScript/Vue)
- AiAssistant.vue: token + cost display row, estimateCost() with 7 model families,
  contextCompacted UI step, pendingCompaction deferred apply,
  messagesForAgentHistory post-compaction history reconstruction
- EditorSettingsDialog.vue: contextWindow input (min=1000, auto-detect)
- settingsStore.ts: AiConfig.contextWindow field
- tauri.ts: AgentEvent type updates, AiChatMessage.kind
- i18n: 6 new keys in en.ts and zh-CN.ts

## Fixed Issues
- messages[0] dropped from LLM context after compaction
- estimate_text_tokens hard threshold causing 2.8x estimate jump
- context_compacted event field semantics mismatch with frontend insert position
- validate_summary English-only keywords causing fallback on non-English LLMs
- Stale agentTokens after conversation switch
@

* remove cost computation logic
2026-06-15 18:55:22 +08:00
Abeautifulsnow d845a318c6 feat(ai-agent): Phase 3 — explain_query tool, parallel/sequential execution, DB gating (#1187)
- Add explain_query tool with structured EXPLAIN result, gated on supports_explain_plan()
- Add supports_sql_query() to gate execute_query/get_sample_data for non-SQL DBs (Redis, ES, MongoDB, etc.)
- Split agent loop tool dispatch: execute_query runs sequentially, all others run in parallel via join_all
- Wire explain_query result button to ExplainPlanViewer in AiAssistant + App.vue
- Fix O(n²) agentSteps rebuild: incremental O(1) push per event during streaming
- finally block falls back to full rebuild only when streaming push did not occur
2026-06-15 13:14:59 +08:00
runstone 094412d956 fix error 2026-06-12 19:00:27 +08:00
runstone 40f0f98540 Merge branch 'main' of https://github.com/Abeautifulsnow/dbx into feat/ai-agent-loop-phase1 2026-06-12 18:52:05 +08:00
runstone 7df7fd9235 feat(ai): add tool result collapsible UI and fix agent mode prompt
AiAssistant.vue:
- Tool call steps now support click-to-expand/collapse for SQL args
  and results (expandedSteps set); chevron rotates on open
- Remove fixed-open result display (was always visible, no toggle)
- Max result height raised to 48 (max-h-48) with scroll

ai.ts (buildModePromptLines agent branch):
- Replace vague "prioritize SQL" hint with explicit tool-use
  instruction: must call execute_query, not just emit SQL text
- List available tools (list_tables, get_columns, execute_query,
  get_sample_data) so LLM knows what it can call
- Clarify allowed statement types for execute_query
2026-06-12 18:27:28 +08:00
runstone 100124da3e feat(ai): Phase 2 SQL 风险分类 + Agent 模式工具调用结果渲染
后端:
  - 新增 sql_risk.rs:基于 sqlparser AST 的 SQL 风险分类(ReadOnly/Write/Ddl/Transaction)
  - agent_tools.rs:新增 execute_query 和 get_sample_data 工具,写操作/DDL 被风险分类阻止
  - agent_loop.rs:支持 is_agent_mode 参数,Agent 模式下暴露全部工具,Ask 模式仅暴露只读工具
  - agent_loop/web/tauri:mode 参数全链路传递(前端→HTTP→Tauri→Rust)

  前端:
  - AiAgentStepItem 接口扩展:toolName/toolArgs/toolResult/isError 字段
  - AiAssistant.vue:工具调用结果实时+最终渲染,SQL 查询结果/错误信息展示
  - ai.ts/http.ts/tauri.ts:mode 参数透传到后端
2026-06-12 17:42:23 +08:00
Abeautifulsnow 082e3bb4eb feat(ai): add agent tool calling loop 2026-06-12 13:18:36 +08:00