diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.test.ts b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.test.ts similarity index 97% rename from apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.test.ts rename to apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.test.ts index a785379fd..f941edc63 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.test.ts +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.test.ts @@ -1,6 +1,6 @@ import type { ThreadMessage } from "@assistant-ui/react"; import { describe, expect, it } from "vitest"; -import { extractLatestQuery } from "./use-ai-table-filter-chat"; +import { extractLatestQuery } from "./use-ai-query-chat"; const fixture = (messages: Array<{ id: string, diff --git a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.ts b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.ts similarity index 62% rename from apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.ts rename to apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.ts index 8513caf16..7f45a5d67 100644 --- a/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-table-filter-chat.ts +++ b/apps/dashboard/src/app/(main)/(protected)/projects/[projectId]/analytics/tables/use-ai-query-chat.ts @@ -1,8 +1,8 @@ "use client"; -import { createAnalyticsTableFilterChatAdapter } from "@/components/vibe-coding"; +import { createAnalyticsQueryChatAdapter } from "@/components/vibe-coding"; import { getPublicEnvVar } from "@/lib/env"; -import { useLocalThreadRuntime, type ThreadMessage, type ToolCallContentPart } from "@assistant-ui/react"; +import { useLocalThreadRuntime, type AssistantRuntime, type ThreadMessage, type ToolCallContentPart } from "@assistant-ui/react"; import { useUser } from "@hexclave/next"; import { throwErr } from "@hexclave/shared/dist/utils/errors"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -58,50 +58,20 @@ export function extractLatestQuery(messages: readonly ThreadMessage[]): { return null; } -/** - * Extracts the trailing text of the last assistant message, so the UI can - * surface what the AI said when it answered without committing a query - * (e.g. "that's an aggregation, which this search can't display"). - */ -function extractLastAssistantText(messages: readonly ThreadMessage[]): string | null { - for (let i = messages.length - 1; i >= 0; i--) { - const msg = messages[i]!; - if (msg.role !== "assistant") continue; - for (let j = msg.content.length - 1; j >= 0; j--) { - const part = msg.content[j]!; - if (part.type === "text" && part.text.trim().length > 0) { - return part.text.trim(); - } - } - } - return null; -} - -export type AiTableFilterChat = { +export type AiQueryChat = { + runtime: AssistantRuntime, messages: readonly ThreadMessage[], isResponding: boolean, error: Error | null, sendMessage: (input: { text: string }) => void, clearMessages: () => void, - /** The last query the AI committed via the queryAnalytics tool (unvalidated). */ + stop: () => void, latestQuery: string | null, - /** - * Set when the last run finished WITHOUT committing a new query — holds the - * assistant's text reply (or null if there was none / a query was - * committed). Cleared on the next send/clear or via `dismissAssistantNote`. - */ - assistantNote: string | null, - dismissAssistantNote: () => void, + queryGeneration: number, + rewindToQuery: (query: string) => void, }; -/** - * AI chat thread backing the analytics table search bar's AI fallback. Uses - * the constrained `filter-analytics-table` system prompt scoped to the given - * table, so the AI only produces `SELECT * FROM