@atercates/claude-deck 0.2.4 → 0.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/app/api/sessions/[id]/fork/route.ts +0 -1
- package/app/api/sessions/[id]/route.ts +0 -5
- package/app/api/sessions/[id]/summarize/route.ts +2 -3
- package/app/api/sessions/route.ts +2 -11
- package/app/page.tsx +4 -45
- package/components/ClaudeProjects/ClaudeProjectCard.tsx +19 -31
- package/components/ClaudeProjects/ClaudeSessionCard.tsx +20 -31
- package/components/NewSessionDialog/AdvancedSettings.tsx +3 -12
- package/components/NewSessionDialog/NewSessionDialog.types.ts +0 -10
- package/components/NewSessionDialog/ProjectSelector.tsx +2 -7
- package/components/NewSessionDialog/hooks/useNewSessionForm.ts +3 -36
- package/components/NewSessionDialog/index.tsx +0 -7
- package/components/Projects/index.ts +0 -1
- package/components/SessionList/hooks/useSessionListMutations.ts +0 -35
- package/components/views/DesktopView.tsx +1 -6
- package/components/views/MobileView.tsx +6 -1
- package/components/views/types.ts +1 -1
- package/data/sessions/index.ts +0 -1
- package/data/sessions/queries.ts +1 -27
- package/hooks/useSessions.ts +0 -12
- package/lib/db/queries.ts +4 -64
- package/lib/db/types.ts +0 -8
- package/lib/orchestration.ts +10 -15
- package/lib/providers/registry.ts +2 -56
- package/lib/providers.ts +19 -100
- package/lib/status-monitor.ts +40 -15
- package/package.json +1 -1
- package/server.ts +1 -1
- package/app/api/groups/[...path]/route.ts +0 -136
- package/app/api/groups/route.ts +0 -93
- package/components/NewSessionDialog/AgentSelector.tsx +0 -37
- package/components/Projects/ProjectCard.tsx +0 -276
- package/components/TmuxSessions.tsx +0 -132
- package/data/groups/index.ts +0 -1
- package/data/groups/mutations.ts +0 -95
- package/hooks/useGroups.ts +0 -37
- package/hooks/useKeybarVisibility.ts +0 -42
- package/lib/claude/process-manager.ts +0 -278
|
@@ -121,11 +121,6 @@ export async function PATCH(request: NextRequest, { params }: RouteParams) {
|
|
|
121
121
|
updates.push(`system_prompt = ?`);
|
|
122
122
|
values.push(body.systemPrompt);
|
|
123
123
|
}
|
|
124
|
-
if (body.groupPath !== undefined) {
|
|
125
|
-
updates.push(`group_path = ?`);
|
|
126
|
-
values.push(body.groupPath);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
124
|
if (updates.length > 0) {
|
|
130
125
|
updates.push("updated_at = datetime('now')");
|
|
131
126
|
values.push(id);
|
|
@@ -264,8 +264,8 @@ export async function POST(
|
|
|
264
264
|
// Create new session in DB (using cwd already fetched above)
|
|
265
265
|
getDb()
|
|
266
266
|
.prepare(
|
|
267
|
-
`INSERT INTO sessions (id, name, tmux_name, working_directory, parent_session_id, model, initial_prompt,
|
|
268
|
-
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?,
|
|
267
|
+
`INSERT INTO sessions (id, name, tmux_name, working_directory, parent_session_id, model, initial_prompt, agent_type, auto_approve, project_id)
|
|
268
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`
|
|
269
269
|
)
|
|
270
270
|
.run(
|
|
271
271
|
newId,
|
|
@@ -275,7 +275,6 @@ export async function POST(
|
|
|
275
275
|
null,
|
|
276
276
|
session.model,
|
|
277
277
|
`Continue from previous session. Here's a summary of the work so far:\n\n${summary}`,
|
|
278
|
-
session.group_path,
|
|
279
278
|
agentType,
|
|
280
279
|
session.auto_approve ? 1 : 0,
|
|
281
280
|
session.project_id || "uncategorized"
|
|
@@ -8,19 +8,12 @@ import { findAvailablePort } from "@/lib/ports";
|
|
|
8
8
|
import { runInBackground } from "@/lib/async-operations";
|
|
9
9
|
import { getProject } from "@/lib/projects";
|
|
10
10
|
|
|
11
|
-
// GET /api/sessions - List all sessions
|
|
11
|
+
// GET /api/sessions - List all sessions
|
|
12
12
|
export async function GET() {
|
|
13
13
|
try {
|
|
14
14
|
const sessions = await queries.getAllSessions();
|
|
15
|
-
const groups = await queries.getAllGroups();
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
const formattedGroups = groups.map((g) => ({
|
|
19
|
-
...g,
|
|
20
|
-
expanded: Boolean(g.expanded),
|
|
21
|
-
}));
|
|
22
|
-
|
|
23
|
-
return NextResponse.json({ sessions, groups: formattedGroups });
|
|
16
|
+
return NextResponse.json({ sessions });
|
|
24
17
|
} catch (error) {
|
|
25
18
|
console.error("Error fetching sessions:", error);
|
|
26
19
|
return NextResponse.json(
|
|
@@ -56,7 +49,6 @@ export async function POST(request: NextRequest) {
|
|
|
56
49
|
parentSessionId = null,
|
|
57
50
|
model = "sonnet",
|
|
58
51
|
systemPrompt = null,
|
|
59
|
-
groupPath = "sessions",
|
|
60
52
|
claudeSessionId = null,
|
|
61
53
|
agentType: rawAgentType = "claude",
|
|
62
54
|
autoApprove = false,
|
|
@@ -141,7 +133,6 @@ export async function POST(request: NextRequest) {
|
|
|
141
133
|
parentSessionId,
|
|
142
134
|
model,
|
|
143
135
|
systemPrompt,
|
|
144
|
-
groupPath,
|
|
145
136
|
agentType,
|
|
146
137
|
autoApprove,
|
|
147
138
|
projectId
|
package/app/page.tsx
CHANGED
|
@@ -33,7 +33,7 @@ import { useDevServersManager } from "@/hooks/useDevServersManager";
|
|
|
33
33
|
import { useSessionStatuses } from "@/hooks/useSessionStatuses";
|
|
34
34
|
import type { Session } from "@/lib/db";
|
|
35
35
|
import type { TerminalHandle } from "@/components/Terminal";
|
|
36
|
-
import {
|
|
36
|
+
import { CLAUDE_COMMAND, buildClaudeFlags } from "@/lib/providers";
|
|
37
37
|
import { DesktopView } from "@/components/views/DesktopView";
|
|
38
38
|
import { MobileView } from "@/components/views/MobileView";
|
|
39
39
|
import { getPendingPrompt, clearPendingPrompt } from "@/stores/initialPrompt";
|
|
@@ -152,16 +152,9 @@ function HomeContent() {
|
|
|
152
152
|
async (
|
|
153
153
|
session: Session
|
|
154
154
|
): Promise<{ sessionName: string; cwd: string; command: string }> => {
|
|
155
|
-
const
|
|
156
|
-
const sessionName = session.tmux_name || `${provider.id}-${session.id}`;
|
|
155
|
+
const sessionName = session.tmux_name || `claude-${session.id}`;
|
|
157
156
|
const cwd = session.working_directory?.replace("~", "$HOME") || "$HOME";
|
|
158
157
|
|
|
159
|
-
// TODO: Add explicit "Enable Orchestration" toggle that creates .mcp.json
|
|
160
|
-
// for conductor sessions. Removed auto-creation because it pollutes projects
|
|
161
|
-
// with .mcp.json files that aren't in their .gitignore.
|
|
162
|
-
// See: /api/sessions/[id]/mcp-config, lib/mcp-config.ts
|
|
163
|
-
|
|
164
|
-
// Get parent session ID for forking
|
|
165
158
|
let parentSessionId: string | null = null;
|
|
166
159
|
if (!session.claude_session_id && session.parent_session_id) {
|
|
167
160
|
const parentSession = sessions.find(
|
|
@@ -170,22 +163,20 @@ function HomeContent() {
|
|
|
170
163
|
parentSessionId = parentSession?.claude_session_id || null;
|
|
171
164
|
}
|
|
172
165
|
|
|
173
|
-
// Check for pending initial prompt
|
|
174
166
|
const initialPrompt = getPendingPrompt(session.id);
|
|
175
167
|
if (initialPrompt) {
|
|
176
168
|
clearPendingPrompt(session.id);
|
|
177
169
|
}
|
|
178
170
|
|
|
179
|
-
const flags =
|
|
171
|
+
const flags = buildClaudeFlags({
|
|
180
172
|
sessionId: session.claude_session_id,
|
|
181
173
|
parentSessionId,
|
|
182
174
|
autoApprove: session.auto_approve,
|
|
183
175
|
model: session.model,
|
|
184
176
|
initialPrompt: initialPrompt || undefined,
|
|
185
177
|
});
|
|
186
|
-
const flagsStr = flags.join(" ");
|
|
187
178
|
|
|
188
|
-
const agentCmd = `${
|
|
179
|
+
const agentCmd = `${CLAUDE_COMMAND} ${flags.join(" ")}`;
|
|
189
180
|
const command = await getInitScriptCommand(agentCmd);
|
|
190
181
|
|
|
191
182
|
return { sessionName, cwd, command };
|
|
@@ -296,37 +287,6 @@ function HomeContent() {
|
|
|
296
287
|
[addTab, focusedPaneId, buildSessionCommand, runSessionInTerminal]
|
|
297
288
|
);
|
|
298
289
|
|
|
299
|
-
// Attach to an already-running tmux session (non-destructive)
|
|
300
|
-
const attachToActiveTmux = useCallback(
|
|
301
|
-
(sessionId: string, tmuxSessionName: string) => {
|
|
302
|
-
const terminalInfo = getTerminalWithFallback();
|
|
303
|
-
if (!terminalInfo) return;
|
|
304
|
-
|
|
305
|
-
const { terminal, paneId } = terminalInfo;
|
|
306
|
-
const activeTab = getActiveTab(paneId);
|
|
307
|
-
const isInTmux = !!activeTab?.attachedTmux;
|
|
308
|
-
|
|
309
|
-
if (isInTmux) {
|
|
310
|
-
terminal.sendInput("\x02d");
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
setTimeout(
|
|
314
|
-
() => {
|
|
315
|
-
terminal.sendInput("\x03");
|
|
316
|
-
setTimeout(() => {
|
|
317
|
-
terminal.sendCommand(
|
|
318
|
-
`tmux attach -t ${tmuxSessionName} 2>/dev/null`
|
|
319
|
-
);
|
|
320
|
-
attachSession(paneId, sessionId, tmuxSessionName);
|
|
321
|
-
terminal.focus();
|
|
322
|
-
}, 50);
|
|
323
|
-
},
|
|
324
|
-
isInTmux ? 100 : 0
|
|
325
|
-
);
|
|
326
|
-
},
|
|
327
|
-
[getTerminalWithFallback, getActiveTab, attachSession]
|
|
328
|
-
);
|
|
329
|
-
|
|
330
290
|
const resumeClaudeSession = useCallback(
|
|
331
291
|
(
|
|
332
292
|
claudeSessionId: string,
|
|
@@ -619,7 +579,6 @@ function HomeContent() {
|
|
|
619
579
|
updateSettings,
|
|
620
580
|
requestPermission,
|
|
621
581
|
attachToSession,
|
|
622
|
-
attachToActiveTmux,
|
|
623
582
|
openSessionInNewTab,
|
|
624
583
|
handleNewSessionInProject,
|
|
625
584
|
handleOpenTerminal,
|
|
@@ -6,19 +6,12 @@ import {
|
|
|
6
6
|
ChevronRight,
|
|
7
7
|
ChevronDown,
|
|
8
8
|
FolderOpen,
|
|
9
|
-
MoreHorizontal,
|
|
10
9
|
Plus,
|
|
11
10
|
Eye,
|
|
12
11
|
EyeOff,
|
|
13
12
|
Loader2,
|
|
14
13
|
} from "lucide-react";
|
|
15
14
|
import { Button } from "@/components/ui/button";
|
|
16
|
-
import {
|
|
17
|
-
DropdownMenu,
|
|
18
|
-
DropdownMenuContent,
|
|
19
|
-
DropdownMenuItem,
|
|
20
|
-
DropdownMenuTrigger,
|
|
21
|
-
} from "@/components/ui/dropdown-menu";
|
|
22
15
|
import {
|
|
23
16
|
ContextMenu,
|
|
24
17
|
ContextMenuContent,
|
|
@@ -119,30 +112,25 @@ export function ClaudeProjectCard({
|
|
|
119
112
|
<Plus className="h-3.5 w-3.5" />
|
|
120
113
|
</Button>
|
|
121
114
|
)}
|
|
122
|
-
<
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
Hide project
|
|
142
|
-
</DropdownMenuItem>
|
|
143
|
-
)}
|
|
144
|
-
</DropdownMenuContent>
|
|
145
|
-
</DropdownMenu>
|
|
115
|
+
<Button
|
|
116
|
+
variant="ghost"
|
|
117
|
+
size="icon-sm"
|
|
118
|
+
className="h-7 w-7 flex-shrink-0 opacity-100 md:h-6 md:w-6 md:opacity-0 md:group-hover:opacity-100"
|
|
119
|
+
onClick={(e) => {
|
|
120
|
+
e.stopPropagation();
|
|
121
|
+
if (project.hidden) {
|
|
122
|
+
handleUnhideProject();
|
|
123
|
+
} else {
|
|
124
|
+
handleHideProject();
|
|
125
|
+
}
|
|
126
|
+
}}
|
|
127
|
+
>
|
|
128
|
+
{project.hidden ? (
|
|
129
|
+
<Eye className="h-3.5 w-3.5" />
|
|
130
|
+
) : (
|
|
131
|
+
<EyeOff className="h-3.5 w-3.5" />
|
|
132
|
+
)}
|
|
133
|
+
</Button>
|
|
146
134
|
</div>
|
|
147
135
|
);
|
|
148
136
|
|
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { cn } from "@/lib/utils";
|
|
4
|
-
import { MessageSquare,
|
|
4
|
+
import { MessageSquare, Eye, EyeOff } from "lucide-react";
|
|
5
5
|
import { Button } from "@/components/ui/button";
|
|
6
|
-
import {
|
|
7
|
-
DropdownMenu,
|
|
8
|
-
DropdownMenuContent,
|
|
9
|
-
DropdownMenuItem,
|
|
10
|
-
DropdownMenuTrigger,
|
|
11
|
-
} from "@/components/ui/dropdown-menu";
|
|
12
6
|
import type { ClaudeSession } from "@/data/claude";
|
|
13
7
|
|
|
14
8
|
interface ClaudeSessionCardProps {
|
|
@@ -71,30 +65,25 @@ export function ClaudeSessionCard({
|
|
|
71
65
|
<span className="text-muted-foreground flex-shrink-0 text-[10px]">
|
|
72
66
|
{getTimeAgo(session.lastActivity)}
|
|
73
67
|
</span>
|
|
74
|
-
<
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Hide session
|
|
94
|
-
</DropdownMenuItem>
|
|
95
|
-
)}
|
|
96
|
-
</DropdownMenuContent>
|
|
97
|
-
</DropdownMenu>
|
|
68
|
+
<Button
|
|
69
|
+
variant="ghost"
|
|
70
|
+
size="icon-sm"
|
|
71
|
+
className="h-6 w-6 flex-shrink-0 opacity-0 group-hover:opacity-100"
|
|
72
|
+
onClick={(e) => {
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
if (session.hidden) {
|
|
75
|
+
onUnhide();
|
|
76
|
+
} else {
|
|
77
|
+
onHide();
|
|
78
|
+
}
|
|
79
|
+
}}
|
|
80
|
+
>
|
|
81
|
+
{session.hidden ? (
|
|
82
|
+
<Eye className="h-3.5 w-3.5" />
|
|
83
|
+
) : (
|
|
84
|
+
<EyeOff className="h-3.5 w-3.5" />
|
|
85
|
+
)}
|
|
86
|
+
</Button>
|
|
98
87
|
</div>
|
|
99
88
|
);
|
|
100
89
|
}
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { ChevronRight } from "lucide-react";
|
|
2
|
-
import
|
|
3
|
-
import { getProviderDefinition } from "@/lib/providers";
|
|
2
|
+
import { CLAUDE_AUTO_APPROVE_FLAG } from "@/lib/providers";
|
|
4
3
|
|
|
5
4
|
interface AdvancedSettingsProps {
|
|
6
5
|
open: boolean;
|
|
7
6
|
onOpenChange: (open: boolean) => void;
|
|
8
|
-
agentType: AgentType;
|
|
9
7
|
useTmux: boolean;
|
|
10
8
|
onUseTmuxChange: (checked: boolean) => void;
|
|
11
9
|
skipPermissions: boolean;
|
|
@@ -15,15 +13,11 @@ interface AdvancedSettingsProps {
|
|
|
15
13
|
export function AdvancedSettings({
|
|
16
14
|
open,
|
|
17
15
|
onOpenChange,
|
|
18
|
-
agentType,
|
|
19
16
|
useTmux,
|
|
20
17
|
onUseTmuxChange,
|
|
21
18
|
skipPermissions,
|
|
22
19
|
onSkipPermissionsChange,
|
|
23
20
|
}: AdvancedSettingsProps) {
|
|
24
|
-
const provider = getProviderDefinition(agentType);
|
|
25
|
-
const supportsAutoApprove = Boolean(provider.autoApproveFlag);
|
|
26
|
-
|
|
27
21
|
return (
|
|
28
22
|
<div className="border-border rounded-lg border">
|
|
29
23
|
<button
|
|
@@ -58,16 +52,13 @@ export function AdvancedSettings({
|
|
|
58
52
|
type="checkbox"
|
|
59
53
|
id="skipPermissions"
|
|
60
54
|
checked={skipPermissions}
|
|
61
|
-
disabled={!supportsAutoApprove}
|
|
62
55
|
onChange={(e) => onSkipPermissionsChange(e.target.checked)}
|
|
63
|
-
className="border-border bg-background accent-primary h-4 w-4 rounded
|
|
56
|
+
className="border-border bg-background accent-primary h-4 w-4 rounded"
|
|
64
57
|
/>
|
|
65
58
|
<label htmlFor="skipPermissions" className="cursor-pointer text-sm">
|
|
66
59
|
Auto-approve tool calls
|
|
67
60
|
<span className="text-muted-foreground ml-1">
|
|
68
|
-
{
|
|
69
|
-
? `(${provider.autoApproveFlag})`
|
|
70
|
-
: "(not supported)"}
|
|
61
|
+
({CLAUDE_AUTO_APPROVE_FLAG})
|
|
71
62
|
</span>
|
|
72
63
|
</label>
|
|
73
64
|
</div>
|
|
@@ -3,7 +3,6 @@ import type { ProjectWithDevServers } from "@/lib/projects";
|
|
|
3
3
|
|
|
4
4
|
// LocalStorage keys
|
|
5
5
|
export const SKIP_PERMISSIONS_KEY = "agentOS:skipPermissions";
|
|
6
|
-
export const AGENT_TYPE_KEY = "agentOS:defaultAgentType";
|
|
7
6
|
export const RECENT_DIRS_KEY = "agentOS:recentDirectories";
|
|
8
7
|
export const USE_TMUX_KEY = "agentOS:useTmux";
|
|
9
8
|
export const MAX_RECENT_DIRS = 5;
|
|
@@ -84,15 +83,6 @@ export interface GitInfo {
|
|
|
84
83
|
currentBranch: string | null;
|
|
85
84
|
}
|
|
86
85
|
|
|
87
|
-
// Agent type options
|
|
88
|
-
export const AGENT_OPTIONS: {
|
|
89
|
-
value: AgentType;
|
|
90
|
-
label: string;
|
|
91
|
-
description: string;
|
|
92
|
-
}[] = [
|
|
93
|
-
{ value: "claude", label: "Claude Code", description: "Anthropic's CLI" },
|
|
94
|
-
];
|
|
95
|
-
|
|
96
86
|
// Props for main dialog
|
|
97
87
|
export interface NewSessionDialogProps {
|
|
98
88
|
open: boolean;
|
|
@@ -9,14 +9,11 @@ import {
|
|
|
9
9
|
} from "@/components/ui/select";
|
|
10
10
|
import { Plus } from "lucide-react";
|
|
11
11
|
import type { ProjectWithDevServers } from "@/lib/projects";
|
|
12
|
-
import type { AgentType } from "@/lib/providers";
|
|
13
|
-
|
|
14
12
|
interface ProjectSelectorProps {
|
|
15
13
|
projects: ProjectWithDevServers[];
|
|
16
14
|
projectId: string | null;
|
|
17
15
|
onProjectChange: (projectId: string | null) => void;
|
|
18
16
|
workingDirectory: string;
|
|
19
|
-
agentType: AgentType;
|
|
20
17
|
showNewProject: boolean;
|
|
21
18
|
onShowNewProjectChange: (show: boolean) => void;
|
|
22
19
|
newProjectName: string;
|
|
@@ -31,7 +28,6 @@ export function ProjectSelector({
|
|
|
31
28
|
projectId,
|
|
32
29
|
onProjectChange,
|
|
33
30
|
workingDirectory,
|
|
34
|
-
agentType,
|
|
35
31
|
showNewProject,
|
|
36
32
|
onShowNewProjectChange,
|
|
37
33
|
newProjectName,
|
|
@@ -129,7 +125,7 @@ export function ProjectSelector({
|
|
|
129
125
|
{showNewProject && (
|
|
130
126
|
<p className="text-muted-foreground text-xs">
|
|
131
127
|
{workingDirectory && workingDirectory !== "~"
|
|
132
|
-
? `New project will use: ${workingDirectory}
|
|
128
|
+
? `New project will use: ${workingDirectory}`
|
|
133
129
|
: "Enter a working directory above to create a project"}
|
|
134
130
|
</p>
|
|
135
131
|
)}
|
|
@@ -137,8 +133,7 @@ export function ProjectSelector({
|
|
|
137
133
|
selectedProject &&
|
|
138
134
|
!selectedProject.is_uncategorized && (
|
|
139
135
|
<p className="text-muted-foreground text-xs">
|
|
140
|
-
Settings inherited: {selectedProject.working_directory}
|
|
141
|
-
{selectedProject.agent_type}
|
|
136
|
+
Settings inherited: {selectedProject.working_directory}
|
|
142
137
|
</p>
|
|
143
138
|
)}
|
|
144
139
|
</div>
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import type { AgentType } from "@/lib/providers";
|
|
3
3
|
import type { ProjectWithDevServers } from "@/lib/projects";
|
|
4
4
|
import { setPendingPrompt } from "@/stores/initialPrompt";
|
|
5
5
|
import { useCreateSession } from "@/data/sessions";
|
|
6
6
|
import {
|
|
7
7
|
type GitInfo,
|
|
8
8
|
SKIP_PERMISSIONS_KEY,
|
|
9
|
-
AGENT_TYPE_KEY,
|
|
10
9
|
RECENT_DIRS_KEY,
|
|
11
10
|
USE_TMUX_KEY,
|
|
12
11
|
MAX_RECENT_DIRS,
|
|
13
|
-
AGENT_OPTIONS,
|
|
14
12
|
generateFeatureName,
|
|
15
13
|
} from "../NewSessionDialog.types";
|
|
16
14
|
|
|
@@ -42,7 +40,6 @@ export function useNewSessionForm({
|
|
|
42
40
|
const [name, setName] = useState("");
|
|
43
41
|
const [workingDirectory, setWorkingDirectory] = useState("~");
|
|
44
42
|
const [projectId, setProjectId] = useState<string | null>(null);
|
|
45
|
-
const [agentType, setAgentType] = useState<AgentType>("claude");
|
|
46
43
|
const [skipPermissions, setSkipPermissions] = useState(false);
|
|
47
44
|
const [useTmux, setUseTmux] = useState(true);
|
|
48
45
|
const [initialPrompt, setInitialPrompt] = useState("");
|
|
@@ -120,13 +117,6 @@ export function useNewSessionForm({
|
|
|
120
117
|
if (savedSkipPerms !== null) {
|
|
121
118
|
setSkipPermissions(savedSkipPerms === "true");
|
|
122
119
|
}
|
|
123
|
-
const savedAgentType = localStorage.getItem(AGENT_TYPE_KEY);
|
|
124
|
-
if (
|
|
125
|
-
savedAgentType &&
|
|
126
|
-
AGENT_OPTIONS.some((opt) => opt.value === savedAgentType)
|
|
127
|
-
) {
|
|
128
|
-
setAgentType(savedAgentType as AgentType);
|
|
129
|
-
}
|
|
130
120
|
const savedUseTmux = localStorage.getItem(USE_TMUX_KEY);
|
|
131
121
|
if (savedUseTmux !== null) {
|
|
132
122
|
setUseTmux(savedUseTmux === "true");
|
|
@@ -150,7 +140,6 @@ export function useNewSessionForm({
|
|
|
150
140
|
const project = projects.find((p) => p.id === selectedProjectId);
|
|
151
141
|
if (project && !project.is_uncategorized) {
|
|
152
142
|
setWorkingDirectory(project.working_directory);
|
|
153
|
-
setAgentType(project.agent_type);
|
|
154
143
|
}
|
|
155
144
|
} else {
|
|
156
145
|
// Otherwise, select first non-uncategorized project
|
|
@@ -158,25 +147,11 @@ export function useNewSessionForm({
|
|
|
158
147
|
if (firstProject) {
|
|
159
148
|
setProjectId(firstProject.id);
|
|
160
149
|
setWorkingDirectory(firstProject.working_directory);
|
|
161
|
-
setAgentType(firstProject.agent_type);
|
|
162
150
|
}
|
|
163
151
|
}
|
|
164
152
|
}
|
|
165
153
|
}, [open, selectedProjectId, projects]);
|
|
166
154
|
|
|
167
|
-
useEffect(() => {
|
|
168
|
-
if (!skipPermissions) {
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (getProviderDefinition(agentType).autoApproveFlag) {
|
|
173
|
-
return;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
setSkipPermissions(false);
|
|
177
|
-
localStorage.setItem(SKIP_PERMISSIONS_KEY, "false");
|
|
178
|
-
}, [agentType, skipPermissions]);
|
|
179
|
-
|
|
180
155
|
// Save directory to recent list
|
|
181
156
|
const addRecentDirectory = useCallback((dir: string) => {
|
|
182
157
|
if (!dir || dir === "~") return;
|
|
@@ -196,7 +171,6 @@ export function useNewSessionForm({
|
|
|
196
171
|
const project = projects.find((p) => p.id === newProjectId);
|
|
197
172
|
if (project && !project.is_uncategorized) {
|
|
198
173
|
setWorkingDirectory(project.working_directory);
|
|
199
|
-
setAgentType(project.agent_type);
|
|
200
174
|
}
|
|
201
175
|
}
|
|
202
176
|
},
|
|
@@ -208,11 +182,6 @@ export function useNewSessionForm({
|
|
|
208
182
|
localStorage.setItem(SKIP_PERMISSIONS_KEY, String(checked));
|
|
209
183
|
};
|
|
210
184
|
|
|
211
|
-
const handleAgentTypeChange = (value: AgentType) => {
|
|
212
|
-
setAgentType(value);
|
|
213
|
-
localStorage.setItem(AGENT_TYPE_KEY, value);
|
|
214
|
-
};
|
|
215
|
-
|
|
216
185
|
const handleUseTmuxChange = (checked: boolean) => {
|
|
217
186
|
setUseTmux(checked);
|
|
218
187
|
localStorage.setItem(USE_TMUX_KEY, String(checked));
|
|
@@ -248,7 +217,7 @@ export function useNewSessionForm({
|
|
|
248
217
|
name: name.trim() || undefined,
|
|
249
218
|
workingDirectory,
|
|
250
219
|
projectId,
|
|
251
|
-
agentType,
|
|
220
|
+
agentType: "claude" as AgentType,
|
|
252
221
|
useWorktree,
|
|
253
222
|
featureName: useWorktree ? featureName.trim() : null,
|
|
254
223
|
baseBranch: useWorktree ? baseBranch : null,
|
|
@@ -291,7 +260,7 @@ export function useNewSessionForm({
|
|
|
291
260
|
const newId = await onCreateProject(
|
|
292
261
|
newProjectName.trim(),
|
|
293
262
|
workingDirectory,
|
|
294
|
-
|
|
263
|
+
"claude"
|
|
295
264
|
);
|
|
296
265
|
if (newId) {
|
|
297
266
|
setProjectId(newId);
|
|
@@ -328,7 +297,6 @@ export function useNewSessionForm({
|
|
|
328
297
|
workingDirectory,
|
|
329
298
|
setWorkingDirectory,
|
|
330
299
|
projectId,
|
|
331
|
-
agentType,
|
|
332
300
|
skipPermissions,
|
|
333
301
|
useTmux,
|
|
334
302
|
initialPrompt,
|
|
@@ -361,7 +329,6 @@ export function useNewSessionForm({
|
|
|
361
329
|
// Handlers
|
|
362
330
|
handleProjectChange,
|
|
363
331
|
handleSkipPermissionsChange,
|
|
364
|
-
handleAgentTypeChange,
|
|
365
332
|
handleUseTmuxChange,
|
|
366
333
|
handleSubmit,
|
|
367
334
|
handleCreateProject,
|
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
import { Button } from "@/components/ui/button";
|
|
11
11
|
import { Input } from "@/components/ui/input";
|
|
12
12
|
import { useNewSessionForm } from "./hooks/useNewSessionForm";
|
|
13
|
-
import { AgentSelector } from "./AgentSelector";
|
|
14
13
|
import { CreatingOverlay } from "./CreatingOverlay";
|
|
15
14
|
import type { NewSessionDialogProps } from "./NewSessionDialog.types";
|
|
16
15
|
|
|
@@ -56,11 +55,6 @@ export function NewSessionDialog({
|
|
|
56
55
|
<DialogTitle>New Session</DialogTitle>
|
|
57
56
|
</DialogHeader>
|
|
58
57
|
<form onSubmit={form.handleSubmit} className="space-y-4">
|
|
59
|
-
<AgentSelector
|
|
60
|
-
value={form.agentType}
|
|
61
|
-
onChange={form.handleAgentTypeChange}
|
|
62
|
-
/>
|
|
63
|
-
|
|
64
58
|
<div className="space-y-2">
|
|
65
59
|
<label className="text-sm font-medium">
|
|
66
60
|
Name{" "}
|
|
@@ -100,7 +94,6 @@ export function NewSessionDialog({
|
|
|
100
94
|
</form>
|
|
101
95
|
</DialogContent>
|
|
102
96
|
</Dialog>
|
|
103
|
-
|
|
104
97
|
</>
|
|
105
98
|
);
|
|
106
99
|
}
|
|
@@ -13,7 +13,6 @@ import {
|
|
|
13
13
|
useDeleteProject,
|
|
14
14
|
useRenameProject,
|
|
15
15
|
} from "@/data/projects";
|
|
16
|
-
import { useToggleGroup, useCreateGroup, useDeleteGroup } from "@/data/groups";
|
|
17
16
|
import {
|
|
18
17
|
useStopDevServer,
|
|
19
18
|
useRestartDevServer,
|
|
@@ -42,11 +41,6 @@ export function useSessionListMutations({
|
|
|
42
41
|
const deleteProjectMutation = useDeleteProject();
|
|
43
42
|
const renameProjectMutation = useRenameProject();
|
|
44
43
|
|
|
45
|
-
// Group mutations
|
|
46
|
-
const toggleGroupMutation = useToggleGroup();
|
|
47
|
-
const createGroupMutation = useCreateGroup();
|
|
48
|
-
const deleteGroupMutation = useDeleteGroup();
|
|
49
|
-
|
|
50
44
|
// Dev server mutations
|
|
51
45
|
const stopDevServerMutation = useStopDevServer();
|
|
52
46
|
const restartDevServerMutation = useRestartDevServer();
|
|
@@ -124,30 +118,6 @@ export function useSessionListMutations({
|
|
|
124
118
|
[renameProjectMutation]
|
|
125
119
|
);
|
|
126
120
|
|
|
127
|
-
// Group handlers
|
|
128
|
-
const handleToggleGroup = useCallback(
|
|
129
|
-
async (path: string, expanded: boolean) => {
|
|
130
|
-
await toggleGroupMutation.mutateAsync({ path, expanded });
|
|
131
|
-
},
|
|
132
|
-
[toggleGroupMutation]
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
const handleCreateGroup = useCallback(
|
|
136
|
-
async (name: string, parentPath?: string) => {
|
|
137
|
-
await createGroupMutation.mutateAsync({ name, parentPath });
|
|
138
|
-
},
|
|
139
|
-
[createGroupMutation]
|
|
140
|
-
);
|
|
141
|
-
|
|
142
|
-
const handleDeleteGroup = useCallback(
|
|
143
|
-
async (path: string) => {
|
|
144
|
-
if (!confirm("Delete this group? Sessions will be moved to parent."))
|
|
145
|
-
return;
|
|
146
|
-
await deleteGroupMutation.mutateAsync(path);
|
|
147
|
-
},
|
|
148
|
-
[deleteGroupMutation]
|
|
149
|
-
);
|
|
150
|
-
|
|
151
121
|
// Dev server handlers
|
|
152
122
|
const handleStopDevServer = useCallback(
|
|
153
123
|
async (serverId: string) => {
|
|
@@ -252,11 +222,6 @@ export function useSessionListMutations({
|
|
|
252
222
|
handleDeleteProject,
|
|
253
223
|
handleRenameProject,
|
|
254
224
|
|
|
255
|
-
// Group handlers
|
|
256
|
-
handleToggleGroup,
|
|
257
|
-
handleCreateGroup,
|
|
258
|
-
handleDeleteGroup,
|
|
259
|
-
|
|
260
225
|
// Dev server handlers
|
|
261
226
|
handleStopDevServer,
|
|
262
227
|
handleRestartDevServer,
|
|
@@ -48,7 +48,6 @@ export function DesktopView({
|
|
|
48
48
|
updateSettings,
|
|
49
49
|
requestPermission,
|
|
50
50
|
attachToSession,
|
|
51
|
-
attachToActiveTmux,
|
|
52
51
|
openSessionInNewTab,
|
|
53
52
|
handleNewSessionInProject,
|
|
54
53
|
handleOpenTerminal,
|
|
@@ -62,18 +61,14 @@ export function DesktopView({
|
|
|
62
61
|
resumeClaudeSession,
|
|
63
62
|
renderPane,
|
|
64
63
|
}: ViewProps) {
|
|
65
|
-
// Select a session by ID — handles both DB sessions and tmux-only sessions
|
|
66
64
|
const selectSessionById = (id: string) => {
|
|
67
65
|
const session = sessions.find((s) => s.id === id);
|
|
68
66
|
if (session) {
|
|
69
67
|
attachToSession(session);
|
|
70
68
|
return;
|
|
71
69
|
}
|
|
72
|
-
// Not in DB — attach directly to the running tmux session
|
|
73
70
|
const status = sessionStatuses[id];
|
|
74
|
-
|
|
75
|
-
attachToActiveTmux(id, status.sessionName);
|
|
76
|
-
}
|
|
71
|
+
resumeClaudeSession(id, status?.cwd || "~");
|
|
77
72
|
};
|
|
78
73
|
|
|
79
74
|
return (
|