feat: Implement GitHub OAuth (#72)
* implement GitHub OAuth * fmt and clippy * add secrets for GitHub App in workflow * fix env vars * use device flow for login instead of callback for better security, add email and username to posthog analytics * cleanup * add user details to sentry context * fixes after rebase * feedback fixes * do not allow to press esc to hide github popup * use oauth app to get user token with full repo access * use PAT token as a backup for creating PRs * update github signin box text * update sign in box styling * fmt --------- Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
This commit is contained in:
259
shared/types.ts
259
shared/types.ts
@@ -4,35 +4,89 @@
|
||||
|
||||
export type ApiResponse<T> = { success: boolean, data: T | null, message: string | null, };
|
||||
|
||||
export type Config = { theme: ThemeMode, executor: ExecutorConfig, disclaimer_acknowledged: boolean, onboarding_acknowledged: boolean, sound_alerts: boolean, sound_file: SoundFile, push_notifications: boolean, editor: EditorConfig, github: GitHubConfig, analytics_enabled: boolean | null, };
|
||||
export type Config = {
|
||||
theme: ThemeMode,
|
||||
executor: ExecutorConfig,
|
||||
disclaimer_acknowledged: boolean,
|
||||
onboarding_acknowledged: boolean,
|
||||
sound_alerts: boolean,
|
||||
sound_file: SoundFile,
|
||||
push_notifications: boolean,
|
||||
editor: EditorConfig,
|
||||
github: GitHubConfig,
|
||||
analytics_enabled: boolean | null,
|
||||
};
|
||||
|
||||
export type ThemeMode = "light" | "dark" | "system" | "purple" | "green" | "blue" | "orange" | "red";
|
||||
|
||||
export type EditorConfig = { editor_type: EditorType, custom_command: string | null, };
|
||||
|
||||
export type GitHubConfig = { token: string | null, default_pr_base: string | null, };
|
||||
export type GitHubConfig = {
|
||||
token?: string | null,
|
||||
default_pr_base: string | null,
|
||||
username?: string | null,
|
||||
primary_email?: string | null,
|
||||
pat?: string | null
|
||||
};
|
||||
|
||||
export type EditorType = "vscode" | "cursor" | "windsurf" | "intellij" | "zed" | "custom";
|
||||
|
||||
export type EditorConstants = { editor_types: Array<EditorType>, editor_labels: Array<string>, };
|
||||
|
||||
export type SoundFile = "abstract-sound1" | "abstract-sound2" | "abstract-sound3" | "abstract-sound4" | "cow-mooing" | "phone-vibration" | "rooster";
|
||||
export type SoundFile =
|
||||
"abstract-sound1"
|
||||
| "abstract-sound2"
|
||||
| "abstract-sound3"
|
||||
| "abstract-sound4"
|
||||
| "cow-mooing"
|
||||
| "phone-vibration"
|
||||
| "rooster";
|
||||
|
||||
export type SoundConstants = { sound_files: Array<SoundFile>, sound_labels: Array<string>, };
|
||||
|
||||
export type ConfigConstants = { editor: EditorConstants, sound: SoundConstants, };
|
||||
|
||||
export type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" } | { "type": "gemini" } | { "type": "opencode" };
|
||||
export type ExecutorConfig = { "type": "echo" } | { "type": "claude" } | { "type": "amp" } | { "type": "gemini" } | {
|
||||
"type": "opencode"
|
||||
};
|
||||
|
||||
export type ExecutorConstants = { executor_types: Array<ExecutorConfig>, executor_labels: Array<string>, };
|
||||
|
||||
export type CreateProject = { name: string, git_repo_path: string, use_existing_repo: boolean, setup_script: string | null, dev_script: string | null, };
|
||||
export type CreateProject = {
|
||||
name: string,
|
||||
git_repo_path: string,
|
||||
use_existing_repo: boolean,
|
||||
setup_script: string | null,
|
||||
dev_script: string | null,
|
||||
};
|
||||
|
||||
export type Project = { id: string, name: string, git_repo_path: string, setup_script: string | null, dev_script: string | null, created_at: Date, updated_at: Date, };
|
||||
export type Project = {
|
||||
id: string,
|
||||
name: string,
|
||||
git_repo_path: string,
|
||||
setup_script: string | null,
|
||||
dev_script: string | null,
|
||||
created_at: Date,
|
||||
updated_at: Date,
|
||||
};
|
||||
|
||||
export type ProjectWithBranch = { id: string, name: string, git_repo_path: string, setup_script: string | null, dev_script: string | null, current_branch: string | null, created_at: Date, updated_at: Date, };
|
||||
export type ProjectWithBranch = {
|
||||
id: string,
|
||||
name: string,
|
||||
git_repo_path: string,
|
||||
setup_script: string | null,
|
||||
dev_script: string | null,
|
||||
current_branch: string | null,
|
||||
created_at: Date,
|
||||
updated_at: Date,
|
||||
};
|
||||
|
||||
export type UpdateProject = { name: string | null, git_repo_path: string | null, setup_script: string | null, dev_script: string | null, };
|
||||
export type UpdateProject = {
|
||||
name: string | null,
|
||||
git_repo_path: string | null,
|
||||
setup_script: string | null,
|
||||
dev_script: string | null,
|
||||
};
|
||||
|
||||
export type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType, };
|
||||
|
||||
@@ -44,19 +98,63 @@ export type CreateBranch = { name: string, base_branch: string | null, };
|
||||
|
||||
export type CreateTask = { project_id: string, title: string, description: string | null, };
|
||||
|
||||
export type CreateTaskAndStart = { project_id: string, title: string, description: string | null, executor: ExecutorConfig | null, };
|
||||
export type CreateTaskAndStart = {
|
||||
project_id: string,
|
||||
title: string,
|
||||
description: string | null,
|
||||
executor: ExecutorConfig | null,
|
||||
};
|
||||
|
||||
export type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
|
||||
|
||||
export type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, };
|
||||
export type Task = {
|
||||
id: string,
|
||||
project_id: string,
|
||||
title: string,
|
||||
description: string | null,
|
||||
status: TaskStatus,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
};
|
||||
|
||||
export type TaskWithAttemptStatus = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, created_at: string, updated_at: string, has_in_progress_attempt: boolean, has_merged_attempt: boolean, has_failed_attempt: boolean, };
|
||||
export type TaskWithAttemptStatus = {
|
||||
id: string,
|
||||
project_id: string,
|
||||
title: string,
|
||||
description: string | null,
|
||||
status: TaskStatus,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
has_in_progress_attempt: boolean,
|
||||
has_merged_attempt: boolean,
|
||||
has_failed_attempt: boolean,
|
||||
};
|
||||
|
||||
export type UpdateTask = { title: string | null, description: string | null, status: TaskStatus | null, };
|
||||
|
||||
export type TaskAttemptStatus = "setuprunning" | "setupcomplete" | "setupfailed" | "executorrunning" | "executorcomplete" | "executorfailed";
|
||||
export type TaskAttemptStatus =
|
||||
"setuprunning"
|
||||
| "setupcomplete"
|
||||
| "setupfailed"
|
||||
| "executorrunning"
|
||||
| "executorcomplete"
|
||||
| "executorfailed";
|
||||
|
||||
export type TaskAttempt = { id: string, task_id: string, worktree_path: string, branch: string, base_branch: string, merge_commit: string | null, executor: string | null, pr_url: string | null, pr_number: bigint | null, pr_status: string | null, pr_merged_at: string | null, created_at: string, updated_at: string, };
|
||||
export type TaskAttempt = {
|
||||
id: string,
|
||||
task_id: string,
|
||||
worktree_path: string,
|
||||
branch: string,
|
||||
base_branch: string,
|
||||
merge_commit: string | null,
|
||||
executor: string | null,
|
||||
pr_url: string | null,
|
||||
pr_number: bigint | null,
|
||||
pr_status: string | null,
|
||||
pr_merged_at: string | null,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
};
|
||||
|
||||
export type CreateTaskAttempt = { executor: string | null, base_branch: string | null, };
|
||||
|
||||
@@ -64,11 +162,28 @@ export type UpdateTaskAttempt = Record<string, never>;
|
||||
|
||||
export type CreateFollowUpAttempt = { prompt: string, };
|
||||
|
||||
export type TaskAttemptActivity = { id: string, execution_process_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, };
|
||||
export type TaskAttemptActivity = {
|
||||
id: string,
|
||||
execution_process_id: string,
|
||||
status: TaskAttemptStatus,
|
||||
note: string | null,
|
||||
created_at: string,
|
||||
};
|
||||
|
||||
export type TaskAttemptActivityWithPrompt = { id: string, execution_process_id: string, status: TaskAttemptStatus, note: string | null, created_at: string, prompt: string | null, };
|
||||
export type TaskAttemptActivityWithPrompt = {
|
||||
id: string,
|
||||
execution_process_id: string,
|
||||
status: TaskAttemptStatus,
|
||||
note: string | null,
|
||||
created_at: string,
|
||||
prompt: string | null,
|
||||
};
|
||||
|
||||
export type CreateTaskAttemptActivity = { execution_process_id: string, status: TaskAttemptStatus | null, note: string | null, };
|
||||
export type CreateTaskAttemptActivity = {
|
||||
execution_process_id: string,
|
||||
status: TaskAttemptStatus | null,
|
||||
note: string | null,
|
||||
};
|
||||
|
||||
export type DirectoryEntry = { name: string, path: string, is_directory: boolean, is_git_repo: boolean, };
|
||||
|
||||
@@ -80,37 +195,125 @@ export type FileDiff = { path: string, chunks: Array<DiffChunk>, };
|
||||
|
||||
export type WorktreeDiff = { files: Array<FileDiff>, };
|
||||
|
||||
export type BranchStatus = { is_behind: boolean, commits_behind: number, commits_ahead: number, up_to_date: boolean, merged: boolean, has_uncommitted_changes: boolean, base_branch_name: string, };
|
||||
export type BranchStatus = {
|
||||
is_behind: boolean,
|
||||
commits_behind: number,
|
||||
commits_ahead: number,
|
||||
up_to_date: boolean,
|
||||
merged: boolean,
|
||||
has_uncommitted_changes: boolean,
|
||||
base_branch_name: string,
|
||||
};
|
||||
|
||||
export type ExecutionState = "NotStarted" | "SetupRunning" | "SetupComplete" | "SetupFailed" | "CodingAgentRunning" | "CodingAgentComplete" | "CodingAgentFailed" | "Complete";
|
||||
export type ExecutionState =
|
||||
"NotStarted"
|
||||
| "SetupRunning"
|
||||
| "SetupComplete"
|
||||
| "SetupFailed"
|
||||
| "CodingAgentRunning"
|
||||
| "CodingAgentComplete"
|
||||
| "CodingAgentFailed"
|
||||
| "Complete";
|
||||
|
||||
export type TaskAttemptState = { execution_state: ExecutionState, has_changes: boolean, has_setup_script: boolean, setup_process_id: string | null, coding_agent_process_id: string | null, };
|
||||
export type TaskAttemptState = {
|
||||
execution_state: ExecutionState,
|
||||
has_changes: boolean,
|
||||
has_setup_script: boolean,
|
||||
setup_process_id: string | null,
|
||||
coding_agent_process_id: string | null,
|
||||
};
|
||||
|
||||
export type ExecutionProcess = { id: string, task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, status: ExecutionProcessStatus, command: string, args: string | null, working_directory: string, stdout: string | null, stderr: string | null, exit_code: bigint | null, started_at: string, completed_at: string | null, created_at: string, updated_at: string, };
|
||||
export type ExecutionProcess = {
|
||||
id: string,
|
||||
task_attempt_id: string,
|
||||
process_type: ExecutionProcessType,
|
||||
executor_type: string | null,
|
||||
status: ExecutionProcessStatus,
|
||||
command: string,
|
||||
args: string | null,
|
||||
working_directory: string,
|
||||
stdout: string | null,
|
||||
stderr: string | null,
|
||||
exit_code: bigint | null,
|
||||
started_at: string,
|
||||
completed_at: string | null,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
};
|
||||
|
||||
export type ExecutionProcessSummary = { id: string, task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, status: ExecutionProcessStatus, command: string, args: string | null, working_directory: string, exit_code: bigint | null, started_at: string, completed_at: string | null, created_at: string, updated_at: string, };
|
||||
export type ExecutionProcessSummary = {
|
||||
id: string,
|
||||
task_attempt_id: string,
|
||||
process_type: ExecutionProcessType,
|
||||
executor_type: string | null,
|
||||
status: ExecutionProcessStatus,
|
||||
command: string,
|
||||
args: string | null,
|
||||
working_directory: string,
|
||||
exit_code: bigint | null,
|
||||
started_at: string,
|
||||
completed_at: string | null,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
};
|
||||
|
||||
export type ExecutionProcessStatus = "running" | "completed" | "failed" | "killed";
|
||||
|
||||
export type ExecutionProcessType = "setupscript" | "codingagent" | "devserver";
|
||||
|
||||
export type CreateExecutionProcess = { task_attempt_id: string, process_type: ExecutionProcessType, executor_type: string | null, command: string, args: string | null, working_directory: string, };
|
||||
export type CreateExecutionProcess = {
|
||||
task_attempt_id: string,
|
||||
process_type: ExecutionProcessType,
|
||||
executor_type: string | null,
|
||||
command: string,
|
||||
args: string | null,
|
||||
working_directory: string,
|
||||
};
|
||||
|
||||
export type UpdateExecutionProcess = { status: ExecutionProcessStatus | null, exit_code: bigint | null, completed_at: string | null, };
|
||||
export type UpdateExecutionProcess = {
|
||||
status: ExecutionProcessStatus | null,
|
||||
exit_code: bigint | null,
|
||||
completed_at: string | null,
|
||||
};
|
||||
|
||||
export type ExecutorSession = { id: string, task_attempt_id: string, execution_process_id: string, session_id: string | null, prompt: string | null, summary: string | null, created_at: string, updated_at: string, };
|
||||
export type ExecutorSession = {
|
||||
id: string,
|
||||
task_attempt_id: string,
|
||||
execution_process_id: string,
|
||||
session_id: string | null,
|
||||
prompt: string | null,
|
||||
summary: string | null,
|
||||
created_at: string,
|
||||
updated_at: string,
|
||||
};
|
||||
|
||||
export type CreateExecutorSession = { task_attempt_id: string, execution_process_id: string, prompt: string | null, };
|
||||
|
||||
export type UpdateExecutorSession = { session_id: string | null, prompt: string | null, summary: string | null, };
|
||||
|
||||
export type NormalizedConversation = { entries: Array<NormalizedEntry>, session_id: string | null, executor_type: string, prompt: string | null, summary: string | null, };
|
||||
export type NormalizedConversation = {
|
||||
entries: Array<NormalizedEntry>,
|
||||
session_id: string | null,
|
||||
executor_type: string,
|
||||
prompt: string | null,
|
||||
summary: string | null,
|
||||
};
|
||||
|
||||
export type NormalizedEntry = { timestamp: string | null, entry_type: NormalizedEntryType, content: string, };
|
||||
|
||||
export type NormalizedEntryType = { "type": "user_message" } | { "type": "assistant_message" } | { "type": "tool_use", tool_name: string, action_type: ActionType, } | { "type": "system_message" } | { "type": "error_message" } | { "type": "thinking" };
|
||||
export type NormalizedEntryType = { "type": "user_message" } | { "type": "assistant_message" } | {
|
||||
"type": "tool_use",
|
||||
tool_name: string,
|
||||
action_type: ActionType,
|
||||
} | { "type": "system_message" } | { "type": "error_message" } | { "type": "thinking" };
|
||||
|
||||
export type ActionType = { "action": "file_read", path: string, } | { "action": "file_write", path: string, } | { "action": "command_run", command: string, } | { "action": "search", query: string, } | { "action": "web_fetch", url: string, } | { "action": "task_create", description: string, } | { "action": "other", description: string, };
|
||||
export type ActionType = { "action": "file_read", path: string, } | { "action": "file_write", path: string, } | {
|
||||
"action": "command_run",
|
||||
command: string,
|
||||
} | { "action": "search", query: string, } | { "action": "web_fetch", url: string, } | {
|
||||
"action": "task_create",
|
||||
description: string,
|
||||
} | { "action": "other", description: string, };
|
||||
|
||||
// Generated constants
|
||||
export const EXECUTOR_TYPES: string[] = [
|
||||
@@ -123,7 +326,7 @@ export const EXECUTOR_TYPES: string[] = [
|
||||
|
||||
export const EDITOR_TYPES: EditorType[] = [
|
||||
"vscode",
|
||||
"cursor",
|
||||
"cursor",
|
||||
"windsurf",
|
||||
"intellij",
|
||||
"zed",
|
||||
|
||||
Reference in New Issue
Block a user