diff --git a/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts index a8f1ca12..2b5871b2 100644 --- a/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts +++ b/apps/frontend/src/main/ipc-handlers/github/investigation-handlers.ts @@ -36,7 +36,7 @@ import { readSettingsFile } from '../../settings-utils'; import { AgentManager } from '../../agent'; import { getGitHubConfig, githubFetch } from './utils'; import type { GitHubAPIComment } from './types'; -import { createSpecForIssue, buildIssueContext, buildInvestigationTask } from './spec-utils'; +import { createSpecForIssue, buildIssueContext, buildInvestigationTask, updateImplementationPlanStatus } from './spec-utils'; import { createContextLogger } from './utils/logger'; import { withProjectOrNull } from './utils/project-middleware'; import { createIPCCommunicators } from './utils/ipc-communicator'; diff --git a/apps/frontend/src/preload/api/modules/github-api.ts b/apps/frontend/src/preload/api/modules/github-api.ts index d8304fd0..36f55841 100644 --- a/apps/frontend/src/preload/api/modules/github-api.ts +++ b/apps/frontend/src/preload/api/modules/github-api.ts @@ -233,6 +233,7 @@ export interface GitHubAPI { // Investigation operations (new system) startInvestigation: (projectId: string, issueNumber: number) => void; cancelInvestigation: (projectId: string, issueNumber: number) => void; + cancelAllInvestigations: (projectId: string) => void; createTaskFromInvestigation: (projectId: string, issueNumber: number) => Promise>; dismissIssue: (projectId: string, issueNumber: number, reason: InvestigationDismissReason) => Promise; postInvestigationToGitHub: (projectId: string, issueNumber: number) => Promise>; @@ -715,6 +716,9 @@ export const createGitHubAPI = (): GitHubAPI => ({ cancelInvestigation: (projectId: string, issueNumber: number): void => sendIpc(IPC_CHANNELS.GITHUB_INVESTIGATION_CANCEL, projectId, issueNumber), + cancelAllInvestigations: (projectId: string): void => + sendIpc(IPC_CHANNELS.GITHUB_INVESTIGATION_CANCEL_ALL, projectId), + createTaskFromInvestigation: (projectId: string, issueNumber: number): Promise> => invokeIpc(IPC_CHANNELS.GITHUB_INVESTIGATION_CREATE_TASK, projectId, issueNumber), diff --git a/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx b/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx index c6245716..6558250c 100644 --- a/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx +++ b/apps/frontend/src/renderer/components/github-issues/components/IssueListHeader.tsx @@ -1,5 +1,5 @@ import { useTranslation } from 'react-i18next'; -import { Github, RefreshCw, Search, Filter, Wand2, Loader2, Layers, EyeOff, Eye } from 'lucide-react'; +import { Github, RefreshCw, Search, Filter, Wand2, Loader2, Layers, EyeOff, Eye, XCircle } from 'lucide-react'; import { Badge } from '../../ui/badge'; import { Button } from '../../ui/button'; import { Input } from '../../ui/input'; @@ -85,6 +85,7 @@ export function IssueListHeader({ showDismissed, onToggleShowDismissed, activeInvestigationCount, + onCancelAllInvestigations, }: IssueListHeaderProps) { const { t } = useTranslation('common'); @@ -119,10 +120,23 @@ export function IssueListHeader({ {t('issues.openCount', { count: openIssuesCount })} {activeInvestigationCount != null && activeInvestigationCount > 0 && ( - - - {t('investigation.stateFilters.activeCount', { count: activeInvestigationCount, defaultValue: '{{count}} investigating' })} - + <> + + + {t('investigation.stateFilters.activeCount', { count: activeInvestigationCount, defaultValue: '{{count}} investigating' })} + + {onCancelAllInvestigations && ( + + )} + )} {/* Legacy triage mode toggle — kept for backwards compat */} {onToggleTriageMode && ( diff --git a/apps/frontend/src/renderer/stores/github/index.ts b/apps/frontend/src/renderer/stores/github/index.ts index 93590626..c065c7d9 100644 --- a/apps/frontend/src/renderer/stores/github/index.ts +++ b/apps/frontend/src/renderer/stores/github/index.ts @@ -37,6 +37,7 @@ export { cleanupInvestigationListeners, startIssueInvestigation, cancelIssueInvestigation, + cancelAllIssueInvestigations, investigateGitHubIssue, loadPersistedInvestigations, type IssueInvestigationState diff --git a/apps/frontend/src/shared/constants/ipc.ts b/apps/frontend/src/shared/constants/ipc.ts index 829750dc..51ef3711 100644 --- a/apps/frontend/src/shared/constants/ipc.ts +++ b/apps/frontend/src/shared/constants/ipc.ts @@ -269,6 +269,7 @@ export const IPC_CHANNELS = { // GitHub Investigation operations (renderer -> main) GITHUB_INVESTIGATION_START: 'github:investigation:start', GITHUB_INVESTIGATION_CANCEL: 'github:investigation:cancel', + GITHUB_INVESTIGATION_CANCEL_ALL: 'github:investigation:cancelAll', GITHUB_INVESTIGATION_CREATE_TASK: 'github:investigation:createTask', GITHUB_INVESTIGATION_DISMISS: 'github:investigation:dismiss', GITHUB_INVESTIGATION_POST_GITHUB: 'github:investigation:postGitHub', diff --git a/apps/frontend/src/shared/types/ipc.ts b/apps/frontend/src/shared/types/ipc.ts index 358cbf3d..e533e6b3 100644 --- a/apps/frontend/src/shared/types/ipc.ts +++ b/apps/frontend/src/shared/types/ipc.ts @@ -542,6 +542,7 @@ export interface ElectronAPI { // GitHub Investigation operations (new system) startInvestigation: (projectId: string, issueNumber: number) => void; cancelInvestigation: (projectId: string, issueNumber: number) => void; + cancelAllInvestigations: (projectId: string) => void; createTaskFromInvestigation: (projectId: string, issueNumber: number) => Promise>; dismissIssue: (projectId: string, issueNumber: number, reason: InvestigationDismissReason) => Promise; postInvestigationToGitHub: (projectId: string, issueNumber: number) => Promise>;