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:
+4
-14
@@ -1,17 +1,5 @@
|
||||
import { useRef } from 'react';
|
||||
import {
|
||||
Loader2,
|
||||
Folder,
|
||||
ClipboardPaste,
|
||||
FolderPlus,
|
||||
FolderUp,
|
||||
LayoutGrid,
|
||||
Upload,
|
||||
ClipboardCopy,
|
||||
MessageSquare,
|
||||
Download,
|
||||
Mic,
|
||||
} from 'lucide-react';
|
||||
import { Loader2, Folder, ClipboardPaste, FolderPlus, FolderUp, LayoutGrid, Upload, ClipboardCopy, MessageSquare, Download, Mic } from 'lucide-react';
|
||||
import { getIcon } from 'material-file-icons';
|
||||
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger } from '@/components/ui/context-menu';
|
||||
import type { UseFileBrowserAppType } from '../useFileBrowserApp';
|
||||
@@ -104,7 +92,9 @@ export const FileViewContainer = ({ fileBrowserManager }: FileViewContainerProps
|
||||
})}
|
||||
</div>
|
||||
) : 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}
|
||||
</div>
|
||||
) : (
|
||||
|
||||
+2
-10
@@ -6,16 +6,8 @@ type SelectionActionsProps = {
|
||||
};
|
||||
|
||||
export const SelectionActions = ({ fileBrowserManager }: SelectionActionsProps) => {
|
||||
const {
|
||||
selected,
|
||||
clipboard,
|
||||
handleCut,
|
||||
handleCopy,
|
||||
handlePaste,
|
||||
handleDownloadSelected,
|
||||
handleDeleteSelected,
|
||||
setSelected,
|
||||
} = fileBrowserManager;
|
||||
const { selected, clipboard, handleCut, handleCopy, handlePaste, handleDownloadSelected, handleDeleteSelected, setSelected } =
|
||||
fileBrowserManager;
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
+197
-271
@@ -33,61 +33,19 @@ type ParallelStep = {
|
||||
|
||||
type ServerMessage =
|
||||
| { 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;
|
||||
type: 'step:complete';
|
||||
stepIndex: number;
|
||||
cost?: { inputTokens: number; outputTokens: number; totalUSD: number };
|
||||
}
|
||||
| { jobId: string; 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: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: '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: 'assistant:delta'; 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;
|
||||
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: 'tool:start'; 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: 'stopped' }
|
||||
| { type: 'job:created'; jobId: string }
|
||||
@@ -103,18 +61,12 @@ export function usePipelineRunner() {
|
||||
const [parallelStep, setParallelStep] = useState<ParallelStep | null>(null);
|
||||
const [messages, setMessages] = useState<ChatMessage[]>([]);
|
||||
const [streamingText, setStreamingText] = useState('');
|
||||
const [totalCost, setTotalCost] = useState<{ inputTokens: number; outputTokens: number; totalUSD: number } | null>(
|
||||
null,
|
||||
);
|
||||
const [totalCost, setTotalCost] = useState<{ inputTokens: number; outputTokens: number; totalUSD: number } | null>(null);
|
||||
const [runningCost, setRunningCost] = useState({ inputTokens: 0, outputTokens: 0, totalUSD: 0 });
|
||||
const [hasError, setHasError] = useState(false);
|
||||
const [skippedItems, setSkippedItems] = useState<Array<{ label: string; reason: string }>>([]);
|
||||
const [elapsed, setElapsed] = useState(0);
|
||||
const [waitingStatus, setWaitingStatus] = useState<{
|
||||
stepIndex: number;
|
||||
elapsed: number;
|
||||
iterationLabel?: string;
|
||||
} | null>(null);
|
||||
const [waitingStatus, setWaitingStatus] = useState<{ stepIndex: number; elapsed: number; iterationLabel?: string } | null>(null);
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
const streamBufferRef = useRef('');
|
||||
const startTimeRef = useRef<number>(0);
|
||||
@@ -132,10 +84,7 @@ export function usePipelineRunner() {
|
||||
}, []);
|
||||
|
||||
const stopTimer = useCallback(() => {
|
||||
if (timerRef.current) {
|
||||
clearInterval(timerRef.current);
|
||||
timerRef.current = null;
|
||||
}
|
||||
if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; }
|
||||
}, []);
|
||||
|
||||
const addCost = useCallback((cost: { inputTokens: number; outputTokens: number; totalUSD: number }) => {
|
||||
@@ -146,184 +95,178 @@ export function usePipelineRunner() {
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const handleEvent = useCallback(
|
||||
(msg: ServerMessage) => {
|
||||
// Filter events by jobId (ignore events from other jobs)
|
||||
if ('jobId' in msg && msg.jobId && jobIdRef.current && msg.jobId !== jobIdRef.current) return;
|
||||
const handleEvent = useCallback((msg: ServerMessage) => {
|
||||
// Filter events by jobId (ignore events from other jobs)
|
||||
if ('jobId' in msg && msg.jobId && jobIdRef.current && msg.jobId !== jobIdRef.current) return;
|
||||
|
||||
switch (msg.type) {
|
||||
case 'job:created':
|
||||
jobIdRef.current = msg.jobId;
|
||||
setJobId(msg.jobId);
|
||||
break;
|
||||
switch (msg.type) {
|
||||
case 'job:created':
|
||||
jobIdRef.current = msg.jobId;
|
||||
setJobId(msg.jobId);
|
||||
break;
|
||||
|
||||
case 'job:state':
|
||||
// Reconnection to a completed/failed job
|
||||
if (
|
||||
msg.status === 'completed' ||
|
||||
msg.status === 'failed' ||
|
||||
msg.status === 'stopped' ||
|
||||
msg.status === 'interrupted'
|
||||
) {
|
||||
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;
|
||||
case 'job:state':
|
||||
// Reconnection to a completed/failed job
|
||||
if (msg.status === 'completed' || msg.status === 'failed' || msg.status === 'stopped' || msg.status === 'interrupted') {
|
||||
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 'tool:start':
|
||||
if (inParallelRef.current && msg.iterationLabel) break;
|
||||
setWaitingStatus(null);
|
||||
flushStream();
|
||||
setMessages((prev) => [
|
||||
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,
|
||||
{
|
||||
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,
|
||||
iterations: prev.iterations.map((it) =>
|
||||
it.label === msg.label ? { ...it, status: 'running' } : it,
|
||||
),
|
||||
);
|
||||
break;
|
||||
};
|
||||
});
|
||||
break;
|
||||
|
||||
case 'pipeline:complete':
|
||||
flushStream();
|
||||
setTotalCost(msg.totalCost);
|
||||
setPhase('done');
|
||||
stopTimer();
|
||||
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 'error':
|
||||
flushStream();
|
||||
setMessages((prev) => [...prev, { role: 'error' as const, id: randomId(), text: msg.message }]);
|
||||
setHasError(true);
|
||||
setPhase('done');
|
||||
stopTimer();
|
||||
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 'stopped':
|
||||
flushStream();
|
||||
setPhase('done');
|
||||
stopTimer();
|
||||
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;
|
||||
}
|
||||
},
|
||||
[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
|
||||
// hold the first render's `handleEvent` forever. That closure carries `flushStream`'s captured
|
||||
@@ -365,35 +308,32 @@ export function usePipelineRunner() {
|
||||
};
|
||||
}, []);
|
||||
|
||||
const run = useCallback(
|
||||
(taskDirName: string, inputs: Record<string, string>, cwd?: string, model?: string, startAt?: number) => {
|
||||
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;
|
||||
const run = useCallback((taskDirName: string, inputs: Record<string, string>, cwd?: string, model?: string, startAt?: number) => {
|
||||
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) return;
|
||||
|
||||
setPhase('running');
|
||||
setMessages([]);
|
||||
setStreamingText('');
|
||||
setTotalCost(null);
|
||||
setRunningCost({ inputTokens: 0, outputTokens: 0, totalUSD: 0 });
|
||||
setHasError(false);
|
||||
setSkippedItems([]);
|
||||
setCurrentStep(null);
|
||||
setParallelStep(null);
|
||||
setWaitingStatus(null);
|
||||
setElapsed(0);
|
||||
setJobId(null);
|
||||
jobIdRef.current = null;
|
||||
streamBufferRef.current = '';
|
||||
setPhase('running');
|
||||
setMessages([]);
|
||||
setStreamingText('');
|
||||
setTotalCost(null);
|
||||
setRunningCost({ inputTokens: 0, outputTokens: 0, totalUSD: 0 });
|
||||
setHasError(false);
|
||||
setSkippedItems([]);
|
||||
setCurrentStep(null);
|
||||
setParallelStep(null);
|
||||
setWaitingStatus(null);
|
||||
setElapsed(0);
|
||||
setJobId(null);
|
||||
jobIdRef.current = null;
|
||||
streamBufferRef.current = '';
|
||||
|
||||
startTimeRef.current = Date.now();
|
||||
if (timerRef.current) clearInterval(timerRef.current);
|
||||
timerRef.current = setInterval(() => {
|
||||
setElapsed(Math.floor((Date.now() - startTimeRef.current) / 1000));
|
||||
}, 1000);
|
||||
startTimeRef.current = Date.now();
|
||||
if (timerRef.current) clearInterval(timerRef.current);
|
||||
timerRef.current = setInterval(() => {
|
||||
setElapsed(Math.floor((Date.now() - startTimeRef.current) / 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(() => {
|
||||
if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN || !jobIdRef.current) return;
|
||||
@@ -401,21 +341,7 @@ export function usePipelineRunner() {
|
||||
}, []);
|
||||
|
||||
return {
|
||||
phase,
|
||||
isConnected,
|
||||
jobId,
|
||||
steps,
|
||||
currentStep,
|
||||
parallelStep,
|
||||
messages,
|
||||
streamingText,
|
||||
totalCost,
|
||||
runningCost,
|
||||
hasError,
|
||||
skippedItems,
|
||||
elapsed,
|
||||
waitingStatus,
|
||||
run,
|
||||
stop,
|
||||
phase, isConnected, 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];
|
||||
|
||||
const onReplaceView =
|
||||
(setSearchParams: SetSearchParams) =>
|
||||
const onReplaceView = (setSearchParams: SetSearchParams) =>
|
||||
(viewPath: string, viewRoot: string, ephemeralPath: string, ephemeralRoot: string) => {
|
||||
setSearchParams((prev) => {
|
||||
const next = new URLSearchParams(prev);
|
||||
@@ -37,12 +36,7 @@ export function ViewerProvider({ children }: { children: ReactNode }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<FileViewerProvider
|
||||
filePath={viewPath}
|
||||
fileName={fileName}
|
||||
onOpenFile={onOpenFile}
|
||||
onReplaceView={onReplaceView(setSearchParams)}
|
||||
>
|
||||
<FileViewerProvider filePath={viewPath} fileName={fileName} onOpenFile={onOpenFile} onReplaceView={onReplaceView(setSearchParams)}>
|
||||
{children}
|
||||
</FileViewerProvider>
|
||||
);
|
||||
@@ -65,13 +59,7 @@ export function EphemeralProvider({ children }: { children: ReactNode }) {
|
||||
};
|
||||
|
||||
return (
|
||||
<FileViewerProvider
|
||||
filePath={ephemeralPath}
|
||||
fileName={fileName}
|
||||
root={ephemeralRoot}
|
||||
onOpenFile={onOpenFile}
|
||||
onReplaceView={onReplaceView(setSearchParams)}
|
||||
>
|
||||
<FileViewerProvider filePath={ephemeralPath} fileName={fileName} root={ephemeralRoot} onOpenFile={onOpenFile} onReplaceView={onReplaceView(setSearchParams)}>
|
||||
{children}
|
||||
</FileViewerProvider>
|
||||
);
|
||||
@@ -85,13 +73,7 @@ export function Ephemeral2Provider({ children }: { children: ReactNode }) {
|
||||
const fileName = ephemeral2Path.split('/').pop() ?? '';
|
||||
|
||||
return (
|
||||
<FileViewerProvider
|
||||
filePath={ephemeral2Path}
|
||||
fileName={fileName}
|
||||
root={ephemeral2Root}
|
||||
autoPlay={ephemeral2Auto}
|
||||
onReplaceView={onReplaceView(setSearchParams)}
|
||||
>
|
||||
<FileViewerProvider filePath={ephemeral2Path} fileName={fileName} root={ephemeral2Root} autoPlay={ephemeral2Auto} onReplaceView={onReplaceView(setSearchParams)}>
|
||||
{children}
|
||||
</FileViewerProvider>
|
||||
);
|
||||
@@ -103,14 +85,15 @@ export const ChatEphemeralBody = () => {
|
||||
const chatContext = searchParams.get('chatContext') ?? '';
|
||||
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 path = chatContext.replace(/^\//, '');
|
||||
const message =
|
||||
chatType === 'file'
|
||||
? `[${tag}: ${path}] Let's talk about this file`
|
||||
: `[${tag}: ${path || '/'}] consider, for this session, this directory as your current working directory`;
|
||||
const message = chatType === 'file'
|
||||
? `[${tag}: ${path}] Let's talk about this file`
|
||||
: `[${tag}: ${path || '/'}] consider, for this session, this directory as your current working directory`;
|
||||
|
||||
const handleMessageComplete = useCallback(() => {
|
||||
bumpFilesRefresh();
|
||||
|
||||
Reference in New Issue
Block a user