Files
automaker/apps/ui/src/hooks/mutations/use-github-mutations.ts
Shirone 006152554b chore: Fix all lint errors and remove unused code
- Fix 75 ESLint errors by updating eslint.config.mjs:
  - Add missing browser globals (MouseEvent, AbortController, Response, etc.)
  - Add Vite define global (__APP_VERSION__)
  - Configure @ts-nocheck to require descriptions
  - Add no-unused-vars rule for .mjs scripts

- Fix runtime bug in agent-output-modal.tsx (setOutput -> setStreamedContent)

- Remove ~120 unused variable warnings across 97 files:
  - Remove unused imports (React hooks, lucide icons, types)
  - Remove unused constants and variables
  - Remove unused function definitions
  - Prefix intentionally unused parameters with underscore

- Add descriptions to all @ts-nocheck comments (25 files)

- Clean up misc issues:
  - Remove invalid deprecation plugin comments
  - Fix eslint-disable comment placement
  - Add missing RefreshCw import in code-view.tsx

Reduces lint warnings from ~300 to 67 (all remaining are no-explicit-any)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 17:33:45 +01:00

162 lines
4.5 KiB
TypeScript

/**
* GitHub Mutation Hooks
*
* React Query mutations for GitHub operations like validating issues.
*/
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { getElectronAPI, GitHubIssue, GitHubComment } from '@/lib/electron';
import { queryKeys } from '@/lib/query-keys';
import { toast } from 'sonner';
import type { LinkedPRInfo, ModelId } from '@automaker/types';
import { resolveModelString } from '@automaker/model-resolver';
/**
* Input for validating a GitHub issue
*/
interface ValidateIssueInput {
issue: GitHubIssue;
model?: ModelId;
thinkingLevel?: number;
reasoningEffort?: string;
comments?: GitHubComment[];
linkedPRs?: LinkedPRInfo[];
}
/**
* Validate a GitHub issue with AI
*
* This mutation triggers an async validation process. Results are delivered
* via WebSocket events (issue_validation_complete, issue_validation_error).
*
* @param projectPath - Path to the project
* @returns Mutation for validating issues
*
* @example
* ```tsx
* const validateMutation = useValidateIssue(projectPath);
*
* validateMutation.mutate({
* issue,
* model: 'sonnet',
* comments,
* linkedPRs,
* });
* ```
*/
export function useValidateIssue(projectPath: string) {
return useMutation({
mutationFn: async (input: ValidateIssueInput) => {
const { issue, model, thinkingLevel, reasoningEffort, comments, linkedPRs } = input;
const api = getElectronAPI();
if (!api.github?.validateIssue) {
throw new Error('Validation API not available');
}
const validationInput = {
issueNumber: issue.number,
issueTitle: issue.title,
issueBody: issue.body || '',
issueLabels: issue.labels.map((l) => l.name),
comments,
linkedPRs,
};
// Resolve model alias to canonical model identifier
const resolvedModel = model ? resolveModelString(model) : undefined;
const result = await api.github.validateIssue(
projectPath,
validationInput,
resolvedModel,
thinkingLevel,
reasoningEffort
);
if (!result.success) {
throw new Error(result.error || 'Failed to start validation');
}
return { issueNumber: issue.number };
},
onSuccess: (_, variables) => {
toast.info(`Starting validation for issue #${variables.issue.number}`, {
description: 'You will be notified when the analysis is complete',
});
},
onError: (error) => {
toast.error('Failed to validate issue', {
description: error instanceof Error ? error.message : 'Unknown error',
});
},
// Note: We don't invalidate queries here because the actual result
// comes through WebSocket events which handle cache invalidation
});
}
/**
* Mark a validation as viewed
*
* @param projectPath - Path to the project
* @returns Mutation for marking validation as viewed
*
* @example
* ```tsx
* const markViewedMutation = useMarkValidationViewed(projectPath);
* markViewedMutation.mutate(issueNumber);
* ```
*/
export function useMarkValidationViewed(projectPath: string) {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async (issueNumber: number) => {
const api = getElectronAPI();
if (!api.github?.markValidationViewed) {
throw new Error('Mark viewed API not available');
}
const result = await api.github.markValidationViewed(projectPath, issueNumber);
if (!result.success) {
throw new Error(result.error || 'Failed to mark as viewed');
}
return { issueNumber };
},
onSuccess: () => {
// Invalidate validations cache to refresh the viewed state
queryClient.invalidateQueries({
queryKey: queryKeys.github.validations(projectPath),
});
},
// Silent mutation - no toast needed for marking as viewed
});
}
/**
* Get running validation status
*
* @param projectPath - Path to the project
* @returns Mutation for getting validation status (returns running issue numbers)
*/
export function useGetValidationStatus(projectPath: string) {
return useMutation({
mutationFn: async () => {
const api = getElectronAPI();
if (!api.github?.getValidationStatus) {
throw new Error('Validation status API not available');
}
const result = await api.github.getValidationStatus(projectPath);
if (!result.success) {
throw new Error(result.error || 'Failed to get validation status');
}
return result.runningIssues ?? [];
},
});
}