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

View File

@ -436,12 +436,12 @@ export class CodeSession extends SocketSession {
}
try {
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
if (success && data.entries) {
if (success && data?.entries) {
this.socket.emit("fileTreeResponse", args.path || "", data.entries);
} else {
this.socket.emit("fileTreeResponse", args.path || "", [], data.error);
this.socket.emit("fileTreeResponse", args.path || "", [], data?.error);
}
cb(success, data);
});

View File

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