Files
Aperant/auto-claude-ui/src/preload/api/modules/github-api.ts
T
AndyMik90 4c1dd89840 feat: add GitHub issue comment selection and fix auto-start bug
## Features
- Add comment selection UI when creating tasks from GitHub issues
  - Fetch and display all comments with author, timestamp, and preview
  - Allow users to select/deselect individual comments via checkboxes
  - Include "Select All" / "Deselect All" toggle functionality
  - Show selected comment count (e.g., "3/5 comments selected")
  - Only selected comments are included in the task description

- Fix auto-start bug where GitHub issues were immediately executed
  - Tasks now stay in "backlog" status after creation
  - Users must manually start tasks from the Kanban board

## Implementation Details

### Backend
- Added `getIssueComments` IPC handler to fetch comments separately
- Modified `investigateGitHubIssue` to accept selectedCommentIds parameter
- Updated comment filtering logic in buildIssueContext
- Removed automatic startSpecCreation call to prevent auto-execution

### Frontend
- Enhanced InvestigationDialog with scrollable comment list UI
- Updated GitHubAPI interface with getIssueComments method
- Modified hooks and stores to pass selected comment IDs through the chain
- Added projectId prop to InvestigationDialog for comment fetching

### Files Changed
- Backend handlers: investigation-handlers.ts, issue-handlers.ts, types.ts
- API layer: github-api.ts
- UI components: InvestigationDialog.tsx, GitHubIssues.tsx
- State management: github-store.ts, useGitHubInvestigation.ts
- Type definitions: types/index.ts, ipc.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-18 18:27:01 +01:00

128 lines
5.6 KiB
TypeScript

import { IPC_CHANNELS } from '../../../shared/constants';
import type {
GitHubRepository,
GitHubIssue,
GitHubSyncStatus,
GitHubImportResult,
GitHubInvestigationStatus,
GitHubInvestigationResult,
IPCResult,
VersionSuggestion
} from '../../../shared/types';
import { createIpcListener, invokeIpc, sendIpc, IpcListenerCleanup } from './ipc-utils';
/**
* GitHub Integration API operations
*/
export interface GitHubAPI {
// Operations
getGitHubRepositories: (projectId: string) => Promise<IPCResult<GitHubRepository[]>>;
getGitHubIssues: (projectId: string, state?: 'open' | 'closed' | 'all') => Promise<IPCResult<GitHubIssue[]>>;
getGitHubIssue: (projectId: string, issueNumber: number) => Promise<IPCResult<GitHubIssue>>;
getIssueComments: (projectId: string, issueNumber: number) => Promise<IPCResult<any[]>>;
checkGitHubConnection: (projectId: string) => Promise<IPCResult<GitHubSyncStatus>>;
investigateGitHubIssue: (projectId: string, issueNumber: number, selectedCommentIds?: number[]) => void;
importGitHubIssues: (projectId: string, issueNumbers: number[]) => Promise<IPCResult<GitHubImportResult>>;
createGitHubRelease: (
projectId: string,
version: string,
releaseNotes: string,
options?: { draft?: boolean; prerelease?: boolean }
) => Promise<IPCResult<{ url: string }>>;
/** AI-powered version suggestion based on commits since last release */
suggestReleaseVersion: (projectId: string) => Promise<IPCResult<VersionSuggestion>>;
// OAuth operations (gh CLI)
checkGitHubCli: () => Promise<IPCResult<{ installed: boolean; version?: string }>>;
checkGitHubAuth: () => Promise<IPCResult<{ authenticated: boolean; username?: string }>>;
startGitHubAuth: () => Promise<IPCResult<{ success: boolean; message?: string }>>;
getGitHubToken: () => Promise<IPCResult<{ token: string }>>;
getGitHubUser: () => Promise<IPCResult<{ username: string; name?: string }>>;
listGitHubUserRepos: () => Promise<IPCResult<{ repos: Array<{ fullName: string; description: string | null; isPrivate: boolean }> }>>;
// Event Listeners
onGitHubInvestigationProgress: (
callback: (projectId: string, status: GitHubInvestigationStatus) => void
) => IpcListenerCleanup;
onGitHubInvestigationComplete: (
callback: (projectId: string, result: GitHubInvestigationResult) => void
) => IpcListenerCleanup;
onGitHubInvestigationError: (
callback: (projectId: string, error: string) => void
) => IpcListenerCleanup;
}
/**
* Creates the GitHub Integration API implementation
*/
export const createGitHubAPI = (): GitHubAPI => ({
// Operations
getGitHubRepositories: (projectId: string): Promise<IPCResult<GitHubRepository[]>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_REPOSITORIES, projectId),
getGitHubIssues: (projectId: string, state?: 'open' | 'closed' | 'all'): Promise<IPCResult<GitHubIssue[]>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_ISSUES, projectId, state),
getGitHubIssue: (projectId: string, issueNumber: number): Promise<IPCResult<GitHubIssue>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_ISSUE, projectId, issueNumber),
getIssueComments: (projectId: string, issueNumber: number): Promise<IPCResult<any[]>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_ISSUE_COMMENTS, projectId, issueNumber),
checkGitHubConnection: (projectId: string): Promise<IPCResult<GitHubSyncStatus>> =>
invokeIpc(IPC_CHANNELS.GITHUB_CHECK_CONNECTION, projectId),
investigateGitHubIssue: (projectId: string, issueNumber: number, selectedCommentIds?: number[]): void =>
sendIpc(IPC_CHANNELS.GITHUB_INVESTIGATE_ISSUE, projectId, issueNumber, selectedCommentIds),
importGitHubIssues: (projectId: string, issueNumbers: number[]): Promise<IPCResult<GitHubImportResult>> =>
invokeIpc(IPC_CHANNELS.GITHUB_IMPORT_ISSUES, projectId, issueNumbers),
createGitHubRelease: (
projectId: string,
version: string,
releaseNotes: string,
options?: { draft?: boolean; prerelease?: boolean }
): Promise<IPCResult<{ url: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_CREATE_RELEASE, projectId, version, releaseNotes, options),
suggestReleaseVersion: (projectId: string): Promise<IPCResult<VersionSuggestion>> =>
invokeIpc(IPC_CHANNELS.RELEASE_SUGGEST_VERSION, projectId),
// OAuth operations (gh CLI)
checkGitHubCli: (): Promise<IPCResult<{ installed: boolean; version?: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_CHECK_CLI),
checkGitHubAuth: (): Promise<IPCResult<{ authenticated: boolean; username?: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_CHECK_AUTH),
startGitHubAuth: (): Promise<IPCResult<{ success: boolean; message?: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_START_AUTH),
getGitHubToken: (): Promise<IPCResult<{ token: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_TOKEN),
getGitHubUser: (): Promise<IPCResult<{ username: string; name?: string }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_GET_USER),
listGitHubUserRepos: (): Promise<IPCResult<{ repos: Array<{ fullName: string; description: string | null; isPrivate: boolean }> }>> =>
invokeIpc(IPC_CHANNELS.GITHUB_LIST_USER_REPOS),
// Event Listeners
onGitHubInvestigationProgress: (
callback: (projectId: string, status: GitHubInvestigationStatus) => void
): IpcListenerCleanup =>
createIpcListener(IPC_CHANNELS.GITHUB_INVESTIGATION_PROGRESS, callback),
onGitHubInvestigationComplete: (
callback: (projectId: string, result: GitHubInvestigationResult) => void
): IpcListenerCleanup =>
createIpcListener(IPC_CHANNELS.GITHUB_INVESTIGATION_COMPLETE, callback),
onGitHubInvestigationError: (
callback: (projectId: string, error: string) => void
): IpcListenerCleanup =>
createIpcListener(IPC_CHANNELS.GITHUB_INVESTIGATION_ERROR, callback)
});