Add description (optional) to SQL query
This commit is contained in:
@@ -38,6 +38,7 @@ import {
|
|||||||
SuggestedAction,
|
SuggestedAction,
|
||||||
ProposalResult,
|
ProposalResult,
|
||||||
FileChange,
|
FileChange,
|
||||||
|
SqlQuery,
|
||||||
} from "@/lib/schemas";
|
} from "@/lib/schemas";
|
||||||
import type { Message } from "@/ipc/ipc_types";
|
import type { Message } from "@/ipc/ipc_types";
|
||||||
import { isPreviewOpenAtom } from "@/atoms/viewAtoms";
|
import { isPreviewOpenAtom } from "@/atoms/viewAtoms";
|
||||||
@@ -547,7 +548,7 @@ function ProposalSummary({
|
|||||||
packagesAdded = [],
|
packagesAdded = [],
|
||||||
filesChanged = [],
|
filesChanged = [],
|
||||||
}: {
|
}: {
|
||||||
sqlQueries?: string[];
|
sqlQueries?: Array<SqlQuery>;
|
||||||
serverFunctions?: FileChange[];
|
serverFunctions?: FileChange[];
|
||||||
packagesAdded?: string[];
|
packagesAdded?: string[];
|
||||||
filesChanged?: FileChange[];
|
filesChanged?: FileChange[];
|
||||||
@@ -600,9 +601,12 @@ function ProposalSummary({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SQL Query item with expandable functionality
|
// SQL Query item with expandable functionality
|
||||||
function SqlQueryItem({ query }: { query: string }) {
|
function SqlQueryItem({ query }: { query: SqlQuery }) {
|
||||||
const [isExpanded, setIsExpanded] = useState(false);
|
const [isExpanded, setIsExpanded] = useState(false);
|
||||||
|
|
||||||
|
const queryContent = query.content;
|
||||||
|
const queryDescription = query.description;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className="bg-(--background-lightest) hover:bg-(--background-lighter) rounded-lg px-3 py-2 border border-border cursor-pointer"
|
className="bg-(--background-lightest) hover:bg-(--background-lighter) rounded-lg px-3 py-2 border border-border cursor-pointer"
|
||||||
@@ -611,7 +615,9 @@ function SqlQueryItem({ query }: { query: string }) {
|
|||||||
<div className="flex items-center justify-between">
|
<div className="flex items-center justify-between">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Database size={16} className="text-muted-foreground flex-shrink-0" />
|
<Database size={16} className="text-muted-foreground flex-shrink-0" />
|
||||||
<span className="text-sm font-medium">SQL Query</span>
|
<span className="text-sm font-medium">
|
||||||
|
{queryDescription || "SQL Query"}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{isExpanded ? (
|
{isExpanded ? (
|
||||||
@@ -623,7 +629,9 @@ function SqlQueryItem({ query }: { query: string }) {
|
|||||||
</div>
|
</div>
|
||||||
{isExpanded && (
|
{isExpanded && (
|
||||||
<div className="mt-2 text-xs max-h-[200px] overflow-auto">
|
<div className="mt-2 text-xs max-h-[200px] overflow-auto">
|
||||||
<CodeHighlight className="language-sql ">{query}</CodeHighlight>
|
<CodeHighlight className="language-sql ">
|
||||||
|
{queryContent}
|
||||||
|
</CodeHighlight>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -14,16 +14,19 @@ import { CustomTagState } from "./stateTypes";
|
|||||||
interface DyadExecuteSqlProps {
|
interface DyadExecuteSqlProps {
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
node?: any;
|
node?: any;
|
||||||
|
description?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DyadExecuteSql: React.FC<DyadExecuteSqlProps> = ({
|
export const DyadExecuteSql: React.FC<DyadExecuteSqlProps> = ({
|
||||||
children,
|
children,
|
||||||
node,
|
node,
|
||||||
|
description,
|
||||||
}) => {
|
}) => {
|
||||||
const [isContentVisible, setIsContentVisible] = useState(false);
|
const [isContentVisible, setIsContentVisible] = useState(false);
|
||||||
const state = node?.properties?.state as CustomTagState;
|
const state = node?.properties?.state as CustomTagState;
|
||||||
const inProgress = state === "pending";
|
const inProgress = state === "pending";
|
||||||
const aborted = state === "aborted";
|
const aborted = state === "aborted";
|
||||||
|
const queryDescription = description || node?.properties?.description;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -40,7 +43,7 @@ export const DyadExecuteSql: React.FC<DyadExecuteSqlProps> = ({
|
|||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<Database size={16} />
|
<Database size={16} />
|
||||||
<span className="text-gray-700 dark:text-gray-300 font-medium text-sm">
|
<span className="text-gray-700 dark:text-gray-300 font-medium text-sm">
|
||||||
SQL Query
|
{queryDescription || "SQL Query"}
|
||||||
</span>
|
</span>
|
||||||
{inProgress && (
|
{inProgress && (
|
||||||
<div className="flex items-center text-amber-600 text-xs">
|
<div className="flex items-center text-amber-600 text-xs">
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import type {
|
|||||||
CodeProposal,
|
CodeProposal,
|
||||||
FileChange,
|
FileChange,
|
||||||
ProposalResult,
|
ProposalResult,
|
||||||
|
SqlQuery,
|
||||||
} from "../../lib/schemas";
|
} from "../../lib/schemas";
|
||||||
import { db } from "../../db";
|
import { db } from "../../db";
|
||||||
import { messages } from "../../db/schema";
|
import { messages } from "../../db/schema";
|
||||||
@@ -105,7 +106,11 @@ const getProposalHandler = async (
|
|||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
// Check if we have enough information to create a proposal
|
// Check if we have enough information to create a proposal
|
||||||
if (filesChanged.length > 0 || packagesAdded.length > 0) {
|
if (
|
||||||
|
filesChanged.length > 0 ||
|
||||||
|
packagesAdded.length > 0 ||
|
||||||
|
proposalExecuteSqlQueries.length > 0
|
||||||
|
) {
|
||||||
const proposal: CodeProposal = {
|
const proposal: CodeProposal = {
|
||||||
type: "code-proposal",
|
type: "code-proposal",
|
||||||
// Use parsed title or a default title if summary tag is missing but write tags exist
|
// Use parsed title or a default title if summary tag is missing but write tags exist
|
||||||
@@ -113,7 +118,10 @@ const getProposalHandler = async (
|
|||||||
securityRisks: [], // Keep empty
|
securityRisks: [], // Keep empty
|
||||||
filesChanged,
|
filesChanged,
|
||||||
packagesAdded,
|
packagesAdded,
|
||||||
sqlQueries: proposalExecuteSqlQueries,
|
sqlQueries: proposalExecuteSqlQueries.map((query) => ({
|
||||||
|
content: query.content,
|
||||||
|
description: query.description,
|
||||||
|
})),
|
||||||
};
|
};
|
||||||
logger.log(
|
logger.log(
|
||||||
"Generated code proposal. title=",
|
"Generated code proposal. title=",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
executeSupabaseSql,
|
executeSupabaseSql,
|
||||||
} from "../../supabase_admin/supabase_management_client";
|
} from "../../supabase_admin/supabase_management_client";
|
||||||
import { isServerFunction } from "../../supabase_admin/supabase_utils";
|
import { isServerFunction } from "../../supabase_admin/supabase_utils";
|
||||||
|
import { SqlQuery } from "../../lib/schemas";
|
||||||
|
|
||||||
const readFile = fs.promises.readFile;
|
const readFile = fs.promises.readFile;
|
||||||
const logger = log.scope("response_processor");
|
const logger = log.scope("response_processor");
|
||||||
@@ -108,14 +109,18 @@ export function getDyadChatSummaryTag(fullResponse: string): string | null {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDyadExecuteSqlTags(fullResponse: string): string[] {
|
export function getDyadExecuteSqlTags(fullResponse: string): SqlQuery[] {
|
||||||
const dyadExecuteSqlRegex =
|
const dyadExecuteSqlRegex =
|
||||||
/<dyad-execute-sql>([\s\S]*?)<\/dyad-execute-sql>/g;
|
/<dyad-execute-sql([^>]*)>([\s\S]*?)<\/dyad-execute-sql>/g;
|
||||||
|
const descriptionRegex = /description="([^"]+)"/;
|
||||||
let match;
|
let match;
|
||||||
const queries: string[] = [];
|
const queries: { content: string; description?: string }[] = [];
|
||||||
|
|
||||||
while ((match = dyadExecuteSqlRegex.exec(fullResponse)) !== null) {
|
while ((match = dyadExecuteSqlRegex.exec(fullResponse)) !== null) {
|
||||||
let content = match[1].trim();
|
const attributesString = match[1] || "";
|
||||||
|
let content = match[2].trim();
|
||||||
|
const descriptionMatch = descriptionRegex.exec(attributesString);
|
||||||
|
const description = descriptionMatch?.[1];
|
||||||
|
|
||||||
// Handle markdown code blocks if present
|
// Handle markdown code blocks if present
|
||||||
const contentLines = content.split("\n");
|
const contentLines = content.split("\n");
|
||||||
@@ -127,7 +132,7 @@ export function getDyadExecuteSqlTags(fullResponse: string): string[] {
|
|||||||
}
|
}
|
||||||
content = contentLines.join("\n");
|
content = contentLines.join("\n");
|
||||||
|
|
||||||
queries.push(content);
|
queries.push({ content, description });
|
||||||
}
|
}
|
||||||
|
|
||||||
return queries;
|
return queries;
|
||||||
@@ -209,11 +214,11 @@ export async function processFullResponseActions(
|
|||||||
try {
|
try {
|
||||||
const result = await executeSupabaseSql({
|
const result = await executeSupabaseSql({
|
||||||
supabaseProjectId: chatWithApp.app.supabaseProjectId!,
|
supabaseProjectId: chatWithApp.app.supabaseProjectId!,
|
||||||
query,
|
query: query.content,
|
||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errors.push({
|
errors.push({
|
||||||
message: `Failed to execute SQL query: ${query}`,
|
message: `Failed to execute SQL query: ${query.content}`,
|
||||||
error: error,
|
error: error,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,13 +132,18 @@ export interface FileChange {
|
|||||||
isServerFunction: boolean;
|
isServerFunction: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SqlQuery {
|
||||||
|
content: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
export interface CodeProposal {
|
export interface CodeProposal {
|
||||||
type: "code-proposal";
|
type: "code-proposal";
|
||||||
title: string;
|
title: string;
|
||||||
securityRisks: SecurityRisk[];
|
securityRisks: SecurityRisk[];
|
||||||
filesChanged: FileChange[];
|
filesChanged: FileChange[];
|
||||||
packagesAdded: string[];
|
packagesAdded: string[];
|
||||||
sqlQueries: string[];
|
sqlQueries: SqlQuery[];
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SuggestedAction {
|
export interface SuggestedAction {
|
||||||
|
|||||||
@@ -89,12 +89,14 @@ function Login() {
|
|||||||
|
|
||||||
## Database
|
## Database
|
||||||
|
|
||||||
If the user wants to use the database, use the following code:
|
If the user wants to use the database, use the following syntax:
|
||||||
|
|
||||||
<dyad-execute-sql>
|
<dyad-execute-sql description="Get all users">
|
||||||
SELECT * FROM users;
|
SELECT * FROM users;
|
||||||
</dyad-execute-sql>
|
</dyad-execute-sql>
|
||||||
|
|
||||||
|
The description should be a short description of what the code is doing and be understandable by semi-technical users.
|
||||||
|
|
||||||
You will need to setup the database schema.
|
You will need to setup the database schema.
|
||||||
|
|
||||||
## Creating User Profiles
|
## Creating User Profiles
|
||||||
@@ -103,7 +105,7 @@ If the user wants to create a user profile, use the following code:
|
|||||||
|
|
||||||
### Create profiles table in public schema
|
### Create profiles table in public schema
|
||||||
|
|
||||||
<dyad-execute-sql>
|
<dyad-execute-sql description="Create profiles table in public schema">
|
||||||
CREATE TABLE public.profiles (
|
CREATE TABLE public.profiles (
|
||||||
id UUID NOT NULL REFERENCES auth.users ON DELETE CASCADE,
|
id UUID NOT NULL REFERENCES auth.users ON DELETE CASCADE,
|
||||||
first_name TEXT,
|
first_name TEXT,
|
||||||
@@ -130,7 +132,7 @@ create policy "Users can update own profile." on profiles for update using ( aut
|
|||||||
|
|
||||||
### Function to insert profile when user signs up
|
### Function to insert profile when user signs up
|
||||||
|
|
||||||
<dyad-execute-sql>
|
<dyad-execute-sql description="Create function to insert profile when user signs up">
|
||||||
CREATE FUNCTION public.handle_new_user()
|
CREATE FUNCTION public.handle_new_user()
|
||||||
RETURNS TRIGGER
|
RETURNS TRIGGER
|
||||||
LANGUAGE PLPGSQL
|
LANGUAGE PLPGSQL
|
||||||
|
|||||||
Reference in New Issue
Block a user