chore: Fix all 246 TypeScript errors in UI

- Extended SetupAPI interface with 20+ missing methods for Cursor, Codex,
  OpenCode, Gemini, and Copilot CLI integrations
- Fixed WorktreeInfo type to include isCurrent and hasWorktree fields
- Added null checks for optional API properties across all hooks
- Fixed Feature type conflicts between @automaker/types and local definitions
- Added missing CLI status hooks for all providers
- Fixed type mismatches in mutation callbacks and event handlers
- Removed dead code referencing non-existent GlobalSettings properties
- Updated mock implementations in electron.ts for all new API methods

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Shirone
2026-01-25 18:36:47 +01:00
parent 0fb471ca15
commit 5c335641fa
48 changed files with 1071 additions and 336 deletions

View File

@@ -1,6 +1,5 @@
import { memo, useEffect, useState, useMemo, useRef } from 'react';
import { Feature, ThinkingLevel, ParsedTask } from '@/store/app-store';
import type { ReasoningEffort } from '@automaker/types';
import { Feature, ThinkingLevel, ReasoningEffort, ParsedTask } from '@/store/app-store';
import { getProviderFromModel } from '@/lib/utils';
import { parseAgentContext, formatModelName, DEFAULT_MODEL } from '@/lib/agent-context-parser';
import { cn } from '@/lib/utils';
@@ -290,7 +289,8 @@ export const AgentInfoPanel = memo(function AgentInfoPanel({
// Agent Info Panel for non-backlog cards
// Show panel if we have agentInfo OR planSpec.tasks (for spec/full mode)
// Note: hasPlanSpecTasks is already defined above and includes freshPlanSpec
if (feature.status !== 'backlog' && (agentInfo || hasPlanSpecTasks)) {
// (The backlog case was already handled above and returned early)
if (agentInfo || hasPlanSpecTasks) {
return (
<>
<div className="mb-3 space-y-2 overflow-hidden">

View File

@@ -23,14 +23,7 @@ import { getHttpApiClient } from '@/lib/http-api-client';
import { toast } from 'sonner';
import { GitMerge, RefreshCw, AlertTriangle } from 'lucide-react';
import { Spinner } from '@/components/ui/spinner';
interface WorktreeInfo {
path: string;
branch: string;
isMain: boolean;
hasChanges?: boolean;
changedFilesCount?: number;
}
import type { WorktreeInfo } from '../worktree-panel/types';
interface RemoteBranch {
name: string;
@@ -49,7 +42,7 @@ interface PullResolveConflictsDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
worktree: WorktreeInfo | null;
onConfirm: (worktree: WorktreeInfo, remoteBranch: string) => void;
onConfirm: (worktree: WorktreeInfo, remoteBranch: string) => void | Promise<void>;
}
export function PullResolveConflictsDialog({

View File

@@ -128,10 +128,9 @@ export function useBoardDragDrop({
const targetBranch = worktreeData.branch;
const currentBranch = draggedFeature.branchName;
// For main worktree, set branchName to null to indicate it should use main
// (must use null not undefined so it serializes to JSON for the API call)
// For main worktree, set branchName to undefined to indicate it should use main
// For other worktrees, set branchName to the target branch
const newBranchName = worktreeData.isMain ? null : targetBranch;
const newBranchName: string | undefined = worktreeData.isMain ? undefined : targetBranch;
// If already on the same branch, nothing to do
// For main worktree: feature with null/undefined branchName is already on main

View File

@@ -185,8 +185,8 @@ export function useBoardFeatures({ currentProject }: UseBoardFeaturesProps) {
features,
isLoading,
persistedCategories,
loadFeatures: () => {
queryClient.invalidateQueries({
loadFeatures: async () => {
await queryClient.invalidateQueries({
queryKey: queryKeys.features.all(currentProject?.path ?? ''),
});
},

View File

@@ -1,5 +1,6 @@
import { useCallback } from 'react';
import { useQueryClient } from '@tanstack/react-query';
import type { Feature as ApiFeature } from '@automaker/types';
import { Feature } from '@/store/app-store';
import { getElectronAPI } from '@/lib/electron';
import { useAppStore } from '@/store/app-store';
@@ -48,14 +49,14 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
feature: result.feature,
});
if (result.success && result.feature) {
const updatedFeature = result.feature;
updateFeature(updatedFeature.id, updatedFeature);
const updatedFeature = result.feature as Feature;
updateFeature(updatedFeature.id, updatedFeature as Partial<Feature>);
queryClient.setQueryData<Feature[]>(
queryKeys.features.all(currentProject.path),
(features) => {
if (!features) return features;
return features.map((feature) =>
feature.id === updatedFeature.id ? updatedFeature : feature
feature.id === updatedFeature.id ? { ...feature, ...updatedFeature } : feature
);
}
);
@@ -85,9 +86,9 @@ export function useBoardPersistence({ currentProject }: UseBoardPersistenceProps
return;
}
const result = await api.features.create(currentProject.path, feature);
const result = await api.features.create(currentProject.path, feature as ApiFeature);
if (result.success && result.feature) {
updateFeature(result.feature.id, result.feature);
updateFeature(result.feature.id, result.feature as Partial<Feature>);
// Invalidate React Query cache to sync UI
queryClient.invalidateQueries({
queryKey: queryKeys.features.all(currentProject.path),

View File

@@ -6,6 +6,7 @@ import {
useEffect,
type RefObject,
type ReactNode,
type UIEvent,
} from 'react';
import { DragOverlay } from '@dnd-kit/core';
import { SortableContext, verticalListSortingStrategy } from '@dnd-kit/sortable';
@@ -79,7 +80,7 @@ const REDUCED_CARD_OPACITY_PERCENT = 85;
type VirtualListItem = { id: string };
interface VirtualListState<Item extends VirtualListItem> {
contentRef: RefObject<HTMLDivElement>;
contentRef: RefObject<HTMLDivElement | null>;
onScroll: (event: UIEvent<HTMLDivElement>) => void;
itemIds: string[];
visibleItems: Item[];

View File

@@ -26,6 +26,9 @@ export function useAvailableEditors() {
const { mutate: refreshMutate, isPending: isRefreshing } = useMutation({
mutationFn: async () => {
const api = getElectronAPI();
if (!api.worktree) {
throw new Error('Worktree API not available');
}
const result = await api.worktree.refreshEditors();
if (!result.success) {
throw new Error(result.error || 'Failed to refresh editors');