@@ -206,9 +220,9 @@ function ChatInputActions() {
) : (
)}
- Review: foo bar changes
+ Review: {proposal.title}
- {securityRisks.length > 0 && (
+ {proposal.securityRisks.length > 0 && (
Security risks found
@@ -221,7 +235,8 @@ function ChatInputActions() {
className="px-8"
size="sm"
variant="outline"
- onClick={handleApprove}
+ onClick={onApprove}
+ disabled={!isApprovable}
>
Approve
@@ -230,7 +245,8 @@ function ChatInputActions() {
className="px-8"
size="sm"
variant="outline"
- onClick={handleReject}
+ onClick={onReject}
+ disabled={!isApprovable}
>
Reject
@@ -256,7 +272,7 @@ function ChatInputActions() {
Security Risks
- {securityRisks.map((risk, index) => (
+ {proposal.securityRisks.map((risk, index) => (
-
{risk.type === "warning" ? (
Files Changed
- {filesChanged.map((file, index) => (
+ {proposal.filesChanged.map((file, index) => (
-
chats.id, { onDelete: "cascade" }),
role: text("role", { enum: ["user", "assistant"] }).notNull(),
content: text("content").notNull(),
+ approvalState: text("approval_state", {
+ enum: ["approved", "rejected", "pending"],
+ }),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.default(sql`(unixepoch())`),
diff --git a/src/hooks/useProposal.ts b/src/hooks/useProposal.ts
new file mode 100644
index 0000000..3a460a3
--- /dev/null
+++ b/src/hooks/useProposal.ts
@@ -0,0 +1,44 @@
+import { useState, useEffect } from "react";
+import { IpcClient } from "@/ipc/ipc_client";
+import type { Proposal } from "@/lib/schemas"; // Import Proposal type
+
+export function useProposal(chatId: number | undefined) {
+ const [proposal, setProposal] = useState(null);
+ const [isLoading, setIsLoading] = useState(false);
+ const [error, setError] = useState(null);
+
+ useEffect(() => {
+ if (chatId === undefined) {
+ setProposal(null);
+ setIsLoading(false);
+ setError(null);
+ return;
+ }
+
+ const fetchProposal = async () => {
+ setIsLoading(true);
+ setError(null);
+ try {
+ const fetchedProposal = await IpcClient.getInstance().getProposal(
+ chatId
+ );
+ setProposal(fetchedProposal);
+ } catch (err: any) {
+ console.error("Error fetching proposal:", err);
+ setError(err.message || "Failed to fetch proposal");
+ setProposal(null); // Clear proposal on error
+ } finally {
+ setIsLoading(false);
+ }
+ };
+
+ fetchProposal();
+
+ // Cleanup function if needed (e.g., for aborting requests)
+ // return () => {
+ // // Abort logic here
+ // };
+ }, [chatId]); // Re-run effect if chatId changes
+
+ return { proposal, isLoading, error };
+}
diff --git a/src/ipc/handlers/proposal_handlers.ts b/src/ipc/handlers/proposal_handlers.ts
new file mode 100644
index 0000000..8d665d7
--- /dev/null
+++ b/src/ipc/handlers/proposal_handlers.ts
@@ -0,0 +1,47 @@
+import { ipcMain, type IpcMainInvokeEvent } from "electron";
+import type { Proposal } from "@/lib/schemas";
+
+// Placeholder Proposal data
+const placeholderProposal: Proposal = {
+ title: "Review: Example Refactoring (from IPC)",
+ securityRisks: [
+ {
+ type: "warning",
+ title: "Potential XSS Vulnerability",
+ description: "User input is directly rendered without sanitization.",
+ },
+ {
+ type: "danger",
+ title: "Hardcoded API Key",
+ description: "API key found in plain text in configuration file.",
+ },
+ ],
+ filesChanged: [
+ {
+ name: "ChatInput.tsx",
+ path: "src/components/chat/ChatInput.tsx",
+ summary: "Added review actions and details section.",
+ },
+ {
+ name: "api.ts",
+ path: "src/lib/api.ts",
+ summary: "Refactored API call structure.",
+ },
+ ],
+};
+
+const getProposalHandler = async (
+ _event: IpcMainInvokeEvent,
+ { chatId }: { chatId: number }
+): Promise => {
+ console.log(`IPC: get-proposal called for chatId: ${chatId}`);
+ // Simulate async operation
+ await new Promise((resolve) => setTimeout(resolve, 500)); // 500ms delay
+ return placeholderProposal;
+};
+
+// Function to register proposal-related handlers
+export function registerProposalHandlers() {
+ ipcMain.handle("get-proposal", getProposalHandler);
+ console.log("Registered proposal IPC handlers");
+}
diff --git a/src/ipc/ipc_client.ts b/src/ipc/ipc_client.ts
index f5ffb13..dcc655b 100644
--- a/src/ipc/ipc_client.ts
+++ b/src/ipc/ipc_client.ts
@@ -17,6 +17,7 @@ import type {
NodeSystemInfo,
Version,
} from "./ipc_types";
+import type { Proposal } from "@/lib/schemas";
import { showError } from "@/lib/toast";
export interface ChatStreamCallbacks {
@@ -614,6 +615,18 @@ export class IpcClient {
}
}
+ // Get proposal details
+ public async getProposal(chatId: number): Promise {
+ try {
+ const data = await this.ipcRenderer.invoke("get-proposal", { chatId });
+ // Assuming the main process returns data matching the Proposal interface
+ return data as Proposal;
+ } catch (error) {
+ showError(error);
+ throw error;
+ }
+ }
+
// Example methods for listening to events (if needed)
// public on(channel: string, func: (...args: any[]) => void): void {
}
diff --git a/src/ipc/ipc_host.ts b/src/ipc/ipc_host.ts
index b969bb7..e7d99cd 100644
--- a/src/ipc/ipc_host.ts
+++ b/src/ipc/ipc_host.ts
@@ -6,6 +6,7 @@ import { registerShellHandlers } from "./handlers/shell_handler";
import { registerDependencyHandlers } from "./handlers/dependency_handlers";
import { registerGithubHandlers } from "./handlers/github_handlers";
import { registerNodeHandlers } from "./handlers/node_handlers";
+import { registerProposalHandlers } from "./handlers/proposal_handlers";
export function registerIpcHandlers() {
// Register all IPC handlers by category
@@ -17,4 +18,5 @@ export function registerIpcHandlers() {
registerDependencyHandlers();
registerGithubHandlers();
registerNodeHandlers();
+ registerProposalHandlers();
}
diff --git a/src/lib/schemas.ts b/src/lib/schemas.ts
index 99e4936..fef934e 100644
--- a/src/lib/schemas.ts
+++ b/src/lib/schemas.ts
@@ -97,3 +97,23 @@ export const UserSettingsSchema = z.object({
* Type derived from the UserSettingsSchema
*/
export type UserSettings = z.infer;
+
+// Define interfaces for the props
+export interface SecurityRisk {
+ type: "warning" | "danger";
+ title: string;
+ description: string;
+}
+
+export interface FileChange {
+ name: string;
+ path: string;
+ summary: string;
+}
+
+// New Proposal interface
+export interface Proposal {
+ title: string;
+ securityRisks: SecurityRisk[];
+ filesChanged: FileChange[];
+}
diff --git a/src/preload.ts b/src/preload.ts
index 3fca189..40b5e50 100644
--- a/src/preload.ts
+++ b/src/preload.ts
@@ -38,6 +38,7 @@ const validInvokeChannels = [
"github:push",
"get-app-version",
"reload-env-path",
+ "get-proposal",
] as const;
// Add valid receive channels