diff --git a/core/src/sqlite_workers/sqlite_database.rs b/core/src/sqlite_workers/sqlite_database.rs
index 7ae5397e9965..1046fea19789 100644
--- a/core/src/sqlite_workers/sqlite_database.rs
+++ b/core/src/sqlite_workers/sqlite_database.rs
@@ -54,7 +54,7 @@ impl SqliteDatabase {
let time_query_start = utils::now();
// Execute the query and collect results
- let mut stmt = conn.prepare(&query).unwrap();
+ let mut stmt = conn.prepare(&query)?;
let column_names = stmt
.column_names()
.into_iter()
diff --git a/front/components/assistant/conversation/TablesQueryAction.tsx b/front/components/assistant/conversation/TablesQueryAction.tsx
index 7722e2cd84e5..a1127350aac1 100644
--- a/front/components/assistant/conversation/TablesQueryAction.tsx
+++ b/front/components/assistant/conversation/TablesQueryAction.tsx
@@ -1,4 +1,5 @@
import {
+ Button,
ChevronDownIcon,
ChevronRightIcon,
Chip,
@@ -6,11 +7,15 @@ import {
Spinner,
Tooltip,
} from "@dust-tt/sparkle";
+import { CloudArrowDownIcon } from "@dust-tt/sparkle";
import type { TablesQueryActionType } from "@dust-tt/types";
+import { stringify } from "csv-stringify";
import dynamic from "next/dynamic";
-import { useState } from "react";
+import { useContext, useState } from "react";
import { amber, emerald, slate } from "tailwindcss/colors";
+import { SendNotificationsContext } from "@app/components/sparkle/Notification";
+
const SyntaxHighlighter = dynamic(
() => import("react-syntax-highlighter").then((mod) => mod.Light),
{ ssr: false }
@@ -21,6 +26,7 @@ export default function TablesQueryAction({
}: {
tablesQueryAction: TablesQueryActionType;
}) {
+ const sendNotification = useContext(SendNotificationsContext);
const [isOutputExpanded, setIsOutputExpanded] = useState(false);
// Extracting question from the params
@@ -42,6 +48,39 @@ export default function TablesQueryAction({
return t.length > maxLength ? t.substring(0, maxLength) + "..." : t;
};
+ const handleDownload = () => {
+ const results =
+ output &&
+ "results" in output &&
+ Array.isArray(output?.results) &&
+ output?.results;
+
+ if (!results) {
+ return;
+ }
+
+ const queryTitle =
+ (output && "query_title" in output && output?.query_title) ??
+ "query_results";
+
+ stringify(results, { header: true }, (err, output) => {
+ if (err) {
+ sendNotification({
+ title: "Error Downloading CSV",
+ type: "error",
+ description: `An error occurred while downloading the CSV: ${err}`,
+ });
+ return;
+ }
+ const blob = new Blob([output], { type: "text/csv" });
+ const url = URL.createObjectURL(blob);
+ const a = document.createElement("a");
+ a.href = url;
+ a.download = `${queryTitle}.csv`;
+ a.click();
+ });
+ };
+
return (
<>
{question && (
@@ -52,6 +91,20 @@ export default function TablesQueryAction({