feat: tool timeout auto-retry, file tree attachment, force stop button
- Add configurable tool timeout with auto-retry: when a tool exceeds the timeout threshold, abort and send a follow-up message asking Claude to try a different approach - Add "+" button on file tree items to attach files directly to chat input via new /api/files/raw endpoint and custom event bridge - Add force stop button in streaming status bar when tool runs >90s, with warning indicators at 60s - Improve doc preview markdown rendering (padding, list indentation) - Bump version to 0.10.0 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
8747464c2f
commit
4fa26032a4
15 files changed
+314
-16
No files matched your search
@@ -13,6 +13,7 @@ import {
|
||||
FileIcon,
|
||||
FolderIcon,
|
||||
FolderOpenIcon,
|
||||
PlusIcon,
|
||||
} from "lucide-react";
|
||||
import {
|
||||
createContext,
|
||||
@@ -27,6 +28,7 @@ interface FileTreeContextType {
|
||||
togglePath: (path: string) => void;
|
||||
selectedPath?: string;
|
||||
onSelect?: (path: string) => void;
|
||||
onAdd?: (path: string) => void;
|
||||
}
|
||||
|
||||
// Default noop for context default value
|
||||
@@ -44,6 +46,7 @@ export type FileTreeProps = HTMLAttributes<HTMLDivElement> & {
|
||||
defaultExpanded?: Set<string>;
|
||||
selectedPath?: string;
|
||||
onSelect?: (path: string) => void;
|
||||
onAdd?: (path: string) => void;
|
||||
onExpandedChange?: (expanded: Set<string>) => void;
|
||||
};
|
||||
|
||||
@@ -52,6 +55,7 @@ export const FileTree = ({
|
||||
defaultExpanded = new Set(),
|
||||
selectedPath,
|
||||
onSelect,
|
||||
onAdd,
|
||||
onExpandedChange,
|
||||
className,
|
||||
children,
|
||||
@@ -75,8 +79,8 @@ export const FileTree = ({
|
||||
);
|
||||
|
||||
const contextValue = useMemo(
|
||||
() => ({ expandedPaths, onSelect, selectedPath, togglePath }),
|
||||
[expandedPaths, onSelect, selectedPath, togglePath]
|
||||
() => ({ expandedPaths, onAdd, onSelect, selectedPath, togglePath }),
|
||||
[expandedPaths, onAdd, onSelect, selectedPath, togglePath]
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -204,7 +208,7 @@ export const FileTreeFile = ({
|
||||
children,
|
||||
...props
|
||||
}: FileTreeFileProps) => {
|
||||
const { selectedPath, onSelect } = useContext(FileTreeContext);
|
||||
const { selectedPath, onSelect, onAdd } = useContext(FileTreeContext);
|
||||
const isSelected = selectedPath === path;
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
@@ -220,13 +224,21 @@ export const FileTreeFile = ({
|
||||
[onSelect, path]
|
||||
);
|
||||
|
||||
const handleAdd = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
e.stopPropagation();
|
||||
onAdd?.(path);
|
||||
},
|
||||
[onAdd, path]
|
||||
);
|
||||
|
||||
const fileContextValue = useMemo(() => ({ name, path }), [name, path]);
|
||||
|
||||
return (
|
||||
<FileTreeFileContext.Provider value={fileContextValue}>
|
||||
<div
|
||||
className={cn(
|
||||
"flex cursor-pointer items-center gap-1 rounded px-2 py-1 transition-colors hover:bg-muted/50",
|
||||
"group/file flex cursor-pointer items-center gap-1 rounded px-2 py-1 transition-colors hover:bg-muted/50",
|
||||
isSelected && "bg-muted",
|
||||
className
|
||||
)}
|
||||
@@ -244,6 +256,16 @@ export const FileTreeFile = ({
|
||||
{icon ?? <FileIcon className="size-4 text-muted-foreground" />}
|
||||
</FileTreeIcon>
|
||||
<FileTreeName>{name}</FileTreeName>
|
||||
{onAdd && (
|
||||
<button
|
||||
type="button"
|
||||
className="ml-auto flex size-5 shrink-0 items-center justify-center rounded opacity-0 transition-opacity hover:bg-muted group-hover/file:opacity-100"
|
||||
onClick={handleAdd}
|
||||
title="Add to chat"
|
||||
>
|
||||
<PlusIcon className="size-3 text-muted-foreground" />
|
||||
</button>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user