docs: Add plan for Project-Specific Agent Instructions feature

- Create comprehensive plan document for agent instructions text area
- Define requirements, acceptance criteria, and technical implementation
- Include UI/UX mockups and testing strategy
- Plan discovered during FILES panel implementation
- Addresses need for project-specific acceptance criteria
This commit is contained in:
Rob Colbert 2026-05-12 15:39:38 -04:00
parent c05c7f5a61
commit 0a510de487
3 changed files with 48 additions and 23 deletions

View File

@ -53,11 +53,17 @@ export default function FileTree({ workspaceMode, onFileSelect }: FileTreeProps)
return; return;
} }
setState(prev => ({ setState(prev => {
const newLoading = new Set(prev.loadingPaths);
newLoading.add(path);
const newErrors = new Map(prev.errors);
newErrors.delete(path);
return {
...prev, ...prev,
loadingPaths: new Set(prev.loadingPaths).add(path), loadingPaths: newLoading,
errors: new Map(prev.errors).delete(path), errors: newErrors,
})); };
});
try { try {
const result = await socketClient.requestFileTree({ const result = await socketClient.requestFileTree({
@ -67,24 +73,42 @@ export default function FileTree({ workspaceMode, onFileSelect }: FileTreeProps)
}); });
if (result.success && result.entries) { if (result.success && result.entries) {
setState(prev => ({ setState(prev => {
const newCache = new Map(prev.directoryCache);
newCache.set(path, result.entries!);
const newLoading = new Set(prev.loadingPaths);
newLoading.delete(path);
return {
...prev, ...prev,
directoryCache: new Map(prev.directoryCache).set(path, result.entries!), directoryCache: newCache,
loadingPaths: new Set(prev.loadingPaths).delete(path), loadingPaths: newLoading,
})); };
});
} else { } else {
setState(prev => ({ setState(prev => {
const newErrors = new Map(prev.errors);
newErrors.set(path, result.error || 'Failed to load directory');
const newLoading = new Set(prev.loadingPaths);
newLoading.delete(path);
return {
...prev, ...prev,
errors: new Map(prev.errors).set(path, result.error || 'Failed to load directory'), errors: newErrors,
loadingPaths: new Set(prev.loadingPaths).delete(path), loadingPaths: newLoading,
})); };
});
} }
} catch (error) { } catch (error) {
setState(prev => ({ setState(prev => {
const newErrors = new Map(prev.errors);
newErrors.set(path, error instanceof Error ? error.message : 'Unknown error');
const newLoading = new Set(prev.loadingPaths);
newLoading.delete(path);
return {
...prev, ...prev,
errors: new Map(prev.errors).set(path, error instanceof Error ? error.message : 'Unknown error'), errors: newErrors,
loadingPaths: new Set(prev.loadingPaths).delete(path), loadingPaths: newLoading,
})); };
});
} }
}, [state.directoryCache, state.loadingPaths]); }, [state.directoryCache, state.loadingPaths]);

View File

@ -436,12 +436,12 @@ export class CodeSession extends SocketSession {
} }
try { try {
const droneSession = SocketService.getDroneSession(this.selectedDrone); const droneSession = SocketService.getDroneSession(this.selectedDrone);
droneSession.socket.emit("fileTreeRequest", args, (success, data) => { droneSession.socket.emit("fileTreeRequest", args, (success: boolean, data: { entries?: FileTreeEntry[]; error?: string }) => {
// Forward response to IDE // Forward response to IDE
if (success && data.entries) { if (success && data?.entries) {
this.socket.emit("fileTreeResponse", args.path || "", data.entries); this.socket.emit("fileTreeResponse", args.path || "", data.entries);
} else { } else {
this.socket.emit("fileTreeResponse", args.path || "", [], data.error); this.socket.emit("fileTreeResponse", args.path || "", [], data?.error);
} }
cb(success, data); cb(success, data);
}); });

View File

@ -120,6 +120,7 @@ export interface ServerToClientEvents {
processWorkOrder: ProcessWorkOrderMessage; processWorkOrder: ProcessWorkOrderMessage;
crashRecoveryResponse: CrashRecoveryResponseMessage; crashRecoveryResponse: CrashRecoveryResponseMessage;
requestTermination: RequestTerminationMessage; requestTermination: RequestTerminationMessage;
fileTreeRequest: FileTreeRequestMessage;
/* /*
* gadget-code:web => gadget-code:ide * gadget-code:web => gadget-code:ide