- {description && (
-
{description}
- )}
- {markdown && !loading && cached && createdAt && (
-
- Generated {timeAgo(createdAt)}
-
- )}
- {markdown && !loading && cached && onReanalyze && (
-
-
- Re-analyze
-
- )}
+
+
+ {description && (
+ {description}
+ )}
+ {markdown && !loading && cached && createdAt && (
+
+ Generated {timeAgo(createdAt)}
+
+ )}
+ {markdown && !loading && cached && onReanalyze && (
+
+
+ Re-analyze
+
+ )}
+
+
+ Note: AI can make mistakes. Please verify responses and generated queries.
+
@@ -214,6 +219,53 @@ export function MarkdownRenderer({ content }: { content: string }) {
continue;
}
+ // Table
+ if (line.trim().startsWith("|") && line.includes("|", 1)) {
+ const tableLines: string[] = [];
+ while (i < lines.length && lines[i].trim().startsWith("|")) {
+ tableLines.push(lines[i].trim());
+ i++;
+ }
+
+ const parseRow = (rowStr: string) => {
+ const parts = rowStr.split("|");
+ if (parts.length > 0 && parts[0].trim() === "") parts.shift();
+ if (parts.length > 0 && parts[parts.length - 1].trim() === "") parts.pop();
+ return parts;
+ };
+
+ const headerCells = parseRow(tableLines[0]);
+ const bodyLines = tableLines.length > 2 ? tableLines.slice(2) : [];
+
+ elements.push(
+
+
+
+
+ {headerCells.map((cell, idx) => (
+
+ {renderInline(cell.trim())}
+
+ ))}
+
+
+
+ {bodyLines.map((rowLine, rowIdx) => (
+
+ {parseRow(rowLine).map((cell, idx) => (
+
+ {renderInline(cell.trim())}
+
+ ))}
+
+ ))}
+
+
+
+ );
+ continue;
+ }
+
// Blank line
if (!line.trim()) {
i++;
diff --git a/src/features/chart/components/ChartVisualization.tsx b/src/features/chart/components/ChartVisualization.tsx
index f490434..0d91e06 100644
--- a/src/features/chart/components/ChartVisualization.tsx
+++ b/src/features/chart/components/ChartVisualization.tsx
@@ -64,7 +64,7 @@ export const ChartVisualization = ({
type: c.type,
isPrimaryKey: c.isPrimaryKey,
})),
- });
+ }, { datasourceName: dbId });
setChartType(rec.chartType);
setXAxis(rec.xAxis);
setYAxis(rec.yAxis);
diff --git a/src/features/database/components/AIWorkspacePanel.tsx b/src/features/database/components/AIWorkspacePanel.tsx
new file mode 100644
index 0000000..8ea9f94
--- /dev/null
+++ b/src/features/database/components/AIWorkspacePanel.tsx
@@ -0,0 +1,87 @@
+import { Sparkles, Terminal, FileJson, Search, Database } from "lucide-react";
+import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
+import { Button } from "@/components/ui/button";
+import AIHistoryPanel from "@/features/ai/components/AIHistoryPanel";
+import { PanelType } from "@/components/layout/VerticalIconBar";
+
+interface AIWorkspacePanelProps {
+ dbId: string;
+ onNavigate: (panel: PanelType) => void;
+}
+
+export default function AIWorkspacePanel({ dbId, onNavigate }: AIWorkspacePanelProps) {
+ return (
+
+
+
+
+ AI Workspace
+
+
+ Central hub for AI-powered features for this database. Use the tools below to analyze data, build queries, and explore your schema using natural language.
+
+
+ Note: AI can make mistakes. Please verify responses and generated queries.
+
+
+
+
+
+
+
+
+ Natural Language to SQL
+
+
+ Write database queries using plain English sentences. Let AI generate the SQL for you.
+
+
+
+ onNavigate("sql-workspace")}>
+ Launch NL Query
+
+
+
+
+
+
+
+
+ Schema Analysis
+
+
+ Generate AI documentation and summaries for your entire database schema.
+
+
+
+ onNavigate("schema-explorer")}>
+ Go to Schema Explorer
+
+
+
+
+
+
+
+
+ Query Explanation
+
+
+ Highlight any complex SQL query in the workspace and let AI explain what it does step-by-step.
+
+
+
+ onNavigate("sql-workspace")}>
+ Open SQL Workspace
+
+
+
+
+
+
+ {/* Pass dbId so it strictly filters for this DB and hides the Global DB column */}
+
+
+
+ );
+}
diff --git a/src/features/settings/components/SettingsDialog.tsx b/src/features/settings/components/SettingsDialog.tsx
index 5caf027..ef14a31 100644
--- a/src/features/settings/components/SettingsDialog.tsx
+++ b/src/features/settings/components/SettingsDialog.tsx
@@ -1,5 +1,5 @@
import { useState } from "react";
-import { AISettings, AIHistoryPanel, CheckForUpdates, ColorVariant, DeveloperMode, ThemeMode, Version, AnalyticsSettings } from "@/features/settings/components";
+import { AISettings, CheckForUpdates, ColorVariant, DeveloperMode, ThemeMode, Version, AnalyticsSettings } from "@/features/settings/components";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
@@ -69,7 +69,6 @@ export function SettingsDialog({ open, onOpenChange }: SettingsDialogProps) {
{activeTab === "ai" && (
)}
diff --git a/src/features/settings/components/index.tsx b/src/features/settings/components/index.tsx
index 7df7d47..e3bbb26 100644
--- a/src/features/settings/components/index.tsx
+++ b/src/features/settings/components/index.tsx
@@ -6,5 +6,5 @@ export { default as AnalyticsSettings } from './AnalyticsSettings'
export { default as CheckForUpdates } from './CheckForUpdates'
export { default as Version } from './Version'
export { default as AISettings } from './AISettings'
-export { default as AIHistoryPanel } from '../../ai/components/AIHistoryPanel'
+
export { SettingsDialog } from './SettingsDialog'
\ No newline at end of file
diff --git a/src/features/workspace/components/ExplainQueryButton.tsx b/src/features/workspace/components/ExplainQueryButton.tsx
index dab13a2..bf500cd 100644
--- a/src/features/workspace/components/ExplainQueryButton.tsx
+++ b/src/features/workspace/components/ExplainQueryButton.tsx
@@ -8,10 +8,10 @@ import { aiService } from "@/services/bridge/ai";
interface ExplainQueryButtonProps {
sql: string;
disabled?: boolean;
- databaseName?: string;
+ dbId?: string;
}
-export function ExplainQueryButton({ sql, disabled, databaseName }: ExplainQueryButtonProps) {
+export function ExplainQueryButton({ sql, disabled, dbId }: ExplainQueryButtonProps) {
const { settings } = useAISettings();
const [open, setOpen] = useState(false);
const [loading, setLoading] = useState(false);
@@ -29,7 +29,7 @@ export function ExplainQueryButton({ sql, disabled, databaseName }: ExplainQuery
try {
const result = await aiService.explainQuery(settings, {
sql: sql.trim(),
- }, { skipCache, datasourceName: databaseName });
+ }, { skipCache, datasourceName: dbId });
setMarkdown(result.markdown);
setCached(result.cached);
setCreatedAt(result.createdAt);
diff --git a/src/features/workspace/components/NLQueryDialog.tsx b/src/features/workspace/components/NLQueryDialog.tsx
index 00f41a1..0dfe8bf 100644
--- a/src/features/workspace/components/NLQueryDialog.tsx
+++ b/src/features/workspace/components/NLQueryDialog.tsx
@@ -69,6 +69,9 @@ export const NLQueryDialog: React.FC
= ({
Natural Language to SQL
+
+ AI can make mistakes. Please verify the generated SQL before applying it to your workspace.
+
diff --git a/src/features/workspace/components/SQLWorkspacePanel.tsx b/src/features/workspace/components/SQLWorkspacePanel.tsx
index 5b909ee..c681b0f 100644
--- a/src/features/workspace/components/SQLWorkspacePanel.tsx
+++ b/src/features/workspace/components/SQLWorkspacePanel.tsx
@@ -180,6 +180,7 @@ const SQLWorkspacePanel = ({ dbId }: SQLWorkspacePanelProps) => {
return (
{/* NL to SQL Query */}
diff --git a/src/pages/DatabaseDetails.tsx b/src/pages/DatabaseDetails.tsx
index 2c9f26c..e10b6ed 100644
--- a/src/pages/DatabaseDetails.tsx
+++ b/src/pages/DatabaseDetails.tsx
@@ -27,6 +27,7 @@ import SQLWorkspacePanel from "@/features/workspace/components/SQLWorkspacePanel
import GitStatusPanel from "@/features/git/components/GitStatusPanel";
import GitStatusBar from "@/features/git/components/GitStatusBar";
import { MonitoringPanel } from "@/features/monitoring/components/MonitoringPanel";
+import AIWorkspacePanel from "@/features/database/components/AIWorkspacePanel";
import { ShortcutsHelp } from "@/components/shared/ShortcutsHelp";
import { ShortcutsTrigger } from "@/components/shared/ShortcutsTrigger";
import { MigrationSyncDialog } from "@/features/project/components/MigrationSyncDialog";
@@ -113,6 +114,7 @@ const DatabaseDetail = () => {
case "er-diagram": return
;
case "monitoring": return
;
case "git-status": return
;
+ case "ai-workspace": return
;
case "migrations": return
;
default:
return (
diff --git a/src/services/bridge/ai.ts b/src/services/bridge/ai.ts
index b1fc4e1..7cec32c 100644
--- a/src/services/bridge/ai.ts
+++ b/src/services/bridge/ai.ts
@@ -275,6 +275,7 @@ class AIService {
async getHistory(params?: {
feature?: string;
provider?: string;
+ datasource_id?: string;
limit?: number;
offset?: number;
}): Promise
{