From 779249cbbdcb6f72e6a142b450af711293e2c3d8 Mon Sep 17 00:00:00 2001 From: Cyber MacGeddon Date: Mon, 23 Feb 2026 23:42:53 +0000 Subject: [PATCH] Added row embedding support --- package-lock.json | 30 +-- package.json | 6 +- src/components/agents/EditDialog.tsx | 48 +++- .../RowEmbeddingsQueryTab.tsx | 238 ++++++++++++++++++ src/pages/StructuredQueryPage.tsx | 11 +- 5 files changed, 312 insertions(+), 21 deletions(-) create mode 100644 src/components/structured-query/RowEmbeddingsQueryTab.tsx diff --git a/package-lock.json b/package-lock.json index d824a292..ec1324f1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,9 +13,9 @@ "@msgpack/msgpack": "^3.1.1", "@tanstack/react-query": "^5.80.3", "@tanstack/react-table": "^8.21.3", - "@trustgraph/client": "^1.4.0", - "@trustgraph/react-provider": "^1.3.0", - "@trustgraph/react-state": "^1.4.0", + "@trustgraph/client": "^1.4.2", + "@trustgraph/react-provider": "^1.4.0", + "@trustgraph/react-state": "^1.4.1", "@types/dagre": "^0.7.53", "compute-cosine-similarity": "^1.1.0", "dagre": "^0.8.5", @@ -2573,29 +2573,29 @@ } }, "node_modules/@trustgraph/client": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@trustgraph/client/-/client-1.4.0.tgz", - "integrity": "sha512-qz4dlI61LQISNfQib8JymNu/sM4wQymtkidEOVybhSXcD39ZDETj4VI/BN41qjiMegKC1WJxKFYDFo6D9au/yQ==", + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@trustgraph/client/-/client-1.4.2.tgz", + "integrity": "sha512-RFAfyfFvJuepvhzmb09c+sxFaSwFdGRZzLqsRtkoxNd+V9jKcc8X8NiAGYzvLWZydP97oBXu91WAN//b5TNZcg==", "license": "Apache-2.0" }, "node_modules/@trustgraph/react-provider": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@trustgraph/react-provider/-/react-provider-1.3.0.tgz", - "integrity": "sha512-pqMRo6PhR49mBnPUA17/Zjq2H31ZLTjk2yma1Ug+yCuh+DASRbvHzkTNXBWi8MFM9ifDP3+jcHapCFuBRDxvLg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@trustgraph/react-provider/-/react-provider-1.4.0.tgz", + "integrity": "sha512-CRtwrbzEOiKoAekXpjIhz8jbvNbaw6Fm0E2EgLnVp5Jf/6GVfPJ6v3eeqG4Z0AlO23cq8k0j88i+nxGI6llQIQ==", "license": "Apache-2.0", "peerDependencies": { - "@trustgraph/client": "^1.3.0", + "@trustgraph/client": "^1.4.0", "react": "^18.0.0 || ^19.0.0" } }, "node_modules/@trustgraph/react-state": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@trustgraph/react-state/-/react-state-1.4.0.tgz", - "integrity": "sha512-WFenhkzQBXViCQAdMQSQjOt+dJYRgKOEwXQ6SstUVfq2a/ZU//GB7juhLKXa5yaE1ymRIin66+XbSOwbzAHBfA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@trustgraph/react-state/-/react-state-1.4.1.tgz", + "integrity": "sha512-/3iimm0wS6hd5pJGR4/Q5ffCdl3ijMl4ezlApsbM8BTBVD8LyxN0L+EO+aIBeE4xrqDpEBt9HmK8HjrnrjAq3Q==", "license": "MIT", "dependencies": { - "@trustgraph/client": "^1.3.0", - "@trustgraph/react-provider": "^1.3.0", + "@trustgraph/client": "^1.4.1", + "@trustgraph/react-provider": "^1.4.0", "compute-cosine-similarity": "^1.1.0", "uuid": "^11.0.3" }, diff --git a/package.json b/package.json index 9e9b0faf..9ff13533 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,9 @@ "@msgpack/msgpack": "^3.1.1", "@tanstack/react-query": "^5.80.3", "@tanstack/react-table": "^8.21.3", - "@trustgraph/client": "^1.4.0", - "@trustgraph/react-provider": "^1.3.0", - "@trustgraph/react-state": "^1.4.0", + "@trustgraph/client": "^1.4.2", + "@trustgraph/react-provider": "^1.4.0", + "@trustgraph/react-state": "^1.4.1", "@types/dagre": "^0.7.53", "compute-cosine-similarity": "^1.1.0", "dagre": "^0.8.5", diff --git a/src/components/agents/EditDialog.tsx b/src/components/agents/EditDialog.tsx index 4c2f01ad..ec5dfb4d 100644 --- a/src/components/agents/EditDialog.tsx +++ b/src/components/agents/EditDialog.tsx @@ -11,6 +11,7 @@ import { usePrompts } from "@trustgraph/react-state"; import SelectField from "../common/SelectField"; import TextAreaField from "../common/TextAreaField"; import TextField from "../common/TextField"; +import NumberField from "../common/NumberField"; import ChipInputField from "../common/ChipInputField"; import { toaster } from "../ui/toaster"; import EditableArgumentsTable from "./EditableArgumentsTable"; @@ -29,6 +30,9 @@ const EditDialog = ({ open, onOpenChange, onComplete, id, create }) => { const [templateId, setTemplateId] = useState(""); const [mcpToolId, setMcpToolId] = useState(""); const [collection, setCollection] = useState(""); + const [schemaName, setSchemaName] = useState(""); + const [indexName, setIndexName] = useState(""); + const [limit, setLimit] = useState(10); const [group, setGroup] = useState([]); const [state, setState] = useState(""); const [applicableStates, setApplicableStates] = useState([]); @@ -56,6 +60,10 @@ const EditDialog = ({ open, onOpenChange, onComplete, id, create }) => { setMcpToolId(x.mcp_tool_id || x["mcp-tool"] || ""); // Handle collection attribute for knowledge-query tools setCollection(x.collection || ""); + // Handle row-embeddings-query fields + setSchemaName(x["schema-name"] || ""); + setIndexName(x["index-name"] || ""); + setLimit(x.limit || 10); // Handle new optional fields setGroup(x.group || []); setState(x.state || ""); @@ -87,6 +95,12 @@ const EditDialog = ({ open, onOpenChange, onComplete, id, create }) => { description: "Execute natural language questions against records in a structured data / object store", }, + { + value: "row-embeddings-query", + label: "Row Embeddings Query", + description: + "Semantic search on structured data indexes using vector similarity", + }, { value: "mcp-tool", label: "MCP Tool", @@ -125,8 +139,12 @@ const EditDialog = ({ open, onOpenChange, onComplete, id, create }) => { arguments: args, ...(type === "prompt" && templateId && { template: templateId }), ...(type === "mcp-tool" && mcpToolId && { "mcp-tool": mcpToolId }), - ...((type === "knowledge-query" || type === "structured-query") && + ...((type === "knowledge-query" || type === "structured-query" || type === "row-embeddings-query") && collection && { collection: collection }), + // Row embeddings query specific fields + ...(type === "row-embeddings-query" && schemaName && { "schema-name": schemaName }), + ...(type === "row-embeddings-query" && indexName && { "index-name": indexName }), + ...(type === "row-embeddings-query" && { limit: limit }), ...(group && group.length > 0 && { group: group }), ...(state && { state: state }), ...(applicableStates && @@ -253,7 +271,7 @@ const EditDialog = ({ open, onOpenChange, onComplete, id, create }) => { /> )} - {(type === "knowledge-query" || type === "structured-query") && ( + {(type === "knowledge-query" || type === "structured-query" || type === "row-embeddings-query") && ( { /> )} + {type === "row-embeddings-query" && ( + <> + setSchemaName(v)} + required={true} + /> + setIndexName(v)} + required={false} + /> + setLimit(v)} + minValue={1} + maxValue={100} + /> + + )} + (); + +const columns = [ + columnHelper.accessor("index_name", { + header: "Index Name", + cell: (info) => {info.getValue()}, + }), + columnHelper.accessor("index_value", { + header: "Index Value", + cell: (info) => {info.getValue()}, + }), + columnHelper.accessor("text", { + header: "Text", + cell: (info) => ( + + {info.getValue()} + + ), + }), + columnHelper.accessor("score", { + header: "Score", + cell: (info) => ( + + {info.getValue().toFixed(4)} + + ), + }), +]; + +const RowEmbeddingsQueryTab: React.FC = () => { + const [query, setQuery] = useState(""); + const [schemaName, setSchemaName] = useState(""); + const [indexName, setIndexName] = useState(""); + const [limit, setLimit] = useState(10); + + const rowEmbeddingsQuery = useRowEmbeddingsQuery(); + const { schemas, schemasLoading } = useSchemas(); + + // Create schema options for dropdown + const schemaItems = useMemo(() => { + if (!schemas || schemas.length === 0) return []; + return schemas.map(([id]: [string, unknown]) => ({ + value: id, + label: id, + description: id, + })); + }, [schemas]); + + const handleSubmit = () => { + if (!query.trim() || !schemaName.trim()) return; + + rowEmbeddingsQuery.executeQuery({ + query: query.trim(), + schemaName: schemaName.trim(), + indexName: indexName.trim() || undefined, + limit: limit, + }); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.shiftKey) { + e.preventDefault(); + handleSubmit(); + } + }; + + // Transform matches for table display + const tableData: RowEmbeddingsResultRow[] = useMemo(() => { + return rowEmbeddingsQuery.matches.map((match) => ({ + index_name: match.index_name, + index_value: match.index_value.join(", "), + text: match.text, + score: match.score, + })); + }, [rowEmbeddingsQuery.matches]); + + // Create the table instance + const table = useReactTable({ + data: tableData, + columns, + getCoreRowModel: getCoreRowModel(), + getSortedRowModel: getSortedRowModel(), + }); + + return ( + + + + Semantic Search on Structured Data + + + Search for records in structured data indexes using semantic similarity. + Enter a query and select a schema to search within. + + + + + {schemaItems.length > 0 ? ( + setSchemaName(values[0] || "")} + items={schemaItems} + /> + ) : ( + + )} + + + + + + + + + + + + + + + + + {/* Error Display */} + {rowEmbeddingsQuery.error && ( + + + Query Error + +