basic suggested action scaffolding

This commit is contained in:
Will Chen
2025-04-18 13:03:19 -07:00
parent b2e3631a29
commit 639b3a320c
10 changed files with 149 additions and 86 deletions

View File

@@ -1,6 +1,6 @@
import { useState, useEffect, useCallback } from "react";
import { IpcClient } from "@/ipc/ipc_client";
import type { Proposal, ProposalResult } from "@/lib/schemas"; // Import Proposal type
import type { CodeProposal, ProposalResult } from "@/lib/schemas"; // Import Proposal type
import { proposalResultAtom } from "@/atoms/proposalAtoms";
import { useAtom } from "jotai";
export function useProposal(chatId?: number | undefined) {
@@ -8,40 +8,35 @@ export function useProposal(chatId?: number | undefined) {
const [isLoading, setIsLoading] = useState<boolean>(false);
const [error, setError] = useState<string | null>(null);
const fetchProposal = useCallback(
async (innerChatId?: number) => {
chatId = chatId ?? innerChatId;
console.log("fetching proposal for chatId", chatId);
if (chatId === undefined) {
setProposalResult(null);
setIsLoading(false);
setError(null);
return;
}
setIsLoading(true);
const fetchProposal = useCallback(async () => {
if (chatId === undefined) {
setProposalResult(null);
setIsLoading(false);
setError(null);
setProposalResult(null); // Reset on new fetch
try {
// Type assertion might be needed depending on how IpcClient is typed
const result = (await IpcClient.getInstance().getProposal(
chatId
)) as ProposalResult | null;
return;
}
setIsLoading(true);
setError(null);
setProposalResult(null); // Reset on new fetch
try {
// Type assertion might be needed depending on how IpcClient is typed
const result = (await IpcClient.getInstance().getProposal(
chatId
)) as ProposalResult | null;
if (result) {
setProposalResult(result);
} else {
setProposalResult(null); // Explicitly set to null if IPC returns null
}
} catch (err: any) {
console.error("Error fetching proposal:", err);
setError(err.message || "Failed to fetch proposal");
setProposalResult(null); // Clear proposal data on error
} finally {
setIsLoading(false);
if (result) {
setProposalResult(result);
} else {
setProposalResult(null); // Explicitly set to null if IPC returns null
}
},
[chatId]
); // Depend on chatId
} catch (err: any) {
console.error("Error fetching proposal:", err);
setError(err.message || "Failed to fetch proposal");
setProposalResult(null); // Clear proposal data on error
} finally {
setIsLoading(false);
}
}, [chatId]); // Depend on chatId
useEffect(() => {
fetchProposal();
@@ -52,18 +47,10 @@ export function useProposal(chatId?: number | undefined) {
// };
}, [fetchProposal]); // Re-run effect if fetchProposal changes (due to chatId change)
const refreshProposal = useCallback(
(chatId?: number) => {
fetchProposal(chatId);
},
[fetchProposal]
);
return {
proposal: proposalResult?.proposal ?? null,
messageId: proposalResult?.messageId,
proposalResult: proposalResult,
isLoading,
error,
refreshProposal, // Expose the refresh function
refreshProposal: fetchProposal, // Expose the refresh function
};
}

View File

@@ -1,7 +1,13 @@
import { useState, useCallback } from "react";
import { IpcClient } from "@/ipc/ipc_client";
import { appOutputAtom, appUrlAtom, currentAppAtom } from "@/atoms/appAtoms";
import { useAtom, useSetAtom } from "jotai";
import {
appOutputAtom,
appUrlAtom,
currentAppAtom,
previewPanelKeyAtom,
selectedAppIdAtom,
} from "@/atoms/appAtoms";
import { useAtom, useAtomValue, useSetAtom } from "jotai";
import { App } from "@/ipc/ipc_types";
export function useRunApp() {
@@ -10,7 +16,8 @@ export function useRunApp() {
const [app, setApp] = useAtom(currentAppAtom);
const setAppOutput = useSetAtom(appOutputAtom);
const [appUrlObj, setAppUrlObj] = useAtom(appUrlAtom);
const setPreviewPanelKey = useSetAtom(previewPanelKeyAtom);
const appId = useAtomValue(selectedAppIdAtom);
const runApp = useCallback(async (appId: number) => {
setLoading(true);
try {
@@ -63,7 +70,10 @@ export function useRunApp() {
}
}, []);
const restartApp = useCallback(async (appId: number) => {
const restartApp = useCallback(async () => {
if (appId === null) {
return;
}
setLoading(true);
try {
const ipcClient = IpcClient.getInstance();
@@ -91,6 +101,7 @@ export function useRunApp() {
console.error(`Error restarting app ${appId}:`, error);
setError(error instanceof Error ? error : new Error(String(error)));
} finally {
setPreviewPanelKey((prevKey) => prevKey + 1);
setLoading(false);
}
}, []);

View File

@@ -16,6 +16,7 @@ import { selectedAppIdAtom } from "@/atoms/appAtoms";
import { useLoadVersions } from "./useLoadVersions";
import { showError } from "@/lib/toast";
import { useProposal } from "./useProposal";
import { useSearch } from "@tanstack/react-router";
export function getRandomString() {
return Math.random().toString(36).substring(2, 15);
@@ -31,7 +32,8 @@ export function useStreamChat() {
const { refreshApp } = useLoadApp(selectedAppId);
const setStreamCount = useSetAtom(chatStreamCountAtom);
const { refreshVersions } = useLoadVersions(selectedAppId);
const { refreshProposal } = useProposal();
const { id: chatId } = useSearch({ from: "/chat" });
const { refreshProposal } = useProposal(chatId);
const streamMessage = useCallback(
async ({
prompt,
@@ -91,7 +93,7 @@ export function useStreamChat() {
if (response.updatedFiles) {
setIsPreviewOpen(true);
}
refreshProposal(chatId);
refreshProposal();
// Keep the same as below
setIsStreaming(false);