diff --git a/packages/app/src/components/agent-status-bar.tsx b/packages/app/src/components/agent-status-bar.tsx index bd95960e0..dc66f27b5 100644 --- a/packages/app/src/components/agent-status-bar.tsx +++ b/packages/app/src/components/agent-status-bar.tsx @@ -226,7 +226,7 @@ function ControlledStatusBar({ const providerAnchorRef = useRef(null); const modeAnchorRef = useRef(null); - const modelAnchorRef = useRef(null); + const _modelAnchorRef = useRef(null); const thinkingAnchorRef = useRef(null); const canSelectProvider = Boolean( @@ -277,7 +277,7 @@ function ControlledStatusBar({ () => (modeOptions ?? []).map((o) => ({ id: o.id, label: o.label })), [modeOptions], ); - const comboboxModelOptions = useMemo( + const _comboboxModelOptions = useMemo( () => (modelOptions ?? []).map((o) => ({ id: o.id, label: o.label })), [modelOptions], ); @@ -462,11 +462,7 @@ function ControlledStatusBar({ ); const renderSheetModelTrigger = useCallback( ({ selectedModelLabel }: { selectedModelLabel: string }) => ( - + {ProviderIcon ? ( ) : null} @@ -1309,14 +1305,14 @@ export const AgentStatusBar = memo(function AgentStatusBar({ export function DraftAgentStatusBar({ providerDefinitions, selectedProvider, - onSelectProvider, + onSelectProvider: _onSelectProvider, modeOptions, selectedMode, onSelectMode, models, selectedModel, onSelectModel, - isModelLoading, + isModelLoading: _isModelLoading, allProviderModels, isAllModelsLoading, onSelectProviderAndModel, diff --git a/packages/app/src/components/agent-stream-view.tsx b/packages/app/src/components/agent-stream-view.tsx index f1ec0056f..eda768e89 100644 --- a/packages/app/src/components/agent-stream-view.tsx +++ b/packages/app/src/components/agent-stream-view.tsx @@ -614,7 +614,7 @@ const AgentStreamViewComponent = forwardRef + ) : null} {footer} diff --git a/packages/app/src/components/callout-card.test.tsx b/packages/app/src/components/callout-card.test.tsx index a5fc2e24a..15b81db7b 100644 --- a/packages/app/src/components/callout-card.test.tsx +++ b/packages/app/src/components/callout-card.test.tsx @@ -63,10 +63,7 @@ function buildSingleAction(onPress: () => void): CalloutCardActions { return [{ label: "Undo", onPress }]; } -function buildTwoActions( - onWhatsNew: () => void, - onInstall: () => void, -): CalloutCardActions { +function buildTwoActions(onWhatsNew: () => void, onInstall: () => void): CalloutCardActions { return [ { label: "What's new", onPress: onWhatsNew }, { label: "Install & restart", onPress: onInstall, variant: "primary" }, diff --git a/packages/app/src/components/combined-model-selector.tsx b/packages/app/src/components/combined-model-selector.tsx index c923b40bc..99bcbac38 100644 --- a/packages/app/src/components/combined-model-selector.tsx +++ b/packages/app/src/components/combined-model-selector.tsx @@ -295,7 +295,7 @@ function FavoritesSection({ canSelectProvider: (provider: string) => boolean; onToggleFavorite?: (provider: string, modelId: string) => void; }) { - const { theme } = useUnistyles(); + const { theme: _theme } = useUnistyles(); if (favoriteRows.length === 0) { return null; @@ -465,7 +465,7 @@ function SelectorContent({ selectedProvider, selectedModel, searchQuery, - onSearchChange, + onSearchChange: _onSearchChange, favoriteKeys, onSelect, canSelectProvider, @@ -492,7 +492,7 @@ function SelectorContent({ [normalizedQuery, scopedRows], ); - const { favoriteRows, regularRows } = useMemo( + const { favoriteRows, regularRows: _regularRows } = useMemo( () => partitionRows(visibleRows, favoriteKeys), [favoriteKeys, visibleRows], ); diff --git a/packages/app/src/components/composer.tsx b/packages/app/src/components/composer.tsx index 668b6d409..185534ee2 100644 --- a/packages/app/src/components/composer.tsx +++ b/packages/app/src/components/composer.tsx @@ -1241,8 +1241,6 @@ export function Composer({ ); } -const BUTTON_SIZE = 40; - const styles = StyleSheet.create(((theme: Theme) => ({ container: { flexDirection: "column", diff --git a/packages/app/src/components/diff-scroll.tsx b/packages/app/src/components/diff-scroll.tsx index ec66855d2..0acb2091d 100644 --- a/packages/app/src/components/diff-scroll.tsx +++ b/packages/app/src/components/diff-scroll.tsx @@ -20,7 +20,7 @@ interface DiffScrollProps { export function DiffScroll({ children, - scrollViewWidth, + scrollViewWidth: _scrollViewWidth, onScrollViewWidthChange, style, contentContainerStyle, diff --git a/packages/app/src/components/file-explorer-pane.tsx b/packages/app/src/components/file-explorer-pane.tsx index 626400225..45024ba68 100644 --- a/packages/app/src/components/file-explorer-pane.tsx +++ b/packages/app/src/components/file-explorer-pane.tsx @@ -144,10 +144,7 @@ function TreeRowItem({ return ( - {depth > 0 && - Array.from({ length: depth }, (_, i) => ( - - ))} + {depth > 0 && Array.from({ length: depth }, (_, i) => )} {(() => { @@ -968,10 +965,7 @@ interface IndentGuideProps { function IndentGuide({ index }: IndentGuideProps) { const { theme } = useUnistyles(); const guideStyle = useMemo( - () => [ - styles.indentGuide, - { left: theme.spacing[3] + index * INDENT_PER_LEVEL + 4 }, - ], + () => [styles.indentGuide, { left: theme.spacing[3] + index * INDENT_PER_LEVEL + 4 }], [index, theme.spacing], ); return ; diff --git a/packages/app/src/components/git-actions-policy.ts b/packages/app/src/components/git-actions-policy.ts index c08964498..30e7605f4 100644 --- a/packages/app/src/components/git-actions-policy.ts +++ b/packages/app/src/components/git-actions-policy.ts @@ -230,15 +230,6 @@ function canPush(input: BuildGitActionsInput): boolean { return input.hasRemote && input.aheadOfOrigin > 0 && input.behindOfOrigin === 0; } -function canMergeBranch(input: BuildGitActionsInput): boolean { - return ( - !input.isOnBaseBranch && - input.baseRefAvailable && - !input.hasUncommittedChanges && - input.aheadCount > 0 - ); -} - function canMergeFromBase(input: BuildGitActionsInput): boolean { return ( !input.isOnBaseBranch && diff --git a/packages/app/src/components/message-input.tsx b/packages/app/src/components/message-input.tsx index 74a72a6f8..f750d5250 100644 --- a/packages/app/src/components/message-input.tsx +++ b/packages/app/src/components/message-input.tsx @@ -430,7 +430,7 @@ export const MessageInput = forwardRef(funct const { isRecording: isDictating, isProcessing: isDictationProcessing, - partialTranscript: dictationPartialTranscript, + partialTranscript: _dictationPartialTranscript, volume: dictationVolume, duration: dictationDuration, error: dictationError, diff --git a/packages/app/src/components/message.tsx b/packages/app/src/components/message.tsx index 910cfdf4b..4f3f64e93 100644 --- a/packages/app/src/components/message.tsx +++ b/packages/app/src/components/message.tsx @@ -1177,10 +1177,7 @@ function AssistantMessageBlockContainer({ marginBottom, children, }: AssistantMessageBlockContainerProps) { - const style = useMemo( - () => (marginBottom > 0 ? { marginBottom } : undefined), - [marginBottom], - ); + const style = useMemo(() => (marginBottom > 0 ? { marginBottom } : undefined), [marginBottom]); return {children}; } @@ -1773,18 +1770,13 @@ function TodoListItemRow({ text, completed }: TodoListItemRowProps) { [completed], ); const textStyle = useMemo( - () => [ - todoListCardStylesheet.itemText, - completed && todoListCardStylesheet.itemTextCompleted, - ], + () => [todoListCardStylesheet.itemText, completed && todoListCardStylesheet.itemTextCompleted], [completed], ); return ( - {completed ? ( - - ) : null} + {completed ? : null} {text} @@ -1836,7 +1828,7 @@ export const TodoListCard = memo(function TodoListCard({ items, disableOuterSpacing, }: TodoListCardProps) { - const { theme: unistylesTheme } = useUnistyles(); + const { theme: _unistylesTheme } = useUnistyles(); const [isExpanded, setIsExpanded] = useState(false); const nextTask = useMemo(() => items.find((item) => !item.completed)?.text, [items]); diff --git a/packages/app/src/components/sidebar-workspace-list.tsx b/packages/app/src/components/sidebar-workspace-list.tsx index eb87aea26..ee530ac01 100644 --- a/packages/app/src/components/sidebar-workspace-list.tsx +++ b/packages/app/src/components/sidebar-workspace-list.tsx @@ -709,7 +709,7 @@ function useLongPressDragInteraction(input: { }, [clearTimers, input.menuController, openContextMenuAtStartPoint]); const handleDragIntent = useCallback( - (details: { dx: number; dy: number; distance: number }) => { + (_details: { dx: number; dy: number; distance: number }) => { if (!dragActivatedRef.current) { return; } @@ -722,7 +722,7 @@ function useLongPressDragInteraction(input: { ); const handleScrollIntent = useCallback( - (details: { dx: number; dy: number; distance: number }) => { + (_details: { dx: number; dy: number; distance: number }) => { scrollIntentRef.current = true; didLongPressRef.current = true; clearTimers(); @@ -731,7 +731,7 @@ function useLongPressDragInteraction(input: { ); const handleSwipeIntent = useCallback( - (details: { dx: number; dy: number; distance: number }) => { + (_details: { dx: number; dy: number; distance: number }) => { didLongPressRef.current = true; clearTimers(); }, @@ -831,7 +831,7 @@ function ProjectHeaderRow({ canCreateWorktree, isProjectActive = false, onWorkspacePress, - onWorktreeCreated, + onWorktreeCreated: _onWorktreeCreated, shortcutNumber = null, showShortcutBadge = false, drag, @@ -854,8 +854,8 @@ function ProjectHeaderRow({ ); onWorkspacePress?.(); }, [displayName, onWorkspacePress, project.iconWorkingDir, serverId]); - const mergeWorkspaces = useSessionStore((state) => state.mergeWorkspaces); - const toast = useToast(); + const _mergeWorkspaces = useSessionStore((state) => state.mergeWorkspaces); + const _toast = useToast(); const interaction = useLongPressDragInteraction({ drag, @@ -1025,7 +1025,7 @@ function WorkspaceRowInner({ archiveShortcutKeys, }: WorkspaceRowInnerProps) { const { theme } = useUnistyles(); - const isCompact = useIsCompactFormFactor(); + const _isCompact = useIsCompactFormFactor(); const [isHovered, setIsHovered] = useState(false); const isTouchPlatform = platformIsNative; const workspaceDirectory = resolveWorkspaceExecutionDirectory({ @@ -2000,8 +2000,8 @@ export function SidebarWorkspaceList({ collapsedProjectKeys, onToggleProjectCollapsed, shortcutIndexByWorkspaceKey, - isRefreshing = false, - onRefresh, + isRefreshing: _isRefreshing = false, + onRefresh: _onRefresh, onWorkspacePress, onAddProject, listFooterComponent, diff --git a/packages/app/src/components/split-container.tsx b/packages/app/src/components/split-container.tsx index 412774450..205fb5567 100644 --- a/packages/app/src/components/split-container.tsx +++ b/packages/app/src/components/split-container.tsx @@ -814,7 +814,7 @@ function SplitPaneView({ onCreateTerminalTab, buildPaneContentModel, onFocusPane, - onSplitPane, + onSplitPane: _onSplitPane, onSplitPaneEmpty, onReorderTabsInPane, renderPaneEmptyState, @@ -823,7 +823,7 @@ function SplitPaneView({ dropPreview, tabDropPreview, }: SplitPaneViewProps) { - const { theme } = useUnistyles(); + const { theme: _theme } = useUnistyles(); const paneRef = useRef(null); const stableOnFocusPane = useStableEvent(onFocusPane); const padding = useWindowControlsPadding("tabRow"); diff --git a/packages/app/src/components/synced-loader.tsx b/packages/app/src/components/synced-loader.tsx index a4e794eca..b8324e020 100644 --- a/packages/app/src/components/synced-loader.tsx +++ b/packages/app/src/components/synced-loader.tsx @@ -13,7 +13,6 @@ const SYNCED_LOADER_DURATION_MS = 950; const SYNCED_LOADER_EPOCH_MS = 0; const DOT_SEQUENCE = [0, 1, 3, 5, 4, 2] as const; const DOT_COUNT = DOT_SEQUENCE.length; -const GRID_ROWS = 3; const GRID_COLUMNS = 2; const SNAKE_SEGMENT_OFFSETS = [0, -1, -2, -3, -4] as const; const SNAKE_OPACITIES = [1, 0.78, 0.56, 0.34, 0] as const; diff --git a/packages/app/src/components/ui/combobox.tsx b/packages/app/src/components/ui/combobox.tsx index 46d89a95b..1015b6124 100644 --- a/packages/app/src/components/ui/combobox.tsx +++ b/packages/app/src/components/ui/combobox.tsx @@ -440,7 +440,7 @@ export function Combobox({ } const measure = () => { - referenceEl.measureInWindow((x, y, width, height) => { + referenceEl.measureInWindow((x, y, width, _height) => { setReferenceLeft((prev) => (prev === x ? prev : x)); setReferenceAtOrigin(Math.abs(x) <= 1 && Math.abs(y) <= 1); setReferenceTop((prev) => (prev === y ? prev : y)); diff --git a/packages/app/src/components/use-bottom-anchor-controller.ts b/packages/app/src/components/use-bottom-anchor-controller.ts index 7de3e56cc..00fe07a2f 100644 --- a/packages/app/src/components/use-bottom-anchor-controller.ts +++ b/packages/app/src/components/use-bottom-anchor-controller.ts @@ -57,18 +57,6 @@ interface ScheduledFrameHandle { callback: () => void; } -type BottomAnchorEvent = - | "request_created" - | "evaluate_called" - | "attempt_started" - | "attempt_verified" - | "attempt_failed" - | "request_fulfilled" - | "request_cancelled" - | "detached_by_user" - | "verification_scheduled" - | "blocked_reason_changed"; - interface BottomAnchorControllerDriver { destroy: () => void; getSnapshot: () => { @@ -242,25 +230,6 @@ function shouldRequireRouteRequestConfirmation(input: { return input.confirmationPasses < 1; } -function getDetailedMeasurementState( - measurementState: ControllerMeasurementState, -): Record { - const distanceFromBottom = Math.max( - 0, - measurementState.contentHeight - (measurementState.offsetY + measurementState.viewportHeight), - ); - return { - containerKey: measurementState.containerKey, - viewportWidth: measurementState.viewportWidth, - viewportHeight: measurementState.viewportHeight, - contentHeight: measurementState.contentHeight, - offsetY: measurementState.offsetY, - distanceFromBottom, - viewportMeasuredForKey: measurementState.viewportMeasuredForKey, - contentMeasuredForKey: measurementState.contentMeasuredForKey, - }; -} - function createBottomAnchorControllerDriver( input: CreateBottomAnchorControllerDriverInput, ): BottomAnchorControllerDriver { @@ -275,7 +244,7 @@ function createBottomAnchorControllerDriver( let stickyMeasurementRevision = 0; let lastVerifiedStickyMeasurementRevision = 0; - const getLogContext = (extra?: Record) => { + const _getLogContext = (extra?: Record) => { const measurementState = input.getMeasurementState(); const distanceFromBottom = Math.max( 0, @@ -336,7 +305,7 @@ function createBottomAnchorControllerDriver( pendingVerification = null; }; - const cancelPendingRequest = (reason: string) => { + const cancelPendingRequest = (_reason: string) => { const currentRequest = pendingRequest; if (!currentRequest) { cancelPendingAttempt(); @@ -358,7 +327,7 @@ function createBottomAnchorControllerDriver( }); const scheduleVerification = (attemptContext: AttemptContext, delayFramesOverride?: number) => { - const scheduledMeasurementState = input.getMeasurementState(); + const _scheduledMeasurementState = input.getMeasurementState(); if (verificationHandle) { input.cancelFrame(verificationHandle); } @@ -461,7 +430,7 @@ function createBottomAnchorControllerDriver( const evaluate = ( animated: boolean, - reason: + _reason: | "request_created" | "viewport_change" | "content_size_change" @@ -660,7 +629,7 @@ export const __private__ = { deriveBottomAnchorBlockedReason, deriveVerificationBlockedReason, deriveRetryDisposition, - deriveModeForLocalRequest(input: { + deriveModeForLocalRequest(_input: { reason: BottomAnchorLocalRequest["reason"]; }): BottomAnchorMode { return "sticky-bottom"; diff --git a/packages/app/src/contexts/session-context.tsx b/packages/app/src/contexts/session-context.tsx index 1563fe63b..f7f4e16e9 100644 --- a/packages/app/src/contexts/session-context.tsx +++ b/packages/app/src/contexts/session-context.tsx @@ -165,21 +165,7 @@ const getLatestPermissionRequest = ( return null; }; -type FileExplorerPayload = Extract< - SessionOutboundMessage, - { type: "file_explorer_response" } ->["payload"]; - -type FileDownloadTokenPayload = Extract< - SessionOutboundMessage, - { type: "file_download_token_response" } ->["payload"]; - type AgentUpdatePayload = Extract["payload"]; -type WorkspaceUpdatePayload = Extract< - SessionOutboundMessage, - { type: "workspace_update" } ->["payload"]; type WorkspaceSetupProgressPayload = Extract< SessionOutboundMessage, { type: "workspace_setup_progress" } @@ -310,7 +296,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider ) => Promise) | null >(null); - const sessionStateTimeoutRef = useRef | null>(null); + const _sessionStateTimeoutRef = useRef | null>(null); const attentionNotifiedRef = useRef>(new Map()); const appStateRef = useRef(AppState.currentState); const revalidationTimerRef = useRef | null>(null); @@ -1583,7 +1569,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider // Keep the ref updated so the agent_update handler can call it sendAgentMessageRef.current = sendAgentMessage; - const cancelAgentRun = useCallback( + const _cancelAgentRun = useCallback( (agentId: string) => { if (!client) { console.warn("[Session] cancelAgent skipped: daemon unavailable"); @@ -1596,7 +1582,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client], ); - const deleteAgent = useCallback( + const _deleteAgent = useCallback( (agentId: string) => { if (!client) { console.warn("[Session] deleteAgent skipped: daemon unavailable"); @@ -1609,7 +1595,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client], ); - const archiveAgent = useCallback( + const _archiveAgent = useCallback( (agentId: string) => { if (!client) { console.warn("[Session] archiveAgent skipped: daemon unavailable"); @@ -1622,7 +1608,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client], ); - const restartServer = useCallback( + const _restartServer = useCallback( (reason?: string) => { if (!client) { console.warn("[Session] restartServer skipped: daemon unavailable"); @@ -1635,7 +1621,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client], ); - const createAgent = useCallback( + const _createAgent = useCallback( async ({ config, initialPrompt, @@ -1677,7 +1663,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client], ); - const setAgentMode = useCallback( + const _setAgentMode = useCallback( (agentId: string, modeId: string) => { if (!client) { console.warn("[Session] setAgentMode skipped: daemon unavailable"); @@ -1691,7 +1677,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client, toast], ); - const setAgentModel = useCallback( + const _setAgentModel = useCallback( (agentId: string, modelId: string | null) => { if (!client) { console.warn("[Session] setAgentModel skipped: daemon unavailable"); @@ -1705,7 +1691,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client, toast], ); - const setAgentThinkingOption = useCallback( + const _setAgentThinkingOption = useCallback( (agentId: string, thinkingOptionId: string | null) => { if (!client) { console.warn("[Session] setAgentThinkingOption skipped: daemon unavailable"); @@ -1719,7 +1705,7 @@ function SessionProviderInternal({ children, serverId, client }: SessionProvider [client, toast], ); - const respondToPermission = useCallback( + const _respondToPermission = useCallback( (agentId: string, requestId: string, response: any) => { if (!client) { console.warn("[Session] respondToPermission skipped: daemon unavailable"); diff --git a/packages/app/src/contexts/session-stream-reducers.test.ts b/packages/app/src/contexts/session-stream-reducers.test.ts index ce021a52b..4eb3279b3 100644 --- a/packages/app/src/contexts/session-stream-reducers.test.ts +++ b/packages/app/src/contexts/session-stream-reducers.test.ts @@ -37,14 +37,6 @@ function makeTimelineEvent( } as AgentStreamEventPayload; } -function makeUserTimelineEvent(text: string): AgentStreamEventPayload { - return { - type: "timeline", - provider: "claude", - item: { type: "user_message", text }, - } as AgentStreamEventPayload; -} - function makeToolCallTimelineEvent(callId: string): AgentStreamEventPayload { return { type: "timeline", diff --git a/packages/app/src/hooks/use-agent-form-state.ts b/packages/app/src/hooks/use-agent-form-state.ts index be93c0241..4902bab77 100644 --- a/packages/app/src/hooks/use-agent-form-state.ts +++ b/packages/app/src/hooks/use-agent-form-state.ts @@ -371,7 +371,7 @@ export function useAgentFormState(options: UseAgentFormStateOptions = {}): UseAg initialValues, isVisible = true, isCreateFlow = true, - isTargetDaemonReady = true, + isTargetDaemonReady: _isTargetDaemonReady = true, onlineServerIds = [], } = options; diff --git a/packages/app/src/hooks/use-command-center.ts b/packages/app/src/hooks/use-command-center.ts index 35328748c..07680beb5 100644 --- a/packages/app/src/hooks/use-command-center.ts +++ b/packages/app/src/hooks/use-command-center.ts @@ -123,7 +123,7 @@ function resolveActionShortcutKeys( } export function useCommandCenter() { - const pathname = usePathname(); + const _pathname = usePathname(); const routeActiveServerId = useActiveServerId(); const { overrides } = useKeyboardShortcutOverrides(); const open = useKeyboardShortcutsStore((s) => s.commandCenterOpen); diff --git a/packages/app/src/panels/agent-panel.tsx b/packages/app/src/panels/agent-panel.tsx index 0cbd984bd..3a71d91f6 100644 --- a/packages/app/src/panels/agent-panel.tsx +++ b/packages/app/src/panels/agent-panel.tsx @@ -311,7 +311,7 @@ function AgentPanelBody({ onOpenWorkspaceFile?: (input: { filePath: string }) => void; }) { const { theme } = useUnistyles(); - const { isArchivingAgent } = useArchiveAgent(); + const { isArchivingAgent: _isArchivingAgent } = useArchiveAgent(); const hasSession = useSessionStore((state) => Boolean(state.sessions[serverId])); const projectPlacement = useStoreWithEqualityFn( useSessionStore, @@ -445,8 +445,6 @@ function AgentPanelBody({ ); } - const isArchivingCurrentAgent = Boolean(agentId && isArchivingAgent({ serverId, agentId })); - return ( { + mutationFn: async (_input?: { paneId?: string }) => { if (!client || !workspaceDirectory) { throw new Error("Host is not connected"); } @@ -1100,12 +1100,12 @@ function WorkspaceScreenContent({ const paneFocusSuppressedRef = useRef(false); const resizeWorkspaceSplit = useWorkspaceLayoutStore((state) => state.resizeSplit); const reorderWorkspaceTabsInPane = useWorkspaceLayoutStore((state) => state.reorderTabsInPane); - const pinnedAgentIds = useWorkspaceLayoutStore((state) => + const _pinnedAgentIds = useWorkspaceLayoutStore((state) => persistenceKey ? (state.pinnedAgentIdsByWorkspace[persistenceKey] ?? EMPTY_PINNED_AGENT_IDS) : EMPTY_PINNED_AGENT_IDS, ); - const hiddenAgentIds = useWorkspaceLayoutStore((state) => + const _hiddenAgentIds = useWorkspaceLayoutStore((state) => persistenceKey ? (state.hiddenAgentIdsByWorkspace[persistenceKey] ?? EMPTY_SET) : EMPTY_SET, ); const pendingByDraftId = useCreateFlowStore((state) => state.pendingByDraftId); @@ -1164,16 +1164,6 @@ function WorkspaceScreenContent({ }; }, [isRouteFocused, normalizedServerId, setFocusedAgentId]); - const ensureWorkspaceTab = useCallback( - function ensureWorkspaceTab(target: WorkspaceTabTarget): string | null { - if (!persistenceKey) { - return null; - } - return openWorkspaceTabInBackground(persistenceKey, target); - }, - [openWorkspaceTabInBackground, persistenceKey], - ); - const openWorkspaceDraftTab = useCallback( function openWorkspaceDraftTab(input?: { draftId?: string; focus?: boolean }) { if (!persistenceKey) { @@ -1429,7 +1419,7 @@ function WorkspaceScreenContent({ [handleOpenFileFromExplorer], ); - const [hoveredTabKey, setHoveredTabKey] = useState(null); + const [_hoveredTabKey, setHoveredTabKey] = useState(null); const [hoveredCloseTabKey, setHoveredCloseTabKey] = useState(null); const tabByKey = useMemo(() => { diff --git a/packages/app/src/stores/workspace-layout-actions.ts b/packages/app/src/stores/workspace-layout-actions.ts index 11e34f936..af75dcfeb 100644 --- a/packages/app/src/stores/workspace-layout-actions.ts +++ b/packages/app/src/stores/workspace-layout-actions.ts @@ -48,11 +48,6 @@ interface ReorderTabsForPaneInput { tabIds: string[]; } -interface UpdateTabInTreeInput { - tabId: string; - target: WorkspaceTabTarget; -} - interface UpdateGroupSizesInTreeInput { groupId: string; sizes: number[]; @@ -760,23 +755,6 @@ function focusTabInPane(root: SplitNodeInternal, paneId: string, tabId: string): }); } -function updateTabInTree(root: SplitNodeInternal, input: UpdateTabInTreeInput): SplitNodeInternal { - const panePath = findPanePathContainingTab(root, input.tabId); - invariant(panePath, `Tab not found: ${input.tabId}`); - return replaceNodeAtPath(root, panePath, (node) => { - invariant(node.kind === "pane", "Expected pane while retargeting tab"); - return { - kind: "pane", - pane: normalizePaneAfterTabChange({ - ...node.pane, - tabs: node.pane.tabs.map((tab) => - tab.tabId === input.tabId ? { ...tab, target: input.target } : tab, - ), - }), - }; - }); -} - function replaceTabInTree( root: SplitNodeInternal, input: { diff --git a/packages/app/src/voice/voice-runtime.ts b/packages/app/src/voice/voice-runtime.ts index 073154371..20e279c3b 100644 --- a/packages/app/src/voice/voice-runtime.ts +++ b/packages/app/src/voice/voice-runtime.ts @@ -238,7 +238,6 @@ export function createVoiceRuntime(deps: VoiceRuntimeDeps): VoiceRuntime { if (snapshotsEqual(next, state.snapshot)) { return; } - const previous = state.snapshot; state.snapshot = next; emit(); } diff --git a/packages/server/src/utils/project-icon.ts b/packages/server/src/utils/project-icon.ts index 729b8944a..7e04a1487 100644 --- a/packages/server/src/utils/project-icon.ts +++ b/packages/server/src/utils/project-icon.ts @@ -219,20 +219,19 @@ async function findIconInDir(dir: string, patterns: string[]): Promise isExistingFile(p))); + const foundIndex = existsResults.findIndex((exists) => exists); + return foundIndex === -1 ? null : (candidatePaths[foundIndex] ?? null); } async function searchPriorityDirs( @@ -240,22 +239,18 @@ async function searchPriorityDirs( ignoredDirsSet: Set, remainingDepth: number, ): Promise { - for (const priorityDir of PRIORITY_DIRS) { - const priorityPath = join(basePath, priorityDir); - if (!(await isExistingDirectory(priorityPath))) { - continue; - } - const result = await searchDirRecursively( - priorityPath, - ICON_PATTERNS, - ignoredDirsSet, - remainingDepth, - ); - if (result) { - return result; - } - } - return null; + const priorityPaths = PRIORITY_DIRS.map((priorityDir) => join(basePath, priorityDir)); + const existenceResults = await Promise.all( + priorityPaths.map((priorityPath) => isExistingDirectory(priorityPath)), + ); + const searchResults = await Promise.all( + priorityPaths.map((priorityPath, index) => + existenceResults[index] + ? searchDirRecursively(priorityPath, ICON_PATTERNS, ignoredDirsSet, remainingDepth) + : Promise.resolve(null), + ), + ); + return searchResults.find((result): result is string => result !== null) ?? null; } async function searchDirRecursively( @@ -283,28 +278,20 @@ async function searchDirRecursively( return null; } - for (const entry of entries) { - if (ignoredDirs.has(entry)) { - continue; - } - - const fullPath = join(dir, entry); - if (!(await isExistingDirectory(fullPath))) { - continue; - } - const result = await searchDirRecursively( - fullPath, - patterns, - ignoredDirs, - maxDepth, - currentDepth + 1, - ); - if (result) { - return result; - } - } - - return null; + const candidatePaths = entries + .filter((entry) => !ignoredDirs.has(entry)) + .map((entry) => join(dir, entry)); + const isDirResults = await Promise.all( + candidatePaths.map((fullPath) => isExistingDirectory(fullPath)), + ); + const recursionResults = await Promise.all( + candidatePaths.map((fullPath, index) => + isDirResults[index] + ? searchDirRecursively(fullPath, patterns, ignoredDirs, maxDepth, currentDepth + 1) + : Promise.resolve(null), + ), + ); + return recursionResults.find((result): result is string => result !== null) ?? null; } /** @@ -328,36 +315,42 @@ export async function findProjectIcon( } // Then search monorepo package directories (packages/*, apps/*) - for (const monoDir of MONOREPO_PACKAGE_DIRS) { - const monoPath = join(projectDir, monoDir); - let packageEntries: string[]; - try { - packageEntries = await readdir(monoPath); - } catch { - continue; - } - - for (const packageName of packageEntries) { - const packagePath = join(monoPath, packageName); - if (!(await isExistingDirectory(packagePath))) { - continue; + const monoPaths = MONOREPO_PACKAGE_DIRS.map((monoDir) => join(projectDir, monoDir)); + const monoEntries = await Promise.all( + monoPaths.map(async (monoPath): Promise => { + try { + return await readdir(monoPath); + } catch { + return null; } - - const packagePriorityResult = await searchPriorityDirs( - packagePath, - ignoredDirsSet, - maxDepth - 1, + }), + ); + const monoResults = await Promise.all( + monoPaths.map(async (monoPath, monoIdx): Promise => { + const packageEntries = monoEntries[monoIdx]; + if (!packageEntries) return null; + const packagePaths = packageEntries.map((packageName) => join(monoPath, packageName)); + const isDirResults = await Promise.all( + packagePaths.map((packagePath) => isExistingDirectory(packagePath)), ); - if (packagePriorityResult) { - return packagePriorityResult; - } - - // Search package root - const found = await findIconInDir(packagePath, ICON_PATTERNS); - if (found) { - return found; - } - } + const packageResults = await Promise.all( + packagePaths.map(async (packagePath, idx): Promise => { + if (!isDirResults[idx]) return null; + const priorityResult = await searchPriorityDirs( + packagePath, + ignoredDirsSet, + maxDepth - 1, + ); + if (priorityResult) return priorityResult; + return await findIconInDir(packagePath, ICON_PATTERNS); + }), + ); + return packageResults.find((result): result is string => result !== null) ?? null; + }), + ); + const monoMatch = monoResults.find((result): result is string => result !== null); + if (monoMatch) { + return monoMatch; } // Then search root and any other non-priority directories @@ -399,22 +392,20 @@ async function findDirRecursively( return null; } - for (const entry of entries) { - if (ignoredDirsSet.has(entry) || priorityDirsSet.has(entry)) { - continue; - } - - const fullPath = join(dir, entry); - if (!(await isExistingDirectory(fullPath))) { - continue; - } - const result = await findDirRecursively(fullPath, maxDepth, currentDepth + 1); - if (result) { - return result; - } - } - - return null; + const candidatePaths = entries + .filter((entry) => !ignoredDirsSet.has(entry) && !priorityDirsSet.has(entry)) + .map((entry) => join(dir, entry)); + const isDirResults = await Promise.all( + candidatePaths.map((fullPath) => isExistingDirectory(fullPath)), + ); + const recursionResults = await Promise.all( + candidatePaths.map((fullPath, index) => + isDirResults[index] + ? findDirRecursively(fullPath, maxDepth, currentDepth + 1) + : Promise.resolve(null), + ), + ); + return recursionResults.find((result): result is string => result !== null) ?? null; } /**