When the user triggers SQL execution via shortcut/toolbar/context-menu
without a manual selection, a floating picker now surfaces the available
execution targets:
- "Current SQL" — the statement at the cursor
- "All SQL" — the entire editor content
Each candidate is highlighted as a preview decoration in the editor as
the user navigates the picker with arrow keys. Only a single entry is
shown when the cursor statement equals the full document.
前端 SQL 范围解析器 (sqlStatementRanges.ts) 按分号拆分语句,同时跳过
字符串、引号标识符、注释和美元引用体中的分隔符,与后端 dbx-core splitter
逻辑一致。选取器支持键盘导航、鼠标悬停高亮、Enter 确认、Esc/失焦取消。
Changes:
- sqlExecutionTarget.ts: add SqlExecutionCandidate, SqlExecutionOverride types
- sqlStatementRanges.ts: frontend SQL tokeniser (new, 848 lines)
- SqlExecutionTargetPicker.vue: accessible floating listbox (new, 109 lines)
- QueryEditor.vue: preview StateEffect/StateField; requestExecute() replaces
executeCurrentSql() to route through picker
- ContentArea.vue: expose requestQueryEditorExecute() to parent
- App.vue: toolbar + global shortcut → requestActiveEditorExecute()
- i18n: editor.executionPicker keys for all locales
- tests: 26 new unit tests for sqlStatementRanges (all 1121 tests pass)
The result used filter:false + validFor, which CodeMirror treats as
mutually exclusive — validFor is ignored, so the list froze and the
selection did not move while typing. Build the result with the default
built-in filter so typing narrows the list and moves the selection.
- add completion module: command names, two-stage subcommands, and key names
- key-name completion is async with a per-db cache capped at 1000 entries, cleared on disconnect
- gate key completion by argument position: stop after a single-key command is filled, keep suggesting for variadic key-list commands
- reuse the diagnostics command table as the data source, showing group/arity/safety
* 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
- 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
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
Move tool calling from non-streaming (complete) API calls to real
streaming SSE, so text, reasoning, and tool call arguments all arrive
incrementally — users see the AI think and act in real time.
- Extract ~370 lines of non-streaming tool-call functions from
agent_loop.rs (call_with_tools, call_openai_with_tools,
call_claude_with_tools, call_gemini_with_tools) and replace with
a single ai::stream_with_tools() dispatch call.
- Add streaming-with-tools infrastructure to ai.rs (~550 lines):
- StreamToolEvent enum: Chunk, ToolCallStart, ToolCallDelta,
ToolCallComplete — provider-agnostic, feeds into the
StreamingToolCallAccumulator
- stream_claude_with_tools(): parse SSE content_block_start/delta/
stop events, incremental input_json_delta for tool arguments
- stream_openai_with_tools(): parse SSE delta.tool_calls with
incremental function.arguments
- stream_gemini_with_tools(): parse SSE functionCall (Gemini
sends complete objects, not deltas — emit as one chunk)
- Cancellation support via tokio::select! in every streaming loop
- Extended timeout for reasoning models (600s vs 120s)
- StreamingToolCallAccumulator: collect partial tool call fragments
from streaming deltas, then deserialize into complete ToolCall
objects in index order once the stream ends.