Enhance session sidebar with PR worktree support (#342)

* feat: refactored sessions sidebar to be workspaces centric

- Add createWorktreeOnly helper and status checks
- Add createWorktreeOnly to create a standalone worktree for the active project
- Show error toasts when no active project or not a Git repository
- Refresh session list and show success toast with created worktree details

* feat: show attention indicator and status marker in SessionSidebar

- Show unread attention indicator for sessions with pending updates
- Display status marker combining streaming and unread indicators in the session row
- Introduce attention diamond pulse animation and associated CSS for the new indicator

* fix(SessionSidebar): reserve header actions space when repo state is known

* chore(doc): add PR status colors to custom themes
This commit is contained in:
Bohdan Triapitsyn
2026-02-07 03:57:46 +02:00
committed by GitHub
parent d5a2e49ae8
commit 7d99aea6cc
46 changed files with 1711 additions and 288 deletions
@@ -229,6 +229,70 @@ export function isCreatingWorktree(): boolean {
return isCreatingWorktreeSession;
}
export async function createWorktreeOnly(): Promise<string | null> {
if (isCreatingWorktreeSession) {
return null;
}
const activeProject = useProjectsStore.getState().getActiveProject();
if (!activeProject?.path) {
toast.error('No active project', {
description: 'Please select a project first.',
});
return null;
}
const projectDirectory = activeProject.path;
let isGitRepo = false;
try {
isGitRepo = await checkIsGitRepository(projectDirectory);
} catch {
// ignored
}
if (!isGitRepo) {
toast.error('Not a Git repository', {
description: 'Worktrees can only be created in Git repositories.',
});
return null;
}
isCreatingWorktreeSession = true;
startConfigUpdate('Creating new worktree...');
try {
const projectRef: ProjectRef = { id: activeProject.id, path: projectDirectory };
const preferredName = generateBranchName();
const setupCommands = await getWorktreeSetupCommands(projectRef);
const metadata = await createSdkWorktree(projectRef, {
preferredName,
setupCommands,
});
const rootBranch = await getRootBranch(projectRef.path).catch(() => undefined);
const status = await getWorktreeStatus(metadata.path).catch(() => undefined);
const branchLabel = metadata.branch || metadata.label || metadata.name;
toast.success('Worktree created', {
description: branchLabel
? `${branchLabel}${rootBranch ? ` from ${rootBranch}` : ''}`
: status?.isDirty ? 'Created (dirty)' : 'Ready',
});
await useSessionStore.getState().loadSessions();
return metadata.path;
} catch (error) {
const message = error instanceof Error ? error.message : 'Failed to create worktree';
toast.error('Failed to create worktree', {
description: message,
});
return null;
} finally {
finishConfigUpdate();
isCreatingWorktreeSession = false;
}
}
/**
* Create a new session with a worktree for a specific branch.
* Unlike createWorktreeSession(), this allows specifying the project and branch explicitly.