revert prettier churn on four files the cliamp move never touched

I ran `bunx prettier --write` over whole directories instead of the files I
edited, so FileViewContainer, SelectionActions, usePipelineRunner and Providers
got rewrapped into a diff about cliamp. Pure whitespace, zero behaviour, and
exactly what CLAUDE.md warns about — unexplained churn in someone else's file.

Worth noting what it revealed rather than just undoing it: those four were not
prettier-clean to begin with, so `bun format` on a clean tree would rewrite
them too. That is a pre-existing inconsistency, not mine to fix in this commit.

bunx tsgo clean.
This commit is contained in:
2026-08-15 13:53:36 +00:00
parent a9bf51407e
commit 1e79b4effd
4 changed files with 213 additions and 322 deletions
@@ -1,17 +1,5 @@
import { useRef } from 'react'; import { useRef } from 'react';
import { import { Loader2, Folder, ClipboardPaste, FolderPlus, FolderUp, LayoutGrid, Upload, ClipboardCopy, MessageSquare, Download, Mic } from 'lucide-react';
Loader2,
Folder,
ClipboardPaste,
FolderPlus,
FolderUp,
LayoutGrid,
Upload,
ClipboardCopy,
MessageSquare,
Download,
Mic,
} from 'lucide-react';
import { getIcon } from 'material-file-icons'; import { getIcon } from 'material-file-icons';
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from '@/components/ui/context-menu'; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from '@/components/ui/context-menu';
import type { UseFileBrowserAppType } from '../useFileBrowserApp'; import type { UseFileBrowserAppType } from '../useFileBrowserApp';
@@ -104,7 +92,9 @@ export const FileViewContainer = ({ fileBrowserManager }: FileViewContainerProps
})} })}
</div> </div>
) : searchResults ? ( ) : searchResults ? (
<div className="flex items-center justify-center py-20 text-duck-dark/40 text-sm">No results found</div> <div className="flex items-center justify-center py-20 text-duck-dark/40 text-sm">
No results found
</div>
) : null} ) : null}
</div> </div>
) : ( ) : (
@@ -6,16 +6,8 @@ type SelectionActionsProps = {
}; };
export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps) => { export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps) => {
const { const { selected, clipboard, handleCut, handleCopy, handlePaste, handleDownloadSelected, handleDeleteSelected, setSelected } =
selected, fileBrowserManager;
clipboard,
handleCut,
handleCopy,
handlePaste,
handleDownloadSelected,
handleDeleteSelected,
setSelected,
} = fileBrowserManager;
return ( return (
<> <>
@@ -33,61 +33,19 @@ type ParallelStep = {
type ServerMessage = type ServerMessage =
| { jobId: string; type: 'pipeline:init'; steps: StepDef[] } | { jobId: string; type: 'pipeline:init'; steps: StepDef[] }
| { | { jobId: string; type: 'step:start'; stepIndex: number; taskName: string; iteration?: { current: number; total: number; label: string } }
jobId: string; | { jobId: string; type: 'step:complete'; stepIndex: number; cost?: { inputTokens: number; outputTokens: number; totalUSD: number } }
type: 'step:start';
stepIndex: number;
taskName: string;
iteration?: { current: number; total: number; label: string };
}
| {
jobId: string;
type: 'step:complete';
stepIndex: number;
cost?: { inputTokens: number; outputTokens: number; totalUSD: number };
}
| { jobId: string; type: 'step:skip'; stepIndex: number; label: string; reason: string } | { jobId: string; type: 'step:skip'; stepIndex: number; label: string; reason: string }
| { | { jobId: string; type: 'step:parallel'; stepIndex: number; taskName: string; iterations: string[]; concurrency: number }
jobId: string;
type: 'step:parallel';
stepIndex: number;
taskName: string;
iterations: string[];
concurrency: number;
}
| { jobId: string; type: 'step:waiting'; stepIndex: number; iterationLabel?: string; elapsed: number } | { jobId: string; type: 'step:waiting'; stepIndex: number; iterationLabel?: string; elapsed: number }
| { jobId: string; type: 'iteration:start'; stepIndex: number; label: string } | { jobId: string; type: 'iteration:start'; stepIndex: number; label: string }
| { | { jobId: string; type: 'iteration:complete'; stepIndex: number; label: string; cost?: { inputTokens: number; outputTokens: number; totalUSD: number } }
jobId: string;
type: 'iteration:complete';
stepIndex: number;
label: string;
cost?: { inputTokens: number; outputTokens: number; totalUSD: number };
}
| { jobId: string; type: 'iteration:error'; stepIndex: number; label: string; error: string } | { jobId: string; type: 'iteration:error'; stepIndex: number; label: string; error: string }
| { jobId: string; type: 'assistant:delta'; text: string; iterationLabel?: string } | { jobId: string; type: 'assistant:delta'; text: string; iterationLabel?: string }
| { jobId: string; type: 'assistant:text'; text: string; iterationLabel?: string } | { jobId: string; type: 'assistant:text'; text: string; iterationLabel?: string }
| { | { jobId: string; type: 'tool:start'; toolCallId: string; toolName: string; toolInput: Record<string, unknown>; iterationLabel?: string }
jobId: string; | { jobId: string; type: 'tool:result'; toolCallId: string; output: string; isError: boolean; iterationLabel?: string }
type: 'tool:start'; | { jobId: string; type: 'pipeline:complete'; totalCost: { inputTokens: number; outputTokens: number; totalUSD: number } }
toolCallId: string;
toolName: string;
toolInput: Record<string, unknown>;
iterationLabel?: string;
}
| {
jobId: string;
type: 'tool:result';
toolCallId: string;
output: string;
isError: boolean;
iterationLabel?: string;
}
| {
jobId: string;
type: 'pipeline:complete';
totalCost: { inputTokens: number; outputTokens: number; totalUSD: number };
}
| { jobId: string; type: 'error'; message: string } | { jobId: string; type: 'error'; message: string }
| { jobId: string; type: 'stopped' } | { jobId: string; type: 'stopped' }
| { type: 'job:created'; jobId: string } | { type: 'job:created'; jobId: string }
@@ -103,18 +61,12 @@ export function usePipelineRunner() {
const [parallelStep, setParallelStep] = useState<ParallelStep | null>(null); const [parallelStep, setParallelStep] = useState<ParallelStep | null>(null);
const [messages, setMessages] = useState<ChatMessage[]>([]); const [messages, setMessages] = useState<ChatMessage[]>([]);
const [streamingText, setStreamingText] = useState(''); const [streamingText, setStreamingText] = useState('');
const [totalCost, setTotalCost] = useState<{ inputTokens: number; outputTokens: number; totalUSD: number } | null>( const [totalCost, setTotalCost] = useState<{ inputTokens: number; outputTokens: number; totalUSD: number } | null>(null);
null,
);
const [runningCost, setRunningCost] = useState({ inputTokens: 0, outputTokens: 0, totalUSD: 0 }); const [runningCost, setRunningCost] = useState({ inputTokens: 0, outputTokens: 0, totalUSD: 0 });
const [hasError, setHasError] = useState(false); const [hasError, setHasError] = useState(false);
const [skippedItems, setSkippedItems] = useState<Array<{ label: string; reason: string }>>([]); const [skippedItems, setSkippedItems] = useState<Array<{ label: string; reason: string }>>([]);
const [elapsed, setElapsed] = useState(0); const [elapsed, setElapsed] = useState(0);
const [waitingStatus, setWaitingStatus] = useState<{ const [waitingStatus, setWaitingStatus] = useState<{ stepIndex: number; elapsed: number; iterationLabel?: string } | null>(null);
stepIndex: number;
elapsed: number;
iterationLabel?: string;
} | null>(null);
const wsRef = useRef<WebSocket | null>(null); const wsRef = useRef<WebSocket | null>(null);
const streamBufferRef = useRef(''); const streamBufferRef = useRef('');
const startTimeRef = useRef<number>(0); const startTimeRef = useRef<number>(0);
@@ -132,10 +84,7 @@ export function usePipelineRunner() {
}, []); }, []);
const stopTimer = useCallback(() => { const stopTimer = useCallback(() => {
if (timerRef.current) { if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; }
clearInterval(timerRef.current);
timerRef.current = null;
}
}, []); }, []);
const addCost = useCallback((cost: { inputTokens: number; outputTokens: number; totalUSD: number }) => { const addCost = useCallback((cost: { inputTokens: number; outputTokens: number; totalUSD: number }) => {
@@ -146,184 +95,178 @@ export function usePipelineRunner() {
})); }));
}, []); }, []);
const handleEvent = useCallback( const handleEvent = useCallback((msg: ServerMessage) => {
(msg: ServerMessage) => { // Filter events by jobId (ignore events from other jobs)
// Filter events by jobId (ignore events from other jobs) if ('jobId' in msg && msg.jobId && jobIdRef.current && msg.jobId !== jobIdRef.current) return;
if ('jobId' in msg && msg.jobId && jobIdRef.current && msg.jobId !== jobIdRef.current) return;
switch (msg.type) { switch (msg.type) {
case 'job:created': case 'job:created':
jobIdRef.current = msg.jobId; jobIdRef.current = msg.jobId;
setJobId(msg.jobId); setJobId(msg.jobId);
break; break;
case 'job:state': case 'job:state':
// Reconnection to a completed/failed job // Reconnection to a completed/failed job
if ( if (msg.status === 'completed' || msg.status === 'failed' || msg.status === 'stopped' || msg.status === 'interrupted') {
msg.status === 'completed' || setPhase('done');
msg.status === 'failed' || if (msg.cost) setTotalCost(msg.cost as { inputTokens: number; outputTokens: number; totalUSD: number });
msg.status === 'stopped' || if (msg.status === 'failed' || msg.status === 'interrupted') setHasError(true);
msg.status === 'interrupted' stopTimer();
) {
setPhase('done');
if (msg.cost) setTotalCost(msg.cost as { inputTokens: number; outputTokens: number; totalUSD: number });
if (msg.status === 'failed' || msg.status === 'interrupted') setHasError(true);
stopTimer();
}
break;
case 'pipeline:init':
setSteps(msg.steps);
break;
case 'step:start':
flushStream();
setMessages([]);
setParallelStep(null);
setWaitingStatus(null);
inParallelRef.current = false;
setCurrentStep({
taskName: msg.taskName,
iteration: msg.iteration,
status: 'running',
});
break;
case 'step:complete':
flushStream();
setWaitingStatus(null);
setCurrentStep((prev) => (prev ? { ...prev, status: 'complete', cost: msg.cost } : null));
if (msg.cost) addCost(msg.cost);
break;
case 'step:skip':
setSkippedItems((prev) => [...prev, { label: msg.label, reason: msg.reason }]);
break;
case 'step:waiting':
setWaitingStatus({ stepIndex: msg.stepIndex, elapsed: msg.elapsed, iterationLabel: msg.iterationLabel });
break;
case 'step:parallel':
flushStream();
setMessages([]);
setCurrentStep(null);
inParallelRef.current = true;
setParallelStep({
stepIndex: msg.stepIndex,
taskName: msg.taskName,
concurrency: msg.concurrency,
iterations: msg.iterations.map((label) => ({ label, status: 'pending' })),
});
break;
case 'iteration:start':
setParallelStep((prev) => {
if (!prev) return prev;
return {
...prev,
iterations: prev.iterations.map((it) => (it.label === msg.label ? { ...it, status: 'running' } : it)),
};
});
break;
case 'iteration:complete':
setParallelStep((prev) => {
if (!prev) return prev;
return {
...prev,
iterations: prev.iterations.map((it) =>
it.label === msg.label ? { ...it, status: 'complete', cost: msg.cost } : it,
),
};
});
if (msg.cost) addCost(msg.cost);
break;
case 'iteration:error':
setParallelStep((prev) => {
if (!prev) return prev;
return {
...prev,
iterations: prev.iterations.map((it) =>
it.label === msg.label ? { ...it, status: 'error', error: msg.error } : it,
),
};
});
break;
case 'assistant:delta':
// Skip messages from parallel sub-agents (shown in iteration grid instead)
if (inParallelRef.current && msg.iterationLabel) break;
setWaitingStatus(null);
streamBufferRef.current += msg.text;
setStreamingText(streamBufferRef.current);
break;
case 'assistant:text': {
if (inParallelRef.current && msg.iterationLabel) break;
const text = msg.text || streamBufferRef.current;
if (text) {
setMessages((prev) => [...prev, { role: 'assistant', id: randomId(), text }]);
}
streamBufferRef.current = '';
setStreamingText('');
break;
} }
break;
case 'tool:start': case 'pipeline:init':
if (inParallelRef.current && msg.iterationLabel) break; setSteps(msg.steps);
setWaitingStatus(null); break;
flushStream();
setMessages((prev) => [ case 'step:start':
flushStream();
setMessages([]);
setParallelStep(null);
setWaitingStatus(null);
inParallelRef.current = false;
setCurrentStep({
taskName: msg.taskName,
iteration: msg.iteration,
status: 'running',
});
break;
case 'step:complete':
flushStream();
setWaitingStatus(null);
setCurrentStep((prev) => prev ? { ...prev, status: 'complete', cost: msg.cost } : null);
if (msg.cost) addCost(msg.cost);
break;
case 'step:skip':
setSkippedItems((prev) => [...prev, { label: msg.label, reason: msg.reason }]);
break;
case 'step:waiting':
setWaitingStatus({ stepIndex: msg.stepIndex, elapsed: msg.elapsed, iterationLabel: msg.iterationLabel });
break;
case 'step:parallel':
flushStream();
setMessages([]);
setCurrentStep(null);
inParallelRef.current = true;
setParallelStep({
stepIndex: msg.stepIndex,
taskName: msg.taskName,
concurrency: msg.concurrency,
iterations: msg.iterations.map((label) => ({ label, status: 'pending' })),
});
break;
case 'iteration:start':
setParallelStep((prev) => {
if (!prev) return prev;
return {
...prev, ...prev,
{ iterations: prev.iterations.map((it) =>
role: 'tool' as const, it.label === msg.label ? { ...it, status: 'running' } : it,
id: randomId(),
toolCallId: msg.toolCallId,
toolName: msg.toolName,
toolInput: msg.toolInput,
output: undefined,
isError: false,
},
]);
break;
case 'tool:result':
if (inParallelRef.current && msg.iterationLabel) break;
setMessages((prev) =>
prev.map((m) =>
m.role === 'tool' && 'toolCallId' in m && m.toolCallId === msg.toolCallId
? { ...m, output: msg.output, isError: msg.isError }
: m,
), ),
); };
break; });
break;
case 'pipeline:complete': case 'iteration:complete':
flushStream(); setParallelStep((prev) => {
setTotalCost(msg.totalCost); if (!prev) return prev;
setPhase('done'); return {
stopTimer(); ...prev,
break; iterations: prev.iterations.map((it) =>
it.label === msg.label ? { ...it, status: 'complete', cost: msg.cost } : it,
),
};
});
if (msg.cost) addCost(msg.cost);
break;
case 'error': case 'iteration:error':
flushStream(); setParallelStep((prev) => {
setMessages((prev) => [...prev, { role: 'error' as const, id: randomId(), text: msg.message }]); if (!prev) return prev;
setHasError(true); return {
setPhase('done'); ...prev,
stopTimer(); iterations: prev.iterations.map((it) =>
break; it.label === msg.label ? { ...it, status: 'error', error: msg.error } : it,
),
};
});
break;
case 'stopped': case 'assistant:delta':
flushStream(); // Skip messages from parallel sub-agents (shown in iteration grid instead)
setPhase('done'); if (inParallelRef.current && msg.iterationLabel) break;
stopTimer(); setWaitingStatus(null);
break; streamBufferRef.current += msg.text;
setStreamingText(streamBufferRef.current);
break;
case 'assistant:text': {
if (inParallelRef.current && msg.iterationLabel) break;
const text = msg.text || streamBufferRef.current;
if (text) {
setMessages((prev) => [...prev, { role: 'assistant', id: randomId(), text }]);
}
streamBufferRef.current = '';
setStreamingText('');
break;
} }
},
[flushStream, stopTimer, addCost], case 'tool:start':
); if (inParallelRef.current && msg.iterationLabel) break;
setWaitingStatus(null);
flushStream();
setMessages((prev) => [
...prev,
{
role: 'tool' as const,
id: randomId(),
toolCallId: msg.toolCallId,
toolName: msg.toolName,
toolInput: msg.toolInput,
output: undefined,
isError: false,
},
]);
break;
case 'tool:result':
if (inParallelRef.current && msg.iterationLabel) break;
setMessages((prev) =>
prev.map((m) =>
m.role === 'tool' && 'toolCallId' in m && m.toolCallId === msg.toolCallId
? { ...m, output: msg.output, isError: msg.isError }
: m,
),
);
break;
case 'pipeline:complete':
flushStream();
setTotalCost(msg.totalCost);
setPhase('done');
stopTimer();
break;
case 'error':
flushStream();
setMessages((prev) => [...prev, { role: 'error' as const, id: randomId(), text: msg.message }]);
setHasError(true);
setPhase('done');
stopTimer();
break;
case 'stopped':
flushStream();
setPhase('done');
stopTimer();
break;
}
}, [flushStream, stopTimer, addCost]);
// The socket below is opened once and must stay open, so its listener is registered once too — and would // The socket below is opened once and must stay open, so its listener is registered once too — and would
// hold the first render's `handleEvent` forever. That closure carries `flushStream`'s captured // hold the first render's `handleEvent` forever. That closure carries `flushStream`'s captured
@@ -365,35 +308,32 @@ export function usePipelineRunner() {
}; };
}, []); }, []);
const run = useCallback( const run = useCallback((taskDirName: string, inputs: Record<string, string>, cwd?: string, model?: string, startAt?: number) => {
(taskDirName: string, inputs: Record<string, string>, cwd?: string, model?: string, startAt?: number) => { if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;
setPhase('running'); setPhase('running');
setMessages([]); setMessages([]);
setStreamingText(''); setStreamingText('');
setTotalCost(null); setTotalCost(null);
setRunningCost({ inputTokens: 0, outputTokens: 0, totalUSD: 0 }); setRunningCost({ inputTokens: 0, outputTokens: 0, totalUSD: 0 });
setHasError(false); setHasError(false);
setSkippedItems([]); setSkippedItems([]);
setCurrentStep(null); setCurrentStep(null);
setParallelStep(null); setParallelStep(null);
setWaitingStatus(null); setWaitingStatus(null);
setElapsed(0); setElapsed(0);
setJobId(null); setJobId(null);
jobIdRef.current = null; jobIdRef.current = null;
streamBufferRef.current = ''; streamBufferRef.current = '';
startTimeRef.current = Date.now(); startTimeRef.current = Date.now();
if (timerRef.current) clearInterval(timerRef.current); if (timerRef.current) clearInterval(timerRef.current);
timerRef.current = setInterval(() => { timerRef.current = setInterval(() => {
setElapsed(Math.floor((Date.now() - startTimeRef.current) / 1000)); setElapsed(Math.floor((Date.now() - startTimeRef.current) / 1000));
}, 1000); }, 1000);
wsRef.current.send(JSON.stringify({ type: 'run', taskDirName, inputs, cwd, model, startAt })); wsRef.current.send(JSON.stringify({ type: 'run', taskDirName, inputs, cwd, model, startAt }));
}, }, []);
[],
);
const stop = useCallback(() => { const stop = useCallback(() => {
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN || !jobIdRef.current) return; if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN || !jobIdRef.current) return;
@@ -401,21 +341,7 @@ export function usePipelineRunner() {
}, []); }, []);
return { return {
phase, phase, isConnected, jobId, steps, currentStep, parallelStep, messages, streamingText,
isConnected, totalCost, runningCost, hasError, skippedItems, elapsed, waitingStatus, run, stop,
jobId,
steps,
currentStep,
parallelStep,
messages,
streamingText,
totalCost,
runningCost,
hasError,
skippedItems,
elapsed,
waitingStatus,
run,
stop,
}; };
} }
@@ -7,8 +7,7 @@ import { EmbeddableChat } from '../../apps/Chat/EmbeddableChat';
type SetSearchParams = ReturnType<typeof useSearchParams>[1]; type SetSearchParams = ReturnType<typeof useSearchParams>[1];
const onReplaceView = const onReplaceView = (setSearchParams: SetSearchParams) =>
(setSearchParams: SetSearchParams) =>
(viewPath: string, viewRoot: string, ephemeralPath: string, ephemeralRoot: string) => { (viewPath: string, viewRoot: string, ephemeralPath: string, ephemeralRoot: string) => {
setSearchParams((prev) => { setSearchParams((prev) => {
const next = new URLSearchParams(prev); const next = new URLSearchParams(prev);
@@ -37,12 +36,7 @@ export function ViewerProvider({ children }: { children: ReactNode }) {
}; };
return ( return (
<FileViewerProvider <FileViewerProvider filePath={viewPath} fileName={fileName} onOpenFile={onOpenFile} onReplaceView={onReplaceView(setSearchParams)}>
filePath={viewPath}
fileName={fileName}
onOpenFile={onOpenFile}
onReplaceView={onReplaceView(setSearchParams)}
>
{children} {children}
</FileViewerProvider> </FileViewerProvider>
); );
@@ -65,13 +59,7 @@ export function EphemeralProvider({ children }: { children: ReactNode }) {
}; };
return ( return (
<FileViewerProvider <FileViewerProvider filePath={ephemeralPath} fileName={fileName} root={ephemeralRoot} onOpenFile={onOpenFile} onReplaceView={onReplaceView(setSearchParams)}>
filePath={ephemeralPath}
fileName={fileName}
root={ephemeralRoot}
onOpenFile={onOpenFile}
onReplaceView={onReplaceView(setSearchParams)}
>
{children} {children}
</FileViewerProvider> </FileViewerProvider>
); );
@@ -85,13 +73,7 @@ export function Ephemeral2Provider({ children }: { children: ReactNode }) {
const fileName = ephemeral2Path.split('/').pop() ?? ''; const fileName = ephemeral2Path.split('/').pop() ?? '';
return ( return (
<FileViewerProvider <FileViewerProvider filePath={ephemeral2Path} fileName={fileName} root={ephemeral2Root} autoPlay={ephemeral2Auto} onReplaceView={onReplaceView(setSearchParams)}>
filePath={ephemeral2Path}
fileName={fileName}
root={ephemeral2Root}
autoPlay={ephemeral2Auto}
onReplaceView={onReplaceView(setSearchParams)}
>
{children} {children}
</FileViewerProvider> </FileViewerProvider>
); );
@@ -103,14 +85,15 @@ export const ChatEphemeralBody = () => {
const chatContext = searchParams.get('chatContext') ?? ''; const chatContext = searchParams.get('chatContext') ?? '';
const chatType = searchParams.get('chatType') as 'file' | 'folder' | null; const chatType = searchParams.get('chatType') as 'file' | 'folder' | null;
const cwdPath = chatType === 'file' ? chatContext.substring(0, chatContext.lastIndexOf('/')) || '/' : chatContext; const cwdPath = chatType === 'file'
? chatContext.substring(0, chatContext.lastIndexOf('/')) || '/'
: chatContext;
const tag = chatType === 'file' ? 'file' : 'folder'; const tag = chatType === 'file' ? 'file' : 'folder';
const path = chatContext.replace(/^\//, ''); const path = chatContext.replace(/^\//, '');
const message = const message = chatType === 'file'
chatType === 'file' ? `[${tag}: ${path}] Let's talk about this file`
? `[${tag}: ${path}] Let's talk about this file` : `[${tag}: ${path || '/'}] consider, for this session, this directory as your current working directory`;
: `[${tag}: ${path || '/'}] consider, for this session, this directory as your current working directory`;
const handleMessageComplete = useCallback(() => { const handleMessageComplete = useCallback(() => {
bumpFilesRefresh(); bumpFilesRefresh();