Commit Graph

1286 Commits

Author SHA1 Message Date
Louis Knight-Webb
9aef10a1bb Done. I added min-w-0 to the URL bar container on line 68. This allows the flex container to shrink below its content size, enabling the truncate class on the URL text to work properly and prevent overflow. (#1892) 2026-01-09 17:20:13 +00:00
Louis Knight-Webb
6e3421c820 Fix CommandBar input and navigation issues with state machine refactor (Vibe Kanban) (#1885)
* Done! I've removed all 7 `shortcut` properties from the action definitions in `index.ts`:

- `NewWorkspace`: removed `shortcut: 'N'`
- `Settings`: removed `shortcut: ','`
- `ToggleSidebar`: removed `shortcut: '['`
- `ToggleGitPanel`: removed `shortcut: ']'`
- `ToggleChangesMode`: removed `shortcut: 'C'`
- `ToggleLogsMode`: removed `shortcut: 'L'`
- `TogglePreviewMode`: removed `shortcut: 'P'`

The `ActionDefinition` type (and its base `ActionBase` interface) were left unchanged as requested.

* fix tailwind nto auto creating styles

* I've successfully completed all the changes. Here's a summary of what was done:

## Summary of Changes

### 1. `ActionExecutorContext` (index.ts)
- Made all properties non-optional
- Removed `gitRepoId` from context (now passed as action parameter)
- Properties now use `| null` for values that may not exist

### 2. New `GitActionDefinition` Type (index.ts)
- Added new action type with `requiresTarget: 'git'`
- Git actions now explicitly require `repoId` as a parameter

### 3. Git Actions Updated (index.ts)
- `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'`
- Each action's `execute` function takes `repoId` as third parameter
- Simplified implementations (no more fallback repo fetching logic)

### 4. `ActionsContext` Provider (ActionsContext.tsx)
- Now calls `useDevServer()` to get dev server state
- Provides all required context properties
- `executeAction` handles three action types: global, workspace, and git
- Removed `contextOverride` pattern

### 5. `ContextBarContainer` (ContextBarContainer.tsx)
- Simplified significantly - no longer builds extended context
- Uses executor context directly from provider
- Removed `containerPath` prop

### 6. `ActionVisibilityContext` (index.ts + useActionVisibility.ts)
- Made `editorType`, `devServerState`, `runningDevServerId` required
- Visibility hook now provides all values from hooks

### 7. Updated Call Sites
- `WorkspacesLayout`: Git actions now pass `repoId` as third parameter
- `WorkspacesMain`: Removed `containerPath` prop from ContextBarContainer

* Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497

* All changes are complete and type checks pass. Here's a summary of the changes made:

## Summary of Changes

### 1. `ActionExecutorContext` - Made all properties non-optional
- Removed `?` from all properties
- Removed `gitRepoId` (moved to per-action parameter)
- Changed nullable properties to use `| null` type

### 2. New `GitActionDefinition` type
- Added new action type with `requiresTarget: 'git'`
- Takes `repoId` as explicit third parameter

### 3. Git actions updated
- `GitCreatePR`, `GitMerge`, `GitRebase`, `GitChangeTarget` now use `requiresTarget: 'git'`
- Each action's `execute` receives `repoId` as parameter

### 4. `ActionsContext` provider centralized
- Now calls `useDevServer()` to provide dev server state
- Provides all required context properties from hooks
- `executeAction` handles three action types: global, workspace, git
- Removed `contextOverride` pattern

### 5. `ActionVisibilityContext` - Made dev server properties required
- `editorType`, `devServerState`, `runningDevServerId` now required
- `useActionVisibilityContext` hook provides all values

### 6. `ContextBarContainer` simplified
- Removed extended context creation
- Uses executor context directly from provider

### 7. Provider order fix
- Moved `ExecutionProcessesProvider` up to `NewDesignScope`
- Required because `useDevServer` depends on `ExecutionProcessesContext`

### Files Modified:
- `vibe-kanban/frontend/src/components/ui-new/actions/index.ts`
- `vibe-kanban/frontend/src/components/ui-new/actions/useActionVisibility.ts`
- `vibe-kanban/frontend/src/contexts/ActionsContext.tsx`
- `vibe-kanban/frontend/src/components/ui-new/containers/ContextBarContainer.tsx`
- `vibe-kanban/frontend/src/components/ui-new/containers/WorkspacesLayout.tsx`
- `vibe-kanban/frontend/src/components/ui-new/views/WorkspacesMain.tsx`
- `vibe-kanban/frontend/src/components/ui-new/scope/NewDesignScope.tsx`

* The implementation is complete. Let me summarize what was changed:

## Summary of Changes

### `pages.ts`
- Added `'selectRepo'` to `PageId` type for dynamic repo selection page
- Created `StaticPageId` type (excludes `selectRepo`) for static page records
- Added `RepoItem` interface for repo selection items
- Extended `ResolvedGroupItem` union type to include `{ type: 'repo'; repo: RepoItem }`
- Updated `Pages` record and `getPageActions` to use `StaticPageId`

### `CommandBarDialog.tsx`
- Added `repos` from `useWorkspaceContext()`
- Added `pendingGitAction` state to track git actions awaiting repo selection
- Reset `pendingGitAction` when dialog opens/closes
- Modified `getPageWithItems` to generate dynamic `selectRepo` page with repo list
- Updated `handleSelect` to:
  - Execute git actions immediately with single repo
  - Navigate to `selectRepo` page when multiple repos exist
  - Execute pending git action when user selects a repo
- Clear `pendingGitAction` when navigating back from `selectRepo` page

### `CommandBar.tsx`
- Added `FolderIcon` import
- Added rendering for `'repo'` item type with folder icon

## Behavior

1. **Single repo**: When user selects a git action (e.g., "Create Pull Request") and the workspace has only one git repo, the action executes immediately with that repo's ID.

2. **Multiple repos**: When workspace has multiple repos, selecting a git action navigates to a "Select Repository" page where the user can choose which repo to use, then the action executes with the selected repo.

3. **Back navigation**: Pressing back from the repo selection page clears the pending action and returns to the previous page.

* Done! The `CommandBarDialog` has been refactored to use a state machine pattern with `useReducer`. Here's a summary of the changes:

## Summary of Changes

**State Machine Types (lines 38-67):**
- `CommandBarState`: Discriminated union with `browsing` and `selectingRepo` states
- `CommandBarEvent`: `RESET`, `SEARCH_CHANGE`, `GO_BACK`, `SELECT_ITEM`
- `CommandBarEffect`: Side effects returned from reducer (`none` or `execute`)

**Reducer (lines 73-201):**
- Pure function returning `[newState, effect]` tuple
- Handles all state transitions based on current state and event
- Git action flow: single repo → execute, multiple repos → transition to `selectingRepo`

**Component Changes:**
- Replaced 4 `useState` calls with single `useReducer`
- `currentPage` is now derived from state (line 249-250)
- `handleSelect` computes effect from reducer, dispatches event, then handles effect (lines 456-475)
- `goBack` and `handleSearchChange` simply dispatch events (lines 446-453)

**Benefits:**
- All state transitions in one place (the reducer)
- State transitions are pure and testable
- Clear separation between state updates and side effects
- Impossible states are unrepresentable (e.g., can't have `pendingAction` while `browsing`)

* Done! Here's the final result:

## Summary

**Before:** 520 lines in 1 file (after initial state machine refactor)
**After:** 487 lines across 4 files

| File | Lines | Purpose |
|------|-------|---------|
| `CommandBarDialog.tsx` | 101 | Thin orchestration (down from 520) |
| `useCommandBarState.ts` | 177 | State machine hook |
| `useResolvedPage.ts` | 150 | Page building logic |
| `injectSearchMatches.ts` | 59 | DRY search helper |

**Key wins:**
- Main component: **520 → 101 lines** (80% reduction)
- Search injection code: **100 → 59 lines** (4× duplication eliminated)
- Each file has single responsibility
- State machine is testable in isolation
- Page building logic is reusable

* Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497

* Done! Here are the final results:

## Final Summary

| File | Before | After | Reduction |
|------|--------|-------|-----------|
| `CommandBarDialog.tsx` | 101 | 106 | +5 (linter formatting) |
| `useCommandBarState.ts` | 177 | 95 | **-82 (46%)** |
| `useResolvedPage.ts` | 150 | 95 | **-55 (37%)** |
| `injectSearchMatches.ts` | 59 | 42 | **-17 (29%)** |
| **Total** | **487** | **338** | **-149 (31%)** |

**Original single file:** 398 lines
**Final 4 files:** 338 lines (15% less code overall)

Key wins:
- Main component is now just 106 lines of thin orchestration
- State machine is flattened (if statements instead of nested switch/case)
- Page resolution is simplified with reused types
- Search injection uses reduce() instead of for-loop
- All files pass type check

* Cleanup script changes for workspace e961e311-6db4-41bf-83a1-ef8dd96eb497

* I've fixed both issues with the CommandBar. Here's a summary of what was wrong and how I fixed it:

## Root Causes

### Issue 1: Nested `<Command>` Components
The `CommandDialog` component was wrapping children in a `<Command>` component, and `CommandBar` also rendered its own `<Command>`. This nested cmdk context caused conflicts with state management.

**Fix:** Removed the `<Command>` wrapper from `CommandDialog` in `Command.tsx:26-44`, and moved the styling classes to `CommandBar`'s `<Command>` component.

### Issue 2: Unstable `dispatch` Function Causing Infinite RESET Loop
In `useCommandBarState.ts`, the `dispatch` function had `[state, repoCount]` in its `useCallback` dependency array. This caused `dispatch` to be recreated on every state change.

In `CommandBarDialog.tsx`, the `useEffect` that resets state when the modal opens had `dispatch` in its dependency array:
```tsx
useEffect(() => {
  if (modal.visible) {
    dispatch({ type: 'RESET', page });
  }
}, [modal.visible, page, dispatch]); // dispatch changes → useEffect runs → RESET
```

This created an infinite loop:
1. User types → state updates → `dispatch` recreated
2. `dispatch` changed → `useEffect` runs → `RESET` dispatched
3. State resets to empty → repeat

**Fix:** Made `dispatch` stable by using refs instead of state in dependencies:
```tsx
const stateRef = useRef<CommandBarState>(browsing(initialPage));
const repoCountRef = useRef(repoCount);

const dispatch = useCallback(
  (event: CommandBarEvent): CommandBarEffect => {
    const [, effect] = reducer(stateRef.current, event, repoCountRef.current);
    rawDispatch(event);
    return effect;
  },
  [] // No dependencies - uses refs for current values
);
```

## Files Changed
1. `vibe-kanban/frontend/src/components/ui-new/primitives/Command.tsx` - Removed nested `<Command>` wrapper from `CommandDialog`
2. `vibe-kanban/frontend/src/components/ui-new/primitives/CommandBar.tsx` - Added styling classes that were on the removed wrapper
3. `vibe-kanban/frontend/src/components/ui-new/dialogs/commandBar/useCommandBarState.ts` - Made `dispatch` stable using refs
2026-01-09 16:25:42 +00:00
Alex Netsch
2c53fc976b Add Azure Repos integration documentation (Vibe Kanban) (#1855)
* Done. I've added the Azure Repos integration documentation:

**Created:**
- `docs/integrations/azure-repos-integration.mdx` - New documentation page covering:
  - Introduction explaining the Azure CLI dependency
  - Manual setup instructions (Azure CLI installation, DevOps extension, authentication)
  - Supported URL formats (modern and legacy Azure DevOps URLs)
  - Pull request creation workflow (same as GitHub)

**Modified:**
- `docs/docs.json` - Added the new page to the Integrations navigation group, positioned right after the GitHub integration page

* Done. I've created `docs/.mintignore` to exclude the `AGENTS.md` and `CLAUDE.md` files from Mintlify's published documentation and link validation. These are AI writing style guides with example placeholder links, not actual user-facing docs.

Once you commit and push this change, the Mintlify validation should pass.
2026-01-09 16:01:36 +00:00
Alex Netsch
29595c1929 Add Azure DevOps repository support for PR operations (Vibe Kanban) (#1808)
* All tasks are complete. Let me summarize what was implemented:

I've successfully implemented Azure DevOps repos support alongside the existing GitHub integration. Here's what was done:

- **`mod.rs`** - Defines the `GitHostService` trait and factory functions for creating services
- **`types.rs`** - Unified types: `GitHostProvider`, `RepoInfo`, `GitHostError`, `CreatePrRequest`, `UnifiedPrComment`
- **`detection.rs`** - URL pattern matching for auto-detecting GitHub (including Enterprise) and Azure DevOps
- **`github/mod.rs`** - `GitHubHostService` implementing the trait
- **`github/cli.rs`** - `GhCli` wrapper (moved from old location)
- **`azure/mod.rs`** - `AzureHostService` implementing the trait
- **`azure/cli.rs`** - `AzCli` wrapper for Azure DevOps CLI commands

1. **Auto-detection**: The system detects the provider from the git remote URL:
   - `github.com` → GitHub
   - `github.*.com` → GitHub Enterprise
   - `dev.azure.com`, `*.visualstudio.com`, or URLs with `/_git/` → Azure DevOps

2. **Unified trait interface**: Both providers implement `GitHostService` with methods for:
   - `get_repo_info()` - Get repository identification
   - `check_auth()` - Verify CLI authentication
   - `create_pr()` - Create pull requests
   - `get_pr_status()` - Get PR status by URL
   - `list_prs_for_branch()` - List PRs for a branch
   - `get_pr_comments()` - Get PR comments

3. **Azure CLI commands supported**:
   - `az repos pr create` - Create PRs
   - `az repos pr show` - View PR details
   - `az repos pr list` - List PRs
   - `az repos pr list-threads` - Get PR comments
   - `az account show` - Auth check

- `pr.rs` - Uses auto-detection for PR creation
- `pr_monitor.rs` - Uses provider detection from PR URL
- `task_attempts.rs` - Uses git_host for push auth checking
- `error.rs` - Updated `GitHost` error variant
- `share.rs` - Updated `GitHost` error variant
- `generate_types.rs` - Updated type exports

- Old `crates/services/src/services/github.rs` module and directory (replaced by git_host)

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

All tests pass, including the new URL decoding tests. The fix is complete - the URL-encoded components (like `Vibe%20Kanban%20Test`) will now be properly decoded to `Vibe Kanban Test` before being passed to the Azure CLI.

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

All done! Here's a summary of the changes:

Updated `get_repo_info()` to use the Azure CLI's `az repos show --detect true` command instead of manual URL parsing, similar to how GitHub uses `gh repo view --json owner,name`.

1. **Added `extract_repo_name_from_url()`** - A simple helper that extracts just the repository name from Azure DevOps URLs (looks for `/_git/{repo}` pattern). This is still needed because `az repos show` requires the `--repository` parameter.

2. **Updated `get_repo_info()`** - Now uses `az repos show --repository {name} --detect true --output json` which:
   - Auto-detects organization and project from git config
   - Returns canonical names (properly decoded)
   - Validates the repo exists

3. **Added `extract_org_from_response()`** - Extracts the organization from the `remoteUrl` field in the CLI response, with fallback to URL parsing.

4. **Fixed `run()` method** - Now properly passes the `dir` parameter to `Command::current_dir()` so the `--detect` flag works correctly.

5. **Kept `parse_azure_remote_url()`** - Still used as a fallback for organization extraction and for PR URL parsing.

6. **Added tests** - New tests for `extract_repo_name_from_url()` covering various URL formats.

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

Done! The cleanup is complete. Here's what was removed:

Removed the brittle `parse_azure_remote_url()` function and related code:

1. **Removed `AzureRepoInfo` struct** - No longer needed
2. **Removed `parse_azure_remote_url()` function** - The ~90-line function that manually parsed various Azure DevOps URL formats
3. **Updated `get_repo_info()`** - Changed from fallback (`unwrap_or_else`) to error (`ok_or_else`) when organization can't be extracted from the CLI response
4. **Removed 4 tests** - `test_parse_azure_remote_url_https`, `test_parse_azure_remote_url_visualstudio`, `test_parse_azure_remote_url_ssh`, `test_parse_azure_remote_url_with_spaces`

The code now relies entirely on:
- `extract_repo_name_from_url()` - Simple helper to get repo name from URL (for passing to `az repos show`)
- `az repos show --detect true` - Azure CLI command that auto-detects org/project from git config
- `extract_org_from_response()` - Extracts org from the CLI's `remoteUrl` JSON field

The implementation is complete. Here's a summary of the changes:

Simplified the Azure DevOps integration by using the CLI's `--detect` flag instead of parsing URLs to extract org/project/repo.

1. **`types.rs`** - Changed `RepoInfo::AzureDevOps` to store just `repo_path: PathBuf` instead of `organization`, `project`, and `repo_name`. Removed the unused `repo_name()` method.

2. **`cli.rs`** - Major simplification:
   - Removed URL parsing helpers: `decode_url_component()`, `extract_repo_name_from_url()`, `extract_org_from_response()`
   - `get_repo_info()` now just verifies it's a valid Azure repo via `az repos show --detect true` and returns the path
   - `create_pr()` now takes `repo_path` and uses `--detect true` instead of explicit org/project/repo
   - `list_prs_for_branch()` now takes `repo_path` and uses `--detect true`
   - `get_pr_threads()` now takes `repo_path` and uses `--detect true`
   - `view_pr()` now takes the full PR URL and parses org + PR ID internally
   - `parse_pr_url()` simplified to return just `(org, pr_id)` instead of 4 values
   - Parsing functions simplified to extract URLs from response's `repository.webUrl` field
   - Updated tests for the new API

3. **`mod.rs`** - Updated `AzureHostService` to:
   - Extract `repo_path` from `RepoInfo::AzureDevOps`
   - Pass `repo_path` to CLI methods that need it
   - Pass the PR URL directly to `view_pr()` for `get_pr_status()`

- URL parsing reduced to minimal extraction of org + PR ID from PR URLs (only needed for `get_pr_status()`)
- Repo-based operations don't parse URLs at all - CLI auto-detects via git config
- Much cleaner, less brittle code

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

All done. The implementation is complete:

**Summary of changes:**

1. **`types.rs`**: Updated `RepoInfo::AzureDevOps` to store `organization_url`, `project`, `repo_name` instead of `repo_path`

2. **`cli.rs`**:
   - `get_repo_info()` now parses the JSON response from `az repos show --detect true` to extract repo name, project name, and organization URL
   - Added `extract_org_url()` helper to extract the base org URL from the API URL
   - Updated `create_pr()`, `list_prs_for_branch()`, `get_pr_threads()` to take explicit `organization_url`, `project`, `repo_name` params

3. **`mod.rs`** (`AzureHostService`):
   - `create_pr()`, `list_prs_for_branch()`, `get_pr_comments()` all now extract org/project/repo from `RepoInfo` and pass them to the CLI methods

The key insight was that the `url` field from `az repos show` (e.g., `https://dev.azure.com/{org}/.../_apis/...`) can be truncated to `https://dev.azure.com/{org}` and used directly with the `--organization` flag — minimal URL parsing needed.

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

* Done. Refactored all 4 `serde_json::Value` parsing sites to use typed structs:

**Changes to `cli.rs`:**

1. **Added typed response structs** with `#[derive(Deserialize)]`:
   - `AzRepoShowResponse`, `AzProject` - for `az repos show`
   - `AzPrResponse`, `AzRepository`, `AzCommit` - for PR responses
   - `AzThread`, `AzThreadContext`, `AzFilePosition`, `AzThreadComment`, `AzAuthor` - for thread comments

2. **Updated parsing functions**:
   - `get_repo_info()` - now deserializes into `AzRepoShowResponse`
   - `parse_pr_response()` - now deserializes into `AzPrResponse`
   - `parse_pr_list_response()` - now deserializes into `Vec<AzPrResponse>`
   - `parse_pr_threads()` - now deserializes into `Vec<AzThread>`

3. **Replaced `extract_pr_info()`** with `az_pr_to_info()` that takes the typed struct directly

4. **Removed `serde_json::Value` import** - no longer needed

The code is now cleaner with no `.get().and_then().as_str()` chains, and serde provides better error messages on parse failures.

* Done. Added the missing `--repository` parameter to `get_pr_threads()`:

1. **`cli.rs`**: Added `repo_name: &str` parameter and `--repository` flag to the CLI command
2. **`mod.rs`**: Updated `get_pr_comments()` to extract both `organization_url` and `repo_name` from `RepoInfo` and pass them to the CLI

Done. Here's a summary of the changes:

**Changes made to `crates/services/src/services/git_host/azure/cli.rs`:**

1. **Removed git2 dependency** - No longer imports `git2::Repository`

2. **Added new typed structs** for `az repos list` response:
   - `AzRepoListItem` - with `name`, `project`, and `remote_url` fields
   - `AzRepoProject` - with `name` field

3. **Rewrote `get_repo_info()`** to use `az repos list --detect true`:
   - Runs CLI command from the repo directory to auto-detect org/project
   - Takes the first repo from the list (assuming single repo per directory)
   - Extracts org from `remoteUrl` field

4. **Replaced `parse_azure_remote_url()`** with simpler `extract_org_from_remote_url()`:
   - Only extracts the organization name from the URL
   - Handles both `dev.azure.com` and `visualstudio.com` formats
   - Much simpler than the previous 3-tuple URL parser

5. **Updated tests** - Replaced the old URL parsing tests with new `extract_org_from_remote_url` tests

The key improvement is that `az repos list --detect true` uses the Azure CLI's built-in detection (from git config) to find the org and project, then returns all repo info including project name. This avoids git2 library usage and complex URL parsing entirely.

Done. Here's a summary of all changes:

**Summary of Changes**

1. **`crates/services/src/services/git_host/types.rs`**:
   - Added `project_id` and `repo_id` fields to `RepoInfo::AzureDevOps` enum variant

2. **`crates/services/src/services/git_host/azure/cli.rs`**:
   - Added `id` field to `AzRepoListItem` struct
   - Added `id` field to `AzRepoProject` struct
   - Added `AzThreadsResponse` struct to wrap the `{ "value": [...] }` REST API response
   - Updated `get_repo_info()` to return `project_id` and `repo_id` from `az repos list` output
   - Updated `get_pr_threads()` to:
     - Accept `project_id` and `repo_id` instead of names
     - Use `az rest` with REST API URL instead of non-existent `az repos pr list-threads`
   - Updated `parse_pr_threads()` to unwrap the `value` field from REST API response

3. **`crates/services/src/services/git_host/azure/mod.rs`**:
   - Updated `create_pr` and `list_prs_for_branch` to use `..` pattern for new fields
   - Updated `get_pr_comments()` to extract and pass `project_id` and `repo_id` to CLI

**Key Improvements**:
- Uses UUIDs (`project_id`, `repo_id`) instead of names for REST API calls, avoiding URL encoding issues with names containing spaces like "Vibe Kanban Test"
- Fixed `get_pr_threads()` to use `az rest` since `az repos pr list-threads` doesn't exist as an Azure CLI command
- All unit tests pass

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

Done. The fix adds `--resource 499b84ac-1321-427f-aa17-267ca6975798` to the `az rest` command, which tells it to request an Azure DevOps token instead of a generic Azure token. This should now properly authenticate to the Azure DevOps REST API.

Done. The fix replaces `az rest` with `az devops invoke --area git --resource pullRequestThreads`. This uses the same authentication as other `az repos pr` commands, so it should work without requiring the separate "identity materialization" step.

Done. The fix replaces the single combined string for `--route-parameters` with individual arguments for each `key=value` pair. This matches how the Azure CLI expects the parameters to be passed - each route parameter should be a separate shell argument after the `--route-parameters` flag.

Done. Removed all the requested comments from:
- `crates/server/src/routes/task_attempts.rs` (lines 451, 490)
- `crates/server/src/routes/task_attempts/pr.rs` (lines 283, 516)
- `crates/services/src/services/git_host/azure/cli.rs` (section header comment, doc comments on structs and methods)

* Done. Removed the module-level doc comment and all the method doc comments from the `GitHostService` trait and public functions in `mod.rs`.

Done. Removed the obvious/redundant comments from `types.rs`.

Done. Removed the unnecessary `Arc` usage from all three functions in `mod.rs`. The strings are already cloned when extracted from `RepoInfo`, so we can just clone them directly in the retry closure.

* All tests pass. Fixed the `npm run check` and `npm run lint` issues by:

1. Regenerated TypeScript types from Rust
2. Updated `frontend/src/lib/api.ts` to use `CreatePrApiRequest` instead of `CreateGitHubPrRequest`
3. Updated `CreatePRDialog.tsx` to handle the new error types (`cli_not_installed`/`cli_not_logged_in` with a `provider` field instead of `github_cli_not_installed`/`github_cli_not_logged_in`)
4. Fixed clippy warnings about collapsible if statements in `parse_pr_url()`

* Done. I've made `url`, `diff_hunk`, and `author_association` optional in the `UnifiedPrComment` type:

**Changes made:**

1. **`crates/services/src/services/git_host/types.rs`** - Changed the `UnifiedPrComment` enum:
   - `url: String` → `url: Option<String>`
   - `diff_hunk: String` → `diff_hunk: Option<String>`
   - `author_association: String` → `author_association: Option<String>`

2. **`crates/services/src/services/git_host/azure/cli.rs`** - Updated Azure comment creation to use `None` instead of empty strings

3. **`crates/services/src/services/git_host/github/mod.rs`** - Wrapped GitHub values in `Some()`

4. **`frontend/src/components/ui/github-comment-card.tsx`** - Updated interface to allow `url?: string | null` and `diffHunk?: string | null`

5. **`frontend/src/components/ui/wysiwyg/nodes/github-comment-node.tsx`**:
   - Updated `NormalizedComment` interface
   - Fixed click handler to check `if (data.url)` before opening
   - Removed `data.url` from validation (only `id`, `comment_type`, `author`, `body` required)

All checks pass (`pnpm run check`, `pnpm run lint`, `cargo test --workspace`).

* Done. All three changes are complete:

1. **Removed unnecessary temp file** in `azure/cli.rs:create_pr()` - was writing body to temp file then immediately reading it back. Now just passes `body` directly to `OsString`.

2. **Added structs for JSON parsing** in `github/cli.rs:parse_pr_comments()` - replaced manual `item.get("field")...` parsing with `GhCommentsWrapper` and `GhCommentResponse` structs using serde.

3. **Added structs for JSON parsing** in `github/cli.rs:parse_pr_review_comments()` - replaced manual parsing with `GhReviewCommentResponse` struct.

All checks pass (`pnpm run check`, `pnpm run lint`, `cargo test --workspace`).

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

Done. Both changes are complete:

1. **Inlined single-field structs** - Consolidated `GhCommentAuthor` and `GhReviewCommentUser` into a single `GhUserLogin` struct that's reused by both `GhCommentResponse` and `GhReviewCommentResponse`.

2. **Converted `extract_pr_info` to struct parsing** - Added `GhPrResponse` and `GhMergeCommit` structs. Replaced the manual `Value::get()` parsing with serde deserialization. The new `pr_response_to_info()` helper converts the parsed struct to `PullRequestInfo`. Also removed the now-unused `serde_json::Value` import.

All checks pass (`pnpm run check`, `pnpm run lint`, `cargo test --workspace`).

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

* Done. I've updated `detection.rs` to use `GitCli` instead of `git2`:

1. **Added `get_remote_url` method to `GitCli`** (`git/cli.rs`) - Uses `git remote get-url <remote>` to get the URL
2. **Updated `detect_provider`** (`git_host/detection.rs`) - Now uses `GitCli::get_remote_url()` instead of `git2::Repository`

This keeps the codebase consistent with the pattern of using `GitCli` for git operations rather than mixing `git2` directly in various modules.

All checks pass (`pnpm run check`, `pnpm run lint`, `cargo test --workspace`).

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

* Done! The refactor is complete. Here's a summary of the changes:

**New Architecture:**

1. **`ProviderKind` enum** (was `GitHostProvider`) - The discriminant for provider types (GitHub, AzureDevOps, Unknown)

2. **`GitHostProvider` trait** (was `GitHostService`) - The interface that provider implementations must satisfy

3. **`GitHubProvider` struct** (was `GitHubHostService`) - GitHub implementation

4. **`AzureDevOpsProvider` struct** (was `AzureHostService`) - Azure DevOps implementation

5. **`GitHostService` struct** (new) - Main entry point that:
   - Holds repo context (`repo_path`, `GitCli`)
   - Provides `provider_for_remote(remote_name)` to get a provider for a specific remote
   - Provides `provider_from_url(url)` for URL-based detection (e.g., PR URLs)
   - Provides `provider_for_kind(kind)` for direct provider construction

**Benefits:**
- Provider detection is now contextual - callers specify which remote they want
- The service struct encapsulates provider detection logic
- Cleaner separation: `GitHostService` is the facade, `GitHostProvider` trait is the contract
- Ready for multi-remote support (different providers for different remotes)

All checks pass (`pnpm run check`, `pnpm run lint`, `cargo test --workspace`).

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

All the call sites have been updated to use the new cleaner `GitHostService` facade API. Here's a summary of the changes:

**Changes made:**

1. **`pr.rs:414-418` (`attach_existing_pr`)**: Simplified from:
   ```rust
   let git_host = git_host::GitHostService::new(&repo.path);
   let git_host_provider = git_host.provider_for_remote("origin")?;
   let repo_info = git_host_provider.get_repo_info(&repo.path).await?;
   let prs = git_host_provider.list_prs_for_branch(&repo_info, &workspace.branch).await?;
   ```
   To:
   ```rust
   let git_host = git_host::GitHostService::new(&repo.path);
   let prs = git_host.list_prs_for_branch(&workspace.branch).await?;
   ```

2. **`pr.rs:511-525` (`get_pr_comments`)**: Simplified from provider-based pattern to:
   ```rust
   let git_host = git_host::GitHostService::new(&repo.path);
   let provider = git_host.provider_kind()?;
   match git_host.get_pr_comments(pr_info.number).await { ... }
   ```

3. **`task_attempts.rs:451-453` (`push_task_attempt_branch`)**: Removed explicit `check_auth()` call since auth is now checked during the actual operation. Just verify provider is supported:
   ```rust
   let git_host = git_host::GitHostService::new(&worktree_path);
   git_host.provider_kind()?;
   ```

4. **`task_attempts.rs:490-492` (`force_push_task_attempt_branch`)**: Same simplification.

The new API is much cleaner - call sites just create a `GitHostService::new(path)` and call methods directly without dealing with providers, repo info, or explicit auth checks.

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

The refactoring is complete. Here's a summary of what was done:

**Changes made:**

1. **`crates/services/Cargo.toml`** - Added `enum_dispatch` dependency

2. **`crates/services/src/services/git_host/mod.rs`** - Completely rewritten:
   - `GitHostProvider` is now a public trait with `#[enum_dispatch(GitHostService)]`
   - `GitHostService` is now an enum with `GitHub` and `AzureDevOps` variants
   - Constructors: `from_pr_url(url)` and `from_remote_url(url)` - no `new()` method
   - Methods now take `repo_path` as a parameter where needed

3. **`crates/services/src/services/git_host/github/mod.rs`** - Updated to match new trait signature (methods take `repo_path`, `check_auth` called inside `create_pr`)

4. **`crates/services/src/services/git_host/azure/mod.rs`** - Updated similarly

5. **`crates/services/src/services/git.rs`** - Added `get_remote_url()` method to `GitService`

6. **Call site updates:**
   - `pr_monitor.rs` - Uses `from_pr_url`
   - `pr.rs` - Uses `get_remote_name_from_branch_name` + `get_remote_url` + `from_remote_url`
   - `task_attempts.rs` - Same pattern for push functions

**New API usage:**
```rust
// From a PR URL (e.g., for checking PR status)
let git_host = GitHostService::from_pr_url(&pr_url)?;
let status = git_host.get_pr_status(&pr_url).await?;

// From a remote URL (e.g., for creating PRs)
let remote_name = git_service.get_remote_name_from_branch_name(&repo_path, &branch)?;
let remote_url = git_service.get_remote_url(&repo_path, &remote_name)?;
let git_host = GitHostService::from_remote_url(&remote_url)?;
let pr_info = git_host.create_pr(&repo_path, &pr_request).await?;

// Get provider kind (infallible since already constructed)
let provider = git_host.provider_kind();
```

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

All cleaned up. Here's the final architecture:

**`git_host/mod.rs`:**
```rust
pub trait GitHostProvider: Send + Sync {
    async fn create_pr(&self, repo_path: &Path, request: &CreatePrRequest) -> Result<PullRequestInfo, GitHostError>;
    async fn get_pr_status(&self, pr_url: &str) -> Result<PullRequestInfo, GitHostError>;
    async fn list_prs_for_branch(&self, repo_path: &Path, branch_name: &str) -> Result<Vec<PullRequestInfo>, GitHostError>;
    async fn get_pr_comments(&self, repo_path: &Path, pr_number: i64) -> Result<Vec<UnifiedPrComment>, GitHostError>;
    fn provider_kind(&self) -> ProviderKind;
}

pub enum GitHostService {
    GitHub(GitHubProvider),
    AzureDevOps(AzureDevOpsProvider),
}

impl GitHostService {
    pub fn from_url(url: &str) -> Result<Self, GitHostError>
}
```

**Changes made:**
1. Removed `check_auth` and `get_repo_info` from the public trait - they're now private methods on each provider
2. Consolidated `from_pr_url` and `from_remote_url` into a single `from_url` constructor
3. The trait now has exactly 5 methods - the minimal public API needed by call sites

**Call site usage is clean:**
```rust
// From any URL (PR URL or remote URL)
let git_host = GitHostService::from_url(&url)?;

// Use the trait methods
let pr_info = git_host.create_pr(&repo_path, &request).await?;
let status = git_host.get_pr_status(&pr_url).await?;
let prs = git_host.list_prs_for_branch(&repo_path, &branch).await?;
let comments = git_host.get_pr_comments(&repo_path, pr_number).await?;
let kind = git_host.provider_kind();
```

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

Done. The refactoring is complete:

1. **Created `GitHubRepoInfo`** in `git_host/github/cli.rs` - a simple struct with `owner` and `repo_name`
2. **Created `AzureRepoInfo`** in `git_host/azure/cli.rs` - a struct with `organization_url`, `project`, `project_id`, `repo_name`, `repo_id`
3. **Updated both providers** to use their respective provider-specific structs directly, removing all the match arms and error cases for "wrong variant" that could never happen
4. **Removed the shared `RepoInfo` enum** from `types.rs` and the public exports

The code is cleaner now - each provider has its own internal representation of repo info, and there's no shared enum that requires impossible error handling paths.

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

The fix compiles. The issue was that `get_remote_name_from_branch_name` was calling `get_remote_from_branch_ref` which uses `repo.branch_remote_name()` - this git2 function requires the branch to have upstream tracking configured. For local branches that haven't been pushed yet (or don't have tracking set), this fails with the error you saw.

The fix changes the behavior to fall back to the default remote (typically "origin") when the branch doesn't have upstream tracking configured. This makes sense because:

1. Most repos only have one remote anyway
2. When creating a PR for a local branch, we need to push to *some* remote - the default is the sensible choice
3. The original code computed `default_remote` but never actually used it as a fallback

Done. Added `get_remote_url_from_branch_or_default` to `GitService` and updated all 4 call sites. The pattern is now:

```rust
let remote_url = deployment
    .git()
    .get_remote_url_from_branch_or_default(&repo_path, &branch)?;
let git_host = git_host::GitHostService::from_url(&remote_url)?;
```

Two lines instead of four, and the function name makes the fallback behavior explicit.

Done. Removed the unnecessary provider detection checks from both `push_task_attempt_branch` and `force_push_task_attempt_branch`. The push operations now just push directly - git push works with any remote regardless of whether we support it as a PR provider. Auth errors from git push itself (SSH keys, HTTPS credentials) still come through `GitServiceError::GitCLI(...)` and propagate to the frontend the same way.

* All done. Removed the low-value comments:
- "Create git host from the PR URL"
- "Fetch comments"
- "Get the URL for a remote (e.g., "origin")."
- "Azure DevOps-specific repository information"
- "GitHub-specific repository information"
- "Get the remote URL for the branch to detect the provider" (2 places)
- "Get repository info from the GitHub CLI"
- "Get repository info from the Azure CLI"
- "Check authentication status" (2 places)

Kept comments that provide actual value like the fallback behavior explanation on `get_remote_url_from_branch_or_default`.

All done. Removed the low-value comments:
- "Create git host from the PR URL"
- "Fetch comments"
- "Get the URL for a remote (e.g., "origin")."
- "Azure DevOps-specific repository information"
- "GitHub-specific repository information"
- "Get the remote URL for the branch to detect the provider" (2 places)
- "Get repository info from the GitHub CLI"
- "Get repository info from the Azure CLI"
- "Check authentication status" (2 places)
- "Get PR status from URL (auto-detects provider)"
- "High-level errors originating from the Azure CLI."
- "High-level errors originating from the GitHub CLI."
- "Azure DevOps hosting provider implementation"
- "GitHub hosting provider implementation"
- "Newtype wrapper for invoking the `gh` command."
- "Newtype wrapper for invoking the `az` command."
- "Trait for git hosting provider operations (GitHub, Azure DevOps, etc.)"
- All the trait method doc comments (Create a pull request, Get PR status, etc.)
- "Git hosting service - dispatches to the appropriate provider."
- "Create a GitHostService by detecting the provider from a URL."
- Simplified the Azure DevOps pattern comments in detection.rs

* Done. Here's a summary of the fix:

**Problem**: `get_repo_info` used `az repos list --detect true` which returns ALL repos in the Azure DevOps project, then just took the first one. This was wrong for multi-repo projects.

**Solution**:
1. `AzureDevOpsProvider` now stores the remote URL passed to `from_url()`
2. `get_repo_info` now takes the remote URL and filters the repo list to find the matching repo using `remote_urls_match()`
3. Added `remote_urls_match()` helper that normalizes URLs (lowercase, strips trailing `/` and `.git`) for comparison
4. Added `extract_organization_url()` to get the Azure organization URL from a remote URL (supports both `dev.azure.com` and legacy `visualstudio.com` formats)
5. Removed the now-unused `extract_org_from_remote_url()` function

The flow is now:
- Call site gets remote URL via `get_remote_url_from_branch_or_default()`
- Creates `GitHostService::from_url(&remote_url)` which stores the URL on `AzureDevOpsProvider`
- When `get_repo_info` is called, it lists all repos in the project and finds the one matching the stored remote URL

Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

* Done. Summary of changes:

1. **`pr.rs:get_pr_comments`** - Now gets the remote URL from `workspace_repo.target_branch` instead of using the PR URL to create the `GitHostService`

2. **`azure/cli.rs`**:
   - Added `ssh_url` field to `AzRepoListItem`
   - Updated `get_repo_info` to detect if the input URL is SSH (`starts_with("git@")`) and compare against the appropriate field (`ssh_url` vs `remote_url`)
   - Renamed `remote_urls_match` to `urls_match` since it now handles both HTTPS and SSH URLs
   - Added SSH URL test case

* Build passes. The simple fix handles both SSH formats without adding a dependency.

* Build passes. Now `ssh_url` is optional - if it's not in the response and the user has an SSH remote configured, they'll get a clear error message ("No repo found matching remote URL: ...").

* Done. The `urls_match` function now normalizes `ssh://` prefix to scp-style before comparing.

* Done. Summary of changes:

1. **Removed `remote_url` field from `AzureDevOpsProvider`** - no longer stored on the struct

2. **Updated `GitHostProvider` trait** - added `remote_url: &str` parameter to:
   - `create_pr`
   - `list_prs_for_branch`
   - `get_pr_comments`

3. **Updated `AzureDevOpsProvider`** - methods now accept `remote_url` and pass it to `get_repo_info`

4. **Updated `GitHubProvider`** - methods accept `_remote_url` (unused, since gh CLI auto-detects)

5. **Updated call sites in `pr.rs`** - all three methods now pass `remote_url`:
   - `create_pr` passes `&remote_url`
   - `list_prs_for_branch` passes `&remote_url`
   - `get_pr_comments` passes `&remote_url`

6. **Fixed `attach_existing_pr`** - now uses `workspace_repo.target_branch` instead of `workspace.branch` when getting the remote URL (consistent with other call sites)

* Cleanup script changes for workspace 28eb9564-f95a-42e0-8cf2-5228c2ffc0bf

* Update frontend remote copy (vibe-kanban a7bf13b6)

We added azure support but in the frontend many things have github specific wording. Please fix!

* Done. I've addressed the PR comment by:

1. **Renamed `CreatePrError` to `PrError`** - A more generic name that works for both `create_pr` and `attach_existing_pr`

2. **Updated `attach_existing_pr`** to mirror the error handling from `create_pr`:
   - Changed return type from `ApiResponse<AttachPrResponse>` to `ApiResponse<AttachPrResponse, PrError>`
   - Added error handling for `GitHostService::from_url()` - handles `UnsupportedProvider` and `CliNotInstalled`
   - Added error handling for `list_prs_for_branch()` - handles `CliNotInstalled` and `AuthFailed`

3. **Updated `generate_types.rs`** to use the renamed `PrError`

4. **Updated `frontend/src/lib/api.ts`** to use `PrError` instead of `CreatePrError`

5. **Regenerated TypeScript types** and verified all checks pass
2026-01-09 15:50:34 +00:00
GitHub Action
3ad03a0a99 chore: bump version to 0.0.147 2026-01-09 14:46:16 +00:00
Solomon
64fe120e72 Explicitly specify the SQLite journal mode (#1882) 2026-01-09 14:44:26 +00:00
Solomon
95ea78cef6 Revert "Reduce SQLITE db locks (#1806)" (#1878)
This reverts commit 25c6d0a7c0.
2026-01-09 12:32:50 +00:00
Alex Netsch
e73c1b4bff All done. Here's a summary of the fix: (#1875)
## Summary

Fixed PR comment labels showing raw translation keys instead of translated text.

**Problem:** The `CommentWidgetLine.tsx` and `ReviewCommentRenderer.tsx` components were using translation keys that didn't exist in the translation files:
- `comments.addReviewComment`
- `comments.addPlaceholder`
- `comments.editPlaceholder`
- `actions.cancel`
- `actions.saveChanges`
- `actions.copied`

**Solution:** Added the missing translation keys to `common.json` in all 6 locales:
- English (en)
- Spanish (es)
- Japanese (ja)
- Korean (ko)
- Simplified Chinese (zh-Hans)
- Traditional Chinese (zh-Hant)

**Verification:**
-  `pnpm run check` passes (TypeScript and Rust checks)
-  i18n check script confirms translation keys are consistent across all locales
-  No duplicate JSON keys
2026-01-09 12:32:50 +00:00
Louis Knight-Webb
06862ab010 Fix GitHub PR button display and refactor RepoCard styling (Vibe Kanban) (#1872)
* Both issues have been fixed:

**1. Fixed translation parameter mismatch** (`RepoCard.tsx:170, 176`)
- Changed `{ prNumber }` to `{ number: prNumber }` to match the translation key `Open PR #{{number}}`

**2. Refactored PR badge styling** (`RepoCard.tsx:156-180`)
- Replaced hardcoded Tailwind colors with design system tokens:
  - Merged badge: `bg-panel text-success` (uses semantic success color)
  - Open PR button/badge: `bg-panel text-normal hover:bg-tertiary transition-colors`
- Updated spacing to use consistent tokens: `gap-half`, `px-base`, `py-half`
- Changed border radius from `rounded-full` to `rounded-sm` to match other UI elements in the panel

* Both fixes are complete:

1. **Added spacing** - Added `mt-half` to the PR status row container (line 158) to create visual separation from the Actions row below

2. **Made merged PRs clickable** - When `prStatus === 'merged'` and `prUrl` is available, it now renders a clickable `<button>` with:
   - The external link icon (`ArrowSquareOutIcon`)
   - Hover state (`hover:bg-tertiary`)
   - Same transition effect as the open PR button

* improve styles
2026-01-09 09:59:54 +00:00
Solomon
25e50a9b6d Revert "disable version bump (#1857)" (#1873)
This reverts commit d1c8ad9ea0.
2026-01-09 09:53:53 +00:00
Solomon
47facf12ec Fix worktree path handling on windows (#1859) 2026-01-09 09:31:08 +00:00
Louis Knight-Webb
af70dd9239 The implementation is complete. Here's a summary of the changes made: (#1871)
## Summary

I've implemented the GitHub PR status display on `WorkspaceSummary.tsx`. The changes include:

### Backend Changes

1. **`crates/db/src/models/merge.rs`** - Added a new method `get_latest_pr_status_for_workspaces()` that efficiently queries the latest PR status for all workspaces grouped by archived status.

2. **`crates/server/src/routes/task_attempts/workspace_summary.rs`** - Added `pr_status: Option<MergeStatus>` field to the `WorkspaceSummary` struct and included the PR status query in the summary endpoint.

### Frontend Changes

3. **`frontend/src/components/ui-new/hooks/useWorkspaces.ts`** - Added `prStatus` to the `SidebarWorkspace` interface and mapped it in `toSidebarWorkspace()`.

4. **`frontend/src/components/ui-new/primitives/WorkspaceSummary.tsx`** - Added:
   - Import for `GitPullRequestIcon`
   - `prStatus` prop to the component
   - Display logic showing:
     - **PR open**: `GitPullRequestIcon` with `text-brand` (orange) color
     - **PR merged**: `GitPullRequestIcon` with `text-success` (green) color
     - **No PR/closed/unknown**: No icon displayed

5. **`frontend/src/components/ui-new/views/WorkspacesSidebar.tsx`** - Passed the `prStatus` prop to both active and archived workspace summaries.

### Generated Types

6. **`shared/types.ts`** - Auto-generated to include the new `pr_status` field in `WorkspaceSummary`.
2026-01-09 09:09:11 +00:00
Anastasiia Solop
b743f849f7 Add rename workspace functionality (Vibe Kanban) (#1868)
* I've added the rename workspace functionality. Here's a summary of the changes:

## Summary

The backend already had rename workspace support via the `PUT /api/task-attempts/{attemptId}` endpoint with the `name` field. I added the frontend UI to expose this functionality.

### Files Created

1. **`frontend/src/components/ui-new/dialogs/RenameWorkspaceDialog.tsx`**
   - New dialog component for renaming workspaces
   - Shows the current name (or branch name as fallback)
   - Allows user to input a new name
   - Handles mutation with proper error handling and cache invalidation

### Files Modified

1. **`frontend/src/components/ui-new/actions/index.ts`**
   - Added `PencilSimpleIcon` import
   - Added `RenameWorkspaceDialog` import
   - Added new `RenameWorkspace` action that shows the rename dialog

2. **`frontend/src/components/ui-new/actions/pages.ts`**
   - Added `Actions.RenameWorkspace` to the `workspaceActions` page (at the top of the list)

3. **`frontend/src/i18n/locales/en/common.json`**
   - Added translations for the rename workspace dialog under `workspaces.rename`

### How to Use

Users can now rename a workspace by:
1. Clicking the three-dot menu (⋯) on any workspace in the sidebar
2. Selecting "Rename" from the command bar
3. Entering a new name in the dialog
4. Clicking "Rename" to save

* Cleanup script changes for workspace 4eb64331-cc43-43af-849e-3731664e53b9

* Added the missing translations for the rename workspace dialog to all locale files:
- **es** (Spanish)
- **ja** (Japanese)
- **ko** (Korean)
- **zh-Hans** (Simplified Chinese)
- **zh-Hant** (Traditional Chinese)
2026-01-09 10:06:29 +01:00
Louis Knight-Webb
078e7fc372 Done! I've changed block: 'nearest' to block: 'start' in ChangesPanelContainer.tsx:168. (#1869)
**What this fixes:**
- `block: 'nearest'` only scrolled the minimum distance to make the element visible, which often left users "halfway" through a file
- `block: 'start'` aligns the top of the selected diff with the top of the scroll container, ensuring the file header is always visible at the top
2026-01-09 08:44:08 +00:00
Louis Knight-Webb
6a07e5cc16 Fix new sessions to inherit last used variant from previous session (Vibe Kanban) (#1870)
* The implementation is complete. Here's a summary of the changes:

## Summary

Fixed the issue where new sessions were inheriting the last used executor but not the last used variant.

### Changes Made to `vibe-kanban/frontend/src/components/ui-new/containers/SessionChatBoxContainer.tsx`:

1. **Added import** for `useExecutionProcesses` hook

2. **Added `lastSessionId`** - gets the most recent session's ID only when in new session mode:
   ```tsx
   const lastSessionId = isNewSessionMode ? sessions?.[0]?.id : undefined;
   ```

3. **Added `useExecutionProcesses` call** - fetches processes from the last session to get the full executor profile:
   ```tsx
   const { executionProcesses: lastSessionProcesses } =
     useExecutionProcesses(lastSessionId);
   ```

4. **Added `lastSessionProfile` memo** - extracts the full profile (executor + variant) from the last session's processes:
   ```tsx
   const lastSessionProfile = useMemo(() => {
     if (!lastSessionProcesses?.length) return null;
     return getLatestProfileFromProcesses(lastSessionProcesses);
   }, [lastSessionProcesses]);
   ```

5. **Updated `latestProfileId` computation** - now uses `lastSessionProfile` (which includes the variant) before falling back to just the executor with `variant: null`

The type check passes successfully. When a user creates a new session, it will now correctly inherit both the executor AND variant from the most recently used session in that workspace.

* Done! The refactoring is complete. Here's a summary of the changes:

## Summary

Refactored the `latestProfileId` logic in `SessionChatBoxContainer.tsx` to be cleaner:

**Before:** 4 separate declarations
- `lastSessionExecutor` memo
- `lastSessionId`
- `lastSessionProcesses` hook
- `lastSessionProfile` memo
- `latestProfileId` memo (referencing all the above)

**After:** 3 declarations, consolidated
- `lastSessionId`
- `lastSessionProcesses` hook
- `latestProfileId` memo (all logic inlined)

**Changes:**
- Removed 2 intermediate `useMemo` hooks
- Inlined `lastSessionExecutor` and `lastSessionProfile` directly into `latestProfileId`
- Same 3-tier fallback behavior preserved: current processes → last session processes → session metadata
- Type check passes
2026-01-09 08:43:57 +00:00
Anastasiia Solop
7d75a73fc8 Make sidebar sections collapsible in workspaces UI (Vibe Kanban) (#1867)
* Done! Here's a summary of the changes:

## Summary

I made the sections in the right sidebar collapsible by:

1. **Created `CollapsibleSectionHeader` component** (`frontend/src/components/ui-new/primitives/CollapsibleSectionHeader.tsx`):
   - Combines the `SectionHeader` styling (left border accent, border-bottom) with collapsible functionality
   - Supports optional icon with action handler (stops propagation to avoid toggling)
   - Uses persisted expanded state via `usePersistedExpanded` hook
   - Shows caret icon that rotates when collapsed

2. **Added new persist keys** (`frontend/src/stores/useUiPreferencesStore.ts`):
   - `gitPanelRepositories` - for Repositories section
   - `gitPanelProject` - for Project section
   - `gitPanelAddRepositories` - for Add Repositories section
   - `processesSection` - for Processes section

3. **Updated `GitPanel.tsx`**: Replaced `SectionHeader` with `CollapsibleSectionHeader` for the Repositories section, wrapping all repo cards and the Advanced section inside

4. **Updated `GitPanelCreate.tsx`**: Made all three sections collapsible:
   - Project section
   - Repositories section
   - Add Repositories section

5. **Updated `ProcessListContainer.tsx`**: Made the Processes section collapsible while keeping the search bar always visible

All sections now:
- Collapse when clicking on the section header
- Expand when clicking again
- Persist their expanded/collapsed state across sessions

* Done! I've made the Changes and Dev Server sections collapsible as well:

**Updated files:**
- `frontend/src/stores/useUiPreferencesStore.ts` - Added `changesSection` and `devServerSection` persist keys
- `frontend/src/components/ui-new/views/FileTree.tsx` - Made the "Changes" section collapsible
- `frontend/src/components/ui-new/views/PreviewControls.tsx` - Made the "Dev Server" section collapsible

All sections now use the `CollapsibleSectionHeader` component and persist their collapsed/expanded state.

* Cleanup script changes for workspace 05769879-a23f-49ac-81f4-b17e18f14025
2026-01-09 09:22:17 +01:00
Anastasiia Solop
3d46edc579 fix hash render in diff file names in the workspaces UI (#1864) 2026-01-09 07:49:23 +01:00
Louis Knight-Webb
527febdc52 Workspaces FE (#1733) 2026-01-08 22:14:38 +00:00
GitHub Action
fe2215ba85 chore: bump version to 0.0.146 2026-01-08 19:40:01 +00:00
Gabriel Gordon-Hall
d1c8ad9ea0 disable version bump (#1857) 2026-01-08 19:38:26 +00:00
GitHub Action
ae852b297f chore: bump version to 0.0.145 2026-01-08 18:46:22 +00:00
Solomon
312ace8708 ignore sqlx version mismatch (#1853)
* Fix migration checksum mismatch

* only fix on windows
2026-01-08 18:44:21 +00:00
Alex Netsch
67711e77f4 Show error when remote branch status is unavailable (Vibe Kanban) (#1825)
* I've completed the implementation. Here's a summary of the changes:

## Summary

### Changes Made

1. **`frontend/src/hooks/useBranchStatus.ts`**
   - Modified to return `{ data, error, isError, isLoading, refetch }` instead of just the query result
   - This exposes the error state to consuming components

2. **`frontend/src/components/tasks/Toolbar/GitOperations.tsx`**
   - Added `branchStatusError` prop to interface
   - Removed `hasConflictsCalculated` from the "Change target branch" button's disabled condition - now it stays enabled even during errors, allowing users to recover
   - Changed the actions section from hiding completely when `selectedRepoStatus` is null to showing an error message when there's a `branchStatusError`

3. **`frontend/src/components/dialogs/tasks/GitActionsDialog.tsx`**
   - Extracted `error` from `useBranchStatus` and passes it to `GitOperations` as `branchStatusError`

4. **`frontend/src/pages/ProjectTasks.tsx`**
   - Updated `DiffsPanelContainer` to accept and pass `branchStatusError`
   - Extracted `branchStatusError` from `useBranchStatus` hook
   - Passes the error through to `DiffsPanelContainer`

5. **i18n translation files** (all 6 locales: en, es, ja, ko, zh-Hans, zh-Hant)
   - Added `git.errors.branchStatusUnavailable` translation string

### Behavior Changes

- **Before**: When branch status API failed, git operations (Merge, PR/Push, Rebase buttons) were completely hidden
- **After**:
  - An error message is shown: "Unable to fetch branch status. You can still change the target branch."
  - The "Change target branch" button remains enabled, allowing users to recover from deadlock situations
  - Users can see something went wrong instead of the UI silently failing

* Cleanup script changes for workspace cdcbb9c6-fc9f-45bf-9c30-0e432d06cccf

* Simplify useBranchStatus hook return

Return useQuery result directly instead of manually constructing an object.
The useQuery hook already returns all needed properties (data, error, isError, isLoading, refetch).

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Restore hasConflictsCalculated check for change target branch button

The conflict check wasn't needed for the branch status error fix.
Keeping it prevents changing target branch during active git conflicts.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 13:42:15 +00:00
Alex Netsch
b63c90186e feat: Show timeout indicator for repository selector (Vibe Kanban) (#1510)
* Done. I've added a 5-second delay to the `list_git_repos` endpoint at `crates/server/src/routes/filesystem.rs:46`. This will let you see:

- "Searching for repositories..." for the first 2 seconds
- "Still searching... (2s)", "Still searching... (3s)", etc. after that
- The "This is taking longer than usual" message after 3 seconds

Remember to remove this delay (marked with `TODO`) once you're done testing!

* Done, the delay has been removed.

* All checks pass. The i18n script now passes with no new violations introduced.

* feat: Add timeout indicator to repository selector

- Shows progressive feedback when repo search takes longer than expected
- Displays "no repos found" message when search completes empty
- Added translations for all 6 locales (EN, ES, JA, KO, ZH-Hans, ZH-Hant)

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-08 13:29:31 +00:00
Solomon
0753a4ff94 Reset the diff view on target-branch change and post rebase (#1800)
* Reset the diff view on target-branch change and post rebase

* Remove unbounded channel

tokio watch is sufficient for watching git head changes in case of rebase.

* fmt

* use git service
2026-01-08 12:58:07 +00:00
Gabriel Gordon-Hall
2f496086ea non-blocking orphan worktree cleanup (#1807) 2026-01-08 12:19:03 +00:00
lif
dcaa8b8769 fix: copy images to agent_working_dir when set (#1752)
* fix: copy images to agent_working_dir when set

When agent_working_dir is configured, copy images to
<workspace>/<agent_working_dir>/.vibe-images/ instead of
<workspace>/.vibe-images/ so that relative paths work
correctly for the AI agent.

Closes #1727

Signed-off-by: majiayu000 <1835304752@qq.com>

* optionally append agent working directory in other image routes

---------

Signed-off-by: majiayu000 <1835304752@qq.com>
Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2026-01-08 12:14:02 +00:00
Solomon
cefb4fb0a2 upgrade copilot cli (#1844) 2026-01-08 11:53:56 +00:00
Solomon
3749be636a WIP: use Opencode sdk (#1823)
Opencode ACP server is broken on windows. Using the Opencode HTTP SDK directly, works better.
2026-01-08 11:29:44 +00:00
Levi Bostian
bf227366b9 create a troubleshoot section to the docs website (#1805)
* add some helpful information to the troubleshooting section of the documentation website

I was having an issue with vibe-kanban recently and I had to do a lot of digging myself in order to debug the issue. It would be helpful to have a troubleshooting section of the website that lists some basic tips for how to fix issues on your own.

* make warning stronger

---------

Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2026-01-08 09:39:58 +00:00
Gabriel Gordon-Hall
76feaefdfe feat: add Exa and Chrome DevTools as one-click MCP server options (Vibe Kanban) (#1801)
* I've added the Exa Code MCP server as a one-click install option. Here's what was configured:

**Changes made to `crates/executors/default_mcp.json`:**

1. **Server configuration** (lines 23-33):
   - Command: `npx -y exa-mcp-server`
   - Tools enabled: `web_search_exa` and `get_code_context_exa` (as requested)
   - Environment variable: `EXA_API_KEY` (required for authentication)

2. **Metadata** (lines 53-58):
   - Name: "Exa"
   - Description: "Web search and code context retrieval powered by Exa AI"
   - URL: https://docs.exa.ai/reference/exa-mcp
   - Icon: `mcp/exa_logo.svg` (already exists)

The Exa MCP server icon was already present in the frontend public assets at `frontend/public/mcp/exa_logo.svg`.

* Done. I've added Chrome DevTools MCP as a one-click install option:

**Server configuration** (lines 34-39):
- Command: `npx chrome-devtools-mcp@latest`
- No environment variables required

**Metadata** (lines 65-70):
- Name: "Chrome DevTools"
- Description: "Browser automation, debugging and performance analysis with Chrome DevTools"
- URL: https://github.com/ChromeDevTools/chrome-devtools-mcp
- Icon: `mcp/chrome_devtools_logo.svg`

* The issue was that `justify-center` and `gap-3` were interfering with Embla Carousel's scroll calculations. Embla uses a specific margin/padding system (`-ml-4` on the content container and `pl-4` on items) to handle spacing and scroll positions. Adding `justify-center` shifts items in a way that breaks the scroll math, making it impossible to scroll to the leftmost items.

The fix removes these conflicting classes from `CarouselContent`.
2026-01-07 16:30:39 +00:00
Solomon
25c6d0a7c0 Reduce SQLITE db locks (#1806)
Common settings to reduce database locks.

> 1. WAL is significantly faster in most scenarios.
 2. WAL provides more concurrency as readers do not block writers and a writer does not block readers. Reading and writing can proceed concurrently.
 3.Disk I/O operations tends to be more sequential using WAL.
 4. WAL uses many fewer fsync() operations and is thus less vulnerable to problems on systems where the fsync() system call is broken.

https://sqlite.org/wal.html
2026-01-06 18:40:07 +00:00
Solomon
0f3ee560f3 Speedup pre-release CI runs (#1804) 2026-01-06 15:58:10 +00:00
GitHub Action
edef39c3fb chore: bump version to 0.0.144 2026-01-06 13:14:34 +00:00
Solomon
3d3f260e1c bump Opencode to v1.1.3 (#1798)
* bump opencode to v1.1.3

* use correct working workspace directory for normalize_logs

use the same directory that was used during agent runtime to ensure make_relative_path works as expected
2026-01-06 13:13:25 +00:00
luo jiyin
8b8c6e98f5 feat(github): Add --body-file support for gh pr create (#1707)
* feat(github): add --body-file support for gh pr create

Use temp file for PR body when content exceeds 1000 chars or contains
newlines, avoiding shell escaping issues and CLI length limits.

Changes:
- Add PreparedPrCreateArgs struct for testable argument building
- Extract should_use_body_file() helper with BODY_FILE_THRESHOLD const
- Refactor create_pr to use prepare_pr_create_args()
- Add 36 unit tests covering parsers, body-file logic, and arg building

* Done! Here's a summary of what I've done:

I've simplified PR #1707's implementation based on your feedback:

**Changes made on top of PR #1707:**

1. **Always use `--body-file`** - Removed the threshold-based conditional logic (`should_use_body_file`) that decided whether to use `--body` or `--body-file`. Now it always uses `--body-file`, which:
   - Eliminates complexity
   - Fixes shell escaping issues for all bodies (not just long/multiline ones)
   - Avoids command-line length limits universally

2. **Simplified struct** - Changed `_temp_file: Option<NamedTempFile>` to `_body_file: NamedTempFile` since it's no longer optional

3. **Removed all tests** - Deleted all 36 tests since the logic is now trivially simple and better tested through integration

**Final diff from main:**
- `+162 lines` adding: body-file support, PR comment features (from original PR #1707)
- `-7 lines` removing: the old `--body` approach and TODO comment

The branch is ready for review. The existing tests in the `services` crate all pass.

Cleanup script changes for workspace 6534b6a9-68c3-4672-a4e8-aaf6939b6499

Done! Here's what I simplified compared to PR #1707:

**Removed:**
- `PreparedPrCreateArgs` struct
- `prepare_pr_create_args` function
- `should_use_body_file` function with threshold logic
- `BODY_FILE_THRESHOLD` constant
- All 36 tests

**The body-file fix is now just ~10 lines added to `create_pr`:**
```rust
// Write body to temp file to avoid shell escaping and length issues
let body = request.body.as_deref().unwrap_or("");
let mut body_file = NamedTempFile::new()
    .map_err(|e| GhCliError::CommandFailed(format!("Failed to create temp file: {e}")))?;
body_file
    .write_all(body.as_bytes())
    .map_err(|e| GhCliError::CommandFailed(format!("Failed to write body: {e}")))?;

// ... then later:
args.push(OsString::from("--body-file"));
args.push(body_file.path().as_os_str().to_os_string());
```

The PR comment types/methods are kept since other code in the branch depends on them (that's a separate feature from the body-file fix).

Cleanup script changes for workspace 6534b6a9-68c3-4672-a4e8-aaf6939b6499

Done. Removed the comment. The temp file cleanup is handled by Rust's RAII - `NamedTempFile` deletes the file when it goes out of scope at the end of `create_pr`.

---------

Co-authored-by: Alex Netsch <alex@bloop.ai>
2026-01-06 12:37:25 +00:00
Joshua Saunders
17afc0cd03 Add composer-1 as a model for Cursor agent (#1786)
* Add composer-1 as a model for Cursor agent

* fmt

---------

Co-authored-by: Gabriel Gordon-Hall <ggordonhall@gmail.com>
2026-01-06 11:14:52 +00:00
Alex Netsch
0478ce06fc Reset workspace cleanup timer at diff view and IDE open (#1654)
* Add workspace.touch to reset cleanup timer at diff view and ide open

* Touch at ensure_container_exists, rm comments
2026-01-06 11:00:48 +00:00
Gabriel Gordon-Hall
3815936857 chore: bump runners (#1797)
* bump runners

* cache sqlx-cli
2026-01-06 10:55:12 +00:00
Alex Netsch
147c4fd53d Support GitHub Enterprise and SSH aliases via gh CLI (Vibe Kanban) (#1783)
* All changes have been implemented and tested. Here's a summary of what was done:

Updated the PR URL parsing logic to support GitHub Enterprise hostnames by using the `url` crate instead of searching for `"github.com"` as a string token.

1. **`crates/review/Cargo.toml`** - Added `url = "2.5"` dependency

2. **`crates/review/src/github.rs`** - Rewrote `parse_pr_url` function to use `Url::parse()` and `path_segments()` instead of string splitting. Added two new test cases:
   - `test_parse_pr_url_github_enterprise` - Tests GitHub Enterprise URLs
   - `test_parse_pr_url_any_host` - Tests that any host with the `/pull/` pattern works

3. **`crates/remote/src/routes/github_app.rs`** - Applied the same pattern to the duplicate `parse_pr_url` function

The new implementation:
- Parses the URL with `Url::parse()`
- Extracts path segments directly (e.g., `["owner", "repo", "pull", "123"]`)
- No longer requires `github.com` as a specific hostname
- Works with any hostname including `github.mycompany.com`, `github.enterprise.corp`, etc.

Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

All done! Here's a summary of what was implemented:

This PR adds support for GitHub Enterprise hostnames and SSH hostname aliases by delegating to the `gh` CLI instead of parsing URLs with hardcoded `github.com` patterns.

**1. `crates/services/src/services/github/cli.rs`**
- Added `run_in_dir()` helper method to run `gh` commands in a specific directory
- Added `get_repo_info(repo_path)` - uses `gh repo view --json owner,name` to get repo info from a directory
- Added `view_pr_by_url(pr_url)` - uses `gh pr view <url>` to get PR info directly from a URL

**2. `crates/services/src/services/github.rs`**
- Exported `GhCli` and `GhCliError` for use by other modules
- Added `update_pr_status_by_url(pr_url)` method to `GitHubService`
- Replaced regex-based `from_remote_url()` with hostname-agnostic URL parsing using the `url` crate (kept for backward compatibility)

**3. `crates/services/src/services/git.rs`**
- Updated `get_github_repo_info()` to use `GhCli::get_repo_info()` instead of parsing URLs

**4. `crates/services/src/services/pr_monitor.rs`**
- Updated `check_pr_status()` to use `update_pr_status_by_url()` instead of parsing the PR URL

**5. Tests** (`crates/services/tests/git_workflow.rs`)
- Updated existing tests for hostname-agnostic parsing
- Added new tests for GitHub Enterprise and SSH alias URLs

**6. `crates/review/src/github.rs`** (previously done)
- Already updated to use hostname-agnostic URL parsing

**7. `crates/remote/src/routes/github_app.rs`** (previously done)
- Already updated to use hostname-agnostic URL parsing

- **SSH hostname aliases** (e.g., `github-xxx` in `~/.ssh/config`) now work
- **GitHub Enterprise** instances (e.g., `github.mycompany.com`) now work
- **No regex** - removed regex dependency from `github.rs`, using simple URL parsing and `gh` CLI
- **Robust** - `gh` CLI handles all the complexity of authentication and hostname resolution

Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

Done! I've simplified the API by:

1. **Removed** the old `update_pr_status(&repo_info, pr_number)` method that took repo info and PR number separately
2. **Renamed** `update_pr_status_by_url(pr_url)` → `update_pr_status(pr_url)` for a cleaner API

Now there's just one method that takes the PR URL directly, and the `gh` CLI handles all the complexity of hostname resolution, SSH aliases, and GitHub Enterprise automatically.

All tests pass. The fix is complete - I renamed the test from `test_parse_pr_url_any_host` to `test_parse_pr_url_custom_github_host` and changed the URL from a misleading GitLab example to a realistic GitHub Enterprise URL (`github.acme.com`).

Done! I've removed `from_remote_url()` entirely:

1. **Removed** `GitHubRepoInfo::from_remote_url()` method from `crates/services/src/services/github.rs`
2. **Removed** the `use url::Url;` import from that file (since it's no longer needed there)
3. **Removed** both tests that exercised the now-deleted function from `crates/services/tests/git_workflow.rs`
4. **Updated** the import to remove `GitHubRepoInfo` and `GitHubServiceError` which are no longer used in tests

All tests pass and the workspace compiles cleanly. The `url` crate is still used elsewhere in the services crate, so I left it in Cargo.toml.

Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

Done! I've made both cleanups:

1. **Consolidated `run()` and `run_in_dir()`** - Now there's a single `run()` method with an optional `dir: Option<&Path>` parameter. All callers pass `None` for global commands and `Some(path)` when running in a specific directory.

2. **Renamed `view_pr_by_url()` to `view_pr()`** - Removed the old `view_pr(owner, repo, pr_number)` method and renamed `view_pr_by_url(pr_url)` to just `view_pr(pr_url)` for a cleaner API.

All tests pass and the workspace compiles cleanly.

Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

Done! I've reverted the test change in `crates/review/src/github.rs` back to the original `test_parse_pr_url_any_host` with the GitLab URL. The `crates/remote/src/routes/github_app.rs` file had no changes from my work to revert.

All tests pass and the workspace compiles. The changes in this PR are now scoped to just the `services` crate:
- `cli.rs` - consolidated `run()`, renamed `view_pr()`
- `github.rs` - removed `from_remote_url()` and `url` import
- `git.rs` - uses `GhCli::get_repo_info()`
- `git_workflow.rs` - removed tests for `from_remote_url()`

Done. I've reset the review and remote crate files to `origin/main`. The changes to those crates are now reverted and can be submitted in a separate PR. All tests pass and the workspace compiles.

This PR now only contains the services crate changes:
- `cli.rs` - consolidated `run()`, renamed `view_pr()`
- `github.rs` - removed `from_remote_url()` and `url` import
- `git.rs` - uses `GhCli::get_repo_info()`
- `git_workflow.rs` - removed tests for `from_remote_url()`

All done. All three review comments addressed:

1. Removed comment "Optionally runs in a specific directory..." from `cli.rs`
2. Removed doc comment from `update_pr_status` in `github.rs`
3. Replaced helper structs with `serde_json::Value` parsing (matches existing pattern in the file)

Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

Done. Reverted to the helper structs.

All done. Summary of changes:

1. **Removed 3 comments** as requested:
   - `git.rs:1599` - removed "Uses `gh repo view` which handles SSH aliases, GitHub Enterprise, etc."
   - `cli.rs:202` - removed "This handles GitHub Enterprise and custom hostnames automatically via the `gh` CLI."
   - `pr_monitor.rs:101` - removed "Use the URL directly - gh CLI handles all hostname/SSH alias complexity"

2. **Clone question in `github.rs:210`** - Added a comment explaining why the clone is needed (spawn_blocking requires owned values, each retry needs fresh copies)

3. **Fixed `--head {owner}:{branch}` bug** - Changed to `--head branch` only, since the `{owner}:{branch}` syntax is not supported per gh docs

4. **Added 2 unit tests** for `get_repo_info()` JSON parsing:
   - `test_parse_repo_info_valid` - tests successful parsing
   - `test_parse_repo_info_invalid` - tests error handling

* Done. Addressed the review comment by:

1. Removed `GitService.get_github_repo_info()` facade from `git.rs`
2. Updated 3 callers in `pr.rs` to use `GhCli::new().get_repo_info()` directly
3. Added `GhCliError` to `ApiError` in `error.rs` for proper error handling
4. Removed unused import in `git.rs`

* Done. Now the architecture is cleaner:

- `GhCli` is an internal implementation detail of `GitHubService`
- Callers use `GitHubService.get_repo_info(&path)` instead of touching `GhCli` directly
- Later, a `GitLabService` could have the same `get_repo_info` interface
- Removed `GhCliError` from `ApiError` since errors are now converted to `GitHubServiceError`

* Done.

* Done. `get_repo_info` is now async with `spawn_blocking`, matching the pattern used by other methods like `check_token`.

* Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338

* Done. `GhCli` and `GhCliError` are now private to the `github` module.

* Cleanup script changes for workspace e22082a4-ca31-4754-9c1c-2dc5b6991338
2026-01-06 10:43:13 +00:00
Gabriel Gordon-Hall
cbfb637b73 fix i18n errors (#1796) 2026-01-06 10:24:33 +00:00
Alex Huang
875b1068a0 feat(i18n): add zh-Hant UI translations and locale mapping (#1777)
* feat(i18n): add zh-Hant UI translations and locale mapping

* chore(i18n): format config

* fix(i18n): add zh-Hant config enum

* chore(types): regenerate
2026-01-05 20:43:31 +00:00
Gabriel Gordon-Hall
2cd4c1b181 Bump Claude Code, Codex, and Gemini CLI versions (Vibe Kanban) (#1778)
* Done! I've updated the Claude Code version from `2.0.75` to `2.0.76` in `mission-control/crates/executors/src/executors/claude.rs:46`.

* Updated Gemini CLI from version 0.21.1 to 0.22.5 in `mission-control/crates/executors/src/executors/gemini.rs:39`.

* Updated Codex from version 0.75.0 to 0.77.0 in `mission-control/crates/executors/src/executors/codex.rs:213`.
2026-01-05 20:41:13 +00:00
Justin Gray
84efb885fb Update opencode-ai version to 1.0.223 (#1739)
Co-authored-by: Warp <agent@warp.dev>
2026-01-05 19:07:03 +00:00
Gabriel Gordon-Hall
7224376170 feat: override auto-detected preview url (#1573)
* override auto-detected preview url

* i18n

* remove redundant useMemo
2026-01-05 18:56:04 +00:00
Gabriel Gordon-Hall
48d2ce1b80 Update docs to remove assertion that worktrees are cleaned up on merge 2026-01-05 17:38:53 +00:00
Alex Netsch
c0dadac9bd Build succeeded with git2 v0.19.0. The fix is complete. (#1774)
**Summary:**
- Bumped `git2` from `0.18` to `0.19` in 4 Cargo.toml files
- This brings in libgit2 1.8.1 which supports `index.skipHash`
- Build compiles successfully
2026-01-05 16:31:31 +00:00
GitHub Action
f99d2f06f2 chore: bump version to 0.0.143 2025-12-29 18:01:52 +00:00
Louis Knight-Webb
9a83d09ffd Fix local build for macOS e2e testing (Vibe Kanban) (#1679)
* Done! Here's a summary of the changes:

## Changes Made

### `npx-cli/bin/download.js`
- Added `LOCAL_DEV_MODE` detection - automatically enabled when R2 placeholders aren't replaced or `VIBE_KANBAN_LOCAL=1` env var is set
- Modified `ensureBinary()` to use local binaries from `npx-cli/dist/{platform}/` in local dev mode
- Exported `LOCAL_DEV_MODE` and `LOCAL_DIST_DIR` for use by `cli.js`

### `npx-cli/bin/cli.js`
- In local dev mode, extracts binaries directly to `npx-cli/dist/{platform}/` instead of global cache
- Skips version update check in local dev mode
- Shows "(local dev)" label in startup message when running locally

### `local-build.sh`
- Added instructions at the end showing how to run the local build

## How to test
```bash
cd vibe-kanban
./local-build.sh
cd npx-cli && node bin/cli.js
```

* Updated the README to reflect the correct local build instructions.

* Fixed. Now `LOCAL_DEV_MODE` only activates when the `dist/` directory actually exists, which means:

1. **Local dev** (after `./local-build.sh` creates `npx-cli/dist/`): local mode works
2. **npx** (npm cache has no `dist/` folder): normal R2 download works

* Done! The fixes are:

1. **`npx-cli/package.json`**: Added `dist` to the `files` array so local binaries get included in the tarball
2. **`npx-cli/bin/cli.js`**: Added a guard to skip `getLatestVersion()` when R2 URL is a placeholder (starts with `__`)

Now the workflow should work:
```bash
cd vibe-kanban
./local-build.sh
cd npx-cli
npm pack
npx vibe-kanban-0.0.142.tgz
```
2025-12-29 18:00:23 +00:00
gsxdsm
332bfbd965 feat: dynamically determine devserver hostname from browser location instead of hardcoding localhost (#1640)
Co-authored-by: Vibe Kanban <noreply@vibekanban.com>
2025-12-28 12:59:51 +00:00