Files
vibe-kanban/shared/types.ts
Louis Knight-Webb 947cb53f44 Edit branch name (vibe-kanban) (#1182)
* ##  Implementation Complete!

I've successfully implemented the branch name editing feature. Here's what was added:

### **Backend Changes**

1. **Database Model** ([task_attempt.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/db/src/models/task_attempt.rs#L407-L421))
   - Added `update_branch_name()` method to update the branch field

2. **Git Service** ([git.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/services/src/services/git.rs#L1508-L1526))
   - Added `rename_local_branch()` to handle actual Git branch renaming using libgit2

3. **API Endpoint** ([task_attempts.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/server/src/routes/task_attempts.rs#L1111-L1196))
   - Added `POST /task-attempts/{id}/rename-branch` endpoint
   - **Validation:** empty names, Git name validity, duplicates, active rebase, open PRs
   - **Flow:** validate → ensure worktree → rename in git → update DB → track analytics

### **Frontend Changes**

4. **API Client** ([api.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/lib/api.ts#L533-L546))
   - Added `renameBranch()` method

5. **Actions Menu** ([ActionsDropdown.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/components/ui/ActionsDropdown.tsx#L93-L102))
   - Added "Edit Branch Name" menu item

6. **Dialog Component** ([EditBranchNameDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/components/dialogs/tasks/EditBranchNameDialog.tsx))
   - Text input with validation
   - Shows backend errors
   - Auto-refreshes data on success

### **Key Features**
 Renames actual Git branch (not just DB)
 Blocks when open PR exists
 Blocks during active rebase
 Validates branch name format
 Prevents duplicate branch names
 Analytics tracking
 All checks pass

The feature is now ready to use from the task attempt dropdown menu!

* Cleanup script changes for task attempt 98509988-cc54-4336-a94a-fb43c16a8235

* ##  Cache Invalidation Fix Complete!

I've updated [EditBranchNameDialog.tsx](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/components/dialogs/tasks/EditBranchNameDialog.tsx#L59-L71) to invalidate all relevant query keys after renaming a branch.

### What Changed
The dialog now invalidates **5 query keys** instead of just 2:

1.  `['taskAttempt', attemptId]` - **Main fix** for DiffsPanel
2.  `['attempt', attemptId]` - Legacy compatibility
3.  `['attemptBranch', attemptId]` - Branch-specific data
4.  `['branchStatus', attemptId]` - Git operations panel
5.  `['taskAttempts']` - Attempts list in TaskPanel

### Result
Now when you rename a branch, **all components immediately show the new name**:
-  DiffsPanel (branch name in Git operations toolbar)
-  TaskPanel (attempts list)
-  GitOperations component
-  Any other component displaying the attempt data

**No page reload needed!** All checks pass.

* Cleanup script changes for task attempt 98509988-cc54-4336-a94a-fb43c16a8235

* ##  Refactored to Use Hook Pattern!

I've successfully extracted the mutation logic into a proper `useRenameBranch` hook following the codebase's established patterns.

### Changes Made

**1. Created new hook:** [useRenameBranch.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/hooks/useRenameBranch.ts)
- Uses `useMutation` from TanStack Query
- Handles cache invalidation internally
- Provides callbacks for success/error handling
- Follows the same pattern as `useChangeTargetBranch`, `useMerge`, `usePush`

**2. Simplified EditBranchNameDialog:**
- Removed manual API call and cache invalidation
- Removed local `isLoading` state (uses `mutation.isPending` instead)
- Removed `queryClient` import
- Much cleaner and more focused on UI

**3. Updated hooks exports:** [index.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/hooks/index.ts#L7)

### Before vs After

**Before (inline mutation):**
- 40+ lines of try/catch, API calls, and invalidation logic
- Manual loading state management
- Hard to test, hard to reuse

**After (hook-based):**
- ~10 lines in dialog
- Hook encapsulates all mutation logic
- Reusable, testable, consistent with codebase

### Benefits
 **Consistency** - Matches existing patterns (useChangeTargetBranch, useMerge, etc.)
 **Reusability** - Can be used anywhere branch renaming is needed
 **Testability** - Hook can be unit tested separately
 **Maintainability** - Single source of truth for invalidation logic
 **Cleaner Dialog** - Dialog focuses purely on UI concerns

All checks pass!

* Cleanup script changes for task attempt 98509988-cc54-4336-a94a-fb43c16a8235

* ##  i18n Check Complete!

All internationalization issues have been resolved:

### Fixed Issues

**1. Missing translation keys** - Added to all locales (en, es, ja, ko):
- `actionsMenu.editBranchName`

**2. Hardcoded strings in EditBranchNameDialog** - Now using translation keys:
- Dialog title → `t('editBranchName.dialog.title')`
- Dialog description → `t('editBranchName.dialog.description')`
- Branch name label → `t('editBranchName.dialog.branchNameLabel')`
- Placeholder text → `t('editBranchName.dialog.placeholder')`
- "Renaming..." → `t('editBranchName.dialog.renaming')`
- "Rename Branch" → `t('editBranchName.dialog.action')`

### Translations Added

**English:** "Edit branch name"
**Spanish (es):** "Editar nombre de rama"
**Japanese (ja):** "ブランチ名を編集"
**Korean (ko):** "브랜치 이름 편집"

### Results
 **No new literal strings introduced**
 **No duplicate keys found**
 **Translation keys consistent across all locales**
 **All type checks pass**

The feature is now fully internationalized and ready for users in all supported languages!

* Cleanup script changes for task attempt 98509988-cc54-4336-a94a-fb43c16a8235

* ##  Child Task Updates Complete!

I've successfully implemented the fix to update child task attempts when renaming a branch.

### What Was Added

**1. Database Helper** ([task_attempt.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/db/src/models/task_attempt.rs#L422-L445))
- Added `update_target_branch_for_children_of_attempt()` method
- Uses single scoped SQL UPDATE with subquery
- Only affects attempts for direct child tasks
- Returns count of updated attempts

**2. Rename Branch Endpoint** ([task_attempts.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/server/src/routes/task_attempts.rs#L1219-L1239))
- Stores old branch name before update
- After renaming, updates all child task attempts
- Logs count of updated children
- Tracks updated count in analytics

### How It Works

**Scenario:**
1. Parent attempt has branch `feature/old`
2. User creates 2 subtasks from parent attempt
3. Subtask attempts inherit `target_branch = "feature/old"`
4. Parent branch renamed to `feature/new`
5.  Both subtask attempts automatically get `target_branch = "feature/new"`

**SQL Query:**
```sql
UPDATE task_attempts
SET target_branch = 'feature/new'
WHERE target_branch = 'feature/old'
  AND task_id IN (
    SELECT id FROM tasks
    WHERE parent_task_attempt = parent_attempt_id
  )
```

### What's Updated
 `target_branch` for all attempts of direct child tasks
 Only when it matches the old branch name
 Scoped by parent-child relationship (via `parent_task_attempt` FK)

### What's NOT Updated
 Unrelated attempts that happen to use same branch name
 Child attempts' own `branch` field (they have their own branches)
 GitHub PR bases (would need GitHub API call)

### Result
 Child task attempts continue to work correctly after parent branch rename
 Efficient single-query update
 Safe scoping prevents unintended changes
 All checks pass

* Cleanup script changes for task attempt 98509988-cc54-4336-a94a-fb43c16a8235

* ##  Analytics & Types Fixed!

### Changes Made

**1. Analytics Anonymity** ([task_attempts.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/server/src/routes/task_attempts.rs#L1240-L1248))
- Removed `old_branch` and `new_branch` from analytics event
- Now only tracks: `attempt_id` and `updated_children` (anonymous)

**2. Type Export** ([generate_types.rs](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/crates/server/src/bin/generate_types.rs#L51-L52))
- Added `RenameBranchRequest::decl()` and `RenameBranchResponse::decl()`
- Types now exported to [shared/types.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/shared/types.ts)

**3. Frontend Type Usage** ([api.ts](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/9850-edit-branch-name/frontend/src/lib/api.ts#L49-L50))
- Imported `RenameBranchRequest` and `RenameBranchResponse` from shared types
- Changed signature from `Promise<{ branch: string }>` to `Promise<RenameBranchResponse>`
- Uses properly typed request payload

### Results
 **Anonymous analytics** - No branch names (PII) sent
 **Type-safe** - Frontend/backend use same shared types
 **Consistent** - Matches pattern of other API methods
 **All checks pass** - TypeScript, Rust, and i18n

* ##  Analytics Now Fully Anonymous!

Removed `attempt_id` from the analytics event. Now the event only tracks:
```json
{
  "updated_children": 0
}
```

Fully anonymous - no IDs, no branch names, no PII. Just aggregate counts for usage metrics.

All checks pass!
2025-11-06 12:52:09 +00:00

339 lines
19 KiB
TypeScript

// This file was generated by `crates/core/src/bin/generate_types.rs`.
// Do not edit this file manually.
// If you are an AI, and you absolutely have to edit this file, please confirm with the user first.
export type DirectoryEntry = { name: string, path: string, is_directory: boolean, is_git_repo: boolean, last_modified: bigint | null, };
export type DirectoryListResponse = { entries: Array<DirectoryEntry>, current_path: string, };
export type Project = { id: string, name: string, git_repo_path: string, setup_script: string | null, dev_script: string | null, cleanup_script: string | null, copy_files: string | null, created_at: Date, updated_at: Date, };
export type CreateProject = { name: string, git_repo_path: string, use_existing_repo: boolean, setup_script: string | null, dev_script: string | null, cleanup_script: string | null, copy_files: string | null, };
export type UpdateProject = { name: string | null, git_repo_path: string | null, setup_script: string | null, dev_script: string | null, cleanup_script: string | null, copy_files: string | null, };
export type SearchResult = { path: string, is_file: boolean, match_type: SearchMatchType, };
export type SearchMatchType = "FileName" | "DirectoryName" | "FullPath";
export type ExecutorAction = { typ: ExecutorActionType, next_action: ExecutorAction | null, };
export type McpConfig = { servers: { [key in string]?: JsonValue }, servers_path: Array<string>, template: JsonValue, preconfigured: JsonValue, is_toml_config: boolean, };
export type ExecutorActionType = { "type": "CodingAgentInitialRequest" } & CodingAgentInitialRequest | { "type": "CodingAgentFollowUpRequest" } & CodingAgentFollowUpRequest | { "type": "ScriptRequest" } & ScriptRequest;
export type ScriptContext = "SetupScript" | "CleanupScript" | "DevServer";
export type ScriptRequest = { script: string, language: ScriptRequestLanguage, context: ScriptContext, };
export type ScriptRequestLanguage = "Bash";
export enum BaseCodingAgent { CLAUDE_CODE = "CLAUDE_CODE", AMP = "AMP", GEMINI = "GEMINI", CODEX = "CODEX", OPENCODE = "OPENCODE", CURSOR_AGENT = "CURSOR_AGENT", QWEN_CODE = "QWEN_CODE", COPILOT = "COPILOT" }
export type CodingAgent = { "CLAUDE_CODE": ClaudeCode } | { "AMP": Amp } | { "GEMINI": Gemini } | { "CODEX": Codex } | { "OPENCODE": Opencode } | { "CURSOR_AGENT": CursorAgent } | { "QWEN_CODE": QwenCode } | { "COPILOT": Copilot };
export type Tag = { id: string, tag_name: string, content: string, created_at: string, updated_at: string, };
export type CreateTag = { tag_name: string, content: string, };
export type UpdateTag = { tag_name: string | null, content: string | null, };
export type TagSearchParams = { search: string | null, };
export type TaskStatus = "todo" | "inprogress" | "inreview" | "done" | "cancelled";
export type Task = { id: string, project_id: string, title: string, description: string | null, status: TaskStatus, parent_task_attempt: string | null, created_at: string, updated_at: string, };
export type TaskWithAttemptStatus = { has_in_progress_attempt: boolean, has_merged_attempt: boolean, last_attempt_failed: boolean, executor: string, id: string, project_id: string, title: string, description: string | null, status: TaskStatus, parent_task_attempt: string | null, created_at: string, updated_at: string, };
export type TaskRelationships = { parent_task: Task | null, current_attempt: TaskAttempt, children: Array<Task>, };
export type CreateTask = { project_id: string, title: string, description: string | null, parent_task_attempt: string | null, image_ids: Array<string> | null, };
export type UpdateTask = { title: string | null, description: string | null, status: TaskStatus | null, parent_task_attempt: string | null, image_ids: Array<string> | null, };
export type Image = { id: string, file_path: string, original_name: string, mime_type: string | null, size_bytes: bigint, hash: string, created_at: string, updated_at: string, };
export type CreateImage = { file_path: string, original_name: string, mime_type: string | null, size_bytes: bigint, hash: string, };
export type ApiResponse<T, E = T> = { success: boolean, data: T | null, error_data: E | null, message: string | null, };
export type UserSystemInfo = { config: Config, analytics_user_id: string, environment: Environment,
/**
* Capabilities supported per executor (e.g., { "CLAUDE_CODE": ["SESSION_FORK"] })
*/
capabilities: { [key in string]?: Array<BaseAgentCapability> }, executors: { [key in BaseCodingAgent]?: ExecutorConfig }, };
export type Environment = { os_type: string, os_version: string, os_architecture: string, bitness: string, };
export type McpServerQuery = { executor: BaseCodingAgent, };
export type UpdateMcpServersBody = { servers: { [key in string]?: JsonValue }, };
export type GetMcpServerResponse = { mcp_config: McpConfig, config_path: string, };
export type CreateFollowUpAttempt = { prompt: string, variant: string | null, image_ids: Array<string> | null, retry_process_id: string | null, force_when_dirty: boolean | null, perform_git_reset: boolean | null, };
export type DraftResponse = { task_attempt_id: string, draft_type: DraftType, retry_process_id: string | null, prompt: string, queued: boolean, variant: string | null, image_ids: Array<string> | null, version: bigint, };
export type UpdateFollowUpDraftRequest = { prompt: string | null, variant: string | null | null, image_ids: Array<string> | null, version: bigint | null, };
export type UpdateRetryFollowUpDraftRequest = { retry_process_id: string, prompt: string | null, variant: string | null | null, image_ids: Array<string> | null, version: bigint | null, };
export type ChangeTargetBranchRequest = { new_target_branch: string, };
export type ChangeTargetBranchResponse = { new_target_branch: string, status: [number, number], };
export type RenameBranchRequest = { new_branch_name: string, };
export type RenameBranchResponse = { branch: string, };
export type CreateAndStartTaskRequest = { task: CreateTask, executor_profile_id: ExecutorProfileId, base_branch: string, };
export type CreateGitHubPrRequest = { title: string, body: string | null, target_branch: string | null, };
export type ImageResponse = { id: string, file_path: string, original_name: string, mime_type: string | null, size_bytes: bigint, hash: string, created_at: string, updated_at: string, };
export enum GitHubServiceError { TOKEN_INVALID = "TOKEN_INVALID", INSUFFICIENT_PERMISSIONS = "INSUFFICIENT_PERMISSIONS", REPO_NOT_FOUND_OR_NO_ACCESS = "REPO_NOT_FOUND_OR_NO_ACCESS" }
export type Config = { config_version: string, theme: ThemeMode, executor_profile: ExecutorProfileId, disclaimer_acknowledged: boolean, onboarding_acknowledged: boolean, github_login_acknowledged: boolean, telemetry_acknowledged: boolean, notifications: NotificationConfig, editor: EditorConfig, github: GitHubConfig, analytics_enabled: boolean | null, workspace_dir: string | null, last_app_version: string | null, show_release_notes: boolean, language: UiLanguage, git_branch_prefix: string, showcases: ShowcaseState, };
export type NotificationConfig = { sound_enabled: boolean, push_enabled: boolean, sound_file: SoundFile, };
export enum ThemeMode { LIGHT = "LIGHT", DARK = "DARK", SYSTEM = "SYSTEM" }
export type EditorConfig = { editor_type: EditorType, custom_command: string | null, remote_ssh_host: string | null, remote_ssh_user: string | null, };
export enum EditorType { VS_CODE = "VS_CODE", CURSOR = "CURSOR", WINDSURF = "WINDSURF", INTELLI_J = "INTELLI_J", ZED = "ZED", XCODE = "XCODE", CUSTOM = "CUSTOM" }
export type GitHubConfig = { pat: string | null, oauth_token: string | null, username: string | null, primary_email: string | null, default_pr_base: string | null, };
export enum SoundFile { ABSTRACT_SOUND1 = "ABSTRACT_SOUND1", ABSTRACT_SOUND2 = "ABSTRACT_SOUND2", ABSTRACT_SOUND3 = "ABSTRACT_SOUND3", ABSTRACT_SOUND4 = "ABSTRACT_SOUND4", COW_MOOING = "COW_MOOING", PHONE_VIBRATION = "PHONE_VIBRATION", ROOSTER = "ROOSTER" }
export type UiLanguage = "BROWSER" | "EN" | "JA" | "ES" | "KO";
export type ShowcaseState = { seen_features: Array<string>, };
export type DeviceFlowStartResponse = { user_code: string, verification_uri: string, expires_in: number, interval: number, };
export enum DevicePollStatus { SLOW_DOWN = "SLOW_DOWN", AUTHORIZATION_PENDING = "AUTHORIZATION_PENDING", SUCCESS = "SUCCESS" }
export enum CheckTokenResponse { VALID = "VALID", INVALID = "INVALID" }
export type GitBranch = { name: string, is_current: boolean, is_remote: boolean, last_commit_date: Date, };
export type Diff = { change: DiffChangeKind, oldPath: string | null, newPath: string | null, oldContent: string | null, newContent: string | null,
/**
* True when file contents are intentionally omitted (e.g., too large)
*/
contentOmitted: boolean,
/**
* Optional precomputed stats for omitted content
*/
additions: number | null, deletions: number | null, };
export type DiffChangeKind = "added" | "deleted" | "modified" | "renamed" | "copied" | "permissionChange";
export type RepositoryInfo = { id: bigint, name: string, full_name: string, owner: string, description: string | null, clone_url: string, ssh_url: string, default_branch: string, private: boolean, };
export type CommandBuilder = {
/**
* Base executable command (e.g., "npx -y @anthropic-ai/claude-code@latest")
*/
base: string,
/**
* Optional parameters to append to the base command
*/
params: Array<string> | null, };
export type ExecutorProfileId = {
/**
* The executor type (e.g., "CLAUDE_CODE", "AMP")
*/
executor: BaseCodingAgent,
/**
* Optional variant name (e.g., "PLAN", "ROUTER")
*/
variant: string | null, };
export type ExecutorConfig = { [key in string]?: { "CLAUDE_CODE": ClaudeCode } | { "AMP": Amp } | { "GEMINI": Gemini } | { "CODEX": Codex } | { "OPENCODE": Opencode } | { "CURSOR_AGENT": CursorAgent } | { "QWEN_CODE": QwenCode } | { "COPILOT": Copilot } };
export enum BaseAgentCapability { SESSION_FORK = "SESSION_FORK", SETUP_HELPER = "SETUP_HELPER" }
export type ClaudeCode = { append_prompt: AppendPrompt, claude_code_router?: boolean | null, plan?: boolean | null, approvals?: boolean | null, model?: string | null, dangerously_skip_permissions?: boolean | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type Gemini = { append_prompt: AppendPrompt, model: GeminiModel, yolo?: boolean | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type GeminiModel = "default" | "flash";
export type Amp = { append_prompt: AppendPrompt, dangerously_allow_all?: boolean | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type Codex = { append_prompt: AppendPrompt, sandbox?: SandboxMode | null, ask_for_approval?: AskForApproval | null, oss?: boolean | null, model?: string | null, model_reasoning_effort?: ReasoningEffort | null, model_reasoning_summary?: ReasoningSummary | null, model_reasoning_summary_format?: ReasoningSummaryFormat | null, profile?: string | null, base_instructions?: string | null, include_plan_tool?: boolean | null, include_apply_patch_tool?: boolean | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type SandboxMode = "auto" | "read-only" | "workspace-write" | "danger-full-access";
export type AskForApproval = "unless-trusted" | "on-failure" | "on-request" | "never";
export type ReasoningEffort = "low" | "medium" | "high";
export type ReasoningSummary = "auto" | "concise" | "detailed" | "none";
export type ReasoningSummaryFormat = "none" | "experimental";
export type CursorAgent = { append_prompt: AppendPrompt, force?: boolean | null, model?: string | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type Copilot = { append_prompt: AppendPrompt, model?: string | null, allow_all_tools?: boolean | null, allow_tool?: string | null, deny_tool?: string | null, add_dir?: Array<string> | null, disable_mcp_server?: Array<string> | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type Opencode = { append_prompt: AppendPrompt, model?: string | null, agent?: string | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type QwenCode = { append_prompt: AppendPrompt, yolo?: boolean | null, base_command_override?: string | null, additional_params?: Array<string> | null, };
export type AppendPrompt = string | null;
export type CodingAgentInitialRequest = { prompt: string,
/**
* Executor profile specification
*/
executor_profile_id: ExecutorProfileId, };
export type CodingAgentFollowUpRequest = { prompt: string, session_id: string,
/**
* Executor profile specification
*/
executor_profile_id: ExecutorProfileId, };
export type CreateTaskAttemptBody = { task_id: string,
/**
* Executor profile specification
*/
executor_profile_id: ExecutorProfileId, base_branch: string, };
export type RunAgentSetupRequest = { executor_profile_id: ExecutorProfileId, };
export type RunAgentSetupResponse = Record<string, never>;
export type RebaseTaskAttemptRequest = { old_base_branch: string | null, new_base_branch: string | null, };
export type GitOperationError = { "type": "merge_conflicts", message: string, op: ConflictOp, } | { "type": "rebase_in_progress" };
export type ReplaceProcessRequest = {
/**
* Process to replace (delete this and later ones)
*/
process_id: string,
/**
* New prompt to use for the replacement follow-up
*/
prompt: string,
/**
* Optional variant override
*/
variant: string | null,
/**
* If true, allow resetting Git even when uncommitted changes exist
*/
force_when_dirty: boolean | null,
/**
* If false, skip performing the Git reset step (history drop still applies)
*/
perform_git_reset: boolean | null, };
export type CommitInfo = { sha: string, subject: string, };
export type BranchStatus = { commits_behind: number | null, commits_ahead: number | null, has_uncommitted_changes: boolean | null, head_oid: string | null, uncommitted_count: number | null, untracked_count: number | null, target_branch_name: string, remote_commits_behind: number | null, remote_commits_ahead: number | null, merges: Array<Merge>,
/**
* True if a `git rebase` is currently in progress in this worktree
*/
is_rebase_in_progress: boolean,
/**
* Current conflict operation if any
*/
conflict_op: ConflictOp | null,
/**
* List of files currently in conflicted (unmerged) state
*/
conflicted_files: Array<string>, };
export type ConflictOp = "rebase" | "merge" | "cherry_pick" | "revert";
export type TaskAttempt = { id: string, task_id: string, container_ref: string | null, branch: string, target_branch: string, executor: string, worktree_deleted: boolean, setup_completed_at: string | null, created_at: string, updated_at: string, };
export type ExecutionProcess = { id: string, task_attempt_id: string, run_reason: ExecutionProcessRunReason, executor_action: ExecutorAction,
/**
* Git HEAD commit OID captured before the process starts
*/
before_head_commit: string | null,
/**
* Git HEAD commit OID captured after the process ends
*/
after_head_commit: string | null, status: ExecutionProcessStatus, exit_code: bigint | null,
/**
* dropped: true if this process is excluded from the current
* history view (due to restore/trimming). Hidden from logs/timeline;
* still listed in the Processes tab.
*/
dropped: boolean, started_at: string, completed_at: string | null, created_at: string, updated_at: string, };
export enum ExecutionProcessStatus { running = "running", completed = "completed", failed = "failed", killed = "killed" }
export type ExecutionProcessRunReason = "setupscript" | "cleanupscript" | "codingagent" | "devserver";
export type Merge = { "type": "direct" } & DirectMerge | { "type": "pr" } & PrMerge;
export type DirectMerge = { id: string, task_attempt_id: string, merge_commit: string, target_branch_name: string, created_at: string, };
export type PrMerge = { id: string, task_attempt_id: string, created_at: string, target_branch_name: string, pr_info: PullRequestInfo, };
export type MergeStatus = "open" | "merged" | "closed" | "unknown";
export type PullRequestInfo = { number: bigint, url: string, status: MergeStatus, merged_at: string | null, merge_commit_sha: string | null, };
export type Draft = { id: string, task_attempt_id: string, draft_type: DraftType, retry_process_id: string | null, prompt: string, queued: boolean, sending: boolean, variant: string | null, image_ids: Array<string> | null, created_at: string, updated_at: string, version: bigint, };
export type DraftType = "follow_up" | "retry";
export type CommandExitStatus = { "type": "exit_code", code: number, } | { "type": "success", success: boolean, };
export type CommandRunResult = { exit_status: CommandExitStatus | null, output: string | null, };
export type NormalizedEntry = { timestamp: string | null, entry_type: NormalizedEntryType, content: string, };
export type NormalizedEntryType = { "type": "user_message" } | { "type": "user_feedback", denied_tool: string, } | { "type": "assistant_message" } | { "type": "tool_use", tool_name: string, action_type: ActionType, status: ToolStatus, } | { "type": "system_message" } | { "type": "error_message", error_type: NormalizedEntryError, } | { "type": "thinking" } | { "type": "loading" } | { "type": "next_action", failed: boolean, execution_processes: number, needs_setup: boolean, };
export type FileChange = { "action": "write", content: string, } | { "action": "delete" } | { "action": "rename", new_path: string, } | { "action": "edit",
/**
* Unified diff containing file header and hunks.
*/
unified_diff: string,
/**
* Whether line number in the hunks are reliable.
*/
has_line_numbers: boolean, };
export type ActionType = { "action": "file_read", path: string, } | { "action": "file_edit", path: string, changes: Array<FileChange>, } | { "action": "command_run", command: string, result: CommandRunResult | null, } | { "action": "search", query: string, } | { "action": "web_fetch", url: string, } | { "action": "tool", tool_name: string, arguments: JsonValue | null, result: ToolResult | null, } | { "action": "task_create", description: string, } | { "action": "plan_presentation", plan: string, } | { "action": "todo_management", todos: Array<TodoItem>, operation: string, } | { "action": "other", description: string, };
export type TodoItem = { content: string, status: string, priority: string | null, };
export type NormalizedEntryError = { "type": "setup_required" } | { "type": "other" };
export type ToolResult = { type: ToolResultValueType,
/**
* For Markdown, this will be a JSON string; for JSON, a structured value
*/
value: JsonValue, };
export type ToolResultValueType = { "type": "markdown" } | { "type": "json" };
export type ToolStatus = { "status": "created" } | { "status": "success" } | { "status": "failed" } | { "status": "denied", reason: string | null, } | { "status": "pending_approval", approval_id: string, requested_at: string, timeout_at: string, } | { "status": "timed_out" };
export type PatchType = { "type": "NORMALIZED_ENTRY", "content": NormalizedEntry } | { "type": "STDOUT", "content": string } | { "type": "STDERR", "content": string } | { "type": "DIFF", "content": Diff };
export type ApprovalStatus = { "status": "pending" } | { "status": "approved" } | { "status": "denied", reason?: string, } | { "status": "timed_out" };
export type CreateApprovalRequest = { tool_name: string, tool_input: JsonValue, tool_call_id: string, };
export type ApprovalResponse = { execution_process_id: string, status: ApprovalStatus, };
export type JsonValue = number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null;