feat: add new session button and integrate worktree session creation logic

This commit is contained in:
Bohdan Triapitsyn
2026-01-08 01:48:42 +02:00
parent 8902662f74
commit cc09f802ce
2 changed files with 33 additions and 31 deletions
+12 -6
View File
@@ -4,12 +4,18 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
- Multi Run / Agent Manager: Select the Agent you want to run for the Worktree sessions (thanks to @wienans).
- Agent Manager now submits the prompt if valid, similar to the Chat interfaces.
- Added worktree management actions in Agent Manager: delete the group or individual worktrees or keep only selected one (thanks to @wienans).
- Fixed IME (Input Method Editor) composition handling for CJK input methods, preventing accidental message send during character conversion (thanks to @madebyjun).
- Added project management with multi-project support and per-project settings for agents/commands/skills.
- Enhanced SSE event stream with heartbeat management, permission bootstrap on connect, and improved reconnection logic.
- Agent Manager / Multi Run: select agent per worktree session (thanks to @wienans).
- Agent Manager / Multi Run: worktree actions to delete group or individual worktrees, or keep only selected one (thanks to @wienans).
- Agent Manager: added "Copy Worktree Path" action in the more menu (thanks to @wienans).
- Worktrees: added session creation flow with loading screen, auto-create worktree setting, and setup commands management.
- Session sidebar: refactoring with unified view for sessions in worktrees.
- Settings: added ability to create new session in worktree by default
- Git view: added branch rename for worktree.
- Chat: fixed IME composition for CJK input to prevent accidental send (thanks to @madebyjun).
- Projects: added multi-project support with per-project settings for agents/commands/skills.
- Event stream: improved SSE with heartbeat management, permission bootstrap on connect, and reconnection logic.
- Tunnel: added QR code and password URL for Cloudflare tunnel (thanks to @martindonadieu).
- Model selector: fixed dropdowns not responding to viewport size.
## [1.4.3] - 2026-01-04
@@ -36,6 +36,7 @@ import {
RiDeleteBinLine,
RiErrorWarningLine,
RiFileCopyLine,
RiFolderAddLine,
RiGitBranchLine,
RiLinkUnlinkM,
RiMore2Line,
@@ -50,10 +51,12 @@ import { useSessionStore } from '@/stores/useSessionStore';
import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { useProjectsStore } from '@/stores/useProjectsStore';
import { useUIStore } from '@/stores/useUIStore';
import { useConfigStore } from '@/stores/useConfigStore';
import type { WorktreeMetadata } from '@/types/worktree';
import { opencodeClient } from '@/lib/opencode/client';
import { checkIsGitRepository } from '@/lib/gitApi';
import { getSafeStorage } from '@/stores/utils/safeStorage';
import { createWorktreeSession } from '@/lib/worktreeSessionCreator';
const PROJECT_COLLAPSE_STORAGE_KEY = 'oc.sessions.projectCollapse';
const SESSION_EXPANDED_STORAGE_KEY = 'oc.sessions.expandedParents';
@@ -232,10 +235,6 @@ const SortableProjectItem: React.FC<SortableProjectItemProps> = ({
</button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="min-w-[180px]">
<DropdownMenuItem onClick={onNewSession}>
<RiAddLine className="mr-1.5 h-4 w-4" />
New Session
</DropdownMenuItem>
{isRepo && !hideDirectoryControls && (
<DropdownMenuItem onClick={onOpenMultiRunLauncher}>
<ArrowsMerge className="mr-1.5 h-4 w-4" />
@@ -252,18 +251,17 @@ const SortableProjectItem: React.FC<SortableProjectItemProps> = ({
</DropdownMenuContent>
</DropdownMenu>
{/* Collapse arrow */}
{/* New session button */}
<button
type="button"
onClick={onToggle}
className="inline-flex h-6 w-6 items-center justify-center text-muted-foreground hover:text-foreground flex-shrink-0"
aria-label={isCollapsed ? 'Expand project' : 'Collapse project'}
onClick={(e) => {
e.stopPropagation();
onNewSession();
}}
className="inline-flex h-6 w-6 items-center justify-center text-muted-foreground hover:text-foreground flex-shrink-0 rounded-md focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary/50"
aria-label="New session"
>
{isCollapsed ? (
<RiArrowRightSLine className="h-4 w-4" />
) : (
<RiArrowDownSLine className="h-4 w-4" />
)}
<RiAddLine className="h-4 w-4" />
</button>
</div>
</div>
@@ -278,13 +276,11 @@ const SortableProjectItem: React.FC<SortableProjectItemProps> = ({
interface ProjectDragOverlayProps {
projectLabel: string;
isActiveProject: boolean;
isCollapsed: boolean;
}
const ProjectDragOverlay: React.FC<ProjectDragOverlayProps> = ({
projectLabel,
isActiveProject,
isCollapsed,
}) => {
return (
<div
@@ -299,11 +295,7 @@ const ProjectDragOverlay: React.FC<ProjectDragOverlayProps> = ({
{projectLabel}
</span>
<span className="inline-flex h-6 w-6 items-center justify-center text-muted-foreground ml-auto">
{isCollapsed ? (
<RiArrowRightSLine className="h-4 w-4" />
) : (
<RiArrowDownSLine className="h-4 w-4" />
)}
<RiAddLine className="h-4 w-4" />
</span>
</div>
</div>
@@ -361,6 +353,8 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
const setSessionSwitcherOpen = useUIStore((state) => state.setSessionSwitcherOpen);
const openMultiRunLauncher = useUIStore((state) => state.openMultiRunLauncher);
const settingsAutoCreateWorktree = useConfigStore((state) => state.settingsAutoCreateWorktree);
const sessions = useSessionStore((state) => state.sessions);
const sessionsByDirectory = useSessionStore((state) => state.sessionsByDirectory);
const currentSessionId = useSessionStore((state) => state.currentSessionId);
@@ -1420,9 +1414,8 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
|| project.normalizedPath
),
isActive: project.id === activeProjectId,
isCollapsed: collapsedProjects.has(project.id),
};
}, [activeDragId, projectSections, homeDirectory, activeProjectId, collapsedProjects]);
}, [activeDragId, projectSections, homeDirectory, activeProjectId]);
return (
<div
@@ -1450,7 +1443,7 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
aria-label="Add project"
title="Add project"
>
<RiAddLine className="h-5 w-5" />
<RiFolderAddLine className="h-4.5 w-4.5" />
</button>
</div>
</div>
@@ -1538,7 +1531,11 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
if (mobileVariant) {
setSessionSwitcherOpen(false);
}
openNewSessionDraft({ directoryOverride: project.normalizedPath });
if (settingsAutoCreateWorktree && isRepo) {
createWorktreeSession();
} else {
openNewSessionDraft({ directoryOverride: project.normalizedPath });
}
}}
onOpenMultiRunLauncher={() => {
if (projectKey !== activeProjectId) {
@@ -1567,7 +1564,6 @@ export const SessionSidebar: React.FC<SessionSidebarProps> = ({
<ProjectDragOverlay
projectLabel={activeDragProject.label}
isActiveProject={activeDragProject.isActive}
isCollapsed={activeDragProject.isCollapsed}
/>
) : null}
</DragOverlay>