Support add dependencies as part of approval workflow

This commit is contained in:
Will Chen
2025-04-21 16:07:40 -07:00
parent 02f1db7791
commit b07defc9b8
10 changed files with 212 additions and 157 deletions

View File

@@ -9,6 +9,7 @@ import {
FileText,
Check,
Loader2,
Package,
} from "lucide-react";
import type React from "react";
import { useCallback, useEffect, useRef, useState } from "react";
@@ -427,26 +428,54 @@ function ChatInputActions({
</ul>
</div>
)}
{proposal.packagesAdded?.length > 0 && (
<div className="mb-3">
<h4 className="font-semibold mb-1">Packages Added</h4>
<ul className="space-y-1">
{proposal.packagesAdded.map((pkg, index) => (
<li
key={index}
className="flex items-center space-x-2"
onClick={() => {
IpcClient.getInstance().openExternalUrl(
`https://www.npmjs.com/package/${pkg}`
);
}}
>
<Package
size={16}
className="text-muted-foreground flex-shrink-0"
/>
<span className="cursor-pointer text-blue-500 hover:text-blue-700 dark:text-blue-400 dark:hover:text-blue-300">
{pkg}
</span>
</li>
))}
</ul>
</div>
)}
<div>
<h4 className="font-semibold mb-1">Files Changed</h4>
<ul className="space-y-1">
{proposal.filesChanged.map((file, index) => (
<li key={index} className="flex items-center space-x-2">
<FileText
size={16}
className="text-muted-foreground flex-shrink-0"
/>
<span title={file.path} className="truncate cursor-default">
{file.name}
</span>
<span className="text-muted-foreground text-xs truncate">
- {file.summary}
</span>
</li>
))}
</ul>
</div>
{proposal.filesChanged?.length > 0 && (
<div>
<h4 className="font-semibold mb-1">Files Changed</h4>
<ul className="space-y-1">
{proposal.filesChanged.map((file, index) => (
<li key={index} className="flex items-center space-x-2">
<FileText
size={16}
className="text-muted-foreground flex-shrink-0"
/>
<span title={file.path} className="truncate cursor-default">
{file.name}
</span>
<span className="text-muted-foreground text-xs truncate">
- {file.summary}
</span>
</li>
))}
</ul>
</div>
)}
</div>
)}
</div>

View File

@@ -29,44 +29,9 @@ export const DyadAddDependency: React.FC<DyadAddDependencyProps> = ({
// Extract package attribute from the node if available
const packages = node?.properties?.packages?.split(" ") || "";
const [isInstalling, setIsInstalling] = useState(false);
const [error, setError] = useState<string | null>(null);
const selectedChatId = useAtomValue(selectedChatIdAtom);
const [messages, setMessages] = useAtom(chatMessagesAtom);
const { streamMessage, isStreaming } = useStreamChat();
const [isContentVisible, setIsContentVisible] = useState(false);
const hasChildren = !!children;
const handleInstall = async () => {
if (!packages || !selectedChatId) return;
setIsInstalling(true);
setError(null);
try {
const ipcClient = IpcClient.getInstance();
await ipcClient.addDependency({
chatId: selectedChatId,
packages,
});
// Refresh the chat messages
const chat = await IpcClient.getInstance().getChat(selectedChatId);
setMessages(chat.messages);
await streamMessage({
prompt: `I've installed ${packages.join(", ")}. Keep going.`,
chatId: selectedChatId,
});
} catch (err) {
setError("There was an error installing this package.");
const chat = await IpcClient.getInstance().getChat(selectedChatId);
setMessages(chat.messages);
} finally {
setIsInstalling(false);
}
};
return (
<div
className={`bg-(--background-lightest) dark:bg-gray-900 hover:bg-(--background-lighter) rounded-lg px-4 py-3 border my-2 ${
@@ -139,27 +104,6 @@ export const DyadAddDependency: React.FC<DyadAddDependencyProps> = ({
</div>
</div>
)}
{/* Always show install button if there are no children */}
{packages.length > 0 && !hasChildren && (
<div className="mt-4 flex justify-center">
<Button
onClick={(e) => {
if (hasChildren) e.stopPropagation();
handleInstall();
}}
disabled={isInstalling || isStreaming}
size="default"
variant="default"
className="font-medium bg-primary/90 flex items-center gap-2 w-full max-w-sm py-4 mt-2 mb-2"
>
<Download size={16} />
{isInstalling ? "Installing..." : "Install packages"}
</Button>
{error && <div className="text-sm text-red-500 mt-2">{error}</div>}
</div>
)}
</div>
);
};