feat: add auto-create worktree setting and related UI components

This commit is contained in:
Bohdan Triapitsyn
2026-01-07 23:37:32 +02:00
parent b6646b6b3e
commit c7700d5384
11 changed files with 144 additions and 14 deletions
+1
View File
@@ -55,6 +55,7 @@ export type DesktopSettings = {
autoDeleteAfterDays?: number;
defaultModel?: string; // format: "provider/model"
defaultAgent?: string;
autoCreateWorktree?: boolean;
queueModeEnabled?: boolean;
// User-added skills catalogs (persisted to ~/.config/openchamber/settings.json)
+3
View File
@@ -255,6 +255,9 @@ const sanitizeWebSettings = (payload: unknown): DesktopSettings | null => {
if (typeof candidate.defaultAgent === 'string' && candidate.defaultAgent.length > 0) {
result.defaultAgent = candidate.defaultAgent;
}
if (typeof candidate.autoCreateWorktree === 'boolean') {
result.autoCreateWorktree = candidate.autoCreateWorktree;
}
if (typeof candidate.queueModeEnabled === 'boolean') {
result.queueModeEnabled = candidate.queueModeEnabled;
}
+48 -1
View File
@@ -8,6 +8,7 @@ import { toast } from 'sonner';
import { useSessionStore } from '@/stores/useSessionStore';
import { useProjectsStore } from '@/stores/useProjectsStore';
import { useConfigStore } from '@/stores/useConfigStore';
import { useContextStore } from '@/stores/contextStore';
import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { checkIsGitRepository } from '@/lib/gitApi';
import { generateUniqueBranchName } from '@/lib/git/branchNameGenerator';
@@ -116,11 +117,57 @@ export async function createWorktreeSession(): Promise<{ id: string } | null> {
}
// Initialize the session
const agents = useConfigStore.getState().agents;
const configState = useConfigStore.getState();
const agents = configState.agents;
sessionStore.initializeNewOpenChamberSession(session.id, agents);
sessionStore.setSessionDirectory(session.id, metadata.path);
sessionStore.setWorktreeMetadata(session.id, createdMetadata);
// Apply default agent and model settings
try {
const visibleAgents = configState.getVisibleAgents();
let agentName: string | undefined;
// Priority: settingsDefaultAgent → build → first visible
if (configState.settingsDefaultAgent) {
const settingsAgent = visibleAgents.find((a) => a.name === configState.settingsDefaultAgent);
if (settingsAgent) {
agentName = settingsAgent.name;
}
}
if (!agentName) {
agentName =
visibleAgents.find((agent) => agent.name === 'build')?.name ||
visibleAgents[0]?.name;
}
if (agentName) {
// 1. Update global UI state
configState.setAgent(agentName);
// 2. Persist to session context so it sticks after reload/switch
useContextStore.getState().saveSessionAgentSelection(session.id, agentName);
// 3. Handle default model for the agent if set in global settings
const settingsDefaultModel = configState.settingsDefaultModel;
if (settingsDefaultModel) {
const parts = settingsDefaultModel.split('/');
if (parts.length === 2) {
const [providerId, modelId] = parts;
// Validate model exists (optional, but good practice)
const modelMetadata = configState.getModelMetadata(providerId, modelId);
if (modelMetadata) {
useContextStore.getState().saveSessionModelSelection(session.id, providerId, modelId);
// Also save the specific agent's model preference for this session
useContextStore.getState().saveAgentModelForSession(session.id, agentName, providerId, modelId);
}
}
}
}
} catch {
// Ignore errors setting default agent
}
// Update directory
useDirectoryStore.getState().setDirectory(metadata.path, { showOverlay: false });