Feature: worktree view customization and stability fixes (#805)

* Changes from feature/worktree-view-customization

* Feature: Git sync, set-tracking, and push divergence handling (#796)

* Add quick-add feature with improved workflows (#802)

* Changes from feature/quick-add

* feat: Clarify system prompt and improve error handling across services. Address PR Feedback

* feat: Improve PR description parsing and refactor event handling

* feat: Add context options to pipeline orchestrator initialization

* fix: Deduplicate React and handle CJS interop for use-sync-external-store

Resolve "Cannot read properties of null (reading 'useState')" errors by
deduplicating React/react-dom and ensuring use-sync-external-store is
bundled together with React to prevent CJS packages from resolving to
different React instances.

* Changes from feature/worktree-view-customization

* refactor: Remove unused worktree swap and highlight props

* refactor: Consolidate feature completion logic and improve thinking level defaults

* feat: Increase max turn limit to 10000

- Update DEFAULT_MAX_TURNS from 1000 to 10000 in settings-helpers.ts and agent-executor.ts
- Update MAX_ALLOWED_TURNS from 2000 to 10000 in settings-helpers.ts
- Update UI clamping logic from 2000 to 10000 in app-store.ts
- Update fallback values from 1000 to 10000 in use-settings-sync.ts
- Update default value from 1000 to 10000 in DEFAULT_GLOBAL_SETTINGS
- Update documentation to reflect new range: 1-10000

Allows agents to perform up to 10000 turns for complex feature execution.

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

* feat: Add model resolution, improve session handling, and enhance UI stability

* refactor: Remove unused sync and tracking branch props from worktree components

* feat: Add PR number update functionality to worktrees. Address pr feedback

* feat: Optimize Gemini CLI startup and add tool result tracking

* refactor: Improve error handling and simplify worktree task cleanup

---------

Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
gsxdsm
2026-02-23 20:31:25 -08:00
committed by GitHub
parent e7504b247f
commit 0330c70261
72 changed files with 3667 additions and 1173 deletions

View File

@@ -1,8 +1,9 @@
import { useState, useEffect, useCallback } from 'react';
import { useState, useEffect, useCallback, useRef } from 'react';
import { Label } from '@/components/ui/label';
import { Checkbox } from '@/components/ui/checkbox';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Slider } from '@/components/ui/slider';
import { ShellSyntaxEditor } from '@/components/ui/shell-syntax-editor';
import {
GitBranch,
@@ -15,6 +16,8 @@ import {
Copy,
Plus,
FolderOpen,
LayoutGrid,
Pin,
} from 'lucide-react';
import { Spinner } from '@/components/ui/spinner';
import { cn } from '@/lib/utils';
@@ -64,6 +67,10 @@ export function WorktreePreferencesSection({ project }: WorktreePreferencesSecti
const copyFiles = copyFilesFromStore ?? EMPTY_FILES;
const setWorktreeCopyFiles = useAppStore((s) => s.setWorktreeCopyFiles);
// Worktree display settings
const pinnedWorktreesCount = useAppStore((s) => s.getPinnedWorktreesCount(project.path));
const setPinnedWorktreesCount = useAppStore((s) => s.setPinnedWorktreesCount);
// Get effective worktrees setting (project override or global fallback)
const effectiveUseWorktrees = projectUseWorktrees ?? globalUseWorktrees;
@@ -78,6 +85,9 @@ export function WorktreePreferencesSection({ project }: WorktreePreferencesSecti
const [newCopyFilePath, setNewCopyFilePath] = useState('');
const [fileSelectorOpen, setFileSelectorOpen] = useState(false);
// Ref for storing previous slider value for rollback on error
const sliderPrevRef = useRef<number | null>(null);
// Check if there are unsaved changes
const hasChanges = scriptContent !== originalContent;
@@ -115,6 +125,9 @@ export function WorktreePreferencesSection({ project }: WorktreePreferencesSecti
if (response.settings.worktreeCopyFiles !== undefined) {
setWorktreeCopyFiles(currentPath, response.settings.worktreeCopyFiles);
}
if (response.settings.pinnedWorktreesCount !== undefined) {
setPinnedWorktreesCount(currentPath, response.settings.pinnedWorktreesCount);
}
}
} catch (error) {
if (!isCancelled) {
@@ -135,6 +148,7 @@ export function WorktreePreferencesSection({ project }: WorktreePreferencesSecti
setDefaultDeleteBranch,
setAutoDismissInitScriptIndicator,
setWorktreeCopyFiles,
setPinnedWorktreesCount,
]);
// Load init script content when project changes
@@ -507,6 +521,78 @@ export function WorktreePreferencesSection({ project }: WorktreePreferencesSecti
{/* Separator */}
<div className="border-t border-border/30" />
{/* Worktree Display Settings */}
<div className="space-y-4">
<div className="flex items-center gap-2">
<LayoutGrid className="w-4 h-4 text-brand-500" />
<Label className="text-foreground font-medium">Display Settings</Label>
</div>
<p className="text-xs text-muted-foreground/80 leading-relaxed">
Control how worktrees are presented in the panel. Pinned worktrees appear as tabs, and
remaining worktrees are available in a combined overflow dropdown.
</p>
{/* Pinned Worktrees Count */}
<div className="group flex items-start space-x-3 p-3 rounded-xl hover:bg-accent/30 transition-colors duration-200 -mx-3">
<div className="mt-0.5">
<Pin className="w-4 h-4 text-brand-500" />
</div>
<div className="space-y-2 flex-1">
<div className="flex items-center justify-between">
<Label
htmlFor="pinned-worktrees-count"
className="text-foreground cursor-pointer font-medium"
>
Pinned Worktree Tabs
</Label>
<span className="text-sm font-medium text-foreground tabular-nums">
{pinnedWorktreesCount}
</span>
</div>
<p className="text-xs text-muted-foreground/80 leading-relaxed">
Number of worktree tabs to pin (excluding the main worktree, which is always shown).
</p>
<Slider
id="pinned-worktrees-count"
min={0}
max={25}
step={1}
value={[pinnedWorktreesCount]}
onValueChange={(value) => {
// Capture previous value before mutation for potential rollback
const prevCount = pinnedWorktreesCount;
// Update local state immediately for visual feedback
const newValue = value[0] ?? pinnedWorktreesCount;
setPinnedWorktreesCount(project.path, newValue);
// Store prev for onValueCommit rollback
sliderPrevRef.current = prevCount;
}}
onValueCommit={async (value) => {
const newValue = value[0] ?? pinnedWorktreesCount;
const prev = sliderPrevRef.current ?? pinnedWorktreesCount;
// Persist to server
try {
const httpClient = getHttpApiClient();
await httpClient.settings.updateProject(project.path, {
pinnedWorktreesCount: newValue,
});
} catch (error) {
console.error('Failed to persist pinnedWorktreesCount:', error);
toast.error('Failed to save pinned worktrees setting');
// Rollback optimistic update using captured previous value
setPinnedWorktreesCount(project.path, prev);
}
}}
className="w-full"
/>
</div>
</div>
</div>
{/* Separator */}
<div className="border-t border-border/30" />
{/* Copy Files Section */}
<div className="space-y-3">
<div className="flex items-center gap-2">