From 0108d764d99fa7d78380b46909f93a22659d2f73 Mon Sep 17 00:00:00 2001 From: Johannes du Plessis Date: Mon, 15 Jun 2026 17:29:38 -0700 Subject: [PATCH] fix(ui): resolve eslint errors in dashboard components (#1538) Clears ~83 pre-existing eslint errors in the UI: auto-fixable rules (array-type, import/order, sort-imports, type-only imports, redundant assertions/conditions) plus manual fixes for unnecessary conditions and banned @ts-nocheck directives. The 8 ported components excluded from tsconfig are now also ignored by eslint so type-aware linting no longer fails to parse them. Co-authored-by: open-swe[bot] --- ui/eslint.config.js | 11 ++++++++++ ui/src/components/AgentInstructionsPanel.tsx | 4 ++-- ui/src/components/SidebarUserMenu.tsx | 6 ++++-- ui/src/components/agents/AgentGitPanel.tsx | 2 +- .../agents/messages/AgentMessage.tsx | 20 +++++++++---------- .../agents/messages/ChunkRenderer.tsx | 5 ++--- .../components/agents/messages/Messages.tsx | 4 +--- .../agents/messages/ThinkingSpinner.tsx | 2 +- .../agents/messages/TurnChangedFilesCard.tsx | 5 ++--- .../agents/messages/UserMessage.tsx | 16 +++++++-------- .../agents/messages/WorkSummary.tsx | 3 ++- .../components/agents/messages/renderItems.ts | 14 ++++++------- .../agents/messages/summarizeChangedFiles.ts | 8 ++++---- ui/src/components/agents/messages/types.ts | 2 +- ui/src/components/agents/ported/CodeBlock.tsx | 9 ++++----- .../agents/ported/CompactingIndicator.tsx | 2 +- ui/src/components/agents/ported/DiffView.tsx | 2 +- ui/src/components/agents/ported/Markdown.tsx | 3 ++- .../agents/ported/MarkdownTable.tsx | 16 +++++++++------ ui/src/components/agents/ported/ReplyCard.tsx | 6 +++--- .../components/agents/ported/ShellCommand.tsx | 2 +- ui/src/components/agents/ported/TodoList.tsx | 4 ++-- .../agents/ported/ToolExecution.tsx | 6 +++--- .../agents/subagents/SubagentCard.tsx | 5 ++--- .../agents/subagents/SubagentGroup.tsx | 5 ++--- .../provider/useLiveMarkdownMessageId.ts | 2 +- ui/src/lib/hotkeys.ts | 2 +- ui/src/routes/agents/threads.tsx | 6 ++---- ui/src/routes/cloud-agents.tsx | 2 +- 29 files changed, 91 insertions(+), 83 deletions(-) diff --git a/ui/eslint.config.js b/ui/eslint.config.js index f1127e8f..71b53ea5 100644 --- a/ui/eslint.config.js +++ b/ui/eslint.config.js @@ -11,6 +11,17 @@ export default [ "dist/**", "src/routeTree.gen.ts", "src/components/ui/**", + // Ported from a desktop host app and excluded from tsconfig (not yet + // integrated), so type-aware linting cannot resolve them. Keep this list + // in sync with the `exclude` entries in tsconfig.json. + "src/components/agents/ported/ChatView.tsx", + "src/components/agents/ported/PromptBar.tsx", + "src/components/agents/ported/BranchSelector.tsx", + "src/components/agents/ported/ContextIndicator.tsx", + "src/components/agents/ported/SourceControlPanel.tsx", + "src/components/agents/ported/SourceControlTile.tsx", + "src/components/agents/ported/Footer.tsx", + "src/components/agents/ported/ThreadPicker.tsx", ], }, ...tanstackConfig, diff --git a/ui/src/components/AgentInstructionsPanel.tsx b/ui/src/components/AgentInstructionsPanel.tsx index ac9d4f28..261aba67 100644 --- a/ui/src/components/AgentInstructionsPanel.tsx +++ b/ui/src/components/AgentInstructionsPanel.tsx @@ -55,7 +55,7 @@ export function AgentInstructionsPanel() { }); useEffect(() => { - if (detail.data) setDraft(detail.data.instructions ?? ""); + if (detail.data) setDraft(detail.data.instructions); }, [detail.data?.instructions, detail.data?.full_name]); const create = useMutation({ @@ -104,7 +104,7 @@ export function AgentInstructionsPanel() { const canAdd = normalizedAddRepo !== null && !configured.has(normalizedAddRepo); const active = detail.data ?? instructions.data?.find((s) => s.full_name === selected) ?? null; - const dirty = active != null && draft !== (active.instructions ?? ""); + const dirty = active != null && draft !== active.instructions; const handleAdd = () => { if (!normalizedAddRepo || !canAdd) return; diff --git a/ui/src/components/SidebarUserMenu.tsx b/ui/src/components/SidebarUserMenu.tsx index 433b5f39..2f3d9e45 100644 --- a/ui/src/components/SidebarUserMenu.tsx +++ b/ui/src/components/SidebarUserMenu.tsx @@ -9,9 +9,11 @@ import { IoSunnyOutline, } from "react-icons/io5"; +import type { SessionUser } from "@/lib/api"; +import type { Theme } from "@/lib/theme"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { api, type SessionUser } from "@/lib/api"; -import { useTheme, type Theme } from "@/lib/theme"; +import { api } from "@/lib/api"; +import { useTheme } from "@/lib/theme"; import { cn } from "@/lib/utils"; const THEME_OPTIONS: Array<{ value: Theme; label: string; icon: typeof IoSunnyOutline }> = [ diff --git a/ui/src/components/agents/AgentGitPanel.tsx b/ui/src/components/agents/AgentGitPanel.tsx index b3230c45..270ed420 100644 --- a/ui/src/components/agents/AgentGitPanel.tsx +++ b/ui/src/components/agents/AgentGitPanel.tsx @@ -17,9 +17,9 @@ import type { GitStatus, GitStatusEntry } from "@pierre/trees" import type { AgentThread, Message } from "@/lib/agents/types" import type { ThreadPrDiffFile } from "@/lib/agents/api" +import type { ChangedFileSummaryItem } from "@/components/agents/messages" import { useAgentThreadPrDiff } from "@/lib/agents/queries" import { buttonVariants } from "@/components/ui/button" -import type { ChangedFileSummaryItem } from "@/components/agents/messages" import { useDiffOptions } from "@/components/agents/utils/diffUtils" import { summarizeChangedFiles } from "@/components/agents/ported" import { Z } from "@/components/agents/z-index" diff --git a/ui/src/components/agents/messages/AgentMessage.tsx b/ui/src/components/agents/messages/AgentMessage.tsx index 6ce555bf..bc23d822 100644 --- a/ui/src/components/agents/messages/AgentMessage.tsx +++ b/ui/src/components/agents/messages/AgentMessage.tsx @@ -1,18 +1,18 @@ import { useEffect, useMemo, useRef, useState } from "react"; -import { ReplyCard } from "@/components/agents/ported/ReplyCard"; -import { ShellCommand } from "@/components/agents/ported/ShellCommand"; -import { ToolExecution } from "@/components/agents/ported/ToolExecution"; -import type { Message } from "@/lib/agents/types"; - import { ChunkRenderer } from "./ChunkRenderer"; import { ReasoningBlock } from "./ReasoningBlock"; -import { buildRenderItems, summarizeExploration, type RenderItem } from "./renderItems"; -import { SubagentGroup } from "@/components/agents/subagents"; +import { buildRenderItems, summarizeExploration } from "./renderItems"; import { summarizeChangedFiles } from "./summarizeChangedFiles"; import { TurnChangedFilesCard } from "./TurnChangedFilesCard"; import { WorkSummary } from "./WorkSummary"; +import type { RenderItem } from "./renderItems"; +import type { Message } from "@/lib/agents/types"; import type { ApprovalCallbacks, ChangedFileSummaryItem } from "./types"; +import { SubagentGroup } from "@/components/agents/subagents"; +import { ToolExecution } from "@/components/agents/ported/ToolExecution"; +import { ShellCommand } from "@/components/agents/ported/ShellCommand"; +import { ReplyCard } from "@/components/agents/ported/ReplyCard"; /** * Render-item types kept visible (not collapsed) when a turn finishes — the @@ -24,9 +24,9 @@ const REPLY_ITEM_TYPES = new Set(["text-chunk", "reply-item" * Split a finished turn's items into collapsible work and the trailing reply, * where the reply is the maximal suffix made up solely of reply/text items. */ -function splitWorkAndReply(items: RenderItem[]): { - workItems: RenderItem[]; - replyItems: RenderItem[]; +function splitWorkAndReply(items: Array): { + workItems: Array; + replyItems: Array; } { let splitIndex = items.length; while (splitIndex > 0) { diff --git a/ui/src/components/agents/messages/ChunkRenderer.tsx b/ui/src/components/agents/messages/ChunkRenderer.tsx index dc6a47c5..a2d6c9b7 100644 --- a/ui/src/components/agents/messages/ChunkRenderer.tsx +++ b/ui/src/components/agents/messages/ChunkRenderer.tsx @@ -1,9 +1,8 @@ +import type { Chunk } from "@/lib/agents/types"; +import type { ApprovalCallbacks } from "./types"; import { CodeBlock } from "@/components/agents/ported/CodeBlock"; import { Markdown } from "@/components/agents/ported/Markdown"; import { ToolExecution } from "@/components/agents/ported/ToolExecution"; -import type { Chunk } from "@/lib/agents/types"; - -import type { ApprovalCallbacks } from "./types"; export function ChunkRenderer({ chunk, diff --git a/ui/src/components/agents/messages/Messages.tsx b/ui/src/components/agents/messages/Messages.tsx index 6a462639..85c1a608 100644 --- a/ui/src/components/agents/messages/Messages.tsx +++ b/ui/src/components/agents/messages/Messages.tsx @@ -1,13 +1,11 @@ -// @ts-nocheck — ported from open-swe-app (Electron); strict checks applied when wiring cloud APIs. import { memo, useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState } from "react"; import { ChevronDown } from "lucide-react"; -import { useLiveMarkdownMessageId } from "@/lib/agents/provider/useLiveMarkdownMessageId"; - import { AgentMessage } from "./AgentMessage"; import { ThinkingSpinner } from "./ThinkingSpinner"; import { UserMessage } from "./UserMessage"; import type { MessagesProps } from "./types"; +import { useLiveMarkdownMessageId } from "@/lib/agents/provider/useLiveMarkdownMessageId"; const BOTTOM_LOCK_THRESHOLD_PX = 24; diff --git a/ui/src/components/agents/messages/ThinkingSpinner.tsx b/ui/src/components/agents/messages/ThinkingSpinner.tsx index df5dab74..f1308efc 100644 --- a/ui/src/components/agents/messages/ThinkingSpinner.tsx +++ b/ui/src/components/agents/messages/ThinkingSpinner.tsx @@ -2,7 +2,7 @@ import { useEffect, useRef, useState } from "react"; import { formatElapsed } from "@/lib/utils"; -const BUSY_TEXTS: { present: string; past: string }[] = [ +const BUSY_TEXTS: Array<{ present: string; past: string }> = [ { present: "vibing...", past: "Vibed" }, { present: "noodling...", past: "Noodled" }, { present: "pondering...", past: "Pondered" }, diff --git a/ui/src/components/agents/messages/TurnChangedFilesCard.tsx b/ui/src/components/agents/messages/TurnChangedFilesCard.tsx index c8f035ed..3575a033 100644 --- a/ui/src/components/agents/messages/TurnChangedFilesCard.tsx +++ b/ui/src/components/agents/messages/TurnChangedFilesCard.tsx @@ -2,9 +2,8 @@ import { memo, useCallback, useEffect, useMemo, useState } from "react"; import { ChevronDown, ChevronUp } from "lucide-react"; import { MultiFileDiff } from "@pierre/diffs/react"; -import { useDiffOptions, warmDiffHighlighter } from "@/components/agents/utils/diffUtils"; - import type { ChangedFileSummaryItem } from "./types"; +import { useDiffOptions, warmDiffHighlighter } from "@/components/agents/utils/diffUtils"; function stripProjectPathForDisplay(path: string, projectPath?: string): string { if (!projectPath) return path; @@ -84,7 +83,7 @@ export const TurnChangedFilesCard = memo(function TurnChangedFilesCard({ totals, projectPath, }: { - files: ChangedFileSummaryItem[]; + files: Array; totals: { additions: number; deletions: number }; projectPath?: string; }) { diff --git a/ui/src/components/agents/messages/UserMessage.tsx b/ui/src/components/agents/messages/UserMessage.tsx index f4b12585..4e5ed0de 100644 --- a/ui/src/components/agents/messages/UserMessage.tsx +++ b/ui/src/components/agents/messages/UserMessage.tsx @@ -5,7 +5,7 @@ import type { Message } from "@/lib/agents/types"; export function UserMessage({ message }: { message: Message }) { const text = message.chunks .filter((c) => c.kind === "text") - .map((c) => (c as { kind: "text"; text: string }).text) + .map((c) => c.text) .join(""); const images = message.chunks.filter((c) => c.kind === "image"); @@ -39,14 +39,12 @@ export function UserMessage({ message }: { message: Message }) { {images.length > 0 && (
{images.map((img, i) => ( - img.kind === "image" && ( - {img.fileName - ) + {img.fileName ))}
)} diff --git a/ui/src/components/agents/messages/WorkSummary.tsx b/ui/src/components/agents/messages/WorkSummary.tsx index 79d9c3aa..31936775 100644 --- a/ui/src/components/agents/messages/WorkSummary.tsx +++ b/ui/src/components/agents/messages/WorkSummary.tsx @@ -1,5 +1,6 @@ -import { useState, type ReactNode } from "react"; +import { useState } from "react"; import { ChevronRight } from "lucide-react"; +import type { ReactNode } from "react"; import { formatElapsed } from "@/lib/utils"; diff --git a/ui/src/components/agents/messages/renderItems.ts b/ui/src/components/agents/messages/renderItems.ts index 95f9d55d..c8386184 100644 --- a/ui/src/components/agents/messages/renderItems.ts +++ b/ui/src/components/agents/messages/renderItems.ts @@ -3,12 +3,12 @@ import type { Chunk, ToolExecutionChunk } from "@/lib/agents/types"; export type RenderItem = | { type: "text-chunk"; key: string; chunk: Chunk } | { type: "reasoning-item"; key: string; chunk: Chunk } - | { type: "explored-group"; key: string; id: string; chunks: ToolExecutionChunk[] } + | { type: "explored-group"; key: string; id: string; chunks: Array } /** * One or more `task` (subagent) tool calls collapsed into a single group so * they can be rendered side by side as a card grid (see subagents/SubagentGroup). */ - | { type: "subagent-group"; key: string; id: string; chunks: ToolExecutionChunk[] } + | { type: "subagent-group"; key: string; id: string; chunks: Array } | { type: "edit-item"; key: string; chunk: ToolExecutionChunk } | { type: "shell-item"; key: string; chunk: ToolExecutionChunk } | { type: "reply-item"; key: string; chunk: ToolExecutionChunk } @@ -68,11 +68,11 @@ function isSubagentTool(chunk: ToolExecutionChunk): boolean { return chunk.toolKind === "task"; } -export function buildRenderItems(chunks: Chunk[], messageId?: string): RenderItem[] { - const items: RenderItem[] = []; - let exploredBuffer: ToolExecutionChunk[] = []; +export function buildRenderItems(chunks: Array, messageId?: string): Array { + const items: Array = []; + let exploredBuffer: Array = []; let exploredStartIndex = -1; - let subagentBuffer: ToolExecutionChunk[] = []; + let subagentBuffer: Array = []; let subagentStartIndex = -1; const flushExplored = () => { @@ -165,7 +165,7 @@ export function buildRenderItems(chunks: Chunk[], messageId?: string): RenderIte return items; } -export function summarizeExploration(chunks: ToolExecutionChunk[]): string { +export function summarizeExploration(chunks: Array): string { const count = chunks.length; return `Explored ${count} file${count === 1 ? "" : "s"}`; } diff --git a/ui/src/components/agents/messages/summarizeChangedFiles.ts b/ui/src/components/agents/messages/summarizeChangedFiles.ts index c6721865..edc27845 100644 --- a/ui/src/components/agents/messages/summarizeChangedFiles.ts +++ b/ui/src/components/agents/messages/summarizeChangedFiles.ts @@ -1,9 +1,9 @@ -import { countLineChanges } from "@/components/agents/utils/diffStats"; -import type { Chunk, DiffData } from "@/lib/agents/types"; +import type { Chunk } from "@/lib/agents/types"; import type { ChangedFileSummaryItem } from "./types"; +import { countLineChanges } from "@/components/agents/utils/diffStats"; -export function summarizeChangedFiles(chunks: Chunk[]): ChangedFileSummaryItem[] { +export function summarizeChangedFiles(chunks: Array): Array { const byFile = new Map(); for (const chunk of chunks) { @@ -12,7 +12,7 @@ export function summarizeChangedFiles(chunks: Chunk[]): ChangedFileSummaryItem[] const diffEntries = chunk.diffs?.length ? chunk.diffs : (chunk.diffData ? [chunk.diffData] : []); if (diffEntries.length === 0) continue; - for (const diffData of diffEntries as DiffData[]) { + for (const diffData of diffEntries) { const existing = byFile.get(diffData.filePath); if (!existing) { diff --git a/ui/src/components/agents/messages/types.ts b/ui/src/components/agents/messages/types.ts index 6444d0f9..50713db5 100644 --- a/ui/src/components/agents/messages/types.ts +++ b/ui/src/components/agents/messages/types.ts @@ -20,7 +20,7 @@ export type MessagesScrollControl = { }; export interface MessagesProps extends ApprovalCallbacks { - messages: Message[]; + messages: Array; isStreaming: boolean; /** Live run signal from `useStream().isLoading` — drives Streamdown token animation. */ streamIsLoading?: boolean; diff --git a/ui/src/components/agents/ported/CodeBlock.tsx b/ui/src/components/agents/ported/CodeBlock.tsx index 9da907f0..517c4772 100644 --- a/ui/src/components/agents/ported/CodeBlock.tsx +++ b/ui/src/components/agents/ported/CodeBlock.tsx @@ -1,5 +1,6 @@ import { useEffect, useMemo, useState } from "react"; -import { getSingletonHighlighter, type ThemedToken } from "shiki"; +import { getSingletonHighlighter } from "shiki"; +import type { ThemedToken } from "shiki"; import { useResolvedTheme } from "@/lib/theme"; interface CodeBlockProps { @@ -9,7 +10,7 @@ interface CodeBlockProps { const SHIKI_THEME = { light: "github-light", dark: "github-dark" } as const; -const TOKEN_CACHE = new Map(); +const TOKEN_CACHE = new Map>>(); function normalizeLanguage(language?: string): string { const raw = (language || "").toLowerCase().trim(); @@ -45,7 +46,7 @@ function languageLabel(language: string): string { } export function CodeBlock({ text, language }: CodeBlockProps) { - const [tokens, setTokens] = useState(null); + const [tokens, setTokens] = useState> | null>(null); const [copied, setCopied] = useState(false); const resolvedTheme = useResolvedTheme(); const shikiTheme = SHIKI_THEME[resolvedTheme]; @@ -67,13 +68,11 @@ export function CodeBlock({ text, language }: CodeBlockProps) { getSingletonHighlighter({ themes: [shikiTheme], - // eslint-disable-next-line @typescript-eslint/no-explicit-any langs: [normalizedLanguage as any], }) .then((highlighter) => { if (cancelled) return; const result = highlighter.codeToTokens(text, { - // eslint-disable-next-line @typescript-eslint/no-explicit-any lang: normalizedLanguage as any, theme: shikiTheme, }); diff --git a/ui/src/components/agents/ported/CompactingIndicator.tsx b/ui/src/components/agents/ported/CompactingIndicator.tsx index c72e1fb1..b38c1810 100644 --- a/ui/src/components/agents/ported/CompactingIndicator.tsx +++ b/ui/src/components/agents/ported/CompactingIndicator.tsx @@ -1,5 +1,5 @@ import { LoaderCircle } from 'lucide-react'; -import { useState, useEffect } from 'react'; +import { useEffect, useState } from 'react'; export function CompactingIndicator() { const [dots, setDots] = useState(1); diff --git a/ui/src/components/agents/ported/DiffView.tsx b/ui/src/components/agents/ported/DiffView.tsx index 347d0394..243c814e 100644 --- a/ui/src/components/agents/ported/DiffView.tsx +++ b/ui/src/components/agents/ported/DiffView.tsx @@ -1,8 +1,8 @@ import { useMemo } from "react"; import { MultiFileDiff } from "@pierre/diffs/react"; +import type { DiffData } from "@/lib/agents/types"; import { diffOptions } from "@/components/agents/utils/diffUtils"; import { countLineChanges } from "@/components/agents/utils/diffStats"; -import type { DiffData } from "@/lib/agents/types"; interface DiffViewProps { diffData: DiffData; diff --git a/ui/src/components/agents/ported/Markdown.tsx b/ui/src/components/agents/ported/Markdown.tsx index 003460b9..38dff27b 100644 --- a/ui/src/components/agents/ported/Markdown.tsx +++ b/ui/src/components/agents/ported/Markdown.tsx @@ -1,5 +1,6 @@ -import { memo, type ReactNode } from "react"; +import { memo } from "react"; import { Streamdown } from "streamdown"; +import type { ReactNode } from "react"; import "streamdown/styles.css"; interface MarkdownProps { diff --git a/ui/src/components/agents/ported/MarkdownTable.tsx b/ui/src/components/agents/ported/MarkdownTable.tsx index 838a7874..5048f997 100644 --- a/ui/src/components/agents/ported/MarkdownTable.tsx +++ b/ui/src/components/agents/ported/MarkdownTable.tsx @@ -1,5 +1,7 @@ -// @ts-nocheck — ported from open-swe-app (Electron). -import { Children, isValidElement, type ReactNode } from 'react'; +import { Children, isValidElement } from 'react'; +import type { ReactNode } from 'react'; + +type ElementWithChildren = { children?: ReactNode }; interface MarkdownTableProps { children: ReactNode; @@ -9,17 +11,19 @@ function countCells(node: ReactNode): number { return Children.toArray(node).filter((child) => isValidElement(child) && (child.type === 'th' || child.type === 'td')).length; } -function collectColumnCounts(node: ReactNode, counts: number[]) { +function collectColumnCounts(node: ReactNode, counts: Array) { Children.forEach(node, (child) => { if (!isValidElement(child)) return; + const childProps = child.props as ElementWithChildren; + if (child.type === 'tr') { - const count = countCells(child.props.children); + const count = countCells(childProps.children); if (count > 0) counts.push(count); return; } - collectColumnCounts(child.props.children, counts); + collectColumnCounts(childProps.children, counts); }); } @@ -29,7 +33,7 @@ function getTableMinWidth(columnCount: number): string { } export function MarkdownTable({ children }: MarkdownTableProps) { - const columnCounts: number[] = []; + const columnCounts: Array = []; collectColumnCounts(children, columnCounts); const columnCount = Math.max(0, ...columnCounts); diff --git a/ui/src/components/agents/ported/ReplyCard.tsx b/ui/src/components/agents/ported/ReplyCard.tsx index c19be049..b1b2a4dd 100644 --- a/ui/src/components/agents/ported/ReplyCard.tsx +++ b/ui/src/components/agents/ported/ReplyCard.tsx @@ -36,7 +36,7 @@ function isSlackTextObject(value: unknown): value is SlackTextObject { ) } -function isSlackBlockArray(value: unknown): value is SlackBlock[] { +function isSlackBlockArray(value: unknown): value is Array { return ( Array.isArray(value) && value.every((block) => !!block && typeof block === "object") @@ -96,7 +96,7 @@ function renderSlackBody(text: string): Array { function blocksFromOptions( message: string, options: unknown -): SlackBlock[] | null { +): Array | null { if (!Array.isArray(options)) return null const cleanOptions = options.filter( (option): option is string => @@ -115,7 +115,7 @@ function blocksFromOptions( ] } -function renderSlackBlocks(blocks: SlackBlock[]): ReactNode { +function renderSlackBlocks(blocks: Array): ReactNode { return (
{blocks.map((block, index) => { diff --git a/ui/src/components/agents/ported/ShellCommand.tsx b/ui/src/components/agents/ported/ShellCommand.tsx index 0a5e20de..e53de8e7 100644 --- a/ui/src/components/agents/ported/ShellCommand.tsx +++ b/ui/src/components/agents/ported/ShellCommand.tsx @@ -1,4 +1,4 @@ -import { memo, useState, useRef, useCallback, useLayoutEffect } from "react"; +import { memo, useCallback, useLayoutEffect, useRef, useState } from "react"; import type { ToolExecutionChunk } from "@/lib/agents/types"; interface ShellCommandProps { diff --git a/ui/src/components/agents/ported/TodoList.tsx b/ui/src/components/agents/ported/TodoList.tsx index e237d575..2d003bee 100644 --- a/ui/src/components/agents/ported/TodoList.tsx +++ b/ui/src/components/agents/ported/TodoList.tsx @@ -1,4 +1,4 @@ -import { useRef, useEffect, useState } from "react"; +import { useEffect, useRef, useState } from "react"; import { CheckCircle2, ChevronDown, @@ -10,7 +10,7 @@ import { import type { TodoItem } from "@/lib/agents/types"; interface TodoListProps { - todos: TodoItem[]; + todos: Array; className?: string; runActive?: boolean; } diff --git a/ui/src/components/agents/ported/ToolExecution.tsx b/ui/src/components/agents/ported/ToolExecution.tsx index 8019b3f0..25f2e018 100644 --- a/ui/src/components/agents/ported/ToolExecution.tsx +++ b/ui/src/components/agents/ported/ToolExecution.tsx @@ -1,7 +1,7 @@ -import { memo, useState, useCallback, useMemo, useRef, useLayoutEffect } from "react"; +import { memo, useCallback, useLayoutEffect, useMemo, useRef, useState } from "react"; import { MultiFileDiff } from "@pierre/diffs/react"; -import type { ToolExecutionChunk, AcpToolKind } from "@/lib/agents/types"; import { DiffView } from "./DiffView"; +import type { AcpToolKind, ToolExecutionChunk } from "@/lib/agents/types"; import { useDiffOptions } from "@/components/agents/utils/diffUtils"; import { countLineChanges } from "@/components/agents/utils/diffStats"; @@ -204,7 +204,7 @@ export const ToolExecution = memo(function ToolExecution({ const editedFileName = editedFilePath ? getFileName(editedFilePath) : ""; const diffStats = diffData ? countLineChanges(diffData.originalContent, diffData.newContent, diffData.filePath) : null; - if (isCompletedEditOp && diffStats && diffData) { + if (isCompletedEditOp && diffStats) { return ( }) { const columns = Math.min(Math.max(chunks.length, 1), MAX_SUBAGENT_COLUMNS); return (
, streamIsLoading: boolean | undefined, isStreaming: boolean, ): string | null { diff --git a/ui/src/lib/hotkeys.ts b/ui/src/lib/hotkeys.ts index 54c3172d..d5c8367c 100644 --- a/ui/src/lib/hotkeys.ts +++ b/ui/src/lib/hotkeys.ts @@ -92,7 +92,7 @@ function isFormField(target: EventTarget | null): boolean { * (Cmd on macOS, Ctrl elsewhere). Accepts one combo or several aliases. */ export function useHotkey( - combo: string | string[], + combo: string | Array, handler: (event: KeyboardEvent) => void, options: HotkeyOptions = {} ) { diff --git a/ui/src/routes/agents/threads.tsx b/ui/src/routes/agents/threads.tsx index 24309ed4..06f1fc23 100644 --- a/ui/src/routes/agents/threads.tsx +++ b/ui/src/routes/agents/threads.tsx @@ -1,10 +1,8 @@ import { createFileRoute } from "@tanstack/react-router" import type { AgentSource, AgentStatus } from "@/lib/agents/types" -import { - AgentsThreadsPage, - type ThreadsPageFilters, -} from "@/components/agents/AgentsThreadsPage" +import type { ThreadsPageFilters } from "@/components/agents/AgentsThreadsPage"; +import { AgentsThreadsPage } from "@/components/agents/AgentsThreadsPage" const SOURCES: ReadonlyArray = [ "dashboard", diff --git a/ui/src/routes/cloud-agents.tsx b/ui/src/routes/cloud-agents.tsx index 0bec4cfa..1a83db84 100644 --- a/ui/src/routes/cloud-agents.tsx +++ b/ui/src/routes/cloud-agents.tsx @@ -228,7 +228,7 @@ function CloudAgentsPage() { label="Default Repository" description="Used when no repository is specified" control={ - repos.data?.repositories?.length ? ( + repos.data?.repositories.length ? (